-
Notifications
You must be signed in to change notification settings - Fork 18k
fix(SqlLab): South pane visual changes #35601
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 6 commits
50e046e
d972a95
e14a28b
96e697f
f1b312f
232c427
cae826c
2f50822
df2ecf8
fc603f5
9f1542b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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 'src/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,40 @@ 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="Refresh table schema" | ||
|
msyavuz marked this conversation as resolved.
Outdated
|
||
| tooltip={t('Refresh table schema')} | ||
| icon="SyncOutlined" | ||
| iconSize="m" | ||
| onClick={refreshTableMetadata} | ||
| /> | ||
| {tableData.selectStar && ( | ||
| <ActionButton | ||
| label="Copy SELECT statement" | ||
| icon="CopyOutlined" | ||
|
msyavuz marked this conversation as resolved.
Outdated
|
||
| iconSize="m" | ||
| tooltip={t('Copy SELECT statement')} | ||
| onClick={() => copyStatementActionRef.current?.click()} | ||
| /> | ||
| )} | ||
| {tableData.view && ( | ||
| <ActionButton | ||
| label="Show CREATE VIEW statement" | ||
| icon="EyeOutlined" | ||
| iconSize="m" | ||
| tooltip={t('Show CREATE VIEW statement')} | ||
| onClick={() => showViewStatementActionRef.current?.click()} | ||
| /> | ||
| )} | ||
| </Flex> | ||
| ); | ||
|
Comment on lines
+229
to
+259
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unmemoized Component Function
Tell me moreWhat is the issue?The titleActions function is defined inside the component, causing it to be recreated on every render. It should be memoized or moved outside the component since it depends on stable props and callbacks. Why this mattersRecreating the function on every render can lead to unnecessary re-renders of child components and impact performance, especially in larger applications. Suggested change ∙ Feature PreviewUse useMemo to memoize the titleActions function: const titleActions = useMemo(
() => (
<Flex>...
</Flex>
),
[theme, tableData.selectStar, tableData.view, refreshTableMetadata]
);Provide feedback to improve future suggestions💬 Looking for more details? Reply to this comment to chat with Korbit. |
||
|
|
||
| if (isMetadataLoading) { | ||
| return <Skeleton active />; | ||
|
|
@@ -282,7 +292,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 +330,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 +429,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; | ||
| `} | ||
| /> | ||
| ); | ||
| }} | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing null check for contentStyle CSS interpolation
Tell me more
What is the issue?
The contentStyle prop is being interpolated directly into CSS without null/undefined checks, which could cause rendering issues if the prop is not provided.
Why this matters
When contentStyle is undefined or null, the CSS interpolation will render 'undefined' or 'null' as literal text in the CSS, potentially breaking styles or causing console warnings.
Suggested change ∙ Feature Preview
Add a null check before interpolating contentStyle:
Or use optional chaining with nullish coalescing:
Provide feedback to improve future suggestions
💬 Looking for more details? Reply to this comment to chat with Korbit.