From 005401db82407d49d2525049bcf92af0f1916358 Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 27 Mar 2024 15:55:02 -0700 Subject: [PATCH 01/25] wip: moving algorithms panel to bottom left toolbar, make sure to condense all possible buttons to keep the toolbar small. Signed-off-by: Alex --- view/src/components/Diagram/Diagram.tsx | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/view/src/components/Diagram/Diagram.tsx b/view/src/components/Diagram/Diagram.tsx index 2deaa42..a91c0ba 100644 --- a/view/src/components/Diagram/Diagram.tsx +++ b/view/src/components/Diagram/Diagram.tsx @@ -489,11 +489,11 @@ function Diagram({ minZoom={0.01} > {initData.legendItems.length > 0 && ( - + )} - + {/*
fitView()}> Fit View @@ -508,7 +508,7 @@ function Diagram({ ) : ( - /* TODO: Implement Add Filter functionality */ + //TODO: Implement Add Filter functionality {}}> Add Filter @@ -517,7 +517,8 @@ function Diagram({ {selectedAutoLayout(autoLayout)} {selectedAlgorithmLayout(algorithmLayout)}
-
+
*/} + {/* Implemented custom interactive button to avoid disabling selection in diagram */} {isInteractive ? : } + + {isInteractive ? : } + Date: Tue, 16 Apr 2024 14:08:41 -0700 Subject: [PATCH 02/25] wip: consolidate toolbar Signed-off-by: Alex --- view/src/components/Diagram/Diagram.tsx | 110 +++++++++++++++--------- 1 file changed, 67 insertions(+), 43 deletions(-) diff --git a/view/src/components/Diagram/Diagram.tsx b/view/src/components/Diagram/Diagram.tsx index a91c0ba..3cbde11 100644 --- a/view/src/components/Diagram/Diagram.tsx +++ b/view/src/components/Diagram/Diagram.tsx @@ -80,6 +80,7 @@ function Diagram({ const { fitView } = useReactFlow(); const { isInteractive, setInteractivity, toggleInteractivity } = useCanvasInteractivity(); + const [showDownloadMenu, setShowDownloadMenu] = useState(true); // Using negative logic here // FIXME: useOnSelectionChange occurs after a selection occurs and will continously running when clicking a node or edge // useOnSelectionChange({ @@ -457,6 +458,18 @@ function Diagram({ return dropDownOptions; }; + /** + * This function toggles the download menu. + * + * @remarks + * + * @param + * + */ + const toggleDownloadMenu = () => { + setShowDownloadMenu(!showDownloadMenu); + }; + return (
- {isInteractive ? : } - - -
- - PNG -
-
- -
- - SVG + +
+ {/* TODO: Style so it looks like icon.png */} + {/*
+ */} +
+
+
+ + {!showDownloadMenu && ( +
+ +
+ + PNG + +
+
+ +
+ + SVG + +
+
+
+ )} Date: Sat, 20 Apr 2024 14:28:47 -0700 Subject: [PATCH 03/25] Add arrow icon to download button to indicate a pop-out menu Signed-off-by: Alex --- view/src/components/Diagram/Diagram.tsx | 27 +++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/view/src/components/Diagram/Diagram.tsx b/view/src/components/Diagram/Diagram.tsx index b6d9936..27d5ba5 100644 --- a/view/src/components/Diagram/Diagram.tsx +++ b/view/src/components/Diagram/Diagram.tsx @@ -479,6 +479,8 @@ function Diagram({ setShowDownloadMenu(!showDownloadMenu); }; + const arrowIconSize = 16; + return (
: }
{/* TODO: Style so it looks like icon.png */} - {/*
- */} -
-
-
+ {/*
+ */} + + +
{!showDownloadMenu && ( From 10b6202927ef0d9ce9136708c6796c681ae9dbf3 Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 21 Apr 2024 14:28:27 -0700 Subject: [PATCH 04/25] wip: build InsertPanel ui component Signed-off-by: Alex --- view/src/components/Diagram/Diagram.tsx | 17 +++++++- view/src/components/Diagram/InsertPanel.tsx | 46 +++++++++++++++++++++ view/src/interfaces/InsertItemType.ts | 7 ++++ 3 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 view/src/components/Diagram/InsertPanel.tsx create mode 100644 view/src/interfaces/InsertItemType.ts diff --git a/view/src/components/Diagram/Diagram.tsx b/view/src/components/Diagram/Diagram.tsx index 27d5ba5..ae93632 100644 --- a/view/src/components/Diagram/Diagram.tsx +++ b/view/src/components/Diagram/Diagram.tsx @@ -25,6 +25,8 @@ import ReactFlow, { getConnectedEdges, } from "reactflow"; +import InsertPanel from "./InsertPanel"; + // Icons import { IconDownload } from "@nasa-jpl/react-stellar"; import LockIcon from "./Icons/Lock"; @@ -34,6 +36,7 @@ import { toPng, toSvg } from "html-to-image"; import Loader from "../shared/Loader"; import ITableData from "../../interfaces/ITableData"; import { LegendItem } from "../../interfaces/LegendItemType"; +import { InsertItem } from "../../interfaces/InsertItemType"; import { VSCodeButton, VSCodeDropdown, @@ -479,7 +482,14 @@ function Diagram({ setShowDownloadMenu(!showDownloadMenu); }; - const arrowIconSize = 16; + const arrowIconSize = 16; // This constant sets the control button dropdown indicator arrow size. + var testInsertItem: InsertItem = { + label: "TestInsertItem", + onItemClicked: () => {console.log("Item was clicked!")}, + icon: + } + + var insertItems: InsertItem[] = [testInsertItem]; return (
+ + + {rightClick && ( diff --git a/view/src/components/Diagram/InsertPanel.tsx b/view/src/components/Diagram/InsertPanel.tsx new file mode 100644 index 0000000..1fe4153 --- /dev/null +++ b/view/src/components/Diagram/InsertPanel.tsx @@ -0,0 +1,46 @@ +import React, { ReactElement } from "react"; + +interface InsertItemProps { + label: string; + onItemClicked: () => void; + icon: ReactElement; +} + +const InsertItem: React.FC = ({ label, onItemClicked, icon }) => { + return ( +
+ { label } + { icon } +
+ ) +} + +interface InsertPanelProps { + components: InsertItemProps[]; + relationships: InsertItemProps[]; +} + +const InsertPanel: React.FC = ({ components, relationships }) => { + return ( +
+ Components +
+ {components.map((component, index) => ( + + ))} +
+ Relationships + {relationships.map((relationship, index) => ( + + ))} +
+ ); +} + +export default InsertPanel; \ No newline at end of file diff --git a/view/src/interfaces/InsertItemType.ts b/view/src/interfaces/InsertItemType.ts new file mode 100644 index 0000000..8de15d0 --- /dev/null +++ b/view/src/interfaces/InsertItemType.ts @@ -0,0 +1,7 @@ +import { ReactElement } from "react" + +export type InsertItem = { + label: string, + onItemClicked: () => void, + icon: ReactElement + } \ No newline at end of file From 052973d742feefe612d3e9fa020322558dee2ddb Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 1 May 2024 13:37:48 -0700 Subject: [PATCH 05/25] wip: build insert panel Signed-off-by: Alex --- view/src/components/Diagram/Diagram.tsx | 9 +- view/src/components/Diagram/InsertPanel.tsx | 98 +++++++++++++-------- view/src/interfaces/InsertItemType.ts | 2 +- 3 files changed, 71 insertions(+), 38 deletions(-) diff --git a/view/src/components/Diagram/Diagram.tsx b/view/src/components/Diagram/Diagram.tsx index ae93632..bccf361 100644 --- a/view/src/components/Diagram/Diagram.tsx +++ b/view/src/components/Diagram/Diagram.tsx @@ -486,10 +486,15 @@ function Diagram({ var testInsertItem: InsertItem = { label: "TestInsertItem", onItemClicked: () => {console.log("Item was clicked!")}, - icon: + icon: } - var insertItems: InsertItem[] = [testInsertItem]; + var insertItems: InsertItem[] = [testInsertItem, testInsertItem, testInsertItem]; return (
void; - icon: ReactElement; + label: string; + icon: ReactElement; + onItemClicked(): void; } -const InsertItem: React.FC = ({ label, onItemClicked, icon }) => { - return ( -
- { label } - { icon } +const InsertItem: React.FC = ({ + label, + icon, + onItemClicked, +}) => { + // TODO: handle onDrag Look at react-beautiful-dnd + // TODO: handle cloning object after dragging + // TODO: handle dropping object after letting go of the mouse + let handleItemClick; + return ( +
+ +
+ ); +}; interface InsertPanelProps { - components: InsertItemProps[]; - relationships: InsertItemProps[]; + components: InsertItemProps[]; + relationships: InsertItemProps[]; } -const InsertPanel: React.FC = ({ components, relationships }) => { - return ( -
- Components -
- {components.map((component, index) => ( - - ))} -
- Relationships - {relationships.map((relationship, index) => ( - - ))} -
- ); -} +const InsertPanel: React.FC = ({ + components, + relationships, +}) => { + // TODO: Remame components to instances + // TODO: Remame relationships to relations + // Refer to http://www.opencaesar.io/oml-tutorials/#tutorial1-create-oml-vocabulary + return ( +
+ Components +
+ {relationships.map((component, index) => ( + + ))} +
+ Relationships + {relationships.map((relationship, index) => ( + + ))} +
+ ); +}; -export default InsertPanel; \ No newline at end of file +export default InsertPanel; diff --git a/view/src/interfaces/InsertItemType.ts b/view/src/interfaces/InsertItemType.ts index 8de15d0..f70e6e9 100644 --- a/view/src/interfaces/InsertItemType.ts +++ b/view/src/interfaces/InsertItemType.ts @@ -4,4 +4,4 @@ export type InsertItem = { label: string, onItemClicked: () => void, icon: ReactElement - } \ No newline at end of file +} \ No newline at end of file From 0c4783707dbf2f5c03274b681ff8ec6d1a793c45 Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 21 May 2024 12:33:31 -0700 Subject: [PATCH 06/25] Rename relationships to relations and components to instances Signed-off-by: Alex --- view/src/components/Diagram/InsertPanel.tsx | 28 ++++++++++----------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/view/src/components/Diagram/InsertPanel.tsx b/view/src/components/Diagram/InsertPanel.tsx index a93d2cb..2163e68 100644 --- a/view/src/components/Diagram/InsertPanel.tsx +++ b/view/src/components/Diagram/InsertPanel.tsx @@ -36,35 +36,33 @@ const InsertItem: React.FC = ({ }; interface InsertPanelProps { - components: InsertItemProps[]; - relationships: InsertItemProps[]; + instances: InsertItemProps[]; + relations: InsertItemProps[]; } const InsertPanel: React.FC = ({ - components, - relationships, + instances, + relations, }) => { - // TODO: Remame components to instances - // TODO: Remame relationships to relations // Refer to http://www.opencaesar.io/oml-tutorials/#tutorial1-create-oml-vocabulary return (
- Components + Instances
- {relationships.map((component, index) => ( + {relations.map((instance, index) => ( ))}
Relationships - {relationships.map((relationship, index) => ( + {relations.map((relation, index) => ( ))}
From 864830379197aa328c38fc238218f0c120c9d3cc Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 21 May 2024 15:21:06 -0700 Subject: [PATCH 07/25] Style insert panel and sub components Signed-off-by: Alex --- view/src/components/Diagram/Diagram.tsx | 6 +-- view/src/components/Diagram/InsertPanel.tsx | 45 ++++++++++++--------- 2 files changed, 30 insertions(+), 21 deletions(-) diff --git a/view/src/components/Diagram/Diagram.tsx b/view/src/components/Diagram/Diagram.tsx index cdcad10..17a5362 100644 --- a/view/src/components/Diagram/Diagram.tsx +++ b/view/src/components/Diagram/Diagram.tsx @@ -501,7 +501,7 @@ function Diagram({ /> } - var insertItems: InsertItem[] = [testInsertItem, testInsertItem, testInsertItem]; + var insertItems: InsertItem[] = [testInsertItem, testInsertItem, testInsertItem, testInsertItem, testInsertItem, testInsertItem]; return (
+ instances={insertItems} + relations={insertItems}/> diff --git a/view/src/components/Diagram/InsertPanel.tsx b/view/src/components/Diagram/InsertPanel.tsx index 2163e68..e2ef4d9 100644 --- a/view/src/components/Diagram/InsertPanel.tsx +++ b/view/src/components/Diagram/InsertPanel.tsx @@ -46,27 +46,36 @@ const InsertPanel: React.FC = ({ }) => { // Refer to http://www.opencaesar.io/oml-tutorials/#tutorial1-create-oml-vocabulary return ( -
- Instances -
- {relations.map((instance, index) => ( - - ))} +
+ + +
+ ); +}; + +const SubPanel: React.FC = ({ + label, + items +}) => { + // Refer to http://www.opencaesar.io/oml-tutorials/#tutorial1-create-oml-vocabulary + return ( +
+
+ {label} +
+ {items.map((item: InsertItemProps) => ( + + ))} +
- Relationships - {relations.map((relation, index) => ( - - ))}
); }; + + export default InsertPanel; From 22e0a1cf833204866be999e4d5fc462b1e3a53bc Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 21 May 2024 15:39:53 -0700 Subject: [PATCH 08/25] Install pragmatic dnd Signed-off-by: Alex --- package-lock.json | 37 ++++++++++++++++++++++++++++++++++++- package.json | 4 +++- yarn.lock | 24 ++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8758f10..dda3247 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "license": "SEE LICENSE IN LICENSE.rmd", "dependencies": { "@actions/core": "^1.10.1", + "@atlaskit/pragmatic-drag-and-drop": "^1.1.9", "@comunica/query-sparql": "^2.10.0", "@emotion/react": "^11.1.5", "@emotion/styled": "^11.1.5", @@ -68,7 +69,8 @@ "use-resize-observer": "^9.1.0", "uuid": "^9.0.0", "uuidv4": "^6.2.13", - "vscode-gradle": "^3.10.1" + "vscode-gradle": "^3.10.1", + "yarn": "^1.22.22" }, "engines": { "vscode": "^1.78.2" @@ -123,6 +125,16 @@ "node": ">=6.0.0" } }, + "node_modules/@atlaskit/pragmatic-drag-and-drop": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@atlaskit/pragmatic-drag-and-drop/-/pragmatic-drag-and-drop-1.1.9.tgz", + "integrity": "sha512-HZkT0mStizzneobq7vINEnEsm7DTu70gaEu0HHSNKv6lkX4tI0h1HoAyDUZqH3xFc5nuhvjdFxygZRzMhs5w+g==", + "dependencies": { + "@babel/runtime": "^7.0.0", + "bind-event-listener": "^3.0.0", + "raf-schd": "^4.0.3" + } + }, "node_modules/@azure/abort-controller": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-1.1.0.tgz", @@ -10099,6 +10111,11 @@ "node": ">=8" } }, + "node_modules/bind-event-listener": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bind-event-listener/-/bind-event-listener-3.0.0.tgz", + "integrity": "sha512-PJvH288AWQhKs2v9zyfYdPzlPqf5bXbGMmhmUIY9x4dAUGIWgomO771oBQNwJnMQSnUIXhKu6sgzpBRXTlvb8Q==" + }, "node_modules/bl": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", @@ -17144,6 +17161,11 @@ } ] }, + "node_modules/raf-schd": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.3.tgz", + "integrity": "sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==" + }, "node_modules/rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", @@ -19858,6 +19880,19 @@ "node": ">=12" } }, + "node_modules/yarn": { + "version": "1.22.22", + "resolved": "https://registry.npmjs.org/yarn/-/yarn-1.22.22.tgz", + "integrity": "sha512-prL3kGtyG7o9Z9Sv8IPfBNrWTDmXB4Qbes8A9rEzt6wkJV8mUvoirjU0Mp3GGAU06Y0XQyA3/2/RQFVuK7MTfg==", + "hasInstallScript": true, + "bin": { + "yarn": "bin/yarn.js", + "yarnpkg": "bin/yarn.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/yauzl": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", diff --git a/package.json b/package.json index d1b329a..d924d59 100644 --- a/package.json +++ b/package.json @@ -264,6 +264,7 @@ }, "dependencies": { "@actions/core": "^1.10.1", + "@atlaskit/pragmatic-drag-and-drop": "^1.1.9", "@comunica/query-sparql": "^2.10.0", "@emotion/react": "^11.1.5", "@emotion/styled": "^11.1.5", @@ -322,7 +323,8 @@ "use-resize-observer": "^9.1.0", "uuid": "^9.0.0", "uuidv4": "^6.2.13", - "vscode-gradle": "^3.10.1" + "vscode-gradle": "^3.10.1", + "yarn": "^1.22.22" }, "overrides": { "react-scripts": { diff --git a/yarn.lock b/yarn.lock index 38b8934..a6ab036 100644 --- a/yarn.lock +++ b/yarn.lock @@ -31,6 +31,15 @@ "@jridgewell/gen-mapping" "^0.3.0" "@jridgewell/trace-mapping" "^0.3.9" +"@atlaskit/pragmatic-drag-and-drop@^1.1.9": + "integrity" "sha512-HZkT0mStizzneobq7vINEnEsm7DTu70gaEu0HHSNKv6lkX4tI0h1HoAyDUZqH3xFc5nuhvjdFxygZRzMhs5w+g==" + "resolved" "https://registry.npmjs.org/@atlaskit/pragmatic-drag-and-drop/-/pragmatic-drag-and-drop-1.1.9.tgz" + "version" "1.1.9" + dependencies: + "@babel/runtime" "^7.0.0" + "bind-event-listener" "^3.0.0" + "raf-schd" "^4.0.3" + "@azure/abort-controller@^1.0.0": "integrity" "sha512-TrRLIoSQVzfAJX9H1JeFjzAoDGcoK1IYX1UImfceTZpsyYfWr09Ss1aHW1y5TrrR3iq6RZLBwJ3E24uwPhwahw==" "resolved" "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-1.1.0.tgz" @@ -5293,6 +5302,11 @@ "resolved" "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz" "version" "2.2.0" +"bind-event-listener@^3.0.0": + "integrity" "sha512-PJvH288AWQhKs2v9zyfYdPzlPqf5bXbGMmhmUIY9x4dAUGIWgomO771oBQNwJnMQSnUIXhKu6sgzpBRXTlvb8Q==" + "resolved" "https://registry.npmjs.org/bind-event-listener/-/bind-event-listener-3.0.0.tgz" + "version" "3.0.0" + "bl@^4.0.3": "integrity" "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==" "resolved" "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz" @@ -8330,6 +8344,11 @@ "resolved" "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz" "version" "1.2.3" +"raf-schd@^4.0.3": + "integrity" "sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==" + "resolved" "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.3.tgz" + "version" "4.0.3" + "rc-motion@^2.0.1": "integrity" "sha512-2xUvo8yGHdOHeQbdI8BtBsCIrWKchEmFEIskf0nmHtJsou+meLd/JE+vnvSX2JxcBrJtXY2LuBpxAOxrbY/wMQ==" "resolved" "https://registry.npmjs.org/rc-motion/-/rc-motion-2.7.3.tgz" @@ -10015,6 +10034,11 @@ "y18n" "^5.0.5" "yargs-parser" "^21.1.1" +"yarn@^1.22.22": + "integrity" "sha512-prL3kGtyG7o9Z9Sv8IPfBNrWTDmXB4Qbes8A9rEzt6wkJV8mUvoirjU0Mp3GGAU06Y0XQyA3/2/RQFVuK7MTfg==" + "resolved" "https://registry.npmjs.org/yarn/-/yarn-1.22.22.tgz" + "version" "1.22.22" + "yauzl@^2.3.1": "integrity" "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==" "resolved" "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz" From 6d4f3e1cdcf92ac812bc25e1c5eebdbfa55c295d Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 22 May 2024 17:13:00 -0700 Subject: [PATCH 09/25] Install pragmatic-dnd Signed-off-by: Alex --- package-lock.json | 21 +++++++++++++++++++++ package.json | 1 + yarn.lock | 19 +++++++++++++++++++ 3 files changed, 41 insertions(+) diff --git a/package-lock.json b/package-lock.json index 8758f10..e91f5ed 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "license": "SEE LICENSE IN LICENSE.rmd", "dependencies": { "@actions/core": "^1.10.1", + "@atlaskit/pragmatic-drag-and-drop": "^1.1.9", "@comunica/query-sparql": "^2.10.0", "@emotion/react": "^11.1.5", "@emotion/styled": "^11.1.5", @@ -123,6 +124,16 @@ "node": ">=6.0.0" } }, + "node_modules/@atlaskit/pragmatic-drag-and-drop": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@atlaskit/pragmatic-drag-and-drop/-/pragmatic-drag-and-drop-1.1.9.tgz", + "integrity": "sha512-HZkT0mStizzneobq7vINEnEsm7DTu70gaEu0HHSNKv6lkX4tI0h1HoAyDUZqH3xFc5nuhvjdFxygZRzMhs5w+g==", + "dependencies": { + "@babel/runtime": "^7.0.0", + "bind-event-listener": "^3.0.0", + "raf-schd": "^4.0.3" + } + }, "node_modules/@azure/abort-controller": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-1.1.0.tgz", @@ -10099,6 +10110,11 @@ "node": ">=8" } }, + "node_modules/bind-event-listener": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bind-event-listener/-/bind-event-listener-3.0.0.tgz", + "integrity": "sha512-PJvH288AWQhKs2v9zyfYdPzlPqf5bXbGMmhmUIY9x4dAUGIWgomO771oBQNwJnMQSnUIXhKu6sgzpBRXTlvb8Q==" + }, "node_modules/bl": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", @@ -17144,6 +17160,11 @@ } ] }, + "node_modules/raf-schd": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.3.tgz", + "integrity": "sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==" + }, "node_modules/rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", diff --git a/package.json b/package.json index d1b329a..00421c5 100644 --- a/package.json +++ b/package.json @@ -264,6 +264,7 @@ }, "dependencies": { "@actions/core": "^1.10.1", + "@atlaskit/pragmatic-drag-and-drop": "^1.1.9", "@comunica/query-sparql": "^2.10.0", "@emotion/react": "^11.1.5", "@emotion/styled": "^11.1.5", diff --git a/yarn.lock b/yarn.lock index 38b8934..77034d7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -31,6 +31,15 @@ "@jridgewell/gen-mapping" "^0.3.0" "@jridgewell/trace-mapping" "^0.3.9" +"@atlaskit/pragmatic-drag-and-drop@^1.1.9": + "integrity" "sha512-HZkT0mStizzneobq7vINEnEsm7DTu70gaEu0HHSNKv6lkX4tI0h1HoAyDUZqH3xFc5nuhvjdFxygZRzMhs5w+g==" + "resolved" "https://registry.npmjs.org/@atlaskit/pragmatic-drag-and-drop/-/pragmatic-drag-and-drop-1.1.9.tgz" + "version" "1.1.9" + dependencies: + "@babel/runtime" "^7.0.0" + "bind-event-listener" "^3.0.0" + "raf-schd" "^4.0.3" + "@azure/abort-controller@^1.0.0": "integrity" "sha512-TrRLIoSQVzfAJX9H1JeFjzAoDGcoK1IYX1UImfceTZpsyYfWr09Ss1aHW1y5TrrR3iq6RZLBwJ3E24uwPhwahw==" "resolved" "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-1.1.0.tgz" @@ -5293,6 +5302,11 @@ "resolved" "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz" "version" "2.2.0" +"bind-event-listener@^3.0.0": + "integrity" "sha512-PJvH288AWQhKs2v9zyfYdPzlPqf5bXbGMmhmUIY9x4dAUGIWgomO771oBQNwJnMQSnUIXhKu6sgzpBRXTlvb8Q==" + "resolved" "https://registry.npmjs.org/bind-event-listener/-/bind-event-listener-3.0.0.tgz" + "version" "3.0.0" + "bl@^4.0.3": "integrity" "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==" "resolved" "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz" @@ -8330,6 +8344,11 @@ "resolved" "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz" "version" "1.2.3" +"raf-schd@^4.0.3": + "integrity" "sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==" + "resolved" "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.3.tgz" + "version" "4.0.3" + "rc-motion@^2.0.1": "integrity" "sha512-2xUvo8yGHdOHeQbdI8BtBsCIrWKchEmFEIskf0nmHtJsou+meLd/JE+vnvSX2JxcBrJtXY2LuBpxAOxrbY/wMQ==" "resolved" "https://registry.npmjs.org/rc-motion/-/rc-motion-2.7.3.tgz" From e43e76ab4011784252ffd04a0751352171d09918 Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 22 May 2024 17:15:12 -0700 Subject: [PATCH 10/25] Remove old click and drag code Signed-off-by: Alex --- view/src/components/Diagram/InsertPanel.tsx | 5 ----- 1 file changed, 5 deletions(-) diff --git a/view/src/components/Diagram/InsertPanel.tsx b/view/src/components/Diagram/InsertPanel.tsx index e2ef4d9..22623bf 100644 --- a/view/src/components/Diagram/InsertPanel.tsx +++ b/view/src/components/Diagram/InsertPanel.tsx @@ -5,13 +5,11 @@ import { Button } from "@nasa-jpl/react-stellar"; interface InsertItemProps { label: string; icon: ReactElement; - onItemClicked(): void; } const InsertItem: React.FC = ({ label, icon, - onItemClicked, }) => { // TODO: handle onDrag Look at react-beautiful-dnd // TODO: handle cloning object after dragging @@ -19,8 +17,6 @@ const InsertItem: React.FC = ({ let handleItemClick; return (
+
+ {label} +
+
+ {icon} +
); }; From 13f20d6253e5f4b9d06f852c38895b5b06505fe8 Mon Sep 17 00:00:00 2001 From: Alex Date: Sat, 25 May 2024 12:28:43 -0700 Subject: [PATCH 13/25] Style instance pane and instance item Signed-off-by: Alex --- view/src/components/Diagram/Diagram.tsx | 36 +++++---- view/src/components/Diagram/InsertPanel.tsx | 81 ++++++++------------- 2 files changed, 50 insertions(+), 67 deletions(-) diff --git a/view/src/components/Diagram/Diagram.tsx b/view/src/components/Diagram/Diagram.tsx index 17a5362..642e1e1 100644 --- a/view/src/components/Diagram/Diagram.tsx +++ b/view/src/components/Diagram/Diagram.tsx @@ -25,7 +25,7 @@ import ReactFlow, { getConnectedEdges, } from "reactflow"; -import InsertPanel from "./InsertPanel"; +import { InsertPanel, InstancePane, InstanceItem } from "./InsertPanel"; // Icons import { IconDownload } from "@nasa-jpl/react-stellar"; @@ -489,19 +489,10 @@ function Diagram({ setShowDownloadMenu(!showDownloadMenu); }; - const arrowIconSize = 16; // This constant sets the control button dropdown indicator arrow size. - var testInsertItem: InsertItem = { - label: "TestInsertItem", - onItemClicked: () => {console.log("Item was clicked!")}, - icon: - } + // This constant sets the control button dropdown indicator arrow size. + const arrowIconSize = 16; - var insertItems: InsertItem[] = [testInsertItem, testInsertItem, testInsertItem, testInsertItem, testInsertItem, testInsertItem]; + var insertItems: string[] = ["Label 1", "Label 2", "Label 3", "Label 4", "Label 5", "Label 6", "Label 7", "Label 8", "Label 9"]; return (
- + + + {insertItems.map((item) => { + return + })} + + +
    +
  • Test
  • +
  • Test
  • +
  • Test
  • +
  • Test
  • +
  • Test
  • +
+
+
diff --git a/view/src/components/Diagram/InsertPanel.tsx b/view/src/components/Diagram/InsertPanel.tsx index 1465c1c..1d5a302 100644 --- a/view/src/components/Diagram/InsertPanel.tsx +++ b/view/src/components/Diagram/InsertPanel.tsx @@ -1,18 +1,23 @@ import React, { ReactElement, useEffect, useRef } from "react"; import "@nasa-jpl/react-stellar/dist/esm/stellar.css"; -import { Button } from "@nasa-jpl/react-stellar"; -import invariant from "tiny-invariant" -import { draggable } from "@atlaskit/pragmatic-drag-and-drop/element/adapter" +import invariant from "tiny-invariant"; +import { draggable } from "@atlaskit/pragmatic-drag-and-drop/element/adapter"; +import Node from "reactflow" interface InsertItemProps { label: string; - icon: ReactElement; + style?: any; } -const InsertItem: React.FC = ({ - label, - icon, -}) => { +const InstanceNode: React.FC = (style) => { + return ( +
+ +
+ ) +} + +export const InstanceItem: React.FC = ({ label, style }) => { // TODO: Use model's node color property instead of hard-coded color // TODO: handle onDrag Look at react-beautiful-dnd // TODO: handle cloning object after dragging @@ -22,66 +27,40 @@ const InsertItem: React.FC = ({ useEffect(() => { const el = ref.current; invariant(el); - - return draggable({ - element: el, - }); + return draggable({element: el}); }, []); + return ( -
-
- {label} -
-
- {icon} +
+
+
+ {label}
+
); }; -interface InsertPanelProps { - instances: InsertItemProps[]; - relations: InsertItemProps[]; -} - -const InsertPanel: React.FC = ({ - instances, - relations, -}) => { +export const InstancePane: React.FC = ({ children }) => { // Refer to http://www.opencaesar.io/oml-tutorials/#tutorial1-create-oml-vocabulary + // h-24 pl-2 flex flex-col items-center space-y-2 overflow-y-auto max-h-[9rem] z-10 return ( -
- - +
+ {"Instance"} +
+ {children} +
); }; -const SubPanel: React.FC = ({ - label, - items -}) => { +export const InsertPanel: React.FC = ({ children }) => { // Refer to http://www.opencaesar.io/oml-tutorials/#tutorial1-create-oml-vocabulary return ( -
-
- {label} -
- {items.map((item: InsertItemProps) => ( - - ))} -
-
+
+ {children}
); }; - - export default InsertPanel; From b496ca04a65330891e91dbe3f9b34dd765c9e78a Mon Sep 17 00:00:00 2001 From: Alex Date: Sat, 25 May 2024 13:14:04 -0700 Subject: [PATCH 14/25] wip: initial relation pane styling Signed-off-by: Alex --- view/src/components/Diagram/Diagram.tsx | 20 ++++++-------- view/src/components/Diagram/InsertPanel.tsx | 29 +++++++++++++++++---- 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/view/src/components/Diagram/Diagram.tsx b/view/src/components/Diagram/Diagram.tsx index 642e1e1..f6b82eb 100644 --- a/view/src/components/Diagram/Diagram.tsx +++ b/view/src/components/Diagram/Diagram.tsx @@ -25,7 +25,7 @@ import ReactFlow, { getConnectedEdges, } from "reactflow"; -import { InsertPanel, InstancePane, InstanceItem } from "./InsertPanel"; +import { InsertPanel, InsertPane, InstanceItem, RelationItem } from "./InsertPanel"; // Icons import { IconDownload } from "@nasa-jpl/react-stellar"; @@ -661,20 +661,16 @@ function Diagram({ /> - + {insertItems.map((item) => { return })} - - -
    -
  • Test
  • -
  • Test
  • -
  • Test
  • -
  • Test
  • -
  • Test
  • -
-
+ + + {insertItems.map((item) => { + return + })} +
diff --git a/view/src/components/Diagram/InsertPanel.tsx b/view/src/components/Diagram/InsertPanel.tsx index 1d5a302..31935f9 100644 --- a/view/src/components/Diagram/InsertPanel.tsx +++ b/view/src/components/Diagram/InsertPanel.tsx @@ -31,22 +31,41 @@ export const InstanceItem: React.FC = ({ label, style }) => { }, []); return ( -
+
- {label} + {label}
); }; -export const InstancePane: React.FC = ({ children }) => { +export const RelationItem: React.FC = ({ label, style }) => { + // TODO: handle onDrag Look at react-beautiful-dnd + // TODO: handle cloning object after dragging + // TODO: handle dropping object after letting go of the mouse + const ref = useRef(null); + + useEffect(() => { + const el = ref.current; + invariant(el); + return draggable({element: el}); + }, []); + + return ( +
+ {label} + +
+ ); +}; + +export const InsertPane: React.FC = ({ label, children }) => { // Refer to http://www.opencaesar.io/oml-tutorials/#tutorial1-create-oml-vocabulary - // h-24 pl-2 flex flex-col items-center space-y-2 overflow-y-auto max-h-[9rem] z-10 return (
- {"Instance"} + {label}
{children}
From c6ef49011d632bcf5dc510ed6f30fa6580b7a785 Mon Sep 17 00:00:00 2001 From: Alex Date: Sat, 25 May 2024 13:33:18 -0700 Subject: [PATCH 15/25] wip: initial relation pane styling Signed-off-by: Alex --- view/src/components/Diagram/Diagram.tsx | 27 ++++++++++--- view/src/components/Diagram/InsertPanel.tsx | 42 +++++++++++++-------- 2 files changed, 47 insertions(+), 22 deletions(-) diff --git a/view/src/components/Diagram/Diagram.tsx b/view/src/components/Diagram/Diagram.tsx index f6b82eb..75f12eb 100644 --- a/view/src/components/Diagram/Diagram.tsx +++ b/view/src/components/Diagram/Diagram.tsx @@ -25,7 +25,12 @@ import ReactFlow, { getConnectedEdges, } from "reactflow"; -import { InsertPanel, InsertPane, InstanceItem, RelationItem } from "./InsertPanel"; +import { + InsertPanel, + InsertPane, + InstanceItem, + RelationItem, +} from "./InsertPanel"; // Icons import { IconDownload } from "@nasa-jpl/react-stellar"; @@ -492,7 +497,17 @@ function Diagram({ // This constant sets the control button dropdown indicator arrow size. const arrowIconSize = 16; - var insertItems: string[] = ["Label 1", "Label 2", "Label 3", "Label 4", "Label 5", "Label 6", "Label 7", "Label 8", "Label 9"]; + var insertItems: string[] = [ + "Label 1", + "Label 2", + "Label 3", + "Label 4", + "Label 5", + "Label 6", + "Label 7", + "Label 8", + "Label 9", + ]; return (
{insertItems.map((item) => { - return + return ; })} - {insertItems.map((item) => { - return + {insertItems.map((item) => { + return ; })} @@ -676,7 +691,7 @@ function Diagram({ {/* Check if rightClick and if layout.contextMenu exists */} - {rightClick && layout.contextMenu &&( + {rightClick && layout.contextMenu && ( = (style) => { - return ( -
- -
- ) -} + return
; +}; export const InstanceItem: React.FC = ({ label, style }) => { // TODO: Use model's node color property instead of hard-coded color @@ -27,14 +23,19 @@ export const InstanceItem: React.FC = ({ label, style }) => { useEffect(() => { const el = ref.current; invariant(el); - return draggable({element: el}); + return draggable({ element: el }); }, []); return (
-
- {label} +
+ + {label} +
@@ -50,13 +51,20 @@ export const RelationItem: React.FC = ({ label, style }) => { useEffect(() => { const el = ref.current; invariant(el); - return draggable({element: el}); + return draggable({ element: el }); }, []); return ( -
- {label} - +
+
+ + {label} + + +
); }; @@ -65,8 +73,10 @@ export const InsertPane: React.FC = ({ label, children }) => { // Refer to http://www.opencaesar.io/oml-tutorials/#tutorial1-create-oml-vocabulary return (
- {label} -
+
+ {label} +
+
{children}
From c0de6a7ac60cf33f2b692078aa5e9ee3dcb64ed2 Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 29 May 2024 11:58:09 -0700 Subject: [PATCH 16/25] Restructure InsertPanel UI components Signed-off-by: Alex --- .vscode/settings.json | 5 ++- view/src/components/Diagram/Diagram.tsx | 10 +++--- view/src/components/Diagram/InsertPanel.tsx | 39 +++++++++++++-------- view/src/interfaces/InsertItemType.ts | 7 ---- 4 files changed, 33 insertions(+), 28 deletions(-) delete mode 100644 view/src/interfaces/InsertItemType.ts diff --git a/.vscode/settings.json b/.vscode/settings.json index 30bf8c2..8b91359 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -7,5 +7,8 @@ "out": true // set this to false to include "out" folder in search results }, // Turn off tsc task auto detection since we have the necessary tasks as npm scripts - "typescript.tsc.autoDetect": "off" + "typescript.tsc.autoDetect": "off", + "cSpell.words": [ + "insertable" + ] } \ No newline at end of file diff --git a/view/src/components/Diagram/Diagram.tsx b/view/src/components/Diagram/Diagram.tsx index 75f12eb..855d832 100644 --- a/view/src/components/Diagram/Diagram.tsx +++ b/view/src/components/Diagram/Diagram.tsx @@ -28,8 +28,9 @@ import ReactFlow, { import { InsertPanel, InsertPane, - InstanceItem, - RelationItem, + InstanceInsertItem, + RelationInsertItem, + DefaultRelationIcon, } from "./InsertPanel"; // Icons @@ -41,7 +42,6 @@ import { toPng, toSvg } from "html-to-image"; import Loader from "../shared/Loader"; import ITableData from "../../interfaces/ITableData"; import { LegendItem } from "../../interfaces/LegendItemType"; -import { InsertItem } from "../../interfaces/InsertItemType"; import { VSCodeButton, VSCodeDropdown, @@ -678,12 +678,12 @@ function Diagram({ {insertItems.map((item) => { - return ; + return ; })} {insertItems.map((item) => { - return ; + return ; })} diff --git a/view/src/components/Diagram/InsertPanel.tsx b/view/src/components/Diagram/InsertPanel.tsx index 410d41f..7b1e701 100644 --- a/view/src/components/Diagram/InsertPanel.tsx +++ b/view/src/components/Diagram/InsertPanel.tsx @@ -4,22 +4,34 @@ import invariant from "tiny-invariant"; import { draggable } from "@atlaskit/pragmatic-drag-and-drop/element/adapter"; import Node from "reactflow"; -interface InsertItemProps { +interface InstanceInsertItemProps { label: string; - style?: any; + style?: string; } -const InstanceNode: React.FC = (style) => { - return
; -}; +interface RelationInsertItemProps { + label: string; + icon: React.ReactElement +} -export const InstanceItem: React.FC = ({ label, style }) => { +// A default icon for a RelationInsertItem +export const DefaultRelationIcon: React.ReactElement = + +/* + * React component `InstanceInsertItem` is a visual representation of an insertable instance that a user can drag from the instance pane of the instance panel and drop into the diagram view. + * + * @param {string} label - String label for the instance + * @param {string} style - TailwindCSS style to specify style attributes for the InstanceNode + */ +export const InstanceInsertItem: React.FC = ({ label, style }) => { // TODO: Use model's node color property instead of hard-coded color // TODO: handle onDrag Look at react-beautiful-dnd // TODO: handle cloning object after dragging // TODO: handle dropping object after letting go of the mouse - const ref = useRef(null); + const ref = useRef(null); // ref for dragging + const defaultNodeStyle = "bg-[#ff0000]" + // Enable dragging of element useEffect(() => { const el = ref.current; invariant(el); @@ -30,7 +42,7 @@ export const InstanceItem: React.FC = ({ label, style }) => {
@@ -42,12 +54,10 @@ export const InstanceItem: React.FC = ({ label, style }) => { ); }; -export const RelationItem: React.FC = ({ label, style }) => { - // TODO: handle onDrag Look at react-beautiful-dnd - // TODO: handle cloning object after dragging - // TODO: handle dropping object after letting go of the mouse +export const RelationInsertItem: React.FC = ({ label, icon }) => { + // TODO: Find a better way to handle icons const ref = useRef(null); - + useEffect(() => { const el = ref.current; invariant(el); @@ -63,7 +73,7 @@ export const RelationItem: React.FC = ({ label, style }) => { {label} - + {icon}
); @@ -84,7 +94,6 @@ export const InsertPane: React.FC = ({ label, children }) => { }; export const InsertPanel: React.FC = ({ children }) => { - // Refer to http://www.opencaesar.io/oml-tutorials/#tutorial1-create-oml-vocabulary return (
{children} diff --git a/view/src/interfaces/InsertItemType.ts b/view/src/interfaces/InsertItemType.ts deleted file mode 100644 index f70e6e9..0000000 --- a/view/src/interfaces/InsertItemType.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { ReactElement } from "react" - -export type InsertItem = { - label: string, - onItemClicked: () => void, - icon: ReactElement -} \ No newline at end of file From 78e399dd5d8f17373c06917b31f028c0ee5a3b69 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 30 May 2024 15:37:13 -0700 Subject: [PATCH 17/25] Add highlighting to draggable elements Signed-off-by: Alex --- view/src/components/Diagram/InsertPanel.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/view/src/components/Diagram/InsertPanel.tsx b/view/src/components/Diagram/InsertPanel.tsx index 7b1e701..594dc3c 100644 --- a/view/src/components/Diagram/InsertPanel.tsx +++ b/view/src/components/Diagram/InsertPanel.tsx @@ -39,7 +39,7 @@ export const InstanceInsertItem: React.FC = ({ label, s }, []); return ( -
+
= ({ label, i return (
From aa55cdc703ac143290ebbfbbd7e7a93c03d2f390 Mon Sep 17 00:00:00 2001 From: greypilgrim Date: Thu, 30 May 2024 22:48:37 +0000 Subject: [PATCH 18/25] Change on hover for instance Signed-off-by: greypilgrim --- view/src/components/Diagram/InsertPanel.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/view/src/components/Diagram/InsertPanel.tsx b/view/src/components/Diagram/InsertPanel.tsx index 594dc3c..9dff111 100644 --- a/view/src/components/Diagram/InsertPanel.tsx +++ b/view/src/components/Diagram/InsertPanel.tsx @@ -39,7 +39,7 @@ export const InstanceInsertItem: React.FC = ({ label, s }, []); return ( -
+
Date: Tue, 4 Jun 2024 15:11:06 -0700 Subject: [PATCH 19/25] add insert panel component with relations data from OML model Signed-off-by: Alex --- commands/src/commands.ts | 13 ++++ commands/src/tablePanelMessageHandler.ts | 8 +++ .../data-manager/getAllElementRelations.ts | 59 +++++++++++++++++++ .../src/sparql/queries/getAllRelations.ts | 22 +++++++ view/src/components/Diagram/Diagram.tsx | 12 ++-- view/src/components/Diagram/InsertPanel.tsx | 4 +- view/src/pages/DiagramView.tsx | 15 +++++ 7 files changed, 127 insertions(+), 6 deletions(-) create mode 100644 controller/src/sparql/data-manager/getAllElementRelations.ts create mode 100644 controller/src/sparql/queries/getAllRelations.ts diff --git a/commands/src/commands.ts b/commands/src/commands.ts index 4af084d..ea1d9cc 100644 --- a/commands/src/commands.ts +++ b/commands/src/commands.ts @@ -18,6 +18,8 @@ export enum Commands { GET_ELEMENT_RELATIONS = 'getElementRelations', // This differs to the GET_ELEMENT_RELATIONS because it grabs the predicate/verb and object instead of the subject of the selected element GET_ELEMENT_RELATIONS_TOTAL = 'getElementRelationsTotal', + // This differs from GET_ELEMENT_RELANTIONS_TOTAL because it gets all relations in OML Model not just a selected element + GET_ALL_ELEMENT_RELATIONS = 'getAllElementRelations', EXECUTE_CREATE_ELEMENTS = 'executeCreateElements', EXECUTE_DELETE_ELEMENTS = 'executeDeleteElements', CREATE_FCR = 'createFCR', @@ -49,6 +51,8 @@ export enum Commands { LOADED_ELEMENT_RELATIONS = 'loadedElementRelations', // This differs to the LOADED_ELEMENT_RELATIONS because it loads the predicate/verb and object instead of the subject of the selected element LOADED_ELEMENT_RELATIONS_TOTAL = 'loadedElementRelationsTotal', + // This differs from LOADED_ELEMENT_RELATIONS_TOTAL because it loads all relations in OML Model not just a selected element + LOADED_ALL_ELEMENT_RELATIONS = 'loadedAllElementRelations', DELETED_ELEMENTS = 'deletedElements', CREATED_ELEMENT = 'createdElement', CLONED_ELEMENTS = 'clonedElements', @@ -94,6 +98,9 @@ export type CommandStructures = { payload: { webviewPath: string; iriArray: string[]; labelArray?: string[] }; wizardId?: string; }; + [Commands.GET_ALL_ELEMENT_RELATIONS]: { + payload: { webviewPath: string }; + }; [Commands.EXECUTE_DELETE_ELEMENTS]: { payload: { webviewPath: string; IRIsToDelete: ITableData[] }; wizardId?: string; @@ -180,6 +187,12 @@ export type CommandStructures = { relations?: Record[]; }; }; + [Commands.LOADED_ALL_ELEMENT_RELATIONS]: { + errorMessage?: string; + payload: { + relations?: string[]; + }; + }; [Commands.DELETED_ELEMENTS]: { errorMessage?: string; wizardId: string; diff --git a/commands/src/tablePanelMessageHandler.ts b/commands/src/tablePanelMessageHandler.ts index 3cfffb9..42d415a 100644 --- a/commands/src/tablePanelMessageHandler.ts +++ b/commands/src/tablePanelMessageHandler.ts @@ -6,6 +6,7 @@ import { SparqlClient } from "../../controller/src/sparql/SparqlClient"; import { getElementRelations } from "../../controller/src/sparql/data-manager/getElementRelations"; import { executeDeleteElements } from "../../controller/src/sparql/data-manager/executeDeleteElements"; import { getElementRelationsTotal } from "../../controller/src/sparql/data-manager/getElementRelationsTotal"; +import { getAllElementRelations } from "../../controller/src/sparql/data-manager/getAllElementRelations"; /** * Handles commands that are sent to a Editor (Table, Tree, or Diagram) @@ -129,6 +130,13 @@ export function handleTablePanelMessage( ) break; + case Commands.GET_ALL_ELEMENT_RELATIONS: + specificMessage = message as CommandStructures[Commands.GET_ALL_ELEMENT_RELATIONS]; + const { webviewPath: relationWebviewPath } = specificMessage.payload; + + // Refer to the CommandStructures[Commands.GET_ALL_ELEMENT_RELATIONS] to see how the parameters are structured + getAllElementRelations(specificMessage.payload.webviewPath); + case Commands.CREATE_FCR: specificMessage = message as CommandStructures[Commands.CREATE_FCR]; const fcrPayload = specificMessage.payload; diff --git a/controller/src/sparql/data-manager/getAllElementRelations.ts b/controller/src/sparql/data-manager/getAllElementRelations.ts new file mode 100644 index 0000000..c5caa05 --- /dev/null +++ b/controller/src/sparql/data-manager/getAllElementRelations.ts @@ -0,0 +1,59 @@ +import * as vscode from "vscode"; +import { TablePanel } from "../../panels/TablePanel"; +import { Commands } from "../../../../commands/src/commands"; +import { SparqlClient } from "../SparqlClient"; +import { getAllRelations } from "../queries/getAllRelations"; + +/** + * This SPARQL query gets all distinct relations from a given OML model and sends them through a controller command. + * + * @remarks + * For more information on OML relations please refer to the official documentation found {@link http://www.opencaesar.io/oml/#Relations | here} + * + * For more information on the postMessage controller command please refer to the official documentation found {@link https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage | here} + * + * @returns + * + */ +export const getAllElementRelations = async ( + webviewPath: string +): Promise => { + try { + const relations_query = getAllRelations(); + const relations_data = await SparqlClient(relations_query, "query"); + + // Get all relation values + const relations: string[] = relations_data.map( + (relation: Record) => { + // We only want values because the record will look like verb: relation_value + // We're only grabbing the verb from the key value pair + // If the relation.verb is not undefined then return it else return a blank string + return relation.verb.split('/').pop() ?? ""; + } + ); + + // Send data to current webview + TablePanel.currentPanels.get(webviewPath)?.sendMessage({ + command: Commands.LOADED_ALL_ELEMENT_RELATIONS, + payload: { + relations: relations, + }, + }); + } catch (error) { + if (error instanceof Error) { + vscode.window.showErrorMessage(`Error: ${error.message}`); + TablePanel.currentPanels.get(webviewPath)?.sendMessage({ + command: Commands.LOADED_ALL_ELEMENT_RELATIONS, + payload: {}, + errorMessage: `Error: ${error.message}`, + }); + } else { + vscode.window.showErrorMessage(`An unknown error occurred: ${error}`); + TablePanel.currentPanels.get(webviewPath)?.sendMessage({ + command: Commands.LOADED_ALL_ELEMENT_RELATIONS, + payload: {}, + errorMessage: `An unknown error occurred: ${error}`, + }); + } + } +}; \ No newline at end of file diff --git a/controller/src/sparql/queries/getAllRelations.ts b/controller/src/sparql/queries/getAllRelations.ts new file mode 100644 index 0000000..5e42014 --- /dev/null +++ b/controller/src/sparql/queries/getAllRelations.ts @@ -0,0 +1,22 @@ +/** + * This SPARQL query gets all relations from a given OML model + * + * @remarks + * For more information on OML relations please refer to the official documentation found {@link http://www.opencaesar.io/oml/#Relations | here} + * + * For more information on SPARQL query `regex` and `str` please refer to the official documentation found {@link https://www.w3.org/TR/sparql11-query/ | here} + * + * @returns SPARQL select query string + * + */ + +export function getAllRelations(): string { + return `SELECT DISTINCT ?verb + WHERE { + ?subject ?verb ?object . + FILTER regex(str(?subject), "description", "i") + FILTER regex(str(?verb), "vocabulary", "i") + } + ORDER BY ?verb`; + } + \ No newline at end of file diff --git a/view/src/components/Diagram/Diagram.tsx b/view/src/components/Diagram/Diagram.tsx index 855d832..64b6afa 100644 --- a/view/src/components/Diagram/Diagram.tsx +++ b/view/src/components/Diagram/Diagram.tsx @@ -61,6 +61,8 @@ const nodeTypes = { function Diagram({ initData, + instances, + relations, webviewPath, hasFilter, clearFilter = () => {}, @@ -76,6 +78,8 @@ function Diagram({ edges: Edge[]; legendItems: LegendItem[]; }; + instances: string[]; + relations: string[]; webviewPath: string; hasFilter: boolean; clearFilter: Function; @@ -677,13 +681,13 @@ function Diagram({ - {insertItems.map((item) => { - return ; + {instances.map((instance: string) => { + return ; })} - {insertItems.map((item) => { - return ; + {relations.map((relation: string) => { + return ; })} diff --git a/view/src/components/Diagram/InsertPanel.tsx b/view/src/components/Diagram/InsertPanel.tsx index 9dff111..7969778 100644 --- a/view/src/components/Diagram/InsertPanel.tsx +++ b/view/src/components/Diagram/InsertPanel.tsx @@ -39,8 +39,8 @@ export const InstanceInsertItem: React.FC = ({ label, s }, []); return ( -
-
+
+
{ }>({ iris: [], filterObject: null }); const [errorMessage, setErrorMessage] = useState(""); const [isLoading, setIsLoading] = useState(true); + const [instances, setInstances] = useState([""]); + const [relations, setRelations] = useState([""]); useEffect(() => { // Only start fetching data when context is loaded @@ -71,6 +73,13 @@ const DiagramView: React.FC = () => { setDiagramLayout(layout); setWebviewPath(webviewPath); + postMessage({ + command: Commands.GET_ALL_ELEMENT_RELATIONS, + payload: { + webviewPath: webviewPath, + }, + }); + postMessage({ command: Commands.GENERATE_TABLE_DATA, payload: { @@ -178,6 +187,10 @@ const DiagramView: React.FC = () => { command: Commands.REFRESH_TABLE_DATA, }); break; + + case Commands.LOADED_ALL_ELEMENT_RELATIONS: + specificMessage = message as CommandStructures[Commands.LOADED_ALL_ELEMENT_RELATIONS]; + setRelations(message.payload.relations) } }; window.addEventListener("message", handler); @@ -266,6 +279,8 @@ const DiagramView: React.FC = () => { 0} clearFilter={() => setFilter({ iris: [], filterObject: null })} From 44a6052160f22d6f3207f1453c79d574d4a54dbe Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 4 Jun 2024 19:50:29 -0700 Subject: [PATCH 20/25] add insert panel component with instance data from OML model Signed-off-by: Alex --- commands/src/commands.ts | 92 ++++++++++--------- commands/src/tablePanelMessageHandler.ts | 26 ++++-- controller/src/extension.ts | 2 - .../data-manager/getAllElementRelations.ts | 20 ++-- .../data-manager/getAllInstanceCategories.ts | 57 ++++++++++++ .../src/sparql/queries/getAllInstances.ts | 21 +++++ .../src/sparql/queries/getAllRelations.ts | 7 +- .../src/sparql/queries/getIriRelations.ts | 6 +- view/src/components/Diagram/Diagram.tsx | 7 +- view/src/components/Diagram/InsertPanel.tsx | 28 ++++-- view/src/pages/DiagramView.tsx | 39 +++++--- 11 files changed, 214 insertions(+), 91 deletions(-) create mode 100644 controller/src/sparql/data-manager/getAllInstanceCategories.ts create mode 100644 controller/src/sparql/queries/getAllInstances.ts diff --git a/commands/src/commands.ts b/commands/src/commands.ts index ea1d9cc..21498b7 100644 --- a/commands/src/commands.ts +++ b/commands/src/commands.ts @@ -7,22 +7,23 @@ export enum Commands { INFORM = "inform", // Table Panel Commands - CREATE_TABLE = 'createTable', - ROW_CLICKED = 'rowClicked', - HIDE_PROPERTIES = 'hideProperties', - ASK_FOR_VIEWPOINTS = 'askForViewpoints', - ASK_FOR_COMMANDS = 'askForCommands', - GENERATE_TABLE_DATA = 'generateTableData', - UPDATE_CM_STATE = 'updateCmState', - REFRESH_TABLE_DATA = 'refreshTableData', - GET_ELEMENT_RELATIONS = 'getElementRelations', + CREATE_TABLE = "createTable", + ROW_CLICKED = "rowClicked", + HIDE_PROPERTIES = "hideProperties", + ASK_FOR_VIEWPOINTS = "askForViewpoints", + ASK_FOR_COMMANDS = "askForCommands", + GENERATE_TABLE_DATA = "generateTableData", + UPDATE_CM_STATE = "updateCmState", + REFRESH_TABLE_DATA = "refreshTableData", + GET_ELEMENT_RELATIONS = "getElementRelations", // This differs to the GET_ELEMENT_RELATIONS because it grabs the predicate/verb and object instead of the subject of the selected element - GET_ELEMENT_RELATIONS_TOTAL = 'getElementRelationsTotal', + GET_ELEMENT_RELATIONS_TOTAL = "getElementRelationsTotal", // This differs from GET_ELEMENT_RELANTIONS_TOTAL because it gets all relations in OML Model not just a selected element - GET_ALL_ELEMENT_RELATIONS = 'getAllElementRelations', - EXECUTE_CREATE_ELEMENTS = 'executeCreateElements', - EXECUTE_DELETE_ELEMENTS = 'executeDeleteElements', - CREATE_FCR = 'createFCR', + GET_ALL_ELEMENT_RELATIONS = "getAllElementRelations", + GET_ALL_INSTANCE_CATEGORIES = "getAllInstanceCategories", + EXECUTE_CREATE_ELEMENTS = "executeCreateElements", + EXECUTE_DELETE_ELEMENTS = "executeDeleteElements", + CREATE_FCR = "createFCR", // Property Panel Commands ASK_FOR_PROPERTIES = "askForProperties", @@ -41,29 +42,29 @@ export enum Commands { PING_TRIPLESTORE_TASK = "pingTriplestoreTask", // Extension To Table Panel Commands - UPDATE_LOCAL_VALUE = 'updateLocalValue', - SEND_VIEWPOINTS = 'sendViewpoints', - SEND_COMMANDS = 'sendCommands', - OPEN_WIZARD = 'openWizard', - CREATE_FILTERED_DIAGRAM = 'createFilteredDiagram', - LOADED_PROPERTY_SHEET = 'loadedPropertySheet', - LOADED_TABLE_DATA = 'loadedTableData', - LOADED_ELEMENT_RELATIONS = 'loadedElementRelations', + UPDATE_LOCAL_VALUE = "updateLocalValue", + SEND_VIEWPOINTS = "sendViewpoints", + SEND_COMMANDS = "sendCommands", + OPEN_WIZARD = "openWizard", + CREATE_FILTERED_DIAGRAM = "createFilteredDiagram", + LOADED_PROPERTY_SHEET = "loadedPropertySheet", + LOADED_TABLE_DATA = "loadedTableData", + LOADED_ELEMENT_RELATIONS = "loadedElementRelations", // This differs to the LOADED_ELEMENT_RELATIONS because it loads the predicate/verb and object instead of the subject of the selected element - LOADED_ELEMENT_RELATIONS_TOTAL = 'loadedElementRelationsTotal', + LOADED_ELEMENT_RELATIONS_TOTAL = "loadedElementRelationsTotal", // This differs from LOADED_ELEMENT_RELATIONS_TOTAL because it loads all relations in OML Model not just a selected element - LOADED_ALL_ELEMENT_RELATIONS = 'loadedAllElementRelations', - DELETED_ELEMENTS = 'deletedElements', - CREATED_ELEMENT = 'createdElement', - CLONED_ELEMENTS = 'clonedElements', - SHOW_PROPERTIES = 'showProperties', + LOADED_ALL_ELEMENT_RELATIONS = "loadedAllElementRelations", + LOADED_ALL_INSTANCE_CATEGORIES = "loadedAllInstanceCategories", + DELETED_ELEMENTS = "deletedElements", + CREATED_ELEMENT = "createdElement", + CLONED_ELEMENTS = "clonedElements", + SHOW_PROPERTIES = "showProperties", // Context Menu to Triplestore. All crud commands - CREATE_QUERY = 'createQuery', - READ_QUERY = 'readQuery', - UPDATE_QUERY = 'updateQuery', - DELETE_QUERY = 'deleteQuery', - + CREATE_QUERY = "createQuery", + READ_QUERY = "readQuery", + UPDATE_QUERY = "updateQuery", + DELETE_QUERY = "deleteQuery", } export type CommandStructures = { @@ -101,6 +102,9 @@ export type CommandStructures = { [Commands.GET_ALL_ELEMENT_RELATIONS]: { payload: { webviewPath: string }; }; + [Commands.GET_ALL_INSTANCE_CATEGORIES]: { + payload: { webviewPath: string }; + }; [Commands.EXECUTE_DELETE_ELEMENTS]: { payload: { webviewPath: string; IRIsToDelete: ITableData[] }; wizardId?: string; @@ -147,10 +151,10 @@ export type CommandStructures = { }; [Commands.UPDATE_LOCAL_VALUE]: {}; [Commands.SEND_VIEWPOINTS]: { - payload: { [filename: string]: Record | any[] } + payload: { [filename: string]: Record | any[] }; }; [Commands.SEND_COMMANDS]: { - payload: { [filename: string]: Record | any[] } + payload: { [filename: string]: Record | any[] }; }; [Commands.OPEN_WIZARD]: { payload: { @@ -193,6 +197,12 @@ export type CommandStructures = { relations?: string[]; }; }; + [Commands.LOADED_ALL_INSTANCE_CATEGORIES]: { + errorMessage?: string; + payload: { + instances?: string[]; + }; + }; [Commands.DELETED_ELEMENTS]: { errorMessage?: string; wizardId: string; @@ -218,21 +228,21 @@ export type CommandStructures = { }; [Commands.CREATE_QUERY]: { query: string; - selectedElements?: string[] + selectedElements?: string[]; }; [Commands.READ_QUERY]: { query: string; - selectedElements?: string[] + selectedElements?: string[]; }; [Commands.UPDATE_QUERY]: { query: string; - selectedElements?: string[] - before_parameters?: Object - after_parameters?: Object + selectedElements?: string[]; + before_parameters?: Object; + after_parameters?: Object; }; [Commands.DELETE_QUERY]: { query: string; - selectedElements?: string[] + selectedElements?: string[]; }; }; diff --git a/commands/src/tablePanelMessageHandler.ts b/commands/src/tablePanelMessageHandler.ts index 42d415a..c687b1d 100644 --- a/commands/src/tablePanelMessageHandler.ts +++ b/commands/src/tablePanelMessageHandler.ts @@ -7,6 +7,7 @@ import { getElementRelations } from "../../controller/src/sparql/data-manager/ge import { executeDeleteElements } from "../../controller/src/sparql/data-manager/executeDeleteElements"; import { getElementRelationsTotal } from "../../controller/src/sparql/data-manager/getElementRelationsTotal"; import { getAllElementRelations } from "../../controller/src/sparql/data-manager/getAllElementRelations"; +import { getAllInstanceCategories } from "../../controller/src/sparql/data-manager/getAllInstanceCategories"; /** * Handles commands that are sent to a Editor (Table, Tree, or Diagram) @@ -102,7 +103,7 @@ export function handleTablePanelMessage( specificMessage.payload.labelArray ); break; - + case Commands.GET_ELEMENT_RELATIONS_TOTAL: specificMessage = message as CommandStructures[Commands.GET_ELEMENT_RELATIONS_TOTAL]; @@ -122,21 +123,30 @@ export function handleTablePanelMessage( const { webviewPath: delWebviewPath, IRIsToDelete = [] } = specificMessage.payload; - // Refer to the CommandStructures[Commands.EXECUTE_DELETE_ELEMENTS] to see how the parameters are structured - executeDeleteElements( - specificMessage.payload.webviewPath, - specificMessage.wizardId, - specificMessage.payload.IRIsToDelete, - ) + // Refer to the CommandStructures[Commands.EXECUTE_DELETE_ELEMENTS] to see how the parameters are structured + executeDeleteElements( + specificMessage.payload.webviewPath, + specificMessage.wizardId, + specificMessage.payload.IRIsToDelete + ); break; case Commands.GET_ALL_ELEMENT_RELATIONS: - specificMessage = message as CommandStructures[Commands.GET_ALL_ELEMENT_RELATIONS]; + specificMessage = + message as CommandStructures[Commands.GET_ALL_ELEMENT_RELATIONS]; const { webviewPath: relationWebviewPath } = specificMessage.payload; // Refer to the CommandStructures[Commands.GET_ALL_ELEMENT_RELATIONS] to see how the parameters are structured getAllElementRelations(specificMessage.payload.webviewPath); + case Commands.GET_ALL_INSTANCE_CATEGORIES: + specificMessage = + message as CommandStructures[Commands.GET_ALL_INSTANCE_CATEGORIES]; + const { webviewPath: instanceWebviewPath } = specificMessage.payload; + + // Refer to the CommandStructures[Commands.GET_ALL_ELEMENT_RELATIONS] to see how the parameters are structured + getAllInstanceCategories(specificMessage.payload.webviewPath); + case Commands.CREATE_FCR: specificMessage = message as CommandStructures[Commands.CREATE_FCR]; const fcrPayload = specificMessage.payload; diff --git a/controller/src/extension.ts b/controller/src/extension.ts index fcd27de..8c80c08 100644 --- a/controller/src/extension.ts +++ b/controller/src/extension.ts @@ -514,5 +514,3 @@ export function activate(context: vscode.ExtensionContext) { function cloneSelectedRows(context: Record) { throw new Error("Function not implemented."); } - - diff --git a/controller/src/sparql/data-manager/getAllElementRelations.ts b/controller/src/sparql/data-manager/getAllElementRelations.ts index c5caa05..5baf823 100644 --- a/controller/src/sparql/data-manager/getAllElementRelations.ts +++ b/controller/src/sparql/data-manager/getAllElementRelations.ts @@ -16,22 +16,22 @@ import { getAllRelations } from "../queries/getAllRelations"; * */ export const getAllElementRelations = async ( - webviewPath: string + webviewPath: string ): Promise => { try { const relations_query = getAllRelations(); const relations_data = await SparqlClient(relations_query, "query"); - + // Get all relation values const relations: string[] = relations_data.map( - (relation: Record) => { - // We only want values because the record will look like verb: relation_value - // We're only grabbing the verb from the key value pair - // If the relation.verb is not undefined then return it else return a blank string - return relation.verb.split('/').pop() ?? ""; - } + (relation: Record) => { + // We only want values because the record will look like verb: relation_value + // We're only grabbing the verb from the key value pair + // If the relation.verb is not undefined then return it else return a blank string + return relation.verb.split("/").pop() ?? ""; + } ); - + // Send data to current webview TablePanel.currentPanels.get(webviewPath)?.sendMessage({ command: Commands.LOADED_ALL_ELEMENT_RELATIONS, @@ -56,4 +56,4 @@ export const getAllElementRelations = async ( }); } } -}; \ No newline at end of file +}; diff --git a/controller/src/sparql/data-manager/getAllInstanceCategories.ts b/controller/src/sparql/data-manager/getAllInstanceCategories.ts new file mode 100644 index 0000000..05cd972 --- /dev/null +++ b/controller/src/sparql/data-manager/getAllInstanceCategories.ts @@ -0,0 +1,57 @@ +import * as vscode from "vscode"; +import { TablePanel } from "../../panels/TablePanel"; +import { Commands } from "../../../../commands/src/commands"; +import { SparqlClient } from "../SparqlClient"; +import { getAllInstances } from "../queries/getAllInstances"; + +/** + * This SPARQL query gets all distinct instances from a given OML model and sends them through a controller command. + * + * @remarks + * For more information on OML instances please refer to the official documentation found {@link http://www.opencaesar.io/oml/#Instances-LR | here} + * + * For more information on the postMessage controller command please refer to the official documentation found {@link https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage | here} + * + * @returns + * + */ +export const getAllInstanceCategories = async ( + webviewPath: string +): Promise => { + try { + const instance_query = getAllInstances(); + const instance_data = await SparqlClient(instance_query, "query"); + // Get all instance values + const instances: string[] = instance_data.map( + (instance: Record) => { + // We only want values because the record will look like verb: instance_value + // We're only grabbing the verb from the key value pair + // If the instance.verb is not undefined then return it else return a blank string + return instance.subject.split("/").pop() ?? ""; + } + ); + // Send data to current webview + TablePanel.currentPanels.get(webviewPath)?.sendMessage({ + command: Commands.LOADED_ALL_INSTANCE_CATEGORIES, + payload: { + instances: instances, + }, + }); + } catch (error) { + if (error instanceof Error) { + vscode.window.showErrorMessage(`Error: ${error.message}`); + TablePanel.currentPanels.get(webviewPath)?.sendMessage({ + command: Commands.LOADED_ALL_INSTANCE_CATEGORIES, + payload: {}, + errorMessage: `Error: ${error.message}`, + }); + } else { + vscode.window.showErrorMessage(`An unknown error occurred: ${error}`); + TablePanel.currentPanels.get(webviewPath)?.sendMessage({ + command: Commands.LOADED_ALL_INSTANCE_CATEGORIES, + payload: {}, + errorMessage: `An unknown error occurred: ${error}`, + }); + } + } +}; diff --git a/controller/src/sparql/queries/getAllInstances.ts b/controller/src/sparql/queries/getAllInstances.ts new file mode 100644 index 0000000..80e8b6c --- /dev/null +++ b/controller/src/sparql/queries/getAllInstances.ts @@ -0,0 +1,21 @@ +/** + * This SPARQL query gets all distinct instances from a given OML model + * + * @remarks + * For more information on OML instances please refer to the official documentation found {@link http://www.opencaesar.io/oml/#Instances-LR | here} + * + * For more information on SPARQL query `regex` and `str` please refer to the official documentation found {@link https://www.w3.org/TR/sparql11-query/ | here} + * + * @returns SPARQL select query string + * + */ + +export function getAllInstances(): string { + return `SELECT DISTINCT ?subject + WHERE { + ?subject ?verb ?object . + FILTER regex(str(?subject), "vocabulary", "i") + FILTER regex(str(?object), "Concept", "i") + } + ORDER BY ?subject`; +} diff --git a/controller/src/sparql/queries/getAllRelations.ts b/controller/src/sparql/queries/getAllRelations.ts index 5e42014..90dc235 100644 --- a/controller/src/sparql/queries/getAllRelations.ts +++ b/controller/src/sparql/queries/getAllRelations.ts @@ -3,7 +3,7 @@ * * @remarks * For more information on OML relations please refer to the official documentation found {@link http://www.opencaesar.io/oml/#Relations | here} - * + * * For more information on SPARQL query `regex` and `str` please refer to the official documentation found {@link https://www.w3.org/TR/sparql11-query/ | here} * * @returns SPARQL select query string @@ -11,12 +11,11 @@ */ export function getAllRelations(): string { - return `SELECT DISTINCT ?verb + return `SELECT DISTINCT ?verb WHERE { ?subject ?verb ?object . FILTER regex(str(?subject), "description", "i") FILTER regex(str(?verb), "vocabulary", "i") } ORDER BY ?verb`; - } - \ No newline at end of file +} diff --git a/controller/src/sparql/queries/getIriRelations.ts b/controller/src/sparql/queries/getIriRelations.ts index b8ab015..4233096 100644 --- a/controller/src/sparql/queries/getIriRelations.ts +++ b/controller/src/sparql/queries/getIriRelations.ts @@ -1,13 +1,13 @@ /** - * This SPARQL query gets all relations for a given IRI which is a owl:NamedIndividual + * This SPARQL query gets all relations for a given IRI which is a owl:NamedIndividual * * @remarks * For more information on OML relations please refer to the official documentation found {@link http://www.opencaesar.io/oml/#Relations | here} - * + * * For more information on SPARQL query `regex` and `str` please refer to the official documentation found {@link https://www.w3.org/TR/sparql11-query/ | here} * * @param IRI of the element. To learn more about IRIs go to this {@link https://www.oxfordsemantic.tech/faqs/what-is-an-iri-what-does-iri-mean | doc} - * + * * @returns SPARQL select query string * */ diff --git a/view/src/components/Diagram/Diagram.tsx b/view/src/components/Diagram/Diagram.tsx index 64b6afa..7fba2a5 100644 --- a/view/src/components/Diagram/Diagram.tsx +++ b/view/src/components/Diagram/Diagram.tsx @@ -687,7 +687,12 @@ function Diagram({ {relations.map((relation: string) => { - return ; + return ( + + ); })} diff --git a/view/src/components/Diagram/InsertPanel.tsx b/view/src/components/Diagram/InsertPanel.tsx index 7969778..f8165b2 100644 --- a/view/src/components/Diagram/InsertPanel.tsx +++ b/view/src/components/Diagram/InsertPanel.tsx @@ -11,25 +11,29 @@ interface InstanceInsertItemProps { interface RelationInsertItemProps { label: string; - icon: React.ReactElement + icon: React.ReactElement; } // A default icon for a RelationInsertItem -export const DefaultRelationIcon: React.ReactElement = +export const DefaultRelationIcon: React.ReactElement = ( + +); +// TODO: Wrap text so that it fits within node. Resize dynamically? /* * React component `InstanceInsertItem` is a visual representation of an insertable instance that a user can drag from the instance pane of the instance panel and drop into the diagram view. * * @param {string} label - String label for the instance * @param {string} style - TailwindCSS style to specify style attributes for the InstanceNode */ -export const InstanceInsertItem: React.FC = ({ label, style }) => { +export const InstanceInsertItem: React.FC = ({ + label, + style, +}) => { // TODO: Use model's node color property instead of hard-coded color - // TODO: handle onDrag Look at react-beautiful-dnd - // TODO: handle cloning object after dragging // TODO: handle dropping object after letting go of the mouse const ref = useRef(null); // ref for dragging - const defaultNodeStyle = "bg-[#ff0000]" + const defaultNodeStyle = "bg-[#ff0000]"; // Enable dragging of element useEffect(() => { @@ -42,7 +46,9 @@ export const InstanceInsertItem: React.FC = ({ label, s
@@ -54,10 +60,14 @@ export const InstanceInsertItem: React.FC = ({ label, s ); }; -export const RelationInsertItem: React.FC = ({ label, icon }) => { +// TODO: Dynamically resize pane/panel on relation name size +export const RelationInsertItem: React.FC = ({ + label, + icon, +}) => { // TODO: Find a better way to handle icons const ref = useRef(null); - + useEffect(() => { const el = ref.current; invariant(el); diff --git a/view/src/pages/DiagramView.tsx b/view/src/pages/DiagramView.tsx index 0e26c67..397511c 100644 --- a/view/src/pages/DiagramView.tsx +++ b/view/src/pages/DiagramView.tsx @@ -80,6 +80,13 @@ const DiagramView: React.FC = () => { }, }); + postMessage({ + command: Commands.GET_ALL_INSTANCE_CATEGORIES, + payload: { + webviewPath: webviewPath, + }, + }); + postMessage({ command: Commands.GENERATE_TABLE_DATA, payload: { @@ -189,8 +196,14 @@ const DiagramView: React.FC = () => { break; case Commands.LOADED_ALL_ELEMENT_RELATIONS: - specificMessage = message as CommandStructures[Commands.LOADED_ALL_ELEMENT_RELATIONS]; - setRelations(message.payload.relations) + specificMessage = + message as CommandStructures[Commands.LOADED_ALL_ELEMENT_RELATIONS]; + setRelations(message.payload.relations); + + case Commands.LOADED_ALL_INSTANCE_CATEGORIES: + specificMessage = + message as CommandStructures[Commands.LOADED_ALL_INSTANCE_CATEGORIES]; + setInstances(message.payload.instances); } }; window.addEventListener("message", handler); @@ -237,17 +250,17 @@ const DiagramView: React.FC = () => { @remarks This method uses the {@link https://react.dev/reference/react/useCallback | useCallback} React hook @param node - The node and its data that is clicked */ - const handleDoubleClickNode = useCallback((node: ITableData) => { - // If there is a iri in the node's data then execute the command to open the modal. - if (node.data.iri) { - openWizard("RelationElementsWizard", { iriArray: [node.data.iri] }); - // UI indication to users - postMessage({ - command: Commands.INFORM, - text: "Opening Relations Wizard...", - }); - }; - }, []); + const handleDoubleClickNode = useCallback((node: ITableData) => { + // If there is a iri in the node's data then execute the command to open the modal. + if (node.data.iri) { + openWizard("RelationElementsWizard", { iriArray: [node.data.iri] }); + // UI indication to users + postMessage({ + command: Commands.INFORM, + text: "Opening Relations Wizard...", + }); + } + }, []); const refreshData = () => { setIsLoading(true); From 40dda23f4274aeb07dabb035714ba7b6c6be0e59 Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 10 Jun 2024 14:50:33 -0700 Subject: [PATCH 21/25] Remove mock instance items Signed-off-by: Alex --- view/src/components/Diagram/Diagram.tsx | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/view/src/components/Diagram/Diagram.tsx b/view/src/components/Diagram/Diagram.tsx index 7fba2a5..1f615c1 100644 --- a/view/src/components/Diagram/Diagram.tsx +++ b/view/src/components/Diagram/Diagram.tsx @@ -501,18 +501,6 @@ function Diagram({ // This constant sets the control button dropdown indicator arrow size. const arrowIconSize = 16; - var insertItems: string[] = [ - "Label 1", - "Label 2", - "Label 3", - "Label 4", - "Label 5", - "Label 6", - "Label 7", - "Label 8", - "Label 9", - ]; - return (
Date: Mon, 10 Jun 2024 17:28:51 -0700 Subject: [PATCH 22/25] Reformat instance and relation items Signed-off-by: Alex --- view/src/components/Diagram/Diagram.tsx | 12 ++++++++-- view/src/components/Diagram/InsertPanel.tsx | 26 +++++++++++++-------- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/view/src/components/Diagram/Diagram.tsx b/view/src/components/Diagram/Diagram.tsx index 1f615c1..a87cab3 100644 --- a/view/src/components/Diagram/Diagram.tsx +++ b/view/src/components/Diagram/Diagram.tsx @@ -670,14 +670,22 @@ function Diagram({ {instances.map((instance: string) => { - return ; + var split = instance.split("#"); + return ( + + ); })} {relations.map((relation: string) => { + var split = relation.split("#"); return ( ); diff --git a/view/src/components/Diagram/InsertPanel.tsx b/view/src/components/Diagram/InsertPanel.tsx index f8165b2..f4bad17 100644 --- a/view/src/components/Diagram/InsertPanel.tsx +++ b/view/src/components/Diagram/InsertPanel.tsx @@ -5,12 +5,14 @@ import { draggable } from "@atlaskit/pragmatic-drag-and-drop/element/adapter"; import Node from "reactflow"; interface InstanceInsertItemProps { - label: string; + categoryLabel: string; + instanceLabel: string; style?: string; } interface RelationInsertItemProps { - label: string; + categoryLabel: string; + relationLabel: string; icon: React.ReactElement; } @@ -27,13 +29,14 @@ export const DefaultRelationIcon: React.ReactElement = ( * @param {string} style - TailwindCSS style to specify style attributes for the InstanceNode */ export const InstanceInsertItem: React.FC = ({ - label, + instanceLabel, + categoryLabel, style, }) => { // TODO: Use model's node color property instead of hard-coded color // TODO: handle dropping object after letting go of the mouse const ref = useRef(null); // ref for dragging - const defaultNodeStyle = "bg-[#ff0000]"; + const defaultNodeStyle = "bg-[#ff0000]"; // red background by default // Enable dragging of element useEffect(() => { @@ -46,13 +49,14 @@ export const InstanceInsertItem: React.FC = ({
- - {label} + +

{categoryLabel}

+

{instanceLabel}

@@ -62,7 +66,8 @@ export const InstanceInsertItem: React.FC = ({ // TODO: Dynamically resize pane/panel on relation name size export const RelationInsertItem: React.FC = ({ - label, + categoryLabel, + relationLabel, icon, }) => { // TODO: Find a better way to handle icons @@ -81,7 +86,8 @@ export const RelationInsertItem: React.FC = ({ ref={ref} > - {label} + {categoryLabel} + {relationLabel} {icon}
@@ -105,7 +111,7 @@ export const InsertPane: React.FC = ({ label, children }) => { export const InsertPanel: React.FC = ({ children }) => { return ( -
+
{children}
); From 9b6b84371502e1aeb03a30a6c39c87fd4bf3a566 Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 10 Jun 2024 17:45:31 -0700 Subject: [PATCH 23/25] Fix npm package vulnerabilities Signed-off-by: Alex --- package-lock.json | 20 ++++++++++---------- yarn.lock | 22 +++++++++++----------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/package-lock.json b/package-lock.json index e68a756..1c108b4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6106,9 +6106,9 @@ } }, "node_modules/@grpc/grpc-js": { - "version": "1.8.16", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.8.16.tgz", - "integrity": "sha512-Nvlq4V7XQmdRVDGgecR8ZPPCeY+uH1LhzbC+QxklwAahpQlq8YLsiOQgfkub9FiakRiohaDy361xqlTLkq9EHw==", + "version": "1.8.22", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.8.22.tgz", + "integrity": "sha512-oAjDdN7fzbUi+4hZjKG96MR6KTEubAeMpQEb+77qy+3r0Ua5xTFuie6JOLr4ZZgl5g+W5/uRTS2M1V8mVAFPuA==", "dependencies": { "@grpc/proto-loader": "^0.7.0", "@types/node": ">=12.12.47" @@ -10197,11 +10197,11 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -11721,9 +11721,9 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dependencies": { "to-regex-range": "^5.0.1" }, diff --git a/yarn.lock b/yarn.lock index 4723c67..6feef99 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3347,9 +3347,9 @@ "@floating-ui/dom" "^1.2.7" "@grpc/grpc-js@^1.2.10": - "integrity" "sha512-Nvlq4V7XQmdRVDGgecR8ZPPCeY+uH1LhzbC+QxklwAahpQlq8YLsiOQgfkub9FiakRiohaDy361xqlTLkq9EHw==" - "resolved" "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.8.16.tgz" - "version" "1.8.16" + "integrity" "sha512-oAjDdN7fzbUi+4hZjKG96MR6KTEubAeMpQEb+77qy+3r0Ua5xTFuie6JOLr4ZZgl5g+W5/uRTS2M1V8mVAFPuA==" + "resolved" "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.8.22.tgz" + "version" "1.8.22" dependencies: "@grpc/proto-loader" "^0.7.0" "@types/node" ">=12.12.47" @@ -5340,11 +5340,11 @@ "concat-map" "0.0.1" "braces@^3.0.2", "braces@~3.0.2": - "integrity" "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==" - "resolved" "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz" - "version" "3.0.2" + "integrity" "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==" + "resolved" "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz" + "version" "3.0.3" dependencies: - "fill-range" "^7.0.1" + "fill-range" "^7.1.1" "browserslist@^4.21.5", "browserslist@^4.21.9", "browserslist@>= 4.21.0": "integrity" "sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==" @@ -6324,10 +6324,10 @@ "sparqlxml-parse" "^2.1.1" "stream-to-string" "^1.1.0" -"fill-range@^7.0.1": - "integrity" "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==" - "resolved" "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz" - "version" "7.0.1" +"fill-range@^7.1.1": + "integrity" "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==" + "resolved" "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz" + "version" "7.1.1" dependencies: "to-regex-range" "^5.0.1" From 101448d5b581422564bd2880477666009b55ac0e Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 10 Jun 2024 17:55:41 -0700 Subject: [PATCH 24/25] Add util for formatting insert entities and its unit test Signed-off-by: Alex --- view/src/components/Diagram/diagramUtils.ts | 17 +++++++++++++++++ .../diagramUtils/combineByCategoty.test.js | 10 ++++++++++ 2 files changed, 27 insertions(+) create mode 100644 view/tests/diagramUtils/combineByCategoty.test.js diff --git a/view/src/components/Diagram/diagramUtils.ts b/view/src/components/Diagram/diagramUtils.ts index ae4d4d9..5445fa7 100644 --- a/view/src/components/Diagram/diagramUtils.ts +++ b/view/src/components/Diagram/diagramUtils.ts @@ -774,3 +774,20 @@ export const getLayoutedElements = ( }) .catch(console.error); }; + +export const combineByCategory = (entities: string[]) => { + let combined: Record = {} // stores the combined entities by category + entities.forEach(entity => { + var split = entity.split("#"); + var value = split.pop() ?? ""; + var category = split.pop() ?? ""; + + if (!combined[category]) { // key is not already in combined + combined[category] = [] // initialize key + } + + combined[category].push(value) // append value to the key's list of entities + }) + + return combined +} \ No newline at end of file diff --git a/view/tests/diagramUtils/combineByCategoty.test.js b/view/tests/diagramUtils/combineByCategoty.test.js new file mode 100644 index 0000000..4e533bf --- /dev/null +++ b/view/tests/diagramUtils/combineByCategoty.test.js @@ -0,0 +1,10 @@ +import { combineByCategory } from "./diagramUtils"; + +test('combines an array of entries "#"into a Record of {"": [...]}', () => { + const input = ["1#one", "1#uno", "2#deux", "2#zwei"] + const result = combineByCategory(input) // using default delimiter '#' + expect(result["1"]).toContain("one") + expect(result["1"]).toContain("uno") + expect(result["2"]).toContain("zwei") + expect(result["2"]).toContain("deux") +}); \ No newline at end of file From b61aa434d37188492bdfed8cce2358a411a87fe3 Mon Sep 17 00:00:00 2001 From: Alex Work Date: Thu, 27 Jun 2024 23:41:25 -0700 Subject: [PATCH 25/25] Style insert items for hover and auto container resizinf Signed-off-by: Alex Work --- view/src/components/Diagram/Diagram.tsx | 43 ++++++++++----------- view/src/components/Diagram/InsertPanel.tsx | 39 ++++++++++++------- 2 files changed, 45 insertions(+), 37 deletions(-) diff --git a/view/src/components/Diagram/Diagram.tsx b/view/src/components/Diagram/Diagram.tsx index a87cab3..f61f0e4 100644 --- a/view/src/components/Diagram/Diagram.tsx +++ b/view/src/components/Diagram/Diagram.tsx @@ -65,13 +65,13 @@ function Diagram({ relations, webviewPath, hasFilter, - clearFilter = () => {}, + clearFilter = () => { }, modelCommands, layout, // TODO: Use onNodeSelected while node is highlighted/selected - onNodeSelected = () => {}, - onNodeClicked = () => {}, - onNodeDoubleClicked = () => {}, + onNodeSelected = () => { }, + onNodeClicked = () => { }, + onNodeDoubleClicked = () => { }, }: { initData: { nodes: ITableData[]; @@ -586,9 +586,8 @@ function Diagram({ {isInteractive ? : } @@ -680,16 +677,18 @@ function Diagram({ })} - {relations.map((relation: string) => { - var split = relation.split("#"); - return ( - - ); - })} +
+ {relations.map((relation: string) => { + var split = relation.split("#"); + return ( + + ); + })} +
diff --git a/view/src/components/Diagram/InsertPanel.tsx b/view/src/components/Diagram/InsertPanel.tsx index f4bad17..6a32545 100644 --- a/view/src/components/Diagram/InsertPanel.tsx +++ b/view/src/components/Diagram/InsertPanel.tsx @@ -46,12 +46,11 @@ export const InstanceInsertItem: React.FC = ({ }, []); return ( -
-
+
+
@@ -80,16 +79,26 @@ export const RelationInsertItem: React.FC = ({ }, []); return ( -
+
- - {categoryLabel} - {relationLabel} - - {icon} +
+
+
{icon}
+
+
+ {categoryLabel} +
+
+ {relationLabel} +
+
+
+
+
+
); @@ -98,11 +107,11 @@ export const RelationInsertItem: React.FC = ({ export const InsertPane: React.FC = ({ label, children }) => { // Refer to http://www.opencaesar.io/oml-tutorials/#tutorial1-create-oml-vocabulary return ( -
+
{label}
-
+
{children}
@@ -111,7 +120,7 @@ export const InsertPane: React.FC = ({ label, children }) => { export const InsertPanel: React.FC = ({ children }) => { return ( -
+
{children}
);