Skip to content

Commit cb26eab

Browse files
authored
🎨 [Frontend] ViP Market: Support 0-cost models (#7245)
1 parent dd053ac commit cb26eab

File tree

7 files changed

+155
-95
lines changed

7 files changed

+155
-95
lines changed

services/static-webserver/client/source/class/osparc/node/TierSelectionView.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,11 @@ qx.Class.define("osparc.node.TierSelectionView", {
4646
tiersLayout.add(tierBox);
4747

4848
const node = this.getNode();
49-
const pricingStore = osparc.store.Pricing.getInstance();
50-
pricingStore.fetchPricingPlansService(node.getKey(), node.getVersion())
49+
osparc.store.Pricing.getInstance().fetchPricingPlansService(node.getKey(), node.getVersion())
5150
.then(pricingPlans => {
5251
if (pricingPlans && "pricingUnits" in pricingPlans && pricingPlans["pricingUnits"].length) {
53-
const pricingUnits = pricingPlans["pricingUnits"].map(princingUnitData => {
54-
const pricingUnit = new osparc.data.model.PricingUnit(princingUnitData);
52+
const pricingUnits = pricingPlans["pricingUnits"].map(pricingUnitData => {
53+
const pricingUnit = new osparc.data.model.PricingUnit(pricingUnitData);
5554
return pricingUnit;
5655
});
5756
pricingUnits.forEach(pricingUnit => {

services/static-webserver/client/source/class/osparc/service/PricingUnitsList.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,7 @@ qx.Class.define("osparc.service.PricingUnitsList", {
4747
},
4848

4949
__fetchUnits: function() {
50-
const pricingStore = osparc.store.Pricing.getInstance();
51-
pricingStore.fetchPricingPlansService(this.__serviceMetadata["key"], this.__serviceMetadata["version"])
50+
osparc.store.Pricing.getInstance().fetchPricingPlansService(this.__serviceMetadata["key"], this.__serviceMetadata["version"])
5251
.then(data => this.__populateList(data["pricingUnits"]))
5352
.catch(err => {
5453
console.error(err);

services/static-webserver/client/source/class/osparc/store/LicensedItems.js

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,24 @@ qx.Class.define("osparc.store.LicensedItems", {
7171
},
7272

7373
licensedResourceNameAndVersion: function(licensedResource) {
74-
const name = licensedResource["source"]["features"]["name"];
75-
const version = licensedResource["source"]["features"]["version"];
74+
const name = licensedResource["source"]["features"]["name"] || osparc.store.LicensedItems.extractNameFromDescription(licensedResource);
75+
const version = licensedResource["source"]["features"]["version"] || "";
7676
return `${name} ${version}`;
7777
},
78+
79+
extractNameFromDescription: function(licensedResource) {
80+
const description = licensedResource["source"]["description"] || "";
81+
const delimiter = " - ";
82+
let typeAndName = description.split(delimiter);
83+
if (typeAndName.length > 1) {
84+
// drop the type
85+
typeAndName.shift();
86+
// join the name
87+
typeAndName = typeAndName.join(delimiter);
88+
return typeAndName;
89+
}
90+
return "";
91+
},
7892
},
7993

8094
members: {

services/static-webserver/client/source/class/osparc/study/NodePricingUnits.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,7 @@ qx.Class.define("osparc.study.NodePricingUnits", {
100100
const studyId = this.getStudyId();
101101
const nodeId = this.getNodeId();
102102

103-
const pricingStore = osparc.store.Pricing.getInstance();
104-
pricingStore.fetchPricingPlansService(nodeKey, nodeVersion)
103+
osparc.store.Pricing.getInstance().fetchPricingPlansService(nodeKey, nodeVersion)
105104
.then(pricingPlanData => {
106105
if (pricingPlanData) {
107106
const unitParams = {

services/static-webserver/client/source/class/osparc/vipMarket/AnatomicalModelDetails.js

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -313,9 +313,17 @@ qx.Class.define("osparc.vipMarket.AnatomicalModelDetails", {
313313
modelId: anatomicalModelsData["licensedResources"][selectedIdx]["source"]["id"]
314314
});
315315
}, this);
316-
if (anatomicalModelsData["seats"].length) {
317-
importSection.add(importButton);
318-
}
316+
317+
osparc.store.Pricing.getInstance().fetchPricingUnits(anatomicalModelsData["pricingPlanId"])
318+
.then(pricingUnits => {
319+
if (
320+
anatomicalModelsData["seats"].length ||
321+
(pricingUnits.length === 1 && pricingUnits[0].getCost() === 0)
322+
) {
323+
importSection.add(importButton);
324+
}
325+
});
326+
319327
return importSection;
320328
},
321329

@@ -336,23 +344,32 @@ qx.Class.define("osparc.vipMarket.AnatomicalModelDetails", {
336344
const licensedItemData = this.getAnatomicalModelsData();
337345
osparc.store.Pricing.getInstance().fetchPricingUnits(licensedItemData["pricingPlanId"])
338346
.then(pricingUnits => {
339-
pricingUnits.forEach(pricingUnit => {
340-
pricingUnit.set({
341-
classification: "LICENSE"
347+
if (pricingUnits.length === 1 && pricingUnits[0].getCost() === 0) {
348+
const availableLabel = new qx.ui.basic.Label().set({
349+
font: "text-14",
350+
value: this.tr("Available for Importing"),
351+
padding: 10,
342352
});
343-
const pUnit = new osparc.study.PricingUnitLicense(pricingUnit).set({
344-
showRentButton: true,
345-
licenseUrl: licensedItemData["termsOfUseUrl"],
346-
});
347-
pUnit.addListener("rentPricingUnit", () => {
348-
this.fireDataEvent("modelPurchaseRequested", {
349-
licensedItemId: licensedItemData["licensedItemId"],
350-
pricingPlanId: licensedItemData["pricingPlanId"],
351-
pricingUnitId: pricingUnit.getPricingUnitId(),
353+
pricingUnitsLayout.add(availableLabel);
354+
} else {
355+
pricingUnits.forEach(pricingUnit => {
356+
pricingUnit.set({
357+
classification: "LICENSE"
352358
});
353-
}, this);
354-
pricingUnitsLayout.add(pUnit);
355-
});
359+
const pUnit = new osparc.study.PricingUnitLicense(pricingUnit).set({
360+
showRentButton: true,
361+
licenseUrl: licensedItemData["termsOfUseUrl"],
362+
});
363+
pUnit.addListener("rentPricingUnit", () => {
364+
this.fireDataEvent("modelPurchaseRequested", {
365+
licensedItemId: licensedItemData["licensedItemId"],
366+
pricingPlanId: licensedItemData["pricingPlanId"],
367+
pricingUnitId: pricingUnit.getPricingUnitId(),
368+
});
369+
}, this);
370+
pricingUnitsLayout.add(pUnit);
371+
});
372+
}
356373
})
357374
.catch(err => console.error(err));
358375
this._add(pricingUnitsLayout);

services/static-webserver/client/source/class/osparc/vipMarket/Market.js

Lines changed: 81 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -33,58 +33,7 @@ qx.Class.define("osparc.vipMarket.Market", {
3333
return;
3434
}
3535

36-
const walletId = contextWallet.getWalletId();
37-
const licensedItemsStore = osparc.store.LicensedItems.getInstance();
38-
Promise.all([
39-
licensedItemsStore.getLicensedItems(),
40-
licensedItemsStore.getPurchasedLicensedItems(walletId),
41-
])
42-
.then(values => {
43-
const licensedItems = values[0];
44-
const purchasedItems = values[1];
45-
osparc.store.LicensedItems.populateSeatsFromPurchases(licensedItems, purchasedItems);
46-
const categories = [];
47-
const purchasedCategory = {
48-
categoryId: "purchasedModels",
49-
label: this.tr("Rented"),
50-
icon: "osparc/market/RentedModels.svg",
51-
items: [],
52-
};
53-
categories.push(purchasedCategory);
54-
licensedItems.forEach(licensedItem => {
55-
if (licensedItem["seats"].length) {
56-
purchasedCategory["items"].push(licensedItem);
57-
if (!openCategory) {
58-
openCategory = purchasedCategory["categoryId"];
59-
}
60-
}
61-
if (licensedItem && licensedItem["categoryId"]) {
62-
const categoryId = licensedItem["categoryId"];
63-
let category = categories.find(cat => cat["categoryId"] === categoryId);
64-
if (!category) {
65-
category = {
66-
categoryId,
67-
label: licensedItem["categoryDisplay"] || "Category",
68-
icon: licensedItem["categoryIcon"] || `osparc/market/${categoryId}.svg`,
69-
items: [],
70-
};
71-
if (!openCategory) {
72-
openCategory = categoryId;
73-
}
74-
categories.push(category);
75-
}
76-
category["items"].push(licensedItem);
77-
}
78-
});
79-
80-
categories.forEach(category => {
81-
this.__buildViPMarketPage(category, category["items"]);
82-
});
83-
84-
if (openCategory) {
85-
this.__openCategory(openCategory);
86-
}
87-
});
36+
this.__populateCategories(openCategory);
8837
},
8938

9039
events: {
@@ -104,6 +53,86 @@ qx.Class.define("osparc.vipMarket.Market", {
10453
__purchasedCategoryButton: null,
10554
__purchasedCategoryMarket: null,
10655

56+
__populateCategories: function(openCategory) {
57+
const store = osparc.store.Store.getInstance();
58+
const contextWallet = store.getContextWallet();
59+
60+
const walletId = contextWallet.getWalletId();
61+
const licensedItemsStore = osparc.store.LicensedItems.getInstance();
62+
Promise.all([
63+
licensedItemsStore.getLicensedItems(),
64+
licensedItemsStore.getPurchasedLicensedItems(walletId),
65+
])
66+
.then(values => {
67+
const licensedItems = values[0];
68+
const purchasedItems = values[1];
69+
osparc.store.LicensedItems.populateSeatsFromPurchases(licensedItems, purchasedItems);
70+
const categories = [];
71+
const purchasedCategory = {
72+
categoryId: "purchasedModels",
73+
label: this.tr("Rented"),
74+
icon: "osparc/market/RentedModels.svg",
75+
items: [],
76+
};
77+
categories.push(purchasedCategory);
78+
licensedItems.forEach(licensedItem => {
79+
if (licensedItem["seats"].length) {
80+
purchasedCategory["items"].push(licensedItem);
81+
if (!openCategory) {
82+
openCategory = purchasedCategory["categoryId"];
83+
}
84+
}
85+
if (licensedItem && licensedItem["categoryId"]) {
86+
const categoryId = licensedItem["categoryId"];
87+
let category = categories.find(cat => cat["categoryId"] === categoryId);
88+
if (!category) {
89+
category = {
90+
categoryId,
91+
label: licensedItem["categoryDisplay"] || "Category",
92+
icon: licensedItem["categoryIcon"] || `osparc/market/${categoryId}.svg`,
93+
items: [],
94+
};
95+
if (!openCategory) {
96+
openCategory = categoryId;
97+
}
98+
categories.push(category);
99+
}
100+
category["items"].push(licensedItem);
101+
}
102+
});
103+
104+
categories.forEach(category => {
105+
this.__buildViPMarketPage(category, category["items"]);
106+
});
107+
108+
if (openCategory) {
109+
this.__openCategory(openCategory);
110+
}
111+
112+
this.__addFreeCategory();
113+
});
114+
},
115+
116+
__addFreeCategory: function() {
117+
const freeCategory = {
118+
categoryId: "freeModels",
119+
label: this.tr("Open Access Models"),
120+
icon: "osparc/market/RentedModels.svg",
121+
items: [],
122+
};
123+
const licensedItemsStore = osparc.store.LicensedItems.getInstance();
124+
licensedItemsStore.getLicensedItems()
125+
.then(async licensedItems => {
126+
for (const licensedItem of licensedItems) {
127+
const pricingUnits = await osparc.store.Pricing.getInstance().fetchPricingUnits(licensedItem["pricingPlanId"]);
128+
if (pricingUnits.length === 1 && pricingUnits[0].getCost() === 0) {
129+
freeCategory["items"].push(licensedItem);
130+
}
131+
}
132+
this.__buildViPMarketPage(freeCategory, freeCategory["items"]);
133+
});
134+
},
135+
107136
__buildViPMarketPage: function(marketTabInfo, licensedItems = []) {
108137
const vipMarketView = new osparc.vipMarket.VipMarket(licensedItems);
109138
vipMarketView.set({

services/static-webserver/client/source/class/osparc/vipMarket/VipMarket.js

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -199,21 +199,24 @@ qx.Class.define("osparc.vipMarket.VipMarket", {
199199
this.__populateModels();
200200

201201
const anatomicModelDetails = this.getChildControl("models-details");
202-
anatomicModelDetails.addListener("modelPurchaseRequested", e => {
203-
const {
204-
licensedItemId,
205-
pricingPlanId,
206-
pricingUnitId,
207-
} = e.getData();
208-
this.__modelPurchaseRequested(licensedItemId, pricingPlanId, pricingUnitId);
209-
}, this);
210-
211-
anatomicModelDetails.addListener("modelImportRequested", e => {
212-
const {
213-
modelId
214-
} = e.getData();
215-
this.__sendImportModelMessage(modelId);
216-
}, this);
202+
if (!anatomicModelDetails.hasListener("modelPurchaseRequested")) {
203+
anatomicModelDetails.addListener("modelPurchaseRequested", e => {
204+
const {
205+
licensedItemId,
206+
pricingPlanId,
207+
pricingUnitId,
208+
} = e.getData();
209+
this.__modelPurchaseRequested(licensedItemId, pricingPlanId, pricingUnitId);
210+
}, this);
211+
}
212+
if (!anatomicModelDetails.hasListener("modelImportRequested")) {
213+
anatomicModelDetails.addListener("modelImportRequested", e => {
214+
const {
215+
modelId
216+
} = e.getData();
217+
this.__sendImportModelMessage(modelId);
218+
}, this);
219+
}
217220
},
218221

219222
__populateModels: function(selectLicensedItemId) {

0 commit comments

Comments
 (0)