1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-06-04 01:18:20 +02:00

Make edit strategy view

This commit is contained in:
ivaosthu 2016-12-17 14:37:11 +01:00
parent efcfcfa347
commit 398f46c561
8 changed files with 257 additions and 89 deletions

View File

@ -1,4 +1,4 @@
import React, { PropTypes } from 'react'; import React, { PropTypes, Component } from 'react';
import { Textfield, IconButton, Menu, MenuItem, Checkbox } from 'react-mdl'; import { Textfield, IconButton, Menu, MenuItem, Checkbox } from 'react-mdl';
import { HeaderTitle, FormButtons } from '../common'; import { HeaderTitle, FormButtons } from '../common';
@ -65,15 +65,43 @@ const Parameters = ({ input = [], count = 0, updateInList }) => (
/>) />)
}</div>); }</div>);
const AddStrategy = ({ class AddStrategy extends Component {
static propTypes () {
return {
input: PropTypes.object,
setValue: PropTypes.func,
updateInList: PropTypes.func,
incValue: PropTypes.func,
clear: PropTypes.func,
onCancel: PropTypes.func,
onSubmit: PropTypes.func,
editmode: PropTypes.bool,
initCallRequired: PropTypes.bool,
init: PropTypes.func,
};
}
componentWillMount () {
// TODO unwind this stuff
if (this.props.initCallRequired === true) {
this.props.init(this.props.input);
}
}
render () {
const {
input, input,
setValue, setValue,
updateInList, updateInList,
incValue, incValue,
// clear,
onCancel, onCancel,
editmode = false,
onSubmit, onSubmit,
}) => ( } = this.props;
return (
<form onSubmit={onSubmit(input)}> <form onSubmit={onSubmit(input)}>
<HeaderTitle title="Create new strategy" subtitle="It is not possible to edit a strategy after it is created."/> <HeaderTitle title="Create new strategy" subtitle="It is not possible to edit a strategy after it is created."/>
<section style={{ margin: '16px 20px' }}> <section style={{ margin: '16px 20px' }}>
@ -81,6 +109,7 @@ const AddStrategy = ({
floatingLabel floatingLabel
name="name" name="name"
required required
disabled={editmode}
pattern="^[0-9a-zA-Z\.\-]+$" pattern="^[0-9a-zA-Z\.\-]+$"
onChange={({ target }) => setValue('name', trim(target.value))} onChange={({ target }) => setValue('name', trim(target.value))}
value={input.name} value={input.name}
@ -109,19 +138,12 @@ const AddStrategy = ({
<hr /> <hr />
<FormButtons <FormButtons
submitText={editmode ? 'Update' : 'Create'}
onCancel={onCancel} onCancel={onCancel}
/> />
</form> </form>
); );
}
AddStrategy.propTypes = { }
input: PropTypes.object,
setValue: PropTypes.func,
updateInList: PropTypes.func,
incValue: PropTypes.func,
clear: PropTypes.func,
onCancel: PropTypes.func,
onSubmit: PropTypes.func,
};
export default AddStrategy; export default AddStrategy;

View File

@ -0,0 +1,71 @@
import { connect } from 'react-redux';
import { createMapper, createActions } from '../input-helpers';
import { updateStrategy } from '../../store/strategy/actions';
import AddStrategy from './add-strategy';
const ID = 'edit-strategy';
function getId (props) {
return [ID, props.strategy.name];
}
// TODO: need to scope to the active strategy
// best is to emulate the "input-storage"?
const mapStateToProps = createMapper({
id: getId,
getDefault: (state, ownProps) => ownProps.strategy,
prepare: (props) => {
props.editmode = true;
return props;
},
});
const prepare = (methods, dispatch) => {
methods.onSubmit = (input) => (
(e) => {
e.preventDefault();
// clean
const parameters = input.parameters
.filter((name) => !!name)
.map(({
name,
type = 'string',
description = '',
required = false,
}) => ({
name,
type,
description,
required,
}));
updateStrategy({
name: input.name,
description: input.description,
parameters,
})(dispatch)
.then(() => methods.clear())
// somewhat quickfix / hacky to go back..
.then(() => window.history.back());
}
);
methods.onCancel = (e) => {
e.preventDefault();
methods.clear();
// somewhat quickfix / hacky to go back..
window.history.back();
};
return methods;
};
const actions = createActions({
id: getId,
prepare,
});
export default connect(mapStateToProps, actions)(AddStrategy);

View File

@ -1,19 +1,8 @@
import React, { Component } from 'react'; import React, { PureComponent } from 'react';
import { Grid, Cell, List, ListItem, ListItemContent } from 'react-mdl'; import { Grid, Cell, List, ListItem, ListItemContent } from 'react-mdl';
import { AppsLinkList, TogglesLinkList, HeaderTitle } from '../common'; import { AppsLinkList, TogglesLinkList } from '../common';
class ShowStrategyComponent extends Component { class ShowStrategyComponent extends PureComponent {
componentDidMount () {
if (!this.props.strategy) {
this.props.fetchStrategies();
};
if (!this.props.applications || this.props.applications.length === 0) {
this.props.fetchApplications();
}
if (!this.props.toggles || this.props.toggles.length === 0) {
this.props.fetchFeatureToggles();
}
}
renderParameters (params) { renderParameters (params) {
if (params) { if (params) {
@ -32,24 +21,17 @@ class ShowStrategyComponent extends Component {
render () { render () {
const { const {
strategy, strategy,
strategyName,
applications, applications,
toggles, toggles,
} = this.props; } = this.props;
if (!strategy) {
return <div>Cannot find Strategy "{strategyName}".</div>;
}
const { const {
name,
description,
parameters = [], parameters = [],
} = strategy; } = strategy;
return ( return (
<div> <div>
<HeaderTitle title={name} subtitle={description} />
<Grid> <Grid>
<Cell col={12}> <Cell col={12}>
<h6>Parameters</h6> <h6>Parameters</h6>

View File

@ -0,0 +1,62 @@
import React, { Component } from 'react';
import { Tabs, Tab, ProgressBar } from 'react-mdl';
import ShowStrategy from './show-strategy-component';
import EditStrategy from './edit-container';
import { HeaderTitle } from '../common';
const EDIT = 1;
export default class StrategyDetails extends Component {
constructor (props) {
super(props);
this.state = { activeTab: 0 };
}
componentDidMount () {
if (!this.props.strategy) {
this.props.fetchStrategies();
};
if (!this.props.applications || this.props.applications.length === 0) {
this.props.fetchApplications();
}
if (!this.props.toggles || this.props.toggles.length === 0) {
this.props.fetchFeatureToggles();
}
}
getTabContent (id) {
if (id === EDIT) {
return <EditStrategy strategy={this.props.strategy} />;
} else {
return (<ShowStrategy
strategy={this.props.strategy}
toggles={this.props.toggles}
applications={this.props.applications} />);
}
}
render () {
const strategy = this.props.strategy;
if (!strategy) {
return <ProgressBar indeterminate />;
}
const tabContent = this.getTabContent(this.state.activeTab);
return (
<div>
<HeaderTitle title={strategy.name} subtitle={strategy.description} />
<Tabs activeTab={this.state.activeTab}
onChange={(tabId) => this.setState({ activeTab: tabId })} ripple>
<Tab>Details</Tab>
<Tab>Edit</Tab>
</Tabs>
<section>
<div className="content">
{tabContent}
</div>
</section>
</div>
);
}
}

View File

@ -1,5 +1,5 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import ShowStrategy from './show-strategy-component'; import ShowStrategy from './strategy-details-component';
import { fetchStrategies } from '../../store/strategy/actions'; import { fetchStrategies } from '../../store/strategy/actions';
import { fetchAll } from '../../store/application/actions'; import { fetchAll } from '../../store/application/actions';
import { fetchFeatureToggles } from '../../store/feature-actions'; import { fetchFeatureToggles } from '../../store/feature-actions';

View File

@ -17,6 +17,15 @@ function create (strategy) {
}).then(throwIfNotSuccess); }).then(throwIfNotSuccess);
} }
function update (strategy) {
return fetch(`${URI}/${strategy.name}`, {
method: 'put',
headers,
body: JSON.stringify(strategy),
credentials: 'include',
}).then(throwIfNotSuccess);
}
function remove (strategy) { function remove (strategy) {
return fetch(`${URI}/${strategy.name}`, { return fetch(`${URI}/${strategy.name}`, {
method: 'DELETE', method: 'DELETE',
@ -28,5 +37,6 @@ function remove (strategy) {
module.exports = { module.exports = {
fetchAll, fetchAll,
create, create,
update,
remove, remove,
}; };

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import ShowStrategy from '../../component/strategies/show-strategy-container'; import ShowStrategy from '../../component/strategies/strategy-details-container';
const render = ({ params }) => <ShowStrategy strategyName={params.strategyName} />; const render = ({ params }) => <ShowStrategy strategyName={params.strategyName} />;

View File

@ -2,21 +2,30 @@ import api from '../../data/strategy-api';
import { fetchApplicationsWithStrategyName } from '../../data/applications-api'; import { fetchApplicationsWithStrategyName } from '../../data/applications-api';
export const ADD_STRATEGY = 'ADD_STRATEGY'; export const ADD_STRATEGY = 'ADD_STRATEGY';
export const UPDATE_STRATEGY = 'UPDATE_STRATEGY';
export const REMOVE_STRATEGY = 'REMOVE_STRATEGY'; export const REMOVE_STRATEGY = 'REMOVE_STRATEGY';
export const REQUEST_STRATEGIES = 'REQUEST_STRATEGIES'; export const REQUEST_STRATEGIES = 'REQUEST_STRATEGIES';
export const START_CREATE_STRATEGY = 'START_CREATE_STRATEGY'; export const START_CREATE_STRATEGY = 'START_CREATE_STRATEGY';
export const START_UPDATE_STRATEGY = 'START_UPDATE_STRATEGY';
export const RECEIVE_STRATEGIES = 'RECEIVE_STRATEGIES'; export const RECEIVE_STRATEGIES = 'RECEIVE_STRATEGIES';
export const ERROR_RECEIVE_STRATEGIES = 'ERROR_RECEIVE_STRATEGIES'; export const ERROR_RECEIVE_STRATEGIES = 'ERROR_RECEIVE_STRATEGIES';
export const ERROR_CREATING_STRATEGY = 'ERROR_CREATING_STRATEGY'; export const ERROR_CREATING_STRATEGY = 'ERROR_CREATING_STRATEGY';
export const ERROR_UPDATING_STRATEGY = 'ERROR_UPDATING_STRATEGY';
const addStrategy = (strategy) => ({ type: ADD_STRATEGY, strategy }); const addStrategy = (strategy) => ({ type: ADD_STRATEGY, strategy });
const createRemoveStrategy = (strategy) => ({ type: REMOVE_STRATEGY, strategy }); const createRemoveStrategy = (strategy) => ({ type: REMOVE_STRATEGY, strategy });
const updatedStrategy = (strategy) => ({ type: UPDATE_STRATEGY, strategy });
const errorCreatingStrategy = (statusCode) => ({ const errorCreatingStrategy = (statusCode) => ({
type: ERROR_CREATING_STRATEGY, type: ERROR_CREATING_STRATEGY,
statusCode, statusCode,
}); });
const errorUpdatingStrategy = (statusCode) => ({
type: ERROR_UPDATING_STRATEGY,
statusCode,
});
const startRequest = () => ({ type: REQUEST_STRATEGIES }); const startRequest = () => ({ type: REQUEST_STRATEGIES });
@ -32,6 +41,8 @@ const errorReceiveStrategies = (statusCode) => ({
statusCode, statusCode,
}); });
const startUpdate = () => ({ type: START_UPDATE_STRATEGY });
export function fetchStrategies () { export function fetchStrategies () {
return dispatch => { return dispatch => {
dispatch(startRequest()); dispatch(startRequest());
@ -52,6 +63,16 @@ export function createStrategy (strategy) {
}; };
} }
export function updateStrategy (strategy) {
return dispatch => {
dispatch(startUpdate());
return api.update(strategy)
.then(() => dispatch(updatedStrategy(strategy)))
.catch(error => dispatch(errorUpdatingStrategy(error)));
};
}
export function removeStrategy (strategy) { export function removeStrategy (strategy) {
return dispatch => api.remove(strategy) return dispatch => api.remove(strategy)