mirror of
https://github.com/bitwarden/browser
synced 2025-12-12 06:13:38 +00:00
[SM-1548] Updating the secrets list to use <bit-table-scroll> (#16201)
* Updating the secrets list to use <bit-table-scroll> * fixing virtaul scroll issue
This commit is contained in:
@@ -83,6 +83,7 @@
|
|||||||
<h2 slot="summary" class="tw-mb-0" bitTypography="h2" noMargin>{{ "secrets" | i18n }}</h2>
|
<h2 slot="summary" class="tw-mb-0" bitTypography="h2" noMargin>{{ "secrets" | i18n }}</h2>
|
||||||
<sm-secrets-list
|
<sm-secrets-list
|
||||||
baseRoute="secrets"
|
baseRoute="secrets"
|
||||||
|
[disableVirtualScroll]="true"
|
||||||
(deleteSecretsEvent)="openDeleteSecret($event)"
|
(deleteSecretsEvent)="openDeleteSecret($event)"
|
||||||
(newSecretEvent)="openNewSecretDialog()"
|
(newSecretEvent)="openNewSecretDialog()"
|
||||||
(editSecretEvent)="openEditSecret($event)"
|
(editSecretEvent)="openEditSecret($event)"
|
||||||
|
|||||||
@@ -23,155 +23,282 @@
|
|||||||
</bit-no-items>
|
</bit-no-items>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<bit-table *ngIf="secrets?.length >= 1" [dataSource]="dataSource">
|
<bit-table-scroll
|
||||||
|
*ngIf="secrets?.length >= 1 && !disableVirtualScroll"
|
||||||
|
[dataSource]="dataSource"
|
||||||
|
[rowSize]="53"
|
||||||
|
>
|
||||||
<ng-container header>
|
<ng-container header>
|
||||||
<tr>
|
<th bitCell class="tw-w-0">
|
||||||
<th bitCell class="tw-w-0">
|
<label class="!tw-mb-0 tw-flex tw-w-fit tw-gap-2 !tw-font-bold !tw-text-muted">
|
||||||
<label class="!tw-mb-0 tw-flex tw-w-fit tw-gap-2 !tw-font-bold !tw-text-muted">
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
(change)="$event ? toggleAll() : null"
|
|
||||||
[checked]="selection.hasValue() && isAllSelected()"
|
|
||||||
[indeterminate]="selection.hasValue() && !isAllSelected()"
|
|
||||||
/>
|
|
||||||
{{ "all" | i18n }}
|
|
||||||
</label>
|
|
||||||
</th>
|
|
||||||
<th bitCell bitSortable="name" default>{{ "name" | i18n }}</th>
|
|
||||||
<th bitCell bitSortable="projects" [fn]="sortProjects">{{ "project" | i18n }}</th>
|
|
||||||
<th bitCell bitSortable="revisionDate">{{ "lastEdited" | i18n }}</th>
|
|
||||||
<th bitCell class="tw-w-0">
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
bitIconButton="bwi-ellipsis-v"
|
|
||||||
buttonType="main"
|
|
||||||
[label]="'options' | i18n"
|
|
||||||
[bitMenuTriggerFor]="tableMenu"
|
|
||||||
></button>
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
</ng-container>
|
|
||||||
<ng-template body let-rows$>
|
|
||||||
<tr bitRow *ngFor="let secret of rows$ | async">
|
|
||||||
<td bitCell>
|
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
(change)="$event ? selection.toggle(secret.id) : null"
|
(change)="$event ? toggleAll() : null"
|
||||||
[checked]="selection.isSelected(secret.id)"
|
[checked]="selection.hasValue() && isAllSelected()"
|
||||||
|
[indeterminate]="selection.hasValue() && !isAllSelected()"
|
||||||
/>
|
/>
|
||||||
</td>
|
{{ "all" | i18n }}
|
||||||
<td bitCell>
|
</label>
|
||||||
<div class="tw-flex tw-items-center tw-gap-4 tw-break-all">
|
</th>
|
||||||
<i class="bwi bwi-key tw-text-muted" aria-hidden="true"></i>
|
<th bitCell bitSortable="name" default>{{ "name" | i18n }}</th>
|
||||||
<div>
|
<th bitCell bitSortable="projects" [fn]="sortProjects">{{ "project" | i18n }}</th>
|
||||||
<div *ngIf="!trash">
|
<th bitCell bitSortable="revisionDate">{{ "lastEdited" | i18n }}</th>
|
||||||
<button type="button" bitLink (click)="editSecret(secret)">
|
<th bitCell class="tw-w-0">
|
||||||
{{ secret.name }}
|
<button
|
||||||
</button>
|
type="button"
|
||||||
</div>
|
bitIconButton="bwi-ellipsis-v"
|
||||||
<div *ngIf="trash">{{ secret.name }}</div>
|
buttonType="main"
|
||||||
<div class="tw-text-sm tw-text-muted">
|
[label]="'options' | i18n"
|
||||||
{{ secret.id }}
|
[bitMenuTriggerFor]="tableMenu"
|
||||||
<button
|
></button>
|
||||||
type="button"
|
</th>
|
||||||
bitIconButton="bwi-clone"
|
</ng-container>
|
||||||
buttonType="main"
|
<ng-template bitRowDef let-row>
|
||||||
size="small"
|
<td bitCell>
|
||||||
[label]="'copyUuid' | i18n"
|
<input
|
||||||
(click)="copySecretUuidEvent.emit(secret.id)"
|
type="checkbox"
|
||||||
></button>
|
(change)="$event ? selection.toggle(row.id) : null"
|
||||||
</div>
|
[checked]="selection.isSelected(row.id)"
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
<td bitCell>
|
||||||
|
<div class="tw-flex tw-items-center tw-gap-4 tw-break-all">
|
||||||
|
<i class="bwi bwi-key tw-text-muted" aria-hidden="true"></i>
|
||||||
|
<div>
|
||||||
|
<div *ngIf="!trash">
|
||||||
|
<button type="button" bitLink (click)="editSecret(row)">
|
||||||
|
{{ row.name }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="trash">{{ row.name }}</div>
|
||||||
|
<div class="tw-text-sm tw-text-muted">
|
||||||
|
{{ row.id }}
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
bitIconButton="bwi-clone"
|
||||||
|
buttonType="main"
|
||||||
|
size="small"
|
||||||
|
[label]="'copyUuid' | i18n"
|
||||||
|
(click)="copySecretUuidEvent.emit(row.id)"
|
||||||
|
></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</div>
|
||||||
<td bitCell>
|
</td>
|
||||||
<span
|
<td bitCell>
|
||||||
*ngFor="let project of secret.projects"
|
<span
|
||||||
bitBadge
|
*ngFor="let project of row.projects"
|
||||||
variant="secondary"
|
bitBadge
|
||||||
class="tw-ml-1"
|
variant="secondary"
|
||||||
[title]="project.name"
|
class="tw-ml-1"
|
||||||
maxWidthClass="tw-max-w-60"
|
[title]="project.name"
|
||||||
>
|
maxWidthClass="tw-max-w-60"
|
||||||
{{ project.name }}
|
>
|
||||||
</span>
|
{{ project.name }}
|
||||||
<span *ngIf="secret.projects.length === 0" bitBadge variant="warning" class="tw-ml-1"
|
</span>
|
||||||
><i class="bwi bwi-fw bwi-exclamation-triangle tw-mr-1" aria-hidden="true"></i
|
<span *ngIf="row.projects.length === 0" bitBadge variant="warning" class="tw-ml-1"
|
||||||
>{{ "unassigned" | i18n }}</span
|
><i class="bwi bwi-fw bwi-exclamation-triangle tw-mr-1" aria-hidden="true"></i
|
||||||
>
|
>{{ "unassigned" | i18n }}</span
|
||||||
</td>
|
>
|
||||||
<td bitCell class="tw-whitespace-nowrap">{{ secret.revisionDate | date: "medium" }}</td>
|
</td>
|
||||||
<td bitCell>
|
<td bitCell class="tw-whitespace-nowrap">{{ row.revisionDate | date: "medium" }}</td>
|
||||||
<button
|
<td bitCell>
|
||||||
type="button"
|
<button
|
||||||
bitIconButton="bwi-ellipsis-v"
|
type="button"
|
||||||
buttonType="main"
|
bitIconButton="bwi-ellipsis-v"
|
||||||
[label]="'options' | i18n"
|
buttonType="main"
|
||||||
[bitMenuTriggerFor]="secretMenu"
|
[label]="'options' | i18n"
|
||||||
></button>
|
[bitMenuTriggerFor]="secretMenu"
|
||||||
</td>
|
></button>
|
||||||
|
</td>
|
||||||
|
|
||||||
<bit-menu #secretMenu>
|
<bit-menu #secretMenu>
|
||||||
<button
|
<button type="button" bitMenuItem (click)="editSecret(row)" *ngIf="row.write && !trash">
|
||||||
type="button"
|
<i class="bwi bwi-fw bwi-pencil" aria-hidden="true"></i>
|
||||||
bitMenuItem
|
{{ "editSecret" | i18n }}
|
||||||
(click)="editSecret(secret)"
|
</button>
|
||||||
*ngIf="secret.write && !trash"
|
<button type="button" bitMenuItem (click)="copySecretNameEvent.emit(row.name)" *ngIf="!trash">
|
||||||
>
|
<i class="bwi bwi-fw bwi-clone" aria-hidden="true"></i>
|
||||||
<i class="bwi bwi-fw bwi-pencil" aria-hidden="true"></i>
|
{{ "copySecretName" | i18n }}
|
||||||
{{ "editSecret" | i18n }}
|
</button>
|
||||||
</button>
|
<button type="button" bitMenuItem (click)="copySecretValueEvent.emit(row.id)" *ngIf="!trash">
|
||||||
<button
|
<i class="bwi bwi-fw bwi-clone" aria-hidden="true"></i>
|
||||||
type="button"
|
{{ "copySecretValue" | i18n }}
|
||||||
bitMenuItem
|
</button>
|
||||||
(click)="copySecretNameEvent.emit(secret.name)"
|
<button type="button" bitMenuItem (click)="restoreSecretsEvent.emit([row.id])" *ngIf="trash">
|
||||||
*ngIf="!trash"
|
<i class="bwi bwi-fw bwi-refresh" aria-hidden="true"></i>
|
||||||
>
|
{{ "restoreSecret" | i18n }}
|
||||||
<i class="bwi bwi-fw bwi-clone" aria-hidden="true"></i>
|
</button>
|
||||||
{{ "copySecretName" | i18n }}
|
<button
|
||||||
</button>
|
type="button"
|
||||||
<button
|
bitMenuItem
|
||||||
type="button"
|
*ngIf="viewEventsAllowed$ | async as allowed"
|
||||||
bitMenuItem
|
(click)="openEventsDialog(row)"
|
||||||
(click)="copySecretValueEvent.emit(secret.id)"
|
>
|
||||||
*ngIf="!trash"
|
<i class="bwi bwi-fw bwi-billing" aria-hidden="true"></i>
|
||||||
>
|
<span> {{ "viewEvents" | i18n }} </span>
|
||||||
<i class="bwi bwi-fw bwi-clone" aria-hidden="true"></i>
|
</button>
|
||||||
{{ "copySecretValue" | i18n }}
|
<button type="button" bitMenuItem (click)="deleteSecretsEvent.emit([row])" *ngIf="row.write">
|
||||||
</button>
|
<i class="bwi bwi-fw bwi-trash tw-text-danger" aria-hidden="true"></i>
|
||||||
<button
|
<span class="tw-text-danger">{{
|
||||||
type="button"
|
(trash ? "permanentlyDelete" : "deleteSecret") | i18n
|
||||||
bitMenuItem
|
}}</span>
|
||||||
(click)="restoreSecretsEvent.emit([secret.id])"
|
</button>
|
||||||
*ngIf="trash"
|
</bit-menu>
|
||||||
>
|
|
||||||
<i class="bwi bwi-fw bwi-refresh" aria-hidden="true"></i>
|
|
||||||
{{ "restoreSecret" | i18n }}
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
bitMenuItem
|
|
||||||
*ngIf="viewEventsAllowed$ | async as allowed"
|
|
||||||
(click)="openEventsDialog(secret)"
|
|
||||||
>
|
|
||||||
<i class="bwi bwi-fw bwi-billing" aria-hidden="true"></i>
|
|
||||||
<span> {{ "viewEvents" | i18n }} </span>
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
bitMenuItem
|
|
||||||
(click)="deleteSecretsEvent.emit([secret])"
|
|
||||||
*ngIf="secret.write"
|
|
||||||
>
|
|
||||||
<i class="bwi bwi-fw bwi-trash tw-text-danger" aria-hidden="true"></i>
|
|
||||||
<span class="tw-text-danger">{{
|
|
||||||
(trash ? "permanentlyDelete" : "deleteSecret") | i18n
|
|
||||||
}}</span>
|
|
||||||
</button>
|
|
||||||
</bit-menu>
|
|
||||||
</tr>
|
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</bit-table>
|
</bit-table-scroll>
|
||||||
|
|
||||||
|
<ng-container *ngIf="disableVirtualScroll">
|
||||||
|
<bit-table *ngIf="secrets?.length >= 1" [dataSource]="dataSource">
|
||||||
|
<ng-container header>
|
||||||
|
<tr>
|
||||||
|
<th bitCell class="tw-w-0">
|
||||||
|
<label class="!tw-mb-0 tw-flex tw-w-fit tw-gap-2 !tw-font-bold !tw-text-muted">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
(change)="$event ? toggleAll() : null"
|
||||||
|
[checked]="selection.hasValue() && isAllSelected()"
|
||||||
|
[indeterminate]="selection.hasValue() && !isAllSelected()"
|
||||||
|
/>
|
||||||
|
{{ "all" | i18n }}
|
||||||
|
</label>
|
||||||
|
</th>
|
||||||
|
<th bitCell bitSortable="name" default>{{ "name" | i18n }}</th>
|
||||||
|
<th bitCell bitSortable="projects" [fn]="sortProjects">{{ "project" | i18n }}</th>
|
||||||
|
<th bitCell bitSortable="revisionDate">{{ "lastEdited" | i18n }}</th>
|
||||||
|
<th bitCell class="tw-w-0">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
bitIconButton="bwi-ellipsis-v"
|
||||||
|
buttonType="main"
|
||||||
|
[label]="'options' | i18n"
|
||||||
|
[bitMenuTriggerFor]="tableMenu"
|
||||||
|
></button>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</ng-container>
|
||||||
|
<ng-template body let-rows$>
|
||||||
|
<tr bitRow *ngFor="let secret of rows$ | async">
|
||||||
|
<td bitCell>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
(change)="$event ? selection.toggle(secret.id) : null"
|
||||||
|
[checked]="selection.isSelected(secret.id)"
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
<td bitCell>
|
||||||
|
<div class="tw-flex tw-items-center tw-gap-4 tw-break-all">
|
||||||
|
<i class="bwi bwi-key tw-text-muted" aria-hidden="true"></i>
|
||||||
|
<div>
|
||||||
|
<div *ngIf="!trash">
|
||||||
|
<button type="button" bitLink (click)="editSecret(secret)">
|
||||||
|
{{ secret.name }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="trash">{{ secret.name }}</div>
|
||||||
|
<div class="tw-text-sm tw-text-muted">
|
||||||
|
{{ secret.id }}
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
bitIconButton="bwi-clone"
|
||||||
|
buttonType="main"
|
||||||
|
size="small"
|
||||||
|
[label]="'copyUuid' | i18n"
|
||||||
|
(click)="copySecretUuidEvent.emit(secret.id)"
|
||||||
|
></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td bitCell>
|
||||||
|
<span
|
||||||
|
*ngFor="let project of secret.projects"
|
||||||
|
bitBadge
|
||||||
|
variant="secondary"
|
||||||
|
class="tw-ml-1"
|
||||||
|
[title]="project.name"
|
||||||
|
maxWidthClass="tw-max-w-60"
|
||||||
|
>
|
||||||
|
{{ project.name }}
|
||||||
|
</span>
|
||||||
|
<span *ngIf="secret.projects.length === 0" bitBadge variant="warning" class="tw-ml-1"
|
||||||
|
><i class="bwi bwi-fw bwi-exclamation-triangle tw-mr-1" aria-hidden="true"></i
|
||||||
|
>{{ "unassigned" | i18n }}</span
|
||||||
|
>
|
||||||
|
</td>
|
||||||
|
<td bitCell class="tw-whitespace-nowrap">{{ secret.revisionDate | date: "medium" }}</td>
|
||||||
|
<td bitCell>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
bitIconButton="bwi-ellipsis-v"
|
||||||
|
buttonType="main"
|
||||||
|
[label]="'options' | i18n"
|
||||||
|
[bitMenuTriggerFor]="secretMenu"
|
||||||
|
></button>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<bit-menu #secretMenu>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
bitMenuItem
|
||||||
|
(click)="editSecret(secret)"
|
||||||
|
*ngIf="secret.write && !trash"
|
||||||
|
>
|
||||||
|
<i class="bwi bwi-fw bwi-pencil" aria-hidden="true"></i>
|
||||||
|
{{ "editSecret" | i18n }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
bitMenuItem
|
||||||
|
(click)="copySecretNameEvent.emit(secret.name)"
|
||||||
|
*ngIf="!trash"
|
||||||
|
>
|
||||||
|
<i class="bwi bwi-fw bwi-clone" aria-hidden="true"></i>
|
||||||
|
{{ "copySecretName" | i18n }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
bitMenuItem
|
||||||
|
(click)="copySecretValueEvent.emit(secret.id)"
|
||||||
|
*ngIf="!trash"
|
||||||
|
>
|
||||||
|
<i class="bwi bwi-fw bwi-clone" aria-hidden="true"></i>
|
||||||
|
{{ "copySecretValue" | i18n }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
bitMenuItem
|
||||||
|
(click)="restoreSecretsEvent.emit([secret.id])"
|
||||||
|
*ngIf="trash"
|
||||||
|
>
|
||||||
|
<i class="bwi bwi-fw bwi-refresh" aria-hidden="true"></i>
|
||||||
|
{{ "restoreSecret" | i18n }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
bitMenuItem
|
||||||
|
*ngIf="viewEventsAllowed$ | async as allowed"
|
||||||
|
(click)="openEventsDialog(secret)"
|
||||||
|
>
|
||||||
|
<i class="bwi bwi-fw bwi-billing" aria-hidden="true"></i>
|
||||||
|
<span> {{ "viewEvents" | i18n }} </span>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
bitMenuItem
|
||||||
|
(click)="deleteSecretsEvent.emit([secret])"
|
||||||
|
*ngIf="secret.write"
|
||||||
|
>
|
||||||
|
<i class="bwi bwi-fw bwi-trash tw-text-danger" aria-hidden="true"></i>
|
||||||
|
<span class="tw-text-danger">{{
|
||||||
|
(trash ? "permanentlyDelete" : "deleteSecret") | i18n
|
||||||
|
}}</span>
|
||||||
|
</button>
|
||||||
|
</bit-menu>
|
||||||
|
</tr>
|
||||||
|
</ng-template>
|
||||||
|
</bit-table>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
<bit-menu #tableMenu>
|
<bit-menu #tableMenu>
|
||||||
<button type="button" bitMenuItem (click)="bulkRestoreSecrets()" *ngIf="trash">
|
<button type="button" bitMenuItem (click)="bulkRestoreSecrets()" *ngIf="trash">
|
||||||
|
|||||||
@@ -29,6 +29,9 @@ import { SecretService } from "../secrets/secret.service";
|
|||||||
export class SecretsListComponent implements OnDestroy, OnInit {
|
export class SecretsListComponent implements OnDestroy, OnInit {
|
||||||
protected dataSource = new TableDataSource<SecretListView>();
|
protected dataSource = new TableDataSource<SecretListView>();
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
disableVirtualScroll: boolean;
|
||||||
|
|
||||||
@Input()
|
@Input()
|
||||||
get secrets(): SecretListView[] {
|
get secrets(): SecretListView[] {
|
||||||
return this._secrets;
|
return this._secrets;
|
||||||
|
|||||||
Reference in New Issue
Block a user