From 950ab6c95b9e9a882647c87162f34453b7f4d825 Mon Sep 17 00:00:00 2001 From: Martin Castro Laminrs Date: Thu, 28 May 2026 16:28:12 +0200 Subject: [PATCH 1/2] =?UTF-8?q?chore(release):=20v1.0.1=20=E2=80=94=20sing?= =?UTF-8?q?le=20INSTALLED=5FAPPS=20line,=20importlib-version?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Owner directive 2026-05-28: the plug-and-play should be a SINGLE `INSTALLED_APPS` line — `django_admin_react` — and have it transparently bring the JSON API along. `django_admin_react.urls` already includes `django_admin_rest_api.api.urls` at `api/v1/`, so the URL include is sufficient; the API package's AppConfig adds nothing the include needs (the API ships zero models + zero signals). Verified against a fresh venv: `GET /admin-react/api/v1/registry/ → 403` (the gate runs as expected) with only `django_admin_react` registered. ## Changes - `README.md`: drop the `django_admin_rest_api` line from the install snippet; lead with "one INSTALLED_APPS line + one URL include." - `tests/test_project/settings.py`: align the test fixture with the README's recommended pattern (only `django_admin_react`). Full backend suite still **45 passed**. - `django_admin_react/__init__.py`: stop hardcoding `__version__ = "0.0.0"` (a placeholder from before any release); read the version from the installed distribution metadata via `importlib.metadata`, so the constant tracks `pyproject.toml` automatically every release. Replace the stale "skeleton" docstring with the real super-layer blurb + cross-links to the sibling packages. - `pyproject.toml`: bump `1.0.0` → `1.0.1`. ## Release path After this merges, tag `v1.0.1` + cut the GitHub Release. If OIDC is still unconfigured (issue #564), the manual fallback is the same `set -a; . ./.env; set +a; poetry build && poetry publish` flow that shipped `1.0.0`. Co-Authored-By: Claude Opus 4.7 (1M context) --- README.md | 7 ++++--- django_admin_react/__init__.py | 25 ++++++++++++++++++++----- pyproject.toml | 2 +- tests/test_project/settings.py | 14 +++++++++----- 4 files changed, 34 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 51bd9fe2..9b8855ec 100644 --- a/README.md +++ b/README.md @@ -9,17 +9,18 @@ your `ModelAdmin` classes drive everything. No React code on your side. INSTALLED_APPS = [ # ... "django.contrib.admin", - "django_admin_rest_api", # the JSON REST API (sibling package — pulled in as a dependency) - "django_admin_react", # this package — the React SPA on top of it + "django_admin_react", # the React SPA — includes the JSON API for you ] # urls.py urlpatterns = [ path("admin/", admin.site.urls), - path("admin-react/", include("django_admin_react.urls")), # SPA + its API include + path("admin-react/", include("django_admin_react.urls")), # SPA + API in one include ] ``` +**One `INSTALLED_APPS` line + one URL include is the entire integration.** `pip install django-admin-react` transitively pulls in the [JSON API](https://pypi.org/project/django-admin-rest-api/) and the [MCP adapter](https://pypi.org/project/django-admin-mcp-api/); `django_admin_react.urls` includes the API endpoints at `/api/v1/…`, so the SPA finds its wire surface with zero configuration. (Mount the API a second time at your own prefix only if a non-SPA client also needs it.) + > **Beta — v1.0.0.** Available on PyPI; the SPA + the API > ([`django-admin-rest-api`](https://pypi.org/project/django-admin-rest-api/)) > + the MCP adapter diff --git a/django_admin_react/__init__.py b/django_admin_react/__init__.py index dbc36c87..ef855a4b 100644 --- a/django_admin_react/__init__.py +++ b/django_admin_react/__init__.py @@ -1,10 +1,25 @@ -"""django-admin-react — a React single-page admin for Django. +"""django-admin-react — the React SPA super-layer for the Django admin. -The actual implementation lands across PRs #2-#7. This package is -currently a skeleton that defines the layout and the Django AppConfig -entry point only. See `ARCHITECTURE.md` for the design contract. +A drop-in single-page admin: same `pip install`, same `INSTALLED_APPS`, +same `urls.py include()` — and your `ModelAdmin` classes drive everything. +The JSON wire surface lives in the sibling +[`django-admin-rest-api`](https://pypi.org/project/django-admin-rest-api/) +package (pulled in as a dependency); the MCP exposure of the same surface +lives in +[`django-admin-mcp-api`](https://pypi.org/project/django-admin-mcp-api/). + +See `README.md` for install + the consumer wiring, and `ARCHITECTURE.md` +for what lives in this repo vs. the API / MCP siblings. """ -__version__ = "0.0.0" +from importlib.metadata import PackageNotFoundError +from importlib.metadata import version as _pkg_version + +try: + # Read the version directly from the installed distribution metadata + # so this constant never drifts from `pyproject.toml` after a release. + __version__ = _pkg_version("django-admin-react") +except PackageNotFoundError: # pragma: no cover — editable / source install + __version__ = "0.0.0" default_app_config = "django_admin_react.apps.DjangoAdminReactConfig" diff --git a/pyproject.toml b/pyproject.toml index d8bd1439..b93dd9f3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "django-admin-react" -version = "1.0.0" +version = "1.0.1" description = "A drop-in React single-page admin for Django, driven entirely by ModelAdmin." authors = ["django-admin-react contributors"] license = "MIT" diff --git a/tests/test_project/settings.py b/tests/test_project/settings.py index f9c397c3..02249358 100644 --- a/tests/test_project/settings.py +++ b/tests/test_project/settings.py @@ -23,11 +23,15 @@ "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", - # The JSON REST API surface (sibling package — implements every - # `/api/v1/...` endpoint). `django_admin_react.urls` includes its - # URLs at the same `api/v1/` prefix the SPA already expects. - "django_admin_rest_api", - # This package — the React SPA super-layer. + # **Minimal plug-and-play (#564 owner directive 2026-05-28):** only + # `django_admin_react` is registered. `pip install django-admin-react` + # transitively pulls in `django-admin-rest-api`; the URL include in + # `django_admin_react.urls` mounts the API at `/api/v1/`, so + # the API package does not need its own `INSTALLED_APPS` entry — the + # endpoints resolve through `include("django_admin_rest_api.api.urls")` + # without the AppConfig being registered (the API ships zero models + + # zero signals, so the registration adds nothing the URL include needs). + # Test-suite parity with the README's recommended snippet. "django_admin_react", # Test-only app with a FileField model retained for back-compat # (the package's own suite owns the upload tests now). From e30b5eb08f23561ddfc9a0ab02c5eadd4ea1fdb4 Mon Sep 17 00:00:00 2001 From: Martin Castro Laminrs Date: Thu, 28 May 2026 17:12:19 +0200 Subject: [PATCH 2/2] fix(spa): bump sidebar divider + filter-field contrast (#556) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The first-section top divider and the model-filter input both used `bg-gray-800` / `border-gray-800` against a `bg-gray-900` sidebar — one step of contrast, which the pilot reported as "no visible divider" and "search box hard to spot." - Divider strength: `border-t border-gray-800` + `divide-y divide-gray-800` → `border-gray-700` / `divide-gray-700`. Two steps off the sidebar surface — the line is now actually visible. - Filter input: `bg-gray-800 border-gray-700` → `bg-gray-700 border-gray-600`, placeholder `text-gray-500` → `text-gray-400`. Matches the contrast level the rest of the app's inputs have. Same fix in dark mode — the sidebar is always dark; there's no light-mode variant. Bundles into the v1.0.1 wheel. Closes #556. Co-Authored-By: Claude Opus 4.7 (1M context) --- frontend/packages/sidebar/src/Sidebar.tsx | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/frontend/packages/sidebar/src/Sidebar.tsx b/frontend/packages/sidebar/src/Sidebar.tsx index a9434f3c..9012f696 100644 --- a/frontend/packages/sidebar/src/Sidebar.tsx +++ b/frontend/packages/sidebar/src/Sidebar.tsx @@ -252,7 +252,11 @@ export function Sidebar() { }} placeholder="Filter models…" aria-label="Filter models" - className="w-full rounded border border-gray-700 bg-gray-800 px-2 py-1 text-sm text-gray-100 placeholder-gray-500 focus:outline-none focus-visible:ring-1 focus-visible:ring-gray-500" + // Bumped one step lighter than the sidebar surface (bg-gray-900) + // so the input reads as a distinct field, not as part of the + // sidebar (#556). `bg-gray-700` + `border-gray-600` gives the + // same two-step contrast the rest of the app's inputs have. + className="w-full rounded border border-gray-600 bg-gray-700 px-2 py-1 text-sm text-gray-100 placeholder-gray-400 focus:outline-none focus-visible:ring-1 focus-visible:ring-gray-500" /> )} @@ -262,8 +266,10 @@ export function Sidebar() { grouped-nav style. */} {/* `border-t` draws the line above the FIRST section (the filter field sits above it); `divide-y` handles the lines between the - rest. */} -