from django.conf import settings from django.db import models NTSC_24 = 24000 / 1001 class Project(models.Model): """One editing project: an uploaded OTIO source + the live mark-group scene (tl.scene) the frontend reads and writes. The scene is just a JSON dump for now — the whole {:tracks :groups} map the client keeps in app-db.""" owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="projects") collaborators = models.ManyToManyField(settings.AUTH_USER_MODEL, blank=True, related_name="shared_projects") name = models.CharField(max_length=200) otio = models.FileField(upload_to="otio/", blank=True, null=True) clip = models.FileField(upload_to="clips/", blank=True, null=True) fps = models.FloatField(default=NTSC_24) scene = models.JSONField(default=dict, blank=True) created = models.DateTimeField(auto_now_add=True) updated = models.DateTimeField(auto_now=True) class Meta: ordering = ["-updated"] def __str__(self): return f"{self.name} (#{self.pk})" class Revision(models.Model): """One scene save: who, when, a summary, and a snapshot of the authored (annotation) layer — the audit trail tying timeline changes to users.""" project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name="revisions") user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, null=True, related_name="+") created = models.DateTimeField(auto_now_add=True) summary = models.CharField(max_length=200, blank=True) annotations = models.JSONField(default=dict, blank=True) class Meta: ordering = ["-created"] def __str__(self): return f"{self.project_id} @ {self.created:%Y-%m-%d %H:%M} by {self.user_id}"