b65e956ad2
Per-artist "+N" accent pill on the artists directory and a "N new since last visit" banner inside ArtistView. Counts new IMAGES (not posts) so multi-image posts increment correctly. - alembic 0034: artist_visit (artist_id PK, last_viewed_at NOT NULL). Seeds every existing artist with last_viewed_at=NOW() so the badge starts at 0 across the board — no noisy "5000 unseen images" on first deploy. - ArtistService.find_or_create autoseeds a visit row alongside new artists, so freshly imported content doesn't read as unseen. - ArtistService.overview reads pre-visit last_viewed_at, counts images created since, then atomically UPSERTs last_viewed_at=NOW() via postgres ON CONFLICT DO UPDATE (no SELECT-then-INSERT race per reference_scalar_one_or_none_duplicates). Returns the pre-update count as `unseen_count_at_visit` so the banner has data. - ArtistDirectoryService.list_artists adds an `unseen_count` aggregate to each card via LEFT JOIN artist_visit + conditional COUNT. NULL last_viewed_at (artist created before this code shipped) defensively counts as "never visited" → all images unseen. - Frontend: ArtistCard renders an accent pill in the preview-strip corner when unseen_count > 0 (capped at 99+); ArtistView shows a closable v-alert banner on initial load when unseen_count_at_visit > 0, re-arms on slug change. Single-row-per-artist (no user_id) — rule #47 multi-user ACL is aspirational; widens to (user_id, artist_id) PK when User lands, per rule #22. Scribe plan #597.
56 lines
1.5 KiB
Python
56 lines
1.5 KiB
Python
"""All ORM models. Import this module to make every model visible to Alembic."""
|
|
|
|
from .app_setting import AppSetting
|
|
from .artist import Artist
|
|
from .artist_visit import ArtistVisit
|
|
from .backup_run import BackupRun
|
|
from .base import Base
|
|
from .credential import Credential
|
|
from .download_event import DownloadEvent
|
|
from .image_provenance import ImageProvenance
|
|
from .image_record import ImageRecord
|
|
from .import_batch import ImportBatch
|
|
from .import_settings import ImportSettings
|
|
from .import_task import ImportTask
|
|
from .library_audit_run import LibraryAuditRun
|
|
from .ml_settings import MLSettings
|
|
from .post import Post
|
|
from .post_attachment import PostAttachment
|
|
from .series_page import SeriesPage
|
|
from .source import Source
|
|
from .tag import Tag, TagKind, image_tag
|
|
from .tag_alias import TagAlias
|
|
from .tag_allowlist import TagAllowlist
|
|
from .tag_reference_embedding import TagReferenceEmbedding
|
|
from .tag_suggestion_rejection import TagSuggestionRejection
|
|
from .task_run import TaskRun
|
|
|
|
__all__ = [
|
|
"Base",
|
|
"AppSetting",
|
|
"Artist",
|
|
"ArtistVisit",
|
|
"BackupRun",
|
|
"Source",
|
|
"Credential",
|
|
"Post",
|
|
"PostAttachment",
|
|
"SeriesPage",
|
|
"ImageRecord",
|
|
"ImageProvenance",
|
|
"Tag",
|
|
"TagKind",
|
|
"image_tag",
|
|
"DownloadEvent",
|
|
"ImportBatch",
|
|
"ImportTask",
|
|
"ImportSettings",
|
|
"LibraryAuditRun",
|
|
"MLSettings",
|
|
"TagAlias",
|
|
"TagAllowlist",
|
|
"TagReferenceEmbedding",
|
|
"TagSuggestionRejection",
|
|
"TaskRun",
|
|
]
|