+
-
@@ -179,11 +179,11 @@
-
-
+
{{ "selfHostingTitle" | i18n }}
+
{{ "selfHostingEnterpriseOrganizationSectionCopy" | i18n }}
-
+
{{ (hasBillingSyncToken ? "manageBillingSync" : "setUpBillingSync") | i18n }}
-
+
-
-
+
{{ "additionalOptions" | i18n }}
+
{{ "additionalOptionsDesc" | i18n }}
-
+
{{ "cancelSubscription" | i18n }}
diff --git a/apps/web/src/app/billing/organizations/organization-subscription-cloud.component.ts b/apps/web/src/app/billing/organizations/organization-subscription-cloud.component.ts
index b9fc6798ec..52245320fe 100644
--- a/apps/web/src/app/billing/organizations/organization-subscription-cloud.component.ts
+++ b/apps/web/src/app/billing/organizations/organization-subscription-cloud.component.ts
@@ -10,7 +10,9 @@ import { OrganizationService } from "@bitwarden/common/admin-console/abstraction
import { OrganizationApiKeyType } from "@bitwarden/common/admin-console/enums";
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
import { PlanType } from "@bitwarden/common/billing/enums";
+import { BitwardenProductType } from "@bitwarden/common/billing/enums/bitwarden-product-type.enum";
import { OrganizationSubscriptionResponse } from "@bitwarden/common/billing/models/response/organization-subscription.response";
+import { BillingSubscriptionItemResponse } from "@bitwarden/common/billing/models/response/subscription.response";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
@@ -26,6 +28,7 @@ import {
})
export class OrganizationSubscriptionCloudComponent implements OnInit, OnDestroy {
sub: OrganizationSubscriptionResponse;
+ lineItems: BillingSubscriptionItemResponse[] = [];
organizationId: string;
userOrg: Organization;
showChangePlan = false;
@@ -68,6 +71,17 @@ export class OrganizationSubscriptionCloudComponent implements OnInit, OnDestroy
.subscribe();
}
+ productName(product: BitwardenProductType) {
+ switch (product) {
+ case BitwardenProductType.PasswordManager:
+ return this.i18nService.t("passwordManager");
+ case BitwardenProductType.SecretsManager:
+ return this.i18nService.t("secretsManager");
+ default:
+ return this.i18nService.t("passwordManager");
+ }
+ }
+
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
@@ -81,6 +95,7 @@ export class OrganizationSubscriptionCloudComponent implements OnInit, OnDestroy
this.userOrg = this.organizationService.get(this.organizationId);
if (this.userOrg.canViewSubscription) {
this.sub = await this.organizationApiService.getSubscription(this.organizationId);
+ this.lineItems = this.sub?.subscription?.items?.sort(sortSubscriptionItems) ?? [];
}
const apiKeyResponse = await this.organizationApiService.getApiKeyInformation(
@@ -332,3 +347,23 @@ export class OrganizationSubscriptionCloudComponent implements OnInit, OnDestroy
return this.subscription == null && this.sub.planType === PlanType.Free && !this.showChangePlan;
}
}
+
+/**
+ * Helper to sort subscription items by product type and then by addon status
+ */
+function sortSubscriptionItems(
+ a: BillingSubscriptionItemResponse,
+ b: BillingSubscriptionItemResponse
+) {
+ if (a.bitwardenProduct == b.bitwardenProduct) {
+ if (a.addonSubscriptionItem == b.addonSubscriptionItem) {
+ return 0;
+ }
+ // sort addon items to the bottom
+ if (a.addonSubscriptionItem) {
+ return 1;
+ }
+ return -1;
+ }
+ return a.bitwardenProduct - b.bitwardenProduct;
+}
diff --git a/apps/web/src/app/billing/organizations/secrets-manager/enroll.component.html b/apps/web/src/app/billing/organizations/secrets-manager/enroll.component.html
index 56a48e09fe..de2b6aa566 100644
--- a/apps/web/src/app/billing/organizations/secrets-manager/enroll.component.html
+++ b/apps/web/src/app/billing/organizations/secrets-manager/enroll.component.html
@@ -1,6 +1,6 @@