From 794a57bfea4433446cd05f6e36eba1ce299c95d2 Mon Sep 17 00:00:00 2001 From: Nick Krantz <125900171+nick-livefront@users.noreply.github.com> Date: Mon, 12 Jan 2026 10:07:38 -0600 Subject: [PATCH] do not show archive option in bulk menu for collections (#18267) --- .../vault-items/vault-items.component.spec.ts | 95 +++++++++++++++++++ .../vault-items/vault-items.component.ts | 3 +- 2 files changed, 97 insertions(+), 1 deletion(-) diff --git a/apps/web/src/app/vault/components/vault-items/vault-items.component.spec.ts b/apps/web/src/app/vault/components/vault-items/vault-items.component.spec.ts index c1c25c625da..5c2ca089ddb 100644 --- a/apps/web/src/app/vault/components/vault-items/vault-items.component.spec.ts +++ b/apps/web/src/app/vault/components/vault-items/vault-items.component.spec.ts @@ -79,6 +79,101 @@ describe("VaultItemsComponent", () => { component = fixture.componentInstance; }); + describe("bulkArchiveAllowed", () => { + it("returns false when no items are selected", () => { + component.userCanArchive = true; + component["selection"].clear(); + + expect(component.bulkArchiveAllowed).toBe(false); + }); + + it("returns false when userCanArchive is false", () => { + component.userCanArchive = false; + + const items: VaultItem[] = [ + { cipher: cipher1 as CipherView }, + { cipher: cipher2 as CipherView }, + ]; + + component["selection"].select(...items); + + expect(component.bulkArchiveAllowed).toBe(false); + }); + + it("returns false when selecting collections", () => { + component.userCanArchive = true; + const collection1 = { id: "col-1", name: "Collection 1" } as CollectionView; + + const items: VaultItem[] = [ + { cipher: cipher1 as CipherView }, + { collection: collection1 }, + ]; + + component["selection"].select(...items); + + expect(component.bulkArchiveAllowed).toBe(false); + }); + + it("returns true when selecting unarchived ciphers without organization", () => { + component.userCanArchive = true; + + const items: VaultItem[] = [ + { cipher: cipher1 as CipherView }, + { cipher: cipher2 as CipherView }, + ]; + + component["selection"].select(...items); + + expect(component.bulkArchiveAllowed).toBe(true); + }); + + it("returns false when any selected cipher has an organizationId", () => { + component.userCanArchive = true; + + const personalCipher: Partial = { + ...cipher1, + organizationId: undefined, + }; + + const orgCipher: Partial = { + ...cipher2, + organizationId: "org-1", + }; + + const items: VaultItem[] = [ + { cipher: personalCipher as CipherView }, + { cipher: orgCipher as CipherView }, + ]; + + component["selection"].select(...items); + + expect(component.bulkArchiveAllowed).toBe(false); + }); + + it("returns false when any selected cipher is already archived", () => { + component.userCanArchive = true; + + const unarchivedCipher: Partial = { + ...cipher1, + archivedDate: undefined, + }; + + const archivedCipher: Partial = { + ...cipher2, + archivedDate: new Date("2024-01-01"), + }; + + const items: VaultItem[] = [ + { cipher: unarchivedCipher as CipherView }, + { cipher: archivedCipher as CipherView }, + ]; + + component["selection"].select(...items); + + expect(component.bulkArchiveAllowed).toBe(false); + }); + }); + describe("bulkUnarchiveAllowed", () => { it("returns false when no items are selected", () => { component["selection"].clear(); diff --git a/apps/web/src/app/vault/components/vault-items/vault-items.component.ts b/apps/web/src/app/vault/components/vault-items/vault-items.component.ts index a51009a1e5b..5e7eb6a0c05 100644 --- a/apps/web/src/app/vault/components/vault-items/vault-items.component.ts +++ b/apps/web/src/app/vault/components/vault-items/vault-items.component.ts @@ -272,7 +272,8 @@ export class VaultItemsComponent { } get bulkArchiveAllowed() { - if (this.selection.selected.length === 0 || !this.userCanArchive) { + const hasCollectionsSelected = this.selection.selected.some((item) => item.collection); + if (this.selection.selected.length === 0 || !this.userCanArchive || hasCollectionsSelected) { return false; }