Skip to content

[ADD] dms_libreoffice_preview: server-side office→PDF preview handler - #6

Closed
dnplkndll wants to merge 0 commit into
19.0-imp-dms-uxfrom
19.0-add-dms-libreoffice-preview
Closed

[ADD] dms_libreoffice_preview: server-side office→PDF preview handler#6
dnplkndll wants to merge 0 commit into
19.0-imp-dms-uxfrom
19.0-add-dms-libreoffice-preview

Conversation

@dnplkndll

@dnplkndll dnplkndll commented May 25, 2026

Copy link
Copy Markdown

Stacked on #3. Needs PR #3's preview-handlers registry (dms.preview_handlers, introduced in Phase 3 of the UX work) — the JS handler in this module imports from @dms/js/components/preview/preview_registry.esm which only exists with #3 applied. PR base targets 19.0-imp-dms-ux accordingly.


First downstream consumer of the Phase 13 preview registry introduced in OCA/dms 19.0. Fork-only PR for runboat preview + stakeholder review; will reopen against OCA/dms once the 19.0.1.0.0 base wheel ships.

What's shipped

A new sibling addon dms_libreoffice_preview/ that converts office files to PDF on the server via headless LibreOffice and routes them through the existing side-pane preview, replacing the OfficeFallbackPreview download card.

  • Lazy + cached: nothing converts until first preview request. Converted PDF cached as a child ir.attachment of the source dms.file (res_model/res_id), keyed on write_date in the description field. Cache auto-invalidates when the source changes and auto-cascades on file deletion.
  • ACL-clean: controller calls dms.file.check_access('read') before serving; the preview attachment inherits the parent's permissions.
  • Sync subprocess per call, 60s timeout, per-conversion temp directory to avoid .~lock collisions between concurrent workers. Daemon mode (unoserver) is a future optimization, not v1.
  • JS handler registers at score 10 — beats the score-0 OfficeFallbackPreview in base dms, leaves room for a future dms_onlyoffice at score 20.
  • Zero new SCSS — reuses the existing o_dms_preview__iframe class so the browser's native PDF viewer renders the result identically to source-PDF files.

Architecture

Browser side                    Server side
─────────────                   ────────────────────────────────────────
clicks .ppt card                ┌─ DmsLibreofficePreviewController ───┐
  │                             │  /dms/file/<id>/libreoffice_preview │
  ▼                             │                                     │
Registry resolves               │  on first hit:                      │
.ppt → office mime              │   • dms_file.check_access('read')   │
  │                             │   • file.sudo()                     │
  ▼ (with this module)          │     ._ensure_libreoffice_preview()  │
LibreofficePreview (score 10)   │   • subprocess soffice → /tmp PDF   │
  ├ <iframe src="…?v=…">        │   • cache as child ir.attachment    │
  ▼                             │   • return cached PDF on subseq.    │
PDF rendered natively           └─────────────────────────────────────┘
by the browser
                                Cache key: description='libreoffice_preview:<write_date>'

External dependency

LibreOffice + fonts. Declared via external_dependencies.deb in __manifest__.py so OCA CI's oca_install_apt_packages picks them up automatically:

apt-get install -y libreoffice fonts-noto fonts-liberation

fonts-noto + fonts-liberation matter even in containers that already have a base font set — headless LibreOffice substitutes ugly fallbacks for missing common fonts and you end up with unreadable PDFs.

Tests

Layer Coverage
Python — mimetype gate ODT detected as supported; arbitrary bytes are not
Python — happy path _ensure_libreoffice_preview() produces a PDF attachment with %PDF- magic bytes
Python — cache hit Second call returns the same ir.attachment.id, no new subprocess
Python — invalidation write_date drift forces a new conversion
Python — no soffice FileNotFoundErrorUserError with install hint
Python — controller 404 for non-office files; 200 + application/pdf for office files
Hoot — registry Every supported office mimetype routes to LibreofficePreview at score 10
Hoot — URL builder src includes /dms/file/<id>/libreoffice_preview + v= cache-bust

soffice-dependent tests skip cleanly when the binary isn't on PATH (covers local dev environments without LibreOffice installed).

Composes with future dms_onlyoffice

OnlyOffice Document Server is a different product (live editing + collab, separate container, AGPL or commercial). When/if dms_onlyoffice ships, it registers at score 20 and wins over this module for office mimetypes — both can coexist; the higher score wins. See memory: dms_onlyoffice_prior_art.md for the bringout 16.0 adapter as a starting point if/when we go that route.

