0) {
+ if (latestMetadata && latestMetadata["hits"] > 0) {
const menuButton = new qx.ui.menu.Button().set({
label: latestMetadata["name"],
font: "text-16",
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 2ad6467669a1..7de8c51a1179 100644
--- a/services/static-webserver/client/source/class/osparc/dashboard/ResourceBrowserBase.js
+++ b/services/static-webserver/client/source/class/osparc/dashboard/ResourceBrowserBase.js
@@ -555,7 +555,9 @@ qx.Class.define("osparc.dashboard.ResourceBrowserBase", {
},
_getOpenMenuButton: function(resourceData) {
- const openButton = new qx.ui.menu.Button(this.tr("Open"));
+ const studyAlias = osparc.product.Utils.getStudyAlias({firstUpperCase: true});
+ const openText = (resourceData["resourceType"] === "study") ? this.tr("Open") : this.tr("New") + " " + studyAlias;
+ const openButton = new qx.ui.menu.Button(openText);
openButton["openResourceButton"] = true;
openButton.addListener("execute", () => {
switch (resourceData["resourceType"]) {
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 9d0cb2d1d3cf..a0ecca56e4db 100644
--- a/services/static-webserver/client/source/class/osparc/dashboard/ResourceDetails.js
+++ b/services/static-webserver/client/source/class/osparc/dashboard/ResourceDetails.js
@@ -23,29 +23,57 @@ qx.Class.define("osparc.dashboard.ResourceDetails", {
this.__resourceData = resourceData;
- this.__resourceModel = null;
+ let latestPromise = null;
switch (resourceData["resourceType"]) {
case "study":
- case "template":
- this.__resourceModel = new osparc.data.model.Study(resourceData);
+ case "template": {
+ const params = {
+ url: {
+ "studyId": resourceData["uuid"]
+ }
+ };
+ latestPromise = osparc.data.Resources.fetch("studies", "getOne", params);
break;
- case "service":
- this.__resourceModel = new osparc.data.model.Service(resourceData);
+ }
+ case "service": {
+ latestPromise = osparc.store.Services.getService(resourceData["key"], resourceData["version"]);
break;
+ }
}
- this.__resourceModel["resourceType"] = resourceData["resourceType"];
- this.__addPages();
+ latestPromise
+ .then(latestResourceData => {
+ this.__resourceData = latestResourceData;
+ this.__resourceData["resourceType"] = resourceData["resourceType"];
+ switch (resourceData["resourceType"]) {
+ case "study":
+ case "template": {
+ osparc.store.Services.getStudyServicesMetadata(latestResourceData)
+ .then(() => {
+ this.__resourceModel = new osparc.data.model.Study(latestResourceData);
+ this.__resourceModel["resourceType"] = resourceData["resourceType"];
+ this.__addPages();
+ })
+ break;
+ }
+ case "service": {
+ this.__resourceModel = new osparc.data.model.Service(latestResourceData);
+ this.__resourceModel["resourceType"] = resourceData["resourceType"];
+ this.__addPages();
+ break;
+ }
+ }
+ });
},
events: {
- "openStudy": "qx.event.type.Data",
+ "pagesAdded": "qx.event.type.Event",
"openTemplate": "qx.event.type.Data",
"openService": "qx.event.type.Data",
"updateStudy": "qx.event.type.Data",
"updateTemplate": "qx.event.type.Data",
"updateService": "qx.event.type.Data",
- "publishTemplate": "qx.event.type.Data"
+ "publishTemplate": "qx.event.type.Data",
},
@@ -163,10 +191,15 @@ qx.Class.define("osparc.dashboard.ResourceDetails", {
"studyId": this.__resourceData["uuid"]
}
};
- osparc.data.Resources.getOne("studies", params)
- .then(updatedStudyData => {
+ Promise.all([
+ osparc.data.Resources.fetch("studies", "getOne", params),
+ osparc.data.Resources.fetch("studies", "getServices", params)
+ ])
+ .then(values => {
+ const updatedStudyData = values[0];
+ const studyServices = values[1];
openButton.setFetching(false);
- const updatableServices = osparc.metadata.ServicesInStudyUpdate.updatableNodeIds(updatedStudyData.workbench);
+ const updatableServices = osparc.metadata.ServicesInStudyUpdate.updatableNodeIds(updatedStudyData.workbench, studyServices["services"]);
if (updatableServices.length && osparc.data.model.Study.canIWrite(updatedStudyData["accessRights"])) {
this.__confirmUpdate();
} else {
@@ -254,34 +287,31 @@ qx.Class.define("osparc.dashboard.ResourceDetails", {
hBox.add(versionsBox);
- const versions = osparc.service.Utils.getVersions(this.__resourceData["key"]);
- let selectedItem = null;
-
- // first setSelection
- versions.forEach(version => {
- selectedItem = osparc.service.Utils.versionToListItem(this.__resourceData["key"], version);
- versionsBox.add(selectedItem);
- if (this.__resourceData["version"] === version) {
- versionsBox.setSelection([selectedItem]);
- }
- });
- osparc.utils.Utils.growSelectBox(versionsBox, 200);
-
- // then listen to changes
- versionsBox.addListener("changeSelection", e => {
- const selection = e.getData();
- if (selection.length) {
- const serviceVersion = selection[0].version;
- if (serviceVersion !== this.__resourceData["version"]) {
- osparc.store.Services.getService(this.__resourceData["key"], serviceVersion)
- .then(serviceData => {
- serviceData["resourceType"] = "service";
- this.__resourceData = serviceData;
- this.__addPages();
- });
+ osparc.store.Services.populateVersionsSelectBox(this.__resourceData["key"], versionsBox)
+ .then(() => {
+ // first setSelection
+ const versionFound = versionsBox.getSelectables().find(selectable => selectable.version === this.__resourceData["version"]);
+ if (versionFound) {
+ versionsBox.setSelection([versionFound]);
}
- }
- }, this);
+ osparc.utils.Utils.growSelectBox(versionsBox, 200);
+
+ // then listen to changes
+ versionsBox.addListener("changeSelection", e => {
+ const selection = e.getData();
+ if (selection.length) {
+ const serviceVersion = selection[0].version;
+ if (serviceVersion !== this.__resourceData["version"]) {
+ osparc.store.Services.getService(this.__resourceData["key"], serviceVersion)
+ .then(serviceData => {
+ serviceData["resourceType"] = "service";
+ this.__resourceData = serviceData;
+ this.__addPages();
+ });
+ }
+ }
+ }, this);
+ });
return hBox;
},
@@ -346,6 +376,8 @@ qx.Class.define("osparc.dashboard.ResourceDetails", {
tabsView.setSelection([pageFound]);
}
}
+
+ this.fireEvent("pagesAdded");
},
__getInfoPage: function() {
@@ -448,7 +480,7 @@ qx.Class.define("osparc.dashboard.ResourceDetails", {
if (
osparc.utils.Resources.isService(resourceData) ||
!osparc.product.Utils.showStudyPreview() ||
- !osparc.study.Utils.getUiMode(resourceData) === "workbench"
+ !(osparc.study.Utils.getUiMode(resourceData) === "workbench")
) {
// there is no pipelining or don't show it
return 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 fec523a23413..eb80bd3b7e65 100644
--- a/services/static-webserver/client/source/class/osparc/dashboard/ServiceBrowser.js
+++ b/services/static-webserver/client/source/class/osparc/dashboard/ServiceBrowser.js
@@ -48,9 +48,24 @@ qx.Class.define("osparc.dashboard.ServiceBrowser", {
// overridden
initResources: function() {
this._resourcesList = [];
- this.getChildControl("resources-layout");
- this.reloadResources();
- this._hideLoadingPage();
+ osparc.store.Services.getServicesLatest(false)
+ .then(services => {
+ // Show "Contact Us" message if services.length === 0
+ // Most probably is a product-stranger user (it can also be that the catalog is down)
+ if (Object.keys(services).length === 0) {
+ let msg = this.tr("It seems you don't have access to this product.");
+ msg += "";
+ msg += this.tr("Please contact us:");
+ msg += "";
+ const supportEmail = osparc.store.VendorInfo.getInstance().getSupportEmail();
+ msg += supportEmail;
+ osparc.FlashMessenger.getInstance().logAs(msg, "WARNING");
+ }
+
+ this.getChildControl("resources-layout");
+ this.reloadResources();
+ this._hideLoadingPage();
+ });
},
reloadResources: function() {
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 9ada537f7509..6b2f783b6103 100644
--- a/services/static-webserver/client/source/class/osparc/dashboard/StudyBrowser.js
+++ b/services/static-webserver/client/source/class/osparc/dashboard/StudyBrowser.js
@@ -269,28 +269,6 @@ qx.Class.define("osparc.dashboard.StudyBrowser", {
}
});
- // Show "Contact Us" message if services.length === 0
- // Most probably is a product-stranger user (it can also be that the catalog is down)
- osparc.store.Services.getServicesLatest()
- .then(services => {
- if (Object.keys(services).length === 0) {
- const noAccessText = new qx.ui.basic.Label().set({
- selectable: true,
- rich: true,
- font: "text-18",
- paddingTop: 20
- });
- let msg = this.tr("It seems you don't have access to this product.");
- msg += "";
- msg += "";
- msg += this.tr("Please contact us:");
- msg += "";
- const supportEmail = osparc.store.VendorInfo.getInstance().getSupportEmail();
- noAccessText.setValue(msg + supportEmail);
- this._addToLayout(noAccessText);
- }
- });
-
this._loadingResourcesBtn.setFetching(true);
this._loadingResourcesBtn.setVisibility("visible");
this.__getNextStudiesRequest()
@@ -383,7 +361,7 @@ qx.Class.define("osparc.dashboard.StudyBrowser", {
studyId
}
};
- osparc.data.Resources.getOne("studies", params)
+ osparc.data.Resources.fetch("studies", "getOne", params)
.then(studyData => {
this.__studyStateReceived(study["uuid"], studyData["state"]);
});
@@ -975,30 +953,20 @@ qx.Class.define("osparc.dashboard.StudyBrowser", {
__addNewStudyFromServiceButton: function(newStudyData) {
if ("expectedKey" in newStudyData) {
const key = newStudyData["expectedKey"];
- // Include deprecated versions, they should all be updatable to a non deprecated version
- const versions = osparc.service.Utils.getVersions(key, false);
- if (versions.length && newStudyData) {
- // scale to latest compatible
- const latestVersion = versions[0];
- const latestCompatible = osparc.service.Utils.getLatestCompatible(key, latestVersion);
- osparc.store.Services.getService(latestCompatible["key"], latestCompatible["version"])
- .then(latestMetadata => {
- // make sure this one is not deprecated
- if (osparc.service.Utils.isDeprecated(latestMetadata)) {
- return;
- }
- const title = newStudyData.title + " " + osparc.service.Utils.extractVersionDisplay(latestMetadata);
- const desc = newStudyData.description;
- const mode = this._resourcesContainer.getMode();
- const newStudyFromServiceButton = (mode === "grid") ? new osparc.dashboard.GridButtonNew(title, desc) : new osparc.dashboard.ListButtonNew(title, desc);
- newStudyFromServiceButton.setCardKey("new-"+key);
- if (newStudyData["idToWidget"]) {
- osparc.utils.Utils.setIdToWidget(newStudyFromServiceButton, newStudyData["idToWidget"]);
- }
- newStudyFromServiceButton.addListener("tap", () => this.__newStudyFromServiceBtnClicked(latestMetadata["key"], latestMetadata["version"], newStudyData.newStudyLabel));
- this._resourcesContainer.addNonResourceCard(newStudyFromServiceButton);
- })
+ const latestMetadata = osparc.store.Services.getLatest(key);
+ if (!latestMetadata) {
+ return;
+ }
+ const title = newStudyData.title + " " + osparc.service.Utils.extractVersionDisplay(latestMetadata);
+ const desc = newStudyData.description;
+ const mode = this._resourcesContainer.getMode();
+ const newStudyFromServiceButton = (mode === "grid") ? new osparc.dashboard.GridButtonNew(title, desc) : new osparc.dashboard.ListButtonNew(title, desc);
+ newStudyFromServiceButton.setCardKey("new-"+key);
+ if (newStudyData["idToWidget"]) {
+ osparc.utils.Utils.setIdToWidget(newStudyFromServiceButton, newStudyData["idToWidget"]);
}
+ newStudyFromServiceButton.addListener("tap", () => this.__newStudyFromServiceBtnClicked(latestMetadata["key"], latestMetadata["version"], newStudyData.newStudyLabel));
+ this._resourcesContainer.addNonResourceCard(newStudyFromServiceButton);
} else if ("myMostUsed" in newStudyData) {
const excludeFrontend = true;
const excludeDeprecated = true
@@ -2079,7 +2047,7 @@ qx.Class.define("osparc.dashboard.StudyBrowser", {
"studyId": data["data"]["uuid"]
}
};
- osparc.data.Resources.getOne("studies", params)
+ osparc.data.Resources.fetch("studies", "getOne", params)
.then(studyData => this._updateStudyData(studyData))
.catch(err => {
console.error(err);
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 716fa31a2e84..0996efeb7bb9 100644
--- a/services/static-webserver/client/source/class/osparc/dashboard/TemplateBrowser.js
+++ b/services/static-webserver/client/source/class/osparc/dashboard/TemplateBrowser.js
@@ -326,7 +326,7 @@ qx.Class.define("osparc.dashboard.TemplateBrowser", {
const templatePromises = [];
for (const nodeId in studyData["workbench"]) {
const node = studyData["workbench"][nodeId];
- const latestCompatible = osparc.service.Utils.getLatestCompatible(node["key"], node["version"]);
+ const latestCompatible = osparc.store.Services.getLatestCompatible(node["key"], node["version"]);
if (latestCompatible && (node["key"] !== latestCompatible["key"] || node["version"] !== latestCompatible["version"])) {
const patchData = {};
if (node["key"] !== latestCompatible["key"]) {
@@ -390,7 +390,7 @@ qx.Class.define("osparc.dashboard.TemplateBrowser", {
return null;
}
- const editButton = new qx.ui.menu.Button(this.tr("Edit"));
+ const editButton = new qx.ui.menu.Button(this.tr("Open"));
editButton.addListener("execute", () => this.__editTemplate(templateData), this);
return editButton;
},
diff --git a/services/static-webserver/client/source/class/osparc/data/Resources.js b/services/static-webserver/client/source/class/osparc/data/Resources.js
index 8fcc7a4b005f..42ca4daf86f4 100644
--- a/services/static-webserver/client/source/class/osparc/data/Resources.js
+++ b/services/static-webserver/client/source/class/osparc/data/Resources.js
@@ -125,6 +125,10 @@ qx.Class.define("osparc.data.Resources", {
method: "GET",
url: statics.API + "/projects/{studyId}"
},
+ getServices: {
+ method: "GET",
+ url: statics.API + "/projects/{studyId}/nodes/-/services"
+ },
getActive: {
useCache: false,
method: "GET",
@@ -574,24 +578,20 @@ qx.Class.define("osparc.data.Resources", {
},
/*
- * SERVICES V2 (web-api >=0.42.0)
+ * SERVICES V2
*/
"servicesV2": {
useCache: false, // handled in osparc.store.Services
idField: ["key", "version"],
endpoints: {
- get: {
+ getOne: {
method: "GET",
- url: statics.API + "/catalog/services/-/latest"
+ url: statics.API + "/catalog/services/{key}/{version}"
},
getPage: {
method: "GET",
url: statics.API + "/catalog/services/-/latest?offset={offset}&limit={limit}"
},
- getOne: {
- method: "GET",
- url: statics.API + "/catalog/services/{key}/{version}"
- },
patch: {
method: "PATCH",
url: statics.API + "/catalog/services/{key}/{version}"
diff --git a/services/static-webserver/client/source/class/osparc/data/model/Node.js b/services/static-webserver/client/source/class/osparc/data/model/Node.js
index 1a0b2d8378d0..efbc869bdf90 100644
--- a/services/static-webserver/client/source/class/osparc/data/model/Node.js
+++ b/services/static-webserver/client/source/class/osparc/data/model/Node.js
@@ -480,13 +480,15 @@ qx.Class.define("osparc.data.model.Node", {
}
}
- this.__initLogger();
-
- this.initIframeHandler();
-
if (this.isParameter()) {
this.__initParameter();
}
+
+ if (osparc.store.Store.getInstance().getCurrentStudy()) {
+ // do not initialize the logger and iframe if the study isn't open
+ this.__initLogger();
+ this.initIframeHandler();
+ }
},
populateNodeUIData: function(nodeUIData) {
@@ -1205,7 +1207,7 @@ qx.Class.define("osparc.data.model.Node", {
if (!["int"].includes(type)) {
return;
}
- const newMetadata = osparc.service.Utils.getParameterMetadata("integer");
+ const newMetadata = osparc.store.Services.getParameterMetadata("integer");
if (newMetadata) {
const value = this.__getInputData()["linspace_start"];
const label = this.getLabel();
@@ -1222,7 +1224,7 @@ qx.Class.define("osparc.data.model.Node", {
if (!["int"].includes(type)) {
return;
}
- const metadata = osparc.service.Utils.getLatest("simcore/services/frontend/data-iterator/int-range")
+ const metadata = osparc.store.Services.getLatest("simcore/services/frontend/data-iterator/int-range")
if (metadata) {
const value = this.__getOutputData("out_1");
const label = this.getLabel();
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 d442cb03b63c..68006af83297 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
@@ -426,7 +426,7 @@ qx.Class.define("osparc.data.model.Workbench", {
},
__filePickerNodeRequested: async function(nodeId, portId, file) {
- const filePickerMetadata = osparc.service.Utils.getFilePicker();
+ const filePickerMetadata = osparc.store.Services.getFilePicker();
const filePicker = await this.createNode(filePickerMetadata["key"], filePickerMetadata["version"]);
if (filePicker === null) {
return;
@@ -469,7 +469,7 @@ qx.Class.define("osparc.data.model.Workbench", {
// create a new ParameterNode
const type = osparc.utils.Ports.getPortType(requesterNode.getMetaData()["inputs"], portId);
- const parameterMetadata = osparc.service.Utils.getParameterMetadata(type);
+ const parameterMetadata = osparc.store.Services.getParameterMetadata(type);
if (parameterMetadata) {
const parameterNode = await this.createNode(parameterMetadata["key"], parameterMetadata["version"]);
if (parameterNode === null) {
@@ -499,7 +499,7 @@ qx.Class.define("osparc.data.model.Workbench", {
// create a new ProbeNode
const requesterPortMD = requesterNode.getMetaData()["outputs"][portId];
const type = osparc.utils.Ports.getPortType(requesterNode.getMetaData()["outputs"], portId);
- const probeMetadata = osparc.service.Utils.getProbeMetadata(type);
+ const probeMetadata = osparc.store.Services.getProbeMetadata(type);
if (probeMetadata) {
const probeNode = await this.createNode(probeMetadata["key"], probeMetadata["version"]);
if (probeNode === null) {
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 1737f1b4bce7..b1cadb8fc9b4 100644
--- a/services/static-webserver/client/source/class/osparc/desktop/MainPage.js
+++ b/services/static-webserver/client/source/class/osparc/desktop/MainPage.js
@@ -308,7 +308,7 @@ qx.Class.define("osparc.desktop.MainPage", {
"studyId": studyId
}
};
- osparc.data.Resources.getOne("studies", params2)
+ osparc.data.Resources.fetch("studies", "getOne", params2)
.then(studyData => {
if (!studyData) {
const msg = this.tr("Study not found");
@@ -348,7 +348,7 @@ qx.Class.define("osparc.desktop.MainPage", {
}
};
// OM TODO. DO NOT ADD ITERATIONS TO STUDIES CACHE
- osparc.data.Resources.getOne("studies", params)
+ osparc.data.Resources.fetch("studies", "getOne", params)
.then(studyData => {
if (!studyData) {
const msg = this.tr("Iteration not found");
diff --git a/services/static-webserver/client/source/class/osparc/desktop/MainPageHandler.js b/services/static-webserver/client/source/class/osparc/desktop/MainPageHandler.js
index d03f9bc85e27..a8bf54dac246 100644
--- a/services/static-webserver/client/source/class/osparc/desktop/MainPageHandler.js
+++ b/services/static-webserver/client/source/class/osparc/desktop/MainPageHandler.js
@@ -69,7 +69,7 @@ qx.Class.define("osparc.desktop.MainPageHandler", {
"studyId": studyId
}
};
- osparc.data.Resources.getOne("studies", params)
+ osparc.data.Resources.fetch("studies", "getOne", params)
.then(studyData => {
if (!studyData) {
const msg = qx.locale.Manager.tr("Study not found");
@@ -110,15 +110,19 @@ qx.Class.define("osparc.desktop.MainPageHandler", {
this.setLoadingPageHeader(qx.locale.Manager.tr("Loading ") + studyData.name);
this.showLoadingPage();
- const inaccessibleServices = osparc.study.Utils.getInaccessibleServices(studyData["workbench"])
- if (inaccessibleServices.length) {
- const msg = osparc.study.Utils.getInaccessibleServicesMsg(inaccessibleServices, studyData["workbench"]);
- osparc.FlashMessenger.getInstance().logAs(msg, "ERROR");
- this.showDashboard();
- return;
- }
- this.showStudyEditor();
- this.__studyEditor.setStudyData(studyData);
+
+ osparc.store.Services.getStudyServicesMetadata(studyData)
+ .finally(() => {
+ const inaccessibleServices = osparc.store.Services.getInaccessibleServices(studyData["workbench"])
+ if (inaccessibleServices.length) {
+ const msg = osparc.store.Services.getInaccessibleServicesMsg(inaccessibleServices, studyData["workbench"]);
+ osparc.FlashMessenger.getInstance().logAs(msg, "ERROR");
+ this.showDashboard();
+ return;
+ }
+ this.showStudyEditor();
+ this.__studyEditor.setStudyData(studyData);
+ });
}
}
});
diff --git a/services/static-webserver/client/source/class/osparc/desktop/StudyEditor.js b/services/static-webserver/client/source/class/osparc/desktop/StudyEditor.js
index bcf31c70f556..f741e3806e66 100644
--- a/services/static-webserver/client/source/class/osparc/desktop/StudyEditor.js
+++ b/services/static-webserver/client/source/class/osparc/desktop/StudyEditor.js
@@ -134,7 +134,7 @@ qx.Class.define("osparc.desktop.StudyEditor", {
"studyId": studyData.uuid
}
};
- osparc.data.Resources.getOne("studies", params)
+ osparc.data.Resources.fetch("studies", "getOne", params)
.then(latestStudyData => {
const study = new osparc.data.model.Study(latestStudyData);
this.setStudy(study);
diff --git a/services/static-webserver/client/source/class/osparc/desktop/WorkbenchView.js b/services/static-webserver/client/source/class/osparc/desktop/WorkbenchView.js
index 1281742898e4..2f40fee70b64 100644
--- a/services/static-webserver/client/source/class/osparc/desktop/WorkbenchView.js
+++ b/services/static-webserver/client/source/class/osparc/desktop/WorkbenchView.js
@@ -1015,7 +1015,7 @@ qx.Class.define("osparc.desktop.WorkbenchView", {
// HEADER
const nodeMetadata = node.getMetaData();
- const version = osparc.service.Utils.getVersionDisplay(nodeMetadata["key"], nodeMetadata["version"]);
+ const version = osparc.store.Services.getVersionDisplay(nodeMetadata["key"], nodeMetadata["version"]);
const header = new qx.ui.basic.Label(`${nodeMetadata["name"]} ${version}`).set({
paddingLeft: 5
});
diff --git a/services/static-webserver/client/source/class/osparc/desktop/credits/CreditsServiceListItem.js b/services/static-webserver/client/source/class/osparc/desktop/credits/CreditsServiceListItem.js
index ab25f0207173..0e5181f56317 100644
--- a/services/static-webserver/client/source/class/osparc/desktop/credits/CreditsServiceListItem.js
+++ b/services/static-webserver/client/source/class/osparc/desktop/credits/CreditsServiceListItem.js
@@ -31,7 +31,7 @@ qx.Class.define("osparc.desktop.credits.CreditsServiceListItem", {
const icon = this.getChildControl("icon");
const name = this.getChildControl("title");
- const serviceMetadata = osparc.service.Utils.getLatest(serviceKey);
+ const serviceMetadata = osparc.store.Services.getLatest(serviceKey);
if (serviceMetadata) {
const source = osparc.utils.Utils.getIconFromResource(serviceMetadata);
icon.setSource(source);
diff --git a/services/static-webserver/client/source/class/osparc/form/renderer/PropForm.js b/services/static-webserver/client/source/class/osparc/form/renderer/PropForm.js
index ccd205a92e05..71c8c6e7cbc0 100644
--- a/services/static-webserver/client/source/class/osparc/form/renderer/PropForm.js
+++ b/services/static-webserver/client/source/class/osparc/form/renderer/PropForm.js
@@ -84,7 +84,7 @@ qx.Class.define("osparc.form.renderer.PropForm", {
isFieldParametrizable: function(field) {
const supportedTypes = [];
- const paramsMD = osparc.service.Utils.getParametersMetadata();
+ const paramsMD = osparc.store.Services.getParametersMetadata();
paramsMD.forEach(paramMD => {
supportedTypes.push(osparc.node.ParameterEditor.getParameterOutputTypeFromMD(paramMD));
});
diff --git a/services/static-webserver/client/source/class/osparc/info/ServiceUtils.js b/services/static-webserver/client/source/class/osparc/info/ServiceUtils.js
index e4a784243ee1..7e4710bcbe21 100644
--- a/services/static-webserver/client/source/class/osparc/info/ServiceUtils.js
+++ b/services/static-webserver/client/source/class/osparc/info/ServiceUtils.js
@@ -64,14 +64,14 @@ qx.Class.define("osparc.info.ServiceUtils", {
},
createVersionDisplay: function(key, version) {
- const versionDisplay = osparc.service.Utils.getVersionDisplay(key, version);
+ const versionDisplay = osparc.store.Services.getVersionDisplay(key, version);
const label = new qx.ui.basic.Label(versionDisplay);
osparc.utils.Utils.setIdToWidget(label, "serviceVersion");
return label;
},
createReleasedDate: function(key, version) {
- const releasedDate = osparc.service.Utils.getReleasedDate(key, version);
+ const releasedDate = osparc.store.Services.getReleasedDate(key, version);
if (releasedDate) {
const label = new qx.ui.basic.Label();
label.set({
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 b760ed077767..ad84337b22bf 100644
--- a/services/static-webserver/client/source/class/osparc/metadata/ServicesInStudy.js
+++ b/services/static-webserver/client/source/class/osparc/metadata/ServicesInStudy.js
@@ -45,6 +45,7 @@ qx.Class.define("osparc.metadata.ServicesInStudy", {
const servicesInStudy = osparc.study.Utils.extractUniqueServices(this._studyData["workbench"]);
if (servicesInStudy.length) {
const promises = [];
+ // the following calls make sure the history of each service is there
servicesInStudy.forEach(srv => promises.push(osparc.store.Services.getService(srv.key, srv.version)));
Promise.all(promises)
.then(() => this._populateLayout());
diff --git a/services/static-webserver/client/source/class/osparc/metadata/ServicesInStudyUpdate.js b/services/static-webserver/client/source/class/osparc/metadata/ServicesInStudyUpdate.js
index bbd9685bfecb..6831b3d70e5f 100644
--- a/services/static-webserver/client/source/class/osparc/metadata/ServicesInStudyUpdate.js
+++ b/services/static-webserver/client/source/class/osparc/metadata/ServicesInStudyUpdate.js
@@ -27,52 +27,18 @@ qx.Class.define("osparc.metadata.ServicesInStudyUpdate", {
UPDATE_BUTTON: Object.keys(osparc.metadata.ServicesInStudy.GRID_POS).length+2
},
- anyServiceDeprecated: function(studyData) {
- if ("workbench" in studyData) {
- return osparc.study.Utils.isWorkbenchDeprecated(studyData["workbench"]);
- }
- return false;
- },
-
- anyServiceRetired: function(studyData) {
- if ("workbench" in studyData) {
- return osparc.study.Utils.isWorkbenchRetired(studyData["workbench"]);
- }
- return false;
- },
-
- anyServiceInaccessible: function(studyData) {
- if ("workbench" in studyData) {
- const inaccessibles = osparc.study.Utils.getInaccessibleServices(studyData["workbench"]);
- return inaccessibles.length;
- }
- return false;
- },
-
- updatableNodeIds: function(workbench) {
+ updatableNodeIds: function(workbench, studyServices) {
const nodeIds = [];
for (const nodeId in workbench) {
const node = workbench[nodeId];
- if (osparc.service.Utils.isUpdatable(node)) {
+ const studyServiceFound = studyServices.find(studyService => studyService["key"] === node["key"] && studyService["release"]["version"] === node["version"]);
+ if (studyServiceFound && studyServiceFound["release"] && studyServiceFound["release"]["compatibility"]) {
nodeIds.push(nodeId);
}
}
return nodeIds;
},
- getLatestVersion: function(studyData, nodeId) {
- if (nodeId in studyData["workbench"]) {
- const node = studyData["workbench"][nodeId];
- if (osparc.service.Utils.isUpdatable(node)) {
- const latestCompatible = osparc.service.Utils.getLatestCompatible(node["key"], node["version"]);
- if (latestCompatible["version"] !== node["version"]) {
- return latestCompatible["version"];
- }
- }
- }
- return null;
- },
-
colorVersionLabel: function(versionLabel, metadata) {
const isDeprecated = osparc.service.Utils.isDeprecated(metadata);
const isRetired = osparc.service.Utils.isRetired(metadata);
@@ -97,57 +63,58 @@ qx.Class.define("osparc.metadata.ServicesInStudyUpdate", {
_populateIntroText: async function() {
const canIWrite = osparc.data.model.Study.canIWrite(this._studyData["accessRights"]);
- const labels = [];
- if (this.self().anyServiceInaccessible(this._studyData)) {
- const inaccessibleText = this.tr("Some services' information is not accessible. Please contact service owner:");
- const inaccessibleLabel = new qx.ui.basic.Label(inaccessibleText);
- labels.push(inaccessibleLabel);
- }
- if (this.self().anyServiceDeprecated(this._studyData)) {
- let deprecatedText = this.tr("Services marked in yellow are deprecated, they will be retired soon.");
- if (canIWrite) {
- deprecatedText += " " + this.tr("They can be updated by pressing the Update button.");
- }
- const deprecatedLabel = new qx.ui.basic.Label(deprecatedText);
- labels.push(deprecatedLabel);
- }
- if (this.self().anyServiceRetired(this._studyData)) {
- let retiredText = this.tr("Services marked in red are retired: you cannot use them anymore.");
- if (canIWrite) {
- retiredText += "
" + this.tr("If the Update button is disabled, they might require manual intervention to be updated:");
- retiredText += "
- " + this.tr("Open the study");
- retiredText += "
- " + this.tr("Click on the retired service, download the data");
- retiredText += "
- " + this.tr("Upload the data to an updated version");
+ const introText = new qx.ui.basic.Label().set({
+ font: "text-14",
+ rich: true
+ });
+ this._introText.add(introText);
+ let msg = "";
+ const params = {
+ url: {
+ studyId: this._studyData["uuid"]
}
- const retiredLabel = new qx.ui.basic.Label(retiredText);
- labels.push(retiredLabel);
- }
- const updatableServices = this.self().updatableNodeIds(this._studyData["workbench"]);
- if (updatableServices.length === 0) {
- const upToDateText = this.tr("All services are up to date to their latest compatible version.");
- const upToDateLabel = new qx.ui.basic.Label(upToDateText);
- labels.push(upToDateLabel);
- } else if (canIWrite) {
- const useUpdateButtonText = this.tr("Use the Update buttons to bring the services to their latest compatible version.");
- const useUpdateButtonLabel = new qx.ui.basic.Label(useUpdateButtonText);
- labels.push(useUpdateButtonLabel);
- } else {
- const notUpToDateText = this.tr("Some services are not up to date.");
- const notUpToDateLabel = new qx.ui.basic.Label(notUpToDateText);
- labels.push(notUpToDateLabel);
- }
+ };
+ osparc.data.Resources.fetch("studies", "getServices", params)
+ .then(resp => {
+ const services = resp["services"];
+ if (osparc.study.Utils.getCantExecuteServices(services).length) {
+ msg += this.tr("Some services are not accessible. Please contact service owner:");
+ msg += "
";
+ }
+ if (osparc.study.Utils.anyServiceRetired(services)) {
+ msg += this.tr("Services marked in red are retired: you cannot use them anymore.");
+ if (canIWrite) {
+ msg += "
" + this.tr("If the Update button is disabled, they might require manual intervention to be updated:");
+ msg += "
- " + this.tr("Open the study");
+ msg += "
- " + this.tr("Click on the retired service, download the data");
+ msg += "
- " + this.tr("Upload the data to an updated version");
+ }
+ msg += "
";
+ }
+ if (osparc.study.Utils.anyServiceDeprecated(services)) {
+ msg += this.tr("Services marked in yellow are deprecated, they will be retired soon.");
+ if (canIWrite) {
+ msg += " " + this.tr("They can be updated by pressing the Update button.");
+ }
+ msg += "
";
+ }
+ const anyServiceUpdatable = osparc.study.Utils.anyServiceUpdatable(services);
+ if (anyServiceUpdatable === false && msg === "") {
+ msg += this.tr("All services are up to date to their latest compatible version.");
+ msg += "
";
+ } else if (canIWrite) {
+ msg += this.tr("Use the Update buttons to bring the services to their latest compatible version.");
+ msg += "
";
+ } else {
+ msg += this.tr("Some services are not up to date.");
+ }
- labels.forEach(label => {
- label.set({
- font: "text-14",
- rich: true
+ introText.setValue(msg);
});
- this._introText.add(label);
- });
},
__updateService: async function(nodeId, key, version, button) {
- const latestCompatible = osparc.service.Utils.getLatestCompatible(key, version);
+ const latestCompatible = osparc.store.Services.getLatestCompatible(key, version);
const patchData = {};
if (key !== latestCompatible["key"]) {
patchData["key"] = latestCompatible["key"];
@@ -201,6 +168,7 @@ qx.Class.define("osparc.metadata.ServicesInStudyUpdate", {
const canIWrite = osparc.data.model.Study.canIWrite(this._studyData["accessRights"]);
let i = 0;
+ const updatableServices = [];
const workbench = this._studyData["workbench"];
for (const nodeId in workbench) {
i++;
@@ -218,7 +186,7 @@ qx.Class.define("osparc.metadata.ServicesInStudyUpdate", {
const compatibleVersionLabel = new qx.ui.basic.Label().set({
font: "text-14"
});
- const latestCompatible = osparc.service.Utils.getLatestCompatible(node["key"], node["version"]);
+ const latestCompatible = osparc.store.Services.getLatestCompatible(node["key"], node["version"]);
if (latestCompatible) {
// updatable
osparc.store.Services.getService(latestCompatible["key"], latestCompatible["version"])
@@ -241,9 +209,9 @@ qx.Class.define("osparc.metadata.ServicesInStudyUpdate", {
column: this.self().GRID_POS.COMPATIBLE_VERSION
});
- const isUpdatable = osparc.service.Utils.isUpdatable(node);
if (latestCompatible && canIWrite) {
const updateButton = new osparc.ui.form.FetchButton(null, "@MaterialIcons/update/14");
+ const isUpdatable = osparc.service.Utils.isUpdatable(metadata);
updateButton.set({
enabled: isUpdatable
});
@@ -257,6 +225,7 @@ qx.Class.define("osparc.metadata.ServicesInStudyUpdate", {
label: this.tr("Update"),
center: true
});
+ updatableServices.push(nodeId);
}
updateButton.addListener("execute", () => this.__updateService(nodeId, node["key"], node["version"], updateButton), this);
this._servicesGrid.add(updateButton, {
@@ -266,7 +235,6 @@ qx.Class.define("osparc.metadata.ServicesInStudyUpdate", {
}
}
- const updatableServices = osparc.metadata.ServicesInStudyUpdate.updatableNodeIds(workbench);
if (updatableServices.length && canIWrite) {
const updateAllButton = this.__updateAllButton;
updateAllButton.show();
diff --git a/services/static-webserver/client/source/class/osparc/node/LifeCycleView.js b/services/static-webserver/client/source/class/osparc/node/LifeCycleView.js
index 5f810b187991..ea6ed0fbb289 100644
--- a/services/static-webserver/client/source/class/osparc/node/LifeCycleView.js
+++ b/services/static-webserver/client/source/class/osparc/node/LifeCycleView.js
@@ -110,7 +110,7 @@ qx.Class.define("osparc.node.LifeCycleView", {
});
updateButton.addListener("execute", () => {
updateButton.setFetching(true);
- const latestCompatible = osparc.service.Utils.getLatestCompatible(node.getKey(), node.getVersion());
+ const latestCompatible = osparc.store.Services.getLatestCompatible(node.getKey(), node.getVersion());
if (node.getKey() !== latestCompatible["key"]) {
node.setKey(latestCompatible["key"]);
}
diff --git a/services/static-webserver/client/source/class/osparc/notification/NotificationUI.js b/services/static-webserver/client/source/class/osparc/notification/NotificationUI.js
index f339a68bf06a..9d9b4bfa656f 100644
--- a/services/static-webserver/client/source/class/osparc/notification/NotificationUI.js
+++ b/services/static-webserver/client/source/class/osparc/notification/NotificationUI.js
@@ -150,7 +150,7 @@ qx.Class.define("osparc.notification.NotificationUI", {
"studyId": resourceId
}
};
- osparc.data.Resources.getOne("studies", params)
+ osparc.data.Resources.fetch("studies", "getOne", params)
.then(study => {
const studyAlias = osparc.product.Utils.getStudyAlias({
firstUpperCase: true
@@ -194,7 +194,7 @@ qx.Class.define("osparc.notification.NotificationUI", {
"studyId": resourceId
}
};
- osparc.data.Resources.getOne("studies", params)
+ osparc.data.Resources.fetch("studies", "getOne", params)
.then(study => titleLabel.setValue(`Note added in '${study["name"]}'`))
.catch(() => this.setEnabled(false));
}
@@ -283,7 +283,7 @@ qx.Class.define("osparc.notification.NotificationUI", {
"studyId": studyId
}
};
- osparc.data.Resources.getOne("studies", params)
+ osparc.data.Resources.fetch("studies", "getOne", params)
.then(studyData => {
if (studyData) {
const studyDataCopy = osparc.data.model.Study.deepCloneStudyObject(studyData);
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 9fbc302b6fbb..6c007907944c 100644
--- a/services/static-webserver/client/source/class/osparc/service/ServiceListItem.js
+++ b/services/static-webserver/client/source/class/osparc/service/ServiceListItem.js
@@ -24,8 +24,7 @@ qx.Class.define("osparc.service.ServiceListItem", {
this.set({
width: this.self().ITEM_WIDTH,
height: this.self().ITEM_HEIGHT,
- paddingTop: 0,
- paddingBottom: 0,
+ padding: this.self().PADDING,
allowGrowX: true,
focusable: true,
});
@@ -53,7 +52,8 @@ qx.Class.define("osparc.service.ServiceListItem", {
statics: {
LATEST: "latest",
ITEM_WIDTH: 550,
- ITEM_HEIGHT: 35,
+ ITEM_HEIGHT: 32 + 2*4, // thumbnail + 2*PADDING
+ PADDING: 4,
SERVICE_THUMBNAIL: osparc.product.Utils.getThumbnailUrl()
},
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 d58094d5900b..ab1ee841c74e 100644
--- a/services/static-webserver/client/source/class/osparc/service/Utils.js
+++ b/services/static-webserver/client/source/class/osparc/service/Utils.js
@@ -24,7 +24,7 @@
* Here is a little example of how to use the widget.
*
*
- * let latestSrv = osparc.service.Utils.getLatest(key);
+ * let latestSrv = osparc.store.Services.getLatest(key);
*
*/
@@ -130,86 +130,11 @@ qx.Class.define("osparc.service.Utils", {
return services;
},
- getVersions: function(key, filterDeprecated = true) {
- const services = osparc.store.Services.servicesCached;
- let versions = [];
- if (key in services) {
- const serviceVersions = services[key];
- versions = versions.concat(Object.keys(serviceVersions));
- if (filterDeprecated) {
- versions = versions.filter(version => {
- if (services[key][version]["retired"]) {
- return false;
- }
- return true;
- });
- }
- versions.sort(osparc.utils.Utils.compareVersionNumbers);
- }
- return versions.reverse();
- },
-
- getLatest: function(key) {
- const services = osparc.store.Services.servicesCached;
- if (key in services) {
- const versions = this.getVersions(key, true);
- if (versions.length) {
- return services[key][versions[0]];
- }
- }
- return null;
- },
-
- getLatestCompatible: function(key, version) {
- const services = osparc.store.Services.servicesCached;
- if (key in services && version in services[key]) {
- const serviceMD = services[key][version];
- if (serviceMD["compatibility"] && serviceMD["compatibility"]["canUpdateTo"]) {
- const canUpdateTo = serviceMD["compatibility"]["canUpdateTo"];
- return {
- key: "key" in canUpdateTo ? canUpdateTo["key"] : key, // key is optional
- version: canUpdateTo["version"]
- }
- }
- // the provided key/version itself is the latest compatible
- return {
- key,
- version
- }
- }
- return null;
- },
-
- getVersionDisplay: function(key, version) {
- const services = osparc.store.Services.servicesCached;
- if (key in services && version in services[key]) {
- return this.extractVersionDisplay(services[key][version]);
- }
- return null;
- },
-
extractVersionDisplay: function(metadata) {
- return metadata["versionDisplay"] ? metadata["versionDisplay"] : metadata["version"];
- },
-
- getReleasedDate: function(key, version) {
- const services = osparc.store.Services.servicesCached;
- if (
- key in services &&
- version in services[key] &&
- "released" in services[key][version]
- ) {
- return services[key][version]["released"];
+ if (metadata) {
+ return metadata["versionDisplay"] ? metadata["versionDisplay"] : metadata["version"];
}
- return null;
- },
-
- versionToListItem: function(key, version) {
- const versionDisplay = this.getVersionDisplay(key, version);
- const listItem = new qx.ui.form.ListItem(versionDisplay);
- osparc.utils.Utils.setIdToWidget(listItem, "serviceVersionItem_" + versionDisplay);
- listItem.version = version;
- return listItem;
+ return "";
},
canIWrite: function(serviceAccessRights) {
@@ -228,14 +153,38 @@ qx.Class.define("osparc.service.Utils", {
DEPRECATED_AUTOUPDATABLE_INSTRUCTIONS: qx.locale.Manager.tr("Please Stop the Service and then Update it"),
RETIRED_AUTOUPDATABLE_INSTRUCTIONS: qx.locale.Manager.tr("Please Update the Service"),
+ extractVersionFromHistory: function(metadata) {
+ if (metadata["history"]) {
+ const found = metadata["history"].find(historyEntry => historyEntry["version"] === metadata["version"]);
+ return found;
+ }
+ return null;
+ },
+
isUpdatable: function(metadata) {
- const latestCompatible = this.getLatestCompatible(metadata["key"], metadata["version"]);
- return latestCompatible && (metadata["key"] !== latestCompatible["key"] || metadata["version"] !== latestCompatible["version"]);
+ const historyEntry = this.extractVersionFromHistory(metadata);
+ if (historyEntry && historyEntry["compatibility"] && historyEntry["compatibility"]["canUpdateTo"]) {
+ const latestCompatible = historyEntry["compatibility"]["canUpdateTo"];
+ return latestCompatible && (metadata["key"] !== latestCompatible["key"] || metadata["version"] !== latestCompatible["version"]);
+ }
+ return false;
+ },
+
+ __extractRetiredDate: function(metadata) {
+ if ("release" in metadata && metadata["release"]["retired"]) {
+ // this works for service latest
+ return new Date(metadata["release"]["retired"]);
+ }
+ const historyEntry = this.extractVersionFromHistory(metadata);
+ if (historyEntry && "retired" in historyEntry && historyEntry["retired"]) {
+ return new Date(historyEntry["retired"]);
+ }
+ return null;
},
isDeprecated: function(metadata) {
- if (metadata && "retired" in metadata && ![null, undefined].includes(metadata["retired"])) {
- const deprecationTime = new Date(metadata["retired"]);
+ const deprecationTime = this.__extractRetiredDate(metadata);
+ if (deprecationTime) {
const now = new Date();
return deprecationTime.getTime() > now.getTime();
}
@@ -243,8 +192,8 @@ qx.Class.define("osparc.service.Utils", {
},
isRetired: function(metadata) {
- if (metadata && "retired" in metadata && ![null, undefined].includes(metadata["retired"])) {
- const deprecationTime = new Date(metadata["retired"]);
+ const deprecationTime = this.__extractRetiredDate(metadata);
+ if (deprecationTime) {
const now = new Date();
return deprecationTime.getTime() < now.getTime();
}
@@ -252,34 +201,11 @@ qx.Class.define("osparc.service.Utils", {
},
getDeprecationDateText: function(metadata) {
- const deprecationTime = new Date(metadata["retired"]);
- return qx.locale.Manager.tr("It will be Retired: ") + osparc.utils.Utils.formatDate(deprecationTime);
- },
-
- getFilePicker: function() {
- return this.self().getLatest("simcore/services/frontend/file-picker");
- },
-
- getParametersMetadata: function() {
- const parametersMetadata = [];
- const services = osparc.store.Services.servicesCached;
- for (const key in services) {
- if (key.includes("simcore/services/frontend/parameter/")) {
- const latest = this.self().getLatest(key);
- if (latest) {
- parametersMetadata.push(latest);
- }
- }
+ if (this.isDeprecated(metadata) || this.isRetired(metadata)) {
+ const deprecationTime = this.__extractRetiredDate(metadata);
+ return qx.locale.Manager.tr("It will be Retired: ") + osparc.utils.Utils.formatDate(deprecationTime);
}
- return parametersMetadata;
- },
-
- getParameterMetadata: function(type) {
- return this.self().getLatest("simcore/services/frontend/parameter/"+type);
- },
-
- getProbeMetadata: function(type) {
- return this.self().getLatest("simcore/services/frontend/iterator-consumer/probe/"+type);
+ return "";
},
removeFileToKeyMap: function(service) {
diff --git a/services/static-webserver/client/source/class/osparc/snapshots/IterationsView.js b/services/static-webserver/client/source/class/osparc/snapshots/IterationsView.js
index c9b1557f1112..b80382fdd17a 100644
--- a/services/static-webserver/client/source/class/osparc/snapshots/IterationsView.js
+++ b/services/static-webserver/client/source/class/osparc/snapshots/IterationsView.js
@@ -76,7 +76,7 @@ qx.Class.define("osparc.snapshots.IterationsView", {
"studyId": iteration["workcopy_project_id"]
}
};
- iterationPromises.push(osparc.data.Resources.getOne("studies", params));
+ iterationPromises.push(osparc.data.Resources.fetch("studies", "getOne", params));
});
Promise.all(iterationPromises)
.then(values => {
@@ -204,7 +204,7 @@ qx.Class.define("osparc.snapshots.IterationsView", {
"studyId": iterationId
}
};
- osparc.data.Resources.getOne("studies", params)
+ osparc.data.Resources.fetch("studies", "getOne", params)
.then(data => {
const studyData = this.__study.serialize();
studyData["workbench"] = data["workbench"];
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 c2abeed32ece..ded5d21101e0 100644
--- a/services/static-webserver/client/source/class/osparc/store/Services.js
+++ b/services/static-webserver/client/source/class/osparc/store/Services.js
@@ -19,11 +19,11 @@ qx.Class.define("osparc.store.Services", {
type: "static",
statics: {
- servicesCached: {},
+ __servicesCached: {},
getServicesLatest: function(useCache = true) {
return new Promise(resolve => {
- if (useCache && Object.keys(this.servicesCached)) {
+ if (useCache && Object.keys(this.__servicesCached)) {
// return latest only
const latest = this.__getLatestCached();
resolve(latest);
@@ -37,9 +37,8 @@ qx.Class.define("osparc.store.Services", {
this.__addTSRInfos(servicesObj);
this.__addExtraTypeInfos(servicesObj);
- // use response to populate servicesCached
Object.values(servicesObj).forEach(serviceKey => {
- Object.values(serviceKey).forEach(srv => this.__addToCache(srv));
+ Object.values(serviceKey).forEach(service => this.__addToCache(service));
});
resolve(servicesObj);
@@ -52,6 +51,110 @@ qx.Class.define("osparc.store.Services", {
});
},
+ getLatest: function(key) {
+ const services = this.__servicesCached;
+ if (key in services) {
+ const latestMetadata = Object.values(services[key])[0];
+ if (!osparc.service.Utils.isRetired(latestMetadata)) {
+ return latestMetadata;
+ }
+ }
+ return null;
+ },
+
+ getLatestCompatible: function(key, version) {
+ const services = this.__servicesCached;
+ if (key in services && version in services[key]) {
+ const serviceMD = services[key][version];
+ if (serviceMD["compatibility"] && serviceMD["compatibility"]["canUpdateTo"]) {
+ const canUpdateTo = serviceMD["compatibility"]["canUpdateTo"];
+ return {
+ key: "key" in canUpdateTo ? canUpdateTo["key"] : key, // key is optional
+ version: canUpdateTo["version"]
+ };
+ }
+ // the provided key/version itself is the latest compatible
+ return {
+ key,
+ version
+ };
+ }
+ return null;
+ },
+
+ getVersionDisplay: function(key, version) {
+ const services = this.__servicesCached;
+ if (key in services && version in services[key]) {
+ return osparc.service.Utils.extractVersionDisplay(services[key][version]);
+ }
+ return null;
+ },
+
+ getReleasedDate: function(key, version) {
+ const services = this.__servicesCached;
+ if (
+ key in services &&
+ version in services[key] &&
+ "released" in services[key][version]
+ ) {
+ return services[key][version]["released"];
+ }
+ return null;
+ },
+
+ getService: function(key, version, useCache = true) {
+ return new Promise(resolve => {
+ if (
+ useCache &&
+ this.__isInCache(key, version) &&
+ "history" in this.__servicesCached[key][version]
+ ) {
+ resolve(this.__servicesCached[key][version]);
+ return;
+ }
+
+ const params = {
+ url: osparc.data.Resources.getServiceUrl(key, version)
+ };
+ osparc.data.Resources.fetch("servicesV2", "getOne", params)
+ .then(service => {
+ this.__addHit(service);
+ this.__addTSRInfo(service);
+ this.__addExtraTypeInfo(service);
+ this.__addToCache(service)
+ resolve(service);
+ })
+ .catch(console.error);
+ });
+ },
+
+ __getAllVersions: function(key) {
+ const services = this.__servicesCached;
+ let versions = [];
+ if (key in services) {
+ const serviceVersions = services[key];
+ versions = versions.concat(Object.keys(serviceVersions));
+ versions.sort(osparc.utils.Utils.compareVersionNumbers);
+ }
+ return versions.reverse();
+ },
+
+ populateVersionsSelectBox: function(key, selectBox) {
+ const versions = this.__getAllVersions(key);
+ return this.getService(key, versions[0])
+ .then(latestMetadata => {
+ latestMetadata["history"].forEach(historyEntry => {
+ if (!historyEntry["retired"]) {
+ const versionDisplay = osparc.service.Utils.extractVersionDisplay(historyEntry);
+ const listItem = new qx.ui.form.ListItem(versionDisplay);
+ osparc.utils.Utils.setIdToWidget(listItem, "serviceVersionItem_" + versionDisplay);
+ listItem.version = historyEntry["version"];
+ selectBox.add(listItem);
+ }
+ });
+ });
+ },
+
getServicesLatestList: function(excludeFrontend = true, excludeDeprecated = true) {
return new Promise(resolve => {
const servicesList = [];
@@ -65,19 +168,25 @@ qx.Class.define("osparc.store.Services", {
// do not add frontend services
continue;
}
- if (excludeDeprecated && serviceLatest["retired"]) {
- // first check if a previous version of this service isn't retired
- let versions = Object.keys(this.servicesCached[key]);
- versions = versions.sort(osparc.utils.Utils.compareVersionNumbers).reverse();
- for (let j=0; j {
- if (useCache && this.__isInCache(key, version)) {
- resolve(this.servicesCached[key][version]);
- return;
- }
-
- const params = {
- url: osparc.data.Resources.getServiceUrl(key, version)
- };
- osparc.data.Resources.getOne("servicesV2", params)
- .then(service => {
- this.__addHit(service);
- this.__addTSRInfo(service);
- this.__addExtraTypeInfo(service);
- this.__addToCache(service)
- resolve(service);
- })
- .catch(console.error);
- });
- },
-
getResources: function(key, version) {
return new Promise(resolve => {
if (
this.__isInCache(key, version) &&
- "resources" in this.servicesCached[key][version]
+ "resources" in this.__servicesCached[key][version]
) {
- resolve(this.servicesCached[key][version]["resources"]);
+ resolve(this.__servicesCached[key][version]["resources"]);
return;
}
@@ -129,7 +216,7 @@ qx.Class.define("osparc.store.Services", {
};
osparc.data.Resources.get("serviceResources", params)
.then(resources => {
- this.servicesCached[key][version]["resources"] = resources;
+ this.__servicesCached[key][version]["resources"] = resources;
resolve(resources);
});
});
@@ -137,7 +224,7 @@ qx.Class.define("osparc.store.Services", {
getMetadata: function(key, version) {
if (this.__isInCache(key, version)) {
- return this.servicesCached[key][version];
+ return this.__servicesCached[key][version];
}
return null;
},
@@ -153,50 +240,97 @@ qx.Class.define("osparc.store.Services", {
};
return osparc.data.Resources.fetch("servicesV2", "patch", params)
.then(() => {
- this.servicesCached[key][version][fieldKey] = value;
+ this.__servicesCached[key][version][fieldKey] = value;
serviceData[fieldKey] = value;
});
},
+ getStudyServicesMetadata: function(studyData) {
+ const wbServices = new Set(osparc.study.Utils.extractUniqueServices(studyData["workbench"]));
+ const promises = [];
+ wbServices.forEach(srv => {
+ promises.push(this.getService(srv["key"], srv["version"]));
+ });
+ return Promise.all(promises);
+ },
+
+ getInaccessibleServices: function(workbench) {
+ const allServices = this.__servicesCached;
+ const unaccessibleServices = [];
+ const wbServices = new Set(osparc.study.Utils.extractUniqueServices(workbench));
+ wbServices.forEach(srv => {
+ if (srv.key in allServices && srv.version in allServices[srv.key]) {
+ return;
+ }
+ const idx = unaccessibleServices.findIndex(unSrv => unSrv.key === srv.key && unSrv.version === srv.version);
+ if (idx === -1) {
+ unaccessibleServices.push(srv);
+ }
+ });
+ return unaccessibleServices;
+ },
+
+ getInaccessibleServicesMsg: function(inaccessibleServices, workbench) {
+ let msg = qx.locale.Manager.tr("Some services are not accessible:
");
+ Object.values(workbench).forEach(node => {
+ const inaccessibleService = inaccessibleServices.find(srv => srv.key === node.key && srv.version === node.version);
+ if (inaccessibleService) {
+ const n = inaccessibleService.key.lastIndexOf("/");
+ const friendlyKey = inaccessibleService.key.substring(n + 1);
+ msg += `- ${node.label} (${friendlyKey}:${inaccessibleService.version})
`;
+ }
+ });
+ return msg;
+ },
+
+ getFilePicker: function() {
+ return this.getLatest("simcore/services/frontend/file-picker");
+ },
+
+ getParametersMetadata: function() {
+ const parametersMetadata = [];
+ const services = this.__servicesCached;
+ for (const key in services) {
+ if (key.includes("simcore/services/frontend/parameter/")) {
+ const latest = this.getLatest(key);
+ if (latest) {
+ parametersMetadata.push(latest);
+ }
+ }
+ }
+ return parametersMetadata;
+ },
+
+ getParameterMetadata: function(type) {
+ return this.getLatest("simcore/services/frontend/parameter/"+type);
+ },
+
+ getProbeMetadata: function(type) {
+ return this.getLatest("simcore/services/frontend/iterator-consumer/probe/"+type);
+ },
+
__addToCache: function(service) {
const key = service.key;
const version = service.version;
- if (!(key in this.servicesCached)) {
- this.servicesCached[key] = {};
- }
- this.servicesCached[key][version] = service;
- this.servicesCached[key][version]["cached"] = true;
-
- if ("history" in service) {
- service["history"].forEach(historyEntry => {
- const hVersion = historyEntry.version;
- if (!(hVersion in this.servicesCached[key])) {
- this.servicesCached[key][hVersion] = {};
- this.servicesCached[key][hVersion]["cached"] = false;
- }
- // merge history data into current metadata
- this.servicesCached[key][hVersion] = {
- ...this.servicesCached[key][hVersion],
- ...historyEntry
- };
- });
+ if (!(key in this.__servicesCached)) {
+ this.__servicesCached[key] = {};
}
+ this.__servicesCached[key][version] = service;
},
__isInCache: function(key, version) {
return (
- key in this.servicesCached &&
- version in this.servicesCached[key] &&
- this.servicesCached[key][version]["cached"]
+ key in this.__servicesCached &&
+ version in this.__servicesCached[key]
);
},
__getLatestCached: function() {
const latestServices = {};
- for (const key in this.servicesCached) {
- let versions = Object.keys(this.servicesCached[key]);
+ for (const key in this.__servicesCached) {
+ let versions = Object.keys(this.__servicesCached[key]);
versions = versions.sort(osparc.utils.Utils.compareVersionNumbers).reverse();
- const latest = this.servicesCached[key][versions[0]];
+ const latest = this.__servicesCached[key][versions[0]];
latestServices[key] = osparc.utils.Utils.deepCloneObject(latest);
}
return latestServices;
diff --git a/services/static-webserver/client/source/class/osparc/study/StudyOptions.js b/services/static-webserver/client/source/class/osparc/study/StudyOptions.js
index b4ea84778a69..a784cdd1335f 100644
--- a/services/static-webserver/client/source/class/osparc/study/StudyOptions.js
+++ b/services/static-webserver/client/source/class/osparc/study/StudyOptions.js
@@ -245,7 +245,7 @@ qx.Class.define("osparc.study.StudyOptions", {
}
};
Promise.all([
- osparc.data.Resources.getOne("studies", params),
+ osparc.data.Resources.fetch("studies", "getOne", params),
osparc.data.Resources.fetch("studies", "getWallet", params)
])
.then(values => {
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 7748d60303fd..52152cb1f60e 100644
--- a/services/static-webserver/client/source/class/osparc/study/Utils.js
+++ b/services/static-webserver/client/source/class/osparc/study/Utils.js
@@ -45,77 +45,45 @@ qx.Class.define("osparc.study.Utils", {
return services;
},
- getInaccessibleServices: function(workbench) {
- const allServices = osparc.store.Services.servicesCached;
- const unaccessibleServices = [];
- const wbServices = new Set(this.extractUniqueServices(workbench));
- wbServices.forEach(srv => {
- if (srv.key in allServices && srv.version in allServices[srv.key]) {
- return;
- }
- const idx = unaccessibleServices.findIndex(unSrv => unSrv.key === srv.key && unSrv.version === srv.version);
- if (idx === -1) {
- unaccessibleServices.push(srv);
- }
- });
- return unaccessibleServices;
+ getCantExecuteServices: function(studyServices = []) {
+ return studyServices.filter(studyService => studyService["myAccessRights"]["execute"] === false);
},
- getInaccessibleServicesMsg: function(inaccessibleServices, workbench) {
- let msg = qx.locale.Manager.tr("Service(s) not accessible:
");
- Object.values(workbench).forEach(node => {
- const inaccessibleService = inaccessibleServices.find(srv => srv.key === node.key && srv.version === node.version);
- if (inaccessibleService) {
- const n = inaccessibleService.key.lastIndexOf("/");
- const friendlyKey = inaccessibleService.key.substring(n + 1);
- msg += `- ${node.label} (${friendlyKey}:${inaccessibleService.version})
`;
+ anyServiceRetired: function(studyServices) {
+ const isRetired = studyServices.some(studyService => {
+ if (studyService["release"] && studyService["release"]["retired"]) {
+ const retirementDate = new Date(studyService["release"]["retired"]);
+ const currentDate = new Date();
+ return retirementDate < currentDate;
}
+ return false;
});
- return msg;
- },
-
- isWorkbenchUpdatable: function(workbench) {
- const services = new Set(this.extractUniqueServices(workbench));
- const isUpdatable = Array.from(services).some(srv => osparc.service.Utils.isUpdatable(srv));
- return isUpdatable;
+ return isRetired;
},
- isWorkbenchRetired: function(workbench) {
- const allServices = osparc.store.Services.servicesCached;
- const services = new Set(this.extractUniqueServices(workbench));
- const isRetired = Array.from(services).some(srv => {
- if (srv.key in allServices && srv.version in allServices[srv.key]) {
- const serviceMD = allServices[srv.key][srv.version];
- if (serviceMD["retired"]) {
- const retirementDate = new Date(serviceMD["retired"]);
- const currentDate = new Date();
- return retirementDate < currentDate;
- }
- return false;
+ anyServiceDeprecated: function(studyServices) {
+ const isDeprecated = studyServices.some(studyService => {
+ if (studyService["release"] && studyService["release"]["retired"]) {
+ const retirementDate = new Date(studyService["release"]["retired"]);
+ const currentDate = new Date();
+ return retirementDate > currentDate;
}
return false;
});
- return isRetired;
+ return isDeprecated;
},
- isWorkbenchDeprecated: function(workbench) {
- const allServices = osparc.store.Services.servicesCached;
- const services = new Set(this.extractUniqueServices(workbench));
- const isRetired = Array.from(services).some(srv => {
- if (srv.key in allServices && srv.version in allServices[srv.key]) {
- const serviceMD = allServices[srv.key][srv.version];
- if ("retired" in serviceMD && serviceMD["retired"]) {
- const retirementDate = new Date(serviceMD["retired"]);
- const currentDate = new Date();
- return retirementDate > currentDate;
- }
- return false;
+ anyServiceUpdatable: function(studyServices) {
+ const isUpdatable = studyServices.some(studyService => {
+ if (studyService["release"] && studyService["release"]["compatibility"]) {
+ return Boolean(studyService["release"]["compatibility"]);
}
return false;
});
- return isRetired;
+ return isUpdatable;
},
+
createStudyFromService: function(key, version, existingStudies, newStudyLabel, contextProps = {}) {
return new Promise((resolve, reject) => {
osparc.store.Services.getService(key, version)
@@ -157,9 +125,9 @@ qx.Class.define("osparc.study.Utils", {
if (!("mode" in minStudyData["ui"])) {
minStudyData["ui"]["mode"] = "standalone";
}
- const inaccessibleServices = this.getInaccessibleServices(minStudyData["workbench"])
+ const inaccessibleServices = osparc.store.Services.getInaccessibleServices(minStudyData["workbench"])
if (inaccessibleServices.length) {
- const msg = this.getInaccessibleServicesMsg(inaccessibleServices, minStudyData["workbench"]);
+ const msg = osparc.store.Services.getInaccessibleServicesMsg(inaccessibleServices, minStudyData["workbench"]);
reject({
message: msg
});
@@ -204,9 +172,9 @@ qx.Class.define("osparc.study.Utils", {
createStudyFromTemplate: function(templateData, loadingPage, contextProps = {}) {
return new Promise((resolve, reject) => {
- const inaccessibleServices = this.getInaccessibleServices(templateData["workbench"]);
+ const inaccessibleServices = osparc.store.Services.getInaccessibleServices(templateData["workbench"]);
if (inaccessibleServices.length) {
- const msg = this.getInaccessibleServicesMsg(inaccessibleServices, templateData["workbench"]);
+ const msg = osparc.store.Services.getInaccessibleServicesMsg(inaccessibleServices, templateData["workbench"]);
reject({
message: msg
});
@@ -293,8 +261,8 @@ qx.Class.define("osparc.study.Utils", {
},
__getBlockedState: function(studyData) {
- if (studyData["workbench"]) {
- const unaccessibleServices = osparc.study.Utils.getInaccessibleServices(studyData["workbench"])
+ if (studyData["services"]) {
+ const unaccessibleServices = osparc.study.Utils.getCantExecuteServices(studyData["services"])
if (unaccessibleServices.length) {
return "UNKNOWN_SERVICES";
}
@@ -362,30 +330,34 @@ qx.Class.define("osparc.study.Utils", {
return Object.values(studyData["workbench"]).filter(nodeData => !osparc.data.model.Node.isFrontend(nodeData));
},
- guessIcon: function(studyData) {
+ guessIcon: async function(studyData) {
if (osparc.product.Utils.isProduct("tis") || osparc.product.Utils.isProduct("tiplite")) {
return this.__guessTIPIcon(studyData);
}
- return this.__guessIcon(studyData);
+ const icon = await this.__guessIcon(studyData);
+ return icon;
},
__guessIcon: function(studyData) {
- // the was to guess the TI type is to check the boot mode of the ti-postpro in the pipeline
- const wbServices = this.self().getNonFrontendNodes(studyData);
- if (wbServices.length === 1) {
- const wbService = wbServices[0];
- const allServices = osparc.store.Services.servicesCached;
- if (wbService.key in allServices && wbService.version in allServices[wbService.key]) {
- const serviceMetadata = allServices[wbService.key][wbService.version];
- if (serviceMetadata["icon"]) {
- return serviceMetadata["icon"];
- }
+ const defaultIcon = osparc.dashboard.CardBase.PRODUCT_ICON;
+ return new Promise(resolve => {
+ // the was to guess the TI type is to check the boot mode of the ti-postpro in the pipeline
+ const wbServices = this.self().getNonFrontendNodes(studyData);
+ if (wbServices.length === 1) {
+ const wbService = wbServices[0];
+ osparc.store.Services.getService(wbService.key, wbService.version)
+ .then(serviceMetadata => {
+ if (serviceMetadata["icon"]) {
+ resolve(serviceMetadata["icon"]);
+ }
+ resolve(defaultIcon);
+ });
+ } else if (wbServices.length > 1) {
+ resolve("osparc/icons/diagram.png");
+ } else {
+ resolve(defaultIcon);
}
- }
- if (wbServices.length > 1) {
- return "osparc/icons/diagram.png";
- }
- return osparc.dashboard.CardBase.PRODUCT_ICON;
+ });
},
__guessTIPIcon: function(studyData) {
diff --git a/services/static-webserver/client/source/class/osparc/utils/Utils.js b/services/static-webserver/client/source/class/osparc/utils/Utils.js
index 885a09d4f0c2..781e0cba3d9f 100644
--- a/services/static-webserver/client/source/class/osparc/utils/Utils.js
+++ b/services/static-webserver/client/source/class/osparc/utils/Utils.js
@@ -91,11 +91,20 @@ qx.Class.define("osparc.utils.Utils", {
FLOATING_Z_INDEX: 1000001 + 1,
+ checkImageExists: function(url) {
+ return new Promise(resolve => {
+ const img = new Image();
+ img.onload = () => resolve(true);
+ img.onerror = () => resolve(false);
+ img.src = url;
+ });
+ },
+
setUrlSourceToImage: function(image, imgSrc) {
let source = osparc.product.Utils.getThumbnailUrl();
- fetch(imgSrc, { method: "HEAD" })
- .then(response => {
- if (response.ok) {
+ this.checkImageExists(imgSrc)
+ .then(exists => {
+ if (exists) {
source = imgSrc;
}
})
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 d14212aa20f5..94229ae175e0 100644
--- a/services/static-webserver/client/source/class/osparc/workbench/ServiceCatalog.js
+++ b/services/static-webserver/client/source/class/osparc/workbench/ServiceCatalog.js
@@ -225,35 +225,30 @@ qx.Class.define("osparc.workbench.ServiceCatalog", {
});
osparc.service.Utils.sortObjectsBasedOn(filteredServices, this.__sortBy);
- const filteredServicesObj = this.__filteredServicesObj = osparc.service.Utils.convertArrayToObject(filteredServices);
-
- const groupedServicesList = [];
- for (const key in filteredServicesObj) {
- const serviceMetadata = osparc.service.Utils.getLatest(key);
- if (serviceMetadata) {
- const service = new osparc.data.model.Service(serviceMetadata);
- groupedServicesList.push(service);
- }
- }
+ this.__filteredServicesObj = osparc.service.Utils.convertArrayToObject(filteredServices);
+
+ const servicesModels = [];
+ filteredServices.forEach(filteredService => {
+ const service = new osparc.data.model.Service(filteredService);
+ servicesModels.push(service);
+ });
- this.__serviceList.setModel(new qx.data.Array(groupedServicesList));
+ this.__serviceList.setModel(new qx.data.Array(servicesModels));
},
__changedSelection: function(key) {
if (this.__versionsBox) {
- let selectBox = this.__versionsBox;
+ const selectBox = this.__versionsBox;
selectBox.removeAll();
if (key in this.__filteredServicesObj) {
const latest = new qx.ui.form.ListItem(this.self().LATEST);
latest.version = this.self().LATEST;
selectBox.add(latest);
- const versions = osparc.service.Utils.getVersions(key);
- versions.forEach(version => {
- const listItem = osparc.service.Utils.versionToListItem(key, version);
- selectBox.add(listItem);
- });
- osparc.utils.Utils.growSelectBox(selectBox, 200);
- selectBox.setSelection([latest]);
+ osparc.store.Services.populateVersionsSelectBox(key, selectBox)
+ .then(() => {
+ osparc.utils.Utils.growSelectBox(selectBox, 200);
+ selectBox.setSelection([latest]);
+ });
}
}
if (this.__addBtn) {
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 19a123cf5473..221fc08417a5 100644
--- a/services/static-webserver/client/source/class/osparc/workbench/WorkbenchUI.js
+++ b/services/static-webserver/client/source/class/osparc/workbench/WorkbenchUI.js
@@ -2005,7 +2005,7 @@ qx.Class.define("osparc.workbench.WorkbenchUI", {
x: e.offsetX,
y: e.offsetY
};
- const service = qx.data.marshal.Json.createModel(osparc.service.Utils.getFilePicker());
+ const service = qx.data.marshal.Json.createModel(osparc.store.Services.getFilePicker());
const nodeUI = await this.__addNode(service, pos);
if (nodeUI) {
const filePicker = new osparc.file.FilePicker(nodeUI.getNode(), "workbench");
@@ -2028,7 +2028,7 @@ qx.Class.define("osparc.workbench.WorkbenchUI", {
const data = this.__isDraggingLink["dragData"];
this.__isDraggingLink = null;
const pos = this.__pointerEventToWorkbenchPos(e, false);
- const service = qx.data.marshal.Json.createModel(osparc.service.Utils.getFilePicker());
+ const service = qx.data.marshal.Json.createModel(osparc.store.Services.getFilePicker());
const nodeUI = await this.__addNode(service, pos);
if (nodeUI) {
const node = nodeUI.getNode();
diff --git a/services/web/server/src/simcore_service_webserver/api/v0/openapi.yaml b/services/web/server/src/simcore_service_webserver/api/v0/openapi.yaml
index cd57f9576b35..a2a2f0735c05 100644
--- a/services/web/server/src/simcore_service_webserver/api/v0/openapi.yaml
+++ b/services/web/server/src/simcore_service_webserver/api/v0/openapi.yaml
@@ -2027,7 +2027,7 @@ paths:
content:
application/json:
schema:
- $ref: '#/components/schemas/Page_CatalogServiceListItem_'
+ $ref: '#/components/schemas/Page_CatalogLatestServiceGet_'
/v0/catalog/services/{service_key}/{service_version}:
get:
tags:
@@ -7855,7 +7855,7 @@ components:
- default
- items
title: BootOption
- CatalogServiceGet:
+ CatalogLatestServiceGet:
properties:
key:
type: string
@@ -7914,11 +7914,9 @@ components:
inputs:
type: object
title: Inputs
- description: inputs with extended information
outputs:
type: object
title: Outputs
- description: outputs with extended information
bootOptions:
anyOf:
- type: object
@@ -7944,19 +7942,12 @@ components:
type: array
- type: 'null'
title: Classifiers
- default: []
quality:
type: object
title: Quality
- default: {}
- history:
- items:
- $ref: '#/components/schemas/ServiceRelease'
- type: array
- title: History
- description: history of releases for this service at this point in time,
- starting from the newest to the oldest. It includes current release.
- default: []
+ release:
+ $ref: '#/components/schemas/ServiceRelease'
+ description: release information of current (latest) service
type: object
required:
- key
@@ -7970,7 +7961,8 @@ components:
- inputs
- outputs
- accessRights
- title: CatalogServiceGet
+ - release
+ title: CatalogLatestServiceGet
example:
accessRights:
'1':
@@ -7984,61 +7976,105 @@ components:
contact: contact@acme.com
description: A service which awaits for time to pass, two times.
description_ui: true
- history:
- - released: '2024-07-20T15:00:00'
- version: 2.2.1
- version_display: Summer Release
- - compatibility:
- canUpdateTo:
- version: 2.2.1
- version: 2.0.0
- - version: 0.9.11
- - version: 0.9.10
- - compatibility:
- canUpdateTo:
- version: 0.9.11
- version: 0.9.8
- - compatibility:
- can_update_to:
- version: 0.9.11
- released: '2024-01-20T18:49:17'
- version: 0.9.1
- versionDisplay: Matterhorn
- - retired: '2024-07-20T15:00:00'
- version: 0.9.0
- - version: 0.8.0
- - version: 0.1.0
icon: https://cdn-icons-png.flaticon.com/512/25/25231.png
inputs:
- input0:
- contentSchema:
- title: Acceleration
- type: number
- x_unit: m/s**2
- description: acceleration with units
+ input_1:
+ description: Pick a file containing only one integer
+ displayOrder: 1
+ fileToKeyMap:
+ single_number.txt: input_1
keyId: input_1
- label: Acceleration
+ label: File with int number
+ type: data:text/plain
+ input_2:
+ contentSchema:
+ minimum: 0
+ title: Sleep interval
+ type: integer
+ x_unit: second
+ defaultValue: 2
+ description: Choose an amount of time to sleep in range [0:]
+ displayOrder: 2
+ keyId: input_2
+ label: Sleep interval
type: ref_contentSchema
- unitLong: meter/second3
- unitShort: m/s3
+ unitLong: second
+ unitShort: s
+ input_3:
+ defaultValue: false
+ description: If set to true will cause service to fail after it sleeps
+ displayOrder: 3
+ keyId: input_3
+ label: Fail after sleep
+ type: boolean
+ input_4:
+ contentSchema:
+ title: Distance to bed
+ type: integer
+ x_unit: meter
+ defaultValue: 0
+ description: It will first walk the distance to bed
+ displayOrder: 4
+ keyId: input_4
+ label: Distance to bed
+ type: ref_contentSchema
+ unitLong: meter
+ unitShort: m
+ input_5:
+ contentSchema:
+ minimum: 0
+ title: Dream of the night
+ type: integer
+ x_unit: byte
+ defaultValue: 0
+ description: Defines the size of the dream that will be generated [0:]
+ displayOrder: 5
+ keyId: input_5
+ label: Dream (or nightmare) of the night
+ type: ref_contentSchema
+ unitLong: byte
+ unitShort: B
key: simcore/services/comp/itis/sleeper
name: sleeper
outputs:
- outFile:
- description: Time the service waited before completion
+ output_1:
+ description: Integer is generated in range [1-9]
+ displayOrder: 1
+ fileToKeyMap:
+ single_number.txt: output_1
+ keyId: output_1
+ label: File containing one random integer
+ type: data:text/plain
+ output_2:
+ contentSchema:
+ title: Random sleep interval
+ type: integer
+ x_unit: second
+ description: Interval is generated in range [1-9]
displayOrder: 2
keyId: output_2
- label: Time Slept
- type: number
- unit: second
- unitLong: seconds
- unitShort: sec
+ label: Random sleep interval
+ type: ref_contentSchema
+ unitLong: second
+ unitShort: s
+ output_3:
+ description: Contains some random data representing a dream
+ displayOrder: 3
+ fileToKeyMap:
+ dream.txt: output_3
+ keyId: output_3
+ label: Dream output
+ type: data:text/plain
owner: owner@acme.com
quality: {}
+ release:
+ released: '2025-07-20T15:00:00'
+ version: 2.2.1
+ version_display: Summer Release
type: computational
version: 2.2.1
version_display: 2 Xtreme
- CatalogServiceListItem:
+ CatalogServiceGet:
properties:
key:
type: string
@@ -8097,9 +8133,11 @@ components:
inputs:
type: object
title: Inputs
+ description: inputs with extended information
outputs:
type: object
title: Outputs
+ description: outputs with extended information
bootOptions:
anyOf:
- type: object
@@ -8125,20 +8163,17 @@ components:
type: array
- type: 'null'
title: Classifiers
- default: []
quality:
type: object
title: Quality
- default: {}
history:
items:
$ref: '#/components/schemas/ServiceRelease'
type: array
title: History
- description: History will be replaced by current 'release' instead
+ description: history of releases for this service at this point in time,
+ starting from the newest to the oldest. It includes current release.
default: []
- deprecated: true
- additionalProperties: false
type: object
required:
- key
@@ -8152,7 +8187,74 @@ components:
- inputs
- outputs
- accessRights
- title: CatalogServiceListItem
+ title: CatalogServiceGet
+ example:
+ accessRights:
+ '1':
+ execute: true
+ write: false
+ authors:
+ - affiliation: ACME
+ email: author@acme.com
+ name: Author Bar
+ classifiers: []
+ contact: contact@acme.com
+ description: A service which awaits for time to pass, two times.
+ description_ui: true
+ history:
+ - released: '2024-07-21T15:00:00'
+ version: 2.2.1
+ version_display: Summer Release
+ - compatibility:
+ canUpdateTo:
+ version: 2.2.1
+ version: 2.0.0
+ - version: 0.9.11
+ - version: 0.9.10
+ - compatibility:
+ canUpdateTo:
+ version: 0.9.11
+ version: 0.9.8
+ - compatibility:
+ can_update_to:
+ version: 0.9.11
+ released: '2024-01-20T18:49:17'
+ version: 0.9.1
+ versionDisplay: Matterhorn
+ - retired: '2024-07-20T16:00:00'
+ version: 0.9.0
+ - version: 0.8.0
+ - version: 0.1.0
+ icon: https://cdn-icons-png.flaticon.com/512/25/25231.png
+ inputs:
+ input0:
+ contentSchema:
+ title: Acceleration
+ type: number
+ x_unit: m/s**2
+ description: acceleration with units
+ keyId: input_1
+ label: Acceleration
+ type: ref_contentSchema
+ unitLong: meter/second3
+ unitShort: m/s3
+ key: simcore/services/comp/itis/sleeper
+ name: sleeper
+ outputs:
+ outFile:
+ description: Time the service waited before completion
+ displayOrder: 2
+ keyId: output_2
+ label: Time Slept
+ type: number
+ unit: second
+ unitLong: seconds
+ unitShort: sec
+ owner: owner@acme.com
+ quality: {}
+ type: computational
+ version: 2.2.1
+ version_display: 2 Xtreme
CatalogServiceUpdate:
properties:
name:
@@ -12391,7 +12493,7 @@ components:
- total
- count
title: PageMetaInfoLimitOffset
- Page_CatalogServiceListItem_:
+ Page_CatalogLatestServiceGet_:
properties:
_meta:
$ref: '#/components/schemas/PageMetaInfoLimitOffset'
@@ -12399,7 +12501,7 @@ components:
$ref: '#/components/schemas/PageLinks'
data:
items:
- $ref: '#/components/schemas/CatalogServiceListItem'
+ $ref: '#/components/schemas/CatalogLatestServiceGet'
type: array
title: Data
additionalProperties: false
@@ -12408,7 +12510,7 @@ components:
- _meta
- _links
- data
- title: Page[CatalogServiceListItem]
+ title: Page[CatalogLatestServiceGet]
Page_LicensedItemPurchaseGet_:
properties:
_meta:
diff --git a/services/web/server/src/simcore_service_webserver/catalog/_controller_rest.py b/services/web/server/src/simcore_service_webserver/catalog/_controller_rest.py
index b4d14c41991e..644edb14d9ae 100644
--- a/services/web/server/src/simcore_service_webserver/catalog/_controller_rest.py
+++ b/services/web/server/src/simcore_service_webserver/catalog/_controller_rest.py
@@ -12,6 +12,7 @@
from aiohttp import web
from aiohttp.web import Request, RouteTableDef
from models_library.api_schemas_webserver.catalog import (
+ CatalogLatestServiceGet,
CatalogServiceGet,
CatalogServiceUpdate,
)
@@ -83,7 +84,7 @@ async def list_services_latest(request: Request):
assert page_meta.limit == query_params.limit # nosec
assert page_meta.offset == query_params.offset # nosec
- page = Page[CatalogServiceGet].model_validate(
+ page = Page[CatalogLatestServiceGet].model_validate(
paginate_data(
chunk=page_items,
request_url=request.url,
diff --git a/services/web/server/tests/unit/with_dbs/01/test_catalog_handlers__services.py b/services/web/server/tests/unit/with_dbs/01/test_catalog_handlers__services.py
index 171537099216..e005192edaea 100644
--- a/services/web/server/tests/unit/with_dbs/01/test_catalog_handlers__services.py
+++ b/services/web/server/tests/unit/with_dbs/01/test_catalog_handlers__services.py
@@ -11,7 +11,7 @@
from aiohttp.test_utils import TestClient
from aioresponses import aioresponses as AioResponsesMock
from faker import Faker
-from models_library.api_schemas_catalog.services import ServiceGetV2
+from models_library.api_schemas_catalog.services import LatestServiceGet, ServiceGetV2
from models_library.api_schemas_webserver.catalog import (
CatalogServiceGet,
CatalogServiceUpdate,
@@ -63,12 +63,12 @@ async def _list(
assert product_name
assert user_id
- items = TypeAdapter(list[ServiceGetV2]).validate_python(
- ServiceGetV2.model_json_schema()["examples"],
+ items = TypeAdapter(list[LatestServiceGet]).validate_python(
+ LatestServiceGet.model_json_schema()["examples"],
)
total_count = len(items)
- return PageRpc[ServiceGetV2].create(
+ return PageRpc[LatestServiceGet].create(
items[offset : offset + limit],
total=total_count,
limit=limit,