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

Basic implementation of deprecation/reactivation of strategies

This commit is contained in:
Christopher Kolstad 2021-01-21 15:27:24 +01:00
parent c536a892b9
commit 3014c0029d
10 changed files with 136 additions and 10 deletions

View File

@ -61,7 +61,9 @@ class AddStrategy extends React.Component {
/> />
<Menu target="strategies-add" valign="bottom" align="right" ripple style={menuStyle}> <Menu target="strategies-add" valign="bottom" align="right" ripple style={menuStyle}>
<MenuItem disabled>Add Strategy:</MenuItem> <MenuItem disabled>Add Strategy:</MenuItem>
{this.props.strategies.map(s => ( {this.props.strategies
.filter(s => !s.deprecated)
.map(s => (
<MenuItem key={s.name} title={s.description} onClick={() => this.addStrategy(s.name)}> <MenuItem key={s.name} title={s.description} onClick={() => this.addStrategy(s.name)}>
{s.name} {s.name}
</MenuItem> </MenuItem>

View File

@ -67,9 +67,17 @@ exports[`renders correctly with one strategy 1`] = `
> >
<strong> <strong>
Another Another
</strong> </strong>
</a> </a>
</react-mdl-ListItemContent> </react-mdl-ListItemContent>
<react-mdl-Button
name="remove"
onClick={[Function]}
>
Deprecate
</react-mdl-Button>
<react-mdl-IconButton <react-mdl-IconButton
name="delete" name="delete"
onClick={[Function]} onClick={[Function]}
@ -132,9 +140,17 @@ exports[`renders correctly with one strategy without permissions 1`] = `
> >
<strong> <strong>
Another Another
</strong> </strong>
</a> </a>
</react-mdl-ListItemContent> </react-mdl-ListItemContent>
<react-mdl-Button
name="remove"
onClick={[Function]}
>
Deprecate
</react-mdl-Button>
</react-mdl-ListItem> </react-mdl-ListItem>
</react-mdl-List> </react-mdl-List>

View File

@ -58,6 +58,7 @@ exports[`renders correctly with one strategy 1`] = `
> >
<div> <div>
<react-mdl-Grid> <react-mdl-Grid>
<react-mdl-Cell <react-mdl-Cell
col={12} col={12}
> >

View File

@ -18,6 +18,8 @@ test('renders correctly with one strategy', () => {
strategies={[strategy]} strategies={[strategy]}
fetchStrategies={jest.fn()} fetchStrategies={jest.fn()}
removeStrategy={jest.fn()} removeStrategy={jest.fn()}
deprecateStrategy={jest.fn()}
reactivateStrategy={jest.fn()}
history={{}} history={{}}
hasPermission={permission => [CREATE_STRATEGY, DELETE_STRATEGY].indexOf(permission) !== -1} hasPermission={permission => [CREATE_STRATEGY, DELETE_STRATEGY].indexOf(permission) !== -1}
/> />
@ -38,6 +40,8 @@ test('renders correctly with one strategy without permissions', () => {
strategies={[strategy]} strategies={[strategy]}
fetchStrategies={jest.fn()} fetchStrategies={jest.fn()}
removeStrategy={jest.fn()} removeStrategy={jest.fn()}
deprecateStrategy={jest.fn()}
reactivateStrategy={jest.fn()}
history={{}} history={{}}
hasPermission={() => false} hasPermission={() => false}
/> />

View File

@ -2,7 +2,7 @@ import React, { Component } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { List, ListItem, ListItemContent, IconButton, Card } from 'react-mdl'; import { List, ListItem, ListItemContent, IconButton, Card, Button } from 'react-mdl';
import { HeaderTitle, styles as commonStyles } from '../common'; import { HeaderTitle, styles as commonStyles } from '../common';
import { CREATE_STRATEGY, DELETE_STRATEGY } from '../../permissions'; import { CREATE_STRATEGY, DELETE_STRATEGY } from '../../permissions';
@ -11,6 +11,8 @@ class StrategiesListComponent extends Component {
strategies: PropTypes.array.isRequired, strategies: PropTypes.array.isRequired,
fetchStrategies: PropTypes.func.isRequired, fetchStrategies: PropTypes.func.isRequired,
removeStrategy: PropTypes.func.isRequired, removeStrategy: PropTypes.func.isRequired,
deprecateStrategy: PropTypes.func.isRequired,
reactivateStrategy: PropTypes.func.isRequired,
history: PropTypes.object.isRequired, history: PropTypes.object.isRequired,
hasPermission: PropTypes.func.isRequired, hasPermission: PropTypes.func.isRequired,
}; };
@ -20,7 +22,7 @@ class StrategiesListComponent extends Component {
} }
render() { render() {
const { strategies, removeStrategy, hasPermission } = this.props; const { strategies, removeStrategy, hasPermission, reactivateStrategy, deprecateStrategy } = this.props;
return ( return (
<Card shadow={0} className={commonStyles.fullwidth} style={{ overflow: 'visible' }}> <Card shadow={0} className={commonStyles.fullwidth} style={{ overflow: 'visible' }}>
@ -45,9 +47,20 @@ class StrategiesListComponent extends Component {
<ListItem key={i} twoLine> <ListItem key={i} twoLine>
<ListItemContent icon="extension" subtitle={strategy.description}> <ListItemContent icon="extension" subtitle={strategy.description}>
<Link to={`/strategies/view/${strategy.name}`}> <Link to={`/strategies/view/${strategy.name}`}>
<strong>{strategy.name}</strong> <strong>
{strategy.name} {strategy.deprecated ? <span>- Deprecated</span> : ''}
</strong>
</Link> </Link>
</ListItemContent> </ListItemContent>
{strategy.deprecated ? (
<Button name="add" onClick={() => reactivateStrategy(strategy)}>
Reactivate
</Button>
) : (
<Button name="remove" onClick={() => deprecateStrategy(strategy)}>
Deprecate
</Button>
)}
{strategy.editable === false || !hasPermission(DELETE_STRATEGY) ? ( {strategy.editable === false || !hasPermission(DELETE_STRATEGY) ? (
'' ''
) : ( ) : (

View File

@ -1,6 +1,6 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import StrategiesListComponent from './list-component.jsx'; import StrategiesListComponent from './list-component.jsx';
import { fetchStrategies, removeStrategy } from './../../store/strategy/actions'; import { fetchStrategies, removeStrategy, deprecateStrategy, reactivateStrategy } from './../../store/strategy/actions';
import { hasPermission } from '../../permissions'; import { hasPermission } from '../../permissions';
const mapStateToProps = state => { const mapStateToProps = state => {
@ -19,6 +19,18 @@ const mapDispatchToProps = dispatch => ({
removeStrategy(strategy)(dispatch); removeStrategy(strategy)(dispatch);
} }
}, },
deprecateStrategy: strategy => {
// eslint-disable-next-line no-alert
if (window.confirm('Are you sure you want to deprecate this strategy?')) {
deprecateStrategy(strategy)(dispatch);
}
},
reactivateStrategy: strategy => {
// eslint-disable-next-line no-alert
if (window.confirm('Are you sure you want to reactivate this strategy?')) {
reactivateStrategy(strategy)(dispatch);
}
},
fetchStrategies: () => fetchStrategies()(dispatch), fetchStrategies: () => fetchStrategies()(dispatch),
}); });

View File

@ -32,6 +32,13 @@ class ShowStrategyComponent extends PureComponent {
return ( return (
<div> <div>
<Grid> <Grid>
{strategy.deprecated ? (
<Cell>
<h5 style={{ color: '#ff0000' }}>Deprecated</h5>
</Cell>
) : (
''
)}
<Cell col={12}> <Cell col={12}>
<h6>Parameters</h6> <h6>Parameters</h6>
<hr /> <hr />

View File

@ -5,14 +5,20 @@ import { dispatchAndThrow } from '../util';
export const ADD_STRATEGY = 'ADD_STRATEGY'; export const ADD_STRATEGY = 'ADD_STRATEGY';
export const UPDATE_STRATEGY = 'UPDATE_STRATEGY'; export const UPDATE_STRATEGY = 'UPDATE_STRATEGY';
export const REMOVE_STRATEGY = 'REMOVE_STRATEGY'; export const REMOVE_STRATEGY = 'REMOVE_STRATEGY';
export const DEPRECATE_STRATEGY = 'DEPRECATE_STRATEGY';
export const REACTIVATE_STRATEGY = 'REACTIVATE_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 START_UPDATE_STRATEGY = 'START_UPDATE_STRATEGY';
export const START_DEPRECATE_STRATEGY = 'START_DEPRECATE_STRATEGY';
export const START_REACTIVATE_STRATEGY = 'START_REACTIVATE_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'; export const ERROR_UPDATING_STRATEGY = 'ERROR_UPDATING_STRATEGY';
export const ERROR_REMOVING_STRATEGY = 'ERROR_REMOVING_STRATEGY'; export const ERROR_REMOVING_STRATEGY = 'ERROR_REMOVING_STRATEGY';
export const ERROR_DEPRECATING_STRATEGY = 'ERROR_DEPRECATING_STRATEGY';
export const ERROR_REACTIVATING_STRATEGY = 'ERROR_REACTIVATING_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 });
@ -26,6 +32,11 @@ const startCreate = () => ({ type: START_CREATE_STRATEGY });
const startUpdate = () => ({ type: START_UPDATE_STRATEGY }); const startUpdate = () => ({ type: START_UPDATE_STRATEGY });
const startDeprecate = () => ({ type: START_DEPRECATE_STRATEGY });
const deprecateStrategyEvent = strategy => ({ type: DEPRECATE_STRATEGY, strategy });
const startReactivate = () => ({ type: START_REACTIVATE_STRATEGY });
const reactivateStrategyEvent = strategy => ({ type: REACTIVATE_STRATEGY, strategy });
export function fetchStrategies() { export function fetchStrategies() {
return dispatch => { return dispatch => {
dispatch(startRequest()); dispatch(startRequest());
@ -70,3 +81,21 @@ export function removeStrategy(strategy) {
export function getApplicationsWithStrategy(strategyName) { export function getApplicationsWithStrategy(strategyName) {
return applicationApi.fetchApplicationsWithStrategyName(strategyName); return applicationApi.fetchApplicationsWithStrategyName(strategyName);
} }
export function deprecateStrategy(strategy) {
return dispatch => {
dispatch(startDeprecate());
api.deprecate(strategy)
.then(() => dispatch(deprecateStrategyEvent(strategy)))
.catch(dispatchAndThrow(dispatch, ERROR_DEPRECATING_STRATEGY));
};
}
export function reactivateStrategy(strategy) {
return dispatch => {
dispatch(startReactivate());
api.reactivate(strategy)
.then(() => dispatch(reactivateStrategyEvent(strategy)))
.catch(dispatchAndThrow(dispatch, ERROR_REACTIVATING_STRATEGY));
};
}

View File

@ -34,9 +34,27 @@ function remove(strategy) {
}).then(throwIfNotSuccess); }).then(throwIfNotSuccess);
} }
function deprecate(strategy) {
return fetch(`${URI}/${strategy.name}/deprecate`, {
method: 'POST',
headers,
credentials: 'include',
}).then(throwIfNotSuccess);
}
function reactivate(strategy) {
return fetch(`${URI}/${strategy.name}/reactivate`, {
method: 'POST',
headers,
credentials: 'include',
}).then(throwIfNotSuccess);
}
export default { export default {
fetchAll, fetchAll,
create, create,
update, update,
remove, remove,
deprecate,
reactivate,
}; };

View File

@ -1,5 +1,12 @@
import { List, Map as $Map } from 'immutable'; import { List, Map as $Map } from 'immutable';
import { RECEIVE_STRATEGIES, REMOVE_STRATEGY, ADD_STRATEGY, UPDATE_STRATEGY } from './actions'; import {
RECEIVE_STRATEGIES,
REMOVE_STRATEGY,
ADD_STRATEGY,
UPDATE_STRATEGY,
DEPRECATE_STRATEGY,
REACTIVATE_STRATEGY,
} from './actions';
function getInitState() { function getInitState() {
return new $Map({ list: new List() }); return new $Map({ list: new List() });
@ -25,6 +32,19 @@ function updateStrategy(state, action) {
); );
} }
function setDeprecationStatus(state, action, status) {
return state.update('list', list =>
list.map(strategy => {
if (strategy.name === action.strategy.name) {
action.strategy.deprecated = status;
return action.strategy;
} else {
return strategy;
}
})
);
}
const strategies = (state = getInitState(), action) => { const strategies = (state = getInitState(), action) => {
switch (action.type) { switch (action.type) {
case RECEIVE_STRATEGIES: case RECEIVE_STRATEGIES:
@ -35,6 +55,10 @@ const strategies = (state = getInitState(), action) => {
return state.update('list', list => list.push(action.strategy)); return state.update('list', list => list.push(action.strategy));
case UPDATE_STRATEGY: case UPDATE_STRATEGY:
return updateStrategy(state, action); return updateStrategy(state, action);
case DEPRECATE_STRATEGY:
return setDeprecationStatus(state, action, true);
case REACTIVATE_STRATEGY:
return setDeprecationStatus(state, action, false);
default: default:
return state; return state;
} }