react-hook-core 0.1.16 → 0.1.18
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/lib/com.js +1 -1
- package/lib/merge.js +1 -6
- package/lib/route.js +52 -8
- package/lib/search.js +19 -15
- package/lib/state.js +2 -1
- package/lib/update.js +23 -7
- package/lib/useEdit.js +23 -17
- package/lib/useSearch.js +14 -4
- package/package.json +1 -1
- package/src/com.ts +53 -53
- package/src/merge.ts +23 -28
- package/src/route.ts +87 -47
- package/src/search.ts +19 -13
- package/src/state.ts +9 -1
- package/src/update.ts +86 -74
- package/src/useEdit.ts +23 -18
- package/src/useSearch.ts +524 -511
package/src/route.ts
CHANGED
|
@@ -1,47 +1,87 @@
|
|
|
1
|
-
import * as qs from
|
|
2
|
-
|
|
3
|
-
export function buildFromUrl<S>(): S {
|
|
4
|
-
return buildParameters(window.location.search);
|
|
5
|
-
}
|
|
6
|
-
export function buildParameters<T>(url: string): T {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
1
|
+
import * as qs from "query-string";
|
|
2
|
+
|
|
3
|
+
export function buildFromUrl<S>(modelT?: S): S {
|
|
4
|
+
return buildParameters<S>(window.location.search, modelT);
|
|
5
|
+
}
|
|
6
|
+
export function buildParameters<T>(url: string, model?: T): T {
|
|
7
|
+
let urlSearch = url;
|
|
8
|
+
const i = urlSearch.indexOf("?");
|
|
9
|
+
if (i >= 0) {
|
|
10
|
+
urlSearch = url.substring(i + 1);
|
|
11
|
+
}
|
|
12
|
+
try {
|
|
13
|
+
const parsed: any = convertToObject<T>(qs.parse(urlSearch), model);
|
|
14
|
+
return parsed;
|
|
15
|
+
} catch (error) {
|
|
16
|
+
console.log(error);
|
|
17
|
+
throw error;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function convertToObject<T>(input: any, model?: T): T {
|
|
22
|
+
if (model){
|
|
23
|
+
return parseToModel(input, model);
|
|
24
|
+
}
|
|
25
|
+
const output: any = {};
|
|
26
|
+
|
|
27
|
+
for (let key in input) {
|
|
28
|
+
const value = input[key];
|
|
29
|
+
const keys = key.split(".");
|
|
30
|
+
|
|
31
|
+
let currentObj: any = output;
|
|
32
|
+
for (let i = 0; i < keys.length; i++) {
|
|
33
|
+
const currentKey = keys[i];
|
|
34
|
+
|
|
35
|
+
if (!currentObj[currentKey]) {
|
|
36
|
+
if (i === keys.length - 1) {
|
|
37
|
+
currentObj[currentKey] = parseValue(value);
|
|
38
|
+
} else {
|
|
39
|
+
currentObj[currentKey] = {};
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
currentObj = currentObj[currentKey];
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return output as T;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function parseToModel(dest: any, src: any) {
|
|
51
|
+
if (typeof dest !== 'object' || typeof src !== 'object') {
|
|
52
|
+
return dest;
|
|
53
|
+
}
|
|
54
|
+
dest = convertToObject(dest)
|
|
55
|
+
for (let key in src) {
|
|
56
|
+
if (!Object.hasOwn(dest, key)) continue;
|
|
57
|
+
if (src.hasOwnProperty(key)) {
|
|
58
|
+
if (src[key] && src[key].constructor === Object) {
|
|
59
|
+
if (!dest[key] || dest[key].constructor !== Object) {
|
|
60
|
+
dest[key] = {};
|
|
61
|
+
}
|
|
62
|
+
parseToModel(dest[key], src[key]);
|
|
63
|
+
} else if (src[key] instanceof Date) {
|
|
64
|
+
dest[key] = new Date(dest[key]);
|
|
65
|
+
} else if (typeof src[key] === 'boolean') {
|
|
66
|
+
if (dest[key].length >0){
|
|
67
|
+
dest[key] = new Boolean(dest[key]);
|
|
68
|
+
}
|
|
69
|
+
} else if (typeof src[key] === 'number') {
|
|
70
|
+
if ( typeof dest[key] === 'string' && dest[key].indexOf(".") !== -1){
|
|
71
|
+
dest[key] = parseFloat(dest[key]);
|
|
72
|
+
}else{
|
|
73
|
+
dest[key] = parseInt(dest[key], 10);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return dest;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function parseValue(value: any): any {
|
|
82
|
+
// Check if the value is a string representing a number and parse it to a number
|
|
83
|
+
if (!isNaN(value) && !isNaN(parseFloat(value))) {
|
|
84
|
+
return parseFloat(value);
|
|
85
|
+
}
|
|
86
|
+
return value;
|
|
87
|
+
}
|
package/src/search.ts
CHANGED
|
@@ -36,6 +36,7 @@ export interface Sortable {
|
|
|
36
36
|
export interface Pagination {
|
|
37
37
|
initPageSize?: number;
|
|
38
38
|
pageSize?: number;
|
|
39
|
+
limit?: number;
|
|
39
40
|
pageIndex?: number;
|
|
40
41
|
total?: number;
|
|
41
42
|
pages?: number;
|
|
@@ -171,13 +172,19 @@ export function changePage(com: Pagination, pageIndex: number, pageSize: number)
|
|
|
171
172
|
com.append = false;
|
|
172
173
|
}
|
|
173
174
|
export function optimizeFilter<S extends Filter>(obj: S, searchable: Searchable, fields?: string[]): S {
|
|
175
|
+
const sLimit = searchable.limit;
|
|
174
176
|
obj.fields = fields;
|
|
175
177
|
if (searchable.pageIndex && searchable.pageIndex > 1) {
|
|
176
178
|
obj.page = searchable.pageIndex;
|
|
177
179
|
} else {
|
|
178
180
|
delete obj.page;
|
|
179
181
|
}
|
|
180
|
-
|
|
182
|
+
if (sLimit){
|
|
183
|
+
obj.limit = searchable.limit;
|
|
184
|
+
}else{
|
|
185
|
+
obj.limit = searchable.pageSize;
|
|
186
|
+
}
|
|
187
|
+
|
|
181
188
|
if (searchable.appendMode && searchable.initPageSize !== searchable.pageSize) {
|
|
182
189
|
obj.firstLimit = searchable.initPageSize;
|
|
183
190
|
} else {
|
|
@@ -194,21 +201,19 @@ export function optimizeFilter<S extends Filter>(obj: S, searchable: Searchable,
|
|
|
194
201
|
return obj;
|
|
195
202
|
}
|
|
196
203
|
|
|
197
|
-
function mapObjects(
|
|
198
|
-
for (let key in
|
|
199
|
-
if (
|
|
200
|
-
if(Array.isArray(
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
if(arrayObjKeyB && arrayObjKeyB.length > 1) {
|
|
205
|
-
objA[key] = [...arrayObjKeyB];
|
|
204
|
+
function mapObjects(dest: any, src: any): void {
|
|
205
|
+
for (let key in dest) {
|
|
206
|
+
if (src.hasOwnProperty(key) && src[key] !== null && src[key] !== undefined) {
|
|
207
|
+
if(Array.isArray(dest[key]) && typeof src[key] === 'string' && src[key].length > 0) {
|
|
208
|
+
const arrayObjKeySrc = src[key].length > 0 ? (src[key])?.split(',') : [];
|
|
209
|
+
if(arrayObjKeySrc && arrayObjKeySrc.length > 1) {
|
|
210
|
+
dest[key] = [...arrayObjKeySrc];
|
|
206
211
|
} else {
|
|
207
|
-
|
|
212
|
+
dest[key] = [];
|
|
213
|
+
dest[key].push(src[key])
|
|
208
214
|
}
|
|
209
|
-
}
|
|
210
215
|
} else {
|
|
211
|
-
|
|
216
|
+
dest[key] = src[key];
|
|
212
217
|
}
|
|
213
218
|
}
|
|
214
219
|
}
|
|
@@ -576,6 +581,7 @@ export function toggleSortStyle(target: HTMLElement): string {
|
|
|
576
581
|
}
|
|
577
582
|
export function getModel<T, S extends Filter>(state: any, modelName: string, searchable: Searchable, fields?: string[], excluding?: string[]|number[]): S {
|
|
578
583
|
let obj2 = getModelFromState(state, modelName);
|
|
584
|
+
|
|
579
585
|
const obj: any = obj2 ? obj2 : {};
|
|
580
586
|
const obj3 = optimizeFilter(obj, searchable, fields);
|
|
581
587
|
obj3.excluding = excluding;
|
package/src/state.ts
CHANGED
|
@@ -75,6 +75,7 @@ export function buildState<S, K extends keyof S>(e: any, state: Readonly<S>, ctr
|
|
|
75
75
|
const dataField = ctrl.getAttribute('data-field');
|
|
76
76
|
const field = (dataField ? dataField : ctrl.name);
|
|
77
77
|
const model = Object.assign({}, ex);
|
|
78
|
+
const dType= 'array'
|
|
78
79
|
if (type && type.toLowerCase() === 'checkbox') {
|
|
79
80
|
let value = model[field];
|
|
80
81
|
if (ctrl.id && ctrl.name !== ctrl.id) {
|
|
@@ -82,7 +83,14 @@ export function buildState<S, K extends keyof S>(e: any, state: Readonly<S>, ctr
|
|
|
82
83
|
value = [];
|
|
83
84
|
}
|
|
84
85
|
value.includes(ctrl.value) ? value = value.filter((v: string) => v !== ctrl.value) : value.push(ctrl.value);
|
|
86
|
+
// if (dType == 'array'){
|
|
87
|
+
// if (value === 'string'){
|
|
88
|
+
// value = [value]
|
|
89
|
+
// }
|
|
90
|
+
// }
|
|
85
91
|
model[field] = value;
|
|
92
|
+
// console.log(model, modelName, model, model[field], field, value )
|
|
93
|
+
// setValue(model, field, value);
|
|
86
94
|
} else {
|
|
87
95
|
const v = valueOfCheckbox(ctrl);
|
|
88
96
|
model[field] = v;
|
|
@@ -103,7 +111,7 @@ export function buildState<S, K extends keyof S>(e: any, state: Readonly<S>, ctr
|
|
|
103
111
|
const objSet: any = {};
|
|
104
112
|
try {
|
|
105
113
|
const selectedDate = new Date(ctrl.value);
|
|
106
|
-
setValue(model, field, ctrl.value && ctrl.value!== '' ? selectedDate.toISOString() :
|
|
114
|
+
setValue(model, field, ctrl.value && ctrl.value!== '' ? selectedDate.toISOString() : null);
|
|
107
115
|
objSet[modelName] = model;
|
|
108
116
|
return objSet;
|
|
109
117
|
} catch (error) {
|
package/src/update.ts
CHANGED
|
@@ -1,74 +1,86 @@
|
|
|
1
|
-
import {getModelName as getModelName2, Locale, removePhoneFormat} from
|
|
2
|
-
import {useMergeState} from
|
|
3
|
-
import {buildFlatState, buildState, handleEvent, localeOf} from
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const
|
|
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
|
-
if (
|
|
48
|
-
if (
|
|
49
|
-
|
|
50
|
-
} else {
|
|
51
|
-
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
setState(objSet);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}
|
|
1
|
+
import { getModelName as getModelName2, Locale, removePhoneFormat } from "./core";
|
|
2
|
+
import { useMergeState } from "./merge";
|
|
3
|
+
import { buildFlatState, buildState, handleEvent, localeOf } from "./state";
|
|
4
|
+
import { useEffect, useState } from "react";
|
|
5
|
+
|
|
6
|
+
const m = "model";
|
|
7
|
+
const _getModelName = (f2?: HTMLFormElement | null): string => {
|
|
8
|
+
return getModelName2(f2, m);
|
|
9
|
+
};
|
|
10
|
+
export const useUpdate = <T>(
|
|
11
|
+
initialState: T,
|
|
12
|
+
getName?: ((f?: HTMLFormElement | null) => string) | string,
|
|
13
|
+
getLocale?: (() => Locale) | Locale,
|
|
14
|
+
removeErr?: (ctrl: HTMLInputElement) => void
|
|
15
|
+
) => {
|
|
16
|
+
const [state, setState] = useMergeState<T>(initialState);
|
|
17
|
+
const [rerender, setRerender] = useState(false);
|
|
18
|
+
|
|
19
|
+
// trigger re-render page when change state in useSearch
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
setRerender(!rerender);
|
|
22
|
+
}, [state]);
|
|
23
|
+
|
|
24
|
+
const updatePhoneState = (event: any) => {
|
|
25
|
+
const re = /^[0-9\b]+$/;
|
|
26
|
+
const target = event.currentTarget as HTMLInputElement;
|
|
27
|
+
const value = removePhoneFormat(target.value);
|
|
28
|
+
if (re.test(value) || !value) {
|
|
29
|
+
updateState(event);
|
|
30
|
+
} else {
|
|
31
|
+
const splitArr = value.split("");
|
|
32
|
+
let responseStr = "";
|
|
33
|
+
splitArr.forEach((element) => {
|
|
34
|
+
if (re.test(element)) {
|
|
35
|
+
responseStr += element;
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
target.value = responseStr;
|
|
39
|
+
updateState(event);
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
const getModelName: (f2?: HTMLFormElement | null) => string = typeof getName === "function" ? getName : _getModelName;
|
|
43
|
+
|
|
44
|
+
const updateState = (e: any, callback?: (prev: any) => void, lc?: Locale) => {
|
|
45
|
+
const ctrl = e.currentTarget as HTMLInputElement;
|
|
46
|
+
let mn: string = m;
|
|
47
|
+
if (getName) {
|
|
48
|
+
if (typeof getName === "string") {
|
|
49
|
+
mn = getName;
|
|
50
|
+
} else {
|
|
51
|
+
mn = getName(ctrl.form);
|
|
52
|
+
}
|
|
53
|
+
} else {
|
|
54
|
+
mn = _getModelName(ctrl.form);
|
|
55
|
+
}
|
|
56
|
+
const l = localeOf(lc, getLocale);
|
|
57
|
+
handleEvent(e, removeErr);
|
|
58
|
+
const objSet = buildState<T, any>(e, state, ctrl, mn, l);
|
|
59
|
+
if (objSet) {
|
|
60
|
+
if (callback) {
|
|
61
|
+
setState({ ...objSet }, callback);
|
|
62
|
+
} else {
|
|
63
|
+
setState(objSet);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
const updateFlatState = (e: any, callback?: () => void, lc?: Locale) => {
|
|
68
|
+
const objSet = buildFlatState<T, any>(e, state, lc);
|
|
69
|
+
if (objSet) {
|
|
70
|
+
if (callback) {
|
|
71
|
+
setState(objSet, callback);
|
|
72
|
+
} else {
|
|
73
|
+
setState(objSet);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
return {
|
|
78
|
+
getModelName,
|
|
79
|
+
updateState,
|
|
80
|
+
updatePhoneState,
|
|
81
|
+
updateFlatState,
|
|
82
|
+
getLocale,
|
|
83
|
+
setState,
|
|
84
|
+
state,
|
|
85
|
+
};
|
|
86
|
+
};
|
package/src/useEdit.ts
CHANGED
|
@@ -215,11 +215,11 @@ export const useCoreEdit = <T, ID, S, P>(
|
|
|
215
215
|
};
|
|
216
216
|
|
|
217
217
|
const _handleNotFound = (form?: any): void => {
|
|
218
|
-
const msg = message(p1.resource.value, '
|
|
218
|
+
const msg = message(p1.resource.value, 'error_404', 'error');
|
|
219
219
|
if (form) {
|
|
220
220
|
setReadOnly(form);
|
|
221
221
|
}
|
|
222
|
-
p1.showError(msg.message, msg.title);
|
|
222
|
+
p1.showError(msg.message, msg.title, undefined, () => window.history.back);
|
|
223
223
|
};
|
|
224
224
|
const handleNotFound = (p && p.handleNotFound ? p.handleNotFound : _handleNotFound);
|
|
225
225
|
|
|
@@ -371,14 +371,10 @@ export const useCoreEdit = <T, ID, S, P>(
|
|
|
371
371
|
const unmappedErrors = u.showFormError(f, errors);
|
|
372
372
|
focusFirstError(f);
|
|
373
373
|
if (!result.message) {
|
|
374
|
-
if (
|
|
375
|
-
result.message =
|
|
374
|
+
if (p1.ui && p1.ui.buildErrorMessage) {
|
|
375
|
+
result.message = p1.ui.buildErrorMessage(unmappedErrors);
|
|
376
376
|
} else {
|
|
377
|
-
|
|
378
|
-
result.message = p1.ui.buildErrorMessage(unmappedErrors);
|
|
379
|
-
} else {
|
|
380
|
-
result.message = errors[0].message;
|
|
381
|
-
}
|
|
377
|
+
result.message = errors[0].message;
|
|
382
378
|
}
|
|
383
379
|
}
|
|
384
380
|
if (result.message) {
|
|
@@ -492,16 +488,25 @@ export const useCoreEdit = <T, ID, S, P>(
|
|
|
492
488
|
const r = p1.resource;
|
|
493
489
|
const title = r.value('error');
|
|
494
490
|
let msg = r.value('error_internal');
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
if (data && (data.status === 401 || data.status === 403)) {
|
|
502
|
-
setReadOnly(refForm.current);
|
|
491
|
+
const st = createEditStatus(p ? p.status : undefined);
|
|
492
|
+
if (data && data.status === 422) {
|
|
493
|
+
fail(err.response?.data);
|
|
494
|
+
const obj = err.response?.data?.value;
|
|
495
|
+
if (obj) {
|
|
496
|
+
callback ? callback(obj as T, showModel) : showModel(obj as T);
|
|
503
497
|
}
|
|
504
|
-
|
|
498
|
+
} else {
|
|
499
|
+
if (data && data.status === 404) {
|
|
500
|
+
handleNotFound(refForm.current);
|
|
501
|
+
} else {
|
|
502
|
+
if (data.status && !isNaN(data.status)) {
|
|
503
|
+
msg = messageByHttpStatus(data.status, r.value);
|
|
504
|
+
}
|
|
505
|
+
if (data && (data.status === 401 || data.status === 403)) {
|
|
506
|
+
setReadOnly(refForm.current);
|
|
507
|
+
}
|
|
508
|
+
p1.showError(msg, title);
|
|
509
|
+
}
|
|
505
510
|
}
|
|
506
511
|
setRunning(false);
|
|
507
512
|
hideLoading(p1.loading);
|