fix(certs): auto-edit first row in Issue Certs wizard so upload is visible
Previous attempt (e5928b96) used CSS to force the binary widget's
"Upload your file" button visible in display mode. Problem: it
rendered a non-clickable stub in every row, then DUPLICATED when
the operator clicked into edit mode (two upload links stacked).
Drop the SCSS hack entirely. Replace with a custom form-view
controller that auto-edits the first incomplete row on mount.
When the wizard opens, the JS:
1. Scopes itself via the form's o_fp_cert_issue_wizard_form class
(no-ops on every other form view in the system).
2. Finds rows where the is_ready toggle is False.
3. Clicks the fischer_file cell of the first such row.
4. The row enters edit mode → Odoo's native binary widget renders
its upload button → operator drops the file → onchange fires
→ readings parse.
Wired via js_class="fp_cert_issue_wizard_form" on the form root.
Banner copy updated to "Click a row, then click Upload your file in
the Fischerscope column" so even if the auto-edit fails for some
DOM reason, the operator knows the click path.
Module: fusion_plating_jobs 19.0.10.16.1 → 19.0.10.16.2.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -3,7 +3,7 @@
|
|||||||
# License OPL-1 (Odoo Proprietary License v1.0)
|
# License OPL-1 (Odoo Proprietary License v1.0)
|
||||||
{
|
{
|
||||||
'name': 'Fusion Plating — Native Jobs',
|
'name': 'Fusion Plating — Native Jobs',
|
||||||
'version': '19.0.10.16.1',
|
'version': '19.0.10.16.2',
|
||||||
'category': 'Manufacturing/Plating',
|
'category': 'Manufacturing/Plating',
|
||||||
'summary': 'Native plating job model — replaces mrp.production / mrp.workorder bridge.',
|
'summary': 'Native plating job model — replaces mrp.production / mrp.workorder bridge.',
|
||||||
'author': 'Nexa Systems Inc.',
|
'author': 'Nexa Systems Inc.',
|
||||||
@@ -87,16 +87,16 @@ full design rationale and §6.2 of the implementation plan for task list.
|
|||||||
'fusion_plating_jobs/static/src/scss/fp_step_quick_look.scss',
|
'fusion_plating_jobs/static/src/scss/fp_step_quick_look.scss',
|
||||||
'fusion_plating_jobs/static/src/scss/fp_record_inputs_dialog.scss',
|
'fusion_plating_jobs/static/src/scss/fp_record_inputs_dialog.scss',
|
||||||
'fusion_plating_jobs/static/src/scss/fp_finish_btn.scss',
|
'fusion_plating_jobs/static/src/scss/fp_finish_btn.scss',
|
||||||
'fusion_plating_jobs/static/src/scss/fp_cert_issue_wizard.scss',
|
|
||||||
'fusion_plating_jobs/static/src/js/fp_record_inputs_dialog.js',
|
'fusion_plating_jobs/static/src/js/fp_record_inputs_dialog.js',
|
||||||
|
'fusion_plating_jobs/static/src/js/fp_cert_issue_wizard_autoedit.js',
|
||||||
'fusion_plating_jobs/static/src/xml/fp_record_inputs_dialog.xml',
|
'fusion_plating_jobs/static/src/xml/fp_record_inputs_dialog.xml',
|
||||||
],
|
],
|
||||||
'web.assets_web_dark': [
|
'web.assets_web_dark': [
|
||||||
'fusion_plating_jobs/static/src/scss/fp_step_quick_look.scss',
|
'fusion_plating_jobs/static/src/scss/fp_step_quick_look.scss',
|
||||||
'fusion_plating_jobs/static/src/scss/fp_record_inputs_dialog.scss',
|
'fusion_plating_jobs/static/src/scss/fp_record_inputs_dialog.scss',
|
||||||
'fusion_plating_jobs/static/src/scss/fp_finish_btn.scss',
|
'fusion_plating_jobs/static/src/scss/fp_finish_btn.scss',
|
||||||
'fusion_plating_jobs/static/src/scss/fp_cert_issue_wizard.scss',
|
|
||||||
'fusion_plating_jobs/static/src/js/fp_record_inputs_dialog.js',
|
'fusion_plating_jobs/static/src/js/fp_record_inputs_dialog.js',
|
||||||
|
'fusion_plating_jobs/static/src/js/fp_cert_issue_wizard_autoedit.js',
|
||||||
'fusion_plating_jobs/static/src/xml/fp_record_inputs_dialog.xml',
|
'fusion_plating_jobs/static/src/xml/fp_record_inputs_dialog.xml',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,86 @@
|
|||||||
|
/** @odoo-module **/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fusion Plating — Issue Certs wizard: auto-edit the first incomplete row
|
||||||
|
* on wizard mount.
|
||||||
|
*
|
||||||
|
* Background: Odoo's editable o2m list keeps non-selected rows in display
|
||||||
|
* mode, which hides the binary widget's "↑ Upload your file" link until
|
||||||
|
* the operator clicks the row. Operators reported the wizard as broken
|
||||||
|
* because the file field appeared empty.
|
||||||
|
*
|
||||||
|
* Fix without fighting CSS: when the wizard's list renders, simulate a
|
||||||
|
* click on the first row that still needs thickness data. The native
|
||||||
|
* binary widget then renders in edit mode and the upload link is
|
||||||
|
* immediately visible — no theme override needed.
|
||||||
|
*
|
||||||
|
* Scoped to `.o_fp_cert_issue_wizard_form` (the wizard form's
|
||||||
|
* css_class) so this DOM-poke doesn't fire on other editable o2m lists.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { registry } from "@web/core/registry";
|
||||||
|
import { formView } from "@web/views/form/form_view";
|
||||||
|
import { FormController } from "@web/views/form/form_controller";
|
||||||
|
import { onMounted } from "@odoo/owl";
|
||||||
|
|
||||||
|
|
||||||
|
export class FpCertIssueWizardFormController extends FormController {
|
||||||
|
setup() {
|
||||||
|
super.setup(...arguments);
|
||||||
|
onMounted(() => {
|
||||||
|
// Defer one tick so the o2m list has finished its first paint.
|
||||||
|
requestAnimationFrame(() => this._fpAutoEditFirstRow());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_fpAutoEditFirstRow() {
|
||||||
|
// Only fire on the cert-issue wizard. Other form views that use
|
||||||
|
// the same FormController class get the default behaviour.
|
||||||
|
const root = this.rootRef && this.rootRef.el;
|
||||||
|
if (!root || !root.classList.contains("o_fp_cert_issue_wizard_form")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// First row that backs a line where is_ready is False (the data
|
||||||
|
// toggle column renders as `false`). Fallback: the very first
|
||||||
|
// data row.
|
||||||
|
const dataRows = root.querySelectorAll(
|
||||||
|
".o_field_one2many[name='line_ids'] .o_list_renderer .o_data_row"
|
||||||
|
);
|
||||||
|
if (!dataRows.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let target = null;
|
||||||
|
for (const row of dataRows) {
|
||||||
|
// Look for an unchecked is_ready toggle inside the row. If
|
||||||
|
// we find one, that row needs attention.
|
||||||
|
const readyToggle = row.querySelector(
|
||||||
|
"[name='is_ready'] input[type='checkbox']"
|
||||||
|
);
|
||||||
|
if (readyToggle && !readyToggle.checked) {
|
||||||
|
target = row;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!target) {
|
||||||
|
target = dataRows[0];
|
||||||
|
}
|
||||||
|
// Find the fischer_file cell specifically — clicking THAT cell
|
||||||
|
// (not just any cell) puts the row in edit mode AND focuses the
|
||||||
|
// upload widget, so the native "Upload your file" link is the
|
||||||
|
// very first thing the operator sees.
|
||||||
|
const fischerCell = target.querySelector("[name='fischer_file']");
|
||||||
|
if (fischerCell) {
|
||||||
|
fischerCell.click();
|
||||||
|
} else {
|
||||||
|
// Fallback: click the row anywhere, then the upload column
|
||||||
|
// shows up in the now-active row.
|
||||||
|
target.click();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
registry.category("views").add("fp_cert_issue_wizard_form", {
|
||||||
|
...formView,
|
||||||
|
Controller: FpCertIssueWizardFormController,
|
||||||
|
});
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
// =============================================================
|
|
||||||
// Fusion Plating — Issue Certs wizard styling
|
|
||||||
// =============================================================
|
|
||||||
//
|
|
||||||
// 2026-05-20: force the Fischerscope binary-field upload button to
|
|
||||||
// be visible in display mode (not just when the row is being edited).
|
|
||||||
// Odoo's default `widget="binary"` only shows "↑ Upload your file"
|
|
||||||
// when the row is in edit mode — operators couldn't see what to
|
|
||||||
// click in the wizard list and reported it as a missing affordance.
|
|
||||||
//
|
|
||||||
// Targets ONLY the fischer_file column in this wizard so it doesn't
|
|
||||||
// affect binary fields elsewhere in the system.
|
|
||||||
|
|
||||||
.o_form_view {
|
|
||||||
.o_field_one2many[name="line_ids"] {
|
|
||||||
// List renderer — affect every binary cell that backs
|
|
||||||
// fischer_file. We can't always target by name attribute
|
|
||||||
// (Odoo 19 doesn't put `name=` on the <td>), so use the
|
|
||||||
// child field widget binding.
|
|
||||||
.o_list_renderer .o_data_cell {
|
|
||||||
.o_field_widget.o_field_binary {
|
|
||||||
// Always show the upload button, even on rows that
|
|
||||||
// aren't currently being edited. The default theme
|
|
||||||
// hides it on non-selected rows.
|
|
||||||
.o_select_file_button {
|
|
||||||
display: inline-flex !important;
|
|
||||||
align-items: center;
|
|
||||||
gap: .25rem;
|
|
||||||
color: var(--primary, #5d83a4);
|
|
||||||
text-decoration: underline dotted;
|
|
||||||
background: transparent;
|
|
||||||
border: 0;
|
|
||||||
padding: .15rem .35rem;
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: .85rem;
|
|
||||||
// Add an upward-arrow + label so it reads as an
|
|
||||||
// action even if Odoo's stock label text changes.
|
|
||||||
&::before {
|
|
||||||
content: "\f093"; // fa-upload (FontAwesome 4)
|
|
||||||
font-family: "FontAwesome";
|
|
||||||
margin-right: .25rem;
|
|
||||||
}
|
|
||||||
&:hover {
|
|
||||||
color: var(--primary-hover, #4a6f8e);
|
|
||||||
background: rgba(93, 131, 164, .08);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Empty cell shouldn't collapse to 0 height — give it
|
|
||||||
// a clickable target area.
|
|
||||||
min-height: 28px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -9,7 +9,9 @@
|
|||||||
<field name="name">fp.cert.issue.wizard.form</field>
|
<field name="name">fp.cert.issue.wizard.form</field>
|
||||||
<field name="model">fp.cert.issue.wizard</field>
|
<field name="model">fp.cert.issue.wizard</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<form string="Issue Certs">
|
<form string="Issue Certs"
|
||||||
|
js_class="fp_cert_issue_wizard_form"
|
||||||
|
class="o_fp_cert_issue_wizard_form">
|
||||||
<sheet>
|
<sheet>
|
||||||
<div class="oe_title">
|
<div class="oe_title">
|
||||||
<h2>
|
<h2>
|
||||||
@@ -19,10 +21,12 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="alert alert-info" role="alert"
|
<div class="alert alert-info" role="alert"
|
||||||
invisible="not has_blocking_lines">
|
invisible="not has_blocking_lines">
|
||||||
<i class="fa fa-info-circle"/>
|
<i class="fa fa-info-circle me-1"/>
|
||||||
At least one cert still needs thickness data
|
At least one cert still needs thickness data
|
||||||
(Fischerscope file or readings). Fill it in
|
(Fischerscope file or readings).
|
||||||
below before confirming.
|
<strong>Click a row, then click
|
||||||
|
<em>Upload your file</em> in the Fischerscope
|
||||||
|
column.</strong>
|
||||||
</div>
|
</div>
|
||||||
<!-- 2026-05-20: surface the file upload INLINE in the
|
<!-- 2026-05-20: surface the file upload INLINE in the
|
||||||
list instead of behind a row-click into a sub-form.
|
list instead of behind a row-click into a sub-form.
|
||||||
|
|||||||
Reference in New Issue
Block a user