Comitt of all things done before I forgot about it. beginnings of a restructuring, I think...

This commit is contained in:
Thomas Lovén 2021-03-09 15:07:31 +01:00
parent 14ec3e37da
commit 65d391e050
6 changed files with 213 additions and 15 deletions

View File

@ -35,6 +35,11 @@
<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-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">

View File

@ -2,6 +2,7 @@ import {demoConfig} from "./demo-config";
import "@vanillawc/wc-codemirror"; import "@vanillawc/wc-codemirror";
import "./script-graph"; import "./script-graph";
import "./script-graph3";
import { ActionHandler } from "./script-to-graph"; import { ActionHandler } from "./script-to-graph";
@ -12,6 +13,9 @@ let nodes = [];
window.onload = () => { window.onload = () => {
const graph2 = document.createElement("script-graph3");
document.querySelector("#graph2").appendChild(graph2);
let src = demoConfig; let src = demoConfig;
const fullcode = document.querySelector("#fullcode"); const fullcode = document.querySelector("#fullcode");

View File

@ -11,9 +11,9 @@ import { mdiPlus } from "@mdi/js";
const SIZE = 35; const SIZE = 35;
const DIST = 20; const DIST = 20;
interface TreeNode { export interface TreeNode {
icon: String; icon: String;
styles: String; styles?: String;
end?: Boolean; end?: Boolean;
children?: (TreeNode | TreeNode[])[]; children?: (TreeNode | TreeNode[])[];
clickCallback?: any; clickCallback?: any;

110
src/script-graph3.ts Normal file
View File

@ -0,0 +1,110 @@
import {
LitElement,
html,
css,
svg,
property,
TemplateResult
} from "lit-element";
import { mdiAsterisk } from "@mdi/js";
const SIZE = 35;
const DIST = 20;
interface GraphNode extends LitElement{
render_svg(): TemplateResult;
width: number;
height: number;
}
class ScriptGraphNode extends LitElement {
@property() icon = mdiAsterisk;
get width() {
return SIZE;
}
get height() {
return SIZE + DIST;
}
render_svg() {
return svg`
<circle
cx="0"
cy="${this.width/2}"
r="${SIZE/2}"
/>
<g style="pointer-events: none" transform="translate(-12, ${this.width/2-12})">
</g>
`
}
}
class ScriptGraph3 extends LitElement {
@property() content = [];
@property() _width = 0;
@property() _height = 0;
connectedCallback() {
super.connectedCallback();
console.log(this.querySelectorAll('*'))
}
async updateChildren() {
this.content = [];
let y = 0;
let w = 0;
for (const e of this.querySelectorAll('*') as NodeListOf<GraphNode>) {
this.content.push({
svg: e.render_svg(),
offset_y: y,
});
y += e.height;
w = Math.max(w, e.width);
}
this._width = w;
this._height = y;
this.requestUpdate();
}
childrenChangedCallback() {
console.log("Children changed");
}
render() {
let y = 0;
let nodes = [];
for (const e of this.content) {
}
return html`
<svg width=500 height=500>
${this.content.map(e =>
svg`
<g transform="translate(${this._width/2} ${e.offset_y})">
${e.svg}
</g>
`)}
</svg>
<slot
@slotchange=${this.updateChildren}
></slot>
<style>
slot {
display: none;
}
</style>
`
}
}
customElements.define("script-graph3", ScriptGraph3);
customElements.define("script-graph-node", ScriptGraphNode);

View File

@ -32,6 +32,9 @@ const ICONS = {
YAML: mdiCodeJson, YAML: mdiCodeJson,
}; };
import { TreeNode} from "./script-graph";
import { Action } from "./types";
const OPTIONS = [ const OPTIONS = [
"condition", "condition",
"delay", "delay",
@ -44,10 +47,14 @@ const OPTIONS = [
"choose", "choose",
]; ];
interface NodeHandler {
(action, selected: any[], select, update): TreeNode;
}
const SPECIAL = { const SPECIAL = {
condition: (action, selected, select, update) => { condition: (action, selected, select, update) => {
return { return {
icon: ICONS["choose"], icon: ICONS["condition"],
clickCallback: () => select([1], action, update), clickCallback: () => select([1], action, update),
children: [ children: [
{ {
@ -164,13 +171,16 @@ const SPECIAL = {
}; };
interface NoAction {
}
export class ActionHandler { export class ActionHandler {
_actions = []; _actions: (Action | NoAction)[] = [];
updateCallback = null; updateCallback = null;
selectCallback = null; selectCallback = null;
selected = []; selected: number[] = [];
constructor(actions = []) { constructor(actions: (Action | NoAction)[] = []) {
this._actions = actions; this._actions = actions;
} }
@ -184,10 +194,10 @@ export class ActionHandler {
} }
get graph() { get graph() {
return this.actions.map((_, idx) => this._make_graph_node(idx)); return this.actions.map((action, idx) => this._make_graph_node(idx, action));
} }
_update_action(idx, action) { _update_action(idx: number, action) {
if(action === null) if(action === null)
this.actions.splice(idx, 1); this.actions.splice(idx, 1);
else else
@ -196,21 +206,20 @@ export class ActionHandler {
this.updateCallback(this.actions); this.updateCallback(this.actions);
} }
_add_action(idx) { _add_action(idx: number) {
this.actions.splice(idx, 0, {}); this.actions.splice(idx, 0, {});
if (this.updateCallback) if (this.updateCallback)
this.updateCallback(this.actions); this.updateCallback(this.actions);
this._select_node([idx], {}, (a) =>this._update_action(idx, a)); this._select_node([idx], {}, (a) =>this._update_action(idx, a));
} }
_select_node(idx, action, update=null) { _select_node(path: number[], action, update=null) {
this.selected = idx; this.selected = path;
if (this.selectCallback) if (this.selectCallback)
this.selectCallback(idx, action, update); this.selectCallback(path, action, update);
} }
_make_graph_node(idx) { _make_graph_node(idx: number, action): TreeNode {
const action = this.actions[idx] || {};
let _type = "yaml"; let _type = "yaml";
if (Object.keys(action).length === 0) if (Object.keys(action).length === 0)
_type = "new"; _type = "new";
@ -218,7 +227,7 @@ export class ActionHandler {
_type = OPTIONS.find((option) => option in action) || "YAML"; _type = OPTIONS.find((option) => option in action) || "YAML";
const selected = this.selected.length >= 1 && this.selected[0] == idx; const selected = this.selected.length >= 1 && this.selected[0] == idx;
let node = {}; let node: TreeNode = {icon: ""};
if (_type in SPECIAL) { if (_type in SPECIAL) {
node = SPECIAL[_type]( node = SPECIAL[_type](

70
src/types.ts Normal file
View File

@ -0,0 +1,70 @@
export interface Condition {
condition: string;
}
export interface EventAction {
event: string;
event_data?: { [key: string]: any };
event_data_template?: { [key: string]: any };
}
export interface ServiceAction {
service: string;
entity_id?: string;
data?: { [key: string]: any };
}
export interface DeviceAction {
device_id: string;
domain: string;
entity_id: string;
}
export interface DelayAction {
delay: number;
}
export interface SceneAction {
scene: string;
}
export interface WaitAction {
wait_template: string;
timeout?: number;
}
export interface RepeatAction {
repeat: CountRepeat | WhileRepeat | UntilRepeat;
}
interface BaseRepeat {
sequence: Action[];
}
export interface CountRepeat extends BaseRepeat {
count: number;
}
export interface WhileRepeat extends BaseRepeat {
while: Condition[];
}
export interface UntilRepeat extends BaseRepeat {
until: Condition[];
}
export interface ChooseAction {
choose: [{ conditions: Condition[]; sequence: Action[] }];
default?: Action[];
}
export type Action =
| EventAction
| DeviceAction
| ServiceAction
| Condition
| DelayAction
| SceneAction
| WaitAction
| RepeatAction
| ChooseAction;