diff --git a/services/static-webserver/client/source/class/osparc/desktop/MainPageHandler.js b/services/static-webserver/client/source/class/osparc/desktop/MainPageHandler.js index 3c51e7d47d11..0fce20f0e48e 100644 --- a/services/static-webserver/client/source/class/osparc/desktop/MainPageHandler.js +++ b/services/static-webserver/client/source/class/osparc/desktop/MainPageHandler.js @@ -97,7 +97,7 @@ qx.Class.define("osparc.desktop.MainPageHandler", { // check if there is any linked node missing if (osparc.study.Utils.isAnyLinkedNodeMissing(studyData)) { - const msg = `${qx.locale.Manager.tr("We encountered an issue with the")} ${studyAlias}
${qx.locale.Manager.tr("Please contact support.")}`; + const msg = `${qx.locale.Manager.tr("We found an issue with some links.")}
${qx.locale.Manager.tr("They will be removed.")}`; throw new Error(msg); } diff --git a/services/static-webserver/client/source/class/osparc/desktop/StudyEditor.js b/services/static-webserver/client/source/class/osparc/desktop/StudyEditor.js index 01342db2c426..24818effe361 100644 --- a/services/static-webserver/client/source/class/osparc/desktop/StudyEditor.js +++ b/services/static-webserver/client/source/class/osparc/desktop/StudyEditor.js @@ -316,6 +316,29 @@ qx.Class.define("osparc.desktop.StudyEditor", { this.__listenToEvent(); this.__listenToServiceStatus(); this.__listenToStatePorts(); + + const socket = osparc.wrapper.WebSocket.getInstance(); + [ + "connect", + "reconnect", + ].forEach(evtName => { + socket.addListener(evtName, () => { + // after a reconnect, re-sync the project document + console.log("WebSocket reconnected, re-syncing project document"); + const studyId = this.getStudy().getUuid(); + osparc.store.Study.getInstance().getOne(studyId) + .then(latestStudyData => { + const latestData = { + "version": this.__lastSyncedProjectVersion, // do not increase the version + "document": latestStudyData, + }; + this.__applyProjectDocument(latestData); + }) + .catch(err => { + console.error("Failed to re-sync project document after WebSocket reconnect:", err); + }); + }); + }); }, __listenToProjectDocument: function() { @@ -727,13 +750,14 @@ qx.Class.define("osparc.desktop.StudyEditor", { osparc.data.Resources.fetch("runPipeline", "startPipeline", params) .then(resp => this.__onPipelineSubmitted(resp)) .catch(err => { - let msg = err.message; const errStatus = err.status; if (errStatus == "409") { - this.getStudyLogger().error(null, "Pipeline is already running"); + osparc.FlashMessenger.logError(err); + const msg = osparc.FlashMessenger.extractMessage(err); + this.getStudyLogger().error(null, msg); } else if (errStatus == "422") { this.getStudyLogger().info(null, "The pipeline is up-to-date"); - msg = this.tr("The pipeline is up-to-date. Do you want to re-run it?"); + const msg = this.tr("The pipeline is up-to-date. Do you want to re-run it?"); const win = new osparc.ui.window.Confirmation(msg).set({ caption: this.tr("Re-run"), confirmText: this.tr("Run"), diff --git a/services/static-webserver/client/source/class/osparc/form/renderer/PropForm.js b/services/static-webserver/client/source/class/osparc/form/renderer/PropForm.js index 0e4578db488f..fb504f8c25fb 100644 --- a/services/static-webserver/client/source/class/osparc/form/renderer/PropForm.js +++ b/services/static-webserver/client/source/class/osparc/form/renderer/PropForm.js @@ -909,6 +909,11 @@ qx.Class.define("osparc.form.renderer.PropForm", { if (!this.__isPortAvailable(toPortId)) { return false; } + const fromNode = study.getWorkbench().getNode(fromNodeId); + if (!fromNode) { + console.error("Node not found while creating link", fromNodeId); + return false; + } const ctrlLink = this.getControlLink(toPortId); ctrlLink.setEnabled(false); @@ -927,8 +932,6 @@ qx.Class.define("osparc.form.renderer.PropForm", { }; ctrlLink.addListener("mouseover", () => highlightEdgeUI(true)); ctrlLink.addListener("mouseout", () => highlightEdgeUI(false)); - - const fromNode = study.getWorkbench().getNode(fromNodeId); const prettifyLinkString = () => { const port = fromNode.getOutput(fromPortId); const fromPortLabel = port ? port.label : null; diff --git a/services/static-webserver/client/source/class/osparc/navigation/StudyTitleWOptions.js b/services/static-webserver/client/source/class/osparc/navigation/StudyTitleWOptions.js index fc88ae1866da..363fc816d2e1 100644 --- a/services/static-webserver/client/source/class/osparc/navigation/StudyTitleWOptions.js +++ b/services/static-webserver/client/source/class/osparc/navigation/StudyTitleWOptions.js @@ -68,6 +68,14 @@ qx.Class.define("osparc.navigation.StudyTitleWOptions", { }); }); break; + case "study-menu-share": + control = new qx.ui.menu.Button().set({ + label: this.tr("Share..."), + icon: "@FontAwesome5Solid/share-alt/14", + ...this.self().BUTTON_OPTIONS + }); + control.addListener("execute", () => this.__openAccessRights()); + break; case "study-menu-reload": control = new qx.ui.menu.Button().set({ label: this.tr("Reload"), @@ -100,6 +108,7 @@ qx.Class.define("osparc.navigation.StudyTitleWOptions", { const optionsMenu = new qx.ui.menu.Menu(); optionsMenu.setAppearance("menu-wider"); optionsMenu.add(this.getChildControl("study-menu-info")); + optionsMenu.add(this.getChildControl("study-menu-share")); optionsMenu.add(this.getChildControl("study-menu-reload")); optionsMenu.add(this.getChildControl("study-menu-conversations")); if (osparc.product.Utils.showConvertToPipeline()) { @@ -133,6 +142,17 @@ qx.Class.define("osparc.navigation.StudyTitleWOptions", { return control || this.base(arguments, id); }, + __openAccessRights: function() { + const studyData = this.getStudy().serialize(); + studyData["resourceType"] = this.getStudy().getTemplateType() ? "template" : "study"; + const collaboratorsView = osparc.info.StudyUtils.openAccessRights(studyData); + collaboratorsView.addListener("updateAccessRights", e => { + const updatedData = e.getData(); + this.getStudy().setAccessRights(updatedData["accessRights"]); + this.fireDataEvent("updateStudy", updatedData); + }, this); + }, + __reloadIFrame: function() { const nodes = this.getStudy().getWorkbench().getNodes(); if (Object.keys(nodes).length === 1) { @@ -145,6 +165,9 @@ qx.Class.define("osparc.navigation.StudyTitleWOptions", { const editTitle = this.getChildControl("edit-title-label"); study.bind("name", editTitle, "value"); + const shareButton = this.getChildControl("study-menu-share"); + shareButton.setEnabled(osparc.data.model.Study.canIWrite(study.getAccessRights())); + const reloadButton = this.getChildControl("study-menu-reload"); study.getUi().bind("mode", reloadButton, "visibility", { converter: mode => mode === "standalone" ? "visible" : "excluded" diff --git a/services/static-webserver/client/source/class/osparc/service/StatusUI.js b/services/static-webserver/client/source/class/osparc/service/StatusUI.js index 092522376017..13631e61983b 100644 --- a/services/static-webserver/client/source/class/osparc/service/StatusUI.js +++ b/services/static-webserver/client/source/class/osparc/service/StatusUI.js @@ -192,14 +192,15 @@ qx.Class.define("osparc.service.StatusUI", { // ports case "modified": - return "busy-orange"; + return "failed-red"; case "up-to-date": return "ready-green"; // output case "busy": - case "out-of-date": return "busy-orange"; + case "out-of-date": + return "failed-red"; /* case "up-to-date": return "ready-green"; diff --git a/services/static-webserver/client/source/class/osparc/workbench/NodeUI.js b/services/static-webserver/client/source/class/osparc/workbench/NodeUI.js index f1f6d693aff5..bbbc448d7d05 100644 --- a/services/static-webserver/client/source/class/osparc/workbench/NodeUI.js +++ b/services/static-webserver/client/source/class/osparc/workbench/NodeUI.js @@ -258,7 +258,9 @@ qx.Class.define("osparc.workbench.NodeUI", { maxHeight: 20, font: "text-10", }); - const statusLabel = control.getChildControl("label"); + const statusLabel = control.getChildControl("label").set({ + maxWidth: 80, + }); const requestOpenLogger = () => this.fireEvent("requestOpenLogger"); const evaluateLabel = () => { const failed = statusLabel.getValue() === "Unsuccessful";