v1.12.24 멤버 작성 이력 통합 표 및 종류 필터 추가

This commit is contained in:
2026-10-21 17:03:07 +09:00
parent 7c95797fd2
commit 93dc6c04bd
13 changed files with 229 additions and 73 deletions

View File

@@ -1,3 +1,7 @@
## 2026-10-21 v1.12.24 — 멤버 작성 이력은 종류 필터가 있는 통합 표로 표시한다
멤버의 게시글과 댓글은 작성한 글 탭 하나에서 종류 열로 구분한다. 대시보드처럼 작성 대상·작성자·시각·내용을 한 줄로 표시해 여러 활동을 빠르게 훑도록 한다. 두 종류를 브라우저에서 따로 조회·합치면 전체 페이지와 최신순 정렬이 틀어질 수 있으므로 서버에서 작성자 조건을 적용한 게시글·댓글을 합친 뒤 종류 필터·검색·전체 건수·페이지를 계산한다. 기존 개별 API는 호환을 유지한다.
## 2026-10-21 v1.12.23 — 대시보드는 최근 활동 요약, 멤버 이력은 탭으로 나눈다
대시보드는 새 댓글의 게시물·작성자·시각을 빠르게 파악하도록 최근 댓글을 작은 한 줄 목록으로 줄이고 CSP 관찰 표와 주기 조회를 제거한다. 이는 관리자 화면 정리이며, 제공된 누적 보고로 보안 정책 강화 여부를 확정한 결정은 아니다. 기존 수집·집계와 보안 헤더는 유지한다.

View File

