mirror of
https://github.com/Unleash/unleash.git
synced 2025-01-06 00:07:44 +01:00
add strategies
This commit is contained in:
parent
0444503e86
commit
a591de0adf
@ -2,10 +2,7 @@ import React, { PropTypes } from 'react';
|
|||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { createFeatureToggles } from '../../store/feature-actions';
|
import { createFeatureToggles } from '../../store/feature-actions';
|
||||||
import AddFeatureToggleUI from './AddFeatureToggleUI';
|
import AddFeatureToggleUI from './AddFeatureToggleUI';
|
||||||
|
import { fetchStrategies } from '../../store/strategy-actions';
|
||||||
const mapStateToProps = (state) => ({
|
|
||||||
strategies: state.strategies.toJS(),
|
|
||||||
});
|
|
||||||
|
|
||||||
class AddFeatureToggle extends React.Component {
|
class AddFeatureToggle extends React.Component {
|
||||||
constructor () {
|
constructor () {
|
||||||
@ -57,9 +54,12 @@ class AddFeatureToggle extends React.Component {
|
|||||||
this.setState({ strategies });
|
this.setState({ strategies });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentDidMount () {
|
||||||
|
this.props.fetchStrategies();
|
||||||
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
return (
|
return (
|
||||||
<div>
|
|
||||||
<AddFeatureToggleUI
|
<AddFeatureToggleUI
|
||||||
strategies={this.props.strategies}
|
strategies={this.props.strategies}
|
||||||
featureToggle={this.state}
|
featureToggle={this.state}
|
||||||
@ -69,9 +69,12 @@ class AddFeatureToggle extends React.Component {
|
|||||||
onSubmit={this.onSubmit}
|
onSubmit={this.onSubmit}
|
||||||
onCancel={this.onCancel}
|
onCancel={this.onCancel}
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect(mapStateToProps)(AddFeatureToggle);
|
const mapStateToProps = (state) => ({
|
||||||
|
strategies: state.strategies.get('list').toArray(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, { fetchStrategies })(AddFeatureToggle);
|
||||||
|
@ -33,7 +33,7 @@ class AddFeatureToggleStrategy extends React.Component {
|
|||||||
renderAddLink () {
|
renderAddLink () {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<a href="" onClick={this.showConfigure}>Add strategy</a>
|
<a href="#" onClick={this.showConfigure}>Add strategy</a>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,32 @@
|
|||||||
|
import { createInc, createClear, createSet } from '../store/input-actions';
|
||||||
|
|
||||||
|
export function createMapper (id, prepare = (v) => v) {
|
||||||
|
return (state) => {
|
||||||
|
let input;
|
||||||
|
if (state.input.has(id)) {
|
||||||
|
input = state.input.get(id).toJS();
|
||||||
|
} else {
|
||||||
|
input = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return prepare({
|
||||||
|
input,
|
||||||
|
}, state);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createActions (id, prepare = (v) => v) {
|
||||||
|
return (dispatch) => (prepare({
|
||||||
|
clear () {
|
||||||
|
dispatch(createClear({ id }));
|
||||||
|
},
|
||||||
|
|
||||||
|
setValue (key, value) {
|
||||||
|
dispatch(createSet({ id, key, value }));
|
||||||
|
},
|
||||||
|
|
||||||
|
incValue (key) {
|
||||||
|
dispatch(createInc({ id, key }));
|
||||||
|
},
|
||||||
|
}, dispatch));
|
||||||
|
}
|
@ -0,0 +1,111 @@
|
|||||||
|
import React, { PropTypes } from 'react';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
|
import Input from 'react-toolbox/lib/input';
|
||||||
|
import Button from 'react-toolbox/lib/button';
|
||||||
|
|
||||||
|
import { createMapper, createActions } from '../input-helpers';
|
||||||
|
import { createStrategy } from '../../store/strategy-actions';
|
||||||
|
|
||||||
|
function gerArrayWithEntries (num) {
|
||||||
|
return Array.from(Array(num));
|
||||||
|
}
|
||||||
|
const PARAM_PREFIX = 'param_';
|
||||||
|
const genParams = (input, num = 0, setValue) => {
|
||||||
|
return (<div>{gerArrayWithEntries(num).map((v, i) => {
|
||||||
|
const key = `${PARAM_PREFIX}${i + 1}`;
|
||||||
|
return (
|
||||||
|
<Input
|
||||||
|
type="text"
|
||||||
|
label={`Parameter name ${i + 1}`}
|
||||||
|
name={key} key={key}
|
||||||
|
onChange={(value) => setValue(key, value)}
|
||||||
|
value={input[key]} />
|
||||||
|
);
|
||||||
|
})}</div>);
|
||||||
|
};
|
||||||
|
|
||||||
|
const AddStrategy = ({
|
||||||
|
input,
|
||||||
|
setValue,
|
||||||
|
incValue,
|
||||||
|
// clear,
|
||||||
|
onCancel,
|
||||||
|
onSubmit,
|
||||||
|
}) => (
|
||||||
|
<form onSubmit={onSubmit(input)}>
|
||||||
|
<section>
|
||||||
|
<Input type="text" label="Strategy name"
|
||||||
|
name="name" required
|
||||||
|
pattern="^[0-9a-zA-Z\.\-]+$"
|
||||||
|
onChange={(value) => setValue('name', value)}
|
||||||
|
value={input.name}
|
||||||
|
/>
|
||||||
|
<Input type="text" multiline label="Description"
|
||||||
|
name="description"
|
||||||
|
onChange={(value) => setValue('description', value)}
|
||||||
|
value={input.description}
|
||||||
|
/>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
{genParams(input, input._params, setValue)}
|
||||||
|
<Button icon="add" accent label="Add parameter" onClick={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
incValue('_params');
|
||||||
|
}}/>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<Button type="submit" raised primary label="Create" />
|
||||||
|
|
||||||
|
<Button type="cancel" raised label="Cancel" onClick={onCancel} />
|
||||||
|
</section>
|
||||||
|
</form>
|
||||||
|
);
|
||||||
|
|
||||||
|
AddStrategy.propTypes = {
|
||||||
|
input: PropTypes.object,
|
||||||
|
setValue: PropTypes.func,
|
||||||
|
incValue: PropTypes.func,
|
||||||
|
clear: PropTypes.func,
|
||||||
|
onCancel: PropTypes.func,
|
||||||
|
onSubmit: PropTypes.func,
|
||||||
|
};
|
||||||
|
|
||||||
|
const ID = 'add-strategy';
|
||||||
|
|
||||||
|
const actions = createActions(ID, (methods, dispatch) => {
|
||||||
|
methods.onSubmit = (input) => (
|
||||||
|
(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
const parametersTemplate = {};
|
||||||
|
Object.keys(input).forEach(key => {
|
||||||
|
if (key.startsWith(PARAM_PREFIX)) {
|
||||||
|
parametersTemplate[input[key]] = 'string';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
input.parametersTemplate = parametersTemplate;
|
||||||
|
|
||||||
|
createStrategy(input)(dispatch)
|
||||||
|
.then(() => methods.clear())
|
||||||
|
// somewhat quickfix / hacky to go back..
|
||||||
|
.then(() => window.history.back());
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
methods.onCancel = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
// somewhat quickfix / hacky to go back..
|
||||||
|
window.history.back();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
return methods;
|
||||||
|
});
|
||||||
|
|
||||||
|
export default connect(createMapper(ID), actions)(AddStrategy);
|
@ -0,0 +1,24 @@
|
|||||||
|
import { connect } from 'react-redux';
|
||||||
|
import StrategiesListComponent from './list.jsx';
|
||||||
|
import { fetchStrategies, removeStrategy } from '../../store/strategy-actions';
|
||||||
|
|
||||||
|
const mapStateToProps = (state) => {
|
||||||
|
const list = state.strategies.get('list').toArray();
|
||||||
|
|
||||||
|
return {
|
||||||
|
strategies: list,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
|
removeStrategy: (strategy) => {
|
||||||
|
if (window.confirm('Are you sure you want to remove this strategy?')) { // eslint-disable-line no-alert
|
||||||
|
removeStrategy(strategy)(dispatch);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fetchStrategies: () => fetchStrategies()(dispatch),
|
||||||
|
});
|
||||||
|
|
||||||
|
const StrategiesListContainer = connect(mapStateToProps, mapDispatchToProps)(StrategiesListComponent);
|
||||||
|
|
||||||
|
export default StrategiesListContainer;
|
@ -0,0 +1,52 @@
|
|||||||
|
import React, { Component } from 'react';
|
||||||
|
import { List, ListItem, ListSubHeader, ListDivider } from 'react-toolbox/lib/list';
|
||||||
|
import FontIcon from 'react-toolbox/lib/font_icon';
|
||||||
|
import style from './strategies.scss';
|
||||||
|
|
||||||
|
class StrategiesListComponent extends Component {
|
||||||
|
|
||||||
|
static contextTypes = {
|
||||||
|
router: React.PropTypes.object,
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount () {
|
||||||
|
this.props.fetchStrategies();
|
||||||
|
}
|
||||||
|
|
||||||
|
getParameterMap ({ parametersTemplate }) {
|
||||||
|
return Object.keys(parametersTemplate || {}).map(k => (
|
||||||
|
<span className={style.label} key={k}>{k}</span>
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
render () {
|
||||||
|
const { strategies, removeStrategy } = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<List ripple >
|
||||||
|
<ListSubHeader caption="Strategies" />
|
||||||
|
{strategies.length > 0 ? strategies.map((strategy, i) => {
|
||||||
|
const actions = this.getParameterMap(strategy).concat([
|
||||||
|
<button className={style['non-style-button']} key="1" onClick={() => removeStrategy(strategy)}>
|
||||||
|
<FontIcon value="delete" />
|
||||||
|
</button>,
|
||||||
|
]);
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ListItem key={i} rightActions={actions}
|
||||||
|
caption={strategy.name}
|
||||||
|
legend={strategy.description} />
|
||||||
|
);
|
||||||
|
}) : <ListItem caption="No entries" />}
|
||||||
|
<ListDivider />
|
||||||
|
<ListItem
|
||||||
|
onClick={() => this.context.router.push('/strategies/create')}
|
||||||
|
caption="Add" legend="new strategy" leftIcon="add" />
|
||||||
|
</List>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default StrategiesListComponent;
|
@ -0,0 +1,18 @@
|
|||||||
|
.label {
|
||||||
|
font-size: 75%;
|
||||||
|
color: #aaa;
|
||||||
|
padding: 4px 5px 3px 5px;
|
||||||
|
background-color: #ddd;
|
||||||
|
border-radius: 5px;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.non-style-button {
|
||||||
|
cursor: pointer;
|
||||||
|
color: #757575;
|
||||||
|
background: none;
|
||||||
|
border: 0;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
@ -1,53 +0,0 @@
|
|||||||
import React, { PropTypes } from 'react';
|
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import { Button } from 'react-toolbox';
|
|
||||||
|
|
||||||
|
|
||||||
class AddStrategy extends React.Component {
|
|
||||||
constructor () {
|
|
||||||
super();
|
|
||||||
this.state = {
|
|
||||||
name: '',
|
|
||||||
parameters: {},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static propTypes () {
|
|
||||||
return {
|
|
||||||
StrategyDefinitions: PropTypes.array.isRequired,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static contextTypes = {
|
|
||||||
router: React.PropTypes.object,
|
|
||||||
}
|
|
||||||
|
|
||||||
onSubmit = (evt) => {
|
|
||||||
evt.preventDefault();
|
|
||||||
};
|
|
||||||
|
|
||||||
addStrategy = (evt) => {
|
|
||||||
evt.preventDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
handleChange = (key, value) => {
|
|
||||||
const change = {};
|
|
||||||
change[key] = value;
|
|
||||||
|
|
||||||
const newState = Object.assign({}, this.state, change);
|
|
||||||
this.setState(newState);
|
|
||||||
};
|
|
||||||
|
|
||||||
render () {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<form onSubmit={this.onSubmit}>
|
|
||||||
New Strategy:
|
|
||||||
<Button type="submit" raised primary label="Create" />
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default connect()(AddStrategy);
|
|
42
packages/unleash-frontend-next/src/data/strategy-api.js
Normal file
42
packages/unleash-frontend-next/src/data/strategy-api.js
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
const URI = '/strategies';
|
||||||
|
|
||||||
|
const headers = {
|
||||||
|
'Accept': 'application/json',
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
};
|
||||||
|
|
||||||
|
function throwIfNotSuccess (response) {
|
||||||
|
if (!response.ok) {
|
||||||
|
let error = new Error('API call failed');
|
||||||
|
error.status = response.status;
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
function fetchAll () {
|
||||||
|
return fetch(URI)
|
||||||
|
.then(throwIfNotSuccess)
|
||||||
|
.then(response => response.json());
|
||||||
|
}
|
||||||
|
|
||||||
|
function create (strategy) {
|
||||||
|
return fetch(URI, {
|
||||||
|
method: 'POST',
|
||||||
|
headers,
|
||||||
|
body: JSON.stringify(strategy),
|
||||||
|
}).then(throwIfNotSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
function remove (strategy) {
|
||||||
|
return fetch(`${URI}/${strategy.name}`, {
|
||||||
|
method: 'DELETE',
|
||||||
|
headers,
|
||||||
|
}).then(throwIfNotSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
fetchAll,
|
||||||
|
create,
|
||||||
|
remove,
|
||||||
|
};
|
@ -12,6 +12,7 @@ import Features from './page/features';
|
|||||||
import CreateFeatureToggle from './page/features/create';
|
import CreateFeatureToggle from './page/features/create';
|
||||||
import EditFeatureToggle from './page/features/edit';
|
import EditFeatureToggle from './page/features/edit';
|
||||||
import Strategies from './page/strategies';
|
import Strategies from './page/strategies';
|
||||||
|
import CreateStrategies from './page/strategies/create';
|
||||||
import HistoryPage from './page/history';
|
import HistoryPage from './page/history';
|
||||||
import Archive from './page/archive';
|
import Archive from './page/archive';
|
||||||
|
|
||||||
@ -31,6 +32,7 @@ ReactDOM.render(
|
|||||||
<Route path="/features/create" component={CreateFeatureToggle} />
|
<Route path="/features/create" component={CreateFeatureToggle} />
|
||||||
<Route path="/features/edit/:name" component={EditFeatureToggle} />
|
<Route path="/features/edit/:name" component={EditFeatureToggle} />
|
||||||
<Route path="/strategies" component={Strategies} />
|
<Route path="/strategies" component={Strategies} />
|
||||||
|
<Route path="/strategies/create" component={CreateStrategies} />
|
||||||
<Route path="/history" component={HistoryPage} />
|
<Route path="/history" component={HistoryPage} />
|
||||||
<Route path="/archive" component={Archive} />
|
<Route path="/archive" component={Archive} />
|
||||||
</Route>
|
</Route>
|
||||||
|
@ -0,0 +1,4 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import AddStrategies from '../../component/strategies/add-strategy';
|
||||||
|
|
||||||
|
export default () => (<AddStrategies />);
|
@ -1,11 +1,4 @@
|
|||||||
import React, { Component } from 'react';
|
import React from 'react';
|
||||||
|
import Strategies from '../../component/strategies';
|
||||||
|
|
||||||
export default class Strategies extends Component {
|
export default () => (<Strategies />);
|
||||||
render () {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<h1>Strategies</h1>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
import { combineReducers } from 'redux';
|
import { combineReducers } from 'redux';
|
||||||
import features from './feature-store';
|
import features from './feature-store';
|
||||||
import strategies from './strategy-store';
|
import strategies from './strategy-store';
|
||||||
|
import input from './input-store';
|
||||||
|
|
||||||
const unleashStore = combineReducers({
|
const unleashStore = combineReducers({
|
||||||
features,
|
features,
|
||||||
strategies,
|
strategies,
|
||||||
|
input,
|
||||||
});
|
});
|
||||||
|
|
||||||
export default unleashStore;
|
export default unleashStore;
|
||||||
|
11
packages/unleash-frontend-next/src/store/input-actions.js
Normal file
11
packages/unleash-frontend-next/src/store/input-actions.js
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
export const actions = {
|
||||||
|
SET_VALUE: 'SET_VALUE',
|
||||||
|
INCREMENT_VALUE: 'INCREMENT_VALUE',
|
||||||
|
CLEAR: 'CLEAR',
|
||||||
|
};
|
||||||
|
|
||||||
|
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 createClear = ({ id }) => ({ type: actions.CLEAR, id });
|
||||||
|
|
||||||
|
export default actions;
|
54
packages/unleash-frontend-next/src/store/input-store.js
Normal file
54
packages/unleash-frontend-next/src/store/input-store.js
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import { Map as $Map } from 'immutable';
|
||||||
|
import actions from './input-actions';
|
||||||
|
|
||||||
|
function getInitState () {
|
||||||
|
return new $Map();
|
||||||
|
}
|
||||||
|
|
||||||
|
function assertId (state, id) {
|
||||||
|
if (!state.has(id)) {
|
||||||
|
return state.set(id, new $Map({ inputId: id }));
|
||||||
|
}
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setKeyValue (state, { id, key, value }) {
|
||||||
|
state = assertId(state, id);
|
||||||
|
return state.setIn([id, key], value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function increment (state, { id, key }) {
|
||||||
|
state = assertId(state, id);
|
||||||
|
return state.updateIn([id, key], (value = 0) => value + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function clear (state, { id }) {
|
||||||
|
if (state.has(id)) {
|
||||||
|
return state.remove(id);
|
||||||
|
}
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
const inputState = (state = getInitState(), action) => {
|
||||||
|
|
||||||
|
if (!action.id) {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (action.type) {
|
||||||
|
case actions.SET_VALUE:
|
||||||
|
if (actions.key != null && actions.value != null) {
|
||||||
|
throw new Error('Missing required key / value');
|
||||||
|
}
|
||||||
|
return setKeyValue(state, action);
|
||||||
|
case actions.INCREMENT_VALUE:
|
||||||
|
return increment(state, action);
|
||||||
|
case actions.CLEAR:
|
||||||
|
return clear(state, action);
|
||||||
|
default:
|
||||||
|
// console.log('TYPE', action.type, action);
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default inputState;
|
63
packages/unleash-frontend-next/src/store/strategy-actions.js
Normal file
63
packages/unleash-frontend-next/src/store/strategy-actions.js
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
import api from '../data/strategy-api';
|
||||||
|
|
||||||
|
export const ADD_STRATEGY = 'ADD_STRATEGY';
|
||||||
|
export const REMOVE_STRATEGY = 'REMOVE_STRATEGY';
|
||||||
|
export const REQUEST_STRATEGIES = 'REQUEST_STRATEGIES';
|
||||||
|
export const START_CREATE_STRATEGY = 'START_CREATE_STRATEGY';
|
||||||
|
export const RECEIVE_STRATEGIES = 'RECEIVE_STRATEGIES';
|
||||||
|
export const ERROR_RECEIVE_STRATEGIES = 'ERROR_RECEIVE_STRATEGIES';
|
||||||
|
export const ERROR_CREATING_STRATEGY = 'ERROR_CREATING_STRATEGY';
|
||||||
|
|
||||||
|
const addStrategy = (strategy) => ({ type: ADD_STRATEGY, strategy });
|
||||||
|
const createRemoveStrategy = (strategy) => ({ type: REMOVE_STRATEGY, strategy });
|
||||||
|
|
||||||
|
const errorCreatingStrategy = (statusCode) => ({
|
||||||
|
type: ERROR_CREATING_STRATEGY,
|
||||||
|
statusCode,
|
||||||
|
});
|
||||||
|
|
||||||
|
const startRequest = () => ({ type: REQUEST_STRATEGIES });
|
||||||
|
|
||||||
|
|
||||||
|
const receiveStrategies = (json) => ({
|
||||||
|
type: RECEIVE_STRATEGIES,
|
||||||
|
value: json.strategies,
|
||||||
|
});
|
||||||
|
|
||||||
|
const startCreate = () => ({ type: START_CREATE_STRATEGY });
|
||||||
|
|
||||||
|
const errorReceiveStrategies = (statusCode) => ({
|
||||||
|
type: ERROR_RECEIVE_STRATEGIES,
|
||||||
|
statusCode,
|
||||||
|
});
|
||||||
|
|
||||||
|
export function fetchStrategies () {
|
||||||
|
return dispatch => {
|
||||||
|
dispatch(startRequest());
|
||||||
|
|
||||||
|
return api.fetchAll()
|
||||||
|
.then(json => dispatch(receiveStrategies(json)))
|
||||||
|
.catch(error => dispatch(errorReceiveStrategies(error)));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createStrategy (strategy) {
|
||||||
|
return dispatch => {
|
||||||
|
dispatch(startCreate());
|
||||||
|
|
||||||
|
return api.create(strategy)
|
||||||
|
.then(() => dispatch(addStrategy(strategy)))
|
||||||
|
.catch(error => dispatch(errorCreatingStrategy(error)));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function removeStrategy (strategy) {
|
||||||
|
return dispatch => {
|
||||||
|
return api.remove(strategy)
|
||||||
|
.then(() => dispatch(createRemoveStrategy(strategy)))
|
||||||
|
.catch(error => dispatch(errorCreatingStrategy(error)));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -1,18 +1,26 @@
|
|||||||
import { List, Map as $Map } from 'immutable';
|
import { List, Map as $Map } from 'immutable';
|
||||||
|
import { RECEIVE_STRATEGIES, REMOVE_STRATEGY, ADD_STRATEGY } from './strategy-actions';
|
||||||
|
|
||||||
const init = new List([
|
function getInitState () {
|
||||||
new $Map({ name: 'default', description: 'Default on/off strategy' }),
|
return new $Map({ list: new List() });
|
||||||
new $Map(
|
}
|
||||||
{
|
|
||||||
name: 'ActiveForUserWithEmail',
|
|
||||||
description: 'Active for user with specified email',
|
|
||||||
parametersTemplate: { emails: 'string', ids: 'string' },
|
|
||||||
}),
|
|
||||||
]);
|
|
||||||
|
|
||||||
|
function removeStrategy (state, action) {
|
||||||
|
const indexToRemove = state.get('list').indexOf(action.strategy);
|
||||||
|
if (indexToRemove !== -1) {
|
||||||
|
return state.update('list', (list) => list.remove(indexToRemove));
|
||||||
|
}
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
const strategies = (state = init, action) => {
|
const strategies = (state = getInitState(), action) => {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
|
case RECEIVE_STRATEGIES:
|
||||||
|
return state.set('list', new List(action.value));
|
||||||
|
case REMOVE_STRATEGY:
|
||||||
|
return removeStrategy(state, action);
|
||||||
|
case ADD_STRATEGY:
|
||||||
|
return state.update('list', (list) => list.push(action.strategy));
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user