mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	add archive
This commit is contained in:
		
							parent
							
								
									42c8d2ecd8
								
							
						
					
					
						commit
						60d4426272
					
				@ -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;
 | 
				
			||||||
@ -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;
 | 
				
			||||||
@ -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;
 | 
				
			||||||
 | 
				
			|||||||
@ -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;
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										36
									
								
								packages/unleash-frontend-next/src/data/archive-api.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								packages/unleash-frontend-next/src/data/archive-api.js
									
									
									
									
									
										Normal 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,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -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>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										33
									
								
								packages/unleash-frontend-next/src/store/archive-actions.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								packages/unleash-frontend-next/src/store/archive-actions.js
									
									
									
									
									
										Normal 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)));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										19
									
								
								packages/unleash-frontend-next/src/store/archive-store.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								packages/unleash-frontend-next/src/store/archive-store.js
									
									
									
									
									
										Normal 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;
 | 
				
			||||||
@ -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;
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user