Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions dms/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@
"dms/static/src/js/fields/path_json/path_owl.xml",
"dms/static/src/js/fields/preview_binary/preview_record.xml",
"dms/static/src/js/views/*.xml",
# SCSS
"dms/static/src/scss/dms_form_hero.scss",
],
"web.assets_frontend": [
"dms/static/src/scss/portal.scss",
Expand Down
101 changes: 101 additions & 0 deletions dms/static/src/scss/dms_form_hero.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
// Copyright 2026 ledoent — Don Kendall
// License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
//
// Condensed form-header layout shared by `dms.directory` and `dms.file`
// forms — both view arches mark their root with `class="o_dms_form"` and
// embed a `<div class="o_dms_form_hero">` at the top of the sheet. Rules
// live here (rather than in dms_directory.scss or file_kanban.scss) so a
// future maintainer extending the hero on either model finds them in one
// obvious place.

.o_dms_form .o_dms_form_hero {
display: flex;
align-items: flex-start;
gap: 1.25rem;
padding: 0 0 1rem;
margin-bottom: 1rem;
border-bottom: 1px solid var(--bs-border-color-translucent, rgba(0, 0, 0, 0.075));

&__media {
flex: 0 0 auto;

.o_dms_form_hero__image {
width: 72px;
height: 72px;
border-radius: 12px;
object-fit: cover;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}

// Style the image widget's empty-state placeholder.
.o_field_image {
margin: 0;
}
}

&__body {
flex: 1 1 auto;
min-width: 0;
display: flex;
flex-direction: column;
gap: 0.5rem;
}

&__title {
display: flex;
align-items: baseline;
gap: 0.75rem;

h1 {
margin: 0;
font-size: 1.5rem;
font-weight: 600;
line-height: 1.2;
}
}

&__path {
font-size: 0.85rem;
}

&__tags {
margin-top: 0.25rem;
}

&__stats {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 1rem;
margin-top: 0.5rem;
max-width: 720px;
}

&__stat_value {
font-size: 1.4rem;
font-weight: 600;
line-height: 1.1;

// Strip the field widget's default chrome (margins, borders) so the
// number reads as a hero stat, not a labelled field.
.o_field_widget {
margin: 0;
padding: 0;
border: none;
background: transparent;
}

// Type stat shows the raw extension ("svg", "pdf") — render as the
// uppercase pill convention used in the kanban cards.
&--uppercase {
text-transform: uppercase;
letter-spacing: 0.02em;
}
}

&__stat_label {
font-size: 0.7rem;
text-transform: uppercase;
letter-spacing: 0.05em;
color: var(--bs-secondary-color, #6c757d);
}
}
229 changes: 135 additions & 94 deletions dms/views/dms_file.xml
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@
<field name="name">dms_file.form</field>
<field name="model">dms.file</field>
<field name="arch" type="xml">
<form string="Files">
<form string="Files" class="o_dms_form">
<header>
<button
class="oe_highlight"
Expand All @@ -354,7 +354,8 @@
/>
</header>
<sheet>
<!-- locked ribbon first, so that archived ribbon appear above if archived-->
<!-- locked ribbon first, so that archived ribbon appears
above if archived -->
<widget
name="web_ribbon"
title="Locked"
Expand All @@ -374,114 +375,154 @@
invisible="active"
/>
<div class="oe_button_box" name="button_box" />
<field
name="image_1920"
widget="image"
class="oe_avatar"
nolabel="1"
options="{'image_preview': 'image_128'}"
/>
<div class="oe_title">
<label for="name" class="oe_edit_only" />
<h1>
<field name="name" />
<field name="active" invisible="1" />
</h1>
<h4>

<!-- Hidden helper fields referenced by conditional
visibility expressions elsewhere in the form. -->
<field name="active" invisible="1" />
<field name="is_lock_editor" invisible="1" />
<field name="is_locked" invisible="1" />
<field name="storage_id_save_type" invisible="1" />

<!-- Hero block — mime-aware identity at the top. -->
<div class="o_dms_form_hero">
<div class="o_dms_form_hero__media">
<field
name="path_json"
widget="path_json"
options="{'prefix': True, 'suffix': False}"
invisible="not name or not directory_id"
name="image_1920"
widget="image"
class="o_dms_form_hero__image"
nolabel="1"
options="{'image_preview': 'image_128'}"
/>
</h4>
</div>
<div class="o_dms_form_hero__body">
<div class="o_dms_form_hero__title">
<label for="name" class="oe_edit_only" />
<h1>
<field name="name" />
</h1>
</div>
<div class="o_dms_form_hero__path text-muted small">
<field
name="path_json"
widget="path_json"
options="{'prefix': True, 'suffix': False}"
invisible="not name or not directory_id"
/>
</div>
<div class="o_dms_form_hero__tags">
<field
name="tag_ids"
widget="many2many_tags"
placeholder="Tags..."
options="{'color_field': 'color', 'no_create_edit': True}"
/>
</div>
<div class="o_dms_form_hero__stats">
<div class="o_dms_form_hero__stat">
<div class="o_dms_form_hero__stat_value">
<field name="human_size" readonly="1" />
</div>
<div class="o_dms_form_hero__stat_label">
Size
</div>
</div>
<div class="o_dms_form_hero__stat">
<div
class="o_dms_form_hero__stat_value o_dms_form_hero__stat_value--uppercase"
>
<field name="extension" readonly="1" />
</div>
<div class="o_dms_form_hero__stat_label">
Type
</div>
</div>
<div class="o_dms_form_hero__stat">
<div class="o_dms_form_hero__stat_value">
<field name="write_date" readonly="1" />
</div>
<div class="o_dms_form_hero__stat_label">
Modified
</div>
</div>
<div class="o_dms_form_hero__stat">
<div class="o_dms_form_hero__stat_value">
<field name="create_uid" readonly="1" />
</div>
<div class="o_dms_form_hero__stat_label">
Owner
</div>
</div>
</div>
</div>
</div>
<group name="content">
<group>
<field name="content" filename="name" />
</group>
<group>
<field name="extension" />
<field name="mimetype" />
</group>
</group>
<group name="settings">
<group>
<field
name="directory_id"
options="{'no_quick_create': True}"
/>
<field
name="storage_id"
options="{'no_open': True}"
groups="!dms.group_dms_manager"
/>
<field name="storage_id" groups="dms.group_dms_manager" />
</group>
<group>
<field
name="category_id"
placeholder="Internal / Human Resource"
options="{'no_open': True, 'no_create': True}"
/>
<field
name="tag_ids"
widget="many2many_tags"
placeholder="Tags..."
options="{'color_field': 'color', 'no_create_edit': True}"
/>
</group>
</group>
<group>
<field name="storage_id_save_type" invisible="True" />
<field
name="res_model"
readonly="True"
invisible="storage_id_save_type != 'attachment'"
/>
<field
name="res_id"
readonly="True"
invisible="storage_id_save_type != 'attachment'"
/>
<field
name="record_ref"
invisible="storage_id_save_type != 'attachment'"
/>
</group>

<!-- Condensed notebook — Content + Metadata replace the
upstream form's loose-fields + 3-page notebook. -->
<notebook>
<page name="page_meta" string="Meta Information">
<page name="page_content" string="Content">
<group>
<group>
<field name="create_date" readonly="1" />
<field name="create_uid" readonly="1" />
</group>
<group>
<field name="write_date" readonly="1" />
<field name="write_uid" readonly="1" />
</group>
<field name="content" filename="name" nolabel="1" />
</group>
<group
string="Attachment storage"
invisible="storage_id_save_type != 'attachment'"
>
<field name="res_model" readonly="1" />
<field name="res_id" readonly="1" />
<field name="record_ref" />
</group>
</page>
<page name="page_access" string="Access Information">
<page name="page_metadata" string="Metadata">
<group>
<group string="Location">
<field
name="directory_id"
options="{'no_quick_create': True}"
/>
<field
name="storage_id"
options="{'no_open': True}"
groups="!dms.group_dms_manager"
/>
<field
name="storage_id"
groups="dms.group_dms_manager"
/>
<field name="mimetype" readonly="1" />
</group>
<group string="Categorisation">
<field
name="category_id"
placeholder="Internal / Human Resource"
options="{'no_open': True, 'no_create': True}"
/>
</group>
</group>
<group string="Permissions">
<group>
<field name="permission_write" readonly="1" />
<field name="permission_unlink" readonly="1" />
</group>
<group>
<field name="is_lock_editor" invisible="1" />
<field name="is_locked" invisible="1" />
<field name="locked_by" />
</group>
</group>
</page>
<page
name="page_technical"
string="Technical Information"
invisible="1"
groups="dms.group_dms_manager,base.group_no_one"
>
<group name="technical">
<group string="Audit">
<group>
<field name="create_date" readonly="1" />
<field name="create_uid" readonly="1" />
</group>
<group>
<field name="write_date" readonly="1" />
<field name="write_uid" readonly="1" />
</group>
</group>
<group
name="technical"
string="Technical"
invisible="1"
groups="dms.group_dms_manager,base.group_no_one"
>
<group name="technical_left" />
<group name="technical_right" />
</group>
Expand Down
Loading