1
0
mirror of https://github.com/bitwarden/browser.git synced 2024-11-25 12:15:18 +01:00

[AC-1120] Implement 'New' button dropdown in Individual Vault (#5235)

* Change 'New' button to dropdown with folders and collections

* Individual vault changes to support adding collections

* Add org selector to CollectionDialogComponent

* Implement CollectionService.upsert() in CollectionAdminService.save()

* Filter collections to ones that users can create collections in

* Filter organizations by ones the user can create a collection in

* CollectionDialog observable updates

* Remove CollectionService.upsert from CollectionAdminService and return collection on save from CollectionDialog.

* Filter out collections that the user does not have access to in collection dialog for Individual Vault.

* Remove add folder action from vault filter

* Remove add button from filters as it is no longer used

* Update comment to reference future ticket

* Change CollectionDialogResult from a class to an interface

* Remove extra call to loadOrg() in the case of opening the modal from the individual vault

* Use async pipe instead of subscribe for organizations
This commit is contained in:
Robyn MacCallum 2023-06-27 11:36:48 -04:00 committed by GitHub
parent 09ef9dd411
commit 683b7fea77
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 174 additions and 57 deletions

View File

@ -22,6 +22,19 @@
<input bitInput appAutofocus formControlName="name" /> <input bitInput appAutofocus formControlName="name" />
</bit-form-field> </bit-form-field>
<bit-form-field *ngIf="showOrgSelector">
<bit-label>{{ "organization" | i18n }}</bit-label>
<bit-select bitInput formControlName="selectedOrg">
<bit-option
*ngFor="let org of organizations$ | async"
icon="bwi-business"
[value]="org.id"
[label]="org.name"
>
</bit-option>
</bit-select>
</bit-form-field>
<bit-form-field> <bit-form-field>
<bit-label>{{ "externalId" | i18n }}</bit-label> <bit-label>{{ "externalId" | i18n }}</bit-label>
<input bitInput formControlName="externalId" /> <input bitInput formControlName="externalId" />

View File

@ -1,7 +1,16 @@
import { DIALOG_DATA, DialogConfig, DialogRef } from "@angular/cdk/dialog"; import { DIALOG_DATA, DialogConfig, DialogRef } from "@angular/cdk/dialog";
import { Component, Inject, OnDestroy, OnInit } from "@angular/core"; import { Component, Inject, OnDestroy, OnInit } from "@angular/core";
import { FormBuilder, Validators } from "@angular/forms"; import { FormBuilder, Validators } from "@angular/forms";
import { combineLatest, of, shareReplay, Subject, switchMap, takeUntil } from "rxjs"; import {
combineLatest,
map,
Observable,
of,
shareReplay,
Subject,
switchMap,
takeUntil,
} from "rxjs";
import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog"; import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog";
import { OrganizationUserService } from "@bitwarden/common/abstractions/organization-user/organization-user.service"; import { OrganizationUserService } from "@bitwarden/common/abstractions/organization-user/organization-user.service";
@ -10,6 +19,8 @@ import { OrganizationService } from "@bitwarden/common/admin-console/abstraction
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization"; 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 { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { Utils } from "@bitwarden/common/platform/misc/utils";
import { CollectionResponse } from "@bitwarden/common/vault/models/response/collection.response";
import { CollectionView } from "@bitwarden/common/vault/models/view/collection.view"; import { CollectionView } from "@bitwarden/common/vault/models/view/collection.view";
import { BitValidators } from "@bitwarden/components"; import { BitValidators } from "@bitwarden/components";
@ -35,9 +46,16 @@ export interface CollectionDialogParams {
organizationId: string; organizationId: string;
initialTab?: CollectionDialogTabType; initialTab?: CollectionDialogTabType;
parentCollectionId?: string; parentCollectionId?: string;
showOrgSelector?: boolean;
collectionIds?: string[];
} }
export enum CollectionDialogResult { export interface CollectionDialogResult {
action: CollectionDialogAction;
collection: CollectionResponse;
}
export enum CollectionDialogAction {
Saved = "saved", Saved = "saved",
Canceled = "canceled", Canceled = "canceled",
Deleted = "deleted", Deleted = "deleted",
@ -48,6 +66,7 @@ export enum CollectionDialogResult {
}) })
export class CollectionDialogComponent implements OnInit, OnDestroy { export class CollectionDialogComponent implements OnInit, OnDestroy {
private destroy$ = new Subject<void>(); private destroy$ = new Subject<void>();
protected organizations$: Observable<Organization[]>;
protected tabIndex: CollectionDialogTabType; protected tabIndex: CollectionDialogTabType;
protected loading = true; protected loading = true;
@ -56,11 +75,13 @@ export class CollectionDialogComponent implements OnInit, OnDestroy {
protected nestOptions: CollectionView[] = []; protected nestOptions: CollectionView[] = [];
protected accessItems: AccessItemView[] = []; protected accessItems: AccessItemView[] = [];
protected deletedParentName: string | undefined; protected deletedParentName: string | undefined;
protected showOrgSelector = false;
protected formGroup = this.formBuilder.group({ protected formGroup = this.formBuilder.group({
name: ["", [Validators.required, BitValidators.forbiddenCharacters(["/"])]], name: ["", [Validators.required, BitValidators.forbiddenCharacters(["/"])]],
externalId: "", externalId: "",
parent: undefined as string | undefined, parent: undefined as string | undefined,
access: [[] as AccessItemValue[]], access: [[] as AccessItemValue[]],
selectedOrg: "",
}); });
protected PermissionMode = PermissionMode; protected PermissionMode = PermissionMode;
@ -79,8 +100,31 @@ export class CollectionDialogComponent implements OnInit, OnDestroy {
this.tabIndex = params.initialTab ?? CollectionDialogTabType.Info; this.tabIndex = params.initialTab ?? CollectionDialogTabType.Info;
} }
ngOnInit() { async ngOnInit() {
const organization$ = of(this.organizationService.get(this.params.organizationId)).pipe( // Opened from the individual vault
if (this.params.showOrgSelector) {
this.showOrgSelector = true;
this.formGroup.controls.selectedOrg.valueChanges
.pipe(takeUntil(this.destroy$))
.subscribe((id) => this.loadOrg(id, this.params.collectionIds));
this.organizations$ = this.organizationService.organizations$.pipe(
map((orgs) =>
orgs
.filter((o) => o.canCreateNewCollections)
.sort(Utils.getSortFunction(this.i18nService, "name"))
)
);
// patchValue will trigger a call to loadOrg() in this case, so no need to call it again here
this.formGroup.patchValue({ selectedOrg: this.params.organizationId });
} else {
// Opened from the org vault
this.formGroup.patchValue({ selectedOrg: this.params.organizationId });
this.loadOrg(this.params.organizationId, this.params.collectionIds);
}
}
async loadOrg(orgId: string, collectionIds: string[]) {
const organization$ = of(this.organizationService.get(orgId)).pipe(
shareReplay({ refCount: true, bufferSize: 1 }) shareReplay({ refCount: true, bufferSize: 1 })
); );
const groups$ = organization$.pipe( const groups$ = organization$.pipe(
@ -89,20 +133,19 @@ export class CollectionDialogComponent implements OnInit, OnDestroy {
return of([] as GroupView[]); return of([] as GroupView[]);
} }
return this.groupService.getAll(this.params.organizationId); return this.groupService.getAll(orgId);
}) })
); );
combineLatest({ combineLatest({
organization: organization$, organization: organization$,
collections: this.collectionService.getAll(this.params.organizationId), collections: this.collectionService.getAll(orgId),
collectionDetails: this.params.collectionId collectionDetails: this.params.collectionId
? this.collectionService.get(this.params.organizationId, this.params.collectionId) ? this.collectionService.get(orgId, this.params.collectionId)
: of(null), : of(null),
groups: groups$, groups: groups$,
users: this.organizationUserService.getAllUsers(this.params.organizationId), users: this.organizationUserService.getAllUsers(orgId),
}) })
.pipe(takeUntil(this.destroy$)) .pipe(takeUntil(this.formGroup.controls.selectedOrg.valueChanges), takeUntil(this.destroy$))
.subscribe(({ organization, collections, collectionDetails, groups, users }) => { .subscribe(({ organization, collections, collectionDetails, groups, users }) => {
this.organization = organization; this.organization = organization;
this.accessItems = [].concat( this.accessItems = [].concat(
@ -110,6 +153,10 @@ export class CollectionDialogComponent implements OnInit, OnDestroy {
users.data.map(mapUserToAccessItemView) users.data.map(mapUserToAccessItemView)
); );
if (collectionIds) {
collections = collections.filter((c) => collectionIds.includes(c.id));
}
if (this.params.collectionId) { if (this.params.collectionId) {
this.collection = collections.find((c) => c.id === this.collectionId); this.collection = collections.find((c) => c.id === this.collectionId);
this.nestOptions = collections.filter((c) => c.id !== this.collectionId); this.nestOptions = collections.filter((c) => c.id !== this.collectionId);
@ -149,7 +196,7 @@ export class CollectionDialogComponent implements OnInit, OnDestroy {
} }
protected async cancel() { protected async cancel() {
this.close(CollectionDialogResult.Canceled); this.close(CollectionDialogAction.Canceled);
} }
protected submit = async () => { protected submit = async () => {
@ -168,7 +215,7 @@ export class CollectionDialogComponent implements OnInit, OnDestroy {
const collectionView = new CollectionAdminView(); const collectionView = new CollectionAdminView();
collectionView.id = this.params.collectionId; collectionView.id = this.params.collectionId;
collectionView.organizationId = this.params.organizationId; collectionView.organizationId = this.formGroup.controls.selectedOrg.value;
collectionView.externalId = this.formGroup.controls.externalId.value; collectionView.externalId = this.formGroup.controls.externalId.value;
collectionView.groups = this.formGroup.controls.access.value collectionView.groups = this.formGroup.controls.access.value
.filter((v) => v.type === AccessItemType.Group) .filter((v) => v.type === AccessItemType.Group)
@ -184,7 +231,7 @@ export class CollectionDialogComponent implements OnInit, OnDestroy {
collectionView.name = this.formGroup.controls.name.value; collectionView.name = this.formGroup.controls.name.value;
} }
await this.collectionService.save(collectionView); const savedCollection = await this.collectionService.save(collectionView);
this.platformUtilsService.showToast( this.platformUtilsService.showToast(
"success", "success",
@ -195,7 +242,7 @@ export class CollectionDialogComponent implements OnInit, OnDestroy {
) )
); );
this.close(CollectionDialogResult.Saved); this.close(CollectionDialogAction.Saved, savedCollection);
}; };
protected delete = async () => { protected delete = async () => {
@ -217,7 +264,7 @@ export class CollectionDialogComponent implements OnInit, OnDestroy {
this.i18nService.t("deletedCollectionId", this.collection?.name) this.i18nService.t("deletedCollectionId", this.collection?.name)
); );
this.close(CollectionDialogResult.Deleted); this.close(CollectionDialogAction.Deleted);
}; };
ngOnDestroy(): void { ngOnDestroy(): void {
@ -225,8 +272,8 @@ export class CollectionDialogComponent implements OnInit, OnDestroy {
this.destroy$.complete(); this.destroy$.complete();
} }
private close(result: CollectionDialogResult) { private close(action: CollectionDialogAction, collection?: CollectionResponse) {
this.dialogRef.close(result); this.dialogRef.close({ action, collection } as CollectionDialogResult);
} }
} }

View File

@ -46,7 +46,7 @@ export class CollectionAdminService {
return view; return view;
} }
async save(collection: CollectionAdminView): Promise<unknown> { async save(collection: CollectionAdminView): Promise<CollectionResponse> {
const request = await this.encrypt(collection); const request = await this.encrypt(collection);
let response: CollectionResponse; let response: CollectionResponse;
@ -61,9 +61,7 @@ export class CollectionAdminService {
); );
} }
// TODO: Implement upsert when in PS-1083: Collection Service refactors return response;
// await this.collectionService.upsert(data);
return;
} }
async delete(organizationId: string, collectionId: string): Promise<void> { async delete(organizationId: string, collectionId: string): Promise<void> {

View File

@ -32,7 +32,6 @@ import { OrganizationOptionsComponent } from "./organization-options.component";
export class VaultFilterComponent implements OnInit, OnDestroy { export class VaultFilterComponent implements OnInit, OnDestroy {
filters?: VaultFilterList; filters?: VaultFilterList;
@Input() activeFilter: VaultFilter = new VaultFilter(); @Input() activeFilter: VaultFilter = new VaultFilter();
@Output() onAddFolder = new EventEmitter<never>();
@Output() onEditFolder = new EventEmitter<FolderFilter>(); @Output() onEditFolder = new EventEmitter<FolderFilter>();
@Input() searchText = ""; @Input() searchText = "";
@ -142,10 +141,6 @@ export class VaultFilterComponent implements OnInit, OnDestroy {
filter.selectedCollectionNode = collectionNode; filter.selectedCollectionNode = collectionNode;
}; };
addFolder = async (): Promise<void> => {
this.onAddFolder.emit();
};
editFolder = async (folder: FolderFilter): Promise<void> => { editFolder = async (folder: FolderFilter): Promise<void> => {
this.onEditFolder.emit(folder); this.onEditFolder.emit(folder);
}; };
@ -249,10 +244,6 @@ export class VaultFilterComponent implements OnInit, OnDestroy {
text: "editFolder", text: "editFolder",
action: this.editFolder, action: this.editFolder,
}, },
add: {
text: "Add Folder",
action: this.addFolder,
},
}; };
return folderFilterSection; return folderFilterSection;
} }

