Skip to content

feat(tasks): add Jira board view and settings - #28

Merged
nplez1 merged 1 commit into
nplez1/mainfrom
nplez1/Tasks-View
Sep 24, 2026
Merged

nplez1 merged 1 commit into
nplez1/mainfrom
nplez1/Tasks-View

Conversation

@nplez1

@nplez1 nplez1 commented Sep 24, 2026 •

Copy link
Copy Markdown
Owner
Files Added Deleted Net
Test 9 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​1146 $\color{#cf222e}{\Huge{\mathbf{−}}}$​1 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​1145
Prod 39 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​2702 $\color{#cf222e}{\Huge{\mathbf{−}}}$​168 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​2534

ELI5

Orca's Tasks view can read Jira, but it only ever showed a flat list of issues, filtered by a JQL search box or a preset. There was no way to see the thing Jira is actually for — the board. Now you pick a board once in Settings → Tasks, and the Jira tab opens on it: the board's own columns, the active sprint, the backlog, and cards you can drag from one column to another. Dragging moves the issue in Jira, using the same status transitions the issue detail pane already used. If you don't pick a board, nothing changes and you still get the issue list.

What Changed

Before

  • Tasks → Jira was the issue list and nothing else: a search/preset bar, a sort control, and issues grouped by status. No board, no sprint, no backlog, no drag-to-transition.
  • Settings → Tasks had a Jira connection section and no board section at all.
  • The only way to move a Jira issue's status was to open the issue and use its transition control.

After

  • With a board chosen in Settings → Tasks → Jira board view, the Jira tab renders a board instead of the list:
    • a header with the board name, a Sprint / Backlog toggle, a Me / Team / All filter, refresh, and an Issue list button;
    • the sprint view shows the board's configured status columns with the active sprint's issue cards, and dragging a card onto a column moves the issue there;
    • the backlog view lists the board's backlog with Load more, and labels why it is showing a backlog when the board has no active sprint;
    • clicking a card opens the existing issue detail pane; if the issue you just moved is open, that pane refetches so it stops showing the old status.
  • Settings → Tasks → Jira board view picks the default board from the boards your Jira credentials can see, and the Jira custom field + value the Team filter matches on.
  • No default board (the default) means the old behaviour, byte for byte: the issue list. In list mode with a board configured there is a Return to board button, and the gear next to the Jira source selector jumps straight to the board settings section.

Mechanism

  • Main process. A new src/main/jira/jira-board-queries.ts adds four reads on top of the existing authenticated Jira request path: listBoards (paged /board), listCustomFields (/field, custom fields only), getBoardOverview (/board/{id} + /configuration for columns + /sprint?state=active for scrum boards only), and listBoardIssues (sprint or backlog). It reuses acquire/release from request-queue, clearToken on an auth error, and the existing record helpers. Cloud and Server differ, so paging is per-auth-type: Cloud boards use /rest/software/1.0 with nextPageToken, Server uses /rest/agile/1.0 with startAt; when neither isLast nor total is available the page size decides.
  • Transport. src/main/ipc/jira-board-handlers.ts registers jira:listBoards, jira:listCustomFields, jira:getBoardOverview, jira:listBoardIssues (validated before dispatch), the preload bridge exposes them, and src/main/runtime/rpc/methods/jira.ts adds jira.listBoards, jira.listCustomFields, jira.getBoardOverview, jira.listBoardIssues with zod params (BoardIdentifier, and BoardIssuePage as a discriminated union on scope) — the catalog is regenerated in the same commit.
  • Renderer. useTaskPageJiraBoardPages owns the two paged issue feeds with per-feed generation counters so a slow page can't land on a newer board; useTaskPageJiraBoard adds the overview, the active sprint, and the filter; task-page-jira-board-model.ts is the pure part — column grouping (including an Other statuses column for issues in no configured column), the Me/Team/All filter, and getTaskPageJiraBoardTransitionTargets. Drag-and-drop goes through the issue's own transitions: zero matching transitions is an error toast, exactly one is applied directly, and more than one opens a chooser dialog.
  • Switching between the two views is a single local jiraBoardViewMode in use-task-page-jira-list-state.ts. When a board is set and that mode is board, the list effects skip their fetch entirely (use-task-page-jira-list-effects.ts) rather than loading a list nobody is looking at; the Jira filter bar and the site selector are hidden while the board is pinned, both because the board's saved filter replaces them.
  • Team filter. The configured field id is appended to the issue fields request and mapped onto the issue (teamValue), then matched exactly against the value from Settings.
  • Settings shape. The task-view settings move out of global-settings-types.ts into src/shared/task-view-settings-types.ts (GlobalSettings is now … & TaskViewSettings), and three keys are added: defaultJiraBoard, jiraTeamFieldId, jiraTeamValue, all defaulted in buildDefaultSettings.

Also in this diff: the branch's own new strings are localized. The first version of this commit called translate('auto.components.TaskPage.5b6b2af943', 'Loading…') at three board loading states, but that key is the existing "Retrying…" string from task-page/github/List.tsx, and because the English boot catalog resolves from en-runtime-required.json when a key is shipped there, reconciling the catalogs would have made the board's spinner read Retrying…. The three sites now use their own jiraBoardLoading key, which leaves en-runtime-required.json unchanged from the base, registers the ~50 new board strings in locales/en.json, and wraps the two new aria-labels (Board.tsx, BoardHeader.tsx) in translate().

Why

  • Why a board at all. The issue list answers "what is assigned to me"; it cannot answer "what is in progress and what is waiting for review", which is the question that makes a Jira board useful and the reason the JQL box keeps getting used for it. The board data (board columns, its saved filter, its sprints) simply does not exist in the JQL search path, so it had to come from the Agile API.
  • Why the Agile API and not JQL. A board's columns are status sets, and its backlog and sprint membership are server-side concepts. Reconstructing them from JQL would mean guessing the board's filter and column mapping client-side and getting it wrong whenever a board is customized — which is the normal case.
  • Why the list view survives. Not every Jira user has a board, and not every board is the one they want at that moment. Pinning the board behind an explicit setting keeps the existing list as the default and keeps JQL search available, rather than replacing one workflow with another.
  • Why transitions instead of writing status. Jira validates status changes through transitions; a board drag can only offer transitions Jira will actually accept for that issue. When more than one transition reaches the target column, the chooser asks instead of picking one, because guessing silently changes the issue's workflow semantics.
  • Why filters are client-side. The board endpoints apply the board's saved filter, and Me/Team are display filters over already-loaded issues; pushing them server-side would need the field id in a JQL/board query for every board type. The cost is real and is called out in Notes — the filter only sees pages that have been loaded, and the empty state says so.

Linked Issue

N/A — there is no tracking issue, and there cannot be one: GitHub issues are disabled on this fork (nplez1/orca reports has_issues: false). The fork tracker is BRANCHES.md; this branch was not listed there before opening.

Visual Proof

N/A — no screenshots, deliberately, at the author's request for this PR. Stated plainly rather than implied: this is a visible change (a new board surface in the Jira Tasks tab and a new settings section), and no capture was taken because the board only renders against a live Jira site with a scrum board attached, which this worktree has no credentials for. The $electron skill AGENTS.md names for rendered-UI checks is not installed here (the available skills are computer-use, find-skills, orca-cli, orchestration), and no app was launched, so the untested-by-eye surface is exactly: column widths and horizontal scroll on a wide board, drag-and-drop feel, and the settings section's two-column layout at narrow widths. The rest of the diff is transport, paging, and pure grouping/group-filter logic, which the tests below assert; what no test asserts is any of it against a live Jira site.

Testing

Verified on macOS, on the branch as pushed (e253a3a059), after rebasing onto origin/nplez1/main (52780417c1, i.e. #26 + #27 — a clean rebase, which is why the PR is one commit):

  • pnpm tc — clean (main, node, web, cli).

  • pnpm test on the ten touched and adjacent suites — 87 passed: jira-board-queries, main/jira/issues, JiraIssueWorkspace.refreshSignal, settings/JiraBoardSettings, settings/TasksPane, task-page-jira-board-model, task-page/jira/Board, task-page/jira/SettingsLink, runtime-jira-client, task-page-jira-grouping. Covers the Cloud/Server paging split and isLast inference, column grouping with an other-statuses column, the transition-target matching (0 / 1 / many), the Team filter, the settings writes (including clearing the team field when the board's site changes), and the detail refetch after a move.

  • pnpm run check:code-quality:changed — 0 new findings across 47 changed files (casting, focused plugins, type-aware, React Doctor, design system, casting-SAFETY), gate passed since 52780417c1.

  • The gates this branch initially failed, now green: verify:localization-catalog, verify:localization-runtime-catalog, verify:localization-extraction, verify:localization-coverage — and the base was re-checked, where all four pass, so the fix in "Also in this diff" is what closed them. verify:rpc-params-catalog passes for the regenerated catalog.

  • Not run locally: the new e2e spec (tests/e2e/jira-tasks-settings-link.spec.ts) needs a built Electron app. CI does cover it — config/scripts/pr-e2e-source-routing.mjs routes this PR's 48 changed files to exactly that spec, so pr.yml's e2e job runs it. Full pnpm lint, full pnpm test, and pnpm build are left to CI. No manual run and no Jira connection — the board has never rendered against a real site, so a reviewer with Jira credentials is the first person to see it work.

  • I manually tested these changes locally

  • Automated tests added/updated, or explained why not below

The commit adds six unit suites and updates two existing ones, plus the e2e spec. Steps for a reviewer with Jira access: Settings → Tasks → Jira board view → pick a scrum board → Tasks → Jira → the board should open on the active sprint; drag a card one column right and confirm Jira records the transition; switch to Backlog and scroll (pages of 100); set a Team field + value and check the Team filter; set No default board and confirm the old list comes back.

AI Disclosure

Authored with an AI coding agent (pi) under human direction; the feature commit carries no model trailer, so no model is named for the code itself. This description was written by a later pi session (deepseek-flash) from the branch diff, the gate output above, and the session that wrote the code.

Review

Start with src/main/jira/jira-board-queries.ts — the paging split between Cloud (/rest/software/1.0, nextPageToken) and Server (/rest/agile/1.0, startAt) and the isLast fallback are the parts most likely to be wrong against a real site. Then task-page-jira-board-model.ts, which is pure and fully tested: column grouping, the Me/Team/All filter, and transition targets. Then Board.tsx (handleDrop → 0/1/many transitions) and use-task-page-jira-board-pages.ts (generation guards). JiraBoardSettings.tsx is the only place that writes the new settings and is worth a look for which fields it clears on change.

Agent skill upstream boundary

  • Not applicable, or this change follows docs/reference/agent-skill-sharing-upstream-boundary.md and copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.

Notes

  • Security: no new credential handling or surface. The four new reads go through the same authenticated request path as every existing Jira call (jiraRequest + acquire/release, clearToken only on an auth error), and board ids / site ids are encodeURIComponentd into the paths before use. The new IPC handlers validate their args before dispatch and the RPC methods validate with zod; listBoardIssues returns an empty page rather than throwing on a malformed request.
  • Cross-platform: no OS-specific code and no new shortcuts or path handling. Drag-and-drop is HTML5 DnD on existing primitives; no components/ui/ primitive was restyled.
  • SSH / remote: the board reads follow the existing Jira target split — runtime-jira-board-client.ts calls the paired runtime over RPC when the Jira integration lives on a runtime environment, and the local IPC bridge otherwise. A runtime that predates these methods answers method_not_found, which the renderer already detects: it toasts once and falls back to the issue list rather than showing an error, so an old runtime paired with a new client degrades instead of breaking. New RPC methods are additive; nothing an old client reads changed shape.
  • Mobile: no mobile code path touched.
  • Folder workspaces: unaffected — this is the Tasks view, which is keyed to providers, not to a worktree.
  • Backwards compatibility: the three new settings are optional and defaulted in buildDefaultSettings (defaultJiraBoard: null, empty team field/value), so an existing profile keeps the issue list until a board is chosen; the GlobalSettings change is a type-only move of the task-view keys into TaskViewSettings. JiraIssue gains an optional teamValue that only the board mapping populates. en-runtime-required.json is byte-identical to the base.
  • Performance: the board loads one page per feed (100 issues) and appends on demand; the sprint and backlog feeds are fetched separately and only when their view is on screen. In board mode the issue-list effects skip their fetch, so switching to the board does not also run the old JQL query. getBoardOverview is three sequential requests per board (board, configuration, active sprints) and is refetched only on refresh or when the selection changes.
  • Known limitation, deliberate: the Me / Team filters are client-side over loaded pages, so on a large board they filter what has been loaded so far — the backlog's empty state says "No matching issues in this page. Load more to continue searching the backlog." rather than claiming there are none. Pushing them server-side is a follow-up, not an oversight.
  • Known gap: the JQL search box is not available in board mode (the board applies its own saved filter); switching to Issue list brings it back.

Checklist

  • This PR is small and focused — one topic, but 48 files and ~3.8k lines: main-process reads, transport, renderer state and a settings surface. Splitting it would mean shipping a board with no data path.
  • I explained what changed and why (ELI5, the user-facing before/after, the mechanism, and why over the alternatives)
  • Before/after screenshots or videos attached for UI changes, or N/A with reason — not captured; see Visual Proof
  • Self-reviewed for correctness, security, and performance
  • Cross-platform, SSH/remote, and path/shortcut impact considered (or N/A)
  • pnpm lint, pnpm typecheck, pnpm test, and pnpm build pass (or CI will cover; local preferred) — pnpm tc, the ten suites above, the changed-code quality gate and all five verify gates pass locally; full pnpm lint, full pnpm test, pnpm build and the e2e spec are left to CI

@nplez1
nplez1 merged commit 7865a2b into nplez1/main Sep 24, 2026
70 of 72 checks passed
@nplez1
nplez1 deleted the nplez1/Tasks-View branch October 24, 2026 03:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant