256 lines
8.4 KiB
Vue
256 lines
8.4 KiB
Vue
<template>
|
|
<div class="flex items-center gap-2">
|
|
<!-- Global Task Columns Toggle Button -->
|
|
<Button
|
|
variant="outline"
|
|
size="sm"
|
|
@click="toggleAllTaskColumns"
|
|
class="h-9"
|
|
>
|
|
<ListTodo v-if="!allTaskColumnsVisible" class="h-4 w-4 mr-2" />
|
|
<ListX v-else class="h-4 w-4 mr-2" />
|
|
{{ allTaskColumnsVisible ? 'Hide' : 'Show' }} Tasks
|
|
</Button>
|
|
|
|
<!-- Column Visibility Dropdown -->
|
|
<Select v-model="selectedColumn" @update:model-value="handleColumnToggle">
|
|
<SelectTrigger class="w-[180px]">
|
|
<SelectValue placeholder="Toggle columns">
|
|
<div class="flex items-center gap-2">
|
|
<Columns class="h-4 w-4" />
|
|
<span>Columns</span>
|
|
</div>
|
|
</SelectValue>
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
<SelectItem value="toggle">Toggle Columns</SelectItem>
|
|
<SelectGroup>
|
|
<SelectLabel>Basic Columns</SelectLabel>
|
|
<SelectItem value="thumbnail" @click.stop>
|
|
<div class="flex items-center gap-2">
|
|
<Checkbox
|
|
v-model="visibleColumns.thumbnail"
|
|
@update:checked="(val: boolean | 'indeterminate') => updateColumn('thumbnail', val)"
|
|
/>
|
|
<span>Thumbnail</span>
|
|
</div>
|
|
</SelectItem>
|
|
<SelectItem value="name" @click.stop>
|
|
<div class="flex items-center gap-2">
|
|
<Checkbox
|
|
v-model="visibleColumns.name"
|
|
@update:checked="(val: boolean | 'indeterminate') => updateColumn('name', val)"
|
|
/>
|
|
<span>Name</span>
|
|
</div>
|
|
</SelectItem>
|
|
<SelectItem value="category" @click.stop>
|
|
<div class="flex items-center gap-2">
|
|
<Checkbox
|
|
v-model="visibleColumns.category"
|
|
@update:checked="(val: boolean | 'indeterminate') => updateColumn('category', val)"
|
|
/>
|
|
<span>Category</span>
|
|
</div>
|
|
</SelectItem>
|
|
<SelectItem value="status" @click.stop>
|
|
<div class="flex items-center gap-2">
|
|
<Checkbox
|
|
v-model="visibleColumns.status"
|
|
@update:checked="(val: boolean | 'indeterminate') => updateColumn('status', val)"
|
|
/>
|
|
<span>Status</span>
|
|
</div>
|
|
</SelectItem>
|
|
</SelectGroup>
|
|
<SelectGroup>
|
|
<SelectLabel>Task Status Columns</SelectLabel>
|
|
<!-- Standard Task Types -->
|
|
<SelectItem value="modeling" @click.stop>
|
|
<div class="flex items-center gap-2">
|
|
<Checkbox
|
|
v-model="visibleColumns.modeling"
|
|
@update:checked="(val: boolean | 'indeterminate') => updateColumn('modeling', val)"
|
|
/>
|
|
<span>Modeling</span>
|
|
</div>
|
|
</SelectItem>
|
|
<SelectItem value="surfacing" @click.stop>
|
|
<div class="flex items-center gap-2">
|
|
<Checkbox
|
|
v-model="visibleColumns.surfacing"
|
|
@update:checked="(val: boolean | 'indeterminate') => updateColumn('surfacing', val)"
|
|
/>
|
|
<span>Surfacing</span>
|
|
</div>
|
|
</SelectItem>
|
|
<SelectItem value="rigging" @click.stop>
|
|
<div class="flex items-center gap-2">
|
|
<Checkbox
|
|
v-model="visibleColumns.rigging"
|
|
@update:checked="(val: boolean | 'indeterminate') => updateColumn('rigging', val)"
|
|
/>
|
|
<span>Rigging</span>
|
|
</div>
|
|
</SelectItem>
|
|
<!-- Custom Task Types -->
|
|
<SelectItem
|
|
v-for="customType in customTaskTypes"
|
|
:key="customType"
|
|
:value="customType"
|
|
@click.stop
|
|
>
|
|
<div class="flex items-center gap-2">
|
|
<Checkbox
|
|
v-model="visibleColumns[customType]"
|
|
@update:checked="(val: boolean | 'indeterminate') => updateColumn(customType, val)"
|
|
/>
|
|
<span>{{ formatTaskType(customType) }}</span>
|
|
</div>
|
|
</SelectItem>
|
|
</SelectGroup>
|
|
<SelectGroup>
|
|
<SelectLabel>Other Columns</SelectLabel>
|
|
<SelectItem value="description" @click.stop>
|
|
<div class="flex items-center gap-2">
|
|
<Checkbox
|
|
v-model="visibleColumns.description"
|
|
@update:checked="(val: boolean | 'indeterminate') => updateColumn('description', val)"
|
|
/>
|
|
<span>Description</span>
|
|
</div>
|
|
</SelectItem>
|
|
<SelectItem value="updatedAt" @click.stop>
|
|
<div class="flex items-center gap-2">
|
|
<Checkbox
|
|
v-model="visibleColumns.updatedAt"
|
|
@update:checked="(val: boolean | 'indeterminate') => updateColumn('updatedAt', val)"
|
|
/>
|
|
<span>Updated</span>
|
|
</div>
|
|
</SelectItem>
|
|
</SelectGroup>
|
|
</SelectContent>
|
|
</Select>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, computed, onMounted } from 'vue'
|
|
import { Columns, ListTodo, ListX } from 'lucide-vue-next'
|
|
import { Button } from '@/components/ui/button'
|
|
import { Checkbox } from '@/components/ui/checkbox'
|
|
import {
|
|
Select,
|
|
SelectContent,
|
|
SelectGroup,
|
|
SelectItem,
|
|
SelectLabel,
|
|
SelectTrigger,
|
|
SelectValue,
|
|
} from '@/components/ui/select'
|
|
|
|
interface Props {
|
|
visibleColumns: Record<string, boolean>;
|
|
projectId?: number;
|
|
}
|
|
|
|
interface Emits {
|
|
(e: "update:visibleColumns", columns: Record<string, boolean>): void;
|
|
}
|
|
|
|
const props = defineProps<Props>();
|
|
const emit = defineEmits<Emits>();
|
|
|
|
const selectedColumn = ref('toggle')
|
|
const customTaskTypes = ref<string[]>([])
|
|
const savedTaskColumnStates = ref<Record<string, boolean>>({})
|
|
|
|
// Standard task types
|
|
const standardTaskTypes = ['modeling', 'surfacing', 'rigging']
|
|
|
|
// All task types (standard + custom)
|
|
const allTaskTypes = computed(() => [...standardTaskTypes, ...customTaskTypes.value])
|
|
|
|
// Check if all task columns are visible
|
|
const allTaskColumnsVisible = computed(() => {
|
|
return allTaskTypes.value.every(taskType => props.visibleColumns[taskType])
|
|
})
|
|
|
|
// Load custom task types from project
|
|
const loadCustomTaskTypes = async () => {
|
|
if (!props.projectId) return
|
|
|
|
try {
|
|
const { projectService } = await import('@/services/project')
|
|
const project = await projectService.getProject(props.projectId)
|
|
customTaskTypes.value = project.custom_asset_task_types || []
|
|
|
|
// Initialize visibility for custom task types if not already set
|
|
const newColumns = { ...props.visibleColumns }
|
|
let hasChanges = false
|
|
|
|
for (const customType of customTaskTypes.value) {
|
|
if (!(customType in newColumns)) {
|
|
newColumns[customType] = true // Show custom types by default
|
|
hasChanges = true
|
|
}
|
|
}
|
|
|
|
if (hasChanges) {
|
|
emit("update:visibleColumns", newColumns)
|
|
}
|
|
} catch (error) {
|
|
console.warn('Could not load custom task types:', error)
|
|
// Continue without custom task types
|
|
}
|
|
}
|
|
|
|
// Toggle all task columns show/hide
|
|
const toggleAllTaskColumns = () => {
|
|
const newColumns = { ...props.visibleColumns }
|
|
|
|
if (allTaskColumnsVisible.value) {
|
|
// Hide all task columns but save their states
|
|
savedTaskColumnStates.value = {}
|
|
for (const taskType of allTaskTypes.value) {
|
|
savedTaskColumnStates.value[taskType] = newColumns[taskType]
|
|
newColumns[taskType] = false
|
|
}
|
|
} else {
|
|
// Restore saved states or show all
|
|
for (const taskType of allTaskTypes.value) {
|
|
if (taskType in savedTaskColumnStates.value) {
|
|
newColumns[taskType] = savedTaskColumnStates.value[taskType]
|
|
} else {
|
|
newColumns[taskType] = true
|
|
}
|
|
}
|
|
savedTaskColumnStates.value = {}
|
|
}
|
|
|
|
emit("update:visibleColumns", newColumns)
|
|
}
|
|
|
|
const handleColumnToggle = () => {
|
|
// Reset selection after interaction
|
|
selectedColumn.value = 'toggle'
|
|
}
|
|
|
|
const updateColumn = (column: string, checked: boolean | 'indeterminate') => {
|
|
const newColumns = { ...props.visibleColumns }
|
|
newColumns[column] = checked === true
|
|
emit('update:visibleColumns', newColumns)
|
|
}
|
|
|
|
const formatTaskType = (taskType: string) => {
|
|
return taskType
|
|
.split('_')
|
|
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
|
|
.join(' ')
|
|
}
|
|
|
|
onMounted(() => {
|
|
loadCustomTaskTypes()
|
|
})
|
|
</script> |