@verisoft/store 18.1.0 → 18.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.json +43 -43
- package/README.md +7 -7
- package/jest.config.ts +22 -22
- package/ng-package.json +7 -7
- package/package.json +13 -12
- package/project.json +36 -36
- package/src/index.ts +12 -9
- package/src/lib/binding-state/binding.actions.ts +76 -0
- package/src/lib/binding-state/binding.effects.ts +472 -0
- package/src/lib/detail-state/detail.actions.ts +89 -63
- package/src/lib/detail-state/detail.effects.ts +283 -131
- package/src/lib/detail-state/detail.models.ts +42 -32
- package/src/lib/detail-state/detail.reducer.ts +147 -122
- package/src/lib/table-state/actions.ts +92 -92
- package/src/lib/table-state/effects.ts +100 -100
- package/src/lib/table-state/models.ts +19 -19
- package/src/lib/table-state/reducers.ts +126 -126
- package/src/test-setup.ts +8 -8
- package/tsconfig.json +29 -29
- package/tsconfig.lib.json +17 -17
- package/tsconfig.lib.prod.json +9 -9
- package/tsconfig.spec.json +16 -16
|
@@ -1,122 +1,147 @@
|
|
|
1
|
-
import { ActionCreator, createReducer, on, ReducerTypes } from '@ngrx/store';
|
|
2
|
-
import {
|
|
3
|
-
createInitDetailAction,
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
formState,
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
),
|
|
73
|
-
|
|
74
|
-
on(
|
|
75
|
-
return {
|
|
76
|
-
...state,
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
}
|
|
112
|
-
}),
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
1
|
+
import { ActionCreator, createReducer, on, ReducerTypes } from '@ngrx/store';
|
|
2
|
+
import {
|
|
3
|
+
createInitDetailAction,
|
|
4
|
+
createInitNewDetailAction,
|
|
5
|
+
createLoadDetailFailureAction,
|
|
6
|
+
createLoadDetailSuccessAction,
|
|
7
|
+
createResetStateAction,
|
|
8
|
+
createSaveDetailAction,
|
|
9
|
+
createSaveDetailFailureAction,
|
|
10
|
+
createSaveDetailSuccessAction,
|
|
11
|
+
createUpdateDetailAction,
|
|
12
|
+
createUpdateDetailSetErrorsAction,
|
|
13
|
+
createUpdateFormStateAction,
|
|
14
|
+
} from './detail.actions';
|
|
15
|
+
import {
|
|
16
|
+
DetailState,
|
|
17
|
+
INITIAL_DETAIL_STATE,
|
|
18
|
+
INITIAL_SAVE_ITEM_STATE,
|
|
19
|
+
} from './detail.models';
|
|
20
|
+
|
|
21
|
+
export function createDetailReducers<
|
|
22
|
+
T = any,
|
|
23
|
+
TState extends DetailState<T> = DetailState<T>
|
|
24
|
+
>(
|
|
25
|
+
detailRepository: string,
|
|
26
|
+
initialState: TState = INITIAL_DETAIL_STATE as unknown as TState,
|
|
27
|
+
...ons: ReducerTypes<TState, readonly ActionCreator[]>[]
|
|
28
|
+
) {
|
|
29
|
+
return createReducer(
|
|
30
|
+
initialState,
|
|
31
|
+
on(createInitDetailAction(detailRepository), (state) => {
|
|
32
|
+
return {
|
|
33
|
+
...state,
|
|
34
|
+
loaded: false,
|
|
35
|
+
error: null,
|
|
36
|
+
};
|
|
37
|
+
}),
|
|
38
|
+
|
|
39
|
+
on(createInitNewDetailAction(detailRepository), (state) => {
|
|
40
|
+
return {
|
|
41
|
+
...state,
|
|
42
|
+
loaded: false,
|
|
43
|
+
error: null,
|
|
44
|
+
};
|
|
45
|
+
}),
|
|
46
|
+
|
|
47
|
+
on(createLoadDetailSuccessAction(detailRepository), (state, { item }) => {
|
|
48
|
+
return {
|
|
49
|
+
...state,
|
|
50
|
+
loaded: true,
|
|
51
|
+
item,
|
|
52
|
+
};
|
|
53
|
+
}),
|
|
54
|
+
|
|
55
|
+
on(createLoadDetailFailureAction(detailRepository), (state, { error }) => {
|
|
56
|
+
return {
|
|
57
|
+
...state,
|
|
58
|
+
loaded: true,
|
|
59
|
+
error,
|
|
60
|
+
};
|
|
61
|
+
}),
|
|
62
|
+
|
|
63
|
+
on(createUpdateDetailAction(detailRepository), (state, { item }) => {
|
|
64
|
+
return {
|
|
65
|
+
...state,
|
|
66
|
+
item,
|
|
67
|
+
formState: {
|
|
68
|
+
dirty: true,
|
|
69
|
+
valid: state.formState?.valid ?? true,
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
}),
|
|
73
|
+
|
|
74
|
+
on(createUpdateDetailSetErrorsAction(detailRepository), (state, { error }) => {
|
|
75
|
+
return {
|
|
76
|
+
...state,
|
|
77
|
+
backendValidationErrors: error
|
|
78
|
+
}
|
|
79
|
+
}),
|
|
80
|
+
|
|
81
|
+
on(
|
|
82
|
+
createUpdateFormStateAction(detailRepository),
|
|
83
|
+
(state, { formState }) => {
|
|
84
|
+
return {
|
|
85
|
+
...state,
|
|
86
|
+
formState,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
),
|
|
90
|
+
|
|
91
|
+
on(createSaveDetailSuccessAction(detailRepository), (state) => {
|
|
92
|
+
return {
|
|
93
|
+
...state,
|
|
94
|
+
formState: {
|
|
95
|
+
dirty: false,
|
|
96
|
+
valid: state.formState?.valid ?? true,
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
}),
|
|
100
|
+
|
|
101
|
+
on(createResetStateAction(detailRepository), () => {
|
|
102
|
+
return {
|
|
103
|
+
...(initialState as any),
|
|
104
|
+
};
|
|
105
|
+
}),
|
|
106
|
+
|
|
107
|
+
on(createSaveDetailFailureAction(detailRepository), (state, { error }) => {
|
|
108
|
+
return {
|
|
109
|
+
...state,
|
|
110
|
+
backendValidationErrors: error.error
|
|
111
|
+
}
|
|
112
|
+
}),
|
|
113
|
+
...ons
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export function createSaveDetailReducers(
|
|
118
|
+
detailRepository: string,
|
|
119
|
+
initialState = INITIAL_SAVE_ITEM_STATE
|
|
120
|
+
) {
|
|
121
|
+
return createReducer(
|
|
122
|
+
initialState,
|
|
123
|
+
|
|
124
|
+
on(createSaveDetailAction(detailRepository), (state) => {
|
|
125
|
+
return {
|
|
126
|
+
...state,
|
|
127
|
+
saveInProgress: true,
|
|
128
|
+
};
|
|
129
|
+
}),
|
|
130
|
+
|
|
131
|
+
on(createSaveDetailSuccessAction(detailRepository), (state, { item }) => {
|
|
132
|
+
return {
|
|
133
|
+
...state,
|
|
134
|
+
item,
|
|
135
|
+
saveInProgress: false,
|
|
136
|
+
};
|
|
137
|
+
}),
|
|
138
|
+
|
|
139
|
+
on(createSaveDetailFailureAction(detailRepository), (state, { error }) => {
|
|
140
|
+
return {
|
|
141
|
+
...state,
|
|
142
|
+
error,
|
|
143
|
+
saveInProgress: false,
|
|
144
|
+
};
|
|
145
|
+
})
|
|
146
|
+
);
|
|
147
|
+
}
|
|
@@ -1,93 +1,93 @@
|
|
|
1
|
-
import { createAction, props } from '@ngrx/store';
|
|
2
|
-
import { Page, Sort } from '@verisoft/core';
|
|
3
|
-
|
|
4
|
-
enum TablePageAction {
|
|
5
|
-
GET_PAGE = 'Get page',
|
|
6
|
-
CREATE_STATIC_FILTER = 'Create static filter',
|
|
7
|
-
DATA_LOAD_SUCCESS = 'Data load success',
|
|
8
|
-
DATA_LOAD_ERROR = 'Data load error',
|
|
9
|
-
REFRESH_PAGE = 'Refresh page',
|
|
10
|
-
FILTER_PAGE = 'Filter page',
|
|
11
|
-
CHANGE_PAGE_SIZE = 'Change page size',
|
|
12
|
-
SORT_PAGE = 'Sort page',
|
|
13
|
-
DESTROY = 'Destroy',
|
|
14
|
-
SELECT_ITEMS = 'Select items',
|
|
15
|
-
REMOVE_RANGE = 'Remove range',
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export function createGetPageTableAction<T = any>(tableRepository: string) {
|
|
19
|
-
return createAction(
|
|
20
|
-
`${tableRepository} ${TablePageAction.GET_PAGE}`,
|
|
21
|
-
props<{
|
|
22
|
-
page: number;
|
|
23
|
-
size: number;
|
|
24
|
-
id?: string | null;
|
|
25
|
-
filter?: Partial<T>;
|
|
26
|
-
sort?: Sort
|
|
27
|
-
}>()
|
|
28
|
-
);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export function createStaticFilterTableAction<T = any>(
|
|
32
|
-
tableRepository: string
|
|
33
|
-
) {
|
|
34
|
-
return createAction(
|
|
35
|
-
`${tableRepository} ${TablePageAction.CREATE_STATIC_FILTER}`,
|
|
36
|
-
props<{
|
|
37
|
-
filter?: Partial<T>;
|
|
38
|
-
}>()
|
|
39
|
-
);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export function createDataLoadSuccessTableAction<T>(tableRepository: string) {
|
|
43
|
-
return createAction(
|
|
44
|
-
`${tableRepository} ${TablePageAction.DATA_LOAD_SUCCESS}`,
|
|
45
|
-
props<{ gPage: Page<T> }>()
|
|
46
|
-
);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export function createDataLoadErrorTableAction(tableRepository: string) {
|
|
50
|
-
return createAction(
|
|
51
|
-
`${tableRepository} ${TablePageAction.DATA_LOAD_ERROR}`,
|
|
52
|
-
props<{ error: any }>()
|
|
53
|
-
);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export function createChangePageSizeTableAction(tableRepository: string) {
|
|
57
|
-
return createAction(
|
|
58
|
-
`${tableRepository} ${TablePageAction.CHANGE_PAGE_SIZE}`,
|
|
59
|
-
props<{ size: number }>()
|
|
60
|
-
);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// TODO: use action in delete item effect
|
|
64
|
-
export function createRefreshPageTableAction(tableRepository: string) {
|
|
65
|
-
return createAction(`${tableRepository} ${TablePageAction.REFRESH_PAGE}`);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export function createFilterPageTableAction<T>(tableRepository: string) {
|
|
69
|
-
return createAction(
|
|
70
|
-
`${tableRepository} ${TablePageAction.REFRESH_PAGE}`,
|
|
71
|
-
props<{ filter: Partial<T> }>()
|
|
72
|
-
);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export function createResetTableFilterAction(tableRepository: string) {
|
|
76
|
-
return createAction(`${tableRepository} ${TablePageAction.REFRESH_PAGE}`);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export function createDestroyTableAction(tableRepository: string) {
|
|
80
|
-
return createAction(`${tableRepository} ${TablePageAction.DESTROY}`);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export function createSelectItemsTableAction<T>(tableRepository: string) {
|
|
84
|
-
return createAction(
|
|
85
|
-
`${tableRepository} ${TablePageAction.SELECT_ITEMS}`,
|
|
86
|
-
props<{ selectedItems: T[] }>()
|
|
87
|
-
);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
export function createRemoveRangeTableAction(tableRepository: string) {
|
|
91
|
-
return createAction(`${tableRepository} ${TablePageAction.REMOVE_RANGE}`
|
|
92
|
-
);
|
|
1
|
+
import { createAction, props } from '@ngrx/store';
|
|
2
|
+
import { Page, Sort } from '@verisoft/core';
|
|
3
|
+
|
|
4
|
+
enum TablePageAction {
|
|
5
|
+
GET_PAGE = 'Get page',
|
|
6
|
+
CREATE_STATIC_FILTER = 'Create static filter',
|
|
7
|
+
DATA_LOAD_SUCCESS = 'Data load success',
|
|
8
|
+
DATA_LOAD_ERROR = 'Data load error',
|
|
9
|
+
REFRESH_PAGE = 'Refresh page',
|
|
10
|
+
FILTER_PAGE = 'Filter page',
|
|
11
|
+
CHANGE_PAGE_SIZE = 'Change page size',
|
|
12
|
+
SORT_PAGE = 'Sort page',
|
|
13
|
+
DESTROY = 'Destroy',
|
|
14
|
+
SELECT_ITEMS = 'Select items',
|
|
15
|
+
REMOVE_RANGE = 'Remove range',
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function createGetPageTableAction<T = any>(tableRepository: string) {
|
|
19
|
+
return createAction(
|
|
20
|
+
`${tableRepository} ${TablePageAction.GET_PAGE}`,
|
|
21
|
+
props<{
|
|
22
|
+
page: number;
|
|
23
|
+
size: number;
|
|
24
|
+
id?: string | null;
|
|
25
|
+
filter?: Partial<T>;
|
|
26
|
+
sort?: Sort[];
|
|
27
|
+
}>()
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function createStaticFilterTableAction<T = any>(
|
|
32
|
+
tableRepository: string
|
|
33
|
+
) {
|
|
34
|
+
return createAction(
|
|
35
|
+
`${tableRepository} ${TablePageAction.CREATE_STATIC_FILTER}`,
|
|
36
|
+
props<{
|
|
37
|
+
filter?: Partial<T>;
|
|
38
|
+
}>()
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function createDataLoadSuccessTableAction<T>(tableRepository: string) {
|
|
43
|
+
return createAction(
|
|
44
|
+
`${tableRepository} ${TablePageAction.DATA_LOAD_SUCCESS}`,
|
|
45
|
+
props<{ gPage: Page<T> }>()
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function createDataLoadErrorTableAction(tableRepository: string) {
|
|
50
|
+
return createAction(
|
|
51
|
+
`${tableRepository} ${TablePageAction.DATA_LOAD_ERROR}`,
|
|
52
|
+
props<{ error: any }>()
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function createChangePageSizeTableAction(tableRepository: string) {
|
|
57
|
+
return createAction(
|
|
58
|
+
`${tableRepository} ${TablePageAction.CHANGE_PAGE_SIZE}`,
|
|
59
|
+
props<{ size: number }>()
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// TODO: use action in delete item effect
|
|
64
|
+
export function createRefreshPageTableAction(tableRepository: string) {
|
|
65
|
+
return createAction(`${tableRepository} ${TablePageAction.REFRESH_PAGE}`);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function createFilterPageTableAction<T>(tableRepository: string) {
|
|
69
|
+
return createAction(
|
|
70
|
+
`${tableRepository} ${TablePageAction.REFRESH_PAGE}`,
|
|
71
|
+
props<{ filter: Partial<T> }>()
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function createResetTableFilterAction(tableRepository: string) {
|
|
76
|
+
return createAction(`${tableRepository} ${TablePageAction.REFRESH_PAGE}`);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function createDestroyTableAction(tableRepository: string) {
|
|
80
|
+
return createAction(`${tableRepository} ${TablePageAction.DESTROY}`);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function createSelectItemsTableAction<T>(tableRepository: string) {
|
|
84
|
+
return createAction(
|
|
85
|
+
`${tableRepository} ${TablePageAction.SELECT_ITEMS}`,
|
|
86
|
+
props<{ selectedItems: T[] }>()
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function createRemoveRangeTableAction(tableRepository: string) {
|
|
91
|
+
return createAction(`${tableRepository} ${TablePageAction.REMOVE_RANGE}`
|
|
92
|
+
);
|
|
93
93
|
}
|
|
@@ -1,100 +1,100 @@
|
|
|
1
|
-
import { Actions, createEffect, ofType } from '@ngrx/effects';
|
|
2
|
-
import { createFeatureSelector, createSelector, Store } from '@ngrx/store';
|
|
3
|
-
import { BaseHttpService, DEFAULT_SEARCH_LIMIT, Page, RequestParams } from '@verisoft/core';
|
|
4
|
-
import { catchError, map, Observable, of, switchMap, withLatestFrom } from 'rxjs';
|
|
5
|
-
import {
|
|
6
|
-
createGetPageTableAction,
|
|
7
|
-
createDataLoadSuccessTableAction,
|
|
8
|
-
createDataLoadErrorTableAction,
|
|
9
|
-
createRemoveRangeTableAction,
|
|
10
|
-
} from './actions';
|
|
11
|
-
import { TableState } from './models';
|
|
12
|
-
|
|
13
|
-
export interface CreateGetPageActionConfig<T> {
|
|
14
|
-
service?: BaseHttpService<T>;
|
|
15
|
-
fetchList?: (requestParams: RequestParams<any>) => Observable<Page<T>>;
|
|
16
|
-
snackbar?: any;
|
|
17
|
-
ngrxFeatureKey?: string;
|
|
18
|
-
requireFilters?: boolean;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export function createGetPageTableEffect<T>(
|
|
22
|
-
tableRepository: string,
|
|
23
|
-
actions$: Actions,
|
|
24
|
-
config: CreateGetPageActionConfig<T>
|
|
25
|
-
) {
|
|
26
|
-
return createEffect(() => {
|
|
27
|
-
return actions$.pipe(
|
|
28
|
-
ofType(createGetPageTableAction(tableRepository)),
|
|
29
|
-
switchMap(({ page, filter, sort, size }) => {
|
|
30
|
-
const requestParams: RequestParams<any> = {
|
|
31
|
-
page,
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
const params = config.service?.createParams(requestParams) ?? requestParams;
|
|
38
|
-
|
|
39
|
-
const fetchList$: Observable<Page<T>> = (config.service?.fetchList(
|
|
40
|
-
params
|
|
41
|
-
) ?? config.fetchList?.(params)) as Observable<Page<T>>;
|
|
42
|
-
if (!fetchList$) {
|
|
43
|
-
throw new Error('Service or fetchList$ must by defined.');
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
return fetchList$.pipe(
|
|
47
|
-
map((gPage) => {
|
|
48
|
-
const p = { ...gPage, number: page };
|
|
49
|
-
return createDataLoadSuccessTableAction(tableRepository)({
|
|
50
|
-
gPage: p,
|
|
51
|
-
});
|
|
52
|
-
}),
|
|
53
|
-
catchError((error) => {
|
|
54
|
-
config.snackbar?.showError(error.message);
|
|
55
|
-
return of(
|
|
56
|
-
createDataLoadErrorTableAction(tableRepository)({ error })
|
|
57
|
-
);
|
|
58
|
-
})
|
|
59
|
-
);
|
|
60
|
-
})
|
|
61
|
-
);
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export function createRemoveRangeTableEffect<T>(
|
|
66
|
-
tableRepository: string,
|
|
67
|
-
ngrxFeatureKey: string,
|
|
68
|
-
actions$: Actions,
|
|
69
|
-
store$: Store<any>,
|
|
70
|
-
config: CreateGetPageActionConfig<T>
|
|
71
|
-
) {
|
|
72
|
-
return createEffect(() => {
|
|
73
|
-
if(!config?.service) {
|
|
74
|
-
throw new Error('Service must be defined!');
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
const selectedItems = createSelector(
|
|
78
|
-
createFeatureSelector<any>(ngrxFeatureKey),
|
|
79
|
-
(state: any) => {
|
|
80
|
-
return (state?.[tableRepository] as TableState<any>)?.selectedItems as any;
|
|
81
|
-
}
|
|
82
|
-
);
|
|
83
|
-
|
|
84
|
-
return actions$.pipe(
|
|
85
|
-
ofType(createRemoveRangeTableAction(tableRepository)),
|
|
86
|
-
withLatestFrom(selectedItems),
|
|
87
|
-
switchMap(([, {selectedItems}]) => {
|
|
88
|
-
return config.service!.removeRange(selectedItems).pipe(
|
|
89
|
-
map(() => {
|
|
90
|
-
return createGetPageTableAction(tableRepository)
|
|
91
|
-
({ page: 0, size: DEFAULT_SEARCH_LIMIT })
|
|
92
|
-
}),
|
|
93
|
-
catchError(error => {
|
|
94
|
-
return of(createDataLoadErrorTableAction(tableRepository)({ error }))
|
|
95
|
-
})
|
|
96
|
-
);
|
|
97
|
-
})
|
|
98
|
-
);
|
|
99
|
-
});
|
|
100
|
-
}
|
|
1
|
+
import { Actions, createEffect, ofType } from '@ngrx/effects';
|
|
2
|
+
import { createFeatureSelector, createSelector, Store } from '@ngrx/store';
|
|
3
|
+
import { BaseHttpService, DEFAULT_SEARCH_LIMIT, Page, RequestParams } from '@verisoft/core';
|
|
4
|
+
import { catchError, map, Observable, of, switchMap, withLatestFrom } from 'rxjs';
|
|
5
|
+
import {
|
|
6
|
+
createGetPageTableAction,
|
|
7
|
+
createDataLoadSuccessTableAction,
|
|
8
|
+
createDataLoadErrorTableAction,
|
|
9
|
+
createRemoveRangeTableAction,
|
|
10
|
+
} from './actions';
|
|
11
|
+
import { TableState } from './models';
|
|
12
|
+
|
|
13
|
+
export interface CreateGetPageActionConfig<T> {
|
|
14
|
+
service?: BaseHttpService<T>;
|
|
15
|
+
fetchList?: (requestParams: RequestParams<any>) => Observable<Page<T>>;
|
|
16
|
+
snackbar?: any;
|
|
17
|
+
ngrxFeatureKey?: string;
|
|
18
|
+
requireFilters?: boolean;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function createGetPageTableEffect<T>(
|
|
22
|
+
tableRepository: string,
|
|
23
|
+
actions$: Actions,
|
|
24
|
+
config: CreateGetPageActionConfig<T>
|
|
25
|
+
) {
|
|
26
|
+
return createEffect(() => {
|
|
27
|
+
return actions$.pipe(
|
|
28
|
+
ofType(createGetPageTableAction(tableRepository)),
|
|
29
|
+
switchMap(({ page, filter, sort, size }) => {
|
|
30
|
+
const requestParams: RequestParams<any> = {
|
|
31
|
+
offset: page * size,
|
|
32
|
+
limit: size,
|
|
33
|
+
sort,
|
|
34
|
+
filter,
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const params = config.service?.createParams(requestParams) ?? requestParams;
|
|
38
|
+
|
|
39
|
+
const fetchList$: Observable<Page<T>> = (config.service?.fetchList(
|
|
40
|
+
params
|
|
41
|
+
) ?? config.fetchList?.(params)) as Observable<Page<T>>;
|
|
42
|
+
if (!fetchList$) {
|
|
43
|
+
throw new Error('Service or fetchList$ must by defined.');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return fetchList$.pipe(
|
|
47
|
+
map((gPage) => {
|
|
48
|
+
const p = { ...gPage, number: page };
|
|
49
|
+
return createDataLoadSuccessTableAction(tableRepository)({
|
|
50
|
+
gPage: p,
|
|
51
|
+
});
|
|
52
|
+
}),
|
|
53
|
+
catchError((error) => {
|
|
54
|
+
config.snackbar?.showError(error.message);
|
|
55
|
+
return of(
|
|
56
|
+
createDataLoadErrorTableAction(tableRepository)({ error })
|
|
57
|
+
);
|
|
58
|
+
})
|
|
59
|
+
);
|
|
60
|
+
})
|
|
61
|
+
);
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function createRemoveRangeTableEffect<T>(
|
|
66
|
+
tableRepository: string,
|
|
67
|
+
ngrxFeatureKey: string,
|
|
68
|
+
actions$: Actions,
|
|
69
|
+
store$: Store<any>,
|
|
70
|
+
config: CreateGetPageActionConfig<T>
|
|
71
|
+
) {
|
|
72
|
+
return createEffect(() => {
|
|
73
|
+
if(!config?.service) {
|
|
74
|
+
throw new Error('Service must be defined!');
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const selectedItems = createSelector(
|
|
78
|
+
createFeatureSelector<any>(ngrxFeatureKey),
|
|
79
|
+
(state: any) => {
|
|
80
|
+
return (state?.[tableRepository] as TableState<any>)?.selectedItems as any;
|
|
81
|
+
}
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
return actions$.pipe(
|
|
85
|
+
ofType(createRemoveRangeTableAction(tableRepository)),
|
|
86
|
+
withLatestFrom(selectedItems),
|
|
87
|
+
switchMap(([, { selectedItems }]) => {
|
|
88
|
+
return config.service!.removeRange(selectedItems).pipe(
|
|
89
|
+
map(() => {
|
|
90
|
+
return createGetPageTableAction(tableRepository)
|
|
91
|
+
({ page: 0, size: DEFAULT_SEARCH_LIMIT })
|
|
92
|
+
}),
|
|
93
|
+
catchError(error => {
|
|
94
|
+
return of(createDataLoadErrorTableAction(tableRepository)({ error }))
|
|
95
|
+
})
|
|
96
|
+
);
|
|
97
|
+
})
|
|
98
|
+
);
|
|
99
|
+
});
|
|
100
|
+
}
|