import { HatGraphNode } from "./hat-graph-node"; import { mdiCallSplit, mdiAbTesting, mdiCheck, mdiClose, mdiChevronRight, mdiExclamation, mdiTimerOutline, mdiTrafficLight, mdiRefresh, mdiArrowUp, mdiCodeJson, mdiCheckBoxOutline, mdiCheckboxBlankOutline, mdiAsterisk, } from "@mdi/js"; import { HatGraph } from "./hat-graph"; import { html } from "lit-element"; import { render } from "lit-html"; const OPTIONS = [ "condition", "delay", "device_id", "event", "scene", "service", "wait_template", "repeat", "choose", ]; const ICONS = { new: mdiAsterisk, service: mdiChevronRight, condition: mdiAbTesting, TRUE: mdiCheck, FALSE: mdiClose, delay: mdiTimerOutline, wait_template: mdiTrafficLight, event: mdiExclamation, repeat: mdiRefresh, repeatReturn: mdiArrowUp, choose: mdiCallSplit, chooseChoice: mdiCheckBoxOutline, chooseDefault: mdiCheckboxBlankOutline, YAML: mdiCodeJson, }; const SPECIAL_NODES = { condition: makeConditionNode, choose: makeChooseNode, repeat: makeRepeatNode, }; function makeConditionNode(config) { const graph = document.createElement("hat-graph") as HatGraph; graph.branching = true; const focused = () => graph.dispatchEvent( new CustomEvent("node-selected", { detail: { config }, bubbles: true }) ); render( html` `, graph ); return graph; } function makeChooseNode(config) { const graph = document.createElement("hat-graph") as HatGraph; graph.branching = true; const focused = () => graph.dispatchEvent( new CustomEvent("node-selected", { detail: { config }, bubbles: true }) ); render( html` ${config.choose?.map((branch) => { return html` ${branch.sequence.map((node) => makeNode(node))} `; })} ${config.default.map((node) => makeNode(node))} `, graph ); return graph; } function makeRepeatNode(config) { const graph = document.createElement("hat-graph") as HatGraph; graph.branching = true; const focused = () => graph.dispatchEvent( new CustomEvent("node-selected", { detail: { config }, bubbles: true }) ); render( html` ${config.repeat.sequence.map((node) => makeNode(node))} `, graph ); return graph; } function makeNode(config) { const type = OPTIONS.find((key) => key in config) || "yaml"; if (type in SPECIAL_NODES) { return SPECIAL_NODES[type](config); } const node = document.createElement("hat-graph-node") as HatGraphNode; node.iconPath = ICONS[type]; node.addEventListener("focus", (ev) => { node.dispatchEvent( new CustomEvent("node-selected", { detail: { config }, bubbles: true }) ); }); return node; } export function makeGraph(nodes) { const graph = document.createElement("hat-graph") as HatGraph; for (const [i, nodeConfig] of nodes.entries()) { const node = makeNode(nodeConfig); node.addEventListener("update-node", (ev) => { ev.stopPropagation(); const config = [...nodes]; config[i] = ev.detail.config; graph.dispatchEvent( new CustomEvent("update-node", { detail: { config }, bubbles: true }) ); }); node.addEventListener("delete-node", (ev) => { ev.stopPropagation(); const config = [...nodes]; config.splice(i, 1); graph.dispatchEvent( new CustomEvent("update-node", { detail: { config }, bubbles: true }) ); }); graph.appendChild(node); } return graph; }