@@ -312,7 +312,7 @@
| components/admin/AdminMarkdownEditor.vue | 관리자 글 Markdown-first 에디터, 라이브·소스 모드 `/` 슬래시 명령(`/표` 기본 표 템플릿 포함, 후보 없는 슬래시 입력은 일반 줄바꿈·커서 이동 허용)·미디어 모달 선택 결과 본문 삽입(이미지·갤러리·비디오·오디오·파일), 코드 블록 본문 슬래시 명령 비활성화, 커서 블록 컨텍스트·선택 텍스트 색상 컨텍스트 `block-panel` emit, 소스 모드 입력 직후 textarea 최신 본문 기준 커서 논리 줄·블록 컨텍스트 갱신, 에디터 본문 `Cmd/Ctrl+Z` 히스토리와 선택 위치 복원, 라이브 이미지 설정 패널·이미지↔갤러리 드래그 변환(`merge-images-to-gallery`·`insert-image-to-gallery`·`extract-gallery-image`), 소스·라이브 `Cmd+Shift+K` 줄 삭제, 소스·라이브 `Cmd/Ctrl+K` 링크 삽입, 코드·콜아웃·토글 내부 줄 삭제, 라이브 fenced 블록 현재 닫는 줄 기준 교체, 블록 패널 바깥 클릭·지원 블록 밖 커서 이동 시 닫기·미디어 모달 중 유지, 슬래시 메뉴 위치·슬래시 명령 실행·공통 포커스·블록 패널 옵션 적용·라이브 미리보기 이벤트 적용 composable 연결, 인용 마지막 줄 아래 방향키 외부 문단 포커스 이동, 인용·콜아웃·코드·토글 선언 줄 옵션 수정, IME 조합 중 현재 블록 범위 안에서만 블록 패널 유지, 소스 모드 wrap 라인 번호 보정·라이브↔소스 위치 복원(코드·콜아웃·토글 선언 줄은 본문 줄로 보정), 라이브 슬래시 명령 후 포커스 복원 지연·미디어 명령 원문 줄 재반영 방지 |
| components/admin/AdminEditorBlockPanel.vue | 게시물 설정 사이드바 오버레이 블록 설정(선택 텍스트 색상, 단일 이미지 대표 너비 셀렉트(전체·갤러리 2장 1칸·갤러리 3장 1칸·갤러리 3장 2칸·직접 입력)·직접 너비·이미지·갤러리·링크·iframe·HTML·인용 배경색·콜아웃 제목·아이콘 ON/OFF 토글·비활성 아이콘 영역·배경색·코드 언어 셀렉트·줄번호 ON/OFF 토글·토글), 갤러리 선택 이미지 강조 |
| components/admin/AdminTagForm.vue | 관리자 태그 생성/수정 폼(이름/슬러그/설명/색상, 태그 헤더 이미지 업로드·삭제, 오버레이 제목·본문 편집, 수정 화면 변경 저장 버튼 변경사항 기준 활성화) |
| components/admin/AdminMemberForm.vue | 관리자 멤버 추가/수정 폼(Ghost형 3분할, 기존 회원 보기/수정 모드 분리, 요약 1fr·입력 2fr, 원형 썸네일 hover 등록·변경·삭제, 기본 정보·레이블·관리자 노트·Google 로그인 연동 상태·활동 요약·정보/작성한 글/작성한 댓글 탭·전체 이력 검색 및 번호형 페이지네이션, 설정 메뉴의 비밀번호 변경·멤버 삭제 모달, 소유자 전용 Google 연동 해제 모달, 저장 토스트, 미저장 변경사항 이탈 확인) |
| components/admin/AdminMemberForm.vue | 관리자 멤버 추가/수정 폼(Ghost형 3분할, 기존 회원 보기/수정 모드 분리, 요약 1fr·입력 2fr, 원형 썸네일 hover 등록·변경·삭제, 기본 정보·레이블·관리자 노트·Google 로그인 연동 상태·활동 요약·정보/작성한 글 탭·게시글/댓글 통합 표·종류 필터·검색 및 번호형 페이지네이션, 설정 메뉴의 비밀번호 변경·멤버 삭제 모달, 소유자 전용 Google 연동 해제 모달, 저장 토스트, 미저장 변경사항 이탈 확인) |
| components/admin/AdminUnsavedChangesModal.vue | 관리자 편집 화면 공통 미저장 변경사항 이탈 확인 모달(상단 40px 위치) |
| components/admin/AdminConfirmModal.vue | 관리자 공통 확인 모달(제목·본문 슬롯·확인/취소 버튼, primary/danger 톤) |
| components/admin/AdminModalFrame.vue | 관리자 공통 일반 모달 프레임(오버레이, dialog 접근성 속성, 기본 패널 스타일, 바깥 클릭 닫기) |
@@ -641,6 +641,8 @@
| components/admin/AdminCommentList.vue | 대시보드 최신 댓글 5개 작은 목록·게시글/작성자/시각/한 줄 내용·30초 갱신·조회 오류 재시도 |
| server/routes/admin/api/comments.get.js | 관리자 댓글 조회 인증·댓글 내용/게시물 제목 검색·Zod query 검증 |
| server/repositories/comment-repository.js | 공개 댓글 조회·작성·좋아요와 관리자 댓글 최신순 페이지 조회 |
| tests/playwright/e2e/admin-comments.spec.js | 멤버 정보/작성 글/댓글 탭·검색·페이지 이동·원문 링크·작은 대시보드 댓글·CSP 제거·게시글 댓글 수 E2E 검증 |
| components/admin/AdminMemberActivityList.vue | 회원별 작성 글·댓글 탭의 전체 이력 최신순 검색·번호형 페이지네이션·게시물 이동 |
| tests/playwright/e2e/admin-comments.spec.js | 멤버 통합 작성 이력 표·전체/댓글/게시글 필터·검색·페이지 이동·원문 링크·작은 대시보드 댓글·CSP 제거·게시글 댓글 수 E2E 검증 |
| components/admin/AdminMemberActivityList.vue | 회원별 게시글·댓글 통합 한 줄 표·종류 필터·전체 이력 최신순 검색·번호형 페이지네이션·게시물 이동 |
| server/routes/admin/api/members/[id]/posts.get.js | 관리자 회원 작성 글 조회 인증·Zod 검증·검색·페이지 API |
| server/repositories/member-activity-repository.js | 회원별 게시글·댓글 통합 최신순 검색·종류 필터·전체 건수 및 페이지 조회 |
| server/routes/admin/api/members/[id]/activity.get.js | 관리자 회원 통합 작성 이력 인증·Zod 조건 검증 API |

