diff --git a/libs/shared/data-access/store/src/lib/hooks.ts b/libs/shared/data-access/store/src/lib/hooks.ts index 9ab46c395fdc6c697ad35d1363ac4c1c16cbb39b..df0faef46e155463bea444790b3ba91dcc076b76 100644 --- a/libs/shared/data-access/store/src/lib/hooks.ts +++ b/libs/shared/data-access/store/src/lib/hooks.ts @@ -1,5 +1,6 @@ import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'; import { selectGraphQueryResult } from './graphQueryResultSlice'; +import { selectSchema } from './schemaSlice'; import type { RootState, AppDispatch } from './store'; // Use throughout your app instead of plain `useDispatch` and `useSelector` @@ -8,3 +9,6 @@ export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector; // Gives the graphQueryResult from the store export const useGraphQueryResult = () => useAppSelector(selectGraphQueryResult); + +// Gives the schema form the store (as a graphology object) +export const useSchema = () => useAppSelector(selectSchema); diff --git a/libs/shared/data-access/store/src/lib/schemaSlice.ts b/libs/shared/data-access/store/src/lib/schemaSlice.ts new file mode 100644 index 0000000000000000000000000000000000000000..a8a22e05b4515e1bbdd1462928ef672d67b97dcd --- /dev/null +++ b/libs/shared/data-access/store/src/lib/schemaSlice.ts @@ -0,0 +1,73 @@ +import { createSlice, PayloadAction } from '@reduxjs/toolkit'; +import type { RootState } from './store'; +import Graph, { DirectedGraph } from 'graphology'; + +/*************** schema format from the backend *************** */ +// TODO: should probably not live here +/** Schema type, consist of nodes and edges */ +export type SchemaFromBackend = { + edges: Edge[]; + nodes: Node[]; +}; + +/** Attribute type, consist of a name */ +export type Attribute = { + name: string; + type: 'string' | 'int' | 'bool' | 'float'; +}; + +/** Node type, consist of a name and a list of attributes */ +export type Node = { + name: string; + attributes: Attribute[]; +}; + +/** Edge type, consist of a name, start point, end point and a list of attributes */ +export type Edge = { + name: string; + to: string; + from: string; + collection: string; + attributes: Attribute[]; +}; +/**************************************************************** */ + +// Define the initial state using that type +export const initialState = { + graphologySerialized: new Graph().export(), +}; + +export const schemaSlice = createSlice({ + name: 'schema', + // `createSlice` will infer the state type from the `initialState` argument + initialState, + reducers: { + readInSchemaFromBackend: ( + state, + action: PayloadAction<SchemaFromBackend> + ) => { + const { nodes, edges } = action.payload; + // Instantiate a directed graph that allows self loops and parallel edges + const schema = new DirectedGraph({ allowSelfLoops: true, multi: true }); + nodes.forEach((node) => { + schema.addNode(node.name, { attributes: node.attributes }); + }); + + edges.forEach((edge) => + schema.addDirectedEdgeWithKey(edge.name, edge.from, edge.to, { + collection: edge.collection, + }) + ); + + state.graphologySerialized = schema.export(); + }, + }, +}); + +export const { readInSchemaFromBackend } = schemaSlice.actions; + +// Select the schema and convert it to a graphology object +export const selectSchema = (state: RootState) => + Graph.from(state.schema.graphologySerialized); + +export default schemaSlice.reducer; diff --git a/libs/shared/data-access/store/src/lib/store.ts b/libs/shared/data-access/store/src/lib/store.ts index 89673e6c1470b47f3b84cbbc8410614aca1fbbc5..c4a617bc4931f87d2811f8a95a027c10d0faee8b 100644 --- a/libs/shared/data-access/store/src/lib/store.ts +++ b/libs/shared/data-access/store/src/lib/store.ts @@ -1,9 +1,11 @@ import { configureStore } from '@reduxjs/toolkit'; import graphQueryResultSlice from './graphQueryResultSlice'; +import schemaSlice from './schemaSlice'; export const store = configureStore({ reducer: { graphQueryResult: graphQueryResultSlice, + schema: schemaSlice, }, }); diff --git a/package.json b/package.json index 98b1999355025e2ce0875f4f3e8b20eceba073ae..64fe528c6b0be6c11047b069b44da5c20b9eb73d 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,8 @@ "@types/react-grid-layout": "^1.3.0", "@types/styled-components": "^5.1.21", "core-js": "^3.6.5", + "graphology": "^0.23.2", + "graphology-types": "^0.23.0", "react": "17.0.2", "react-dom": "17.0.2", "react-grid-layout": "^1.3.3", diff --git a/yarn.lock b/yarn.lock index fc458d50301af293f8ac085e2bb3424eafc557b1..948c5e10973c321308c4797e1bfc37117c2868d6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8304,7 +8304,7 @@ eventemitter3@^4.0.0, eventemitter3@^4.0.4: resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== -events@^3.0.0, events@^3.2.0: +events@^3.0.0, events@^3.2.0, events@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== @@ -9326,6 +9326,19 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6 resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96" integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== +graphology-types@^0.23.0: + version "0.23.0" + resolved "https://registry.yarnpkg.com/graphology-types/-/graphology-types-0.23.0.tgz#76a0564baf31891044a7b0cc6cd028810541bb7a" + integrity sha512-6Je1NWU3el7YmybAhRzrOEi79Blhx05EU3wGUCvP5ikaxRXEflrW/5unfw5q/wqfwjryM9tcwUv4M7TZ8yTBYQ== + +graphology@^0.23.2: + version "0.23.2" + resolved "https://registry.yarnpkg.com/graphology/-/graphology-0.23.2.tgz#b09a33a9408a7615c3c9cff98e7404cc70a21820" + integrity sha512-RHcLpAP4M+KPShLQEvgkT1Y4vxl+FFbmmy3D0mupO+VXIuYC8zdmMcHs40D9m3mmN067zGS+lUaHjDq06Td7PQ== + dependencies: + events "^3.3.0" + obliterator "^2.0.0" + handle-thing@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e" @@ -12427,6 +12440,11 @@ objectorarray@^1.0.5: resolved "https://registry.yarnpkg.com/objectorarray/-/objectorarray-1.0.5.tgz#2c05248bbefabd8f43ad13b41085951aac5e68a5" integrity sha512-eJJDYkhJFFbBBAxeh8xW+weHlkI28n2ZdQV/J/DNfWfSKlGEf2xcfAbZTv3riEXHAhL9SVOTs2pRmXiSTf78xg== +obliterator@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/obliterator/-/obliterator-2.0.1.tgz#fbdd873bf39fc4f365a53b1fc86617a22526987c" + integrity sha512-XnkiCrrBcIZQitJPAI36mrrpEUvatbte8hLcTcQwKA1v9NkCKasSi+UAguLsLDs/out7MoRzAlmz7VXvY6ph6w== + obuf@^1.0.0, obuf@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e"