Files
document-server/backend/database/migrations/006_add_canonical_path.sql
hyungi cfb9485d4f 🚀 배포용: PDF 뷰어 개선 및 서적별 UI 데본씽크 스타일 적용
 주요 개선사항:
- PDF API 500 에러 수정 (한글 파일명 UTF-8 인코딩 처리)
- PDF 뷰어 기능 완전 구현 (PDF.js 통합, 네비게이션, 확대/축소)
- 서적별 문서 그룹화 UI 데본씽크 스타일로 개선
- PDF Manager 페이지 서적별 보기 기능 추가
- Alpine.js 로드 순서 최적화로 JavaScript 에러 해결

🎨 UI/UX 개선:
- 확장/축소 가능한 아코디언 스타일 서적 목록
- 간결하고 직관적인 데본씽크 스타일 인터페이스
- PDF 상태 표시 (HTML 연결, 서적 분류)
- 반응형 디자인 및 부드러운 애니메이션

🔧 기술적 개선:
- PDF.js 워커 설정 및 토큰 인증 처리
- 서적별 PDF 자동 그룹화 로직
- Alpine.js 컴포넌트 초기화 최적화
2025-09-05 07:13:49 +09:00

99 lines
3.7 KiB
PL/PgSQL

-- 006_add_canonical_path.sql
-- 정사 경로 표시를 위한 필드 추가
-- memo_nodes 테이블에 정사 경로 관련 필드 추가
ALTER TABLE memo_nodes
ADD COLUMN is_canonical BOOLEAN DEFAULT FALSE,
ADD COLUMN canonical_order INTEGER DEFAULT NULL,
ADD COLUMN story_path TEXT DEFAULT NULL; -- 정사 경로 저장 (예: /1/3/7)
-- 정사 경로 순서를 위한 인덱스 추가
CREATE INDEX idx_memo_nodes_canonical_order ON memo_nodes(tree_id, canonical_order) WHERE is_canonical = TRUE;
-- 트리별 정사 경로 통계를 위한 뷰 생성
CREATE OR REPLACE VIEW memo_tree_canonical_stats AS
SELECT
t.id as tree_id,
t.title as tree_title,
COUNT(n.id) as total_nodes,
COUNT(CASE WHEN n.is_canonical = TRUE THEN 1 END) as canonical_nodes,
MAX(n.canonical_order) as max_canonical_order,
STRING_AGG(
CASE WHEN n.is_canonical = TRUE THEN n.title END,
''
ORDER BY n.canonical_order
) as canonical_story_path
FROM memo_trees t
LEFT JOIN memo_nodes n ON t.id = n.tree_id
GROUP BY t.id, t.title;
-- 정사 경로 순서 자동 업데이트 함수 (분기점에서 하나만 선택 가능)
CREATE OR REPLACE FUNCTION update_canonical_order()
RETURNS TRIGGER AS $$
BEGIN
-- 정사로 설정될 때
IF NEW.is_canonical = TRUE AND (OLD.is_canonical IS NULL OR OLD.is_canonical = FALSE) THEN
-- 같은 부모를 가진 다른 형제 노드들의 정사 상태 해제 (분기점에서 하나만 선택)
IF NEW.parent_id IS NOT NULL THEN
UPDATE memo_nodes
SET is_canonical = FALSE, canonical_order = NULL, story_path = NULL
WHERE tree_id = NEW.tree_id
AND parent_id = NEW.parent_id
AND id != NEW.id
AND is_canonical = TRUE;
END IF;
-- 부모 노드의 순서를 기준으로 순서 계산
IF NEW.parent_id IS NULL THEN
-- 루트 노드는 항상 1
NEW.canonical_order = 1;
ELSE
-- 부모 노드의 순서 + 1
SELECT COALESCE(parent.canonical_order, 0) + 1
INTO NEW.canonical_order
FROM memo_nodes parent
WHERE parent.id = NEW.parent_id AND parent.is_canonical = TRUE;
-- 부모가 정사가 아니면 순서 할당 안함
IF NEW.canonical_order IS NULL THEN
NEW.canonical_order = NULL;
END IF;
END IF;
-- 정사 경로 업데이트
NEW.story_path = COALESCE(NEW.path, '');
END IF;
-- 정사에서 제외될 때 순서 제거
IF NEW.is_canonical = FALSE AND OLD.is_canonical = TRUE THEN
NEW.canonical_order = NULL;
NEW.story_path = NULL;
-- 뒤의 순서들을 앞으로 당기기
UPDATE memo_nodes
SET canonical_order = canonical_order - 1
WHERE tree_id = NEW.tree_id
AND is_canonical = TRUE
AND canonical_order > OLD.canonical_order;
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- 트리거 생성
DROP TRIGGER IF EXISTS trigger_update_canonical_order ON memo_nodes;
CREATE TRIGGER trigger_update_canonical_order
BEFORE UPDATE ON memo_nodes
FOR EACH ROW
EXECUTE FUNCTION update_canonical_order();
-- 기존 루트 노드들을 정사로 설정 (기본값)
UPDATE memo_nodes
SET is_canonical = TRUE, canonical_order = 1
WHERE parent_id IS NULL AND is_canonical = FALSE;
COMMENT ON COLUMN memo_nodes.is_canonical IS '정사 경로 여부 (소설의 메인 스토리라인)';
COMMENT ON COLUMN memo_nodes.canonical_order IS '정사 경로에서의 순서 (1부터 시작)';
COMMENT ON COLUMN memo_nodes.story_path IS '정사 경로 문자열 표현';