2018-12-13 21:24:41 +01:00
|
|
|
import React, { PureComponent } from 'react';
|
2018-11-26 13:57:31 +01:00
|
|
|
import appEvents from 'app/core/app_events';
|
|
|
|
|
import { CopyToClipboard } from 'app/core/components/CopyToClipboard/CopyToClipboard';
|
2020-01-27 07:25:24 +01:00
|
|
|
import { JSONFormatter, LoadingPlaceholder } from '@grafana/ui';
|
2019-10-14 09:27:47 +01:00
|
|
|
import { CoreEvents } from 'app/types';
|
2019-10-31 10:48:05 +01:00
|
|
|
import { AppEvents, PanelEvents } from '@grafana/data';
|
2018-11-26 13:57:31 +01:00
|
|
|
|
2018-11-27 10:52:47 +01:00
|
|
|
interface DsQuery {
|
|
|
|
|
isLoading: boolean;
|
|
|
|
|
response: {};
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-26 13:57:31 +01:00
|
|
|
interface Props {
|
2018-11-27 10:52:47 +01:00
|
|
|
panel: any;
|
2018-11-26 13:57:31 +01:00
|
|
|
}
|
|
|
|
|
|
2018-11-26 14:26:28 +01:00
|
|
|
interface State {
|
|
|
|
|
allNodesExpanded: boolean;
|
2018-11-27 10:52:47 +01:00
|
|
|
isMocking: boolean;
|
|
|
|
|
mockedResponse: string;
|
|
|
|
|
dsQuery: DsQuery;
|
2018-11-26 14:26:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export class QueryInspector extends PureComponent<Props, State> {
|
2018-11-26 13:57:31 +01:00
|
|
|
formattedJson: any;
|
|
|
|
|
clipboard: any;
|
|
|
|
|
|
2019-07-30 15:49:32 +02:00
|
|
|
constructor(props: Props) {
|
2018-11-26 13:57:31 +01:00
|
|
|
super(props);
|
2018-11-26 14:26:28 +01:00
|
|
|
this.state = {
|
|
|
|
|
allNodesExpanded: null,
|
2018-11-27 10:52:47 +01:00
|
|
|
isMocking: false,
|
|
|
|
|
mockedResponse: '',
|
|
|
|
|
dsQuery: {
|
|
|
|
|
isLoading: false,
|
|
|
|
|
response: {},
|
|
|
|
|
},
|
2018-11-26 14:26:28 +01:00
|
|
|
};
|
2018-11-26 13:57:31 +01:00
|
|
|
}
|
|
|
|
|
|
2018-11-27 10:52:47 +01:00
|
|
|
componentDidMount() {
|
|
|
|
|
const { panel } = this.props;
|
2019-04-12 10:01:50 +02:00
|
|
|
|
2019-10-14 09:27:47 +01:00
|
|
|
appEvents.on(CoreEvents.dsRequestResponse, this.onDataSourceResponse);
|
|
|
|
|
appEvents.on(CoreEvents.dsRequestError, this.onRequestError);
|
2019-04-12 10:01:50 +02:00
|
|
|
|
2019-10-14 09:27:47 +01:00
|
|
|
panel.events.on(PanelEvents.refresh, this.onPanelRefresh);
|
2018-11-27 10:52:47 +01:00
|
|
|
panel.refresh();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
componentWillUnmount() {
|
|
|
|
|
const { panel } = this.props;
|
2019-04-12 10:01:50 +02:00
|
|
|
|
2019-10-14 09:27:47 +01:00
|
|
|
appEvents.off(CoreEvents.dsRequestResponse, this.onDataSourceResponse);
|
|
|
|
|
appEvents.on(CoreEvents.dsRequestError, this.onRequestError);
|
2019-04-12 10:01:50 +02:00
|
|
|
|
2019-10-14 09:27:47 +01:00
|
|
|
panel.events.off(PanelEvents.refresh, this.onPanelRefresh);
|
2018-11-27 10:52:47 +01:00
|
|
|
}
|
|
|
|
|
|
2019-07-30 15:49:32 +02:00
|
|
|
handleMocking(response: any) {
|
2018-11-27 10:52:47 +01:00
|
|
|
const { mockedResponse } = this.state;
|
|
|
|
|
let mockedData;
|
|
|
|
|
try {
|
|
|
|
|
mockedData = JSON.parse(mockedResponse);
|
|
|
|
|
} catch (err) {
|
2019-10-14 09:27:47 +01:00
|
|
|
appEvents.emit(AppEvents.alertError, ['R: Failed to parse mocked response']);
|
2018-11-27 10:52:47 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
response.data = mockedData;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
onPanelRefresh = () => {
|
|
|
|
|
this.setState(prevState => ({
|
|
|
|
|
...prevState,
|
|
|
|
|
dsQuery: {
|
|
|
|
|
isLoading: true,
|
|
|
|
|
response: {},
|
|
|
|
|
},
|
|
|
|
|
}));
|
|
|
|
|
};
|
|
|
|
|
|
2019-04-12 10:01:50 +02:00
|
|
|
onRequestError = (err: any) => {
|
|
|
|
|
this.onDataSourceResponse(err);
|
|
|
|
|
};
|
|
|
|
|
|
2018-11-27 10:52:47 +01:00
|
|
|
onDataSourceResponse = (response: any = {}) => {
|
|
|
|
|
if (this.state.isMocking) {
|
|
|
|
|
this.handleMocking(response);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-27 12:33:30 +01:00
|
|
|
response = { ...response }; // clone - dont modify the response
|
2018-11-27 10:52:47 +01:00
|
|
|
|
|
|
|
|
if (response.headers) {
|
|
|
|
|
delete response.headers;
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-27 07:25:24 +01:00
|
|
|
if (response.request) {
|
2018-11-27 10:52:47 +01:00
|
|
|
delete response.request.transformRequest;
|
|
|
|
|
delete response.request.transformResponse;
|
|
|
|
|
delete response.request.paramSerializer;
|
|
|
|
|
delete response.request.jsonpCallbackParam;
|
|
|
|
|
delete response.request.headers;
|
|
|
|
|
delete response.request.requestId;
|
|
|
|
|
delete response.request.inspect;
|
|
|
|
|
delete response.request.retry;
|
|
|
|
|
delete response.request.timeout;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (response.data) {
|
|
|
|
|
response.response = response.data;
|
|
|
|
|
|
|
|
|
|
delete response.data;
|
|
|
|
|
delete response.status;
|
|
|
|
|
delete response.statusText;
|
2020-01-27 07:25:24 +01:00
|
|
|
delete response.ok;
|
|
|
|
|
delete response.url;
|
|
|
|
|
delete response.redirected;
|
|
|
|
|
delete response.type;
|
2018-11-27 10:52:47 +01:00
|
|
|
delete response.$$config;
|
|
|
|
|
}
|
|
|
|
|
this.setState(prevState => ({
|
|
|
|
|
...prevState,
|
|
|
|
|
dsQuery: {
|
|
|
|
|
isLoading: false,
|
|
|
|
|
response: response,
|
|
|
|
|
},
|
|
|
|
|
}));
|
|
|
|
|
};
|
|
|
|
|
|
2019-07-30 15:49:32 +02:00
|
|
|
setFormattedJson = (formattedJson: any) => {
|
2018-11-26 13:57:31 +01:00
|
|
|
this.formattedJson = formattedJson;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
getTextForClipboard = () => {
|
|
|
|
|
return JSON.stringify(this.formattedJson, null, 2);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
onClipboardSuccess = () => {
|
2019-10-14 09:27:47 +01:00
|
|
|
appEvents.emit(AppEvents.alertSuccess, ['Content copied to clipboard']);
|
2018-11-26 13:57:31 +01:00
|
|
|
};
|
|
|
|
|
|
2018-11-26 14:26:28 +01:00
|
|
|
onToggleExpand = () => {
|
|
|
|
|
this.setState(prevState => ({
|
|
|
|
|
...prevState,
|
|
|
|
|
allNodesExpanded: !this.state.allNodesExpanded,
|
|
|
|
|
}));
|
|
|
|
|
};
|
|
|
|
|
|
2018-11-27 10:52:47 +01:00
|
|
|
onToggleMocking = () => {
|
|
|
|
|
this.setState(prevState => ({
|
|
|
|
|
...prevState,
|
|
|
|
|
isMocking: !this.state.isMocking,
|
|
|
|
|
}));
|
|
|
|
|
};
|
|
|
|
|
|
2018-11-26 14:26:28 +01:00
|
|
|
getNrOfOpenNodes = () => {
|
|
|
|
|
if (this.state.allNodesExpanded === null) {
|
2018-11-27 10:52:47 +01:00
|
|
|
return 3; // 3 is default, ie when state is null
|
2018-11-26 14:26:28 +01:00
|
|
|
} else if (this.state.allNodesExpanded) {
|
|
|
|
|
return 20;
|
|
|
|
|
}
|
|
|
|
|
return 1;
|
|
|
|
|
};
|
|
|
|
|
|
2019-07-30 15:49:32 +02:00
|
|
|
setMockedResponse = (evt: any) => {
|
2018-11-27 10:52:47 +01:00
|
|
|
const mockedResponse = evt.target.value;
|
|
|
|
|
this.setState(prevState => ({
|
|
|
|
|
...prevState,
|
|
|
|
|
mockedResponse,
|
|
|
|
|
}));
|
|
|
|
|
};
|
|
|
|
|
|
2018-11-27 12:33:30 +01:00
|
|
|
renderExpandCollapse = () => {
|
|
|
|
|
const { allNodesExpanded } = this.state;
|
|
|
|
|
|
|
|
|
|
const collapse = (
|
|
|
|
|
<>
|
|
|
|
|
<i className="fa fa-minus-square-o" /> Collapse All
|
|
|
|
|
</>
|
|
|
|
|
);
|
|
|
|
|
const expand = (
|
|
|
|
|
<>
|
|
|
|
|
<i className="fa fa-plus-square-o" /> Expand All
|
|
|
|
|
</>
|
|
|
|
|
);
|
|
|
|
|
return allNodesExpanded ? collapse : expand;
|
|
|
|
|
};
|
|
|
|
|
|
2018-11-26 13:57:31 +01:00
|
|
|
render() {
|
2018-11-27 10:52:47 +01:00
|
|
|
const { response, isLoading } = this.state.dsQuery;
|
2018-11-26 14:26:28 +01:00
|
|
|
const openNodes = this.getNrOfOpenNodes();
|
2018-11-27 10:52:47 +01:00
|
|
|
|
|
|
|
|
if (isLoading) {
|
|
|
|
|
return <LoadingPlaceholder text="Loading query inspector..." />;
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-26 13:57:31 +01:00
|
|
|
return (
|
|
|
|
|
<>
|
2018-12-13 21:24:41 +01:00
|
|
|
<div className="pull-right">
|
2018-11-27 10:52:47 +01:00
|
|
|
<button className="btn btn-transparent btn-p-x-0 m-r-1" onClick={this.onToggleExpand}>
|
2018-11-27 12:33:30 +01:00
|
|
|
{this.renderExpandCollapse()}
|
2018-11-27 10:52:47 +01:00
|
|
|
</button>
|
|
|
|
|
<CopyToClipboard
|
|
|
|
|
className="btn btn-transparent btn-p-x-0"
|
|
|
|
|
text={this.getTextForClipboard}
|
|
|
|
|
onSuccess={this.onClipboardSuccess}
|
|
|
|
|
>
|
2018-11-27 12:23:11 +01:00
|
|
|
<i className="fa fa-clipboard" /> Copy to Clipboard
|
2018-11-27 10:52:47 +01:00
|
|
|
</CopyToClipboard>
|
|
|
|
|
</div>
|
|
|
|
|
|
2019-01-18 19:22:40 +01:00
|
|
|
<JSONFormatter json={response} open={openNodes} onDidRender={this.setFormattedJson} />
|
2018-11-26 13:57:31 +01:00
|
|
|
</>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|