Shelf State Erweiterung

This commit is contained in:
Lorenz Hilpert
2020-06-24 12:17:06 +02:00
parent 4ab9603238
commit 98ccc48424
8 changed files with 157 additions and 12 deletions

View File

@@ -13,7 +13,7 @@ export class BranchService {
constructor(private checkoutService: StoreCheckoutService, private orderService: OrderService, private ssoService: SsoService) {}
getCurrentBranchNumber() {
this.ssoService.getClaimByKey('branch_no');
return this.ssoService.getClaimByKey('branch_no');
}
searchBranches(input: string, skip: number, take: number): Observable<BranchDTO[]> {

View File

@@ -1,4 +1,9 @@
import { OrderItemListItemDTO } from '@swagger/oms';
export interface SearchProcess {
id: number; // Porzess ID;
input?: string;
results: OrderItemListItemDTO[];
hits?: number;
fetching: boolean;
}

View File

@@ -1,4 +1,5 @@
import { createAction, props } from '@ngrx/store';
import { OrderItemListItemDTO, StrictHttpResponse, ListResponseArgsOfOrderItemListItemDTO } from '@swagger/oms';
const prefix = '[CUSTOMER] [SHELF] [SEARCH]';
@@ -7,3 +8,18 @@ export const addSearchProcess = createAction(`${prefix} Add Search Process`, pro
export const removeSearchProcess = createAction(`${prefix} Remove Search Process`, props<{ id: number }>());
export const setInput = createAction(`${prefix} Search Input`, props<{ id: number; input: string }>());
export const clearResults = createAction(`${prefix} Clear Results`, props<{ id: number }>());
export const addResults = createAction(`${prefix} Add Results`, props<{ id: number; results: OrderItemListItemDTO[] }>());
export const clearHits = createAction(`${prefix} Clear Hits`, props<{ id: number }>());
export const setHits = createAction(`${prefix} Set Hits`, props<{ id: number; hits: number }>());
export const fetchResults = createAction(`${prefix} Fetch Results`, props<{ id: number }>());
export const fetchResultsDone = createAction(
`${prefix} Fetch Results Done`,
props<{ id: number; response: StrictHttpResponse<ListResponseArgsOfOrderItemListItemDTO> }>()
);

View File

@@ -1,16 +1,62 @@
import { Injectable } from '@angular/core';
import { Store } from '@ngrx/store';
import { Actions, createEffect, ofType } from '@ngrx/effects';
import { Actions as NgxsActions, ofActionDispatched } from '@ngxs/store';
import { AddProcess, DeleteProcess } from 'apps/sales/src/app/core/store/actions/process.actions';
import * as actions from './search.actions';
import { switchMap, withLatestFrom, catchError, map, flatMap } from 'rxjs/operators';
import { OrderService, StrictHttpResponse, ListResponseArgsOfOrderItemListItemDTO } from '@swagger/oms';
import { BranchService } from '@sales/core-services';
import { SearchStateFacade } from './search.facade';
import { of, NEVER } from 'rxjs';
@Injectable()
export class SearchEffects {
constructor(private ngxsActions$: NgxsActions, private store: Store<any>) {
constructor(
private actions$: Actions,
private ngxsActions$: NgxsActions,
private store: Store<any>,
private searchStateFacade: SearchStateFacade,
private orderService: OrderService,
private branchService: BranchService
) {
this.initAddProcess();
this.initRemoveProcess();
}
fetchResults$ = createEffect(() =>
this.actions$.pipe(
ofType(actions.fetchResults),
withLatestFrom(((a) => this.searchStateFacade.getProcess$(a.id))()),
switchMap(([a, process]) =>
this.orderService
.OrderWarenausgabeResponse({
branchNumber: this.branchService.getCurrentBranchNumber(),
input: process.input,
skip: process.hits || 0,
take: 20,
})
.pipe(
catchError((err) => of<StrictHttpResponse<ListResponseArgsOfOrderItemListItemDTO>>(err)),
map((response) => actions.fetchResultsDone({ id: a.id, response }))
)
)
)
);
fetchResultsDone$ = createEffect(() =>
this.actions$.pipe(
ofType(actions.fetchResultsDone),
flatMap((action) => {
if (action.response.ok) {
const result = action.response.body;
return [actions.setHits({ id: action.id, hits: result.hits }), actions.addResults({ id: action.id, results: result.result })];
}
return NEVER;
})
)
);
initAddProcess() {
this.ngxsActions$.pipe(ofActionDispatched(AddProcess)).subscribe((action) => {
if (action instanceof AddProcess) {

View File

@@ -2,21 +2,60 @@ import { Injectable } from '@angular/core';
import { Store } from '@ngrx/store';
import { Store as NgxsStore } from '@ngxs/store';
import * as actions from './search.actions';
import * as selectors from './search.selectors';
import { SharedSelectors } from 'apps/sales/src/app/core/store/selectors/shared.selectors';
import { map, first } from 'rxjs/operators';
import { map, first, switchMap } from 'rxjs/operators';
@Injectable({ providedIn: 'root' })
export class SearchStateFacade {
get process$() {
return this.getProcessId$().pipe(switchMap((id) => this.getProcess$(id)));
}
get input$() {
return this.getProcessId$().pipe(switchMap((id) => this.getInput$(id)));
}
get results$() {
return this.getProcessId$().pipe(switchMap((id) => this.getResults$(id)));
}
get hits$() {
return this.getProcessId$().pipe(switchMap((id) => this.getHits$(id)));
}
get fetching$() {
return this.getProcessId$().pipe(switchMap((id) => this.getFetching$(id)));
}
constructor(private store: Store<any>, private ngxsStore: NgxsStore) {}
getProcessId$() {
return this.ngxsStore.select(SharedSelectors.getCurrentProcess).pipe(map((currentProcess) => currentProcess.id));
}
getProcessId() {
return this.ngxsStore
.select(SharedSelectors.getCurrentProcess)
.pipe(
map((currentProcess) => currentProcess.id),
first()
)
.toPromise();
return this.getProcessId$().pipe(first()).toPromise();
}
getProcess$(id: number) {
return this.store.select(selectors.selectProcess, id);
}
getInput$(id: number) {
return this.store.select(selectors.selectInput, id);
}
getResults$(id: number) {
return this.store.select(selectors.selectResults, id);
}
getHits$(id: number) {
return this.store.select(selectors.selectHits, id);
}
getFetching$(id: number) {
return this.store.select(selectors.selectFetching, id);
}
async setInput(input: string, id?: number) {
@@ -28,4 +67,12 @@ export class SearchStateFacade {
this.store.dispatch(actions.setInput({ input, id: processId }));
}
async fetchResults(id?: number) {
let processId = id;
if (typeof processId !== 'number') {
processId = await this.getProcessId();
}
this.store.dispatch(actions.fetchResults({ id: processId }));
}
}

View File

@@ -1,10 +1,20 @@
import { createReducer, Action, on } from '@ngrx/store';
import { INITIAL_SEARCH_STATE, SearchState, searchStateAdapter } from './search.state';
import { INITIAL_SEARCH_STATE, SearchState, searchStateAdapter, INITIAL_SEARCH_PROCESS } from './search.state';
import * as actions from './search.actions';
const _searchReducer = createReducer(
INITIAL_SEARCH_STATE,
on(actions.addSearchProcess, (s, a) => searchStateAdapter.addOne({ id: a.id }, s))
on(actions.addSearchProcess, (s, a) => searchStateAdapter.addOne({ ...INITIAL_SEARCH_PROCESS, id: a.id }, s)),
on(actions.removeSearchProcess, (s, a) => searchStateAdapter.removeOne(a.id, s)),
on(actions.setInput, (s, a) => searchStateAdapter.updateOne({ id: a.id, changes: { input: a.input } }, s)),
on(actions.clearResults, (s, a) => searchStateAdapter.updateOne({ id: a.id, changes: { results: [] } }, s)),
on(actions.addResults, (s, a) =>
searchStateAdapter.updateOne({ id: a.id, changes: { results: [...s.entities[a.id].results, ...a.results] } }, s)
),
on(actions.clearHits, (s, a) => searchStateAdapter.updateOne({ id: a.id, changes: { hits: undefined } }, s)),
on(actions.setHits, (s, a) => searchStateAdapter.updateOne({ id: a.id, changes: { hits: a.hits } }, s)),
on(actions.fetchResults, (s, a) => searchStateAdapter.updateOne({ id: a.id, changes: { fetching: true } }, s)),
on(actions.fetchResultsDone, (s, a) => searchStateAdapter.updateOne({ id: a.id, changes: { fetching: false } }, s))
);
export function searchReducer(state: SearchState, action: Action) {

View File

@@ -1,4 +1,19 @@
import { createSelector } from '@ngrx/store';
import { selectShelfState } from '../shelf.selectors';
import { searchStateAdapter } from './search.state';
import { Dictionary } from '@ngrx/entity';
import { SearchProcess } from './defs';
export const selectSearchState = createSelector(selectShelfState, (s) => s.search);
const { selectEntities } = searchStateAdapter.getSelectors(selectSearchState);
export const selectProcess = createSelector(selectEntities, (entities: Dictionary<SearchProcess>, id: number) => entities[id]);
export const selectInput = createSelector(selectEntities, (entities: Dictionary<SearchProcess>, id: number) => entities[id].input);
export const selectResults = createSelector(selectEntities, (entities: Dictionary<SearchProcess>, id: number) => entities[id].results);
export const selectHits = createSelector(selectEntities, (entities: Dictionary<SearchProcess>, id: number) => entities[id].hits);
export const selectFetching = createSelector(selectEntities, (entities: Dictionary<SearchProcess>, id: number) => entities[id].fetching);

View File

@@ -8,3 +8,9 @@ export const searchStateAdapter = createEntityAdapter<SearchProcess>();
export const INITIAL_SEARCH_STATE: SearchState = {
...searchStateAdapter.getInitialState(),
};
export const INITIAL_SEARCH_PROCESS: SearchProcess = {
id: undefined,
results: [],
fetching: false,
};