mirror of
https://github.com/bitwarden/browser
synced 2025-12-20 18:23:31 +00:00
PM-18401 apply scroll tables across all tables (#13474)
This commit is contained in:
@@ -69,55 +69,15 @@
|
||||
{{ "markAppAsCritical" | i18n }}
|
||||
</button>
|
||||
</div>
|
||||
<bit-table [dataSource]="dataSource">
|
||||
<ng-container header>
|
||||
<tr>
|
||||
<th *ngIf="isCriticalAppsFeatureEnabled"></th>
|
||||
<th bitSortable="applicationName" bitCell>{{ "application" | i18n }}</th>
|
||||
<th bitSortable="atRiskPasswordCount" bitCell>{{ "atRiskPasswords" | i18n }}</th>
|
||||
<th bitSortable="passwordCount" bitCell>{{ "totalPasswords" | i18n }}</th>
|
||||
<th bitSortable="atRiskMemberCount" bitCell>{{ "atRiskMembers" | i18n }}</th>
|
||||
<th bitSortable="memberCount" bitCell>{{ "totalMembers" | i18n }}</th>
|
||||
</tr>
|
||||
</ng-container>
|
||||
<ng-template body let-rows$>
|
||||
<tr
|
||||
bitRow
|
||||
*ngFor="let r of rows$ | async; trackBy: trackByFunction"
|
||||
[ngClass]="{ 'tw-bg-primary-100': dataService.drawerInvokerId === r.applicationName }"
|
||||
>
|
||||
<td *ngIf="isCriticalAppsFeatureEnabled">
|
||||
<input
|
||||
bitCheckbox
|
||||
type="checkbox"
|
||||
*ngIf="!r.isMarkedAsCritical"
|
||||
[checked]="selectedUrls.has(r.applicationName)"
|
||||
(change)="onCheckboxChange(r.applicationName, $event)"
|
||||
/>
|
||||
<i class="bwi bwi-star-f" *ngIf="r.isMarkedAsCritical"></i>
|
||||
</td>
|
||||
<td class="tw-cursor-pointer" (click)="showAppAtRiskMembers(r.applicationName)" bitCell>
|
||||
<span>{{ r.applicationName }}</span>
|
||||
</td>
|
||||
<td bitCell>
|
||||
<span>
|
||||
{{ r.atRiskPasswordCount }}
|
||||
</span>
|
||||
</td>
|
||||
<td bitCell>
|
||||
<span>
|
||||
{{ r.passwordCount }}
|
||||
</span>
|
||||
</td>
|
||||
<td bitCell>
|
||||
<span>
|
||||
{{ r.atRiskMemberCount }}
|
||||
</span>
|
||||
</td>
|
||||
<td bitCell data-testid="total-membership">
|
||||
{{ r.memberCount }}
|
||||
</td>
|
||||
</tr>
|
||||
</ng-template>
|
||||
</bit-table>
|
||||
|
||||
<app-table-row-scrollable
|
||||
[dataSource]="dataSource"
|
||||
[showRowCheckBox]="true"
|
||||
[showRowMenuForCriticalApps]="false"
|
||||
[selectedUrls]="selectedUrls"
|
||||
[isCriticalAppsFeatureEnabled]="isCriticalAppsFeatureEnabled"
|
||||
[isDrawerIsOpenForThisRecord]="isDrawerOpenForTableRow"
|
||||
[checkboxChange]="onCheckboxChange"
|
||||
[showAppAtRiskMembers]="showAppAtRiskMembers"
|
||||
></app-table-row-scrollable>
|
||||
</div>
|
||||
|
||||
@@ -37,6 +37,7 @@ import { HeaderModule } from "@bitwarden/web-vault/app/layouts/header/header.mod
|
||||
import { SharedModule } from "@bitwarden/web-vault/app/shared";
|
||||
import { PipesModule } from "@bitwarden/web-vault/app/vault/individual-vault/pipes/pipes.module";
|
||||
|
||||
import { AppTableRowScrollableComponent } from "./app-table-row-scrollable.component";
|
||||
import { ApplicationsLoadingComponent } from "./risk-insights-loading.component";
|
||||
|
||||
@Component({
|
||||
@@ -51,6 +52,7 @@ import { ApplicationsLoadingComponent } from "./risk-insights-loading.component"
|
||||
PipesModule,
|
||||
NoItemsModule,
|
||||
SharedModule,
|
||||
AppTableRowScrollableComponent,
|
||||
],
|
||||
})
|
||||
export class AllApplicationsComponent implements OnInit {
|
||||
@@ -190,14 +192,18 @@ export class AllApplicationsComponent implements OnInit {
|
||||
this.dataService.setDrawerForOrgAtRiskApps(data, invokerId);
|
||||
};
|
||||
|
||||
onCheckboxChange(applicationName: string, event: Event) {
|
||||
onCheckboxChange = (applicationName: string, event: Event) => {
|
||||
const isChecked = (event.target as HTMLInputElement).checked;
|
||||
if (isChecked) {
|
||||
this.selectedUrls.add(applicationName);
|
||||
} else {
|
||||
this.selectedUrls.delete(applicationName);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
getSelectedUrls = () => Array.from(this.selectedUrls);
|
||||
|
||||
isDrawerOpenForTableRow = (applicationName: string): boolean => {
|
||||
return this.dataService.drawerInvokerId === applicationName;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
<ng-container>
|
||||
<bit-table-scroll
|
||||
[dataSource]="dataSource"
|
||||
[rowSize]="53"
|
||||
class="tw-table tw-w-full table-hover table-list"
|
||||
>
|
||||
<ng-container header>
|
||||
<th *ngIf="isCriticalAppsFeatureEnabled"></th>
|
||||
<th bitSortable="applicationName" bitCell>{{ "application" | i18n }}</th>
|
||||
<th bitSortable="atRiskPasswordCount" bitCell>{{ "atRiskPasswords" | i18n }}</th>
|
||||
<th bitSortable="passwordCount" bitCell>{{ "totalPasswords" | i18n }}</th>
|
||||
<th bitSortable="atRiskMemberCount" bitCell>{{ "atRiskMembers" | i18n }}</th>
|
||||
<th bitSortable="memberCount" bitCell>{{ "totalMembers" | i18n }}</th>
|
||||
</ng-container>
|
||||
<ng-template bitRowDef let-row>
|
||||
<td
|
||||
bitCell
|
||||
*ngIf="isCriticalAppsFeatureEnabled && showRowCheckBox"
|
||||
[ngClass]="{ 'tw-bg-primary-100': isDrawerIsOpenForThisRecord(row.applicationName) }"
|
||||
>
|
||||
<input
|
||||
bitCheckbox
|
||||
type="checkbox"
|
||||
*ngIf="!row.isMarkedAsCritical"
|
||||
[checked]="selectedUrls.has(row.applicationName)"
|
||||
(change)="checkboxChange(row.applicationName, $event)"
|
||||
/>
|
||||
<i class="bwi bwi-star-f" *ngIf="row.isMarkedAsCritical"></i>
|
||||
</td>
|
||||
<td
|
||||
bitCell
|
||||
*ngIf="!showRowCheckBox"
|
||||
[ngClass]="{ 'tw-bg-primary-100': isDrawerIsOpenForThisRecord(row.applicationName) }"
|
||||
>
|
||||
<i class="bwi bwi-star-f" *ngIf="row.isMarkedAsCritical"></i>
|
||||
</td>
|
||||
<td
|
||||
class="tw-cursor-pointer"
|
||||
[ngClass]="{ 'tw-bg-primary-100': isDrawerIsOpenForThisRecord(row.applicationName) }"
|
||||
(click)="showAppAtRiskMembers(row.applicationName)"
|
||||
(keypress)="showAppAtRiskMembers(row.applicationName)"
|
||||
bitCell
|
||||
>
|
||||
<span>{{ row.applicationName }}</span>
|
||||
</td>
|
||||
<td
|
||||
bitCell
|
||||
[ngClass]="{ 'tw-bg-primary-100': isDrawerIsOpenForThisRecord(row.applicationName) }"
|
||||
>
|
||||
<span>
|
||||
{{ row.atRiskPasswordCount }}
|
||||
</span>
|
||||
</td>
|
||||
<td
|
||||
bitCell
|
||||
[ngClass]="{ 'tw-bg-primary-100': isDrawerIsOpenForThisRecord(row.applicationName) }"
|
||||
>
|
||||
<span>
|
||||
{{ row.passwordCount }}
|
||||
</span>
|
||||
</td>
|
||||
<td
|
||||
bitCell
|
||||
[ngClass]="{ 'tw-bg-primary-100': isDrawerIsOpenForThisRecord(row.applicationName) }"
|
||||
>
|
||||
<span>
|
||||
{{ row.atRiskMemberCount }}
|
||||
</span>
|
||||
</td>
|
||||
<td
|
||||
bitCell
|
||||
data-testid="total-membership"
|
||||
[ngClass]="{ 'tw-bg-primary-100': isDrawerIsOpenForThisRecord(row.applicationName) }"
|
||||
>
|
||||
{{ row.memberCount }}
|
||||
</td>
|
||||
<td
|
||||
bitCell
|
||||
*ngIf="showRowMenuForCriticalApps"
|
||||
[ngClass]="{ 'tw-bg-primary-100': isDrawerIsOpenForThisRecord(row.applicationName) }"
|
||||
>
|
||||
<button
|
||||
[bitMenuTriggerFor]="rowMenu"
|
||||
type="button"
|
||||
bitIconButton="bwi-ellipsis-v"
|
||||
size="small"
|
||||
appA11yTitle="{{ 'options' | i18n }}"
|
||||
></button>
|
||||
|
||||
<bit-menu #rowMenu>
|
||||
<button type="button" bitMenuItem (click)="unmarkAsCriticalApp(row.applicationName)">
|
||||
<i aria-hidden="true" class="bwi bwi-star-f"></i> {{ "unmarkAsCriticalApp" | i18n }}
|
||||
</button>
|
||||
</bit-menu>
|
||||
</td>
|
||||
</ng-template>
|
||||
</bit-table-scroll>
|
||||
</ng-container>
|
||||
@@ -0,0 +1,26 @@
|
||||
import { CommonModule } from "@angular/common";
|
||||
import { Component, Input } from "@angular/core";
|
||||
|
||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||
import { ApplicationHealthReportDetailWithCriticalFlag } from "@bitwarden/bit-common/tools/reports/risk-insights/models/password-health";
|
||||
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";
|
||||
|
||||
@Component({
|
||||
selector: "app-table-row-scrollable",
|
||||
standalone: true,
|
||||
imports: [CommonModule, JslibModule, TableModule, SharedModule, PipesModule, MenuModule],
|
||||
templateUrl: "./app-table-row-scrollable.component.html",
|
||||
})
|
||||
export class AppTableRowScrollableComponent {
|
||||
@Input() dataSource!: TableDataSource<ApplicationHealthReportDetailWithCriticalFlag>;
|
||||
@Input() showRowMenuForCriticalApps: boolean = false;
|
||||
@Input() showRowCheckBox: boolean = false;
|
||||
@Input() selectedUrls: Set<string> = new Set<string>();
|
||||
@Input() isCriticalAppsFeatureEnabled: boolean = false;
|
||||
@Input() isDrawerIsOpenForThisRecord!: (applicationName: string) => boolean;
|
||||
@Input() showAppAtRiskMembers!: (applicationName: string) => void;
|
||||
@Input() unmarkAsCriticalApp!: (applicationName: string) => void;
|
||||
@Input() checkboxChange!: (applicationName: string, $event: Event) => void;
|
||||
}
|
||||
@@ -73,63 +73,14 @@
|
||||
[formControl]="searchControl"
|
||||
></bit-search>
|
||||
</div>
|
||||
<bit-table [dataSource]="dataSource">
|
||||
<ng-container header>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th bitSortable="applicationName" bitCell>{{ "application" | i18n }}</th>
|
||||
<th bitSortable="atRiskPasswordCount" bitCell>{{ "atRiskPasswords" | i18n }}</th>
|
||||
<th bitSortable="passwordCount" bitCell>{{ "totalPasswords" | i18n }}</th>
|
||||
<th bitSortable="atRiskMemberCount" bitCell>{{ "atRiskMembers" | i18n }}</th>
|
||||
<th bitSortable="memberCount" bitCell>{{ "totalMembers" | i18n }}</th>
|
||||
</tr>
|
||||
</ng-container>
|
||||
<ng-template body let-rows$>
|
||||
<tr
|
||||
bitRow
|
||||
*ngFor="let r of rows$ | async; trackBy: trackByFunction"
|
||||
[ngClass]="{ 'tw-bg-primary-100': dataService.drawerInvokerId === r.applicationName }"
|
||||
>
|
||||
<td>
|
||||
<i class="bwi bwi-star-f" *ngIf="r.isMarkedAsCritical"></i>
|
||||
</td>
|
||||
<td class="tw-cursor-pointer" (click)="showAppAtRiskMembers(r.applicationName)" bitCell>
|
||||
<span>{{ r.applicationName }}</span>
|
||||
</td>
|
||||
<td bitCell>
|
||||
<span>
|
||||
{{ r.atRiskPasswordCount }}
|
||||
</span>
|
||||
</td>
|
||||
<td bitCell>
|
||||
<span>
|
||||
{{ r.passwordCount }}
|
||||
</span>
|
||||
</td>
|
||||
<td bitCell>
|
||||
<span>
|
||||
{{ r.atRiskMemberCount }}
|
||||
</span>
|
||||
</td>
|
||||
<td bitCell data-testid="total-membership">
|
||||
{{ r.memberCount }}
|
||||
</td>
|
||||
<td bitCell>
|
||||
<button
|
||||
[bitMenuTriggerFor]="rowMenu"
|
||||
type="button"
|
||||
bitIconButton="bwi-ellipsis-v"
|
||||
size="small"
|
||||
appA11yTitle="{{ 'options' | i18n }}"
|
||||
></button>
|
||||
|
||||
<bit-menu #rowMenu>
|
||||
<button type="button" bitMenuItem (click)="unmarkAsCriticalApp(r.applicationName)">
|
||||
<i aria-hidden="true" class="bwi bwi-star-f"></i> {{ "unmarkAsCriticalApp" | i18n }}
|
||||
</button>
|
||||
</bit-menu>
|
||||
</td>
|
||||
</tr>
|
||||
</ng-template>
|
||||
</bit-table>
|
||||
<app-table-row-scrollable
|
||||
[dataSource]="dataSource"
|
||||
[showRowCheckBox]="false"
|
||||
[showRowMenuForCriticalApps]="true"
|
||||
[isCriticalAppsFeatureEnabled]="true"
|
||||
[isDrawerIsOpenForThisRecord]="isDrawerOpenForTableRow"
|
||||
[showAppAtRiskMembers]="showAppAtRiskMembers"
|
||||
[unmarkAsCriticalApp]="unmarkAsCriticalApp"
|
||||
></app-table-row-scrollable>
|
||||
</div>
|
||||
|
||||
@@ -35,13 +35,22 @@ import { PipesModule } from "@bitwarden/web-vault/app/vault/individual-vault/pip
|
||||
import { CreateTasksRequest } from "../../vault/services/abstractions/admin-task.abstraction";
|
||||
import { DefaultAdminTaskService } from "../../vault/services/default-admin-task.service";
|
||||
|
||||
import { AppTableRowScrollableComponent } from "./app-table-row-scrollable.component";
|
||||
import { RiskInsightsTabType } from "./risk-insights.component";
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
selector: "tools-critical-applications",
|
||||
templateUrl: "./critical-applications.component.html",
|
||||
imports: [CardComponent, HeaderModule, SearchModule, NoItemsModule, PipesModule, SharedModule],
|
||||
imports: [
|
||||
CardComponent,
|
||||
HeaderModule,
|
||||
SearchModule,
|
||||
NoItemsModule,
|
||||
PipesModule,
|
||||
SharedModule,
|
||||
AppTableRowScrollableComponent,
|
||||
],
|
||||
providers: [DefaultAdminTaskService],
|
||||
})
|
||||
export class CriticalApplicationsComponent implements OnInit {
|
||||
@@ -181,4 +190,7 @@ export class CriticalApplicationsComponent implements OnInit {
|
||||
trackByFunction(_: number, item: ApplicationHealthReportDetailWithCriticalFlag) {
|
||||
return item.applicationName;
|
||||
}
|
||||
isDrawerOpenForTableRow = (applicationName: string) => {
|
||||
return this.dataService.drawerInvokerId === applicationName;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -9,47 +9,43 @@
|
||||
<span class="tw-sr-only">{{ "loading" | i18n }}</span>
|
||||
</div>
|
||||
<div class="tw-mt-4" *ngIf="!loading">
|
||||
<bit-table [dataSource]="dataSource">
|
||||
<bit-table-scroll [dataSource]="dataSource" [rowSize]="53">
|
||||
<ng-container header>
|
||||
<tr bitRow>
|
||||
<th bitCell bitSortable="hostURI">{{ "application" | i18n }}</th>
|
||||
<th bitCell class="tw-text-right">{{ "weakness" | i18n }}</th>
|
||||
<th bitCell class="tw-text-right">{{ "timesReused" | i18n }}</th>
|
||||
<th bitCell class="tw-text-right">{{ "timesExposed" | i18n }}</th>
|
||||
<th bitCell class="tw-text-right">{{ "totalMembers" | i18n }}</th>
|
||||
</tr>
|
||||
<th bitCell bitSortable="hostURI">{{ "application" | i18n }}</th>
|
||||
<th bitCell class="tw-text-right">{{ "weakness" | i18n }}</th>
|
||||
<th bitCell class="tw-text-right">{{ "timesReused" | i18n }}</th>
|
||||
<th bitCell class="tw-text-right">{{ "timesExposed" | i18n }}</th>
|
||||
<th bitCell class="tw-text-right">{{ "totalMembers" | i18n }}</th>
|
||||
</ng-container>
|
||||
<ng-template body let-rows$>
|
||||
<tr bitRow *ngFor="let r of rows$ | async">
|
||||
<td bitCell>
|
||||
<ng-container>
|
||||
<span>{{ r.hostURI }}</span>
|
||||
</ng-container>
|
||||
</td>
|
||||
<td bitCell class="tw-text-right">
|
||||
<span
|
||||
bitBadge
|
||||
*ngIf="passwordStrengthMap.has(r.id)"
|
||||
[variant]="passwordStrengthMap.get(r.id)[1]"
|
||||
>
|
||||
{{ passwordStrengthMap.get(r.id)[0] | i18n }}
|
||||
</span>
|
||||
</td>
|
||||
<td bitCell class="tw-text-right">
|
||||
<span bitBadge *ngIf="passwordUseMap.has(r.login.password)" variant="warning">
|
||||
{{ "reusedXTimes" | i18n: passwordUseMap.get(r.login.password) }}
|
||||
</span>
|
||||
</td>
|
||||
<td bitCell class="tw-text-right">
|
||||
<span bitBadge *ngIf="exposedPasswordMap.has(r.id)" variant="warning">
|
||||
{{ "exposedXTimes" | i18n: exposedPasswordMap.get(r.id) }}
|
||||
</span>
|
||||
</td>
|
||||
<td bitCell class="tw-text-right" data-testid="total-membership">
|
||||
{{ totalMembersMap.get(r.id) || 0 }}
|
||||
</td>
|
||||
</tr>
|
||||
<ng-template bitRowDef let-row>
|
||||
<td bitCell>
|
||||
<ng-container>
|
||||
<span>{{ row.hostURI }}</span>
|
||||
</ng-container>
|
||||
</td>
|
||||
<td bitCell class="tw-text-right">
|
||||
<span
|
||||
bitBadge
|
||||
*ngIf="passwordStrengthMap.has(row.id)"
|
||||
[variant]="passwordStrengthMap.get(row.id)[1]"
|
||||
>
|
||||
{{ passwordStrengthMap.get(row.id)[0] | i18n }}
|
||||
</span>
|
||||
</td>
|
||||
<td bitCell class="tw-text-right">
|
||||
<span bitBadge *ngIf="passwordUseMap.has(row.login.password)" variant="warning">
|
||||
{{ "reusedXTimes" | i18n: passwordUseMap.get(row.login.password) }}
|
||||
</span>
|
||||
</td>
|
||||
<td bitCell class="tw-text-right">
|
||||
<span bitBadge *ngIf="exposedPasswordMap.has(row.id)" variant="warning">
|
||||
{{ "exposedXTimes" | i18n: exposedPasswordMap.get(row.id) }}
|
||||
</span>
|
||||
</td>
|
||||
<td bitCell class="tw-text-right" data-testid="total-membership">
|
||||
{{ totalMembersMap.get(row.id) || 0 }}
|
||||
</td>
|
||||
</ng-template>
|
||||
</bit-table>
|
||||
</bit-table-scroll>
|
||||
</div>
|
||||
</bit-container>
|
||||
|
||||
@@ -8,57 +8,53 @@
|
||||
<span class="tw-sr-only">{{ "loading" | i18n }}</span>
|
||||
</div>
|
||||
<div class="tw-flex tw-flex-col" *ngIf="!loading && dataSource.data.length">
|
||||
<bit-table [dataSource]="dataSource">
|
||||
<bit-table-scroll [dataSource]="dataSource" [rowSize]="74">
|
||||
<ng-container header>
|
||||
<tr bitRow>
|
||||
<th bitCell></th>
|
||||
<th bitCell bitSortable="name">{{ "name" | i18n }}</th>
|
||||
<th bitCell class="tw-text-right">{{ "weakness" | i18n }}</th>
|
||||
<th bitCell class="tw-text-right">{{ "timesReused" | i18n }}</th>
|
||||
<th bitCell class="tw-text-right">{{ "timesExposed" | i18n }}</th>
|
||||
<th bitCell class="tw-text-right">{{ "totalMembers" | i18n }}</th>
|
||||
</tr>
|
||||
<th bitCell></th>
|
||||
<th bitCell bitSortable="name">{{ "name" | i18n }}</th>
|
||||
<th bitCell class="tw-text-right">{{ "weakness" | i18n }}</th>
|
||||
<th bitCell class="tw-text-right">{{ "timesReused" | i18n }}</th>
|
||||
<th bitCell class="tw-text-right">{{ "timesExposed" | i18n }}</th>
|
||||
<th bitCell class="tw-text-right">{{ "totalMembers" | i18n }}</th>
|
||||
</ng-container>
|
||||
<ng-template body let-rows$>
|
||||
<tr bitRow *ngFor="let r of rows$ | async; trackBy: trackByFunction">
|
||||
<td bitCell>
|
||||
<input
|
||||
bitCheckbox
|
||||
type="checkbox"
|
||||
[checked]="selectedIds.has(r.id)"
|
||||
(change)="onCheckboxChange(r.id, $event)"
|
||||
/>
|
||||
</td>
|
||||
<td bitCell>
|
||||
<ng-container>
|
||||
<span>{{ r.name }}</span>
|
||||
</ng-container>
|
||||
<br />
|
||||
<small>{{ r.subTitle }}</small>
|
||||
</td>
|
||||
<td bitCell class="tw-text-right">
|
||||
<span
|
||||
bitBadge
|
||||
*ngIf="passwordStrengthMap.has(r.id)"
|
||||
[variant]="passwordStrengthMap.get(r.id)[1]"
|
||||
>
|
||||
{{ passwordStrengthMap.get(r.id)[0] | i18n }}
|
||||
</span>
|
||||
</td>
|
||||
<td bitCell class="tw-text-right">
|
||||
<span bitBadge *ngIf="passwordUseMap.has(r.login.password)" variant="warning">
|
||||
{{ "reusedXTimes" | i18n: passwordUseMap.get(r.login.password) }}
|
||||
</span>
|
||||
</td>
|
||||
<td bitCell class="tw-text-right">
|
||||
<span bitBadge *ngIf="exposedPasswordMap.has(r.id)" variant="warning">
|
||||
{{ "exposedXTimes" | i18n: exposedPasswordMap.get(r.id) }}
|
||||
</span>
|
||||
</td>
|
||||
<td bitCell class="tw-text-right" data-testid="total-membership">
|
||||
{{ totalMembersMap.get(r.id) || 0 }}
|
||||
</td>
|
||||
</tr>
|
||||
<ng-template bitRowDef let-row>
|
||||
<td bitCell>
|
||||
<input
|
||||
bitCheckbox
|
||||
type="checkbox"
|
||||
[checked]="selectedIds.has(row.id)"
|
||||
(change)="onCheckboxChange(row.id, $event)"
|
||||
/>
|
||||
</td>
|
||||
<td bitCell>
|
||||
<ng-container>
|
||||
<span>{{ row.name }}</span>
|
||||
</ng-container>
|
||||
<br />
|
||||
<small>{{ row.subTitle }}</small>
|
||||
</td>
|
||||
<td bitCell class="tw-text-right">
|
||||
<span
|
||||
bitBadge
|
||||
*ngIf="passwordStrengthMap.has(row.id)"
|
||||
[variant]="passwordStrengthMap.get(row.id)[1]"
|
||||
>
|
||||
{{ passwordStrengthMap.get(row.id)[0] | i18n }}
|
||||
</span>
|
||||
</td>
|
||||
<td bitCell class="tw-text-right">
|
||||
<span bitBadge *ngIf="passwordUseMap.has(row.login.password)" variant="warning">
|
||||
{{ "reusedXTimes" | i18n: passwordUseMap.get(row.login.password) }}
|
||||
</span>
|
||||
</td>
|
||||
<td bitCell class="tw-text-right">
|
||||
<span bitBadge *ngIf="exposedPasswordMap.has(row.id)" variant="warning">
|
||||
{{ "exposedXTimes" | i18n: exposedPasswordMap.get(row.id) }}
|
||||
</span>
|
||||
</td>
|
||||
<td bitCell class="tw-text-right" data-testid="total-membership">
|
||||
{{ totalMembersMap.get(row.id) || 0 }}
|
||||
</td>
|
||||
</ng-template>
|
||||
</bit-table>
|
||||
</bit-table-scroll>
|
||||
</div>
|
||||
|
||||
@@ -9,49 +9,45 @@
|
||||
<span class="tw-sr-only">{{ "loading" | i18n }}</span>
|
||||
</div>
|
||||
<div class="tw-mt-4" *ngIf="!loading && dataSource.data.length">
|
||||
<bit-table [dataSource]="dataSource">
|
||||
<bit-table-scroll [dataSource]="dataSource" [rowSize]="53">
|
||||
<ng-container header>
|
||||
<tr bitRow>
|
||||
<th bitCell></th>
|
||||
<th bitCell bitSortable="name">{{ "name" | i18n }}</th>
|
||||
<th bitCell class="tw-text-right">{{ "weakness" | i18n }}</th>
|
||||
<th bitCell class="tw-text-right">{{ "timesReused" | i18n }}</th>
|
||||
<th bitCell class="tw-text-right">{{ "timesExposed" | i18n }}</th>
|
||||
</tr>
|
||||
<th bitCell></th>
|
||||
<th bitCell bitSortable="name">{{ "name" | i18n }}</th>
|
||||
<th bitCell class="tw-text-right">{{ "weakness" | i18n }}</th>
|
||||
<th bitCell class="tw-text-right">{{ "timesReused" | i18n }}</th>
|
||||
<th bitCell class="tw-text-right">{{ "timesExposed" | i18n }}</th>
|
||||
</ng-container>
|
||||
<ng-template body let-rows$>
|
||||
<tr bitRow *ngFor="let r of rows$ | async">
|
||||
<td bitCell>
|
||||
<app-vault-icon [cipher]="r"></app-vault-icon>
|
||||
</td>
|
||||
<td bitCell>
|
||||
<ng-container>
|
||||
<span>{{ r.name }}</span>
|
||||
</ng-container>
|
||||
<br />
|
||||
<small>{{ r.subTitle }}</small>
|
||||
</td>
|
||||
<td bitCell class="tw-text-right">
|
||||
<span
|
||||
bitBadge
|
||||
*ngIf="r.weakPasswordDetail"
|
||||
[variant]="r.weakPasswordDetail?.detailValue.badgeVariant"
|
||||
>
|
||||
{{ r.weakPasswordDetail?.detailValue.label | i18n }}
|
||||
</span>
|
||||
</td>
|
||||
<td bitCell class="tw-text-right">
|
||||
<span bitBadge *ngIf="passwordUseMap.has(r.login.password)" variant="warning">
|
||||
{{ "reusedXTimes" | i18n: passwordUseMap.get(r.login.password) }}
|
||||
</span>
|
||||
</td>
|
||||
<td bitCell class="tw-text-right">
|
||||
<span bitBadge variant="warning" *ngIf="r.exposedPasswordDetail">
|
||||
{{ "exposedXTimes" | i18n: r.exposedPasswordDetail?.exposedXTimes }}
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<ng-template bitRowDef let-row>
|
||||
<td bitCell>
|
||||
<app-vault-icon [cipher]="row"></app-vault-icon>
|
||||
</td>
|
||||
<td bitCell>
|
||||
<ng-container>
|
||||
<span>{{ row.name }}</span>
|
||||
</ng-container>
|
||||
<br />
|
||||
<small>{{ row.subTitle }}</small>
|
||||
</td>
|
||||
<td bitCell class="tw-text-right">
|
||||
<span
|
||||
bitBadge
|
||||
*ngIf="row.weakPasswordDetail"
|
||||
[variant]="row.weakPasswordDetail?.detailValue.badgeVariant"
|
||||
>
|
||||
{{ row.weakPasswordDetail?.detailValue.label | i18n }}
|
||||
</span>
|
||||
</td>
|
||||
<td bitCell class="tw-text-right">
|
||||
<span bitBadge *ngIf="passwordUseMap.has(row.login.password)" variant="warning">
|
||||
{{ "reusedXTimes" | i18n: passwordUseMap.get(row.login.password) }}
|
||||
</span>
|
||||
</td>
|
||||
<td bitCell class="tw-text-right">
|
||||
<span bitBadge variant="warning" *ngIf="row.exposedPasswordDetail">
|
||||
{{ "exposedXTimes" | i18n: row.exposedPasswordDetail?.exposedXTimes }}
|
||||
</span>
|
||||
</td>
|
||||
</ng-template>
|
||||
</bit-table>
|
||||
</bit-table-scroll>
|
||||
</div>
|
||||
</bit-container>
|
||||
|
||||
Reference in New Issue
Block a user