fix(projects): scope project-issue move to its own project #18

Merged
oleks merged 2 commits from fix/user-project-move-multiproject-detach into main 2026-05-17 17:06:19 +03:00

2 Commits

Author SHA1 Message Date
Claude 078459c497 fix(projects): scope project-issue move to its own project
MoveIssuesOnProjectColumn updated `project_issue` with a WHERE clause on
issue_id only. An issue assigned to several projects has one project_issue
row per project, so moving it within one project rewrote project_board_id
for every project the issue belonged to, detaching it from all the others.

Scope the UPDATE to (issue_id, project_id) so only the target project's
row changes. Mirrors the fix already present in upstream/main.

Adds an integration regression test asserting an issue in two user
projects keeps its column in the other project after a move. Fixes #17.
2026-05-17 16:59:31 +03:00
Oleks 1cd81ff925 feat(api): state filter + populated num_issues on project columns
Adds two improvements to the user/org/repo project-board REST API:

* state filter on column-issues endpoints (issue #4)
  GET /api/v1/{users,orgs}/{name}/-/projects/{id}/columns/{col}/issues
  GET /api/v1/repos/{owner}/{repo}/projects/{id}/columns/{col}/issues
  Now accept ?state=open|closed|all (default open), matching the convention
  on the project-list endpoint and on /repos/.../issues. Applied at the
  IssuesOptions layer so all three scopes inherit the filter.

* populated num_issues / num_open_issues / num_closed_issues on column-list
  (issue #5)
  ColumnList.LoadIssueCounts runs two grouped queries against project_issue
  joined with issue (one open, one closed). All three List*Columns handlers
  call it before converting, so num_issues stops being null and consumers
  can render a kanban summary in a single round trip instead of N+1.

Tests:
* unit: empty-input fast path on ColumnList.LoadIssueCounts.
* integration: extended testAPIListProjectColumnIssues / -User / -Org to
  close an issue, then verify default=open hides it, state=closed and
  state=all return it, and the column-list response carries the correct
  open/closed/total split.

Closes #4, closes #5
2026-05-15 21:54:35 +03:00