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:
@@ -6,7 +6,7 @@ import secrets
|
||||
from typing import Optional, List
|
||||
|
||||
from app.extensions import db, cache
|
||||
from app.models import Player, Group, Content, PlayerFeedback
|
||||
from app.models import Player, Content, PlayerFeedback, Playlist
|
||||
from app.utils.logger import log_action
|
||||
from app.utils.group_player_management import get_player_status_info
|
||||
|
||||
@@ -20,7 +20,7 @@ def list():
|
||||
"""Display list of all players."""
|
||||
try:
|
||||
players = Player.query.order_by(Player.name).all()
|
||||
groups = Group.query.all()
|
||||
playlists = Playlist.query.all()
|
||||
|
||||
# Get player status for each player
|
||||
player_statuses = {}
|
||||
@@ -30,7 +30,7 @@ def list():
|
||||
|
||||
return render_template('players/players_list.html',
|
||||
players=players,
|
||||
groups=groups,
|
||||
playlists=playlists,
|
||||
player_statuses=player_statuses)
|
||||
except Exception as e:
|
||||
log_action('error', f'Error loading players list: {str(e)}')
|
||||
@@ -43,8 +43,7 @@ def list():
|
||||
def add_player():
|
||||
"""Add a new player."""
|
||||
if request.method == 'GET':
|
||||
groups = Group.query.order_by(Group.name).all()
|
||||
return render_template('players/add_player.html', groups=groups)
|
||||
return render_template('players/add_player.html')
|
||||
|
||||
try:
|
||||
name = request.form.get('name', '').strip()
|
||||
@@ -53,7 +52,6 @@ def add_player():
|
||||
password = request.form.get('password', '').strip()
|
||||
quickconnect_code = request.form.get('quickconnect_code', '').strip()
|
||||
orientation = request.form.get('orientation', 'Landscape')
|
||||
group_id = request.form.get('group_id')
|
||||
|
||||
# Validation
|
||||
if not name or len(name) < 3:
|
||||
@@ -83,8 +81,7 @@ def add_player():
|
||||
hostname=hostname,
|
||||
location=location or None,
|
||||
auth_code=auth_code,
|
||||
orientation=orientation,
|
||||
group_id=int(group_id) if group_id else None
|
||||
orientation=orientation
|
||||
)
|
||||
|
||||
# Set password if provided
|
||||
@@ -128,13 +125,11 @@ def edit_player(player_id: int):
|
||||
player = Player.query.get_or_404(player_id)
|
||||
|
||||
if request.method == 'GET':
|
||||
groups = Group.query.order_by(Group.name).all()
|
||||
return render_template('players/edit_player.html', player=player, groups=groups)
|
||||
return render_template('players/edit_player.html', player=player)
|
||||
|
||||
try:
|
||||
name = request.form.get('name', '').strip()
|
||||
location = request.form.get('location', '').strip()
|
||||
group_id = request.form.get('group_id')
|
||||
|
||||
# Validation
|
||||
if not name or len(name) < 3:
|
||||
@@ -144,7 +139,6 @@ def edit_player(player_id: int):
|
||||
# Update player
|
||||
player.name = name
|
||||
player.location = location or None
|
||||
player.group_id = int(group_id) if group_id else None
|
||||
db.session.commit()
|
||||
|
||||
# Clear cache for this player
|
||||
@@ -243,6 +237,88 @@ def player_page(player_id: int):
|
||||
return redirect(url_for('players.list'))
|
||||
|
||||
|
||||
@players_bp.route('/<int:player_id>/manage', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
def manage_player(player_id: int):
|
||||
"""Manage player - edit credentials, assign playlist, view logs."""
|
||||
player = Player.query.get_or_404(player_id)
|
||||
|
||||
if request.method == 'POST':
|
||||
action = request.form.get('action')
|
||||
|
||||
try:
|
||||
if action == 'update_credentials':
|
||||
# Update player name, location, orientation
|
||||
name = request.form.get('name', '').strip()
|
||||
location = request.form.get('location', '').strip()
|
||||
orientation = request.form.get('orientation', 'Landscape')
|
||||
|
||||
if not name or len(name) < 3:
|
||||
flash('Player name must be at least 3 characters long.', 'warning')
|
||||
return redirect(url_for('players.manage_player', player_id=player_id))
|
||||
|
||||
player.name = name
|
||||
player.location = location or None
|
||||
player.orientation = orientation
|
||||
db.session.commit()
|
||||
|
||||
log_action('info', f'Player "{name}" credentials updated')
|
||||
flash(f'Player "{name}" updated successfully.', 'success')
|
||||
|
||||
elif action == 'assign_playlist':
|
||||
# Assign playlist to player
|
||||
playlist_id = request.form.get('playlist_id')
|
||||
|
||||
if playlist_id:
|
||||
playlist = Playlist.query.get(int(playlist_id))
|
||||
if playlist:
|
||||
player.playlist_id = int(playlist_id)
|
||||
db.session.commit()
|
||||
cache.delete_memoized(get_player_playlist, player_id)
|
||||
log_action('info', f'Player "{player.name}" assigned to playlist "{playlist.name}"')
|
||||
flash(f'Player assigned to playlist "{playlist.name}".', 'success')
|
||||
else:
|
||||
flash('Invalid playlist selected.', 'warning')
|
||||
else:
|
||||
# Unassign playlist
|
||||
player.playlist_id = None
|
||||
db.session.commit()
|
||||
cache.delete_memoized(get_player_playlist, player_id)
|
||||
log_action('info', f'Player "{player.name}" unassigned from playlist')
|
||||
flash('Player unassigned from playlist.', 'success')
|
||||
|
||||
except Exception as e:
|
||||
db.session.rollback()
|
||||
log_action('error', f'Error managing player: {str(e)}')
|
||||
flash('Error updating player. Please try again.', 'danger')
|
||||
|
||||
return redirect(url_for('players.manage_player', player_id=player_id))
|
||||
|
||||
# GET request - show manage page
|
||||
playlists = Playlist.query.order_by(Playlist.name).all()
|
||||
|
||||
# Get player's current playlist
|
||||
current_playlist = None
|
||||
if player.playlist_id:
|
||||
current_playlist = Playlist.query.get(player.playlist_id)
|
||||
|
||||
# Get recent feedback/logs from player
|
||||
recent_logs = PlayerFeedback.query.filter_by(player_id=player_id)\
|
||||
.order_by(PlayerFeedback.timestamp.desc())\
|
||||
.limit(20)\
|
||||
.all()
|
||||
|
||||
# Get player status
|
||||
status_info = get_player_status_info(player_id)
|
||||
|
||||
return render_template('players/manage_player.html',
|
||||
player=player,
|
||||
playlists=playlists,
|
||||
current_playlist=current_playlist,
|
||||
recent_logs=recent_logs,
|
||||
status_info=status_info)
|
||||
|
||||
|
||||
@players_bp.route('/<int:player_id>/fullscreen')
|
||||
def player_fullscreen(player_id: int):
|
||||
"""Display player fullscreen view (no authentication required for players)."""
|
||||
@@ -303,35 +379,11 @@ def get_player_playlist(player_id: int) -> List[dict]:
|
||||
@players_bp.route('/<int:player_id>/reorder', methods=['POST'])
|
||||
@login_required
|
||||
def reorder_content(player_id: int):
|
||||
"""Reorder content for a player's group."""
|
||||
try:
|
||||
player = Player.query.get_or_404(player_id)
|
||||
|
||||
if not player.group_id:
|
||||
flash('Player is not assigned to a group.', 'warning')
|
||||
return redirect(url_for('players.player_page', player_id=player_id))
|
||||
|
||||
# Get new order from request
|
||||
content_order = request.json.get('order', [])
|
||||
|
||||
# Update positions
|
||||
for idx, content_id in enumerate(content_order):
|
||||
content = Content.query.get(content_id)
|
||||
if content and content in player.group.contents:
|
||||
content.position = idx
|
||||
|
||||
db.session.commit()
|
||||
|
||||
# Clear cache
|
||||
cache.delete_memoized(get_player_playlist, player_id)
|
||||
|
||||
log_action('info', f'Content reordered for player {player_id}')
|
||||
return jsonify({'success': True})
|
||||
|
||||
except Exception as e:
|
||||
db.session.rollback()
|
||||
log_action('error', f'Error reordering content: {str(e)}')
|
||||
return jsonify({'success': False, 'error': str(e)}), 500
|
||||
"""Legacy endpoint - Content reordering now handled in playlist management."""
|
||||
return jsonify({
|
||||
'success': False,
|
||||
'error': 'Content reordering is now managed through playlists. Use the Playlists page to reorder content.'
|
||||
}), 400
|
||||
|
||||
|
||||
@players_bp.route('/bulk/delete', methods=['POST'])
|
||||
@@ -366,35 +418,35 @@ def bulk_delete_players():
|
||||
return jsonify({'success': False, 'error': str(e)}), 500
|
||||
|
||||
|
||||
@players_bp.route('/bulk/assign-group', methods=['POST'])
|
||||
@players_bp.route('/bulk/assign-playlist', methods=['POST'])
|
||||
@login_required
|
||||
def bulk_assign_group():
|
||||
"""Assign multiple players to a group."""
|
||||
def bulk_assign_playlist():
|
||||
"""Assign multiple players to a playlist."""
|
||||
try:
|
||||
player_ids = request.json.get('player_ids', [])
|
||||
group_id = request.json.get('group_id')
|
||||
playlist_id = request.json.get('playlist_id')
|
||||
|
||||
if not player_ids:
|
||||
return jsonify({'success': False, 'error': 'No players selected'}), 400
|
||||
|
||||
# Validate group
|
||||
if group_id:
|
||||
group = Group.query.get(group_id)
|
||||
if not group:
|
||||
return jsonify({'success': False, 'error': 'Invalid group'}), 400
|
||||
# Validate playlist
|
||||
if playlist_id:
|
||||
playlist = Playlist.query.get(playlist_id)
|
||||
if not playlist:
|
||||
return jsonify({'success': False, 'error': 'Invalid playlist'}), 400
|
||||
|
||||
# Assign players
|
||||
updated_count = 0
|
||||
for player_id in player_ids:
|
||||
player = Player.query.get(player_id)
|
||||
if player:
|
||||
player.group_id = group_id
|
||||
player.playlist_id = playlist_id
|
||||
cache.delete_memoized(get_player_playlist, player_id)
|
||||
updated_count += 1
|
||||
|
||||
db.session.commit()
|
||||
|
||||
log_action('info', f'Bulk assigned {updated_count} players to group {group_id}')
|
||||
log_action('info', f'Bulk assigned {updated_count} players to playlist {playlist_id}')
|
||||
return jsonify({'success': True, 'updated': updated_count})
|
||||
|
||||
except Exception as e:
|
||||
|
||||
Reference in New Issue
Block a user