Script-to-graph functions added for new method
This commit is contained in:
parent
b1916fe55d
commit
ccbe62c0d9
31
.vscode/tasks.json
vendored
Normal file
31
.vscode/tasks.json
vendored
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"version": "2.0.0",
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"label": "npm: build",
|
||||||
|
"type": "npm",
|
||||||
|
"script": "build",
|
||||||
|
"problemMatcher": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "npm: watch",
|
||||||
|
"type": "npm",
|
||||||
|
"script": "watch",
|
||||||
|
"problemMatcher": [],
|
||||||
|
"presentation": {
|
||||||
|
"panel": "shared",
|
||||||
|
"group": "test"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "npm: serve",
|
||||||
|
"type": "npm",
|
||||||
|
"script": "serve",
|
||||||
|
"problemMatcher": [],
|
||||||
|
"presentation": {
|
||||||
|
"panel": "shared",
|
||||||
|
"group": "test"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
32
index.html
32
index.html
@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<title>Script graph demo</title>
|
<title>Script graph demo</title>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/js-yaml/3.14.0/js-yaml.min.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/js-yaml/3.14.0/js-yaml.min.js"></script>
|
||||||
<script src="index.js" type="module"></script>
|
<script src="index.js" type="module" defer></script>
|
||||||
</head>
|
</head>
|
||||||
<body style="margin: 24px">
|
<body style="margin: 24px">
|
||||||
<style>
|
<style>
|
||||||
@ -35,36 +35,6 @@
|
|||||||
<div>
|
<div>
|
||||||
<div class="card" id="graph">
|
<div class="card" id="graph">
|
||||||
</div>
|
</div>
|
||||||
<div class="card" id="graph2">
|
|
||||||
<script-graph3>
|
|
||||||
<script-graph-node></script-graph-node>
|
|
||||||
<script-graph-node
|
|
||||||
icon="check"
|
|
||||||
></script-graph-node>
|
|
||||||
<script-graph-branch>
|
|
||||||
<script-graph-node
|
|
||||||
icon="check"
|
|
||||||
></script-graph-node>
|
|
||||||
<script-graph3>
|
|
||||||
<script-graph-node
|
|
||||||
icon="check"
|
|
||||||
></script-graph-node>
|
|
||||||
<script-graph-node
|
|
||||||
icon="check"
|
|
||||||
></script-graph-node>
|
|
||||||
</script-graph3>
|
|
||||||
<script-graph-branch>
|
|
||||||
<script-graph-node
|
|
||||||
icon="check"
|
|
||||||
></script-graph-node>
|
|
||||||
<script-graph-node
|
|
||||||
icon="check"
|
|
||||||
></script-graph-node>
|
|
||||||
</script-graph-branch>
|
|
||||||
</script-graph-branch>
|
|
||||||
<script-graph-node></script-graph-node>
|
|
||||||
</script-graph3>
|
|
||||||
</div>
|
|
||||||
<div class="card code">
|
<div class="card code">
|
||||||
<h1> Selected node code </h1>
|
<h1> Selected node code </h1>
|
||||||
<wc-codemirror mode="json" id="snippet">
|
<wc-codemirror mode="json" id="snippet">
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "rollup -c",
|
"build": "rollup -c",
|
||||||
"watch": "rollup -c -w",
|
"watch": "rollup -c --watch",
|
||||||
"serve": "http-server ."
|
"serve": "http-server ."
|
||||||
},
|
},
|
||||||
"author": "",
|
"author": "",
|
||||||
|
@ -1,13 +1,11 @@
|
|||||||
import resolve from "@rollup/plugin-node-resolve";
|
import nodeResolve from "@rollup/plugin-node-resolve";
|
||||||
import typescript from "@rollup/plugin-typescript";
|
import typescript from "@rollup/plugin-typescript";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
input: "./src/main.js",
|
input: "src/main.js",
|
||||||
output: [
|
output: {
|
||||||
{
|
|
||||||
file: "index.js",
|
file: "index.js",
|
||||||
format: "cjs"
|
format: "es",
|
||||||
}
|
},
|
||||||
],
|
plugins: [nodeResolve(), typescript()],
|
||||||
plugins: [resolve(), typescript()]
|
|
||||||
};
|
};
|
||||||
|
118
src/hat-graph/hat-graph-node.ts
Normal file
118
src/hat-graph/hat-graph-node.ts
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
import { css, LitElement, property, svg } from "lit-element";
|
||||||
|
import {
|
||||||
|
mdiCallSplit,
|
||||||
|
mdiAbTesting,
|
||||||
|
mdiCheck,
|
||||||
|
mdiClose,
|
||||||
|
mdiChevronRight,
|
||||||
|
mdiExclamation,
|
||||||
|
mdiTimerOutline,
|
||||||
|
mdiTrafficLight,
|
||||||
|
mdiRefresh,
|
||||||
|
mdiArrowUp,
|
||||||
|
mdiCodeJson,
|
||||||
|
mdiCheckBoxOutline,
|
||||||
|
mdiCheckboxBlankOutline,
|
||||||
|
mdiAsterisk,
|
||||||
|
mdiCircleOutline,
|
||||||
|
} from "@mdi/js";
|
||||||
|
|
||||||
|
const NODE_SIZE = 24;
|
||||||
|
|
||||||
|
const ICONS = {
|
||||||
|
"call-split": mdiCallSplit,
|
||||||
|
"ab-testing": mdiAbTesting,
|
||||||
|
check: mdiCheck,
|
||||||
|
close: mdiClose,
|
||||||
|
"chevron-right": mdiChevronRight,
|
||||||
|
exclamation: mdiExclamation,
|
||||||
|
asterisk: mdiAsterisk,
|
||||||
|
};
|
||||||
|
|
||||||
|
export class HatGraphNode extends LitElement {
|
||||||
|
@property() icon = "chevron-right";
|
||||||
|
@property() iconPath?;
|
||||||
|
|
||||||
|
connectedCallback() {
|
||||||
|
super.connectedCallback();
|
||||||
|
if (!this.hasAttribute("tabindex")) this.setAttribute("tabindex", "0");
|
||||||
|
}
|
||||||
|
|
||||||
|
updateNode(config) {
|
||||||
|
this.dispatchEvent(
|
||||||
|
new CustomEvent("update-node", {
|
||||||
|
detail: { config },
|
||||||
|
bubbles: true,
|
||||||
|
composed: true,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteNode() {
|
||||||
|
this.dispatchEvent(new CustomEvent("delete-node", { bubbles: true }));
|
||||||
|
}
|
||||||
|
|
||||||
|
prependNode(config) {
|
||||||
|
this.dispatchEvent(
|
||||||
|
new CustomEvent("prepend-node", { detail: { config }, bubbles: true })
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
get width() {
|
||||||
|
return NODE_SIZE + 5;
|
||||||
|
}
|
||||||
|
get height() {
|
||||||
|
return NODE_SIZE + 5;
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
return svg`
|
||||||
|
<svg
|
||||||
|
width="${this.width}"
|
||||||
|
height="${this.height}"
|
||||||
|
viewBox="${-this.width / 2} 0 ${this.width} ${this.height}"
|
||||||
|
>
|
||||||
|
<circle
|
||||||
|
cx="0"
|
||||||
|
cy="${this.width / 2}"
|
||||||
|
r="${NODE_SIZE / 2}"
|
||||||
|
/>
|
||||||
|
<g
|
||||||
|
style="pointer-events: none"
|
||||||
|
transform="translate(${-12} ${this.width / 2 - 12})"
|
||||||
|
>
|
||||||
|
${
|
||||||
|
this.iconPath
|
||||||
|
? svg`<path d="${this.iconPath}"/>`
|
||||||
|
: ICONS[this.icon]
|
||||||
|
? svg`<path d="${ICONS[this.icon]}"/>`
|
||||||
|
: ""
|
||||||
|
}
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles() {
|
||||||
|
return css`
|
||||||
|
:host {
|
||||||
|
display: flex;
|
||||||
|
--stroke-clr: var(--stroke-color, rgb(3, 169, 244));
|
||||||
|
--hover-clr: var(--hover-color, rgb(255, 152, 0));
|
||||||
|
}
|
||||||
|
circle {
|
||||||
|
stroke: var(--stroke-clr);
|
||||||
|
stroke-width: 2;
|
||||||
|
fill: white;
|
||||||
|
}
|
||||||
|
:host(:hover) {
|
||||||
|
--stroke-clr: var(--hover-clr);
|
||||||
|
}
|
||||||
|
:host(:focus) {
|
||||||
|
--stroke-clr: green;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define("hat-graph-node", HatGraphNode);
|
162
src/hat-graph/hat-graph.ts
Normal file
162
src/hat-graph/hat-graph.ts
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
import { css, html, LitElement, property, svg } from "lit-element";
|
||||||
|
|
||||||
|
import "./hat-graph-node";
|
||||||
|
|
||||||
|
const BRANCH_HEIGHT = 30;
|
||||||
|
const BRANCH_CURVATURE = 25;
|
||||||
|
const VERTICAL_SPACING = 10;
|
||||||
|
const NODE_SIZE = 24;
|
||||||
|
|
||||||
|
export class HatGraph extends LitElement {
|
||||||
|
@property() _num_items = 0;
|
||||||
|
|
||||||
|
@property({ reflect: true }) branching?;
|
||||||
|
|
||||||
|
get width() {
|
||||||
|
let w = 0;
|
||||||
|
if (this.branching !== undefined) {
|
||||||
|
for (const c of this.children) {
|
||||||
|
if (c.slot === "head") continue;
|
||||||
|
w += (c as any).width;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (const c of this.children) {
|
||||||
|
w = Math.max(w, (c as any).width);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
get height() {
|
||||||
|
let h = 0;
|
||||||
|
if (this.branching !== undefined) {
|
||||||
|
for (const c of this.children) {
|
||||||
|
if (c.slot === "head") continue;
|
||||||
|
h = Math.max(h, (c as any).height);
|
||||||
|
}
|
||||||
|
h += 2 * BRANCH_HEIGHT;
|
||||||
|
} else {
|
||||||
|
for (const c of this.children) {
|
||||||
|
h += (c as any).height + VERTICAL_SPACING;
|
||||||
|
}
|
||||||
|
h;
|
||||||
|
}
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateChildren() {
|
||||||
|
this._num_items = this.children.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
let branch_x = [];
|
||||||
|
let total = 0;
|
||||||
|
if (this.branching !== undefined) {
|
||||||
|
for (const c of Array.from(this.children)) {
|
||||||
|
if (c.slot === "head") continue;
|
||||||
|
const rect = c.getBoundingClientRect();
|
||||||
|
branch_x.push(rect.width / 2 + total);
|
||||||
|
total += rect.width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const line_end = this.height - BRANCH_HEIGHT;
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<svg width="${this.width}" height="${this.height}">
|
||||||
|
<rect
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
width="${this.width}"
|
||||||
|
height="${this.height}"
|
||||||
|
fill="white"
|
||||||
|
/>
|
||||||
|
${this.branching !== undefined
|
||||||
|
? branch_x.map((x) => {
|
||||||
|
return svg`
|
||||||
|
<path
|
||||||
|
class="line"
|
||||||
|
d="
|
||||||
|
M ${this.width / 2} 0
|
||||||
|
C ${this.width / 2} ${BRANCH_CURVATURE}
|
||||||
|
${x} ${BRANCH_HEIGHT - BRANCH_CURVATURE}
|
||||||
|
${x} ${BRANCH_HEIGHT}
|
||||||
|
L ${x} ${line_end}
|
||||||
|
C ${x} ${line_end + BRANCH_CURVATURE}
|
||||||
|
${this.width / 2} ${this.height - BRANCH_CURVATURE}
|
||||||
|
${this.width / 2} ${this.height}
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
`;
|
||||||
|
})
|
||||||
|
: svg`
|
||||||
|
<path
|
||||||
|
class="line"
|
||||||
|
d="
|
||||||
|
M ${this.width / 2} 0
|
||||||
|
L ${this.width / 2} ${this.height}
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
`}
|
||||||
|
</svg>
|
||||||
|
<slot name="head"> </slot>
|
||||||
|
<div
|
||||||
|
id="branches"
|
||||||
|
class="${this.querySelector(":scope > [slot='head']") ? "" : "no-head"}"
|
||||||
|
>
|
||||||
|
<slot @slotchange=${this.updateChildren}></slot>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles() {
|
||||||
|
return css`
|
||||||
|
:host {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
--stroke-clr: var(--stroke-color, rgb(3, 169, 244));
|
||||||
|
--hover-clr: var(--hover-color, rgb(255, 152, 0));
|
||||||
|
}
|
||||||
|
#branches {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
:host([branching]) #branches {
|
||||||
|
top: ${BRANCH_HEIGHT}px;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: start;
|
||||||
|
}
|
||||||
|
:host(:not([branching])) #branches {
|
||||||
|
top: ${VERTICAL_SPACING + NODE_SIZE}px; /* SHould be something else*/
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
:host(:not([branching])) #branches.no-head {
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
path.line {
|
||||||
|
stroke: var(--stroke-clr);
|
||||||
|
stroke-width: 2;
|
||||||
|
fill: none;
|
||||||
|
}
|
||||||
|
:host(:not([branching])) ::slotted(*) {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
::slotted(:last-child) {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
::slotted([slot="head"]) {
|
||||||
|
position: absolute;
|
||||||
|
top: ${BRANCH_HEIGHT / 2}px;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
}
|
||||||
|
:host(:focus-within) ::slotted([slot="head"]) {
|
||||||
|
--stroke-color: green;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define("hat-graph", HatGraph);
|
193
src/hat-graph/make-graph.ts
Normal file
193
src/hat-graph/make-graph.ts
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
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`
|
||||||
|
<hat-graph-node slot="head" .iconPath=${mdiAbTesting} @focus=${focused}>
|
||||||
|
</hat-graph-node>
|
||||||
|
<hat-graph-node .iconPath=${mdiCheck} @focus=${focused}></hat-graph-node>
|
||||||
|
<hat-graph-node .iconPath=${mdiClose} @focus=${focused}></hat-graph-node>
|
||||||
|
`,
|
||||||
|
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`
|
||||||
|
<hat-graph-node slot="head" iconPath="${mdiCallSplit}" @focus=${focused}>
|
||||||
|
</hat-graph-node>
|
||||||
|
${config.choose?.map((branch) => {
|
||||||
|
return html`
|
||||||
|
<hat-graph>
|
||||||
|
<hat-graph-node
|
||||||
|
slot="head"
|
||||||
|
.iconPath=${mdiCheckBoxOutline}
|
||||||
|
@focus=${focused}
|
||||||
|
></hat-graph-node>
|
||||||
|
${branch.sequence.map((node) => makeNode(node))}
|
||||||
|
</hat-graph>
|
||||||
|
`;
|
||||||
|
})}
|
||||||
|
<hat-graph>
|
||||||
|
<hat-graph-node
|
||||||
|
slot="head"
|
||||||
|
.iconPath=${mdiCheckboxBlankOutline}
|
||||||
|
@focus=${focused}
|
||||||
|
></hat-graph-node>
|
||||||
|
${config.default.map((node) => makeNode(node))}
|
||||||
|
</hat-graph>
|
||||||
|
`,
|
||||||
|
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`
|
||||||
|
<hat-graph-node
|
||||||
|
.iconPath=${mdiArrowUp}
|
||||||
|
@focus=${focused}
|
||||||
|
></hat-graph-node>
|
||||||
|
<hat-graph>
|
||||||
|
${config.repeat.sequence.map((node) => makeNode(node))}
|
||||||
|
</hat-graph>
|
||||||
|
`,
|
||||||
|
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;
|
||||||
|
}
|
75
src/main.js
75
src/main.js
@ -1,8 +1,11 @@
|
|||||||
import {demoConfig} from "./demo-config";
|
import { demoConfig2 } from "./demo-config";
|
||||||
import "@vanillawc/wc-codemirror";
|
import "@vanillawc/wc-codemirror";
|
||||||
|
|
||||||
import "./script-graph";
|
import "./script-graph";
|
||||||
import "./script-graph3";
|
// import "./script-graph3";
|
||||||
|
import "./hat-graph/hat-graph-node";
|
||||||
|
import "./hat-graph/hat-graph";
|
||||||
|
import { makeGraph } from "./hat-graph/make-graph";
|
||||||
|
|
||||||
import { ActionHandler } from "./script-to-graph";
|
import { ActionHandler } from "./script-to-graph";
|
||||||
|
|
||||||
@ -12,7 +15,7 @@ let index_counter = 0;
|
|||||||
let nodes = [];
|
let nodes = [];
|
||||||
|
|
||||||
window.onload = () => {
|
window.onload = () => {
|
||||||
|
return;
|
||||||
//const graph2 = document.createElement("script-graph3");
|
//const graph2 = document.createElement("script-graph3");
|
||||||
//document.querySelector("#graph2").appendChild(graph2);
|
//document.querySelector("#graph2").appendChild(graph2);
|
||||||
|
|
||||||
@ -20,10 +23,10 @@ window.onload = () => {
|
|||||||
|
|
||||||
const fullcode = document.querySelector("#fullcode");
|
const fullcode = document.querySelector("#fullcode");
|
||||||
fullcode.mode = "yaml";
|
fullcode.mode = "yaml";
|
||||||
window.setTimeout(()=> fullcode.value = jsyaml.safeDump(src), 100);
|
window.setTimeout(() => (fullcode.value = jsyaml.safeDump(src)), 100);
|
||||||
|
|
||||||
const updateButton = document.querySelector("#updateButton");
|
const updateButton = document.querySelector("#updateButton");
|
||||||
updateButton.addEventListener('click', () => {
|
updateButton.addEventListener("click", () => {
|
||||||
src = jsyaml.safeLoad(fullcode.value);
|
src = jsyaml.safeLoad(fullcode.value);
|
||||||
index_counter = 0;
|
index_counter = 0;
|
||||||
nodes = [];
|
nodes = [];
|
||||||
@ -43,11 +46,67 @@ window.onload = () => {
|
|||||||
graph.tree = tr.graph;
|
graph.tree = tr.graph;
|
||||||
const code = document.querySelector("#snippet");
|
const code = document.querySelector("#snippet");
|
||||||
code.value = jsyaml.safeDump(action);
|
code.value = jsyaml.safeDump(action);
|
||||||
document.querySelector("#saveSnippet").onclick = () => update(jsyaml.safeLoad(code.value));
|
document.querySelector("#saveSnippet").onclick = () =>
|
||||||
document.querySelector("#deleteSnippet").onclick = () => update(jsyaml.safeLoad(null));
|
update(jsyaml.safeLoad(code.value));
|
||||||
}
|
document.querySelector("#deleteSnippet").onclick = () =>
|
||||||
|
update(jsyaml.safeLoad(null));
|
||||||
|
};
|
||||||
|
|
||||||
graph.tree = tr.graph;
|
graph.tree = tr.graph;
|
||||||
document.querySelector("#graph").appendChild(graph);
|
document.querySelector("#graph").appendChild(graph);
|
||||||
|
};
|
||||||
|
|
||||||
|
function nodeSelected(ev) {
|
||||||
|
console.log(ev);
|
||||||
|
const code = document.querySelector("#snippet");
|
||||||
|
code.value = jsyaml.safeDump(ev.detail.config);
|
||||||
|
code.currentNode = ev.target;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function rebuildGraph(config) {
|
||||||
|
const graphCard = document.querySelector("#graph");
|
||||||
|
|
||||||
|
while (graphCard.firstChild) graphCard.removeChild(graphCard.firstChild);
|
||||||
|
|
||||||
|
const graph = makeGraph(config);
|
||||||
|
graph.addEventListener("node-selected", nodeSelected);
|
||||||
|
graph.addEventListener("update-node", (ev) => {
|
||||||
|
const code = document.querySelector("#fullcode");
|
||||||
|
code.value = jsyaml.safeDump(ev.detail.config);
|
||||||
|
rebuildGraph(ev.detail.config);
|
||||||
|
});
|
||||||
|
|
||||||
|
graphCard.appendChild(graph);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setup() {
|
||||||
|
let src = demoConfig2;
|
||||||
|
const fullcode = document.querySelector("#fullcode");
|
||||||
|
fullcode.mode = "yaml";
|
||||||
|
window.setTimeout(() => (fullcode.value = jsyaml.safeDump(src)), 100);
|
||||||
|
|
||||||
|
rebuildGraph(src);
|
||||||
|
|
||||||
|
const updateButton = document.querySelector("#updateButton");
|
||||||
|
updateButton.addEventListener("click", () => {
|
||||||
|
src = jsyaml.safeLoad(fullcode.value);
|
||||||
|
rebuildGraph(src);
|
||||||
|
});
|
||||||
|
|
||||||
|
document.querySelector("#saveSnippet").onclick = () => {
|
||||||
|
const code = document.querySelector("#snippet");
|
||||||
|
console.log(code.currentNode);
|
||||||
|
if (code.currentNode) {
|
||||||
|
code.currentNode.updateNode(jsyaml.safeLoad(code.value));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
document.querySelector("#deleteSnippet").onclick = () => {
|
||||||
|
const code = document.querySelector("#snippet");
|
||||||
|
console.log(code.currentNode);
|
||||||
|
if (code.currentNode) {
|
||||||
|
code.currentNode.deleteNode();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
setup();
|
||||||
|
@ -1,18 +1,9 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "es6",
|
"target": "es2017",
|
||||||
"module": "ESNext",
|
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"sourceMap": true,
|
"resolveJsonModule": true,
|
||||||
"emitDecoratorMetadata": true,
|
"allowSyntheticDefaultImports": true,
|
||||||
"experimentalDecorators": true,
|
"experimentalDecorators": true
|
||||||
"removeComments": false,
|
}
|
||||||
"noImplicitAny": false
|
|
||||||
},
|
|
||||||
"include": [
|
|
||||||
"src/**/*.ts"
|
|
||||||
],
|
|
||||||
"exclude": [
|
|
||||||
"node_modules"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user