23740af816
Coordinators can configure, per task type, accepted file extensions, a
naming convention, and (for video files) required resolution/format/
codec/frame rate. All checking happens entirely client-side in the
browser before upload - the backend only stores and validates the
configuration itself, never inspects submitted files.
- backend: submission_config_by_task_type JSON column on Project,
schemas/submission_config.py for validation, GET/PUT
/projects/{id}/submission-config endpoints. Added .mxf/.ma/.usd(a/c)
to the supported file formats.
- frontend: new Submissions tab in Project Settings
(SubmissionConfigManager.vue) to configure rules per task type.
TaskSubmissions.vue enforces them before upload: extension/naming
checks via regex, and real video resolution/codec/frame rate
detection via mediainfo.js (parses container metadata directly,
so it works for formats browsers can't play natively like MXF,
ProRes, or DNxHD).
86 lines
2.4 KiB
Python
86 lines
2.4 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Migration script to add the submission_config_by_task_type column to the projects table.
|
|
|
|
Usage:
|
|
python migrate_project_submission_config.py
|
|
"""
|
|
|
|
import sqlite3
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
|
|
def get_database_path():
|
|
"""Get the database path, trying multiple possible locations."""
|
|
possible_paths = [
|
|
"vfx_project_management.db", # Primary database
|
|
"database.db",
|
|
"../vfx_project_management.db"
|
|
]
|
|
|
|
for path in possible_paths:
|
|
if Path(path).exists():
|
|
return path
|
|
|
|
return "vfx_project_management.db"
|
|
|
|
|
|
def check_column_exists(cursor, table_name, column_name):
|
|
"""Check if a column exists in a table."""
|
|
cursor.execute(f"PRAGMA table_info({table_name})")
|
|
columns = [column[1] for column in cursor.fetchall()]
|
|
return column_name in columns
|
|
|
|
|
|
def migrate_database():
|
|
"""Add submission_config_by_task_type column to the projects table."""
|
|
db_path = get_database_path()
|
|
print(f"Using database: {db_path}")
|
|
|
|
conn = None
|
|
try:
|
|
conn = sqlite3.connect(db_path)
|
|
cursor = conn.cursor()
|
|
|
|
cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='projects'")
|
|
if not cursor.fetchone():
|
|
print("Projects table not found. Creating new database schema...")
|
|
conn.close()
|
|
return
|
|
|
|
if check_column_exists(cursor, "projects", "submission_config_by_task_type"):
|
|
print("Column submission_config_by_task_type already exists, skipping...")
|
|
else:
|
|
print("Adding column: submission_config_by_task_type")
|
|
cursor.execute("ALTER TABLE projects ADD COLUMN submission_config_by_task_type JSON")
|
|
|
|
conn.commit()
|
|
|
|
cursor.execute("SELECT COUNT(*) FROM projects")
|
|
project_count = cursor.fetchone()[0]
|
|
print(f"Migration completed successfully! {project_count} projects unaffected (column defaults to NULL).")
|
|
|
|
except sqlite3.Error as e:
|
|
print(f"Database error: {e}")
|
|
if conn:
|
|
conn.rollback()
|
|
sys.exit(1)
|
|
except Exception as e:
|
|
print(f"Unexpected error: {e}")
|
|
if conn:
|
|
conn.rollback()
|
|
sys.exit(1)
|
|
finally:
|
|
if conn:
|
|
conn.close()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
print("VFX Project Management - Submission Configuration Migration")
|
|
print("=" * 60)
|
|
|
|
migrate_database()
|
|
|
|
print("\nMigration completed successfully!")
|