| <!DOCTYPE html>
|
| <html lang="en">
|
| <head>
|
| <meta charset="UTF-8">
|
| <meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| <title>VvvebJs - User Dashboard</title>
|
| <link href="css/editor.css" rel="stylesheet">
|
| <style>
|
| .user-dashboard {
|
| max-width: 1200px;
|
| margin: 0 auto;
|
| padding: 20px;
|
| }
|
|
|
| .user-info {
|
| background: #f8f9fa;
|
| padding: 15px;
|
| border-radius: 5px;
|
| margin-bottom: 20px;
|
| }
|
|
|
| .file-manager {
|
| background: white;
|
| border: 1px solid #ddd;
|
| border-radius: 5px;
|
| overflow: hidden;
|
| }
|
|
|
| .file-manager-header {
|
| background: #007bff;
|
| color: white;
|
| padding: 15px;
|
| display: flex;
|
| justify-content: space-between;
|
| align-items: center;
|
| }
|
|
|
| .file-list {
|
| max-height: 400px;
|
| overflow-y: auto;
|
| }
|
|
|
| .file-item {
|
| display: flex;
|
| justify-content: space-between;
|
| align-items: center;
|
| padding: 10px 15px;
|
| border-bottom: 1px solid #eee;
|
| transition: background-color 0.2s;
|
| }
|
|
|
| .file-item:hover {
|
| background-color: #f8f9fa;
|
| }
|
|
|
| .file-name {
|
| font-weight: 500;
|
| color: #333;
|
| }
|
|
|
| .file-meta {
|
| font-size: 0.85em;
|
| color: #666;
|
| }
|
|
|
| .file-actions {
|
| display: flex;
|
| gap: 10px;
|
| }
|
|
|
| .btn {
|
| padding: 5px 10px;
|
| border: none;
|
| border-radius: 3px;
|
| cursor: pointer;
|
| font-size: 0.85em;
|
| text-decoration: none;
|
| display: inline-block;
|
| }
|
|
|
| .btn-primary {
|
| background: #007bff;
|
| color: white;
|
| }
|
|
|
| .btn-warning {
|
| background: #ffc107;
|
| color: #333;
|
| }
|
|
|
| .btn-danger {
|
| background: #dc3545;
|
| color: white;
|
| }
|
|
|
| .btn-success {
|
| background: #28a745;
|
| color: white;
|
| }
|
|
|
| .empty-state {
|
| text-align: center;
|
| padding: 40px;
|
| color: #666;
|
| }
|
|
|
| .loading {
|
| text-align: center;
|
| padding: 20px;
|
| color: #666;
|
| }
|
|
|
| .error {
|
| background: #f8d7da;
|
| color: #721c24;
|
| padding: 10px;
|
| border-radius: 3px;
|
| margin: 10px 0;
|
| }
|
|
|
| .success {
|
| background: #d4edda;
|
| color: #155724;
|
| padding: 10px;
|
| border-radius: 3px;
|
| margin: 10px 0;
|
| }
|
|
|
| .modal {
|
| display: none;
|
| position: fixed;
|
| z-index: 1000;
|
| left: 0;
|
| top: 0;
|
| width: 100%;
|
| height: 100%;
|
| background-color: rgba(0,0,0,0.4);
|
| }
|
|
|
| .modal-content {
|
| background-color: #fefefe;
|
| margin: 15% auto;
|
| padding: 20px;
|
| border: 1px solid #888;
|
| border-radius: 5px;
|
| width: 300px;
|
| }
|
|
|
| .modal-header {
|
| display: flex;
|
| justify-content: space-between;
|
| align-items: center;
|
| margin-bottom: 15px;
|
| }
|
|
|
| .close {
|
| color: #aaa;
|
| font-size: 28px;
|
| font-weight: bold;
|
| cursor: pointer;
|
| }
|
|
|
| .close:hover {
|
| color: black;
|
| }
|
|
|
| .form-group {
|
| margin-bottom: 15px;
|
| }
|
|
|
| .form-group label {
|
| display: block;
|
| margin-bottom: 5px;
|
| font-weight: bold;
|
| }
|
|
|
| .form-group input {
|
| width: 100%;
|
| padding: 8px;
|
| border: 1px solid #ddd;
|
| border-radius: 3px;
|
| box-sizing: border-box;
|
| }
|
| </style>
|
| </head>
|
| <body>
|
| <div class="user-dashboard">
|
| <div class="user-info">
|
| <h2>Welcome to VvvebJs</h2>
|
| <p><strong>User:</strong> <span id="current-user">Loading...</span></p>
|
| <p><strong>Storage Path:</strong> <span id="user-path">Loading...</span></p>
|
| </div>
|
|
|
| <div class="file-manager">
|
| <div class="file-manager-header">
|
| <h3>My Files</h3>
|
| <div>
|
| <button class="btn btn-success" onclick="createNewFile()">New Page</button>
|
| <button class="btn btn-primary" onclick="refreshFileList()">Refresh</button>
|
| <a href="editor.html" class="btn btn-primary">Open Editor</a>
|
| </div>
|
| </div>
|
|
|
| <div id="file-list-container">
|
| <div class="loading">Loading files...</div>
|
| </div>
|
| </div>
|
| </div>
|
|
|
|
|
| <div id="renameModal" class="modal">
|
| <div class="modal-content">
|
| <div class="modal-header">
|
| <h4>Rename File</h4>
|
| <span class="close" onclick="closeModal('renameModal')">×</span>
|
| </div>
|
| <div class="form-group">
|
| <label for="newFileName">New filename:</label>
|
| <input type="text" id="newFileName" placeholder="Enter new filename">
|
| </div>
|
| <div>
|
| <button class="btn btn-primary" onclick="confirmRename()">Rename</button>
|
| <button class="btn" onclick="closeModal('renameModal')">Cancel</button>
|
| </div>
|
| </div>
|
| </div>
|
|
|
|
|
| <div id="deleteModal" class="modal">
|
| <div class="modal-content">
|
| <div class="modal-header">
|
| <h4>Delete File</h4>
|
| <span class="close" onclick="closeModal('deleteModal')">×</span>
|
| </div>
|
| <p>Are you sure you want to delete <strong id="deleteFileName"></strong>?</p>
|
| <div>
|
| <button class="btn btn-danger" onclick="confirmDelete()">Delete</button>
|
| <button class="btn" onclick="closeModal('deleteModal')">Cancel</button>
|
| </div>
|
| </div>
|
| </div>
|
|
|
| <script>
|
| let currentFiles = [];
|
| let selectedFile = '';
|
|
|
|
|
| document.addEventListener('DOMContentLoaded', function() {
|
| checkAuthenticationAndInit();
|
| });
|
|
|
| async function checkAuthenticationAndInit() {
|
| try {
|
| const response = await fetch('save.php?action=checkAuth');
|
| if (response.status === 401) {
|
|
|
| window.location.href = 'index.html';
|
| return;
|
| }
|
|
|
| const data = await response.json();
|
| if (!data.authenticated) {
|
|
|
| window.location.href = 'index.html';
|
| return;
|
| }
|
|
|
|
|
| loadUserInfo();
|
| loadFileList();
|
| } catch (error) {
|
| console.error('Auth check failed:', error);
|
|
|
| window.location.href = 'index.html';
|
| }
|
| }
|
|
|
| async function loadUserInfo() {
|
| try {
|
| const response = await fetch('save.php?action=checkAuth');
|
| const data = await response.json();
|
|
|
| if (data.success) {
|
| document.getElementById('current-user').textContent = data.user;
|
| document.getElementById('user-path').textContent = data.userPath || 'Default';
|
| }
|
| } catch (error) {
|
| console.error('Error loading user info:', error);
|
| }
|
| }
|
|
|
| async function loadFileList() {
|
| const container = document.getElementById('file-list-container');
|
| container.innerHTML = '<div class="loading">Loading files...</div>';
|
|
|
| try {
|
| const response = await fetch('save.php?action=listFiles');
|
| const data = await response.json();
|
|
|
| if (data.success) {
|
| currentFiles = data.files;
|
| renderFileList(data.files);
|
| } else {
|
| container.innerHTML = '<div class="error">Error loading files: ' + (data.message || 'Unknown error') + '</div>';
|
| }
|
| } catch (error) {
|
| console.error('Error loading files:', error);
|
| container.innerHTML = '<div class="error">Error loading files: ' + error.message + '</div>';
|
| }
|
| }
|
|
|
| function renderFileList(files) {
|
| const container = document.getElementById('file-list-container');
|
|
|
| if (files.length === 0) {
|
| container.innerHTML = `
|
| <div class="empty-state">
|
| <p>No files found. <a href="editor.html" class="btn btn-success">Create your first page</a></p>
|
| </div>
|
| `;
|
| return;
|
| }
|
|
|
| const fileListHTML = files.map(file => `
|
| <div class="file-item">
|
| <div>
|
| <div class="file-name">${file.name}</div>
|
| <div class="file-meta">
|
| ${file.size ? `Size: ${formatFileSize(file.size)} • ` : ''}
|
| Path: ${file.path || file.name}
|
| </div>
|
| </div>
|
| <div class="file-actions">
|
| <a href="editor.html?file=${encodeURIComponent(file.path || file.name)}"
|
| class="btn btn-primary">Edit</a>
|
| ${file.url ? `<a href="${file.url}" target="_blank" class="btn btn-success">View</a>` : ''}
|
| <button class="btn btn-warning" onclick="renameFile('${file.name}')">Rename</button>
|
| <button class="btn btn-danger" onclick="deleteFile('${file.name}')">Delete</button>
|
| </div>
|
| </div>
|
| `).join('');
|
|
|
| container.innerHTML = '<div class="file-list">' + fileListHTML + '</div>';
|
| }
|
|
|
| function formatFileSize(bytes) {
|
| if (bytes === 0) return '0 Bytes';
|
| const k = 1024;
|
| const sizes = ['Bytes', 'KB', 'MB', 'GB'];
|
| const i = Math.floor(Math.log(bytes) / Math.log(k));
|
| return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
| }
|
|
|
| function refreshFileList() {
|
| loadFileList();
|
| }
|
|
|
| function createNewFile() {
|
| const fileName = prompt('Enter filename (without .html extension):');
|
| if (fileName) {
|
| const safeFileName = fileName.replace(/[^a-zA-Z0-9_-]/g, '_') + '.html';
|
| window.location.href = `editor.html?file=${encodeURIComponent(safeFileName)}`;
|
| }
|
| }
|
|
|
| function renameFile(fileName) {
|
| selectedFile = fileName;
|
| document.getElementById('newFileName').value = fileName.replace('.html', '');
|
| openModal('renameModal');
|
| }
|
|
|
| async function confirmRename() {
|
| const newFileName = document.getElementById('newFileName').value.trim();
|
| if (!newFileName) {
|
| alert('Please enter a valid filename');
|
| return;
|
| }
|
|
|
| const safeNewFileName = newFileName.replace(/[^a-zA-Z0-9_-]/g, '_') + '.html';
|
|
|
| try {
|
| const formData = new FormData();
|
| formData.append('file', selectedFile);
|
| formData.append('newfile', safeNewFileName);
|
|
|
| const response = await fetch('save.php?action=rename', {
|
| method: 'POST',
|
| body: formData
|
| });
|
|
|
| const result = await response.text();
|
| if (response.ok) {
|
| showMessage('File renamed successfully', 'success');
|
| closeModal('renameModal');
|
| loadFileList();
|
| } else {
|
| showMessage('Error renaming file: ' + result, 'error');
|
| }
|
| } catch (error) {
|
| showMessage('Error renaming file: ' + error.message, 'error');
|
| }
|
| }
|
|
|
| function deleteFile(fileName) {
|
| selectedFile = fileName;
|
| document.getElementById('deleteFileName').textContent = fileName;
|
| openModal('deleteModal');
|
| }
|
|
|
| async function confirmDelete() {
|
| try {
|
| const formData = new FormData();
|
| formData.append('file', selectedFile);
|
|
|
| const response = await fetch('save.php?action=delete', {
|
| method: 'POST',
|
| body: formData
|
| });
|
|
|
| const result = await response.text();
|
| if (response.ok) {
|
| showMessage('File deleted successfully', 'success');
|
| closeModal('deleteModal');
|
| loadFileList();
|
| } else {
|
| showMessage('Error deleting file: ' + result, 'error');
|
| }
|
| } catch (error) {
|
| showMessage('Error deleting file: ' + error.message, 'error');
|
| }
|
| }
|
|
|
| function openModal(modalId) {
|
| document.getElementById(modalId).style.display = 'block';
|
| }
|
|
|
| function closeModal(modalId) {
|
| document.getElementById(modalId).style.display = 'none';
|
| }
|
|
|
| function showMessage(message, type) {
|
| const container = document.querySelector('.user-dashboard');
|
| const messageDiv = document.createElement('div');
|
| messageDiv.className = type;
|
| messageDiv.textContent = message;
|
|
|
| container.insertBefore(messageDiv, container.firstChild);
|
|
|
| setTimeout(() => {
|
| messageDiv.remove();
|
| }, 5000);
|
| }
|
|
|
|
|
| window.onclick = function(event) {
|
| const modals = document.querySelectorAll('.modal');
|
| modals.forEach(modal => {
|
| if (event.target === modal) {
|
| modal.style.display = 'none';
|
| }
|
| });
|
| }
|
| </script>
|
| </body>
|
| </html> |