Skip to content

feat(settings): add Administration Previews page - #63796

Open
rayvincent2 wants to merge 16 commits into
nextcloud:masterfrom
rayvincent2:feat/63795/previews-admin-page
Open

feat(settings): add Administration Previews page#63796
rayvincent2 wants to merge 16 commits into
nextcloud:masterfrom
rayvincent2:feat/63795/previews-admin-page

Conversation

@rayvincent2

Copy link
Copy Markdown

Summary

Adds a core Administration → Previews page (/settings/admin/previews) so admins can inspect and edit the existing preview config without hand-editing PHP arrays or fumbling with settings via occ.

This is a UI over the current keys (enable_previews, enabledPreviewProviders, size/memory/filesize limits, jpeg/webp quality, concurrency, Imaginary URL/key/preview_format, ffmpeg/LibreOffice paths, preview_expiration_days). No new public API for Memories or Preview Generator. An instance that never opens the page keeps today’s config.

Backwards compatible: same config keys, types, defaults, and IPreview API. The only change is that enabledPreviewProviders order is now try-order, not just a whitelist.

What the page does:

  • Full provider catalog with availability (ffmpeg, Imagick format, LibreOffice, Imaginary URL). A provider that still says “Requires …” cannot be enabled. Filling a path/URL unlocks the switch but does not auto-enable it. Save drops catalog providers that still fail their requirement.
  • Enable/disable and global try-order. enabledPreviewProviders stays a class-name whitelist; array order is now generation priority (IPreview::getProviders() is rebuilt in that order). Membership is unchanged. Unset lists are not rewritten on load; the first Save is what persists the key.
  • Reset to defaults restores the recommended list for this host (natives; Imaginary first if a URL is set; native HEIC only if Imagick can decode it). Movie / ImaginaryPDF are not auto-enabled.
  • Failed generations list with retry/clear (oc_preview_failures). Retry is getPreview() again, not a force-delete of cached blobs.
  • Master switch: when previews are off, the rest of the page is inert until Save.

Not in this PR (keep elsewhere):

Reviewers: the attached previews-admin-product-spec.md is the product spec for this page (config mapping, master vs this try-order, HEIC/Imaginary, failure recording, docs notes for previews_configuration.html). It is not the published admin manual and is not committed in the tree.

Screenshots

Previews-Administration-settings-Nextcloud-08-29-2026_12_08_PM

TODO

  • Unit tests for admin config, generator order, failure recording, section icon
  • Playwright admin-settings-previews.spec.ts
  • [X ] Attach screenshots (page + left-nav icon)
  • Attach previews-admin-product-spec.md

Checklist

  • Code is properly formatted
  • Sign-off message is added to all commits (verify the tip commit)
  • Tests (unit, integration, api and/or acceptance) are included
  • Screenshots before/after for front-end changes
  • Documentation (manuals or wiki) has been updated or is not required (spec attached; RST follow-up)
  • Backports requested where applicable (ex: critical bugfixes) (new 36 feature; no backport)
  • Labels added where applicable (ex: bug/enhancement, 3. to review, feature component)
  • Milestone added for target branch/version (ex: 32.x for stable32) (36.x / master)

AI (if applicable)

  • The content of this PR was partly or fully generated using AI

Assisted by Grok (grok-4.6). I reviewed, tested on a live instance, and signed the commits. The product spec attached here was also drafted with that assistance and is for reviewers/docs, not shipped UI copy.

Add typed preview admin config, a MIME provider-priority resolver, HTTP
cache policies for preview responses, and a preview_failures table used
when generation cannot produce a preview. Authenticated responses stay
private unless an admin configures otherwise.

Assisted-by: Grok:grok-4.6
Signed-off-by: Ray Vincent <rayhvincent@gmail.com>
Add an Administration → Previews section for general limits, Imaginary,
provider order, MIME overrides, HTTP cache headers, and failed
generations. Saving is admin-delegable and requires password
confirmation.

Assisted-by: Grok:grok-4.6
Signed-off-by: Ray Vincent <rayhvincent@gmail.com>
Add concurrency, preview file expiry, failure retention, WebP quality,
and ffmpeg/LibreOffice paths to Administration → Previews. Fields that
depend on Imagick, ffmpeg, LibreOffice, or Imaginary are labelled from
detected availability and hidden when they do not apply.

Assisted-by: Grok:grok-4.6
Signed-off-by: Ray Vincent <rayhvincent@gmail.com>
Keep WebP quality, external-tool paths, and s-maxage visible instead of
hiding them. Label each as in use, not enabled yet, or not detected, and
offer an action that enables the related provider or visibility.

Assisted-by: Grok:grok-4.6
Signed-off-by: Ray Vincent <rayhvincent@gmail.com>
Move the enable toggle next to Save and disable the remaining admin
sections when previews are off, using a native fieldset and inert so
those controls are visibly and programmatically uneditable.

