[19.0][MIG+IMP] dms: Migration to 19.0 with kanban/form/portal UI enhancements#1
Open
dnplkndll wants to merge 195 commits into
Open
[19.0][MIG+IMP] dms: Migration to 19.0 with kanban/form/portal UI enhancements#1dnplkndll wants to merge 195 commits into
dnplkndll wants to merge 195 commits into
Conversation
versions of muk_dms than 12.0.2.0.0. Tested from 1.2.4 version.
In v13, this test is programmed in such a way that the demo user is supposed to be able to copy that subdirectory: https://github.com/OCA/dms/blob/c3f802db43362127e70d8c7b4987fb71d4c1f01c/dms/tests/test_directory.py#L40 However, in OCA#7 that test was modified indicating that demo user didn't have permissions to do that: https://github.com/OCA/dms/blob/e3b6d8d24534f2a68bfb88e310cc70cefe46bb64/dms/tests/test_directory.py#L39 Rolling back that change to ensure premissions remain the same in both versions of the module. Also changing the directory to test to ensure it contains no SVG files, whose detection seems to differ among environments, and which have some specific permission restrictions that can make the modified test fail or pass. @Tecnativa TT25645
Currently translated at 89.6% (322 of 359 strings) Translation: dms-18.0/dms-18.0-dms Translate-URL: https://translation.odoo-community.org/projects/dms-18-0/dms-18-0-dms/es/
The _check_access_dms_record method uses self.search(domain) to verify write permissions. However, search() applies active_test=True by default, which excludes archived records (active=False). This means when a user tries to unarchive a file via toggle_active(), the write permission check cannot find the archived record in the search results, causing an AccessError even when the user has full write permissions through DMS access groups. Fix: add active_test=False context to include archived records in the permission check search.
- Bump manifest version to 19.0.1.0.0.
- Adopt 19.0 group privilege model: replace res.groups.category_id with
privilege_id and the new res.groups.privilege record.
- Simplify to a 2-tier security structure (user / manager); group_dms_user
now implies base.group_user directly. Removed group_dms_viewer.
- res.users.groups_id → group_ids (demo XML + tests).
- res.groups.users → user_ids in access_groups._compute_users dependency.
- auto_join=True/False → bypass_search_access=True/False on 10 fields
across access_groups, directory, dms_file, storage.
- _sql_constraints → models.Constraint in dms_category, access_groups, tag.
- odoo.osv.expression → odoo.fields.Domain (all imports + AND/OR/Domain.TRUE
/FALSE/NEGATIVE_OPERATORS aliases at module top).
- read_group → _read_group with the new aggregate-tuple return format in
dms_security_mixin._get_domain_by_inheritance.
- @http.route(type='json') → type='jsonrpc' on the onboarding controller.
- Translation modernisation per pylint_odoo 19.0 (W8161 prefer-env-translation
+ W8301 translation-not-lazy): replace 'from odoo import _' with
self.env._() and lazy positional/keyword formatting throughout controllers
and models.
- DMS access filter restoration: override _search() on dms.security.mixin
to AND the access-group + inheritance domain into all non-su searches.
19.0 changed ir.rule._compute_domain() to use Domain.optimize (basic
level) instead of optimize_full, which means 'search=' methods on
computed-Boolean fields like permission_read are silently bypassed when
rule domain_force is evaluated. Without this override the
[('permission_read', '=', user.id)] global rules no-op and every user
sees every record.
- _search_starred now handles both '=' and 'in' operators (19.0's basic
optimizer normalises ('starred','=',True) to ('starred','in',{True}),
which the old single-operator branch did not recognise).
- Demo-data test guards: tests referencing dms.file_*_demo /
base.partner_demo_portal now skipTest() when the xmlid isn't found,
since 19.0 defaults to with_demo=False on CI.
- index=True → index='btree' on dms_file.attachment_id.
- _get_ref_selection(): pylint: disable=no-search-all (intentional,
enumerates all registered models for the reference selection).
- View / JS cleanups (adopted from OCA#474 by @HaithamSaqr): removed
deprecated <group expand='0' string='Group By'> attributes; removed
unsupported target='inline' on ir.actions.act_window; fixed OWL XPath
'//div' → '.' in empty KanbanView/ListView Buttons templates; replaced
store.Attachment with store['ir.attachment'] in attachment JS models.
Replace the auto res.users avatar in the kanban-card footer with a colour-coded initial chip, and surface human_size / extension / lock state as Bootstrap-style chips. Adds a new dms/static/src/scss/kanban.scss asset registered under web.assets_backend.
For records whose mimetype starts with image/, render a square thumbnail from /web/image/dms.file/<id>/image_128 instead of the generic file-type SVG icon. The image_1920 compute on dms.file already populates these for supported PIL mimetypes (+ image/svg+xml).
Replace the stacked Locked/Locked/Archived ribbon trio with two distinct ribbons (Locked-by-me + Archived) and fold the filename / path row and a new metadata pill row (extension, human_size, mimetype, lock state, updated-at) into a single oe_title hero block. The avatar image stays unchanged for image previews.
Delete the Meta Information + Access Information notebook pages and fold their fields into the existing settings group as two stacks: a Location column (directory, storage, category, tags) and an Activity column (created/updated chips, permission_write and permission_unlink toggles). The Technical Information page remains gated behind debug.
Replace the bare /my/dms portal table with a responsive Bootstrap card grid (col-12 / col-md-6 / col-lg-4 / col-xl-3). Directories get an orange folder badge; files get a monospaced uppercase extension badge plus a per-mimetype left-border accent (pdf=magenta, docs=blue, sheets=green, etc.). Hover lifts the card with a soft shadow.
Enable hierarchize=1 on the directory_id search panel field so the directory tree renders as a proper parent-child outline, and switch both directory_id and category_id to select=multi so users can chip-style filter on multiple directories/categories at once. SCSS tightens label density and dims counters with tabular-nums.
Replace the fa-cloud-upload fa-10x icon with an animated overlay: marching dashed border, a bobbing upload icon, a Drop files to upload CTA and a release-to-add hint. Pure CSS keyframes, no extra JS.
Apply the same hero/inline-metadata treatment to the dms.directory form as to dms.file: hero block with folder glyph, Root pill, human_size and count_elements chips, and a starred toggle. Fold the Meta Information + Access Information notebook pages into a unified Location + Activity group with 4 boolean_toggle permission pills (read/create/write/unlink). The inheriting view_dms_directory_new_form xpath is rebased onto the remaining settings group.
Hoists the per-extension and per-initial color systems into a single `_dms_tokens.scss` partial. The partial exposes: - `$dms-bucket-palette` — eight semantic buckets used for anything that needs a stable per-identity tint - `$dms-extension-accents` — file-family palette consumed by both backend kanban cards and portal cards - `dms-bucket-index($key)` / `dms-bucket-color($key)` — pure Sass hash helpers, no JS hook required - `dms-extension-vars($selector)` / `dms-initial-vars($selector)` — mixins that emit `--dms-accent` keyed off `data-ext` / `data-initial` No behaviour change yet — the partial is not @import-ed by anything in this commit. Subsequent commits replace the inline palettes in kanban.scss and portal.scss with calls into this partial.
…gn file kanban + form heros Introduces a shared `.o_dms_card` chrome (accent spine, hover lift, 56px tinted tile) and applies it across the directory kanban, the file kanban, and the directory/file form heros so the whole module reads as one visual system. Specifically: - **Directory kanban**: rebuilt from a `row g-0` thumbnail+text layout into a `flex` row with a 56px `.o_dms_card_tile` carrying the folder icon over a `--dms-accent` gradient. Tint is derived from a hash of the directory name (`data-initial`), so distinct directories read as distinct without any per-record color picking. Metadata gets surfaced as proper chips — directory count, file count, human size, and the last-writer initials chip — replacing the prior text-with-icon footer (which also rendered "5Directories" without spacing because the &nbsp; was a literal token). - **File kanban**: same wrapper class so spine + hover lift apply. `data-ext` on the card drives the per-extension `--dms-accent`; the extension chip then reads off `var(--dms-accent)` instead of a fixed primary. Image-mimetype previews use `.o_dms_card_tile_preview` to drop the chrome treatment so photos read as photos. The extension chip strips the leading dot so it shows `PDF` not `.PDF`. - **Form heros**: `.o_dms_dir_hero_icon` is gone — the hero glyph is now a tinted 28px square (`.o_dms_hero_icon`) consuming the same `--dms-accent` variable. Directory hero pins the variable to amber (matching the kanban default for directories), file hero stays neutral gray (per-extension tint isn't available statically in form arch and isn't worth a dedicated widget). - The kanban renderer's drop-zone background gets a soft radial wash so the marching-dash border doesn't feel detached when it appears. Replaces the manually-enumerated 26-letter `$dms-initial-palette` with the hash-bucket mixin from `_dms_tokens.scss`. No behaviour change for existing initial chips — same eight buckets, same letter→bucket mapping — but the source of truth is now a single 8-entry map.
Replaces the inline 26-entry `$dms-portal-accents` map with a single call into the shared `_dms_tokens.scss` partial. Same per-extension palette, same selectors generated — but the source of truth is now shared with the backend file kanban, so adding a new extension only requires touching one map. Tightens the visual treatment to match the backend cards: - The badge gets the same 135° highlight gradient the kanban tile uses (`linear-gradient(...) , var(--dms-accent)`), so the two surfaces feel like the same component at different scales - Card hover now lifts (`translateY(-1px)`) + softens the border toward the accent, matching the backend `.o_dms_card` hover - Card body picks up a faint top-edge gradient (`color-mix(... 6%, white)`) so the accent stripe doesn't feel detached from the card - Removes the now-redundant `.o_dms_portal_badge_dir` class — the parent card already sets `--dms-accent: #f08c00` via `.o_dms_portal_card_dir`, so the badge inherits it via the variable cascade
Documents the accent system, card chrome, metadata chips, hero block, portal grid, searchpanel typography, and drop-zone treatment introduced in the 19.0 series. Points readers at `_dms_tokens.scss` as the single source of truth for the palette + bucket-hash helpers.
…import The previous commit chain introduced `_dms_tokens.scss` with shared mixins/maps and tried to load it from `kanban.scss` and `portal.scss` via `@import "./dms_tokens";`. That fails under Odoo 19's SCSS bundler — libsass is invoked over a concatenated string of all bundle SCSS files and is not given an include-path that resolves relative imports inside an addon's static directory, so the @import returns nothing and every consuming `@include` errors with "no mixin named ...". Fix is two-fold: 1. List `_dms_tokens.scss` at the top of both `web.assets_backend` and `web.assets_frontend` in `__manifest__.py`. Odoo concatenates the listed SCSS files in order before compiling, so the partial's maps and mixin definitions are visible to every file that follows it in the bundle. 2. Drop the now-redundant `@import "./dms_tokens";` line from `kanban.scss` and `portal.scss`. The header comment in each file now points at the manifest as the load mechanism. Regenerated `README.rst` and `static/description/index.html` from the already-merged `readme/USAGE.md` UI section (oca-gen-addon-readme).
Re-flows long-attribute tags in the directory + file kanban XML templates and breaks the `dms-initial-vars` letter list onto one entry per line in `_dms_tokens.scss`. No semantic change — pure formatting required by the OCA prettier-with-plugin-xml configuration. (Force-pushing the earlier commits with the formatting baked in is not authorized for this PR branch; the prettier hook produces an additive diff that is safe to land as its own commit.)
Odoo's asset bundler scans SCSS source for `@import "..."` and emits a
WARNING-level log "Local import './dms_tokens' is forbidden for
security reasons" whenever it finds the pattern — even inside a
comment. With OCA_ENABLE_CHECKLOG_ODOO=1 those warnings fail the test
job ("Errors detected in log").
The actual `@import` directives were already removed in the previous
fix commit, but each SCSS header still mentioned the string by name
while explaining the manifest-based load mechanism. Rewords the
comments so the substring no longer appears anywhere in the bundle
inputs.
Three regressions identified during code review of the migration commit
([19.0][MIG] dms: Migration to 19.0). All restore behaviour that was
present in the 18.0 baseline and silently dropped during the port.
1. **File kanban view loses its Upload/Scan buttons.** The 18.0
`dms.KanbanButtons` template was deleted and
`buttonTemplate: "dms.KanbanButtons"` was removed from
`FileKanbanView`. A replacement template
(`dms.FileKanbanView.Buttons`) was added in
`file_kanban_controller.xml` but never wired into the view config,
and the template's `t-ref` + `t-on-change` names did not match the
`createFileUploadExtension()` API
(`fileInput` / `onChangeFileInput` / `uploadDocument`). Fix:
- Realign `dms.FileKanbanView.Buttons` to the extension's actual
ref/handler names, and restore the responsive mobile-Scan +
desktop-Upload pair.
- Add `buttonTemplate: "dms.FileKanbanView.Buttons"` to
`FileKanbanView` so the kanban toolbar actually receives the
buttons.
2. **`filter_domain` silently dropped from category + tag search.**
The 18.0 views explicitly set:
- `dms.category` → `['|', ('name', 'ilike', self), ('parent_id', 'child_of', raw_value)]`
(searching a parent category surfaces descendants — important UX
for hierarchical categories like `Internal / Human Resource`).
- `dms.tag` → `[('name', 'ilike', self)]` (case-insensitive
contains-match; locks in semantics regardless of Odoo's evolving
default field-search behaviour).
The migration replaced both with bare `<field name="name" />`,
changing search semantics. Restored both explicitly with a comment
noting why.
3. **List-renderer xpath `.` is correct but unobvious.** Odoo 19's
`web.ListView.Buttons` is a flat list of `<button>` siblings — the
18.0 `o_list_buttons` wrapper div is gone, so the prior class-scoped
xpath has no anchor. Bare `.` (the implicit root) is the right
answer in 19, but it reads as fragile. Added a comment block above
the three `<xpath>` blocks explaining the Odoo-19-side change and
why three separate one-node patches are preferable to a single
multi-node patch (sibling-addon merge friendliness).
Adds a token-by-token comparison table to USAGE.md so reviewers can see exactly which Odoo 19 `$o-*` and Bootstrap variables every `--dms-*` value falls back to, plus the rationale for places where we deliberately diverge (smaller 56px tile, smaller 11px chip font, hover-lift not present in Odoo core). Authoritative reference for the comparison is upstream `odoo/odoo@19.0:addons/web/static/src/scss/primary_variables.scss` and `addons/web/static/src/views/kanban/kanban.variables.scss`. Odoo does not publish a formal design-system document for 19.0, so we inline the relevant tokens here for review convenience. README.rst + the static description page are regenerated from readme/*.md by oca-gen-addon-readme.
Merged
6 tasks
dnplkndll
added a commit
to ledoent/odoo-design-system
that referenced
this pull request
May 16, 2026
A full Before / After / Roadmap walk through every dms surface we touched in ledoent/dms#1, packaged so a designer can import it into the design.hz.ledoweb.com Penpot instance without rebuilding from blank. ## What's in the bundle - `docs/case-studies/dms/README.md` — the master document. Reads as a design-review brief: aesthetic direction, surface-by-surface before/ after with embedded GCS-hosted screenshots, "why" + "next" for each, a 10-item ranked roadmap, and the token contract that ties the whole thing back to the design system. - `docs/case-studies/dms/surfaces.json` — structured frame manifest. One entry per Penpot page: label, screenshot URL, annotation text, forward-move list. The bootstrap script consumes this. - `docs/case-studies/dms/roadmap.json` — the 10-item roadmap as data (rank, surface, impact, effort, summary, dependency). Same content as the markdown table but consumable by the bootstrap script for the Roadmap page card stack. - `docs/case-studies/dms/scripts/bootstrap-penpot.mjs` — Node script that hits Penpot's REST API to create the project + file + one page per surface from `surfaces.json`, plus a Roadmap page from `roadmap.json`. Designer takes over from the skeleton. - `docs/case-studies/dms/scripts/README.md` — how to get a Penpot access token, run the script, and what it doesn't try to do. ## Why semi-automated for now `infra/deployments/penpot/README.md` calls out that the Penpot MCP server isn't wired into Claude yet. Until it is, the bootstrap script provides the REST-API floor: it creates the project skeleton and surfaces the screenshot URLs the designer drags onto each page. When MCP lands this script gets replaced by a declarative translator that is idempotent and layout-aware. ## Why a case study This is also the first artifact in a `docs/case-studies/` series. The same shape (README + surfaces.json + roadmap.json + bootstrap) should work for every OCA module we migrate to a coherent visual layer — establish the pattern here, reuse for the next module.
dnplkndll
added a commit
to ledoent/odoo-design-system
that referenced
this pull request
May 16, 2026
* docs: ship the DMS migration as a design case study (penpot-ready) A full Before / After / Roadmap walk through every dms surface we touched in ledoent/dms#1, packaged so a designer can import it into the design.hz.ledoweb.com Penpot instance without rebuilding from blank. ## What's in the bundle - `docs/case-studies/dms/README.md` — the master document. Reads as a design-review brief: aesthetic direction, surface-by-surface before/ after with embedded GCS-hosted screenshots, "why" + "next" for each, a 10-item ranked roadmap, and the token contract that ties the whole thing back to the design system. - `docs/case-studies/dms/surfaces.json` — structured frame manifest. One entry per Penpot page: label, screenshot URL, annotation text, forward-move list. The bootstrap script consumes this. - `docs/case-studies/dms/roadmap.json` — the 10-item roadmap as data (rank, surface, impact, effort, summary, dependency). Same content as the markdown table but consumable by the bootstrap script for the Roadmap page card stack. - `docs/case-studies/dms/scripts/bootstrap-penpot.mjs` — Node script that hits Penpot's REST API to create the project + file + one page per surface from `surfaces.json`, plus a Roadmap page from `roadmap.json`. Designer takes over from the skeleton. - `docs/case-studies/dms/scripts/README.md` — how to get a Penpot access token, run the script, and what it doesn't try to do. ## Why semi-automated for now `infra/deployments/penpot/README.md` calls out that the Penpot MCP server isn't wired into Claude yet. Until it is, the bootstrap script provides the REST-API floor: it creates the project skeleton and surfaces the screenshot URLs the designer drags onto each page. When MCP lands this script gets replaced by a declarative translator that is idempotent and layout-aware. ## Why a case study This is also the first artifact in a `docs/case-studies/` series. The same shape (README + surfaces.json + roadmap.json + bootstrap) should work for every OCA module we migrate to a coherent visual layer — establish the pattern here, reuse for the next module. * docs(dms): add idempotent Penpot service-account bootstrap script Registers hello@ledoweb.com on design.hz.ledoweb.com via the REST API, activates the profile via direct DB UPDATE (SMTP unconfigured on the cluster so verification email goes nowhere), mints a long-lived access token, and writes credentials to .env at the repo root. Re-runs reuse the existing password to refresh the token without locking out the account. Unblocks the Penpot MCP server wiring — the access token this writes is what design.hz.ledoweb.com/mcp authenticates against.
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.
What changed
Migrates the
dmsmodule from 18.0 → 19.0 and layers a refreshed visual design on top. Targets ledoent's 19.0 fork branch so we can pilot the redesigned DMS experience on Runboat before any upstream OCA contribution.The visual direction is "editorial / data-density / archival": every kanban card, form hero, and portal tile carries a single
--dms-accentCSS variable driven by data attributes on the markup. File cards key off the extension (data-ext); directory cards key off a hash of the directory name (data-initial). The same palette tints the card spine, the accent tile, and the metadata chips, so each identity reads as one visual unit across surfaces.Migration
[19.0][MIG] dms: Migration to 19.0— base port of the OCA 18.0 module to Odoo 19.0 (manifest version, deprecated API replacements, removal of dropped fields, view syntax updates).UI overhaul
Backend kanban — directory cards
Previously: a generic
folder.svgicon + name + tags + a<i class="fa fa-folder" /><span> </span>5Directoriesfooter that rendered the count and label without spacing because the was a literal markup token.Now: a 56px tinted tile, a clean name + tag row, a relative date, and a proper chip row showing subdirectory count, file count, human size, and the last-writer initials chip. The whole card uses the unified
.o_dms_cardchrome with an accent spine and a 1px hover lift.Backend kanban — file cards
File cards already had chips in the prior iteration. This pass:
.o_dms_cardchrome (accent spine + hover lift) so directory and file kanbans feel like one component family.var(--dms-accent)driven bydata-ext, so each file family (docs / code / images / media / archives …) reads as its own color..o_dms_card_tile_previewto drop the tinted treatment so photos read as photos.PDF, not.PDF).Form-view hero
The directory and file form heros share the same tinted 28px hero icon (
.o_dms_hero_icon). Directory hero is pinned to the "paper / amber" accent that the directory kanban defaults to; file hero stays neutral gray. Chip row collapses extension, size, lock state, and root state into a single line under the title.Portal
/my/dmsPortal cards consume the same shared accent system. Directory cards get the amber stripe; file cards get the per-extension stripe. Both cards lift on hover and the badge gets the same 135° highlight gradient the backend kanban tile uses.
Architecture
_dms_tokens.scss(NEW) — single source of truth for the palette, the per-extension accents, and the bucket-hash helpers. It's prepended into bothweb.assets_backendandweb.assets_frontendin__manifest__.pyso the maps and mixins are visible to every consumer SCSS file in the bundle. Odoo's asset bundler rejects relative@importfor security, so the prepend-via-manifest pattern is the load mechanism.kanban.scss— unified.o_dms_cardchrome (spine + hover lift + tinted tile) shared between directory and file cards. The 26-letter$dms-initial-paletteis gone; the hash-bucket helper from the partial generates the same selectors from an 8-entry map.portal.scss— drops its inline 26-entry extension palette and reuses the partial'sdms-extension-vars($selector)mixin. Card hover and badge gradient now match the backend.Verification
19.0-imp-dmsandpr1./my/dmsrenders directories + files with per-extension stripes and hover lift..tr_dms_directory_linkare preserved).Notes
19.0-imp-dmswas seeded with the upstream history before the migration commits. Squash-merging will collapse the chain to a single commit on19.0. The actual new work for the 19.0 series is the 13 commits prefixed[19.0][MIG|IMP|REF|DOC|FIX|CI]at the tip.19.0branch on this fork is currently just OCA repo scaffolding (copier files, no modules); this PR introducesdms/as the first 19.0 module.