1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-01-31 00:16:47 +01:00

minor feature cleanup

This commit is contained in:
sveisvei 2016-10-24 18:48:24 +02:00
parent 90c9682634
commit 993785f264
11 changed files with 166 additions and 176 deletions

View File

@ -3,72 +3,81 @@ import { Input, Switch, Button } from 'react-toolbox';
import AddFeatureToggleStrategy from './AddFeatureToggleStrategy'; import AddFeatureToggleStrategy from './AddFeatureToggleStrategy';
import ConfiguredStrategies from './ConfiguredStrategies'; import ConfiguredStrategies from './ConfiguredStrategies';
class AddFeatureToggleUI extends React.Component { const AddFeatureToggleUI = ({
static propTypes () { strategies,
return { featureToggle,
strategies: PropTypes.array.required, updateField,
featureToggle: PropTypes.object, addStrategy,
updateField: PropTypes.func.required, removeStrategy,
addStrategy: PropTypes.func.required, onSubmit,
removeStrategy: PropTypes.func.required, onCancel,
onSubmit: PropTypes.func.required, editmode,
onCancel: PropTypes.func.required, }) => {
editmode: PropTypes.bool, const {
}; name, // eslint-disable-line
} description,
enabled,
} = featureToggle;
const configuredStrategies = featureToggle.strategies;
render () { return (
const configuredStrategies = this.props.featureToggle.strategies; <form onSubmit={onSubmit}>
<section>
return ( <Input
<form onSubmit={this.props.onSubmit}> type="text"
<section> label="Name"
<Input name="name"
type="text" disabled={editmode}
label="Name" required
name="name" value={name}
disabled={this.props.editmode} onChange={updateField.bind(this, 'name')} />
required <Input
value={this.props.featureToggle.name} type="text"
onChange={this.props.updateField.bind(this, 'name')} /> multiline label="Description"
<Input required
type="text" value={description}
multiline label="Description" onChange={updateField.bind(this, 'description')} />
required
value={this.props.featureToggle.description}
onChange={this.props.updateField.bind(this, 'description')} />
<br />
<Switch
checked={this.props.featureToggle.enabled}
label="Enabled"
onChange={this.props.updateField.bind(this, 'enabled')} />
<br />
</section>
<section>
<strong>Activation strategies</strong>
<ConfiguredStrategies
configuredStrategies={configuredStrategies}
removeStrategy={this.props.removeStrategy} />
</section>
<section>
<AddFeatureToggleStrategy
strategies={this.props.strategies}
addStrategy={this.props.addStrategy} />
</section>
<br /> <br />
<Switch
checked={enabled}
label="Enabled"
onChange={updateField.bind(this, 'enabled')} />
<Button type="submit" raised primary label={this.props.editmode ? 'Update' : 'Create'} /> <br />
<Button type="cancel" raised label="Cancel" onClick={this.props.onCancel} /> </section>
</form>
); <section>
} <strong>Activation strategies</strong>
} <ConfiguredStrategies
configuredStrategies={configuredStrategies}
removeStrategy={removeStrategy} />
</section>
<section>
<AddFeatureToggleStrategy strategies={strategies} addStrategy={addStrategy} />
</section>
<br />
<Button type="submit" raised primary label={editmode ? 'Update' : 'Create'} />
&nbsp;
<Button type="cancel" raised label="Cancel" onClick={onCancel} />
</form>
);
};
AddFeatureToggleUI.propTypes = {
strategies: PropTypes.array.required,
featureToggle: PropTypes.object,
updateField: PropTypes.func.required,
addStrategy: PropTypes.func.required,
removeStrategy: PropTypes.func.required,
onSubmit: PropTypes.func.required,
onCancel: PropTypes.func.required,
editmode: PropTypes.bool,
};
export default AddFeatureToggleUI; export default AddFeatureToggleUI;

View File

