Sacha Weatherstone
4 years ago
No known key found for this signature in database
GPG Key ID: 7AB2D7E206124B31
7 changed files with
137 additions and
82 deletions
-
src/components/Card.tsx
-
src/components/Dropdown.tsx
-
src/components/Widgets/BatteryWidget.tsx
-
src/components/Widgets/ConfiguringWidget.tsx
-
src/components/Widgets/NodeInfoWidget.tsx
-
src/components/Widgets/PeersWidget.tsx
-
src/components/Widgets/PositionWidget.tsx
|
|
|
@ -7,7 +7,7 @@ export const Card = ({ |
|
|
|
}: JSX.IntrinsicElements["div"]): JSX.Element => { |
|
|
|
return ( |
|
|
|
<div |
|
|
|
className={`flex overflow-hidden rounded-2xl bg-white text-sm text-black shadow-md ${ |
|
|
|
className={`flex overflow-hidden rounded-md bg-white text-sm text-black shadow-md ${ |
|
|
|
className ?? "" |
|
|
|
}`}
|
|
|
|
{...rest} |
|
|
|
|
|
|
|
@ -0,0 +1,39 @@ |
|
|
|
import type React from "react"; |
|
|
|
|
|
|
|
import { Disclosure } from "@headlessui/react"; |
|
|
|
import { ChevronDownIcon, ChevronUpIcon } from "@heroicons/react/24/outline"; |
|
|
|
|
|
|
|
export interface DropdownProps { |
|
|
|
title: string; |
|
|
|
icon: JSX.Element; |
|
|
|
children: React.ReactNode; |
|
|
|
} |
|
|
|
|
|
|
|
export const Dropdown = ({ |
|
|
|
title, |
|
|
|
icon, |
|
|
|
children, |
|
|
|
}: DropdownProps): JSX.Element => { |
|
|
|
return ( |
|
|
|
<Disclosure defaultOpen> |
|
|
|
{({ open }) => ( |
|
|
|
<> |
|
|
|
<Disclosure.Button className="flex h-8 justify-between bg-slate-100 px-2 hover:bg-slate-200"> |
|
|
|
<div className="my-auto flex gap-2 text-slate-700"> |
|
|
|
<div className="my-auto">{icon}</div> |
|
|
|
<span className="text-lg font-medium">{title}</span> |
|
|
|
</div> |
|
|
|
<div className="my-auto text-slate-600"> |
|
|
|
{open ? ( |
|
|
|
<ChevronUpIcon className="h-5" /> |
|
|
|
) : ( |
|
|
|
<ChevronDownIcon className="h-5" /> |
|
|
|
)} |
|
|
|
</div> |
|
|
|
</Disclosure.Button> |
|
|
|
<Disclosure.Panel>{children}</Disclosure.Panel> |
|
|
|
</> |
|
|
|
)} |
|
|
|
</Disclosure> |
|
|
|
); |
|
|
|
}; |
|
|
|
@ -1,8 +1,10 @@ |
|
|
|
import type React from "react"; |
|
|
|
|
|
|
|
import { BoltIcon } from "@heroicons/react/24/outline"; |
|
|
|
import { Battery100Icon, BoltIcon } from "@heroicons/react/24/outline"; |
|
|
|
|
|
|
|
import { Card } from "../Card.js"; |
|
|
|
import { Dropdown } from "../Dropdown.js"; |
|
|
|
import { Mono } from "../Mono.js"; |
|
|
|
|
|
|
|
export interface BatteryWidgetProps { |
|
|
|
batteryLevel: number; |
|
|
|
@ -14,17 +16,22 @@ export const BatteryWidget = ({ |
|
|
|
voltage, |
|
|
|
}: BatteryWidgetProps): JSX.Element => { |
|
|
|
return ( |
|
|
|
<Card> |
|
|
|
<Card className="flex-col"> |
|
|
|
<Dropdown title="Position" icon={<BoltIcon className="h-4" />}> |
|
|
|
<div className="flex"> |
|
|
|
<div className="flex w-20 bg-slate-700 p-3"> |
|
|
|
<BoltIcon className="m-auto h-12 text-white" /> |
|
|
|
<Battery100Icon className="m-auto h-12 text-white" /> |
|
|
|
</div> |
|
|
|
<div className="w-full"> |
|
|
|
<div className="flex h-8 bg-slate-100"> |
|
|
|
<span className="m-auto text-lg font-medium">Power</span> |
|
|
|
</div> |
|
|
|
<span>{batteryLevel}</span> |
|
|
|
<span>{voltage}</span> |
|
|
|
<span className="m-auto text-lg"> |
|
|
|
{batteryLevel} |
|
|
|
<Mono>%</Mono> |
|
|
|
</span> |
|
|
|
<span className="m-auto text-lg"> |
|
|
|
{voltage} |
|
|
|
<Mono>v</Mono> |
|
|
|
</span> |
|
|
|
</div> |
|
|
|
</Dropdown> |
|
|
|
</Card> |
|
|
|
); |
|
|
|
}; |
|
|
|
|
|
|
|
@ -1,9 +1,11 @@ |
|
|
|
import React, { useEffect } from "react"; |
|
|
|
|
|
|
|
import { useDevice } from "@core/providers/useDevice.js"; |
|
|
|
import { AdjustmentsHorizontalIcon } from "@heroicons/react/24/outline"; |
|
|
|
|
|
|
|
import { Button } from "../Button.js"; |
|
|
|
import { Card } from "../Card.js"; |
|
|
|
import { Dropdown } from "../Dropdown.js"; |
|
|
|
|
|
|
|
export const ConfiguringWidget = (): JSX.Element => { |
|
|
|
const { |
|
|
|
@ -36,9 +38,10 @@ export const ConfiguringWidget = (): JSX.Element => { |
|
|
|
|
|
|
|
return ( |
|
|
|
<Card className="flex-col"> |
|
|
|
<div className="flex h-8 bg-slate-100"> |
|
|
|
<span className="m-auto text-lg font-medium">Power</span> |
|
|
|
</div> |
|
|
|
<Dropdown |
|
|
|
title="Config Status" |
|
|
|
icon={<AdjustmentsHorizontalIcon className="h-4" />} |
|
|
|
> |
|
|
|
<div className="flex flex-col gap-2 p-3"> |
|
|
|
<ol className="flex flex-col gap-3 overflow-hidden"> |
|
|
|
<StatusIndicator |
|
|
|
@ -73,6 +76,7 @@ export const ConfiguringWidget = (): JSX.Element => { |
|
|
|
Retry |
|
|
|
</Button> |
|
|
|
</div> |
|
|
|
</Dropdown> |
|
|
|
</Card> |
|
|
|
); |
|
|
|
}; |
|
|
|
|
|
|
|
@ -1,8 +1,10 @@ |
|
|
|
import type React from "react"; |
|
|
|
|
|
|
|
import { InformationCircleIcon } from "@heroicons/react/24/outline"; |
|
|
|
import type { Protobuf } from "@meshtastic/meshtasticjs"; |
|
|
|
|
|
|
|
import { Card } from "../Card.js"; |
|
|
|
import { Dropdown } from "../Dropdown.js"; |
|
|
|
|
|
|
|
export interface NodeInfoWidgetProps { |
|
|
|
hardware: Protobuf.MyNodeInfo; |
|
|
|
@ -13,9 +15,10 @@ export const NodeInfoWidget = ({ |
|
|
|
}: NodeInfoWidgetProps): JSX.Element => { |
|
|
|
return ( |
|
|
|
<Card className="flex-col"> |
|
|
|
<div className="flex h-8 bg-slate-100"> |
|
|
|
<span className="m-auto text-lg font-medium">Information</span> |
|
|
|
</div> |
|
|
|
<Dropdown |
|
|
|
title="Information" |
|
|
|
icon={<InformationCircleIcon className="h-4" />} |
|
|
|
> |
|
|
|
<div className="flex flex-col gap-2 p-3"> |
|
|
|
<dl className="mt-2 border-b border-gray-200"> |
|
|
|
<div className="flex justify-between py-1 text-sm font-medium"> |
|
|
|
@ -33,6 +36,7 @@ export const NodeInfoWidget = ({ |
|
|
|
</dd> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</Dropdown> |
|
|
|
</Card> |
|
|
|
); |
|
|
|
}; |
|
|
|
|
|
|
|
@ -3,10 +3,14 @@ import type React from "react"; |
|
|
|
import { base16 } from "rfc4648"; |
|
|
|
|
|
|
|
import { Hashicon } from "@emeraldpay/hashicon-react"; |
|
|
|
import { EllipsisHorizontalCircleIcon } from "@heroicons/react/24/outline"; |
|
|
|
import { |
|
|
|
EllipsisHorizontalCircleIcon, |
|
|
|
UserGroupIcon, |
|
|
|
} from "@heroicons/react/24/outline"; |
|
|
|
import type { Protobuf } from "@meshtastic/meshtasticjs"; |
|
|
|
|
|
|
|
import { Card } from "../Card.js"; |
|
|
|
import { Dropdown } from "../Dropdown.js"; |
|
|
|
import { IconButton } from "../IconButton.js"; |
|
|
|
import { Mono } from "../Mono.js"; |
|
|
|
|
|
|
|
@ -16,12 +20,9 @@ export interface PeersWidgetProps { |
|
|
|
|
|
|
|
export const PeersWidget = ({ peers }: PeersWidgetProps): JSX.Element => { |
|
|
|
return ( |
|
|
|
<Card> |
|
|
|
<div className="flex w-full flex-col gap-1"> |
|
|
|
<div className="flex h-8 bg-slate-100"> |
|
|
|
<span className="m-auto text-lg font-medium">Peers</span> |
|
|
|
</div> |
|
|
|
<div className="p-4"> |
|
|
|
<Card className="flex-col"> |
|
|
|
<Dropdown title="Peers" icon={<UserGroupIcon className="h-4" />}> |
|
|
|
<div className="p-3"> |
|
|
|
{peers.map((peer) => ( |
|
|
|
<div |
|
|
|
className="flex gap-2 rounded-md p-2 hover:bg-slate-100" |
|
|
|
@ -49,7 +50,7 @@ export const PeersWidget = ({ peers }: PeersWidgetProps): JSX.Element => { |
|
|
|
</div> |
|
|
|
))} |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</Dropdown> |
|
|
|
</Card> |
|
|
|
); |
|
|
|
}; |
|
|
|
|
|
|
|
@ -3,6 +3,7 @@ import type React from "react"; |
|
|
|
import { MapPinIcon } from "@heroicons/react/24/outline"; |
|
|
|
|
|
|
|
import { Card } from "../Card.js"; |
|
|
|
import { Dropdown } from "../Dropdown.js"; |
|
|
|
|
|
|
|
export interface PositionWidgetProps { |
|
|
|
grid: string; |
|
|
|
@ -10,16 +11,15 @@ export interface PositionWidgetProps { |
|
|
|
|
|
|
|
export const PositionWidget = ({ grid }: PositionWidgetProps): JSX.Element => { |
|
|
|
return ( |
|
|
|
<Card> |
|
|
|
<Card className="flex-col"> |
|
|
|
<Dropdown title="Position" icon={<MapPinIcon className="h-4" />}> |
|
|
|
<div className="flex"> |
|
|
|
<div className="flex w-20 bg-teal-600 p-3"> |
|
|
|
<MapPinIcon className="m-auto h-12 text-white" /> |
|
|
|
</div> |
|
|
|
<div className="flex w-full flex-col"> |
|
|
|
<div className="flex h-8 bg-slate-100"> |
|
|
|
<span className="m-auto text-lg font-medium">Position</span> |
|
|
|
</div> |
|
|
|
<span className="m-auto text-lg">{grid}</span> |
|
|
|
</div> |
|
|
|
</Dropdown> |
|
|
|
</Card> |
|
|
|
); |
|
|
|
}; |
|
|
|
|