Skip to content

Commit d2db9cf

Browse files
committed
New simple panel app has been added
1 parent 3b428d8 commit d2db9cf

File tree

9 files changed

+217
-67
lines changed

9 files changed

+217
-67
lines changed
Lines changed: 60 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,12 @@
1-
import { v4 as uuidv4 } from 'uuid';
2-
import { ReactElement } from 'react';
3-
import { MenuItem } from '@mui/material';
4-
import { IdType } from '../../../models/IdType'
5-
import { Column } from '../../../models/TableModel'
6-
import { useTableStore } from '../../../store/TableStore'
7-
import { useLayoutStore } from '../../../store/LayoutStore';
8-
import { useNetworkStore } from '../../../store/NetworkStore';
9-
import { ValueType } from '../../../models/TableModel/ValueType';
10-
import { putNetworkSummaryToDb } from '../../../store/persist/db';
11-
import { useWorkspaceStore } from '../../../store/WorkspaceStore';
12-
import { useViewModelStore } from '../../../store/ViewModelStore';
13-
import { useVisualStyleStore } from '../../../store/VisualStyleStore';
14-
import { ValueTypeName } from '../../../models/TableModel/ValueTypeName';
15-
import { AttributeName } from '../../../models/TableModel/AttributeName';
16-
import { BaseMenuProps } from '../../../components/ToolBar/BaseMenuProps';
17-
import { LayoutAlgorithm, LayoutEngine } from '../../../models/LayoutModel'
18-
import {
19-
createEmptyNetworkWithView, DEFAULT_ATTRIBUTE,
20-
createNodeView, createEdgeView
21-
} from '../utils/createNewNetwork';
22-
import { VisualPropertyGroup } from '../../../models/VisualStyleModel/VisualPropertyGroup';
23-
241
// Define default columns for demo edge and node tables
252
const DEMO_EDGE_TABLE_COLUMN: Column = {
263
name: DEFAULT_ATTRIBUTE,
27-
type: ValueTypeName.String
28-
};
4+
type: ValueTypeName.String,
5+
}
296
const DEMO_NODE_TABLE_COLUMN: Column = {
307
name: DEFAULT_ATTRIBUTE,
31-
type: ValueTypeName.String
32-
};
8+
type: ValueTypeName.String,
9+
}
3310

3411
/**
3512
* TutorialMenuItemTwo component:
@@ -39,21 +16,24 @@ const DEMO_NODE_TABLE_COLUMN: Column = {
3916
* - handleClose: A function from the parent component that will be called to close the menu.
4017
*/
4118

