form-craft-package 1.7.2 → 1.7.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "form-craft-package",
3
- "version": "1.7.2",
3
+ "version": "1.7.3",
4
4
  "main": "index.ts",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1",
@@ -1,10 +1,10 @@
1
- import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
1
+ import { useCallback, useEffect, useMemo, useState } from 'react'
2
2
  import client from '../../../functions/axios-handler'
3
3
  import { parseJSON } from '../../../functions/forms/json-handlers'
4
4
  import FormDataListSkeleton_Table from '../../common/loading-skeletons/table'
5
+ import { IFormData, IFormDataListConfig, IFormSchema, IDndLayoutStructure_Responsive } from '../../../types'
5
6
  import { ICustomFunctionCall } from '../layout-renderer/3-element/1-dynamic-button'
6
- import FormDataListTableComponent from './table'
7
- import { IFormDataListConfig, IFormSchema, IFormJoin, IDndLayoutElement, IFormDataListData } from '../../../types'
7
+ import FormDataListTableComponent, { IReqDataConfig } from './table'
8
8
 
9
9
  function FormDataListComponent({
10
10
  formName,
@@ -15,12 +15,14 @@ function FormDataListComponent({
15
15
  onCustomFunctionCall,
16
16
  }: IFormDataListComponent) {
17
17
  const [loading, setLoading] = useState(true)
18
- const [dataList, setDataList] = useState<{ data: IFormDataListData[]; total: number }>({ data: [], total: 0 })
19
- const [listLayoutConfig, setListLayoutConfig] = useState<IDataListLayoutConfig>()
20
-
21
- const dataProjectRef = useRef<{ [key: string]: string }>({})
22
- const formJoinsRef = useRef<IFormJoin[]>([])
23
- const defaultFilterReqDataRef = useRef<IDataListReqData | undefined>(undefined)
18
+ const [formData, setFormData] = useState<{ data: IFormData[]; total: number }>({ data: [], total: 0 })
19
+ const [dataListConfig, setDataListConfig] = useState<
20
+ | {
21
+ dataListConfig: IFormDataListConfig & { configForFormId: number }
22
+ detailsLayoutConfig: IDndLayoutStructure_Responsive
23
+ }
24
+ | undefined
25
+ >()
24
26
 
25
27
  const attachmentBaseUrl = useMemo(() => `${baseServerUrl}/api/attachment/${companyKey}`, [baseServerUrl, companyKey])
26
28
  const dataListHeaderContext = { formId, userId, attachmentBaseUrl, formName, companyKey }
@@ -31,115 +33,50 @@ function FormDataListComponent({
31
33
  if (res.status === 200) {
32
34
  const parsedData: IFormSchema | null = parseJSON(res.data.data)
33
35
  if (parsedData) {
34
- console.log(parsedData.dataListConfig)
35
- const { columns, joins, pagination, defaultFilter, defaultSorter } = parsedData.dataListConfig
36
-
37
- if (Array.isArray(columns))
38
- dataProjectRef.current = columns.reduce(
39
- (curr, c) => (c.key ? { ...curr, [c.key.replace(/\./g, '_')]: `$${c.key}` } : curr),
40
- {},
41
- )
42
- if (Array.isArray(joins)) formJoinsRef.current = joins
43
-
44
- const defaultReqData: IDataListReqData = {}
45
- if (!pagination?.hasNoPagination) {
46
- defaultReqData.skip = 0
47
- defaultReqData.size = pagination?.defaultPageSize ?? 10
48
- }
49
- if (defaultSorter) defaultReqData.sort = JSON.stringify({ [defaultSorter.field]: defaultSorter.order })
50
- if (defaultFilter?.config)
51
- // The operators are stored using @, and here it replaces @ with $. Otherwise, MongoDB's JSON-to-BSON conversion driver was detecting certain operators, especially $regex, and automatically modified them. To prevent data manipulation by the MongoDB driver, @ is used instead of $.
52
- defaultReqData.match = JSON.stringify(defaultFilter.config).replaceAll('@', '$')
53
-
54
- defaultFilterReqDataRef.current = defaultReqData
55
-
56
- fetchFormDataList(defaultReqData)
57
-
58
36
  // configForFormId is passed to ensure that the table shows the correct data list when the forms are switched quickly
59
- setListLayoutConfig({ configForFormId: formId, dataListConfig: parsedData.dataListConfig })
37
+ setDataListConfig({
38
+ dataListConfig: { ...parsedData.dataListConfig, configForFormId: formId },
39
+ detailsLayoutConfig: {
40
+ elements: parsedData.detailsConfig.elements,
41
+ layouts: parsedData.detailsConfig.layouts,
42
+ },
43
+ })
60
44
  }
61
45
  }
62
46
  })
63
47
  }
64
48
  }, [formId])
