-
Notifications
You must be signed in to change notification settings - Fork 27
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implements mesh wide map. Fixes #394. It implements bunch of new features such: - [x] It show geolocated nodes on the map, using shared stated nodes package - [x] Show bat links, and wifi links between this nodes, using shared state bat links and wifi inks data types - [x] Monitor the state of the nodes and the links - [x] You can mark the actual state of the shared state data type as the reference state to monitor changes - [x] It inform you of errors on the shared state, such non located nodes, missing shared states packages or the reference state is not set - [x] You can switch between layers to see.
- Loading branch information
Showing
78 changed files
with
11,955 additions
and
1,784 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,12 @@ | ||
import { Trans } from "@lingui/macro"; | ||
|
||
import { MapIcon } from "components/icons/teenny/map"; | ||
import { PinIcon } from "components/icons/teenny/pin"; | ||
|
||
export const LocateMenu = () => ( | ||
<span> | ||
<MapIcon /> | ||
<PinIcon /> | ||
<a href={"#/locate"}> | ||
<Trans>Map</Trans> | ||
<Trans>Locate</Trans> | ||
</a> | ||
</span> | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { MeshWideMenu } from "./src/meshWideMenu"; | ||
import MeshWidePage from "./src/meshWidePage"; | ||
import MeshWideConfigPage from "./src/screens/configPage"; | ||
|
||
export default { | ||
name: "MeshWide", | ||
page: MeshWidePage, | ||
menu: MeshWideMenu, | ||
additionalRoutes: [["/meshwide/config", MeshWideConfigPage]], | ||
} as LimePlugin; |
58 changes: 58 additions & 0 deletions
58
plugins/lime-plugin-mesh-wide/src/components/Components.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import { VNode } from "preact"; | ||
|
||
import { Button } from "components/buttons/button"; | ||
import { BinIcon } from "components/icons/bin"; | ||
import { EditIcon } from "components/icons/edit"; | ||
|
||
import SuccessIcon from "plugins/lime-plugin-mesh-wide/src/icons/SuccessIcon"; | ||
import ErrorIcon from "plugins/lime-plugin-mesh-wide/src/icons/errorIcon"; | ||
|
||
interface IStatusMessage { | ||
isError: boolean; | ||
children: VNode | string; | ||
} | ||
|
||
export const StatusAndButton = ({ | ||
isError, | ||
children, | ||
btn, | ||
onClick, | ||
}: { btn?: VNode | string; onClick?: () => void } & IStatusMessage) => { | ||
const containerClasses = | ||
"flex flex-col items-center justify-center text-center bg-white py-5 gap-3"; | ||
|
||
return ( | ||
<div className={containerClasses}> | ||
<StatusMessage isError={isError}>{children}</StatusMessage> | ||
{btn && <Button onClick={onClick}>{btn}</Button>} | ||
</div> | ||
); | ||
}; | ||
|
||
export const StatusMessage = ({ | ||
isError, | ||
children, | ||
classes, | ||
}: { | ||
classes?: string; | ||
} & IStatusMessage) => ( | ||
<div | ||
className={`flex flex-row gap-3 ${classes} items-center justify-center text-center`} | ||
> | ||
{isError ? <ErrorIcon /> : <SuccessIcon />} | ||
{children} | ||
</div> | ||
); | ||
|
||
export const EditOrDelete = ({ | ||
onEdit, | ||
onDelete, | ||
}: { | ||
onEdit: (e) => void; | ||
onDelete: (e) => void; | ||
}) => ( | ||
<div className={"flex flex-row gap-3"}> | ||
<EditIcon className={"cursor-pointer"} onClick={onEdit} /> | ||
<BinIcon className={"cursor-pointer"} onClick={onDelete} /> | ||
</div> | ||
); |
262 changes: 262 additions & 0 deletions
262
plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,262 @@ | ||
import { Trans } from "@lingui/macro"; | ||
import { useState } from "preact/hooks"; | ||
|
||
import Tabs from "components/tabs"; | ||
|
||
import { StatusAndButton } from "plugins/lime-plugin-mesh-wide/src/components/Components"; | ||
import { useSetReferenceState } from "plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/SetReferenceStateBtn"; | ||
import { | ||
getQueryByLinkType, | ||
usePointToPointErrors, | ||
} from "plugins/lime-plugin-mesh-wide/src/hooks/useLocatedLinks"; | ||
import ErrorIcon from "plugins/lime-plugin-mesh-wide/src/icons/errorIcon"; | ||
import { MacToMacLink } from "plugins/lime-plugin-mesh-wide/src/lib/links/PointToPointLink"; | ||
import { readableBytes } from "plugins/lime-plugin-mesh-wide/src/lib/utils"; | ||
import { | ||
BaseMacToMacLink, | ||
BatmanLinkErrorCodes, | ||
IBatManLinkData, | ||
ILinkMtoMErrors, | ||
IWifiLinkData, | ||
LinkMapFeature, | ||
WifiLinkErrorCodes, | ||
} from "plugins/lime-plugin-mesh-wide/src/meshWideTypes"; | ||
|
||
import { isEmpty } from "utils/utils"; | ||
|
||
import { Row, TitleAndText } from "./index"; | ||
|
||
const BatmanDetail = ({ | ||
name, | ||
errorsArray, | ||
node, | ||
}: { | ||
name: string; | ||
errorsArray: BatmanLinkErrorCodes[] | undefined; | ||
node: IBatManLinkData; | ||
}) => { | ||
return ( | ||
<> | ||
<Row> | ||
<div className={"flex"}> | ||
<strong>{name}</strong>{" "} | ||
{errorsArray?.length > 0 && <ErrorIcon />} | ||
</div> | ||
</Row> | ||
<Row> | ||
<TitleAndText title={<Trans>Iface</Trans>}> | ||
{node?.iface} | ||
</TitleAndText> | ||
<TitleAndText title={<Trans>Last seen</Trans>}> | ||
<>{node?.last_seen_msecs} ms</> | ||
</TitleAndText> | ||
</Row> | ||
</> | ||
); | ||
}; | ||
|
||
const WifiDetail = ({ | ||
name, | ||
errorsArray, | ||
node, | ||
}: { | ||
name: string; | ||
errorsArray: WifiLinkErrorCodes[]; | ||
node: IWifiLinkData; | ||
}) => { | ||
return ( | ||
<div> | ||
<Row> | ||
<div className={"flex"}> | ||
<strong>{name}</strong>{" "} | ||
{errorsArray?.length > 0 && <ErrorIcon />} | ||
</div> | ||
</Row> | ||
<Row> | ||
<TitleAndText | ||
title={<Trans>Signal</Trans>} | ||
error={ | ||
errorsArray?.includes( | ||
WifiLinkErrorCodes.SIGNAL_LOSS | ||
) ? ( | ||
<Trans> | ||
The signal is X below the reference state | ||
</Trans> | ||
) : null | ||
} | ||
> | ||
{node?.signal?.toString() ?? "0"} | ||
</TitleAndText> | ||
<TitleAndText | ||
title={<Trans>Chains</Trans>} | ||
error={ | ||
errorsArray?.includes(WifiLinkErrorCodes.CHAIN_LOSS) ? ( | ||
<Trans> | ||
The difference between chains is too big | ||
</Trans> | ||
) : null | ||
} | ||
> | ||
{node?.chains?.toString() ?? "0/0"} | ||
</TitleAndText> | ||
</Row> | ||
<Row> | ||
<TitleAndText title={<Trans>TxRate</Trans>}> | ||
{`${readableBytes(node.tx_rate)}`} | ||
</TitleAndText> | ||
<TitleAndText title={<Trans>RxRate</Trans>}> | ||
{`${readableBytes(node.rx_rate)}`} | ||
</TitleAndText> | ||
</Row> | ||
</div> | ||
); | ||
}; | ||
|
||
const SelectedLink = ({ | ||
linkDetail, | ||
errors, | ||
}: { | ||
linkDetail: BaseMacToMacLink; | ||
errors: ILinkMtoMErrors | undefined; | ||
}) => { | ||
if (linkDetail === undefined || (errors && !errors?.linkUp)) | ||
return ( | ||
<div> | ||
<Trans>This link seems down</Trans> | ||
</div> | ||
); | ||
|
||
const names = linkDetail?.names; | ||
const linkType = linkDetail.type; | ||
|
||
return ( | ||
<> | ||
<Row> | ||
{names && ( | ||
<div className={"text-3xl"}> | ||
<Trans> | ||
Link from <strong>{names[0]}</strong> to{" "} | ||
<strong>{names[1]}</strong> | ||
</Trans> | ||
</div> | ||
)} | ||
</Row> | ||
{names.map((name, i) => { | ||
const node = linkDetail.linkByName(name); | ||
const errorsArray = errors?.linkErrors[name] ?? []; | ||
return linkType === "wifi_links_info" ? ( | ||
<WifiDetail | ||
key={i} | ||
name={name} | ||
errorsArray={errorsArray as WifiLinkErrorCodes[]} | ||
node={node as IWifiLinkData} | ||
/> | ||
) : ( | ||
<BatmanDetail | ||
key={i} | ||
name={name} | ||
errorsArray={errorsArray as BatmanLinkErrorCodes[]} | ||
node={node as IBatManLinkData} | ||
/> | ||
); | ||
})} | ||
</> | ||
); | ||
}; | ||
|
||
const LinkFeatureDetail = ({ actual, reference }: LinkMapFeature) => { | ||
const linkToShow = reference ?? actual; | ||
const [selectedLink, setSelectedLink] = useState(0); | ||
const { errors } = usePointToPointErrors({ | ||
id: linkToShow.id, | ||
type: linkToShow.type, | ||
}); | ||
const linkType = linkToShow.type; | ||
|
||
const tabs = linkToShow.links.map( | ||
(link: MacToMacLink<typeof linkType>, i) => { | ||
return { | ||
key: i, | ||
repr: ( | ||
<div className={"flex"}> | ||
<Trans> | ||
Link {i + 1}{" "} | ||
{errors && | ||
errors?.macToMacErrors[link.id]?.hasErrors ? ( | ||
<ErrorIcon /> | ||
) : null} | ||
</Trans> | ||
</div> | ||
), | ||
}; | ||
} | ||
); | ||
|
||
return ( | ||
<div className="d-flex flex-column flex-grow-1 overflow-auto gap-6"> | ||
{tabs?.length > 1 && ( | ||
<Tabs | ||
tabs={tabs} | ||
current={selectedLink} | ||
onChange={setSelectedLink} | ||
/> | ||
)} | ||
{selectedLink !== null && ( | ||
<SelectedLink | ||
linkDetail={actual?.links[selectedLink]} | ||
errors={ | ||
errors?.macToMacErrors[actual?.links[selectedLink]?.id] | ||
} | ||
/> | ||
)} | ||
</div> | ||
); | ||
}; | ||
|
||
export const LinkReferenceStatus = ({ reference }: LinkMapFeature) => { | ||
const isNewNode = !reference; | ||
|
||
const { errors } = usePointToPointErrors({ | ||
id: reference.id, | ||
type: reference.type, | ||
}); | ||
|
||
// Check if there are errors of global reference state to shown | ||
const { reference: fetchDataReference } = getQueryByLinkType( | ||
reference.type | ||
); | ||
const { data: referenceData, isError: isReferenceError } = | ||
fetchDataReference({}); | ||
let referenceError = false; | ||
if (!referenceData || isEmpty(referenceData) || isReferenceError) { | ||
referenceError = true; | ||
} | ||
|
||
// Mutation to update the reference state | ||
const { mutate, btnText } = useSetReferenceState(reference.type); | ||
|
||
let errorMessage = <Trans>Same status as in the reference state</Trans>; | ||
if (referenceError) { | ||
errorMessage = <Trans>Reference is not set or has errors</Trans>; | ||
} else if (errors?.hasErrors) { | ||
errorMessage = <Trans>This link has errors</Trans>; | ||
} else if (isNewNode) { | ||
errorMessage = ( | ||
<Trans>This Link is not registered on the reference state</Trans> | ||
); | ||
} | ||
|
||
const hasError = errors?.hasErrors || referenceError || isNewNode; | ||
|
||
return ( | ||
<StatusAndButton | ||
isError={hasError} | ||
btn={hasError && btnText} | ||
onClick={mutate} | ||
> | ||
{errorMessage} | ||
</StatusAndButton> | ||
); | ||
}; | ||
|
||
export default LinkFeatureDetail; |
Oops, something went wrong.