Init Repo
This commit is contained in:
@@ -0,0 +1,136 @@
|
||||
# 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:**
|
||||
```typescript
|
||||
const selectedShots = ref<number[]>([]);
|
||||
```
|
||||
|
||||
**After:**
|
||||
```typescript
|
||||
const selectedShots = ref<Record<number, boolean>>({});
|
||||
```
|
||||
|
||||
### 2. Select All Checkbox
|
||||
**Before:**
|
||||
```vue
|
||||
<Checkbox
|
||||
:checked="selectedShots.length === filteredShots.length && filteredShots.length > 0"
|
||||
:indeterminate="selectedShots.length > 0 && selectedShots.length < filteredShots.length"
|
||||
@update:checked="toggleSelectAll"
|
||||
/>
|
||||
```
|
||||
|
||||
**After:**
|
||||
```vue
|
||||
<Checkbox v-model="selectAllChecked" />
|
||||
```
|
||||
|
||||
With computed property:
|
||||
```typescript
|
||||
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:**
|
||||
```vue
|
||||
<Checkbox
|
||||
:checked="selectedShots.includes(shot.id)"
|
||||
@update:checked="(checked) => toggleShotSelection(shot.id, checked)"
|
||||
@click.stop
|
||||
/>
|
||||
```
|
||||
|
||||
**After:**
|
||||
```vue
|
||||
<Checkbox
|
||||
v-model="selectedShots[shot.id]"
|
||||
@click.stop
|
||||
/>
|
||||
```
|
||||
|
||||
### 4. Helper Method
|
||||
Added helper to get selected IDs:
|
||||
```typescript
|
||||
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:
|
||||
```typescript
|
||||
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:**
|
||||
```typescript
|
||||
watch(() => props.shots, () => {
|
||||
selectedShots.value = []
|
||||
})
|
||||
```
|
||||
|
||||
**After:**
|
||||
```typescript
|
||||
watch(() => props.shots, () => {
|
||||
selectedShots.value = {}
|
||||
})
|
||||
```
|
||||
|
||||
## Benefits
|
||||
|
||||
1. **Consistent with AssetBrowser**: Both components now use the same pattern
|
||||
2. **Direct v-model Binding**: Uses reka-ui's native v-model support
|
||||
3. **Better Performance**: Object property access is faster than array operations
|
||||
4. **Cleaner Code**: No manual event handlers needed
|
||||
5. **Fully Reactive**: Vue's reactivity handles everything automatically
|
||||
|
||||
## Testing
|
||||
|
||||
Test the following scenarios:
|
||||
1. Click individual checkboxes to select/deselect shots
|
||||
2. Click the "Select All" checkbox to select/deselect all shots
|
||||
3. Use Ctrl/Cmd+Click for multi-selection
|
||||
4. Use Shift+Click for range selection
|
||||
5. Verify the selection state persists correctly
|
||||
6. Verify the row highlighting reflects the selection state
|
||||
|
||||
## Related Files
|
||||
|
||||
- `frontend/src/components/shot/ShotsTableView.vue` - Updated component
|
||||
- `frontend/docs/checkbox-selection-refactor.md` - Original AssetBrowser refactor documentation
|
||||
Reference in New Issue
Block a user