diff --git a/package.json b/package.json index d328e24dd..f73d174c0 100644 --- a/package.json +++ b/package.json @@ -53,6 +53,7 @@ "react-syntax-highlighter": "^15.5.0", "shape": "npm:@multiprocess/shape", "source-map-support": "^0.5.21", + "sql-formatter": "^6.1.1", "tmp-promise": "^3.0.3", "tweetnacl": "^1.0.3", "tweetnacl-util": "^0.15.1", diff --git a/ui/Panel.tsx b/ui/Panel.tsx index 1c290ca9c..dcd6e7171 100644 --- a/ui/Panel.tsx +++ b/ui/Panel.tsx @@ -4,6 +4,7 @@ import { IconArrowsDiagonalMinimize2, IconArrowsMaximize, IconArrowsMinimize, + IconBraces, IconChevronDown, IconChevronUp, IconEye, @@ -17,10 +18,11 @@ import formatDistanceToNow from 'date-fns/formatDistanceToNow'; import circularSafeStringify from 'json-stringify-safe'; import * as React from 'react'; import { toString } from 'shape'; +import { format as sqlFormat } from 'sql-formatter'; import { MODE_FEATURES } from '../shared/constants'; import { EVAL_ERRORS } from '../shared/errors'; import log from '../shared/log'; -import { PanelInfo, PanelResult } from '../shared/state'; +import { PanelInfo, PanelResult, ProgramPanelInfo } from '../shared/state'; import { humanSize } from '../shared/text'; import { panelRPC } from './asyncRPC'; import { Alert } from './components/Alert'; @@ -255,6 +257,22 @@ export function Panel({ setError(results.exception); }, [results.exception]); + function formatThis() { + const old = panel.content; + try { + panel.content = sqlFormat(old); + if (panel.content === old) { + // Don't update if it hasn't changed + return; + } + } catch (e) { + log.error(e); + panel.content = old; + } + + updatePanel(panel); + } + async function evalThis() { if (killable) { await killProcess(); @@ -449,6 +467,16 @@ export function Panel({ {loading ? : } + {panel.type === + 'database' /* TODO: this format should become part of the paneldetails object */ || + (panel.type === 'program' && + (panel as ProgramPanelInfo).program.type === 'sql') ? ( + + + + ) : null}