command/meta multi select

This commit is contained in:
Diego Imbert
2026-02-05 18:00:54 +01:00
parent 5eac04e3de
commit 33a03f48e6
3 changed files with 69 additions and 42 deletions
+7 -22
View File
@@ -37,7 +37,6 @@
containsLabel?: boolean
showTag?: boolean
activeLabel: string | null
selectionMode?: boolean
}
let {
@@ -46,8 +45,7 @@
containerWidth = 0,
containsLabel = false,
showTag = true,
activeLabel,
selectionMode = false
activeLabel
}: Props = $props()
let scheduleEditor: ScheduleEditor | undefined = $state(undefined)
@@ -66,32 +64,19 @@
<!-- svelte-ignore a11y_no_static_element_interactions -->
<div
class={twMerge(
'hover:bg-surface-hover cursor-pointer',
selected ? 'bg-surface-accent-selected' : '',
'cursor-pointer',
selected ? 'bg-surface-accent-selected' : 'hover:bg-surface-hover',
'grid items-center h-full'
)}
class:grid-runs-table={!containsLabel && !selectionMode && showTag}
class:grid-runs-table-with-labels={containsLabel && !selectionMode && showTag}
class:grid-runs-table-selection={!containsLabel && selectionMode && showTag}
class:grid-runs-table-with-labels-selection={containsLabel && selectionMode && showTag}
class:grid-runs-table-no-tag={!containsLabel && !selectionMode && !showTag}
class:grid-runs-table-with-labels-no-tag={containsLabel && !selectionMode && !showTag}
class:grid-runs-table-selection-no-tag={!containsLabel && selectionMode && !showTag}
class:grid-runs-table-with-labels-selection-no-tag={containsLabel && selectionMode && !showTag}
class:grid-runs-table={!containsLabel && showTag}
class:grid-runs-table-with-labels={containsLabel && showTag}
class:grid-runs-table-no-tag={!containsLabel && !showTag}
class:grid-runs-table-with-labels-no-tag={containsLabel && !showTag}
style="width: {containerWidth}px"
onclick={() => {
dispatch('select')
}}
>
<!-- Selection column (only when in selection mode) -->
{#if selectionMode}
<div class="flex items-center justify-center">
<div class="w-4 h-4">
<input type="checkbox" checked={selected} />
</div>
</div>
{/if}
<!-- Status -->
<div class="flex items-center justify-start pl-4">
<JobStatusIcon {job} {isExternal} />
@@ -8,6 +8,7 @@
import Popover from '../Popover.svelte'
import { workspaceStore } from '$lib/stores'
import './runs-grid.css'
import { useKeyboardModifiers } from '$lib/svelte5Utils.svelte'
interface Props {
//import InfiniteLoading from 'svelte-infinite-loading'
@@ -15,13 +16,13 @@
externalJobs?: Job[]
omittedObscuredJobs: boolean
showExternalJobs?: boolean
selectionMode?: boolean
selectedIds?: string[]
selectedWorkspace?: string | undefined
activeLabel?: string | null
// const loadMoreQuantity: number = 100
lastFetchWentToEnd?: boolean
perPage?: number
allSelected?: boolean
}
let {
@@ -29,14 +30,16 @@
externalJobs = [],
omittedObscuredJobs,
showExternalJobs = false,
selectionMode = false,
selectedIds = $bindable([]),
selectedWorkspace = $bindable(undefined),
activeLabel = null,
lastFetchWentToEnd = false,
perPage = 1000
perPage = 1000,
allSelected = $bindable()
}: Props = $props()
const keyboardModifiers = useKeyboardModifiers()
function getTime(job: Job): string | undefined {
return job['completed_at'] ?? job['started_at'] ?? job['scheduled_for'] ?? job['created_at']
}
@@ -196,20 +199,11 @@
<div>
<div
class="grid sticky top-0 w-full min-h-6 my-2 pr-4 items-end"
class:grid-runs-table={!containsLabel && !selectionMode && showTag}
class:grid-runs-table-with-labels={containsLabel && !selectionMode && showTag}
class:grid-runs-table-selection={!containsLabel && selectionMode && showTag}
class:grid-runs-table-with-labels-selection={containsLabel && selectionMode && showTag}
class:grid-runs-table-no-tag={!containsLabel && !selectionMode && !showTag}
class:grid-runs-table-with-labels-no-tag={containsLabel && !selectionMode && !showTag}
class:grid-runs-table-selection-no-tag={!containsLabel && selectionMode && !showTag}
class:grid-runs-table-with-labels-selection-no-tag={containsLabel &&
selectionMode &&
!showTag}
class:grid-runs-table={!containsLabel && showTag}
class:grid-runs-table-with-labels={containsLabel && showTag}
class:grid-runs-table-no-tag={!containsLabel && !showTag}
class:grid-runs-table-with-labels-no-tag={containsLabel && !showTag}
>
{#if selectionMode}
<div class="text-xs font-semibold pl-4"></div>
{/if}
<div class="text-2xs px-4 flex flex-row items-center gap-2 leading-3">
{#if showExternalJobs && externalJobs.length > 0}
<div class="flex flex-row">
@@ -276,16 +270,15 @@
{jobOrDate.date}
</div>
{:else}
<div class="flex flex-row items-center h-full w-full">
<div class="flex flex-row items-center h-full w-full select-none">
<RunRow
{containsLabel}
{showTag}
job={jobOrDate.job}
selected={jobOrDate.job.id !== '-' && selectedIds.includes(jobOrDate.job.id)}
{selectionMode}
on:select={() => {
on:select={(e) => {
const jobId = jobOrDate.job.id
if (selectionMode) {
if (keyboardModifiers.control || keyboardModifiers.meta) {
if (selectedIds.includes(jobOrDate.job.id)) {
selectedIds = selectedIds.filter((id) => id != jobId)
} else {
+49
View File
@@ -415,3 +415,52 @@ export function useInfiniteQuery<TData, TPageParam = number>(
reset
}
}
export function useKeyboardModifiers(): {
shift: boolean
control: boolean
meta: boolean
command: boolean
} {
if (typeof window === 'undefined')
return { shift: false, control: false, meta: false, command: false }
let _shift = $state(false)
let control = $state(false)
let meta = $state(false)
let command = $state(false)
$effect(() => {
const handleKeyDown = (event: KeyboardEvent) => {
if (event.key === 'Shift') _shift = true
else if (event.key === 'Control') control = true
else if (event.key === 'Meta') meta = true
else if (event.key === 'Command') command = true
}
const handleKeyUp = (event: KeyboardEvent) => {
if (event.key === 'Shift') _shift = false
else if (event.key === 'Control') control = false
else if (event.key === 'Meta') meta = false
else if (event.key === 'Command') command = false
}
window.addEventListener('keydown', handleKeyDown)
window.addEventListener('keyup', handleKeyUp)
return () => {
window.removeEventListener('keydown', handleKeyDown)
window.removeEventListener('keyup', handleKeyUp)
}
})
return {
get shift() {
return _shift
},
get control() {
return control
},
get meta() {
return meta
},
get command() {
return command
}
}
}