@tsed/react-formio 2.0.3 → 2.1.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.
Files changed (39) hide show
  1. package/coverage.json +4 -4
  2. package/dist/components/actions-table/actionsTable.component.d.ts +1 -1
  3. package/dist/components/form-access/formAccess.component.d.ts +1 -1
  4. package/dist/components/form-edit/formEdit.stories.d.ts +1 -1
  5. package/dist/components/forms-table/formsTable.component.d.ts +1 -1
  6. package/dist/components/submissions-table/submissionsTable.component.d.ts +1 -1
  7. package/dist/components/table/components/defaultCells.component.d.ts +4 -0
  8. package/dist/components/table/components/defaultRow.component.d.ts +12 -0
  9. package/dist/components/table/components/dragNDropContainer.d.ts +4 -0
  10. package/dist/components/table/hooks/useCustomTable.hook.d.ts +187 -0
  11. package/dist/components/table/hooks/useDragnDropRow.hook.d.ts +266 -0
  12. package/dist/components/table/index.d.ts +2 -1
  13. package/dist/components/table/table.component.d.ts +2 -71
  14. package/dist/components/table/table.stories.d.ts +25 -0
  15. package/dist/components/table/utils/swapElements.d.ts +1 -0
  16. package/dist/components/table/utils/swapElements.spec.d.ts +1 -0
  17. package/dist/index.js +315 -88
  18. package/dist/index.js.map +1 -1
  19. package/dist/index.modern.js +445 -225
  20. package/dist/index.modern.js.map +1 -1
  21. package/package.json +5 -3
  22. package/src/components/actions-table/actionsTable.component.tsx +2 -1
  23. package/src/components/form-access/formAccess.component.tsx +1 -1
  24. package/src/components/form-edit/formEdit.stories.tsx +2 -2
  25. package/src/components/forms-table/formsTable.component.tsx +2 -1
  26. package/src/components/forms-table/formsTable.stories.tsx +2 -2
  27. package/src/components/submissions-table/submissionsTable.component.tsx +2 -1
  28. package/src/components/table/components/defaultCells.component.tsx +21 -0
  29. package/src/components/table/components/defaultRow.component.tsx +50 -0
  30. package/src/components/table/components/dragNDropContainer.tsx +7 -0
  31. package/src/components/table/hooks/useCustomTable.hook.tsx +231 -0
  32. package/src/components/table/hooks/useDragnDropRow.hook.ts +80 -0
  33. package/src/components/table/index.ts +2 -1
  34. package/src/components/table/table.component.tsx +83 -233
  35. package/src/components/table/table.stories.tsx +56 -0
  36. package/src/components/table/utils/swapElements.spec.ts +7 -0
  37. package/src/components/table/utils/swapElements.ts +7 -0
  38. /package/dist/components/table/{utils → hooks}/useOperations.hook.d.ts +0 -0
  39. /package/src/components/table/{utils → hooks}/useOperations.hook.tsx +0 -0
@@ -1,247 +1,97 @@
1
1
  import classnames from "classnames";
2
- import noop from "lodash/noop";
3
2
  import React, { PropsWithChildren } from "react";
