From 1ce7f2ec6fac26a3088e8a98d559595562c79131 Mon Sep 17 00:00:00 2001 From: Nathan Huh Date: Wed, 25 Mar 2026 10:21:09 +0900 Subject: [PATCH] docs: add M5 (UI beautification) and M6 (search/filter) milestones MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add M5 milestone: file extraction of app.go, bubbles components (textinput, spinner, table), enhanced lipgloss styles - Add M6 milestone: fuzzy matching via sahilm/fuzzy, match highlighting, universal filter on all list views, unified Filterable architecture - Update M4.1 to cross-reference moved items (spinners → M5.3, fuzzy → M6) - Update implementation order diagram with M5/M6 - Update architecture docs (EN/KR): RDS status to implemented, add Planned Improvements section - Update project overview docs (EN/KR): note planned bubbles and fuzzy deps --- .kiro/docs/architecture-en.md | 21 +++++++- .kiro/docs/architecture.md | 21 +++++++- .kiro/steering/project-overview-en.md | 5 +- .kiro/steering/project-overview.md | 5 +- PLAN.md | 74 +++++++++++++++++++++++++-- 5 files changed, 117 insertions(+), 9 deletions(-) diff --git a/.kiro/docs/architecture-en.md b/.kiro/docs/architecture-en.md index 6747501..727b9bc 100644 --- a/.kiro/docs/architecture-en.md +++ b/.kiro/docs/architecture-en.md @@ -163,10 +163,29 @@ unic init --force # Overwrite existing config file |---------|---------|--------| | EC2 | SSM Session Manager (connect to EC2 instances) | ✅ Implemented | | VPC | VPC Browser (VPCs → subnets → available IPs) | ✅ Implemented | -| RDS | ListDBInstances | 🚧 Coming Soon | +| RDS | RDS Browser (list, detail, start/stop/failover) | ✅ Implemented | | Route53 | ListHostedZones | 🚧 Coming Soon | | IAM | ListUsers | 🚧 Coming Soon | +## Planned Improvements + +### M5 — UI Beautification (Charmbracelet Ecosystem) + +- **File extraction**: Split `internal/app/app.go` (~1700 lines) into `styles.go`, `views.go`, `commands.go`, `filter.go` +- **bubbles components**: Add `bubbles/textinput` (filter input), `bubbles/spinner` (loading), `bubbles/table` (context picker) +- **Enhanced styles**: Bordered list views, full-width status bar, consistent label alignment, styled help bar +- Dependency: `github.com/charmbracelet/bubbles` + +### M6 — Search/Filter for Long Lists + +- **Fuzzy matching**: Replace `strings.Contains` with `sahilm/fuzzy` for scored fuzzy search +- **Match highlighting**: Bold + orange on matched characters in list items +- **Universal filter**: Add "/" filter to all list views (VPC list and subnet list currently missing) +- **Unified architecture**: `Filterable` interface + generic `applyFuzzyFilter[T]()` to eliminate per-screen duplication +- Dependency: `github.com/sahilm/fuzzy` + +See `PLAN.md` for full milestone details and implementation order. + ## New Feature Addition Checklist 1. `internal/domain/model.go` → Add `AwsService` and `FeatureKind` string constants diff --git a/.kiro/docs/architecture.md b/.kiro/docs/architecture.md index de5274b..f209e25 100644 --- a/.kiro/docs/architecture.md +++ b/.kiro/docs/architecture.md @@ -163,10 +163,29 @@ unic init --force # 기존 설정 파일 덮어쓰기 |--------|------|------| | EC2 | SSM Session Manager (EC2 인스턴스 접속) | ✅ 구현 완료 | | VPC | VPC Browser (VPC → 서브넷 → 가용 IP) | ✅ 구현 완료 | -| RDS | ListDBInstances | 🚧 Coming Soon | +| RDS | RDS Browser (목록, 상세, 시작/중지/장애조치) | ✅ 구현 완료 | | Route53 | ListHostedZones | 🚧 Coming Soon | | IAM | ListUsers | 🚧 Coming Soon | +## 계획된 개선 사항 + +### M5 — UI 개선 (Charmbracelet 생태계) + +- **파일 분리**: `internal/app/app.go` (~1700줄)를 `styles.go`, `views.go`, `commands.go`, `filter.go`로 분리 +- **bubbles 컴포넌트**: `bubbles/textinput` (필터 입력), `bubbles/spinner` (로딩), `bubbles/table` (컨텍스트 선택기) 추가 +- **스타일 강화**: 테두리가 있는 목록 뷰, 전체 너비 상태 바, 일관된 레이블 정렬, 스타일 적용된 도움말 바 +- 의존성: `github.com/charmbracelet/bubbles` + +### M6 — 긴 목록 검색/필터 + +- **퍼지 매칭**: `strings.Contains`를 `sahilm/fuzzy`로 교체하여 점수 기반 퍼지 검색 구현 +- **매칭 하이라이트**: 매칭된 문자에 굵은체 + 주황색 스타일 적용 +- **전체 필터 지원**: 모든 목록 뷰에 "/" 필터 추가 (현재 VPC 목록, 서브넷 목록에 미지원) +- **통합 아키텍처**: `Filterable` 인터페이스 + 제네릭 `applyFuzzyFilter[T]()` 로 화면별 중복 제거 +- 의존성: `github.com/sahilm/fuzzy` + +자세한 마일스톤 및 구현 순서는 `PLAN.md` 참조. + ## 새 기능 추가 체크리스트 1. `internal/domain/model.go` → `AwsService`, `FeatureKind` 문자열 상수 추가 diff --git a/.kiro/steering/project-overview-en.md b/.kiro/steering/project-overview-en.md index dffe335..fcfd5c0 100644 --- a/.kiro/steering/project-overview-en.md +++ b/.kiro/steering/project-overview-en.md @@ -9,9 +9,10 @@ UNIC is a Go-based TUI (Terminal User Interface) tool for browsing and managing ## Tech Stack - Language: Go (1.22+) -- TUI Framework: Bubbletea + Lipgloss + Bubbles +- TUI Framework: Bubbletea + Lipgloss + Bubbles (planned: bubbles/textinput, bubbles/spinner, bubbles/table) +- Search: sahilm/fuzzy (planned — M6 fuzzy search/filter) - CLI Parser: Cobra -- AWS SDK: aws-sdk-go-v2 (ec2, ssm, sts) +- AWS SDK: aws-sdk-go-v2 (ec2, rds, ssm, sts, sso, ssooidc) - Config: gopkg.in/yaml.v3 (YAML-based) - Concurrency: goroutines + errgroup - Error Handling: fmt.Errorf wrapping / standard errors package diff --git a/.kiro/steering/project-overview.md b/.kiro/steering/project-overview.md index 2d74654..5c48d9e 100644 --- a/.kiro/steering/project-overview.md +++ b/.kiro/steering/project-overview.md @@ -9,9 +9,10 @@ UNIC은 Go 기반 TUI(Terminal User Interface) 도구로, AWS 리소스를 탐 ## 기술 스택 - 언어: Go (1.22+) -- TUI 프레임워크: Bubbletea + Lipgloss + Bubbles +- TUI 프레임워크: Bubbletea + Lipgloss + Bubbles (계획: bubbles/textinput, bubbles/spinner, bubbles/table) +- 검색: sahilm/fuzzy (계획 — M6 퍼지 검색/필터) - CLI 파서: Cobra -- AWS SDK: aws-sdk-go-v2 (ec2, ssm, sts) +- AWS SDK: aws-sdk-go-v2 (ec2, rds, ssm, sts, sso, ssooidc) - 설정 파일: gopkg.in/yaml.v3 (YAML 기반) - 동시성: goroutines + errgroup - 에러 처리: fmt.Errorf 래핑 / 표준 errors 패키지 diff --git a/PLAN.md b/PLAN.md index 49cc59a..bc5a090 100644 --- a/PLAN.md +++ b/PLAN.md @@ -157,9 +157,9 @@ unic/ **M4.1 — UX** - Keyboard shortcut help screen (`?` key) -- Fuzzy search/filter on all list views -- Loading spinners for async operations - Color theme (respect terminal colors via Lipgloss) +- ~~Fuzzy search/filter on all list views~~ → moved to M6 +- ~~Loading spinners for async operations~~ → moved to M5.3 **M4.2 — Error Handling & Logging** - Structured error messages with actionable hints @@ -174,6 +174,66 @@ unic/ --- +### M5 — UI Beautification (Charmbracelet Ecosystem) + +Prerequisite: `go get github.com/charmbracelet/bubbles` + +**M5.1 — File Extraction (no behavior change)** +- Split `internal/app/app.go` (~1700 lines) into focused files: + - `styles.go` — all lipgloss style vars + new styles + - `views.go` — all `view*()` methods + `renderStatusBar()` + - `commands.go` — all `tea.Cmd` functions (`load*`, `execute*`, `poll*`, etc.) + - `filter.go` — filter logic (`applyFilter`, `applyRDSFilter`, `applyIPFilter`) +- `app.go` retains: Model struct, `New()`, `Init()`, `Update()`, and all `update*()` methods + +**M5.2 — bubbles/textinput for Filter** +- Replace manual character-by-character filter input with a single shared `textinput.Model` +- On "/" key → `filterTI.Focus()`, on esc/enter → `filterTI.Blur()` +- Check `filterTI.Focused()` instead of `filterActive` booleans +- Remove: `filterInput`, `filterActive`, `rdsFilter`, `rdsFilterActive`, `ipFilter`, `ipFilterActive` + +**M5.3 — bubbles/spinner for Loading** +- Replace static `"Loading..."` with animated spinner (`spinner.MiniDot`) +- Start spinner tick on entering `screenLoading`, ignore ticks elsewhere + +**M5.4 — bubbles/table for Context Picker** +- Convert manual column-aligned context picker to `bubbles/table` +- Columns: Name, Region, Auth, Current (*) +- Keep "a" key shortcut for adding contexts + +**M5.5 — Enhanced Lipgloss Styles** +- Status bar: full-width via `lipgloss.Width(m.width)`, left/right split with `JoinHorizontal` +- List views: wrap content in `lipgloss.RoundedBorder()` box +- Detail views: consistent label alignment with `lipgloss.NewStyle().Width(14)` +- Help bar: consistent `helpStyle` across all screens + +--- + +### M6 — Search/Filter for Long Lists + +Prerequisite: `go get github.com/sahilm/fuzzy` + +**M6.1 — Fuzzy Matching** +- Replace `strings.Contains` filter logic with `sahilm/fuzzy` scored fuzzy matching +- Match against `DisplayTitle()` for both filtering and highlighting +- Sort results by score descending + +**M6.2 — Match Highlighting** +- Highlight matched characters with bold + orange (color 214) style +- Use match indices from fuzzy library to render per-character styling + +**M6.3 — Filter on All List Views** +- Add "/" filter to VPC list and subnet list (currently missing) +- All filterable items already implement `FilterText()` and `DisplayTitle()` + +**M6.4 — Unified Filter Architecture** +- Define `Filterable` interface: `FilterText() string`, `DisplayTitle() string` +- Implement generic `applyFuzzyFilter[T Filterable](items []T, query string) []filterMatch[T]` +- Store `matchIndices [][]int` parallel to filtered slices for highlighting +- Eliminate per-screen filter state duplication + +--- + ## Implementation Order ``` @@ -182,12 +242,20 @@ M1.1 → M1.2 → M2.1 → M2.2 → M2.3 → M2.4 M3.1 ~ M3.8 (independent, any order) ↓ M4.1 → M4.2 → M4.3 + ↓ + M5.1 → M5.2 ~ M5.5 + ↓ + M6.1 ~ M6.4 ``` +Note: M5.2 (textinput) provides the foundation for M6 (enhanced search) — they converge naturally. + - M1 is complete; M2 is deferred (relying on AWS SDK default credential chain) +- M2.1 (Context-based auth with SSO, credential, assume-role) is complete - M3 services are independent of each other, build in any order -- M3.1 (VPC) and M3.4 (SSM Sessions) are complete +- M3.1 (VPC), M3.2 (RDS), and M3.4 (SSM Sessions) are complete - M4.3 (Distribution) is partially done (GoReleaser + GitHub Actions) +- M5 and M6 can begin independently of remaining M3/M4 work ---