From 89a300fe3e3fb3bdbd91e5e4f75d3047665a25e5 Mon Sep 17 00:00:00 2001
From: Matthew Shao <me@matshao.com>
Date: Mon, 10 Jul 2017 20:42:24 +0800
Subject: [web] Try StringSequence update logic and add tooltip.

---
 web/src/js/components/Modal/OptionMaster.jsx | 176 +++++++++++++++++++++------
 1 file changed, 138 insertions(+), 38 deletions(-)

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

diff --git a/web/src/js/components/Modal/OptionMaster.jsx b/web/src/js/components/Modal/OptionMaster.jsx
index 3b4bae80..ac65a22a 100644
--- a/web/src/js/components/Modal/OptionMaster.jsx
+++ b/web/src/js/components/Modal/OptionMaster.jsx
@@ -6,12 +6,19 @@ PureBooleanOption.PropTypes = {
     onChange: PropTypes.func.isRequired,
 }
 
-function PureBooleanOption({ value, onChange, help}) {
+function PureBooleanOption({ value, onChange, ...props}) {
+        let onFocus = () => { props.onFocus() },
+            onBlur = () => { props.onBlur() },
+            onMouseEnter = () => { props.onMouseEnter() },
+            onMouseLeave = () => { props.onMouseLeave() }
         return (
                 <input type="checkbox"
                         checked={value}
                         onChange={onChange}
-                        title={help}
+                        onFocus={onFocus}
+                        onBlur={onBlur}
+                        onMouseOver={onMouseEnter}
+                        onMouseLeave={onMouseLeave}
                 />
         )
 }
@@ -21,14 +28,21 @@ PureStringOption.PropTypes = {
     onChange: PropTypes.func.isRequired,
 }
 
-function PureStringOption( { value, onChange, help }) {
-    let onKeyDown = (e) => {e.stopPropagation()}
+function PureStringOption( { value, onChange, ...props }) {
+    let onKeyDown = (e) => {e.stopPropagation()},
+        onFocus = () => { props.onFocus() },
+        onBlur = () => { props.onBlur() },
+        onMouseEnter = () => { props.onMouseEnter() },
+        onMouseLeave = () => { props.onMouseLeave() }
     return (
             <input type="text"
                     value={value}
                     onChange={onChange}
-                    title={help}
                     onKeyDown={onKeyDown}
+                    onFocus={onFocus}
+                    onBlur={onBlur}
+                    onMouseOver={onMouseEnter}
+                    onMouseLeave={onMouseLeave}
             />
     )
 }
@@ -38,14 +52,22 @@ PureNumberOption.PropTypes = {
     onChange: PropTypes.func.isRequired,
 }
 
-function PureNumberOption( {value, onChange, help }) {
-    let onKeyDown = (e) => {e.stopPropagation()}
+function PureNumberOption( {value, onChange, ...props }) {
+    let onKeyDown = (e) => {e.stopPropagation()},
+        onFocus = () => { props.onFocus() },
+        onBlur = () => { props.onBlur() },
+        onMouseEnter = () => { props.onMouseEnter() },
+        onMouseLeave = () => { props.onMouseLeave() }
+
     return (
             <input type="number"
                     value={value}
                     onChange={onChange}
-                    title={help}
                     onKeyDown={onKeyDown}
+                    onFocus={onFocus}
+                    onBlur={onBlur}
+                    onMouseOver={onMouseEnter}
+                    onMouseLeave={onMouseLeave}
             />
     )
 }
@@ -55,9 +77,21 @@ PureChoicesOption.PropTypes = {
     onChange: PropTypes.func.isRequired,
 }
 
-function PureChoicesOption( { value, onChange, name, help, choices }) {
+function PureChoicesOption( { value, onChange, name, choices, ...props}) {
+    let onFocus = () => { props.onFocus() },
+        onBlur = () => { props.onBlur() },
+        onMouseEnter = () => { props.onMouseEnter() },
+        onMouseLeave = () => { props.onMouseLeave() }
     return (
-            <select name={name} onChange={onChange} title={help} selected={value}>
+            <select
+                name={name}
+                onChange={onChange}
+                selected={value}
+                onFocus={onFocus}
+                onBlur={onBlur}
+                onMouseOver={onMouseEnter}
+                onMouseLeave={onMouseLeave}
+            >
                 { choices.map((choice, index) => (
                     <option key={index} value={choice}> {choice} </option>
                 ))}
@@ -68,34 +102,42 @@ function PureChoicesOption( { value, onChange, name, help, choices }) {
 class PureStringSequenceOption extends Component {
     constructor(props, context) {
         super(props, context)
-        this.state = { height: 1, focus: false }
+        this.state = { height: 1, focus: false, value: this.props.value}
 
         this.onFocus = this.onFocus.bind(this)
         this.onBlur = this.onBlur.bind(this)
         this.onKeyDown = this.onKeyDown.bind(this)
+        this.onChange = this.onChange.bind(this)
     }
 
     onFocus() {
         this.setState( {focus: true, height: 3 })
+        this.props.onFocus()
     }
 
     onBlur() {
         this.setState( {focus: false, height: 1})
+        this.props.onBlur()
     }
 
     onKeyDown(e) {
         e.stopPropagation()
     }
 
+    onChange(e) {
+        const value = e.target.value.split("\n")
+        console.log(value)
+        this.props.onChange(e)
+        this.setState({ value })
+    }
+
     render() {
-        const {value, onChange, help} = this.props
-        const {height, focus} = this.state
+        const {height, value} = this.state
         return (
             <textarea
                 rows={height}
                 value={value}
-                onChange={onChange}
-                title={help}
+                onChange={this.onChange}
                 onKeyDown={this.onKeyDown}
                 onFocus={this.onFocus}
                 onBlur={this.onBlur}
@@ -112,15 +154,36 @@ const OptionTypes = {
     "sequence of str": PureStringSequenceOption,
 }
 
-export default function OptionMaster({option, name, updateOptions, ...props}) {
-    let WrappedComponent = null
-    if (option.choices) {
-        WrappedComponent = PureChoicesOption
-    } else {
-        WrappedComponent = OptionTypes[option.type]
+export default class OptionMaster extends Component {
+
+    constructor(props, context) {
+        super(props, context)
+        this.state = {
+                updateOptions: this.props.updateOptions,
+                option: this.props.option,
+                name: this.props.name,
+                mousefocus: false,
+                focus: false,
+
+        }
+        if (props.option.choices) {
+            this.WrappedComponent = PureChoicesOption
+        } else {
+            this.WrappedComponent = OptionTypes[props.option.type]
+        }
+        this.onChange = this.onChange.bind(this)
+        this.onMouseEnter = this.onMouseEnter.bind(this)
+        this.onMouseLeave = this.onMouseLeave.bind(this)
+        this.onFocus = this.onFocus.bind(this)
+        this.onBlur = this.onBlur.bind(this)
     }
 
-    let onChange = (e) => {
+    componentWillReceiveProps(nextProps) {
+        this.setState({ option: nextProps.option })
+    }
+
+    onChange(e) {
+        const { updateOptions, option, name } = this.state
         switch (option.type) {
             case 'bool' :
                 updateOptions({[name]: !option.value})
@@ -128,25 +191,62 @@ export default function OptionMaster({option, name, updateOptions, ...props}) {
             case 'int':
                 updateOptions({[name]: parseInt(e.target.value)})
                 break
+            case 'sequence of str':
+                const value = e.target.value.split('\n')
+                updateOptions({[name]: value})
+                break
             default:
                 updateOptions({[name]: e.target.value})
         }
     }
-    return (
-        <div className="row">
-            <div className="col-sm-8">
-                {name}
-            </div>
-            <div className="col-sm-4">
-                <WrappedComponent
-                    children={props.children}
-                    value={option.value}
-                    onChange={onChange}
-                    name={name}
-                    help={option.help}
-                    choices={option.choices}
-                />
+
+    onMouseEnter() {
+        console.log(this.state)
+        this.setState({ mousefocus: true })
+    }
+
+    onMouseLeave() {
+        this.setState({ mousefocus: false })
+    }
+
+    onFocus() {
+        console.log(this.state)
+        this.setState({ focus: true })
+    }
+
+    onBlur() {
+        this.setState({ focus: false })
+    }
+
+    render() {
+        const { name, children } = this.props
+        const { option, focus, mousefocus } = this.state
+        const WrappedComponent = this.WrappedComponent
+        return (
+            <div className="row">
+                <div className="col-sm-8">
+                    {name}
+                </div>
+                <div className="col-sm-4">
+                    <WrappedComponent
+                        children={children}
+                        value={option.value}
+                        onChange={this.onChange}
+                        name={name}
+                        choices={option.choices}
+                        onFocus={this.onFocus}
+                        onBlur={this.onBlur}
+                        onMouseEnter={this.onMouseEnter}
+                        onMouseLeave={this.onMouseLeave}
+                    />
+                    {(focus || mousefocus) && (
+                        <div className="tooltip tooltip-bottom" role="tooltip" style={{opacity: 1}}>
+                        <div className="tooltip-inner">
+                            {option.help}
+                        </div>
+                    </div>)}
+                </div>
             </div>
-        </div>
-    )
+        )
+    }
 }
-- 
cgit v1.2.3

