FN-8481: enable GitHub tracking for Ideas tasks
Allow operators to manage GitHub tracking from Ideas intake and Coding (Ideas) task details. - Permit GitHub tracking toggles in the Ideas column and the built-in Coding (Ideas) workflow. - Cover fallback and resolved workflow metadata paths with dashboard tests. - Add a patch changeset for the operator-facing capability. Files changed: .changeset/fn-8481-ideas-github-tracking.md | 7 ++++ .../dashboard/app/components/TaskDetailModal.tsx | 13 +++++-- ...lModal.inline-editing-and-integrations.test.tsx | 40 ++++++++++++++++++++-- 3 files changed, 56 insertions(+), 4 deletions(-) Fusion-Task-Id: FN-8481 Fusion-Task-Lineage: d267e203-bceb-492b-b218-8829406ef537 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
This commit is contained in:
7
.changeset/fn-8481-ideas-github-tracking.md
Normal file
7
.changeset/fn-8481-ideas-github-tracking.md
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
"@runfusion/fusion": patch
|
||||
---
|
||||
|
||||
summary: Let operators enable or disable GitHub tracking from Coding Ideas task details.
|
||||
category: feature
|
||||
dev: GitHub tracking eligibility now recognizes the Ideas intake column and `builtin:coding-ideas` workflow ID.
|
||||
@@ -650,7 +650,16 @@ function getProvenanceLabel(task: Task | TaskDetail, options: ProvenanceLabelOpt
|
||||
// #1403: widened to ColumnId so `.has(task.column)` accepts custom column ids
|
||||
// (non-members correctly resolve to false → not editable).
|
||||
const EDITABLE_COLUMNS: Set<ColumnId> = new Set<ColumnId>(["triage", "todo"]);
|
||||
const GITHUB_TRACKING_EDITABLE_COLUMNS: Set<ColumnId> = new Set<ColumnId>(["triage", "todo", "in-progress", "in-review"]);
|
||||
const GITHUB_TRACKING_EDITABLE_COLUMNS: Set<ColumnId> = new Set<ColumnId>(["triage", "todo", "in-progress", "in-review", "ideas"]);
|
||||
const CODING_IDEAS_WORKFLOW_ID = "builtin:coding-ideas";
|
||||
|
||||
/*
|
||||
FNXC:GitHubTracking 2026-07-22-00:46:
|
||||
Ideas tasks must be able to opt into or out of GitHub tracking before planning, whether they remain in the Ideas intake column or have advanced in Coding (Ideas). Use the resolved workflow ID rather than its display name so localized names and arbitrary custom workflows cannot gain this editing capability.
|
||||
*/
|
||||
function canTaskEditGithubTracking(column: ColumnId, workflowId: string | undefined): boolean {
|
||||
return GITHUB_TRACKING_EDITABLE_COLUMNS.has(column) || workflowId === CODING_IDEAS_WORKFLOW_ID;
|
||||
}
|
||||
|
||||
export function TaskDetailContent({
|
||||
task,
|
||||
@@ -1618,7 +1627,7 @@ export function TaskDetailContent({
|
||||
|
||||
// Check if task can be edited
|
||||
const canEdit = EDITABLE_COLUMNS.has(task.column) && !isSaving;
|
||||
const canEditGithubTracking = GITHUB_TRACKING_EDITABLE_COLUMNS.has(task.column) && !isSaving;
|
||||
const canEditGithubTracking = canTaskEditGithubTracking(task.column, taskWorkflowBadge?.id) && !isSaving;
|
||||
const githubTrackingEnabled = githubTrackingEnabledDraft ?? (workingTask.githubTracking?.enabled === true);
|
||||
const githubTrackedIssue = workingTask.githubTracking?.issue;
|
||||
const gitlabTrackedItem = workingTask.gitlabTracking?.item;
|
||||
|
||||
@@ -3414,14 +3414,50 @@ describe("TaskDetailModal inline action row parity (FN-8194)", () => {
|
||||
expect(toggle).toHaveClass("btn-primary");
|
||||
});
|
||||
|
||||
it("hides the GitHub toggle for non-editable and GitLab-tracked tasks", () => {
|
||||
it("enables GitHub tracking for Ideas intake tasks after workflow metadata fails", async () => {
|
||||
const { updateTask, fetchBoardWorkflows } = await import("../../api");
|
||||
const mockUpdate = vi.mocked(updateTask);
|
||||
vi.mocked(fetchBoardWorkflows).mockRejectedValueOnce(new Error("workflow metadata unavailable"));
|
||||
mockUpdate.mockResolvedValueOnce(makeTask({ id: "FN-ideas", column: "ideas", githubTracking: { enabled: true } }) as Task);
|
||||
|
||||
renderDetail(makeTask({ id: "FN-ideas", column: "ideas", githubTracking: { enabled: false } }));
|
||||
|
||||
const toggle = screen.getByTestId("detail-inline-github-toggle");
|
||||
expect(toggle).toHaveAttribute("aria-pressed", "false");
|
||||
fireEvent.click(toggle);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockUpdate).toHaveBeenCalledWith("FN-ideas", { githubTracking: { enabled: true } }, undefined);
|
||||
});
|
||||
expect(toggle).toHaveAttribute("aria-pressed", "true");
|
||||
});
|
||||
|
||||
it("shows the GitHub toggle after Coding (Ideas) workflow metadata resolves", async () => {
|
||||
const { fetchBoardWorkflows } = await import("../../api");
|
||||
vi.mocked(fetchBoardWorkflows).mockResolvedValueOnce({
|
||||
flagEnabled: true,
|
||||
defaultWorkflowId: "builtin:coding",
|
||||
workflows: [
|
||||
{ id: "builtin:coding", name: "Coding", columns: [{ id: "done", name: "Done", flags: {} }] },
|
||||
{ id: "builtin:coding-ideas", name: "Coding (Ideas)", columns: [{ id: "done", name: "Done", flags: {} }] },
|
||||
],
|
||||
taskWorkflowIds: { "FN-ideas-workflow": "builtin:coding-ideas" },
|
||||
});
|
||||
|
||||
renderDetail(makeTask({ id: "FN-ideas-workflow", column: "done", githubTracking: { enabled: false } }));
|
||||
|
||||
expect(screen.queryByTestId("detail-inline-github-toggle")).not.toBeInTheDocument();
|
||||
expect(await screen.findByTestId("detail-inline-github-toggle")).toHaveAttribute("aria-pressed", "false");
|
||||
});
|
||||
|
||||
it("hides the GitHub toggle for unrelated and GitLab-tracked tasks", () => {
|
||||
const { unmount } = renderDetail(makeTask({ id: "FN-8194", column: "done", githubTracking: { enabled: true } }));
|
||||
expect(screen.queryByTestId("detail-inline-github-toggle")).not.toBeInTheDocument();
|
||||
unmount();
|
||||
|
||||
renderDetail(makeTask({
|
||||
id: "FN-8195",
|
||||
column: "todo",
|
||||
column: "ideas",
|
||||
gitlabTracking: {
|
||||
item: {
|
||||
kind: "project_issue",
|
||||
|
||||
Reference in New Issue
Block a user