feat: add page shell, preferences and translations
Base layout with top bar, role-based menu, profile menu and phone layout; theme, language and German form of address kept in cookies; German formal, German informal and English text; Fluent avatar bundled in the image by a Node build stage; placeholder pages for the Publisher and Admin groups. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N3t4WL7bd9bdHHNjEsxzqC
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
"""The left menu, declared once. An entry is shown only to users who may open its page."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Entry:
|
||||
label: object # lazy translated string
|
||||
url_name: str
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Group:
|
||||
title: object | None
|
||||
role: str | None # None: everyone; otherwise "publisher" or "admin"
|
||||
entries: tuple[Entry, ...]
|
||||
|
||||
|
||||
MENU = (
|
||||
Group(None, None, (Entry(_("Home"), "home"),)),
|
||||
Group(
|
||||
_("Publishing"),
|
||||
"publisher",
|
||||
(Entry(_("Manage announcements"), "publish-announcements"),),
|
||||
),
|
||||
Group(
|
||||
_("Administration"),
|
||||
"admin",
|
||||
(
|
||||
Entry(_("Appearance"), "admin-appearance"),
|
||||
Entry(_("Settings"), "admin-settings"),
|
||||
Entry(_("Audit log"), "admin-audit"),
|
||||
Entry(_("Status"), "admin-status"),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
def _allowed(group: Group, portal_user) -> bool:
|
||||
if group.role is None:
|
||||
return True
|
||||
return bool(getattr(portal_user, f"is_{group.role}", False))
|
||||
|
||||
|
||||
def for_user(portal_user, current_path: str) -> list[dict]:
|
||||
"""The groups this user sees, each entry with its address and whether it is current."""
|
||||
groups = []
|
||||
for group in MENU:
|
||||
if not _allowed(group, portal_user):
|
||||
continue
|
||||
entries = []
|
||||
for entry in group.entries:
|
||||
url = reverse(entry.url_name)
|
||||
entries.append({"label": entry.label, "url": url, "current": url == current_path})
|
||||
groups.append({"title": group.title, "entries": entries})
|
||||
return groups
|
||||
Reference in New Issue
Block a user