3.4 KiB
3.4 KiB
Shot Table Checkbox Selection Fix
Overview
Applied the same checkbox selection refactor to ShotsTableView component that was done for AssetBrowser, converting from array-based to object-based selection state.
Changes Made
1. Selection State Structure
Before:
const selectedShots = ref<number[]>([]);
After:
const selectedShots = ref<Record<number, boolean>>({});
2. Select All Checkbox
Before:
<Checkbox
:checked="selectedShots.length === filteredShots.length && filteredShots.length > 0"
:indeterminate="selectedShots.length > 0 && selectedShots.length < filteredShots.length"
@update:checked="toggleSelectAll"
/>
After:
<Checkbox v-model="selectAllChecked" />
With computed property:
const selectAllChecked = computed({
get: () => {
return filteredShots.value.length > 0 &&
filteredShots.value.every(shot => selectedShots.value[shot.id]);
},
set: (checked: boolean) => {
filteredShots.value.forEach(shot => {
selectedShots.value[shot.id] = checked;
});
}
});
3. Row Checkboxes
Before:
<Checkbox
:checked="selectedShots.includes(shot.id)"
@update:checked="(checked) => toggleShotSelection(shot.id, checked)"
@click.stop
/>
After:
<Checkbox
v-model="selectedShots[shot.id]"
@click.stop
/>
4. Helper Method
Added helper to get selected IDs:
const getSelectedShotIds = () => {
return Object.keys(selectedShots.value)
.filter(id => selectedShots.value[Number(id)])
.map(id => Number(id));
};
5. Row Selection Logic
Updated to work with object-based state:
const handleRowClick = (shot: Shot, event: MouseEvent) => {
if (event.ctrlKey || event.metaKey) {
// Multi-select with Ctrl/Cmd - toggle selection
selectedShots.value[shot.id] = !selectedShots.value[shot.id];
} else if (event.shiftKey && getSelectedShotIds().length > 0) {
// Range select with Shift
const selectedIds = getSelectedShotIds();
const lastSelectedId = selectedIds[selectedIds.length - 1];
// ... range selection logic
selectedShots.value = {};
for (let i = start; i <= end; i++) {
selectedShots.value[filteredShots.value[i].id] = true;
}
} else {
// Single select
emit('select', shot);
}
};
6. Watcher Update
Before:
watch(() => props.shots, () => {
selectedShots.value = []
})
After:
watch(() => props.shots, () => {
selectedShots.value = {}
})
Benefits
- Consistent with AssetBrowser: Both components now use the same pattern
- Direct v-model Binding: Uses reka-ui's native v-model support
- Better Performance: Object property access is faster than array operations
- Cleaner Code: No manual event handlers needed
- Fully Reactive: Vue's reactivity handles everything automatically
Testing
Test the following scenarios:
- Click individual checkboxes to select/deselect shots
- Click the "Select All" checkbox to select/deselect all shots
- Use Ctrl/Cmd+Click for multi-selection
- Use Shift+Click for range selection
- Verify the selection state persists correctly
- Verify the row highlighting reflects the selection state
Related Files
frontend/src/components/shot/ShotsTableView.vue- Updated componentfrontend/docs/checkbox-selection-refactor.md- Original AssetBrowser refactor documentation