fix(configurator): Part cell row 1 shows part# / rev separately via CSS overlay
Root cause: my @api.depends_context('fp_express_part_picker') decorator
on _compute_display_name was not honored by Odoo. Verified via odoo
shell — display_name returns the full 'PART (Rev X) — Name' regardless
of context. Reason: display_name is defined on the base Model class
and Odoo registers the field metadata (incl. _depends_context) when
the field is FIRST declared. Subclass redefinitions of the compute
method don't update _depends_context after the fact.
Workaround: don't rely on display_name context override. Instead,
overlay a custom span on top of the Many2OneField that shows JUST
the part_number_display value. CSS overlay uses:
- position: absolute / inset: 0
- background: $xpr-card (matches list row background)
- z-index: 2 over the picker
- pointer-events: none so clicks pass through to the picker
When the picker is focused (:focus-within parent), the overlay
hides so the user sees the autocomplete input value as they type.
When not focused, the overlay covers display_name with just the
part number.
Row 1 now reads 'ENG-1042 / B' — picker on the left (showing only
part_number_display), separator, revision on the right. Matches the
mockup pixel layout the user requested.
This commit is contained in:
@@ -34,6 +34,14 @@ export class FpExpressPartCell extends Component {
|
||||
return !!this.props.record.data.part_catalog_id;
|
||||
}
|
||||
|
||||
get partNumber() {
|
||||
return this.props.record.data.part_number_display || "";
|
||||
}
|
||||
|
||||
get partRev() {
|
||||
return this.props.record.data.part_revision_display || "";
|
||||
}
|
||||
|
||||
get partName() {
|
||||
return this.props.record.data.part_name_editable || "";
|
||||
}
|
||||
|
||||
@@ -547,11 +547,20 @@
|
||||
.o_fp_xpr_part_id {
|
||||
font-weight: 600;
|
||||
font-size: 13px;
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 4px;
|
||||
|
||||
// The embedded Many2OneField input — strip its chrome so it
|
||||
// looks like inline-bold text. Restore the dropdown affordance
|
||||
// on hover/focus.
|
||||
// The picker + overlay container
|
||||
.o_fp_xpr_part_picker_wrap {
|
||||
position: relative;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
// Strip Many2OneField chrome to inline-bold-text
|
||||
.o_field_widget,
|
||||
.o_field_widget > div,
|
||||
.o_field_widget input,
|
||||
.o_field_many2one input {
|
||||
border: none;
|
||||
@@ -559,21 +568,48 @@
|
||||
padding: 1px 4px;
|
||||
font-weight: 600;
|
||||
font-size: 13px;
|
||||
color: $xpr-text;
|
||||
color: $xpr-accent;
|
||||
width: 100%;
|
||||
}
|
||||
.o_field_widget input:focus {
|
||||
background: $xpr-cell-focus;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
// OVERLAY — shown when picker not focused; hides display_name
|
||||
// and shows just part_number_display
|
||||
.o_fp_xpr_part_num_overlay {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: $xpr-card;
|
||||
z-index: 2;
|
||||
pointer-events: none;
|
||||
padding: 1px 4px;
|
||||
font-weight: 600;
|
||||
font-size: 13px;
|
||||
color: $xpr-accent;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
// Hide overlay when picker is focused (user is typing/searching)
|
||||
.o_fp_xpr_part_picker_wrap:focus-within .o_fp_xpr_part_num_overlay {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.o_fp_xpr_part_sep {
|
||||
color: $xpr-text-dim;
|
||||
font-weight: 400;
|
||||
padding: 0 2px;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
.o_fp_xpr_part_rev {
|
||||
font-weight: 600;
|
||||
color: $xpr-text;
|
||||
min-width: 30px;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
.o_fp_xpr_part_rev_empty {
|
||||
color: $xpr-text-dim;
|
||||
@@ -581,6 +617,10 @@
|
||||
font-style: italic;
|
||||
}
|
||||
}
|
||||
// Overlay background matches the row hover state
|
||||
.o_list_view tbody tr:hover & .o_fp_xpr_part_num_overlay {
|
||||
background: $xpr-row-hover;
|
||||
}
|
||||
.o_fp_xpr_part_name {
|
||||
.o_fp_xpr_part_name_input {
|
||||
width: 100%;
|
||||
|
||||
@@ -11,9 +11,20 @@
|
||||
-->
|
||||
<t t-name="fusion_plating_configurator.FpExpressPartCell">
|
||||
<div class="o_fp_xpr_part_cell">
|
||||
<!-- Row 1 — Part picker -->
|
||||
<!-- Row 1 — Part picker (left, with part-number overlay) + / + Revision (right)
|
||||
The overlay shows JUST the part_number_display when not focused;
|
||||
on focus, the overlay hides so the user sees the autocomplete input. -->
|
||||
<div class="o_fp_xpr_part_row o_fp_xpr_part_id">
|
||||
<Many2OneField t-props="props"/>
|
||||
<div class="o_fp_xpr_part_picker_wrap">
|
||||
<Many2OneField t-props="props"/>
|
||||
<span t-if="hasPart"
|
||||
class="o_fp_xpr_part_num_overlay"
|
||||
t-esc="partNumber"/>
|
||||
</div>
|
||||
<span class="o_fp_xpr_part_sep">/</span>
|
||||
<span class="o_fp_xpr_part_rev"
|
||||
t-att-class="{ 'o_fp_xpr_part_rev_empty': !partRev }"
|
||||
t-esc="partRev or 'rev'"/>
|
||||
</div>
|
||||
<!-- Row 2 — Editable part description (saves to part.name) -->
|
||||
<div class="o_fp_xpr_part_row o_fp_xpr_part_name">
|
||||
|
||||
Reference in New Issue
Block a user