diff --git a/apps/web/src/locales/en/messages.json b/apps/web/src/locales/en/messages.json
index dd2e132ba0..2e5633af5c 100644
--- a/apps/web/src/locales/en/messages.json
+++ b/apps/web/src/locales/en/messages.json
@@ -2,6 +2,9 @@
"allApplications": {
"message": "All applications"
},
+ "activity": {
+ "message": "Activity"
+ },
"appLogoLabel": {
"message": "Bitwarden logo"
},
diff --git a/bitwarden_license/bit-web/src/app/dirt/access-intelligence/all-activity.component.html b/bitwarden_license/bit-web/src/app/dirt/access-intelligence/all-activity.component.html
new file mode 100644
index 0000000000..330e092094
--- /dev/null
+++ b/bitwarden_license/bit-web/src/app/dirt/access-intelligence/all-activity.component.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+ {{ organization.name }}
+
+
+
+
+
+
+
diff --git a/bitwarden_license/bit-web/src/app/dirt/access-intelligence/all-activity.component.ts b/bitwarden_license/bit-web/src/app/dirt/access-intelligence/all-activity.component.ts
new file mode 100644
index 0000000000..552a67e799
--- /dev/null
+++ b/bitwarden_license/bit-web/src/app/dirt/access-intelligence/all-activity.component.ts
@@ -0,0 +1,46 @@
+import { Component, OnInit } from "@angular/core";
+import { ActivatedRoute } from "@angular/router";
+import { firstValueFrom, Observable } from "rxjs";
+
+import { RiskInsightsDataService } from "@bitwarden/bit-common/dirt/reports/risk-insights";
+import { AtRiskApplicationDetail } from "@bitwarden/bit-common/dirt/reports/risk-insights/models/password-health";
+import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
+import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
+import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
+import { getUserId } from "@bitwarden/common/auth/services/account.service";
+import { getById } from "@bitwarden/common/platform/misc";
+import { SharedModule } from "@bitwarden/web-vault/app/shared";
+
+import { ApplicationsLoadingComponent } from "./risk-insights-loading.component";
+
+@Component({
+ selector: "tools-all-activity",
+ imports: [ApplicationsLoadingComponent, SharedModule],
+ templateUrl: "./all-activity.component.html",
+})
+export class AllActivityComponent implements OnInit {
+ isLoading$: Observable = this.dataService.isLoading$;
+ atRiskAppDetails: AtRiskApplicationDetail[] = [];
+ organization: Organization | null = null;
+
+ async ngOnInit(): Promise {
+ const organizationId = this.activatedRoute.snapshot.paramMap.get("organizationId");
+ const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
+
+ if (organizationId) {
+ this.organization =
+ (await firstValueFrom(
+ this.organizationService.organizations$(userId).pipe(getById(organizationId)),
+ )) ?? null;
+
+ this.atRiskAppDetails = this.dataService.atRiskAppDetails ?? [];
+ }
+ }
+
+ constructor(
+ protected activatedRoute: ActivatedRoute,
+ private accountService: AccountService,
+ protected organizationService: OrganizationService,
+ protected dataService: RiskInsightsDataService,
+ ) {}
+}
diff --git a/bitwarden_license/bit-web/src/app/dirt/access-intelligence/risk-insights.component.html b/bitwarden_license/bit-web/src/app/dirt/access-intelligence/risk-insights.component.html
index 89ea600f6e..ab00d2955a 100644
--- a/bitwarden_license/bit-web/src/app/dirt/access-intelligence/risk-insights.component.html
+++ b/bitwarden_license/bit-web/src/app/dirt/access-intelligence/risk-insights.component.html
@@ -34,6 +34,11 @@
+ @if (isRiskInsightsActivityTabFeatureEnabled) {
+
+
+
+ }
diff --git a/bitwarden_license/bit-web/src/app/dirt/access-intelligence/risk-insights.component.ts b/bitwarden_license/bit-web/src/app/dirt/access-intelligence/risk-insights.component.ts
index 0b32d311e4..03cd60667b 100644
--- a/bitwarden_license/bit-web/src/app/dirt/access-intelligence/risk-insights.component.ts
+++ b/bitwarden_license/bit-web/src/app/dirt/access-intelligence/risk-insights.component.ts
@@ -17,6 +17,7 @@ import {
} from "@bitwarden/bit-common/dirt/reports/risk-insights/models/password-health";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { getUserId } from "@bitwarden/common/auth/services/account.service";
+import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { OrganizationId } from "@bitwarden/common/types/guid";
import {
@@ -29,15 +30,17 @@ import {
} from "@bitwarden/components";
import { HeaderModule } from "@bitwarden/web-vault/app/layouts/header/header.module";
+import { AllActivityComponent } from "./all-activity.component";
import { AllApplicationsComponent } from "./all-applications.component";
import { CriticalApplicationsComponent } from "./critical-applications.component";
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
export enum RiskInsightsTabType {
- AllApps = 0,
- CriticalApps = 1,
- NotifiedMembers = 2,
+ AllActivity = 0,
+ AllApps = 1,
+ CriticalApps = 2,
+ NotifiedMembers = 3,
}
@Component({
@@ -54,10 +57,12 @@ export enum RiskInsightsTabType {
DrawerComponent,
DrawerBodyComponent,
DrawerHeaderComponent,
+ AllActivityComponent,
],
})
export class RiskInsightsComponent implements OnInit {
tabIndex: RiskInsightsTabType = RiskInsightsTabType.AllApps;
+ isRiskInsightsActivityTabFeatureEnabled: boolean = false;
dataLastUpdated: Date = new Date();
@@ -69,6 +74,7 @@ export class RiskInsightsComponent implements OnInit {
private organizationId: OrganizationId = "" as OrganizationId;
private destroyRef = inject(DestroyRef);
+
isLoading$: Observable = new Observable();
isRefreshing$: Observable = new Observable();
dataLastUpdated$: Observable = new Observable();
@@ -85,6 +91,14 @@ export class RiskInsightsComponent implements OnInit {
this.route.queryParams.pipe(takeUntilDestroyed()).subscribe(({ tabIndex }) => {
this.tabIndex = !isNaN(Number(tabIndex)) ? Number(tabIndex) : RiskInsightsTabType.AllApps;
});
+
+ this.configService
+ .getFeatureFlag$(FeatureFlag.PM22887_RiskInsightsActivityTab)
+ .pipe(takeUntilDestroyed(this.destroyRef))
+ .subscribe((isEnabled) => {
+ this.isRiskInsightsActivityTabFeatureEnabled = isEnabled;
+ this.tabIndex = 0; // default to first tab
+ });
}
async ngOnInit() {