diff --git a/pkgs/ui/src/app/access-point/page.tsx b/pkgs/ui/src/app/access-point/page.tsx index 77487be..5a00802 100644 --- a/pkgs/ui/src/app/access-point/page.tsx +++ b/pkgs/ui/src/app/access-point/page.tsx @@ -11,6 +11,7 @@ import { } from "@/config/access_point"; import { useEffect } from "react"; import useGetEntityByNameOrDid from "@/components/hooks/useGetEntityByNameOrDid"; +import { projectConfig } from "@/config/config"; export default function AccessPoint() { const { entity } = useGetEntityByNameOrDid("AP"); @@ -46,7 +47,7 @@ export default function AccessPoint() { useEffect(() => { const interval = setInterval(() => { onRefresh(); - }, 5000); + }, projectConfig.REFRESH_FREQUENCY); return () => clearInterval(interval); // eslint-disable-next-line react-hooks/exhaustive-deps diff --git a/pkgs/ui/src/app/client/client.tsx b/pkgs/ui/src/app/client/client.tsx index 6772be4..7994702 100644 --- a/pkgs/ui/src/app/client/client.tsx +++ b/pkgs/ui/src/app/client/client.tsx @@ -5,15 +5,10 @@ import CustomTable from "@/components/table"; import { Alert, Button, - Card, - CardContent, - CardHeader, Snackbar, - Typography, CircularProgress, IconButton, } from "@mui/material"; -import CopyToClipboard from "@/components/copy_to_clipboard"; import { attachEntity, detachEntity, @@ -27,6 +22,8 @@ import { useGetAllServices } from "@/api/services/services"; import axios from "axios"; import CloseIcon from "@mui/icons-material/Close"; import { useSearchParams } from "next/navigation"; +import SummaryDetails from "@/components/summary_card"; +import { projectConfig } from "@/config/config"; interface SnackMessage { message: string; @@ -136,13 +133,12 @@ export default function Client() { useEffect(() => { const interval = setInterval(() => { onRefresh(); - }, 5000); + }, projectConfig.REFRESH_FREQUENCY); return () => clearInterval(interval); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); - const cardContentRef = useRef(null); const [snackbarOpen, setSnackbarOpen] = useState(false); const [snackbarMessage, setSnackbarMessage] = useState< SnackMessage | undefined @@ -179,23 +175,16 @@ export default function Client() { - - } - /> - - - DID: {entity?.did} - - - IP: {entity?.ip} - - - Network: {entity?.network} - - - +

Client View

{ const interval = setInterval(() => { onRefresh(); - }, 5000); + }, projectConfig.REFRESH_FREQUENCY); return () => clearInterval(interval); // eslint-disable-next-line react-hooks/exhaustive-deps diff --git a/pkgs/ui/src/app/home/page.tsx b/pkgs/ui/src/app/home/page.tsx index 7b31e65..bd22485 100644 --- a/pkgs/ui/src/app/home/page.tsx +++ b/pkgs/ui/src/app/home/page.tsx @@ -8,6 +8,7 @@ import dynamic from "next/dynamic"; import { useEffect } from "react"; import { mutate } from "swr"; import ErrorBoundary from "@/components/error_boundary"; +import { projectConfig } from "@/config/config"; const NoSSRSequenceDiagram = dynamic( () => import("../../components/sequence_diagram"), @@ -30,7 +31,7 @@ export default function Home() { useEffect(() => { const interval = setInterval(() => { onRefresh(); - }, 5000); + }, projectConfig.REFRESH_FREQUENCY); return () => clearInterval(interval); // eslint-disable-next-line react-hooks/exhaustive-deps diff --git a/pkgs/ui/src/components/entity_actions/index.tsx b/pkgs/ui/src/components/entity_actions/index.tsx new file mode 100644 index 0000000..7a3ba8d --- /dev/null +++ b/pkgs/ui/src/components/entity_actions/index.tsx @@ -0,0 +1,111 @@ +import { IEntityActions } from "@/types"; +import { Button, Snackbar, Alert, AlertColor } from "@mui/material"; +import { useState } from "react"; +import useAxios from "../hooks/useAxios"; +import { deleteEntity } from "@/api/entities/entities"; + +interface Props { + endpointData: IEntityActions[]; + rowData?: any; +} + +const SNACKBAR_DEFAULT = { + open: false, + message: "", + severity: "info" as AlertColor, +}; + +const EntityActions = ({ endpointData, rowData }: Props) => { + const [currentEndpoint, setCurrentEndpoint] = useState(""); + const [shouldFetch, setShouldFetch] = useState(false); + const { error } = useAxios(currentEndpoint, "GET", null, true, shouldFetch); + + const [snackbar, setSnackbar] = useState<{ + open: boolean; + message: string; + severity: AlertColor; + }>(SNACKBAR_DEFAULT); + + console.error("Error registering/deregistering:", error); + + const onDeleteEntity = async () => { + if (rowData) + try { + const response = await deleteEntity({ + entity_did: rowData?.entity_did, + }); + console.log("On Delete:", response.data.message); + setSnackbar({ + open: true, + message: response.data.message, + severity: "success", + }); + } catch (error) { + console.error("Error deleting entity: ", error); + setSnackbar({ + open: true, + message: "Failed to delete entity.", + severity: "error", + }); + } + }; + + const onRegisterEntity = (endpoint: string) => { + setCurrentEndpoint(endpoint); + setShouldFetch(true); + }; + + const onDeregisterEntity = (endpoint: string) => { + setCurrentEndpoint(endpoint); + setShouldFetch(true); + }; + + const handleCloseSnackbar = () => { + setSnackbar(SNACKBAR_DEFAULT); + }; + + return ( + <> +
+ {endpointData.map( + ({ name, endpoint }: IEntityActions, index: number) => { + const isRegister = name && name.toLocaleLowerCase() === "register"; + return ( + + ); + }, + )} + +
+ + + {snackbar.message} + + + + ); +}; + +export default EntityActions; diff --git a/pkgs/ui/src/components/hooks/useAxios.tsx b/pkgs/ui/src/components/hooks/useAxios.tsx new file mode 100644 index 0000000..48a0493 --- /dev/null +++ b/pkgs/ui/src/components/hooks/useAxios.tsx @@ -0,0 +1,49 @@ +import { useState, useEffect } from "react"; +import axios from "axios"; +import { projectConfig } from "@/config/config"; + +const useAxios = ( + url: string, + method = "GET", + payload = null, + isFullUrl = false, + shouldFetch = false, +) => { + const [data, setData] = useState(null); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + + const fetch = () => { + setLoading(true); + setError(null); + const finalUrl = isFullUrl ? url : projectConfig.BASE_URL + url; + + const axiosConfig = { + url: finalUrl, + method, + data: payload, + }; + + axios(axiosConfig) + .then((response) => { + setData(response.data); + }) + .catch((error) => { + setError(error); + }) + .finally(() => { + setLoading(false); + }); + }; + + useEffect(() => { + if (shouldFetch) { + fetch(); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [url, method, JSON.stringify(payload), shouldFetch]); + + return { data, loading, error, refetch: fetch }; +}; + +export default useAxios; diff --git a/pkgs/ui/src/components/hooks/useFetch.tsx b/pkgs/ui/src/components/hooks/useFetch.tsx deleted file mode 100644 index 8eae13c..0000000 --- a/pkgs/ui/src/components/hooks/useFetch.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import { useState, useEffect } from "react"; -import axios from "axios"; -import { projectConfig } from "@/config/config"; - -const useFetch = (url: string) => { - const [data, setData] = useState([]); - const [loading, setLoading] = useState(true); - const [error, setError] = useState(null); - - const fetch = () => { - setLoading(true); - axios - .get(projectConfig.BASE_URL + url) - .then((response) => { - setData(response.data); - }) - .catch((error) => { - setError(error); - }) - .finally(() => { - setLoading(false); - }); - }; - - useEffect(() => { - fetch(); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [url]); - - return { data, loading, error, fetch }; -}; - -export default useFetch; diff --git a/pkgs/ui/src/components/table/index.tsx b/pkgs/ui/src/components/table/index.tsx index 635fbe4..d4d35bf 100644 --- a/pkgs/ui/src/components/table/index.tsx +++ b/pkgs/ui/src/components/table/index.tsx @@ -23,7 +23,8 @@ const CustomTable = ({ configuration, data, loading, tkey }: ICustomTable) => { const renderTableCell = ( value: any, cellKey: string, - render?: (param: any) => void | undefined, + render?: (param: any, data?: any) => void | undefined, + rowData?: any, ) => { let renderedValue = value; @@ -35,7 +36,7 @@ const CustomTable = ({ configuration, data, loading, tkey }: ICustomTable) => { renderedValue = ; // cover use case if we want to render a component - if (render) renderedValue = render(value); + if (render) renderedValue = render(value, rowData); // catch use case where the value is an object but the render function is not provided in the table config if ( @@ -66,17 +67,18 @@ const CustomTable = ({ configuration, data, loading, tkey }: ICustomTable) => { - {data.map((data: any, rowIndex: number) => ( + {data.map((rowData: any, rowIndex: number) => ( {configuration.map( (column: CustomTableConfiguration, columnIndex: number) => { - const cellValue: any = data[column.key]; + const cellValue: any = rowData[column.key]; const cellKey = tkey + ":" + column.key + ":" + rowIndex; const renderComponent = column?.render; return renderTableCell( cellValue, cellKey + ":" + columnIndex, renderComponent, + rowData, ); }, )} diff --git a/pkgs/ui/src/config/client_1/index.tsx b/pkgs/ui/src/config/client_1/index.tsx index e1ad33e..64a9e2d 100644 --- a/pkgs/ui/src/config/client_1/index.tsx +++ b/pkgs/ui/src/config/client_1/index.tsx @@ -2,6 +2,7 @@ import { Button, IconButton, Tooltip } from "@mui/material"; import AddCircleIcon from "@mui/icons-material/AddCircle"; import RemoveCircleIcon from "@mui/icons-material/RemoveCircle"; import DeleteIcon from "@mui/icons-material/Delete"; +import EntityActions from "@/components/entity_actions"; export const ClientTableConfig = [ { @@ -88,39 +89,10 @@ export const ServiceTableConfig = [ { key: "action", label: "Actions", - render: () => { - return ( - <> - - - - - - - - - - - - - - - - - - ); - // let renderedValue: any = ""; - // if (typeof value === "object") - // renderedValue = ( - // <> - // {[...value.data, { name: 'Delete', endpoint: '' }].map((actionType: any) => ( - // <> - // - // - // ))} - // - // ); - // return renderedValue; + render: (value: any, rowData?: any) => { + if (value && value?.data.length > 0) + return ; + else return "N/A"; }, }, ]; diff --git a/pkgs/ui/src/config/config.tsx b/pkgs/ui/src/config/config.tsx index a42175e..7f4a73a 100644 --- a/pkgs/ui/src/config/config.tsx +++ b/pkgs/ui/src/config/config.tsx @@ -9,6 +9,7 @@ import BuildIcon from "@mui/icons-material/Build"; export const projectConfig: any = { BASE_URL: "http://localhost:2979/api/v1", + REFRESH_FREQUENCY: 5000, GROUPS: [ { groupName: "Attachement", diff --git a/pkgs/ui/src/types/index.ts b/pkgs/ui/src/types/index.ts index d1be251..28fe7f0 100644 --- a/pkgs/ui/src/types/index.ts +++ b/pkgs/ui/src/types/index.ts @@ -13,17 +13,22 @@ export interface ICustomTable { export interface EntityDetails { label: string; - value: string; + value: string | undefined; } export interface Entity { - name: string; + name?: string; details: EntityDetails[]; } export interface ISummaryDetails { - entity: any; + entity: Entity; fake?: boolean; hasRefreshButton?: boolean; onRefresh?: () => void; } + +export interface IEntityActions { + name: string; + endpoint: string; +}