mirror of
https://github.com/Unleash/unleash.git
synced 2025-02-04 00:18:01 +01:00
add sort strategies via react-dnd
This commit is contained in:
parent
4d5c901807
commit
7243dce22d
@ -40,6 +40,8 @@
|
|||||||
"normalize.css": "^5.0.0",
|
"normalize.css": "^5.0.0",
|
||||||
"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-dnd": "^2.1.4",
|
||||||
|
"react-dnd-html5-backend": "^2.1.2",
|
||||||
"react-dom": "^15.3.1",
|
"react-dom": "^15.3.1",
|
||||||
"react-mdl": "^1.9.0",
|
"react-mdl": "^1.9.0",
|
||||||
"react-modal": "^1.6.4",
|
"react-modal": "^1.6.4",
|
||||||
|
@ -39,6 +39,10 @@ const prepare = (methods, dispatch) => {
|
|||||||
methods.updateInList('strategies', index, n);
|
methods.updateInList('strategies', index, n);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
methods.moveStrategy = (index, toIndex) => {
|
||||||
|
methods.moveItem('strategies', index, toIndex);
|
||||||
|
};
|
||||||
|
|
||||||
methods.removeStrategy = (index) => {
|
methods.removeStrategy = (index) => {
|
||||||
methods.removeFromList('strategies', index);
|
methods.removeFromList('strategies', index);
|
||||||
};
|
};
|
||||||
|
@ -45,6 +45,10 @@ const prepare = (methods, dispatch) => {
|
|||||||
methods.removeFromList('strategies', index);
|
methods.removeFromList('strategies', index);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
methods.moveStrategy = (index, toIndex) => {
|
||||||
|
methods.moveItem('strategies', index, toIndex);
|
||||||
|
};
|
||||||
|
|
||||||
methods.updateStrategy = (index, n) => {
|
methods.updateStrategy = (index, n) => {
|
||||||
methods.updateInList('strategies', index, n);
|
methods.updateInList('strategies', index, n);
|
||||||
};
|
};
|
||||||
|
@ -29,6 +29,7 @@ class AddFeatureToggleComponent extends Component {
|
|||||||
addStrategy,
|
addStrategy,
|
||||||
removeStrategy,
|
removeStrategy,
|
||||||
updateStrategy,
|
updateStrategy,
|
||||||
|
moveStrategy,
|
||||||
onSubmit,
|
onSubmit,
|
||||||
onCancel,
|
onCancel,
|
||||||
editmode = false,
|
editmode = false,
|
||||||
@ -81,6 +82,7 @@ class AddFeatureToggleComponent extends Component {
|
|||||||
configuredStrategies={configuredStrategies}
|
configuredStrategies={configuredStrategies}
|
||||||
addStrategy={addStrategy}
|
addStrategy={addStrategy}
|
||||||
updateStrategy={updateStrategy}
|
updateStrategy={updateStrategy}
|
||||||
|
moveStrategy={moveStrategy}
|
||||||
removeStrategy={removeStrategy} />
|
removeStrategy={removeStrategy} />
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
import React, { PropTypes } from 'react';
|
import React, { PropTypes } from 'react';
|
||||||
import ConfigureStrategy from './strategy-configure';
|
import ConfigureStrategy from './strategy-configure';
|
||||||
|
import { DragDropContext } from 'react-dnd';
|
||||||
|
import HTML5Backend from 'react-dnd-html5-backend';
|
||||||
|
|
||||||
|
@DragDropContext(HTML5Backend) // eslint-disable-line new-cap
|
||||||
class StrategiesList extends React.Component {
|
class StrategiesList extends React.Component {
|
||||||
|
|
||||||
static propTypes () {
|
static propTypes () {
|
||||||
@ -9,6 +12,7 @@ class StrategiesList extends React.Component {
|
|||||||
configuredStrategies: PropTypes.array.isRequired,
|
configuredStrategies: PropTypes.array.isRequired,
|
||||||
updateStrategy: PropTypes.func.isRequired,
|
updateStrategy: PropTypes.func.isRequired,
|
||||||
removeStrategy: PropTypes.func.isRequired,
|
removeStrategy: PropTypes.func.isRequired,
|
||||||
|
moveStrategy: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -16,6 +20,9 @@ class StrategiesList extends React.Component {
|
|||||||
const {
|
const {
|
||||||
strategies,
|
strategies,
|
||||||
configuredStrategies,
|
configuredStrategies,
|
||||||
|
moveStrategy,
|
||||||
|
removeStrategy,
|
||||||
|
updateStrategy,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
if (!configuredStrategies || configuredStrategies.length === 0) {
|
if (!configuredStrategies || configuredStrategies.length === 0) {
|
||||||
@ -24,10 +31,12 @@ class StrategiesList extends React.Component {
|
|||||||
|
|
||||||
const blocks = configuredStrategies.map((strategy, i) => (
|
const blocks = configuredStrategies.map((strategy, i) => (
|
||||||
<ConfigureStrategy
|
<ConfigureStrategy
|
||||||
|
index={i}
|
||||||
key={`${strategy.name}-${i}`}
|
key={`${strategy.name}-${i}`}
|
||||||
strategy={strategy}
|
strategy={strategy}
|
||||||
removeStrategy={this.props.removeStrategy.bind(null, i)}
|
moveStrategy={moveStrategy}
|
||||||
updateStrategy={this.props.updateStrategy.bind(null, i)}
|
removeStrategy={removeStrategy.bind(null, i)}
|
||||||
|
updateStrategy={updateStrategy.bind(null, i)}
|
||||||
strategyDefinition={strategies.find(s => s.name === strategy.name)} />
|
strategyDefinition={strategies.find(s => s.name === strategy.name)} />
|
||||||
));
|
));
|
||||||
return (
|
return (
|
||||||
|
@ -4,6 +4,7 @@ import {
|
|||||||
Card, CardTitle, CardText, CardActions, CardMenu,
|
Card, CardTitle, CardText, CardActions, CardMenu,
|
||||||
IconButton, Icon,
|
IconButton, Icon,
|
||||||
} from 'react-mdl';
|
} from 'react-mdl';
|
||||||
|
import { DragSource, DropTarget } from 'react-dnd';
|
||||||
import { Link } from 'react-router';
|
import { Link } from 'react-router';
|
||||||
import StrategyInputPercentage from './strategy-input-percentage';
|
import StrategyInputPercentage from './strategy-input-percentage';
|
||||||
import StrategyInputList from './strategy-input-list';
|
import StrategyInputList from './strategy-input-list';
|
||||||
@ -13,7 +14,6 @@ const style = {
|
|||||||
minWidth: '300px',
|
minWidth: '300px',
|
||||||
maxWidth: '100%',
|
maxWidth: '100%',
|
||||||
margin: '5px 20px 15px 0px',
|
margin: '5px 20px 15px 0px',
|
||||||
background: '#f2f9fc',
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const helpText = {
|
const helpText = {
|
||||||
@ -21,6 +21,34 @@ const helpText = {
|
|||||||
fontSize: '12px',
|
fontSize: '12px',
|
||||||
lineHeight: '14px',
|
lineHeight: '14px',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const dragSource = {
|
||||||
|
beginDrag (props) {
|
||||||
|
return {
|
||||||
|
index: props.index,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const dragTarget = {
|
||||||
|
drop (props, monitor) {
|
||||||
|
const dragIndex = monitor.getItem().index;
|
||||||
|
const toIndex = props.index;
|
||||||
|
if (dragIndex !== toIndex) {
|
||||||
|
props.moveStrategy(dragIndex, toIndex);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
@DropTarget('strategy', dragTarget, connect => ({ // eslint-disable-line new-cap
|
||||||
|
connectDropTarget: connect.dropTarget(),
|
||||||
|
}))
|
||||||
|
@DragSource('strategy', dragSource, (connect, monitor) => ({ // eslint-disable-line new-cap
|
||||||
|
connectDragSource: connect.dragSource(),
|
||||||
|
connectDragPreview: connect.dragPreview(),
|
||||||
|
isDragging: monitor.isDragging(),
|
||||||
|
}))
|
||||||
class StrategyConfigure extends React.Component {
|
class StrategyConfigure extends React.Component {
|
||||||
|
|
||||||
static propTypes () {
|
static propTypes () {
|
||||||
@ -29,13 +57,14 @@ class StrategyConfigure extends React.Component {
|
|||||||
strategyDefinition: PropTypes.object.isRequired,
|
strategyDefinition: PropTypes.object.isRequired,
|
||||||
updateStrategy: PropTypes.func.isRequired,
|
updateStrategy: PropTypes.func.isRequired,
|
||||||
removeStrategy: PropTypes.func.isRequired,
|
removeStrategy: PropTypes.func.isRequired,
|
||||||
|
moveStrategy: PropTypes.func.isRequired,
|
||||||
|
isDragging: PropTypes.bool.isRequired,
|
||||||
|
connectDragPreview: PropTypes.func.isRequired,
|
||||||
|
connectDragSource: PropTypes.func.isRequired,
|
||||||
|
connectDropTarget: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// shouldComponentUpdate (props, nextProps) {
|
|
||||||
// console.log({ props, nextProps });
|
|
||||||
// }
|
|
||||||
|
|
||||||
handleConfigChange = (key, e) => {
|
handleConfigChange = (key, e) => {
|
||||||
this.setConfig(key, e.target.value);
|
this.setConfig(key, e.target.value);
|
||||||
};
|
};
|
||||||
@ -125,31 +154,16 @@ class StrategyConfigure extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
if (!this.props.strategyDefinition) {
|
const { isDragging, connectDragPreview, connectDragSource, connectDropTarget } = this.props;
|
||||||
const { name } = this.props.strategy;
|
|
||||||
return (
|
|
||||||
<Card shadow={0} style={style}>
|
|
||||||
<CardTitle>"{name}" deleted?</CardTitle>
|
|
||||||
<CardText>
|
|
||||||
The strategy "{name}" does not exist on this server.
|
|
||||||
<Link to={`/strategies/create?name=${name}`}>Want to create it now?</Link>
|
|
||||||
</CardText>
|
|
||||||
<CardActions>
|
|
||||||
<Button onClick={this.handleRemove} label="remove strategy" accent raised>Remove</Button>
|
|
||||||
</CardActions>
|
|
||||||
|
|
||||||
</Card>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
let item;
|
||||||
|
if (this.props.strategyDefinition) {
|
||||||
const inputFields = this.renderInputFields(this.props.strategyDefinition);
|
const inputFields = this.renderInputFields(this.props.strategyDefinition);
|
||||||
|
|
||||||
const { name } = this.props.strategy;
|
const { name } = this.props.strategy;
|
||||||
|
item = (
|
||||||
return (
|
<Card shadow={0} style={{ background: '#f2f9fc', width: '100%', display: 'block', opacity: isDragging ? '0.1' : '1' }}>
|
||||||
<Card shadow={0} style={style}>
|
|
||||||
<CardTitle style={{ color: '#fff', height: '65px', background: '#607d8b' }}>
|
<CardTitle style={{ color: '#fff', height: '65px', background: '#607d8b' }}>
|
||||||
<Icon name="extension" /> { name }
|
<Icon name="extension" /> {name}
|
||||||
</CardTitle>
|
</CardTitle>
|
||||||
<CardText>
|
<CardText>
|
||||||
{this.props.strategyDefinition.description}
|
{this.props.strategyDefinition.description}
|
||||||
@ -168,9 +182,35 @@ class StrategyConfigure extends React.Component {
|
|||||||
<Icon name="link" />
|
<Icon name="link" />
|
||||||
</Link>
|
</Link>
|
||||||
<IconButton title="Remove strategy from toggle" name="delete" onClick={this.handleRemove} />
|
<IconButton title="Remove strategy from toggle" name="delete" onClick={this.handleRemove} />
|
||||||
|
{connectDragSource(
|
||||||
|
<span style={{
|
||||||
|
cursor: 'pointer',
|
||||||
|
display: 'inline-block',
|
||||||
|
verticalAlign: 'bottom',
|
||||||
|
}}><Icon name="reorder" /></span>)}
|
||||||
</CardMenu>
|
</CardMenu>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
const { name } = this.props.strategy;
|
||||||
|
item = (
|
||||||
|
<Card shadow={0} style={style}>
|
||||||
|
<CardTitle>"{name}" deleted?</CardTitle>
|
||||||
|
<CardText>
|
||||||
|
The strategy "{name}" does not exist on this server.
|
||||||
|
<Link to={`/strategies/create?name=${name}`}>Want to create it now?</Link>
|
||||||
|
</CardText>
|
||||||
|
<CardActions>
|
||||||
|
<Button onClick={this.handleRemove} label="remove strategy" accent raised>Remove</Button>
|
||||||
|
</CardActions>
|
||||||
|
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (connectDropTarget(connectDragPreview(
|
||||||
|
<div style={style}>{item}</div>
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import {
|
|||||||
createPush,
|
createPush,
|
||||||
createUp,
|
createUp,
|
||||||
createInit,
|
createInit,
|
||||||
|
createMove,
|
||||||
} from '../store/input-actions';
|
} from '../store/input-actions';
|
||||||
|
|
||||||
function getId (id, ownProps) {
|
function getId (id, ownProps) {
|
||||||
@ -57,6 +58,10 @@ export function createActions ({ id, prepare = (v) => v }) {
|
|||||||
dispatch(createPop({ id: getId(id, ownProps), key, index }));
|
dispatch(createPop({ id: getId(id, ownProps), key, index }));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
moveItem (key, index, toIndex) {
|
||||||
|
dispatch(createMove({ id: getId(id, ownProps), key, index, toIndex }));
|
||||||
|
},
|
||||||
|
|
||||||
updateInList (key, index, newValue, merge = false) {
|
updateInList (key, index, newValue, merge = false) {
|
||||||
dispatch(createUp({ id: getId(id, ownProps), key, index, newValue, merge }));
|
dispatch(createUp({ id: getId(id, ownProps), key, index, newValue, merge }));
|
||||||
},
|
},
|
||||||
|
@ -6,6 +6,7 @@ export const actions = {
|
|||||||
LIST_UP: 'LIST_UP',
|
LIST_UP: 'LIST_UP',
|
||||||
CLEAR: 'CLEAR',
|
CLEAR: 'CLEAR',
|
||||||
INIT: 'INIT',
|
INIT: 'INIT',
|
||||||
|
MOVE: 'MOVE',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const createInit = ({ id, value }) => ({ type: actions.INIT, id, value });
|
export const createInit = ({ id, value }) => ({ type: actions.INIT, id, value });
|
||||||
@ -13,6 +14,7 @@ export const createInc = ({ id, key }) => ({ type: actions.INCREMENT_VALUE, id,
|
|||||||
export const createSet = ({ id, key, value }) => ({ type: actions.SET_VALUE, id, key, value });
|
export const createSet = ({ id, key, value }) => ({ type: actions.SET_VALUE, id, key, value });
|
||||||
export const createPush = ({ id, key, value }) => ({ type: actions.LIST_PUSH, id, key, value });
|
export const createPush = ({ id, key, value }) => ({ type: actions.LIST_PUSH, id, key, value });
|
||||||
export const createPop = ({ id, key, index }) => ({ type: actions.LIST_POP, id, key, index });
|
export const createPop = ({ id, key, index }) => ({ type: actions.LIST_POP, id, key, index });
|
||||||
|
export const createMove = ({ id, key, index, toIndex }) => ({ type: actions.MOVE, id, key, index, toIndex });
|
||||||
export const createUp = ({ id, key, index, newValue, merge }) => ({ type: actions.LIST_UP, id, key, index, newValue, merge });
|
export const createUp = ({ id, key, index, newValue, merge }) => ({ type: actions.LIST_UP, id, key, index, newValue, merge });
|
||||||
export const createClear = ({ id }) => ({ type: actions.CLEAR, id });
|
export const createClear = ({ id }) => ({ type: actions.CLEAR, id });
|
||||||
|
|
||||||
|
@ -69,6 +69,13 @@ function removeFromList (state, { id, key, index }) {
|
|||||||
return state.updateIn(id.concat([key]), (list) => list.remove(index));
|
return state.updateIn(id.concat([key]), (list) => list.remove(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function move (state, { id, key, index, toIndex }) {
|
||||||
|
return state.updateIn(id.concat([key]), list => {
|
||||||
|
const olditem = list.get(index);
|
||||||
|
return list.delete(index).insert(toIndex, olditem);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const inputState = (state = getInitState(), action) => {
|
const inputState = (state = getInitState(), action) => {
|
||||||
if (!action.id) {
|
if (!action.id) {
|
||||||
return state;
|
return state;
|
||||||
@ -88,6 +95,8 @@ const inputState = (state = getInitState(), action) => {
|
|||||||
return addToList(state, action);
|
return addToList(state, action);
|
||||||
case actions.LIST_POP:
|
case actions.LIST_POP:
|
||||||
return removeFromList(state, action);
|
return removeFromList(state, action);
|
||||||
|
case actions.MOVE:
|
||||||
|
return move(state, action);
|
||||||
case actions.LIST_UP:
|
case actions.LIST_UP:
|
||||||
return updateInList(state, action);
|
return updateInList(state, action);
|
||||||
case actions.CLEAR:
|
case actions.CLEAR:
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"globalDependencies": {
|
"globalDependencies": {
|
||||||
|
"react-dnd": "registry:dt/react-dnd#2.0.2+20161111212335",
|
||||||
"react-mdl": "registry:dt/react-mdl#0.0.0+20160830142027"
|
"react-mdl": "registry:dt/react-mdl#0.0.0+20160830142027"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user