mirror of
https://github.com/bitwarden/browser
synced 2025-12-16 00:03:56 +00:00
* [EC-14] initial refactoring of vault filter * [EC-14] return observable trees for all filters with head node * [EC-14] Remove bindings on callbacks * [EC-14] fix formatting on disabled orgs * [EC-14] hide MyVault if personal org policy * [EC-14] add check for single org policy * [EC-14] add policies to org and change node constructor * [EC-14] don't show options if personal vault policy * [EC-14] default to all vaults * [EC-14] add default selection to filters * [EC-14] finish filter model callbacks * [EC-14] finish filter functionality and begin cleaning up * [EC-14] clean up old components and start on org vault * [EC-14] loop through filters for presentation * [EC-14] refactor VaultFilterService and put filter presentation data back into Vault Filter component. Remove VaultService * [EC-14] begin refactoring org vault * [EC-14] Refactor Vault Filter Service to use observables * [EC-14] finish org vault filter * [EC-14] fix vault model tests * [EC-14] fix org service calls * [EC-14] pull refactor out of shared code * [EC-14] include head node for collections even if collections aren't loaded yet * [EC-14] fix url params for vaults * [EC-14] remove comments * [EC-14] Remove unnecesary getter for org on vault filter * [EC-14] fix linter * [EC-14] fix prettier * [EC-14] add deprecated methods to collection service for desktop and browser * [EC-14] simplify cipher type node check * [EC-14] add getters to vault filter model * [EC-14] refactor how we build the filter list into methods * [EC-14] add getters to build filter method * [EC-14] start adding header and collection rows * [EC-14] remove param ids if false * [EC-14] Make collection rows navigatable * [EC-14] fix collapsing nodes * [EC-14] add specific type to search placeholder * [EC-14] remove extra constructor and comment from org vault filter * [EC-14] extract subscription callback to methods * [EC-14] Remove unecessary await * [EC-14] Remove ternary operators while building org filter * [EC-14] remove unnecessary deps array in vault filter service declaration * [EC-14] consolidate new models into one file * [EC-14] change name of edit collections method * [EC-14] add collection badges to item rows * [EC-14] show groups badge on collection rows * [EC-14] add bulk actions to header menu button * [EC-14] initialize nested observable inside of service Signed-off-by: Jacob Fink <jfink@bitwarden.com> * [EC-14] change how we load orgs into the vault filter and select the default filter * [EC-14] remove get from getters name * [EC-14] remove eslint-disable comment * [EC-14] move vault filter service abstraction to angular folder and separate * [EC-14] rename filter types and delete VaultFilterLabel * [EC-14] remove changes to workspace file * [EC-14] remove deprecated service from jslib module * [EC-14] remove any remaining files from common code * [EC-14] consolidate vault filter components into components folder * [EC-14] simplify method call * [EC-14] refactor the vault filter service - orgs now have observable property - BehaviorSubjects have been migrated to ReplaySubjects if they don't need starting value - added unit tests - fix small error when selecting org badge of personal vault - renamed some properties * [EC-14] replace mergeMap with switchMap in vault filter service * [EC-14] early return to prevent nesting * [EC-14] clean up filterCollections method * [EC-14] use isDeleted helper in html * [EC-14] add jsdoc comments to ServiceUtils * [EC-14] fix linter * [EC-14] use array.slice instead of setting length * [EC-14] resolve merge conflicts * [EC-14] remove checkbox from end user vault collection rows * [EC-14] add owner column to collections in end user vault * [EC-14] add a11y titles for vault filters * Update apps/web/src/app/vault/vault-filter/services/vault-filter.service.ts Co-authored-by: Thomas Rittson <31796059+eliykat@users.noreply.github.com> * [EC-14] add missing high level jsdoc description * [EC-14] fix storybook absolute imports * [EC-14] delete vault-shared.module * [EC-14] change search placeholder text to getter and add missing strings * [EC-14] remove two way binding from search text in vault filter * [EC-14] removed all binding from search text and just use input event * [EC-14] remove async from apply vault filter * [EC-14] remove circular observable calls in vault filter service Co-authored-by: Thomas Rittson <eliykat@users.noreply.github.com> * [EC-14] move collapsed nodes to vault filter section * [EC-14] deconstruct filter section inside component * [EC-14] fix merge conflicts and introduce refactored organization service to vault filter service * [EC-14] remove mutation from filter builders * [EC-14] fix styling on buildFolderTree * [EC-14] remove leftover folder-filters reference and use ternary for collapse icon * [EC-14] remove unecessary checks * [EC-14] stop rebuilding filters when the organization changes * [EC-14] Move subscription out of setter in vault filter section * [EC-14] remove extra policy service methods from vault filter service * [EC-14] remove new methods from old vault-filter.service * [EC-14] Use vault filter service in vault components * [EC-14] reload collections from vault now that we have vault filter service * [EC-14] remove currentFilterCollections in vault filter component * [EC-14] change VaultFilterType to more specific OrganizationFilter in organization-options * [EC-14] include org check in isNodeSelected * [EC-14] add getters to filter function, fix storybook, and add test for All Collections * [EC-14] Resolve merge conflicts * [EC-14] fix merge conflicts * [EC-14] fix merge conflicts: org service protected and remove absolute path * [EC-14] separate org vault filter service observables * [EC-14] remove folder subject in vault filter service * [EC-14] remove collections subject from vault filter service * [EC-14] change collection api call name - getCollectionsWithDetails to getManyCollectionsWithDetails * [EC-14] add collection functionality - add endpoint to bulk delete collections - add logic to bulk delete both ciphers and collections - refresh ciphers list after making collection changes - stop making api calls from ciphers list each time a filter changes * [EC-14] get collections from vault filter service - for badge, instead of passing through @Input variable * [EC-14] only bulk delete collections if passed * [EC-14] fix deleting ciphers in org vault - reuse same logic from end user vault - call different api endpoints * [EC-14] include collections in MaxCheckedCount * [EC-14] add paging to collections * [EC-14] hide collections if searching * [EC-14] change vault table to new table component - removed a lot of scss classes to use tailwind alternatives - added getters for arrays in component that template can reference - imported and used new bitIconButton for options button * [EC-14] remove cursor pointer when checkbox not available * [EC-14] stop reloading cipher list too early * [EC-14] stop setting cipher component to loaded too early - loaded variable on cipher component hides the loaded indicator - when setting the default filter, we were triggering that variable - instead, we'll just set the active filter and let it grab the filter when ready * [EC-14] check/navigate collection when clicked * [EC-14] rename edit collections callback - used to be onEditCollection - renamed to onEditCipherCollections * [EC-14] remove showOrganizationBadge property - property used to tell template whether it was org vault or end user - replace with check for organization property * [EC-14] replace || with ?? in load function of ciphers * [EC-14] remove nested subscriptions - nested subscriptions = bad - the only dependency any of the subscriptions have is on the organization - use withLatestFrom to verify that the org has been set before firing * [EC-14] add getters and rename method * [EC-14] add null check in bulk delete component - some input variables can be null, so we can't just check the length * [EC-14] add ItemRow type - ItemRow can be either CipherView or CollectionFilter - Consolidated a large portion of selection logic * [EC-14] remove extra applyFilter override - Removed extra applyFIlter, allCiphers has already been filtered by org - Also reordered some of the methods to make more sense * [EC-14] remove extra collections uncheck * [EC-14] transition bulk delete to dialog service * [EC-14] transition bulk restore to dialog service * [EC-14] transition bulk move to dialog service * [EC-14] transition bulk share to dialog service * [EC-14] remove modal references * [EC-14] reload cipher list when changing orgs * [EC-14] add helper method to bulk delete dialog - Gives us built in typing instead of having to redeclare * [EC-14] add helper to open bulk restore dialog - Gives us typing without redeclaring * [EC-14] add open helper to bulk move dialog * [EC-14] add open helper to bulk share dialog - Adds typing to data - also removed the component refs from bulk actions * [EC-14] remove modal service from bulk actions * [EC-14] introduce VaultItemRow to combine cipher and collections * [EC-14] show loading indicator while switching orgs * [EC-14] remove indexing every time filter changes - also reverted back to using setter for changing org * [EC-14] allow searching by function in search pipe - this allows us to search parent properties in objects Co-authored-by: Andreas Coroiu <andreas@andreascoroiu.com> * [EC-14] make collections searchable - used search pipe to filter based on search text * [EC-14] consolidate bulk dialogs in single module * [EC-14] remove form promise from bulk dialogs * [EC-14] stop casting dialog return type - we now have a helper function that gives us typing on result * [EC-14] add length check to array guard * [EC-14] remove extra false assignment * [EC-14] move to sentence case * [EC-14] address pr feedback * [EC-14] add back the default assignment to deleted - we need this default assignment to check for null or undefined values * [EC-14] remove optional chaining - everything is initialized to an empty array so it should never be null * [EC-14] remove manager check to show org vault - this is fixed upstream in a more comprehensive way * [EC-686] add tests and comments to serviceUtils (#4092) * [EC-686] add tests and comments to serviceUtls * [EC-686] whitelist spec filename from linter * [EC-686] fix prettier * [EC-14] use new collection admin service * [EC-14] fix groups searching * [EC-14] use new groups service and models * [EC-14] fix shared module * [EC-14] remove leftover empty vault filter service * [EC-14] remove CollectionGroupDetailsView models * [EC-14] replace GroupDetails with AdminView - Collections in vault filter now use admin view to get access details - Collections shown in cipher list use admin view for access details * [EC-14] add back the dialog to shared module * [EC-14] hide org vault if lacking permissions * [EC-14] add edit collection dialog to vault * [EC-14] add screen reader label to share dialog * [EC-14] moved sync call below subscription - the subscription gives a callback for when we finish a sync - by awaiting the sync before we weren't using the callback to refresh * [EC-14] move cipher params check to switchMap - we want to avoid async subscriptions * [EC-14] clean up subscriptions in org vault - added takeUntil - use combineLatest * [EC-14] clean up vault subscriptions - remove nested subscriptions - use takeUntil * [EC-14] init ciphers component first * [EC-14] fix view vault tab permissions - CanViewAssignedCollections doesn't include CanViewAllCollections - CanViewAssignedCollections does include IsManager * [EC-14] reduce nesting * [EC-14] rename bulk action dialogs selectors * [EC-14] fix permissions for collection management - users with custom admin permissions should be able to edit as well * [EC-14] prettier * [EC-14] use percentages for table columns widths * [EC-14] use GetCollectionAccessDetails in cli - renamed api call Signed-off-by: Jacob Fink <jfink@bitwarden.com> Co-authored-by: Thomas Rittson <31796059+eliykat@users.noreply.github.com> Co-authored-by: Thomas Rittson <eliykat@users.noreply.github.com> Co-authored-by: Andreas Coroiu <andreas@andreascoroiu.com>
306 lines
12 KiB
HTML
306 lines
12 KiB
HTML
<ng-container>
|
|
<bit-table
|
|
*ngIf="filteredCiphers.length || filteredCollections.length"
|
|
infiniteScroll
|
|
[infiniteScrollDistance]="1"
|
|
[infiniteScrollDisabled]="!isPaging()"
|
|
(scrolled)="loadMore()"
|
|
>
|
|
<ng-container header>
|
|
<tr>
|
|
<th bitCell class="tw-min-w-fit" colspan="2">
|
|
<input
|
|
class="tw-mr-2"
|
|
type="checkbox"
|
|
id="checkAll"
|
|
(change)="checkAll($any($event.target).checked)"
|
|
[(ngModel)]="isAllChecked"
|
|
/>
|
|
<label class="tw-mb-0 !tw-font-bold !tw-text-muted" for="checkAll">{{
|
|
"all" | i18n
|
|
}}</label>
|
|
</th>
|
|
<th bitCell class="tw-w-1/2">{{ "name" | i18n }}</th>
|
|
<th bitCell class="tw-w-1/2">
|
|
<ng-container *ngIf="!organization">{{ "owner" | i18n }}</ng-container>
|
|
<ng-container *ngIf="organization">
|
|
{{ (activeFilter.selectedCollectionNode ? "groups" : "collections") | i18n }}
|
|
</ng-container>
|
|
</th>
|
|
<th bitCell class="tw-min-w-fit">
|
|
<button
|
|
[bitMenuTriggerFor]="headerMenu"
|
|
bitIconButton="bwi-ellipsis-v"
|
|
size="small"
|
|
type="button"
|
|
appA11yTitle="{{ 'options' | i18n }}"
|
|
></button>
|
|
<bit-menu #headerMenu>
|
|
<ng-container>
|
|
<button
|
|
class="dropdown-item"
|
|
appStopClick
|
|
(click)="bulkMove()"
|
|
*ngIf="!activeFilter.isDeleted && !organization"
|
|
>
|
|
<i class="bwi bwi-fw bwi-folder" aria-hidden="true"></i>
|
|
{{ "moveSelected" | i18n }}
|
|
</button>
|
|
<button
|
|
class="dropdown-item"
|
|
appStopClick
|
|
(click)="bulkShare()"
|
|
*ngIf="!activeFilter.isDeleted && !organization"
|
|
>
|
|
<i class="bwi bwi-fw bwi-arrow-circle-right" aria-hidden="true"></i>
|
|
{{ "moveSelectedToOrg" | i18n }}
|
|
</button>
|
|
<button class="dropdown-item" (click)="bulkRestore()" *ngIf="activeFilter.isDeleted">
|
|
<i class="bwi bwi-fw bwi-undo" aria-hidden="true"></i>
|
|
{{ "restoreSelected" | i18n }}
|
|
</button>
|
|
<button class="dropdown-item text-danger" (click)="bulkDelete()">
|
|
<i class="bwi bwi-fw bwi-trash" aria-hidden="true"></i>
|
|
{{
|
|
(activeFilter.isDeleted ? "permanentlyDeleteSelected" : "deleteSelected") | i18n
|
|
}}
|
|
</button>
|
|
</ng-container>
|
|
</bit-menu>
|
|
</th>
|
|
</tr>
|
|
</ng-container>
|
|
<ng-container body>
|
|
<tr bitRow *ngFor="let col of filteredCollections">
|
|
<td bitCell (click)="selectRow(col)">
|
|
<input
|
|
*ngIf="organization && col.node.id !== null"
|
|
class="tw-cursor-pointer"
|
|
type="checkbox"
|
|
[(ngModel)]="$any(col).checked"
|
|
appStopProp
|
|
/>
|
|
</td>
|
|
<td bitCell (click)="selectRow(col)">
|
|
<div class="icon" aria-hidden="true">
|
|
<i class="bwi bwi-fw bwi-lg bwi-collection"></i>
|
|
</div>
|
|
</td>
|
|
<td bitCell class="tw-font-bold" (click)="selectRow(col)">
|
|
<button bitLink linkType="secondary" (click)="navigateCollection(col)">
|
|
{{ col.node.name }}
|
|
</button>
|
|
</td>
|
|
<td bitCell (click)="selectRow(col)">
|
|
<ng-container *ngIf="!organization">
|
|
<app-org-badge
|
|
organizationName="{{ col.node.organizationId | orgNameFromId: organizations }}"
|
|
[profileName]="profileName"
|
|
(onOrganizationClicked)="onOrganizationClicked(col.node.organizationId)"
|
|
>
|
|
</app-org-badge>
|
|
</ng-container>
|
|
<ng-container *ngIf="organization && activeFilter.selectedCollectionNode">
|
|
<app-group-badge
|
|
*ngIf="col.node.groups"
|
|
[selectedGroups]="col.node.groups"
|
|
[allGroups]="groups"
|
|
></app-group-badge>
|
|
</ng-container>
|
|
</td>
|
|
<td bitCell>
|
|
<button
|
|
*ngIf="organization && col.node.id !== null"
|
|
[bitMenuTriggerFor]="collectionOptions"
|
|
size="small"
|
|
bitIconButton="bwi-ellipsis-v"
|
|
type="button"
|
|
appA11yTitle="{{ 'options' | i18n }}"
|
|
></button>
|
|
<bit-menu #collectionOptions>
|
|
<button
|
|
*ngIf="organization?.canEditAssignedCollections || organization?.canEditAnyCollection"
|
|
bitMenuItem
|
|
(click)="editCollection(col.node, 'info')"
|
|
>
|
|
<i class="bwi bwi-fw bwi-pencil-square" aria-hidden="true"></i>
|
|
{{ "editInfo" | i18n }}
|
|
</button>
|
|
<button
|
|
*ngIf="organization?.canEditAssignedCollections || organization?.canEditAnyCollection"
|
|
bitMenuItem
|
|
(click)="editCollection(col.node, 'access')"
|
|
>
|
|
<i class="bwi bwi-fw bwi-users" aria-hidden="true"></i>
|
|
{{ "access" | i18n }}
|
|
</button>
|
|
<button
|
|
*ngIf="
|
|
organization?.canDeleteAssignedCollections || organization?.canDeleteAnyCollection
|
|
"
|
|
bitMenuItem
|
|
(click)="deleteCollection(col.node)"
|
|
>
|
|
<span class="tw-text-danger">
|
|
<i class="bwi bwi-fw bwi-trash" aria-hidden="true"></i>
|
|
{{ "delete" | i18n }}
|
|
</span>
|
|
</button>
|
|
</bit-menu>
|
|
</td>
|
|
</tr>
|
|
<tr bitRow *ngFor="let c of filteredCiphers">
|
|
<td bitCell (click)="selectRow(c)">
|
|
<input type="checkbox" [(ngModel)]="$any(c).checked" appStopProp />
|
|
</td>
|
|
<td bitCell (click)="selectRow(c)">
|
|
<app-vault-icon [cipher]="c"></app-vault-icon>
|
|
</td>
|
|
<td bitCell (click)="selectRow(c)">
|
|
<a
|
|
appStopProp
|
|
[routerLink]="[]"
|
|
[queryParams]="{ itemId: c.id }"
|
|
queryParamsHandling="merge"
|
|
title="{{ 'editItem' | i18n }}"
|
|
>{{ c.name }}</a
|
|
>
|
|
<ng-container *ngIf="c.hasAttachments">
|
|
<i
|
|
class="bwi bwi-paperclip"
|
|
appStopProp
|
|
title="{{ 'attachments' | i18n }}"
|
|
aria-hidden="true"
|
|
></i>
|
|
<span class="sr-only">{{ "attachments" | i18n }}</span>
|
|
<ng-container *ngIf="showFixOldAttachments(c)">
|
|
<i
|
|
class="bwi bwi-exclamation-triangle text-warning"
|
|
appStopProp
|
|
title="{{ 'attachmentsNeedFix' | i18n }}"
|
|
aria-hidden="true"
|
|
></i>
|
|
<span class="sr-only">{{ "attachmentsNeedFix" | i18n }}</span>
|
|
</ng-container>
|
|
</ng-container>
|
|
<br />
|
|
<small appStopProp>{{ c.subTitle }}</small>
|
|
</td>
|
|
<td bitCell>
|
|
<ng-container *ngIf="!organization">
|
|
<app-org-badge
|
|
organizationName="{{ c.organizationId | orgNameFromId: organizations }}"
|
|
profileName="{{ profileName }}"
|
|
(onOrganizationClicked)="onOrganizationClicked(c.organizationId)"
|
|
>
|
|
</app-org-badge>
|
|
</ng-container>
|
|
<ng-container *ngIf="organization && !activeFilter.selectedCollectionNode">
|
|
<app-collection-badge
|
|
*ngIf="c.collectionIds"
|
|
[collectionIds]="c.collectionIds"
|
|
[collections]="vaultFilterService.filteredCollections$ | async"
|
|
></app-collection-badge>
|
|
</ng-container>
|
|
</td>
|
|
<td bitCell>
|
|
<button
|
|
[bitMenuTriggerFor]="cipherOptions"
|
|
size="small"
|
|
bitIconButton="bwi-ellipsis-v"
|
|
type="button"
|
|
appA11yTitle="{{ 'options' | i18n }}"
|
|
></button>
|
|
<bit-menu #cipherOptions>
|
|
<ng-container *ngIf="c.type === cipherType.Login && !c.isDeleted">
|
|
<button bitMenuItem (click)="copy(c, c.login.username, 'username', 'Username')">
|
|
<i class="bwi bwi-fw bwi-clone" aria-hidden="true"></i>
|
|
{{ "copyUsername" | i18n }}
|
|
</button>
|
|
<button
|
|
bitMenuItem
|
|
(click)="copy(c, c.login.password, 'password', 'Password')"
|
|
*ngIf="c.viewPassword"
|
|
>
|
|
<i class="bwi bwi-fw bwi-clone" aria-hidden="true"></i>
|
|
{{ "copyPassword" | i18n }}
|
|
</button>
|
|
<button
|
|
bitMenuItem
|
|
(click)="copy(c, c.login.totp, 'verificationCodeTotp', 'TOTP')"
|
|
*ngIf="displayTotpCopyButton(c)"
|
|
>
|
|
<i class="bwi bwi-fw bwi-clone" aria-hidden="true"></i>
|
|
{{ "copyVerificationCode" | i18n }}
|
|
</button>
|
|
<button bitMenuItem *ngIf="c.login.canLaunch" (click)="launch(c.login.launchUri)">
|
|
<i class="bwi bwi-fw bwi-share-square" aria-hidden="true"></i>
|
|
{{ "launch" | i18n }}
|
|
</button>
|
|
</ng-container>
|
|
<button bitMenuItem (click)="attachments(c)">
|
|
<i class="bwi bwi-fw bwi-paperclip" aria-hidden="true"></i>
|
|
{{ "attachments" | i18n }}
|
|
</button>
|
|
<button
|
|
bitMenuItem
|
|
*ngIf="((!organization && !c.organizationId) || organization) && !c.isDeleted"
|
|
(click)="clone(c)"
|
|
>
|
|
<i class="bwi bwi-fw bwi-files" aria-hidden="true"></i>
|
|
{{ "clone" | i18n }}
|
|
</button>
|
|
<button
|
|
bitMenuItem
|
|
*ngIf="!organization && !c.organizationId && !c.isDeleted"
|
|
(click)="share(c)"
|
|
>
|
|
<i class="bwi bwi-fw bwi-arrow-circle-right" aria-hidden="true"></i>
|
|
{{ "moveToOrganization" | i18n }}
|
|
</button>
|
|
<button
|
|
bitMenuItem
|
|
*ngIf="c.organizationId && !c.isDeleted"
|
|
(click)="editCipherCollections(c)"
|
|
>
|
|
<i class="bwi bwi-fw bwi-collection" aria-hidden="true"></i>
|
|
{{ "collections" | i18n }}
|
|
</button>
|
|
<button bitMenuItem *ngIf="c.organizationId && accessEvents" (click)="events(c)">
|
|
<i class="bwi bwi-fw bwi-file-text" aria-hidden="true"></i>
|
|
{{ "eventLogs" | i18n }}
|
|
</button>
|
|
<button bitMenuItem (click)="restore(c)" *ngIf="c.isDeleted">
|
|
<i class="bwi bwi-fw bwi-undo" aria-hidden="true"></i>
|
|
{{ "restore" | i18n }}
|
|
</button>
|
|
<button bitMenuItem (click)="deleteCipher(c)">
|
|
<span class="tw-text-danger">
|
|
<i class="bwi bwi-fw bwi-trash" aria-hidden="true"></i>
|
|
{{ (c.isDeleted ? "permanentlyDelete" : "delete") | i18n }}
|
|
</span>
|
|
</button>
|
|
</bit-menu>
|
|
</td>
|
|
</tr>
|
|
</ng-container>
|
|
</bit-table>
|
|
<div class="no-items" *ngIf="!filteredCiphers.length && !filteredCollections.length">
|
|
<ng-container *ngIf="!loaded">
|
|
<i
|
|
class="bwi bwi-spinner bwi-spin text-muted"
|
|
title="{{ 'loading' | i18n }}"
|
|
aria-hidden="true"
|
|
></i>
|
|
<span class="sr-only">{{ "loading" | i18n }}</span>
|
|
</ng-container>
|
|
<ng-container *ngIf="loaded">
|
|
<bit-icon [icon]="noItemIcon" aria-hidden="true"></bit-icon>
|
|
<p>{{ "noItemsInList" | i18n }}</p>
|
|
<button (click)="addCipher()" class="btn btn-outline-primary" *ngIf="showAddNew">
|
|
<i class="bwi bwi-plus bwi-fw"></i>{{ "addItem" | i18n }}
|
|
</button>
|
|
</ng-container>
|
|
</div>
|
|
</ng-container>
|