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

[PM-12389] Vault Item Dialog Fixes (#11374)

* [PM-12389] Hide delete button when there is no cipher to delete

* [PM-12389] Ensure decrypted collections and folders are available before building cipher form config

* [PM-12389] Hide the delete button when cloning ciphers
This commit is contained in:
Shane Melton 2024-10-07 07:23:00 -07:00 committed by GitHub
parent a4123cb8ba
commit 68f4c2e879
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 29 additions and 6 deletions

View File

@ -65,7 +65,7 @@
> >
{{ "cancel" | i18n }} {{ "cancel" | i18n }}
</button> </button>
<div class="tw-ml-auto"> <div class="tw-ml-auto" *ngIf="showDelete">
<button <button
bitIconButton="bwi-trash" bitIconButton="bwi-trash"
type="button" type="button"
@ -73,6 +73,7 @@
[appA11yTitle]="'delete' | i18n" [appA11yTitle]="'delete' | i18n"
[bitAction]="delete" [bitAction]="delete"
[disabled]="!canDelete" [disabled]="!canDelete"
data-testid="delete-cipher-btn"
></button> ></button>
</div> </div>
</ng-container> </ng-container>

View File

@ -179,6 +179,15 @@ export class VaultItemDialogComponent implements OnInit, OnDestroy {
return this.cipher?.edit ?? false; return this.cipher?.edit ?? false;
} }
protected get showDelete() {
// Don't show the delete button when cloning a cipher
if (this.params.mode == "form" && this.formConfig.mode === "clone") {
return false;
}
// Never show the delete button for new ciphers
return this.cipher != null;
}
protected get showCipherView() { protected get showCipherView() {
return this.cipher != undefined && (this.params.mode === "view" || this.loadingForm); return this.cipher != undefined && (this.params.mode === "view" || this.loadingForm);
} }
@ -332,8 +341,8 @@ export class VaultItemDialogComponent implements OnInit, OnDestroy {
}; };
cancel = async () => { cancel = async () => {
// We're in View mode, or we don't have a cipher, close the dialog. // We're in View mode, we don't have a cipher, or we were cloning, close the dialog.
if (this.params.mode === "view" || this.cipher == null) { if (this.params.mode === "view" || this.cipher == null || this.formConfig.mode === "clone") {
this.dialogRef.close(this._cipherModified ? VaultItemDialogResult.Saved : undefined); this.dialogRef.close(this._cipherModified ? VaultItemDialogResult.Saved : undefined);
return; return;
} }

View File

@ -8,6 +8,7 @@ import { TreeNode } from "../models/domain/tree-node";
import { CollectionView } from "../models/view/collection.view"; import { CollectionView } from "../models/view/collection.view";
export abstract class CollectionService { export abstract class CollectionService {
encryptedCollections$: Observable<Collection[]>;
decryptedCollections$: Observable<CollectionView[]>; decryptedCollections$: Observable<CollectionView[]>;
clearActiveUserCache: () => Promise<void>; clearActiveUserCache: () => Promise<void>;

View File

@ -1,5 +1,5 @@
import { inject, Injectable } from "@angular/core"; import { inject, Injectable } from "@angular/core";
import { combineLatest, firstValueFrom, map } from "rxjs"; import { combineLatest, filter, firstValueFrom, map, switchMap } from "rxjs";
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction"; import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
@ -39,9 +39,21 @@ export class DefaultCipherFormConfigService implements CipherFormConfigService {
await firstValueFrom( await firstValueFrom(
combineLatest([ combineLatest([
this.organizations$, this.organizations$,
this.collectionService.decryptedCollections$, this.collectionService.encryptedCollections$.pipe(
switchMap((c) =>
this.collectionService.decryptedCollections$.pipe(
filter((d) => d.length === c.length), // Ensure all collections have been decrypted
),
),
),
this.allowPersonalOwnership$, this.allowPersonalOwnership$,
this.folderService.folderViews$, this.folderService.folders$.pipe(
switchMap((f) =>
this.folderService.folderViews$.pipe(
filter((d) => d.length - 1 === f.length), // -1 for "No Folder" in folderViews$
),
),
),
this.getCipher(cipherId), this.getCipher(cipherId),
]), ]),
); );