Assisted-by: Grok:grok-4.6
Signed-off-by: Ray Vincent <rayhvincent@gmail.com>
Track form dirty state from a settings snapshot, disable Save until
something changes, prompt on leave/reload, and add a second Save
changes control at the bottom of the long admin page.

Assisted-by: Grok:grok-4.6
Signed-off-by: Ray Vincent <rayhvincent@gmail.com>
Remove preview_provider_mime_priority/deny and the resolver so provider
order is only enabledPreviewProviders. Clarify that preview_format is
Imaginary-only. Tighten HTTP cache fields (required s-maxage when public,
hidden when private) and polish provider availability, Imaginary/Movie
Office sections, and quality copy.

Assisted-by: Grok:grok-4.6
Signed-off-by: Ray Vincent <rayhvincent@gmail.com>
Drop the HTTP cache policy UI. Record a failed generation when a
higher-priority provider misses even if a later one succeeds, and when
a preview request 404s. Use recommended defaults (Imaginary first when
configured, HEIC fallback, Movie available but not enabled). Mark
discouraged providers as unsupported, restore default order on reset,
and replace the status buttons with a dropdown plus source MIME
filtering and drag-and-drop.

Assisted-by: Grok:grok-4.6
Signed-off-by: Ray Vincent <rayhvincent@gmail.com>
Address ESLint indent and NcButton variants, Psalm catalog typing, PHP
CS import order, and run the e2e spec serially with NcSelect helpers.

Assisted-by: Grok:grok-4.6
Signed-off-by: Ray Vincent <rayhvincent@gmail.com>
Disable enabling a provider while Availability still says Requires.
Typing an Imaginary URL, ffmpeg path, or LibreOffice path unlocks the
switch but does not auto-enable. Save drops catalog providers that
still do not meet their requirement.

Assisted-by: Grok:grok-4.6
Signed-off-by: Ray Vincent <rayhvincent@gmail.com>
getProviders() still returns a MIME-regex map, but keys are inserted in
enabledPreviewProviders order instead of regex length. Generator walks
that map so overlapping providers (for example Imaginary then HEIC) run
in the admin table order, and a later provider still runs if an earlier
one fails.

Assisted-by: Grok:grok-4.6
Signed-off-by: Ray Vincent <rayhvincent@gmail.com>
Use longform watch handlers so Vue 2 object-shorthand and
new-line-between-multi-line-property pass.

Assisted-by: Grok:grok-4.6
Signed-off-by: Ray Vincent <rayhvincent@gmail.com>
Use a settings-owned template SVG instead of the themed MIME
filetypes/image.svg icon, which does not render in the left nav.

Assisted-by: Grok:grok-4.6
Signed-off-by: Ray Vincent <rayhvincent@gmail.com>
Match the save toast exactly and query provider enable controls as
switches, matching NcCheckboxRadioSwitch.

Assisted-by: Grok:grok-4.6
Signed-off-by: Ray Vincent <rayhvincent@gmail.com>
@rayvincent2
rayvincent2 requested review from a team, hweihwang and sorbaugh as code owners August 29, 2026 19:13
@rayvincent2
rayvincent2 requested review from Altahrim, CarlSchwan, kristian-zendato, leftybournes and skjnldsv and removed request for a team August 29, 2026 19:13
@rayvincent2 rayvincent2 changed the title Feat/63795/previews admin page feat(settings): add Administration Previews page Aug 29, 2026
@CarlSchwan

Copy link
Copy Markdown
Member

I like the idea. I will have to careful review the code next week

@rayvincent2

Copy link
Copy Markdown
Author

Yeah, sorry it's a big one... I'm happy to split it up if needed. I learned a lot about how previews are generated by each provider which I'm excited to reveal through this admin page.

I left my commit history so you could see my thought process as I went along too. Happy to squash that as needed.

I look forward to your comments!

@skjnldsv

Copy link
Copy Markdown
Member

Wow, that is a great feature!
I'll add that to the to-do next week too!! 👍

Comment thread apps/settings/src/views/AdminSettingsPreviews.vue Outdated

@susnux susnux left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great idea to improve this also for visual configuration!

Some review comments added. Some more general comments:

  1. This PR combines 3 separate features. Please split those. into individual scoped pull requests with 1 feature only.
  • Preview output format
  • Preview UI config
  • Preview "failures"
  1. For the "failures" I am not sure about the use case - thats already covered from the error log no? (while the other features are more explaining thus splitting would be again great)
  2. Please use modern code style for new files, meaning e.g. controllers should use Route definition using attributes and new Vue components must be script setup and Typescript.
  3. Please add e2e tests for the changes using our Playwright tests - see the other examples we have (use accessible selectors (name / role), neither custom data-* nor class names as the tests should work just like users interact with the page not like how scripts would see it).

For (4) adding something like this to the prompt often improves results:

