node-red-contrib-step-escape
Version:
A custom Node-RED Dashboard node that displays a block with a dark background, grey right border, full tab height, and 35% width.
99 lines (84 loc) • 4.04 kB
JavaScript
module.exports = function (RED) {
function CustomBlockLogicNode(config) {
RED.nodes.createNode(this, config);
const node = this;
config.steps = config.steps || [];
const context = node.context();
const storedSteps = context.get("steps") || config.steps.map(step => ({ ...step, state: step.state || "not-executed" }));
config.steps = storedSteps;
console.log("Logic: Loaded steps at startup:", JSON.stringify(config.steps));
const sendInitialSteps = () => {
if (config.steps.length > 0) {
node.send({
topic: "update_steps",
payload: config.steps
});
}
};
sendInitialSteps();
setTimeout(sendInitialSteps, 1000);
setTimeout(sendInitialSteps, 3000);
// ▶️ ▶️ LOGIC ON INPUT MESSAGE
node.on("input", function (msg) {
if (!msg.payload || config.steps.length === 0) return;
const payload = msg.payload.toString().trim();
let updated = false;
// ✅ RESET MODE
if (payload.toLowerCase() === "reset") {
config.steps = config.steps.map(step => ({
...step,
state: "not-executed"
}));
context.set("steps", config.steps);
node.send({
topic: "update_steps",
payload: config.steps
});
node.status({ fill: "blue", shape: "ring", text: "Étapes réinitialisées" });
console.log("Logic: Toutes les étapes ont été réinitialisées.");
return;
}
// ✅ VALIDATION LOGIC
const newSteps = config.steps.map((step, index) => {
const validation = (step.validation || "").trim();
let newState = step.state || "not-executed";
if (validation === payload) {
const prevStepValidated = index === 0 || config.steps[index - 1].state === "validated";
if (prevStepValidated) {
if (newState !== "validated") {
newState = "validated";
updated = true;
console.log("Logic: Set step to validated:", step.name);
}
} else if (newState !== "invalid-order" && newState !== "in-progress") {
newState = "invalid-order";
updated = true;
console.log("Logic: Set step to invalid-order:", step.name);
}
}
return { ...step, state: newState };
});
newSteps.forEach((step, index) => {
if (index > 0 && newSteps[index - 1].state === "validated" && (step.state === "not-executed" || step.state === "invalid-order")) {
step.state = "in-progress";
updated = true;
console.log("Logic: Set step to in-progress:", step.name);
} else if (step.state === "in-progress" && (index === 0 || newSteps[index - 1].state !== "validated")) {
step.state = "not-executed";
updated = true;
console.log("Logic: Reverted step to not-executed:", step.name);
}
});
config.steps = newSteps;
if (updated) {
context.set("steps", config.steps);
node.send({
topic: "update_steps",
payload: config.steps
});
node.status({ fill: "green", shape: "dot", text: "Étapes mises à jour" });
}
});
}
RED.nodes.registerType("step-escape", CustomBlockLogicNode);
};