From c1762e2c8a959e875742b2c57363c3acb65a5aec Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Wed, 27 Nov 2024 18:29:26 +0100 Subject: [PATCH 01/33] VIP Store --- .../source/class/osparc/vipStore/VIPStore.js | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js diff --git a/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js b/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js new file mode 100644 index 00000000000..fd2b3db1340 --- /dev/null +++ b/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js @@ -0,0 +1,67 @@ +/* ************************************************************************ + + osparc - the simcore frontend + + https://osparc.io + + Copyright: + 2024 IT'IS Foundation, https://itis.swiss + + License: + MIT: https://opensource.org/licenses/MIT + + Authors: + * Odei Maiz (odeimaiz) + +************************************************************************ */ + +qx.Class.define("osparc.vipCenter.VIPStore", { + extend: osparc.ui.window.Window, + type: "singleton", + + construct: function() { + this.base(arguments, this.tr("VIP Store")); + + this.set({ + layout: new qx.ui.layout.VBox(10), + maxWidth: this.self().MAX_WIDTH, + maxHeight: this.self().MAX_HEIGHT, + contentPadding: this.self().PADDING, + resizable: true, + showMaximize: false, + showMinimize: false, + centerOnAppear: true, + clickAwayClose: true, + modal: true + }); + const closeBtn = this.getChildControl("close-button"); + osparc.utils.Utils.setIdToWidget(closeBtn, "vipStoreWindowCloseBtn"); + + this.__buildLayout(); + }, + + statics: { + MAX_WIDTH: 700, + MAX_HEIGHT: 700, + PADDING: 15, + }, + + members: { + __dummyViewer: null, + __anatomicalModelsRaw: null, + + __buildLayout: async function() { + this.__dummyViewer = new osparc.ui.basic.JsonTreeWidget(); + this._add(this.__dummyViewer); + + // fetch data + const resp = await fetch("https://itis.swiss/PD_DirectDownload/getDownloadableItems/AnatomicalModels", {method:"POST"}); + const anatomicalModelsRaw = this.__anatomicalModelsRaw = await resp.json(); + this.__populateModels(anatomicalModelsRaw); + }, + + __populateModels: function(anatomicalModels) { + this.__dummyViewer.setData(anatomicalModels); + }, + } +}); From cf85791dae703530ac3a1c829f7f45ebf9e07122 Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Wed, 27 Nov 2024 18:34:52 +0100 Subject: [PATCH 02/33] open vip store --- .../client/source/class/osparc/navigation/UserMenu.js | 11 +++++++++++ .../client/source/class/osparc/vipStore/VIPStore.js | 8 ++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/services/static-webserver/client/source/class/osparc/navigation/UserMenu.js b/services/static-webserver/client/source/class/osparc/navigation/UserMenu.js index e4798ed1464..7024d38aafa 100644 --- a/services/static-webserver/client/source/class/osparc/navigation/UserMenu.js +++ b/services/static-webserver/client/source/class/osparc/navigation/UserMenu.js @@ -103,6 +103,11 @@ qx.Class.define("osparc.navigation.UserMenu", { control.addListener("execute", () => osparc.cluster.Utils.popUpClustersDetails(), this); this.add(control); break; + case "vip-store": + control = new qx.ui.menu.Button(this.tr("VIP Store")); + control.addListener("execute", () => osparc.vipStore.VIPStore.getInstance().open()); + this.add(control); + break; case "about": control = new qx.ui.menu.Button(this.tr("About oSPARC")); osparc.utils.Utils.setIdToWidget(control, "userMenuAboutBtn"); @@ -178,6 +183,12 @@ qx.Class.define("osparc.navigation.UserMenu", { this.addSeparator(); this.__addAnnouncements(); + + if (osparc.product.Utils.isProduct("osparc")) { + this.addSeparator(); + this.getChildControl("vip-store"); + } + this.getChildControl("about"); if (osparc.product.Utils.showAboutProduct()) { this.getChildControl("about-product"); diff --git a/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js b/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js index fd2b3db1340..507180d0350 100644 --- a/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js +++ b/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js @@ -15,7 +15,7 @@ ************************************************************************ */ -qx.Class.define("osparc.vipCenter.VIPStore", { +qx.Class.define("osparc.vipStore.VIPStore", { extend: osparc.ui.window.Window, type: "singleton", @@ -23,7 +23,7 @@ qx.Class.define("osparc.vipCenter.VIPStore", { this.base(arguments, this.tr("VIP Store")); this.set({ - layout: new qx.ui.layout.VBox(10), + layout: new qx.ui.layout.HBox(10), maxWidth: this.self().MAX_WIDTH, maxHeight: this.self().MAX_HEIGHT, contentPadding: this.self().PADDING, @@ -41,7 +41,7 @@ qx.Class.define("osparc.vipCenter.VIPStore", { }, statics: { - MAX_WIDTH: 700, + MAX_WIDTH: 900, MAX_HEIGHT: 700, PADDING: 15, }, @@ -61,7 +61,7 @@ qx.Class.define("osparc.vipCenter.VIPStore", { }, __populateModels: function(anatomicalModels) { - this.__dummyViewer.setData(anatomicalModels); + this.__dummyViewer.setJson(anatomicalModels); }, } }); From f5d66519890a81448dc87c44a7b2dd9b19164e9c Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Wed, 27 Nov 2024 18:35:43 +0100 Subject: [PATCH 03/33] minor --- .../client/source/class/osparc/navigation/UserMenu.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/services/static-webserver/client/source/class/osparc/navigation/UserMenu.js b/services/static-webserver/client/source/class/osparc/navigation/UserMenu.js index 7024d38aafa..e95c0cd92c8 100644 --- a/services/static-webserver/client/source/class/osparc/navigation/UserMenu.js +++ b/services/static-webserver/client/source/class/osparc/navigation/UserMenu.js @@ -185,7 +185,6 @@ qx.Class.define("osparc.navigation.UserMenu", { this.__addAnnouncements(); if (osparc.product.Utils.isProduct("osparc")) { - this.addSeparator(); this.getChildControl("vip-store"); } @@ -252,6 +251,11 @@ qx.Class.define("osparc.navigation.UserMenu", { this.addSeparator(); this.__addAnnouncements(); + + if (osparc.product.Utils.isProduct("osparc")) { + this.getChildControl("vip-store"); + } + this.getChildControl("about"); if (!osparc.product.Utils.isProduct("osparc")) { this.getChildControl("about-product"); From 52fc036ab7f9c52f1c682005e00814501246151c Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Wed, 27 Nov 2024 19:05:16 +0100 Subject: [PATCH 04/33] list models --- .../osparc/vipStore/AnatomicModelListItem.js | 174 ++++++++++++++++++ .../source/class/osparc/vipStore/VIPStore.js | 47 ++++- 2 files changed, 215 insertions(+), 6 deletions(-) create mode 100644 services/static-webserver/client/source/class/osparc/vipStore/AnatomicModelListItem.js diff --git a/services/static-webserver/client/source/class/osparc/vipStore/AnatomicModelListItem.js b/services/static-webserver/client/source/class/osparc/vipStore/AnatomicModelListItem.js new file mode 100644 index 00000000000..92d471ab543 --- /dev/null +++ b/services/static-webserver/client/source/class/osparc/vipStore/AnatomicModelListItem.js @@ -0,0 +1,174 @@ +/* ************************************************************************ + + osparc - the simcore frontend + + https://osparc.io + + Copyright: + 2024 IT'IS Foundation, https://itis.swiss + + License: + MIT: https://opensource.org/licenses/MIT + + Authors: + * Odei Maiz (odeimaiz) + +************************************************************************ */ + +qx.Class.define("osparc.vipStore.AnatomicModelListItem", { + extend: qx.ui.core.Widget, + implement : [qx.ui.form.IModel, osparc.filter.IFilterable], + include : [qx.ui.form.MModelProperty, osparc.filter.MFilterable], + + construct: function() { + this.base(arguments); + + const layout = new qx.ui.layout.Grid(8, 1); + layout.setColumnWidth(0, 32); + layout.setRowFlex(0, 1); + layout.setColumnFlex(1, 1); + layout.setColumnAlign(0, "center", "middle"); + layout.setColumnAlign(2, "center", "middle"); + this._setLayout(layout); + + this.set({ + padding: 5, + minHeight: 48, + alignY: "middle", + }); + + this.addListener("pointerover", this._onPointerOver, this); + this.addListener("pointerout", this._onPointerOut, this); + }, + + events: { + /** (Fired by {@link qx.ui.form.List}) */ + "action" : "qx.event.type.Event" + }, + + properties: { + appearance: { + refine: true, + init: "selectable" + }, + + modelId: { + check: "String", + init: null, + nullable: false, + event: "changemodelId", + }, + + thumbnail: { + check: "String", + init: null, + nullable: true, + event: "changeThumbnail", + apply: "__applyThumbnail", + }, + + name: { + check: "String", + init: null, + nullable: false, + event: "changeName", + apply: "__applyName", + }, + + date: { + check: "Date", + init: null, + nullable: true, + event: "changeDate", + }, + }, + + members: { // eslint-disable-line qx-rules/no-refs-in-members + // overridden + _forwardStates: { + focused : true, + hovered : true, + selected : true, + dragover : true + }, + + _createChildControlImpl: function(id) { + let control; + switch (id) { + case "thumbnail": + control = new qx.ui.basic.Image().set({ + alignY: "middle", + scale: true, + allowGrowX: true, + allowGrowY: true, + allowShrinkX: true, + allowShrinkY: true, + maxWidth: 32, + maxHeight: 32 + }); + this._add(control, { + row: 0, + column: 0, + rowSpan: 2 + }); + break; + case "name": + control = new qx.ui.basic.Label().set({ + font: "text-14" + }); + this._add(control, { + row: 0, + column: 1 + }); + break; + } + + return control || this.base(arguments, id); + }, + + __applyThumbnail: function(value) { + this.getChildControl("thumbnail").setSource(value); + }, + + __applyName: function(value) { + this.getChildControl("name").setValue(value); + }, + + + + _onPointerOver: function() { + this.addState("hovered"); + }, + + _onPointerOut : function() { + this.removeState("hovered"); + }, + + _filter: function() { + this.exclude(); + }, + + _unfilter: function() { + this.show(); + }, + + _shouldApplyFilter: function(data) { + if (data.text) { + const checks = [ + this.getName(), + ]; + if (checks.filter(check => check && check.toLowerCase().trim().includes(data.text)).length == 0) { + return true; + } + } + return false; + }, + + _shouldReactToFilter: function(data) { + if (data.text && data.text.length > 1) { + return true; + } + return false; + } + } +}); diff --git a/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js b/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js index 507180d0350..0b62d12a2b6 100644 --- a/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js +++ b/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js @@ -47,21 +47,56 @@ qx.Class.define("osparc.vipStore.VIPStore", { }, members: { - __dummyViewer: null, __anatomicalModelsRaw: null, + __anatomicalModelsModel: null, __buildLayout: async function() { - this.__dummyViewer = new osparc.ui.basic.JsonTreeWidget(); - this._add(this.__dummyViewer); + const modelsUIList = new qx.ui.form.List().set({ + decorator: "no-border", + spacing: 3, + width: 250 + }); + this._add(modelsUIList) + + const anatomicalModelsModel = this.__anatomicalModelsModel = new qx.data.Array(); + const membersCtrl = new qx.data.controller.List(anatomicalModelsModel, modelsUIList, "name"); + membersCtrl.setDelegate({ + createItem: () => new osparc.vipStore.AnatomicModelListItem(), + bindItem: (ctrl, item, id) => { + ctrl.bindProperty("id", "modelId", null, item, id); + ctrl.bindProperty("thumbnail", "thumbnail", null, item, id); + ctrl.bindProperty("name", "name", null, item, id); + ctrl.bindProperty("date", "date", null, item, id); + }, + }); // fetch data const resp = await fetch("https://itis.swiss/PD_DirectDownload/getDownloadableItems/AnatomicalModels", {method:"POST"}); - const anatomicalModelsRaw = this.__anatomicalModelsRaw = await resp.json(); + const anatomicalModelsRaw = await resp.json(); this.__populateModels(anatomicalModelsRaw); }, - __populateModels: function(anatomicalModels) { - this.__dummyViewer.setJson(anatomicalModels); + __populateModels: function(anatomicalModelsRaw) { + const anatomicalModels = this.__anatomicalModels = anatomicalModelsRaw["availableDownloads"]; + + const anatomicalModelsModel = this.__anatomicalModelsModel; + anatomicalModelsModel.removeAll(); + + anatomicalModels.forEach(anatomicalModelData => { + // this is a JSON but it's missing the quotes + const rawData = anatomicalModelData["Features"]; + let formattedData = rawData + .replace(/([a-zA-Z0-9_]+):/g, '"$1":') // Add quotes around keys + .replace(/: ([^,{}]+)/g, ': "$1"'); // Add quotes around all values + + features = JSON.parse(formattedData); + const anatomicalModel = {}; + anatomicalModel["id"] = anatomicalModelData["ID"]; + anatomicalModel["thumbnail"] = anatomicalModelData["Thumbnail"]; + anatomicalModel["name"] = features["name"]; + anatomicalModel["date"] = new Date(features["date"]); + anatomicalModelsModel.append(qx.data.marshal.Json.createModel(anatomicalModel)); + }); }, } }); From 2745cf6f0ea53c749c8dc509c7381ad532b1b47f Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Wed, 27 Nov 2024 19:09:02 +0100 Subject: [PATCH 05/33] minor --- .../source/class/osparc/vipStore/AnatomicModelListItem.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/services/static-webserver/client/source/class/osparc/vipStore/AnatomicModelListItem.js b/services/static-webserver/client/source/class/osparc/vipStore/AnatomicModelListItem.js index 92d471ab543..c1ac90ce8d1 100644 --- a/services/static-webserver/client/source/class/osparc/vipStore/AnatomicModelListItem.js +++ b/services/static-webserver/client/source/class/osparc/vipStore/AnatomicModelListItem.js @@ -23,12 +23,12 @@ qx.Class.define("osparc.vipStore.AnatomicModelListItem", { construct: function() { this.base(arguments); - const layout = new qx.ui.layout.Grid(8, 1); - layout.setColumnWidth(0, 32); + const layout = new qx.ui.layout.Grid(5, 5); + layout.setColumnWidth(0, 64); layout.setRowFlex(0, 1); layout.setColumnFlex(1, 1); layout.setColumnAlign(0, "center", "middle"); - layout.setColumnAlign(2, "center", "middle"); + layout.setColumnAlign(1, "center", "middle"); this._setLayout(layout); this.set({ From ae788940ac880ca2a5abb6e60a7870b76c842bf6 Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Wed, 27 Nov 2024 19:17:18 +0100 Subject: [PATCH 06/33] minor --- .../source/class/osparc/vipStore/AnatomicModelListItem.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/static-webserver/client/source/class/osparc/vipStore/AnatomicModelListItem.js b/services/static-webserver/client/source/class/osparc/vipStore/AnatomicModelListItem.js index c1ac90ce8d1..77c565c9f7d 100644 --- a/services/static-webserver/client/source/class/osparc/vipStore/AnatomicModelListItem.js +++ b/services/static-webserver/client/source/class/osparc/vipStore/AnatomicModelListItem.js @@ -28,7 +28,7 @@ qx.Class.define("osparc.vipStore.AnatomicModelListItem", { layout.setRowFlex(0, 1); layout.setColumnFlex(1, 1); layout.setColumnAlign(0, "center", "middle"); - layout.setColumnAlign(1, "center", "middle"); + layout.setColumnAlign(1, "left", "middle"); this._setLayout(layout); this.set({ From 81e050c08d3334cf4e983708ef741c094b70f067 Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Thu, 28 Nov 2024 09:57:55 +0100 Subject: [PATCH 07/33] parse Features --- .../source/class/osparc/vipStore/VIPStore.js | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js b/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js index 0b62d12a2b6..6fda33756a0 100644 --- a/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js +++ b/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js @@ -84,12 +84,15 @@ qx.Class.define("osparc.vipStore.VIPStore", { anatomicalModels.forEach(anatomicalModelData => { // this is a JSON but it's missing the quotes - const rawData = anatomicalModelData["Features"]; - let formattedData = rawData - .replace(/([a-zA-Z0-9_]+):/g, '"$1":') // Add quotes around keys - .replace(/: ([^,{}]+)/g, ': "$1"'); // Add quotes around all values - - features = JSON.parse(formattedData); + let featuresRaw = anatomicalModelData["Features"]; + featuresRaw = featuresRaw.substring(1, featuresRaw.length-1); // remove brackets + featuresRaw = featuresRaw.split(","); // split the string by commas + const features = {}; + featuresRaw.forEach(pair => { // each pair is "key: value" + const keyValue = pair.split(":"); + features[keyValue[0].trim()] = keyValue[1].trim() + }); + const anatomicalModel = {}; anatomicalModel["id"] = anatomicalModelData["ID"]; anatomicalModel["thumbnail"] = anatomicalModelData["Thumbnail"]; From 8d6ef134b1c8faf74196da12815330fe06417a94 Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Thu, 28 Nov 2024 11:47:53 +0100 Subject: [PATCH 08/33] Details --- .../osparc/vipStore/AnatomicalModelDetails.js | 52 +++++++++++++++++++ ...ListItem.js => AnatomicalModelListItem.js} | 2 +- .../source/class/osparc/vipStore/VIPStore.js | 11 ++-- 3 files changed, 61 insertions(+), 4 deletions(-) create mode 100644 services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelDetails.js rename services/static-webserver/client/source/class/osparc/vipStore/{AnatomicModelListItem.js => AnatomicalModelListItem.js} (98%) diff --git a/services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelDetails.js b/services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelDetails.js new file mode 100644 index 00000000000..44cd23e74ef --- /dev/null +++ b/services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelDetails.js @@ -0,0 +1,52 @@ +/* ************************************************************************ + + osparc - the simcore frontend + + https://osparc.io + + Copyright: + 2024 IT'IS Foundation, https://itis.swiss + + License: + MIT: https://opensource.org/licenses/MIT + + Authors: + * Odei Maiz (odeimaiz) + +************************************************************************ */ + +qx.Class.define("osparc.vipStore.AnatomicalModelDetails", { + extend: qx.ui.core.Widget, + + construct: function() { + this.base(arguments); + + const layout = new qx.ui.layout.Grid(10, 10); + layout.setColumnWidth(0, 64); + layout.setRowFlex(0, 1); + layout.setColumnFlex(1, 1); + layout.setColumnAlign(0, "center", "middle"); + layout.setColumnAlign(1, "left", "middle"); + this._setLayout(layout); + + this.set({ + padding: 5, + }); + }, + + properties: { + anatomicalModelsData: { + check: "String", + init: null, + nullable: false, + apply: "__poplulateLayout" + }, + }, + + members: { + + __poplulateLayout: function() { + this.getChildControl("thumbnail").setSource(value); + }, + } +}); diff --git a/services/static-webserver/client/source/class/osparc/vipStore/AnatomicModelListItem.js b/services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelListItem.js similarity index 98% rename from services/static-webserver/client/source/class/osparc/vipStore/AnatomicModelListItem.js rename to services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelListItem.js index 77c565c9f7d..83fd9856a1c 100644 --- a/services/static-webserver/client/source/class/osparc/vipStore/AnatomicModelListItem.js +++ b/services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelListItem.js @@ -15,7 +15,7 @@ ************************************************************************ */ -qx.Class.define("osparc.vipStore.AnatomicModelListItem", { +qx.Class.define("osparc.vipStore.AnatomicalModelListItem", { extend: qx.ui.core.Widget, implement : [qx.ui.form.IModel, osparc.filter.IFilterable], include : [qx.ui.form.MModelProperty, osparc.filter.MFilterable], diff --git a/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js b/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js index 6fda33756a0..0ef1f36af96 100644 --- a/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js +++ b/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js @@ -24,8 +24,8 @@ qx.Class.define("osparc.vipStore.VIPStore", { this.set({ layout: new qx.ui.layout.HBox(10), - maxWidth: this.self().MAX_WIDTH, - maxHeight: this.self().MAX_HEIGHT, + minWidth: this.self().MAX_WIDTH, + minHeight: this.self().MAX_HEIGHT, contentPadding: this.self().PADDING, resizable: true, showMaximize: false, @@ -61,7 +61,7 @@ qx.Class.define("osparc.vipStore.VIPStore", { const anatomicalModelsModel = this.__anatomicalModelsModel = new qx.data.Array(); const membersCtrl = new qx.data.controller.List(anatomicalModelsModel, modelsUIList, "name"); membersCtrl.setDelegate({ - createItem: () => new osparc.vipStore.AnatomicModelListItem(), + createItem: () => new osparc.vipStore.AnatomicalModelListItem(), bindItem: (ctrl, item, id) => { ctrl.bindProperty("id", "modelId", null, item, id); ctrl.bindProperty("thumbnail", "thumbnail", null, item, id); @@ -70,6 +70,11 @@ qx.Class.define("osparc.vipStore.VIPStore", { }, }); + const anatomicModelDetails = new osparc.vipStore.AnatomicalModelDetails(); + this._add(anatomicModelDetails, { + flex: 1 + }); + // fetch data const resp = await fetch("https://itis.swiss/PD_DirectDownload/getDownloadableItems/AnatomicalModels", {method:"POST"}); const anatomicalModelsRaw = await resp.json(); From 6914ccb9d91f25db3fcebfa30f04b4ede3f34251 Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Thu, 28 Nov 2024 13:55:10 +0100 Subject: [PATCH 09/33] working --- .../osparc/vipStore/AnatomicalModelDetails.js | 167 ++++++++++++++++-- .../vipStore/AnatomicalModelListItem.js | 2 +- .../source/class/osparc/vipStore/VIPStore.js | 94 +++++++--- 3 files changed, 223 insertions(+), 40 deletions(-) diff --git a/services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelDetails.js b/services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelDetails.js index 44cd23e74ef..cb8cba23801 100644 --- a/services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelDetails.js +++ b/services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelDetails.js @@ -21,32 +21,173 @@ qx.Class.define("osparc.vipStore.AnatomicalModelDetails", { construct: function() { this.base(arguments); - const layout = new qx.ui.layout.Grid(10, 10); - layout.setColumnWidth(0, 64); - layout.setRowFlex(0, 1); - layout.setColumnFlex(1, 1); - layout.setColumnAlign(0, "center", "middle"); - layout.setColumnAlign(1, "left", "middle"); + const layout = new qx.ui.layout.Grow(); this._setLayout(layout); - this.set({ - padding: 5, - }); + this.__poplulateLayout(); }, properties: { anatomicalModelsData: { - check: "String", + check: "Object", init: null, - nullable: false, + nullable: true, apply: "__poplulateLayout" }, }, members: { - __poplulateLayout: function() { - this.getChildControl("thumbnail").setSource(value); + this._removeAll(); + + const anatomicalModelsData = this.getAnatomicalModelsData(); + if (anatomicalModelsData) { + const card = this.__createcCard(anatomicalModelsData); + this._add(card); + } else { + const selectModelLabel = new qx.ui.basic.Label().set({ + value: this.tr("Select a model for more details"), + font: "text-16", + alignX: "center", + alignY: "middle", + allowGrowX: true, + allowGrowY: true, + }); + this._add(selectModelLabel); + } + }, + + __createcCard: function(anatomicalModelsData) { + console.log(anatomicalModelsData); + + const cardGrid = new qx.ui.layout.Grid(16, 16); + const cardLayout = new qx.ui.container.Composite(cardGrid); + + const features = anatomicalModelsData["Features"]; + + const titleLabel = new qx.ui.basic.Label().set({ + value: anatomicalModelsData["Description"], + font: "text-16", + alignX: "center", + alignY: "middle", + allowGrowX: true, + allowGrowY: true, + }); + cardLayout.add(titleLabel, { + column: 0, + row: 0, + colSpan: 2, + }); + + const nameLabel = new qx.ui.basic.Label().set({ + value: features["name"], + font: "text-16", + alignX: "center", + alignY: "middle", + allowGrowX: true, + allowGrowY: true, + }); + cardLayout.add(nameLabel, { + column: 0, + row: 1, + colSpan: 2, + }); + + const thumbnail = new qx.ui.basic.Image().set({ + source: anatomicalModelsData["Thumbnail"], + alignY: "middle", + scale: true, + allowGrowX: true, + allowGrowY: true, + allowShrinkX: true, + allowShrinkY: true, + maxWidth: 256, + maxHeight: 256, + }); + cardLayout.add(thumbnail, { + column: 0, + row: 2, + }); + + const moreInfoGrid = new qx.ui.layout.Grid(8, 8); + const moreInfoLayout = new qx.ui.container.Composite(moreInfoGrid).set({ + marginTop: 16, + }); + let idx = 0; + [ + "Name", + "Version", + "Sex", + "Weight", + "Height", + "Date", + "Ethnicity", + ].forEach(key => { + if (key.toLowerCase() in features) { + const titleLabel = new qx.ui.basic.Label().set({ + value: key, + font: "text-14", + alignX: "right", + }); + moreInfoLayout.add(titleLabel, { + column: 0, + row: idx, + }); + + const nameLabel = new qx.ui.basic.Label().set({ + value: features[key.toLowerCase()], + font: "text-14", + alignX: "left", + }); + moreInfoLayout.add(nameLabel, { + column: 1, + row: idx, + }); + + idx++; + } + }); + + const doiTitle = new qx.ui.basic.Label().set({ + value: "DOI", + font: "text-14", + alignX: "right", + marginTop: 16, + }); + moreInfoLayout.add(doiTitle, { + column: 0, + row: idx, + }); + + const doiValue = new qx.ui.basic.Label().set({ + value: anatomicalModelsData["DOI"], + font: "text-14", + alignX: "left", + marginTop: 16, + }); + moreInfoLayout.add(doiValue, { + column: 1, + row: idx, + }); + + cardLayout.add(moreInfoLayout, { + column: 1, + row: 2, + }); + + + const leaseModelButton = new qx.ui.form.Button().set({ + label: this.tr("Lease model (2 months)"), + appearance: "strong-button", + center: true, + }); + cardLayout.add(leaseModelButton, { + column: 0, + row: 3, + colSpan: 2, + }); + + return cardLayout; }, } }); diff --git a/services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelListItem.js b/services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelListItem.js index 83fd9856a1c..c91a4f57084 100644 --- a/services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelListItem.js +++ b/services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelListItem.js @@ -53,7 +53,7 @@ qx.Class.define("osparc.vipStore.AnatomicalModelListItem", { }, modelId: { - check: "String", + check: "Number", init: null, nullable: false, event: "changemodelId", diff --git a/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js b/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js index 0ef1f36af96..5e42f6da44a 100644 --- a/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js +++ b/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js @@ -23,7 +23,7 @@ qx.Class.define("osparc.vipStore.VIPStore", { this.base(arguments, this.tr("VIP Store")); this.set({ - layout: new qx.ui.layout.HBox(10), + layout: new qx.ui.layout.VBox(10), minWidth: this.self().MAX_WIDTH, minHeight: this.self().MAX_HEIGHT, contentPadding: this.self().PADDING, @@ -44,19 +44,57 @@ qx.Class.define("osparc.vipStore.VIPStore", { MAX_WIDTH: 900, MAX_HEIGHT: 700, PADDING: 15, + + curateAnatomicalModels: function(anatomicalModelsRaw) { + const anatomicalModels = []; + const models = anatomicalModelsRaw["availableDownloads"]; + models.forEach(model => { + const curatedModel = {}; + Object.keys(model).forEach(key => { + if (key === "Features") { + let featuresRaw = model["Features"]; + featuresRaw = featuresRaw.substring(1, featuresRaw.length-1); // remove brackets + featuresRaw = featuresRaw.split(","); // split the string by commas + const features = {}; + featuresRaw.forEach(pair => { // each pair is "key: value" + const keyValue = pair.split(":"); + features[keyValue[0].trim()] = keyValue[1].trim() + }); + curatedModel["Features"] = features; + } else { + curatedModel[key] = model[key]; + } + }); + anatomicalModels.push(curatedModel); + }); + return anatomicalModels; + }, }, members: { - __anatomicalModelsRaw: null, __anatomicalModelsModel: null, + __anatomicalModels: null, __buildLayout: async function() { + this._removeAll(); + + const toolbarLayout = new qx.ui.container.Composite(new qx.ui.layout.HBox(10)).set({ + maxHeight: 30 + }); + this._add(toolbarLayout); + + const modelsLayout = new qx.ui.container.Composite(new qx.ui.layout.HBox(10)); + this._add(modelsLayout, { + flex: 1 + }); + const modelsUIList = new qx.ui.form.List().set({ decorator: "no-border", - spacing: 3, - width: 250 + spacing: 5, + minWidth: 250, + maxWidth: 250 }); - this._add(modelsUIList) + modelsLayout.add(modelsUIList) const anatomicalModelsModel = this.__anatomicalModelsModel = new qx.data.Array(); const membersCtrl = new qx.data.controller.List(anatomicalModelsModel, modelsUIList, "name"); @@ -70,39 +108,43 @@ qx.Class.define("osparc.vipStore.VIPStore", { }, }); - const anatomicModelDetails = new osparc.vipStore.AnatomicalModelDetails(); - this._add(anatomicModelDetails, { + const anatomicModelDetails = new osparc.vipStore.AnatomicalModelDetails().set({ + padding: 20, + }); + modelsLayout.add(anatomicModelDetails, { flex: 1 }); + modelsUIList.addListener("changeSelection", e => { + const selection = e.getData(); + if (selection.length) { + const modelId = selection[0].getModelId(); + const modelFound = this.__anatomicalModels.find(anatomicalModel => anatomicalModel["ID"] === modelId); + if (modelFound) { + anatomicModelDetails.setAnatomicalModelsData(modelFound); + return; + } + } + anatomicModelDetails.setAnatomicalModelsData(null); + }, this); + // fetch data const resp = await fetch("https://itis.swiss/PD_DirectDownload/getDownloadableItems/AnatomicalModels", {method:"POST"}); const anatomicalModelsRaw = await resp.json(); - this.__populateModels(anatomicalModelsRaw); + this.__anatomicalModels = this.self().curateAnatomicalModels(anatomicalModelsRaw); + this.__populateModels(); }, - __populateModels: function(anatomicalModelsRaw) { - const anatomicalModels = this.__anatomicalModels = anatomicalModelsRaw["availableDownloads"]; - + __populateModels: function() { const anatomicalModelsModel = this.__anatomicalModelsModel; anatomicalModelsModel.removeAll(); - - anatomicalModels.forEach(anatomicalModelData => { - // this is a JSON but it's missing the quotes - let featuresRaw = anatomicalModelData["Features"]; - featuresRaw = featuresRaw.substring(1, featuresRaw.length-1); // remove brackets - featuresRaw = featuresRaw.split(","); // split the string by commas - const features = {}; - featuresRaw.forEach(pair => { // each pair is "key: value" - const keyValue = pair.split(":"); - features[keyValue[0].trim()] = keyValue[1].trim() - }); + this.__anatomicalModels.forEach(model => { const anatomicalModel = {}; - anatomicalModel["id"] = anatomicalModelData["ID"]; - anatomicalModel["thumbnail"] = anatomicalModelData["Thumbnail"]; - anatomicalModel["name"] = features["name"]; - anatomicalModel["date"] = new Date(features["date"]); + anatomicalModel["id"] = model["ID"]; + anatomicalModel["thumbnail"] = model["Thumbnail"]; + anatomicalModel["name"] = model["Features"]["name"]; + anatomicalModel["date"] = new Date(model["Features"]["date"]); anatomicalModelsModel.append(qx.data.marshal.Json.createModel(anatomicalModel)); }); }, From d72a8ee94a30c8980eb923e21f824e0a9ddd5cca Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Thu, 28 Nov 2024 14:13:03 +0100 Subject: [PATCH 10/33] sorted with thumbnail --- .../osparc/vipStore/AnatomicalModelDetails.js | 46 +++++++------------ .../source/class/osparc/vipStore/VIPStore.js | 17 ++++--- 2 files changed, 25 insertions(+), 38 deletions(-) diff --git a/services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelDetails.js b/services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelDetails.js index cb8cba23801..494ddc2e577 100644 --- a/services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelDetails.js +++ b/services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelDetails.js @@ -65,32 +65,21 @@ qx.Class.define("osparc.vipStore.AnatomicalModelDetails", { const features = anatomicalModelsData["Features"]; - const titleLabel = new qx.ui.basic.Label().set({ - value: anatomicalModelsData["Description"], - font: "text-16", - alignX: "center", - alignY: "middle", - allowGrowX: true, - allowGrowY: true, - }); - cardLayout.add(titleLabel, { - column: 0, - row: 0, - colSpan: 2, - }); - - const nameLabel = new qx.ui.basic.Label().set({ - value: features["name"], - font: "text-16", - alignX: "center", - alignY: "middle", - allowGrowX: true, - allowGrowY: true, - }); - cardLayout.add(nameLabel, { - column: 0, - row: 1, - colSpan: 2, + const description = anatomicalModelsData["Description"]; + description.split(" - ").forEach((desc, idx) => { + const titleLabel = new qx.ui.basic.Label().set({ + value: desc, + font: "text-16", + alignX: "center", + alignY: "middle", + allowGrowX: true, + allowGrowY: true, + }); + cardLayout.add(titleLabel, { + column: 0, + row: idx, + colSpan: 2, + }); }); const thumbnail = new qx.ui.basic.Image().set({ @@ -110,14 +99,13 @@ qx.Class.define("osparc.vipStore.AnatomicalModelDetails", { }); const moreInfoGrid = new qx.ui.layout.Grid(8, 8); - const moreInfoLayout = new qx.ui.container.Composite(moreInfoGrid).set({ - marginTop: 16, - }); + const moreInfoLayout = new qx.ui.container.Composite(moreInfoGrid); let idx = 0; [ "Name", "Version", "Sex", + "Age", "Weight", "Height", "Date", diff --git a/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js b/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js index 5e42f6da44a..6b168c043b3 100644 --- a/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js +++ b/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js @@ -24,6 +24,7 @@ qx.Class.define("osparc.vipStore.VIPStore", { this.set({ layout: new qx.ui.layout.VBox(10), + width: this.self().MAX_WIDTH, minWidth: this.self().MAX_WIDTH, minHeight: this.self().MAX_HEIGHT, contentPadding: this.self().PADDING, @@ -34,8 +35,6 @@ qx.Class.define("osparc.vipStore.VIPStore", { clickAwayClose: true, modal: true }); - const closeBtn = this.getChildControl("close-button"); - osparc.utils.Utils.setIdToWidget(closeBtn, "vipStoreWindowCloseBtn"); this.__buildLayout(); }, @@ -76,8 +75,6 @@ qx.Class.define("osparc.vipStore.VIPStore", { __anatomicalModels: null, __buildLayout: async function() { - this._removeAll(); - const toolbarLayout = new qx.ui.container.Composite(new qx.ui.layout.HBox(10)).set({ maxHeight: 30 }); @@ -136,17 +133,19 @@ qx.Class.define("osparc.vipStore.VIPStore", { }, __populateModels: function() { - const anatomicalModelsModel = this.__anatomicalModelsModel; - anatomicalModelsModel.removeAll(); - + this.__anatomicalModelsModel.removeAll(); + + const models = []; this.__anatomicalModels.forEach(model => { const anatomicalModel = {}; anatomicalModel["id"] = model["ID"]; anatomicalModel["thumbnail"] = model["Thumbnail"]; - anatomicalModel["name"] = model["Features"]["name"]; + anatomicalModel["name"] = model["Features"]["name"] + " " + model["Features"]["version"]; anatomicalModel["date"] = new Date(model["Features"]["date"]); - anatomicalModelsModel.append(qx.data.marshal.Json.createModel(anatomicalModel)); + models.push(anatomicalModel); }); + models.sort((a, b) => a["name"].localeCompare(b["name"])); + models.forEach(model => this.__anatomicalModelsModel.append(qx.data.marshal.Json.createModel(model))); }, } }); From c1c8ff47230ca4ae2f867e62dc03044924056d8f Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Thu, 28 Nov 2024 14:16:51 +0100 Subject: [PATCH 11/33] aesthetics --- .../osparc/vipStore/AnatomicalModelDetails.js | 48 ++++++++++--------- .../vipStore/AnatomicalModelListItem.js | 3 +- 2 files changed, 27 insertions(+), 24 deletions(-) diff --git a/services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelDetails.js b/services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelDetails.js index 494ddc2e577..da0173505a5 100644 --- a/services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelDetails.js +++ b/services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelDetails.js @@ -136,36 +136,38 @@ qx.Class.define("osparc.vipStore.AnatomicalModelDetails", { } }); - const doiTitle = new qx.ui.basic.Label().set({ - value: "DOI", - font: "text-14", - alignX: "right", - marginTop: 16, - }); - moreInfoLayout.add(doiTitle, { - column: 0, - row: idx, - }); - - const doiValue = new qx.ui.basic.Label().set({ - value: anatomicalModelsData["DOI"], - font: "text-14", - alignX: "left", - marginTop: 16, - }); - moreInfoLayout.add(doiValue, { - column: 1, - row: idx, - }); + if (anatomicalModelsData["DOI"]) { + const doiTitle = new qx.ui.basic.Label().set({ + value: "DOI", + font: "text-14", + alignX: "right", + marginTop: 16, + }); + moreInfoLayout.add(doiTitle, { + column: 0, + row: idx, + }); + + const doiValue = new qx.ui.basic.Label().set({ + value: anatomicalModelsData["DOI"], + font: "text-14", + alignX: "left", + marginTop: 16, + }); + moreInfoLayout.add(doiValue, { + column: 1, + row: idx, + }); + } cardLayout.add(moreInfoLayout, { column: 1, row: 2, }); - + const leaseModelButton = new qx.ui.form.Button().set({ - label: this.tr("Lease model (2 months)"), + label: this.tr("Lease model (2 for months)"), appearance: "strong-button", center: true, }); diff --git a/services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelListItem.js b/services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelListItem.js index c91a4f57084..c10ecd8305c 100644 --- a/services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelListItem.js +++ b/services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelListItem.js @@ -114,7 +114,8 @@ qx.Class.define("osparc.vipStore.AnatomicalModelListItem", { break; case "name": control = new qx.ui.basic.Label().set({ - font: "text-14" + font: "text-14", + alignY: "middle", }); this._add(control, { row: 0, From 59393e8878a557c07fe2053b702c18fada7418cc Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Thu, 28 Nov 2024 16:02:05 +0100 Subject: [PATCH 12/33] showS4LStore --- .../client/source/class/osparc/navigation/UserMenu.js | 4 ++-- .../client/source/class/osparc/product/Utils.js | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/services/static-webserver/client/source/class/osparc/navigation/UserMenu.js b/services/static-webserver/client/source/class/osparc/navigation/UserMenu.js index e95c0cd92c8..1a6cd1c78e7 100644 --- a/services/static-webserver/client/source/class/osparc/navigation/UserMenu.js +++ b/services/static-webserver/client/source/class/osparc/navigation/UserMenu.js @@ -184,7 +184,7 @@ qx.Class.define("osparc.navigation.UserMenu", { this.__addAnnouncements(); - if (osparc.product.Utils.isProduct("osparc")) { + if (osparc.product.Utils.showS4LStore()) { this.getChildControl("vip-store"); } @@ -252,7 +252,7 @@ qx.Class.define("osparc.navigation.UserMenu", { this.__addAnnouncements(); - if (osparc.product.Utils.isProduct("osparc")) { + if (osparc.product.Utils.showS4LStore()) { this.getChildControl("vip-store"); } diff --git a/services/static-webserver/client/source/class/osparc/product/Utils.js b/services/static-webserver/client/source/class/osparc/product/Utils.js index 123d993e01b..84d9f132303 100644 --- a/services/static-webserver/client/source/class/osparc/product/Utils.js +++ b/services/static-webserver/client/source/class/osparc/product/Utils.js @@ -270,6 +270,14 @@ qx.Class.define("osparc.product.Utils", { return true; }, + showS4LStore: function() { + const platformName = osparc.store.StaticInfo.getInstance().getPlatformName(); + if (this.isS4LProduct() && platformName !== "production") { + return true; + } + return false; + }, + getProductThumbUrl: function(asset = "Default.png") { const base = "https://raw.githubusercontent.com/ZurichMedTech/s4l-assets/main/app/full/project_thumbnails" let url; From 8afdcae530bc5aac86afefbbb44f0b15e86ee62b Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Thu, 28 Nov 2024 16:15:56 +0100 Subject: [PATCH 13/33] minor --- .../client/source/class/osparc/product/Utils.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/services/static-webserver/client/source/class/osparc/product/Utils.js b/services/static-webserver/client/source/class/osparc/product/Utils.js index 84d9f132303..9eeb63ee900 100644 --- a/services/static-webserver/client/source/class/osparc/product/Utils.js +++ b/services/static-webserver/client/source/class/osparc/product/Utils.js @@ -272,7 +272,13 @@ qx.Class.define("osparc.product.Utils", { showS4LStore: function() { const platformName = osparc.store.StaticInfo.getInstance().getPlatformName(); - if (this.isS4LProduct() && platformName !== "production") { + if (platformName !== "master") { + return false; + } + if (this.getProductName().includes("osparc")) { + return true; + } + if (this.isS4LProduct()) { return true; } return false; From 7905a98f2e1bd0c4885a14fa2c781dc124480009 Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Thu, 28 Nov 2024 16:29:10 +0100 Subject: [PATCH 14/33] Tabbed View --- .../class/osparc/navigation/UserMenu.js | 10 ++-- .../source/class/osparc/vipStore/Store.js | 43 +++++++++++++++ .../class/osparc/vipStore/StoreWindow.js | 54 +++++++++++++++++++ .../source/class/osparc/vipStore/VIPStore.js | 25 ++------- 4 files changed, 106 insertions(+), 26 deletions(-) create mode 100644 services/static-webserver/client/source/class/osparc/vipStore/Store.js create mode 100644 services/static-webserver/client/source/class/osparc/vipStore/StoreWindow.js diff --git a/services/static-webserver/client/source/class/osparc/navigation/UserMenu.js b/services/static-webserver/client/source/class/osparc/navigation/UserMenu.js index 1a6cd1c78e7..0ee2bbabf88 100644 --- a/services/static-webserver/client/source/class/osparc/navigation/UserMenu.js +++ b/services/static-webserver/client/source/class/osparc/navigation/UserMenu.js @@ -103,9 +103,9 @@ qx.Class.define("osparc.navigation.UserMenu", { control.addListener("execute", () => osparc.cluster.Utils.popUpClustersDetails(), this); this.add(control); break; - case "vip-store": - control = new qx.ui.menu.Button(this.tr("VIP Store")); - control.addListener("execute", () => osparc.vipStore.VIPStore.getInstance().open()); + case "store": + control = new qx.ui.menu.Button(this.tr("Store")); + control.addListener("execute", () => osparc.vipStore.StoreWindow.openWindow()); this.add(control); break; case "about": @@ -185,7 +185,7 @@ qx.Class.define("osparc.navigation.UserMenu", { this.__addAnnouncements(); if (osparc.product.Utils.showS4LStore()) { - this.getChildControl("vip-store"); + this.getChildControl("store"); } this.getChildControl("about"); @@ -253,7 +253,7 @@ qx.Class.define("osparc.navigation.UserMenu", { this.__addAnnouncements(); if (osparc.product.Utils.showS4LStore()) { - this.getChildControl("vip-store"); + this.getChildControl("store"); } this.getChildControl("about"); diff --git a/services/static-webserver/client/source/class/osparc/vipStore/Store.js b/services/static-webserver/client/source/class/osparc/vipStore/Store.js new file mode 100644 index 00000000000..1bd955ab2e3 --- /dev/null +++ b/services/static-webserver/client/source/class/osparc/vipStore/Store.js @@ -0,0 +1,43 @@ +/* ************************************************************************ + + osparc - the simcore frontend + + https://osparc.io + + Copyright: + 2024 IT'IS Foundation, https://itis.swiss + + License: + MIT: https://opensource.org/licenses/MIT + + Authors: + * Odei Maiz (odeimaiz) + +************************************************************************ */ + +qx.Class.define("osparc.vipStore.Store", { + extend: osparc.ui.window.TabbedView, + + construct: function() { + this.base(arguments); + + const miniWallet = osparc.desktop.credits.BillingCenter.createMiniWalletView().set({ + paddingRight: 10 + }); + this.addWidgetOnTopOfTheTabs(miniWallet); + + this.__vipStorePage = this.__getVIPStorePage(); + }, + + members: { + __vipStorePage: null, + + __getVIPStorePage: function() { + const title = this.tr("VIP Models"); + const iconSrc = "@FontAwesome5Solid/users/22"; + const vipStoreView = new osparc.vipStore.VIPStore(); + const page = this.addTab(title, iconSrc, vipStoreView); + return page; + }, + } +}); diff --git a/services/static-webserver/client/source/class/osparc/vipStore/StoreWindow.js b/services/static-webserver/client/source/class/osparc/vipStore/StoreWindow.js new file mode 100644 index 00000000000..cb63356b81c --- /dev/null +++ b/services/static-webserver/client/source/class/osparc/vipStore/StoreWindow.js @@ -0,0 +1,54 @@ +/* ************************************************************************ + + osparc - the simcore frontend + + https://osparc.io + + Copyright: + 2024 IT'IS Foundation, https://itis.swiss + + License: + MIT: https://opensource.org/licenses/MIT + + Authors: + * Odei Maiz (odeimaiz) + +************************************************************************ */ + +qx.Class.define("osparc.vipStore.StoreWindow", { + extend: osparc.ui.window.TabbedWindow, + + construct: function() { + this.base(arguments, "store", this.tr("Store")); + + + osparc.utils.Utils.setIdToWidget(this, "storeWindow"); + + const width = 1035; + const height = 700; + this.set({ + width, + height + }) + + const vipStore = this.__vipStore = new osparc.vipStore.Store(); + this._setTabbedView(vipStore); + }, + + statics: { + openWindow: function() { + const storeWindow = new osparc.vipStore.StoreWindow(); + storeWindow.center(); + storeWindow.open(); + return storeWindow; + } + }, + + members: { + __vipStore: null, + + openVIPStore: function() { + return this.__vipStore.openVIPStore(); + }, + } +}); diff --git a/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js b/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js index 6b168c043b3..94a1b446857 100644 --- a/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js +++ b/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js @@ -16,34 +16,17 @@ ************************************************************************ */ qx.Class.define("osparc.vipStore.VIPStore", { - extend: osparc.ui.window.Window, - type: "singleton", + extend: qx.ui.core.Widget, construct: function() { - this.base(arguments, this.tr("VIP Store")); - - this.set({ - layout: new qx.ui.layout.VBox(10), - width: this.self().MAX_WIDTH, - minWidth: this.self().MAX_WIDTH, - minHeight: this.self().MAX_HEIGHT, - contentPadding: this.self().PADDING, - resizable: true, - showMaximize: false, - showMinimize: false, - centerOnAppear: true, - clickAwayClose: true, - modal: true - }); + this.base(arguments); + + this._setLayout(new qx.ui.layout.VBox(10)); this.__buildLayout(); }, statics: { - MAX_WIDTH: 900, - MAX_HEIGHT: 700, - PADDING: 15, - curateAnatomicalModels: function(anatomicalModelsRaw) { const anatomicalModels = []; const models = anatomicalModelsRaw["availableDownloads"]; From 32eff5f76d52b6d2f8f4abc7c6e8c0cb38de21ec Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Thu, 28 Nov 2024 16:33:48 +0100 Subject: [PATCH 15/33] loading --- .../client/source/class/osparc/vipStore/VIPStore.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js b/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js index 94a1b446857..bdecbf620c6 100644 --- a/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js +++ b/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js @@ -88,6 +88,13 @@ qx.Class.define("osparc.vipStore.VIPStore", { }, }); + const loadingModel = { + id: 0, + thumbnail: "@FontAwesome5Solid/spinner/32", + name: this.tr("Loading"), + }; + this.__anatomicalModelsModel.append(qx.data.marshal.Json.createModel(loadingModel)); + const anatomicModelDetails = new osparc.vipStore.AnatomicalModelDetails().set({ padding: 20, }); From ab2c4f6feade33c6265e01bf432707facc179531 Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Thu, 28 Nov 2024 16:48:00 +0100 Subject: [PATCH 16/33] filter and sort buttons --- .../osparc/dashboard/SortedByMenuButton.js | 1 + .../osparc/vipStore/SortModelsButtons.js | 101 ++++++++++++++++++ .../source/class/osparc/vipStore/VIPStore.js | 20 +++- 3 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 services/static-webserver/client/source/class/osparc/vipStore/SortModelsButtons.js diff --git a/services/static-webserver/client/source/class/osparc/dashboard/SortedByMenuButton.js b/services/static-webserver/client/source/class/osparc/dashboard/SortedByMenuButton.js index 24427e4995b..7bb0bcb8d4a 100644 --- a/services/static-webserver/client/source/class/osparc/dashboard/SortedByMenuButton.js +++ b/services/static-webserver/client/source/class/osparc/dashboard/SortedByMenuButton.js @@ -65,6 +65,7 @@ qx.Class.define("osparc.dashboard.SortedByMenuButton", { field: "last_change_date", direction: "desc" }, + getSortByOptions: function() { return [{ id: "name", diff --git a/services/static-webserver/client/source/class/osparc/vipStore/SortModelsButtons.js b/services/static-webserver/client/source/class/osparc/vipStore/SortModelsButtons.js new file mode 100644 index 00000000000..69d982a11d0 --- /dev/null +++ b/services/static-webserver/client/source/class/osparc/vipStore/SortModelsButtons.js @@ -0,0 +1,101 @@ +/* ************************************************************************ + + osparc - the simcore frontend + + https://osparc.io + + Copyright: + 2022 IT'IS Foundation, https://itis.swiss + + License: + MIT: https://opensource.org/licenses/MIT + + Authors: + * Odei Maiz (odeimaiz) + +************************************************************************ */ + +qx.Class.define("osparc.vipStore.SortModelsButtons", { + extend: qx.ui.form.MenuButton, + + construct: function() { + this.base(arguments, this.tr("Sort"), "@FontAwesome5Solid/chevron-down/10"); + + this.set({ + iconPosition: "left", + marginRight: 8 + }); + + const sortByMenu = new qx.ui.menu.Menu().set({ + font: "text-14" + }); + this.setMenu(sortByMenu); + + const nameAsc = new qx.ui.menu.Button().set({ + label: this.tr("Name"), + icon: "@FontAwesome5Solid/sort-alpha-down/14" + }); + nameAsc["sortBy"] = "name"; + nameAsc["orderBy"] = "down"; + const nameDesc = new qx.ui.menu.Button().set({ + label: this.tr("Name"), + icon: "@FontAwesome5Solid/sort-alpha-up/14" + }); + nameDesc["sortBy"] = "name"; + nameDesc["orderBy"] = "up"; + + const dateDesc = new qx.ui.menu.Button().set({ + label: this.tr("Date"), + icon: "@FontAwesome5Solid/arrow-down/14" + }); + dateDesc["sortBy"] = "date"; + dateDesc["orderBy"] = "down"; + const dateAsc = new qx.ui.menu.Button().set({ + label: this.tr("Date"), + icon: "@FontAwesome5Solid/arrow-up/14" + }); + dateAsc["sortBy"] = "date"; + dateAsc["orderBy"] = "down"; + + [ + nameAsc, + nameDesc, + dateDesc, + dateAsc, + ].forEach((btn, idx) => { + sortByMenu.add(btn); + + btn.addListener("execute", () => this.__buttonExecuted(btn)); + + if (idx === 0) { + btn.execute(); + } + }); + }, + + events: { + "sortBy": "qx.event.type.Data" + }, + + statics: { + DefaultSorting: { + "sort": "name", + "order": "down" + } + }, + + members: { + __buttonExecuted: function(btn) { + this.set({ + label: btn.getLabel(), + icon: btn.getIcon() + }); + + const data = { + "sort": btn["sortBy"], + "order": btn["orderBy"] + }; + this.fireDataEvent("sortBy", data); + } + } +}); diff --git a/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js b/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js index bdecbf620c6..3f113d66871 100644 --- a/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js +++ b/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js @@ -59,10 +59,25 @@ qx.Class.define("osparc.vipStore.VIPStore", { __buildLayout: async function() { const toolbarLayout = new qx.ui.container.Composite(new qx.ui.layout.HBox(10)).set({ - maxHeight: 30 + alignY: "middle", + // maxHeight: 30 }); this._add(toolbarLayout); + const sortModelsButtons = new osparc.vipStore.SortModelsButtons().set({ + alignY: "bottom", + maxHeight: 27, + }); + toolbarLayout.add(sortModelsButtons); + + const filter = new osparc.filter.TextFilter("name", "vipModels").set({ + alignY: "middle", + allowGrowY: false, + minWidth: 200, + }); + this.addListener("appear", () => filter.getChildControl("textfield").focus()); + toolbarLayout.add(filter); + const modelsLayout = new qx.ui.container.Composite(new qx.ui.layout.HBox(10)); this._add(modelsLayout, { flex: 1 @@ -86,6 +101,9 @@ qx.Class.define("osparc.vipStore.VIPStore", { ctrl.bindProperty("name", "name", null, item, id); ctrl.bindProperty("date", "date", null, item, id); }, + configureItem: item => { + item.subscribeToFilterGroup("vipModels"); + }, }); const loadingModel = { From ed7e1733d2f1ec1bb4117d38bbb71b05046fadfd Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Thu, 28 Nov 2024 16:49:25 +0100 Subject: [PATCH 17/33] filter working --- .../client/source/class/osparc/vipStore/VIPStore.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js b/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js index 3f113d66871..804f93e9486 100644 --- a/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js +++ b/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js @@ -70,7 +70,7 @@ qx.Class.define("osparc.vipStore.VIPStore", { }); toolbarLayout.add(sortModelsButtons); - const filter = new osparc.filter.TextFilter("name", "vipModels").set({ + const filter = new osparc.filter.TextFilter("text", "vipModels").set({ alignY: "middle", allowGrowY: false, minWidth: 200, From e14cd4ba876bdee5f2d45d8c3825cefb5df7a5fc Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Thu, 28 Nov 2024 17:04:30 +0100 Subject: [PATCH 18/33] sorting --- .../source/class/osparc/vipStore/VIPStore.js | 32 ++++++++++++++++--- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js b/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js index 804f93e9486..affb78f3843 100644 --- a/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js +++ b/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js @@ -56,6 +56,7 @@ qx.Class.define("osparc.vipStore.VIPStore", { members: { __anatomicalModelsModel: null, __anatomicalModels: null, + __sortByButton: null, __buildLayout: async function() { const toolbarLayout = new qx.ui.container.Composite(new qx.ui.layout.HBox(10)).set({ @@ -64,7 +65,7 @@ qx.Class.define("osparc.vipStore.VIPStore", { }); this._add(toolbarLayout); - const sortModelsButtons = new osparc.vipStore.SortModelsButtons().set({ + const sortModelsButtons = this.__sortByButton = new osparc.vipStore.SortModelsButtons().set({ alignY: "bottom", maxHeight: 27, }); @@ -73,7 +74,7 @@ qx.Class.define("osparc.vipStore.VIPStore", { const filter = new osparc.filter.TextFilter("text", "vipModels").set({ alignY: "middle", allowGrowY: false, - minWidth: 200, + minWidth: 170, }); this.addListener("appear", () => filter.getChildControl("textfield").focus()); toolbarLayout.add(filter); @@ -137,12 +138,11 @@ qx.Class.define("osparc.vipStore.VIPStore", { const resp = await fetch("https://itis.swiss/PD_DirectDownload/getDownloadableItems/AnatomicalModels", {method:"POST"}); const anatomicalModelsRaw = await resp.json(); this.__anatomicalModels = this.self().curateAnatomicalModels(anatomicalModelsRaw); + this.__populateModels(); }, __populateModels: function() { - this.__anatomicalModelsModel.removeAll(); - const models = []; this.__anatomicalModels.forEach(model => { const anatomicalModel = {}; @@ -152,8 +152,32 @@ qx.Class.define("osparc.vipStore.VIPStore", { anatomicalModel["date"] = new Date(model["Features"]["date"]); models.push(anatomicalModel); }); + + this.__anatomicalModelsModel.removeAll(); models.sort((a, b) => a["name"].localeCompare(b["name"])); models.forEach(model => this.__anatomicalModelsModel.append(qx.data.marshal.Json.createModel(model))); + + this.__sortByButton.addListener("sortBy", e => { + const sortBy = e.getData(); + this.__anatomicalModelsModel.removeAll(); + models.sort((a, b) => { + if (sortBy["sort"] === "name") { + if (sortBy["orderBy"] === "down") { + return a["name"].localeCompare(b["name"]); + } else { + return b["name"].localeCompare(a["name"]); + } + } else if (sortBy["sort"] === "date") { + if (sortBy["orderBy"] === "down") { + return a["date"] - b["date"]; + } else { + return b["date"] - a["date"]; + } + } + return a["name"].localeCompare(b["name"]); + }); + models.forEach(model => this.__anatomicalModelsModel.append(qx.data.marshal.Json.createModel(model))); + }, this); }, } }); From 860e167b25af1b5f670d545427355b41fa8138e4 Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Thu, 28 Nov 2024 17:26:06 +0100 Subject: [PATCH 19/33] leased --- .../vipStore/AnatomicalModelListItem.js | 7 ++++ .../source/class/osparc/vipStore/VIPStore.js | 33 +++++++++++++++---- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelListItem.js b/services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelListItem.js index c10ecd8305c..6d1c4251aa5 100644 --- a/services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelListItem.js +++ b/services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelListItem.js @@ -81,6 +81,13 @@ qx.Class.define("osparc.vipStore.AnatomicalModelListItem", { nullable: true, event: "changeDate", }, + + leased: { + check: "Boolean", + init: false, + nullable: true, + event: "changeLeased", + }, }, members: { // eslint-disable-line qx-rules/no-refs-in-members diff --git a/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js b/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js index affb78f3843..203fcae7ac3 100644 --- a/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js +++ b/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js @@ -46,6 +46,9 @@ qx.Class.define("osparc.vipStore.VIPStore", { } else { curatedModel[key] = model[key]; } + if (key === "ID" && [22].includes(model[key])) { + curatedModel["leased"] = true; + } }); anatomicalModels.push(curatedModel); }); @@ -58,7 +61,7 @@ qx.Class.define("osparc.vipStore.VIPStore", { __anatomicalModels: null, __sortByButton: null, - __buildLayout: async function() { + __buildLayout: function() { const toolbarLayout = new qx.ui.container.Composite(new qx.ui.layout.HBox(10)).set({ alignY: "middle", // maxHeight: 30 @@ -101,10 +104,23 @@ qx.Class.define("osparc.vipStore.VIPStore", { ctrl.bindProperty("thumbnail", "thumbnail", null, item, id); ctrl.bindProperty("name", "name", null, item, id); ctrl.bindProperty("date", "date", null, item, id); + ctrl.bindProperty("leased", "leased", null, item, id); }, configureItem: item => { item.subscribeToFilterGroup("vipModels"); }, + group: model => { + return model.getLeased ? model.getLeased() : null; + }, + createGroupItem() { + return new qx.ui.form.ListItem(); + }, + configureGroupItem: item => { + item.setBackgroundColor("strong-color"); + }, + bindGroupItem: (controller, item, id) => { + controller.bindProperty(null, "leased", null, item, id); + }, }); const loadingModel = { @@ -134,12 +150,15 @@ qx.Class.define("osparc.vipStore.VIPStore", { anatomicModelDetails.setAnatomicalModelsData(null); }, this); - // fetch data - const resp = await fetch("https://itis.swiss/PD_DirectDownload/getDownloadableItems/AnatomicalModels", {method:"POST"}); - const anatomicalModelsRaw = await resp.json(); - this.__anatomicalModels = this.self().curateAnatomicalModels(anatomicalModelsRaw); - - this.__populateModels(); + fetch("https://itis.swiss/PD_DirectDownload/getDownloadableItems/AnatomicalModels", { + method:"POST" + }) + .then(resp => resp.json()) + .then(anatomicalModelsRaw => { + this.__anatomicalModels = this.self().curateAnatomicalModels(anatomicalModelsRaw); + this.__populateModels(); + }) + .catch(err => console.error(err)); }, __populateModels: function() { From 08500ffa06744eb589ba3b896258fc4981e83ce1 Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Thu, 28 Nov 2024 17:59:36 +0100 Subject: [PATCH 20/33] leased --- .../source/class/osparc/vipStore/AnatomicalModelListItem.js | 2 +- .../client/source/class/osparc/vipStore/VIPStore.js | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelListItem.js b/services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelListItem.js index 6d1c4251aa5..f718966f49a 100644 --- a/services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelListItem.js +++ b/services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelListItem.js @@ -33,7 +33,7 @@ qx.Class.define("osparc.vipStore.AnatomicalModelListItem", { this.set({ padding: 5, - minHeight: 48, + height: 48, alignY: "middle", }); diff --git a/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js b/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js index 203fcae7ac3..2bec70af1ec 100644 --- a/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js +++ b/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js @@ -46,8 +46,8 @@ qx.Class.define("osparc.vipStore.VIPStore", { } else { curatedModel[key] = model[key]; } - if (key === "ID" && [22].includes(model[key])) { - curatedModel["leased"] = true; + if (key === "ID") { + curatedModel["leased"] = [22].includes(model[key]); } }); anatomicalModels.push(curatedModel); @@ -169,6 +169,7 @@ qx.Class.define("osparc.vipStore.VIPStore", { anatomicalModel["thumbnail"] = model["Thumbnail"]; anatomicalModel["name"] = model["Features"]["name"] + " " + model["Features"]["version"]; anatomicalModel["date"] = new Date(model["Features"]["date"]); + anatomicalModel["leased"] = model["leased"]; models.push(anatomicalModel); }); From f6acefb4a6efc3e9ef1fdf69763afe0a00e063aa Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Thu, 28 Nov 2024 18:16:47 +0100 Subject: [PATCH 21/33] backgroundColor --- .../class/osparc/vipStore/AnatomicalModelListItem.js | 7 ++++++- .../client/source/class/osparc/vipStore/VIPStore.js | 12 ------------ 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelListItem.js b/services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelListItem.js index f718966f49a..e3040db2fdd 100644 --- a/services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelListItem.js +++ b/services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelListItem.js @@ -87,6 +87,7 @@ qx.Class.define("osparc.vipStore.AnatomicalModelListItem", { init: false, nullable: true, event: "changeLeased", + apply: "__applyLeased", }, }, @@ -142,7 +143,11 @@ qx.Class.define("osparc.vipStore.AnatomicalModelListItem", { this.getChildControl("name").setValue(value); }, - + __applyLeased: function(value) { + if (value) { + this.setBackgroundColor("strong-main"); + } + }, _onPointerOver: function() { this.addState("hovered"); diff --git a/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js b/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js index 2bec70af1ec..11247f5bc05 100644 --- a/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js +++ b/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js @@ -109,18 +109,6 @@ qx.Class.define("osparc.vipStore.VIPStore", { configureItem: item => { item.subscribeToFilterGroup("vipModels"); }, - group: model => { - return model.getLeased ? model.getLeased() : null; - }, - createGroupItem() { - return new qx.ui.form.ListItem(); - }, - configureGroupItem: item => { - item.setBackgroundColor("strong-color"); - }, - bindGroupItem: (controller, item, id) => { - controller.bindProperty(null, "leased", null, item, id); - }, }); const loadingModel = { From b4ae1af99eb1efc469b0d6a8a3204c3f76dc4cdd Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Thu, 28 Nov 2024 18:17:19 +0100 Subject: [PATCH 22/33] minor --- .../client/source/class/osparc/vipStore/VIPStore.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js b/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js index 11247f5bc05..2569b1d15a5 100644 --- a/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js +++ b/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js @@ -162,7 +162,9 @@ qx.Class.define("osparc.vipStore.VIPStore", { }); this.__anatomicalModelsModel.removeAll(); - models.sort((a, b) => a["name"].localeCompare(b["name"])); + models.sort((a, b) => { + return a["name"].localeCompare(b["name"]); + }); models.forEach(model => this.__anatomicalModelsModel.append(qx.data.marshal.Json.createModel(model))); this.__sortByButton.addListener("sortBy", e => { From 787decf1d86ca60f8c0954e70959255f7f549763 Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Thu, 28 Nov 2024 18:23:36 +0100 Subject: [PATCH 23/33] sorting --- .../client/source/class/osparc/vipStore/VIPStore.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js b/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js index 2569b1d15a5..c34e9c95c5e 100644 --- a/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js +++ b/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js @@ -163,6 +163,10 @@ qx.Class.define("osparc.vipStore.VIPStore", { this.__anatomicalModelsModel.removeAll(); models.sort((a, b) => { + if (b["leased"] !== a["leased"]) { + return b["leased"] - a["leased"]; + } + // second criteria return a["name"].localeCompare(b["name"]); }); models.forEach(model => this.__anatomicalModelsModel.append(qx.data.marshal.Json.createModel(model))); From b92d042f4ab93303c7293fe4f97c1ce582edd6cd Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Thu, 28 Nov 2024 18:32:28 +0100 Subject: [PATCH 24/33] sort wokrs --- .../source/class/osparc/vipStore/VIPStore.js | 51 ++++++++++--------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js b/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js index c34e9c95c5e..af42dc5685c 100644 --- a/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js +++ b/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js @@ -162,34 +162,39 @@ qx.Class.define("osparc.vipStore.VIPStore", { }); this.__anatomicalModelsModel.removeAll(); - models.sort((a, b) => { - if (b["leased"] !== a["leased"]) { - return b["leased"] - a["leased"]; - } - // second criteria - return a["name"].localeCompare(b["name"]); - }); - models.forEach(model => this.__anatomicalModelsModel.append(qx.data.marshal.Json.createModel(model))); - - this.__sortByButton.addListener("sortBy", e => { - const sortBy = e.getData(); - this.__anatomicalModelsModel.removeAll(); + const sortModel = sortBy => { models.sort((a, b) => { - if (sortBy["sort"] === "name") { - if (sortBy["orderBy"] === "down") { - return a["name"].localeCompare(b["name"]); - } else { - return b["name"].localeCompare(a["name"]); - } - } else if (sortBy["sort"] === "date") { - if (sortBy["orderBy"] === "down") { - return a["date"] - b["date"]; - } else { - return b["date"] - a["date"]; + // first criteria + if (b["leased"] !== a["leased"]) { + return b["leased"] - a["leased"]; + } + // second criteria + if (sortBy) { + if (sortBy["sort"] === "name") { + if (sortBy["orderBy"] === "down") { + return a["name"].localeCompare(b["name"]); + } else { + return b["name"].localeCompare(a["name"]); + } + } else if (sortBy["sort"] === "date") { + if (sortBy["orderBy"] === "down") { + return a["date"] - b["date"]; + } else { + return b["date"] - a["date"]; + } } } + // default criteria return a["name"].localeCompare(b["name"]); }); + }; + sortModel(); + models.forEach(model => this.__anatomicalModelsModel.append(qx.data.marshal.Json.createModel(model))); + + this.__sortByButton.addListener("sortBy", e => { + this.__anatomicalModelsModel.removeAll(); + const sortBy = e.getData(); + sortModel(sortBy); models.forEach(model => this.__anatomicalModelsModel.append(qx.data.marshal.Json.createModel(model))); }, this); }, From 160b19028ba0dca58bfbe324b7549649902c828c Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Thu, 28 Nov 2024 18:37:49 +0100 Subject: [PATCH 25/33] fixed --- .../client/source/class/osparc/vipStore/VIPStore.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js b/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js index af42dc5685c..9264b182ca3 100644 --- a/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js +++ b/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js @@ -171,20 +171,23 @@ qx.Class.define("osparc.vipStore.VIPStore", { // second criteria if (sortBy) { if (sortBy["sort"] === "name") { - if (sortBy["orderBy"] === "down") { + if (sortBy["order"] === "down") { + // A -> Z return a["name"].localeCompare(b["name"]); } else { return b["name"].localeCompare(a["name"]); } } else if (sortBy["sort"] === "date") { - if (sortBy["orderBy"] === "down") { - return a["date"] - b["date"]; - } else { + if (sortBy["order"] === "down") { + // Now -> Yesterday return b["date"] - a["date"]; + } else { + return a["date"] - b["date"]; } } } // default criteria + // A -> Z return a["name"].localeCompare(b["name"]); }); }; From 6b24ef5a05440f2441d012f8886e744e42fd2efd Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Thu, 28 Nov 2024 18:40:42 +0100 Subject: [PATCH 26/33] comment --- .../client/source/class/osparc/vipStore/VIPStore.js | 1 + 1 file changed, 1 insertion(+) diff --git a/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js b/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js index 9264b182ca3..09596bd1ddc 100644 --- a/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js +++ b/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js @@ -166,6 +166,7 @@ qx.Class.define("osparc.vipStore.VIPStore", { models.sort((a, b) => { // first criteria if (b["leased"] !== a["leased"]) { + // leased first return b["leased"] - a["leased"]; } // second criteria From 52fc81cb4e61907a1265a289d9510f927a29befc Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Thu, 28 Nov 2024 18:50:23 +0100 Subject: [PATCH 27/33] "modelLeased" --- .../class/osparc/vipStore/AnatomicalModelDetails.js | 13 ++++++++++++- .../client/source/class/osparc/vipStore/VIPStore.js | 9 +++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelDetails.js b/services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelDetails.js index da0173505a5..10e26c513ed 100644 --- a/services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelDetails.js +++ b/services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelDetails.js @@ -27,6 +27,10 @@ qx.Class.define("osparc.vipStore.AnatomicalModelDetails", { this.__poplulateLayout(); }, + events: { + "modelLeased": "qx.event.type.Event", + }, + properties: { anatomicalModelsData: { check: "Object", @@ -166,11 +170,18 @@ qx.Class.define("osparc.vipStore.AnatomicalModelDetails", { }); - const leaseModelButton = new qx.ui.form.Button().set({ + const leaseModelButton = new osparc.ui.form.FetchButton().set({ label: this.tr("Lease model (2 for months)"), appearance: "strong-button", center: true, }); + leaseModelButton.addListener("execute", () => { + leaseModelButton.setFetching(true); + setTimeout(() => { + leaseModelButton.setFetching(false); + this.fireDataEvent("modelLeased", this.getAnatomicalModelsData()["ID"]); + }, 2000); + }); cardLayout.add(leaseModelButton, { column: 0, row: 3, diff --git a/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js b/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js index 09596bd1ddc..908cfc60d47 100644 --- a/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js +++ b/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js @@ -145,6 +145,15 @@ qx.Class.define("osparc.vipStore.VIPStore", { .then(anatomicalModelsRaw => { this.__anatomicalModels = this.self().curateAnatomicalModels(anatomicalModelsRaw); this.__populateModels(); + + anatomicModelDetails.addListener("modelLeased", e => { + const modelId = e.getData(); + const found = this.__anatomicalModels.find(model => model["ID"] === modelId); + if (found) { + found["leased"] = true; + }; + this.__populateModels(); + }, this); }) .catch(err => console.error(err)); }, From c05ab72be22ed2b76bafcdb9b804ace7f3f60e7b Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Thu, 28 Nov 2024 18:56:07 +0100 Subject: [PATCH 28/33] aesthetics --- .../osparc/vipStore/AnatomicalModelDetails.js | 18 ++++++++++++++++-- .../source/class/osparc/vipStore/VIPStore.js | 3 ++- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelDetails.js b/services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelDetails.js index 10e26c513ed..9c93b7c767d 100644 --- a/services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelDetails.js +++ b/services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelDetails.js @@ -169,7 +169,18 @@ qx.Class.define("osparc.vipStore.AnatomicalModelDetails", { row: 2, }); - + const buttonsLayout = new qx.ui.container.Composite(new qx.ui.layout.HBox(5)); + if (anatomicalModelsData["leased"]) { + const leaseModelButton = new qx.ui.form.Button().set({ + label: this.tr("3 seats Leased (27 days left)"), + appearance: "strong-button", + center: true, + enabled: false, + }); + buttonsLayout.add(leaseModelButton, { + flex: 1 + }); + } const leaseModelButton = new osparc.ui.form.FetchButton().set({ label: this.tr("Lease model (2 for months)"), appearance: "strong-button", @@ -182,7 +193,10 @@ qx.Class.define("osparc.vipStore.AnatomicalModelDetails", { this.fireDataEvent("modelLeased", this.getAnatomicalModelsData()["ID"]); }, 2000); }); - cardLayout.add(leaseModelButton, { + buttonsLayout.add(leaseModelButton, { + flex: 1 + }); + cardLayout.add(buttonsLayout, { column: 0, row: 3, colSpan: 2, diff --git a/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js b/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js index 908cfc60d47..48a2cfa4d80 100644 --- a/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js +++ b/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js @@ -151,8 +151,9 @@ qx.Class.define("osparc.vipStore.VIPStore", { const found = this.__anatomicalModels.find(model => model["ID"] === modelId); if (found) { found["leased"] = true; + this.__populateModels(); + anatomicModelDetails.setAnatomicalModelsData(found); }; - this.__populateModels(); }, this); }) .catch(err => console.error(err)); From d77c9da6eb171bb0d084908948e9394fdf48d3e6 Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Thu, 28 Nov 2024 18:57:17 +0100 Subject: [PATCH 29/33] minor --- .../client/source/class/osparc/product/Utils.js | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/services/static-webserver/client/source/class/osparc/product/Utils.js b/services/static-webserver/client/source/class/osparc/product/Utils.js index 9eeb63ee900..45d3b7de661 100644 --- a/services/static-webserver/client/source/class/osparc/product/Utils.js +++ b/services/static-webserver/client/source/class/osparc/product/Utils.js @@ -275,13 +275,7 @@ qx.Class.define("osparc.product.Utils", { if (platformName !== "master") { return false; } - if (this.getProductName().includes("osparc")) { - return true; - } - if (this.isS4LProduct()) { - return true; - } - return false; + return this.isS4LProduct(); }, getProductThumbUrl: function(asset = "Default.png") { From 4b79bb07ce05bfdc37da9b3c1d7a6d98e19b0db5 Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Fri, 29 Nov 2024 13:25:02 +0100 Subject: [PATCH 30/33] vipStore -> vipMarket --- .../class/osparc/navigation/UserMenu.js | 10 ++-- .../AnatomicalModelDetails.js | 47 +++++++++---------- .../AnatomicalModelListItem.js | 2 +- .../Store.js => vipMarket/Market.js} | 12 ++--- .../MarketWindow.js} | 16 +++---- .../SortModelsButtons.js | 2 +- .../VIPStore.js => vipMarket/VIPMarket.js} | 8 ++-- 7 files changed, 48 insertions(+), 49 deletions(-) rename services/static-webserver/client/source/class/osparc/{vipStore => vipMarket}/AnatomicalModelDetails.js (87%) rename services/static-webserver/client/source/class/osparc/{vipStore => vipMarket}/AnatomicalModelListItem.js (98%) rename services/static-webserver/client/source/class/osparc/{vipStore/Store.js => vipMarket/Market.js} (73%) rename services/static-webserver/client/source/class/osparc/{vipStore/StoreWindow.js => vipMarket/MarketWindow.js} (67%) rename services/static-webserver/client/source/class/osparc/{vipStore => vipMarket}/SortModelsButtons.js (97%) rename services/static-webserver/client/source/class/osparc/{vipStore/VIPStore.js => vipMarket/VIPMarket.js} (96%) diff --git a/services/static-webserver/client/source/class/osparc/navigation/UserMenu.js b/services/static-webserver/client/source/class/osparc/navigation/UserMenu.js index 0ee2bbabf88..dc029edbba9 100644 --- a/services/static-webserver/client/source/class/osparc/navigation/UserMenu.js +++ b/services/static-webserver/client/source/class/osparc/navigation/UserMenu.js @@ -103,9 +103,9 @@ qx.Class.define("osparc.navigation.UserMenu", { control.addListener("execute", () => osparc.cluster.Utils.popUpClustersDetails(), this); this.add(control); break; - case "store": - control = new qx.ui.menu.Button(this.tr("Store")); - control.addListener("execute", () => osparc.vipStore.StoreWindow.openWindow()); + case "market": + control = new qx.ui.menu.Button(this.tr("Market")); + control.addListener("execute", () => osparc.vipMarket.MarketWindow.openWindow()); this.add(control); break; case "about": @@ -185,7 +185,7 @@ qx.Class.define("osparc.navigation.UserMenu", { this.__addAnnouncements(); if (osparc.product.Utils.showS4LStore()) { - this.getChildControl("store"); + this.getChildControl("market"); } this.getChildControl("about"); @@ -253,7 +253,7 @@ qx.Class.define("osparc.navigation.UserMenu", { this.__addAnnouncements(); if (osparc.product.Utils.showS4LStore()) { - this.getChildControl("store"); + this.getChildControl("market"); } this.getChildControl("about"); diff --git a/services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelDetails.js b/services/static-webserver/client/source/class/osparc/vipMarket/AnatomicalModelDetails.js similarity index 87% rename from services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelDetails.js rename to services/static-webserver/client/source/class/osparc/vipMarket/AnatomicalModelDetails.js index 9c93b7c767d..6aebd9331fe 100644 --- a/services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelDetails.js +++ b/services/static-webserver/client/source/class/osparc/vipMarket/AnatomicalModelDetails.js @@ -15,7 +15,7 @@ ************************************************************************ */ -qx.Class.define("osparc.vipStore.AnatomicalModelDetails", { +qx.Class.define("osparc.vipMarket.AnatomicalModelDetails", { extend: qx.ui.core.Widget, construct: function() { @@ -114,6 +114,7 @@ qx.Class.define("osparc.vipStore.AnatomicalModelDetails", { "Height", "Date", "Ethnicity", + "Functionality", ].forEach(key => { if (key.toLowerCase() in features) { const titleLabel = new qx.ui.basic.Label().set({ @@ -140,29 +141,27 @@ qx.Class.define("osparc.vipStore.AnatomicalModelDetails", { } }); - if (anatomicalModelsData["DOI"]) { - const doiTitle = new qx.ui.basic.Label().set({ - value: "DOI", - font: "text-14", - alignX: "right", - marginTop: 16, - }); - moreInfoLayout.add(doiTitle, { - column: 0, - row: idx, - }); - - const doiValue = new qx.ui.basic.Label().set({ - value: anatomicalModelsData["DOI"], - font: "text-14", - alignX: "left", - marginTop: 16, - }); - moreInfoLayout.add(doiValue, { - column: 1, - row: idx, - }); - } + const doiTitle = new qx.ui.basic.Label().set({ + value: "DOI", + font: "text-14", + alignX: "right", + marginTop: 16, + }); + moreInfoLayout.add(doiTitle, { + column: 0, + row: idx, + }); + + const doiValue = new qx.ui.basic.Label().set({ + value: anatomicalModelsData["DOI"] ? anatomicalModelsData["DOI"] : "-", + font: "text-14", + alignX: "left", + marginTop: 16, + }); + moreInfoLayout.add(doiValue, { + column: 1, + row: idx, + }); cardLayout.add(moreInfoLayout, { column: 1, diff --git a/services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelListItem.js b/services/static-webserver/client/source/class/osparc/vipMarket/AnatomicalModelListItem.js similarity index 98% rename from services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelListItem.js rename to services/static-webserver/client/source/class/osparc/vipMarket/AnatomicalModelListItem.js index e3040db2fdd..3b12de9852c 100644 --- a/services/static-webserver/client/source/class/osparc/vipStore/AnatomicalModelListItem.js +++ b/services/static-webserver/client/source/class/osparc/vipMarket/AnatomicalModelListItem.js @@ -15,7 +15,7 @@ ************************************************************************ */ -qx.Class.define("osparc.vipStore.AnatomicalModelListItem", { +qx.Class.define("osparc.vipMarket.AnatomicalModelListItem", { extend: qx.ui.core.Widget, implement : [qx.ui.form.IModel, osparc.filter.IFilterable], include : [qx.ui.form.MModelProperty, osparc.filter.MFilterable], diff --git a/services/static-webserver/client/source/class/osparc/vipStore/Store.js b/services/static-webserver/client/source/class/osparc/vipMarket/Market.js similarity index 73% rename from services/static-webserver/client/source/class/osparc/vipStore/Store.js rename to services/static-webserver/client/source/class/osparc/vipMarket/Market.js index 1bd955ab2e3..14aae9bd3de 100644 --- a/services/static-webserver/client/source/class/osparc/vipStore/Store.js +++ b/services/static-webserver/client/source/class/osparc/vipMarket/Market.js @@ -15,7 +15,7 @@ ************************************************************************ */ -qx.Class.define("osparc.vipStore.Store", { +qx.Class.define("osparc.vipMarket.Market", { extend: osparc.ui.window.TabbedView, construct: function() { @@ -26,17 +26,17 @@ qx.Class.define("osparc.vipStore.Store", { }); this.addWidgetOnTopOfTheTabs(miniWallet); - this.__vipStorePage = this.__getVIPStorePage(); + this.__vipMarketPage = this.__getVIPMarketPage(); }, members: { - __vipStorePage: null, + __vipMarketPage: null, - __getVIPStorePage: function() { + __getVIPMarketPage: function() { const title = this.tr("VIP Models"); const iconSrc = "@FontAwesome5Solid/users/22"; - const vipStoreView = new osparc.vipStore.VIPStore(); - const page = this.addTab(title, iconSrc, vipStoreView); + const vipMarketView = new osparc.vipMarket.VIPMarket(); + const page = this.addTab(title, iconSrc, vipMarketView); return page; }, } diff --git a/services/static-webserver/client/source/class/osparc/vipStore/StoreWindow.js b/services/static-webserver/client/source/class/osparc/vipMarket/MarketWindow.js similarity index 67% rename from services/static-webserver/client/source/class/osparc/vipStore/StoreWindow.js rename to services/static-webserver/client/source/class/osparc/vipMarket/MarketWindow.js index cb63356b81c..483a5be950f 100644 --- a/services/static-webserver/client/source/class/osparc/vipStore/StoreWindow.js +++ b/services/static-webserver/client/source/class/osparc/vipMarket/MarketWindow.js @@ -15,11 +15,11 @@ ************************************************************************ */ -qx.Class.define("osparc.vipStore.StoreWindow", { +qx.Class.define("osparc.vipMarket.MarketWindow", { extend: osparc.ui.window.TabbedWindow, construct: function() { - this.base(arguments, "store", this.tr("Store")); + this.base(arguments, "store", this.tr("Market")); osparc.utils.Utils.setIdToWidget(this, "storeWindow"); @@ -31,13 +31,13 @@ qx.Class.define("osparc.vipStore.StoreWindow", { height }) - const vipStore = this.__vipStore = new osparc.vipStore.Store(); - this._setTabbedView(vipStore); + const vipMarket = this.__vipMarket = new osparc.vipMarket.Market(); + this._setTabbedView(vipMarket); }, statics: { openWindow: function() { - const storeWindow = new osparc.vipStore.StoreWindow(); + const storeWindow = new osparc.vipMarket.MarketWindow(); storeWindow.center(); storeWindow.open(); return storeWindow; @@ -45,10 +45,10 @@ qx.Class.define("osparc.vipStore.StoreWindow", { }, members: { - __vipStore: null, + __vipMarket: null, - openVIPStore: function() { - return this.__vipStore.openVIPStore(); + openVIPMarket: function() { + return this.__vipMarket.openVIPMarket(); }, } }); diff --git a/services/static-webserver/client/source/class/osparc/vipStore/SortModelsButtons.js b/services/static-webserver/client/source/class/osparc/vipMarket/SortModelsButtons.js similarity index 97% rename from services/static-webserver/client/source/class/osparc/vipStore/SortModelsButtons.js rename to services/static-webserver/client/source/class/osparc/vipMarket/SortModelsButtons.js index 69d982a11d0..c23f8c17c5c 100644 --- a/services/static-webserver/client/source/class/osparc/vipStore/SortModelsButtons.js +++ b/services/static-webserver/client/source/class/osparc/vipMarket/SortModelsButtons.js @@ -15,7 +15,7 @@ ************************************************************************ */ -qx.Class.define("osparc.vipStore.SortModelsButtons", { +qx.Class.define("osparc.vipMarket.SortModelsButtons", { extend: qx.ui.form.MenuButton, construct: function() { diff --git a/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js b/services/static-webserver/client/source/class/osparc/vipMarket/VIPMarket.js similarity index 96% rename from services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js rename to services/static-webserver/client/source/class/osparc/vipMarket/VIPMarket.js index 48a2cfa4d80..e198d8e8126 100644 --- a/services/static-webserver/client/source/class/osparc/vipStore/VIPStore.js +++ b/services/static-webserver/client/source/class/osparc/vipMarket/VIPMarket.js @@ -15,7 +15,7 @@ ************************************************************************ */ -qx.Class.define("osparc.vipStore.VIPStore", { +qx.Class.define("osparc.vipMarket.VIPMarket", { extend: qx.ui.core.Widget, construct: function() { @@ -68,7 +68,7 @@ qx.Class.define("osparc.vipStore.VIPStore", { }); this._add(toolbarLayout); - const sortModelsButtons = this.__sortByButton = new osparc.vipStore.SortModelsButtons().set({ + const sortModelsButtons = this.__sortByButton = new osparc.vipMarket.SortModelsButtons().set({ alignY: "bottom", maxHeight: 27, }); @@ -98,7 +98,7 @@ qx.Class.define("osparc.vipStore.VIPStore", { const anatomicalModelsModel = this.__anatomicalModelsModel = new qx.data.Array(); const membersCtrl = new qx.data.controller.List(anatomicalModelsModel, modelsUIList, "name"); membersCtrl.setDelegate({ - createItem: () => new osparc.vipStore.AnatomicalModelListItem(), + createItem: () => new osparc.vipMarket.AnatomicalModelListItem(), bindItem: (ctrl, item, id) => { ctrl.bindProperty("id", "modelId", null, item, id); ctrl.bindProperty("thumbnail", "thumbnail", null, item, id); @@ -118,7 +118,7 @@ qx.Class.define("osparc.vipStore.VIPStore", { }; this.__anatomicalModelsModel.append(qx.data.marshal.Json.createModel(loadingModel)); - const anatomicModelDetails = new osparc.vipStore.AnatomicalModelDetails().set({ + const anatomicModelDetails = new osparc.vipMarket.AnatomicalModelDetails().set({ padding: 20, }); modelsLayout.add(anatomicModelDetails, { From ac98719b6662d82232cb86195f8c9cd4c6b4b95b Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Fri, 29 Nov 2024 13:55:28 +0100 Subject: [PATCH 31/33] aesthetics --- .../source/class/osparc/data/Resources.js | 1 + .../osparc/vipMarket/AnatomicalModelDetails.js | 17 ++++++++--------- .../osparc/vipMarket/AnatomicalModelListItem.js | 1 + .../source/class/osparc/vipMarket/VIPMarket.js | 1 - 4 files changed, 10 insertions(+), 10 deletions(-) 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 8ff5eb822ba..87428d24117 100644 --- a/services/static-webserver/client/source/class/osparc/data/Resources.js +++ b/services/static-webserver/client/source/class/osparc/data/Resources.js @@ -98,6 +98,7 @@ qx.Class.define("osparc.data.Resources", { * added by oSPARC as compilation vars */ "appSummary": { + useCache: false, endpoints: { get: { method: "GET", diff --git a/services/static-webserver/client/source/class/osparc/vipMarket/AnatomicalModelDetails.js b/services/static-webserver/client/source/class/osparc/vipMarket/AnatomicalModelDetails.js index 6aebd9331fe..40ffda37b27 100644 --- a/services/static-webserver/client/source/class/osparc/vipMarket/AnatomicalModelDetails.js +++ b/services/static-webserver/client/source/class/osparc/vipMarket/AnatomicalModelDetails.js @@ -67,8 +67,6 @@ qx.Class.define("osparc.vipMarket.AnatomicalModelDetails", { const cardGrid = new qx.ui.layout.Grid(16, 16); const cardLayout = new qx.ui.container.Composite(cardGrid); - const features = anatomicalModelsData["Features"]; - const description = anatomicalModelsData["Description"]; description.split(" - ").forEach((desc, idx) => { const titleLabel = new qx.ui.basic.Label().set({ @@ -102,8 +100,9 @@ qx.Class.define("osparc.vipMarket.AnatomicalModelDetails", { row: 2, }); - const moreInfoGrid = new qx.ui.layout.Grid(8, 8); - const moreInfoLayout = new qx.ui.container.Composite(moreInfoGrid); + const features = anatomicalModelsData["Features"]; + const featuresGrid = new qx.ui.layout.Grid(8, 8); + const featuresLayout = new qx.ui.container.Composite(featuresGrid); let idx = 0; [ "Name", @@ -122,7 +121,7 @@ qx.Class.define("osparc.vipMarket.AnatomicalModelDetails", { font: "text-14", alignX: "right", }); - moreInfoLayout.add(titleLabel, { + featuresLayout.add(titleLabel, { column: 0, row: idx, }); @@ -132,7 +131,7 @@ qx.Class.define("osparc.vipMarket.AnatomicalModelDetails", { font: "text-14", alignX: "left", }); - moreInfoLayout.add(nameLabel, { + featuresLayout.add(nameLabel, { column: 1, row: idx, }); @@ -147,7 +146,7 @@ qx.Class.define("osparc.vipMarket.AnatomicalModelDetails", { alignX: "right", marginTop: 16, }); - moreInfoLayout.add(doiTitle, { + featuresLayout.add(doiTitle, { column: 0, row: idx, }); @@ -158,12 +157,12 @@ qx.Class.define("osparc.vipMarket.AnatomicalModelDetails", { alignX: "left", marginTop: 16, }); - moreInfoLayout.add(doiValue, { + featuresLayout.add(doiValue, { column: 1, row: idx, }); - cardLayout.add(moreInfoLayout, { + cardLayout.add(featuresLayout, { column: 1, row: 2, }); diff --git a/services/static-webserver/client/source/class/osparc/vipMarket/AnatomicalModelListItem.js b/services/static-webserver/client/source/class/osparc/vipMarket/AnatomicalModelListItem.js index 3b12de9852c..4beac36d736 100644 --- a/services/static-webserver/client/source/class/osparc/vipMarket/AnatomicalModelListItem.js +++ b/services/static-webserver/client/source/class/osparc/vipMarket/AnatomicalModelListItem.js @@ -35,6 +35,7 @@ qx.Class.define("osparc.vipMarket.AnatomicalModelListItem", { padding: 5, height: 48, alignY: "middle", + decorator: "rounded", }); this.addListener("pointerover", this._onPointerOver, this); diff --git a/services/static-webserver/client/source/class/osparc/vipMarket/VIPMarket.js b/services/static-webserver/client/source/class/osparc/vipMarket/VIPMarket.js index e198d8e8126..4e0c87689aa 100644 --- a/services/static-webserver/client/source/class/osparc/vipMarket/VIPMarket.js +++ b/services/static-webserver/client/source/class/osparc/vipMarket/VIPMarket.js @@ -64,7 +64,6 @@ qx.Class.define("osparc.vipMarket.VIPMarket", { __buildLayout: function() { const toolbarLayout = new qx.ui.container.Composite(new qx.ui.layout.HBox(10)).set({ alignY: "middle", - // maxHeight: 30 }); this._add(toolbarLayout); From 380968be2cc08db755b8e59c9416d26fa9ce9e47 Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Fri, 29 Nov 2024 14:15:19 +0100 Subject: [PATCH 32/33] renaming --- .../client/source/class/osparc/vipMarket/Market.js | 8 ++++---- .../client/source/class/osparc/vipMarket/MarketWindow.js | 4 ++-- .../class/osparc/vipMarket/{VIPMarket.js => VipMarket.js} | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) rename services/static-webserver/client/source/class/osparc/vipMarket/{VIPMarket.js => VipMarket.js} (99%) diff --git a/services/static-webserver/client/source/class/osparc/vipMarket/Market.js b/services/static-webserver/client/source/class/osparc/vipMarket/Market.js index 14aae9bd3de..dd6a2250c44 100644 --- a/services/static-webserver/client/source/class/osparc/vipMarket/Market.js +++ b/services/static-webserver/client/source/class/osparc/vipMarket/Market.js @@ -26,16 +26,16 @@ qx.Class.define("osparc.vipMarket.Market", { }); this.addWidgetOnTopOfTheTabs(miniWallet); - this.__vipMarketPage = this.__getVIPMarketPage(); + this.__vipMarketPage = this.__getVipMarketPage(); }, members: { __vipMarketPage: null, - __getVIPMarketPage: function() { - const title = this.tr("VIP Models"); + __getVipMarketPage: function() { + const title = this.tr("ViP Models"); const iconSrc = "@FontAwesome5Solid/users/22"; - const vipMarketView = new osparc.vipMarket.VIPMarket(); + const vipMarketView = new osparc.vipMarket.VipMarket(); const page = this.addTab(title, iconSrc, vipMarketView); return page; }, diff --git a/services/static-webserver/client/source/class/osparc/vipMarket/MarketWindow.js b/services/static-webserver/client/source/class/osparc/vipMarket/MarketWindow.js index 483a5be950f..d01207f883f 100644 --- a/services/static-webserver/client/source/class/osparc/vipMarket/MarketWindow.js +++ b/services/static-webserver/client/source/class/osparc/vipMarket/MarketWindow.js @@ -47,8 +47,8 @@ qx.Class.define("osparc.vipMarket.MarketWindow", { members: { __vipMarket: null, - openVIPMarket: function() { - return this.__vipMarket.openVIPMarket(); + openVipMarket: function() { + return this.__vipMarket.openVipMarket(); }, } }); diff --git a/services/static-webserver/client/source/class/osparc/vipMarket/VIPMarket.js b/services/static-webserver/client/source/class/osparc/vipMarket/VipMarket.js similarity index 99% rename from services/static-webserver/client/source/class/osparc/vipMarket/VIPMarket.js rename to services/static-webserver/client/source/class/osparc/vipMarket/VipMarket.js index 4e0c87689aa..ff0af06af15 100644 --- a/services/static-webserver/client/source/class/osparc/vipMarket/VIPMarket.js +++ b/services/static-webserver/client/source/class/osparc/vipMarket/VipMarket.js @@ -15,7 +15,7 @@ ************************************************************************ */ -qx.Class.define("osparc.vipMarket.VIPMarket", { +qx.Class.define("osparc.vipMarket.VipMarket", { extend: qx.ui.core.Widget, construct: function() { From 641a724d9c448768eb9f723ed636c4259044d196 Mon Sep 17 00:00:00 2001 From: odeimaiz Date: Fri, 29 Nov 2024 14:20:27 +0100 Subject: [PATCH 33/33] minor --- .../client/source/class/osparc/vipMarket/SortModelsButtons.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/static-webserver/client/source/class/osparc/vipMarket/SortModelsButtons.js b/services/static-webserver/client/source/class/osparc/vipMarket/SortModelsButtons.js index c23f8c17c5c..da3ed278f2b 100644 --- a/services/static-webserver/client/source/class/osparc/vipMarket/SortModelsButtons.js +++ b/services/static-webserver/client/source/class/osparc/vipMarket/SortModelsButtons.js @@ -5,7 +5,7 @@ https://osparc.io Copyright: - 2022 IT'IS Foundation, https://itis.swiss + 2024 IT'IS Foundation, https://itis.swiss License: MIT: https://opensource.org/licenses/MIT