Skip to content

Commit

Permalink
Fix errors for al model element configurations when uploading new bpmn
Browse files Browse the repository at this point in the history
  • Loading branch information
LeonBein committed Oct 25, 2023
1 parent 7281122 commit 474f83e
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 14 deletions.
7 changes: 7 additions & 0 deletions dataModel/DataModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ SimulationModelModdle.prototype.isEnumType = function (typeName) {

// Eg. limitToDataScheme(myScenario)
export function limitToDataScheme(object) {
if(object === undefined) return null;
return Object.fromEntries(Object.entries(object)
.map(([key, value]) => ({key, value, moddleProperty : object.$descriptor.properties.find(prop => parseNameNS(prop.name).localName === key)}) )
.filter(({moddleProperty}) => moddleProperty)
Expand All @@ -124,4 +125,10 @@ export function limitToDataScheme(object) {
value.map(limitToDataScheme) :
limitToDataScheme(value)])
);
}

export function assign(moddleElement, plainObject) {
Object.entries(SimulationModelModdle.getInstance().create(moddleElement.$descriptor.name, plainObject))
.filter(([key, value]) => moddleElement.$descriptor.properties.find(prop => parseNameNS(prop.name).localName === key))
.forEach(([key, value]) => moddleElement[key] = value);
}
2 changes: 1 addition & 1 deletion dataModel/SimulationModelDescriptor.js
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ export const SimulationModelDescriptor = {
"name": "Gateway",
"superClass": ["ModelElement"],
"properties": [
{ "name": "probabilities", "type": "String" } // TODO this shouldn't work, but it does. It is actually a map to String
{ "name": "probabilities", "type": "String", default : {} } // TODO this shouldn't work, but it does. It is actually a map to String
]
},

Expand Down
54 changes: 50 additions & 4 deletions frontend/cypress/e2e/application.cy.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { getScenarioFileName, purgeDatabase, setFile, updateProject } from "../../src/util/Storage";
import { deepCopy } from "../../src/util/ObjectUtil";
import { CopyIcon, DeleteIcon } from "@chakra-ui/icons";
import { FiEye } from "react-icons/fi";
import { renderToString } from 'react-dom/server';
Expand All @@ -13,11 +14,21 @@ function udescribe(){}; // For debug; quick way to comment out a test

const defaultProjectName = 'testProject';
const defaultScenarioName = defaultScenarioData.scenarioName;
const noModelConfigScenarioName = defaultScenarioName + '_noModelConfig';

