From babd967eb8ac62c4a6ff6734ff57e46faaa5bab6 Mon Sep 17 00:00:00 2001
From: Maximilian Hils <git@maximilianhils.com>
Date: Mon, 17 Jul 2017 20:46:28 +0200
Subject: [web] options: make help and err permanently visible, improve perf

---
 web/src/js/components/Modal/Option.jsx | 121 +++++++++++++++++++++++++++++++++
 1 file changed, 121 insertions(+)
 create mode 100644 web/src/js/components/Modal/Option.jsx

(limited to 'web/src/js/components/Modal/Option.jsx')

diff --git a/web/src/js/components/Modal/Option.jsx b/web/src/js/components/Modal/Option.jsx
new file mode 100644
index 00000000..1aca23c2
--- /dev/null
+++ b/web/src/js/components/Modal/Option.jsx
@@ -0,0 +1,121 @@
+import React, { Component } from "react"
+import PropTypes from "prop-types"
+import { connect } from "react-redux"
+import { update as updateOptions } from "../../ducks/options"
+import { Key } from "../../utils"
+
+const stopPropagation = e => {
+    if (e.keyCode !== Key.ESC) {
+        e.stopPropagation()
+    }
+}
+
+BooleanOption.PropTypes = {
+    value: PropTypes.bool.isRequired,
+    onChange: PropTypes.func.isRequired,
+}
+function BooleanOption({ value, onChange, ...props }) {
+    return (
+        <input type="checkbox"
+               checked={value}
+               onChange={e => onChange(e.target.checked)}
+               {...props}
+        />
+    )
+}
+
+StringOption.PropTypes = {
+    value: PropTypes.string.isRequired,
+    onChange: PropTypes.func.isRequired,
+}
+function StringOption({ value, onChange, ...props }) {
+    return (
+        <input type="text"
+               value={value || ""}
+               onChange={e => onChange(e.target.value)}
+               {...props}
+        />
+    )
+}
+
+NumberOption.PropTypes = {
+    value: PropTypes.number.isRequired,
+    onChange: PropTypes.func.isRequired,
+}
+function NumberOption({ value, onChange, ...props }) {
+    return (
+        <input type="number"
+               value={value}
+               onChange={(e) => onChange(parseInt(e.target.value))}
+               {...props}
+        />
+    )
+}
+
+ChoicesOption.PropTypes = {
+    value: PropTypes.string.isRequired,
+    onChange: PropTypes.func.isRequired,
+}
+function ChoicesOption({ value, onChange, choices, ...props }) {
+    return (
+        <select
+            onChange={(e) => onChange(e.target.value)}
+            selected={value}
+            {...props}
+        >
+            { choices.map(
+                choice => (
+                    <option key={choice} value={choice}>{choice}</option>
+                )
+            )}
+        </select>
+    )
+}
+
+StringSequenceOption.PropTypes = {
+    value: PropTypes.string.isRequired,
+    onChange: PropTypes.func.isRequired,
+}
+function StringSequenceOption({ value, onChange, ...props }) {
+    const height = Math.max(value.length, 1)
+    return <textarea
+        rows={height}
+        value={value.join("\n")}
+        onChange={e => onChange(e.target.value.split("\n"))}
+        {...props}
+    />
+}
+
+const Options = {
+    "bool": BooleanOption,
+    "str": StringOption,
+    "int": NumberOption,
+    "optional str": StringOption,
+    "sequence of str": StringSequenceOption,
+}
+
+function PureOption({ choices, type, value, onChange }) {
+    if (choices) {
+        return <ChoicesOption
+            value={value}
+            onChange={onChange}
+            choices={choices}
+            onKeyDown={stopPropagation}
+        />
+    }
+    const Opt = Options[type]
+    return <Opt
+        value={value}
+        onChange={onChange}
+        onKeyDown={stopPropagation}
+    />
+}
+export default connect(
+    (state, { name }) => ({
+        ...state.options[name],
+        ...state.ui.optionsEditor[name]
+    }),
+    (dispatch, { name }) => ({
+        onChange: value => dispatch(updateOptions(name, value))
+    })
+)(PureOption)
-- 
cgit v1.2.3

