updated to get card name

This commit is contained in:
DigiServer Developer
2025-12-13 21:51:45 +02:00
parent 0dfeb0ef7f
commit 87709bab4d
12 changed files with 347 additions and 33 deletions

View File

@@ -772,3 +772,79 @@ def upload_login_logo():
flash(f'Error uploading logo: {str(e)}', 'danger')
return redirect(url_for('admin.customize_logos'))
@admin_bp.route('/editing-users')
@login_required
@admin_required
def manage_editing_users():
"""Display and manage users that edit images on players."""
try:
from app.models.player_user import PlayerUser
from app.models.player_edit import PlayerEdit
# Get all editing users
users = PlayerUser.query.order_by(PlayerUser.created_at.desc()).all()
# Get edit counts for each user
user_stats = {}
for user in users:
edit_count = PlayerEdit.query.filter_by(user=user.user_code).count()
user_stats[user.user_code] = edit_count
return render_template('admin/editing_users.html',
users=users,
user_stats=user_stats)
except Exception as e:
log_action('error', f'Error loading editing users: {str(e)}')
flash('Error loading editing users.', 'danger')
return redirect(url_for('admin.admin_panel'))
@admin_bp.route('/editing-users/<int:user_id>/update', methods=['POST'])
@login_required
@admin_required
def update_editing_user(user_id: int):
"""Update editing user name."""
try:
from app.models.player_user import PlayerUser
user = PlayerUser.query.get_or_404(user_id)
user_name = request.form.get('user_name', '').strip()
user.user_name = user_name if user_name else None
user.updated_at = datetime.utcnow()
db.session.commit()
log_action('info', f'Updated editing user {user.user_code} name to: {user_name or "None"}')
flash('User name updated successfully!', 'success')
except Exception as e:
db.session.rollback()
log_action('error', f'Error updating editing user: {str(e)}')
flash(f'Error updating user: {str(e)}', 'danger')
return redirect(url_for('admin.manage_editing_users'))
@admin_bp.route('/editing-users/<int:user_id>/delete', methods=['POST'])
@login_required
@admin_required
def delete_editing_user(user_id: int):
"""Delete editing user."""
try:
from app.models.player_user import PlayerUser
user = PlayerUser.query.get_or_404(user_id)
user_code = user.user_code
db.session.delete(user)
db.session.commit()
log_action('info', f'Deleted editing user: {user_code}')
flash('User deleted successfully!', 'success')
except Exception as e:
db.session.rollback()
log_action('error', f'Error deleting editing user: {str(e)}')
flash(f'Error deleting user: {str(e)}', 'danger')
return redirect(url_for('admin.manage_editing_users'))

View File