4
- import { CellProps, FilterProps, Renderer, TableOptions, useFilters, useGroupBy, usePagination, useSortBy, useTable } from "react-table";
5
-
6
- import { OnClickOperation, Operation, QueryOptions } from "../../interfaces";
7
- import { Pagination as DefaultPagination } from "../pagination/pagination.component";
8
- import { DefaultArrowSort } from "./components/defaultArrowSort.component";
9
- import { DefaultCellHeader, DefaultCellHeaderProps } from "./components/defaultCellHeader.component";
10
- import { DefaultColumnFilter } from "./filters/defaultColumnFilter.component";
11
- import { useOperations } from "./utils/useOperations.hook";
12
-
13
- export interface TableProps<Data extends object = any> extends TableOptions<Data>, Partial<QueryOptions> {
14
- className?: string;
15
- /**
16
- * Call the listener when a filter / pagination / sort change.
17
- */
18
- onChange?: (query: QueryOptions) => void;
19
- /**
20
- * Call the listener when a line is clicked.
21
- */
22
- onClick?: OnClickOperation<Data>;
23
- /**
24
- * Pagination steps list
25
- */
26
- pageSizes?: number[];
27
- /**
28
- *
29
- */
30
- isLoading?: boolean;
31
- /**
32
- * Custom EmptyData displayed when there is no data
33
- */
34
- EmptyData?: React.ComponentType;
35
- /**
36
- * Custom ArrowSort
37
- */
38
- ArrowSort?: React.ComponentType;
39
- /**
40
- * Custom default ColumnFilter
41
- */
42
- ColumnFilter?: Renderer<FilterProps<Data>>;
43
- /**
44
- * Custom cell
45
- */
46
- Cell?: React.ComponentType<CellProps<Data>>;
47
- /**
48
- *
49
- */
50
- CellHeader?: React.ComponentType<DefaultCellHeaderProps<Data>>;
51
- /**
52
- *
53
- */
54
- CellOperations?: React.ComponentType;
55
- /**
56
- * Custom Loader
57
- */
58
- Loader?: React.ComponentType;
59
- /**
60
- * Custom Loader
61
- */
62
- Pagination?: React.ComponentType;
63
- /**
64
- * Disable filters
65
- */
66
- disableFilters?: boolean;
67
- /**
68
- * Disable pagination
69
- */
70
- disablePagination?: boolean;
71
- manualPagination?: boolean;
72
- manualSortBy?: boolean;
73
- manualFilters?: boolean;
74
- /**
75
- * Configuration operation for each line.
76
- */
77
- operations?: Operation[];
78
-
79
- i18n?: (f: string) => string;
80
- }
81
-
82
- function getOperationCallback(operations: Operation[], onClick: OnClickOperation) {
83
- return (data: any, action: string) => {
84
- const operation = operations.find((operation) => operation.action === action || operation.alias === action);
85
- if (operation) {
86
- onClick(data, operation);
87
- }
88
- };
89
- }
90
-
91
- function DefaultLoader() {
92
- return <div className={"text-center p-2 pb-4 font-bold"}>Loading in progress</div>;
93
- }
94
-
95
- function DefaultEmptyData() {
96
- return <div className='text-center p-2 pb-4 font-bold'>No data found</div>;
97
- }
98
-
99
- const hooks = [useFilters, useGroupBy, useSortBy, usePagination];
100
3
 
4
+ import { DrapNDropContainer } from "./components/dragNDropContainer";
5
+ import { TableProps, useCustomTable } from "./hooks/useCustomTable.hook";
101
6
  export function Table<Data extends object = any>(props: PropsWithChildren<TableProps<Data>>) {
102
7
  const {
103
- children,
104
- className = "",
105
- columns,
106
- data,
107
- onChange = noop,
108
- onClick = noop,
109
- operations = [],
110
- pageSizes = [10, 25, 50, 100],
111
- filters: controlledFilters,
112
- filterId: controlledFilterId,
113
- pageSize: controlledPageSize,
114
- pageIndex: controlledPageIndex,
115
- sortBy: controlledSortBy,
8
+ className,
9
+ tableInstance,
10
+ CellHeader,
116
11
  isLoading,
117
- disableFilters,
12
+ onClick,
13
+ Loader,
14
+ EmptyData,
15
+ Row,
16
+ data,
118
17
  disablePagination,
119
- ArrowSort = DefaultArrowSort,
120
- ColumnFilter = DefaultColumnFilter,
121
- EmptyData = DefaultEmptyData,
122
- Loader = DefaultLoader,
123
- Pagination = DefaultPagination,
124
- CellHeader = DefaultCellHeader as any,
125
- CellOperations,
126
- i18n = (f: string) => f,
127
- ...ctx
128
- } = props;
129
-
130
- const _onClick = getOperationCallback(operations, onClick);
131
-
132
- const defaultColumn = React.useMemo(
133
- () => ({
134
- // Let's set up our default Filter UI
135
- Filter: ColumnFilter,
136
- ArrowSort
137
- }),
138
- [ColumnFilter, ArrowSort]
139
- ) as any;
140
-
141
- const [filterId, setFilterId] = React.useState(controlledFilterId);
142
-
143
- const tableInstance = useTable<Data>(
144
- {
145
- ...props,
146
- columns,
147
- data,
148
- ctx,
149
- defaultColumn,
150
- initialState: {
151
- ...(props.initialState || {}),
152
- filters: controlledFilters || [],
153
- pageIndex: controlledPageIndex || 0,
154
- pageSize: controlledPageSize || 10,
155
- sortBy: controlledSortBy || []
156
- } as any,
157
- manualPagination: props.manualPagination === undefined ? true : props.manualPagination,
158
- manualSortBy: props.manualSortBy === undefined ? true : props.manualPagination,
159
- manualFilters: props.manualFilters === undefined ? true : props.manualFilters,
160
- disableFilters,
161
- filterId,
162
- setFilterId
163
- } as any,
164
- ...hooks,
165
- useOperations({ operations, CellOperations, onClick: _onClick, ctx, i18n })
166
- );
167
-
168
- const {
18
+ Pagination,
19
+ pageIndex,
20
+ pageSize,
21
+ pageSizes,
169
22
  setPageSize,
170
- state: { pageIndex, pageSize, sortBy, filters }
171
- } = tableInstance;
172
-
173
- React.useEffect(() => {
174
- onChange({
175
- pageIndex,
176
- pageSize,
177
- sortBy,
178
- filters,
179
- filterId
180
- });
181
- }, [onChange, pageIndex, pageSize, sortBy, filters, filterId]);
23
+ i18n,
24
+ enableDragNDrop,
25
+ children,
26
+ onDrag,
27
+ onDrop
28
+ } = useCustomTable(props);
182
29
 
