7 changed files with 168 additions and 56 deletions
@ -1,50 +0,0 @@ |
|||||
import type React from "react"; |
|
||||
import { useState } from "react"; |
|
||||
|
|
||||
import { useDevice } from "@app/core/providers/useDevice.js"; |
|
||||
import { ChevronDownIcon, ChevronUpIcon } from "@heroicons/react/24/outline"; |
|
||||
|
|
||||
export const Drawer = (): JSX.Element => { |
|
||||
const [drawerOpen, setDrawerOpen] = useState(false); |
|
||||
|
|
||||
const tabs = [{ title: "Notifications" }, { title: "Debug" }]; |
|
||||
|
|
||||
const { config, moduleConfig, hardware, nodes, waypoints, connection } = |
|
||||
useDevice(); |
|
||||
|
|
||||
const [serialLogs, setSerialLogs] = useState<string>(""); |
|
||||
|
|
||||
connection?.onDeviceDebugLog.subscribe((packet) => { |
|
||||
setSerialLogs(serialLogs + new TextDecoder().decode(packet)); |
|
||||
}); |
|
||||
|
|
||||
return ( |
|
||||
<div className={`shadow-md ${drawerOpen ? "h-40" : "h-8"}`}> |
|
||||
<div className="flex h-8 bg-slate-50"> |
|
||||
<div |
|
||||
onClick={() => { |
|
||||
setDrawerOpen(!drawerOpen); |
|
||||
}} |
|
||||
className="ml-auto flex px-2 hover:cursor-pointer hover:bg-slate-100" |
|
||||
> |
|
||||
<div className="m-auto"> |
|
||||
{drawerOpen ? ( |
|
||||
<ChevronDownIcon className="h-4 text-gray-700" /> |
|
||||
) : ( |
|
||||
<ChevronUpIcon className="h-4 text-gray-700" /> |
|
||||
)} |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div className={`${drawerOpen ? "flex" : "hidden"}`}> |
|
||||
<div> |
|
||||
{serialLogs.split("\n").map((line, index) => ( |
|
||||
<div key={index} className="text-sm"> |
|
||||
{line} |
|
||||
</div> |
|
||||
))} |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
); |
|
||||
}; |
|
||||
@ -0,0 +1,98 @@ |
|||||
|
import "chartjs-adapter-date-fns"; |
||||
|
|
||||
|
import type React from "react"; |
||||
|
|
||||
|
import { |
||||
|
Chart as ChartJS, |
||||
|
Filler, |
||||
|
Legend, |
||||
|
LinearScale, |
||||
|
LineElement, |
||||
|
PointElement, |
||||
|
TimeSeriesScale, |
||||
|
Tooltip |
||||
|
} from "chart.js"; |
||||
|
import { Line } from "react-chartjs-2"; |
||||
|
|
||||
|
import { useDevice } from "@app/core/providers/useDevice.js"; |
||||
|
|
||||
|
export const Metrics = (): JSX.Element => { |
||||
|
const { nodes, hardware } = useDevice(); |
||||
|
|
||||
|
const myNode = nodes.find((n) => n.data.num === hardware.myNodeNum); |
||||
|
|
||||
|
ChartJS.register( |
||||
|
LinearScale, |
||||
|
PointElement, |
||||
|
LineElement, |
||||
|
Tooltip, |
||||
|
Filler, |
||||
|
Legend, |
||||
|
TimeSeriesScale |
||||
|
); |
||||
|
|
||||
|
return ( |
||||
|
<div className="flex h-full w-full flex-grow"> |
||||
|
{/* {myNode?.deviceMetrics.map((metric) => ( |
||||
|
<p>{metric.airUtilTx}</p> |
||||
|
))} */} |
||||
|
<Line |
||||
|
className="h-full w-full flex-grow" |
||||
|
options={{ |
||||
|
responsive: true, |
||||
|
maintainAspectRatio: false, |
||||
|
scales: { |
||||
|
x: { |
||||
|
type: "timeseries" |
||||
|
} |
||||
|
} |
||||
|
}} |
||||
|
data={{ |
||||
|
labels: [], |
||||
|
datasets: [ |
||||
|
{ |
||||
|
fill: true, |
||||
|
label: "airUtilTx", |
||||
|
data: myNode?.deviceMetrics.map((metric) => { |
||||
|
return { |
||||
|
x: metric.timestamp, |
||||
|
y: metric.airUtilTx |
||||
|
}; |
||||
|
}) |
||||
|
}, |
||||
|
{ |
||||
|
fill: true, |
||||
|
label: "channelUtilization", |
||||
|
data: myNode?.deviceMetrics.map((metric) => { |
||||
|
return { |
||||
|
x: metric.timestamp, |
||||
|
y: metric.channelUtilization |
||||
|
}; |
||||
|
}) |
||||
|
}, |
||||
|
{ |
||||
|
fill: true, |
||||
|
label: "batteryLevel", |
||||
|
data: myNode?.deviceMetrics.map((metric) => { |
||||
|
return { |
||||
|
x: metric.timestamp, |
||||
|
y: metric.batteryLevel |
||||
|
}; |
||||
|
}) |
||||
|
}, |
||||
|
{ |
||||
|
fill: true, |
||||
|
label: "voltage", |
||||
|
data: myNode?.deviceMetrics.map((metric) => { |
||||
|
return { |
||||
|
x: metric.timestamp, |
||||
|
y: metric.voltage |
||||
|
}; |
||||
|
}) |
||||
|
} |
||||
|
] |
||||
|
}} |
||||
|
/> |
||||
|
</div> |
||||
|
); |
||||
|
}; |
||||
@ -0,0 +1,3 @@ |
|||||
|
export const Notifications = (): JSX.Element => { |
||||
|
return <div></div>; |
||||
|
}; |
||||
@ -0,0 +1,65 @@ |
|||||
|
import type React from "react"; |
||||
|
import { useState } from "react"; |
||||
|
|
||||
|
import { Tab } from "@headlessui/react"; |
||||
|
import { ChevronDownIcon, ChevronUpIcon } from "@heroicons/react/24/outline"; |
||||
|
|
||||
|
import type { TabType } from "../layout/page/TabbedContent.js"; |
||||
|
import { Metrics } from "./Metrics.js"; |
||||
|
import { Notifications } from "./Notifications.js"; |
||||
|
|
||||
|
export const Drawer = (): JSX.Element => { |
||||
|
const [drawerOpen, setDrawerOpen] = useState(false); |
||||
|
|
||||
|
const tabs: TabType[] = [ |
||||
|
{ name: "Notifications", element: Notifications }, |
||||
|
{ name: "Metrics", element: Metrics } |
||||
|
]; |
||||
|
return ( |
||||
|
<Tab.Group> |
||||
|
<Tab.List className="flex"> |
||||
|
{tabs.map((tab, index) => ( |
||||
|
<Tab key={index}> |
||||
|
{({ selected }) => ( |
||||
|
<div |
||||
|
onClick={() => { |
||||
|
setDrawerOpen(true); |
||||
|
}} |
||||
|
className={`flex h-full cursor-pointer px-1 first:pl-2 last:pr-2 hover:bg-orange-300 ${ |
||||
|
selected ? "bg-orange-500 text-white" : "bg-white text-black" |
||||
|
}`}
|
||||
|
> |
||||
|
<span className="m-auto select-none">{tab.name}</span> |
||||
|
</div> |
||||
|
)} |
||||
|
</Tab> |
||||
|
))} |
||||
|
|
||||
|
<div className="ml-auto flex h-8"> |
||||
|
<div |
||||
|
onClick={() => { |
||||
|
setDrawerOpen(!drawerOpen); |
||||
|
}} |
||||
|
className="flex cursor-pointer px-2" |
||||
|
> |
||||
|
<div className="m-auto"> |
||||
|
{drawerOpen ? ( |
||||
|
<ChevronDownIcon className="h-4 text-gray-700" /> |
||||
|
) : ( |
||||
|
<ChevronUpIcon className="h-4 text-gray-700" /> |
||||
|
)} |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</Tab.List> |
||||
|
|
||||
|
<Tab.Panels className={`${drawerOpen ? "flex" : "hidden"}`}> |
||||
|
{tabs.map((tab, index) => ( |
||||
|
<Tab.Panel key={index} className="flex h-40 flex-grow"> |
||||
|
{tab.element} |
||||
|
</Tab.Panel> |
||||
|
))} |
||||
|
</Tab.Panels> |
||||
|
</Tab.Group> |
||||
|
); |
||||
|
}; |
||||
Loading…
Reference in new issue