form-craft-package 1.11.9-dev.0 → 1.11.12

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "form-craft-package",
3
- "version": "1.11.9-dev.0",
3
+ "version": "1.11.12",
4
4
  "main": "index.ts",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1",
@@ -370,7 +370,7 @@ export const TemplateLayout = ({
370
370
  return (
371
371
  <Layout className="fc-layout min-h-screen">
372
372
  <Header
373
- className="fc-header sticky top-0 z-40 flex items-center shadow-sm justify-between px-1 overflow-visible"
373
+ className="fc-header sticky top-0 z-40 flex items-center shadow-sm justify-between px-1 overflow-hidden"
374
374
  style={{ height: headerHeight, lineHeight: 'normal' }}
375
375
  >
376
376
  <div className="flex">
@@ -254,7 +254,8 @@ const handleFilterValues = async (
254
254
  let stringifiedFilter = JSON.stringify((config as IFilterCustom).config)
255
255
 
256
256
  const placeholder = isNumber || isBoolean ? `"${VALUE_REPLACEMENT_PLACEHOLDER}"` : VALUE_REPLACEMENT_PLACEHOLDER
257
- stringifiedFilter = stringifiedFilter.replaceAll(placeholder, value).replaceAll('@', '$')
257
+ const resolvedValue = !isNumber && !isBoolean ? value.replace(/\s+/g, '').split('').join('\\\\s*') : value
258
+ stringifiedFilter = stringifiedFilter.replaceAll(placeholder, resolvedValue).replaceAll('@', '$')
258
259
 
259
260
  if (value2) stringifiedFilter = stringifiedFilter.replaceAll(VALUE_REPLACEMENT_PLACEHOLDER2, value2)
260
261
 
@@ -140,7 +140,11 @@ export const useSendNotificationAction = ({
140
140
  )
141
141
 
142
142
  const onSendNotification = useCallback(
143
- async (notifActionProps: IButtonProps_SendNotification, newFormDataId?: string) => {
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
@@ -165,6 +169,7 @@ export const useSendNotificationAction = ({
165
169
  setDataLoadingType?.(FormLoadingModalTypeEnum.GeneratingReport)
166
170
  formTemplateReportAttachments = await handleTemplateReport(formNotif.attachments!, targetFormDataId)
167
171
  }
172
+ const additionalEmailAttachments = [...formTemplateReportAttachments, ...extraAttachments]
168
173
 
169
174
  setDataLoadingType?.(FormLoadingModalTypeEnum.SendingNotification)
170
175
 
@@ -179,7 +184,7 @@ export const useSendNotificationAction = ({
179
184
  replacementData: formDataRes.data,
180
185
  formId,
181
186
  fileBaseUrl,
182
- additionalEmailAttachments: formTemplateReportAttachments,
187
+ additionalEmailAttachments,
183
188
  })
184
189
 
185
190
  if (!notificationRequests.length) {
@@ -228,6 +228,7 @@ function LayoutRenderer_Gallery({
228
228
  isOpen={isUploadModalOpen}
229
229
  formContext={formContext}
230
230
  formItem={formItem}
231
+ elementProps={elementProps}
231
232
  elementKey={elementKey}
232
233
  textConditions={textConditions}
233
234
  isDisabled={isDisabled}
@@ -1,21 +1,29 @@
1
1
  import client from '../../../../../api/client'
2
2
  import { isNewFormDataPage, resolveConditionalText } from '../../../../../functions'
3
3
  import { saveFile } from '../../../../../functions/forms/form'
4
- import { TranslationTextSubTypeEnum, TranslationTextTypeEnum } from '../../../../../enums'
4
+ import {
5
+ ButtonActionCategoryEnum,
6
+ EmailAttachmentTypeEnum,
7
+ TranslationTextSubTypeEnum,
8
+ TranslationTextTypeEnum,
9
+ } from '../../../../../enums'
5
10
  import { RcFile, UploadFile, UploadProps } from 'antd/es/upload'
6
11
  import { Form, Modal, Spin, Upload } from 'antd'
7
12
  import { useCallback, useEffect, useMemo, useState } from 'react'
8
13
  import { FaUpload } from 'react-icons/fa6'
14
+ import { useSendNotificationAction } from '../1-dynamic-button/use-send-notification.hook'
9
15
  import { Button_FillerPortal } from '../../../../common/button'
10
16
  import { useNotification, useTranslation } from '../../../../common/custom-hooks'
11
17
  import useGetCurrentBreakpoint from '../../../../common/custom-hooks/use-window-width.hook'
12
18
  import { IElementBaseProps } from '..'
13
19
  import { IFormContext } from '../../1-row'
20
+ import { IEmail_Attachment, IGalleryElementProps } from '../../../../../types'
14
21
 
15
22
  export default function GalleryUploadModal({
16
23
  isOpen,
17
24
  formContext,
18
25
  formItem,
26
+ elementProps,
19
27
  elementKey,
20
28
  textConditions,
21
29
  onDiscardSuccess,
@@ -23,6 +31,7 @@ export default function GalleryUploadModal({
23
31
  }: {
24
32
  isOpen: boolean
25
33
  formContext: IFormContext
34
+ elementProps: IGalleryElementProps
26
35
  onDiscardSuccess: () => void
27
36
  onSaveSuccess: (blobNames: string[]) => void
28
37
  } & IElementBaseProps) {
@@ -35,6 +44,13 @@ export default function GalleryUploadModal({
35
44
  const [isUploadLoading, setIsUploadLoading] = useState(false)
36
45
  const [isSaving, setIsSaving] = useState(false)
37
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
 
@@ -147,13 +163,58 @@ export default function GalleryUploadModal({
147
163
  data: JSON.stringify(parsedData),
148
164
  })
149
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
+
150
201
  setUploadedFiles([])
151
- onSaveSuccess(uploadedBlobNames)
202
+ onSaveSuccess(savedBlobNames)
152
203
  }
153
204
  } finally {
154
205
  setIsSaving(false)
155
206
  }
156
- }, [formDataId, formId, formItem.path, onSaveSuccess, uploadedBlobNames])
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,13 +225,18 @@ export default function GalleryUploadModal({
164
225
  title={title || 'Upload pictures'}
165
226
  footer={
166
227
  <div className="flex justify-between">
167
- <Button_FillerPortal outline disabled={isUploadLoading} loading={isDiscarding} onClick={discardUploadedFiles}>
228
+ <Button_FillerPortal
229
+ outline
230
+ disabled={isUploadLoading || isSendingNotification}
231
+ loading={isDiscarding}
232
+ onClick={discardUploadedFiles}
233
+ >
168
234
  {discardText || 'Discard & Close'}
169
235
  </Button_FillerPortal>
170
236
  <Button_FillerPortal
171
237
  primary
172
- disabled={isUploadLoading || isDiscarding}
173
- loading={isSaving}
238
+ disabled={isUploadLoading || isDiscarding || isSendingNotification}
239
+ loading={isSaving || isSendingNotification}
174
240
  onClick={saveUploadedFiles}
175
241
  >
176
242
  {saveText || 'Save Pictures'}
@@ -178,7 +244,7 @@ export default function GalleryUploadModal({
178
244
  </div>
179
245
  }
180
246
  >
181
- <Spin spinning={isUploadLoading}>
247
+ <Spin spinning={isUploadLoading || isSendingNotification}>
182
248
  <Upload.Dragger {...uploadProps} fileList={uploadedFiles}>
183
249
  <div className="flex flex-col items-center">
184
250
  <FaUpload size={24} className="text-primary" />
@@ -191,6 +191,8 @@ export interface IGalleryElementProps {
191
191
  grid?: Partial<Record<DeviceBreakpointEnum, IGalleryElementGridConfig | null>>
192
192
  uploadButtonConditions?: IFormLayoutElementConditions
193
193
  deleteButtonConditions?: IFormLayoutElementConditions
194
+ sendNotification?: boolean
195
+ notificationId?: number
194
196
  }
195
197
  export interface IGalleryElementGridConfig {
196
198
  count?: number | null