diff --git a/services/static-webserver/client/source/class/osparc/dashboard/MoveResourceTo.js b/services/static-webserver/client/source/class/osparc/dashboard/MoveResourceTo.js index 11a744ba9ea..cd9a98d1d6f 100644 --- a/services/static-webserver/client/source/class/osparc/dashboard/MoveResourceTo.js +++ b/services/static-webserver/client/source/class/osparc/dashboard/MoveResourceTo.js @@ -39,7 +39,14 @@ qx.Class.define("osparc.dashboard.MoveResourceTo", { const item = selection.getItem(0); this.__selectedWorkspaceId = item.getWorkspaceId(); this.__selectedFolderId = item.getFolderId(); - moveButton.setEnabled(this.__currentWorkspaceId !== this.__selectedWorkspaceId || this.__currentFolderId !== this.__selectedFolderId); + if (this.__selectedWorkspaceId === -1) { + // "Shared Workspaces" + moveButton.setEnabled(false); + } else { + // In principle, valid location + // disable if it's the current location + moveButton.setEnabled(this.__currentWorkspaceId !== this.__selectedWorkspaceId || this.__currentFolderId !== this.__selectedFolderId); + } } }, this); moveButton.addListener("execute", () => { diff --git a/services/static-webserver/client/source/class/osparc/dashboard/WorkspacesAndFoldersTree.js b/services/static-webserver/client/source/class/osparc/dashboard/WorkspacesAndFoldersTree.js index 93f1125049e..c65318bfcd3 100644 --- a/services/static-webserver/client/source/class/osparc/dashboard/WorkspacesAndFoldersTree.js +++ b/services/static-webserver/client/source/class/osparc/dashboard/WorkspacesAndFoldersTree.js @@ -74,7 +74,7 @@ qx.Class.define("osparc.dashboard.WorkspacesAndFoldersTree", { osparc.store.Workspaces.getInstance().addListener("workspaceRemoved", e => { const workspace = e.getData(); - this.__removeWorkspace(workspace); + this.__workspaceRemoved(workspace); }, this); this.getSelection().addListener("change", () => { @@ -227,11 +227,21 @@ qx.Class.define("osparc.dashboard.WorkspacesAndFoldersTree", { this.__populateFolder(workspaceModel, workspace.getWorkspaceId(), null); }, - __removeWorkspace: function(workspace) { + __workspaceRemoved: function(workspace) { + // remove it from the tree const sharedWorkspaceModel = this.__getModel(-1, null); const idx = sharedWorkspaceModel.getChildren().toArray().findIndex(w => workspace.getWorkspaceId() === w.getWorkspaceId()); if (idx > -1) { - sharedWorkspaceModel.getChildren().toArray().splice(idx, 1); + sharedWorkspaceModel.getChildren().removeAt(idx); + } + + // remove it from the cached models + const modelFound = this.__getModel(workspace.getWorkspaceId(), null); + if (modelFound) { + const index = this.__models.indexOf(modelFound); + if (index > -1) { // only splice array when item is found + this.__models.splice(index, 1); // 2nd parameter means remove one item only + } } }, @@ -283,7 +293,19 @@ qx.Class.define("osparc.dashboard.WorkspacesAndFoldersTree", { if (parentModel) { const idx = parentModel.getChildren().toArray().findIndex(c => folder.getWorkspaceId() === c.getWorkspaceId() && folder.getFolderId() === c.getFolderId()); if (idx > -1) { - parentModel.getChildren().toArray().splice(idx, 1); + parentModel.getChildren().removeAt(idx); + } + } + + if (oldParentFolderId === undefined) { + // it was removed, not moved + // remove it from the cached models + const modelFound = this.__getModel(folder.getWorkspaceId(), folder.getParentFolderId()); + if (modelFound) { + const index = this.__models.indexOf(modelFound); + if (index > -1) { // only splice array when item is found + this.__models.splice(index, 1); // 2nd parameter means remove one item only + } } } }, diff --git a/services/static-webserver/client/source/class/osparc/data/model/IframeHandler.js b/services/static-webserver/client/source/class/osparc/data/model/IframeHandler.js index 9620c80daf1..fa037642af4 100644 --- a/services/static-webserver/client/source/class/osparc/data/model/IframeHandler.js +++ b/services/static-webserver/client/source/class/osparc/data/model/IframeHandler.js @@ -84,7 +84,9 @@ qx.Class.define("osparc.data.model.IframeHandler", { this.__unresponsiveRetries = 5; this.__nodeState(); - this.getIFrame().resetSource(); + if (this.getIFrame()) { + this.getIFrame().resetSource(); + } }, __initIFrame: function() { @@ -365,7 +367,9 @@ qx.Class.define("osparc.data.model.IframeHandler", { // will switch to the loading page node.resetServiceUrl(); - this.getIFrame().resetSource(); + if (this.getIFrame()) { + this.getIFrame().resetSource(); + } this.fireEvent("iframeChanged"); } }, @@ -396,8 +400,10 @@ qx.Class.define("osparc.data.model.IframeHandler", { const status = node.getStatus().getInteractive(); // it might have been stopped if (["running", "ready"].includes(status)) { - this.getIFrame().resetSource(); - this.getIFrame().setSource(node.getServiceUrl()); + if (this.getIFrame()) { + this.getIFrame().resetSource(); + this.getIFrame().setSource(node.getServiceUrl()); + } // fire event to force switching to iframe's content: // it is required in those cases where the native 'load' event isn't triggered (voila) diff --git a/services/static-webserver/client/source/class/osparc/desktop/organizations/MembersList.js b/services/static-webserver/client/source/class/osparc/desktop/organizations/MembersList.js index e5cb935cdf8..eb694304233 100644 --- a/services/static-webserver/client/source/class/osparc/desktop/organizations/MembersList.js +++ b/services/static-webserver/client/source/class/osparc/desktop/organizations/MembersList.js @@ -358,7 +358,8 @@ qx.Class.define("osparc.desktop.organizations.MembersList", { } }) .catch(err => { - osparc.FlashMessenger.getInstance().logAs(this.tr("Something went wrong adding the user"), "ERROR"); + const errorMessage = err["message"] || this.tr("Something went wrong adding the user"); + osparc.FlashMessenger.getInstance().logAs(errorMessage, "ERROR"); console.error(err); }); }, diff --git a/services/static-webserver/client/source/class/osparc/desktop/organizations/OrganizationsList.js b/services/static-webserver/client/source/class/osparc/desktop/organizations/OrganizationsList.js index 705e943ef5a..740f54211fa 100644 --- a/services/static-webserver/client/source/class/osparc/desktop/organizations/OrganizationsList.js +++ b/services/static-webserver/client/source/class/osparc/desktop/organizations/OrganizationsList.js @@ -101,7 +101,7 @@ qx.Class.define("osparc.desktop.organizations.OrganizationsList", { createOrgBtn.addListener("execute", function() { const newOrg = true; const orgEditor = new osparc.editor.OrganizationEditor(newOrg); - const title = this.tr("Organization Details Editor"); + const title = this.tr("New Organization"); const win = osparc.ui.window.Window.popUpInWindow(orgEditor, title, 400, 250); orgEditor.addListener("createOrg", () => { this.__createOrganization(win, orgEditor.getChildControl("create"), orgEditor); @@ -298,7 +298,8 @@ qx.Class.define("osparc.desktop.organizations.OrganizationsList", { }); }) .catch(err => { - osparc.FlashMessenger.getInstance().logAs(this.tr("Something went wrong creating ") + name, "ERROR"); + const errorMessage = err["message"] || this.tr("Something went wrong creating ") + name; + osparc.FlashMessenger.getInstance().logAs(errorMessage, "ERROR"); button.setFetching(false); console.error(err); }) diff --git a/services/static-webserver/client/source/class/osparc/editor/OrganizationEditor.js b/services/static-webserver/client/source/class/osparc/editor/OrganizationEditor.js index b817d11a1d0..f4be5233d2f 100644 --- a/services/static-webserver/client/source/class/osparc/editor/OrganizationEditor.js +++ b/services/static-webserver/client/source/class/osparc/editor/OrganizationEditor.js @@ -30,6 +30,11 @@ qx.Class.define("osparc.editor.OrganizationEditor", { this.getChildControl("description"); this.getChildControl("thumbnail"); newOrg ? this.getChildControl("create") : this.getChildControl("save"); + + this.addListener("appear", () => { + title.focus(); + title.activate(); + }); }, properties: { diff --git a/services/static-webserver/client/source/class/osparc/info/ServiceLarge.js b/services/static-webserver/client/source/class/osparc/info/ServiceLarge.js index a95b78be639..217c13e58e9 100644 --- a/services/static-webserver/client/source/class/osparc/info/ServiceLarge.js +++ b/services/static-webserver/client/source/class/osparc/info/ServiceLarge.js @@ -20,14 +20,14 @@ qx.Class.define("osparc.info.ServiceLarge", { extend: osparc.info.CardLarge, /** - * @param serviceData {Object} Serialized Service Object + * @param metadata {Object} Serialized Service Object * @param instance {Object} instance related data * @param openOptions {Boolean} open edit options in new window or fire event */ - construct: function(serviceData, instance = null, openOptions = true) { + construct: function(metadata, instance = null, openOptions = true) { this.base(arguments); - this.setService(serviceData); + this.setService(metadata); if (instance) { if ("nodeId" in instance) { @@ -79,6 +79,19 @@ qx.Class.define("osparc.info.ServiceLarge", { } }, + statics: { + popUpInWindow: function(serviceLarge) { + const metadata = serviceLarge.getService(); + const versionDisplay = osparc.service.Utils.extractVersionDisplay(metadata); + const title = `${metadata["name"]} ${versionDisplay}`; + const width = osparc.info.CardLarge.WIDTH; + const height = osparc.info.CardLarge.HEIGHT; + osparc.ui.window.Window.popUpInWindow(serviceLarge, title, width, height).set({ + maxHeight: height + }); + }, + }, + members: { _rebuildLayout: function() { this._removeAll(); @@ -90,72 +103,85 @@ qx.Class.define("osparc.info.ServiceLarge", { vBox.add(deprecated); } - const title = this.__createTitle(); - const titleLayout = this.__createViewWithEdit(title, this.__openTitleEditor); - - const extraInfo = this.__extraInfo(); - const extraInfoLayout = this.__createExtraInfo(extraInfo); - - const bounds = this.getBounds(); - const offset = 30; - const maxThumbnailHeight = extraInfo.length*20; - let widgetWidth = bounds ? bounds.width - offset : 500 - offset; - let thumbnailWidth = widgetWidth - 2 * osparc.info.CardLarge.PADDING - osparc.info.CardLarge.EXTRA_INFO_WIDTH; - thumbnailWidth = Math.min(thumbnailWidth - 20, osparc.info.CardLarge.THUMBNAIL_MAX_WIDTH); - const thumbnail = this.__createThumbnail(thumbnailWidth, maxThumbnailHeight); - const thumbnailLayout = this.__createViewWithEdit(thumbnail, this.__openThumbnailEditor); - thumbnailLayout.getLayout().set({ - alignX: "center" - }); - - const infoAndThumbnail = new qx.ui.container.Composite(new qx.ui.layout.HBox(3).set({ - alignX: "center" - })); - infoAndThumbnail.add(extraInfoLayout); - infoAndThumbnail.add(thumbnailLayout, { - flex: 1 - }); - - let descriptionUi = null; - if (osparc.service.Utils.canIWrite(this.getService()["accessRights"])) { - descriptionUi = this.__createDescriptionUi(); - } - const description = this.__createDescription(); const editInTitle = this.__createViewWithEdit(description.getChildren()[0], this.__openDescriptionEditor); description.addAt(editInTitle, 0); - let resources = null; - if (!osparc.desktop.credits.Utils.areWalletsEnabled()) { - resources = this.__createResources(); - } - const copyMetadataButton = new qx.ui.form.Button(this.tr("Copy Raw metadata"), "@FontAwesome5Solid/copy/12").set({ allowGrowX: false }); copyMetadataButton.addListener("execute", () => osparc.utils.Utils.copyTextToClipboard(osparc.utils.Utils.prettifyJson(this.getService())), this); - if ( this.getService()["descriptionUi"] && !osparc.service.Utils.canIWrite(this.getService()["accessRights"]) && description.getChildren().length > 1 ) { - // Show description only - vBox.add(description.getChildren()[1]); + // Show also the copy Id buttons too + const buttonsLayout = new qx.ui.container.Composite(new qx.ui.layout.HBox(10)); + if (this.getNodeId()) { + const studyAlias = osparc.product.Utils.getStudyAlias({firstUpperCase: true}); + const copyStudyIdButton = new qx.ui.form.Button(this.tr(`Copy ${studyAlias} Id`), "@FontAwesome5Solid/copy/12").set({ + toolTipText: qx.locale.Manager.tr("Copy to clipboard"), + }); + copyStudyIdButton.addListener("execute", this.__copyStudyIdToClipboard, this); + buttonsLayout.add(copyStudyIdButton); + vBox.add(buttonsLayout); + + const copyNodeIdButton = new qx.ui.form.Button(this.tr("Copy Service Id"), "@FontAwesome5Solid/copy/12").set({ + toolTipText: qx.locale.Manager.tr("Copy to clipboard"), + }); + copyNodeIdButton.addListener("execute", this.__copyNodeIdToClipboard, this); + buttonsLayout.add(copyNodeIdButton); + vBox.add(buttonsLayout); + } + // Also copyMetadataButton if tester if (osparc.data.Permissions.getInstance().isTester()) { - // Also copyMetadataButton if tester - vBox.add(copyMetadataButton); + buttonsLayout.add(copyMetadataButton); + vBox.add(buttonsLayout); } + // Show description only + vBox.add(description.getChildren()[1]); } else { + const title = this.__createTitle(); + const titleLayout = this.__createViewWithEdit(title, this.__openTitleEditor); vBox.add(titleLayout); + + const extraInfo = this.__extraInfo(); + const extraInfoLayout = this.__createExtraInfo(extraInfo); + const bounds = this.getBounds(); + const offset = 30; + const maxThumbnailHeight = extraInfo.length*20; + let widgetWidth = bounds ? bounds.width - offset : 500 - offset; + let thumbnailWidth = widgetWidth - 2 * osparc.info.CardLarge.PADDING - osparc.info.CardLarge.EXTRA_INFO_WIDTH; + thumbnailWidth = Math.min(thumbnailWidth - 20, osparc.info.CardLarge.THUMBNAIL_MAX_WIDTH); + const thumbnail = this.__createThumbnail(thumbnailWidth, maxThumbnailHeight); + const thumbnailLayout = this.__createViewWithEdit(thumbnail, this.__openThumbnailEditor); + thumbnailLayout.getLayout().set({ + alignX: "center" + }); + const infoAndThumbnail = new qx.ui.container.Composite(new qx.ui.layout.HBox(3).set({ + alignX: "center" + })); + infoAndThumbnail.add(extraInfoLayout); + infoAndThumbnail.add(thumbnailLayout, { + flex: 1 + }); vBox.add(infoAndThumbnail); - if (descriptionUi) { - vBox.add(descriptionUi); + + if (osparc.service.Utils.canIWrite(this.getService()["accessRights"])) { + const descriptionUi = this.__createDescriptionUi(); + if (descriptionUi) { + vBox.add(descriptionUi); + } } vBox.add(description); - if (resources) { - vBox.add(resources); + + if (!osparc.desktop.credits.Utils.areWalletsEnabled()) { + const resources = this.__createResources(); + if (resources) { + vBox.add(resources); + } } vBox.add(copyMetadataButton); } @@ -429,6 +455,10 @@ qx.Class.define("osparc.info.ServiceLarge", { titleEditor.open(); }, + __copyStudyIdToClipboard: function() { + osparc.utils.Utils.copyTextToClipboard(this.getStudyId()); + }, + __copyNodeIdToClipboard: function() { osparc.utils.Utils.copyTextToClipboard(this.getNodeId()); }, diff --git a/services/static-webserver/client/source/class/osparc/metadata/ServicesInStudy.js b/services/static-webserver/client/source/class/osparc/metadata/ServicesInStudy.js index b51dc1c7515..eae2df3f1b9 100644 --- a/services/static-webserver/client/source/class/osparc/metadata/ServicesInStudy.js +++ b/services/static-webserver/client/source/class/osparc/metadata/ServicesInStudy.js @@ -147,12 +147,7 @@ qx.Class.define("osparc.metadata.ServicesInStudy", { studyId: this._studyData["uuid"], label: node["label"] }); - const title = this.tr("Service information"); - const width = osparc.info.CardLarge.WIDTH; - const height = osparc.info.CardLarge.HEIGHT; - osparc.ui.window.Window.popUpInWindow(serviceDetails, title, width, height).set({ - maxHeight: height - }); + osparc.info.ServiceLarge.popUpInWindow(serviceDetails); }, this); this._servicesGrid.add(infoButton, { row: i, diff --git a/services/static-webserver/client/source/class/osparc/node/slideshow/BaseNodeView.js b/services/static-webserver/client/source/class/osparc/node/slideshow/BaseNodeView.js index e7de026cd94..a2ee4daab00 100644 --- a/services/static-webserver/client/source/class/osparc/node/slideshow/BaseNodeView.js +++ b/services/static-webserver/client/source/class/osparc/node/slideshow/BaseNodeView.js @@ -217,17 +217,13 @@ qx.Class.define("osparc.node.slideshow.BaseNodeView", { __openServiceDetails: function() { const node = this.getNode(); - const serviceDetails = new osparc.info.ServiceLarge(node.getMetaData(), { + const metadata = node.getMetaData(); + const serviceDetails = new osparc.info.ServiceLarge(metadata, { nodeId: node.getNodeId(), label: node.getLabel(), studyId: node.getStudy().getUuid() }); - const title = this.tr("Service information"); - const width = osparc.info.CardLarge.WIDTH; - const height = osparc.info.CardLarge.HEIGHT; - osparc.ui.window.Window.popUpInWindow(serviceDetails, title, width, height).set({ - maxHeight: height - }); + osparc.info.ServiceLarge.popUpInWindow(serviceDetails); }, __openInstructions: function() { diff --git a/services/static-webserver/client/source/class/osparc/service/ServiceListItem.js b/services/static-webserver/client/source/class/osparc/service/ServiceListItem.js index 959859389ac..c970c2df3a9 100644 --- a/services/static-webserver/client/source/class/osparc/service/ServiceListItem.js +++ b/services/static-webserver/client/source/class/osparc/service/ServiceListItem.js @@ -161,12 +161,7 @@ qx.Class.define("osparc.service.ServiceListItem", { osparc.store.Services.getService(key, version) .then(serviceMetadata => { const serviceDetails = new osparc.info.ServiceLarge(serviceMetadata); - const title = this.tr("Service information"); - const width = osparc.info.CardLarge.WIDTH; - const height = osparc.info.CardLarge.HEIGHT; - osparc.ui.window.Window.popUpInWindow(serviceDetails, title, width, height).set({ - maxHeight: height - }); + osparc.info.ServiceLarge.popUpInWindow(serviceDetails); }); }, diff --git a/services/static-webserver/client/source/class/osparc/widget/NodesTree.js b/services/static-webserver/client/source/class/osparc/widget/NodesTree.js index 0b543b6a158..e88930b09c5 100644 --- a/services/static-webserver/client/source/class/osparc/widget/NodesTree.js +++ b/services/static-webserver/client/source/class/osparc/widget/NodesTree.js @@ -290,15 +290,13 @@ qx.Class.define("osparc.widget.NodesTree", { }); } else { const node = study.getWorkbench().getNode(nodeId); - const serviceDetails = new osparc.info.ServiceLarge(node.getMetaData(), { + const metadata = node.getMetaData(); + const serviceDetails = new osparc.info.ServiceLarge(metadata, { nodeId, label: node.getLabel(), studyId: study.getUuid() }); - const title = this.tr("Service information"); - osparc.ui.window.Window.popUpInWindow(serviceDetails, title, width, height).set({ - maxHeight: height - }); + osparc.info.ServiceLarge.popUpInWindow(serviceDetails); } } }, diff --git a/services/static-webserver/client/source/class/osparc/workbench/ServiceCatalog.js b/services/static-webserver/client/source/class/osparc/workbench/ServiceCatalog.js index faf60dd0034..b9dd0867a4c 100644 --- a/services/static-webserver/client/source/class/osparc/workbench/ServiceCatalog.js +++ b/services/static-webserver/client/source/class/osparc/workbench/ServiceCatalog.js @@ -300,12 +300,7 @@ qx.Class.define("osparc.workbench.ServiceCatalog", { __showServiceDetails: async function() { const serviceMetadata = await this.__getSelectedService(); const serviceDetails = new osparc.info.ServiceLarge(serviceMetadata); - const title = this.tr("Service information"); - const width = osparc.info.CardLarge.WIDTH; - const height = osparc.info.CardLarge.HEIGHT; - osparc.ui.window.Window.popUpInWindow(serviceDetails, title, width, height).set({ - maxHeight: height, - }); + osparc.info.ServiceLarge.popUpInWindow(serviceDetails); }, __onCancel: function() { diff --git a/services/static-webserver/client/source/class/osparc/workbench/WorkbenchUI.js b/services/static-webserver/client/source/class/osparc/workbench/WorkbenchUI.js index 21c55e487d1..504faf3c33f 100644 --- a/services/static-webserver/client/source/class/osparc/workbench/WorkbenchUI.js +++ b/services/static-webserver/client/source/class/osparc/workbench/WorkbenchUI.js @@ -1665,17 +1665,13 @@ qx.Class.define("osparc.workbench.WorkbenchUI", { __openNodeInfo: function(nodeId) { if (nodeId) { const node = this.getStudy().getWorkbench().getNode(nodeId); - const serviceDetails = new osparc.info.ServiceLarge(node.getMetaData(), { + const metadata = node.getMetaData(); + const serviceDetails = new osparc.info.ServiceLarge(metadata, { nodeId, label: node.getLabel(), studyId: this.getStudy().getUuid() }); - const title = this.tr("Service information"); - const width = osparc.info.CardLarge.WIDTH; - const height = osparc.info.CardLarge.HEIGHT; - osparc.ui.window.Window.popUpInWindow(serviceDetails, title, width, height).set({ - maxHeight: height - }); + osparc.info.ServiceLarge.popUpInWindow(serviceDetails); } },