Skip to content

Commit 61f24dc

Browse files
committed
Move Table functions to a different file to shorten TableContent code
1 parent 40f0cdd commit 61f24dc

File tree

2 files changed

+231
-165
lines changed

2 files changed

+231
-165
lines changed

src/lib/components/Table/TableContent.svelte

Lines changed: 74 additions & 164 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<script lang="ts">
2-
import { afterUpdate, onDestroy, createEventDispatcher } from 'svelte';
2+
import { afterUpdate, createEventDispatcher, onDestroy } from 'svelte';
33
import { readable, writable } from 'svelte/store';
44
55
import Fa from 'svelte-fa';
@@ -26,18 +26,9 @@
2626
import TablePagination from './TablePagination.svelte';
2727
import TablePaginationServer from './TablePaginationServer.svelte';
2828
import ColumnsMenu from './ColumnsMenu.svelte';
29+
import * as utils from './utils';
2930
import { columnFilter, searchFilter } from './filter';
30-
import {
31-
cellStyle,
32-
exportAsCsv,
33-
jsonToCsv,
34-
fixedWidth,
35-
normalizeFilters,
36-
resetResize,
37-
convertServerColumns,
38-
minWidth
39-
} from './shared';
40-
import { Receive, Send } from '$models/Models';
31+
import { Send } from '$models/Models';
4132
import type { TableConfig } from '$models/Models';
4233
import type { FilterOptionsEnum } from '$models/Enums';
4334
@@ -68,7 +59,7 @@
6859
let tableRef: HTMLTableElement;
6960
7061
const serverSide = server !== undefined;
71-
const { baseUrl, entityId, versionId, sendModel = new Send() } = server ?? {};
62+
const { sendModel = new Send() } = server ?? {};
7263
7364
const filters = writable<{
7465
[key: string]: { [key in FilterOptionsEnum]?: number | string | Date };
@@ -86,7 +77,7 @@
8677
const colWidths = writable<number[]>([]);
8778
8879
// Server-side variables
89-
const serverItems = serverSide ? writable<Number>(0) : undefined;
80+
const serverItems = serverSide ? writable<number>(0) : undefined;
9081
const serverItemCount = serverSide
9182
? readable<Number>(0, (set) => {
9283
serverItems!.subscribe((val) => set(val));
@@ -209,7 +200,7 @@
209200
id,
210201
tableId,
211202
values,
212-
updateTable,
203+
updateTable: updateTableWithParams,
213204
pageIndex,
214205
toFilterableValueFn,
215206
filters,
@@ -257,7 +248,7 @@
257248
id,
258249
tableId,
259250
values,
260-
updateTable,
251+
updateTable: updateTableWithParams,
261252
pageIndex,
262253
filters
263254
})
@@ -312,65 +303,6 @@
312303
// Column visibility configuration
313304
const { hiddenColumnIds } = pluginStates.hideColumns;
314305
315-
const updateTable = async () => {
316-
if (!sendModel) throw new Error('Server-side configuration is missing');
317-
318-
sendModel.limit = $pageSize;
319-
sendModel.offset = $pageSize * $pageIndex;
320-
sendModel.version = versionId || -1;
321-
sendModel.id = entityId || -1;
322-
sendModel.filter = normalizeFilters($filters);
323-
324-
let fetchData;
325-
326-
try {
327-
isFetching = true;
328-
fetchData = await fetch(baseUrl || '', {
329-
headers: {
330-
'Content-Type': 'application/json'
331-
},
332-
method: 'POST',
333-
body: JSON.stringify(sendModel)
334-
});
335-
} catch (error) {
336-
throw new Error(`Network error: ${(error as Error).message}`);
337-
} finally {
338-
isFetching = false;
339-
}
340-
341-
if (!fetchData.ok) {
342-
throw new Error('Failed to fetch data');
343-
}
344-
345-
const response: Receive = await fetchData.json();
346-
347-
// Format server columns to the client columns
348-
if (response.columns !== undefined) {
349-
columns = convertServerColumns(response.columns, columns);
350-
351-
const clientCols = response.columns.reduce((acc, col) => {
352-
acc[col.key] = col.column;
353-
return acc;
354-
}, {});
355-
356-
const tmpArr: any[] = [];
357-
358-
response.data.forEach((row, index) => {
359-
const tmp: { [key: string]: any } = {};
360-
Object.keys(row).forEach((key) => {
361-
tmp[clientCols[key]] = row[key];
362-
});
363-
tmpArr.push(tmp);
364-
});
365-
dispatch('fetch', columns);
366-
$data = tmpArr;
367-
}
368-
369-
$serverItems = response.count;
370-
371-
return response;
372-
};
373-
374306
const sortServer = (order: 'asc' | 'desc' | undefined, id: string) => {
375307
if (!sendModel) throw new Error('Server-side configuration is missing');
376308
// Set parameter for sorting
@@ -383,83 +315,70 @@
383315
// Reset pagination
384316
$pageIndex = 0;
385317
386-
updateTable();
318+
updateTableWithParams();
387319
};
388320
389-
const getMaxCellHeightInRow = () => {
390-
if (!tableRef || resizable === 'columns' || resizable === 'none') return;
391-
392-
tableRef.querySelectorAll('tbody tr').forEach((row, index) => {
393-
const cells = row.querySelectorAll('td');
394-
395-
let maxHeight = optionsComponent ? 56 : 44;
396-
let minHeight = optionsComponent ? 56 : 44;
321+
// Function to update the table with the provided parameters for easily passing to other components
322+
const updateTableWithParams = async () => {
323+
isFetching = true;
324+
const result = await utils.updateTable(
325+
$pageSize,
326+
$pageIndex,
327+
server,
328+
$filters,
329+
data,
330+
serverItems,
331+
columns,
332+
dispatch
333+
);
334+
isFetching = false;
397335
398-
cells.forEach((cell) => {
399-
const cellHeight = cell.getBoundingClientRect().height;
400-
// + 2 pixels for rendering borders correctly
401-
if (cellHeight > maxHeight) {
402-
maxHeight = cellHeight + 2;
403-
}
404-
if (cellHeight < minHeight) {
405-
minHeight = cellHeight + 2;
406-
}
407-
});
408-
409-
rowHeights.update((rh) => {
410-
const id = +row.id.split(`${tableId}-row-`)[1];
411-
return {
412-
...rh,
413-
[id]: {
414-
max: maxHeight - 24,
415-
min: Math.max(minHeight - 24, rowHeight ?? 20)
416-
}
417-
};
418-
});
419-
});
336+
return result;
420337
};
421338
422-
const getMinCellWidthInColumn = () => {
423-
if (!tableRef || resizable === 'rows' || resizable === 'none') return;
424-
425-
// Initialize the colWidths array if it is empty
426-
if ($colWidths.length === 0) {
427-
$colWidths = Array.from({ length: $headerRows[0].cells.length }, () => 100);
339+
// Initializes observers for rows and columns
340+
const getDimensions = () => {
341+
if (!tableRef) return;
342+
if (resizable === 'none') return;
343+
else if (resizable === 'columns') {
344+
observeHeaderColumns();
345+
} else if (resizable === 'rows') {
346+
observeFirstCells();
347+
} else {
348+
observeHeaderColumns();
349+
observeFirstCells();
428350
}
429-
430-
colWidths.update((cw) => {
431-
tableRef?.querySelectorAll('thead tr th span').forEach((cell, index) => {
432-
// + 12 pixels for padding and + 32 pixels for filter icon
433-
// If the column width is 100, which means it has not been initialized, then calculate the width
434-
cw[index] = cw[index] === 100 ? cell.getBoundingClientRect().width + 12 + 32 : cw[index];
435-
});
436-
return cw;
437-
});
438351
};
439352
353+
// Resize observer for rows
440354
const resizeRowsObserver = new ResizeObserver(() => {
441-
getMaxCellHeightInRow();
355+
utils.getMaxCellHeightInRow(
356+
tableRef,
357+
resizable,
358+
optionsComponent,
359+
rowHeights,
360+
tableId,
361+
rowHeight
362+
);
442363
});
443364
365+
// Resize observers for columns
444366
const resizeColumnsObserver = new ResizeObserver(() => {
445-
getMinCellWidthInColumn();
367+
utils.getMinCellWidthInColumn(tableRef, colWidths, $headerRows[0].cells.length, resizable);
446368
});
447369
370+
// Adds observers on the first cells of each row to resize rows
448371
const observeFirstCells = () => {
449372
if (!tableRef) return;
450373
451-
$pageRows.forEach((row) => {
452-
const cell = tableRef.querySelector(`#${tableId}-row-${row.id}`);
453-
if (cell) {
454-
resizeRowsObserver.observe(cell);
455-
}
456-
});
457-
458374
tableRef.querySelectorAll('tbody tr td:first-child').forEach((cell) => {
459375
resizeRowsObserver.observe(cell);
460376
});
377+
378+
return resizeRowsObserver;
461379
};
462380
381+
// Adds observers on the header columns to resize columns
463382
const observeHeaderColumns = () => {
464383
if (!tableRef) return;
465384
@@ -469,6 +388,7 @@
469388
};
470389
471390
afterUpdate(() => {
391+
// If not resizable, return
472392
if (resizable !== 'rows' && resizable !== 'both') {
473393
return;
474394
}
@@ -480,27 +400,13 @@
480400
}
481401
});
482402
483-
// Remove the resize observer when the component is destroyed for performance reasons
484403
onDestroy(() => {
485-
resizeRowsObserver.disconnect();
486404
resizeColumnsObserver.disconnect();
405+
resizeRowsObserver.disconnect();
487406
});
488407
489-
const getDimensions = () => {
490-
if (!tableRef) return;
491-
if (resizable === 'none') return;
492-
else if (resizable === 'columns') {
493-
observeHeaderColumns();
494-
} else if (resizable === 'rows') {
495-
observeFirstCells();
496-
} else {
497-
observeHeaderColumns();
498-
observeFirstCells();
499-
}
500-
};
501-
502408
$: sortKeys = pluginStates.sort.sortKeys;
503-
$: serverSide && updateTable();
409+
$: serverSide && updateTableWithParams();
504410
$: serverSide && sortServer($sortKeys[0]?.order, $sortKeys[0]?.id);
505411
$: $hiddenColumnIds = shownColumns.filter((col) => !col.visible).map((col) => col.id);
506412
</script>
@@ -600,19 +506,22 @@
600506
class="btn btn-sm variant-filled-primary rounded-full order-last flex gap-2 items-center"
601507
aria-label="Reset sizing of columns and rows"
602508
on:click|preventDefault={() =>
603-
resetResize($headerRows, $pageRows, tableId, columns, resizable)}
509+
utils.resetResize($headerRows, $pageRows, tableId, columns, resizable)}
604510
><Fa icon={faCompress} /> Reset sizing</button
605511
>
606512
{/if}
513+
<!-- Enable export as CSV button if exportable === true -->
607514
{#if exportable}
608515
<button
609516
type="button"
610517
class="btn btn-sm variant-filled-primary rounded-full order-last flex items-center gap-2"
611518
aria-label="Export table data as CSV"
612-
on:click|preventDefault={() => exportAsCsv(tableId, jsonToCsv($exportedData))}
519+
on:click|preventDefault={() =>
520+
utils.exportAsCsv(tableId, utils.jsonToCsv($exportedData))}
613521
><Fa icon={faDownload} /> Export as CSV</button
614522
>
615523
{/if}
524+
<!-- Enable show/hide columns menu if showColumnsMenu === true -->
616525
{#if showColumnsMenu && shownColumns.length > 0}
617526
<ColumnsMenu bind:columns={shownColumns} {tableId} />
618527
{/if}
@@ -646,16 +555,20 @@
646555
{...attrs}
647556
style={`
648557
width: ${cell.isData() ? 'auto' : '0'};
649-
${cellStyle(cell.id, columns)}
558+
${utils.cellStyle(cell.id, columns)}
650559
`}
651560
>
652561
<div
653562
class="overflow-auto"
654563
class:resize-x={(resizable === 'columns' || resizable === 'both') &&
655-
!fixedWidth(cell.id, columns)}
564+
!utils.fixedWidth(cell.id, columns)}
656565
id="th-{tableId}-{cell.id}"
657566
style={`
658-
min-width: ${minWidth(cell.id, columns) ? minWidth(cell.id, columns) : $colWidths[index]}px;
567+
min-width: ${
568+
utils.minWidth(cell.id, columns)
569+
? utils.minWidth(cell.id, columns)
570+
: $colWidths[index]
571+
}px;
659572
`}
660573
>
661574
<div class="flex justify-between items-center">
@@ -714,15 +627,7 @@
714627
? 'resize-y overflow-auto'
715628
: 'block'}"
716629
id="{tableId}-{cell.id}-{row.id}"
717-
style={`
718-
min-height: ${$rowHeights && $rowHeights[+row.id] ? `${$rowHeights[+row.id].min}px` : 'auto'};
719-
max-height: ${
720-
index !== 0 && $rowHeights && $rowHeights[+row.id]
721-
? `${$rowHeights[+row.id].max}px`
722-
: 'auto'
723-
};
724-
height: ${$rowHeights && $rowHeights[+row.id] ? `${$rowHeights[+row.id].min}px` : 'auto'};
725-
`}
630+
style={utils.getResizeStyles($rowHeights, row.id, index)}
726631
>
727632
<!-- Adding config for initial rowHeight, if provided -->
728633
<div
@@ -735,8 +640,8 @@
735640
class="grow overflow-auto"
736641
style={cell.isData()
737642
? `width: ${
738-
minWidth(cell.id, columns)
739-
? minWidth(cell.id, columns)
643+
utils.minWidth(cell.id, columns)
644+
? utils.minWidth(cell.id, columns)
740645
: $colWidths[index]
741646
}px;`
742647
: 'max-width: min-content;'}
@@ -779,13 +684,18 @@
779684
{pageIndex}
780685
{pageSize}
781686
{serverItemCount}
782-
{updateTable}
687+
updateTable={updateTableWithParams}
783688
{pageSizes}
784689
{pageIndexStringType}
785690
id={tableId}
786691
/>
787692
{:else}
788-
<TablePagination pageConfig={pluginStates.page} {pageSizes} id={tableId} {pageIndexStringType} />
693+
<TablePagination
694+
pageConfig={pluginStates.page}
695+
{pageSizes}
696+
id={tableId}
697+
{pageIndexStringType}
698+
/>
789699
{/if}
790700
{/if}
791701
</div>

0 commit comments

Comments
 (0)