183
30
  // Render the UI for your table
184
31
  return (
185
- <div className={classnames("table-group table-responsive", className)}>
186
- <table
187
- className={"table table-striped table-hover"}
188
- {...tableInstance.getTableProps()}
189
- /* style={{ marginBottom: disablePagination ? "-1px" : "0px" }} */
190
- >
191
- <thead>
192
- {tableInstance.headerGroups.map((headerGroup, i) => (
193
- <tr {...headerGroup.getHeaderGroupProps()} key={`tableInstance.headerGroups${i}`}>
194
- {headerGroup.headers.map((column) => (
195
- <th
196
- /* className='text-left py-2 align-top' */
197
- {...column.getHeaderProps()}
198
- key={`tableInstance.headers.column.${column.id}`}
199
- >
200
- <CellHeader column={column} />
201
- </th>
202
- ))}
203
- </tr>
204
- ))}
205
- </thead>
206
- {!isLoading ? (
207
- <tbody {...tableInstance.getTableBodyProps()}>
208
- {tableInstance.page.map((row) => {
209
- tableInstance.prepareRow(row);
210
- return (
211
- <tr onClick={() => _onClick(row.original, "row")} {...row.getRowProps()} key={`tableInstance.page.${row.id}`}>
212
- {row.cells.map((cell, i) => {
213
- const { hidden, colspan } = cell.column as any;
214
- if (hidden) {
215
- return null;
216
- }
217
- return (
218
- <td colSpan={colspan} {...cell.getCellProps()} key={`tableInstance.page.cells.${cell.value || "value"}.${i}`}>
219
- {cell.render("Cell")}
220
- </td>
221
- );
222
- })}
223
- </tr>
224
- );
225
- })}
226
- </tbody>
32
+ <DrapNDropContainer enableDragNDrop={enableDragNDrop}>
33
+ <div className={classnames("table-group table-responsive", className)}>
34
+ <table
35
+ className={"table table-striped table-hover"}
36
+ {...tableInstance.getTableProps()}
37
+ /* style={{ marginBottom: disablePagination ? "-1px" : "0px" }} */
38
+ >
39
+ <thead>
40
+ {tableInstance.headerGroups.map((headerGroup, i) => (
41
+ <tr {...headerGroup.getHeaderGroupProps()} key={`tableInstance.headerGroups${i}`}>
42
+ {enableDragNDrop ? (
43
+ <th role='columnheader' className='text-center'>
44
+ <div className='table-cell-header'></div>
45
+ </th>
46
+ ) : null}
47
+ {headerGroup.headers.map((column) => (
48
+ <th
49
+ /* className='text-left py-2 align-top' */
50
+ {...column.getHeaderProps()}
51
+ key={`tableInstance.headers.column.${column.id}`}
52
+ >
53
+ <CellHeader column={column} />
54
+ </th>
55
+ ))}
56
+ </tr>
57
+ ))}
58
+ </thead>
59
+ {!isLoading ? (
60
+ <tbody {...tableInstance.getTableBodyProps()}>
61
+ {tableInstance.page.map((row, index) => {
62
+ tableInstance.prepareRow(row);
63
+ return (
64
+ <Row<Data>
65
+ index={index}
66
+ enableDragNDrop={enableDragNDrop}
67
+ onClick={onClick}
68
+ row={row}
69
+ key={`tableInstance.page.${row.id}`}
70
+ onDrag={onDrag}
71
+ onDrop={onDrop}
72
+ />
73
+ );
74
+ })}
75
+ </tbody>
76
+ ) : null}
77
+ </table>
78
+ {isLoading ? <Loader /> : null}
79
+ {!data.length ? <EmptyData /> : null}
80
+ {!isLoading && data.length && !disablePagination ? (
81
+ <div className={"overflow-hidden"}>
82
+ <Pagination
83
+ {...tableInstance}
84
+ className={"text-sm"}
85
+ pageIndex={pageIndex}
86
+ pageSize={pageSize}
87
+ pageSizes={pageSizes}
88
+ setPageSize={setPageSize}
89
+ i18n={i18n}
90
+ />
91
+ </div>
227
92
  ) : null}
228
- </table>
229
- {isLoading ? <Loader /> : null}
230
- {!data.length ? <EmptyData /> : null}
231
- {!isLoading && data.length && !disablePagination ? (
232
- <div className={"overflow-hidden"}>
233
- <Pagination
234
- {...tableInstance}
235
- className={"text-sm"}
236
- pageIndex={pageIndex}
237
- pageSize={pageSize}
238
- pageSizes={pageSizes}
239
- setPageSize={setPageSize}
240
- i18n={i18n}
241
- />
242
- </div>
243
- ) : null}
244
- {children}
245
- </div>
93
+ {children}
94
+ </div>
95
+ </DrapNDropContainer>
246
96
  );
247
97
  }
@@ -62,3 +62,59 @@ Sandbox.args = {
62
62
  }
63
63
  ]
