@aemforms/af-core 0.22.73 → 0.22.75
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/esm/afb-events.js +6 -1
- package/esm/afb-runtime.js +1745 -1666
- package/esm/types/src/BaseNode.d.ts +4 -2
- package/esm/types/src/Checkbox.d.ts +72 -0
- package/esm/types/src/Container.d.ts +4 -2
- package/esm/types/src/Field.d.ts +3 -2
- package/esm/types/src/Form.d.ts +4 -2
- package/esm/types/src/FormInstance.d.ts +1 -1
- package/esm/types/src/controller/Events.d.ts +3 -0
- package/esm/types/src/types/Json.d.ts +1 -0
- package/esm/types/src/utils/ValidationUtils.d.ts +2 -1
- package/lib/BaseNode.d.ts +4 -2
- package/lib/BaseNode.js +11 -2
- package/lib/Checkbox.d.ts +72 -0
- package/lib/Checkbox.js +55 -0
- package/lib/Container.d.ts +4 -2
- package/lib/Field.d.ts +3 -2
- package/lib/Field.js +0 -1
- package/lib/Form.d.ts +4 -2
- package/lib/Form.js +1 -1
- package/lib/FormInstance.d.ts +1 -1
- package/lib/FormInstance.js +6 -1
- package/lib/controller/Events.d.ts +3 -0
- package/lib/controller/Events.js +7 -1
- package/lib/rules/FunctionRuntime.js +25 -6
- package/lib/types/Json.d.ts +1 -0
- package/lib/utils/ValidationUtils.d.ts +2 -1
- package/lib/utils/ValidationUtils.js +3 -1
- package/package.json +2 -2
package/esm/afb-runtime.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { propertyChange, ExecuteRule, Initialize, RemoveItem, SubmitSuccess, CustomEvent, SubmitFailure, Submit, RemoveInstance, AddInstance, Reset, AddItem, Click, Change, FormLoad, FieldChanged, ValidationComplete, Valid, Invalid } from './afb-events.js';
|
|
1
|
+
import { propertyChange, ExecuteRule, Initialize, RemoveItem, SubmitSuccess, CustomEvent, SubmitError, SubmitFailure, Submit, RemoveInstance, AddInstance, Reset, AddItem, Click, Change, FormLoad, FieldChanged, ValidationComplete, Valid, Invalid } from './afb-events.js';
|
|
2
2
|
import Formula from '@adobe/json-formula';
|
|
3
3
|
import { parseDefaultDate, datetimeToNumber, format, parseDateSkeleton, formatDate, numberToDatetime } from '@aemforms/af-formatters';
|
|
4
4
|
|
|
@@ -578,593 +578,664 @@ const resolveData = (data, input, create) => {
|
|
|
578
578
|
return result;
|
|
579
579
|
};
|
|
580
580
|
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
'
|
|
584
|
-
'
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
'errorMessage',
|
|
589
|
-
'readOnly',
|
|
590
|
-
'enum',
|
|
591
|
-
'enumNames',
|
|
592
|
-
'required',
|
|
593
|
-
'properties',
|
|
594
|
-
'exclusiveMinimum',
|
|
595
|
-
'exclusiveMaximum',
|
|
596
|
-
'maximum',
|
|
597
|
-
'maxItems',
|
|
598
|
-
'minimum',
|
|
599
|
-
'minItems'
|
|
600
|
-
];
|
|
601
|
-
const dynamicProps = [
|
|
602
|
-
...editableProperties,
|
|
603
|
-
'index',
|
|
604
|
-
'activeChild'
|
|
605
|
-
];
|
|
606
|
-
const staticFields = ['plain-text', 'image'];
|
|
607
|
-
class ActionImplWithTarget {
|
|
608
|
-
_action;
|
|
609
|
-
_target;
|
|
610
|
-
constructor(_action, _target) {
|
|
611
|
-
this._action = _action;
|
|
612
|
-
this._target = _target;
|
|
581
|
+
class FileObject {
|
|
582
|
+
data;
|
|
583
|
+
mediaType = 'application/octet-stream';
|
|
584
|
+
name = 'unknown';
|
|
585
|
+
size = 0;
|
|
586
|
+
constructor(init) {
|
|
587
|
+
Object.assign(this, init);
|
|
613
588
|
}
|
|
614
589
|
get type() {
|
|
615
|
-
return this.
|
|
616
|
-
}
|
|
617
|
-
get payload() {
|
|
618
|
-
return this._action.payload;
|
|
619
|
-
}
|
|
620
|
-
get metadata() {
|
|
621
|
-
return this._action.metadata;
|
|
622
|
-
}
|
|
623
|
-
get target() {
|
|
624
|
-
return this._target;
|
|
625
|
-
}
|
|
626
|
-
get isCustomEvent() {
|
|
627
|
-
return this._action.isCustomEvent;
|
|
590
|
+
return this.mediaType;
|
|
628
591
|
}
|
|
629
|
-
|
|
630
|
-
return
|
|
592
|
+
toJSON() {
|
|
593
|
+
return {
|
|
594
|
+
'name': this.name,
|
|
595
|
+
'size': this.size,
|
|
596
|
+
'mediaType': this.mediaType,
|
|
597
|
+
'data': this.data.toString()
|
|
598
|
+
};
|
|
631
599
|
}
|
|
632
|
-
|
|
633
|
-
return this.
|
|
600
|
+
equals(obj) {
|
|
601
|
+
return (this.data === obj.data &&
|
|
602
|
+
this.mediaType === obj.mediaType &&
|
|
603
|
+
this.name === obj.name &&
|
|
604
|
+
this.size === obj.size);
|
|
634
605
|
}
|
|
635
606
|
}
|
|
636
|
-
|
|
637
|
-
const
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
};
|
|
607
|
+
|
|
608
|
+
const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_'.split('');
|
|
609
|
+
const fileSizeRegex = /^(\d*\.?\d+)(\\?(?=[KMGT])([KMGT])(?:i?B)?|B?)$/i;
|
|
610
|
+
const randomWord = (l) => {
|
|
611
|
+
const ret = [];
|
|
612
|
+
for (let i = 0; i <= l; i++) {
|
|
613
|
+
let randIndex;
|
|
614
|
+
if (i === 0) {
|
|
615
|
+
randIndex = Math.floor(Math.random() * (chars.length - 11));
|
|
646
616
|
}
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
if (get != undefined) {
|
|
652
|
-
descriptor.get = function () {
|
|
653
|
-
if (fieldTypes.indexOf(this.fieldType) > -1 === includeOrExclude) {
|
|
654
|
-
return get.call(this);
|
|
655
|
-
}
|
|
656
|
-
return undefined;
|
|
657
|
-
};
|
|
658
|
-
}
|
|
659
|
-
const set = descriptor.set;
|
|
660
|
-
if (set != undefined) {
|
|
661
|
-
descriptor.set = function (value) {
|
|
662
|
-
if (fieldTypes.indexOf(this.fieldType) > -1 === includeOrExclude) {
|
|
663
|
-
set.call(this, value);
|
|
664
|
-
}
|
|
665
|
-
};
|
|
617
|
+
else {
|
|
618
|
+
randIndex = Math.floor(Math.random() * (chars.length));
|
|
619
|
+
}
|
|
620
|
+
ret.push(chars[randIndex]);
|
|
666
621
|
}
|
|
622
|
+
return ret.join('');
|
|
667
623
|
};
|
|
668
|
-
const
|
|
669
|
-
const
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
_lang = '';
|
|
674
|
-
_callbacks = {};
|
|
675
|
-
_dependents = [];
|
|
676
|
-
_jsonModel;
|
|
677
|
-
_tokens = [];
|
|
678
|
-
get isContainer() {
|
|
679
|
-
return false;
|
|
680
|
-
}
|
|
681
|
-
constructor(params, _options) {
|
|
682
|
-
this._options = _options;
|
|
683
|
-
this[qualifiedName] = null;
|
|
684
|
-
this._jsonModel = {
|
|
685
|
-
...params,
|
|
686
|
-
id: 'id' in params ? params.id : this.form.getUniqueId()
|
|
687
|
-
};
|
|
688
|
-
}
|
|
689
|
-
setupRuleNode() {
|
|
690
|
-
const self = this;
|
|
691
|
-
this._ruleNode = new Proxy(this.ruleNodeReference(), {
|
|
692
|
-
get: (ruleNodeReference, prop) => {
|
|
693
|
-
return self.getFromRule(ruleNodeReference, prop);
|
|
694
|
-
}
|
|
695
|
-
});
|
|
696
|
-
}
|
|
697
|
-
ruleNodeReference() {
|
|
698
|
-
return this;
|
|
699
|
-
}
|
|
700
|
-
getRuleNode() {
|
|
701
|
-
return this._ruleNode;
|
|
702
|
-
}
|
|
703
|
-
getFromRule(ruleNodeReference, prop) {
|
|
704
|
-
if (prop === Symbol.toPrimitive || (prop === 'valueOf' && !ruleNodeReference.hasOwnProperty('valueOf'))) {
|
|
705
|
-
return this.valueOf;
|
|
624
|
+
const getAttachments = (input, excludeUnbound = false) => {
|
|
625
|
+
const items = input.items || [];
|
|
626
|
+
return items?.reduce((acc, item) => {
|
|
627
|
+
if (excludeUnbound && item.dataRef === null) {
|
|
628
|
+
return acc;
|
|
706
629
|
}
|
|
707
|
-
|
|
708
|
-
|
|
630
|
+
let ret = null;
|
|
631
|
+
if (item.isContainer) {
|
|
632
|
+
ret = getAttachments(item, excludeUnbound);
|
|
709
633
|
}
|
|
710
|
-
else
|
|
711
|
-
if (
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
return
|
|
720
|
-
}
|
|
721
|
-
else {
|
|
722
|
-
return retValue;
|
|
723
|
-
}
|
|
724
|
-
}
|
|
725
|
-
}
|
|
726
|
-
else {
|
|
727
|
-
if (ruleNodeReference.hasOwnProperty(prop)) {
|
|
728
|
-
return ruleNodeReference[prop];
|
|
634
|
+
else {
|
|
635
|
+
if (isFile(item.getState())) {
|
|
636
|
+
ret = {};
|
|
637
|
+
const name = item.name || '';
|
|
638
|
+
const dataRef = (item.dataRef != null)
|
|
639
|
+
? item.dataRef
|
|
640
|
+
: (name.length > 0 ? item.name : undefined);
|
|
641
|
+
if (item.value instanceof Array) {
|
|
642
|
+
ret[item.id] = item.value.map((x) => {
|
|
643
|
+
return { ...x, 'dataRef': dataRef };
|
|
644
|
+
});
|
|
729
645
|
}
|
|
730
|
-
else if (
|
|
731
|
-
|
|
646
|
+
else if (item.value != null) {
|
|
647
|
+
ret[item.id] = { ...item.value, 'dataRef': dataRef };
|
|
732
648
|
}
|
|
733
649
|
}
|
|
734
650
|
}
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
651
|
+
return Object.assign(acc, ret);
|
|
652
|
+
}, {});
|
|
653
|
+
};
|
|
654
|
+
const getFileSizeInBytes = (str) => {
|
|
655
|
+
let retVal = 0;
|
|
656
|
+
if (typeof str === 'string') {
|
|
657
|
+
const matches = fileSizeRegex.exec(str.trim());
|
|
658
|
+
if (matches != null) {
|
|
659
|
+
retVal = sizeToBytes(parseFloat(matches[1]), (matches[2] || 'kb').toUpperCase());
|
|
742
660
|
}
|
|
743
|
-
return 0;
|
|
744
|
-
}
|
|
745
|
-
get parent() {
|
|
746
|
-
return this._options.parent;
|
|
747
|
-
}
|
|
748
|
-
get type() {
|
|
749
|
-
return this._jsonModel.type;
|
|
750
|
-
}
|
|
751
|
-
get repeatable() {
|
|
752
|
-
return this.parent?.hasDynamicItems();
|
|
753
|
-
}
|
|
754
|
-
get fieldType() {
|
|
755
|
-
return this._jsonModel.fieldType || 'text-input';
|
|
756
|
-
}
|
|
757
|
-
get ':type'() {
|
|
758
|
-
return this._jsonModel[':type'] || this.fieldType;
|
|
759
|
-
}
|
|
760
|
-
get name() {
|
|
761
|
-
return this._jsonModel.name;
|
|
762
|
-
}
|
|
763
|
-
get description() {
|
|
764
|
-
return this._jsonModel.description;
|
|
765
|
-
}
|
|
766
|
-
set description(d) {
|
|
767
|
-
this._setProperty('description', d);
|
|
768
|
-
}
|
|
769
|
-
get dataRef() {
|
|
770
|
-
return this._jsonModel.dataRef;
|
|
771
661
|
}
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
662
|
+
return retVal;
|
|
663
|
+
};
|
|
664
|
+
const sizeToBytes = (size, symbol) => {
|
|
665
|
+
const sizes = { 'KB': 1, 'MB': 2, 'GB': 3, 'TB': 4 };
|
|
666
|
+
const i = Math.pow(1024, sizes[symbol]);
|
|
667
|
+
return Math.round(size * i);
|
|
668
|
+
};
|
|
669
|
+
const IdGenerator = function* (initial = 50) {
|
|
670
|
+
const initialize = function () {
|
|
671
|
+
const arr = [];
|
|
672
|
+
for (let i = 0; i < initial; i++) {
|
|
673
|
+
arr.push(randomWord(10));
|
|
778
674
|
}
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
675
|
+
return arr;
|
|
676
|
+
};
|
|
677
|
+
const passedIds = {};
|
|
678
|
+
let ids = initialize();
|
|
679
|
+
do {
|
|
680
|
+
let x = ids.pop();
|
|
681
|
+
while (x in passedIds) {
|
|
682
|
+
if (ids.length === 0) {
|
|
683
|
+
ids = initialize();
|
|
684
|
+
}
|
|
685
|
+
x = ids.pop();
|
|
686
|
+
}
|
|
687
|
+
passedIds[x] = true;
|
|
688
|
+
yield ids.pop();
|
|
689
|
+
if (ids.length === 0) {
|
|
690
|
+
ids = initialize();
|
|
691
|
+
}
|
|
692
|
+
} while (ids.length > 0);
|
|
693
|
+
};
|
|
694
|
+
const isDataUrl = (str) => {
|
|
695
|
+
const dataUrlRegex = /^data:([a-z]+\/[a-z0-9-+.]+)?;(?:name=(.*);)?base64,(.*)$/;
|
|
696
|
+
return dataUrlRegex.exec(str.trim()) != null;
|
|
697
|
+
};
|
|
698
|
+
const extractFileInfo = (file) => {
|
|
699
|
+
if (file !== null) {
|
|
700
|
+
let retVal = null;
|
|
701
|
+
if (file instanceof FileObject) {
|
|
702
|
+
retVal = file;
|
|
703
|
+
}
|
|
704
|
+
else if (typeof File !== 'undefined' && file instanceof File) {
|
|
705
|
+
retVal = {
|
|
706
|
+
name: file.name,
|
|
707
|
+
mediaType: file.type,
|
|
708
|
+
size: file.size,
|
|
709
|
+
data: file
|
|
710
|
+
};
|
|
711
|
+
}
|
|
712
|
+
else if (typeof file === 'string' && isDataUrl(file)) {
|
|
713
|
+
const result = dataURItoBlob(file);
|
|
714
|
+
if (result !== null) {
|
|
715
|
+
const { blob, name } = result;
|
|
716
|
+
retVal = {
|
|
717
|
+
name: name,
|
|
718
|
+
mediaType: blob.type,
|
|
719
|
+
size: blob.size,
|
|
720
|
+
data: blob
|
|
721
|
+
};
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
else {
|
|
725
|
+
let jFile = file;
|
|
726
|
+
try {
|
|
727
|
+
jFile = JSON.parse(file);
|
|
728
|
+
retVal = jFile;
|
|
729
|
+
if (!retVal.mediaType) {
|
|
730
|
+
retVal.mediaType = retVal.type;
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
catch (ex) {
|
|
734
|
+
}
|
|
735
|
+
if (typeof jFile?.data === 'string' && isDataUrl(jFile?.data)) {
|
|
736
|
+
const result = dataURItoBlob(jFile?.data);
|
|
737
|
+
if (result !== null) {
|
|
738
|
+
const blob = result.blob;
|
|
739
|
+
retVal = {
|
|
740
|
+
name: jFile?.name,
|
|
741
|
+
mediaType: jFile?.type || jFile?.mediaType,
|
|
742
|
+
size: blob.size,
|
|
743
|
+
data: blob
|
|
744
|
+
};
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
else if (typeof jFile === 'string') {
|
|
748
|
+
const fileName = jFile.split('/').pop();
|
|
749
|
+
retVal = {
|
|
750
|
+
name: fileName,
|
|
751
|
+
mediaType: 'application/octet-stream',
|
|
752
|
+
size: 0,
|
|
753
|
+
data: jFile
|
|
754
|
+
};
|
|
755
|
+
}
|
|
756
|
+
else if (typeof jFile === 'object') {
|
|
757
|
+
retVal = {
|
|
758
|
+
name: jFile?.name,
|
|
759
|
+
mediaType: jFile?.type || jFile?.mediaType,
|
|
760
|
+
size: jFile?.size,
|
|
761
|
+
data: jFile?.data
|
|
762
|
+
};
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
if (retVal !== null && retVal.data != null) {
|
|
766
|
+
return new FileObject(retVal);
|
|
785
767
|
}
|
|
768
|
+
return null;
|
|
786
769
|
}
|
|
787
|
-
|
|
788
|
-
return
|
|
770
|
+
else {
|
|
771
|
+
return null;
|
|
789
772
|
}
|
|
790
|
-
|
|
791
|
-
|
|
773
|
+
};
|
|
774
|
+
const dataURItoBlob = (dataURI) => {
|
|
775
|
+
const regex = /^data:([a-z]+\/[a-z0-9-+.]+)?(?:;name=([^;]+))?(;base64)?,(.+)$/;
|
|
776
|
+
const groups = regex.exec(dataURI);
|
|
777
|
+
if (groups !== null) {
|
|
778
|
+
const type = groups[1] || '';
|
|
779
|
+
const name = groups[2] || 'unknown';
|
|
780
|
+
const isBase64 = typeof groups[3] === 'string';
|
|
781
|
+
if (isBase64) {
|
|
782
|
+
const binary = atob(groups[4]);
|
|
783
|
+
const array = [];
|
|
784
|
+
for (let i = 0; i < binary.length; i++) {
|
|
785
|
+
array.push(binary.charCodeAt(i));
|
|
786
|
+
}
|
|
787
|
+
const blob = new window.Blob([new Uint8Array(array)], { type });
|
|
788
|
+
return { name, blob };
|
|
789
|
+
}
|
|
790
|
+
else {
|
|
791
|
+
const blob = new window.Blob([groups[4]], { type });
|
|
792
|
+
return { name, blob };
|
|
793
|
+
}
|
|
792
794
|
}
|
|
793
|
-
|
|
794
|
-
return
|
|
795
|
+
else {
|
|
796
|
+
return null;
|
|
795
797
|
}
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
this.notifyDependents(changeAction);
|
|
804
|
-
}
|
|
798
|
+
};
|
|
799
|
+
const isFormOrSiteContainer = (model) => {
|
|
800
|
+
return (':items' in model || 'cqItems' in model) && (':itemsOrder' in model || 'cqItemsOrder' in model);
|
|
801
|
+
};
|
|
802
|
+
const sitesModelToFormModel = (sitesModel) => {
|
|
803
|
+
if (!sitesModel || !Object.keys(sitesModel).length) {
|
|
804
|
+
return sitesModel;
|
|
805
805
|
}
|
|
806
|
-
|
|
807
|
-
|
|
806
|
+
if (isFormOrSiteContainer(sitesModel)) {
|
|
807
|
+
const itemsArr = [];
|
|
808
|
+
const itemsOrder = sitesModel[':itemsOrder'] || sitesModel.cqItemsOrder;
|
|
809
|
+
const items = sitesModel[':items'] || sitesModel.cqItems;
|
|
810
|
+
itemsOrder.forEach((elemName) => {
|
|
811
|
+
itemsArr.push(sitesModelToFormModel(items[elemName]));
|
|
812
|
+
});
|
|
813
|
+
sitesModel.items = itemsArr;
|
|
808
814
|
}
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
815
|
+
return sitesModel;
|
|
816
|
+
};
|
|
817
|
+
const replaceTemplatePlaceholders = (str, values = []) => {
|
|
818
|
+
return str?.replace(/\${(\d+)}/g, (match, index) => {
|
|
819
|
+
const replacement = values[index];
|
|
820
|
+
return typeof replacement !== 'undefined' ? replacement : match;
|
|
821
|
+
});
|
|
822
|
+
};
|
|
823
|
+
|
|
824
|
+
const dateRegex = /^(\d{4})-(\d{1,2})-(\d{1,2})$/;
|
|
825
|
+
const emailRegex = /^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/;
|
|
826
|
+
const days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
827
|
+
const daysInMonth = (leapYear, month) => {
|
|
828
|
+
if (leapYear && month == 2) {
|
|
829
|
+
return 29;
|
|
812
830
|
}
|
|
813
|
-
|
|
831
|
+
return days[month - 1];
|
|
832
|
+
};
|
|
833
|
+
const isLeapYear = (year) => {
|
|
834
|
+
return year % 400 === 0 || year % 4 === 0 && year % 100 !== 0;
|
|
835
|
+
};
|
|
836
|
+
const coerceType = (param, type) => {
|
|
837
|
+
let num;
|
|
838
|
+
switch (type) {
|
|
839
|
+
case 'string':
|
|
840
|
+
return param + '';
|
|
841
|
+
case 'number':
|
|
842
|
+
num = +param;
|
|
843
|
+
if (!isNaN(num)) {
|
|
844
|
+
return num;
|
|
845
|
+
}
|
|
846
|
+
break;
|
|
847
|
+
case 'boolean':
|
|
848
|
+
if (typeof param === 'string') {
|
|
849
|
+
return param === 'true';
|
|
850
|
+
}
|
|
851
|
+
else if (typeof param === 'number') {
|
|
852
|
+
return param !== 0;
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
throw `${param} has invalid type. Expected : ${type}, Actual ${typeof param}`;
|
|
856
|
+
};
|
|
857
|
+
const checkNumber = (inputVal) => {
|
|
858
|
+
if (inputVal === '' || inputVal == null) {
|
|
814
859
|
return {
|
|
815
|
-
|
|
816
|
-
properties: this.properties,
|
|
817
|
-
index: this.index,
|
|
818
|
-
parent: undefined,
|
|
819
|
-
qualifiedName: this.qualifiedName,
|
|
820
|
-
repeatable: this.repeatable === true ? true : undefined,
|
|
821
|
-
':type': this[':type'],
|
|
822
|
-
...(forRestore ? {
|
|
823
|
-
_dependents: this._dependents.length ? this._dependents.map(x => x.node.id) : undefined,
|
|
824
|
-
allowedComponents: undefined,
|
|
825
|
-
columnClassNames: undefined,
|
|
826
|
-
columnCount: undefined,
|
|
827
|
-
gridClassNames: undefined
|
|
828
|
-
} : {})
|
|
860
|
+
value: '', valid: true
|
|
829
861
|
};
|
|
830
862
|
}
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
863
|
+
let value = parseFloat(inputVal);
|
|
864
|
+
const valid = !isNaN(value);
|
|
865
|
+
if (!valid) {
|
|
866
|
+
value = inputVal;
|
|
867
|
+
}
|
|
868
|
+
return {
|
|
869
|
+
value, valid
|
|
870
|
+
};
|
|
871
|
+
};
|
|
872
|
+
const checkInteger = (inputVal) => {
|
|
873
|
+
if (inputVal == '' || inputVal == null) {
|
|
834
874
|
return {
|
|
835
|
-
|
|
836
|
-
this._callbacks[eventName] = this._callbacks[eventName].filter(x => x !== callback);
|
|
837
|
-
}
|
|
875
|
+
value: '', valid: true
|
|
838
876
|
};
|
|
839
877
|
}
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
const propsToLook = [...dynamicProps, 'items'];
|
|
845
|
-
const isPropChanged = changes.findIndex(x => {
|
|
846
|
-
return propsToLook.indexOf(x.propertyName) > -1;
|
|
847
|
-
}) > -1;
|
|
848
|
-
if (isPropChanged) {
|
|
849
|
-
dependent.dispatch(new ExecuteRule());
|
|
850
|
-
}
|
|
851
|
-
});
|
|
852
|
-
this._dependents.push({ node: dependent, subscription });
|
|
853
|
-
}
|
|
878
|
+
let value = parseFloat(inputVal);
|
|
879
|
+
const valid = !isNaN(value) && Math.round(value) === value;
|
|
880
|
+
if (!valid) {
|
|
881
|
+
value = inputVal;
|
|
854
882
|
}
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
queueEvent(action) {
|
|
863
|
-
const actionWithTarget = new ActionImplWithTarget(action, this);
|
|
864
|
-
this.form.getEventQueue().queue(this, actionWithTarget, ['valid', 'invalid'].indexOf(actionWithTarget.type) > -1);
|
|
865
|
-
}
|
|
866
|
-
dispatch(action) {
|
|
867
|
-
this.queueEvent(action);
|
|
868
|
-
this.form.getEventQueue().runPendingQueue();
|
|
869
|
-
}
|
|
870
|
-
notifyDependents(action) {
|
|
871
|
-
const depsToRestore = this._jsonModel._dependents;
|
|
872
|
-
if (depsToRestore) {
|
|
873
|
-
depsToRestore.forEach((x) => {
|
|
874
|
-
const node = this.form.getElement(x);
|
|
875
|
-
if (node) {
|
|
876
|
-
this._addDependent(node);
|
|
877
|
-
}
|
|
878
|
-
});
|
|
879
|
-
this._jsonModel._dependents = undefined;
|
|
880
|
-
}
|
|
881
|
-
const handlers = this._callbacks[action.type] || [];
|
|
882
|
-
handlers.forEach(x => {
|
|
883
|
-
x(new ActionImplWithTarget(action, this));
|
|
884
|
-
});
|
|
883
|
+
return {
|
|
884
|
+
value, valid
|
|
885
|
+
};
|
|
886
|
+
};
|
|
887
|
+
const toArray = (inputVal) => {
|
|
888
|
+
if (inputVal != null && !(inputVal instanceof Array)) {
|
|
889
|
+
return [inputVal];
|
|
885
890
|
}
|
|
886
|
-
|
|
887
|
-
|
|
891
|
+
return inputVal;
|
|
892
|
+
};
|
|
893
|
+
const checkBool = (inputVal) => {
|
|
894
|
+
const valid = typeof inputVal === 'boolean' || inputVal === 'true' || inputVal === 'false';
|
|
895
|
+
const value = typeof inputVal === 'boolean' ? inputVal : (valid ? inputVal === 'true' : inputVal);
|
|
896
|
+
return { valid, value };
|
|
897
|
+
};
|
|
898
|
+
const checkFile = (inputVal) => {
|
|
899
|
+
const value = extractFileInfo(inputVal);
|
|
900
|
+
const valid = value !== null;
|
|
901
|
+
return {
|
|
902
|
+
value: valid ? value : inputVal,
|
|
903
|
+
valid
|
|
904
|
+
};
|
|
905
|
+
};
|
|
906
|
+
const matchMediaType = (mediaType, accepts) => {
|
|
907
|
+
return !mediaType || accepts.some((accept) => {
|
|
908
|
+
const trimmedAccept = accept.trim();
|
|
909
|
+
const prefixAccept = trimmedAccept.split('/')[0];
|
|
910
|
+
const suffixAccept = trimmedAccept.split('.')[1];
|
|
911
|
+
return ((trimmedAccept.includes('*') && mediaType.startsWith(prefixAccept)) ||
|
|
912
|
+
(trimmedAccept.includes('.') && mediaType.endsWith(suffixAccept)) ||
|
|
913
|
+
(trimmedAccept === mediaType));
|
|
914
|
+
});
|
|
915
|
+
};
|
|
916
|
+
const partitionArray = (inputVal, validatorFn) => {
|
|
917
|
+
const value = toArray(inputVal);
|
|
918
|
+
if (value == null) {
|
|
919
|
+
return [[], [value]];
|
|
888
920
|
}
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
isValueSame = JSON.stringify(newValue) === JSON.stringify(oldValue);
|
|
895
|
-
}
|
|
896
|
-
else {
|
|
897
|
-
isValueSame = oldValue === newValue;
|
|
898
|
-
}
|
|
899
|
-
if (!isValueSame) {
|
|
900
|
-
this._jsonModel[prop] = newValue;
|
|
901
|
-
const changeAction = propertyChange(prop, newValue, oldValue);
|
|
902
|
-
if (notify) {
|
|
903
|
-
this.notifyDependents(changeAction);
|
|
904
|
-
}
|
|
905
|
-
notifyChildren.call(this, changeAction);
|
|
906
|
-
return changeAction.payload.changes;
|
|
921
|
+
return value.reduce((acc, x) => {
|
|
922
|
+
if (acc[1].length == 0) {
|
|
923
|
+
const r = validatorFn(x);
|
|
924
|
+
const index = r.valid ? 0 : 1;
|
|
925
|
+
acc[index].push(r.value);
|
|
907
926
|
}
|
|
908
|
-
return
|
|
909
|
-
}
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
927
|
+
return acc;
|
|
928
|
+
}, [[], []]);
|
|
929
|
+
};
|
|
930
|
+
const ValidConstraints = {
|
|
931
|
+
date: ['minimum', 'maximum', 'exclusiveMinimum', 'exclusiveMaximum', 'format'],
|
|
932
|
+
string: ['minLength', 'maxLength', 'pattern'],
|
|
933
|
+
number: ['minimum', 'maximum', 'exclusiveMinimum', 'exclusiveMaximum'],
|
|
934
|
+
array: ['minItems', 'maxItems', 'uniqueItems'],
|
|
935
|
+
file: ['accept', 'maxFileSize'],
|
|
936
|
+
email: ['minLength', 'maxLength', 'format', 'pattern']
|
|
937
|
+
};
|
|
938
|
+
const validationConstraintsList = ['type', 'format', 'minimum', 'maximum', 'exclusiveMinimum', 'exclusiveMaximum', 'minItems',
|
|
939
|
+
'maxItems', 'uniqueItems', 'minLength', 'maxLength', 'pattern', 'required', 'enum', 'accept', 'maxFileSize'];
|
|
940
|
+
const Constraints = {
|
|
941
|
+
type: (constraint, inputVal) => {
|
|
942
|
+
let value = inputVal;
|
|
943
|
+
if (inputVal == undefined) {
|
|
944
|
+
return {
|
|
945
|
+
valid: true,
|
|
946
|
+
value: inputVal
|
|
947
|
+
};
|
|
914
948
|
}
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
949
|
+
let valid = true, res;
|
|
950
|
+
switch (constraint) {
|
|
951
|
+
case 'string':
|
|
952
|
+
valid = true;
|
|
953
|
+
value = inputVal.toString();
|
|
954
|
+
break;
|
|
955
|
+
case 'string[]':
|
|
956
|
+
value = toArray(inputVal);
|
|
957
|
+
break;
|
|
958
|
+
case 'number':
|
|
959
|
+
res = checkNumber(inputVal);
|
|
960
|
+
value = res.value;
|
|
961
|
+
valid = res.valid;
|
|
962
|
+
break;
|
|
963
|
+
case 'boolean':
|
|
964
|
+
res = checkBool(inputVal);
|
|
965
|
+
valid = res.valid;
|
|
966
|
+
value = res.value;
|
|
967
|
+
break;
|
|
968
|
+
case 'integer':
|
|
969
|
+
res = checkInteger(inputVal);
|
|
970
|
+
valid = res.valid;
|
|
971
|
+
value = res.value;
|
|
972
|
+
break;
|
|
973
|
+
case 'integer[]':
|
|
974
|
+
res = partitionArray(inputVal, checkInteger);
|
|
975
|
+
valid = res[1].length === 0;
|
|
976
|
+
value = valid ? res[0] : inputVal;
|
|
977
|
+
break;
|
|
978
|
+
case 'file':
|
|
979
|
+
res = checkFile(inputVal instanceof Array ? inputVal[0] : inputVal);
|
|
980
|
+
valid = res.valid;
|
|
981
|
+
value = res.value;
|
|
982
|
+
break;
|
|
983
|
+
case 'file[]':
|
|
984
|
+
res = partitionArray(inputVal, checkFile);
|
|
985
|
+
valid = res[1].length === 0;
|
|
986
|
+
value = valid ? res[0] : inputVal;
|
|
987
|
+
break;
|
|
988
|
+
case 'number[]':
|
|
989
|
+
res = partitionArray(inputVal, checkNumber);
|
|
990
|
+
valid = res[1].length === 0;
|
|
991
|
+
value = valid ? res[0] : inputVal;
|
|
992
|
+
break;
|
|
993
|
+
case 'boolean[]':
|
|
994
|
+
res = partitionArray(inputVal, checkBool);
|
|
995
|
+
valid = res[1].length === 0;
|
|
996
|
+
value = valid ? res[0] : inputVal;
|
|
997
|
+
break;
|
|
919
998
|
}
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
while (!repeatRoot.repeatable && repeatRoot !== this.form) {
|
|
931
|
-
repeatRoot = repeatRoot.parent;
|
|
932
|
-
}
|
|
933
|
-
searchData = repeatRoot.getDataNode();
|
|
934
|
-
}
|
|
935
|
-
if (typeof searchData !== 'undefined') {
|
|
936
|
-
const name = this._tokens[this._tokens.length - 1].value;
|
|
937
|
-
const create = this.defaultDataModel(name);
|
|
938
|
-
_data = resolveData(searchData, this._tokens, create);
|
|
939
|
-
_parent = resolveData(searchData, this._tokens.slice(0, -1));
|
|
940
|
-
_key = name;
|
|
941
|
-
}
|
|
999
|
+
return {
|
|
1000
|
+
valid,
|
|
1001
|
+
value
|
|
1002
|
+
};
|
|
1003
|
+
},
|
|
1004
|
+
format: (constraint, input) => {
|
|
1005
|
+
let valid = true;
|
|
1006
|
+
const value = input;
|
|
1007
|
+
if (input === null) {
|
|
1008
|
+
return { value, valid };
|
|
942
1009
|
}
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
const
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
if (_data === undefined) {
|
|
954
|
-
_data = create;
|
|
955
|
-
contextualDataModel.$addDataNode(key, _data);
|
|
956
|
-
}
|
|
957
|
-
}
|
|
1010
|
+
let res;
|
|
1011
|
+
switch (constraint) {
|
|
1012
|
+
case 'date':
|
|
1013
|
+
res = dateRegex.exec((input || '').trim());
|
|
1014
|
+
if (res != null) {
|
|
1015
|
+
const [match, year, month, date] = res;
|
|
1016
|
+
const [nMonth, nDate] = [+month, +date];
|
|
1017
|
+
const leapYear = isLeapYear(+year);
|
|
1018
|
+
valid = (nMonth >= 1 && nMonth <= 12) &&
|
|
1019
|
+
(nDate >= 1 && nDate <= daysInMonth(leapYear, nMonth));
|
|
958
1020
|
}
|
|
959
1021
|
else {
|
|
960
|
-
|
|
1022
|
+
valid = false;
|
|
961
1023
|
}
|
|
962
|
-
|
|
1024
|
+
break;
|
|
1025
|
+
case 'email':
|
|
1026
|
+
valid = new RegExp(emailRegex).test((input || '').trim());
|
|
1027
|
+
break;
|
|
1028
|
+
case 'data-url':
|
|
1029
|
+
valid = true;
|
|
1030
|
+
break;
|
|
963
1031
|
}
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
1032
|
+
return { valid, value };
|
|
1033
|
+
},
|
|
1034
|
+
minimum: (constraint, value) => {
|
|
1035
|
+
return { valid: value >= constraint, value };
|
|
1036
|
+
},
|
|
1037
|
+
maximum: (constraint, value) => {
|
|
1038
|
+
return { valid: value <= constraint, value };
|
|
1039
|
+
},
|
|
1040
|
+
exclusiveMinimum: (constraint, value) => {
|
|
1041
|
+
return { valid: value > constraint, value };
|
|
1042
|
+
},
|
|
1043
|
+
exclusiveMaximum: (constraint, value) => {
|
|
1044
|
+
return { valid: value < constraint, value };
|
|
1045
|
+
},
|
|
1046
|
+
minItems: (constraint, value) => {
|
|
1047
|
+
return { valid: (value instanceof Array) && value.length >= constraint, value };
|
|
1048
|
+
},
|
|
1049
|
+
maxItems: (constraint, value) => {
|
|
1050
|
+
return { valid: (value instanceof Array) && value.length <= constraint, value };
|
|
1051
|
+
},
|
|
1052
|
+
uniqueItems: (constraint, value) => {
|
|
1053
|
+
return { valid: !constraint || ((value instanceof Array) && value.length === new Set(value).size), value };
|
|
1054
|
+
},
|
|
1055
|
+
minLength: (constraint, value) => {
|
|
1056
|
+
return { ...Constraints.minimum(constraint, typeof value === 'string' ? value.length : 0), value };
|
|
1057
|
+
},
|
|
1058
|
+
maxLength: (constraint, value) => {
|
|
1059
|
+
return { ...Constraints.maximum(constraint, typeof value === 'string' ? value.length : 0), value };
|
|
1060
|
+
},
|
|
1061
|
+
pattern: (constraint, value) => {
|
|
1062
|
+
let regex;
|
|
1063
|
+
if (typeof constraint === 'string') {
|
|
1064
|
+
regex = new RegExp(constraint);
|
|
971
1065
|
}
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
getDataNode() {
|
|
975
|
-
return this._data;
|
|
976
|
-
}
|
|
977
|
-
get lang() {
|
|
978
|
-
if (this._jsonModel.lang) {
|
|
979
|
-
this._lang = this._jsonModel.lang;
|
|
1066
|
+
else {
|
|
1067
|
+
regex = constraint;
|
|
980
1068
|
}
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
1069
|
+
return { valid: regex.test(value), value };
|
|
1070
|
+
},
|
|
1071
|
+
required: (constraint, value) => {
|
|
1072
|
+
const valid = constraint ? value != null && value !== '' : true;
|
|
1073
|
+
return { valid, value };
|
|
1074
|
+
},
|
|
1075
|
+
enum: (constraint, value) => {
|
|
1076
|
+
return {
|
|
1077
|
+
valid: constraint.indexOf(value) > -1,
|
|
1078
|
+
value
|
|
1079
|
+
};
|
|
1080
|
+
},
|
|
1081
|
+
accept: (constraint, value) => {
|
|
1082
|
+
if (!constraint || constraint.length === 0 || value === null || value === undefined) {
|
|
1083
|
+
return {
|
|
1084
|
+
valid: true,
|
|
1085
|
+
value
|
|
1086
|
+
};
|
|
988
1087
|
}
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
1088
|
+
const tempValue = value instanceof Array ? value : [value];
|
|
1089
|
+
const invalidFile = tempValue.some((file) => !matchMediaType(file.type, constraint));
|
|
1090
|
+
return {
|
|
1091
|
+
valid: !invalidFile,
|
|
1092
|
+
value
|
|
1093
|
+
};
|
|
1094
|
+
},
|
|
1095
|
+
maxFileSize: (constraint, value) => {
|
|
1096
|
+
const sizeLimit = typeof constraint === 'string' ? getFileSizeInBytes(constraint) : constraint;
|
|
1097
|
+
return {
|
|
1098
|
+
valid: !(value instanceof FileObject) || value.size <= sizeLimit,
|
|
1099
|
+
value
|
|
1100
|
+
};
|
|
993
1101
|
}
|
|
994
|
-
|
|
995
|
-
|
|
1102
|
+
};
|
|
1103
|
+
|
|
1104
|
+
const editableProperties = [
|
|
1105
|
+
'value',
|
|
1106
|
+
'label',
|
|
1107
|
+
'description',
|
|
1108
|
+
'visible',
|
|
1109
|
+
'enabled',
|
|
1110
|
+
'valid',
|
|
1111
|
+
'errorMessage',
|
|
1112
|
+
'readOnly',
|
|
1113
|
+
'enum',
|
|
1114
|
+
'enumNames',
|
|
1115
|
+
'required',
|
|
1116
|
+
'properties',
|
|
1117
|
+
'exclusiveMinimum',
|
|
1118
|
+
'exclusiveMaximum',
|
|
1119
|
+
'maximum',
|
|
1120
|
+
'maxItems',
|
|
1121
|
+
'minimum',
|
|
1122
|
+
'minItems',
|
|
1123
|
+
'checked'
|
|
1124
|
+
];
|
|
1125
|
+
const dynamicProps = [
|
|
1126
|
+
...editableProperties,
|
|
1127
|
+
'index',
|
|
1128
|
+
'activeChild'
|
|
1129
|
+
];
|
|
1130
|
+
const staticFields = ['plain-text', 'image'];
|
|
1131
|
+
class ActionImplWithTarget {
|
|
1132
|
+
_action;
|
|
1133
|
+
_target;
|
|
1134
|
+
constructor(_action, _target) {
|
|
1135
|
+
this._action = _action;
|
|
1136
|
+
this._target = _target;
|
|
996
1137
|
}
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
while (nonTransparentParent != null && nonTransparentParent.isTransparent()) {
|
|
1000
|
-
nonTransparentParent = nonTransparentParent.parent;
|
|
1001
|
-
}
|
|
1002
|
-
return nonTransparentParent;
|
|
1138
|
+
get type() {
|
|
1139
|
+
return this._action.type;
|
|
1003
1140
|
}
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
let dataNode, parent = this.parent;
|
|
1007
|
-
do {
|
|
1008
|
-
dataNode = parent.getDataNode();
|
|
1009
|
-
parent = parent.parent;
|
|
1010
|
-
} while (dataNode === undefined);
|
|
1011
|
-
this._bindToDataModel(dataNode);
|
|
1012
|
-
}
|
|
1141
|
+
get payload() {
|
|
1142
|
+
return this._action.payload;
|
|
1013
1143
|
}
|
|
1014
|
-
|
|
1015
|
-
return
|
|
1016
|
-
const currentValue = updates[propertyName];
|
|
1017
|
-
const changes = this._setProperty(propertyName, currentValue, false);
|
|
1018
|
-
if (changes.length > 0) {
|
|
1019
|
-
acc[propertyName] = changes[0];
|
|
1020
|
-
}
|
|
1021
|
-
return acc;
|
|
1022
|
-
}, {});
|
|
1144
|
+
get metadata() {
|
|
1145
|
+
return this._action.metadata;
|
|
1023
1146
|
}
|
|
1024
|
-
get
|
|
1025
|
-
|
|
1026
|
-
return null;
|
|
1027
|
-
}
|
|
1028
|
-
if (this[qualifiedName] !== null) {
|
|
1029
|
-
return this[qualifiedName];
|
|
1030
|
-
}
|
|
1031
|
-
const parent = this.getNonTransparentParent();
|
|
1032
|
-
if (parent && parent.type === 'array') {
|
|
1033
|
-
this[qualifiedName] = `${parent.qualifiedName}[${this.index}]`;
|
|
1034
|
-
}
|
|
1035
|
-
else {
|
|
1036
|
-
this[qualifiedName] = `${parent.qualifiedName}.${this.name}`;
|
|
1037
|
-
}
|
|
1038
|
-
return this[qualifiedName];
|
|
1147
|
+
get target() {
|
|
1148
|
+
return this._target;
|
|
1039
1149
|
}
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
this.parent.activeChild = this;
|
|
1043
|
-
}
|
|
1150
|
+
get isCustomEvent() {
|
|
1151
|
+
return this._action.isCustomEvent;
|
|
1044
1152
|
}
|
|
1045
|
-
|
|
1046
|
-
return
|
|
1153
|
+
get originalAction() {
|
|
1154
|
+
return this._action.originalAction;
|
|
1047
1155
|
}
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
if (this._jsonModel[key] === undefined && value !== undefined) {
|
|
1051
|
-
this._jsonModel[key] = value;
|
|
1052
|
-
}
|
|
1053
|
-
else if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
|
|
1054
|
-
Object.keys(value).forEach((keyOfValue) => {
|
|
1055
|
-
if (this._jsonModel[key][keyOfValue] === undefined) {
|
|
1056
|
-
this._jsonModel[key][keyOfValue] = value[keyOfValue];
|
|
1057
|
-
}
|
|
1058
|
-
});
|
|
1059
|
-
}
|
|
1060
|
-
});
|
|
1156
|
+
toString() {
|
|
1157
|
+
return this._action.toString();
|
|
1061
1158
|
}
|
|
1062
1159
|
}
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
dependencyTracked()
|
|
1074
|
-
], BaseNode.prototype, "label", null);
|
|
1075
|
-
__decorate([
|
|
1076
|
-
dependencyTracked()
|
|
1077
|
-
], BaseNode.prototype, "properties", null);
|
|
1078
|
-
|
|
1079
|
-
class Scriptable extends BaseNode {
|
|
1080
|
-
_events = {};
|
|
1081
|
-
_rules = {};
|
|
1082
|
-
getRules() {
|
|
1083
|
-
return typeof this._jsonModel.rules !== 'object' ? {} : this._jsonModel.rules;
|
|
1084
|
-
}
|
|
1085
|
-
getCompiledRule(eName, rule) {
|
|
1086
|
-
if (!(eName in this._rules)) {
|
|
1087
|
-
const eString = rule || this.getRules()[eName];
|
|
1088
|
-
if (typeof eString === 'string' && eString.length > 0) {
|
|
1089
|
-
try {
|
|
1090
|
-
this._rules[eName] = this.ruleEngine.compileRule(eString, this.lang);
|
|
1091
|
-
}
|
|
1092
|
-
catch (e) {
|
|
1093
|
-
this.form.logger.error(`Unable to compile rule \`"${eName}" : "${eString}"\` Exception : ${e}`);
|
|
1094
|
-
}
|
|
1095
|
-
}
|
|
1096
|
-
else {
|
|
1097
|
-
throw new Error(`only expression strings are supported. ${typeof (eString)} types are not supported`);
|
|
1098
|
-
}
|
|
1160
|
+
const target = Symbol('target');
|
|
1161
|
+
const qualifiedName = Symbol('qualifiedName');
|
|
1162
|
+
function dependencyTracked() {
|
|
1163
|
+
return function (target, propertyKey, descriptor) {
|
|
1164
|
+
const get = descriptor.get;
|
|
1165
|
+
if (get != undefined) {
|
|
1166
|
+
descriptor.get = function () {
|
|
1167
|
+
this.ruleEngine.trackDependency(this);
|
|
1168
|
+
return get.call(this);
|
|
1169
|
+
};
|
|
1099
1170
|
}
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1171
|
+
};
|
|
1172
|
+
}
|
|
1173
|
+
const addOnly = (includeOrExclude) => (...fieldTypes) => (target, propertyKey, descriptor) => {
|
|
1174
|
+
const get = descriptor.get;
|
|
1175
|
+
if (get != undefined) {
|
|
1176
|
+
descriptor.get = function () {
|
|
1177
|
+
if (fieldTypes.indexOf(this.fieldType) > -1 === includeOrExclude) {
|
|
1178
|
+
return get.call(this);
|
|
1107
1179
|
}
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
return null;
|
|
1117
|
-
}).filter(x => x !== null);
|
|
1180
|
+
return undefined;
|
|
1181
|
+
};
|
|
1182
|
+
}
|
|
1183
|
+
const set = descriptor.set;
|
|
1184
|
+
if (set != undefined) {
|
|
1185
|
+
descriptor.set = function (value) {
|
|
1186
|
+
if (fieldTypes.indexOf(this.fieldType) > -1 === includeOrExclude) {
|
|
1187
|
+
set.call(this, value);
|
|
1118
1188
|
}
|
|
1119
|
-
}
|
|
1120
|
-
|
|
1189
|
+
};
|
|
1190
|
+
}
|
|
1191
|
+
};
|
|
1192
|
+
const include = addOnly(true);
|
|
1193
|
+
const exclude = addOnly(false);
|
|
1194
|
+
class BaseNode {
|
|
1195
|
+
_options;
|
|
1196
|
+
_ruleNode;
|
|
1197
|
+
_lang = '';
|
|
1198
|
+
_callbacks = {};
|
|
1199
|
+
_dependents = [];
|
|
1200
|
+
_jsonModel;
|
|
1201
|
+
_tokens = [];
|
|
1202
|
+
get isContainer() {
|
|
1203
|
+
return false;
|
|
1121
1204
|
}
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1205
|
+
constructor(params, _options) {
|
|
1206
|
+
this._options = _options;
|
|
1207
|
+
this[qualifiedName] = null;
|
|
1208
|
+
this._jsonModel = {
|
|
1209
|
+
...params,
|
|
1210
|
+
id: 'id' in params ? params.id : this.form.getUniqueId()
|
|
1211
|
+
};
|
|
1212
|
+
}
|
|
1213
|
+
setupRuleNode() {
|
|
1214
|
+
const self = this;
|
|
1215
|
+
this._ruleNode = new Proxy(this.ruleNodeReference(), {
|
|
1216
|
+
get: (ruleNodeReference, prop) => {
|
|
1217
|
+
return self.getFromRule(ruleNodeReference, prop);
|
|
1131
1218
|
}
|
|
1132
1219
|
});
|
|
1133
1220
|
}
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
if (entries.length > 0) {
|
|
1137
|
-
const scope = this.getExpressionScope();
|
|
1138
|
-
entries.forEach(([prop, rule]) => {
|
|
1139
|
-
const node = this.getCompiledRule(prop, rule);
|
|
1140
|
-
if (node) {
|
|
1141
|
-
const newVal = this.ruleEngine.execute(node, scope, context, true);
|
|
1142
|
-
if (editableProperties.indexOf(prop) > -1) {
|
|
1143
|
-
const oldAndNewValueAreEmpty = this.isEmpty() && this.isEmpty(newVal) && prop === 'value';
|
|
1144
|
-
if (!oldAndNewValueAreEmpty) {
|
|
1145
|
-
this[prop] = newVal;
|
|
1146
|
-
}
|
|
1147
|
-
}
|
|
1148
|
-
else {
|
|
1149
|
-
this.form.logger.warn(`${prop} is not a valid editable property.`);
|
|
1150
|
-
}
|
|
1151
|
-
}
|
|
1152
|
-
});
|
|
1153
|
-
}
|
|
1221
|
+
ruleNodeReference() {
|
|
1222
|
+
return this;
|
|
1154
1223
|
}
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1224
|
+
getRuleNode() {
|
|
1225
|
+
return this._ruleNode;
|
|
1226
|
+
}
|
|
1227
|
+
getFromRule(ruleNodeReference, prop) {
|
|
1228
|
+
if (prop === Symbol.toPrimitive || (prop === 'valueOf' && !ruleNodeReference.hasOwnProperty('valueOf'))) {
|
|
1229
|
+
return this.valueOf;
|
|
1230
|
+
}
|
|
1231
|
+
else if (prop === target) {
|
|
1232
|
+
return this;
|
|
1233
|
+
}
|
|
1234
|
+
else if (typeof (prop) === 'string') {
|
|
1235
|
+
if (prop.startsWith('$')) {
|
|
1236
|
+
prop = prop.substr(1);
|
|
1237
|
+
if (typeof this[prop] !== 'function') {
|
|
1238
|
+
const retValue = this[prop];
|
|
1168
1239
|
if (retValue instanceof BaseNode) {
|
|
1169
1240
|
return retValue.getRuleNode();
|
|
1170
1241
|
}
|
|
@@ -1175,918 +1246,1135 @@ class Scriptable extends BaseNode {
|
|
|
1175
1246
|
return retValue;
|
|
1176
1247
|
}
|
|
1177
1248
|
}
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1249
|
+
}
|
|
1250
|
+
else {
|
|
1251
|
+
if (ruleNodeReference.hasOwnProperty(prop)) {
|
|
1252
|
+
return ruleNodeReference[prop];
|
|
1253
|
+
}
|
|
1254
|
+
else if (typeof ruleNodeReference[prop] === 'function') {
|
|
1255
|
+
return ruleNodeReference[prop];
|
|
1185
1256
|
}
|
|
1186
|
-
},
|
|
1187
|
-
has: (target, prop) => {
|
|
1188
|
-
prop = prop;
|
|
1189
|
-
const selfPropertyOrChild = target.self[prop];
|
|
1190
|
-
const sibling = target.siblings[prop];
|
|
1191
|
-
return typeof selfPropertyOrChild != 'undefined' || typeof sibling != 'undefined';
|
|
1192
1257
|
}
|
|
1193
|
-
});
|
|
1194
|
-
return scope;
|
|
1195
|
-
}
|
|
1196
|
-
executeEvent(context, node) {
|
|
1197
|
-
let updates;
|
|
1198
|
-
if (node) {
|
|
1199
|
-
updates = this.ruleEngine.execute(node, this.getExpressionScope(), context);
|
|
1200
|
-
}
|
|
1201
|
-
if (typeof updates !== 'undefined' && updates != null) {
|
|
1202
|
-
this.applyUpdates(updates);
|
|
1203
|
-
}
|
|
1204
|
-
}
|
|
1205
|
-
executeRule(event, context) {
|
|
1206
|
-
if (typeof event.payload.ruleName === 'undefined') {
|
|
1207
|
-
this.executeAllRules(context);
|
|
1208
1258
|
}
|
|
1209
1259
|
}
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
'form': this.form,
|
|
1213
|
-
'$form': this.form.getRuleNode(),
|
|
1214
|
-
'$field': this.getRuleNode(),
|
|
1215
|
-
'field': this
|
|
1216
|
-
};
|
|
1217
|
-
const node = this.ruleEngine.compileRule(expr, this.lang);
|
|
1218
|
-
return this.ruleEngine.execute(node, this.getExpressionScope(), ruleContext);
|
|
1260
|
+
get id() {
|
|
1261
|
+
return this._jsonModel.id;
|
|
1219
1262
|
}
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
'$form': this.form.getRuleNode(),
|
|
1224
|
-
'$field': this.getRuleNode(),
|
|
1225
|
-
'field': this,
|
|
1226
|
-
'$event': {
|
|
1227
|
-
type: action.type,
|
|
1228
|
-
payload: action.payload,
|
|
1229
|
-
target: this.getRuleNode()
|
|
1230
|
-
}
|
|
1231
|
-
};
|
|
1232
|
-
const eventName = action.isCustomEvent ? `custom:${action.type}` : action.type;
|
|
1233
|
-
const funcName = action.isCustomEvent ? `custom_${action.type}` : action.type;
|
|
1234
|
-
const node = this.getCompiledEvent(eventName);
|
|
1235
|
-
if (funcName in this && typeof this[funcName] === 'function') {
|
|
1236
|
-
this[funcName](action, context);
|
|
1263
|
+
get index() {
|
|
1264
|
+
if (this.parent) {
|
|
1265
|
+
return this.parent.indexOf(this);
|
|
1237
1266
|
}
|
|
1238
|
-
|
|
1239
|
-
this.notifyDependents(action);
|
|
1240
|
-
}
|
|
1241
|
-
}
|
|
1242
|
-
|
|
1243
|
-
const notifyChildrenAttributes = [
|
|
1244
|
-
'readOnly', 'enabled'
|
|
1245
|
-
];
|
|
1246
|
-
class Container extends Scriptable {
|
|
1247
|
-
_children = [];
|
|
1248
|
-
_childrenReference;
|
|
1249
|
-
_itemTemplate = null;
|
|
1250
|
-
fieldFactory;
|
|
1251
|
-
constructor(json, _options) {
|
|
1252
|
-
super(json, { form: _options.form, parent: _options.parent, mode: _options.mode });
|
|
1253
|
-
this.fieldFactory = _options.fieldFactory;
|
|
1254
|
-
}
|
|
1255
|
-
_getDefaults() {
|
|
1256
|
-
return {
|
|
1257
|
-
...super._getDefaults(),
|
|
1258
|
-
enabled: true,
|
|
1259
|
-
readOnly: false
|
|
1260
|
-
};
|
|
1261
|
-
}
|
|
1262
|
-
ruleNodeReference() {
|
|
1263
|
-
return this._childrenReference;
|
|
1264
|
-
}
|
|
1265
|
-
get items() {
|
|
1266
|
-
return this._children;
|
|
1267
|
+
return 0;
|
|
1267
1268
|
}
|
|
1268
|
-
get
|
|
1269
|
-
return this.
|
|
1269
|
+
get parent() {
|
|
1270
|
+
return this._options.parent;
|
|
1270
1271
|
}
|
|
1271
|
-
|
|
1272
|
-
this._jsonModel.
|
|
1273
|
-
const minItems = this._jsonModel.minItems || 1;
|
|
1274
|
-
const itemsLength = this._children.length;
|
|
1275
|
-
const items2Remove = Math.min(itemsLength - m, itemsLength - minItems);
|
|
1276
|
-
if (items2Remove > 0) {
|
|
1277
|
-
for (let i = 0; i < items2Remove; i++) {
|
|
1278
|
-
this.getDataNode().$removeDataNode(m + i);
|
|
1279
|
-
this._childrenReference.pop();
|
|
1280
|
-
}
|
|
1281
|
-
const elems = this._children.splice(m, items2Remove);
|
|
1282
|
-
this.notifyDependents(propertyChange('items', elems, null));
|
|
1283
|
-
}
|
|
1272
|
+
get type() {
|
|
1273
|
+
return this._jsonModel.type;
|
|
1284
1274
|
}
|
|
1285
|
-
get
|
|
1286
|
-
return this.
|
|
1275
|
+
get repeatable() {
|
|
1276
|
+
return this.parent?.hasDynamicItems();
|
|
1287
1277
|
}
|
|
1288
|
-
|
|
1289
|
-
this._jsonModel.
|
|
1290
|
-
const itemsLength = this._children.length;
|
|
1291
|
-
const difference = itemsLength - m;
|
|
1292
|
-
const items2Add = Math.abs(difference);
|
|
1293
|
-
if (difference < 0) {
|
|
1294
|
-
const elems = [];
|
|
1295
|
-
for (let i = 0; i < items2Add; i++) {
|
|
1296
|
-
elems.push(this._addChild(this._itemTemplate, null, true));
|
|
1297
|
-
}
|
|
1298
|
-
this.notifyDependents(propertyChange('items', elems, null));
|
|
1299
|
-
}
|
|
1278
|
+
get fieldType() {
|
|
1279
|
+
return this._jsonModel.fieldType || 'text-input';
|
|
1300
1280
|
}
|
|
1301
|
-
|
|
1302
|
-
return this.
|
|
1281
|
+
get ':type'() {
|
|
1282
|
+
return this._jsonModel[':type'] || this.fieldType;
|
|
1303
1283
|
}
|
|
1304
|
-
get
|
|
1305
|
-
return
|
|
1284
|
+
get name() {
|
|
1285
|
+
return this._jsonModel.name;
|
|
1306
1286
|
}
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
return (':items' in item || 'cqItems' in item) && !('fieldType' in item);
|
|
1287
|
+
get description() {
|
|
1288
|
+
return this._jsonModel.description;
|
|
1310
1289
|
}
|
|
1311
|
-
|
|
1312
|
-
|
|
1290
|
+
set description(d) {
|
|
1291
|
+
this._setProperty('description', d);
|
|
1313
1292
|
}
|
|
1314
|
-
|
|
1315
|
-
return this._jsonModel.
|
|
1316
|
-
if (this.isSiteContainer(x)) {
|
|
1317
|
-
const newObjWithId = {
|
|
1318
|
-
...(x?.id ? { id: this.form.getUniqueId() } : {})
|
|
1319
|
-
};
|
|
1320
|
-
return {
|
|
1321
|
-
...x,
|
|
1322
|
-
...newObjWithId,
|
|
1323
|
-
':items': this.walkSiteContainerItems(x)
|
|
1324
|
-
};
|
|
1325
|
-
}
|
|
1326
|
-
else if (this.isAFormField(x)) {
|
|
1327
|
-
return { ...this.form.getElement(x?.id).getState(isRepeatableChild, forRestore) };
|
|
1328
|
-
}
|
|
1329
|
-
else {
|
|
1330
|
-
return x;
|
|
1331
|
-
}
|
|
1332
|
-
}) : [];
|
|
1293
|
+
get dataRef() {
|
|
1294
|
+
return this._jsonModel.dataRef;
|
|
1333
1295
|
}
|
|
1334
|
-
|
|
1335
|
-
if (this.
|
|
1336
|
-
|
|
1337
|
-
return this._getFormAndSitesState(isRepeatableChild, forRestore);
|
|
1338
|
-
}
|
|
1339
|
-
else {
|
|
1340
|
-
return this._children.map(x => {
|
|
1341
|
-
return { ...x.getState(true, forRestore) };
|
|
1342
|
-
});
|
|
1343
|
-
}
|
|
1296
|
+
get visible() {
|
|
1297
|
+
if (this.parent?.visible !== undefined) {
|
|
1298
|
+
return this.parent?.visible ? this._jsonModel.visible : false;
|
|
1344
1299
|
}
|
|
1345
1300
|
else {
|
|
1346
|
-
return this.
|
|
1301
|
+
return this._jsonModel.visible;
|
|
1347
1302
|
}
|
|
1348
1303
|
}
|
|
1349
|
-
|
|
1304
|
+
set visible(v) {
|
|
1305
|
+
if (v !== this._jsonModel.visible) {
|
|
1306
|
+
const changeAction = propertyChange('visible', v, this._jsonModel.visible);
|
|
1307
|
+
this._jsonModel.visible = v;
|
|
1308
|
+
this.notifyDependents(changeAction);
|
|
1309
|
+
}
|
|
1310
|
+
}
|
|
1311
|
+
get form() {
|
|
1312
|
+
return this._options.form;
|
|
1313
|
+
}
|
|
1314
|
+
get ruleEngine() {
|
|
1315
|
+
return this.form.ruleEngine;
|
|
1316
|
+
}
|
|
1317
|
+
get label() {
|
|
1318
|
+
return this._jsonModel.label;
|
|
1319
|
+
}
|
|
1320
|
+
set label(l) {
|
|
1321
|
+
if (l !== this._jsonModel.label) {
|
|
1322
|
+
const changeAction = propertyChange('label', l, this._jsonModel.label);
|
|
1323
|
+
this._jsonModel = {
|
|
1324
|
+
...this._jsonModel,
|
|
1325
|
+
label: l
|
|
1326
|
+
};
|
|
1327
|
+
this.notifyDependents(changeAction);
|
|
1328
|
+
}
|
|
1329
|
+
}
|
|
1330
|
+
get uniqueItems() {
|
|
1331
|
+
return this._jsonModel.uniqueItems;
|
|
1332
|
+
}
|
|
1333
|
+
isTransparent() {
|
|
1334
|
+
const isNonTransparent = this.parent?._jsonModel.type === 'array';
|
|
1335
|
+
return !this._jsonModel.name && !isNonTransparent;
|
|
1336
|
+
}
|
|
1337
|
+
getState(forRestore = false) {
|
|
1350
1338
|
return {
|
|
1351
|
-
...
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1339
|
+
...this._jsonModel,
|
|
1340
|
+
properties: this.properties,
|
|
1341
|
+
index: this.index,
|
|
1342
|
+
parent: undefined,
|
|
1343
|
+
qualifiedName: this.qualifiedName,
|
|
1344
|
+
...(this.repeatable === true ? {
|
|
1345
|
+
repeatable: true,
|
|
1346
|
+
minOccur: this.parent.minItems,
|
|
1347
|
+
maxOccur: this.parent.maxItems
|
|
1355
1348
|
} : {}),
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1349
|
+
':type': this[':type'],
|
|
1350
|
+
...(forRestore ? {
|
|
1351
|
+
_dependents: this._dependents.length ? this._dependents.map(x => x.node.id) : undefined,
|
|
1352
|
+
allowedComponents: undefined,
|
|
1353
|
+
columnClassNames: undefined,
|
|
1354
|
+
columnCount: undefined,
|
|
1355
|
+
gridClassNames: undefined
|
|
1356
|
+
} : {})
|
|
1359
1357
|
};
|
|
1360
1358
|
}
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
return [key, this.form.getElement(value?.id).getState()];
|
|
1368
|
-
}
|
|
1369
|
-
else if (this.isSiteContainer(value)) {
|
|
1370
|
-
return this.walkSiteContainerItems(value);
|
|
1371
|
-
}
|
|
1372
|
-
else {
|
|
1373
|
-
if (typeof value === 'object') {
|
|
1374
|
-
const newObjWithId = {
|
|
1375
|
-
...(value?.id ? { id: this.form.getUniqueId() } : {})
|
|
1376
|
-
};
|
|
1377
|
-
return [key, {
|
|
1378
|
-
...value,
|
|
1379
|
-
...newObjWithId
|
|
1380
|
-
}
|
|
1381
|
-
];
|
|
1382
|
-
}
|
|
1383
|
-
else {
|
|
1384
|
-
return [key, value];
|
|
1385
|
-
}
|
|
1359
|
+
subscribe(callback, eventName = 'change') {
|
|
1360
|
+
this._callbacks[eventName] = this._callbacks[eventName] || [];
|
|
1361
|
+
this._callbacks[eventName].push(callback);
|
|
1362
|
+
return {
|
|
1363
|
+
unsubscribe: () => {
|
|
1364
|
+
this._callbacks[eventName] = this._callbacks[eventName].filter(x => x !== callback);
|
|
1386
1365
|
}
|
|
1387
|
-
}
|
|
1366
|
+
};
|
|
1388
1367
|
}
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
self.ruleEngine.trackDependency(self);
|
|
1401
|
-
if (this._children[name] !== undefined) {
|
|
1402
|
-
return this._children[name].getRuleNode();
|
|
1403
|
-
}
|
|
1404
|
-
}
|
|
1405
|
-
else {
|
|
1406
|
-
return child.getRuleNode();
|
|
1407
|
-
}
|
|
1408
|
-
},
|
|
1409
|
-
configurable: true,
|
|
1410
|
-
enumerable: true
|
|
1368
|
+
_addDependent(dependent) {
|
|
1369
|
+
if (this._dependents.find(({ node }) => node === dependent) === undefined) {
|
|
1370
|
+
const subscription = this.subscribe((change) => {
|
|
1371
|
+
const changes = change.payload.changes;
|
|
1372
|
+
const propsToLook = [...dynamicProps, 'items'];
|
|
1373
|
+
const isPropChanged = changes.findIndex(x => {
|
|
1374
|
+
return propsToLook.indexOf(x.propertyName) > -1;
|
|
1375
|
+
}) > -1;
|
|
1376
|
+
if (isPropChanged) {
|
|
1377
|
+
dependent.dispatch(new ExecuteRule());
|
|
1378
|
+
}
|
|
1411
1379
|
});
|
|
1380
|
+
this._dependents.push({ node: dependent, subscription });
|
|
1412
1381
|
}
|
|
1413
1382
|
}
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
if (typeof index !== 'number' || index > nonTransparentParent._children.length) {
|
|
1420
|
-
index = this._children.length;
|
|
1421
|
-
}
|
|
1422
|
-
const form = this.form;
|
|
1423
|
-
const itemTemplate = {
|
|
1424
|
-
index,
|
|
1425
|
-
...deepClone(itemJson, cloneIds ? () => { return form.getUniqueId(); } : undefined)
|
|
1426
|
-
};
|
|
1427
|
-
const retVal = this._createChild(itemTemplate, { parent: this, form: this.form, mode });
|
|
1428
|
-
itemJson.id = retVal.id;
|
|
1429
|
-
this.form.fieldAdded(retVal);
|
|
1430
|
-
this._addChildToRuleNode(retVal, { parent: nonTransparentParent });
|
|
1431
|
-
if (index === this._children.length) {
|
|
1432
|
-
this._children.push(retVal);
|
|
1383
|
+
removeDependent(dependent) {
|
|
1384
|
+
const index = this._dependents.findIndex(({ node }) => node === dependent);
|
|
1385
|
+
if (index > -1) {
|
|
1386
|
+
this._dependents[index].subscription.unsubscribe();
|
|
1387
|
+
this._dependents.splice(index, 1);
|
|
1433
1388
|
}
|
|
1434
|
-
|
|
1435
|
-
|
|
1389
|
+
}
|
|
1390
|
+
queueEvent(action) {
|
|
1391
|
+
const actionWithTarget = new ActionImplWithTarget(action, this);
|
|
1392
|
+
this.form.getEventQueue().queue(this, actionWithTarget, ['valid', 'invalid'].indexOf(actionWithTarget.type) > -1);
|
|
1393
|
+
}
|
|
1394
|
+
dispatch(action) {
|
|
1395
|
+
this.queueEvent(action);
|
|
1396
|
+
this.form.getEventQueue().runPendingQueue();
|
|
1397
|
+
}
|
|
1398
|
+
notifyDependents(action) {
|
|
1399
|
+
const depsToRestore = this._jsonModel._dependents;
|
|
1400
|
+
if (depsToRestore) {
|
|
1401
|
+
depsToRestore.forEach((x) => {
|
|
1402
|
+
const node = this.form.getElement(x);
|
|
1403
|
+
if (node) {
|
|
1404
|
+
this._addDependent(node);
|
|
1405
|
+
}
|
|
1406
|
+
});
|
|
1407
|
+
this._jsonModel._dependents = undefined;
|
|
1436
1408
|
}
|
|
1437
|
-
|
|
1409
|
+
const handlers = this._callbacks[action.type] || [];
|
|
1410
|
+
handlers.forEach(x => {
|
|
1411
|
+
x(new ActionImplWithTarget(action, this));
|
|
1412
|
+
});
|
|
1438
1413
|
}
|
|
1439
|
-
|
|
1440
|
-
return
|
|
1414
|
+
isEmpty(value = this._jsonModel.value) {
|
|
1415
|
+
return value === undefined || value === null || value === '';
|
|
1441
1416
|
}
|
|
1442
|
-
|
|
1443
|
-
const
|
|
1444
|
-
|
|
1445
|
-
|
|
1417
|
+
_setProperty(prop, newValue, notify = true, notifyChildren = (action) => { }) {
|
|
1418
|
+
const oldValue = this._jsonModel[prop];
|
|
1419
|
+
let isValueSame = false;
|
|
1420
|
+
if (newValue !== null && oldValue !== null &&
|
|
1421
|
+
typeof newValue === 'object' && typeof oldValue === 'object') {
|
|
1422
|
+
isValueSame = JSON.stringify(newValue) === JSON.stringify(oldValue);
|
|
1446
1423
|
}
|
|
1447
1424
|
else {
|
|
1448
|
-
|
|
1449
|
-
return new DataGroup(name, instance, type);
|
|
1425
|
+
isValueSame = oldValue === newValue;
|
|
1450
1426
|
}
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
}
|
|
1457
|
-
_initialize(mode) {
|
|
1458
|
-
super._initialize(mode);
|
|
1459
|
-
const items = this._jsonModel.items || [];
|
|
1460
|
-
this._childrenReference = this._jsonModel.type == 'array' ? [] : {};
|
|
1461
|
-
if (this._canHaveRepeatingChildren(mode)) {
|
|
1462
|
-
this._itemTemplate = deepClone(items[0]);
|
|
1463
|
-
if (mode === 'restore') {
|
|
1464
|
-
this._itemTemplate.repeatable = undefined;
|
|
1465
|
-
}
|
|
1466
|
-
if (typeof (this._jsonModel.minItems) !== 'number') {
|
|
1467
|
-
this._jsonModel.minItems = 0;
|
|
1427
|
+
if (!isValueSame) {
|
|
1428
|
+
this._jsonModel[prop] = newValue;
|
|
1429
|
+
const changeAction = propertyChange(prop, newValue, oldValue);
|
|
1430
|
+
if (notify) {
|
|
1431
|
+
this.notifyDependents(changeAction);
|
|
1468
1432
|
}
|
|
1469
|
-
|
|
1470
|
-
|
|
1433
|
+
notifyChildren.call(this, changeAction);
|
|
1434
|
+
if (validationConstraintsList.includes(prop)) {
|
|
1435
|
+
this.validate();
|
|
1471
1436
|
}
|
|
1472
|
-
|
|
1473
|
-
|
|
1437
|
+
return changeAction.payload.changes;
|
|
1438
|
+
}
|
|
1439
|
+
return [];
|
|
1440
|
+
}
|
|
1441
|
+
_bindToDataModel(contextualDataModel) {
|
|
1442
|
+
if (this.id === '$form') {
|
|
1443
|
+
this._data = contextualDataModel;
|
|
1444
|
+
return;
|
|
1445
|
+
}
|
|
1446
|
+
const dataRef = this._jsonModel.dataRef;
|
|
1447
|
+
let _data, _parent = contextualDataModel, _key = '';
|
|
1448
|
+
if (dataRef === null) {
|
|
1449
|
+
_data = NullDataValue;
|
|
1450
|
+
}
|
|
1451
|
+
else if (dataRef !== undefined && !this.repeatable) {
|
|
1452
|
+
if (this._tokens.length === 0) {
|
|
1453
|
+
this._tokens = tokenize(dataRef);
|
|
1474
1454
|
}
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
child = this._addChild(itemTemplate, undefined, i > this._jsonModel.items.length - 1, mode);
|
|
1484
|
-
}
|
|
1485
|
-
else {
|
|
1486
|
-
child = this._addChild(this._itemTemplate, undefined, i > this._jsonModel.items.length - 1);
|
|
1487
|
-
}
|
|
1488
|
-
if (mode === 'create') {
|
|
1489
|
-
items[0].id = child.id;
|
|
1455
|
+
let searchData = contextualDataModel;
|
|
1456
|
+
if (this._tokens[0].type === TOK_GLOBAL) {
|
|
1457
|
+
searchData = this.form.getDataNode();
|
|
1458
|
+
}
|
|
1459
|
+
else if (this._tokens[0].type === TOK_REPEATABLE) {
|
|
1460
|
+
let repeatRoot = this.parent;
|
|
1461
|
+
while (!repeatRoot.repeatable && repeatRoot !== this.form) {
|
|
1462
|
+
repeatRoot = repeatRoot.parent;
|
|
1490
1463
|
}
|
|
1491
|
-
|
|
1464
|
+
searchData = repeatRoot.getDataNode();
|
|
1465
|
+
}
|
|
1466
|
+
if (typeof searchData !== 'undefined') {
|
|
1467
|
+
const name = this._tokens[this._tokens.length - 1].value;
|
|
1468
|
+
const create = this.defaultDataModel(name);
|
|
1469
|
+
_data = resolveData(searchData, this._tokens, create);
|
|
1470
|
+
_parent = resolveData(searchData, this._tokens.slice(0, -1));
|
|
1471
|
+
_key = name;
|
|
1492
1472
|
}
|
|
1493
1473
|
}
|
|
1494
|
-
else
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1474
|
+
else {
|
|
1475
|
+
if (contextualDataModel !== NullDataValue && staticFields.indexOf(this.fieldType) === -1) {
|
|
1476
|
+
_parent = contextualDataModel;
|
|
1477
|
+
const name = this._jsonModel.name || '';
|
|
1478
|
+
const key = contextualDataModel.$type === 'array' ? this.index : name;
|
|
1479
|
+
_key = key;
|
|
1480
|
+
if (key !== '') {
|
|
1481
|
+
const create = this.defaultDataModel(key);
|
|
1482
|
+
if (create !== undefined) {
|
|
1483
|
+
_data = contextualDataModel.$getDataNode(key);
|
|
1484
|
+
if (_data === undefined) {
|
|
1485
|
+
_data = create;
|
|
1486
|
+
contextualDataModel.$addDataNode(key, _data);
|
|
1487
|
+
}
|
|
1488
|
+
}
|
|
1502
1489
|
}
|
|
1503
1490
|
else {
|
|
1504
|
-
|
|
1491
|
+
_data = undefined;
|
|
1505
1492
|
}
|
|
1506
|
-
}
|
|
1507
|
-
this._jsonModel.minItems = this._children.length;
|
|
1508
|
-
this._jsonModel.maxItems = this._children.length;
|
|
1509
|
-
this._jsonModel.initialItems = this._children.length;
|
|
1493
|
+
}
|
|
1510
1494
|
}
|
|
1511
|
-
|
|
1512
|
-
this.
|
|
1495
|
+
if (_data) {
|
|
1496
|
+
if (!this.isContainer && _parent !== NullDataValue && _data !== NullDataValue) {
|
|
1497
|
+
_data = _data?.$convertToDataValue();
|
|
1498
|
+
_parent.$addDataNode(_key, _data, true);
|
|
1499
|
+
}
|
|
1500
|
+
_data?.$bindToField(this);
|
|
1501
|
+
this._data = _data;
|
|
1513
1502
|
}
|
|
1514
|
-
this.setupRuleNode();
|
|
1515
1503
|
}
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
const child = this._addChild(value);
|
|
1520
|
-
child._initialize();
|
|
1521
|
-
}
|
|
1522
|
-
else if (this.isSiteContainer(value)) {
|
|
1523
|
-
return this._initializeSiteContainer(value);
|
|
1524
|
-
}
|
|
1525
|
-
});
|
|
1504
|
+
_data;
|
|
1505
|
+
getDataNode() {
|
|
1506
|
+
return this._data;
|
|
1526
1507
|
}
|
|
1527
|
-
|
|
1528
|
-
if (
|
|
1529
|
-
|
|
1530
|
-
const dataNode = this.getDataNode();
|
|
1531
|
-
let instanceIndex = action.payload;
|
|
1532
|
-
const retVal = this._addChild(this._itemTemplate, action.payload, true);
|
|
1533
|
-
if (typeof instanceIndex !== 'number' || instanceIndex > this._children.length) {
|
|
1534
|
-
instanceIndex = this._children.length;
|
|
1535
|
-
}
|
|
1536
|
-
const _data = retVal.defaultDataModel(instanceIndex);
|
|
1537
|
-
if (_data) {
|
|
1538
|
-
dataNode.$addDataNode(instanceIndex, _data);
|
|
1539
|
-
}
|
|
1540
|
-
retVal._initialize('create');
|
|
1541
|
-
this.notifyDependents(propertyChange('items', retVal.getState(), null));
|
|
1542
|
-
retVal.dispatch(new Initialize());
|
|
1543
|
-
retVal.dispatch(new ExecuteRule());
|
|
1544
|
-
for (let i = instanceIndex + 1; i < this._children.length; i++) {
|
|
1545
|
-
this._children[i].dispatch(new ExecuteRule());
|
|
1546
|
-
}
|
|
1547
|
-
}
|
|
1508
|
+
get lang() {
|
|
1509
|
+
if (this._jsonModel.lang) {
|
|
1510
|
+
this._lang = this._jsonModel.lang;
|
|
1548
1511
|
}
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
if (this._children.length == 0) {
|
|
1553
|
-
return;
|
|
1554
|
-
}
|
|
1555
|
-
let instanceIndex = action.payload;
|
|
1556
|
-
if (typeof instanceIndex !== 'number') {
|
|
1557
|
-
instanceIndex = this._children.length - 1;
|
|
1512
|
+
if (!this._lang) {
|
|
1513
|
+
if (this.parent) {
|
|
1514
|
+
this._lang = this.parent.lang;
|
|
1558
1515
|
}
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
this._childrenReference.pop();
|
|
1562
|
-
this._children.splice(instanceIndex, 1);
|
|
1563
|
-
this.getDataNode().$removeDataNode(instanceIndex);
|
|
1564
|
-
for (let i = instanceIndex; i < this._children.length; i++) {
|
|
1565
|
-
this._children[i].dispatch(new ExecuteRule());
|
|
1566
|
-
}
|
|
1567
|
-
this.notifyDependents(propertyChange('items', null, state));
|
|
1516
|
+
else {
|
|
1517
|
+
this._lang = Intl.DateTimeFormat().resolvedOptions().locale;
|
|
1568
1518
|
}
|
|
1569
1519
|
}
|
|
1520
|
+
return this._lang;
|
|
1570
1521
|
}
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1522
|
+
get properties() {
|
|
1523
|
+
return this._jsonModel.properties || {};
|
|
1524
|
+
}
|
|
1525
|
+
set properties(p) {
|
|
1526
|
+
this._setProperty('properties', { ...p });
|
|
1527
|
+
}
|
|
1528
|
+
getNonTransparentParent() {
|
|
1529
|
+
let nonTransparentParent = this.parent;
|
|
1530
|
+
while (nonTransparentParent != null && nonTransparentParent.isTransparent()) {
|
|
1531
|
+
nonTransparentParent = nonTransparentParent.parent;
|
|
1577
1532
|
}
|
|
1533
|
+
return nonTransparentParent;
|
|
1578
1534
|
}
|
|
1579
|
-
|
|
1580
|
-
if (this.
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1535
|
+
_initialize(mode) {
|
|
1536
|
+
if (typeof this._data === 'undefined') {
|
|
1537
|
+
let dataNode, parent = this.parent;
|
|
1538
|
+
do {
|
|
1539
|
+
dataNode = parent.getDataNode();
|
|
1540
|
+
parent = parent.parent;
|
|
1541
|
+
} while (dataNode === undefined);
|
|
1542
|
+
this._bindToDataModel(dataNode);
|
|
1587
1543
|
}
|
|
1588
|
-
this.items.forEach(x => {
|
|
1589
|
-
x.reset();
|
|
1590
|
-
});
|
|
1591
1544
|
}
|
|
1592
|
-
|
|
1593
|
-
return
|
|
1594
|
-
|
|
1595
|
-
|
|
1545
|
+
_applyUpdates(propNames, updates) {
|
|
1546
|
+
return propNames.reduce((acc, propertyName) => {
|
|
1547
|
+
const currentValue = updates[propertyName];
|
|
1548
|
+
const changes = this._setProperty(propertyName, currentValue, false);
|
|
1549
|
+
if (changes.length > 0) {
|
|
1550
|
+
acc[propertyName] = changes[0];
|
|
1551
|
+
}
|
|
1552
|
+
return acc;
|
|
1553
|
+
}, {});
|
|
1596
1554
|
}
|
|
1597
|
-
|
|
1598
|
-
|
|
1555
|
+
get qualifiedName() {
|
|
1556
|
+
if (this.isTransparent()) {
|
|
1557
|
+
return null;
|
|
1558
|
+
}
|
|
1559
|
+
if (this[qualifiedName] !== null) {
|
|
1560
|
+
return this[qualifiedName];
|
|
1561
|
+
}
|
|
1562
|
+
const parent = this.getNonTransparentParent();
|
|
1563
|
+
if (parent && parent.type === 'array') {
|
|
1564
|
+
this[qualifiedName] = `${parent.qualifiedName}[${this.index}]`;
|
|
1565
|
+
}
|
|
1566
|
+
else {
|
|
1567
|
+
this[qualifiedName] = `${parent.qualifiedName}.${this.name}`;
|
|
1568
|
+
}
|
|
1569
|
+
return this[qualifiedName];
|
|
1599
1570
|
}
|
|
1600
|
-
|
|
1601
|
-
this.
|
|
1602
|
-
|
|
1603
|
-
|
|
1571
|
+
focus() {
|
|
1572
|
+
if (this.parent) {
|
|
1573
|
+
this.parent.activeChild = this;
|
|
1574
|
+
}
|
|
1604
1575
|
}
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
const items2Remove = Math.min(itemsLength - dataLength, itemsLength - minItems);
|
|
1613
|
-
while (items2Add > 0) {
|
|
1614
|
-
items2Add--;
|
|
1615
|
-
const child = this._addChild(this._itemTemplate);
|
|
1616
|
-
child._initialize('create');
|
|
1576
|
+
_getDefaults() {
|
|
1577
|
+
return {};
|
|
1578
|
+
}
|
|
1579
|
+
_applyDefaultsInModel() {
|
|
1580
|
+
Object.entries(this._getDefaults()).map(([key, value]) => {
|
|
1581
|
+
if (this._jsonModel[key] === undefined && value !== undefined) {
|
|
1582
|
+
this._jsonModel[key] = value;
|
|
1617
1583
|
}
|
|
1618
|
-
if (
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1584
|
+
else if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
|
|
1585
|
+
Object.keys(value).forEach((keyOfValue) => {
|
|
1586
|
+
if (this._jsonModel[key][keyOfValue] === undefined) {
|
|
1587
|
+
this._jsonModel[key][keyOfValue] = value[keyOfValue];
|
|
1588
|
+
}
|
|
1589
|
+
});
|
|
1590
|
+
}
|
|
1591
|
+
});
|
|
1592
|
+
}
|
|
1593
|
+
}
|
|
1594
|
+
__decorate([
|
|
1595
|
+
dependencyTracked()
|
|
1596
|
+
], BaseNode.prototype, "index", null);
|
|
1597
|
+
__decorate([
|
|
1598
|
+
dependencyTracked()
|
|
1599
|
+
], BaseNode.prototype, "description", null);
|
|
1600
|
+
__decorate([
|
|
1601
|
+
dependencyTracked()
|
|
1602
|
+
], BaseNode.prototype, "visible", null);
|
|
1603
|
+
__decorate([
|
|
1604
|
+
dependencyTracked()
|
|
1605
|
+
], BaseNode.prototype, "label", null);
|
|
1606
|
+
__decorate([
|
|
1607
|
+
dependencyTracked()
|
|
1608
|
+
], BaseNode.prototype, "properties", null);
|
|
1609
|
+
|
|
1610
|
+
class Scriptable extends BaseNode {
|
|
1611
|
+
_events = {};
|
|
1612
|
+
_rules = {};
|
|
1613
|
+
getRules() {
|
|
1614
|
+
return typeof this._jsonModel.rules !== 'object' ? {} : this._jsonModel.rules;
|
|
1615
|
+
}
|
|
1616
|
+
getCompiledRule(eName, rule) {
|
|
1617
|
+
if (!(eName in this._rules)) {
|
|
1618
|
+
const eString = rule || this.getRules()[eName];
|
|
1619
|
+
if (typeof eString === 'string' && eString.length > 0) {
|
|
1620
|
+
try {
|
|
1621
|
+
this._rules[eName] = this.ruleEngine.compileRule(eString, this.lang);
|
|
1622
|
+
}
|
|
1623
|
+
catch (e) {
|
|
1624
|
+
this.form.logger.error(`Unable to compile rule \`"${eName}" : "${eString}"\` Exception : ${e}`);
|
|
1622
1625
|
}
|
|
1623
1626
|
}
|
|
1627
|
+
else {
|
|
1628
|
+
throw new Error(`only expression strings are supported. ${typeof (eString)} types are not supported`);
|
|
1629
|
+
}
|
|
1624
1630
|
}
|
|
1625
|
-
this.
|
|
1626
|
-
x.importData(contextualDataModel);
|
|
1627
|
-
});
|
|
1628
|
-
}
|
|
1629
|
-
get activeChild() {
|
|
1630
|
-
return this._activeChild;
|
|
1631
|
+
return this._rules[eName];
|
|
1631
1632
|
}
|
|
1632
|
-
|
|
1633
|
-
if (
|
|
1634
|
-
let
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
activeChild.activeChild = null;
|
|
1638
|
-
activeChild = temp;
|
|
1633
|
+
getCompiledEvent(eName) {
|
|
1634
|
+
if (!(eName in this._events)) {
|
|
1635
|
+
let eString = this._jsonModel.events?.[eName];
|
|
1636
|
+
if (typeof eString === 'string' && eString.length > 0) {
|
|
1637
|
+
eString = [eString];
|
|
1639
1638
|
}
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1639
|
+
if (typeof eString !== 'undefined' && eString.length > 0) {
|
|
1640
|
+
this._events[eName] = eString.map(x => {
|
|
1641
|
+
try {
|
|
1642
|
+
return this.ruleEngine.compileRule(x, this.lang);
|
|
1643
|
+
}
|
|
1644
|
+
catch (e) {
|
|
1645
|
+
this.form.logger.error(`Unable to compile expression \`"${eName}" : "${eString}"\` Exception : ${e}`);
|
|
1646
|
+
}
|
|
1647
|
+
return null;
|
|
1648
|
+
}).filter(x => x !== null);
|
|
1644
1649
|
}
|
|
1645
|
-
this._jsonModel.activeChild = c?.id;
|
|
1646
|
-
this.notifyDependents(change);
|
|
1647
|
-
}
|
|
1648
|
-
}
|
|
1649
|
-
get enabled() {
|
|
1650
|
-
if (this.parent?.enabled !== undefined) {
|
|
1651
|
-
return !this.parent?.enabled ? false : this._jsonModel.enabled;
|
|
1652
|
-
}
|
|
1653
|
-
else {
|
|
1654
|
-
return this._jsonModel.enabled;
|
|
1655
|
-
}
|
|
1656
|
-
}
|
|
1657
|
-
set enabled(e) {
|
|
1658
|
-
this._setProperty('enabled', e, true, this.notifyChildren);
|
|
1659
|
-
}
|
|
1660
|
-
get readOnly() {
|
|
1661
|
-
if (this.parent?.readOnly !== undefined) {
|
|
1662
|
-
return this.parent.readOnly ? true : this._jsonModel.readOnly;
|
|
1663
|
-
}
|
|
1664
|
-
else {
|
|
1665
|
-
return this._jsonModel.readOnly;
|
|
1666
1650
|
}
|
|
1651
|
+
return this._events[eName] || [];
|
|
1667
1652
|
}
|
|
1668
|
-
|
|
1669
|
-
|
|
1653
|
+
applyUpdates(updates) {
|
|
1654
|
+
Object.entries(updates).forEach(([key, value]) => {
|
|
1655
|
+
if (key in editableProperties || (key in this && typeof this[key] !== 'function')) {
|
|
1656
|
+
try {
|
|
1657
|
+
this[key] = value;
|
|
1658
|
+
}
|
|
1659
|
+
catch (e) {
|
|
1660
|
+
console.error(e);
|
|
1661
|
+
}
|
|
1662
|
+
}
|
|
1663
|
+
});
|
|
1670
1664
|
}
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1665
|
+
executeAllRules(context) {
|
|
1666
|
+
const entries = Object.entries(this.getRules());
|
|
1667
|
+
if (entries.length > 0) {
|
|
1668
|
+
const scope = this.getExpressionScope();
|
|
1669
|
+
entries.forEach(([prop, rule]) => {
|
|
1670
|
+
const node = this.getCompiledRule(prop, rule);
|
|
1671
|
+
if (node) {
|
|
1672
|
+
const newVal = this.ruleEngine.execute(node, scope, context, true);
|
|
1673
|
+
if (editableProperties.indexOf(prop) > -1) {
|
|
1674
|
+
const oldAndNewValueAreEmpty = this.isEmpty() && this.isEmpty(newVal) && prop === 'value';
|
|
1675
|
+
if (!oldAndNewValueAreEmpty) {
|
|
1676
|
+
this[prop] = newVal;
|
|
1679
1677
|
}
|
|
1680
|
-
}
|
|
1678
|
+
}
|
|
1679
|
+
else {
|
|
1680
|
+
this.form.logger.warn(`${prop} is not a valid editable property.`);
|
|
1681
|
+
}
|
|
1681
1682
|
}
|
|
1682
|
-
}
|
|
1683
|
+
});
|
|
1683
1684
|
}
|
|
1684
1685
|
}
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
dependencyTracked()
|
|
1691
|
-
], Container.prototype, "minItems", null);
|
|
1692
|
-
__decorate([
|
|
1693
|
-
dependencyTracked()
|
|
1694
|
-
], Container.prototype, "activeChild", null);
|
|
1695
|
-
|
|
1696
|
-
class Node {
|
|
1697
|
-
_jsonModel;
|
|
1698
|
-
constructor(inputModel) {
|
|
1699
|
-
this._jsonModel = {
|
|
1700
|
-
...inputModel
|
|
1686
|
+
getExpressionScope() {
|
|
1687
|
+
const parent = this.getNonTransparentParent();
|
|
1688
|
+
const target = {
|
|
1689
|
+
self: this.getRuleNode(),
|
|
1690
|
+
siblings: parent?.ruleNodeReference() || {}
|
|
1701
1691
|
};
|
|
1692
|
+
const scope = new Proxy(target, {
|
|
1693
|
+
get: (target, prop) => {
|
|
1694
|
+
if (prop === Symbol.toStringTag) {
|
|
1695
|
+
return 'Object';
|
|
1696
|
+
}
|
|
1697
|
+
if (typeof prop === 'string' && prop.startsWith('$')) {
|
|
1698
|
+
const retValue = target.self[prop];
|
|
1699
|
+
if (retValue instanceof BaseNode) {
|
|
1700
|
+
return retValue.getRuleNode();
|
|
1701
|
+
}
|
|
1702
|
+
else if (retValue instanceof Array) {
|
|
1703
|
+
return retValue.map(r => r instanceof BaseNode ? r.getRuleNode() : r);
|
|
1704
|
+
}
|
|
1705
|
+
else {
|
|
1706
|
+
return retValue;
|
|
1707
|
+
}
|
|
1708
|
+
}
|
|
1709
|
+
else {
|
|
1710
|
+
if (prop in target.siblings) {
|
|
1711
|
+
return target.siblings[prop];
|
|
1712
|
+
}
|
|
1713
|
+
else {
|
|
1714
|
+
return target.self[prop];
|
|
1715
|
+
}
|
|
1716
|
+
}
|
|
1717
|
+
},
|
|
1718
|
+
has: (target, prop) => {
|
|
1719
|
+
prop = prop;
|
|
1720
|
+
const selfPropertyOrChild = target.self[prop];
|
|
1721
|
+
const sibling = target.siblings[prop];
|
|
1722
|
+
return typeof selfPropertyOrChild != 'undefined' || typeof sibling != 'undefined';
|
|
1723
|
+
}
|
|
1724
|
+
});
|
|
1725
|
+
return scope;
|
|
1702
1726
|
}
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1727
|
+
executeEvent(context, node) {
|
|
1728
|
+
let updates;
|
|
1729
|
+
if (node) {
|
|
1730
|
+
updates = this.ruleEngine.execute(node, this.getExpressionScope(), context);
|
|
1731
|
+
}
|
|
1732
|
+
if (typeof updates !== 'undefined' && updates != null) {
|
|
1733
|
+
this.applyUpdates(updates);
|
|
1734
|
+
}
|
|
1708
1735
|
}
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
return this.getP('version', '');
|
|
1736
|
+
executeRule(event, context) {
|
|
1737
|
+
if (typeof event.payload.ruleName === 'undefined') {
|
|
1738
|
+
this.executeAllRules(context);
|
|
1739
|
+
}
|
|
1714
1740
|
}
|
|
1715
|
-
|
|
1716
|
-
|
|
1741
|
+
executeExpression(expr) {
|
|
1742
|
+
const ruleContext = {
|
|
1743
|
+
'form': this.form,
|
|
1744
|
+
'$form': this.form.getRuleNode(),
|
|
1745
|
+
'$field': this.getRuleNode(),
|
|
1746
|
+
'field': this
|
|
1747
|
+
};
|
|
1748
|
+
const node = this.ruleEngine.compileRule(expr, this.lang);
|
|
1749
|
+
return this.ruleEngine.execute(node, this.getExpressionScope(), ruleContext);
|
|
1717
1750
|
}
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1751
|
+
executeAction(action) {
|
|
1752
|
+
const context = {
|
|
1753
|
+
'form': this.form,
|
|
1754
|
+
'$form': this.form.getRuleNode(),
|
|
1755
|
+
'$field': this.getRuleNode(),
|
|
1756
|
+
'field': this,
|
|
1757
|
+
'$event': {
|
|
1758
|
+
type: action.type,
|
|
1759
|
+
payload: action.payload,
|
|
1760
|
+
target: this.getRuleNode()
|
|
1761
|
+
}
|
|
1762
|
+
};
|
|
1763
|
+
const eventName = action.isCustomEvent ? `custom:${action.type}` : action.type;
|
|
1764
|
+
const funcName = action.isCustomEvent ? `custom_${action.type}` : action.type;
|
|
1765
|
+
const node = this.getCompiledEvent(eventName);
|
|
1766
|
+
if (funcName in this && typeof this[funcName] === 'function') {
|
|
1767
|
+
this[funcName](action, context);
|
|
1768
|
+
}
|
|
1769
|
+
node.forEach((n) => this.executeEvent(context, n));
|
|
1770
|
+
this.notifyDependents(action);
|
|
1726
1771
|
}
|
|
1727
1772
|
}
|
|
1728
1773
|
|
|
1729
|
-
const
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
info(msg) {
|
|
1741
|
-
this.log(msg, 'info');
|
|
1742
|
-
}
|
|
1743
|
-
warn(msg) {
|
|
1744
|
-
this.log(msg, 'warn');
|
|
1745
|
-
}
|
|
1746
|
-
error(msg) {
|
|
1747
|
-
this.log(msg, 'error');
|
|
1774
|
+
const notifyChildrenAttributes = [
|
|
1775
|
+
'readOnly', 'enabled'
|
|
1776
|
+
];
|
|
1777
|
+
class Container extends Scriptable {
|
|
1778
|
+
_children = [];
|
|
1779
|
+
_childrenReference;
|
|
1780
|
+
_itemTemplate = null;
|
|
1781
|
+
fieldFactory;
|
|
1782
|
+
constructor(json, _options) {
|
|
1783
|
+
super(json, { form: _options.form, parent: _options.parent, mode: _options.mode });
|
|
1784
|
+
this.fieldFactory = _options.fieldFactory;
|
|
1748
1785
|
}
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1786
|
+
_getDefaults() {
|
|
1787
|
+
return {
|
|
1788
|
+
...super._getDefaults(),
|
|
1789
|
+
enabled: true,
|
|
1790
|
+
readOnly: false
|
|
1791
|
+
};
|
|
1753
1792
|
}
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
this.logLevel = levels[logLevel];
|
|
1793
|
+
ruleNodeReference() {
|
|
1794
|
+
return this._childrenReference;
|
|
1757
1795
|
}
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
class EventNode {
|
|
1761
|
-
_node;
|
|
1762
|
-
_event;
|
|
1763
|
-
constructor(_node, _event) {
|
|
1764
|
-
this._node = _node;
|
|
1765
|
-
this._event = _event;
|
|
1796
|
+
get items() {
|
|
1797
|
+
return this._children;
|
|
1766
1798
|
}
|
|
1767
|
-
get
|
|
1768
|
-
return this.
|
|
1799
|
+
get maxItems() {
|
|
1800
|
+
return this._jsonModel.maxItems;
|
|
1769
1801
|
}
|
|
1770
|
-
|
|
1771
|
-
|
|
1802
|
+
set maxItems(m) {
|
|
1803
|
+
this._jsonModel.maxItems = m;
|
|
1804
|
+
const minItems = this._jsonModel.minItems || 1;
|
|
1805
|
+
const itemsLength = this._children.length;
|
|
1806
|
+
const items2Remove = Math.min(itemsLength - m, itemsLength - minItems);
|
|
1807
|
+
if (items2Remove > 0) {
|
|
1808
|
+
for (let i = 0; i < items2Remove; i++) {
|
|
1809
|
+
this.getDataNode().$removeDataNode(m + i);
|
|
1810
|
+
this._childrenReference.pop();
|
|
1811
|
+
}
|
|
1812
|
+
const elems = this._children.splice(m, items2Remove);
|
|
1813
|
+
this.notifyDependents(propertyChange('items', elems, null));
|
|
1814
|
+
}
|
|
1772
1815
|
}
|
|
1773
|
-
|
|
1774
|
-
return
|
|
1816
|
+
get minItems() {
|
|
1817
|
+
return this._jsonModel.minItems;
|
|
1775
1818
|
}
|
|
1776
|
-
|
|
1777
|
-
|
|
1819
|
+
set minItems(m) {
|
|
1820
|
+
this._jsonModel.minItems = m;
|
|
1821
|
+
const itemsLength = this._children.length;
|
|
1822
|
+
const difference = itemsLength - m;
|
|
1823
|
+
const items2Add = Math.abs(difference);
|
|
1824
|
+
if (difference < 0) {
|
|
1825
|
+
const elems = [];
|
|
1826
|
+
for (let i = 0; i < items2Add; i++) {
|
|
1827
|
+
elems.push(this._addChild(this._itemTemplate, null, true));
|
|
1828
|
+
}
|
|
1829
|
+
this.notifyDependents(propertyChange('items', elems, null));
|
|
1830
|
+
}
|
|
1778
1831
|
}
|
|
1779
|
-
|
|
1780
|
-
return this.
|
|
1832
|
+
hasDynamicItems() {
|
|
1833
|
+
return this._itemTemplate != null;
|
|
1781
1834
|
}
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
logger;
|
|
1785
|
-
static MAX_EVENT_CYCLE_COUNT = 10;
|
|
1786
|
-
_runningEventCount;
|
|
1787
|
-
_isProcessing = false;
|
|
1788
|
-
_pendingEvents = [];
|
|
1789
|
-
constructor(logger = new Logger('off')) {
|
|
1790
|
-
this.logger = logger;
|
|
1791
|
-
this._runningEventCount = {};
|
|
1835
|
+
get isContainer() {
|
|
1836
|
+
return true;
|
|
1792
1837
|
}
|
|
1793
|
-
|
|
1794
|
-
|
|
1838
|
+
_activeChild = null;
|
|
1839
|
+
isSiteContainer(item) {
|
|
1840
|
+
return (':items' in item || 'cqItems' in item) && !('fieldType' in item);
|
|
1795
1841
|
}
|
|
1796
|
-
|
|
1797
|
-
return
|
|
1842
|
+
isAFormField(item) {
|
|
1843
|
+
return ('fieldType' in item || 'id' in item || 'name' in item || 'dataRef' in item || 'type' in item);
|
|
1798
1844
|
}
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1845
|
+
_getFormAndSitesState(isRepeatableChild = false, forRestore = false) {
|
|
1846
|
+
return this._jsonModel.items ? this._jsonModel.items.map((x) => {
|
|
1847
|
+
if (this.isSiteContainer(x)) {
|
|
1848
|
+
const newObjWithId = {
|
|
1849
|
+
...(x?.id ? { id: this.form.getUniqueId() } : {})
|
|
1850
|
+
};
|
|
1851
|
+
return {
|
|
1852
|
+
...x,
|
|
1853
|
+
...newObjWithId,
|
|
1854
|
+
':items': this.walkSiteContainerItems(x)
|
|
1855
|
+
};
|
|
1856
|
+
}
|
|
1857
|
+
else if (this.isAFormField(x)) {
|
|
1858
|
+
return { ...this.form.getElement(x?.id).getState(isRepeatableChild, forRestore) };
|
|
1859
|
+
}
|
|
1860
|
+
else {
|
|
1861
|
+
return x;
|
|
1862
|
+
}
|
|
1863
|
+
}) : [];
|
|
1802
1864
|
}
|
|
1803
|
-
|
|
1804
|
-
if (
|
|
1805
|
-
|
|
1865
|
+
getItemsState(isRepeatableChild = false, forRestore = false) {
|
|
1866
|
+
if (this._jsonModel.type === 'array' || isRepeatable$1(this._jsonModel) || isRepeatableChild) {
|
|
1867
|
+
if (isRepeatableChild) {
|
|
1868
|
+
return this._getFormAndSitesState(isRepeatableChild, forRestore);
|
|
1869
|
+
}
|
|
1870
|
+
else {
|
|
1871
|
+
return this._children.map(x => {
|
|
1872
|
+
return { ...x.getState(true, forRestore) };
|
|
1873
|
+
});
|
|
1874
|
+
}
|
|
1806
1875
|
}
|
|
1807
|
-
|
|
1808
|
-
|
|
1876
|
+
else {
|
|
1877
|
+
return this._getFormAndSitesState(isRepeatableChild, forRestore);
|
|
1809
1878
|
}
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1879
|
+
}
|
|
1880
|
+
getState(isRepeatableChild = false, forRestore = false) {
|
|
1881
|
+
return {
|
|
1882
|
+
...super.getState(forRestore),
|
|
1883
|
+
...(forRestore ? {
|
|
1884
|
+
':items': undefined,
|
|
1885
|
+
':itemsOrder': undefined
|
|
1886
|
+
} : {}),
|
|
1887
|
+
items: this.getItemsState(isRepeatableChild, forRestore),
|
|
1888
|
+
enabled: this.enabled,
|
|
1889
|
+
readOnly: this.readOnly
|
|
1890
|
+
};
|
|
1891
|
+
}
|
|
1892
|
+
_createChild(child, options) {
|
|
1893
|
+
return this.fieldFactory.createField(child, options);
|
|
1894
|
+
}
|
|
1895
|
+
walkSiteContainerItems(x) {
|
|
1896
|
+
return Object.fromEntries(Object.entries(x[':items']).map(([key, value]) => {
|
|
1897
|
+
if (this.isAFormField(value)) {
|
|
1898
|
+
return [key, this.form.getElement(value?.id).getState()];
|
|
1899
|
+
}
|
|
1900
|
+
else if (this.isSiteContainer(value)) {
|
|
1901
|
+
return this.walkSiteContainerItems(value);
|
|
1902
|
+
}
|
|
1903
|
+
else {
|
|
1904
|
+
if (typeof value === 'object') {
|
|
1905
|
+
const newObjWithId = {
|
|
1906
|
+
...(value?.id ? { id: this.form.getUniqueId() } : {})
|
|
1907
|
+
};
|
|
1908
|
+
return [key, {
|
|
1909
|
+
...value,
|
|
1910
|
+
...newObjWithId
|
|
1911
|
+
}
|
|
1912
|
+
];
|
|
1818
1913
|
}
|
|
1819
1914
|
else {
|
|
1820
|
-
|
|
1915
|
+
return [key, value];
|
|
1821
1916
|
}
|
|
1822
|
-
this._runningEventCount[evntNode.valueOf()] = counter + 1;
|
|
1823
1917
|
}
|
|
1824
|
-
|
|
1825
|
-
this.logger.info(`Skipped queueing event : ${e.type} node: ${node.id} - ${node.name} with count=${counter}`);
|
|
1826
|
-
}
|
|
1827
|
-
});
|
|
1918
|
+
}));
|
|
1828
1919
|
}
|
|
1829
|
-
|
|
1830
|
-
|
|
1920
|
+
_addChildToRuleNode(child, options) {
|
|
1921
|
+
const self = this;
|
|
1922
|
+
const { parent = this } = options;
|
|
1923
|
+
const name = parent.type == 'array' ? parent._children.length + '' : child.name || '';
|
|
1924
|
+
if (name.length > 0) {
|
|
1925
|
+
Object.defineProperty(parent._childrenReference, name, {
|
|
1926
|
+
get: () => {
|
|
1927
|
+
if (child.isContainer && child.hasDynamicItems()) {
|
|
1928
|
+
self.ruleEngine.trackDependency(child);
|
|
1929
|
+
}
|
|
1930
|
+
if (self.hasDynamicItems()) {
|
|
1931
|
+
self.ruleEngine.trackDependency(self);
|
|
1932
|
+
if (this._children[name] !== undefined) {
|
|
1933
|
+
return this._children[name].getRuleNode();
|
|
1934
|
+
}
|
|
1935
|
+
}
|
|
1936
|
+
else {
|
|
1937
|
+
return child.getRuleNode();
|
|
1938
|
+
}
|
|
1939
|
+
},
|
|
1940
|
+
configurable: true,
|
|
1941
|
+
enumerable: true
|
|
1942
|
+
});
|
|
1943
|
+
}
|
|
1831
1944
|
}
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1945
|
+
_addChild(itemJson, index, cloneIds = false, mode = 'create') {
|
|
1946
|
+
let nonTransparentParent = this;
|
|
1947
|
+
while (nonTransparentParent != null && nonTransparentParent.isTransparent()) {
|
|
1948
|
+
nonTransparentParent = nonTransparentParent.parent;
|
|
1835
1949
|
}
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
const e = this._pendingEvents[0];
|
|
1839
|
-
this.logger.info(`Dequeued event : ${e.event.type} node: ${e.node.id} - ${e.node.name}`);
|
|
1840
|
-
e.node.executeAction(e.event);
|
|
1841
|
-
this._pendingEvents.shift();
|
|
1950
|
+
if (typeof index !== 'number' || index > nonTransparentParent._children.length) {
|
|
1951
|
+
index = this._children.length;
|
|
1842
1952
|
}
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
}
|
|
1847
|
-
|
|
1848
|
-
class FileObject {
|
|
1849
|
-
data;
|
|
1850
|
-
mediaType = 'application/octet-stream';
|
|
1851
|
-
name = 'unknown';
|
|
1852
|
-
size = 0;
|
|
1853
|
-
constructor(init) {
|
|
1854
|
-
Object.assign(this, init);
|
|
1855
|
-
}
|
|
1856
|
-
get type() {
|
|
1857
|
-
return this.mediaType;
|
|
1858
|
-
}
|
|
1859
|
-
toJSON() {
|
|
1860
|
-
return {
|
|
1861
|
-
'name': this.name,
|
|
1862
|
-
'size': this.size,
|
|
1863
|
-
'mediaType': this.mediaType,
|
|
1864
|
-
'data': this.data.toString()
|
|
1953
|
+
const form = this.form;
|
|
1954
|
+
const itemTemplate = {
|
|
1955
|
+
index,
|
|
1956
|
+
...deepClone(itemJson, cloneIds ? () => { return form.getUniqueId(); } : undefined)
|
|
1865
1957
|
};
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
this.
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1958
|
+
const retVal = this._createChild(itemTemplate, { parent: this, form: this.form, mode });
|
|
1959
|
+
itemJson.id = retVal.id;
|
|
1960
|
+
this.form.fieldAdded(retVal);
|
|
1961
|
+
this._addChildToRuleNode(retVal, { parent: nonTransparentParent });
|
|
1962
|
+
if (index === this._children.length) {
|
|
1963
|
+
this._children.push(retVal);
|
|
1964
|
+
}
|
|
1965
|
+
else {
|
|
1966
|
+
this._children.splice(index, 0, retVal);
|
|
1967
|
+
}
|
|
1968
|
+
return retVal;
|
|
1969
|
+
}
|
|
1970
|
+
indexOf(f) {
|
|
1971
|
+
return this._children.indexOf(f);
|
|
1972
|
+
}
|
|
1973
|
+
defaultDataModel(name) {
|
|
1974
|
+
const type = this._jsonModel.type || undefined;
|
|
1975
|
+
if (type === undefined) {
|
|
1976
|
+
return undefined;
|
|
1883
1977
|
}
|
|
1884
1978
|
else {
|
|
1885
|
-
|
|
1979
|
+
const instance = type === 'array' ? [] : {};
|
|
1980
|
+
return new DataGroup(name, instance, type);
|
|
1886
1981
|
}
|
|
1887
|
-
ret.push(chars[randIndex]);
|
|
1888
1982
|
}
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1983
|
+
_canHaveRepeatingChildren(mode = 'create') {
|
|
1984
|
+
const items = this._jsonModel.items;
|
|
1985
|
+
return this._jsonModel.type == 'array' && this.getDataNode() != null &&
|
|
1986
|
+
(items.length === 1 || (items[0].repeatable == true && mode === 'restore'));
|
|
1987
|
+
}
|
|
1988
|
+
_initialize(mode) {
|
|
1989
|
+
super._initialize(mode);
|
|
1990
|
+
const items = this._jsonModel.items || [];
|
|
1991
|
+
this._childrenReference = this._jsonModel.type == 'array' ? [] : {};
|
|
1992
|
+
if (this._canHaveRepeatingChildren(mode)) {
|
|
1993
|
+
this._itemTemplate = deepClone(items[0]);
|
|
1994
|
+
if (mode === 'restore') {
|
|
1995
|
+
this._itemTemplate.repeatable = undefined;
|
|
1996
|
+
}
|
|
1997
|
+
if (typeof (this._jsonModel.minItems) !== 'number') {
|
|
1998
|
+
this._jsonModel.minItems = 0;
|
|
1999
|
+
}
|
|
2000
|
+
if (typeof (this._jsonModel.maxItems) !== 'number') {
|
|
2001
|
+
this._jsonModel.maxItems = -1;
|
|
2002
|
+
}
|
|
2003
|
+
if (typeof (this._jsonModel.initialItems) !== 'number') {
|
|
2004
|
+
this._jsonModel.initialItems = Math.max(1, this._jsonModel.minItems);
|
|
2005
|
+
}
|
|
2006
|
+
for (let i = 0; i < this._jsonModel.initialItems; i++) {
|
|
2007
|
+
let child;
|
|
2008
|
+
if (mode === 'restore') {
|
|
2009
|
+
let itemTemplate = this._itemTemplate;
|
|
2010
|
+
if (i < this._jsonModel.items.length) {
|
|
2011
|
+
itemTemplate = deepClone(items[i]);
|
|
2012
|
+
itemTemplate.repeatable = undefined;
|
|
2013
|
+
}
|
|
2014
|
+
child = this._addChild(itemTemplate, undefined, i > this._jsonModel.items.length - 1, mode);
|
|
2015
|
+
}
|
|
2016
|
+
else {
|
|
2017
|
+
child = this._addChild(this._itemTemplate, undefined, i > this._jsonModel.items.length - 1);
|
|
2018
|
+
}
|
|
2019
|
+
if (mode === 'create') {
|
|
2020
|
+
items[0].id = child.id;
|
|
2021
|
+
}
|
|
2022
|
+
child._initialize(mode);
|
|
2023
|
+
}
|
|
1896
2024
|
}
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
2025
|
+
else if (items.length > 0) {
|
|
2026
|
+
items.forEach((item) => {
|
|
2027
|
+
if (this.isSiteContainer(item)) {
|
|
2028
|
+
this._initializeSiteContainer(item);
|
|
2029
|
+
}
|
|
2030
|
+
else if (this.isAFormField(item)) {
|
|
2031
|
+
const child = this._addChild(item, undefined, false, mode);
|
|
2032
|
+
child._initialize(mode);
|
|
2033
|
+
}
|
|
2034
|
+
else {
|
|
2035
|
+
this.form.logger.warn(`A container item was not initialized. ${item}`);
|
|
2036
|
+
}
|
|
2037
|
+
});
|
|
2038
|
+
this._jsonModel.minItems = this._children.length;
|
|
2039
|
+
this._jsonModel.maxItems = this._children.length;
|
|
2040
|
+
this._jsonModel.initialItems = this._children.length;
|
|
1900
2041
|
}
|
|
1901
2042
|
else {
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
2043
|
+
this.form.logger.warn('A container exists with no items.');
|
|
2044
|
+
}
|
|
2045
|
+
this.setupRuleNode();
|
|
2046
|
+
}
|
|
2047
|
+
_initializeSiteContainer(item) {
|
|
2048
|
+
Object.entries(item[':items']).forEach(([key, value]) => {
|
|
2049
|
+
if (this.isAFormField(value)) {
|
|
2050
|
+
const child = this._addChild(value);
|
|
2051
|
+
child._initialize();
|
|
2052
|
+
}
|
|
2053
|
+
else if (this.isSiteContainer(value)) {
|
|
2054
|
+
return this._initializeSiteContainer(value);
|
|
2055
|
+
}
|
|
2056
|
+
});
|
|
2057
|
+
}
|
|
2058
|
+
addItem(action) {
|
|
2059
|
+
if ((action.type === 'addItem' || action.type == 'addInstance') && this._itemTemplate != null) {
|
|
2060
|
+
if ((this._jsonModel.maxItems === -1) || (this._children.length < this._jsonModel.maxItems)) {
|
|
2061
|
+
const dataNode = this.getDataNode();
|
|
2062
|
+
let instanceIndex = action.payload;
|
|
2063
|
+
const retVal = this._addChild(this._itemTemplate, action.payload, true);
|
|
2064
|
+
if (typeof instanceIndex !== 'number' || instanceIndex > this._children.length) {
|
|
2065
|
+
instanceIndex = this._children.length;
|
|
1912
2066
|
}
|
|
1913
|
-
|
|
1914
|
-
|
|
2067
|
+
const _data = retVal.defaultDataModel(instanceIndex);
|
|
2068
|
+
if (_data) {
|
|
2069
|
+
dataNode.$addDataNode(instanceIndex, _data);
|
|
2070
|
+
}
|
|
2071
|
+
retVal._initialize('create');
|
|
2072
|
+
this.notifyDependents(propertyChange('items', retVal.getState(), null));
|
|
2073
|
+
retVal.dispatch(new Initialize());
|
|
2074
|
+
retVal.dispatch(new ExecuteRule());
|
|
2075
|
+
for (let i = instanceIndex + 1; i < this._children.length; i++) {
|
|
2076
|
+
this._children[i].dispatch(new ExecuteRule());
|
|
1915
2077
|
}
|
|
1916
2078
|
}
|
|
1917
2079
|
}
|
|
1918
|
-
return Object.assign(acc, ret);
|
|
1919
|
-
}, {});
|
|
1920
|
-
};
|
|
1921
|
-
const getFileSizeInBytes = (str) => {
|
|
1922
|
-
let retVal = 0;
|
|
1923
|
-
if (typeof str === 'string') {
|
|
1924
|
-
const matches = fileSizeRegex.exec(str.trim());
|
|
1925
|
-
if (matches != null) {
|
|
1926
|
-
retVal = sizeToBytes(parseFloat(matches[1]), (matches[2] || 'kb').toUpperCase());
|
|
1927
|
-
}
|
|
1928
2080
|
}
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
const i = Math.pow(1024, sizes[symbol]);
|
|
1934
|
-
return Math.round(size * i);
|
|
1935
|
-
};
|
|
1936
|
-
const IdGenerator = function* (initial = 50) {
|
|
1937
|
-
const initialize = function () {
|
|
1938
|
-
const arr = [];
|
|
1939
|
-
for (let i = 0; i < initial; i++) {
|
|
1940
|
-
arr.push(randomWord(10));
|
|
1941
|
-
}
|
|
1942
|
-
return arr;
|
|
1943
|
-
};
|
|
1944
|
-
const passedIds = {};
|
|
1945
|
-
let ids = initialize();
|
|
1946
|
-
do {
|
|
1947
|
-
let x = ids.pop();
|
|
1948
|
-
while (x in passedIds) {
|
|
1949
|
-
if (ids.length === 0) {
|
|
1950
|
-
ids = initialize();
|
|
2081
|
+
removeItem(action) {
|
|
2082
|
+
if ((action.type === 'removeItem' || action.type == 'removeInstance') && this._itemTemplate != null) {
|
|
2083
|
+
if (this._children.length == 0) {
|
|
2084
|
+
return;
|
|
1951
2085
|
}
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
const extractFileInfo = (file) => {
|
|
1966
|
-
if (file !== null) {
|
|
1967
|
-
let retVal = null;
|
|
1968
|
-
if (file instanceof FileObject) {
|
|
1969
|
-
retVal = file;
|
|
1970
|
-
}
|
|
1971
|
-
else if (typeof File !== 'undefined' && file instanceof File) {
|
|
1972
|
-
retVal = {
|
|
1973
|
-
name: file.name,
|
|
1974
|
-
mediaType: file.type,
|
|
1975
|
-
size: file.size,
|
|
1976
|
-
data: file
|
|
1977
|
-
};
|
|
1978
|
-
}
|
|
1979
|
-
else if (typeof file === 'string' && isDataUrl(file)) {
|
|
1980
|
-
const result = dataURItoBlob(file);
|
|
1981
|
-
if (result !== null) {
|
|
1982
|
-
const { blob, name } = result;
|
|
1983
|
-
retVal = {
|
|
1984
|
-
name: name,
|
|
1985
|
-
mediaType: blob.type,
|
|
1986
|
-
size: blob.size,
|
|
1987
|
-
data: blob
|
|
1988
|
-
};
|
|
2086
|
+
let instanceIndex = action.payload;
|
|
2087
|
+
if (typeof instanceIndex !== 'number') {
|
|
2088
|
+
instanceIndex = this._children.length - 1;
|
|
2089
|
+
}
|
|
2090
|
+
const state = this._children[instanceIndex].getState();
|
|
2091
|
+
if (this._children.length > this._jsonModel.minItems) {
|
|
2092
|
+
this._childrenReference.pop();
|
|
2093
|
+
this._children.splice(instanceIndex, 1);
|
|
2094
|
+
this.getDataNode().$removeDataNode(instanceIndex);
|
|
2095
|
+
for (let i = instanceIndex; i < this._children.length; i++) {
|
|
2096
|
+
this._children[i].dispatch(new ExecuteRule());
|
|
2097
|
+
}
|
|
2098
|
+
this.notifyDependents(propertyChange('items', null, state));
|
|
1989
2099
|
}
|
|
1990
2100
|
}
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
2101
|
+
}
|
|
2102
|
+
queueEvent(action) {
|
|
2103
|
+
super.queueEvent(action);
|
|
2104
|
+
if (action.metadata?.dispatch) {
|
|
2105
|
+
this.items.forEach(x => {
|
|
2106
|
+
x.queueEvent(action);
|
|
2107
|
+
});
|
|
2108
|
+
}
|
|
2109
|
+
}
|
|
2110
|
+
reset() {
|
|
2111
|
+
if (this.type === 'array' || isRepeatable$1(this._jsonModel)) {
|
|
2112
|
+
if (this.items.length > this._jsonModel.initialItems) {
|
|
2113
|
+
const itemsToBeRemoved = this.items.length - this._jsonModel.initialItems;
|
|
2114
|
+
for (let i = 0; i < itemsToBeRemoved; i++) {
|
|
2115
|
+
this.dispatch(new RemoveItem());
|
|
1998
2116
|
}
|
|
1999
2117
|
}
|
|
2000
|
-
|
|
2118
|
+
}
|
|
2119
|
+
this.items.forEach(x => {
|
|
2120
|
+
x.reset();
|
|
2121
|
+
});
|
|
2122
|
+
}
|
|
2123
|
+
validate() {
|
|
2124
|
+
return this.items.flatMap(x => {
|
|
2125
|
+
return x.validate();
|
|
2126
|
+
}).filter(x => x.fieldName !== '');
|
|
2127
|
+
}
|
|
2128
|
+
dispatch(action) {
|
|
2129
|
+
super.dispatch(action);
|
|
2130
|
+
}
|
|
2131
|
+
importData(contextualDataModel) {
|
|
2132
|
+
this._bindToDataModel(contextualDataModel);
|
|
2133
|
+
const dataNode = this.getDataNode() || contextualDataModel;
|
|
2134
|
+
this.syncDataAndFormModel(dataNode);
|
|
2135
|
+
}
|
|
2136
|
+
syncDataAndFormModel(contextualDataModel) {
|
|
2137
|
+
if (contextualDataModel?.$type === 'array' && this._itemTemplate != null) {
|
|
2138
|
+
const dataLength = contextualDataModel?.$value.length;
|
|
2139
|
+
const itemsLength = this._children.length;
|
|
2140
|
+
const maxItems = this._jsonModel.maxItems === -1 ? dataLength : this._jsonModel.maxItems;
|
|
2141
|
+
const minItems = this._jsonModel.minItems;
|
|
2142
|
+
let items2Add = Math.min(dataLength - itemsLength, maxItems - itemsLength);
|
|
2143
|
+
const items2Remove = Math.min(itemsLength - dataLength, itemsLength - minItems);
|
|
2144
|
+
while (items2Add > 0) {
|
|
2145
|
+
items2Add--;
|
|
2146
|
+
const child = this._addChild(this._itemTemplate);
|
|
2147
|
+
child._initialize('create');
|
|
2001
2148
|
}
|
|
2002
|
-
if (
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
retVal = {
|
|
2007
|
-
name: jFile?.name,
|
|
2008
|
-
mediaType: jFile?.type || jFile?.mediaType,
|
|
2009
|
-
size: blob.size,
|
|
2010
|
-
data: blob
|
|
2011
|
-
};
|
|
2149
|
+
if (items2Remove > 0) {
|
|
2150
|
+
this._children.splice(dataLength, items2Remove);
|
|
2151
|
+
for (let i = 0; i < items2Remove; i++) {
|
|
2152
|
+
this._childrenReference.pop();
|
|
2012
2153
|
}
|
|
2013
2154
|
}
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2155
|
+
}
|
|
2156
|
+
this._children.forEach(x => {
|
|
2157
|
+
x.importData(contextualDataModel);
|
|
2158
|
+
});
|
|
2159
|
+
}
|
|
2160
|
+
get activeChild() {
|
|
2161
|
+
return this._activeChild;
|
|
2162
|
+
}
|
|
2163
|
+
set activeChild(c) {
|
|
2164
|
+
if (c !== this._activeChild) {
|
|
2165
|
+
let activeChild = this._activeChild;
|
|
2166
|
+
while (activeChild instanceof Container) {
|
|
2167
|
+
const temp = activeChild.activeChild;
|
|
2168
|
+
activeChild.activeChild = null;
|
|
2169
|
+
activeChild = temp;
|
|
2022
2170
|
}
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
size: jFile?.size,
|
|
2028
|
-
data: jFile?.data
|
|
2029
|
-
};
|
|
2171
|
+
const change = propertyChange('activeChild', c, this._activeChild);
|
|
2172
|
+
this._activeChild = c;
|
|
2173
|
+
if (this.parent && c !== null) {
|
|
2174
|
+
this.parent.activeChild = this;
|
|
2030
2175
|
}
|
|
2176
|
+
this._jsonModel.activeChild = c?.id;
|
|
2177
|
+
this.notifyDependents(change);
|
|
2031
2178
|
}
|
|
2032
|
-
|
|
2033
|
-
|
|
2179
|
+
}
|
|
2180
|
+
get enabled() {
|
|
2181
|
+
if (this.parent?.enabled !== undefined) {
|
|
2182
|
+
return !this.parent?.enabled ? false : this._jsonModel.enabled;
|
|
2183
|
+
}
|
|
2184
|
+
else {
|
|
2185
|
+
return this._jsonModel.enabled;
|
|
2034
2186
|
}
|
|
2035
|
-
return null;
|
|
2036
2187
|
}
|
|
2037
|
-
|
|
2038
|
-
|
|
2188
|
+
set enabled(e) {
|
|
2189
|
+
this._setProperty('enabled', e, true, this.notifyChildren);
|
|
2039
2190
|
}
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
const groups = regex.exec(dataURI);
|
|
2044
|
-
if (groups !== null) {
|
|
2045
|
-
const type = groups[1] || '';
|
|
2046
|
-
const name = groups[2] || 'unknown';
|
|
2047
|
-
const isBase64 = typeof groups[3] === 'string';
|
|
2048
|
-
if (isBase64) {
|
|
2049
|
-
const binary = atob(groups[4]);
|
|
2050
|
-
const array = [];
|
|
2051
|
-
for (let i = 0; i < binary.length; i++) {
|
|
2052
|
-
array.push(binary.charCodeAt(i));
|
|
2053
|
-
}
|
|
2054
|
-
const blob = new window.Blob([new Uint8Array(array)], { type });
|
|
2055
|
-
return { name, blob };
|
|
2191
|
+
get readOnly() {
|
|
2192
|
+
if (this.parent?.readOnly !== undefined) {
|
|
2193
|
+
return this.parent.readOnly ? true : this._jsonModel.readOnly;
|
|
2056
2194
|
}
|
|
2057
2195
|
else {
|
|
2058
|
-
|
|
2059
|
-
return { name, blob };
|
|
2196
|
+
return this._jsonModel.readOnly;
|
|
2060
2197
|
}
|
|
2061
2198
|
}
|
|
2062
|
-
|
|
2063
|
-
|
|
2199
|
+
set readOnly(e) {
|
|
2200
|
+
this._setProperty('readOnly', e, true, this.notifyChildren);
|
|
2064
2201
|
}
|
|
2202
|
+
notifyChildren(action) {
|
|
2203
|
+
if (action.payload !== undefined && action.payload.changes !== undefined) {
|
|
2204
|
+
for (const change of action.payload.changes) {
|
|
2205
|
+
if (change.propertyName !== undefined && notifyChildrenAttributes.includes(change.propertyName)) {
|
|
2206
|
+
this.items.forEach((child) => {
|
|
2207
|
+
this.notifyDependents.call(child, propertyChange(change.propertyName, child.getState()[change.propertyName], null));
|
|
2208
|
+
if (child.fieldType === 'panel') {
|
|
2209
|
+
this.notifyChildren.call(child, action);
|
|
2210
|
+
}
|
|
2211
|
+
});
|
|
2212
|
+
}
|
|
2213
|
+
}
|
|
2214
|
+
}
|
|
2215
|
+
}
|
|
2216
|
+
}
|
|
2217
|
+
__decorate([
|
|
2218
|
+
dependencyTracked()
|
|
2219
|
+
], Container.prototype, "maxItems", null);
|
|
2220
|
+
__decorate([
|
|
2221
|
+
dependencyTracked()
|
|
2222
|
+
], Container.prototype, "minItems", null);
|
|
2223
|
+
__decorate([
|
|
2224
|
+
dependencyTracked()
|
|
2225
|
+
], Container.prototype, "activeChild", null);
|
|
2226
|
+
|
|
2227
|
+
class Node {
|
|
2228
|
+
_jsonModel;
|
|
2229
|
+
constructor(inputModel) {
|
|
2230
|
+
this._jsonModel = {
|
|
2231
|
+
...inputModel
|
|
2232
|
+
};
|
|
2233
|
+
}
|
|
2234
|
+
getP(key, def) {
|
|
2235
|
+
return getProperty(this._jsonModel, key, def);
|
|
2236
|
+
}
|
|
2237
|
+
get isContainer() {
|
|
2238
|
+
return false;
|
|
2239
|
+
}
|
|
2240
|
+
}
|
|
2241
|
+
|
|
2242
|
+
class FormMetaData extends Node {
|
|
2243
|
+
get version() {
|
|
2244
|
+
return this.getP('version', '');
|
|
2245
|
+
}
|
|
2246
|
+
get grammar() {
|
|
2247
|
+
return this.getP('grammar', '');
|
|
2248
|
+
}
|
|
2249
|
+
}
|
|
2250
|
+
|
|
2251
|
+
class SubmitMetaData {
|
|
2252
|
+
lang;
|
|
2253
|
+
captchaInfo;
|
|
2254
|
+
constructor(lang = '', captchaInfo) {
|
|
2255
|
+
this.lang = lang;
|
|
2256
|
+
this.captchaInfo = captchaInfo;
|
|
2257
|
+
}
|
|
2258
|
+
}
|
|
2259
|
+
|
|
2260
|
+
const levels = {
|
|
2261
|
+
off: 0,
|
|
2262
|
+
debug: 1,
|
|
2263
|
+
info: 2,
|
|
2264
|
+
warn: 3,
|
|
2265
|
+
error: 4
|
|
2065
2266
|
};
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
const sitesModelToFormModel = (sitesModel) => {
|
|
2070
|
-
if (!sitesModel || !Object.keys(sitesModel).length) {
|
|
2071
|
-
return sitesModel;
|
|
2267
|
+
class Logger {
|
|
2268
|
+
debug(msg) {
|
|
2269
|
+
this.log(msg, 'debug');
|
|
2072
2270
|
}
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2271
|
+
info(msg) {
|
|
2272
|
+
this.log(msg, 'info');
|
|
2273
|
+
}
|
|
2274
|
+
warn(msg) {
|
|
2275
|
+
this.log(msg, 'warn');
|
|
2276
|
+
}
|
|
2277
|
+
error(msg) {
|
|
2278
|
+
this.log(msg, 'error');
|
|
2279
|
+
}
|
|
2280
|
+
log(msg, level) {
|
|
2281
|
+
if (this.logLevel !== 0 && this.logLevel <= levels[level]) {
|
|
2282
|
+
console[level](msg);
|
|
2283
|
+
}
|
|
2284
|
+
}
|
|
2285
|
+
logLevel;
|
|
2286
|
+
constructor(logLevel = 'off') {
|
|
2287
|
+
this.logLevel = levels[logLevel];
|
|
2288
|
+
}
|
|
2289
|
+
}
|
|
2290
|
+
|
|
2291
|
+
class EventNode {
|
|
2292
|
+
_node;
|
|
2293
|
+
_event;
|
|
2294
|
+
constructor(_node, _event) {
|
|
2295
|
+
this._node = _node;
|
|
2296
|
+
this._event = _event;
|
|
2297
|
+
}
|
|
2298
|
+
get node() {
|
|
2299
|
+
return this._node;
|
|
2300
|
+
}
|
|
2301
|
+
get event() {
|
|
2302
|
+
return this._event;
|
|
2303
|
+
}
|
|
2304
|
+
isEqual(that) {
|
|
2305
|
+
return that !== null && that !== undefined && this._node == that._node && this._event.type == that._event.type;
|
|
2306
|
+
}
|
|
2307
|
+
toString() {
|
|
2308
|
+
return this._node.id + '__' + this.event.type;
|
|
2309
|
+
}
|
|
2310
|
+
valueOf() {
|
|
2311
|
+
return this.toString();
|
|
2312
|
+
}
|
|
2313
|
+
}
|
|
2314
|
+
class EventQueue {
|
|
2315
|
+
logger;
|
|
2316
|
+
static MAX_EVENT_CYCLE_COUNT = 10;
|
|
2317
|
+
_runningEventCount;
|
|
2318
|
+
_isProcessing = false;
|
|
2319
|
+
_pendingEvents = [];
|
|
2320
|
+
constructor(logger = new Logger('off')) {
|
|
2321
|
+
this.logger = logger;
|
|
2322
|
+
this._runningEventCount = {};
|
|
2323
|
+
}
|
|
2324
|
+
get length() {
|
|
2325
|
+
return this._pendingEvents.length;
|
|
2326
|
+
}
|
|
2327
|
+
get isProcessing() {
|
|
2328
|
+
return this._isProcessing;
|
|
2329
|
+
}
|
|
2330
|
+
isQueued(node, event) {
|
|
2331
|
+
const evntNode = new EventNode(node, event);
|
|
2332
|
+
return this._pendingEvents.find(x => evntNode.isEqual(x)) !== undefined;
|
|
2333
|
+
}
|
|
2334
|
+
queue(node, events, priority = false) {
|
|
2335
|
+
if (!node || !events) {
|
|
2336
|
+
return;
|
|
2337
|
+
}
|
|
2338
|
+
if (!(events instanceof Array)) {
|
|
2339
|
+
events = [events];
|
|
2340
|
+
}
|
|
2341
|
+
events.forEach(e => {
|
|
2342
|
+
const evntNode = new EventNode(node, e);
|
|
2343
|
+
const counter = this._runningEventCount[evntNode.valueOf()] || 0;
|
|
2344
|
+
if (counter < EventQueue.MAX_EVENT_CYCLE_COUNT) {
|
|
2345
|
+
this.logger.info(`Queued event : ${e.type} node: ${node.id} - ${node.name}`);
|
|
2346
|
+
if (priority) {
|
|
2347
|
+
const index = this._isProcessing ? 1 : 0;
|
|
2348
|
+
this._pendingEvents.splice(index, 0, evntNode);
|
|
2349
|
+
}
|
|
2350
|
+
else {
|
|
2351
|
+
this._pendingEvents.push(evntNode);
|
|
2352
|
+
}
|
|
2353
|
+
this._runningEventCount[evntNode.valueOf()] = counter + 1;
|
|
2354
|
+
}
|
|
2355
|
+
else {
|
|
2356
|
+
this.logger.info(`Skipped queueing event : ${e.type} node: ${node.id} - ${node.name} with count=${counter}`);
|
|
2357
|
+
}
|
|
2079
2358
|
});
|
|
2080
|
-
sitesModel.items = itemsArr;
|
|
2081
2359
|
}
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2360
|
+
empty() {
|
|
2361
|
+
this._pendingEvents = [];
|
|
2362
|
+
}
|
|
2363
|
+
runPendingQueue() {
|
|
2364
|
+
if (this._isProcessing) {
|
|
2365
|
+
return;
|
|
2366
|
+
}
|
|
2367
|
+
this._isProcessing = true;
|
|
2368
|
+
while (this._pendingEvents.length > 0) {
|
|
2369
|
+
const e = this._pendingEvents[0];
|
|
2370
|
+
this.logger.info(`Dequeued event : ${e.event.type} node: ${e.node.id} - ${e.node.name}`);
|
|
2371
|
+
e.node.executeAction(e.event);
|
|
2372
|
+
this._pendingEvents.shift();
|
|
2373
|
+
}
|
|
2374
|
+
this._runningEventCount = {};
|
|
2375
|
+
this._isProcessing = false;
|
|
2376
|
+
}
|
|
2377
|
+
}
|
|
2090
2378
|
|
|
2091
2379
|
const request$1 = (url, data = null, options = {}) => {
|
|
2092
2380
|
const opts = { ...defaultRequestOptions, ...options };
|
|
@@ -2203,7 +2491,8 @@ const request = async (context, uri, httpVerb, payload, success, error, headers)
|
|
|
2203
2491
|
else {
|
|
2204
2492
|
context.form.logger.error('Error invoking a rest API');
|
|
2205
2493
|
const eName = getCustomEventName(error);
|
|
2206
|
-
if (error === '
|
|
2494
|
+
if (error === 'submitError') {
|
|
2495
|
+
context.form.dispatch(new SubmitError(result, true));
|
|
2207
2496
|
context.form.dispatch(new SubmitFailure(result, true));
|
|
2208
2497
|
}
|
|
2209
2498
|
else {
|
|
@@ -2334,6 +2623,11 @@ class FunctionRuntimeImpl {
|
|
|
2334
2623
|
},
|
|
2335
2624
|
exportData: () => {
|
|
2336
2625
|
return FunctionRuntimeImpl.getInstance().getFunctions().exportData._func.call(undefined, args, data, interpreter);
|
|
2626
|
+
},
|
|
2627
|
+
submitForm: (payload, validateForm, contentType) => {
|
|
2628
|
+
const submitAs = contentType || 'multipart/form-data';
|
|
2629
|
+
const args = ['custom:submitSuccess', 'custom:submitError', submitAs, payload, validateForm];
|
|
2630
|
+
return FunctionRuntimeImpl.getInstance().getFunctions().submitForm._func.call(undefined, args, data, interpreter);
|
|
2337
2631
|
}
|
|
2338
2632
|
}
|
|
2339
2633
|
};
|
|
@@ -2435,11 +2729,24 @@ class FunctionRuntimeImpl {
|
|
|
2435
2729
|
},
|
|
2436
2730
|
submitForm: {
|
|
2437
2731
|
_func: (args, data, interpreter) => {
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2732
|
+
let success = 'custom:submitSuccess';
|
|
2733
|
+
let error = 'custom:submitError';
|
|
2734
|
+
let submit_data;
|
|
2735
|
+
let validate_form;
|
|
2736
|
+
let submit_as;
|
|
2737
|
+
if (args.length > 0 && typeof valueOf(args[0]) === 'object') {
|
|
2738
|
+
submit_data = args.length > 0 ? valueOf(args[0]) : null;
|
|
2739
|
+
validate_form = args.length > 1 ? valueOf(args[1]) : true;
|
|
2740
|
+
submit_as = args.length > 2 ? toString(args[2]) : 'multipart/form-data';
|
|
2741
|
+
}
|
|
2742
|
+
else {
|
|
2743
|
+
interpreter.globals.form.logger.warn('This usage of submitForm is deprecated. Please see the documentation and update');
|
|
2744
|
+
success = toString(args[0]);
|
|
2745
|
+
error = toString(args[1]);
|
|
2746
|
+
submit_as = args.length > 2 ? toString(args[2]) : 'multipart/form-data';
|
|
2747
|
+
submit_data = args.length > 3 ? valueOf(args[3]) : null;
|
|
2748
|
+
validate_form = args.length > 4 ? valueOf(args[4]) : true;
|
|
2749
|
+
}
|
|
2443
2750
|
interpreter.globals.form.dispatch(new Submit({
|
|
2444
2751
|
success,
|
|
2445
2752
|
error,
|
|
@@ -2776,7 +3083,7 @@ class Form extends Container {
|
|
|
2776
3083
|
if (!validate_form || this.validate().length === 0) {
|
|
2777
3084
|
const payload = action?.payload || {};
|
|
2778
3085
|
const successEventName = payload?.success ? payload?.success : 'submitSuccess';
|
|
2779
|
-
const failureEventName = payload?.error ? payload?.error : '
|
|
3086
|
+
const failureEventName = payload?.error ? payload?.error : 'submitError';
|
|
2780
3087
|
submit(context, successEventName, failureEventName, payload?.submit_as, payload?.data);
|
|
2781
3088
|
}
|
|
2782
3089
|
}
|
|
@@ -2852,379 +3159,101 @@ class RuleEngine {
|
|
|
2852
3159
|
}
|
|
2853
3160
|
execute(node, data, globals, useValueOf = false) {
|
|
2854
3161
|
const { formula, ast } = node;
|
|
2855
|
-
const oldContext = this._context;
|
|
2856
|
-
this._context = globals;
|
|
2857
|
-
let res = undefined;
|
|
2858
|
-
try {
|
|
2859
|
-
res = formula.run(ast, data, 'en-US', globals);
|
|
2860
|
-
}
|
|
2861
|
-
catch (err) {
|
|
2862
|
-
this._context?.form?.logger?.error(err);
|
|
2863
|
-
}
|
|
2864
|
-
while (this.debugInfo.length > 0) {
|
|
2865
|
-
this._context?.form?.logger?.debug(this.debugInfo.pop());
|
|
2866
|
-
}
|
|
2867
|
-
let finalRes = res;
|
|
2868
|
-
if (useValueOf) {
|
|
2869
|
-
if (typeof res === 'object' && res !== null) {
|
|
2870
|
-
finalRes = Object.getPrototypeOf(res).valueOf.call(res);
|
|
2871
|
-
}
|
|
2872
|
-
}
|
|
2873
|
-
this._context = oldContext;
|
|
2874
|
-
return finalRes;
|
|
2875
|
-
}
|
|
2876
|
-
trackDependency(subscriber) {
|
|
2877
|
-
if (this._context && this._context.field !== undefined && this._context.field !== subscriber) {
|
|
2878
|
-
subscriber._addDependent(this._context.field);
|
|
2879
|
-
}
|
|
2880
|
-
}
|
|
2881
|
-
}
|
|
2882
|
-
|
|
2883
|
-
class Fieldset extends Container {
|
|
2884
|
-
constructor(params, _options) {
|
|
2885
|
-
super(params, _options);
|
|
2886
|
-
if (_options.mode !== 'restore') {
|
|
2887
|
-
this._applyDefaults();
|
|
2888
|
-
this.queueEvent(new Initialize());
|
|
2889
|
-
this.queueEvent(new ExecuteRule());
|
|
2890
|
-
}
|
|
2891
|
-
}
|
|
2892
|
-
_getDefaults() {
|
|
2893
|
-
return {
|
|
2894
|
-
...super._getDefaults(),
|
|
2895
|
-
visible: true,
|
|
2896
|
-
required: false,
|
|
2897
|
-
label: {
|
|
2898
|
-
visible: true,
|
|
2899
|
-
richText: false
|
|
2900
|
-
}
|
|
2901
|
-
};
|
|
2902
|
-
}
|
|
2903
|
-
_applyDefaults() {
|
|
2904
|
-
super._applyDefaultsInModel();
|
|
2905
|
-
if (this._jsonModel.dataRef && this._jsonModel.type === undefined) {
|
|
2906
|
-
this._jsonModel.type = 'object';
|
|
2907
|
-
}
|
|
2908
|
-
}
|
|
2909
|
-
get type() {
|
|
2910
|
-
const ret = super.type;
|
|
2911
|
-
if (ret === 'array' || ret === 'object') {
|
|
2912
|
-
return ret;
|
|
2913
|
-
}
|
|
2914
|
-
return undefined;
|
|
2915
|
-
}
|
|
2916
|
-
get items() {
|
|
2917
|
-
return super.items;
|
|
2918
|
-
}
|
|
2919
|
-
get value() {
|
|
2920
|
-
return null;
|
|
2921
|
-
}
|
|
2922
|
-
get fieldType() {
|
|
2923
|
-
return 'panel';
|
|
2924
|
-
}
|
|
2925
|
-
}
|
|
2926
|
-
|
|
2927
|
-
class InstanceManager extends Fieldset {
|
|
2928
|
-
get maxOccur() {
|
|
2929
|
-
return this._jsonModel.maxItems;
|
|
2930
|
-
}
|
|
2931
|
-
set maxOccur(m) {
|
|
2932
|
-
this.maxItems = m;
|
|
2933
|
-
}
|
|
2934
|
-
get minOccur() {
|
|
2935
|
-
return this.minItems;
|
|
2936
|
-
}
|
|
2937
|
-
addInstance(action) {
|
|
2938
|
-
return this.addItem(action);
|
|
2939
|
-
}
|
|
2940
|
-
removeInstance(action) {
|
|
2941
|
-
return this.removeItem(action);
|
|
2942
|
-
}
|
|
2943
|
-
}
|
|
2944
|
-
__decorate([
|
|
2945
|
-
dependencyTracked()
|
|
2946
|
-
], InstanceManager.prototype, "maxOccur", null);
|
|
2947
|
-
__decorate([
|
|
2948
|
-
dependencyTracked()
|
|
2949
|
-
], InstanceManager.prototype, "minOccur", null);
|
|
2950
|
-
|
|
2951
|
-
const dateRegex = /^(\d{4})-(\d{1,2})-(\d{1,2})$/;
|
|
2952
|
-
const emailRegex = /^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/;
|
|
2953
|
-
const days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
2954
|
-
const daysInMonth = (leapYear, month) => {
|
|
2955
|
-
if (leapYear && month == 2) {
|
|
2956
|
-
return 29;
|
|
2957
|
-
}
|
|
2958
|
-
return days[month - 1];
|
|
2959
|
-
};
|
|
2960
|
-
const isLeapYear = (year) => {
|
|
2961
|
-
return year % 400 === 0 || year % 4 === 0 && year % 100 !== 0;
|
|
2962
|
-
};
|
|
2963
|
-
const coerceType = (param, type) => {
|
|
2964
|
-
let num;
|
|
2965
|
-
switch (type) {
|
|
2966
|
-
case 'string':
|
|
2967
|
-
return param + '';
|
|
2968
|
-
case 'number':
|
|
2969
|
-
num = +param;
|
|
2970
|
-
if (!isNaN(num)) {
|
|
2971
|
-
return num;
|
|
2972
|
-
}
|
|
2973
|
-
break;
|
|
2974
|
-
case 'boolean':
|
|
2975
|
-
if (typeof param === 'string') {
|
|
2976
|
-
return param === 'true';
|
|
2977
|
-
}
|
|
2978
|
-
else if (typeof param === 'number') {
|
|
2979
|
-
return param !== 0;
|
|
2980
|
-
}
|
|
2981
|
-
}
|
|
2982
|
-
throw `${param} has invalid type. Expected : ${type}, Actual ${typeof param}`;
|
|
2983
|
-
};
|
|
2984
|
-
const checkNumber = (inputVal) => {
|
|
2985
|
-
if (inputVal === '' || inputVal == null) {
|
|
2986
|
-
return {
|
|
2987
|
-
value: '', valid: true
|
|
2988
|
-
};
|
|
2989
|
-
}
|
|
2990
|
-
let value = parseFloat(inputVal);
|
|
2991
|
-
const valid = !isNaN(value);
|
|
2992
|
-
if (!valid) {
|
|
2993
|
-
value = inputVal;
|
|
2994
|
-
}
|
|
2995
|
-
return {
|
|
2996
|
-
value, valid
|
|
2997
|
-
};
|
|
2998
|
-
};
|
|
2999
|
-
const checkInteger = (inputVal) => {
|
|
3000
|
-
if (inputVal == '' || inputVal == null) {
|
|
3001
|
-
return {
|
|
3002
|
-
value: '', valid: true
|
|
3003
|
-
};
|
|
3004
|
-
}
|
|
3005
|
-
let value = parseFloat(inputVal);
|
|
3006
|
-
const valid = !isNaN(value) && Math.round(value) === value;
|
|
3007
|
-
if (!valid) {
|
|
3008
|
-
value = inputVal;
|
|
3009
|
-
}
|
|
3010
|
-
return {
|
|
3011
|
-
value, valid
|
|
3012
|
-
};
|
|
3013
|
-
};
|
|
3014
|
-
const toArray = (inputVal) => {
|
|
3015
|
-
if (inputVal != null && !(inputVal instanceof Array)) {
|
|
3016
|
-
return [inputVal];
|
|
3017
|
-
}
|
|
3018
|
-
return inputVal;
|
|
3019
|
-
};
|
|
3020
|
-
const checkBool = (inputVal) => {
|
|
3021
|
-
const valid = typeof inputVal === 'boolean' || inputVal === 'true' || inputVal === 'false';
|
|
3022
|
-
const value = typeof inputVal === 'boolean' ? inputVal : (valid ? inputVal === 'true' : inputVal);
|
|
3023
|
-
return { valid, value };
|
|
3024
|
-
};
|
|
3025
|
-
const checkFile = (inputVal) => {
|
|
3026
|
-
const value = extractFileInfo(inputVal);
|
|
3027
|
-
const valid = value !== null;
|
|
3028
|
-
return {
|
|
3029
|
-
value: valid ? value : inputVal,
|
|
3030
|
-
valid
|
|
3031
|
-
};
|
|
3032
|
-
};
|
|
3033
|
-
const matchMediaType = (mediaType, accepts) => {
|
|
3034
|
-
return !mediaType || accepts.some((accept) => {
|
|
3035
|
-
const trimmedAccept = accept.trim();
|
|
3036
|
-
const prefixAccept = trimmedAccept.split('/')[0];
|
|
3037
|
-
const suffixAccept = trimmedAccept.split('.')[1];
|
|
3038
|
-
return ((trimmedAccept.includes('*') && mediaType.startsWith(prefixAccept)) ||
|
|
3039
|
-
(trimmedAccept.includes('.') && mediaType.endsWith(suffixAccept)) ||
|
|
3040
|
-
(trimmedAccept === mediaType));
|
|
3041
|
-
});
|
|
3042
|
-
};
|
|
3043
|
-
const partitionArray = (inputVal, validatorFn) => {
|
|
3044
|
-
const value = toArray(inputVal);
|
|
3045
|
-
if (value == null) {
|
|
3046
|
-
return [[], [value]];
|
|
3047
|
-
}
|
|
3048
|
-
return value.reduce((acc, x) => {
|
|
3049
|
-
if (acc[1].length == 0) {
|
|
3050
|
-
const r = validatorFn(x);
|
|
3051
|
-
const index = r.valid ? 0 : 1;
|
|
3052
|
-
acc[index].push(r.value);
|
|
3053
|
-
}
|
|
3054
|
-
return acc;
|
|
3055
|
-
}, [[], []]);
|
|
3056
|
-
};
|
|
3057
|
-
const ValidConstraints = {
|
|
3058
|
-
date: ['minimum', 'maximum', 'exclusiveMinimum', 'exclusiveMaximum', 'format'],
|
|
3059
|
-
string: ['minLength', 'maxLength', 'pattern'],
|
|
3060
|
-
number: ['minimum', 'maximum', 'exclusiveMinimum', 'exclusiveMaximum'],
|
|
3061
|
-
array: ['minItems', 'maxItems', 'uniqueItems'],
|
|
3062
|
-
file: ['accept', 'maxFileSize'],
|
|
3063
|
-
email: ['minLength', 'maxLength', 'format', 'pattern']
|
|
3064
|
-
};
|
|
3065
|
-
const Constraints = {
|
|
3066
|
-
type: (constraint, inputVal) => {
|
|
3067
|
-
let value = inputVal;
|
|
3068
|
-
if (inputVal == undefined) {
|
|
3069
|
-
return {
|
|
3070
|
-
valid: true,
|
|
3071
|
-
value: inputVal
|
|
3072
|
-
};
|
|
3162
|
+
const oldContext = this._context;
|
|
3163
|
+
this._context = globals;
|
|
3164
|
+
let res = undefined;
|
|
3165
|
+
try {
|
|
3166
|
+
res = formula.run(ast, data, 'en-US', globals);
|
|
3073
3167
|
}
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
case 'string':
|
|
3077
|
-
valid = true;
|
|
3078
|
-
value = inputVal.toString();
|
|
3079
|
-
break;
|
|
3080
|
-
case 'string[]':
|
|
3081
|
-
value = toArray(inputVal);
|
|
3082
|
-
break;
|
|
3083
|
-
case 'number':
|
|
3084
|
-
res = checkNumber(inputVal);
|
|
3085
|
-
value = res.value;
|
|
3086
|
-
valid = res.valid;
|
|
3087
|
-
break;
|
|
3088
|
-
case 'boolean':
|
|
3089
|
-
res = checkBool(inputVal);
|
|
3090
|
-
valid = res.valid;
|
|
3091
|
-
value = res.value;
|
|
3092
|
-
break;
|
|
3093
|
-
case 'integer':
|
|
3094
|
-
res = checkInteger(inputVal);
|
|
3095
|
-
valid = res.valid;
|
|
3096
|
-
value = res.value;
|
|
3097
|
-
break;
|
|
3098
|
-
case 'integer[]':
|
|
3099
|
-
res = partitionArray(inputVal, checkInteger);
|
|
3100
|
-
valid = res[1].length === 0;
|
|
3101
|
-
value = valid ? res[0] : inputVal;
|
|
3102
|
-
break;
|
|
3103
|
-
case 'file':
|
|
3104
|
-
res = checkFile(inputVal instanceof Array ? inputVal[0] : inputVal);
|
|
3105
|
-
valid = res.valid;
|
|
3106
|
-
value = res.value;
|
|
3107
|
-
break;
|
|
3108
|
-
case 'file[]':
|
|
3109
|
-
res = partitionArray(inputVal, checkFile);
|
|
3110
|
-
valid = res[1].length === 0;
|
|
3111
|
-
value = valid ? res[0] : inputVal;
|
|
3112
|
-
break;
|
|
3113
|
-
case 'number[]':
|
|
3114
|
-
res = partitionArray(inputVal, checkNumber);
|
|
3115
|
-
valid = res[1].length === 0;
|
|
3116
|
-
value = valid ? res[0] : inputVal;
|
|
3117
|
-
break;
|
|
3118
|
-
case 'boolean[]':
|
|
3119
|
-
res = partitionArray(inputVal, checkBool);
|
|
3120
|
-
valid = res[1].length === 0;
|
|
3121
|
-
value = valid ? res[0] : inputVal;
|
|
3122
|
-
break;
|
|
3168
|
+
catch (err) {
|
|
3169
|
+
this._context?.form?.logger?.error(err);
|
|
3123
3170
|
}
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
value
|
|
3127
|
-
};
|
|
3128
|
-
},
|
|
3129
|
-
format: (constraint, input) => {
|
|
3130
|
-
let valid = true;
|
|
3131
|
-
const value = input;
|
|
3132
|
-
if (input === null) {
|
|
3133
|
-
return { value, valid };
|
|
3171
|
+
while (this.debugInfo.length > 0) {
|
|
3172
|
+
this._context?.form?.logger?.debug(this.debugInfo.pop());
|
|
3134
3173
|
}
|
|
3135
|
-
let res;
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
const [match, year, month, date] = res;
|
|
3141
|
-
const [nMonth, nDate] = [+month, +date];
|
|
3142
|
-
const leapYear = isLeapYear(+year);
|
|
3143
|
-
valid = (nMonth >= 1 && nMonth <= 12) &&
|
|
3144
|
-
(nDate >= 1 && nDate <= daysInMonth(leapYear, nMonth));
|
|
3145
|
-
}
|
|
3146
|
-
else {
|
|
3147
|
-
valid = false;
|
|
3148
|
-
}
|
|
3149
|
-
break;
|
|
3150
|
-
case 'email':
|
|
3151
|
-
valid = new RegExp(emailRegex).test((input || '').trim());
|
|
3152
|
-
break;
|
|
3153
|
-
case 'data-url':
|
|
3154
|
-
valid = true;
|
|
3155
|
-
break;
|
|
3174
|
+
let finalRes = res;
|
|
3175
|
+
if (useValueOf) {
|
|
3176
|
+
if (typeof res === 'object' && res !== null) {
|
|
3177
|
+
finalRes = Object.getPrototypeOf(res).valueOf.call(res);
|
|
3178
|
+
}
|
|
3156
3179
|
}
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
return { valid: value <= constraint, value };
|
|
3164
|
-
},
|
|
3165
|
-
exclusiveMinimum: (constraint, value) => {
|
|
3166
|
-
return { valid: value > constraint, value };
|
|
3167
|
-
},
|
|
3168
|
-
exclusiveMaximum: (constraint, value) => {
|
|
3169
|
-
return { valid: value < constraint, value };
|
|
3170
|
-
},
|
|
3171
|
-
minItems: (constraint, value) => {
|
|
3172
|
-
return { valid: (value instanceof Array) && value.length >= constraint, value };
|
|
3173
|
-
},
|
|
3174
|
-
maxItems: (constraint, value) => {
|
|
3175
|
-
return { valid: (value instanceof Array) && value.length <= constraint, value };
|
|
3176
|
-
},
|
|
3177
|
-
uniqueItems: (constraint, value) => {
|
|
3178
|
-
return { valid: !constraint || ((value instanceof Array) && value.length === new Set(value).size), value };
|
|
3179
|
-
},
|
|
3180
|
-
minLength: (constraint, value) => {
|
|
3181
|
-
return { ...Constraints.minimum(constraint, typeof value === 'string' ? value.length : 0), value };
|
|
3182
|
-
},
|
|
3183
|
-
maxLength: (constraint, value) => {
|
|
3184
|
-
return { ...Constraints.maximum(constraint, typeof value === 'string' ? value.length : 0), value };
|
|
3185
|
-
},
|
|
3186
|
-
pattern: (constraint, value) => {
|
|
3187
|
-
let regex;
|
|
3188
|
-
if (typeof constraint === 'string') {
|
|
3189
|
-
regex = new RegExp(constraint);
|
|
3180
|
+
this._context = oldContext;
|
|
3181
|
+
return finalRes;
|
|
3182
|
+
}
|
|
3183
|
+
trackDependency(subscriber) {
|
|
3184
|
+
if (this._context && this._context.field !== undefined && this._context.field !== subscriber) {
|
|
3185
|
+
subscriber._addDependent(this._context.field);
|
|
3190
3186
|
}
|
|
3191
|
-
|
|
3192
|
-
|
|
3187
|
+
}
|
|
3188
|
+
}
|
|
3189
|
+
|
|
3190
|
+
class Fieldset extends Container {
|
|
3191
|
+
constructor(params, _options) {
|
|
3192
|
+
super(params, _options);
|
|
3193
|
+
if (_options.mode !== 'restore') {
|
|
3194
|
+
this._applyDefaults();
|
|
3195
|
+
this.queueEvent(new Initialize());
|
|
3196
|
+
this.queueEvent(new ExecuteRule());
|
|
3193
3197
|
}
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
required: (constraint, value) => {
|
|
3197
|
-
const valid = constraint ? value != null && value !== '' : true;
|
|
3198
|
-
return { valid, value };
|
|
3199
|
-
},
|
|
3200
|
-
enum: (constraint, value) => {
|
|
3198
|
+
}
|
|
3199
|
+
_getDefaults() {
|
|
3201
3200
|
return {
|
|
3202
|
-
|
|
3203
|
-
|
|
3201
|
+
...super._getDefaults(),
|
|
3202
|
+
visible: true,
|
|
3203
|
+
required: false,
|
|
3204
|
+
label: {
|
|
3205
|
+
visible: true,
|
|
3206
|
+
richText: false
|
|
3207
|
+
}
|
|
3204
3208
|
};
|
|
3205
|
-
}
|
|
3206
|
-
|
|
3207
|
-
|
|
3208
|
-
|
|
3209
|
-
|
|
3210
|
-
value
|
|
3211
|
-
};
|
|
3209
|
+
}
|
|
3210
|
+
_applyDefaults() {
|
|
3211
|
+
super._applyDefaultsInModel();
|
|
3212
|
+
if (this._jsonModel.dataRef && this._jsonModel.type === undefined) {
|
|
3213
|
+
this._jsonModel.type = 'object';
|
|
3212
3214
|
}
|
|
3213
|
-
const tempValue = value instanceof Array ? value : [value];
|
|
3214
|
-
const invalidFile = tempValue.some((file) => !matchMediaType(file.type, constraint));
|
|
3215
|
-
return {
|
|
3216
|
-
valid: !invalidFile,
|
|
3217
|
-
value
|
|
3218
|
-
};
|
|
3219
|
-
},
|
|
3220
|
-
maxFileSize: (constraint, value) => {
|
|
3221
|
-
const sizeLimit = typeof constraint === 'string' ? getFileSizeInBytes(constraint) : constraint;
|
|
3222
|
-
return {
|
|
3223
|
-
valid: !(value instanceof FileObject) || value.size <= sizeLimit,
|
|
3224
|
-
value
|
|
3225
|
-
};
|
|
3226
3215
|
}
|
|
3227
|
-
|
|
3216
|
+
get type() {
|
|
3217
|
+
const ret = super.type;
|
|
3218
|
+
if (ret === 'array' || ret === 'object') {
|
|
3219
|
+
return ret;
|
|
3220
|
+
}
|
|
3221
|
+
return undefined;
|
|
3222
|
+
}
|
|
3223
|
+
get items() {
|
|
3224
|
+
return super.items;
|
|
3225
|
+
}
|
|
3226
|
+
get value() {
|
|
3227
|
+
return null;
|
|
3228
|
+
}
|
|
3229
|
+
get fieldType() {
|
|
3230
|
+
return 'panel';
|
|
3231
|
+
}
|
|
3232
|
+
}
|
|
3233
|
+
|
|
3234
|
+
class InstanceManager extends Fieldset {
|
|
3235
|
+
get maxOccur() {
|
|
3236
|
+
return this._jsonModel.maxItems;
|
|
3237
|
+
}
|
|
3238
|
+
set maxOccur(m) {
|
|
3239
|
+
this.maxItems = m;
|
|
3240
|
+
}
|
|
3241
|
+
get minOccur() {
|
|
3242
|
+
return this.minItems;
|
|
3243
|
+
}
|
|
3244
|
+
addInstance(action) {
|
|
3245
|
+
return this.addItem(action);
|
|
3246
|
+
}
|
|
3247
|
+
removeInstance(action) {
|
|
3248
|
+
return this.removeItem(action);
|
|
3249
|
+
}
|
|
3250
|
+
}
|
|
3251
|
+
__decorate([
|
|
3252
|
+
dependencyTracked()
|
|
3253
|
+
], InstanceManager.prototype, "maxOccur", null);
|
|
3254
|
+
__decorate([
|
|
3255
|
+
dependencyTracked()
|
|
3256
|
+
], InstanceManager.prototype, "minOccur", null);
|
|
3228
3257
|
|
|
3229
3258
|
const validTypes = ['string', 'number', 'integer', 'boolean', 'file', 'string[]', 'number[]', 'integer[]', 'boolean[]', 'file[]', 'array', 'object'];
|
|
3230
3259
|
class Field extends Scriptable {
|
|
@@ -3449,7 +3478,6 @@ class Field extends Scriptable {
|
|
|
3449
3478
|
}
|
|
3450
3479
|
set required(r) {
|
|
3451
3480
|
this._setProperty('required', r);
|
|
3452
|
-
this.validate();
|
|
3453
3481
|
}
|
|
3454
3482
|
get maximum() {
|
|
3455
3483
|
if (this.type === 'number' || this.format === 'date' || this.type === 'integer') {
|
|
@@ -4078,6 +4106,17 @@ class Checkbox extends Field {
|
|
|
4078
4106
|
baseConstraints.required = requiredConstraint(this.offValue());
|
|
4079
4107
|
return baseConstraints;
|
|
4080
4108
|
}
|
|
4109
|
+
_applyDefaults() {
|
|
4110
|
+
if (typeof this._jsonModel.checked === 'boolean') {
|
|
4111
|
+
if (this._jsonModel.checked) {
|
|
4112
|
+
this._jsonModel.default = this._jsonModel.enum?.[0];
|
|
4113
|
+
}
|
|
4114
|
+
else {
|
|
4115
|
+
this._jsonModel.default = this._jsonModel.enum?.[1];
|
|
4116
|
+
}
|
|
4117
|
+
}
|
|
4118
|
+
super._applyDefaults();
|
|
4119
|
+
}
|
|
4081
4120
|
_getDefaults() {
|
|
4082
4121
|
return {
|
|
4083
4122
|
...super._getDefaults(),
|
|
@@ -4087,7 +4126,43 @@ class Checkbox extends Field {
|
|
|
4087
4126
|
get enum() {
|
|
4088
4127
|
return this._jsonModel.enum || [];
|
|
4089
4128
|
}
|
|
4129
|
+
updateDataNodeAndTypedValue(val) {
|
|
4130
|
+
const changes = super.updateDataNodeAndTypedValue(val);
|
|
4131
|
+
const valueChange = changes.find((c) => c.propertyName === 'value');
|
|
4132
|
+
if (valueChange) {
|
|
4133
|
+
const oldChecked = valueChange.prevValue === this._jsonModel.enum?.[0];
|
|
4134
|
+
const newChecked = valueChange.currentValue === this._jsonModel.enum?.[0];
|
|
4135
|
+
if (oldChecked !== newChecked) {
|
|
4136
|
+
changes.push({
|
|
4137
|
+
propertyName: 'checked',
|
|
4138
|
+
prevValue: oldChecked,
|
|
4139
|
+
currentValue: newChecked
|
|
4140
|
+
});
|
|
4141
|
+
}
|
|
4142
|
+
}
|
|
4143
|
+
return changes;
|
|
4144
|
+
}
|
|
4145
|
+
set checked(check) {
|
|
4146
|
+
if (check) {
|
|
4147
|
+
this.value = this._jsonModel.enum?.[0];
|
|
4148
|
+
}
|
|
4149
|
+
else {
|
|
4150
|
+
this.value = this._jsonModel.enum?.[1];
|
|
4151
|
+
}
|
|
4152
|
+
}
|
|
4153
|
+
get checked() {
|
|
4154
|
+
return this.value === this._jsonModel.enum?.[0];
|
|
4155
|
+
}
|
|
4156
|
+
getState(isRepeatableChild = false, forRestore = false) {
|
|
4157
|
+
return {
|
|
4158
|
+
...super.getState(isRepeatableChild, forRestore),
|
|
4159
|
+
checked: this.checked
|
|
4160
|
+
};
|
|
4161
|
+
}
|
|
4090
4162
|
}
|
|
4163
|
+
__decorate([
|
|
4164
|
+
dependencyTracked()
|
|
4165
|
+
], Checkbox.prototype, "checked", null);
|
|
4091
4166
|
|
|
4092
4167
|
class CheckboxGroup extends Field {
|
|
4093
4168
|
constructor(params, _options) {
|
|
@@ -4259,9 +4334,13 @@ const createFormInstance = (formModel, callback, logLevel = 'error', fModel = un
|
|
|
4259
4334
|
const defaultOptions = {
|
|
4260
4335
|
logLevel: 'error'
|
|
4261
4336
|
};
|
|
4262
|
-
const restoreFormInstance = (formModel, { logLevel } = defaultOptions) => {
|
|
4337
|
+
const restoreFormInstance = (formModel, data = null, { logLevel } = defaultOptions) => {
|
|
4263
4338
|
try {
|
|
4264
4339
|
const form = new Form({ ...formModel }, FormFieldFactory, new RuleEngine(), new EventQueue(new Logger(logLevel)), logLevel, 'restore');
|
|
4340
|
+
if (data) {
|
|
4341
|
+
form._bindToDataModel(new DataGroup('$form', data));
|
|
4342
|
+
form.syncDataAndFormModel(form.getDataNode());
|
|
4343
|
+
}
|
|
4265
4344
|
form.getEventQueue().empty();
|
|
4266
4345
|
return form;
|
|
4267
4346
|
}
|