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 fe9f48b49578..63b9566d3540 100644 --- a/services/static-webserver/client/source/class/osparc/dashboard/Dashboard.js +++ b/services/static-webserver/client/source/class/osparc/dashboard/Dashboard.js @@ -123,14 +123,16 @@ qx.Class.define("osparc.dashboard.Dashboard", { icon: "@FontAwesome5Solid/copy/"+tabIconSize, buildLayout: this.__createTemplateBrowser }); - tabs.push({ - id: "hypertoolsTab", - buttonId: "hypertoolsTabBtn", - label: this.tr("HYPERTOOLS"), - icon: "@FontAwesome5Solid/copy/"+tabIconSize, - initVisibility: "excluded", - buildLayout: this.__createHypertoolsBrowser - }); + if (osparc.product.Utils.isS4LProduct() && osparc.store.StaticInfo.getInstance().isDevFeaturesEnabled()) { + tabs.push({ + id: "hypertoolsTab", + buttonId: "hypertoolsTabBtn", + label: this.tr("HYPERTOOLS"), + icon: "@FontAwesome5Solid/copy/"+tabIconSize, + // initVisibility: "excluded", + buildLayout: this.__createHypertoolsBrowser + }); + } } if (permissions.canDo("dashboard.services.read")) { tabs.push({ @@ -172,26 +174,25 @@ qx.Class.define("osparc.dashboard.Dashboard", { osparc.utils.Utils.setIdToWidget(tabButton, buttonId); tabPage.setLayout(new qx.ui.layout.Grow()); - const viewLayout = buildLayout.call(this); + const resourceBrowser = buildLayout.call(this); tabButton.addListener("execute", () => { - if (viewLayout.resetSelection) { - viewLayout.resetSelection(); + if (resourceBrowser.resetSelection) { + resourceBrowser.resetSelection(); } }, this); - viewLayout.addListener("changeTab", e => { + + resourceBrowser.addListener("changeTab", e => { const activeTab = e.getData(); const tabFound = this.getSelectables().find(s => s.id === activeTab); if (tabFound) { this.setSelection([tabFound]); } }, this); - viewLayout.addListener("showTab", e => { - const showTab = e.getData(); - tabButton.setVisibility(showTab ? "visible" : "excluded"); - }) + const scrollerMainView = new qx.ui.container.Scroll(); - scrollerMainView.add(viewLayout); + scrollerMainView.add(resourceBrowser); tabPage.add(scrollerMainView); + tabPage.resourceBrowser = resourceBrowser; this.add(tabPage); }, this); @@ -200,20 +201,24 @@ 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(() => { - [ - this.__studyBrowser, - this.__templateBrowser, - this.__hypertoolBrowser, - this.__serviceBrowser, - this.__dataBrowser - ].forEach(resourceBrowser => { - if (resourceBrowser) { - resourceBrowser.initResources(); + if (this.__studyBrowser) { + this.__studyBrowser.initResources(); + } + if (this.__serviceBrowser) { + this.__serviceBrowser.initResources(); + } + if (this.__dataBrowser) { + this.__dataBrowser.initResources(); + } + + this.addListener("changeSelection", e => { + const selectedTab = e.getData()[0]; + if (selectedTab && selectedTab.resourceBrowser) { + selectedTab.resourceBrowser.initResources(); } - }); + }, this); }) .catch(err => console.error(err)); }, diff --git a/services/static-webserver/client/source/class/osparc/dashboard/DataBrowser.js b/services/static-webserver/client/source/class/osparc/dashboard/DataBrowser.js index 710e2d35d29d..f109994119c2 100644 --- a/services/static-webserver/client/source/class/osparc/dashboard/DataBrowser.js +++ b/services/static-webserver/client/source/class/osparc/dashboard/DataBrowser.js @@ -55,6 +55,11 @@ qx.Class.define("osparc.dashboard.DataBrowser", { // overridden initResources: function() { + if (this._resourcesInitialized) { + return; + } + this._resourcesInitialized = true; + this._hideLoadingPage(); this.__buildLayout(); 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 401ce83446b8..3e4592eac750 100644 --- a/services/static-webserver/client/source/class/osparc/dashboard/NewPlusMenu.js +++ b/services/static-webserver/client/source/class/osparc/dashboard/NewPlusMenu.js @@ -172,7 +172,6 @@ qx.Class.define("osparc.dashboard.NewPlusMenu", { __addUIConfigItems: function() { const plusButtonConfig = osparc.store.Products.getInstance().getPlusButtonUiConfig(); if (plusButtonConfig) { - const templates = osparc.store.Templates.getInstance().getTemplates() if (plusButtonConfig["categories"]) { this.__addCategories(plusButtonConfig["categories"]); } @@ -182,7 +181,7 @@ qx.Class.define("osparc.dashboard.NewPlusMenu", { } else if (buttonConfig["resourceType"] === "study") { this.__addEmptyStudyButton(buttonConfig); } else if (buttonConfig["resourceType"] === "template") { - this.__addFromTemplateButton(buttonConfig, templates); + this.__addFromTemplateButton(buttonConfig); } else if (buttonConfig["resourceType"] === "service") { this.__addFromServiceButton(buttonConfig); } @@ -191,28 +190,30 @@ qx.Class.define("osparc.dashboard.NewPlusMenu", { }, __addHypertools: function() { - const hypertools = osparc.store.Templates.getInstance().getTemplatesByType(osparc.data.model.StudyUI.HYPERTOOL_TYPE); - if (hypertools.length) { - const hypertoolsMenuButton = this.self().createMenuButton("@FontAwesome5Solid/star/16", this.tr("Hypertools")); - this.addAt(hypertoolsMenuButton, this.__itemIdx); - this.__itemIdx++; - - const hypertoolsMenu = new qx.ui.menu.Menu().set({ - appearance: "menu-wider", - }); - hypertoolsMenuButton.setMenu(hypertoolsMenu); - - hypertools.forEach(templateData => { - const hypertoolButton = this.self().createMenuButton(templateData["icon"], templateData["name"]); - hypertoolButton.addListener("tap", () => { - this.fireDataEvent("newStudyFromTemplateClicked", { - templateData, - newStudyLabel: templateData["name"], + osparc.store.Templates.getTemplatesHypertools() + .then(hypertools => { + if (hypertools.length) { + const hypertoolsMenuButton = this.self().createMenuButton("@FontAwesome5Solid/star/16", this.tr("Hypertools")); + this.addAt(hypertoolsMenuButton, this.__itemIdx); + this.__itemIdx++; + + const hypertoolsMenu = new qx.ui.menu.Menu().set({ + appearance: "menu-wider", }); - }); - hypertoolsMenu.add(hypertoolButton); + hypertoolsMenuButton.setMenu(hypertoolsMenu); + + hypertools.forEach(templateData => { + const hypertoolButton = this.self().createMenuButton(templateData["icon"], templateData["name"]); + hypertoolButton.addListener("tap", () => { + this.fireDataEvent("newStudyFromTemplateClicked", { + templateData, + newStudyLabel: templateData["name"], + }); + }); + hypertoolsMenu.add(hypertoolButton); + }); + } }); - } }, __addOtherTabsAccess: function() { @@ -321,24 +322,27 @@ qx.Class.define("osparc.dashboard.NewPlusMenu", { this.__addFromResourceButton(menuButton, buttonConfig["category"]); }, - __addFromTemplateButton: function(buttonConfig, templates) { - const menuButton = this.self().createMenuButton(null, buttonConfig["title"]); - osparc.utils.Utils.setIdToWidget(menuButton, buttonConfig["idToWidget"]); - // disable it until found in templates store - menuButton.setEnabled(false); - - let templateMetadata = templates.find(t => t.name === buttonConfig["expectedTemplateLabel"]); - if (templateMetadata) { - menuButton.setEnabled(true); - menuButton.addListener("tap", () => { - this.fireDataEvent("newStudyFromTemplateClicked", { - templateData: templateMetadata, - newStudyLabel: buttonConfig["newStudyLabel"], - }); + __addFromTemplateButton: function(buttonConfig) { + osparc.store.Templates.getTemplates() + .then(templates => { + const menuButton = this.self().createMenuButton(null, buttonConfig["title"]); + osparc.utils.Utils.setIdToWidget(menuButton, buttonConfig["idToWidget"]); + // disable it until found in templates store + menuButton.setEnabled(false); + + let templateMetadata = templates.find(t => t.name === buttonConfig["expectedTemplateLabel"]); + if (templateMetadata) { + menuButton.setEnabled(true); + menuButton.addListener("tap", () => { + this.fireDataEvent("newStudyFromTemplateClicked", { + templateData: templateMetadata, + newStudyLabel: buttonConfig["newStudyLabel"], + }); + }); + this.__addIcon(menuButton, buttonConfig["icon"], templateMetadata); + this.__addFromResourceButton(menuButton, buttonConfig["category"]); + } }); - this.__addIcon(menuButton, buttonConfig["icon"], templateMetadata); - this.__addFromResourceButton(menuButton, buttonConfig["category"]); - } }, __addFromServiceButton: function(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 0161fce39f7f..1f25797bdb44 100644 --- a/services/static-webserver/client/source/class/osparc/dashboard/NewStudies.js +++ b/services/static-webserver/client/source/class/osparc/dashboard/NewStudies.js @@ -36,13 +36,17 @@ qx.Class.define("osparc.dashboard.NewStudies", { }); this._add(this.__flatList); - 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); - }); + osparc.store.Templates.getTemplates() + .then(templates => { + this.__newStudies = newButtonsInfo.filter(newButtonInfo => { + if (newButtonInfo.showDisabled) { + return true; + } + return templates.find(t => t.name === newButtonInfo.expectedTemplateLabel); + }); + + this.setGroupBy("category"); + }); }, properties: { diff --git a/services/static-webserver/client/source/class/osparc/dashboard/ResourceBrowserBase.js b/services/static-webserver/client/source/class/osparc/dashboard/ResourceBrowserBase.js index 11a37a8a30d7..d244902d3511 100644 --- a/services/static-webserver/client/source/class/osparc/dashboard/ResourceBrowserBase.js +++ b/services/static-webserver/client/source/class/osparc/dashboard/ResourceBrowserBase.js @@ -31,6 +31,8 @@ qx.Class.define("osparc.dashboard.ResourceBrowserBase", { construct: function() { this.base(arguments); + this._resourcesInitialized = false; + this._showLoadingPage(this.tr("Starting") + " " + osparc.store.StaticInfo.getInstance().getDisplayName()); const padding = osparc.dashboard.Dashboard.PADDING; @@ -88,7 +90,6 @@ qx.Class.define("osparc.dashboard.ResourceBrowserBase", { events: { "changeTab": "qx.event.type.Data", - "showTab": "qx.event.type.Data", "publishTemplate": "qx.event.type.Data", }, @@ -210,6 +211,7 @@ qx.Class.define("osparc.dashboard.ResourceBrowserBase", { __centerLayout: null, _resourceType: null, _resourcesList: null, + _resourcesInitialized: null, _toolbar: null, _searchBarFilter: null, __viewModeLayout: null, diff --git a/services/static-webserver/client/source/class/osparc/dashboard/ServiceBrowser.js b/services/static-webserver/client/source/class/osparc/dashboard/ServiceBrowser.js index 199fdc0d8d18..50305eb14085 100644 --- a/services/static-webserver/client/source/class/osparc/dashboard/ServiceBrowser.js +++ b/services/static-webserver/client/source/class/osparc/dashboard/ServiceBrowser.js @@ -37,6 +37,11 @@ qx.Class.define("osparc.dashboard.ServiceBrowser", { // overridden initResources: function() { + if (this._resourcesInitialized) { + return; + } + this._resourcesInitialized = true; + this._resourcesList = []; osparc.store.Services.getServicesLatest() .then(services => { 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 16013177925e..27d9e6ec4112 100644 --- a/services/static-webserver/client/source/class/osparc/dashboard/StudyBrowser.js +++ b/services/static-webserver/client/source/class/osparc/dashboard/StudyBrowser.js @@ -92,6 +92,11 @@ qx.Class.define("osparc.dashboard.StudyBrowser", { // overridden initResources: function() { + if (this._resourcesInitialized) { + return; + } + this._resourcesInitialized = true; + this._resourcesList = []; this.__getActiveStudy() .then(() => { @@ -907,25 +912,26 @@ qx.Class.define("osparc.dashboard.StudyBrowser", { newPlansBtn.setEnabled(true); newPlansBtn.addListener("tap", () => { - const templates = osparc.store.Templates.getInstance().getTemplates(); - if (templates) { - const newStudies = new osparc.dashboard.NewStudies(newStudiesConfig); - 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.store.Templates.getTemplates() + .then(templates => { + if (templates) { + const newStudies = new osparc.dashboard.NewStudies(newStudiesConfig); + 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"); } }); - osparc.utils.Utils.setIdToWidget(win, "newStudiesWindow"); - } }); } }, 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 eb9886e4bb9a..483fa3fa4cc1 100644 --- a/services/static-webserver/client/source/class/osparc/dashboard/TemplateBrowser.js +++ b/services/static-webserver/client/source/class/osparc/dashboard/TemplateBrowser.js @@ -31,11 +31,19 @@ qx.Class.define("osparc.dashboard.TemplateBrowser", { // overridden initResources: function() { - this._resourcesList = []; - this.getChildControl("resources-layout"); - this.reloadResources(); - this.__attachEventHandlers(); - this._hideLoadingPage(); + if (this._resourcesInitialized) { + return; + } + this._resourcesInitialized = true; + + osparc.store.Templates.getTemplates() + .then(() => { + this._resourcesList = []; + this.getChildControl("resources-layout"); + this.reloadResources(); + this.__attachEventHandlers(); + this._hideLoadingPage(); + }); }, reloadResources: function(useCache = true) { @@ -76,17 +84,13 @@ qx.Class.define("osparc.dashboard.TemplateBrowser", { __reloadTemplates: function(useCache) { this.__tasksToCards(); - const templatesStore = osparc.store.Templates.getInstance(); if (useCache) { - const templates = templatesStore.getTemplates(); - this.__setResourcesToList(templates); + osparc.store.Templates.getTemplates() + .then(templates => this.__setResourcesToList(templates)); } else { - templatesStore.fetchAllTemplates() + osparc.store.Templates.getTemplates(useCache) .then(templates => this.__setResourcesToList(templates)) - .catch(err => { - console.error(err); - this.__setResourcesToList([]); - }); + .catch(() => this.__setResourcesToList([])); } }, @@ -103,7 +107,6 @@ qx.Class.define("osparc.dashboard.TemplateBrowser", { __setResourcesToList: function(templatesList) { templatesList.forEach(template => template["resourceType"] = "template"); this._resourcesList = templatesList.filter(template => osparc.study.Utils.extractTemplateType(template) === this.__templateType); - this.fireDataEvent("showTab", Boolean(this._resourcesList.length)); this._reloadCards(); }, 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 b66b89784951..25a06cc579ef 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,14 +86,16 @@ qx.Class.define("osparc.desktop.organizations.TemplatesList", { item.subscribeToFilterGroup("organizationTemplatesList"); item.addListener("openMoreInfo", e => { const templateId = e.getData()["key"]; - const templateData = osparc.store.Templates.getInstance().getTemplate(templateId); - if (templateData) { - templateData["resourceType"] = "template"; - const resourceDetails = new osparc.dashboard.ResourceDetails(templateData).set({ - showOpenButton: false + osparc.store.Templates.getTemplate(templateId) + .then(templateData => { + if (templateData) { + templateData["resourceType"] = "template"; + const resourceDetails = new osparc.dashboard.ResourceDetails(templateData).set({ + showOpenButton: false + }); + osparc.dashboard.ResourceDetails.popUpInWindow(resourceDetails); + } }); - osparc.dashboard.ResourceDetails.popUpInWindow(resourceDetails); - } }); } }); @@ -110,14 +112,16 @@ qx.Class.define("osparc.desktop.organizations.TemplatesList", { return; } - const groupId = orgModel.getGroupId(); - 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)); - }); + osparc.store.Templates.getTemplates() + .then(templates => { + const groupId = orgModel.getGroupId(); + 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 cc6749a07c50..6a0a2483849e 100644 --- a/services/static-webserver/client/source/class/osparc/store/Templates.js +++ b/services/static-webserver/client/source/class/osparc/store/Templates.js @@ -16,40 +16,57 @@ ************************************************************************ */ qx.Class.define("osparc.store.Templates", { - extend: qx.core.Object, - type: "singleton", + type: "static", - construct: function() { - this.base(arguments); - - this.__templates = []; - }, - - members: { + statics: { __templates: null, + __templatesPromisesCached: null, - fetchAllTemplates: function() { - if (this.__templates.length) { - return new Promise(resolve => resolve(this.__templates)); - } - - return osparc.data.Resources.getInstance().getAllPages("templates") + __fetchAllTemplates: function() { + return this.__templatesPromisesCached = osparc.data.Resources.getInstance().getAllPages("templates") .then(templates => { this.__templates = templates; return templates; + }) + .catch(err => { + osparc.FlashMessenger.logError(err); + }) + .finally(() => { + this.__templatesPromisesCached = null; }); }, - getTemplates: function() { - return this.__templates; + getTemplates: function(useCache = true) { + if (this.__templatesPromisesCached) { + // fetching templates already in progress + return this.__templatesPromisesCached; + } + + if (this.__templates === null) { + // no templates cached, fetch them + return this.__fetchAllTemplates(); + } + + if (useCache) { + // templates already cached, return them + return new Promise(resolve => resolve(this.__templates)); + } + // templates cached but force a refresh + return this.__fetchAllTemplates(); }, - getTemplatesByType: function(type) { - return this.__templates.filter(t => osparc.study.Utils.extractTemplateType(t) === type); + getTemplatesHypertools: function() { + return this.getTemplates() + .then(templates => { + return templates.filter(t => osparc.study.Utils.extractTemplateType(t) === osparc.data.model.StudyUI.HYPERTOOL_TYPE); + }); }, getTemplate: function(templateId) { - return this.__templates.find(t => t.uuid === templateId); + return this.getTemplates() + .then(templates => { + return templates.find(t => t.uuid === templateId); + }); }, } }); diff --git a/services/static-webserver/client/source/class/osparc/study/Conversations.js b/services/static-webserver/client/source/class/osparc/study/Conversations.js index 2b4238d0ab97..d43a945cf0cd 100644 --- a/services/static-webserver/client/source/class/osparc/study/Conversations.js +++ b/services/static-webserver/client/source/class/osparc/study/Conversations.js @@ -90,7 +90,7 @@ qx.Class.define("osparc.study.Conversations", { "type": "MESSAGE", } }; - osparc.data.Resources.fetch("conversations", "addMessage", params) + return osparc.data.Resources.fetch("conversations", "addMessage", params) .catch(err => osparc.FlashMessenger.logError(err)); }, }, diff --git a/tests/e2e/tests/startupCalls.js b/tests/e2e/tests/startupCalls.js index 78d080c1367c..ae4c642c8557 100644 --- a/tests/e2e/tests/startupCalls.js +++ b/tests/e2e/tests/startupCalls.js @@ -86,10 +86,13 @@ module.exports = { expect(Array.isArray(responseEnv.data)).toBeTruthy(); }, ourTimeout); + /* + // templates are lazy loaded test('Templates', async () => { const responseEnv = await responses.templates; expect(Array.isArray(responseEnv.data)).toBeTruthy(); }, ourTimeout); + */ test('Services', async () => { const responseEnv = await responses.services;