diff --git a/services/static-webserver/client/source/class/osparc/component/resourceUsage/OverviewTable.js b/services/static-webserver/client/source/class/osparc/component/resourceUsage/OverviewTable.js index 04a3e60db62..3daf5ae81ad 100644 --- a/services/static-webserver/client/source/class/osparc/component/resourceUsage/OverviewTable.js +++ b/services/static-webserver/client/source/class/osparc/component/resourceUsage/OverviewTable.js @@ -85,11 +85,15 @@ qx.Class.define("osparc.component.resourceUsage.OverviewTable", { const serviceName = parts.pop(); newData[cols["service"].pos] = serviceName + ":" + data["service_version"]; } - const startTime = new Date(data["started_at"]); - newData[cols["start"].pos] = osparc.utils.Utils.formatDateAndTime(startTime); - const stopTime = new Date(data["stopped_at"]); - const durationTimeSec = (stopTime - startTime)/1000; - newData[cols["duration"].pos] = durationTimeSec; + if (data["started_at"]) { + const startTime = new Date(data["started_at"]); + newData[cols["start"].pos] = osparc.utils.Utils.formatDateAndTime(startTime); + if (data["stopped_at"]) { + const stopTime = new Date(data["stopped_at"]); + const durationTimeSec = (stopTime - startTime)/1000; + newData[cols["duration"].pos] = durationTimeSec; + } + } newData[cols["status"].pos] = qx.lang.String.firstUp(data["service_run_status"].toLowerCase()); newData[cols["wallet"].pos] = data["wallet_label"] ? data["wallet_label"] : "unknown"; newData[cols["cost"].pos] = "unknown"; 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 65e24638c61..b51e985fecf 100644 --- a/services/static-webserver/client/source/class/osparc/data/Resources.js +++ b/services/static-webserver/client/source/class/osparc/data/Resources.js @@ -641,6 +641,21 @@ qx.Class.define("osparc.data.Resources", { } } }, + /* + * PAYMENTS + */ + "payments": { + endpoints: { + get: { + method: "GET", + url: statics.API + "/wallets/-/payments" + }, + post: { + method: "POST", + url: statics.API + "/wallets/{walletId}/payments" + } + } + }, /* * CLUSTERS */ diff --git a/services/static-webserver/client/source/class/osparc/desktop/credits/BuyCredits.js b/services/static-webserver/client/source/class/osparc/desktop/credits/BuyCredits.js index 5d6aea406aa..07e78ae2f12 100644 --- a/services/static-webserver/client/source/class/osparc/desktop/credits/BuyCredits.js +++ b/services/static-webserver/client/source/class/osparc/desktop/credits/BuyCredits.js @@ -25,7 +25,7 @@ qx.Class.define("osparc.desktop.credits.BuyCredits", { this.__buildLayout(); - this.initNCredits(); + this.initTotalPrice(); this.initCreditPrice(); }, @@ -38,40 +38,40 @@ qx.Class.define("osparc.desktop.credits.BuyCredits", { apply: "__applyWallet" }, - nCredits: { + totalPrice: { check: "Number", init: 50, nullable: false, - event: "changeNCredits", - apply: "__applyNCredits" + event: "changeTotalPrice", + apply: "__applyTotalPrice" }, creditPrice: { check: "Number", - init: 5, + init: 1, nullable: false, event: "changeCreditPrice", apply: "__applyCreditPrice" }, - totalPrice: { + nCredits: { check: "Number", init: null, nullable: false, - event: "changeTotalPrice" + event: "changeNCredits" } }, events: { - "transactionSuccessful": "qx.event.type.Data" + "transactionCompleted": "qx.event.type.Event" }, statics: { CREDIT_PRICES: [ - [1, 3], - [10, 2.5], - [100, 2], - [1000, 1.5] + [1, 1], + [10, 1], + [100, 1], + [1000, 1] ] }, @@ -109,21 +109,21 @@ qx.Class.define("osparc.desktop.credits.BuyCredits", { control = this.__getCreditsLeftView(); this.getChildControl("wallet-info").add(control); break; - case "credit-offers-view": - control = this.__getCreditOffersView(); + case "one-time-payment-layout": + control = new qx.ui.container.Composite(new qx.ui.layout.VBox(15)); this.getChildControl("left-side").add(control); break; case "credit-selector": control = this.__getCreditSelector(); - this.getChildControl("left-side").add(control); + this.getChildControl("one-time-payment-layout").add(control); break; case "summary-view": control = this.__getSummaryView(); - this.getChildControl("left-side").add(control); + this.getChildControl("one-time-payment-layout").add(control); break; case "buy-button": control = this.__getBuyButton(); - this.getChildControl("left-side").add(control); + this.getChildControl("one-time-payment-layout").add(control); break; case "credits-explanation": control = this.__getCreditsExplanation(); @@ -147,32 +147,35 @@ qx.Class.define("osparc.desktop.credits.BuyCredits", { __buildLayout: function() { this.getChildControl("wallet-selector"); this.getChildControl("credits-left-view"); - // this.getChildControl("credit-offers-view"); + this.__builyOneTimePayment(); + + this.getChildControl("credits-explanation"); + }, + + __builyOneTimePayment: function() { this.getChildControl("credit-selector"); this.getChildControl("summary-view"); this.getChildControl("buy-button"); - - this.getChildControl("credits-explanation"); }, - __applyNCredits: function(nCredits) { + __applyTotalPrice: function(totalPrice) { let creditPrice = this.self().CREDIT_PRICES[0][1]; - if (nCredits >= this.self().CREDIT_PRICES[1][0]) { + if (totalPrice >= this.self().CREDIT_PRICES[1][0]) { creditPrice = this.self().CREDIT_PRICES[1][1]; } - if (nCredits >= this.self().CREDIT_PRICES[2][0]) { + if (totalPrice >= this.self().CREDIT_PRICES[2][0]) { creditPrice = this.self().CREDIT_PRICES[2][1]; } - if (nCredits >= this.self().CREDIT_PRICES[3][0]) { + if (totalPrice >= this.self().CREDIT_PRICES[3][0]) { creditPrice = this.self().CREDIT_PRICES[3][1]; } this.setCreditPrice(creditPrice); - this.setTotalPrice(creditPrice * nCredits); + this.setNCredits(totalPrice / creditPrice); }, __applyCreditPrice: function(creditPrice) { - this.setTotalPrice(creditPrice * this.getNCredits()); + this.setNCredits(creditPrice * this.getTotalPrice()); }, __getWalletSelector: function() { @@ -202,91 +205,40 @@ qx.Class.define("osparc.desktop.credits.BuyCredits", { return creditsLeftView; }, - __getCreditOffersView: function() { - const grid = new qx.ui.layout.Grid(15, 10); - grid.setColumnAlign(0, "right", "middle"); - const layout = new qx.ui.container.Composite(grid).set({ - padding: 5, - backgroundColor: "background-main-3" - }); - - let row = 0; - const creditsTitle = new qx.ui.basic.Label(this.tr("Credits")).set({ - font: "text-16" - }); - layout.add(creditsTitle, { - row, - column: 0 - }); - - const pricePerCreditTitle = new qx.ui.basic.Label(this.tr("Price/Credit")).set({ - font: "text-16" - }); - layout.add(pricePerCreditTitle, { - row, - column: 1 - }); - row++; - - this.self().CREDIT_PRICES.forEach(pair => { - const creditsLabel = new qx.ui.basic.Label().set({ - value: "> " + pair[0], - font: "text-14" - }); - layout.add(creditsLabel, { - row, - column: 0 - }); - - const pricePerCreditLabel = new qx.ui.basic.Label().set({ - value: pair[1] + " $", - alignX: "center", - font: "text-14" - }); - layout.add(pricePerCreditLabel, { - row, - column: 1 - }); - - row++; - }); - return layout; - }, - __getCreditSelector: function() { const vLayout = new qx.ui.container.Composite(new qx.ui.layout.VBox(5)); const label = new qx.ui.basic.Label().set({ - value: this.tr("Credits:"), + value: this.tr("Payment amount:"), font: "text-14" }); vLayout.add(label); const layout = new qx.ui.container.Composite(new qx.ui.layout.HBox(0)); - const minBtn = new qx.ui.form.Button().set({ + const lessBtn = new qx.ui.form.Button().set({ label: this.tr("-"), width: 25 }); - minBtn.addListener("execute", () => this.setNCredits(this.getNCredits()-1)); - layout.add(minBtn); + lessBtn.addListener("execute", () => this.setTotalPrice(this.getTotalPrice()-1)); + layout.add(lessBtn); - const nCreditsField = new qx.ui.form.TextField().set({ + const paymentAmountField = new qx.ui.form.TextField().set({ width: 100, textAlign: "center", font: "text-14" }); - this.bind("nCredits", nCreditsField, "value", { + this.bind("totalPrice", paymentAmountField, "value", { converter: val => val.toString() }); - nCreditsField.addListener("changeValue", e => this.setNCredits(parseInt(e.getData()))); - layout.add(nCreditsField); + paymentAmountField.addListener("changeValue", e => this.setTotalPrice(Number(e.getData()))); + layout.add(paymentAmountField); const moreBtn = new qx.ui.form.Button().set({ label: this.tr("+"), width: 25 }); - moreBtn.addListener("execute", () => this.setNCredits(this.getNCredits()+1)); + moreBtn.addListener("execute", () => this.setTotalPrice(this.getTotalPrice()+1)); layout.add(moreBtn); vLayout.add(layout); @@ -312,7 +264,7 @@ qx.Class.define("osparc.desktop.credits.BuyCredits", { font: "text-16" }); this.bind("totalPrice", totalPriceLabel, "value", { - converter: totalPrice => totalPrice + " $" + converter: totalPrice => (totalPrice ? totalPrice.toFixed(2) : 0).toString() + " $" }); layout.add(totalPriceLabel, { row, @@ -320,6 +272,26 @@ qx.Class.define("osparc.desktop.credits.BuyCredits", { }); row++; + const nCreditsTitle = new qx.ui.basic.Label().set({ + value: "Total credits", + font: "text-16" + }); + layout.add(nCreditsTitle, { + row, + column: 0 + }); + const nCreditsLabel = new qx.ui.basic.Label().set({ + font: "text-16" + }); + this.bind("nCredits", nCreditsLabel, "value", { + converter: nCredits => (nCredits ? nCredits.toFixed(2) : 0).toString() + }); + layout.add(nCreditsLabel, { + row, + column: 1 + }); + row++; + const creditPriceTitle = new qx.ui.basic.Label().set({ value: "Credit price", font: "text-14" @@ -422,48 +394,19 @@ qx.Class.define("osparc.desktop.credits.BuyCredits", { const totalPrice = this.getTotalPrice(); const wallet = this.getWallet(); buying(); - setTimeout(() => { - if (nCredits < 100) { - let url = "https://www.payment.appmotion.de"; - url += "/pay?id=2"; - - const paymentGateway = new osparc.desktop.credits.PaymentGateway().set({ - url, - nCredits, - totalPrice, - walletName: wallet.getName() - }); - const title = "AppMotion's middleware"; - const win = osparc.ui.window.Window.popUpInWindow(paymentGateway, title, 320, 475); - win.center(); - win.open(); - paymentGateway.addListener("paymentSuccessful", () => { - transactionFinished(); - let msg = "Payment Successful"; - msg += "
"; - msg += "You now have " + nCredits + " more credits"; - osparc.component.message.FlashMessenger.getInstance().logAs(msg, "INFO", null, 10000); - wallet.setCreditsAvailable(wallet.getCreditsAvailable() + nCredits); - this.fireDataEvent("transactionSuccessful", { - nCredits, - totalPrice, - walletName: wallet.getName() - }); - }); - paymentGateway.addListener("paymentFailed", () => { - transactionFinished(); - let msg = "Payment Failed"; - msg += "
"; - msg += "Please try again"; - osparc.component.message.FlashMessenger.getInstance().logAs(msg, "ERROR", null, 10000); - }); - paymentGateway.addListener("close", () => { - win.close(); - transactionFinished(); - }); - } else { - transactionFinished(); + const params = { + url: { + walletId: wallet.getWalletId() + }, + data: { + priceDollars: totalPrice, + osparcCredits: nCredits + } + }; + osparc.data.Resources.fetch("payments", "post", params) + .then(data => { + const url = data["paymentFormUrl"]; const options = { width: 400, height: 400, @@ -478,12 +421,28 @@ qx.Class.define("osparc.desktop.credits.BuyCredits", { blocker.setBlockerColor("#FFF"); blocker.setBlockerOpacity(0.6); this.__pgWindow = qx.bom.Window.open( - "https://www.sandbox.paypal.com/checkoutnow?sessionID=uid_528c54d94a_mti6mty6mzk&buttonSessionID=uid_fd2db9090d_mti6mty6mzk&stickinessID=uid_b4ee25a7cf_mdc6nta6ntq&smokeHash=&token=6XJ77332V85719833&fundingSource=paypal&buyerCountry=GB&locale.x=en_GB&commit=false&enableFunding.0=paylater&clientID=Ac9r0wZ444AH4c8nEvA7l5QbBaGtf8B0y2ZSTGvQDXFNb0HlkFb9cseCUWMZ0_mJUJPfd2NYjJx4HYLI&env=sandbox&sdkMeta=eyJ1cmwiOiJodHRwczovL3d3dy5wYXlwYWwuY29tL3Nkay9qcz9jbGllbnQtaWQ9QWM5cjB3WjQ0NEFINGM4bkV2QTdsNVFiQmFHdGY4QjB5MlpTVEd2UURYRk5iMEhsa0ZiOWNzZUNVV01aMF9tSlVKUGZkMk5Zakp4NEhZTEkmY29tbWl0PWZhbHNlJmN1cnJlbmN5PUdCUCZkaXNhYmxlLWZ1bmRpbmc9Y2FyZCZlbmFibGUtZnVuZGluZz1wYXlsYXRlciZidXllci1jb3VudHJ5PUdCJmxvY2FsZT1lbl9HQiZjb21wb25lbnRzPW1lc3NhZ2VzLGJ1dHRvbnMiLCJhdHRycyI6eyJkYXRhLXVpZCI6InVpZF9iZnZyaHB5ZXZ4ZXF1aXVpc2FodHJiamhpb3piangifX0&xcomponent=1&version=5.0.394", + url, "pgWindow", options, modal, useNativeModalDialog ); + this.__pgWindow.onbeforeunload = () => { + transactionFinished(); + // inform backend + }; + + // Listen to socket event + const socket = osparc.wrapper.WebSocket.getInstance(); + const slotName = "paymentCompleted"; + if (!socket.slotExists(slotName)) { + socket.on(slotName, jsonString => { + const paymentData = JSON.parse(jsonString); + console.log(paymentData); + this.fireEvent("transactionCompleted"); + this.__pgWindow.close(); + }); + } // enhance the blocker const blockerDomEl = blocker.getBlockerElement(); @@ -505,8 +464,12 @@ qx.Class.define("osparc.desktop.credits.BuyCredits", { blockerDomEl.appendChild(label); blockerDomEl.addEventListener("click", () => this.__pgWindow.focus()); - } - }, 3000); + }) + .catch(err => { + console.error(err); + osparc.component.message.FlashMessenger.logAs(err.message, "ERROR"); + transactionFinished(); + }); }); return buyBtn; }, @@ -515,7 +478,7 @@ qx.Class.define("osparc.desktop.credits.BuyCredits", { const layout = new qx.ui.container.Composite(new qx.ui.layout.VBox(20)); const label1 = new qx.ui.basic.Label().set({ - value: "Here we explain what you can run/do with credits.", + value: "Explain here what a Credit is and what one can run/do with them.", font: "text-16", rich: true, wrap: true @@ -523,20 +486,12 @@ qx.Class.define("osparc.desktop.credits.BuyCredits", { layout.add(label1); const label2 = new qx.ui.basic.Label().set({ - value: "They can be used for:
- using the GUI
- modeling
- running solvers
- transfer data
- import VIP models?
- collaboration?", - font: "text-16", - rich: true, - wrap: true - }); - layout.add(label2); - - const label3 = new qx.ui.basic.Label().set({ value: "If something goes wrong you won't be charged", font: "text-16", rich: true, wrap: true }); - layout.add(label3); + layout.add(label2); return layout; } diff --git a/services/static-webserver/client/source/class/osparc/desktop/credits/CreditsWindow.js b/services/static-webserver/client/source/class/osparc/desktop/credits/CreditsWindow.js index 9e66733f85c..8e002f6ddca 100644 --- a/services/static-webserver/client/source/class/osparc/desktop/credits/CreditsWindow.js +++ b/services/static-webserver/client/source/class/osparc/desktop/credits/CreditsWindow.js @@ -21,8 +21,6 @@ qx.Class.define("osparc.desktop.credits.CreditsWindow", { construct: function(walletsEnabled = false) { this.base(arguments, "credits", this.tr("User Center")); - this.__walletsEnabled = walletsEnabled; - const viewWidth = walletsEnabled ? 1050 : 800; const viewHeight = walletsEnabled ? 700 : 600; @@ -37,41 +35,8 @@ qx.Class.define("osparc.desktop.credits.CreditsWindow", { appearance: "service-window" }); - const tabViews = this.__tabsView = new qx.ui.tabview.TabView().set({ - barPosition: "left", - contentPadding: 0 - }); - tabViews.getChildControl("bar").add(this.__getMiniProfileView()); - - if (this.__walletsEnabled) { - const overviewPage = this.__overviewPage = this.__getOverviewPage(); - tabViews.add(overviewPage); - } - - const profilePage = this.__profilePage = this.__getProfilePage(); - tabViews.add(profilePage); - - if (this.__walletsEnabled) { - const walletsPage = this.__walletsPage = this.__getWalletsPage(); - tabViews.add(walletsPage); - } - - if (this.__walletsEnabled) { - const buyCreditsPage = this.__buyCreditsPage = this.__getBuyCreditsPage(); - tabViews.add(buyCreditsPage); - } - - if (this.__walletsEnabled) { - const transactionsPage = this.__transactionsPage = this.__getTransactionsPage(); - tabViews.add(transactionsPage); - } - - if (osparc.data.Permissions.getInstance().canDo("usage.all.read")) { - const usageOverviewPage = this.__usageOverviewPage = this.__getUsageOverviewPage(); - tabViews.add(usageOverviewPage); - } - - this.add(tabViews); + const userCenter = this.__userCenter = new osparc.desktop.credits.UserCenter(walletsEnabled); + this.add(userCenter); }, statics: { @@ -84,190 +49,14 @@ qx.Class.define("osparc.desktop.credits.CreditsWindow", { }, members: { - __walletsEnabled: null, - __tabsView: null, - __overviewPage: null, - __profilePage: null, - __walletsPage: null, - __buyCreditsPage: null, - __transactionsPage: null, - __usageOverviewPage: null, - __buyCredits: null, - __transactionsTable: null, - - __getMiniProfileView: function() { - const layout = new qx.ui.container.Composite(new qx.ui.layout.VBox(8)).set({ - alignX: "center", - maxWidth: 150 - }); - - const authData = osparc.auth.Data.getInstance(); - const email = authData.getEmail(); - const img = new qx.ui.basic.Image().set({ - source: osparc.utils.Avatar.getUrl(email, 100), - maxWidth: 80, - maxHeight: 80, - scale: true, - decorator: new qx.ui.decoration.Decorator().set({ - radius: 30 - }), - alignX: "center" - }); - layout.add(img); - - const name = new qx.ui.basic.Label().set({ - font: "text-14", - alignX: "center" - }); - layout.add(name); - authData.bind("firstName", name, "value", { - converter: firstName => firstName + " " + authData.getLastName() - }); - authData.bind("lastName", name, "value", { - converter: lastName => authData.getFirstName() + " " + lastName - }); - - const emailLabel = new qx.ui.basic.Label(email).set({ - font: "text-13", - alignX: "center" - }); - layout.add(emailLabel); - - layout.add(new qx.ui.core.Spacer(15, 15), { - flex: 1 - }); - - return layout; - }, - - __getOverviewPage: function() { - const title = this.tr("Overview"); - const iconSrc = "@FontAwesome5Solid/table/22"; - const page = new osparc.desktop.preferences.pages.BasePage(title, iconSrc); - page.showLabelOnTab(); - const overview = new osparc.desktop.credits.Overview(); - overview.set({ - margin: 10 - }); - overview.addListener("toWallets", () => this.openWallets()); - overview.addListener("toTransactions", () => this.__openTransactions()); - overview.addListener("toUsageOverview", () => this.__openUsageOverview()); - page.add(overview); - return page; - }, - - __getProfilePage: function() { - const page = new osparc.desktop.credits.ProfilePage(); - page.showLabelOnTab(); - return page; - }, - - __getWalletsPage: function() { - const title = this.tr("Wallets"); - const iconSrc = "@MaterialIcons/account_balance_wallet/22"; - const page = new osparc.desktop.preferences.pages.BasePage(title, iconSrc); - page.showLabelOnTab(); - const walletsView = new osparc.desktop.wallets.WalletsView(); - walletsView.set({ - margin: 10 - }); - walletsView.addListener("buyCredits", e => { - this.__openBuyCredits(); - const { - walletId - } = e.getData(); - const store = osparc.store.Store.getInstance(); - const found = store.getWallets().find(wallet => wallet.getWalletId() === parseInt(walletId)); - if (found) { - this.__buyCredits.setWallet(found); - } - }); - page.add(walletsView); - return page; - }, - - __getBuyCreditsPage: function() { - const title = this.tr("Buy Credits"); - const iconSrc = "@FontAwesome5Solid/dollar-sign/22"; - const page = new osparc.desktop.preferences.pages.BasePage(title, iconSrc); - page.showLabelOnTab(); - const buyCredits = this.__buyCredits = new osparc.desktop.credits.BuyCredits(); - buyCredits.set({ - margin: 10 - }); - buyCredits.addListener("transactionSuccessful", e => { - const { - nCredits, - totalPrice, - walletName - } = e.getData(); - this.__transactionsTable.addRow(nCredits, totalPrice, walletName); - this.__openTransactions(); - }, this); - page.add(buyCredits); - return page; - }, - - __getTransactionsPage: function() { - const title = this.tr("Transactions"); - const iconSrc = "@FontAwesome5Solid/exchange-alt/22"; - const page = new osparc.desktop.preferences.pages.BasePage(title, iconSrc); - page.showLabelOnTab(); - const transactions = this.__transactionsTable = new osparc.desktop.credits.Transactions(); - transactions.set({ - margin: 10 - }); - page.add(transactions); - return page; - }, - - __getUsageOverviewPage: function() { - const title = this.tr("Usage"); - const iconSrc = "@FontAwesome5Solid/list/22"; - const page = new osparc.desktop.preferences.pages.BasePage(title, iconSrc); - page.showLabelOnTab(); - const usageOverview = new osparc.component.resourceUsage.Overview(); - usageOverview.set({ - margin: 10 - }); - page.add(usageOverview); - return page; - }, - - __openPage: function(page) { - if (page) { - this.__tabsView.setSelection([page]); - } - }, + __userCenter: null, openOverview: function() { - if (this.__overviewPage) { - this.__openPage(this.__overviewPage); - } else { - // fallback - this.__openPage(this.__profilePage); - } + this.__userCenter.openOverview(); }, openWallets: function() { - if (this.__walletsPage) { - this.__openPage(this.__walletsPage); - } else { - // fallback - this.__openPage(this.__profilePage); - } - }, - - __openBuyCredits: function() { - this.__openPage(this.__buyCreditsPage); - }, - - __openTransactions: function() { - this.__openPage(this.__transactionsPage); - }, - - __openUsageOverview: function() { - this.__openPage(this.__usageOverviewPage); + this.__userCenter.openWallets(); } } }); diff --git a/services/static-webserver/client/source/class/osparc/desktop/credits/Overview.js b/services/static-webserver/client/source/class/osparc/desktop/credits/Overview.js index c2395686447..2a533e5354c 100644 --- a/services/static-webserver/client/source/class/osparc/desktop/credits/Overview.js +++ b/services/static-webserver/client/source/class/osparc/desktop/credits/Overview.js @@ -30,6 +30,7 @@ qx.Class.define("osparc.desktop.credits.Overview", { }, events: { + "buyCredits": "qx.event.type.Data", "toWallets": "qx.event.type.Event", "toTransactions": "qx.event.type.Event", "toUsageOverview": "qx.event.type.Event" @@ -41,7 +42,9 @@ qx.Class.define("osparc.desktop.credits.Overview", { switch (id) { case "wallets-card": { const content = this.__createWalletsView(); - control = this.__createOverviewCard("Wallets", content, "toWallets"); + const wallets = osparc.store.Store.getInstance().getWallets(); + control = this.__createOverviewCard(`Wallets (${wallets.length})`, content, "toWallets"); + control.getChildren()[0].setValue(this.tr("Credits")); this._add(control, { column: 0, row: 0 @@ -112,11 +115,88 @@ qx.Class.define("osparc.desktop.credits.Overview", { }, __createWalletsView: function() { + const activeWallet = osparc.store.Store.getInstance().getActiveWallet(); + const preferredWallet = osparc.desktop.credits.Utils.getFavouriteWallet(); + const oneWallet = activeWallet ? activeWallet : preferredWallet; + if (oneWallet) { + // show one wallet + return this.__showOneWallet(oneWallet); + } + // show some wallets + return this.__showSomeWallets(); + }, + + __showOneWallet: function(wallet) { + const layout = new qx.ui.container.Composite(new qx.ui.layout.VBox(10)); + + const titleLayout = new qx.ui.container.Composite(new qx.ui.layout.HBox(10)).set({ + alignY: "middle" + }); + const maxSize = 24; + // thumbnail or shared or not shared + const thumbnail = new qx.ui.basic.Image().set({ + backgroundColor: "transparent", + alignX: "center", + alignY: "middle", + scale: true, + allowShrinkX: true, + allowShrinkY: true, + maxHeight: maxSize, + maxWidth: maxSize + }); + const value = wallet.getThumbnail(); + if (value) { + thumbnail.setSource(value); + } else if (wallet.getAccessRights() && wallet.getAccessRights().length > 1) { + thumbnail.setSource(osparc.utils.Icons.organization(maxSize-4)); + } else { + thumbnail.setSource(osparc.utils.Icons.user(maxSize-4)); + } + titleLayout.add(thumbnail); + // name + const walletName = new qx.ui.basic.Label().set({ + font: "text-14", + alignY: "middle", + maxWidth: 200 + }); + wallet.bind("name", walletName, "value"); + titleLayout.add(walletName); + layout.add(titleLayout); + + const progressBar = new osparc.desktop.credits.CreditsIndicatorWText(wallet, "vertical").set({ + allowShrinkY: true + }); + progressBar.getChildControl("credits-indicator").set({ + minWidth: 100 + }); + progressBar.getChildControl("credits-text").set({ + font: "text-16" + }); + layout.add(progressBar); + + const buyButton = new qx.ui.form.Button().set({ + label: this.tr("Buy Credits"), + icon: "@FontAwesome5Solid/dollar-sign/16", + maxHeight: 30, + alignY: "middle", + allowGrowX: false, + height: 25 + }); + const myAccessRights = wallet.getMyAccessRights(); + buyButton.setVisibility(myAccessRights && myAccessRights["write"] ? "visible" : "excluded"); + buyButton.addListener("execute", () => this.fireDataEvent("buyCredits", { + walletId: wallet.getWalletId() + }), this); + layout.add(buyButton); + + return layout; + }, + + __showSomeWallets: function() { const grid = new qx.ui.layout.Grid(12, 8); const layout = new qx.ui.container.Composite(grid); - - const wallets = osparc.store.Store.getInstance().getWallets(); const maxWallets = 5; + const wallets = osparc.store.Store.getInstance().getWallets(); for (let i=0; i isDefault ? "@FontAwesome5Solid/star/18" : "@FontAwesome5Regular/star/18" - }); - wallet.bind("defaultWallet", starImage, "textColor", { - converter: isDefault => isDefault ? "strong-main" : "text" - }); - layout.add(starImage, { - column, - row: i - }); - column++; } return layout; @@ -214,33 +278,45 @@ qx.Class.define("osparc.desktop.credits.Overview", { }); }); - const entries = [[ - osparc.utils.Utils.formatDateAndTime(new Date()), - 10, - 0, - "My Wallet", - "Welcome to Sim4Life" - ], [ - osparc.utils.Utils.formatDateAndTime(new Date()), - 50, - 125, - "My Wallet", - "" - ]]; - const maxTransactions = 4; - entries.forEach((entry, row) => { - if (row < maxTransactions) { - entry.forEach((data, column) => { - const text = new qx.ui.basic.Label(data.toString()).set({ - font: "text-13" + osparc.data.Resources.fetch("payments", "get") + .then(transactions => { + if ("data" in transactions) { + const maxTransactions = 4; + transactions["data"].forEach((transaction, row) => { + if (row < maxTransactions) { + let walletName = null; + if (transaction["walletId"]) { + const found = osparc.desktop.credits.Utils.getWallet(transaction["walletId"]); + if (found) { + walletName = found.getName(); + } + } + const entry = [ + osparc.utils.Utils.formatDateAndTime(new Date(transaction["createdAt"])), + transaction["priceDollars"].toString(), + transaction["osparcCredits"].toString(), + walletName, + transaction["comment"] + ]; + entry.forEach((data, column) => { + const text = new qx.ui.basic.Label(data).set({ + font: "text-13" + }); + layout.add(text, { + row: row+1, + column + }); + }); + row++; + } }); - layout.add(text, { - row: row+1, - column - }); - }); - } - }); + } + }) + .catch(err => { + osparc.component.message.FlashMessenger.getInstance().logAs(err.message, "ERROR"); + console.error(err); + }); + return layout; }, diff --git a/services/static-webserver/client/source/class/osparc/desktop/credits/Transactions.js b/services/static-webserver/client/source/class/osparc/desktop/credits/Transactions.js index 36393698e4a..ae08df4a286 100644 --- a/services/static-webserver/client/source/class/osparc/desktop/credits/Transactions.js +++ b/services/static-webserver/client/source/class/osparc/desktop/credits/Transactions.js @@ -32,13 +32,13 @@ qx.Class.define("osparc.desktop.credits.Transactions", { pos: 0, title: qx.locale.Manager.tr("Date") }, - credits: { + price: { pos: 1, - title: qx.locale.Manager.tr("Credits") + title: qx.locale.Manager.tr("Price") }, - price: { + credits: { pos: 2, - title: qx.locale.Manager.tr("Price") + title: qx.locale.Manager.tr("Credits") }, wallet: { pos: 3, @@ -73,36 +73,49 @@ qx.Class.define("osparc.desktop.credits.Transactions", { table.makeItLoose(); this._add(table); + this.refetchData(); + }, + + refetchData: function() { this.__rawData = []; - // welcome - this.addRow( - 20, - 0, - "My Wallet", - "Welcome to Sim4Life", - null - ); - - // one payment - this.addRow( - 50, - 125, - "My Wallet", - "", - "https://assets.website-files.com/63206faf68ab2dc3ee3e623b/634ea60a9381021f775e7a28_Placeholder%20PDF.pdf" - ); + osparc.data.Resources.fetch("payments", "get") + .then(transactions => { + if ("data" in transactions) { + transactions["data"].forEach(transaction => { + let walletName = null; + if (transaction["walletId"]) { + const found = osparc.desktop.credits.Utils.getWallet(transaction["walletId"]); + if (found) { + walletName = found.getName(); + } + } + this.__addRow( + transaction["createdAt"], + transaction["priceDollars"], + transaction["osparcCredits"], + walletName, + transaction["comment"], + "https://assets.website-files.com/63206faf68ab2dc3ee3e623b/634ea60a9381021f775e7a28_Placeholder%20PDF.pdf" + ); + }); + } + }) + .catch(err => { + osparc.component.message.FlashMessenger.getInstance().logAs(err.message, "ERROR"); + console.error(err); + }); }, __createPdfIconWithLink: function(link) { return `Invoice`; }, - addRow: function(nCredits, price, walletName, comment, invoiceUrl) { + __addRow: function(createdAt, price, nCredits, walletName, comment, invoiceUrl) { const newData = [ - osparc.utils.Utils.formatDateAndTime(new Date()), - nCredits ? nCredits : 0, + osparc.utils.Utils.formatDateAndTime(new Date(createdAt)), price ? price : 0, + nCredits ? nCredits : 0, walletName ? walletName : "Unknown Wallet", comment ? comment : "", invoiceUrl ? this.__createPdfIconWithLink(invoiceUrl) : null diff --git a/services/static-webserver/client/source/class/osparc/desktop/credits/UserCenter.js b/services/static-webserver/client/source/class/osparc/desktop/credits/UserCenter.js index 1ee31b85e68..f9b7afda273 100644 --- a/services/static-webserver/client/source/class/osparc/desktop/credits/UserCenter.js +++ b/services/static-webserver/client/source/class/osparc/desktop/credits/UserCenter.js @@ -34,19 +34,6 @@ qx.Class.define("osparc.desktop.credits.UserCenter", { }) }); - const titleLayout = new qx.ui.container.Composite(new qx.ui.layout.HBox(5)); - const title = new qx.ui.basic.Label().set({ - value: this.tr("User Center"), - font: "text-16", - textAlign: "center", - allowGrowX: true, - marginBottom: 10 - }); - titleLayout.add(title, { - flex: 1 - }); - this._add(titleLayout); - const tabViews = this.__tabsView = new qx.ui.tabview.TabView().set({ barPosition: "left", contentPadding: 0 @@ -159,6 +146,17 @@ qx.Class.define("osparc.desktop.credits.UserCenter", { overview.set({ margin: 10 }); + overview.addListener("buyCredits", e => { + this.__openBuyCredits(); + const { + walletId + } = e.getData(); + const store = osparc.store.Store.getInstance(); + const found = store.getWallets().find(wallet => wallet.getWalletId() === parseInt(walletId)); + if (found) { + this.__buyCredits.setWallet(found); + } + }); overview.addListener("toWallets", () => this.openWallets()); overview.addListener("toTransactions", () => this.__openTransactions()); overview.addListener("toUsageOverview", () => this.__openUsageOverview()); @@ -205,15 +203,7 @@ qx.Class.define("osparc.desktop.credits.UserCenter", { buyCredits.set({ margin: 10 }); - buyCredits.addListener("transactionSuccessful", e => { - const { - nCredits, - totalPrice, - walletName - } = e.getData(); - this.__transactionsTable.addRow(nCredits, totalPrice, walletName); - this.__openTransactions(); - }, this); + buyCredits.addListener("transactionCompleted", () => this.__openTransactions(true), this); page.add(buyCredits); return page; }, @@ -272,8 +262,13 @@ qx.Class.define("osparc.desktop.credits.UserCenter", { this.__openPage(this.__buyCreditsPage); }, - __openTransactions: function() { - this.__openPage(this.__transactionsPage); + __openTransactions: function(fetchTransactions = false) { + if (fetchTransactions) { + this.__transactionsTable.refetch(); + this.__openPage(this.__transactionsPage); + } else { + this.__openPage(this.__transactionsPage); + } }, __openUsageOverview: function() { diff --git a/services/static-webserver/client/source/class/osparc/desktop/credits/Utils.js b/services/static-webserver/client/source/class/osparc/desktop/credits/Utils.js index 61f374412b8..95eb0ca7956 100644 --- a/services/static-webserver/client/source/class/osparc/desktop/credits/Utils.js +++ b/services/static-webserver/client/source/class/osparc/desktop/credits/Utils.js @@ -85,6 +85,16 @@ qx.Class.define("osparc.desktop.credits.Utils", { return false; }, + getWallet: function(walletId) { + const store = osparc.store.Store.getInstance(); + const wallets = store.getWallets(); + const favouriteWallet = wallets.find(wallet => wallet.getWalletId() === walletId); + if (favouriteWallet) { + return favouriteWallet; + } + return null; + }, + getFavouriteWallet: function() { const store = osparc.store.Store.getInstance(); const wallets = store.getWallets(); diff --git a/services/static-webserver/client/source/class/osparc/desktop/credits/WalletsMiniViewer.js b/services/static-webserver/client/source/class/osparc/desktop/credits/WalletsMiniViewer.js index a6b21e83066..1988e004591 100644 --- a/services/static-webserver/client/source/class/osparc/desktop/credits/WalletsMiniViewer.js +++ b/services/static-webserver/client/source/class/osparc/desktop/credits/WalletsMiniViewer.js @@ -62,11 +62,10 @@ qx.Class.define("osparc.desktop.credits.WalletsMiniViewer", { __reloadLayout: function() { const activeWallet = this.getActiveWallet(); - if (activeWallet) { - this.__showOneWallet(activeWallet); - } else if (osparc.store.Store.getInstance().getWallets().find(wallet => wallet.isDefaultWallet())) { - const found = osparc.store.Store.getInstance().getWallets().find(wallet => wallet.isDefaultWallet()); - this.__showOneWallet(found); + const preferredWallet = osparc.desktop.credits.Utils.getFavouriteWallet(); + const oneWallet = activeWallet ? activeWallet : preferredWallet; + if (oneWallet) { + this.__showOneWallet(oneWallet); } else if (osparc.store.Store.getInstance().getWallets().length) { this.__showAllWallets(); } else { diff --git a/services/static-webserver/client/source/class/osparc/navigation/NavigationBar.js b/services/static-webserver/client/source/class/osparc/navigation/NavigationBar.js index 46d413c15d5..975c4b129d9 100644 --- a/services/static-webserver/client/source/class/osparc/navigation/NavigationBar.js +++ b/services/static-webserver/client/source/class/osparc/navigation/NavigationBar.js @@ -272,8 +272,8 @@ qx.Class.define("osparc.navigation.NavigationBar", { } case "wallets-viewer": control = new osparc.desktop.credits.WalletsMiniViewer().set({ - maxWidth: 50, - minWidth: 50, + maxWidth: 60, + minWidth: 60, maxHeight: this.self().HEIGHT }); this.getChildControl("right-items").add(control);