The earlier swap to BOX_CAMPAIGNS_FOLDER_ID=133295752718 was wrong — Video Master operates on the automation campaigns folder (156182880490), where subfolders are named by campaign TITLE rather than the numeric job ID used in Reporting's root. Reverted the default in config.py and all three .env example files. Folder naming on Box is inconsistent — '1_CFUL263C01C_Kids drop1' vs '1_CFUL263C01F-Kids drop 2' vs 'Summer Activation 2026' all coexist. search_subfolder now strips every non-alphanumeric character from both the search input and the folder names before substring match, so: "kids drop 1" → matches "1_CFUL263C01C_Kids drop1" "Spring 2026" → matches "4023 Spring 2026" "winterfilm" → matches "1_WA20263C01 Winter Film" Form label/placeholder updated to "Campaign Title" with a hint that spaces/underscores/hyphens/case are all ignored.
77 lines
2.9 KiB
Python
77 lines
2.9 KiB
Python
"""Application configuration."""
|
|
import os
|
|
from dotenv import load_dotenv
|
|
|
|
# Load environment variables
|
|
load_dotenv()
|
|
|
|
class Config:
|
|
"""Base configuration."""
|
|
|
|
# Flask
|
|
SECRET_KEY = os.environ.get('SECRET_KEY', 'dev-secret-key-change-in-production')
|
|
|
|
# Authentication (simple username:password_hash pairs, comma-separated)
|
|
AUTH_USERS = os.environ.get('AUTH_USERS', '')
|
|
|
|
# Box
|
|
BOX_CONFIG_PATH = os.environ.get('BOX_CONFIG_PATH', 'config/box_config.json')
|
|
BOX_REPORT_FOLDER_ID = os.environ.get('BOX_REPORT_FOLDER_ID', '133295752718')
|
|
# Different folder root from REPORT — Video Master operates on the
|
|
# automation campaigns folder where each subfolder is named by
|
|
# campaign title (not by job number like the Reporting tool's root).
|
|
BOX_CAMPAIGNS_FOLDER_ID = os.environ.get('BOX_CAMPAIGNS_FOLDER_ID', '156182880490')
|
|
|
|
# Server
|
|
HOST = os.environ.get('HOST', '0.0.0.0')
|
|
PORT = int(os.environ.get('PORT', 5000))
|
|
|
|
# Database
|
|
# Use absolute path for SQLite database
|
|
BASE_DIR = os.path.abspath(os.path.dirname(__file__))
|
|
SQLALCHEMY_DATABASE_URI = os.environ.get(
|
|
'DATABASE_URI',
|
|
f'sqlite:///{os.path.join(BASE_DIR, "database", "qc_platform.db")}'
|
|
)
|
|
SQLALCHEMY_TRACK_MODIFICATIONS = False
|
|
SQLALCHEMY_ECHO = os.environ.get('FLASK_ENV') == 'development'
|
|
|
|
# Session Configuration
|
|
SESSION_COOKIE_SECURE = os.environ.get('FLASK_ENV') == 'production'
|
|
SESSION_COOKIE_HTTPONLY = True
|
|
SESSION_COOKIE_SAMESITE = 'Lax'
|
|
SESSION_COOKIE_PATH = os.environ.get('SESSION_COOKIE_PATH', '/')
|
|
|
|
# File Upload Configuration
|
|
MAX_CONTENT_LENGTH = 500 * 1024 * 1024 # 500 MB max file size
|
|
UPLOAD_FOLDER = 'uploads'
|
|
STORAGE_FOLDER = 'storage'
|
|
|
|
# Module-specific paths
|
|
HM_QC_UPLOAD_PATH = 'uploads/hm_qc'
|
|
VIDEO_QC_UPLOAD_PATH = 'uploads/video_qc'
|
|
VIDEO_MASTER_UPLOAD_PATH = 'uploads/video_master'
|
|
|
|
HM_QC_STORAGE_PATH = 'storage/reports/hm_qc'
|
|
CONSOLIDATED_STORAGE_PATH = 'storage/reports/consolidated'
|
|
|
|
# Campaign presentation storage
|
|
CAMPAIGN_STORAGE_PATH = 'storage/campaigns'
|
|
|
|
# Pricing reference storage (per-row, selectable at configure time)
|
|
PRICING_REF_STORAGE_PATH = 'storage/pricing_references'
|
|
|
|
# Legacy global pricing (auto-imported into PricingReference on first run)
|
|
GLOBAL_PRICING_PDF_PATH = 'storage/reference/global_pricing.pdf'
|
|
GLOBAL_PRICING_JSON_PATH = 'storage/reference/global_pricing.json'
|
|
|
|
# LLM Configuration
|
|
OPENAI_API_KEY = os.environ.get('OPENAI_API_KEY')
|
|
ANTHROPIC_API_KEY = os.environ.get('ANTHROPIC_API_KEY')
|
|
AZURE_OPENAI_API_KEY = os.environ.get('AZURE_OPENAI_API_KEY')
|
|
AZURE_OPENAI_ENDPOINT = os.environ.get('AZURE_OPENAI_ENDPOINT')
|
|
GOOGLE_API_KEY = os.environ.get('GOOGLE_API_KEY')
|
|
|
|
# Application
|
|
MAX_REPORTS_PER_JOB = 100 # Limit reports fetched per job number
|
|
CACHE_TIMEOUT = 300 # 5 minutes cache for Box searches
|