122 lines
6.0 KiB
Markdown
122 lines
6.0 KiB
Markdown
# gitea plugin — roadmap
|
||
|
||
> **Status:** scaffold. Phase 1 = accounts CRUD + connection test only.
|
||
> The `gitea-issue-client/` Python tool in the project root is the
|
||
> reference for the full feature surface that needs to be ported.
|
||
|
||
## Phase 1 — done ✅
|
||
|
||
- [x] `GiteaClient.php` cURL wrapper with `testConnection()`,
|
||
`searchIssues()`, `listRepoIssues()`, `getIssue()`, `listIssueComments()`
|
||
- [x] `gitea_accounts` table with encrypted token (vault key, same as email)
|
||
- [x] Routes: `GET/POST/PATCH/DELETE /api/gitea/accounts` + `POST .../test`
|
||
- [x] Settings tab via `hyprcrd.settings.registerTab`
|
||
- [x] Header button "gitea"
|
||
- [x] Welcome view + accounts management form
|
||
- [x] Connection test against `/api/v1/user`
|
||
|
||
## Phase 2 — issue reader ✅
|
||
|
||
- [x] **Issue list view** in the overlay:
|
||
- Search box (`q` parameter, debounced 350ms)
|
||
- State filter (open/closed/all)
|
||
- Pagination (prev/next, hasMore heuristic since Gitea doesn't always return total)
|
||
- Each row: title, repo path, state badge, labels, author, age
|
||
- [x] **Issue detail view** (right pane):
|
||
- Subject + state badge + labels + #number + repo
|
||
- Body (markdown rendered via `hyprcrd.markdown.render` — exposed by core)
|
||
- Comments list (each with author + relative timestamp + rendered markdown)
|
||
- "Open on Gitea" link button
|
||
- [x] **Extract → card**:
|
||
- Card title = `[repo#number] title`
|
||
- Card body = metadata header + body + comments + `#gitea #issue` tags
|
||
- Color: green (#22c55e)
|
||
- [ ] **Issue → card backlink** in a `gitea_issue_links` table — needed
|
||
for Phase 5 bidirectional sync
|
||
|
||
## Phase 3 — write operations
|
||
|
||
- [x] **Add comment** — composer textarea always visible at the bottom of the
|
||
detail pane. Ctrl/Cmd+Enter posts. New comment is appended to local state
|
||
and re-rendered immediately.
|
||
- [x] **Close / reopen** — single button in the action bar that toggles state.
|
||
Updates the badge, button label, and the row in the list.
|
||
- [x] **Edit title** — pencil icon next to the title swaps to an inline input.
|
||
Enter saves, Escape cancels. PATCH `/issues/{index}`.
|
||
- [x] **Edit body** — pencil icon next to the body swaps to a textarea.
|
||
Ctrl/Cmd+Enter saves, Escape cancels.
|
||
- [x] **Set labels** — tag icon opens an inline editor that fetches the repo's
|
||
label list (`GET /api/gitea/repo/.../labels`) and shows checkboxes with
|
||
original colors. Save uses `PUT /issues/{index}/labels`.
|
||
- [ ] **Set assignees** — needs a collaborator typeahead (next round, see
|
||
TODO Phase 3.5)
|
||
- [ ] **Set milestone** — needs milestone fetch + dropdown (next round)
|
||
- [ ] **Set due date** — date picker (next round)
|
||
|
||
## Phase 3.5 — remaining metadata
|
||
|
||
- [ ] `GET /api/gitea/repo/{accId}/{owner}/{repo}/milestones`
|
||
- [ ] `GET /api/gitea/repo/{accId}/{owner}/{repo}/collaborators`
|
||
- [ ] Milestone dropdown in detail view
|
||
- [ ] Assignee multi-select with typeahead
|
||
- [ ] Due date input + clear button
|
||
|
||
## Phase 4 — create issues
|
||
|
||
- [x] **"new issue" button** in the list toolbar
|
||
- [x] **Repo picker** loaded from `/user/repos` (cached per account, filtered
|
||
to non-archived repos with push permission)
|
||
- [x] **Title + body + labels** form
|
||
- [x] **Submit** creates via POST `/repo/{accId}/{owner}/{repo}/issues`,
|
||
refreshes list, auto-opens the new issue in the detail view
|
||
- [ ] **Create from card**: a card → push as new gitea issue, store the
|
||
backref so future edits can sync both ways (Phase 5)
|
||
- [ ] **Pre-fill template** from a repo's `.gitea/ISSUE_TEMPLATE.md`
|
||
if available (next round)
|
||
|
||
## Phase 5 — bidirectional sync (the killer feature)
|
||
|
||
- [ ] When a card has a gitea backref, an "issue" badge appears
|
||
- [ ] Edit the card body in hyprcrd → "push to gitea" button
|
||
- [ ] "pull from gitea" button refreshes the card from the live issue
|
||
- [ ] Conflict detection via `updated_at` timestamps
|
||
- [ ] This replaces the Python tool's `gir push` workflow
|
||
|
||
## Phase 6 — multi-instance + ergonomics
|
||
|
||
- [ ] Account selector remembers last-used account in localStorage
|
||
- [ ] Per-account default filters (e.g. always show `assigned=true`)
|
||
- [ ] Org/repo browsing tree on the left
|
||
- [ ] Label browser per repo
|
||
- [ ] Milestone view
|
||
- [ ] Search across multiple accounts
|
||
|
||
## Hardening
|
||
|
||
- [ ] Rate limiting on test endpoint
|
||
- [ ] Better error messages (currently raw HTTP body leaks through)
|
||
- [ ] Cert pinning option for self-hosted gitea instances
|
||
- [ ] Connection caching (currently every request opens a new cURL handle)
|
||
- [ ] Map common errors (401 → "token expired", 403 → "no access", etc.)
|
||
|
||
## Mapping from the Python tool
|
||
|
||
| Python feature | hyprcrd plan |
|
||
|----------------------------------------|-------------------------------------------|
|
||
| `gi search` | overlay issue list with `q` filter |
|
||
| `gi list --owner --repo` | overlay with owner/repo filter |
|
||
| `gi get` | overlay detail pane |
|
||
| `gi create` | Phase 4 "new issue" button |
|
||
| `gi edit` | Phase 3 detail-pane edit buttons |
|
||
| `gi comment` | Phase 3 comment box in detail pane |
|
||
| `gi comments` | Phase 2 comments rendering |
|
||
| `gir fetch` → markdown files | Phase 2 extract-as-card (no files needed) |
|
||
| `gir push` → sync local edits | Phase 5 bidirectional sync |
|
||
| `gir new --push` | Phase 4 create-from-card |
|
||
| `gir clean` | not needed (cards are managed via the UI) |
|
||
| `_valid-metadata.md` per repo | label/milestone dropdowns at edit time |
|
||
| `templates/gir-new-issue.md` | configurable issue template per account |
|
||
|
||
Once Phase 2–4 are done, the entire `gitea-issue-client/` Python tool
|
||
can be removed from the project root.
|