From abef765aa28d665e7e5efd91a1c4200073214017 Mon Sep 17 00:00:00 2001 From: selankon Date: Fri, 10 May 2024 11:17:57 +0200 Subject: [PATCH 1/7] chore(meshwide): fix floating alert position --- .../src/components/Map/FloatingAlert.tsx | 16 +++++++++------- .../lime-plugin-mesh-wide/src/containers/Map.tsx | 2 -- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/plugins/lime-plugin-mesh-wide/src/components/Map/FloatingAlert.tsx b/plugins/lime-plugin-mesh-wide/src/components/Map/FloatingAlert.tsx index 30600437..33ddb97c 100644 --- a/plugins/lime-plugin-mesh-wide/src/components/Map/FloatingAlert.tsx +++ b/plugins/lime-plugin-mesh-wide/src/components/Map/FloatingAlert.tsx @@ -48,13 +48,15 @@ export const FloatingAlert = () => { ]); return hasErrors ? ( -
-
- +
+
+
+ +
) : null; diff --git a/plugins/lime-plugin-mesh-wide/src/containers/Map.tsx b/plugins/lime-plugin-mesh-wide/src/containers/Map.tsx index d261ed68..3b14986a 100644 --- a/plugins/lime-plugin-mesh-wide/src/containers/Map.tsx +++ b/plugins/lime-plugin-mesh-wide/src/containers/Map.tsx @@ -12,7 +12,6 @@ import { useLoadLeaflet, useLocation, } from "plugins/lime-plugin-locate/src/locateQueries"; -import { FloatingAlert } from "plugins/lime-plugin-mesh-wide/src/components/Map/FloatingAlert"; import { BatmanLinksLayer, WifiLinksLayer, @@ -89,7 +88,6 @@ export const MeshWideMap = ({ attribution={openStreetMapAttribution} url={openStreetMapTileString} /> - From 067276fa3eb46851e3a6f88b76d5caed78703453 Mon Sep 17 00:00:00 2001 From: selankon Date: Fri, 10 May 2024 13:29:03 +0200 Subject: [PATCH 2/7] chore(meshwide): dinamically add supported layers --- .../src/containers/Map.tsx | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/plugins/lime-plugin-mesh-wide/src/containers/Map.tsx b/plugins/lime-plugin-mesh-wide/src/containers/Map.tsx index 3b14986a..b4d9f190 100644 --- a/plugins/lime-plugin-mesh-wide/src/containers/Map.tsx +++ b/plugins/lime-plugin-mesh-wide/src/containers/Map.tsx @@ -1,5 +1,5 @@ -import { t } from "@lingui/macro"; import L from "leaflet"; +import { ComponentChildren } from "preact"; import { useEffect, useRef } from "preact/hooks"; import { LayerGroup, @@ -18,6 +18,7 @@ import { } from "plugins/lime-plugin-mesh-wide/src/containers/MapLayers/LinksLayers"; import NodesLayer from "plugins/lime-plugin-mesh-wide/src/containers/MapLayers/NodesLayer"; import { useSelectedMapFeature } from "plugins/lime-plugin-mesh-wide/src/meshWideQueries"; +import { DataTypes } from "plugins/lime-plugin-mesh-wide/src/meshWideTypes"; const openStreetMapTileString = "https://{s}.tile.osm.org/{z}/{x}/{y}.png"; const openStreetMapAttribution = @@ -76,6 +77,15 @@ export const MeshWideMap = ({ } }, [loading, nodeLocation]); + const mapSupportedLayers: Record< + DataTypes, + { name: string; layer: ComponentChildren } + > = { + node_info: { name: "Nodes", layer: }, + wifi_links_info: { name: "Wifi Links", layer: }, + bat_links_info: { name: "Batman", layer: }, + }; + return ( - - - - - - - - - - - - - - - + {Object.values(mapSupportedLayers).map(({ name, layer }, k) => ( + + {layer} + + ))} ); From 9329905f310d88351c638678257a37fa5a8adde2 Mon Sep 17 00:00:00 2001 From: selankon Date: Fri, 10 May 2024 14:37:08 +0200 Subject: [PATCH 3/7] chore(meshwide): implement button to refresh nodes --- .../components/FeatureDetail/NodeDetail.tsx | 6 +- .../FeatureDetail/UpdateNodeInfoBtn.tsx | 134 ++++++++++++++++++ .../src/meshWideQueriesKeys.tsx | 5 + .../src/meshWideTypes.tsx | 7 + src/components/icons/teenny/refresh.jsx | 16 +++ 5 files changed, 167 insertions(+), 1 deletion(-) create mode 100644 plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/UpdateNodeInfoBtn.tsx create mode 100644 src/components/icons/teenny/refresh.jsx 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 0d81296f..06596cf9 100644 --- a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx +++ b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/NodeDetail.tsx @@ -3,6 +3,7 @@ import { Trans } from "@lingui/macro"; 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, @@ -40,7 +41,10 @@ const NodeDetails = ({ actual, reference, name }: NodeMapFeature) => {
{name}
- +
+ + +
{!isDown ? ( diff --git a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/UpdateNodeInfoBtn.tsx b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/UpdateNodeInfoBtn.tsx new file mode 100644 index 00000000..3baf32e7 --- /dev/null +++ b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/UpdateNodeInfoBtn.tsx @@ -0,0 +1,134 @@ +import { Trans } from "@lingui/macro"; +import { useMutation } from "@tanstack/react-query"; +import { useCallback } from "react"; + +import { Button } from "components/buttons/button"; +import { RefreshIcon } from "components/icons/teenny/refresh"; +import { useToast } from "components/toast/toastProvider"; + +import { callToRemoteNode } from "plugins/lime-plugin-mesh-wide-upgrade/src/utils/api"; +import { doSharedStateApiCall } from "plugins/lime-plugin-mesh-wide/src/meshWideApi"; +import { + getFromSharedStateKeys, + syncFromSharedStateAsyncKey, +} from "plugins/lime-plugin-mesh-wide/src/meshWideQueriesKeys"; +import { + DataTypes, + INodeInfo, + completeDataTypeKeys, +} from "plugins/lime-plugin-mesh-wide/src/meshWideTypes"; + +import queryCache from "utils/queryCache"; + +interface IRemoteRebotProps { + ip: string; +} + +export async function publishOnRemoteNode({ ip }: IRemoteRebotProps) { + return await callToRemoteNode({ + ip, + apiCall: (customApi) => + customApi + .call("shared-state-async", "publish_all", {}) + .then(() => true), + }); +} + +export async function syncDataType({ + dataType, + ip, +}: { + dataType: DataTypes; + ip: string; +}) { + const queryKey = getFromSharedStateKeys.syncFromSharedStateAsync( + dataType, + ip + ); + return doSharedStateApiCall(queryKey); +} + +export async function syncAllDataTypes({ ip }: { ip: string }) { + const promises = (Object.keys(completeDataTypeKeys) as DataTypes[]).map( + (dataType) => syncDataType({ dataType, ip }) + ); + return await Promise.all(promises); +} + +const useSyncDataTypes = ({ ip, ...opts }: { ip: string; opts?: any }) => { + return useMutation((props: IRemoteRebotProps) => syncAllDataTypes({ ip }), { + mutationKey: [syncFromSharedStateAsyncKey, ip], + ...opts, + }); +}; + +const usePublishOnRemoteNode = ({ + ip, + ...opts +}: { + ip: string; + opts?: any; +}) => { + return useMutation( + (props: IRemoteRebotProps) => publishOnRemoteNode({ ip }), + { + mutationKey: [syncFromSharedStateAsyncKey, ip], + ...opts, + } + ); +}; + +const UpdateNodeInfoBtn = ({ node }: { node: INodeInfo }) => { + const ip = node.ipv4; + + const { showToast } = useToast(); + const { mutateAsync: localNodeSync } = useSyncDataTypes({ + ip, + }); + const { mutateAsync: publishOnRemoteNode } = usePublishOnRemoteNode({ + ip, + }); + + const invalidateQueries = useCallback(() => { + for (const dataType of Object.keys( + completeDataTypeKeys + ) as DataTypes[]) { + queryCache.invalidateQueries({ + queryKey: + getFromSharedStateKeys.getFromSharedStateAsync(dataType), + }); + } + }, []); + + // useCallback to sync the node data + const syncNode = useCallback(async () => { + try { + await localNodeSync({ ip }); + } catch (e) { + showToast({ + text: ( + + Error connecting with {node.hostname}, is node up? + + ), + }); + } + await publishOnRemoteNode({ ip }); + await invalidateQueries(); + }, [ + invalidateQueries, + ip, + localNodeSync, + node.hostname, + publishOnRemoteNode, + showToast, + ]); + + return ( + + ); +}; + +export default UpdateNodeInfoBtn; diff --git a/plugins/lime-plugin-mesh-wide/src/meshWideQueriesKeys.tsx b/plugins/lime-plugin-mesh-wide/src/meshWideQueriesKeys.tsx index 237afe23..c37d74f1 100644 --- a/plugins/lime-plugin-mesh-wide/src/meshWideQueriesKeys.tsx +++ b/plugins/lime-plugin-mesh-wide/src/meshWideQueriesKeys.tsx @@ -8,6 +8,7 @@ export const getFromSharedStateMultiWriterKey = [ "getFromSharedStateMultiWriter", ]; export const getFromSharedStateAsyncKey = ["shared-state-async", "get"]; +export const syncFromSharedStateAsyncKey = ["shared-state-async", "sync"]; export const insertIntoSharedStateKey = [ "shared-state", @@ -19,6 +20,10 @@ export const getFromSharedStateKeys = { ...getFromSharedStateAsyncKey, { data_type: dataType }, ], + syncFromSharedStateAsync: ( + dataType: T, + ip: string + ) => [...syncFromSharedStateAsyncKey, { data_type: dataType, ip }], getFromSharedStateMultiWriter: (dataType: DataTypes) => [ ...getFromSharedStateMultiWriterKey, { data_type: dataType }, diff --git a/plugins/lime-plugin-mesh-wide/src/meshWideTypes.tsx b/plugins/lime-plugin-mesh-wide/src/meshWideTypes.tsx index a73fcd17..014bb795 100644 --- a/plugins/lime-plugin-mesh-wide/src/meshWideTypes.tsx +++ b/plugins/lime-plugin-mesh-wide/src/meshWideTypes.tsx @@ -198,3 +198,10 @@ export type SharedStateReturnType = { data: T; error: number; }; +// Util in order to iterate over the keys of the DataTypeMap +export type CompleteDataTypeKeys = { [K in DataTypes]: true }; +export const completeDataTypeKeys: CompleteDataTypeKeys = { + node_info: true, + wifi_links_info: true, + bat_links_info: true, +}; diff --git a/src/components/icons/teenny/refresh.jsx b/src/components/icons/teenny/refresh.jsx new file mode 100644 index 00000000..2b443694 --- /dev/null +++ b/src/components/icons/teenny/refresh.jsx @@ -0,0 +1,16 @@ +export const RefreshIcon = () => { + return ( + + + + ); +}; From aaedbff241f7fa63e99aa4c2896ce04a3aa18577 Mon Sep 17 00:00:00 2001 From: selankon Date: Fri, 10 May 2024 16:28:34 +0200 Subject: [PATCH 4/7] chore(meshwide): fix mutation keys --- .../FeatureDetail/UpdateNodeInfoBtn.tsx | 48 +++++++++---------- .../src/meshWideQueriesKeys.tsx | 8 +++- 2 files changed, 30 insertions(+), 26 deletions(-) diff --git a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/UpdateNodeInfoBtn.tsx b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/UpdateNodeInfoBtn.tsx index 3baf32e7..0e5f8c6b 100644 --- a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/UpdateNodeInfoBtn.tsx +++ b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/UpdateNodeInfoBtn.tsx @@ -10,6 +10,7 @@ import { callToRemoteNode } from "plugins/lime-plugin-mesh-wide-upgrade/src/util import { doSharedStateApiCall } from "plugins/lime-plugin-mesh-wide/src/meshWideApi"; import { getFromSharedStateKeys, + publishAllFromSharedStateAsyncKey, syncFromSharedStateAsyncKey, } from "plugins/lime-plugin-mesh-wide/src/meshWideQueriesKeys"; import { @@ -29,11 +30,24 @@ export async function publishOnRemoteNode({ ip }: IRemoteRebotProps) { ip, apiCall: (customApi) => customApi - .call("shared-state-async", "publish_all", {}) + .call(...publishAllFromSharedStateAsyncKey, {}) .then(() => true), }); } +const usePublishOnRemoteNode = ({ + ip, + ...opts +}: { + ip: string; + opts?: any; +}) => { + return useMutation(publishOnRemoteNode, { + mutationKey: [publishAllFromSharedStateAsyncKey, ip], + ...opts, + }); +}; + export async function syncDataType({ dataType, ip, @@ -41,10 +55,9 @@ export async function syncDataType({ dataType: DataTypes; ip: string; }) { - const queryKey = getFromSharedStateKeys.syncFromSharedStateAsync( - dataType, - ip - ); + const queryKey = getFromSharedStateKeys.syncFromSharedStateAsync(dataType, [ + ip, + ]); return doSharedStateApiCall(queryKey); } @@ -56,28 +69,12 @@ export async function syncAllDataTypes({ ip }: { ip: string }) { } const useSyncDataTypes = ({ ip, ...opts }: { ip: string; opts?: any }) => { - return useMutation((props: IRemoteRebotProps) => syncAllDataTypes({ ip }), { + return useMutation(syncAllDataTypes, { mutationKey: [syncFromSharedStateAsyncKey, ip], ...opts, }); }; -const usePublishOnRemoteNode = ({ - ip, - ...opts -}: { - ip: string; - opts?: any; -}) => { - return useMutation( - (props: IRemoteRebotProps) => publishOnRemoteNode({ ip }), - { - mutationKey: [syncFromSharedStateAsyncKey, ip], - ...opts, - } - ); -}; - const UpdateNodeInfoBtn = ({ node }: { node: INodeInfo }) => { const ip = node.ipv4; @@ -103,7 +100,7 @@ const UpdateNodeInfoBtn = ({ node }: { node: INodeInfo }) => { // useCallback to sync the node data const syncNode = useCallback(async () => { try { - await localNodeSync({ ip }); + await publishOnRemoteNode({ ip }); } catch (e) { showToast({ text: ( @@ -111,9 +108,12 @@ const UpdateNodeInfoBtn = ({ node }: { node: INodeInfo }) => { Error connecting with {node.hostname}, is node up? ), + duration: 5000, }); + console.error(e); } - await publishOnRemoteNode({ ip }); + + await localNodeSync({ ip }); await invalidateQueries(); }, [ invalidateQueries, diff --git a/plugins/lime-plugin-mesh-wide/src/meshWideQueriesKeys.tsx b/plugins/lime-plugin-mesh-wide/src/meshWideQueriesKeys.tsx index c37d74f1..dc8138fc 100644 --- a/plugins/lime-plugin-mesh-wide/src/meshWideQueriesKeys.tsx +++ b/plugins/lime-plugin-mesh-wide/src/meshWideQueriesKeys.tsx @@ -9,6 +9,10 @@ export const getFromSharedStateMultiWriterKey = [ ]; export const getFromSharedStateAsyncKey = ["shared-state-async", "get"]; export const syncFromSharedStateAsyncKey = ["shared-state-async", "sync"]; +export const publishAllFromSharedStateAsyncKey = [ + "shared-state-async", + "publish_all", +]; export const insertIntoSharedStateKey = [ "shared-state", @@ -22,8 +26,8 @@ export const getFromSharedStateKeys = { ], syncFromSharedStateAsync: ( dataType: T, - ip: string - ) => [...syncFromSharedStateAsyncKey, { data_type: dataType, ip }], + peers_ip: string[] + ) => [...syncFromSharedStateAsyncKey, { data_type: dataType, peers_ip }], getFromSharedStateMultiWriter: (dataType: DataTypes) => [ ...getFromSharedStateMultiWriterKey, { data_type: dataType }, From 32a5db57b0bf9fdfbbcb86b1ea2fc89fec2506cb Mon Sep 17 00:00:00 2001 From: selankon Date: Fri, 10 May 2024 16:34:52 +0200 Subject: [PATCH 5/7] chore(meshwide): refactor to correct place --- .../FeatureDetail/UpdateNodeInfoBtn.tsx | 65 ++----------------- .../lime-plugin-mesh-wide/src/meshWideApi.ts | 44 +++++++++++++ .../src/meshWideQueries.tsx | 42 +++++++++++- 3 files changed, 88 insertions(+), 63 deletions(-) diff --git a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/UpdateNodeInfoBtn.tsx b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/UpdateNodeInfoBtn.tsx index 0e5f8c6b..d780ddb9 100644 --- a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/UpdateNodeInfoBtn.tsx +++ b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/UpdateNodeInfoBtn.tsx @@ -1,18 +1,15 @@ import { Trans } from "@lingui/macro"; -import { useMutation } from "@tanstack/react-query"; import { useCallback } from "react"; import { Button } from "components/buttons/button"; import { RefreshIcon } from "components/icons/teenny/refresh"; import { useToast } from "components/toast/toastProvider"; -import { callToRemoteNode } from "plugins/lime-plugin-mesh-wide-upgrade/src/utils/api"; -import { doSharedStateApiCall } from "plugins/lime-plugin-mesh-wide/src/meshWideApi"; import { - getFromSharedStateKeys, - publishAllFromSharedStateAsyncKey, - syncFromSharedStateAsyncKey, -} from "plugins/lime-plugin-mesh-wide/src/meshWideQueriesKeys"; + usePublishOnRemoteNode, + useSyncDataTypes, +} from "plugins/lime-plugin-mesh-wide/src/meshWideQueries"; +import { getFromSharedStateKeys } from "plugins/lime-plugin-mesh-wide/src/meshWideQueriesKeys"; import { DataTypes, INodeInfo, @@ -21,60 +18,6 @@ import { import queryCache from "utils/queryCache"; -interface IRemoteRebotProps { - ip: string; -} - -export async function publishOnRemoteNode({ ip }: IRemoteRebotProps) { - return await callToRemoteNode({ - ip, - apiCall: (customApi) => - customApi - .call(...publishAllFromSharedStateAsyncKey, {}) - .then(() => true), - }); -} - -const usePublishOnRemoteNode = ({ - ip, - ...opts -}: { - ip: string; - opts?: any; -}) => { - return useMutation(publishOnRemoteNode, { - mutationKey: [publishAllFromSharedStateAsyncKey, ip], - ...opts, - }); -}; - -export async function syncDataType({ - dataType, - ip, -}: { - dataType: DataTypes; - ip: string; -}) { - const queryKey = getFromSharedStateKeys.syncFromSharedStateAsync(dataType, [ - ip, - ]); - return doSharedStateApiCall(queryKey); -} - -export async function syncAllDataTypes({ ip }: { ip: string }) { - const promises = (Object.keys(completeDataTypeKeys) as DataTypes[]).map( - (dataType) => syncDataType({ dataType, ip }) - ); - return await Promise.all(promises); -} - -const useSyncDataTypes = ({ ip, ...opts }: { ip: string; opts?: any }) => { - return useMutation(syncAllDataTypes, { - mutationKey: [syncFromSharedStateAsyncKey, ip], - ...opts, - }); -}; - const UpdateNodeInfoBtn = ({ node }: { node: INodeInfo }) => { const ip = node.ipv4; diff --git a/plugins/lime-plugin-mesh-wide/src/meshWideApi.ts b/plugins/lime-plugin-mesh-wide/src/meshWideApi.ts index c8470df9..682de569 100644 --- a/plugins/lime-plugin-mesh-wide/src/meshWideApi.ts +++ b/plugins/lime-plugin-mesh-wide/src/meshWideApi.ts @@ -1,9 +1,15 @@ import { QueryKey } from "@tanstack/react-query"; +import { callToRemoteNode } from "plugins/lime-plugin-mesh-wide-upgrade/src/utils/api"; +import { + getFromSharedStateKeys, + publishAllFromSharedStateAsyncKey, +} from "plugins/lime-plugin-mesh-wide/src/meshWideQueriesKeys"; import { DataTypeMap, DataTypes, SharedStateReturnType, + completeDataTypeKeys, } from "plugins/lime-plugin-mesh-wide/src/meshWideTypes"; import api from "utils/uhttpd.service"; @@ -19,3 +25,41 @@ export const doSharedStateApiCall = async ( } return res.data; }; + +/** + * Sync all data types from shared state from remote node + */ + +interface ISyncWithIpProps { + ip: string; +} + +export async function publishOnRemoteNode({ ip }: ISyncWithIpProps) { + return await callToRemoteNode({ + ip, + apiCall: (customApi) => + customApi + .call(...publishAllFromSharedStateAsyncKey, {}) + .then(() => true), + }); +} + +export async function syncDataType({ + dataType, + ip, +}: { + dataType: DataTypes; + ip: string; +}) { + const queryKey = getFromSharedStateKeys.syncFromSharedStateAsync(dataType, [ + ip, + ]); + return doSharedStateApiCall(queryKey); +} + +export async function syncAllDataTypes({ ip }: { ip: string }) { + const promises = (Object.keys(completeDataTypeKeys) as DataTypes[]).map( + (dataType) => syncDataType({ dataType, ip }) + ); + return await Promise.all(promises); +} diff --git a/plugins/lime-plugin-mesh-wide/src/meshWideQueries.tsx b/plugins/lime-plugin-mesh-wide/src/meshWideQueries.tsx index 50570c3b..f1d57c9a 100644 --- a/plugins/lime-plugin-mesh-wide/src/meshWideQueries.tsx +++ b/plugins/lime-plugin-mesh-wide/src/meshWideQueries.tsx @@ -1,8 +1,16 @@ import { useMutation, useQuery } from "@tanstack/react-query"; -import { doSharedStateApiCall } from "plugins/lime-plugin-mesh-wide/src/meshWideApi"; +import { + doSharedStateApiCall, + publishOnRemoteNode, + syncAllDataTypes, +} from "plugins/lime-plugin-mesh-wide/src/meshWideApi"; import { getMeshWideConfig } from "plugins/lime-plugin-mesh-wide/src/meshWideMocks"; -import { getFromSharedStateKeys } from "plugins/lime-plugin-mesh-wide/src/meshWideQueriesKeys"; +import { + getFromSharedStateKeys, + publishAllFromSharedStateAsyncKey, + syncFromSharedStateAsyncKey, +} from "plugins/lime-plugin-mesh-wide/src/meshWideQueriesKeys"; import { DataTypes, IBatmanLinks, @@ -152,6 +160,36 @@ export const useSetBatmanLinksInfoReferenceState = (params) => { ); }; +/** + * Sync all data types from shared state from remote node + * */ + +export const usePublishOnRemoteNode = ({ + ip, + ...opts +}: { + ip: string; + opts?: any; +}) => { + return useMutation(publishOnRemoteNode, { + mutationKey: [publishAllFromSharedStateAsyncKey, ip], + ...opts, + }); +}; + +export const useSyncDataTypes = ({ + ip, + ...opts +}: { + ip: string; + opts?: any; +}) => { + return useMutation(syncAllDataTypes, { + mutationKey: [syncFromSharedStateAsyncKey, ip], + ...opts, + }); +}; + /** * Set mesh wide config */ From 585aa6b0037e58ec8ccfd8dd7bc3c658a37c7fec Mon Sep 17 00:00:00 2001 From: selankon Date: Fri, 10 May 2024 17:02:39 +0200 Subject: [PATCH 6/7] chore(meshwide): add isLoading state --- .../FeatureDetail/UpdateNodeInfoBtn.tsx | 46 ++++++++++++------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/UpdateNodeInfoBtn.tsx b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/UpdateNodeInfoBtn.tsx index d780ddb9..2c3d9137 100644 --- a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/UpdateNodeInfoBtn.tsx +++ b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/UpdateNodeInfoBtn.tsx @@ -1,4 +1,5 @@ import { Trans } from "@lingui/macro"; +import { useState } from "preact/hooks"; import { useCallback } from "react"; import { Button } from "components/buttons/button"; @@ -21,7 +22,9 @@ import queryCache from "utils/queryCache"; const UpdateNodeInfoBtn = ({ node }: { node: INodeInfo }) => { const ip = node.ipv4; + const [isLoading, setIsLoading] = useState(false); const { showToast } = useToast(); + const { mutateAsync: localNodeSync } = useSyncDataTypes({ ip, }); @@ -42,25 +45,31 @@ const UpdateNodeInfoBtn = ({ node }: { node: INodeInfo }) => { // useCallback to sync the node data const syncNode = useCallback(async () => { - try { - await publishOnRemoteNode({ ip }); - } catch (e) { - showToast({ - text: ( - - Error connecting with {node.hostname}, is node up? - - ), - duration: 5000, + if (isLoading) return; + setIsLoading(true); + publishOnRemoteNode({ ip }) + .catch((e) => { + showToast({ + text: ( + + Error connecting with {node.hostname}, is node up? + + ), + duration: 5000, + }); + throw e; + }) + .then(async () => { + await localNodeSync({ ip }); + await invalidateQueries(); + }) + .finally(() => { + setIsLoading(false); }); - console.error(e); - } - - await localNodeSync({ ip }); - await invalidateQueries(); }, [ invalidateQueries, ip, + isLoading, localNodeSync, node.hostname, publishOnRemoteNode, @@ -68,7 +77,12 @@ const UpdateNodeInfoBtn = ({ node }: { node: INodeInfo }) => { ]); return ( - ); From 5e3b5c72a561e85d23dd0c829d218c459d3d218d Mon Sep 17 00:00:00 2001 From: selankon Date: Fri, 10 May 2024 17:08:06 +0200 Subject: [PATCH 7/7] chore(meshwide): sync node on component mount --- .../components/FeatureDetail/UpdateNodeInfoBtn.tsx | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/UpdateNodeInfoBtn.tsx b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/UpdateNodeInfoBtn.tsx index 2c3d9137..b8a8b9db 100644 --- a/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/UpdateNodeInfoBtn.tsx +++ b/plugins/lime-plugin-mesh-wide/src/components/FeatureDetail/UpdateNodeInfoBtn.tsx @@ -1,5 +1,5 @@ import { Trans } from "@lingui/macro"; -import { useState } from "preact/hooks"; +import { useEffect, useState } from "preact/hooks"; import { useCallback } from "react"; import { Button } from "components/buttons/button"; @@ -23,7 +23,7 @@ const UpdateNodeInfoBtn = ({ node }: { node: INodeInfo }) => { const ip = node.ipv4; const [isLoading, setIsLoading] = useState(false); - const { showToast } = useToast(); + const { showToast, hideToast } = useToast(); const { mutateAsync: localNodeSync } = useSyncDataTypes({ ip, @@ -76,6 +76,14 @@ const UpdateNodeInfoBtn = ({ node }: { node: INodeInfo }) => { showToast, ]); + // Use effect to sync the node data on mount + useEffect(() => { + (async () => { + await syncNode(); + })(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [node.ipv4]); + return (