Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ const useDropdownMenu = (user: User | null) => {
],
[
{
label: 'Logout',
label: 'Sign out',
type: 'button',
icon: LogOut,
onClick: async () => {
Expand Down
2 changes: 1 addition & 1 deletion apps/learn/components/side-navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ function SideNavigation({ internalPaths }: SideNavigationProps) {
],
[
{
label: 'Logout',
label: 'Sign out',
type: 'button',
icon: LogOut,
onClick: async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {
AccordionContent,
AccordionItem,
AccordionTrigger,
Badge,
FormControl,
FormField,
FormInputGroupInput,
Expand Down Expand Up @@ -42,8 +41,8 @@ export const AdvancedSettings = ({
}) => {
const handleNumberChange =
(field: { onChange: (value?: number) => void }) => (e: ChangeEvent<HTMLInputElement>) => {
const val = e.target.value
field.onChange(val === '' ? undefined : Number(val))
const parsed = e.target.valueAsNumber
field.onChange(e.target.value === '' || Number.isNaN(parsed) ? undefined : parsed)
}

return (
Expand All @@ -59,7 +58,6 @@ export const AdvancedSettings = ({
</div>
</AccordionTrigger>
<AccordionContent className="pb-0! pt-3 [&>div]:flex [&>div]:flex-col [&>div]:gap-y-4">
{/* Batch wait time - applies to all destinations */}
<FormField
control={form.control}
name="maxFillMs"
Expand Down Expand Up @@ -161,7 +159,7 @@ export const AdvancedSettings = ({
<SelectTrigger>
{INVALIDATED_SLOT_BEHAVIOR_LABELS[field.value ?? 'error']}
</SelectTrigger>
<SelectContent>
<SelectContent side="bottom" collisionPadding={16}>
<SelectItem value="error" className="[&>span]:top-2.5">
<p>Block startup</p>
<p className="text-foreground-lighter">
Expand All @@ -188,12 +186,7 @@ export const AdvancedSettings = ({
name="connectionPoolSize"
render={({ field }) => (
<FormItemLayout
label={
<div className="flex flex-col gap-y-2">
<span>Connection pool size</span>
<Badge className="w-min">BigQuery only</Badge>
</div>
}
label="Connection pool size"
layout="horizontal"
description="Number of BigQuery connections used for destination writes."
>
Expand Down Expand Up @@ -222,12 +215,7 @@ export const AdvancedSettings = ({
name="maxStalenessMins"
render={({ field }) => (
<FormItemLayout
label={
<div className="flex flex-col gap-y-2">
<span>Maximum staleness</span>
<Badge className="w-min">BigQuery only</Badge>
</div>
}
label="Maximum staleness"
layout="horizontal"
description="Set the maximum age of query results while BigQuery applies ongoing changes, or leave blank for the freshest results."
>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useCallback } from 'react'
import { useMemo } from 'react'

// Replication metadata (publication names, publication tables, source tables,
// columns) and similar destination-form option lists follow one rule:
Expand Down Expand Up @@ -26,12 +26,11 @@ interface UseRefreshOnOpenProps {
}

export const useRefreshOnOpen = ({ isEnabled = true, refetch }: UseRefreshOnOpenProps) => {
const handleOpenChange = useCallback(
(isOpen: boolean) => {
return useMemo(() => {
const handleOpenChange = (isOpen: boolean) => {
if (isOpen && isEnabled) void refetch()
},
[isEnabled, refetch]
)
}

return { handleOpenChange }
return { handleOpenChange }
}, [isEnabled, refetch])
}
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ export const QueryCell = forwardRef<QueryEditorHandle, QueryCellProps>(function
onDisplayChange={handleDisplayChange}
toolbarActions={
<ExplorerToolbarAction
icon={<AlignLeft />}
icon={<AlignLeft size={16} strokeWidth={2} />}
tooltip={
<div className="flex items-center gap-2.5">
<span>Prettify SQL</span>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import { useMemo } from 'react'
import { type ChartConfig as ChartSeriesConfig } from 'ui'
import { cn, type ChartConfig as ChartSeriesConfig } from 'ui'
import { Chart, ChartBar, ChartCard, ChartContent, ChartLine } from 'ui-patterns/Chart'

import { type QueryResult } from '../types'
import NoDataPlaceholder from '@/components/ui/Charts/NoDataPlaceholder'
import { formatLogTick, getCumulativeResults } from '@/components/ui/QueryBlock/QueryBlock.utils'
import {
computeYAxisWidth,
formatLogTick,
formatYAxisTick,
getCumulativeResults,
} from '@/components/ui/QueryBlock/QueryBlock.utils'
import { type ChartConfig } from '@/data/content/notebooks/notebook-schema'

interface QueryResultChartProps {
Expand Down Expand Up @@ -58,6 +63,20 @@ export const QueryResultChart = ({ chart, result }: QueryResultChartProps) => {
)
const resultToRender = cumulative ? cumulativeResults : chartRows

const yAxisWidth = Math.max(
36,
...y_series.map((key) =>
computeYAxisWidth(resultToRender, key, { isLogScale: effectiveScale === 'log' })
)
)

const yAxisProps = {
...(show_labels ? { width: yAxisWidth } : {}),
scale: effectiveScale === 'log' ? 'log' : 'auto',
domain: effectiveScale === 'log' ? ([1, 'auto'] as const) : undefined,
tickFormatter: effectiveScale === 'log' ? formatLogTick : formatYAxisTick,
}

if (!result || (result?.rows && result.rows.length === 0)) {
return (
<NoDataPlaceholder
Expand Down Expand Up @@ -85,7 +104,7 @@ export const QueryResultChart = ({ chart, result }: QueryResultChartProps) => {
return (
<Chart className="flex flex-grow min-h-0">
<ChartCard className="flex flex-grow rounded-none border-0 min-h-0">
<ChartContent className="min-h-0 w-full">
<ChartContent className={cn('min-h-0 h-full w-full', show_labels && 'pl-2 pb-2')}>
{type === 'bar' && (
<ChartBar
isFullHeight
Expand All @@ -96,11 +115,7 @@ export const QueryResultChart = ({ chart, result }: QueryResultChartProps) => {
showXAxis={show_labels}
showYAxis={show_labels}
data={resultToRender}
YAxisProps={{
scale: effectiveScale === 'log' ? 'log' : 'auto',
domain: effectiveScale === 'log' ? [1, 'auto'] : undefined,
tickFormatter: effectiveScale === 'log' ? formatLogTick : undefined,
}}
YAxisProps={yAxisProps}
/>
)}
{type === 'line' && (
Expand All @@ -113,11 +128,7 @@ export const QueryResultChart = ({ chart, result }: QueryResultChartProps) => {
showXAxis={show_labels}
showYAxis={show_labels}
data={resultToRender}
YAxisProps={{
scale: effectiveScale === 'log' ? 'log' : 'auto',
domain: effectiveScale === 'log' ? [1, 'auto'] : undefined,
tickFormatter: effectiveScale === 'log' ? formatLogTick : undefined,
}}
YAxisProps={yAxisProps}
/>
)}
</ChartContent>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { ChevronDown, Play } from 'lucide-react'
import {
Button,
DropdownMenu,
DropdownMenuContent,
DropdownMenuTrigger,
KeyboardShortcut,
} from 'ui'

import { ButtonTooltip } from '@/components/ui/ButtonTooltip'
import { DropdownMenuItemTooltip } from '@/components/ui/DropdownMenuItemTooltip'

interface QueryRunButtonProps {
isExecuting: boolean
disabled: boolean
hasSelection: boolean
onRun: () => void
onRunSelected: () => void
}

export const QueryRunButton = ({
isExecuting,
disabled,
hasSelection,
onRun,
onRunSelected,
}: QueryRunButtonProps) => {
return (
<div className="flex w-fit">
<ButtonTooltip
type="button"
variant="default"
size="tiny"
loading={isExecuting}
disabled={disabled}
icon={<Play size={16} strokeWidth={2} />}
className="rounded-r-none hover:z-10 focus-visible:z-10 focus-visible:rounded-r-sm"
onClick={onRun}
tooltip={{
content: {
side: 'bottom',
text: (
<div className="flex items-center gap-2.5">
<span>Run query</span>
<KeyboardShortcut keys={['Meta', 'Enter']} />
</div>
),
},
}}
>
Run
</ButtonTooltip>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
type="button"
variant="default"
size="tiny"
disabled={disabled}
aria-label="More actions"
className="shrink-0 rounded-l-none px-[4px] py-[5px] -ml-px focus-visible:z-10 focus-visible:rounded-l-sm"
icon={<ChevronDown />}
/>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="w-48">
<DropdownMenuItemTooltip
disabled={!hasSelection}
onClick={onRunSelected}
tooltip={{
content: {
side: 'left',
text: !hasSelection
? 'Select SQL in the editor to run part of the query'
: undefined,
},
}}
>
Run selected
</DropdownMenuItemTooltip>
</DropdownMenuContent>
</DropdownMenu>
</div>
)
}
24 changes: 9 additions & 15 deletions apps/studio/components/interfaces/Explorer/QueryEditor/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useMonaco } from '@monaco-editor/react'
import { acceptUntrustedSql, untrustedSql, type UntrustedSqlFragment } from '@supabase/pg-meta'
import { useFlag } from 'common'
import { CodeSquare, Eye, EyeOff, Play } from 'lucide-react'
import { CodeSquare, Eye, EyeOff } from 'lucide-react'
import type { editor as monacoEditor, Selection } from 'monaco-editor'
import {
forwardRef,
Expand All @@ -12,7 +12,7 @@ import {
useState,
type ReactNode,
} from 'react'
import { Button, cn, KeyboardShortcut } from 'ui'
import { Button, cn } from 'ui'

import { resolveLogTimeRange } from '../../QuerySources/LogTimeRange.utils'
import {
Expand All @@ -32,6 +32,7 @@ import {
import { type QueryDisplay, type QueryResult } from '../types'
import { DisplaySettingsButton } from './DisplaySettingsButton'
import { QueryResultRenderer } from './QueryResultRenderer'
import { QueryRunButton } from './QueryRunButton'
import { QuerySourceMenu } from './QuerySourceMenu'
import { useQueryEditorAi } from './useQueryEditorAi'
import { LegacyLogsRewriteBanner } from '@/components/interfaces/Settings/Logs/LegacyLogsRewriteBanner'
Expand Down Expand Up @@ -437,26 +438,19 @@ export const QueryEditor = forwardRef<QueryEditorHandle, QueryEditorProps>(funct

{toolbarActions}

<ExplorerToolbarAction
icon={<Play size={16} strokeWidth={2} />}
loading={isExecuting}
tooltip={
<div className="flex items-center gap-2.5">
<span>{hasSelection ? 'Run selected query' : 'Run query'}</span>
<KeyboardShortcut keys={['Meta', 'Enter']} />
</div>
}
<QueryRunButton
isExecuting={isExecuting}
disabled={
isBusy || pendingProposal !== null || isRunDisabled || sql.trim().length === 0
}
onClick={() => {
hasSelection={showQuery && hasSelection}
onRun={() => handleRunQuery({ rawSql: sql })}
onRunSelected={() => {
const editorInstance = editorInstanceRef.current
const rawSql = editorInstance ? getEditorValueOrSelection(editorInstance) : sql
handleRunQuery({ rawSql })
}}
>
{hasSelection ? 'Run selected' : 'Run'}
</ExplorerToolbarAction>
/>
</ExplorerToolbarActions>
</ExplorerToolbar>

Expand Down
Loading
Loading