fix(project): keep taskIds unique on replayed move-to-done (#8469) (#9076)

This commit is contained in:
Johannes Millan 2026-07-16 17:09:04 +02:00 committed by GitHub
parent 470c700358
commit 5fcb1cb2d7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 30 additions and 2 deletions

View file

@ -383,6 +383,32 @@ describe('projectReducer', () => {
// When target is DONE and afterTaskId is null, append to end
expect((r.entities as any).P1.taskIds).toEqual(['T1', 'T2', 'B1']);
});
it('should not duplicate the task id when re-replayed (DONE, null anchor) (#8469)', () => {
const s = fakeEntityStateFromArray([
{
id: 'P1',
taskIds: ['T1', 'T2'],
backlogTaskIds: ['B1', 'B2'],
isEnableBacklog: true,
},
] as Partial<Project>[]);
const action = moveProjectTaskToRegularList({
taskId: 'B1',
afterTaskId: null,
workContextId: 'P1',
src: 'BACKLOG',
target: 'DONE',
}) as any;
// Re-applying the same op on top of already-applied state (snapshot
// re-replay window, #8469) must not append the id a second time.
const once = projectReducer(s as any, action);
const twice = projectReducer(once, action);
expect((twice.entities as any).P1.taskIds).toEqual(['T1', 'T2', 'B1']);
expect((twice.entities as any).P1.backlogTaskIds).toEqual(['B2']);
});
});
describe('moveTaskInTodayList (anchor-based)', () => {

View file

@ -333,10 +333,12 @@ export const projectReducer = createReducer<ProjectState>(
const filteredBacklog = backlogIdsBefore.filter(filterOutId(taskId));
// When moving to DONE section with null anchor, append to end
// Otherwise use standard anchor-based positioning
// Otherwise use standard anchor-based positioning.
// Filter the id out before appending (like moveItemAfterAnchor does) so an
// op re-replayed on top of already-applied state can't duplicate it (#8469).
const newTodaysTaskIds =
afterTaskId === null && target === 'DONE'
? [...todaysTaskIdsBefore, taskId]
? [...todaysTaskIdsBefore.filter(filterOutId(taskId)), taskId]
: moveItemAfterAnchor(taskId, afterTaskId, todaysTaskIdsBefore);
return projectAdapter.updateOne(