UNPKG

model-navigator-standalone

Version:

Standalone MDF graph model visualizer

223 lines (208 loc) 7.42 kB
import { createSlice, createSelector } from '@reduxjs/toolkit'; import _ from 'lodash'; const initialState = { isGraphView: true, layoutInitialized: false, modelID: "", nodes: [], edges: [], graphViewConfig: {}, legendDisplayed: true, expandedNodeID: null, foregroundedNodes: [], legendItems: [], categories: [], hoveringNode: null, focusedNodeID: null, highlightingNodeID: null, relatedNodeIDs: [], secondHighlightingNodeID: null, dataModelStructure: null, canvasBoundingRect: { top: 0, left: 0 }, needReset: false, tableExpandNodeIDs: [], overlayTableHidden: true, graphNodesSVGElements: null, matchedNodeIDs: [], matchedNodeIDsInProperties: [], matchedNodeIDsInNameAndDescription: [], highlightingMatchedNodeID: null, highlightingMatchedNodeOpened: false, }; const graphSlice = createSlice({ name: 'graph', initialState, reducers: { reactFlowGraphInitialized(state, action) { const { graphViewConfig, model, } = action.payload; state.graphViewConfig = graphViewConfig; //?? state.categories = _.uniq(model.tag_kvs('Category').map(([,val]) => val)); state.modelID = model.id || "none"; }, reactFlowGraphDataCalculated(state, action) { const { flowData } = action.payload; state.nodes = flowData.nodes; state.edges = flowData.edges; }, reactFlowGraphModelUpdateRequested(state, action) { state.updateModel = true; }, clickedBlankSpace(state, action) { // this is weird. if (state.highlightingNode) { if (state.secondHighlightingNodeID) { state.secondHighlightingNodeID = null; } else { state.highlightingNode = null; state.tableExpandNodeID = null; } } }, tableNodeExpandChanged(state, action) { const { nodeState, nodeID } = action.payload; state.highlightingNode = nodeID; state.secondHighlightingNodeID = null; switch (nodeState) { case 'open': if (state.tableExpandNodeIDs) { !state.tableExpandNodeIDs.includes(nodeID) && state.tableExpandNodeIDs.push(nodeID); } else { state.tableExpandNodeIDs = [nodeID]; } break; case 'close': state.tableExpandNodeIDs = _.filter(state.tableExpandNodeIDs, elt => elt !== nodeID); break; default: break; } }, // expand tables nodeS // graph nodes svg elements updated reactFlowPanelClicked(state, action) { }, reactFlowNodeDragStarted(state, action) { }, // reactFlowNodeExpanded(state, action) { // }, reactFlowNodeDisplayChanged(state, action) { const display = action.payload; state.nodeDisplayed = display; }, reactFlowGraphViewChanged(state, action) { // determine param, onViewChange const view = action.payload; localStorage.setItem('reactflowGraphView', JSON.stringify(view)); state.reactFlowView = view; }, reactFlowNodeFocused(state, action) { const nodeID = action.payload; state.focusedNodeId = nodeID; }, reactFlowNodeClicked(state, action) { const {id: nodeID, isSearchMode} = action.payload; state.highlightingMatchedNodeID = nodeID; state.highlightingNodeID = nodeID; state.highlightingMatchedNodeOpened = false; if (state.expandedNodeID === nodeID) { state.expandedNodeID = null; } else { state.expandedNodeID = nodeID; } state.overlayTableHidden = isSearchMode ? false : true; }, changedVisOverlayPropTable(state, action) { const vis = action.payload; if (vis === 'hide') { state.expandedNodeID = null; state.overlayTableHidden = true; } else { state.overlayTableHidden = false; } }, tabGraphViewChanged(state, action) { const showGraphView = action.payload; state.isGraphView = showGraphView; }, legendDisplayChanged(state, action) { const display = action.payload; state.legendDisplayed = display; }, canvasWidthChanged(state, action) { const width = action.payload; state.graphViewConfig.canvasWidth = width; }, graphLegendCalculated(state, action) { const legendItems = action.payload; state.legendItems = legendItems; }, hoveringNodeUpdated(state, action) { const nodeID = action.payload; const newHoverNode = state.nodes.find( n => n.id === nodeID ); state.hoveringNode = newHoverNode; }, canvasBoundingRectUpdated(state, action) { const boundingRect = action.payload; state.canvasBoundingRect = boundingRect; }, // graph update related highlighting node graphRelatedHighlightingNodesUpdated(state, action) { const nodeIDs = action.payload; state.relatedNodeIDs = nodeIDs; }, // graph update second highlighting node candidates // graph update path related to second highlighting node // graph update data model structure canvasResetRequested(state, action) { const needReset = action.payload; state.needReset = needReset; }, // graph reset highlight }, }); export const { // reducer/actions reactFlowGraphInitialized, tableNodeExpandChanged, reactFlowGraphDataCalculated, reactFlowGraphModelUpdateRequested, reactFlowPanelClicked, reactFlowNodeDragStarted, reactFlowNodeClicked, reactFlowNodeExpanded, reactFlowNodeFocused, reactFlowNodeDisplayChanged, reactFlowGraphViewChanged, clickedBlankSpace, graphLegendCalculated, tabGraphViewChanged, legendDisplayChanged, canvasWidthChanged, graphTableViewToggled, hoveringNodeUpdated, canvasBoundingRectUpdated, changedVisOverlayPropTable, canvasRestRequested, } = graphSlice.actions; export default graphSlice.reducer; // export Selectors export const selectModelID = state => state.graph.modelID; export const selectIsGraphView = state => state.graph.isGraphView; export const selectLegendDisplayed = state => state.graph.legendDisplayed; export const selectGraphViewConfig = state => state.graph.graphViewConfig; export const selectCategories = state => state.graph.categories; export const selectCanvasWidth = state => state.graph.graphViewConfig.canvasWidth; export const selectHighlightingMatchedNodeID = state => state.graph.highlightingMatchedNodeID; export const selectHighlightingNodeID = state => state.graph.highlightingNodeID; export const selectHighlightedNodes = state => state.graph.selectHighlightedNodes; export const selectExpandedNodeID = state => state.graph.expandedNodeID; export const selectFocusedNodeID = state => state.graph.focusedNodeID; // export const selectNodeDisplayed = state => state.graph.nodeDisplayed; export const selectOverlayTableHidden = state => state.graph.overlayTableHidden; export const selectNodeIsExpanded = (state, nodeID) => state.graph.expandedNodeID === nodeID; export const selectNodeIsForegrounded = (state, nodeID) => state.graph.foregroundedNodes.includes(nodeID); export const selectTableNodeIsExpanded = (state, nodeID) => state.graph.tableExpandNodeIDs && state.graph.tableExpandNodeIDs.includes(nodeID); export const selectPropTableNodeID = createSelector( [selectHighlightingMatchedNodeID, selectHighlightingNodeID], (matchedNodeID, highlightingNodeID) => { return matchedNodeID || highlightingNodeID || null; });