@bexis2/bexis2-core-ui 0.4.23 → 0.4.24
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 +9 -0
- package/dist/components/Facets/Facets.svelte +13 -9
- package/dist/components/Table/TableContent.svelte +74 -141
- package/dist/components/Table/TableContent.svelte.d.ts +0 -1
- package/dist/components/Table/TablePagination.svelte +15 -7
- package/dist/components/Table/TablePagination.svelte.d.ts +2 -0
- package/dist/components/Table/TablePaginationServer.svelte +11 -9
- package/dist/components/Table/TablePaginationServer.svelte.d.ts +1 -0
- package/dist/components/Table/utils.d.ts +34 -0
- package/dist/components/Table/{shared.js → utils.js} +109 -0
- package/dist/models/Models.d.ts +2 -0
- package/package.json +1 -1
- package/src/lib/components/Facets/Facets.svelte +13 -9
- package/src/lib/components/Table/TableContent.svelte +81 -167
- package/src/lib/components/Table/TablePagination.svelte +17 -7
- package/src/lib/components/Table/TablePaginationServer.svelte +16 -9
- package/src/lib/components/Table/{shared.ts → utils.ts} +157 -1
- package/src/lib/models/Models.ts +2 -0
- package/dist/components/Table/shared.d.ts +0 -15
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
export let id; // Unique table ID
|
|
11
11
|
export let pageIndex;
|
|
12
12
|
export let pageSize;
|
|
13
|
+
export let pageIndexStringType;
|
|
13
14
|
export let pageSizes; // Available page sizes
|
|
14
15
|
export let serverItemCount; // Total number of items expected from the server. `serverSide` must be true on table config.
|
|
15
16
|
export let updateTable; // Function to update table
|
|
@@ -20,6 +21,9 @@
|
|
|
20
21
|
let goToNextPageDisabled = true;
|
|
21
22
|
let goToPreviousPageDisabled = true;
|
|
22
23
|
|
|
24
|
+
// Index information string
|
|
25
|
+
let indexInformation = '';
|
|
26
|
+
|
|
23
27
|
// Handles the input change event
|
|
24
28
|
const handleChange = (e) => {
|
|
25
29
|
const value = e.target.value;
|
|
@@ -58,12 +62,23 @@
|
|
|
58
62
|
updateTable();
|
|
59
63
|
};
|
|
60
64
|
|
|
65
|
+
const getIndexInfomationString = () => {
|
|
66
|
+
if (pageIndexStringType === 'pages') {
|
|
67
|
+
return pageCount > 0 ? `Page ${$pageIndex + 1} of ${pageCount}` : 'No pages';
|
|
68
|
+
} else {
|
|
69
|
+
return `Showing ${$pageIndex * $pageSize + 1} - ${($pageIndex + 1) * $pageSize} of ${
|
|
70
|
+
pageCount * $pageSize
|
|
71
|
+
} items`;
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
|
|
61
75
|
$: pageCount = Math.ceil($serverItemCount / $pageSize);
|
|
62
76
|
$: goToFirstPageDisabled = !$pageIndex;
|
|
63
77
|
$: goToLastPageDisabled = $pageIndex == pageCount - 1;
|
|
64
78
|
$: goToNextPageDisabled = $pageIndex == pageCount - 1;
|
|
65
79
|
$: goToPreviousPageDisabled = !$pageIndex;
|
|
66
80
|
$: $pageSize && updateTable(); // Update query when page size changes
|
|
81
|
+
$: pageCount, $pageIndex, $pageSize, (indexInformation = getIndexInfomationString());
|
|
67
82
|
|
|
68
83
|
updateTable();
|
|
69
84
|
</script>
|
|
@@ -127,15 +142,7 @@
|
|
|
127
142
|
</div>
|
|
128
143
|
<div class="flex justify-end items-center">
|
|
129
144
|
<span class="text-sm text-gray-500">
|
|
130
|
-
{
|
|
131
|
-
{#if pageCount == 1}
|
|
132
|
-
1 page
|
|
133
|
-
{:else}
|
|
134
|
-
{pageCount} pages
|
|
135
|
-
{/if}
|
|
136
|
-
{:else}
|
|
137
|
-
No pages
|
|
138
|
-
{/if}
|
|
145
|
+
{indexInformation}
|
|
139
146
|
</span>
|
|
140
147
|
</div>
|
|
141
148
|
</div>
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import dateFormat from 'dateformat';
|
|
2
|
+
import { SvelteComponent } from 'svelte';
|
|
3
|
+
import type { Writable } from 'svelte/store';
|
|
2
4
|
|
|
5
|
+
import { Send, Receive } from '$models/Models';
|
|
3
6
|
import type { FilterOptionsEnum } from '$models/Enums';
|
|
4
|
-
import type { Columns, Filter, ServerColumn } from '$models/Models';
|
|
7
|
+
import type { Columns, Filter, ServerColumn, ServerConfig } from '$models/Models';
|
|
5
8
|
|
|
6
9
|
// Function to determine minWidth for a column to simplify the logic in the HTML
|
|
7
10
|
export const minWidth = (id: string, columns: Columns | undefined) => {
|
|
@@ -158,6 +161,76 @@ export const missingValuesFn = (
|
|
|
158
161
|
return foundKey ? missingValues[foundKey] : key;
|
|
159
162
|
};
|
|
160
163
|
|
|
164
|
+
// Function to update the server-side table data
|
|
165
|
+
export const updateTable = async (
|
|
166
|
+
pageSize: number,
|
|
167
|
+
pageIndex: number,
|
|
168
|
+
server: ServerConfig | undefined,
|
|
169
|
+
filters: {
|
|
170
|
+
[key: string]: { [key in FilterOptionsEnum]?: number | string | Date }
|
|
171
|
+
},
|
|
172
|
+
data: Writable<any[]>,
|
|
173
|
+
serverItems: Writable<number> | undefined,
|
|
174
|
+
columns: Columns | undefined,
|
|
175
|
+
dispatch: any
|
|
176
|
+
) => {
|
|
177
|
+
const { baseUrl, entityId, versionId, sendModel = new Send() } = server ?? {};
|
|
178
|
+
|
|
179
|
+
if (!sendModel) throw new Error('Server-side configuration is missing');
|
|
180
|
+
|
|
181
|
+
sendModel.limit = pageSize;
|
|
182
|
+
sendModel.offset = pageSize * pageIndex;
|
|
183
|
+
sendModel.version = versionId || -1;
|
|
184
|
+
sendModel.id = entityId || -1;
|
|
185
|
+
sendModel.filter = normalizeFilters(filters);
|
|
186
|
+
|
|
187
|
+
let fetchData;
|
|
188
|
+
|
|
189
|
+
try {
|
|
190
|
+
fetchData = await fetch(baseUrl || '', {
|
|
191
|
+
headers: {
|
|
192
|
+
'Content-Type': 'application/json'
|
|
193
|
+
},
|
|
194
|
+
method: 'POST',
|
|
195
|
+
body: JSON.stringify(sendModel)
|
|
196
|
+
});
|
|
197
|
+
} catch (error) {
|
|
198
|
+
throw new Error(`Network error: ${(error as Error).message}`);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
if (!fetchData.ok) {
|
|
202
|
+
throw new Error('Failed to fetch data');
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const response: Receive = await fetchData.json();
|
|
206
|
+
|
|
207
|
+
// Format server columns to the client columns
|
|
208
|
+
if (response.columns !== undefined) {
|
|
209
|
+
columns = convertServerColumns(response.columns, columns);
|
|
210
|
+
|
|
211
|
+
const clientCols = response.columns.reduce((acc, col) => {
|
|
212
|
+
acc[col.key] = col.column;
|
|
213
|
+
return acc;
|
|
214
|
+
}, {});
|
|
215
|
+
|
|
216
|
+
const tmpArr: any[] = [];
|
|
217
|
+
|
|
218
|
+
response.data.forEach((row, index) => {
|
|
219
|
+
const tmp: { [key: string]: any } = {};
|
|
220
|
+
Object.keys(row).forEach((key) => {
|
|
221
|
+
tmp[clientCols[key]] = row[key];
|
|
222
|
+
});
|
|
223
|
+
tmpArr.push(tmp);
|
|
224
|
+
});
|
|
225
|
+
dispatch('fetch', columns);
|
|
226
|
+
data.set(tmpArr);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
serverItems?.set(response.count);
|
|
230
|
+
|
|
231
|
+
return response;
|
|
232
|
+
};
|
|
233
|
+
|
|
161
234
|
export const convertServerColumns = (
|
|
162
235
|
serverColumns: ServerColumn[],
|
|
163
236
|
columns: Columns | undefined
|
|
@@ -215,3 +288,86 @@ export const convertServerColumns = (
|
|
|
215
288
|
|
|
216
289
|
return columnsConfig;
|
|
217
290
|
};
|
|
291
|
+
|
|
292
|
+
// Calculates the maximum height of the cells in each row
|
|
293
|
+
export const getMaxCellHeightInRow = (
|
|
294
|
+
tableRef: HTMLTableElement,
|
|
295
|
+
resizable: 'columns' | 'rows' | 'none' | 'both',
|
|
296
|
+
optionsComponent: typeof SvelteComponent | undefined,
|
|
297
|
+
rowHeights: Writable<{ [key: number]: { max: number; min: number } }>,
|
|
298
|
+
tableId: string,
|
|
299
|
+
rowHeight: number | null
|
|
300
|
+
) => {
|
|
301
|
+
if (!tableRef || resizable === 'columns' || resizable === 'none') return;
|
|
302
|
+
|
|
303
|
+
tableRef.querySelectorAll('tbody tr').forEach((row, index) => {
|
|
304
|
+
const cells = row.querySelectorAll('td');
|
|
305
|
+
|
|
306
|
+
let maxHeight = optionsComponent ? 56 : 44;
|
|
307
|
+
let minHeight = optionsComponent ? 56 : 44;
|
|
308
|
+
|
|
309
|
+
cells.forEach((cell) => {
|
|
310
|
+
const cellHeight = cell.getBoundingClientRect().height;
|
|
311
|
+
// + 2 pixels for rendering borders correctly
|
|
312
|
+
if (cellHeight > maxHeight) {
|
|
313
|
+
maxHeight = cellHeight + 2;
|
|
314
|
+
}
|
|
315
|
+
if (cellHeight < minHeight) {
|
|
316
|
+
minHeight = cellHeight + 2;
|
|
317
|
+
}
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
rowHeights.update((rh) => {
|
|
321
|
+
const id = +row.id.split(`${tableId}-row-`)[1];
|
|
322
|
+
return {
|
|
323
|
+
...rh,
|
|
324
|
+
[id]: {
|
|
325
|
+
max: maxHeight - 24,
|
|
326
|
+
min: Math.max(minHeight - 24, rowHeight ?? 20)
|
|
327
|
+
}
|
|
328
|
+
};
|
|
329
|
+
});
|
|
330
|
+
});
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
// Calculates the minimum width of the cells in each column
|
|
334
|
+
export const getMinCellWidthInColumn = (
|
|
335
|
+
tableRef: HTMLTableElement,
|
|
336
|
+
colWidths: Writable<number[]>,
|
|
337
|
+
headerRowsLength: number,
|
|
338
|
+
resizable: 'columns' | 'rows' | 'none' | 'both'
|
|
339
|
+
) => {
|
|
340
|
+
if (!tableRef || resizable === 'rows' || resizable === 'none') return;
|
|
341
|
+
|
|
342
|
+
// Initialize the column widths if they are not already initialized
|
|
343
|
+
colWidths.update((cw) => {
|
|
344
|
+
if (cw.length === 0) {
|
|
345
|
+
return Array.from({ length: headerRowsLength }, () => 100);
|
|
346
|
+
}
|
|
347
|
+
return cw;
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
colWidths.update((cw) => {
|
|
351
|
+
tableRef?.querySelectorAll('thead tr th span').forEach((cell, index) => {
|
|
352
|
+
// + 12 pixels for padding and + 32 pixels for filter icon
|
|
353
|
+
// If the column width is 100, which means it has not been initialized, then calculate the width
|
|
354
|
+
cw[index] = cw[index] === 100 ? cell.getBoundingClientRect().width + 12 + 32 : cw[index];
|
|
355
|
+
});
|
|
356
|
+
return cw;
|
|
357
|
+
});
|
|
358
|
+
};
|
|
359
|
+
|
|
360
|
+
export const getResizeStyles = (
|
|
361
|
+
rowHeights: { [key: number]: { max: number; min: number } },
|
|
362
|
+
id: string | number,
|
|
363
|
+
index: number
|
|
364
|
+
) => {
|
|
365
|
+
return `
|
|
366
|
+
min-height: ${rowHeights && rowHeights[+id] ? `${rowHeights[+id].min}px` : 'auto'};
|
|
367
|
+
max-height: ${index !== 0 && rowHeights && rowHeights[+id]
|
|
368
|
+
? `${rowHeights[+id].max}px`
|
|
369
|
+
: 'auto'
|
|
370
|
+
};
|
|
371
|
+
height: ${rowHeights && rowHeights[+id] ? `${rowHeights[+id].min}px` : 'auto'};
|
|
372
|
+
`;
|
|
373
|
+
}
|
package/src/lib/models/Models.ts
CHANGED
|
@@ -117,6 +117,7 @@ export interface TableConfig<T> {
|
|
|
117
117
|
id: string;
|
|
118
118
|
data: Writable<T[]>;
|
|
119
119
|
resizable?: 'none' | 'rows' | 'columns' | 'both'; // none by default
|
|
120
|
+
showColumnsMenu?: boolean; // false by default
|
|
120
121
|
toggle?: boolean; // false by default
|
|
121
122
|
search?: boolean; // true by default
|
|
122
123
|
fitToScreen?: boolean; // true by default
|
|
@@ -126,6 +127,7 @@ export interface TableConfig<T> {
|
|
|
126
127
|
exportable?: boolean; // false by default
|
|
127
128
|
pageSizes?: number[]; // [5, 10, 20, 50, 100] by default
|
|
128
129
|
defaultPageSize?: number; // 10 by default
|
|
130
|
+
pageIndexStringType?: 'items' | 'pages'; // pages by default
|
|
129
131
|
optionsComponent?: typeof SvelteComponent;
|
|
130
132
|
|
|
131
133
|
server?: ServerConfig;
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import type { FilterOptionsEnum } from '../../models/Enums';
|
|
2
|
-
import type { Columns, Filter, ServerColumn } from '../../models/Models';
|
|
3
|
-
export declare const minWidth: (id: string, columns: Columns | undefined) => number;
|
|
4
|
-
export declare const fixedWidth: (id: string, columns: Columns | undefined) => number;
|
|
5
|
-
export declare const cellStyle: (id: string, columns: Columns | undefined) => string;
|
|
6
|
-
export declare const normalizeFilters: (filters: {
|
|
7
|
-
[key: string]: { [key in FilterOptionsEnum]?: number | string | Date; };
|
|
8
|
-
}) => Filter[];
|
|
9
|
-
export declare const exportAsCsv: (tableId: string, exportedData: string) => void;
|
|
10
|
-
export declare const jsonToCsv: (data: string) => string;
|
|
11
|
-
export declare const resetResize: (headerRows: any, pageRows: any, tableId: string, columns: Columns | undefined, resizable: "none" | "rows" | "columns" | "both") => void;
|
|
12
|
-
export declare const missingValuesFn: (key: number | string, missingValues: {
|
|
13
|
-
[key: string | number]: string;
|
|
14
|
-
}) => string | number;
|
|
15
|
-
export declare const convertServerColumns: (serverColumns: ServerColumn[], columns: Columns | undefined) => Columns;
|