Lint files
This commit is contained in:
@@ -1,4 +0,0 @@
|
|||||||
{
|
|
||||||
"tabWidth": 2,
|
|
||||||
"useTabs": false
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
module.exports = {
|
||||||
|
plugins: [require('prettier-plugin-tailwindcss')],
|
||||||
|
}
|
||||||
+1
-1
@@ -19,7 +19,7 @@ export const App = (): JSX.Element => {
|
|||||||
const device = getDevice(selectedDevice);
|
const device = getDevice(selectedDevice);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="h-full flex w-full">
|
<div className="flex h-full w-full">
|
||||||
<DeviceSelector />
|
<DeviceSelector />
|
||||||
|
|
||||||
{device && (
|
{device && (
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import type React from 'react';
|
import type React from "react";
|
||||||
|
|
||||||
import { DeviceContext } from '@core/providers/useDevice.js';
|
import { DeviceContext } from "@core/providers/useDevice.js";
|
||||||
import type { Device } from '@core/stores/deviceStore.js';
|
import type { Device } from "@core/stores/deviceStore.js";
|
||||||
|
|
||||||
export interface DeviceProps {
|
export interface DeviceProps {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export const Button = ({
|
|||||||
}: ButtonProps): JSX.Element => {
|
}: ButtonProps): JSX.Element => {
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
className={`px-3 w-full rounded-md flex border border-transparent focus:outline-none focus:ring-2 focus:ring-orange-500 focus:ring-offset-2 ${
|
className={`flex w-full rounded-md border border-transparent px-3 focus:outline-none focus:ring-2 focus:ring-orange-500 focus:ring-offset-2 ${
|
||||||
variant === "primary"
|
variant === "primary"
|
||||||
? "bg-orange-600 text-white shadow-sm hover:bg-orange-700"
|
? "bg-orange-600 text-white shadow-sm hover:bg-orange-700"
|
||||||
: "bg-orange-100 text-orange-700 hover:bg-orange-200"
|
: "bg-orange-100 text-orange-700 hover:bg-orange-200"
|
||||||
@@ -33,7 +33,7 @@ export const Button = ({
|
|||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
{...rest}
|
{...rest}
|
||||||
>
|
>
|
||||||
<div className="flex items-center m-auto gap-2 font-medium">
|
<div className="m-auto flex items-center gap-2 font-medium">
|
||||||
{iconBefore}
|
{iconBefore}
|
||||||
{children}
|
{children}
|
||||||
{iconAfter}
|
{iconAfter}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export const DeviceSelector = (): JSX.Element => {
|
|||||||
const { selectedDevice, setSelectedDevice } = useAppStore();
|
const { selectedDevice, setSelectedDevice } = useAppStore();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex bg-slate-50 w-16 items-center whitespace-nowrap py-12 text-sm [writing-mode:vertical-rl] h-full">
|
<div className="flex h-full w-16 items-center whitespace-nowrap bg-slate-50 py-12 text-sm [writing-mode:vertical-rl]">
|
||||||
<span className="font-mono text-slate-500">Connected Devices</span>
|
<span className="font-mono text-slate-500">Connected Devices</span>
|
||||||
<span className="mt-6 flex gap-4 font-bold text-slate-900">
|
<span className="mt-6 flex gap-4 font-bold text-slate-900">
|
||||||
{getDevices().map((device) => (
|
{getDevices().map((device) => (
|
||||||
@@ -19,11 +19,11 @@ export const DeviceSelector = (): JSX.Element => {
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
setSelectedDevice(device.id);
|
setSelectedDevice(device.id);
|
||||||
}}
|
}}
|
||||||
className="group flex w-8 h-8 p-0.5 cursor-pointer drop-shadow-md"
|
className="group flex h-8 w-8 cursor-pointer p-0.5 drop-shadow-md"
|
||||||
>
|
>
|
||||||
<Hashicon size={32} value={device.hardware.myNodeNum.toString()} />
|
<Hashicon size={32} value={device.hardware.myNodeNum.toString()} />
|
||||||
<div
|
<div
|
||||||
className={`absolute -left-1.5 w-0.5 h-7 rounded-full group-hover:bg-orange-300 ${
|
className={`absolute -left-1.5 h-7 w-0.5 rounded-full group-hover:bg-orange-300 ${
|
||||||
device.id === selectedDevice
|
device.id === selectedDevice
|
||||||
? "bg-orange-400"
|
? "bg-orange-400"
|
||||||
: "bg-transparent"
|
: "bg-transparent"
|
||||||
@@ -35,14 +35,14 @@ export const DeviceSelector = (): JSX.Element => {
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
setSelectedDevice(0);
|
setSelectedDevice(0);
|
||||||
}}
|
}}
|
||||||
className={`w-8 h-8 p-2 border-dashed border-2 rounded-md hover:border-orange-300 cursor-pointer ${
|
className={`h-8 w-8 cursor-pointer rounded-md border-2 border-dashed p-2 hover:border-orange-300 ${
|
||||||
selectedDevice === 0 ? "border-orange-400" : "border-slate-200"
|
selectedDevice === 0 ? "border-orange-400" : "border-slate-200"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<PlusIcon />
|
<PlusIcon />
|
||||||
</div>
|
</div>
|
||||||
</span>
|
</span>
|
||||||
<img src="Logo_Black.svg" className="px-3 mt-auto" />
|
<img src="Logo_Black.svg" className="mt-auto px-3" />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ export const QRDialog = ({
|
|||||||
</Dialog.Description>
|
</Dialog.Description>
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
<span className="font-medium text-lg">Channels to include</span>
|
<span className="text-lg font-medium">Channels to include</span>
|
||||||
<span className="text-sm text-slate-600">
|
<span className="text-sm text-slate-600">
|
||||||
The current LoRa configuration will also be shared.
|
The current LoRa configuration will also be shared.
|
||||||
</span>
|
</span>
|
||||||
@@ -86,8 +86,8 @@ export const QRDialog = ({
|
|||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col flex-grow m-2">
|
<div className="m-2 flex flex-grow flex-col">
|
||||||
<div className="flex m-auto">
|
<div className="m-auto flex">
|
||||||
<QRCode value={QRCodeURL} size={250} qrStyle="dots" />
|
<QRCode value={QRCodeURL} size={250} qrStyle="dots" />
|
||||||
</div>
|
</div>
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ export const IconButton = ({
|
|||||||
}: IconButtonProps): JSX.Element => {
|
}: IconButtonProps): JSX.Element => {
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
className={`flex border border-transparent rounded-md focus:outline-none focus:ring-2 focus:ring-orange-500 focus:ring-offset-2 ${
|
className={`flex rounded-md border border-transparent focus:outline-none focus:ring-2 focus:ring-orange-500 focus:ring-offset-2 ${
|
||||||
variant === "primary"
|
variant === "primary"
|
||||||
? "bg-orange-600 text-white shadow-sm hover:bg-orange-700"
|
? "bg-orange-600 text-white shadow-sm hover:bg-orange-700"
|
||||||
: "bg-orange-100 text-orange-700 hover:bg-orange-200"
|
: "bg-orange-100 text-orange-700 hover:bg-orange-200"
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ export const NewDevice = () => {
|
|||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-96 h-96 m-auto">
|
<div className="m-auto h-96 w-96">
|
||||||
<TabbedContent tabs={tabs} />
|
<TabbedContent tabs={tabs} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -35,8 +35,8 @@ export const BLE = (): JSX.Element => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col p-4 gap-2 w-full">
|
<div className="flex w-full flex-col gap-2 p-4">
|
||||||
<div className="flex gap-2 flex-col h-48 overflow-y-auto">
|
<div className="flex h-48 flex-col gap-2 overflow-y-auto">
|
||||||
{bleDevices.map((device, index) => (
|
{bleDevices.map((device, index) => (
|
||||||
<Button
|
<Button
|
||||||
key={index}
|
key={index}
|
||||||
|
|||||||
@@ -48,8 +48,8 @@ export const HTTP = (): JSX.Element => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||||
<form className="w-full p-4 gap-2 flex flex-col" onSubmit={onSubmit}>
|
<form className="flex w-full flex-col gap-2 p-4" onSubmit={onSubmit}>
|
||||||
<div className="h-48 flex flex-col gap-2">
|
<div className="flex h-48 flex-col gap-2">
|
||||||
<Input
|
<Input
|
||||||
label="IP Address/Hostname"
|
label="IP Address/Hostname"
|
||||||
prefix={TLSEnabled ? "https://" : "http://"}
|
prefix={TLSEnabled ? "https://" : "http://"}
|
||||||
|
|||||||
@@ -46,8 +46,8 @@ export const Serial = (): JSX.Element => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col p-4 gap-2 w-full">
|
<div className="flex w-full flex-col gap-2 p-4">
|
||||||
<div className="flex gap-2 flex-col h-48 overflow-y-auto">
|
<div className="flex h-48 flex-col gap-2 overflow-y-auto">
|
||||||
{serialPorts.map((port, index) => (
|
{serialPorts.map((port, index) => (
|
||||||
<Button
|
<Button
|
||||||
key={index}
|
key={index}
|
||||||
|
|||||||
@@ -31,8 +31,8 @@ export const ChannelChat = ({ channel }: ChannelChatProps): JSX.Element => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col flex-grow">
|
<div className="flex flex-grow flex-col">
|
||||||
<div className="flex flex-col flex-grow">
|
<div className="flex flex-grow flex-col">
|
||||||
{channel.messages.map((message, index) => (
|
{channel.messages.map((message, index) => (
|
||||||
<Message
|
<Message
|
||||||
key={index}
|
key={index}
|
||||||
|
|||||||
@@ -29,17 +29,17 @@ export const Message = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
return lastMsgSameUser ? (
|
return lastMsgSameUser ? (
|
||||||
<div className="flex ml-4">
|
<div className="ml-4 flex">
|
||||||
{message.ack ? (
|
{message.ack ? (
|
||||||
<CheckCircleIcon className="my-auto text-slate-200 h-4" />
|
<CheckCircleIcon className="my-auto h-4 text-slate-200" />
|
||||||
) : (
|
) : (
|
||||||
<EllipsisHorizontalCircleIcon className="my-auto text-slate-200 h-4" />
|
<EllipsisHorizontalCircleIcon className="my-auto h-4 text-slate-200" />
|
||||||
)}
|
)}
|
||||||
{"waypointID" in message ? (
|
{"waypointID" in message ? (
|
||||||
<WaypointMessage waypointID={message.waypointID} />
|
<WaypointMessage waypointID={message.waypointID} />
|
||||||
) : (
|
) : (
|
||||||
<span
|
<span
|
||||||
className={`ml-4 pl-2 border-l-2 border-l-slate-200 ${
|
className={`ml-4 border-l-2 border-l-slate-200 pl-2 ${
|
||||||
message.ack ? "text-black" : "text-slate-500"
|
message.ack ? "text-black" : "text-slate-500"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
@@ -48,9 +48,9 @@ export const Message = ({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="mx-4 gap-2 mt-2">
|
<div className="mx-4 mt-2 gap-2">
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
<div className="cursor-pointer w-6" onClick={openPeer}>
|
<div className="w-6 cursor-pointer" onClick={openPeer}>
|
||||||
<Hashicon value={(sender?.num ?? 0).toString()} size={32} />
|
<Hashicon value={(sender?.num ?? 0).toString()} size={32} />
|
||||||
</div>
|
</div>
|
||||||
<span
|
<span
|
||||||
@@ -68,15 +68,15 @@ export const Message = ({
|
|||||||
</div>
|
</div>
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
{message.ack ? (
|
{message.ack ? (
|
||||||
<CheckCircleIcon className="my-auto text-slate-200 h-4" />
|
<CheckCircleIcon className="my-auto h-4 text-slate-200" />
|
||||||
) : (
|
) : (
|
||||||
<EllipsisHorizontalCircleIcon className="my-auto text-slate-200 h-4" />
|
<EllipsisHorizontalCircleIcon className="my-auto h-4 text-slate-200" />
|
||||||
)}
|
)}
|
||||||
{"waypointID" in message ? (
|
{"waypointID" in message ? (
|
||||||
<WaypointMessage waypointID={message.waypointID} />
|
<WaypointMessage waypointID={message.waypointID} />
|
||||||
) : (
|
) : (
|
||||||
<span
|
<span
|
||||||
className={`ml-4 pl-2 border-l-2 border-l-slate-200 ${
|
className={`ml-4 border-l-2 border-l-slate-200 pl-2 ${
|
||||||
message.ack ? "text-black" : "text-slate-500"
|
message.ack ? "text-black" : "text-slate-500"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ export const NewLocationMessage = (): JSX.Element => {
|
|||||||
const { connection } = useDevice();
|
const { connection } = useDevice();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-96 m-4">
|
<div className="m-4 w-96">
|
||||||
<form
|
<form
|
||||||
onSubmit={(e): void => {
|
onSubmit={(e): void => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|||||||
@@ -15,13 +15,13 @@ export const WaypointMessage = ({
|
|||||||
const waypoint = waypoints.find((wp) => wp.id === waypointID);
|
const waypoint = waypoints.find((wp) => wp.id === waypointID);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="ml-4 pl-2 border-l-slate-200 border-l-2">
|
<div className="ml-4 border-l-2 border-l-slate-200 pl-2">
|
||||||
<div className="gap-2 flex rounded-md p-2 shadow-md shadow-orange-300">
|
<div className="flex gap-2 rounded-md p-2 shadow-md shadow-orange-300">
|
||||||
<MapPinIcon className="m-auto w-6 text-slate-600" />
|
<MapPinIcon className="m-auto w-6 text-slate-600" />
|
||||||
<div>
|
<div>
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
<div className="font-bold">{waypoint?.name}</div>
|
<div className="font-bold">{waypoint?.name}</div>
|
||||||
<span className="text-sm font-mono text-slate-500">
|
<span className="font-mono text-sm text-slate-500">
|
||||||
{toMGRS(waypoint?.latitudeI, waypoint?.longitudeI)}
|
{toMGRS(waypoint?.latitudeI, waypoint?.longitudeI)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ export const PageNav = (): JSX.Element => {
|
|||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex bg-slate-50 w-12 items-center whitespace-nowrap py-4 text-sm [writing-mode:vertical-rl] h-full border-r border-slate-200 flex-shrink-0">
|
<div className="flex h-full w-12 flex-shrink-0 items-center whitespace-nowrap border-r border-slate-200 bg-slate-50 py-4 text-sm [writing-mode:vertical-rl]">
|
||||||
<span className="mt-6 flex gap-4 font-bold text-slate-500">
|
<span className="mt-6 flex gap-4 font-bold text-slate-500">
|
||||||
{pages.map((Link) => (
|
{pages.map((Link) => (
|
||||||
<div
|
<div
|
||||||
@@ -62,7 +62,7 @@ export const PageNav = (): JSX.Element => {
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
setActivePage(Link.page);
|
setActivePage(Link.page);
|
||||||
}}
|
}}
|
||||||
className={`w-8 h-8 p-1 border-2 rounded-md hover:border-orange-300 cursor-pointer ${
|
className={`h-8 w-8 cursor-pointer rounded-md border-2 p-1 hover:border-orange-300 ${
|
||||||
Link.page === activePage
|
Link.page === activePage
|
||||||
? "border-orange-400"
|
? "border-orange-400"
|
||||||
: "border-slate-200"
|
: "border-slate-200"
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ export const Sidebar = (): JSX.Element => {
|
|||||||
const { selectedDevice, setSelectedDevice } = useAppStore();
|
const { selectedDevice, setSelectedDevice } = useAppStore();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col relative bg-slate-50 w-80 p-2 border-x border-slate-200 gap-2 flex-shrink-0">
|
<div className="relative flex w-80 flex-shrink-0 flex-col gap-2 border-x border-slate-200 bg-slate-50 p-2">
|
||||||
<DeviceWidget
|
<DeviceWidget
|
||||||
name={
|
name={
|
||||||
nodes.find((n) => n.data.num === hardware.myNodeNum)?.data.user
|
nodes.find((n) => n.data.num === hardware.myNodeNum)?.data.user
|
||||||
@@ -55,7 +55,7 @@ export const Sidebar = (): JSX.Element => {
|
|||||||
<dl className="mt-2 divide-y divide-gray-200 border-t border-b border-gray-200">
|
<dl className="mt-2 divide-y divide-gray-200 border-t border-b border-gray-200">
|
||||||
<div className="flex justify-between py-3 text-sm font-medium">
|
<div className="flex justify-between py-3 text-sm font-medium">
|
||||||
<dt className="text-gray-500">Firmware version</dt>
|
<dt className="text-gray-500">Firmware version</dt>
|
||||||
<dd className="whitespace-nowrap text-gray-900 hover:underline hover:text-orange-400 cursor-pointer">
|
<dd className="cursor-pointer whitespace-nowrap text-gray-900 hover:text-orange-400 hover:underline">
|
||||||
{hardware.firmwareVersion}
|
{hardware.firmwareVersion}
|
||||||
</dd>
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
@@ -64,7 +64,7 @@ export const Sidebar = (): JSX.Element => {
|
|||||||
<dt className="text-gray-500">Bitrate</dt>
|
<dt className="text-gray-500">Bitrate</dt>
|
||||||
<dd className="whitespace-nowrap text-gray-900">
|
<dd className="whitespace-nowrap text-gray-900">
|
||||||
{hardware.bitrate.toFixed(2)}
|
{hardware.bitrate.toFixed(2)}
|
||||||
<span className="font-mono text-slate-500 text-sm ">bps</span>
|
<span className="font-mono text-sm text-slate-500 ">bps</span>
|
||||||
</dd>
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -32,9 +32,9 @@ export const ConfiguringWidget = (): JSX.Element => {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="p-6 flex flex-col rounded-2xl mb-4 text-sm space-y-3 bg-[#f9e3aa] text-black">
|
<div className="mb-4 flex flex-col space-y-3 rounded-2xl bg-[#f9e3aa] p-6 text-sm text-black">
|
||||||
<p className="text-xl font-bold">Connecting to device</p>
|
<p className="text-xl font-bold">Connecting to device</p>
|
||||||
<ol className="flex flex-col overflow-hidden gap-3">
|
<ol className="flex flex-col gap-3 overflow-hidden">
|
||||||
<StatusIndicator
|
<StatusIndicator
|
||||||
title="Device Info"
|
title="Device Info"
|
||||||
current={hardware.myNodeNum ? 1 : 0}
|
current={hardware.myNodeNum ? 1 : 0}
|
||||||
@@ -58,7 +58,7 @@ export const ConfiguringWidget = (): JSX.Element => {
|
|||||||
/>
|
/>
|
||||||
</ol>
|
</ol>
|
||||||
<div
|
<div
|
||||||
className="mt-2 rounded-md bg-[#dabb6b] p-1 ring-[#f9e3aa] cursor-pointer text-center"
|
className="mt-2 cursor-pointer rounded-md bg-[#dabb6b] p-1 text-center ring-[#f9e3aa]"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
void connection?.configure();
|
void connection?.configure();
|
||||||
}}
|
}}
|
||||||
@@ -89,12 +89,12 @@ const StatusIndicator = ({
|
|||||||
/>
|
/>
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
<div
|
<div
|
||||||
className={`flex relative z-10 h-5 w-5 rounded-full border-2 ${
|
className={`relative z-10 flex h-5 w-5 rounded-full border-2 ${
|
||||||
current === 0
|
current === 0
|
||||||
? "border-[#dabb6b] bg-[#f9e3aa]"
|
? "border-[#dabb6b] bg-[#f9e3aa]"
|
||||||
: current >= total
|
: current >= total
|
||||||
? "bg-green-500 border-green-500"
|
? "border-green-500 bg-green-500"
|
||||||
: "bg-[#f9e3aa] border-green-500"
|
: "border-green-500 bg-[#f9e3aa]"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
@@ -104,7 +104,7 @@ const StatusIndicator = ({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span className="flex text-sm ml-4 gap-1">
|
<span className="ml-4 flex gap-1 text-sm">
|
||||||
<span className="font-medium">{title}</span>
|
<span className="font-medium">{title}</span>
|
||||||
<span className="font-mono text-slate-500">
|
<span className="font-mono text-slate-500">
|
||||||
({current}
|
({current}
|
||||||
|
|||||||
@@ -21,19 +21,19 @@ export const DeviceWidget = ({
|
|||||||
reconnect,
|
reconnect,
|
||||||
}: DeviceWidgetProps): JSX.Element => {
|
}: DeviceWidgetProps): JSX.Element => {
|
||||||
return (
|
return (
|
||||||
<div className="relative rounded-xl bg-emerald-400 overflow-hidden">
|
<div className="relative overflow-hidden rounded-xl bg-emerald-400">
|
||||||
<div className="absolute w-full h-full bottom-20">
|
<div className="absolute bottom-20 h-full w-full">
|
||||||
<Hashicon size={350} value={nodeNum} />
|
<Hashicon size={350} value={nodeNum} />
|
||||||
</div>
|
</div>
|
||||||
<div className="flex backdrop-blur-md backdrop-brightness-50 backdrop-hue-rotate-30 p-3">
|
<div className="flex p-3 backdrop-blur-md backdrop-brightness-50 backdrop-hue-rotate-30">
|
||||||
<div className="drop-shadow-md">
|
<div className="drop-shadow-md">
|
||||||
<Hashicon size={96} value={nodeNum} />
|
<Hashicon size={96} value={nodeNum} />
|
||||||
</div>
|
</div>
|
||||||
<div className="w-full flex flex-col">
|
<div className="flex w-full flex-col">
|
||||||
<span className="font-bold text-slate-200 ml-auto text-xl whitespace-nowrap">
|
<span className="ml-auto whitespace-nowrap text-xl font-bold text-slate-200">
|
||||||
{name}
|
{name}
|
||||||
</span>
|
</span>
|
||||||
<div className="ml-auto my-auto">
|
<div className="my-auto ml-auto">
|
||||||
<Button
|
<Button
|
||||||
onClick={disconnected ? reconnect : disconnect}
|
onClick={disconnected ? reconnect : disconnect}
|
||||||
variant={disconnected ? "secondary" : "primary"}
|
variant={disconnected ? "secondary" : "primary"}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ export interface NodeInfoWidgetProps {}
|
|||||||
|
|
||||||
export const NodeInfoWidget = ({}: NodeInfoWidgetProps): JSX.Element => {
|
export const NodeInfoWidget = ({}: NodeInfoWidgetProps): JSX.Element => {
|
||||||
return (
|
return (
|
||||||
<div className="p-6 flex flex-col rounded-2xl mb-4 text-sm space-y-3 bg-[#f9e3aa] text-black">
|
<div className="mb-4 flex flex-col space-y-3 rounded-2xl bg-[#f9e3aa] p-6 text-sm text-black">
|
||||||
node info
|
node info
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ export interface PeersWidgetProps {}
|
|||||||
|
|
||||||
export const PeersWidget = ({}: PeersWidgetProps): JSX.Element => {
|
export const PeersWidget = ({}: PeersWidgetProps): JSX.Element => {
|
||||||
return (
|
return (
|
||||||
<div className="p-6 flex flex-col rounded-2xl mb-4 text-sm space-y-3 bg-[#f9e3aa] text-black">
|
<div className="mb-4 flex flex-col space-y-3 rounded-2xl bg-[#f9e3aa] p-6 text-sm text-black">
|
||||||
Peers
|
Peers
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ export interface PositionWidgetProps {}
|
|||||||
|
|
||||||
export const PositionWidget = ({}: PositionWidgetProps): JSX.Element => {
|
export const PositionWidget = ({}: PositionWidgetProps): JSX.Element => {
|
||||||
return (
|
return (
|
||||||
<div className="p-6 flex flex-col rounded-2xl mb-4 text-sm space-y-3 bg-[#f9e3aa] text-black">
|
<div className="mb-4 flex flex-col space-y-3 rounded-2xl bg-[#f9e3aa] p-6 text-sm text-black">
|
||||||
position
|
position
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -34,29 +34,29 @@ export const Form = ({
|
|||||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||||
<form className="w-full" onSubmit={onSubmit} {...props}>
|
<form className="w-full" onSubmit={onSubmit} {...props}>
|
||||||
{loading && (
|
{loading && (
|
||||||
<div className="absolute flex w-full h-full bg-slate-600 rounded-md z-10">
|
<div className="absolute z-10 flex h-full w-full rounded-md bg-slate-600">
|
||||||
<ArrowPathIcon className="h-8 animate-spin m-auto" />
|
<ArrowPathIcon className="m-auto h-8 animate-spin" />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="select-none rounded-md p-4 bg-gray-700">
|
<div className="select-none rounded-md bg-gray-700 p-4">
|
||||||
<ol className="flex gap-4">
|
<ol className="flex gap-4">
|
||||||
<li className="text-gray-400 hover:text-gray-200 cursor-pointer">
|
<li className="cursor-pointer text-gray-400 hover:text-gray-200">
|
||||||
<HomeIcon className="h-5 w-5 flex-shrink-0 text-gray-400" />
|
<HomeIcon className="h-5 w-5 flex-shrink-0 text-gray-400" />
|
||||||
</li>
|
</li>
|
||||||
{breadcrumbs.map((breadcrumb, index) => (
|
{breadcrumbs.map((breadcrumb, index) => (
|
||||||
<li key={index} className="flex gap-4">
|
<li key={index} className="flex gap-4">
|
||||||
<ChevronRightIcon className="h-5 w-5 flex-shrink-0 text-gray-500" />
|
<ChevronRightIcon className="h-5 w-5 flex-shrink-0 text-gray-500" />
|
||||||
<span className="text-sm font-medium text-gray-400 hover:text-gray-200 cursor-pointer">
|
<span className="cursor-pointer text-sm font-medium text-gray-400 hover:text-gray-200">
|
||||||
{breadcrumb}
|
{breadcrumb}
|
||||||
</span>
|
</span>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ol>
|
</ol>
|
||||||
<div className="mt-2 flex items-center">
|
<div className="mt-2 flex items-center">
|
||||||
<h2 className="font-bold text-white truncate text-3xl tracking-tight">
|
<h2 className="truncate text-3xl font-bold tracking-tight text-white">
|
||||||
{title}
|
{title}
|
||||||
</h2>
|
</h2>
|
||||||
<div className="flex gap-2 ml-auto">
|
<div className="ml-auto flex gap-2">
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@@ -73,7 +73,7 @@ export const Form = ({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col p-2 gap-3">{children}</div>
|
<div className="flex flex-col gap-3 p-2">{children}</div>
|
||||||
</form>
|
</form>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ export const Input = forwardRef<HTMLInputElement, InputProps>(function Input(
|
|||||||
)}
|
)}
|
||||||
<input
|
<input
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={`block w-full min-w-0 flex-1 rounded-md border border-gray-300 px-3 h-10 focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm ${
|
className={`block h-10 w-full min-w-0 flex-1 rounded-md border border-gray-300 px-3 focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm ${
|
||||||
prefix ? "rounded-l-none" : ""
|
prefix ? "rounded-l-none" : ""
|
||||||
} ${action ? "rounded-r-none" : ""}`}
|
} ${action ? "rounded-r-none" : ""}`}
|
||||||
{...rest}
|
{...rest}
|
||||||
|
|||||||
@@ -20,13 +20,13 @@ export const TabbedContent = ({
|
|||||||
actions,
|
actions,
|
||||||
}: TabbedContentProps): JSX.Element => {
|
}: TabbedContentProps): JSX.Element => {
|
||||||
return (
|
return (
|
||||||
<Tab.Group as="div" className="flex flex-col gap-2 p-4 flex-grow">
|
<Tab.Group as="div" className="flex flex-grow flex-col gap-2 p-4">
|
||||||
<Tab.List className="flex gap-4 border-b pb-3">
|
<Tab.List className="flex gap-4 border-b pb-3">
|
||||||
{tabs.map((entry, index) => (
|
{tabs.map((entry, index) => (
|
||||||
<Tab key={index}>
|
<Tab key={index}>
|
||||||
{({ selected }) => (
|
{({ selected }) => (
|
||||||
<div
|
<div
|
||||||
className={`flex gap-3 h-10 font-medium text-sm rounded-md cursor-pointer px-3 ${
|
className={`flex h-10 cursor-pointer gap-3 rounded-md px-3 text-sm font-medium ${
|
||||||
selected
|
selected
|
||||||
? "bg-gray-100 text-gray-700"
|
? "bg-gray-100 text-gray-700"
|
||||||
: "text-gray-500 hover:text-gray-700"
|
: "text-gray-500 hover:text-gray-700"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { createContext, useContext } from 'react';
|
import { createContext, useContext } from "react";
|
||||||
|
|
||||||
import type { Device } from '@core/stores/deviceStore.js';
|
import type { Device } from "@core/stores/deviceStore.js";
|
||||||
|
|
||||||
export const DeviceContext = createContext<Device | undefined>(undefined);
|
export const DeviceContext = createContext<Device | undefined>(undefined);
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import create from 'zustand';
|
import create from "zustand";
|
||||||
|
|
||||||
interface AppState {
|
interface AppState {
|
||||||
selectedDevice: number;
|
selectedDevice: number;
|
||||||
|
|||||||
@@ -23,13 +23,13 @@ export const AppConfig = (): JSX.Element => {
|
|||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tab.Group as="div" className="flex gap-3 w-full">
|
<Tab.Group as="div" className="flex w-full gap-3">
|
||||||
<Tab.List className="flex flex-col w-44 gap-1">
|
<Tab.List className="flex w-44 flex-col gap-1">
|
||||||
{configSections.map((Config, index) => (
|
{configSections.map((Config, index) => (
|
||||||
<Tab key={index} as={Fragment}>
|
<Tab key={index} as={Fragment}>
|
||||||
{({ selected }) => (
|
{({ selected }) => (
|
||||||
<div
|
<div
|
||||||
className={`flex items-center px-3 py-2 text-sm font-medium rounded-md cursor-pointer ${
|
className={`flex cursor-pointer items-center rounded-md px-3 py-2 text-sm font-medium ${
|
||||||
selected
|
selected
|
||||||
? "bg-gray-100 text-gray-900"
|
? "bg-gray-100 text-gray-900"
|
||||||
: "text-gray-600 hover:bg-gray-50 hover:text-gray-900"
|
: "text-gray-600 hover:bg-gray-50 hover:text-gray-900"
|
||||||
|
|||||||
@@ -52,13 +52,13 @@ export const DeviceConfig = (): JSX.Element => {
|
|||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tab.Group as="div" className="flex gap-3 w-full">
|
<Tab.Group as="div" className="flex w-full gap-3">
|
||||||
<Tab.List className="flex flex-col w-44 gap-1">
|
<Tab.List className="flex w-44 flex-col gap-1">
|
||||||
{configSections.map((Config, index) => (
|
{configSections.map((Config, index) => (
|
||||||
<Tab key={index} as={Fragment}>
|
<Tab key={index} as={Fragment}>
|
||||||
{({ selected }) => (
|
{({ selected }) => (
|
||||||
<div
|
<div
|
||||||
className={`flex items-center px-3 py-2 text-sm font-medium rounded-md cursor-pointer ${
|
className={`flex cursor-pointer items-center rounded-md px-3 py-2 text-sm font-medium ${
|
||||||
selected
|
selected
|
||||||
? "bg-gray-100 text-gray-900"
|
? "bg-gray-100 text-gray-900"
|
||||||
: "text-gray-600 hover:bg-gray-50 hover:text-gray-900"
|
: "text-gray-600 hover:bg-gray-50 hover:text-gray-900"
|
||||||
|
|||||||
@@ -45,13 +45,13 @@ export const ModuleConfig = (): JSX.Element => {
|
|||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tab.Group as="div" className="flex gap-3 w-full">
|
<Tab.Group as="div" className="flex w-full gap-3">
|
||||||
<Tab.List className="flex flex-col gap-1 w-44">
|
<Tab.List className="flex w-44 flex-col gap-1">
|
||||||
{configSections.map((Config, index) => (
|
{configSections.map((Config, index) => (
|
||||||
<Tab key={index} as={Fragment}>
|
<Tab key={index} as={Fragment}>
|
||||||
{({ selected }) => (
|
{({ selected }) => (
|
||||||
<div
|
<div
|
||||||
className={`flex items-center px-3 py-2 text-sm font-medium rounded-md cursor-pointer ${
|
className={`flex cursor-pointer items-center rounded-md px-3 py-2 text-sm font-medium ${
|
||||||
selected
|
selected
|
||||||
? "bg-gray-100 text-gray-900"
|
? "bg-gray-100 text-gray-900"
|
||||||
: "text-gray-600 hover:bg-gray-50 hover:text-gray-900"
|
: "text-gray-600 hover:bg-gray-50 hover:text-gray-900"
|
||||||
|
|||||||
+2
-2
@@ -14,8 +14,8 @@ export const MapPage = (): JSX.Element => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex-grow">
|
<div className="flex-grow">
|
||||||
<div className="absolute z-10 right-0 top-0 m-2 rounded-md p-2 shadow-md bg-white">
|
<div className="absolute right-0 top-0 z-10 m-2 rounded-md bg-white p-2 shadow-md">
|
||||||
<div className="font-medium text-lg p-1">Title</div>
|
<div className="p-1 text-lg font-medium">Title</div>
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
{nodes.map((n) => (
|
{nodes.map((n) => (
|
||||||
<div key={n.data.num} className="flex gap-2">
|
<div key={n.data.num} className="flex gap-2">
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ export const MessagesPage = (): JSX.Element => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col w-full">
|
<div className="flex w-full flex-col">
|
||||||
<TabbedContent
|
<TabbedContent
|
||||||
tabs={tabs}
|
tabs={tabs}
|
||||||
actions={[
|
actions={[
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { IsBoolean, IsEnum } from 'class-validator';
|
import { IsBoolean, IsEnum } from "class-validator";
|
||||||
|
|
||||||
import { Protobuf } from '@meshtastic/meshtasticjs';
|
import { Protobuf } from "@meshtastic/meshtasticjs";
|
||||||
|
|
||||||
export class DeviceValidation implements Protobuf.Config_DeviceConfig {
|
export class DeviceValidation implements Protobuf.Config_DeviceConfig {
|
||||||
@IsEnum(Protobuf.Config_DeviceConfig_Role)
|
@IsEnum(Protobuf.Config_DeviceConfig_Role)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { IsBoolean, IsInt } from 'class-validator';
|
import { IsBoolean, IsInt } from "class-validator";
|
||||||
|
|
||||||
import type { Protobuf } from '@meshtastic/meshtasticjs';
|
import type { Protobuf } from "@meshtastic/meshtasticjs";
|
||||||
|
|
||||||
export class PositionValidation implements Protobuf.Config_PositionConfig {
|
export class PositionValidation implements Protobuf.Config_PositionConfig {
|
||||||
@IsInt()
|
@IsInt()
|
||||||
|
|||||||
Reference in New Issue
Block a user