From 30ef66139e2b787b7615fdfdada6fa4afab7d971 Mon Sep 17 00:00:00 2001 From: vinith-kovan <156108204+vinith-kovan@users.noreply.github.com> Date: Thu, 9 May 2024 20:46:43 +0530 Subject: [PATCH] [PM 5007] migrate premium component (#8387) * premium component migration * premium component migration * premium component migration * premium component migration --- .../billing/individual/premium.component.html | 258 +++++++++--------- .../billing/individual/premium.component.ts | 116 ++++---- 2 files changed, 196 insertions(+), 178 deletions(-) diff --git a/apps/web/src/app/billing/individual/premium.component.html b/apps/web/src/app/billing/individual/premium.component.html index f962f7cfe1..e3afa7779b 100644 --- a/apps/web/src/app/billing/individual/premium.component.html +++ b/apps/web/src/app/billing/individual/premium.component.html @@ -1,129 +1,143 @@ - -
-

{{ "goPremium" | i18n }}

-
- - {{ "alreadyPremiumFromOrg" | i18n }} - - -

{{ "premiumUpgradeUnlockFeatures" | i18n }}

- -

- {{ - "premiumPriceWithFamilyPlan" | i18n: (premiumPrice | currency: "$") : familyPlanMaxUserCount - }} - {{ - "bitwardenFamiliesPlan" | i18n - }} -

- +

{{ "goPremium" | i18n }}

+ - {{ "purchasePremium" | i18n }} -
-
- -

{{ "uploadLicenseFilePremium" | i18n }}

-
-
- - - {{ - "licenseFileDesc" | i18n: "bitwarden_premium_license.json" - }} -
- + {{ this.licenseFile ? this.licenseFile.name : ("noFileChosen" | i18n) }} + + + {{ "licenseFileDesc" | i18n: "bitwarden_premium_license.json" }} + +
-
-
-

{{ "addons" | i18n }}

-
-
- - - {{ - "additionalStorageIntervalDesc" - | i18n: "1 GB" : (storageGbPrice | currency: "$") : ("year" | i18n) - }} + + + +

{{ "addons" | i18n }}

+
+ + {{ "additionalStorageGb" | i18n }} + + {{ + "additionalStorageIntervalDesc" + | i18n: "1 GB" : (storageGbPrice | currency: "$") : ("year" | i18n) + }} +
-
-

{{ "summary" | i18n }}

- {{ "premiumMembership" | i18n }}: {{ premiumPrice | currency: "$" }}
- {{ "additionalStorageGb" | i18n }}: {{ additionalStorage || 0 }} GB × - {{ storageGbPrice | currency: "$" }} = - {{ additionalStorageTotal | currency: "$" }} -
-

{{ "paymentInformation" | i18n }}

- - -
-
- {{ "planPrice" | i18n }}: {{ subtotal | currency: "USD $" }} -
- - {{ "estimatedTax" | i18n }}: {{ taxCharges | currency: "USD $" }} - + + +

{{ "summary" | i18n }}

+ {{ "premiumMembership" | i18n }}: {{ premiumPrice | currency: "$" }}
+ {{ "additionalStorageGb" | i18n }}: {{ additionalStorage || 0 }} GB × + {{ storageGbPrice | currency: "$" }} = + {{ additionalStorageTotal | currency: "$" }} +
+
+ +

{{ "paymentInformation" | i18n }}

+ + +
+
+ {{ "planPrice" | i18n }}: {{ subtotal | currency: "USD $" }} +
+ + {{ "estimatedTax" | i18n }}: {{ taxCharges | currency: "USD $" }} + +
+
+

+ {{ "total" | i18n }}: {{ total | currency: "USD $" }}/{{ "year" | i18n }} +

-
-

- {{ "total" | i18n }}: {{ total | currency: "USD $" }}/{{ "year" | i18n }} -

-
- {{ "paymentChargedAnnually" | i18n }} - +

{{ "paymentChargedAnnually" | i18n }}

+ + diff --git a/apps/web/src/app/billing/individual/premium.component.ts b/apps/web/src/app/billing/individual/premium.component.ts index 60536c17b5..79a8bad75a 100644 --- a/apps/web/src/app/billing/individual/premium.component.ts +++ b/apps/web/src/app/billing/individual/premium.component.ts @@ -1,4 +1,5 @@ import { Component, OnInit, ViewChild } from "@angular/core"; +import { FormControl, FormGroup, Validators } from "@angular/forms"; import { Router } from "@angular/router"; import { firstValueFrom, Observable } from "rxjs"; @@ -7,7 +8,6 @@ import { TokenService } from "@bitwarden/common/auth/abstractions/token.service" import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service"; import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; -import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction"; @@ -26,11 +26,16 @@ export class PremiumComponent implements OnInit { premiumPrice = 10; familyPlanMaxUserCount = 6; storageGbPrice = 4; - additionalStorage = 0; cloudWebVaultUrl: string; + licenseFile: File = null; formPromise: Promise; - + protected licenseForm = new FormGroup({ + file: new FormControl(null, [Validators.required]), + }); + protected addonForm = new FormGroup({ + additionalStorage: new FormControl(0, [Validators.max(99), Validators.min(0)]), + }); constructor( private apiService: ApiService, private i18nService: I18nService, @@ -39,14 +44,17 @@ export class PremiumComponent implements OnInit { private router: Router, private messagingService: MessagingService, private syncService: SyncService, - private logService: LogService, private environmentService: EnvironmentService, private billingAccountProfileStateService: BillingAccountProfileStateService, ) { this.selfHosted = platformUtilsService.isSelfHost(); this.canAccessPremium$ = billingAccountProfileStateService.hasPremiumFromAnySource$; } - + protected setSelectedFile(event: Event) { + const fileInputEl = event.target; + const file: File = fileInputEl.files.length > 0 ? fileInputEl.files[0] : null; + this.licenseFile = file; + } async ngOnInit() { this.cloudWebVaultUrl = await firstValueFrom(this.environmentService.cloudWebVaultUrl$); if (await firstValueFrom(this.billingAccountProfileStateService.hasPremiumPersonally$)) { @@ -56,13 +64,11 @@ export class PremiumComponent implements OnInit { return; } } - - async submit() { - let files: FileList = null; + submit = async () => { + this.licenseForm.markAllAsTouched(); + this.addonForm.markAllAsTouched(); if (this.selfHosted) { - const fileEl = document.getElementById("file") as HTMLInputElement; - files = fileEl.files; - if (files == null || files.length === 0) { + if (this.licenseFile == null) { this.platformUtilsService.showToast( "error", this.i18nService.t("errorOccurred"), @@ -72,53 +78,48 @@ export class PremiumComponent implements OnInit { } } - try { - if (this.selfHosted) { - // eslint-disable-next-line @typescript-eslint/no-misused-promises - if (!this.tokenService.getEmailVerified()) { - this.platformUtilsService.showToast( - "error", - this.i18nService.t("errorOccurred"), - this.i18nService.t("verifyEmailFirst"), - ); - return; - } - - const fd = new FormData(); - fd.append("license", files[0]); - this.formPromise = this.apiService.postAccountLicense(fd).then(() => { - return this.finalizePremium(); - }); - } else { - this.formPromise = this.paymentComponent - .createPaymentToken() - .then((result) => { - const fd = new FormData(); - fd.append("paymentMethodType", result[1].toString()); - if (result[0] != null) { - fd.append("paymentToken", result[0]); - } - fd.append("additionalStorageGb", (this.additionalStorage || 0).toString()); - fd.append("country", this.taxInfoComponent.taxInfo.country); - fd.append("postalCode", this.taxInfoComponent.taxInfo.postalCode); - return this.apiService.postPremium(fd); - }) - .then((paymentResponse) => { - if (!paymentResponse.success && paymentResponse.paymentIntentClientSecret != null) { - return this.paymentComponent.handleStripeCardPayment( - paymentResponse.paymentIntentClientSecret, - () => this.finalizePremium(), - ); - } else { - return this.finalizePremium(); - } - }); + if (this.selfHosted) { + // eslint-disable-next-line @typescript-eslint/no-misused-promises + if (!this.tokenService.getEmailVerified()) { + this.platformUtilsService.showToast( + "error", + this.i18nService.t("errorOccurred"), + this.i18nService.t("verifyEmailFirst"), + ); + return; } - await this.formPromise; - } catch (e) { - this.logService.error(e); + + const fd = new FormData(); + fd.append("license", this.licenseFile); + await this.apiService.postAccountLicense(fd).then(() => { + return this.finalizePremium(); + }); + } else { + await this.paymentComponent + .createPaymentToken() + .then((result) => { + const fd = new FormData(); + fd.append("paymentMethodType", result[1].toString()); + if (result[0] != null) { + fd.append("paymentToken", result[0]); + } + fd.append("additionalStorageGb", (this.additionalStorage || 0).toString()); + fd.append("country", this.taxInfoComponent.taxInfo.country); + fd.append("postalCode", this.taxInfoComponent.taxInfo.postalCode); + return this.apiService.postPremium(fd); + }) + .then((paymentResponse) => { + if (!paymentResponse.success && paymentResponse.paymentIntentClientSecret != null) { + return this.paymentComponent.handleStripeCardPayment( + paymentResponse.paymentIntentClientSecret, + () => this.finalizePremium(), + ); + } else { + return this.finalizePremium(); + } + }); } - } + }; async finalizePremium() { await this.apiService.refreshIdentityToken(); @@ -127,6 +128,9 @@ export class PremiumComponent implements OnInit { await this.router.navigate(["/settings/subscription/user-subscription"]); } + get additionalStorage(): number { + return this.addonForm.get("additionalStorage").value; + } get additionalStorageTotal(): number { return this.storageGbPrice * Math.abs(this.additionalStorage || 0); }