diff --git a/e2e/suite1/specs/panelEdit_queries.spec.ts b/e2e/suite1/specs/panelEdit_queries.spec.ts index 02d9db38b4a..486e486a232 100644 --- a/e2e/suite1/specs/panelEdit_queries.spec.ts +++ b/e2e/suite1/specs/panelEdit_queries.spec.ts @@ -75,44 +75,6 @@ e2e.scenario({ e2e().wait('@apiPostQuery'); - // Change order or query rows - // Check the order of the rows before - e2e.components.QueryEditorRows.rows() - .eq(0) - .within(() => { - e2e.components.QueryEditorRow.title('B').should('be.visible'); - }); - - e2e.components.QueryEditorRows.rows() - .eq(1) - .within(() => { - e2e.components.QueryEditorRow.title('A').should('be.visible'); - }); - - // Change so A is first - e2e.components.QueryEditorRow.actionButton('Move query up') - .eq(1) - .click(); - - e2e().wait('@apiPostQuery'); - - // Avoid flaky tests - // Maybe the virtual dom performs optimzations such as node position swapping, meaning 1 becomes 0 and it gets that element before the change because and never finds title 'A' - e2e().wait(250); - - // Check the order of the rows after change - e2e.components.QueryEditorRows.rows() - .eq(0) - .within(() => { - e2e.components.QueryEditorRow.title('A').should('be.visible'); - }); - - e2e.components.QueryEditorRows.rows() - .eq(1) - .within(() => { - e2e.components.QueryEditorRow.title('B').should('be.visible'); - }); - // Disable / enable row expectInspectorResultAndClose(keys => { const length = keys.length; @@ -120,7 +82,7 @@ e2e.scenario({ expect(keys[length - 1].innerText).equals('B:'); }); - // Disable row with refId B + // Disable row with refId A e2e.components.QueryEditorRow.actionButton('Disable/enable query') .eq(1) .should('be.visible') @@ -130,7 +92,7 @@ e2e.scenario({ expectInspectorResultAndClose(keys => { const length = keys.length; - expect(keys[length - 1].innerText).equals('A:'); + expect(keys[length - 1].innerText).equals('B:'); }); // Enable row with refId B diff --git a/public/app/core/components/QueryOperationRow/QueryOperationRow.tsx b/public/app/core/components/QueryOperationRow/QueryOperationRow.tsx index f5545adb85b..f18ddfb4ca0 100644 --- a/public/app/core/components/QueryOperationRow/QueryOperationRow.tsx +++ b/public/app/core/components/QueryOperationRow/QueryOperationRow.tsx @@ -1,5 +1,5 @@ import React, { useState, useCallback } from 'react'; -import { HorizontalGroup, Icon, renderOrCallToRender, stylesFactory, useTheme } from '@grafana/ui'; +import { Icon, renderOrCallToRender, stylesFactory, useTheme } from '@grafana/ui'; import { GrafanaTheme } from '@grafana/data'; import { css } from 'emotion'; import { useUpdateEffect } from 'react-use'; @@ -66,33 +66,36 @@ export const QueryOperationRow: React.FC = ({ const rowHeader = (
- -
- {draggable && ( - - )} - - {title && {titleElement}} - {headerElement} -
- {actions && actionsElement} -
+
+ + {title && {titleElement}} + {headerElement} +
+ {actions && actionsElement} + {draggable && ( + + )}
); - return draggable ? ( - - {provided => { - return ( - <> -
-
{rowHeader}
- {isContentVisible &&
{children}
} -
- - ); - }} -
- ) : ( + + if (draggable) { + return ( + + {provided => { + return ( + <> +
+
{rowHeader}
+ {isContentVisible &&
{children}
} +
+ + ); + }} +
+ ); + } + + return (
{rowHeader} {isContentVisible &&
{children}
} @@ -116,8 +119,11 @@ const getQueryOperationRowStyles = stylesFactory((theme: GrafanaTheme) => { justify-content: space-between; `, dragIcon: css` - opacity: 0.4; cursor: drag; + color: ${theme.colors.textWeak}; + &:hover { + color: ${theme.colors.text}; + } `, collapseIcon: css` color: ${theme.colors.textWeak}; @@ -128,7 +134,10 @@ const getQueryOperationRowStyles = stylesFactory((theme: GrafanaTheme) => { titleWrapper: css` display: flex; align-items: center; + flex-grow: 1; cursor: pointer; + overflow: hidden; + margin-right: ${theme.spacing.sm}; `, title: css` font-weight: ${theme.typography.weight.semibold}; diff --git a/public/app/features/dashboard/components/TransformationsEditor/TransformationOperationRow.tsx b/public/app/features/dashboard/components/TransformationsEditor/TransformationOperationRow.tsx index e3763f56076..b0049f149d5 100644 --- a/public/app/features/dashboard/components/TransformationsEditor/TransformationOperationRow.tsx +++ b/public/app/features/dashboard/components/TransformationsEditor/TransformationOperationRow.tsx @@ -27,7 +27,7 @@ export const TransformationOperationRow: React.FC { return ( - + void; onRemoveQuery: (query: DataQuery) => void; - onMoveQuery: (query: DataQuery, direction: number) => void; onChange: (query: DataQuery) => void; } @@ -232,7 +231,7 @@ export class QueryEditorRow extends PureComponent { const isDisabled = query.hide; return ( - + {hasTextEditMode && ( { }} /> )} - this.props.onMoveQuery(query, 1)} - /> - this.props.onMoveQuery(query, -1)} /> - {
{ panel.refresh(); }; - onMoveQuery = (query: DataQuery, direction: number) => { - const { queries, onChangeQueries, panel } = this.props; - - const index = _.indexOf(queries, query); - // @ts-ignore - _.move(queries, index, index + direction); - onChangeQueries(queries); - panel.refresh(); - }; - onChangeQuery(query: DataQuery, index: number) { const { queries, onChangeQueries } = this.props; @@ -76,24 +64,55 @@ export class QueryEditorRows extends PureComponent { ); } + onDragEnd = (result: DropResult) => { + const { queries, onChangeQueries, panel } = this.props; + + if (!result || !result.destination) { + return; + } + + const startIndex = result.source.index; + const endIndex = result.destination.index; + if (startIndex === endIndex) { + return; + } + + const update = Array.from(queries); + const [removed] = update.splice(startIndex, 1); + update.splice(endIndex, 0, removed); + onChangeQueries(update); + panel.refresh(); + }; + render() { const { props } = this; - return props.queries.map((query, index) => ( - this.onChangeQuery(query, index)} - onRemoveQuery={this.onRemoveQuery} - onAddQuery={this.onAddQuery} - onMoveQuery={this.onMoveQuery} - inMixedMode={props.datasource.meta.mixed} - /> - )); + return ( + + + {provided => { + return ( +
+ {props.queries.map((query, index) => ( + this.onChangeQuery(query, index)} + onRemoveQuery={this.onRemoveQuery} + onAddQuery={this.onAddQuery} + inMixedMode={props.datasource.meta.mixed} + /> + ))} +
+ ); + }} +
+
+ ); } }