Offer department-owned task types in the shot/asset Add Task dropdowns
ShotDetailPanel and AssetDetailPanel now merge department task types (filtered to shot/asset departments respectively) into the flat task type list shown in "Add Task", so types like Animation's blocking or Composite's first_pass are selectable at creation time instead of only via editing a task's type afterward. No backend change needed since task creation already derives department from an owned task type.
This commit is contained in:
@@ -293,6 +293,7 @@ import { assetService, AssetStatus, type Asset, type TaskStatusInfo } from '@/se
|
||||
import { taskService, type ProductionNote, type Submission } from '@/services/task'
|
||||
import { useAuthStore } from '@/stores/auth'
|
||||
import { useUserStore } from '@/stores/user'
|
||||
import { useDepartmentsStore } from '@/stores/departments'
|
||||
|
||||
interface Task {
|
||||
id: number
|
||||
@@ -321,6 +322,7 @@ const emit = defineEmits<Emits>()
|
||||
|
||||
const authStore = useAuthStore()
|
||||
const userStore = useUserStore()
|
||||
const departmentsStore = useDepartmentsStore()
|
||||
|
||||
// Reactive state
|
||||
const asset = ref<Asset | null>(null)
|
||||
@@ -363,9 +365,15 @@ const progressPercentage = computed(() => {
|
||||
return Math.round((completedTasksCount.value / tasks.value.length) * 100)
|
||||
})
|
||||
|
||||
// Task types offered in "Add Task" include the flat asset task type list
|
||||
// plus every task type owned by an asset department (e.g. Modeling's own
|
||||
// task types), deduped against types the asset already has a task for.
|
||||
const availableTaskTypes = computed(() => {
|
||||
const existingTypes = new Set(tasks.value.map(task => task.task_type))
|
||||
return props.allTaskTypes.filter(type => !existingTypes.has(type))
|
||||
const departmentTaskTypes = departmentsStore.getDepartmentsByType(props.projectId, 'asset')
|
||||
.flatMap(d => d.task_types)
|
||||
const merged = Array.from(new Set([...props.allTaskTypes, ...departmentTaskTypes]))
|
||||
return merged.filter(type => !existingTypes.has(type))
|
||||
})
|
||||
|
||||
const taskStatusCounts = computed(() => {
|
||||
@@ -394,7 +402,8 @@ const loadAssetDetails = async () => {
|
||||
isLoading.value = true
|
||||
error.value = null
|
||||
asset.value = await assetService.getAsset(props.assetId)
|
||||
|
||||
departmentsStore.fetchProjectDepartments(props.projectId)
|
||||
|
||||
// Load users if not already loaded (for user name resolution)
|
||||
if (userStore.users.length === 0) {
|
||||
try {
|
||||
|
||||
@@ -341,6 +341,7 @@ import { shotService, type Shot, type TaskStatusInfo } from '@/services/shot'
|
||||
import { taskService, type ProductionNote, type Submission } from '@/services/task'
|
||||
import { projectService, type ProjectMember } from '@/services/project'
|
||||
import { useTaskStatusesStore } from '@/stores/taskStatuses'
|
||||
import { useDepartmentsStore } from '@/stores/departments'
|
||||
import { useAvatarUrl } from '@/composables/useAvatarUrl'
|
||||
import { usePermission } from '@/composables/usePermission'
|
||||
|
||||
@@ -375,6 +376,7 @@ const props = defineProps<Props>()
|
||||
const emit = defineEmits<Emits>()
|
||||
|
||||
const taskStatusesStore = useTaskStatusesStore()
|
||||
const departmentsStore = useDepartmentsStore()
|
||||
const { getAvatarUrl } = useAvatarUrl()
|
||||
const { isAdmin, isCoordinatorOrAdmin } = usePermission()
|
||||
|
||||
@@ -435,9 +437,15 @@ const canUploadReferences = computed(() => {
|
||||
|
||||
const canEditDesign = computed(() => isCoordinatorOrAdmin.value)
|
||||
|
||||
// Task types offered in "Add Task" include the flat shot task type list
|
||||
// plus every task type owned by a shot department (e.g. Animation's own
|
||||
// task types), deduped against types the shot already has a task for.
|
||||
const availableTaskTypes = computed(() => {
|
||||
const existingTypes = new Set(tasks.value.map(task => task.task_type))
|
||||
return props.allTaskTypes.filter(type => !existingTypes.has(type))
|
||||
const departmentTaskTypes = departmentsStore.getDepartmentsByType(props.projectId, 'shot')
|
||||
.flatMap(d => d.task_types)
|
||||
const merged = Array.from(new Set([...props.allTaskTypes, ...departmentTaskTypes]))
|
||||
return merged.filter(type => !existingTypes.has(type))
|
||||
})
|
||||
|
||||
// Methods
|
||||
@@ -446,6 +454,7 @@ const loadShotDetails = async () => {
|
||||
isLoading.value = true
|
||||
error.value = null
|
||||
shot.value = props.initialShot ?? await shotService.getShot(props.shotId)
|
||||
departmentsStore.fetchProjectDepartments(props.projectId)
|
||||
await Promise.all([
|
||||
taskStatusesStore.fetchProjectStatuses(props.projectId),
|
||||
loadProjectMembers()
|
||||
|
||||
Reference in New Issue
Block a user