@teselagen/ui 0.8.6-beta.13 → 0.8.6-beta.15
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/README.md +1 -1
- package/index.cjs.js +16984 -16904
- package/index.es.js +16984 -16904
- package/package.json +3 -3
- package/src/DataTable/index.js +2 -2
- package/src/DataTable/utils/filterLocalEntitiesToHasura.js +97 -47
- package/src/DataTable/utils/filterLocalEntitiesToHasura.test.js +625 -12
- package/src/DataTable/utils/queryParams.js +53 -18
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@teselagen/ui",
|
|
3
|
-
"version": "0.8.6-beta.
|
|
3
|
+
"version": "0.8.6-beta.15",
|
|
4
4
|
"main": "./src/index.js",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
"@dnd-kit/core": "^6.1.0",
|
|
18
18
|
"@dnd-kit/modifiers": "^7.0.0",
|
|
19
19
|
"@dnd-kit/sortable": "^8.0.0",
|
|
20
|
+
"@teselagen/react-table": "6.10.16",
|
|
20
21
|
"classnames": "^2.3.2",
|
|
21
22
|
"color": "^3.2.1",
|
|
22
23
|
"copy-to-clipboard": "^3.3.1",
|
|
@@ -54,8 +55,7 @@
|
|
|
54
55
|
"chance": "^1.1.11",
|
|
55
56
|
"@dnd-kit/utilities": "3.2.2",
|
|
56
57
|
"@teselagen/file-utils": "0.3.20",
|
|
57
|
-
"@blueprintjs/icons": "3.33.0"
|
|
58
|
-
"jszip": "3.10.1"
|
|
58
|
+
"@blueprintjs/icons": "3.33.0"
|
|
59
59
|
},
|
|
60
60
|
"license": "MIT"
|
|
61
61
|
}
|
package/src/DataTable/index.js
CHANGED
|
@@ -92,9 +92,9 @@ import { viewColumn, openColumn, multiViewColumn } from "./viewColumn";
|
|
|
92
92
|
import convertSchema from "./utils/convertSchema";
|
|
93
93
|
import TableFormTrackerContext from "./TableFormTrackerContext";
|
|
94
94
|
import {
|
|
95
|
-
getCurrentParamsFromUrl,
|
|
96
95
|
getQueryParams,
|
|
97
96
|
makeDataTableHandlers,
|
|
97
|
+
getCurrentParamsFromUrl,
|
|
98
98
|
setCurrentParamsOnUrl
|
|
99
99
|
} from "./utils/queryParams";
|
|
100
100
|
import { useColumns } from "./Columns";
|
|
@@ -3078,7 +3078,7 @@ const DataTable = ({
|
|
|
3078
3078
|
try {
|
|
3079
3079
|
const allEntities = await safeQuery(fragment, {
|
|
3080
3080
|
variables: {
|
|
3081
|
-
|
|
3081
|
+
where: variables.where,
|
|
3082
3082
|
sort: variables.sort
|
|
3083
3083
|
},
|
|
3084
3084
|
canCancel: true
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import {} from "jszip";
|
|
2
1
|
import {
|
|
3
2
|
isEmpty,
|
|
4
3
|
every,
|
|
@@ -10,7 +9,9 @@ import {
|
|
|
10
9
|
includes,
|
|
11
10
|
isObject,
|
|
12
11
|
has,
|
|
13
|
-
orderBy
|
|
12
|
+
orderBy,
|
|
13
|
+
endsWith,
|
|
14
|
+
get
|
|
14
15
|
} from "lodash-es";
|
|
15
16
|
|
|
16
17
|
export function filterLocalEntitiesToHasura(
|
|
@@ -230,8 +231,6 @@ function applyWhereClause(records, where) {
|
|
|
230
231
|
// order_by looks like this: [{ some_field: "asc" }, { some_other_field: "desc" }] or {some_field: "asc"}
|
|
231
232
|
// returns the records sorted by the order_by clause
|
|
232
233
|
function applyOrderBy(records, _order_by) {
|
|
233
|
-
// console.log('records start:', records)
|
|
234
|
-
// console.log('_order_by:', _order_by)
|
|
235
234
|
const order_by = isArray(_order_by)
|
|
236
235
|
? _order_by
|
|
237
236
|
: isEmpty(_order_by)
|
|
@@ -239,53 +238,104 @@ function applyOrderBy(records, _order_by) {
|
|
|
239
238
|
: [_order_by];
|
|
240
239
|
|
|
241
240
|
if (order_by.length > 0) {
|
|
242
|
-
const
|
|
243
|
-
const
|
|
244
|
-
const iteratees = [];
|
|
241
|
+
const orderFuncs = [];
|
|
242
|
+
const ascOrDescArray = [];
|
|
245
243
|
|
|
246
|
-
order_by.forEach(
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
fields.push(field);
|
|
251
|
-
directions.push(direction);
|
|
244
|
+
order_by.forEach(
|
|
245
|
+
({ path, direction, type, sortFn, getValueToFilterOn, ownProps }) => {
|
|
246
|
+
// Default direction is "desc" if not specified
|
|
247
|
+
direction = direction || "desc";
|
|
252
248
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
249
|
+
if (sortFn) {
|
|
250
|
+
// Handle specifically custom sort functions
|
|
251
|
+
// First make sure we have an array of sort functions
|
|
252
|
+
const sortFnArray = Array.isArray(sortFn) ? sortFn : [sortFn];
|
|
253
|
+
|
|
254
|
+
// For each sort function
|
|
255
|
+
sortFnArray.forEach(fn => {
|
|
256
|
+
// First handle null check for this function's values
|
|
257
|
+
orderFuncs.push(r => {
|
|
258
|
+
const val = fn(r);
|
|
259
|
+
return val !== null && val !== undefined ? 1 : 0;
|
|
260
|
+
});
|
|
261
|
+
ascOrDescArray.push("desc"); // Always push nulls to the bottom
|
|
262
|
+
|
|
263
|
+
// Then the actual sort function
|
|
264
|
+
orderFuncs.push(fn);
|
|
265
|
+
ascOrDescArray.push(direction);
|
|
266
|
+
});
|
|
267
|
+
} else if (getValueToFilterOn) {
|
|
268
|
+
// Custom getValue function
|
|
269
|
+
// First handle null check
|
|
270
|
+
orderFuncs.push(r => {
|
|
271
|
+
const val = getValueToFilterOn(r, ownProps);
|
|
272
|
+
return val !== null && val !== undefined ? 1 : 0;
|
|
273
|
+
});
|
|
274
|
+
ascOrDescArray.push("desc"); // Always push nulls to the bottom
|
|
275
|
+
|
|
276
|
+
// Then the actual value getter function
|
|
277
|
+
orderFuncs.push(r => getValueToFilterOn(r, ownProps));
|
|
278
|
+
ascOrDescArray.push(direction);
|
|
279
|
+
} else if (type === "timestamp") {
|
|
280
|
+
// Sort nulls/undefined to the bottom regardless of sort direction
|
|
281
|
+
orderFuncs.push(r => {
|
|
282
|
+
const val = get(r, path);
|
|
283
|
+
// First check if value exists, this ensures nulls go to the bottom
|
|
284
|
+
return val ? 1 : 0;
|
|
285
|
+
});
|
|
286
|
+
ascOrDescArray.push("desc"); // always put nulls at the bottom
|
|
287
|
+
|
|
288
|
+
// Then actual timestamp sorting
|
|
289
|
+
orderFuncs.push(r => {
|
|
290
|
+
const val = get(r, path);
|
|
291
|
+
return val ? new Date(val).getTime() : -Infinity;
|
|
292
|
+
});
|
|
293
|
+
ascOrDescArray.push(direction);
|
|
294
|
+
} else if (path && endsWith(path.toLowerCase(), "id")) {
|
|
295
|
+
// Handle ID fields - sort numerically
|
|
296
|
+
// First handle null check
|
|
297
|
+
orderFuncs.push(r => {
|
|
298
|
+
const val = get(r, path);
|
|
299
|
+
return val !== null && val !== undefined ? 1 : 0;
|
|
300
|
+
});
|
|
301
|
+
ascOrDescArray.push("desc"); // Always push nulls to the bottom
|
|
302
|
+
|
|
303
|
+
// Then the actual ID parsing
|
|
304
|
+
orderFuncs.push(o => {
|
|
305
|
+
const val = get(o, path);
|
|
306
|
+
if (val === null || val === undefined) return -Infinity;
|
|
307
|
+
return parseInt(val, 10) || 0;
|
|
308
|
+
});
|
|
309
|
+
ascOrDescArray.push(direction);
|
|
310
|
+
} else {
|
|
311
|
+
// Default sorting
|
|
312
|
+
// First sort by existence (non-nulls first)
|
|
313
|
+
orderFuncs.push(r => {
|
|
314
|
+
const val = get(r, path);
|
|
315
|
+
return val !== null && val !== undefined ? 1 : 0;
|
|
316
|
+
});
|
|
317
|
+
ascOrDescArray.push("desc"); // Always put nulls at the bottom
|
|
318
|
+
|
|
319
|
+
// Then sort by actual value
|
|
320
|
+
orderFuncs.push(r => {
|
|
321
|
+
const val = get(r, path);
|
|
322
|
+
if (val === null || val === undefined) return -Infinity;
|
|
323
|
+
|
|
324
|
+
// For string sorting, implement natural sort
|
|
325
|
+
if (isString(val)) {
|
|
326
|
+
return val.toLowerCase().replace(/(\d+)/g, num =>
|
|
327
|
+
// Pad numbers with leading zeros for proper natural sort
|
|
328
|
+
num.padStart(10, "0")
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
return val;
|
|
332
|
+
});
|
|
333
|
+
ascOrDescArray.push(direction);
|
|
265
334
|
}
|
|
266
|
-
return value;
|
|
267
|
-
});
|
|
268
|
-
});
|
|
269
|
-
|
|
270
|
-
// First sort normally
|
|
271
|
-
let sortedRecords = orderBy(records, iteratees, directions);
|
|
272
|
-
|
|
273
|
-
// Then ensure entries with a value for the field come before entries without a value
|
|
274
|
-
// for any field sorted in descending order
|
|
275
|
-
order_by.forEach((item) => {
|
|
276
|
-
const field = Object.keys(item)[0];
|
|
277
|
-
const direction = item[field];
|
|
278
|
-
|
|
279
|
-
if (direction === 'desc') {
|
|
280
|
-
// For descending sorts, we want entries with values to appear before entries without values
|
|
281
|
-
sortedRecords = [
|
|
282
|
-
...sortedRecords.filter(record => !isNull(record[field]) && record[field] !== undefined),
|
|
283
|
-
...sortedRecords.filter(record => isNull(record[field]) || record[field] === undefined)
|
|
284
|
-
];
|
|
285
335
|
}
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
records =
|
|
336
|
+
);
|
|
337
|
+
|
|
338
|
+
records = orderBy(records, orderFuncs, ascOrDescArray);
|
|
289
339
|
}
|
|
290
340
|
return records;
|
|
291
341
|
}
|