View File

@@ -1089,15 +1089,21 @@ APP_PORT=43080
- 첫 커밋 이후 변경사항을 커밋할 때마다 패치 버전 증가
- 메이저/마이너 버전은 구조 변경 또는 기능 묶음 단위로 결정
## 관리자 댓글·회원 작성 이력 조회 (v1.12.23)
## 관리자 댓글·회원 작성 이력 조회 (v1.12.24)
- `GET /admin/api/comments`: 관리자 세션 필수. `memberId`(선택 UUID), `q`(기본 빈 문자열, trim, 최대 200자, 댓글 내용·게시물 제목 부분 검색), `page`(기본 1, 1~1000000 정수), `pageSize`(기본 10, 1~100 정수). 잘못된 조건은 400, 미인증은 401.
- 응답 `{ items, pagination: { page, pageSize, total, pageCount } }`. 항목은 `id`, `body`, `status`, `parentId`, `createdAt`, `userId`, `username`, `postId`, `postTitle`, `postSlug`, `postStatus` 제공. 모든 상태의 댓글·답글 포함, 작성 시각·ID 내림차순. 범위 초과 페이지는 마지막 페이지로 보정.
- 멤버 상세는 `정보 / 작성한 글 / 작성한 댓글` 탭을 제공하며 정보로 진입한다. 정보 편집값은 탭 이동 시 유지한다. 이력은 선택한 탭에서만 조회하고, 10개씩 번호형 페이지네이션·검색 버튼/Enter로 검색한다. 검색 시 첫 페이지로 돌아가며 최신 작성순으로 전체 이력을 조회한다.
- 멤버 상세는 `정보 / 작성한 글` 탭을 제공하며 정보로 진입한다. 정보 편집값은 탭 이동 시 유지한다. 작성한 글 탭에서 게시글·댓글 전체 이력을 `구분 / 게시글 / 작성자 / 작성일 / 내용` 한 줄 표로 통합 표시한다. 긴 제목·내용은 말줄임과 title로 표시하며 좁은 화면은 표 내부 가로 스크롤을 제공한다.
- 상단 `전체 / 댓글 / 게시글` 종류 필터와 검색 버튼/Enter 검색을 제공한다. 검색·종류 변경 시 첫 페이지로 돌아가며 10개씩 번호형 페이지네이션으로 최신순 전체 이력을 조회한다.
- 대시보드는 최신 댓글 5개를 30초마다 갱신한다. 게시물·작성자·짧은 시각·말줄임 한 줄 내용만 작은 행으로 표시한다. 조회 오류는 재시도하며 이력 조회 중은 로딩 표시.
- 댓글 내용은 일반 텍스트로 표시. 작성자는 멤버 상세, 게시물 제목은 관리자 편집으로 이동. 공개·멤버십 글은 새 창의 `/post/:slug#comments` 링크 제공(공개 화면의 기존 접근 권한 적용).
- 댓글 내용은 일반 텍스트로 표시한다. 대시보드 작성자는 멤버 상세로 이동한다. 통합 표의 게시글 제목은 `publicUrl`이 있으면 새 창의 공개 화면으로, 없으면 관리자 편집으로 이동한다(공개 화면의 기존 접근 권한 적용).
- 게시글 목록 댓글 열은 기존 `commentCount` 사용. 공개 상태 댓글·답글만 집계.
- `GET /admin/api/members/:id/posts`: 관리자 세션 필수. 회원 UUID와 `q`(trim, 최대 200자), `page`(1~1000000, 기본 1), `pageSize`(1~100, 기본 10) 검증. 잘못된 조건 400, 미인증 401.
- 작성 글은 `posts.author_id`로 필터하고 초안·비공개·멤버십·공개 전체 포함, `created_at DESC, id DESC` 순서. `q`는 제목·주소·요약·본문의 문자 그대로 부분 검색이며 댓글 검색도 `%`, `_`를 와일드카드로 취급하지 않는다.
- 작성 글 응답 `{ items: [{ id, title, slug, status, createdAt, publishedAt }], pagination: { page, pageSize, total, pageCount } }`. 범위 초과 페이지는 마지막으로 보정하고 미작성·검색 결과 없음은 빈 목록 반환.
- `GET /admin/api/members/:id/activity`: 관리자 회원 통합 작성 이력 조회. `memberId` UUID, `type`은 `all`(기본)/`post`/`comment`, `q`(trim, 최대 200자), `page`(기본 1, 1~1000000), `pageSize`(기본 10, 1~100). 미인증 401, 잘못된 조건 400.
- 게시글(`posts.author_id`)과 댓글·답글(`comments.user_id`)을 `UNION ALL`로 합쳐 `createdAt DESC, kind ASC, id DESC`로 정렬한 뒤 전체 건수·페이지를 계산한다. 검색은 게시글 제목·주소·요약·본문 또는 댓글 내용·대상 게시글 제목의 문자 그대로 부분 검색. 모든 상태를 포함하며 초과 페이지는 마지막 페이지로 보정한다.
- 응답 `{ items: [{ kind, id, postId, postTitle, postSlug, postStatus, publishedAt, createdAt, username, body, publicUrl }], pagination: { page, pageSize, total, pageCount } }`. `kind`는 `post`/`comment`. 게시글 body는 최대 320자 일반 텍스트 요약, 댓글은 원문 텍스트. 공개 접근 가능한 게시글은 `publicUrl` 제공(댓글은 `#comments`), 초안·비공개·예약 글은 null이며 관리자 편집으로 이동.
- 기존 `/admin/api/comments`, `/admin/api/members/:id/posts` 응답 계약은 유지하며 멤버 작성한 글 화면은 통합 `/activity`를 사용한다.

