mirror of
https://github.com/bitwarden/browser
synced 2025-12-14 15:23:33 +00:00
[PM-8553] browser v2 search bar defects (#9506)
* update no results icon and no results scrolling * update v2 search so the term persist when the user clicks into an item and exits the item
This commit is contained in:
@@ -1,12 +1,14 @@
|
||||
import { CommonModule } from "@angular/common";
|
||||
import { Component, Output, EventEmitter } from "@angular/core";
|
||||
import { Component } from "@angular/core";
|
||||
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
||||
import { FormsModule } from "@angular/forms";
|
||||
import { Subject, debounceTime } from "rxjs";
|
||||
import { Subject, Subscription, debounceTime, filter } from "rxjs";
|
||||
|
||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||
import { SearchModule } from "@bitwarden/components";
|
||||
|
||||
import { VaultPopupItemsService } from "../../../services/vault-popup-items.service";
|
||||
|
||||
const SearchTextDebounceInterval = 200;
|
||||
|
||||
@Component({
|
||||
@@ -17,19 +19,34 @@ const SearchTextDebounceInterval = 200;
|
||||
})
|
||||
export class VaultV2SearchComponent {
|
||||
searchText: string;
|
||||
@Output() searchTextChanged = new EventEmitter<string>();
|
||||
|
||||
private searchText$ = new Subject<string>();
|
||||
|
||||
constructor() {
|
||||
this.searchText$
|
||||
.pipe(debounceTime(SearchTextDebounceInterval), takeUntilDestroyed())
|
||||
.subscribe((data) => {
|
||||
this.searchTextChanged.emit(data);
|
||||
});
|
||||
constructor(private vaultPopupItemsService: VaultPopupItemsService) {
|
||||
this.subscribeToLatestSearchText();
|
||||
this.subscribeToApplyFilter();
|
||||
}
|
||||
|
||||
onSearchTextChanged() {
|
||||
this.searchText$.next(this.searchText);
|
||||
}
|
||||
|
||||
subscribeToLatestSearchText(): Subscription {
|
||||
return this.vaultPopupItemsService.latestSearchText$
|
||||
.pipe(
|
||||
takeUntilDestroyed(),
|
||||
filter((data) => !!data),
|
||||
)
|
||||
.subscribe((text) => {
|
||||
this.searchText = text;
|
||||
});
|
||||
}
|
||||
|
||||
subscribeToApplyFilter(): Subscription {
|
||||
return this.searchText$
|
||||
.pipe(debounceTime(SearchTextDebounceInterval), takeUntilDestroyed())
|
||||
.subscribe((data) => {
|
||||
this.vaultPopupItemsService.applyFilter(data);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,18 +22,15 @@
|
||||
</div>
|
||||
|
||||
<ng-container *ngIf="!(showEmptyState$ | async)">
|
||||
<div class="tw-fixed">
|
||||
<app-vault-v2-search (searchTextChanged)="handleSearchTextChange($event)">
|
||||
</app-vault-v2-search>
|
||||
<app-vault-v2-search> </app-vault-v2-search>
|
||||
|
||||
<app-vault-list-filters></app-vault-list-filters>
|
||||
</div>
|
||||
<app-vault-list-filters></app-vault-list-filters>
|
||||
|
||||
<div
|
||||
*ngIf="(showNoResultsState$ | async) && !(showDeactivatedOrg$ | async)"
|
||||
class="tw-flex tw-flex-col tw-h-full tw-justify-center"
|
||||
class="tw-flex tw-flex-col tw-justify-center tw-h-auto tw-pt-12"
|
||||
>
|
||||
<bit-no-items>
|
||||
<bit-no-items [icon]="noResultsIcon">
|
||||
<ng-container slot="title">{{ "noItemsMatchSearch" | i18n }}</ng-container>
|
||||
<ng-container slot="description">{{ "clearFiltersOrTryAnother" | i18n }}</ng-container>
|
||||
</bit-no-items>
|
||||
@@ -41,7 +38,7 @@
|
||||
|
||||
<div
|
||||
*ngIf="showDeactivatedOrg$ | async"
|
||||
class="tw-flex tw-flex-col tw-h-full tw-justify-center"
|
||||
class="tw-flex tw-flex-col tw-justify-center tw-h-auto tw-pt-12"
|
||||
>
|
||||
<bit-no-items [icon]="deactivatedIcon">
|
||||
<ng-container slot="title">{{ "organizationIsDeactivated" | i18n }}</ng-container>
|
||||
|
||||
@@ -44,6 +44,7 @@ export class VaultV2Component implements OnInit, OnDestroy {
|
||||
|
||||
protected vaultIcon = Icons.Vault;
|
||||
protected deactivatedIcon = Icons.DeactivatedOrg;
|
||||
protected noResultsIcon = Icons.NoResults;
|
||||
|
||||
constructor(
|
||||
private vaultPopupItemsService: VaultPopupItemsService,
|
||||
@@ -54,10 +55,6 @@ export class VaultV2Component implements OnInit, OnDestroy {
|
||||
|
||||
ngOnDestroy(): void {}
|
||||
|
||||
handleSearchTextChange(searchText: string) {
|
||||
this.vaultPopupItemsService.applyFilter(searchText);
|
||||
}
|
||||
|
||||
addCipher() {
|
||||
// TODO: Add currently filtered organization to query params if available
|
||||
void this.router.navigate(["/add-cipher"], {});
|
||||
|
||||
@@ -38,7 +38,8 @@ import { MY_VAULT_ID, VaultPopupListFiltersService } from "./vault-popup-list-fi
|
||||
})
|
||||
export class VaultPopupItemsService {
|
||||
private _refreshCurrentTab$ = new Subject<void>();
|
||||
private searchText$ = new BehaviorSubject<string>("");
|
||||
private _searchText$ = new BehaviorSubject<string>("");
|
||||
latestSearchText$: Observable<string> = this._searchText$.asObservable();
|
||||
|
||||
/**
|
||||
* Observable that contains the list of other cipher types that should be shown
|
||||
@@ -105,7 +106,7 @@ export class VaultPopupItemsService {
|
||||
|
||||
private _filteredCipherList$: Observable<PopupCipherView[]> = combineLatest([
|
||||
this._cipherList$,
|
||||
this.searchText$,
|
||||
this._searchText$,
|
||||
this.vaultPopupListFiltersService.filterFunction$,
|
||||
]).pipe(
|
||||
map(([ciphers, searchText, filterFunction]): [CipherView[], string] => [
|
||||
@@ -179,7 +180,7 @@ export class VaultPopupItemsService {
|
||||
* Observable that indicates whether a filter is currently applied to the ciphers.
|
||||
*/
|
||||
hasFilterApplied$ = combineLatest([
|
||||
this.searchText$,
|
||||
this._searchText$,
|
||||
this.vaultPopupListFiltersService.filters$,
|
||||
]).pipe(
|
||||
switchMap(([searchText, filters]) => {
|
||||
@@ -242,7 +243,7 @@ export class VaultPopupItemsService {
|
||||
}
|
||||
|
||||
applyFilter(newSearchText: string) {
|
||||
this.searchText$.next(newSearchText);
|
||||
this._searchText$.next(newSearchText);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user