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() {