diff --git a/services/web/client/source/class/osparc/component/widget/NodesTree.js b/services/web/client/source/class/osparc/component/widget/NodesTree.js index 0e602e768e2..761990019a3 100644 --- a/services/web/client/source/class/osparc/component/widget/NodesTree.js +++ b/services/web/client/source/class/osparc/component/widget/NodesTree.js @@ -65,21 +65,29 @@ qx.Class.define("osparc.component.widget.NodesTree", { }, statics: { + getSortingValue: function(node) { + if (node.isFilePicker()) { + return osparc.utils.Services.getSorting("file"); + } else if (node.isParameter()) { + return osparc.utils.Services.getSorting("parameter"); + } + return osparc.utils.Services.getSorting(node.getMetaData().type); + }, + convertModel: function(nodes) { - let children = []; + const children = []; for (let nodeId in nodes) { const node = nodes[nodeId]; - let nodeInTree = { - label: "", - nodeId: node.getNodeId() + const nodeInTree = { + label: node.getLabel(), + children: node.isContainer() ? this.convertModel(node.getInnerNodes()) : [], + isContainer: node.isContainer(), + nodeId: node.getNodeId(), + sortingValue: this.self().getSortingValue(node) }; - nodeInTree.label = node.getLabel(); - nodeInTree.isContainer = node.isContainer(); - if (node.isContainer()) { - nodeInTree.children = this.convertModel(node.getInnerNodes()); - } children.push(nodeInTree); } + // children.sort((firstEl, secondEl) => firstEl.sortingValue - secondEl.sortingValue); return children; } }, @@ -111,11 +119,12 @@ qx.Class.define("osparc.component.widget.NodesTree", { populateTree: function() { const study = this.getStudy(); const topLevelNodes = study.getWorkbench().getNodes(); - let data = { + const data = { label: study.getName(), children: this.self().convertModel(topLevelNodes), + isContainer: true, nodeId: study.getUuid(), - isContainer: true + sortingValue: 0 }; let newModel = qx.data.marshal.Json.createModel(data, true); let oldModel = this.getModel(); @@ -134,19 +143,15 @@ qx.Class.define("osparc.component.widget.NodesTree", { bindItem: (c, item, id) => { c.bindDefaultProperties(item, id); c.bindProperty("nodeId", "nodeId", null, item, id); - const node = study.getWorkbench().getNode(item.getModel().getNodeId()); - if (node) { - node.bind("label", item.getModel(), "label"); - } c.bindProperty("label", "label", null, item, id); + const node = study.getWorkbench().getNode(item.getModel().getNodeId()); if (item.getModel().getNodeId() === study.getUuid()) { item.setIcon("@FontAwesome5Solid/home/14"); item.getChildControl("options-delete-button").exclude(); - } - if (node) { - if (node.isDynamic()) { - item.getChildControl("fullscreen-button").show(); - } + } else if (node) { + node.bind("label", item.getModel(), "label"); + + // set icon if (node.isFilePicker()) { const icon = osparc.utils.Services.getIcon("file"); item.setIcon(icon+"14"); @@ -159,6 +164,22 @@ qx.Class.define("osparc.component.widget.NodesTree", { item.setIcon(icon+"14"); } } + + // bind running/interactive status to icon color + if (node.isDynamic()) { + node.getStatus().bind("interactive", item.getChildControl("icon"), "textColor", { + converter: status => osparc.utils.StatusUI.getColor(status) + }, this); + } else if (node.isComputational()) { + node.getStatus().bind("running", item.getChildControl("icon"), "textColor", { + converter: status => osparc.utils.StatusUI.getColor(status) + }, this); + } + + // add fullscreen + if (node.isDynamic()) { + item.getChildControl("fullscreen-button").show(); + } } }, configureItem: item => { @@ -166,8 +187,12 @@ qx.Class.define("osparc.component.widget.NodesTree", { this.__openItem(item.getModel().getNodeId()); this.nodeSelected(item.getModel().getNodeId()); }, this); - } + }, + sorter: (itemA, itemB) => itemA.getSortingValue() - itemB.getSortingValue() }); + const nChildren = newModel.getChildren().length; + console.log(nChildren); + this.setHeight(nChildren*21 + 12); } }, diff --git a/services/web/client/source/class/osparc/component/workbench/WorkbenchUI.js b/services/web/client/source/class/osparc/component/workbench/WorkbenchUI.js index 0a98c3b9d75..021f7965cdd 100644 --- a/services/web/client/source/class/osparc/component/workbench/WorkbenchUI.js +++ b/services/web/client/source/class/osparc/component/workbench/WorkbenchUI.js @@ -314,13 +314,30 @@ qx.Class.define("osparc.component.workbench.WorkbenchUI", { return inputOutputNodesLayout; }, - __createServiceCatalog: function(winPos) { + openServiceCatalog: function(winPos, nodePos) { const srvCat = new osparc.component.workbench.ServiceCatalog(); const maxLeft = this.getBounds().width - osparc.component.workbench.ServiceCatalog.Width; const maxHeight = this.getBounds().height - osparc.component.workbench.ServiceCatalog.Height; - const posX = Math.min(winPos.x, maxLeft); - const posY = Math.min(winPos.y, maxHeight); + const posX = winPos ? Math.min(winPos.x, maxLeft) : 100; + const posY = winPos ? Math.min(winPos.y, maxHeight) : 100; srvCat.moveTo(posX + this.__getLeftOffset(), posY + this.__getTopOffset()); + srvCat.addListener("addService", e => { + const { + service, + nodeLeftId, + nodeRightId + } = e.getData(); + const newNodeUI = this.__addNode(service, nodePos); + if (nodeLeftId !== null || nodeRightId !== null) { + const newNodeId = newNodeUI.getNodeId(); + this._createEdgeBetweenNodes({ + nodeId: nodeLeftId ? nodeLeftId : newNodeId + }, { + nodeId: nodeRightId ? nodeRightId : newNodeId + }); + } + }, this); + srvCat.open(); return srvCat; }, @@ -372,9 +389,11 @@ qx.Class.define("osparc.component.workbench.WorkbenchUI", { }, _addNodeUIToWorkbench: function(nodeUI, position) { - if (!("x" in position) || isNaN(position["x"]) || position["x"] < 0) { - console.error("not a valid position"); - return; + if (position === undefined || !("x" in position) || isNaN(position["x"]) || position["x"] < 0) { + position = { + x: 10, + y: 10 + }; } this.__updateWorkbenchLayoutSize(position); @@ -681,32 +700,9 @@ qx.Class.define("osparc.component.workbench.WorkbenchUI", { if (this.__tempEdgeNodeId === dragNodeId) { const winPos = this.__unscaleCoordinates(this.__pointerPos.x, this.__pointerPos.y); - const srvCat = this.__createServiceCatalog(winPos); - if (this.__tempEdgeIsInput === true) { - srvCat.setContext(null, dragNodeId); - } else { - srvCat.setContext(dragNodeId, null); - } - srvCat.addListener("addService", ev => { - const { - service, - nodeLeftId, - nodeRightId - } = ev.getData(); - const newNodeUI = this.__addNode(service, this.__pointerPos); - if (nodeLeftId !== null || nodeRightId !== null) { - const newNodeId = newNodeUI.getNodeId(); - this._createEdgeBetweenNodes({ - nodeId: nodeLeftId ? nodeLeftId : newNodeId - }, { - nodeId: nodeRightId ? nodeRightId : newNodeId - }); - } - }, this); - srvCat.addListener("close", () => { - this.__removeTempEdge(); - }, this); - srvCat.open(); + const srvCat = this.openServiceCatalog(winPos, this.__pointerPos); + this.__tempEdgeIsInput === true ? srvCat.setContext(null, dragNodeId) : srvCat.setContext(dragNodeId, null); + srvCat.addListener("close", () => this.__removeTempEdge(), this); } qx.bom.Element.removeListener( this.__desktop, @@ -1315,15 +1311,8 @@ qx.Class.define("osparc.component.workbench.WorkbenchUI", { return; } const winPos = this.__pointerEventToWorkbenchPos(pointerEvent, false); - const scaledPos = this.__pointerEventToWorkbenchPos(pointerEvent, true); - const srvCat = this.__createServiceCatalog(winPos); - srvCat.addListener("addService", e => { - const { - service - } = e.getData(); - this.__addNode(service, scaledPos); - }, this); - srvCat.open(); + const nodePos = this.__pointerEventToWorkbenchPos(pointerEvent, true); + this.openServiceCatalog(winPos, nodePos); }, this); this.__workbenchLayout.addListener("resize", () => this.__updateHint(), this); diff --git a/services/web/client/source/class/osparc/desktop/WorkbenchView.js b/services/web/client/source/class/osparc/desktop/WorkbenchView.js index b05d953f3cc..35ecb59451f 100644 --- a/services/web/client/source/class/osparc/desktop/WorkbenchView.js +++ b/services/web/client/source/class/osparc/desktop/WorkbenchView.js @@ -27,6 +27,7 @@ qx.Class.define("osparc.desktop.WorkbenchView", { this.setOffset(2); osparc.desktop.WorkbenchView.decorateSplitter(this.getChildControl("splitter")); + osparc.desktop.WorkbenchView.decorateSlider(this.getChildControl("slider")); this.__sidePanels = this.getChildControl("side-panels"); this.getChildControl("main-panel-tabs"); @@ -40,14 +41,24 @@ qx.Class.define("osparc.desktop.WorkbenchView", { TAB_BUTTON_HEIGHT: 50, decorateSplitter: function(splitter) { - splitter.setWidth(2); const colorManager = qx.theme.manager.Color.getInstance(); const binaryColor = osparc.utils.Utils.getRoundedBinaryColor(colorManager.resolve("background-main")); - splitter.setBackgroundColor(binaryColor); + splitter.set({ + width: 2, + backgroundColor: binaryColor + }); colorManager.addListener("changeTheme", () => { const newBinaryColor = osparc.utils.Utils.getRoundedBinaryColor(colorManager.resolve("background-main")); splitter.setBackgroundColor(newBinaryColor); }, this); + }, + + decorateSlider: function(slider) { + slider.set({ + width: 2, + backgroundColor: "#007fd4", // Visual Studio blue + opacity: 1 + }); } }, @@ -88,6 +99,7 @@ qx.Class.define("osparc.desktop.WorkbenchView", { width: Math.min(parseInt(window.innerWidth * (0.16+0.24)), 550) }); osparc.desktop.WorkbenchView.decorateSplitter(control.getChildControl("splitter")); + osparc.desktop.WorkbenchView.decorateSlider(control.getChildControl("slider")); this.add(control, 0); // flex 0 break; } @@ -260,7 +272,7 @@ qx.Class.define("osparc.desktop.WorkbenchView", { const topBar = tabViewPrimary.getChildControl("bar"); this.__addTopBarSpacer(topBar); - const homeAndNodesTree = new qx.ui.container.Composite(new qx.ui.layout.VBox(0)).set({ + const homeAndNodesTree = new qx.ui.container.Composite(new qx.ui.layout.VBox(15)).set({ backgroundColor: primaryColumnBGColor }); @@ -268,20 +280,30 @@ qx.Class.define("osparc.desktop.WorkbenchView", { alignY: "middle", minHeight: 32, maxHeight: 32, - backgroundColor: primaryColumnBGColor, - marginBottom: 5 + backgroundColor: primaryColumnBGColor }); studyTreeItem.setStudy(study); homeAndNodesTree.add(studyTreeItem); const nodesTree = this.__nodesTree = new osparc.component.widget.NodesTree().set({ backgroundColor: primaryColumnBGColor, - hideRoot: true + hideRoot: true, + allowGrowY: true, + minHeight: 5 }); nodesTree.setStudy(study); - homeAndNodesTree.add(nodesTree, { - flex: 1 + homeAndNodesTree.add(nodesTree); + + const addNewNodeBtn = new qx.ui.form.Button().set({ + label: this.tr("Add new node"), + icon: "@FontAwesome5Solid/plus/14", + allowGrowX: false, + alignX: "left", + marginLeft: 14 }); + addNewNodeBtn.addListener("execute", () => this.__workbenchUI.openServiceCatalog()); + homeAndNodesTree.add(addNewNodeBtn); + const nodesPage = this.__createTabPage("@FontAwesome5Solid/list", this.tr("Nodes"), homeAndNodesTree, primaryColumnBGColor); tabViewPrimary.add(nodesPage); @@ -304,6 +326,10 @@ qx.Class.define("osparc.desktop.WorkbenchView", { const topBar = tabViewSecondary.getChildControl("bar"); this.__addTopBarSpacer(topBar); + const studyOptionsPage = this.__studyOptionsPage = this.__createTabPage("@FontAwesome5Solid/book", this.tr("Study options")); + studyOptionsPage.exclude(); + tabViewSecondary.add(studyOptionsPage); + const infoPage = this.__infoPage = this.__createTabPage("@FontAwesome5Solid/info", this.tr("Information")); infoPage.exclude(); tabViewSecondary.add(infoPage); @@ -680,12 +706,15 @@ qx.Class.define("osparc.desktop.WorkbenchView", { }, __populateSecondPanel: function(node) { - this.__infoPage.removeAll(); - this.__settingsPage.removeAll(); - this.__outputsPage.removeAll(); - this.__infoPage.getChildControl("button").exclude(); - this.__settingsPage.getChildControl("button").exclude(); - this.__outputsPage.getChildControl("button").exclude(); + [ + this.__studyOptionsPage, + this.__infoPage, + this.__settingsPage, + this.__outputsPage + ].forEach(page => { + page.removeAll(); + page.getChildControl("button").exclude(); + }); if (node instanceof osparc.data.model.Study) { this.__populateSecondPanelStudy(node); @@ -699,10 +728,10 @@ qx.Class.define("osparc.desktop.WorkbenchView", { }, __populateSecondPanelStudy: function(study) { - this.__infoPage.getChildControl("button").show(); - this.getChildControl("side-panel-right-tabs").setSelection([this.__infoPage]); + this.__studyOptionsPage.getChildControl("button").show(); + this.getChildControl("side-panel-right-tabs").setSelection([this.__studyOptionsPage]); - this.__infoPage.add(new osparc.studycard.Medium(study), { + this.__studyOptionsPage.add(new osparc.studycard.Medium(study), { flex: 1 }); }, @@ -865,9 +894,6 @@ qx.Class.define("osparc.desktop.WorkbenchView", { }, __attachEventHandlers: function() { - // const blocker = this.getBlocker(); - // blocker.addListener("tap", this.getChildControl("side-panels").toggleCollapsed.bind(this.getChildControl("side-panels"))); - const maximizeIframeCb = msg => { this.__maximizeIframe(msg.getData()); }; @@ -963,6 +989,7 @@ qx.Class.define("osparc.desktop.WorkbenchView", { return; } } + this.__maximizeIframe(false); this.nodeSelected(this.getStudy().getUuid()); } } diff --git a/services/web/client/source/class/osparc/utils/Services.js b/services/web/client/source/class/osparc/utils/Services.js index 879d998061d..f467a02310f 100644 --- a/services/web/client/source/class/osparc/utils/Services.js +++ b/services/web/client/source/class/osparc/utils/Services.js @@ -33,21 +33,25 @@ qx.Class.define("osparc.utils.Services", { statics: { TYPES: { - computational: { - label: "Computational", - icon: "@FontAwesome5Solid/cogs/" - }, - dynamic: { - label: "Interactive", - icon: "@FontAwesome5Solid/mouse-pointer/" - }, parameter: { label: "", - icon: "@FontAwesome5Solid/sliders-h/" + icon: "@FontAwesome5Solid/sliders-h/", + sorting: 0 }, file: { label: "", - icon: "@FontAwesome5Solid/file/" + icon: "@FontAwesome5Solid/file/", + sorting: 1 + }, + computational: { + label: "Computational", + icon: "@FontAwesome5Solid/cogs/", + sorting: 2 + }, + dynamic: { + label: "Interactive", + icon: "@FontAwesome5Solid/mouse-pointer/", + sorting: 3 } }, @@ -79,6 +83,14 @@ qx.Class.define("osparc.utils.Services", { return typeInfo[""]; }, + getSorting(type) { + const typeInfo = this.getType(type); + if (typeInfo) { + return typeInfo["sorting"]; + } + return 0; + }, + convertArrayToObject: function(servicesArray) { let services = {}; for (let i = 0; i < servicesArray.length; i++) {