Skip to main content

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 Dashboard
Same view zoomed on the cards — note the per-card monospace data, hairline grid, and the top-right ▤ ◐ ↻ action buttons Dashboard detail
Notifications bell dropdown — per-user activity stream with read markers and the Mark all action Notifications bell
Recent activity card with long Django content-type pills wrapping cleanly inside the column Recent activity
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) Changelist

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-review and kiwitcms-requirements). No AdminSite subclass. No template inheritance fights with Grappelli.
  • No Kiwi changes. Drops in via the kiwitcms.plugins entry 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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

kiwi_tcms_admin_overlay-0.1.0.tar.gz (68.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

kiwi_tcms_admin_overlay-0.1.0-py3-none-any.whl (83.3 kB view details)

Uploaded Python 3

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

Hashes for kiwi_tcms_admin_overlay-0.1.0.tar.gz
Algorithm Hash digest
SHA256 72e7498b30ca238e38d7dfdfc3cf9c54c7f35726a1654db448b7236c453effa4
MD5 5a108615fe6988603d0c3653ff3d1739
BLAKE2b-256 083ae3d7c0a0a73a1004abe0885308d4a07fe871f38a3c7e678d192ee7a96c15

See more details on using hashes here.

File details

Details for the file kiwi_tcms_admin_overlay-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for kiwi_tcms_admin_overlay-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 1326e6da1217b00e679e9d3a11c42e7f6a0415f733c4e86c50382a05b20084d4
MD5 5f0cea2dac4ad677d09229b6381d7b14
BLAKE2b-256 999c19f35e43fc6132754609ff5011ed4ed020802f9f32335934d81ab77d917e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page