diff --git a/ui/src/context/LiveUpdatesProvider.test.ts b/ui/src/context/LiveUpdatesProvider.test.ts index 5aa7654e..673b7032 100644 --- a/ui/src/context/LiveUpdatesProvider.test.ts +++ b/ui/src/context/LiveUpdatesProvider.test.ts @@ -100,6 +100,94 @@ describe("LiveUpdatesProvider issue invalidation", () => { }); }); + it("refreshes issue document caches when a document activity event arrives", () => { + const invalidations: unknown[] = []; + const queryClient = { + invalidateQueries: (input: unknown) => { + invalidations.push(input); + }, + getQueryData: () => undefined, + }; + + __liveUpdatesTestUtils.invalidateActivityQueries( + queryClient as never, + "company-1", + { + entityType: "issue", + entityId: "issue-1", + action: "issue.document_updated", + actorType: "agent", + actorId: "agent-1", + details: { + identifier: "PAP-9403", + key: "plan", + }, + }, + { userId: "user-1", agentId: null }, + { pathname: "/PAP/issues/PAP-9403", isForegrounded: true }, + ); + + expect(invalidations).toContainEqual({ + queryKey: queryKeys.issues.detail("issue-1"), + }); + expect(invalidations).toContainEqual({ + queryKey: queryKeys.issues.documents("issue-1"), + }); + expect(invalidations).toContainEqual({ + queryKey: queryKeys.issues.document("issue-1", "plan"), + }); + expect(invalidations).toContainEqual({ + queryKey: queryKeys.issues.documentRevisions("issue-1", "plan"), + }); + expect(invalidations).toContainEqual({ + queryKey: queryKeys.issues.documents("PAP-9403"), + }); + expect(invalidations).toContainEqual({ + queryKey: queryKeys.issues.document("PAP-9403", "plan"), + }); + expect(invalidations).toContainEqual({ + queryKey: queryKeys.issues.documentRevisions("PAP-9403", "plan"), + }); + expect(invalidations).not.toContainEqual({ + queryKey: queryKeys.issues.documents("issue-1"), + refetchType: "inactive", + }); + }); + + it("refreshes all issue document caches when document activity omits a document key", () => { + const invalidations: unknown[] = []; + const queryClient = { + invalidateQueries: (input: unknown) => { + invalidations.push(input); + }, + getQueryData: () => undefined, + }; + + __liveUpdatesTestUtils.invalidateActivityQueries( + queryClient as never, + "company-1", + { + entityType: "issue", + entityId: "issue-1", + action: "issue.document_deleted", + actorType: "agent", + actorId: "agent-1", + details: null, + }, + { userId: "user-1", agentId: null }, + ); + + expect(invalidations).toContainEqual({ + queryKey: queryKeys.issues.documents("issue-1"), + }); + expect(invalidations).toContainEqual({ + queryKey: ["issues", "document", "issue-1"], + }); + expect(invalidations).toContainEqual({ + queryKey: ["issues", "document-revisions", "issue-1"], + }); + }); + it("keeps self-authored comment events from refetching the active issue tree", () => { const invalidations: unknown[] = []; const queryClient = { diff --git a/ui/src/context/LiveUpdatesProvider.tsx b/ui/src/context/LiveUpdatesProvider.tsx index 99f3a2fc..783537e0 100644 --- a/ui/src/context/LiveUpdatesProvider.tsx +++ b/ui/src/context/LiveUpdatesProvider.tsx @@ -408,6 +408,12 @@ async function hydrateVisibleIssueComment( } const ISSUE_TOAST_ACTIONS = new Set(["issue.created", "issue.updated", "issue.comment_added"]); +const ISSUE_DOCUMENT_ACTIVITY_ACTIONS = new Set([ + "issue.document_created", + "issue.document_updated", + "issue.document_restored", + "issue.document_deleted", +]); const AGENT_TOAST_STATUSES = new Set(["error"]); const RUN_TOAST_STATUSES = new Set(["failed", "timed_out", "cancelled"]); @@ -685,6 +691,17 @@ function invalidateActivityQueries( if (action === "issue.comment_added") { queryClient.invalidateQueries({ queryKey: queryKeys.issues.comments(ref), ...invalidationOptions }); } + if (action && ISSUE_DOCUMENT_ACTIVITY_ACTIONS.has(action)) { + const documentKey = readString(details?.key); + queryClient.invalidateQueries({ queryKey: queryKeys.issues.documents(ref), ...invalidationOptions }); + if (documentKey) { + queryClient.invalidateQueries({ queryKey: queryKeys.issues.document(ref, documentKey), ...invalidationOptions }); + queryClient.invalidateQueries({ queryKey: queryKeys.issues.documentRevisions(ref, documentKey), ...invalidationOptions }); + } else { + queryClient.invalidateQueries({ queryKey: ["issues", "document", ref], ...invalidationOptions }); + queryClient.invalidateQueries({ queryKey: ["issues", "document-revisions", ref], ...invalidationOptions }); + } + } if (action?.startsWith("issue.thread_interaction_")) { queryClient.invalidateQueries({ queryKey: queryKeys.issues.interactions(ref), ...invalidationOptions }); }