diff --git a/services/static-webserver/client/source/class/osparc/dashboard/CardBase.js b/services/static-webserver/client/source/class/osparc/dashboard/CardBase.js index 189c437192d..9a561af4ab0 100644 --- a/services/static-webserver/client/source/class/osparc/dashboard/CardBase.js +++ b/services/static-webserver/client/source/class/osparc/dashboard/CardBase.js @@ -526,12 +526,13 @@ qx.Class.define("osparc.dashboard.CardBase", { }); if (resourceData["resourceType"] === "study" || resourceData["resourceType"] === "template") { - osparc.store.Services.getStudyServices(this.getResourceData()["uuid"]) + osparc.store.Services.getStudyServices(resourceData.uuid) .then(resp => { const services = resp["services"]; resourceData["services"] = services; this.setServices(services); - }); + }) + .catch(err => console.error(err)); osparc.study.Utils.guessIcon(resourceData) .then(iconSource => this.setIcon(iconSource)); @@ -664,14 +665,21 @@ qx.Class.define("osparc.dashboard.CardBase", { } // Block card - const unaccessibleServices = osparc.study.Utils.getCantExecuteServices(services); - if (unaccessibleServices.length) { + const cantReadServices = osparc.study.Utils.getCantExecuteServices(services); + let inaccessibleServices = []; + if (this.isResourceType("study") || this.isResourceType("template")) { + inaccessibleServices = osparc.store.Services.getInaccessibleServices(this.getResourceData()["workbench"]); + } + if (cantReadServices.length || inaccessibleServices.length) { this.setBlocked("UNKNOWN_SERVICES"); const image = "@FontAwesome5Solid/ban/"; - let toolTipText = this.tr("Unaccessible service(s):"); - unaccessibleServices.forEach(unSrv => { + let toolTipText = this.tr("Inaccessible service(s):"); + cantReadServices.forEach(unSrv => { toolTipText += "
" + unSrv.key + ":" + osparc.service.Utils.extractVersionDisplay(unSrv.release); }); + inaccessibleServices.forEach(unSrv => { + toolTipText += "
" + unSrv.key + ":" + unSrv.version; + }); this.__showBlockedCard(image, toolTipText); } diff --git a/services/static-webserver/client/source/class/osparc/dashboard/ResourceDetails.js b/services/static-webserver/client/source/class/osparc/dashboard/ResourceDetails.js index 2ebc0ae4249..6d671f57554 100644 --- a/services/static-webserver/client/source/class/osparc/dashboard/ResourceDetails.js +++ b/services/static-webserver/client/source/class/osparc/dashboard/ResourceDetails.js @@ -49,9 +49,10 @@ qx.Class.define("osparc.dashboard.ResourceDetails", { case "study": case "template": { osparc.store.Services.getStudyServicesMetadata(latestResourceData) - .then(() => { + .finally(() => { this.__resourceModel = new osparc.data.model.Study(latestResourceData); this.__resourceModel["resourceType"] = resourceData["resourceType"]; + this.__resourceData["services"] = resourceData["services"]; this.__addPages(); }) break; diff --git a/services/static-webserver/client/source/class/osparc/data/model/Workbench.js b/services/static-webserver/client/source/class/osparc/data/model/Workbench.js index 55c64406cd4..02917b2730e 100644 --- a/services/static-webserver/client/source/class/osparc/data/model/Workbench.js +++ b/services/static-webserver/client/source/class/osparc/data/model/Workbench.js @@ -272,12 +272,12 @@ qx.Class.define("osparc.data.model.Workbench", { }, __createNode: function(study, metadata, uuid) { - osparc.utils.Utils.localCache.serviceToFavs(metadata.key); const node = new osparc.data.model.Node(study, metadata, uuid); node.addListener("keyChanged", () => this.fireEvent("reloadModel"), this); node.addListener("changeInputNodes", () => this.fireDataEvent("pipelineChanged"), this); node.addListener("reloadModel", () => this.fireEvent("reloadModel"), this); node.addListener("updateStudyDocument", () => this.fireEvent("updateStudyDocument"), this); + osparc.utils.Utils.localCache.serviceToFavs(metadata.key); return node; }, @@ -685,15 +685,20 @@ qx.Class.define("osparc.data.model.Workbench", { __deserializeNodes: function(workbenchData, workbenchUIData = {}) { const nodeIds = Object.keys(workbenchData); - - const metadataPromises = []; + const serviceMetadataPromises = []; nodeIds.forEach(nodeId => { const nodeData = workbenchData[nodeId]; - metadataPromises.push(osparc.store.Services.getService(nodeData.key, nodeData.version)); + serviceMetadataPromises.push(osparc.store.Services.getService(nodeData.key, nodeData.version)); }); - - return Promise.all(metadataPromises) - .then(values => { + return Promise.allSettled(serviceMetadataPromises) + .then(results => { + const missing = results.filter(result => result.status === "rejected" || result.value === null) + if (missing.length) { + const errorMsg = qx.locale.Manager.tr("Service metadata missing"); + osparc.FlashMessenger.logError(errorMsg); + return; + } + const values = results.map(result => result.value); // Create first all the nodes for (let i=0; i${qx.locale.Manager.tr("Please contact support.")}`; throw new Error(msg); } @@ -113,10 +113,10 @@ qx.Class.define("osparc.desktop.MainPageHandler", { osparc.store.Services.getStudyServicesMetadata(studyData) .finally(() => { - const inaccessibleServices = osparc.store.Services.getInaccessibleServices(studyData["workbench"]) + const inaccessibleServices = osparc.store.Services.getInaccessibleServices(studyData["workbench"]); if (inaccessibleServices.length) { const msg = osparc.store.Services.getInaccessibleServicesMsg(inaccessibleServices, studyData["workbench"]); - osparc.FlashMessenger.getInstance().logError(msg); + osparc.FlashMessenger.logError(msg); this.showDashboard(); return; } diff --git a/services/static-webserver/client/source/class/osparc/store/Services.js b/services/static-webserver/client/source/class/osparc/store/Services.js index 8f1e390a8cf..0c06a7775a0 100644 --- a/services/static-webserver/client/source/class/osparc/store/Services.js +++ b/services/static-webserver/client/source/class/osparc/store/Services.js @@ -40,7 +40,7 @@ qx.Class.define("osparc.store.Services", { this.__addExtraTypeInfos(servicesObj); Object.values(servicesObj).forEach(serviceKey => { - Object.values(serviceKey).forEach(service => this.__addToCache(service)); + Object.values(serviceKey).forEach(service => this.__addServiceToCache(service)); }); resolve(servicesObj); @@ -110,7 +110,10 @@ qx.Class.define("osparc.store.Services", { if ( useCache && this.__isInCache(key, version) && - "history" in this.__servicesCached[key][version] + ( + this.__servicesCached[key][version] === null || + "history" in this.__servicesCached[key][version] + ) ) { resolve(this.__servicesCached[key][version]); return; @@ -127,17 +130,16 @@ qx.Class.define("osparc.store.Services", { this.__addHit(service); this.__addTSRInfo(service); this.__addExtraTypeInfo(service); - this.__addToCache(service) + this.__addServiceToCache(service); + delete this.__servicesPromisesCached[key][version]; resolve(service); }) .catch(err => { // store it in cache to avoid asking again - this.__servicesCached[key][version] = null; + this.__addToCache(key, version, null); + delete this.__servicesPromisesCached[key][version]; console.error(err); reject(); - }) - .finally(() => { - delete this.__servicesPromisesCached[key][version]; }); }); }, @@ -282,23 +284,27 @@ qx.Class.define("osparc.store.Services", { wbServices.forEach(srv => { promises.push(this.getService(srv["key"], srv["version"])); }); - return Promise.all(promises); + return Promise.allSettled(promises); }, getInaccessibleServices: function(workbench) { const allServices = this.__servicesCached; - const unaccessibleServices = []; + const inaccessibleServices = []; const wbServices = osparc.study.Utils.extractUniqueServices(workbench); wbServices.forEach(srv => { - if (srv.key in allServices && srv.version in allServices[srv.key]) { + if ( + srv.key in allServices && + srv.version in allServices[srv.key] && + allServices[srv.key][srv.version] // check metadata is not null + ) { return; } - const idx = unaccessibleServices.findIndex(unSrv => unSrv.key === srv.key && unSrv.version === srv.version); + const idx = inaccessibleServices.findIndex(unSrv => unSrv.key === srv.key && unSrv.version === srv.version); if (idx === -1) { - unaccessibleServices.push(srv); + inaccessibleServices.push(srv); } }); - return unaccessibleServices; + return inaccessibleServices; }, getInaccessibleServicesMsg: function(inaccessibleServices, workbench) { @@ -340,13 +346,17 @@ qx.Class.define("osparc.store.Services", { return this.getLatest("simcore/services/frontend/iterator-consumer/probe/"+type); }, - __addToCache: function(service) { + __addServiceToCache: function(service) { const key = service.key; const version = service.version; + this.__addToCache(key, version, service); + }, + + __addToCache: function(key, version, value) { if (!(key in this.__servicesCached)) { this.__servicesCached[key] = {}; } - this.__servicesCached[key][version] = service; + this.__servicesCached[key][version] = value; }, __isInCache: function(key, version) { diff --git a/services/static-webserver/client/source/class/osparc/store/Store.js b/services/static-webserver/client/source/class/osparc/store/Store.js index 81a1c4e9dcd..627eb89f584 100644 --- a/services/static-webserver/client/source/class/osparc/store/Store.js +++ b/services/static-webserver/client/source/class/osparc/store/Store.js @@ -226,6 +226,14 @@ qx.Class.define("osparc.store.Store", { check: "Array", init: [] }, + organizationMembers: { + check: "Array", + init: null, + }, + notifications: { + check: "Array", + init: null, + }, }, events: { 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 e04e452ceb3..faf17ed124d 100644 --- a/services/static-webserver/client/source/class/osparc/study/Utils.js +++ b/services/static-webserver/client/source/class/osparc/study/Utils.js @@ -23,17 +23,13 @@ qx.Class.define("osparc.study.Utils", { type: "static", statics: { - __isAnyLinkedNodeMissing: function(studyData) { + isAnyLinkedNodeMissing: function(studyData) { const existingNodeIds = Object.keys(studyData["workbench"]); const linkedNodeIds = osparc.data.model.Workbench.getLinkedNodeIds(studyData["workbench"]); const allExist = linkedNodeIds.every(linkedNodeId => existingNodeIds.includes(linkedNodeId)); return !allExist; }, - isCorrupt: function(studyData) { - return this.__isAnyLinkedNodeMissing(studyData); - }, - extractUniqueServices: function(workbench) { const services = new Set([]); Object.values(workbench).forEach(srv => { @@ -274,8 +270,9 @@ qx.Class.define("osparc.study.Utils", { __getBlockedState: function(studyData) { if (studyData["services"]) { - const unaccessibleServices = osparc.study.Utils.getCantExecuteServices(studyData["services"]) - if (unaccessibleServices.length) { + const cantReadServices = osparc.study.Utils.getCantExecuteServices(studyData["services"]); + const inaccessibleServices = osparc.store.Services.getInaccessibleServices(studyData["workbench"]); + if (cantReadServices.length || inaccessibleServices.length) { return "UNKNOWN_SERVICES"; } } @@ -358,7 +355,7 @@ qx.Class.define("osparc.study.Utils", { const wbService = wbServices[0]; osparc.store.Services.getService(wbService.key, wbService.version) .then(serviceMetadata => { - if (serviceMetadata["icon"]) { + if (serviceMetadata && serviceMetadata["icon"]) { resolve(serviceMetadata["icon"]); } resolve(defaultIcon);