42-
export const TutorialMenuItemTwo = ({ handleClose }: BaseMenuProps): ReactElement => {
19+
export const TutorialMenuItemTwo = ({
20+
handleClose,
21+
}: BaseMenuProps): ReactElement => {
4322
// Define constants and hooks for network and node IDs
44-
const nodeOneId = '1';
45-
const nodeTwoId = '2';
46-
const edgeId = 'e1';
23+
const nodeOneId = '1'
24+
const nodeTwoId = '2'
25+
const edgeId = 'e1'
4726
const NODE_TYPE = VisualPropertyGroup.Node
4827
const EDGE_TYPE = VisualPropertyGroup.Edge
49-
const newNetworkUuid = uuidv4();
28+
const newNetworkUuid = uuidv4()
5029

5130
// Use custom hooks for state management across different stores
52-
const { addNewNetwork, addNodesToNetwork, addEdgeToNetwork } = useNetworkStore((state) => ({
53-
addNewNetwork: state.add,
54-
addNodesToNetwork: state.addNodes,
55-
addEdgeToNetwork: state.addEdge,
56-
}));
31+
const { addNewNetwork, addNodesToNetwork, addEdgeToNetwork } =
32+
useNetworkStore((state) => ({
33+
addNewNetwork: state.add,
34+
addNodesToNetwork: state.addNodes,
35+
addEdgeToNetwork: state.addEdge,
36+
}))
5737
const addNodeViews = useViewModelStore((state) => state.addNodeViews)
5838
const addEdgeView = useViewModelStore((state) => state.addEdgeView)
5939
const setVisualStyle = useVisualStyleStore((state) => state.add)
@@ -82,7 +62,8 @@ export const TutorialMenuItemTwo = ({ handleClose }: BaseMenuProps): ReactElemen
8262
layoutEngines.find((engine) => engine.name === defaultLayout.engineName) ??
8363
layoutEngines[0]
8464

85-
const updateNodePositions: ( // Function to update node positions after layout is applied
65+
const updateNodePositions: (
66+
// Function to update node positions after layout is applied
8667
networkId: IdType,
8768
positions: Map<IdType, [number, number, number?]>,
8869
) => void = useViewModelStore((state) => state.updateNodePositions)
@@ -96,21 +77,29 @@ export const TutorialMenuItemTwo = ({ handleClose }: BaseMenuProps): ReactElemen
9677
/**
9778
* handleClick function:
9879
* This function is called when the menu item is clicked.
99-
* It firstly creates an empty networkWithView,
80+
* It firstly creates an empty networkWithView,
10081
* then it adds two nodes and one edge to the network and applies the defualt layout.
10182
* Finally, it updates network views, tables, and the summary.
10283
*/
10384
try {
104-
// Create a new network with specified node and edge attributes
105-
const [newNetworkWithView, newNetworkSummary] = await createEmptyNetworkWithView([DEMO_NODE_TABLE_COLUMN],
106-
[DEMO_EDGE_TABLE_COLUMN], newNetworkUuid);
107-
108-
// Update state stores with the new network and its components
109-
addNetworkToWorkspace(newNetworkUuid);
110-
addNewNetwork(newNetworkWithView.network);
111-
setVisualStyle(newNetworkUuid, newNetworkWithView.visualStyle);
112-
setTables(newNetworkUuid, newNetworkWithView.nodeTable, newNetworkWithView.edgeTable);
113-
setViewModel(newNetworkUuid, newNetworkWithView.networkViews[0]);
85+
// Create a new network with specified node and edge attributes
86+
const [newNetworkWithView, newNetworkSummary] =
87+
await createEmptyNetworkWithView(
88+
[DEMO_NODE_TABLE_COLUMN],
89+
[DEMO_EDGE_TABLE_COLUMN],
90+
newNetworkUuid,
91+
)
92+
93+
// Update state stores with the new network and its components
94+
addNetworkToWorkspace(newNetworkUuid)
95+
addNewNetwork(newNetworkWithView.network)
96+
setVisualStyle(newNetworkUuid, newNetworkWithView.visualStyle)
97+
setTables(
98+
newNetworkUuid,
99+
newNetworkWithView.nodeTable,
100+
newNetworkWithView.edgeTable,
101+
)
102+
setViewModel(newNetworkUuid, newNetworkWithView.networkViews[0])
114103
setCurrentNetworkId(newNetworkUuid)
115104

116105
// Add nodes and an edge to the network
@@ -119,15 +108,22 @@ export const TutorialMenuItemTwo = ({ handleClose }: BaseMenuProps): ReactElemen
119108

120109
// Apply layout to the network
121110
setIsRunning(true)
122-
engine.apply(newNetworkWithView.network.nodes,
123-
newNetworkWithView.network.edges, afterLayout, defaultLayout)
111+
engine.apply(
112+
newNetworkWithView.network.nodes,
113+
newNetworkWithView.network.edges,
114+
afterLayout,
115+
defaultLayout,
116+
)
124117

125118
// Update tables with node and edge attributes
126-
const nodeAttr: Array<[IdType, Record<AttributeName, ValueType>]>
127-
= [[nodeOneId, { [DEFAULT_ATTRIBUTE]: NODE_TYPE + nodeOneId }],
128-
[nodeTwoId, { [DEFAULT_ATTRIBUTE]: NODE_TYPE + nodeTwoId }]];
129-
const edgeAttr: [IdType, Record<AttributeName, ValueType>]
130-
= [edgeId, { [DEFAULT_ATTRIBUTE]: edgeId }];
119+
const nodeAttr: Array<[IdType, Record<AttributeName, ValueType>]> = [
120+
[nodeOneId, { [DEFAULT_ATTRIBUTE]: NODE_TYPE + nodeOneId }],
121+
[nodeTwoId, { [DEFAULT_ATTRIBUTE]: NODE_TYPE + nodeTwoId }],
122+
]
123+
const edgeAttr: [IdType, Record<AttributeName, ValueType>] = [
124+
edgeId,
125+
{ [DEFAULT_ATTRIBUTE]: edgeId },
126+
]
131127
addRowsToTable(newNetworkUuid, NODE_TYPE, nodeAttr)
132128
addRowToTable(newNetworkUuid, EDGE_TYPE, edgeAttr)
133129

@@ -141,20 +137,19 @@ export const TutorialMenuItemTwo = ({ handleClose }: BaseMenuProps): ReactElemen
141137
// Update network summary and persist to the database
142138
await putNetworkSummaryToDb({
143139
...newNetworkSummary,
144-
nodeCount: 2, edgeCount: 1, hasLayout: true, modificationTime: new Date(Date.now()),
140+
nodeCount: 2,
141+
edgeCount: 1,
142+
hasLayout: true,
143+
modificationTime: new Date(Date.now()),
145144
})
146145

147146
// Close the menu item after operations are complete
148-
handleClose();
147+
handleClose()
149148
} catch (error) {
150149
console.error(error)
151150
}
152-
};
151+
}
153152

154153
// Render a MenuItem that triggers network creation on click
155-
return (
156-
<MenuItem onClick={handleClick}>
157-
Create Example Network
158-
</MenuItem>
159-
);
160-
};
154+
return <MenuItem onClick={handleClick}>Create Example Network</MenuItem>
155+
}

package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@
44
"private": true,
55
"workspaces": [
66
"hello-world",
7-
"simple-menu"
7+
"simple-menu",
8+
"simple-panel"
89
],
910
"scripts": {
1011
"build": "npm run build --workspaces",
1112
"dev": "concurrently \"npm:dev:*\"",
1213
"dev:hello-world": "npm run dev -w hello-world",
13-
"dev:simple-menu": "npm run dev -w simple-menu"
14+
"dev:simple-menu": "npm run dev -w simple-menu",
15+
"dev:simple-panel": "npm run dev -w simple-panel"
1416
},
1517
"peerDependencies": {
1618
"@mui/material": "^5.16.4",

simple-panel/package.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"name": "@cytoscape-web/simple-panel",
3+
"description": "A simple panel component for Cytoscape Web",
4+
"version": "1.0.0",
5+
"private": "true",
6+
"type": "module",
7+
"scripts": {
8+
"build": "webpack --config webpack.config.js",
9+
"dev": "webpack serve --open /remoteEntry.js --mode development"
10+
}
11+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { ComponentType, CyApp } from '@cytoscape-web/types'
2+
3+
export const SimplePanelApp: CyApp = {
4+
id: 'simplePanel',
5+
name: 'Simple Panel App',
6+
url: '',
7+
components: [
8+
{
9+
id: 'SimplePanel',
10+
type: ComponentType.Panel,
11+
},
12+
],
13+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { useEffect } from 'react'
2+
3+
// Dynamic import from the host app
4+
import { useWorkspaceStore } from 'cyweb/WorkspaceStore'
5+
6+
import { Network, IdType } from '@cytoscape-web/types'
7+
8+
interface HelloPanelProps {
9+
message: string
10+
}
11+
12+
const SimplePanel = ({ message }: HelloPanelProps): JSX.Element => {
13+
const workspace = useWorkspaceStore((state: any) => state.workspace)
14+
15+
const ids: IdType[] = workspace.networkIds
16+
17+
useEffect(() => {
18+
console.log('Simple Panel initialized', workspace)
19+
}, [])
20+
21+
return (
22+
<div>
23+
<h4>Simple panel example {message}</h4>
24+
<p>Current Network ID: {workspace.currentNetworkId}</p>
25+
<h5>Networks:</h5>
26+
<ul>
27+
{ids.map((id: IdType) => (
28+
<li key={id}>{id}</li>
29+
))}
30+
</ul>
31+
</div>
32+
)
33+
}
34+
35+
export default SimplePanel

simple-panel/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { SimplePanelApp as default } from './SimplePanelApp'

simple-panel/src/remotes.d.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
declare module 'cyweb/useDataStore'
2+
declare module 'cyweb/WorkspaceStore'
3+
declare module 'cyweb/NetworkStore'
4+
declare module 'cyweb/Network'

simple-panel/tsconfig.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"include": ["src/**/*"],
3+
"compilerOptions": {
4+
"allowSyntheticDefaultImports": true,
5+
"outDir": "./dist/",
6+
"noImplicitAny": true,
7+
"module": "ESNext",
8+
"target": "ESNext",
9+
"jsx": "react-jsx",
10+
"allowJs": true,
11+
"esModuleInterop": true,
12+
"moduleResolution": "node",
13+
"sourceMap": true,
14+
"strictNullChecks": true,
15+
"resolveJsonModule": true,
16+
"baseUrl": "."
17+
}
18+
}

simple-panel/webpack.config.js

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import path from 'path'
2+
import url from 'url'
3+
import webpack from 'webpack'
4+
import packageJson from '../package.json' assert { type: 'json' }
5+
6+
const { ModuleFederationPlugin } = webpack.container
7+
8+
// Extract some properties from the package.json file to avoid duplication
9+
const deps = packageJson.peerDependencies
10+
11+
const __filename = url.fileURLToPath(import.meta.url)
12+
const __dirname = path.dirname(__filename)
13+
14+
const DEV_SERVER_PORT = 4001
15+
16+
export default {
17+
mode: 'development',
18+
devtool: false,
19+
target: 'web',
20+
optimization: {
21+
minimize: false,
22+
runtimeChunk: false,
23+
splitChunks: {
24+
chunks: 'async',
25+
name: false,
26+
},
27+
},
28+
entry: './src/index.ts',
29+
output: {
30+
clean: true,
31+
path: path.resolve(__dirname, 'dist'),
32+
publicPath: 'auto',
33+
},
34+
resolve: {
35+
extensions: ['.ts', '.tsx', '.js', '.jsx', '.json'],
36+
},
37+
plugins: [
38+
new ModuleFederationPlugin({
39+
name: 'simplePanel',
40+
filename: 'remoteEntry.js',
41+
remotes: {
42+
// Import some data providers from the host application
43+
cyweb: 'cyweb@http://localhost:5500/remoteEntry.js',
44+
},
45+
exposes: {
46+
'./SimplePanelApp': './src/SimplePanelApp',
47+
'./SimplePanel': './src/components/SimplePanel.tsx',
48+
},
49+
shared: {
50+
react: { singleton: true, requiredVersion: deps.react },
51+
'react-dom': { singleton: true, requiredVersion: deps['react-dom'] },
52+
},
53+
}),
54+
],
55+
module: {
56+
rules: [
57+
{
58+
test: /\.tsx?$/,
59+
use: 'ts-loader',
60+
exclude: /node_modules/,
61+
},
62+
],
63+
},
64+
devServer: {
65+
hot: true,
66+
port: DEV_SERVER_PORT,
67+
headers: {
68+
'Access-Control-Allow-Origin': '*', // allow access from any origin
69+
},
70+
},
71+
}

0 commit comments

Comments
 (0)