tuning ui and adding adaptive themeing to extension

This commit is contained in:
Bryan Van Deusen
2026-01-25 18:47:06 -05:00
parent dc6755a0c2
commit 997f31ae27
23 changed files with 978 additions and 114 deletions
+26 -5
View File
@@ -1,6 +1,6 @@
"""SQLAlchemy base model."""
from datetime import datetime
from datetime import datetime, timezone
from sqlalchemy import func
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
@@ -10,8 +10,29 @@ class Base(DeclarativeBase):
pass
class TimestampMixin:
"""Mixin for created_at and updated_at timestamps."""
def utcnow():
"""Return current UTC time as timezone-aware datetime."""
return datetime.now(timezone.utc)
created_at: Mapped[datetime] = mapped_column(default=func.now())
updated_at: Mapped[datetime] = mapped_column(default=func.now(), onupdate=func.now())
def format_datetime(dt):
"""Format datetime as ISO string with UTC marker for API responses.
If the datetime is naive (no timezone), assumes UTC and appends Z.
This ensures JavaScript Date() correctly interprets the timezone.
"""
if not dt:
return None
# If naive (no timezone), assume UTC and append Z
if dt.tzinfo is None:
return dt.isoformat() + "Z"
return dt.isoformat()
class TimestampMixin:
"""Mixin for created_at and updated_at timestamps.
Uses UTC timestamps for consistency. Frontend should convert to local time.
"""
created_at: Mapped[datetime] = mapped_column(default=utcnow)
updated_at: Mapped[datetime] = mapped_column(default=utcnow, onupdate=utcnow)
+4 -4
View File
@@ -6,7 +6,7 @@ from sqlalchemy import String, Integer, Text, ForeignKey, BigInteger
from sqlalchemy.dialects.postgresql import JSONB
from sqlalchemy.orm import Mapped, mapped_column, relationship
from app.models.base import Base, TimestampMixin
from app.models.base import Base, TimestampMixin, format_datetime
class DownloadStatus:
@@ -79,10 +79,10 @@ class Download(Base, TimestampMixin):
"error_message": self.error_message,
"file_count": self.file_count,
"total_size": self.total_size,
"started_at": self.started_at.isoformat() if self.started_at else None,
"completed_at": self.completed_at.isoformat() if self.completed_at else None,
"started_at": format_datetime(self.started_at),
"completed_at": format_datetime(self.completed_at),
"metadata": self.metadata_,
"created_at": self.created_at.isoformat() if self.created_at else None,
"created_at": format_datetime(self.created_at),
}
+5 -5
View File
@@ -6,7 +6,7 @@ from sqlalchemy import String, Boolean, Integer, Text, ForeignKey, UniqueConstra
from sqlalchemy.dialects.postgresql import JSONB
from sqlalchemy.orm import Mapped, mapped_column, relationship
from app.models.base import Base, TimestampMixin
from app.models.base import Base, TimestampMixin, format_datetime
class Source(Base, TimestampMixin):
@@ -55,12 +55,12 @@ class Source(Base, TimestampMixin):
"url": self.url,
"enabled": self.enabled,
"check_interval": self.check_interval,
"last_check": self.last_check.isoformat() if self.last_check else None,
"last_success": self.last_success.isoformat() if self.last_success else None,
"last_check": format_datetime(self.last_check),
"last_success": format_datetime(self.last_success),
"error_count": self.error_count,
"metadata": self.metadata_,
"created_at": self.created_at.isoformat() if self.created_at else None,
"updated_at": self.updated_at.isoformat() if self.updated_at else None,
"created_at": format_datetime(self.created_at),
"updated_at": format_datetime(self.updated_at),
}
if include_subscription and self.subscription:
result["subscription_name"] = self.subscription.name
+3 -3
View File
@@ -6,7 +6,7 @@ from sqlalchemy import String, Boolean, Integer, Text
from sqlalchemy.dialects.postgresql import JSONB
from sqlalchemy.orm import Mapped, mapped_column, relationship
from app.models.base import Base, TimestampMixin
from app.models.base import Base, TimestampMixin, format_datetime
if TYPE_CHECKING:
from app.models.source import Source
@@ -64,8 +64,8 @@ class Subscription(Base, TimestampMixin):
"metadata": self.metadata_,
"platform_count": self.platform_count,
"enabled_source_count": self.enabled_source_count,
"created_at": self.created_at.isoformat() if self.created_at else None,
"updated_at": self.updated_at.isoformat() if self.updated_at else None,
"created_at": format_datetime(self.created_at),
"updated_at": format_datetime(self.updated_at),
}
if include_sources and self.sources:
result["sources"] = [s.to_dict(include_subscription=False) for s in self.sources]