From eb38e0df6b49c81b3f21198b1e1e2d730f9bbb40 Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Wed, 16 Apr 2025 15:45:01 +0200 Subject: [PATCH 01/16] addMoreMenu --- .../class/osparc/dashboard/NewPlusMenu.js | 30 +++++++++++++++++-- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/services/static-webserver/client/source/class/osparc/dashboard/NewPlusMenu.js b/services/static-webserver/client/source/class/osparc/dashboard/NewPlusMenu.js index 6d8c391fb934..1165235cc6bf 100644 --- a/services/static-webserver/client/source/class/osparc/dashboard/NewPlusMenu.js +++ b/services/static-webserver/client/source/class/osparc/dashboard/NewPlusMenu.js @@ -77,6 +77,7 @@ qx.Class.define("osparc.dashboard.NewPlusMenu", { }); this.__categoryHeaders = []; + this.__itemIdx = 0; this.__addItems(); }, @@ -137,11 +138,13 @@ qx.Class.define("osparc.dashboard.NewPlusMenu", { members: { __categoryHeaders: null, + __itemIdx: null, _createChildControlImpl: function(id) { let control; switch (id) { case "new-folder": + this.addSeparator(); control = this.self().createMenuButton( osparc.dashboard.CardBase.NEW_ICON + "16", this.tr("New Folder"), @@ -155,9 +158,9 @@ qx.Class.define("osparc.dashboard.NewPlusMenu", { }, __addItems: async function() { - this.getChildControl("new-folder"); - this.addSeparator(); await this.__addNewStudyItems(); + this.__addMoreMenu(); + this.getChildControl("new-folder"); }, __addNewStudyItems: async function() { @@ -183,6 +186,26 @@ qx.Class.define("osparc.dashboard.NewPlusMenu", { } }, + __addMoreMenu: function() { + const moreMenuButton = this.self().createMenuButton("@FontAwesome5Solid/star/14", this.tr("More")); + this.addAt(moreMenuButton, this.__itemIdx); + this.__itemIdx++; + + const moreMenu = new qx.ui.menu.Menu().set({ + appearance: "menu-wider", + }); + + const templatesButton = new qx.ui.menu.Button(this.tr("Tutorials..."), "@FontAwesome5Solid/copy/14"); + templatesButton.addListener("execute", () => this.fireDataEvent("moveFolderToRequested", this.getFolderId()), this); + moreMenu.add(templatesButton); + + const servicesButton = new qx.ui.menu.Button(this.tr("Services..."), "@FontAwesome5Solid/cog/14"); + servicesButton.addListener("execute", () => this.fireDataEvent("moveFolderToRequested", this.getFolderId()), this); + moreMenu.add(servicesButton); + + moreMenuButton.setMenu(moreMenu); + }, + __getLastIdxFromCategory: function(categoryId) { for (let i=this.getChildren().length-1; i>=0; i--) { const child = this.getChildren()[i]; @@ -237,7 +260,8 @@ qx.Class.define("osparc.dashboard.NewPlusMenu", { menuButton["categoryId"] = category; this.addAt(menuButton, idx+1); } else { - this.add(menuButton); + this.addAt(menuButton, this.__itemIdx); + this.__itemIdx++; } }, From d6897dcac600d879c5346b00f911021ded149d08 Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Wed, 16 Apr 2025 16:01:40 +0200 Subject: [PATCH 02/16] minor --- .../client/source/class/osparc/dashboard/NewPlusMenu.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/services/static-webserver/client/source/class/osparc/dashboard/NewPlusMenu.js b/services/static-webserver/client/source/class/osparc/dashboard/NewPlusMenu.js index 1165235cc6bf..bca98890eacc 100644 --- a/services/static-webserver/client/source/class/osparc/dashboard/NewPlusMenu.js +++ b/services/static-webserver/client/source/class/osparc/dashboard/NewPlusMenu.js @@ -146,7 +146,7 @@ qx.Class.define("osparc.dashboard.NewPlusMenu", { case "new-folder": this.addSeparator(); control = this.self().createMenuButton( - osparc.dashboard.CardBase.NEW_ICON + "16", + "@FontAwesome5Solid/folder/16", this.tr("New Folder"), ); osparc.utils.Utils.setIdToWidget(control, "newFolderButton"); @@ -187,7 +187,7 @@ qx.Class.define("osparc.dashboard.NewPlusMenu", { }, __addMoreMenu: function() { - const moreMenuButton = this.self().createMenuButton("@FontAwesome5Solid/star/14", this.tr("More")); + const moreMenuButton = this.self().createMenuButton("@FontAwesome5Solid/star/16", this.tr("More")); this.addAt(moreMenuButton, this.__itemIdx); this.__itemIdx++; @@ -195,11 +195,11 @@ qx.Class.define("osparc.dashboard.NewPlusMenu", { appearance: "menu-wider", }); - const templatesButton = new qx.ui.menu.Button(this.tr("Tutorials..."), "@FontAwesome5Solid/copy/14"); + const templatesButton = this.self().createMenuButton("@FontAwesome5Solid/copy/16", this.tr("Tutorials...")); templatesButton.addListener("execute", () => this.fireDataEvent("moveFolderToRequested", this.getFolderId()), this); moreMenu.add(templatesButton); - const servicesButton = new qx.ui.menu.Button(this.tr("Services..."), "@FontAwesome5Solid/cog/14"); + const servicesButton = this.self().createMenuButton("@FontAwesome5Solid/cog/16", this.tr("Services...")); servicesButton.addListener("execute", () => this.fireDataEvent("moveFolderToRequested", this.getFolderId()), this); moreMenu.add(servicesButton); From e51ad6a6c39cdd50d4cfab24aea39b72c05b7674 Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Wed, 16 Apr 2025 16:07:25 +0200 Subject: [PATCH 03/16] changeTab --- .../client/source/class/osparc/dashboard/NewPlusMenu.js | 5 +++-- .../client/source/class/osparc/dashboard/StudyBrowser.js | 2 ++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/services/static-webserver/client/source/class/osparc/dashboard/NewPlusMenu.js b/services/static-webserver/client/source/class/osparc/dashboard/NewPlusMenu.js index bca98890eacc..70fc01cc8abe 100644 --- a/services/static-webserver/client/source/class/osparc/dashboard/NewPlusMenu.js +++ b/services/static-webserver/client/source/class/osparc/dashboard/NewPlusMenu.js @@ -84,6 +84,7 @@ qx.Class.define("osparc.dashboard.NewPlusMenu", { events: { "createFolder": "qx.event.type.Data", + "changeTab": "qx.event.type.Data", "newEmptyStudyClicked": "qx.event.type.Data", "newStudyFromTemplateClicked": "qx.event.type.Data", "newStudyFromServiceClicked": "qx.event.type.Data", @@ -196,11 +197,11 @@ qx.Class.define("osparc.dashboard.NewPlusMenu", { }); const templatesButton = this.self().createMenuButton("@FontAwesome5Solid/copy/16", this.tr("Tutorials...")); - templatesButton.addListener("execute", () => this.fireDataEvent("moveFolderToRequested", this.getFolderId()), this); + templatesButton.addListener("execute", () => this.fireDataEvent("changeTab", "templatesTab"), this); moreMenu.add(templatesButton); const servicesButton = this.self().createMenuButton("@FontAwesome5Solid/cog/16", this.tr("Services...")); - servicesButton.addListener("execute", () => this.fireDataEvent("moveFolderToRequested", this.getFolderId()), this); + servicesButton.addListener("execute", () => this.fireDataEvent("changeTab", "servicesTab"), this); moreMenu.add(servicesButton); moreMenuButton.setMenu(moreMenu); diff --git a/services/static-webserver/client/source/class/osparc/dashboard/StudyBrowser.js b/services/static-webserver/client/source/class/osparc/dashboard/StudyBrowser.js index 941c02a1e230..863a16f8a5d3 100644 --- a/services/static-webserver/client/source/class/osparc/dashboard/StudyBrowser.js +++ b/services/static-webserver/client/source/class/osparc/dashboard/StudyBrowser.js @@ -836,6 +836,8 @@ qx.Class.define("osparc.dashboard.StudyBrowser", { this.__createFolder(data); }, this); + newPlusButtonMenu.addListener("changeTab", e => this.fireDataEvent("changeTab", e.getData())); + newPlusButtonMenu.addListener("newEmptyStudyClicked", e => { const { newStudyLabel, From fbcf000cefc4988c557fec47b03bb4c4f30fe4a0 Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Wed, 16 Apr 2025 17:13:15 +0200 Subject: [PATCH 04/16] Templates store --- .../class/osparc/dashboard/Dashboard.js | 1 + .../class/osparc/dashboard/NewPlusMenu.js | 38 +++++++-------- .../class/osparc/dashboard/NewStudies.js | 20 ++++---- .../class/osparc/dashboard/StudyBrowser.js | 42 ++++++++--------- .../source/class/osparc/store/Templates.js | 47 +++++++++++++++++++ 5 files changed, 94 insertions(+), 54 deletions(-) create mode 100644 services/static-webserver/client/source/class/osparc/store/Templates.js diff --git a/services/static-webserver/client/source/class/osparc/dashboard/Dashboard.js b/services/static-webserver/client/source/class/osparc/dashboard/Dashboard.js index ee1c1bbbe764..e9b50616f63a 100644 --- a/services/static-webserver/client/source/class/osparc/dashboard/Dashboard.js +++ b/services/static-webserver/client/source/class/osparc/dashboard/Dashboard.js @@ -182,6 +182,7 @@ qx.Class.define("osparc.dashboard.Dashboard", { const groupsStore = osparc.store.Groups.getInstance(); preResourcePromises.push(groupsStore.fetchGroupsAndMembers()); preResourcePromises.push(osparc.store.Services.getServicesLatest(false)); + preResourcePromises.push(osparc.store.Templates.getInstance().fetchAllTemplates()); Promise.all(preResourcePromises) .then(() => { [ diff --git a/services/static-webserver/client/source/class/osparc/dashboard/NewPlusMenu.js b/services/static-webserver/client/source/class/osparc/dashboard/NewPlusMenu.js index 70fc01cc8abe..981de433404f 100644 --- a/services/static-webserver/client/source/class/osparc/dashboard/NewPlusMenu.js +++ b/services/static-webserver/client/source/class/osparc/dashboard/NewPlusMenu.js @@ -158,32 +158,30 @@ qx.Class.define("osparc.dashboard.NewPlusMenu", { return control || this.base(arguments, id); }, - __addItems: async function() { - await this.__addNewStudyItems(); + __addItems: function() { + this.__addNewStudyItems(); this.__addMoreMenu(); this.getChildControl("new-folder"); }, - __addNewStudyItems: async function() { + __addNewStudyItems: function() { const plusButtonConfig = osparc.store.Products.getInstance().getPlusButtonUiConfig(); if (plusButtonConfig) { - await osparc.data.Resources.get("templates") - .then(templates => { - if (plusButtonConfig["categories"]) { - this.__addCategories(plusButtonConfig["categories"]); - } - plusButtonConfig["resources"].forEach(buttonConfig => { - if (buttonConfig["showDisabled"]) { - this.__addDisabledButton(buttonConfig); - } else if (buttonConfig["resourceType"] === "study") { - this.__addEmptyStudyButton(buttonConfig); - } else if (buttonConfig["resourceType"] === "template") { - this.__addFromTemplateButton(buttonConfig, templates); - } else if (buttonConfig["resourceType"] === "service") { - this.__addFromServiceButton(buttonConfig); - } - }); - }); + const templates = osparc.store.Templates.getInstance().getTemplates() + if (plusButtonConfig["categories"]) { + this.__addCategories(plusButtonConfig["categories"]); + } + plusButtonConfig["resources"].forEach(buttonConfig => { + if (buttonConfig["showDisabled"]) { + this.__addDisabledButton(buttonConfig); + } else if (buttonConfig["resourceType"] === "study") { + this.__addEmptyStudyButton(buttonConfig); + } else if (buttonConfig["resourceType"] === "template") { + this.__addFromTemplateButton(buttonConfig, templates); + } else if (buttonConfig["resourceType"] === "service") { + this.__addFromServiceButton(buttonConfig); + } + }); } }, diff --git a/services/static-webserver/client/source/class/osparc/dashboard/NewStudies.js b/services/static-webserver/client/source/class/osparc/dashboard/NewStudies.js index 847d29d84a8f..48a8c4a8016f 100644 --- a/services/static-webserver/client/source/class/osparc/dashboard/NewStudies.js +++ b/services/static-webserver/client/source/class/osparc/dashboard/NewStudies.js @@ -36,18 +36,14 @@ qx.Class.define("osparc.dashboard.NewStudies", { }); this._add(this.__flatList); - osparc.data.Resources.get("templates") - .then(templates => { - const displayTemplates = newButtonsInfo.filter(newButtonInfo => { - if (newButtonInfo.showDisabled) { - return true; - } - return templates.find(t => t.name === newButtonInfo.expectedTemplateLabel); - }); - this.__newStudies = displayTemplates; - }) - .catch(console.error) - .finally(() => this.fireEvent("templatesLoaded")); + const templates = osparc.store.Templates.getInstance().getTemplates() + this.__newStudies = newButtonsInfo.filter(newButtonInfo => { + if (newButtonInfo.showDisabled) { + return true; + } + return templates.find(t => t.name === newButtonInfo.expectedTemplateLabel); + }); + this.fireEvent("templatesLoaded"); }, properties: { diff --git a/services/static-webserver/client/source/class/osparc/dashboard/StudyBrowser.js b/services/static-webserver/client/source/class/osparc/dashboard/StudyBrowser.js index 863a16f8a5d3..782ea1c3d212 100644 --- a/services/static-webserver/client/source/class/osparc/dashboard/StudyBrowser.js +++ b/services/static-webserver/client/source/class/osparc/dashboard/StudyBrowser.js @@ -973,29 +973,27 @@ qx.Class.define("osparc.dashboard.StudyBrowser", { newPlansBtn.setEnabled(true); newPlansBtn.addListener("tap", () => { - osparc.data.Resources.get("templates") - .then(templates => { - if (templates) { - const newStudies = new osparc.dashboard.NewStudies(newStudiesConfig); - newStudies.addListener("templatesLoaded", () => { - newStudies.setGroupBy("category"); - const winTitle = this.tr("New Plan"); - const win = osparc.ui.window.Window.popUpInWindow(newStudies, winTitle, osparc.dashboard.NewStudies.WIDTH+40, 300).set({ - clickAwayClose: false, - resizable: true - }); - newStudies.addListener("newStudyClicked", e => { - win.close(); - const templateInfo = e.getData(); - const templateData = templates.find(t => t.name === templateInfo.expectedTemplateLabel); - if (templateData) { - this.__newPlanBtnClicked(templateData, templateInfo.newStudyLabel); - } - }); - osparc.utils.Utils.setIdToWidget(win, "newStudiesWindow"); - }); - } + const templates = osparc.store.Templates.getInstance().getTemplates(); + if (templates) { + const newStudies = new osparc.dashboard.NewStudies(newStudiesConfig); + newStudies.addListener("templatesLoaded", () => { + newStudies.setGroupBy("category"); + const winTitle = this.tr("New Plan"); + const win = osparc.ui.window.Window.popUpInWindow(newStudies, winTitle, osparc.dashboard.NewStudies.WIDTH+40, 300).set({ + clickAwayClose: false, + resizable: true + }); + newStudies.addListener("newStudyClicked", e => { + win.close(); + const templateInfo = e.getData(); + const templateData = templates.find(t => t.name === templateInfo.expectedTemplateLabel); + if (templateData) { + this.__newPlanBtnClicked(templateData, templateInfo.newStudyLabel); + } + }); + osparc.utils.Utils.setIdToWidget(win, "newStudiesWindow"); }); + } }); } }, diff --git a/services/static-webserver/client/source/class/osparc/store/Templates.js b/services/static-webserver/client/source/class/osparc/store/Templates.js new file mode 100644 index 000000000000..84e5fd0281d7 --- /dev/null +++ b/services/static-webserver/client/source/class/osparc/store/Templates.js @@ -0,0 +1,47 @@ +/* ************************************************************************ + + osparc - the simcore frontend + + https://osparc.io + + Copyright: + 2025 IT'IS Foundation, https://itis.swiss + + License: + MIT: https://opensource.org/licenses/MIT + + Authors: + * Odei Maiz (odeimaiz) + +************************************************************************ */ + +qx.Class.define("osparc.store.Templates", { + extend: qx.core.Object, + type: "singleton", + + construct: function() { + this.base(arguments); + + this.__templates = []; + }, + + members: { + __templates: null, + + fetchAllTemplates: function() { + if (this.__templates.length) { + return new Promise(resolve => resolve(this.__templates)); + } + + return osparc.data.Resources.getInstance().getAllPages("templates") + .then(templates => { + this.__templates = templates; + return templates; + }); + }, + + getTemplates: function() { + return this.__templates; + }, + } +}); From d95e5008ca079a5fa61ad346867000975fd78acb Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Wed, 16 Apr 2025 17:19:02 +0200 Subject: [PATCH 05/16] more to Store --- .../desktop/organizations/TemplatesList.js | 33 ++++++++----------- .../source/class/osparc/store/Templates.js | 4 +++ 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/services/static-webserver/client/source/class/osparc/desktop/organizations/TemplatesList.js b/services/static-webserver/client/source/class/osparc/desktop/organizations/TemplatesList.js index bc0431ac22d9..b66b89784951 100644 --- a/services/static-webserver/client/source/class/osparc/desktop/organizations/TemplatesList.js +++ b/services/static-webserver/client/source/class/osparc/desktop/organizations/TemplatesList.js @@ -86,17 +86,14 @@ qx.Class.define("osparc.desktop.organizations.TemplatesList", { item.subscribeToFilterGroup("organizationTemplatesList"); item.addListener("openMoreInfo", e => { const templateId = e.getData()["key"]; - osparc.data.Resources.get("templates") - .then(templates => { - const templateData = templates.find(t => t.uuid === templateId); - if (templateData) { - templateData["resourceType"] = "template"; - const resourceDetails = new osparc.dashboard.ResourceDetails(templateData).set({ - showOpenButton: false - }); - osparc.dashboard.ResourceDetails.popUpInWindow(resourceDetails); - } + const templateData = osparc.store.Templates.getInstance().getTemplate(templateId); + if (templateData) { + templateData["resourceType"] = "template"; + const resourceDetails = new osparc.dashboard.ResourceDetails(templateData).set({ + showOpenButton: false }); + osparc.dashboard.ResourceDetails.popUpInWindow(resourceDetails); + } }); } }); @@ -114,15 +111,13 @@ qx.Class.define("osparc.desktop.organizations.TemplatesList", { } const groupId = orgModel.getGroupId(); - osparc.data.Resources.getInstance().getAllPages("templates") - .then(templates => { - const orgTemplates = templates.filter(template => groupId in template["accessRights"]); - orgTemplates.forEach(orgTemplate => { - const orgTemplateCopy = osparc.utils.Utils.deepCloneObject(orgTemplate); - orgTemplateCopy["orgId"] = groupId; - templatesModel.append(qx.data.marshal.Json.createModel(orgTemplateCopy)); - }); - }); + const templates = osparc.store.Templates.getInstance().getTemplates(); + const orgTemplates = templates.filter(template => groupId in template["accessRights"]); + orgTemplates.forEach(orgTemplate => { + const orgTemplateCopy = osparc.utils.Utils.deepCloneObject(orgTemplate); + orgTemplateCopy["orgId"] = groupId; + templatesModel.append(qx.data.marshal.Json.createModel(orgTemplateCopy)); + }); } } }); diff --git a/services/static-webserver/client/source/class/osparc/store/Templates.js b/services/static-webserver/client/source/class/osparc/store/Templates.js index 84e5fd0281d7..db2468b08525 100644 --- a/services/static-webserver/client/source/class/osparc/store/Templates.js +++ b/services/static-webserver/client/source/class/osparc/store/Templates.js @@ -43,5 +43,9 @@ qx.Class.define("osparc.store.Templates", { getTemplates: function() { return this.__templates; }, + + getTemplate: function(templateId) { + return this.__templates.find(t => t.uuid === templateId); + }, } }); From ea2779eb2b5a4ad9584905ba15a2ede1a95bc103 Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Wed, 16 Apr 2025 17:29:00 +0200 Subject: [PATCH 06/16] more refactoring --- .../class/osparc/dashboard/TemplateBrowser.js | 28 ++++++++++--------- .../source/class/osparc/desktop/MainPage.js | 4 ++- .../source/class/osparc/info/StudyLarge.js | 4 --- .../source/class/osparc/store/Templates.js | 4 +++ 4 files changed, 22 insertions(+), 18 deletions(-) diff --git a/services/static-webserver/client/source/class/osparc/dashboard/TemplateBrowser.js b/services/static-webserver/client/source/class/osparc/dashboard/TemplateBrowser.js index f5b1d9c8bc38..8815591543e1 100644 --- a/services/static-webserver/client/source/class/osparc/dashboard/TemplateBrowser.js +++ b/services/static-webserver/client/source/class/osparc/dashboard/TemplateBrowser.js @@ -35,18 +35,14 @@ qx.Class.define("osparc.dashboard.TemplateBrowser", { this._hideLoadingPage(); }, - reloadResources: function() { + reloadResources: function(useCache = true) { if (osparc.data.Permissions.getInstance().canDo("studies.templates.read")) { - this.__reloadTemplates(); + this.__reloadTemplates(useCache); } else { this.__setResourcesToList([]); } }, - invalidateTemplates: function() { - osparc.store.Store.getInstance().invalidate("templates"); - }, - __attachEventHandlers: function() { const socket = osparc.wrapper.WebSocket.getInstance(); socket.on("projectStateUpdated", data => { @@ -74,15 +70,21 @@ qx.Class.define("osparc.dashboard.TemplateBrowser", { } }, - __reloadTemplates: function() { + __reloadTemplates: function(useCache) { this.__tasksToCards(); - osparc.data.Resources.getInstance().getAllPages("templates") - .then(templates => this.__setResourcesToList(templates)) - .catch(err => { - console.error(err); - this.__setResourcesToList([]); - }); + const templatesStore = osparc.store.Templates.getInstance(); + if (useCache) { + const templates = templatesStore.getTemplates(); + this.__setResourcesToList(templates); + } else { + templatesStore.fetchAllTemplates() + .then(templates => this.__setResourcesToList(templates)) + .catch(err => { + console.error(err); + this.__setResourcesToList([]); + }); + } }, _updateTemplateData: function(templateData) { diff --git a/services/static-webserver/client/source/class/osparc/desktop/MainPage.js b/services/static-webserver/client/source/class/osparc/desktop/MainPage.js index 350361c6e9b4..4e3492e3e546 100644 --- a/services/static-webserver/client/source/class/osparc/desktop/MainPage.js +++ b/services/static-webserver/client/source/class/osparc/desktop/MainPage.js @@ -158,7 +158,9 @@ qx.Class.define("osparc.desktop.MainPage", { this.closeEditor(); this.__showDashboard(); // reset templates - this.__dashboard.getTemplateBrowser().invalidateTemplates(); + // OM is this needed? + // this.__dashboard.getTemplateBrowser().invalidateTemplates(); + osparc.store.Templates.getInstance().invalidateTemplates(); this.__dashboard.getTemplateBrowser().reloadResources(); // reset studies this.__dashboard.getStudyBrowser().invalidateStudies(); diff --git a/services/static-webserver/client/source/class/osparc/info/StudyLarge.js b/services/static-webserver/client/source/class/osparc/info/StudyLarge.js index e0b66e410470..069eb30a3e32 100644 --- a/services/static-webserver/client/source/class/osparc/info/StudyLarge.js +++ b/services/static-webserver/client/source/class/osparc/info/StudyLarge.js @@ -310,10 +310,6 @@ qx.Class.define("osparc.info.StudyLarge", { studyData["resourceType"] = this.__isTemplate ? "template" : "study"; this.fireDataEvent("updateStudy", studyData); qx.event.message.Bus.getInstance().dispatchByName("updateStudy", studyData); - if (this.__isTemplate) { - // reload templates - osparc.data.Resources.get("templates", {}, false) - } }) .catch(err => { const msg = this.tr("An issue occurred while updating the information."); diff --git a/services/static-webserver/client/source/class/osparc/store/Templates.js b/services/static-webserver/client/source/class/osparc/store/Templates.js index db2468b08525..5c47dcdc4a9b 100644 --- a/services/static-webserver/client/source/class/osparc/store/Templates.js +++ b/services/static-webserver/client/source/class/osparc/store/Templates.js @@ -40,6 +40,10 @@ qx.Class.define("osparc.store.Templates", { }); }, + invalidateTemplates: function() { + this.__templates = []; + }, + getTemplates: function() { return this.__templates; }, From 947b02e1dd02594a3538430f6a27a8621b5354f1 Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Wed, 16 Apr 2025 17:55:46 +0200 Subject: [PATCH 07/16] addEmptyStudyButton --- .../class/osparc/dashboard/NewPlusMenu.js | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/services/static-webserver/client/source/class/osparc/dashboard/NewPlusMenu.js b/services/static-webserver/client/source/class/osparc/dashboard/NewPlusMenu.js index 981de433404f..972df6a55792 100644 --- a/services/static-webserver/client/source/class/osparc/dashboard/NewPlusMenu.js +++ b/services/static-webserver/client/source/class/osparc/dashboard/NewPlusMenu.js @@ -160,6 +160,7 @@ qx.Class.define("osparc.dashboard.NewPlusMenu", { __addItems: function() { this.__addNewStudyItems(); + this.__addEmptyStudyButton(); this.__addMoreMenu(); this.getChildControl("new-folder"); }, @@ -228,14 +229,8 @@ qx.Class.define("osparc.dashboard.NewPlusMenu", { }); }, - __addIcon: function(menuButton, resourceInfo, resourceMetadata) { - let source = null; - if (resourceInfo && resourceInfo["icon"]) { - source = resourceInfo["icon"]; - } else { - source = osparc.utils.Utils.getIconFromResource(resourceMetadata); - } - + __addIcon: function(menuButton, icon, resourceMetadata) { + const source = icon ? icon : osparc.utils.Utils.getIconFromResource(resourceMetadata); if (source) { const thumbnail = new osparc.ui.basic.Thumbnail(source, 24, 24).set({ minHeight: 24, @@ -269,21 +264,25 @@ qx.Class.define("osparc.dashboard.NewPlusMenu", { osparc.utils.Utils.setIdToWidget(menuButton, buttonConfig["idToWidget"]); menuButton.setEnabled(false); - this.__addIcon(menuButton, buttonConfig); + this.__addIcon(menuButton, buttonConfig["icon"]); this.__addFromResourceButton(menuButton, buttonConfig["category"]); }, - __addEmptyStudyButton: function(buttonConfig) { - const menuButton = this.self().createMenuButton(null, buttonConfig["title"]); - osparc.utils.Utils.setIdToWidget(menuButton, buttonConfig["idToWidget"]); + __addEmptyStudyButton: function(buttonConfig = {}) { + if (this.__emptyPipelineButton) { + return; + } + + const menuButton = this.__emptyPipelineButton = this.self().createMenuButton(null, buttonConfig["title"] || "Empty Pipeline"); + osparc.utils.Utils.setIdToWidget(menuButton, buttonConfig["idToWidget"] || "emptyStudyBtn"); menuButton.addListener("tap", () => { this.fireDataEvent("newEmptyStudyClicked", { - newStudyLabel: buttonConfig["newStudyLabel"], + newStudyLabel: buttonConfig["newStudyLabel"] || "Empty Pipeline", }); }); - this.__addIcon(menuButton, buttonConfig); + this.__addIcon(menuButton, buttonConfig["icon"] || "osparc/icons/diagram.png"); this.__addFromResourceButton(menuButton, buttonConfig["category"]); }, @@ -302,7 +301,7 @@ qx.Class.define("osparc.dashboard.NewPlusMenu", { newStudyLabel: buttonConfig["newStudyLabel"], }); }); - this.__addIcon(menuButton, buttonConfig, templateMetadata); + this.__addIcon(menuButton, buttonConfig["icon"], templateMetadata); this.__addFromResourceButton(menuButton, buttonConfig["category"]); } }, @@ -350,7 +349,7 @@ qx.Class.define("osparc.dashboard.NewPlusMenu", { return; } menuButton.setEnabled(true); - this.__addIcon(menuButton, buttonConfig, latestMetadata); + this.__addIcon(menuButton, buttonConfig["icon"], latestMetadata); this.__addFromResourceButton(menuButton, buttonConfig["category"]); addListenerToButton(menuButton, latestMetadata); } else if ("myMostUsed" in buttonConfig) { From 9198b5f9beb40b011f094800d95be6e7d728a65f Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Thu, 17 Apr 2025 12:21:15 +0200 Subject: [PATCH 08/16] Display Maintenance message --- .../source/class/osparc/MaintenanceTracker.js | 23 ++++++++++--------- .../source/class/osparc/admin/Maintenance.js | 5 ++++ 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/services/static-webserver/client/source/class/osparc/MaintenanceTracker.js b/services/static-webserver/client/source/class/osparc/MaintenanceTracker.js index 4a8d552deff3..2823d768e141 100644 --- a/services/static-webserver/client/source/class/osparc/MaintenanceTracker.js +++ b/services/static-webserver/client/source/class/osparc/MaintenanceTracker.js @@ -129,27 +129,28 @@ qx.Class.define("osparc.MaintenanceTracker", { } }, + __messageToRibbon: function(closable) { + this.__removeRibbonMessage(); + const text = this.__getText(); + const notification = new osparc.notification.RibbonNotification(text, "maintenance", closable); + osparc.notification.RibbonNotifications.getInstance().addNotification(notification); + this.__lastRibbonMessage = notification; + }, + __scheduleRibbonMessage: function() { const now = new Date(); const diffClosable = this.getStart().getTime() - now.getTime() - this.self().CLOSABLE_WARN_IN_ADVANCE; const diffPermanent = this.getStart().getTime() - now.getTime() - this.self().PERMANENT_WARN_IN_ADVANCE; - const messageToRibbon = closable => { - this.__removeRibbonMessage(); - const text = this.__getText(); - const notification = new osparc.notification.RibbonNotification(text, "maintenance", closable); - osparc.notification.RibbonNotifications.getInstance().addNotification(notification); - this.__lastRibbonMessage = notification; - }; if (diffClosable < 0) { - messageToRibbon(true); + this.__messageToRibbon(true); } else { - setTimeout(() => messageToRibbon(true), diffClosable); + setTimeout(() => this.__messageToRibbon(true), diffClosable); } if (diffPermanent < 0) { - messageToRibbon(false); + this.__messageToRibbon(false); } else { - setTimeout(() => messageToRibbon(false), diffPermanent); + setTimeout(() => this.__messageToRibbon(false), diffPermanent); } }, diff --git a/services/static-webserver/client/source/class/osparc/admin/Maintenance.js b/services/static-webserver/client/source/class/osparc/admin/Maintenance.js index e40df76f3a10..395757ff4030 100644 --- a/services/static-webserver/client/source/class/osparc/admin/Maintenance.js +++ b/services/static-webserver/client/source/class/osparc/admin/Maintenance.js @@ -53,6 +53,11 @@ qx.Class.define("osparc.admin.Maintenance", { const respLabel = new qx.ui.basic.Label(this.tr("Start and End dates go in UTC time zone")); vBox.add(respLabel); + const displayMaintenanceBtn = new qx.ui.form.Button(this.tr("Display Maintenance message")); + // eslint-disable-next-line no-underscore-dangle + displayMaintenanceBtn.addListener("execute", () => osparc.MaintenanceTracker.getInstance().__messageToRibbon(true)); + vBox.add(displayMaintenanceBtn); + const invitationRespViewer = new osparc.ui.basic.JsonTreeWidget(data, "maintenance-data"); const container = new qx.ui.container.Scroll(); container.add(invitationRespViewer); From 06872811373a2aa29673d4b304a60b271b9abab0 Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Thu, 17 Apr 2025 12:29:20 +0200 Subject: [PATCH 09/16] renaming --- .../client/source/class/osparc/dashboard/NewPlusMenu.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/services/static-webserver/client/source/class/osparc/dashboard/NewPlusMenu.js b/services/static-webserver/client/source/class/osparc/dashboard/NewPlusMenu.js index 972df6a55792..426d4e944dc8 100644 --- a/services/static-webserver/client/source/class/osparc/dashboard/NewPlusMenu.js +++ b/services/static-webserver/client/source/class/osparc/dashboard/NewPlusMenu.js @@ -159,13 +159,13 @@ qx.Class.define("osparc.dashboard.NewPlusMenu", { }, __addItems: function() { - this.__addNewStudyItems(); + this.__addUIConfigItems(); this.__addEmptyStudyButton(); - this.__addMoreMenu(); + this.__addOtherTabsAccess(); this.getChildControl("new-folder"); }, - __addNewStudyItems: function() { + __addUIConfigItems: function() { const plusButtonConfig = osparc.store.Products.getInstance().getPlusButtonUiConfig(); if (plusButtonConfig) { const templates = osparc.store.Templates.getInstance().getTemplates() @@ -186,7 +186,7 @@ qx.Class.define("osparc.dashboard.NewPlusMenu", { } }, - __addMoreMenu: function() { + __addOtherTabsAccess: function() { const moreMenuButton = this.self().createMenuButton("@FontAwesome5Solid/star/16", this.tr("More")); this.addAt(moreMenuButton, this.__itemIdx); this.__itemIdx++; From bcef0b31e85322fe0394d492abfa16819897afc3 Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Thu, 17 Apr 2025 12:36:15 +0200 Subject: [PATCH 10/16] s4l and s4lacad have Empty Pipeline by default --- .../source/class/osparc/dashboard/NewPlusMenu.js | 1 - .../client/source/resource/osparc/ui_config.json | 10 ++++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/services/static-webserver/client/source/class/osparc/dashboard/NewPlusMenu.js b/services/static-webserver/client/source/class/osparc/dashboard/NewPlusMenu.js index 426d4e944dc8..0fad5a57bff4 100644 --- a/services/static-webserver/client/source/class/osparc/dashboard/NewPlusMenu.js +++ b/services/static-webserver/client/source/class/osparc/dashboard/NewPlusMenu.js @@ -160,7 +160,6 @@ qx.Class.define("osparc.dashboard.NewPlusMenu", { __addItems: function() { this.__addUIConfigItems(); - this.__addEmptyStudyButton(); this.__addOtherTabsAccess(); this.getChildControl("new-folder"); }, diff --git a/services/static-webserver/client/source/resource/osparc/ui_config.json b/services/static-webserver/client/source/resource/osparc/ui_config.json index 826f64cf9a90..181f1f846f55 100644 --- a/services/static-webserver/client/source/resource/osparc/ui_config.json +++ b/services/static-webserver/client/source/resource/osparc/ui_config.json @@ -114,6 +114,11 @@ "expectedKey": "simcore/services/dynamic/iseg-web", "title": "Segmentation", "newStudyLabel": "Segmentation" + }, { + "resourceType": "study", + "title": "Empty Pipeline", + "newStudyLabel": "New Pipeline", + "idToWidget": "emptyStudyBtn" }] } }, @@ -135,6 +140,11 @@ "expectedKey": "simcore/services/dynamic/iseg-web", "title": "Segmentation", "newStudyLabel": "Segmentation" + }, { + "resourceType": "study", + "title": "Empty Pipeline", + "newStudyLabel": "New Pipeline", + "idToWidget": "emptyStudyBtn" }] } }, From 9efd723644d614ee679b955cfb8e6c1956935301 Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Thu, 17 Apr 2025 13:19:01 +0200 Subject: [PATCH 11/16] minor --- .../client/source/class/osparc/service/Utils.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/services/static-webserver/client/source/class/osparc/service/Utils.js b/services/static-webserver/client/source/class/osparc/service/Utils.js index ab1ee841c74e..ef6e687d2542 100644 --- a/services/static-webserver/client/source/class/osparc/service/Utils.js +++ b/services/static-webserver/client/source/class/osparc/service/Utils.js @@ -171,6 +171,10 @@ qx.Class.define("osparc.service.Utils", { }, __extractRetiredDate: function(metadata) { + if (!metadata) { + return null; + } + if ("release" in metadata && metadata["release"]["retired"]) { // this works for service latest return new Date(metadata["release"]["retired"]); From bb84c084ac89f082646f8ad949b2a77a3ecc933c Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Thu, 17 Apr 2025 14:00:34 +0200 Subject: [PATCH 12/16] data tab only available in osparc and testers --- .../client/source/class/osparc/dashboard/Dashboard.js | 1 - .../client/source/class/osparc/data/Permissions.js | 8 ++++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/services/static-webserver/client/source/class/osparc/dashboard/Dashboard.js b/services/static-webserver/client/source/class/osparc/dashboard/Dashboard.js index c0ec6676f175..fe9f48b49578 100644 --- a/services/static-webserver/client/source/class/osparc/dashboard/Dashboard.js +++ b/services/static-webserver/client/source/class/osparc/dashboard/Dashboard.js @@ -147,7 +147,6 @@ qx.Class.define("osparc.dashboard.Dashboard", { buttonId: "dataTabBtn", label: this.tr("DATA"), icon: "@FontAwesome5Solid/folder/"+tabIconSize, - initVisibility: osparc.product.Utils.isProduct("osparc") ? "visible" : "excluded", buildLayout: this.__createDataBrowser }); } diff --git a/services/static-webserver/client/source/class/osparc/data/Permissions.js b/services/static-webserver/client/source/class/osparc/data/Permissions.js index c5029458feb8..c21914386467 100644 --- a/services/static-webserver/client/source/class/osparc/data/Permissions.js +++ b/services/static-webserver/client/source/class/osparc/data/Permissions.js @@ -145,6 +145,7 @@ qx.Class.define("osparc.data.Permissions", { ], "admin": [] }; + let fromUserToTester = []; if (osparc.product.Utils.isProduct("tis") || osparc.product.Utils.isProduct("tiplite")) { // "templates" and "services" tabs only for testers @@ -162,6 +163,13 @@ qx.Class.define("osparc.data.Permissions", { "dashboard.services.read" ]; } + if (osparc.product.Utils.getProductName() !== "osparc") { + // data tab only available in osparc and testers + fromUserToTester = [ + "dashboard.data.read" + ]; + } + fromUserToTester.forEach(onlyTester => { const idx = initPermissions.user.indexOf(onlyTester); if (idx > -1) { From 70b62b060c6f43153663a416c4878d7cdc950cca Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Thu, 17 Apr 2025 14:14:32 +0200 Subject: [PATCH 13/16] dynamic More --- .../class/osparc/dashboard/NewPlusMenu.js | 26 ++++++++++++++----- .../source/class/osparc/store/Templates.js | 4 +++ 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/services/static-webserver/client/source/class/osparc/dashboard/NewPlusMenu.js b/services/static-webserver/client/source/class/osparc/dashboard/NewPlusMenu.js index 0fad5a57bff4..7bba3f305fad 100644 --- a/services/static-webserver/client/source/class/osparc/dashboard/NewPlusMenu.js +++ b/services/static-webserver/client/source/class/osparc/dashboard/NewPlusMenu.js @@ -194,13 +194,27 @@ qx.Class.define("osparc.dashboard.NewPlusMenu", { appearance: "menu-wider", }); - const templatesButton = this.self().createMenuButton("@FontAwesome5Solid/copy/16", this.tr("Tutorials...")); - templatesButton.addListener("execute", () => this.fireDataEvent("changeTab", "templatesTab"), this); - moreMenu.add(templatesButton); + const permissions = osparc.data.Permissions.getInstance(); + if (permissions.canDo("dashboard.templates.read")) { + const templatesButton = this.self().createMenuButton("@FontAwesome5Solid/copy/16", this.tr("Tutorials...")); + templatesButton.addListener("execute", () => this.fireDataEvent("changeTab", "templatesTab"), this); + moreMenu.add(templatesButton); + + const hypertoolsButton = this.self().createMenuButton("@FontAwesome5Solid/copy/16", this.tr("Hypertools...")); + hypertoolsButton.addListener("execute", () => this.fireDataEvent("changeTab", "hypertoolsTab"), this); + const hypertools = osparc.store.Templates.getInstance().getTemplatesByType(osparc.data.model.StudyUI.HYPERTOOL_TYPE); + if (hypertools.length) { + moreMenu.add(hypertoolsButton); + } + } + + if (permissions.canDo("dashboard.services.read")) { + const servicesButton = this.self().createMenuButton("@FontAwesome5Solid/cog/16", this.tr("Services...")); + servicesButton.addListener("execute", () => this.fireDataEvent("changeTab", "servicesTab"), this); + moreMenu.add(servicesButton); + } - const servicesButton = this.self().createMenuButton("@FontAwesome5Solid/cog/16", this.tr("Services...")); - servicesButton.addListener("execute", () => this.fireDataEvent("changeTab", "servicesTab"), this); - moreMenu.add(servicesButton); + moreMenuButton.setVisibility(moreMenu.getChildren().length ? "visible" : "excluded"); moreMenuButton.setMenu(moreMenu); }, diff --git a/services/static-webserver/client/source/class/osparc/store/Templates.js b/services/static-webserver/client/source/class/osparc/store/Templates.js index 5c47dcdc4a9b..d18425e30ee9 100644 --- a/services/static-webserver/client/source/class/osparc/store/Templates.js +++ b/services/static-webserver/client/source/class/osparc/store/Templates.js @@ -48,6 +48,10 @@ qx.Class.define("osparc.store.Templates", { return this.__templates; }, + getTemplatesByType: function(type) { + return this.__templates.filter(t => osparc.study.Utils.extractTemplateType(t) === type); + }, + getTemplate: function(templateId) { return this.__templates.find(t => t.uuid === templateId); }, From df4466e0a6f470234c3ff35505df0e100c759d91 Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Thu, 17 Apr 2025 14:15:22 +0200 Subject: [PATCH 14/16] minor --- .../client/source/class/osparc/dashboard/NewPlusMenu.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/services/static-webserver/client/source/class/osparc/dashboard/NewPlusMenu.js b/services/static-webserver/client/source/class/osparc/dashboard/NewPlusMenu.js index 7bba3f305fad..ac4a054789e1 100644 --- a/services/static-webserver/client/source/class/osparc/dashboard/NewPlusMenu.js +++ b/services/static-webserver/client/source/class/osparc/dashboard/NewPlusMenu.js @@ -160,7 +160,9 @@ qx.Class.define("osparc.dashboard.NewPlusMenu", { __addItems: function() { this.__addUIConfigItems(); - this.__addOtherTabsAccess(); + if (osparc.store.StaticInfo.getInstance().isDevFeaturesEnabled()) { + this.__addOtherTabsAccess(); + } this.getChildControl("new-folder"); }, From b8fc8c0cea9ae31f1691d8d6229e32e7ef4a2cc8 Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Thu, 17 Apr 2025 14:22:17 +0200 Subject: [PATCH 15/16] minor --- .../client/source/class/osparc/study/Utils.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/services/static-webserver/client/source/class/osparc/study/Utils.js b/services/static-webserver/client/source/class/osparc/study/Utils.js index 6b883c5c20bf..8f1dad69d406 100644 --- a/services/static-webserver/client/source/class/osparc/study/Utils.js +++ b/services/static-webserver/client/source/class/osparc/study/Utils.js @@ -389,10 +389,8 @@ qx.Class.define("osparc.study.Utils", { } resolve(defaultIcon); }); - } else if (wbServices.length > 1) { - resolve("osparc/icons/diagram.png"); } else { - resolve(defaultIcon); + resolve("osparc/icons/diagram.png"); } } }); From 9a2aad88a426b6809738a40aa8b7012ed3dab660 Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Thu, 17 Apr 2025 14:26:34 +0200 Subject: [PATCH 16/16] cleanup --- .../client/source/class/osparc/desktop/MainPage.js | 5 ----- .../client/source/class/osparc/store/Templates.js | 4 ---- 2 files changed, 9 deletions(-) diff --git a/services/static-webserver/client/source/class/osparc/desktop/MainPage.js b/services/static-webserver/client/source/class/osparc/desktop/MainPage.js index 6632701f6a8d..3b4677d25e9d 100644 --- a/services/static-webserver/client/source/class/osparc/desktop/MainPage.js +++ b/services/static-webserver/client/source/class/osparc/desktop/MainPage.js @@ -157,11 +157,6 @@ qx.Class.define("osparc.desktop.MainPage", { } this.closeEditor(); this.__showDashboard(); - // reset templates - // OM is this needed? - // this.__dashboard.getTemplateBrowser().invalidateTemplates(); - osparc.store.Templates.getInstance().invalidateTemplates(); - this.__dashboard.getTemplateBrowser().reloadResources(); // reset studies this.__dashboard.getStudyBrowser().invalidateStudies(); this.__dashboard.getStudyBrowser().reloadResources(); diff --git a/services/static-webserver/client/source/class/osparc/store/Templates.js b/services/static-webserver/client/source/class/osparc/store/Templates.js index d18425e30ee9..cc6749a07c50 100644 --- a/services/static-webserver/client/source/class/osparc/store/Templates.js +++ b/services/static-webserver/client/source/class/osparc/store/Templates.js @@ -40,10 +40,6 @@ qx.Class.define("osparc.store.Templates", { }); }, - invalidateTemplates: function() { - this.__templates = []; - }, - getTemplates: function() { return this.__templates; },