re-Made server totally - version 1.0 now come.
This commit is contained in:
228
templates/user_files.html
Normal file
228
templates/user_files.html
Normal file
@@ -0,0 +1,228 @@
|
||||
{% 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 %}
|
||||
Reference in New Issue
Block a user