import React from 'react'; import { Button, Dropdown, Tabs, Tooltip, type MenuProps } from 'antd'; import { CloseOutlined, EyeInvisibleOutlined, RobotOutlined } from '@ant-design/icons'; import type { EditRowLocator } from '../utils/rowLocator'; import type { QueryResultPaginationState } from '../utils/queryResultPagination'; import { t as defaultTranslate } from '../i18n'; import { useOptionalI18n } from '../i18n/provider'; import DataGrid from './DataGrid'; export type QueryEditorResultSet = { key: string; sql: string; exportSql?: string; sourceStatementIndex?: number; statementResultIndex?: number; rows: any[]; columns: string[]; messages?: string[]; resultType?: 'grid' | 'message'; tableName?: string; pkColumns: string[]; editLocator?: EditRowLocator; readOnly: boolean; showRowNumberColumn?: boolean; truncated?: boolean; pkLoading?: boolean; page?: QueryResultPaginationState & { loading?: boolean }; }; interface QueryEditorResultsPanelProps { resultSets: QueryEditorResultSet[]; activeResultKey: string; loading: boolean; executionError: string; darkMode: boolean; isV2Ui: boolean; currentDb: string; currentConnectionId: string; toggleShortcutLabel: string; onActiveResultKeyChange: (key: string) => void; onHide: () => void; onCloseResult: (key: string) => void; onCloseOtherResultTabs: (key: string) => void; onCloseResultTabsToLeft: (key: string) => void; onCloseResultTabsToRight: (key: string) => void; onCloseAllResultTabs: () => void; onReloadResult: (key: string, sql: string) => void; onResultPageChange: (key: string, page: number, pageSize: number) => void; onDiagnoseExecutionError: () => void; } const isAffectedRowsResult = (result: QueryEditorResultSet): boolean => result.columns.length === 1 && result.columns[0] === 'affectedRows'; const QueryEditorResultsPanel: React.FC = ({ resultSets, activeResultKey, loading, executionError, darkMode, isV2Ui, currentDb, currentConnectionId, toggleShortcutLabel, onActiveResultKeyChange, onHide, onCloseResult, onCloseOtherResultTabs, onCloseResultTabsToLeft, onCloseResultTabsToRight, onCloseAllResultTabs, onReloadResult, onResultPageChange, onDiagnoseExecutionError, }) => { const i18n = useOptionalI18n(); const t = i18n?.t ?? defaultTranslate; const resolvedActiveResultKey = activeResultKey || resultSets[0]?.key || ''; const activeResultSet = resultSets.find((rs) => rs.key === resolvedActiveResultKey) || null; const activeResultUsesDataGrid = Boolean( activeResultSet && activeResultSet.resultType !== 'message' && !isAffectedRowsResult(activeResultSet), ); const hideTooltipTitle = toggleShortcutLabel ? t('query_editor.results_panel.tooltip.hide_with_shortcut', { shortcut: toggleShortcutLabel }) : t('query_editor.results_panel.tooltip.hide'); const buildResultTabMenuItems = (key: string, index: number): MenuProps['items'] => [ { key: 'close-other', label: t('query_editor.results_panel.menu.close_other'), disabled: resultSets.length <= 1, onClick: () => onCloseOtherResultTabs(key), }, { key: 'close-left', label: t('query_editor.results_panel.menu.close_left'), disabled: index <= 0, onClick: () => onCloseResultTabsToLeft(key), }, { key: 'close-right', label: t('query_editor.results_panel.menu.close_right'), disabled: index >= resultSets.length - 1, onClick: () => onCloseResultTabsToRight(key), }, { type: 'divider' }, { key: 'close-all', label: t('query_editor.results_panel.menu.close_all'), disabled: resultSets.length === 0, onClick: onCloseAllResultTabs, }, ]; const hideButton = ( ); const tabsHideButton = ( ); return ( <>
{resultSets.length > 0 ? ( ({ key: rs.key, label: (
{ event.preventDefault(); }} > {rs.resultType === 'message' ? t('query_editor.results_panel.tab.message', { index: idx + 1 }) : t('query_editor.results_panel.tab.result', { index: idx + 1 })} {(() => { if (rs.resultType === 'message') { return i; } if (isAffectedRowsResult(rs)) { return ; } if (!Array.isArray(rs.rows)) { return null; } return {rs.rows.length}; })()} { e.preventDefault(); e.stopPropagation(); onCloseResult(rs.key); }} >
), children: (() => { if (rs.resultType === 'message') { return (
{t('query_editor.results_panel.message.title')}
{(rs.messages || []).join('\n')}
); } if (isAffectedRowsResult(rs)) { const affected = Number(rs.rows[0]?.affectedRows ?? 0); return (
{t('query_editor.result.execution_success')} {t('query_editor.result.affected_rows', { count: affected })} {Array.isArray(rs.messages) && rs.messages.length > 0 && (
{rs.messages.join('\n')}
)}
); } return (
{Array.isArray(rs.messages) && rs.messages.length > 0 && (
{rs.messages.join('\n')}
)} { if (rs.page) { onResultPageChange(rs.key, rs.page.current, rs.page.pageSize); return; } onReloadResult(rs.key, rs.sql); }} pagination={rs.page ? { current: rs.page.current, pageSize: rs.page.pageSize, total: rs.page.total, totalKnown: rs.page.totalKnown, } : undefined} onPageChange={rs.page ? ((page, size) => onResultPageChange(rs.key, page, size)) : undefined} readOnly={rs.readOnly} toolbarExtraActions={resolvedActiveResultKey === rs.key ? toolbarHideButton : null} />
); })(), }))} /> ) : executionError ? ( <>
{t('query_editor.results_panel.panel.title')} {hideButton}
{t('query_editor.result.execution_failed')}
{executionError}
) : ( <>
{t('query_editor.results_panel.panel.title')} {hideButton}
{isV2Ui && (
{t('query_editor.empty_state.title')} {t('query_editor.empty_state.description')}
)}
)}
); }; export default QueryEditorResultsPanel;