Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion e2e/questdb
Submodule questdb updated 365 files
148 changes: 101 additions & 47 deletions src/consts/shared-definitions.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/modules/ConsoleEventTracker/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,12 +163,12 @@ export enum ConsoleEvent {
MCP_DUPLICATE_CELL = "mcp.duplicate_cell",
MCP_SET_LAYOUT_MODE = "mcp.set_layout_mode",
MCP_SET_CELL_LAYOUT = "mcp.set_cell_layout",
MCP_SET_CELL_DIMENSIONS = "mcp.set_cell_dimensions",
MCP_SET_CELL_MODE = "mcp.set_cell_mode",
MCP_SET_CELL_CHART_CONFIG = "mcp.set_cell_chart_config",
MCP_SET_CELL_AUTOREFRESH = "mcp.set_cell_autorefresh",
MCP_SET_NOTEBOOK_AUTOREFRESH = "mcp.set_notebook_autorefresh",
MCP_SET_CELL_NAME = "mcp.set_cell_name",
MCP_SET_CELL_VIEW_MAXIMIZED = "mcp.set_cell_view_maximized",
MCP_SET_CELL_MAXIMIZED = "mcp.set_cell_maximized",
MCP_APPLY_NOTEBOOK_STATE = "mcp.apply_notebook_state",
MCP_GET_TABLES = "mcp.get_tables",
Expand Down
30 changes: 30 additions & 0 deletions src/scenes/Editor/Monaco/importTabs.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -775,6 +775,36 @@ describe("sanitizeBuffer", () => {
})

describe("notebookViewState sanitization", () => {
it("imports one preferred view and maps main's legacy boolean", () => {
const input = {
label: "Notebook",
value: "",
position: 0,
notebookViewState: {
cells: [
{ id: "preferred", value: "SELECT 1", preferredView: "editor" },
{ id: "legacy-on", value: "SELECT 2", isViewMaximized: true },
{ id: "legacy-off", value: "SELECT 3", isViewMaximized: false },
{
id: "markdown",
value: "# Title",
type: "markdown",
preferredView: "result",
},
],
},
}

const cells = sanitizeBuffer(input).notebookViewState?.cells
expect(cells?.map((cell) => cell.preferredView)).toEqual([
"editor",
"result",
"editor_result",
undefined,
])
expect(cells?.every((cell) => !("isViewMaximized" in cell))).toBe(true)
})

it("whitelists cell fields, reindexes positions, drops session state", () => {
const input = {
label: "Notebook",
Expand Down
15 changes: 13 additions & 2 deletions src/scenes/Editor/Monaco/importTabs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -271,8 +271,19 @@ const sanitizeNotebookCell = (
const chartConfig = sanitizeChartConfig(item.chartConfig)
if (chartConfig) cell.chartConfig = chartConfig
if (isAutoRefresh(item.autoRefresh)) cell.autoRefresh = item.autoRefresh
if (typeof item.isViewMaximized === "boolean")
cell.isViewMaximized = item.isViewMaximized
if (item.type !== "markdown") {
if (
item.preferredView === "editor" ||
item.preferredView === "result" ||
item.preferredView === "editor_result"
) {
cell.preferredView = item.preferredView
} else if (item.isViewMaximized === true) {
cell.preferredView = "result"
} else {
cell.preferredView = "editor_result"
}
}
if (typeof item.topHeight === "number") cell.topHeight = item.topHeight
if (typeof item.bottomHeight === "number")
cell.bottomHeight = item.bottomHeight
Expand Down
15 changes: 8 additions & 7 deletions src/scenes/Editor/Notebook/NotebookProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { unstable_batchedUpdates } from "react-dom"
import { useEditor } from "../../../providers/EditorProvider"
import { QuestContext } from "../../../providers/QuestProvider"
import type {
AgentCellView,
CellResult,
NotebookCell,
NotebookVariable,
Expand All @@ -35,7 +36,7 @@ import {
registerController,
setCellMaximizedTransition,
setCellModeTransition,
setCellViewMaximizedTransition,
setCellPreferredViewTransition,
unregisterController,
type NotebookControllerActions,
type NotebookTransitionResult,
Expand Down Expand Up @@ -128,7 +129,7 @@ export type NotebookActions = {
setCellRefresh: (cellId: string, value: AutoRefresh | undefined) => void
resetAutoRefreshOverrides: () => void
refreshAllCells: () => { refreshed: number; skippedWrites: number }
setCellViewMaximized: (cellId: string, value: boolean) => void
setCellPreferredView: (cellId: string, view: AgentCellView) => void
setFocusedCell: (cellId: string | null) => void
setMaximizedCellId: (cellId: string | null) => void
getCellsSnapshot: () => NotebookCell[]
Expand Down Expand Up @@ -158,7 +159,7 @@ const NOOP_ACTIONS: NotebookActions = {
setCellRefresh: () => undefined,
resetAutoRefreshOverrides: () => undefined,
refreshAllCells: () => ({ refreshed: 0, skippedWrites: 0 }),
setCellViewMaximized: () => undefined,
setCellPreferredView: () => undefined,
setFocusedCell: () => undefined,
setMaximizedCellId: () => undefined,
getCellsSnapshot: () => [],
Expand Down Expand Up @@ -767,11 +768,11 @@ export const NotebookProvider: React.FC<{
[applyTransition, bufferId],
)

const setCellViewMaximized = useCallback(
(cellId: string, value: boolean) =>
const setCellPreferredView = useCallback(
(cellId: string, view: AgentCellView) =>
silently(() =>
applyTransition((parts) =>
setCellViewMaximizedTransition(parts, bufferId, cellId, value),
setCellPreferredViewTransition(parts, bufferId, cellId, view),
),
),
[applyTransition, bufferId],
Expand Down Expand Up @@ -828,7 +829,7 @@ export const NotebookProvider: React.FC<{
setCellRefresh: store.setCellRefresh,
resetAutoRefreshOverrides,
refreshAllCells: () => cellRefreshEngine.refreshAll(),
setCellViewMaximized,
setCellPreferredView,
setFocusedCell,
setMaximizedCellId,
getCellsSnapshot: () => store.cellsRef.current.slice(),
Expand Down
64 changes: 37 additions & 27 deletions src/scenes/Editor/Notebook/cells/Cell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,12 @@ import {
CELL_EDITOR_PADDING,
isDoubleView,
isExpectingResult,
MIN_BOTTOM_HEIGHT_PX,
minBottomHeightFor,
resolveAutoRefresh,
resolveCellPaneLayout,
resolveCellView,
} from "../notebookUtils"
import type { CellToolbarTier } from "../notebookUtils"
import {
useCellContentMode,
useCellVirtualizationEngine,
Expand All @@ -51,6 +53,7 @@ import {
useCellResizeOrchestration,
} from "./useCellResizeOrchestration"
import { CellBottomContent } from "./CellBottomContent"
import { publishLiveCellPresentation } from "../notebookPresentationStore"
import { getMonacoThemeName } from "../../../../utils/monacoInit"

const EditorContainer = styled.div<{ $spotlight: boolean }>`
Expand Down Expand Up @@ -118,6 +121,7 @@ type Props = {
isFocused: boolean
isMaximized: boolean
isRunning: boolean
toolbarTierOverride?: CellToolbarTier
}

const CellInner: React.FC<Props> = ({
Expand All @@ -129,6 +133,7 @@ const CellInner: React.FC<Props> = ({
isFocused,
isMaximized,
isRunning,
toolbarTierOverride,
}) => {
const { setCellChartConfig, clearCellResult, updateCell, setFocusedCell } =
useNotebookActions()
Expand All @@ -147,7 +152,8 @@ const CellInner: React.FC<Props> = ({
const resultRef = useRef<HTMLDivElement | null>(null)
const headerRef = useRef<HTMLDivElement | null>(null)

const toolbarTier = useCellToolbarTier(headerRef, isMaximized)
const observedToolbarTier = useCellToolbarTier(headerRef, isMaximized)
const toolbarTier = toolbarTierOverride ?? observedToolbarTier
const { loading: chartLoading, refreshing: chartRefreshing } =
useChartLoading(cell)
const chartZoomed = useChartZoomed(cell.id)
Expand All @@ -174,14 +180,22 @@ const CellInner: React.FC<Props> = ({
// in the grid item's height (both go through computeCellHeights).
const expectingResult = isExpectingResult(cell, resultStatus)
const doubleView = isDoubleView(cell) || expectingResult
// Compact can't split — one full-height pane: the result fills the cell by
// default, "View SQL" (isViewMaximized === false) shows the editor instead.
const isCompactTier = toolbarTier === "compact"
const isViewMaximized = isCompactTier
? doubleView && cell.isViewMaximized !== false
: doubleView && !!cell.isViewMaximized
const showBottomSlot = isViewMaximized || (doubleView && !isCompactTier)
const isSplit = doubleView && !isViewMaximized && !isCompactTier
const paneLayout = resolveCellPaneLayout(cell, expectingResult, isCompactTier)

useEffect(
() =>
publishLiveCellPresentation(bufferIdForEvents, cell.id, {
compact: isCompactTier,
paneLayout,
expectingResult,
}),
[bufferIdForEvents, cell.id, expectingResult, isCompactTier, paneLayout],
)

const resultOnly = paneLayout === "result"
const showBottomSlot = paneLayout !== "editor"
const isSplit = paneLayout === "split"
const runActive = !isDrawMode && doubleView
const view = resolveCellView(cell)
const canRun = !!stripSQLComments(cell.value).trim()
Expand Down Expand Up @@ -234,7 +248,7 @@ const CellInner: React.FC<Props> = ({

const { editorRef, monacoRef, handleEditorMount } = useMonacoCellEditor({
cellId: cell.id,
editorMounted: !isViewMaximized && contentMode === "full",
editorMounted: !resultOnly && contentMode === "full",
editorViewState: cell.editorViewState,
quest,
onFocus: useCallback(
Expand Down Expand Up @@ -425,6 +439,7 @@ const CellInner: React.FC<Props> = ({
isRunning={isRunning}
headerRef={headerRef}
toolbarTier={toolbarTier}
paneLayout={paneLayout}
chartZoomed={chartZoomed}
left={
<CellNameLabel
Expand Down Expand Up @@ -468,7 +483,7 @@ const CellInner: React.FC<Props> = ({
view={view}
cellAutoRefresh={cell.autoRefresh}
autoRefreshDefault={autoRefreshDefault}
isViewMaximized={isViewMaximized}
paneLayout={paneLayout}
isRunning={isRunning}
isGridLoading={isGridLoading}
isChartLoading={chartLoading}
Expand All @@ -480,7 +495,7 @@ const CellInner: React.FC<Props> = ({
<CellViewToggle
cellId={cell.id}
view={view}
isViewMaximized={isViewMaximized}
paneLayout={paneLayout}
isGridLoading={isGridLoading}
isChartLoading={chartLoading}
isRunning={isRunning}
Expand All @@ -490,7 +505,7 @@ const CellInner: React.FC<Props> = ({
)
}
/>
{!isViewMaximized && (
{!resultOnly && (
<EditorContainer
ref={editorContainerRef}
$spotlight={isMaximized}
Expand Down Expand Up @@ -561,17 +576,17 @@ const CellInner: React.FC<Props> = ({
doubleView={doubleView}
/>
)}
{/* Bottom slot: result grid OR chart, OR chart filling the whole cell
when expanded. */}
{/* Bottom slot: result grid OR chart. Hiding the editor preserves this
pane's own height instead of borrowing the editor allocation. */}
{showBottomSlot && (
<BottomSlot
ref={resultRef}
$spotlight={isMaximized}
style={
isViewMaximized
resultOnly
? isMaximized
? { flex: 1 }
: { height: topHeight + bottomHeight }
: { height: bottomHeight }
: isMaximized
? { flex: 1 - spotlightEditorRatio }
: { height: bottomHeight }
Expand All @@ -598,32 +613,27 @@ const CellInner: React.FC<Props> = ({
<ResizeHandle
overlay
targetRef={
isViewMaximized || showBottomSlot ? resultRef : editorContainerRef
resultOnly || showBottomSlot ? resultRef : editorContainerRef
}
onResize={
isViewMaximized
resultOnly
? maximizedChartResizeLive
: showBottomSlot
? bottomResize.resizeLive
: topResize.resizeLive
}
onResizeEnd={(height) => {
void trackEvent(ConsoleEvent.NOTEBOOK_CELL_RESIZE, { region: "s" })
if (isViewMaximized) maximizedChartResizeEnd(height)
if (resultOnly) maximizedChartResizeEnd(height)
else if (showBottomSlot) bottomResize.resizeEnd(height)
else topResize.resizeEnd(height)
}}
onDoubleClick={() => {
void trackEvent(ConsoleEvent.NOTEBOOK_CELL_SIZE_RESET)
if (isViewMaximized) resetToDefaults()
else resetBottomArea()
resetBottomArea()
}}
minHeight={
isViewMaximized
? MIN_EDITOR_HEIGHT + MIN_BOTTOM_HEIGHT_PX
: showBottomSlot
? MIN_BOTTOM_HEIGHT_PX
: undefined
resultOnly || showBottomSlot ? minBottomHeightFor(cell) : undefined
}
/>
) : null
Expand Down
5 changes: 4 additions & 1 deletion src/scenes/Editor/Notebook/cells/CellDragHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import styled from "styled-components"
import { CellToolbar } from "./CellToolbar"
import { eventBus } from "../../../../modules/EventBus"
import { EventType } from "../../../../modules/EventBus/types"
import type { CellToolbarTier } from "../notebookUtils"
import type { CellPaneLayout, CellToolbarTier } from "../notebookUtils"
import type { AutoRefresh, NotebookCell } from "../../../../store/notebook"
import { editorCardHeaderStyles } from "../../sharedStyles"

Expand Down Expand Up @@ -62,6 +62,7 @@ type Props = {
// cells omit it (no width-driven tiering).
headerRef?: RefObject<HTMLDivElement>
toolbarTier?: CellToolbarTier
paneLayout?: CellPaneLayout
chartZoomed?: boolean
}

Expand All @@ -78,6 +79,7 @@ export const CellDragHeader: React.FC<Props> = ({
right,
headerRef,
toolbarTier,
paneLayout,
chartZoomed,
}) => (
<HeaderBar
Expand Down Expand Up @@ -111,6 +113,7 @@ export const CellDragHeader: React.FC<Props> = ({
isRunning={isRunning}
inline
toolbarTier={toolbarTier}
paneLayout={paneLayout}
chartZoomed={chartZoomed}
/>
</RightSide>
Expand Down
Loading
Loading