feat: add JSON view mode toggle for query results

Add a Table/JSON segmented toggle to both the query workspace and
table data viewer, allowing users to switch between tabular and
pretty-printed JSON display of results without exporting to a file.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-13 13:05:52 +03:00
parent e02225a3b9
commit a2371f00df
4 changed files with 173 additions and 34 deletions

View File

@@ -13,7 +13,7 @@ import { useCompletionSchema } from "@/hooks/use-completion-schema";
import { useConnections } from "@/hooks/use-connections";
import { useAppStore } from "@/stores/app-store";
import { Button } from "@/components/ui/button";
import { Play, Loader2, Lock, BarChart3, Download, AlignLeft, Bookmark } from "lucide-react";
import { Play, Loader2, Lock, BarChart3, Download, AlignLeft, Bookmark, Table2, Braces } from "lucide-react";
import { format as formatSql } from "sql-formatter";
import { SaveQueryDialog } from "@/components/saved-queries/SaveQueryDialog";
import {
@@ -49,6 +49,7 @@ export function WorkspacePanel({
const [error, setError] = useState<string | null>(null);
const [explainData, setExplainData] = useState<ExplainResult | null>(null);
const [resultView, setResultView] = useState<"results" | "explain">("results");
const [resultViewMode, setResultViewMode] = useState<"table" | "json">("table");
const [saveDialogOpen, setSaveDialogOpen] = useState(false);
const queryMutation = useQueryExecution();
@@ -290,7 +291,7 @@ export function WorkspacePanel({
<ResizableHandle withHandle />
<ResizablePanel id="results" defaultSize="60%" minSize="15%">
{(explainData || result || error) && (
<div className="flex border-b text-xs">
<div className="flex items-center border-b text-xs">
<button
className={`px-3 py-1 font-medium ${
resultView === "results"
@@ -313,6 +314,34 @@ export function WorkspacePanel({
Explain
</button>
)}
{resultView === "results" && result && result.columns.length > 0 && (
<div className="ml-auto mr-2 flex items-center rounded-md border">
<button
className={`flex items-center gap-1 px-2 py-0.5 font-medium ${
resultViewMode === "table"
? "bg-muted text-foreground"
: "text-muted-foreground hover:text-foreground"
}`}
onClick={() => setResultViewMode("table")}
title="Table view"
>
<Table2 className="h-3 w-3" />
Table
</button>
<button
className={`flex items-center gap-1 px-2 py-0.5 font-medium ${
resultViewMode === "json"
? "bg-muted text-foreground"
: "text-muted-foreground hover:text-foreground"
}`}
onClick={() => setResultViewMode("json")}
title="JSON view"
>
<Braces className="h-3 w-3" />
JSON
</button>
</div>
)}
</div>
)}
{resultView === "explain" && explainData ? (
@@ -322,6 +351,7 @@ export function WorkspacePanel({
result={result}
error={error}
isLoading={queryMutation.isPending && resultView === "results"}
viewMode={resultViewMode}
/>
)}
</ResizablePanel>