mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-14 13:33:03 +00:00
turned filterValues in to a RemoteData object, added fade animations
This commit is contained in:
@@ -6,8 +6,9 @@
|
||||
<input type="checkbox" [checked]="true" class="my-1 align-self-stretch"/>
|
||||
<span class="filter-value pl-1">{{value}}</span>
|
||||
</a>
|
||||
<ng-container *ngFor="let page of (filterValues$ | async)">
|
||||
<ng-container *ngFor="let value of (page | async)?.payload.page; let i=index">
|
||||
<ng-container *ngFor="let page of (filterValues$ | async)?.payload">
|
||||
<div [@facetLoad]="animationState">
|
||||
<ng-container *ngFor="let value of page.page; let i=index">
|
||||
<a *ngIf="!(selectedValues | async).includes(value.value)" class="d-flex flex-row"
|
||||
[routerLink]="[getSearchLink()]"
|
||||
[queryParams]="getAddParams(value.value) | async" queryParamsHandling="merge">
|
||||
@@ -18,6 +19,7 @@
|
||||
</span>
|
||||
</a>
|
||||
</ng-container>
|
||||
</div>
|
||||
</ng-container>
|
||||
<div class="clearfix toggle-more-filters">
|
||||
<a class="float-left" *ngIf="!(isLastPage$ | async)"
|
||||
|
@@ -2,7 +2,10 @@ import { Component, OnInit } from '@angular/core';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { FilterType } from '../../../search-service/filter-type.model';
|
||||
import { renderFacetFor } from '../search-filter-type-decorator';
|
||||
import { SearchFacetFilterComponent } from '../search-facet-filter/search-facet-filter.component';
|
||||
import {
|
||||
facetLoad,
|
||||
SearchFacetFilterComponent
|
||||
} from '../search-facet-filter/search-facet-filter.component';
|
||||
|
||||
/**
|
||||
* This component renders a simple item page.
|
||||
@@ -14,6 +17,7 @@ import { SearchFacetFilterComponent } from '../search-facet-filter/search-facet-
|
||||
selector: 'ds-search-boolean-filter',
|
||||
styleUrls: ['./search-boolean-filter.component.scss'],
|
||||
templateUrl: './search-boolean-filter.component.html',
|
||||
animations: [facetLoad]
|
||||
})
|
||||
|
||||
@renderFacetFor(FilterType.boolean)
|
||||
|
@@ -1,17 +1,20 @@
|
||||
import { Component, Inject, OnChanges, OnDestroy, OnInit, SimpleChanges } from '@angular/core';
|
||||
import { animate, state, style, transition, trigger } from '@angular/animations';
|
||||
import { Component, Inject, OnDestroy, OnInit } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { Subject } from 'rxjs/Subject';
|
||||
import { Subscription } from 'rxjs/Subscription';
|
||||
import { RemoteDataBuildService } from '../../../../core/cache/builders/remote-data-build.service';
|
||||
import { PaginatedList } from '../../../../core/data/paginated-list';
|
||||
import { RemoteData } from '../../../../core/data/remote-data';
|
||||
import { hasNoValue, hasValue, isNotEmpty } from '../../../../shared/empty.util';
|
||||
import { EmphasizePipe } from '../../../../shared/utils/emphasize.pipe';
|
||||
import { SearchOptions } from '../../../search-options.model';
|
||||
import { FacetValue } from '../../../search-service/facet-value.model';
|
||||
import { SearchFilterConfig } from '../../../search-service/search-filter-config.model';
|
||||
import { Router } from '@angular/router';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { FILTER_CONFIG, SearchFilterService } from '../search-filter.service';
|
||||
import { hasNoValue, hasValue, isNotEmpty } from '../../../../shared/empty.util';
|
||||
import { RemoteData } from '../../../../core/data/remote-data';
|
||||
import { PaginatedList } from '../../../../core/data/paginated-list';
|
||||
import { SearchService } from '../../../search-service/search.service';
|
||||
import { SearchOptions } from '../../../search-options.model';
|
||||
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
|
||||
import { Subscription } from 'rxjs/Subscription';
|
||||
import { EmphasizePipe } from '../../../../shared/utils/emphasize.pipe';
|
||||
import { FILTER_CONFIG, SearchFilterService } from '../search-filter.service';
|
||||
|
||||
/**
|
||||
* This component renders a simple item page.
|
||||
@@ -26,48 +29,66 @@ import { EmphasizePipe } from '../../../../shared/utils/emphasize.pipe';
|
||||
|
||||
export class SearchFacetFilterComponent implements OnInit, OnDestroy {
|
||||
filterValues: Array<Observable<RemoteData<PaginatedList<FacetValue>>>> = [];
|
||||
filterValues$: BehaviorSubject<any> = new BehaviorSubject(this.filterValues);
|
||||
filterValues$: Subject<RemoteData<Array<PaginatedList<FacetValue>>>>;
|
||||
currentPage: Observable<number>;
|
||||
isLastPage$: BehaviorSubject<boolean> = new BehaviorSubject(false);
|
||||
filter: string;
|
||||
pageChange = false;
|
||||
sub: Subscription;
|
||||
private subs: Subscription[] = [];
|
||||
filterSearchResults: Observable<any[]> = Observable.of([]);
|
||||
selectedValues: Observable<string[]>;
|
||||
private collapseNextUpdate = true;
|
||||
animationState = 'loading';
|
||||
|
||||
constructor(protected searchService: SearchService,
|
||||
protected filterService: SearchFilterService,
|
||||
protected rdbs: RemoteDataBuildService,
|
||||
protected router: Router,
|
||||
@Inject(FILTER_CONFIG) public filterConfig: SearchFilterConfig) {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.filterValues$ = new BehaviorSubject(new RemoteData(true, false, undefined, undefined, undefined));
|
||||
this.currentPage = this.getCurrentPage().distinctUntilChanged();
|
||||
this.selectedValues = this.filterService.getSelectedValuesForFilter(this.filterConfig);
|
||||
const searchOptions = this.filterService.getSearchOptions().distinctUntilChanged();
|
||||
searchOptions.subscribe((options) => this.updateFilterValueList(options));
|
||||
this.subs.push(searchOptions.subscribe((options) => this.updateFilterValueList(options)));
|
||||
|
||||
const facetValues = Observable.combineLatest(searchOptions, this.currentPage, (options, page) => {
|
||||
return {values: this.searchService.getFacetValuesFor(this.filterConfig, page, options), page: page};
|
||||
});
|
||||
facetValues.subscribe((facetOutcome) => {
|
||||
|
||||
|
||||
|
||||
this.subs.push(facetValues.subscribe((facetOutcome) => {
|
||||
const newValues$ = facetOutcome.values;
|
||||
|
||||
if (facetOutcome.page > 1) {
|
||||
this.filterValues = [...this.filterValues, newValues$];
|
||||
} else {
|
||||
this.filterValues = [newValues$]
|
||||
if (this.collapseNextUpdate) {
|
||||
this.showFirstPageOnly();
|
||||
facetOutcome.page = 1;
|
||||
this.collapseNextUpdate = false;
|
||||
}
|
||||
if (facetOutcome.page === 1) {
|
||||
this.filterValues = [];
|
||||
}
|
||||
|
||||
this.filterValues$.next(this.filterValues);
|
||||
newValues$.first().subscribe((rd) => {
|
||||
this.filterValues = [...this.filterValues, newValues$];
|
||||
|
||||
this.subs.push(this.rdbs.aggregate(this.filterValues).subscribe((rd: RemoteData<Array<PaginatedList<FacetValue>>>) => {
|
||||
this.animationState = 'ready';
|
||||
this.filterValues$.next(rd);
|
||||
}));
|
||||
this.subs.push(newValues$.first().subscribe((rd) => {
|
||||
this.isLastPage$.next(hasNoValue(rd.payload.next))
|
||||
});
|
||||
});
|
||||
}));
|
||||
}));
|
||||
|
||||
}
|
||||
|
||||
updateFilterValueList(options: SearchOptions) {
|
||||
// this.unsubscribe();
|
||||
this.showFirstPageOnly();
|
||||
// this.showFirstPageOnly();
|
||||
this.animationState = 'loading';
|
||||
this.collapseNextUpdate = true;
|
||||
this.filter = '';
|
||||
}
|
||||
|
||||
@@ -138,13 +159,9 @@ export class SearchFacetFilterComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.unsubscribe();
|
||||
}
|
||||
|
||||
unsubscribe(): void {
|
||||
if (hasValue(this.sub)) {
|
||||
this.sub.unsubscribe();
|
||||
}
|
||||
this.subs
|
||||
.filter((sub) => hasValue(sub))
|
||||
.forEach((sub) => sub.unsubscribe());
|
||||
}
|
||||
|
||||
findSuggestions(data): void {
|
||||
@@ -171,3 +188,9 @@ export class SearchFacetFilterComponent implements OnInit, OnDestroy {
|
||||
return new EmphasizePipe().transform(facet.value, query) + ' (' + facet.count + ')';
|
||||
}
|
||||
}
|
||||
|
||||
export const facetLoad = trigger('facetLoad', [
|
||||
state('ready', style({ opacity: 1 })),
|
||||
state('loading', style({ opacity: 0 })),
|
||||
transition('loading <=> ready', animate(100)),
|
||||
]);
|
||||
|
@@ -6,8 +6,9 @@
|
||||
<input type="checkbox" [checked]="true" class="my-1 align-self-stretch"/>
|
||||
<span class="filter-value pl-1">{{value}}</span>
|
||||
</a>
|
||||
<ng-container *ngFor="let page of (filterValues$ | async)">
|
||||
<ng-container *ngFor="let value of (page | async)?.payload.page; let i=index">
|
||||
<ng-container *ngFor="let page of (filterValues$ | async)?.payload">
|
||||
<div [@facetLoad]="animationState">
|
||||
<ng-container *ngFor="let value of page.page; let i=index">
|
||||
<a *ngIf="!(selectedValues | async).includes(value.value)" class="d-flex flex-row"
|
||||
[routerLink]="[getSearchLink()]"
|
||||
[queryParams]="getAddParams(value.value) | async" queryParamsHandling="merge" >
|
||||
@@ -18,6 +19,7 @@
|
||||
</span>
|
||||
</a>
|
||||
</ng-container>
|
||||
</div>
|
||||
</ng-container>
|
||||
<div class="clearfix toggle-more-filters">
|
||||
<a class="float-left" *ngIf="!(isLastPage$ | async)"
|
||||
|
@@ -3,7 +3,10 @@ import { FacetValue } from '../../../search-service/facet-value.model';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { FilterType } from '../../../search-service/filter-type.model';
|
||||
import { renderFacetFor } from '../search-filter-type-decorator';
|
||||
import { SearchFacetFilterComponent } from '../search-facet-filter/search-facet-filter.component';
|
||||
import {
|
||||
facetLoad,
|
||||
SearchFacetFilterComponent
|
||||
} from '../search-facet-filter/search-facet-filter.component';
|
||||
|
||||
/**
|
||||
* This component renders a simple item page.
|
||||
@@ -15,6 +18,7 @@ import { SearchFacetFilterComponent } from '../search-facet-filter/search-facet-
|
||||
selector: 'ds-search-hierarchy-filter',
|
||||
styleUrls: ['./search-hierarchy-filter.component.scss'],
|
||||
templateUrl: './search-hierarchy-filter.component.html',
|
||||
animations: [facetLoad]
|
||||
})
|
||||
|
||||
@renderFacetFor(FilterType.hierarchy)
|
||||
|
@@ -23,8 +23,9 @@
|
||||
ngDefaultControl></nouislider>
|
||||
|
||||
</ng-container>
|
||||
<ng-container *ngFor="let page of (filterValues$ | async)">
|
||||
<ng-container *ngFor="let value of (page | async)?.payload.page; let i=index">
|
||||
<ng-container *ngFor="let page of (filterValues$ | async)?.payload">
|
||||
<div [@facetLoad]="animationState">
|
||||
<ng-container *ngFor="let value of page.page; let i=index">
|
||||
<a *ngIf="!(selectedValues | async).includes(value.value)" class="d-flex flex-row"
|
||||
[routerLink]="[getSearchLink()]"
|
||||
[queryParams]="getAddParams(value.value) | async" queryParamsHandling="merge">
|
||||
@@ -34,6 +35,7 @@
|
||||
</span>
|
||||
</a>
|
||||
</ng-container>
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -1,8 +1,12 @@
|
||||
import { isPlatformBrowser } from '@angular/common';
|
||||
import { Component, Inject, OnInit, PLATFORM_ID } from '@angular/core';
|
||||
import { RemoteDataBuildService } from '../../../../core/cache/builders/remote-data-build.service';
|
||||
import { FilterType } from '../../../search-service/filter-type.model';
|
||||
import { renderFacetFor } from '../search-filter-type-decorator';
|
||||
import { SearchFacetFilterComponent } from '../search-facet-filter/search-facet-filter.component';
|
||||
import {
|
||||
facetLoad,
|
||||
SearchFacetFilterComponent
|
||||
} from '../search-facet-filter/search-facet-filter.component';
|
||||
import { SearchFilterConfig } from '../../../search-service/search-filter-config.model';
|
||||
import { FILTER_CONFIG, SearchFilterService } from '../search-filter.service';
|
||||
import { SearchService } from '../../../search-service/search.service';
|
||||
@@ -24,6 +28,7 @@ const rangeDelimiter = '-';
|
||||
selector: 'ds-search-range-filter',
|
||||
styleUrls: ['./search-range-filter.component.scss'],
|
||||
templateUrl: './search-range-filter.component.html',
|
||||
animations: [facetLoad]
|
||||
})
|
||||
|
||||
@renderFacetFor(FilterType.range)
|
||||
@@ -35,10 +40,11 @@ export class SearchRangeFilterComponent extends SearchFacetFilterComponent imple
|
||||
constructor(protected searchService: SearchService,
|
||||
protected filterService: SearchFilterService,
|
||||
protected router: Router,
|
||||
protected rdbs: RemoteDataBuildService,
|
||||
@Inject(FILTER_CONFIG) public filterConfig: SearchFilterConfig,
|
||||
@Inject(PLATFORM_ID) private platformId: any,
|
||||
private route: ActivatedRoute) {
|
||||
super(searchService, filterService, router, filterConfig);
|
||||
super(searchService, filterService, rdbs, router, filterConfig);
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
|
@@ -6,18 +6,22 @@
|
||||
<input type="checkbox" [checked]="true" class="my-1 align-self-stretch"/>
|
||||
<span class="filter-value pl-1">{{value}}</span>
|
||||
</a>
|
||||
<ng-container *ngFor="let page of (filterValues$ | async)">
|
||||
<ng-container *ngFor="let value of (page | async)?.payload.page; let i=index">
|
||||
<ng-container *ngVar="(filterValues$ | async) as filterValuesRD">
|
||||
<div [@facetLoad]="animationState">
|
||||
<ng-container *ngFor="let page of filterValuesRD?.payload">
|
||||
<ng-container *ngFor="let value of page.page; let i=index">
|
||||
<a *ngIf="!(selectedValues | async).includes(value.value)" class="d-flex flex-row"
|
||||
[routerLink]="[getSearchLink()]"
|
||||
[queryParams]="getAddParams(value.value) | async" queryParamsHandling="merge" >
|
||||
<input type="checkbox" [checked]="false" class="my-1 align-self-stretch"/>
|
||||
<span class="filter-value px-1">{{value.value}}</span>
|
||||
<span class="float-right filter-value-count ml-auto">
|
||||
<span class="badge badge-secondary badge-pill">{{value.count}}</span>
|
||||
</span>
|
||||
<input type="checkbox" [checked]="false" class="my-1 align-self-stretch"/>
|
||||
<span class="filter-value px-1">{{value.value}}</span>
|
||||
<span class="float-right filter-value-count ml-auto">
|
||||
<span class="badge badge-secondary badge-pill">{{value.count}}</span>
|
||||
</span>
|
||||
</a>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
</div>
|
||||
</ng-container>
|
||||
<div class="clearfix toggle-more-filters">
|
||||
<a class="float-left" *ngIf="!(isLastPage$ | async)"
|
||||
|
@@ -1,9 +1,12 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { FacetValue } from '../../../search-service/facet-value.model';
|
||||
import { animate, state, style, transition, trigger } from '@angular/animations';
|
||||
import { Component, HostBinding, OnInit } from '@angular/core';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { FilterType } from '../../../search-service/filter-type.model';
|
||||
import {
|
||||
facetLoad,
|
||||
SearchFacetFilterComponent
|
||||
} from '../search-facet-filter/search-facet-filter.component';
|
||||
import { renderFacetFor } from '../search-filter-type-decorator';
|
||||
import { SearchFacetFilterComponent } from '../search-facet-filter/search-facet-filter.component';
|
||||
|
||||
/**
|
||||
* This component renders a simple item page.
|
||||
@@ -15,6 +18,7 @@ import { SearchFacetFilterComponent } from '../search-facet-filter/search-facet-
|
||||
selector: 'ds-search-text-filter',
|
||||
styleUrls: ['./search-text-filter.component.scss'],
|
||||
templateUrl: './search-text-filter.component.html',
|
||||
animations: [facetLoad]
|
||||
})
|
||||
|
||||
@renderFacetFor(FilterType.text)
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<div>
|
||||
<label>{{ message }}</label>
|
||||
<label *ngIf="message">{{ message }}</label>
|
||||
<div class="loader">
|
||||
<span class="l-1"></span>
|
||||
<span class="l-2"></span>
|
||||
|
Reference in New Issue
Block a user