[HIMA-944] working on the list element for remission

This commit is contained in:
Eraldo Hasanaj
2019-11-08 17:44:20 +01:00
parent c83601e5a5
commit 8d0c3cd20c
32 changed files with 710 additions and 74 deletions

View File

@@ -1,4 +1,6 @@
import { RemissionProcess, RemissionProduct, FilterOption } from '@isa/remission';
import { Side } from '@libs/ui/lib/small-double-choice-switch';
import { RemissionResourceType } from '../../modules/remission/models/remission-resource-type.model';
export interface Remission {
remissionProcessCreated?: boolean;
@@ -10,4 +12,7 @@ export interface Remission {
centralSelectedOptions?: FilterOption[];
overflowSelectedGroups?: string[];
overflowSelectedOptions?: FilterOption[];
centralTarget?: Side;
overflowTarget?: Side;
source?: RemissionResourceType;
}

View File

@@ -1,6 +1,7 @@
import { Remission } from '../../models/remission.model';
import { RemissionProcess, FilterOption } from '@isa/remission';
import { RemissionProcess, FilterOption, RemissionProduct, RemissionSupplier } from '@isa/remission';
import { RemissionResourceType } from '../../../modules/remission/models/remission-resource-type.model';
import { Side } from '@libs/ui/lib/small-double-choice-switch';
export const SET_REMISSION_CREATED = '[REMISSION] Set created';
export const SET_REMISSION_STARTED = '[REMISSION] Set started';
@@ -9,6 +10,9 @@ export const SET_REMISSION_PROCESS = '[REMISSION] Set remission process';
export const RELOAD_REMISSION = '[REMISSION] Reload';
export const INIT_REMISSION_STATE = '[REMISSION] Init';
export const SET_REMISSION_FILTERS = '[REMISSION] Set filters';
export const SET_REMISSION_SOURCE = '[REMISSION] Set source';
export const SET_REMISSION_TARGET = '[REMISSION] Set target';
export const SET_REMISSION_PRODUCTS = '[REMISSION] Set products';
export class SetRemissionCreated {
static readonly type = SET_REMISSION_CREATED;
@@ -49,3 +53,21 @@ export class SetRemissionFilters {
constructor(public filterGroups: string[], public filterOptions: FilterOption[], public source: RemissionResourceType) {}
}
export class SetRemissionSource {
static readonly type = SET_REMISSION_SOURCE;
constructor(public source: RemissionResourceType) {}
}
export class SetRemissionTarget {
static readonly type = SET_REMISSION_TARGET;
constructor(public target: Side, public supplier: RemissionSupplier, public source: RemissionResourceType) {}
}
export class SetRemissionProducts {
static readonly type = SET_REMISSION_PRODUCTS;
constructor(public products: RemissionProduct[]) {}
}

View File

@@ -25,29 +25,43 @@ export class RemissionSelectors {
@Selector([RemissionState])
static getRemissionSelectedGroups(remissionState: RemissionStateModel) {
return (source: RemissionResourceType) => {
const remission = remissionState.remission;
if (remission) {
if (source === RemissionResourceType.Central) {
return remission.centralSelectedGroups;
} else {
return remission.overflowSelectedGroups;
}
const remission = remissionState.remission;
if (remission) {
if (remission.source === RemissionResourceType.Overflow) {
return remission.overflowSelectedGroups;
} else {
return remission.centralSelectedGroups;
}
};
}
}
@Selector([RemissionState])
static getRemissionSelectedOptions(remissionState: RemissionStateModel) {
return (source: RemissionResourceType) => {
const remission = remissionState.remission;
if (remission) {
if (source === RemissionResourceType.Central) {
return remission.centralSelectedOptions;
} else {
return remission.overflowSelectedOptions;
}
const remission = remissionState.remission;
if (remission) {
if (remission.source === RemissionResourceType.Overflow) {
return remission.overflowSelectedOptions;
} else {
return remission.centralSelectedOptions;
}
};
}
}
@Selector([RemissionState])
static getRemissiontarget(remissionState: RemissionStateModel) {
const remission = remissionState.remission;
if (remission) {
if (remission.source === RemissionResourceType.Overflow) {
return remission.overflowTarget;
} else {
return remission.centralTarget;
}
}
}
@Selector([RemissionState])
static getRemissionSource(remissionState: RemissionStateModel) {
const remission = remissionState.remission;
return remission.source;
}
}

View File

@@ -6,6 +6,7 @@ import { AppUserDataSync } from '../actions/app.actions';
import { isNullOrUndefined } from 'util';
import { RemissionResourceType } from '../../../modules/remission/models/remission-resource-type.model';
import { RemissionService } from '@isa/remission';
import { Side } from '@libs/ui/lib/small-double-choice-switch';
export class RemissionStateModel {
remission: Remission;
@@ -70,6 +71,47 @@ export class RemissionState {
this.syncApiState(remission);
}
@Action(actions.SetRemissionTarget)
setRemissionTarget(ctx: StateContext<RemissionStateModel>, { target, supplier, source }: actions.SetRemissionTarget) {
const state = ctx.getState();
const currentRemission = state.remission;
let remission: Remission;
if (source === RemissionResourceType.Central) {
remission = {
...currentRemission,
centralTarget: target,
};
} else {
remission = {
...currentRemission,
overflowTarget: target,
};
}
ctx.patchState({ remission });
this.syncApiState(remission);
}
@Action(actions.SetRemissionSource)
setRemissionSource(ctx: StateContext<RemissionStateModel>, { source }: actions.SetRemissionSource) {
const state = ctx.getState();
const currentRemission = state.remission;
const remission: Remission = {
...currentRemission,
source,
};
ctx.patchState({ remission });
this.syncApiState(remission);
}
@Action(actions.SetRemissionProducts)
setRemissionProducts(ctx: StateContext<RemissionStateModel>, { products }: actions.SetRemissionProducts) {
const state = ctx.getState();
const currentRemission = state.remission;
const remission: Remission = { ...currentRemission, remissionProducts: products };
ctx.patchState({ remission });
this.syncApiState(remission);
}
@Action(actions.InitRemissionState)
initRemissionState(ctx: StateContext<RemissionStateModel>) {
const state = ctx.getState();
@@ -79,6 +121,9 @@ export class RemissionState {
remissionProcessCreated: false,
remissionProcessCompleted: false,
remissionProcessStarted: false,
centralTarget: Side.LEFT,
overflowTarget: Side.LEFT,
source: RemissionResourceType.Central,
};
ctx.patchState({ remission });
this.syncApiState(remission);

View File

@@ -1,5 +1,5 @@
import { Component, OnInit, Input, Output, EventEmitter, OnDestroy } from '@angular/core';
import { Filter, FilterOptionGroup, FilterOption } from '@isa/remission';
import { Filter, FilterOptionGroup, FilterOption, RemissionService } from '@isa/remission';
import { fadeInAnimation } from '../../animations/fadeIn.animation';
import { growShrinkAnimation } from '../../animations/grow-shrink.animation';
import { RemissionResourceType } from '../../models/remission-resource-type.model';
@@ -42,7 +42,6 @@ export class RemissionFilterItemComponent implements OnInit, OnDestroy {
this.store
.select(RemissionSelectors.getRemissionSelectedGroups)
.pipe(
map(fn => fn(this.remissionResourceType)),
filter(data => !isNullOrUndefined(data)),
take(1)
)
@@ -53,7 +52,6 @@ export class RemissionFilterItemComponent implements OnInit, OnDestroy {
this.store
.select(RemissionSelectors.getRemissionSelectedOptions)
.pipe(
map(fn => fn(this.remissionResourceType)),
filter(data => !isNullOrUndefined(data)),
take(1)
)
@@ -67,7 +65,6 @@ export class RemissionFilterItemComponent implements OnInit, OnDestroy {
takeUntil(this.destroy$)
)
.subscribe(option => {
console.log(option);
this.removeOptionsFromSelected(option);
if (this.hasGrouping) {
this.uncheckGroupOfOption(option);
@@ -78,12 +75,25 @@ export class RemissionFilterItemComponent implements OnInit, OnDestroy {
this.remissionHelper.filtersClearedEvent$.pipe(takeUntil(this.destroy$)).subscribe(() => {
this.selectedOptions = [];
this.selectedGroups = [];
this.updateFilters();
});
this.remissionHelper.reApplyFilters$
.pipe(
filter(data => !isNullOrUndefined(data) && data === this.remissionResourceType),
takeUntil(this.destroy$)
)
.subscribe(() => this.updateFilters());
this.remissionHelper.closeFilters$.pipe(takeUntil(this.destroy$)).subscribe(() => {
this.expanded = false;
});
}
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 });
}
uncheckGroupOfOption(option: FilterOption) {

View File

@@ -7,8 +7,4 @@
display: flex;
justify-content: center;
}
.filter {
margin-right: 15px;
}
}

View File

@@ -1,8 +1,7 @@
import { Component, OnInit, Input, ChangeDetectorRef, ViewChildren, QueryList } from '@angular/core';
import { Component, OnInit, Input, ViewChildren, QueryList } from '@angular/core';
import { Filter, RemissionService } from '@isa/remission';
import { RemissionResourceType } from '../../models/remission-resource-type.model';
import { take } from 'rxjs/operators';
import { ViewRef_ } from '@angular/core/src/view';
import { RemissionFilterItemComponent } from '../remission-filter-item/remission-filter-item.component';
@Component({
@@ -17,25 +16,22 @@ export class RemissionFiltersComponent implements OnInit {
}
@ViewChildren('filterItem') filterItems: QueryList<RemissionFilterItemComponent>;
_remissionResourceType: RemissionResourceType;
remissionFilters$ = this.remissionService.getFilters();
filters: Filter[];
loadItems = true;
constructor(private remissionService: RemissionService, private cdrf: ChangeDetectorRef) {}
constructor(private remissionService: RemissionService) {}
ngOnInit() {}
subscriptions() {
this.loadItems = false;
this.remissionFilters$.pipe(take(1)).subscribe(this.remissionFiltersSubscription);
this.remissionService
.getFilters({ remissionSourceType: this._remissionResourceType })
.pipe(take(1))
.subscribe(this.remissionFiltersSubscription);
}
remissionFiltersSubscription = (remissionFilters: Filter[]) => {
// TODO: this will be removed when the get filters method will accept source target as parameter
if (this._remissionResourceType === RemissionResourceType.Overflow) {
this.filters = remissionFilters.filter(filter => filter.id === '421228ce');
} else {
this.filters = remissionFilters;
}
this.filters = remissionFilters;
this.loadItems = true;
};

View File

@@ -0,0 +1,3 @@
<p>
remission-list-card-loading works!
</p>

View File

@@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { RemissionListCardLoadingComponent } from './remission-list-card-loading.component';
describe('RemissionListCardLoadingComponent', () => {
let component: RemissionListCardLoadingComponent;
let fixture: ComponentFixture<RemissionListCardLoadingComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ RemissionListCardLoadingComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(RemissionListCardLoadingComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,12 @@
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-remission-list-card-loading',
templateUrl: './remission-list-card-loading.component.html',
styleUrls: ['./remission-list-card-loading.component.scss'],
})
export class RemissionListCardLoadingComponent implements OnInit {
constructor() {}
ngOnInit() {}
}

View File

@@ -0,0 +1,5 @@
<div class="card-container">
<div class="card-wrapper">
{{ product.name }}
</div>
</div>

View File

@@ -0,0 +1,14 @@
.card-container {
min-height: 200px;
margin-bottom: 10px;
border-radius: 5px;
background-color: #ffffff;
.card-wrapper {
padding-top: 22px;
padding-left: 24px;
padding-right: 24px;
padding-bottom: 16px;
// box-shadow: 0 0 18px 0 #b8b3b7;
}
}

View File

@@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { RemissionListCardComponent } from './remission-list-card.component';
describe('RemissionListCardComponent', () => {
let component: RemissionListCardComponent;
let fixture: ComponentFixture<RemissionListCardComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ RemissionListCardComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(RemissionListCardComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,14 @@
import { Component, OnInit, Input } from '@angular/core';
import { RemissionProduct } from '@isa/remission';
@Component({
selector: 'app-remission-list-card',
templateUrl: './remission-list-card.component.html',
styleUrls: ['./remission-list-card.component.scss'],
})
export class RemissionListCardComponent implements OnInit {
@Input() product: RemissionProduct;
constructor() {}
ngOnInit() {}
}

View File

@@ -0,0 +1,16 @@
<div class="result-container">
<ng-container>
<cdk-virtual-scroll-viewport itemSize="200" class="viewport" #scroller>
<div *cdkVirtualFor="let product of ds; let first = first; let last = last; let index = index">
<ng-container *ngIf="product != null; else loadingComponent">
<app-remission-list-card [product]="product"></app-remission-list-card>
</ng-container>
</div>
<ng-template #loadingComponent>
<div height="200">
loading
</div>
</ng-template>
</cdk-virtual-scroll-viewport>
</ng-container>
</div>

View File

@@ -0,0 +1,13 @@
.result-container {
height: 500px;
}
.viewport {
padding-bottom: 10px;
height: calc(100% - 10px);
width: 100%;
}
.cdk-virtual-scroll-content-wrapper {
min-width: 100%;
padding-top: 5px;
}

View File

@@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { RemissionListComponent } from './remission-list.component';
describe('RemissionListComponent', () => {
let component: RemissionListComponent;
let fixture: ComponentFixture<RemissionListComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ RemissionListComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(RemissionListComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,46 @@
import { Component, OnInit, Input, OnDestroy } from '@angular/core';
import { RemissionListDataSource } from './remission-list.datasource';
import { RemissionService } from '@isa/remission';
import { Store } from '@ngxs/store';
import { RemissionHelperService } from '../../services/remission-helper.service';
import { Subject } from 'rxjs';
import { takeUntil, filter } from 'rxjs/operators';
import { isNullOrUndefined } from 'util';
@Component({
selector: 'app-remission-list',
templateUrl: './remission-list.component.html',
styleUrls: ['./remission-list.component.scss'],
})
export class RemissionListComponent implements OnInit, OnDestroy {
remissionProcesessId: string;
ds: RemissionListDataSource;
destroy$ = new Subject();
constructor(private remisssionService: RemissionService, private store: Store, private remissionHelper: RemissionHelperService) {}
ngOnInit() {
this.subscriptions();
}
ngOnDestroy() {
this.destroy$.next();
}
subscriptions() {
this.remissionHelper.loadRemissionListProducts$
.pipe(
filter(data => !isNullOrUndefined(data)),
takeUntil(this.destroy$)
)
.subscribe(remissionProcessId => {
this.remissionProcesessId = remissionProcessId;
this.loadDataSource(remissionProcessId);
});
}
loadDataSource(remissionProcesessId) {
if (remissionProcesessId) {
this.ds = new RemissionListDataSource(this.remisssionService, this.remissionHelper, this.store, this.remissionProcesessId);
}
}
}

View File

@@ -0,0 +1,117 @@
import { DataSource, CollectionViewer } from '@angular/cdk/collections';
import { BehaviorSubject, Observable, Subject } from 'rxjs';
import { Store } from '@ngxs/store';
import { take, takeUntil, debounceTime } from 'rxjs/operators';
import { RemissionProduct, RemissionService } from '@isa/remission';
import { SetRemissionProducts } from 'apps/sales/src/app/core/store/actions/remission.actions';
import { RemissionHelperService } from '../../services/remission-helper.service';
export class RemissionListDataSource extends DataSource<RemissionProduct | undefined> {
private pageSize = 10;
private fetchedPages = new Set<number>();
private cachedData = Array.from<RemissionProduct>({ length: 10 });
private dataStream = new BehaviorSubject<(RemissionProduct | undefined)[]>(this.cachedData);
destroy$ = new Subject();
public loading = true;
public results = false;
public allHits = 0;
public firstLoad = true;
constructor(
private search: RemissionService,
private helper: RemissionHelperService,
private store: Store,
private remissionProcessId: string
) {
super();
}
connect(collectionViewer: CollectionViewer): Observable<(RemissionProduct | undefined)[]> {
collectionViewer.viewChange.pipe(takeUntil(this.destroy$)).subscribe(range => {
const startPage = this.getPageForIndex(range.start);
const endPage = this.getPageForIndex(range.end);
for (let i = startPage; i <= endPage; i++) {
if (this.firstLoad && i === 0) {
return;
}
this.fetchPage(i);
}
});
this.dataStream
.pipe(
takeUntil(this.destroy$),
debounceTime(1000)
)
.subscribe(i => {
this.store.dispatch(new SetRemissionProducts([...i]));
});
this.fetchPage(0);
return this.dataStream;
}
disconnect(): void {
this.destroy$.next();
}
public getPageForIndex(index: number): number {
return Math.floor(index / this.pageSize);
}
public getPrevItem(index: number) {
if (index < 1) {
return null;
}
if (!this.cachedData) {
return null;
}
return this.cachedData[index - 1];
}
public getNextItem(index: number) {
if (!index) {
return null;
}
if (!this.cachedData) {
return null;
}
return this.cachedData[index + 1];
}
private fetchPage(page: number): number {
if (page === 0) {
this.results = false;
}
if (this.fetchedPages.has(page)) {
return;
}
this.fetchedPages.add(page);
this.loading = true;
const remissionSearch$ = this.search.getRemissionProducts({ remissionProcessId: this.remissionProcessId });
remissionSearch$
.pipe(take(1))
.subscribe((result: { skip?: number; take?: number; hits?: number; items: RemissionProduct[]; completed: boolean }) => {
console.log('product results', result);
this.loading = false;
this.results = true;
const products = result && result.items ? result.items : [];
if (page === 0) {
this.cachedData = Array.from<RemissionProduct>({ length: result.hits });
this.allHits = result.hits;
this.helper.setRemissionListHits(this.allHits);
}
this.cachedData.splice(page * this.pageSize, this.pageSize, ...products);
this.dataStream.next(this.cachedData);
if (page === 0) {
// dispatch immediately on first page load
this.firstLoad = false;
this.store.dispatch(new SetRemissionProducts(this.cachedData));
}
});
}
}

View File

@@ -1,9 +1,9 @@
<div class="selected-filters" *ngIf="options">
<ng-container *ngFor="let option of options">
<div class="selected-option">
<span>{{ option.name }}</span>
<div>{{ option.name }}</div>
<lib-icon (click)="removeOption(option)" name="close-branch"></lib-icon>
</div>
</ng-container>
<span class="remove-all" (click)="clearAllFilter()" *ngIf="options.length > 0">Alle Filter entfernen</span>
<div class="remove-all" (click)="clearAllFilter()" *ngIf="options.length > 0">Alle Filter entfernen</div>
</div>

View File

@@ -4,24 +4,26 @@
margin-top: 17px;
justify-content: center;
span {
.selected-option {
font-size: 16px;
font-weight: bold;
color: #596470;
line-height: 2;
}
.selected-option {
padding-right: 40px;
padding-right: 13px;
display: flex;
lib-icon {
position: absolute;
margin-left: 12px;
margin-top: 7px;
margin-top: 2px;
cursor: pointer;
}
}
.remove-all {
font-size: 16px;
font-weight: bold;
color: #596470;
line-height: 2;
padding-left: 15px;
cursor: pointer;
}
}

View File

@@ -28,7 +28,6 @@ export class RemissionSelectedFilterItemsComponent implements OnInit, OnDestroy
this.store
.select(RemissionSelectors.getRemissionSelectedOptions)
.pipe(
map(fn => fn(this.remissionResourceType)),
filter(data => !isNullOrUndefined(data)),
takeUntil(this.destroy$)
)
@@ -38,7 +37,6 @@ export class RemissionSelectedFilterItemsComponent implements OnInit, OnDestroy
}
clearAllFilter() {
this.store.dispatch(new SetRemissionFilters([], [], this.remissionResourceType));
this.remissionHelper.clearFilters();
}

View File

@@ -26,5 +26,5 @@ export const RESOURCE_TYPE_SWITCH = <DoubleChoiceSwitch>{
unSelectedbackground: '#ffffff',
unSelectedText: '#000000',
},
isFirstSwitchedOn: false,
isFirstSwitchedOn: true,
};

View File

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

View File

@@ -1,4 +1,4 @@
<div class="remission-list-container">
<div class="remission-list-container" (scroll)="scrollHandler($event)">
<div class="headers" *ngIf="resourceTypeSwitch">
<div class="header-item resource-type">
<lib-double-choice-switch [model]="resourceTypeSwitch" (change)="resourceTypeChange($event)"></lib-double-choice-switch>
@@ -26,6 +26,7 @@
[rightValue]="suppliers.rightSupplier.name"
switchColor="#596470"
defaultBgColor="#cfd4d8"
(switch)="supplierUpdated($event)"
[selectedSide]="selectedSupplier"
></lib-small-double-choice-switch>
</div>
@@ -33,5 +34,19 @@
<div class="filters">
<app-remission-filters [remissionResourceType]="selectedRemissionResourceType"></app-remission-filters>
</div>
<div class="actions">
<div class="start-remission">
<app-button [primary]="true" (action)="startRemission()">Remission starten</app-button>
</div>
<div class="add-article">
<app-button (action)="addArticleToRemissionList()">Artikel hinzufügen</app-button>
</div>
</div>
</div>
<div class="list">
<div class="hits" *ngIf="remissionListHits">
<span>{{ remissionListHits }} Titel</span>
</div>
<app-remission-list></app-remission-list>
</div>
</div>

View File

@@ -66,7 +66,6 @@
div {
width: 221px;
margin-right: 23px;
}
}
@@ -76,5 +75,38 @@
justify-content: center;
margin-top: 22px;
}
.actions {
display: flex;
flex-direction: column;
justify-content: center;
.start-remission,
.add-article {
display: flex;
justify-content: center;
}
.start-remission {
padding-top: 45px;
}
.add-article {
padding-top: 27px;
}
}
}
.list {
.hits {
display: flex;
justify-content: flex-end;
font-size: 15px;
color: #596470;
font-weight: 500;
margin-bottom: 15px;
}
margin-top: 40px;
}
}

View File

@@ -1,33 +1,51 @@
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Component, OnInit, OnDestroy, HostListener, AfterViewInit } from '@angular/core';
import { Subject, Observable } from 'rxjs';
import { takeUntil, filter, take, tap, switchMap, catchError } from 'rxjs/operators';
import { takeUntil, filter, take, tap, switchMap, catchError, delay } from 'rxjs/operators';
import { DoubleChoiceSwitch, DoubleChoiceSwitchColor } from '@libs/ui';
import { RemissionResourceType } from '../../models/remission-resource-type.model';
import { ResourceTypeSpecificModel } from '../../models/resource-type-specific-model.model';
import { CapacityTypeClientWrapper } from '../../models/capacity-type-client-wrapper.model';
import { Side } from '@libs/ui/lib/small-double-choice-switch';
import { RemissionSupplier, RemissionService, RemissionSourceType, RemissionProcess, CapacityType, Filter } from '@isa/remission';
import {
RemissionSupplier,
RemissionService,
RemissionSourceType,
RemissionProcess,
CapacityType,
Filter,
FilterOption,
RemissionFilter,
} from '@isa/remission';
import { Select, Store } from '@ngxs/store';
import { RemissionSelectors } from 'apps/sales/src/app/core/store/selectors/remission.selectors';
import { RemissionProcessStatuses } from 'apps/sales/src/app/core/models/remission-process-statuses.model';
import { RESOURCE_TYPE_SPECIFIC_MODEL_OPTIONS, RESOURCE_TYPE_SWITCH } from '../../constants/remission.constants';
import { isNullOrUndefined } from 'util';
import { SetRemissionProcess, SetRemissionCreated } from 'apps/sales/src/app/core/store/actions/remission.actions';
import {
SetRemissionProcess,
SetRemissionCreated,
SetRemissionFilters,
SetRemissionSource,
SetRemissionTarget,
} from 'apps/sales/src/app/core/store/actions/remission.actions';
import { RemissionHelperService } from '../../services/remission-helper.service';
import { UpdateFilter } from '../../models/update-filter.model';
@Component({
selector: 'app-remission-list-create',
templateUrl: './remission-list-create.component.html',
styleUrls: ['./remission-list-create.component.scss'],
})
export class RemissionListCreateComponent implements OnInit, OnDestroy {
export class RemissionListCreateComponent implements OnInit, OnDestroy, AfterViewInit {
@Select(RemissionSelectors.getRemissionProcessStatuses) remissionProcessStatuses$: Observable<RemissionProcessStatuses>;
@Select(RemissionSelectors.getRemissionProcess) currentRemissionProcess$: Observable<RemissionProcess>;
@Select(RemissionSelectors.getRemissionSource) currentRemissionSource$: Observable<RemissionResourceType>;
@Select(RemissionSelectors.getRemissiontarget) currentRemissionTarget$: Observable<Side>;
remissionProcess$: Observable<RemissionProcess>;
remissionSuppliers$ = this.remissionService.getRemissionTargets();
remissionSources$ = this.remissionService.getRemissionSources();
destroy$ = new Subject();
selectedRemissionResourceType: RemissionResourceType = RemissionResourceType.Overflow;
selectedRemissionResourceType: RemissionResourceType = RemissionResourceType.Central;
selectedResourceTypeSpecificModel: ResourceTypeSpecificModel = RESOURCE_TYPE_SPECIFIC_MODEL_OPTIONS[this.selectedRemissionResourceType];
capacities: CapacityTypeClientWrapper[];
selectedSupplier: Side = Side.LEFT;
@@ -35,12 +53,16 @@ export class RemissionListCreateComponent implements OnInit, OnDestroy {
remissionProcess: RemissionProcess;
resourceTypeSwitch = RESOURCE_TYPE_SWITCH;
remissionProcessStatuses: RemissionProcessStatuses;
constructor(private remissionService: RemissionService, private store: Store) {}
processNeedsToBeRestoredFromCache = false;
remissionListHits: number;
constructor(private remissionService: RemissionService, private store: Store, private remissionHelper: RemissionHelperService) {}
ngOnInit() {
this.subscriptions();
}
ngAfterViewInit() {}
subscriptions() {
this.remissionSuppliers$
.pipe(
@@ -48,9 +70,58 @@ export class RemissionListCreateComponent implements OnInit, OnDestroy {
filter(this.remissionSuppliersFilter)
)
.subscribe(this.remissionSuppliersSubscriptionHandler);
this.remissionSubsribtionInitialisation();
this.remissionHelper.filtersUpdated$
.pipe(
takeUntil(this.destroy$),
filter(data => !isNullOrUndefined(data))
)
.subscribe(this.filtersUpdatedHandler);
this.remissionHelper.remissionListHits$
.pipe(
delay(0),
filter(data => !isNullOrUndefined(data)),
takeUntil(this.destroy$)
)
.subscribe(hits => {
console.log(hits);
this.remissionListHits = hits;
});
}
loadCurrentRemissionSource() {
this.currentRemissionSource$
.pipe(
filter(data => !isNullOrUndefined(data)),
take(1)
)
.subscribe(this.currentRemissionSourcesSubscriptionHandler);
}
currentRemissionSourcesSubscriptionHandler = (source: RemissionResourceType) => {
this.selectedRemissionResourceType = source;
this.selectedResourceTypeSpecificModel = RESOURCE_TYPE_SPECIFIC_MODEL_OPTIONS[source];
this.resourceTypeSwitch.isFirstSwitchedOn = source === RemissionResourceType.Central;
this.remissionHelper.updateFilters({ source: source });
};
loadCurrentRemissionTarget() {
this.currentRemissionTarget$
.pipe(
filter(data => !isNullOrUndefined(data)),
take(1)
)
.subscribe(this.currentRemissionTargetSubscriptionHandler);
}
currentRemissionTargetSubscriptionHandler = (side: Side) => {
this.selectedSupplier = side;
this.remissionHelper.updateFilters({ target: side === Side.LEFT ? this.suppliers.leftSupplier : this.suppliers.rightSupplier });
};
remissionSubsribtionInitialisation() {
this.loadCurrentRemissionProcessStatuses().then(remissionProcessStatuses => {
this.remissionProcessStatuses = remissionProcessStatuses;
@@ -59,6 +130,35 @@ export class RemissionListCreateComponent implements OnInit, OnDestroy {
});
}
filtersUpdatedHandler = (updates: UpdateFilter) => {
const changes = <RemissionFilter>{
skip: 0,
take: 10,
};
if (updates.filterId && updates.options) {
changes.filter = { [updates.filterId]: [...updates.options.map(op => op.id)] };
}
if (updates.source) {
changes.source = updates.source;
}
if (updates.target) {
changes.target = updates.target;
}
console.log(changes);
if (!this.remissionProcess) {
return;
}
this.remissionService
.updateRemissionFilter({
remissionProcessId: this.remissionProcess.id,
changes: changes,
})
.toPromise();
};
remissionCreatedSuccesfullyHandler = (remissionProcess: RemissionProcess) => {
if (remissionProcess) {
this.remissionProcess = remissionProcess;
@@ -77,24 +177,29 @@ export class RemissionListCreateComponent implements OnInit, OnDestroy {
}
continueProcess() {
console.log('process continued');
return this.loadCurrentRemissionProcess().pipe(
take(1),
switchMap(remissionProcess => {
return this.remissionService.continueProcess(remissionProcess);
}),
catchError(error => {
// TODO: uncomment error loging
// console.error(error);
return this.createProcess();
})
catchError(this.continueProcessErrorHandler)
);
}
continueProcessErrorHandler = (error: any) => {
console.error(error);
this.processNeedsToBeRestoredFromCache = true;
return this.createProcess();
};
createProcess() {
console.log('process created');
return this.remissionService.createProcess().pipe(tap(this.remissionCreatedSuccesfullyHandler));
}
loadCurrentRemissionProcess() {
return this.currentRemissionProcess$.pipe(filter(data => !isNullOrUndefined(data)));
return this.currentRemissionProcess$.pipe(filter(data => !isNullOrUndefined(data), take(1)));
}
remissionSourcesFilter = (remissionSources: RemissionSourceType[]) => {
@@ -107,17 +212,33 @@ export class RemissionListCreateComponent implements OnInit, OnDestroy {
remissionSuppliersSubscriptionHandler = (remissionSuppliers: RemissionSupplier[]) => {
this.suppliers = {
leftSupplier: remissionSuppliers[0],
rightSupplier: remissionSuppliers[1],
leftSupplier: remissionSuppliers[1],
rightSupplier: remissionSuppliers[0],
};
};
remisionProcessSubscriptionHandler = (remissionProcess: RemissionProcess) => {
this.remissionProcess = remissionProcess;
(!isNullOrUndefined(remissionProcess.capacities)).ifTrue(() => this.capacitiesBinder(remissionProcess.capacities));
this.processNeedsToBeRestoredFromCache.ifTrue(() => this.restoreProcess());
this.selectedRemissionResourceType =
remissionProcess.filter.source === 'zentral' ? RemissionResourceType.Central : RemissionResourceType.Overflow;
this.resourceTypeSwitch.isFirstSwitchedOn = this.selectedRemissionResourceType === RemissionResourceType.Central;
this.selectedResourceTypeSpecificModel = RESOURCE_TYPE_SPECIFIC_MODEL_OPTIONS[this.selectedRemissionResourceType];
this.selectedSupplier = remissionProcess.filter.target.name === this.suppliers.leftSupplier.name ? Side.LEFT : Side.RIGHT;
this.store.dispatch(new SetRemissionProcess(remissionProcess));
this.remissionHelper.loadRemissionListProducts(remissionProcess.id);
// TODO: remove console logging
console.log('remission subscribed', remissionProcess);
};
restoreProcess = () => {
this.processNeedsToBeRestoredFromCache = false;
this.loadCurrentRemissionSource();
this.loadCurrentRemissionTarget();
this.remissionHelper.reApplyFilters(this.selectedRemissionResourceType);
};
capacitiesBinder = (capacities: CapacityType[]) => {
this.capacities = [];
capacities.forEach(capacity => {
@@ -135,6 +256,37 @@ export class RemissionListCreateComponent implements OnInit, OnDestroy {
this.resourceTypeSwitch = model;
this.selectedRemissionResourceType = model.isFirstSwitchedOn ? RemissionResourceType.Central : RemissionResourceType.Overflow;
this.selectedResourceTypeSpecificModel = RESOURCE_TYPE_SPECIFIC_MODEL_OPTIONS[this.selectedRemissionResourceType];
this.store.dispatch(new SetRemissionSource(this.selectedRemissionResourceType));
this.remissionHelper.updateFilters({ source: this.selectedRemissionResourceType });
this.loadCurrentRemissionTarget();
this.remissionHelper.reApplyFilters(this.selectedRemissionResourceType);
}
supplierUpdated(side: Side) {
this.selectedSupplier = side;
this.store.dispatch(
new SetRemissionTarget(
side,
side === Side.LEFT ? this.suppliers.leftSupplier : this.suppliers.rightSupplier,
this.selectedRemissionResourceType
)
);
this.remissionHelper.updateFilters({ target: side === Side.LEFT ? this.suppliers.leftSupplier : this.suppliers.rightSupplier });
}
startRemission() {
// TODO: Implement method
throw new Error('(startRemission) Method not implemented');
}
addArticleToRemissionList() {
// TODO: Implement method
throw new Error('(addArticleToRemissionList) Method not implemented');
}
@HostListener('window:scroll', ['$event'])
scrollHandler(event) {
this.remissionHelper.closeFilters();
}
ngOnDestroy() {

View File

@@ -7,10 +7,23 @@ import { DoubleChoiceSwitchModule, ProgressBarModule, IconModule, ButtonModule }
import { SmallDoubleChoiceSwitchModule } from '@libs/ui/lib/small-double-choice-switch';
import { RemissionFiltersComponent } from './components/remission-filters/remission-filters.component';
import { RemissionFilterItemComponent } from './components/remission-filter-item/remission-filter-item.component';
// tslint:disable-next-line: max-line-length
import { RemissionSelectedFilterItemsComponent } from './components/remission-selected-filter-items/remission-selected-filter-items.component';
import { RemissionListComponent } from './components/remission-list/remission-list.component';
import { RemissionListCardComponent } from './components/remission-list-card/remission-list-card.component';
import { RemissionListCardLoadingComponent } from './components/remission-list-card-loading/remission-list-card-loading.component';
import { ScrollingModule } from '@angular/cdk/scrolling';
@NgModule({
declarations: [RemissionListCreateComponent, RemissionFiltersComponent, RemissionFilterItemComponent, RemissionSelectedFilterItemsComponent],
declarations: [
RemissionListCreateComponent,
RemissionFiltersComponent,
RemissionFilterItemComponent,
RemissionSelectedFilterItemsComponent,
RemissionListComponent,
RemissionListCardComponent,
RemissionListCardLoadingComponent,
],
imports: [
CommonModule,
RemissionClientRoutingModule,
@@ -19,6 +32,7 @@ import { RemissionSelectedFilterItemsComponent } from './components/remission-se
SmallDoubleChoiceSwitchModule,
IconModule,
ButtonModule,
ScrollingModule,
],
})
export class RemissionClientModule {}

View File

@@ -1,6 +1,8 @@
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';
import { Subject, BehaviorSubject } from 'rxjs';
import { FilterOption } from '@isa/remission';
import { UpdateFilter } from '../models/update-filter.model';
import { RemissionResourceType } from '../models/remission-resource-type.model';
@Injectable({
providedIn: 'root',
@@ -8,8 +10,18 @@ import { FilterOption } from '@isa/remission';
export class RemissionHelperService {
filteOptionsDeleteEvents$ = new Subject<FilterOption>();
filtersClearedEvent$ = new Subject();
closeFilters$ = new Subject();
loadRemissionListProducts$ = new Subject<string>();
filtersUpdated$ = new Subject<UpdateFilter>();
reApplyFilters$ = new BehaviorSubject<RemissionResourceType>(null);
remissionListHits$ = new BehaviorSubject<number>(null);
constructor() {}
public deleteFilterOption = (option: FilterOption) => this.filteOptionsDeleteEvents$.next(option);
public clearFilters = () => this.filtersClearedEvent$.next();
public closeFilters = () => this.closeFilters$.next();
public updateFilters = (changes: UpdateFilter) => this.filtersUpdated$.next(changes);
public reApplyFilters = (source: RemissionResourceType) => this.reApplyFilters$.next(source);
public loadRemissionListProducts = (remissionProcessId: string) => this.loadRemissionListProducts$.next(remissionProcessId);
public setRemissionListHits = (hits: number) => this.remissionListHits$.next(hits);
}

6
package-lock.json generated
View File

@@ -1039,9 +1039,9 @@
}
},
"@isa/remission": {
"version": "0.1.1",
"resolved": "https://pkgs.dev.azure.com/hugendubel/_packaging/hugendubel/npm/registry/@isa/remission/-/remission-0.1.1.tgz",
"integrity": "sha1-/AQheJAheH7YcMtrmKCNTVFbo14=",
"version": "0.1.2",
"resolved": "https://pkgs.dev.azure.com/hugendubel/_packaging/hugendubel/npm/registry/@isa/remission/-/remission-0.1.2.tgz",
"integrity": "sha1-+NzVCbHooC+NWxVLZAJ4hKm7Hys=",
"requires": {
"deep-equal": "^1.1.0",
"tslib": "^1.9.0",

View File

@@ -27,7 +27,7 @@
"@angular/pwa": "^0.13.4",
"@angular/router": "~7.2.12",
"@angular/service-worker": "~7.2.12",
"@isa/remission": "^0.1.1",
"@isa/remission": "^0.1.2",
"@ngxs/store": "^3.4.1",
"@types/faker": "^4.1.5",
"@zxing/ngx-scanner": "^1.3.0",