import { createSlice, PayloadAction } from '@reduxjs/toolkit'; import type { RootState } from './store'; import { MultiGraph } from 'graphology'; import { SerializedGraph } from 'graphology-types'; import { AllLayoutAlgorithms } from '@graphpolaris/shared/graph-layout'; import { Graphology } from 'libs/shared/graph-layout/src/factory/graphology-layouts'; /*************** 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 MultiGraph().export(), schemaLayout: 'Graphology_noverlap', }; export const schemaSlice = createSlice({ name: 'schema', // `createSlice` will infer the state type from the `initialState` argument initialState, reducers: { setSchema: (state, action: PayloadAction<SerializedGraph>) => { // console.log('setSchema in schemaslice', action); state.graphologySerialized = action.payload; }, readInSchemaFromBackend: ( state, action: PayloadAction<SchemaFromBackend> ) => { const { nodes, edges } = action.payload; // Instantiate a directed graph that allows self loops and parallel edges const schema = new MultiGraph({ allowSelfLoops: 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(); }, setGraphLayout: (state, action: PayloadAction<AllLayoutAlgorithms>) => { state.schemaLayout = action.payload; }, }, }); export const { readInSchemaFromBackend, setSchema } = schemaSlice.actions; /** * Select the schema and convert it to a graphology object * */ export const selectSchema = (state: RootState) => MultiGraph.from(state.schema.graphologySerialized).copy(); /** * selects the SchemaLayout enum * @param {GraphLayout} state * @returns {GraphLayout} enum of type GraphLayout */ export const selectSchemaLayout = (state: RootState) => state.schema.schemaLayout; export default schemaSlice.reducer;