mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	add fields to strategies
This commit is contained in:
		
							parent
							
								
									66527bf085
								
							
						
					
					
						commit
						821bf0e19b
					
				| @ -29,9 +29,7 @@ export const HeaderTitle = ({ title, actions, subtitle }) => ( | ||||
|                 {subtitle && <small>{subtitle}</small>} | ||||
|             </div> | ||||
| 
 | ||||
|             <div style={{ flex: '1', textAlign: 'right' }}> | ||||
|                 {actions} | ||||
|             </div> | ||||
|             {actions && <div style={{ flex: '1', textAlign: 'right' }}>{actions}</div>} | ||||
|     </div> | ||||
| ); | ||||
| 
 | ||||
|  | ||||
| @ -14,9 +14,8 @@ class AddStrategy extends React.Component { | ||||
|     addStrategy = (strategyName) => { | ||||
|         const selectedStrategy = this.props.strategies.find(s => s.name === strategyName); | ||||
|         const parameters = {}; | ||||
|         const keys = Object.keys(selectedStrategy.parametersTemplate || {}); | ||||
|         keys.forEach(prop => { parameters[prop] = ''; }); | ||||
| 
 | ||||
|         selectedStrategy.parameters.forEach(({ name }) => { parameters[name] = ''; }); | ||||
| 
 | ||||
|         this.props.addStrategy({ | ||||
|             name: selectedStrategy.name, | ||||
| @ -40,7 +39,9 @@ class AddStrategy extends React.Component { | ||||
|                 <IconButton name="add" id="strategies-add" raised accent title="Add Strategy" onClick={this.stopPropagation}/> | ||||
|                 <Menu target="strategies-add" valign="bottom" align="right" ripple style={menuStyle}> | ||||
|                     <MenuItem disabled>Add Strategy:</MenuItem> | ||||
|                     {this.props.strategies.map((s) => <MenuItem key={s.name} onClick={() => this.addStrategy(s.name)}>{s.name}</MenuItem>)} | ||||
|                     {this.props.strategies.map((s) => | ||||
|                         <MenuItem key={s.name} title={s.description} onClick={() => this.addStrategy(s.name)}>{s.name}</MenuItem>) | ||||
|                     } | ||||
|                 </Menu> | ||||
|             </div> | ||||
|         ); | ||||
|  | ||||
| @ -22,13 +22,13 @@ class StrategiesList extends React.Component { | ||||
|             return <i style={{ color: 'red' }}>No strategies added</i>; | ||||
|         } | ||||
| 
 | ||||
|         const blocks = configuredStrategies.map((strat, i) => ( | ||||
|         const blocks = configuredStrategies.map((strategy, i) => ( | ||||
|             <ConfigureStrategy | ||||
|                 key={`${strat.name}-${i}`} | ||||
|                 strategy={strat} | ||||
|                 key={`${strategy.name}-${i}`} | ||||
|                 strategy={strategy} | ||||
|                 removeStrategy={this.props.removeStrategy.bind(null, i)} | ||||
|                 updateStrategy={this.props.updateStrategy.bind(null, i)} | ||||
|                 strategyDefinition={strategies.find(s => s.name === strat.name)} /> | ||||
|                 strategyDefinition={strategies.find(s => s.name === strategy.name)} /> | ||||
|         )); | ||||
|         return ( | ||||
|             <div style={{ display: 'flex', flexWrap: 'wrap' }}> | ||||
|  | ||||
| @ -47,24 +47,23 @@ class StrategyConfigure extends React.Component { | ||||
|         this.props.removeStrategy(); | ||||
|     } | ||||
| 
 | ||||
|     renderInputFields (strategyDefinition) { | ||||
|         if (strategyDefinition.parametersTemplate) { | ||||
|             const keys = Object.keys(strategyDefinition.parametersTemplate); | ||||
|             if (keys.length === 0) { | ||||
|                 return null; | ||||
|             } | ||||
|             return keys.map(field => { | ||||
|                 const type = strategyDefinition.parametersTemplate[field]; | ||||
|                 let value = this.props.strategy.parameters[field]; | ||||
|     renderInputFields ({ parameters }) { | ||||
|         if (parameters && parameters.length > 0) { | ||||
|             return parameters.map(({ name, type, description, required }) => { | ||||
|                 let value = this.props.strategy.parameters[name]; | ||||
|                 if (type === 'percentage') { | ||||
|                     if (value == null || (typeof value === 'string' && value === '')) { | ||||
|                         value = 50; // default value | ||||
|                     } | ||||
|                     return (<StrategyInputPersentage | ||||
|                         key={field} | ||||
|                         field={field} | ||||
|                         onChange={this.handleConfigChange.bind(this, field)} | ||||
|                         value={1 * value} />); | ||||
|                     return ( | ||||
|                         <div key={name}> | ||||
|                             <StrategyInputPersentage | ||||
|                                 name={name} | ||||
|                                 onChange={this.handleConfigChange.bind(this, name)} | ||||
|                                 value={1 * value} /> | ||||
|                             {description && <p>{description}</p>} | ||||
|                         </div> | ||||
|                     ); | ||||
|                 } else if (type === 'list') { | ||||
|                     let list = []; | ||||
|                     if (typeof value === 'string') { | ||||
| @ -73,33 +72,44 @@ class StrategyConfigure extends React.Component { | ||||
|                             .split(',') | ||||
|                             .filter(Boolean); | ||||
|                     } | ||||
|                     return (<StrategyInputList key={field} field={field} list={list} setConfig={this.setConfig} />); | ||||
|                     return ( | ||||
|                         <div key={name}> | ||||
|                             <StrategyInputList name={name} list={list} setConfig={this.setConfig} /> | ||||
|                             {description && <p>{description}</p>} | ||||
|                         </div> | ||||
|                     ); | ||||
|                 } else if (type === 'number') { | ||||
|                     return ( | ||||
|                         <Textfield | ||||
|                             pattern="-?[0-9]*(\.[0-9]+)?" | ||||
|                             error={`${field} is not a number!`} | ||||
|                             floatingLabel | ||||
|                             style={{ width: '100%' }} | ||||
|                             key={field} | ||||
|                             name={field} | ||||
|                             label={field} | ||||
|                             onChange={this.handleConfigChange.bind(this, field)} | ||||
|                             value={value} | ||||
|                         /> | ||||
|                         <div key={name}> | ||||
|                             <Textfield | ||||
|                                 pattern="-?[0-9]*(\.[0-9]+)?" | ||||
|                                 error={`${name} is not a number!`} | ||||
|                                 floatingLabel | ||||
|                                 required={required} | ||||
|                                 style={{ width: '100%' }} | ||||
|                                 name={name} | ||||
|                                 label={name} | ||||
|                                 onChange={this.handleConfigChange.bind(this, name)} | ||||
|                                 value={value} | ||||
|                             /> | ||||
|                             {description && <p>{description}</p>} | ||||
|                         </div> | ||||
|                     ); | ||||
|                 } else { | ||||
|                     return ( | ||||
|                         <Textfield | ||||
|                             floatingLabel | ||||
|                             rows={2} | ||||
|                             style={{ width: '100%' }} | ||||
|                             key={field} | ||||
|                             name={field} | ||||
|                             label={field} | ||||
|                             onChange={this.handleConfigChange.bind(this, field)} | ||||
|                             value={value} | ||||
|                         /> | ||||
|                         <div key={name}> | ||||
|                             <Textfield | ||||
|                                 floatingLabel | ||||
|                                 rows={2} | ||||
|                                 style={{ width: '100%' }} | ||||
|                                 required={required} | ||||
|                                 name={name} | ||||
|                                 label={name} | ||||
|                                 onChange={this.handleConfigChange.bind(this, name)} | ||||
|                                 value={value} | ||||
|                             /> | ||||
|                             {description && <p>{description}</p>} | ||||
|                         </div> | ||||
|                     ); | ||||
|                 } | ||||
|             }); | ||||
|  | ||||
| @ -1,36 +1,80 @@ | ||||
| import React from 'react'; | ||||
| import React, { Component, PropTypes } from 'react'; | ||||
| import { | ||||
|     Textfield, | ||||
|     IconButton, | ||||
|     Chip, | ||||
| }  from 'react-mdl'; | ||||
| 
 | ||||
| export default ({ field, list, setConfig }) => ( | ||||
|     <div style={{ margin: '16px 20px' }}> | ||||
|         <h6>{field}</h6> | ||||
|         {list.map((entryValue, index) => ( | ||||
|             <Chip style={{ marginRight: '3px' }} onClose={() => { | ||||
|                 list[index] = null; | ||||
|                 setConfig(field, list.filter(Boolean).join(',')); | ||||
|             }}>{entryValue}</Chip> | ||||
|         ))} | ||||
| export default class InputList extends Component { | ||||
| 
 | ||||
|         <form style={{ display: 'block', padding: 0, margin: 0 }} onSubmit={(e) => { | ||||
|     static propTypes = { | ||||
|         field: PropTypes.string.isRequired, | ||||
|         list: PropTypes.array.isRequired, | ||||
|         setConfig: PropTypes.func.isRequired, | ||||
|     } | ||||
| 
 | ||||
|     onBlur = (e) => { | ||||
|         this.setValue(e); | ||||
|         window.removeEventListener('keydown', this.onKeyHandler, false); | ||||
|     } | ||||
| 
 | ||||
|     onFocus  = (e) => { | ||||
|         e.preventDefault(); | ||||
|         e.stopPropagation(); | ||||
|         window.addEventListener('keydown', this.onKeyHandler, false); | ||||
|     } | ||||
| 
 | ||||
|     onKeyHandler = (e) => { | ||||
|         if (e.key === 'Enter') { | ||||
|             this.setValue(); | ||||
|             e.preventDefault(); | ||||
|             e.stopPropagation(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     setValue = (e) => { | ||||
|         if (e) { | ||||
|             e.preventDefault(); | ||||
|             e.stopPropagation(); | ||||
|         } | ||||
| 
 | ||||
|         const { field, list, setConfig } = this.props; | ||||
|         const inputValue = document.querySelector(`[name="${field}_input"]`); | ||||
|         if (inputValue && inputValue.value) { | ||||
|             list.push(inputValue.value); | ||||
|             inputValue.value = ''; | ||||
|             setConfig(field, list.join(',')); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     onClose (index) { | ||||
|         const { field, list, setConfig } = this.props; | ||||
|         list[index] = null; | ||||
|         setConfig(field, list.length === 1 ? '' : list.filter(Boolean).join(',')); | ||||
|     } | ||||
| 
 | ||||
|     render () { | ||||
|         const { name, list } = this.props; | ||||
|         return (<div> | ||||
|             <p>{name}</p> | ||||
|             {list.map((entryValue, index) => ( | ||||
|                 <Chip | ||||
|                     key={index + entryValue} | ||||
|                     style={{ marginRight: '3px' }} | ||||
|                     onClose={() => this.onClose(index)}>{entryValue}</Chip> | ||||
|             ))} | ||||
| 
 | ||||
|             const inputValue = document.querySelector(`[name="${field}_input"]`); | ||||
|             if (inputValue && inputValue.value) { | ||||
|                 list.push(inputValue.value); | ||||
|                 inputValue.value = ''; | ||||
|                 setConfig(field, list.join(',')); | ||||
|             } | ||||
|         }}> | ||||
|             <div style={{ display: 'flex' }}> | ||||
|                 <Textfield name={`${field}_input`} style={{ width: '100%', flex: 1 }} floatingLabel label="Add list entry" /> | ||||
|                 <IconButton name="add" raised style={{ flex: 1, flexGrow: 0, margin: '20px 0 0 10px' }}/> | ||||
|                 <Textfield | ||||
|                     name={`${name}_input`} | ||||
|                     style={{ width: '100%', flex: 1 }} | ||||
|                     floatingLabel | ||||
|                     label="Add list entry" | ||||
|                     onFocus={this.onFocus} | ||||
|                     onBlur={this.onBlur} /> | ||||
|                 <IconButton name="add" raised style={{ flex: 1, flexGrow: 0, margin: '20px 0 0 10px' }} onClick={this.setValue} /> | ||||
|             </div> | ||||
|         </form> | ||||
| 
 | ||||
|     </div> | ||||
| ); | ||||
|         </div>); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -8,9 +8,9 @@ const labelStyle = { | ||||
|     fontSize: '12px', | ||||
| }; | ||||
| 
 | ||||
| export default ({ field, value, onChange }) => ( | ||||
| export default ({ name, value, onChange }) => ( | ||||
|     <div> | ||||
|         <div style={labelStyle}>{field}: {value}%</div> | ||||
|         <Slider min={0} max={100} defaultValue={value} value={value} onChange={onChange} label={field} /> | ||||
|         <div style={labelStyle}>{name}: {value}%</div> | ||||
|         <Slider min={0} max={100} defaultValue={value} value={value} onChange={onChange} label={name} /> | ||||
|     </div> | ||||
| ); | ||||
|  | ||||
| @ -57,8 +57,8 @@ export function createActions ({ id, prepare = (v) => v }) { | ||||
|             dispatch(createPop({ id: getId(id, ownProps), key, index })); | ||||
|         }, | ||||
| 
 | ||||
|         updateInList (key, index, newValue) { | ||||
|             dispatch(createUp({ id: getId(id, ownProps), key, index, newValue })); | ||||
|         updateInList (key, index, newValue, merge = false) { | ||||
|             dispatch(createUp({ id: getId(id, ownProps), key, index, newValue, merge })); | ||||
|         }, | ||||
| 
 | ||||
|         incValue (key) { | ||||
|  | ||||
| @ -3,7 +3,7 @@ import { connect } from 'react-redux'; | ||||
| import { createMapper, createActions } from '../input-helpers'; | ||||
| import { createStrategy } from '../../store/strategy/actions'; | ||||
| 
 | ||||
| import AddStrategy, { PARAM_PREFIX, TYPE_PREFIX } from './add-strategy'; | ||||
| import AddStrategy from './add-strategy'; | ||||
| 
 | ||||
| const ID = 'add-strategy'; | ||||
| 
 | ||||
| @ -12,15 +12,28 @@ const prepare = (methods, dispatch) => { | ||||
|         (e) => { | ||||
|             e.preventDefault(); | ||||
| 
 | ||||
|             const parametersTemplate = {}; | ||||
|             Object.keys(input).forEach(key => { | ||||
|                 if (key.startsWith(PARAM_PREFIX)) { | ||||
|                     parametersTemplate[input[key]] = input[key.replace(PARAM_PREFIX, TYPE_PREFIX)] || 'string'; | ||||
|                 } | ||||
|             }); | ||||
|             input.parametersTemplate = parametersTemplate; | ||||
| 
 | ||||
|             createStrategy(input)(dispatch) | ||||
| 
 | ||||
|             // clean
 | ||||
|             const parameters = input.parameters | ||||
|                 .filter((name) => !!name) | ||||
|                 .map(({ | ||||
|                     name, | ||||
|                     type = 'string', | ||||
|                     description = '', | ||||
|                     required = false, | ||||
|                 }) => ({ | ||||
|                     name, | ||||
|                     type, | ||||
|                     description, | ||||
|                     required, | ||||
|                 })); | ||||
| 
 | ||||
|             createStrategy({ | ||||
|                 name: input.name, | ||||
|                 description: input.description, | ||||
|                 parameters, | ||||
|             })(dispatch) | ||||
|                 .then(() => methods.clear()) | ||||
|                 // somewhat quickfix / hacky to go back..
 | ||||
|                 .then(() => window.history.back()); | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| import React, { PropTypes } from 'react'; | ||||
| 
 | ||||
| import { Textfield, IconButton, Menu, MenuItem } from 'react-mdl'; | ||||
| import { Textfield, IconButton, Menu, MenuItem, Checkbox } from 'react-mdl'; | ||||
| import { HeaderTitle, FormButtons } from '../common'; | ||||
| 
 | ||||
| 
 | ||||
| @ -15,40 +15,60 @@ const trim = (value) => { | ||||
| function gerArrayWithEntries (num) { | ||||
|     return Array.from(Array(num)); | ||||
| } | ||||
| export const PARAM_PREFIX = 'param_'; | ||||
| export const TYPE_PREFIX = 'type_'; | ||||
| 
 | ||||
| const genParams = (input, num = 0, setValue) => (<div>{gerArrayWithEntries(num).map((v, i) => { | ||||
|     const key = `${PARAM_PREFIX}${i + 1}`; | ||||
|     const typeKey = `${TYPE_PREFIX}${i + 1}`; | ||||
|     return ( | ||||
|         <div key={key}> | ||||
|             <Textfield | ||||
|                 style={{ width: '50%' }} | ||||
|                 floatingLabel | ||||
|                 label={`Parameter name ${i + 1}`} | ||||
|                 name={key} | ||||
|                 onChange={({ target }) => setValue(key, target.value)} | ||||
|                 value={input[key]} /> | ||||
|                 <div style={{ position: 'relative', display: 'inline-block' }}> | ||||
|                     <span id={`${key}-type-menu`}> | ||||
|                         {input[typeKey] || 'string'} | ||||
|                         <IconButton name="arrow_drop_down" onClick={(evt) => evt.preventDefault()} /> | ||||
|                     </span> | ||||
|                     <Menu target={`${key}-type-menu`} align="right"> | ||||
|                         <MenuItem onClick={() => setValue(typeKey, 'string')}>String</MenuItem> | ||||
|                         <MenuItem onClick={() => setValue(typeKey, 'percentage')}>Percentage</MenuItem> | ||||
|                         <MenuItem onClick={() => setValue(typeKey, 'list')}>List of values</MenuItem> | ||||
|                         <MenuItem onClick={() => setValue(typeKey, 'number')}>Number</MenuItem> | ||||
|                     </Menu> | ||||
|                 </div> | ||||
| const Parameter = ({ set, input = {}, index }) => ( | ||||
|     <div  style={{ background: '#f1f1f1', margin: '20px 0', padding: '10px' }}> | ||||
|         <Textfield | ||||
|             style={{ width: '50%' }} | ||||
|             floatingLabel | ||||
|             label={`Parameter name ${index + 1}`} | ||||
|             onChange={({ target }) => set({ name: target.value }, true)} | ||||
|             value={input.name} /> | ||||
|         <div style={{ position: 'relative', display: 'inline-block' }}> | ||||
|             <span id={`${index}-type-menu`}> | ||||
|                 {input.type || 'string'} | ||||
|                 <IconButton name="arrow_drop_down" onClick={(evt) => evt.preventDefault()} /> | ||||
|             </span> | ||||
|             <Menu target={`${index}-type-menu`} align="right"> | ||||
|                 <MenuItem onClick={() => set({ type: 'string' })}>String</MenuItem> | ||||
|                 <MenuItem onClick={() => set({ type: 'percentage' })}>Percentage</MenuItem> | ||||
|                 <MenuItem onClick={() => set({ type: 'list' })}>List of values</MenuItem> | ||||
|                 <MenuItem onClick={() => set({ type: 'number' })}>Number</MenuItem> | ||||
|             </Menu> | ||||
|         </div> | ||||
|     ); | ||||
| })}</div>); | ||||
|         <Textfield | ||||
|             floatingLabel | ||||
|             style={{ width: '100%' }} | ||||
|             rows={2} | ||||
|             label={`Parameter name ${index + 1} description`} | ||||
|             onChange={({ target }) => set({ description: target.value })} | ||||
|             value={input.description} | ||||
|         /> | ||||
|         <Checkbox | ||||
|             label="Required" | ||||
|             checked={!!input.required} | ||||
|             onChange={() => set({ required: !input.required })} | ||||
|             ripple | ||||
|             defaultChecked | ||||
|         /> | ||||
|     </div> | ||||
| ); | ||||
| 
 | ||||
| const Parameters = ({ input = [], count = 0, updateInList }) => ( | ||||
| <div>{ | ||||
|     gerArrayWithEntries(count) | ||||
|     .map((v, i) => <Parameter | ||||
|         key={i} | ||||
|         set={(v) => updateInList('parameters', i, v, true)} | ||||
|         index={i} | ||||
|         input={input[i]} | ||||
|     />) | ||||
| }</div>); | ||||
| 
 | ||||
| const AddStrategy = ({ | ||||
|     input, | ||||
|     setValue, | ||||
|     updateInList, | ||||
|     incValue, | ||||
|     // clear, | ||||
|     onCancel, | ||||
| @ -78,7 +98,7 @@ const AddStrategy = ({ | ||||
|         </section> | ||||
| 
 | ||||
|         <section style={{ margin: '0 20px' }}> | ||||
|             {genParams(input, input._params, setValue)} | ||||
|             <Parameters input={input.parameters} count={input._params} updateInList={updateInList} /> | ||||
|             <IconButton raised name="add" title="Add parameter" onClick={(e) => { | ||||
|                 e.preventDefault(); | ||||
|                 incValue('_params'); | ||||
| @ -97,6 +117,7 @@ const AddStrategy = ({ | ||||
| AddStrategy.propTypes = { | ||||
|     input: PropTypes.object, | ||||
|     setValue: PropTypes.func, | ||||
|     updateInList: PropTypes.func, | ||||
|     incValue: PropTypes.func, | ||||
|     clear: PropTypes.func, | ||||
|     onCancel: PropTypes.func, | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| import React, { Component } from 'react'; | ||||
| import { Link } from 'react-router'; | ||||
| 
 | ||||
| import { List, ListItem, ListItemContent, Chip, Icon, IconButton } from 'react-mdl'; | ||||
| import { List, ListItem, ListItemContent, IconButton } from 'react-mdl'; | ||||
| import { HeaderTitle } from '../common'; | ||||
| 
 | ||||
| class StrategiesListComponent extends Component { | ||||
| @ -14,12 +14,6 @@ class StrategiesListComponent extends Component { | ||||
|         this.props.fetchStrategies(); | ||||
|     } | ||||
| 
 | ||||
|     getParameterMap ({ parametersTemplate }) { | ||||
|         return Object.keys(parametersTemplate || {}).map(k => ( | ||||
|             <Chip key={k}><small>{k}</small></Chip> | ||||
|         )); | ||||
|     } | ||||
| 
 | ||||
|     render () { | ||||
|         const { strategies, removeStrategy } = this.props; | ||||
| 
 | ||||
|  | ||||
| @ -1,6 +1,5 @@ | ||||
| import React, { Component } from 'react'; | ||||
| import { Grid, Cell } from 'react-mdl'; | ||||
| 
 | ||||
| import { Grid, Cell, List, ListItem, ListItemContent } from 'react-mdl'; | ||||
| import { AppsLinkList, TogglesLinkList, HeaderTitle } from '../common'; | ||||
| 
 | ||||
| class ShowStrategyComponent extends Component { | ||||
| @ -16,13 +15,17 @@ class ShowStrategyComponent extends Component { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     renderParameters (parametersTemplate) { | ||||
|         if (parametersTemplate) { | ||||
|             return Object.keys(parametersTemplate).map((name, i) => ( | ||||
|                 <li key={`${name}-${i}`}><strong>{name}</strong> ({parametersTemplate[name]})</li> | ||||
|     renderParameters (params) { | ||||
|         if (params) { | ||||
|             return params.map(({ name, type, description, required }, i) => ( | ||||
|                 <ListItem twoLine key={`${name}-${i}`} title={required ? 'Required' : ''}> | ||||
|                     <ListItemContent avatar={required ? 'add' : ' '} subtitle={description}> | ||||
|                         {name} <small>({type})</small> | ||||
|                     </ListItemContent> | ||||
|                 </ListItem> | ||||
|             )); | ||||
|         } else { | ||||
|             return <li>(no params)</li>; | ||||
|             return <ListItem>(no params)</ListItem>; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| @ -41,28 +44,28 @@ class ShowStrategyComponent extends Component { | ||||
|         const { | ||||
|             name, | ||||
|             description, | ||||
|             parametersTemplate = {}, | ||||
|             parameters = [], | ||||
|         } = strategy; | ||||
| 
 | ||||
|         return ( | ||||
|             <div> | ||||
|                 <HeaderTitle title={name} subtitle={description} /> | ||||
|                 <Grid> | ||||
|                     <Cell col={4}> | ||||
|                     <Cell col={12}> | ||||
|                         <h6>Parameters</h6> | ||||
|                         <hr /> | ||||
|                         <ol className="demo-list-item mdl-list"> | ||||
|                             {this.renderParameters(parametersTemplate)} | ||||
|                         </ol> | ||||
|                         <List> | ||||
|                             {this.renderParameters(parameters)} | ||||
|                         </List> | ||||
|                     </Cell> | ||||
| 
 | ||||
|                     <Cell col={4}> | ||||
|                     <Cell col={6}> | ||||
|                         <h6>Applications using this strategy</h6> | ||||
|                         <hr /> | ||||
|                         <AppsLinkList apps={applications} /> | ||||
|                     </Cell> | ||||
| 
 | ||||
|                     <Cell col={4}> | ||||
|                     <Cell col={6}> | ||||
|                         <h6>Toggles using this strategy</h6> | ||||
|                         <hr /> | ||||
|                         <TogglesLinkList toggles={toggles} /> | ||||
|  | ||||
| @ -13,7 +13,7 @@ export const createInc = ({ id, key }) => ({ type: actions.INCREMENT_VALUE, id, | ||||
| 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, index }) => ({ type: actions.LIST_POP, id, key, index }); | ||||
| export const createUp = ({ id, key, index, newValue }) => ({ type: actions.LIST_UP, id, key, index, newValue }); | ||||
| export const createUp = ({ id, key, index, newValue, merge }) => ({ type: actions.LIST_UP, id, key, index, newValue, merge }); | ||||
| export const createClear = ({ id }) => ({ type: actions.CLEAR, id }); | ||||
| 
 | ||||
| export default actions; | ||||
|  | ||||
| @ -48,11 +48,18 @@ function addToList (state, { id, key, value }) { | ||||
|     return state.updateIn(id.concat([key]), (list) => list.push(value)); | ||||
| } | ||||
| 
 | ||||
| function updateInList (state, { id, key, index, newValue }) { | ||||
| function updateInList (state, { id, key, index, newValue, merge }) { | ||||
|     state = assertId(state, id); | ||||
|     state = assertList(state, id, key); | ||||
| 
 | ||||
|     return state.updateIn(id.concat([key]), (list) => list.set(index, newValue)); | ||||
|     return state.updateIn(id.concat([key]), (list) => { | ||||
|         if (merge && list.has(index)) { | ||||
|             newValue = list.get(index).merge(new $Map(newValue)); | ||||
|         } else if (typeof newValue !== 'string' ) { | ||||
|             newValue = fromJS(newValue); | ||||
|         } | ||||
|         return list.set(index, newValue); | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| function removeFromList (state, { id, key, index }) { | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user