Skip to content

Commit cd484c5

Browse files
odeimaizmrnicegyu11
authored andcommitted
🎨 [Frontend] ViP Market: Give access to purchased lower versions and how info (ITISFoundation#7230)
1 parent 5610199 commit cd484c5

File tree

6 files changed

+228
-116
lines changed

6 files changed

+228
-116
lines changed

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

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,53 @@ qx.Class.define("osparc.store.LicensedItems", {
2626
},
2727

2828
statics: {
29-
purchasesToNSeats: function(purchases) {
30-
let nSeats = 0;
29+
populateSeatsFromPurchases: function(licensedItems, purchases) {
30+
// reset seats
31+
licensedItems.forEach(licensedItem => licensedItem["seats"] = []);
32+
// populate seats
3133
purchases.forEach(purchase => {
32-
if ("numberOfSeats" in purchase) {
33-
nSeats += purchase["numberOfSeats"];
34-
} else if ("getNumberOfSeats" in purchase) {
35-
nSeats += purchase.getNumberOfSeats();
34+
const {
35+
key,
36+
version,
37+
} = purchase;
38+
licensedItems.forEach(licensedItem => {
39+
if (licensedItem["key"] === key && licensedItem["version"] <= version) {
40+
licensedItem["seats"].push({
41+
licensedItemId: purchase["licensedItemId"],
42+
licensedItemPurchaseId: purchase["licensedItemPurchaseId"],
43+
numOfSeats: purchase["numOfSeats"],
44+
expireAt: new Date(purchase["expireAt"]),
45+
});
46+
}
47+
});
48+
})
49+
},
50+
51+
getLowerLicensedItems: function(licensedItems, key, version) {
52+
const lowerLicensedItems = [];
53+
licensedItems.forEach(licensedItem => {
54+
if (licensedItem["key"] === key && licensedItem["version"] < version) {
55+
lowerLicensedItems.push(licensedItem);
56+
}
57+
});
58+
return lowerLicensedItems;
59+
},
60+
61+
seatsToNSeats: function(seats) {
62+
let nSeats = 0;
63+
seats.forEach(seat => {
64+
if ("numOfSeats" in seat) {
65+
nSeats += seat["numOfSeats"];
66+
} else if ("getNumOfSeats" in seat) {
67+
nSeats += seat.getNumOfSeats();
3668
}
3769
});
3870
return nSeats;
3971
},
72+
73+
licensedResourceNameAndVersion: function(licensedResource) {
74+
return `${licensedResource["source"]["features"]["name"]} ${licensedResource["source"]["features"]["version"]}`;
75+
},
4076
},
4177

4278
members: {
@@ -68,7 +104,7 @@ qx.Class.define("osparc.store.LicensedItems", {
68104
return osparc.data.Resources.fetch("licensedItems", "purchases", purchasesParams, options);
69105
},
70106

71-
purchaseLicensedItem: function(licensedItemId, walletId, pricingPlanId, pricingUnitId, numberOfSeats) {
107+
purchaseLicensedItem: function(licensedItemId, walletId, pricingPlanId, pricingUnitId, numOfSeats) {
72108
const params = {
73109
url: {
74110
licensedItemId
@@ -77,7 +113,7 @@ qx.Class.define("osparc.store.LicensedItems", {
77113
"wallet_id": walletId,
78114
"pricing_plan_id": pricingPlanId,
79115
"pricing_unit_id": pricingUnitId,
80-
"num_of_seats": numberOfSeats, // this should go away
116+
"num_of_seats": numOfSeats, // this should go away
81117
},
82118
}
83119
return osparc.data.Resources.fetch("licensedItems", "purchase", params);

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

Lines changed: 114 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ qx.Class.define("osparc.vipMarket.AnatomicalModelDetails", {
5555
const anatomicalModelsData = this.getAnatomicalModelsData();
5656
if (anatomicalModelsData && anatomicalModelsData["licensedResources"].length) {
5757
this.__addModelsInfo();
58-
this.__addPricingUnits();
58+
this.__addPricing();
5959
this.__addSeatsSection();
6060
} else {
6161
const selectModelLabel = new qx.ui.basic.Label().set({
@@ -108,7 +108,8 @@ qx.Class.define("osparc.vipMarket.AnatomicalModelDetails", {
108108
const topGrid = new qx.ui.layout.Grid(8, 8);
109109
topGrid.setColumnFlex(0, 1);
110110
const topLayout = new qx.ui.container.Composite(topGrid);
111-
const description = anatomicalModel["description"] || "";
111+
let description = anatomicalModel["description"] || "";
112+
description = description.replace(/SPEAG/g, " "); // remove SPEAG substring
112113
const delimiter = " - ";
113114
let titleAndSubtitle = description.split(delimiter);
114115
if (titleAndSubtitle.length > 0) {
@@ -289,19 +290,28 @@ qx.Class.define("osparc.vipMarket.AnatomicalModelDetails", {
289290
modelId: anatomicalModelsData["licensedResources"][selectedIdx]["source"]["id"]
290291
});
291292
}, this);
292-
if (anatomicalModelsData["purchases"].length) {
293+
if (anatomicalModelsData["seats"].length) {
293294
importSection.add(importButton);
294295
}
295296
return importSection;
296297
},
297298

298-
__addPricingUnits: function() {
299-
const anatomicalModelsData = this.getAnatomicalModelsData();
299+
__addPricing: function() {
300+
const layout = new qx.ui.container.Composite(new qx.ui.layout.VBox().set({
301+
alignX: "center"
302+
}))
303+
304+
const pricingLayout = new qx.ui.container.Composite(new qx.ui.layout.VBox()).set({
305+
allowGrowX: false,
306+
decorator: "border",
307+
});
308+
layout.add(pricingLayout)
309+
300310
const pricingUnitsLayout = new qx.ui.container.Composite(new qx.ui.layout.HBox(10).set({
301311
alignX: "center"
302312
}));
303-
304-
osparc.store.Pricing.getInstance().fetchPricingUnits(anatomicalModelsData["pricingPlanId"])
313+
const licensedItemData = this.getAnatomicalModelsData();
314+
osparc.store.Pricing.getInstance().fetchPricingUnits(licensedItemData["pricingPlanId"])
305315
.then(pricingUnits => {
306316
pricingUnits.forEach(pricingUnit => {
307317
pricingUnit.set({
@@ -312,35 +322,118 @@ qx.Class.define("osparc.vipMarket.AnatomicalModelDetails", {
312322
});
313323
pUnit.addListener("rentPricingUnit", () => {
314324
this.fireDataEvent("modelPurchaseRequested", {
315-
licensedItemId: anatomicalModelsData["licensedItemId"],
316-
pricingPlanId: anatomicalModelsData["pricingPlanId"],
325+
licensedItemId: licensedItemData["licensedItemId"],
326+
pricingPlanId: licensedItemData["pricingPlanId"],
317327
pricingUnitId: pricingUnit.getPricingUnitId(),
318328
});
319329
}, this);
320330
pricingUnitsLayout.add(pUnit);
321331
});
322332
})
323333
.catch(err => console.error(err));
324-
325334
this._add(pricingUnitsLayout);
335+
pricingLayout.add(pricingUnitsLayout)
336+
337+
const poweredByLabel = new qx.ui.basic.Label().set({
338+
font: "text-14",
339+
padding: 10,
340+
rich: true,
341+
alignX: "center",
342+
});
343+
osparc.store.LicensedItems.getInstance().getLicensedItems()
344+
.then(licensedItems => {
345+
const lowerLicensedItems = osparc.store.LicensedItems.getLowerLicensedItems(licensedItems, licensedItemData["key"], licensedItemData["version"])
346+
if (licensedItemData["licensedResources"].length > 1 || lowerLicensedItems.length) {
347+
let text = this.tr("This Bundle gives you access to:") + "<br>";
348+
licensedItemData["licensedResources"].forEach(licensedResource => {
349+
text += `- ${osparc.store.LicensedItems.licensedResourceNameAndVersion(licensedResource)}<br>`;
350+
});
351+
lowerLicensedItems.forEach(lowerLicensedItem => {
352+
lowerLicensedItem["licensedResources"].forEach(licensedResource => {
353+
text += `- ${osparc.store.LicensedItems.licensedResourceNameAndVersion(licensedResource)} <br>`;
354+
});
355+
})
356+
poweredByLabel.setValue(text);
357+
pricingLayout.add(poweredByLabel);
358+
}
359+
});
360+
361+
this._add(layout);
326362
},
327363

328364
__addSeatsSection: function() {
329-
const anatomicalModelsData = this.getAnatomicalModelsData();
330-
const seatsSection = new qx.ui.container.Composite(new qx.ui.layout.VBox(5).set({
365+
const licensedItemData = this.getAnatomicalModelsData();
366+
if (licensedItemData["seats"].length === 0) {
367+
return;
368+
}
369+
370+
const layout = new qx.ui.container.Composite(new qx.ui.layout.VBox().set({
331371
alignX: "center",
332372
}));
333373

334-
anatomicalModelsData["purchases"].forEach(purchase => {
335-
const seatsText = "seat" + (purchase["numberOfSeats"] > 1 ? "s" : "");
336-
const entry = new qx.ui.basic.Label().set({
337-
value: `${purchase["numberOfSeats"]} ${seatsText} available until ${osparc.utils.Utils.formatDate(purchase["expiresAt"])}`,
338-
font: "text-14",
339-
});
340-
seatsSection.add(entry);
341-
});
374+
osparc.store.LicensedItems.getInstance().getLicensedItems()
375+
.then(licensedItems => {
376+
const grid = new qx.ui.layout.Grid(15, 5);
377+
grid.setColumnAlign(0, "left", "middle");
378+
grid.setColumnAlign(1, "center", "middle");
379+
grid.setColumnAlign(2, "right", "middle");
380+
const seatsSection = new qx.ui.container.Composite(grid).set({
381+
allowGrowX: false,
382+
decorator: "border",
383+
padding: 10,
384+
});
385+
386+
let rowIdx = 0;
387+
seatsSection.add(new qx.ui.basic.Label("Models Rented").set({font: "title-14"}), {
388+
column: 0,
389+
row: rowIdx,
390+
});
391+
seatsSection.add(new qx.ui.basic.Label("Seats").set({font: "title-14"}), {
392+
column: 1,
393+
row: rowIdx,
394+
});
395+
seatsSection.add(new qx.ui.basic.Label("Until").set({font: "title-14"}), {
396+
column: 2,
397+
row: rowIdx,
398+
});
399+
rowIdx++;
400+
401+
const entryToGrid = (licensedResource, seat, row) => {
402+
const title = osparc.store.LicensedItems.licensedResourceNameAndVersion(licensedResource);
403+
seatsSection.add(new qx.ui.basic.Label(title).set({font: "text-14"}), {
404+
column: 0,
405+
row,
406+
});
407+
seatsSection.add(new qx.ui.basic.Label(seat["numOfSeats"].toString()).set({font: "text-14"}), {
408+
column: 1,
409+
row,
410+
});
411+
seatsSection.add(new qx.ui.basic.Label(osparc.utils.Utils.formatDate(seat["expireAt"])).set({font: "text-14"}), {
412+
column: 2,
413+
row,
414+
});
415+
};
416+
417+
licensedItemData["seats"].forEach(seat => {
418+
licensedItemData["licensedResources"].forEach(licensedResource => {
419+
entryToGrid(licensedResource, seat, rowIdx);
420+
rowIdx++;
421+
});
422+
});
342423

343-
this._add(seatsSection);
424+
const lowerLicensedItems = osparc.store.LicensedItems.getLowerLicensedItems(licensedItems, licensedItemData["key"], licensedItemData["version"])
425+
lowerLicensedItems.forEach(lowerLicensedItem => {
426+
lowerLicensedItem["seats"].forEach(seat => {
427+
lowerLicensedItem["licensedResources"].forEach(licensedResource => {
428+
entryToGrid(licensedResource, seat, rowIdx);
429+
rowIdx++;
430+
});
431+
});
432+
});
433+
434+
layout.add(seatsSection);
435+
this._add(layout);
436+
});
344437
},
345438
}
346439
});

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

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,18 +54,18 @@ qx.Class.define("osparc.vipMarket.AnatomicalModelListItem", {
5454
init: "selectable"
5555
},
5656

57-
licenseKey: {
57+
key: {
5858
check: "String",
5959
init: null,
6060
nullable: false,
61-
event: "changeLicenseKey",
61+
event: "changeKey",
6262
},
6363

64-
licenseVersion: {
64+
version: {
6565
check: "String",
6666
init: null,
6767
nullable: false,
68-
event: "changeLicenseVersion",
68+
event: "changeVersion",
6969
},
7070

7171
licensedItemId: {
@@ -105,12 +105,12 @@ qx.Class.define("osparc.vipMarket.AnatomicalModelListItem", {
105105
event: "changePricingPlanId",
106106
},
107107

108-
purchases: {
108+
seats: {
109109
check: "Array",
110110
nullable: false,
111111
init: [],
112-
event: "changePurchases",
113-
apply: "__applyPurchases",
112+
event: "changeSeats",
113+
apply: "__applySeats",
114114
},
115115
},
116116

@@ -179,9 +179,9 @@ qx.Class.define("osparc.vipMarket.AnatomicalModelListItem", {
179179
this.getChildControl("name").setValue(value);
180180
},
181181

182-
__applyPurchases: function(purchases) {
182+
__applySeats: function(seats) {
183183
const nSeatsLabel = this.getChildControl("n-seats");
184-
const nSeats = osparc.store.LicensedItems.purchasesToNSeats(purchases);
184+
const nSeats = osparc.store.LicensedItems.seatsToNSeats(seats);
185185
if (nSeats) {
186186
nSeatsLabel.setValue(`(${nSeats})`);
187187
} else {

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ qx.Class.define("osparc.vipMarket.Market", {
4242
.then(values => {
4343
const licensedItems = values[0];
4444
const purchasedItems = values[1];
45+
osparc.store.LicensedItems.populateSeatsFromPurchases(licensedItems, purchasedItems);
4546
const categories = [];
4647
const purchasedCategory = {
4748
categoryId: "purchasedModels",
@@ -51,7 +52,7 @@ qx.Class.define("osparc.vipMarket.Market", {
5152
};
5253
categories.push(purchasedCategory);
5354
licensedItems.forEach(licensedItem => {
54-
if (purchasedItems.find(purchasedItem => purchasedItem["licensedItemId"] === licensedItem["licensedItemId"])) {
55+
if (licensedItem["seats"].length) {
5556
purchasedCategory["items"].push(licensedItem);
5657
if (!openCategory) {
5758
openCategory = purchasedCategory["categoryId"];
@@ -133,9 +134,10 @@ qx.Class.define("osparc.vipMarket.Market", {
133134
.then(values => {
134135
const licensedItems = values[0];
135136
const purchasedItems = values[1];
137+
osparc.store.LicensedItems.populateSeatsFromPurchases(licensedItems, purchasedItems);
136138
let items = [];
137139
licensedItems.forEach(licensedItem => {
138-
if (purchasedItems.find(purchasedItem => purchasedItem["licensedItemId"] === licensedItem["licensedItemId"])) {
140+
if (licensedItem["seats"].length) {
139141
items.push(licensedItem);
140142
}
141143
});

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ qx.Class.define("osparc.vipMarket.MarketWindow", {
2323

2424
osparc.utils.Utils.setIdToWidget(this, "storeWindow");
2525

26-
const width = 1050;
26+
const width = 1080;
2727
const height = 700;
2828
this.set({
2929
width,

0 commit comments

Comments
 (0)