1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-16 08:13:42 +00:00

[PM-28451] Fix icons in application review table (#17512)

* Fix icons in application review table

* Add default icon if none is found in review applications table. Move function to computed signal

* Rename function

* Remove redundant if statement
This commit is contained in:
Leslie Tilton
2025-11-21 09:12:48 -06:00
committed by GitHub
parent e9f67f4fd6
commit 994077f4de
6 changed files with 43 additions and 9 deletions

View File

@@ -28,7 +28,7 @@
</div>
<dirt-review-applications-view
[applications]="getApplications()"
[applications]="applicationsWithIcons()"
[selectedApplications]="selectedApplications()"
(onToggleSelection)="toggleSelection($event)"
(onToggleAll)="toggleAll()"

View File

@@ -33,6 +33,7 @@ import {
} from "@bitwarden/components";
import { I18nPipe } from "@bitwarden/ui-common";
import { CipherIcon } from "../../shared/app-table-row-scrollable.component";
import { AccessIntelligenceSecurityTasksService } from "../../shared/security-tasks.service";
import { AssignTasksViewComponent } from "./assign-tasks-view.component";
@@ -99,6 +100,16 @@ export class NewApplicationsDialogComponent {
// Applications selected to save as critical applications
protected readonly selectedApplications = signal<Set<string>>(new Set());
protected readonly applicationIcons = signal<Map<string, CipherIcon>>(
new Map<string, CipherIcon>(),
);
protected readonly applicationsWithIcons = computed(() => {
return this.dialogParams.newApplications.map((app) => {
const iconCipher = this.applicationIcons().get(app.applicationName);
return { ...app, iconCipher } as ApplicationHealthReportDetail & { iconCipher: CipherIcon };
});
});
// Used to determine if there are unassigned at-risk cipher IDs
private readonly _tasks!: Signal<SecurityTask[]>;
@@ -150,6 +161,7 @@ export class NewApplicationsDialogComponent {
private securityTasksService: AccessIntelligenceSecurityTasksService,
private toastService: ToastService,
) {
this.setApplicationIconMap(this.dialogParams.newApplications);
// Setup the _tasks signal by manually passing in the injector
this._tasks = toSignal(this.securityTasksService.tasks$, {
initialValue: [],
@@ -172,10 +184,6 @@ export class NewApplicationsDialogComponent {
);
}
getApplications() {
return this.dialogParams.newApplications;
}
/**
* Returns true if the organization has no existing critical applications.
* Used to conditionally show different titles and descriptions.
@@ -184,6 +192,22 @@ export class NewApplicationsDialogComponent {
return !this.dialogParams.hasExistingCriticalApplications;
}
/**
* Maps applications to a corresponding iconCipher
*
* @param applications
*/
setApplicationIconMap(applications: ApplicationHealthReportDetail[]) {
// Map the report data to include the iconCipher for each application
const iconCiphers = new Map<string, CipherIcon>();
applications.forEach((app) => {
const iconCipher =
app.cipherIds.length > 0 ? this.dataService.getCipherIcon(app.cipherIds[0]) : undefined;
iconCiphers.set(app.applicationName, iconCipher);
});
this.applicationIcons.set(iconCiphers);
}
/**
* Toggles the selection state of an application.
* @param applicationName The application to toggle

View File

@@ -62,7 +62,11 @@
</td>
<td bitTypography="body1" class="tw-py-3 tw-px-2">
<div class="tw-flex tw-items-center tw-gap-2">
<i class="bwi bwi-globe tw-text-muted" aria-hidden="true"></i>
@if (app.iconCipher) {
<app-vault-icon [cipher]="app.iconCipher"></app-vault-icon>
} @else {
<i class="bwi bwi-globe tw-text-muted" aria-hidden="true"></i>
}
<span>{{ app.applicationName }}</span>
</div>
</td>

View File

@@ -5,6 +5,9 @@ import { FormsModule } from "@angular/forms";
import { ApplicationHealthReportDetail } from "@bitwarden/bit-common/dirt/reports/risk-insights";
import { ButtonModule, DialogModule, SearchModule, TypographyModule } from "@bitwarden/components";
import { I18nPipe } from "@bitwarden/ui-common";
import { SharedModule } from "@bitwarden/web-vault/app/shared";
import { CipherIcon } from "../../shared/app-table-row-scrollable.component";
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
@@ -18,10 +21,12 @@ import { I18nPipe } from "@bitwarden/ui-common";
SearchModule,
TypographyModule,
I18nPipe,
SharedModule,
],
})
export class ReviewApplicationsViewComponent {
readonly applications = input.required<ApplicationHealthReportDetail[]>();
readonly applications =
input.required<Array<ApplicationHealthReportDetail & { iconCipher: CipherIcon }>>();
readonly selectedApplications = input.required<Set<string>>();
protected readonly searchText = signal<string>("");

View File

@@ -45,7 +45,6 @@
tabindex="0"
[attr.aria-label]="'viewItem' | i18n"
>
<!-- Passing the first cipher of the application for app-vault-icon cipher input requirement -->
<app-vault-icon *ngIf="row.iconCipher" [cipher]="row.iconCipher"></app-vault-icon>
</td>
<td

View File

@@ -8,8 +8,10 @@ import { MenuModule, TableDataSource, TableModule } from "@bitwarden/components"
import { SharedModule } from "@bitwarden/web-vault/app/shared";
import { PipesModule } from "@bitwarden/web-vault/app/vault/individual-vault/pipes/pipes.module";
export type CipherIcon = CipherViewLike | undefined;
export type ApplicationTableDataSource = ApplicationHealthReportDetailEnriched & {
iconCipher: CipherViewLike | undefined;
iconCipher: CipherIcon;
};
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush