form-craft-package 1.7.9-dev.2 → 1.7.10-dev.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.ts +4 -1
- package/package.json +4 -4
- package/src/api/client.ts +10 -0
- package/src/components/common/countdown.tsx +44 -0
- package/src/components/common/custom-hooks/index.ts +2 -0
- package/src/components/common/custom-hooks/use-breadcrumb.hook.ts +18 -0
- package/src/components/common/custom-hooks/use-check-element-conditions.hook.ts +3 -2
- package/src/components/common/custom-hooks/use-dayjs-extender.hook.ts +8 -0
- package/src/components/common/custom-hooks/use-many-to-many-connector.hook.ts +2 -3
- package/src/components/common/custom-hooks/use-notification.hook.tsx +1 -1
- package/src/components/common/custom-hooks/use-window-width.hook.ts +6 -4
- package/src/components/common/loading-skeletons/details.tsx +61 -6
- package/src/components/common/loading-skeletons/index.tsx +10 -2
- package/src/components/form/1-list/index.tsx +32 -17
- package/src/components/form/1-list/table-header.tsx +29 -55
- package/src/components/form/1-list/table.tsx +3 -5
- package/src/components/form/2-details/index.tsx +26 -26
- package/src/components/form/layout-renderer/1-row/index.tsx +9 -7
- package/src/components/form/layout-renderer/3-element/1-dynamic-button/index.tsx +25 -19
- package/src/components/form/layout-renderer/3-element/1-dynamic-button/use-button-navigate.hook.tsx +11 -5
- package/src/components/form/layout-renderer/3-element/1-dynamic-button/use-custom-function-call.hook.ts +22 -0
- package/src/components/form/layout-renderer/3-element/1-dynamic-button/use-generate-report.hook.tsx +2 -2
- package/src/components/form/layout-renderer/3-element/2-field-element.tsx +40 -6
- package/src/components/form/layout-renderer/3-element/5-re-captcha.tsx +1 -1
- package/src/components/form/layout-renderer/3-element/6-signature.tsx +2 -3
- package/src/components/form/layout-renderer/3-element/8-fields-with-options.tsx +142 -61
- package/src/components/form/layout-renderer/3-element/9-form-data-render.tsx +34 -27
- package/src/components/form/layout-renderer/3-element/index.tsx +3 -0
- package/src/components/index.tsx +2 -0
- package/src/components/modals/pdf-preview.modal.tsx +41 -0
- package/src/constants.ts +1 -0
- package/src/enums/form.enum.ts +8 -7
- package/src/enums/index.ts +1 -0
- package/src/functions/forms/conditional-rule-validator.ts +2 -0
- package/src/functions/forms/data-render-functions.tsx +21 -6
- package/src/functions/forms/get-data-list-option-value.ts +3 -3
- package/src/functions/forms/index.ts +33 -4
- package/src/functions/forms/linked-form-joins.ts +19 -0
- package/src/functions/reports/create-blob-url.ts +16 -0
- package/src/functions/reports/index.tsx +1 -0
- package/src/types/forms/data-list/filter-config.ts +5 -16
- package/src/types/forms/data-list/index.ts +2 -0
- package/src/types/forms/index.ts +0 -1
- package/src/types/forms/layout-elements/data-render-config.ts +5 -5
- package/src/types/forms/layout-elements/field-option-source.ts +25 -10
- package/src/types/forms/layout-elements/index.ts +7 -1
- package/src/types/forms/layout-elements/style.ts +0 -4
- package/src/types/forms/relationship/index.ts +6 -6
- package/src/types/index.ts +2 -0
- package/src/functions/forms/breadcrumb-handlers.ts +0 -21
|
@@ -1,18 +1,22 @@
|
|
|
1
1
|
import { Form } from 'antd'
|
|
2
2
|
import { useCallback, useEffect, useMemo, useState } from 'react'
|
|
3
3
|
import { IDndLayoutStructure_Responsive, IFormSchema } from '../../../types'
|
|
4
|
-
import { NEW_FORM_DATA_IDENTIFIER } from '../../../constants'
|
|
5
4
|
import { LayoutRendererRow } from '../layout-renderer/1-row'
|
|
6
5
|
import { DynamicFormButtonRender, ICustomFunctionCall } from '../layout-renderer/3-element/1-dynamic-button'
|
|
7
6
|
import FormDataListSkeleton_Details from '../../common/loading-skeletons/details'
|
|
8
7
|
import { useLocation } from 'react-router-dom'
|
|
9
|
-
import { fromMongoDbExtendedJSON, isValidMongoDbId, queryParamsToObject } from '../../../functions/forms'
|
|
10
8
|
import { DeviceBreakpointEnum, FormPreservedItemKeys, LOCAL_STORAGE_KEYS_ENUM } from '../../../enums'
|
|
11
9
|
import useGetCurrentBreakpoint from '../../common/custom-hooks/use-window-width.hook'
|
|
12
10
|
import client from '../../../api/client'
|
|
13
11
|
import { useBreadcrumb } from '../../common/custom-hooks/use-breadcrumb.hook'
|
|
14
12
|
import NotFound from '../../common/not-found'
|
|
15
13
|
import { useManyToManyConnector } from '../../common/custom-hooks/use-many-to-many-connector.hook'
|
|
14
|
+
import {
|
|
15
|
+
fromMongoDbExtendedJSON,
|
|
16
|
+
isNewFormDataPage,
|
|
17
|
+
isValidMongoDbId,
|
|
18
|
+
queryParamsToObject,
|
|
19
|
+
} from '../../../functions/forms'
|
|
16
20
|
|
|
17
21
|
export default function FormDataDetailsComponent({
|
|
18
22
|
isPublic,
|
|
@@ -46,10 +50,9 @@ export default function FormDataDetailsComponent({
|
|
|
46
50
|
}, [formDataId])
|
|
47
51
|
|
|
48
52
|
useEffect(() => {
|
|
49
|
-
const isNewDataPage = formDataId === NEW_FORM_DATA_IDENTIFIER
|
|
50
53
|
const splittedFormName = formName?.split(' ')?.[0] ?? ''
|
|
51
54
|
push({
|
|
52
|
-
label:
|
|
55
|
+
label: isNewFormDataPage(formDataId) ? `New ${splittedFormName.toLowerCase()}` : `${splittedFormName} details`,
|
|
53
56
|
href: location.pathname,
|
|
54
57
|
})
|
|
55
58
|
}, [location.pathname, formName, formDataId])
|
|
@@ -61,7 +64,7 @@ export default function FormDataDetailsComponent({
|
|
|
61
64
|
|
|
62
65
|
// Apply initialValues from parent
|
|
63
66
|
useEffect(() => {
|
|
64
|
-
if (initialValues && formDataId
|
|
67
|
+
if (initialValues && isNewFormDataPage(formDataId)) {
|
|
65
68
|
formDataRef.setFieldsValue(initialValues)
|
|
66
69
|
}
|
|
67
70
|
}, [initialValues, formDataId, formDataRef])
|
|
@@ -85,8 +88,7 @@ export default function FormDataDetailsComponent({
|
|
|
85
88
|
|
|
86
89
|
const fetchFormData = useCallback(
|
|
87
90
|
(dFormId?: number) => {
|
|
88
|
-
if (formDataId
|
|
89
|
-
setLoadings((c) => ({ ...c, data: false }))
|
|
91
|
+
if (isNewFormDataPage(formDataId) || !isValidMongoDbId(formDataId)) setLoadings((c) => ({ ...c, data: false }))
|
|
90
92
|
else {
|
|
91
93
|
if (!dFormId) {
|
|
92
94
|
console.error('Form ID is required to fetch form data')
|
|
@@ -151,25 +153,23 @@ export default function FormDataDetailsComponent({
|
|
|
151
153
|
if (isNotFound) return <NotFound />
|
|
152
154
|
|
|
153
155
|
return (
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
</Form>
|
|
172
|
-
</>
|
|
156
|
+
<Form layout="vertical" name="dynamic_form_data_form" form={formDataRef}>
|
|
157
|
+
{layout.map((row, rowIdx) => (
|
|
158
|
+
<LayoutRendererRow
|
|
159
|
+
key={rowIdx}
|
|
160
|
+
rowData={row}
|
|
161
|
+
formContext={formContext}
|
|
162
|
+
elements={layoutConfig.elements}
|
|
163
|
+
renderButton={(btnProps, conditions) => (
|
|
164
|
+
<DynamicFormButtonRender
|
|
165
|
+
displayStateProps={{ btnProps, conditions, defaultDisabled: true }}
|
|
166
|
+
formContext={formContext}
|
|
167
|
+
onCustomFunctionCall={onCustomFunctionCall}
|
|
168
|
+
/>
|
|
169
|
+
)}
|
|
170
|
+
/>
|
|
171
|
+
))}
|
|
172
|
+
</Form>
|
|
173
173
|
)
|
|
174
174
|
}
|
|
175
175
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FormInstance } from 'antd'
|
|
2
|
-
import {
|
|
2
|
+
import { getGridContainerStyle, getColumnStyle, kebabCaseToCamelCase } from '../../../../functions/forms'
|
|
3
3
|
import LayoutRendererCol from '../2-col'
|
|
4
4
|
import { memo, ReactElement, ReactNode, useEffect, useMemo, useRef, useState } from 'react'
|
|
5
5
|
import { LayoutRowConditionalHeaderRenderer } from './header-render'
|
|
@@ -26,14 +26,15 @@ export const LayoutRendererRow = memo(
|
|
|
26
26
|
if (hideCol) hideCol(hiddenElementCount === rowData.children.length)
|
|
27
27
|
}, [hiddenElementCount, JSON.stringify(rowData.children)])
|
|
28
28
|
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
return () => setHiddenElementCount(0)
|
|
31
|
+
}, [])
|
|
32
|
+
|
|
29
33
|
return (
|
|
30
34
|
<LayoutRowConditionalHeaderRenderer header={rowData.props?.header}>
|
|
31
35
|
<LayoutRowRepeatableRenderer basePath={basePath} repeatingSection={rowData.props?.repeatingSection}>
|
|
32
36
|
{(formListItemProps) => {
|
|
33
|
-
const style: { [key: string]: any } = {
|
|
34
|
-
...styleConfig,
|
|
35
|
-
...getFlexContainerStyle(rowData.display),
|
|
36
|
-
}
|
|
37
|
+
const style: { [key: string]: any } = { ...styleConfig, ...getGridContainerStyle(rowData.display) }
|
|
37
38
|
|
|
38
39
|
if (hiddenElementCount === rowData.children.length) return <></>
|
|
39
40
|
|
|
@@ -62,7 +63,7 @@ export const LayoutRendererRow = memo(
|
|
|
62
63
|
formContext={formContext}
|
|
63
64
|
colStyle={getColumnStyle(colIdx, rowData.display)}
|
|
64
65
|
renderButton={renderButton}
|
|
65
|
-
hideRow={(isHidden) =>
|
|
66
|
+
hideRow={(isHidden) => {
|
|
66
67
|
setHiddenElementCount((c) => {
|
|
67
68
|
if (isHidden) {
|
|
68
69
|
hiddenColIdx.current = [...hiddenColIdx.current, colIdx]
|
|
@@ -72,7 +73,7 @@ export const LayoutRendererRow = memo(
|
|
|
72
73
|
return c - 1
|
|
73
74
|
}
|
|
74
75
|
})
|
|
75
|
-
}
|
|
76
|
+
}}
|
|
76
77
|
/>
|
|
77
78
|
))}
|
|
78
79
|
{formListItemProps?.removeButton}
|
|
@@ -102,6 +103,7 @@ export interface IFormContext {
|
|
|
102
103
|
formName?: string // only passed in DynamicButton component
|
|
103
104
|
formKey?: string
|
|
104
105
|
formId?: number
|
|
106
|
+
detailPageFormId?: number
|
|
105
107
|
parentFormJoins?: IFormJoin[]
|
|
106
108
|
manyToManyRelInfo?: { middleFormId: number; currentFormId: number; otherFormId: number } | null
|
|
107
109
|
}
|
|
@@ -10,7 +10,6 @@ import { useCreateDataWithPdfActions } from './use-create-data.hook'
|
|
|
10
10
|
import { useSaveExistingDataAction } from './use-save-data.hook'
|
|
11
11
|
import { useGenerateReportAction } from './use-generate-report.hook'
|
|
12
12
|
import { useSaveSignatureAction } from './use-save-signature.hook'
|
|
13
|
-
import { NEW_FORM_DATA_IDENTIFIER } from '../../../../../constants'
|
|
14
13
|
import { Button_FillerPortal } from '../../../../common/button'
|
|
15
14
|
import { getButtonRenderProps } from '../../../../../functions/forms/get-element-props'
|
|
16
15
|
import WarningIcon from '../../../../common/warning-icon'
|
|
@@ -18,7 +17,8 @@ import FormDataLoadingIndicatorModal from '../../../../modals/form-data-loading.
|
|
|
18
17
|
import { IFormContext } from '../../1-row'
|
|
19
18
|
import { ButtonActionCategoryEnum, FormLoadingModalTypeEnum } from '../../../../../enums'
|
|
20
19
|
import { useButtonNavigateAction } from './use-button-navigate.hook'
|
|
21
|
-
import { constructDynamicFormHref } from '../../../../../functions'
|
|
20
|
+
import { constructDynamicFormHref, isNewFormDataPage } from '../../../../../functions'
|
|
21
|
+
import { useCustomFunctionCallAction } from './use-custom-function-call.hook'
|
|
22
22
|
import {
|
|
23
23
|
IButtonElementProps,
|
|
24
24
|
IFormLayoutElementConditions,
|
|
@@ -60,8 +60,9 @@ export const DynamicFormButtonRender = memo((props: IDynamicButton) => {
|
|
|
60
60
|
|
|
61
61
|
const handleSecondaryAction = useCallback(
|
|
62
62
|
(formDataId?: string) => {
|
|
63
|
-
if (!btnProps.secondaryAction) {
|
|
64
|
-
if (formInfo?.name
|
|
63
|
+
if (!btnProps.secondaryAction || Object.values(btnProps.secondaryAction).length === 0) {
|
|
64
|
+
if (formInfo?.name && formDataId)
|
|
65
|
+
navigate(`${constructDynamicFormHref(formInfo.name)}/${formDataId}`, { replace: true })
|
|
65
66
|
setTimeout(() => {
|
|
66
67
|
setDataLoadingType(undefined)
|
|
67
68
|
displayResultMessage()
|
|
@@ -72,7 +73,7 @@ export const DynamicFormButtonRender = memo((props: IDynamicButton) => {
|
|
|
72
73
|
const { category } = btnProps.secondaryAction
|
|
73
74
|
if (category === ButtonActionCategoryEnum.Navigate) onButtonNavigate(btnProps.secondaryAction)
|
|
74
75
|
else if (category === ButtonActionCategoryEnum.CustomFunction) {
|
|
75
|
-
|
|
76
|
+
onFunctionCall(btnProps.secondaryAction.functionName, btnProps.messages ?? defaultMessage)
|
|
76
77
|
setTimeout(() => setLoading(false), 500)
|
|
77
78
|
}
|
|
78
79
|
},
|
|
@@ -105,16 +106,23 @@ export const DynamicFormButtonRender = memo((props: IDynamicButton) => {
|
|
|
105
106
|
setLoading(false)
|
|
106
107
|
},
|
|
107
108
|
onSuccess: (formDataId?: string) => handleSecondaryAction(formDataId),
|
|
108
|
-
onError: () =>
|
|
109
|
+
onError: () => {
|
|
110
|
+
setDataLoadingType(undefined)
|
|
111
|
+
displayResultMessage(false)
|
|
112
|
+
},
|
|
109
113
|
onFinal: () => setLoading(false),
|
|
110
114
|
})
|
|
111
115
|
const onSaveExistingData = useSaveExistingDataAction({
|
|
112
116
|
...formContext,
|
|
113
117
|
setDataLoadingType,
|
|
114
118
|
onSuccess: () => handleSecondaryAction(),
|
|
115
|
-
onError: () =>
|
|
119
|
+
onError: () => {
|
|
120
|
+
setDataLoadingType(undefined)
|
|
121
|
+
displayResultMessage(false)
|
|
122
|
+
},
|
|
116
123
|
onFinal: () => setLoading(false),
|
|
117
124
|
})
|
|
125
|
+
const onFunctionCall = useCustomFunctionCallAction({ ...formContext, onCustomFunctionCall })
|
|
118
126
|
const { onGenerateReport, ChooseTemplateReportModal } = useGenerateReportAction({
|
|
119
127
|
...formContext,
|
|
120
128
|
onSuccess: () => {},
|
|
@@ -157,7 +165,7 @@ export const DynamicFormButtonRender = memo((props: IDynamicButton) => {
|
|
|
157
165
|
case ButtonActionCategoryEnum.SaveDataChanges:
|
|
158
166
|
await onSaveSignature()
|
|
159
167
|
|
|
160
|
-
if (formDataId
|
|
168
|
+
if (isNewFormDataPage(formDataId)) {
|
|
161
169
|
if (isPublic && submissionPdfConfig) onGeneratePdfProof()
|
|
162
170
|
else onCreateNewData()
|
|
163
171
|
} else onSaveExistingData()
|
|
@@ -179,7 +187,7 @@ export const DynamicFormButtonRender = memo((props: IDynamicButton) => {
|
|
|
179
187
|
break
|
|
180
188
|
|
|
181
189
|
case ButtonActionCategoryEnum.CustomFunction:
|
|
182
|
-
|
|
190
|
+
onFunctionCall(btnProps.functionName, btnProps.messages)
|
|
183
191
|
setTimeout(() => setLoading(false), 500)
|
|
184
192
|
break
|
|
185
193
|
|
|
@@ -197,7 +205,7 @@ export const DynamicFormButtonRender = memo((props: IDynamicButton) => {
|
|
|
197
205
|
formDataId,
|
|
198
206
|
isPublic,
|
|
199
207
|
submissionPdfConfig,
|
|
200
|
-
|
|
208
|
+
onFunctionCall,
|
|
201
209
|
onDuplicateData,
|
|
202
210
|
onDeleteData,
|
|
203
211
|
onPublishData,
|
|
@@ -222,7 +230,7 @@ export const DynamicFormButtonRender = memo((props: IDynamicButton) => {
|
|
|
222
230
|
if (inPreviewMode) return
|
|
223
231
|
if (
|
|
224
232
|
isPublic &&
|
|
225
|
-
formDataId
|
|
233
|
+
isNewFormDataPage(formDataId) &&
|
|
226
234
|
[ButtonActionCategoryEnum.SaveDataChanges, ButtonActionCategoryEnum.Navigate].includes(btnProps.category)
|
|
227
235
|
)
|
|
228
236
|
return
|
|
@@ -240,7 +248,7 @@ export const DynamicFormButtonRender = memo((props: IDynamicButton) => {
|
|
|
240
248
|
}}
|
|
241
249
|
>
|
|
242
250
|
{isPublic &&
|
|
243
|
-
formDataId
|
|
251
|
+
isNewFormDataPage(formDataId) &&
|
|
244
252
|
btnProps.category !== ButtonActionCategoryEnum.SaveDataChanges && (
|
|
245
253
|
<WarningIcon tooltip={BUTTON_CUSTOM_ERROR_MESSAGES.UnavailableForPublic} />
|
|
246
254
|
)}
|
|
@@ -270,13 +278,11 @@ interface IDynamicButton_DisplayStateProps {
|
|
|
270
278
|
}
|
|
271
279
|
|
|
272
280
|
export interface ICustomFunctionCall {
|
|
273
|
-
onCustomFunctionCall?: (
|
|
274
|
-
fnName
|
|
275
|
-
messages?: {
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
},
|
|
279
|
-
) => void
|
|
281
|
+
onCustomFunctionCall?: (params: {
|
|
282
|
+
fnName: string
|
|
283
|
+
messages?: { success?: string; error?: string }
|
|
284
|
+
formData?: { [key: string]: any }
|
|
285
|
+
}) => void
|
|
280
286
|
}
|
|
281
287
|
export interface IOnSuccessFunctions {
|
|
282
288
|
onSuccess: (formDataId?: string) => void
|
package/src/components/form/layout-renderer/3-element/1-dynamic-button/use-button-navigate.hook.tsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useCallback } from 'react'
|
|
2
2
|
import { IButtonProps_Navigate } from '../../../../../types'
|
|
3
3
|
import { useFindDynamiForm, useNotification } from '../../../../common/custom-hooks'
|
|
4
|
-
import { constructDynamicFormHref } from '../../../../../functions/forms'
|
|
4
|
+
import { constructDynamicFormHref, isNewFormDataPage } from '../../../../../functions/forms'
|
|
5
5
|
import { NavigateButtonCustomComponentType, NavigateButtonTypesEnum } from '../../../../../enums'
|
|
6
6
|
import { IFormContext } from '../../1-row'
|
|
7
7
|
import { BUTTON_CUSTOM_ERROR_MESSAGES, IOnSuccessFunctions } from '.'
|
|
@@ -18,7 +18,7 @@ export const useButtonNavigateAction = ({
|
|
|
18
18
|
onFinal,
|
|
19
19
|
...formContext
|
|
20
20
|
}: IOnSuccessFunctions & IFormContext) => {
|
|
21
|
-
const { formRef, formDataId, parentFormJoins, manyToManyRelInfo } = formContext
|
|
21
|
+
const { formRef, formDataId, detailPageFormId, parentFormJoins, manyToManyRelInfo } = formContext
|
|
22
22
|
const { getFormById } = useFindDynamiForm()
|
|
23
23
|
const { error } = useNotification()
|
|
24
24
|
const { updateCrumb } = useBreadcrumb()
|
|
@@ -32,14 +32,20 @@ export const useButtonNavigateAction = ({
|
|
|
32
32
|
switch (btnProps.navigateType) {
|
|
33
33
|
case NavigateButtonTypesEnum.NewDataPage:
|
|
34
34
|
let newDatapageNavigateUrl = `${baseDynamicUrl}/${NEW_FORM_DATA_IDENTIFIER}`
|
|
35
|
+
|
|
35
36
|
if (manyToManyRelInfo && parentFormJoins && formDataId) {
|
|
36
37
|
const middleFormInfo = getFormById(manyToManyRelInfo.middleFormId)
|
|
37
38
|
|
|
38
39
|
if (middleFormInfo)
|
|
39
40
|
newDatapageNavigateUrl = `${constructDynamicFormHref(middleFormInfo.name)}/${NEW_FORM_DATA_IDENTIFIER}`
|
|
40
41
|
}
|
|
41
|
-
if (formDataId
|
|
42
|
-
updateCrumb(location.pathname, {
|
|
42
|
+
if (!isNewFormDataPage(formDataId))
|
|
43
|
+
updateCrumb(location.pathname, {
|
|
44
|
+
formJoins: parentFormJoins,
|
|
45
|
+
detailPageFormId,
|
|
46
|
+
formDataId,
|
|
47
|
+
manyToManyRelInfo,
|
|
48
|
+
})
|
|
43
49
|
|
|
44
50
|
navigate(newDatapageNavigateUrl)
|
|
45
51
|
break
|
|
@@ -81,7 +87,7 @@ export const useButtonNavigateAction = ({
|
|
|
81
87
|
break
|
|
82
88
|
}
|
|
83
89
|
},
|
|
84
|
-
[parentFormJoins, manyToManyRelInfo, formRef],
|
|
90
|
+
[parentFormJoins, detailPageFormId, manyToManyRelInfo, formRef],
|
|
85
91
|
)
|
|
86
92
|
|
|
87
93
|
return onButtonNavigate
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { useCallback } from 'react'
|
|
2
|
+
import { IFormContext } from '../../1-row'
|
|
3
|
+
import { ICustomFunctionCall } from '.'
|
|
4
|
+
|
|
5
|
+
export const useCustomFunctionCallAction = ({
|
|
6
|
+
formRef,
|
|
7
|
+
formDataId,
|
|
8
|
+
formId,
|
|
9
|
+
onCustomFunctionCall,
|
|
10
|
+
}: IFormContext & ICustomFunctionCall) => {
|
|
11
|
+
const onFunctionCall = useCallback(
|
|
12
|
+
async (functionName: string, messages?: { success?: string; error?: string }) => {
|
|
13
|
+
let formData: { [key: string]: any } | undefined = undefined
|
|
14
|
+
if (formRef) formData = await formRef.validateFields()
|
|
15
|
+
|
|
16
|
+
onCustomFunctionCall?.({ fnName: functionName, messages, formData: { ...formData, formId, formDataId } })
|
|
17
|
+
},
|
|
18
|
+
[formRef, formId, formDataId],
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
return onFunctionCall
|
|
22
|
+
}
|
package/src/components/form/layout-renderer/3-element/1-dynamic-button/use-generate-report.hook.tsx
CHANGED
|
@@ -112,13 +112,13 @@ export const useGenerateReportAction = ({
|
|
|
112
112
|
),
|
|
113
113
|
}
|
|
114
114
|
} else if (rep.optionSource.type === FieldElementOptionSourceEnum.DynamicForm) {
|
|
115
|
-
const formDataResData = await fetchFormDataAsLookup(rep.optionSource.
|
|
115
|
+
const formDataResData = await fetchFormDataAsLookup(rep.optionSource.formId)
|
|
116
116
|
|
|
117
117
|
return {
|
|
118
118
|
placeholder: rep.placeholder,
|
|
119
119
|
value: renderData(
|
|
120
120
|
formDataResData.find((data) => data.id === (value as unknown as string))?.[
|
|
121
|
-
rep.optionSource.
|
|
121
|
+
rep.optionSource.field
|
|
122
122
|
],
|
|
123
123
|
rep.renderConfig,
|
|
124
124
|
),
|
|
@@ -3,7 +3,7 @@ import { FaCaretDown } from 'react-icons/fa'
|
|
|
3
3
|
import dayjs, { Dayjs } from 'dayjs'
|
|
4
4
|
import { FaUpload } from 'react-icons/fa6'
|
|
5
5
|
import { CountryEnum, DataSanitizationTypeEnum, ElementTypeEnum } from '../../../../enums'
|
|
6
|
-
import { formatByPattern, mapToFormItemRules } from '../../../../functions/forms'
|
|
6
|
+
import { formatByPattern, mapToFormItemRules, renderData } from '../../../../functions/forms'
|
|
7
7
|
import { DisabledFieldIndicator } from '../../../common/disabled-field-indicator'
|
|
8
8
|
import CustomColorField from '../../../common/color-field'
|
|
9
9
|
import { IDataSanitization, IValidationRule } from '../../../../types'
|
|
@@ -83,6 +83,7 @@ const getField = ({
|
|
|
83
83
|
isCustom,
|
|
84
84
|
country = CountryEnum.US,
|
|
85
85
|
decimalPoint = 0,
|
|
86
|
+
mode,
|
|
86
87
|
disabledDate,
|
|
87
88
|
}: Partial<IMapperFieldObj>): JSX.Element => {
|
|
88
89
|
placeholder = placeholder && placeholder.length > 0 ? placeholder : typeof label === 'string' ? label : ''
|
|
@@ -99,13 +100,44 @@ const getField = ({
|
|
|
99
100
|
disabled={disabled}
|
|
100
101
|
showSearch
|
|
101
102
|
optionFilterProp="label"
|
|
102
|
-
filterOption={(input, option) =>
|
|
103
|
-
option &&
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
103
|
+
filterOption={(input, option) => {
|
|
104
|
+
const noOtherField = !option?.field2 && !option?.field3 && !option?.field4
|
|
105
|
+
const text = option
|
|
106
|
+
? typeof option.label === 'string' && noOtherField
|
|
107
|
+
? option.label
|
|
108
|
+
: [option.label, option.field2 ?? '', option.field3 ?? '', option.field4 ?? ''].join(' ')
|
|
109
|
+
: ''
|
|
110
|
+
|
|
111
|
+
return text.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
|
112
|
+
}}
|
|
113
|
+
optionRender={(option: any) => {
|
|
114
|
+
const opData = option.data || {}
|
|
115
|
+
const noOtherField = !opData.field2 && !opData.field3 && !opData.field4
|
|
116
|
+
|
|
117
|
+
if (noOtherField) return option.label
|
|
118
|
+
|
|
119
|
+
return (
|
|
120
|
+
<div key={opData.value} className="flex flex-col gap-0.5">
|
|
121
|
+
<div className="space-x-2">
|
|
122
|
+
<span className="text-primary font-bold">{opData.label}</span>
|
|
123
|
+
{opData.field2 && (
|
|
124
|
+
<span className="text-12 italic font-normal">
|
|
125
|
+
({opData.field2_RC ? renderData(opData.field2, opData.field2_RC) : opData.field2})
|
|
126
|
+
</span>
|
|
127
|
+
)}
|
|
128
|
+
</div>
|
|
129
|
+
{opData.field3 && (
|
|
130
|
+
<div className="text-12">
|
|
131
|
+
{opData.field3_RC ? renderData(opData.field3, opData.field3_RC) : opData.field3}
|
|
132
|
+
</div>
|
|
133
|
+
)}
|
|
134
|
+
{opData.field4 && opData.field4_RC ? renderData(opData.field4, opData.field4_RC) : opData.field4}
|
|
135
|
+
</div>
|
|
136
|
+
)
|
|
137
|
+
}}
|
|
107
138
|
allowClear={allowClear}
|
|
108
139
|
className="w-full"
|
|
140
|
+
mode={mode}
|
|
109
141
|
/>
|
|
110
142
|
)
|
|
111
143
|
case ElementTypeEnum.Checkbox:
|
|
@@ -220,11 +252,13 @@ interface IMapperFieldObj {
|
|
|
220
252
|
sanitization?: IDataSanitization
|
|
221
253
|
country?: CountryEnum
|
|
222
254
|
decimalPoint?: number
|
|
255
|
+
mode?: 'multiple' | 'tags'
|
|
223
256
|
disabledDate?: (date: Dayjs) => boolean
|
|
224
257
|
}
|
|
225
258
|
interface ISelectOption {
|
|
226
259
|
value: number | boolean | string
|
|
227
260
|
label: string | ReactNode
|
|
261
|
+
[key: string]: any
|
|
228
262
|
}
|
|
229
263
|
const datepickerFormats = [
|
|
230
264
|
'MM/DD/YYYY',
|
|
@@ -13,7 +13,7 @@ export default function LayoutRenderer_ReCaptcha({
|
|
|
13
13
|
}: ILayoutRenderer_RichEditor) {
|
|
14
14
|
const { formRef, formKey } = formContext
|
|
15
15
|
const [tokenVerificationFailed, setTokenVerificationFailed] = useState(false)
|
|
16
|
-
const verifyApiCancelFuncRef = useRef<() => void | undefined>(
|
|
16
|
+
const verifyApiCancelFuncRef = useRef<() => void | undefined>()
|
|
17
17
|
|
|
18
18
|
const verifyReCaptcha = useCallback(
|
|
19
19
|
(token: string | null) => {
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import { Form } from 'antd'
|
|
2
2
|
import { useEffect, useMemo, useRef } from 'react'
|
|
3
3
|
import SignatureCanvas from 'react-signature-canvas'
|
|
4
|
-
import { NEW_FORM_DATA_IDENTIFIER } from '../../../../constants'
|
|
5
4
|
import { FormPreservedItemKeys } from '../../../../enums'
|
|
6
5
|
import { Button_FillerPortal } from '../../../common/button'
|
|
7
6
|
import { useFormPreservedItemValues } from '../../../common/custom-hooks/use-preserved-form-items.hook'
|
|
8
7
|
import { IElementBaseProps } from '.'
|
|
9
8
|
import { ISignatureElementProps, IValidationRule } from '../../../../types'
|
|
10
9
|
import { IFormContext } from '../1-row'
|
|
11
|
-
import { mapToFormItemRules } from '../../../../functions'
|
|
10
|
+
import { isNewFormDataPage, mapToFormItemRules } from '../../../../functions'
|
|
12
11
|
|
|
13
12
|
export default function LayoutRenderer_Signature({
|
|
14
13
|
formItem,
|
|
@@ -55,7 +54,7 @@ export default function LayoutRenderer_Signature({
|
|
|
55
54
|
}
|
|
56
55
|
labelAlign="left"
|
|
57
56
|
>
|
|
58
|
-
{(inPreviewMode || formDataId
|
|
57
|
+
{(inPreviewMode || isNewFormDataPage(formDataId)) && !isGeneratingPdf ? (
|
|
59
58
|
<SignatureCanvas
|
|
60
59
|
ref={sigCanvasRef}
|
|
61
60
|
canvasProps={{
|