@teselagen/ui 0.8.6-beta.14 → 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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@teselagen/ui",
3
- "version": "0.8.6-beta.14",
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
  }
@@ -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";
@@ -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(
@@ -237,57 +238,104 @@ function applyOrderBy(records, _order_by) {
237
238
  : [_order_by];
238
239
 
239
240
  if (order_by.length > 0) {
240
- const fields = [];
241
- const directions = [];
242
- const iteratees = [];
241
+ const orderFuncs = [];
242
+ const ascOrDescArray = [];
243
243
 
244
- order_by.forEach(item => {
245
- // Hasura-style: { field: "asc" }
246
- const field = Object.keys(item)[0];
247
- const direction = item[field];
248
- fields.push(field);
249
- 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";
250
248
 
251
- // Create a custom iteratee function for natural sorting
252
- iteratees.push(record => {
253
- const value = record[field];
254
- // Handle null values based on sort direction
255
- if (isNull(value) || value === undefined) {
256
- return direction === "asc" ? -Infinity : -Infinity;
257
- }
258
- // Use natural sorting only for strings that contain numbers
259
- if (isString(value) && /\d/.test(value)) {
260
- // Return the value in a format that can be naturally sorted
261
- // This effectively creates a sort key that respects natural ordering
262
- return value.replace(/(\d+)/g, num => num.padStart(10, "0"));
263
- }
264
- return value;
265
- });
266
- });
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
267
275
 
268
- // First sort normally
269
- let sortedRecords = orderBy(records, iteratees, directions);
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
270
287
 
271
- // Then ensure entries with a value for the field come before entries without a value
272
- // for any field sorted in descending order
273
- order_by.forEach(item => {
274
- const field = Object.keys(item)[0];
275
- const direction = item[field];
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
276
302
 
277
- if (direction === "desc") {
278
- // For descending sorts, we want entries with values to appear before entries without values
279
- sortedRecords = [
280
- ...sortedRecords.filter(
281
- record => !isNull(record[field]) && record[field] !== undefined
282
- ),
283
- ...sortedRecords.filter(
284
- record => isNull(record[field]) || record[field] === undefined
285
- )
286
- ];
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);
334
+ }
287
335
  }
288
- });
336
+ );
289
337
 
290
- records = sortedRecords;
338
+ records = orderBy(records, orderFuncs, ascOrDescArray);
291
339
  }
292
340
  return records;
293
341
  }