Browse Source

Merge pull request #234 from Hunter275/revert-remove-node-work

revert "remove node work" commit
pull/233/head
Ben Meadors 2 years ago
committed by GitHub
parent
commit
8ad1fbaa1c
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 2
      package.json
  2. 6502
      pnpm-lock.yaml
  3. 7
      src/components/Dialog/DialogManager.tsx
  4. 52
      src/components/Dialog/RemoveNodeDialog.tsx
  5. 7
      src/core/stores/appStore.ts
  6. 17
      src/core/stores/deviceStore.ts
  7. 19
      src/pages/Nodes.tsx

2
package.json

@ -22,7 +22,7 @@
"dependencies": { "dependencies": {
"@bufbuild/protobuf": "^1.8.0", "@bufbuild/protobuf": "^1.8.0",
"@emeraldpay/hashicon-react": "^0.5.2", "@emeraldpay/hashicon-react": "^0.5.2",
"@meshtastic/js": "2.3.3-0", "@meshtastic/js": "2.3.4-0",
"@radix-ui/react-accordion": "^1.1.2", "@radix-ui/react-accordion": "^1.1.2",
"@radix-ui/react-checkbox": "^1.0.4", "@radix-ui/react-checkbox": "^1.0.4",
"@radix-ui/react-dialog": "^1.0.5", "@radix-ui/react-dialog": "^1.0.5",

6502
pnpm-lock.yaml

File diff suppressed because it is too large

7
src/components/Dialog/DialogManager.tsx

@ -3,6 +3,7 @@ import { ImportDialog } from "@components/Dialog/ImportDialog.js";
import { QRDialog } from "@components/Dialog/QRDialog.js"; import { QRDialog } from "@components/Dialog/QRDialog.js";
import { RebootDialog } from "@components/Dialog/RebootDialog.js"; import { RebootDialog } from "@components/Dialog/RebootDialog.js";
import { ShutdownDialog } from "@components/Dialog/ShutdownDialog.js"; import { ShutdownDialog } from "@components/Dialog/ShutdownDialog.js";
import { RemoveNodeDialog } from "@app/components/Dialog/RemoveNodeDialog.js"
import { useDevice } from "@core/stores/deviceStore.js"; import { useDevice } from "@core/stores/deviceStore.js";
export const DialogManager = (): JSX.Element => { export const DialogManager = (): JSX.Element => {
@ -42,6 +43,12 @@ export const DialogManager = (): JSX.Element => {
setDialogOpen("deviceName", open); setDialogOpen("deviceName", open);
}} }}
/> />
<RemoveNodeDialog
open={dialog.nodeRemoval}
onOpenChange={(open) => {
setDialogOpen("nodeRemoval", open);
}}
/>
</> </>
); );
}; };

52
src/components/Dialog/RemoveNodeDialog.tsx

@ -0,0 +1,52 @@
import { useAppStore } from "@app/core/stores/appStore";
import { useDevice } from "@app/core/stores/deviceStore.js";
import { Button } from "@components/UI/Button.js";
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from "@components/UI/Dialog.js";
import { Label } from "@components/UI/Label.js";
export interface RemoveNodeDialogProps {
open: boolean;
onOpenChange: (open: boolean) => void;
}
export const RemoveNodeDialog = ({
open,
onOpenChange,
}: RemoveNodeDialogProps): JSX.Element => {
const { connection, nodes, removeNode } = useDevice();
const { nodeNumToBeRemoved } = useAppStore();
const onSubmit = () => {
connection?.removeNodeByNum(nodeNumToBeRemoved);
removeNode(nodeNumToBeRemoved);
onOpenChange(false);
};
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent>
<DialogHeader>
<DialogTitle>Remove Node?</DialogTitle>
<DialogDescription>
Are you sure you want to remove this Node?
</DialogDescription>
</DialogHeader>
<div className="gap-4">
<form onSubmit={onSubmit}>
<Label>{nodes.get(nodeNumToBeRemoved)?.user?.longName}</Label>
</form>
</div>
<DialogFooter>
<Button variant="destructive" onClick={() => onSubmit()}>Remove</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
};

7
src/core/stores/appStore.ts

