@bexis2/bexis2-core-ui 0.4.95 → 0.4.97
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 +105 -24
- package/dist/components/CodeEditor/CodeEditor.svelte +2 -2
- package/dist/components/Facets/ShowMore.svelte +4 -6
- package/dist/components/File/FileUploader.svelte +6 -3
- package/dist/components/Table/Table.svelte +31 -5
- package/dist/components/Table/TableContent.svelte +226 -27
- package/dist/components/Table/TableFilter.svelte +25 -12
- package/dist/components/Table/TableFilterServer.svelte +51 -6
- package/dist/components/Table/TablePaginationServer.svelte +27 -8
- package/dist/components/Table/clientDB.d.ts +22 -0
- package/dist/components/Table/clientDB.js +236 -0
- package/dist/components/Table/filter.js +21 -2
- package/dist/components/Table/tableWorker.d.ts +1 -0
- package/dist/components/Table/tableWorker.js +179 -0
- package/dist/components/Table/utils.d.ts +1 -2
- package/dist/components/Table/utils.js +64 -31
- package/dist/components/form/CheckboxKvPList.svelte +15 -15
- package/dist/components/form/CheckboxList.svelte +1 -1
- package/dist/components/form/DateInput.svelte +12 -1
- package/dist/components/form/DatePickerInput.svelte +51 -29
- package/dist/components/form/Dropdown.svelte +14 -3
- package/dist/components/form/DropdownKvP.svelte +13 -2
- package/dist/components/form/InputContainer.svelte +17 -15
- package/dist/components/form/MultiSelect.svelte +30 -29
- package/dist/components/form/NumberInput.svelte +12 -1
- package/dist/components/form/TextArea.svelte +12 -1
- package/dist/components/form/TextInput.svelte +12 -1
- package/dist/components/page/Alert.svelte +5 -1
- package/dist/components/page/BackToTop.svelte +3 -1
- package/dist/components/page/Docs.svelte +9 -2
- package/dist/components/page/GoToTop.svelte +14 -15
- package/dist/components/page/Page.svelte +50 -56
- package/dist/components/page/breadcrumb/BreadcrumbDataCaller.js +11 -15
- package/dist/components/page/menu/MenuAccountBar.svelte +1 -5
- package/dist/components/page/menu/MenuDataCaller.js +1 -1
- package/dist/components/page/menu/MenuItem.svelte +9 -7
- package/dist/components/page/menu/MenuSublist.svelte +7 -5
- package/dist/components/page/menu/SettingsBar.svelte +4 -1
- package/dist/components/toggle/Toggle.svelte +9 -9
- package/dist/css/core.ui.postcss +1 -2
- package/dist/services/Api.js +4 -4
- package/dist/services/BaseCaller.js +1 -1
- package/package.json +114 -114
- package/src/lib/components/CodeEditor/CodeEditor.svelte +4 -4
- package/src/lib/components/Facets/Facets.svelte +2 -2
- package/src/lib/components/Facets/ShowMore.svelte +4 -6
- package/src/lib/components/File/FileUploader.svelte +17 -14
- package/src/lib/components/Table/Table.svelte +32 -5
- package/src/lib/components/Table/TableContent.svelte +261 -38
- package/src/lib/components/Table/TableFilter.svelte +34 -8
- package/src/lib/components/Table/TableFilterServer.svelte +65 -9
- package/src/lib/components/Table/TablePagination.svelte +6 -2
- package/src/lib/components/Table/TablePaginationServer.svelte +36 -10
- package/src/lib/components/Table/clientDB.js +236 -0
- package/src/lib/components/Table/filter.ts +44 -24
- package/src/lib/components/Table/tableWorker.js +179 -0
- package/src/lib/components/Table/utils.ts +80 -46
- package/src/lib/components/form/Checkbox.svelte +1 -1
- package/src/lib/components/form/CheckboxKvPList.svelte +15 -16
- package/src/lib/components/form/CheckboxList.svelte +1 -1
- package/src/lib/components/form/DateInput.svelte +13 -2
- package/src/lib/components/form/DatePickerInput.svelte +51 -29
- package/src/lib/components/form/Dropdown.svelte +14 -3
- package/src/lib/components/form/DropdownKvP.svelte +13 -2
- package/src/lib/components/form/InputContainer.svelte +18 -17
- package/src/lib/components/form/MultiSelect.svelte +30 -29
- package/src/lib/components/form/NumberInput.svelte +21 -12
- package/src/lib/components/form/TextArea.svelte +13 -2
- package/src/lib/components/form/TextInput.svelte +13 -2
- package/src/lib/components/page/Alert.svelte +5 -1
- package/src/lib/components/page/BackToTop.svelte +3 -1
- package/src/lib/components/page/Docs.svelte +9 -2
- package/src/lib/components/page/GoToTop.svelte +14 -15
- package/src/lib/components/page/Notification.svelte +1 -1
- package/src/lib/components/page/Page.svelte +67 -78
- package/src/lib/components/page/breadcrumb/Breadcrumb.svelte +2 -3
- package/src/lib/components/page/breadcrumb/BreadcrumbDataCaller.js +11 -15
- package/src/lib/components/page/menu/MenuAccountBar.svelte +1 -6
- package/src/lib/components/page/menu/MenuDataCaller.js +1 -1
- package/src/lib/components/page/menu/MenuItem.svelte +10 -8
- package/src/lib/components/page/menu/MenuSublist.svelte +35 -41
- package/src/lib/components/page/menu/SettingsBar.svelte +5 -2
- package/src/lib/components/toggle/Toggle.svelte +28 -30
- package/src/lib/css/core.ui.postcss +1 -2
- package/src/lib/index.ts +1 -2
- package/src/lib/services/Api.ts +21 -20
- package/src/lib/services/BaseCaller.js +1 -1
- package/src/lib/stores/apiStores.ts +1 -5
- package/src/lib/stores/pageStores.ts +0 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script>import { afterUpdate, createEventDispatcher, onDestroy, onMount } from "svelte";
|
|
2
|
-
import {
|
|
2
|
+
import { writable } from "svelte/store";
|
|
3
3
|
import Fa from "svelte-fa";
|
|
4
4
|
import { faCompress, faDownload, faXmark } from "@fortawesome/free-solid-svg-icons";
|
|
5
5
|
import { createTable, Subscribe, Render, createRender } from "svelte-headless-table";
|
|
@@ -21,6 +21,7 @@ import TableFilterServer from "./TableFilterServer.svelte";
|
|
|
21
21
|
import TablePagination from "./TablePagination.svelte";
|
|
22
22
|
import TablePaginationServer from "./TablePaginationServer.svelte";
|
|
23
23
|
import ColumnsMenu from "./ColumnsMenu.svelte";
|
|
24
|
+
import ClientDB from "./clientDB.js";
|
|
24
25
|
import * as utils from "./utils";
|
|
25
26
|
import { columnFilter, searchFilter } from "./filter";
|
|
26
27
|
import { Send } from "../../models/Models";
|
|
@@ -56,20 +57,27 @@ let {
|
|
|
56
57
|
// Whether to display the export button and enable export functionality
|
|
57
58
|
server
|
|
58
59
|
} = config;
|
|
60
|
+
const clientDb = config.clientDb ?? false;
|
|
61
|
+
const clientDbSeedData = config.clientDbSeedData ?? [];
|
|
62
|
+
const initialServerCount = Number(config.__initialServerCount ?? 0);
|
|
59
63
|
let searchValue = "";
|
|
60
64
|
let isFetching = false;
|
|
61
65
|
let tableRef;
|
|
62
|
-
|
|
66
|
+
let serverItemCountValue = Number.isFinite(initialServerCount) ? initialServerCount : 0;
|
|
67
|
+
const serverSide = server !== void 0 || clientDb;
|
|
68
|
+
let _clientDbInstance = null;
|
|
69
|
+
let clientDbEnabled = clientDb;
|
|
70
|
+
let clientDbReady = false;
|
|
71
|
+
let clientDbInitSource = [];
|
|
72
|
+
let clientDbSeedSize = 0;
|
|
63
73
|
const { sendModel = new Send() } = server ?? {};
|
|
64
74
|
const filters = writable({});
|
|
65
75
|
const dispatch = createEventDispatcher();
|
|
66
76
|
const actionDispatcher = (obj) => dispatch("action", obj);
|
|
67
77
|
const rowHeights = writable({});
|
|
68
78
|
const colWidths = writable([]);
|
|
69
|
-
const serverItems = serverSide ? writable(0) : void 0;
|
|
70
|
-
const serverItemCount =
|
|
71
|
-
serverItems.subscribe((val) => set(val));
|
|
72
|
-
}) : void 0;
|
|
79
|
+
const serverItems = serverSide ? writable(Number.isFinite(initialServerCount) ? initialServerCount : 0) : void 0;
|
|
80
|
+
const serverItemCount = serverItems;
|
|
73
81
|
const table = createTable(data, {
|
|
74
82
|
colFilter: addColumnFilters(),
|
|
75
83
|
tableFilter: addTableFilter({
|
|
@@ -90,13 +98,22 @@ const table = createTable(data, {
|
|
|
90
98
|
export: addDataExport({ format: "json" })
|
|
91
99
|
});
|
|
92
100
|
const allCols = {};
|
|
93
|
-
|
|
94
|
-
Object.keys(
|
|
95
|
-
if (
|
|
96
|
-
|
|
101
|
+
if (columns && Object.keys(columns).length > 0) {
|
|
102
|
+
Object.keys(columns).forEach((key) => {
|
|
103
|
+
if (optionsComponent !== void 0 && key === "optionsColumn") {
|
|
104
|
+
return;
|
|
97
105
|
}
|
|
106
|
+
allCols[key] = {};
|
|
98
107
|
});
|
|
99
|
-
}
|
|
108
|
+
} else {
|
|
109
|
+
$data.forEach((item) => {
|
|
110
|
+
Object.keys(item).forEach((key) => {
|
|
111
|
+
if (!allCols[key]) {
|
|
112
|
+
allCols[key] = {};
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
}
|
|
100
117
|
Object.keys(allCols).forEach((key) => {
|
|
101
118
|
$filters = { ...$filters, [key]: {} };
|
|
102
119
|
});
|
|
@@ -226,10 +243,21 @@ const tableColumns = [
|
|
|
226
243
|
}
|
|
227
244
|
})
|
|
228
245
|
];
|
|
246
|
+
const getUniqueOptionsColumnId = () => {
|
|
247
|
+
const used = new Set(unexcludedColumns.map((col) => String(col)));
|
|
248
|
+
let id = "optionsColumn";
|
|
249
|
+
let i = 1;
|
|
250
|
+
while (used.has(id)) {
|
|
251
|
+
id = `optionsColumn_${i}`;
|
|
252
|
+
i += 1;
|
|
253
|
+
}
|
|
254
|
+
return id;
|
|
255
|
+
};
|
|
229
256
|
if (optionsComponent !== void 0) {
|
|
257
|
+
const optionsColumnId = getUniqueOptionsColumnId();
|
|
230
258
|
tableColumns.push(
|
|
231
259
|
table.display({
|
|
232
|
-
id:
|
|
260
|
+
id: optionsColumnId,
|
|
233
261
|
header: "",
|
|
234
262
|
plugins: {
|
|
235
263
|
export: {
|
|
@@ -251,7 +279,7 @@ const { filterValue } = pluginStates.tableFilter;
|
|
|
251
279
|
const { exportedData } = pluginStates.export;
|
|
252
280
|
const { pageIndex, pageSize } = pluginStates.page;
|
|
253
281
|
const { hiddenColumnIds } = pluginStates.hideColumns;
|
|
254
|
-
let prevSort =
|
|
282
|
+
let prevSort = [];
|
|
255
283
|
const sortServer = (order, id) => {
|
|
256
284
|
if (!sendModel) throw new Error("Server-side configuration is missing");
|
|
257
285
|
if (order === void 0) {
|
|
@@ -259,19 +287,137 @@ const sortServer = (order, id) => {
|
|
|
259
287
|
} else {
|
|
260
288
|
sendModel.order = [{ column: id, direction: order }];
|
|
261
289
|
}
|
|
262
|
-
if (JSON.stringify(sendModel.order) !== JSON.stringify(prevSort)
|
|
290
|
+
if (JSON.stringify(sendModel.order) !== JSON.stringify(prevSort)) {
|
|
263
291
|
$pageIndex = 0;
|
|
264
292
|
$data = [];
|
|
265
293
|
updateTableWithParams();
|
|
266
294
|
}
|
|
267
|
-
|
|
268
|
-
prevSort = [];
|
|
269
|
-
} else {
|
|
270
|
-
prevSort = sendModel.order;
|
|
271
|
-
}
|
|
295
|
+
prevSort = sendModel.order ? [...sendModel.order] : [];
|
|
272
296
|
};
|
|
273
297
|
const updateTableWithParams = async () => {
|
|
274
|
-
if (
|
|
298
|
+
if (clientDbEnabled) {
|
|
299
|
+
isFetching = true;
|
|
300
|
+
const filtersNormalized = utils.normalizeFilters($filters);
|
|
301
|
+
const q = sendModel?.q || "";
|
|
302
|
+
const offset2 = $pageSize * $pageIndex;
|
|
303
|
+
const limit = $pageSize;
|
|
304
|
+
if (!_clientDbInstance) {
|
|
305
|
+
_clientDbInstance = new ClientDB(tableId);
|
|
306
|
+
}
|
|
307
|
+
if (!clientDbReady) {
|
|
308
|
+
const source = clientDbInitSource.length > 0 ? clientDbInitSource : $data;
|
|
309
|
+
const getValue = (row, column) => {
|
|
310
|
+
const dot = String(column || "").replaceAll("%%%", ".");
|
|
311
|
+
return row[dot] ?? row[column] ?? row[dot.replaceAll(".", "%%%")];
|
|
312
|
+
};
|
|
313
|
+
const localMatches = (row) => {
|
|
314
|
+
if (q && q.length > 0) {
|
|
315
|
+
const ql = String(q).toLowerCase();
|
|
316
|
+
let found = false;
|
|
317
|
+
for (const k in row) {
|
|
318
|
+
const v = row[k];
|
|
319
|
+
if (v == null) continue;
|
|
320
|
+
if (String(v).toLowerCase().includes(ql)) {
|
|
321
|
+
found = true;
|
|
322
|
+
break;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
if (!found) return false;
|
|
326
|
+
}
|
|
327
|
+
for (const f of filtersNormalized) {
|
|
328
|
+
const actual = getValue(row, f.column);
|
|
329
|
+
const val = f.value;
|
|
330
|
+
if (val == null) continue;
|
|
331
|
+
const aStr = String(actual ?? "").toLowerCase();
|
|
332
|
+
const vStr = String(val ?? "").toLowerCase();
|
|
333
|
+
const aNum = Number(actual);
|
|
334
|
+
const vNum = Number(val);
|
|
335
|
+
const aDate = new Date(actual).getTime();
|
|
336
|
+
const vDate = new Date(val).getTime();
|
|
337
|
+
switch (f.filterBy) {
|
|
338
|
+
case "c":
|
|
339
|
+
if (!aStr.includes(vStr)) return false;
|
|
340
|
+
break;
|
|
341
|
+
case "nc":
|
|
342
|
+
if (aStr.includes(vStr)) return false;
|
|
343
|
+
break;
|
|
344
|
+
case "sw":
|
|
345
|
+
if (!aStr.startsWith(vStr)) return false;
|
|
346
|
+
break;
|
|
347
|
+
case "ew":
|
|
348
|
+
if (!aStr.endsWith(vStr)) return false;
|
|
349
|
+
break;
|
|
350
|
+
case "e":
|
|
351
|
+
if (actual != val) return false;
|
|
352
|
+
break;
|
|
353
|
+
case "ne":
|
|
354
|
+
if (actual == val) return false;
|
|
355
|
+
break;
|
|
356
|
+
case "gt":
|
|
357
|
+
if (Number.isNaN(aNum) || Number.isNaN(vNum) || !(aNum > vNum)) return false;
|
|
358
|
+
break;
|
|
359
|
+
case "lt":
|
|
360
|
+
if (Number.isNaN(aNum) || Number.isNaN(vNum) || !(aNum < vNum)) return false;
|
|
361
|
+
break;
|
|
362
|
+
case "gte":
|
|
363
|
+
if (Number.isNaN(aNum) || Number.isNaN(vNum) || !(aNum >= vNum)) return false;
|
|
364
|
+
break;
|
|
365
|
+
case "lte":
|
|
366
|
+
if (Number.isNaN(aNum) || Number.isNaN(vNum) || !(aNum <= vNum)) return false;
|
|
367
|
+
break;
|
|
368
|
+
case "o":
|
|
369
|
+
if (Number.isNaN(aDate) || Number.isNaN(vDate) || aDate !== vDate) return false;
|
|
370
|
+
break;
|
|
371
|
+
case "sf":
|
|
372
|
+
case "a":
|
|
373
|
+
if (Number.isNaN(aDate) || Number.isNaN(vDate) || !(aDate >= vDate)) return false;
|
|
374
|
+
break;
|
|
375
|
+
case "u":
|
|
376
|
+
case "b":
|
|
377
|
+
if (Number.isNaN(aDate) || Number.isNaN(vDate) || !(aDate <= vDate)) return false;
|
|
378
|
+
break;
|
|
379
|
+
case "no":
|
|
380
|
+
if (Number.isNaN(aDate) || Number.isNaN(vDate) || aDate === vDate) return false;
|
|
381
|
+
break;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
return true;
|
|
385
|
+
};
|
|
386
|
+
const filtered = source.filter(localMatches);
|
|
387
|
+
const order = sendModel?.order || [];
|
|
388
|
+
if (order.length > 0) {
|
|
389
|
+
const { column, direction } = order[0];
|
|
390
|
+
const dir = direction === "desc" ? -1 : 1;
|
|
391
|
+
filtered.sort((a, b) => {
|
|
392
|
+
const av = getValue(a, column);
|
|
393
|
+
const bv = getValue(b, column);
|
|
394
|
+
if (av == null && bv == null) return 0;
|
|
395
|
+
if (av == null) return -1 * dir;
|
|
396
|
+
if (bv == null) return 1 * dir;
|
|
397
|
+
if (typeof av === "number" && typeof bv === "number") return (av - bv) * dir;
|
|
398
|
+
return String(av).localeCompare(String(bv)) * dir;
|
|
399
|
+
});
|
|
400
|
+
}
|
|
401
|
+
const localRows = filtered.slice(offset2, offset2 + limit);
|
|
402
|
+
serverItems?.set(filtered.length);
|
|
403
|
+
data.set(localRows);
|
|
404
|
+
isFetching = false;
|
|
405
|
+
return { rows: localRows, total: filtered.length };
|
|
406
|
+
}
|
|
407
|
+
const res = await _clientDbInstance.query({
|
|
408
|
+
q,
|
|
409
|
+
filters: filtersNormalized,
|
|
410
|
+
order: sendModel?.order || [],
|
|
411
|
+
offset: offset2,
|
|
412
|
+
limit
|
|
413
|
+
});
|
|
414
|
+
const payload = res.payload ? res.payload : res;
|
|
415
|
+
serverItems?.set(payload.total ?? payload.totalCount ?? 0);
|
|
416
|
+
data.set(payload.rows ?? []);
|
|
417
|
+
isFetching = false;
|
|
418
|
+
return payload;
|
|
419
|
+
}
|
|
420
|
+
if ($data.length > 0 && serverSide && Number($serverItemCount) > 0) {
|
|
275
421
|
console.log("Table is not empty");
|
|
276
422
|
return;
|
|
277
423
|
}
|
|
@@ -332,6 +478,9 @@ afterUpdate(() => {
|
|
|
332
478
|
if (resizable !== "rows" && resizable !== "both") {
|
|
333
479
|
return;
|
|
334
480
|
}
|
|
481
|
+
if (!$pageRows || $pageRows.length === 0) {
|
|
482
|
+
return;
|
|
483
|
+
}
|
|
335
484
|
const e = tableRef?.querySelector(`#${tableId}-row-${$pageRows[0].id}`);
|
|
336
485
|
if (e) {
|
|
337
486
|
getDimensions();
|
|
@@ -340,10 +489,45 @@ afterUpdate(() => {
|
|
|
340
489
|
onDestroy(() => {
|
|
341
490
|
resizeColumnsObserver.disconnect();
|
|
342
491
|
resizeRowsObserver.disconnect();
|
|
492
|
+
if (_clientDbInstance) {
|
|
493
|
+
try {
|
|
494
|
+
_clientDbInstance.destroy();
|
|
495
|
+
} catch (e) {
|
|
496
|
+
}
|
|
497
|
+
}
|
|
343
498
|
});
|
|
344
499
|
$: sortKeys = pluginStates.sort.sortKeys;
|
|
345
|
-
|
|
346
|
-
|
|
500
|
+
$: serverItemCountValue = clientDbEnabled ? Number($serverItemCount) > 0 ? Math.max(
|
|
501
|
+
Number($serverItemCount),
|
|
502
|
+
initialServerCount,
|
|
503
|
+
clientDbSeedSize,
|
|
504
|
+
clientDbInitSource.length,
|
|
505
|
+
$data.length
|
|
506
|
+
) : Math.max(initialServerCount, clientDbSeedSize, clientDbInitSource.length, $data.length) : Number($serverItemCount);
|
|
507
|
+
onMount(async () => {
|
|
508
|
+
if (clientDbEnabled) {
|
|
509
|
+
const seed = Array.isArray(clientDbSeedData) ? clientDbSeedData : [];
|
|
510
|
+
const hasSeed = seed.length > 0;
|
|
511
|
+
clientDbSeedSize = seed.length;
|
|
512
|
+
if (hasSeed || $data && $data.length > 0) {
|
|
513
|
+
clientDbInitSource = hasSeed ? [...seed] : [...$data];
|
|
514
|
+
const firstPage = clientDbInitSource.slice(0, $pageSize);
|
|
515
|
+
serverItems?.set(clientDbInitSource.length);
|
|
516
|
+
data.set(firstPage);
|
|
517
|
+
_clientDbInstance = new ClientDB(tableId);
|
|
518
|
+
_clientDbInstance.init(clientDbInitSource).then(async () => {
|
|
519
|
+
const result = await updateTableWithParams();
|
|
520
|
+
clientDbReady = true;
|
|
521
|
+
clientDbInitSource = [];
|
|
522
|
+
return result;
|
|
523
|
+
}).catch(() => {
|
|
524
|
+
clientDbReady = false;
|
|
525
|
+
});
|
|
526
|
+
} else if (!_clientDbInstance) {
|
|
527
|
+
_clientDbInstance = new ClientDB(tableId);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
if (server !== void 0) {
|
|
347
531
|
updateTableWithParams();
|
|
348
532
|
}
|
|
349
533
|
});
|
|
@@ -358,14 +542,19 @@ $: $hiddenColumnIds = shownColumns.filter((col) => !col.visible).map((col) => co
|
|
|
358
542
|
{#if search}
|
|
359
543
|
<form
|
|
360
544
|
class="flex gap-2"
|
|
361
|
-
on:submit|preventDefault={() => {
|
|
545
|
+
on:submit|preventDefault={async () => {
|
|
362
546
|
if (serverSide && !sendModel) {
|
|
363
547
|
throw new Error('Server-side configuration is missing');
|
|
364
548
|
} else {
|
|
365
549
|
sendModel.q = searchValue;
|
|
366
550
|
}
|
|
367
551
|
|
|
552
|
+
$pageIndex = 0;
|
|
368
553
|
$filterValue = searchValue;
|
|
554
|
+
if (serverSide) {
|
|
555
|
+
$data = [];
|
|
556
|
+
await updateTableWithParams();
|
|
557
|
+
}
|
|
369
558
|
}}
|
|
370
559
|
>
|
|
371
560
|
<div class="relative w-full flex items-center">
|
|
@@ -383,15 +572,20 @@ $: $hiddenColumnIds = shownColumns.filter((col) => !col.visible).map((col) => co
|
|
|
383
572
|
id="{tableId}-searchReset"
|
|
384
573
|
class="absolute right-3 items-center"
|
|
385
574
|
aria-label="Clear search"
|
|
386
|
-
on:click|preventDefault={() => {
|
|
575
|
+
on:click|preventDefault={async () => {
|
|
387
576
|
if (serverSide && !sendModel) {
|
|
388
577
|
throw new Error('Server-side configuration is missing');
|
|
389
578
|
} else {
|
|
390
579
|
sendModel.q = '';
|
|
391
580
|
}
|
|
392
581
|
|
|
582
|
+
$pageIndex = 0;
|
|
393
583
|
searchValue = '';
|
|
394
584
|
$filterValue = '';
|
|
585
|
+
if (serverSide) {
|
|
586
|
+
$data = [];
|
|
587
|
+
await updateTableWithParams();
|
|
588
|
+
}
|
|
395
589
|
}}><Fa icon={faXmark} /></button
|
|
396
590
|
>
|
|
397
591
|
</div>
|
|
@@ -401,14 +595,19 @@ $: $hiddenColumnIds = shownColumns.filter((col) => !col.visible).map((col) => co
|
|
|
401
595
|
id="{tableId}-searchSubmit"
|
|
402
596
|
class="btn variant-filled-primary"
|
|
403
597
|
aria-label="Search"
|
|
404
|
-
on:click|preventDefault={() => {
|
|
598
|
+
on:click|preventDefault={async () => {
|
|
405
599
|
if (serverSide && !sendModel) {
|
|
406
600
|
throw new Error('Server-side configuration is missing');
|
|
407
601
|
} else {
|
|
408
602
|
sendModel.q = searchValue;
|
|
409
603
|
}
|
|
410
604
|
|
|
605
|
+
$pageIndex = 0;
|
|
411
606
|
$filterValue = searchValue;
|
|
607
|
+
if (serverSide) {
|
|
608
|
+
$data = [];
|
|
609
|
+
await updateTableWithParams();
|
|
610
|
+
}
|
|
412
611
|
}}>Search</button
|
|
413
612
|
>
|
|
414
613
|
</form>
|
|
@@ -530,7 +729,7 @@ $: $hiddenColumnIds = shownColumns.filter((col) => !col.visible).map((col) => co
|
|
|
530
729
|
? `Remove sorting by ${cell.label} column`
|
|
531
730
|
: `Sort by ${cell.label} column in ascending order`}
|
|
532
731
|
>
|
|
533
|
-
{cell.render().replaceAll('%%%', '.')}
|
|
732
|
+
{String(cell.render()).replaceAll('%%%', '.')}
|
|
534
733
|
</span>
|
|
535
734
|
<div class="w-2">
|
|
536
735
|
{#if props.sort.order === 'asc'}
|
|
@@ -625,7 +824,7 @@ $: $hiddenColumnIds = shownColumns.filter((col) => !col.visible).map((col) => co
|
|
|
625
824
|
<TablePaginationServer
|
|
626
825
|
pageConfig={pluginStates.page}
|
|
627
826
|
{pageSizes}
|
|
628
|
-
itemCount={
|
|
827
|
+
itemCount={serverItemCountValue}
|
|
629
828
|
updateTable={updateTableWithParams}
|
|
630
829
|
id={tableId}
|
|
631
830
|
{data}
|
|
@@ -16,7 +16,7 @@ let type = "string";
|
|
|
16
16
|
let isDate = false;
|
|
17
17
|
let dropdowns = [];
|
|
18
18
|
$values.forEach((item) => {
|
|
19
|
-
if (item) {
|
|
19
|
+
if (item !== null && item !== void 0) {
|
|
20
20
|
type = typeof (toFilterableValueFn ? toFilterableValueFn(item) : item);
|
|
21
21
|
if (type === "object") {
|
|
22
22
|
if (toFilterableValueFn && toFilterableValueFn(item) instanceof Date) {
|
|
@@ -105,6 +105,16 @@ const options = {
|
|
|
105
105
|
value: FilterOptionsEnum.no,
|
|
106
106
|
label: "Is not on"
|
|
107
107
|
}
|
|
108
|
+
],
|
|
109
|
+
boolean: [
|
|
110
|
+
{
|
|
111
|
+
value: FilterOptionsEnum.e,
|
|
112
|
+
label: "Is equal to"
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
value: FilterOptionsEnum.ne,
|
|
116
|
+
label: "Is not equal to"
|
|
117
|
+
}
|
|
108
118
|
]
|
|
109
119
|
};
|
|
110
120
|
const popupId = `${tableId}-${id}`;
|
|
@@ -129,14 +139,10 @@ const getMissingValue = (value) => {
|
|
|
129
139
|
};
|
|
130
140
|
const optionChangeHandler = (e, index) => {
|
|
131
141
|
delete $filters[id][dropdowns[index].option];
|
|
142
|
+
const val = dropdowns[index].value;
|
|
132
143
|
$filters[id] = {
|
|
133
144
|
...$filters[id],
|
|
134
|
-
[e.target.value]: (
|
|
135
|
-
// type === 'number'
|
|
136
|
-
// ?
|
|
137
|
-
getMissingValue(dropdowns[index].value)
|
|
138
|
-
)
|
|
139
|
-
// : dropdowns[index].value
|
|
145
|
+
[e.target.value]: type === "boolean" ? val === "" || val === void 0 ? void 0 : getMissingValue(val) === "true" || getMissingValue(val) === true : getMissingValue(val)
|
|
140
146
|
};
|
|
141
147
|
$filters = $filters;
|
|
142
148
|
dropdowns[index] = {
|
|
@@ -154,11 +160,7 @@ const valueChangeHandler = (e, index) => {
|
|
|
154
160
|
...$filters,
|
|
155
161
|
[id]: {
|
|
156
162
|
...$filters[id],
|
|
157
|
-
[dropdowns[index].option]: (
|
|
158
|
-
// type === 'number' ?
|
|
159
|
-
getMissingValue(e.target.value)
|
|
160
|
-
)
|
|
161
|
-
// : dropdowns[index].value
|
|
163
|
+
[dropdowns[index].option]: type === "boolean" ? e.target.value === "" ? void 0 : getMissingValue(e.target.value) === "true" || getMissingValue(e.target.value) === true : getMissingValue(e.target.value)
|
|
162
164
|
}
|
|
163
165
|
};
|
|
164
166
|
};
|
|
@@ -265,6 +267,17 @@ onMount(() => {
|
|
|
265
267
|
bind:value={dropdown.value}
|
|
266
268
|
aria-label="Filter value"
|
|
267
269
|
/>
|
|
270
|
+
{:else if type === 'boolean'}
|
|
271
|
+
<select
|
|
272
|
+
class="select border border-primary-500 text-sm p-1"
|
|
273
|
+
on:change={(e) => valueChangeHandler(e, index)}
|
|
274
|
+
bind:value={dropdown.value}
|
|
275
|
+
aria-label="Filter value"
|
|
276
|
+
>
|
|
277
|
+
<option value="" disabled selected>Select value...</option>
|
|
278
|
+
<option value="true">True</option>
|
|
279
|
+
<option value="false">False</option>
|
|
280
|
+
</select>
|
|
268
281
|
{:else}
|
|
269
282
|
<input
|
|
270
283
|
type="date"
|
|
@@ -16,8 +16,9 @@ let type = "string";
|
|
|
16
16
|
let isDate = false;
|
|
17
17
|
let dropdowns = [];
|
|
18
18
|
$values.forEach((item) => {
|
|
19
|
-
if (item) {
|
|
20
|
-
|
|
19
|
+
if (item !== null && item !== void 0) {
|
|
20
|
+
const rawType = typeof (toFilterableValueFn ? toFilterableValueFn(item) : item);
|
|
21
|
+
type = rawType === "bigint" ? "number" : rawType;
|
|
21
22
|
if (type === "object") {
|
|
22
23
|
if ((toFilterableValueFn ? toFilterableValueFn(item) : item) instanceof Date) {
|
|
23
24
|
isDate = true;
|
|
@@ -104,6 +105,16 @@ const options = {
|
|
|
104
105
|
// value: FilterOptionsEnum.no,
|
|
105
106
|
// label: 'Is not on'
|
|
106
107
|
// }
|
|
108
|
+
],
|
|
109
|
+
boolean: [
|
|
110
|
+
{
|
|
111
|
+
value: FilterOptionsEnum.e,
|
|
112
|
+
label: "Is equal to"
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
value: FilterOptionsEnum.ne,
|
|
116
|
+
label: "Is not equal to"
|
|
117
|
+
}
|
|
107
118
|
]
|
|
108
119
|
};
|
|
109
120
|
const popupId = `${tableId}-${id}`;
|
|
@@ -114,7 +125,8 @@ const popupFeatured = {
|
|
|
114
125
|
};
|
|
115
126
|
const stringValues = $values.map((item) => toStringFn ? toStringFn(item) : item);
|
|
116
127
|
const missingValues = stringValues.reduce((acc, item, index) => {
|
|
117
|
-
|
|
128
|
+
const strRepresentation = String(item).toLowerCase();
|
|
129
|
+
acc[strRepresentation] = $values[index];
|
|
118
130
|
return acc;
|
|
119
131
|
}, {});
|
|
120
132
|
const getMissingValue = (value) => {
|
|
@@ -122,9 +134,10 @@ const getMissingValue = (value) => {
|
|
|
122
134
|
};
|
|
123
135
|
const optionChangeHandler = (e, index) => {
|
|
124
136
|
delete $filters[id][dropdowns[index].option];
|
|
137
|
+
const val = dropdowns[index].value;
|
|
125
138
|
$filters[id] = {
|
|
126
139
|
...$filters[id],
|
|
127
|
-
[e.target.value]: getMissingValue(dropdowns[index].value)
|
|
140
|
+
[e.target.value]: type === "boolean" ? val === "" || val === void 0 ? void 0 : getMissingValue(val) === "true" || getMissingValue(val) === true : getMissingValue(dropdowns[index].value)
|
|
128
141
|
};
|
|
129
142
|
$filters = $filters;
|
|
130
143
|
dropdowns[index] = {
|
|
@@ -142,7 +155,28 @@ const valueChangeHandler = (e, index) => {
|
|
|
142
155
|
...$filters,
|
|
143
156
|
[id]: {
|
|
144
157
|
...$filters[id],
|
|
145
|
-
[dropdowns[index].option]:
|
|
158
|
+
[dropdowns[index].option]: (() => {
|
|
159
|
+
const rawVal = getMissingValue(e.target.value);
|
|
160
|
+
if (rawVal === "" || rawVal === void 0 || rawVal === null) {
|
|
161
|
+
return void 0;
|
|
162
|
+
}
|
|
163
|
+
if (type === "number") {
|
|
164
|
+
const cleanStr = String(rawVal).trim();
|
|
165
|
+
const isBigInt = /^\d+$/.test(cleanStr) && cleanStr.length >= 16;
|
|
166
|
+
if (isBigInt) {
|
|
167
|
+
try {
|
|
168
|
+
return BigInt(cleanStr);
|
|
169
|
+
} catch {
|
|
170
|
+
return cleanStr;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return parseFloat(cleanStr) || void 0;
|
|
174
|
+
}
|
|
175
|
+
if (type === "boolean") {
|
|
176
|
+
return rawVal === "true" || rawVal === true;
|
|
177
|
+
}
|
|
178
|
+
return rawVal;
|
|
179
|
+
})()
|
|
146
180
|
}
|
|
147
181
|
};
|
|
148
182
|
};
|
|
@@ -241,7 +275,7 @@ $: console.log($filters);
|
|
|
241
275
|
on:click|preventDefault={() => removeFilter(dropdown.option)}
|
|
242
276
|
on:keydown|preventDefault={() => removeFilter(dropdown.option)}
|
|
243
277
|
aria-label="Remove filter"
|
|
244
|
-
|
|
278
|
+
>
|
|
245
279
|
<Fa icon={faXmark} />
|
|
246
280
|
</div>
|
|
247
281
|
{/if}
|
|
@@ -262,6 +296,17 @@ $: console.log($filters);
|
|
|
262
296
|
bind:value={dropdown.value}
|
|
263
297
|
aria-label="Filter value"
|
|
264
298
|
/>
|
|
299
|
+
{:else if type === 'boolean'}
|
|
300
|
+
<select
|
|
301
|
+
class="select border border-primary-500 text-sm p-1"
|
|
302
|
+
on:change={(e) => valueChangeHandler(e, index)}
|
|
303
|
+
bind:value={dropdown.value}
|
|
304
|
+
aria-label="Filter value"
|
|
305
|
+
>
|
|
306
|
+
<option value="" disabled selected>Select value...</option>
|
|
307
|
+
<option value="true">True</option>
|
|
308
|
+
<option value="false">False</option>
|
|
309
|
+
</select>
|
|
265
310
|
{:else}
|
|
266
311
|
<input
|
|
267
312
|
type="date"
|
|
@@ -7,6 +7,17 @@ export let pageSizes;
|
|
|
7
7
|
export let id;
|
|
8
8
|
export let updateTable;
|
|
9
9
|
export let data;
|
|
10
|
+
const toCount = (value) => {
|
|
11
|
+
if (typeof value === "number") return Number.isNaN(value) ? 0 : value;
|
|
12
|
+
const parsed = Number(String(value ?? "").replace(/[^0-9.-]/g, ""));
|
|
13
|
+
return Number.isNaN(parsed) ? 0 : parsed;
|
|
14
|
+
};
|
|
15
|
+
const getEffectiveCount = () => {
|
|
16
|
+
const count = toCount(itemCount);
|
|
17
|
+
if (count > 0) return count;
|
|
18
|
+
return Array.isArray($data) ? $data.length : 0;
|
|
19
|
+
};
|
|
20
|
+
let effectiveCount = 0;
|
|
10
21
|
let indexInformation = "";
|
|
11
22
|
const { pageIndex, pageCount, pageSize } = pageConfig;
|
|
12
23
|
let pageSizeDropdownValue = $pageSize;
|
|
@@ -17,17 +28,19 @@ const pageSizePopup = {
|
|
|
17
28
|
closeQuery: ".listbox-item"
|
|
18
29
|
};
|
|
19
30
|
const getIndexInfomationString = () => {
|
|
20
|
-
|
|
31
|
+
const count = effectiveCount;
|
|
32
|
+
return count === 0 ? "No items" : `Displaying items ${$pageIndex * $pageSize + 1} - ${Math.min(
|
|
21
33
|
($pageIndex + 1) * $pageSize,
|
|
22
|
-
|
|
23
|
-
)} of ${
|
|
34
|
+
count
|
|
35
|
+
)} of ${count}`;
|
|
24
36
|
};
|
|
25
37
|
function updateTableServer() {
|
|
26
38
|
$data = [];
|
|
27
39
|
updateTable();
|
|
28
40
|
}
|
|
41
|
+
$: effectiveCount = getEffectiveCount();
|
|
29
42
|
$: paginationSettings = {
|
|
30
|
-
size:
|
|
43
|
+
size: effectiveCount,
|
|
31
44
|
limit: $pageSize,
|
|
32
45
|
page: $pageIndex,
|
|
33
46
|
amounts: pageSizes
|
|
@@ -52,9 +65,12 @@ $: $pageCount, $pageIndex, $pageSize, itemCount, indexInformation = getIndexInfo
|
|
|
52
65
|
{#each pageSizes as size}
|
|
53
66
|
<ListBoxItem
|
|
54
67
|
bind:group={pageSizeDropdownValue}
|
|
55
|
-
name="medium"
|
|
56
|
-
|
|
57
|
-
|
|
68
|
+
name="medium"
|
|
69
|
+
value={size}
|
|
70
|
+
on:click={() => {
|
|
71
|
+
$pageSize = size;
|
|
72
|
+
updateTableServer();
|
|
73
|
+
}}>{size}</ListBoxItem
|
|
58
74
|
>
|
|
59
75
|
{/each}
|
|
60
76
|
</ListBox>
|
|
@@ -63,7 +79,10 @@ $: $pageCount, $pageIndex, $pageSize, itemCount, indexInformation = getIndexInfo
|
|
|
63
79
|
</div>
|
|
64
80
|
<div class="flex justify-center">
|
|
65
81
|
<Paginator
|
|
66
|
-
on:page={(page) => {
|
|
82
|
+
on:page={(page) => {
|
|
83
|
+
$pageIndex = page.detail;
|
|
84
|
+
updateTableServer();
|
|
85
|
+
}}
|
|
67
86
|
settings={paginationSettings}
|
|
68
87
|
select="hidden"
|
|
69
88
|
active="!variant-filled-secondary !text-on-secondary-token"
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export default class ClientDB {
|
|
2
|
+
constructor(tableId: any);
|
|
3
|
+
tableId: any;
|
|
4
|
+
db: any;
|
|
5
|
+
init(rows: any): Promise<{
|
|
6
|
+
tableId: any;
|
|
7
|
+
count: any;
|
|
8
|
+
}>;
|
|
9
|
+
query({ q, filters, order, offset, limit }?: {
|
|
10
|
+
q?: string | undefined;
|
|
11
|
+
filters?: never[] | undefined;
|
|
12
|
+
order?: never[] | undefined;
|
|
13
|
+
offset?: number | undefined;
|
|
14
|
+
limit?: number | undefined;
|
|
15
|
+
}): Promise<{
|
|
16
|
+
tableId: any;
|
|
17
|
+
rows: any[];
|
|
18
|
+
total: number;
|
|
19
|
+
}>;
|
|
20
|
+
clear(): Promise<void>;
|
|
21
|
+
destroy(): void;
|
|
22
|
+
}
|