Skip to content

Commit

Permalink
add insert panel component with relations data from OML model
Browse files Browse the repository at this point in the history
Signed-off-by: Alex <[email protected]>
  • Loading branch information
aematei committed Jun 4, 2024
1 parent aa55cdc commit 5b02395
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 6 deletions.
13 changes: 13 additions & 0 deletions commands/src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down Expand Up @@ -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',
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -180,6 +187,12 @@ export type CommandStructures = {
relations?: Record<string, any>[];
};
};
[Commands.LOADED_ALL_ELEMENT_RELATIONS]: {
errorMessage?: string;
payload: {
relations?: string[];
};
};
[Commands.DELETED_ELEMENTS]: {
errorMessage?: string;
wizardId: string;
Expand Down
8 changes: 8 additions & 0 deletions commands/src/tablePanelMessageHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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;
Expand Down
59 changes: 59 additions & 0 deletions controller/src/sparql/data-manager/getAllElementRelations.ts
Original file line number Diff line number Diff line change
@@ -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<void> => {
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<string, string>) => {
// 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}`,
});
}
}
};
22 changes: 22 additions & 0 deletions controller/src/sparql/queries/getAllRelations.ts
Original file line number Diff line number Diff line change
@@ -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`;
}

12 changes: 8 additions & 4 deletions view/src/components/Diagram/Diagram.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ const nodeTypes = {

function Diagram({
initData,
instances,
relations,
webviewPath,
hasFilter,
clearFilter = () => {},
Expand All @@ -76,6 +78,8 @@ function Diagram({
edges: Edge[];
legendItems: LegendItem[];
};
instances: string[];
relations: string[];
webviewPath: string;
hasFilter: boolean;
clearFilter: Function;
Expand Down Expand Up @@ -677,13 +681,13 @@ function Diagram({
<Panel position="top-left" className="flow-panel">
<InsertPanel>
<InsertPane label="Instance">
{insertItems.map((item) => {
return <InstanceInsertItem label={item} />;
{instances.map((instance: string) => {
return <InstanceInsertItem label={instance} />;
})}
</InsertPane>
<InsertPane label="Relation">
{insertItems.map((item) => {
return <RelationInsertItem label={item} icon={DefaultRelationIcon}/>;
{relations.map((relation: string) => {
return <RelationInsertItem label={relation} icon={DefaultRelationIcon}/>;
})}
</InsertPane>
</InsertPanel>
Expand Down
4 changes: 2 additions & 2 deletions view/src/components/Diagram/InsertPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ export const InstanceInsertItem: React.FC<InstanceInsertItemProps> = ({ label, s
}, []);

return (
<div className="flex flex-row items-center hover:backdrop-brightness-200">
<div className="relative left-[1px] z-10 h-2 w-2 border-[1px] rounded-full bg-black border-white "></div>
<div className="flex flex-row items-center">
<div className="relative left-[1px] z-10 h-2 w-2 border-[1px] rounded-full bg-black border-white hover:backdrop-brightness-200"></div>
<div
className={`flex flex-none justify-center items-center rounded h-11 w-24 z-0 ${style ?? defaultNodeStyle}`}
ref={ref}
Expand Down
15 changes: 15 additions & 0 deletions view/src/pages/DiagramView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ const DiagramView: React.FC = () => {
}>({ iris: [], filterObject: null });
const [errorMessage, setErrorMessage] = useState<string>("");
const [isLoading, setIsLoading] = useState<boolean>(true);
const [instances, setInstances] = useState<string[]>([""]);
const [relations, setRelations] = useState<string[]>([""]);

useEffect(() => {
// Only start fetching data when context is loaded
Expand Down Expand Up @@ -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: {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -266,6 +279,8 @@ const DiagramView: React.FC = () => {
<ReactFlowProvider>
<Diagram
initData={createPageContent}
instances={instances}
relations={relations}
webviewPath={webviewPath}
hasFilter={filter.iris.length > 0}
clearFilter={() => setFilter({ iris: [], filterObject: null })}
Expand Down

0 comments on commit 5b02395

Please sign in to comment.