From b382eb857bb1d4e1d29ec5e1964368de9c0411ac Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 4 Sep 2026 11:33:23 +0100 Subject: [PATCH] v0.2.1: top-bar avatar, You/Admin settings groups, admin models MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Replace the gear/username button with a round initials avatar (per-user deterministic color via a new daybook_extras template filter); dropdown now shows the username and keeps Settings/About/theme/logout. Sets up an optional profile photo later. - Regroup the settings nav into "You" (Account, API Keys, Storage, Demo Data) and a superuser-only "Admin" (Users), About separate — the split now reflects who each setting affects, not a flat list. - Register ApiKey (key read-only) and TagColor in Django admin so /admin/ is complete as the operator break-glass tool, distinct from the themed Settings product surface. Co-Authored-By: Claude Opus 4.8 --- CHANGELOG.md | 16 +++++++- artifacts/admin.py | 17 +++++++- artifacts/templatetags/__init__.py | 0 artifacts/templatetags/daybook_extras.py | 30 ++++++++++++++ daybook_project/__init__.py | 2 +- static/daybook.css | 51 ++++++++++++++++++++++++ templates/artifacts/_topbar.html | 7 ++-- templates/artifacts/settings_base.html | 23 ++++++++--- 8 files changed, 134 insertions(+), 12 deletions(-) create mode 100644 artifacts/templatetags/__init__.py create mode 100644 artifacts/templatetags/daybook_extras.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 651b123..801f2a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,19 @@ the git tags (`vX.Y.Z`) and `daybook_project.__version__`. _Nothing yet._ +## [0.2.1] — 2026-09-04 + +### Added +- Top-bar **avatar**: a round initials badge (deterministic per-user color) + replaces the gear/username button; lays the groundwork for profile photos. +- Django admin now registers `ApiKey` and `TagColor`, so `/admin/` is complete + as an operator break-glass tool (key value shown read-only). + +### Changed +- Settings nav regrouped into **You** (Account, API Keys, Storage, Demo Data) + and a superuser-only **Admin** (Users) section, with About on its own — the + personal/admin split now mirrors who each setting affects. + ## [0.2.0] — 2026-09-04 ### Added @@ -85,7 +98,8 @@ First tagged release. - Dockerised (Gunicorn + whitenoise), SQLite, `git`-based deploy with a runbook (`deploy/cloud_agent_deploy.md`) and health check. -[Unreleased]: https://git.cygnus.systems/peter/daybook/compare/v0.2.0...HEAD +[Unreleased]: https://git.cygnus.systems/peter/daybook/compare/v0.2.1...HEAD +[0.2.1]: https://git.cygnus.systems/peter/daybook/compare/v0.2.0...v0.2.1 [0.2.0]: https://git.cygnus.systems/peter/daybook/compare/v0.1.1...v0.2.0 [0.1.1]: https://git.cygnus.systems/peter/daybook/compare/v0.1.0...v0.1.1 [0.1.0]: https://git.cygnus.systems/peter/daybook/releases/tag/v0.1.0 diff --git a/artifacts/admin.py b/artifacts/admin.py index 0a0d7f2..347749d 100644 --- a/artifacts/admin.py +++ b/artifacts/admin.py @@ -1,6 +1,6 @@ from django.contrib import admin -from .models import Artifact, Asset, UserProfile +from .models import ApiKey, Artifact, Asset, TagColor, UserProfile @admin.register(Artifact) @@ -21,3 +21,18 @@ class AssetAdmin(admin.ModelAdmin): list_display = ("id", "owner", "artifact", "content_type", "size_bytes", "created_at") list_filter = ("owner", "content_type") search_fields = ("id",) + + +@admin.register(ApiKey) +class ApiKeyAdmin(admin.ModelAdmin): + list_display = ("name", "user", "key", "created_at", "last_used_at") + list_filter = ("user",) + search_fields = ("name", "key", "user__username") + # The key value and timestamps are system-managed; show but don't hand-edit. + readonly_fields = ("key", "created_at", "last_used_at") + + +@admin.register(TagColor) +class TagColorAdmin(admin.ModelAdmin): + list_display = ("name", "color") + search_fields = ("name",) diff --git a/artifacts/templatetags/__init__.py b/artifacts/templatetags/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/artifacts/templatetags/daybook_extras.py b/artifacts/templatetags/daybook_extras.py new file mode 100644 index 0000000..bb27bde --- /dev/null +++ b/artifacts/templatetags/daybook_extras.py @@ -0,0 +1,30 @@ +from django import template + +register = template.Library() + +# A small fixed palette. A user's avatar color is picked deterministically from +# their username, so it stays stable across sessions and page loads. +_AVATAR_COLORS = [ + "#4a6ea8", + "#3f8f7b", + "#a3712a", + "#8a4f9e", + "#a3312a", + "#2f7d95", + "#6b7280", + "#7b6a3f", +] + + +@register.filter +def avatar_color(value): + text = str(value or "") + if not text: + return _AVATAR_COLORS[0] + return _AVATAR_COLORS[sum(ord(c) for c in text) % len(_AVATAR_COLORS)] + + +@register.filter +def avatar_initial(value): + text = str(value or "").strip() + return text[0].upper() if text else "?" diff --git a/daybook_project/__init__.py b/daybook_project/__init__.py index b5b7a6a..f7e7251 100644 --- a/daybook_project/__init__.py +++ b/daybook_project/__init__.py @@ -1,4 +1,4 @@ # Single source of truth for the app version. Bump this, commit, then tag the # commit `vX.Y.Z` and deploy. Surfaced on Settings -> About and in # GET /api/capabilities ("version"). -__version__ = "0.2.0" +__version__ = "0.2.1" diff --git a/static/daybook.css b/static/daybook.css index 203eacf..805b76b 100644 --- a/static/daybook.css +++ b/static/daybook.css @@ -128,6 +128,42 @@ body { border-color: var(--control-border); } +.avatar-button { + background: transparent; + border: 0; + border-radius: 50%; + cursor: pointer; + line-height: 0; + padding: 2px; +} + +.avatar-button:hover .avatar, +.avatar-button:focus-visible .avatar { + box-shadow: 0 0 0 2px var(--content-bg), 0 0 0 4px var(--control-border); +} + +.avatar { + align-items: center; + border-radius: 50%; + color: #fff; + display: inline-flex; + font-size: 0.9rem; + font-weight: 600; + height: 2rem; + justify-content: center; + line-height: 1; + width: 2rem; +} + +.user-menu-name { + border-bottom: 1px solid var(--control-border); + color: var(--muted); + font-size: 0.8rem; + font-weight: 600; + margin-bottom: 0.25rem; + padding: 0.5rem 0.8rem; +} + .user-menu-dropdown { background: var(--surface); border: 1px solid var(--control-border); @@ -968,6 +1004,21 @@ kbd { padding-bottom: 0.7rem !important; } +.settings-nav-group { + display: flex; + flex-direction: column; + margin-bottom: 0.9rem; +} + +.settings-nav-heading { + color: var(--muted); + font-size: 0.7rem; + font-weight: 700; + letter-spacing: 0.06em; + padding: 0.3rem 0.7rem; + text-transform: uppercase; +} + .settings-panel { max-width: 42rem; padding: 1.6rem 2rem; diff --git a/templates/artifacts/_topbar.html b/templates/artifacts/_topbar.html index 5dbcde5..c63dfe7 100644 --- a/templates/artifacts/_topbar.html +++ b/templates/artifacts/_topbar.html @@ -1,3 +1,4 @@ +{% load daybook_extras %}

AgentFeed

@@ -6,12 +7,12 @@ {% if topbar_toolbar %}{% include topbar_toolbar %}{% endif %}
-