Skip to content

Commit

Permalink
refactor(web): use queries to retrieve iSCSI nodes
Browse files Browse the repository at this point in the history
  • Loading branch information
imobachgs committed Sep 11, 2024
1 parent d58f979 commit 8f68af9
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 96 deletions.
8 changes: 7 additions & 1 deletion web/src/api/storage/iscsi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
*/

import { get, patch } from "~/api/http";
import { ISCSIInitiator } from "./types";
import { ISCSIInitiator, ISCSINode } from "~/api/storage/types";

/**
* Returns the iSCSI initiator.
Expand All @@ -32,7 +32,13 @@ const fetchInitiator = (): Promise<ISCSIInitiator> => get("/api/storage/iscsi/in
*/
const updateInitiator = ({ name }) => patch("/api/storage/iscsi/initiator", { name });

/**
* Returns the iSCSI nodes.
*/
const fetchNodes = (): Promise<ISCSINode[]> => get("/api/storage/iscsi/nodes");

export {
fetchInitiator,
fetchNodes,
updateInitiator
}
103 changes: 11 additions & 92 deletions web/src/components/storage/iscsi/TargetsSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,101 +19,22 @@
* find current contact information at www.suse.com.
*/

import React, { useEffect, useReducer } from "react";
import React, { useState } from "react";
import { Button, Toolbar, ToolbarItem, ToolbarContent, Stack } from "@patternfly/react-core";
import { Section, SectionSkeleton } from "~/components/core";
import { Section } from "~/components/core";
import { NodesPresenter, DiscoverForm } from "~/components/storage/iscsi";
import { useInstallerClient } from "~/context/installer";
import { useCancellablePromise } from "~/utils";
import { _ } from "~/i18n";

const reducer = (state, action) => {
switch (action.type) {
case "SET_NODES": {
return { ...state, nodes: action.payload.nodes };
}

case "ADD_NODE": {
if (state.nodes.find((n) => n.id === action.payload.node.id)) return state;

const nodes = [...state.nodes];
nodes.push(action.payload.node);
return { ...state, nodes };
}

case "UPDATE_NODE": {
const index = state.nodes.findIndex((n) => n.id === action.payload.node.id);
if (index === -1) return state;

const nodes = [...state.nodes];
nodes[index] = action.payload.node;
return { ...state, nodes };
}

case "REMOVE_NODE": {
const nodes = state.nodes.filter((n) => n.id !== action.payload.node.id);
return { ...state, nodes };
}

case "OPEN_DISCOVER_FORM": {
return { ...state, isDiscoverFormOpen: true };
}

case "CLOSE_DISCOVER_FORM": {
return { ...state, isDiscoverFormOpen: false };
}

case "START_LOADING": {
return { ...state, isLoading: true };
}

case "STOP_LOADING": {
return { ...state, isLoading: false };
}

default: {
return state;
}
}
};

const initialState = {
nodes: [],
isDiscoverFormOpen: false,
isLoading: true,
};
import { useNodes, useNodesChanges } from "~/queries/storage/iscsi";

export default function TargetsSection() {
const { storage: client } = useInstallerClient();
const { cancellablePromise } = useCancellablePromise();
const [state, dispatch] = useReducer(reducer, initialState);

useEffect(() => {
const loadNodes = async () => {
dispatch({ type: "START_LOADING" });
const nodes = await cancellablePromise(client.iscsi.getNodes());
dispatch({ type: "SET_NODES", payload: { nodes } });
dispatch({ type: "STOP_LOADING" });
};
const [isDiscoverFormOpen, setIsDiscoverFormOpen] = useState<boolean>(false);
const nodes = useNodes();
useNodesChanges();

loadNodes().catch(console.error);
}, [cancellablePromise, client.iscsi]);

useEffect(() => {
const action = (type, node) => dispatch({ type, payload: { node } });

client.iscsi.onNodeAdded((n) => action("ADD_NODE", n));
client.iscsi.onNodeChanged((n) => action("UPDATE_NODE", n));
client.iscsi.onNodeRemoved((n) => action("REMOVE_NODE", n));
}, [client.iscsi]);

const openDiscoverForm = () => {
dispatch({ type: "OPEN_DISCOVER_FORM" });
};

const closeDiscoverForm = () => {
dispatch({ type: "CLOSE_DISCOVER_FORM" });
};
const openDiscoverForm = () => setIsDiscoverFormOpen(true);
const closeDiscoverForm = () => setIsDiscoverFormOpen(false);

const submitDiscoverForm = async (data) => {
const { username, password, reverseUsername, reversePassword } = data;
Expand All @@ -130,9 +51,7 @@ export default function TargetsSection() {
};

const SectionContent = () => {
if (state.isLoading) return <SectionSkeleton />;

if (state.nodes.length === 0) {
if (nodes.length === 0) {
return (
<Stack hasGutter>
<div>{_("No iSCSI targets found.")}</div>
Expand All @@ -157,7 +76,7 @@ export default function TargetsSection() {
</ToolbarItem>
</ToolbarContent>
</Toolbar>
<NodesPresenter nodes={state.nodes} client={client} />
<NodesPresenter nodes={nodes} client={client} />
</>
);
};
Expand All @@ -166,7 +85,7 @@ export default function TargetsSection() {
// TRANSLATORS: iSCSI targets section title
<Section title={_("Targets")}>
<SectionContent />
{state.isDiscoverFormOpen && (
{isDiscoverFormOpen && (
<DiscoverForm onSubmit={submitDiscoverForm} onCancel={closeDiscoverForm} />
)}
</Section>
Expand Down
38 changes: 35 additions & 3 deletions web/src/queries/storage/iscsi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@

import { useMutation, useQueryClient, useSuspenseQuery } from "@tanstack/react-query";
import React from "react";
import { fetchInitiator, updateInitiator } from "~/api/storage/iscsi";
import { fetchInitiator, fetchNodes, updateInitiator } from "~/api/storage/iscsi";
import { ISCSIInitiator } from "~/types/storage";
import { useInstallerClient } from "~/context/installer";
import { ISCSINode } from "~/api/storage/types";

const initiatorQuery = {
queryKey: ["storage", "iscsi", "initiator"],
Expand Down Expand Up @@ -60,11 +61,42 @@ const useInitiatorChanges = () => {
queryClient.setQueryData(initiatorQuery.queryKey, { name, value, offloadCard: "" });
}
})
});
}, [client, queryClient]);
};

const nodesQuery = {
queryKey: ["storage", "iscsi", "nodes"],
queryFn: fetchNodes
};

const useNodes = (): ISCSINode[] => {
const { data } = useSuspenseQuery(nodesQuery);
return data;
}

const useNodesChanges = () => {
const client = useInstallerClient();
const queryClient = useQueryClient();

React.useEffect(() => {
if (!client) return;

return client.ws().onEvent(({ type }) => {
if (["ISCSINodeAdded", "ISCSINodeChanged", "ISCSINodeRemoved"].includes(type)) {
console.log("cleaning-up");
// FIXME: update with the information coming from the signal
queryClient.invalidateQueries({ queryKey: ["storage"] });
queryClient.invalidateQueries({ queryKey: nodesQuery.queryKey });
}
});
}, [client, queryClient]);
};


export {
useInitiator,
useInitiatorMutation,
useInitiatorChanges
useInitiatorChanges,
useNodes,
useNodesChanges
}

0 comments on commit 8f68af9

Please sign in to comment.