@@ -794,13 +794,23 @@ def receive_edited_media():
except:
time_of_mod = datetime.utcnow()
# Auto-create PlayerUser record if user code is provided
user_code = metadata.get('user')
if user_code:
from app.models.player_user import PlayerUser
existing_user = PlayerUser.query.filter_by(user_code=user_code).first()
if not existing_user:
new_user = PlayerUser(user_code=user_code)
db.session.add(new_user)
log_action('info', f'Auto-created PlayerUser record for code: {user_code}')
edit_record = PlayerEdit(
player_id=player.id,
content_id=content.id,
original_name=original_name,
new_name=new_filename,
version=version,
user=metadata.get('user'),
user=user_code,
time_of_modification=time_of_mod,
metadata_path=metadata_path,
edited_file_path=edited_file_path

View File

@@ -343,6 +343,7 @@ def edited_media(player_id: int):
# Get all edited media history from player
from app.models.player_edit import PlayerEdit
edited_media = PlayerEdit.query.filter_by(player_id=player_id)\
.order_by(PlayerEdit.created_at.desc())\
.all()

View File

@@ -7,6 +7,7 @@ from app.models.content import Content
from app.models.server_log import ServerLog
from app.models.player_feedback import PlayerFeedback
from app.models.player_edit import PlayerEdit
from app.models.player_user import PlayerUser
__all__ = [
'User',
@@ -17,6 +18,7 @@ __all__ = [
'ServerLog',
'PlayerFeedback',
'PlayerEdit',
'PlayerUser',
'group_content',
'playlist_content',
]

37
app/models/player_user.py Normal file
View File

@@ -0,0 +1,37 @@
"""Player user model for managing user codes and names."""
from datetime import datetime
from app.extensions import db
class PlayerUser(db.Model):
"""Player user model for managing user codes and names globally.
Attributes:
id: Primary key
user_code: User code received from player (unique)
user_name: Display name for the user
created_at: Record creation timestamp
updated_at: Record update timestamp
"""
__tablename__ = 'player_user'
id = db.Column(db.Integer, primary_key=True)
user_code = db.Column(db.String(255), nullable=False, unique=True, index=True)
user_name = db.Column(db.String(255), nullable=True)
created_at = db.Column(db.DateTime, default=datetime.utcnow, nullable=False)
updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)
def __repr__(self) -> str:
"""String representation of PlayerUser."""
return f'<PlayerUser {self.user_code} -> {self.user_name or "Unnamed"}>'
def to_dict(self) -> dict:
"""Convert to dictionary for API responses."""
return {
'id': self.id,
'user_code': self.user_code,
'user_name': self.user_name,
'created_at': self.created_at.isoformat() if self.created_at else None,
'updated_at': self.updated_at.isoformat() if self.updated_at else None,
}

View File

@@ -56,6 +56,9 @@
<a href="{{ url_for('admin.user_management') }}" class="btn btn-primary">
Manage Users
</a>
<a href="{{ url_for('admin.manage_editing_users') }}" class="btn btn-secondary" style="margin-left: 0.5rem;">
Manage Users That Edited Images
</a>
</div>
</div>

View File

@@ -0,0 +1,105 @@
{% extends "base.html" %}
{% block title %}Manage Editing Users{% endblock %}
{% block content %}
<div style="margin-bottom: 2rem;">
<div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 1rem;">
<div style="display: flex; align-items: center; gap: 1rem;">
<a href="{{ url_for('admin.admin_panel') }}"
class="btn"
style="background: #6c757d; color: white; padding: 0.5rem 1rem; text-decoration: none; border-radius: 6px;">
← Back to Admin
</a>
<h1 style="margin: 0;">👤 Manage Editing Users</h1>
</div>
</div>
<p style="color: #6c757d;">Manage users who edit images on players. User codes are automatically created from player metadata.</p>
</div>
{% if users %}
<div class="card">
<div class="card-header">
<h3 style="margin: 0;">Editing Users ({{ users|length }})</h3>
</div>
<div class="card-body" style="padding: 0;">
<table class="table" style="margin: 0;">
<thead>
<tr>
<th style="width: 30%;">User Code</th>
<th style="width: 30%;">Display Name</th>
<th style="width: 15%;">Edits Count</th>
<th style="width: 15%;">Created</th>
<th style="width: 10%;">Actions</th>
</tr>
</thead>
<tbody>
{% for user in users %}
<tr>
<td style="font-family: monospace; font-weight: 600;">{{ user.user_code }}</td>
<td>
<form method="POST" action="{{ url_for('admin.update_editing_user', user_id=user.id) }}" style="display: flex; gap: 0.5rem; align-items: center;">
<input type="text"
name="user_name"
value="{{ user.user_name or '' }}"
placeholder="Enter display name"
class="form-control"
style="flex: 1;">
<button type="submit" class="btn btn-sm btn-primary">Save</button>
</form>
</td>
<td>
<span class="badge badge-info">{{ user_stats.get(user.user_code, 0) }} edits</span>
</td>
<td>{{ user.created_at | localtime('%Y-%m-%d %H:%M') }}</td>
<td>
<form method="POST"
action="{{ url_for('admin.delete_editing_user', user_id=user.id) }}"
style="display: inline;"
onsubmit="return confirm('Are you sure you want to delete this user? This will not delete their edit history.');">
<button type="submit" class="btn btn-sm btn-danger">Delete</button>
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% else %}
<div class="card" style="text-align: center; padding: 4rem 2rem;">
<div style="font-size: 4rem; margin-bottom: 1rem; opacity: 0.5;">👤</div>
<h2 style="color: #6c757d; margin-bottom: 1rem;">No Editing Users Yet</h2>
<p style="color: #6c757d; font-size: 1.1rem;">
User codes will appear here automatically when players edit media files.
</p>
</div>
{% endif %}
<style>
body.dark-mode .table {
color: #e2e8f0;
}
body.dark-mode .table thead th {
background: #2d3748;
color: #e2e8f0;
border-color: #4a5568;
}
body.dark-mode .table tbody tr {
border-color: #4a5568;
}
body.dark-mode .table tbody tr:hover {
background: #2d3748;
}
body.dark-mode .form-control {
background: #2d3748;
color: #e2e8f0;
border-color: #4a5568;
}
</style>
{% endblock %}