Sophisticated admin overlay for Kiwi TCMS — dashboard, command palette, smart sidebar, contextual badges, notifications. Pure additive plugin; no Kiwi changes required.
Project description
kiwi-tcms-admin-overlay
A Kiwi TCMS plugin that overlays a sophisticated admin shell on top of Django's stock admin — dashboard, command palette, smart sidebar grouping, contextual badges, and live notifications — without modifying Kiwi TCMS or any other plugin.
Screenshots
The overlay layered on a real Kiwi TCMS install:
| Dashboard with categorised sidebar, hero, three cards (Quick stats / System health / Recent activity), and the plugin tile grid below | |
Same view zoomed on the cards — note the per-card monospace data, hairline grid, and the top-right ▤ ◐ ↻ action buttons |
|
Notifications bell dropdown — per-user activity stream with read markers and the Mark all action |
|
| Recent activity card with long Django content-type pills wrapping cleanly inside the column | |
Stock Django changelist restyled — mono uppercase headers, hairline rules, hover paper-sunken; the trailing column shows the per-row badges (e.g. 45 pass · 9 fail on TestRun) |
The full design preview is at docs/design-preview.html — open it in any browser to see every component at full fidelity, including the light/dark/system theme toggle, without spinning up Django.
Why
Kiwi's /admin/ is the stock Django admin (lightly skinned by Grappelli). Once several plugins are installed, the index becomes a flat alphabetic wall of model classes. There's no global search, no dashboard, no per-domain grouping, no contextual signal. This plugin enriches that experience without forking anything.
How it stays out of the way
- Pure additive. Composes the existing Django admin via response-rewriting middleware (the same pattern used by
kiwitcms-reviewandkiwitcms-requirements). NoAdminSitesubclass. No template inheritance fights with Grappelli. - No Kiwi changes. Drops in via the
kiwitcms.pluginsentry point. - Easily disabled. Set
KIWI_TCMS_ADMIN_OVERLAY = {"enabled": False}and the overlay deactivates without uninstall. - No rebranding. "Kiwi TCMS" wordmark is preserved everywhere, per upstream license.
What it adds
| Surface | Where | What |
|---|---|---|
| Console rail | top of every admin page | Brand mark + status line + theme/density/refresh actions |
| Dashboard | /admin/ |
Quick stats, system health, recent activity, plugin tiles |
| Sidebar | /admin/ |
Categorised model navigation grouped by domain |
| Command palette | anywhere via Cmd/Ctrl+K | Substring search across admin models, add-forms, recent objects |
| Row badges | every changelist | Per-row context like 45 pass · 9 fail on TestRun, severity pill on Bug |
| Notifications bell | topbar | Per-user activity stream with persistent read markers |
| Accessibility | everywhere | WCAG 2.1 AA contrast in light/dark; prefers-reduced-motion respected; full keyboard nav |
Compatibility
| Versions tested | |
|---|---|
| Django | 4.2 LTS, 5.0, 5.1, 5.2 |
| Python | 3.9, 3.10, 3.11, 3.12 |
| Kiwi TCMS | any release that loads plugins via kiwitcms.plugins entry point |
Install (development)
pip install -e /path/to/kiwi-tcms-admin-overlay
./manage.py migrate kiwi_tcms_admin_overlay
./manage.py runserver
Visit /admin/ — the new shell renders. Stock admin pages still work.
Configure
Every option is optional. Defaults shown:
# settings.py (or local_settings.py)
KIWI_TCMS_ADMIN_OVERLAY = {
"enabled": True,
"categories": None, # None → use defaults; list → replace
"category_overrides": {}, # surgical {"app_label": "category_key"}
"dashboard_cache_seconds": 30,
"notifications_poll_seconds": 60,
"show_uncategorised_warning": True,
"theme_default": "system", # light | dark | system
}
Extending — for plugin authors
Three registries are available; call them from your own AppConfig.ready():
from kiwi_tcms_admin_overlay import (
AdminCategory, register_category,
Badge, register_badge,
register_notification_source,
)
class MyPluginConfig(AppConfig):
def ready(self):
# Sidebar grouping
register_category(AdminCategory(
"my_domain", "My Domain", "fa-flask", 25,
("my_plugin_app",),
))
# Per-row changelist badges
def badge_provider(model, queryset):
return {row.pk: [Badge("active", "pass")] for row in queryset.filter(active=True)}
register_badge("my_plugin_app", "mything", badge_provider)
# Notification source for the bell
def notifs(request, limit):
for item in MyNotification.objects.filter(user=request.user)[:limit]:
yield {
"source": "my_plugin",
"key": str(item.pk),
"label": item.title,
"hint": "my_plugin.mything",
"verb": "needs review",
"actor": item.from_user.username,
"time": item.created_at.isoformat(),
"href": item.get_absolute_url(),
}
register_notification_source("my_plugin", notifs)
All registrations are app-startup-only; runtime mutation is rejected so per-user caches stay consistent.
Architecture
┌─────────────────────────────────────────────────────┐
│ Browser (admin page) │
│ ┌────────────────────────────────────────────────┐ │
│ │ overlay.css + shell.js + palette.js + │ │
│ │ badges.js + notifications.js │ │
│ └────────────────────────────────────────────────┘ │
│ ↕ │
│ /admin_overlay/api/{dashboard,health,sidebar,…}/ │
└─────────────────────────────────────────────────────┘
↕
┌─────────────────────────────────────────────────────┐
│ Django (your existing Kiwi install) │
│ • AdminOverlayMiddleware injects bundle into HTML │
│ • ModelAdmin permissions gate every endpoint │
│ • OverlayNotificationRead persists read markers │
└─────────────────────────────────────────────────────┘
Testing
make test # full pytest suite (107 tests at 0.1.0)
make test-a11y # contrast + accessibility-only (fast canary)
make lint # flake8 + pylint
The accessibility CI surface includes a contrast verifier that asserts every documented design-token pair meets WCAG AA in both light and dark mode. See docs/accessibility.md for the manual axe-core audit procedure.
Design preview
docs/design-preview.html is a single self-contained file demonstrating every UI component at full fidelity, with light/dark/system theme cycling. Open it in any browser without Django running.
Status
v0.1.0 — feature-complete, internal use only. PyPI publish on hold pending broader review.
License
GPL-2.0-or-later, matching Kiwi TCMS upstream.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file kiwi_tcms_admin_overlay-0.1.0.tar.gz.
File metadata
- Download URL: kiwi_tcms_admin_overlay-0.1.0.tar.gz
- Upload date:
- Size: 68.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
72e7498b30ca238e38d7dfdfc3cf9c54c7f35726a1654db448b7236c453effa4
|
|
| MD5 |
5a108615fe6988603d0c3653ff3d1739
|
|
| BLAKE2b-256 |
083ae3d7c0a0a73a1004abe0885308d4a07fe871f38a3c7e678d192ee7a96c15
|
File details
Details for the file kiwi_tcms_admin_overlay-0.1.0-py3-none-any.whl.
File metadata
- Download URL: kiwi_tcms_admin_overlay-0.1.0-py3-none-any.whl
- Upload date:
- Size: 83.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1326e6da1217b00e679e9d3a11c42e7f6a0415f733c4e86c50382a05b20084d4
|
|
| MD5 |
5f0cea2dac4ad677d09229b6381d7b14
|
|
| BLAKE2b-256 |
999c19f35e43fc6132754609ff5011ed4ed020802f9f32335934d81ab77d917e
|