From 92ae5756465f033ee71882784806ea27c4687034 Mon Sep 17 00:00:00 2001 From: hehih Date: Sat, 30 May 2026 22:02:10 +0900 Subject: [PATCH] docs: add dashboard full-set enhancement spec --- .claude/settings.local.json | 3 +- .../2026-05-30-dashboard-fullset-design.md | 80 +++++++++++++++++++ 2 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 docs/superpowers/specs/2026-05-30-dashboard-fullset-design.md diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 4157904..f99c0f7 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -13,7 +13,8 @@ "Bash(git -c user.name=\"hehih\" -c user.email=\"hehihoho86@gmail.com\" commit -q -m \"docs: add discovery page design spec\")", "Bash(git -c user.name=\"hehih\" -c user.email=\"hehihoho86@gmail.com\" commit -q -m \"docs: add discovery page implementation plan\")", "PowerShell($env:JAVA_HOME=\"D:\\\\Development\\\\app\\\\JDK\\\\jdk-21.0.5\"; .\\\\gradlew.bat clean compileJava --console=plain 2>&1 | Select-Object -Last 12)", - "Bash(git -c user.name=hehih -c user.email=hehihoho86@gmail.com commit -q -m 'feat\\(discover\\): add discovery page for finding rework candidates *)" + "Bash(git -c user.name=hehih -c user.email=hehihoho86@gmail.com commit -q -m 'feat\\(discover\\): add discovery page for finding rework candidates *)", + "Bash(git -c user.name=\"hehih\" -c user.email=\"hehihoho86@gmail.com\" commit -q -m \"docs: add dashboard full-set enhancement spec\")" ] } } diff --git a/docs/superpowers/specs/2026-05-30-dashboard-fullset-design.md b/docs/superpowers/specs/2026-05-30-dashboard-fullset-design.md new file mode 100644 index 0000000..f106ef3 --- /dev/null +++ b/docs/superpowers/specs/2026-05-30-dashboard-fullset-design.md @@ -0,0 +1,80 @@ +# 대시보드 풀세트 강화 — 설계 + +작성일: 2026-05-30 +상태: 승인됨 (구현 대기) + +## 목적 + +홈 대시보드에서 파이프라인 전체(수집→큐레이션→재가공→발행)를 한눈에 본다. +현재 빠진 **완료(DONE)·발행(publish) 현황·카테고리 분포**를 채우고 단계별 흐름을 시각화한다. + +## 제약 / 비범위 + +- **시계열 추이 없음**: `ChannelVideo`에 수집 시각 필드가 없어(있는 건 영상 업로드일 `publishedAt`) "날짜별 수집량" 차트는 만들지 않는다. "현재 스냅샷" 중심. +- AI/외부 호출 없음. +- 차트 라이브러리 추가 없음 — 막대는 CSS(div 너비 %)로 그린다. (채널 성장 차트가 쓰는 Chart.js는 CDN으로 이미 있으나 대시보드엔 도입 안 함, YAGNI.) + +## 현재 상태 + +- `dashboard.html`: KPI 카드 3개(수집 총계/TARGET/NEW) + 떡상 후보 TOP5 + 수집 출처. `/api/v1/channel-videos/stats`·`/outperformers` 를 각각 fetch. +- `pipelineStats()`(curation): `total`, `byStatus`(NEW/REVIEWING/TARGET/DONE/EXCLUDED), `bySource`(CHANNEL/SEARCH) 반환. +- 발행/카테고리 집계는 대시보드에 없음. + +## 화면 구성 (dashboard.html 재작성) + +1. **KPI 카드 5개**: 수집 총계 · 미검토(NEW) · 작업대상(TARGET) · **완료(DONE)** · **발행완료(PUBLISHED)**. (뒤 2개 신규) +2. **파이프라인 깔때기**: `수집 → 검토중 → 작업대상 → 완료 → 발행완료` 가로 막대(각 단계 너비 = 총계 대비 %). 제외(EXCLUDED)는 깔때기 밖 작은 뱃지로 별도 표기. +3. **2단**: 떡상 후보 TOP5(기존 유지) | **발행 현황**(DRAFT/READY/PUBLISHED 카운트 막대 + 최근 5건 목록). +4. **2단**: **카테고리 분포**(카테고리 색상 막대 + 건수 + 총계 대비 %, 미분류 포함) | **수집 출처 & 포맷**(채널/검색 + Shorts/롱폼 비율). + +전체는 **단일 호출** `GET /api/dashboard/summary` 로 받아 렌더(현재의 다중 fetch 제거). + +## 백엔드 + +### 단위와 책임 + +1. **`ChannelVideoRepository`** (수정) — 카운트 2개 추가: + - `long countByIsShortsTrue();` + - `long countByCategoryIdIsNull();` +2. **`PublishPackageRepository`** (수정) — `long countByStatus(String status);` +3. **`ChannelVideoCurationService.pipelineStats()`** (수정) — 기존 반환에 `shorts`(Shorts 수), `longForm`(total - shorts) 키 추가. (기존 키 유지 → 보드 등 하위호환) +4. **`CategoryService.distribution()`** (신규) — `Map`: `categories`=[{id,name,color,count}], `uncategorized`=미분류 수. (이미 `categoryRepository` + `channelVideoRepository` 보유) +5. **`PublishService.dashboardSummary()`** (신규) — `Map`: `byStatus`={DRAFT,READY,PUBLISHED}, `recent`=최신 5건(`list(null)` 앞 5개). +6. **`DashboardService.summary()`** (신규, `service` 패키지) — 위 서비스들을 조합해 하나의 `Map` 반환: + ``` + { pipeline: pipelineStats(), // total, byStatus, bySource, shorts, longForm + categories: categoryService.distribution(), + publish: publishService.dashboardSummary(), + outperformers: curationService.findOutperformers(5, BigDecimal.ONE) } + ``` + 의존: `ChannelVideoCurationService`, `CategoryService`, `PublishService` (서비스만 조합, 리포지토리 직접 접근 없음). +7. **`DashboardApiController`** (신규, `web` 패키지) — `GET /api/dashboard/summary` → `ApiResponse>`. + +## 데이터 흐름 + +``` +dashboard.html (진입) + → GET /api/dashboard/summary + → DashboardService.summary() + ├ curationService.pipelineStats() (+shorts/longForm) + ├ categoryService.distribution() + ├ publishService.dashboardSummary() + └ curationService.findOutperformers(5, 1) + → KPI/깔때기/떡상/발행/카테고리/출처 렌더 +``` + +## 에러 / 빈 상태 + +- summary 호출 실패: 각 섹션에 "불러오기 실패" 표시(현재 dashboard.html 의 try/catch 패턴 유지, 단 단일 호출). +- 데이터 0: 깔때기·분포는 0% 막대 + "아직 데이터가 없습니다" 류 안내. 떡상 0건은 기존 문구 유지. +- 백필 안 된 옛 영상으로 `shorts`/비율이 0이어도 화면은 정상(0 표기). + +## 검증 방법 + +테스트 인프라가 없으므로(기존 관행) `compileJava` + `bootRun` 기동(빈/쿼리 에러 0건) + (UI 수동 확인은 사용자가 나중에 일괄). + +## 영향 / 변경 파일 요약 + +신규: `DashboardService`, `DashboardApiController`, 스펙 문서. +수정: `ChannelVideoRepository`(count 2), `PublishPackageRepository`(count 1), `ChannelVideoCurationService`(pipelineStats 확장), `CategoryService`(distribution 추가), `PublishService`(dashboardSummary 추가), `dashboard.html`(재작성). +기존 페이지/엔드포인트(보드·수집함·발굴 등)는 영향 없음.