Create a Playwright end-to-end test for [feature].
Use Page Object Models where possible and useful, share logic in utils or fixtures if useful. Use accessible roles or names for selectors instead of data-* selectors or class names. Focus on non flaky tests.

(of course adjust this too your needs)

Comment thread apps/settings/lib/Controller/PreviewAdminController.php Outdated
Comment thread apps/settings/appinfo/routes.php Outdated
Comment thread lib/private/Preview/Failure/PreviewFailure.php Outdated
Comment thread apps/settings/src/views/AdminSettingsPreviews.vue Outdated
Comment thread apps/settings/src/views/AdminSettingsPreviews.vue Outdated
Comment thread apps/settings/src/views/AdminSettingsPreviews.vue Outdated
Comment thread apps/settings/src/views/AdminSettingsPreviews.vue Outdated
Comment thread apps/settings/src/views/AdminSettingsPreviews.vue Outdated
Comment thread config/config.sample.php Outdated
Comment on lines +1676 to +1704
/**
* Output format used only by the Imaginary preview providers
* (``OC\Preview\Imaginary`` and ``OC\Preview\ImaginaryPDF``).
* Other providers ignore this key and keep the source image type.
*
* Valid values: ``jpeg``, ``webp``
*
* ``webp`` forces WebP for every Imaginary source. ``jpeg`` writes JPEG
* for most images and PNG for GIF, PDF, PNG, SVG, and Illustrator files.
*
* Defaults to ``jpeg``
*/
'preview_format' => 'jpeg',

/**
* How long failed preview generations are kept in ``oc_preview_failures``.
*
* Defaults to ``30`` days. Set to ``0`` to disable time-based cleanup
* (the max-rows cap still applies).
*/
'preview_failures_retention_days' => 30,

/**
* Maximum number of rows in ``oc_preview_failures``.
*
* Defaults to ``5000``. Oldest rows are dropped when the cap is exceeded.
*/
'preview_failures_max_rows' => 5000,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This independent from the UI changes, please split this big PR into individual features

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed the preview failures related config entries, but left the preview_format entry since it was implemented, but not added to this config sample from a previous implementation #38032.

Should we leave it in the config because it was should be there but was missed. Or would you prefer that I remove it? It's related to this PR because I've added the ability to manipulate this configuration via the admin page because it's an existing feature.

Comment thread apps/settings/src/views/AdminSettingsPreviews.vue
… feedback

Remove preview-failure recording from this PR. Convert the admin API to
an OCS controller with ApiRoute attributes, save on edit, keep sibling
NcSettingsSection blocks, and keep provider table order when toggling.

Assisted-by: Grok:grok-4.6
Signed-off-by: Ray Vincent <rayhvincent@gmail.com>
@rayvincent2

Copy link
Copy Markdown
Author

@susnux , thanks for the review — this is a much tighter PR now.

I pulled the preview-failures work out entirely (backend + UI). This PR is now only the Previews admin page plus honoring enabledPreviewProviders order as generation try-order. Happy to bring failures back later as its own PR if we agree it's a feature worth adding.

The other notes should be addressed here as well:

  • On sections: I kept sibling NcSettingsSections (Providers, General, Preview quality, Performance, Imaginary, Movie, Office) so the page still reads like Basic Settings. They are not nested. When previews are off, the rest of the page is hidden with v-if rather than wrapped in a fieldset. Let me know if I understood your guidance on NcSettingsSection nesting.
  • OCS controller + ApiRoute attributes (no routes.php entries)
  • New Vue is script setup lang="ts"
  • Save-on-edit
  • Providers is a real <table>
  • Playwright uses roles/names, no data-cy
  • Copy no longer names Preview Generator / Memories / Photos; product name comes from theming
  • Number fields have min/max; Office is framed as office documents
  • Read-only config.php still shows the page with a note and disabled controls (same idea as Mail)
  • On preview_format in config.sample.php: Imaginary already reads that key and has since NC 28. It was added in Imaginary WebP support #38032 for Imaginary WebP and never landed in config.sample.php. I only documented what was already implemented. Should I drop the sample comment from this PR and have that addressed separately? Based on the implementation I would expect it to be better named imaginary_format, but that's a breaking change and outside this PR. I'll take your lead on whether to leave config.sample.php alone. For completeness of this admin page I think we should still expose the Imaginary output format, since it is already a supported feature.

Please also find the updated previews-admin-product-spec.02.md file for reference if it helps understand the breadth of this work. Apologies if this file is more of a distraction than a help.

Use helper-text on the Imaginary API key field and aria-describedby on
the preview output format select so extra copy is associated with the
control.

Assisted-by: Grok:grok-4.6
Signed-off-by: Ray Vincent <rayhvincent@gmail.com>
@rayvincent2
rayvincent2 requested a review from susnux September 1, 2026 20:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Administration UI for core preview settings

5 participants