generated from Luis/nextjs-python-web-template
current progress with diagram and project fixes
This commit is contained in:
committed by
Sara Pervana
parent
60205b3c22
commit
c03da10e98
@@ -139,7 +139,7 @@ export default function Client({ params }: { params: { name: string } }) {
|
|||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const cardContentRef = useRef(null);
|
const cardContentRef = useRef<HTMLDivElement>(null);
|
||||||
const [snackbarOpen, setSnackbarOpen] = useState(false);
|
const [snackbarOpen, setSnackbarOpen] = useState(false);
|
||||||
const [snackbarMessage, setSnackbarMessage] = useState<
|
const [snackbarMessage, setSnackbarMessage] = useState<
|
||||||
SnackMessage | undefined
|
SnackMessage | undefined
|
||||||
|
|||||||
@@ -42,7 +42,6 @@ export default function Home() {
|
|||||||
entity={{ name: "Home", details: [] }}
|
entity={{ name: "Home", details: [] }}
|
||||||
hasRefreshButton={true}
|
hasRefreshButton={true}
|
||||||
onRefresh={onRefresh}
|
onRefresh={onRefresh}
|
||||||
hasAttachDetach={false}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@@ -51,7 +51,6 @@ export default function RootLayout({
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<meta name="description" content="Service Aware Networks" />
|
<meta name="description" content="Service Aware Networks" />
|
||||||
<link rel="icon" href="tub-favicon.ico" sizes="any" />
|
<link rel="icon" href="tub-favicon.ico" sizes="any" />
|
||||||
{/* <script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script> */}
|
|
||||||
<script
|
<script
|
||||||
// eslint-disable-next-line react/no-danger
|
// eslint-disable-next-line react/no-danger
|
||||||
dangerouslySetInnerHTML={{
|
dangerouslySetInnerHTML={{
|
||||||
|
|||||||
@@ -1,26 +1,50 @@
|
|||||||
import { useState } from "react";
|
import { useState, RefObject } from "react";
|
||||||
import { Button, Snackbar } from "@mui/material";
|
import { Tooltip, Snackbar } from "@mui/material";
|
||||||
|
import ContentCopyIcon from "@mui/icons-material/ContentCopy";
|
||||||
|
|
||||||
const CopyToClipboard = ({ contentRef }: { contentRef: any }) => {
|
const CopyToClipboard = ({
|
||||||
|
contentRef,
|
||||||
|
textToCopy,
|
||||||
|
}: {
|
||||||
|
contentRef?: RefObject<HTMLDivElement>;
|
||||||
|
textToCopy?: string;
|
||||||
|
}) => {
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
|
|
||||||
const handleClick = () => {
|
const handleClick = () => {
|
||||||
if (contentRef.current) {
|
// Prioritize direct text copy if 'textToCopy' is provided
|
||||||
const text = contentRef.current.textContent;
|
const text = textToCopy || contentRef?.current?.textContent || "";
|
||||||
navigator.clipboard.writeText(text);
|
const copiedText = textToCopy ? JSON.stringify(text, null, 2) : text;
|
||||||
setOpen(true);
|
|
||||||
|
if (text) {
|
||||||
|
navigator.clipboard.writeText(copiedText).then(
|
||||||
|
() => {
|
||||||
|
setOpen(true);
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
console.error("Could not copy text: ", err);
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Button onClick={handleClick}>Copy</Button>
|
<Tooltip placement="left" title="Copy to Clipboard">
|
||||||
|
<ContentCopyIcon onClick={handleClick} className="cursor-pointer" />
|
||||||
|
</Tooltip>
|
||||||
<Snackbar
|
<Snackbar
|
||||||
open={open}
|
open={open}
|
||||||
onClose={() => setOpen(false)}
|
onClose={() => setOpen(false)}
|
||||||
autoHideDuration={2000}
|
autoHideDuration={2000}
|
||||||
message="Copied to clipboard"
|
message="Copied to clipboard!"
|
||||||
|
anchorOrigin={{
|
||||||
|
vertical: "bottom",
|
||||||
|
horizontal: "left",
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default CopyToClipboard;
|
export default CopyToClipboard;
|
||||||
|
|||||||
73
pkgs/ui/src/components/copy_to_clipboard/readme.md
Normal file
73
pkgs/ui/src/components/copy_to_clipboard/readme.md
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
# CopyToClipboard Component
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The `CopyToClipboard` component is a versatile UI component designed to facilitate copying text to the user's clipboard. It can copy text from two sources: directly from a passed text string prop (`textToCopy`) or from the text content of a referenced div element (`contentRef`). The component includes a clickable icon and displays a confirmation snackbar notification once the copy action is successful.
|
||||||
|
|
||||||
|
## Props
|
||||||
|
|
||||||
|
The component accepts the following props:
|
||||||
|
|
||||||
|
1. `textToCopy` (optional): A string representing the direct text you want to copy. If provided, this text is copied to the clipboard when the icon is clicked.
|
||||||
|
|
||||||
|
2. `contentRef` (optional): A `RefObject<HTMLDivElement>` that references a div element. The text content of this div is copied to the clipboard if `textToCopy` is not provided.
|
||||||
|
|
||||||
|
## Behavior
|
||||||
|
|
||||||
|
- Copy Action: When the copy icon is clicked, the component:
|
||||||
|
|
||||||
|
- Prioritizes copying the text from the textToCopy prop if it's provided and not an empty string.
|
||||||
|
- If textToCopy is not provided or is empty, it then attempts to copy the text content of the element referenced by contentRef.
|
||||||
|
- Uses the Clipboard API (`navigator.clipboard.writeText`) to copy the text to the user's clipboard.
|
||||||
|
- Displays a snackbar notification confirming the copy action if successful.
|
||||||
|
|
||||||
|
- Snackbar Notification: A temporary notification that:
|
||||||
|
- Appears after the text is successfully copied.
|
||||||
|
- Displays the message "Copied to clipboard!".
|
||||||
|
- Disappears automatically after 2000 milliseconds and is positioned at the bottom left of the screen.
|
||||||
|
|
||||||
|
## How to Use
|
||||||
|
|
||||||
|
1. Import the `CopyToClipboard` component.
|
||||||
|
2. Use the component in one of the following ways:
|
||||||
|
3. Pass a `textToCopy` prop with the text you want to copy, OR
|
||||||
|
4. Pass a `contentRef` prop pointing to a div element containing the text you want to copy.
|
||||||
|
5. Render the `CopyToClipboard` component where you want the copy icon to appear.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
Using `textToCopy` prop:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import CopyToClipboard from "./CopyToClipboard";
|
||||||
|
|
||||||
|
const SomeComponent = () => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<CopyToClipboard textToCopy="Text to be copied" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SomeComponent;
|
||||||
|
```
|
||||||
|
|
||||||
|
Using `contentRef` prop:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import React, { useRef } from "react";
|
||||||
|
import CopyToClipboard from "./CopyToClipboard";
|
||||||
|
|
||||||
|
const SomeComponent = () => {
|
||||||
|
const textRef = useRef(null);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div ref={textRef}>Text to copy from ref</div>
|
||||||
|
<CopyToClipboard contentRef={textRef} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SomeComponent;
|
||||||
|
```
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { BASE_URL } from "@/constants";
|
import { projectConfig } from "@/config/config";
|
||||||
|
|
||||||
const useFetch = (url: string) => {
|
const useFetch = (url: string) => {
|
||||||
const [data, setData] = useState([]);
|
const [data, setData] = useState([]);
|
||||||
@@ -10,7 +10,7 @@ const useFetch = (url: string) => {
|
|||||||
const fetch = () => {
|
const fetch = () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
axios
|
axios
|
||||||
.get(BASE_URL + url)
|
.get(projectConfig.BASE_URL + url)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
setData(response.data);
|
setData(response.data);
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,136 +1,276 @@
|
|||||||
import { Eventmessage } from "@/api/model";
|
import { Eventmessage } from "@/api/model";
|
||||||
|
|
||||||
export const generateMermaidString = (data: Eventmessage[] | undefined) => {
|
export const generateMermaidString = (data: Eventmessage[] | undefined) => {
|
||||||
if (!data || data.length === 0) return "";
|
if (!data) return "";
|
||||||
|
|
||||||
const participants = Array.from(
|
let mermaidString = "";
|
||||||
new Set(data.flatMap((item) => [item.src_did, item.des_did])),
|
|
||||||
);
|
|
||||||
|
|
||||||
let mermaidString = "sequenceDiagram\n";
|
// We'll use a Set to ensure participant uniqueness
|
||||||
|
const participants: Set<string> = new Set();
|
||||||
|
|
||||||
participants.forEach((participant, index) => {
|
// Define colors for groups (if you have more groups, add more colors)
|
||||||
mermaidString += ` participant ${String.fromCharCode(
|
const groupColors: Record<number, string> = {
|
||||||
65 + index,
|
0: "rgb(191, 223, 255)",
|
||||||
)} as ${participant}\n`;
|
1: "rgb(200, 150, 255)",
|
||||||
});
|
// Add more group colors if needed
|
||||||
|
};
|
||||||
|
|
||||||
let currentGroupId: number | null = null;
|
// Loop through the groups and group_ids to build the string
|
||||||
|
Object.entries(data).forEach(([group, groupData]) => {
|
||||||
|
// Add a rectangle for each group with a note
|
||||||
|
mermaidString += ` rect ${
|
||||||
|
groupColors[parseInt(group)] || "rgb(128, 128, 128)"
|
||||||
|
}\n`; // Fallback color if not defined
|
||||||
|
mermaidString += ` Note over ${Object.values(groupData)
|
||||||
|
.flatMap((gd) => gd.map((msg: any) => msg.src_name))
|
||||||
|
.join(",")}: Group ${group}\n`;
|
||||||
|
|
||||||
data.forEach((item, index) => {
|
Object.entries(groupData).forEach(([groupId, messages]) => {
|
||||||
const srcParticipant = String.fromCharCode(
|
// Add a rectangle for each group_id with a note
|
||||||
65 + participants.indexOf(item.src_did),
|
mermaidString += ` alt Group ID ${groupId}\n`;
|
||||||
);
|
|
||||||
const desParticipant = String.fromCharCode(
|
|
||||||
65 + participants.indexOf(item.des_did),
|
|
||||||
);
|
|
||||||
const timestamp = new Date(item.timestamp * 1000).toLocaleString();
|
|
||||||
const message = item.msg.text || `Event message ${index + 1}`;
|
|
||||||
|
|
||||||
if (item.group_id !== currentGroupId) {
|
messages.forEach((msg: any) => {
|
||||||
if (currentGroupId !== null) {
|
// Ensure we include each participant
|
||||||
mermaidString += ` end\n`;
|
participants.add(msg.src_name);
|
||||||
}
|
participants.add(msg.des_name);
|
||||||
mermaidString += ` alt Group ${item.group_id}\n`;
|
|
||||||
currentGroupId = item.group_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
mermaidString += ` ${srcParticipant}->>${desParticipant}: [${timestamp}] ${message}\n`;
|
// Add each message
|
||||||
});
|
mermaidString += ` ${msg.src_name}->>${msg.des_name}: [${msg.msg_type_name}]: Event Message ${msg.id}\n`;
|
||||||
|
});
|
||||||
|
|
||||||
|
mermaidString += ` end\n`;
|
||||||
|
});
|
||||||
|
|
||||||
if (currentGroupId !== null) {
|
|
||||||
mermaidString += ` end\n`;
|
mermaidString += ` end\n`;
|
||||||
}
|
});
|
||||||
|
|
||||||
|
// Add participants at the start of the string
|
||||||
|
const participantString = Array.from(participants)
|
||||||
|
.map((participant) => {
|
||||||
|
return ` participant ${participant}\n`;
|
||||||
|
})
|
||||||
|
.join("");
|
||||||
|
|
||||||
|
// Prepend participants to the mermaidString
|
||||||
|
mermaidString = `sequenceDiagram\n${participantString}` + mermaidString;
|
||||||
|
|
||||||
return mermaidString;
|
return mermaidString;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Dummy Data
|
export const mermaidSample = `
|
||||||
|
sequenceDiagram
|
||||||
|
participant C0 as C0 <br/>did:sov:test:120
|
||||||
|
participant C1 as C1 <br/>did:sov:test:121
|
||||||
|
participant C2 as C2 <br/>did:sov:test:122
|
||||||
|
|
||||||
export const dataFromBE = [
|
rect rgb(255, 154, 162)
|
||||||
|
Note over C0,C1 : Group 0
|
||||||
|
alt Group Id 16
|
||||||
|
C1->>C0: [Presentation]: Event Message 1
|
||||||
|
C1->>C0: [DID Resolution]: Event Message 2
|
||||||
|
end
|
||||||
|
|
||||||
|
alt Group Id 51
|
||||||
|
C0->>C1: [Attachement]: Event Message 3
|
||||||
|
C0->>C1: [Connection Setup]: Event Message 4
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
rect rgb(254, 183, 177)
|
||||||
|
Note over C1,C2 : Group 1
|
||||||
|
alt Group Id 13
|
||||||
|
C2->>C1: [Presentation]: Event Message 5
|
||||||
|
C2->>C1: [DID Resolution]: Event Message 6
|
||||||
|
end
|
||||||
|
|
||||||
|
alt Group Id 21
|
||||||
|
C1->>C2: [Attachement]: Event Message 7
|
||||||
|
C1->>C2: [Connection Setup]: Event Message 8
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
rect rgb(255, 218, 192)
|
||||||
|
Note over C0,C1 : Group 0
|
||||||
|
alt Group Id 16
|
||||||
|
C1->>C0: [Presentation]: Event Message 1
|
||||||
|
C1->>C0: [DID Resolution]: Event Message 2
|
||||||
|
end
|
||||||
|
|
||||||
|
alt Group Id 51
|
||||||
|
C0->>C1: [Attachement]: Event Message 3
|
||||||
|
C0->>C1: [Connection Setup]: Event Message 4
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
rect rgb(255, 236, 196)
|
||||||
|
Note over C1,C2 : Group 1
|
||||||
|
alt Group Id 13
|
||||||
|
C2->>C1: [Presentation]: Event Message 5
|
||||||
|
C2->>C1: [DID Resolution]: Event Message 6
|
||||||
|
end
|
||||||
|
|
||||||
|
alt Group Id 21
|
||||||
|
C1->>C2: [Attachement]: Event Message 7
|
||||||
|
C1->>C2: [Connection Setup]: Event Message 8
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
rect rgb(226, 240, 204)
|
||||||
|
Note over C0,C1 : Group 0
|
||||||
|
alt Group Id 16
|
||||||
|
C1->>C0: [Presentation]: Event Message 1
|
||||||
|
C1->>C0: [DID Resolution]: Event Message 2
|
||||||
|
end
|
||||||
|
|
||||||
|
alt Group Id 51
|
||||||
|
C0->>C1: [Attachement]: Event Message 3
|
||||||
|
C0->>C1: [Connection Setup]: Event Message 4
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
rect rgb(181, 234, 214)
|
||||||
|
Note over C1,C2 : Group 1
|
||||||
|
alt Group Id 13
|
||||||
|
C2->>C1: [Presentation]: Event Message 5
|
||||||
|
C2->>C1: [DID Resolution]: Event Message 6
|
||||||
|
end
|
||||||
|
|
||||||
|
alt Group Id 21
|
||||||
|
C1->>C2: [Attachement]: Event Message 7
|
||||||
|
C1->>C2: [Connection Setup]: Event Message 8
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
rect rgb(183, 219, 235)
|
||||||
|
Note over C0,C1 : Group 0
|
||||||
|
alt Group Id 16
|
||||||
|
C1->>C0: [Presentation]: Event Message 1
|
||||||
|
C1->>C0: [DID Resolution]: Event Message 2
|
||||||
|
end
|
||||||
|
|
||||||
|
alt Group Id 51
|
||||||
|
C0->>C1: [Attachement]: Event Message 3
|
||||||
|
C0->>C1: [Connection Setup]: Event Message 4
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
rect rgb(199, 206, 234)
|
||||||
|
Note over C1,C2 : Group 1
|
||||||
|
alt Group Id 13
|
||||||
|
C2->>C1: [Presentation]: Event Message 5
|
||||||
|
C2->>C1: [DID Resolution]: Event Message 6
|
||||||
|
end
|
||||||
|
|
||||||
|
alt Group Id 21
|
||||||
|
C1->>C2: [Attachement]: Event Message 7
|
||||||
|
C1->>C2: [Connection Setup]: Event Message 8
|
||||||
|
end
|
||||||
|
end
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const eventMessages = [
|
||||||
{
|
{
|
||||||
id: 12,
|
timestamp: 1706034368,
|
||||||
timestamp: 1704892813,
|
|
||||||
group: 0,
|
group: 0,
|
||||||
group_id: 12,
|
group_id: 16,
|
||||||
// "group_name": "Data",
|
|
||||||
msg_type: 4,
|
|
||||||
src_did: "did:sov:test:121",
|
|
||||||
// "src_name": "Entity A",
|
|
||||||
des_did: "did:sov:test:120",
|
|
||||||
// "des_name": "Entity B",
|
|
||||||
msg: {
|
|
||||||
text: "Hello World",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 60,
|
|
||||||
timestamp: 1704892823,
|
|
||||||
group: 1,
|
|
||||||
group_id: 19,
|
|
||||||
msg_type: 4,
|
|
||||||
src_did: "did:sov:test:122",
|
|
||||||
des_did: "did:sov:test:121",
|
|
||||||
msg: {},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 30162,
|
|
||||||
timestamp: 1704892817,
|
|
||||||
group: 1,
|
|
||||||
group_id: 53,
|
|
||||||
msg_type: 2,
|
|
||||||
src_did: "did:sov:test:121",
|
|
||||||
des_did: "did:sov:test:122",
|
|
||||||
msg: {},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 63043,
|
|
||||||
timestamp: 1704892809,
|
|
||||||
group: 0,
|
|
||||||
group_id: 12,
|
|
||||||
msg_type: 3,
|
msg_type: 3,
|
||||||
src_did: "did:sov:test:121",
|
src_did: "did:sov:test:121",
|
||||||
des_did: "did:sov:test:120",
|
des_did: "did:sov:test:120",
|
||||||
msg: {},
|
msg: {},
|
||||||
|
id: 3,
|
||||||
|
des_name: "C0",
|
||||||
|
src_name: "C1",
|
||||||
|
msg_type_name: "Presentation",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 66251,
|
timestamp: 1706034372,
|
||||||
timestamp: 1704892805,
|
group: 0,
|
||||||
|
group_id: 16,
|
||||||
|
msg_type: 4,
|
||||||
|
src_did: "did:sov:test:121",
|
||||||
|
des_did: "did:sov:test:120",
|
||||||
|
msg: {},
|
||||||
|
id: 4,
|
||||||
|
des_name: "C0",
|
||||||
|
src_name: "C1",
|
||||||
|
msg_type_name: "DID Resolution",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
timestamp: 1706034364,
|
||||||
group: 0,
|
group: 0,
|
||||||
group_id: 51,
|
group_id: 51,
|
||||||
msg_type: 1,
|
msg_type: 1,
|
||||||
src_did: "did:sov:test:120",
|
src_did: "did:sov:test:120",
|
||||||
des_did: "did:sov:test:121",
|
des_did: "did:sov:test:121",
|
||||||
msg: {},
|
msg: {},
|
||||||
|
id: 1,
|
||||||
|
des_name: "C1",
|
||||||
|
src_name: "C0",
|
||||||
|
msg_type_name: "Attachement",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 85434,
|
timestamp: 1706034366,
|
||||||
timestamp: 1704892807,
|
|
||||||
group: 0,
|
group: 0,
|
||||||
group_id: 51,
|
group_id: 51,
|
||||||
msg_type: 2,
|
msg_type: 2,
|
||||||
src_did: "did:sov:test:120",
|
src_did: "did:sov:test:120",
|
||||||
des_did: "did:sov:test:121",
|
des_did: "did:sov:test:121",
|
||||||
msg: {},
|
msg: {},
|
||||||
|
id: 2,
|
||||||
|
des_name: "C1",
|
||||||
|
src_name: "C0",
|
||||||
|
msg_type_name: "Connection Setup",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 124842,
|
timestamp: 1706034378,
|
||||||
timestamp: 1704892819,
|
|
||||||
group: 1,
|
group: 1,
|
||||||
group_id: 19,
|
group_id: 13,
|
||||||
msg_type: 3,
|
msg_type: 3,
|
||||||
src_did: "did:sov:test:122",
|
src_did: "did:sov:test:122",
|
||||||
des_did: "did:sov:test:121",
|
des_did: "did:sov:test:121",
|
||||||
msg: {},
|
msg: {},
|
||||||
|
id: 7,
|
||||||
|
des_name: "C1",
|
||||||
|
src_name: "C2",
|
||||||
|
msg_type_name: "Presentation",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 246326,
|
timestamp: 1706034382,
|
||||||
timestamp: 1704892815,
|
|
||||||
group: 1,
|
group: 1,
|
||||||
group_id: 53,
|
group_id: 13,
|
||||||
|
msg_type: 4,
|
||||||
|
src_did: "did:sov:test:122",
|
||||||
|
des_did: "did:sov:test:121",
|
||||||
|
msg: {},
|
||||||
|
id: 8,
|
||||||
|
des_name: "C1",
|
||||||
|
src_name: "C2",
|
||||||
|
msg_type_name: "DID Resolution",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
timestamp: 1706034374,
|
||||||
|
group: 1,
|
||||||
|
group_id: 21,
|
||||||
msg_type: 1,
|
msg_type: 1,
|
||||||
src_did: "did:sov:test:121",
|
src_did: "did:sov:test:121",
|
||||||
des_did: "did:sov:test:122",
|
des_did: "did:sov:test:122",
|
||||||
msg: {},
|
msg: {},
|
||||||
|
id: 5,
|
||||||
|
des_name: "C2",
|
||||||
|
src_name: "C1",
|
||||||
|
msg_type_name: "Attachement",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
timestamp: 1706034376,
|
||||||
|
group: 1,
|
||||||
|
group_id: 21,
|
||||||
|
msg_type: 2,
|
||||||
|
src_did: "did:sov:test:121",
|
||||||
|
des_did: "did:sov:test:122",
|
||||||
|
msg: {},
|
||||||
|
id: 6,
|
||||||
|
des_name: "C2",
|
||||||
|
src_name: "C1",
|
||||||
|
msg_type_name: "Connection Setup",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -2,32 +2,59 @@
|
|||||||
|
|
||||||
import { useRef, useEffect, useState } from "react";
|
import { useRef, useEffect, useState } from "react";
|
||||||
import mermaid from "mermaid";
|
import mermaid from "mermaid";
|
||||||
import { IconButton } from "@mui/material";
|
import {
|
||||||
|
Button,
|
||||||
|
Card,
|
||||||
|
Chip,
|
||||||
|
Dialog,
|
||||||
|
DialogActions,
|
||||||
|
Tooltip,
|
||||||
|
DialogContent,
|
||||||
|
DialogContentText,
|
||||||
|
DialogTitle,
|
||||||
|
IconButton,
|
||||||
|
List,
|
||||||
|
TextField,
|
||||||
|
} from "@mui/material";
|
||||||
|
//Icons
|
||||||
import RefreshIcon from "@mui/icons-material/Refresh";
|
import RefreshIcon from "@mui/icons-material/Refresh";
|
||||||
import ZoomInIcon from "@mui/icons-material/ZoomIn";
|
import ZoomInIcon from "@mui/icons-material/ZoomIn";
|
||||||
import ZoomOutIcon from "@mui/icons-material/ZoomOut";
|
import ZoomOutIcon from "@mui/icons-material/ZoomOut";
|
||||||
import FullscreenIcon from "@mui/icons-material/Fullscreen";
|
import FullscreenIcon from "@mui/icons-material/Fullscreen";
|
||||||
import DownloadIcon from "@mui/icons-material/Download";
|
import DownloadIcon from "@mui/icons-material/Download";
|
||||||
import ResetIcon from "@mui/icons-material/Autorenew";
|
import ResetIcon from "@mui/icons-material/Autorenew";
|
||||||
import Tooltip from "@mui/material/Tooltip";
|
import FilterAltIcon from "@mui/icons-material/FilterAlt";
|
||||||
|
import ContentCopyIcon from "@mui/icons-material/ContentCopy";
|
||||||
|
|
||||||
|
// Custom Components
|
||||||
import { NoDataOverlay } from "../noDataOverlay";
|
import { NoDataOverlay } from "../noDataOverlay";
|
||||||
|
import { LoadingOverlay } from "../join/loadingOverlay";
|
||||||
|
|
||||||
import { useGetAllEventmessages } from "@/api/eventmessages/eventmessages";
|
import { useGetAllEventmessages } from "@/api/eventmessages/eventmessages";
|
||||||
import { mutate } from "swr";
|
import { mutate } from "swr";
|
||||||
import { LoadingOverlay } from "../join/loadingOverlay";
|
|
||||||
//import { generateMermaidString } from "./helpers";
|
import { eventMessages, generateMermaidString, mermaidSample } from "./helpers";
|
||||||
|
import { iconMatch } from "@/config/config";
|
||||||
|
import CopyToClipboard from "../copy_to_clipboard";
|
||||||
|
import { formatDateTime } from "@/utils/helpers";
|
||||||
|
|
||||||
const SequenceDiagram = () => {
|
const SequenceDiagram = () => {
|
||||||
const {
|
const {
|
||||||
// data: eventMessagesData,
|
data: eventMessagesData,
|
||||||
isLoading: loadingEventMessages,
|
isLoading: loadingEventMessages,
|
||||||
swrKey: eventMessagesKeyFunc,
|
swrKey: eventMessagesKeyFunc,
|
||||||
} = useGetAllEventmessages();
|
} = useGetAllEventmessages();
|
||||||
|
|
||||||
const mermaidRef: any = useRef(null);
|
const mermaidRef: any = useRef(null);
|
||||||
const [scale, setScale] = useState(1);
|
const [scale, setScale] = useState(1);
|
||||||
const hasData = false; // TODO: Readd this, right now it's always false
|
const [openFilters, setOpenFilters] = useState(false);
|
||||||
|
|
||||||
const mermaidString = ""; //generateMermaidString(eventMessagesData?.data);
|
const [sequenceNr, setSequenceNr] = useState("");
|
||||||
|
const hasData = eventMessagesData?.data;
|
||||||
|
|
||||||
|
// const mermaidString = generateMermaidString(eventMessagesData?.data);
|
||||||
|
|
||||||
|
const mermaidString = mermaidSample;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!loadingEventMessages && hasData)
|
if (!loadingEventMessages && hasData)
|
||||||
@@ -35,7 +62,8 @@ const SequenceDiagram = () => {
|
|||||||
startOnLoad: false,
|
startOnLoad: false,
|
||||||
securityLevel: "loose",
|
securityLevel: "loose",
|
||||||
sequence: {
|
sequence: {
|
||||||
mirrorActors: false,
|
mirrorActors: true,
|
||||||
|
showSequenceNumbers: true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -126,55 +154,177 @@ const SequenceDiagram = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const toggleFilters = () => {
|
||||||
|
setOpenFilters((prevState) => !prevState);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onSearchBySeqNumber = (e: any) => {
|
||||||
|
setSequenceNr(e.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const copyToClipboard = (data: any) => {
|
||||||
|
navigator.clipboard.writeText(JSON.stringify(data, null, 2)).then(() => {
|
||||||
|
alert("JSON copied to clipboard!");
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const isFilterMatch = (index: number) => {
|
||||||
|
if (!sequenceNr) return true;
|
||||||
|
|
||||||
|
const filterSeqNrInt = parseInt(sequenceNr, 10);
|
||||||
|
return index + 1 === filterSeqNrInt;
|
||||||
|
};
|
||||||
|
|
||||||
if (loadingEventMessages)
|
if (loadingEventMessages)
|
||||||
return <LoadingOverlay title="Loading Diagram" subtitle="Please wait..." />;
|
return <LoadingOverlay title="Loading Diagram" subtitle="Please wait..." />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col items-end">
|
<>
|
||||||
{hasData ? (
|
<div className="flex flex-col items-end">
|
||||||
|
{hasData ? (
|
||||||
|
<>
|
||||||
|
<div className="flex justify-end">
|
||||||
|
<Tooltip placement="top" title="Filter Messages">
|
||||||
|
<IconButton color="primary" onClick={toggleFilters}>
|
||||||
|
<FilterAltIcon />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip placement="top" title="Refresh Diagram">
|
||||||
|
<IconButton color="primary" onClick={onRefresh}>
|
||||||
|
<RefreshIcon />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip title="Zoom In" placement="top">
|
||||||
|
<IconButton color="primary" onClick={zoomIn}>
|
||||||
|
<ZoomInIcon />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip title="Zoom Out" placement="top">
|
||||||
|
<IconButton color="primary" onClick={zoomOut}>
|
||||||
|
<ZoomOutIcon />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip title="Reset" placement="top">
|
||||||
|
<IconButton color="primary" onClick={resetZoom}>
|
||||||
|
<ResetIcon />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip title="View in Fullscreen" placement="top">
|
||||||
|
<IconButton color="primary" onClick={viewInFullScreen}>
|
||||||
|
<FullscreenIcon />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip title="Download as PNG" placement="top">
|
||||||
|
<IconButton color="primary" onClick={downloadAsPng}>
|
||||||
|
<DownloadIcon />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
<div className="w-full p-2.5">
|
||||||
|
<div className="mermaid" ref={mermaidRef}></div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<div className="flex w-full justify-center">
|
||||||
|
<NoDataOverlay label="No Activity yet" />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{openFilters && (
|
||||||
<>
|
<>
|
||||||
<div className="flex justify-end">
|
<Dialog
|
||||||
<Tooltip placement="top" title="Refresh Diagram">
|
open={openFilters}
|
||||||
<IconButton color="default" onClick={onRefresh}>
|
keepMounted
|
||||||
<RefreshIcon />
|
fullWidth
|
||||||
</IconButton>
|
maxWidth="lg"
|
||||||
</Tooltip>
|
onClose={toggleFilters}
|
||||||
<Tooltip title="Zoom In" placement="top">
|
>
|
||||||
<IconButton color="primary" onClick={zoomIn}>
|
<DialogTitle>All Event Messages</DialogTitle>
|
||||||
<ZoomInIcon />
|
<DialogContent>
|
||||||
</IconButton>
|
<DialogContentText>
|
||||||
</Tooltip>
|
<div className="flex items-center gap-2.5">
|
||||||
<Tooltip title="Zoom Out" placement="top">
|
<label>Search by Sequence # </label>
|
||||||
<IconButton color="primary" onClick={zoomOut}>
|
<TextField
|
||||||
<ZoomOutIcon />
|
onChange={onSearchBySeqNumber}
|
||||||
</IconButton>
|
size="small"
|
||||||
</Tooltip>
|
variant="outlined"
|
||||||
<Tooltip title="Reset" placement="top">
|
/>
|
||||||
<IconButton color="primary" onClick={resetZoom}>
|
</div>
|
||||||
<ResetIcon />
|
<List className="w-full" component="nav">
|
||||||
</IconButton>
|
{eventMessages
|
||||||
</Tooltip>
|
.filter((_: any, index: number) => {
|
||||||
<Tooltip title="View in Fullscreen" placement="top">
|
return isFilterMatch(index);
|
||||||
<IconButton color="primary" onClick={viewInFullScreen}>
|
})
|
||||||
<FullscreenIcon />
|
.map((message: any, index: number) => {
|
||||||
</IconButton>
|
const {
|
||||||
</Tooltip>
|
msg_type_name: msgType,
|
||||||
<Tooltip title="Download as PNG" placement="top">
|
des_name,
|
||||||
<IconButton color="primary" onClick={downloadAsPng}>
|
src_name,
|
||||||
<DownloadIcon />
|
group,
|
||||||
</IconButton>
|
group_id,
|
||||||
</Tooltip>
|
timestamp,
|
||||||
</div>
|
src_did,
|
||||||
<div className="w-full p-2.5">
|
des_did,
|
||||||
<div className="mermaid" ref={mermaidRef}></div>
|
msg,
|
||||||
</div>
|
} = message;
|
||||||
|
|
||||||
|
const formattedTimeStamp = formatDateTime(timestamp);
|
||||||
|
const IconComponent = iconMatch[msgType];
|
||||||
|
return (
|
||||||
|
<div className="flex items-center gap-5 mb-7">
|
||||||
|
<Chip label={sequenceNr ? sequenceNr : ++index} />
|
||||||
|
<Card className="w-full p-2">
|
||||||
|
<div className="flex justify-between">
|
||||||
|
<div>
|
||||||
|
<span className="font-bold flex gap-2">
|
||||||
|
{IconComponent} {message.msg_type_name}
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
Sender: {src_name} <Chip label={src_did} /> |{" "}
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
Receiver: {des_name} <Chip label={des_did} />{" "}
|
||||||
|
|{" "}
|
||||||
|
</span>
|
||||||
|
<span>Group: {group} | </span>
|
||||||
|
<span>Group ID: {group_id}</span>
|
||||||
|
</div>
|
||||||
|
<span>{formattedTimeStamp}</span>
|
||||||
|
</div>
|
||||||
|
<span className="font-bold">
|
||||||
|
Event Message {sequenceNr ? sequenceNr : index++}
|
||||||
|
</span>
|
||||||
|
<div
|
||||||
|
className="flex"
|
||||||
|
style={{
|
||||||
|
border: "1px solid #f1f1f1",
|
||||||
|
borderRadius: 5,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<pre className="flex-1 p-2">
|
||||||
|
{JSON.stringify(message, null, 2)}
|
||||||
|
</pre>
|
||||||
|
<div className="flex-shrink-0 p-2">
|
||||||
|
<CopyToClipboard textToCopy={message} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</List>
|
||||||
|
</DialogContentText>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button variant="contained" onClick={toggleFilters}>
|
||||||
|
Close
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
</>
|
</>
|
||||||
) : (
|
|
||||||
<div className="flex w-full justify-center">
|
|
||||||
<NoDataOverlay label="No Activity yet" />
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -13,29 +13,17 @@ import { EntityDetails, ISummaryDetails } from "@/types";
|
|||||||
const SummaryDetails = ({
|
const SummaryDetails = ({
|
||||||
entity,
|
entity,
|
||||||
hasRefreshButton,
|
hasRefreshButton,
|
||||||
hasAttachDetach,
|
|
||||||
fake,
|
fake,
|
||||||
onRefresh,
|
onRefresh,
|
||||||
}: ISummaryDetails) => {
|
}: ISummaryDetails) => {
|
||||||
const cardContentRef = useRef(null);
|
const cardContentRef = useRef<HTMLDivElement>(null);
|
||||||
const hasDetails = entity.details && entity.details.length > 0;
|
const hasDetails = entity.details && entity.details.length > 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div
|
<div className="flex items-center justify-between">
|
||||||
style={{
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "space-between",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<h2>{entity.name}</h2>
|
<h2>{entity.name}</h2>
|
||||||
<div>
|
<div>
|
||||||
{hasAttachDetach && (
|
|
||||||
<Button className="mr-6" variant="contained">
|
|
||||||
Attach / Detach
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
{hasRefreshButton && (
|
{hasRefreshButton && (
|
||||||
<Button onClick={onRefresh} variant="contained">
|
<Button onClick={onRefresh} variant="contained">
|
||||||
Refresh
|
Refresh
|
||||||
@@ -46,7 +34,7 @@ const SummaryDetails = ({
|
|||||||
{hasDetails && (
|
{hasDetails && (
|
||||||
<Card variant="outlined">
|
<Card variant="outlined">
|
||||||
<CardHeader
|
<CardHeader
|
||||||
subheader={fake ? "Summary (Fake Data)" : "Summary"}
|
subheader={`Summary ${fake ? "(Fake Data)" : ""}`}
|
||||||
action={<CopyToClipboard contentRef={cardContentRef} />}
|
action={<CopyToClipboard contentRef={cardContentRef} />}
|
||||||
/>
|
/>
|
||||||
<CardContent ref={cardContentRef}>
|
<CardContent ref={cardContentRef}>
|
||||||
|
|||||||
52
pkgs/ui/src/components/summary_card/readme.md
Normal file
52
pkgs/ui/src/components/summary_card/readme.md
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
# SummaryDetails Component
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The `SummaryDetails` component is a flexible UI component designed to display a summary of details related to a specific entity in a card format. It is equipped with optional functionalities such as refreshing the data.
|
||||||
|
|
||||||
|
## Props
|
||||||
|
|
||||||
|
The component accepts the following props:
|
||||||
|
|
||||||
|
1. `entity`: An object representing the entity whose details are to be displayed. It should have a name and details, where details is an array of `EntityDetails` objects.
|
||||||
|
|
||||||
|
2. `hasRefreshButton` (optional): A boolean indicating if a Refresh button should be displayed. If true, the button is shown, allowing the user to refresh the entity details.
|
||||||
|
|
||||||
|
3. `fake` (optional): A boolean indicating if the displayed data is fake. If true, a label '(Fake Data)' is displayed in the card's header.
|
||||||
|
|
||||||
|
4. `onRefresh` (optional): A function to be called when the Refresh button is clicked. It should handle the logic for refreshing the entity details.
|
||||||
|
|
||||||
|
## UI Structure
|
||||||
|
|
||||||
|
- The component starts with a flex container displaying the entity's name and optional button (Refresh) based on the props.
|
||||||
|
- If the entity has details (checked by `hasDetails`), it displays a card containing:
|
||||||
|
- A `CardHeader` with a subheader indicating it's a summary and whether the data is fake.
|
||||||
|
- A `CopyToClipboard` component attached to the card's action, allowing the user to copy the details.
|
||||||
|
- A `CardContent` section listing all the details. Each detail is displayed as a `Typography` component, showing the label and value of each `EntityDetails` item.
|
||||||
|
|
||||||
|
## How to Use
|
||||||
|
|
||||||
|
1. Import the `SummaryDetails` component.
|
||||||
|
2. Create an entity object with a name and details, where details is an array of objects with label and value.
|
||||||
|
3. Optionally, decide if you want the Refresh functionality by setting `hasRefreshButton` to `true`.
|
||||||
|
4. If using the `Refresh` functionality, provide an `onRefresh` function to handle the logic.
|
||||||
|
5. Render the `SummaryDetails` component with the desired props.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
<SummaryDetails
|
||||||
|
entity={{
|
||||||
|
name: "Sample Entity",
|
||||||
|
details: [
|
||||||
|
{ label: "Detail 1", value: "Value 1" },
|
||||||
|
{ label: "Detail 2", value: "Value 2" },
|
||||||
|
// ... more details
|
||||||
|
],
|
||||||
|
}}
|
||||||
|
hasRefreshButton={true}
|
||||||
|
onRefresh={() => {
|
||||||
|
// handle refresh button logic/callback
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
```
|
||||||
@@ -36,9 +36,16 @@ const CustomTable = ({ configuration, data, loading, tkey }: ICustomTable) => {
|
|||||||
|
|
||||||
// cover use case if we want to render a component
|
// cover use case if we want to render a component
|
||||||
if (render) renderedValue = render(value);
|
if (render) renderedValue = render(value);
|
||||||
if (typeof renderedValue === "object" && render === undefined) {
|
|
||||||
|
// catch use case where the value is an object but the render function is not provided in the table config
|
||||||
|
if (
|
||||||
|
typeof value === "object" &&
|
||||||
|
!Array.isArray(value) &&
|
||||||
|
render === undefined
|
||||||
|
) {
|
||||||
console.warn("Missing render function for column " + cellKey);
|
console.warn("Missing render function for column " + cellKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ErrorBoundary>
|
<ErrorBoundary>
|
||||||
<StyledTableCell key={cellKey} align="left">
|
<StyledTableCell key={cellKey} align="left">
|
||||||
|
|||||||
75
pkgs/ui/src/components/table/readme.md
Normal file
75
pkgs/ui/src/components/table/readme.md
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
# CustomTable Component
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The `CustomTable` component is a dynamic and flexible table designed to display data in a structured tabular format. It is highly customizable, allowing specific rendering for different data types and providing a user-friendly display for loading and empty data states.
|
||||||
|
|
||||||
|
## Props
|
||||||
|
|
||||||
|
The component accepts the following props:
|
||||||
|
|
||||||
|
1. `configuration`: An array of `CustomTableConfiguration` objects defining the structure and customization options for table columns, including:
|
||||||
|
|
||||||
|
- `key`: Corresponds to the key in the data objects for the column.
|
||||||
|
- `label`: Text label for the column header.
|
||||||
|
- `render` (optional): A function for custom rendering of the cell's content.
|
||||||
|
- `data`: An array of data objects, each representing a row in the table.
|
||||||
|
- `loading` (optional): If `true`, displays a loading state (skeleton screen).
|
||||||
|
- `tkey`: A unique key for the table, used for constructing unique cell keys.
|
||||||
|
|
||||||
|
## Behavior
|
||||||
|
|
||||||
|
- **Loading State**: Displays a `Skeleton` loader when `loading` is `true`.
|
||||||
|
- **Empty Data State**: Displays a `NoDataOverlay` component with a message if no data is available.
|
||||||
|
- **Data Rendering**:
|
||||||
|
- Dynamically renders cells based on `configuration`.
|
||||||
|
- Handles different data types:
|
||||||
|
- Joins array elements with a comma.
|
||||||
|
- Shows a disabled checkbox for boolean values.
|
||||||
|
- Uses the provided `render` function for custom rendering.
|
||||||
|
- Logs a warning if a cell's value is an object (not an array), and no `render` function is provided.
|
||||||
|
- **Error Handling**: Each cell is wrapped in an `ErrorBoundary` component for graceful error handling.
|
||||||
|
|
||||||
|
## How to Use
|
||||||
|
|
||||||
|
1. Import the `CustomTable` component.
|
||||||
|
2. Define the `configuration` for table columns.
|
||||||
|
3. Provide `data` as an array of objects corresponding to the configuration.
|
||||||
|
4. Optionally, control the loading state with the `loading` prop.
|
||||||
|
5. Provide a unique `tkey` for the table.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import CustomTable from "./CustomTable";
|
||||||
|
|
||||||
|
const tableConfig = [
|
||||||
|
{ key: "name", label: "Name" },
|
||||||
|
{ key: "age", label: "Age" },
|
||||||
|
{
|
||||||
|
key: "isActive",
|
||||||
|
label: "Active",
|
||||||
|
render: (isActive) => (isActive ? "Yes" : "No"),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const tableData = [
|
||||||
|
{ name: "John Doe", age: 30, isActive: true },
|
||||||
|
{ name: "Jane Smith", age: 25, isActive: false },
|
||||||
|
];
|
||||||
|
|
||||||
|
const SomeComponent = () => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<CustomTable
|
||||||
|
configuration={tableConfig}
|
||||||
|
data={tableData}
|
||||||
|
loading={false}
|
||||||
|
tkey="unique-table-key"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SomeComponent;
|
||||||
|
```
|
||||||
@@ -4,7 +4,6 @@ import TableRow from "@mui/material/TableRow";
|
|||||||
|
|
||||||
export const StyledTableCell = styled(TableCell)(({ theme }) => ({
|
export const StyledTableCell = styled(TableCell)(({ theme }) => ({
|
||||||
[`&.${tableCellClasses.head}`]: {
|
[`&.${tableCellClasses.head}`]: {
|
||||||
// backgroundColor: theme.palette.common.black,
|
|
||||||
backgroundColor: "#003258",
|
backgroundColor: "#003258",
|
||||||
color: theme.palette.common.white,
|
color: theme.palette.common.white,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ export const APSummaryDetails = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// AP - 2 Tables Configurations to display labels
|
||||||
|
|
||||||
export const APAttachmentsTableConfig = [
|
export const APAttachmentsTableConfig = [
|
||||||
{
|
{
|
||||||
key: "name",
|
key: "name",
|
||||||
@@ -61,29 +63,9 @@ export const APServiceRepositoryTableConfig = [
|
|||||||
label: "Status",
|
label: "Status",
|
||||||
render: (value: any) => {
|
render: (value: any) => {
|
||||||
let renderedValue: any = "";
|
let renderedValue: any = "";
|
||||||
if (Array.isArray(value.data)) {
|
if (Array.isArray(value.data)) renderedValue = value.data.join(", ");
|
||||||
renderedValue = value.data.join(", ");
|
else console.error("Status is not an array", value);
|
||||||
} else {
|
|
||||||
console.error("Status is not an array", value);
|
|
||||||
}
|
|
||||||
return renderedValue;
|
return renderedValue;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// {
|
|
||||||
// key: "other",
|
|
||||||
// label: "Type",
|
|
||||||
// render: (value: any) => {
|
|
||||||
// let renderedValue: any = "";
|
|
||||||
// if (typeof value === "object") {
|
|
||||||
// const label = Object.keys(value)[0];
|
|
||||||
// const info = value[label];
|
|
||||||
// renderedValue = (
|
|
||||||
// <code>
|
|
||||||
// {label} {info}
|
|
||||||
// </code>
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
// return renderedValue;
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
];
|
];
|
||||||
|
|||||||
112
pkgs/ui/src/config/config.tsx
Normal file
112
pkgs/ui/src/config/config.tsx
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
import AttachmentIcon from "@mui/icons-material/Attachment";
|
||||||
|
import ArticleIcon from "@mui/icons-material/Article";
|
||||||
|
import ConstructionIcon from "@mui/icons-material/Construction";
|
||||||
|
import AssignmentTurnedInIcon from "@mui/icons-material/AssignmentTurnedIn";
|
||||||
|
import RemoveCircleIcon from "@mui/icons-material/RemoveCircle";
|
||||||
|
import AddCircleIcon from "@mui/icons-material/AddCircle";
|
||||||
|
import PageviewIcon from "@mui/icons-material/Pageview";
|
||||||
|
import BuildIcon from "@mui/icons-material/Build";
|
||||||
|
|
||||||
|
// Palette: https://coolors.co/palette/ff9aa2-feb7b1-ffdac0-ffecc4-e2f0cc-b5ead6-b7dbeb-c7ceea
|
||||||
|
|
||||||
|
export const projectConfig = {
|
||||||
|
BASE_URL: "http://localhost:2979/api/v1",
|
||||||
|
GROUPS: {
|
||||||
|
1: {
|
||||||
|
groupName: "Attachment",
|
||||||
|
groupColor: "rgb(255, 154, 162)",
|
||||||
|
groupIcon: AttachmentIcon,
|
||||||
|
messageTypes: [
|
||||||
|
{ id: 1, label: "Attachment Request Send" },
|
||||||
|
{ id: 2, label: "Attachment Request Received" },
|
||||||
|
{ id: 3, label: "Attachment Response Send" },
|
||||||
|
{ id: 4, label: "Attachment Response Received" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
2: {
|
||||||
|
groupName: "Connection Setup",
|
||||||
|
groupColor: "rgb(254, 183, 177)",
|
||||||
|
groupIcon: ConstructionIcon,
|
||||||
|
messageTypes: [
|
||||||
|
{ id: 1, label: "Connection request send" },
|
||||||
|
{ id: 2, label: "Connection request received" },
|
||||||
|
{ id: 3, label: "Connection response send" },
|
||||||
|
{ id: 4, label: "Connection response received" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
3: {
|
||||||
|
groupName: "Presentation",
|
||||||
|
groupColor: "rgb(255, 218, 192)",
|
||||||
|
groupIcon: ArticleIcon,
|
||||||
|
messageTypes: [
|
||||||
|
{ id: 1, label: "Request send" },
|
||||||
|
{ id: 2, label: "Request received" },
|
||||||
|
{ id: 3, label: "Presentation send" },
|
||||||
|
{ id: 4, label: "Presentation received" },
|
||||||
|
{ id: 5, label: "Presentation acknowledged" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
4: {
|
||||||
|
groupName: "DID Resolution",
|
||||||
|
groupColor: "rgb(255, 236, 196)",
|
||||||
|
groupIcon: AssignmentTurnedInIcon,
|
||||||
|
messageTypes: [
|
||||||
|
{ id: 1, label: "DID Resolution Request send" },
|
||||||
|
{ id: 2, label: "DID Resolution Request received" },
|
||||||
|
{ id: 3, label: "DID Resolution Response send" },
|
||||||
|
{ id: 4, label: "DID Resolution Response received" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
5: {
|
||||||
|
groupName: "Service De-registration",
|
||||||
|
groupColor: "rgb(226, 240, 204)",
|
||||||
|
groupIcon: RemoveCircleIcon,
|
||||||
|
messageTypes: [
|
||||||
|
{ id: 1, label: "Service De-registration send" },
|
||||||
|
{ id: 2, label: "Service De-registration received" },
|
||||||
|
{ id: 3, label: "Service De-registration successful send" },
|
||||||
|
{ id: 4, label: "Service De-registration successful received" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
6: {
|
||||||
|
groupName: "Service Registration",
|
||||||
|
groupColor: "rgb(181, 234, 214)",
|
||||||
|
groupIcon: AddCircleIcon,
|
||||||
|
messageTypes: [
|
||||||
|
{ id: 1, label: "Service Registration send" },
|
||||||
|
{ id: 2, label: "Service Registration received" },
|
||||||
|
{ id: 3, label: "Service Registration successful send" },
|
||||||
|
{ id: 4, label: "Service Registration successful received" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
7: {
|
||||||
|
groupName: "Service Discovery",
|
||||||
|
groupColor: "rgb(183, 219, 235)",
|
||||||
|
groupIcon: PageviewIcon,
|
||||||
|
messageTypes: [
|
||||||
|
{ id: 1, label: "Service Discovery send" },
|
||||||
|
{ id: 2, label: "Service Discovery received" },
|
||||||
|
{ id: 3, label: "Service Discovery Result send" },
|
||||||
|
{ id: 4, label: "Service Discovery Result received" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
8: {
|
||||||
|
groupName: "Service Operation",
|
||||||
|
groupColor: "rgb(199, 206, 234)",
|
||||||
|
groupIcon: BuildIcon,
|
||||||
|
messageTypes: [
|
||||||
|
{ id: 1, label: "Service Request Send" },
|
||||||
|
{ id: 2, label: "Service Request Received" },
|
||||||
|
{ id: 3, label: "Service Response Send" },
|
||||||
|
{ id: 4, label: "Service Response Received" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const iconMatch: any = {
|
||||||
|
Attachement: <AttachmentIcon />,
|
||||||
|
Presentation: <ArticleIcon />,
|
||||||
|
"DID Resolution": <AssignmentTurnedInIcon />,
|
||||||
|
"Connection Setup": <ConstructionIcon />,
|
||||||
|
};
|
||||||
@@ -13,7 +13,7 @@ export const DLGSummaryDetails = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
// DLG Resolution Table
|
// DLG - 2 Tables Configurations to display labels
|
||||||
|
|
||||||
export const DLGResolutionDummyData = [
|
export const DLGResolutionDummyData = [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
const BASE_URL = "http://localhost:2979/api/v1";
|
|
||||||
|
|
||||||
// Home View
|
|
||||||
const HOME_VIEW_TABLE = "/get_entities";
|
|
||||||
|
|
||||||
// Access Point
|
|
||||||
const SERVICE_REPOSITORY_URL = "/get_repositories";
|
|
||||||
|
|
||||||
export { BASE_URL, HOME_VIEW_TABLE, SERVICE_REPOSITORY_URL };
|
|
||||||
@@ -25,6 +25,5 @@ export interface ISummaryDetails {
|
|||||||
entity: any;
|
entity: any;
|
||||||
fake?: boolean;
|
fake?: boolean;
|
||||||
hasRefreshButton?: boolean;
|
hasRefreshButton?: boolean;
|
||||||
hasAttachDetach?: boolean;
|
|
||||||
onRefresh?: () => void;
|
onRefresh?: () => void;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
export const formatDateTime = (date: string) => {
|
export const formatDateTime = (date: string | number) => {
|
||||||
const _date = new Date(date);
|
const dateToFormat = typeof date === "number" ? date * 1000 : date;
|
||||||
|
const _date = new Date(dateToFormat);
|
||||||
return _date.toLocaleDateString("en-US", {
|
return _date.toLocaleDateString("en-US", {
|
||||||
year: "numeric",
|
year: "numeric",
|
||||||
month: "long",
|
month: "long",
|
||||||
|
|||||||
Reference in New Issue
Block a user