@flowerforce/flower-core 3.3.1-beta.1 → 4.0.1-beta.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/dist/index.cjs.js +241 -271
- package/dist/index.esm.js +231 -270
- package/dist/src/constants/index.d.ts +5 -0
- package/dist/src/event-emitter/index.d.ts +1 -0
- package/dist/src/index.d.ts +6 -8
- package/dist/src/interfaces/CoreInterface.d.ts +23 -17
- package/dist/src/interfaces/ReducerInterface.d.ts +117 -99
- package/dist/src/{rules-matcher/interface.d.ts → interfaces/RulesMatcherInterface.d.ts} +1 -1
- package/dist/src/interfaces/SelectorsInterface.d.ts +21 -12
- package/dist/src/interfaces/Store.d.ts +2 -10
- package/dist/src/interfaces/UtilsInterface.d.ts +1 -1
- package/dist/src/interfaces/index.d.ts +3 -0
- package/dist/src/rules-matcher/RulesMatcher.d.ts +2 -0
- package/dist/src/rules-matcher/index.d.ts +2 -0
- package/dist/src/rules-matcher/utils.d.ts +2 -3
- package/dist/src/state-manager/index.d.ts +2 -0
- package/dist/src/state-manager/state-functions/FlowerCoreMergedReducers.d.ts +2 -0
- package/dist/src/state-manager/state-functions/FlowerCoreStateFunctions.d.ts +5 -0
- package/dist/src/state-manager/state-functions/FlowerDataStateFunctions.d.ts +13 -0
- package/dist/src/state-manager/state-functions/index.d.ts +4 -0
- package/dist/src/state-manager/state-selectors/FlowerCoreStateSelectors.d.ts +2 -0
- package/dist/src/state-manager/state-selectors/FlowerFormStateSelectors.d.ts +2 -0
- package/dist/src/state-manager/state-selectors/FlowerSelectorsMerged.d.ts +2 -0
- package/dist/src/state-manager/state-selectors/index.d.ts +4 -0
- package/dist/src/{FlowerCoreStateUtils.d.ts → utils/FlowerCoreStateUtils.d.ts} +2 -2
- package/dist/src/{CoreUtils.d.ts → utils/FlowerCoreUtils.d.ts} +1 -2
- package/dist/src/utils/FlowerFlowUtils.d.ts +3 -0
- package/dist/src/utils/FlowerFormCoreUtils.d.ts +2 -0
- package/dist/src/utils/index.d.ts +4 -0
- package/package.json +1 -1
- package/dist/src/FlowerCoreStateFunctions.d.ts +0 -5
- package/dist/src/FlowerCoreStateSelectors.d.ts +0 -2
- package/dist/src/RulesMatcher.d.ts +0 -5
- package/dist/src/devtoolState.d.ts +0 -2
- /package/dist/src/{Emitter.d.ts → event-emitter/Emitter.d.ts} +0 -0
package/dist/index.esm.js
CHANGED
@@ -1,11 +1,5 @@
|
|
1
1
|
import { TinyEmitter } from 'tiny-emitter';
|
2
|
-
import _set from 'lodash/set';
|
3
|
-
import _unset from 'lodash/unset';
|
4
2
|
import _get from 'lodash/get';
|
5
|
-
import _last from 'lodash/last';
|
6
|
-
import _slice from 'lodash/slice';
|
7
|
-
import _cloneDeep from 'lodash/cloneDeep';
|
8
|
-
import lastIndexOf from 'lodash/lastIndexOf';
|
9
3
|
import find from 'lodash/find';
|
10
4
|
import keyBy from 'lodash/keyBy';
|
11
5
|
import has from 'lodash/has';
|
@@ -16,10 +10,56 @@ import mapKeys from 'lodash/mapKeys';
|
|
16
10
|
import mapValues from 'lodash/mapValues';
|
17
11
|
import _trimStart from 'lodash/trimStart';
|
18
12
|
import _intersection from 'lodash/intersection';
|
13
|
+
import _set from 'lodash/set';
|
14
|
+
import _last from 'lodash/last';
|
15
|
+
import _slice from 'lodash/slice';
|
16
|
+
import _cloneDeep from 'lodash/cloneDeep';
|
17
|
+
import lastIndexOf from 'lodash/lastIndexOf';
|
18
|
+
import _unset from 'lodash/unset';
|
19
19
|
import { unflatten } from 'flat';
|
20
20
|
|
21
21
|
const Emitter = new TinyEmitter();
|
22
22
|
|
23
|
+
var REDUCER_NAME;
|
24
|
+
(function (REDUCER_NAME) {
|
25
|
+
REDUCER_NAME["FLOWER_FLOW"] = "FlowerFlow";
|
26
|
+
REDUCER_NAME["FLOWER_DATA"] = "FlowerData";
|
27
|
+
})(REDUCER_NAME || (REDUCER_NAME = {}));
|
28
|
+
const devtoolState = {};
|
29
|
+
|
30
|
+
const FlowerStateUtils = {
|
31
|
+
getAllData: (state) => state &&
|
32
|
+
Object.entries(state ?? {}).reduce((acc, [k, v]) => ({ ...acc, [k]: v?.data ?? v }), {}),
|
33
|
+
selectFlowerFormNode: (name) => (state) => _get(state, name),
|
34
|
+
makeSelectCurrentNextRules: (name) => (state) => {
|
35
|
+
const nextRules = _get(state, [name, 'nextRules']);
|
36
|
+
const currentNodeId = FlowerStateUtils.makeSelectCurrentNodeId(name)(state);
|
37
|
+
return _get(nextRules, [currentNodeId]);
|
38
|
+
},
|
39
|
+
makeSelectCurrentNodeId: (name) => (state) => {
|
40
|
+
const subState = _get(state, [name]);
|
41
|
+
const startId = _get(state, ['startId']);
|
42
|
+
return _get(subState, ['current']) || startId;
|
43
|
+
},
|
44
|
+
makeSelectNodeErrors: (name) => (state) => {
|
45
|
+
const form = FlowerStateUtils.selectFlowerFormNode(name)(state);
|
46
|
+
return createFormData(form);
|
47
|
+
}
|
48
|
+
};
|
49
|
+
const createFormData = (form) => {
|
50
|
+
const validationErrors = form && form.errors;
|
51
|
+
const allErrors = Object.values(validationErrors || {});
|
52
|
+
return {
|
53
|
+
isSubmitted: form?.isSubmitted || false,
|
54
|
+
isDirty: Object.values(form?.dirty || {}).some(Boolean) || false,
|
55
|
+
hasFocus: form?.hasFocus,
|
56
|
+
errors: form?.errors,
|
57
|
+
customErrors: form?.customErrors,
|
58
|
+
isValidating: form?.isValidating,
|
59
|
+
isValid: allErrors.flat().length === 0
|
60
|
+
};
|
61
|
+
};
|
62
|
+
|
23
63
|
const EMPTY_STRING_REGEXP = /^\s*$/;
|
24
64
|
/**
|
25
65
|
* Defines a utility object named rulesMatcherUtils, which contains various helper functions used for processing rules and data in a rule-matching context.
|
@@ -240,10 +280,6 @@ const rulesMatcher = (rules, formValue = {}, apply = true, options) => {
|
|
240
280
|
const valid = rulesMatcherUtils.checkRule(conditions, formValue, options ?? {});
|
241
281
|
return [valid === apply];
|
242
282
|
};
|
243
|
-
const MatchRules = {
|
244
|
-
rulesMatcher,
|
245
|
-
utils: rulesMatcherUtils
|
246
|
-
};
|
247
283
|
|
248
284
|
/* eslint-disable no-useless-escape */
|
249
285
|
// TODO align this set of functions to selectors and reducers functions
|
@@ -266,36 +302,12 @@ const flattenRules = (ob) => {
|
|
266
302
|
}
|
267
303
|
return result;
|
268
304
|
};
|
269
|
-
// export const searchEmptyKeyRecursively = <T extends object>(
|
270
|
-
// _key: "$and" | "$or",
|
271
|
-
// obj: T
|
272
|
-
// ) => {
|
273
|
-
// if (
|
274
|
-
// isEmpty(obj) ||
|
275
|
-
// typeof obj !== "object" ||
|
276
|
-
// Object.keys(obj).length === 0
|
277
|
-
// ) {
|
278
|
-
// return true;
|
279
|
-
// }
|
280
|
-
// if (Object.keys(obj).includes(_key)) {
|
281
|
-
// if (obj[_key] && obj[_key].length === 0) return true;
|
282
|
-
// return Object.keys(obj).map((key) =>
|
283
|
-
// searchEmptyKeyRecursively(_key, obj[key])
|
284
|
-
// );
|
285
|
-
// }
|
286
|
-
// return Object.keys(obj)
|
287
|
-
// .map((key) => searchEmptyKeyRecursively(_key, obj[key]))
|
288
|
-
// .every((v) => v === true);
|
289
|
-
// };
|
290
305
|
const getRulesExists = (rules) => {
|
291
|
-
return Object.keys(rules).length ?
|
306
|
+
return Object.keys(rules).length ? FlowUtils.mapEdge(rules) : undefined;
|
292
307
|
};
|
293
|
-
|
294
|
-
* Defines a collection of utility functions for processing rules, nodes and graph-like structures
|
295
|
-
*/
|
296
|
-
const CoreUtils = {
|
308
|
+
const FlowUtils = {
|
297
309
|
generateRulesName: (nextRules) => {
|
298
|
-
|
310
|
+
return nextRules.reduce((acc, inc) => {
|
299
311
|
const n = typeof inc.rules === 'string'
|
300
312
|
? inc.rules || '__ERROR_NAME__'
|
301
313
|
: inc.rules?.name || '__ERROR_NAME__';
|
@@ -304,7 +316,6 @@ const CoreUtils = {
|
|
304
316
|
[n]: inc.nodeId
|
305
317
|
};
|
306
318
|
}, {});
|
307
|
-
return a;
|
308
319
|
},
|
309
320
|
mapKeysDeepLodash: (obj, cb, isRecursive) => {
|
310
321
|
/* istanbul ignore next */
|
@@ -320,13 +331,13 @@ const CoreUtils = {
|
|
320
331
|
}
|
321
332
|
}
|
322
333
|
if (Array.isArray(obj)) {
|
323
|
-
return obj.map((item) =>
|
334
|
+
return obj.map((item) => FlowUtils.mapKeysDeepLodash(item, cb, true));
|
324
335
|
}
|
325
336
|
if (!isPlainObject(obj)) {
|
326
337
|
return obj;
|
327
338
|
}
|
328
339
|
const result = mapKeys(obj, cb);
|
329
|
-
return mapValues(result, (value) =>
|
340
|
+
return mapValues(result, (value) => FlowUtils.mapKeysDeepLodash(value, cb, true));
|
330
341
|
},
|
331
342
|
generateNodes: (nodes) => keyBy(nodes.map((s) => omit(s, 'nextRules')), 'nodeId'),
|
332
343
|
makeObjectRules: (nodes) => nodes.reduce((acc, inc) => ({ ...acc, [inc.nodeId]: inc.nextRules }), {}),
|
@@ -343,17 +354,18 @@ const CoreUtils = {
|
|
343
354
|
},
|
344
355
|
mapEdge: (nextNode) => {
|
345
356
|
const res = nextNode.sort((a, b) => {
|
346
|
-
const x =
|
347
|
-
const y =
|
357
|
+
const x = FlowUtils.isEmptyRules(a.rules);
|
358
|
+
const y = FlowUtils.isEmptyRules(b.rules);
|
348
359
|
return Number(x) - Number(y);
|
349
360
|
});
|
350
361
|
return res;
|
351
362
|
},
|
352
363
|
makeRules: (rules) => Object.entries(rules).reduce((acc2, [k, v]) => [...acc2, { nodeId: k, rules: v }], []),
|
364
|
+
// TODO: This function is strictly related to React nodes, could make sense to move it in the flower-react folder
|
353
365
|
generateNodesForFlowerJson: (nodes) => nodes
|
354
366
|
.filter((e) => !!_get(e, 'props.id'))
|
355
367
|
.map((e) => {
|
356
|
-
const rules =
|
368
|
+
const rules = FlowUtils.makeRules(e.props.to ?? {});
|
357
369
|
const nextRules = getRulesExists(rules);
|
358
370
|
const children = e.props.data?.children;
|
359
371
|
return {
|
@@ -366,29 +378,6 @@ const CoreUtils = {
|
|
366
378
|
disabled: e.props.disabled
|
367
379
|
};
|
368
380
|
}),
|
369
|
-
cleanPath: (name, char = '^') => _trimStart(name, char),
|
370
|
-
getPath: (idValue) => {
|
371
|
-
if (!idValue) {
|
372
|
-
return {
|
373
|
-
path: []
|
374
|
-
};
|
375
|
-
}
|
376
|
-
if (idValue === '*') {
|
377
|
-
return {
|
378
|
-
path: '*'
|
379
|
-
};
|
380
|
-
}
|
381
|
-
if (idValue.indexOf('^') === 0) {
|
382
|
-
const [flowNameFromPath, ...rest] = CoreUtils.cleanPath(idValue).split('.');
|
383
|
-
return {
|
384
|
-
flowNameFromPath,
|
385
|
-
path: rest
|
386
|
-
};
|
387
|
-
}
|
388
|
-
return {
|
389
|
-
path: idValue.split('.')
|
390
|
-
};
|
391
|
-
},
|
392
381
|
allEqual: (arr, arr2) => arr.length === arr2.length && arr.every((v) => arr2.includes(v)),
|
393
382
|
findValidRule: (nextRules, value, prefix) => find(nextRules, (rule) => {
|
394
383
|
// fix per evitare di entrare in un nodo senza regole, ma con un name,
|
@@ -408,53 +397,52 @@ const CoreUtils = {
|
|
408
397
|
if (typeof rule.rules.rules === 'string') {
|
409
398
|
return false;
|
410
399
|
}
|
411
|
-
const [valid] =
|
400
|
+
const [valid] = rulesMatcher(rule.rules.rules, value, true, {
|
412
401
|
prefix
|
413
402
|
});
|
414
403
|
return valid;
|
415
404
|
})
|
416
405
|
};
|
417
406
|
|
418
|
-
const
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
407
|
+
const FormUtils = {
|
408
|
+
cleanPath: (name, char = '^') => _trimStart(name, char),
|
409
|
+
getPath: (idValue) => {
|
410
|
+
if (!idValue) {
|
411
|
+
return {
|
412
|
+
path: []
|
413
|
+
};
|
414
|
+
}
|
415
|
+
if (idValue === '*') {
|
416
|
+
return {
|
417
|
+
path: '*'
|
418
|
+
};
|
419
|
+
}
|
420
|
+
if (idValue.indexOf('^') === 0) {
|
421
|
+
const [formName, ...rest] = FormUtils.cleanPath(idValue).split('.');
|
422
|
+
return {
|
423
|
+
formName,
|
424
|
+
path: rest
|
425
|
+
};
|
426
|
+
}
|
427
|
+
return {
|
428
|
+
path: idValue.split('.')
|
429
|
+
};
|
435
430
|
}
|
436
431
|
};
|
437
|
-
const createFormData = (form) => {
|
438
|
-
const validationErrors = form && form.errors;
|
439
|
-
const allErrors = Object.values(validationErrors || {});
|
440
|
-
return {
|
441
|
-
isSubmitted: form?.isSubmitted || false,
|
442
|
-
isDirty: form?.isDirty || false,
|
443
|
-
hasFocus: form?.hasFocus,
|
444
|
-
errors: form?.errors,
|
445
|
-
customErrors: form?.customErrors,
|
446
|
-
isValidating: form?.isValidating,
|
447
|
-
isValid: allErrors.flat().length === 0
|
448
|
-
};
|
449
|
-
};
|
450
432
|
|
451
|
-
|
433
|
+
/**
|
434
|
+
* Defines a collection of utility functions for processing rules, nodes and graph-like structures
|
435
|
+
*/
|
436
|
+
const CoreUtils = {
|
437
|
+
...FlowUtils,
|
438
|
+
...FormUtils
|
439
|
+
};
|
452
440
|
|
453
|
-
const { generateNodes, hasNode, makeObjectRules, generateRulesName, findValidRule
|
441
|
+
const { generateNodes, hasNode, makeObjectRules, generateRulesName, findValidRule } = CoreUtils;
|
454
442
|
/**
|
455
443
|
* These functions are Redux reducers used in a Flux architecture for managing state transitions and updates in a Flower application.
|
456
444
|
*/
|
457
|
-
const
|
445
|
+
const FlowerCoreBaseReducers = {
|
458
446
|
historyAdd: (state, { payload }) => {
|
459
447
|
if (hasNode(state, payload.name, payload.node)) {
|
460
448
|
state[payload.name].history.push(payload.node);
|
@@ -473,27 +461,11 @@ const FlowerCoreReducers = {
|
|
473
461
|
}
|
474
462
|
return state;
|
475
463
|
},
|
476
|
-
setFormTouched: (state, { payload }) => {
|
477
|
-
if (!_get(state, [
|
478
|
-
typeof payload === 'string' ? payload : payload.flowName,
|
479
|
-
'nodes',
|
480
|
-
typeof payload === 'string' ? payload : payload.currentNode
|
481
|
-
])) {
|
482
|
-
return state;
|
483
|
-
}
|
484
|
-
_set(state, [
|
485
|
-
typeof payload === 'string' ? payload : payload.flowName,
|
486
|
-
'form',
|
487
|
-
typeof payload === 'string' ? payload : payload.currentNode,
|
488
|
-
'isSubmitted'
|
489
|
-
], true);
|
490
|
-
return state;
|
491
|
-
},
|
492
464
|
// TODO check internal logic and use case
|
493
465
|
/* istanbul ignore next */
|
494
466
|
forceAddHistory: (state, { payload }) => {
|
495
467
|
const { name, flowName, history } = payload;
|
496
|
-
const key = name || flowName || ''
|
468
|
+
const key = name || flowName || '';
|
497
469
|
const resultHistory = history.slice(1, -1);
|
498
470
|
state[key].history.push(...resultHistory);
|
499
471
|
return state;
|
@@ -566,7 +538,8 @@ const FlowerCoreReducers = {
|
|
566
538
|
return state;
|
567
539
|
},
|
568
540
|
destroy: (state, { payload }) => {
|
569
|
-
|
541
|
+
delete state[payload.name];
|
542
|
+
return state;
|
570
543
|
},
|
571
544
|
initNodes: (state, { payload }) => {
|
572
545
|
if (payload.persist && _get(state, [payload.name, 'persist']))
|
@@ -589,8 +562,7 @@ const FlowerCoreReducers = {
|
|
589
562
|
current,
|
590
563
|
history,
|
591
564
|
nodes: generateNodes(payload.nodes),
|
592
|
-
nextRules: makeObjectRules(payload.nodes)
|
593
|
-
data: payload.initialData
|
565
|
+
nextRules: makeObjectRules(payload.nodes)
|
594
566
|
});
|
595
567
|
},
|
596
568
|
// TODO usato solo da flower su vscode
|
@@ -607,105 +579,14 @@ const FlowerCoreReducers = {
|
|
607
579
|
}
|
608
580
|
}
|
609
581
|
},
|
610
|
-
formAddCustomErrors: (state, { payload }) => {
|
611
|
-
_set(state, [payload.name, 'form', payload.currentNode, 'customErrors', payload.id], payload.errors);
|
612
|
-
},
|
613
|
-
formAddErrors: (state, { payload }) => {
|
614
|
-
_set(state, [payload.name, 'form', payload.currentNode, 'errors', payload.id], payload.errors);
|
615
|
-
},
|
616
|
-
formRemoveErrors: (state, { payload }) => {
|
617
|
-
_unset(state, [
|
618
|
-
payload.name,
|
619
|
-
'form',
|
620
|
-
payload.currentNode,
|
621
|
-
'errors',
|
622
|
-
payload.id
|
623
|
-
]);
|
624
|
-
_unset(state, [
|
625
|
-
payload.name,
|
626
|
-
'form',
|
627
|
-
payload.currentNode,
|
628
|
-
'customErrors',
|
629
|
-
payload.id
|
630
|
-
]);
|
631
|
-
_unset(state, [payload.name, 'form', payload.currentNode, 'isValidating']);
|
632
|
-
},
|
633
|
-
formFieldTouch: (state, { payload }) => {
|
634
|
-
_set(state, [payload.name, 'form', payload.currentNode, 'touches', payload.id], payload.touched);
|
635
|
-
},
|
636
|
-
formFieldFocus: (state, { payload }) => {
|
637
|
-
if (!payload.focused) {
|
638
|
-
_unset(state, [payload.name, 'form', payload.currentNode, 'hasFocus']);
|
639
|
-
return;
|
640
|
-
}
|
641
|
-
_set(state, [payload.name, 'form', payload.currentNode, 'hasFocus'], payload.id);
|
642
|
-
},
|
643
|
-
addData: (state, { payload }) => {
|
644
|
-
const prevData = _get(state, [payload.flowName, 'data']);
|
645
|
-
_set(state, [payload.flowName, 'data'], { ...prevData, ...payload.value });
|
646
|
-
},
|
647
|
-
addDataByPath: (state, { payload }) => {
|
648
|
-
const { path: newpath } = getPath(payload.id);
|
649
|
-
const currentNode = FlowerStateUtils.makeSelectCurrentNodeId(payload.flowName)(state);
|
650
|
-
if (payload.id && payload.id.length) {
|
651
|
-
_set(state, [payload.flowName, 'data', ...newpath], payload.value);
|
652
|
-
if (payload && payload.dirty) {
|
653
|
-
_set(state, [payload.flowName, 'form', currentNode, 'dirty', payload.id], payload.dirty);
|
654
|
-
_set(state, [payload.flowName, 'form', currentNode, 'isDirty'], true);
|
655
|
-
}
|
656
|
-
}
|
657
|
-
},
|
658
|
-
// TODO usato al momento solo il devtool
|
659
|
-
replaceData: /* istanbul ignore next */ (state, { payload }) => {
|
660
|
-
/* istanbul ignore next */
|
661
|
-
_set(state, [payload.flowName, 'data'], payload.value);
|
662
|
-
},
|
663
|
-
unsetData: (state, { payload }) => {
|
664
|
-
const currentNode = FlowerStateUtils.makeSelectCurrentNodeId(payload.flowName)(state);
|
665
|
-
_unset(state, [
|
666
|
-
payload.flowName,
|
667
|
-
'form',
|
668
|
-
currentNode,
|
669
|
-
'dirty',
|
670
|
-
...payload.id
|
671
|
-
]);
|
672
|
-
_unset(state, [
|
673
|
-
payload.flowName,
|
674
|
-
'form',
|
675
|
-
currentNode,
|
676
|
-
'touches',
|
677
|
-
...payload.id
|
678
|
-
]);
|
679
|
-
_unset(state, [payload.flowName, 'data', ...payload.id]);
|
680
|
-
},
|
681
|
-
setFormIsValidating: (state, { payload }) => {
|
682
|
-
_set(state, [payload.name, 'form', payload.currentNode, 'isValidating'], payload.isValidating);
|
683
|
-
},
|
684
|
-
resetForm: (state, { payload }) => {
|
685
|
-
const touchedFields = _get(state, [payload.flowName, 'form', payload.id, 'errors'], {});
|
686
|
-
Object.keys(touchedFields).forEach((key) => {
|
687
|
-
const { flowNameFromPath = payload.flowName, path } = getPath(key);
|
688
|
-
_unset(state, [flowNameFromPath, 'data', ...path]);
|
689
|
-
});
|
690
|
-
_unset(state, [payload.flowName, 'form', payload.id, 'touches']);
|
691
|
-
_unset(state, [payload.flowName, 'form', payload.id, 'dirty']);
|
692
|
-
_unset(state, [payload.flowName, 'form', payload.id, 'isDirty']);
|
693
|
-
_unset(state, [payload.flowName, 'form', payload.id, 'isSubmitted']);
|
694
|
-
},
|
695
582
|
node: (state, { payload }) => {
|
696
583
|
const { name, history } = payload;
|
697
584
|
const node = payload.nodeId || payload.node || '';
|
698
585
|
const flowName = name || payload.flowName || '';
|
699
|
-
const startNode = _get(state, [payload.name, 'startId']);
|
700
|
-
const currentNodeId = _get(state, [payload.name, 'current'], startNode);
|
701
|
-
FlowerCoreReducers.setFormTouched(state, {
|
702
|
-
type: 'setFormTouched',
|
703
|
-
payload: { flowName, currentNode: currentNodeId }
|
704
|
-
});
|
705
586
|
/* istanbul ignore next */
|
706
587
|
// eslint-disable-next-line no-underscore-dangle
|
707
588
|
if (devtoolState && _get(devtoolState, '__FLOWER_DEVTOOLS__') && history) {
|
708
|
-
|
589
|
+
FlowerCoreBaseReducers.forceAddHistory(state, {
|
709
590
|
type: 'forceAddHistory',
|
710
591
|
payload: {
|
711
592
|
name,
|
@@ -714,34 +595,35 @@ const FlowerCoreReducers = {
|
|
714
595
|
}
|
715
596
|
});
|
716
597
|
}
|
717
|
-
|
598
|
+
FlowerCoreBaseReducers.historyAdd(state, {
|
718
599
|
type: 'historyAdd',
|
719
600
|
payload: { name: name || flowName || '', node }
|
720
601
|
});
|
721
602
|
},
|
722
603
|
prevToNode: (state, { payload }) => {
|
723
604
|
const { node, name, flowName } = payload;
|
724
|
-
|
605
|
+
FlowerCoreBaseReducers.historyPrevToNode(state, {
|
725
606
|
type: 'historyPrevToNode',
|
726
607
|
payload: { name: name || flowName || '', node }
|
727
608
|
});
|
728
609
|
},
|
729
610
|
next: (state, { payload }) => {
|
730
|
-
const { name, data = {},
|
731
|
-
const flowName = name ||
|
611
|
+
const { name, route, flowName: flow, data = {}, dataIn = {} } = payload;
|
612
|
+
const flowName = name || flow || '';
|
613
|
+
const { FlowerData, FlowerFlow, ...external } = data;
|
732
614
|
const currentNodeId = FlowerStateUtils.makeSelectCurrentNodeId(flowName)(state);
|
733
615
|
const currentNextRules = FlowerStateUtils.makeSelectCurrentNextRules(flowName)(state);
|
734
|
-
const
|
735
|
-
const
|
616
|
+
const $data = FlowerStateUtils.makeSelectNodeErrors(flowName, currentNodeId)(FlowerData);
|
617
|
+
const internalClonedData = _cloneDeep(FlowerStateUtils.getAllData(FlowerData));
|
618
|
+
const externalClonedData = _cloneDeep(FlowerStateUtils.getAllData(external));
|
736
619
|
const stateWithNodeData = {
|
737
|
-
$in:
|
738
|
-
$
|
739
|
-
|
620
|
+
$in: dataIn,
|
621
|
+
/** @deprecated use $data instead */
|
622
|
+
$form: $data,
|
623
|
+
$data,
|
624
|
+
...externalClonedData,
|
625
|
+
...internalClonedData
|
740
626
|
};
|
741
|
-
FlowerCoreReducers.setFormTouched(state, {
|
742
|
-
type: 'setFormTouched',
|
743
|
-
payload: { flowName, currentNode: currentNodeId }
|
744
|
-
});
|
745
627
|
if (!currentNextRules) {
|
746
628
|
return;
|
747
629
|
}
|
@@ -750,7 +632,7 @@ const FlowerCoreReducers = {
|
|
750
632
|
if (!rulesByName[route]) {
|
751
633
|
return;
|
752
634
|
}
|
753
|
-
|
635
|
+
FlowerCoreBaseReducers.historyAdd(state, {
|
754
636
|
type: 'historyAdd',
|
755
637
|
payload: { name: flowName, node: rulesByName[route] }
|
756
638
|
});
|
@@ -761,51 +643,132 @@ const FlowerCoreReducers = {
|
|
761
643
|
if (!nextNumberNode) {
|
762
644
|
return;
|
763
645
|
}
|
764
|
-
|
646
|
+
FlowerCoreBaseReducers.historyAdd(state, {
|
765
647
|
type: 'historyAdd',
|
766
648
|
payload: { name: flowName, node: nextNumberNode }
|
767
649
|
});
|
768
650
|
},
|
769
651
|
prev: (state, { payload }) => {
|
770
652
|
const { name, flowName } = payload;
|
771
|
-
|
653
|
+
FlowerCoreBaseReducers.historyPop(state, {
|
772
654
|
type: 'historyPop',
|
773
655
|
payload: { name: name || flowName || '' }
|
774
656
|
});
|
775
657
|
},
|
776
658
|
restart: (state, { payload }) => {
|
777
659
|
const { name, flowName } = payload;
|
778
|
-
|
660
|
+
FlowerCoreBaseReducers.restoreHistory(state, {
|
779
661
|
type: 'restoreHistory',
|
780
662
|
payload: { name: name || flowName || '' }
|
781
663
|
});
|
782
664
|
},
|
783
665
|
reset: (state, { payload }) => {
|
784
|
-
const { name, flowName
|
785
|
-
|
666
|
+
const { name, flowName } = payload;
|
667
|
+
FlowerCoreBaseReducers.restoreHistory(state, {
|
786
668
|
type: 'restoreHistory',
|
787
669
|
payload: { name: name || flowName || '' }
|
788
670
|
});
|
789
|
-
_set(state, [name || flowName || '', 'form'], {});
|
790
|
-
_set(state, [name || flowName || '', 'data'], initialData);
|
791
671
|
}
|
792
672
|
};
|
793
673
|
|
794
|
-
const
|
795
|
-
|
674
|
+
const { getPath } = CoreUtils;
|
675
|
+
/**
|
676
|
+
* formName => FlowerForm
|
677
|
+
* initialData => FlowerForm
|
678
|
+
* fieldName => FlowerField
|
679
|
+
* fieldValue => FlowerField
|
680
|
+
* errors => FlowerField
|
681
|
+
* customErrors => FlowerField
|
682
|
+
* fieldTouched => FlowerField
|
683
|
+
* fieldDirty => FlowerField
|
684
|
+
* fieldHasFocus => FlowerField
|
685
|
+
*/
|
686
|
+
const FlowerCoreDataReducers = {
|
687
|
+
setFormTouched: (state, { payload }) => {
|
688
|
+
if (!_get(state, typeof payload === 'string' ? payload : payload.formName)) {
|
689
|
+
return state;
|
690
|
+
}
|
691
|
+
_set(state, typeof payload === 'string' ? payload : payload.formName, true);
|
692
|
+
return state;
|
693
|
+
},
|
694
|
+
formAddCustomErrors: (state, { payload }) => {
|
695
|
+
_set(state, [payload.formName, 'customErrors', payload.id], payload.errors);
|
696
|
+
},
|
697
|
+
formAddErrors: (state, { payload }) => {
|
698
|
+
_set(state, [payload.formName, 'errors', payload.id], payload.errors);
|
699
|
+
},
|
700
|
+
formRemoveErrors: (state, { payload }) => {
|
701
|
+
_unset(state, [payload.formName, 'errors', payload.id]);
|
702
|
+
_unset(state, [payload.formName, 'customErrors', payload.id]);
|
703
|
+
_unset(state, [payload.formName, 'isValidating']);
|
704
|
+
},
|
705
|
+
formFieldTouch: (state, { payload }) => {
|
706
|
+
_set(state, [payload.formName, 'touches', payload.id], payload.touched);
|
707
|
+
},
|
708
|
+
formFieldDirty: (state, { payload }) => {
|
709
|
+
_set(state, [payload.formName, 'dirty', payload.id], payload.dirty);
|
710
|
+
},
|
711
|
+
formFieldFocus: (state, { payload }) => {
|
712
|
+
if (!payload.focused) {
|
713
|
+
_unset(state, [payload.formName, 'hasFocus']);
|
714
|
+
return;
|
715
|
+
}
|
716
|
+
_set(state, [payload.formName, 'hasFocus'], payload.id);
|
717
|
+
},
|
718
|
+
addData: (state, { payload }) => {
|
719
|
+
const prevData = _get(state, [payload.formName, 'data'], {});
|
720
|
+
_set(state, [payload.formName, 'data'], { ...prevData, ...payload.value });
|
721
|
+
},
|
722
|
+
addDataByPath: (state, { payload }) => {
|
723
|
+
const { path: newpath } = getPath(payload.id);
|
724
|
+
if (payload.id && payload.id.length) {
|
725
|
+
_set(state, [payload.formName, 'data', ...newpath], payload.value);
|
726
|
+
if (payload && payload.dirty) {
|
727
|
+
_set(state, [payload.formName, 'dirty', payload.id], payload.dirty);
|
728
|
+
}
|
729
|
+
}
|
730
|
+
},
|
731
|
+
// TODO usato al momento solo il devtool
|
732
|
+
replaceData: /* istanbul ignore next */ (state, { payload }) => {
|
733
|
+
/* istanbul ignore next */
|
734
|
+
_set(state, [payload.formName, 'data'], payload.value);
|
735
|
+
},
|
736
|
+
unsetData: (state, { payload }) => {
|
737
|
+
_unset(state, [payload.formName, 'data', ...payload.id]);
|
738
|
+
},
|
739
|
+
setFormIsValidating: (state, { payload }) => {
|
740
|
+
_set(state, [payload.formName, 'isValidating'], payload.isValidating);
|
741
|
+
},
|
742
|
+
resetForm: (state, { payload: { formName, initialData } }) => {
|
743
|
+
const touchedFields = _get(state, [formName, 'errors'], {});
|
744
|
+
const newStateData = initialData
|
745
|
+
? Object.keys(touchedFields).reduce((acc, key) => {
|
746
|
+
const { path } = getPath(key);
|
747
|
+
const initialDataByPath = _get(initialData, [...path], undefined);
|
748
|
+
_set(acc, [...path], initialDataByPath);
|
749
|
+
return acc;
|
750
|
+
}, {})
|
751
|
+
: {};
|
752
|
+
_set(state, [formName, 'data'], newStateData);
|
753
|
+
_unset(state, [formName, 'touches']);
|
754
|
+
_unset(state, [formName, 'dirty']);
|
755
|
+
_unset(state, [formName, 'isSubmitted']);
|
756
|
+
},
|
757
|
+
initForm: (state, { payload: { formName, initialData } }) => {
|
758
|
+
_set(state, [formName, 'data'], initialData);
|
759
|
+
}
|
760
|
+
};
|
761
|
+
|
762
|
+
const FlowerCoreReducers = { ...FlowerCoreBaseReducers, ...FlowerCoreDataReducers };
|
763
|
+
|
764
|
+
const FlowerCoreStateBaseSelectors = {
|
765
|
+
selectGlobal: (state) => state && state[REDUCER_NAME.FLOWER_FLOW],
|
796
766
|
selectFlower: (name) => (state) => _get(state, [name]),
|
797
|
-
selectFlowerFormNode: (id) => (state) =>
|
767
|
+
// selectFlowerFormNode: (id) => (state) =>
|
768
|
+
// _get(state, [REDUCER_NAME.FLOWER_DATA, id]),
|
798
769
|
selectFlowerHistory: (flower) => _get(flower, ['history'], []),
|
799
770
|
makeSelectNodesIds: (flower) => _get(flower, ['nodes']),
|
800
771
|
makeSelectStartNodeId: (flower) => _get(flower, ['startId']),
|
801
|
-
getDataByFlow: (flower) => _get(flower, ['data']) ?? {},
|
802
|
-
getDataFromState: (id) => (data) => (id === '*' ? data : _get(data, id)),
|
803
|
-
makeSelectNodeFormSubmitted: (form) => form && form.isSubmitted,
|
804
|
-
makeSelectNodeFormFieldTouched: (id) => (form) => form && form.touches && form.touches[id],
|
805
|
-
makeSelectNodeFormFieldFocused: (id) => (form) => {
|
806
|
-
return form && form.hasFocus === id ? id : undefined;
|
807
|
-
},
|
808
|
-
makeSelectNodeFormFieldDirty: (id) => (form) => form && form.dirty && form.dirty[id],
|
809
772
|
makeSelectCurrentNodeId: (flower, startNodeId) => _get(flower, ['current']) || startNodeId,
|
810
773
|
makeSelectCurrentNodeDisabled: (nodes, current) => !!_get(nodes, [current, 'disabled']),
|
811
774
|
makeSelectPrevNodeRetain: (nodes, history, current) => {
|
@@ -826,7 +789,22 @@ const FlowerCoreStateSelectors = {
|
|
826
789
|
return nodes[prevFlowerNode] && nodes[prevFlowerNode].retain
|
827
790
|
? prevFlowerNode
|
828
791
|
: undefined;
|
792
|
+
}
|
793
|
+
};
|
794
|
+
|
795
|
+
const FlowerCoreStateDataSelectors = {
|
796
|
+
selectGlobalReducerByName: (name) => (state) => state[name] ?? state[REDUCER_NAME.FLOWER_DATA][name],
|
797
|
+
selectGlobalForm: (state) => {
|
798
|
+
return state && state[REDUCER_NAME.FLOWER_DATA];
|
829
799
|
},
|
800
|
+
// getDataByFlow: (flower) => _get(flower, 'data') ?? {},
|
801
|
+
getDataFromState: (id) => (data) => (id === '*' ? data : _get(data, id)),
|
802
|
+
makeSelectNodeFormSubmitted: (form) => form && form.isSubmitted,
|
803
|
+
makeSelectNodeFormFieldTouched: (id) => (form) => form && form.touches && form.touches[id],
|
804
|
+
makeSelectNodeFormFieldFocused: (id) => (form) => {
|
805
|
+
return form && form.hasFocus === id ? id : undefined;
|
806
|
+
},
|
807
|
+
makeSelectNodeFormFieldDirty: (id) => (form) => form && form.dirty && form.dirty[id],
|
830
808
|
makeSelectNodeErrors: createFormData,
|
831
809
|
makeSelectFieldError: (name, id, validate) => (data, form) => {
|
832
810
|
const customErrors = Object.entries((form && form.customErrors) || {})
|
@@ -841,7 +819,7 @@ const FlowerCoreStateSelectors = {
|
|
841
819
|
if (!rule.rules)
|
842
820
|
return true;
|
843
821
|
const transformSelf = CoreUtils.mapKeysDeepLodash(rule.rules, (v, key) => key === '$self' ? id : key);
|
844
|
-
const [hasError] =
|
822
|
+
const [hasError] = rulesMatcher(transformSelf, data, false, {
|
845
823
|
prefix: name
|
846
824
|
});
|
847
825
|
return hasError;
|
@@ -863,33 +841,16 @@ const FlowerCoreStateSelectors = {
|
|
863
841
|
const k = inc;
|
864
842
|
return Object.assign(acc, { [k]: _get(state, k) });
|
865
843
|
}, {});
|
866
|
-
const [disabled] =
|
844
|
+
const [disabled] = rulesMatcher(rules, { ...unflatten(res) }, false, {
|
845
|
+
prefix: flowName
|
846
|
+
});
|
867
847
|
return disabled;
|
868
848
|
}
|
869
849
|
};
|
870
850
|
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
RulesOperators["$ne"] = "$ne";
|
876
|
-
RulesOperators["$gt"] = "$gt";
|
877
|
-
RulesOperators["$gte"] = "$gte";
|
878
|
-
RulesOperators["$lt"] = "$lt";
|
879
|
-
RulesOperators["$lte"] = "$lte";
|
880
|
-
RulesOperators["$strGt"] = "$strGt";
|
881
|
-
RulesOperators["$strGte"] = "$strGte";
|
882
|
-
RulesOperators["$strLt"] = "$strLt";
|
883
|
-
RulesOperators["$strLte"] = "$strLte";
|
884
|
-
RulesOperators["$in"] = "$in";
|
885
|
-
RulesOperators["$nin"] = "$nin";
|
886
|
-
RulesOperators["$all"] = "$all";
|
887
|
-
RulesOperators["$regex"] = "$regex";
|
888
|
-
})(RulesOperators || (RulesOperators = {}));
|
889
|
-
var RulesModes;
|
890
|
-
(function (RulesModes) {
|
891
|
-
RulesModes["$and"] = "$and";
|
892
|
-
RulesModes["$or"] = "$or";
|
893
|
-
})(RulesModes || (RulesModes = {}));
|
851
|
+
const FlowerCoreStateSelectors = {
|
852
|
+
...FlowerCoreStateBaseSelectors,
|
853
|
+
...FlowerCoreStateDataSelectors
|
854
|
+
};
|
894
855
|
|
895
|
-
export { CoreUtils, Emitter,
|
856
|
+
export { CoreUtils, Emitter, FlowUtils, FlowerCoreBaseReducers, FlowerCoreDataReducers, FlowerCoreReducers, FlowerCoreStateBaseSelectors, FlowerCoreStateDataSelectors, FlowerCoreStateSelectors, FlowerStateUtils, FormUtils, REDUCER_NAME, createFormData, devtoolState, flattenRules, rulesMatcher, rulesMatcherUtils };
|