form-craft-package 1.1.2 → 1.1.3
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/common/custom-hooks/use-find-dynamic-form.ts +1 -1
- package/src/components/form/2-details/index.tsx +4 -2
- package/src/components/form/layout-renderer/3-element/1-dynamic-button.tsx +33 -11
- package/src/components/form/layout-renderer/3-element/5-re-captcha.tsx +2 -1
- package/src/components/form/layout-renderer/3-element/6-signature.tsx +12 -60
- package/src/components/form/layout-renderer/3-element/7-file-upload.tsx +8 -17
- package/src/constants.ts +0 -3
- package/src/enums.ts +15 -1
- package/src/functions/form.ts +15 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useState, useEffect } from 'react'
|
|
2
2
|
import { useParams } from 'react-router-dom'
|
|
3
|
-
import { LOCAL_STORAGE_KEYS_ENUM } from '../../../constants'
|
|
4
3
|
import { IDynamicForm } from '../../../types'
|
|
4
|
+
import { LOCAL_STORAGE_KEYS_ENUM } from '../../../enums'
|
|
5
5
|
|
|
6
6
|
export const useFindDynamiForm = () => {
|
|
7
7
|
const { formName } = useParams<{ formName: string }>()
|
|
@@ -9,6 +9,7 @@ import { DynamicFormButtonRender, ICustomFunctionCall } from '../layout-renderer
|
|
|
9
9
|
import FormDataListSkeleton_Details from '../../common/loading-skeletons/details'
|
|
10
10
|
import { useLocation } from 'react-router-dom'
|
|
11
11
|
import { queryParamsToObject } from '../../../functions'
|
|
12
|
+
import { FormPreservedItemKeys } from '../../../enums'
|
|
12
13
|
|
|
13
14
|
export default function FormDataDetailsComponent({
|
|
14
15
|
isPublic,
|
|
@@ -28,7 +29,7 @@ export default function FormDataDetailsComponent({
|
|
|
28
29
|
// this is for converting the screen to PDF
|
|
29
30
|
if (isPublic && location.search) {
|
|
30
31
|
const formValues = queryParamsToObject(location.search)
|
|
31
|
-
formDataRef.setFieldsValue(formValues)
|
|
32
|
+
formDataRef.setFieldsValue({ ...formValues, [FormPreservedItemKeys.IsGeneratingPDF]: true })
|
|
32
33
|
}
|
|
33
34
|
}, [isPublic, location, formDataRef])
|
|
34
35
|
|
|
@@ -66,10 +67,11 @@ export default function FormDataDetailsComponent({
|
|
|
66
67
|
if (res.status === 200) {
|
|
67
68
|
const parsedData: IFormSchema | null = parseJSON(res.data.data)
|
|
68
69
|
if (parsedData) {
|
|
70
|
+
console.log({parsedData})
|
|
69
71
|
const { layout, migrationRules, convertScreenToPdf = false } = parsedData.detailsConfig
|
|
70
72
|
|
|
71
73
|
if (isPublic) {
|
|
72
|
-
formDataRef.setFieldValue(
|
|
74
|
+
formDataRef.setFieldValue(FormPreservedItemKeys.ConvertScreenToPDF, convertScreenToPdf)
|
|
73
75
|
setLoadings((c) => ({ ...c, data: false }))
|
|
74
76
|
} else fetchFormData(formId, migrationRules)
|
|
75
77
|
setLayout(layout)
|
|
@@ -3,15 +3,16 @@ import { useLocation, useNavigate } from 'react-router-dom'
|
|
|
3
3
|
import { Form, FormInstance } from 'antd'
|
|
4
4
|
import { getButtonRenderProps } from '../../../../functions/get-element-props'
|
|
5
5
|
import { stringifyJSON } from '../../../../functions/json-handlers'
|
|
6
|
-
import { ButtonActionCategoryEnum, FormLoadingModalTypeEnum } from '../../../../enums'
|
|
6
|
+
import { ButtonActionCategoryEnum, FormLoadingModalTypeEnum, FormPreservedItemKeys } from '../../../../enums'
|
|
7
7
|
import { IDataRender_ButtonProps, IFormLayoutElementConditions } from '../../../../types'
|
|
8
8
|
import { NEW_FORM_DATA_IDENTIFIER } from '../../../../constants'
|
|
9
9
|
import { Button_FillerPortal } from '../../../common/button'
|
|
10
|
-
import { extractDynamicFormHref, objectToQueryParams } from '../../../../functions'
|
|
10
|
+
import { base64ToBlob, extractDynamicFormHref, objectToQueryParams } from '../../../../functions'
|
|
11
11
|
import { useNotification } from '../../../common/custom-hooks/use-notification.hook'
|
|
12
12
|
import client from '../../../../functions/axios-handler'
|
|
13
13
|
import { useLazyModalOpener } from '../../../common/custom-hooks/use-lazy-modal-opener.hook'
|
|
14
14
|
import WarningIcon from '../../../common/warning-icon'
|
|
15
|
+
import { saveFile } from '../../../../functions/form'
|
|
15
16
|
|
|
16
17
|
const FormDataLoadingIndicatorModal = lazy(() => import('../../../modals/form-data-loading.modal'))
|
|
17
18
|
|
|
@@ -34,9 +35,12 @@ export const DynamicFormButtonRender = memo(
|
|
|
34
35
|
const [dataLoadingType, setDataLoadingType] = useState<FormLoadingModalTypeEnum | undefined>()
|
|
35
36
|
|
|
36
37
|
const formValues = Form.useWatch([], { form: formRef, preserve: true })
|
|
37
|
-
const formId = Form.useWatch(
|
|
38
|
-
const formKey = Form.useWatch(
|
|
39
|
-
const convertScreenToPdf = Form.useWatch(
|
|
38
|
+
const formId = Form.useWatch(FormPreservedItemKeys.FormId, { form: formRef, preserve: true }) // for public use
|
|
39
|
+
const formKey = Form.useWatch(FormPreservedItemKeys.FormKey, { form: formRef, preserve: true }) // for public use
|
|
40
|
+
const convertScreenToPdf = Form.useWatch(FormPreservedItemKeys.ConvertScreenToPDF, {
|
|
41
|
+
form: formRef,
|
|
42
|
+
preserve: true,
|
|
43
|
+
}) // for public use
|
|
40
44
|
|
|
41
45
|
const baseDynamicUrl = useMemo(() => extractDynamicFormHref(location.pathname), [location.pathname])
|
|
42
46
|
|
|
@@ -133,7 +137,7 @@ export const DynamicFormButtonRender = memo(
|
|
|
133
137
|
if (isPublic) reqData.private = true // TODO: figure out what this is
|
|
134
138
|
else reqData.version = 1
|
|
135
139
|
|
|
136
|
-
const endpoint = isPublic ? `/api/
|
|
140
|
+
const endpoint = isPublic ? `/api/site/${formKey}` : `/api/formdata/${formId}`
|
|
137
141
|
|
|
138
142
|
client
|
|
139
143
|
.post(endpoint, reqData)
|
|
@@ -156,13 +160,21 @@ export const DynamicFormButtonRender = memo(
|
|
|
156
160
|
const generatePdfProof = useCallback(() => {
|
|
157
161
|
formRef?.validateFields().then((values) => {
|
|
158
162
|
const queryParams = objectToQueryParams(values)
|
|
163
|
+
console.log(queryParams)
|
|
159
164
|
const fullUrl = `${location.pathname}?${queryParams}`
|
|
160
165
|
console.log(fullUrl)
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
166
|
+
const blobName = 'abc'
|
|
167
|
+
client
|
|
168
|
+
.post(`/api/attachment/pdf/${formKey}/${fullUrl}/${blobName}`)
|
|
169
|
+
.then((res) => {
|
|
170
|
+
if (res.status < 300) {
|
|
171
|
+
console.log(res.data)
|
|
172
|
+
onCreateNewData(res.data)
|
|
173
|
+
}
|
|
174
|
+
})
|
|
175
|
+
.catch(() => error({ message: 'Error occured while generating PDF!' }))
|
|
164
176
|
})
|
|
165
|
-
}, [formRef, location.pathname])
|
|
177
|
+
}, [formRef, location.pathname, formKey])
|
|
166
178
|
|
|
167
179
|
const onSaveExistingData = useCallback(() => {
|
|
168
180
|
formRef!.validateFields().then((values) => {
|
|
@@ -191,7 +203,7 @@ export const DynamicFormButtonRender = memo(
|
|
|
191
203
|
})
|
|
192
204
|
}, [formRef, formId, formDataId])
|
|
193
205
|
|
|
194
|
-
const onButtonClick = useCallback(() => {
|
|
206
|
+
const onButtonClick = useCallback(async () => {
|
|
195
207
|
switch (btnProps.category) {
|
|
196
208
|
case ButtonActionCategoryEnum.CreateNewData:
|
|
197
209
|
navigate(`${baseDynamicUrl}/${NEW_FORM_DATA_IDENTIFIER}`)
|
|
@@ -214,6 +226,16 @@ export const DynamicFormButtonRender = memo(
|
|
|
214
226
|
break
|
|
215
227
|
case ButtonActionCategoryEnum.SaveDataChanges:
|
|
216
228
|
if (formRef) {
|
|
229
|
+
const signatureField = formRef.getFieldValue(FormPreservedItemKeys.HasSignature)
|
|
230
|
+
if (!!signatureField) {
|
|
231
|
+
setDataLoadingType(FormLoadingModalTypeEnum.GeneratingPdf)
|
|
232
|
+
|
|
233
|
+
const signatureBase64 = formRef.getFieldValue(signatureField)
|
|
234
|
+
const blobName = await saveFile(base64ToBlob(signatureBase64), 'signature')
|
|
235
|
+
|
|
236
|
+
if (!!blobName) formRef.setFieldValue(signatureField, blobName)
|
|
237
|
+
}
|
|
238
|
+
|
|
217
239
|
if (formDataId === NEW_FORM_DATA_IDENTIFIER) {
|
|
218
240
|
if (convertScreenToPdf) generatePdfProof()
|
|
219
241
|
else onCreateNewData()
|
|
@@ -2,10 +2,11 @@ import { Form, FormInstance } from 'antd'
|
|
|
2
2
|
import { useCallback, useState } from 'react'
|
|
3
3
|
import ReCAPTCHA from 'react-google-recaptcha'
|
|
4
4
|
import client from '../../../../functions/axios-handler'
|
|
5
|
+
import { FormPreservedItemKeys } from '../../../../enums'
|
|
5
6
|
|
|
6
7
|
export default function LayoutRenderer_ReCaptcha({ formRef, fieldKey, elementProps }: ILayoutRenderer_RichEditor) {
|
|
7
8
|
const [tokenVerificationFailed, setTokenVerificationFailed] = useState(false)
|
|
8
|
-
const formKey = Form.useWatch(
|
|
9
|
+
const formKey = Form.useWatch(FormPreservedItemKeys.FormKey, { form: formRef, preserve: true })
|
|
9
10
|
|
|
10
11
|
const verifyReCaptcha = useCallback(
|
|
11
12
|
(token: string | null) => {
|
|
@@ -1,71 +1,21 @@
|
|
|
1
1
|
import { Form, FormInstance } from 'antd'
|
|
2
|
-
import {
|
|
2
|
+
import { useRef } from 'react'
|
|
3
3
|
import SignatureCanvas from 'react-signature-canvas'
|
|
4
|
-
import { Button_FillerPortal } from '../../../common/button'
|
|
5
|
-
import client from '../../../../functions/axios-handler'
|
|
6
|
-
import { base64ToBlob } from '../../../../functions'
|
|
7
4
|
import { NEW_FORM_DATA_IDENTIFIER } from '../../../../constants'
|
|
5
|
+
import { FormPreservedItemKeys } from '../../../../enums'
|
|
8
6
|
|
|
9
7
|
export default function LayoutRenderer_Signature({ formRef, fieldKey, elementProps }: ILayoutRenderer_Signature) {
|
|
10
|
-
const [loading, setLoading] = useState(false)
|
|
11
8
|
const sigCanvasRef = useRef<SignatureCanvas>(null)
|
|
12
9
|
const savedSignatureBlobName = Form.useWatch(fieldKey, formRef)
|
|
13
|
-
const formDataId = Form.useWatch(
|
|
14
|
-
const baseServerUrl = Form.useWatch(
|
|
15
|
-
const companyKey = Form.useWatch(
|
|
16
|
-
|
|
17
|
-
const saveSignature = useCallback(
|
|
18
|
-
(signatureBase64: string) => {
|
|
19
|
-
setLoading(true)
|
|
20
|
-
const formData = new FormData()
|
|
21
|
-
formData.append('file', base64ToBlob(signatureBase64), 'signature.jpg')
|
|
22
|
-
client
|
|
23
|
-
.post('/api/attachment', formData)
|
|
24
|
-
.then((res) => {
|
|
25
|
-
if (res.status < 300 && res.data) formRef.setFieldValue(fieldKey, res.data)
|
|
26
|
-
})
|
|
27
|
-
.finally(() => setLoading(false))
|
|
28
|
-
},
|
|
29
|
-
[fieldKey],
|
|
30
|
-
)
|
|
31
|
-
|
|
32
|
-
const deleteSavedSignature = useCallback((blobName: string) => {
|
|
33
|
-
setLoading(true)
|
|
34
|
-
client
|
|
35
|
-
.delete(`/api/attachment/${blobName}`)
|
|
36
|
-
.then((res) => {
|
|
37
|
-
if (res.status < 300) {
|
|
38
|
-
formRef.setFieldValue(fieldKey, null)
|
|
39
|
-
sigCanvasRef.current?.clear()
|
|
40
|
-
}
|
|
41
|
-
})
|
|
42
|
-
.finally(() => setLoading(false))
|
|
43
|
-
}, [])
|
|
10
|
+
const formDataId = Form.useWatch(FormPreservedItemKeys.FormDataId, { form: formRef, preserve: true })
|
|
11
|
+
const baseServerUrl = Form.useWatch(FormPreservedItemKeys.BaseServerUrl, { form: formRef, preserve: true })
|
|
12
|
+
const companyKey = Form.useWatch(FormPreservedItemKeys.CompanyKey, { form: formRef, preserve: true })
|
|
13
|
+
const isGeneratingPdf = Form.useWatch(FormPreservedItemKeys.IsGeneratingPDF, { form: formRef, preserve: true })
|
|
44
14
|
|
|
45
15
|
return (
|
|
46
|
-
<Form.Item
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
<>
|
|
50
|
-
<span>{elementProps.hasNoLabel ? '' : elementProps.label}</span>
|
|
51
|
-
{formDataId === NEW_FORM_DATA_IDENTIFIER && (
|
|
52
|
-
<Button_FillerPortal
|
|
53
|
-
link
|
|
54
|
-
loading={loading}
|
|
55
|
-
onClick={() => {
|
|
56
|
-
if (savedSignatureBlobName) deleteSavedSignature(savedSignatureBlobName)
|
|
57
|
-
else sigCanvasRef.current?.clear()
|
|
58
|
-
}}
|
|
59
|
-
>
|
|
60
|
-
<span className="underline">Clear field</span>
|
|
61
|
-
</Button_FillerPortal>
|
|
62
|
-
)}
|
|
63
|
-
</>
|
|
64
|
-
}
|
|
65
|
-
labelAlign="left"
|
|
66
|
-
>
|
|
67
|
-
{formDataId !== NEW_FORM_DATA_IDENTIFIER ? (
|
|
68
|
-
<div className="h-[300px] rounded-md">
|
|
16
|
+
<Form.Item name={fieldKey} label={elementProps.hasNoLabel ? '' : elementProps.label} labelAlign="left">
|
|
17
|
+
{formDataId !== NEW_FORM_DATA_IDENTIFIER || isGeneratingPdf ? (
|
|
18
|
+
<div className="h-[300px] rounded-md border-2 border-[#f0f0f0]">
|
|
69
19
|
<img alt="signature" src={`${baseServerUrl}/api/attachment/${companyKey}/${savedSignatureBlobName}`} />
|
|
70
20
|
</div>
|
|
71
21
|
) : (
|
|
@@ -78,7 +28,9 @@ export default function LayoutRenderer_Signature({ formRef, fieldKey, elementPro
|
|
|
78
28
|
}}
|
|
79
29
|
onEnd={() => {
|
|
80
30
|
const sigBase64 = sigCanvasRef.current?.toDataURL()
|
|
81
|
-
if (sigBase64)
|
|
31
|
+
if (sigBase64)
|
|
32
|
+
formRef.setFieldsValue({ [fieldKey]: sigBase64, [FormPreservedItemKeys.HasSignature]: fieldKey })
|
|
33
|
+
// saveSignature(sigBase64)
|
|
82
34
|
}}
|
|
83
35
|
/>
|
|
84
36
|
)}
|
|
@@ -6,6 +6,7 @@ import { FaFile, FaUpload } from 'react-icons/fa6'
|
|
|
6
6
|
import { IFileUploadElementRules } from '../../../../types'
|
|
7
7
|
import { useNotification } from '../../../common/custom-hooks'
|
|
8
8
|
import { FaTrashAlt } from 'react-icons/fa'
|
|
9
|
+
import { saveFile } from '../../../../functions/form'
|
|
9
10
|
|
|
10
11
|
export default function LayoutRenderer_FileUpload({
|
|
11
12
|
formRef,
|
|
@@ -17,21 +18,6 @@ export default function LayoutRenderer_FileUpload({
|
|
|
17
18
|
const [loading, setLoading] = useState(false)
|
|
18
19
|
const savedSignatureBlobName = Form.useWatch(fieldKey, formRef)
|
|
19
20
|
|
|
20
|
-
const saveFile = useCallback(
|
|
21
|
-
(file: any) => {
|
|
22
|
-
setLoading(true)
|
|
23
|
-
const formData = new FormData()
|
|
24
|
-
formData.append('file', file.originFileObj, file.name)
|
|
25
|
-
client
|
|
26
|
-
.post('/api/attachment', formData)
|
|
27
|
-
.then((res) => {
|
|
28
|
-
if (res.status < 300 && res.data) formRef.setFieldValue(fieldKey, res.data)
|
|
29
|
-
})
|
|
30
|
-
.finally(() => setLoading(false))
|
|
31
|
-
},
|
|
32
|
-
[fieldKey],
|
|
33
|
-
)
|
|
34
|
-
|
|
35
21
|
const deleteSavedFile = useCallback((blobName: string) => {
|
|
36
22
|
setLoading(true)
|
|
37
23
|
client
|
|
@@ -48,8 +34,13 @@ export default function LayoutRenderer_FileUpload({
|
|
|
48
34
|
customRequest: ({ file, onSuccess }: any): void => {
|
|
49
35
|
setTimeout(() => onSuccess('ok', file), 100)
|
|
50
36
|
},
|
|
51
|
-
onChange: (fileInfo: any) => {
|
|
52
|
-
if (fileInfo.file.status === 'done')
|
|
37
|
+
onChange: async (fileInfo: any) => {
|
|
38
|
+
if (fileInfo.file.status === 'done') {
|
|
39
|
+
setLoading(true)
|
|
40
|
+
const blobName = await saveFile(fileInfo.file.originFileObj, fileInfo.file.name)
|
|
41
|
+
if (blobName) formRef.setFieldValue(fieldKey, blobName)
|
|
42
|
+
setLoading(false)
|
|
43
|
+
}
|
|
53
44
|
},
|
|
54
45
|
}
|
|
55
46
|
|
package/src/constants.ts
CHANGED
|
@@ -10,6 +10,3 @@ export const DEFAULT_FLEX_CONFIG = {
|
|
|
10
10
|
Item: { flexBasis: '0', flexGrow: 1, display: CSSLayoutType.Flex, flexDirection: FlexDirection.Col, gap: '10px' },
|
|
11
11
|
}
|
|
12
12
|
export const NEW_FORM_DATA_IDENTIFIER = 'new'
|
|
13
|
-
export enum LOCAL_STORAGE_KEYS_ENUM {
|
|
14
|
-
DynamicForms = '38be231fe41c169037ed04c267ebe070',
|
|
15
|
-
}
|
package/src/enums.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
export enum LOCAL_STORAGE_KEYS_ENUM {
|
|
2
|
+
DynamicForms = '38be231fe41c169037ed04c267ebe070',
|
|
3
|
+
}
|
|
1
4
|
export enum ElementTypeEnum {
|
|
2
5
|
ShortInput = 'Short Input',
|
|
3
6
|
LongInput = 'Long Input',
|
|
@@ -163,6 +166,7 @@ export enum ResponsivenessDeviceEnum {
|
|
|
163
166
|
Mobile = 'xs',
|
|
164
167
|
}
|
|
165
168
|
export enum FormLoadingModalTypeEnum {
|
|
169
|
+
GeneratingPdf,
|
|
166
170
|
SavingChanges,
|
|
167
171
|
ErrorOccured,
|
|
168
172
|
}
|
|
@@ -181,4 +185,14 @@ export enum FileTypeEnum {
|
|
|
181
185
|
EXCEL = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
|
182
186
|
CSV = 'text/csv',
|
|
183
187
|
DOCX = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
|
184
|
-
}
|
|
188
|
+
}
|
|
189
|
+
export enum FormPreservedItemKeys {
|
|
190
|
+
FormId = 'formId',
|
|
191
|
+
FormKey = 'formKey',
|
|
192
|
+
FormDataId = 'formDataId',
|
|
193
|
+
BaseServerUrl = 'baseServerUrl',
|
|
194
|
+
CompanyKey = 'companyKey',
|
|
195
|
+
ConvertScreenToPDF = 'convertScreenToPdf',
|
|
196
|
+
IsGeneratingPDF = 'isGeneratingPdf',
|
|
197
|
+
HasSignature = 'hasSignature',
|
|
198
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import client from './axios-handler'
|
|
2
|
+
|
|
3
|
+
export const saveFile = async (file: any, fileName: string): Promise<string | null> => {
|
|
4
|
+
try {
|
|
5
|
+
const formData = new FormData()
|
|
6
|
+
formData.append('file', file, fileName)
|
|
7
|
+
const response = await client.post('/api/attachment', formData)
|
|
8
|
+
if (response.status < 300) return response.data
|
|
9
|
+
|
|
10
|
+
return null
|
|
11
|
+
} catch (error: any) {
|
|
12
|
+
console.error(error.response)
|
|
13
|
+
return null
|
|
14
|
+
}
|
|
15
|
+
}
|