diff --git a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx
index 7436f2eb..bbf3d051 100644
--- a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx
+++ b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/LinkDetail.tsx
@@ -1,17 +1,20 @@
import { Trans } from "@lingui/macro";
import { useState } from "preact/hooks";
+import { useCallback } from "react";
import { Warning } from "components/icons/status";
import Tabs from "components/tabs";
+import { useToast } from "components/toast/toastProvider";
import { StatusAndButton } from "plugins/lime-plugin-mesh-wide/src/components/Components";
-import { useSetReferenceState } from "plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/SetReferenceStateBtn";
+import { useSetLinkReferenceStateModal } from "plugins/lime-plugin-mesh-wide/src/components/configPage/modals";
import {
getQueryByLinkType,
usePointToPointErrors,
} from "plugins/lime-plugin-mesh-wide/src/hooks/useLocatedLinks";
import { MacToMacLink } from "plugins/lime-plugin-mesh-wide/src/lib/links/PointToPointLink";
import { readableBytes } from "plugins/lime-plugin-mesh-wide/src/lib/utils";
+import { useSetLinkReferenceState } from "plugins/lime-plugin-mesh-wide/src/meshWideQueries";
import {
BaseMacToMacLink,
BatmanLinkErrorCodes,
@@ -221,6 +224,8 @@ export const LinkReferenceStatus = ({ reference }: LinkMapFeature) => {
type: reference.type,
});
+ const isDown = !errors.linkUp;
+
// Check if there are errors of global reference state to shown
const { reference: fetchDataReference } = getQueryByLinkType(
reference.type
@@ -232,8 +237,63 @@ export const LinkReferenceStatus = ({ reference }: LinkMapFeature) => {
referenceError = true;
}
+ const { toggleModal, confirmModal, isModalOpen } =
+ useSetLinkReferenceStateModal();
+ const { showToast } = useToast();
+
// Mutation to update the reference state
- const { mutate, btnText } = useSetReferenceState(reference.type);
+ const nodesToUpdate = reference.nodes.reduce((acc, node) => {
+ acc[node.ipv4] = node.hostname;
+ return acc;
+ }, {});
+ const { callMutations } = useSetLinkReferenceState({
+ linkType: reference.type,
+ linkToUpdate: reference,
+ isDown,
+ nodesToUpdate,
+ params: {
+ onSuccess: () => {
+ showToast({
+ text: New reference state set!,
+ });
+ },
+ onError: () => {
+ showToast({
+ text: Error setting new reference state!,
+ });
+ },
+ onSettled: () => {
+ if (isModalOpen) toggleModal();
+ },
+ },
+ });
+
+ const setReferenceState = useCallback(async () => {
+ confirmModal(
+ reference.type,
+ Object.values(nodesToUpdate),
+ isDown,
+ async () => {
+ await callMutations();
+ }
+ );
+ }, [callMutations, confirmModal, isDown, nodesToUpdate, reference.type]);
+
+ let btnText = (
+
+ Set reference state for this
+
{reference.type} link
+
+ );
+ if (isDown) {
+ btnText = (
+
+ Delete this {reference.type} link
+
+ from reference state
+
+ );
+ }
let errorMessage = Same status as in the reference state;
if (referenceError) {
@@ -252,7 +312,7 @@ export const LinkReferenceStatus = ({ reference }: LinkMapFeature) => {
{errorMessage}
diff --git a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx
index 0357bc4f..d7ddde77 100644
--- a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx
+++ b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx
@@ -1,16 +1,22 @@
import { Trans } from "@lingui/macro";
+import { useCallback } from "react";
+
+import { useToast } from "components/toast/toastProvider";
import { StatusAndButton } from "plugins/lime-plugin-mesh-wide/src/components/Components";
import RemoteRebootBtn from "plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/RebootNodeBtn";
-import { useSetReferenceState } from "plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/SetReferenceStateBtn";
import UpdateNodeInfoBtn from "plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/UpdateNodeInfoBtn";
import {
Row,
TitleAndText,
} from "plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/index";
+import { useSetNoeInfoReferenceStateModal } from "plugins/lime-plugin-mesh-wide/src/components/configPage/modals";
import { useSingleNodeErrors } from "plugins/lime-plugin-mesh-wide/src/hooks/useSingleNodeErrors";
import { getArrayDifference } from "plugins/lime-plugin-mesh-wide/src/lib/utils";
-import { useMeshWideNodesReference } from "plugins/lime-plugin-mesh-wide/src/meshWideQueries";
+import {
+ useMeshWideNodesReference,
+ useSetNodeInfoReferenceState,
+} from "plugins/lime-plugin-mesh-wide/src/meshWideQueries";
import {
NodeErrorCodes,
NodeMapFeature,
@@ -111,12 +117,49 @@ export const NodeReferenceStatus = ({ actual, reference }: NodeMapFeature) => {
reference,
});
+ const hostname = isDown ? reference.hostname : actual.hostname;
+ const ip = isDown ? reference.ipv4 : actual.ipv4;
+
// Check if there are errors of global reference state to shown
const { data: meshWideNodesReference, isError: isReferenceError } =
useMeshWideNodesReference({});
+ const { toggleModal, confirmModal, isModalOpen } =
+ useSetNoeInfoReferenceStateModal();
+ const { showToast } = useToast();
+
// Mutation to update the reference state
- const { mutate, btnText } = useSetReferenceState("node_info");
+ const { mutateAsync } = useSetNodeInfoReferenceState({
+ ip,
+ hostname,
+ isDown,
+ params: {
+ onSuccess: () => {
+ showToast({
+ text: New reference state set!,
+ });
+ },
+ onError: () => {
+ showToast({
+ text: Error setting new reference state!,
+ });
+ },
+ onSettled: () => {
+ if (isModalOpen) toggleModal();
+ },
+ },
+ });
+
+ const setReferenceState = useCallback(async () => {
+ confirmModal(hostname, isDown, async () => {
+ await mutateAsync();
+ });
+ }, [confirmModal, hostname, isDown, mutateAsync]);
+
+ let btnText = Set reference state for this node;
+ if (isDown) {
+ btnText = Delete this this node from reference state;
+ }
let referenceError = false;
if (
@@ -144,7 +187,7 @@ export const NodeReferenceStatus = ({ actual, reference }: NodeMapFeature) => {
{errorMessage}
diff --git a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/SetReferenceStateBtn.tsx b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/SetReferenceStateBtn.tsx
deleted file mode 100644
index fda44759..00000000
--- a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/SetReferenceStateBtn.tsx
+++ /dev/null
@@ -1,69 +0,0 @@
-import { Trans } from "@lingui/macro";
-import { useCallback } from "react";
-
-import { useToast } from "components/toast/toastProvider";
-
-import { useSetReferenceStateModal } from "plugins/lime-plugin-mesh-wide/src/components/configPage/modals";
-import {
- useSetBatmanLinksInfoReferenceState,
- useSetNodeInfoReferenceState,
- useSetWifiLinksInfoReferenceState,
-} from "plugins/lime-plugin-mesh-wide/src/meshWideQueries";
-import { DataTypes } from "plugins/lime-plugin-mesh-wide/src/meshWideTypes";
-
-const toastDuration = 5000;
-
-export const useSetReferenceState = (dataType: T) => {
- const { toggleModal, confirmModal, isModalOpen } =
- useSetReferenceStateModal();
- const { showToast } = useToast();
-
- const mutationOpts = {
- onSuccess: () => {
- showToast({
- text: New reference state set!,
- duration: toastDuration,
- });
- },
- onError: () => {
- showToast({
- text: Error setting new reference state!,
- duration: toastDuration,
- });
- },
- onSettled: () => {
- if (isModalOpen) toggleModal();
- },
- };
-
- const { mutateAsync: nodesMutation } =
- useSetNodeInfoReferenceState(mutationOpts);
- const { mutateAsync: wifiMutation } =
- useSetWifiLinksInfoReferenceState(mutationOpts);
- const { mutateAsync: batmanMutation } =
- useSetBatmanLinksInfoReferenceState(mutationOpts);
-
- const btnText = Set {dataType} reference state;
-
- const mutate = useCallback(async () => {
- switch (dataType) {
- case "node_info":
- await confirmModal(dataType, async () => {
- await nodesMutation();
- });
- break;
- case "wifi_links_info":
- confirmModal(dataType, async () => {
- await wifiMutation();
- });
- break;
- case "bat_links_info":
- confirmModal(dataType, async () => {
- await batmanMutation();
- });
- break;
- }
- }, [batmanMutation, confirmModal, dataType, nodesMutation, wifiMutation]);
-
- return { mutate, btnText };
-};
diff --git a/plugins/lime-plugin-mesh-wide/src/components/configPage/modals.tsx b/plugins/lime-plugin-mesh-wide/src/components/configPage/modals.tsx
index e0f2f40b..c4ce68c7 100644
--- a/plugins/lime-plugin-mesh-wide/src/components/configPage/modals.tsx
+++ b/plugins/lime-plugin-mesh-wide/src/components/configPage/modals.tsx
@@ -85,18 +85,77 @@ export const useAddNewSectionModal = () => {
return { actionModal, toggleModal };
};
-export const useSetReferenceStateModal = () => {
+export const useSetNoeInfoReferenceStateModal = () => {
const { toggleModal, setModalState, isModalOpen } = useModal();
const confirmModal = useCallback(
- (dataType: DataTypes, cb: () => Promise) => {
+ (nodeName: string, isDown: boolean, cb: () => Promise) => {
+ let title = Set reference state for {nodeName};
+ let content = Set the reference state for this node.;
+ if (isDown) {
+ title = (
+ Remove {nodeName} from the reference state
+ );
+ content = (
+
+ This node seems down, remove them from the reference
+ state?
+
+ );
+ }
setModalState({
- title: Set reference state for {dataType},
- content: (
+ title,
+ content,
+ successCb: cb,
+ successBtnText: Continue,
+ });
+ toggleModal();
+ },
+ [setModalState, toggleModal]
+ );
+ return { confirmModal, toggleModal, isModalOpen };
+};
+
+export const useSetLinkReferenceStateModal = () => {
+ const { toggleModal, setModalState, isModalOpen } = useModal();
+
+ const confirmModal = useCallback(
+ (
+ dataType: DataTypes,
+ nodes: string[],
+ isDown: boolean,
+ cb: () => Promise
+ ) => {
+ let title = (
+ Set reference state for this {dataType} link?
+ );
+ let content = (
+ This will set the reference state of this link:
+ );
+ if (isDown) {
+ title = (
+
+ Remove this {dataType} from the reference state
+
+ );
+ content = (
- Are you sure you want to set this reference state for{" "}
- {dataType}
+ This link seems down, remove them from the reference
+ state?
+ );
+ }
+ setModalState({
+ title,
+ content: (
+
+ {content}
+
+
+
{nodes[0]}
+
{nodes[1]}
+
+
),
successCb: cb,
successBtnText: Continue,
diff --git a/plugins/lime-plugin-mesh-wide/src/hooks/useLocatedLinks.tsx b/plugins/lime-plugin-mesh-wide/src/hooks/useLocatedLinks.tsx
index 4be5cb17..12894ec9 100644
--- a/plugins/lime-plugin-mesh-wide/src/hooks/useLocatedLinks.tsx
+++ b/plugins/lime-plugin-mesh-wide/src/hooks/useLocatedLinks.tsx
@@ -35,16 +35,19 @@ interface getQueryByLinkTypeReturnType {
export const getQueryByLinkType = (
type: T
): getQueryByLinkTypeReturnType => {
- if (type === "bat_links_info") {
- return {
- state: useMeshWideBatman,
- reference: useMeshWideBatmanReference,
- } as getQueryByLinkTypeReturnType;
+ switch (type) {
+ case "bat_links_info":
+ return {
+ state: useMeshWideBatman,
+ reference: useMeshWideBatmanReference,
+ } as getQueryByLinkTypeReturnType;
+ case "wifi_links_info":
+ default:
+ return {
+ state: useMeshWideLinks,
+ reference: useMeshWideLinksReference,
+ } as getQueryByLinkTypeReturnType;
}
- return {
- state: useMeshWideLinks,
- reference: useMeshWideLinksReference,
- } as getQueryByLinkTypeReturnType;
};
interface IUselocatedLinks {
diff --git a/plugins/lime-plugin-mesh-wide/src/lib/links/PointToPointLink.ts b/plugins/lime-plugin-mesh-wide/src/lib/links/PointToPointLink.ts
index 067c458f..dae62fd9 100644
--- a/plugins/lime-plugin-mesh-wide/src/lib/links/PointToPointLink.ts
+++ b/plugins/lime-plugin-mesh-wide/src/lib/links/PointToPointLink.ts
@@ -2,6 +2,7 @@ import {
BaseMacToMacLink,
Coordinates,
ILocatedLink,
+ INodeInfo,
LinkDataTypes,
LinkType,
MacToMacLinkId,
@@ -15,11 +16,15 @@ import {
*/
export class PontToPointLink {
private _links: BaseMacToMacLink[] = [];
+ private _nodes: INodeInfo[] = [];
public readonly id: PointToPointLinkId;
public readonly coordinates: Coordinates[] = [];
- constructor(coord1: Coordinates, coord2: Coordinates) {
+ constructor(node1: INodeInfo, node2: INodeInfo) {
+ const coord1 = node1.coordinates;
+ const coord2 = node2.coordinates;
this.id = PontToPointLink.generateId(coord1, coord2);
+ this.nodes.push(node1, node2);
this.coordinates.push(coord1, coord2);
}
@@ -50,19 +55,14 @@ export class PontToPointLink {
return false;
}
- get names(): string[] {
- return [
- ...this._links.reduce((acc, link) => {
- Object.keys(link).forEach((key) => acc.add(key));
- return acc;
- }, new Set()),
- ] as string[];
- }
-
get links() {
return this._links;
}
+ get nodes() {
+ return this._nodes;
+ }
+
/**
* Generate a deterministic unique id based on the coordinates of a node.
* @param coord1
diff --git a/plugins/lime-plugin-mesh-wide/src/lib/links/getLinksCoordinates.ts b/plugins/lime-plugin-mesh-wide/src/lib/links/getLinksCoordinates.ts
index e620c716..8736f9ec 100644
--- a/plugins/lime-plugin-mesh-wide/src/lib/links/getLinksCoordinates.ts
+++ b/plugins/lime-plugin-mesh-wide/src/lib/links/getLinksCoordinates.ts
@@ -55,8 +55,8 @@ export const mergeLinksAndCoordinates = (
// If this point to point link no exists, instantiate it
if (!result[linkKey]) {
result[linkKey] = new PontToPointLink(
- nodes[linkNodeName].coordinates,
- nodes[dstNodeName!].coordinates
+ nodes[linkNodeName],
+ nodes[dstNodeName]
);
}
// If the link PontToPointLink already exists and the link is already added, ignore it
diff --git a/plugins/lime-plugin-mesh-wide/src/meshWideQueries.tsx b/plugins/lime-plugin-mesh-wide/src/meshWideQueries.tsx
index aa86658a..9c8ddc3a 100644
--- a/plugins/lime-plugin-mesh-wide/src/meshWideQueries.tsx
+++ b/plugins/lime-plugin-mesh-wide/src/meshWideQueries.tsx
@@ -1,5 +1,8 @@
import { useMutation, useQuery } from "@tanstack/react-query";
+import { meshUpgradeQueryKeys } from "plugins/lime-plugin-mesh-wide-upgrade/src/meshUpgradeQueriesKeys";
+import { getQueryByLinkType } from "plugins/lime-plugin-mesh-wide/src/hooks/useLocatedLinks";
+import { PontToPointLink } from "plugins/lime-plugin-mesh-wide/src/lib/links/PointToPointLink";
import {
doSharedStateApiCall,
syncAllDataTypes,
@@ -15,9 +18,11 @@ import {
IMeshWideConfig,
INodes,
IWifiLinks,
+ LinkType,
SelectedMapFeature,
} from "plugins/lime-plugin-mesh-wide/src/meshWideTypes";
+import { useMeshWideSyncCall } from "utils/meshWideSyncCall";
import { useSharedData } from "utils/useSharedData";
const refetchInterval = 60000;
@@ -110,21 +115,28 @@ export function useMeshWideNodes(params) {
* to unify criterias and add a confirmation modal
*/
-interface IShatedStateRemoteQueryProps {
+interface ISharedStateRemoteQueryProps {
ip: string;
- hostname?: string;
params?: any;
}
+type ISharedStateSetReferenceQueryProps = {
+ isDown: boolean;
+ hostname?: string;
+} & ISharedStateRemoteQueryProps;
+
export const useSetNodeInfoReferenceState = ({
ip,
hostname,
+ isDown,
params,
-}: IShatedStateRemoteQueryProps) => {
+}: ISharedStateSetReferenceQueryProps) => {
const type = "node_info";
const { data } = useMeshWideNodes({});
+ // Ignore the types here because it to delete a node you have to pass an empty object
+ // @ts-ignore
const queryKey = getFromSharedStateKeys.insertIntoReferenceState(type, {
- [hostname]: data[hostname],
+ [hostname]: isDown ? null : data[hostname],
});
return useMutation(
queryKey,
@@ -135,42 +147,50 @@ export const useSetNodeInfoReferenceState = ({
);
};
-export const useSetWifiLinksInfoReferenceState = ({
- ip,
- hostname,
- params,
-}: IShatedStateRemoteQueryProps) => {
- const type = "wifi_links_info";
- const { data } = useMeshWideLinks({});
- const queryKey = getFromSharedStateKeys.insertIntoReferenceState(type, {
- [hostname]: data[hostname],
- });
- return useMutation(
- queryKey,
- () => doSharedStateApiCall(queryKey, ip),
- {
- ...params,
- }
- );
-};
+interface IUseSetLinkReferenceState {
+ linkType: LinkType;
+ linkToUpdate: PontToPointLink;
+ nodesToUpdate: { [ip: string]: string }; // { ip: hostname }
+ params: any;
+ isDown: boolean;
+}
-export const useSetBatmanLinksInfoReferenceState = ({
- ip,
- hostname,
+export const useSetLinkReferenceState = ({
+ linkType,
+ linkToUpdate,
+ isDown,
+ nodesToUpdate,
params,
-}: IShatedStateRemoteQueryProps) => {
- const type = "bat_links_info";
- const { data } = useMeshWideBatman({});
- const queryKey = getFromSharedStateKeys.insertIntoReferenceState(type, {
- [hostname]: data[hostname],
+}: IUseSetLinkReferenceState) => {
+ const { state, reference } = getQueryByLinkType(linkType);
+ const { data } = state({});
+ const { data: referenceData } = reference({});
+
+ return useMeshWideSyncCall({
+ mutationKey: meshUpgradeQueryKeys.remoteConfirmUpgrade(),
+ mutationFn: ({ ip }) => {
+ const hostname = nodesToUpdate[ip];
+ const referenceLinks = referenceData[hostname];
+ for (const mactomac of linkToUpdate.links) {
+ if (isDown) {
+ delete referenceLinks[mactomac.id];
+ continue;
+ }
+ referenceLinks[mactomac.id] = data[hostname][mactomac.id];
+ }
+ const queryKey = getFromSharedStateKeys.insertIntoReferenceState(
+ linkType,
+ // For some reason I have to ignore the types here because it not infers properly.
+ // Using the same code but for a specific link type, it works.
+ // For some reason with the use of getQueryByLinkType it doesn't work.
+ // @ts-ignore
+ { [hostname]: referenceLinks }
+ );
+ return doSharedStateApiCall(queryKey, ip);
+ },
+ ips: Object.keys(nodesToUpdate),
+ options: params,
});
- return useMutation(
- queryKey,
- () => doSharedStateApiCall(queryKey, ip),
- {
- ...params,
- }
- );
};
/**
@@ -179,9 +199,8 @@ export const useSetBatmanLinksInfoReferenceState = ({
export const usePublishOnRemoteNode = ({
ip,
- hostname,
...opts
-}: IShatedStateRemoteQueryProps) => {
+}: ISharedStateRemoteQueryProps) => {
return useMutation({
mutationFn: ({ ip }) =>
doSharedStateApiCall(
@@ -195,11 +214,11 @@ export const usePublishOnRemoteNode = ({
export const useSyncDataTypes = ({
ip,
- ...opts
-}: IShatedStateRemoteQueryProps) => {
+ params,
+}: ISharedStateRemoteQueryProps) => {
return useMutation(syncAllDataTypes, {
mutationKey: [syncFromSharedStateKey, ip],
- ...opts,
+ ...params,
});
};