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

add archive

This commit is contained in:
sveisvei 2016-10-25 22:53:38 +02:00 committed by Ivar Conradi Østhus
parent fa01ebe2af
commit 223d0a1421
9 changed files with 163 additions and 38 deletions

View File

@ -0,0 +1,15 @@
import { connect } from 'react-redux';
import ListComponent from './archive-list-component';
import { fetchArchive, revive } from '../../store/archive-actions';
const mapStateToProps = (state) => {
const archive = state.archive.get('list').toArray(); // eslint-disable-line no-shadow
return {
archive,
};
};
const ArchiveListContainer = connect(mapStateToProps, { fetchArchive, revive })(ListComponent);
export default ArchiveListContainer;

View File

@ -0,0 +1,48 @@
import React, { Component } from 'react';
import { List, ListItem, ListSubHeader } from 'react-toolbox/lib/list';
import FontIcon from 'react-toolbox/lib/font_icon';
import Chip from 'react-toolbox/lib/chip';
import Switch from 'react-toolbox/lib/switch';
const ArchivedFeature = ({ feature, revive }) => {
const { name, description, enabled, strategies } = feature; // eslint-disable-line no-shadow
const actions = [
<div>{strategies && strategies.map(s => <Chip><small>{s.name}</small></Chip>)}</div>,
<FontIcon style={{ cursor: 'pointer' }} value="restore" onClick={() => revive(feature)} />,
];
const leftActions = [
<Switch disabled checked={enabled} />,
];
return (
<ListItem
key={name}
leftActions={leftActions}
rightActions={actions}
caption={name}
legend={(description && description.substring(0, 100)) || '-'}
/>
);
};
class ArchiveList extends Component {
componentDidMount () {
this.props.fetchArchive();
}
render () {
const { archive, revive } = this.props;
return (
<List ripple >
<ListSubHeader caption="Archive" />
{archive.length > 0 ?
archive.map((feature, i) => <ArchivedFeature key={i} feature={feature} revive={revive} />) :
<ListItem caption="No archived feature toggles" />}
</List>
);
}
}
export default ArchiveList;

View File

@ -10,6 +10,6 @@ const mapStateToProps = (state) => {
}; };
}; };
const StrategiesListContainer = connect(mapStateToProps, { fetchHistory })(ListComponent); const HistoryListContainer = connect(mapStateToProps, { fetchHistory })(ListComponent);
export default StrategiesListContainer; export default HistoryListContainer;

View File

@ -1,13 +1,7 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { List, ListItem, ListSubHeader, ListDivider } from 'react-toolbox/lib/list'; import { List, ListItem, ListSubHeader } from 'react-toolbox/lib/list';
import FontIcon from 'react-toolbox/lib/font_icon';
import Chip from 'react-toolbox/lib/chip';
class StrategiesListComponent extends Component { class HistoryList extends Component {
static contextTypes = {
router: React.PropTypes.object,
}
componentDidMount () { componentDidMount () {
this.props.fetchHistory(); this.props.fetchHistory();
@ -33,7 +27,7 @@ class StrategiesListComponent extends Component {
} }
render () { render () {
const { history } = this.props; const { history } = this.props; // eslint-disable-line no-shadow
return ( return (
<List ripple > <List ripple >
@ -61,4 +55,4 @@ class StrategiesListComponent extends Component {
} }
export default StrategiesListComponent; export default HistoryList;

View File

@ -0,0 +1,36 @@
const URI = '/archive';
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}/features`)
.then(throwIfNotSuccess)
.then(response => response.json());
}
function revive (feature) {
return fetch(`${URI}/revive`, {
method: 'POST',
headers,
body: JSON.stringify(feature),
}).then(throwIfNotSuccess);
}
module.exports = {
fetchAll,
revive,
};

View File

@ -1,28 +1,6 @@
import React, { Component } from 'react'; import React from 'react';
import { Card, CardTitle, CardText } from 'react-toolbox'; import Archive from '../../component/archive/archive-container';
const render = () => <Archive />;
export default class Archive extends Component { export default render;
render () {
return (
<Card>
<CardTitle>Archived Feture Toggles</CardTitle>
<CardText>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam pharetra finibus
ullamcorper. Proin laoreet faucibus venenatis. Aenean quis leo finibus, maximus
nisi finibus, fringilla ex. Nam mollis congue orci eu consectetur. Aliquam a
massa quis tortor vestibulum lacinia. Phasellus nisi velit, mattis vel nulla
a, rhoncus porta dui. Vestibulum viverra augue in pellentesque tincidunt.
Aliquam rhoncus nunc ipsum, sed vehicula leo dictum in. Phasellus accumsan
elis sem, in ullamcorper nisi accumsan vitae. Nullam vitae consectetur mi,
sed vulputate augue. In quis augue tellus. Duis convallis cursus elit, in
interdum nisl pulvinar viverra. Sed vel ornare sapien, eu consectetur metus.
Vivamus at porta nisl. Nullam in aliquam nisl.
</p>
</CardText>
</Card>
);
}
};

View File

@ -0,0 +1,33 @@
import api from '../data/archive-api';
export const REVIVE_TOGGLE = 'REVIVE_TOGGLE';
export const RECEIVE_ARCHIVE = 'RECEIVE_ARCHIVE';
export const ERROR_RECEIVE_ARCHIVE = 'ERROR_RECEIVE_ARCHIVE';
const receiveArchive = (json) => ({
type: RECEIVE_ARCHIVE,
value: json.features,
});
const reviveToggle = (archiveFeatureToggle) => ({
type: REVIVE_TOGGLE,
value: archiveFeatureToggle,
});
const errorReceiveArchive = (statusCode) => ({
type: ERROR_RECEIVE_ARCHIVE,
statusCode,
});
export function revive (featureToggle) {
return dispatch => api.revive(featureToggle)
.then(() => dispatch(reviveToggle(featureToggle)))
.catch(error => dispatch(errorReceiveArchive(error)));
}
export function fetchArchive () {
return dispatch => api.fetchAll()
.then(json => dispatch(receiveArchive(json)))
.catch(error => dispatch(errorReceiveArchive(error)));
}

View File

@ -0,0 +1,19 @@
import { List, Map as $Map } from 'immutable';
import { RECEIVE_ARCHIVE, REVIVE_TOGGLE } from './archive-actions';
function getInitState () {
return new $Map({ list: new List() });
}
const archiveStore = (state = getInitState(), action) => {
switch (action.type) {
case REVIVE_TOGGLE:
return state.update('list', (list) => list.remove(list.indexOf(action.value)));
case RECEIVE_ARCHIVE:
return state.set('list', new List(action.value));
default:
return state;
}
};
export default archiveStore;

View File

@ -3,12 +3,14 @@ import features from './feature-store';
import strategies from './strategy-store'; import strategies from './strategy-store';
import input from './input-store'; import input from './input-store';
import history from './history-store'; // eslint-disable-line import history from './history-store'; // eslint-disable-line
import archive from './archive-store';
const unleashStore = combineReducers({ const unleashStore = combineReducers({
features, features,
strategies, strategies,
input, input,
history, history,
archive,
}); });
export default unleashStore; export default unleashStore;