Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement mesh wide map #416

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
121 commits
Select commit Hold shift + click to select a range
d1c212d
fix(typescript): Fix typescript no strict mode
fnbellomo Dec 18, 2022
4f80d9f
chore(tailwindcss): Install tailwindcss
selankon Feb 10, 2023
d836580
chore(locate): implement react leaflet
selankon Mar 31, 2023
98c513c
chore(meshwide): bootstrap Mesh Wide page
selankon Apr 12, 2023
3a8a38d
chore(meshwide): create bottom sheet
selankon Apr 14, 2023
2cdc044
chore(meshwide): add footer to BottosmSheet
selankon Apr 17, 2023
04ebe64
chore(meshwide): add attribute to disable close button
selankon Apr 17, 2023
4d0bf0e
chore(components): implement danger outline button
selankon Apr 17, 2023
3091e64
chore(meshwide): create bottom sheet mock
selankon Apr 17, 2023
c783bb4
chore(meshwide): implement bad sync state
selankon Apr 18, 2023
0386803
chore(meshwide): apply some styles
selankon Apr 18, 2023
fb1ba3c
WIP save some work
selankon Apr 20, 2023
f99287f
chore(rxPage): add missing changes
selankon May 3, 2023
f0b3c85
chore(meshwide): fix ts errors
selankon May 4, 2023
3d87aa3
chore(meshwide): split on different files
selankon May 4, 2023
18bbf28
chore(meshwide): show community layer
selankon May 10, 2023
42bcbe6
chore(meshwide): try to use a callback to select a layer
selankon May 16, 2023
d421123
chore(meshwide): use react-leaflet components to show features
selankon May 16, 2023
4f65718
chore(meshwide): use query to store selected feature
selankon May 17, 2023
10ad250
chore(meshwide): configure bottom sheet logic
selankon May 18, 2023
e471067
chore(meshwide): implement bottom sheet for links behaviour
selankon May 18, 2023
62979b9
chore(meshwide): split components to reuse them
selankon May 22, 2023
ffc0241
chore(meshwide): create mesh wide config page
selankon May 23, 2023
9e498b5
chore(src): refactor collapsible component style
selankon May 24, 2023
fe94f16
chore(meshwide): implement meshwide config object
selankon May 24, 2023
bd21e0a
chore(meshwide): fix isLoading
selankon May 24, 2023
e7c7632
chore(meshwide): move to proper side
selankon May 25, 2023
2bdf49c
chore(meshwide): fix buttons path
selankon May 26, 2023
2320dc9
chore(meshwide): implement mesh wide config form
selankon May 29, 2023
ebfab26
chore(components): implement modal provider
selankon May 30, 2023
d03e937
chore(meshwide): implement modals
selankon May 31, 2023
642b875
chore(components): move modal folder
selankon Jun 1, 2023
d63c82b
chore(components): improve toast
selankon Jun 1, 2023
f291433
chore(meshwide): implement add new section modal
selankon Jun 2, 2023
a606f00
chore(meshwide): split code
selankon Jun 2, 2023
445376e
chore(meshwide): fix form modal and toasts
selankon Jun 2, 2023
50283bd
chore(meshwide): add markers sync styles
selankon Jun 6, 2023
3fbc963
chore(meshwide): use query properly
selankon Jun 8, 2023
0aa958c
chore(meshwide): fix link lines styles
selankon Jun 8, 2023
1037af7
chore(meshwide): create shared data hook
selankon Aug 3, 2023
dcc1992
chore(meshwide): write mesh wide links mocks
selankon Aug 7, 2023
842ae61
chore(meshwide): refactor with state reference queries
selankon Aug 7, 2023
e261866
chore(meshwide): show links on map
selankon Aug 8, 2023
fb8f15f
chore(meshwide): refactor to have a point to point with multiple links
selankon Aug 9, 2023
756d2ea
chore(meshwide): fix selected feature
selankon Aug 9, 2023
b97516f
chore(meshwide): pass reference state links
selankon Aug 10, 2023
03d784a
chore(meshwide): fix merge geo and links algorithm
selankon Aug 10, 2023
ad9823f
chore(meshwide): test mergeLinksAndCoordinates
selankon Aug 28, 2023
baba8b3
chore(meshwide): create LinkDetail object
selankon Aug 29, 2023
cbb01fe
chore(meshwide): implement multiple links between points
selankon Aug 30, 2023
b3e2f68
chore(meshwide): refactor component folders
selankon Aug 30, 2023
52f2a92
chore(meshwide): show specific link point data
selankon Aug 30, 2023
b2a53f1
chore(meshwide): split NodesLayer on sepparated folder
selankon Aug 31, 2023
830b13d
chore(meshwide): share actual and reference state on selected feature
selankon Sep 4, 2023
ec4a185
chore(meshwide): implement wifi links errors
selankon Sep 4, 2023
d9ce6a8
chore(meshwide): improve mocks
selankon Sep 5, 2023
bf4059f
chore(meshwide): show link errors on map
selankon Sep 5, 2023
7cc0941
chore(meshwide): move located links into a hook
selankon Sep 5, 2023
f90df70
chore(meshwide): store errors on a hook
selankon Sep 5, 2023
ea2265c
chore(meshwide): split icons
selankon Sep 6, 2023
0015dd1
chore(meshwide): show errors on feature detail
selankon Sep 6, 2023
98bfc33
chore(meshwide): fix node interface
selankon Sep 8, 2023
9bcdb06
chore(meshwide): implement node erros
selankon Sep 8, 2023
0f60b9f
chore(meshwide): show node detail errors
selankon Sep 13, 2023
2cef8a0
chore(meshwide): im[plement missing macs without missing nodes
selankon Sep 13, 2023
fe11c89
chore(meshwide): implement show missing macs
selankon Sep 14, 2023
3260d22
chore(meshwide): fix errors visualization
selankon Sep 14, 2023
47f8938
chore(meshwide): clean nodes that are not geolocated
selankon Sep 14, 2023
97ea07f
chore(meshwide): implement invalid nodes list
selankon Sep 15, 2023
7017e1c
chore(meshwide): implement invalid nodes alert
selankon Sep 15, 2023
e673a48
chore(meshwide): implement feature bottom sheet tests
selankon Sep 27, 2023
663aa66
chore(meshwide): link selected feature with type string
selankon Sep 27, 2023
3a8d0c5
chore(meshwide): implement layers control
selankon Sep 28, 2023
b201e90
chore(meshwide): implement generic link functions
selankon Sep 28, 2023
7901537
chore(meshwide): implement batman errors
selankon Oct 4, 2023
083a70a
chore(meshwide): implement batman links visualization
selankon Oct 5, 2023
045fbba
chore(meshwide): fix mocks
selankon Oct 5, 2023
9d457e1
chore(meshwide): add tests
selankon Oct 16, 2023
c9b6239
chore(meshwide): fix test regression
selankon Dec 12, 2023
26ea467
chore(meshwide): fix rebase
selankon Mar 26, 2024
9b6f7a8
chore(meshwide): handle error
selankon Mar 26, 2024
fa748cb
chore(meshwide): create mesh wide query keys
selankon Mar 26, 2024
da51d5a
chore(meshwide): fix rebase
selankon Apr 3, 2024
34d8a9c
chore(meshwide): fix alert position
selankon Apr 3, 2024
193fbe2
chore(meshwide): fix center map
selankon Apr 3, 2024
d23de4c
chore(meshwide): fix floating alert
selankon Apr 4, 2024
c82f595
chore(meshwide): prevent empty shared state
selankon Apr 4, 2024
383b4ac
chore(meshwide): fix leaflet load
selankon Apr 4, 2024
ee610c1
chore(meshwide): implement check query errors by timer
selankon Apr 5, 2024
273aa77
chore(meshwide): implement meshWide errors show
selankon Apr 5, 2024
ce1e341
chore(meshwide): disable nodes_and_links keys
selankon Apr 5, 2024
67dfbf3
chore(meshwide): refactor to new schema type
selankon Apr 5, 2024
99cc4d4
chore(meshwide): hide error
selankon Apr 5, 2024
4f8c857
chore(meshwide): prevent empty reference state
selankon Apr 5, 2024
3ba117a
chore(meshwide): fix lint
selankon Apr 5, 2024
9ed8abb
chore(meshwide): use the new mesh wide response type
selankon Apr 9, 2024
24fede7
chore(meshwide): implement close feature
selankon Apr 9, 2024
201c1c2
chore(meshwide): fix types
selankon Apr 9, 2024
3bc18d0
chore(meshwide): fix reference state errors
selankon Apr 10, 2024
37a2485
chore(meshwide): fix typo
selankon Apr 10, 2024
39b5cca
chore(meshwide): fix show batman
selankon Apr 11, 2024
7563722
chore(meshwide): implement set reference state button
selankon Apr 11, 2024
6bb10eb
chore(meshwide): prevent undefined errors
selankon Apr 11, 2024
9c307c4
chore(meshwide): show reference is not set on feature detail
selankon Apr 12, 2024
cf2a9d7
chore(meshwide): refactor query names
selankon Apr 12, 2024
71bffec
chore(meshwide): refactor keynames
selankon Apr 16, 2024
ee6dc4a
chore(meshupgrade): add isLoading no modal
selankon Mar 6, 2024
9ae97d7
chore(meshupgrade): create is disabled button
selankon Mar 6, 2024
a2f1134
chore(meshupgrade): fix modal callbacks
selankon Mar 6, 2024
9d3a46b
chore(meshwide): fix modal isLoading
selankon Apr 17, 2024
c72c12e
chore(meshwide): implement set reference state
selankon Apr 17, 2024
9f72976
chore(meshwide): refactor function name
selankon Apr 18, 2024
afa3e2d
chore(meshwide): implement new nodes visualization
selankon Apr 23, 2024
1bb3c9f
chore(meshwide): Prevent undefined link destination nodes
selankon Apr 25, 2024
c224da4
chore(meshwide): disable power button and floating button
selankon Apr 25, 2024
596d137
chore(meshwide): fix some todos
selankon Apr 26, 2024
8d1a0fd
chore(meshwide): add refetch interval
selankon May 5, 2024
884ffc1
chore(meshwide): implement provider
selankon May 6, 2024
7f43ba6
chore(meshwide): implement different providers by link type
selankon May 6, 2024
1ae9585
chore(meshwide): multiple fixes
selankon May 7, 2024
5c5e5d3
chore(meshwide): fix menu names and icons
selankon May 7, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/* eslint @typescript-eslint/no-var-requires: "off" */
const preactPreset = require("jest-preset-preact");

const esModules = ["@react-leaflet", "react-leaflet"].join("|");

/** @returns {Promise<import('jest').Config>} */
module.exports = {
preset: "jest-preset-preact",
Expand All @@ -22,4 +24,5 @@ module.exports = {
"^.+\\.[tj]sx?$": "babel-jest",
},
clearMocks: true,
transformIgnorePatterns: [`/node_modules/(?!${esModules})`],
};
7,978 changes: 6,273 additions & 1,705 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,12 @@
"react-leaflet": "^4.2.1",
"react-redux": "^8.0.4",
"react-router-redux": "^4.0.8",
"react-spring": "^9.7.1",
"react-use": "^17.4.0",
"redux": "^4.2.0",
"redux-observable": "^2.0.0",
"simple-color-scale": "^1.0.1",
"tailwindcss": "^3.2.6",
"timeago.js": "^4.0.2"
},
"husky": {
Expand Down
Empty file modified plugins/lime-plugin-locate/index.ts
100755 → 100644
Empty file.
6 changes: 3 additions & 3 deletions plugins/lime-plugin-locate/src/locateMenu.js
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>
);
10 changes: 10 additions & 0 deletions plugins/lime-plugin-mesh-wide/index.ts
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 plugins/lime-plugin-mesh-wide/src/components/Components.tsx
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>
);
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;
Loading
Loading