Comitt of all things done before I forgot about it. beginnings of a restructuring, I think...
This commit is contained in:
		
							parent
							
								
									14ec3e37da
								
							
						
					
					
						commit
						65d391e050
					
				@ -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">
 | 
				
			||||||
 | 
				
			|||||||
@ -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");
 | 
				
			||||||
 | 
				
			|||||||
@ -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
									
								
							
							
						
						
									
										110
									
								
								src/script-graph3.ts
									
									
									
									
									
										Normal 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);
 | 
				
			||||||
@ -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
									
								
							
							
						
						
									
										70
									
								
								src/types.ts
									
									
									
									
									
										Normal 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;
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user