1
0
mirror of https://github.com/bitwarden/browser.git synced 2024-12-01 13:13:36 +01:00

AC-1965 collections navigation highlight (#7574)

* keep collections in filters highlighted when featureflag is on and user navigates to a specific collection
* apply flexible collections logic to the bitcrumbs and filters in org view
This commit is contained in:
Jason Ng 2024-01-22 15:01:15 -05:00 committed by GitHub
parent 0127db44a0
commit fd2947c6b3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 47 additions and 10 deletions

View File

@ -24,6 +24,7 @@ export abstract class VaultFilterService {
getCollectionNodeFromTree: (id: string) => Promise<TreeNode<CollectionFilter>>; getCollectionNodeFromTree: (id: string) => Promise<TreeNode<CollectionFilter>>;
setCollapsedFilterNodes: (collapsedFilterNodes: Set<string>) => Promise<void>; setCollapsedFilterNodes: (collapsedFilterNodes: Set<string>) => Promise<void>;
expandOrgFilter: () => Promise<void>; expandOrgFilter: () => Promise<void>;
getOrganizationFilter: () => Observable<Organization>;
setOrganizationFilter: (organization: Organization) => void; setOrganizationFilter: (organization: Organization) => void;
buildTypeTree: ( buildTypeTree: (
head: CipherTypeFilter, head: CipherTypeFilter,

View File

@ -144,6 +144,13 @@ describe("vault filter service", () => {
createFolderView("folder test id", "test"), createFolderView("folder test id", "test"),
]); ]);
}); });
it("returns current organization", () => {
vaultFilterService.getOrganizationFilter().subscribe((org) => {
expect(org.id).toEqual("org test id");
expect(org.identifier).toEqual("Test Org");
});
});
}); });
describe("folder tree", () => { describe("folder tree", () => {

View File

@ -106,6 +106,10 @@ export class VaultFilterService implements VaultFilterServiceAbstraction {
return nodes; return nodes;
} }
getOrganizationFilter() {
return this._organizationFilter;
}
setOrganizationFilter(organization: Organization) { setOrganizationFilter(organization: Organization) {
if (organization?.id != "AllVaults") { if (organization?.id != "AllVaults") {
this._organizationFilter.next(organization); this._organizationFilter.next(organization);

View File

@ -15,6 +15,7 @@ import { VaultFilter } from "../models/vault-filter.model";
}) })
export class VaultFilterSectionComponent implements OnInit, OnDestroy { export class VaultFilterSectionComponent implements OnInit, OnDestroy {
private destroy$ = new Subject<void>(); private destroy$ = new Subject<void>();
protected flexibleCollectionsEnabled: boolean;
@Input() activeFilter: VaultFilter; @Input() activeFilter: VaultFilter;
@Input() section: VaultFilterSection; @Input() section: VaultFilterSection;
@ -35,10 +36,16 @@ export class VaultFilterSectionComponent implements OnInit, OnDestroy {
}); });
} }
ngOnInit() { async ngOnInit() {
this.section?.data$?.pipe(takeUntil(this.destroy$)).subscribe((data) => { this.section?.data$?.pipe(takeUntil(this.destroy$)).subscribe((data) => {
this.data = data; this.data = data;
}); });
this.vaultFilterService
.getOrganizationFilter()
.pipe(takeUntil(this.destroy$))
.subscribe((org) => {
this.flexibleCollectionsEnabled = org != null ? org.flexibleCollections : false;
});
} }
ngOnDestroy() { ngOnDestroy() {
@ -67,11 +74,19 @@ export class VaultFilterSectionComponent implements OnInit, OnDestroy {
} }
isNodeSelected(filterNode: TreeNode<VaultFilterType>) { isNodeSelected(filterNode: TreeNode<VaultFilterType>) {
const { organizationId, cipherTypeId, folderId, collectionId, isCollectionSelected } =
this.activeFilter;
const collectionStatus = this.flexibleCollectionsEnabled
? filterNode?.node.id === "AllCollections" &&
(isCollectionSelected || collectionId === "AllCollections")
: collectionId === filterNode?.node.id;
return ( return (
this.activeFilter.organizationId === filterNode?.node.id || organizationId === filterNode?.node.id ||
this.activeFilter.cipherTypeId === filterNode?.node.id || cipherTypeId === filterNode?.node.id ||
this.activeFilter.folderId === filterNode?.node.id || folderId === filterNode?.node.id ||
this.activeFilter.collectionId === filterNode?.node.id collectionStatus
); );
} }

View File

@ -1,9 +1,8 @@
import { Component, Input, OnDestroy, OnInit } from "@angular/core"; import { Component, Input, OnDestroy, OnInit, SimpleChanges } from "@angular/core";
import { firstValueFrom, Subject } from "rxjs"; import { firstValueFrom, Subject } from "rxjs";
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction"; import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization"; import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction";
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 { TreeNode } from "@bitwarden/common/vault/models/domain/tree-node"; import { TreeNode } from "@bitwarden/common/vault/models/domain/tree-node";
@ -36,7 +35,6 @@ export class VaultFilterComponent extends BaseVaultFilterComponent implements On
protected policyService: PolicyService, protected policyService: PolicyService,
protected i18nService: I18nService, protected i18nService: I18nService,
protected platformUtilsService: PlatformUtilsService, protected platformUtilsService: PlatformUtilsService,
protected configService: ConfigServiceAbstraction,
) { ) {
super(vaultFilterService, policyService, i18nService, platformUtilsService); super(vaultFilterService, policyService, i18nService, platformUtilsService);
} }
@ -51,6 +49,12 @@ export class VaultFilterComponent extends BaseVaultFilterComponent implements On
this.isLoaded = true; this.isLoaded = true;
} }
async ngOnChanges(changes: SimpleChanges) {
if (changes.organization) {
this.filters = await this.buildAllFilters();
}
}
ngOnDestroy() { ngOnDestroy() {
this.destroy$.next(); this.destroy$.next();
this.destroy$.complete(); this.destroy$.complete();
@ -97,7 +101,7 @@ export class VaultFilterComponent extends BaseVaultFilterComponent implements On
async buildAllFilters(): Promise<VaultFilterList> { async buildAllFilters(): Promise<VaultFilterList> {
const builderFilter = {} as VaultFilterList; const builderFilter = {} as VaultFilterList;
builderFilter.typeFilter = await this.addTypeFilter(["favorites"]); builderFilter.typeFilter = await this.addTypeFilter(["favorites"]);
if (this.organization?.flexibleCollections) { if (this._organization?.flexibleCollections) {
builderFilter.collectionFilter = await this.addCollectionFilter(); builderFilter.collectionFilter = await this.addCollectionFilter();
} else { } else {
builderFilter.collectionFilter = await super.addCollectionFilter(); builderFilter.collectionFilter = await super.addCollectionFilter();

View File

@ -6,7 +6,13 @@
[queryParams]="{ organizationId: organization.id, collectionId: null }" [queryParams]="{ organizationId: organization.id, collectionId: null }"
queryParamsHandling="merge" queryParamsHandling="merge"
> >
{{ organization.name }} {{ "vault" | i18n | lowercase }} {{ organization.name }}
<span *ngIf="!organization.flexibleCollections">
{{ "vault" | i18n | lowercase }}
</span>
<span *ngIf="organization.flexibleCollections">
{{ "collections" | i18n | lowercase }}
</span>
</bit-breadcrumb> </bit-breadcrumb>
<ng-container> <ng-container>
<bit-breadcrumb <bit-breadcrumb