Skip to content

Commit 4b0ae7d

Browse files
authored
Merge pull request #106 from BEXIS2/table
Table
2 parents 440f50c + f7c4226 commit 4b0ae7d

18 files changed

+225
-148
lines changed

src/app.postcss

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,16 @@ body {
1212
[type='text']:focus {
1313
--tw-ring-color: #00000;
1414
}
15+
16+
.svelte-select, .svelte-select-list {
17+
@apply dark:!bg-zinc-700 border dark:!border-zinc-500;
18+
}
19+
20+
.multi-item {
21+
@apply dark:!bg-zinc-500 dark:!outline-zinc-400;
22+
}
23+
24+
.list-item .item.hover:not(.active):not(.list-group-title) {
25+
@apply dark:!text-black;
26+
}
27+

src/lib/components/Facets/Facets.svelte

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
ref: ShowMore,
2727
props: {
2828
group,
29-
handleSave,
29+
handleApply,
3030
handleCancel
3131
}
3232
}
@@ -45,7 +45,7 @@
4545
4646
const modalStore = getModalStore();
4747
48-
const handleSave = (group: SelectedFacetGroup) => {
48+
const handleApply = (group: SelectedFacetGroup) => {
4949
const { name: groupName, children } = group;
5050
5151
dispatch('showMoreOpenChange', {
@@ -110,9 +110,8 @@
110110
changed.length && dispatch('facetSelect', changed);
111111
};
112112
113-
// Keeping the sorting function, but stays unused for now
114113
const sortOptions = () => {
115-
// Sort facets in a descending order if count exits, or sort alphabetically
114+
// Sort facets in a descending order if count exits
116115
Object.keys(selected).forEach((group) => {
117116
const checked = Object.keys(selected[group].children)
118117
.filter((item) => selected[group].children[item].selected)
@@ -121,13 +120,20 @@
121120
if (a.count != undefined && b.count != undefined) {
122121
return b.count - a.count;
123122
}
124-
return a.displayName.localeCompare(b.displayName);
123+
return 0;
125124
})
126125
.map((item) => item.name);
127126
128-
const unchecked = Object.keys(selected[group].children).filter(
129-
(item) => !checked.includes(item)
130-
);
127+
const unchecked = Object.keys(selected[group].children)
128+
.filter((item) => !checked.includes(item))
129+
.map((item) => selected[group].children[item])
130+
.sort((a, b) => {
131+
if (a.count != undefined && b.count != undefined) {
132+
return b.count - a.count;
133+
}
134+
return 0;
135+
})
136+
.map((item) => item.name);
131137
132138
const groupIndex = displayedGroups.findIndex((g) => g.name === group);
133139
@@ -172,7 +178,7 @@
172178
});
173179
174180
$: displayedGroups = structuredClone($groups);
175-
$: selectedItems, mapSelected('items'); // sortOptions(); // Sorting is not used for now
181+
$: selectedItems, mapSelected('items'), sortOptions();
176182
$: selectedGroups, mapSelected('groups');
177183
</script>
178184

@@ -186,7 +192,7 @@
186192
bind:checked={selectedGroups[group.name]}
187193
bind:group={selectedGroups}
188194
>
189-
<p class="font-semibold">
195+
<p class="font-semibold whitespace-nowrap">
190196
{group.displayName}{group.count !== undefined ? ` (${group.count})` : ''}
191197
</p>
192198

@@ -204,7 +210,12 @@
204210
selection
205211
multiple
206212
>
207-
<p>{item.displayName} ({item.count})</p>
213+
<div class="flex gap-2">
214+
<p class="w-max grow truncate">
215+
<span title={item.displayName}>{item.displayName}</span>
216+
</p>
217+
<span>({item.count})</span>
218+
</div>
208219
</TreeViewItem>
209220
{/each}
210221
<!-- Trigger for the Modal to view all options -->
@@ -226,7 +237,12 @@
226237
selection
227238
multiple
228239
>
229-
<p>{item.displayName} ({item.count})</p>
240+
<div class="flex gap-2">
241+
<p class="w-max grow truncate">
242+
<span title={item.displayName}>{item.displayName}</span>
243+
</p>
244+
<span>({item.count})</span>
245+
</div>
230246
</TreeViewItem>
231247
{/each}
232248
{/if}

src/lib/components/Facets/ShowMore.svelte

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import type { SelectedFacetGroup } from '$models/Models';
33
44
export let group: SelectedFacetGroup;
5-
export let handleSave: (group: SelectedFacetGroup) => {};
5+
export let handleApply: (group: SelectedFacetGroup) => {};
66
export let handleCancel: (groupName: string) => {};
77
88
let selected = structuredClone(group.children);
@@ -15,8 +15,8 @@
1515
Object.keys(selected).forEach((key) => (selected[key].selected = false));
1616
};
1717
18-
const onSave = () => {
19-
handleSave({
18+
const onApply = () => {
19+
handleApply({
2020
...group,
2121
children: selected
2222
});
@@ -29,32 +29,46 @@
2929
};
3030
3131
const gridClass = (items: any[]) => {
32-
if (items.length >= 50) {
33-
return 'grid-cols-5';
34-
} else if (items.length >= 30) {
35-
return 'grid-cols-4';
36-
} else if (items.length >= 20) {
37-
return 'grid-cols-3';
38-
}
32+
const ceil = Math.ceil(Math.sqrt(items.length));
33+
const max = Math.max(ceil, Math.floor(items.length / 3));
3934
40-
return 'grid-cols-2';
35+
const classes = [
36+
'grid-rows-1',
37+
'grid-rows-2',
38+
'grid-rows-3',
39+
'grid-rows-4',
40+
'grid-rows-5',
41+
'grid-rows-6',
42+
'grid-rows-7',
43+
'grid-rows-8',
44+
'grid-rows-9',
45+
'grid-rows-10',
46+
'grid-rows-11',
47+
'grid-rows-12'
48+
];
49+
50+
if (max > 12) {
51+
return 'grid-rows-12';
52+
} else return classes[max - 1 || 1];
4153
};
4254
</script>
4355

44-
<div class="p-5 rounded-md bg-surface-50 dark:bg-surface-800 border-primary-500 border-2">
56+
<div class="p-5 rounded-md max-w-6xl bg-surface-50 dark:bg-surface-800 border-primary-500 border-2">
4557
<!-- Header -->
4658
<h2 class="text-xl font-semibold">{group.displayName}</h2>
4759

4860
<!-- Items -->
4961
<div
50-
class="grid {gridClass(
62+
class="{gridClass(
5163
Object.keys(selected)
52-
)} !gap-x-20 gap-y-2 py-10 px-2 max-h-[1000px] overflow-x-auto max-w-6xl"
64+
)} grid grid-flow-col gap-x-10 gap-y-2 py-10 px-2 h-full overflow-x-auto"
5365
>
5466
{#each Object.keys(selected) as key}
55-
<label class="flex gap-3 items-center">
67+
<label class="flex gap-3 items-center w-48">
5668
<input type="checkbox" class="checkbox" bind:checked={selected[key].selected} />
57-
<span class="whitespace-nowrap break-before-avoid break-after-avoid"
69+
<span
70+
title={selected[key].displayName}
71+
class="whitespace-nowrap break-before-avoid break-after-avoid truncate"
5872
>{selected[key].displayName}</span
5973
>
6074
</label>
@@ -68,7 +82,7 @@
6882
<button class="btn btn-sm variant-filled-tertiary" on:click={selectAll}>All</button>
6983
</div>
7084
<div class="flex gap-3">
71-
<button class="btn btn-sm variant-filled-primary" on:click={onSave}>Save</button>
85+
<button class="btn btn-sm variant-filled-primary" on:click={onApply}>Apply</button>
7286
<button class="btn btn-sm variant-filled-secondary" on:click={onCancel}>Cancel</button>
7387
</div>
7488
</div>

src/lib/components/Table/ColumnsMenu.svelte

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
<button
1616
type="button"
1717
class="btn btn-sm variant-filled-primary rounded-full order-last"
18+
aria-label="Open menu to hide/show columns"
1819
use:popup={popupCombobox}>Columns</button
1920
>
2021

@@ -25,6 +26,7 @@
2526
{#each columns as column}
2627
<div class="flex gap-3 items-center">
2728
<input
29+
aria-label="Toggle column visibility for column {column.label}"
2830
type="checkbox"
2931
bind:checked={column.visible}
3032
disabled={columns.filter((c) => c.visible).length === 1 && column.visible}

src/lib/components/Table/TableContent.svelte

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -165,9 +165,9 @@
165165
header: header ?? key,
166166
accessor: accessor,
167167
// Render the cell with the provided component, or use the toStringFn if provided, or just use the value
168-
cell: ({ value, row }) => {
168+
cell: ({ value, row, column }) => {
169169
return renderComponent
170-
? createRender(renderComponent, { value, row, dispatchFn: actionDispatcher })
170+
? createRender(renderComponent, { value, row, column, dispatchFn: actionDispatcher })
171171
: toStringFn
172172
? toStringFn(value)
173173
: value;
@@ -394,7 +394,7 @@
394394
} else {
395395
sendModel.q = searchValue;
396396
}
397-
397+
398398
$filterValue = searchValue;
399399
}}
400400
>
@@ -409,6 +409,7 @@
409409
type="reset"
410410
id="{tableId}-searchReset"
411411
class="absolute right-3 items-center"
412+
aria-label="Clear search"
412413
on:click|preventDefault={() => {
413414
if (serverSide && !sendModel) {
414415
throw new Error('Server-side configuration is missing');

src/lib/components/Table/TableFilter.svelte

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@
240240
type="button"
241241
use:popup={popupFeatured}
242242
id="{popupId}-button"
243+
aria-label="Open filter menu for column {id}"
243244
>
244245
<Fa icon={faFilter} size="12" />
245246
</button>
@@ -249,6 +250,7 @@
249250
<button
250251
class="btn variant-filled-primary btn-sm"
251252
type="button"
253+
aria-label="Clear Filters"
252254
on:click|preventDefault={() => {
253255
// Set the defaults when cleared
254256
clearFilters();
@@ -273,6 +275,7 @@
273275
{#each options[type] as option (option)}
274276
<option
275277
value={option.value}
278+
aria-label={option.label}
276279
selected={dropdown.option === option.value}
277280
disabled={Object.keys($filters[id]).includes(option.value) &&
278281
dropdown.option !== option.value}>{option.label}</option
@@ -282,6 +285,7 @@
282285
{#if dropdowns.length > 1}
283286
<div
284287
class="btn variant-filled-warning btn-sm h-full"
288+
aria-label="Remove filter"
285289
on:click|preventDefault={() => removeFilter(dropdown.option)}
286290
on:keydown|preventDefault={() => removeFilter(dropdown.option)}
287291
>
@@ -296,13 +300,15 @@
296300
class="input p-1 border border-primary-500"
297301
on:input={(e) => valueChangeHandler(e, index)}
298302
bind:value={dropdown.value}
303+
aria-label="Filter value"
299304
/>
300305
{:else}
301306
<input
302307
type="date"
303308
class="input p-1 border border-primary-500"
304309
on:input={(e) => valueChangeHandler(e, index)}
305310
bind:value={dropdown.formValue}
311+
aria-label="Filter value"
306312
/>
307313
{/if}
308314
</div>
@@ -321,13 +327,15 @@
321327
on:keydown|stopPropagation={() => {
322328
addFilter(remainingFilters[0].value, undefined);
323329
}}
330+
aria-label="Add filter"
324331
>
325332
<div class="flex gap-1 items-center"><Fa icon={faPlus} />Add Filter</div>
326333
</div>
327334
{/if}
328335
<button
329336
class="btn variant-filled-primary btn-sm"
330337
type="button"
338+
aria-label="Apply filters"
331339
on:click|preventDefault={() => {
332340
$pageIndex = 0;
333341
$filterValue = $filters[id];

src/lib/components/Table/TableFilterServer.svelte

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@
233233
type="button"
234234
use:popup={popupFeatured}
235235
id="{popupId}-button"
236+
aria-label="Open filter menu for column {id}"
236237
>
237238
<Fa icon={faFilter} size="12" />
238239
</button>
@@ -242,6 +243,7 @@
242243
<button
243244
class="btn variant-filled-primary btn-sm"
244245
type="button"
246+
aria-label="Clear Filters"
245247
on:click|preventDefault={() => {
246248
// Set the defaults when cleared
247249
clearFilters();
@@ -264,6 +266,7 @@
264266
{#each options[type] as option (option)}
265267
<option
266268
value={option.value}
269+
aria-label={option.label}
267270
selected={dropdown.option === option.value}
268271
disabled={Object.keys($filters[id]).includes(option.value) &&
269272
dropdown.option !== option.value}>{option.label}</option
@@ -275,7 +278,8 @@
275278
class="btn variant-filled-warning btn-sm h-full"
276279
on:click|preventDefault={() => removeFilter(dropdown.option)}
277280
on:keydown|preventDefault={() => removeFilter(dropdown.option)}
278-
>
281+
aria-label="Remove filter"
282+
>
279283
<Fa icon={faXmark} />
280284
</div>
281285
{/if}
@@ -294,13 +298,15 @@
294298
class="input p-1 border border-primary-500"
295299
on:input={(e) => valueChangeHandler(e, index)}
296300
bind:value={dropdown.value}
301+
aria-label="Filter value"
297302
/>
298303
{:else}
299304
<input
300305
type="date"
301306
class="input p-1 border border-primary-500"
302307
on:input={(e) => valueChangeHandler(e, index)}
303308
bind:value={dropdown.value}
309+
aria-label="Filter value"
304310
/>
305311
{/if}
306312
</div>
@@ -313,6 +319,7 @@
313319
{#if remainingFilters.length}
314320
<div
315321
class="btn variant-filled-secondary btn-sm cursor-pointer"
322+
aria-label="Add filter"
316323
on:click|stopPropagation={() => {
317324
addFilter(remainingFilters[0].value, undefined);
318325
}}
@@ -326,6 +333,7 @@
326333
<button
327334
class="btn variant-filled-primary btn-sm"
328335
type="button"
336+
aria-label="Apply filters"
329337
on:click|preventDefault={applyFilters}>Apply</button
330338
>
331339
</div>

0 commit comments

Comments
 (0)