Skip to content
This repository was archived by the owner on Jun 5, 2020. It is now read-only.

Commit d016e45

Browse files
committed
Reorder actions
1 parent 2f774fa commit d016e45

File tree

5 files changed

+71
-14
lines changed

5 files changed

+71
-14
lines changed

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@
8181
"jss-vendor-prefixer": "^3.0.1",
8282
"lodash.debounce": "^4.0.3",
8383
"react-base16-styling": "^0.4.1",
84+
"react-dragula": "^1.1.17",
8485
"react-json-tree": "^0.10.0",
8586
"react-pure-render": "^1.0.2",
8687
"redux-devtools-themes": "^1.0.0"

src/ActionList.jsx

+30-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React, { Component } from 'react';
22
import ReactDOM from 'react-dom';
3+
import dragula from 'react-dragula';
34
import ActionListRow from './ActionListRow';
45
import ActionListHeader from './ActionListHeader';
56
import shouldPureComponentUpdate from 'react-pure-render/function';
@@ -19,6 +20,31 @@ export default class ActionList extends Component {
1920

2021
componentDidMount() {
2122
this.scrollToBottom(true);
23+
if (!this.props.draggableActions) return;
24+
const container = ReactDOM.findDOMNode(this.refs.rows);
25+
this.drake = dragula([container], {
26+
copy: false,
27+
copySortSource: false,
28+
mirrorContainer: container,
29+
accepts: (el, target, source, sibling) => (
30+
!sibling || parseInt(sibling.getAttribute('data-id'))
31+
),
32+
moves: (el, source, handle) => (
33+
parseInt(el.getAttribute('data-id')) &&
34+
handle.className.indexOf('selectorButton') !== 0
35+
),
36+
}).on('drop', (el, target, source, sibling) => {
37+
let beforeActionId = Infinity;
38+
if (sibling && sibling.className.indexOf('gu-mirror') === -1) {
39+
beforeActionId = parseInt(sibling.getAttribute('data-id'));
40+
}
41+
const actionId = parseInt(el.getAttribute('data-id'));
42+
this.props.onReorderAction(actionId, beforeActionId)
43+
});
44+
}
45+
46+
componentWillUnmount() {
47+
if (this.drake) this.drake.destroy();
2248
}
2349

2450
componentDidUpdate(prevProps) {
@@ -57,13 +83,16 @@ export default class ActionList extends Component {
5783
{filteredActionIds.map(actionId =>
5884
<ActionListRow key={actionId}
5985
styling={styling}
86+
actionId={actionId}
6087
isInitAction={!actionId}
6188
isSelected={
6289
startActionId !== null &&
6390
actionId >= startActionId && actionId <= selectedActionId ||
6491
actionId === selectedActionId
6592
}
66-
isInFuture={actionId > currentActionId}
93+
isInFuture={
94+
actionIds.indexOf(actionId) > actionIds.indexOf(currentActionId)
95+
}
6796
onSelect={(e) => onSelect(e, actionId)}
6897
timestamps={getTimestamps(actions, actionIds, actionId)}
6998
action={actions[actionId].action}

src/ActionListRow.jsx

+8-6
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export default class ActionListRow extends Component {
2727
shouldComponentUpdate = shouldPureComponentUpdate
2828

2929
render() {
30-
const { styling, isSelected, action, isInitAction, onSelect,
30+
const { styling, isSelected, action, actionId, isInitAction, onSelect,
3131
timestamps, isSkipped, isInFuture } = this.props;
3232
const { hover } = this.state;
3333
const timeDelta = timestamps.current - timestamps.previous;
@@ -41,6 +41,8 @@ export default class ActionListRow extends Component {
4141
onMouseEnter={this.handleMouseEnter}
4242
onMouseLeave={this.handleMouseLeave}
4343
onMouseDown={this.handleMouseDown}
44+
onMouseUp={this.handleMouseEnter}
45+
data-id={actionId}
4446
{...styling([
4547
'actionListItem',
4648
isSelected && 'actionListItemSelected',
@@ -91,22 +93,22 @@ export default class ActionListRow extends Component {
9193

9294
handleMouseEnter = e => {
9395
if (this.hover) return;
96+
this.handleMouseLeave.cancel();
9497
this.handleMouseEnterDebounced(e.buttons);
9598
}
9699

97100
handleMouseEnterDebounced = debounce((buttons) => {
98101
if (buttons) return;
99102
this.setState({ hover: true });
100-
}, 300)
103+
}, 150)
101104

102-
handleMouseLeave = () => {
105+
handleMouseLeave = debounce(() => {
103106
this.handleMouseEnterDebounced.cancel();
104107
if (this.state.hover) this.setState({ hover: false });
105-
}
108+
}, 100)
106109

107110
handleMouseDown = e => {
108111
if (e.target.className.indexOf('selectorButton') === 0) return;
109-
if (this.handleMouseEnterDebounced) this.handleMouseEnterDebounced.cancel();
110-
if (this.state.hover) this.setState({ hover: false });
112+
this.handleMouseLeave();
111113
}
112114
}

src/DevtoolsInspector.js

+14-6
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { getBase16Theme } from 'react-base16-styling';
99
import { reducer, updateMonitorState } from './redux';
1010
import { ActionCreators } from 'redux-devtools';
1111

12-
const { commit, sweep, toggleAction, jumpToAction, jumpToState } = ActionCreators;
12+
const { commit, sweep, toggleAction, jumpToAction, jumpToState, reorderAction } = ActionCreators;
1313

1414
function getLastActionId(props) {
1515
return props.stagedActionIds[props.stagedActionIds.length - 1];
@@ -86,6 +86,7 @@ export default class DevtoolsInspector extends Component {
8686
initialScrollTop: PropTypes.number
8787
}),
8888
preserveScrollTop: PropTypes.bool,
89+
draggableActions: PropTypes.bool,
8990
stagedActions: PropTypes.array,
9091
select: PropTypes.func.isRequired,
9192
theme: PropTypes.oneOfType([
@@ -100,6 +101,7 @@ export default class DevtoolsInspector extends Component {
100101
static defaultProps = {
101102
select: (state) => state,
102103
supportImmutable: false,
104+
draggableActions: true,
103105
theme: 'inspector',
104106
invertTheme: true
105107
};
@@ -136,7 +138,9 @@ export default class DevtoolsInspector extends Component {
136138
getCurrentActionId(nextProps, nextMonitorState) ||
137139
monitorState.startActionId !== nextMonitorState.startActionId ||
138140
monitorState.inspectedStatePath !== nextMonitorState.inspectedStatePath ||
139-
monitorState.inspectedActionPath !== nextMonitorState.inspectedActionPath
141+
monitorState.inspectedActionPath !== nextMonitorState.inspectedActionPath ||
142+
this.props.computedStates !== nextProps.computedStates ||
143+
this.props.stagedActionIds !== nextProps.stagedActionIds
140144
) {
141145
this.setState(createIntermediateState(nextProps, nextMonitorState));
142146
}
@@ -148,7 +152,7 @@ export default class DevtoolsInspector extends Component {
148152
}
149153

150154
render() {
151-
const { stagedActionIds: actionIds, actionsById: actions, computedStates,
155+
const { stagedActionIds: actionIds, actionsById: actions, computedStates, draggableActions,
152156
tabs, invertTheme, skippedActionIds, currentStateIndex, monitorState } = this.props;
153157
const { selectedActionId, startActionId, searchValue, tabName } = monitorState;
154158
const inspectedPathType = tabName === 'Action' ? 'inspectedActionPath' : 'inspectedStatePath';
@@ -162,16 +166,16 @@ export default class DevtoolsInspector extends Component {
162166
ref='inspector'
163167
{...styling(['inspector', isWideLayout && 'inspectorWide'], isWideLayout)}>
164168
<ActionList {...{
165-
actions, actionIds, isWideLayout, searchValue, selectedActionId, startActionId
169+
actions, actionIds, isWideLayout, searchValue, selectedActionId, startActionId,
170+
skippedActionIds, draggableActions, styling
166171
}}
167-
styling={styling}
168172
onSearch={this.handleSearch}
169173
onSelect={this.handleSelectAction}
170174
onToggleAction={this.handleToggleAction}
171175
onJumpToState={this.handleJumpToState}
172176
onCommit={this.handleCommit}
173177
onSweep={this.handleSweep}
174-
skippedActionIds={skippedActionIds}
178+
onReorderAction={this.handleReorderAction}
175179
currentActionId={actionIds[currentStateIndex]}
176180
lastActionId={getLastActionId(this.props)} />
177181
<ActionPreview {...{
@@ -199,6 +203,10 @@ export default class DevtoolsInspector extends Component {
199203
}
200204
};
201205

206+
handleReorderAction = (actionId, beforeActionId) => {
207+
if (reorderAction) this.props.dispatch(reorderAction(actionId, beforeActionId));
208+
};
209+
202210
handleCommit = () => {
203211
this.props.dispatch(commit());
204212
};

src/utils/createStylingFromTheme.js

+18-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,24 @@ const getSheetFromColorMap = map => ({
8181
},
8282

8383
actionListRows: {
84-
overflow: 'auto'
84+
overflow: 'auto',
85+
86+
'& div.gu-transit': {
87+
opacity: '0.3'
88+
},
89+
90+
'& div.gu-mirror': {
91+
position: 'fixed',
92+
opacity: '0.8',
93+
height: 'auto !important',
94+
'border-width': '1px',
95+
'border-style': 'solid',
96+
'border-color': map.LIST_BORDER_COLOR
97+
},
98+
99+
'& div.gu-hide': {
100+
display: 'none'
101+
}
85102
},
86103

87104
actionListHeaderSelector: {

0 commit comments

Comments
 (0)