View File

@ -34,16 +34,6 @@
<h3 *ngIf="!headerInfo.isSelectable" class="filter-title"> <h3 *ngIf="!headerInfo.isSelectable" class="filter-title">
&nbsp;{{ headerNode.node.name | i18n }} &nbsp;{{ headerNode.node.name | i18n }}
</h3> </h3>
<button
type="button"
*ngIf="showAddButton"
(click)="onAdd()"
class="text-muted ml-auto add-button"
appA11yTitle="{{ addInfo.text | i18n }}"
>
<i class="bwi bwi-plus bwi-fw" aria-hidden="true"></i>
</button>
</div> </div>
<ul <ul
id="{{ headerNode.node.name }}-filters" id="{{ headerNode.node.name }}-filters"

View File

@ -87,10 +87,6 @@ export class VaultFilterSectionComponent implements OnInit, OnDestroy {
return this.section.add; return this.section.add;
} }
get showAddButton() {
return this.section.add && !this.section.add.route;
}
get showAddLink() { get showAddLink() {
return this.section.add && this.section.add.route; return this.section.add && this.section.add.route;
} }

View File

@ -40,9 +40,31 @@
</div> </div>
<div *ngIf="filter.type !== 'trash'" class="tw-shrink-0"> <div *ngIf="filter.type !== 'trash'" class="tw-shrink-0">
<button type="button" bitButton buttonType="primary" (click)="addCipher()"> <div appListDropdown>
<i class="bwi bwi-plus bwi-fw" aria-hidden="true"></i> <button
{{ "newItem" | i18n }} bitButton
</button> buttonType="primary"
type="button"
[bitMenuTriggerFor]="addOptions"
id="newItemDropdown"
appA11yTitle="{{ 'new' | i18n }}"
>
{{ "new" | i18n }}<i class="bwi bwi-angle-down tw-ml-2" aria-hidden="true"></i>
</button>
<bit-menu #addOptions aria-labelledby="newItemDropdown">
<button type="button" bitMenuItem (click)="addCipher()">
<i class="bwi bwi-fw bwi-globe" aria-hidden="true"></i>
{{ "item" | i18n }}
</button>
<button type="button" bitMenuItem (click)="addFolder()">
<i class="bwi bwi-fw bwi-folder" aria-hidden="true"></i>
{{ "folder" | i18n }}
</button>
<button *ngIf="canCreateCollections" type="button" bitMenuItem (click)="addCollection()">
<i class="bwi bwi-fw bwi-collection" aria-hidden="true"></i>
{{ "collection" | i18n }}
</button>
</bit-menu>
</div>
</div> </div>
</div> </div>

