[2.x] Rework the admin settings page - #507
Merged
Merged
Conversation
The settings page was a single ~800 line scroll with eleven fieldsets and everything visible at once. Users reported it as complicated, badly laid out, and confusing to configure — S3 especially. Splits it into four tabs (Files, Storage, Images, Advanced), with the active tab held in the `page` route parameter so it survives a reload and each tab is a real link. The admin panel routes on the hash, so writing the tab into location.hash replaced the route and bounced to the dashboard; this follows fof/seo's approach instead. File types are no longer edited as raw regexes. A pattern that decomposes cleanly renders as a media type plus one chip per subtype; anything that does not — no anchors, wildcards, nested groups — keeps its raw input untouched and is marked advanced, because silently rewriting a working pattern is worse than showing a regex. Every row can switch to raw editing regardless. Presets cover the groupings forums actually ask for. Row order is now visible and adjustable: the backend matches with first(), so the first matching pattern wins, which the old UI never showed. S3 is rebuilt around a provider preset (AWS, R2, Backblaze B2, Spaces, MinIO, Other) that sets the endpoint format, addressing style and ACL support an admin previously had to know from the provider's own docs. Existing configurations are detected from the saved endpoint. The two fieldsets are merged, and help text rewritten to say when each field applies rather than only what it is. Storage services are shown when configured or in use, with an explicit affordance for setting up another — configuring storage before assigning a file type to it is a normal order to work in. Services whose composer package is absent now link to install instructions rather than being silently absent. Saved data formats are unchanged throughout; this is presentation only. Also fixes the download template descriptions, which rendered blank because they used React's dangerouslySetInnerHTML rather than m.trust. Adds Jest for pure-logic frontend tests, following the bundled extensions' @flarum/jest-config setup. Standalone use needs four workarounds for flarum/framework#4689, each documented in jest.config.cjs. 37 tests cover the pattern round trip, which is the part that could corrupt saved config — and they caught a real bug, where + was rejected in subtypes, so svg+xml (in the shipped default pattern) could not be entered.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Changes proposed in this pull request:
The page was a single ~800 line scroll with eleven fieldsets, everything visible at once. Saved data formats are unchanged throughout — this is presentation only.
1. Four tabs
Files, Storage, Images, Advanced. Only the active panel renders. Each tab carries an unsaved-changes marker, since one save button now serves four panels.
The active tab lives in the
pageroute parameter, following fof/seo's admin pages. This matters: the admin panel routes on the hash (m.route.prefix = '#'), so an earlier version that wrote the tab key intolocation.hashreplaced the route and bounced to the dashboard on reload. Using the route also makes each tab a real link — bookmarkable, middle-clickable, works with browser Back.2. File types are no longer edited as raw regexes
A pattern that decomposes cleanly renders as a media type plus one chip per subtype:
Anything that does not decompose — no anchors (
text\/plain), wildcards (^image\/.*$), optional characters (jpe?g), nested groups, alternation in the type — keeps its raw input untouched and is marked "Advanced pattern". Silently rewriting a working pattern would be far worse than showing a regex. Every row can switch to raw editing regardless, so a technical admin is never boxed in.An "Add file types…" picker covers the groupings forums actually ask for (Images, PDF, Word documents, Spreadsheets, Archives, Audio, Video), plus "Custom pattern…".
3. Row order is now visible and adjustable
getMimeConfiguration()matches with->first(), so the first matching pattern wins — invisible in the old UI, and a correctness trap: adding a broad rule above a specific one silently changes where files go. Rows now have move up/down controls and a note explaining the behaviour. Verified that object key order survives the JSON round trip in both JS and PHP.4. S3 rebuilt around a provider preset
AWS, Cloudflare R2, Backblaze B2, DigitalOcean Spaces, MinIO, Other. Choosing one sets the endpoint format, addressing style and ACL support that an admin previously had to know from the provider's own documentation — R2, for instance, needs path-style addressing and rejects ACLs, none of which the page said. Existing configurations are detected from the saved endpoint, so upgraders see their provider already selected.
The two fieldsets ("AWS S3 storage settings" / "Advanced S3 storage settings") are merged — nothing previously indicated that a non-AWS provider needs fields from both. Help text rewritten to say when each field applies; the old
s3_compatible_storagestring ("only required when using S3 compatible storage") is gone.5. Storage visibility
Services are shown when configured or in use by a file type — configuring storage before assigning anything to it is a normal order to work in, and a part-configured service must not vanish. An explicit "Configure another storage service" affordance reveals the rest.
Services whose composer package is absent never appeared at all, so admins had no way to discover S3 or Qiniu existed. There is now a link to install instructions, which the README previously did not contain (it documented configuring S3 but never installing it).
6. Bug fix: blank template descriptions
The download-template list rendered every description blank, because it used React's
dangerouslySetInnerHTMLrather than Mithril'sm.trust.Reviewers should focus on:
mimePatterns.tsparse/build round trip. This rewrites saved config, so it is the highest-risk part. It refuses anything it cannot rebuild byte-identically. Tests cover both patterns from a real forum plus the shipped default.js/infrastructure changes —"type": "module",webpack.config.js→.cjs, and five new devDependencies. Needed for Jest; called out separately below.Frontend testing
Adds Jest via
@flarum/jest-config, matching the bundled extensions (tags, mentions, embed). Standalone use needs four workarounds for flarum/framework#4689, each documented inline injest.config.cjs:setup-env.jsimports@flarum/core→ mapped to the Composer-vendored copytest-matchers.tsis TypeScript insidenode_modules, never transformed → scopedtransformIgnorePatterns@babel/runtime/helpers/esm/*, blocked by that package'sexportsmap → mapped directly@babel/runtimev8 removed those helpers → pinned^7, matching the monorepoWorth noting:
@flarum/jest-configis published to npm (2.0.0) — issue #4689 states otherwise, so that part appears out of date. The real blockers were the four above. Happy to write this up on the issue if useful.enable_tests: trueadded tofrontend.yml. 37 tests, all passing.Confirmed
composer test).Testing
tsc --noEmitclean. Prettier clean.