import { createSlice, PayloadAction } from '@reduxjs/toolkit'; import type { RootState } from './store'; import Graph 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: { setSchema: (state, action: PayloadAction<Graph>) => { state.graphologySerialized = action.payload.export(); }, readInSchemaFromBackend: ( state, action: PayloadAction<SchemaFromBackend> ) => { const { nodes, edges } = action.payload; // Instantiate a directed graph that allows self loops and parallel edges const schema = new Graph({ allowSelfLoops: true, multi: true }); console.log('Updating schema'); // The graph schema needs a node for each node AND edge. These need then be connected nodes.forEach((node) => { schema.addNode(node.name, { name: node.name, attributes: node.attributes, x: 0, y: 0, }); }); // The name of the edge will be name + from + to, since edge names are not unique edges.forEach((edge) => { const edgeID = edge.name + edge.from + edge.to; // This node is the actual edge schema.addNode(edgeID, { name: edge.name, attributes: edge.attributes, from: edge.from, to: edge.to, collection: edge.collection, x: 0, y: 0, }); // These lines are simply for keeping the schema together schema.addDirectedEdgeWithKey(edgeID + 'f', edge.from, edgeID); schema.addDirectedEdgeWithKey(edgeID + 't', edgeID, edge.to); }); state.graphologySerialized = schema.export(); }, }, }); export const { readInSchemaFromBackend, setSchema } = 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;