diff --git a/libs/angular/src/vault/components/vault-items.component.ts b/libs/angular/src/vault/components/vault-items.component.ts index 783a643d44b..89b01a7f2d7 100644 --- a/libs/angular/src/vault/components/vault-items.component.ts +++ b/libs/angular/src/vault/components/vault-items.component.ts @@ -2,17 +2,31 @@ // @ts-strict-ignore import { Directive, EventEmitter, Input, OnDestroy, OnInit, Output } from "@angular/core"; import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; -import { BehaviorSubject, Observable, Subject, firstValueFrom, map } from "rxjs"; +import { + BehaviorSubject, + Observable, + Subject, + combineLatest, + firstValueFrom, + map, + of, + switchMap, +} from "rxjs"; import { SearchService } from "@bitwarden/common/abstractions/search.service"; +import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; import { Organization } from "@bitwarden/common/admin-console/models/domain/organization"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { getUserId } from "@bitwarden/common/auth/services/account.service"; import { UserId } from "@bitwarden/common/types/guid"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; +import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; import { FilterService } from "@bitwarden/common/vault/search/filter.service"; -import { ProcessInstructions } from "@bitwarden/common/vault/search/query.types"; +import { ParseResult } from "@bitwarden/common/vault/search/query.types"; + +// eslint-disable-next-line no-restricted-imports -- TODO: this needs to go +import { CollectionService } from "../../../../admin-console/src/common/collections"; @Directive() export class VaultItemsComponent implements OnInit, OnDestroy { @@ -34,7 +48,7 @@ export class VaultItemsComponent implements OnInit, OnDestroy { private destroy$ = new Subject(); private searchTimeout: any = null; private isSearchable: boolean = false; - private processInstructions$: Observable; + private parsedFilter$: Observable; private _searchText$ = new BehaviorSubject(""); get searchText() { return this._searchText$.value; @@ -47,16 +61,18 @@ export class VaultItemsComponent implements OnInit, OnDestroy { protected filterService: FilterService, protected searchService: SearchService, protected cipherService: CipherService, + protected folderService: FolderService, + protected organizationService: OrganizationService, + protected collectionService: CollectionService, protected accountService: AccountService, ) {} async ngOnInit() { this.userId = await firstValueFrom(getUserId(this.accountService.activeAccount$)); - const parsed$ = this.filterService.parse(this._searchText$).pipe(takeUntilDestroyed()); + const parsedFilter$ = this.filterService.parse(this._searchText$).pipe(takeUntilDestroyed()); - this.processInstructions$ = parsed$.pipe(map((p) => p.processInstructions)); - parsed$.subscribe(({ isError }) => { + parsedFilter$.subscribe(({ isError }) => { this.isSearchable = !isError; }); } @@ -138,6 +154,33 @@ export class VaultItemsComponent implements OnInit, OnDestroy { indexedCiphers = [...failedCiphers, ...indexedCiphers]; } - this.ciphers = await firstValueFrom(this.filterService.filter(this.processInstructions$)); + const context$ = this.accountService.activeAccount$.pipe( + switchMap((account) => { + return this.filterService.context$({ + ciphers: this.cipherService.cipherViews$(account.id), + folders: this.folderService.folderViews$(account.id), + collections: this.collectionService.decryptedCollections$, + organizations: this.organizationService.organizations$(account.id), + }); + }), + ); + + const ciphers$ = combineLatest([this.parsedFilter$, context$]).pipe( + switchMap(([parsedFilter, context]) => { + return this.filterService.filter(of([parsedFilter, context])); + }), + // this.filterService.filter, + switchMap((result) => { + if (result.isError) { + // return all ciphers + return context$.pipe(map((c) => c.ciphers)); + } else { + // return filtered ciphers + return of(result.ciphers); + } + }), + ); + + this.ciphers = await firstValueFrom(ciphers$); } }