diff --git a/packages/grafana-ui/src/components/Monaco/CodeEditor.tsx b/packages/grafana-ui/src/components/Monaco/CodeEditor.tsx index ae959975bbb..00aaf6b4533 100644 --- a/packages/grafana-ui/src/components/Monaco/CodeEditor.tsx +++ b/packages/grafana-ui/src/components/Monaco/CodeEditor.tsx @@ -129,7 +129,8 @@ class UnthemedCodeEditor extends PureComponent { }; render() { - const { theme, language, width, height, showMiniMap, showLineNumbers, readOnly, monacoOptions } = this.props; + const { theme, language, width, height, showMiniMap, showLineNumbers, readOnly, wordWrap, monacoOptions } = + this.props; const { alwaysConsumeMouseWheel, ...restMonacoOptions } = monacoOptions ?? {}; const value = this.props.value ?? ''; @@ -138,7 +139,7 @@ class UnthemedCodeEditor extends PureComponent { const containerStyles = this.props.containerStyles ?? getStyles(theme).container; const options: MonacoOptions = { - wordWrap: 'off', + wordWrap: wordWrap ? 'on' : 'off', tabSize: 2, codeLens: false, contextmenu: false, diff --git a/packages/grafana-ui/src/components/Monaco/types.ts b/packages/grafana-ui/src/components/Monaco/types.ts index d41fcbe13d3..0d403c0ca24 100644 --- a/packages/grafana-ui/src/components/Monaco/types.ts +++ b/packages/grafana-ui/src/components/Monaco/types.ts @@ -27,6 +27,7 @@ export interface CodeEditorProps { readOnly?: boolean; showMiniMap?: boolean; showLineNumbers?: boolean; + wordWrap?: boolean; monacoOptions?: MonacoOptions; /** diff --git a/packages/grafana-ui/src/components/Table/CellActions.tsx b/packages/grafana-ui/src/components/Table/CellActions.tsx index e5908664428..222c441d5e2 100644 --- a/packages/grafana-ui/src/components/Table/CellActions.tsx +++ b/packages/grafana-ui/src/components/Table/CellActions.tsx @@ -6,12 +6,12 @@ import { IconButton } from '../IconButton/IconButton'; import { Stack } from '../Layout/Stack/Stack'; import { TooltipPlacement } from '../Tooltip'; -import { TableCellInspector } from './TableCellInspector'; +import { TableCellInspector, TableCellInspectorMode } from './TableCellInspector'; import { FILTER_FOR_OPERATOR, FILTER_OUT_OPERATOR, TableCellProps } from './types'; import { getTextAlign } from './utils'; interface CellActionProps extends TableCellProps { - previewMode: 'text' | 'code'; + previewMode: TableCellInspectorMode; } interface CommonButtonProps { diff --git a/packages/grafana-ui/src/components/Table/DefaultCell.tsx b/packages/grafana-ui/src/components/Table/DefaultCell.tsx index 02b03f10ea3..77a30a7c051 100644 --- a/packages/grafana-ui/src/components/Table/DefaultCell.tsx +++ b/packages/grafana-ui/src/components/Table/DefaultCell.tsx @@ -11,6 +11,7 @@ import { clearLinkButtonStyles } from '../Button'; import { DataLinksContextMenu } from '../DataLinks/DataLinksContextMenu'; import { CellActions } from './CellActions'; +import { TableCellInspectorMode } from './TableCellInspector'; import { TableStyles } from './styles'; import { TableCellProps, CustomCellRendererProps, TableCellOptions } from './types'; import { getCellColors, getCellOptions } from './utils'; @@ -114,7 +115,9 @@ export const DefaultCell = (props: TableCellProps) => { )} - {hover && showActions && } + {hover && showActions && ( + + )} ); }; diff --git a/packages/grafana-ui/src/components/Table/JSONViewCell.tsx b/packages/grafana-ui/src/components/Table/JSONViewCell.tsx index ba5691b2c7e..d013d6dc6ad 100644 --- a/packages/grafana-ui/src/components/Table/JSONViewCell.tsx +++ b/packages/grafana-ui/src/components/Table/JSONViewCell.tsx @@ -7,6 +7,7 @@ import { Button, clearLinkButtonStyles } from '../Button'; import { DataLinksContextMenu } from '../DataLinks/DataLinksContextMenu'; import { CellActions } from './CellActions'; +import { TableCellInspectorMode } from './TableCellInspector'; import { TableCellProps } from './types'; export function JSONViewCell(props: TableCellProps): JSX.Element { @@ -51,7 +52,7 @@ export function JSONViewCell(props: TableCellProps): JSX.Element { )} - {inspectEnabled && } + {inspectEnabled && } ); } diff --git a/packages/grafana-ui/src/components/Table/TableCellInspector.tsx b/packages/grafana-ui/src/components/Table/TableCellInspector.tsx index 7cc49f706b6..7f318608705 100644 --- a/packages/grafana-ui/src/components/Table/TableCellInspector.tsx +++ b/packages/grafana-ui/src/components/Table/TableCellInspector.tsx @@ -1,57 +1,84 @@ import { isString } from 'lodash'; +import { useState } from 'react'; import { ClipboardButton } from '../ClipboardButton/ClipboardButton'; import { Drawer } from '../Drawer/Drawer'; +import { Stack } from '../Layout/Stack/Stack'; import { CodeEditor } from '../Monaco/CodeEditor'; +import { Tab, TabsBar } from '../Tabs'; + +export enum TableCellInspectorMode { + code = 'code', + text = 'text', +} interface TableCellInspectorProps { value: any; onDismiss: () => void; - mode: 'code' | 'text'; + mode: TableCellInspectorMode; } export function TableCellInspector({ value, onDismiss, mode }: TableCellInspectorProps) { let displayValue = value; + const [currentMode, setMode] = useState(mode); + if (isString(value)) { const trimmedValue = value.trim(); // Exclude numeric strings like '123' from being displayed in code/JSON mode if (trimmedValue[0] === '{' || trimmedValue[0] === '[' || mode === 'code') { try { value = JSON.parse(value); - mode = 'code'; - } catch { - mode = 'text'; - } // ignore errors - } else { - mode = 'text'; + } catch {} } } else { displayValue = JSON.stringify(value, null, ' '); } let text = displayValue; - if (mode === 'code') { - text = JSON.stringify(value, null, ' '); - } + const tabs = [ + { + label: 'Plain text', + value: 'text', + }, + { + label: 'Code editor', + value: 'code', + }, + ]; + + const changeTabs = () => { + setMode(currentMode === TableCellInspectorMode.text ? TableCellInspectorMode.code : TableCellInspectorMode.text); + }; + + const tabBar = ( + + {tabs.map((t, index) => ( + + ))} + + ); return ( - - {mode === 'code' ? ( - 100} - value={text} - readOnly={true} - /> - ) : ( -
{text}
- )} - text}> - Copy to Clipboard - + + + text} style={{ marginLeft: 'auto', width: '200px' }}> + Copy to Clipboard + + {currentMode === 'code' ? ( + 100} + value={text} + readOnly={true} + wordWrap={true} + /> + ) : ( +
{text}
+ )} +
); }