updated digiserver 2

This commit is contained in:
ske087
2025-11-12 16:07:03 +02:00
parent 2deb398fd8
commit e5a00d19a5
44 changed files with 2656 additions and 230 deletions

View File

@@ -0,0 +1,205 @@
{% extends "base.html" %}
{% block title %}Content Library - DigiServer v2{% endblock %}
{% block content %}
<div class="container">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
<h1>Content Library</h1>
<a href="{{ url_for('content.upload_content') }}" class="btn btn-success">+ Upload Content</a>
</div>
{% if content_list %}
<div class="card">
<div style="margin-bottom: 15px; padding: 15px; background: #f8f9fa; border-radius: 5px;">
<strong>Total Files:</strong> {{ content_list|length }} |
<strong>Total Assignments:</strong> {% set total = namespace(count=0) %}{% for item in content_list %}{% set total.count = total.count + item.player_count %}{% endfor %}{{ total.count }}
</div>
<table style="width: 100%; border-collapse: collapse;">
<thead>
<tr style="background: #f8f9fa; text-align: left;">
<th style="padding: 12px; border-bottom: 2px solid #dee2e6;">File Name</th>
<th style="padding: 12px; border-bottom: 2px solid #dee2e6;">Type</th>
<th style="padding: 12px; border-bottom: 2px solid #dee2e6;">Duration</th>
<th style="padding: 12px; border-bottom: 2px solid #dee2e6;">Size</th>
<th style="padding: 12px; border-bottom: 2px solid #dee2e6;">Assigned To</th>
<th style="padding: 12px; border-bottom: 2px solid #dee2e6;">Uploaded</th>
<th style="padding: 12px; border-bottom: 2px solid #dee2e6;">Actions</th>
</tr>
</thead>
<tbody>
{% for item in content_list %}
<tr style="border-bottom: 1px solid #dee2e6;">
<td style="padding: 12px;">
<strong>{{ item.filename }}</strong>
</td>
<td style="padding: 12px;">
{% if item.content_type == 'image' %}
<span style="background: #28a745; color: white; padding: 3px 8px; border-radius: 3px; font-size: 12px;">📷 Image</span>
{% elif item.content_type == 'video' %}
<span style="background: #007bff; color: white; padding: 3px 8px; border-radius: 3px; font-size: 12px;">🎬 Video</span>
{% elif item.content_type == 'pdf' %}
<span style="background: #dc3545; color: white; padding: 3px 8px; border-radius: 3px; font-size: 12px;">📄 PDF</span>
{% elif item.content_type == 'presentation' %}
<span style="background: #ffc107; color: black; padding: 3px 8px; border-radius: 3px; font-size: 12px;">📊 PPT</span>
{% else %}
<span style="background: #6c757d; color: white; padding: 3px 8px; border-radius: 3px; font-size: 12px;">📁 Other</span>
{% endif %}
</td>
<td style="padding: 12px;">
{{ item.duration }}s
</td>
<td style="padding: 12px;">
{{ item.file_size }} MB
</td>
<td style="padding: 12px;">
{% if item.player_count == 0 %}
<span style="color: #6c757d; font-style: italic;">Not assigned</span>
{% else %}
<div style="max-height: 100px; overflow-y: auto;">
{% for player in item.players %}
<div style="margin-bottom: 5px;">
<strong>{{ player.name }}</strong>
{% if player.group %}
<span style="color: #6c757d; font-size: 12px;">({{ player.group }})</span>
{% endif %}
</div>
{% endfor %}
</div>
<div style="margin-top: 5px;">
<span style="background: #007bff; color: white; padding: 2px 6px; border-radius: 3px; font-size: 11px;">
{{ item.player_count }} player{% if item.player_count != 1 %}s{% endif %}
</span>
</div>
{% endif %}
</td>
<td style="padding: 12px;">
<small style="color: #6c757d;">{{ item.uploaded_at.strftime('%Y-%m-%d %H:%M') }}</small>
</td>
<td style="padding: 12px;">
{% if item.player_count > 0 %}
{% set first_player = item.players[0] %}
<a href="{{ url_for('players.player_page', player_id=first_player.id) }}"
class="btn btn-primary btn-sm"
title="Manage Playlist for {{ first_player.name }}"
style="margin-bottom: 5px;">
📝 Manage Playlist
</a>
{% if item.player_count > 1 %}
<button onclick="showAllPlayers('{{ item.filename|replace("'", "\\'") }}', {{ item.players|tojson }})"
class="btn btn-info btn-sm"
title="View all players with this content">
👥 View All ({{ item.player_count }})
</button>
{% endif %}
{% endif %}
<button onclick="deleteContent('{{ item.filename|replace("'", "\\'") }}')"
class="btn btn-danger btn-sm"
title="Delete this content from all playlists"
style="margin-top: 5px;">
🗑️ Delete
</button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div style="background: #d1ecf1; border: 1px solid #bee5eb; color: #0c5460; padding: 15px; border-radius: 5px;">
No content uploaded yet. <a href="{{ url_for('content.upload_content') }}" style="color: #0c5460; text-decoration: underline;">Upload your first content</a>
</div>
{% endif %}
</div>
<!-- Modal for viewing all players -->
<div id="playersModal" class="modal" style="display: none;">
<div class="modal-content" style="max-width: 600px; margin: 100px auto; background: white; padding: 30px; border-radius: 8px; box-shadow: 0 4px 20px rgba(0,0,0,0.3);">
<h2 id="modalTitle" style="margin-bottom: 20px; color: #2c3e50;">Players with this content</h2>
<div id="playersList" style="max-height: 400px; overflow-y: auto;"></div>
<div style="text-align: center; margin-top: 20px;">
<button type="button" class="btn" onclick="closePlayersModal()">Close</button>
</div>
</div>
</div>
<style>
.modal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
z-index: 9999;
overflow-y: auto;
}
</style>
<script>
function showAllPlayers(filename, players) {
document.getElementById('modalTitle').textContent = 'Players with: ' + filename;
const playersList = document.getElementById('playersList');
playersList.innerHTML = '<table style="width: 100%; border-collapse: collapse;">';
playersList.innerHTML += '<thead><tr style="background: #f8f9fa;"><th style="padding: 10px; text-align: left;">Player Name</th><th style="padding: 10px; text-align: left;">Group</th><th style="padding: 10px; text-align: left;">Action</th></tr></thead><tbody>';
players.forEach(player => {
playersList.innerHTML += `
<tr style="border-bottom: 1px solid #dee2e6;">
<td style="padding: 10px;"><strong>${player.name}</strong></td>
<td style="padding: 10px;">${player.group || '-'}</td>
<td style="padding: 10px;">
<a href="/players/${player.id}" class="btn btn-sm" style="background: #007bff; color: white; padding: 5px 10px; text-decoration: none; border-radius: 3px;">
Manage Playlist
</a>
</td>
</tr>
`;
});
playersList.innerHTML += '</tbody></table>';
document.getElementById('playersModal').style.display = 'block';
}
function closePlayersModal() {
document.getElementById('playersModal').style.display = 'none';
}
function deleteContent(filename) {
if (confirm(`Are you sure you want to delete "${filename}"?\n\nThis will remove it from ALL player playlists!`)) {
fetch('/content/delete-by-filename', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
filename: filename
})
})
.then(response => response.json())
.then(data => {
if (data.success) {
alert(`Successfully deleted "${filename}" from ${data.deleted_count} playlist(s)`);
location.reload();
} else {
alert('Error deleting content: ' + data.message);
}
})
.catch(error => {
alert('Error deleting content: ' + error);
});
}
}
// Close modal when clicking outside
window.onclick = function(event) {
const modal = document.getElementById('playersModal');
if (event.target == modal) {
closePlayersModal();
}
}
</script>
{% endblock %}