1
0
mirror of https://github.com/bitwarden/browser synced 2026-01-31 00:33:33 +00:00

[BUG FIX]Desktop/Pm 31148/Pm 31149/Unexpected behaviors for Collections and Folders (#18506)

* fixed collections still appearing if all orgs are suspended

* fixed 'No folders' not displaying vault items

* PR followup:
- converted `allOrganizationsDisabled` to computed property
- converted observables to signals
This commit is contained in:
Leslie Xiong
2026-01-23 10:55:41 -05:00
committed by GitHub
parent c2f68e0bf6
commit f57cb83d46
3 changed files with 26 additions and 22 deletions

View File

@@ -6,11 +6,11 @@
<bit-nav-group icon="bwi-vault" [text]="'vault' | i18n" route="new-vault">
<app-organization-filter
[activeFilter]="activeFilter()"
[organizations]="organizations$ | async"
[organizations]="organizations()"
[activeOrganizationDataOwnership]="activeOrganizationDataOwnershipPolicy"
[activeSingleOrganizationPolicy]="activeSingleOrganizationPolicy"
/>
<app-type-filter [activeFilter]="activeFilter()" [cipherTypes]="cipherTypes$ | async" />
<app-type-filter [activeFilter]="activeFilter()" [cipherTypes]="cipherTypes()" />
<app-status-filter [hideArchive]="!showArchiveVaultFilter" [activeFilter]="activeFilter()" />
@if (showCollectionsFilter()) {
<bit-nav-group
@@ -20,7 +20,7 @@
[appA11yTitle]="'collections' | i18n"
[disableToggleOnClick]="true"
>
@for (collection of (collections$ | async)?.children ?? []; track collection.node.id) {
@for (collection of collections()?.children ?? []; track collection.node.id) {
<app-collection-filter [activeFilter]="activeFilter()" [collection]="collection" />
}
</bit-nav-group>
@@ -32,7 +32,7 @@
[appA11yTitle]="'folders' | i18n"
[disableToggleOnClick]="true"
>
@for (folder of (folders$ | async)?.children ?? []; track folder.node.id) {
@for (folder of folders()?.children ?? []; track folder.node.id) {
<app-folder-filter
[activeFilter]="activeFilter()"
[folder]="folder"

View File

@@ -2,7 +2,8 @@
// @ts-strict-ignore
import { CommonModule } from "@angular/common";
import { Component, inject, OnInit, output, computed, signal } from "@angular/core";
import { firstValueFrom, Observable, Subject, takeUntil } from "rxjs";
import { toSignal } from "@angular/core/rxjs-interop";
import { firstValueFrom, Subject, takeUntil } from "rxjs";
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
import { PolicyType } from "@bitwarden/common/admin-console/enums";
@@ -12,13 +13,9 @@ import { UserId } from "@bitwarden/common/types/guid";
import { CipherArchiveService } from "@bitwarden/common/vault/abstractions/cipher-archive.service";
import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
import { PremiumUpgradePromptService } from "@bitwarden/common/vault/abstractions/premium-upgrade-prompt.service";
import { TreeNode } from "@bitwarden/common/vault/models/domain/tree-node";
import { NavigationModule, DialogService, A11yTitleDirective } from "@bitwarden/components";
import { I18nPipe } from "@bitwarden/ui-common";
import {
OrganizationFilter,
CipherTypeFilter,
CollectionFilter,
FolderFilter,
VaultFilter,
VaultFilterServiceAbstraction as VaultFilterService,
@@ -75,13 +72,25 @@ export class VaultFilterComponent implements OnInit {
protected showArchiveVaultFilter = false;
protected activeOrganizationDataOwnershipPolicy: boolean;
protected activeSingleOrganizationPolicy: boolean;
protected organizations$: Observable<TreeNode<OrganizationFilter>>;
protected collections$: Observable<TreeNode<CollectionFilter>>;
protected folders$: Observable<TreeNode<FolderFilter>>;
protected cipherTypes$: Observable<TreeNode<CipherTypeFilter>>;
protected readonly organizations = toSignal(this.vaultFilterService.organizationTree$);
protected readonly collections = toSignal(this.vaultFilterService.collectionTree$);
protected readonly folders = toSignal(this.vaultFilterService.folderTree$);
protected readonly cipherTypes = toSignal(this.vaultFilterService.cipherTypeTree$);
protected readonly showCollectionsFilter = computed<boolean>(() => {
return this.organizations$ != null && !this.activeFilter()?.isMyVaultSelected;
return (
this.organizations() != null &&
!this.activeFilter()?.isMyVaultSelected &&
!this.allOrganizationsDisabled()
);
});
protected readonly allOrganizationsDisabled = computed<boolean>(() => {
if (!this.organizations()) {
return false;
}
const orgs = this.organizations().children.filter((org) => org.node.id !== "MyVault");
return orgs.length > 0 && orgs.every((org) => !org.node.enabled);
});
private async setActivePolicies() {
@@ -98,16 +107,9 @@ export class VaultFilterComponent implements OnInit {
async ngOnInit(): Promise<void> {
this.activeUserId = await firstValueFrom(this.accountService.activeAccount$.pipe(getUserId));
this.organizations$ = this.vaultFilterService.organizationTree$;
if (
this.organizations$ != null &&
(await firstValueFrom(this.organizations$)).children.length > 0
) {
if (this.organizations() != null && this.organizations().children.length > 0) {
await this.setActivePolicies();
}
this.cipherTypes$ = this.vaultFilterService.cipherTypeTree$;
this.folders$ = this.vaultFilterService.folderTree$;
this.collections$ = this.vaultFilterService.collectionTree$;
this.showArchiveVaultFilter = await firstValueFrom(
this.cipherArchiveService.hasArchiveFlagEnabled$,

View File

@@ -805,6 +805,8 @@ export class VaultComponent implements OnInit, OnDestroy, CopyClickListener {
type: CipherViewLikeUtils.getType(cipher),
// Normalize undefined organizationId to null for filter compatibility
organizationId: cipher.organizationId ?? null,
// Normalize empty string folderId to null for filter compatibility
folderId: cipher.folderId ? cipher.folderId : null,
// Explicitly include isDeleted and isArchived since they might be getters
isDeleted: CipherViewLikeUtils.isDeleted(cipher),
isArchived: CipherViewLikeUtils.isArchived(cipher),