mirror of
https://github.com/multica-ai/multica.git
synced 2026-07-05 13:29:44 +02:00
fix(issues): drop redundant WS position->list invalidate
onIssueUpdated already surgically patches the non-filtered workspace board via patchIssueInBuckets (cross-status move + same-column reorder). The extra `if (position) invalidateQueries(list)` re-pulled the whole board on top of that, re-introducing drag flicker through the echoed-back WS event. Removed. Filtered myAll lists still invalidate (membership can change there) — the client-side membership reconciliation for those is a separate follow-up. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
@@ -262,6 +262,41 @@ describe("project progress invalidation", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("onIssueUpdated — position move is surgical, not a list refetch", () => {
|
||||
let qc: QueryClient;
|
||||
|
||||
beforeEach(() => {
|
||||
qc = new QueryClient();
|
||||
});
|
||||
|
||||
const issueA: Issue = { ...baseIssue, id: "issue-1", position: 0 };
|
||||
const issueB: Issue = { ...baseIssue, id: "issue-2", position: 10 };
|
||||
|
||||
it("reorders the moved card in place and does NOT invalidate the workspace list", () => {
|
||||
qc.setQueryData<ListIssuesCache>(issueKeys.list(WS_ID), makeListCache(issueA, issueB));
|
||||
|
||||
// issue-1 moves below issue-2 (position 0 -> 20) — a remote/echoed drag.
|
||||
onIssueUpdated(qc, WS_ID, { ...issueA, position: 20 });
|
||||
|
||||
const list = qc.getQueryData<ListIssuesCache>(issueKeys.list(WS_ID));
|
||||
// Surgically reordered into its new slot: proof the patch alone suffices.
|
||||
expect(list?.byStatus.todo?.issues.map((i) => i.id)).toEqual(["issue-2", "issue-1"]);
|
||||
// The old redundant `position -> invalidate(list)` is gone — no full-board
|
||||
// refetch on top of the surgical patch (that was the flicker source).
|
||||
expect(qc.getQueryState(issueKeys.list(WS_ID))?.isInvalidated).toBe(false);
|
||||
});
|
||||
|
||||
it("still invalidates the filtered myAll lists (membership can change there)", () => {
|
||||
qc.setQueryData<ListIssuesCache>(issueKeys.list(WS_ID), makeListCache(issueA, issueB));
|
||||
qc.setQueryData<ListIssuesCache>(issueKeys.myAll(WS_ID), makeListCache(issueA));
|
||||
|
||||
onIssueUpdated(qc, WS_ID, { ...issueA, position: 20 });
|
||||
|
||||
expectInvalidated(qc, issueKeys.myAll(WS_ID));
|
||||
expect(qc.getQueryState(issueKeys.list(WS_ID))?.isInvalidated).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("onIssueDeleted", () => {
|
||||
let qc: QueryClient;
|
||||
|
||||
|
||||
@@ -59,9 +59,17 @@ export function onIssueUpdated(
|
||||
for (const [key, data] of listQueries) {
|
||||
if (data) qc.setQueryData<ListIssuesCache>(key, patchIssueInBuckets(data, issue.id, issue));
|
||||
}
|
||||
if (issue.position !== undefined) {
|
||||
qc.invalidateQueries({ queryKey: issueKeys.list(wsId) });
|
||||
}
|
||||
// The workspace board (issueKeys.list) is NOT filtered: an issue is always a
|
||||
// member, so patchIssueInBuckets above is a complete surgical reconcile —
|
||||
// cross-status move, same-column reorder, and field updates all land in the
|
||||
// right bucket/slot. The old `if (position) invalidateQueries(list)` re-pulled
|
||||
// the entire board on top of that, which is the full-list refetch that made a
|
||||
// drag (local or echoed back over WS) flicker. It is pure redundancy here.
|
||||
//
|
||||
// myAll (My Issues / Project / actor lists) IS filtered: a change can move an
|
||||
// issue in/out of the filter and the client cannot recompute that membership
|
||||
// here, so that one is still invalidated. (Replacing this with client-side
|
||||
// membership reconciliation is the separate follow-up — see issue thread.)
|
||||
qc.invalidateQueries({ queryKey: issueKeys.myAll(wsId) });
|
||||
qc.invalidateQueries({ queryKey: issueKeys.assigneeGroupsAll(wsId) });
|
||||
qc.invalidateQueries({ queryKey: issueKeys.myAssigneeGroupsAll(wsId) });
|
||||
|
||||
Reference in New Issue
Block a user