import { useFlag, useParams } from 'common' import { Check, ChevronDown } from 'lucide-react' import { Button, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger, } from 'ui' import { RowLimitSubMenu } from '../../SQLEditor/UtilityPanel/QuerySourceMenu/RowLimitSubMenu' import { RunAsSubMenu } from '../../SQLEditor/UtilityPanel/QuerySourceMenu/RunAsSubMenu' import { DatabaseParametersSubMenu } from '@/components/interfaces/QuerySources/DatabaseParametersSubMenu' import { LogsCustomRangeDialog } from '@/components/interfaces/QuerySources/LogsCustomRangeDialog' import { LogsTimeRangeSubMenu } from '@/components/interfaces/QuerySources/LogsTimeRangeSubMenu' import { QuerySourceIcon } from '@/components/interfaces/QuerySources/QuerySourceIcon' import { useLogsCustomRange } from '@/components/interfaces/QuerySources/useLogsCustomRange' import UpgradePrompt from '@/components/interfaces/Settings/Logs/UpgradePrompt' import { createDefaultSourceBinding, QUERY_SOURCE_LABELS, QUERY_SOURCES, type QuerySourceBinding, } from '@/data/query-sources/query-source-registry' import { type RoleImpersonationController } from '@/state/role-impersonation-state' export type QuerySourceMenuProps = { disabled?: boolean rowLimit?: number onRowLimitChange?: (val: number) => void roleImpersonationState?: RoleImpersonationController source: QuerySourceBinding onSourceChange: (source: QuerySourceBinding) => void } /** * Source binding and parameter controls shared by standalone Explorer queries * and notebook query-cell toolbars. The consumer owns the binding; this menu * only emits complete, validated-by-construction `QuerySourceBinding` values. * * Selecting a different backend emits that backend's default binding — deciding * what happens to the query body is the consumer's call, since a notebook cell * has SQL to preserve or discard and a fresh draft does not. */ export const QuerySourceMenu = ({ disabled = false, rowLimit = 100, onRowLimitChange, roleImpersonationState, source, onSourceChange, }: QuerySourceMenuProps) => { const { ref } = useParams() const isLogsSourceEnabled = useFlag('sqlEditorLogsSource') const isOtelLogsEnabled = useFlag('otelLegacyLogs') const { isCustomRangeOpen, setIsCustomRangeOpen, showUpgradePrompt, setShowUpgradePrompt, handleApplyCustomRange, } = useLogsCustomRange({ onRangeChange: (time_range) => onSourceChange({ _tag: 'logs', time_range }), }) const availableSources = QUERY_SOURCES.filter( (candidate) => candidate._tag !== 'logs' || (isLogsSourceEnabled && isOtelLogsEnabled) || source._tag === 'logs' ) return ( <> {availableSources.map((candidate) => ( { event.preventDefault() if (candidate._tag !== source._tag) { onSourceChange(createDefaultSourceBinding(candidate._tag)) } }} > {QUERY_SOURCE_LABELS[candidate._tag]} {source._tag === candidate._tag && } ))} {source._tag === 'database' ? ( <> onSourceChange({ _tag: 'database', database_identifier }) } /> {roleImpersonationState !== undefined && ( )} {onRowLimitChange !== undefined && ( onRowLimitChange(Number(val))} /> )} ) : ( onSourceChange({ _tag: 'logs', time_range })} onOpenCustomRange={() => setIsCustomRangeOpen(true)} onShowUpgrade={() => setShowUpgradePrompt(true)} /> )} {source._tag === 'logs' && ( <> )} ) }