feat: support selecting by columns in table

This commit is contained in:
Ruben Fiszel
2024-06-05 19:57:54 +02:00
parent 4cefe0e886
commit b77042a310
2 changed files with 54 additions and 9 deletions
@@ -92,6 +92,7 @@
$: slicedData = data.slice((currentPage - 1) * perPage, currentPage * perPage)
let selection = [] as Array<number>
let colSelection = [] as Array<string>
// Function to handle individual row checkbox change
function handleCheckboxChange(rowId: number) {
@@ -106,14 +107,19 @@
// Function to handle select all checkbox change
function handleSelectAllChange() {
if (selection.length === 0 || selection.length < slicedData.length) {
if (
selection.length === 0 ||
(selection.length < slicedData.length &&
(colSelection.length === 0 || colSelection.length < headers.length))
) {
// Select all rows
selection = slicedData.map((row) => row._id)
colSelection = [...headers]
} else {
// Deselect all rows
selection = []
colSelection = []
}
selection = [...selection]
}
let renderCount = 0
@@ -134,6 +140,16 @@
// let typof = typeof value
// return (value != undefined && typof === 'string') || typof === 'number' || typof === 'boolean'
// }
function handleColumnSelected(key: string) {
if (colSelection.includes(key)) {
// Remove the id from the colSelection array
colSelection = colSelection.filter((id) => id !== key)
} else {
// Add the id to the colSelection array
colSelection = [...colSelection, key]
}
}
</script>
<DarkModeObserver bind:darkMode />
@@ -156,11 +172,27 @@
selection.length > 0
? structuredObjects
.filter(({ _id }) => selection.includes(_id))
.map((obj) => obj.rowData)
: objects
.map((obj) =>
colSelection.length == 0
? obj.rowData
: Object.fromEntries(
Object.entries(obj.rowData).filter(([key, _]) =>
colSelection.includes(key)
)
)
)
: colSelection.length == 0
? objects
: objects.map((obj) =>
Object.fromEntries(
Object.entries(obj).filter(([key, _]) => colSelection.includes(key))
)
)
)
}}
customText={selection.length > 0 ? 'Download selected as CSV' : undefined}
customText={selection.length > 0 || colSelection.length > 0
? 'Download selected as CSV'
: undefined}
/>
<Dropdown
items={() => {
@@ -190,6 +222,7 @@
displayName: 'Clear selection',
icon: Columns,
action: () => {
colSelection = []
selection = []
renderCount++
}
@@ -273,6 +306,12 @@
<MoveVertical size="16" class=" hover:text-gray-600 text-gray-400" />
</button>
{/if}
<input
type="checkbox"
class="!w-4 !h-4"
checked={colSelection.includes(key)}
on:change={() => handleColumnSelected(key)}
/>
</div>
</Cell>
{/each}
@@ -280,7 +319,7 @@
</Head>
<tbody class="divide-y">
{#each slicedData as { _id, rowData }, index (index)}
<Row dividable selected={selection.includes(_id)}>
<Row dividable selected={selection.includes(_id) && colSelection.length == 0}>
<Cell first={true} last={false} class="w-6">
<input
type="checkbox"
@@ -291,7 +330,11 @@
</Cell>
{#each headers as key, index}
{@const value = rowData[key]}
<Cell last={index == Object.values(rowData ?? {}).length - 1}>
<Cell
selected={colSelection.includes(key) &&
(selection.length == 0 || selection.includes(_id))}
last={index == Object.values(rowData ?? {}).length - 1}
>
{#if Array.isArray(value) && value.length === 0}
<div />
{:else if Array.isArray(value) && typeof value?.[0] === 'string'}
@@ -8,7 +8,7 @@
export let numeric: boolean = false
export let head: boolean = false
export let shouldStopPropagation: boolean = false
export let selected = false
export let sticky: boolean = false
let Tag = head ? 'th' : 'td'
@@ -37,7 +37,9 @@
sticky ? `!p-0 sticky ${first ? 'left-0' : 'right-0'}` : 'px-2 py-3.5',
size === 'sm' ? 'px-1.5 py-2.5' : '',
size === 'lg' ? 'px-3 py-4' : '',
size === 'xs' ? 'px-1 py-1.5' : ''
size === 'xs' ? 'px-1 py-1.5' : '',
selected ? 'bg-blue-50 dark:bg-blue-900/50' : '',
'transition-all'
)}
>
{#if sticky}