Commit 7a1eff19 by Ivana Huckova Committed by GitHub

Explore: Add functionality to show/hide query row results (#19794)

parent 2a78d2a6
......@@ -7,11 +7,12 @@ import { hot } from 'react-hot-loader';
import { connect } from 'react-redux';
// Components
import QueryEditor from './QueryEditor';
import { QueryRowActions } from './QueryRowActions';
// Actions
import { changeQuery, modifyQueries, runQueries, addQueryRow } from './state/actions';
// Types
import { StoreState } from 'app/types';
import { TimeRange, AbsoluteTimeRange } from '@grafana/data';
import { TimeRange, AbsoluteTimeRange, LoadingState } from '@grafana/data';
import { DataQuery, DataSourceApi, QueryFixAction, DataSourceStatus, PanelData } from '@grafana/ui';
import { HistoryItem, ExploreItemState, ExploreId, ExploreMode } from 'app/types/explore';
import { Emitter } from 'app/core/utils/emitter';
......@@ -76,8 +77,13 @@ export class QueryRow extends PureComponent<QueryRowProps, QueryRowState> {
this.props.addQueryRow(exploreId, index);
};
onClickClearButton = () => {
this.onChange(null, true);
onClickToggleHiddenQuery = () => {
const { exploreId, index, query } = this.props;
const newQuery = {
...query,
hide: !query.hide,
};
this.props.changeQuery(exploreId, newQuery, index, true);
};
onClickHintFix = (action: QueryFixAction) => {
......@@ -120,8 +126,10 @@ export class QueryRow extends PureComponent<QueryRowProps, QueryRowState> {
latency,
mode,
} = this.props;
const canToggleEditorModes =
mode === ExploreMode.Metrics && has(datasourceInstance, 'components.QueryCtrl.prototype.toggleEditorMode');
const canHide = queryResponse.state !== LoadingState.NotStarted;
const queryErrors = queryResponse.error && queryResponse.error.refId === query.refId ? [queryResponse.error] : [];
let QueryField;
......@@ -163,32 +171,17 @@ export class QueryRow extends PureComponent<QueryRowProps, QueryRowState> {
)}
</div>
<div className="query-row-status">
<QueryStatus queryResponse={queryResponse} latency={latency} />
</div>
<div className="gf-form-inline flex-shrink-0">
{canToggleEditorModes && (
<div className="gf-form">
<button className="gf-form-label gf-form-label--btn" onClick={this.onClickToggleEditorMode}>
<i className="fa fa-pencil" />
</button>
</div>
)}
<div className="gf-form">
<button className="gf-form-label gf-form-label--btn" onClick={this.onClickClearButton}>
<i className="fa fa-times" />
</button>
</div>
<div className="gf-form">
<button className="gf-form-label gf-form-label--btn" onClick={this.onClickAddButton}>
<i className="fa fa-plus" />
</button>
</div>
<div className="gf-form">
<button className="gf-form-label gf-form-label--btn" onClick={this.onClickRemoveButton}>
<i className="fa fa-minus" />
</button>
</div>
<QueryStatus queryResponse={queryResponse} latency={query.hide ? 0 : latency} />
</div>
<QueryRowActions
canToggleEditorModes={canToggleEditorModes}
hideQuery={query.hide}
canHide={canHide}
onClickToggleEditorMode={this.onClickToggleEditorMode}
onClickToggleHiddenQuery={this.onClickToggleHiddenQuery}
onClickAddButton={this.onClickAddButton}
onClickRemoveButton={this.onClickRemoveButton}
/>
</div>
);
}
......
import React from 'react';
import { QueryRowActions, Props } from './QueryRowActions';
import { shallow } from 'enzyme';
const setup = (propOverrides?: object) => {
const props: Props = {
hideQuery: false,
canHide: true,
canToggleEditorModes: true,
onClickToggleEditorMode: () => {},
onClickToggleHiddenQuery: () => {},
onClickAddButton: () => {},
onClickRemoveButton: () => {},
};
Object.assign(props, propOverrides);
const wrapper = shallow(<QueryRowActions {...props} />);
return wrapper;
};
describe('QueryRowActions', () => {
it('should render component', () => {
const wrapper = setup();
expect(wrapper).toMatchSnapshot();
});
it('should render component without editor mode', () => {
const wrapper = setup({ canToggleEditorModes: false });
expect(wrapper.find({ 'aria-label': 'Edit mode button' })).toHaveLength(0);
});
it('should change icon to fa-eye-slash when query row result is hidden', () => {
const wrapper = setup({ hideQuery: true });
expect(wrapper.find('i.fa-eye-slash')).toHaveLength(1);
});
it('should change icon to fa-eye when query row result is not hidden', () => {
const wrapper = setup({ hideQuery: false });
expect(wrapper.find('i.fa-eye')).toHaveLength(1);
});
});
import React from 'react';
export type Props = {
canToggleEditorModes: boolean;
hideQuery: boolean;
canHide: boolean;
onClickToggleEditorMode: () => void;
onClickToggleHiddenQuery: () => void;
onClickAddButton: () => void;
onClickRemoveButton: () => void;
};
export function QueryRowActions(props: Props) {
const {
canToggleEditorModes,
onClickToggleEditorMode,
onClickToggleHiddenQuery,
onClickAddButton,
onClickRemoveButton,
hideQuery,
canHide,
} = props;
return (
<div className="gf-form-inline flex-shrink-0">
{canToggleEditorModes && (
<div className="gf-form">
<button
aria-label="Edit mode button"
className="gf-form-label gf-form-label--btn"
onClick={onClickToggleEditorMode}
>
<i className="fa fa-pencil" />
</button>
</div>
)}
<div className="gf-form">
<button disabled={!canHide} className="gf-form-label gf-form-label--btn" onClick={onClickToggleHiddenQuery}>
<i className={hideQuery ? 'fa fa-eye-slash' : 'fa fa-eye'} />
</button>
</div>
<div className="gf-form">
<button className="gf-form-label gf-form-label--btn" onClick={onClickAddButton}>
<i className="fa fa-plus" />
</button>
</div>
<div className="gf-form">
<button className="gf-form-label gf-form-label--btn" onClick={onClickRemoveButton}>
<i className="fa fa-minus" />
</button>
</div>
</div>
);
}
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`QueryRowActions should render component 1`] = `
<div
className="gf-form-inline flex-shrink-0"
>
<div
className="gf-form"
>
<button
aria-label="Edit mode button"
className="gf-form-label gf-form-label--btn"
onClick={[Function]}
>
<i
className="fa fa-pencil"
/>
</button>
</div>
<div
className="gf-form"
>
<button
className="gf-form-label gf-form-label--btn"
disabled={false}
onClick={[Function]}
>
<i
className="fa fa-eye"
/>
</button>
</div>
<div
className="gf-form"
>
<button
className="gf-form-label gf-form-label--btn"
onClick={[Function]}
>
<i
className="fa fa-plus"
/>
</button>
</div>
<div
className="gf-form"
>
<button
className="gf-form-label gf-form-label--btn"
onClick={[Function]}
>
<i
className="fa fa-minus"
/>
</button>
</div>
</div>
`;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment