Replace emoji icons with local SVG files for consistent rendering

- Created 10 SVG icon files in app/static/icons/ (Feather Icons style)
- Updated base.html with SVG icons in navigation and dark mode toggle
- Updated dashboard.html with icons in stats cards and quick actions
- Updated content_list_new.html (playlist management) with SVG icons
- Updated upload_media.html with upload-related icons
- Updated manage_player.html with player management icons
- Icons use currentColor for automatic theme adaptation
- Removed emoji dependency for better Raspberry Pi compatibility
- Added ICON_INTEGRATION.md documentation
This commit is contained in:
ske087
2025-11-13 21:00:07 +02:00
parent e5a00d19a5
commit 498c03ef00
37 changed files with 4240 additions and 840 deletions

View File

@@ -27,8 +27,8 @@
<a href="{{ url_for('players.edit_player', player_id=player.id) }}" class="btn btn-primary">
✏️ Edit Player
</a>
<a href="{{ url_for('content.upload_content', target_type='player', target_id=player.id, return_url=url_for('players.player_page', player_id=player.id)) }}" class="btn btn-success">
📤 Upload Content
<a href="{{ url_for('playlist.manage_playlist', player_id=player.id) }}" class="btn btn-success">
🎬 Manage Playlist
</a>
<a href="{{ url_for('players.list') }}" class="btn">
← Back to Players
@@ -62,18 +62,6 @@
<td style="padding: 10px; font-weight: bold;">Orientation:</td>
<td style="padding: 10px;">{{ player.orientation or 'Landscape' }}</td>
</tr>
<tr style="border-bottom: 1px solid #dee2e6;">
<td style="padding: 10px; font-weight: bold;">Group:</td>
<td style="padding: 10px;">
{% if player.group %}
<span style="background: #007bff; color: white; padding: 3px 8px; border-radius: 3px; font-size: 12px;">
{{ player.group.name }}
</span>
{% else %}
<span style="color: #6c757d;">No group</span>
{% endif %}
</td>
</tr>
<tr>
<td style="padding: 10px; font-weight: bold;">Created:</td>
<td style="padding: 10px;">{{ player.created_at.strftime('%Y-%m-%d %H:%M') }}</td>
@@ -138,77 +126,43 @@
<!-- Playlist Management Card -->
<div class="card" style="margin-bottom: 20px;">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px;">
<h3 style="margin: 0;">🎬 Current Playlist</h3>
<div>
<a href="{{ url_for('content.upload_content', target_type='player', target_id=player.id, return_url=url_for('players.player_page', player_id=player.id)) }}"
class="btn btn-success btn-sm">
+ Add Content
</a>
</div>
<h3 style="margin: 0;">🎬 Playlist Management</h3>
</div>
{% if playlist %}
<div style="background: #f8f9fa; padding: 10px; border-radius: 5px; margin-bottom: 15px;">
<strong>Total Items:</strong> {{ playlist|length }} |
<strong>Total Duration:</strong> {% set total_duration = namespace(value=0) %}{% for item in playlist %}{% set total_duration.value = total_duration.value + (item.duration or 10) %}{% endfor %}{{ total_duration.value }}s
<div style="background: #f8f9fa; padding: 15px; border-radius: 5px; margin-bottom: 15px;">
<div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px;">
<div>
<div style="font-size: 12px; color: #6c757d; margin-bottom: 5px;">Total Items</div>
<div style="font-size: 24px; font-weight: bold; color: #333;">{{ playlist|length }}</div>
</div>
<div>
<div style="font-size: 12px; color: #6c757d; margin-bottom: 5px;">Total Duration</div>
<div style="font-size: 24px; font-weight: bold; color: #333;">
{% set total_duration = namespace(value=0) %}
{% for item in playlist %}
{% set total_duration.value = total_duration.value + (item.duration or 10) %}
{% endfor %}
{{ total_duration.value }}s
</div>
</div>
<div>
<div style="font-size: 12px; color: #6c757d; margin-bottom: 5px;">Playlist Version</div>
<div style="font-size: 24px; font-weight: bold; color: #333;">{{ player.playlist_version }}</div>
</div>
</div>
</div>
{% endif %}
<table style="width: 100%; border-collapse: collapse;">
<thead>
<tr style="background: #f8f9fa; text-align: left;">
<th style="padding: 10px; border-bottom: 2px solid #dee2e6; width: 50px;">Order</th>
<th style="padding: 10px; border-bottom: 2px solid #dee2e6;">File Name</th>
<th style="padding: 10px; border-bottom: 2px solid #dee2e6;">Type</th>
<th style="padding: 10px; border-bottom: 2px solid #dee2e6;">Duration</th>
<th style="padding: 10px; border-bottom: 2px solid #dee2e6;">Actions</th>
</tr>
</thead>
<tbody id="playlist-items">
{% for item in playlist %}
<tr style="border-bottom: 1px solid #dee2e6;" data-content-id="{{ item.id }}">
<td style="padding: 10px; text-align: center;">
<strong>{{ loop.index }}</strong>
</td>
<td style="padding: 10px;">
{{ item.filename }}
</td>
<td style="padding: 10px;">
{% if item.type == 'image' %}
<span style="background: #28a745; color: white; padding: 3px 8px; border-radius: 3px; font-size: 12px;">📷 Image</span>
{% elif item.type == 'video' %}
<span style="background: #007bff; color: white; padding: 3px 8px; border-radius: 3px; font-size: 12px;">🎬 Video</span>
{% elif item.type == 'pdf' %}
<span style="background: #dc3545; color: white; padding: 3px 8px; border-radius: 3px; font-size: 12px;">📄 PDF</span>
{% else %}
<span style="background: #6c757d; color: white; padding: 3px 8px; border-radius: 3px; font-size: 12px;">📁 Other</span>
{% endif %}
</td>
<td style="padding: 10px;">
{{ item.duration or 10 }}s
</td>
<td style="padding: 10px;">
<button onclick="moveUp({{ item.id }})" class="btn btn-sm"
style="background: #007bff; color: white; padding: 3px 8px; margin-right: 5px;"
{% if loop.first %}disabled{% endif %}>
</button>
<button onclick="moveDown({{ item.id }})" class="btn btn-sm"
style="background: #007bff; color: white; padding: 3px 8px; margin-right: 5px;"
{% if loop.last %}disabled{% endif %}>
</button>
<button onclick="removeFromPlaylist({{ item.id }}, '{{ item.filename }}')"
class="btn btn-danger btn-sm" style="padding: 3px 8px;">
🗑️ Remove
</button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<div style="background: #fff3cd; border: 1px solid #ffc107; color: #856404; padding: 15px; border-radius: 5px; text-align: center;">
⚠️ No content in playlist. <a href="{{ url_for('content.upload_content', target_type='player', target_id=player.id, return_url=url_for('players.player_page', player_id=player.id)) }}" style="color: #856404; text-decoration: underline;">Upload content</a> to get started.
<a href="{{ url_for('playlist.manage_playlist', player_id=player.id) }}"
class="btn btn-primary"
style="display: inline-block; width: 100%; text-align: center; padding: 15px; font-size: 16px;">
🎬 Open Playlist Manager
</a>
{% if not playlist %}
<div style="background: #fff3cd; border: 1px solid #ffc107; color: #856404; padding: 15px; border-radius: 5px; text-align: center; margin-top: 15px;">
⚠️ No content in playlist. Open the playlist manager to add content.
</div>
{% endif %}
</div>
@@ -270,62 +224,4 @@
</div>
</div>
<script>
function moveUp(contentId) {
updatePlaylistOrder(contentId, 'up');
}
function moveDown(contentId) {
updatePlaylistOrder(contentId, 'down');
}
function updatePlaylistOrder(contentId, direction) {
fetch('/players/{{ player.id }}/playlist/reorder', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
content_id: contentId,
direction: direction
})
})
.then(response => response.json())
.then(data => {
if (data.success) {
location.reload();
} else {
alert('Error reordering playlist: ' + data.message);
}
})
.catch(error => {
alert('Error reordering playlist: ' + error);
});
}
function removeFromPlaylist(contentId, filename) {
if (confirm(`Remove "${filename}" from this player's playlist?`)) {
fetch('/players/{{ player.id }}/playlist/remove', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
content_id: contentId
})
})
.then(response => response.json())
.then(data => {
if (data.success) {
location.reload();
} else {
alert('Error removing content: ' + data.message);
}
})
.catch(error => {
alert('Error removing content: ' + error);
});
}
}
</script>
{% endblock %}