65
49
 
66
- const fetchFormDataList = useCallback(
67
- (reqData?: IDataListReqData) => {
68
- if (!reqData || !formId) return
69
-
70
- if (!reqData.skip && defaultFilterReqDataRef.current?.skip) reqData.skip = defaultFilterReqDataRef.current.skip
71
- if (!reqData.size && defaultFilterReqDataRef.current?.size) reqData.size = defaultFilterReqDataRef.current.size
72
- if (!reqData.sort && defaultFilterReqDataRef.current?.sort) reqData.sort = defaultFilterReqDataRef.current.sort
73
- if (!reqData.match && defaultFilterReqDataRef.current?.match)
74
- reqData.match = defaultFilterReqDataRef.current.match
75
-
76
- console.log({ reqData })
50
+ const fetchFormDataList = useCallback((reqData: IReqDataConfig, dynamicFormId?: number) => {
51
+ if (!reqData || !dynamicFormId) return
77
52
 
78
- client
79
- .post(`/api/report/data/${formId}`, {
80
- joins: formJoinsRef.current,
81
- ...reqData,
82
- project: JSON.stringify(dataProjectRef.current),
83
- })
84
- .then((res) => {
85
- if (res.status === 200) setDataList({ data: res.data.data, total: res.data.totalRecords })
86
- })
87
- .finally(() => setLoading(false))
88
- },
89
- [formId],
90
- )
91
-
92
- // useEffect(() => {
93
- // client.post('/api/report/data/86', {
94
- // joins: [
95
- // // {
96
- // // formId: 85,
97
- // // foreignField: '_id',
98
- // // localField: 'Data.dId',
99
- // // alias: '85',
100
- // // },
101
- // // {
102
- // // formId: 84,
103
- // // foreignField: '_id',
104
- // // localField: '85.Data.cId',
105
- // // alias: '84',
106
- // // },
107
- // // {
108
- // // formId: 83,
109
- // // foreignField: '_id',
110
- // // localField: '84.Data.bId',
111
- // // alias: '83',
112
- // // },
113
- // // {
114
- // // formId: 82,
115
- // // foreignField: '_id',
116
- // // localField: '83.Data.aId',
117
- // // alias: '82',
118
- // // },
119
- // ],
120
- // // match: JSON.stringify({ $expr: { $eq: ['$82._id', { $toObjectId: '67b7c0a5e46d36ac56ea6548' }] } }),
121
- // sort: JSON.stringify({
122
- // '82.Data.field1': MongoDbSortOrderEnum.Descending,
123
- // 'Data.field1': MongoDbSortOrderEnum.Ascending,
124
- // }),
125
- // project: JSON.stringify({
126
- // Data_field1: '$Data.field1',
127
- // '85_Data_field1': '$85.Data.field1',
128
- // '84_Data_field1': '$84.Data.field1',
129
- // '83_Data_field1': '$83.Data.field1',
130
- // '82_Data_field1': '$82.Data.field1',
131
- // }),
132
- // skip: 0, // current
133
- // limit: 10, // pageSize
134
- // })
135
- // }, [])
53
+ client
54
+ .post(`/api/formdata/list/${dynamicFormId}`, {
55
+ ...reqData,
56
+ pagination: {
57
+ number: reqData.pagination.current,
58
+ size: reqData.pagination.pageSize,
59
+ },
60
+ })
61
+ .then((res) => {
62
+ if (res.status === 200)
63
+ setFormData({
64
+ ...res.data,
65
+ data: res.data.data.map((d: IFormData) => {
66
+ const { data, ...restD } = d
67
+ return { ...restD, ...JSON.parse(data) }
68
+ }),
69
+ })
70
+ })
71
+ .finally(() => setLoading(false))
72
+ }, [])
136
73
 
