423 lines
14 KiB
JavaScript
423 lines
14 KiB
JavaScript
export function createIniPanelStateSummary({
|
|
badges = {},
|
|
machine = null,
|
|
machineFiles = null,
|
|
sessionSnapshot = null,
|
|
sessionReadiness = null,
|
|
sessionLoad = null,
|
|
runReadiness = null,
|
|
run = null,
|
|
fiveaxisRemap = null,
|
|
} = {}) {
|
|
return {
|
|
badges: {
|
|
ini: badges.ini ?? null,
|
|
interp: badges.interp ?? null,
|
|
opfs: badges.opfs ?? null,
|
|
},
|
|
machine,
|
|
machineFiles,
|
|
sessionSnapshot,
|
|
sessionReadiness,
|
|
sessionLoad,
|
|
runReadiness,
|
|
run,
|
|
fiveaxisRemap: fiveaxisRemap ?? null,
|
|
};
|
|
}
|
|
|
|
export function createMachineSessionStateSnapshot({
|
|
badges = {},
|
|
machine = null,
|
|
machineFiles = null,
|
|
sessionSnapshot = null,
|
|
sessionReadiness = null,
|
|
sessionLoad = null,
|
|
runReadiness = null,
|
|
selectedProgram = null,
|
|
run = null,
|
|
fields = {},
|
|
lastAction = null,
|
|
error = null,
|
|
fiveaxisRemap = null,
|
|
} = {}) {
|
|
return {
|
|
...createIniPanelStateSummary({
|
|
badges,
|
|
machine,
|
|
machineFiles,
|
|
sessionSnapshot,
|
|
sessionReadiness,
|
|
sessionLoad,
|
|
runReadiness,
|
|
run,
|
|
fiveaxisRemap,
|
|
}),
|
|
selectedProgram,
|
|
fields: {
|
|
sessionIni: fields.sessionIni ?? null,
|
|
sessionParameters: fields.sessionParameters ?? null,
|
|
sessionToolTable: fields.sessionToolTable ?? null,
|
|
sessionGcode: fields.sessionGcode ?? null,
|
|
sessionSnapshot: fields.sessionSnapshot ?? null,
|
|
runStatus: fields.runStatus ?? null,
|
|
runSource: fields.runSource ?? null,
|
|
runSnapshot: fields.runSnapshot ?? null,
|
|
runWorkflow: fields.runWorkflow ?? null,
|
|
runOpfsPath: fields.runOpfsPath ?? null,
|
|
runWasmPath: fields.runWasmPath ?? null,
|
|
},
|
|
lastAction: lastAction ?? null,
|
|
error: error ?? null,
|
|
};
|
|
}
|
|
|
|
export function createMachineSessionStateReport(state = {}) {
|
|
const badges = state.badges ?? {};
|
|
const fields = state.fields ?? {};
|
|
const sessionSnapshot = state.sessionSnapshot ?? {};
|
|
const sessionReadiness = state.sessionReadiness ?? null;
|
|
const sessionLoad = state.sessionLoad ?? {};
|
|
const runReadiness = state.runReadiness ?? {};
|
|
const selectedProgram = state.selectedProgram ?? {};
|
|
const run = state.run ?? {};
|
|
return {
|
|
readiness: {
|
|
ini: badges.ini ?? null,
|
|
interp: badges.interp ?? null,
|
|
opfs: badges.opfs ?? null,
|
|
},
|
|
session: {
|
|
snapshotLabel: sessionSnapshot.snapshotLabel ?? fields.sessionSnapshot ?? null,
|
|
workflow: sessionSnapshot.workflow ?? fields.runWorkflow ?? null,
|
|
ini: fields.sessionIni ?? sessionSnapshot.iniOpfsPath ?? sessionLoad.iniWasmPath ?? null,
|
|
parameters: fields.sessionParameters ?? sessionSnapshot.parameterOpfsPath ?? sessionLoad.parameterWasmPath ?? null,
|
|
toolTable: fields.sessionToolTable ?? sessionSnapshot.toolTableOpfsPath ?? sessionLoad.toolTableWasmPath ?? null,
|
|
gcode: fields.sessionGcode ?? sessionSnapshot.gcodeOpfsPath ?? null,
|
|
},
|
|
sessionReadiness,
|
|
loaded: {
|
|
iniWasmPath: sessionLoad.iniWasmPath ?? null,
|
|
parameterWasmPath: sessionLoad.parameterWasmPath ?? null,
|
|
toolTableWasmPath: sessionLoad.toolTableWasmPath ?? null,
|
|
},
|
|
program: {
|
|
source: selectedProgram.source ?? run.programSource ?? fields.runSource ?? null,
|
|
opfsPath: selectedProgram.opfsPath ?? run.programOpfsPath ?? fields.runOpfsPath ?? null,
|
|
wasmPath: selectedProgram.wasmPath ?? run.programWasmPath ?? fields.runWasmPath ?? null,
|
|
},
|
|
runReadiness: {
|
|
phase: runReadiness.phase ?? null,
|
|
canRun: Boolean(runReadiness.canRun),
|
|
missing: Array.isArray(runReadiness.missing) ? runReadiness.missing : [],
|
|
buttonEnabled: Boolean(runReadiness.runButton?.enabled),
|
|
buttonReason: runReadiness.runButton?.reason ?? null,
|
|
programSource: runReadiness.program?.source ?? null,
|
|
programOpfsPath: runReadiness.program?.opfsPath ?? null,
|
|
programWasmPath: runReadiness.program?.wasmPath ?? null,
|
|
iniWasmPath: runReadiness.loadedSession?.iniWasmPath ?? null,
|
|
},
|
|
run: {
|
|
status: run.runStatus ?? fields.runStatus ?? null,
|
|
canonicalEventCount: run.canonicalEventCount ?? 0,
|
|
motionSnapshotCount: run.motionSnapshotCount ?? 0,
|
|
iniWasmPath: run.iniWasmPath ?? null,
|
|
},
|
|
status: {
|
|
lastAction: state.lastAction ?? null,
|
|
error: state.error ?? null,
|
|
fiveaxisRemap: state.fiveaxisRemap ?? null,
|
|
},
|
|
};
|
|
}
|
|
|
|
export function createMachineSessionStateReportExport(state = {}, options = {}) {
|
|
const report = createMachineSessionStateReport(state);
|
|
return {
|
|
filename: options.filename ?? "machine-session-state-report.json",
|
|
mediaType: "application/json",
|
|
report,
|
|
text: `${JSON.stringify(report, null, 2)}\n`,
|
|
};
|
|
}
|
|
|
|
export function createMachineSessionWorkflowStatus(state = {}) {
|
|
const report = createMachineSessionStateReport(state);
|
|
const overview = createMachineSessionWorkflowOverview(report);
|
|
return {
|
|
readiness: report.readiness,
|
|
overview,
|
|
sessionReadiness: report.sessionReadiness ?? null,
|
|
runReadiness: report.runReadiness,
|
|
lastAction: report.status.lastAction,
|
|
error: report.status.error,
|
|
session: report.session,
|
|
run: report.run,
|
|
};
|
|
}
|
|
|
|
export function createMachineSessionPersistenceSummary({
|
|
state = {},
|
|
report = createMachineSessionStateReport(state),
|
|
workflowStatus = createMachineSessionWorkflowStatus(state),
|
|
readonlyStatus = null,
|
|
handoffSummary = null,
|
|
handoffWorkflowSummary = null,
|
|
} = {}) {
|
|
const readiness = report.readiness ?? {};
|
|
const machineFiles = state.machineFiles ?? {};
|
|
const session = report.session ?? {};
|
|
const loaded = report.loaded ?? {};
|
|
const sessionReadiness = report.sessionReadiness ?? workflowStatus.sessionReadiness ?? null;
|
|
const opfsReady = String(readiness.opfs ?? "").toLowerCase().includes("ready");
|
|
const machineFileLabels = [
|
|
machineFiles.iniOpfsPath || session.ini ? "ini" : null,
|
|
machineFiles.parameterOpfsPath || session.parameters ? "parameters" : null,
|
|
machineFiles.toolTableOpfsPath || session.toolTable ? "tool-table" : null,
|
|
machineFiles.gcodeOpfsPath || session.gcode ? "g-code" : null,
|
|
].filter(Boolean);
|
|
const machineFilesReady = machineFileLabels.length > 0;
|
|
const snapshotReady = Boolean(session.snapshotLabel);
|
|
const sessionReadinessReady = sessionReadiness?.ready === true;
|
|
const sessionLoadReady = Boolean(loaded.iniWasmPath);
|
|
const readonlyStatusValue = readonlyStatus
|
|
? (readonlyStatus.ready === true ? "ready" : readonlyStatus.phase ?? "available")
|
|
: "not-provided";
|
|
const handoffValue = handoffWorkflowSummary
|
|
? (handoffWorkflowSummary.ready === true ? "ready" : handoffWorkflowSummary.phase ?? "blocked")
|
|
: (
|
|
handoffSummary
|
|
? (handoffSummary.ready === true ? "ready" : handoffSummary.phase ?? "blocked")
|
|
: "not-provided"
|
|
);
|
|
const checks = {
|
|
opfs: opfsReady,
|
|
machineFiles: machineFilesReady,
|
|
sessionSnapshot: snapshotReady,
|
|
sessionReadiness: sessionReadinessReady,
|
|
sessionLoad: sessionLoadReady,
|
|
};
|
|
const missing = Object.entries(checks)
|
|
.filter(([, passed]) => !passed)
|
|
.map(([name]) => name);
|
|
const ready = missing.length === 0;
|
|
|
|
return {
|
|
apiName: "machine-session-persistence-summary",
|
|
summaryVersion: 1,
|
|
phase: ready ? "ready" : "waiting",
|
|
ready,
|
|
checks,
|
|
missing,
|
|
counts: {
|
|
machineFiles: machineFileLabels.length,
|
|
missing: missing.length,
|
|
},
|
|
rows: [
|
|
{
|
|
id: "opfs",
|
|
label: "OPFS",
|
|
value: readiness.opfs ?? "missing",
|
|
},
|
|
{
|
|
id: "machine-files",
|
|
label: "Machine files",
|
|
value: machineFileLabels.length > 0 ? machineFileLabels.join(", ") : "missing",
|
|
},
|
|
{
|
|
id: "session-snapshot",
|
|
label: "Session snapshot",
|
|
value: session.snapshotLabel ?? "missing",
|
|
},
|
|
{
|
|
id: "session-readiness",
|
|
label: "Session readiness",
|
|
value: sessionReadiness
|
|
? (sessionReadiness.ready ? "ready" : `blocked: ${sessionReadiness.missing?.join(", ") || "unknown"}`)
|
|
: "missing",
|
|
},
|
|
{
|
|
id: "session-load",
|
|
label: "Session load",
|
|
value: loaded.iniWasmPath ? `loaded: ${loaded.iniWasmPath}` : "missing",
|
|
},
|
|
{
|
|
id: "readonly-status",
|
|
label: "Readonly status",
|
|
value: readonlyStatusValue,
|
|
},
|
|
{
|
|
id: "handoff-readiness",
|
|
label: "Handoff readiness",
|
|
value: handoffValue,
|
|
},
|
|
],
|
|
};
|
|
}
|
|
|
|
export function createMachineSessionPersistenceDisplayViewModel(
|
|
summary = createMachineSessionPersistenceSummary(),
|
|
) {
|
|
const missing = Array.isArray(summary?.missing) ? summary.missing : [];
|
|
const rows = Array.isArray(summary?.rows)
|
|
? summary.rows.map(({ id, label, value }) => ({
|
|
id,
|
|
label,
|
|
value: value == null ? "" : String(value),
|
|
}))
|
|
: [];
|
|
return {
|
|
phase: summary?.phase === "ready" ? "ready" : "waiting",
|
|
title: "OPFS/session persistence",
|
|
statusText: summary?.ready ? "Ready" : "Waiting",
|
|
detailText: missing.length > 0 ? missing.join(", ") : "No missing persistence requirements",
|
|
rows,
|
|
};
|
|
}
|
|
|
|
export function createMachineSessionPersistenceRenderState(
|
|
displayViewModel = createMachineSessionPersistenceDisplayViewModel(),
|
|
) {
|
|
const rows = Array.isArray(displayViewModel?.rows)
|
|
? displayViewModel.rows.map(({ id, label, value }) => ({
|
|
id,
|
|
label,
|
|
value: value == null ? "" : String(value),
|
|
}))
|
|
: [];
|
|
const ready = displayViewModel?.phase === "ready" && displayViewModel?.statusText === "Ready";
|
|
const statusText = displayViewModel?.statusText ?? (ready ? "Ready" : "Waiting");
|
|
const detailText = displayViewModel?.detailText ?? "No missing persistence requirements";
|
|
return {
|
|
apiName: "machine-session-persistence-render-state",
|
|
renderStateVersion: 1,
|
|
phase: ready ? "ready" : "waiting",
|
|
ready,
|
|
title: displayViewModel?.title ?? "OPFS/session persistence",
|
|
statusText,
|
|
detailText,
|
|
statusLine: `${statusText}: ${detailText}`,
|
|
rows,
|
|
dataset: {
|
|
persistencePhase: ready ? "ready" : "waiting",
|
|
persistenceReady: ready ? "true" : "false",
|
|
persistenceScope: "opfs-session",
|
|
},
|
|
};
|
|
}
|
|
|
|
export function createMachineSessionWorkflowOverview(report = {}) {
|
|
const readiness = report.readiness ?? {};
|
|
const loaded = report.loaded ?? {};
|
|
const session = report.session ?? {};
|
|
const runReadiness = report.runReadiness ?? {};
|
|
const run = report.run ?? {};
|
|
const status = report.status ?? {};
|
|
const loadedIniWasmPath = loaded.iniWasmPath ?? runReadiness.iniWasmPath ?? null;
|
|
const missing = [];
|
|
if (!loadedIniWasmPath) {
|
|
missing.push("loaded-session");
|
|
}
|
|
if (!session.snapshotLabel) {
|
|
missing.push("session-snapshot");
|
|
}
|
|
if (!runReadiness.canRun) {
|
|
missing.push("run-readiness");
|
|
}
|
|
return {
|
|
phase: run.status ? "ran" : (missing.length === 0 ? "ready" : "waiting"),
|
|
missing,
|
|
readiness,
|
|
session: {
|
|
snapshotLabel: session.snapshotLabel ?? null,
|
|
workflow: session.workflow ?? null,
|
|
ini: session.ini ?? null,
|
|
gcode: session.gcode ?? null,
|
|
},
|
|
loaded,
|
|
runReadiness,
|
|
run: {
|
|
status: run.status ?? null,
|
|
canonicalEventCount: run.canonicalEventCount ?? 0,
|
|
motionSnapshotCount: run.motionSnapshotCount ?? 0,
|
|
iniWasmPath: run.iniWasmPath ?? null,
|
|
},
|
|
status: {
|
|
lastAction: status.lastAction ?? null,
|
|
error: status.error ?? null,
|
|
},
|
|
};
|
|
}
|
|
|
|
export function createMachineSessionStateBundle(state = {}, options = {}) {
|
|
const report = createMachineSessionStateReport(state);
|
|
const exportPayload = createMachineSessionStateReportExport(state, options);
|
|
const workflowStatus = createMachineSessionWorkflowStatus(state);
|
|
const overview = createMachineSessionWorkflowOverview(report);
|
|
return {
|
|
report,
|
|
overview,
|
|
export: exportPayload,
|
|
workflowStatus,
|
|
};
|
|
}
|
|
|
|
export function createMachineSessionControlView(bundle = {}) {
|
|
const report = bundle.report ?? {};
|
|
const workflowStatus = bundle.workflowStatus ?? {};
|
|
const overview = bundle.overview ?? workflowStatus.overview ?? {};
|
|
const session = workflowStatus.session ?? report.session ?? {};
|
|
const runReadiness = workflowStatus.runReadiness ?? report.runReadiness ?? {};
|
|
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: "workflow",
|
|
title: "Workflow",
|
|
rows: [
|
|
{ label: "Phase", value: overview.phase ?? null },
|
|
{ label: "Missing", value: overview.missing?.join(", ") || null },
|
|
{ label: "Last action", value: overview.status?.lastAction ?? null },
|
|
{ label: "Error", value: overview.status?.error ?? null },
|
|
],
|
|
},
|
|
{
|
|
id: "run",
|
|
title: "Run",
|
|
rows: [
|
|
{ label: "Ready", value: runReadiness.phase ?? null },
|
|
{ label: "Button", value: runReadiness.buttonEnabled ? "enabled" : "disabled" },
|
|
{ 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 },
|
|
],
|
|
},
|
|
],
|
|
};
|
|
}
|