diff --git a/apps/web/src/app/billing/individual/user-subscription.component.html b/apps/web/src/app/billing/individual/user-subscription.component.html index bed41c8dc5..5f9e6463f1 100644 --- a/apps/web/src/app/billing/individual/user-subscription.component.html +++ b/apps/web/src/app/billing/individual/user-subscription.component.html @@ -1,10 +1,10 @@ - {{ "loading" | i18n }} + {{ "loading" | i18n }} -

{{ "subscriptionPendingCanceled" | i18n }}

+

{{ "subscriptionPendingCanceled" | i18n }}

@@ -39,12 +37,12 @@
{{ sub.expiration | date: "mediumDate" }}
{{ "neverExpires" | i18n }}
-
-
+
+
{{ "status" | i18n }}
- {{ (subscription && subscription.status) || "-" }} + {{ (subscription && subscription.status) || "-" }} {{ "pendingCancellation" | i18n }} @@ -61,19 +59,19 @@
-
- {{ "details" | i18n }} - - +
+ {{ "details" | i18n }} + +
- - + - -
+ {{ i.name }} {{ i.quantity > 1 ? "×" + i.quantity : "" }} @ {{ i.amount | currency: "$" }} {{ i.quantity * i.amount | currency: "$" }} /{{ i.interval | i18n }}{{ i.quantity * i.amount | currency: "$" }} /{{ i.interval | i18n }}
+ +
@@ -91,27 +89,9 @@ {{ "launchCloudSubscription" | i18n }}
-
-
- -

{{ "updateLicense" | i18n }}

- - -
-
-
+
-

{{ "storage" | i18n }}

-

{{ "subscriptionStorage" | i18n: sub.maxStorageGb || 0 : sub.storageName || "0 MB" }}

-
-
- {{ storagePercentage / 100 | percent }} -
-
+

{{ "storage" | i18n }}

+

+ {{ "subscriptionStorage" | i18n: sub.maxStorageGb || 0 : sub.storageName || "0 MB" }} +

+ -
-
- -
diff --git a/apps/web/src/app/billing/individual/user-subscription.component.ts b/apps/web/src/app/billing/individual/user-subscription.component.ts index fa21317c18..8535f23f82 100644 --- a/apps/web/src/app/billing/individual/user-subscription.component.ts +++ b/apps/web/src/app/billing/individual/user-subscription.component.ts @@ -20,6 +20,10 @@ import { OffboardingSurveyDialogResultType, openOffboardingSurvey, } from "../shared/offboarding-survey.component"; +import { + UpdateLicenseDialogComponent, + UpdateLicenseDialogResult, +} from "../shared/update-license-dialog.component"; @Component({ templateUrl: "user-subscription.component.html", @@ -131,21 +135,16 @@ export class UserSubscriptionComponent implements OnInit { }); } - updateLicense() { + updateLicense = async () => { if (this.loading) { return; } - this.showUpdateLicense = true; - } - - closeUpdateLicense(load: boolean) { - this.showUpdateLicense = false; - if (load) { - // FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling. - // eslint-disable-next-line @typescript-eslint/no-floating-promises - this.load(); + const dialogRef = UpdateLicenseDialogComponent.open(this.dialogService); + const result = await lastValueFrom(dialogRef.closed); + if (result === UpdateLicenseDialogResult.Updated) { + await this.load(); } - } + }; adjustStorage = (add: boolean) => { return async () => { diff --git a/apps/web/src/app/billing/shared/billing-shared.module.ts b/apps/web/src/app/billing/shared/billing-shared.module.ts index 35fe33c7e0..0031cff775 100644 --- a/apps/web/src/app/billing/shared/billing-shared.module.ts +++ b/apps/web/src/app/billing/shared/billing-shared.module.ts @@ -12,6 +12,7 @@ import { PaymentMethodComponent } from "./payment-method.component"; import { PaymentComponent } from "./payment.component"; import { SecretsManagerSubscribeComponent } from "./sm-subscribe.component"; import { TaxInfoComponent } from "./tax-info.component"; +import { UpdateLicenseDialogComponent } from "./update-license-dialog.component"; import { UpdateLicenseComponent } from "./update-license.component"; @NgModule({ @@ -24,6 +25,7 @@ import { UpdateLicenseComponent } from "./update-license.component"; PaymentMethodComponent, SecretsManagerSubscribeComponent, UpdateLicenseComponent, + UpdateLicenseDialogComponent, OffboardingSurveyComponent, ], exports: [ @@ -34,6 +36,7 @@ import { UpdateLicenseComponent } from "./update-license.component"; BillingHistoryComponent, SecretsManagerSubscribeComponent, UpdateLicenseComponent, + UpdateLicenseDialogComponent, OffboardingSurveyComponent, ], }) diff --git a/apps/web/src/app/billing/shared/update-license-dialog.component.html b/apps/web/src/app/billing/shared/update-license-dialog.component.html new file mode 100644 index 0000000000..6430c47528 --- /dev/null +++ b/apps/web/src/app/billing/shared/update-license-dialog.component.html @@ -0,0 +1,40 @@ +
+ + + + {{ "licenseFile" | i18n }} +
+ + {{ licenseFile ? licenseFile.name : ("noFileChosen" | i18n) }} +
+ + {{ "licenseFileDesc" | i18n: "bitwarden_premium_license.json" }} +
+
+ + + + +
+
diff --git a/apps/web/src/app/billing/shared/update-license-dialog.component.ts b/apps/web/src/app/billing/shared/update-license-dialog.component.ts new file mode 100644 index 0000000000..5f9a1e94be --- /dev/null +++ b/apps/web/src/app/billing/shared/update-license-dialog.component.ts @@ -0,0 +1,38 @@ +import { Component } from "@angular/core"; +import { FormBuilder } from "@angular/forms"; + +import { ApiService } from "@bitwarden/common/abstractions/api.service"; +import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction"; +import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; +import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; +import { DialogService } from "@bitwarden/components"; + +import { UpdateLicenseComponent } from "./update-license.component"; + +export enum UpdateLicenseDialogResult { + Updated = "updated", + Cancelled = "cancelled", +} +@Component({ + templateUrl: "update-license-dialog.component.html", +}) +export class UpdateLicenseDialogComponent extends UpdateLicenseComponent { + constructor( + apiService: ApiService, + i18nService: I18nService, + platformUtilsService: PlatformUtilsService, + organizationApiService: OrganizationApiServiceAbstraction, + formBuilder: FormBuilder, + ) { + super(apiService, i18nService, platformUtilsService, organizationApiService, formBuilder); + } + async submitLicense() { + await this.submit(); + } + submitLicenseDialog = async () => { + await this.submitLicense(); + }; + static open(dialogService: DialogService) { + return dialogService.open(UpdateLicenseDialogComponent); + } +}