diff --git a/src/components/Main.js b/src/components/Main.js
index d437f503..d079ab17 100644
--- a/src/components/Main.js
+++ b/src/components/Main.js
@@ -1,13 +1,14 @@
import React from 'react';
// import MechanismNode from '../model/nodes/mechanism/MechanismNode';
import { withStyles } from '@mui/styles';
+import { PNLClasses } from '../constants';
+import { buildModel } from '../model/utils';
import BG from "../assets/svg/bg-dotted.svg";
import ModelInterpreter from '../model/Interpreter';
+import Composition from './views/compositions/Composition';
+import GenericMechanism from './views/mechanisms/GenericMechanism';
import MetaDiagram, { ComponentsMap } from "@metacell/meta-diagram";
import CustomLinkWidget from './views/projections/CustomLinkWidget';
-import GenericMechanism from './views/mechanisms/GenericMechanism';
-import { buildModel } from '../model/utils';
-import { PNLClasses } from '../constants';
const mockModel = require('../resources/model').mockModel;
@@ -33,14 +34,15 @@ class Main extends React.Component {
const model = interpreter.getModel();
const metaModel = buildModel(model);
- const componentsMap = new ComponentsMap(
- new Map(Object.entries({'mechanism': GenericMechanism})),
- new Map(Object.entries({'projection': CustomLinkWidget}))
- )
+ const componentsMap = new ComponentsMap(new Map(), new Map());
+
+ componentsMap.nodes.set(PNLClasses.COMPOSITION, Composition);
+ componentsMap.nodes.set(PNLClasses.MECHANISM, GenericMechanism);
+ componentsMap.links.set(PNLClasses.PROJECTION, CustomLinkWidget);
return (
-
({
+ root: {
+ '& .react-draggable': {
+ background: draggableBg,
+ border: `0.125rem solid ${chipBorderColor}`,
+ borderRadius: '0.75rem',
+ display: "flex !important",
+ alignItems: "center",
+ justifyContent: "center",
+
+ '&:hover': {
+ borderColor: listItemActiveBg
+ },
+ },
+
+ '& .MuiChip-root': {
+ background: chipBorderColor,
+ borderRadius: '0.75rem',
+ padding: '0 0.5rem',
+ display: "flex",
+ left: 0,
+ position: 'absolute',
+ color: chipTextColor,
+ top: '-1.75rem',
+ alignItems: "center",
+ height: '1.5rem',
+ letterSpacing: '-0.005rem',
+ fontWeight: 510,
+ fontSize: '0.8125rem',
+ lineHeight: '1.25rem',
+ flexDirection: 'row-reverse',
+
+ '& .MuiChip-label': {
+ padding: 0,
+ },
+
+ '& .MuiChip-icon': {
+ margin: '0 0 0 0.25rem',
+ },
+ },
+ },
+
+ selected: {
+ '&:before': {
+ left: 0,
+ ...commonStyles
+ },
+
+ '&:after': {
+ right: 0,
+ ...commonStyles
+ },
+
+ '& .MuiChip-root': {
+ background: listItemActiveBg
+ },
+
+ '& .react-draggable': {
+ borderColor: listItemActiveBg,
+ }
+ },
+});
+
+class Composition extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ expanded: false,
+ width: 442,
+ height: 192,
+ x: 0,
+ y: 0
+ }
+ this.changeVisibility = this.changeVisibility.bind(this);
+ }
+
+ changeVisibility() {
+ this.setState({expanded: !this.state.expanded});
+ }
+
+ render() {
+ const { expanded } = this.state;
+ const { classes } = this.props;
+
+ return (
+
+ {
+ this.setState({ x: d.x, y: d.y });
+ }}
+ onResizeStop={(e, direction, ref, delta, position) => {
+ this.setState({
+ width: ref.style.width,
+ height: ref.style.height,
+ ...position
+ });
+ }}
+ >
+ } label="New Comp" color="secondary" />
+
+
+ );
+ }
+}
+
+export default withStyles(styles)(Composition);
diff --git a/src/components/views/mechanisms/GenericMechanism.js b/src/components/views/mechanisms/GenericMechanism.js
index 74ebdce1..e591606b 100644
--- a/src/components/views/mechanisms/GenericMechanism.js
+++ b/src/components/views/mechanisms/GenericMechanism.js
@@ -1,10 +1,7 @@
import * as React from "react";
import MechSimple from "./MechSimple";
import MechMetadata from "./MechMetadata";
-import { Rnd } from "react-rnd";
import { withStyles } from "@mui/styles";
-import { Box, Chip } from "@mui/material";
-import MORE_OPTION from "../../../assets/svg/option.svg"
import vars from "../../../assets/styles/variables";
const { draggableBg, listItemActiveBg, textWhite, chipTextColor, chipBorderColor } = vars;
@@ -97,37 +94,14 @@ class GenericMechanism extends React.Component {
render() {
const { expanded } = this.state;
- const { classes } = this.props;
return (
- // <>
- // { expanded
- // ? ( )
- // : ( )
- // }
- // >
-
- {
- this.setState({ x: d.x, y: d.y });
- }}
- onResizeStop={(e, direction, ref, delta, position) => {
- this.setState({
- width: ref.style.width,
- height: ref.style.height,
- ...position
- });
- }}
- >
- } label="New Comp" color="secondary" />
- { expanded
+ <>
+ { expanded
? ( )
: ( )
}
-
-
+ >
);
}
}
diff --git a/src/model/Interpreter.ts b/src/model/Interpreter.ts
index 58d5fcb2..0fe782c8 100644
--- a/src/model/Interpreter.ts
+++ b/src/model/Interpreter.ts
@@ -1,9 +1,9 @@
import { GVTypes, PNLClasses } from '../constants';
+import { PortTypes } from '@metacell/meta-diagram';
import ProjectionLink from './links/ProjectionLink';
import QueryService from '../services/queryService';
import MechanismNode from './nodes/mechanism/MechanismNode';
import CompositionNode from './nodes/composition/CompositionNode';
-import { PortTypes } from '@metacell/meta-diagram';
const html2json = require('html2json').html2json
const typesArray = Object.values(GVTypes);
@@ -13,10 +13,15 @@ const parse = require('dotparser');
export default class ModelInterpreter {
nativeModel: any;
jsonModel: Object;
+ modelMap: { [key: string]: Map };
constructor(model: any) {
this.nativeModel = model;
this.jsonModel = this._convertModel(model);
+ this.modelMap = {
+ 'nodes': new Map(),
+ 'links': new Map()
+ };
}
_convertModel(model: any) : Object {
@@ -26,13 +31,13 @@ export default class ModelInterpreter {
};
parsedModel[PNLClasses.COMPOSITION] = model[PNLClasses.COMPOSITION].map((singleModel: any) => {
- const newModel = parse(singleModel).map((elem: any) => ModelInterpreter.castObject(elem));
+ const newModel = parse(singleModel).map((elem: any) => ModelInterpreter.castObject(elem, undefined, this.modelMap));
return newModel;
});
parsedModel[PNLClasses.MECHANISM] = model[PNLClasses.MECHANISM].map((singleNode: any) => {
let tempNode = parse(singleNode)[0].children.filter((elem: { node_id: { id: string; }; }) => elem.node_id.id !== 'graph');
- let newNode = tempNode.map((elem: any) => ModelInterpreter.castObject(elem));
+ let newNode = tempNode.map((elem: any) => ModelInterpreter.castObject(elem, undefined, this.modelMap));
return newNode;
});
@@ -51,6 +56,10 @@ export default class ModelInterpreter {
return this.nativeModel;
}
+ getModelElementsMap() {
+ return this.modelMap;
+ }
+
static parseNodePorts(name: string, type: string): { [key: string]: any } {
let ports: { [key: string]: any[] } = {
[PortTypes.INPUT_PORT]: [],
@@ -80,7 +89,11 @@ export default class ModelInterpreter {
return ports;
}
- static castObject(item: MechanismNode|CompositionNode|ProjectionLink|any) : MechanismNode|CompositionNode|ProjectionLink {
+ static castObject(
+ item: MechanismNode|CompositionNode|ProjectionLink|any,
+ parent: any|undefined,
+ modelMap: { [key: string]: Map })
+ : MechanismNode|CompositionNode|ProjectionLink {
let newNode = item;
if (item?.type === undefined) {
throw new TypeError('type is missing, object cannot be casted to the right class type.');
@@ -94,6 +107,8 @@ export default class ModelInterpreter {
[PNLClasses.PROJECTION]: [],
[PNLClasses.COMPOSITION]: [],
}
+ newNode = new CompositionNode(item.id, parent, '', false, ports, extra, children);
+ modelMap['nodes'].set(newNode.getName(), newNode);
item.children.forEach((element: any) => {
if (element.type === 'attr_stmt') {
extra[element.target] = {}
@@ -107,15 +122,15 @@ export default class ModelInterpreter {
if (typesArray.includes(element.type)) {
switch (element.type) {
case GVTypes.COMPOSITION: {
- children[PNLClasses.COMPOSITION].push(ModelInterpreter.castObject(element));
+ children[PNLClasses.COMPOSITION].push(ModelInterpreter.castObject(element, newNode, modelMap));
break;
}
case GVTypes.MECHANISM: {
- children[PNLClasses.MECHANISM].push(ModelInterpreter.castObject(element));
+ children[PNLClasses.MECHANISM].push(ModelInterpreter.castObject(element, newNode, modelMap));
break;
}
case GVTypes.PROJECTION: {
- children[PNLClasses.PROJECTION].push(ModelInterpreter.castObject(element));
+ children[PNLClasses.PROJECTION].push(ModelInterpreter.castObject(element, newNode, modelMap));
break;
}
default:
@@ -125,7 +140,6 @@ export default class ModelInterpreter {
}
}
});
- newNode = new CompositionNode(item.id, '', false, ports, extra, children);
break;
}
case GVTypes.MECHANISM: {
@@ -142,7 +156,8 @@ export default class ModelInterpreter {
extra[singleAttr?.id] = singleAttr?.eq;
}
});
- newNode = new MechanismNode(item?.node_id?.id, '', false, ports, extra);
+ newNode = new MechanismNode(item?.node_id?.id, parent, '', false, ports, extra);
+ modelMap['nodes'].set(newNode.getName(), newNode);
break;
}
case GVTypes.PROJECTION: {
@@ -165,6 +180,7 @@ export default class ModelInterpreter {
receiverPort = item.edge_list[1]['port']['id'];
}
newNode = new ProjectionLink(name, sender, senderPort, receiver, receiverPort, false, extra);
+ modelMap['links'].set(newNode.getName(), newNode);
break;
}
default:
diff --git a/src/model/nodes/composition/CompositionNode.ts b/src/model/nodes/composition/CompositionNode.ts
index 204ff8a1..9a7fb71f 100644
--- a/src/model/nodes/composition/CompositionNode.ts
+++ b/src/model/nodes/composition/CompositionNode.ts
@@ -1,20 +1,25 @@
-// import MetaDiagram from 'meta-diagram';
-import Port from '../PortNode';
-import PortNode from '../PortNode';
import { PNLClasses } from '../../../constants';
import ModelInterpreter from '../../Interpreter';
import MechanismNode from '../mechanism/MechanismNode';
import ProjectionLink from '../../links/ProjectionLink';
-// import { castObject } from '../../utils';
-
+import { MetaNode, MetaPort, Position, PortTypes } from '@metacell/meta-diagram';
export default class CompositionNode extends MechanismNode {
children: {[key: string]: any};
childrenMap: Map;
innerClass: String;
+ parent: MechanismNode|CompositionNode|undefined;
- constructor(name: string, icon?: string, isExpaded?: boolean, ports?: { [key: string]: Array }, extra?: Object, children?: {[key: string]: any}) {
- super(name, icon, isExpaded, ports, extra);
+ constructor(
+ name: string,
+ parent: MechanismNode|CompositionNode|undefined,
+ icon?: string,
+ isExpaded?: boolean,
+ ports?: { [key: string]: Array },
+ extra?: Object,
+ children?: {[key: string]: any})
+ {
+ super(name, parent, icon, isExpaded, ports, extra);
this.childrenMap = new Map();
this.children = children !== undefined ? children : {
@@ -34,20 +39,20 @@ export default class CompositionNode extends MechanismNode {
return;
}
- const castChild = ModelInterpreter.castObject(child);
- this.childrenMap.set(child.id, castChild);
+ // const castChild = ModelInterpreter.castObject(child, this.parent);
+ // this.childrenMap.set(child.id, castChild);
- switch(castChild.getType()) {
- case PNLClasses.COMPOSITION:
- this.children[PNLClasses.COMPOSITION].push(castChild);
- break;
- case PNLClasses.MECHANISM:
- this.children[PNLClasses.MECHANISM].push(castChild);
- break;
- case PNLClasses.PROJECTION:
- this.children[PNLClasses.PROJECTION].push(castChild);
- break;
- }
+ // switch(castChild.getType()) {
+ // case PNLClasses.COMPOSITION:
+ // this.children[PNLClasses.COMPOSITION].push(castChild);
+ // break;
+ // case PNLClasses.MECHANISM:
+ // this.children[PNLClasses.MECHANISM].push(castChild);
+ // break;
+ // case PNLClasses.PROJECTION:
+ // this.children[PNLClasses.PROJECTION].push(castChild);
+ // break;
+ // }
}
getChildren() : {[key: string]: any} {
@@ -58,7 +63,33 @@ export default class CompositionNode extends MechanismNode {
return this.innerClass;
}
- getMetaDiagram() : any {
- console.log("Composition Node implementation of getMetaDiagram.");
+ getMetaNode() : any {
+ // TODO: get position from the graphviz data
+ let x = 200 + Math.random() * 600;
+ let y = 200 + Math.random() * 600;
+ let parent = this.parent ? this.parent.getMetaNode() : undefined;
+ let ports: Array = []
+ // TODO: the MetaPort has the enum prefix cause the projections are created with that prefix
+ // from the graphviz data we get.
+ // this.ports[PortTypes.INPUT_PORT].forEach((port: any) => ports.push(new MetaPort(PortTypes.INPUT_PORT + '-' + port, PortTypes.INPUT_PORT + '-' + port, PortTypes.INPUT_PORT, new Position(0, 0), new Map())));
+ // this.ports[PortTypes.OUTPUT_PORT].forEach((port: any) => ports.push(new MetaPort(PortTypes.OUTPUT_PORT + '-' + port, PortTypes.OUTPUT_PORT + '-' + port, PortTypes.OUTPUT_PORT, new Position(0, 0), new Map())));
+ // this.ports[PortTypes.PARAMETER_PORT].forEach((port: any) => ports.push(new MetaPort(PortTypes.PARAMETER_PORT + '-' + port, PortTypes.PARAMETER_PORT + '-' + port, PortTypes.PARAMETER_PORT, new Position(0, 0), new Map())));
+ return new MetaNode(
+ this.name,
+ this.name,
+ PNLClasses.COMPOSITION,
+ new Position(x, y),
+ 'node-gray',
+ parent,
+ ports,
+ new Map(Object.entries({
+ name: 'Mechanism Name',
+ variant: 'node-gray',
+ pnlClass: 'ProcessingMechanism',
+ shape: 'circle',
+ selected: false
+ })
+ )
+ );
}
}
\ No newline at end of file
diff --git a/src/model/nodes/mechanism/MechanismNode.ts b/src/model/nodes/mechanism/MechanismNode.ts
index 73a75dca..121159ea 100644
--- a/src/model/nodes/mechanism/MechanismNode.ts
+++ b/src/model/nodes/mechanism/MechanismNode.ts
@@ -1,5 +1,6 @@
import { PNLClasses } from '../../../constants';
import IMetaDiagramConverter from '../IMetaDiagramConverter';
+import CompositionNode from '../composition/CompositionNode';
import { MetaNode, MetaPort, Position, PortTypes } from '@metacell/meta-diagram';
export default class MechanismNode implements IMetaDiagramConverter {
@@ -9,14 +10,23 @@ export default class MechanismNode implements IMetaDiagramConverter {
ports: { [key: string]: Array } ;
extra: Object;
innerClass: String;
+ parent: MechanismNode|CompositionNode|undefined;
- constructor(name: string, icon?: string, isExpaded?: boolean, ports?: { [key: string]: Array }, extra?: Object) {
+ constructor(
+ name: string,
+ parent: MechanismNode|CompositionNode|undefined,
+ icon?: string,
+ isExpaded?: boolean,
+ ports?: { [key: string]: Array },
+ extra?: Object)
+ {
this.name = name;
this.icon = icon !== undefined ? icon : "";
this.ports = ports !== undefined ? ports : {};
this.extra = extra !== undefined ? extra : [];
this.isExpanded = isExpaded !== undefined ? isExpaded : false;
this.innerClass = PNLClasses.MECHANISM;
+ this.parent = parent;
}
getName() : string {
@@ -56,18 +66,20 @@ export default class MechanismNode implements IMetaDiagramConverter {
// TODO: get position from the graphviz data
let x = 200 + Math.random() * 600;
let y = 200 + Math.random() * 600;
+ let parent = this.parent ? this.parent.getMetaNode() : undefined;
let ports: Array = []
// TODO: the MetaPort has the enum prefix cause the projections are created with that prefix
// from the graphviz data we get.
this.ports[PortTypes.INPUT_PORT].forEach((port: any) => ports.push(new MetaPort(PortTypes.INPUT_PORT + '-' + port, PortTypes.INPUT_PORT + '-' + port, PortTypes.INPUT_PORT, new Position(0, 0), new Map())));
this.ports[PortTypes.OUTPUT_PORT].forEach((port: any) => ports.push(new MetaPort(PortTypes.OUTPUT_PORT + '-' + port, PortTypes.OUTPUT_PORT + '-' + port, PortTypes.OUTPUT_PORT, new Position(0, 0), new Map())));
- // this.ports[PortTypes.PARAMETER_PORT].forEach((port: any) => ports.push(new MetaPort(PortTypes.PARAMETER_PORT + '-' + port, PortTypes.PARAMETER_PORT + '-' + port, PortTypes.PARAMETER_PORT, new Position(0, 0), new Map())));
+ this.ports[PortTypes.PARAMETER_PORT].forEach((port: any) => ports.push(new MetaPort(PortTypes.PARAMETER_PORT + '-' + port, PortTypes.PARAMETER_PORT + '-' + port, PortTypes.PARAMETER_PORT, new Position(0, 0), new Map())));
return new MetaNode(
this.name,
this.name,
- 'mechanism',
+ PNLClasses.MECHANISM,
new Position(x, y),
'node-gray',
+ parent,
ports,
new Map(Object.entries({
name: 'Mechanism Name',
diff --git a/src/model/utils.js b/src/model/utils.js
index 3a6d2d12..26b25e07 100644
--- a/src/model/utils.js
+++ b/src/model/utils.js
@@ -48,13 +48,11 @@ export function buildModel(frontendModel, coord, prevModel) {
frontendModel[PNLClasses.COMPOSITION]?.forEach( node => {
if (Array.isArray(node)) {
node.forEach( comp => {
- // TODO: create the composition and add it to the model
- coordinates.y += 250;
+ finalModel[PNLClasses.COMPOSITION]?.push(comp.getMetaNode());
buildModel(comp.children, coordinates, finalModel);
});
} else {
- // TODO: create the composition and add it to the model
- coordinates.y += 250;
+ finalModel[PNLClasses.COMPOSITION]?.push(node.getMetaNode());
buildModel(node.children, coordinates, finalModel);
}
});