@ -26,6 +26,7 @@ interface AppState {
rasterSources: RasterSource[]; rasterSources: RasterSource[];
commandPaletteOpen: boolean; commandPaletteOpen: boolean;
darkMode: boolean; darkMode: boolean;
nodeNumToBeRemoved: number;
accent: AccentColor; accent: AccentColor;
connectDialogOpen: boolean; connectDialogOpen: boolean;
@ -38,6 +39,7 @@ interface AppState {
removeDevice: (deviceId: number) => void; removeDevice: (deviceId: number) => void;
setCommandPaletteOpen: (open: boolean) => void; setCommandPaletteOpen: (open: boolean) => void;
setDarkMode: (enabled: boolean) => void; setDarkMode: (enabled: boolean) => void;
setNodeNumToBeRemoved: (nodeNum: number) => void;
setAccent: (color: AccentColor) => void; setAccent: (color: AccentColor) => void;
setConnectDialogOpen: (open: boolean) => void; setConnectDialogOpen: (open: boolean) => void;
} }
@ -51,6 +53,7 @@ export const useAppStore = create<AppState>()((set) => ({
darkMode: window.matchMedia("(prefers-color-scheme: dark)").matches, darkMode: window.matchMedia("(prefers-color-scheme: dark)").matches,
accent: "orange", accent: "orange",
connectDialogOpen: false, connectDialogOpen: false,
nodeNumToBeRemoved: 0,
setRasterSources: (sources: RasterSource[]) => { setRasterSources: (sources: RasterSource[]) => {
set( set(
@ -99,6 +102,10 @@ export const useAppStore = create<AppState>()((set) => ({
}), }),
); );
}, },
setNodeNumToBeRemoved: (nodeNum) =>
set((state) => ({
nodeNumToBeRemoved: nodeNum
})),
setAccent(color) { setAccent(color) {
set( set(
produce<AppState>((draft) => { produce<AppState>((draft) => {

17
src/core/stores/deviceStore.ts

@ -24,7 +24,8 @@ export type DialogVariant =
| "QR" | "QR"
| "shutdown" | "shutdown"
| "reboot" | "reboot"
| "deviceName"; | "deviceName"
| "nodeRemoval";
export interface Device { export interface Device {
id: number; id: number;
@ -54,6 +55,7 @@ export interface Device {
shutdown: boolean; shutdown: boolean;
reboot: boolean; reboot: boolean;
deviceName: boolean; deviceName: boolean;
nodeRemoval: boolean;
}; };
setStatus: (status: Types.DeviceStatusEnum) => void; setStatus: (status: Types.DeviceStatusEnum) => void;
@ -74,6 +76,7 @@ export interface Device {
addConnection: (connection: Types.ConnectionType) => void; addConnection: (connection: Types.ConnectionType) => void;
addMessage: (message: MessageWithState) => void; addMessage: (message: MessageWithState) => void;
addMetadata: (from: number, metadata: Protobuf.Mesh.DeviceMetadata) => void; addMetadata: (from: number, metadata: Protobuf.Mesh.DeviceMetadata) => void;
removeNode: (nodeNum: number) => void;
setMessageState: ( setMessageState: (
type: "direct" | "broadcast", type: "direct" | "broadcast",
channelIndex: Types.ChannelNumber, channelIndex: Types.ChannelNumber,
@ -130,6 +133,7 @@ export const useDeviceStore = create<DeviceState>((set, get) => ({
shutdown: false, shutdown: false,
reboot: false, reboot: false,
deviceName: false, deviceName: false,
nodeRemoval: false,
}, },
pendingSettingsChanges: false, pendingSettingsChanges: false,
messageDraft: "", messageDraft: "",
@ -494,6 +498,17 @@ export const useDeviceStore = create<DeviceState>((set, get) => ({
}), }),
); );
}, },
removeNode: (nodeNum) => {
set(
produce<DeviceState>((draft) => {
const device = draft.devices.get(id);
if (!device) {
return;
}
device.nodes.delete(nodeNum);
})
)
},
setMessageState: ( setMessageState: (
type: "direct" | "broadcast", type: "direct" | "broadcast",
channelIndex: Types.ChannelNumber, channelIndex: Types.ChannelNumber,

19
src/pages/Nodes.tsx

@ -6,9 +6,18 @@ import { useDevice } from "@core/stores/deviceStore.js";
import { Hashicon } from "@emeraldpay/hashicon-react"; import { Hashicon } from "@emeraldpay/hashicon-react";
import { Protobuf } from "@meshtastic/js"; import { Protobuf } from "@meshtastic/js";
import { base16 } from "rfc4648"; import { base16 } from "rfc4648";
import { Button } from "@components/UI/Button.js";
import { TrashIcon } from "lucide-react";
import { useAppStore } from "@app/core/stores/appStore";
export interface DeleteNoteDialogProps {
open: boolean;
onOpenChange: (open: boolean) => void;
}
export const NodesPage = (): JSX.Element => { export const NodesPage = (): JSX.Element => {
const { nodes, hardware } = useDevice(); const { nodes, hardware, setDialogOpen } = useDevice();
const { setNodeNumToBeRemoved } = useAppStore();
const filteredNodes = Array.from(nodes.values()).filter( const filteredNodes = Array.from(nodes.values()).filter(
(n) => n.num !== hardware.myNodeNum, (n) => n.num !== hardware.myNodeNum,
@ -27,6 +36,7 @@ export const NodesPage = (): JSX.Element => {
{ title: "Last Heard", type: "normal", sortable: true }, { title: "Last Heard", type: "normal", sortable: true },
{ title: "SNR", type: "normal", sortable: true }, { title: "SNR", type: "normal", sortable: true },
{ title: "Connection", type: "normal", sortable: true }, { title: "Connection", type: "normal", sortable: true },
{ title: "Remove", type: "normal", sortable: false },
]} ]}
rows={filteredNodes.map((node) => [ rows={filteredNodes.map((node) => [
<Hashicon size={24} value={node.num.toString()} />, <Hashicon size={24} value={node.num.toString()} />,
@ -56,13 +66,6 @@ export const NodesPage = (): JSX.Element => {
{Math.min(Math.max((node.snr + 10) * 5, 0), 100)}%/ {Math.min(Math.max((node.snr + 10) * 5, 0), 100)}%/
{(node.snr + 10) * 5}raw {(node.snr + 10) * 5}raw
</Mono>, </Mono>,
<Mono>
{node.lastHeard != 0 ?
(node.viaMqtt === false && node.hopsAway === 0
? "Direct": node.hopsAway.toString() + " hops away")
: "-"}
{node.viaMqtt === true? ", via MQTT": ""}
</Mono>
])} ])}
/> />
</div> </div>

Loading…
Cancel
Save