@teselagen/ui 0.8.6-beta.12 → 0.8.6-beta.14
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/index.cjs.js +20 -2
- package/index.es.js +20 -2
- package/package.json +1 -1
- package/src/DataTable/index.js +1 -1
- package/src/DataTable/utils/filterLocalEntitiesToHasura.js +27 -2
- package/src/DataTable/utils/filterLocalEntitiesToHasura.test.js +126 -16
- package/src/DataTable/utils/tableQueryParamsToHasuraClauses.js +3 -3
package/index.cjs.js
CHANGED
|
@@ -22228,13 +22228,31 @@ function applyOrderBy(records, _order_by) {
|
|
|
22228
22228
|
directions.push(direction);
|
|
22229
22229
|
iteratees.push((record) => {
|
|
22230
22230
|
const value = record[field];
|
|
22231
|
+
if (isNull(value) || value === void 0) {
|
|
22232
|
+
return direction === "asc" ? -Infinity : -Infinity;
|
|
22233
|
+
}
|
|
22231
22234
|
if (isString$1(value) && /\d/.test(value)) {
|
|
22232
22235
|
return value.replace(/(\d+)/g, (num) => num.padStart(10, "0"));
|
|
22233
22236
|
}
|
|
22234
22237
|
return value;
|
|
22235
22238
|
});
|
|
22236
22239
|
});
|
|
22237
|
-
|
|
22240
|
+
let sortedRecords = orderBy$1(records, iteratees, directions);
|
|
22241
|
+
order_by.forEach((item) => {
|
|
22242
|
+
const field = Object.keys(item)[0];
|
|
22243
|
+
const direction = item[field];
|
|
22244
|
+
if (direction === "desc") {
|
|
22245
|
+
sortedRecords = [
|
|
22246
|
+
...sortedRecords.filter(
|
|
22247
|
+
(record) => !isNull(record[field]) && record[field] !== void 0
|
|
22248
|
+
),
|
|
22249
|
+
...sortedRecords.filter(
|
|
22250
|
+
(record) => isNull(record[field]) || record[field] === void 0
|
|
22251
|
+
)
|
|
22252
|
+
];
|
|
22253
|
+
}
|
|
22254
|
+
});
|
|
22255
|
+
records = sortedRecords;
|
|
22238
22256
|
}
|
|
22239
22257
|
return records;
|
|
22240
22258
|
}
|
|
@@ -61163,7 +61181,7 @@ const DataTable = /* @__PURE__ */ __name((_I) => {
|
|
|
61163
61181
|
try {
|
|
61164
61182
|
const allEntities = yield safeQuery(fragment, {
|
|
61165
61183
|
variables: {
|
|
61166
|
-
|
|
61184
|
+
where: variables.where,
|
|
61167
61185
|
sort: variables.sort
|
|
61168
61186
|
},
|
|
61169
61187
|
canCancel: true
|
package/index.es.js
CHANGED
|
@@ -22210,13 +22210,31 @@ function applyOrderBy(records, _order_by) {
|
|
|
22210
22210
|
directions.push(direction);
|
|
22211
22211
|
iteratees.push((record) => {
|
|
22212
22212
|
const value = record[field];
|
|
22213
|
+
if (isNull(value) || value === void 0) {
|
|
22214
|
+
return direction === "asc" ? -Infinity : -Infinity;
|
|
22215
|
+
}
|
|
22213
22216
|
if (isString$1(value) && /\d/.test(value)) {
|
|
22214
22217
|
return value.replace(/(\d+)/g, (num) => num.padStart(10, "0"));
|
|
22215
22218
|
}
|
|
22216
22219
|
return value;
|
|
22217
22220
|
});
|
|
22218
22221
|
});
|
|
22219
|
-
|
|
22222
|
+
let sortedRecords = orderBy$1(records, iteratees, directions);
|
|
22223
|
+
order_by.forEach((item) => {
|
|
22224
|
+
const field = Object.keys(item)[0];
|
|
22225
|
+
const direction = item[field];
|
|
22226
|
+
if (direction === "desc") {
|
|
22227
|
+
sortedRecords = [
|
|
22228
|
+
...sortedRecords.filter(
|
|
22229
|
+
(record) => !isNull(record[field]) && record[field] !== void 0
|
|
22230
|
+
),
|
|
22231
|
+
...sortedRecords.filter(
|
|
22232
|
+
(record) => isNull(record[field]) || record[field] === void 0
|
|
22233
|
+
)
|
|
22234
|
+
];
|
|
22235
|
+
}
|
|
22236
|
+
});
|
|
22237
|
+
records = sortedRecords;
|
|
22220
22238
|
}
|
|
22221
22239
|
return records;
|
|
22222
22240
|
}
|
|
@@ -61145,7 +61163,7 @@ const DataTable = /* @__PURE__ */ __name((_I) => {
|
|
|
61145
61163
|
try {
|
|
61146
61164
|
const allEntities = yield safeQuery(fragment, {
|
|
61147
61165
|
variables: {
|
|
61148
|
-
|
|
61166
|
+
where: variables.where,
|
|
61149
61167
|
sort: variables.sort
|
|
61150
61168
|
},
|
|
61151
61169
|
canCancel: true
|
package/package.json
CHANGED
package/src/DataTable/index.js
CHANGED
|
@@ -251,6 +251,10 @@ function applyOrderBy(records, _order_by) {
|
|
|
251
251
|
// Create a custom iteratee function for natural sorting
|
|
252
252
|
iteratees.push(record => {
|
|
253
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
|
+
}
|
|
254
258
|
// Use natural sorting only for strings that contain numbers
|
|
255
259
|
if (isString(value) && /\d/.test(value)) {
|
|
256
260
|
// Return the value in a format that can be naturally sorted
|
|
@@ -261,8 +265,29 @@ function applyOrderBy(records, _order_by) {
|
|
|
261
265
|
});
|
|
262
266
|
});
|
|
263
267
|
|
|
264
|
-
//
|
|
265
|
-
|
|
268
|
+
// First sort normally
|
|
269
|
+
let sortedRecords = orderBy(records, iteratees, directions);
|
|
270
|
+
|
|
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];
|
|
276
|
+
|
|
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
|
+
];
|
|
287
|
+
}
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
records = sortedRecords;
|
|
266
291
|
}
|
|
267
292
|
return records;
|
|
268
293
|
}
|
|
@@ -379,42 +379,152 @@ describe("filterLocalEntitiesToHasura", () => {
|
|
|
379
379
|
]);
|
|
380
380
|
expect(result.entityCount).toBe(3);
|
|
381
381
|
});
|
|
382
|
-
it("should order by age ascending", () => {
|
|
383
|
-
const result = filterLocalEntitiesToHasura(
|
|
384
|
-
|
|
385
|
-
|
|
382
|
+
it("should order by age ascending and put null vals last by default", () => {
|
|
383
|
+
const result = filterLocalEntitiesToHasura(
|
|
384
|
+
[{ id: 111, name: "Null Age", age: null, city: "Unknown" }, ...records],
|
|
385
|
+
{
|
|
386
|
+
order_by: { age: "asc" }
|
|
387
|
+
}
|
|
388
|
+
);
|
|
386
389
|
expect(result.entities).toEqual([
|
|
387
390
|
records[3],
|
|
388
391
|
records[1],
|
|
389
392
|
records[0],
|
|
390
|
-
records[2]
|
|
393
|
+
records[2],
|
|
394
|
+
{ id: 111, name: "Null Age", age: null, city: "Unknown" }
|
|
391
395
|
]);
|
|
392
396
|
expect(result.entitiesAcrossPages).toEqual([
|
|
393
397
|
records[3],
|
|
394
398
|
records[1],
|
|
395
399
|
records[0],
|
|
396
|
-
records[2]
|
|
400
|
+
records[2],
|
|
401
|
+
{ id: 111, name: "Null Age", age: null, city: "Unknown" }
|
|
397
402
|
]);
|
|
398
|
-
expect(result.entityCount).toBe(
|
|
403
|
+
expect(result.entityCount).toBe(5);
|
|
399
404
|
});
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
+
it("should order by age desc and put null/undefined vals last by default", () => {
|
|
406
|
+
const result = filterLocalEntitiesToHasura(
|
|
407
|
+
[
|
|
408
|
+
{ id: 111, name: "Null Age", age: null, city: "Unknown" },
|
|
409
|
+
{ id: 1121, name: "Undefined Age", age: undefined, city: "Unknown" },
|
|
410
|
+
...records
|
|
411
|
+
],
|
|
412
|
+
{
|
|
413
|
+
order_by: { age: "desc" }
|
|
414
|
+
}
|
|
415
|
+
);
|
|
405
416
|
expect(result.entities).toEqual([
|
|
406
417
|
records[2],
|
|
407
418
|
records[0],
|
|
408
419
|
records[1],
|
|
409
|
-
records[3]
|
|
420
|
+
records[3],
|
|
421
|
+
{ id: 111, name: "Null Age", age: null, city: "Unknown" },
|
|
422
|
+
{ id: 1121, name: "Undefined Age", age: undefined, city: "Unknown" }
|
|
410
423
|
]);
|
|
411
|
-
expect(result.
|
|
424
|
+
expect(result.entityCount).toBe(6);
|
|
425
|
+
});
|
|
426
|
+
|
|
427
|
+
it.only("should order by updatedAt descending, putting null/undefined vals last ", () => {
|
|
428
|
+
const result = filterLocalEntitiesToHasura(
|
|
429
|
+
[
|
|
430
|
+
{
|
|
431
|
+
name: "-10_signal",
|
|
432
|
+
color: "#4ECDC4",
|
|
433
|
+
isGenbankStandardType: true,
|
|
434
|
+
__typename: "featureTypeOverride"
|
|
435
|
+
},
|
|
436
|
+
{
|
|
437
|
+
name: "-35_signal",
|
|
438
|
+
color: "#F7FFF7",
|
|
439
|
+
isGenbankStandardType: true,
|
|
440
|
+
__typename: "featureTypeOverride"
|
|
441
|
+
},
|
|
442
|
+
{
|
|
443
|
+
name: "3'clip",
|
|
444
|
+
color: "#FF6B6B",
|
|
445
|
+
isGenbankStandardType: true,
|
|
446
|
+
__typename: "featureTypeOverride"
|
|
447
|
+
},
|
|
448
|
+
{
|
|
449
|
+
name: "3'UTR",
|
|
450
|
+
color: "#FFE66D",
|
|
451
|
+
isGenbankStandardType: true,
|
|
452
|
+
__typename: "featureTypeOverride"
|
|
453
|
+
},
|
|
454
|
+
|
|
455
|
+
{
|
|
456
|
+
__typename: "featureTypeOverride",
|
|
457
|
+
id: "33a90fcb-fc26-406f-a6d5-41ac4ba8ea64",
|
|
458
|
+
name: "lalala",
|
|
459
|
+
description: null,
|
|
460
|
+
color: "#81bb41",
|
|
461
|
+
genbankEquivalentType: null,
|
|
462
|
+
updatedAt: "2025-06-03T01:02:24.737499+00:00",
|
|
463
|
+
isHidden: false,
|
|
464
|
+
isCustomType: true
|
|
465
|
+
}
|
|
466
|
+
],
|
|
467
|
+
{
|
|
468
|
+
order_by: [{ updatedAt: "desc" }]
|
|
469
|
+
}
|
|
470
|
+
);
|
|
471
|
+
expect(result.entities).toEqual([
|
|
472
|
+
{
|
|
473
|
+
__typename: "featureTypeOverride",
|
|
474
|
+
id: "33a90fcb-fc26-406f-a6d5-41ac4ba8ea64",
|
|
475
|
+
name: "lalala",
|
|
476
|
+
description: null,
|
|
477
|
+
color: "#81bb41",
|
|
478
|
+
genbankEquivalentType: null,
|
|
479
|
+
updatedAt: "2025-06-03T01:02:24.737499+00:00",
|
|
480
|
+
isHidden: false,
|
|
481
|
+
isCustomType: true
|
|
482
|
+
},
|
|
483
|
+
{
|
|
484
|
+
name: "-10_signal",
|
|
485
|
+
color: "#4ECDC4",
|
|
486
|
+
isGenbankStandardType: true,
|
|
487
|
+
__typename: "featureTypeOverride"
|
|
488
|
+
},
|
|
489
|
+
{
|
|
490
|
+
name: "-35_signal",
|
|
491
|
+
color: "#F7FFF7",
|
|
492
|
+
isGenbankStandardType: true,
|
|
493
|
+
__typename: "featureTypeOverride"
|
|
494
|
+
},
|
|
495
|
+
{
|
|
496
|
+
name: "3'clip",
|
|
497
|
+
color: "#FF6B6B",
|
|
498
|
+
isGenbankStandardType: true,
|
|
499
|
+
__typename: "featureTypeOverride"
|
|
500
|
+
},
|
|
501
|
+
{
|
|
502
|
+
name: "3'UTR",
|
|
503
|
+
color: "#FFE66D",
|
|
504
|
+
isGenbankStandardType: true,
|
|
505
|
+
__typename: "featureTypeOverride"
|
|
506
|
+
}
|
|
507
|
+
]);
|
|
508
|
+
});
|
|
509
|
+
it("should order by age descending, putting null/undefined vals last ", () => {
|
|
510
|
+
const result = filterLocalEntitiesToHasura(
|
|
511
|
+
[
|
|
512
|
+
{ id: 111, name: "Null Age", age: null, city: "Unknown" },
|
|
513
|
+
{ id: 1121, name: "Undefined Age", age: undefined, city: "Unknown" },
|
|
514
|
+
...records
|
|
515
|
+
],
|
|
516
|
+
{
|
|
517
|
+
order_by: { age: "desc" }
|
|
518
|
+
}
|
|
519
|
+
);
|
|
520
|
+
expect(result.entities).toEqual([
|
|
412
521
|
records[2],
|
|
413
522
|
records[0],
|
|
414
523
|
records[1],
|
|
415
|
-
records[3]
|
|
524
|
+
records[3],
|
|
525
|
+
{ id: 111, name: "Null Age", age: null, city: "Unknown" },
|
|
526
|
+
{ id: 1121, name: "Undefined Age", age: undefined, city: "Unknown" }
|
|
416
527
|
]);
|
|
417
|
-
expect(result.entityCount).toBe(4);
|
|
418
528
|
});
|
|
419
529
|
|
|
420
530
|
it("should order by name ascending", () => {
|
|
@@ -21,18 +21,18 @@ export function tableQueryParamsToHasuraClauses({
|
|
|
21
21
|
const uniqueFieldsByPath = {};
|
|
22
22
|
|
|
23
23
|
// Split the search term by comma to support multi-term searching
|
|
24
|
-
const searchTerms = searchTerm.split(
|
|
24
|
+
const searchTerms = searchTerm.split(",");
|
|
25
25
|
|
|
26
26
|
schema.fields.forEach(field => {
|
|
27
27
|
const { type, path, searchDisabled } = field;
|
|
28
28
|
if (uniqueFieldsByPath[path]) return; // Skip if already added
|
|
29
29
|
uniqueFieldsByPath[path] = true;
|
|
30
30
|
if (searchDisabled || field.filterDisabled || type === "color") return;
|
|
31
|
-
|
|
31
|
+
|
|
32
32
|
// Process each search term
|
|
33
33
|
searchTerms.forEach(term => {
|
|
34
34
|
const filterValue = term.trim(); // Trim the term to handle spaces after commas
|
|
35
|
-
|
|
35
|
+
|
|
36
36
|
if (type === "string" || type === "lookup") {
|
|
37
37
|
const o = set({}, path, { _ilike: `%${filterValue}%` });
|
|
38
38
|
searchTermFilters.push(o);
|