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

added redux with a small example store

This commit is contained in:
ivaosthu 2016-09-16 21:36:35 +02:00
parent 437641ac2e
commit 0ea97f77b5
17 changed files with 244 additions and 22 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -34,8 +34,10 @@
"react": "^15.3.1", "react": "^15.3.1",
"react-addons-css-transition-group": "^15.3.1", "react-addons-css-transition-group": "^15.3.1",
"react-dom": "^15.3.1", "react-dom": "^15.3.1",
"react-redux": "^4.4.5",
"react-router": "^2.8.0", "react-router": "^2.8.0",
"react-toolbox": "^1.2.1" "react-toolbox": "^1.2.1",
"redux": "^3.6.0"
}, },
"devDependencies": { "devDependencies": {
"babel-core": "^6.14.0", "babel-core": "^6.14.0",
@ -49,6 +51,7 @@
"extract-text-webpack-plugin": "^1.0.1", "extract-text-webpack-plugin": "^1.0.1",
"node-sass": "~3.7.0", "node-sass": "~3.7.0",
"postcss-loader": "^0.13.0", "postcss-loader": "^0.13.0",
"redux-devtools": "^3.3.1",
"sass-loader": "^4.0.2", "sass-loader": "^4.0.2",
"style-loader": "^0.13.1", "style-loader": "^0.13.1",
"toolbox-loader": "0.0.3", "toolbox-loader": "0.0.3",

View File

@ -6,9 +6,9 @@ export default class UnleashNav extends Component {
render () { render () {
return ( return (
<List selectable ripple> <List selectable ripple>
<Link to="/features"><ListItem selectable className="active" caption="Feature Toggles" /></Link> <Link to="/"><ListItem selectable className="active" caption="Feature Toggles" /></Link>
<Link to="/strategies"><ListItem selectable caption="Strategies" /></Link> <Link to="/strategies"><ListItem selectable caption="Strategies" /></Link>
<Link to="/log"><ListItem selectable caption="Log" /></Link> <Link to="/logs"><ListItem selectable caption="Log" /></Link>
<Link to="/archive"><ListItem selectable caption="Archive" /></Link> <Link to="/archive"><ListItem selectable caption="Archive" /></Link>
<ListDivider /> <ListDivider />
<ListSubHeader Resources/> <ListSubHeader Resources/>

View File

@ -0,0 +1,11 @@
let nextFeatureId = 0;
export const addFeatureToggle = (featureName) => ({
type: 'ADD_FEATURE_TOGGLE',
id: nextFeatureId++,
featureName,
});
export const toggleFeature = (id) => ({
type: 'TOGGLE_FEATURE_TOGGLE',
id,
});

View File

@ -0,0 +1,31 @@
import React from 'react';
import { connect } from 'react-redux';
import { addFeatureToggle } from '../../action';
let AddFeatureToggle = ({ dispatch }) => {
let input;
return (
<div>
<form onSubmit={e => {
e.preventDefault();
if (!input.value.trim()) {
return;
}
dispatch(addFeatureToggle(input.value));
input.value = '';
}}>
<input ref={node => {
input = node;
}} />
<button type="submit">
Add Feature Toggle.
</button>
</form>
</div>
);
};
AddFeatureToggle = connect()(AddFeatureToggle);
export default AddFeatureToggle;

View File

@ -0,0 +1,16 @@
import React, { PropTypes } from 'react';
const Feature = ({ onClick, featureName, enabled }) => (
<li>
{featureName} is {enabled ? 'enabled ' : 'disabled '}
<a onClick={onClick} href="#">toggle</a>
</li>
);
Feature.propTypes = {
onClick: PropTypes.func.isRequired,
enabled: PropTypes.bool.isRequired,
featureName: PropTypes.string.isRequired,
};
export default Feature;

View File

@ -0,0 +1,21 @@
import React, { PropTypes } from 'react';
import Feature from './Feature';
const FeatureList = ({ features, onFeatureClick }) => (
<ul>
{features.map(featureToggle =>
<Feature
key={featureToggle.id}
{...featureToggle}
onClick={() => onFeatureClick(featureToggle.id)}
/>
)}
</ul>
);
FeatureList.propTypes = {
onFeatureClick: PropTypes.func.isRequired,
features: PropTypes.array.isRequired,
};
export default FeatureList;

View File

@ -0,0 +1,21 @@
import { connect } from 'react-redux';
import { toggleFeature } from '../../action';
import FeatureList from './FeatureList';
const mapStateToProps = (state) => ({
features: state.features,
});
const mapDispatchToProps = (dispatch) => ({
onFeatureClick: (id) => {
dispatch(toggleFeature(id));
},
});
const FeatureListContainer = connect(
mapStateToProps,
mapDispatchToProps
)(FeatureList);
export default FeatureListContainer;

View File

@ -1,17 +1,27 @@
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import { Router, Route, hashHistory } from 'react-router'; import { Router, Route, IndexRoute, hashHistory } from 'react-router';
import App from './App'; import { Provider } from 'react-redux';
import Features from './Features'; import { createStore } from 'redux';
import Strategies from './Strategies';
ReactDOM.render(( import store from './store';
import App from './App';
import Features from './page/features';
import Strategies from './page/strategies';
import Logs from './page/logs';
import Archive from './page/archive';
const unleashStore = createStore(store);
ReactDOM.render(
<Provider store={unleashStore}>
<Router history={hashHistory}> <Router history={hashHistory}>
<Route path="/" component={App}> <Route path="/" component={App}>
<Route path="/features" component={Features} /> <IndexRoute component={Features} />
<Route path="/strategies" component={Strategies} /> <Route path="/strategies" component={Strategies} />
<Route path="/log" component={Strategies} /> <Route path="/logs" component={Logs} />
<Route path="/archive" component={Strategies} /> <Route path="/archive" component={Archive} />
</Route> </Route>
</Router> </Router>
), document.getElementById('app')); </Provider>, document.getElementById('app'));

View File

@ -2,11 +2,11 @@ import React, { Component } from 'react';
import { Card, CardTitle, CardText } from 'react-toolbox'; import { Card, CardTitle, CardText } from 'react-toolbox';
export default class Features extends Component { export default class Archive extends Component {
render () { render () {
return ( return (
<Card> <Card>
<CardTitle>Feture toggles</CardTitle> <CardTitle>Archived Feture Toggles</CardTitle>
<CardText> <CardText>
<p> <p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam pharetra finibus Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam pharetra finibus

View File

@ -0,0 +1,17 @@
import React, { Component } from 'react';
import FeatureListContainer from '../../component/feature/FeatureListContainer';
import AddFeatureToggle from '../../component/feature/AddFeatureToggle';
export default class Features extends Component {
render () {
return (
<div>
<h1>Feature Toggles</h1>
<AddFeatureToggle />
<FeatureListContainer />
</div>
);
}
};

View File

@ -1,12 +1,11 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
export default class Strategies extends Component { export default class Strategies extends Component {
render () { render () {
return ( return (
<p> <div>
<h1>Strategies</h1> <h1>Strategies</h1>
</p> </div>
); );
} }
}; };

View File

@ -0,0 +1,39 @@
const feature = (state = {}, action) => {
switch (action.type) {
case 'ADD_FEATURE_TOGGLE':
return {
id: action.id,
featureName: action.featureName,
enabled: false,
};
case 'TOGGLE_FEATURE_TOGGLE':
if (state.id !== action.id) {
return state;
}
return Object.assign({}, state, {
enabled: !state.enabled,
});
default:
return state;
}
};
const features = (state = [{ id: 1, featureName: 'test', enabled: true }], action) => {
switch (action.type) {
case 'ADD_FEATURE_TOGGLE':
return [
...state,
feature(undefined, action),
];
case 'TOGGLE_FEATURE_TOGGLE':
return state.map(t =>
feature(t, action)
);
default:
return state;
}
};
export default features;

View File

@ -0,0 +1,8 @@
import { combineReducers } from 'redux';
import features from './features';
const unleashStore = combineReducers({
features,
});
export default unleashStore;