Major UI overhaul and upload system improvements

- Removed hierarchy view and integrated functionality into index.html
- Added book-based document grouping with dedicated book-documents.html page
- Implemented comprehensive multi-file upload system with drag-and-drop reordering
- Added HTML-PDF matching functionality with download capability
- Enhanced upload workflow with 3-step process (File Selection, Book Settings, Order & Match)
- Added book conflict resolution (existing book vs new edition)
- Improved document order adjustment with one-click sort options
- Added modular header component system
- Updated API connectivity for Docker environment
- Enhanced viewer.html with PDF download functionality
- Fixed browser caching issues with version management
- Improved mobile responsiveness and modern UI design
This commit is contained in:
Hyungi Ahn
2025-08-25 15:58:30 +09:00
parent f95f67364a
commit 4038040faa
21 changed files with 3875 additions and 2603 deletions

View File

@@ -3,9 +3,12 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>스토리 뷰 - 정사 경로</title>
<title>스토리 뷰</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<!-- 헤더 로더 -->
<script src="static/js/header-loader.js"></script>
<style>
/* 목차 스타일 */
.toc-item {
@@ -37,40 +40,8 @@
</style>
</head>
<body class="bg-gray-50" x-data="storyViewApp()" x-init="init()">
<!-- 헤더 -->
<header class="bg-white shadow-sm border-b no-print">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex justify-between items-center h-16">
<!-- 왼쪽: 로고 및 네비게이션 -->
<div class="flex items-center space-x-4">
<a href="index.html" class="flex items-center space-x-2">
<i class="fas fa-book text-blue-600 text-xl"></i>
<span class="text-xl font-bold text-gray-900">Document Server</span>
</a>
<span class="text-gray-400">|</span>
<nav class="flex space-x-4">
<a href="memo-tree.html" class="text-gray-600 hover:text-blue-600 px-3 py-2 rounded-md text-sm font-medium">
<i class="fas fa-sitemap mr-1"></i> 트리 에디터
</a>
<a href="story-view.html" class="bg-blue-100 text-blue-700 px-3 py-2 rounded-md text-sm font-medium">
<i class="fas fa-book-open mr-1"></i> 스토리 뷰
</a>
</nav>
</div>
<!-- 오른쪽: 사용자 정보 및 액션 -->
<div class="flex items-center space-x-4">
<div x-show="currentUser" class="flex items-center space-x-3">
<span class="text-sm text-gray-600" x-text="currentUser?.full_name || currentUser?.email"></span>
<button @click="logout()" class="text-sm text-gray-500 hover:text-gray-700">로그아웃</button>
</div>
<button x-show="!currentUser" @click="openLoginModal()" class="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700">
로그인
</button>
</div>
</div>
</div>
</header>
<!-- 공통 헤더 컨테이너 -->
<div id="header-container"></div>
<!-- 메인 컨테이너 -->
<div class="min-h-screen pt-4" x-show="currentUser">
@@ -101,13 +72,6 @@
<!-- 액션 버튼들 -->
<div class="flex items-center space-x-2">
<button
@click="toggleView()"
class="px-3 py-2 bg-gray-600 text-white rounded-md hover:bg-gray-700 text-sm"
>
<i class="fas fa-eye mr-1"></i>
<span x-text="viewMode === 'toc' ? '전체보기' : '목차보기'"></span>
</button>
<button
@click="exportStory()"
class="px-3 py-2 bg-green-600 text-white rounded-md hover:bg-green-700 text-sm"
@@ -128,13 +92,13 @@
<div x-show="!selectedTree" class="bg-white rounded-lg shadow-sm p-12 text-center">
<i class="fas fa-book-open text-6xl text-gray-300 mb-4"></i>
<h3 class="text-lg font-medium text-gray-900 mb-2">스토리를 선택하세요</h3>
<p class="text-gray-500">위에서 트리를 선택하면 정사 경로가 목차 형태로 표시됩니다</p>
<p class="text-gray-500">위에서 트리를 선택하면 목차가 표시됩니다</p>
</div>
<!-- 정사 노드 없음 상태 -->
<div x-show="selectedTree && canonicalNodes.length === 0" class="bg-white rounded-lg shadow-sm p-12 text-center">
<i class="fas fa-route text-6xl text-gray-300 mb-4"></i>
<h3 class="text-lg font-medium text-gray-900 mb-2">정사 경로가 없습니다</h3>
<h3 class="text-lg font-medium text-gray-900 mb-2">스토리 노드가 없습니다</h3>
<p class="text-gray-500 mb-4">트리 에디터에서 노드들을 정사로 설정해주세요</p>
<a href="memo-tree.html" class="inline-flex items-center px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700">
<i class="fas fa-sitemap mr-2"></i> 트리 에디터로 가기
@@ -157,10 +121,10 @@
</div>
<!-- 목차 뷰 -->
<div x-show="viewMode === 'toc'" class="bg-white rounded-lg shadow-sm">
<div class="bg-white rounded-lg shadow-sm">
<div class="p-6 border-b">
<h2 class="text-xl font-semibold text-gray-900 flex items-center">
<i class="fas fa-list mr-2"></i> 목차 (정사 경로)
<i class="fas fa-list mr-2"></i> 목차
</h2>
</div>
<div class="p-6">
@@ -168,7 +132,7 @@
<template x-for="(node, index) in canonicalNodes" :key="node.id">
<div
class="toc-item flex items-center p-3 rounded-lg cursor-pointer"
@click="scrollToChapter(node.id)"
@click="openStoryReader(node.id, index)"
>
<span class="toc-number text-sm font-medium text-gray-500 mr-3" x-text="`${index + 1}.`"></span>
<div class="flex-1">
@@ -185,54 +149,7 @@
</div>
</div>
</div>
<!-- 전체 스토리 뷰 -->
<div x-show="viewMode === 'full'" class="bg-white rounded-lg shadow-sm">
<div class="p-6 border-b">
<h2 class="text-xl font-semibold text-gray-900 flex items-center">
<i class="fas fa-book-open mr-2"></i> 전체 스토리
</h2>
</div>
<div class="story-content">
<template x-for="(node, index) in canonicalNodes" :key="node.id">
<div :id="`chapter-${node.id}`" class="chapter-section">
<!-- 챕터 헤더 -->
<div class="p-6 bg-gray-50 border-b">
<div class="flex items-center justify-between">
<div>
<h3 class="text-lg font-semibold text-gray-900 flex items-center">
<span class="text-blue-600 mr-2" x-text="`${index + 1}.`"></span>
<span x-text="node.title"></span>
</h3>
<div class="flex items-center space-x-3 text-sm text-gray-500 mt-1">
<span x-text="getNodeTypeLabel(node.node_type)"></span>
<span x-show="node.word_count > 0" x-text="`${node.word_count}단어`"></span>
<span x-text="getStatusLabel(node.status)"></span>
</div>
</div>
<button
@click="editChapter(node)"
class="no-print px-3 py-1 text-sm text-blue-600 hover:bg-blue-50 rounded"
>
<i class="fas fa-edit mr-1"></i> 편집
</button>
</div>
</div>
<!-- 챕터 내용 -->
<div class="p-6">
<div x-show="node.content" class="prose max-w-none" x-html="formatContent(node.content)"></div>
<div x-show="!node.content" class="text-gray-400 italic text-center py-8">
이 챕터는 아직 내용이 없습니다
</div>
</div>
<!-- 챕터 구분선 -->
<div x-show="index < canonicalNodes.length - 1" class="chapter-divider"></div>
</div>
</template>
</div>
</div>
</div>
</div>
</div>
@@ -371,9 +288,9 @@
// 스크립트 순차 로딩
(async () => {
try {
await loadScript('static/js/api.js?v=2025012290');
await loadScript('static/js/api.js?v=2025012380');
console.log('✅ API 스크립트 로드 완료');
await loadScript('static/js/story-view.js?v=2025012295');
await loadScript('static/js/story-view.js?v=2025012364');
console.log('✅ Story View 스크립트 로드 완료');
// 모든 스크립트 로드 완료 후 Alpine.js 로드