Add real replacement pages for Pages, Media Library, and Users (v2.6.0)

Completes the "skinned vs. replaced" conversion started with Posts —
every native list-table screen the user asked about now has a genuine
custom Vue page behind it instead of dark-themed CSS over the native
markup. All three follow the same pattern as Posts: own REST controller
in admin/src/Rest/, own Vue page matching the Comments layout, native
screen redirected away (direct visits too, not just the sidebar link),
gated by its own Settings toggle defaulting to on.

- Pages (PagesData.php + Pages.vue): same as Posts, parent page shown
  instead of categories. edit.php?post_type=page redirects; other post
  types untouched.
- Media Library (MediaData.php + Media.vue): thumbnail grid with type
  filters (Images/Audio/Video/Documents/Unattached). Replaces the
  browse/library experience only — media-new.php (the actual upload
  screen) is untouched, same reasoning as leaving the block editor
  alone for Posts/Pages.
- Users (UsersData.php + Users.vue): filterable by role. Deleting a
  user always reassigns their content to whoever performs the deletion
  rather than exposing WP core's reassign-or-delete-everything choice
  as a one-click action — deliberately simplified to avoid a surprising,
  highly destructive default. user-new.php untouched.

Verified live: Media's grid renders real thumbnails/dimensions/file
sizes with working filters and search; Users shows real accounts with
role filters and correctly hides delete for the current user; both
redirect correctly from their native URLs.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
nixpanel
2026-07-05 06:40:22 -05:00
co-authored by Claude Sonnet 5
parent 56b6674527
commit 204c4365e2
18 changed files with 2542 additions and 44 deletions
+69 -41
View File
@@ -1,6 +1,6 @@
# Aurora Admin v2 — Project Status
_Last updated: 2026-07-05 (latest session — real Posts replacement page, first of the "skinned vs. replaced" pages to actually get replaced)_
_Last updated: 2026-07-05 (latest session — Pages/Media/Users replacement pages, completing the "skinned vs. replaced" conversion started with Posts)_
## What this project is
@@ -149,51 +149,79 @@ get back up to speed instead of relying on prior chat history.
## Skinned vs. replaced native pages (important distinction, ask before assuming)
Not every native WP admin page gets the same treatment, and the user has
explicitly said they don't want the "skinned" approach used more broadly
without a real replacement behind it — check this list before describing
a page as "already handled":
The user explicitly said they didn't want the "skinned" approach used
without a real replacement behind it. As of this session, **every native
list-table screen has been converted** — there's no more "just skinned"
category left among the pages that had one:
- **Actually replaced** — the native page never renders; a real custom Vue
page (own REST controller, own list/detail UI) takes over entirely:
Comments, Installed Plugins, Menu Creator, Admin Notices, Role Editor,
Activity Log, Database Explorer, and now **Posts** (added this session
— see below).
- **Just skinned** — the real native WordPress page still renders; only
`admin/assets/native-dark.css` restyles it dark. Same underlying
markup, same native limitations, no new functionality: Pages, Media,
Users, and every other native screen not listed above.
Activity Log, Database Explorer, **Posts, Pages, Media Library, and
Users** (the last four all added this session, in that order — Posts
first as its own commit/version, then Pages/Media/Users together).
- **Deliberately still native** (not a "skinning" gap — these are specific
screens/actions, not list-tables, and rebuilding them wasn't in scope):
the block editor (`post.php`/`post-new.php` — dark-themed chrome only,
per "Window chrome" above), `media-new.php` (upload/drag-drop),
`user-new.php` (account creation), individual edit screens reached from
a list row (`user-edit.php`, comment/media edit), Settings/Profile
pages, the Site Editor. If a new "why isn't X replaced" question comes
up, check whether it's actually one of these deliberate exceptions
before treating it as a gap.
**Posts** (`admin/src/Rest/PostsData.php` + `app/src/pages/posts/Posts.vue`,
entry `posts.js`) was the first of these converted from skinned to
replaced, built directly off the Comments pattern:
- REST: GET `/posts` (status/search/pagination, matching native filters:
all/publish/draft/pending/trash), POST `/posts/trash`, POST
`/posts/restore`, DELETE `/posts/{id}` (permanent). Capability checks
mirror native (`edit_posts` to list, `edit_post`/`delete_post` per-item).
- `SubApps.php`: registered as `aurora-admin-posts`, parented under
`edit.php` (same pattern as Plugins under `plugins.php`) so it shares
the native "Posts" top-level menu's `hook_suffix` slot.
- `SubApps::redirect_native_pages()`: visiting `edit.php` directly (typed
URL, bookmark — not just the sidebar link) redirects to the Aurora page,
gated on **only** the default post type (`post_type=post` or absent) —
`edit.php?post_type=page` (Pages) and any other custom post type's list
screen is explicitly left alone, since only Posts has a replacement.
- `MenuSerializer.php`: the sidebar's own "Posts"/"All Posts" links
(both share the literal `edit.php` slug) get rewritten the same way
Plugins'/Comments' links already were.
- Gated by Settings > Posts' "Modern posts table" toggle — this is the
same toggle that got **removed** two commits ago for describing a
feature that didn't exist; it's back now that it does, defaulting to
on. `modern_plugins`/`modern_comments` also got a `default: true` UI
fix at the same time (they already defaulted true server-side, but the
Settings UI toggle showed off until explicitly saved — cosmetic
mismatch, now consistent).
- **Not done**: Pages, Media, Users remain skinned-only. Each would be a
comparable-sized build to Posts/Comments (own REST controller, own
list/detail UI) — ask the user before starting one, per the pattern
established this session (they picked "Posts first, then expand" over
doing all four at once).
All four of this session's pages (`PostsData.php`+`Posts.vue`,
`PagesData.php`+`Pages.vue`, `MediaData.php`+`Media.vue`,
`UsersData.php`+`Users.vue`) follow one shared pattern, established with
Posts and repeated for the other three:
- A REST controller in `admin/src/Rest/` with list (status/type/role +
search + pagination, matching native filter tabs) and action endpoints
(trash/restore/delete, or just delete for Media/Users, which don't have
a trash state in the same way). Capability checks mirror WP core's own
for that screen (`edit_posts`/`edit_pages`/`upload_files`/`list_users`
to view; per-item `edit_post`/`delete_post`/`delete_page`/`delete_user`
for actions).
- A Vue page in `app/src/pages/<name>/` + entry in `app/src/entries/` +
registered in `app/vite.config.js`, visually matching the Comments
layout (filter pills, search, table with inline row actions,
pagination) — Media is the one exception, using a thumbnail grid
instead of a table, since that's what a media library actually needs.
- `SubApps.php`: new `PAGES` entry, `parent_slug()`/`capability()` cases,
and a branch in `redirect_native_pages()` — the native screen's file
(`edit.php`, `edit.php?post_type=page`, `upload.php`, `users.php`)
redirects to the Aurora page on **direct visits** (typed URL/bookmark),
not just the sidebar link.
- `MenuSerializer.php`: a matching rewrite so the sidebar's own link
(which shares the same slug as the parent, per WP convention) points at
the Aurora page too.
- A Settings toggle (`modern_posts`/`modern_pages`/`modern_media`/
`modern_users`, all `default: true`) gating the redirect+link-rewrite,
so the native screen can still be reached if turned off. `modern_pages`/
`modern_media`/`modern_users` are new categories/fields this session;
`modern_posts` already existed (see below). All the `modern_*` toggles
now consistently set `default: true` in the Settings UI to match their
actual PHP default (previously some defaulted true server-side but
showed off in the UI until explicitly saved — cosmetic mismatch, fixed
across the board).
Two deliberate scope decisions worth remembering if asked "why doesn't X
work":
- **Media**: replaces the *library/browse* experience only — uploading
(`media-new.php`, drag-drop/chunked uploads) was left alone entirely,
same reasoning as leaving the block editor alone for Posts/Pages.
- **Users**: deleting a user always reassigns their content to whoever
performs the deletion, rather than exposing WP core's "delete this
user's content too, or reassign to someone else" choice screen as a
one-click REST action — the null-reassign path in `wp_delete_user()` is
much more destructive than is safe to offer with one click, so it's not
offered at all.
`modern_posts`/`modern_plugins`/`modern_comments` were themselves each
briefly **removed** earlier in this same session (when they had no
implementation behind them) and re-added once real pages existed — if
you ever see a settings field described as removed for "describing a
feature that didn't exist," check whether it's since been rebuilt before
assuming it's still missing.
## Theme system (rewrite — supersedes the old dark_mode 3-state model)