mirror of
https://github.com/bitwarden/browser
synced 2025-12-06 00:13:28 +00:00
[PM-27739] Fix bug for icons not showing on application tables (#17373)
* Added function to get a cipher icon for application tables. Update all application component to use signal properties * Fix type * Handle no ciphers on application
This commit is contained in:
@@ -35,6 +35,7 @@ import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
|||||||
import { CipherId, OrganizationId, UserId } from "@bitwarden/common/types/guid";
|
import { CipherId, OrganizationId, UserId } from "@bitwarden/common/types/guid";
|
||||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||||
|
import { CipherViewLike } from "@bitwarden/common/vault/utils/cipher-view-like-utils";
|
||||||
import { LogService } from "@bitwarden/logging";
|
import { LogService } from "@bitwarden/logging";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -191,6 +192,23 @@ export class RiskInsightsOrchestratorService {
|
|||||||
this._generateReportTriggerSubject.next(true);
|
this._generateReportTriggerSubject.next(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the cipher icon for a given cipher ID
|
||||||
|
*
|
||||||
|
* @param cipherId The ID of the cipher to get the icon for
|
||||||
|
* @returns A CipherViewLike if found, otherwise undefined
|
||||||
|
*/
|
||||||
|
getCipherIcon(cipherId: string): CipherViewLike | undefined {
|
||||||
|
const currentCiphers = this._ciphersSubject.value;
|
||||||
|
if (!currentCiphers) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
const foundCipher = currentCiphers.find((c) => c.id === cipherId);
|
||||||
|
|
||||||
|
return foundCipher;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the service context for a specific organization
|
* Initializes the service context for a specific organization
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -87,7 +87,9 @@ export class RiskInsightsDataService {
|
|||||||
this._destroy$.complete();
|
this._destroy$.complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----- UI-triggered methods (delegate to orchestrator) -----
|
getCipherIcon(cipherId: string) {
|
||||||
|
return this.orchestrator.getCipherIcon(cipherId);
|
||||||
|
}
|
||||||
initializeForOrganization(organizationId: OrganizationId) {
|
initializeForOrganization(organizationId: OrganizationId) {
|
||||||
this.orchestrator.initializeForOrganization(organizationId);
|
this.orchestrator.initializeForOrganization(organizationId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,10 +22,10 @@
|
|||||||
bitTypography="h3"
|
bitTypography="h3"
|
||||||
class="!tw-mb-0"
|
class="!tw-mb-0"
|
||||||
aria-describedby="allAppsOrgAtRiskMembersLabel"
|
aria-describedby="allAppsOrgAtRiskMembersLabel"
|
||||||
>{{ applicationSummary.totalAtRiskMemberCount }}</span
|
>{{ applicationSummary().totalAtRiskMemberCount }}</span
|
||||||
>
|
>
|
||||||
<span bitTypography="body2">{{
|
<span bitTypography="body2">{{
|
||||||
"cardMetrics" | i18n: applicationSummary.totalMemberCount
|
"cardMetrics" | i18n: applicationSummary().totalMemberCount
|
||||||
}}</span>
|
}}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="tw-flex tw-items-baseline tw-mt-1 tw-gap-2">
|
<div class="tw-flex tw-items-baseline tw-mt-1 tw-gap-2">
|
||||||
@@ -62,10 +62,10 @@
|
|||||||
bitTypography="h3"
|
bitTypography="h3"
|
||||||
class="!tw-mb-0"
|
class="!tw-mb-0"
|
||||||
aria-describedby="allAppsOrgAtRiskApplicationsLabel"
|
aria-describedby="allAppsOrgAtRiskApplicationsLabel"
|
||||||
>{{ applicationSummary.totalAtRiskApplicationCount }}</span
|
>{{ applicationSummary().totalAtRiskApplicationCount }}</span
|
||||||
>
|
>
|
||||||
<span bitTypography="body2">{{
|
<span bitTypography="body2">{{
|
||||||
"cardMetrics" | i18n: applicationSummary.totalApplicationCount
|
"cardMetrics" | i18n: applicationSummary().totalApplicationCount
|
||||||
}}</span>
|
}}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="tw-flex tw-items-baseline tw-mt-1 tw-gap-2">
|
<div class="tw-flex tw-items-baseline tw-mt-1 tw-gap-2">
|
||||||
@@ -95,11 +95,11 @@
|
|||||||
type="button"
|
type="button"
|
||||||
[buttonType]="'primary'"
|
[buttonType]="'primary'"
|
||||||
bitButton
|
bitButton
|
||||||
[disabled]="!selectedUrls.size"
|
[disabled]="!selectedUrls().size"
|
||||||
[loading]="markingAsCritical"
|
[loading]="markingAsCritical()"
|
||||||
(click)="markAppsAsCritical()"
|
(click)="markAppsAsCritical()"
|
||||||
>
|
>
|
||||||
<i class="bwi tw-mr-2" [ngClass]="selectedUrls.size ? 'bwi-star-f' : 'bwi-star'"></i>
|
<i class="bwi tw-mr-2" [ngClass]="selectedUrls().size ? 'bwi-star-f' : 'bwi-star'"></i>
|
||||||
{{ "markAppAsCritical" | i18n }}
|
{{ "markAppAsCritical" | i18n }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -108,7 +108,7 @@
|
|||||||
[dataSource]="dataSource"
|
[dataSource]="dataSource"
|
||||||
[showRowCheckBox]="true"
|
[showRowCheckBox]="true"
|
||||||
[showRowMenuForCriticalApps]="false"
|
[showRowMenuForCriticalApps]="false"
|
||||||
[selectedUrls]="selectedUrls"
|
[selectedUrls]="selectedUrls()"
|
||||||
[openApplication]="drawerDetails.invokerId || ''"
|
[openApplication]="drawerDetails.invokerId || ''"
|
||||||
[checkboxChange]="onCheckboxChange"
|
[checkboxChange]="onCheckboxChange"
|
||||||
[showAppAtRiskMembers]="showAppAtRiskMembers"
|
[showAppAtRiskMembers]="showAppAtRiskMembers"
|
||||||
|
|||||||
@@ -1,20 +1,23 @@
|
|||||||
import { Component, DestroyRef, inject, OnInit } from "@angular/core";
|
import {
|
||||||
|
Component,
|
||||||
|
DestroyRef,
|
||||||
|
inject,
|
||||||
|
OnInit,
|
||||||
|
ChangeDetectionStrategy,
|
||||||
|
signal,
|
||||||
|
} from "@angular/core";
|
||||||
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
||||||
import { FormControl } from "@angular/forms";
|
import { FormControl } from "@angular/forms";
|
||||||
import { ActivatedRoute, Router } from "@angular/router";
|
import { ActivatedRoute } from "@angular/router";
|
||||||
import { debounceTime } from "rxjs";
|
import { debounceTime } from "rxjs";
|
||||||
|
|
||||||
import { Security } from "@bitwarden/assets/svg";
|
import { Security } from "@bitwarden/assets/svg";
|
||||||
import {
|
import { RiskInsightsDataService } from "@bitwarden/bit-common/dirt/reports/risk-insights";
|
||||||
ApplicationHealthReportDetailEnriched,
|
|
||||||
RiskInsightsDataService,
|
|
||||||
} from "@bitwarden/bit-common/dirt/reports/risk-insights";
|
|
||||||
import { createNewSummaryData } from "@bitwarden/bit-common/dirt/reports/risk-insights/helpers";
|
import { createNewSummaryData } from "@bitwarden/bit-common/dirt/reports/risk-insights/helpers";
|
||||||
import {
|
import {
|
||||||
OrganizationReportSummary,
|
OrganizationReportSummary,
|
||||||
ReportStatus,
|
ReportStatus,
|
||||||
} from "@bitwarden/bit-common/dirt/reports/risk-insights/models/report-models";
|
} from "@bitwarden/bit-common/dirt/reports/risk-insights/models/report-models";
|
||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import {
|
import {
|
||||||
IconButtonModule,
|
IconButtonModule,
|
||||||
@@ -29,12 +32,14 @@ import { HeaderModule } from "@bitwarden/web-vault/app/layouts/header/header.mod
|
|||||||
import { SharedModule } from "@bitwarden/web-vault/app/shared";
|
import { SharedModule } from "@bitwarden/web-vault/app/shared";
|
||||||
import { PipesModule } from "@bitwarden/web-vault/app/vault/individual-vault/pipes/pipes.module";
|
import { PipesModule } from "@bitwarden/web-vault/app/vault/individual-vault/pipes/pipes.module";
|
||||||
|
|
||||||
import { AppTableRowScrollableComponent } from "../shared/app-table-row-scrollable.component";
|
import {
|
||||||
|
ApplicationTableDataSource,
|
||||||
|
AppTableRowScrollableComponent,
|
||||||
|
} from "../shared/app-table-row-scrollable.component";
|
||||||
import { ApplicationsLoadingComponent } from "../shared/risk-insights-loading.component";
|
import { ApplicationsLoadingComponent } from "../shared/risk-insights-loading.component";
|
||||||
|
|
||||||
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
|
|
||||||
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
|
|
||||||
@Component({
|
@Component({
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
selector: "dirt-all-applications",
|
selector: "dirt-all-applications",
|
||||||
templateUrl: "./all-applications.component.html",
|
templateUrl: "./all-applications.component.html",
|
||||||
imports: [
|
imports: [
|
||||||
@@ -51,24 +56,25 @@ import { ApplicationsLoadingComponent } from "../shared/risk-insights-loading.co
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class AllApplicationsComponent implements OnInit {
|
export class AllApplicationsComponent implements OnInit {
|
||||||
protected dataSource = new TableDataSource<ApplicationHealthReportDetailEnriched>();
|
|
||||||
protected selectedUrls: Set<string> = new Set<string>();
|
|
||||||
protected searchControl = new FormControl("", { nonNullable: true });
|
|
||||||
protected organization = new Organization();
|
|
||||||
noItemsIcon = Security;
|
|
||||||
protected markingAsCritical = false;
|
|
||||||
protected applicationSummary: OrganizationReportSummary = createNewSummaryData();
|
|
||||||
protected ReportStatusEnum = ReportStatus;
|
|
||||||
|
|
||||||
destroyRef = inject(DestroyRef);
|
destroyRef = inject(DestroyRef);
|
||||||
|
|
||||||
|
protected ReportStatusEnum = ReportStatus;
|
||||||
|
protected noItemsIcon = Security;
|
||||||
|
|
||||||
|
// Standard properties
|
||||||
|
protected readonly dataSource = new TableDataSource<ApplicationTableDataSource>();
|
||||||
|
protected readonly searchControl = new FormControl("", { nonNullable: true });
|
||||||
|
|
||||||
|
// Template driven properties
|
||||||
|
protected readonly selectedUrls = signal(new Set<string>());
|
||||||
|
protected readonly markingAsCritical = signal(false);
|
||||||
|
protected readonly applicationSummary = signal<OrganizationReportSummary>(createNewSummaryData());
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
protected i18nService: I18nService,
|
protected i18nService: I18nService,
|
||||||
protected activatedRoute: ActivatedRoute,
|
protected activatedRoute: ActivatedRoute,
|
||||||
protected toastService: ToastService,
|
protected toastService: ToastService,
|
||||||
protected dataService: RiskInsightsDataService,
|
protected dataService: RiskInsightsDataService,
|
||||||
private router: Router,
|
|
||||||
// protected allActivitiesService: AllActivitiesService,
|
|
||||||
) {
|
) {
|
||||||
this.searchControl.valueChanges
|
this.searchControl.valueChanges
|
||||||
.pipe(debounceTime(200), takeUntilDestroyed())
|
.pipe(debounceTime(200), takeUntilDestroyed())
|
||||||
@@ -78,8 +84,21 @@ export class AllApplicationsComponent implements OnInit {
|
|||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
this.dataService.enrichedReportData$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe({
|
this.dataService.enrichedReportData$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe({
|
||||||
next: (report) => {
|
next: (report) => {
|
||||||
this.applicationSummary = report?.summaryData ?? createNewSummaryData();
|
if (report != null) {
|
||||||
this.dataSource.data = report?.reportData ?? [];
|
this.applicationSummary.set(report.summaryData);
|
||||||
|
|
||||||
|
// Map the report data to include the iconCipher for each application
|
||||||
|
const tableDataWithIcon = report.reportData.map((app) => ({
|
||||||
|
...app,
|
||||||
|
iconCipher:
|
||||||
|
app.cipherIds.length > 0
|
||||||
|
? this.dataService.getCipherIcon(app.cipherIds[0])
|
||||||
|
: undefined,
|
||||||
|
}));
|
||||||
|
this.dataSource.data = tableDataWithIcon;
|
||||||
|
} else {
|
||||||
|
this.dataSource.data = [];
|
||||||
|
}
|
||||||
},
|
},
|
||||||
error: () => {
|
error: () => {
|
||||||
this.dataSource.data = [];
|
this.dataSource.data = [];
|
||||||
@@ -88,15 +107,15 @@ export class AllApplicationsComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
isMarkedAsCriticalItem(applicationName: string) {
|
isMarkedAsCriticalItem(applicationName: string) {
|
||||||
return this.selectedUrls.has(applicationName);
|
return this.selectedUrls().has(applicationName);
|
||||||
}
|
}
|
||||||
|
|
||||||
markAppsAsCritical = async () => {
|
markAppsAsCritical = async () => {
|
||||||
this.markingAsCritical = true;
|
this.markingAsCritical.set(true);
|
||||||
const count = this.selectedUrls.size;
|
const count = this.selectedUrls().size;
|
||||||
|
|
||||||
this.dataService
|
this.dataService
|
||||||
.saveCriticalApplications(Array.from(this.selectedUrls))
|
.saveCriticalApplications(Array.from(this.selectedUrls()))
|
||||||
.pipe(takeUntilDestroyed(this.destroyRef))
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
||||||
.subscribe({
|
.subscribe({
|
||||||
next: () => {
|
next: () => {
|
||||||
@@ -105,8 +124,8 @@ export class AllApplicationsComponent implements OnInit {
|
|||||||
title: "",
|
title: "",
|
||||||
message: this.i18nService.t("criticalApplicationsMarkedSuccess", count.toString()),
|
message: this.i18nService.t("criticalApplicationsMarkedSuccess", count.toString()),
|
||||||
});
|
});
|
||||||
this.selectedUrls.clear();
|
this.selectedUrls.set(new Set<string>());
|
||||||
this.markingAsCritical = false;
|
this.markingAsCritical.set(false);
|
||||||
},
|
},
|
||||||
error: () => {
|
error: () => {
|
||||||
this.toastService.showToast({
|
this.toastService.showToast({
|
||||||
@@ -125,9 +144,15 @@ export class AllApplicationsComponent implements OnInit {
|
|||||||
onCheckboxChange = (applicationName: string, event: Event) => {
|
onCheckboxChange = (applicationName: string, event: Event) => {
|
||||||
const isChecked = (event.target as HTMLInputElement).checked;
|
const isChecked = (event.target as HTMLInputElement).checked;
|
||||||
if (isChecked) {
|
if (isChecked) {
|
||||||
this.selectedUrls.add(applicationName);
|
this.selectedUrls.update((selectedUrls) => {
|
||||||
|
selectedUrls.add(applicationName);
|
||||||
|
return selectedUrls;
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
this.selectedUrls.delete(applicationName);
|
this.selectedUrls.update((selectedUrls) => {
|
||||||
|
selectedUrls.delete(applicationName);
|
||||||
|
return selectedUrls;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// FIXME: Update this file to be type safe and remove this and next line
|
// FIXME: Update this file to be type safe and remove this and next line
|
||||||
// @ts-strict-ignore
|
// @ts-strict-ignore
|
||||||
import { Component, DestroyRef, inject, OnInit } from "@angular/core";
|
import { Component, DestroyRef, inject, OnInit, ChangeDetectionStrategy } from "@angular/core";
|
||||||
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
||||||
import { FormControl } from "@angular/forms";
|
import { FormControl } from "@angular/forms";
|
||||||
import { ActivatedRoute, Router } from "@angular/router";
|
import { ActivatedRoute, Router } from "@angular/router";
|
||||||
@@ -8,7 +8,6 @@ import { debounceTime, EMPTY, from, map, switchMap, take } from "rxjs";
|
|||||||
|
|
||||||
import { Security } from "@bitwarden/assets/svg";
|
import { Security } from "@bitwarden/assets/svg";
|
||||||
import {
|
import {
|
||||||
ApplicationHealthReportDetailEnriched,
|
|
||||||
CriticalAppsService,
|
CriticalAppsService,
|
||||||
RiskInsightsDataService,
|
RiskInsightsDataService,
|
||||||
RiskInsightsReportService,
|
RiskInsightsReportService,
|
||||||
@@ -30,12 +29,14 @@ import { SharedModule } from "@bitwarden/web-vault/app/shared";
|
|||||||
import { PipesModule } from "@bitwarden/web-vault/app/vault/individual-vault/pipes/pipes.module";
|
import { PipesModule } from "@bitwarden/web-vault/app/vault/individual-vault/pipes/pipes.module";
|
||||||
|
|
||||||
import { RiskInsightsTabType } from "../models/risk-insights.models";
|
import { RiskInsightsTabType } from "../models/risk-insights.models";
|
||||||
import { AppTableRowScrollableComponent } from "../shared/app-table-row-scrollable.component";
|
import {
|
||||||
|
ApplicationTableDataSource,
|
||||||
|
AppTableRowScrollableComponent,
|
||||||
|
} from "../shared/app-table-row-scrollable.component";
|
||||||
import { AccessIntelligenceSecurityTasksService } from "../shared/security-tasks.service";
|
import { AccessIntelligenceSecurityTasksService } from "../shared/security-tasks.service";
|
||||||
|
|
||||||
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
|
|
||||||
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
|
|
||||||
@Component({
|
@Component({
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
selector: "dirt-critical-applications",
|
selector: "dirt-critical-applications",
|
||||||
templateUrl: "./critical-applications.component.html",
|
templateUrl: "./critical-applications.component.html",
|
||||||
imports: [
|
imports: [
|
||||||
@@ -55,7 +56,7 @@ export class CriticalApplicationsComponent implements OnInit {
|
|||||||
protected organizationId: OrganizationId;
|
protected organizationId: OrganizationId;
|
||||||
noItemsIcon = Security;
|
noItemsIcon = Security;
|
||||||
|
|
||||||
protected dataSource = new TableDataSource<ApplicationHealthReportDetailEnriched>();
|
protected dataSource = new TableDataSource<ApplicationTableDataSource>();
|
||||||
protected applicationSummary = {} as OrganizationReportSummary;
|
protected applicationSummary = {} as OrganizationReportSummary;
|
||||||
|
|
||||||
protected selectedIds: Set<number> = new Set<number>();
|
protected selectedIds: Set<number> = new Set<number>();
|
||||||
@@ -79,9 +80,24 @@ export class CriticalApplicationsComponent implements OnInit {
|
|||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
this.dataService.criticalReportResults$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe({
|
this.dataService.criticalReportResults$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe({
|
||||||
next: (criticalReport) => {
|
next: (criticalReport) => {
|
||||||
this.dataSource.data = criticalReport?.reportData ?? [];
|
if (criticalReport != null) {
|
||||||
this.applicationSummary = criticalReport?.summaryData ?? createNewSummaryData();
|
// Map the report data to include the iconCipher for each application
|
||||||
this.enableRequestPasswordChange = criticalReport?.summaryData?.totalAtRiskMemberCount > 0;
|
const tableDataWithIcon = criticalReport.reportData.map((app) => ({
|
||||||
|
...app,
|
||||||
|
iconCipher:
|
||||||
|
app.cipherIds.length > 0
|
||||||
|
? this.dataService.getCipherIcon(app.cipherIds[0])
|
||||||
|
: undefined,
|
||||||
|
}));
|
||||||
|
this.dataSource.data = tableDataWithIcon;
|
||||||
|
|
||||||
|
this.applicationSummary = criticalReport.summaryData;
|
||||||
|
this.enableRequestPasswordChange = criticalReport.summaryData.totalAtRiskMemberCount > 0;
|
||||||
|
} else {
|
||||||
|
this.dataSource.data = [];
|
||||||
|
this.applicationSummary = createNewSummaryData();
|
||||||
|
this.enableRequestPasswordChange = false;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
error: () => {
|
error: () => {
|
||||||
this.dataSource.data = [];
|
this.dataSource.data = [];
|
||||||
|
|||||||
@@ -46,10 +46,7 @@
|
|||||||
[attr.aria-label]="'viewItem' | i18n"
|
[attr.aria-label]="'viewItem' | i18n"
|
||||||
>
|
>
|
||||||
<!-- Passing the first cipher of the application for app-vault-icon cipher input requirement -->
|
<!-- Passing the first cipher of the application for app-vault-icon cipher input requirement -->
|
||||||
<app-vault-icon
|
<app-vault-icon *ngIf="row.iconCipher" [cipher]="row.iconCipher"></app-vault-icon>
|
||||||
*ngIf="row.cipherIds.length > 0"
|
|
||||||
[cipher]="row.cipherIds[0]"
|
|
||||||
></app-vault-icon>
|
|
||||||
</td>
|
</td>
|
||||||
<td
|
<td
|
||||||
class="tw-cursor-pointer"
|
class="tw-cursor-pointer"
|
||||||
|
|||||||
@@ -3,10 +3,15 @@ import { Component, Input } from "@angular/core";
|
|||||||
|
|
||||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||||
import { ApplicationHealthReportDetailEnriched } from "@bitwarden/bit-common/dirt/reports/risk-insights";
|
import { ApplicationHealthReportDetailEnriched } from "@bitwarden/bit-common/dirt/reports/risk-insights";
|
||||||
|
import { CipherViewLike } from "@bitwarden/common/vault/utils/cipher-view-like-utils";
|
||||||
import { MenuModule, TableDataSource, TableModule } from "@bitwarden/components";
|
import { MenuModule, TableDataSource, TableModule } from "@bitwarden/components";
|
||||||
import { SharedModule } from "@bitwarden/web-vault/app/shared";
|
import { SharedModule } from "@bitwarden/web-vault/app/shared";
|
||||||
import { PipesModule } from "@bitwarden/web-vault/app/vault/individual-vault/pipes/pipes.module";
|
import { PipesModule } from "@bitwarden/web-vault/app/vault/individual-vault/pipes/pipes.module";
|
||||||
|
|
||||||
|
export type ApplicationTableDataSource = ApplicationHealthReportDetailEnriched & {
|
||||||
|
iconCipher: CipherViewLike | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
|
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
|
||||||
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
|
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
|
||||||
@Component({
|
@Component({
|
||||||
@@ -18,7 +23,7 @@ export class AppTableRowScrollableComponent {
|
|||||||
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
|
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
|
||||||
// eslint-disable-next-line @angular-eslint/prefer-signals
|
// eslint-disable-next-line @angular-eslint/prefer-signals
|
||||||
@Input()
|
@Input()
|
||||||
dataSource!: TableDataSource<ApplicationHealthReportDetailEnriched>;
|
dataSource!: TableDataSource<ApplicationTableDataSource>;
|
||||||
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
|
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
|
||||||
// eslint-disable-next-line @angular-eslint/prefer-signals
|
// eslint-disable-next-line @angular-eslint/prefer-signals
|
||||||
@Input() showRowMenuForCriticalApps: boolean = false;
|
@Input() showRowMenuForCriticalApps: boolean = false;
|
||||||
|
|||||||
Reference in New Issue
Block a user