@verisoft/store 20.0.0 → 20.1.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.
@@ -0,0 +1,99 @@
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)({ page: 0, size: DEFAULT_SEARCH_LIMIT })
91
+ }),
92
+ catchError(error => {
93
+ return of(createDataLoadErrorTableAction(tableRepository)({ error }))
94
+ })
95
+ );
96
+ })
97
+ );
98
+ });
99
+ }
@@ -0,0 +1,20 @@
1
+ import { DEFAULT_SEARCH_LIMIT, DEFAULT_SEARCH_PARAMS, Page, RequestParams } from "@verisoft/core";
2
+
3
+ export interface TableState<T> {
4
+ dataLoading: boolean;
5
+ requestParams: RequestParams<T>;
6
+ gPage?: Page<T>;
7
+ error?: string | null;
8
+ selectedItems?: T[];
9
+ }
10
+
11
+ export const INITIAL_TABLE_STATE: TableState<any> = {
12
+ gPage: {
13
+ data: [],
14
+ size: DEFAULT_SEARCH_LIMIT,
15
+ total: 0.
16
+ } as unknown as Page<any>,
17
+ dataLoading: false,
18
+ requestParams: DEFAULT_SEARCH_PARAMS,
19
+ selectedItems: []
20
+ };
@@ -0,0 +1,126 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import { ActionCreator, ReducerTypes, createReducer, on } from '@ngrx/store';
3
+ import {
4
+ createGetPageTableAction,
5
+ createStaticFilterTableAction,
6
+ createDataLoadSuccessTableAction,
7
+ createDataLoadErrorTableAction,
8
+ createFilterPageTableAction,
9
+ createDestroyTableAction,
10
+ createSelectItemsTableAction,
11
+ createChangePageSizeTableAction,
12
+ createResetTableFilterAction,
13
+ } from './actions';
14
+ import { INITIAL_TABLE_STATE, TableState } from './models';
15
+
16
+ export function createTablePageReducers<
17
+ T = any,
18
+ TState extends TableState<T> = TableState<T>
19
+ >(
20
+ tableRepository: string,
21
+ initialState: TState = INITIAL_TABLE_STATE as unknown as TState,
22
+ ...ons: ReducerTypes<TState, readonly ActionCreator[]>[]
23
+ ) {
24
+ return createReducer(
25
+ initialState,
26
+ on(
27
+ createGetPageTableAction(tableRepository),
28
+ (state, { page, id, filter, sort }) => {
29
+ return {
30
+ ...state,
31
+ requestParams: {
32
+ ...state.requestParams,
33
+ filter: filter ?? state.requestParams.filter,
34
+ sort: sort ?? state.requestParams.sort,
35
+ id: id ?? state.requestParams.id,
36
+ page,
37
+ },
38
+ dataLoading: true,
39
+ submitted: true,
40
+ };
41
+ }
42
+ ),
43
+
44
+ on(createStaticFilterTableAction(tableRepository), (state, { filter }) => {
45
+ return {
46
+ ...state,
47
+ requestParams: {
48
+ ...state.requestParams,
49
+ filter: {
50
+ ...state.requestParams?.filter,
51
+ filter,
52
+ },
53
+ },
54
+ };
55
+ }),
56
+
57
+ on(createResetTableFilterAction(tableRepository), (state) => {
58
+ return {
59
+ ...state,
60
+ requestParams: {
61
+ ...state.requestParams,
62
+ filter: undefined,
63
+ page: 1
64
+ },
65
+ }
66
+ }),
67
+
68
+ on(
69
+ createDataLoadSuccessTableAction(tableRepository),
70
+ (state, { gPage }) => {
71
+ return {
72
+ ...state,
73
+ gPage,
74
+ dataLoading: false,
75
+ };
76
+ }
77
+ ),
78
+
79
+ on(createDataLoadErrorTableAction(tableRepository), (state, { error }) => {
80
+ return {
81
+ ...state,
82
+ error,
83
+ dataLoading: false,
84
+ };
85
+ }),
86
+
87
+ on(createFilterPageTableAction(tableRepository), (state, { filter }) => {
88
+ return {
89
+ ...state,
90
+ requestParams: {
91
+ ...state.requestParams,
92
+ filter: filter,
93
+ page: 1,
94
+ },
95
+ dataLoading: true,
96
+ };
97
+ }),
98
+
99
+ on(createDestroyTableAction(tableRepository), () => {
100
+ return {
101
+ ...(initialState as any),
102
+ };
103
+ }),
104
+
105
+ on(
106
+ createSelectItemsTableAction(tableRepository),
107
+ (state, { selectedItems }) => {
108
+ return {
109
+ ...state,
110
+ selectedItems,
111
+ };
112
+ }
113
+ ),
114
+
115
+ on(createChangePageSizeTableAction(tableRepository), (state, { size }) => {
116
+ return {
117
+ ...state,
118
+ requestParams: {
119
+ ...state.requestParams,
120
+ size,
121
+ }
122
+ }
123
+ }),
124
+ ...ons
125
+ );
126
+ }
@@ -0,0 +1,8 @@
1
+ // @ts-expect-error https://thymikee.github.io/jest-preset-angular/docs/getting-started/test-environment
2
+ globalThis.ngJest = {
3
+ testEnvironmentOptions: {
4
+ errorOnUnknownElements: true,
5
+ errorOnUnknownProperties: true,
6
+ },
7
+ };
8
+ import 'jest-preset-angular/setup-jest';
package/tsconfig.json ADDED
@@ -0,0 +1,29 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "es2022",
4
+ "useDefineForClassFields": false,
5
+ "forceConsistentCasingInFileNames": true,
6
+ "strict": true,
7
+ "noImplicitOverride": true,
8
+ "noPropertyAccessFromIndexSignature": true,
9
+ "noImplicitReturns": true,
10
+ "noFallthroughCasesInSwitch": true
11
+ },
12
+ "files": [],
13
+ "include": [],
14
+ "references": [
15
+ {
16
+ "path": "./tsconfig.lib.json"
17
+ },
18
+ {
19
+ "path": "./tsconfig.spec.json"
20
+ }
21
+ ],
22
+ "extends": "../../../tsconfig.base.json",
23
+ "angularCompilerOptions": {
24
+ "enableI18nLegacyMessageIdFormat": false,
25
+ "strictInjectionParameters": true,
26
+ "strictInputAccessModifiers": true,
27
+ "strictTemplates": true
28
+ }
29
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "../../../dist/out-tsc",
5
+ "declaration": true,
6
+ "declarationMap": true,
7
+ "inlineSources": true,
8
+ "types": []
9
+ },
10
+ "exclude": [
11
+ "src/**/*.spec.ts",
12
+ "src/test-setup.ts",
13
+ "jest.config.ts",
14
+ "src/**/*.test.ts"
15
+ ],
16
+ "include": ["src/**/*.ts"]
17
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "./tsconfig.lib.json",
3
+ "compilerOptions": {
4
+ "declarationMap": false
5
+ },
6
+ "angularCompilerOptions": {
7
+ "compilationMode": "partial"
8
+ }
9
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "../../../dist/out-tsc",
5
+ "module": "commonjs",
6
+ "target": "es2016",
7
+ "types": ["jest", "node"]
8
+ },
9
+ "files": ["src/test-setup.ts"],
10
+ "include": [
11
+ "jest.config.ts",
12
+ "src/**/*.test.ts",
13
+ "src/**/*.spec.ts",
14
+ "src/**/*.d.ts"
15
+ ]
16
+ }