'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 true_type_of = (obj) => Object.prototype.toString.call(obj).slice(8, -1).toLowerCase(); function Tip({id, tip}) { return ( {tip}} > ); } 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); } 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 && } {this.props.title}
{this.props.tip && } {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); } 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 && }
); } } 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); } 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 && }
); } } 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); } 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 && }
); } } 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 = true_type_of(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 ( true_type_of(options.type) === "string" && (true_type_of(options.args) === "object" || true_type_of(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 FilterOptions(options, data) { let options_t = true_type_of(options); let target = {}; if (options_t === "array") { options.map((option_item, _) => { Object.assign(target, FilterOptions(option_item, data)) }); } else if (options_t === "object") { if ( true_type_of(options.type) === "string" && (true_type_of(options.args) === "object" || true_type_of(options.items) === "array") ) { if (options.type in componentsList) { target[options.args.outvar] = data[options.args.outvar]; } else if (options.type === "Group") { Object.assign(target, FilterOptions(jsonLogic.apply(options.items, data), data)) } } else { Object.assign(target, FilterOptions(jsonLogic.apply(options, data), data)) } } return target } export function OptionsDialogPopup({options, data, target, id, big, first, last, options_class}) { 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"} ${(!big && first) ? "overlay-first" : ""} ${(!big && last) ? "overlay-last" : ""} ${options_class || ""}`; const handleClick = (event) => { setShow(!show); }; return (
); } export function OptionsSummaryPopup({id, options, data}) { const [show, setShow] = useState(false); const [position, setPosition] = useState({x: 0, y: 0}); const [size, setSize] = useState({w: 0, h: 0}); let display_options = FilterOptions(options, data); const close = () => { setShow(false); document.removeEventListener("scroll", handleScroll, true); } const ref = useClickAway(close); const reposition = () => { let popup_button = document.getElementById(id + "img"); if (!popup_button) { document.removeEventListener("scroll", handleScroll, true); return; } let rect = popup_button.getBoundingClientRect() let pos_x = (rect.left + rect.right) / 2; let pos_y = (rect.top + rect.bottom) / 2; 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}); } } const handleScroll = (e) => { if (e.target !== document.getElementById(id)) { close(); } } 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", handleScroll, true); } }; const stringify = (value) => { let value_type = true_type_of(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(display_options) .filter(([key, value], _) => key !== "ext_data") .map(([key, value], _) => { return (

{key}: {stringify(value)}

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