View File

@@ -4,7 +4,7 @@
## 2차 관리자 개발
- `npm run test:api`의 기존 미디어 카탈로그 회귀 실패 조사: `core-api.spec.js`의 프로필 이미지 `usage`에 `type=user`가 없어 `typeLabel` 확인 실패. 댓글·회원 작성 글 검색/페이지 API 검증은 통과. 격리 DB에서 사용처 계산·카탈로그 캐시 반영 순서 확인.
- `npm run test:api`의 기존 미디어 카탈로그 회귀 실패 조사: `core-api.spec.js`의 프로필 이미지 `usage`에 `type=user`가 없어 `typeLabel` 확인 실패. 댓글·회원 통합 작성 이력 검색/페이지 API 검증은 통과. 격리 DB에서 사용처 계산·카탈로그 캐시 반영 순서 확인.
## 프론트엔드 개발

View File

@@ -1,5 +1,14 @@
# 업데이트 이력
## v1.12.24
- 멤버 작성 글·댓글 탭을 작성한 글 탭 하나로 통합.
- 구분·게시글·작성자·작성일·한 줄 내용 표와 전체/댓글/게시글 필터 추가.
- 게시글·댓글 통합 최신순 검색·페이지 조회 API와 검색·필터 변경 시 첫 페이지 조회 추가.
- 통합 정렬·작성자 격리·종류 필터·검색·페이지 이동 API/E2E 검증 보강.
- JavaScript 문법 검사·단위 테스트 273건·프로덕션 빌드·Chromium E2E 11건 검증 진행.
- API 통합 검증 11건 통과, 기존 미디어 사용처 검증 실패 1건·후속 미실행 1건 유지.
## v1.12.23
- 대시보드 CSP 관찰 표·조회·자동 갱신 제거.