Skip to content

[19.0][MIG] dms_user_role: Migration to 19.0#11

Open
dnplkndll wants to merge 21 commits into
19.0-imp-dms-uxfrom
19.0-mig-dms_user_role
Open

[19.0][MIG] dms_user_role: Migration to 19.0#11
dnplkndll wants to merge 21 commits into
19.0-imp-dms-uxfrom
19.0-mig-dms_user_role

Conversation

@dnplkndll
Copy link
Copy Markdown

Port of dms_user_role from 18.0 to 19.0. Migration guide: https://odoo-community.org/page/migration-guide

Depends on ledoent/dms #8 (base dms 19.0 UX branch).

Non-mechanical adaptations worth flagging

None — pure ACL extension with no 19.0 API gaps. The _compute_users override uses record.users / record.count_users which are unchanged in 19.0, and the view xpath <page name="groups" position="before"> is still valid against the 19.0 base form.

base_user_role is published at 19.0.1.0.2.2 on PyPI; no dep pin needed.

dnplkndll added 12 commits May 25, 2026 21:14
…review + form heroes + portal grid + test coverage)

Comprehensive UX upgrade for OCA dms on 19.0, stacked on the in-flight MIG.
Fork-only PR for runboat preview + stakeholder review. See PR description for
the full breakdown; this is a single squash of 50 iteration commits.

