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