// @flow import React from "react"; import keys from "lodash/keys"; import map from "lodash/map"; import throttle from "lodash/throttle"; import { renderRawIcon } from "config/icon"; import ListItemSecondaryAction from "@material-ui/core/ListItemSecondaryAction"; import ListItemText from "@material-ui/core/ListItemText"; import ListSubheader from "@material-ui/core/ListSubheader"; import Switch from "@material-ui/core/Switch"; import Input from "@material-ui/core/Input"; import InputLabel from "@material-ui/core/InputLabel"; import FormControl from "@material-ui/core/FormControl"; import Select from "@material-ui/core/Select"; import MenuItem from "@material-ui/core/MenuItem"; import Button from "@material-ui/core/Button"; import LinearProgress from "@material-ui/core/LinearProgress"; import SliderComponent from "@material-ui/lab/Slider"; import type { UIControl, UIToggle, UIDropDown, UILink, UISection, UIText, UIProgress, UISlider } from "config/flowtypes"; import keyOf from "utils/keyOf"; type UiItemProps = { item: I, state: State, onChangeState: (topic: string, nextState: string) => void }; // eslint-disable-next-line flowtype/no-weak-types export default class UiItem extends React.PureComponent> { constructor(props: UiItemProps) { super(props); } runPrimaryAction() { } render() { return null; } /* * TODO: The type system can't really check if the enableCondition is of * any function type or if it is a TopicDependentOption or a * StateDependentOption. This should be fixed. */ isEnabled() { if (Object.keys(this.props.item).includes("enableCondition") && typeof this.props.item.enableCondition == "function") { const enableCondition = this.props.item.enableCondition; const state = this.props.state; return enableCondition(state); } else { return true; } } } export class UiControl extends UiItem { constructor(props: UiItemProps) { super(props); } changeState(next: string) { if (this.props.item.topic == null) { throw new Error( `Missing topic in ${this.props.item.type} "${this.props.item.text}"` ); } this.debouncedChange(next); } debouncedChange = throttle((next: string) => this.props.onChangeState(this.props.item.topic, next), 50, { leading: true, trailing: true }); getValue() { const control = this.props.item; const topic: string = control.topic || ""; const value = this.props.state[topic]; if (value == null) { if (topic === "") { throw new Error( `Missing topic in ${control.type} "${control.text}"` ); } throw new Error( `Unknown topic "${topic}" in ${control.type} "${control.text}"` ); } return value; } } export class Toggle extends UiControl { isToggled = () => { const value = this.getValue(); const control = this.props.item; const isChecked = control.toggled || ((i, _s) => i === (control.on || "on")); const checked = isChecked(value, this.props.state); return checked; } runPrimaryAction = () => { if (this.isEnabled()) { const control = this.props.item; const toggled = this.isToggled(); const on = control.on == null ? "on" : control.on; const off = control.off == null ? "off" : control.off; const next = toggled ? off : on; this.changeState(next); } } render() { return [ , ]; } } export class DropDown extends UiControl { runPrimaryAction = (next?: string) => { if (this.isEnabled()) { const control = this.props.item; const optionKeys = keys(control.options); const value = this.getValue(); const valueIndex = keyOf(optionKeys, value); if (next == null) { this.changeState(optionKeys[(valueIndex + 1) % optionKeys.length]); } else { this.changeState(next); } } } render() { const control = this.props.item; const value = this.getValue(); const id = `${control.topic}-${control.text}`; const options = control.options; if (options == null) { throw new Error( `Parameter "options" missing for ${control.type} "${control.text}"` ); } return ( {control.text} } > {map(options, (v, k) => {v})} ); } } export class Slider extends UiControl { runPrimaryAction = (e: ?Event, v: ?number) => { if (v != null) { this.changeState(v.toString()); } } render() { return [ , ]; } } export class Link extends UiItem { runPrimaryAction = () => { const control = this.props.item; if (control.link == null) { throw new Error( `Parameter "link" missing for ${control.type} "${control.text}"` ); } if (this.isEnabled()) { window.open(control.link, "_blank"); } } render() { return ( ); } } export class Section extends UiItem { render() { return ( {this.props.item.text} ); } } export class Text extends UiControl { render() { return [ , ]; } } export class Progress extends UiControl { render() { const min = this.props.item.min || 0; const max = this.props.item.max || 100; const val = parseFloat(this.getValue()); const value = val * 100 / max - min; return [ ,
]; } }