fix(SqlLab): South pane visual changes (#35601)

This commit is contained in:
Mehmet Salih Yavuz
2025-10-27 22:07:06 +03:00
committed by GitHub
parent 0bf34d4d6f
commit 6e60a00d69
10 changed files with 266 additions and 107 deletions

View File

@@ -27,6 +27,7 @@ import {
css,
FeatureFlag,
isFeatureEnabled,
useTheme,
} from '@superset-ui/core';
import QueryTable from 'src/SqlLab/components/QueryTable';
import { SqlLabRootState } from 'src/SqlLab/types';
@@ -67,6 +68,7 @@ const QueryHistory = ({
const { id, tabViewId } = useQueryEditor(String(queryEditorId), [
'tabViewId',
]);
const theme = useTheme();
const editorId = tabViewId ?? id;
const [ref, hasReachedBottom] = useInView({ threshold: 0 });
const [pageIndex, setPageIndex] = useState(0);
@@ -118,7 +120,11 @@ const QueryHistory = ({
}
return editorQueries.length > 0 ? (
<>
<div
css={css`
padding-left: ${theme.sizeUnit * 4}px;
`}
>
<QueryTable
columns={[
'state',
@@ -144,7 +150,7 @@ const QueryHistory = ({
/>
)}
{isFetching && <Skeleton active />}
</>
</div>
) : (
<StyledEmptyStateWrapper>
<EmptyState

View File

@@ -148,6 +148,7 @@ const ReturnedRows = styled.div`
const ResultSetControls = styled.div`
display: flex;
justify-content: space-between;
padding-left: ${({ theme }) => theme.sizeUnit * 4}px;
`;
const ResultSetButtons = styled.div`
@@ -669,6 +670,7 @@ const ResultSet = ({
css={css`
display: flex;
justify-content: space-between;
padding-left: ${theme.sizeUnit * 4}px;
align-items: center;
gap: ${GAP}px;
`}
@@ -704,6 +706,7 @@ const ResultSet = ({
<div
css={css`
flex: 1 1 auto;
padding-left: ${theme.sizeUnit * 4}px;
`}
>
<AutoSizer disableWidth>

View File

@@ -185,6 +185,7 @@ const StyledSqlEditor = styled.div`
.queryPane {
padding: ${theme.sizeUnit * 2}px;
padding-left: 0px;
+ .ant-splitter-bar .ant-splitter-bar-dragger {
&::before {
background: transparent;

View File

@@ -138,32 +138,30 @@ test('renders preview', async () => {
// eslint-disable-next-line no-restricted-globals -- TODO: Migrate from describe blocks
describe('table actions', () => {
test('refreshes table metadata when triggered', async () => {
const { getByRole, getByText } = render(<TablePreview {...mockedProps} />, {
const { getByRole } = render(<TablePreview {...mockedProps} />, {
useRedux: true,
initialState,
});
await waitFor(() =>
expect(fetchMock.calls(getTableMetadataEndpoint)).toHaveLength(1),
);
const menuButton = getByRole('button', { name: /Table actions/i });
fireEvent.click(menuButton);
fireEvent.click(getByText('Refresh table schema'));
const refreshButton = getByRole('button', { name: 'sync' });
fireEvent.click(refreshButton);
await waitFor(() =>
expect(fetchMock.calls(getTableMetadataEndpoint)).toHaveLength(2),
);
});
test('shows CREATE VIEW statement', async () => {
const { getByRole, getByText } = render(<TablePreview {...mockedProps} />, {
const { getByRole } = render(<TablePreview {...mockedProps} />, {
useRedux: true,
initialState,
});
await waitFor(() =>
expect(fetchMock.calls(getTableMetadataEndpoint)).toHaveLength(1),
);
const menuButton = getByRole('button', { name: /Table actions/i });
fireEvent.click(menuButton);
fireEvent.click(getByText('Show CREATE VIEW statement'));
const viewButton = getByRole('button', { name: 'eye' });
fireEvent.click(viewButton);
await waitFor(() =>
expect(
screen.queryByRole('dialog', { name: 'CREATE VIEW statement' }),

View File

@@ -25,15 +25,15 @@ import {
getExtensionsRegistry,
styled,
t,
useTheme,
} from '@superset-ui/core';
import {
SafeMarkdown,
Alert,
Breadcrumb,
Button,
Card,
Dropdown,
Skeleton,
Flex,
} from '@superset-ui/core/components';
import AutoSizer from 'react-virtualized-auto-sizer';
import { Icons } from '@superset-ui/core/components/Icons';
@@ -47,7 +47,7 @@ import {
useTableMetadataQuery,
} from 'src/hooks/apiResources';
import { runTablePreviewQuery } from 'src/SqlLab/actions/sqlLab';
import { Menu } from '@superset-ui/core/components/Menu';
import { ActionButton } from '@superset-ui/core/components/ActionButton';
import ResultSet from '../ResultSet';
import ShowSQL from '../ShowSQL';
@@ -68,23 +68,6 @@ const TABS_KEYS = {
INDEXES: 'indexes',
SAMPLE: 'sample',
};
const MENUS = [
{
key: 'refresh-table',
label: t('Refresh table schema'),
icon: <Icons.SyncOutlined iconSize="s" aria-hidden />,
},
{
key: 'copy-select-statement',
label: t('Copy SELECT statement'),
icon: <Icons.CopyOutlined iconSize="s" aria-hidden />,
},
{
key: 'show-create-view-statement',
label: t('Show CREATE VIEW statement'),
icon: <Icons.EyeOutlined iconSize="s" aria-hidden />,
},
];
const TAB_HEADER_HEIGHT = 80;
const PREVIEW_QUERY_LIMIT = 100;
@@ -96,6 +79,8 @@ const Title = styled.div`
column-gap: ${theme.sizeUnit}px;
font-size: ${theme.fontSizeLG}px;
font-weight: ${theme.fontWeightStrong};
padding-top: ${theme.sizeUnit * 2}px;
padding-left: ${theme.sizeUnit * 4}px;
`}
`;
const renderWell = (partitions: TableMetaData['partitions']) => {
@@ -133,6 +118,7 @@ const renderWell = (partitions: TableMetaData['partitions']) => {
const TablePreview: FC<Props> = ({ dbId, catalog, schema, tableName }) => {
const dispatch = useDispatch();
const theme = useTheme();
const [databaseName, backend, disableDataPreview] = useSelector<
SqlLabRootState,
string[]
@@ -240,16 +226,37 @@ const TablePreview: FC<Props> = ({ dbId, catalog, schema, tableName }) => {
],
);
const dropdownMenu = useMemo(() => {
let menus = [...MENUS];
if (!tableData.selectStar) {
menus = menus.filter(({ key }) => key !== 'copy-select-statement');
}
if (!tableData.view) {
menus = menus.filter(({ key }) => key !== 'show-create-view-statement');
}
return menus;
}, [tableData.view, tableData.selectStar]);
const titleActions = () => (
<Flex
align="center"
css={css`
padding-left: ${theme.sizeUnit * 2}px;
`}
>
<ActionButton
label={t('Refresh table schema')}
tooltip={t('Refresh table schema')}
icon={<Icons.SyncOutlined iconSize="m" />}
onClick={refreshTableMetadata}
/>
{tableData.selectStar && (
<ActionButton
label={t('Copy SELECT statement')}
icon={<Icons.CopyOutlined iconSize="m" />}
tooltip={t('Copy SELECT statement')}
onClick={() => copyStatementActionRef.current?.click()}
/>
)}
{tableData.view && (
<ActionButton
label={t('Show CREATE VIEW statement')}
icon={<Icons.EyeOutlined iconSize="m" />}
tooltip={t('Show CREATE VIEW statement')}
onClick={() => showViewStatementActionRef.current?.click()}
/>
)}
</Flex>
);
if (isMetadataLoading) {
return <Skeleton active />;
@@ -282,7 +289,12 @@ const TablePreview: FC<Props> = ({ dbId, catalog, schema, tableName }) => {
flex-direction: column;
`}
>
<Breadcrumb separator=">">
<Breadcrumb
separator=">"
css={css`
padding-left: ${theme.sizeUnit * 4}px;
`}
>
<Breadcrumb.Item>{backend}</Breadcrumb.Item>
<Breadcrumb.Item>{databaseName}</Breadcrumb.Item>
{catalog && <Breadcrumb.Item>{catalog}</Breadcrumb.Item>}
@@ -315,33 +327,7 @@ const TablePreview: FC<Props> = ({ dbId, catalog, schema, tableName }) => {
<Title>
<Icons.InsertRowAboveOutlined iconSize="l" />
{tableName}
<Dropdown
popupRender={() => (
<Menu
onClick={({ key }) => {
if (key === 'refresh-table') {
refreshTableMetadata();
}
if (key === 'copy-select-statement') {
copyStatementActionRef.current?.click();
}
if (key === 'show-create-view-statement') {
showViewStatementActionRef.current?.click();
}
}}
items={dropdownMenu}
/>
)}
trigger={['click']}
>
<Button buttonSize="xsmall" buttonStyle="link">
<Icons.DownSquareOutlined
iconSize="m"
style={{ marginTop: 2, marginLeft: 4 }}
aria-label={t('Table actions')}
/>
</Button>
</Dropdown>
{titleActions()}
</Title>
{isMetadataRefreshing ? (
<Skeleton active />
@@ -440,7 +426,11 @@ const TablePreview: FC<Props> = ({ dbId, catalog, schema, tableName }) => {
css={css`
height: ${height}px;
`}
tabBarStyle={{ paddingLeft: theme.sizeUnit * 4 }}
items={tabItems}
contentStyle={css`
padding-left: ${theme.sizeUnit * 4}px;
`}
/>
);
}}