@teselagen/ui 0.5.21 → 0.5.23-beta.1

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 (76) hide show
  1. package/DataTable/Columns.d.ts +1 -0
  2. package/DataTable/DisplayOptions.d.ts +14 -14
  3. package/DataTable/EditabelCell.d.ts +3 -5
  4. package/DataTable/FilterAndSortMenu.d.ts +9 -9
  5. package/DataTable/PagingTool.d.ts +25 -2
  6. package/DataTable/SearchBar.d.ts +2 -2
  7. package/DataTable/SortableColumns.d.ts +6 -9
  8. package/DataTable/ThComponent.d.ts +9 -0
  9. package/DataTable/index.d.ts +0 -5
  10. package/DataTable/utils/getIdOrCodeOrIndex.d.ts +1 -2
  11. package/DataTable/utils/handleCopyTable.d.ts +1 -0
  12. package/DataTable/utils/index.d.ts +4 -2
  13. package/DataTable/utils/primarySelectedValue.d.ts +1 -0
  14. package/DataTable/utils/queryParams.d.ts +6 -0
  15. package/DataTable/utils/removeCleanRows.d.ts +1 -1
  16. package/DataTable/utils/rowClick.d.ts +24 -3
  17. package/DataTable/utils/useDeepEqualMemo.d.ts +1 -0
  18. package/DataTable/utils/useTableParams.d.ts +49 -0
  19. package/FormComponents/Uploader.d.ts +34 -1
  20. package/FormComponents/index.d.ts +111 -45
  21. package/MatchHeaders.d.ts +9 -10
  22. package/SimpleStepViz.d.ts +2 -1
  23. package/TgSuggest/index.d.ts +1 -21
  24. package/UploadCsvWizard.d.ts +1 -1
  25. package/index.cjs.js +41038 -45265
  26. package/index.d.ts +3 -2
  27. package/index.es.js +44524 -48751
  28. package/package.json +2 -8
  29. package/src/DataTable/CellDragHandle.js +70 -69
  30. package/src/DataTable/ColumnFilterMenu.js +18 -18
  31. package/src/DataTable/Columns.js +1066 -0
  32. package/src/DataTable/DisplayOptions.js +173 -192
  33. package/src/DataTable/EditabelCell.js +6 -16
  34. package/src/DataTable/FilterAndSortMenu.js +213 -234
  35. package/src/DataTable/PagingTool.js +47 -56
  36. package/src/DataTable/SearchBar.js +3 -3
  37. package/src/DataTable/SortableColumns.js +44 -39
  38. package/src/DataTable/ThComponent.js +44 -0
  39. package/src/DataTable/dataTableEnhancer.js +35 -294
  40. package/src/DataTable/index.js +2933 -3601
  41. package/src/DataTable/utils/getIdOrCodeOrIndex.js +1 -1
  42. package/src/DataTable/utils/handleCopyTable.js +16 -0
  43. package/src/DataTable/utils/index.js +7 -3
  44. package/src/DataTable/utils/primarySelectedValue.js +1 -0
  45. package/src/DataTable/utils/queryParams.js +42 -13
  46. package/src/DataTable/utils/removeCleanRows.js +3 -3
  47. package/src/DataTable/utils/rowClick.js +34 -9
  48. package/src/DataTable/utils/selection.js +1 -1
  49. package/src/DataTable/utils/useDeepEqualMemo.js +10 -0
  50. package/src/DataTable/utils/useTableParams.js +361 -0
  51. package/src/DataTable/utils/withTableParams.js +30 -87
  52. package/src/DataTable/validateTableWideErrors.js +1 -1
  53. package/src/DialogFooter/index.js +3 -3
  54. package/src/FillWindow.js +2 -3
  55. package/src/FormComponents/Uploader.js +825 -784
  56. package/src/FormComponents/index.js +441 -603
  57. package/src/FormComponents/tryToMatchSchemas.js +1 -6
  58. package/src/MatchHeaders.js +27 -22
  59. package/src/SimpleStepViz.js +19 -23
  60. package/src/TgSuggest/index.js +94 -106
  61. package/src/UploadCsvWizard.js +570 -577
  62. package/src/index.js +4 -3
  63. package/src/showDialogOnDocBody.js +5 -9
  64. package/src/useDialog.js +25 -26
  65. package/src/utils/commandControls.js +2 -2
  66. package/src/utils/handlerHelpers.js +19 -25
  67. package/src/utils/popoverOverflowModifiers.js +1 -1
  68. package/src/utils/renderOnDoc.js +8 -5
  69. package/src/utils/tagUtils.js +3 -3
  70. package/src/utils/useTraceUpdate.js +19 -0
  71. package/src/wrapDialog.js +0 -2
  72. package/style.css +251 -251
  73. package/useDialog.d.ts +2 -6
  74. package/utils/renderOnDoc.d.ts +1 -1
  75. package/utils/tagUtils.d.ts +5 -1
  76. package/utils/useTraceUpdate.d.ts +1 -0