Phases shipped:
  • Phase 1 — kanban density tiers (comfortable / compact / list) with toggle.
  • Phase 2 — directories landing dashboard: stat bar + live 30-day daily
    sparklines (line for files, bar for storage) + 24-hour line for "new today"
    + week-deltas. All data via _read_group over indexed create_date.
  • Phase 3 — side-pane file preview with extensible handler registry
    (dms.preview_handlers) + Download / Share / Open form toolbar. Built-in
    handlers for image, PDF, audio, video; office-format fallback with
    download + Google Viewer affordance.
  • Phase 8 — visual identity: per-extension accent palette (PDF crimson, code
    teal, docs blue, etc.) extracted to a shared SCSS partial used by both
    backend kanban and frontend portal; animated dropzone with marching dashed
    border; hash-bucketed initials chip on directory kanban cards; condensed
    form heroes for directory + file (icon + title + tag chips + path + stats
    grid + 2-tab notebook replacing the upstream loose-fields layout); portal
    card grid mirroring backend accents.
  • Phase 11 — late mockup gaps: kanban directory subtitle + extension pill;
    search facet pill styling scoped to dms surfaces.
  • Phase 12 — test coverage: 61 Hoot + Python test cases. Hoot suites for
    DmsStatBar, FilePreviewPane, kanban + list renderer routing, preview
    handler URL builders + dispatch; mount-view regression tests pinning the
    two browser-only Owl quirks (regex-literal tokenizer crash, boolean attr
    serialization). Python tests for get_dashboard_stats + _compute_path.
  • Phase 13 — preview routing consolidation: kanban file-icon click
    routes through the side-pane registry (dropping a redundant detour into
    Odoo's built-in `fileViewer` modal that bypassed the handler chain).
    New TextPreview handler covers text/*, application/json,
    application/xml, application/javascript via the same `/web/content`
    iframe pattern PdfPreview uses — browsers render the source natively.
    Form binary-field readable_types extended so the preview button shows
    for text mimetypes too.
  • CI — workflow_dispatch added to tests workflow so we can manually trigger
    when GitHub's anti-abuse heuristic throttles fork PR runs.

Architecture notes:
  • Preview-handler registry (dms.preview_handlers) is the extension point for
    downstream modules; the always-last DownloadFallback at score=-100 means
    every mimetype gets some handler.
  • path_names compute uses direct field assignment (OCA idiom).
  • Sparkline geometry is pure inline-SVG in dms_stat_bar.esm.js; no chart
    library dependency. Geometry pinned by Hoot tests.
  • Owl quirks documented + pinned by mount-view tests: QWeb t-* expressions
    can't tokenize regex literals; t-att-boolean serializes as empty string
    unless coerced to "true"/"false".

Signed-off-by: Don Kendall <dkendall@ledoweb.com>
Fork-only — diagnostics-stage iteration on top of the base UX modernisation
in this PR. To be split / squashed appropriately before any upstream OCA
submission.

OWL 19.0 readiness audit (per oca-review U/T pattern catalog)
- U7 (HIGH): delete dead static/src/js/views/file_kanban_controller.{xml,esm.js}.
  The XML defined dms.FileKanbanView.Buttons via t-inherit="web.KanbanView.Buttons"
  — the exact pattern that crashes at OWL render against 19.0's emptied
  template. Not wired anywhere; the view uses the self-contained
  dms.KanbanButtons template.
- U5 (MEDIUM): coerce boolean t-att-* attributes to explicit 'true'/'false'
  strings. Owl serializes truthy booleans as a presence flag (<div data-loading>),
  so CSS selectors [data-loading="true"] and tour selectors
  [aria-pressed="true"] silently never matched. Applied to data-loading
  on the stat bar and to aria-pressed on both density and preview toggles.
- U2 (style): convert 10 OWL 1 prototype-assignment idioms
  (Foo.template = "x"; Foo.props = {...}) to OWL 2 static class fields
  across 7 component classes. Cross-file `Renderer.template = "..."`
  assignments lifted into the renderer class declarations where they belong.

View toolbar collapse (overlap fix)
- Both renderers were stacking four absolute-positioned floaters in the
  top-right corner: preview-toggle pill (kanban + list), density toggle.
  Now collapse to icon-only buttons below Bootstrap lg (991.98px) so they
  share the row without overlapping the view controls.
Footer creator avatar in the directory kanban was rendering as a square
because core's oe_kanban_avatar doesn't apply border-radius in this
context. Add a scoped rule under .mk_directory_kanban_view so the
20x20 avatar matches the circular treatment already used on file cards.
Live audit on the PR #8 runboat (2026-05-26) surfaced these defects:

B1 — Sample.md rendered as raw text in the side pane. libmagic returns
text/plain for .md (no magic signature distinguishes it from prose), so
_effectiveMimetype() returned text/plain and TextPreview won over
MarkdownPreview. Add text/plain to _STORED_OVERRIDABLE so the extension
mapping wins for .md / .markdown / .json / .xml / .csv / etc.

B2 / B3 / B4 — Files list view polish:
- Add a leading mime-icon column (icon_url + image_url widget, 24×24)
  so list view matches kanban's scannability.
- Replace the raw mimetype column ("application/vnd.oasis.ope…") with
  the short extension field; rename column header to "Type".
- Set explicit widths on name (320), extension (90), human_size (100),
  write_date (180) so name no longer truncates ("Document…").

B5 — Form hero "TYPE" stat showed lowercase ("svg") while kanban cards
use uppercase ("SVG"). Add &--uppercase modifier on .o_dms_form_hero
__stat_value and apply it to the extension stat.

B9 — Standardise the modified-date column label across list ("Modified")
and form hero ("Modified"); upstream had "Last Updated on" in list.

B10 — Hide the Subdirectories / Files table in the directory form when
empty, reclaiming ~150px of blank rows on leaf directories. The
hero-stat tiles still expose the "+ Add" affordance.
B7 — Chromium's PDF viewer shows a dark grey backdrop during the
brief render window. Looked broken in screenshots / screen shares /
demos even though the PDF was loading fine. Force a white background
on .o_dms_preview__iframe so the loading paint is clean.

B8 — Empty preview pane consumed 40% of the viewport even when
nothing was selected. Add a .o_dms_preview_pane--empty modifier
(toggled when state.file is null and we're not loading/erroring)
that collapses the pane to 240px. The listing reclaims ~200px of
horizontal space; the eye-icon empty-state stays visible at the
narrower width. Pane snaps back to 40% the moment a file is
selected. Matches the macOS Finder / GNOME Files pattern.
Sibling addons (dms_field, dms_auto_classification, dms_libreoffice_preview,
future dms_onlyoffice / dms_ocr / dms_annotation) need the same
localStorage-backed UI state + side-pane state shape that the base file
renderers ship. Without an extraction they would each re-implement the
readStored/writeStored ceremony and the toggle/close/select methods.

useStoredState(key, default, {serializer, deserializer})
  - useState that auto-loads from localStorage on setup and auto-persists
    every change via useEffect. Templates read state.value; assignments
    to state.value flow through to writeStored.
  - serializer/deserializer hooks support booleans, JSON-shaped state,
    or any custom encoding without forcing a String(...) at the call
    site.

useDmsPreviewState(storageKey)
  - Encapsulates the open / recordId / toggle / close / select machinery
    that was duplicated across file_kanban_renderer + file_list_renderer.
  - recordId is intentionally non-persisted — it's tied to the current
    view's record set, not the user's hide/show preference.

Both renderers refactored to use the new hooks. Template-facing API
(previewState.open, previewState.recordId, togglePreview(), closePreview())
preserved via shim methods, so file_kanban_renderer.xml + file_list_renderer.xml
need no changes.

Lines of state machinery in the two renderers: ~85 → ~30.
Today, renaming a file means: click card → form opens → click name field
→ type → click save → back to kanban. Five clicks per rename. With
hundreds of files in a typical DMS, that's painful.

Add inline-rename to the file kanban card, matching the macOS Finder /
GNOME Files / Google Drive idiom:

- Double-click the filename on a card.
- The label swaps for a focused <input> at the same flow slot (no card
  geometry shift).
- Enter commits via record.update + record.save.
- Esc cancels (no write).
- Blur commits if the draft changed, cancels otherwise.

FileKanbanRecord gains a useState({active, draft}). The template
branches on renameState.active to render either the static label
(with dblclick handler) or the input (with input/keydown/blur
handlers). onGlobalClick swallows clicks while renaming so the input
doesn't accidentally trigger the side-pane preview routing.

SCSS adds an .o_kanban_dms_card__name_input rule with a primary-border
focus ring so the editable state is visually distinct from the read
state.

Also: extend .gitignore with session-local artefact patterns
(*-PLAN.md, SESSION-HANDOFF-*.md, DMS-UX-AUDIT-*.md, screenshots/,
dms-ux-prototype.html) so future commits don't accidentally pull in
work-in-progress audit material.
"Recent (7 days)" filter on the file search view, alongside "My Files"
and "Modification Date". Domain: write_date >= context_today() - 7d.

The audit doc proposed injecting a "🕒 Recent" pseudo-node into the
search-panel directory tree, which would require overriding
search_panel_select_range AND wiring the frontend to interpret the
synthetic entry as a date filter rather than a directory_id filter
— ~3 hours of work. This commit ships the 80% UX value (one click
to filter to recent files) for ~2 minutes of code. The search-panel
sliver injection remains a follow-up if the search-bar filter
proves discoverable enough; if so, we don't need to do it.
…stry, useDmsAccent)

- Add `name="hero_chips"` named div to both dms.file and dms.directory
  form heroes so siblings can inject chips without xpath collisions
- New `preview_action_registry.esm.js`: `dms.preview_actions` registry
  for extra FilePreviewPane action buttons; FilePreviewPane iterates
  registered entries after Download/Share/Open
- New `use_dms_accent.esm.js`: getDmsAccent/getDmsAccentFromName helpers
  + useDmsAccent OWL composable matching the dms_ext_palette.scss mapping
- Hoot tests for both new utilities
- Prettier: capitalise inline comments in use_dms_accent.esm.js; reflow
  _file helper and long assertion in preview_action_registry.test.js;
  collapse single-item import in use_dms_accent.test.js
- Remove t-on-input/keydown/blur/click/dblclick from kanban rename input
  in arch XML (19.0 view validator rejects t-on-* event directives in arch);
  wire all five handlers imperatively via useEffect(() => [renameInput.el])
  in FileKanbanRecord.setup() — same behaviour, validator-clean arch
…rrors

19.0 kanban arch validator rejects ALL OWL-specific directives (t-on-*, t-ref,
etc.) — not just t-on-input. The F3 inline rename used both t-ref and t-on-*,
making it impossible to keep in arch without a full widget-component extraction.

- Strip the renameState/startRename/commitRename/onRenameKeydown block from
  FileKanbanRecord; keep only the onGlobalClick override (preview pane routing)
- Remove the t-if/t-else rename block from dms_file.xml kanban arch; name div
  is now a plain static element (rename still available via Open form dialog)
- Replace () => {} noop callbacks in preview_action_registry.test.js with
  () => undefined to satisfy no-empty-function ESLint error rule
@dnplkndll dnplkndll force-pushed the 19.0-mig-dms_user_role branch 2 times, most recently from 01f6f89 to 995770a Compare May 27, 2026 14:24
dnplkndll and others added 6 commits May 27, 2026 10:37
- sort-imports: reorder import declarations by member-syntax tier then
  first-member alphabetically (multiple before single, none first)
- no-implicit-coercion: replace unary + on toFixed() results with Number()
- no-negated-condition: flip !== null ternary to positive condition
- no-inline-comments: remove inline comment on code line
- capitalized-comments: capitalize section comments in _ACCENT_MAP
TT48182

[UPD] Update dms_user_role.pot
[UPD] Update dms_user_role.pot
@dnplkndll dnplkndll force-pushed the 19.0-mig-dms_user_role branch from 995770a to 27ae930 Compare May 27, 2026 14:40
@dnplkndll dnplkndll force-pushed the 19.0-imp-dms-ux branch 2 times, most recently from beb9548 to cbef9f5 Compare May 29, 2026 01:08
dnplkndll added 3 commits May 28, 2026 22:28
…_user_role API

19.0 base_user_role removed the `users` field from res.users.role in favour
of `role_user_ids` (computed from line_ids.user_id). @api.depends path was
invalid at registry load, crashing module installation.
@dnplkndll dnplkndll force-pushed the 19.0-mig-dms_user_role branch from 1fd9a8f to de0ab13 Compare May 29, 2026 02:29
@dnplkndll dnplkndll force-pushed the 19.0-imp-dms-ux branch 3 times, most recently from 35f61e8 to 9929ce9 Compare May 29, 2026 20:42
@dnplkndll dnplkndll force-pushed the 19.0-imp-dms-ux branch 3 times, most recently from 41843a7 to fec90a4 Compare May 30, 2026 03:33
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.

2 participants