u
This commit is contained in:
@@ -609,6 +609,7 @@ _none_
|
|||||||
- Returns: `200 SSE`
|
- Returns: `200 SSE`
|
||||||
|
|
||||||
- Events:
|
- Events:
|
||||||
|
- `user`: `{ selectedCompanyId }`
|
||||||
- `company`: `{ companyId }`
|
- `company`: `{ companyId }`
|
||||||
- `category`: `{}`
|
- `category`: `{}`
|
||||||
- `articles`: `{}`
|
- `articles`: `{}`
|
||||||
|
|||||||
@@ -211,6 +211,7 @@ const initialUserSettings = readInitialUserSettings();
|
|||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
// 1. Company profile
|
// 1. Company profile
|
||||||
|
companies: [],
|
||||||
current: null,
|
current: null,
|
||||||
status: 'idle',
|
status: 'idle',
|
||||||
error: null,
|
error: null,
|
||||||
@@ -385,18 +386,33 @@ async function fetchCarriersList() {
|
|||||||
|
|
||||||
const actions = {
|
const actions = {
|
||||||
// #region 1. Company profile & orchestration
|
// #region 1. Company profile & orchestration
|
||||||
// MARK: calls company.getById from ../api/index.js
|
// MARK: calls company.list from ../api/index.js
|
||||||
async load() {
|
async load() {
|
||||||
const companyId = authAutomat.state.user?.selectedCompanyId;
|
const hasAuth = Boolean(
|
||||||
if (!companyId) return null;
|
authAutomat.state.hasAuth ??
|
||||||
|
(authAutomat.state.status === 'authed' && authAutomat.state.user),
|
||||||
|
);
|
||||||
|
if (!hasAuth) return null;
|
||||||
if (inflightCompany) return inflightCompany;
|
if (inflightCompany) return inflightCompany;
|
||||||
companyAutomat.setState({ status: 'loading', error: null });
|
companyAutomat.setState({ status: 'loading', error: null });
|
||||||
inflightCompany = (async () => {
|
inflightCompany = (async () => {
|
||||||
try {
|
try {
|
||||||
const data = await companyApi.getById(companyId);
|
const data = await companyApi.list();
|
||||||
const normalized = normalizeCompany(data.company);
|
const companies = Array.isArray(data?.companies)
|
||||||
companyAutomat.setState({ current: normalized, status: 'succeeded', error: null });
|
? data.companies.map((item) => normalizeCompany(item)).filter(Boolean)
|
||||||
return normalized;
|
: [];
|
||||||
|
const companyId = authAutomat.state.user?.selectedCompanyId;
|
||||||
|
const current =
|
||||||
|
companyId != null
|
||||||
|
? (companies.find(
|
||||||
|
(item) => item.id === companyId || String(item.id) === String(companyId),
|
||||||
|
) ?? null)
|
||||||
|
: null;
|
||||||
|
if (companyId != null && !current) {
|
||||||
|
throw new Error('Unternehmen nicht gefunden.');
|
||||||
|
}
|
||||||
|
companyAutomat.setState({ companies, current, status: 'succeeded', error: null });
|
||||||
|
return current;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
companyAutomat.setState({ status: 'failed', error: err?.message ?? String(err) });
|
companyAutomat.setState({ status: 'failed', error: err?.message ?? String(err) });
|
||||||
throw err;
|
throw err;
|
||||||
@@ -407,16 +423,55 @@ const actions = {
|
|||||||
return inflightCompany;
|
return inflightCompany;
|
||||||
},
|
},
|
||||||
|
|
||||||
// MARK: calls company.update and company.getById from ../api/index.js
|
// MARK: calls company.list from ../api/index.js
|
||||||
|
async reload() {
|
||||||
|
const hasAuth = Boolean(
|
||||||
|
authAutomat.state.hasAuth ??
|
||||||
|
(authAutomat.state.status === 'authed' && authAutomat.state.user),
|
||||||
|
);
|
||||||
|
if (!hasAuth) return null;
|
||||||
|
try {
|
||||||
|
const data = await companyApi.list();
|
||||||
|
const companies = Array.isArray(data?.companies)
|
||||||
|
? data.companies.map((item) => normalizeCompany(item)).filter(Boolean)
|
||||||
|
: [];
|
||||||
|
const companyId = authAutomat.state.user?.selectedCompanyId;
|
||||||
|
const current =
|
||||||
|
companyId != null
|
||||||
|
? (companies.find(
|
||||||
|
(item) => item.id === companyId || String(item.id) === String(companyId),
|
||||||
|
) ?? companyAutomat.state.current)
|
||||||
|
: null;
|
||||||
|
companyAutomat.setState({ companies, current, status: 'succeeded', error: null });
|
||||||
|
return current;
|
||||||
|
} catch (err) {
|
||||||
|
companyAutomat.setState({ error: err?.message ?? String(err) });
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// MARK: calls company.update and company.list from ../api/index.js
|
||||||
async update(payload) {
|
async update(payload) {
|
||||||
const companyId = authAutomat.state.user?.selectedCompanyId;
|
const companyId = authAutomat.state.user?.selectedCompanyId;
|
||||||
if (!companyId) throw new Error('Kein Unternehmen ausgewählt.');
|
if (!companyId) throw new Error('Kein Unternehmen ausgewählt.');
|
||||||
companyAutomat.setState({ status: 'loading', error: null });
|
companyAutomat.setState({ status: 'loading', error: null });
|
||||||
try {
|
try {
|
||||||
await companyApi.update(companyId, payload);
|
await companyApi.update(companyId, payload);
|
||||||
const data = await companyApi.getById(companyId);
|
const data = await companyApi.list();
|
||||||
const normalized = normalizeCompany(data.company, payload);
|
const companies = Array.isArray(data?.companies)
|
||||||
companyAutomat.setState({ current: normalized, status: 'succeeded', error: null });
|
? data.companies
|
||||||
|
.map((item) =>
|
||||||
|
item.id === companyId || String(item.id) === String(companyId)
|
||||||
|
? normalizeCompany(item, payload)
|
||||||
|
: normalizeCompany(item),
|
||||||
|
)
|
||||||
|
.filter(Boolean)
|
||||||
|
: [];
|
||||||
|
const normalized =
|
||||||
|
companies.find((item) => item.id === companyId || String(item.id) === String(companyId)) ??
|
||||||
|
null;
|
||||||
|
if (!normalized) throw new Error('Unternehmen nicht gefunden.');
|
||||||
|
companyAutomat.setState({ companies, current: normalized, status: 'succeeded', error: null });
|
||||||
return normalized;
|
return normalized;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
companyAutomat.setState({ status: 'failed', error: err?.message ?? String(err) });
|
companyAutomat.setState({ status: 'failed', error: err?.message ?? String(err) });
|
||||||
@@ -1391,17 +1446,24 @@ companyAutomat = new Automat(initialState, actions, { name: 'company' });
|
|||||||
hydrateUserSettingsFromIdb(companyAutomat);
|
hydrateUserSettingsFromIdb(companyAutomat);
|
||||||
|
|
||||||
// #region authAutomat synchronization
|
// #region authAutomat synchronization
|
||||||
let lastCompanyKey;
|
let lastAuthKey;
|
||||||
|
|
||||||
function syncWithAuth(auth) {
|
function syncWithAuth(auth) {
|
||||||
|
const hasAuth = Boolean(
|
||||||
|
auth?.hasAuth ?? (auth?.status === 'authed' && auth?.user),
|
||||||
|
);
|
||||||
const hasCompany = Boolean(
|
const hasCompany = Boolean(
|
||||||
auth?.hasCompany ?? (auth?.status === 'authed' && auth?.user?.selectedCompanyId != null),
|
auth?.hasCompany ?? (hasAuth && auth?.user?.selectedCompanyId != null),
|
||||||
);
|
);
|
||||||
const companyId = hasCompany ? String(auth.user.selectedCompanyId) : null;
|
const companyId = hasCompany ? String(auth.user.selectedCompanyId) : null;
|
||||||
if (companyId === lastCompanyKey) return;
|
const authKey = hasAuth ? `authed:${companyId ?? ''}` : 'anon';
|
||||||
lastCompanyKey = companyId;
|
if (authKey === lastAuthKey) return;
|
||||||
if (companyId == null) {
|
lastAuthKey = authKey;
|
||||||
|
if (!hasAuth) {
|
||||||
companyAutomat.actions.reset();
|
companyAutomat.actions.reset();
|
||||||
|
} else if (companyId == null) {
|
||||||
|
companyAutomat.actions.reset();
|
||||||
|
void companyAutomat.actions.load().catch(() => {});
|
||||||
} else {
|
} else {
|
||||||
companyAutomat.actions.reset();
|
companyAutomat.actions.reset();
|
||||||
void companyAutomat.actions.loadAll();
|
void companyAutomat.actions.loadAll();
|
||||||
@@ -1414,6 +1476,7 @@ syncWithAuth(authAutomat.state);
|
|||||||
|
|
||||||
// #region selectors & exported action helpers
|
// #region selectors & exported action helpers
|
||||||
// Company profile selectors
|
// Company profile selectors
|
||||||
|
export const selectCompanies = () => companyAutomat.state.companies;
|
||||||
export const selectCurrentCompany = () => companyAutomat.state.current;
|
export const selectCurrentCompany = () => companyAutomat.state.current;
|
||||||
export const selectCompanyId = () => companyAutomat.state.current?.id ?? null;
|
export const selectCompanyId = () => companyAutomat.state.current?.id ?? null;
|
||||||
export const selectCompanyStatus = () => companyAutomat.state.status;
|
export const selectCompanyStatus = () => companyAutomat.state.status;
|
||||||
|
|||||||
@@ -134,6 +134,7 @@ export {
|
|||||||
|
|
||||||
export { default as companyAutomat } from './companyAutomat';
|
export { default as companyAutomat } from './companyAutomat';
|
||||||
export {
|
export {
|
||||||
|
selectCompanies,
|
||||||
selectCurrentCompany,
|
selectCurrentCompany,
|
||||||
selectCompanyId,
|
selectCompanyId,
|
||||||
selectCompanyStatus,
|
selectCompanyStatus,
|
||||||
|
|||||||
@@ -182,6 +182,15 @@ function connect() {
|
|||||||
|
|
||||||
const es = new EventSource(url.href, { withCredentials: true });
|
const es = new EventSource(url.href, { withCredentials: true });
|
||||||
|
|
||||||
|
addTrackedListener(es, 'company', () => {
|
||||||
|
const comp = Automat.get('company');
|
||||||
|
if (comp?.actions?.reload) {
|
||||||
|
void comp.actions.reload().catch((err) => {
|
||||||
|
console.error('[sse] company refresh failed', err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Category tree changed: refresh the tree and every open category view.
|
// Category tree changed: refresh the tree and every open category view.
|
||||||
addTrackedListener(es, 'category', () => {
|
addTrackedListener(es, 'category', () => {
|
||||||
const cat = Automat.get('category');
|
const cat = Automat.get('category');
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Component } from 'react';
|
import { PureComponent } from 'react';
|
||||||
import Alert from '@mui/material/Alert';
|
import Alert from '@mui/material/Alert';
|
||||||
import Box from '@mui/material/Box';
|
import Box from '@mui/material/Box';
|
||||||
import Button from '@mui/material/Button';
|
import Button from '@mui/material/Button';
|
||||||
@@ -36,8 +36,8 @@ import RequestQuoteIcon from '@mui/icons-material/RequestQuote';
|
|||||||
import ShoppingCartIcon from '@mui/icons-material/ShoppingCart';
|
import ShoppingCartIcon from '@mui/icons-material/ShoppingCart';
|
||||||
import AssignmentReturnIcon from '@mui/icons-material/AssignmentReturn';
|
import AssignmentReturnIcon from '@mui/icons-material/AssignmentReturn';
|
||||||
import BackendError from './BackendError';
|
import BackendError from './BackendError';
|
||||||
import { company } from '../api';
|
import authAutomat from '../automats/authAutomat';
|
||||||
import authAutomat, { bootstrapAuthMe } from '../automats/authAutomat';
|
import companyAutomat from '../automats/companyAutomat';
|
||||||
import {
|
import {
|
||||||
defaultIso639,
|
defaultIso639,
|
||||||
ISO639_OPTIONS,
|
ISO639_OPTIONS,
|
||||||
@@ -126,12 +126,18 @@ function formatNumberPreview(prefix, padding, next, offset = 0) {
|
|||||||
return `${prefix ?? ''}${numStr}`;
|
return `${prefix ?? ''}${numStr}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
class CompanySetupDialog extends Component {
|
function mapCompanyState(state) {
|
||||||
|
return {
|
||||||
|
companies: Array.isArray(state?.companies) ? state.companies : [],
|
||||||
|
loading: state?.status === 'idle' || state?.status === 'loading',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
class CompanySetupDialog extends PureComponent {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
companies: [],
|
...mapCompanyState(companyAutomat.state),
|
||||||
loading: true,
|
|
||||||
busy: false,
|
busy: false,
|
||||||
error: null,
|
error: null,
|
||||||
name: '',
|
name: '',
|
||||||
@@ -150,26 +156,21 @@ class CompanySetupDialog extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
void this.loadCompanies();
|
this.unsubscribe = companyAutomat.subscribe(this, mapCompanyState);
|
||||||
|
this.setState(mapCompanyState(companyAutomat.state));
|
||||||
|
if (companyAutomat.state.status !== 'succeeded') {
|
||||||
|
void companyAutomat.actions.load().catch(() => {});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async loadCompanies() {
|
componentWillUnmount() {
|
||||||
this.setState({ loading: true });
|
this.unsubscribe?.();
|
||||||
try {
|
|
||||||
const data = await company.list();
|
|
||||||
this.setState({ companies: data.companies ?? [] });
|
|
||||||
} catch {
|
|
||||||
this.setState({ companies: [] });
|
|
||||||
} finally {
|
|
||||||
this.setState({ loading: false });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async handleSelect(companyId) {
|
async handleSelect(companyId) {
|
||||||
this.setState({ busy: true, error: null });
|
this.setState({ busy: true, error: null });
|
||||||
try {
|
try {
|
||||||
await authAutomat.actions.selectCompany(companyId);
|
await authAutomat.actions.selectCompany(companyId);
|
||||||
await bootstrapAuthMe();
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.setState({ error: backendErrorFrom(err) });
|
this.setState({ error: backendErrorFrom(err) });
|
||||||
} finally {
|
} finally {
|
||||||
@@ -224,8 +225,6 @@ class CompanySetupDialog extends Component {
|
|||||||
reducedtaxrate: parsedReducedtaxrate,
|
reducedtaxrate: parsedReducedtaxrate,
|
||||||
numbers,
|
numbers,
|
||||||
});
|
});
|
||||||
|
|
||||||
await bootstrapAuthMe();
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.setState({ error: backendErrorFrom(err) });
|
this.setState({ error: backendErrorFrom(err) });
|
||||||
} finally {
|
} finally {
|
||||||
@@ -236,7 +235,6 @@ class CompanySetupDialog extends Component {
|
|||||||
async handleLogout() {
|
async handleLogout() {
|
||||||
try {
|
try {
|
||||||
await authAutomat.actions.logout();
|
await authAutomat.actions.logout();
|
||||||
await bootstrapAuthMe();
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.setState({ error: backendErrorFrom(err) });
|
this.setState({ error: backendErrorFrom(err) });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,11 +12,10 @@ import CloseIcon from '@mui/icons-material/Close';
|
|||||||
import DeleteSweepIcon from '@mui/icons-material/DeleteSweep';
|
import DeleteSweepIcon from '@mui/icons-material/DeleteSweep';
|
||||||
import DragIndicatorIcon from '@mui/icons-material/DragIndicator';
|
import DragIndicatorIcon from '@mui/icons-material/DragIndicator';
|
||||||
import SensorsIcon from '@mui/icons-material/Sensors';
|
import SensorsIcon from '@mui/icons-material/Sensors';
|
||||||
import sseAutomat, { getSseClientId } from '../automats/sseAutomat';
|
import sseAutomat from '../automats/sseAutomat';
|
||||||
|
|
||||||
const PANEL_WIDTH = 420;
|
const PANEL_WIDTH = 420;
|
||||||
const PANEL_HEIGHT = 380;
|
const PANEL_HEIGHT = 380;
|
||||||
const RAW_EVENT_LIMIT = 500;
|
|
||||||
const pulseAnimationA = keyframes`
|
const pulseAnimationA = keyframes`
|
||||||
0% { transform: scale(1); box-shadow: 0 0 0 0 rgba(255, 255, 255, 0); }
|
0% { transform: scale(1); box-shadow: 0 0 0 0 rgba(255, 255, 255, 0); }
|
||||||
35% { transform: scale(1.16); box-shadow: 0 0 0 8px rgba(255, 255, 255, 0.55); }
|
35% { transform: scale(1.16); box-shadow: 0 0 0 8px rgba(255, 255, 255, 0.55); }
|
||||||
@@ -43,15 +42,11 @@ class SseMonitor extends PureComponent {
|
|||||||
this.state = {
|
this.state = {
|
||||||
status: sseAutomat.state.status,
|
status: sseAutomat.state.status,
|
||||||
companyId: sseAutomat.state.companyId,
|
companyId: sseAutomat.state.companyId,
|
||||||
events: [],
|
events: sseAutomat.state.events,
|
||||||
open: false,
|
open: false,
|
||||||
position: null,
|
position: null,
|
||||||
eventPulse: 0,
|
eventPulse: 0,
|
||||||
};
|
};
|
||||||
this.nextRawId = 0;
|
|
||||||
this.rawAbort = null;
|
|
||||||
this.rawReconnectTimer = null;
|
|
||||||
this.rawBuffer = '';
|
|
||||||
this.panelRef = createRef();
|
this.panelRef = createRef();
|
||||||
this.handleToggle = this.handleToggle.bind(this);
|
this.handleToggle = this.handleToggle.bind(this);
|
||||||
this.handleKeyDown = this.handleKeyDown.bind(this);
|
this.handleKeyDown = this.handleKeyDown.bind(this);
|
||||||
@@ -66,15 +61,14 @@ class SseMonitor extends PureComponent {
|
|||||||
this.unsubscribe = sseAutomat.subscribe(this, (state) => ({
|
this.unsubscribe = sseAutomat.subscribe(this, (state) => ({
|
||||||
status: state.status,
|
status: state.status,
|
||||||
companyId: state.companyId,
|
companyId: state.companyId,
|
||||||
|
events: state.events,
|
||||||
}));
|
}));
|
||||||
window.addEventListener('keydown', this.handleKeyDown);
|
window.addEventListener('keydown', this.handleKeyDown);
|
||||||
this.startRawStream();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
this.unsubscribe?.();
|
this.unsubscribe?.();
|
||||||
window.removeEventListener('keydown', this.handleKeyDown);
|
window.removeEventListener('keydown', this.handleKeyDown);
|
||||||
this.stopRawStream();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate(prevProps, prevState) {
|
componentDidUpdate(prevProps, prevState) {
|
||||||
@@ -83,96 +77,6 @@ class SseMonitor extends PureComponent {
|
|||||||
if (currentEventId != null && currentEventId !== previousEventId) {
|
if (currentEventId != null && currentEventId !== previousEventId) {
|
||||||
this.setState((state) => ({ eventPulse: state.eventPulse + 1 }));
|
this.setState((state) => ({ eventPulse: state.eventPulse + 1 }));
|
||||||
}
|
}
|
||||||
if (prevState.companyId !== this.state.companyId) {
|
|
||||||
this.startRawStream();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pushRawEvent(type, data) {
|
|
||||||
const entry = {
|
|
||||||
id: ++this.nextRawId,
|
|
||||||
type: type || 'message',
|
|
||||||
data: data ?? '',
|
|
||||||
lastEventId: '',
|
|
||||||
time: Date.now(),
|
|
||||||
};
|
|
||||||
this.setState((state) => ({
|
|
||||||
events: [...state.events.slice(-(RAW_EVENT_LIMIT - 1)), entry],
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
handleRawChunk(text) {
|
|
||||||
this.rawBuffer += text;
|
|
||||||
let boundary;
|
|
||||||
while ((boundary = this.rawBuffer.indexOf('\n\n')) !== -1) {
|
|
||||||
const frame = this.rawBuffer.slice(0, boundary);
|
|
||||||
this.rawBuffer = this.rawBuffer.slice(boundary + 2);
|
|
||||||
let type = '';
|
|
||||||
const dataLines = [];
|
|
||||||
let comment = '';
|
|
||||||
for (const line of frame.split('\n')) {
|
|
||||||
if (line.startsWith(':')) {
|
|
||||||
comment = line.slice(1).trim();
|
|
||||||
} else if (line.startsWith('event:')) {
|
|
||||||
type = line.slice(6).trim();
|
|
||||||
} else if (line.startsWith('data:')) {
|
|
||||||
dataLines.push(line.slice(5).trimStart());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// No filtering: show every frame, including heartbeats and
|
|
||||||
// events no automat listens for (brand, modelconversation, ...).
|
|
||||||
if (!type && comment) {
|
|
||||||
this.pushRawEvent(comment, '');
|
|
||||||
} else if (type || dataLines.length > 0) {
|
|
||||||
this.pushRawEvent(type || 'message', dataLines.join('\n'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
stopRawStream() {
|
|
||||||
if (this.rawReconnectTimer) {
|
|
||||||
clearTimeout(this.rawReconnectTimer);
|
|
||||||
this.rawReconnectTimer = null;
|
|
||||||
}
|
|
||||||
if (this.rawAbort) {
|
|
||||||
try {
|
|
||||||
this.rawAbort.abort();
|
|
||||||
} catch {}
|
|
||||||
this.rawAbort = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async startRawStream() {
|
|
||||||
this.stopRawStream();
|
|
||||||
this.rawBuffer = '';
|
|
||||||
const controller = new AbortController();
|
|
||||||
this.rawAbort = controller;
|
|
||||||
try {
|
|
||||||
const url = new URL('/api/events', window.location.origin);
|
|
||||||
try {
|
|
||||||
const cid = getSseClientId();
|
|
||||||
if (cid) url.searchParams.set('cid', `${cid}-monitor`);
|
|
||||||
} catch {}
|
|
||||||
const res = await fetch(url.href, {
|
|
||||||
credentials: 'include',
|
|
||||||
signal: controller.signal,
|
|
||||||
headers: { Accept: 'text/event-stream' },
|
|
||||||
});
|
|
||||||
if (!res.ok || !res.body) throw new Error(`SSE monitor HTTP ${res.status}`);
|
|
||||||
const reader = res.body.getReader();
|
|
||||||
const decoder = new TextDecoder();
|
|
||||||
for (;;) {
|
|
||||||
const { done, value } = await reader.read();
|
|
||||||
if (done) break;
|
|
||||||
this.handleRawChunk(decoder.decode(value, { stream: true }));
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
if (controller.signal.aborted) return;
|
|
||||||
this.pushRawEvent('error', String(err?.message ?? err));
|
|
||||||
}
|
|
||||||
if (!controller.signal.aborted && !this.rawReconnectTimer) {
|
|
||||||
this.rawReconnectTimer = setTimeout(() => this.startRawStream(), 3000);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handleKeyDown(event) {
|
handleKeyDown(event) {
|
||||||
@@ -190,7 +94,7 @@ class SseMonitor extends PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleClear() {
|
handleClear() {
|
||||||
this.setState({ events: [] });
|
sseAutomat.actions.clearEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
handlePointerDown(event) {
|
handlePointerDown(event) {
|
||||||
|
|||||||
Reference in New Issue
Block a user