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;
|
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() {
|
get partName() {
|
||||||
return this.props.record.data.part_name_editable || "";
|
return this.props.record.data.part_name_editable || "";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -547,11 +547,20 @@
|
|||||||
.o_fp_xpr_part_id {
|
.o_fp_xpr_part_id {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
gap: 4px;
|
||||||
|
|
||||||
// The embedded Many2OneField input — strip its chrome so it
|
// The picker + overlay container
|
||||||
// looks like inline-bold text. Restore the dropdown affordance
|
.o_fp_xpr_part_picker_wrap {
|
||||||
// on hover/focus.
|
position: relative;
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Strip Many2OneField chrome to inline-bold-text
|
||||||
.o_field_widget,
|
.o_field_widget,
|
||||||
|
.o_field_widget > div,
|
||||||
.o_field_widget input,
|
.o_field_widget input,
|
||||||
.o_field_many2one input {
|
.o_field_many2one input {
|
||||||
border: none;
|
border: none;
|
||||||
@@ -559,21 +568,48 @@
|
|||||||
padding: 1px 4px;
|
padding: 1px 4px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
color: $xpr-text;
|
color: $xpr-accent;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
.o_field_widget input:focus {
|
.o_field_widget input:focus {
|
||||||
background: $xpr-cell-focus;
|
background: $xpr-cell-focus;
|
||||||
outline: none;
|
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 {
|
.o_fp_xpr_part_sep {
|
||||||
color: $xpr-text-dim;
|
color: $xpr-text-dim;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
padding: 0 2px;
|
padding: 0 2px;
|
||||||
|
flex: 0 0 auto;
|
||||||
}
|
}
|
||||||
.o_fp_xpr_part_rev {
|
.o_fp_xpr_part_rev {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: $xpr-text;
|
color: $xpr-text;
|
||||||
min-width: 30px;
|
min-width: 30px;
|
||||||
|
flex: 0 0 auto;
|
||||||
}
|
}
|
||||||
.o_fp_xpr_part_rev_empty {
|
.o_fp_xpr_part_rev_empty {
|
||||||
color: $xpr-text-dim;
|
color: $xpr-text-dim;
|
||||||
@@ -581,6 +617,10 @@
|
|||||||
font-style: italic;
|
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 {
|
||||||
.o_fp_xpr_part_name_input {
|
.o_fp_xpr_part_name_input {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|||||||
@@ -11,9 +11,20 @@
|
|||||||
-->
|
-->
|
||||||
<t t-name="fusion_plating_configurator.FpExpressPartCell">
|
<t t-name="fusion_plating_configurator.FpExpressPartCell">
|
||||||
<div class="o_fp_xpr_part_cell">
|
<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">
|
<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>
|
</div>
|
||||||
<!-- Row 2 — Editable part description (saves to part.name) -->
|
<!-- Row 2 — Editable part description (saves to part.name) -->
|
||||||
<div class="o_fp_xpr_part_row o_fp_xpr_part_name">
|
<div class="o_fp_xpr_part_row o_fp_xpr_part_name">
|
||||||
|
|||||||
Reference in New Issue
Block a user