Files
digiserver/templates/upload_content.html
2025-08-05 16:50:46 +03:00

360 lines
17 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Upload Content</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
body.dark-mode {
background-color: #121212;
color: #ffffff;
}
.card.dark-mode {
background-color: #1e1e1e;
color: #ffffff;
}
.dark-mode label, .dark-mode th, .dark-mode td {
color: #ffffff;
}
.logo {
max-height: 100px;
margin-right: 20px;
}
/* Modal styling for dark mode */
.modal-content.dark-mode {
background-color: #1e1e1e;
color: #ffffff;
}
.modal-header.dark-mode {
border-bottom: 1px solid #444;
}
.modal-footer.dark-mode {
border-top: 1px solid #444;
}
.progress-bar {
background-color: #007bff;
}
@media (max-width: 768px) {
h1 {
font-size: 1.5rem;
}
.btn {
font-size: 0.9rem;
padding: 0.5rem 1rem;
}
.card {
margin-bottom: 1rem;
}
}
</style>
</head>
<body class="{{ 'dark-mode' if theme == 'dark' else '' }}">
<div class="container py-5">
<div class="d-flex justify-content-start align-items-center mb-4">
{% if logo_exists %}
<img src="{{ url_for('static', filename='uploads/logo.png') }}" alt="Logo" class="logo">
{% endif %}
<h1 class="mb-0">Upload Content</h1>
</div>
<form id="upload-form" action="{{ url_for('upload_content') }}" method="post" enctype="multipart/form-data" onsubmit="showStatusModal()">
<input type="hidden" name="return_url" value="{{ return_url }}">
<div class="row">
<div class="col-md-6 col-12">
<div class="mb-3">
<label for="target_type" class="form-label">Target Type:</label>
<select name="target_type" id="target_type" class="form-select" required onchange="updateTargetIdOptions()">
<option value="" disabled selected>Select Target Type</option>
<option value="player" {% if target_type == 'player' %}selected{% endif %}>Player</option>
<option value="group" {% if target_type == 'group' %}selected{% endif %}>Group</option>
</select>
</div>
</div>
<div class="col-md-6 col-12">
<div class="mb-3">
<label for="target_id" class="form-label">Target ID:</label>
<select name="target_id" id="target_id" class="form-select" required>
{% if target_type == 'player' %}
<optgroup label="Players">
{% for player in players %}
<option value="{{ player.id }}" {% if target_id == player.id %}selected{% endif %}>{{ player.username }}</option>
{% endfor %}
</optgroup>
{% elif target_type == 'group' %}
<optgroup label="Groups">
{% for group in groups %}
<option value="{{ group.id }}" {% if target_id == group.id %}selected{% endif %}>{{ group.name }}</option>
{% endfor %}
</optgroup>
{% else %}
<option value="" disabled selected>Select a Target ID</option>
{% endif %}
</select>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6 col-12">
<div class="mb-3">
<label for="media_type" class="form-label">Media Type:</label>
<select name="media_type" id="media_type" class="form-select" required>
<option value="image">Image</option>
<option value="video">Video</option>
<option value="pdf">PDF</option>
<option value="ppt">PPT/PPTX</option>
</select>
</div>
</div>
<div class="col-md-6 col-12">
<div class="mb-3">
<label for="files" class="form-label">Files:</label>
<input type="file" name="files" id="files" class="form-control" multiple required onchange="handleFileChange()">
</div>
</div>
</div>
<div class="row">
<div class="col-md-6 col-12">
<div class="mb-3">
<label for="duration" class="form-label">Duration (seconds):</label>
<input type="number" name="duration" id="duration" class="form-control" required>
</div>
</div>
</div>
<div class="text-center">
<button type="submit" id="submit-button" class="btn btn-primary">Upload</button>
<a href="{{ return_url }}" class="btn btn-secondary mt-3">Back</a>
<a href="{{ url_for('dashboard') }}" class="btn btn-secondary mt-3">Back to Dashboard</a>
</div>
</form>
<!-- Modal for Status Updates -->
<div class="modal fade" id="statusModal" tabindex="-1" aria-labelledby="statusModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-lg">
<div class="modal-content {{ 'dark-mode' if theme == 'dark' else '' }}">
<div class="modal-header {{ 'dark-mode' if theme == 'dark' else '' }}">
<h5 class="modal-title" id="statusModalLabel">Processing Files</h5>
</div>
<div class="modal-body">
<p id="status-message">Uploading and processing your files. Please wait...</p>
<div class="progress mb-3">
<div id="progress-bar" class="progress-bar progress-bar-striped progress-bar-animated" role="progressbar" style="width: 0%;" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<!-- Real-time performance monitoring during upload -->
<div class="performance-monitor mt-4">
<h6>System Load During Upload:</h6>
<div class="row">
<div class="col-4">
<small>CPU Usage</small>
<div class="progress mb-1" style="height: 20px;">
<div id="modal-cpu-bar" class="progress-bar bg-info" style="width: 0%;">0%</div>
</div>
</div>
<div class="col-4">
<small>Memory Usage</small>
<div class="progress mb-1" style="height: 20px;">
<div id="modal-memory-bar" class="progress-bar bg-warning" style="width: 0%;">0%</div>
</div>
</div>
<div class="col-4">
<small>Disk Usage</small>
<div class="progress mb-1" style="height: 20px;">
<div id="modal-disk-bar" class="progress-bar bg-danger" style="width: 0%;">0%</div>
</div>
</div>
</div>
<div class="mt-2">
<small id="perf-stats" class="text-muted">Waiting for performance data...</small>
</div>
</div>
</div>
<div class="modal-footer {{ 'dark-mode' if theme == 'dark' else '' }}">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" disabled>Close</button>
</div>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js"></script>
<script>
function updateTargetIdOptions() {
const targetType = document.getElementById('target_type').value;
const targetIdSelect = document.getElementById('target_id');
targetIdSelect.innerHTML = ''; // Clear existing options
if (targetType === 'player') {
const players = {{ players|tojson }};
const optgroup = document.createElement('optgroup');
optgroup.label = 'Players';
players.forEach(player => {
const option = document.createElement('option');
option.value = player.id;
option.textContent = player.username;
optgroup.appendChild(option);
});
targetIdSelect.appendChild(optgroup);
} else if (targetType === 'group') {
const groups = {{ groups|tojson }};
const optgroup = document.createElement('optgroup');
optgroup.label = 'Groups';
groups.forEach(group => {
const option = document.createElement('option');
option.value = group.id;
option.textContent = group.name;
optgroup.appendChild(option);
});
targetIdSelect.appendChild(optgroup);
}
}
function handleFileChange() {
const mediaType = document.getElementById('media_type').value;
const filesInput = document.getElementById('files');
const durationInput = document.getElementById('duration');
if (mediaType === 'video' && filesInput.files.length > 0) {
const file = filesInput.files[0];
const video = document.createElement('video');
video.preload = 'metadata';
video.onloadedmetadata = function () {
window.URL.revokeObjectURL(video.src);
const duration = Math.round(video.duration);
durationInput.value = duration; // Set the duration in the input field
};
video.src = URL.createObjectURL(file);
}
}
function showStatusModal() {
console.log("Processing popup triggered");
const statusModal = new bootstrap.Modal(document.getElementById('statusModal'));
statusModal.show();
// Update status message based on media type
const mediaType = document.getElementById('media_type').value;
const statusMessage = document.getElementById('status-message');
switch(mediaType) {
case 'image':
statusMessage.textContent = 'Uploading images...';
break;
case 'video':
statusMessage.textContent = 'Uploading and processing video. This may take a while...';
break;
case 'pdf':
statusMessage.textContent = 'Converting PDF to images. This may take a while...';
break;
case 'ppt':
statusMessage.textContent = 'Converting PowerPoint to images. This may take a while...';
break;
default:
statusMessage.textContent = 'Uploading and processing your files. Please wait...';
}
// Start performance monitoring during upload
startUploadMonitoring();
// Simulate progress updates
const progressBar = document.getElementById('progress-bar');
let progress = 0;
const interval = setInterval(() => {
// For slow processes, increment more slowly
const increment = (mediaType === 'image') ? 20 : 5;
progress += increment;
if (progress >= 100) {
clearInterval(interval);
stopUploadMonitoring();
statusMessage.textContent = 'Files uploaded and processed successfully!';
// Enable the close button
document.querySelector('[data-bs-dismiss="modal"]').disabled = false;
} else {
progressBar.style.width = `${progress}%`;
progressBar.setAttribute('aria-valuenow', progress);
}
}, 500);
}
// Performance monitoring during upload
let uploadMonitoringInterval = null;
let startCpu = 0, startMemory = 0;
let maxUploadCpu = 0, maxUploadMemory = 0;
function updateModalPerformance(data) {
// Update CPU bar
const cpuBar = document.getElementById('modal-cpu-bar');
cpuBar.style.width = `${data.cpu_percent}%`;
cpuBar.textContent = `${data.cpu_percent.toFixed(1)}%`;
if (data.cpu_percent > 75) cpuBar.className = 'progress-bar bg-danger';
else if (data.cpu_percent > 50) cpuBar.className = 'progress-bar bg-warning';
else cpuBar.className = 'progress-bar bg-info';
// Update Memory bar
const memoryBar = document.getElementById('modal-memory-bar');
memoryBar.style.width = `${data.memory_percent}%`;
memoryBar.textContent = `${data.memory_percent.toFixed(1)}%`;
if (data.memory_percent > 75) memoryBar.className = 'progress-bar bg-danger';
else if (data.memory_percent > 50) memoryBar.className = 'progress-bar bg-warning';
else memoryBar.className = 'progress-bar bg-warning';
// Update Disk bar
const diskBar = document.getElementById('modal-disk-bar');
diskBar.style.width = `${data.disk_percent}%`;
diskBar.textContent = `${data.disk_percent.toFixed(1)}%`;
if (data.disk_percent > 85) diskBar.className = 'progress-bar bg-danger';
else diskBar.className = 'progress-bar bg-danger';
// Track peaks
if (data.cpu_percent > maxUploadCpu) maxUploadCpu = data.cpu_percent;
if (data.memory_percent > maxUploadMemory) maxUploadMemory = data.memory_percent;
// Update stats text
const perfStats = document.getElementById('perf-stats');
const cpuChange = startCpu ? (data.cpu_percent - startCpu).toFixed(1) : '0.0';
const memChange = startMemory ? (data.memory_percent - startMemory).toFixed(1) : '0.0';
perfStats.innerHTML = `CPU: ${cpuChange > 0 ? '+' : ''}${cpuChange}% | Memory: ${memChange > 0 ? '+' : ''}${memChange}% | Peak CPU: ${maxUploadCpu.toFixed(1)}%`;
}
function startUploadMonitoring() {
// Get baseline performance
fetch('/api/performance')
.then(response => response.json())
.then(data => {
if (!data.error) {
startCpu = data.cpu_percent;
startMemory = data.memory_percent;
maxUploadCpu = data.cpu_percent;
maxUploadMemory = data.memory_percent;
updateModalPerformance(data);
}
});
// Start monitoring every 1 second during upload
uploadMonitoringInterval = setInterval(() => {
fetch('/api/performance')
.then(response => response.json())
.then(data => {
if (!data.error) {
updateModalPerformance(data);
}
})
.catch(error => {
console.log('Performance monitoring error:', error);
});
}, 1000);
}
function stopUploadMonitoring() {
if (uploadMonitoringInterval) {
clearInterval(uploadMonitoringInterval);
uploadMonitoringInterval = null;
}
}
</script>
</body>
</html>