Skip to content

Commit

Permalink
Merge pull request #46 from MetaCell/feature/34
Browse files Browse the repository at this point in the history
Tests for frontend model interpreter + refactoring in the installation process + model interpreter refactoring
  • Loading branch information
zsinnema authored Aug 11, 2022
2 parents f4c7f1b + 74b6415 commit d48582f
Show file tree
Hide file tree
Showing 18 changed files with 1,359 additions and 594 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,6 @@ yarn-error.log*
/dist/
/node_modules/
public/config.ini
dependencies/*
dependencies/*
.yalc
yalc.lock
5 changes: 1 addition & 4 deletions config-overrides.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,5 @@ module.exports = function override(config, env) {
Buffer: ["buffer", "Buffer"],
}),
]
// console.log(config.resolve)
// console.log(config.plugins)

return config
}
}
25 changes: 25 additions & 0 deletions dev_setup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/bin/bash

# TODO we will uncomment the below when we will have the deployment for this
#mv package.json old_package.json
#mv package.dev package.json
npm -g install yalc

if [ -d '../meta-diagram' ]; then
cd ../meta-diagram;
yarn && yarn run build:dev && yalc push --changed
cd -
else
cd ../
git clone https://github.com/metacell/meta-diagram
cd meta-diagram
yarn && yarn run build:dev && yalc push --changed
cd -
fi

yalc add @metacell/meta-diagram
yarn
yarn run start
#mv package.json package.dev
#mv old_package.json package.json

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"@fortawesome/fontawesome-svg-core": "^1.2.35",
"@fortawesome/free-solid-svg-icons": "^5.13.0",
"@fortawesome/react-fontawesome": "^0.1.9",
"@metacell/meta-diagram": "file:.yalc/@metacell/meta-diagram",
"@mui/icons-material": "^5.8.4",
"@mui/material": "^5.8.4",
"@mui/styles": "^5.8.4",
Expand All @@ -25,7 +26,6 @@
"electron-is-dev": "^1.2.0",
"html2json": "^1.0.2",
"lodash": "^4.17.21",
"meta-diagram": "github:MetaCell/meta-diagram#develop",
"pathfinding": "^0.4.18",
"paths-js": "^0.4.11",
"process": "^0.11.10",
Expand All @@ -42,6 +42,7 @@
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test",
"test-no-watch": "react-app-rewired test --watchAll=false",
"eject": "react-app-rewired eject",
"dev": "concurrently -k \"BROWSER=none npm start\" \"npm:electron\"",
"electron": "wait-on tcp:3000 && electron ."
Expand Down
8 changes: 0 additions & 8 deletions src/App.test.js

This file was deleted.

13 changes: 7 additions & 6 deletions src/components/Main.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ import React from 'react';
import { withStyles } from '@mui/styles';
import BG from "../assets/svg/bg-dotted.svg";
import ModelInterpreter from '../model/Interpreter';
import MetaDiagram, { ComponentsMap } from "meta-diagram";
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;

Expand All @@ -32,14 +33,14 @@ 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(Object.entries({'mechanism': GenericMechanism})),
new Map(Object.entries({'projection': CustomLinkWidget}))
)

return (
<div className={classes.root}>
<MetaDiagram metaNodes={metaModel.mechanisms} metaLinks={metaModel.projections} componentsMap={componentsMap}
<MetaDiagram metaNodes={metaModel[PNLClasses.MECHANISM]} metaLinks={metaModel[PNLClasses.PROJECTION]} componentsMap={componentsMap}
metaTheme={{
customThemeVariables: {},
canvasClassName: classes.canvasBG,
Expand Down
2 changes: 1 addition & 1 deletion src/components/views/mechanisms/CustomNodeWidget.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from "react";
import {DiagramEngine, PortWidget} from "@projectstorm/react-diagrams";
import {MetaNodeModel} from "meta-diagram";
import {MetaNodeModel} from "@metacell/meta-diagram";
import {Typography} from "@mui/material";

export class CustomNodeWidget extends React.Component {
Expand Down
2 changes: 1 addition & 1 deletion src/components/views/projections/CustomLinkWidget.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as React from "react";
import {MetaLinkModel} from "meta-diagram";
import {MetaLinkModel} from "@metacell/meta-diagram";

export class CustomLinkWidget extends React.Component {
constructor(props) {
Expand Down
8 changes: 7 additions & 1 deletion src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,14 @@ export enum Direction {
OUTPUT = "out",
}

export enum PNLTypes {
export enum GVTypes {
COMPOSITION = 'digraph',
MECHANISM = 'node_stmt',
PROJECTION = 'edge_stmt'
}

export enum PNLClasses {
COMPOSITION = 'composition',
MECHANISM = 'mechanism',
PROJECTION = 'projection'
}
117 changes: 110 additions & 7 deletions src/model/Interpreter.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import { castObject } from './utils';
// import { castObject } from './utils';
import { GVTypes, PNLClasses } from '../constants';
import ProjectionLink from './links/ProjectionLink';
import MechanismNode from './nodes/mechanism/MechanismNode';
import CompositionNode from './nodes/composition/CompositionNode';

const html2json = require('html2json').html2json
const typesArray = Object.values(GVTypes);
const parse = require('dotparser');


Expand All @@ -13,18 +20,18 @@ export default class ModelInterpreter {

_convertModel(model: any) : Object {
const parsedModel = {
'compositions': [],
'mechanisms': [],
[PNLClasses.COMPOSITION]: [],
[PNLClasses.MECHANISM]: [],
};

parsedModel.compositions = model.compositions.map((singleModel: any) => {
const newModel = parse(singleModel).map((elem: any) => castObject(elem));
parsedModel[PNLClasses.COMPOSITION] = model[PNLClasses.COMPOSITION].map((singleModel: any) => {
const newModel = parse(singleModel).map((elem: any) => ModelInterpreter.castObject(elem));
return newModel;
});

parsedModel.mechanisms = model.mechanisms.map((singleNode: any) => {
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) => castObject(elem));
let newNode = tempNode.map((elem: any) => ModelInterpreter.castObject(elem));
return newNode;
});

Expand All @@ -42,4 +49,100 @@ export default class ModelInterpreter {
getNativeModel() {
return this.nativeModel;
}

static castObject(item: MechanismNode|CompositionNode|ProjectionLink|any) : 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.');
}
switch (item.type) {
case GVTypes.COMPOSITION: {
let extra: { [key: string]: any } = {};
let ports : any = [];
let children: { [key: string]: any } = {
[PNLClasses.MECHANISM]: [],
[PNLClasses.PROJECTION]: [],
[PNLClasses.COMPOSITION]: [],
}
item.children.forEach((element: any) => {
if (element.type === 'attr_stmt') {
extra[element.target] = {}
element.attr_list.forEach( (innerElement: any) => {
if (innerElement.type === 'attr') {
extra[element.target][innerElement?.id] = innerElement?.eq;
}
});
return;
}
if (typesArray.includes(element.type)) {
switch (element.type) {
case GVTypes.COMPOSITION: {
children[PNLClasses.COMPOSITION].push(ModelInterpreter.castObject(element));
break;
}
case GVTypes.MECHANISM: {
children[PNLClasses.MECHANISM].push(ModelInterpreter.castObject(element));
break;
}
case GVTypes.PROJECTION: {
children[PNLClasses.PROJECTION].push(ModelInterpreter.castObject(element));
break;
}
default:
// TODO: enable this in the future
// throw new Error(`Casting error, "${item.type}" type not known.`);
console.log(`Casting error, "${item.type}" type not known.`);
}
}
});
newNode = new CompositionNode(item.id, '', false, ports, extra, children);
break;
}
case GVTypes.MECHANISM: {
let ports : any = [];
let extra: { [key: string]: any } = {};
item.attr_list.forEach((singleAttr: any) => {
if (singleAttr.id === 'label') {
// TODO: implement the parsing of the json structure generated below
// in order to detect ports and other elements of the node.
//
// parsedHtml = html2json(singleAttr.eq);
return;
}
if (singleAttr.type === 'attr') {
extra[singleAttr?.id] = singleAttr?.eq;
}
});
newNode = new MechanismNode(item?.node_id?.id, '', false, ports, extra);
break;
}
case GVTypes.PROJECTION: {
let name = '';
let extra: { [key: string]: any } = {};
let sender, senderPort, receiver, receiverPort;
item.attr_list.forEach((singleAttr: any) => {
if (singleAttr.id === 'label') {
name = singleAttr.eq;
return;
}
if (singleAttr.type === 'attr') {
extra[singleAttr?.id] = singleAttr?.eq;
}
});
if (item.edge_list.length === 2) {
sender = item.edge_list[0].id;
senderPort = item.edge_list[0]['port']['id'];
receiver = item.edge_list[1].id;
receiverPort = item.edge_list[1]['port']['id'];
}
newNode = new ProjectionLink(name, sender, senderPort, receiver, receiverPort, false, extra);
break;
}
default:
// TODO: enable this in the future
// throw new Error(`Casting error, "${item.type}" type not known.`);
console.log(`Casting error, "${item.type}" type not known.`);
}
return newNode;
}
}
9 changes: 8 additions & 1 deletion src/model/links/ProjectionLink.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// import MetaLink from 'meta-diagram';
import IMetaLinkConverter from './IMetaLinkConverter';
import { MetaLink } from 'meta-diagram';
import { MetaLink } from '@metacell/meta-diagram';
import { PNLClasses } from '../../constants';

export default class ProjectionLink implements IMetaLinkConverter {
name: string;
Expand All @@ -10,6 +11,7 @@ export default class ProjectionLink implements IMetaLinkConverter {
receiverPort: string;
extra: Object;
isExpanded: Boolean;
innerClass: String;

constructor(name: string, sender: string, senderPort: string, receiver: string, receiverPort: string, isExpanded?: Boolean, extra?: Object) {
this.name = name;
Expand All @@ -19,6 +21,7 @@ export default class ProjectionLink implements IMetaLinkConverter {
this.receiverPort = receiverPort;
this.extra = extra !== undefined ? extra : {};
this.isExpanded = isExpanded !== undefined ? isExpanded : false;
this.innerClass = PNLClasses.PROJECTION;
}

getName() : string {
Expand Down Expand Up @@ -73,4 +76,8 @@ export default class ProjectionLink implements IMetaLinkConverter {
)
);
}

getType(): String {
return this.innerClass;
}
}
2 changes: 1 addition & 1 deletion src/model/nodes/IMetaDiagramConverter.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { MetaNode } from 'meta-diagram';
import { MetaNode } from '@metacell/meta-diagram';

export default interface IMetaDiagramConverter {
getMetaNode(): MetaNode;
Expand Down
40 changes: 32 additions & 8 deletions src/model/nodes/composition/CompositionNode.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
// 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 { castObject } from '../../utils';
import ProjectionLink from '../../links/ProjectionLink';
// import { castObject } from '../../utils';


export default class CompositionNode extends MechanismNode {
children: Array<MechanismNode|CompositionNode>;
childrenMap: Map<String, MechanismNode|CompositionNode>;
children: {[key: string]: any};
childrenMap: Map<String, MechanismNode|CompositionNode|ProjectionLink>;
innerClass: String;

constructor(name: string, icon?: string, isExpaded?: boolean, ports?: Array<PortNode>, extra?: Object, children?: Array<MechanismNode|CompositionNode>) {
constructor(name: string, icon?: string, isExpaded?: boolean, ports?: Array<PortNode>, extra?: Object, children?: {[key: string]: any}) {
super(name, icon, isExpaded, ports, extra);

this.childrenMap = new Map();
this.children = children !== undefined ? children : [];
this.children = children !== undefined ? children : {
'mechanisms': [],
'projections': [],
'compositions': [],
};
this.innerClass = PNLClasses.COMPOSITION;
}

addChild(child: any) {
Expand All @@ -25,15 +34,30 @@ export default class CompositionNode extends MechanismNode {
return;
}

const castChild = castObject(child);
const castChild = ModelInterpreter.castObject(child);
this.childrenMap.set(child.id, castChild);
this.children.push(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;
}
}

getChildren() : Array<MechanismNode|CompositionNode> {
getChildren() : {[key: string]: any} {
return this.children;
}

getType(): String {
return this.innerClass;
}

getMetaDiagram() : any {
console.log("Composition Node implementation of getMetaDiagram.");
}
Expand Down
Loading

0 comments on commit d48582f

Please sign in to comment.