@ -2,9 +2,11 @@ import React, { PropTypes } from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { editFeatureToggle } from '../../store/feature-actions'; import { editFeatureToggle } from '../../store/feature-actions';
import AddFeatureToggleUI from './AddFeatureToggleUI'; import AddFeatureToggleUI from './AddFeatureToggleUI';
import { fetchStrategies } from '../../store/strategy-actions';
const mapStateToProps = (state, ownProps) => ({ const mapStateToProps = (state, ownProps) => ({
strategies: state.strategies.toJS(), strategies: state.strategies.get('list').toArray(),
featureToggle: state.features.toJS().find(toggle => toggle.name === ownProps.featureToggleName) || {}, featureToggle: state.features.toJS().find(toggle => toggle.name === ownProps.featureToggleName) || {},
}); });
@ -28,6 +30,11 @@ class EditFeatureToggle extends React.Component {
}; };
} }
componentDidMount () {
// todo fetch feature if missing? (reload of page does not fetch data from url)
this.props.fetchStrategies();
}
static contextTypes = { static contextTypes = {
router: React.PropTypes.object, router: React.PropTypes.object,
} }
@ -62,20 +69,18 @@ class EditFeatureToggle extends React.Component {
render () { render () {
return ( return (
<div> <AddFeatureToggleUI
<AddFeatureToggleUI editmode="true"
editmode="true" strategies={this.props.strategies}
strategies={this.props.strategies} featureToggle={this.state}
featureToggle={this.state} updateField={this.updateField}
updateField={this.updateField} addStrategy={this.addStrategy}
addStrategy={this.addStrategy} removeStrategy={this.removeStrategy}
removeStrategy={this.removeStrategy} onSubmit={this.onSubmit}
onSubmit={this.onSubmit} onCancel={this.onCancel}
onCancel={this.onCancel} />
/>
</div>
); );
} }
} }
export default connect(mapStateToProps)(EditFeatureToggle); export default connect(mapStateToProps, { fetchStrategies })(EditFeatureToggle);

View File

@ -1,33 +1,43 @@
/* eslint no-shadow: ["error", { "allow": ["name"] }]*/
import React, { PropTypes } from 'react'; import React, { PropTypes } from 'react';
import { Switch, FontIcon } from 'react-toolbox';
import { Link } from 'react-router';
const Feature = ({ onClick, name, enabled, strategies, onFeatureRemove }) => ( import { Link } from 'react-router';
<tr> import FontIcon from 'react-toolbox/lib/font_icon';
<td style={{ paddingTop: '1.5rem' }}><Switch onChange={onClick} checked={enabled} /></td> import Switch from 'react-toolbox/lib/switch';
<td> import { ListItem } from 'react-toolbox/lib/list';
<Link to={`/features/edit/${name}`} title={`Edit ${name}`}>
{name} import style from './feature.scss';
</Link>
</td> const Feature = ({ feature, onFeatureClick, onFeatureRemove }) => {
<td>{strategies.map(s => s.name).join(', ')}</td> const { name, description, enabled, strategies } = feature; // eslint-disable-line no-shadow
<td style={{ textAlign: 'right' }}>
<Link to={`/features/edit/${name}`} title={`Edit ${name}`}> const actions = [
<FontIcon value="edit" /> strategies.map(s => s.name).join(', '),
</Link> <Link to={`/features/edit/${name}`} title={`Edit ${name}`}>
<FontIcon style={{ cursor: 'pointer' }} value="delete" onClick={onFeatureRemove} /> <FontIcon value="edit" className={style.action} />
</td> </Link>,
</tr> <FontIcon className={style.action} value="delete" onClick={() => onFeatureRemove(name)} />,
); ];
const leftActions = [
<Switch onChange={() => onFeatureClick(feature)} checked={enabled} />,
];
return (
<ListItem
leftActions={leftActions}
rightActions={actions}
caption={<Link to={`/features/edit/${name}`} title={`Edit ${name}`} className={style.link}>
{name}
</Link>}
legend={(description && description.substring(0, 100)) || '-'}
/>
);
};
Feature.propTypes = { Feature.propTypes = {
onClick: PropTypes.func.isRequired, feature: PropTypes.object,
onFeatureRemove: PropTypes.func.isRequired, onFeatureClick: PropTypes.func,
enabled: PropTypes.bool.isRequired, onFeatureRemove: PropTypes.func,
strategies: PropTypes.array.isRequired,
name: PropTypes.string.isRequired,
}; };
export default Feature; export default Feature;

View File

