mirror of
https://github.com/meshtastic/web.git
synced 2026-01-27 16:58:52 -05:00
WIP
This commit is contained in:
@@ -28,7 +28,7 @@
|
||||
"react-hook-form": "^7.27.0",
|
||||
"react-icons": "^4.3.1",
|
||||
"react-json-pretty": "^2.2.0",
|
||||
"react-multi-select-component": "^4.2.1",
|
||||
"react-multi-select-component": "^4.2.2",
|
||||
"react-qr-code": "^2.0.3",
|
||||
"react-redux": "^7.2.6",
|
||||
"react-use-clipboard": "^1.0.7",
|
||||
|
||||
8
pnpm-lock.yaml
generated
8
pnpm-lock.yaml
generated
@@ -40,7 +40,7 @@ specifiers:
|
||||
react-hook-form: ^7.27.0
|
||||
react-icons: ^4.3.1
|
||||
react-json-pretty: ^2.2.0
|
||||
react-multi-select-component: ^4.2.1
|
||||
react-multi-select-component: ^4.2.2
|
||||
react-qr-code: ^2.0.3
|
||||
react-redux: ^7.2.6
|
||||
react-use-clipboard: ^1.0.7
|
||||
@@ -75,7 +75,7 @@ dependencies:
|
||||
react-hook-form: 7.27.0_react@17.0.2
|
||||
react-icons: 4.3.1_react@17.0.2
|
||||
react-json-pretty: 2.2.0_react-dom@17.0.2+react@17.0.2
|
||||
react-multi-select-component: 4.2.1_react-dom@17.0.2+react@17.0.2
|
||||
react-multi-select-component: 4.2.2_react-dom@17.0.2+react@17.0.2
|
||||
react-qr-code: 2.0.3_react@17.0.2
|
||||
react-redux: 7.2.6_react-dom@17.0.2+react@17.0.2
|
||||
react-use-clipboard: 1.0.7_react-dom@17.0.2+react@17.0.2
|
||||
@@ -4875,8 +4875,8 @@ packages:
|
||||
react-dom: 17.0.2_react@17.0.2
|
||||
dev: false
|
||||
|
||||
/react-multi-select-component/4.2.1_react-dom@17.0.2+react@17.0.2:
|
||||
resolution: {integrity: sha512-wRteBq1pqKLlYX/ob8I1aBapPokQiRzOJzVqJDVVTHb0Ap/QWXVE4OXE2xwhVf3qmmYvOguvOKQQbQiEYxhONA==}
|
||||
/react-multi-select-component/4.2.2_react-dom@17.0.2+react@17.0.2:
|
||||
resolution: {integrity: sha512-FvlHp1a4LzwJr121mq4q8NnO4l9HgDo7Z9gk4uCzhRygc78QmqoEcgKEwfcfaQKJp2HAZw4b31P87ex2mLK38A==}
|
||||
peerDependencies:
|
||||
react: ^16 || ^17
|
||||
react-dom: ^16 || ^17
|
||||
|
||||
@@ -57,52 +57,50 @@ export const Connection = (): JSX.Element => {
|
||||
}}
|
||||
>
|
||||
<Card>
|
||||
<div className="flex w-full max-w-3xl justify-between p-10">
|
||||
{state.deviceStatus ===
|
||||
Types.DeviceStatusEnum.DEVICE_DISCONNECTED ? (
|
||||
<div className="space-y-2">
|
||||
<Select
|
||||
label="Connection Method"
|
||||
optionsEnum={connType}
|
||||
value={appState.connType}
|
||||
onChange={(e): void => {
|
||||
dispatch(setConnType(parseInt(e.target.value)));
|
||||
}}
|
||||
/>
|
||||
{appState.connType === connType.HTTP && <HTTP />}
|
||||
{appState.connType === connType.BLE && <BLE />}
|
||||
{appState.connType === connType.SERIAL && <Serial />}
|
||||
</div>
|
||||
) : (
|
||||
<div>
|
||||
<span>Connecting...</span>
|
||||
{state.deviceStatus ===
|
||||
Types.DeviceStatusEnum.DEVICE_CONNECTED && (
|
||||
<Button
|
||||
border
|
||||
onClick={async (): Promise<void> => {
|
||||
await connection.disconnect();
|
||||
<div className="flex w-full max-w-3xl gap-2 p-2">
|
||||
<div className="w-1/2">
|
||||
{state.deviceStatus ===
|
||||
Types.DeviceStatusEnum.DEVICE_DISCONNECTED ? (
|
||||
<div className="space-y-2">
|
||||
<Select
|
||||
label="Connection Method"
|
||||
optionsEnum={connType}
|
||||
value={appState.connType}
|
||||
onChange={(e): void => {
|
||||
dispatch(setConnType(parseInt(e.target.value)));
|
||||
}}
|
||||
>
|
||||
Disconnect
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<div className="rounded-md bg-secondaryDark p-2">
|
||||
{state.logs.map((log, index) => (
|
||||
<div className="flex">
|
||||
<div>
|
||||
[
|
||||
{log.date.toLocaleTimeString(undefined, {
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
})}
|
||||
]
|
||||
</div>
|
||||
<div key={index}>{log.message}</div>
|
||||
/>
|
||||
{appState.connType === connType.HTTP && <HTTP />}
|
||||
{appState.connType === connType.BLE && <BLE />}
|
||||
{appState.connType === connType.SERIAL && <Serial />}
|
||||
</div>
|
||||
))}
|
||||
) : (
|
||||
<div>
|
||||
<span>Connecting...</span>
|
||||
{state.deviceStatus ===
|
||||
Types.DeviceStatusEnum.DEVICE_CONNECTED && (
|
||||
<Button
|
||||
border
|
||||
onClick={async (): Promise<void> => {
|
||||
await connection.disconnect();
|
||||
}}
|
||||
>
|
||||
Disconnect
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="w-1/2 ">
|
||||
<div className="h-96 overflow-y-auto rounded-md bg-secondaryDark p-2">
|
||||
{state.logs.map((log, index) => (
|
||||
<div key={index} className="flex">
|
||||
<div>[{log.date.toISOString()}]</div>
|
||||
<div>[{log.emitter}]</div>
|
||||
<div key={index}>{log.message}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React from 'react';
|
||||
|
||||
import { FiFile, FiInfo } from 'react-icons/fi';
|
||||
import { MdSubject } from 'react-icons/md';
|
||||
import { RiPinDistanceFill } from 'react-icons/ri';
|
||||
import { VscExtensions } from 'react-icons/vsc';
|
||||
|
||||
@@ -9,10 +10,11 @@ import { ExternalSection } from '@app/components/layout/Sidebar/sections/Externa
|
||||
|
||||
import { FileBrowser } from './FileBrowser';
|
||||
import { Info } from './Info';
|
||||
import { Logs } from './Logs';
|
||||
|
||||
export const Extensions = (): JSX.Element => {
|
||||
const [selectedExtension, setSelectedExtension] = React.useState<
|
||||
'info' | 'fileBrowser' | 'rangeTest'
|
||||
'info' | 'logs' | 'fileBrowser' | 'rangeTest'
|
||||
>('info');
|
||||
|
||||
return (
|
||||
@@ -28,6 +30,13 @@ export const Extensions = (): JSX.Element => {
|
||||
icon={<FiInfo />}
|
||||
title="Node Info"
|
||||
/>
|
||||
<ExternalSection
|
||||
onClick={(): void => {
|
||||
setSelectedExtension('logs');
|
||||
}}
|
||||
icon={<MdSubject />}
|
||||
title="Logs"
|
||||
/>
|
||||
<ExternalSection
|
||||
onClick={(): void => {
|
||||
setSelectedExtension('fileBrowser');
|
||||
@@ -48,6 +57,8 @@ export const Extensions = (): JSX.Element => {
|
||||
<div className="w-full">
|
||||
{selectedExtension === 'info' && <Info />}
|
||||
|
||||
{selectedExtension === 'logs' && <Logs />}
|
||||
|
||||
{selectedExtension === 'fileBrowser' && <FileBrowser />}
|
||||
</div>
|
||||
</Layout>
|
||||
|
||||
62
src/pages/Extensions/Logs.tsx
Normal file
62
src/pages/Extensions/Logs.tsx
Normal file
@@ -0,0 +1,62 @@
|
||||
import React from 'react';
|
||||
|
||||
import { useAppSelector } from '@app/hooks/useAppSelector';
|
||||
import { Protobuf } from '@meshtastic/meshtasticjs';
|
||||
|
||||
export const Logs = (): JSX.Element => {
|
||||
const logs = useAppSelector((state) => state.meshtastic.logs);
|
||||
|
||||
const logColor = (level: Protobuf.LogRecord_Level): string => {
|
||||
switch (level) {
|
||||
case Protobuf.LogRecord_Level.UNSET:
|
||||
return 'text-blue-500';
|
||||
case Protobuf.LogRecord_Level.CRITICAL:
|
||||
return 'text-blue-500';
|
||||
case Protobuf.LogRecord_Level.ERROR:
|
||||
return 'text-blue-500';
|
||||
case Protobuf.LogRecord_Level.WARNING:
|
||||
return 'text-blue-500';
|
||||
case Protobuf.LogRecord_Level.INFO:
|
||||
return 'text-blue-500';
|
||||
case Protobuf.LogRecord_Level.DEBUG:
|
||||
return 'text-blue-500';
|
||||
case Protobuf.LogRecord_Level.TRACE:
|
||||
return 'text-blue-500';
|
||||
}
|
||||
};
|
||||
|
||||
const stringToColour = (str: string) => {
|
||||
let hash = 0;
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
hash = str.charCodeAt(i) + ((hash << 5) - hash);
|
||||
}
|
||||
let colour = '#';
|
||||
for (let i = 0; i < 3; i++) {
|
||||
const value = (hash >> (i * 8)) & 0xff;
|
||||
colour += ('00' + value.toString(16)).substr(-2);
|
||||
}
|
||||
return colour;
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex h-full w-full select-none flex-col gap-4 p-4">
|
||||
<div className="flex w-full select-none flex-col gap-2 overflow-y-auto rounded-md p-4 shadow-md dark:bg-primaryDark">
|
||||
{logs.map((log, index) => (
|
||||
<div key={index} className="flex gap-2">
|
||||
<div className="text-sm font-light dark:text-gray-400">
|
||||
{log.date.toISOString()}
|
||||
</div>
|
||||
<div>[{log.emitter}]</div>
|
||||
<div className={`text-sm font-medium ${logColor(log.level)}`}>
|
||||
[{Protobuf.LogRecord_Level[log.level]}]
|
||||
</div>
|
||||
<div style={{ color: stringToColour(log.emitter) }}>
|
||||
{stringToColour(log.emitter)}
|
||||
</div>
|
||||
<div>{log.message}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user