'use strict'; import React, {Component} from "react"; import jsonLogic from 'json-logic-js'; import {useState, useEffect} from 'react'; import {useClickAway} from "@uidotdev/usehooks"; import {OverlayTrigger, Tooltip} from "react-bootstrap"; // https://stackoverflow.com/a/70511311 const trueTypeOf = (obj) => Object.prototype.toString.call(obj).slice(8, -1).toLowerCase(); class Radio extends Component { constructor(props) { super(props); // Initialize the state object with the initial values from the props this.state = { variant: props.outvar in props.data ? props.data[props.outvar] : props.variants[props.fallback ? props.fallback : 0], }; // Bind the event handler to this this.handleClick = this.handleClick.bind(this); this.props.target.construct(this.props.outvar, this.state.variant); } componentWillUnmount() { this.props.target.unmount(this.props.outvar); } handleClick(variant) { // Update the state object with the new value for outvar this.setState({ ...this.state, variant: variant }); this.props.target.update(this.props.outvar, variant); } render() { let key = this.props.id + this.props.outvar; return (
{this.props.icon ? : null} {this.props.title}
{ this.props.tip ? ( {this.props.tip} }> ) : null } {this.props.variants.map((variant, _) => (
this.handleClick(variant)} onChange={() => this.handleClick(variant)} />
))}
); } } function RadioWrapper(target, id, data, {title, variants, outvar, fallback, icon, tip}) { return ; } class Switch extends Component { constructor(props) { super(props); // Initialize the state object with the initial values from the props this.state = { checked: props.outvar in props.data ? !!(props.data[props.outvar]) : !!(props.fallback) }; // Bind the event handler to this this.handleClick = this.handleClick.bind(this); this.props.target.construct(this.props.outvar, this.state.checked); } componentWillUnmount() { this.props.target.unmount(this.props.outvar); } handleClick() { // Update the state object with the new value for outvar let new_checked = !this.state.checked; this.setState({ checked: new_checked }); this.props.target.update(this.props.outvar, new_checked); } render() { let key = this.props.id + this.props.outvar; return (
{ this.props.tip ? ( {this.props.tip} }> ) : null }
); } } function SwitchWrapper(target, id, data, {title, fallback, outvar, icon, tip}) { return ; } class Line extends Component { constructor(props) { super(props); // Initialize the state object with the initial values from the props this.state = { text: props.outvar in props.data ? props.data[props.outvar] : (props.fallback ? props.fallback : "") }; // Bind the event handler to this this.handleClick = this.handleClick.bind(this); this.props.target.construct(this.props.outvar, this.state.text); } componentWillUnmount() { this.props.target.unmount(this.props.outvar); } handleClick(element) { let text = element.target.value; this.setState({ text: text }); this.props.target.update(this.props.outvar, text); } render() { let key = this.props.id + this.props.outvar; return (
{ this.props.tip ? ( {this.props.tip} }> ) : null }
); } } function LineWrapper(target, id, data, {title, fallback, outvar, icon, tip}) { return ; } class SwitchLine extends Component { constructor(props) { super(props); // Initialize the state object with the initial values from the props this.state = { text: props.outvar in props.data ? props.data[props.outvar].text : (props.fallback ? props.fallback.text : ""), checked: props.outvar in props.data ? props.data[props.outvar].checked : (props.fallback ? props.fallback.checked : false) }; // Bind the event handler to this this.handleText = this.handleText.bind(this); this.handleCheck = this.handleCheck.bind(this); this.props.target.construct(this.props.outvar, this.state); } componentWillUnmount() { this.props.target.unmount(this.props.outvar); } handleText(element) { let new_state = { ...this.state, text: element.target.value } this.setState(new_state); this.props.target.update(this.props.outvar, new_state); } handleCheck() { // Update the state object with the new value for outvar let new_state = { ...this.state, checked: !this.state.checked } this.setState(new_state); this.props.target.update(this.props.outvar, new_state); } render() { let key = this.props.id + this.props.outvar; return (
{ this.props.tip ? ( {this.props.tip} }> ) : null }
); } } function SwitchLineWrapper(target, id, data, {title, fallback, outvar, icon, tip}) { return ; } function UnimplementedComponent(type, id) { //console.error("Missing component with type:", type) return
UNIMPLEMENTED
} const componentsList = { "Radio": RadioWrapper, "Switch": SwitchWrapper, "Line": LineWrapper, "SwitchLine": SwitchLineWrapper, "Default": UnimplementedComponent, }; export function ProcessOptions({options, data, target, id}) { let options_t = trueTypeOf(options); if (options_t === "array") { return Array.from( options.map((option_item, i) => ProcessOptions({ options: option_item, data: data, target: target, id: id + i })) ); } else if (options_t === "object") { if ( trueTypeOf(options.type) === "string" && (trueTypeOf(options.args) === "object" || trueTypeOf(options.items) === "array") ) { if (options.type in componentsList) { return componentsList[options.type](target, id + options.type, data, options.args); } else if (options.type === "Group") { return (
{ ProcessOptions({options: jsonLogic.apply(options.items, data), data: data, target: target, id: id}) }
); } else { return componentsList["Default"](options.type, id + "missing"); } } else { return ProcessOptions({options: jsonLogic.apply(options, data), data: data, target: target, id: id}); } } } export function OptionsDialogPopup({options, data, target, id, big}) { const [show, setShow] = useState(false); const ref = useClickAway((e) => { if (e.type === "mousedown") // ignore touchstart setShow(false) } ); let div_classes = "overlayVariant border rounded " + (big ? "overlay-bigcard" : "overlay-smallcard") const handleClick = (event) => { setShow(!show); }; return (
); } export function OptionsSummaryPopup({id, data}) { const [show, setShow] = useState(false); const [position, setPosition] = useState({x: 0, y: 0}); const [size, setSize] = useState({w: 0, h: 0}); const close = () => { setShow(false); document.removeEventListener("scroll", reposition, true); } const ref = useClickAway(close); const reposition = () => { console.trace("reposition") let popup_button = document.getElementById(id + "img"); let rect = popup_button.getBoundingClientRect() let pos_x = (rect.left + rect.right) / 2; let pos_y = (rect.top + rect.bottom) / 2; console.trace("reposition", pos_x, pos_y) if (pos_x + size.w > window.innerWidth) { setPosition({x: pos_x - size.w - 20, y: pos_y - size.h / 2}); } else { setPosition({x: pos_x - size.w / 2, y: pos_y - size.h - 20}); } } useEffect(() => { if (show) { let popup = document.getElementById(id); let width = popup.offsetWidth; let height = popup.offsetHeight; setSize({w: width, h: height}); reposition() } }, [show]) useEffect(() => { if (show) { reposition(); } }, [show, size]) const handleClick = (event) => { setShow(!show); if (!show) { document.addEventListener("scroll", reposition, true); } }; const stringify = (value) => { let value_type = trueTypeOf(value); if (value_type === "string") { return value; } else if (value_type === "object") { if (value.checked === false) { return "off"; } else if (value.checked === true && value.text) { return value.text; } } return JSON.stringify(value); } return (
{Array.from(Object.entries(data) .filter(([key, value], _) => key !== "ext_data") .map(([key, value], _) => { return (

{key}: {stringify(value)}

); }))}
); } export function fill_ext_data(data, index) { return { has_other_dio: data.filter((value, item_index) => index !== item_index && value.name.endsWith("-TTL")).length > 0, has_dds: data.filter(((value, _) => value.name === "DDS" )).length > 0, has_sampler: data.filter(((value, _) => value.name === "Sampler" )).length > 0 } }