react-hook-core 0.1.22 → 0.1.23

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/src/useEdit.ts CHANGED
@@ -1,539 +1,539 @@
1
- import {useEffect, useState} from 'react';
2
- import {useNavigate, useParams} from 'react-router';
3
- import {Attributes, buildId, createEditStatus, EditStatusConfig, ErrorMessage, getModelName as getModelName2, hideLoading, initForm, LoadingService, Locale, message, messageByHttpStatus, ResourceService, showLoading, UIService} from './core';
4
- import {build, createModel as createModel2, EditParameter, GenericService, handleStatus, handleVersion, initPropertyNullInModel} from './edit';
5
- import {focusFirstError, readOnly as setReadOnly} from './formutil';
6
- import {DispatchWithCallback, useMergeState} from './merge';
7
- import {clone, makeDiff} from './reflect';
8
- import {localeOf} from './state';
9
- import {useUpdate} from './update';
10
-
11
- export interface BaseEditComponentParam<T, ID> {
12
- status?: EditStatusConfig;
13
- backOnSuccess?: boolean;
14
- name?: string;
15
- metadata?: Attributes;
16
- keys?: string[];
17
- version?: string;
18
- setBack?: boolean;
19
- patchable?: boolean;
20
-
21
- addable?: boolean;
22
- readOnly?: boolean;
23
- deletable?: boolean;
24
-
25
- insertSuccessMsg?: string;
26
- updateSuccessMsg?: string;
27
-
28
- handleNotFound?: (form?: HTMLFormElement) => void;
29
- getModelName?: (f?: HTMLFormElement) => string;
30
- getModel?: () => T;
31
- showModel?: (m: T) => void;
32
- createModel?: () => T;
33
- onSave?: (isBack?: boolean) => void;
34
- validate?: (obj: T, callback: (obj2?: T) => void) => void;
35
- succeed?: (origin: T, msg: string, version?: string, isBack?: boolean, model?: T) => void;
36
- fail?: (result: ErrorMessage[]) => void;
37
- postSave?: (res: number|T|ErrorMessage[], origin: T, version?: string, isPatch?: boolean, backOnSave?: boolean) => void;
38
- handleError?: (error: any) => void;
39
- handleDuplicateKey?: (result?: T) => void;
40
- load?: (i: ID|null, callback?: (m: T, showM: (m2: T) => void) => void) => void;
41
- doSave?: (obj: T, diff?: T, version?: string, isBack?: boolean) => void;
42
- // prepareCustomData?: (data: any) => void; // need to review
43
- }
44
- export interface HookBaseEditParameter<T, ID, S> extends BaseEditComponentParam<T, ID> {
45
- refForm: any;
46
- initialState: S;
47
- service: GenericService<T, ID, number|T|ErrorMessage[]>;
48
- resource: ResourceService;
49
- showMessage: (msg: string) => void;
50
- showError: (m: string, header?: string, detail?: string, callback?: () => void) => void;
51
- getLocale?: () => Locale;
52
- confirm: (m2: string, header?: string, yesCallback?: () => void, btnLeftText?: string, btnRightText?: string, noCallback?: () => void) => void;
53
- ui?: UIService;
54
- loading?: LoadingService;
55
- }
56
- export interface EditComponentParam<T, ID, S> extends BaseEditComponentParam<T, ID> {
57
- initialize?: (id: ID|null, ld: (i: ID|null, cb?: (m: T, showF: (model: T) => void) => void) => void, setState2: DispatchWithCallback<Partial<S>>, callback?: (m: T, showF: (model: T) => void) => void) => void;
58
- callback?: (m: T, showF: (model: T) => void) => void;
59
- }
60
- export interface HookPropsEditParameter<T, ID, S, P> extends HookPropsBaseEditParameter<T, ID, S, P> {
61
- initialize?: (id: ID|null, ld: (i: ID|null, cb?: (m: T, showF: (model: T) => void) => void) => void, setState2: DispatchWithCallback<Partial<S>>, callback?: (m: T, showF: (model: T) => void) => void) => void;
62
- callback?: (m: T, showF: (model: T) => void) => void;
63
- }
64
- export interface HookPropsBaseEditParameter<T, ID, S, P> extends HookBaseEditParameter<T, ID, S> {
65
- props: P;
66
- // prepareCustomData?: (data: any) => void;
67
- }
68
- export const useEdit = <T, ID, S>(
69
- refForm: any,
70
- initialState: S,
71
- service: GenericService<T, ID, number|T|ErrorMessage[]>,
72
-
73
- p2: EditParameter,
74
- p?: EditComponentParam<T, ID, S>
75
- ) => {
76
- const params = useParams();
77
- const baseProps = useCoreEdit(refForm, initialState, service, p2, p);
78
- useEffect(() => {
79
- if (refForm) {
80
- const registerEvents = (p2.ui ? p2.ui.registerEvents : undefined);
81
- initForm(baseProps.refForm.current, registerEvents);
82
- }
83
- const n = baseProps.getModelName(refForm.current);
84
- const obj: any = {};
85
- obj[n] = baseProps.createModel();
86
- baseProps.setState(obj);
87
- let keys: string[]|undefined;
88
- if (p && !p.keys && service && service.metadata) {
89
- const metadata = (p.metadata ? p.metadata : service.metadata());
90
- if (metadata) {
91
- const meta = build(metadata);
92
- keys = (p.keys ? p.keys : (meta ? meta.keys : undefined));
93
- const version = (p.version ? p.version : (meta ? meta.version : undefined));
94
- p.keys = keys;
95
- p.version = version;
96
- }
97
- }
98
- const id = buildId<ID>(params, keys);
99
- if (p && p.initialize) {
100
- p.initialize(id, baseProps.load, baseProps.setState, p.callback);
101
- } else {
102
- try {
103
- baseProps.load(id, p ? p.callback : undefined);
104
- } catch (error) {
105
- p2.showError(error as string);
106
- hideLoading(p2.loading);
107
- }
108
- }
109
- // eslint-disable-next-line react-hooks/exhaustive-deps
110
- }, []);
111
- return {...baseProps};
112
- };
113
- export const useEditProps = <T, ID, S, P>(
114
- props: P,
115
- refForm: any,
116
- initialState: S,
117
- service: GenericService<T, ID, number|T|ErrorMessage[]>,
118
- p2: EditParameter,
119
- p?: EditComponentParam<T, ID, S>
120
- ) => {
121
- const params = useParams();
122
- const baseProps = useCoreEdit<T, ID, S, P>(refForm, initialState, service, p2, p, props);
123
- useEffect(() => {
124
- if (refForm) {
125
- const registerEvents = (p2.ui ? p2.ui.registerEvents : undefined);
126
- initForm(baseProps.refForm.current, registerEvents);
127
- }
128
- const n = baseProps.getModelName(refForm.current);
129
- const obj: any = {};
130
- obj[n] = baseProps.createModel();
131
- baseProps.setState(obj);
132
- let keys: string[]|undefined;
133
- if (p && !p.keys && service && service.metadata) {
134
- const metadata = (p.metadata ? p.metadata : service.metadata());
135
- if (metadata) {
136
- const meta = build(metadata);
137
- keys = (p.keys ? p.keys : (meta ? meta.keys : undefined));
138
- const version = (p.version ? p.version : (meta ? meta.version : undefined));
139
- p.keys = keys;
140
- p.version = version;
141
- }
142
- }
143
- const id = buildId<ID>(params, keys);
144
- if (p && p.initialize) {
145
- p.initialize(id, baseProps.load, baseProps.setState, p.callback);
146
- } else {
147
- baseProps.load(id, p ? p.callback : undefined);
148
- }
149
- // eslint-disable-next-line react-hooks/exhaustive-deps
150
- }, []);
151
- return {...baseProps};
152
- };
153
- export const useEditOneProps = <T, ID, S, P>(p: HookPropsEditParameter<T, ID, S, P>) => {
154
- return useEditProps(p.props, p.refForm, p.initialState, p.service, p, p);
155
- };
156
- export const useEditOne = <T, ID, S>(p: HookBaseEditParameter<T, ID, S>) => {
157
- return useEdit(p.refForm, p.initialState, p.service, p, p);
158
- };
159
- export const useCoreEdit = <T, ID, S, P>(
160
- refForm: any,
161
- initialState: S,
162
- service: GenericService<T, ID, number|T|ErrorMessage[]>,
163
- p1: EditParameter,
164
- p?: BaseEditComponentParam<T, ID>,
165
- props?: P
166
- ) => {
167
- /*
168
- const {
169
- backOnSuccess = true,
170
- patchable = true,
171
- addable = true
172
- } = p; */
173
- const navigate = useNavigate();
174
- const addable = (p && p.patchable !== false ? true : undefined);
175
- const back = (event?: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
176
- if (event) {
177
- event.preventDefault();
178
- }
179
- navigate(-1);
180
- };
181
-
182
- const [running, setRunning] = useState<boolean>();
183
-
184
- const getModelName = (f?: HTMLFormElement|null): string => {
185
- if (p && p.name && p.name.length > 0) {
186
- return p.name;
187
- }
188
- return getModelName2(f);
189
- };
190
- const baseProps = useUpdate<S>(initialState, getModelName, p1.getLocale);
191
-
192
- const { state, setState } = baseProps;
193
- const [flag, setFlag] = useMergeState({
194
- newMode: false,
195
- setBack: false,
196
- addable,
197
- readOnly: p ? p.readOnly : undefined,
198
- originalModel: undefined
199
- });
200
-
201
- const showModel = (model: T) => {
202
- const n = getModelName(refForm.current);
203
- const objSet: any = {};
204
- objSet[n] = model;
205
- setState(objSet);
206
- if (p && p.readOnly) {
207
- const f = refForm.current;
208
- setReadOnly(f);
209
- }
210
- };
211
-
212
- const resetState = (newMode: boolean, model: T, originalModel?: T) => {
213
- setFlag({ newMode, originalModel } as any);
214
- showModel(model);
215
- };
216
-
217
- const _handleNotFound = (form?: any): void => {
218
- const msg = message(p1.resource.value, 'error_404', 'error');
219
- if (form) {
220
- setReadOnly(form);
221
- }
222
- p1.showError(msg.message, msg.title, undefined, () => window.history.back);
223
- };
224
- const handleNotFound = (p && p.handleNotFound ? p.handleNotFound : _handleNotFound);
225
-
226
- const _getModel = () => {
227
- const n = getModelName(refForm.current);
228
- if (props) {
229
- return (props as any)[n] || (state as any)[n];
230
- } else {
231
- return (state as any)[n];
232
- }
233
- };
234
- const getModel = (p && p.getModel ? p.getModel : _getModel);
235
-
236
- const _createModel = (): T => {
237
- const metadata = (p && p.metadata ? p.metadata : (service.metadata ? service.metadata() : undefined));
238
- if (metadata) {
239
- const obj = createModel2<T>(metadata);
240
- return obj;
241
- } else {
242
- const obj: any = {};
243
- return obj;
244
- }
245
- };
246
- const createModel = (p && p.createModel ? p.createModel : _createModel);
247
-
248
- const create = (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
249
- event.preventDefault();
250
- const obj = createModel();
251
- resetState(true, obj, undefined);
252
- const u = p1.ui;
253
- if (u) {
254
- setTimeout(() => {
255
- u.removeFormError(refForm.current);
256
- }, 100);
257
- }
258
- };
259
-
260
- const _onSave = (isBack?: boolean) => {
261
- if (flag.newMode === true && flag.addable === false) {
262
- const m = message(p1.resource.value, 'error_permission_add', 'error_permission');
263
- p1.showError(m.message, m.title);
264
- return;
265
- } else if (p && flag.newMode === false && p.readOnly) {
266
- const msg = message(p1.resource.value, 'error_permission_edit', 'error_permission');
267
- p1.showError(msg.message, msg.title);
268
- return;
269
- } else {
270
- if (running === true) {
271
- return;
272
- }
273
- const obj = getModel();
274
- const metadata = (p && p.metadata ? p.metadata : (service.metadata ? service.metadata() : undefined));
275
- let keys: string[]|undefined;
276
- let version: string|undefined;
277
- if (p && metadata && (!p.keys || !p.version)) {
278
- const meta = build(metadata);
279
- keys = (p.keys ? p.keys : (meta ? meta.keys : undefined));
280
- version = (p.version ? p.version : (meta ? meta.version : undefined));
281
- }
282
- if (flag.newMode) {
283
- validate(obj, () => {
284
- const msg = message(p1.resource.value, 'msg_confirm_save', 'confirm', 'yes', 'no');
285
- p1.confirm(msg.message, msg.title, () => {
286
- doSave(obj, undefined, version, isBack);
287
- }, msg.no, msg.yes);
288
- });
289
- } else {
290
- const diffObj = makeDiff(initPropertyNullInModel(flag.originalModel, metadata), obj, keys, version);
291
- const objKeys = Object.keys(diffObj);
292
- if (objKeys.length === 0) {
293
- p1.showMessage(p1.resource.value('msg_no_change'));
294
- } else {
295
- validate(obj, () => {
296
- const msg = message(p1.resource.value, 'msg_confirm_save', 'confirm', 'yes', 'no');
297
- p1.confirm(msg.message, msg.title, () => {
298
- doSave(obj, diffObj as any, version, isBack);
299
- }, msg.no, msg.yes);
300
- });
301
- }
302
- }
303
- }
304
- };
305
- const onSave = (p && p.onSave ? p.onSave : _onSave);
306
-
307
- const save = (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
308
- event.preventDefault();
309
- event.persist();
310
- onSave();
311
- };
312
-
313
- const _validate = (obj: T, callback: (obj2?: T) => void) => {
314
- if (p1.ui) {
315
- const valid = p1.ui.validateForm(refForm.current, localeOf(undefined, p1.getLocale));
316
- if (valid) {
317
- callback(obj);
318
- }
319
- } else {
320
- callback(obj);
321
- }
322
- };
323
- const validate = (p && p.validate ? p.validate : _validate);
324
-
325
- const _succeed = (origin: T, msg: string, version?: string, isBack?: boolean, model?: T) => {
326
- if (model) {
327
- setFlag({ newMode: false });
328
- if (model && flag.setBack === true) {
329
- resetState(false, model, clone(model));
330
- } else {
331
- handleVersion(origin, version);
332
- }
333
- } else {
334
- handleVersion(origin, version);
335
- }
336
- p1.showMessage(msg);
337
- if (isBack) {
338
- back(undefined);
339
- }
340
- };
341
- const succeed = (p && p.succeed ? p.succeed : _succeed);
342
-
343
- const _fail = (result: ErrorMessage[]) => {
344
- const f = refForm.current;
345
- const u = p1.ui;
346
- if (u && f) {
347
- const unmappedErrors = u.showFormError(f, result);
348
- focusFirstError(f);
349
- if (unmappedErrors && unmappedErrors.length > 0) {
350
- const t = p1.resource.value('error');
351
- if (p1.ui && p1.ui.buildErrorMessage) {
352
- const msg = p1.ui.buildErrorMessage(unmappedErrors);
353
- p1.showError(msg, t);
354
- } else {
355
- p1.showError(unmappedErrors[0].field + ' ' + unmappedErrors[0].code + ' ' + unmappedErrors[0].message, t);
356
- }
357
- }
358
- } else {
359
- const t = p1.resource.value('error');
360
- if (result.length > 0) {
361
- p1.showError(result[0].field + ' ' + result[0].code + ' ' + result[0].message, t);
362
- } else {
363
- p1.showError(t, t);
364
- }
365
- }
366
- };
367
- const fail = (p && p.fail ? p.fail : _fail);
368
-
369
- const _handleError = function (err: any) {
370
- if (err) {
371
- setRunning(false);
372
- hideLoading(p1.loading);
373
- const errMsg = p1.resource.value('error_internal');
374
- const data = (err && err.response) ? err.response : err;
375
- if (data.status === 400) {
376
- const errMsg = p1.resource.value('error_400');
377
- p1.showError(errMsg, "Error");
378
- } else{
379
- p1.showError(errMsg, "Error");
380
- }
381
- }
382
- };
383
- const handleError = (p && p.handleError ? p.handleError : _handleError);
384
-
385
- const _postSave = (r: number | T|ErrorMessage[], origin: T, version?: string, isPatch?: boolean, backOnSave?: boolean) => {
386
- setRunning(false);
387
- hideLoading(p1.loading);
388
- const x: any = r;
389
- const successMsg = p1.resource.value('msg_save_success');
390
- const newMod = flag.newMode;
391
- const st = createEditStatus(p ? p.status : undefined);
392
- if (Array.isArray(x)) {
393
- fail(x);
394
- } else if (!isNaN(x)) {
395
- if (x === st.success) {
396
- succeed(origin, successMsg, version, backOnSave);
397
- } else {
398
- if (newMod && x === st.duplicate_key) {
399
- handleDuplicateKey();
400
- } else if (!newMod && x === st.not_found) {
401
- handleNotFound();
402
- } else if (!newMod && x === st.version_error) {
403
- const title = p1.resource.value('error');
404
- const err = p1.resource.value('error_version');
405
- p1.showError(err, title);
406
- } else {
407
- handleStatus(x as number, st, p1.resource.value, p1.showError);
408
- }
409
- }
410
- } else {
411
- const result = r as T;
412
- if (isPatch) {
413
- const keys = Object.keys(result as any);
414
- const a: any = origin;
415
- for (const k of keys) {
416
- a[k] = (result as any)[k];
417
- }
418
- succeed(a, successMsg, undefined, backOnSave);
419
- } else {
420
- succeed(origin, successMsg, version, backOnSave, r as T);
421
- }
422
- p1.showMessage(successMsg);
423
- }
424
- };
425
- const postSave = (p && p.postSave ? p.postSave : _postSave);
426
-
427
- const _handleDuplicateKey = (result?: T) => {
428
- const msg = message(p1.resource.value, 'error_duplicate_key', 'error');
429
- p1.showError(msg.message, msg.title);
430
- };
431
- const handleDuplicateKey = (p && p.handleDuplicateKey ? p.handleDuplicateKey : _handleDuplicateKey);
432
-
433
- const _doSave = (obj: T, body?: Partial<T>, version?: string, isBack?: boolean) => {
434
- setRunning(true);
435
- showLoading(p1.loading);
436
- const isBackO = (isBack != null && isBack !== undefined ? isBack : false);
437
- const patchable = (p ? p.patchable : true);
438
- if (flag.newMode === false) {
439
- if (service.patch && patchable !== false && body && Object.keys(body).length > 0) {
440
- service.patch(body).then(result => {
441
- postSave(result, obj, version, true, isBackO);
442
- }).catch(handleError);
443
- } else {
444
- service.update(obj).then(result => postSave(result, obj, version, false, isBackO)).catch(handleError);
445
- }
446
- } else {
447
- service.insert(obj).then(result => postSave(result, obj, version, false, isBackO)).catch(handleError);
448
- }
449
- };
450
-
451
- const doSave = (p && p.doSave ? p.doSave : _doSave);
452
-
453
- const _load = (_id: ID|null, callback?: (m: T, showM: (m2: T) => void) => void) => {
454
- const id: any = _id;
455
- if (id != null && id !== '') {
456
- setRunning(true);
457
- showLoading(p1.loading);
458
- service.load(id).then(obj => {
459
- if (!obj) {
460
- handleNotFound(refForm.current);
461
- } else {
462
- setFlag({ newMode: false, originalModel: clone(obj) });
463
- if (callback) {
464
- callback(obj, showModel);
465
- } else {
466
- showModel(obj);
467
- }
468
- }
469
- setRunning(false);
470
- hideLoading(p1.loading);
471
- }).catch(err => {
472
- const data = (err && err.response) ? err.response : err;
473
- const r = p1.resource;
474
- const title = r.value('error');
475
- let msg = r.value('error_internal');
476
- if (data && data.status === 422) {
477
- fail(err.response?.data);
478
- const obj = err.response?.data?.value;
479
- if (obj) {
480
- callback ? callback(obj as T, showModel) : showModel(obj as T);
481
- }
482
- } else {
483
- if (data && data.status === 404) {
484
- handleNotFound(refForm.current);
485
- } else {
486
- if (data.status && !isNaN(data.status)) {
487
- msg = messageByHttpStatus(data.status, r.value);
488
- }
489
- if (data && (data.status === 401 || data.status === 403)) {
490
- setReadOnly(refForm.current);
491
- }
492
- p1.showError(msg, title);
493
- }
494
- }
495
- setRunning(false);
496
- hideLoading(p1.loading);
497
- });
498
- } else {
499
- const obj = createModel();
500
- setFlag({ newMode: true, originalModel: undefined });
501
- if (callback) {
502
- callback(obj, showModel);
503
- } else {
504
- showModel(obj);
505
- }
506
- }
507
- };
508
- const load = (p && p.load ? p.load : _load);
509
-
510
- return {
511
- ...baseProps,
512
- back,
513
- refForm,
514
- ui: p1.ui,
515
- resource: p1.resource.resource(),
516
- flag,
517
- running,
518
- setRunning,
519
- showModel,
520
- getModelName,
521
- resetState,
522
- handleNotFound,
523
- getModel,
524
- createModel,
525
- create,
526
- save,
527
- onSave,
528
- // eslint-disable-next-line no-restricted-globals
529
- confirm,
530
- validate,
531
- showMessage: p1.showMessage,
532
- succeed,
533
- fail,
534
- postSave,
535
- handleDuplicateKey,
536
- load,
537
- doSave
538
- };
539
- };
1
+ import {useEffect, useState} from 'react';
2
+ import {useNavigate, useParams} from 'react-router';
3
+ import {Attributes, buildId, createEditStatus, EditStatusConfig, ErrorMessage, getModelName as getModelName2, hideLoading, initForm, LoadingService, Locale, message, messageByHttpStatus, ResourceService, showLoading, UIService} from './core';
4
+ import {build, createModel as createModel2, EditParameter, GenericService, handleStatus, handleVersion, initPropertyNullInModel} from './edit';
5
+ import {focusFirstError, readOnly as setReadOnly} from './formutil';
6
+ import {DispatchWithCallback, useMergeState} from './merge';
7
+ import {clone, makeDiff} from './reflect';
8
+ import {localeOf} from './state';
9
+ import {useUpdate} from './update';
10
+
11
+ export interface BaseEditComponentParam<T, ID> {
12
+ status?: EditStatusConfig;
13
+ backOnSuccess?: boolean;
14
+ name?: string;
15
+ metadata?: Attributes;
16
+ keys?: string[];
17
+ version?: string;
18
+ setBack?: boolean;
19
+ patchable?: boolean;
20
+
21
+ addable?: boolean;
22
+ readOnly?: boolean;
23
+ deletable?: boolean;
24
+
25
+ insertSuccessMsg?: string;
26
+ updateSuccessMsg?: string;
27
+
28
+ handleNotFound?: (form?: HTMLFormElement) => void;
29
+ getModelName?: (f?: HTMLFormElement) => string;
30
+ getModel?: () => T;
31
+ showModel?: (m: T) => void;
32
+ createModel?: () => T;
33
+ onSave?: (isBack?: boolean) => void;
34
+ validate?: (obj: T, callback: (obj2?: T) => void) => void;
35
+ succeed?: (msg: string, origin: T, version?: string, isBack?: boolean, model?: T) => void;
36
+ fail?: (result: ErrorMessage[]) => void;
37
+ postSave?: (res: number|T|ErrorMessage[], origin: T, version?: string, isPatch?: boolean, backOnSave?: boolean) => void;
38
+ handleError?: (error: any) => void;
39
+ handleDuplicateKey?: (result?: T) => void;
40
+ load?: (i: ID|null, callback?: (m: T, showM: (m2: T) => void) => void) => void;
41
+ doSave?: (obj: T, diff?: T, version?: string, isBack?: boolean) => void;
42
+ // prepareCustomData?: (data: any) => void; // need to review
43
+ }
44
+ export interface HookBaseEditParameter<T, ID, S> extends BaseEditComponentParam<T, ID> {
45
+ refForm: any;
46
+ initialState: S;
47
+ service: GenericService<T, ID, number|T|ErrorMessage[]>;
48
+ resource: ResourceService;
49
+ showMessage: (msg: string) => void;
50
+ showError: (m: string, header?: string, detail?: string, callback?: () => void) => void;
51
+ getLocale?: () => Locale;
52
+ confirm: (m2: string, header?: string, yesCallback?: () => void, btnLeftText?: string, btnRightText?: string, noCallback?: () => void) => void;
53
+ ui?: UIService;
54
+ loading?: LoadingService;
55
+ }
56
+ export interface EditComponentParam<T, ID, S> extends BaseEditComponentParam<T, ID> {
57
+ initialize?: (id: ID|null, ld: (i: ID|null, cb?: (m: T, showF: (model: T) => void) => void) => void, setState2: DispatchWithCallback<Partial<S>>, callback?: (m: T, showF: (model: T) => void) => void) => void;
58
+ callback?: (m: T, showF: (model: T) => void) => void;
59
+ }
60
+ export interface HookPropsEditParameter<T, ID, S, P> extends HookPropsBaseEditParameter<T, ID, S, P> {
61
+ initialize?: (id: ID|null, ld: (i: ID|null, cb?: (m: T, showF: (model: T) => void) => void) => void, setState2: DispatchWithCallback<Partial<S>>, callback?: (m: T, showF: (model: T) => void) => void) => void;
62
+ callback?: (m: T, showF: (model: T) => void) => void;
63
+ }
64
+ export interface HookPropsBaseEditParameter<T, ID, S, P> extends HookBaseEditParameter<T, ID, S> {
65
+ props: P;
66
+ // prepareCustomData?: (data: any) => void;
67
+ }
68
+ export const useEdit = <T, ID, S>(
69
+ refForm: any,
70
+ initialState: S,
71
+ service: GenericService<T, ID, number|T|ErrorMessage[]>,
72
+
73
+ p2: EditParameter,
74
+ p?: EditComponentParam<T, ID, S>
75
+ ) => {
76
+ const params = useParams();
77
+ const baseProps = useCoreEdit(refForm, initialState, service, p2, p);
78
+ useEffect(() => {
79
+ if (refForm) {
80
+ const registerEvents = (p2.ui ? p2.ui.registerEvents : undefined);
81
+ initForm(baseProps.refForm.current, registerEvents);
82
+ }
83
+ const n = baseProps.getModelName(refForm.current);
84
+ const obj: any = {};
85
+ obj[n] = baseProps.createModel();
86
+ baseProps.setState(obj);
87
+ let keys: string[]|undefined;
88
+ if (p && !p.keys && service && service.metadata) {
89
+ const metadata = (p.metadata ? p.metadata : service.metadata());
90
+ if (metadata) {
91
+ const meta = build(metadata);
92
+ keys = (p.keys ? p.keys : (meta ? meta.keys : undefined));
93
+ const version = (p.version ? p.version : (meta ? meta.version : undefined));
94
+ p.keys = keys;
95
+ p.version = version;
96
+ }
97
+ }
98
+ const id = buildId<ID>(params, keys);
99
+ if (p && p.initialize) {
100
+ p.initialize(id, baseProps.load, baseProps.setState, p.callback);
101
+ } else {
102
+ try {
103
+ baseProps.load(id, p ? p.callback : undefined);
104
+ } catch (error) {
105
+ p2.showError(error as string);
106
+ hideLoading(p2.loading);
107
+ }
108
+ }
109
+ // eslint-disable-next-line react-hooks/exhaustive-deps
110
+ }, []);
111
+ return {...baseProps};
112
+ };
113
+ export const useEditProps = <T, ID, S, P>(
114
+ props: P,
115
+ refForm: any,
116
+ initialState: S,
117
+ service: GenericService<T, ID, number|T|ErrorMessage[]>,
118
+ p2: EditParameter,
119
+ p?: EditComponentParam<T, ID, S>
120
+ ) => {
121
+ const params = useParams();
122
+ const baseProps = useCoreEdit<T, ID, S, P>(refForm, initialState, service, p2, p, props);
123
+ useEffect(() => {
124
+ if (refForm) {
125
+ const registerEvents = (p2.ui ? p2.ui.registerEvents : undefined);
126
+ initForm(baseProps.refForm.current, registerEvents);
127
+ }
128
+ const n = baseProps.getModelName(refForm.current);
129
+ const obj: any = {};
130
+ obj[n] = baseProps.createModel();
131
+ baseProps.setState(obj);
132
+ let keys: string[]|undefined;
133
+ if (p && !p.keys && service && service.metadata) {
134
+ const metadata = (p.metadata ? p.metadata : service.metadata());
135
+ if (metadata) {
136
+ const meta = build(metadata);
137
+ keys = (p.keys ? p.keys : (meta ? meta.keys : undefined));
138
+ const version = (p.version ? p.version : (meta ? meta.version : undefined));
139
+ p.keys = keys;
140
+ p.version = version;
141
+ }
142
+ }
143
+ const id = buildId<ID>(params, keys);
144
+ if (p && p.initialize) {
145
+ p.initialize(id, baseProps.load, baseProps.setState, p.callback);
146
+ } else {
147
+ baseProps.load(id, p ? p.callback : undefined);
148
+ }
149
+ // eslint-disable-next-line react-hooks/exhaustive-deps
150
+ }, []);
151
+ return {...baseProps};
152
+ };
153
+ export const useEditOneProps = <T, ID, S, P>(p: HookPropsEditParameter<T, ID, S, P>) => {
154
+ return useEditProps(p.props, p.refForm, p.initialState, p.service, p, p);
155
+ };
156
+ export const useEditOne = <T, ID, S>(p: HookBaseEditParameter<T, ID, S>) => {
157
+ return useEdit(p.refForm, p.initialState, p.service, p, p);
158
+ };
159
+ export const useCoreEdit = <T, ID, S, P>(
160
+ refForm: any,
161
+ initialState: S,
162
+ service: GenericService<T, ID, number|T|ErrorMessage[]>,
163
+ p1: EditParameter,
164
+ p?: BaseEditComponentParam<T, ID>,
165
+ props?: P
166
+ ) => {
167
+ /*
168
+ const {
169
+ backOnSuccess = true,
170
+ patchable = true,
171
+ addable = true
172
+ } = p; */
173
+ const navigate = useNavigate();
174
+ const addable = (p && p.patchable !== false ? true : undefined);
175
+ const back = (event?: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
176
+ if (event) {
177
+ event.preventDefault();
178
+ }
179
+ navigate(-1);
180
+ };
181
+
182
+ const [running, setRunning] = useState<boolean>();
183
+
184
+ const getModelName = (f?: HTMLFormElement|null): string => {
185
+ if (p && p.name && p.name.length > 0) {
186
+ return p.name;
187
+ }
188
+ return getModelName2(f);
189
+ };
190
+ const baseProps = useUpdate<S>(initialState, getModelName, p1.getLocale);
191
+
192
+ const { state, setState } = baseProps;
193
+ const [flag, setFlag] = useMergeState({
194
+ newMode: false,
195
+ setBack: false,
196
+ addable,
197
+ readOnly: p ? p.readOnly : undefined,
198
+ originalModel: undefined
199
+ });
200
+
201
+ const showModel = (model: T) => {
202
+ const n = getModelName(refForm.current);
203
+ const objSet: any = {};
204
+ objSet[n] = model;
205
+ setState(objSet);
206
+ if (p && p.readOnly) {
207
+ const f = refForm.current;
208
+ setReadOnly(f);
209
+ }
210
+ };
211
+
212
+ const resetState = (newMode: boolean, model: T, originalModel?: T) => {
213
+ setFlag({ newMode, originalModel } as any);
214
+ showModel(model);
215
+ };
216
+
217
+ const _handleNotFound = (form?: any): void => {
218
+ const msg = message(p1.resource.value, 'error_404', 'error');
219
+ if (form) {
220
+ setReadOnly(form);
221
+ }
222
+ p1.showError(msg.message, msg.title, undefined, () => window.history.back);
223
+ };
224
+ const handleNotFound = (p && p.handleNotFound ? p.handleNotFound : _handleNotFound);
225
+
226
+ const _getModel = () => {
227
+ const n = getModelName(refForm.current);
228
+ if (props) {
229
+ return (props as any)[n] || (state as any)[n];
230
+ } else {
231
+ return (state as any)[n];
232
+ }
233
+ };
234
+ const getModel = (p && p.getModel ? p.getModel : _getModel);
235
+
236
+ const _createModel = (): T => {
237
+ const metadata = (p && p.metadata ? p.metadata : (service.metadata ? service.metadata() : undefined));
238
+ if (metadata) {
239
+ const obj = createModel2<T>(metadata);
240
+ return obj;
241
+ } else {
242
+ const obj: any = {};
243
+ return obj;
244
+ }
245
+ };
246
+ const createModel = (p && p.createModel ? p.createModel : _createModel);
247
+
248
+ const create = (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
249
+ event.preventDefault();
250
+ const obj = createModel();
251
+ resetState(true, obj, undefined);
252
+ const u = p1.ui;
253
+ if (u) {
254
+ setTimeout(() => {
255
+ u.removeFormError(refForm.current);
256
+ }, 100);
257
+ }
258
+ };
259
+
260
+ const _onSave = (isBack?: boolean) => {
261
+ if (flag.newMode === true && flag.addable === false) {
262
+ const m = message(p1.resource.value, 'error_permission_add', 'error_permission');
263
+ p1.showError(m.message, m.title);
264
+ return;
265
+ } else if (p && flag.newMode === false && p.readOnly) {
266
+ const msg = message(p1.resource.value, 'error_permission_edit', 'error_permission');
267
+ p1.showError(msg.message, msg.title);
268
+ return;
269
+ } else {
270
+ if (running === true) {
271
+ return;
272
+ }
273
+ const obj = getModel();
274
+ const metadata = (p && p.metadata ? p.metadata : (service.metadata ? service.metadata() : undefined));
275
+ let keys: string[]|undefined;
276
+ let version: string|undefined;
277
+ if (p && metadata && (!p.keys || !p.version)) {
278
+ const meta = build(metadata);
279
+ keys = (p.keys ? p.keys : (meta ? meta.keys : undefined));
280
+ version = (p.version ? p.version : (meta ? meta.version : undefined));
281
+ }
282
+ if (flag.newMode) {
283
+ validate(obj, () => {
284
+ const msg = message(p1.resource.value, 'msg_confirm_save', 'confirm', 'yes', 'no');
285
+ p1.confirm(msg.message, msg.title, () => {
286
+ doSave(obj, undefined, version, isBack);
287
+ }, msg.no, msg.yes);
288
+ });
289
+ } else {
290
+ const diffObj = makeDiff(initPropertyNullInModel(flag.originalModel, metadata), obj, keys, version);
291
+ const objKeys = Object.keys(diffObj);
292
+ if (objKeys.length === 0) {
293
+ p1.showMessage(p1.resource.value('msg_no_change'));
294
+ } else {
295
+ validate(obj, () => {
296
+ const msg = message(p1.resource.value, 'msg_confirm_save', 'confirm', 'yes', 'no');
297
+ p1.confirm(msg.message, msg.title, () => {
298
+ doSave(obj, diffObj as any, version, isBack);
299
+ }, msg.no, msg.yes);
300
+ });
301
+ }
302
+ }
303
+ }
304
+ };
305
+ const onSave = (p && p.onSave ? p.onSave : _onSave);
306
+
307
+ const save = (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
308
+ event.preventDefault();
309
+ event.persist();
310
+ onSave();
311
+ };
312
+
313
+ const _validate = (obj: T, callback: (obj2?: T) => void) => {
314
+ if (p1.ui) {
315
+ const valid = p1.ui.validateForm(refForm.current, localeOf(undefined, p1.getLocale));
316
+ if (valid) {
317
+ callback(obj);
318
+ }
319
+ } else {
320
+ callback(obj);
321
+ }
322
+ };
323
+ const validate = (p && p.validate ? p.validate : _validate);
324
+
325
+ const _succeed = (msg: string, origin: T, version?: string, isBack?: boolean, model?: T) => {
326
+ if (model) {
327
+ setFlag({ newMode: false });
328
+ if (model && flag.setBack === true) {
329
+ resetState(false, model, clone(model));
330
+ } else {
331
+ handleVersion(origin, version);
332
+ }
333
+ } else {
334
+ handleVersion(origin, version);
335
+ }
336
+ p1.showMessage(msg);
337
+ if (isBack) {
338
+ back(undefined);
339
+ }
340
+ };
341
+ const succeed = (p && p.succeed ? p.succeed : _succeed);
342
+
343
+ const _fail = (result: ErrorMessage[]) => {
344
+ const f = refForm.current;
345
+ const u = p1.ui;
346
+ if (u && f) {
347
+ const unmappedErrors = u.showFormError(f, result);
348
+ focusFirstError(f);
349
+ if (unmappedErrors && unmappedErrors.length > 0) {
350
+ const t = p1.resource.value('error');
351
+ if (p1.ui && p1.ui.buildErrorMessage) {
352
+ const msg = p1.ui.buildErrorMessage(unmappedErrors);
353
+ p1.showError(msg, t);
354
+ } else {
355
+ p1.showError(unmappedErrors[0].field + ' ' + unmappedErrors[0].code + ' ' + unmappedErrors[0].message, t);
356
+ }
357
+ }
358
+ } else {
359
+ const t = p1.resource.value('error');
360
+ if (result.length > 0) {
361
+ p1.showError(result[0].field + ' ' + result[0].code + ' ' + result[0].message, t);
362
+ } else {
363
+ p1.showError(t, t);
364
+ }
365
+ }
366
+ };
367
+ const fail = (p && p.fail ? p.fail : _fail);
368
+
369
+ const _handleError = function (err: any) {
370
+ if (err) {
371
+ setRunning(false);
372
+ hideLoading(p1.loading);
373
+ const errMsg = p1.resource.value('error_internal');
374
+ const data = (err && err.response) ? err.response : err;
375
+ if (data.status === 400) {
376
+ const errMsg = p1.resource.value('error_400');
377
+ p1.showError(errMsg, "Error");
378
+ } else{
379
+ p1.showError(errMsg, "Error");
380
+ }
381
+ }
382
+ };
383
+ const handleError = (p && p.handleError ? p.handleError : _handleError);
384
+
385
+ const _postSave = (r: number | T|ErrorMessage[], origin: T, version?: string, isPatch?: boolean, backOnSave?: boolean) => {
386
+ setRunning(false);
387
+ hideLoading(p1.loading);
388
+ const x: any = r;
389
+ const successMsg = p1.resource.value('msg_save_success');
390
+ const newMod = flag.newMode;
391
+ const st = createEditStatus(p ? p.status : undefined);
392
+ if (Array.isArray(x)) {
393
+ fail(x);
394
+ } else if (!isNaN(x)) {
395
+ if (x === st.success) {
396
+ succeed(successMsg, origin, version, backOnSave);
397
+ } else {
398
+ if (newMod && x === st.duplicate_key) {
399
+ handleDuplicateKey();
400
+ } else if (!newMod && x === st.not_found) {
401
+ handleNotFound();
402
+ } else if (!newMod && x === st.version_error) {
403
+ const title = p1.resource.value('error');
404
+ const err = p1.resource.value('error_version');
405
+ p1.showError(err, title);
406
+ } else {
407
+ handleStatus(x as number, st, p1.resource.value, p1.showError);
408
+ }
409
+ }
410
+ } else {
411
+ const result = r as T;
412
+ if (isPatch) {
413
+ const keys = Object.keys(result as any);
414
+ const a: any = origin;
415
+ for (const k of keys) {
416
+ a[k] = (result as any)[k];
417
+ }
418
+ succeed(successMsg, a, undefined, backOnSave, a);
419
+ } else {
420
+ succeed(successMsg, origin, version, backOnSave, r as T);
421
+ }
422
+ p1.showMessage(successMsg);
423
+ }
424
+ };
425
+ const postSave = (p && p.postSave ? p.postSave : _postSave);
426
+
427
+ const _handleDuplicateKey = (result?: T) => {
428
+ const msg = message(p1.resource.value, 'error_duplicate_key', 'error');
429
+ p1.showError(msg.message, msg.title);
430
+ };
431
+ const handleDuplicateKey = (p && p.handleDuplicateKey ? p.handleDuplicateKey : _handleDuplicateKey);
432
+
433
+ const _doSave = (obj: T, body?: Partial<T>, version?: string, isBack?: boolean) => {
434
+ setRunning(true);
435
+ showLoading(p1.loading);
436
+ const isBackO = (isBack != null && isBack !== undefined ? isBack : false);
437
+ const patchable = (p ? p.patchable : true);
438
+ if (flag.newMode === false) {
439
+ if (service.patch && patchable !== false && body && Object.keys(body).length > 0) {
440
+ service.patch(body).then(result => {
441
+ postSave(result, obj, version, true, isBackO);
442
+ }).catch(handleError);
443
+ } else {
444
+ service.update(obj).then(result => postSave(result, obj, version, false, isBackO)).catch(handleError);
445
+ }
446
+ } else {
447
+ service.insert(obj).then(result => postSave(result, obj, version, false, isBackO)).catch(handleError);
448
+ }
449
+ };
450
+
451
+ const doSave = (p && p.doSave ? p.doSave : _doSave);
452
+
453
+ const _load = (_id: ID|null, callback?: (m: T, showM: (m2: T) => void) => void) => {
454
+ const id: any = _id;
455
+ if (id != null && id !== '') {
456
+ setRunning(true);
457
+ showLoading(p1.loading);
458
+ service.load(id).then(obj => {
459
+ if (!obj) {
460
+ handleNotFound(refForm.current);
461
+ } else {
462
+ setFlag({ newMode: false, originalModel: clone(obj) });
463
+ if (callback) {
464
+ callback(obj, showModel);
465
+ } else {
466
+ showModel(obj);
467
+ }
468
+ }
469
+ setRunning(false);
470
+ hideLoading(p1.loading);
471
+ }).catch(err => {
472
+ const data = (err && err.response) ? err.response : err;
473
+ const r = p1.resource;
474
+ const title = r.value('error');
475
+ let msg = r.value('error_internal');
476
+ if (data && data.status === 422) {
477
+ fail(err.response?.data);
478
+ const obj = err.response?.data?.value;
479
+ if (obj) {
480
+ callback ? callback(obj as T, showModel) : showModel(obj as T);
481
+ }
482
+ } else {
483
+ if (data && data.status === 404) {
484
+ handleNotFound(refForm.current);
485
+ } else {
486
+ if (data.status && !isNaN(data.status)) {
487
+ msg = messageByHttpStatus(data.status, r.value);
488
+ }
489
+ if (data && (data.status === 401 || data.status === 403)) {
490
+ setReadOnly(refForm.current);
491
+ }
492
+ p1.showError(msg, title);
493
+ }
494
+ }
495
+ setRunning(false);
496
+ hideLoading(p1.loading);
497
+ });
498
+ } else {
499
+ const obj = createModel();
500
+ setFlag({ newMode: true, originalModel: undefined });
501
+ if (callback) {
502
+ callback(obj, showModel);
503
+ } else {
504
+ showModel(obj);
505
+ }
506
+ }
507
+ };
508
+ const load = (p && p.load ? p.load : _load);
509
+
510
+ return {
511
+ ...baseProps,
512
+ back,
513
+ refForm,
514
+ ui: p1.ui,
515
+ resource: p1.resource.resource(),
516
+ flag,
517
+ running,
518
+ setRunning,
519
+ showModel,
520
+ getModelName,
521
+ resetState,
522
+ handleNotFound,
523
+ getModel,
524
+ createModel,
525
+ create,
526
+ save,
527
+ onSave,
528
+ // eslint-disable-next-line no-restricted-globals
529
+ confirm,
530
+ validate,
531
+ showMessage: p1.showMessage,
532
+ succeed,
533
+ fail,
534
+ postSave,
535
+ handleDuplicateKey,
536
+ load,
537
+ doSave
538
+ };
539
+ };