Merge branch 'fix/848-849-Filter-Reset-On-Unselected-Filters-And-PrimaryFilters-Not-Affects-Selected-Filters' into feature/189-Warenausgabe/277-Filter/main

This commit is contained in:
Sebastian
2020-07-21 00:14:01 +02:00
8 changed files with 110 additions and 17 deletions

View File

@@ -24,10 +24,6 @@ $font-size: 18px;
}
.clear-all {
&:only-child {
display: none;
}
.filter-name {
padding-right: $filter-padding-right;
padding-left: 2rem;

View File

@@ -22,6 +22,7 @@
<app-selected-filter-options
[value]="filters"
(filterChanged)="onFiltersChange($event)"
[showResetButton]="filters | hasSelectedFilters"
>
</app-selected-filter-options>
</div>

View File

@@ -9,6 +9,7 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { RemissionUeberlaufCapacitiesModule } from '../../pages/remission-list-create/ueberlauf-capacities';
import { SharedModule } from 'apps/sales/src/app/shared/shared.module';
import { RemissionRequiredCapacitiesWidgetModule } from '../../components/remission-required-capacities-widget';
import { HasSelectedFiltersPipe } from '../../pipes';
@NgModule({
imports: [
@@ -21,8 +22,8 @@ import { RemissionRequiredCapacitiesWidgetModule } from '../../components/remiss
RemissionUeberlaufCapacitiesModule,
RemissionRequiredCapacitiesWidgetModule,
],
exports: [RemissionListFilterComponent],
declarations: [RemissionListFilterComponent],
exports: [RemissionListFilterComponent, HasSelectedFiltersPipe],
declarations: [RemissionListFilterComponent, HasSelectedFiltersPipe],
entryComponents: [RemissionListFilterComponent],
})
export class RemissionListFilterModule {}

View File

@@ -0,0 +1,27 @@
import { HasSelectedFiltersPipe } from './has-selected-filters.pipe';
import { filters } from '../mocks';
fdescribe('Pipe: HasSelectedFiltersPipe', () => {
let pipe: HasSelectedFiltersPipe;
beforeEach(() => {
pipe = new HasSelectedFiltersPipe();
});
it('should return true', () => {
const filterWithSelected = filters;
const result = pipe.transform(filterWithSelected);
expect(result).toBeTruthy();
});
it('should return false', () => {
const filterWithSelected = filters.map((f) => ({
...f,
options: f.options.map((o) => ({ ...o, selected: false })),
}));
const result = pipe.transform(filterWithSelected);
expect(result).toBeFalsy();
});
});

View File

@@ -0,0 +1,15 @@
import { Pipe, PipeTransform } from '@angular/core';
import { SelectFilter } from '../../filter';
@Pipe({
name: 'hasSelectedFilters',
})
export class HasSelectedFiltersPipe implements PipeTransform {
hasSelectedFilters = (filter: SelectFilter[]) => {
return filter.some((f) => f.options.some((o) => o.selected));
};
transform(filters: SelectFilter[]): boolean {
return this.hasSelectedFilters(filters);
}
}

View File

@@ -0,0 +1,4 @@
// start:ng42.barrel
export * from './has-selected-filters.pipe';
// end:ng42.barrel

View File

@@ -3,6 +3,7 @@ import { SearchStateFacade } from '@shelf-store';
import { ShelfFilterService } from './shelf-filter.service';
import { mockFilters } from '../shared/mockdata';
import { hot, cold } from 'jasmine-marbles';
import { Subject } from 'rxjs';
fdescribe('#ShelfFilterService', () => {
let service: ShelfFilterService;
@@ -16,11 +17,11 @@ fdescribe('#ShelfFilterService', () => {
useValue: jasmine.createSpyObj('searchStateFacade', [
'selectFilters$',
'primaryFilterChangedFromDefault$',
'selectFilters$',
]),
},
],
});
spyOn(
ShelfFilterService.prototype,
'initPendingFilters'
@@ -28,12 +29,49 @@ fdescribe('#ShelfFilterService', () => {
facade = TestBed.get(SearchStateFacade);
service = TestBed.get(ShelfFilterService);
spyOn(service, 'initService').and.callFake(() => {});
});
it('should be created', () => {
expect(service).toBeTruthy();
});
xdescribe('initPendingFilters', () => {
beforeEach(() => {
spyOn(service.pendingFilters$, 'next').and.callFake(() => {});
spyOn(service, 'lastFilterGroupChanged$').and.returnValue({
next: new Subject(),
});
});
xit('should should update pending filters only when filters change for the first time', async () => {
spyOnProperty(
service,
'pendingFiltersShouldUpdate$',
'get'
).and.callThrough();
});
const filters$ = hot('-a---b---c|', {
a: mockFilters,
b: { ...mockFilters },
c: { ...mockFilters },
});
((facade.selectFilters$ as unknown) as jasmine.Spy).and.returnValue(
filters$
);
const resetFilter$ = hot('-a', { a: true });
spyOnProperty(service, 'resetFilters$', 'get').and.returnValue(
resetFilter$
);
const expected = hot('-a', { a: mockFilters });
expect(service.pendingFiltersShouldUpdate$).toBeObservable(expected);
});
describe('#filtersChangedFromDefault', () => {
beforeEach(() => {
spyOnProperty(service, 'filtersChangedFromDefault$').and.callThrough();

View File

@@ -1,7 +1,7 @@
import { Injectable, OnDestroy } from '@angular/core';
import { Observable, BehaviorSubject, Subject, combineLatest } from 'rxjs';
import { SelectFilter, Filter, SelectFilterOption } from '../../filter';
import { tap, startWith, map, filter, takeUntil } from 'rxjs/operators';
import { tap, startWith, map, filter, takeUntil, take } from 'rxjs/operators';
import { SearchStateFacade } from '../../../store/customer';
import { flatten } from '../../../shared/utils';
import { isNullOrUndefined } from 'util';
@@ -20,8 +20,7 @@ export class ShelfFilterService implements OnDestroy {
public overlayClosed$ = new Subject<void>();
constructor(private searchStateFacade: SearchStateFacade) {
this.filters$ = this.searchStateFacade.selectFilters$;
this.initPendingFilters();
this.initService();
}
get hasSelectedFilters$(): Observable<boolean> {
@@ -55,19 +54,31 @@ export class ShelfFilterService implements OnDestroy {
);
}
get pendingFiltersShouldUpdate$() {
return combineLatest([
this.filters$.pipe(
filter((filters) => !isNullOrUndefined(filters)),
take(1)
),
this.resetFilters$.pipe(
startWith(true),
tap(() => this.pendingFilters$.next(null))
),
]);
}
initService() {
this.filters$ = this.searchStateFacade.selectFilters$;
this.initPendingFilters();
}
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
initPendingFilters() {
combineLatest([
this.filters$.pipe(filter((filters) => !isNullOrUndefined(filters))),
this.resetFilters$.pipe(
startWith(true),
tap(() => this.pendingFilters$.next(null))
),
])
this.pendingFiltersShouldUpdate$
.pipe(takeUntil(this.destroy$))
.subscribe(([filters]) => {
this.pendingFilters$.next(filters.map(cloneFilter));