diff --git a/services/static-webserver/client/source/class/osparc/editor/ThumbnailSuggestions.js b/services/static-webserver/client/source/class/osparc/editor/ThumbnailSuggestions.js index 188485676ac4..c51dace40c58 100644 --- a/services/static-webserver/client/source/class/osparc/editor/ThumbnailSuggestions.js +++ b/services/static-webserver/client/source/class/osparc/editor/ThumbnailSuggestions.js @@ -209,15 +209,18 @@ qx.Class.define("osparc.editor.ThumbnailSuggestions", { this.setSuggestions(this.__thumbnails); }, - thumbnailTapped: function(thumbnail) { + __thumbnailTapped: function(thumbnail) { + // reset decoration + const unselectedBorderColor = qx.theme.manager.Color.getInstance().resolve("text"); + const unselectedBGColor = qx.theme.manager.Color.getInstance().resolve("fab-background"); this.getChildren().forEach(thumbnailImg => { - osparc.utils.Utils.updateBorderColor(thumbnailImg, qx.theme.manager.Color.getInstance().resolve("box-shadow")); - osparc.utils.Utils.addBackground(thumbnailImg, qx.theme.manager.Color.getInstance().resolve("fab-background")); + osparc.utils.Utils.updateBorderColor(thumbnailImg, unselectedBorderColor); + osparc.utils.Utils.addBackground(thumbnailImg, unselectedBGColor); }); - const color = qx.theme.manager.Color.getInstance().resolve("background-selected-dark"); - const bgColor = qx.theme.manager.Color.getInstance().resolve("background-selected"); - osparc.utils.Utils.updateBorderColor(thumbnail, color); - osparc.utils.Utils.addBackground(thumbnail, bgColor); + const selectedBorderColor = qx.theme.manager.Color.getInstance().resolve("strong-main"); + const selectedBGColor = qx.theme.manager.Color.getInstance().resolve("background-selected"); + osparc.utils.Utils.updateBorderColor(thumbnail, selectedBorderColor); + osparc.utils.Utils.addBackground(thumbnail, selectedBGColor); this.fireDataEvent("thumbnailTapped", { type: thumbnail.thumbnailType || "templateThumbnail", source: thumbnail.thumbnailFileUrl || thumbnail.getSource() @@ -238,9 +241,7 @@ qx.Class.define("osparc.editor.ThumbnailSuggestions", { thumbnail.thumbnailFileUrl = suggestion.fileUrl || suggestion; thumbnail.addListener("mouseover", () => thumbnail.set({decorator: "thumbnail-selected"}), this); thumbnail.addListener("mouseout", () => thumbnail.set({decorator: "thumbnail"}), this); - thumbnail.addListener("tap", () => { - this.thumbnailTapped(thumbnail); - }, this); + thumbnail.addListener("tap", () => this.__thumbnailTapped(thumbnail), this); this.add(thumbnail); }); } 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 9c77be0601be..c077e347ce85 100644 --- a/services/static-webserver/client/source/class/osparc/vipMarket/AnatomicalModelDetails.js +++ b/services/static-webserver/client/source/class/osparc/vipMarket/AnatomicalModelDetails.js @@ -21,7 +21,7 @@ qx.Class.define("osparc.vipMarket.AnatomicalModelDetails", { construct: function() { this.base(arguments); - const layout = new qx.ui.layout.VBox(10); + const layout = new qx.ui.layout.VBox(15); this._setLayout(layout); this.__populateLayout(); @@ -48,7 +48,25 @@ qx.Class.define("osparc.vipMarket.AnatomicalModelDetails", { }, }, + statics: { + createThumbnail: function(source, size) { + return new qx.ui.basic.Image().set({ + source: source, + alignY: "middle", + scale: true, + allowGrowX: true, + allowGrowY: true, + allowShrinkX: true, + allowShrinkY: true, + maxWidth: size, + maxHeight: size, + }); + }, + }, + members: { + __selectedModelLayout: null, + __populateLayout: function() { this._removeAll(); @@ -71,43 +89,56 @@ qx.Class.define("osparc.vipMarket.AnatomicalModelDetails", { }, __addModelsInfo: function() { - const modelLayout = new qx.ui.container.Composite(new qx.ui.layout.VBox(16)); + const modelLayout = new qx.ui.container.Composite(new qx.ui.layout.VBox(6)); + + this.__selectedModelLayout = new qx.ui.container.Composite(new qx.ui.layout.VBox(6)); + modelLayout.add(this.__selectedModelLayout); const anatomicalModelsData = this.getAnatomicalModelsData(); const modelsInfo = anatomicalModelsData["licensedResources"]; if (modelsInfo.length > 1) { - const sBox = new qx.ui.form.SelectBox().set({ - minWidth: 200, - allowGrowX: false, - }); - modelsInfo.forEach(modelInfo => { - const sbItem = new qx.ui.form.ListItem(modelInfo["source"]["features"]["name"]); - sbItem.modelId = modelInfo["source"]["id"]; - sBox.add(sbItem); + const modelSelectionLayout = new qx.ui.container.Composite(new qx.ui.layout.VBox(4)); + const titleLabel = new qx.ui.basic.Label(this.tr("This bundle contains:")); + modelSelectionLayout.add(titleLabel); + const thumbnailsLayout = new qx.ui.container.Composite(new qx.ui.layout.HBox(2)); + modelSelectionLayout.add(thumbnailsLayout); + const thumbnailTapped = idx => { + this.__populateSelectedModelInfo(idx); + const selectedBorderColor = qx.theme.manager.Color.getInstance().resolve("strong-main"); + const unselectedBorderColor = "transparent"; + thumbnailsLayout.getChildren().forEach((thumbnail, index) => { + osparc.utils.Utils.updateBorderColor(thumbnail, index === idx ? selectedBorderColor : unselectedBorderColor); + }); + } + modelsInfo.forEach((modelInfo, idx) => { + const miniThumbnail = this.self().createThumbnail(modelInfo["source"]["thumbnail"], 32); + miniThumbnail.set({ + toolTipText: osparc.store.LicensedItems.licensedResourceNameAndVersion(modelInfo), + }); + osparc.utils.Utils.addBorder(miniThumbnail); + miniThumbnail.addListener("tap", () => thumbnailTapped(idx)); + thumbnailsLayout.add(miniThumbnail); }); - this._add(sBox); - sBox.addListener("changeSelection", e => { - const selection = e.getData(); - if (selection.length) { - const idxFound = modelsInfo.findIndex(mdlInfo => mdlInfo["source"]["id"] === selection[0].modelId) - this.__populateModelInfo(modelLayout, anatomicalModelsData, idxFound); - } - }, this); - this.__populateModelInfo(modelLayout, anatomicalModelsData, 0); + modelLayout.add(modelSelectionLayout); + thumbnailTapped(0); + + this.__populateSelectedModelInfo(); } else { - this.__populateModelInfo(modelLayout, anatomicalModelsData, 0); + this.__populateSelectedModelInfo(); } this._add(modelLayout); }, - __populateModelInfo: function(modelLayout, anatomicalModelsData, selectedIdx = 0) { - modelLayout.removeAll(); + __populateSelectedModelInfo: function(selectedIdx = 0) { + this.__selectedModelLayout.removeAll(); - const anatomicalModel = anatomicalModelsData["licensedResources"][selectedIdx]["source"]; - const topGrid = new qx.ui.layout.Grid(8, 8); + const anatomicalModelsData = this.getAnatomicalModelsData(); + + const topGrid = new qx.ui.layout.Grid(8, 6); topGrid.setColumnFlex(0, 1); - const topLayout = new qx.ui.container.Composite(topGrid); + const headerLayout = new qx.ui.container.Composite(topGrid); + const anatomicalModel = anatomicalModelsData["licensedResources"][selectedIdx]["source"]; let description = anatomicalModel["description"] || ""; description = description.replace(/SPEAG/g, " "); // remove SPEAG substring const delimiter = " - "; @@ -120,7 +151,7 @@ qx.Class.define("osparc.vipMarket.AnatomicalModelDetails", { allowGrowX: true, allowGrowY: true, }); - topLayout.add(titleLabel, { + headerLayout.add(titleLabel, { column: 0, row: 0, }); @@ -135,7 +166,7 @@ qx.Class.define("osparc.vipMarket.AnatomicalModelDetails", { allowGrowX: true, allowGrowY: true, }); - topLayout.add(subtitleLabel, { + headerLayout.add(subtitleLabel, { column: 0, row: 1, }); @@ -166,27 +197,17 @@ qx.Class.define("osparc.vipMarket.AnatomicalModelDetails", { decorator: "rounded", }); manufacturerLink.addListener("tap", () => window.open(manufacturerData["link"])); - topLayout.add(manufacturerLink, { + headerLayout.add(manufacturerLink, { column: 1, row: 0, rowSpan: 2, }); } - modelLayout.add(topLayout); + this.__selectedModelLayout.add(headerLayout); const middleLayout = new qx.ui.container.Composite(new qx.ui.layout.HBox(16)); - const thumbnail = new qx.ui.basic.Image().set({ - source: anatomicalModel["thumbnail"], - alignY: "middle", - scale: true, - allowGrowX: true, - allowGrowY: true, - allowShrinkX: true, - allowShrinkY: true, - maxWidth: 256, - maxHeight: 256, - }); + const thumbnail = this.self().createThumbnail(anatomicalModel["thumbnail"], 256); middleLayout.add(thumbnail); const features = anatomicalModel["features"]; @@ -264,14 +285,14 @@ qx.Class.define("osparc.vipMarket.AnatomicalModelDetails", { middleLayout.add(featuresLayout); - modelLayout.add(middleLayout); + this.__selectedModelLayout.add(middleLayout); - const importButton = this.__createImportSection(anatomicalModelsData, selectedIdx); - modelLayout.add(importButton); + const importSection = this.__createImportSection(anatomicalModelsData, selectedIdx); + this.__selectedModelLayout.add(importSection); }, __createImportSection: function(anatomicalModelsData, selectedIdx) { - const importSection = new qx.ui.container.Composite(new qx.ui.layout.VBox(5).set({ + const importSection = new qx.ui.container.Composite(new qx.ui.layout.VBox().set({ alignX: "center" })); @@ -281,6 +302,7 @@ qx.Class.define("osparc.vipMarket.AnatomicalModelDetails", { center: true, maxWidth: 200, alignX: "center", + marginTop: 10, }); this.bind("openBy", importButton, "visibility", { converter: openBy => openBy ? "visible" : "excluded" @@ -344,7 +366,7 @@ qx.Class.define("osparc.vipMarket.AnatomicalModelDetails", { .then(licensedItems => { const lowerLicensedItems = osparc.store.LicensedItems.getLowerLicensedItems(licensedItems, licensedItemData["key"], licensedItemData["version"]) if (licensedItemData["licensedResources"].length > 1 || lowerLicensedItems.length) { - let text = this.tr("This Bundle gives you access to:") + "
"; + let text = this.tr("This bundle gives you access to:") + "
"; licensedItemData["licensedResources"].forEach(licensedResource => { text += `- ${osparc.store.LicensedItems.licensedResourceNameAndVersion(licensedResource)}
`; }); 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 a794db74b124..164bbed280d1 100644 --- a/services/static-webserver/client/source/class/osparc/vipMarket/AnatomicalModelListItem.js +++ b/services/static-webserver/client/source/class/osparc/vipMarket/AnatomicalModelListItem.js @@ -177,6 +177,10 @@ qx.Class.define("osparc.vipMarket.AnatomicalModelListItem", { __applyDisplayName: function(value) { this.getChildControl("name").setValue(value); + + this.set({ + toolTipText: value + }); }, __applySeats: function(seats) {