github austinginder/minn-admin v0.12.0

latest releases: v0.35.0, v0.34.0, v0.33.0...
one month ago

The workflow release. Surfaces grow from lists into complete workflows: schema-driven settings views, bulk actions with shift-select, status filters, parameterized actions, setup gates for first-run installs, and honest outcome reporting, all proven end to end on Gravity Forms and Gravity SMTP. Six more plugins join the families (Perfmatters, Ninja Forms, Solid Security, Limit Login Attempts Reloaded, WP Mail Logging, Duplicator), Settings mirrors WP 7.0's new Connectors registry, the license manager settles in beside the plugins it describes on Extensions → Licenses, and the header wears the site's own name and icon so you can tell which site you're in at a glance.

Added

  • Solid Security support: its lockouts join the Activity Log family: every host, user and username lockout with a locked / expired / released pill, a "Locked out now" tab, search, and a status card reporting who's locked out right now, all-time lockouts, banned hosts and which protection modules are on. Actively locked rows carry a Release lockout action through Solid Security's own lockout API, and the System page gains a Solid Security posture row (brute force protection on or off, with firewall and two-factor noted). Its dynamically granted management capability is honored, so sites using its user-groups feature keep their access model.
  • Ninja Forms support: entries join the Forms surface as contact cards: answers summarized in form order, per-form tabs, search across every field, and a detail card with labeled answers, entry number and submission time. Field labels are read from Ninja Forms' own models at runtime, so editing a form updates old entries' cards too, and answers whose field was since removed still show. A Forms view lists each form with a live entry count and a one-click jump into Ninja Forms' builder, and Trash routes through its own submission model (restore stays on its screen; the confirm says so). Its submissions capability filter is honored, so a site that grants entries to editors grants Minn's view the same way.
  • Duplicator support: its packages join the Backups family: every package with its archive size read from the files on disk, who built it, and a completed / building / error pill; a status card with the newest package, package count and total disk footprint (honestly labeled: free-tier packages are manual builds, so Minn makes no freshness claims, the Disembark rule); and package delete routed through Duplicator's own cleanup so archive files, logs and temp files go with the row. Building a package stays on Duplicator's screen, one click away.
  • WP Mail Logging support: its email log joins the Email family: every logged send with sent/failed status, tabs, search, a detail view with the full message (HTML mail renders sandboxed) plus headers, host and the error text, Resend routed through the plugin's own resender service (so recipient splitting, header cleaning and attachment paths stay its logic, and the new attempt appears as its own log entry), and permanent delete matching its log screen. Its "who can see submission data" capability setting is honored.
  • Limit Login Attempts Reloaded support: the lockout log joins the Activity Log family. Every lockout with the username, IP, attempt count, gateway (login form, XML-RPC, password reset) and a lifecycle pill (locked / expired / unlocked), a "Locked out now" tab, search, and a status card showing who's locked out right now, failed attempts in the last 24 hours, all-time lockouts and the configured policy. Actively locked rows carry an Unlock IP action that mirrors the plugin's own unlock handler through its own Config store. Plugin settings stay on its screen, one click away.
  • Perfmatters support, and settings-only surfaces: a surface can now declare settings with no collection at all and its settings view renders as the whole page, the right shape for plugins that are configuration rather than data. The bundled Perfmatters adapter is the first: a Performance page under Tools with all nine of its settings tabs (General, JavaScript, CSS, Code, Preload, Lazy Loading, Fonts, CDN, Analytics) drawn at runtime from the plugin's own core-Settings-API registrations, so a Perfmatters update that adds a field shows up in Minn without an adapter change. Saves merge only the edited keys and go through Perfmatters' own registered sanitizer (one-per-line lists normalize exactly like its own form), unknown keys never write, and the handful of fields drawn by bespoke callbacks count as locked with a link to the full screen.
  • Gravity SMTP suppressions: the Email surface's view switcher gains Suppressions: the addresses Gravity SMTP refuses to send to, listed with reason and notes, searchable, with suppress-an-address (create form) and reactivate, all through Gravity SMTP's own model under its granular suppression capabilities. Reads use a direct scoped query because the plugin's own count and search disagree on partial terms, which would have made the pager lie. The status card links out to the debug log until surfaces grow a third list view.
  • Status filters on surfaces: a collection can declare a filter (a second dimension beside the tabs, rendered as a segmented control) whose value rides a plain query parameter or merges into the same JSON criteria object the search box uses, for APIs like Gravity Forms that take both in one param. Gravity Forms entries get Received / Spam / Trash views out of it, which finally makes the whole workflow round-trip inside Minn: spam and trashed entries are visible, Not spam, Restore and Delete permanently appear exactly where they apply, and the bulk bar only offers verbs at least one listed entry can take.
  • Actions can report honest outcomes: an action route may return a message that replaces the default "done" toast. Gravity SMTP's send-a-test and resend use it for the multi-mailer reality: only one mail plugin can own the sending pipeline, so when another active mailer (FluentSMTP, say) carries the send, the email delivers but never appears in Gravity SMTP's log. The toast now says exactly that instead of implying it was logged.
  • Parameterized actions: a surface action (detail modal or status card) can declare fields, and clicking it swaps the button row for an inline form whose values ride the request. First consumers: Send a test email on the Email surface's status card (through Gravity SMTP's own force-connector pattern) and Add note on Gravity Forms entries (shimmed through GFAPI::add_note; Gravity Forms' own REST notes route creates the note but then fatals building its response). The status card also now reports the active sending service and test mode at a glance.
  • Bulk actions on surfaces: any surface (bundled or third-party) can declare bulk actions and its list grows a checkbox column with shift-range select, a Select-page control and a selection bar. Actions apply per item so one failure never aborts the rest, per-item conditions skip ineligible rows in a mixed selection, and the result toast counts done, skipped and failed. Documented in docs/for-plugin-authors.md, validated on the Integrations card.
  • Gravity Forms entry workflow: entries can be starred and unstarred (singly or in bulk), marked as spam, trashed in bulk, and their notifications resent, all through Gravity Forms' own workflow endpoint under its own capabilities. Opening an entry marks it read exactly like GF's own screen, and entry notes now render as a section on the entry card (which used to drop sections it didn't recognize). Restoring from spam or trash stays in wp-admin until Minn grows a status filter, and the actions say so honestly.
  • Gravity SMTP, fully at home: the Email Log surface grows a Settings view built from Gravity SMTP's own settings schema. The Sending tab lists all 21 connectors, renders the primary connector's configuration (host, credentials, from controls, whatever that connector declares), and switching the primary service reloads the tab with the new service's own fields; the General tab covers test mode and the email and debug log controls. Everything reads and writes through Gravity SMTP's own data stores, so GRAVITYSMTP_* wp-config constants keep winning and stored secrets stay behind their **************** mask (an unchanged mask never overwrites the real value). The surface now honors Gravity SMTP's granular gravitysmtp_* capabilities instead of a flat admin check, the email detail is enriched through its own models (from, cc, bcc, source, resend eligibility), and Resend replays the original recipients, headers and attachments through the configured connector rather than approximating with a plain send. One-click OAuth handshakes (Google, Microsoft, Zoho) stay on Gravity SMTP's own screen, honestly counted as advanced settings with a link.
  • Settings views for surfaces: an adapter (bundled or third-party) can now declare a settings key on its surface and get a real settings UI in Minn: tabs it names, forms drawn from a schema its own route serves at runtime, saves routed back through the plugin's own settings APIs. Only edited keys ride a save (untouched values never round-trip through a plugin's sanitizers), masked secrets that ride back unchanged never clobber the stored value, a refused save keeps the form as typed, and a group's locked count links the too-bespoke remainder to wp-admin. Because the schema is read from the live plugin, a plugin adding a field updates its own coverage with no Minn release. The contract is documented in docs/for-plugin-authors.md and validated on the System page's Integrations card.
  • WP 7.0 Connectors: Settings gains a Connectors section mirroring core's new connector registry (AI providers and other external services). Each connector card shows its connection state and where its key comes from: a saved key, a wp-config constant or an environment variable, with the latter two honestly read-only since they win over anything saved. Cards install or activate the provider's companion plugin in place, link to the vendor's key page, and save keys through core's own settings route, so core masks every response (a raw key is never echoed back to the browser) and validates AI provider keys against the live provider. A rejected key is named plainly, kept in the field for a retype, and never stored. Third-party connectors registered through core's wp_connectors_init appear automatically.
  • Setup gates: a freshly installed plugin often needs its own first-run install (tables, default groups) before its surface can work, and pointing a fully-armed surface at it produced raw errors deep in a form. A surface can now declare a setup gate: until the plugin's own readiness check passes, the surface renders a setup card in place of the list, with the plugin's wizard questions as toggles and one Set up now button that runs the plugin's own installer. The bundled Redirection adapter is the reference (monitoring and logging surface as toggles; IP logging defaults off, a privacy choice Minn won't make silently), setups Minn genuinely cannot run inline render an honest link-out, and the contract is documented in docs/for-plugin-authors.md and validated on the Integrations card.

