diff --git a/apps/web/src/app/organizations/settings/billing-sync-api-key.component.html b/apps/web/src/app/organizations/billing/billing-sync-api-key.component.html
similarity index 100%
rename from apps/web/src/app/organizations/settings/billing-sync-api-key.component.html
rename to apps/web/src/app/organizations/billing/billing-sync-api-key.component.html
diff --git a/apps/web/src/app/organizations/settings/billing-sync-api-key.component.ts b/apps/web/src/app/organizations/billing/billing-sync-api-key.component.ts
similarity index 100%
rename from apps/web/src/app/organizations/settings/billing-sync-api-key.component.ts
rename to apps/web/src/app/organizations/billing/billing-sync-api-key.component.ts
diff --git a/apps/web/src/app/organizations/billing/organization-billing-history-view.component.html b/apps/web/src/app/organizations/billing/organization-billing-history-view.component.html
new file mode 100644
index 00000000000..6622245ad1d
--- /dev/null
+++ b/apps/web/src/app/organizations/billing/organization-billing-history-view.component.html
@@ -0,0 +1,27 @@
+
+
+
+ {{ "loading" | i18n }}
+
+
+
+
diff --git a/apps/web/src/app/organizations/billing/organization-billing-history-view.component.ts b/apps/web/src/app/organizations/billing/organization-billing-history-view.component.ts
new file mode 100644
index 00000000000..6680b3f19a9
--- /dev/null
+++ b/apps/web/src/app/organizations/billing/organization-billing-history-view.component.ts
@@ -0,0 +1,35 @@
+import { Component, OnInit } from "@angular/core";
+import { ActivatedRoute } from "@angular/router";
+
+import { ApiService } from "@bitwarden/common/abstractions/api.service";
+import { BillingHistoryResponse } from "@bitwarden/common/models/response/billingHistoryResponse";
+
+@Component({
+ selector: "app-org-billing-history-view",
+ templateUrl: "organization-billing-history-view.component.html",
+})
+export class OrgBillingHistoryViewComponent implements OnInit {
+ loading = false;
+ firstLoaded = false;
+ billing: BillingHistoryResponse;
+ organizationId: string;
+
+ constructor(private apiService: ApiService, private route: ActivatedRoute) {}
+
+ async ngOnInit() {
+ this.route.params.subscribe(async (params) => {
+ this.organizationId = params.organizationId;
+ await this.load();
+ this.firstLoaded = true;
+ });
+ }
+
+ async load() {
+ if (this.loading) {
+ return;
+ }
+ this.loading = true;
+ this.billing = await this.apiService.getOrganizationBilling(this.organizationId);
+ this.loading = false;
+ }
+}
diff --git a/apps/web/src/app/organizations/billing/organization-billing-routing.module.ts b/apps/web/src/app/organizations/billing/organization-billing-routing.module.ts
new file mode 100644
index 00000000000..476b98e1c36
--- /dev/null
+++ b/apps/web/src/app/organizations/billing/organization-billing-routing.module.ts
@@ -0,0 +1,47 @@
+import { NgModule } from "@angular/core";
+import { RouterModule, Routes } from "@angular/router";
+
+import { Permissions } from "@bitwarden/common/enums/permissions";
+
+import { PaymentMethodComponent } from "../../settings/payment-method.component";
+import { PermissionsGuard } from "../guards/permissions.guard";
+import { NavigationPermissionsService } from "../services/navigation-permissions.service";
+
+import { OrgBillingHistoryViewComponent } from "./organization-billing-history-view.component";
+import { OrganizationBillingTabComponent } from "./organization-billing-tab.component";
+import { OrganizationSubscriptionComponent } from "./organization-subscription.component";
+
+const routes: Routes = [
+ {
+ path: "",
+ component: OrganizationBillingTabComponent,
+ canActivate: [PermissionsGuard],
+ data: { permissions: NavigationPermissionsService.getPermissions("billing") },
+ children: [
+ { path: "", pathMatch: "full", redirectTo: "subscription" },
+ {
+ path: "subscription",
+ component: OrganizationSubscriptionComponent,
+ data: { titleId: "subscription" },
+ },
+ {
+ path: "payment-method",
+ component: PaymentMethodComponent,
+ canActivate: [PermissionsGuard],
+ data: { titleId: "paymentMethod", permissions: [Permissions.ManageBilling] },
+ },
+ {
+ path: "history",
+ component: OrgBillingHistoryViewComponent,
+ canActivate: [PermissionsGuard],
+ data: { titleId: "billingHistory", permissions: [Permissions.ManageBilling] },
+ },
+ ],
+ },
+];
+
+@NgModule({
+ imports: [RouterModule.forChild(routes)],
+ exports: [RouterModule],
+})
+export class OrganizationBillingRoutingModule {}
diff --git a/apps/web/src/app/organizations/billing/organization-billing-tab.component.html b/apps/web/src/app/organizations/billing/organization-billing-tab.component.html
new file mode 100644
index 00000000000..b01c0eea7f0
--- /dev/null
+++ b/apps/web/src/app/organizations/billing/organization-billing-tab.component.html
@@ -0,0 +1,23 @@
+
diff --git a/apps/web/src/app/organizations/billing/organization-billing-tab.component.ts b/apps/web/src/app/organizations/billing/organization-billing-tab.component.ts
new file mode 100644
index 00000000000..17f47e54d10
--- /dev/null
+++ b/apps/web/src/app/organizations/billing/organization-billing-tab.component.ts
@@ -0,0 +1,7 @@
+import { Component } from "@angular/core";
+
+@Component({
+ selector: "app-org-billing-tab",
+ templateUrl: "organization-billing-tab.component.html",
+})
+export class OrganizationBillingTabComponent {}
diff --git a/apps/web/src/app/organizations/billing/organization-billing.module.ts b/apps/web/src/app/organizations/billing/organization-billing.module.ts
new file mode 100644
index 00000000000..7e2dcf534e9
--- /dev/null
+++ b/apps/web/src/app/organizations/billing/organization-billing.module.ts
@@ -0,0 +1,21 @@
+import { NgModule } from "@angular/core";
+
+import { LooseComponentsModule } from "../../shared/loose-components.module";
+import { SharedModule } from "../../shared/shared.module";
+
+import { BillingSyncApiKeyComponent } from "./billing-sync-api-key.component";
+import { OrgBillingHistoryViewComponent } from "./organization-billing-history-view.component";
+import { OrganizationBillingRoutingModule } from "./organization-billing-routing.module";
+import { OrganizationBillingTabComponent } from "./organization-billing-tab.component";
+import { OrganizationSubscriptionComponent } from "./organization-subscription.component";
+
+@NgModule({
+ imports: [SharedModule, LooseComponentsModule, OrganizationBillingRoutingModule],
+ declarations: [
+ BillingSyncApiKeyComponent,
+ OrganizationBillingTabComponent,
+ OrganizationSubscriptionComponent,
+ OrgBillingHistoryViewComponent,
+ ],
+})
+export class OrganizationBillingModule {}
diff --git a/apps/web/src/app/organizations/settings/organization-subscription.component.html b/apps/web/src/app/organizations/billing/organization-subscription.component.html
similarity index 100%
rename from apps/web/src/app/organizations/settings/organization-subscription.component.html
rename to apps/web/src/app/organizations/billing/organization-subscription.component.html
diff --git a/apps/web/src/app/organizations/settings/organization-subscription.component.ts b/apps/web/src/app/organizations/billing/organization-subscription.component.ts
similarity index 100%
rename from apps/web/src/app/organizations/settings/organization-subscription.component.ts
rename to apps/web/src/app/organizations/billing/organization-subscription.component.ts
diff --git a/apps/web/src/app/organizations/layouts/organization-layout.component.html b/apps/web/src/app/organizations/layouts/organization-layout.component.html
index 3834635e189..8716e12740d 100644
--- a/apps/web/src/app/organizations/layouts/organization-layout.component.html
+++ b/apps/web/src/app/organizations/layouts/organization-layout.component.html
@@ -6,34 +6,27 @@
class="my-auto pl-1"
[activeOrganization]="organization"
>
-
+
+ {{ "vault" | i18n }}
+ {{
+ "members" | i18n
+ }}
+ {{
+ "groups" | i18n
+ }}
+ {{
+ reportTabLabel | i18n
+ }}
+ {{
+ "billing" | i18n
+ }}
+ {{
+ "settings" | i18n
+ }}
+
+
diff --git a/apps/web/src/app/organizations/layouts/organization-layout.component.ts b/apps/web/src/app/organizations/layouts/organization-layout.component.ts
index c9dcbd5cf3c..3b46a2521a6 100644
--- a/apps/web/src/app/organizations/layouts/organization-layout.component.ts
+++ b/apps/web/src/app/organizations/layouts/organization-layout.component.ts
@@ -50,49 +50,29 @@ export class OrganizationLayoutComponent implements OnInit, OnDestroy {
this.organization = await this.organizationService.get(this.organizationId);
}
- get showManageTab(): boolean {
- return NavigationPermissionsService.canAccessManage(this.organization);
- }
-
- get showToolsTab(): boolean {
- return NavigationPermissionsService.canAccessTools(this.organization);
- }
-
get showSettingsTab(): boolean {
return NavigationPermissionsService.canAccessSettings(this.organization);
}
- get toolsRoute(): string {
- return this.organization.canAccessImportExport
- ? "tools/import"
- : "tools/exposed-passwords-report";
+ get showMembersTab(): boolean {
+ return NavigationPermissionsService.canAccessMembers(this.organization);
}
- get manageRoute(): string {
- let route: string;
- switch (true) {
- case this.organization.canManageUsers:
- route = "manage/people";
- break;
- case this.organization.canViewAssignedCollections || this.organization.canViewAllCollections:
- route = "manage/collections";
- break;
- case this.organization.canManageGroups:
- route = "manage/groups";
- break;
- case this.organization.canManagePolicies:
- route = "manage/policies";
- break;
- case this.organization.canManageSso:
- route = "manage/sso";
- break;
- case this.organization.canManageScim:
- route = "manage/scim";
- break;
- case this.organization.canAccessEventLogs:
- route = "manage/events";
- break;
- }
- return route;
+ get showGroupsTab(): boolean {
+ return (
+ this.organization.useGroups && NavigationPermissionsService.canAccessGroups(this.organization)
+ );
+ }
+
+ get showReportsTab(): boolean {
+ return NavigationPermissionsService.canAccessReporting(this.organization);
+ }
+
+ get showBillingTab(): boolean {
+ return NavigationPermissionsService.canAccessBilling(this.organization);
+ }
+
+ get reportTabLabel(): string {
+ return this.organization.useEvents ? "reporting" : "reports";
}
}
diff --git a/apps/web/src/app/organizations/manage/groups.component.html b/apps/web/src/app/organizations/manage/groups.component.html
index 050307b8539..72c6c2ee115 100644
--- a/apps/web/src/app/organizations/manage/groups.component.html
+++ b/apps/web/src/app/organizations/manage/groups.component.html
@@ -1,77 +1,79 @@
-