1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-12 14:23:32 +00:00

PM-2630 virtual scroll on tables (#13725)

Tested by QA and passed.
This commit is contained in:
Vijay Oommen
2025-03-10 14:52:52 -05:00
committed by GitHub
parent f682870e41
commit a877450e0a
4 changed files with 186 additions and 198 deletions

View File

@@ -26,9 +26,8 @@
</bit-toggle> </bit-toggle>
</ng-container> </ng-container>
</bit-toggle-group> </bit-toggle-group>
<bit-table [dataSource]="dataSource"> <bit-table-scroll [dataSource]="dataSource" [rowSize]="53">
<ng-container header> <ng-container header>
<tr bitRow>
<th bitCell></th> <th bitCell></th>
<th bitCell bitSortable="name">{{ "name" | i18n }}</th> <th bitCell bitSortable="name">{{ "name" | i18n }}</th>
<th bitCell bitSortable="organizationId" *ngIf="!isAdminConsoleActive"> <th bitCell bitSortable="organizationId" *ngIf="!isAdminConsoleActive">
@@ -37,28 +36,26 @@
<th bitCell class="tw-text-right" bitSortable="exposedXTimes"> <th bitCell class="tw-text-right" bitSortable="exposedXTimes">
{{ "timesExposed" | i18n }} {{ "timesExposed" | i18n }}
</th> </th>
</tr>
</ng-container> </ng-container>
<ng-template body let-rows$> <ng-template bitRowDef let-row>
<tr bitRow *ngFor="let r of rows$ | async">
<td bitCell> <td bitCell>
<app-vault-icon [cipher]="r"></app-vault-icon> <app-vault-icon [cipher]="row"></app-vault-icon>
</td> </td>
<td bitCell> <td bitCell>
<ng-container *ngIf="!organization || canManageCipher(r); else cantManage"> <ng-container *ngIf="!organization || canManageCipher(row); else cantManage">
<a <a
bitLink bitLink
href="#" href="#"
appStopClick appStopClick
(click)="selectCipher(r)" (click)="selectCipher(row)"
title="{{ 'editItemWithName' | i18n: r.name }}" title="{{ 'editItemWithName' | i18n: row.name }}"
>{{ r.name }}</a >{{ row.name }}</a
> >
</ng-container> </ng-container>
<ng-template #cantManage> <ng-template #cantManage>
<span>{{ r.name }}</span> <span>{{ row.name }}</span>
</ng-template> </ng-template>
<ng-container *ngIf="!organization && r.organizationId"> <ng-container *ngIf="!organization && row.organizationId">
<i <i
class="bwi bwi-collection" class="bwi bwi-collection"
appStopProp appStopProp
@@ -67,7 +64,7 @@
></i> ></i>
<span class="tw-sr-only">{{ "shared" | i18n }}</span> <span class="tw-sr-only">{{ "shared" | i18n }}</span>
</ng-container> </ng-container>
<ng-container *ngIf="r.hasAttachments"> <ng-container *ngIf="row.hasAttachments">
<i <i
class="bwi bwi-paperclip" class="bwi bwi-paperclip"
appStopProp appStopProp
@@ -77,26 +74,25 @@
<span class="tw-sr-only">{{ "attachments" | i18n }}</span> <span class="tw-sr-only">{{ "attachments" | i18n }}</span>
</ng-container> </ng-container>
<br /> <br />
<small>{{ r.subTitle }}</small> <small>{{ row.subTitle }}</small>
</td> </td>
<td bitCell *ngIf="!isAdminConsoleActive"> <td bitCell *ngIf="!isAdminConsoleActive">
<app-org-badge <app-org-badge
*ngIf="!organization" *ngIf="!organization"
[disabled]="disabled" [disabled]="disabled"
[organizationId]="r.organizationId" [organizationId]="row.organizationId"
[organizationName]="r.organizationId | orgNameFromId: (organizations$ | async)" [organizationName]="row.organizationId | orgNameFromId: (organizations$ | async)"
appStopProp appStopProp
> >
</app-org-badge> </app-org-badge>
</td> </td>
<td bitCell class="tw-text-right"> <td bitCell class="tw-text-right">
<span bitBadge variant="warning"> <span bitBadge variant="warning">
{{ "exposedXTimes" | i18n: (r.exposedXTimes | number) }} {{ "exposedXTimes" | i18n: (row.exposedXTimes | number) }}
</span> </span>
</td> </td>
</tr>
</ng-template> </ng-template>
</bit-table> </bit-table-scroll>
</ng-container> </ng-container>
</div> </div>
<ng-template #cipherAddEdit></ng-template> <ng-template #cipherAddEdit></ng-template>

View File

@@ -33,35 +33,32 @@
</ng-container> </ng-container>
</bit-toggle-group> </bit-toggle-group>
<bit-table [dataSource]="dataSource"> <bit-table-scroll [dataSource]="dataSource" [rowSize]="75">
<ng-container header *ngIf="!isAdminConsoleActive"> <ng-container header *ngIf="!isAdminConsoleActive">
<tr bitRow>
<th bitCell></th> <th bitCell></th>
<th bitCell>{{ "name" | i18n }}</th> <th bitCell>{{ "name" | i18n }}</th>
<th bitCell>{{ "owner" | i18n }}</th> <th bitCell>{{ "owner" | i18n }}</th>
<th bitCell class="tw-text-right">{{ "timesReused" | i18n }}</th> <th bitCell class="tw-text-right">{{ "timesReused" | i18n }}</th>
</tr>
</ng-container> </ng-container>
<ng-template body let-rows$> <ng-template bitRowDef let-row>
<tr bitRow *ngFor="let r of rows$ | async">
<td bitCell> <td bitCell>
<app-vault-icon [cipher]="r"></app-vault-icon> <app-vault-icon [cipher]="row"></app-vault-icon>
</td> </td>
<td bitCell> <td bitCell>
<ng-container *ngIf="!organization || canManageCipher(r); else cantManage"> <ng-container *ngIf="!organization || canManageCipher(row); else cantManage">
<a <a
bitLink bitLink
href="#" href="#"
appStopClick appStopClick
(click)="selectCipher(r)" (click)="selectCipher(row)"
title="{{ 'editItemWithName' | i18n: r.name }}" title="{{ 'editItemWithName' | i18n: row.name }}"
>{{ r.name }}</a >{{ row.name }}</a
> >
</ng-container> </ng-container>
<ng-template #cantManage> <ng-template #cantManage>
<span>{{ r.name }}</span> <span>{{ row.name }}</span>
</ng-template> </ng-template>
<ng-container *ngIf="!organization && r.organizationId"> <ng-container *ngIf="!organization && row.organizationId">
<i <i
class="bwi bwi-collection" class="bwi bwi-collection"
appStopProp appStopProp
@@ -70,7 +67,7 @@
></i> ></i>
<span class="tw-sr-only">{{ "shared" | i18n }}</span> <span class="tw-sr-only">{{ "shared" | i18n }}</span>
</ng-container> </ng-container>
<ng-container *ngIf="r.hasAttachments"> <ng-container *ngIf="row.hasAttachments">
<i <i
class="bwi bwi-paperclip" class="bwi bwi-paperclip"
appStopProp appStopProp
@@ -80,26 +77,25 @@
<span class="tw-sr-only">{{ "attachments" | i18n }}</span> <span class="tw-sr-only">{{ "attachments" | i18n }}</span>
</ng-container> </ng-container>
<br /> <br />
<small>{{ r.subTitle }}</small> <small>{{ row.subTitle }}</small>
</td> </td>
<td bitCell> <td bitCell>
<app-org-badge <app-org-badge
*ngIf="!organization" *ngIf="!organization"
[disabled]="disabled" [disabled]="disabled"
[organizationId]="r.organizationId" [organizationId]="row.organizationId"
[organizationName]="r.organizationId | orgNameFromId: (organizations$ | async)" [organizationName]="row.organizationId | orgNameFromId: (organizations$ | async)"
appStopProp appStopProp
> >
</app-org-badge> </app-org-badge>
</td> </td>
<td bitCell class="tw-text-right"> <td bitCell class="tw-text-right">
<span bitBadge variant="warning"> <span bitBadge variant="warning">
{{ "reusedXTimes" | i18n: passwordUseMap.get(r.login.password) }} {{ "reusedXTimes" | i18n: passwordUseMap.get(row.login.password) }}
</span> </span>
</td> </td>
</tr>
</ng-template> </ng-template>
</bit-table> </bit-table-scroll>
</ng-container> </ng-container>
</div> </div>
<ng-template #cipherAddEdit></ng-template> <ng-template #cipherAddEdit></ng-template>

View File

@@ -31,9 +31,8 @@
</bit-toggle> </bit-toggle>
</ng-container> </ng-container>
</bit-toggle-group> </bit-toggle-group>
<bit-table [dataSource]="dataSource"> <bit-table-scroll [dataSource]="dataSource" [rowSize]="53">
<ng-container header> <ng-container header>
<tr bitRow>
<th bitCell></th> <th bitCell></th>
<th bitCell bitSortable="name">{{ "name" | i18n }}</th> <th bitCell bitSortable="name">{{ "name" | i18n }}</th>
<th bitCell bitSortable="organizationId" *ngIf="!isAdminConsoleActive"> <th bitCell bitSortable="organizationId" *ngIf="!isAdminConsoleActive">
@@ -42,28 +41,26 @@
<th bitCell class="tw-text-right" bitSortable="score" default> <th bitCell class="tw-text-right" bitSortable="score" default>
{{ "weakness" | i18n }} {{ "weakness" | i18n }}
</th> </th>
</tr>
</ng-container> </ng-container>
<ng-template body let-rows$> <ng-template bitRowDef let-row>
<tr bitRow *ngFor="let r of rows$ | async">
<td bitCell> <td bitCell>
<app-vault-icon [cipher]="r"></app-vault-icon> <app-vault-icon [cipher]="row"></app-vault-icon>
</td> </td>
<td bitCell> <td bitCell>
<ng-container *ngIf="!organization || canManageCipher(r); else cantManage"> <ng-container *ngIf="!organization || canManageCipher(row); else cantManage">
<a <a
bitLink bitLink
href="#" href="#"
appStopClick appStopClick
(click)="selectCipher(r)" (click)="selectCipher(row)"
title="{{ 'editItemWithName' | i18n: r.name }}" title="{{ 'editItemWithName' | i18n: row.name }}"
>{{ r.name }}</a >{{ row.name }}</a
> >
</ng-container> </ng-container>
<ng-template #cantManage> <ng-template #cantManage>
<span>{{ r.name }}</span> <span>{{ row.name }}</span>
</ng-template> </ng-template>
<ng-container *ngIf="!organization && r.organizationId"> <ng-container *ngIf="!organization && row.organizationId">
<i <i
class="bwi bwi-collection" class="bwi bwi-collection"
appStopProp appStopProp
@@ -72,7 +69,7 @@
></i> ></i>
<span class="tw-sr-only">{{ "shared" | i18n }}</span> <span class="tw-sr-only">{{ "shared" | i18n }}</span>
</ng-container> </ng-container>
<ng-container *ngIf="r.hasAttachments"> <ng-container *ngIf="row.hasAttachments">
<i <i
class="bwi bwi-paperclip" class="bwi bwi-paperclip"
appStopProp appStopProp
@@ -82,26 +79,25 @@
<span class="tw-sr-only">{{ "attachments" | i18n }}</span> <span class="tw-sr-only">{{ "attachments" | i18n }}</span>
</ng-container> </ng-container>
<br /> <br />
<small>{{ r.subTitle }}</small> <small>{{ row.subTitle }}</small>
</td> </td>
<td bitCell *ngIf="!isAdminConsoleActive"> <td bitCell *ngIf="!isAdminConsoleActive">
<app-org-badge <app-org-badge
*ngIf="!organization" *ngIf="!organization"
[disabled]="disabled" [disabled]="disabled"
[organizationId]="r.organizationId" [organizationId]="row.organizationId"
[organizationName]="r.organizationId | orgNameFromId: (organizations$ | async)" [organizationName]="row.organizationId | orgNameFromId: (organizations$ | async)"
appStopProp appStopProp
> >
</app-org-badge> </app-org-badge>
</td> </td>
<td bitCell class="tw-text-right"> <td bitCell class="tw-text-right">
<span bitBadge [variant]="r.reportValue.badgeVariant"> <span bitBadge [variant]="row.reportValue.badgeVariant">
{{ r.reportValue.label | i18n }} {{ row.reportValue.label | i18n }}
</span> </span>
</td> </td>
</tr>
</ng-template> </ng-template>
</bit-table> </bit-table-scroll>
</ng-container> </ng-container>
</div> </div>
<ng-template #cipherAddEdit></ng-template> <ng-template #cipherAddEdit></ng-template>

View File

@@ -12,7 +12,7 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr *cdkVirtualFor="let r of rows$; trackBy: trackBy" bitRow> <tr *cdkVirtualFor="let r of rows$; trackBy: trackBy; templateCacheSize: 0" bitRow>
<ng-container *ngTemplateOutlet="rowDef.template; context: { $implicit: r }"></ng-container> <ng-container *ngTemplateOutlet="rowDef.template; context: { $implicit: r }"></ng-container>
</tr> </tr>
</tbody> </tbody>