Add button to sheet and shift selector

This commit is contained in:
Roman Krček
2025-09-07 22:15:03 +02:00
parent 9de5646519
commit dcba02260a

View File

@@ -17,6 +17,7 @@
let sortColumn = $state<keyof RowData | null>(null); let sortColumn = $state<keyof RowData | null>(null);
let sortDirection = $state<'asc' | 'desc'>('asc'); let sortDirection = $state<'asc' | 'desc'>('asc');
let lastCheckedId: string | null = $state(null);
const ROW_LIMIT = 200; const ROW_LIMIT = 200;
@@ -85,20 +86,52 @@
} finally { } finally {
isLoading = false; isLoading = false;
} }
} // Run on component mount }
function handleRowClick(event: MouseEvent, clickedId: string) {
const clickedRow = rows.find((r) => r.id === clickedId);
if (!clickedRow || !clickedRow._valid) return;
// Handle shift-clicking for range selection
if (event.shiftKey && lastCheckedId) {
const lastIndex = displayData.findIndex((r) => r.id === lastCheckedId);
const currentIndex = displayData.findIndex((r) => r.id === clickedId);
if (lastIndex !== -1 && currentIndex !== -1) {
const start = Math.min(lastIndex, currentIndex);
const end = Math.max(lastIndex, currentIndex);
const isChecked = !clickedRow._checked; // The state to apply to the range
for (let i = start; i <= end; i++) {
const rowToSelect = displayData[i];
if (rowToSelect && rowToSelect._valid) {
// Prevent checking more than the limit
if (isChecked && selectedCount >= ROW_LIMIT && !rowToSelect._checked) {
continue;
}
rowToSelect._checked = isChecked;
}
}
}
} else {
// Normal click, just toggle the state
if (!clickedRow._checked && selectedCount >= ROW_LIMIT) {
// Do not allow checking more than the limit
} else {
clickedRow._checked = !clickedRow._checked;
}
}
// Update the last checked ID for the next shift-click
lastCheckedId = clickedId;
}
// Run on component mount
onMount(() => { onMount(() => {
ensureToken(); ensureToken();
fetchAndProcessData(); fetchAndProcessData();
}); });
// Function to toggle a single row's checked state
function toggleRow(id: string) {
const row = rows.find((r) => r.id === id);
if (row && row._valid) {
row._checked = !row._checked;
}
}
// Function to toggle select-all: selects first 200 eligible items in current view // Function to toggle select-all: selects first 200 eligible items in current view
function toggleSelectAll(event: Event) { function toggleSelectAll(event: Event) {
const target = event.target as HTMLInputElement; const target = event.target as HTMLInputElement;
@@ -169,56 +202,62 @@
<div> <div>
<h2 class="mb-2 text-xl font-semibold text-gray-900">Filter and Select Rows</h2> <h2 class="mb-2 text-xl font-semibold text-gray-900">Filter and Select Rows</h2>
<p class="text-sm text-gray-700"> <p class="text-sm text-gray-700">
Review your data and select which rows to include. Select a batch of max 200 items by using the top checkbox. Review your data and select which rows to include. Select a batch of max 200 items by using
the top checkbox.
</p> </p>
<p class="text-sm text-gray-700"> <p class="mt-1 text-sm text-gray-700">
Tip: Hold <kbd
class="rounded-md border border-gray-400 bg-gray-200 px-1.5 py-0.5 text-xs font-semibold"
>Shift</kbd
> and click two checkboxes to select a range of rows.
</p>
<p class="mt-1 text-sm text-gray-700">
Already printed or invalid data is marked in the status column. Already printed or invalid data is marked in the status column.
</p> </p>
{#if $selectedSheet?.id}
<p class="mt-1 text-sm text-gray-500">
Need to make changes?
<a
href={`https://docs.google.com/spreadsheets/d/${$selectedSheet.id}/edit`}
target="_blank"
rel="noopener noreferrer"
class="text-blue-600 underline hover:text-blue-800"
>
Open the spreadsheet
</a>
</p>
{/if}
</div> </div>
<button <div class="flex flex-col space-y-2">
onclick={fetchAndProcessData} {#if $selectedSheet?.id}
class="inline-flex items-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 disabled:cursor-wait disabled:opacity-50" <a
disabled={isLoading} href={`https://docs.google.com/spreadsheets/d/${$selectedSheet.id}/edit`}
> target="_blank"
{#if isLoading} rel="noopener noreferrer"
<svg class="inline-flex items-center justify-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2"
class="-ml-1 mr-2 h-5 w-5 animate-spin text-gray-500"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
> >
<circle Open Sheet
class="opacity-25" </a>
cx="12"
cy="12"
r="10"
stroke="currentColor"
stroke-width="4"
></circle>
<path
class="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
></path>
</svg>
Refreshing...
{:else}
Refresh Data
{/if} {/if}
</button> <button
onclick={fetchAndProcessData}
class="inline-flex items-center justify-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 disabled:cursor-wait disabled:opacity-50"
disabled={isLoading}
>
{#if isLoading}
<svg
class="-ml-1 mr-2 h-5 w-5 animate-spin text-gray-500"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
>
<circle
class="opacity-25"
cx="12"
cy="12"
r="10"
stroke="currentColor"
stroke-width="4"
></circle>
<path
class="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
></path>
</svg>
Refreshing...
{:else}
Refresh Data
{/if}
</button>
</div>
</div> </div>
{#if isLoading} {#if isLoading}
@@ -313,7 +352,7 @@
class="h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-500 disabled:cursor-not-allowed disabled:bg-gray-200" class="h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-500 disabled:cursor-not-allowed disabled:bg-gray-200"
checked={row._checked} checked={row._checked}
disabled={!row._valid || (selectedCount >= ROW_LIMIT && !row._checked)} disabled={!row._valid || (selectedCount >= ROW_LIMIT && !row._checked)}
onchange={() => toggleRow(row.id)} onclick={(e) => handleRowClick(e, row.id)}
/> />
</td> </td>
<td class="whitespace-nowrap px-4 py-3 text-sm">{row._rowIndex}</td> <td class="whitespace-nowrap px-4 py-3 text-sm">{row._rowIndex}</td>