@masterteam/form-builder 0.0.34 → 0.0.36
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/assets/i18n/ar.json +85 -83
- package/assets/i18n/en.json +85 -83
- package/fesm2022/masterteam-form-builder.mjs +67 -15
- package/fesm2022/masterteam-form-builder.mjs.map +1 -1
- package/package.json +18 -18
package/assets/i18n/ar.json
CHANGED
|
@@ -1,83 +1,85 @@
|
|
|
1
|
-
{
|
|
2
|
-
"formBuilder": {
|
|
3
|
-
"save": "حفظ",
|
|
4
|
-
"cancel": "إلغاء",
|
|
5
|
-
"delete": "حذف",
|
|
6
|
-
"name-ar": "الاسم بالعربية",
|
|
7
|
-
"name-en": "الاسم بالإنجليزية",
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"validation-
|
|
35
|
-
"validation-
|
|
36
|
-
"validation-
|
|
37
|
-
"validation-
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"severity
|
|
43
|
-
"severity-
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"is-
|
|
52
|
-
"is-
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
"scope-
|
|
62
|
-
"scope-
|
|
63
|
-
"scope-
|
|
64
|
-
"scope-
|
|
65
|
-
"scope-
|
|
66
|
-
"scope-
|
|
67
|
-
"scope-
|
|
68
|
-
"
|
|
69
|
-
"
|
|
70
|
-
"
|
|
71
|
-
"no-
|
|
72
|
-
"
|
|
73
|
-
"
|
|
74
|
-
"
|
|
75
|
-
"
|
|
76
|
-
"
|
|
77
|
-
"
|
|
78
|
-
"
|
|
79
|
-
"toolbar-
|
|
80
|
-
"toolbar-
|
|
81
|
-
"
|
|
82
|
-
|
|
83
|
-
|
|
1
|
+
{
|
|
2
|
+
"formBuilder": {
|
|
3
|
+
"save": "حفظ",
|
|
4
|
+
"cancel": "إلغاء",
|
|
5
|
+
"delete": "حذف",
|
|
6
|
+
"name-ar": "الاسم بالعربية",
|
|
7
|
+
"name-en": "الاسم بالإنجليزية",
|
|
8
|
+
"required": "هذا الحقل مطلوب",
|
|
9
|
+
"whitespace-invalid": "أدخل حرفًا واحدًا على الأقل غير المسافة",
|
|
10
|
+
"system": "نظام",
|
|
11
|
+
"custom": "مخصص",
|
|
12
|
+
"layout": "التخطيط",
|
|
13
|
+
"reset": "إعادة تعيين",
|
|
14
|
+
"preview": "معاينة",
|
|
15
|
+
"add-section": "إضافة قسم",
|
|
16
|
+
"edit-section": "تعديل القسم",
|
|
17
|
+
"edit-field": "تعديل الحقل",
|
|
18
|
+
"remove-field": "إزالة الحقل",
|
|
19
|
+
"drag-from-the-side": "اسحب عناصرك من اللوحة الجانبية",
|
|
20
|
+
"change-width": "تغيير العرض",
|
|
21
|
+
"is-required": "مطلوب",
|
|
22
|
+
"size": "الحجم",
|
|
23
|
+
"field-settings": "إعدادات الحقل",
|
|
24
|
+
"form-elements": "عناصر النموذج",
|
|
25
|
+
"no-section": "لنبدأ بإضافة قسم إلى نموذجك، انقر على زر إضافة قسم أعلاه.",
|
|
26
|
+
"hidden-in-creation": "مخفي عند الإنشاء",
|
|
27
|
+
"hidden-in-edit-form": "مخفي في نموذج التعديل",
|
|
28
|
+
"show-hide": "إظهار/إخفاء",
|
|
29
|
+
"show-hide-description": "الإظهار بناءً على قيمة خصائص أخرى",
|
|
30
|
+
"set-conditions": "تعيين الشروط",
|
|
31
|
+
"conditional-display-formula": "معادلة الإظهار الشرطي",
|
|
32
|
+
"enter-formula": "أدخل المعادلة...",
|
|
33
|
+
"validation-rules": "قواعد التحقق",
|
|
34
|
+
"add-validation-rule": "إضافة قاعدة تحقق",
|
|
35
|
+
"edit-validation-rule": "تعديل قاعدة التحقق",
|
|
36
|
+
"validation-formula": "المعادلة",
|
|
37
|
+
"validation-message": "الرسالة",
|
|
38
|
+
"validation-active": "نشط",
|
|
39
|
+
"validation-formula-placeholder": "أنشئ معادلة التحقق...",
|
|
40
|
+
"message-en": "الرسالة (الإنجليزية)",
|
|
41
|
+
"message-ar": "الرسالة (العربية)",
|
|
42
|
+
"severity": "نوع رسالة التحقق",
|
|
43
|
+
"severity-hint": "اختر ما إذا كانت القاعدة ستظهر كخطأ أو تحذير عند فشل التحقق.",
|
|
44
|
+
"severity-error": "خطأ",
|
|
45
|
+
"severity-warning": "تحذير",
|
|
46
|
+
"create-form": "إنشاء نموذج",
|
|
47
|
+
"edit-form": "تعديل النموذج",
|
|
48
|
+
"search-properties": "البحث في الخصائص",
|
|
49
|
+
"no-data-found": "لا توجد بيانات",
|
|
50
|
+
"no-fields-visible": "لا توجد حقول مرئية في هذا الوضع",
|
|
51
|
+
"is-read": "قابل للقراءة",
|
|
52
|
+
"is-read-description": "عند التعطيل، سيتم إخفاء هذا الحقل عن المستخدمين",
|
|
53
|
+
"is-write": "قابل للتعديل",
|
|
54
|
+
"is-write-description": "عند التعطيل، سيكون هذا الحقل للقراءة فقط للمستخدمين",
|
|
55
|
+
"hidden": "مخفي",
|
|
56
|
+
"read-only": "للقراءة فقط",
|
|
57
|
+
"sections": "أقسام",
|
|
58
|
+
"steps": "خطوات",
|
|
59
|
+
"tabs": "تبويبات",
|
|
60
|
+
"wizard": "خطوات رأسية",
|
|
61
|
+
"scope-current": "الحالي",
|
|
62
|
+
"scope-host": "المضيف",
|
|
63
|
+
"scope-level": "المستوى",
|
|
64
|
+
"scope-parent": "الأصل",
|
|
65
|
+
"scope-ancestors": "الأسلاف",
|
|
66
|
+
"scope-children": "الأبناء",
|
|
67
|
+
"scope-descendants": "السلالة",
|
|
68
|
+
"scope-related": "المرتبط",
|
|
69
|
+
"scope-siblings": "الإخوة",
|
|
70
|
+
"path": "المسار",
|
|
71
|
+
"no-context": "لا يوجد سياق متاح",
|
|
72
|
+
"select": "اختر",
|
|
73
|
+
"no-options": "لا توجد خيارات",
|
|
74
|
+
"add-segment": "إضافة مقطع",
|
|
75
|
+
"scope-select-placeholder": "اختر...",
|
|
76
|
+
"select-property": "اختر خاصية",
|
|
77
|
+
"no-properties-available": "لا توجد خصائص متاحة",
|
|
78
|
+
"all-items-in-use": "جميع العناصر مستخدمة",
|
|
79
|
+
"toolbar-functions": "الدوال",
|
|
80
|
+
"toolbar-fields": "الحقول",
|
|
81
|
+
"toolbar-operators": "العوامل",
|
|
82
|
+
"toolbar-no-fields": "لا توجد حقول متاحة",
|
|
83
|
+
"build-condition-formula": "أنشئ صيغة الشرط..."
|
|
84
|
+
}
|
|
85
|
+
}
|
package/assets/i18n/en.json
CHANGED
|
@@ -1,83 +1,85 @@
|
|
|
1
|
-
{
|
|
2
|
-
"formBuilder": {
|
|
3
|
-
"save": "Save",
|
|
4
|
-
"cancel": "Cancel",
|
|
5
|
-
"delete": "Delete",
|
|
6
|
-
"name-ar": "Name (Arabic)",
|
|
7
|
-
"name-en": "Name (English)",
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"validation-
|
|
35
|
-
"validation-
|
|
36
|
-
"validation-
|
|
37
|
-
"validation-
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"severity
|
|
43
|
-
"severity-
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"no-
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"is-
|
|
52
|
-
"is-
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
"scope-
|
|
62
|
-
"scope-
|
|
63
|
-
"scope-
|
|
64
|
-
"scope-
|
|
65
|
-
"scope-
|
|
66
|
-
"scope-
|
|
67
|
-
"scope-
|
|
68
|
-
"
|
|
69
|
-
"
|
|
70
|
-
"
|
|
71
|
-
"no-
|
|
72
|
-
"
|
|
73
|
-
"
|
|
74
|
-
"
|
|
75
|
-
"
|
|
76
|
-
"
|
|
77
|
-
"
|
|
78
|
-
"
|
|
79
|
-
"toolbar-
|
|
80
|
-
"toolbar-
|
|
81
|
-
"
|
|
82
|
-
|
|
83
|
-
|
|
1
|
+
{
|
|
2
|
+
"formBuilder": {
|
|
3
|
+
"save": "Save",
|
|
4
|
+
"cancel": "Cancel",
|
|
5
|
+
"delete": "Delete",
|
|
6
|
+
"name-ar": "Name (Arabic)",
|
|
7
|
+
"name-en": "Name (English)",
|
|
8
|
+
"required": "This field is required",
|
|
9
|
+
"whitespace-invalid": "Enter at least one non-space character",
|
|
10
|
+
"system": "System",
|
|
11
|
+
"custom": "Custom",
|
|
12
|
+
"layout": "Layout",
|
|
13
|
+
"reset": "Reset",
|
|
14
|
+
"preview": "Preview",
|
|
15
|
+
"add-section": "Add Section",
|
|
16
|
+
"edit-section": "Edit Section",
|
|
17
|
+
"edit-field": "Edit Field",
|
|
18
|
+
"remove-field": "Remove Field",
|
|
19
|
+
"drag-from-the-side": "Drag your elemnents from the side panel",
|
|
20
|
+
"change-width": "Change Width",
|
|
21
|
+
"is-required": "Is Required",
|
|
22
|
+
"size": "Size",
|
|
23
|
+
"field-settings": "Field Settings",
|
|
24
|
+
"form-elements": "Form Elements",
|
|
25
|
+
"no-section": "Let's start by adding a section to your form, click the add section button above.",
|
|
26
|
+
"hidden-in-creation": "Hidden In Creation",
|
|
27
|
+
"hidden-in-edit-form": "Hidden In Edit Form",
|
|
28
|
+
"show-hide": "Show/Hide",
|
|
29
|
+
"show-hide-description": "Show Based On The Value Of Other Properties",
|
|
30
|
+
"set-conditions": "Set Conditions",
|
|
31
|
+
"conditional-display-formula": "Conditional Display Formula",
|
|
32
|
+
"enter-formula": "Enter formula...",
|
|
33
|
+
"validation-rules": "Validation Rules",
|
|
34
|
+
"add-validation-rule": "Add Validation Rule",
|
|
35
|
+
"edit-validation-rule": "Edit Validation Rule",
|
|
36
|
+
"validation-formula": "Formula",
|
|
37
|
+
"validation-message": "Message",
|
|
38
|
+
"validation-active": "Active",
|
|
39
|
+
"validation-formula-placeholder": "Build validation formula...",
|
|
40
|
+
"message-en": "Message (English)",
|
|
41
|
+
"message-ar": "Message (Arabic)",
|
|
42
|
+
"severity": "Validation Message Type",
|
|
43
|
+
"severity-hint": "Choose whether this rule shows an error or a warning when validation fails.",
|
|
44
|
+
"severity-error": "Error",
|
|
45
|
+
"severity-warning": "Warning",
|
|
46
|
+
"create-form": "Create Form",
|
|
47
|
+
"edit-form": "Edit Form",
|
|
48
|
+
"no-data-found": "No data found",
|
|
49
|
+
"search-properties": "Search Properties",
|
|
50
|
+
"no-fields-visible": "No fields visible in this mode",
|
|
51
|
+
"is-read": "Readable",
|
|
52
|
+
"is-read-description": "When disabled, this field will be hidden from users",
|
|
53
|
+
"is-write": "Editable",
|
|
54
|
+
"is-write-description": "When disabled, this field will be read-only for users",
|
|
55
|
+
"hidden": "Hidden",
|
|
56
|
+
"read-only": "Read Only",
|
|
57
|
+
"sections": "Sections",
|
|
58
|
+
"steps": "Steps",
|
|
59
|
+
"tabs": "Tabs",
|
|
60
|
+
"wizard": "Wizard",
|
|
61
|
+
"scope-current": "Current",
|
|
62
|
+
"scope-host": "Host",
|
|
63
|
+
"scope-level": "Level",
|
|
64
|
+
"scope-parent": "Parent",
|
|
65
|
+
"scope-ancestors": "Ancestors",
|
|
66
|
+
"scope-children": "Children",
|
|
67
|
+
"scope-descendants": "Descendants",
|
|
68
|
+
"scope-related": "Related",
|
|
69
|
+
"scope-siblings": "Siblings",
|
|
70
|
+
"path": "Path",
|
|
71
|
+
"no-context": "No context available",
|
|
72
|
+
"select": "Select",
|
|
73
|
+
"no-options": "No options",
|
|
74
|
+
"add-segment": "Add Segment",
|
|
75
|
+
"scope-select-placeholder": "Select...",
|
|
76
|
+
"select-property": "Select a property",
|
|
77
|
+
"no-properties-available": "No properties available",
|
|
78
|
+
"all-items-in-use": "All items are in use",
|
|
79
|
+
"toolbar-functions": "Functions",
|
|
80
|
+
"toolbar-fields": "Fields",
|
|
81
|
+
"toolbar-operators": "Operators",
|
|
82
|
+
"toolbar-no-fields": "No fields available",
|
|
83
|
+
"build-condition-formula": "Build condition formula..."
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -24,11 +24,11 @@ import { DynamicField } from '@masterteam/forms/dynamic-field';
|
|
|
24
24
|
import { Icon } from '@masterteam/icons';
|
|
25
25
|
import { Action, Selector, State, Store, select } from '@ngxs/store';
|
|
26
26
|
import { HttpClient } from '@angular/common/http';
|
|
27
|
-
import { CrudStateBase, handleApiRequest, RadioCardsFieldConfig } from '@masterteam/components';
|
|
27
|
+
import { CrudStateBase, handleApiRequest, RadioCardsFieldConfig, ValidatorConfig } from '@masterteam/components';
|
|
28
28
|
import { DynamicForm } from '@masterteam/forms/dynamic-form';
|
|
29
29
|
import { ToggleField } from '@masterteam/components/toggle-field';
|
|
30
30
|
import { ModalRef } from '@masterteam/components/dialog';
|
|
31
|
-
import { CONDITION_FUNCTION_CATEGORIES, CONDITION_OPERATORS, FormulaToolbar, FormulaEditor } from '@masterteam/components/formula';
|
|
31
|
+
import { CONDITION_FUNCTION_CATEGORIES, CONDITION_OPERATORS, FormulaToolbar, FormulaEditor, serializeTokens, tokenizeFormulaTemplate } from '@masterteam/components/formula';
|
|
32
32
|
import { Tooltip } from '@masterteam/components/tooltip';
|
|
33
33
|
import { ClientForm } from '@masterteam/forms/client-form';
|
|
34
34
|
import { Table } from '@masterteam/components/table';
|
|
@@ -1500,6 +1500,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
1500
1500
|
], template: "<ng-container *transloco=\"let t; prefix: 'formBuilder'\">\n <div\n [class]=\"[\n modalService.contentClass,\n 'min-w-0',\n 'p-4',\n 'overflow-y-hidden!',\n 'max-[640px]:p-3',\n ]\"\n >\n <div class=\"mt-2 flex h-full min-h-0 flex-col gap-4 overflow-y-auto pb-10\">\n <mt-dynamic-form\n [formConfig]=\"activeFormConfig()\"\n [formControl]=\"formControl\"\n >\n </mt-dynamic-form>\n\n <!-- isRead Toggle -->\n <mt-toggle-field\n toggleShape=\"card\"\n [label]=\"t('is-read')\"\n [descriptionCard]=\"t('is-read-description')\"\n icon=\"general.eye\"\n [formControl]=\"isReadControl\"\n ></mt-toggle-field>\n\n <!-- isWrite Toggle -->\n <mt-toggle-field\n toggleShape=\"card\"\n [label]=\"t('is-write')\"\n [descriptionCard]=\"t('is-write-description')\"\n icon=\"general.edit-02\"\n [formControl]=\"isWriteControl\"\n ></mt-toggle-field>\n\n @if (!isManageProperties()) {\n <!-- Show/Hide Toggle with Set Conditions -->\n <mt-toggle-field\n toggleShape=\"card\"\n [label]=\"t('show-hide')\"\n [descriptionCard]=\"t('show-hide-description')\"\n icon=\"general.eye\"\n [formControl]=\"showHideControl\"\n class=\"mt-3\"\n >\n <ng-template #toggleCardBottom>\n @if (showHideControl.value) {\n <div class=\"mt-3\">\n <mt-button\n [label]=\"t('set-conditions')\"\n size=\"small\"\n styleClass=\"w-full sm:w-auto\"\n (onClick)=\"onSetConditions()\"\n ></mt-button>\n </div>\n }\n </ng-template>\n </mt-toggle-field>\n }\n </div>\n </div>\n\n <div\n [class]=\"[\n modalService.footerClass,\n '!h-auto',\n 'min-h-0',\n 'flex-col',\n 'gap-2',\n 'sm:flex-row',\n 'sm:items-center',\n 'sm:justify-end',\n ]\"\n >\n @if (initialData() && !isManageProperties()) {\n <mt-button\n [tooltip]=\"t('delete')\"\n severity=\"danger\"\n [variant]=\"'outlined'\"\n icon=\"general.trash-01\"\n [loading]=\"deleting()\"\n [disabled]=\"submitting()\"\n (onClick)=\"onDelete($event)\"\n class=\"self-start sm:me-auto\"\n ></mt-button>\n }\n <mt-button\n [label]=\"t('cancel')\"\n variant=\"outlined\"\n [disabled]=\"submitting() || deleting()\"\n styleClass=\"w-full sm:w-auto\"\n (onClick)=\"onCancel()\"\n >\n </mt-button>\n <mt-button\n [disabled]=\"!formControl.valid || deleting()\"\n [label]=\"t('save')\"\n severity=\"primary\"\n [loading]=\"submitting()\"\n styleClass=\"w-full sm:w-auto\"\n (onClick)=\"onSave()\"\n >\n </mt-button>\n </div>\n</ng-container>\n" }]
|
|
1501
1501
|
}], ctorParameters: () => [], propDecorators: { sectionId: [{ type: i0.Input, args: [{ isSignal: true, alias: "sectionId", required: false }] }], initialData: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialData", required: false }] }], allSections: [{ type: i0.Input, args: [{ isSignal: true, alias: "allSections", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }] } });
|
|
1502
1502
|
|
|
1503
|
+
const hasNonWhitespaceValue = (value) => {
|
|
1504
|
+
if (value === null || value === undefined || value === '')
|
|
1505
|
+
return true;
|
|
1506
|
+
return typeof value !== 'string' || value.trim().length > 0;
|
|
1507
|
+
};
|
|
1503
1508
|
class FBSectionForm {
|
|
1504
1509
|
transloco = inject(TranslocoService);
|
|
1505
1510
|
modalService = inject(ModalService);
|
|
@@ -1528,6 +1533,10 @@ class FBSectionForm {
|
|
|
1528
1533
|
label: this.transloco.translate('formBuilder.name-ar'),
|
|
1529
1534
|
type: 'text',
|
|
1530
1535
|
placeholder: this.transloco.translate('formBuilder.name-ar'),
|
|
1536
|
+
validators: [
|
|
1537
|
+
ValidatorConfig.required(this.transloco.translate('formBuilder.required')),
|
|
1538
|
+
ValidatorConfig.custom(hasNonWhitespaceValue, this.transloco.translate('formBuilder.whitespace-invalid')),
|
|
1539
|
+
],
|
|
1531
1540
|
colSpan: 12,
|
|
1532
1541
|
order: 1,
|
|
1533
1542
|
},
|
|
@@ -1536,6 +1545,10 @@ class FBSectionForm {
|
|
|
1536
1545
|
label: this.transloco.translate('formBuilder.name-en'),
|
|
1537
1546
|
type: 'text',
|
|
1538
1547
|
placeholder: this.transloco.translate('formBuilder.name-en'),
|
|
1548
|
+
validators: [
|
|
1549
|
+
ValidatorConfig.required(this.transloco.translate('formBuilder.required')),
|
|
1550
|
+
ValidatorConfig.custom(hasNonWhitespaceValue, this.transloco.translate('formBuilder.whitespace-invalid')),
|
|
1551
|
+
],
|
|
1539
1552
|
colSpan: 12,
|
|
1540
1553
|
order: 2,
|
|
1541
1554
|
},
|
|
@@ -1557,11 +1570,15 @@ class FBSectionForm {
|
|
|
1557
1570
|
onSave() {
|
|
1558
1571
|
if (this.formControl.invalid)
|
|
1559
1572
|
return;
|
|
1560
|
-
const formValue = this.formControl.value;
|
|
1573
|
+
const formValue = this.formControl.value ?? {};
|
|
1574
|
+
const nameAr = String(formValue['name-ar'] ?? '').trim();
|
|
1575
|
+
const nameEn = String(formValue['name-en'] ?? '').trim();
|
|
1576
|
+
if (!nameAr || !nameEn)
|
|
1577
|
+
return;
|
|
1561
1578
|
const payload = {
|
|
1562
1579
|
name: {
|
|
1563
|
-
ar:
|
|
1564
|
-
en:
|
|
1580
|
+
ar: nameAr,
|
|
1581
|
+
en: nameEn,
|
|
1565
1582
|
},
|
|
1566
1583
|
};
|
|
1567
1584
|
this.submitting.set(true);
|
|
@@ -2004,11 +2021,14 @@ class FBValidationRuleForm {
|
|
|
2004
2021
|
})),
|
|
2005
2022
|
};
|
|
2006
2023
|
}, ...(ngDevMode ? [{ debugName: "formulaPropertiesByPath" }] : /* istanbul ignore next */ []));
|
|
2024
|
+
hasFormula = computed(() => {
|
|
2025
|
+
const value = this.formulaControl.value;
|
|
2026
|
+
const expression = value?.expression?.trim() ?? '';
|
|
2027
|
+
return expression.length > 0 || (value?.builder?.length ?? 0) > 0;
|
|
2028
|
+
}, ...(ngDevMode ? [{ debugName: "hasFormula" }] : /* istanbul ignore next */ []));
|
|
2007
2029
|
canSave = computed(() => {
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
// expression.length > 0 &&
|
|
2011
|
-
this.formulaValidation().isValid && !this.submitting());
|
|
2030
|
+
return (this.hasFormula() &&
|
|
2031
|
+
this.formulaValidation().isValid && !this.submitting());
|
|
2012
2032
|
}, ...(ngDevMode ? [{ debugName: "canSave" }] : /* istanbul ignore next */ []));
|
|
2013
2033
|
severityOptions = computed(() => {
|
|
2014
2034
|
const _lang = this.activeLang();
|
|
@@ -2043,9 +2063,11 @@ class FBValidationRuleForm {
|
|
|
2043
2063
|
this.messageEnControl.setValue(data.message?.en ?? '');
|
|
2044
2064
|
this.messageArControl.setValue(data.message?.ar ?? '');
|
|
2045
2065
|
this.severityControl.setValue(data.severity ?? 'error');
|
|
2066
|
+
const builder = this.parseStoredFormulaTokens(data.formulaTokens);
|
|
2067
|
+
const expression = data.formulaText?.trim() || serializeTokens(builder) || '';
|
|
2046
2068
|
this.formulaControl.setValue({
|
|
2047
|
-
expression
|
|
2048
|
-
builder
|
|
2069
|
+
expression,
|
|
2070
|
+
builder,
|
|
2049
2071
|
});
|
|
2050
2072
|
this.formulaValidation.set(EMPTY_FORMULA_VALIDATION);
|
|
2051
2073
|
this.saveError.set(null);
|
|
@@ -2055,13 +2077,14 @@ class FBValidationRuleForm {
|
|
|
2055
2077
|
this.formulaValidation.set(result);
|
|
2056
2078
|
}
|
|
2057
2079
|
onSave() {
|
|
2058
|
-
const
|
|
2059
|
-
|
|
2080
|
+
const formulaValue = this.formulaControl.value;
|
|
2081
|
+
const formulaPayload = this.buildFormulaPayload(formulaValue);
|
|
2082
|
+
if (!formulaPayload || !this.formulaValidation().isValid) {
|
|
2060
2083
|
return;
|
|
2061
2084
|
}
|
|
2062
2085
|
const payload = {
|
|
2063
|
-
formulaTokens,
|
|
2064
|
-
formulaText:
|
|
2086
|
+
formulaTokens: formulaPayload.formulaTokens,
|
|
2087
|
+
formulaText: formulaPayload.formulaText,
|
|
2065
2088
|
message: {
|
|
2066
2089
|
en: this.messageEnControl.value ?? '',
|
|
2067
2090
|
ar: this.messageArControl.value ?? '',
|
|
@@ -2093,6 +2116,35 @@ class FBValidationRuleForm {
|
|
|
2093
2116
|
const numericValue = Number(value);
|
|
2094
2117
|
return Number.isFinite(numericValue) ? numericValue : undefined;
|
|
2095
2118
|
}
|
|
2119
|
+
parseStoredFormulaTokens(value) {
|
|
2120
|
+
const normalized = value?.trim();
|
|
2121
|
+
if (!normalized) {
|
|
2122
|
+
return [];
|
|
2123
|
+
}
|
|
2124
|
+
try {
|
|
2125
|
+
const parsed = JSON.parse(normalized);
|
|
2126
|
+
return Array.isArray(parsed) ? parsed : [];
|
|
2127
|
+
}
|
|
2128
|
+
catch {
|
|
2129
|
+
// Support legacy rows that stored raw expression text instead of token JSON.
|
|
2130
|
+
return tokenizeFormulaTemplate(normalized);
|
|
2131
|
+
}
|
|
2132
|
+
}
|
|
2133
|
+
buildFormulaPayload(value) {
|
|
2134
|
+
const expression = value?.expression?.trim() ?? '';
|
|
2135
|
+
let builder = Array.isArray(value?.builder) ? value.builder : [];
|
|
2136
|
+
if (builder.length === 0 && expression) {
|
|
2137
|
+
builder = tokenizeFormulaTemplate(expression);
|
|
2138
|
+
}
|
|
2139
|
+
const formulaText = expression || serializeTokens(builder);
|
|
2140
|
+
if (!formulaText || builder.length === 0) {
|
|
2141
|
+
return null;
|
|
2142
|
+
}
|
|
2143
|
+
return {
|
|
2144
|
+
formulaTokens: JSON.stringify(builder),
|
|
2145
|
+
formulaText,
|
|
2146
|
+
};
|
|
2147
|
+
}
|
|
2096
2148
|
handleSaveError(error) {
|
|
2097
2149
|
const message = error?.error?.message ??
|
|
2098
2150
|
error?.message ??
|