function loadDefaultProjectData() {
const fileName = getScenarioFileName(defaultScenarioName);
return cy.wrap((async () => {
await setFile(defaultProjectName, fileName, JSON.stringify(defaultScenarioData));
// Default Scenario
const defaultScenarioFileName = getScenarioFileName(defaultScenarioName);
await setFile(defaultProjectName, defaultScenarioFileName, JSON.stringify(defaultScenarioData));

// Scenario without model data (as if it was newly created)
const noModelConfigScenarioData = deepCopy(defaultScenarioData);
noModelConfigScenarioData.scenarioName = noModelConfigScenarioName;
noModelConfigScenarioData.models[0].modelParameter = {};
const noModelConfigScenarioFileName = getScenarioFileName(noModelConfigScenarioData.scenarioName);
await setFile(defaultProjectName, noModelConfigScenarioFileName, JSON.stringify(noModelConfigScenarioData));

await updateProject(defaultProjectName);
})()).then(() => cy.reload()) // Reload to ensure new data is displayed
}
Expand Down Expand Up @@ -95,7 +106,10 @@ describe('Inside a project', () => {
beforeEach(() => {
cy.visit('http://localhost:3000'); // Necessary duplicate to avoid not being able to click on select project
// load and open default project:
loadDefaultProjectData().then(() => cy.findByText(defaultProjectName).click())
loadDefaultProjectData().then(() => {
cy.findByText(defaultProjectName).click();
cy.get('select').select(defaultScenarioName);
});
});


Expand Down Expand Up @@ -194,14 +208,41 @@ describe('Inside a project', () => {
}

const defaultModelParameter = defaultScenarioData.models[0].modelParameter;
const parameters = [{scenarioName : defaultScenarioName}, {scenarioName : noModelConfigScenarioName}];

beforeEach(() => cy.visit('http://localhost:3000/modelbased'));

// BEGIN foreach scenario
parameters.forEach(currentParameters => { describe(JSON.stringify(currentParameters), () => {

beforeEach(() => {
cy.visit('http://localhost:3000/modelbased');
cy.get('select').select(currentParameters.scenarioName);
});

it('shows all activities and gateways', () => {
[... defaultModelParameter.activities, ... defaultModelParameter.gateways]
.forEach(({id}) => getModelElement(id).should('exist'));
});

//TODO refactor common code between edit element tests

it('allows to edit activity costs', () => {
const field = () => cy.findAllByRole('textbox', { name: /.*cost.*/gi }).first();
const selectElement = () => {
getModelElement(defaultModelParameter.activities[0].id).click();
cy.findByText('General Parameters').click();
};
const value = 42.0;

selectElement();
field().type('{selectAll}{backspace}'+value);
cy.wait(1000); // After each keystroke there is a short delay until saved to allow more inputs
cy.reload();
cy.get('select').select(currentParameters.scenarioName);
selectElement();
field().should('have.value', ''+value);;
});

it('allows to edit gateway probabilities', () => {
const field = () => cy.findAllByRole('textbox', { name: /to.*/g }).first();
const selectElement = () => getModelElement(defaultModelParameter.gateways[0].id).click();
Expand All @@ -211,6 +252,7 @@ describe('Inside a project', () => {
field().type('{selectAll}{backspace}'+value);
cy.wait(1000); // After each keystroke there is a short delay until saved to allow more inputs
cy.reload();
cy.get('select').select(currentParameters.scenarioName);
selectElement();
field().should('have.value', ''+value);;
});
Expand All @@ -228,9 +270,13 @@ describe('Inside a project', () => {
field().type('{selectAll}{backspace}'+value);
cy.wait(1000); // After each keystroke there is a short delay until saved to allow more inputs
cy.reload();
cy.get('select').select(currentParameters.scenarioName);
selectElement();
field().should('have.value', ''+value);;
});

// END foreach scenario
})})

});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@ import { getElementLabel } from "../../../util/BpmnUtil";
import {
debounce
} from 'min-dash';
import { limitToDataScheme } from "simulation-bridge-datamodel/DataModel";
import SimulationModelModdle, { assign, limitToDataScheme } from "simulation-bridge-datamodel/DataModel";

// TODO replace emptyconfig with moddle type name
export default function AbstractModelElementEditor({type, typeName, state, setState, currentElement, getData, emptyConfig, children, setSave}) {
export default function AbstractModelElementEditor({type, typeName, state, setState, currentElement, getData, moddleClass, children, setSave}) {

function getExistingElementConfiguration() {
return getData().getCurrentModel().modelParameter[type].find(value => value.id === currentElement.id)
Expand All @@ -18,15 +17,19 @@ export default function AbstractModelElementEditor({type, typeName, state, setSt

function save() {
if (!getExistingElementConfiguration()) {
getData().getCurrentModel().modelParameter[type].push({...state});
const newElementConfiguration = SimulationModelModdle.getInstance().create(moddleClass, state);
getData().getCurrentModel().modelParameter[type].push(newElementConfiguration);
} else {
Object.assign(getExistingElementConfiguration(), state);
//TODO refactor the need for de- and re-moddleifying
assign(getExistingElementConfiguration(), state);
}
setState({...state}); //Ensure that state changes are notfied even before save and reload
debounceSave();
}

useEffect(() => setState({... (limitToDataScheme(getExistingElementConfiguration()) || emptyConfig)}), [currentElement.id]);
useEffect(() => setState({... (
limitToDataScheme(getExistingElementConfiguration() || SimulationModelModdle.getInstance().create(moddleClass, {id : currentElement.id}))
)}), [currentElement.id]);
setSave(save);

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ const Activity = ({ getData, currentElement }) => {
setState : setActivityConfiguration,
currentElement,
getData,
emptyConfig : SimulationModelModdle.getInstance().create('simulationmodel:Activity', {id : currentElement.id}),
moddleClass : 'simulationmodel:Activity',
setSave
}}>

Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/EditorSidebar/Modelbased/Event.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const Event = ({ getData, currentElement }) => {
setState : setEventConfiguration,
currentElement,
getData,
emptyConfig : SimulationModelModdle.getInstance().create('simulationmodel:Event', {id : currentElement.id}),
moddleClass : 'simulationmodel:Event',
setSave
}}>{
eventConfiguration && (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ const Gateway = ({ currentElement, getData}) => {
setState: setGatewayConfiguration,
currentElement,
getData,
emptyConfig : SimulationModelModdle.getInstance().create('simulationmodel:Gateway', {id : currentElement.id}),
moddleClass : 'simulationmodel:Gateway',
setSave
}}>

Expand Down

0 comments on commit 474f83e

Please sign in to comment.