推进 INI 面板 session snapshot workflow helper
This commit is contained in:
@@ -8,6 +8,9 @@ for summarizing machine session snapshot state.
|
||||
for machine-session load state. These helpers are pure so browser UI panels,
|
||||
SDK-facing wrappers, and Node smoke tests can share the same data shape without
|
||||
parsing log text.
|
||||
`runtime/ui/ini-panel/session-workflow.js` contains the reusable UI workflow for
|
||||
saving the machine text files, default G-code, and machine session snapshot as
|
||||
one host-boundary operation.
|
||||
|
||||
The helpers do not implement CNC behavior. G-code execution, canonical events,
|
||||
tool handling, parameters, kinematics, and planner behavior remain owned by the
|
||||
@@ -53,6 +56,42 @@ The returned summary has this shape:
|
||||
}
|
||||
```
|
||||
|
||||
## `saveMachineSessionSnapshotWorkflow(input)`
|
||||
|
||||
The workflow writes the current INI/tool/parameter text files, writes the
|
||||
default G-code program, saves the machine session snapshot, and returns the
|
||||
snapshot summary, field state, and log lines for UI consumers.
|
||||
|
||||
The persistence functions are injected by the caller:
|
||||
|
||||
```js
|
||||
{
|
||||
saveMachineTextFiles,
|
||||
saveGcodeProgram,
|
||||
saveMachineSessionSnapshot
|
||||
}
|
||||
```
|
||||
|
||||
The returned object has this shape:
|
||||
|
||||
```js
|
||||
{
|
||||
snapshot: { ... },
|
||||
summary: { snapshotLabel: "...", workflow: "save-session-snapshot" },
|
||||
fields: {
|
||||
sessionIni: "linuxcnc/machines/xyzab-tdr/machine.ini",
|
||||
sessionParameters: "linuxcnc/machines/xyzab-tdr/linuxcnc.var",
|
||||
sessionToolTable: "linuxcnc/machines/xyzab-tdr/tool.tbl",
|
||||
sessionGcode: "linuxcnc/gcode/ui-session.ngc",
|
||||
sessionSnapshot: "ui-machine-session/ui-machine-session.json"
|
||||
},
|
||||
logLines: [
|
||||
"Snapshot: ui-machine-session/ui-machine-session.json",
|
||||
"Workflow: save-session-snapshot"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Log Helpers
|
||||
|
||||
- `sessionSnapshotSummaryLogLines(summary)` renders snapshot label, workflow,
|
||||
@@ -61,6 +100,8 @@ The returned summary has this shape:
|
||||
save/restore log summaries.
|
||||
- `machineSessionLoadLogLines(summary)` renders the interpreter/session
|
||||
OPFS-to-WASM mapping and captured result lines.
|
||||
- `sessionSnapshotSaveLogLines(summary)` renders the save-workflow snapshot
|
||||
paths used by the INI panel.
|
||||
|
||||
## Boundary Rules
|
||||
|
||||
@@ -76,6 +117,7 @@ Run the focused Node smoke after changing these helpers:
|
||||
|
||||
```bash
|
||||
wasm-port/tests/ui/node/verify_ini_panel_session_summary.sh
|
||||
wasm-port/tests/ui/node/verify_ini_panel_session_workflow.sh
|
||||
```
|
||||
|
||||
The aggregate UI Node smoke is:
|
||||
|
||||
@@ -41,6 +41,9 @@ import {
|
||||
sessionSnapshotMetadataLogLines,
|
||||
sessionSnapshotSummaryLogLines,
|
||||
} from "./session-summary.js";
|
||||
import {
|
||||
saveMachineSessionSnapshotWorkflow,
|
||||
} from "./session-workflow.js";
|
||||
|
||||
const SAMPLE_PATH =
|
||||
"../../../vendor/linuxcnc/configs/sim/axis/vismach/5axis/table-dual-rotary/xyzab-tdr.ini";
|
||||
@@ -566,35 +569,28 @@ document.getElementById("save-machine-files").addEventListener("click", async ()
|
||||
|
||||
document.getElementById("save-session-snapshot").addEventListener("click", async () => {
|
||||
try {
|
||||
await saveMachineTextFiles(MACHINE_ID, {
|
||||
ini: editor.value,
|
||||
toolTable: DEFAULT_TOOL_TABLE,
|
||||
parameters: DEFAULT_PARAMETERS,
|
||||
const workflow = await saveMachineSessionSnapshotWorkflow({
|
||||
machineId: MACHINE_ID,
|
||||
snapshotId: UI_SESSION.snapshotId,
|
||||
snapshotFilename: UI_SESSION.snapshotFilename,
|
||||
snapshotLabel: sessionSnapshotLabel(UI_SESSION),
|
||||
iniText: editor.value,
|
||||
toolTableText: DEFAULT_TOOL_TABLE,
|
||||
parameterText: DEFAULT_PARAMETERS,
|
||||
gcodeFilename: UI_SESSION.defaultGcodeFilename,
|
||||
gcodeText: DEFAULT_GCODE,
|
||||
metadata: sessionSnapshotMetadata(),
|
||||
saveMachineTextFiles,
|
||||
saveGcodeProgram,
|
||||
saveMachineSessionSnapshot,
|
||||
});
|
||||
await saveGcodeProgram(UI_SESSION.defaultGcodeFilename, DEFAULT_GCODE);
|
||||
const snapshot = await saveMachineSessionSnapshot(
|
||||
UI_SESSION.snapshotId,
|
||||
MACHINE_ID,
|
||||
{
|
||||
filename: UI_SESSION.snapshotFilename,
|
||||
gcodeFilename: UI_SESSION.defaultGcodeFilename,
|
||||
metadata: sessionSnapshotMetadata(),
|
||||
},
|
||||
);
|
||||
setField("sessionIni", snapshot.payload.files.ini);
|
||||
setField("sessionParameters", snapshot.payload.files.parameters);
|
||||
setField("sessionToolTable", snapshot.payload.files.toolTable);
|
||||
setField("sessionGcode", snapshot.payload.files.gcode);
|
||||
setField("sessionSnapshot", sessionSnapshotLabel(UI_SESSION));
|
||||
const summary = createSessionSnapshotSummary(snapshot, sessionSnapshotLabel(UI_SESSION));
|
||||
for (const [name, value] of Object.entries(workflow.fields)) {
|
||||
setField(name, value);
|
||||
}
|
||||
setLog(
|
||||
[
|
||||
"Saved machine session snapshot to OPFS.",
|
||||
...sessionSnapshotSummaryLogLines(summary),
|
||||
`INI: ${summary.iniOpfsPath}`,
|
||||
`Parameter file: ${summary.parameterOpfsPath}`,
|
||||
`Tool table file: ${summary.toolTableOpfsPath}`,
|
||||
`G-code: ${summary.gcodeOpfsPath}`,
|
||||
...workflow.logLines,
|
||||
].join("\n"),
|
||||
);
|
||||
} catch (error) {
|
||||
|
||||
65
wasm-port/runtime/ui/ini-panel/session-workflow.js
Normal file
65
wasm-port/runtime/ui/ini-panel/session-workflow.js
Normal file
@@ -0,0 +1,65 @@
|
||||
import {
|
||||
createSessionSnapshotSummary,
|
||||
sessionSnapshotSummaryLogLines,
|
||||
} from "./session-summary.js";
|
||||
|
||||
export function createSessionSnapshotFieldState(summary) {
|
||||
return {
|
||||
sessionIni: summary.iniOpfsPath,
|
||||
sessionParameters: summary.parameterOpfsPath,
|
||||
sessionToolTable: summary.toolTableOpfsPath,
|
||||
sessionGcode: summary.gcodeOpfsPath,
|
||||
sessionSnapshot: summary.snapshotLabel,
|
||||
};
|
||||
}
|
||||
|
||||
export function sessionSnapshotSaveLogLines(summary) {
|
||||
return [
|
||||
...sessionSnapshotSummaryLogLines(summary),
|
||||
`INI: ${summary.iniOpfsPath}`,
|
||||
`Parameter file: ${summary.parameterOpfsPath}`,
|
||||
`Tool table file: ${summary.toolTableOpfsPath}`,
|
||||
`G-code: ${summary.gcodeOpfsPath}`,
|
||||
];
|
||||
}
|
||||
|
||||
export async function saveMachineSessionSnapshotWorkflow({
|
||||
machineId,
|
||||
snapshotId,
|
||||
snapshotFilename,
|
||||
snapshotLabel,
|
||||
iniText,
|
||||
toolTableText,
|
||||
parameterText,
|
||||
gcodeFilename,
|
||||
gcodeText,
|
||||
metadata,
|
||||
saveMachineTextFiles,
|
||||
saveGcodeProgram,
|
||||
saveMachineSessionSnapshot,
|
||||
}) {
|
||||
await Promise.all([
|
||||
saveMachineTextFiles(machineId, {
|
||||
ini: iniText,
|
||||
toolTable: toolTableText,
|
||||
parameters: parameterText,
|
||||
}),
|
||||
saveGcodeProgram(gcodeFilename, gcodeText),
|
||||
]);
|
||||
const snapshot = await saveMachineSessionSnapshot(
|
||||
snapshotId,
|
||||
machineId,
|
||||
{
|
||||
filename: snapshotFilename,
|
||||
gcodeFilename,
|
||||
metadata,
|
||||
},
|
||||
);
|
||||
const summary = createSessionSnapshotSummary(snapshot, snapshotLabel);
|
||||
return {
|
||||
snapshot,
|
||||
summary,
|
||||
fields: createSessionSnapshotFieldState(summary),
|
||||
logLines: sessionSnapshotSaveLogLines(summary),
|
||||
};
|
||||
}
|
||||
107
wasm-port/tests/ui/node/verify_ini_panel_session_workflow.mjs
Normal file
107
wasm-port/tests/ui/node/verify_ini_panel_session_workflow.mjs
Normal file
@@ -0,0 +1,107 @@
|
||||
import assert from "node:assert/strict";
|
||||
|
||||
import {
|
||||
saveMachineSessionSnapshotWorkflow,
|
||||
} from "../../../runtime/ui/ini-panel/session-workflow.js";
|
||||
|
||||
const calls = [];
|
||||
const workflow = await saveMachineSessionSnapshotWorkflow({
|
||||
machineId: "xyzab-tdr",
|
||||
snapshotId: "ui-machine-session",
|
||||
snapshotFilename: "ui-machine-session.json",
|
||||
snapshotLabel: "ui-machine-session/ui-machine-session.json",
|
||||
iniText: "[EMC]\nMACHINE = xyzab-tdr\n",
|
||||
toolTableText: "T2 P7 Z3.125 D1.5 I12 J34 Q4 ;ui session tool\n",
|
||||
parameterText: "5161 0.0\n",
|
||||
gcodeFilename: "ui-session.ngc",
|
||||
gcodeText: "G0 X1.0 Y2.0 (Comment)\nG1 X3.0 Y4.0 F120.0\n",
|
||||
metadata: {
|
||||
source: "ini-panel",
|
||||
workflow: "save-session-snapshot",
|
||||
snapshotLabel: "ui-machine-session/ui-machine-session.json",
|
||||
defaultGcodeOpfsPath: "linuxcnc/gcode/ui-session.ngc",
|
||||
},
|
||||
saveMachineTextFiles: async (machineId, files) => {
|
||||
calls.push(["saveMachineTextFiles", machineId, files]);
|
||||
},
|
||||
saveGcodeProgram: async (filename, text) => {
|
||||
calls.push(["saveGcodeProgram", filename, text]);
|
||||
},
|
||||
saveMachineSessionSnapshot: async (snapshotId, machineId, options) => {
|
||||
calls.push(["saveMachineSessionSnapshot", snapshotId, machineId, options]);
|
||||
return {
|
||||
sessionId: snapshotId,
|
||||
metadata: options.metadata,
|
||||
payload: {
|
||||
files: {
|
||||
ini: "linuxcnc/machines/xyzab-tdr/machine.ini",
|
||||
parameters: "linuxcnc/machines/xyzab-tdr/linuxcnc.var",
|
||||
toolTable: "linuxcnc/machines/xyzab-tdr/tool.tbl",
|
||||
gcode: "linuxcnc/gcode/ui-session.ngc",
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
assert.deepEqual(calls, [
|
||||
[
|
||||
"saveMachineTextFiles",
|
||||
"xyzab-tdr",
|
||||
{
|
||||
ini: "[EMC]\nMACHINE = xyzab-tdr\n",
|
||||
toolTable: "T2 P7 Z3.125 D1.5 I12 J34 Q4 ;ui session tool\n",
|
||||
parameters: "5161 0.0\n",
|
||||
},
|
||||
],
|
||||
[
|
||||
"saveGcodeProgram",
|
||||
"ui-session.ngc",
|
||||
"G0 X1.0 Y2.0 (Comment)\nG1 X3.0 Y4.0 F120.0\n",
|
||||
],
|
||||
[
|
||||
"saveMachineSessionSnapshot",
|
||||
"ui-machine-session",
|
||||
"xyzab-tdr",
|
||||
{
|
||||
filename: "ui-machine-session.json",
|
||||
gcodeFilename: "ui-session.ngc",
|
||||
metadata: {
|
||||
source: "ini-panel",
|
||||
workflow: "save-session-snapshot",
|
||||
snapshotLabel: "ui-machine-session/ui-machine-session.json",
|
||||
defaultGcodeOpfsPath: "linuxcnc/gcode/ui-session.ngc",
|
||||
},
|
||||
},
|
||||
],
|
||||
]);
|
||||
|
||||
assert.deepEqual(workflow.summary, {
|
||||
snapshotLabel: "ui-machine-session/ui-machine-session.json",
|
||||
workflow: "save-session-snapshot",
|
||||
defaultGcodeOpfsPath: "linuxcnc/gcode/ui-session.ngc",
|
||||
iniOpfsPath: "linuxcnc/machines/xyzab-tdr/machine.ini",
|
||||
parameterOpfsPath: "linuxcnc/machines/xyzab-tdr/linuxcnc.var",
|
||||
toolTableOpfsPath: "linuxcnc/machines/xyzab-tdr/tool.tbl",
|
||||
gcodeOpfsPath: "linuxcnc/gcode/ui-session.ngc",
|
||||
});
|
||||
|
||||
assert.deepEqual(workflow.fields, {
|
||||
sessionIni: "linuxcnc/machines/xyzab-tdr/machine.ini",
|
||||
sessionParameters: "linuxcnc/machines/xyzab-tdr/linuxcnc.var",
|
||||
sessionToolTable: "linuxcnc/machines/xyzab-tdr/tool.tbl",
|
||||
sessionGcode: "linuxcnc/gcode/ui-session.ngc",
|
||||
sessionSnapshot: "ui-machine-session/ui-machine-session.json",
|
||||
});
|
||||
|
||||
assert.deepEqual(workflow.logLines, [
|
||||
"Snapshot: ui-machine-session/ui-machine-session.json",
|
||||
"Workflow: save-session-snapshot",
|
||||
"Default G-code: linuxcnc/gcode/ui-session.ngc",
|
||||
"INI: linuxcnc/machines/xyzab-tdr/machine.ini",
|
||||
"Parameter file: linuxcnc/machines/xyzab-tdr/linuxcnc.var",
|
||||
"Tool table file: linuxcnc/machines/xyzab-tdr/tool.tbl",
|
||||
"G-code: linuxcnc/gcode/ui-session.ngc",
|
||||
]);
|
||||
|
||||
console.log("ini_panel_session_workflow_node_smoke=ok");
|
||||
6
wasm-port/tests/ui/node/verify_ini_panel_session_workflow.sh
Executable file
6
wasm-port/tests/ui/node/verify_ini_panel_session_workflow.sh
Executable file
@@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "$0")/../../.." && pwd)"
|
||||
|
||||
node "$ROOT_DIR/tests/ui/node/verify_ini_panel_session_workflow.mjs"
|
||||
@@ -5,6 +5,7 @@ ROOT_DIR="$(cd "$(dirname "$0")/../../.." && pwd)"
|
||||
|
||||
"$ROOT_DIR/tests/ui/node/verify_ini_panel_run_summary.sh"
|
||||
"$ROOT_DIR/tests/ui/node/verify_ini_panel_session_summary.sh"
|
||||
"$ROOT_DIR/tests/ui/node/verify_ini_panel_session_workflow.sh"
|
||||
"$ROOT_DIR/tests/ui/node/verify_ini_panel_machine_file_summary.sh"
|
||||
"$ROOT_DIR/tests/ui/node/verify_ini_panel_state_summary.sh"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user