@@ -1,4 +1,4 @@
1
- export default (record, rowIndex) => {
1
+ export const getIdOrCodeOrIndex = (record, rowIndex) => {
2
2
  if (record.id || record.id === 0) {
3
3
  return record.id;
4
4
  } else if (record.code) {
@@ -0,0 +1,16 @@
1
+ import { getAllRows } from "./getAllRows";
2
+ import { handleCopyRows } from "./handleCopyRows";
3
+
4
+ export const handleCopyTable = (e, opts) => {
5
+ try {
6
+ const allRowEls = getAllRows(e);
7
+ if (!allRowEls) return;
8
+ handleCopyRows(allRowEls, {
9
+ ...opts,
10
+ onFinishMsg: "Table Copied"
11
+ });
12
+ } catch (error) {
13
+ console.error(`error:`, error);
14
+ window.toastr.error("Error copying rows.");
15
+ }
16
+ };
@@ -2,7 +2,6 @@ import { isEntityClean } from "./isEntityClean";
2
2
  import { getSelectedRowsFromEntities } from "./selection";
3
3
  import { removeCleanRows } from "./removeCleanRows";
4
4
  import { getIdOrCodeOrIndex } from "./getIdOrCodeOrIndex";
5
- import computePresets from "./computePresets";
6
5
  import { getRecordsFromIdMap } from "./withSelectedEntities";
7
6
  import { formatPasteData } from "./formatPasteData";
8
7
  import { getFieldPathToField } from "./getFieldPathToField";
@@ -23,9 +22,11 @@ import { handleCopyHelper } from "./handleCopyHelper";
23
22
  import { handleCopyRows } from "./handleCopyRows";
24
23
  import { handleCopyColumn } from "./handleCopyColumn";
25
24
  import { isBottomRightCornerOfRectangle } from "./isBottomRightCornerOfRectangle";
25
+ import { handleCopyTable } from "./handleCopyTable";
26
+ import { PRIMARY_SELECTED_VAL } from "./primarySelectedValue";
27
+ import { useDeepEqualMemo } from "./useDeepEqualMemo";
26
28
 
27
29
  export {
28
- computePresets,
29
30
  defaultParsePaste,
30
31
  formatPasteData,
31
32
  getAllRows,
@@ -44,8 +45,11 @@ export {
44
45
  handleCopyColumn,
45
46
  handleCopyHelper,
46
47
  handleCopyRows,
48
+ handleCopyTable,
47
49
  isBottomRightCornerOfRectangle,
48
50
  isEntityClean,
51
+ PRIMARY_SELECTED_VAL,
49
52
  removeCleanRows,
50
- stripNumberAtEnd
53
+ stripNumberAtEnd,
54
+ useDeepEqualMemo
51
55
  };
@@ -0,0 +1 @@
1
+ export const PRIMARY_SELECTED_VAL = "main_cell";
@@ -39,7 +39,7 @@ export function getMergedOpts(topLevel = {}, instanceLevel = {}) {
39
39
  //filters look like this:
40
40
  // {
41
41
  // selectedFilter: 'textContains', //camel case
42
- // filterOn: ccDisplayName, //camel case display name
42
+ // filterOn: ccDisplayName, //camel case display name if available and string, otherwise path
43
43
  // filterValue: 'thomas',
44
44
  // }
45
45
  ],
@@ -63,9 +63,27 @@ function safeParse(val) {
63
63
  return val;
64
64
  }
65
65
  }
66
+
67
+ /**
68
+ *
69
+ * @param {object} field
70
+ * @returns the camelCase display name of the field, to be used for filters, sorting, etc
71
+ */
72
+ export function getCCDisplayName(field) {
73
+ return camelCase(
74
+ typeof field.displayName === "string" ? field.displayName : field.path
75
+ );
76
+ }
77
+
78
+ /**
79
+ * Takes a schema and returns an object with the fields mapped by their camelCased display name.
80
+ * If the displayName is not set or is a jsx element, the path is used instead.
81
+ * The same conversion must be done when using the result of this method
82
+ */
66
83
  function getFieldsMappedByCCDisplayName(schema) {
67
84
  return schema.fields.reduce((acc, field) => {
68
- acc[camelCase(field.displayName || field.path)] = field;
85
+ const ccDisplayName = getCCDisplayName(field);
86
+ acc[ccDisplayName] = field;
69
87
  return acc;
70
88
  }, {});
71
89
  }
@@ -75,14 +93,14 @@ function orderEntitiesLocal(orderArray, entities, schema, ownProps) {
75
93
  const orderFuncs = [];
76
94
  const ascOrDescArray = [];
77
95
  orderArray.forEach(order => {
78
- const ccDisplayName = order.replace(/^-/gi, "");
96
+ const ccDisplayName = order.replace(/^-/gi, ""); // "-updatedAt" => "updatedAt"
79
97
  const ccFields = getFieldsMappedByCCDisplayName(schema);
80
98
  const field = ccFields[ccDisplayName];
81
99
  if (!field) {
82
100
  throw new Error(
83
101
  "Ruh roh, there should have been a column to sort on for " +
84
102
  order +
85
- "but none was found in " +
103
+ " but none was found in " +
86
104
  schema.fields
87
105
  );
88
106
  }
@@ -234,14 +252,14 @@ function getFiltersFromSearchTerm(searchTerm, schema) {
234
252
  isSearchTermFilter: true
235
253
  };
236
254
  schema.fields.forEach(field => {
237
- const { type, displayName, path, searchDisabled } = field;
255
+ const { type, searchDisabled } = field;
238
256
  if (searchDisabled || field.filterDisabled || type === "color") return;
239
- const nameToUse = camelCase(displayName || path);
257
+ const ccDisplayName = getCCDisplayName(field);
240
258
  const filterValue = cleanFilterValue(searchTerm, type);
241
259
  if (type === "string" || type === "lookup") {
242
260
  searchTermFilters.push({
243
261
  ...sharedFields,
244
- filterOn: nameToUse,
262
+ filterOn: ccDisplayName,
245
263
  filterValue: searchTerm,
246
264
  selectedFilter: "contains"
247
265
  });
@@ -256,14 +274,14 @@ function getFiltersFromSearchTerm(searchTerm, schema) {
256
274
  if ("true".replace(regex, "") !== "true") {
257
275
  searchTermFilters.push({
258
276
  ...sharedFields,
259
- filterOn: nameToUse,
277
+ filterOn: ccDisplayName,
260
278
  filterValue: true,
261
279
  selectedFilter: "true"
262
280
  });
263
281
  } else if ("false".replace(regex, "") !== "false") {
264
282
  searchTermFilters.push({
265
283
  ...sharedFields,
266
- filterOn: nameToUse,
284
+ filterOn: ccDisplayName,
267
285
  filterValue: false,
268
286
  selectedFilter: "false"
269
287
  });
@@ -278,7 +296,7 @@ function getFiltersFromSearchTerm(searchTerm, schema) {
278
296
  }
279
297
  searchTermFilters.push({
280
298
  ...sharedFields,
281
- filterOn: nameToUse,
299
+ filterOn: ccDisplayName,
282
300
  filterValue: filterValue,
283
301
  selectedFilter: "equalTo"
284
302
  });
@@ -347,7 +365,13 @@ function getSubFilter(
347
365
  if (!fieldVal?.toString) return false;
348
366
  return (
349
367
  arrayFilterValue
350
- .map(val => val && val.toLowerCase())
368
+ .map(val => {
369
+ if (val) {
370
+ if (val.toString) return val.toString().toLowerCase();
371
+ return val.toLowerCase();
372
+ }
373
+ return undefined;
374
+ })
351
375
  .indexOf(fieldVal.toString().toLowerCase()) > -1
352
376
  );
353
377
  };
@@ -359,7 +383,13 @@ function getSubFilter(
359
383
  if (!fieldVal?.toString) return false;
360
384
  return (
361
385
  arrayFilterValue
362
- .map(val => val && val.toLowerCase())
386
+ .map(val => {
387
+ if (val) {
388
+ if (val.toString) return val.toString().toLowerCase();
389
+ return val.toLowerCase();
390
+ }
391
+ return undefined;
392
+ })
363
393
  .indexOf(fieldVal.toString().toLowerCase()) === -1
364
394
  );
365
395
  };
@@ -859,7 +889,6 @@ export function getQueryParams({
859
889
  }));
860
890
  });
861
891
  };
862
-
863
892
  const orFiltersObject = getQueries(orFilters, qb, ccFields);
864
893
  let allOrFilters = flattenFilters(orFiltersObject);
865
894
 
@@ -1,9 +1,9 @@
1
1
  import { isEntityClean } from "./isEntityClean";
2
2
  import { getIdOrCodeOrIndex } from "./getIdOrCodeOrIndex";
3
3
 
4
- export const removeCleanRows = (reduxFormEntities, reduxFormCellValidation) => {
4
+ export const removeCleanRows = (entities, cellValidation) => {
5
5
  const toFilterOut = {};
6
- const entsToUse = (reduxFormEntities || []).filter(e => {
6
+ const entsToUse = (entities || []).filter(e => {
7
7
  if (!(e._isClean || isEntityClean(e))) return true;
8
8
  else {
9
9
  toFilterOut[getIdOrCodeOrIndex(e)] = true;
@@ -12,7 +12,7 @@ export const removeCleanRows = (reduxFormEntities, reduxFormCellValidation) => {
12
12
  });
13
13
 
14
14
  const validationToUse = {};
15
- Object.entries(reduxFormCellValidation || {}).forEach(([k, v]) => {
15
+ Object.entries(cellValidation || {}).forEach(([k, v]) => {
16
16
  const [rowId] = k.split(":");
17
17
  if (!toFilterOut[rowId]) {
18
18
  validationToUse[k] = v;
@@ -1,17 +1,27 @@
1
1
  import { isEmpty, forEach, range } from "lodash-es";
2
2
  import { getSelectedRowsFromEntities } from "./selection";
3
- import getIdOrCodeOrIndex from "./getIdOrCodeOrIndex";
3
+ import { getIdOrCodeOrIndex } from "./getIdOrCodeOrIndex";
4
4
  import { getRecordsFromIdMap } from "./withSelectedEntities";
5
5
 
6
- export default function rowClick(e, rowInfo, entities, props) {
7
- const {
6
+ export default function rowClick(
7
+ e,
8
+ rowInfo,
9
+ entities,
10
+ {
8
11
  reduxFormSelectedEntityIdMap,
9
12
  isSingleSelect,
10
13
  noSelect,
11
14
  onRowClick,
12
15
  isEntityDisabled,
13
- withCheckboxes
14
- } = props;
16
+ withCheckboxes,
17
+ onDeselect,
18
+ onSingleRowSelect,
19
+ onMultiRowSelect,
20
+ noDeselectAll,
21
+ onRowSelect,
22
+ change
23
+ }
24
+ ) {
15
25
  const entity = rowInfo.original;
16
26
  onRowClick(e, entity, rowInfo);
17
27
  if (noSelect || isEntityDisabled(entity)) return;
@@ -101,7 +111,19 @@ export default function rowClick(e, rowInfo, entities, props) {
101
111
  }
102
112
  }
103
113
 
104
- finalizeSelection({ idMap: newIdMap, entities, props });
114
+ finalizeSelection({
115
+ idMap: newIdMap,
116
+ entities,
117
+ props: {
118
+ onDeselect,
119
+ onSingleRowSelect,
120
+ onMultiRowSelect,
121
+ noDeselectAll,
122
+ onRowSelect,
123
+ noSelect,
124
+ change
125
+ }
126
+ });
105
127
  }
106
128
 
107
129
  export function changeSelectedEntities({ idMap, entities = [], change }) {
@@ -124,8 +146,10 @@ export function changeSelectedEntities({ idMap, entities = [], change }) {
124
146
  change("reduxFormSelectedEntityIdMap", newIdMap);
125
147
  }
126
148
 
127
- export function finalizeSelection({ idMap, entities, props }) {
128
- const {
149
+ export function finalizeSelection({
150
+ idMap,
151
+ entities,
152
+ props: {
129
153
  onDeselect,
130
154
  onSingleRowSelect,
131
155
  onMultiRowSelect,
@@ -133,7 +157,8 @@ export function finalizeSelection({ idMap, entities, props }) {
133
157
  onRowSelect,
134
158
  noSelect,
135
159
  change
136
- } = props;
160
+ }
161
+ }) {
137
162
  if (noSelect) return;
138
163
  if (
139
164
  noDeselectAll &&
@@ -1,4 +1,4 @@
1
- import getIdOrCodeOrIndex from "./getIdOrCodeOrIndex";
1
+ import { getIdOrCodeOrIndex } from "./getIdOrCodeOrIndex";
2
2
 
3
3
  export const getSelectedRowsFromEntities = (entities, idMap) => {
4
4
  if (!idMap) return [];
@@ -0,0 +1,10 @@
1
+ import { isEqual } from "lodash-es";
2
+ import { useRef } from "react";
3
+
4
+ export const useDeepEqualMemo = value => {
5
+ const ref = useRef();
6
+ if (!isEqual(value, ref.current)) {
7
+ ref.current = value;
8
+ }
9
+ return ref.current;
10
+ };
@@ -0,0 +1,361 @@
1
+ import { useContext, useEffect, useMemo, useState } from "react";
2
+ import { change } from "redux-form";
3
+ import { useDispatch, useSelector } from "react-redux";
4
+ import { isFunction, keyBy, get } from "lodash-es";
5
+ import TableFormTrackerContext from "../TableFormTrackerContext";
6
+ import { viewColumn, openColumn } from "./viewColumn";
7
+ import convertSchema from "./convertSchema";
8
+ import { getRecordsFromIdMap } from "./withSelectedEntities";
9
+ import {
10
+ makeDataTableHandlers,
11
+ getQueryParams,
12
+ setCurrentParamsOnUrl,
13
+ getCurrentParamsFromUrl,
14
+ getCCDisplayName
15
+ } from "./queryParams";
16
+ import getTableConfigFromStorage from "./getTableConfigFromStorage";
17
+
18
+ /*
19
+ NOTE:
20
+ This haven't been tested yet. It is the first version of what we should replace withTableParams
21
+ and also the first bit of the DataTable.
22
+ */
23
+
24
+ /**
25
+ * Note all these options can be passed at Design Time or at Runtime (like reduxForm())
26
+ *
27
+ * @export
28
+ *
29
+ * @param {compOrOpts} compOrOpts
30
+ * @typedef {object} compOrOpts
31
+ * @property {*string} formName - required unique identifier for the table
32
+ * @property {Object | Function} schema - The data table schema or a function returning it. The function wll be called with props as the argument.
33
+ * @property {boolean} urlConnected - whether the table should connect to/update the URL
34
+ * @property {boolean} withSelectedEntities - whether or not to pass the selected entities
35
+ * @property {boolean} isCodeModel - whether the model is keyed by code instead of id in the db
36
+ * @property {object} defaults - tableParam defaults such as pageSize, filter, etc
37
+ * @property {boolean} noOrderError - won't console an error if an order is not found on schema
38
+ */
39
+ export default function useTableParams(
40
+ props // This should be the same as the spread above
41
+ ) {
42
+ const {
43
+ formName,
44
+ isTableParamsConnected,
45
+ urlConnected,
46
+ onlyOneFilter,
47
+ defaults = {},
48
+ // WE NEED THIS HOOK TO BE WRAPPED IN A WITHROUTER OR MOVE TO REACT-ROUTER-DOM 5
49
+ // BEST SOLUTION IS TO ASSUME IT IS GOING TO BE RECEIVED
50
+ history,
51
+ withSelectedEntities,
52
+ tableParams: _tableParams,
53
+ schema: __schema,
54
+ noForm,
55
+ orderByFirstColumn,
56
+ withDisplayOptions,
57
+ syncDisplayOptionsToDb,
58
+ tableConfigurations,
59
+ isViewable,
60
+ isOpenable,
61
+ showEmptyColumnsByDefault,
62
+ isSimple,
63
+ entities: _origEntities = [],
64
+ cellRenderer,
65
+ additionalFilter,
66
+ additionalOrFilter,
67
+ doNotCoercePageSize,
68
+ isLocalCall
69
+ } = props;
70
+ const isInfinite = props.isInfinite || isSimple || !props.withPaging;
71
+ const additionalFilterToUse =
72
+ typeof additionalFilter === "function"
73
+ ? additionalFilter.bind(this, props)
74
+ : () => additionalFilter;
75
+
76
+ const additionalOrFilterToUse =
77
+ typeof additionalOrFilter === "function"
78
+ ? additionalOrFilter.bind(this, props)
79
+ : () => additionalOrFilter;
80
+
81
+ let _schema;
82
+ if (isFunction(__schema)) _schema = __schema(props);
83
+ else _schema = __schema;
84
+ const convertedSchema = convertSchema(_schema);
85
+
86
+ if (isLocalCall) {
87
+ if (!noForm && (!formName || formName === "tgDataTable")) {
88
+ throw new Error(
89
+ "Please pass a unique 'formName' prop to the locally connected <DataTable/> component with schema: ",
90
+ _schema
91
+ );
92
+ }
93
+ if (orderByFirstColumn && !defaults?.order?.length) {
94
+ const r = [getCCDisplayName(convertedSchema.fields[0])];
95
+ defaults.order = r;
96
+ }
97
+ } else {
98
+ //in user instantiated withTableParams() call
99
+ if (!formName || formName === "tgDataTable") {
100
+ throw new Error(
101
+ "Please pass a unique 'formName' prop to the withTableParams() with schema: ",
102
+ _schema
103
+ );
104
+ }
105
+ }
106
+
107
+ const [showForcedHiddenColumns, setShowForcedHidden] = useState(() => {
108
+ if (showEmptyColumnsByDefault) {
109
+ return true;
110
+ }
111
+ return false;
112
+ });
113
+
114
+ const [tableConfig, setTableConfig] = useState({ fieldOptions: [] });
115
+
116
+ useEffect(() => {
117
+ let newTableConfig = {};
118
+ if (withDisplayOptions) {
119
+ if (syncDisplayOptionsToDb) {
120
+ newTableConfig = tableConfigurations && tableConfigurations[0];
121
+ } else {
122
+ newTableConfig = getTableConfigFromStorage(formName);
123
+ }
124
+ if (!newTableConfig) {
125
+ newTableConfig = {
126
+ fieldOptions: []
127
+ };
128
+ }
129
+ }
130
+ setTableConfig(newTableConfig);
131
+ }, [
132
+ formName,
133
+ syncDisplayOptionsToDb,
134
+ tableConfigurations,
135
+ withDisplayOptions
136
+ ]);
137
+
138
+ // make user set page size persist
139
+ const userSetPageSize =
140
+ tableConfig?.userSetPageSize && parseInt(tableConfig.userSetPageSize, 10);
141
+ if (!syncDisplayOptionsToDb && userSetPageSize) {
142
+ defaults.pageSize = userSetPageSize;
143
+ }
144
+
145
+ const {
146
+ reduxFormSearchInput = "",
147
+ onlyShowRowsWErrors,
148
+ reduxFormCellValidation,
149
+ reduxFormEntities,
150
+ reduxFormSelectedCells = {},
151
+ reduxFormSelectedEntityIdMap = {},
152
+ reduxFormQueryParams = {}
153
+ } = useSelector(state => {
154
+ if (!state.form[formName]) return {};
155
+ return state.form[formName].values || {};
156
+ });
157
+
158
+ const entities = reduxFormEntities || _origEntities;
159
+
160
+ const { schema } = useMemo(() => {
161
+ const schema = convertSchema(_schema);
162
+ if (isViewable) {
163
+ schema.fields = [viewColumn, ...schema.fields];
164
+ }
165
+ if (isOpenable) {
166
+ schema.fields = [openColumn, ...schema.fields];
167
+ }
168
+ // this must come before handling orderings.
169
+ schema.fields = schema.fields.map(field => {
170
+ if (field.placementPath) {
171
+ return {
172
+ ...field,
173
+ sortDisabled:
174
+ field.sortDisabled ||
175
+ (typeof field.path === "string" && field.path.includes(".")),
176
+ path: field.placementPath
177
+ };
178
+ } else {
179
+ return field;
180
+ }
181
+ });
182
+
183
+ if (withDisplayOptions) {
184
+ const fieldOptsByPath = keyBy(tableConfig.fieldOptions, "path");
185
+ schema.fields = schema.fields.map(field => {
186
+ const fieldOpt = fieldOptsByPath[field.path];
187
+ let noValsForField = false;
188
+ // only add this hidden column ability if no paging
189
+ if (
190
+ !showForcedHiddenColumns &&
191
+ withDisplayOptions &&
192
+ (isSimple || isInfinite)
193
+ ) {
194
+ noValsForField = entities.every(e => {
195
+ const val = get(e, field.path);
196
+ return field.render
197
+ ? !field.render(val, e)
198
+ : cellRenderer[field.path]
199
+ ? !cellRenderer[field.path](val, e)
200
+ : !val;
201
+ });
202
+ }
203
+ if (noValsForField) {
204
+ return {
205
+ ...field,
206
+ isHidden: true,
207
+ isForcedHidden: true
208
+ };
209
+ } else if (fieldOpt) {
210
+ return {
211
+ ...field,
212
+ isHidden: fieldOpt.isHidden
213
+ };
214
+ } else {
215
+ return field;
216
+ }
217
+ });
218
+
219
+ const columnOrderings = tableConfig.columnOrderings;
220
+ if (columnOrderings) {
221
+ const fieldsWithOrders = [];
222
+ const fieldsWithoutOrder = [];
223
+ // if a new field has been added since the orderings were set then we want
224
+ // it to be at the end instead of the beginning
225
+ schema.fields.forEach(field => {
226
+ if (columnOrderings.indexOf(field.path) > -1) {
227
+ fieldsWithOrders.push(field);
228
+ } else {
229
+ fieldsWithoutOrder.push(field);
230
+ }
231
+ });
232
+ schema.fields = fieldsWithOrders
233
+ .sort(({ path: path1 }, { path: path2 }) => {
234
+ return (
235
+ columnOrderings.indexOf(path1) - columnOrderings.indexOf(path2)
236
+ );
237
+ })
238
+ .concat(fieldsWithoutOrder);
239
+ setTableConfig(prev => ({
240
+ ...prev,
241
+ columnOrderings: schema.fields.map(f => f.path)
242
+ }));
243
+ }
244
+ }
245
+ return { schema };
246
+ }, [
247
+ _schema,
248
+ cellRenderer,
249
+ entities,
250
+ isInfinite,
251
+ isOpenable,
252
+ isSimple,
253
+ isViewable,
254
+ showForcedHiddenColumns,
255
+ tableConfig,
256
+ withDisplayOptions
257
+ ]);
258
+
259
+ const selectedEntities = withSelectedEntities
260
+ ? getRecordsFromIdMap(reduxFormSelectedEntityIdMap)
261
+ : undefined;
262
+
263
+ const currentParams = urlConnected
264
+ ? getCurrentParamsFromUrl(history.location) //important to use history location and not ownProps.location because for some reason the location path lags one render behind!!
265
+ : reduxFormQueryParams;
266
+
267
+ currentParams.searchTerm = reduxFormSearchInput;
268
+
269
+ props = {
270
+ ...props,
271
+ ...getQueryParams({
272
+ doNotCoercePageSize,
273
+ currentParams,
274
+ entities: props.entities, // for local table
275
+ urlConnected,
276
+ defaults: props.defaults,
277
+ schema: convertedSchema,
278
+ isInfinite,
279
+ isLocalCall,
280
+ additionalFilter: additionalFilterToUse,
281
+ additionalOrFilter: additionalOrFilterToUse,
282
+ noOrderError: props.noOrderError,
283
+ isCodeModel: props.isCodeModel,
284
+ ownProps: props
285
+ })
286
+ };
287
+
288
+ const dispatch = useDispatch();
289
+ let tableParams;
290
+ if (!isTableParamsConnected) {
291
+ const updateSearch = val => {
292
+ setTimeout(() => {
293
+ dispatch(change(formName, "reduxFormSearchInput", val || ""));
294
+ });
295
+ };
296
+
297
+ let setNewParams;
298
+ if (urlConnected) {
299
+ setNewParams = newParams => {
300
+ setCurrentParamsOnUrl(newParams, history.replace);
301
+ dispatch(change(formName, "reduxFormQueryParams", newParams)); //we always will update the redux params as a workaround for withRouter not always working if inside a redux-connected container https://github.com/ReactTraining/react-router/issues/5037
302
+ };
303
+ } else {
304
+ setNewParams = function (newParams) {
305
+ dispatch(change(formName, "reduxFormQueryParams", newParams));
306
+ };
307
+ }
308
+
309
+ const bindThese = makeDataTableHandlers({
310
+ setNewParams,
311
+ updateSearch,
312
+ defaults,
313
+ onlyOneFilter
314
+ });
315
+
316
+ const boundDispatchProps = {};
317
+ //bind currentParams to actions
318
+ Object.keys(bindThese).forEach(function (key) {
319
+ const action = bindThese[key];
320
+ boundDispatchProps[key] = function (...args) {
321
+ action(...args, currentParams);
322
+ };
323
+ });
324
+
325
+ const changeFormValue = (...args) => dispatch(change(formName, ...args));
326
+
327
+ tableParams = {
328
+ changeFormValue,
329
+ selectedEntities,
330
+ ..._tableParams,
331
+ ...props,
332
+ ...boundDispatchProps,
333
+ form: formName, //this will override the default redux form name
334
+ isTableParamsConnected: true //let the table know not to do local sorting/filtering etc.
335
+ };
336
+ }
337
+
338
+ const formTracker = useContext(TableFormTrackerContext);
339
+ useEffect(() => {
340
+ if (formTracker.isActive && !formTracker.formNames.includes(formName)) {
341
+ formTracker.pushFormName(formName);
342
+ }
343
+ }, [formTracker, formName]);
344
+
345
+ return {
346
+ ...props,
347
+ selectedEntities,
348
+ tableParams,
349
+ currentParams,
350
+ schema,
351
+ entities,
352
+ reduxFormSearchInput,
353
+ onlyShowRowsWErrors,
354
+ reduxFormCellValidation,
355
+ reduxFormSelectedCells,
356
+ reduxFormSelectedEntityIdMap,
357
+ reduxFormQueryParams,
358
+ showForcedHiddenColumns,
359
+ setShowForcedHidden
360
+ };
361
+ }