diff --git a/public/app/core/components/CopyToClipboard/CopyToClipboard.tsx b/public/app/core/components/CopyToClipboard/CopyToClipboard.tsx new file mode 100644 index 00000000000..153dae2a9c6 --- /dev/null +++ b/public/app/core/components/CopyToClipboard/CopyToClipboard.tsx @@ -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 { + 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 + ); + } +} diff --git a/public/app/core/components/JSONFormatter/JSONFormatter.tsx b/public/app/core/components/JSONFormatter/JSONFormatter.tsx index 1dcc9fd170b..73c055de94b 100644 --- a/public/app/core/components/JSONFormatter/JSONFormatter.tsx +++ b/public/app/core/components/JSONFormatter/JSONFormatter.tsx @@ -7,6 +7,7 @@ interface Props { json: {}; config?: any; open?: number; + onDidRender?: (formattedJson: any) => void; } export class JSONFormatter extends PureComponent { @@ -16,7 +17,6 @@ export class JSONFormatter extends PureComponent { open: 3, config: { animateOpen: true, - theme: 'dark', }, }; @@ -29,7 +29,7 @@ export class JSONFormatter extends PureComponent { } renderJson = () => { - const { json, config, open } = this.props; + const { json, config, open, onDidRender } = this.props; const wrapperEl = this.wrapperRef.current; const formatter = new JsonExplorer(json, open, config); const hasChildren: boolean = wrapperEl.hasChildNodes(); @@ -38,6 +38,10 @@ export class JSONFormatter extends PureComponent { } else { wrapperEl.appendChild(formatter.render()); } + + if (onDidRender) { + onDidRender(formatter.json); + } }; render() { diff --git a/public/app/features/dashboard/dashgrid/QueriesTab.tsx b/public/app/features/dashboard/dashgrid/QueriesTab.tsx index db5bcc44f2d..d35e55f591d 100644 --- a/public/app/features/dashboard/dashgrid/QueriesTab.tsx +++ b/public/app/features/dashboard/dashgrid/QueriesTab.tsx @@ -3,11 +3,11 @@ import DataSourceOption from './DataSourceOption'; import { getAngularLoader, AngularComponent } from 'app/core/services/AngularLoader'; import { EditorTabBody } from './EditorTabBody'; import { DataSourcePicker } from './DataSourcePicker'; -import { JSONFormatter } from 'app/core/components/JSONFormatter/JSONFormatter'; import { PanelModel } from '../panel_model'; import { DashboardModel } from '../dashboard_model'; import './../../panel/metrics_tab'; import config from 'app/core/config'; +import { QueryInspector } from './QueryInspector'; // Services import { getDatasourceSrv } from 'app/features/plugins/datasource_srv'; @@ -298,7 +298,11 @@ export class QueriesTab extends PureComponent { renderQueryInspector = () => { const { response, isLoading } = this.state.dsQuery; - return isLoading ? : ; + return isLoading ? ( + + ) : ( + + ); }; renderHelp = () => { diff --git a/public/app/features/dashboard/dashgrid/QueryInspector.tsx b/public/app/features/dashboard/dashgrid/QueryInspector.tsx new file mode 100644 index 00000000000..ace155fec43 --- /dev/null +++ b/public/app/features/dashboard/dashgrid/QueryInspector.tsx @@ -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 { + 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 ( + <> + {/* */} + {/* + */} + + + <> + Copy to Clipboard + + + + + ); + } +}