generated from Luis/nextjs-python-web-template
added a lot of stuff
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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<HTMLDivElement>(null);
|
||||
const [snackbarOpen, setSnackbarOpen] = useState(false);
|
||||
const [snackbarMessage, setSnackbarMessage] = useState<
|
||||
SnackMessage | undefined
|
||||
@@ -179,23 +175,16 @@ export default function Client() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Card variant="outlined">
|
||||
<CardHeader
|
||||
subheader="Summary"
|
||||
action={<CopyToClipboard contentRef={cardContentRef} />}
|
||||
/>
|
||||
<CardContent ref={cardContentRef}>
|
||||
<Typography color="text.primary" gutterBottom>
|
||||
DID: <code>{entity?.did}</code>
|
||||
</Typography>
|
||||
<Typography color="text.primary" gutterBottom>
|
||||
IP: <code>{entity?.ip}</code>
|
||||
</Typography>
|
||||
<Typography color="text.primary" gutterBottom>
|
||||
Network: <code>{entity?.network}</code>
|
||||
</Typography>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<SummaryDetails
|
||||
entity={{
|
||||
name: "",
|
||||
details: [
|
||||
{ label: "DID", value: entity?.did },
|
||||
{ label: "IP", value: entity?.ip },
|
||||
{ label: "Network", value: entity?.network },
|
||||
],
|
||||
}}
|
||||
/>
|
||||
<div>
|
||||
<h4>Client View</h4>
|
||||
<CustomTable
|
||||
|
||||
@@ -7,6 +7,7 @@ import { useEffect } from "react";
|
||||
import { useGetAllResolutions } from "@/api/resolution/resolution";
|
||||
import { mutate } from "swr";
|
||||
import useGetEntityByNameOrDid from "@/components/hooks/useGetEntityByNameOrDid";
|
||||
import { projectConfig } from "@/config/config";
|
||||
|
||||
export default function DLG() {
|
||||
const { entity } = useGetEntityByNameOrDid("DLG");
|
||||
@@ -30,7 +31,7 @@ export default function DLG() {
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => {
|
||||
onRefresh();
|
||||
}, 5000);
|
||||
}, projectConfig.REFRESH_FREQUENCY);
|
||||
|
||||
return () => clearInterval(interval);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
|
||||
@@ -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
|
||||
|
||||
111
pkgs/ui/src/components/entity_actions/index.tsx
Normal file
111
pkgs/ui/src/components/entity_actions/index.tsx
Normal file
@@ -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 (
|
||||
<>
|
||||
<div className="flex justify-between">
|
||||
{endpointData.map(
|
||||
({ name, endpoint }: IEntityActions, index: number) => {
|
||||
const isRegister = name && name.toLocaleLowerCase() === "register";
|
||||
return (
|
||||
<Button
|
||||
key={index}
|
||||
onClick={() =>
|
||||
isRegister
|
||||
? onRegisterEntity(endpoint)
|
||||
: onDeregisterEntity(endpoint)
|
||||
}
|
||||
variant="contained"
|
||||
size="small"
|
||||
>
|
||||
{name}
|
||||
</Button>
|
||||
);
|
||||
},
|
||||
)}
|
||||
<Button onClick={onDeleteEntity} size="small" variant="contained">
|
||||
Delete
|
||||
</Button>
|
||||
</div>
|
||||
<Snackbar
|
||||
anchorOrigin={{ vertical: "top", horizontal: "center" }}
|
||||
open={snackbar.open}
|
||||
autoHideDuration={5000}
|
||||
onClose={handleCloseSnackbar}
|
||||
>
|
||||
<Alert
|
||||
onClose={handleCloseSnackbar}
|
||||
severity={snackbar?.severity}
|
||||
sx={{ width: "100%" }}
|
||||
>
|
||||
{snackbar.message}
|
||||
</Alert>
|
||||
</Snackbar>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default EntityActions;
|
||||
49
pkgs/ui/src/components/hooks/useAxios.tsx
Normal file
49
pkgs/ui/src/components/hooks/useAxios.tsx
Normal file
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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 = <Checkbox disabled checked={value} />;
|
||||
|
||||
// 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) => {
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{data.map((data: any, rowIndex: number) => (
|
||||
{data.map((rowData: any, rowIndex: number) => (
|
||||
<StyledTableRow key={rowIndex}>
|
||||
{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,
|
||||
);
|
||||
},
|
||||
)}
|
||||
|
||||
@@ -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 (
|
||||
<>
|
||||
<Tooltip title="Register" placement="top">
|
||||
<IconButton disabled size="small">
|
||||
<AddCircleIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip title="De-register" placement="top">
|
||||
<IconButton disabled size="small">
|
||||
<RemoveCircleIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Tooltip title="Delete" placement="top">
|
||||
<IconButton disabled size="small" color="secondary">
|
||||
<DeleteIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</>
|
||||
);
|
||||
// let renderedValue: any = "";
|
||||
// if (typeof value === "object")
|
||||
// renderedValue = (
|
||||
// <>
|
||||
// {[...value.data, { name: 'Delete', endpoint: '' }].map((actionType: any) => (
|
||||
// <>
|
||||
// <Button disabled style={{ marginRight: 8 }} variant="outlined" size="small">{actionType.name}</Button>
|
||||
// </>
|
||||
// ))}
|
||||
// </>
|
||||
// );
|
||||
// return renderedValue;
|
||||
render: (value: any, rowData?: any) => {
|
||||
if (value && value?.data.length > 0)
|
||||
return <EntityActions rowData={rowData} endpointData={value.data} />;
|
||||
else return "N/A";
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user