Skip to content

Commit

Permalink
🎨 [Frontend] ViP Market: Give access to purchased lower versions and …
Browse files Browse the repository at this point in the history
…how info (#7230)
  • Loading branch information
odeimaiz authored Feb 14, 2025
1 parent 4ca666e commit 4bed41e
Show file tree
Hide file tree
Showing 6 changed files with 228 additions and 116 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,53 @@ qx.Class.define("osparc.store.LicensedItems", {
},

statics: {
purchasesToNSeats: function(purchases) {
let nSeats = 0;
populateSeatsFromPurchases: function(licensedItems, purchases) {
// reset seats
licensedItems.forEach(licensedItem => licensedItem["seats"] = []);
// populate seats
purchases.forEach(purchase => {
if ("numberOfSeats" in purchase) {
nSeats += purchase["numberOfSeats"];
} else if ("getNumberOfSeats" in purchase) {
nSeats += purchase.getNumberOfSeats();
const {
key,
version,
} = purchase;
licensedItems.forEach(licensedItem => {
if (licensedItem["key"] === key && licensedItem["version"] <= version) {
licensedItem["seats"].push({
licensedItemId: purchase["licensedItemId"],
licensedItemPurchaseId: purchase["licensedItemPurchaseId"],
numOfSeats: purchase["numOfSeats"],
expireAt: new Date(purchase["expireAt"]),
});
}
});
})
},

getLowerLicensedItems: function(licensedItems, key, version) {
const lowerLicensedItems = [];
licensedItems.forEach(licensedItem => {
if (licensedItem["key"] === key && licensedItem["version"] < version) {
lowerLicensedItems.push(licensedItem);
}
});
return lowerLicensedItems;
},

seatsToNSeats: function(seats) {
let nSeats = 0;
seats.forEach(seat => {
if ("numOfSeats" in seat) {
nSeats += seat["numOfSeats"];
} else if ("getNumOfSeats" in seat) {
nSeats += seat.getNumOfSeats();
}
});
return nSeats;
},

licensedResourceNameAndVersion: function(licensedResource) {
return `${licensedResource["source"]["features"]["name"]} ${licensedResource["source"]["features"]["version"]}`;
},
},

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

purchaseLicensedItem: function(licensedItemId, walletId, pricingPlanId, pricingUnitId, numberOfSeats) {
purchaseLicensedItem: function(licensedItemId, walletId, pricingPlanId, pricingUnitId, numOfSeats) {
const params = {
url: {
licensedItemId
Expand All @@ -77,7 +113,7 @@ qx.Class.define("osparc.store.LicensedItems", {
"wallet_id": walletId,
"pricing_plan_id": pricingPlanId,
"pricing_unit_id": pricingUnitId,
"num_of_seats": numberOfSeats, // this should go away
"num_of_seats": numOfSeats, // this should go away
},
}
return osparc.data.Resources.fetch("licensedItems", "purchase", params);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ qx.Class.define("osparc.vipMarket.AnatomicalModelDetails", {
const anatomicalModelsData = this.getAnatomicalModelsData();
if (anatomicalModelsData && anatomicalModelsData["licensedResources"].length) {
this.__addModelsInfo();
this.__addPricingUnits();
this.__addPricing();
this.__addSeatsSection();
} else {
const selectModelLabel = new qx.ui.basic.Label().set({
Expand Down Expand Up @@ -108,7 +108,8 @@ qx.Class.define("osparc.vipMarket.AnatomicalModelDetails", {
const topGrid = new qx.ui.layout.Grid(8, 8);
topGrid.setColumnFlex(0, 1);
const topLayout = new qx.ui.container.Composite(topGrid);
const description = anatomicalModel["description"] || "";
let description = anatomicalModel["description"] || "";
description = description.replace(/SPEAG/g, " "); // remove SPEAG substring
const delimiter = " - ";
let titleAndSubtitle = description.split(delimiter);
if (titleAndSubtitle.length > 0) {
Expand Down Expand Up @@ -289,19 +290,28 @@ qx.Class.define("osparc.vipMarket.AnatomicalModelDetails", {
modelId: anatomicalModelsData["licensedResources"][selectedIdx]["source"]["id"]
});
}, this);
if (anatomicalModelsData["purchases"].length) {
if (anatomicalModelsData["seats"].length) {
importSection.add(importButton);
}
return importSection;
},

__addPricingUnits: function() {
const anatomicalModelsData = this.getAnatomicalModelsData();
__addPricing: function() {
const layout = new qx.ui.container.Composite(new qx.ui.layout.VBox().set({
alignX: "center"
}))

const pricingLayout = new qx.ui.container.Composite(new qx.ui.layout.VBox()).set({
allowGrowX: false,
decorator: "border",
});
layout.add(pricingLayout)

const pricingUnitsLayout = new qx.ui.container.Composite(new qx.ui.layout.HBox(10).set({
alignX: "center"
}));

osparc.store.Pricing.getInstance().fetchPricingUnits(anatomicalModelsData["pricingPlanId"])
const licensedItemData = this.getAnatomicalModelsData();
osparc.store.Pricing.getInstance().fetchPricingUnits(licensedItemData["pricingPlanId"])
.then(pricingUnits => {
pricingUnits.forEach(pricingUnit => {
pricingUnit.set({
Expand All @@ -312,35 +322,118 @@ qx.Class.define("osparc.vipMarket.AnatomicalModelDetails", {
});
pUnit.addListener("rentPricingUnit", () => {
this.fireDataEvent("modelPurchaseRequested", {
licensedItemId: anatomicalModelsData["licensedItemId"],
pricingPlanId: anatomicalModelsData["pricingPlanId"],
licensedItemId: licensedItemData["licensedItemId"],
pricingPlanId: licensedItemData["pricingPlanId"],
pricingUnitId: pricingUnit.getPricingUnitId(),
});
}, this);
pricingUnitsLayout.add(pUnit);
});
})
.catch(err => console.error(err));

this._add(pricingUnitsLayout);
pricingLayout.add(pricingUnitsLayout)

const poweredByLabel = new qx.ui.basic.Label().set({
font: "text-14",
padding: 10,
rich: true,
alignX: "center",
});
osparc.store.LicensedItems.getInstance().getLicensedItems()
.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:") + "<br>";
licensedItemData["licensedResources"].forEach(licensedResource => {
text += `- ${osparc.store.LicensedItems.licensedResourceNameAndVersion(licensedResource)}<br>`;
});
lowerLicensedItems.forEach(lowerLicensedItem => {
lowerLicensedItem["licensedResources"].forEach(licensedResource => {
text += `- ${osparc.store.LicensedItems.licensedResourceNameAndVersion(licensedResource)} <br>`;
});
})
poweredByLabel.setValue(text);
pricingLayout.add(poweredByLabel);
}
});

this._add(layout);
},

__addSeatsSection: function() {
const anatomicalModelsData = this.getAnatomicalModelsData();
const seatsSection = new qx.ui.container.Composite(new qx.ui.layout.VBox(5).set({
const licensedItemData = this.getAnatomicalModelsData();
if (licensedItemData["seats"].length === 0) {
return;
}

const layout = new qx.ui.container.Composite(new qx.ui.layout.VBox().set({
alignX: "center",
}));

anatomicalModelsData["purchases"].forEach(purchase => {
const seatsText = "seat" + (purchase["numberOfSeats"] > 1 ? "s" : "");
const entry = new qx.ui.basic.Label().set({
value: `${purchase["numberOfSeats"]} ${seatsText} available until ${osparc.utils.Utils.formatDate(purchase["expiresAt"])}`,
font: "text-14",
});
seatsSection.add(entry);
});
osparc.store.LicensedItems.getInstance().getLicensedItems()
.then(licensedItems => {
const grid = new qx.ui.layout.Grid(15, 5);
grid.setColumnAlign(0, "left", "middle");
grid.setColumnAlign(1, "center", "middle");
grid.setColumnAlign(2, "right", "middle");
const seatsSection = new qx.ui.container.Composite(grid).set({
allowGrowX: false,
decorator: "border",
padding: 10,
});

let rowIdx = 0;
seatsSection.add(new qx.ui.basic.Label("Models Rented").set({font: "title-14"}), {
column: 0,
row: rowIdx,
});
seatsSection.add(new qx.ui.basic.Label("Seats").set({font: "title-14"}), {
column: 1,
row: rowIdx,
});
seatsSection.add(new qx.ui.basic.Label("Until").set({font: "title-14"}), {
column: 2,
row: rowIdx,
});
rowIdx++;

const entryToGrid = (licensedResource, seat, row) => {
const title = osparc.store.LicensedItems.licensedResourceNameAndVersion(licensedResource);
seatsSection.add(new qx.ui.basic.Label(title).set({font: "text-14"}), {
column: 0,
row,
});
seatsSection.add(new qx.ui.basic.Label(seat["numOfSeats"].toString()).set({font: "text-14"}), {
column: 1,
row,
});
seatsSection.add(new qx.ui.basic.Label(osparc.utils.Utils.formatDate(seat["expireAt"])).set({font: "text-14"}), {
column: 2,
row,
});
};

licensedItemData["seats"].forEach(seat => {
licensedItemData["licensedResources"].forEach(licensedResource => {
entryToGrid(licensedResource, seat, rowIdx);
rowIdx++;
});
});

this._add(seatsSection);
const lowerLicensedItems = osparc.store.LicensedItems.getLowerLicensedItems(licensedItems, licensedItemData["key"], licensedItemData["version"])
lowerLicensedItems.forEach(lowerLicensedItem => {
lowerLicensedItem["seats"].forEach(seat => {
lowerLicensedItem["licensedResources"].forEach(licensedResource => {
entryToGrid(licensedResource, seat, rowIdx);
rowIdx++;
});
});
});

layout.add(seatsSection);
this._add(layout);
});
},
}
});
Original file line number Diff line number Diff line change
Expand Up @@ -54,18 +54,18 @@ qx.Class.define("osparc.vipMarket.AnatomicalModelListItem", {
init: "selectable"
},

licenseKey: {
key: {
check: "String",
init: null,
nullable: false,
event: "changeLicenseKey",
event: "changeKey",
},

licenseVersion: {
version: {
check: "String",
init: null,
nullable: false,
event: "changeLicenseVersion",
event: "changeVersion",
},

licensedItemId: {
Expand Down Expand Up @@ -105,12 +105,12 @@ qx.Class.define("osparc.vipMarket.AnatomicalModelListItem", {
event: "changePricingPlanId",
},

purchases: {
seats: {
check: "Array",
nullable: false,
init: [],
event: "changePurchases",
apply: "__applyPurchases",
event: "changeSeats",
apply: "__applySeats",
},
},

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

__applyPurchases: function(purchases) {
__applySeats: function(seats) {
const nSeatsLabel = this.getChildControl("n-seats");
const nSeats = osparc.store.LicensedItems.purchasesToNSeats(purchases);
const nSeats = osparc.store.LicensedItems.seatsToNSeats(seats);
if (nSeats) {
nSeatsLabel.setValue(`(${nSeats})`);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ qx.Class.define("osparc.vipMarket.Market", {
.then(values => {
const licensedItems = values[0];
const purchasedItems = values[1];
osparc.store.LicensedItems.populateSeatsFromPurchases(licensedItems, purchasedItems);
const categories = [];
const purchasedCategory = {
categoryId: "purchasedModels",
Expand All @@ -51,7 +52,7 @@ qx.Class.define("osparc.vipMarket.Market", {
};
categories.push(purchasedCategory);
licensedItems.forEach(licensedItem => {
if (purchasedItems.find(purchasedItem => purchasedItem["licensedItemId"] === licensedItem["licensedItemId"])) {
if (licensedItem["seats"].length) {
purchasedCategory["items"].push(licensedItem);
if (!openCategory) {
openCategory = purchasedCategory["categoryId"];
Expand Down Expand Up @@ -133,9 +134,10 @@ qx.Class.define("osparc.vipMarket.Market", {
.then(values => {
const licensedItems = values[0];
const purchasedItems = values[1];
osparc.store.LicensedItems.populateSeatsFromPurchases(licensedItems, purchasedItems);
let items = [];
licensedItems.forEach(licensedItem => {
if (purchasedItems.find(purchasedItem => purchasedItem["licensedItemId"] === licensedItem["licensedItemId"])) {
if (licensedItem["seats"].length) {
items.push(licensedItem);
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ qx.Class.define("osparc.vipMarket.MarketWindow", {

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

const width = 1050;
const width = 1080;
const height = 700;
this.set({
width,
Expand Down
Loading

0 comments on commit 4bed41e

Please sign in to comment.