feat(digiserver-v2): port edited media report and deploy badge features from standalone
- Added edited_media_report route to players blueprint with tabular report view - Created edited_media_report.html template with summary stats, dark mode, print/PDF support - Created _deploy_badge.html partial template for deployment status display - Added deployment status column and badge CSS to players_list.html - Added 'View Report' button to manage_player.html next to 'View All Edited Media' - Fixed api.py receive_edited_media with robust content lookup: - Fallback content lookup by regex path matching (edited_media/<id>/) - Fallback via PlayerEdit record if direct lookup fails - First-edit original file preservation (moves original to versionized folder) Enterprise-specific features (portal SSO, internal sync, playlist permissions, WAL mode) are preserved unchanged.
This commit is contained in:
@@ -765,6 +765,8 @@ def receive_edited_media():
|
||||
|
||||
# Import required modules
|
||||
import os
|
||||
import shutil
|
||||
import re
|
||||
from werkzeug.utils import secure_filename
|
||||
from app.models.player_edit import PlayerEdit
|
||||
|
||||
@@ -772,6 +774,19 @@ def receive_edited_media():
|
||||
original_name = metadata['original_name']
|
||||
content = Content.query.filter_by(filename=original_name).first()
|
||||
|
||||
if not content:
|
||||
# Try to extract content_id from a path like "edited_media/<id>/file"
|
||||
m = re.match(r'edited_media/(\d+)/', original_name)
|
||||
if m:
|
||||
content = db.session.get(Content, int(m.group(1)))
|
||||
if not content:
|
||||
# Last resort – look up the most recent PlayerEdit for this
|
||||
# content and use its content_id.
|
||||
fallback_edit = PlayerEdit.query.filter_by(new_name=original_name)\
|
||||
.order_by(PlayerEdit.created_at.desc()).first()
|
||||
if fallback_edit:
|
||||
content = db.session.get(Content, fallback_edit.content_id)
|
||||
|
||||
if not content:
|
||||
log_action('warning', f'Player {player.name} tried to edit non-existent content: {original_name}')
|
||||
return jsonify({'error': f'Original content not found: {original_name}'}), 404
|
||||
@@ -781,20 +796,31 @@ def receive_edited_media():
|
||||
edited_media_dir = os.path.join(base_upload_dir, 'edited_media', str(content.id))
|
||||
os.makedirs(edited_media_dir, exist_ok=True)
|
||||
|
||||
# On the very first edit (v1) move the original file into the
|
||||
# versionized folder so it is never orphaned.
|
||||
is_first_edit = PlayerEdit.query.filter_by(content_id=content.id).count() == 0
|
||||
if is_first_edit:
|
||||
orig_upload = os.path.join(base_upload_dir, content.filename)
|
||||
# content.filename might already be an edited_media/ path if
|
||||
# this is a re-process; only move if it's a plain filename.
|
||||
if os.path.isfile(orig_upload) and not content.filename.startswith('edited_media/'):
|
||||
orig_stored = f"original_{content.filename}"
|
||||
shutil.move(orig_upload, os.path.join(edited_media_dir, orig_stored))
|
||||
log_action('info', f'Moved original file "{content.filename}" to versionized folder as "{orig_stored}"')
|
||||
|
||||
# Save the edited file with version suffix
|
||||
version = metadata['version']
|
||||
new_filename = metadata['new_name']
|
||||
edited_file_path = os.path.join(edited_media_dir, new_filename)
|
||||
file.save(edited_file_path)
|
||||
|
||||
# Save metadata JSON file
|
||||
# Save metadata JSON side-car file
|
||||
metadata_filename = f"{os.path.splitext(new_filename)[0]}_metadata.json"
|
||||
metadata_path = os.path.join(edited_media_dir, metadata_filename)
|
||||
with open(metadata_path, 'w') as f:
|
||||
json.dump(metadata, f, indent=2)
|
||||
|
||||
# Update the content record to reference the edited version path
|
||||
# Keep original filename unchanged, point to edited_media folder
|
||||
old_filename = content.filename
|
||||
content.filename = f"edited_media/{content.id}/{new_filename}"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user