feat(fusion_plating_shopfloor): GateViz shared OWL service
Plan task P1.4. "Can't start yet — Waiting on Step N: X" block reused across JobWorkspace step rows and Manager Plant Board cards. Icon set maps to blocker_kind (predecessor/contract_review/parts_not_received/ racking_required/manager_input). Optional Jump button propagates to parent via onJump callback. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -68,6 +68,9 @@ Copyright (c) 2026 Nexa Systems Inc. All rights reserved.
|
|||||||
'fusion_plating_shopfloor/static/src/scss/components/_workflow_chip.scss',
|
'fusion_plating_shopfloor/static/src/scss/components/_workflow_chip.scss',
|
||||||
'fusion_plating_shopfloor/static/src/xml/components/workflow_chip.xml',
|
'fusion_plating_shopfloor/static/src/xml/components/workflow_chip.xml',
|
||||||
'fusion_plating_shopfloor/static/src/js/components/workflow_chip.js',
|
'fusion_plating_shopfloor/static/src/js/components/workflow_chip.js',
|
||||||
|
'fusion_plating_shopfloor/static/src/scss/components/_gate_viz.scss',
|
||||||
|
'fusion_plating_shopfloor/static/src/xml/components/gate_viz.xml',
|
||||||
|
'fusion_plating_shopfloor/static/src/js/components/gate_viz.js',
|
||||||
'fusion_plating_shopfloor/static/src/scss/qr_scanner.scss',
|
'fusion_plating_shopfloor/static/src/scss/qr_scanner.scss',
|
||||||
'fusion_plating_shopfloor/static/src/scss/fusion_plating_shopfloor.scss',
|
'fusion_plating_shopfloor/static/src/scss/fusion_plating_shopfloor.scss',
|
||||||
'fusion_plating_shopfloor/static/src/scss/plant_overview.scss',
|
'fusion_plating_shopfloor/static/src/scss/plant_overview.scss',
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
/** @odoo-module **/
|
||||||
|
// =============================================================================
|
||||||
|
// Fusion Plating — GateViz (shared OWL service)
|
||||||
|
//
|
||||||
|
// "Can't start because…" explainer for fp.job.step blockers. Drives off
|
||||||
|
// step.blocker_kind/reason from the backend compute. Used in:
|
||||||
|
// • JobWorkspace step rows (inline)
|
||||||
|
// • Manager Plant Board "Needs Worker" cards (badge form)
|
||||||
|
//
|
||||||
|
// Props:
|
||||||
|
// canStart : Boolean — when true, renders nothing
|
||||||
|
// blockerKind : String — predecessor/contract_review/
|
||||||
|
// parts_not_received/racking_required/
|
||||||
|
// manager_input/other
|
||||||
|
// blockerReason : String — human-readable explanation
|
||||||
|
// jumpTargetModel : String — optional model name for tap-to-jump
|
||||||
|
// jumpTargetId : Number — optional record id for tap-to-jump
|
||||||
|
// onJump : Function — called with {model, id} on Jump click
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
import { Component } from "@odoo/owl";
|
||||||
|
|
||||||
|
export class GateViz extends Component {
|
||||||
|
static template = "fusion_plating_shopfloor.GateViz";
|
||||||
|
static props = {
|
||||||
|
canStart: { type: Boolean, optional: false },
|
||||||
|
blockerKind: { type: String, optional: true },
|
||||||
|
blockerReason: { type: String, optional: true },
|
||||||
|
jumpTargetModel: { type: String, optional: true },
|
||||||
|
jumpTargetId: { type: Number, optional: true },
|
||||||
|
onJump: { type: Function, optional: true },
|
||||||
|
};
|
||||||
|
|
||||||
|
get iconClass() {
|
||||||
|
const map = {
|
||||||
|
predecessor: "fa-lock",
|
||||||
|
contract_review: "fa-file-text-o",
|
||||||
|
parts_not_received: "fa-truck",
|
||||||
|
racking_required: "fa-th-large",
|
||||||
|
manager_input: "fa-user-md",
|
||||||
|
};
|
||||||
|
return map[this.props.blockerKind] || "fa-pause-circle";
|
||||||
|
}
|
||||||
|
|
||||||
|
onJumpClick() {
|
||||||
|
if (this.props.onJump && this.props.jumpTargetModel && this.props.jumpTargetId) {
|
||||||
|
this.props.onJump({
|
||||||
|
model: this.props.jumpTargetModel,
|
||||||
|
id: this.props.jumpTargetId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
// =============================================================================
|
||||||
|
// GateViz — "this step can't start because..." explainer
|
||||||
|
// Dark-mode aware via $o-webclient-color-scheme branch.
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
$o-webclient-color-scheme: bright !default;
|
||||||
|
|
||||||
|
$_gate-bg-hex: rgba(255, 159, 10, 0.10);
|
||||||
|
$_gate-border-hex: #ff9f0a;
|
||||||
|
$_gate-text-hex: #b06600;
|
||||||
|
|
||||||
|
@if $o-webclient-color-scheme == dark {
|
||||||
|
$_gate-text-hex: #ffb84d !global;
|
||||||
|
}
|
||||||
|
|
||||||
|
.o_fp_gate {
|
||||||
|
background: $_gate-bg-hex;
|
||||||
|
border-left: 3px solid $_gate-border-hex;
|
||||||
|
padding: 0.5rem 0.75rem;
|
||||||
|
border-radius: 0 6px 6px 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.o_fp_gate_icon { color: $_gate-border-hex; margin-top: 0.15rem; }
|
||||||
|
.o_fp_gate_body { flex: 1; }
|
||||||
|
.o_fp_gate_title { font-weight: 600; color: $_gate-text-hex; font-size: 0.85rem; }
|
||||||
|
.o_fp_gate_reason { color: var(--text-secondary, #666); font-size: 0.78rem; margin-top: 0.1rem; }
|
||||||
|
.o_fp_gate_jump { flex-shrink: 0; }
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<templates xml:space="preserve">
|
||||||
|
|
||||||
|
<t t-name="fusion_plating_shopfloor.GateViz">
|
||||||
|
<div class="o_fp_gate" t-if="!props.canStart">
|
||||||
|
<i t-att-class="'fa o_fp_gate_icon ' + iconClass"/>
|
||||||
|
<div class="o_fp_gate_body">
|
||||||
|
<div class="o_fp_gate_title">Can't start yet</div>
|
||||||
|
<div class="o_fp_gate_reason">
|
||||||
|
<t t-esc="props.blockerReason or 'Reason unknown — open the step in the back-office.'"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button t-if="props.jumpTargetModel and props.jumpTargetId and props.onJump"
|
||||||
|
class="btn btn-sm btn-outline-warning o_fp_gate_jump"
|
||||||
|
t-on-click="onJumpClick">
|
||||||
|
Jump <i class="fa fa-arrow-right"/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</t>
|
||||||
|
|
||||||
|
</templates>
|
||||||
Reference in New Issue
Block a user