推进 INI 面板 control view helper
This commit is contained in:
61
text11.txt
61
text11.txt
@@ -958,3 +958,64 @@ host_wasm_opfs_browser_smokes=ok
|
||||
继续沿“单点只读入口”推进,把 `window.linuxCncIniPanelApi` 再收敛成一个更明确的
|
||||
`getMachineSessionView()` 或 `getMachineSessionStateBundle()` 的稳定消费者契约,并开始只
|
||||
在这个 bundle 上面叠控制页展示逻辑;仍不新增按钮、不把 CNC 语义搬进 JS。
|
||||
|
||||
十、2026-06-14 继续执行记录:INI panel control view helper
|
||||
|
||||
本轮按“加快实质性推进”继续往控制网页界面的只读展示层推进,在 bundle 之上新增
|
||||
control view helper,让上层 UI 可以直接渲染 status 与 sections/rows。
|
||||
|
||||
完成内容:
|
||||
|
||||
- `wasm-port/runtime/ui/ini-panel/panel-state-summary.js` 新增
|
||||
`createMachineSessionControlView(bundle)`;
|
||||
- control view 返回:
|
||||
- `status`;
|
||||
- `sections`;
|
||||
- readiness/session/run 三组 rows;
|
||||
- `wasm-port/runtime/ui/ini-panel/app.js` 在
|
||||
`window.linuxCncIniPanelApi`、`window.getMachineSessionControlView()` 下暴露该 helper;
|
||||
- `wasm-port/tests/ui/node/verify_ini_panel_state_summary.mjs` 覆盖 view model 输出结构;
|
||||
- `wasm-port/tests/browser/ini_panel_smoke.html` 在真实 save、restore-load、run 流程后验证
|
||||
control view 的 status、section id、workflow row 和 canonical-event row;
|
||||
- `wasm-port/docs/ui-panel-state-summary.md` 补充 control view helper 说明;
|
||||
- 未新增按钮;
|
||||
- 未解析 G-code;
|
||||
- 未解释 canonical events;
|
||||
- 未改变 OPFS/session persistence、LinuxCNC interpreter、tool、parameter、planner 或
|
||||
LinuxCNC-owned runtime semantics。
|
||||
|
||||
验证已通过:
|
||||
|
||||
```bash
|
||||
git diff --check
|
||||
wasm-port/tests/ui/node/verify_ini_panel_state_summary.sh
|
||||
wasm-port/tests/ui/node/verify_ui_node_smokes.sh
|
||||
SKIP_INI_BUILD=1 SKIP_INTERP_BUILD=1 wasm-port/tests/browser/verify_ini_panel_browser.sh
|
||||
wasm-port/tools/verify_vendor_sync.sh
|
||||
wasm-port/tools/verify_no_standalone_cnc_semantics.sh
|
||||
SKIP_INTERP_BUILD=1 wasm-port/tests/wasm/node/verify_interp_wasm.sh
|
||||
SKIP_INTERP_BUILD=1 wasm-port/tests/wasm/node/verify_sim_configs_inventory_wasm.sh
|
||||
wasm-port/tests/host/verify_host_smokes.sh
|
||||
```
|
||||
|
||||
关键输出:
|
||||
|
||||
```text
|
||||
ini_panel_state_summary_node_smoke=ok
|
||||
ui_node_smokes=ok
|
||||
browser_ini_opfs_smoke=ok
|
||||
vendor sync up to date
|
||||
standalone CNC semantics guard complete
|
||||
interp_wasm_node_smoke=ok
|
||||
sim_configs_wasm_node_inventory_executed=28
|
||||
sim_configs_wasm_node_inventory_passed=28
|
||||
sim_configs_wasm_node_inventory_skipped=131
|
||||
sim_configs_wasm_node_inventory_unexpected_fail=0
|
||||
host_wasm_opfs_browser_smokes=ok
|
||||
```
|
||||
|
||||
下一步建议:
|
||||
|
||||
继续推进实际控制网页界面的只读展示层。下一批建议新增一个极薄的 browser smoke 或
|
||||
文档化控制页消费示例,直接读取 `window.linuxCncIniPanelApi.getMachineSessionControlView()`
|
||||
并渲染 sections;仍保持只读,不加控制按钮,不解析 G-code。
|
||||
|
||||
@@ -22,6 +22,7 @@ For control-page polling, use
|
||||
`window.linuxCncIniPanelApi.getMachineSessionWorkflowStatus()`. It returns a
|
||||
smaller workflow-facing object derived from the same report data.
|
||||
For a single read call, use `window.linuxCncIniPanelApi.getMachineSessionStateBundle()`.
|
||||
For direct rendering, use `window.linuxCncIniPanelApi.getMachineSessionControlView()`.
|
||||
|
||||
## `createIniPanelStateSummary(input)`
|
||||
|
||||
@@ -142,6 +143,24 @@ It is the preferred single-entry helper for control-page polling and other
|
||||
upper-level UI consumers that want one stable read instead of stitching the
|
||||
three views together themselves.
|
||||
|
||||
## `createMachineSessionControlView(bundle)`
|
||||
|
||||
This helper maps a bundle into UI-ready status and sections:
|
||||
|
||||
```js
|
||||
{
|
||||
status: { lastAction: "run-gcode", error: null, runStatus: "ok" },
|
||||
sections: [
|
||||
{ id: "readiness", title: "Readiness", rows: [{ label: "INI", value: "..." }] },
|
||||
{ id: "session", title: "Session", rows: [{ label: "Workflow", value: "..." }] },
|
||||
{ id: "run", title: "Run", rows: [{ label: "Canonical events", value: 2 }] }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
It is a presentation mapping over the bundle only. It does not parse G-code,
|
||||
canonical events, or LinuxCNC-owned runtime content.
|
||||
|
||||
## Boundary Rules
|
||||
|
||||
- Do not parse G-code text in this helper.
|
||||
|
||||
@@ -46,6 +46,7 @@ import {
|
||||
saveMachineSessionSnapshotWorkflow,
|
||||
} from "./session-workflow.js";
|
||||
import {
|
||||
createMachineSessionControlView,
|
||||
createMachineSessionStateSnapshot,
|
||||
createMachineSessionStateBundle,
|
||||
createMachineSessionStateReport,
|
||||
@@ -171,6 +172,10 @@ function getMachineSessionStateBundle() {
|
||||
return createMachineSessionStateBundle(window.linuxCncIniPanelMachineSessionState);
|
||||
}
|
||||
|
||||
function getMachineSessionControlView() {
|
||||
return createMachineSessionControlView(getMachineSessionStateBundle());
|
||||
}
|
||||
|
||||
function updatePanelMachineSessionState(patch = {}) {
|
||||
panelMachineSessionState = createMachineSessionStateSnapshot({
|
||||
...panelMachineSessionState,
|
||||
@@ -185,11 +190,13 @@ function updatePanelMachineSessionState(patch = {}) {
|
||||
}
|
||||
|
||||
window.linuxCncIniPanelApi = {
|
||||
getMachineSessionControlView,
|
||||
getMachineSessionStateBundle,
|
||||
getMachineSessionStateReport,
|
||||
getMachineSessionStateReportExport,
|
||||
getMachineSessionWorkflowStatus,
|
||||
};
|
||||
window.getMachineSessionControlView = getMachineSessionControlView;
|
||||
window.getMachineSessionStateBundle = getMachineSessionStateBundle;
|
||||
window.getMachineSessionStateReport = getMachineSessionStateReport;
|
||||
window.getMachineSessionStateReportExport = getMachineSessionStateReportExport;
|
||||
|
||||
@@ -140,3 +140,48 @@ export function createMachineSessionStateBundle(state = {}, options = {}) {
|
||||
workflowStatus,
|
||||
};
|
||||
}
|
||||
|
||||
export function createMachineSessionControlView(bundle = {}) {
|
||||
const report = bundle.report ?? {};
|
||||
const workflowStatus = bundle.workflowStatus ?? {};
|
||||
const session = workflowStatus.session ?? report.session ?? {};
|
||||
const run = workflowStatus.run ?? report.run ?? {};
|
||||
return {
|
||||
status: {
|
||||
lastAction: workflowStatus.lastAction ?? report.status?.lastAction ?? null,
|
||||
error: workflowStatus.error ?? report.status?.error ?? null,
|
||||
runStatus: run.status ?? null,
|
||||
},
|
||||
sections: [
|
||||
{
|
||||
id: "readiness",
|
||||
title: "Readiness",
|
||||
rows: [
|
||||
{ label: "INI", value: workflowStatus.readiness?.ini ?? report.readiness?.ini ?? null },
|
||||
{ label: "Interpreter", value: workflowStatus.readiness?.interp ?? report.readiness?.interp ?? null },
|
||||
{ label: "OPFS", value: workflowStatus.readiness?.opfs ?? report.readiness?.opfs ?? null },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "session",
|
||||
title: "Session",
|
||||
rows: [
|
||||
{ label: "Snapshot", value: session.snapshotLabel ?? null },
|
||||
{ label: "Workflow", value: session.workflow ?? null },
|
||||
{ label: "INI", value: session.ini ?? null },
|
||||
{ label: "G-code", value: session.gcode ?? null },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "run",
|
||||
title: "Run",
|
||||
rows: [
|
||||
{ label: "Status", value: run.status ?? null },
|
||||
{ label: "Canonical events", value: run.canonicalEventCount ?? 0 },
|
||||
{ label: "Motion snapshots", value: run.motionSnapshotCount ?? 0 },
|
||||
{ label: "INI WASM", value: run.iniWasmPath ?? null },
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
@@ -369,6 +369,7 @@ TOOL_TABLE = browser-tool.tbl
|
||||
);
|
||||
const uiApi = uiDocument.defaultView.linuxCncIniPanelApi;
|
||||
if (
|
||||
!uiApi?.getMachineSessionControlView ||
|
||||
!uiApi?.getMachineSessionStateBundle ||
|
||||
!uiApi?.getMachineSessionStateReport ||
|
||||
!uiApi?.getMachineSessionStateReportExport ||
|
||||
@@ -830,6 +831,32 @@ TOOL_TABLE = browser-tool.tbl
|
||||
machineSessionStateBundle.workflowStatus.lastAction,
|
||||
"UI legacy machine session state bundle getter matches API namespace",
|
||||
);
|
||||
const machineSessionControlView = uiApi.getMachineSessionControlView();
|
||||
assertEqual(
|
||||
machineSessionControlView.status.runStatus,
|
||||
"ok",
|
||||
"UI machine session control view run status",
|
||||
);
|
||||
assertEqual(
|
||||
machineSessionControlView.sections[0].id,
|
||||
"readiness",
|
||||
"UI machine session control view readiness section",
|
||||
);
|
||||
assertEqual(
|
||||
machineSessionControlView.sections[1].rows[1].value,
|
||||
"save-session-snapshot",
|
||||
"UI machine session control view session workflow row",
|
||||
);
|
||||
assertEqual(
|
||||
machineSessionControlView.sections[2].rows[1].value,
|
||||
2,
|
||||
"UI machine session control view canonical event row",
|
||||
);
|
||||
assertEqual(
|
||||
uiDocument.defaultView.getMachineSessionControlView().status.lastAction,
|
||||
machineSessionControlView.status.lastAction,
|
||||
"UI legacy machine session control view getter matches API namespace",
|
||||
);
|
||||
assertEqual(
|
||||
uiDocument.defaultView.getMachineSessionStateReport().status.lastAction,
|
||||
machineSessionStateReport.status.lastAction,
|
||||
|
||||
@@ -2,6 +2,7 @@ import assert from "node:assert/strict";
|
||||
|
||||
import {
|
||||
createIniPanelStateSummary,
|
||||
createMachineSessionControlView,
|
||||
createMachineSessionStateSnapshot,
|
||||
createMachineSessionStateBundle,
|
||||
createMachineSessionStateReport,
|
||||
@@ -473,17 +474,92 @@ assert.deepEqual(
|
||||
);
|
||||
|
||||
assert.deepEqual(
|
||||
createMachineSessionControlView({
|
||||
report: expectedBundleReport,
|
||||
export: {
|
||||
filename: "machine-session-state-report.json",
|
||||
mediaType: "application/json",
|
||||
report: expectedBundleReport,
|
||||
text: `${JSON.stringify(expectedBundleReport, null, 2)}\n`,
|
||||
},
|
||||
workflowStatus: {
|
||||
readiness: {
|
||||
ini: "INI WASM: ready",
|
||||
interp: "Interpreter WASM: ready",
|
||||
opfs: "OPFS: ready",
|
||||
},
|
||||
lastAction: "run-gcode",
|
||||
error: null,
|
||||
session: {
|
||||
snapshotLabel: "ui-machine-session/ui-machine-session.json",
|
||||
workflow: "save-session-snapshot",
|
||||
ini: "/work/session-machine.ini",
|
||||
parameters: null,
|
||||
toolTable: null,
|
||||
gcode: "linuxcnc/gcode/ui-session.ngc",
|
||||
},
|
||||
run: {
|
||||
status: "ok",
|
||||
canonicalEventCount: 2,
|
||||
motionSnapshotCount: 2,
|
||||
iniWasmPath: null,
|
||||
},
|
||||
},
|
||||
}),
|
||||
{
|
||||
status: {
|
||||
lastAction: "run-gcode",
|
||||
error: null,
|
||||
runStatus: "ok",
|
||||
},
|
||||
sections: [
|
||||
{
|
||||
id: "readiness",
|
||||
title: "Readiness",
|
||||
rows: [
|
||||
{ label: "INI", value: "INI WASM: ready" },
|
||||
{ label: "Interpreter", value: "Interpreter WASM: ready" },
|
||||
{ label: "OPFS", value: "OPFS: ready" },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "session",
|
||||
title: "Session",
|
||||
rows: [
|
||||
{ label: "Snapshot", value: "ui-machine-session/ui-machine-session.json" },
|
||||
{ label: "Workflow", value: "save-session-snapshot" },
|
||||
{ label: "INI", value: "/work/session-machine.ini" },
|
||||
{ label: "G-code", value: "linuxcnc/gcode/ui-session.ngc" },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "run",
|
||||
title: "Run",
|
||||
rows: [
|
||||
{ label: "Status", value: "ok" },
|
||||
{ label: "Canonical events", value: 2 },
|
||||
{ label: "Motion snapshots", value: 2 },
|
||||
{ label: "INI WASM", value: null },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
);
|
||||
|
||||
assert.deepEqual(
|
||||
{
|
||||
getMachineSessionControlView: typeof globalThis.window?.linuxCncIniPanelApi?.getMachineSessionControlView,
|
||||
getMachineSessionStateBundle: typeof globalThis.window?.linuxCncIniPanelApi?.getMachineSessionStateBundle,
|
||||
getMachineSessionStateReport: typeof globalThis.window?.linuxCncIniPanelApi?.getMachineSessionStateReport,
|
||||
getMachineSessionStateReportExport: typeof globalThis.window?.linuxCncIniPanelApi?.getMachineSessionStateReportExport,
|
||||
getMachineSessionWorkflowStatus: typeof globalThis.window?.linuxCncIniPanelApi?.getMachineSessionWorkflowStatus,
|
||||
getMachineSessionStateBundle: typeof globalThis.window?.linuxCncIniPanelApi?.getMachineSessionStateBundle,
|
||||
},
|
||||
{
|
||||
getMachineSessionControlView: "undefined",
|
||||
getMachineSessionStateBundle: "undefined",
|
||||
getMachineSessionStateReport: "undefined",
|
||||
getMachineSessionStateReportExport: "undefined",
|
||||
getMachineSessionWorkflowStatus: "undefined",
|
||||
getMachineSessionStateBundle: "undefined",
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user