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
62 lines
1.7 KiB
Python
62 lines
1.7 KiB
Python
"""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
|