diff --git a/client/app/components/Parameters.jsx b/client/app/components/Parameters.jsx
index 89ea3c9690..6d4ceb4486 100644
--- a/client/app/components/Parameters.jsx
+++ b/client/app/components/Parameters.jsx
@@ -2,7 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import { size, filter, forEach, extend } from 'lodash';
import { react2angular } from 'react2angular';
-import { sortableContainer, sortableElement, sortableHandle } from 'react-sortable-hoc';
+import { SortableContainer, SortableElement, DragHandle } from '@/components/sortable';
import { $location } from '@/services/ng';
import { Parameter } from '@/services/query';
import ParameterApplyButton from '@/components/ParameterApplyButton';
@@ -12,18 +12,6 @@ import { toHuman } from '@/filters';
import './Parameters.less';
-const DragHandle = sortableHandle(({ parameterName }) => (
-
-));
-
-const SortableItem = sortableElement(({ className, parameterName, disabled, children }) => (
-
- {!disabled && }
- {children}
-
-));
-const SortableContainer = sortableContainer(({ children }) => children);
-
function updateUrl(parameters) {
const params = extend({}, $location.search());
parameters.forEach((param) => {
@@ -50,12 +38,12 @@ export class Parameters extends React.Component {
onValuesChange: () => {},
onPendingValuesChange: () => {},
onParametersEdit: () => {},
- }
+ };
constructor(props) {
super(props);
const { parameters } = props;
- this.state = { parameters, dragging: false };
+ this.state = { parameters };
if (!props.disableUrlUpdate) {
updateUrl(parameters);
}
@@ -101,11 +89,6 @@ export class Parameters extends React.Component {
return { parameters };
});
}
- this.setState({ dragging: false });
- };
-
- onBeforeSortStart = () => {
- this.setState({ dragging: true });
};
applyChanges = () => {
@@ -170,32 +153,32 @@ export class Parameters extends React.Component {
}
render() {
- const { parameters, dragging } = this.state;
+ const { parameters } = this.state;
const { editable } = this.props;
const dirtyParamCount = size(filter(parameters, 'hasPendingValue'));
return (
-
- {parameters.map((param, index) => (
-
+ {parameters.map((param, index) => (
+
+
+ {editable &&
}
{this.renderParameter(param, index)}
-
- ))}
-
-
-
+
+
+ ))}
+
);
}
diff --git a/client/app/components/Parameters.less b/client/app/components/Parameters.less
index 304c1a8f86..338912fe80 100644
--- a/client/app/components/Parameters.less
+++ b/client/app/components/Parameters.less
@@ -1,32 +1,25 @@
@import '../assets/less/ant';
-.drag-handle {
- background: linear-gradient(90deg, transparent 0px, white 1px, white 2px)
- center,
- linear-gradient(transparent 0px, white 1px, white 2px) center, #111111;
- background-size: 2px 2px;
- display: inline-block;
- width: 6px;
- height: 36px;
- vertical-align: bottom;
- margin-right: 5px;
- cursor: move;
-}
-
.parameter-block {
display: inline-block;
background: white;
padding: 0 12px 6px 0;
vertical-align: top;
+ z-index: 1;
+
+ .drag-handle {
+ padding: 0 5px;
+ margin-left: -5px;
+ height: 36px;
+ }
- .parameter-container[data-draggable] & {
+ .parameter-container.sortable-container & {
margin: 4px 0 0 4px;
padding: 3px 6px 6px;
}
&.parameter-dragged {
box-shadow: 0 4px 9px -3px rgba(102, 136, 153, 0.15);
- width: auto !important;
}
}
@@ -53,20 +46,13 @@
.parameter-container {
position: relative;
- &[data-draggable] {
+ &.sortable-container {
padding: 0 4px 4px 0;
- transition: background-color 200ms ease-out;
- transition-delay: 300ms; // short pause before returning to original bgcolor
- }
-
- &[data-dragging] {
- transition-delay: 0s;
- background-color: #f6f8f9;
}
.parameter-apply-button {
display: none; // default for mobile
-
+
// "floating" on desktop
@media (min-width: 768px) {
position: absolute;
@@ -83,7 +69,7 @@
display: block;
pointer-events: none; // so tooltip doesn't remain after button hides
}
-
+
&[data-show="true"] {
opacity: 1;
display: block;
@@ -118,7 +104,7 @@
line-height: 15px;
background: #f77b74;
border-radius: 7px;
- box-shadow: 0px 0px 0 1px white, -1px 1px 0 1px #5d6f7d85;
+ box-shadow: 0 0 0 1px white, -1px 1px 0 1px #5d6f7d85;
}
}
}
diff --git a/client/app/components/sortable/index.jsx b/client/app/components/sortable/index.jsx
new file mode 100644
index 0000000000..7365e64fae
--- /dev/null
+++ b/client/app/components/sortable/index.jsx
@@ -0,0 +1,80 @@
+import { isFunction, wrap } from 'lodash';
+import React, { useRef, useState } from 'react';
+import PropTypes from 'prop-types';
+import cx from 'classnames';
+import { sortableContainer, sortableElement, sortableHandle } from 'react-sortable-hoc';
+
+import './style.less';
+
+export const DragHandle = sortableHandle(({ className, ...restProps }) => (
+
+));
+
+export const SortableContainerWrapper = sortableContainer(({ children }) => children);
+
+export const SortableElement = sortableElement(({ children }) => children);
+
+export function SortableContainer({ disabled, containerProps, children, ...wrapperProps }) {
+ const containerRef = useRef();
+ const [isDragging, setIsDragging] = useState(false);
+
+ wrapperProps = { ...wrapperProps };
+ containerProps = { ...containerProps };
+
+ if (disabled) {
+ // Disabled state:
+ // - forbid drag'n'drop (and therefore no need to hook events
+ // - don't override anything on container element
+ wrapperProps.shouldCancelStart = () => true;
+ } else {
+ // Enabled state:
+
+ // - use container element as a default helper element
+ wrapperProps.helperContainer = wrap(wrapperProps.helperContainer, helperContainer => (
+ isFunction(helperContainer) ?
+ helperContainer(containerRef.current) :
+ containerRef.current
+ ));
+
+ // - hook drag start/end events
+ wrapperProps.updateBeforeSortStart = wrap(wrapperProps.updateBeforeSortStart, (updateBeforeSortStart, ...args) => {
+ setIsDragging(true);
+ if (isFunction(updateBeforeSortStart)) {
+ updateBeforeSortStart(...args);
+ }
+ });
+ wrapperProps.onSortEnd = wrap(wrapperProps.onSortEnd, (onSortEnd, ...args) => {
+ setIsDragging(false);
+ if (isFunction(onSortEnd)) {
+ onSortEnd(...args);
+ }
+ });
+
+ // - update container element: add classes and take a ref
+ containerProps.className = cx(
+ 'sortable-container',
+ { 'sortable-container-dragging': isDragging },
+ containerProps.className,
+ );
+ containerProps.ref = containerRef;
+ }
+
+ // order of props matters - we override some of them
+ return (
+
+ {children}
+
+ );
+}
+
+SortableContainer.propTypes = {
+ disabled: PropTypes.bool,
+ containerProps: PropTypes.object, // eslint-disable-line react/forbid-prop-types
+ children: PropTypes.node,
+};
+
+SortableContainer.defaultProps = {
+ disabled: false,
+ containerProps: {},
+ children: null,
+};
diff --git a/client/app/components/sortable/style.less b/client/app/components/sortable/style.less
new file mode 100644
index 0000000000..1277df8e9b
--- /dev/null
+++ b/client/app/components/sortable/style.less
@@ -0,0 +1,30 @@
+.drag-handle {
+ vertical-align: bottom;
+ cursor: move;
+
+ display: inline-flex;
+ align-items: stretch;
+ justify-content: center;
+
+ &:before {
+ content: '';
+ display: block;
+ width: 6px;
+
+ background:
+ linear-gradient(90deg, transparent 0px, white 1px, white 2px) center,
+ linear-gradient(transparent 0px, white 1px, white 2px) center,
+ #111111;
+ background-size: 2px 2px;
+ }
+}
+
+.sortable-container {
+ transition: background-color 200ms ease-out;
+ transition-delay: 300ms; // short pause before returning to original bgcolor
+
+ &.sortable-container-dragging {
+ transition-delay: 0s;
+ background-color: #f6f8f9;
+ }
+}
diff --git a/package-lock.json b/package-lock.json
index 7ebb282402..296687724a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -15004,9 +15004,9 @@
}
},
"react-sortable-hoc": {
- "version": "1.9.1",
- "resolved": "https://registry.npmjs.org/react-sortable-hoc/-/react-sortable-hoc-1.9.1.tgz",
- "integrity": "sha512-2VeofjRav8+eZeE5Nm/+b8mrA94rQ+gBsqhXi8pRBSjOWNqslU3ZEm+0XhSlfoXJY2lkgHipfYAUuJbDtCixRg==",
+ "version": "1.10.1",
+ "resolved": "https://registry.npmjs.org/react-sortable-hoc/-/react-sortable-hoc-1.10.1.tgz",
+ "integrity": "sha512-eVyv5rrK6qY9bG60bboRY78In7OpdRRg+hxp4QMLIjC/UJaFSU7exTYd0764GtXvBqh+b+faYGzren5/ffRYKw==",
"requires": {
"@babel/runtime": "^7.2.0",
"invariant": "^2.2.4",
@@ -15014,9 +15014,9 @@
},
"dependencies": {
"@babel/runtime": {
- "version": "7.5.5",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.5.5.tgz",
- "integrity": "sha512-28QvEGyQyNkB0/m2B4FU7IEZGK2NUrcMtT6BZEFALTguLk+AUT6ofsHtPk5QyjAdUkpMJ+/Em+quwz4HOt30AQ==",
+ "version": "7.6.2",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.6.2.tgz",
+ "integrity": "sha512-EXxN64agfUqqIGeEjI5dL5z0Sw0ZwWo1mLTi4mQowCZ42O59b7DRpZAnTC6OqdF28wMBMFKNb/4uFGrVaigSpg==",
"requires": {
"regenerator-runtime": "^0.13.2"
}
diff --git a/package.json b/package.json
index afd15ea52a..c351ca84d7 100644
--- a/package.json
+++ b/package.json
@@ -82,7 +82,7 @@
"react-dom": "^16.8.3",
"react-grid-layout": "git+https://github.com/getredash/react-grid-layout.git",
"react-pivottable": "^0.9.0",
- "react-sortable-hoc": "^1.9.1",
+ "react-sortable-hoc": "^1.10.1",
"react2angular": "^3.2.1",
"tinycolor2": "^1.4.1",
"ui-select": "^0.19.8"