mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
react-panel: Add CopyToClipboard-component and separate QueryInspector to its own component from QueriesTab
This commit is contained in:
@@ -0,0 +1,67 @@
|
|||||||
|
import React, { PureComponent } from 'react';
|
||||||
|
import ClipboardJS from 'clipboard';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
text: () => string;
|
||||||
|
elType?: string;
|
||||||
|
onSuccess?: (evt: any) => void;
|
||||||
|
onError?: (evt: any) => void;
|
||||||
|
className?: string;
|
||||||
|
children?: JSX.Element | string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class CopyToClipboard extends PureComponent<Props> {
|
||||||
|
clipboardjs: any;
|
||||||
|
myRef: any;
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.myRef = React.createRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
const { text, onSuccess, onError } = this.props;
|
||||||
|
|
||||||
|
this.clipboardjs = new ClipboardJS(this.myRef.current, {
|
||||||
|
text: text,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (onSuccess) {
|
||||||
|
this.clipboardjs.on('success', evt => {
|
||||||
|
evt.clearSelection();
|
||||||
|
onSuccess(evt);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (onError) {
|
||||||
|
this.clipboardjs.on('error', evt => {
|
||||||
|
console.error('Action:', evt.action);
|
||||||
|
console.error('Trigger:', evt.trigger);
|
||||||
|
onError(evt);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
if (this.clipboardjs) {
|
||||||
|
this.clipboardjs.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getElementType = () => {
|
||||||
|
return this.props.elType || 'button';
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { elType, text, children, onError, onSuccess, ...restProps } = this.props;
|
||||||
|
|
||||||
|
return React.createElement(
|
||||||
|
this.getElementType(),
|
||||||
|
{
|
||||||
|
ref: this.myRef,
|
||||||
|
...restProps,
|
||||||
|
},
|
||||||
|
this.props.children
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@ interface Props {
|
|||||||
json: {};
|
json: {};
|
||||||
config?: any;
|
config?: any;
|
||||||
open?: number;
|
open?: number;
|
||||||
|
onDidRender?: (formattedJson: any) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class JSONFormatter extends PureComponent<Props> {
|
export class JSONFormatter extends PureComponent<Props> {
|
||||||
@@ -16,7 +17,6 @@ export class JSONFormatter extends PureComponent<Props> {
|
|||||||
open: 3,
|
open: 3,
|
||||||
config: {
|
config: {
|
||||||
animateOpen: true,
|
animateOpen: true,
|
||||||
theme: 'dark',
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -29,7 +29,7 @@ export class JSONFormatter extends PureComponent<Props> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderJson = () => {
|
renderJson = () => {
|
||||||
const { json, config, open } = this.props;
|
const { json, config, open, onDidRender } = this.props;
|
||||||
const wrapperEl = this.wrapperRef.current;
|
const wrapperEl = this.wrapperRef.current;
|
||||||
const formatter = new JsonExplorer(json, open, config);
|
const formatter = new JsonExplorer(json, open, config);
|
||||||
const hasChildren: boolean = wrapperEl.hasChildNodes();
|
const hasChildren: boolean = wrapperEl.hasChildNodes();
|
||||||
@@ -38,6 +38,10 @@ export class JSONFormatter extends PureComponent<Props> {
|
|||||||
} else {
|
} else {
|
||||||
wrapperEl.appendChild(formatter.render());
|
wrapperEl.appendChild(formatter.render());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (onDidRender) {
|
||||||
|
onDidRender(formatter.json);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|||||||
@@ -3,11 +3,11 @@ import DataSourceOption from './DataSourceOption';
|
|||||||
import { getAngularLoader, AngularComponent } from 'app/core/services/AngularLoader';
|
import { getAngularLoader, AngularComponent } from 'app/core/services/AngularLoader';
|
||||||
import { EditorTabBody } from './EditorTabBody';
|
import { EditorTabBody } from './EditorTabBody';
|
||||||
import { DataSourcePicker } from './DataSourcePicker';
|
import { DataSourcePicker } from './DataSourcePicker';
|
||||||
import { JSONFormatter } from 'app/core/components/JSONFormatter/JSONFormatter';
|
|
||||||
import { PanelModel } from '../panel_model';
|
import { PanelModel } from '../panel_model';
|
||||||
import { DashboardModel } from '../dashboard_model';
|
import { DashboardModel } from '../dashboard_model';
|
||||||
import './../../panel/metrics_tab';
|
import './../../panel/metrics_tab';
|
||||||
import config from 'app/core/config';
|
import config from 'app/core/config';
|
||||||
|
import { QueryInspector } from './QueryInspector';
|
||||||
|
|
||||||
// Services
|
// Services
|
||||||
import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
|
import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
|
||||||
@@ -298,7 +298,11 @@ export class QueriesTab extends PureComponent<Props, State> {
|
|||||||
|
|
||||||
renderQueryInspector = () => {
|
renderQueryInspector = () => {
|
||||||
const { response, isLoading } = this.state.dsQuery;
|
const { response, isLoading } = this.state.dsQuery;
|
||||||
return isLoading ? <LoadingPlaceholder text="Loading query inspector..." /> : <JSONFormatter json={response} />;
|
return isLoading ? (
|
||||||
|
<LoadingPlaceholder text="Loading query inspector..." />
|
||||||
|
) : (
|
||||||
|
<QueryInspector response={response} />
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
renderHelp = () => {
|
renderHelp = () => {
|
||||||
|
|||||||
61
public/app/features/dashboard/dashgrid/QueryInspector.tsx
Normal file
61
public/app/features/dashboard/dashgrid/QueryInspector.tsx
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
import React, { PureComponent } from 'react';
|
||||||
|
import { JSONFormatter } from 'app/core/components/JSONFormatter/JSONFormatter';
|
||||||
|
import appEvents from 'app/core/app_events';
|
||||||
|
import { CopyToClipboard } from 'app/core/components/CopyToClipboard/CopyToClipboard';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
response: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class QueryInspector extends PureComponent<Props> {
|
||||||
|
formattedJson: any;
|
||||||
|
clipboard: any;
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
|
|
||||||
|
setFormattedJson = formattedJson => {
|
||||||
|
this.formattedJson = formattedJson;
|
||||||
|
};
|
||||||
|
|
||||||
|
getTextForClipboard = () => {
|
||||||
|
return JSON.stringify(this.formattedJson, null, 2);
|
||||||
|
};
|
||||||
|
|
||||||
|
onClipboardSuccess = () => {
|
||||||
|
appEvents.emit('alert-success', ['Content copied to clipboard']);
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { response } = this.props;
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{/* <div className="query-troubleshooter__header">
|
||||||
|
<a className="pointer" ng-click="ctrl.toggleMocking()">Mock Response</a>
|
||||||
|
<a className="pointer" ng-click="ctrl.toggleExpand()" ng-hide="ctrl.allNodesExpanded">
|
||||||
|
<i className="fa fa-plus-square-o"></i> Expand All
|
||||||
|
</a>
|
||||||
|
<a className="pointer ng-hide" ng-click="ctrl.toggleExpand()" ng-show="ctrl.allNodesExpanded">
|
||||||
|
<i className="fa fa-minus-square-o"></i> Collapse All
|
||||||
|
</a>
|
||||||
|
<a className="pointer ng-isolate-scope" clipboard-button="ctrl.getClipboardText()"><i className="fa fa-clipboard"></i> Copy to Clipboard</a>
|
||||||
|
|
||||||
|
</div> */}
|
||||||
|
{/* <button onClick={this.copyToClipboard}>Copy</button>
|
||||||
|
<button ref={this.copyButtonRef}>Copy2</button> */}
|
||||||
|
|
||||||
|
<CopyToClipboard
|
||||||
|
className="btn btn-transparent"
|
||||||
|
text={this.getTextForClipboard}
|
||||||
|
onSuccess={this.onClipboardSuccess}
|
||||||
|
>
|
||||||
|
<>
|
||||||
|
<i className="fa fa-clipboard" /> Copy to Clipboard
|
||||||
|
</>
|
||||||
|
</CopyToClipboard>
|
||||||
|
<JSONFormatter json={response} onDidRender={this.setFormattedJson} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user