🚀 배포용: 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 컴포넌트 초기화 최적화
This commit is contained in:
97
backend/database/migrations/007_fix_canonical_order.sql
Normal file
97
backend/database/migrations/007_fix_canonical_order.sql
Normal file
@@ -0,0 +1,97 @@
|
||||
-- 007_fix_canonical_order.sql
|
||||
-- 정사 경로 순서 계산 로직 수정
|
||||
|
||||
-- 기존 트리거 삭제
|
||||
DROP TRIGGER IF EXISTS trigger_update_canonical_order ON memo_nodes;
|
||||
DROP FUNCTION IF EXISTS update_canonical_order();
|
||||
|
||||
-- 정사 경로 순서를 올바르게 계산하는 함수
|
||||
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;
|
||||
|
||||
-- 정사 경로 업데이트
|
||||
NEW.story_path = COALESCE(NEW.path, '');
|
||||
|
||||
-- 순서는 별도 함수에서 일괄 계산
|
||||
PERFORM recalculate_canonical_orders(NEW.tree_id);
|
||||
END IF;
|
||||
|
||||
-- 정사에서 제외될 때
|
||||
IF NEW.is_canonical = FALSE AND OLD.is_canonical = TRUE THEN
|
||||
NEW.canonical_order = NULL;
|
||||
NEW.story_path = NULL;
|
||||
|
||||
-- 순서 재계산
|
||||
PERFORM recalculate_canonical_orders(NEW.tree_id);
|
||||
END IF;
|
||||
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
-- 트리별 정사 경로 순서를 DFS로 재계산하는 함수
|
||||
CREATE OR REPLACE FUNCTION recalculate_canonical_orders(tree_uuid UUID)
|
||||
RETURNS VOID AS $$
|
||||
DECLARE
|
||||
current_order INTEGER := 1;
|
||||
BEGIN
|
||||
-- 모든 정사 노드의 순서를 NULL로 초기화
|
||||
UPDATE memo_nodes
|
||||
SET canonical_order = NULL
|
||||
WHERE tree_id = tree_uuid AND is_canonical = TRUE;
|
||||
|
||||
-- DFS로 순서 할당 (재귀 CTE 사용)
|
||||
WITH RECURSIVE canonical_path AS (
|
||||
-- 루트 노드들 (정사인 것만)
|
||||
SELECT id, parent_id, title, 1 as order_num, ARRAY[id] as path
|
||||
FROM memo_nodes
|
||||
WHERE tree_id = tree_uuid
|
||||
AND parent_id IS NULL
|
||||
AND is_canonical = TRUE
|
||||
|
||||
UNION ALL
|
||||
|
||||
-- 자식 노드들 (정사인 것만)
|
||||
SELECT n.id, n.parent_id, n.title,
|
||||
cp.order_num + 1 as order_num,
|
||||
cp.path || n.id
|
||||
FROM memo_nodes n
|
||||
INNER JOIN canonical_path cp ON n.parent_id = cp.id
|
||||
WHERE n.tree_id = tree_uuid
|
||||
AND n.is_canonical = TRUE
|
||||
)
|
||||
UPDATE memo_nodes
|
||||
SET canonical_order = cp.order_num
|
||||
FROM canonical_path cp
|
||||
WHERE memo_nodes.id = cp.id;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
-- 트리거 다시 생성
|
||||
CREATE TRIGGER trigger_update_canonical_order
|
||||
AFTER UPDATE ON memo_nodes
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_canonical_order();
|
||||
|
||||
-- 기존 데이터의 순서 재계산
|
||||
DO $$
|
||||
DECLARE
|
||||
tree_rec RECORD;
|
||||
BEGIN
|
||||
FOR tree_rec IN SELECT DISTINCT tree_id FROM memo_nodes WHERE is_canonical = TRUE
|
||||
LOOP
|
||||
PERFORM recalculate_canonical_orders(tree_rec.tree_id);
|
||||
END LOOP;
|
||||
END $$;
|
||||
Reference in New Issue
Block a user