Out of scope

  • Daemon / unoserver listener — only if conversion throughput becomes a bottleneck. Today: subprocess per call.
  • CSS theming of the converted PDF — LibreOffice's default rendering only.
  • Backend tour — defer to v1.1 once the runboat image reliably has LibreOffice installed.

dnplkndll added a commit that referenced this pull request May 25, 2026
The new module addition (dms_libreoffice_preview) pushed after a burst
of activity on PR #3 / PR #5 today \u2014 GitHub's anti-abuse heuristic
silently dropped the pull_request trigger for PR #6. workflow_dispatch
lets us `gh workflow run` manually when this happens. Same pattern
used on the 19.0-imp-dms-ux + 19.0-ci-ui-artifacts branches.
dnplkndll added a commit that referenced this pull request May 25, 2026
The new module addition (dms_libreoffice_preview) pushed after a burst
of activity on PR #3 / PR #5 today \u2014 GitHub's anti-abuse heuristic
silently dropped the pull_request trigger for PR #6. workflow_dispatch
lets us `gh workflow run` manually when this happens. Same pattern
used on the 19.0-imp-dms-ux + 19.0-ci-ui-artifacts branches.
@dnplkndll
dnplkndll force-pushed the 19.0-add-dms-libreoffice-preview branch from ad6c14d to 5c2f379 Compare May 25, 2026 20:25
dnplkndll added a commit that referenced this pull request May 25, 2026
The new module addition (dms_libreoffice_preview) pushed after a burst
of activity on PR #3 / PR #5 today \u2014 GitHub's anti-abuse heuristic
silently dropped the pull_request trigger for PR #6. workflow_dispatch
lets us `gh workflow run` manually when this happens. Same pattern
used on the 19.0-imp-dms-ux + 19.0-ci-ui-artifacts branches.
@dnplkndll
dnplkndll force-pushed the 19.0-add-dms-libreoffice-preview branch from 5c2f379 to 55bfe72 Compare May 25, 2026 20:26
dnplkndll added a commit that referenced this pull request May 25, 2026
…TP tests

Two CI failures from the first run on PR #6:

1. test_cache_invalidation: previous version keyed the cache on
   write_date, which doesn't reliably bump between a .write() call and
   the very next read in the same transaction \u2014 both calls hit the same
   cached attachment id and the assertion failed. Switch the cache key
   to dms.file.checksum (SHA1 of content, already maintained by base
   dms). Renaming a file no longer triggers re-conversion; only an
   actual content change does. Test renamed to
   test_cache_invalidation_on_content_change and writes a fresh ODT
   body via a seeded _build_minimal_odt(seed=...) helper.

2. test_controller_returns_pdf returned 404 because admin isn't in
   DocumentsBaseCase.access_group; check_access('read') failed and the
   controller short-circuited. Authenticate as dms-user (which IS in
   the group) and set its password since new_test_user() leaves it
   blank by default.
@dnplkndll
dnplkndll force-pushed the 19.0-add-dms-libreoffice-preview branch 2 times, most recently from 794f0ef to 5f2f1e1 Compare May 25, 2026 21:36
@dnplkndll
dnplkndll changed the base branch from 19.0-mig-dms to 19.0-imp-dms-ux May 25, 2026 21:36
@dnplkndll
dnplkndll force-pushed the 19.0-add-dms-libreoffice-preview branch from 5f2f1e1 to 2c7584a Compare May 25, 2026 22:08
@dnplkndll
dnplkndll force-pushed the 19.0-add-dms-libreoffice-preview branch from 2c7584a to a9f9ba7 Compare May 25, 2026 22:09
@dnplkndll
dnplkndll force-pushed the 19.0-add-dms-libreoffice-preview branch from a9f9ba7 to d9c2f07 Compare May 25, 2026 22:31
@dnplkndll
dnplkndll force-pushed the 19.0-imp-dms-ux branch 2 times, most recently from 095f9d7 to e8ffea4 Compare May 25, 2026 23:21
@dnplkndll
dnplkndll force-pushed the 19.0-add-dms-libreoffice-preview branch from d9c2f07 to 38cf981 Compare May 25, 2026 23:21
@dnplkndll dnplkndll closed this May 25, 2026
@dnplkndll
dnplkndll force-pushed the 19.0-add-dms-libreoffice-preview branch from 38cf981 to cbb1ac7 Compare May 25, 2026 23:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant