Skip to content

Commit 2d2d5de

Browse files
committed
#36 composition implementation, metanode instantiation and pluggin required parts of the library
1 parent c2f503d commit 2d2d5de

File tree

7 files changed

+231
-75
lines changed

7 files changed

+231
-75
lines changed

src/components/Main.js

+10-8
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import React from 'react';
22
// import MechanismNode from '../model/nodes/mechanism/MechanismNode';
33
import { withStyles } from '@mui/styles';
4+
import { PNLClasses } from '../constants';
5+
import { buildModel } from '../model/utils';
46
import BG from "../assets/svg/bg-dotted.svg";
57
import ModelInterpreter from '../model/Interpreter';
8+
import Composition from './views/compositions/Composition';
9+
import GenericMechanism from './views/mechanisms/GenericMechanism';
610
import MetaDiagram, { ComponentsMap } from "@metacell/meta-diagram";
711
import CustomLinkWidget from './views/projections/CustomLinkWidget';
8-
import GenericMechanism from './views/mechanisms/GenericMechanism';
9-
import { buildModel } from '../model/utils';
10-
import { PNLClasses } from '../constants';
1112

1213
const mockModel = require('../resources/model').mockModel;
1314

@@ -33,14 +34,15 @@ class Main extends React.Component {
3334
const model = interpreter.getModel();
3435
const metaModel = buildModel(model);
3536

36-
const componentsMap = new ComponentsMap(
37-
new Map(Object.entries({'mechanism': GenericMechanism})),
38-
new Map(Object.entries({'projection': CustomLinkWidget}))
39-
)
37+
const componentsMap = new ComponentsMap(new Map(), new Map());
38+
39+
componentsMap.nodes.set(PNLClasses.COMPOSITION, Composition);
40+
componentsMap.nodes.set(PNLClasses.MECHANISM, GenericMechanism);
41+
componentsMap.links.set(PNLClasses.PROJECTION, CustomLinkWidget);
4042

4143
return (
4244
<div className={classes.root}>
43-
<MetaDiagram metaNodes={metaModel[PNLClasses.MECHANISM]} metaLinks={metaModel[PNLClasses.PROJECTION]} componentsMap={componentsMap}
45+
<MetaDiagram metaNodes={[...metaModel[PNLClasses.COMPOSITION], ...metaModel[PNLClasses.MECHANISM],]} metaLinks={metaModel[PNLClasses.PROJECTION]} componentsMap={componentsMap}
4446
metaTheme={{
4547
customThemeVariables: {},
4648
canvasClassName: classes.canvasBG,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
import * as React from "react";
2+
import { Rnd } from "react-rnd";
3+
import { withStyles } from "@mui/styles";
4+
import { Box, Chip } from "@mui/material";
5+
import vars from "../../../assets/styles/variables";
6+
import MORE_OPTION from "../../../assets/svg/option.svg"
7+
8+
const { draggableBg, listItemActiveBg, textWhite, chipTextColor, chipBorderColor } = vars;
9+
10+
const commonStyles = {
11+
background: `${textWhite} !important`,
12+
border: `0.0975rem solid ${listItemActiveBg} !important`,
13+
borderRadius: '0.125rem !important'
14+
};
15+
16+
const styles = () => ({
17+
root: {
18+
'& .react-draggable': {
19+
background: draggableBg,
20+
border: `0.125rem solid ${chipBorderColor}`,
21+
borderRadius: '0.75rem',
22+
display: "flex !important",
23+
alignItems: "center",
24+
justifyContent: "center",
25+
26+
'&:hover': {
27+
borderColor: listItemActiveBg
28+
},
29+
},
30+
31+
'& .MuiChip-root': {
32+
background: chipBorderColor,
33+
borderRadius: '0.75rem',
34+
padding: '0 0.5rem',
35+
display: "flex",
36+
left: 0,
37+
position: 'absolute',
38+
color: chipTextColor,
39+
top: '-1.75rem',
40+
alignItems: "center",
41+
height: '1.5rem',
42+
letterSpacing: '-0.005rem',
43+
fontWeight: 510,
44+
fontSize: '0.8125rem',
45+
lineHeight: '1.25rem',
46+
flexDirection: 'row-reverse',
47+
48+
'& .MuiChip-label': {
49+
padding: 0,
50+
},
51+
52+
'& .MuiChip-icon': {
53+
margin: '0 0 0 0.25rem',
54+
},
55+
},
56+
},
57+
58+
selected: {
59+
'&:before': {
60+
left: 0,
61+
...commonStyles
62+
},
63+
64+
'&:after': {
65+
right: 0,
66+
...commonStyles
67+
},
68+
69+
'& .MuiChip-root': {
70+
background: listItemActiveBg
71+
},
72+
73+
'& .react-draggable': {
74+
borderColor: listItemActiveBg,
75+
}
76+
},
77+
});
78+
79+
class Composition extends React.Component {
80+
constructor(props) {
81+
super(props);
82+
this.state = {
83+
expanded: false,
84+
width: 442,
85+
height: 192,
86+
x: 0,
87+
y: 0
88+
}
89+
this.changeVisibility = this.changeVisibility.bind(this);
90+
}
91+
92+
changeVisibility() {
93+
this.setState({expanded: !this.state.expanded});
94+
}
95+
96+
render() {
97+
const { expanded } = this.state;
98+
const { classes } = this.props;
99+
100+
return (
101+
<Box className={`${classes.root} ${expanded ? classes.selected : ''}`}>
102+
<Rnd
103+
size={{ width: this.state.width, height: this.state.height }}
104+
position={{ x: this.state.x, y: this.state.y }}
105+
onDragStop={(e, d) => {
106+
this.setState({ x: d.x, y: d.y });
107+
}}
108+
onResizeStop={(e, direction, ref, delta, position) => {
109+
this.setState({
110+
width: ref.style.width,
111+
height: ref.style.height,
112+
...position
113+
});
114+
}}
115+
>
116+
<Chip icon={<img src={MORE_OPTION} alt="" />} label="New Comp" color="secondary" />
117+
</Rnd>
118+
</Box>
119+
);
120+
}
121+
}
122+
123+
export default withStyles(styles)(Composition);

src/components/views/mechanisms/GenericMechanism.js

+3-29
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
import * as React from "react";
22
import MechSimple from "./MechSimple";
33
import MechMetadata from "./MechMetadata";
4-
import { Rnd } from "react-rnd";
54
import { withStyles } from "@mui/styles";
6-
import { Box, Chip } from "@mui/material";
7-
import MORE_OPTION from "../../../assets/svg/option.svg"
85
import vars from "../../../assets/styles/variables";
96

107
const { draggableBg, listItemActiveBg, textWhite, chipTextColor, chipBorderColor } = vars;
@@ -97,37 +94,14 @@ class GenericMechanism extends React.Component {
9794

9895
render() {
9996
const { expanded } = this.state;
100-
const { classes } = this.props;
10197

10298
return (
103-
// <>
104-
// { expanded
105-
// ? ( <MechMetadata changeVisibility={this.changeVisibility} {...this.props} /> )
106-
// : ( <MechSimple changeVisibility={this.changeVisibility} {...this.props} /> )
107-
// }
108-
// </>
109-
<Box className={`${classes.root} ${expanded ? classes.selected : ''}`}>
110-
<Rnd
111-
size={{ width: this.state.width, height: this.state.height }}
112-
position={{ x: this.state.x, y: this.state.y }}
113-
onDragStop={(e, d) => {
114-
this.setState({ x: d.x, y: d.y });
115-
}}
116-
onResizeStop={(e, direction, ref, delta, position) => {
117-
this.setState({
118-
width: ref.style.width,
119-
height: ref.style.height,
120-
...position
121-
});
122-
}}
123-
>
124-
<Chip icon={<img src={MORE_OPTION} alt="" />} label="New Comp" color="secondary" />
125-
{ expanded
99+
<>
100+
{ expanded
126101
? ( <MechMetadata changeVisibility={this.changeVisibility} {...this.props} /> )
127102
: ( <MechSimple changeVisibility={this.changeVisibility} {...this.props} /> )
128103
}
129-
</Rnd>
130-
</Box>
104+
</>
131105
);
132106
}
133107
}

src/model/Interpreter.ts

+25-9
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { GVTypes, PNLClasses } from '../constants';
2+
import { PortTypes } from '@metacell/meta-diagram';
23
import ProjectionLink from './links/ProjectionLink';
34
import QueryService from '../services/queryService';
45
import MechanismNode from './nodes/mechanism/MechanismNode';
56
import CompositionNode from './nodes/composition/CompositionNode';
6-
import { PortTypes } from '@metacell/meta-diagram';
77

88
const html2json = require('html2json').html2json
99
const typesArray = Object.values(GVTypes);
@@ -13,10 +13,15 @@ const parse = require('dotparser');
1313
export default class ModelInterpreter {
1414
nativeModel: any;
1515
jsonModel: Object;
16+
modelMap: { [key: string]: Map<String, CompositionNode|MechanismNode|ProjectionLink|any> };
1617

1718
constructor(model: any) {
1819
this.nativeModel = model;
1920
this.jsonModel = this._convertModel(model);
21+
this.modelMap = {
22+
'nodes': new Map(),
23+
'links': new Map()
24+
};
2025
}
2126

2227
_convertModel(model: any) : Object {
@@ -26,13 +31,13 @@ export default class ModelInterpreter {
2631
};
2732

2833
parsedModel[PNLClasses.COMPOSITION] = model[PNLClasses.COMPOSITION].map((singleModel: any) => {
29-
const newModel = parse(singleModel).map((elem: any) => ModelInterpreter.castObject(elem));
34+
const newModel = parse(singleModel).map((elem: any) => ModelInterpreter.castObject(elem, undefined, this.modelMap));
3035
return newModel;
3136
});
3237

3338
parsedModel[PNLClasses.MECHANISM] = model[PNLClasses.MECHANISM].map((singleNode: any) => {
3439
let tempNode = parse(singleNode)[0].children.filter((elem: { node_id: { id: string; }; }) => elem.node_id.id !== 'graph');
35-
let newNode = tempNode.map((elem: any) => ModelInterpreter.castObject(elem));
40+
let newNode = tempNode.map((elem: any) => ModelInterpreter.castObject(elem, undefined, this.modelMap));
3641
return newNode;
3742
});
3843

@@ -51,6 +56,10 @@ export default class ModelInterpreter {
5156
return this.nativeModel;
5257
}
5358

59+
getModelElementsMap() {
60+
return this.modelMap;
61+
}
62+
5463
static parseNodePorts(name: string, type: string): { [key: string]: any } {
5564
let ports: { [key: string]: any[] } = {
5665
[PortTypes.INPUT_PORT]: [],
@@ -80,7 +89,11 @@ export default class ModelInterpreter {
8089
return ports;
8190
}
8291

83-
static castObject(item: MechanismNode|CompositionNode|ProjectionLink|any) : MechanismNode|CompositionNode|ProjectionLink {
92+
static castObject(
93+
item: MechanismNode|CompositionNode|ProjectionLink|any,
94+
parent: any|undefined,
95+
modelMap: { [key: string]: Map<String, CompositionNode|MechanismNode|ProjectionLink|any> })
96+
: MechanismNode|CompositionNode|ProjectionLink {
8497
let newNode = item;
8598
if (item?.type === undefined) {
8699
throw new TypeError('type is missing, object cannot be casted to the right class type.');
@@ -94,6 +107,8 @@ export default class ModelInterpreter {
94107
[PNLClasses.PROJECTION]: [],
95108
[PNLClasses.COMPOSITION]: [],
96109
}
110+
newNode = new CompositionNode(item.id, parent, '', false, ports, extra, children);
111+
modelMap['nodes'].set(newNode.getName(), newNode);
97112
item.children.forEach((element: any) => {
98113
if (element.type === 'attr_stmt') {
99114
extra[element.target] = {}
@@ -107,15 +122,15 @@ export default class ModelInterpreter {
107122
if (typesArray.includes(element.type)) {
108123
switch (element.type) {
109124
case GVTypes.COMPOSITION: {
110-
children[PNLClasses.COMPOSITION].push(ModelInterpreter.castObject(element));
125+
children[PNLClasses.COMPOSITION].push(ModelInterpreter.castObject(element, newNode, modelMap));
111126
break;
112127
}
113128
case GVTypes.MECHANISM: {
114-
children[PNLClasses.MECHANISM].push(ModelInterpreter.castObject(element));
129+
children[PNLClasses.MECHANISM].push(ModelInterpreter.castObject(element, newNode, modelMap));
115130
break;
116131
}
117132
case GVTypes.PROJECTION: {
118-
children[PNLClasses.PROJECTION].push(ModelInterpreter.castObject(element));
133+
children[PNLClasses.PROJECTION].push(ModelInterpreter.castObject(element, newNode, modelMap));
119134
break;
120135
}
121136
default:
@@ -125,7 +140,6 @@ export default class ModelInterpreter {
125140
}
126141
}
127142
});
128-
newNode = new CompositionNode(item.id, '', false, ports, extra, children);
129143
break;
130144
}
131145
case GVTypes.MECHANISM: {
@@ -142,7 +156,8 @@ export default class ModelInterpreter {
142156
extra[singleAttr?.id] = singleAttr?.eq;
143157
}
144158
});
145-
newNode = new MechanismNode(item?.node_id?.id, '', false, ports, extra);
159+
newNode = new MechanismNode(item?.node_id?.id, parent, '', false, ports, extra);
160+
modelMap['nodes'].set(newNode.getName(), newNode);
146161
break;
147162
}
148163
case GVTypes.PROJECTION: {
@@ -165,6 +180,7 @@ export default class ModelInterpreter {
165180
receiverPort = item.edge_list[1]['port']['id'];
166181
}
167182
newNode = new ProjectionLink(name, sender, senderPort, receiver, receiverPort, false, extra);
183+
modelMap['links'].set(newNode.getName(), newNode);
168184
break;
169185
}
170186
default:

0 commit comments

Comments
 (0)