diff --git a/services/web/client/source/class/osparc/data/model/Node.js b/services/web/client/source/class/osparc/data/model/Node.js index e84b1131b9e..8c4836b181b 100644 --- a/services/web/client/source/class/osparc/data/model/Node.js +++ b/services/web/client/source/class/osparc/data/model/Node.js @@ -156,7 +156,8 @@ qx.Class.define("osparc.data.model.Node", { propsForm: { check: "osparc.component.form.renderer.PropForm", init: null, - nullable: true + nullable: true, + apply: "__applyPropsForm" }, propsFormEditor: { @@ -513,6 +514,15 @@ qx.Class.define("osparc.data.model.Node", { } }, + __applyPropsForm: function() { + const checkIsPipelineRunning = () => { + const isPipelineRunning = this.getStudy().isPipelineRunning(); + this.getPropsForm().setEnabled(!isPipelineRunning); + }; + this.getStudy().addListener("changeState", () => checkIsPipelineRunning(), this); + checkIsPipelineRunning(); + }, + getInputsDefaultWidget: function() { return this.__inputsDefaultWidget; }, diff --git a/services/web/client/source/class/osparc/data/model/Study.js b/services/web/client/source/class/osparc/data/model/Study.js index 799f45413d5..60754e7401d 100644 --- a/services/web/client/source/class/osparc/data/model/Study.js +++ b/services/web/client/source/class/osparc/data/model/Study.js @@ -390,6 +390,16 @@ qx.Class.define("osparc.data.model.Study", { return null; }, + isPipelineRunning: function() { + const pipelineState = this.getPipelineState(); + return [ + "PUBLISHED", + "PENDING", + "STARTED", + "RETRY" + ].includes(pipelineState); + }, + isLocked: function() { if (this.getState() && "locked" in this.getState()) { return this.getState()["locked"]["value"]; diff --git a/services/web/client/source/class/osparc/desktop/StartStopButtons.js b/services/web/client/source/class/osparc/desktop/StartStopButtons.js index 34cd91cf930..d5436ccd47c 100644 --- a/services/web/client/source/class/osparc/desktop/StartStopButtons.js +++ b/services/web/client/source/class/osparc/desktop/StartStopButtons.js @@ -197,7 +197,11 @@ qx.Class.define("osparc.desktop.StartStopButtons", { __checkButtonsVisible: function() { const allNodes = this.getStudy().getWorkbench().getNodes(true); const isRunnable = Object.values(allNodes).some(node => (node.isComputational() || node.isIterator())); - this.__getStartButtons().forEach(startBtn => startBtn.setEnabled(isRunnable)); + this.__getStartButtons().forEach(startBtn => { + if (!startBtn.isFetching()) { + startBtn.setEnabled(isRunnable); + } + }, this); const isReadOnly = this.getStudy().isReadOnly(); this.setVisibility(isReadOnly ? "excluded" : "visible"); @@ -206,26 +210,7 @@ qx.Class.define("osparc.desktop.StartStopButtons", { __updateRunButtonsStatus: function() { const study = this.getStudy(); if (study) { - const startButtons = this.__getStartButtons(); - const stopButton = this.__stopButton; - const pipelineState = study.getPipelineState(); - if (pipelineState) { - switch (pipelineState) { - case "PENDING": - case "PUBLISHED": - case "STARTED": - startButtons.forEach(startButton => startButton.setFetching(true)); - stopButton.setEnabled(true); - break; - case "NOT_STARTED": - case "SUCCESS": - case "FAILED": - default: - startButtons.forEach(startButton => startButton.setFetching(false)); - stopButton.setEnabled(false); - break; - } - } + this.setRunning(study.isPipelineRunning()); } } } diff --git a/services/web/client/source/class/osparc/desktop/StudyEditor.js b/services/web/client/source/class/osparc/desktop/StudyEditor.js index 8513048c71b..7f500d1aa43 100644 --- a/services/web/client/source/class/osparc/desktop/StudyEditor.js +++ b/services/web/client/source/class/osparc/desktop/StudyEditor.js @@ -562,8 +562,12 @@ qx.Class.define("osparc.desktop.StudyEditor", { this.__lastSavedStudy = osparc.wrapper.JsonDiffPatch.getInstance().clone(newObj); }) .catch(error => { - console.error(error); - osparc.component.message.FlashMessenger.getInstance().logAs(this.tr("Error saving the study"), "ERROR"); + if ("status" in error && error.status === 409) { + osparc.component.message.FlashMessenger.getInstance().logAs(error.message, "ERROR"); + } else { + console.error(error); + osparc.component.message.FlashMessenger.getInstance().logAs(this.tr("Error saving the study"), "ERROR"); + } this.__getStudyLogger().error(null, "Error updating pipeline"); // Need to throw the error to be able to handle it later throw error; diff --git a/tests/e2e/portal/2D_Plot.js b/tests/e2e/portal/2D_Plot.js index 94a3436c07c..71d992ff01d 100644 --- a/tests/e2e/portal/2D_Plot.js +++ b/tests/e2e/portal/2D_Plot.js @@ -29,8 +29,6 @@ async function runTutorial () { await tutorial.waitFor(5000, 'Some time for starting the service'); await utils.takeScreenshot(page, screenshotPrefix + 'service_started'); - await tutorial.openNode(1); - await tutorial.waitFor(2000); await utils.takeScreenshot(page, screenshotPrefix + 'iFrame0'); diff --git a/tests/performance/locust_files/director_services.py b/tests/performance/locust_files/director_services.py index 1743004e082..d7e63a900f0 100644 --- a/tests/performance/locust_files/director_services.py +++ b/tests/performance/locust_files/director_services.py @@ -22,7 +22,7 @@ def __init__(self, *args, **kwargs): @task() def get_services(self): self.client.get( - "v0/services?user_id=" + self.user_id, + f"v0/services?user_id={self.user_id}", headers={ "x-simcore-products-name": "osparc", },