Fixed

  • Table, image and code chips wiggled during scrolling: the ⚙ chips on editable tables, images and code blocks were pinned to the viewport and chased the page per scroll frame, so fast scrolling made them jitter, drift past their block and snap back (worst with the trackpad's elastic bounce). They now live inside the scroller at content coordinates like island chips, riding the scroll natively with zero lag, and re-anchor whenever the page actually reflows (late image loads, block previews rendering) instead of on every scroll tick. The sticky toolbar covers passing chips naturally.
  • Combobox panel detached during fast scrolling: a dropdown panel that had re-anchored to the viewport (the no-room-below escape) chased the page during scrolling and visibly lagged behind it, showing a gap between the panel and the content until the scroll settled, worst with the trackpad's elastic bounce. A re-anchored panel now closes on a real page scroll, exactly like a native select; panels that fit in place still ride the scroll seamlessly, scrolling inside the option list never closes it, and the highlighted option is revealed by scrolling only the list itself (revealing it the old way could nudge the page and instantly re-close the panel).
  • ACF panel saves failed with an empty select in the group: ACF reports false over REST for any field without a value, including selects and text fields. Panel saves round-trip the whole values object, so that sentinel made ACF's own validation reject the write and every panel save on the post failed with a 400, while the editor looked fine. Empty values now normalize on load, and clearing a select sends the null ACF expects.

Improved

  • "Week starts on" is a themed dropdown: Settings → Site now renders it as Minn's searchable combobox like the other pickers, instead of a native OS select popup.
  • The header wears the site's own identity: the sidebar logo used to say the product twice (the "m" mark and a "minn" wordmark). Now the mark is the site's WordPress Site Icon when one is set (falling back to the gradient "m" tile), and the wordmark is the site name, so you can tell which site you're in at a glance, the same context wp-admin gives. The name falls back to "minn" when a site has no name, and a long title truncates rather than pushing the version badge around. Changing the Site title or Site icon in Settings updates the header immediately, no reload.
  • A quiet way back to wp-admin: the account card now carries a WordPress mark beside Log out that opens the classic admin in a new tab. The exit used to live only in the ⌘K palette and the contextual "Edit in wp-admin ↗" links, so someone who didn't know the palette had no visible way out. It stays deliberately quiet (a small icon, not a prominent topbar button): Minn is where you work, wp-admin is a tool you dip into.
  • One Time Login gets its first UI: that plugin is CLI-only (it ships no admin screen), so the users row menu now offers Copy one-time login link, minting a single-use login-as-that-user link through the plugin's own token generator and copying it to the clipboard. The link is a secret, so it's generated on demand and never stored; the endpoint is gated on edit_user for the target, matching the plugin's own REST route. When "Minn is the default admin" is on, a one-time login lands in Minn too (the plugin hardcodes a wp-admin redirect that skips the normal login filter, so Minn intercepts its own post-auth hook).
  • Switched sessions get a way home: switching to another account via User Switching used to be a one-way door in Minn (the plugin's switch-back link lives in wp-admin's admin bar, which Minn never renders). A switched session now shows an amber Switch back to ⟨you⟩ bar above the user card, through the plugin's own nonce URL, landing back in Minn as yourself.
  • Health cards with a destination are clickable: System health cards that have somewhere to act now carry a small ↗ and go there: Backups opens the Backups surface, Debug mode scrolls to the Debug tools card, a pending WordPress update opens Extensions, a hidden site opens Settings → Visibility, and Licenses opens the license manager. Adapter posture rows can declare an href (Wordfence's firewall and scan rows open its own screens; Solid Security's row opens its dashboard). Cards that are pure facts with no in-app fix (PHP version, HTTPS, memory) stay plain on purpose.
  • The license manager moves to Extensions → Licenses, de-noised: licenses now live beside the plugins and themes they belong to, as a third Extensions tab. Rows group by state (needs attention first, then valid, then no license), inactive components collapse behind a count, and only Activate stays an inline button: deactivate, re-verify and turn-on tuck into a per-row ⋯ menu built from what that row can actually do. The System page keeps the Licenses health check (now clickable, jumping straight to the manager) and the copy report's licenses section; the big card and its ~40 always-visible buttons are gone.
  • Extensions toolbar, calmed: the view switcher (Plugins / Themes / Licenses) sits on its own row with page-wide Update all beside it, and the second row is consistent across tabs: quiet text filters with counts (no more boxed pill strip stacked on a boxed tab strip), then search and the Add button aligned right.
  • Plugin icons load themselves: wp.org icons and directory links ride the update-check transient, which every plugin activate/deactivate wipes. When it's empty, Minn now primes it on demand instead of showing letter tiles until the next cron check, so a site whose only admin is Minn still gets real icons.
  • Adapter dropdowns are themed autocompletes: every select an adapter declares (surface settings, create and edit forms, parameterized action fields) now renders as Minn's strict searchable combobox instead of a native OS select popup, the same control the Email surface's primary-service picker already used. Typing filters, the current choice stays highlighted, and an untouched control still submits exactly what an untouched select would. Editor sidebar panels and the block inspector deliberately keep native selects (compact, and their clear-to-default semantics live there).
  • Images can link, and the lightbox is a toggle: the image popover gains a Link URL field (with open-in-new-tab) and an "Expand on click" lightbox switch, closing two gaps where the block editor was still required. The link is stored exactly as Gutenberg stores it (the anchor wrapped inside the figure), so posts stay valid in both editors, and the two options are mutually exclusive with an explanation, matching core's own rule.
  • Focus and outline mode wear an exit chip: entering either mode used to leave no visible way out (the entry toast names the shortcut, then vanishes). The topbar now shows a dismissible "Focus mode ✕" / "Outline mode ✕" chip beside the editor's status badge; clicking it exits, and it survives reloads with the persisted mode. A back arrow was considered and rejected: it reads as "leave the editor," and this is a view mode, not a place.
  • Recent activity is clickable: the Overview feed's rows navigate to where the activity happened: posts and pages open in the editor, comments land on the matching moderation tab.
  • Gravity Forms notification notes read clean: notes written by notification logging store raw HTML that wp-admin renders; Minn's entry card showed the markup as text soup. Notes now render as plain text with the note's link (View Email and friends) surfaced as a proper link row.
  • The mail surface is called Email now (it grew settings and a status card; "Email Log" undersold it and read oddly as a place to configure sending). Gravity SMTP's view switcher reads Log / Settings, and the primary-service picker is the same themed autocomplete used everywhere else in Minn instead of a 21-option native select. The form engine gained combobox as a first-class field type for any adapter's settings.
  • One form engine: the three field renderers that grew up independently (surface create and edit forms, editor sidebar panels, the block inspector's generated controls) now render through a single engine with one field vocabulary, one value reader and one coercion path. Nothing changes for adapter authors except more consistency: edit fields accept the full create vocabulary (textarea, select, tags, rows, placeholder), and the Integrations card now validates create and detail.edit field lists (unknown types, selects without options, unknown keys) instead of letting them fail silently in the app.

Don't miss a new minn-admin release

NewReleases is sending notifications on new releases.