Metadata-Version: 2.4
Name: kiwi-tcms-admin-overlay
Version: 0.1.0
Summary: Sophisticated admin overlay for Kiwi TCMS — dashboard, command palette, smart sidebar, contextual badges, notifications. Pure additive plugin; no Kiwi changes required.
Author-email: Achmad Fienan Rahardianto <veenone@gmail.com>
License-Expression: GPL-2.0-or-later
Project-URL: Homepage, https://github.com/veenone/kiwi-tcms-admin-overlay
Project-URL: Repository, https://github.com/veenone/kiwi-tcms-admin-overlay
Project-URL: Issues, https://github.com/veenone/kiwi-tcms-admin-overlay/issues
Keywords: tcms,kiwi,plugin,admin,ui,dashboard,django-admin,overlay
Classifier: Framework :: Django
Classifier: Framework :: Django :: 4.2
Classifier: Framework :: Django :: 5.0
Classifier: Framework :: Django :: 5.1
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: System Administrators
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Quality Assurance
Classifier: Topic :: Software Development :: Testing
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: Django>=4.2
Provides-Extra: dev
Requires-Dist: build>=1.0; extra == "dev"
Requires-Dist: twine>=4.0; extra == "dev"
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-django>=4.5; extra == "dev"
Dynamic: license-file

# 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](docs/screenshots/01-dashboard.png) |
| Same view zoomed on the cards — note the per-card monospace data, hairline grid, and the top-right `▤ ◐ ↻` action buttons | ![Dashboard detail](docs/screenshots/02-dashboard-detail.png) |
| **Notifications bell** dropdown — per-user activity stream with read markers and the `Mark all` action | ![Notifications bell](docs/screenshots/03-notifications-bell.png) |
| Recent activity card with long Django content-type pills wrapping cleanly inside the column | ![Recent activity](docs/screenshots/04-recent-activity.png) |
| **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](docs/screenshots/05-changelist.png) |

The full design preview is at [`docs/design-preview.html`](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)

```bash
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:

```python
# 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()`:

```python
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

```bash
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`](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.
