form-craft-package 1.11.9-dev.0 → 1.11.10
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/.claude/settings.local.json +7 -0
- package/package.json +1 -1
- package/src/components/form/layout-renderer/3-element/1-dynamic-button/use-send-notification.hook.ts +20 -15
- package/src/components/form/layout-renderer/3-element/18-gallery/index.tsx +8 -7
- package/src/components/form/layout-renderer/3-element/18-gallery/upload.modal.tsx +134 -68
- package/src/types/forms/layout-elements/index.ts +8 -6
package/package.json
CHANGED
package/src/components/form/layout-renderer/3-element/1-dynamic-button/use-send-notification.hook.ts
CHANGED
|
@@ -139,8 +139,12 @@ export const useSendNotificationAction = ({
|
|
|
139
139
|
[formTemplateReports, formId, formDataId, companyKey],
|
|
140
140
|
)
|
|
141
141
|
|
|
142
|
-
const onSendNotification = useCallback(
|
|
143
|
-
async (
|
|
142
|
+
const onSendNotification = useCallback(
|
|
143
|
+
async (
|
|
144
|
+
notifActionProps: IButtonProps_SendNotification,
|
|
145
|
+
newFormDataId?: string,
|
|
146
|
+
extraAttachments: IEmail_Attachment[] = [],
|
|
147
|
+
) => {
|
|
144
148
|
const { notificationId } = notifActionProps
|
|
145
149
|
|
|
146
150
|
const { joins = [], notifications } = formNotifications
|
|
@@ -160,13 +164,14 @@ export const useSendNotificationAction = ({
|
|
|
160
164
|
|
|
161
165
|
const hasAttachments = Array.isArray(formNotif.attachments) && formNotif.attachments.length > 0
|
|
162
166
|
|
|
163
|
-
let formTemplateReportAttachments: IEmail_Attachment[] = []
|
|
164
|
-
if (hasAttachments) {
|
|
165
|
-
setDataLoadingType?.(FormLoadingModalTypeEnum.GeneratingReport)
|
|
166
|
-
formTemplateReportAttachments = await handleTemplateReport(formNotif.attachments!, targetFormDataId)
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
|
|
167
|
+
let formTemplateReportAttachments: IEmail_Attachment[] = []
|
|
168
|
+
if (hasAttachments) {
|
|
169
|
+
setDataLoadingType?.(FormLoadingModalTypeEnum.GeneratingReport)
|
|
170
|
+
formTemplateReportAttachments = await handleTemplateReport(formNotif.attachments!, targetFormDataId)
|
|
171
|
+
}
|
|
172
|
+
const additionalEmailAttachments = [...formTemplateReportAttachments, ...extraAttachments]
|
|
173
|
+
|
|
174
|
+
setDataLoadingType?.(FormLoadingModalTypeEnum.SendingNotification)
|
|
170
175
|
|
|
171
176
|
try {
|
|
172
177
|
const notifConfigRes = await client.get(`/api/notificationconfig/${notificationId}/data`)
|
|
@@ -175,12 +180,12 @@ export const useSendNotificationAction = ({
|
|
|
175
180
|
const notificationRequests = await buildNotificationRequests({
|
|
176
181
|
notificationId: formNotif.id,
|
|
177
182
|
notificationConfig: notifConfigRes.data.data,
|
|
178
|
-
formNotification: formNotif,
|
|
179
|
-
replacementData: formDataRes.data,
|
|
180
|
-
formId,
|
|
181
|
-
fileBaseUrl,
|
|
182
|
-
additionalEmailAttachments
|
|
183
|
-
})
|
|
183
|
+
formNotification: formNotif,
|
|
184
|
+
replacementData: formDataRes.data,
|
|
185
|
+
formId,
|
|
186
|
+
fileBaseUrl,
|
|
187
|
+
additionalEmailAttachments,
|
|
188
|
+
})
|
|
184
189
|
|
|
185
190
|
if (!notificationRequests.length) {
|
|
186
191
|
onFinal()
|
|
@@ -224,13 +224,14 @@ function LayoutRenderer_Gallery({
|
|
|
224
224
|
<Empty description={emptyDescription || 'No pictures uploaded'} />
|
|
225
225
|
)}
|
|
226
226
|
</Form.Item>
|
|
227
|
-
<GalleryUploadModal
|
|
228
|
-
isOpen={isUploadModalOpen}
|
|
229
|
-
formContext={formContext}
|
|
230
|
-
formItem={formItem}
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
227
|
+
<GalleryUploadModal
|
|
228
|
+
isOpen={isUploadModalOpen}
|
|
229
|
+
formContext={formContext}
|
|
230
|
+
formItem={formItem}
|
|
231
|
+
elementProps={elementProps}
|
|
232
|
+
elementKey={elementKey}
|
|
233
|
+
textConditions={textConditions}
|
|
234
|
+
isDisabled={isDisabled}
|
|
234
235
|
onDiscardSuccess={() => setIsUploadModalOpen(false)}
|
|
235
236
|
onSaveSuccess={(uploadedBlobNames) => {
|
|
236
237
|
formRef?.setFieldValue(formItem.path, [
|
|
@@ -1,40 +1,56 @@
|
|
|
1
|
-
import client from '../../../../../api/client'
|
|
2
|
-
import { isNewFormDataPage, resolveConditionalText } from '../../../../../functions'
|
|
3
|
-
import { saveFile } from '../../../../../functions/forms/form'
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
import {
|
|
11
|
-
import
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
1
|
+
import client from '../../../../../api/client'
|
|
2
|
+
import { isNewFormDataPage, resolveConditionalText } from '../../../../../functions'
|
|
3
|
+
import { saveFile } from '../../../../../functions/forms/form'
|
|
4
|
+
import {
|
|
5
|
+
ButtonActionCategoryEnum,
|
|
6
|
+
EmailAttachmentTypeEnum,
|
|
7
|
+
TranslationTextSubTypeEnum,
|
|
8
|
+
TranslationTextTypeEnum,
|
|
9
|
+
} from '../../../../../enums'
|
|
10
|
+
import { RcFile, UploadFile, UploadProps } from 'antd/es/upload'
|
|
11
|
+
import { Form, Modal, Spin, Upload } from 'antd'
|
|
12
|
+
import { useCallback, useEffect, useMemo, useState } from 'react'
|
|
13
|
+
import { FaUpload } from 'react-icons/fa6'
|
|
14
|
+
import { useSendNotificationAction } from '../1-dynamic-button/use-send-notification.hook'
|
|
15
|
+
import { Button_FillerPortal } from '../../../../common/button'
|
|
16
|
+
import { useNotification, useTranslation } from '../../../../common/custom-hooks'
|
|
17
|
+
import useGetCurrentBreakpoint from '../../../../common/custom-hooks/use-window-width.hook'
|
|
18
|
+
import { IElementBaseProps } from '..'
|
|
19
|
+
import { IFormContext } from '../../1-row'
|
|
20
|
+
import { IEmail_Attachment, IGalleryElementProps } from '../../../../../types'
|
|
21
|
+
|
|
22
|
+
export default function GalleryUploadModal({
|
|
23
|
+
isOpen,
|
|
24
|
+
formContext,
|
|
25
|
+
formItem,
|
|
26
|
+
elementProps,
|
|
27
|
+
elementKey,
|
|
28
|
+
textConditions,
|
|
29
|
+
onDiscardSuccess,
|
|
30
|
+
onSaveSuccess,
|
|
31
|
+
}: {
|
|
32
|
+
isOpen: boolean
|
|
33
|
+
formContext: IFormContext
|
|
34
|
+
elementProps: IGalleryElementProps
|
|
35
|
+
onDiscardSuccess: () => void
|
|
36
|
+
onSaveSuccess: (blobNames: string[]) => void
|
|
37
|
+
} & IElementBaseProps) {
|
|
29
38
|
const { formRef, formDataId, companyKey, formId } = formContext
|
|
30
39
|
const { t } = useTranslation(formId)
|
|
31
40
|
const currentBreakpoint = useGetCurrentBreakpoint()
|
|
32
41
|
const { warningModal } = useNotification()
|
|
33
42
|
|
|
34
43
|
const [uploadedFiles, setUploadedFiles] = useState<UploadFile[]>([])
|
|
35
|
-
const [isUploadLoading, setIsUploadLoading] = useState(false)
|
|
36
|
-
const [isSaving, setIsSaving] = useState(false)
|
|
37
|
-
const [isDiscarding, setIsDiscarding] = useState(false)
|
|
44
|
+
const [isUploadLoading, setIsUploadLoading] = useState(false)
|
|
45
|
+
const [isSaving, setIsSaving] = useState(false)
|
|
46
|
+
const [isDiscarding, setIsDiscarding] = useState(false)
|
|
47
|
+
const [isSendingNotification, setIsSendingNotification] = useState(false)
|
|
48
|
+
const onSendNotification = useSendNotificationAction({
|
|
49
|
+
...formContext,
|
|
50
|
+
onSuccess: () => {},
|
|
51
|
+
onError: () => {},
|
|
52
|
+
onFinal: () => {},
|
|
53
|
+
})
|
|
38
54
|
|
|
39
55
|
const allValues = Form.useWatch([], { form: formRef, preserve: true })
|
|
40
56
|
|
|
@@ -123,11 +139,11 @@ export default function GalleryUploadModal({
|
|
|
123
139
|
}
|
|
124
140
|
}, [onDiscardSuccess, uploadedBlobNames])
|
|
125
141
|
|
|
126
|
-
const saveUploadedFiles = useCallback(async () => {
|
|
127
|
-
if (!formId || !formDataId || isNewFormDataPage(formDataId)) return
|
|
128
|
-
|
|
129
|
-
setIsSaving(true)
|
|
130
|
-
try {
|
|
142
|
+
const saveUploadedFiles = useCallback(async () => {
|
|
143
|
+
if (!formId || !formDataId || isNewFormDataPage(formDataId)) return
|
|
144
|
+
|
|
145
|
+
setIsSaving(true)
|
|
146
|
+
try {
|
|
131
147
|
const formDataRes = await client.get(`/api/formdata/${formId}/${formDataId}`)
|
|
132
148
|
const parsedData = JSON.parse(formDataRes.data.data)
|
|
133
149
|
const fieldPath = Array.isArray(formItem.path) ? formItem.path : [formItem.path]
|
|
@@ -140,20 +156,65 @@ export default function GalleryUploadModal({
|
|
|
140
156
|
...(Array.isArray(existingBlobNames) ? existingBlobNames : []),
|
|
141
157
|
...uploadedBlobNames,
|
|
142
158
|
]
|
|
143
|
-
const res = await client.put(`/api/formdata/${formId}/${formDataId}`, {
|
|
144
|
-
name: formDataRes.data.name,
|
|
145
|
-
version: formDataRes.data.version,
|
|
146
|
-
private: formDataRes.data.private,
|
|
147
|
-
data: JSON.stringify(parsedData),
|
|
148
|
-
})
|
|
149
|
-
if (res.status === 200) {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
159
|
+
const res = await client.put(`/api/formdata/${formId}/${formDataId}`, {
|
|
160
|
+
name: formDataRes.data.name,
|
|
161
|
+
version: formDataRes.data.version,
|
|
162
|
+
private: formDataRes.data.private,
|
|
163
|
+
data: JSON.stringify(parsedData),
|
|
164
|
+
})
|
|
165
|
+
if (res.status === 200) {
|
|
166
|
+
const shouldSendNotification = elementProps.sendNotification && !!elementProps.notificationId
|
|
167
|
+
const savedBlobNames = [...uploadedBlobNames]
|
|
168
|
+
|
|
169
|
+
if (shouldSendNotification) {
|
|
170
|
+
const extraAttachments: IEmail_Attachment[] = uploadedFiles
|
|
171
|
+
.map((file) => {
|
|
172
|
+
const blobName =
|
|
173
|
+
typeof file.response === 'object' && file.response
|
|
174
|
+
? (file.response as { blobName?: string }).blobName
|
|
175
|
+
: undefined
|
|
176
|
+
if (!blobName) return null
|
|
177
|
+
|
|
178
|
+
return {
|
|
179
|
+
blobName,
|
|
180
|
+
fileName: file.name,
|
|
181
|
+
type: EmailAttachmentTypeEnum.Image,
|
|
182
|
+
}
|
|
183
|
+
})
|
|
184
|
+
.filter((attachment): attachment is IEmail_Attachment => !!attachment)
|
|
185
|
+
|
|
186
|
+
setIsSendingNotification(true)
|
|
187
|
+
try {
|
|
188
|
+
await onSendNotification(
|
|
189
|
+
{
|
|
190
|
+
category: ButtonActionCategoryEnum.SendNotification,
|
|
191
|
+
notificationId: elementProps.notificationId!,
|
|
192
|
+
},
|
|
193
|
+
formDataId,
|
|
194
|
+
extraAttachments,
|
|
195
|
+
)
|
|
196
|
+
} finally {
|
|
197
|
+
setIsSendingNotification(false)
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
setUploadedFiles([])
|
|
202
|
+
onSaveSuccess(savedBlobNames)
|
|
203
|
+
}
|
|
204
|
+
} finally {
|
|
205
|
+
setIsSaving(false)
|
|
206
|
+
}
|
|
207
|
+
}, [
|
|
208
|
+
elementProps.notificationId,
|
|
209
|
+
elementProps.sendNotification,
|
|
210
|
+
formDataId,
|
|
211
|
+
formId,
|
|
212
|
+
formItem.path,
|
|
213
|
+
onSaveSuccess,
|
|
214
|
+
onSendNotification,
|
|
215
|
+
uploadedFiles,
|
|
216
|
+
uploadedBlobNames,
|
|
217
|
+
])
|
|
157
218
|
|
|
158
219
|
return (
|
|
159
220
|
<Modal
|
|
@@ -164,24 +225,29 @@ export default function GalleryUploadModal({
|
|
|
164
225
|
title={title || 'Upload pictures'}
|
|
165
226
|
footer={
|
|
166
227
|
<div className="flex justify-between">
|
|
167
|
-
<Button_FillerPortal
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
228
|
+
<Button_FillerPortal
|
|
229
|
+
outline
|
|
230
|
+
disabled={isUploadLoading || isSendingNotification}
|
|
231
|
+
loading={isDiscarding}
|
|
232
|
+
onClick={discardUploadedFiles}
|
|
233
|
+
>
|
|
234
|
+
{discardText || 'Discard & Close'}
|
|
235
|
+
</Button_FillerPortal>
|
|
236
|
+
<Button_FillerPortal
|
|
237
|
+
primary
|
|
238
|
+
disabled={isUploadLoading || isDiscarding || isSendingNotification}
|
|
239
|
+
loading={isSaving || isSendingNotification}
|
|
240
|
+
onClick={saveUploadedFiles}
|
|
241
|
+
>
|
|
242
|
+
{saveText || 'Save Pictures'}
|
|
243
|
+
</Button_FillerPortal>
|
|
244
|
+
</div>
|
|
245
|
+
}
|
|
246
|
+
>
|
|
247
|
+
<Spin spinning={isUploadLoading || isSendingNotification}>
|
|
248
|
+
<Upload.Dragger {...uploadProps} fileList={uploadedFiles}>
|
|
249
|
+
<div className="flex flex-col items-center">
|
|
250
|
+
<FaUpload size={24} className="text-primary" />
|
|
185
251
|
<span className="font-semibold mt-2 text-secondary">
|
|
186
252
|
{text || 'Click or drag image files to this area'}
|
|
187
253
|
</span>
|
|
@@ -186,12 +186,14 @@ export interface IGalleryElement extends BaseFormLayoutElement {
|
|
|
186
186
|
elementType: ElementTypeEnum.Gallery
|
|
187
187
|
props: IGalleryElementProps
|
|
188
188
|
}
|
|
189
|
-
export interface IGalleryElementProps {
|
|
190
|
-
hasNoLabel?: boolean
|
|
191
|
-
grid?: Partial<Record<DeviceBreakpointEnum, IGalleryElementGridConfig | null>>
|
|
192
|
-
uploadButtonConditions?: IFormLayoutElementConditions
|
|
193
|
-
deleteButtonConditions?: IFormLayoutElementConditions
|
|
194
|
-
|
|
189
|
+
export interface IGalleryElementProps {
|
|
190
|
+
hasNoLabel?: boolean
|
|
191
|
+
grid?: Partial<Record<DeviceBreakpointEnum, IGalleryElementGridConfig | null>>
|
|
192
|
+
uploadButtonConditions?: IFormLayoutElementConditions
|
|
193
|
+
deleteButtonConditions?: IFormLayoutElementConditions
|
|
194
|
+
sendNotification?: boolean
|
|
195
|
+
notificationId?: number
|
|
196
|
+
}
|
|
195
197
|
export interface IGalleryElementGridConfig {
|
|
196
198
|
count?: number | null
|
|
197
199
|
row?: number | null
|