FileServer/templates/user_files.html

228 lines
7.2 KiB
HTML

{% extends "base.html" %}
{% block title %}My Files - Das File Storage{% endblock %}
{% block content %}
<div class="nav-tabs">
<a href="/dashboard" class="nav-tab active">📂 My Files</a>
<a href="/settings" class="nav-tab">⚙️ Settings</a>
{% if is_admin %}
<a href="/admin" class="nav-tab">👑 Admin Panel</a>
{% endif %}
</div>
{% if message %}
<div class="alert alert-success">
{{ message }}
</div>
{% endif %}
{% if error %}
<div class="alert alert-error">
{{ error }}
</div>
{% endif %}
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
<h2>My Files</h2>
<button onclick="openUploadModal()" class="btn btn-primary">
⬆️ Upload File
</button>
</div>
{% if files %}
<table>
<thead>
<tr>
<th>Filename</th>
<th>Size</th>
<th>Uploaded</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for file in files %}
<tr>
<td>
<strong>{{ file.filename }}</strong>
<div class="file-size">{{ file.content_type or 'Unknown' }}</div>
</td>
<td class="file-size">{{ format_size(file.file_size) }}</td>
<td class="file-size">{{ file.uploaded_at.strftime('%Y-%m-%d %H:%M') }}</td>
<td>
<button onclick="downloadFile({{ file.id }}, '{{ file.filename }}')" class="btn btn-primary btn-small">
⬇️ Download
</button>
<button onclick="showShareLink('{{ file.share_token }}')" class="btn btn-success btn-small">
🔗 Share
</button>
<button onclick="deleteFile({{ file.id }}, '{{ file.filename }}')" class="btn btn-danger btn-small">
🗑️ Delete
</button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<div class="empty-state">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z" />
</svg>
<h3>No files yet</h3>
<p>Upload your first file to get started</p>
</div>
{% endif %}
<!-- Upload Modal -->
<div id="uploadModal" class="modal">
<div class="modal-content">
<div class="modal-header">Upload File</div>
<form id="uploadForm" enctype="multipart/form-data">
<div class="form-group">
<label for="fileInput">Choose file</label>
<input type="file" id="fileInput" name="file" required>
</div>
<div class="form-actions">
<button type="button" onclick="closeUploadModal()" class="btn btn-secondary">Cancel</button>
<button type="submit" class="btn btn-primary">Upload</button>
</div>
</form>
<div id="uploadProgress" style="display: none; margin-top: 20px;">
<div style="background: #e5e7eb; height: 20px; border-radius: 10px; overflow: hidden;">
<div id="progressBar" style="background: #667eea; height: 100%; width: 0%; transition: width 0.3s;"></div>
</div>
<p style="text-align: center; margin-top: 10px; color: #6b7280;">Uploading...</p>
</div>
</div>
</div>
<!-- Share Modal -->
<div id="shareModal" class="modal">
<div class="modal-content">
<div class="modal-header">Share File</div>
<p style="margin-bottom: 15px; color: #6b7280;">Anyone with this link can download the file:</p>
<div class="share-link">
<input type="text" id="shareLink" readonly>
<button onclick="copyShareLink()" class="btn btn-primary btn-small">📋 Copy</button>
</div>
<div class="form-actions" style="margin-top: 20px;">
<button onclick="closeShareModal()" class="btn btn-secondary">Close</button>
</div>
</div>
</div>
{% endblock %}
{% block extra_scripts %}
<script>
function openUploadModal() {
document.getElementById('uploadModal').classList.add('active');
}
function closeUploadModal() {
document.getElementById('uploadModal').classList.remove('active');
document.getElementById('uploadForm').reset();
document.getElementById('uploadProgress').style.display = 'none';
}
document.getElementById('uploadForm').addEventListener('submit', async (e) => {
e.preventDefault();
const fileInput = document.getElementById('fileInput');
const file = fileInput.files[0];
if (!file) return;
const formData = new FormData();
formData.append('file', file);
document.getElementById('uploadProgress').style.display = 'block';
try {
const response = await fetch('/api/files/upload', {
method: 'POST',
body: formData
});
if (response.ok) {
window.location.reload();
} else {
const error = await response.json();
alert('Upload failed: ' + (error.detail || 'Unknown error'));
document.getElementById('uploadProgress').style.display = 'none';
}
} catch (error) {
alert('Upload failed: ' + error.message);
document.getElementById('uploadProgress').style.display = 'none';
}
});
async function downloadFile(fileId, filename) {
try {
const response = await fetch(`/api/files/${fileId}/download`);
if (response.ok) {
const blob = await response.blob();
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
document.body.removeChild(a);
} else {
alert('Download failed');
}
} catch (error) {
alert('Download failed: ' + error.message);
}
}
function showShareLink(shareToken) {
const shareLink = window.location.origin + '/share/' + shareToken;
document.getElementById('shareLink').value = shareLink;
document.getElementById('shareModal').classList.add('active');
}
function closeShareModal() {
document.getElementById('shareModal').classList.remove('active');
}
function copyShareLink() {
const input = document.getElementById('shareLink');
input.select();
document.execCommand('copy');
alert('Link copied to clipboard!');
}
async function deleteFile(fileId, filename) {
if (!confirm(`Are you sure you want to delete "${filename}"?`)) {
return;
}
try {
const response = await fetch(`/api/files/${fileId}`, {
method: 'DELETE'
});
if (response.ok) {
window.location.reload();
} else {
alert('Delete failed');
}
} catch (error) {
alert('Delete failed: ' + error.message);
}
}
// Close modals when clicking outside
document.querySelectorAll('.modal').forEach(modal => {
modal.addEventListener('click', (e) => {
if (e.target === modal) {
modal.classList.remove('active');
}
});
});
</script>
{% endblock %}