mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-15 20:33:47 +00:00
refactor: migrate logs (#673)
This commit is contained in:
@@ -3,6 +3,7 @@ import { ErrorBoundary } from '@sentry/react';
|
||||
import { useKeyDown } from '../../common/hooks/useKeyDown';
|
||||
|
||||
import AboutPanel from './panel/about-panel/AboutPanel';
|
||||
import LogPanel from './panel/log-panel/LogPanel';
|
||||
import ProjectPanel from './panel/project-panel/ProjectPanel';
|
||||
import PanelContent from './panel-content/PanelContent';
|
||||
import PanelList from './panel-list/PanelList';
|
||||
@@ -26,6 +27,7 @@ export default function AppSettings() {
|
||||
<PanelContent onClose={closeSettings}>
|
||||
{selectedPanel === 'project' && <ProjectPanel />}
|
||||
{selectedPanel === 'about' && <AboutPanel />}
|
||||
{selectedPanel === 'log' && <LogPanel />}
|
||||
</PanelContent>
|
||||
</ErrorBoundary>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
@use '../../../../theme/ontimeColours' as *;
|
||||
@use '../../../../theme/v2Styles' as *;
|
||||
|
||||
$info-gray: $secondary-text-gray;
|
||||
$info-hover: $section-white;
|
||||
|
||||
.log {
|
||||
font-size: $inner-section-text-size;
|
||||
overflow-y: auto;
|
||||
user-select: text;
|
||||
min-height: 10vh;
|
||||
max-height: 40vh;
|
||||
}
|
||||
|
||||
.logEntry {
|
||||
display: flex;
|
||||
|
||||
&.INFO {
|
||||
color: $info-gray;
|
||||
}
|
||||
|
||||
&.WARN {
|
||||
color: $warning-orange;
|
||||
}
|
||||
|
||||
&.ERROR {
|
||||
color: $error-red;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: $info-hover;
|
||||
}
|
||||
|
||||
.time {
|
||||
width: 4.5em;
|
||||
}
|
||||
|
||||
.origin {
|
||||
width: 6em;
|
||||
}
|
||||
|
||||
.msg {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.buttonBar {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.5rem;
|
||||
justify-content: flex-start;
|
||||
padding-bottom: 0.5rem;
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
import { useCallback, useState } from 'react';
|
||||
import { Button } from '@chakra-ui/react';
|
||||
import { LogOrigin } from 'ontime-types';
|
||||
|
||||
import { clearLogs, useLogData } from '../../../../common/stores/logger';
|
||||
|
||||
import style from './Log.module.scss';
|
||||
|
||||
export default function Log() {
|
||||
const { logs: logData } = useLogData();
|
||||
|
||||
const [showClient, setShowClient] = useState(true);
|
||||
const [showServer, setShowServer] = useState(true);
|
||||
const [showRx, setShowRx] = useState(true);
|
||||
const [showTx, setShowTx] = useState(true);
|
||||
const [showPlayback, setShowPlayback] = useState(true);
|
||||
const [showUser, setShowUser] = useState(true);
|
||||
|
||||
const matchers: LogOrigin[] = [];
|
||||
if (showUser) {
|
||||
matchers.push(LogOrigin.User);
|
||||
}
|
||||
if (showClient) {
|
||||
matchers.push(LogOrigin.Client);
|
||||
}
|
||||
if (showServer) {
|
||||
matchers.push(LogOrigin.Server);
|
||||
}
|
||||
if (showRx) {
|
||||
matchers.push(LogOrigin.Rx);
|
||||
}
|
||||
if (showTx) {
|
||||
matchers.push(LogOrigin.Tx);
|
||||
}
|
||||
if (showPlayback) {
|
||||
matchers.push(LogOrigin.Playback);
|
||||
}
|
||||
|
||||
const filteredData = logData.filter((entry) => matchers.some((match) => entry.origin === match));
|
||||
|
||||
const disableOthers = useCallback((toEnable: LogOrigin) => {
|
||||
toEnable === LogOrigin.User ? setShowUser(true) : setShowUser(false);
|
||||
toEnable === LogOrigin.Client ? setShowClient(true) : setShowClient(false);
|
||||
toEnable === LogOrigin.Server ? setShowServer(true) : setShowServer(false);
|
||||
toEnable === LogOrigin.Rx ? setShowRx(true) : setShowRx(false);
|
||||
toEnable === LogOrigin.Tx ? setShowTx(true) : setShowTx(false);
|
||||
toEnable === LogOrigin.Playback ? setShowPlayback(true) : setShowPlayback(false);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className={style.buttonBar}>
|
||||
<Button
|
||||
variant={showUser ? 'ontime-filled' : 'ontime-subtle'}
|
||||
size='sm'
|
||||
onClick={() => setShowUser((s) => !s)}
|
||||
onAuxClick={() => disableOthers(LogOrigin.User)}
|
||||
onContextMenu={(e) => e.preventDefault()}
|
||||
>
|
||||
{LogOrigin.User}
|
||||
</Button>
|
||||
<Button
|
||||
variant={showClient ? 'ontime-filled' : 'ontime-subtle'}
|
||||
size='sm'
|
||||
onClick={() => setShowClient((s) => !s)}
|
||||
onAuxClick={() => disableOthers(LogOrigin.Client)}
|
||||
onContextMenu={(e) => e.preventDefault()}
|
||||
>
|
||||
{LogOrigin.Client}
|
||||
</Button>
|
||||
<Button
|
||||
variant={showServer ? 'ontime-filled' : 'ontime-subtle'}
|
||||
size='sm'
|
||||
onClick={() => setShowServer((s) => !s)}
|
||||
onAuxClick={() => disableOthers(LogOrigin.Server)}
|
||||
onContextMenu={(e) => e.preventDefault()}
|
||||
>
|
||||
{LogOrigin.Server}
|
||||
</Button>
|
||||
<Button
|
||||
variant={showPlayback ? 'ontime-filled' : 'ontime-subtle'}
|
||||
size='sm'
|
||||
onClick={() => setShowPlayback((s) => !s)}
|
||||
onAuxClick={() => disableOthers(LogOrigin.Playback)}
|
||||
onContextMenu={(e) => e.preventDefault()}
|
||||
>
|
||||
{LogOrigin.Playback}
|
||||
</Button>
|
||||
<Button
|
||||
variant={showRx ? 'ontime-filled' : 'ontime-subtle'}
|
||||
size='sm'
|
||||
onClick={() => setShowRx((s) => !s)}
|
||||
onAuxClick={() => disableOthers(LogOrigin.Rx)}
|
||||
onContextMenu={(e) => e.preventDefault()}
|
||||
>
|
||||
{LogOrigin.Rx}
|
||||
</Button>
|
||||
<Button
|
||||
variant={showTx ? 'ontime-filled' : 'ontime-subtle'}
|
||||
size='sm'
|
||||
onClick={() => setShowTx((s) => !s)}
|
||||
onAuxClick={() => disableOthers(LogOrigin.Tx)}
|
||||
onContextMenu={(e) => e.preventDefault()}
|
||||
>
|
||||
{LogOrigin.Tx}
|
||||
</Button>
|
||||
<Button variant='ontime-outlined' size='sm' onClick={clearLogs}>
|
||||
Clear
|
||||
</Button>
|
||||
</div>
|
||||
<ul className={style.log}>
|
||||
{filteredData.map((logEntry) => (
|
||||
<li key={logEntry.id} className={`${style.logEntry} ${style[logEntry.level]} `}>
|
||||
<span className={style.time}>{logEntry.time}</span>
|
||||
<span className={style.origin}>{logEntry.origin}</span>
|
||||
<span className={style.msg}>{logEntry.text}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import * as Panel from '../PanelUtils';
|
||||
|
||||
import Log from './Log';
|
||||
import InfoNif from './NetworkInterfaces';
|
||||
|
||||
export default function LogPanel() {
|
||||
return (
|
||||
<>
|
||||
<Panel.Header>Application log</Panel.Header>
|
||||
<Panel.Section>
|
||||
<Panel.SubHeader>Available networks</Panel.SubHeader>
|
||||
<Panel.Card>
|
||||
<Panel.Paragraph>Ontime is streaming on the following network interfaces</Panel.Paragraph>
|
||||
<InfoNif />
|
||||
</Panel.Card>
|
||||
</Panel.Section>
|
||||
|
||||
<Panel.Section>
|
||||
<Panel.SubHeader>Network log</Panel.SubHeader>
|
||||
<Panel.Card>
|
||||
<Log />
|
||||
</Panel.Card>
|
||||
</Panel.Section>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
@use '../../../../theme/v2Styles' as *;
|
||||
|
||||
.interfaces {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: $section-spacing;
|
||||
row-gap: $element-inner-spacing;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import { serverPort } from '../../../../common/api/apiConstants';
|
||||
import AppLink from '../../../../common/components/app-link/AppLink';
|
||||
import useInfo from '../../../../common/hooks-query/useInfo';
|
||||
|
||||
import style from './NetworkInterfaces.module.scss';
|
||||
|
||||
export default function InfoNif() {
|
||||
const { data } = useInfo();
|
||||
|
||||
return (
|
||||
<div className={style.interfaces}>
|
||||
{data?.networkInterfaces?.map((nif) => (
|
||||
<AppLink key={nif.address} href={`http://${nif.address}:${serverPort}`}>
|
||||
{`${nif.name} - ${nif.address}`}
|
||||
</AppLink>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user