@ -1,11 +1,8 @@
import React, { PropTypes } from 'react'; import React, { PropTypes } from 'react';
import Feature from './Feature'; import Feature from './Feature';
import style from './table.scss'; import { List, ListItem, ListSubHeader, ListDivider } from 'react-toolbox/lib/list';
export default class FeatureList extends React.Component { export default class FeatureList extends React.Component {
constructor () {
super();
}
static propTypes () { static propTypes () {
return { return {
@ -16,35 +13,28 @@ export default class FeatureList extends React.Component {
}; };
} }
static contextTypes = {
router: React.PropTypes.object,
}
componentDidMount () { componentDidMount () {
this.props.fetchFeatureToggles(); this.props.fetchFeatureToggles();
} }
render () { render () {
const onFeatureClick = this.props.onFeatureClick; const { features, onFeatureClick, onFeatureRemove } = this.props;
const onFeatureRemove = this.props.onFeatureRemove;
const features = this.props.features.map(featureToggle =>
<Feature key={featureToggle.name}
{...featureToggle}
onClick={() => onFeatureClick(featureToggle)}
onFeatureRemove={() => onFeatureRemove(featureToggle.name)}
/>
);
return ( return (
<table className={style.ztable}> <List>
<thead> <ListSubHeader caption="Feature toggles" />
<tr> {features.map(feature =>
<th width="80">Enabled</th> <Feature feature={feature} onFeatureClick={onFeatureClick} onFeatureRemove={onFeatureRemove}/>
<th>Feature Toggle</th> )}
<th>Strategies</th> <ListDivider />
<th width="100" style={{ textAlign: 'right' }}>Actions</th> <ListItem
</tr> onClick={() => this.context.router.push('/features/create')}
</thead> caption="Add" legend="new feature toggle" leftIcon="add" />
<tbody> </List>
{features}
</tbody>
</table>
); );
} }
} }

View File

@ -4,7 +4,6 @@ import FeatureList from './FeatureList';
const mapStateToProps = (state) => ({ const mapStateToProps = (state) => ({
features: state.features.toJS(), features: state.features.toJS(),
strategies: state.strategies.toJS(),
}); });
const mapDispatchToProps = { const mapDispatchToProps = {

View File

@ -0,0 +1,8 @@
.link {
color: #212121;
}
.action {
color: #aaa !important;
cursor: pointer;
}

View File

@ -1,12 +0,0 @@
.ztable tbody tr:nth-child(odd) {
background-color: #efefef;
}
.ztable {
margin: 10px;
border-collapse: separate;
border-spacing: 0;
}
.ztable td, th {
padding: 4px 10px;
}

View File

@ -1,13 +1,11 @@
import React, { Component } from 'react'; import React from 'react';
import AddFeatureToggle from '../../component/feature/AddFeatureToggle'; import AddFeatureToggle from '../../component/feature/AddFeatureToggle';
export default class Features extends Component { const render = () => (
render () { <div>
return ( <h3>Create feature toggle</h3>
<div> <AddFeatureToggle />
<h1>Create Feature Toggle</h1> </div>
<AddFeatureToggle /> );
</div>
); export default render;
}
};

View File

@ -8,14 +8,10 @@ export default class Features extends Component {
}; };
} }
static contextTypes = {
router: React.PropTypes.object,
}
render () { render () {
return ( return (
<div> <div>
<h1>Edit Feature Toggle</h1> <h3>Edit feature toggle</h3>
<EditFeatureToggle featureToggleName={this.props.params.name} /> <EditFeatureToggle featureToggleName={this.props.params.name} />
</div> </div>
); );

View File

@ -1,21 +1,8 @@
import React, { Component } from 'react'; import React from 'react';
import FeatureListContainer from '../../component/feature/FeatureListContainer'; import FeatureListContainer from '../../component/feature/FeatureListContainer';
import { Button } from 'react-toolbox';
const render = () => (<FeatureListContainer />);
export default render;
export default class Features extends Component {
static contextTypes = {
router: React.PropTypes.object,
}
render () {
const createHref = this.context.router.createHref('/features/create');
return (
<div>
<h1>Feature Toggles</h1>
<Button href={createHref} icon="add" raised primary label="New Feature Toggle"/>
<FeatureListContainer />
</div>
);
}
};

View File

@ -4,7 +4,7 @@ export default class EventHisotry extends Component {
render () { render () {
return ( return (
<div> <div>
<h1>Event history</h1> <h2>Event history</h2>
</div> </div>
); );
} }