hIMA-702 filtering refactor

This commit is contained in:
Adrian Toczydlowski
2019-12-18 02:30:50 +01:00
parent 08aaadeec2
commit d537bf062e
17 changed files with 182 additions and 116 deletions

View File

@@ -11,6 +11,7 @@ export interface Remission {
remissionProducts?: RemissionProduct[];
centralSelectedGroups?: FilterOption[];
centralSelectedOptions?: FilterOption[];
centralSelectedAktionenFilter?: FilterOption[];
overflowSelectedGroups?: FilterOption[];
overflowSelectedOptions?: FilterOption[];
centralTarget?: Side;

View File

@@ -67,7 +67,12 @@ export class CompleateRemissionState {
export class SetRemissionFilters {
static readonly type = SET_REMISSION_FILTERS;
constructor(public filterGroups: FilterOption[], public filterOptions: FilterOption[], public source: RemissionResourceType) {}
constructor(
public filterGroups: FilterOption[],
public filterOptions: FilterOption[],
public source: RemissionResourceType,
public filterId: string = 'abteilungen'
) {}
}
export class SetRemissionSource {

View File

@@ -57,13 +57,19 @@ export class RemissionSelectors {
@Selector([RemissionState])
static getCentralSelectedFilters(remissionState: RemissionStateModel) {
const remission = remissionState.remission;
return remission.centralSelectedOptions;
return remission.centralSelectedOptions || [];
}
@Selector([RemissionState])
static getCentralSelectedAktionenFilter(remissionState: RemissionStateModel) {
const remission = remissionState.remission;
return remission.centralSelectedAktionenFilter || [];
}
@Selector([RemissionState])
static getOverviewSelectedFilters(remissionState: RemissionStateModel) {
const remission = remissionState.remission;
return remission.overflowSelectedOptions;
return remission.overflowSelectedGroups || [];
}
@Selector([RemissionState])
@@ -84,15 +90,17 @@ export class RemissionSelectors {
}
@Selector([RemissionState])
static getRemissionSelectedGroups(remissionState: RemissionStateModel) {
const remission = remissionState.remission;
if (remission) {
if (remission.source === RemissionResourceType.Overflow) {
return remission.overflowSelectedGroups;
} else {
return remission.centralSelectedGroups;
static getRemissionSelectedGroups(filterId = 'abteilungen') {
return state => {
const { remission } = state.remission;
if (remission) {
if (remission.source === RemissionResourceType.Overflow) {
return remission.overflowSelectedGroups;
} else {
return filterId === 'abteilungen' ? remission.centralSelectedGroups : remission.centralSelectedAktionenFilter;
}
}
}
};
}
@Selector([RemissionState])
@@ -107,6 +115,26 @@ export class RemissionSelectors {
}
}
@Selector([RemissionState])
static getRemissionSelectedFilters(remissionState: RemissionStateModel) {
const remission = remissionState.remission;
if (remission) {
if (remission.source === RemissionResourceType.Overflow) {
return remission.overflowSelectedGroups;
} else {
const centralSelectedAktionenFilters = remission.centralSelectedAktionenFilter || [];
return [
...centralSelectedAktionenFilters,
...remission.centralSelectedGroups,
...remission.centralSelectedOptions.filter(
selectedOption =>
!remission.centralSelectedGroups.some(group => !!group.options.find(option => option.id === selectedOption.id))
)
];
}
}
}
@Selector([RemissionState])
static getRemissiontarget(remissionState: RemissionStateModel) {
const remission = remissionState.remission;

View File

@@ -22,7 +22,7 @@ import { ReloadGoodsIn } from '../actions/goods-in.actions';
import { ReloadBranchProcess } from '../actions/branch-process.actions';
import { ReloadRemission } from '../actions/remission.actions';
export const SYNC_DATA_VERSION = 135;
export const SYNC_DATA_VERSION = 142;
export class AppStateModel {
currentProcesssId: number;

View File

@@ -78,15 +78,25 @@ export class RemissionState {
}
@Action(actions.SetRemissionFilters)
setRemissionFilters(ctx: StateContext<RemissionStateModel>, { filterGroups, filterOptions, source }: actions.SetRemissionFilters) {
setRemissionFilters(
ctx: StateContext<RemissionStateModel>,
{ filterGroups, filterOptions, source, filterId }: actions.SetRemissionFilters
) {
const state = ctx.getState();
const currentRemission = state.remission;
let remission: Remission;
console.count('setRemissionFilters#');
if (source === RemissionResourceType.Central) {
remission = { ...currentRemission, centralSelectedGroups: filterGroups, centralSelectedOptions: filterOptions };
remission = {
...currentRemission,
...(filterId === 'abteilungen' && { centralSelectedGroups: filterGroups, centralSelectedOptions: filterOptions }),
...(filterId === 'aktionen' && { centralSelectedAktionenFilter: filterGroups })
};
} else {
remission = { ...currentRemission, overflowSelectedGroups: filterGroups, overflowSelectedOptions: filterOptions };
remission = {
...currentRemission,
overflowSelectedGroups: filterGroups,
overflowSelectedOptions: filterOptions
};
}
ctx.patchState({ remission });
this.syncApiState(remission);

View File

@@ -47,7 +47,7 @@
<hr class="branch" />
</ng-container>
<div class="action">
<app-button primary="true" [disabled]="noFiltersSelected()" (action)="updateFilters()">Filtern</app-button>
<app-button primary="true" (action)="updateFilters()">Filtern</app-button>
</div>
</div>
</ng-container>

View File

@@ -29,16 +29,6 @@ export class RemissionFilterItemComponent implements OnInit, OnDestroy {
selectedOptions: FilterOption[] = [];
hideSubFilters = false;
// get optionsTopPosition() {
// let value = 680;
// const filterEl = document.getElementById('filter');
// if (filterEl) {
// const topPosition = filterEl.getBoundingClientRect().top;
// value = topPosition + 47;
// }
// return value + 'px';
// }
constructor(private store: Store, private remissionHelper: RemissionHelperService, private cdrf: ChangeDetectorRef) {}
ngOnInit() {
@@ -55,7 +45,7 @@ export class RemissionFilterItemComponent implements OnInit, OnDestroy {
subscriptions() {
this.store
.select(RemissionSelectors.getRemissionSelectedGroups)
.select(RemissionSelectors.getRemissionSelectedGroups(this.filter.id))
.pipe(
filter(data => !isNullOrUndefined(data)),
take(1)
@@ -77,13 +67,21 @@ export class RemissionFilterItemComponent implements OnInit, OnDestroy {
this.remissionHelper.filteOptionsDeleteEvents$
.pipe(
filter(data => !isNullOrUndefined(data)),
filter(
data =>
this.selectedGroups.some(group => group.name === data.name) || this.selectedOptions.some(option => option.name === data.name)
),
takeUntil(this.destroy$)
)
.subscribe(option => {
if (this.remissionResourceType === RemissionResourceType.Overflow) {
this.toggleFirstLevelItem(option);
} else {
this.removeOptionsFromSelected(option);
if (option.options) {
this.toggleGrouping(option);
} else {
this.removeOptionsFromSelected(option);
}
if (this.hasGrouping) {
this.uncheckGroupOfOption(option);
}
@@ -113,15 +111,21 @@ export class RemissionFilterItemComponent implements OnInit, OnDestroy {
updateFilters() {
this.expanded = false;
this.store.dispatch(new SetRemissionFilters([...this.selectedGroups], [...this.selectedOptions], this.remissionResourceType));
this.remissionHelper.updateFilters({ filterId: this.filter.id, options: this.selectedOptions });
this.store.dispatch(
new SetRemissionFilters([...this.selectedGroups], [...this.selectedOptions], this.remissionResourceType, this.filter.id)
);
this.remissionHelper.updateFilters({
filters: {
[this.filter.id]: this.remissionResourceType === RemissionResourceType.Overflow ? this.selectedGroups : this.selectedOptions
}
});
this.remissionHelper.setFilterHeight(0);
}
uncheckGroupOfOption(option: FilterOption) {
const groups = this.filter.options;
groups.forEach(gr => {
const containsOption = gr.options.findIndex(op => op.id === option.id) !== -1;
const containsOption = gr.options ? gr.options.findIndex(op => op.id === option.id) !== -1 : gr.id === option.id;
if (containsOption) {
const index = this.selectedGroups.findIndex(i => i.name === gr.name);
if (index > -1) {
@@ -131,7 +135,7 @@ export class RemissionFilterItemComponent implements OnInit, OnDestroy {
});
}
noFiltersSelected = () => this.selectedOptions.length < 1;
noFiltersSelected = () => (this.selectedGroups.length > 0 ? false : this.selectedOptions.length < 1);
areFilterOptionsGoups(f: Filter) {
this.hasGrouping = f.options && f.options.length > 0 ? this.isInstanceOfFilterOpionsGroups(f.options) : false;
@@ -220,7 +224,7 @@ export class RemissionFilterItemComponent implements OnInit, OnDestroy {
if (isGroupSelected) {
this.removeGroupFromSelected(group);
} else {
this.addGroupToSelected(group);
this.remissionResourceType === RemissionResourceType.Overflow ? this.selectedGroups.push(group) : this.addGroupToSelected(group);
}
}
@@ -275,24 +279,28 @@ export class RemissionFilterItemComponent implements OnInit, OnDestroy {
selectAllOptionsOfGroup(group: FilterOption) {
const filterGroup = this.filter.options.find(t => t.name === group.name);
const options = filterGroup.options;
options.forEach(op => {
const isSelected = this.selectedOptions.findIndex(o => o.id === op.id) !== -1;
if (!isSelected) {
this.selectedOptions.push(op);
}
});
const options = filterGroup && filterGroup.options;
if (options) {
options.forEach(op => {
const isSelected = this.selectedOptions.findIndex(o => o.id === op.id) !== -1;
if (!isSelected) {
this.selectedOptions.push(op);
}
});
}
}
unSelectAllOptionsOfGroup(group: FilterOption) {
const filterGroup = this.filter.options.find(t => t.name === group.name);
const options = filterGroup.options;
options.forEach(op => {
const isSelected = this.selectedOptions.findIndex(o => o.id === op.id) !== -1;
if (isSelected) {
this.removeOptionsFromSelected(op);
}
});
const options = filterGroup && filterGroup.options;
if (options) {
options.forEach(op => {
const isSelected = this.selectedOptions.findIndex(o => o.id === op.id) !== -1;
if (isSelected) {
this.removeOptionsFromSelected(op);
}
});
}
}
toggle() {

View File

@@ -1,5 +1,6 @@
import { ChangeDetectionStrategy, Component, OnInit, Input, ViewChildren, QueryList, ChangeDetectorRef } from '@angular/core';
import { take } from 'rxjs/operators';
import { ChangeDetectionStrategy, Component, OnInit, Input, ViewChildren, QueryList, ChangeDetectorRef, OnDestroy } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil, tap, distinctUntilChanged } from 'rxjs/operators';
import { Filter, RemissionService } from '@isa/remission';
@@ -12,30 +13,37 @@ import { RemissionFilterItemComponent } from '../remission-filter-item/remission
styleUrls: ['./remission-filters.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class RemissionFiltersComponent implements OnInit {
export class RemissionFiltersComponent implements OnInit, OnDestroy {
@Input() remissionProcessId: number;
@Input()
set remissionResourceType(val: RemissionResourceType) {
this._remissionResourceType = val;
this.subscriptions();
}
get remissionResourceType(): RemissionResourceType {
return this._remissionResourceType;
}
@ViewChildren('filterItem') filterItems: QueryList<RemissionFilterItemComponent>;
filters: Filter[];
destroy$ = new Subject();
loadItems = true;
private _remissionResourceType: RemissionResourceType;
constructor(private cdr: ChangeDetectorRef, private remissionService: RemissionService) {}
ngOnInit() {}
ngOnInit() {
this.subscriptions();
}
ngOnDestroy() {
this.destroy$.next();
}
subscriptions() {
this.loadItems = false;
this.remissionService
.getFilters({ remissionProcessId: this.remissionProcessId })
.pipe(take(1))
.pipe(distinctUntilChanged(), takeUntil(this.destroy$))
.subscribe(this.remissionFiltersSubscription);
}

View File

@@ -107,10 +107,11 @@ export class RemissionListComponent implements OnInit, OnDestroy {
this.products = [];
this.remissionHelper.setRemissionListHits(0);
if (updates.filterId && updates.options) {
changes.filter = {
[updates.filterId]: [...updates.options.map(op => op.id)]
};
if (updates.filters) {
changes.filter = {};
Object.keys(updates.filters).forEach(filterId => {
changes.filter[filterId] = [...updates.filters[filterId].map(op => op.id)];
});
}
if (updates.source) {
@@ -129,7 +130,7 @@ export class RemissionListComponent implements OnInit, OnDestroy {
remissionProcessId: this.remissionProcess.id,
changes: changes
})
.toPromise();
.subscribe();
};
subscribeToFilterHeightChanges() {

View File

@@ -19,19 +19,17 @@ export class RemissionSelectedFilterItemsComponent implements OnInit, OnDestroy
this.subscriptions();
}
remissionResourceType: RemissionResourceType;
@Select(RemissionSelectors.getRemissionSelectedOptions) centralFilters$: Observable<FilterOption[]>;
@Select(RemissionSelectors.getRemissionSelectedGroups) overflowFilters$: Observable<FilterOption[]>;
@Select(RemissionSelectors.getRemissionSelectedFilters) selectedFilters$: Observable<FilterOption[]>;
destroy$ = new Subject();
options: FilterOption[];
constructor(private store: Store, private remissionHelper: RemissionHelperService) {}
constructor(private remissionHelper: RemissionHelperService) {}
ngOnInit() {
this.subscriptions();
}
subscriptions() {
const filters$ = this.remissionResourceType === RemissionResourceType.Central ? this.centralFilters$ : this.overflowFilters$;
filters$
this.selectedFilters$
.pipe(
filter(data => !isNullOrUndefined(data)),
distinctUntilChanged(),
@@ -47,6 +45,7 @@ export class RemissionSelectedFilterItemsComponent implements OnInit, OnDestroy
}
removeOption(option: FilterOption) {
// somehow send a filterId
this.remissionHelper.deleteFilterOption(option);
}

View File

@@ -1,8 +1,7 @@
import { FilterOption, RemissionSourceType, RemissionSupplier } from '@isa/remission';
export interface UpdateFilter {
filterId?: string;
options?: FilterOption[];
filters?: { [filterId: string]: FilterOption[] };
source?: RemissionSourceType;
target?: RemissionSupplier;
remissionProcessId?: number;

View File

@@ -1,4 +1,4 @@
<div #remissionListContainer id="remission-list-container" class="remission-list-container" (scroll)="scrollHandler($event)">
<div #remissionListContainer id="remission-list-container" class="remission-list-container">
<div class="headers" *ngIf="resourceTypeSwitch">
<div class="header-item resource-type">
<lib-double-choice-switch [model]="resourceTypeSwitch" (change)="resourceTypeChange($event)"></lib-double-choice-switch>

View File

@@ -176,10 +176,12 @@ export class RemissionListCreateComponent implements OnInit, OnDestroy {
}
currentRemissionTargetSubscriptionHandler = (side: Side) => {
this.selectedSupplier = side;
this.remissionHelper.updateFilters({
target: side === Side.LEFT ? this.suppliers.leftSupplier : this.suppliers.rightSupplier
});
if (side !== this.selectedSupplier) {
this.selectedSupplier = side;
this.remissionHelper.updateFilters({
target: side === Side.LEFT ? this.suppliers.leftSupplier : this.suppliers.rightSupplier
});
}
};
remissionSubsribtionInitialisation() {
@@ -187,7 +189,6 @@ export class RemissionListCreateComponent implements OnInit, OnDestroy {
if (remissionProcessStatuses.started && !remissionProcessStatuses.completed) {
this.navigateToStartedRemission();
} else {
this.reinitializeFilters();
this.remissionProcessStatuses = remissionProcessStatuses;
this.remissionProcess$ = !this.remissionProcessStatuses.created ? this.createProcess() : this.continueProcess();
this.remissionProcess$.pipe(takeUntil(this.destroy$)).subscribe(this.remisionProcessSubscriptionHandler);
@@ -273,6 +274,7 @@ export class RemissionListCreateComponent implements OnInit, OnDestroy {
.then(() => {
this.store.dispatch(new ActivateRemissionReminder());
});
this.reinitializeFilters();
};
shouldShowOverflowInitialMessage(remissionFilter: RemissionFilter) {
@@ -386,20 +388,6 @@ export class RemissionListCreateComponent implements OnInit, OnDestroy {
this.store.dispatch(new SetBranchProcessCurrentPath(path));
}
scrollHandler(event) {
const { clientHeight, scrollHeight, scrollTop } = event.target;
if (scrollTop + clientHeight === scrollHeight) {
this.setScrollToTopBotomVisibility(false, false);
} else if (scrollTop > this.lastScrollTop) {
this.setScrollToTopBotomVisibility(true, false);
} else if (scrollTop > 500) {
this.setScrollToTopBotomVisibility(false, true);
} else {
this.setScrollToTopBotomVisibility(false, false);
}
this.lastScrollTop = scrollTop <= 0 ? 0 : scrollTop;
}
navigateToTop() {
this.remissionListContainer.nativeElement.scrollTo({ top: 0, behavior: 'smooth' });
}
@@ -479,15 +467,22 @@ export class RemissionListCreateComponent implements OnInit, OnDestroy {
}
private reinitializeFilters() {
const options =
const abteilungenFilters =
this.selectedRemissionResourceType === RemissionResourceType.Central
? this.store.selectSnapshot(RemissionSelectors.getCentralSelectedFilters)
: this.store.selectSnapshot(RemissionSelectors.getOverviewSelectedFilters);
const aktionenFilters =
this.selectedRemissionResourceType === RemissionResourceType.Central
? this.store.selectSnapshot(RemissionSelectors.getCentralSelectedAktionenFilter)
: [];
this.remissionHelper.updateFilters({
source: this.selectedRemissionResourceType,
// Change it when Aktionen filter will be ready
filterId: 'abteilungen',
options
filters: {
abteilungen: abteilungenFilters,
...(aktionenFilters.length > 0 && {
aktionen: aktionenFilters
})
}
});
}
}

View File

@@ -165,15 +165,18 @@ export class RemissionListStartedComponent implements OnInit, OnDestroy {
}
currentRemissionTargetSubscriptionHandler = (side: Side) => {
this.selectedSupplier = side;
const supplier = side === Side.LEFT ? this.suppliers.leftSupplier : this.suppliers.rightSupplier;
this.selectedSupplierName = supplier.name;
this.remissionHelper.updateFilters({ target: side === Side.LEFT ? this.suppliers.leftSupplier : this.suppliers.rightSupplier });
if (side !== this.selectedSupplier) {
this.selectedSupplier = side;
const supplier = side === Side.LEFT ? this.suppliers.leftSupplier : this.suppliers.rightSupplier;
this.selectedSupplierName = supplier.name;
this.remissionHelper.updateFilters({
target: supplier
});
}
};
remissionSubsribtionInitialisation() {
this.loadCurrentRemissionProcessStatuses().then(remissionProcessStatuses => {
this.reinitializeFilters();
this.remissionProcessStatuses = remissionProcessStatuses;
this.remissionProcess$ = !this.remissionProcessStatuses.created ? this.createProcess() : this.continueProcess();
this.remissionProcess$.pipe(distinctUntilChanged(), takeUntil(this.destroy$)).subscribe(this.remisionProcessSubscriptionHandler);
@@ -251,9 +254,12 @@ export class RemissionListStartedComponent implements OnInit, OnDestroy {
if (this.suppliers) {
setTimeout(() => {
this.selectedSupplier = remissionProcess.filter.target.name === this.suppliers.leftSupplier.name ? Side.LEFT : Side.RIGHT;
const supplier = this.selectedSupplier === Side.LEFT ? this.suppliers.leftSupplier : this.suppliers.rightSupplier;
this.selectedSupplierName = supplier.name;
});
}
this.store.dispatch(new SetRemissionProcess(remissionProcess));
this.reinitializeFilters();
};
shouldShowOverflowInitialMessage(remissionFilter: RemissionFilter) {
@@ -389,15 +395,22 @@ export class RemissionListStartedComponent implements OnInit, OnDestroy {
}
private reinitializeFilters() {
const options =
const abteilungenFilters =
this.selectedRemissionResourceType === RemissionResourceType.Central
? this.store.selectSnapshot(RemissionSelectors.getCentralSelectedFilters)
: this.store.selectSnapshot(RemissionSelectors.getOverviewSelectedFilters);
const aktionenFilters =
this.selectedRemissionResourceType === RemissionResourceType.Central
? this.store.selectSnapshot(RemissionSelectors.getCentralSelectedAktionenFilter)
: [];
this.remissionHelper.updateFilters({
source: this.selectedRemissionResourceType,
// Change it when Aktionen filter will be ready
filterId: 'abteilungen',
options
filters: {
abteilungen: abteilungenFilters,
...(aktionenFilters.length > 0 && {
aktionen: aktionenFilters
})
}
});
}
}

View File

@@ -16,7 +16,6 @@ export class NativeContainerService {
this.wm = fromEvent(this.windowRef.nativeWindow, 'message').pipe(
map((e: MessageEvent) => {
console.dir(e);
return e.data;
})
);

24
package-lock.json generated
View File

@@ -1071,33 +1071,33 @@
}
},
"@isa/catsearch-api": {
"version": "0.0.37",
"resolved": "https://pkgs.dev.azure.com/hugendubel/_packaging/hugendubel/npm/registry/@isa/catsearch-api/-/catsearch-api-0.0.37.tgz",
"integrity": "sha1-RxNLxkj7IntrUVKjFm4Uoq0w8B8=",
"version": "0.0.38",
"resolved": "https://pkgs.dev.azure.com/hugendubel/_packaging/hugendubel/npm/registry/@isa/catsearch-api/-/catsearch-api-0.0.38.tgz",
"integrity": "sha1-A1suI/W15bYqYRLXKT7UatZgjYY=",
"requires": {
"tslib": "^1.9.0"
}
},
"@isa/print-api": {
"version": "0.0.37",
"resolved": "https://pkgs.dev.azure.com/hugendubel/_packaging/hugendubel/npm/registry/@isa/print-api/-/print-api-0.0.37.tgz",
"integrity": "sha1-pbuTxdhnvYvgJbKnu3JLwXabN3k=",
"version": "0.0.38",
"resolved": "https://pkgs.dev.azure.com/hugendubel/_packaging/hugendubel/npm/registry/@isa/print-api/-/print-api-0.0.38.tgz",
"integrity": "sha1-2h1uCcI/KMVhabN/W1tKlHxrsCI=",
"requires": {
"tslib": "^1.9.0"
}
},
"@isa/remi-api": {
"version": "0.0.37",
"resolved": "https://pkgs.dev.azure.com/hugendubel/_packaging/hugendubel/npm/registry/@isa/remi-api/-/remi-api-0.0.37.tgz",
"integrity": "sha1-4ogvOiR9KBd8tWx5x528Sg0duSw=",
"version": "0.0.38",
"resolved": "https://pkgs.dev.azure.com/hugendubel/_packaging/hugendubel/npm/registry/@isa/remi-api/-/remi-api-0.0.38.tgz",
"integrity": "sha1-ovohI0L+KKv15qqF+rbrovQm9Vw=",
"requires": {
"tslib": "^1.9.0"
}
},
"@isa/remission": {
"version": "0.2.6",
"resolved": "https://pkgs.dev.azure.com/hugendubel/_packaging/hugendubel/npm/registry/@isa/remission/-/remission-0.2.6.tgz",
"integrity": "sha1-eFhDk1Eyl/OP9NLAQuEIweMV84M=",
"version": "0.2.9",
"resolved": "https://pkgs.dev.azure.com/hugendubel/_packaging/hugendubel/npm/registry/@isa/remission/-/remission-0.2.9.tgz",
"integrity": "sha1-LfhzQpZaN87ywmCGtJgyPPfuU38=",
"requires": {
"tslib": "^1.9.0"
}

View File

@@ -37,10 +37,10 @@
"@cmf/core": "^0.1.12",
"@cmf/inventory-api": "^0.1.12",
"@cmf/trade-api": "^0.1.12",
"@isa/catsearch-api": "^0.0.37",
"@isa/print-api": "^0.0.37",
"@isa/remi-api": "^0.0.37",
"@isa/remission": "^0.2.6",
"@isa/catsearch-api": "^0.0.38",
"@isa/print-api": "^0.0.38",
"@isa/remi-api": "^0.0.38",
"@isa/remission": "^0.2.8",
"@ng-idle/core": "^8.0.0-beta.4",
"@ng-idle/keepalive": "^8.0.0-beta.4",
"@ngxs/store": "^3.4.1",