View File

@ -39,11 +39,26 @@ export class VaultHeaderComponent {
*/ */
@Input() collection?: TreeNode<CollectionView>; @Input() collection?: TreeNode<CollectionView>;
/**
* Whether 'Collection' option is shown in the 'New' dropdown
*/
@Input() canCreateCollections: boolean;
/** /**
* Emits an event when the new item button is clicked in the header * Emits an event when the new item button is clicked in the header
*/ */
@Output() onAddCipher = new EventEmitter<void>(); @Output() onAddCipher = new EventEmitter<void>();
/**
* Emits an event when the new collection button is clicked in the 'New' dropdown menu
*/
@Output() onAddCollection = new EventEmitter<null>();
/**
* Emits an event when the new folder button is clicked in the 'New' dropdown menu
*/
@Output() onAddFolder = new EventEmitter<null>();
constructor(private i18nService: I18nService) {} constructor(private i18nService: I18nService) {}
/** /**
@ -115,4 +130,12 @@ export class VaultHeaderComponent {
protected addCipher() { protected addCipher() {
this.onAddCipher.emit(); this.onAddCipher.emit();
} }
async addFolder(): Promise<void> {
this.onAddFolder.emit();
}
async addCollection(): Promise<void> {
this.onAddCollection.emit();
}
} }

View File

@ -9,7 +9,6 @@
[activeFilter]="activeFilter" [activeFilter]="activeFilter"
[searchText]="currentSearchText$ | async" [searchText]="currentSearchText$ | async"
(searchTextChanged)="filterSearchText($event)" (searchTextChanged)="filterSearchText($event)"
(onAddFolder)="addFolder()"
(onEditFolder)="editFolder($event)" (onEditFolder)="editFolder($event)"
></app-vault-filter> ></app-vault-filter>
</div> </div>
@ -21,8 +20,11 @@
[filter]="filter" [filter]="filter"
[loading]="refreshing && !performingInitialLoad" [loading]="refreshing && !performingInitialLoad"
[organizations]="allOrganizations" [organizations]="allOrganizations"
[canCreateCollections]="canCreateCollections"
[collection]="selectedCollection" [collection]="selectedCollection"
(onAddCipher)="addCipher()" (onAddCipher)="addCipher()"
(onAddCollection)="addCollection()"
(onAddFolder)="addFolder()"
></app-vault-header> ></app-vault-header>
<app-callout type="warning" *ngIf="activeFilter.isDeleted" icon="bwi-exclamation-triangle"> <app-callout type="warning" *ngIf="activeFilter.isDeleted" icon="bwi-exclamation-triangle">
{{ trashCleanupWarning }} {{ trashCleanupWarning }}

View File

@ -54,11 +54,14 @@ import { CollectionService } from "@bitwarden/common/vault/abstractions/collecti
import { PasswordRepromptService } from "@bitwarden/common/vault/abstractions/password-reprompt.service"; import { PasswordRepromptService } from "@bitwarden/common/vault/abstractions/password-reprompt.service";
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction"; import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
import { CipherRepromptType } from "@bitwarden/common/vault/enums/cipher-reprompt-type"; import { CipherRepromptType } from "@bitwarden/common/vault/enums/cipher-reprompt-type";
import { CollectionData } from "@bitwarden/common/vault/models/data/collection.data";
import { CollectionDetailsResponse } from "@bitwarden/common/vault/models/response/collection.response";
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
import { CollectionView } from "@bitwarden/common/vault/models/view/collection.view"; import { CollectionView } from "@bitwarden/common/vault/models/view/collection.view";
import { Icons } from "@bitwarden/components"; import { Icons } from "@bitwarden/components";
import { UpdateKeyComponent } from "../../settings/update-key.component"; import { UpdateKeyComponent } from "../../settings/update-key.component";
import { CollectionDialogAction, openCollectionDialog } from "../components/collection-dialog";
import { VaultItemEvent } from "../components/vault-items/vault-item-event"; import { VaultItemEvent } from "../components/vault-items/vault-item-event";
import { getNestedCollectionTree } from "../utils/collection-utils"; import { getNestedCollectionTree } from "../utils/collection-utils";
@ -140,6 +143,7 @@ export class VaultComponent implements OnInit, OnDestroy {
protected collections: CollectionView[]; protected collections: CollectionView[];
protected isEmpty: boolean; protected isEmpty: boolean;
protected selectedCollection: TreeNode<CollectionView> | undefined; protected selectedCollection: TreeNode<CollectionView> | undefined;
protected canCreateCollections = false;
protected currentSearchText$: Observable<string>; protected currentSearchText$: Observable<string>;
private searchText$ = new Subject<string>(); private searchText$ = new Subject<string>();
@ -234,12 +238,9 @@ export class VaultComponent implements OnInit, OnDestroy {
const canAccessPremium$ = Utils.asyncToObservable(() => const canAccessPremium$ = Utils.asyncToObservable(() =>
this.stateService.getCanAccessPremium() this.stateService.getCanAccessPremium()
).pipe(shareReplay({ refCount: true, bufferSize: 1 })); ).pipe(shareReplay({ refCount: true, bufferSize: 1 }));
const allCollections$ = Utils.asyncToObservable(() => const allCollections$ = Utils.asyncToObservable(() => this.collectionService.getAllDecrypted());
this.collectionService.getAllDecrypted()
).pipe(shareReplay({ refCount: true, bufferSize: 1 }));
const nestedCollections$ = allCollections$.pipe( const nestedCollections$ = allCollections$.pipe(
map((collections) => getNestedCollectionTree(collections)), map((collections) => getNestedCollectionTree(collections))
shareReplay({ refCount: true, bufferSize: 1 })
); );
this.searchText$ this.searchText$
@ -384,6 +385,8 @@ export class VaultComponent implements OnInit, OnDestroy {
this.collections = collections; this.collections = collections;
this.selectedCollection = selectedCollection; this.selectedCollection = selectedCollection;
this.canCreateCollections = allOrganizations?.some((o) => o.canCreateNewCollections);
this.showBulkMove = this.showBulkMove =
filter.type !== "trash" && filter.type !== "trash" &&
(filter.organizationId === undefined || filter.organizationId === Unassigned); (filter.organizationId === undefined || filter.organizationId === Unassigned);
@ -639,6 +642,32 @@ export class VaultComponent implements OnInit, OnDestroy {
return childComponent; return childComponent;
} }
async addCollection() {
const dialog = openCollectionDialog(this.dialogService, {
data: {
organizationId: this.allOrganizations
.filter((o) => o.canCreateNewCollections)
.sort(Utils.getSortFunction(this.i18nService, "name"))[0].id,
parentCollectionId: this.filter.collectionId,
showOrgSelector: true,
collectionIds: this.allCollections.map((c) => c.id),
},
});
const result = await lastValueFrom(dialog.closed);
if (result.action === CollectionDialogAction.Saved) {
if (result.collection) {
// Update CollectionService with the new collection
const c = new CollectionData(result.collection as CollectionDetailsResponse);
await this.collectionService.upsert(c);
}
this.refresh();
} else if (result.action === CollectionDialogAction.Deleted) {
// TODO: Remove collection from collectionService when collection
// deletion is implemented in the individual vault in AC-1347
this.refresh();
}
}
async cloneCipher(cipher: CipherView) { async cloneCipher(cipher: CipherView) {
const component = await this.editCipher(cipher); const component = await this.editCipher(cipher);
component.cloneMode = true; component.cloneMode = true;

View File

@ -60,7 +60,7 @@ import { openEntityEventsDialog } from "../../admin-console/organizations/manage
import { VaultFilterService } from "../../vault/individual-vault/vault-filter/services/abstractions/vault-filter.service"; import { VaultFilterService } from "../../vault/individual-vault/vault-filter/services/abstractions/vault-filter.service";
import { VaultFilter } from "../../vault/individual-vault/vault-filter/shared/models/vault-filter.model"; import { VaultFilter } from "../../vault/individual-vault/vault-filter/shared/models/vault-filter.model";
import { import {
CollectionDialogResult, CollectionDialogAction,
CollectionDialogTabType, CollectionDialogTabType,
openCollectionDialog, openCollectionDialog,
} from "../components/collection-dialog"; } from "../components/collection-dialog";
@ -866,7 +866,10 @@ export class VaultComponent implements OnInit, OnDestroy {
}); });
const result = await lastValueFrom(dialog.closed); const result = await lastValueFrom(dialog.closed);
if (result === CollectionDialogResult.Saved || result === CollectionDialogResult.Deleted) { if (
result.action === CollectionDialogAction.Saved ||
result.action === CollectionDialogAction.Deleted
) {
this.refresh(); this.refresh();
} }
} }
@ -877,7 +880,10 @@ export class VaultComponent implements OnInit, OnDestroy {
}); });
const result = await lastValueFrom(dialog.closed); const result = await lastValueFrom(dialog.closed);
if (result === CollectionDialogResult.Saved || result === CollectionDialogResult.Deleted) { if (
result.action === CollectionDialogAction.Saved ||
result.action === CollectionDialogAction.Deleted
) {
this.refresh(); this.refresh();
} }
} }