diff --git a/components/admin/AdminMediaFolderPanel.vue b/components/admin/AdminMediaFolderPanel.vue new file mode 100644 index 0000000..672f012 --- /dev/null +++ b/components/admin/AdminMediaFolderPanel.vue @@ -0,0 +1,170 @@ + + + + + + + diff --git a/docs/map.md b/docs/map.md index 7de2740..0c39430 100644 --- a/docs/map.md +++ b/docs/map.md @@ -190,6 +190,7 @@ | components/admin/AdminSiteCodeSettingsCard.vue | 관리자 사이트 설정의 ads.txt·공통 헤더 코드·공통 푸터 코드 카드 | | components/admin/AdminAdsSettingsCard.vue | 관리자 사이트 설정의 위치별 Ads 코드 카드(메인 피드·메인 인피드·오른쪽 사이드·게시물 오른쪽 사이드·게시물 본문 상단·인아티클·하단) | | components/admin/AdminPostExportFileRow.vue | 관리자 사이트 설정 내보내기 작업의 분할 파일 선택 행 | +| components/admin/AdminMediaFolderPanel.vue | 관리자 미디어 화면의 폴더 사이드바(라이브러리 폴더 트리·폴더별 개수·드래그 드롭 이동·폴더 삭제 메뉴·폴더 추가 버튼·시스템 이미지 탭 안내 패널) | | components/admin/AdminMediaVideoThumbnail.vue | 관리자 미디어 목록 비디오 항목의 초반 프레임 캔버스 썸네일 | | components/admin/AdminPostForm.vue | 관리자 글 작성/수정 폼, Ghost형 툴바(왼쪽 상태 텍스트·Publish/Update/Unpublish/Unschedule, 서버 반영 상태 기준 분기), 초안만 서버 디바운스 자동 저장·자동 저장 실패 payload 반복 재시도 차단·자동 저장 실패/진행 중 이탈 차단·신규 임시 슬러그·중복 슬러그 필드 하단 오류 표시·중복 슬러그 중 Publish/Update/최종 저장 비활성화·저장 중 추가 변경 재자동저장·발행 저장 중 이탈 확인·발행·예약·멤버십·비공개 상태 저장, 미저장 비교에서 태그 표시명 보조값 제외, 공개 상태 전환 시 빈 발행 시각 현재 시각 보정, 발행 모달(중앙 배치), 설정 패널 상태와 이벤트 연결, 미리보기 emit·미저장 이탈 가드, 자동 생성 썸네일을 숨기는 원본 전용 대표 이미지 선택(서버 페이지네이션·파일명/사용처 검색·번호형 페이지 이동·작은 파생 이미지 우선 미리보기·고정 높이 모달), 대표 이미지 본문 상단 표시 토글, 추천 글 토글, 사이트 설정 기준 태그 최대 개수 제한, 태그 색상 배지 다중 입력·최근 사용 태그 5개 우선 추천·메인 태그 드롭다운·부분 검색 추천, 새 태그 입력명 유지와 `/`→`-` 슬러그 변환 | | components/admin/AdminPostSettingsSidebar.vue | 관리자 게시물 작성/수정 우측 설정 사이드바(Post URL·상태·발행 시각·요약·태그·대표 이미지 표시·추천 글·검색엔진 노출·본문 통계·삭제 버튼·블록 설정 패널 오버레이) | diff --git a/docs/todo.md b/docs/todo.md index 2667a0e..72dfe61 100644 --- a/docs/todo.md +++ b/docs/todo.md @@ -5,7 +5,7 @@ - 거대 컴포넌트 책임 분리 진행. - `components/admin/AdminMarkdownEditor.vue`: 미디어 모달, 슬래시 명령, 히스토리·선택 복원, 라이브/소스 전환 로직을 단계적으로 composable 또는 하위 컴포넌트로 분리. - `components/content/ContentMarkdownRenderer.vue`: 파싱·블록 렌더링·라이브 편집 중개·라이트박스·광고 삽입 책임을 분리. - - `pages/admin/media/index.vue`: 미디어 목록, 폴더 트리, 상세 모달, 재생성 액션을 작은 단위로 분리. + - `pages/admin/media/index.vue`: 미디어 목록, 상세 모달, 재생성 액션을 작은 단위로 분리. - 미디어 카탈로그 전환 코드 수명 정리. - 운영 `MEDIA_CATALOG_MODE=database` 안정화 후 `shadow`/`filesystem` 런타임 분기 축소 가능 여부 검토. - fallback은 운영 안정성에 필요하므로 제거 전 reconcile·로그·테스트 기준을 먼저 정리. diff --git a/docs/update.md b/docs/update.md index cc51b7d..0decb7a 100644 --- a/docs/update.md +++ b/docs/update.md @@ -1,5 +1,11 @@ # 업데이트 이력 +## v1.11.44 + +- 관리자 미디어 화면의 폴더 사이드바 렌더링을 `AdminMediaFolderPanel` 컴포넌트로 분리. +- 라이브러리 폴더 트리와 대표·본문·프로필 이미지 탭 안내 패널 표시 책임을 하위 컴포넌트로 이동. +- 미디어 화면은 폴더 목록 계산·선택·드롭·삭제·생성 액션 연결만 담당하도록 정리. + ## v1.11.43 - 관리자 게시물 폼의 우측 설정 패널 렌더링을 `AdminPostSettingsSidebar` 컴포넌트로 분리. diff --git a/package-lock.json b/package-lock.json index 1f824c1..4123a3b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "sori.studio", - "version": "1.11.43", + "version": "1.11.44", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "sori.studio", - "version": "1.11.43", + "version": "1.11.44", "hasInstallScript": true, "dependencies": { "@nuxtjs/tailwindcss": "^6.14.0", diff --git a/package.json b/package.json index 10f80ae..37e9edd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "sori.studio", - "version": "1.11.43", + "version": "1.11.44", "private": true, "type": "module", "imports": { diff --git a/pages/admin/media/index.vue b/pages/admin/media/index.vue index 9b61ebb..1f24d9d 100644 --- a/pages/admin/media/index.vue +++ b/pages/admin/media/index.vue @@ -36,13 +36,6 @@ const memberRoleBadgeLabels = { member: '멤버' } -/** - * 논리 폴더 경로가 썸네일 전용 루트인지 확인한다. - * @param {string} folder - 폴더 경로 - * @returns {boolean} 썸네일 전용이면 true - */ -const isThumbnailFolderPath = (folder) => folder === MEDIA_THUMBNAIL_ROOT || String(folder).startsWith(`${MEDIA_THUMBNAIL_ROOT}/`) - const activeTab = ref('library') const searchText = ref('') const { @@ -83,13 +76,6 @@ const { toast, showToast } = useAdminToast() const { openMenuId, closeMenu } = useAdminRowMenu() -/** - * 폴더 행 메뉴 id - * @param {string} folder - 폴더 경로 - * @returns {string} - */ -const getFolderMenuId = (folder) => `folder:${folder}` - const mediaQuery = computed(() => ({ paged: '1', tab: activeTab.value, @@ -712,20 +698,6 @@ const formatFileSize = (size) => { return `${(size / 1024 / 1024).toFixed(1)} MB` } -/** - * 폴더 경로의 표시 이름 조회 - * @param {string} folder - 폴더 경로 - * @returns {string} 표시 이름 - */ -const getFolderName = (folder) => folder.split('/').filter(Boolean).pop() || '미분류' - -/** - * 폴더 깊이 조회 - * @param {string} folder - 폴더 경로 - * @returns {number} 폴더 깊이 - */ -const getFolderDepth = (folder) => Math.max(folder.split('/').filter(Boolean).length - 1, 0) - /** * 미디어 선택 여부 확인 * @param {Object} item - 미디어 항목 @@ -1433,90 +1405,22 @@ watch(() => mediaPagination.value.page, (page) => {