From eb7b5d3abbc2f2420c82b8710f8b9b4a234f9479 Mon Sep 17 00:00:00 2001 From: Joshua Laymon Date: Sat, 6 Sep 2025 04:14:55 +0000 Subject: [PATCH] Update web/core/context_processors.py --- web/core/context_processors.py | 63 +++++++++++++--------------------- 1 file changed, 23 insertions(+), 40 deletions(-) diff --git a/web/core/context_processors.py b/web/core/context_processors.py index 77a7ab9..1b6ecfb 100644 --- a/web/core/context_processors.py +++ b/web/core/context_processors.py @@ -1,12 +1,9 @@ # core/context_processors.py + from pathlib import Path -import os - -from django.contrib.staticfiles import finders -from django.contrib.staticfiles.storage import staticfiles_storage - from .models_ann import Announcement, AnnouncementDismissal - +from django.contrib.staticfiles import finders +import os def app_version(request): version_file = Path(__file__).resolve().parent.parent / "version.txt" @@ -17,50 +14,36 @@ def app_version(request): version = "v0.0.0" return {"APP_VERSION": version} - def available_themes(request): """ - Return a list of theme names by scanning /static/themes/*.css. - Works in development (finders) and production (staticfiles_storage). - Never returns an empty list. + Return clean theme names by scanning /static/themes/*.css. + Fingerprinted files like 'classic.400a2f.css' are normalized to 'classic'. """ - names = set() + bases = [] + for finder in finders.get_finders(): + for path, storage in finder.list(['themes']): + if not (path.startswith('themes/') and path.endswith('.css')): + continue + filename = os.path.basename(path)[:-4] # drop .css + base = filename.split('.', 1)[0] # drop any fingerprint + if base: + bases.append(base) - # A) Dev/app static: scan all registered static finders - try: - for finder in finders.get_finders(): - for path, storage in finder.list(['themes']): - # e.g. "themes/midnight.css" - if path.startswith('themes/') and path.endswith('.css'): - names.add(os.path.basename(path)[:-4]) # strip ".css" - except Exception: - pass - - # B) Prod/collected: scan STATIC_ROOT via staticfiles_storage - try: - dirs, files = staticfiles_storage.listdir('themes') - for f in files: - if f.endswith('.css'): - names.add(f[:-4]) - except Exception: - pass - - # C) Safety net: default themes so the selector is never empty - if not names: - names.update({'midnight', 'dawn', 'forest', 'sandstone'}) - - return {'available_themes': sorted(names)} + # Prefer a nice order with Classic first; fall back to alpha for unknowns + order = ["classic", "dawn", "forest", "midnight", "mint", "sandstone", "original"] + # de-dupe while preserving order preference + uniq = [] + for name in bases: + if name not in uniq: + uniq.append(name) + uniq.sort(key=lambda n: (order.index(n) if n in order else len(order)+1, n)) + return {"available_themes": uniq} def pending_announcement(request): - """ - Expose the latest active, current announcement the user has not dismissed. - We'll only use it on the Search page via include. - """ user = getattr(request, "user", None) if not (user and user.is_authenticated): return {"pending_announcement": None} - current = [a for a in Announcement.objects.all() if a.is_current()] for a in current: if not AnnouncementDismissal.objects.filter(user=user, announcement=a).exists():