feat(fusion_plating_shopfloor): workspace sign-off confirms saved signature, draws only when absent
onFinishStep: if the user has a saved Plating Signature, show FpSignatureConfirm (one-tap, preview); otherwise open the draw-pad. Factored _openSignaturePad + _commitSignOff (sends null data URI when using the saved signature). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -25,6 +25,7 @@ import { useService } from "@web/core/utils/hooks";
|
|||||||
import { WorkflowChip } from "./components/workflow_chip";
|
import { WorkflowChip } from "./components/workflow_chip";
|
||||||
import { GateViz } from "./components/gate_viz";
|
import { GateViz } from "./components/gate_viz";
|
||||||
import { FpSignaturePad } from "./components/signature_pad";
|
import { FpSignaturePad } from "./components/signature_pad";
|
||||||
|
import { FpSignatureConfirm } from "./components/signature_confirm";
|
||||||
import { FpHoldComposer } from "./components/hold_composer";
|
import { FpHoldComposer } from "./components/hold_composer";
|
||||||
import { FpTabletLock } from "./tablet_lock";
|
import { FpTabletLock } from "./tablet_lock";
|
||||||
import { FpRackPartsDialog } from "./rack_parts_dialog";
|
import { FpRackPartsDialog } from "./rack_parts_dialog";
|
||||||
@@ -38,7 +39,7 @@ import { FileModel } from "@web/core/file_viewer/file_model";
|
|||||||
export class FpJobWorkspace extends Component {
|
export class FpJobWorkspace extends Component {
|
||||||
static template = "fusion_plating_shopfloor.JobWorkspace";
|
static template = "fusion_plating_shopfloor.JobWorkspace";
|
||||||
static props = ["*"];
|
static props = ["*"];
|
||||||
static components = { WorkflowChip, GateViz, FpSignaturePad, FpHoldComposer, FpTabletLock, FpRackPartsDialog, FpDamageDialog, FpFinishBlockDialog, RackingPanel, FpMovePartsDialog };
|
static components = { WorkflowChip, GateViz, FpSignaturePad, FpSignatureConfirm, FpHoldComposer, FpTabletLock, FpRackPartsDialog, FpDamageDialog, FpFinishBlockDialog, RackingPanel, FpMovePartsDialog };
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
this.notification = useService("notification");
|
this.notification = useService("notification");
|
||||||
@@ -363,26 +364,20 @@ export class FpJobWorkspace extends Component {
|
|||||||
|
|
||||||
async onFinishStep(step) {
|
async onFinishStep(step) {
|
||||||
if (step.requires_signoff) {
|
if (step.requires_signoff) {
|
||||||
this.dialog.add(FpSignaturePad, {
|
if (this.state.data.user_has_plating_signature) {
|
||||||
title: `Sign to finish ${step.name}`,
|
// One-tap confirm with a preview of the saved Plating Signature.
|
||||||
contextLabel: `${this.state.data.job.display_wo_name} · Step ${step.sequence_display}: ${step.name}`,
|
this.dialog.add(FpSignatureConfirm, {
|
||||||
onSubmit: async (dataUri) => {
|
title: `Sign to finish ${step.name}`,
|
||||||
try {
|
contextLabel: `${this.state.data.job.display_wo_name} · Step ${step.sequence_display}: ${step.name}`,
|
||||||
const res = await fpRpc("/fp/workspace/sign_off", {
|
signatureUrl: this.state.data.user_plating_signature,
|
||||||
step_id: step.id,
|
onConfirm: () => this._commitSignOff(step, null), // use saved sig
|
||||||
signature_data_uri: dataUri,
|
onRedraw: () => this._openSignaturePad(step), // draw a new one
|
||||||
});
|
});
|
||||||
if (res && res.ok) {
|
} else {
|
||||||
this.notification.add("Step signed off and finished.", { type: "success" });
|
// First time — draw once; the backend persists it to the
|
||||||
await this.refresh();
|
// user's Plating Signature so later sign-offs are one-tap.
|
||||||
} else {
|
this._openSignaturePad(step);
|
||||||
this.notification.add((res && res.error) || "Sign-off failed", { type: "danger" });
|
}
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
this.notification.add(err.message, { type: "danger" });
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Plain finish — route through /fp/workspace/finish_step which
|
// Plain finish — route through /fp/workspace/finish_step which
|
||||||
@@ -391,6 +386,31 @@ export class FpJobWorkspace extends Component {
|
|||||||
await this._callFinishStep(step, /* bypass */ false);
|
await this._callFinishStep(step, /* bypass */ false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_openSignaturePad(step) {
|
||||||
|
this.dialog.add(FpSignaturePad, {
|
||||||
|
title: `Sign to finish ${step.name}`,
|
||||||
|
contextLabel: `${this.state.data.job.display_wo_name} · Step ${step.sequence_display}: ${step.name}`,
|
||||||
|
onSubmit: (dataUri) => this._commitSignOff(step, dataUri),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async _commitSignOff(step, dataUri) {
|
||||||
|
try {
|
||||||
|
const res = await fpRpc("/fp/workspace/sign_off", {
|
||||||
|
step_id: step.id,
|
||||||
|
signature_data_uri: dataUri, // null -> backend uses the saved signature
|
||||||
|
});
|
||||||
|
if (res && res.ok) {
|
||||||
|
this.notification.add("Step signed off and finished.", { type: "success" });
|
||||||
|
await this.refresh();
|
||||||
|
} else {
|
||||||
|
this.notification.add((res && res.error) || "Sign-off failed", { type: "danger" });
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
this.notification.add(err.message, { type: "danger" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async _callFinishStep(step, bypassRequiredInputs) {
|
async _callFinishStep(step, bypassRequiredInputs) {
|
||||||
try {
|
try {
|
||||||
const res = await rpc("/fp/workspace/finish_step", {
|
const res = await rpc("/fp/workspace/finish_step", {
|
||||||
|
|||||||
Reference in New Issue
Block a user