64
64
  };
65
+
66
+ export const TableWithDragNDrop = (args: any) => {
67
+ const [skip, setSkip] = React.useState(0);
68
+ const [limit, setLimit] = React.useState(10);
69
+ const [serverCount] = React.useState(87);
70
+ const [data, setData] = React.useState(() => formSubmissions);
71
+
72
+ const onChange = (obj: any) => {
73
+ setLimit(obj.pageSize);
74
+ setSkip(obj.pageIndex * obj.pageSize);
75
+ args.onChange && args.onChange(obj);
76
+ };
77
+
78
+ return (
79
+ <Table
80
+ {...args}
81
+ data={data}
82
+ onChange={onChange}
83
+ {...mapPagination({
84
+ skip,
85
+ limit,
86
+ serverCount
87
+ })}
88
+ onDrag={(data) => {
89
+ setData(data);
90
+ }}
91
+ />
92
+ );
93
+ };
94
+
95
+ TableWithDragNDrop.args = {
96
+ enableDragNDrop: true,
97
+ data: [],
98
+ columns: mapFormToColumns(formSchema as any),
99
+ operations: [
100
+ {
101
+ title: "Edit",
102
+ action: "edit",
103
+ alias: "row",
104
+ path: "/resources/:resourceId/submissions/:submissionId",
105
+ icon: "edit",
106
+ permissionsResolver() {
107
+ return true;
108
+ }
109
+ },
110
+ {
111
+ action: "delete",
112
+ path: "/resources/:resourceId/submissions/:submissionId/delete",
113
+ icon: "trash",
114
+ buttonType: "danger",
115
+ permissionsResolver() {
116
+ return true;
117
+ }
118
+ }
119
+ ]
120
+ };
@@ -0,0 +1,7 @@
1
+ import { swapElements } from "./swapElements";
2
+
3
+ describe("swapElements", () => {
4
+ it("should swap elements in array", () => {
5
+ expect(swapElements([1, 2, 3, 4, 5], 1, 3)).toEqual([1, 4, 3, 2, 5]);
6
+ });
7
+ });
@@ -0,0 +1,7 @@
1
+ export const swapElements = <T = any>(myArray: T[], index1: number, index2: number): T[] => {
2
+ myArray = [...myArray];
3
+
4
+ [myArray[index1], myArray[index2]] = [myArray[index2], myArray[index1]];
5
+
6
+ return myArray;
7
+ };