form-craft-package 1.8.1-dev.2 → 1.8.2-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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "form-craft-package",
3
- "version": "1.8.1-dev.2",
3
+ "version": "1.8.2-dev.0",
4
4
  "main": "index.ts",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1",
@@ -1,19 +1,18 @@
1
1
  import { Form, FormInstance } from 'antd'
2
2
  import { useRef, useState } from 'react'
3
3
 
4
- export default function CustomColorField({ formRef, name, isPreview, disabled }: ICustomColorField) {
4
+ export default function CustomColorField({ formRef, name, disabled }: ICustomColorField) {
5
5
  const colorInputRef = useRef<HTMLInputElement>(null)
6
6
  const [fieldValue, setFieldValue] = useState('')
7
7
 
8
8
  const color = Form.useWatch(name, formRef)
9
9
 
10
- if (!isPreview && !formRef)
11
- <div className="text-warning italic leading-4">Form instance is missing for color field!</div>
10
+ if (!formRef) <div className="text-warning italic leading-4">Form instance is missing for color field!</div>
12
11
 
13
12
  return (
14
13
  <div
15
14
  className={`flex items-center gap-2 border bg-white rounded-lg w-full p-1 ${
16
- isPreview || disabled ? 'cursor-not-allowed' : 'cursor-pointer'
15
+ disabled ? 'cursor-not-allowed' : 'cursor-pointer'
17
16
  }`}
18
17
  onClick={() => {
19
18
  colorInputRef.current?.click()
@@ -25,11 +24,8 @@ export default function CustomColorField({ formRef, name, isPreview, disabled }:
25
24
  ref={colorInputRef}
26
25
  value={fieldValue ?? color}
27
26
  onChange={(e) => setFieldValue(e.target.value)}
28
- className={`opacity-0 absolute w-[24px] h-[24px] ${
29
- isPreview || disabled ? 'cursor-not-allowed' : 'cursor-pointer'
30
- }`}
27
+ className={`opacity-0 absolute w-[24px] h-[24px] ${disabled ? 'cursor-not-allowed' : 'cursor-pointer'}`}
31
28
  onBlur={() => formRef?.setFieldValue(name, fieldValue)}
32
- disabled={isPreview}
33
29
  />
34
30
  <div className="w-[24px] h-[24px] rounded cursor-pointer border" style={{ backgroundColor: color }}></div>
35
31
  <span className="uppercase pr-1">{color}</span>
@@ -38,7 +34,6 @@ export default function CustomColorField({ formRef, name, isPreview, disabled }:
38
34
  }
39
35
 
40
36
  interface ICustomColorField {
41
- isPreview?: boolean
42
37
  formRef?: FormInstance
43
38
  name?: string | (string | number)[]
44
39
  disabled?: boolean
@@ -5,7 +5,6 @@ export const useFormPreservedItemValues = (formRef?: FormInstance): IFormValues
5
5
  const baseServerUrl = Form.useWatch(FormPreservedItemKeys.BaseServerUrl, { form: formRef, preserve: true })
6
6
  const isGeneratingPdf = Form.useWatch(FormPreservedItemKeys.IsGeneratingPDF, { form: formRef, preserve: true })
7
7
  const hasSignature = Form.useWatch(FormPreservedItemKeys.HasSignature, { form: formRef, preserve: true })
8
- const inPreviewMode = Form.useWatch(FormPreservedItemKeys.InPreviewMode, { form: formRef, preserve: true })
9
8
  const isPublic = Form.useWatch(FormPreservedItemKeys.IsPublic, { form: formRef, preserve: true })
10
9
  const submissionPdfConfig = Form.useWatch(FormPreservedItemKeys.SubmissionPdfConfig, {
11
10
  form: formRef,
@@ -17,7 +16,6 @@ export const useFormPreservedItemValues = (formRef?: FormInstance): IFormValues
17
16
  [FormPreservedItemKeys.SubmissionPdfConfig]: submissionPdfConfig,
18
17
  [FormPreservedItemKeys.IsGeneratingPDF]: isGeneratingPdf,
19
18
  [FormPreservedItemKeys.HasSignature]: hasSignature,
20
- [FormPreservedItemKeys.InPreviewMode]: inPreviewMode,
21
19
  [FormPreservedItemKeys.IsPublic]: isPublic,
22
20
  }
23
21
  }
@@ -2,7 +2,7 @@ import { Form } from 'antd'
2
2
  import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
3
3
  import dayjs from 'dayjs'
4
4
  import { extractFiltersFromLayout } from '../../../functions/forms'
5
- import { DeviceBreakpointEnum, FilterConfigTypeEnum, FormPreservedItemKeys } from '../../../enums'
5
+ import { DeviceBreakpointEnum, FilterConfigTypeEnum } from '../../../enums'
6
6
  import { LayoutRendererRow } from '../layout-renderer/1-row'
7
7
  import useGetCurrentBreakpoint from '../../common/custom-hooks/use-window-width.hook'
8
8
  import { IDataListHeaderLayoutContext } from './table'
@@ -52,10 +52,6 @@ export default function FormDataListHeaderComponent({
52
52
 
53
53
  const filterValues = Form.useWatch([], filtersFormRef)
54
54
 
55
- useEffect(() => {
56
- if (filtersFormRef) filtersFormRef.setFieldsValue({ [FormPreservedItemKeys.InPreviewMode]: false })
57
- }, [filtersFormRef])
58
-
59
55
  const organizeFilterData = useCallback(
60
56
  async (values: { [key: string]: any }) => {
61
57
  const filtersWithConfig: [string, string][] = Object.entries(values).filter(
@@ -101,8 +101,6 @@ export default function FormDataListTableComponent({
101
101
  [tableColumns, currentBreakpoint],
102
102
  )
103
103
 
104
- // if (loading) return
105
- console.log(loading, parentLoadings)
106
104
  if ((loading || parentLoadings.initial) && loadingBlock) return loadingBlock
107
105
 
108
106
  return (
@@ -2,11 +2,6 @@ import { Form, Spin } from 'antd'
2
2
  import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
3
3
  import { IDndLayoutStructure_Responsive } from '../../../types'
4
4
  import { LayoutRendererRow } from '../layout-renderer/1-row'
5
- import {
6
- DynamicFormButtonRender,
7
- ICustomFunctionCall,
8
- IDynamicButton_DisplayStateProps,
9
- } from '../layout-renderer/3-element/1-dynamic-button'
10
5
  import FormDataListSkeleton_Details from '../../common/loading-skeletons/details'
11
6
  import { useLocation } from 'react-router-dom'
12
7
  import useGetCurrentBreakpoint from '../../common/custom-hooks/use-window-width.hook'
@@ -19,6 +14,12 @@ import { UserAuth } from '../../../api/user'
19
14
  import { useCacheFormLayoutConfig } from '../../common/custom-hooks/use-cache-form-layout-config.hook'
20
15
  import { useSetHiddenNodes } from '../../common/custom-hooks/use-node-condition.hook/use-hidden-elements.hook'
21
16
  import { useSetDisabledElements } from '../../common/custom-hooks/use-node-condition.hook/use-disabled-elements.hook'
17
+ import { ELEMENTS_DEFAULT_CLASS } from '../../../constants'
18
+ import {
19
+ DynamicFormButtonRender,
20
+ ICustomFunctionCall,
21
+ IDynamicButton_DisplayStateProps,
22
+ } from '../layout-renderer/3-element/1-dynamic-button'
22
23
  import {
23
24
  fromMongoDbExtendedJSON,
24
25
  getPickerFieldsWithOriginalTz,
@@ -26,7 +27,6 @@ import {
26
27
  isValidMongoDbId,
27
28
  queryParamsToObject,
28
29
  } from '../../../functions/forms'
29
- import { ELEMENTS_DEFAULT_CLASS } from '../../../constants'
30
30
 
31
31
  export default function FormDataDetailsComponent({
32
32
  isPublic,
@@ -94,7 +94,6 @@ export default function FormDataDetailsComponent({
94
94
  formDataRef.setFieldsValue({
95
95
  [FormPreservedItemKeys.BaseServerUrl]: baseServerUrl,
96
96
  [FormPreservedItemKeys.IsPublic]: isPublic,
97
- [FormPreservedItemKeys.InPreviewMode]: false,
98
97
  })
99
98
  }, [formDataRef, baseServerUrl, isPublic])
100
99
 
@@ -18,11 +18,11 @@ import { useButtonNavigateAction } from './use-button-navigate.hook'
18
18
  import { constructDynamicFormHref, isNewFormDataPage } from '../../../../../functions'
19
19
  import { useCustomFunctionCallAction } from './use-custom-function-call.hook'
20
20
  import { IButtonElementProps, IButtonProps_Other, IButtonProps_Navigate } from '../../../../../types'
21
+ import { ELEMENTS_DEFAULT_CLASS } from '../../../../../constants'
21
22
  import {
22
23
  useIsNodeDisabled,
23
24
  useIsNodeHidden,
24
25
  } from '../../../../common/custom-hooks/use-node-condition.hook/use-node-condition.hook'
25
- import { ELEMENTS_DEFAULT_CLASS } from '../../../../../constants'
26
26
 
27
27
  export const DynamicFormButtonRender = memo((props: IDynamicButton) => {
28
28
  const { displayStateProps = {}, formContext = {}, onCustomFunctionCall = () => {} } = props
@@ -33,7 +33,7 @@ export const DynamicFormButtonRender = memo((props: IDynamicButton) => {
33
33
  const { success, warning, error, confirmModal } = useNotification()
34
34
  const [loading, setLoading] = useState(false)
35
35
  const [dataLoadingType, setDataLoadingType] = useState<FormLoadingModalTypeEnum | undefined>()
36
- const { inPreviewMode, isPublic = false, submissionPdfConfig } = useFormPreservedItemValues(formRef)
36
+ const { isPublic = false, submissionPdfConfig } = useFormPreservedItemValues(formRef)
37
37
 
38
38
  const isElementHidden = useIsNodeHidden(btnKey)
39
39
  const isElementDisabled = useIsNodeDisabled(btnKey)
@@ -227,7 +227,6 @@ export const DynamicFormButtonRender = memo((props: IDynamicButton) => {
227
227
  disabled={isElementDisabled}
228
228
  className={`${ELEMENTS_DEFAULT_CLASS.Button} w-full ${isElementHidden ? 'hidden' : ''}`}
229
229
  onClick={(e) => {
230
- if (inPreviewMode) return
231
230
  if (
232
231
  isPublic &&
233
232
  isNewFormDataPage(formDataId) &&
@@ -252,7 +251,6 @@ export const DynamicFormButtonRender = memo((props: IDynamicButton) => {
252
251
  btnProps.category !== ButtonActionCategoryEnum.SaveDataChanges && (
253
252
  <WarningIcon tooltip={BUTTON_CUSTOM_ERROR_MESSAGES.UnavailableForPublic} />
254
253
  )}
255
- {inPreviewMode && <WarningIcon tooltip={BUTTON_CUSTOM_ERROR_MESSAGES.InPreviewMode} />}
256
254
  {btnProps.label}
257
255
  </Button_FillerPortal>
258
256
  {!!dataLoadingType && (
@@ -296,5 +294,4 @@ export const BUTTON_CUSTOM_ERROR_MESSAGES = {
296
294
  DataIdNotFound: 'Data id was not found!',
297
295
  FormInstanceNotFound: 'Form ref was not found!',
298
296
  UnavailableForPublic: 'Button action is NOT allowed for public use!',
299
- InPreviewMode: 'Buttons will not work in preview mode!',
300
297
  }
@@ -20,7 +20,7 @@ export default function LayoutRenderer_Signature({
20
20
  const { formRef, formDataId, companyKey } = formContext
21
21
  const sigCanvasRef = useRef<SignatureCanvas>(null)
22
22
  const savedSignatureBlobName = Form.useWatch(formItem.path, formRef)
23
- const { isGeneratingPdf, baseServerUrl, inPreviewMode } = useFormPreservedItemValues(formRef)
23
+ const { isGeneratingPdf, baseServerUrl } = useFormPreservedItemValues(formRef)
24
24
 
25
25
  useEffect(() => {
26
26
  if (isDisabled) sigCanvasRef.current?.off()
@@ -55,7 +55,7 @@ export default function LayoutRenderer_Signature({
55
55
  }
56
56
  labelAlign="left"
57
57
  >
58
- {(inPreviewMode || isNewFormDataPage(formDataId)) && !isGeneratingPdf ? (
58
+ {isNewFormDataPage(formDataId) && !isGeneratingPdf ? (
59
59
  <SignatureCanvas
60
60
  ref={sigCanvasRef}
61
61
  canvasProps={{
@@ -3,7 +3,6 @@ import { PageViewTypEnum, FieldElementOptionSourceEnum, FilterConfigTypeEnum } f
3
3
  import { IElementBaseProps } from '.'
4
4
  import { LayoutRenderer_FieldElement } from './2-field-element'
5
5
  import { getElementGeneralizedProps } from '../../../../functions/forms/get-element-props'
6
- import { useFormPreservedItemValues } from '../../../common/custom-hooks/use-preserved-form-items.hook'
7
6
  import { IFormContext } from '../1-row'
8
7
  import { cancelableClient } from '../../../../api/client'
9
8
  import { useBreadcrumb } from '../../../common/custom-hooks/use-breadcrumb.hook'
@@ -36,7 +35,6 @@ export default function LayoutRenderer_FieldsWithOptions({
36
35
  const { getFormById } = useFindDynamiForm()
37
36
 
38
37
  const { formRef, formId, formDataId, detailPageFormId } = formContext
39
- const { inPreviewMode } = useFormPreservedItemValues(formRef)
40
38
  const { breadcrumbs, push } = useBreadcrumb()
41
39
 
42
40
  const props = getElementGeneralizedProps(elementData.props)
@@ -193,12 +191,12 @@ export default function LayoutRenderer_FieldsWithOptions({
193
191
  )
194
192
 
195
193
  useEffect(() => {
196
- if (!props.optionSource || inPreviewMode === undefined) return
194
+ if (!props.optionSource) return
197
195
 
198
196
  if (props.optionSource.type === FieldElementOptionSourceEnum.Static) {
199
197
  setOptions(props.optionSource.options.map((op: IFormLayoutFieldOption) => ({ value: op.id, label: op.value })))
200
198
  setLoading(false)
201
- } else if (!inPreviewMode) {
199
+ } else {
202
200
  switch (props.optionSource.type) {
203
201
  case FieldElementOptionSourceEnum.DynamicForm:
204
202
  fetchFormData(props.optionSource)
@@ -214,8 +212,8 @@ export default function LayoutRenderer_FieldsWithOptions({
214
212
  setLoading(false)
215
213
  return
216
214
  }
217
- } else setLoading(false)
218
- }, [props.optionSource, inPreviewMode, fetchLinkedFormData, fetchFormData, cachedConfig])
215
+ }
216
+ }, [props.optionSource, fetchLinkedFormData, fetchFormData, cachedConfig])
219
217
 
220
218
  useEffect(() => {
221
219
  return () => {
@@ -33,8 +33,6 @@ export default function LayoutRenderer_LoadFormData({ formContext, elementProps
33
33
  const formJoinsRef = useRef<IFormJoin[]>([])
34
34
  const m2mForeignKeysRef = useRef<{ currentForm: string; otherForm: string } | undefined>()
35
35
 
36
- console.log({ cachedConfig })
37
-
38
36
  const fetchDataList = useCallback(
39
37
  (
40
38
  headerAppliedFilters: string = initialFilter && initialFilter.type === FilterConfigTypeEnum.Custom
@@ -2,7 +2,6 @@ export * from './form/layout-renderer/1-row'
2
2
  export * from './form/layout-renderer/3-element/1-dynamic-button'
3
3
  export * from './form/1-list'
4
4
  export * from './form/2-details'
5
- export * from './form/3-preview'
6
5
  export * from './common/button'
7
6
  export * from './report/1-list'
8
7
  export * from './companies'
package/src/constants.ts CHANGED
@@ -197,7 +197,6 @@ export const ELEMENTS_DEFAULT_CLASS = {
197
197
  DataTable: 'fc-form-data-table',
198
198
  DataListHeaderForm: 'fc-data-list-header-form',
199
199
  DataDetailsForm: 'fc-data-details-form',
200
- PreviewForm: 'fc-preview-form',
201
200
  LayoutRowContainer: 'fc-layout-row-container',
202
201
  LayoutRow: 'fc-layout-row',
203
202
  LayoutCol: 'fc-layout-col',
@@ -137,7 +137,6 @@ export enum FormPreservedItemKeys {
137
137
  SubmissionPdfConfig = 'submissionPdfConfig',
138
138
  IsGeneratingPDF = 'isGeneratingPdf',
139
139
  HasSignature = 'hasSignature',
140
- InPreviewMode = 'inPreviewMode',
141
140
  IsPublic = 'isPublic',
142
141
  }
143
142
  export enum DataCategoryEnum {
@@ -25,7 +25,8 @@ export async function processOptions(options: IFormDataListColumn[]): Promise<{
25
25
 
26
26
  groupedRequests.forEach((paths, formId) => {
27
27
  const cachedConfig = REACT_QUERY_CLIENT.getQueryData(['layoutConfig', String(formId)])
28
- if (cachedConfig) apiCallPromises.push(Promise.resolve({ _id: '-1', Data: cachedConfig }))
28
+
29
+ if (cachedConfig) apiCallPromises.push(Promise.resolve({ _id: '-1', Data: extractByDotPaths(paths, cachedConfig) }))
29
30
  else
30
31
  apiCallPromises.push(
31
32
  client.post(`/api/form/${formId}`, { project: JSON.stringify(paths) }).then((res) => res.data),
@@ -73,3 +74,34 @@ export async function processOptions(options: IFormDataListColumn[]): Promise<{
73
74
  await Promise.all(dynamicApiPromises)
74
75
  return finalResult
75
76
  }
77
+
78
+ export function extractByDotPaths(paths: Record<string, any>, source: Record<string, any>): Record<string, any> {
79
+ const result: Record<string, any> = {}
80
+
81
+ for (const rawPath of Object.keys(paths)) {
82
+ const parts = rawPath.split('.')
83
+ if (parts[0] === 'Data') parts.shift()
84
+
85
+ let cursor: any = source
86
+ for (const segment of parts) {
87
+ if (cursor != null && segment in cursor) cursor = cursor[segment]
88
+ else {
89
+ cursor = undefined
90
+ break
91
+ }
92
+ }
93
+
94
+ if (cursor !== undefined) {
95
+ let target = result
96
+ for (const segment of parts.slice(0, -1)) {
97
+ if (!(segment in target)) target[segment] = {}
98
+
99
+ target = target[segment]
100
+ }
101
+
102
+ target[parts[parts.length - 1]] = cursor
103
+ }
104
+ }
105
+
106
+ return result
107
+ }
@@ -1,47 +0,0 @@
1
- import { Form } from 'antd'
2
- import { IDndLayoutStructure } from '../../../types'
3
- import { FormPreservedItemKeys } from '../../../enums'
4
- import { LayoutRendererRow } from '../layout-renderer/1-row'
5
- import { useNotification } from '../../common/custom-hooks'
6
- import { useEffect, useMemo } from 'react'
7
- import {
8
- DynamicFormButtonRender,
9
- IDynamicButton_DisplayStateProps,
10
- } from '../layout-renderer/3-element/1-dynamic-button'
11
- import { ELEMENTS_DEFAULT_CLASS } from '../../../constants'
12
-
13
- export const FormPreviewComponent = ({
14
- layout,
15
- elements = {},
16
- dataCount,
17
- }: { dataCount?: 'pending' | number } & IDndLayoutStructure) => {
18
- const [previewFormRef] = Form.useForm()
19
- const { infoModal } = useNotification()
20
-
21
- useEffect(() => {
22
- previewFormRef.setFieldValue(FormPreservedItemKeys.InPreviewMode, true)
23
- }, [previewFormRef])
24
-
25
- const formContext = useMemo(() => ({ formRef: previewFormRef }), [previewFormRef])
26
-
27
- return (
28
- <Form layout="vertical" form={previewFormRef} className={ELEMENTS_DEFAULT_CLASS.PreviewForm}>
29
- {layout.map((row, rowIdx) => (
30
- <LayoutRendererRow
31
- key={rowIdx}
32
- rowData={row}
33
- dataCount={dataCount}
34
- formContext={formContext}
35
- elements={elements}
36
- renderButton={(btnProps) => (
37
- <DynamicFormButtonRender
38
- displayStateProps={btnProps as IDynamicButton_DisplayStateProps}
39
- formContext={formContext}
40
- onCustomFunctionCall={() => infoModal({ content: 'Custom function call!' })}
41
- />
42
- )}
43
- />
44
- ))}
45
- </Form>
46
- )
47
- }