form-craft-package 1.5.4 → 1.5.6
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/package.json +1 -1
- package/src/components/form/1-list/table.tsx +2 -2
- package/src/components/form/layout-renderer/1-row/index.tsx +0 -1
- package/src/components/form/layout-renderer/3-element/1-dynamic-button/index.tsx +3 -4
- package/src/components/form/layout-renderer/3-element/10-currency.tsx +52 -0
- package/src/components/form/layout-renderer/3-element/3-read-field-data.tsx +4 -108
- package/src/components/form/layout-renderer/3-element/5-re-captcha.tsx +0 -2
- package/src/components/form/layout-renderer/3-element/7-file-upload.tsx +1 -1
- package/src/components/form/layout-renderer/3-element/8-fields-with-options.tsx +0 -1
- package/src/components/form/layout-renderer/3-element/9-form-data-render.tsx +0 -6
- package/src/components/form/layout-renderer/3-element/index.tsx +5 -1
- package/src/enums.ts +2 -1
- package/src/functions/evaluate-value.ts +100 -0
- package/src/functions/index.ts +66 -0
- package/src/types/layout-elements/field-option-source.ts +14 -1
- package/src/types/layout-elements/index.ts +1 -0
package/package.json
CHANGED
|
@@ -6,7 +6,7 @@ import { FormInstance, Table } from 'antd'
|
|
|
6
6
|
import { FilterConfigTypeEnum, FormDataListViewTypeEnum, MongoDbSortOrderEnum } from '../../../enums'
|
|
7
7
|
import { ICustomFunctionCall } from '../layout-renderer/3-element/1-dynamic-button'
|
|
8
8
|
import { SorterResult } from 'antd/es/table/interface'
|
|
9
|
-
import { extractElementsOptions, generateTableColumns } from '../../../functions'
|
|
9
|
+
import { appendOptionsFromDetailsLayout, extractElementsOptions, generateTableColumns } from '../../../functions'
|
|
10
10
|
import { useLocation } from 'react-router-dom'
|
|
11
11
|
|
|
12
12
|
export default function FormDataListTableComponent({
|
|
@@ -69,7 +69,7 @@ export default function FormDataListTableComponent({
|
|
|
69
69
|
optionKeyValuePair = await extractElementsOptions(layout, elementsWithOptions_key)
|
|
70
70
|
|
|
71
71
|
setTableColumns(generateTableColumns(elements, optionKeyValuePair, { attachmentBaseUrl, formName, formRef }))
|
|
72
|
-
setHeaderLayout(header.layout)
|
|
72
|
+
setHeaderLayout(appendOptionsFromDetailsLayout(header.layout, layout))
|
|
73
73
|
setOtherConfigs({ ...restConfigs, hasNoPagination: pagination?.hasNoPagination ?? false })
|
|
74
74
|
|
|
75
75
|
if (defaultFilter && defaultFilter.type !== FilterConfigTypeEnum.NoFilter)
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { useNavigate } from 'react-router-dom'
|
|
2
2
|
import { useNotification } from '../../../../common/custom-hooks'
|
|
3
3
|
import { useCheckElementConditions } from '../../../../common/custom-hooks/use-check-element-conditions.hook'
|
|
4
|
-
import { memo, useCallback,
|
|
5
|
-
import { ButtonActionCategoryEnum, FormLoadingModalTypeEnum
|
|
4
|
+
import { memo, useCallback, useMemo, useState } from 'react'
|
|
5
|
+
import { ButtonActionCategoryEnum, FormLoadingModalTypeEnum } from '../../../../../enums'
|
|
6
6
|
import { useFormPreservedItemValues } from '../../../../common/custom-hooks/use-preserved-form-items.hook'
|
|
7
7
|
import { constructDynamicFormHref } from '../../../../../functions'
|
|
8
8
|
import { useDuplicateDataAction } from './use-duplicate-data.hook'
|
|
@@ -17,7 +17,6 @@ import { Button_FillerPortal } from '../../../../common/button'
|
|
|
17
17
|
import { getButtonRenderProps } from '../../../../../functions/get-element-props'
|
|
18
18
|
import WarningIcon from '../../../../common/warning-icon'
|
|
19
19
|
import { IButtonNavigateState, IDataRender_ButtonProps, IFormLayoutElementConditions } from '../../../../../types'
|
|
20
|
-
import { FormInstance } from 'antd'
|
|
21
20
|
import FormDataLoadingIndicatorModal from '../../../../modals/form-data-loading.modal'
|
|
22
21
|
import { IFormContext } from '../../1-row'
|
|
23
22
|
|
|
@@ -152,7 +151,7 @@ export const DynamicFormButtonRender = memo((props: IDynamicButton) => {
|
|
|
152
151
|
|
|
153
152
|
break
|
|
154
153
|
|
|
155
|
-
case ButtonActionCategoryEnum.
|
|
154
|
+
case ButtonActionCategoryEnum.ReturnOneBack:
|
|
156
155
|
navigate(-1)
|
|
157
156
|
setLoading(false)
|
|
158
157
|
break
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { LayoutRenderer_FieldElement } from './2-field-element'
|
|
2
|
+
import { IFormContext } from '../1-row'
|
|
3
|
+
import { ICurrencyInputElement } from '../../../../types'
|
|
4
|
+
import { IElementBaseProps } from '.'
|
|
5
|
+
import { getElementGeneralizedProps } from '../../../../functions/get-element-props'
|
|
6
|
+
import { Form } from 'antd'
|
|
7
|
+
import { useEffect, useMemo } from 'react'
|
|
8
|
+
import { evaluateValue } from '../../../../functions/evaluate-value'
|
|
9
|
+
|
|
10
|
+
export default function LayoutRenderer_CurrencyField({
|
|
11
|
+
formContext,
|
|
12
|
+
formItem,
|
|
13
|
+
elementData,
|
|
14
|
+
isDisabled,
|
|
15
|
+
}: ILayoutRenderer_CurrencyField) {
|
|
16
|
+
const { formRef } = formContext
|
|
17
|
+
const props = getElementGeneralizedProps(elementData.props)
|
|
18
|
+
|
|
19
|
+
const formValues = Form.useWatch([], { form: formRef, preserve: true })
|
|
20
|
+
|
|
21
|
+
const evaluatedValue = useMemo(() => {
|
|
22
|
+
if (!props.evaluationConfig) return -1
|
|
23
|
+
|
|
24
|
+
if (formValues) return evaluateValue(props.evaluationConfig, formValues)
|
|
25
|
+
|
|
26
|
+
return 0
|
|
27
|
+
}, [formValues, props])
|
|
28
|
+
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
if (evaluatedValue > -1 && isDisabled) formRef?.setFieldValue(formItem.path, evaluatedValue)
|
|
31
|
+
}, [evaluatedValue, isDisabled, formItem.path])
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<LayoutRenderer_FieldElement
|
|
35
|
+
fields={[
|
|
36
|
+
{
|
|
37
|
+
...props,
|
|
38
|
+
type: elementData.elementType,
|
|
39
|
+
name: formItem.name,
|
|
40
|
+
validations: elementData.validations,
|
|
41
|
+
disabled: isDisabled,
|
|
42
|
+
},
|
|
43
|
+
]}
|
|
44
|
+
formRef={formRef}
|
|
45
|
+
/>
|
|
46
|
+
)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
type ILayoutRenderer_CurrencyField = {
|
|
50
|
+
formContext: IFormContext
|
|
51
|
+
elementData: ICurrencyInputElement
|
|
52
|
+
} & IElementBaseProps
|
|
@@ -2,16 +2,10 @@ import { Form } from 'antd'
|
|
|
2
2
|
import { renderData } from '../../../../functions'
|
|
3
3
|
import { useFormPreservedItemValues } from '../../../common/custom-hooks/use-preserved-form-items.hook'
|
|
4
4
|
import { useMemo } from 'react'
|
|
5
|
-
import { DataRenderTypeEnum
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
IEvaluationCondition,
|
|
9
|
-
IEvaluationConfig,
|
|
10
|
-
IEvaluationOnField,
|
|
11
|
-
IEvaluationOnList,
|
|
12
|
-
IReadFieldDataElementProps,
|
|
13
|
-
} from '../../../../types'
|
|
5
|
+
import { DataRenderTypeEnum } from '../../../../enums'
|
|
6
|
+
import { IReadFieldDataElementProps } from '../../../../types'
|
|
14
7
|
import { IFormContext } from '../1-row'
|
|
8
|
+
import { evaluateValue } from '../../../../functions/evaluate-value'
|
|
15
9
|
|
|
16
10
|
export default function LayoutRenderer_ReadFieldData({
|
|
17
11
|
formContext,
|
|
@@ -34,7 +28,7 @@ export default function LayoutRenderer_ReadFieldData({
|
|
|
34
28
|
const evaluatedValue = useMemo(() => {
|
|
35
29
|
if (elementProps.isValueEvaluated && formValues) {
|
|
36
30
|
const config = elementProps.evaluationConfig
|
|
37
|
-
return
|
|
31
|
+
return evaluateValue(config, formValues)
|
|
38
32
|
}
|
|
39
33
|
return 0
|
|
40
34
|
}, [formValues, elementProps])
|
|
@@ -63,101 +57,3 @@ type ILayoutRenderer_ReadFieldData = {
|
|
|
63
57
|
elementProps: IReadFieldDataElementProps
|
|
64
58
|
style?: { [key: string]: any }
|
|
65
59
|
}
|
|
66
|
-
|
|
67
|
-
const evaluateConfig = (config: IEvaluationConfig, data: { [key: string]: any }): number => {
|
|
68
|
-
// Helper to check an evaluation’s condition (if any)
|
|
69
|
-
function checkConditions(
|
|
70
|
-
dataToCheckConditions: { [key: string]: any },
|
|
71
|
-
conditions?: IEvaluationCondition[],
|
|
72
|
-
): boolean {
|
|
73
|
-
if (!conditions || conditions.length === 0) return true
|
|
74
|
-
// As stated, at most one condition is supported.
|
|
75
|
-
const condition = conditions[0]
|
|
76
|
-
|
|
77
|
-
// Currently only the Equal operator is supported.
|
|
78
|
-
return dataToCheckConditions[condition.field] === condition.value
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// Helper to combine values using the operator.
|
|
82
|
-
function applyOperator(operator: EvaluationOperatorsEnum, values: number[]): number {
|
|
83
|
-
if (values.length === 0) return 0
|
|
84
|
-
let result = values[0]
|
|
85
|
-
for (let i = 1; i < values.length; i++) {
|
|
86
|
-
const value = values[i]
|
|
87
|
-
switch (operator) {
|
|
88
|
-
case EvaluationOperatorsEnum.Add:
|
|
89
|
-
result += value
|
|
90
|
-
break
|
|
91
|
-
case EvaluationOperatorsEnum.Subtract:
|
|
92
|
-
result -= value
|
|
93
|
-
break
|
|
94
|
-
case EvaluationOperatorsEnum.Multiply:
|
|
95
|
-
result *= value
|
|
96
|
-
break
|
|
97
|
-
case EvaluationOperatorsEnum.Divide:
|
|
98
|
-
result /= value
|
|
99
|
-
break
|
|
100
|
-
default:
|
|
101
|
-
throw new Error(`Unsupported operator: ${operator}`)
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
return result
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// Object to store results from each evaluation by its id.
|
|
108
|
-
const evaluationResults: { [id: string]: number } = {}
|
|
109
|
-
|
|
110
|
-
// Process each evaluation in the config.
|
|
111
|
-
for (const evaluation of config.evaluations) {
|
|
112
|
-
// Evaluation based on fields (IEvaluationOnField)
|
|
113
|
-
if (evaluation.type === EvaluationValueTypeEnum.Fields) {
|
|
114
|
-
// If a condition exists and fails, treat the result as 0.
|
|
115
|
-
if (!checkConditions(data, evaluation.conditions)) {
|
|
116
|
-
evaluationResults[evaluation.id] = 0
|
|
117
|
-
continue
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
const evalFields = (evaluation as IEvaluationOnField).fields
|
|
121
|
-
// For each field, take the value from data (using default if missing)
|
|
122
|
-
const values = evalFields.map((fieldConfig) => {
|
|
123
|
-
const value = data[fieldConfig.field]
|
|
124
|
-
return value !== undefined && value !== null ? value : fieldConfig.defaultValue ?? 0
|
|
125
|
-
})
|
|
126
|
-
evaluationResults[evaluation.id] = applyOperator(evaluation.operator, values)
|
|
127
|
-
}
|
|
128
|
-
// Evaluation based on a list (IEvaluationOnList)
|
|
129
|
-
else if (evaluation.type === EvaluationValueTypeEnum.List) {
|
|
130
|
-
const listData = data[(evaluation as IEvaluationOnList).list]
|
|
131
|
-
if (Array.isArray(listData)) {
|
|
132
|
-
const values = listData.map((item, itemIdx) => {
|
|
133
|
-
const listItemData = listData[itemIdx]
|
|
134
|
-
if (!checkConditions(listItemData, evaluation.conditions)) return 0
|
|
135
|
-
|
|
136
|
-
const fieldValue = item[(evaluation as IEvaluationOnList).listField.field]
|
|
137
|
-
|
|
138
|
-
return fieldValue !== undefined && fieldValue !== null
|
|
139
|
-
? fieldValue
|
|
140
|
-
: (evaluation as IEvaluationOnList).listField.defaultValue ?? 0
|
|
141
|
-
})
|
|
142
|
-
evaluationResults[evaluation.id] = applyOperator(evaluation.operator, values)
|
|
143
|
-
} else {
|
|
144
|
-
evaluationResults[evaluation.id] = 0
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// Determine and return the final result.
|
|
150
|
-
// If evaluationGroups is provided, use the last one as the final evaluation.
|
|
151
|
-
if (config.evaluationGroups && config.evaluationGroups.length > 0) {
|
|
152
|
-
const finalGroup = config.evaluationGroups[config.evaluationGroups.length - 1]
|
|
153
|
-
// Retrieve results for the evaluation IDs in the group (defaulting to 0 if missing)
|
|
154
|
-
const groupValues = finalGroup.evaluationIds.map((id) => evaluationResults[id] ?? 0)
|
|
155
|
-
return applyOperator(finalGroup.operator, groupValues)
|
|
156
|
-
}
|
|
157
|
-
// Otherwise, return the result from the last evaluation.
|
|
158
|
-
else if (config.evaluations.length > 0) {
|
|
159
|
-
const lastEvaluation = config.evaluations[config.evaluations.length - 1]
|
|
160
|
-
return evaluationResults[lastEvaluation.id]
|
|
161
|
-
}
|
|
162
|
-
return 0
|
|
163
|
-
}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import { Form } from 'antd'
|
|
2
1
|
import { useCallback, useState } from 'react'
|
|
3
2
|
import ReCAPTCHA from 'react-google-recaptcha'
|
|
4
3
|
import client from '../../../../functions/axios-handler'
|
|
5
|
-
import { FormPreservedItemKeys } from '../../../../enums'
|
|
6
4
|
import { IElementBaseProps } from '.'
|
|
7
5
|
import { IReCaptchaElementProps } from '../../../../types'
|
|
8
6
|
import { IFormContext } from '../1-row'
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { FormInstance } from 'antd'
|
|
2
1
|
import { useCallback, useEffect, useMemo, useState } from 'react'
|
|
3
2
|
import { IFilterByLinkedFormRelPath, IFormLayoutFieldOption, IRadioElement, ISelectElement } from '../../../../types'
|
|
4
3
|
import { FieldElementOptionSourceEnum } from '../../../../enums'
|
|
@@ -168,12 +168,6 @@ export default function LayoutRenderer_LoadFormData({
|
|
|
168
168
|
}
|
|
169
169
|
|
|
170
170
|
if (!hasInitialFetched.current) {
|
|
171
|
-
// client.get(`/api/form/${form.relationshipConfig.formId}`).then((res) => {
|
|
172
|
-
// if (res.status === 200) {
|
|
173
|
-
// const { relationships: allRelationships, detailsConfig = { layout: [] } } = JSON.parse(res.data.data)
|
|
174
|
-
// }
|
|
175
|
-
// c})
|
|
176
|
-
|
|
177
171
|
fetchFormDetails(
|
|
178
172
|
form.id,
|
|
179
173
|
form.relationshipConfig.formId,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Divider
|
|
1
|
+
import { Divider } from 'antd'
|
|
2
2
|
import { memo, ReactElement, ReactNode, useEffect, useMemo } from 'react'
|
|
3
3
|
import { IDataRender_ButtonProps, IFormLayoutElement, IReadFieldDataElementProps } from '../../../../types'
|
|
4
4
|
import { getElementGeneralizedProps } from '../../../../functions/get-element-props'
|
|
@@ -15,6 +15,7 @@ import { IFormLayoutElementConditions } from '../../../../types/layout-elements/
|
|
|
15
15
|
import LayoutRenderer_FieldsWithOptions from './8-fields-with-options'
|
|
16
16
|
import LayoutRenderer_LoadFormData from './9-form-data-render'
|
|
17
17
|
import { IFormContext } from '../1-row'
|
|
18
|
+
import LayoutRenderer_CurrencyField from './10-currency'
|
|
18
19
|
|
|
19
20
|
function LayoutRendererElementWrapper({
|
|
20
21
|
hideElement,
|
|
@@ -141,6 +142,9 @@ function LayoutRendererElement({
|
|
|
141
142
|
case ElementTypeEnum.LoadFormData:
|
|
142
143
|
return <LayoutRenderer_LoadFormData elementProps={props} formContext={formContext} {...elementBaseProps} />
|
|
143
144
|
|
|
145
|
+
case ElementTypeEnum.CurrencyInput:
|
|
146
|
+
return <LayoutRenderer_CurrencyField elementData={elementData} formContext={formContext} {...elementBaseProps} />
|
|
147
|
+
|
|
144
148
|
default:
|
|
145
149
|
return (
|
|
146
150
|
<LayoutRenderer_FieldElement
|
package/src/enums.ts
CHANGED
|
@@ -126,6 +126,7 @@ export enum ButtonElementSizeEnum {
|
|
|
126
126
|
}
|
|
127
127
|
export enum FieldElementOptionSourceEnum {
|
|
128
128
|
Static = 'Static',
|
|
129
|
+
ReadFromDetails = 'ReadFromDetails',
|
|
129
130
|
DynamicForm = 'DynamicForm',
|
|
130
131
|
LinkedForm = 'LinkedForm',
|
|
131
132
|
}
|
|
@@ -140,7 +141,7 @@ export enum ButtonActionCategoryEnum {
|
|
|
140
141
|
DuplicateData = 'duplicate-data',
|
|
141
142
|
SaveDataChanges = 'save-data-changes',
|
|
142
143
|
PublishDataChanges = 'publish-data-changes',
|
|
143
|
-
|
|
144
|
+
ReturnOneBack = 'return-one-back',
|
|
144
145
|
ViewDataVersions = 'view-data-versions',
|
|
145
146
|
GenerateReport = 'generate-report',
|
|
146
147
|
CustomFunction = 'custom-function',
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { EvaluationOperatorsEnum, EvaluationValueTypeEnum } from '../enums'
|
|
2
|
+
import { IEvaluationCondition, IEvaluationConfig, IEvaluationOnField, IEvaluationOnList } from '../types'
|
|
3
|
+
|
|
4
|
+
export const evaluateValue = (config: IEvaluationConfig, data: { [key: string]: any }): number => {
|
|
5
|
+
// Helper to check an evaluation’s condition (if any)
|
|
6
|
+
function checkConditions(
|
|
7
|
+
dataToCheckConditions: { [key: string]: any },
|
|
8
|
+
conditions?: IEvaluationCondition[],
|
|
9
|
+
): boolean {
|
|
10
|
+
if (!conditions || conditions.length === 0) return true
|
|
11
|
+
// As stated, at most one condition is supported.
|
|
12
|
+
const condition = conditions[0]
|
|
13
|
+
|
|
14
|
+
// Currently only the Equal operator is supported.
|
|
15
|
+
return dataToCheckConditions[condition.field] === condition.value
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Helper to combine values using the operator.
|
|
19
|
+
function applyOperator(operator: EvaluationOperatorsEnum, values: number[]): number {
|
|
20
|
+
if (values.length === 0) return 0
|
|
21
|
+
let result = values[0]
|
|
22
|
+
for (let i = 1; i < values.length; i++) {
|
|
23
|
+
const value = values[i]
|
|
24
|
+
switch (operator) {
|
|
25
|
+
case EvaluationOperatorsEnum.Add:
|
|
26
|
+
result += value
|
|
27
|
+
break
|
|
28
|
+
case EvaluationOperatorsEnum.Subtract:
|
|
29
|
+
result -= value
|
|
30
|
+
break
|
|
31
|
+
case EvaluationOperatorsEnum.Multiply:
|
|
32
|
+
result *= value
|
|
33
|
+
break
|
|
34
|
+
case EvaluationOperatorsEnum.Divide:
|
|
35
|
+
result /= value
|
|
36
|
+
break
|
|
37
|
+
default:
|
|
38
|
+
throw new Error(`Unsupported operator: ${operator}`)
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return result
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Object to store results from each evaluation by its id.
|
|
45
|
+
const evaluationResults: { [id: string]: number } = {}
|
|
46
|
+
|
|
47
|
+
// Process each evaluation in the config.
|
|
48
|
+
for (const evaluation of config.evaluations) {
|
|
49
|
+
// Evaluation based on fields (IEvaluationOnField)
|
|
50
|
+
if (evaluation.type === EvaluationValueTypeEnum.Fields) {
|
|
51
|
+
// If a condition exists and fails, treat the result as 0.
|
|
52
|
+
if (!checkConditions(data, evaluation.conditions)) {
|
|
53
|
+
evaluationResults[evaluation.id] = 0
|
|
54
|
+
continue
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const evalFields = (evaluation as IEvaluationOnField).fields
|
|
58
|
+
// For each field, take the value from data (using default if missing)
|
|
59
|
+
const values = evalFields.map((fieldConfig) => {
|
|
60
|
+
const value = data[fieldConfig.field]
|
|
61
|
+
return value !== undefined && value !== null ? value : fieldConfig.defaultValue ?? 0
|
|
62
|
+
})
|
|
63
|
+
evaluationResults[evaluation.id] = applyOperator(evaluation.operator, values)
|
|
64
|
+
}
|
|
65
|
+
// Evaluation based on a list (IEvaluationOnList)
|
|
66
|
+
else if (evaluation.type === EvaluationValueTypeEnum.List) {
|
|
67
|
+
const listData = data[(evaluation as IEvaluationOnList).list]
|
|
68
|
+
if (Array.isArray(listData)) {
|
|
69
|
+
const values = listData.map((item, itemIdx) => {
|
|
70
|
+
const listItemData = listData[itemIdx]
|
|
71
|
+
if (!checkConditions(listItemData, evaluation.conditions)) return 0
|
|
72
|
+
|
|
73
|
+
const fieldValue = item[(evaluation as IEvaluationOnList).listField.field]
|
|
74
|
+
|
|
75
|
+
return fieldValue !== undefined && fieldValue !== null
|
|
76
|
+
? fieldValue
|
|
77
|
+
: (evaluation as IEvaluationOnList).listField.defaultValue ?? 0
|
|
78
|
+
})
|
|
79
|
+
evaluationResults[evaluation.id] = applyOperator(evaluation.operator, values)
|
|
80
|
+
} else {
|
|
81
|
+
evaluationResults[evaluation.id] = 0
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Determine and return the final result.
|
|
87
|
+
// If evaluationGroups is provided, use the last one as the final evaluation.
|
|
88
|
+
if (config.evaluationGroups && config.evaluationGroups.length > 0) {
|
|
89
|
+
const finalGroup = config.evaluationGroups[config.evaluationGroups.length - 1]
|
|
90
|
+
// Retrieve results for the evaluation IDs in the group (defaulting to 0 if missing)
|
|
91
|
+
const groupValues = finalGroup.evaluationIds.map((id) => evaluationResults[id] ?? 0)
|
|
92
|
+
return applyOperator(finalGroup.operator, groupValues)
|
|
93
|
+
}
|
|
94
|
+
// Otherwise, return the result from the last evaluation.
|
|
95
|
+
else if (config.evaluations.length > 0) {
|
|
96
|
+
const lastEvaluation = config.evaluations[config.evaluations.length - 1]
|
|
97
|
+
return evaluationResults[lastEvaluation.id]
|
|
98
|
+
}
|
|
99
|
+
return 0
|
|
100
|
+
}
|
package/src/functions/index.ts
CHANGED
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
IOptionSourceConstant,
|
|
14
14
|
IOptionSourceForm,
|
|
15
15
|
IFormData,
|
|
16
|
+
IOptionSourceReadFromDetails,
|
|
16
17
|
} from '../types'
|
|
17
18
|
import client from './axios-handler'
|
|
18
19
|
export * from './create-form-rules'
|
|
@@ -116,6 +117,71 @@ export const extractDateFields = (layout: IFormLayoutRow[]): string[] => {
|
|
|
116
117
|
return dateFieldKeys.filter((s) => !!s)
|
|
117
118
|
}
|
|
118
119
|
|
|
120
|
+
export const appendOptionsFromDetailsLayout = (
|
|
121
|
+
headerLayout: IFormLayoutRow[],
|
|
122
|
+
detailsLayout: IFormLayoutRow[],
|
|
123
|
+
): IFormLayoutRow[] => {
|
|
124
|
+
function findNodeByKey(
|
|
125
|
+
node: IFormLayoutRow | IFormLayoutCol | IFormLayoutElement,
|
|
126
|
+
key: string,
|
|
127
|
+
): ISelectElement | IRadioElement | null {
|
|
128
|
+
// Only check for the key if the nodeType is not "Row" or "Col"
|
|
129
|
+
if (node.nodeType !== FormLayoutNodeEnum.Row && node.nodeType !== FormLayoutNodeEnum.Col) {
|
|
130
|
+
if (node.elementType === ElementTypeEnum.Select || node.elementType === ElementTypeEnum.Radio) return node
|
|
131
|
+
return null
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// If the node has children, traverse them recursively
|
|
135
|
+
if (node.children) {
|
|
136
|
+
for (const child of node.children) {
|
|
137
|
+
const found = findNodeByKey(child, key)
|
|
138
|
+
if (found) return found
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return null
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function traverseAndSearch(
|
|
145
|
+
node: IFormLayoutRow | IFormLayoutCol | IFormLayoutElement,
|
|
146
|
+
): IFormLayoutRow | IFormLayoutCol | IFormLayoutElement {
|
|
147
|
+
if (node.nodeType === FormLayoutNodeEnum.Row || node.nodeType === FormLayoutNodeEnum.Col)
|
|
148
|
+
return {
|
|
149
|
+
...node,
|
|
150
|
+
children: node.children.map((nodeChild) => traverseAndSearch(nodeChild)),
|
|
151
|
+
} as IFormLayoutRow | IFormLayoutCol
|
|
152
|
+
|
|
153
|
+
if (![ElementTypeEnum.Select, ElementTypeEnum.Radio].includes(node.elementType)) return node as IFormLayoutElement
|
|
154
|
+
|
|
155
|
+
const optionSource = (node as ISelectElement | IRadioElement).props.optionSource
|
|
156
|
+
if (!optionSource || optionSource.type !== FieldElementOptionSourceEnum.ReadFromDetails) return node as IFormLayoutElement
|
|
157
|
+
|
|
158
|
+
const fieldKey = ((node as ISelectElement | IRadioElement).props.optionSource as IOptionSourceReadFromDetails)
|
|
159
|
+
?.field
|
|
160
|
+
|
|
161
|
+
let field: ISelectElement | IRadioElement | null = null
|
|
162
|
+
detailsLayout.forEach((row) => {
|
|
163
|
+
field = findNodeByKey(row, fieldKey)
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
const options =
|
|
167
|
+
field && [ElementTypeEnum.Select, ElementTypeEnum.Radio].includes((field as IFormLayoutElement).elementType)
|
|
168
|
+
? ((field as ISelectElement | IRadioElement).props.optionSource as IOptionSourceConstant).options ?? []
|
|
169
|
+
: []
|
|
170
|
+
|
|
171
|
+
return {
|
|
172
|
+
...node,
|
|
173
|
+
props: node.props
|
|
174
|
+
? {
|
|
175
|
+
...node.props,
|
|
176
|
+
optionSource: { type: FieldElementOptionSourceEnum.Static, options },
|
|
177
|
+
}
|
|
178
|
+
: {},
|
|
179
|
+
} as ISelectElement | IRadioElement
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return headerLayout.map((node) => traverseAndSearch(node)) as IFormLayoutRow[]
|
|
183
|
+
}
|
|
184
|
+
|
|
119
185
|
/** --------------------------------------------------------------------------------------------------------- */
|
|
120
186
|
|
|
121
187
|
export const getFlexContainerStyle = (device: ResponsivenessDeviceEnum, responsiveness?: IFlexConfig) =>
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { IFilterConfig } from '..'
|
|
2
2
|
import { FieldElementOptionSourceEnum } from '../../enums'
|
|
3
3
|
|
|
4
|
-
export type IFieldElementOptionSource =
|
|
4
|
+
export type IFieldElementOptionSource =
|
|
5
|
+
| IOptionSourceConstant
|
|
6
|
+
| IOptionSourceForm
|
|
7
|
+
| IOptionSourceReadFromDetails
|
|
8
|
+
| IOptionSourceLinkedForm
|
|
5
9
|
|
|
6
10
|
export interface IOptionSourceConstant {
|
|
7
11
|
type: FieldElementOptionSourceEnum.Static
|
|
@@ -23,3 +27,12 @@ export interface IOptionSourceFormInfo {
|
|
|
23
27
|
formName: string
|
|
24
28
|
field: string
|
|
25
29
|
}
|
|
30
|
+
|
|
31
|
+
export interface IOptionSourceReadFromDetails {
|
|
32
|
+
type: FieldElementOptionSourceEnum.ReadFromDetails
|
|
33
|
+
field: string
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface IOptionSourceLinkedForm {
|
|
37
|
+
type: FieldElementOptionSourceEnum.LinkedForm
|
|
38
|
+
}
|
|
@@ -101,6 +101,7 @@ export interface ICurrencyInputElementProps {
|
|
|
101
101
|
description?: string
|
|
102
102
|
country?: CountryEnum
|
|
103
103
|
decimalPoint?: number
|
|
104
|
+
evaluationConfig?: IEvaluationConfig
|
|
104
105
|
}
|
|
105
106
|
|
|
106
107
|
/** -------------------------------------------------------------------------------------------- */
|