Add complete Jaryo File Manager with Synology NAS deployment support
This commit is contained in:
260
admin/api-client.js
Normal file
260
admin/api-client.js
Normal file
@@ -0,0 +1,260 @@
|
||||
// 관리자용 API 클라이언트
|
||||
// SQLite 백엔드와 통신하는 함수들
|
||||
|
||||
const API_BASE_URL = '';
|
||||
|
||||
// API 요청 헬퍼 함수
|
||||
async function apiRequest(url, options = {}) {
|
||||
const fullUrl = `${API_BASE_URL}${url}`;
|
||||
console.log('🌐 API 요청:', options.method || 'GET', fullUrl);
|
||||
console.log('요청 옵션:', options);
|
||||
|
||||
const response = await fetch(fullUrl, {
|
||||
credentials: 'include', // 세션 쿠키 포함
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
...options.headers
|
||||
},
|
||||
...options
|
||||
});
|
||||
|
||||
console.log('📨 응답 받음:', response.status, response.statusText);
|
||||
console.log('응답 URL:', response.url);
|
||||
|
||||
if (!response.ok) {
|
||||
const error = await response.text();
|
||||
console.error('❌ API 오류 응답:', error);
|
||||
throw new Error(`API Error: ${response.status} - ${error}`);
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
// 인증 관련 API
|
||||
const AuthAPI = {
|
||||
// 현재 세션 확인
|
||||
async getSession() {
|
||||
try {
|
||||
const response = await apiRequest('/api/auth/session');
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
console.error('세션 확인 오류:', error);
|
||||
return { user: null };
|
||||
}
|
||||
},
|
||||
|
||||
// 로그인
|
||||
async login(email, password) {
|
||||
try {
|
||||
const response = await apiRequest('/api/auth/login', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ email, password })
|
||||
});
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
console.error('로그인 오류:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
// 로그아웃
|
||||
async logout() {
|
||||
try {
|
||||
await apiRequest('/api/auth/logout', {
|
||||
method: 'POST'
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('로그아웃 오류:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 파일 관리 API
|
||||
const FilesAPI = {
|
||||
// 모든 파일 조회 (관리자용)
|
||||
async getAll() {
|
||||
try {
|
||||
const response = await apiRequest('/api/files');
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
console.error('파일 목록 조회 오류:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
// 공개 파일 조회 (일반 사용자용)
|
||||
async getPublic() {
|
||||
try {
|
||||
const response = await apiRequest('/api/files/public');
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
console.error('공개 파일 목록 조회 오류:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
// 파일 추가
|
||||
async create(formData) {
|
||||
try {
|
||||
const response = await fetch('/api/files', {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
body: formData // FormData는 Content-Type 헤더를 자동 설정
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const error = await response.text();
|
||||
throw new Error(`API Error: ${response.status} - ${error}`);
|
||||
}
|
||||
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
console.error('파일 추가 오류:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
// 파일 수정 (FormData 지원)
|
||||
async update(id, data) {
|
||||
try {
|
||||
let requestOptions;
|
||||
|
||||
if (data instanceof FormData) {
|
||||
// FormData인 경우 (파일 업로드 포함)
|
||||
requestOptions = {
|
||||
method: 'PUT',
|
||||
credentials: 'include',
|
||||
body: data // FormData는 Content-Type 헤더를 자동 설정
|
||||
};
|
||||
|
||||
console.log('📁 FormData를 사용한 파일 수정 요청');
|
||||
const response = await fetch(`/api/files/${id}`, requestOptions);
|
||||
|
||||
if (!response.ok) {
|
||||
const error = await response.text();
|
||||
throw new Error(`API Error: ${response.status} - ${error}`);
|
||||
}
|
||||
|
||||
return await response.json();
|
||||
} else {
|
||||
// 일반 JSON 데이터인 경우
|
||||
const response = await apiRequest(`/api/files/${id}`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
return await response.json();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('파일 수정 오류:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
// 파일 삭제
|
||||
async delete(id) {
|
||||
try {
|
||||
await apiRequest(`/api/files/${id}`, {
|
||||
method: 'DELETE'
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('파일 삭제 오류:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
// 파일 다운로드
|
||||
async download(fileId, attachmentId) {
|
||||
try {
|
||||
const response = await apiRequest(`/api/download/${fileId}/${attachmentId}`);
|
||||
return response;
|
||||
} catch (error) {
|
||||
console.error('파일 다운로드 오류:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 카테고리 관리 API
|
||||
const CategoriesAPI = {
|
||||
// 모든 카테고리 조회
|
||||
async getAll() {
|
||||
try {
|
||||
const response = await apiRequest('/api/categories');
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
console.error('카테고리 목록 조회 오류:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
// 카테고리 추가
|
||||
async create(name) {
|
||||
try {
|
||||
const response = await apiRequest('/api/categories', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ name })
|
||||
});
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
console.error('카테고리 추가 오류:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
// 카테고리 수정
|
||||
async update(id, name) {
|
||||
try {
|
||||
const url = `/api/categories/${id}`;
|
||||
console.log('🔄 카테고리 수정 API 호출:', url);
|
||||
console.log('전송 데이터:', { id, name });
|
||||
|
||||
const response = await apiRequest(url, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify({ name })
|
||||
});
|
||||
|
||||
console.log('API 응답 상태:', response.status);
|
||||
const result = await response.json();
|
||||
console.log('API 응답 데이터:', result);
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.error('카테고리 수정 오류:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
// 카테고리 삭제
|
||||
async delete(id) {
|
||||
try {
|
||||
await apiRequest(`/api/categories/${id}`, {
|
||||
method: 'DELETE'
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('카테고리 삭제 오류:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 연결 테스트 API
|
||||
const SystemAPI = {
|
||||
// 서버 연결 테스트
|
||||
async testConnection() {
|
||||
try {
|
||||
const response = await fetch('/api/health');
|
||||
return response.ok;
|
||||
} catch (error) {
|
||||
console.error('연결 테스트 오류:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 전역으로 내보내기
|
||||
window.AdminAPI = {
|
||||
Auth: AuthAPI,
|
||||
Files: FilesAPI,
|
||||
Categories: CategoriesAPI,
|
||||
System: SystemAPI
|
||||
};
|
229
admin/index.html
229
admin/index.html
@@ -3,45 +3,72 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>자료실 - CRUD 시스템</title>
|
||||
<title>자료실 - 관리자</title>
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
<script src="https://unpkg.com/@supabase/supabase-js@2"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<header>
|
||||
<h1>📚 자료실 관리 시스템</h1>
|
||||
<p>파일과 문서를 효율적으로 관리하세요</p>
|
||||
<div id="authSection" class="auth-section">
|
||||
<div id="authButtons" class="auth-buttons" style="display: none;">
|
||||
<button id="loginBtn" class="auth-btn">🔑 로그인</button>
|
||||
<button id="signupBtn" class="auth-btn">👤 회원가입</button>
|
||||
<h1>📚 자료실 관리자</h1>
|
||||
<p>관리자 전용 페이지입니다</p>
|
||||
|
||||
<!-- 로그인 폼 -->
|
||||
<div id="loginSection" class="login-section">
|
||||
<div class="login-form">
|
||||
<h3>🔐 관리자 로그인</h3>
|
||||
<div class="form-group">
|
||||
<input type="email" id="adminEmail" placeholder="이메일" value="admin@jaryo.com" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="password" id="adminPassword" placeholder="비밀번호" required>
|
||||
</div>
|
||||
<button id="loginBtn" class="login-btn">로그인</button>
|
||||
</div>
|
||||
<div id="userInfo" class="user-info" style="display: flex;">
|
||||
<span id="userEmail">오프라인 사용자</span>
|
||||
<span id="syncStatus" class="sync-status offline">🟡 오프라인</span>
|
||||
<button id="logoutBtn" class="auth-btn" style="display: none;">🚪 로그아웃</button>
|
||||
|
||||
<div class="public-link">
|
||||
<a href="/" class="public-btn">👥 일반 자료실 보기</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 로그인 후 표시될 관리자 정보 -->
|
||||
<div id="adminSection" class="admin-section" style="display: none;">
|
||||
<div class="admin-info">
|
||||
<span id="adminUserEmail">관리자</span>
|
||||
<span id="connectionStatus" class="connection-status online">🟢 온라인</span>
|
||||
<button id="logoutBtn" class="logout-btn">🚪 로그아웃</button>
|
||||
</div>
|
||||
|
||||
<div class="public-link">
|
||||
<a href="/" class="public-btn">👥 일반 자료실 보기</a>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="search-section">
|
||||
<input type="text" id="searchInput" placeholder="제목, 설명, 카테고리로 검색...">
|
||||
<select id="categoryFilter">
|
||||
<option value="">전체 카테고리</option>
|
||||
<option value="문서">문서</option>
|
||||
<option value="이미지">이미지</option>
|
||||
<option value="동영상">동영상</option>
|
||||
<option value="프레젠테이션">프레젠테이션</option>
|
||||
<option value="기타">기타</option>
|
||||
</select>
|
||||
<button id="searchBtn">🔍 검색</button>
|
||||
</div>
|
||||
<!-- 관리자 전용 영역 (로그인 후에만 표시) -->
|
||||
<div id="adminPanel" style="display: none;">
|
||||
<div class="search-section">
|
||||
<input type="text" id="searchInput" placeholder="제목, 설명, 카테고리로 검색...">
|
||||
<select id="categoryFilter">
|
||||
<option value="">전체 카테고리</option>
|
||||
<option value="문서">문서</option>
|
||||
<option value="이미지">이미지</option>
|
||||
<option value="동영상">동영상</option>
|
||||
<option value="프레젠테이션">프레젠테이션</option>
|
||||
<option value="기타">기타</option>
|
||||
</select>
|
||||
<button id="searchBtn">🔍 검색</button>
|
||||
</div>
|
||||
|
||||
<div class="form-section">
|
||||
<h2>📁 새 자료 추가</h2>
|
||||
<form id="fileForm">
|
||||
<div class="form-section">
|
||||
<div class="section-tabs">
|
||||
<button class="tab-btn active" id="fileTabBtn">📁 자료 관리</button>
|
||||
<button class="tab-btn" id="categoryTabBtn">🏷️ 카테고리 관리</button>
|
||||
</div>
|
||||
|
||||
<div id="fileTab" class="tab-content active">
|
||||
<h2>📁 새 자료 추가</h2>
|
||||
<form id="fileForm">
|
||||
<div class="form-group">
|
||||
<label for="fileTitle">제목 *</label>
|
||||
<input type="text" id="fileTitle" required>
|
||||
@@ -67,7 +94,7 @@
|
||||
<div class="form-group">
|
||||
<label for="fileUpload">파일 첨부 (여러 파일 선택 가능)</label>
|
||||
<div class="file-upload-area" id="fileUploadArea">
|
||||
<input type="file" id="fileUpload" multiple accept="*/*">
|
||||
<input type="file" id="fileUpload" multiple accept="*/*" style="display: none;">
|
||||
<div class="upload-placeholder">
|
||||
<div class="upload-icon">📁</div>
|
||||
<p><strong>파일을 여기로 드래그하거나 클릭하여 선택하세요</strong></p>
|
||||
@@ -88,6 +115,29 @@
|
||||
<button type="button" id="cancelBtn">❌ 취소</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="categoryTab" class="tab-content">
|
||||
<h2>🏷️ 카테고리 관리</h2>
|
||||
<form id="categoryForm">
|
||||
<div class="form-group">
|
||||
<label for="categoryName">카테고리 이름 *</label>
|
||||
<input type="text" id="categoryName" required placeholder="새 카테고리 이름">
|
||||
</div>
|
||||
|
||||
<div class="form-buttons">
|
||||
<button type="submit" id="addCategoryBtn">➕ 카테고리 추가</button>
|
||||
<button type="button" id="cancelCategoryBtn">❌ 취소</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="category-list-section">
|
||||
<h3>📋 현재 카테고리</h3>
|
||||
<div class="category-list" id="categoryList">
|
||||
<!-- 카테고리 목록이 여기에 표시됩니다 -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="list-section">
|
||||
@@ -128,40 +178,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 인증 모달 -->
|
||||
<div id="authModal" class="modal">
|
||||
<div class="modal-content">
|
||||
<h2 id="authModalTitle">🔑 로그인</h2>
|
||||
<form id="authForm">
|
||||
<div class="form-group">
|
||||
<label for="authEmail">이메일 *</label>
|
||||
<input type="email" id="authEmail" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="authPassword">비밀번호 *</label>
|
||||
<input type="password" id="authPassword" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group" id="confirmPasswordGroup" style="display: none;">
|
||||
<label for="authConfirmPassword">비밀번호 확인 *</label>
|
||||
<input type="password" id="authConfirmPassword">
|
||||
</div>
|
||||
|
||||
<div class="form-buttons">
|
||||
<button type="submit" id="authSubmitBtn">🔑 로그인</button>
|
||||
<button type="button" id="authCancelBtn">❌ 취소</button>
|
||||
</div>
|
||||
|
||||
<div class="auth-switch">
|
||||
<p id="authSwitchText">계정이 없으신가요? <a href="#" id="authSwitchLink">회원가입하기</a></p>
|
||||
</div>
|
||||
</form>
|
||||
<div id="authLoading" class="loading" style="display: none;">
|
||||
<p>처리 중...</p>
|
||||
</div>
|
||||
<!-- adminPanel 끝 -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -196,6 +213,50 @@
|
||||
<input type="text" id="editTags" placeholder="쉼표로 구분하여 입력">
|
||||
</div>
|
||||
|
||||
<!-- 첨부파일 관리 섹션 -->
|
||||
<div class="form-group">
|
||||
<label>📎 첨부파일 관리</label>
|
||||
<div class="attachment-management">
|
||||
<!-- 기존 첨부파일 목록 -->
|
||||
<div class="existing-attachments-section">
|
||||
<h4 class="section-title">🗂️ 기존 첨부파일</h4>
|
||||
<div class="existing-attachments" id="existingAttachments">
|
||||
<div class="no-existing-files" id="noExistingFiles">
|
||||
<span class="placeholder-text">📂 기존 첨부파일이 없습니다</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 새 파일 추가 섹션 -->
|
||||
<div class="new-attachments-section">
|
||||
<h4 class="section-title">➕ 새 파일 추가</h4>
|
||||
|
||||
<!-- 드래그&드롭 영역 -->
|
||||
<div class="file-drop-zone" id="fileDropZone">
|
||||
<div class="drop-zone-content">
|
||||
<div class="drop-zone-icon">📁</div>
|
||||
<div class="drop-zone-text">
|
||||
<p><strong>파일을 여기로 드래그하세요</strong></p>
|
||||
<p class="or-text">또는</p>
|
||||
</div>
|
||||
<button type="button" class="file-select-btn" id="fileSelectBtn">
|
||||
📂 파일 선택
|
||||
</button>
|
||||
<input type="file" id="newAttachments" multiple accept="*/*" hidden>
|
||||
</div>
|
||||
<div class="drop-zone-hint">
|
||||
<small>여러 파일을 동시에 선택할 수 있습니다</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 선택된 새 파일 미리보기 -->
|
||||
<div class="new-files-preview" id="newFilesPreview">
|
||||
<!-- 선택된 파일들이 여기에 표시됩니다 -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-buttons">
|
||||
<button type="submit">💾 저장</button>
|
||||
<button type="button" id="closeModal">❌ 취소</button>
|
||||
@@ -204,7 +265,49 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="supabase-config.js"></script>
|
||||
<!-- 카테고리 수정 모달 -->
|
||||
<div id="editCategoryModal" class="modal">
|
||||
<div class="modal-content">
|
||||
<h2>✏️ 카테고리 수정</h2>
|
||||
<form id="editCategoryForm">
|
||||
<div class="form-group">
|
||||
<label for="editCategoryName">카테고리 이름 *</label>
|
||||
<input type="text" id="editCategoryName" required>
|
||||
</div>
|
||||
|
||||
<div class="form-buttons">
|
||||
<button type="submit">💾 저장</button>
|
||||
<button type="button" id="closeCategoryModal">❌ 취소</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="api-client.js"></script>
|
||||
<script src="script.js"></script>
|
||||
|
||||
<script>
|
||||
// 페이지 로드 완료 후 디버깅 정보 출력
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
console.log('✅ DOM 로드 완료');
|
||||
console.log('📋 fileList 요소:', document.getElementById('fileList'));
|
||||
console.log('📋 pagination 요소:', document.getElementById('pagination'));
|
||||
|
||||
// 3초 후 파일 매니저 상태 확인
|
||||
setTimeout(() => {
|
||||
if (window.fileManager) {
|
||||
console.log('📋 FileManager 인스턴스:', window.fileManager);
|
||||
console.log('📋 파일 개수:', window.fileManager.files?.length || 0);
|
||||
console.log('📋 현재 사용자:', window.fileManager.currentUser);
|
||||
|
||||
// 강제로 다시 렌더링 시도
|
||||
if (window.fileManager.files && window.fileManager.files.length > 0) {
|
||||
console.log('🔄 파일 목록 강제 재렌더링...');
|
||||
window.fileManager.renderFiles();
|
||||
}
|
||||
}
|
||||
}, 3000);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
2810
admin/script.js
2810
admin/script.js
File diff suppressed because it is too large
Load Diff
1298
admin/styles.css
1298
admin/styles.css
File diff suppressed because it is too large
Load Diff
@@ -1,119 +0,0 @@
|
||||
// Supabase configuration (오프라인 모드)
|
||||
// ⚠️ 오프라인 모드로 강제 설정됨
|
||||
const SUPABASE_CONFIG = {
|
||||
url: 'https://kncudtzthmjegowbgnto.supabase.co',
|
||||
anonKey: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImtuY3VkdHp0aG1qZWdvd2JnbnRvIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NTU1Njc5OTksImV4cCI6MjA3MTE0Mzk5OX0.NlJN2vdgM96RvyVJE6ILQeDVUOU9X2F9vUn-jr_xlKc'
|
||||
};
|
||||
|
||||
// Supabase 클라이언트 초기화 (강제 비활성화)
|
||||
let supabase = null;
|
||||
|
||||
// 설정이 유효한지 확인
|
||||
function isSupabaseConfigured() {
|
||||
return false; // 강제로 false 반환
|
||||
}
|
||||
|
||||
// Supabase 클라이언트 초기화 함수 (오프라인 모드 강제)
|
||||
function initializeSupabase() {
|
||||
console.log('⚠️ 오프라인 모드로 강제 설정되었습니다.');
|
||||
return false;
|
||||
}
|
||||
|
||||
// 인증 상태 변경 리스너 (오프라인 모드용 - 빈 함수)
|
||||
function setupAuthListener(callback) {
|
||||
// 오프라인 모드에서는 아무것도 하지 않음
|
||||
return;
|
||||
}
|
||||
|
||||
// 현재 사용자 가져오기 (오프라인 모드용 - null 반환)
|
||||
async function getCurrentUser() {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 로그인 (오프라인 모드용 - 빈 함수)
|
||||
async function signIn(email, password) {
|
||||
throw new Error('오프라인 모드에서는 로그인할 수 없습니다.');
|
||||
}
|
||||
|
||||
// 회원가입 (오프라인 모드용 - 빈 함수)
|
||||
async function signUp(email, password, metadata = {}) {
|
||||
throw new Error('오프라인 모드에서는 회원가입할 수 없습니다.');
|
||||
}
|
||||
|
||||
// 로그아웃 (오프라인 모드용 - 빈 함수)
|
||||
async function signOut() {
|
||||
throw new Error('오프라인 모드에서는 로그아웃할 수 없습니다.');
|
||||
}
|
||||
|
||||
// 데이터베이스 헬퍼 함수들 (오프라인 모드용)
|
||||
const SupabaseHelper = {
|
||||
// 파일 목록 가져오기 (오프라인 모드용)
|
||||
async getFiles(userId) {
|
||||
console.log('🔍 SupabaseHelper.getFiles 호출됨 (오프라인 모드)');
|
||||
throw new Error('오프라인 모드에서는 Supabase 데이터베이스를 사용할 수 없습니다.');
|
||||
},
|
||||
|
||||
// 파일 추가 (오프라인 모드용)
|
||||
async addFile(fileData, userId) {
|
||||
console.log('🔍 SupabaseHelper.addFile 호출됨 (오프라인 모드)');
|
||||
throw new Error('오프라인 모드에서는 Supabase 데이터베이스를 사용할 수 없습니다.');
|
||||
},
|
||||
|
||||
// 파일 수정 (오프라인 모드용)
|
||||
async updateFile(id, updates, userId) {
|
||||
console.log('🔍 SupabaseHelper.updateFile 호출됨 (오프라인 모드)');
|
||||
throw new Error('오프라인 모드에서는 Supabase 데이터베이스를 사용할 수 없습니다.');
|
||||
},
|
||||
|
||||
// 파일 삭제 (오프라인 모드용)
|
||||
async deleteFile(id, userId) {
|
||||
console.log('🔍 SupabaseHelper.deleteFile 호출됨 (오프라인 모드)');
|
||||
throw new Error('오프라인 모드에서는 Supabase 데이터베이스를 사용할 수 없습니다.');
|
||||
},
|
||||
|
||||
// 실시간 구독 설정 (오프라인 모드용)
|
||||
subscribeToFiles(userId, callback) {
|
||||
console.log('🔍 SupabaseHelper.subscribeToFiles 호출됨 (오프라인 모드)');
|
||||
return null;
|
||||
},
|
||||
|
||||
// 파일 업로드 (오프라인 모드용)
|
||||
async uploadFile(file, filePath) {
|
||||
console.log('🔍 SupabaseHelper.uploadFile 호출됨 (오프라인 모드)');
|
||||
throw new Error('오프라인 모드에서는 Supabase Storage를 사용할 수 없습니다.');
|
||||
},
|
||||
|
||||
// 파일 다운로드 URL 가져오기 (오프라인 모드용)
|
||||
async getFileUrl(filePath) {
|
||||
console.log('🔍 SupabaseHelper.getFileUrl 호출됨 (오프라인 모드)');
|
||||
throw new Error('오프라인 모드에서는 Supabase Storage를 사용할 수 없습니다.');
|
||||
},
|
||||
|
||||
// 파일 삭제 (Storage) (오프라인 모드용)
|
||||
async deleteStorageFile(filePath) {
|
||||
console.log('🔍 SupabaseHelper.deleteStorageFile 호출됨 (오프라인 모드)');
|
||||
throw new Error('오프라인 모드에서는 Supabase Storage를 사용할 수 없습니다.');
|
||||
},
|
||||
|
||||
// 첨부파일 정보 추가 (오프라인 모드용)
|
||||
async addFileAttachment(fileId, attachmentData) {
|
||||
console.log('🔍 SupabaseHelper.addFileAttachment 호출됨 (오프라인 모드)');
|
||||
throw new Error('오프라인 모드에서는 Supabase 데이터베이스를 사용할 수 없습니다.');
|
||||
},
|
||||
|
||||
// Storage 버킷 확인 및 생성 (오프라인 모드용)
|
||||
async checkOrCreateBucket() {
|
||||
console.log('🔍 SupabaseHelper.checkOrCreateBucket 호출됨 (오프라인 모드)');
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// 전역으로 내보내기
|
||||
window.SupabaseHelper = SupabaseHelper;
|
||||
window.initializeSupabase = initializeSupabase;
|
||||
window.isSupabaseConfigured = isSupabaseConfigured;
|
||||
window.setupAuthListener = setupAuthListener;
|
||||
window.getCurrentUser = getCurrentUser;
|
||||
window.signIn = signIn;
|
||||
window.signUp = signUp;
|
||||
window.signOut = signOut;
|
Reference in New Issue
Block a user