Skip to content
11 changes: 5 additions & 6 deletions src/components/lists/TaskList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -594,7 +594,7 @@ export default {
'addSelectedTasks',
'clearSelectedTasks',
'updateTask',
'unassignPersonFromTask',
'unassignPersonFromTasks',
'removeSelectedTask'
]),

Expand Down Expand Up @@ -633,12 +633,11 @@ export default {
},

onUnassign(task, person) {
if (this.selectedTasks.size > 0) {
this.selectedTasks.forEach(t => {
this.unassignPersonFromTask({ task: t, person })
})
const tasks = Array.from(this.selectedTasks.values())
if (!this.selectedTasks.has(task.id)) {
tasks.push(task)
}
this.unassignPersonFromTask({ task, person })
this.unassignPersonFromTasks({ tasks, person })
},

updateStartDate(date) {
Expand Down
62 changes: 46 additions & 16 deletions src/components/pages/Breakdown.vue
Original file line number Diff line number Diff line change
Expand Up @@ -772,6 +772,7 @@ export default {
'loadSequences',
'saveBreakdownSearchFilterGroup',
'saveCasting',
'saveCastings',
'setAssetLinkLabel',
'setAssetSearch',
'setCastingEpisodes',
Expand Down Expand Up @@ -953,23 +954,24 @@ export default {
key => this.selection[key]
)

for (const entityId of entityIds) {
entityIds.forEach(entityId => {
this.addAssetToCasting({
entityId,
assetId,
nbOccurences: amount,
label: this.castingType === 'shot' ? 'animate' : 'fixed'
})

delete this.saveErrors[entityId]
})

try {
await this.saveCasting(entityId)
this.setLock()
} catch (err) {
try {
await this.saveCastings(entityIds)
this.setLock()
} catch (err) {
entityIds.forEach(entityId => {
this.saveErrors[entityId] = true
console.error(err)
}
})
console.error(err)
}
},

Expand Down Expand Up @@ -1008,14 +1010,39 @@ export default {
const entityIds = Object.keys(this.selection).filter(
key => this.selection[key]
)
const removals = []
for (const entityId of entityIds) {
const asset = this.casting[entityId].find(
asset => asset.asset_id === assetId
)
if (asset) {
await this.removeOneAsset(assetId, entityId, asset.nb_occurences)
if (this.isEpisodeCasting && asset.nb_occurences === 1) {
// The confirmation modal flow handles this entity on its own.
await this.removeOneAsset(assetId, entityId, asset.nb_occurences)
} else {
removals.push(entityId)
}
}
}
if (removals.length === 0) return
this.isLocked = true
this.loading.remove = true
removals.forEach(entityId => {
this.removeAssetFromCasting({ entityId, assetId, nbOccurences: 1 })
delete this.saveErrors[entityId]
})
try {
await this.saveCastings(removals)
this.setLock()
} catch (err) {
removals.forEach(entityId => {
this.saveErrors[entityId] = true
})
this.errors.remove = true
console.error(err)
} finally {
this.loading.remove = false
}
},

removeOneAsset(assetId, entityId, nbOccurences) {
Expand Down Expand Up @@ -1284,18 +1311,21 @@ export default {
const selectedElements = Object.keys(this.selection).filter(
key => this.selection[key]
)
for (const entityId of selectedElements) {
selectedElements.forEach(entityId => {
this.setEntityCasting({
entityId,
casting: castingToPaste
})
delete this.saveErrors[entityId]
await this.saveCasting(entityId)
.then(this.setLock)
.catch(err => {
this.saveErrors[entityId] = true
console.error(err)
})
})
try {
await this.saveCastings(selectedElements)
this.setLock()
} catch (err) {
selectedElements.forEach(entityId => {
this.saveErrors[entityId] = true
})
console.error(err)
}
return castingToPaste
},
Expand Down
28 changes: 25 additions & 3 deletions src/components/pages/Playlist.vue
Original file line number Diff line number Diff line change
Expand Up @@ -848,6 +848,7 @@ export default {

methods: {
...mapActions([
'addEntitiesToPlaylist',
'changePlaylistOrder',
'changePlaylistPreview',
'changePlaylistType',
Expand Down Expand Up @@ -1424,9 +1425,30 @@ export default {
// Captured once: keep adding to the playlist the user started from,
// even if they switch playlists mid-sequence.
const playlist = this.currentPlaylist
for (const entity of entities || []) {
this.entitiesAddedWhilePanelOpen = true
await this.addEntity(entity, playlist)
if (!entities?.length) return
this.entitiesAddedWhilePanelOpen = true
entities.forEach(entity => {
this.entityLoading[entity.id] = true
})
try {
await this.addEntitiesToPlaylist({
playlist,
entityIds: entities.map(entity => entity.id)
})
if (playlist.id === this.currentPlaylist.id) {
const loadedPlaylist = await this.loadPlaylist(playlist)
this.currentPlaylist = ref(loadedPlaylist)
this.rebuildCurrentEntities()
this.$nextTick(() => {
this.playlistPlayer?.scrollToRight()
})
}
} catch (err) {
console.error(err)
} finally {
entities.forEach(entity => {
this.entityLoading[entity.id] = false
})
}
},

Expand Down
53 changes: 33 additions & 20 deletions src/components/pages/ProductionSchedule.vue
Original file line number Diff line number Diff line change
Expand Up @@ -1693,6 +1693,11 @@ export default {
const startDate = parseDate(this.assignments.startDate)
const endDate = parseDate(this.assignments.endDate)

// accumulated during the distribution loop, flushed as one
// clear-assignation request plus one assign request per assignee
const taskIdsToUnassign = []
const taskIdsByAssignee = new Map()

let cumulatedTasks = 0
let nextAssigneeIndex = 0
let nextStartDate = startDate.clone()
Expand Down Expand Up @@ -1722,7 +1727,7 @@ export default {
if (this.isVersioned) {
versionedTask.assignees = []
} else {
await this.unassignSelectedTasks({ taskIds: [task.id] })
taskIdsToUnassign.push(task.id)
}
}

Expand Down Expand Up @@ -1771,25 +1776,23 @@ export default {
await this.updateScheduleVersionedTask(versionedTask)
}
} else {
await Promise.all([
// assign task to the current assignee
this.assignSelectedTasks({
personId: taskAssignee.id,
taskIds: [task.id]
}),
// save task dates & estimation
this.updateTask({
taskId: task.id,
data: {
estimation: daysToMinutes(
this.organisation,
taskEstimation
),
start_date: taskStartDate.format('YYYY-MM-DD'),
due_date: taskEndDate.format('YYYY-MM-DD')
}
})
])
// assignation to the current assignee is batched after the loop
if (!taskIdsByAssignee.has(taskAssignee.id)) {
taskIdsByAssignee.set(taskAssignee.id, [])
}
taskIdsByAssignee.get(taskAssignee.id).push(task.id)
// save task dates & estimation
await this.updateTask({
taskId: task.id,
data: {
estimation: daysToMinutes(
this.organisation,
taskEstimation
),
start_date: taskStartDate.format('YYYY-MM-DD'),
due_date: taskEndDate.format('YYYY-MM-DD')
}
})
}
// set next start date
if ((cumulatedTasks * taskEstimation) % 1 !== 0) {
Expand All @@ -1802,6 +1805,16 @@ export default {
}
}

// unassign first so batched assignations are not cleared right after
if (taskIdsToUnassign.length > 0) {
await this.unassignSelectedTasks({ taskIds: taskIdsToUnassign })
}
await Promise.all(
Array.from(taskIdsByAssignee, ([personId, taskIds]) =>
this.assignSelectedTasks({ personId, taskIds })
)
)

// refresh schedule
this.expandTaskTypeElement(
this.selectedTaskType,
Expand Down
37 changes: 17 additions & 20 deletions src/components/pages/production/NewProduction.vue
Original file line number Diff line number Diff line change
Expand Up @@ -828,28 +828,25 @@ const deleteFromList = (object, listName) => {
}

const createTaskTypesAndStatuses = async () => {
await func.runPromiseAsSeries(
productionToCreate.assetTaskTypes
.concat(productionToCreate.shotTaskTypes)
.map(async (taskType, index) => {
const finalIndex =
taskType.for_entity === 'Shot'
? index - productionToCreate.assetTaskTypes.length
: index
return await store.dispatch('addTaskTypeToProduction', {
taskTypeId: taskType.id,
priority: finalIndex + 1
})
const calls = productionToCreate.assetTaskTypes
.concat(productionToCreate.shotTaskTypes)
.map((taskType, index) => () => {
const finalIndex =
taskType.for_entity === 'Shot'
? index - productionToCreate.assetTaskTypes.length
: index
return store.dispatch('addTaskTypeToProduction', {
taskTypeId: taskType.id,
priority: finalIndex + 1
})
.concat(
productionToCreate.taskStatuses.map(async taskStatus => {
return await store.dispatch(
'addTaskStatusToProduction',
taskStatus.id
)
})
})
.concat(
productionToCreate.taskStatuses.map(
taskStatus => () =>
store.dispatch('addTaskStatusToProduction', taskStatus.id)
)
)
)
await func.runPromiseMapAsSeries(calls, call => call())
}

const createAssets = async () => {
Expand Down
4 changes: 2 additions & 2 deletions src/components/pages/production/ProductionTaskTypes.vue
Original file line number Diff line number Diff line change
Expand Up @@ -305,8 +305,8 @@ const savePriorities = async forms => {
if (now - lastCall > 1000 && !isSaving) {
lastCall = now
isSaving = true
await func.runPromiseAsSeries(
forms.map(async form => store.dispatch('editTaskTypeLink', form))
await func.runPromiseMapAsSeries(forms, form =>
store.dispatch('editTaskTypeLink', form)
)
isSaving = false
if (newSaveCall) {
Expand Down
35 changes: 14 additions & 21 deletions src/components/tops/ActionPanel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -1366,7 +1366,7 @@ export default {
'setAssetSearch',
'setLastTaskPreview',
'subscribeToTask',
'unassignPersonFromTask',
'unassignPersonFromTasks',
'unassignSelectedTasks',
'unsubscribeFromTask'
]),
Expand Down Expand Up @@ -1420,16 +1420,14 @@ export default {
const person = this.isCurrentUserArtist ? this.user : this.person
if (person) {
this.loading.assignation = true
func
.runPromiseAsSeries(
Array.from(this.selectedTasks.values()).map(task => {
return this.unassignPersonFromTask({ task, person })
})
)
.then(() => {
this.unassignPersonFromTasks({
tasks: Array.from(this.selectedTasks.values()),
person
})
.catch(console.error)
.finally(() => {
this.loading.assignation = false
})
.catch(console.error)
}
},

Expand Down Expand Up @@ -1555,10 +1553,8 @@ export default {
confirmTasksSubscription() {
this.loading.tasksSubscription = true
func
.runPromiseAsSeries(
Array.from(this.selectedTasks.values()).map(task => {
return this.subscribeToTask(task.id)
})
.runPromiseMapAsSeries(Array.from(this.selectedTasks.values()), task =>
this.subscribeToTask(task.id)
)
.then(() => {
this.loading.tasksSubscription = false
Expand All @@ -1573,10 +1569,8 @@ export default {
confirmTasksUnsubscription() {
this.loading.tasksSubscription = true
func
.runPromiseAsSeries(
Array.from(this.selectedTasks.values()).map(task => {
return this.unsubscribeFromTask(task.id)
})
.runPromiseMapAsSeries(Array.from(this.selectedTasks.values()), task =>
this.unsubscribeFromTask(task.id)
)
.then(() => {
this.loading.tasksSubscription = false
Expand All @@ -1602,10 +1596,9 @@ export default {
this.loading.setThumbnails = false
} else {
func
.runPromiseAsSeries(
Array.from(this.selectedTasks.values()).map(task => {
return this.setLastTaskPreview(task.id)
})
.runPromiseMapAsSeries(
Array.from(this.selectedTasks.values()),
task => this.setLastTaskPreview(task.id)
)
.then(() => {
this.loading.setThumbnails = false
Expand Down
Loading