mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	semi working input state store
This commit is contained in:
		
							parent
							
								
									d12396cf57
								
							
						
					
					
						commit
						ab64d7eb1c
					
				| @ -1,78 +1,88 @@ | ||||
| import React, { PropTypes } from 'react'; | ||||
| import React, { Component, PropTypes } from 'react'; | ||||
| import { Input, Switch, Button } from 'react-toolbox'; | ||||
| import AddFeatureToggleStrategy from './strategies-for-toggle'; | ||||
| import SelectStrategies from './strategies-for-toggle'; | ||||
| import SelectedStrategies from './selected-strategies'; | ||||
| 
 | ||||
| const AddFeatureToggleComponent = ({ | ||||
|     strategies, | ||||
|     featureToggle, | ||||
|     updateField, | ||||
|     addStrategy, | ||||
|     removeStrategy, | ||||
|     onSubmit, | ||||
|     onCancel, | ||||
|     editmode, | ||||
| }) => { | ||||
|     const { | ||||
|         name, // eslint-disable-line | ||||
|         description, | ||||
|         enabled, | ||||
|     } = featureToggle; | ||||
|     const configuredStrategies = featureToggle.strategies; | ||||
| class AddFeatureToggleComponent extends Component { | ||||
| 
 | ||||
|     return ( | ||||
|         <form onSubmit={onSubmit}> | ||||
|             <section> | ||||
|                 <Input | ||||
|                     type="text" | ||||
|                     label="Name" | ||||
|                     name="name" | ||||
|                     disabled={editmode} | ||||
|                     required | ||||
|                     value={name} | ||||
|                     onChange={updateField.bind(this, 'name')} /> | ||||
|                 <Input | ||||
|                     type="text" | ||||
|                     multiline label="Description" | ||||
|                     required | ||||
|                     value={description} | ||||
|                     onChange={updateField.bind(this, 'description')} /> | ||||
|     componentWillMount () { | ||||
|         // TODO unwind this stuff | ||||
|         if (this.props.initCallRequired === true) { | ||||
|             this.props.init(this.props.input); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     render () { | ||||
|         const { | ||||
|             input, | ||||
|             setValue, | ||||
|             addStrategy, | ||||
|             removeStrategy, | ||||
|             onSubmit, | ||||
|             onCancel, | ||||
|             editmode = false, | ||||
|         } = this.props; | ||||
| 
 | ||||
|         const { | ||||
|             name, // eslint-disable-line | ||||
|             description, | ||||
|             enabled, | ||||
|         } = input; | ||||
|         const configuredStrategies = input.strategies || []; | ||||
| 
 | ||||
|         return ( | ||||
|             <form onSubmit={onSubmit(input)}> | ||||
|                 <section> | ||||
|                     <Input | ||||
|                         type="text" | ||||
|                         label="Name" | ||||
|                         name="name" | ||||
|                         disabled={editmode} | ||||
|                         required | ||||
|                         value={name} | ||||
|                         onChange={(v) => setValue('name', v)} /> | ||||
|                     <Input | ||||
|                         type="text" | ||||
|                         multiline label="Description" | ||||
|                         required | ||||
|                         value={description} | ||||
|                         onChange={(v) => setValue('description', v)} /> | ||||
| 
 | ||||
|                     <br /> | ||||
| 
 | ||||
|                     <Switch | ||||
|                         checked={enabled} | ||||
|                         label="Enabled" | ||||
|                         onChange={(v) => setValue('enabled', v)} /> | ||||
|                     <br /> | ||||
|                 </section> | ||||
| 
 | ||||
|                 <section> | ||||
|                     <strong>Activation strategies</strong> | ||||
|                     <SelectedStrategies | ||||
|                         configuredStrategies={configuredStrategies} | ||||
|                         removeStrategy={removeStrategy} /> | ||||
|                 </section> | ||||
| 
 | ||||
|                 <section> | ||||
|                     <SelectStrategies addStrategy={addStrategy} /> | ||||
|                 </section> | ||||
| 
 | ||||
|                 <br /> | ||||
| 
 | ||||
|                 <Switch | ||||
|                     checked={enabled} | ||||
|                     label="Enabled" | ||||
|                     onChange={updateField.bind(this, 'enabled')} /> | ||||
|                 <Button type="submit" raised primary label={editmode ? 'Update' : 'Create'} /> | ||||
|                   | ||||
|                 <Button type="cancel" raised label="Cancel" onClick={onCancel} /> | ||||
|             </form> | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|                 <br /> | ||||
|             </section> | ||||
| 
 | ||||
|             <section> | ||||
|                 <strong>Activation strategies</strong> | ||||
|                 <SelectedStrategies | ||||
|                     configuredStrategies={configuredStrategies} | ||||
|                     removeStrategy={removeStrategy} /> | ||||
|             </section> | ||||
| 
 | ||||
|             <section> | ||||
|                 <AddFeatureToggleStrategy strategies={strategies} addStrategy={addStrategy} /> | ||||
|             </section> | ||||
| 
 | ||||
|             <br /> | ||||
| 
 | ||||
| 
 | ||||
|             <Button type="submit" raised primary label={editmode ? 'Update' : 'Create'} /> | ||||
|               | ||||
|             <Button type="cancel" raised label="Cancel" onClick={onCancel} /> | ||||
|         </form> | ||||
|     ); | ||||
| }; | ||||
| 
 | ||||
| AddFeatureToggleComponent.propTypes = { | ||||
|     strategies: PropTypes.array.required, | ||||
|     featureToggle: PropTypes.object, | ||||
|     updateField: PropTypes.func.required, | ||||
|     input: PropTypes.object, | ||||
|     setValue: PropTypes.func.required, | ||||
|     addStrategy: PropTypes.func.required, | ||||
|     removeStrategy: PropTypes.func.required, | ||||
|     onSubmit: PropTypes.func.required, | ||||
|  | ||||
| @ -1,80 +1,36 @@ | ||||
| import React, { PropTypes } from 'react'; | ||||
| import { connect } from 'react-redux'; | ||||
| 
 | ||||
| import { createFeatureToggles } from '../../store/feature-actions'; | ||||
| import { fetchStrategies } from '../../store/strategy-actions'; | ||||
| import AddFeatureToggleUI from './add-component'; | ||||
| import AddComponent from './add-component'; | ||||
| import { createMapper, createActions } from '../input-helpers'; | ||||
| 
 | ||||
| class AddFeatureToggle extends React.Component { | ||||
|     constructor () { | ||||
|         super(); | ||||
|         this.state = { | ||||
|             name: '', | ||||
|             description: '', | ||||
|             enabled: false, | ||||
|             strategies: [], | ||||
|         }; | ||||
|     } | ||||
| const ID = 'add-feature-toggle'; | ||||
| const mapStateToProps = createMapper({ id: ID }); | ||||
| const prepare = (methods, dispatch) => { | ||||
|     methods.onSubmit = (input) => ( | ||||
|         (e) => { | ||||
|             e.preventDefault(); | ||||
|             // TODO: should add error handling | ||||
|             createFeatureToggles(input)(dispatch) | ||||
|                 .then(() => methods.clear()) | ||||
|                 .then(() => window.history.back()); | ||||
|         } | ||||
|     ); | ||||
| 
 | ||||
|     static propTypes () { | ||||
|         return { | ||||
|             dispatch: PropTypes.func.isRequired, | ||||
|             strategies: PropTypes.array, | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
|     static contextTypes = { | ||||
|         router: React.PropTypes.object, | ||||
|     } | ||||
| 
 | ||||
|     onSubmit = (evt) => { | ||||
|         evt.preventDefault(); | ||||
|         this.props.dispatch(createFeatureToggles(this.state)); | ||||
|         this.context.router.push('/features'); | ||||
|     methods.onCancel = () => { | ||||
|         window.history.back(); | ||||
|     }; | ||||
| 
 | ||||
|     onCancel = (evt) => { | ||||
|         evt.preventDefault(); | ||||
|         this.context.router.push('/features'); | ||||
|     methods.addStrategy = (v) => { | ||||
|         methods.pushToList('strategies', v); | ||||
|     }; | ||||
| 
 | ||||
|     updateField = (key, value) => { | ||||
|         const change = {}; | ||||
|         change[key] = value; | ||||
|         this.setState(change); | ||||
|     methods.removeStrategy = (v) => { | ||||
|         methods.removeFromList('strategies', v); | ||||
|     }; | ||||
| 
 | ||||
|     addStrategy = (strategy) => { | ||||
|         const strategies = this.state.strategies; | ||||
|         strategies.push(strategy); | ||||
|         this.setState({ strategies }); | ||||
|     } | ||||
|     return methods; | ||||
| }; | ||||
| const actions = createActions({ id: ID, prepare }); | ||||
| 
 | ||||
|     removeStrategy = (strategy) => { | ||||
|         const strategies = this.state.strategies.filter(s => s !== strategy); | ||||
|         this.setState({ strategies }); | ||||
|     } | ||||
| 
 | ||||
|     componentDidMount () { | ||||
|         this.props.fetchStrategies(); | ||||
|     } | ||||
| 
 | ||||
|     render () { | ||||
|         return ( | ||||
|             <AddFeatureToggleUI | ||||
|                 strategies={this.props.strategies} | ||||
|                 featureToggle={this.state} | ||||
|                 updateField={this.updateField} | ||||
|                 addStrategy={this.addStrategy} | ||||
|                 removeStrategy={this.removeStrategy} | ||||
|                 onSubmit={this.onSubmit} | ||||
|                 onCancel={this.onCancel} | ||||
|             /> | ||||
|         ); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| const mapStateToProps = (state) => ({ | ||||
|     strategies: state.strategies.get('list').toArray(), | ||||
| }); | ||||
| 
 | ||||
| export default connect(mapStateToProps, { fetchStrategies })(AddFeatureToggle); | ||||
| export default connect(mapStateToProps, actions)(AddComponent); | ||||
|  | ||||
| @ -1,86 +1,62 @@ | ||||
| import React, { PropTypes } from 'react'; | ||||
| import { connect } from 'react-redux'; | ||||
| import { editFeatureToggle } from '../../store/feature-actions'; | ||||
| import AddFeatureToggleComponent from './add-component'; | ||||
| import { fetchStrategies } from '../../store/strategy-actions'; | ||||
| 
 | ||||
| import { requestUpdateFeatureToggle } from '../../store/feature-actions'; | ||||
| import AddComponent from './add-component'; | ||||
| import { createMapper, createActions } from '../input-helpers'; | ||||
| 
 | ||||
| const mapStateToProps = (state, ownProps) => ({ | ||||
|     strategies: state.strategies.get('list').toArray(), | ||||
|     featureToggle: state.features.toJS().find(toggle => toggle.name === ownProps.featureToggleName) || {}, | ||||
| const ID = 'edit-feature-toggle'; | ||||
| function getId (props) { | ||||
|     return [ID, props.featureToggleName]; | ||||
| } | ||||
| // TODO: need to scope to the active featureToggle | ||||
| // best is to emulate the "input-storage"? | ||||
| const mapStateToProps = createMapper({ | ||||
|     id: getId, | ||||
|     getDefault: (state, ownProps) => { | ||||
|         if (ownProps.featureToggleName) { | ||||
|             const match = state.features.findEntry((entry) => entry.get('name') === ownProps.featureToggleName); | ||||
| 
 | ||||
|             if (match && match[1]) { | ||||
|                 return match[1].toJS(); | ||||
|             } | ||||
|         } | ||||
|         return {}; | ||||
|     }, | ||||
|     prepare: (props) => { | ||||
|         props.editmode = true; | ||||
|         return props; | ||||
|     }, | ||||
| }); | ||||
| 
 | ||||
| class EditFeatureToggle extends React.Component { | ||||
|     constructor (props) { | ||||
|         super(props); | ||||
|         this.state = { | ||||
|             name: props.featureToggle.name || '', | ||||
|             description: props.featureToggle.description || '', | ||||
|             enabled: props.featureToggle.enabled || false, | ||||
|             strategies: props.featureToggle.strategies || [], | ||||
|         }; | ||||
|     } | ||||
| const prepare =  (methods, dispatch) => { | ||||
|     methods.onSubmit = (input) => ( | ||||
|         (e) => { | ||||
|             e.preventDefault(); | ||||
|              // TODO: should add error handling | ||||
|             requestUpdateFeatureToggle(input)(dispatch) | ||||
|                 .then(() => methods.clear()) | ||||
|                 .then(() => window.history.back()); | ||||
|         } | ||||
|     ); | ||||
| 
 | ||||
|     static propTypes () { | ||||
|         return { | ||||
|             dispatch: PropTypes.func.isRequired, | ||||
|             strategies: PropTypes.array, | ||||
|             featureToggle: PropTypes.featureToggle.isRequired, | ||||
|             fetchFeatureToggles: PropTypes.func.isRequired, | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
|     componentDidMount () { | ||||
|         // todo fetch feature if missing? (reload of page does not fetch data from url) | ||||
|         this.props.fetchStrategies(); | ||||
|     } | ||||
| 
 | ||||
|     static contextTypes = { | ||||
|         router: React.PropTypes.object, | ||||
|     } | ||||
| 
 | ||||
|     onSubmit = (evt) => { | ||||
|         evt.preventDefault(); | ||||
|         this.props.dispatch(editFeatureToggle(this.state)); | ||||
|         this.context.router.push('/features'); | ||||
|     methods.onCancel = () => { | ||||
|         window.history.back(); | ||||
|     }; | ||||
| 
 | ||||
|     onCancel = (evt) => { | ||||
|         evt.preventDefault(); | ||||
|         this.context.router.push('/features'); | ||||
|     methods.addStrategy = (v) => { | ||||
|         methods.pushToList('strategies', v); | ||||
|     }; | ||||
| 
 | ||||
|     updateField = (key, value) => { | ||||
|         const change = {}; | ||||
|         change[key] = value; | ||||
|         this.setState(change); | ||||
|     methods.removeStrategy = (v) => { | ||||
|         methods.removeFromList('strategies', v); | ||||
|     }; | ||||
| 
 | ||||
|     addStrategy = (strategy) => { | ||||
|         const strategies = this.state.strategies; | ||||
|         strategies.push(strategy); | ||||
|         this.setState({ strategies }); | ||||
|     } | ||||
|     return methods; | ||||
| }; | ||||
| 
 | ||||
|     removeStrategy = (strategy) => { | ||||
|         const strategies = this.state.strategies.filter(s => s !== strategy); | ||||
|         this.setState({ strategies }); | ||||
|     } | ||||
| const actions = createActions({ | ||||
|     id: getId, | ||||
|     prepare, | ||||
| }); | ||||
| 
 | ||||
|     render () { | ||||
|         return ( | ||||
|             <AddFeatureToggleComponent | ||||
|                 editmode="true" | ||||
|                 strategies={this.props.strategies} | ||||
|                 featureToggle={this.state} | ||||
|                 updateField={this.updateField} | ||||
|                 addStrategy={this.addStrategy} | ||||
|                 removeStrategy={this.removeStrategy} | ||||
|                 onSubmit={this.onSubmit} | ||||
|                 onCancel={this.onCancel} | ||||
|             /> | ||||
|         ); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| export default connect(mapStateToProps, { fetchStrategies })(EditFeatureToggle); | ||||
| export default connect(mapStateToProps, actions)(AddComponent); | ||||
|  | ||||
| @ -0,0 +1,8 @@ | ||||
| import { connect } from 'react-redux'; | ||||
| import SelectStrategies from './select-strategies'; | ||||
| import { fetchStrategies } from '../../store/strategy-actions'; | ||||
| 
 | ||||
| 
 | ||||
| export default connect((state) => ({ | ||||
|     strategies: state.strategies.get('list').toArray(), | ||||
| }), { fetchStrategies })(SelectStrategies); | ||||
| @ -18,6 +18,17 @@ class SelectStrategies extends React.Component { | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
|     componentWillMount () { | ||||
|         this.props.fetchStrategies(); | ||||
|     } | ||||
| 
 | ||||
|     componentWillReceiveProps (nextProps) { | ||||
|         // this will fix async strategies list loading after mounted | ||||
|         if (!this.state.selectedStrategy && nextProps.strategies.length > 0) { | ||||
|             this.setState({ selectedStrategy: nextProps.strategies[0] }); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     handleChange = (evt) => { | ||||
|         const strategyName = evt.target.value; | ||||
|         const selectedStrategy = this.props.strategies.find(s => s.name === strategyName); | ||||
| @ -63,7 +74,11 @@ class SelectStrategies extends React.Component { | ||||
|             padding: '10px', | ||||
|         }; | ||||
| 
 | ||||
|         const selectedStrategy = this.state.selectedStrategy; | ||||
|         const selectedStrategy = this.state.selectedStrategy || this.props.strategies[0]; | ||||
| 
 | ||||
|         if (!selectedStrategy) { | ||||
|             return <div>Strategies loading...</div>; | ||||
|         } | ||||
| 
 | ||||
|         return ( | ||||
|             <div style={style}> | ||||
|  | ||||
| @ -19,7 +19,7 @@ class SelectedStrategies extends React.Component { | ||||
| 
 | ||||
|     render () { | ||||
|         const removeStrategy = this.props.removeStrategy; | ||||
|         const strategies = this.props.configuredStrategies.map((s, index) => ( | ||||
|         const configuredStrategies = this.props.configuredStrategies.map((s, index) => ( | ||||
|             <Chip | ||||
|                 key={`${index}-${s.name}`} | ||||
|                 deletable | ||||
| @ -31,7 +31,7 @@ class SelectedStrategies extends React.Component { | ||||
|         )); | ||||
|         return ( | ||||
|             <div> | ||||
|                 {strategies.length > 0 ? strategies : <p>No activation strategies added</p>} | ||||
|                 {configuredStrategies.length > 0 ? configuredStrategies : <p>No activation strategies added</p>} | ||||
|             </div> | ||||
|         ); | ||||
|     } | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| import React, { PropTypes } from 'react'; | ||||
| import SelectStrategies from './select-strategies'; | ||||
| import SelectStrategies from './select-strategies-container'; | ||||
| 
 | ||||
| class AddStrategiesToToggle extends React.Component { | ||||
|     constructor () { | ||||
| @ -11,7 +11,6 @@ class AddStrategiesToToggle extends React.Component { | ||||
| 
 | ||||
|     static propTypes () { | ||||
|         return { | ||||
|             strategies: PropTypes.array.isRequired, | ||||
|             addStrategy: PropTypes.func.isRequired, | ||||
|         }; | ||||
|     } | ||||
| @ -39,12 +38,11 @@ class AddStrategiesToToggle extends React.Component { | ||||
|     } | ||||
| 
 | ||||
|     render () { | ||||
|         return this.state.showConfigure ? | ||||
|             <SelectStrategies | ||||
|                 strategies={this.props.strategies} | ||||
|                 cancelConfig={this.cancelConfig} | ||||
|                 addStrategy={this.addStrategy} /> : | ||||
|             this.renderAddLink(); | ||||
|         return ( | ||||
|             this.state.showConfigure ? | ||||
|             <SelectStrategies cancelConfig={this.cancelConfig} addStrategy={this.addStrategy} /> : | ||||
|             this.renderAddLink() | ||||
|         ); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -1,32 +1,63 @@ | ||||
| import { createInc, createClear, createSet } from '../store/input-actions'; | ||||
| import { | ||||
|     createInc, | ||||
|     createClear, | ||||
|     createSet, | ||||
|     createPop, | ||||
|     createPush, | ||||
|     createInit, | ||||
| } from '../store/input-actions'; | ||||
| 
 | ||||
| export function createMapper (id, prepare = (v) => v) { | ||||
|     return (state) => { | ||||
| function getId (id, ownProps) { | ||||
|     if (typeof id === 'function') { | ||||
|         return id(ownProps); // should return array...
 | ||||
|     } | ||||
|     return [id]; | ||||
| } | ||||
| 
 | ||||
| export function createMapper ({ id, getDefault, prepare = (v) => v }) { | ||||
|     return (state, ownProps) => { | ||||
|         let input; | ||||
|         if (state.input.has(id)) { | ||||
|             input = state.input.get(id).toJS(); | ||||
|         let initCallRequired = false; | ||||
|         const scope = getId(id, ownProps); | ||||
|         if (state.input.hasIn(scope)) { | ||||
|             input = state.input.getIn(scope).toJS(); | ||||
|         } else { | ||||
|             input = {}; | ||||
|             initCallRequired = true; | ||||
|             input = getDefault ? getDefault(state, ownProps) : {}; | ||||
|         } | ||||
| 
 | ||||
|         return prepare({ | ||||
|             initCallRequired, | ||||
|             input, | ||||
|         }, state); | ||||
|         }, state, ownProps); | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
| export function createActions (id, prepare = (v) => v) { | ||||
|     return (dispatch) => (prepare({ | ||||
| export function createActions ({ id, prepare = (v) => v }) { | ||||
|     return (dispatch, ownProps) => (prepare({ | ||||
| 
 | ||||
|         clear () { | ||||
|             dispatch(createClear({ id })); | ||||
|             dispatch(createClear({ id: getId(id, ownProps) })); | ||||
|         }, | ||||
| 
 | ||||
|         init (value) { | ||||
|             dispatch(createInit({ id: getId(id, ownProps), value })); | ||||
|         }, | ||||
| 
 | ||||
|         setValue (key, value) { | ||||
|             dispatch(createSet({ id, key, value })); | ||||
|             dispatch(createSet({ id: getId(id, ownProps), key, value })); | ||||
|         }, | ||||
| 
 | ||||
|         pushToList (key, value) { | ||||
|             dispatch(createPush({ id: getId(id, ownProps), key, value })); | ||||
|         }, | ||||
| 
 | ||||
|         removeFromList (key, value) { | ||||
|             dispatch(createPop({ id: getId(id, ownProps), key, value })); | ||||
|         }, | ||||
| 
 | ||||
|         incValue (key) { | ||||
|             dispatch(createInc({ id, key })); | ||||
|             dispatch(createInc({ id: getId(id, ownProps), key })); | ||||
|         }, | ||||
|     }, dispatch)); | ||||
|     }, dispatch, ownProps)); | ||||
| } | ||||
|  | ||||
| @ -7,7 +7,7 @@ import AddStrategy, { PARAM_PREFIX } from './add-strategy'; | ||||
| 
 | ||||
| const ID = 'add-strategy'; | ||||
| 
 | ||||
| const actions = createActions(ID, (methods, dispatch) => { | ||||
| const prepare = (methods, dispatch) => { | ||||
|     methods.onSubmit = (input) => ( | ||||
|         (e) => { | ||||
|             e.preventDefault(); | ||||
| @ -35,6 +35,11 @@ const actions = createActions(ID, (methods, dispatch) => { | ||||
| 
 | ||||
| 
 | ||||
|     return methods; | ||||
| }; | ||||
| 
 | ||||
| const actions = createActions({ | ||||
|     id: ID, | ||||
|     prepare, | ||||
| }); | ||||
| 
 | ||||
| export default connect(createMapper(ID), actions)(AddStrategy); | ||||
| export default connect(createMapper({ id: ID }), actions)(AddStrategy); | ||||
|  | ||||
| @ -1,11 +1,17 @@ | ||||
| export const actions = { | ||||
|     SET_VALUE: 'SET_VALUE', | ||||
|     INCREMENT_VALUE: 'INCREMENT_VALUE', | ||||
|     LIST_PUSH: 'LIST_PUSH', | ||||
|     LIST_POP: 'LIST_POP', | ||||
|     CLEAR: 'CLEAR', | ||||
|     INIT: 'INIT', | ||||
| }; | ||||
| 
 | ||||
| export const createInit = ({ id, value }) => ({ type: actions.INIT, id, value }); | ||||
| export const createInc = ({ id, key }) => ({ type: actions.INCREMENT_VALUE, id, key }); | ||||
| export const createSet = ({ id, key, value }) => ({ type: actions.SET_VALUE, id, key, value }); | ||||
| export const createPush = ({ id, key, value }) => ({ type: actions.LIST_PUSH, id, key, value }); | ||||
| export const createPop = ({ id, key, value }) => ({ type: actions.LIST_POP, id, key, value }); | ||||
| export const createClear = ({ id }) => ({ type: actions.CLEAR, id }); | ||||
| 
 | ||||
| export default actions; | ||||
|  | ||||
| @ -1,41 +1,68 @@ | ||||
| import { Map as $Map } from 'immutable'; | ||||
| import { Map as $Map, List, fromJS } from 'immutable'; | ||||
| import actions from './input-actions'; | ||||
| 
 | ||||
| function getInitState () { | ||||
|     return new $Map(); | ||||
| } | ||||
| 
 | ||||
| function init (state, { id, value }) { | ||||
|     state = assertId(state, id); | ||||
|     return state.setIn(id, fromJS(value)); | ||||
| } | ||||
| 
 | ||||
| function assertId (state, id) { | ||||
|     if (!state.has(id)) { | ||||
|         return state.set(id, new $Map({ inputId: id })); | ||||
|     if (!state.hasIn(id)) { | ||||
|         return state.setIn(id, new $Map({ inputId: id })); | ||||
|     } | ||||
|     return state; | ||||
| } | ||||
| 
 | ||||
| function assertList (state, id, key) { | ||||
|     if (!state.getIn(id).has(key)) { | ||||
|         return state.setIn(id.concat([key]), new List()); | ||||
|     } | ||||
|     return state; | ||||
| } | ||||
| 
 | ||||
| function setKeyValue (state, { id, key, value }) { | ||||
|     state = assertId(state, id); | ||||
|     return state.setIn([id, key], value); | ||||
|     return state.setIn(id.concat([key]), value); | ||||
| } | ||||
| 
 | ||||
| function increment (state, { id, key }) { | ||||
|     state = assertId(state, id); | ||||
|     return state.updateIn([id, key], (value = 0)  => value + 1); | ||||
|     return state.updateIn(id.concat([key]), (value = 0)  => value + 1); | ||||
| } | ||||
| 
 | ||||
| function clear (state, { id }) { | ||||
|     if (state.has(id)) { | ||||
|         return state.remove(id); | ||||
|     if (state.hasIn(id)) { | ||||
|         return state.removeIn(id); | ||||
|     } | ||||
|     return state; | ||||
| } | ||||
| 
 | ||||
| const inputState = (state = getInitState(), action) => { | ||||
| function addToList (state, { id, key, value }) { | ||||
|     state = assertId(state, id); | ||||
|     state = assertList(state, id, key); | ||||
| 
 | ||||
|     return state.updateIn(id.concat([key]), (list) => list.push(value)); | ||||
| } | ||||
| 
 | ||||
| function removeFromList (state, { id, key, value }) { | ||||
|     state = assertId(state, id); | ||||
|     state = assertList(state, id, key); | ||||
| 
 | ||||
|     return state.updateIn(id.concat([key]), (list) => list.remove(list.indexOf(value))); | ||||
| } | ||||
| 
 | ||||
| const inputState = (state = getInitState(), action) => { | ||||
|     if (!action.id) { | ||||
|         return state; | ||||
|     } | ||||
| 
 | ||||
|     switch (action.type) { | ||||
|         case actions.INIT: | ||||
|             return init(state, action); | ||||
|         case actions.SET_VALUE: | ||||
|             if (actions.key != null && actions.value != null) { | ||||
|                 throw new Error('Missing required key / value'); | ||||
| @ -43,6 +70,10 @@ const inputState = (state = getInitState(), action) => { | ||||
|             return setKeyValue(state, action); | ||||
|         case actions.INCREMENT_VALUE: | ||||
|             return increment(state, action); | ||||
|         case actions.LIST_PUSH: | ||||
|             return addToList(state, action); | ||||
|         case actions.LIST_POP: | ||||
|             return removeFromList(state, action); | ||||
|         case actions.CLEAR: | ||||
|             return clear(state, action); | ||||
|         default: | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user