Skip to content

Commit 0d1ba68

Browse files
authored
Run partial pipeline. Frontend (#2057)
* Computational services also have a status * setRunningStatus from WS message * deserialize running state * "Retrieve" button doesn't belong to the node * "Run" or "Run selection" depending on the selection * tap on the empty workbench resets selection * Run partial pipeline * Do not show empty chip, just hide it * Do not update Run button text if it's fetching * Let backend update progress. Do not set them to 0 in the frontend
1 parent bbc5fc8 commit 0d1ba68

File tree

10 files changed

+143
-65
lines changed

10 files changed

+143
-65
lines changed

services/web/client/source/class/osparc/component/node/BaseNodeView.js

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -328,9 +328,17 @@ qx.Class.define("osparc.component.node.BaseNodeView", {
328328

329329
_addButtons: function() {
330330
this.__buttonContainer.removeAll();
331-
let retrieveIFrameButton = this.getNode().getRetrieveIFrameButton();
332-
if (retrieveIFrameButton) {
333-
this.__buttonContainer.add(retrieveIFrameButton);
331+
if (this.getNode().isDynamic() && this.getNode().isRealService()) {
332+
const retrieveBtn = new qx.ui.toolbar.Button(this.tr("Retrieve"), "@FontAwesome5Solid/spinner/14");
333+
osparc.utils.Utils.setIdToWidget(retrieveBtn, "nodeViewRetrieveBtn");
334+
retrieveBtn.addListener("execute", e => {
335+
this.getNode().callRetrieveInputs();
336+
}, this);
337+
this.getNode().bind("serviceUrl", retrieveBtn, "enabled", {
338+
converter: value => Boolean(value)
339+
});
340+
retrieveBtn.setEnabled(Boolean(this.getNode().getServiceUrl()));
341+
this.__buttonContainer.add(retrieveBtn);
334342
}
335343
this.__buttonContainer.add(this.__filesButton);
336344
this.__header.add(this.__buttonContainer);

services/web/client/source/class/osparc/component/workbench/NodeUI.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -179,10 +179,9 @@ qx.Class.define("osparc.component.workbench.NodeUI", {
179179
if (node.isComputational() || node.isFilePicker()) {
180180
this.__progressBar = this.getChildControl("progress");
181181
}
182-
if (node.isDynamic()) {
183-
const nodeStatus = new osparc.ui.basic.NodeStatusUI(node);
184-
this.__chipContainer.add(nodeStatus);
185-
}
182+
183+
const nodeStatus = new osparc.ui.basic.NodeStatusUI(node);
184+
this.__chipContainer.add(nodeStatus);
186185
},
187186

188187
populateNodeLayout: function() {

services/web/client/source/class/osparc/component/workbench/WorkbenchUI.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,7 @@ qx.Class.define("osparc.component.workbench.WorkbenchUI", {
410410
},
411411

412412
resetSelectedNodes: function() {
413+
this.__selectedNodes.forEach(node => node.removeState("selected"));
413414
this.__selectedNodes = [];
414415
qx.event.message.Bus.dispatchByName("changeWorkbenchSelection", []);
415416
},
@@ -1106,7 +1107,6 @@ qx.Class.define("osparc.component.workbench.WorkbenchUI", {
11061107

11071108
const commandEsc = new qx.ui.command.Command("Esc");
11081109
commandEsc.addListener("execute", () => {
1109-
this.__selectedNodes.forEach(node => node.removeState("selected"));
11101110
this.resetSelectedNodes();
11111111
});
11121112

@@ -1132,6 +1132,10 @@ qx.Class.define("osparc.component.workbench.WorkbenchUI", {
11321132
commandEsc.setEnabled(false);
11331133
});
11341134

1135+
this.__workbenchLayout.addListener("tap", () => {
1136+
this.resetSelectedNodes();
1137+
}, this);
1138+
11351139
this.__workbenchLayout.addListener("dbltap", e => {
11361140
if (this.getStudy().isReadOnly()) {
11371141
return;

services/web/client/source/class/osparc/data/Permissions.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,10 @@ qx.Class.define("osparc.data.Permissions", {
222222
osparc.component.message.FlashMessenger.getInstance().logAs("Operation not permitted", "ERROR");
223223
}
224224
return canDo;
225+
},
226+
227+
isTester: function() {
228+
return this.__userRole === "tester";
225229
}
226230
}
227231
});

services/web/client/source/class/osparc/data/model/Node.js

Lines changed: 8 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
* let node = new osparc.data.model.Node(key, version, uuid);
3434
* node.populateNodeData(nodeData);
3535
* node.giveUniqueName();
36-
* node.addDynamicButtons();
3736
* node.startDynamicService();
3837
* </pre>
3938
*/
@@ -158,11 +157,6 @@ qx.Class.define("osparc.data.model.Node", {
158157
nullable: true
159158
},
160159

161-
retrieveIFrameButton: {
162-
check: "qx.ui.form.Button",
163-
init: null
164-
},
165-
166160
status: {
167161
check: "osparc.data.model.NodeStatus",
168162
nullable: false
@@ -344,6 +338,10 @@ qx.Class.define("osparc.data.model.Node", {
344338

345339
this.populateInputOutputData(nodeData);
346340

341+
if (nodeData.state) {
342+
this.getStatus().setRunningStatus(nodeData.state);
343+
}
344+
347345
if (nodeData.progress) {
348346
this.getStatus().setProgress(nodeData.progress);
349347
}
@@ -399,8 +397,6 @@ qx.Class.define("osparc.data.model.Node", {
399397
},
400398

401399
startInBackend: function() {
402-
this.addDynamicButtons();
403-
404400
// create the node in the backend here
405401
const key = this.getKey();
406402
const version = this.getVersion();
@@ -500,7 +496,7 @@ qx.Class.define("osparc.data.model.Node", {
500496
propsForm.addListener("linkFieldModified", e => {
501497
const linkFieldModified = e.getData();
502498
const portId = linkFieldModified.portId;
503-
this.__retrieveInputs(portId);
499+
this.callRetrieveInputs(portId);
504500
}, this);
505501
},
506502

@@ -638,7 +634,7 @@ qx.Class.define("osparc.data.model.Node", {
638634
this.__createAutoPortConnection(inputNode, innerNode);
639635
}
640636
}
641-
this.__retrieveInputs();
637+
this.callRetrieveInputs();
642638
}
643639
},
644640

@@ -820,7 +816,7 @@ qx.Class.define("osparc.data.model.Node", {
820816
}
821817
},
822818

823-
__retrieveInputs: function(portKey) {
819+
callRetrieveInputs: function(portKey) {
824820
if (this.isContainer()) {
825821
const innerNodes = Object.values(this.getInnerNodes());
826822
for (let i=0; i<innerNodes.length; i++) {
@@ -898,29 +894,6 @@ qx.Class.define("osparc.data.model.Node", {
898894
}
899895
},
900896

901-
addDynamicButtons: function() {
902-
if (this.isDynamic() && this.isRealService()) {
903-
this.__addRetrieveButton();
904-
}
905-
if (this.isContainer()) {
906-
const innerNodes = Object.values(this.getInnerNodes());
907-
if (innerNodes.some(innerNode => innerNode.isDynamic())) {
908-
this.__addRetrieveButton();
909-
this.getRetrieveIFrameButton().setEnabled(true);
910-
}
911-
}
912-
},
913-
914-
__addRetrieveButton: function() {
915-
const retrieveBtn = new qx.ui.toolbar.Button(this.tr("Retrieve"), "@FontAwesome5Solid/spinner/14");
916-
osparc.utils.Utils.setIdToWidget(retrieveBtn, "nodeViewRetrieveBtn");
917-
retrieveBtn.addListener("execute", e => {
918-
this.__retrieveInputs();
919-
}, this);
920-
retrieveBtn.setEnabled(false);
921-
this.setRetrieveIFrameButton(retrieveBtn);
922-
},
923-
924897
startDynamicService: function() {
925898
if (this.isDynamic() && this.isRealService()) {
926899
const metaData = this.getMetaData();
@@ -1072,7 +1045,6 @@ qx.Class.define("osparc.data.model.Node", {
10721045
};
10731046
this.fireDataEvent("showInLogger", msgData);
10741047

1075-
this.getRetrieveIFrameButton().setEnabled(true);
10761048
this.getStatus().setProgress(100);
10771049

10781050
// FIXME: Apparently no all services are inmediately ready when they publish the port
@@ -1083,7 +1055,7 @@ qx.Class.define("osparc.data.model.Node", {
10831055
this.__restartIFrame();
10841056
}, this, waitFor);
10851057

1086-
this.__retrieveInputs();
1058+
this.callRetrieveInputs();
10871059
},
10881060

10891061
__removeInnerNodes: function() {

services/web/client/source/class/osparc/data/model/NodeStatus.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@ qx.Class.define("osparc.data.model.NodeStatus", {
3434
event: "changeProgress"
3535
},
3636

37+
runningStatus: {
38+
check: ["UNKNOWN", "NOT_STARTED", "PUBLISHED", "PENDING", "STARTED", "RETRY", "SUCCESS", "FAILED", "ABORTED"],
39+
nullable: true,
40+
event: "changeRunningStatus"
41+
},
42+
3743
interactiveStatus: {
3844
check: ["idle", "starting", "pulling", "pending", "connecting", "ready", "failed"],
3945
nullable: true,

services/web/client/source/class/osparc/data/model/Workbench.js

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ qx.Class.define("osparc.data.model.Workbench", {
7272
const allModels = this.getNodes(true);
7373
const nodes = Object.values(allModels);
7474
for (const node of nodes) {
75-
node.addDynamicButtons();
7675
node.startDynamicService();
7776
}
7877
},
@@ -335,16 +334,6 @@ qx.Class.define("osparc.data.model.Workbench", {
335334
return false;
336335
},
337336

338-
clearProgressData: function() {
339-
const allNodes = this.getNodes(true);
340-
const nodes = Object.values(allNodes);
341-
for (const node of nodes) {
342-
if (node.isComputational() && !node.isFilePicker()) {
343-
node.getStatus().setProgress(0);
344-
}
345-
}
346-
},
347-
348337
__deserialize: function(workbenchData, workbenchUIData) {
349338
this.__deserializeNodes(workbenchData, workbenchUIData);
350339
this.__deserializeEdges(workbenchData);

services/web/client/source/class/osparc/desktop/ControlsBar.js

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -129,11 +129,11 @@ qx.Class.define("osparc.desktop.ControlsBar", {
129129

130130
osparc.store.Store.getInstance().addListener("changeCurrentStudy", e => {
131131
const study = e.getData();
132-
this.__updateRunButtons(study);
132+
this.__updateRunButtonsStatus(study);
133133
});
134134
},
135135

136-
__updateRunButtons: function(study) {
136+
__updateRunButtonsStatus: function(study) {
137137
if (study) {
138138
const startButton = this.__startButton;
139139
const stopButton = this.__stopButton;
@@ -224,14 +224,21 @@ qx.Class.define("osparc.desktop.ControlsBar", {
224224
return button;
225225
},
226226

227-
__updateGroupButtonsVisibility: function(msg) {
227+
__workbenchSelectionChanged: function(msg) {
228228
const selectedNodes = msg.getData();
229229
this.__groupButton.setVisibility(selectedNodes.length ? "visible" : "excluded");
230230
this.__ungroupButton.setVisibility((selectedNodes.length === 1 && selectedNodes[0].isContainer()) ? "visible" : "excluded");
231+
if (!this.__startButton.isFetching()) {
232+
if (selectedNodes.length) {
233+
this.__startButton.setLabel(this.tr("Run selection"));
234+
} else {
235+
this.__startButton.setLabel(this.tr("Run"));
236+
}
237+
}
231238
},
232239

233240
__attachEventHandlers: function() {
234-
qx.event.message.Bus.subscribe("changeWorkbenchSelection", this.__updateGroupButtonsVisibility, this);
241+
qx.event.message.Bus.subscribe("changeWorkbenchSelection", this.__workbenchSelectionChanged, this);
235242
}
236243
}
237244
});

services/web/client/source/class/osparc/desktop/WorkbenchView.js

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ qx.Class.define("osparc.desktop.WorkbenchView", {
254254
this.__doStartPipeline();
255255
})
256256
.catch(() => {
257-
this.getLogger().error(null, "Couldn't run the pipeline: Pipeline failed to save.");
257+
this.getLogger().error(null, "Run failed");
258258
runButton.setFetching(false);
259259
});
260260
},
@@ -266,12 +266,20 @@ qx.Class.define("osparc.desktop.WorkbenchView", {
266266
this.__requestStartPipeline(secondaryStudyId);
267267
});
268268
} else {
269-
this.getStudy().getWorkbench().clearProgressData();
270-
this.__requestStartPipeline(this.getStudy().getUuid());
269+
const selectedNodeUIs = this.__workbenchUI.getSelectedNodes();
270+
if (this.__isSelectionEmpty(selectedNodeUIs)) {
271+
this.__requestStartPipeline(this.getStudy().getUuid());
272+
} else {
273+
const selectedNodeIDs = [];
274+
selectedNodeUIs.forEach(nodeUI => {
275+
selectedNodeIDs.push(nodeUI.getNodeId());
276+
});
277+
this.__requestStartPipeline(this.getStudy().getUuid(), selectedNodeIDs);
278+
}
271279
}
272280
},
273281

274-
__requestStartPipeline: function(studyId) {
282+
__requestStartPipeline: function(studyId, selectedNodeIDs = []) {
275283
const url = "/computation/pipeline/" + encodeURIComponent(studyId) + ":start";
276284
const req = new osparc.io.request.ApiRequest(url, "POST");
277285
const runButton = this.__mainPanel.getControls().getStartButton();
@@ -288,9 +296,17 @@ qx.Class.define("osparc.desktop.WorkbenchView", {
288296
}
289297
runButton.setFetching(false);
290298
}, this);
291-
req.send();
299+
if (selectedNodeIDs.length) {
300+
req.setRequestData({
301+
"subgraph": selectedNodeIDs
302+
});
303+
req.send();
304+
this.getLogger().info(null, "Starting partial pipeline");
305+
} else {
306+
req.send();
307+
this.getLogger().info(null, "Starting pipeline");
308+
}
292309

293-
this.getLogger().info(null, "Starting pipeline");
294310
return true;
295311
},
296312

@@ -637,6 +653,8 @@ qx.Class.define("osparc.desktop.WorkbenchView", {
637653
const node = workbench.getNode(nodeId);
638654
if (node) {
639655
node.getStatus().setProgress(progress);
656+
} else if (osparc.data.Permissions.getInstance().isTester()) {
657+
console.log("Ignored ws 'progress' msg", d);
640658
}
641659
}, this);
642660
}
@@ -654,8 +672,13 @@ qx.Class.define("osparc.desktop.WorkbenchView", {
654672
node.setOutputData(nodeData.outputs);
655673
if (nodeData.progress) {
656674
const progress = Number.parseInt(nodeData.progress);
675+
if ("state" in nodeData && node.isComputational()) {
676+
node.getStatus().setRunningStatus(nodeData["state"]);
677+
}
657678
node.getStatus().setProgress(progress);
658679
}
680+
} else if (osparc.data.Permissions.getInstance().isTester()) {
681+
console.log("Ignored ws 'nodeUpdated' msg", d);
659682
}
660683
}, this);
661684
}

0 commit comments

Comments
 (0)