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:
@@ -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 로드
|
||||
|
||||
Reference in New Issue
Block a user