diff --git a/apps/web/src/locales/en/messages.json b/apps/web/src/locales/en/messages.json index 2e0fd99bbcc..36d68429ac6 100644 --- a/apps/web/src/locales/en/messages.json +++ b/apps/web/src/locales/en/messages.json @@ -343,6 +343,12 @@ "reviewNow": { "message": "Review now" }, + "allCaughtUp": { + "message": "All caught up!" + }, + "noNewApplicationsToReviewAtThisTime": { + "message": "No new applications to review at this time" + }, "prioritizeCriticalApplications": { "message": "Prioritize critical applications" }, diff --git a/bitwarden_license/bit-web/src/app/dirt/access-intelligence/activity/activity-card.component.html b/bitwarden_license/bit-web/src/app/dirt/access-intelligence/activity/activity-card.component.html index 756907d24e6..73f98034f0a 100644 --- a/bitwarden_license/bit-web/src/app/dirt/access-intelligence/activity/activity-card.component.html +++ b/bitwarden_license/bit-web/src/app/dirt/access-intelligence/activity/activity-card.component.html @@ -2,7 +2,7 @@ {{ title }}
@if (iconClass) { - + } {{ cardMetrics }}
diff --git a/bitwarden_license/bit-web/src/app/dirt/access-intelligence/activity/activity-card.component.ts b/bitwarden_license/bit-web/src/app/dirt/access-intelligence/activity/activity-card.component.ts index 427e7262f50..24d931165a7 100644 --- a/bitwarden_license/bit-web/src/app/dirt/access-intelligence/activity/activity-card.component.ts +++ b/bitwarden_license/bit-web/src/app/dirt/access-intelligence/activity/activity-card.component.ts @@ -58,6 +58,14 @@ export class ActivityCardComponent { // eslint-disable-next-line @angular-eslint/prefer-signals @Input() iconClass: string | null = null; + /** + * CSS class for icon color (e.g., "tw-text-success", "tw-text-muted"). + * Defaults to "tw-text-muted" if not provided. + */ + // FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals + // eslint-disable-next-line @angular-eslint/prefer-signals + @Input() iconColorClass: string = "tw-text-muted"; + /** * Button text. If provided, a button will be displayed instead of a navigation link. */ diff --git a/bitwarden_license/bit-web/src/app/dirt/access-intelligence/activity/all-activity.component.html b/bitwarden_license/bit-web/src/app/dirt/access-intelligence/activity/all-activity.component.html index 82137c9acca..8cdb927ab65 100644 --- a/bitwarden_license/bit-web/src/app/dirt/access-intelligence/activity/all-activity.component.html +++ b/bitwarden_license/bit-web/src/app/dirt/access-intelligence/activity/all-activity.component.html @@ -45,10 +45,19 @@
  • diff --git a/bitwarden_license/bit-web/src/app/dirt/access-intelligence/activity/all-activity.component.ts b/bitwarden_license/bit-web/src/app/dirt/access-intelligence/activity/all-activity.component.ts index b12a8fffedb..150c66ad2d4 100644 --- a/bitwarden_license/bit-web/src/app/dirt/access-intelligence/activity/all-activity.component.ts +++ b/bitwarden_license/bit-web/src/app/dirt/access-intelligence/activity/all-activity.component.ts @@ -42,6 +42,9 @@ export class AllActivityComponent implements OnInit { newApplicationsCount = 0; newApplications: string[] = []; passwordChangeMetricHasProgressBar = false; + allAppsHaveReviewDate = false; + isAllCaughtUp = false; + hasLoadedApplicationData = false; destroyRef = inject(DestroyRef); @@ -79,6 +82,7 @@ export class AllActivityComponent implements OnInit { .subscribe((newApps) => { this.newApplications = newApps; this.newApplicationsCount = newApps.length; + this.updateIsAllCaughtUp(); }); this.allActivitiesService.passwordChangeProgressMetricHasProgressBar$ @@ -86,9 +90,39 @@ export class AllActivityComponent implements OnInit { .subscribe((hasProgressBar) => { this.passwordChangeMetricHasProgressBar = hasProgressBar; }); + + this.dataService.enrichedReportData$ + .pipe(takeUntilDestroyed(this.destroyRef)) + .subscribe((enrichedData) => { + if (enrichedData?.applicationData && enrichedData.applicationData.length > 0) { + this.hasLoadedApplicationData = true; + // Check if all apps have a review date (not null and not undefined) + this.allAppsHaveReviewDate = enrichedData.applicationData.every( + (app) => app.reviewedDate !== null && app.reviewedDate !== undefined, + ); + } else { + this.hasLoadedApplicationData = enrichedData !== null; + this.allAppsHaveReviewDate = false; + } + this.updateIsAllCaughtUp(); + }); } } + /** + * Updates the isAllCaughtUp flag based on current state. + * Only shows "All caught up!" when: + * - Data has been loaded (hasLoadedApplicationData is true) + * - No new applications need review + * - All apps have a review date + */ + private updateIsAllCaughtUp(): void { + this.isAllCaughtUp = + this.hasLoadedApplicationData && + this.newApplicationsCount === 0 && + this.allAppsHaveReviewDate; + } + /** * Handles the review new applications button click. * Opens a dialog showing the list of new applications that can be marked as critical.