137
74
  return (
138
75
  <FormDataListTableComponent
139
- layoutsConfigs={listLayoutConfig}
140
- dataList={dataList}
76
+ {...dataListConfig}
77
+ dataList={formData}
141
78
  updateDataList={(reqData) => {
142
- fetchFormDataList(reqData)
79
+ fetchFormDataList(reqData, formId)
143
80
  }}
144
81
  parentLoading={loading}
145
82
  loadingBlock={<FormDataListSkeleton_Table />}
@@ -158,17 +95,3 @@ type IFormDataListComponent = {
158
95
  formId?: number
159
96
  userId: string | number
160
97
  } & ICustomFunctionCall
161
-
162
- export interface IDataListReqData {
163
- skip?: number
164
- size?: number
165
- sort?: string
166
- match?: string
167
- }
168
-
169
- export type IDataListLayoutConfig =
170
- | {
171
- configForFormId: number
172
- dataListConfig: IFormDataListConfig
173
- }
174
- | undefined
@@ -4,7 +4,6 @@ import {
4
4
  IDndLayoutStructure_Responsive,
5
5
  IFormData,
6
6
  IFormDataListConfig,
7
- IFormDataListData,
8
7
  IFormDataTableColumn,
9
8
  } from '../../../types'
10
9
  import FormDataListHeaderComponent from './table-header'
@@ -21,10 +20,10 @@ import {
21
20
  FormDataListViewTypeEnum,
22
21
  MongoDbSortOrderEnum,
23
22
  } from '../../../enums'
24
- import { IDataListReqData, IDataListLayoutConfig } from '.'
25
23
 
26
24
  export default function FormDataListTableComponent({
27
- layoutsConfigs,
25
+ dataListConfig,
26
+ detailsLayoutConfig,
28
27
  parentLoading,
29
28
  dataList,
30
29
  loadingBlock,
@@ -64,15 +63,16 @@ export default function FormDataListTableComponent({
64
63
  setIsHandlingSchema(true)
65
64
  }, [location.pathname])
66
65
 
67
- // useEffect(() => {
68
- // if (debouncedFilterReqData) updateDataList(debouncedFilterReqData)
69
- // }, [debouncedFilterReqData])
66
+ useEffect(() => {
67
+ if (debouncedFilterReqData) updateDataList(debouncedFilterReqData)
68
+ }, [debouncedFilterReqData])
70
69
 
71
70
  const handleDataListConfig = useCallback(
72
- async (layoutsConfigs: IDataListLayoutConfig) => {
73
- const { configForFormId, dataListConfig } = layoutsConfigs!
74
-
75
- if (configForFormId !== formId) return
71
+ async (
72
+ config: IFormDataListConfig & { configForFormId?: number },
73
+ layoutConfig?: IDndLayoutStructure_Responsive,
74
+ ) => {
75
+ if (config.configForFormId && config.configForFormId !== formId) return
76
76
 
77
77
  const {
78
78
  columns = [],
@@ -81,44 +81,42 @@ export default function FormDataListTableComponent({
81
81
  defaultFilter,
82
82
  defaultSorter,
83
83
  ...restConfigs
84
- } = dataListConfig
84
+ } = config
85
85
 
86
- console.log({ columns })
87
-
88
- // TODO:
89
- // const elementsWithOptions_key = columns.filter((op) => op.key && op.isSelectOption).map((op) => op.key)
86
+ const elementsWithOptions_key = columns
87
+ .filter((op) => op.isSelectOption)
88
+ .map((op) => (op.key.includes('Data.') ? op.key.replace('Data.', '') : op.key))
90
89
 
91
90
  let optionKeyValuePair = {}
92
- // if (elementsWithOptions_key.length > 0)
93
- // optionKeyValuePair = await extractElementsOptions(elements ?? {}, elementsWithOptions_key)
91
+ if (elementsWithOptions_key.length > 0)
92
+ optionKeyValuePair = await extractElementsOptions(layoutConfig?.elements ?? {}, elementsWithOptions_key)
94
93
 
95
94
  setTableColumns(generateTableColumns(columns, optionKeyValuePair, dataListHeaderContext))
96
95
  setHeaderLayoutConfig({
97
96
  layouts: header.layouts,
98
- elements: header.elements,
99
- // elements: appendOptionsFromDetailsLayout(header.elements, layoutConfig?.elements),
97
+ elements: appendOptionsFromDetailsLayout(header.elements, layoutConfig?.elements),
100
98
  })
101
99
  setOtherConfigs({ ...restConfigs, hasNoPagination: pagination?.hasNoPagination ?? false })
102
100
 
103
- // if (defaultFilter && defaultFilter.type !== FilterConfigTypeEnum.NoFilter)
104
- // defaultFilterRef.current = {
105
- // ...defaultFilterRef.current,
106
- // customFilter: defaultFilter.type === FilterConfigTypeEnum.ByAuthUser ? { createdById: userId } : {},
107
- // dynamicFilter: defaultFilter.config
108
- // ? // The operators are stored using @, and here it replaces @ with $. Otherwise, MongoDB's JSON-to-BSON conversion driver was detecting certain operators, especially $regex, and automatically modified them. To prevent data manipulation by the MongoDB driver, @ is used instead of $.
109
- // JSON.stringify(defaultFilter.config).replaceAll('@', '$')
110
- // : JSON.stringify({}),
111
- // }
112
- // defaultFilterRef.current = {
113
- // ...defaultFilterRef.current,
114
- // sort: defaultSorter ? { [defaultSorter.field]: defaultSorter.order } : {},
115
- // pagination: {
116
- // current: 1,
117
- // pageSize: pagination?.defaultPageSize ?? 10,
118
- // showSizeChanger: pagination?.showSizeChanger ?? false,
119
- // pageSizeOptions: pagination?.pageSizeOptions ?? [],
120
- // },
121
- // }
101
+ if (defaultFilter && defaultFilter.type !== FilterConfigTypeEnum.NoFilter)
102
+ defaultFilterRef.current = {
103
+ ...defaultFilterRef.current,
104
+ customFilter: defaultFilter.type === FilterConfigTypeEnum.ByAuthUser ? { createdById: userId } : {},
105
+ dynamicFilter: defaultFilter.config
106
+ ? // The operators are stored using @, and here it replaces @ with $. Otherwise, MongoDB's JSON-to-BSON conversion driver was detecting certain operators, especially $regex, and automatically modified them. To prevent data manipulation by the MongoDB driver, @ is used instead of $.
107
+ JSON.stringify(defaultFilter.config).replaceAll('@', '$')
108
+ : JSON.stringify({}),
109
+ }
110
+ defaultFilterRef.current = {
111
+ ...defaultFilterRef.current,
112
+ sort: defaultSorter ? { [defaultSorter.field]: defaultSorter.order } : {},
113
+ pagination: {
114
+ current: 1,
115
+ pageSize: pagination?.defaultPageSize ?? 10,
116
+ showSizeChanger: pagination?.showSizeChanger ?? false,
117
+ pageSizeOptions: pagination?.pageSizeOptions ?? [],
118
+ },
119
+ }
122
120
 
123
121
  setIsHandlingSchema(false)
124
122
  isFinishedHandlingRef.current = true
@@ -127,8 +125,8 @@ export default function FormDataListTableComponent({
127
125
  )
128
126
 
129
127
  useEffect(() => {
130
- if (layoutsConfigs) handleDataListConfig(layoutsConfigs)
131
- }, [layoutsConfigs])
128
+ if (dataListConfig) handleDataListConfig(dataListConfig, detailsLayoutConfig)
129
+ }, [dataListConfig, detailsLayoutConfig])
132
130
 
133
131
  const tableColumnsFiltered = useMemo(
134
132
  () => tableColumns.filter((op) => !Array.isArray(op.hideScreens) || !op.hideScreens.includes(currentBreakpoint)),
@@ -158,35 +156,39 @@ export default function FormDataListTableComponent({
158
156
  onCustomFunctionCall={onCustomFunctionCall}
159
157
  {...dataListHeaderContext}
160
158
  />
161
- {(!otherConfigs || otherConfigs.listType === FormDataListViewTypeEnum.Table) && (
162
- <Table<IFormDataListData>
159
+ {dataListConfig?.listType === FormDataListViewTypeEnum.Table && (
160
+ <Table<IFormData>
163
161
  dataSource={dataList.data}
164
162
  columns={tableColumnsFiltered}
165
- rowKey={(record) => record.id} // TODO: change this to _id
166
- pagination={otherConfigs?.hasNoPagination ? false : { ...filterReqData?.pagination, total: dataList.total }}
163
+ rowKey={(record) => record.id}
164
+ pagination={
165
+ otherConfigs?.hasNoPagination
166
+ ? false
167
+ : { ...defaultFilterRef.current.pagination, ...filterReqData?.pagination, total: dataList.total }
168
+ }
167
169
  loading={parentLoading}
168
- // onChange={(cbPagination, _, sorter: SorterResult<IFormData> | SorterResult<IFormData>[]) => {
169
- // console.log('ON TABLE CHANGE', cbPagination, sorter)
170
- // setParentLoading(true)
171
-
172
- // setFilterReqData((c) => {
173
- // if (!c) return c
174
-
175
- // return {
176
- // ...c,
177
- // sort:
178
- // sorter && (sorter as SorterResult<IFormData>).field
179
- // ? {
180
- // [(sorter as SorterResult<IFormData>).field as string]:
181
- // (sorter as SorterResult<IFormData>).order === 'ascend'
182
- // ? MongoDbSortOrderEnum.Ascending
183
- // : MongoDbSortOrderEnum.Descending,
184
- // }
185
- // : {},
186
- // pagination: cbPagination as IPagination,
187
- // }
188
- // })
189
- // }}
170
+ onChange={(cbPagination, _, sorter: SorterResult<IFormData> | SorterResult<IFormData>[]) => {
171
+ console.log('ON TABLE CHANGE', cbPagination, sorter)
172
+ setParentLoading(true)
173
+
174
+ setFilterReqData((c) => {
175
+ if (!c) return c
176
+
177
+ return {
178
+ ...c,
179
+ sort:
180
+ sorter && (sorter as SorterResult<IFormData>).field
181
+ ? {
182
+ [(sorter as SorterResult<IFormData>).field as string]:
183
+ (sorter as SorterResult<IFormData>).order === 'ascend'
184
+ ? MongoDbSortOrderEnum.Ascending
185
+ : MongoDbSortOrderEnum.Descending,
186
+ }
187
+ : {},
188
+ pagination: cbPagination as IPagination,
189
+ }
190
+ })
191
+ }}
190
192
  />
191
193
  )}
192
194
  </>
@@ -194,12 +196,13 @@ export default function FormDataListTableComponent({
194
196
  }
195
197
 
196
198
  type IFormDataListTableComponent = {
197
- layoutsConfigs: IDataListLayoutConfig
198
- dataList: { data: IFormDataListData[]; total: number }
199
+ dataListConfig?: IFormDataListConfig & { configForFormId?: number }
200
+ detailsLayoutConfig?: IDndLayoutStructure_Responsive
201
+ dataList: { data: IFormData[]; total: number }
199
202
  parentLoading: boolean
200
203
  loadingBlock?: JSX.Element
201
204
  setParentLoading: React.Dispatch<React.SetStateAction<boolean>>
202
- updateDataList: (reqData: IDataListReqData) => void
205
+ updateDataList: (reqData: IReqDataConfig) => void
203
206
  } & ICustomFunctionCall &
204
207
  IDataListHeaderContext
205
208
 
@@ -4,56 +4,63 @@ import LayoutRendererCol from '../2-col'
4
4
  import { memo, ReactElement, ReactNode, useMemo, useState } from 'react'
5
5
  import { LayoutRowConditionalHeaderRenderer } from './header-render'
6
6
  import { LayoutRowRepeatableRenderer } from './repeatable-render'
7
- import { IButtonElementProps, IDndLayoutElement, IFormLayoutElementConditions, IDndLayoutRow } from '../../../../types'
7
+ import {
8
+ IButtonElementProps,
9
+ IDndLayoutElement,
10
+ IFormLayoutElementConditions,
11
+ IDndLayoutRow,
12
+ } from '../../../../types'
8
13
 
9
14
  export const LayoutRendererRow = memo(
10
15
  ({ basePath = [], rowData, titleComponent, formContext, elements, renderButton }: ILayoutRendererRow) => {
11
16
  const [hiddenElementCount, setHiddenElementCount] = useState(0)
12
17
 
13
18
  const styleConfig = useMemo(() => {
14
- if (!rowData.style) return {}
19
+ if (!rowData.style || !rowData.style) return {}
15
20
  return kebabCaseToCamelCase(rowData.style)
16
21
  }, [rowData.style])
17
22
 
18
23
  return (
19
- <LayoutRowConditionalHeaderRenderer header={rowData.props?.header}>
20
- <LayoutRowRepeatableRenderer basePath={basePath} repeatingSection={rowData.props?.repeatingSection}>
21
- {(formListItemProps) => {
22
- const style: { [key: string]: any } = {
23
- ...styleConfig,
24
- ...getFlexContainerStyle(rowData.display),
25
- }
26
- if (hiddenElementCount === rowData.children.length) style.display = 'none'
24
+ <>
25
+ <LayoutRowConditionalHeaderRenderer header={rowData.props?.header}>
26
+ <LayoutRowRepeatableRenderer basePath={basePath} repeatingSection={rowData.props?.repeatingSection}>
27
+ {(formListItemProps) => {
28
+ const style: { [key: string]: any } = {
29
+ ...styleConfig,
30
+ ...getFlexContainerStyle(rowData.display),
31
+ }
32
+ if (hiddenElementCount === rowData.children.length) style.display = 'none'
27
33
 
28
- return (
29
- <div style={{ ...style, maxWidth: '100vw', overflowX: 'auto' }}>
30
- {rowData.children.map((col, colIdx) => (
31
- <LayoutRendererCol
32
- key={colIdx}
33
- basePath={formListItemProps ? formListItemProps.updatedBasePath : basePath}
34
- colData={col}
35
- titleComponent={titleComponent}
36
- elements={elements}
37
- formContext={formContext}
38
- colStyle={getColumnStyle(colIdx, rowData.display)}
39
- renderButton={renderButton}
40
- hideRow={(isHidden) =>
41
- setHiddenElementCount((c) => {
42
- if (isHidden) return c + 1
43
- else {
44
- if (c - 1 < 0) return 0
45
- return c - 1
46
- }
47
- })
48
- }
49
- />
50
- ))}
51
- {formListItemProps?.removeButton}
52
- </div>
53
- )
54
- }}
55
- </LayoutRowRepeatableRenderer>
56
- </LayoutRowConditionalHeaderRenderer>
34
+ return (
35
+ <div style={style}>
36
+ {rowData.children.map((col, colIdx) => (
37
+ <LayoutRendererCol
38
+ key={colIdx}
39
+ basePath={formListItemProps ? formListItemProps.updatedBasePath : basePath}
40
+ colData={col}
41
+ titleComponent={titleComponent}
42
+ elements={elements}
43
+ formContext={formContext}
44
+ colStyle={getColumnStyle(colIdx, rowData.display)}
45
+ renderButton={renderButton}
46
+ hideRow={(isHidden) =>
47
+ setHiddenElementCount((c) => {
48
+ if (isHidden) return c + 1
49
+ else {
50
+ if (c - 1 < 0) return 0
51
+ return c - 1
52
+ }
53
+ })
54
+ }
55
+ />
56
+ ))}
57
+ {formListItemProps?.removeButton}
58
+ </div>
59
+ )
60
+ }}
61
+ </LayoutRowRepeatableRenderer>
62
+ </LayoutRowConditionalHeaderRenderer>
63
+ </>
57
64
  )
58
65
  },
59
66
  )
@@ -8,7 +8,6 @@ export enum ElementTypeEnum {
8
8
  NumberInput = 'NumberInput',
9
9
  CurrencyInput = 'CurrencyInput',
10
10
  Select = 'Select',
11
- TreeSelect = 'TreeSelect',
12
11
  Radio = 'Radio',
13
12
  Checkbox = 'Checkbox',
14
13
  CheckboxGroup = 'CheckboxGroup',
@@ -20,7 +20,6 @@ export interface IFormDataListConfig {
20
20
  listType: FormDataListViewTypeEnum
21
21
  columns: IFormDataListColumn[]
22
22
  header: IDndLayoutStructure_Responsive
23
- joins?: IFormJoin[]
24
23
  pagination?: IFormDataListPagination
25
24
  title?: string
26
25
  showCount?: boolean
@@ -54,6 +53,3 @@ export interface IFormJoin {
54
53
  localField: string
55
54
  alias: string
56
55
  }
57
- export interface IFormDataListData {
58
- [key: string]: any
59
- }