From 3950cf065e54aee6846db53cd5941317d540f232 Mon Sep 17 00:00:00 2001
From: Damian Pendrak
Date: Mon, 7 Apr 2025 23:35:39 +0200
Subject: [PATCH] refactor(Collapse): Upgrade Collapse to Antd5 (#32959)
Co-authored-by: Maxime Beauchemin
---
.../e2e/explore/advanced_analytics.test.ts | 4 +-
.../cypress/support/directories.ts | 22 +-
.../ColumnElement/ColumnElement.test.tsx | 18 +-
.../SqlLab/components/ColumnElement/index.tsx | 9 +-
.../components/SqlEditorLeftBar/index.tsx | 71 +-
.../TableElement/TableElement.test.tsx | 1 +
.../SqlLab/components/TableElement/index.tsx | 243 ++--
.../components/Collapse/Collapse.stories.tsx | 39 +-
.../src/components/Collapse/Collapse.test.tsx | 46 +-
.../src/components/Collapse/index.tsx | 107 +-
.../ErrorMessage/MarshmallowErrorMessage.tsx | 41 +-
.../src/components/IconTooltip/index.tsx | 20 +-
.../src/components/Icons/AntdEnhanced.tsx | 2 +
superset-frontend/src/components/index.ts | 1 -
.../CrossFilters/VerticalCollapse.tsx | 65 +-
.../FilterControls/FilterControls.tsx | 1 -
.../FiltersDropdownContent/index.tsx | 1 -
.../FiltersOutOfScopeCollapsible/index.tsx | 81 +-
.../FiltersConfigForm/FiltersConfigForm.tsx | 831 ++++++-------
.../FiltersConfigModal.test.tsx | 4 -
.../components/ControlPanelsContainer.tsx | 65 +-
.../components/DatasourcePanel/index.tsx | 3 -
.../components/ExploreChartPanel/index.jsx | 16 -
.../controls/FixedOrMetricControl/index.jsx | 147 +--
.../VizTypeControl/VizTypeGallery.tsx | 59 +-
.../features/alerts/AlertReportModal.test.tsx | 2 +-
.../src/features/alerts/AlertReportModal.tsx | 950 ++++++++-------
.../alerts/components/StyledPanel.tsx | 77 --
.../OAuth2ClientField.tsx | 108 +-
.../databases/DatabaseModal/ExtraOptions.tsx | 1073 +++++++++--------
.../databases/DatabaseModal/index.test.tsx | 54 +-
.../databases/DatabaseModal/styles.ts | 26 -
.../databases/UploadDataModel/index.tsx | 890 +++++++-------
.../databases/UploadDataModel/styles.ts | 24 -
.../src/pages/Home/Home.test.tsx | 2 +-
superset-frontend/src/pages/Home/index.tsx | 156 +--
36 files changed, 2490 insertions(+), 2769 deletions(-)
delete mode 100644 superset-frontend/src/features/alerts/components/StyledPanel.tsx
diff --git a/superset-frontend/cypress-base/cypress/e2e/explore/advanced_analytics.test.ts b/superset-frontend/cypress-base/cypress/e2e/explore/advanced_analytics.test.ts
index 2d50460fd79..d7c3aff4e10 100644
--- a/superset-frontend/cypress-base/cypress/e2e/explore/advanced_analytics.test.ts
+++ b/superset-frontend/cypress-base/cypress/e2e/explore/advanced_analytics.test.ts
@@ -29,7 +29,7 @@ describe('Advanced analytics', () => {
cy.visitChartByName('Num Births Trend');
cy.verifySliceSuccess({ waitAlias: '@v1Data' });
- cy.get('.ant-collapse-header')
+ cy.get('.antd5-collapse-header')
.contains('Advanced analytics')
.click({ force: true });
@@ -52,7 +52,7 @@ describe('Advanced analytics', () => {
waitAlias: '@v1Data',
});
cy.wait('@getExplore');
- cy.get('.ant-collapse-header')
+ cy.get('.antd5-collapse-header')
.contains('Advanced analytics')
.click({ force: true });
cy.get('[data-test=time_compare]')
diff --git a/superset-frontend/cypress-base/cypress/support/directories.ts b/superset-frontend/cypress-base/cypress/support/directories.ts
index 3669109bbc4..b1b4a63babc 100644
--- a/superset-frontend/cypress-base/cypress/support/directories.ts
+++ b/superset-frontend/cypress-base/cypress/support/directories.ts
@@ -52,16 +52,16 @@ export const securityAccess = {
};
export const homePage = {
homeSection: {
- sectionArea: '.ant-collapse-content-box',
+ sectionArea: '.antd5-collapse-content-box',
sectionElement: '.antd5-card-meta-title',
},
sections: {
- expandedSection: '.ant-collapse-item-active',
+ expandedSection: '.antd5-collapse-item-active',
expandedSectionHeader: '[aria-expanded="true"]',
- collapseExpandButton: '.ant-collapse-arrow',
- collapsedSection: '[class="ant-collapse-item"]',
+ collapseExpandButton: '.antd5-collapse-arrow',
+ collapsedSection: '[class="antd5-collapse-item"]',
collapsedSectionHeader: '[aria-expanded="false"]',
- section: '[class^="ant-collapse-item"]',
+ section: '[class^="antd5-collapse-item"]',
sectionsMenuContainer: "[role='navigation']",
sectionsMenuItem: "[role='menuitem']",
card: dataTestLocator('styled-card'),
@@ -112,7 +112,7 @@ export const databasesPage = {
advancedTab: '#rc-tabs-0-tab-2',
activeTab: '.antd5-tabs-tab-active',
securitySubMenu:
- ':nth-child(3) > .ant-collapse-header > .anticon > svg > path',
+ ':nth-child(3) > .antd5-collapse-header > .anticon > svg > path',
aceTextInput: '.ace_text-input',
aceContent: '.ace_content',
connectButton: '.css-16i3wh7',
@@ -359,14 +359,14 @@ export const nativeFilters = {
removeFilter: '[aria-label="remove"]',
silentLoading: '.loading inline-centered css-101mkpk',
filterConfigurationSections: {
- sectionHeader: '.ant-collapse-header',
+ sectionHeader: '.antd5-collapse-header',
displayedSection: 'div[style="height: 100%; overflow-y: auto;"]',
- collapseExpandButton: '.ant-collapse-arrow',
+ collapseExpandButton: '.antd5-collapse-arrow',
checkedCheckbox: '.ant-checkbox-wrapper-checked',
infoTooltip: '[aria-label="Show info tooltip"]',
parentFilterInput: dataTestLocator('parent-filter-input'),
filterPlaceholder: '.ant-select-selection-placeholder',
- collapsedSectionContainer: '[class="ant-collapse-content-box"]',
+ collapsedSectionContainer: '[class="antd5-collapse-content-box"]',
},
filtersList: {
list: '.antd5-tabs-nav-list',
@@ -460,7 +460,7 @@ export const dashboardListView = {
};
export const exploreView = {
openDatasourceMenu: dataTestLocator('open-datasource-tab'),
- sectionsHeader: '.ant-collapse-header',
+ sectionsHeader: '.antd5-collapse-header',
datasourceMenuThreeDots: dataTestLocator('datasource-menu-trigger'),
threeDotsMenuDropdown: {
editDataset: dataTestLocator('edit-dataset'),
@@ -495,7 +495,7 @@ export const exploreView = {
},
controlPanel: {
panel: dataTestLocator('control-tabs'),
- categoryArea: '.ant-collapse-content-box',
+ categoryArea: '.antd5-collapse-content-box',
dragField: dataTestLocator('datasource'),
metricsField: dataTestLocator('metrics'),
optionField: dataTestLocator('option-label'),
diff --git a/superset-frontend/src/SqlLab/components/ColumnElement/ColumnElement.test.tsx b/superset-frontend/src/SqlLab/components/ColumnElement/ColumnElement.test.tsx
index 09105bb5fa2..437be27504a 100644
--- a/superset-frontend/src/SqlLab/components/ColumnElement/ColumnElement.test.tsx
+++ b/superset-frontend/src/SqlLab/components/ColumnElement/ColumnElement.test.tsx
@@ -32,23 +32,23 @@ describe('ColumnElement', () => {
it('renders a proper primary key', () => {
const { container } = render( );
expect(container.querySelector('i.fa-key')).toBeInTheDocument();
- expect(container.querySelector('.col-name')?.firstChild).toHaveTextContent(
- 'id',
- );
+ expect(
+ container.querySelector('[data-test="col-name"]')?.firstChild,
+ ).toHaveTextContent('id');
});
it('renders a multi-key column', () => {
const { container } = render( );
expect(container.querySelector('i.fa-link')).toBeInTheDocument();
expect(container.querySelector('i.fa-bookmark')).toBeInTheDocument();
- expect(container.querySelector('.col-name')?.firstChild).toHaveTextContent(
- 'first_name',
- );
+ expect(
+ container.querySelector('[data-test="col-name"]')?.firstChild,
+ ).toHaveTextContent('first_name');
});
it('renders a column with no keys', () => {
const { container } = render( );
expect(container.querySelector('i')).not.toBeInTheDocument();
- expect(container.querySelector('.col-name')?.firstChild).toHaveTextContent(
- 'last_name',
- );
+ expect(
+ container.querySelector('[data-test="col-name"]')?.firstChild,
+ ).toHaveTextContent('last_name');
});
});
diff --git a/superset-frontend/src/SqlLab/components/ColumnElement/index.tsx b/superset-frontend/src/SqlLab/components/ColumnElement/index.tsx
index 3cc9d14f552..d918af42812 100644
--- a/superset-frontend/src/SqlLab/components/ColumnElement/index.tsx
+++ b/superset-frontend/src/SqlLab/components/ColumnElement/index.tsx
@@ -20,6 +20,7 @@ import { ReactNode } from 'react';
import { ClassNames } from '@emotion/react';
import { styled, useTheme, t } from '@superset-ui/core';
import { Tooltip } from 'src/components/Tooltip';
+import { Flex } from 'src/components/Flex';
const StyledTooltip = (props: any) => {
const theme = useTheme();
@@ -104,15 +105,15 @@ const ColumnElement = ({ column }: ColumnElementProps) => {
));
}
return (
-
-
+
+
{columnName}
{icons}
-
+
{column.type}
-
+
);
};
diff --git a/superset-frontend/src/SqlLab/components/SqlEditorLeftBar/index.tsx b/superset-frontend/src/SqlLab/components/SqlEditorLeftBar/index.tsx
index b6d00e3a67d..897e5de4290 100644
--- a/superset-frontend/src/SqlLab/components/SqlEditorLeftBar/index.tsx
+++ b/superset-frontend/src/SqlLab/components/SqlEditorLeftBar/index.tsx
@@ -34,11 +34,8 @@ import {
resetState,
} from 'src/SqlLab/actions/sqlLab';
import Button from 'src/components/Button';
-import { t, styled, css, SupersetTheme } from '@superset-ui/core';
-import Collapse from 'src/components/Collapse';
-import { Icons } from 'src/components/Icons';
+import { t, styled, css } from '@superset-ui/core';
import { TableSelectorMultiple } from 'src/components/TableSelector';
-import { IconTooltip } from 'src/components/IconTooltip';
import useQueryEditor from 'src/SqlLab/hooks/useQueryEditor';
import type { DatabaseObject } from 'src/components/DatabaseSelector';
import { EmptyState } from 'src/components/EmptyState';
@@ -60,29 +57,6 @@ const StyledScrollbarContainer = styled.div`
overflow: auto;
`;
-const collapseStyles = (theme: SupersetTheme) => css`
- .ant-collapse-item {
- margin-bottom: ${theme.sizeUnit * 3}px;
- }
- .ant-collapse-header {
- padding: 0px !important;
- display: flex;
- align-items: center;
- }
- .ant-collapse-content-box {
- padding: 0px ${theme.sizeUnit * 4}px 0px 0px !important;
- }
- .ant-collapse-arrow {
- padding: 0 !important;
- bottom: ${theme.sizeUnit}px !important;
- right: ${theme.sizeUnit * 4}px !important;
- color: ${theme.colorPrimaryText} !important;
- &:hover {
- color: ${theme.colorPrimaryTextHover} !important;
- }
- }
-`;
-
const LeftBarStyles = styled.div`
${({ theme }) => css`
height: 100%;
@@ -194,25 +168,6 @@ const SqlEditorLeftBar = ({
});
};
- const renderExpandIconWithTooltip = ({ isActive }: { isActive: boolean }) => (
-
-
-
- );
-
const shouldShowReset = window.location.search === '?reset=1';
const tableMetaDataHeight = height - 130; // 130 is the height of the selects above
@@ -276,20 +231,16 @@ const SqlEditorLeftBar = ({
height: ${tableMetaDataHeight}px;
`}
>
-
expanded)
- .map(({ id }) => id)}
- css={collapseStyles}
- expandIconPosition="right"
- ghost
- onChange={onToggleTable}
- expandIcon={renderExpandIconWithTooltip}
- >
- {tables.map(table => (
-
- ))}
-
+ {tables.map(table => (
+
expanded)
+ .map(({ id }) => id)}
+ onChange={onToggleTable}
+ />
+ ))}
{shouldShowReset && (
diff --git a/superset-frontend/src/SqlLab/components/TableElement/TableElement.test.tsx b/superset-frontend/src/SqlLab/components/TableElement/TableElement.test.tsx
index b9cd94e5663..94fedeae9b6 100644
--- a/superset-frontend/src/SqlLab/components/TableElement/TableElement.test.tsx
+++ b/superset-frontend/src/SqlLab/components/TableElement/TableElement.test.tsx
@@ -76,6 +76,7 @@ const mockedProps = {
...table,
initialized: true,
},
+ activeKey: [table.id],
};
test('renders', () => {
diff --git a/superset-frontend/src/SqlLab/components/TableElement/index.tsx b/superset-frontend/src/SqlLab/components/TableElement/index.tsx
index 061d67dcc76..b9a80a8bbd4 100644
--- a/superset-frontend/src/SqlLab/components/TableElement/index.tsx
+++ b/superset-frontend/src/SqlLab/components/TableElement/index.tsx
@@ -21,10 +21,10 @@
import { useState, useRef, useEffect } from 'react';
import { useDispatch } from 'react-redux';
import type { Table } from 'src/SqlLab/types';
-import Collapse from 'src/components/Collapse';
+import Collapse, { CollapseProps } from 'src/components/Collapse';
import Card from 'src/components/Card';
import ButtonGroup from 'src/components/ButtonGroup';
-import { css, t, styled, useTheme } from '@superset-ui/core';
+import { t, styled, useTheme } from '@superset-ui/core';
import { debounce } from 'lodash';
import {
@@ -46,6 +46,8 @@ import Loading from 'src/components/Loading';
import useEffectEvent from 'src/hooks/useEffectEvent';
import { ActionType } from 'src/types/Action';
import { Icons } from 'src/components/Icons';
+import { Flex } from 'src/components/Flex';
+import { Space } from 'src/components/Space';
import ColumnElement, { ColumnKeyTypeType } from '../ColumnElement';
import ShowSQL from '../ShowSQL';
@@ -55,15 +57,11 @@ export interface Column {
type: string;
}
-export interface TableElementProps {
+export interface TableElementProps extends CollapseProps {
table: Table;
}
const StyledSpan = styled.span`
- color: ${({ theme }) => theme.colorPrimaryText};
- &:hover {
- color: ${({ theme }) => theme.colorPrimaryTextHover};
- }
cursor: pointer;
`;
@@ -72,41 +70,8 @@ const Fade = styled.div`
opacity: ${(props: { hovered: boolean }) => (props.hovered ? 1 : 0)};
`;
-const StyledCollapsePanel = styled(Collapse.Panel)`
- ${({ theme }) => css`
- & {
- .ws-el-controls {
- margin-right: ${-theme.sizeUnit}px;
- display: flex;
- }
-
- .header-container {
- display: flex;
- flex: 1;
- align-items: center;
- width: 100%;
-
- .table-name {
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- font-size: ${theme.fontSizeLG}px;
- flex: 1;
- }
-
- .header-right-side {
- margin-left: auto;
- display: flex;
- align-items: center;
- margin-right: ${theme.sizeUnit * 8}px;
- }
- }
- }
- `}
-`;
-
const TableElement = ({ table, ...props }: TableElementProps) => {
- const { dbId, catalog, schema, name, expanded } = table;
+ const { dbId, catalog, schema, name, expanded, id } = table;
const theme = useTheme();
const dispatch = useDispatch();
const {
@@ -273,77 +238,85 @@ const TableElement = ({ table, ...props }: TableElementProps) => {
);
}
return (
-
-
-
-
- {keyLink}
-
- {tableData.selectStar && (
-
-
-
- }
- text={tableData.selectStar}
- shouldShowText={false}
- />
+
+ {isMetadataFetching || isExtraMetadataLoading ? (
+
+ ) : (
+ e.stopPropagation()}
+ >
+
+
+
+
+
+ {keyLink}
+
+
+
+ {tableData.selectStar && (
+
+
+
+ }
+ text={tableData.selectStar}
+ shouldShowText={false}
+ />
+ )}
+ {tableData.view && (
+
+ )}
+
+
+
+
+
+
)}
- {tableData.view && (
-
- )}
-
-
-
-
+
);
};
@@ -358,8 +331,6 @@ const TableElement = ({ table, ...props }: TableElementProps) => {
setHover(true)}
- onMouseLeave={() => setHover(false)}
>
{
{name}
-
-
- {isMetadataFetching || isExtraMetadataLoading ? (
-
- ) : (
- e.stopPropagation()}
- >
- {renderControls()}
-
- )}
-
);
};
@@ -407,12 +364,7 @@ const TableElement = ({ table, ...props }: TableElementProps) => {
}
const metadata = (
- setHover(true)}
- onMouseLeave={() => setHover(false)}
- css={{ paddingTop: 6 }}
- >
+
{renderWell()}
{cols?.map(col =>
)}
@@ -423,15 +375,22 @@ const TableElement = ({ table, ...props }: TableElementProps) => {
};
return (
-
- {renderBody()}
-
+
setHover(true),
+ onMouseLeave: () => setHover(false),
+ },
+ ]}
+ />
);
};
diff --git a/superset-frontend/src/components/Collapse/Collapse.stories.tsx b/superset-frontend/src/components/Collapse/Collapse.stories.tsx
index f20c0349dc7..eb6c57ba459 100644
--- a/superset-frontend/src/components/Collapse/Collapse.stories.tsx
+++ b/superset-frontend/src/components/Collapse/Collapse.stories.tsx
@@ -16,7 +16,6 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { useTheme } from '@superset-ui/core';
import Collapse, { CollapseProps } from '.';
export default {
@@ -24,30 +23,30 @@ export default {
component: Collapse,
};
-export const InteractiveCollapse = (args: CollapseProps) => {
- const theme = useTheme();
- return (
-
-
- Content 1
-
-
- Content 2
-
-
- );
-};
+export const InteractiveCollapse = (args: CollapseProps) => (
+
+);
InteractiveCollapse.args = {
ghost: false,
bordered: true,
accordion: false,
+ animateArrows: false,
};
InteractiveCollapse.argTypes = {
diff --git a/superset-frontend/src/components/Collapse/Collapse.test.tsx b/superset-frontend/src/components/Collapse/Collapse.test.tsx
index 69eca8344e0..80f0687ae44 100644
--- a/superset-frontend/src/components/Collapse/Collapse.test.tsx
+++ b/superset-frontend/src/components/Collapse/Collapse.test.tsx
@@ -18,19 +18,25 @@
*/
import { render, screen } from 'spec/helpers/testing-library';
import userEvent from '@testing-library/user-event';
-import { supersetTheme } from '@superset-ui/core';
import Collapse, { CollapseProps } from '.';
function renderCollapse(props?: CollapseProps) {
return render(
-
-
- Content 1
-
-
- Content 2
-
- ,
+ ,
);
}
@@ -81,25 +87,3 @@ test('collapses on click', () => {
);
expect(screen.queryByText('Content 2')).not.toBeInTheDocument();
});
-
-test('renders with custom properties', () => {
- renderCollapse({
- light: true,
- bigger: true,
- bold: true,
- animateArrows: true,
- });
-
- const header = document.getElementsByClassName('ant-collapse-header')[0];
- const arrow =
- document.getElementsByClassName('ant-collapse-arrow')[0].children[0];
-
- const headerStyle = window.getComputedStyle(header);
- const arrowStyle = window.getComputedStyle(arrow);
-
- expect(headerStyle.fontWeight).toBe(
- supersetTheme.fontWeightStrong.toString(),
- );
- expect(headerStyle.fontSize).toBe(`${supersetTheme.sizeUnit * 4}px`);
- expect(arrowStyle.transition).toBe('transform 0.24s');
-});
diff --git a/superset-frontend/src/components/Collapse/index.tsx b/superset-frontend/src/components/Collapse/index.tsx
index ad34c0c67b6..c8e2b16b0e6 100644
--- a/superset-frontend/src/components/Collapse/index.tsx
+++ b/superset-frontend/src/components/Collapse/index.tsx
@@ -17,86 +17,67 @@
* under the License.
*/
import { styled } from '@superset-ui/core';
-// eslint-disable-next-line no-restricted-imports
-import { Collapse as AntdCollapse } from 'antd'; // TODO: Remove antd
-// eslint-disable-next-line no-restricted-imports
-import { CollapseProps as AntdCollapseProps } from 'antd/lib/collapse'; // TODO: Remove antd
+import {
+ Collapse as AntdCollapse,
+ CollapseProps as AntdCollapseProps,
+} from 'antd-v5';
export interface CollapseProps extends AntdCollapseProps {
- light?: boolean;
- bigger?: boolean;
- bold?: boolean;
animateArrows?: boolean;
}
-const Collapse = Object.assign(
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- styled(({ light, bigger, bold, animateArrows, ...props }: CollapseProps) => (
-
- ))`
- .ant-collapse-item {
- .ant-collapse-header {
- font-weight: ${({ bold, theme }) =>
- bold ? theme.fontWeightStrong : theme.fontWeightNormal};
- font-size: ${({ bigger, theme }) =>
- bigger ? `${theme.sizeUnit * 4}px` : 'inherit'};
+const Collapse = styled((props: CollapseProps) => )`
+ .antd5-collapse-item {
+ .antd5-collapse-header {
+ .antd5-collapse-arrow svg {
+ transition: ${({ animateArrows }) =>
+ animateArrows ? 'transform 0.24s' : 'none'};
+ }
- .ant-collapse-arrow svg {
- transition: ${({ animateArrows }) =>
- animateArrows ? 'transform 0.24s' : 'none'};
- }
-
- ${({ expandIconPosition }) =>
- expandIconPosition &&
- expandIconPosition === 'right' &&
- `
- .anticon.anticon-right.ant-collapse-arrow > svg {
+ ${({ expandIconPosition }) =>
+ expandIconPosition &&
+ expandIconPosition === 'right' &&
+ `
+ .anticon.anticon-right.antd5-collapse-arrow > svg {
transform: rotate(90deg) !important;
}
`}
+ }
- ${({ light, theme }) =>
- light &&
- `
- color: ${theme.colorTextSecondary};
- .ant-collapse-arrow svg {
- color: ${theme.colorTextSecondary};
- }
- `}
+ ${({ ghost, bordered, theme }) =>
+ ghost &&
+ bordered &&
+ `
+ border-bottom: 1px solid ${theme.colorBorderSecondary};
+ `}
+ .antd5-collapse-content {
+ color: ${({ theme }) => theme.colorText};
- ${({ ghost, bordered, theme }) =>
- ghost &&
- bordered &&
- `
- border-bottom: 1px solid ${theme.colorBorderSecondary};
- `}
- }
- .ant-collapse-content {
- color: ${({ theme }) => theme.colorText};
- .ant-collapse-content-box {
- .loading.inline {
- margin: ${({ theme }) => theme.sizeUnit * 12}px auto;
- display: block;
- }
+ .antd5-collapse-content-box {
+ .loading.inline {
+ margin: ${({ theme }) => theme.sizeUnit * 12}px auto;
+ display: block;
}
}
}
- .ant-collapse-item-active {
- .ant-collapse-header {
- ${({ expandIconPosition }) =>
- expandIconPosition &&
- expandIconPosition === 'right' &&
- `
- .anticon.anticon-right.ant-collapse-arrow > svg {
+ }
+
+ .hidden-collapse-header .antd5-collapse-header {
+ display: none;
+ }
+
+ .antd5-collapse-item-active {
+ .antd5-collapse-header {
+ ${({ expandIconPosition }) =>
+ expandIconPosition &&
+ expandIconPosition === 'right' &&
+ `
+ .anticon.anticon-right.antd5-collapse-arrow > svg {
transform: rotate(-90deg) !important;
}
`}
- }
}
- `,
- {
- Panel: AntdCollapse.Panel,
- },
-);
+ }
+`;
export default Collapse;
diff --git a/superset-frontend/src/components/ErrorMessage/MarshmallowErrorMessage.tsx b/superset-frontend/src/components/ErrorMessage/MarshmallowErrorMessage.tsx
index 5b59fbf9721..0251de7882d 100644
--- a/superset-frontend/src/components/ErrorMessage/MarshmallowErrorMessage.tsx
+++ b/superset-frontend/src/components/ErrorMessage/MarshmallowErrorMessage.tsx
@@ -17,7 +17,7 @@
* under the License.
*/
import { JSONTree } from 'react-json-tree';
-import { css, styled, SupersetTheme, t } from '@superset-ui/core';
+import { styled, t } from '@superset-ui/core';
import { useJsonTreeTheme } from 'src/hooks/useJsonTreeTheme';
import Collapse from 'src/components/Collapse';
@@ -37,18 +37,6 @@ const StyledUl = styled.ul`
padding-top: ${({ theme }) => theme.sizeUnit * 4}px;
`;
-const collapseStyle = (theme: SupersetTheme) => css`
- .ant-collapse-arrow {
- left: 0px !important;
- }
- .ant-collapse-header {
- padding-left: ${theme.sizeUnit * 4}px !important;
- }
- .ant-collapse-content-box {
- padding: 0px !important;
- }
-`;
-
const extractInvalidValues = (messages: object, payload: object): string[] => {
const invalidValues: string[] = [];
@@ -99,16 +87,23 @@ export default function MarshmallowErrorMessage({
)}
-
-
- true}
- hideRoot
- theme={jsonTreeTheme}
- />
-
-
+ true}
+ hideRoot
+ theme={jsonTreeTheme}
+ />
+ ),
+ },
+ ]}
+ />
);
}
diff --git a/superset-frontend/src/components/IconTooltip/index.tsx b/superset-frontend/src/components/IconTooltip/index.tsx
index bb8c5bb7015..3e5cea7b3d7 100644
--- a/superset-frontend/src/components/IconTooltip/index.tsx
+++ b/superset-frontend/src/components/IconTooltip/index.tsx
@@ -18,7 +18,6 @@
*/
import { ReactNode } from 'react';
import { Tooltip } from 'src/components/Tooltip';
-import { styled } from '@superset-ui/core';
export interface Props {
children?: ReactNode;
@@ -41,13 +40,6 @@ export interface Props {
tooltip?: string | null;
}
-const StyledSpan = styled.span`
- color: ${({ theme }) => theme.colorPrimaryText};
- &: hover {
- color: ${({ theme }) => theme.colors.primary.dark2};
- }
-`;
-
const IconTooltip = ({
children = null,
className = '',
@@ -57,13 +49,19 @@ const IconTooltip = ({
tooltip = null,
}: Props) => {
const iconTooltip = (
-
{children}
-
+
);
if (tooltip) {
return (
diff --git a/superset-frontend/src/components/Icons/AntdEnhanced.tsx b/superset-frontend/src/components/Icons/AntdEnhanced.tsx
index 574b2ebc88c..6c801589f79 100644
--- a/superset-frontend/src/components/Icons/AntdEnhanced.tsx
+++ b/superset-frontend/src/components/Icons/AntdEnhanced.tsx
@@ -113,6 +113,7 @@ import {
FilterOutlined,
UnorderedListOutlined,
WarningOutlined,
+ SortAscendingOutlined,
KeyOutlined,
} from '@ant-design/icons';
import { FC } from 'react';
@@ -216,6 +217,7 @@ const AntdIcons = {
FilterOutlined,
UnorderedListOutlined,
WarningOutlined,
+ SortAscendingOutlined,
KeyOutlined,
} as const;
diff --git a/superset-frontend/src/components/index.ts b/superset-frontend/src/components/index.ts
index b0eaf695d7e..591598452f9 100644
--- a/superset-frontend/src/components/index.ts
+++ b/superset-frontend/src/components/index.ts
@@ -27,7 +27,6 @@
export {
Breadcrumb as AntdBreadcrumb,
Checkbox as AntdCheckbox,
- Collapse as AntdCollapse,
Select as AntdSelect,
} from 'antd';
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/CrossFilters/VerticalCollapse.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/CrossFilters/VerticalCollapse.tsx
index 48915f09633..1b3361dcd4a 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/CrossFilters/VerticalCollapse.tsx
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/CrossFilters/VerticalCollapse.tsx
@@ -19,40 +19,16 @@
import { useMemo } from 'react';
import Collapse from 'src/components/Collapse';
-import { styled, t, useTheme, css } from '@superset-ui/core';
+import { t } from '@superset-ui/core';
import { FilterBarOrientation } from 'src/dashboard/types';
+import { Divider } from 'src/components/Divider';
import CrossFilter from './CrossFilter';
import { CrossFilterIndicator } from '../../selectors';
-const StyledCollapse = styled(Collapse)`
- ${({ theme }) => `
- .ant-collapse-header {
- margin-bottom: ${theme.sizeUnit * 4}px;
- }
- .ant-collapse-item > .ant-collapse-header {
- padding-bottom: 0;
- }
- .ant-collapse-item > .ant-collapse-header > .ant-collapse-arrow {
- font-size: ${theme.fontSizeXS}px;
- padding-top: ${theme.sizeUnit * 3}px;
- }
- .ant-collapse-item > .ant-collapse-content > .ant-collapse-content-box {
- padding-top: 0;
- }
- `}
-`;
-
-const StyledCrossFiltersTitle = styled.span`
- ${({ theme }) => `
- font-size: ${theme.fontSizeSM}px;
- `}
-`;
-
const CrossFiltersVerticalCollapse = (props: {
crossFilters: CrossFilterIndicator[];
}) => {
const { crossFilters } = props;
- const theme = useTheme();
const crossFiltersIndicators = useMemo(
() =>
crossFilters.map(filter => (
@@ -70,32 +46,23 @@ const CrossFiltersVerticalCollapse = (props: {
}
return (
-
-
- {t('Cross-filters')}
-
- }
- >
- {crossFiltersIndicators}
-
-
-
+ items={[
+ {
+ key: 'crossFilters',
+ label: t('Cross-filters'),
+ children: (
+ <>
+ {crossFiltersIndicators}
+
+ >
+ ),
+ },
+ ]}
+ />
);
};
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControls.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControls.tsx
index fee23889a50..d9e44a4d9b1 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControls.tsx
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControls.tsx
@@ -145,7 +145,6 @@ const FilterControls: FC
= ({
0}
renderer={renderer}
/>
)}
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FiltersDropdownContent/index.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FiltersDropdownContent/index.tsx
index 36f91fe1eaf..b52f7dfb0f3 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FiltersDropdownContent/index.tsx
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FiltersDropdownContent/index.tsx
@@ -65,7 +65,6 @@ export const FiltersDropdownContent = ({
filtersOutOfScope={filtersOutOfScope}
renderer={renderer}
forceRender={forceRenderOutOfScope}
- horizontalOverflow
/>
)}
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FiltersOutOfScopeCollapsible/index.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FiltersOutOfScopeCollapsible/index.tsx
index ceb09dab1aa..59f934592d3 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FiltersOutOfScopeCollapsible/index.tsx
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FiltersOutOfScopeCollapsible/index.tsx
@@ -18,82 +18,39 @@
*/
import { ReactNode } from 'react';
import { css, Divider, Filter, SupersetTheme, t } from '@superset-ui/core';
-import { AntdCollapse } from 'src/components';
+import Collapse from 'src/components/Collapse';
export interface FiltersOutOfScopeCollapsibleProps {
filtersOutOfScope: (Filter | Divider)[];
renderer: (filter: Filter | Divider, index: number) => ReactNode;
- hasTopMargin?: boolean;
- horizontalOverflow?: boolean;
forceRender?: boolean;
}
export const FiltersOutOfScopeCollapsible = ({
filtersOutOfScope,
renderer,
- hasTopMargin,
- horizontalOverflow,
forceRender = false,
}: FiltersOutOfScopeCollapsibleProps) => (
-
- horizontalOverflow
- ? css`
- &.ant-collapse > .ant-collapse-item {
- & > .ant-collapse-header {
- padding: 0;
-
- & > .ant-collapse-arrow {
- right: 0;
- padding: 0;
- }
- }
-
- & .ant-collapse-content-box {
- padding: ${theme.sizeUnit * 4}px 0 0;
- margin-bottom: ${theme.sizeUnit * -4}px;
- }
- }
- `
- : css`
- &.ant-collapse {
- margin-top: ${hasTopMargin ? theme.sizeUnit * 6 : 0}px;
- & > .ant-collapse-item {
- & > .ant-collapse-header {
- padding-left: 0;
- padding-bottom: ${theme.sizeUnit * 2}px;
-
- & > .ant-collapse-arrow {
- right: ${theme.sizeUnit}px;
- }
- }
-
- & .ant-collapse-content-box {
- padding: ${theme.sizeUnit * 4}px 0 0;
- }
- }
- }
- `
- }
- >
- css`
- font-size: ${theme.fontSizeSM}px;
- `}
- >
- {t('Filters out of scope (%d)', filtersOutOfScope.length)}
-
- }
- key="1"
- >
- {filtersOutOfScope.map(renderer)}
-
-
+ items={[
+ {
+ key: 'out-of-scope-filters',
+ label: (
+
css`
+ font-size: ${theme.fontSizeSM}px;
+ `}
+ >
+ {t('Filters out of scope (%d)', filtersOutOfScope.length)}
+
+ ),
+ children: filtersOutOfScope.map(renderer),
+ forceRender,
+ },
+ ]}
+ />
);
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx
index 3a4d1c0b2f2..2d24cd7ecb4 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx
@@ -163,36 +163,11 @@ const DefaultValueContainer = styled.div`
align-items: center;
`;
-const StyledCollapse = styled(Collapse)`
- border-left: 0;
- border-top: 1px solid ${({ theme }) => theme.colorSplit};
- border-radius: 0;
-
- .ant-collapse-header {
- border-bottom: 1px solid ${({ theme }) => theme.colorSplit};
- border-top: 1px solid ${({ theme }) => theme.colorSplit};
- margin-top: -1px;
- border-radius: 0;
- }
-
- .ant-collapse-content {
- border: 0;
- }
-
- .ant-collapse-content-box {
- padding-top: ${({ theme }) => theme.sizeUnit * 2}px;
- }
-
- &.ant-collapse > .ant-collapse-item {
- border: 0;
- border-radius: 0;
- }
-`;
-
const StyledAsterisk = styled.span`
color: ${({ theme }) => theme.colorError};
font-size: ${({ theme }) => theme.fontSizeSM}px;
margin-left: ${({ theme }) => theme.sizeUnit - 1}px;
+
&:before {
content: '*';
}
@@ -891,397 +866,445 @@ const FiltersConfigForm = (
)}
)}
-
{
handleActiveFilterPanelChange(key);
}}
expandIconPosition="right"
key={`native-filter-config-${filterId}`}
- >
- {formFilter?.filterType !== 'filter_time' && (
-
- {canDependOnOtherFilters && hasAvailableFilters && (
-
- {
- setNativeFilterFieldValues(form, filterId, {
- dependencies,
- });
- forceUpdate();
- validateDependencies();
- formChanged();
- }}
- getDependencySuggestion={() =>
- getDependencySuggestion(filterId)
- }
- >
- {hasTimeDependency ? timeColumn : undefined}
-
-
- )}
- {hasDataset && hasAdditionalFilters && (
-
-
+ {canDependOnOtherFilters && hasAvailableFilters && (
+
+ {
+ setNativeFilterFieldValues(form, filterId, {
+ dependencies,
+ });
+ forceUpdate();
+ validateDependencies();
+ formChanged();
+ }}
+ getDependencySuggestion={() =>
+ getDependencySuggestion(filterId)
+ }
+ >
+ {hasTimeDependency ? timeColumn : undefined}
+
+
+ )}
+ {hasDataset && hasAdditionalFilters && (
+
+ {
- formChanged();
- if (checked) {
- validatePreFilter();
- }
- }}
- >
-
- c.filterable,
- ) || []
- }
- savedMetrics={datasetDetails?.metrics || []}
- datasource={datasetDetails}
- onChange={(filters: AdhocFilter[]) => {
- setNativeFilterFieldValues(form, filterId, {
- adhoc_filters: filters,
- });
- forceUpdate();
- formChanged();
- validatePreFilter();
- }}
- label={
-
- {t('Pre-filter')}
- {!hasTimeRange && }
-
- }
- />
-
- {showTimeRangePicker && (
- {t('Time range')}}
- initialValue={
- filterToEdit?.time_range || t('No filter')
- }
- required={!hasAdhoc}
- rules={[
- {
- validator: preFilterValidator,
- },
- ]}
- >
- {
- setNativeFilterFieldValues(form, filterId, {
- time_range: timeRange,
- });
- forceUpdate();
- formChanged();
- validatePreFilter();
- }}
- />
-
- )}
- {hasTimeRange && !hasTimeDependency
- ? timeColumn
- : undefined}
-
-
- )}
- {formFilter?.filterType !== 'filter_range' ? (
-
- {
- onSortChanged(checked || undefined);
- formChanged();
- }}
- >
- {t('Sort type')}}
- >
- {
- onSortChanged(value.target.value);
- formChanged();
- }}
- />
-
- {hasMetrics && (
-
- {t('Sort Metric')}
-
- >
- }
- data-test="field-input"
- >
- ({
- value: metric.metric_name,
- label: metric.verbose_name ?? metric.metric_name,
- }))}
- onChange={value => {
- if (value !== undefined) {
- setNativeFilterFieldValues(form, filterId, {
- sortMetric: value,
- });
- forceUpdate();
- }
- formChanged();
- }}
- />
-
- )}
-
-
- ) : (
-
- {
- onEnableSingleValueChanged(
- checked ? SingleValueType.Exact : undefined,
- );
- formChanged();
- }}
- >
- {t('Single value type')}
- }
- >
- {
- onEnableSingleValueChanged(value.target.value);
- formChanged();
- }}
- options={[
- {
- label: t('Minimum'),
- value: SingleValueType.Minimum,
- },
- { label: t('Exact'), value: SingleValueType.Exact },
- {
- label: t('Maximum'),
- value: SingleValueType.Maximum,
- },
- ]}
- />
-
-
-
- )}
-
- )}
-
- {t('Description')}}
- >
-
-
-
-
- {
- setHasDefaultValue(value);
- if (!value) {
- setNativeFilterFieldValues(form, filterId, {
- defaultDataMask: null,
- });
- }
- formChanged();
- }}
- >
- {!isRemoved && (
- {t('Default Value')}}
- required={hasDefaultValue}
- rules={[
- {
- validator: () => {
- if (formFilter?.defaultDataMask?.filterState?.value) {
- // requires managing the error as the DefaultValue
- // component does not use an Antdesign compatible input
- const formValidationFields = form.getFieldsError();
- setErroredFilters(prevErroredFilters => {
- if (
- prevErroredFilters.length &&
- !formValidationFields.find(
- f => f.errors.length > 0,
- )
- ) {
- return [];
- }
- return prevErroredFilters;
- });
- return Promise.resolve();
- }
- setErroredFilters(prevErroredFilters => {
- if (prevErroredFilters.includes(filterId)) {
- return prevErroredFilters;
- }
- return [...prevErroredFilters, filterId];
- });
- return Promise.reject(
- new Error(t('Please choose a valid value')),
- );
- },
- },
- ]}
- >
- {error || showDefaultValue ? (
-
- {error ? (
-
- }
- />
- ) : (
- {
- if (
- !isEqual(
- initialDefaultValue?.filterState?.value,
- dataMask?.filterState?.value,
- )
- ) {
+ onChange={checked => {
formChanged();
- }
- setNativeFilterFieldValues(form, filterId, {
- defaultDataMask: dataMask,
- });
- form.validateFields([
- ['filters', filterId, 'defaultDataMask'],
- ]);
- forceUpdate();
- }}
- hasDefaultValue={hasDefaultValue}
- filterId={filterId}
- hasDataset={hasDataset}
- form={form}
- formData={newFormData}
- enableNoResults={enableNoResults}
- />
+ if (checked) {
+ validatePreFilter();
+ }
+ }}
+ >
+
+ c.filterable,
+ ) || []
+ }
+ savedMetrics={datasetDetails?.metrics || []}
+ datasource={datasetDetails}
+ onChange={(filters: AdhocFilter[]) => {
+ setNativeFilterFieldValues(form, filterId, {
+ adhoc_filters: filters,
+ });
+ forceUpdate();
+ formChanged();
+ validatePreFilter();
+ }}
+ label={
+
+
+ {t('Pre-filter')}
+
+ {!hasTimeRange && }
+
+ }
+ />
+
+ {showTimeRangePicker && (
+ {t('Time range')}
+ }
+ initialValue={
+ filterToEdit?.time_range || t('No filter')
+ }
+ required={!hasAdhoc}
+ rules={[
+ {
+ validator: preFilterValidator,
+ },
+ ]}
+ >
+ {
+ setNativeFilterFieldValues(
+ form,
+ filterId,
+ {
+ time_range: timeRange,
+ },
+ );
+ forceUpdate();
+ formChanged();
+ validatePreFilter();
+ }}
+ />
+
+ )}
+ {hasTimeRange && !hasTimeDependency
+ ? timeColumn
+ : undefined}
+
+
)}
- {hasDataset && datasetId && (
-
- refreshHandler(true)}
- />
-
+ {formFilter?.filterType !== 'filter_range' ? (
+
+ {
+ onSortChanged(checked || undefined);
+ formChanged();
+ }}
+ >
+ {t('Sort type')}
+ }
+ >
+ {
+ onSortChanged(value.target.value);
+ formChanged();
+ }}
+ />
+
+ {hasMetrics && (
+
+
+ {t('Sort Metric')}
+
+
+
+ >
+ }
+ data-test="field-input"
+ >
+ ({
+ value: metric.metric_name,
+ label:
+ metric.verbose_name ??
+ metric.metric_name,
+ }))}
+ onChange={value => {
+ if (value !== undefined) {
+ setNativeFilterFieldValues(
+ form,
+ filterId,
+ {
+ sortMetric: value,
+ },
+ );
+ forceUpdate();
+ }
+ formChanged();
+ }}
+ />
+
+ )}
+
+
+ ) : (
+
+ {
+ onEnableSingleValueChanged(
+ checked ? SingleValueType.Exact : undefined,
+ );
+ formChanged();
+ }}
+ >
+
+ {t('Single value type')}
+
+ }
+ >
+ {
+ onEnableSingleValueChanged(
+ value.target.value,
+ );
+ formChanged();
+ }}
+ options={[
+ {
+ label: t('Minimum'),
+ value: SingleValueType.Minimum,
+ },
+ {
+ label: t('Exact'),
+ value: SingleValueType.Exact,
+ },
+ {
+ label: t('Maximum'),
+ value: SingleValueType.Maximum,
+ },
+ ]}
+ />
+
+
+
)}
-
- ) : (
- t('Fill all required fields to enable "Default Value"')
- )}
-
- )}
-
-
- {Object.keys(controlItems)
- .sort(
- (a, b) =>
- controlsOrder.indexOf(a as ControlKey) -
- controlsOrder.indexOf(b as ControlKey),
- )
- .map(key => controlItems[key].element)}
-
-
+ >
+ ),
+ },
+ ]
+ : []),
+ {
+ label: FilterPanels.settings.name,
+ key: `${filterId}-${FilterPanels.settings.key}`,
+ forceRender: true,
+ children: (
+ <>
+
{t('Description')}}
+ >
+
+
+
+
+ {
+ setHasDefaultValue(value);
+ if (!value) {
+ setNativeFilterFieldValues(form, filterId, {
+ defaultDataMask: null,
+ });
+ }
+ formChanged();
+ }}
+ >
+ {!isRemoved && (
+ {t('Default Value')}
+ }
+ required={hasDefaultValue}
+ rules={[
+ {
+ validator: () => {
+ if (
+ formFilter?.defaultDataMask?.filterState
+ ?.value
+ ) {
+ // requires managing the error as the DefaultValue
+ // component does not use an Antdesign compatible input
+ const formValidationFields =
+ form.getFieldsError();
+ setErroredFilters(prevErroredFilters => {
+ if (
+ prevErroredFilters.length &&
+ !formValidationFields.find(
+ f => f.errors.length > 0,
+ )
+ ) {
+ return [];
+ }
+ return prevErroredFilters;
+ });
+ return Promise.resolve();
+ }
+ setErroredFilters(prevErroredFilters => {
+ if (prevErroredFilters.includes(filterId)) {
+ return prevErroredFilters;
+ }
+ return [...prevErroredFilters, filterId];
+ });
+ return Promise.reject(
+ new Error(t('Please choose a valid value')),
+ );
+ },
+ },
+ ]}
+ >
+ {error || showDefaultValue ? (
+
+ {error ? (
+
+ }
+ />
+ ) : (
+ {
+ if (
+ !isEqual(
+ initialDefaultValue?.filterState?.value,
+ dataMask?.filterState?.value,
+ )
+ ) {
+ formChanged();
+ }
+ setNativeFilterFieldValues(form, filterId, {
+ defaultDataMask: dataMask,
+ });
+ form.validateFields([
+ ['filters', filterId, 'defaultDataMask'],
+ ]);
+ forceUpdate();
+ }}
+ hasDefaultValue={hasDefaultValue}
+ filterId={filterId}
+ hasDataset={hasDataset}
+ form={form}
+ formData={newFormData}
+ enableNoResults={enableNoResults}
+ />
+ )}
+ {hasDataset && datasetId && (
+
+ refreshHandler(true)}
+ />
+
+ )}
+
+ ) : (
+ t(
+ 'Fill all required fields to enable "Default Value"',
+ )
+ )}
+
+ )}
+
+
+ {Object.keys(controlItems)
+ .sort(
+ (a, b) =>
+ controlsOrder.indexOf(a as ControlKey) -
+ controlsOrder.indexOf(b as ControlKey),
+ )
+ .map(key => controlItems[key].element)}
+ >
+ ),
+ },
+ ]}
+ />
{
defaultRender();
- userEvent.click(screen.getByText(FILTER_SETTINGS_REGEX));
-
expect(screen.getByText(FILTER_TYPE_REGEX)).toBeInTheDocument();
expect(screen.getByText(FILTER_NAME_REGEX)).toBeInTheDocument();
expect(screen.getByText(DATASET_REGEX)).toBeInTheDocument();
@@ -201,8 +199,6 @@ test('renders a numerical range filter type', async () => {
await waitFor(() => userEvent.click(screen.getByText(NUMERICAL_RANGE_REGEX)));
- userEvent.click(screen.getByText(FILTER_SETTINGS_REGEX));
-
expect(screen.getByText(FILTER_TYPE_REGEX)).toBeInTheDocument();
expect(screen.getByText(FILTER_NAME_REGEX)).toBeInTheDocument();
expect(screen.getByText(DATASET_REGEX)).toBeInTheDocument();
diff --git a/superset-frontend/src/explore/components/ControlPanelsContainer.tsx b/superset-frontend/src/explore/components/ControlPanelsContainer.tsx
index 8ef318b1a87..a0e70038876 100644
--- a/superset-frontend/src/explore/components/ControlPanelsContainer.tsx
+++ b/superset-frontend/src/explore/components/ControlPanelsContainer.tsx
@@ -590,7 +590,7 @@ export const ControlPanelsContainer = (props: ControlPanelsContainerProps) => {
);
- return (
+ const PanelChildren = (
<>
{
.filter(Boolean)}
/>
{isVisible && (
- css`
- margin-bottom: 0;
- box-shadow: none;
-
- &:last-child {
- padding-bottom: ${theme.sizeUnit * 16}px;
- border-bottom: 0;
- }
-
- .panel-body {
- margin-left: ${theme.sizeUnit * 4}px;
- padding-bottom: 0;
- }
-
- span.label {
- display: inline-block;
- }
- ${!section.label &&
- `
- .ant-collapse-header {
- display: none;
- }
- `}
- `}
- header={ }
- key={sectionId}
- >
+ <>
{section.controlSetRows.map((controlSets, i) => {
const renderedControls = controlSets
.map(controlItem => {
@@ -666,10 +639,18 @@ export const ControlPanelsContainer = (props: ControlPanelsContainerProps) => {
/>
);
})}
-
+ >
)}
>
);
+
+ return {
+ key: String(section.label),
+ label: ,
+ children: PanelChildren,
+ className: section.label ? '' : 'hidden-collapse-header',
+ style: { visibility: isVisible ? 'visible' : 'hidden' },
+ };
};
const hasControlsTransferred =
@@ -769,14 +750,16 @@ export const ControlPanelsContainer = (props: ControlPanelsContainerProps) => {
key: TABS_KEYS.DATA,
label: dataTabTitle,
children: (
-
+ <>
{showDatasourceAlert && }
- {querySections.map(renderControlPanelSection)}
-
+
+ >
),
},
...(showCustomizeTab
@@ -789,9 +772,11 @@ export const ControlPanelsContainer = (props: ControlPanelsContainerProps) => {
defaultActiveKey={expandedCustomizeSections}
expandIconPosition="right"
ghost
- >
- {customizeSections.map(renderControlPanelSection)}
-
+ bordered
+ items={[
+ ...customizeSections.map(renderControlPanelSection),
+ ]}
+ />
),
},
]
diff --git a/superset-frontend/src/explore/components/DatasourcePanel/index.tsx b/superset-frontend/src/explore/components/DatasourcePanel/index.tsx
index caf696b63d9..1c68422f26c 100644
--- a/superset-frontend/src/explore/components/DatasourcePanel/index.tsx
+++ b/superset-frontend/src/explore/components/DatasourcePanel/index.tsx
@@ -84,9 +84,6 @@ const DatasourceContainer = styled.div`
display: flex;
flex-direction: column;
max-height: 100%;
- .ant-collapse {
- height: auto;
- }
.field-selections {
padding: 0 0 ${theme.sizeUnit}px;
overflow: auto;
diff --git a/superset-frontend/src/explore/components/ExploreChartPanel/index.jsx b/superset-frontend/src/explore/components/ExploreChartPanel/index.jsx
index c39c6eb9a7c..3db1dd934be 100644
--- a/superset-frontend/src/explore/components/ExploreChartPanel/index.jsx
+++ b/superset-frontend/src/explore/components/ExploreChartPanel/index.jsx
@@ -103,22 +103,6 @@ const Styles = styled.div`
display: ${({ showSplite }) => (showSplite ? 'block' : 'none')};
cursor: row-resize;
}
-
- .ant-collapse {
- .antd5-tabs {
- height: 100%;
- .antd5-tabs-nav {
- padding-left: ${({ theme }) => theme.sizeUnit * 5}px;
- margin: 0;
- }
- .antd5-tabs-content-holder {
- overflow: hidden;
- .antd5-tabs-content {
- height: 100%;
- }
- }
- }
- }
`;
const ExploreChartPanel = ({
diff --git a/superset-frontend/src/explore/components/controls/FixedOrMetricControl/index.jsx b/superset-frontend/src/explore/components/controls/FixedOrMetricControl/index.jsx
index 2aa19ac7261..187ad7e4b9b 100644
--- a/superset-frontend/src/explore/components/controls/FixedOrMetricControl/index.jsx
+++ b/superset-frontend/src/explore/components/controls/FixedOrMetricControl/index.jsx
@@ -18,7 +18,7 @@
*/
import { Component } from 'react';
import PropTypes from 'prop-types';
-import { css, t } from '@superset-ui/core';
+import { t } from '@superset-ui/core';
import Label from 'src/components/Label';
import Collapse from 'src/components/Collapse';
import TextControl from 'src/explore/components/controls/TextControl';
@@ -102,87 +102,70 @@ export default class FixedOrMetricControl extends Component {
css`
- &.ant-collapse
- > .ant-collapse-item.ant-collapse-no-arrow
- > .ant-collapse-header {
- border: 0px;
- padding: 0px 0px ${theme.sizeUnit * 2}px 0px;
- display: inline-block;
- }
- &.ant-collapse-ghost
- > .ant-collapse-item
- > .ant-collapse-content
- > .ant-collapse-content-box {
- padding: 0px;
-
- & .well {
- margin-bottom: 0px;
- padding: ${theme.sizeUnit * 2}px;
- }
- }
- `}
- >
-
- {this.state.type === controlTypes.fixed && (
- {this.state.fixedValue}
- )}
- {this.state.type === controlTypes.metric && (
-
- {t('metric')}:
-
- {this.state.metricValue
- ? this.state.metricValue.label
- : null}
-
-
- )}
-
- }
- >
-
-
{
- this.setType(controlTypes.fixed);
- }}
- >
- {
- this.setType(controlTypes.fixed);
- }}
- value={this.state.fixedValue}
- />
-
-
{
- this.setType(controlTypes.metric);
- }}
- >
- {
- this.setType(controlTypes.metric);
- }}
- onChange={this.setMetric}
- value={this.state.metricValue}
- datasource={this.props.datasource}
- />
-
-
-
-
+ items={[
+ {
+ key: 'fixed-or-metric',
+ showArrow: false,
+ label: (
+
+ {this.state.type === controlTypes.fixed && (
+ {this.state.fixedValue}
+ )}
+ {this.state.type === controlTypes.metric && (
+
+ {t('metric')}:
+
+ {this.state.metricValue
+ ? this.state.metricValue.label
+ : null}
+
+
+ )}
+
+ ),
+ children: (
+
+
{
+ this.setType(controlTypes.fixed);
+ }}
+ >
+ {
+ this.setType(controlTypes.fixed);
+ }}
+ value={this.state.fixedValue}
+ />
+
+
{
+ this.setType(controlTypes.metric);
+ }}
+ >
+ {
+ this.setType(controlTypes.metric);
+ }}
+ onChange={this.setMetric}
+ value={this.state.metricValue}
+ datasource={this.props.datasource}
+ />
+
+
+ ),
+ },
+ ]}
+ />
);
}
diff --git a/superset-frontend/src/explore/components/controls/VizTypeControl/VizTypeGallery.tsx b/superset-frontend/src/explore/components/controls/VizTypeControl/VizTypeGallery.tsx
index 081ec504e33..1f0d9a9099e 100644
--- a/superset-frontend/src/explore/components/controls/VizTypeControl/VizTypeGallery.tsx
+++ b/superset-frontend/src/explore/components/controls/VizTypeControl/VizTypeGallery.tsx
@@ -39,7 +39,6 @@ import {
chartLabelWeight,
chartLabelExplanations,
} from '@superset-ui/core';
-import { AntdCollapse } from 'src/components';
import { Tooltip } from 'src/components/Tooltip';
import { Input } from 'src/components/Input';
import Label from 'src/components/Label';
@@ -47,6 +46,7 @@ import { usePluginContext } from 'src/components/DynamicPlugins';
import { Icons } from 'src/components/Icons';
import { nativeFilterGate } from 'src/dashboard/components/nativeFilters/utils';
import scrollIntoView from 'scroll-into-view-if-needed';
+import Collapse from 'src/components/Collapse';
interface VizTypeGalleryProps {
onChange: (vizType: string | null) => void;
@@ -116,14 +116,15 @@ const LeftPane = styled.div`
border-right: 1px solid ${({ theme }) => theme.colorBorder};
overflow: auto;
- .ant-collapse .ant-collapse-item {
- .ant-collapse-header {
+ .antd5-collapse .antd5-collapse-item {
+ .antd5-collapse-header {
font-size: ${({ theme }) => theme.fontSizeSM}px;
color: ${({ theme }) => theme.colorText};
padding-left: ${({ theme }) => theme.sizeUnit * 2}px;
padding-bottom: ${({ theme }) => theme.sizeUnit}px;
}
- .ant-collapse-content .ant-collapse-content-box {
+
+ .antd5-collapse-content .antd5-collapse-content-box {
display: flex;
flex-direction: column;
padding: 0 ${({ theme }) => theme.sizeUnit * 2}px;
@@ -694,37 +695,37 @@ export default function VizTypeGallery(props: VizTypeGalleryProps) {
}
onClick={clickSelector}
/>
-
- {Object.keys(sectionMap).map(sectionId => {
+ items={Object.keys(sectionMap).map(sectionId => {
const section = sectionMap[sectionId as keyof typeof sectionMap];
- return (
- {section.title}}
- key={sectionId}
- >
- {section.selectors.map((selector: string) => (
-
- ))}
-
- );
+ return {
+ key: sectionId,
+ label: {section.title} ,
+ children: (
+ <>
+ {section.selectors.map((selector: string) => (
+
+ ))}
+ >
+ ),
+ };
})}
-
+ />
diff --git a/superset-frontend/src/features/alerts/AlertReportModal.test.tsx b/superset-frontend/src/features/alerts/AlertReportModal.test.tsx
index f526b465c1e..b79d27811e5 100644
--- a/superset-frontend/src/features/alerts/AlertReportModal.test.tsx
+++ b/superset-frontend/src/features/alerts/AlertReportModal.test.tsx
@@ -365,7 +365,7 @@ test('renders all Alert Condition fields', async () => {
});
userEvent.click(screen.getByTestId('alert-condition-panel'));
const database = screen.getByRole('combobox', { name: /database/i });
- const sql = screen.getAllByRole('textbox')[2];
+ const sql = screen.getByRole('textbox');
const condition = screen.getByRole('combobox', { name: /condition/i });
const threshold = screen.getByRole('spinbutton');
expect(database).toBeInTheDocument();
diff --git a/superset-frontend/src/features/alerts/AlertReportModal.tsx b/superset-frontend/src/features/alerts/AlertReportModal.tsx
index fb94c5c1114..63602cdb9ba 100644
--- a/superset-frontend/src/features/alerts/AlertReportModal.tsx
+++ b/superset-frontend/src/features/alerts/AlertReportModal.tsx
@@ -77,7 +77,6 @@ import NumberInput from './components/NumberInput';
import { AlertReportCronScheduler } from './components/AlertReportCronScheduler';
import { NotificationMethod } from './components/NotificationMethod';
import ValidatedPanelHeader from './components/ValidatedPanelHeader';
-import StyledPanel from './components/StyledPanel';
import { buildErrorTooltipMessage } from './buildErrorTooltipMessage';
const TIMEOUT_MIN = 1;
@@ -210,14 +209,11 @@ const StyledModal = styled(Modal)`
margin-top: ${({ theme }) => theme.sizeUnit}px;
}
- .ant-collapse > .ant-collapse-item {
- border-bottom: none;
- }
-
.inline-container {
display: flex;
flex-direction: row;
align-items: center;
+
&.wrap {
flex-wrap: wrap;
}
@@ -253,6 +249,7 @@ export const StyledInputContainer = styled.div`
-webkit-appearance: none;
margin: 0;
}
+
input[type='number'] {
-moz-appearance: textfield;
}
@@ -1471,473 +1468,502 @@ const AlertReportModal: FunctionComponent = ({
expandIconPosition="right"
defaultActiveKey="general"
accordion
- css={css`
- border: 'none';
- `}
- >
-
- }
- key="general"
- >
-
-
-
- {isReport ? t('Report name') : t('Alert name')}
- *
-
-
-
-
-
-
-
- {t('Owners')}
- *
-
-
-
-
- {t('Description')}
-
-
-
-
-
-
-
- {isReport ? t('Report is active') : t('Alert is active')}
-
-
-
-
- {!isReport && (
-
- }
- key="condition"
- >
-
-
- {t('Database')}
- *
-
-
-
-
-
- {t('SQL Query')}
-
- *
-
-
-
-
-
-
- {t('Trigger Alert If...')}
- *
-
-
-
+
+
+ {isReport ? t('Report name') : t('Alert name')}
+ *
+
+
+
+
+
+
+
+ {t('Owners')}
+ *
+
+
+
+
+ {t('Description')}
+
+
+
+
+
+
-
-
-
-
- {t('Value')}{' '}
- {!conditionNotNull && * }
-
-
-
-
-
-
-
- )}
-
- }
- key="contents"
- >
-
-
- {t('Content type')}
- *
-
-
-
-
- {contentType === ContentType.Chart ? (
- <>
-
- {t('Select chart')}
- *
-
-
- >
- ) : (
- <>
-
- {t('Select dashboard')}
- *
-
-
- >
- )}
-
-
- {formatOptionEnabled && (
- <>
-
- {t('Content format')}
- *
-
- FORMAT_OPTIONS[key as FORMAT_OPTIONS_KEY],
- )
- : /* If chart is of text based viz type: show text
- format option */
- TEXT_BASED_VISUALIZATION_TYPES.includes(chartVizType)
- ? Object.values(FORMAT_OPTIONS)
- : ['pdf', 'png', 'csv'].map(
- key => FORMAT_OPTIONS[key as FORMAT_OPTIONS_KEY],
- )
- }
- placeholder={t('Select format')}
- />
- >
- )}
-
- {tabsEnabled && contentType === ContentType.Dashboard && (
-
- <>
- {t('Select tab')}
-
- >
-
- )}
- {isScreenshot && (
-
- {t('Screenshot width')}
-
-
+
+ {isReport ? t('Report is active') : t('Alert is active')}
+
+
-
- )}
- {(isReport || contentType === ContentType.Dashboard) && (
-
-
- {t('Ignore cache when generating report')}
-
-
- )}
-
-
- }
- key="schedule"
- >
- updateAlertState('crontab', newVal)}
- />
-
-
- {t('Timezone')} *
-
-
-
-
-
- {t('Log retention')}
- *
-
-
-
-
-
-
- {isReport ? (
- <>
-
- {t('Working timeout')}
- *
-
-
-
-
- >
- ) : (
- <>
- {t('Grace period')}
-
-
-
- >
- )}
-
-
-
- }
- key="notification"
- >
- {notificationSettings.map((notificationSetting, i) => (
-
-
-
- ))}
+ ),
+ },
+ ...(!isReport
+ ? [
+ {
+ key: 'condition',
+ label: (
+
+ ),
+ children: (
+
+
+
+ {t('Database')}
+ *
+
+
+
+
+
+ {t('SQL Query')}
+
+ *
+
+
+
+
+
+
+ {t('Trigger Alert If...')}
+ *
+
+
+
+
+
+
+
+ {t('Value')}{' '}
+ {!conditionNotNull && (
+ *
+ )}
+
+
+
+
+
+
+
+ ),
+ },
+ ]
+ : []),
{
- // Prohibit 'add notification method' button if only one present
- allowedNotificationMethodsCount > notificationSettings.length && (
-
- )
- }
-
-
+ ),
+ children: (
+ <>
+
+
+ {t('Content type')}
+ *
+
+
+
+
+ {contentType === ContentType.Chart ? (
+ <>
+
+ {t('Select chart')}
+ *
+
+
+ >
+ ) : (
+ <>
+
+ {t('Select dashboard')}
+ *
+
+
+ >
+ )}
+
+
+ {formatOptionEnabled && (
+ <>
+
+ {t('Content format')}
+ *
+
+
+ FORMAT_OPTIONS[key as FORMAT_OPTIONS_KEY],
+ )
+ : /* If chart is of text based viz type: show text
+ format option */
+ TEXT_BASED_VISUALIZATION_TYPES.includes(
+ chartVizType,
+ )
+ ? Object.values(FORMAT_OPTIONS)
+ : ['pdf', 'png', 'csv'].map(
+ key =>
+ FORMAT_OPTIONS[key as FORMAT_OPTIONS_KEY],
+ )
+ }
+ placeholder={t('Select format')}
+ />
+ >
+ )}
+
+ {tabsEnabled && contentType === ContentType.Dashboard && (
+
+ <>
+ {t('Select tab')}
+
+ >
+
+ )}
+ {isScreenshot && (
+
+ {t('Screenshot width')}
+
+
+
+
+ )}
+ {(isReport || contentType === ContentType.Dashboard) && (
+
+
+ {t('Ignore cache when generating report')}
+
+
+ )}
+ >
+ ),
+ },
+ {
+ key: 'schedule',
+ label: (
+
+ ),
+ children: (
+ <>
+ updateAlertState('crontab', newVal)}
+ />
+
+
+ {t('Timezone')} *
+
+
+
+
+
+ {t('Log retention')}
+ *
+
+
+
+
+
+
+ {isReport ? (
+ <>
+
+ {t('Working timeout')}
+ *
+
+
+
+
+ >
+ ) : (
+ <>
+ {t('Grace period')}
+
+
+
+ >
+ )}
+
+ >
+ ),
+ },
+ {
+ key: 'notification',
+ label: (
+
+ ),
+ children: (
+ <>
+ {notificationSettings.map((notificationSetting, i) => (
+
+
+
+ ))}
+ {
+ // Prohibit 'add notification method' button if only one present
+ allowedNotificationMethodsCount >
+ notificationSettings.length && (
+
+ )
+ }
+ >
+ ),
+ },
+ ]}
+ />
);
};
diff --git a/superset-frontend/src/features/alerts/components/StyledPanel.tsx b/superset-frontend/src/features/alerts/components/StyledPanel.tsx
deleted file mode 100644
index eb2f8c837a3..00000000000
--- a/superset-frontend/src/features/alerts/components/StyledPanel.tsx
+++ /dev/null
@@ -1,77 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-import { ReactNode } from 'react';
-import { css, SupersetTheme } from '@superset-ui/core';
-// eslint-disable-next-line no-restricted-imports
-import { Collapse as AntdCollapse } from 'antd'; // TODO: Remove antd
-// eslint-disable-next-line no-restricted-imports
-import { CollapsePanelProps } from 'antd/lib/collapse'; // TODO: Remove antd
-
-const anticonHeight = 12;
-const antdPanelStyles = (theme: SupersetTheme) => css`
- .ant-collapse-header {
- display: flex;
- flex-direction: column;
- justify-content: center;
- align-items: flex-start;
- padding: 0px ${theme.sizeUnit * 4}px;
-
- .anticon.anticon-right.ant-collapse-arrow {
- padding: 0;
- top: calc(50% - ${anticonHeight / 2}px);
- }
-
- .collapse-panel-title {
- font-size: ${theme.sizeUnit * 4}px;
- font-weight: ${theme.fontWeightStrong};
- line-height: 130%;
- }
-
- .collapse-panel-subtitle {
- color: ${theme.colors.grayscale.base};
- font-size: ${theme.fontSizeSM}px;
- font-weight: ${theme.fontWeightNormal};
- line-height: 150%;
- margin-bottom: 0;
- padding-top: ${theme.sizeUnit}px;
- }
-
- .collapse-panel-asterisk {
- color: var(--semantic-error-base, ${theme.colors.warning.dark1});
- }
- .validation-checkmark {
- width: ${theme.sizeUnit * 4}px;
- height: ${theme.sizeUnit * 4}px;
- margin-left: ${theme.sizeUnit}px;
- color: ${theme.colorSuccess};
- }
- }
-`;
-
-export interface PanelProps extends CollapsePanelProps {
- children?: ReactNode;
-}
-const StyledPanel = (props: PanelProps) => (
- antdPanelStyles(theme)}
- {...props}
- />
-);
-
-export default StyledPanel;
diff --git a/superset-frontend/src/features/databases/DatabaseModal/DatabaseConnectionForm/OAuth2ClientField.tsx b/superset-frontend/src/features/databases/DatabaseModal/DatabaseConnectionForm/OAuth2ClientField.tsx
index 32ced645652..7b78a54e974 100644
--- a/superset-frontend/src/features/databases/DatabaseModal/DatabaseConnectionForm/OAuth2ClientField.tsx
+++ b/superset-frontend/src/features/databases/DatabaseModal/DatabaseConnectionForm/OAuth2ClientField.tsx
@@ -18,8 +18,6 @@
*/
import { useState } from 'react';
-import { css, SupersetTheme } from '@superset-ui/core';
-
import Collapse from 'src/components/Collapse';
import { Input } from 'src/components/Input';
import { FormItem } from 'src/components/Form';
@@ -33,16 +31,6 @@ const LABELS = {
SCOPE: 'Scope',
};
-const collapseStyle = (theme: SupersetTheme) => css`
- .ant-collapse-header {
- padding-bottom: ${theme.sizeUnit * 1.5}px !important;
- padding-top: ${theme.sizeUnit * 1.5}px !important;
- }
- .anticon.ant-collapse-arrow {
- top: 0 !important;
- }
-`;
-
interface OAuth2ClientInfo {
id: string;
secret: string;
@@ -91,51 +79,55 @@ export const OAuth2ClientField = ({
};
return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+ ),
+ },
+ ]}
+ />
);
};
diff --git a/superset-frontend/src/features/databases/DatabaseModal/ExtraOptions.tsx b/superset-frontend/src/features/databases/DatabaseModal/ExtraOptions.tsx
index 969901fd2db..1e90d663554 100644
--- a/superset-frontend/src/features/databases/DatabaseModal/ExtraOptions.tsx
+++ b/superset-frontend/src/features/databases/DatabaseModal/ExtraOptions.tsx
@@ -33,7 +33,6 @@ import {
StyledInputContainer,
StyledJsonEditor,
StyledExpandableForm,
- antdCollapseStyles,
no_margin_bottom,
} from './styles';
import { DatabaseObject, ExtraJson } from '../types';
@@ -86,547 +85,575 @@ const ExtraOptions = ({
antdCollapseStyles(theme)}
- >
-
- {t('SQL Lab')}
-
- {t('Adjust how this database will interact with SQL Lab.')}
-
-
- }
- key="1"
- >
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {t('CTAS & CVAS SCHEMA')}
+ items={[
+ {
+ key: 'sql-lab',
+ label: (
+
+
{t('SQL Lab')}
+
{t('Adjust how this database will interact with SQL Lab.')}
+
+ ),
+ children: (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {t('CTAS & CVAS SCHEMA')}
+
+
+
+
+
+ {t(
+ 'Force all tables and views to be created in this schema when clicking CTAS or CVAS in SQL Lab.',
+ )}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+ ),
+ },
+ {
+ key: 'performance',
+ label: (
+
+
{t('Performance')}
+
{t('Adjust performance settings of this database.')}
+
+ ),
+ children: (
+ <>
+
+ {t('Chart cache timeout')}
{t(
- 'Force all tables and views to be created in this schema when clicking CTAS or CVAS in SQL Lab.',
+ 'Duration (in seconds) of the caching timeout for charts of this database.' +
+ ' A timeout of 0 indicates that the cache never expires, and -1 bypasses the cache.' +
+ ' Note this defaults to the global timeout if undefined.',
)}
-
-
-
-
-
+ {t('Schema cache timeout')}
+
+
+
+
+ {t(
+ 'Duration (in seconds) of the metadata caching timeout for schemas of ' +
+ 'this database. If left unset, the cache never expires.',
)}
- />
-
-
-
-
-
-
+
+
+ {t('Table cache timeout')}
+
+
+
+
+ {t(
+ 'Duration (in seconds) of the metadata caching timeout for tables of ' +
+ 'this database. If left unset, the cache never expires. ',
)}
- />
-
-
-
-
-
-
+
+
+
+
+
+ {isAllowRunAsyncDisabled && (
+
)}
- />
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {t('Performance')}
-
- {t('Adjust performance settings of this database.')}
-
-
- }
- key="2"
- >
-
- {t('Chart cache timeout')}
-
-
-
-
- {t(
- 'Duration (in seconds) of the caching timeout for charts of this database.' +
- ' A timeout of 0 indicates that the cache never expires, and -1 bypasses the cache.' +
- ' Note this defaults to the global timeout if undefined.',
- )}
-
-
-
- {t('Schema cache timeout')}
-
-
-
-
- {t(
- 'Duration (in seconds) of the metadata caching timeout for schemas of ' +
- 'this database. If left unset, the cache never expires.',
- )}
-
-
-
- {t('Table cache timeout')}
-
-
-
-
- {t(
- 'Duration (in seconds) of the metadata caching timeout for tables of ' +
- 'this database. If left unset, the cache never expires. ',
- )}
-
-
-
-
-
-
- {isAllowRunAsyncDisabled && (
-
- )}
-
-
-
-
-
-
-
-
-
-
- {t('Security')}
- {t('Add extra connection information.')}
-
- }
- key="3"
- >
-
- {t('Secure extra')}
-
-
- onEditorChange({ json, name: 'masked_encrypted_extra' })
- }
- width="100%"
- height="160px"
- />
-
-
+
+
+
+
+
+
+
+
+ >
+ ),
+ },
+ {
+ key: 'security',
+ label: (
- {t(
- 'JSON string containing additional connection configuration. ' +
- 'This is used to provide connection information for systems ' +
- 'like Hive, Presto and BigQuery which do not conform to the ' +
- 'username:password syntax normally used by SQLAlchemy.',
- )}
+
{t('Security')}
+
{t('Add extra connection information.')}
-
-
-
- {t('Root certificate')}
-
-
-
-
- {t(
- 'Optional CA_BUNDLE contents to validate HTTPS requests. Only ' +
- 'available on certain database engines.',
- )}
-
-
-
-
-
-
-
-
- {isFileUploadSupportedByEngine && (
-
-
-
-
-
- )}
- {isFileUploadSupportedByEngine && !!db?.allow_file_upload && (
-
-
- {t('Schemas allowed for File upload')}
-
-
-
-
-
- {t(
- 'A comma-separated list of schemas that files are allowed to upload to.',
- )}
-
-
- )}
-
- {extraExtension && ExtraExtensionComponent && ExtensionDescription && (
-
- {ExtraExtensionLogo && }
- ({
- fontSize: theme.fontSizeLG,
- fontWeight: theme.fontWeightStrong,
- })}
+ ),
+ children: (
+ <>
+
+ {t('Secure extra')}
+
+
+ onEditorChange({ json, name: 'masked_encrypted_extra' })
+ }
+ width="100%"
+ height="160px"
+ />
+
+
+
+ {t(
+ 'JSON string containing additional connection configuration. ' +
+ 'This is used to provide connection information for systems ' +
+ 'like Hive, Presto and BigQuery which do not conform to the ' +
+ 'username:password syntax normally used by SQLAlchemy.',
+ )}
+
+
+
+
+ {t('Root certificate')}
+
+
+
+
+ {t(
+ 'Optional CA_BUNDLE contents to validate HTTPS requests. Only ' +
+ 'available on certain database engines.',
+ )}
+
+
+
- {extraExtension?.title}
-
-
-
-
-
- }
- key={extraExtension?.title}
- // @ts-ignore, 'icon' is valid in >=4.9.0 but missing from `CollapsibleType`
- collapsible={extraExtension.enabled?.() ? 'icon' : 'disabled'}
- >
-
-
-
-
- )}
-
- {t('Other')}
- {t('Additional settings.')}
-
- }
- key="4"
- >
-
- {t('Metadata Parameters')}
-
-
- onExtraEditorChange({ json, name: 'metadata_params' })
- }
- width="100%"
- height="160px"
- value={
- !Object.keys(extraJson?.metadata_params || {}).length
- ? ''
- : extraJson?.metadata_params
- }
- />
-
-
+
+
+
+
+
+ {isFileUploadSupportedByEngine && (
+
+
+
+
+
+ )}
+ {isFileUploadSupportedByEngine && !!db?.allow_file_upload && (
+
+
+ {t('Schemas allowed for File upload')}
+
+
+
+
+
+ {t(
+ 'A comma-separated list of schemas that files are allowed to upload to.',
+ )}
+
+
+ )}
+ >
+ ),
+ },
+ ...(extraExtension && ExtraExtensionComponent && ExtensionDescription
+ ? [
+ {
+ key: extraExtension?.title,
+ collapsible: extraExtension.enabled?.()
+ ? ('icon' as const)
+ : ('disabled' as const),
+ label: (
+
+ {ExtraExtensionLogo &&
}
+
({
+ fontSize: theme.fontSizeLG,
+ fontWeight: theme.fontWeightStrong,
+ })}
+ >
+ {extraExtension?.title}
+
+
+
+
+
+ ),
+ children: (
+
+
+
+ ),
+ },
+ ]
+ : []),
+ {
+ key: 'other',
+ label: (
- {t(
- 'The metadata_params object gets unpacked into the sqlalchemy.MetaData call.',
- )}
+
{t('Other')}
+
{t('Additional settings.')}
-
-
-
- {t('Engine Parameters')}
-
-
- onExtraEditorChange({ json, name: 'engine_params' })
- }
- width="100%"
- height="160px"
- value={
- !Object.keys(extraJson?.engine_params || {}).length
- ? ''
- : extraJson?.engine_params
- }
- />
-
-
-
- {t(
- 'The engine_params object gets unpacked into the sqlalchemy.create_engine call.',
+ ),
+ children: (
+ <>
+
+ {t('Metadata Parameters')}
+
+
+ onExtraEditorChange({ json, name: 'metadata_params' })
+ }
+ width="100%"
+ height="160px"
+ value={
+ !Object.keys(extraJson?.metadata_params || {}).length
+ ? ''
+ : extraJson?.metadata_params
+ }
+ />
+
+
+
+ {t(
+ 'The metadata_params object gets unpacked into the sqlalchemy.MetaData call.',
+ )}
+
+
+
+
+ {t('Engine Parameters')}
+
+
+ onExtraEditorChange({ json, name: 'engine_params' })
+ }
+ width="100%"
+ height="160px"
+ value={
+ !Object.keys(extraJson?.engine_params || {}).length
+ ? ''
+ : extraJson?.engine_params
+ }
+ />
+
+
+
+ {t(
+ 'The engine_params object gets unpacked into the sqlalchemy.create_engine call.',
+ )}
+
+
+
+
+
+ {t('Version')}
+
+
+
+
+
+ {t(
+ 'Specify the database version. This is used with Presto for query cost ' +
+ 'estimation, and Dremio for syntax changes, among others.',
+ )}
+
+
+
+
+
+
+
+
+ {supportsDynamicCatalog && (
+
+
+
+
+
+
)}
-
-
-
-
-
- {t('Version')}
-
-
-
-
-
- {t(
- 'Specify the database version. This is used with Presto for query cost ' +
- 'estimation, and Dremio for syntax changes, among others.',
- )}
-
-
-
-
-
-
-
-
- {supportsDynamicCatalog && (
-
-
-
-
-
-
- )}
-
-
+ >
+ ),
+ },
+ ]}
+ />
);
};
diff --git a/superset-frontend/src/features/databases/DatabaseModal/index.test.tsx b/superset-frontend/src/features/databases/DatabaseModal/index.test.tsx
index 1edb3bd7cc0..4be033d4117 100644
--- a/superset-frontend/src/features/databases/DatabaseModal/index.test.tsx
+++ b/superset-frontend/src/features/databases/DatabaseModal/index.test.tsx
@@ -563,37 +563,37 @@ describe('DatabaseModal', () => {
const advancedTab = screen.getByRole('tab', { name: /advanced/i });
// - Advanced tabs
const sqlLabTab = screen.getByRole('tab', {
- name: /right sql lab adjust how this database will interact with sql lab\./i,
+ name: /collapsed sql lab adjust how this database will interact with sql lab\./i,
});
const sqlLabTabArrow = within(sqlLabTab).getByRole('img', {
- name: /right/i,
+ name: /collapsed/i,
});
const sqlLabTabHeading = screen.getByRole('heading', {
name: /sql lab/i,
});
const performanceTab = screen.getByRole('tab', {
- name: /right performance adjust performance settings of this database\./i,
+ name: /collapsed performance adjust performance settings of this database\./i,
});
const performanceTabArrow = within(performanceTab).getByRole('img', {
- name: /right/i,
+ name: /collapsed/i,
});
const performanceTabHeading = screen.getByRole('heading', {
name: /performance/i,
});
const securityTab = screen.getByRole('tab', {
- name: /right security add extra connection information\./i,
+ name: /collapsed security add extra connection information\./i,
});
const securityTabArrow = within(securityTab).getByRole('img', {
- name: /right/i,
+ name: /collapsed/i,
});
const securityTabHeading = screen.getByRole('heading', {
name: /security/i,
});
const otherTab = screen.getByRole('tab', {
- name: /right other additional settings\./i,
+ name: /collapsed other additional settings\./i,
});
const otherTabArrow = within(otherTab).getByRole('img', {
- name: /right/i,
+ name: /collapsed/i,
});
const otherTabHeading = screen.getByRole('heading', { name: /other/i });
// renderModalFooter() - Advanced tab's footer
@@ -646,7 +646,7 @@ describe('DatabaseModal', () => {
// Click the "SQL Lab" tab
userEvent.click(
await screen.findByRole('tab', {
- name: /right sql lab adjust how this database will interact with sql lab\./i,
+ name: /collapsed sql lab adjust how this database will interact with sql lab\./i,
}),
);
expect(await screen.findByText(/step 2 of 2/i)).toBeInTheDocument();
@@ -674,7 +674,7 @@ describe('DatabaseModal', () => {
});
// - Advanced tabs
const sqlLabTab = screen.getByRole('tab', {
- name: /right sql lab adjust how this database will interact with sql lab\./i,
+ name: /expanded sql lab adjust how this database will interact with sql lab\./i,
});
// These are the checkbox SVGs that cover the actual checkboxes
const checkboxOffSVGs = screen.getAllByRole('img', {
@@ -814,7 +814,7 @@ describe('DatabaseModal', () => {
// Click the "Performance" tab
userEvent.click(
screen.getByRole('tab', {
- name: /right performance adjust performance settings of this database\./i,
+ name: /collapsed performance adjust performance settings of this database\./i,
}),
);
expect(await screen.findByText(/step 2 of 2/i)).toBeInTheDocument();
@@ -839,10 +839,10 @@ describe('DatabaseModal', () => {
const advancedTab = screen.getByRole('tab', { name: /advanced/i });
// - Advanced tabs
const sqlLabTab = screen.getByRole('tab', {
- name: /right sql lab adjust how this database will interact with sql lab\./i,
+ name: /collapsed sql lab adjust how this database will interact with sql lab\./i,
});
const performanceTab = screen.getByRole('tab', {
- name: /right performance adjust performance settings of this database\./i,
+ name: /expanded performance adjust performance settings of this database\./i,
});
// ---------- Assertions ----------
@@ -879,7 +879,7 @@ describe('DatabaseModal', () => {
// Click the "Security" tab
userEvent.click(
screen.getByRole('tab', {
- name: /right security add extra connection information\./i,
+ name: /collapsed security add extra connection information\./i,
}),
);
expect(await screen.findByText(/step 2 of 2/i)).toBeInTheDocument();
@@ -904,13 +904,13 @@ describe('DatabaseModal', () => {
const advancedTab = screen.getByRole('tab', { name: /advanced/i });
// - Advanced tabs
const sqlLabTab = screen.getByRole('tab', {
- name: /right sql lab adjust how this database will interact with sql lab\./i,
+ name: /collapsed sql lab adjust how this database will interact with sql lab\./i,
});
const performanceTab = screen.getByRole('tab', {
- name: /right performance adjust performance settings of this database\./i,
+ name: /collapsed performance adjust performance settings of this database\./i,
});
const securityTab = screen.getByRole('tab', {
- name: /right security add extra connection information\./i,
+ name: /expanded security add extra connection information\./i,
});
const allowFileUploadCheckbox = screen.getByRole('checkbox', {
name: /Allow file uploads to database/i,
@@ -965,7 +965,7 @@ describe('DatabaseModal', () => {
// Click the "Security" tab
userEvent.click(
screen.getByRole('tab', {
- name: /right security add extra connection information\./i,
+ name: /collapsed security add extra connection information\./i,
}),
);
// Click the "Allow file uploads" tab
@@ -995,13 +995,13 @@ describe('DatabaseModal', () => {
const advancedTab = screen.getByRole('tab', { name: /advanced/i });
// - Advanced tabs
const sqlLabTab = screen.getByRole('tab', {
- name: /right sql lab adjust how this database will interact with sql lab\./i,
+ name: /collapsed sql lab adjust how this database will interact with sql lab\./i,
});
const performanceTab = screen.getByRole('tab', {
- name: /right performance adjust performance settings of this database\./i,
+ name: /collapsed performance adjust performance settings of this database\./i,
});
const securityTab = screen.getByRole('tab', {
- name: /right security add extra connection information\./i,
+ name: /expanded security add extra connection information\./i,
});
const allowFileUploadText = screen.getByText(
/Allow file uploads to database/i,
@@ -1053,7 +1053,7 @@ describe('DatabaseModal', () => {
// Click the "Other" tab
userEvent.click(
screen.getByRole('tab', {
- name: /right other additional settings\./i,
+ name: /collapsed other additional settings\./i,
}),
);
expect(await screen.findByText(/step 2 of 2/i)).toBeInTheDocument();
@@ -1078,16 +1078,16 @@ describe('DatabaseModal', () => {
const advancedTab = screen.getByRole('tab', { name: /advanced/i });
// - Advanced tabs
const sqlLabTab = screen.getByRole('tab', {
- name: /right sql lab adjust how this database will interact with sql lab\./i,
+ name: /collapsed sql lab adjust how this database will interact with sql lab\./i,
});
const performanceTab = screen.getByRole('tab', {
- name: /right performance adjust performance settings of this database\./i,
+ name: /collapsed performance adjust performance settings of this database\./i,
});
const securityTab = screen.getByRole('tab', {
- name: /right security add extra connection information\./i,
+ name: /collapsed security add extra connection information\./i,
});
const otherTab = screen.getByRole('tab', {
- name: /right other additional settings\./i,
+ name: /expanded other additional settings\./i,
});
// ---------- Assertions ----------
@@ -1484,7 +1484,7 @@ describe('DatabaseModal', () => {
// Click the "Security" tab
userEvent.click(
screen.getByRole('tab', {
- name: /right security add extra connection information\./i,
+ name: /collapsed security add extra connection information\./i,
}),
);
diff --git a/superset-frontend/src/features/databases/DatabaseModal/styles.ts b/superset-frontend/src/features/databases/DatabaseModal/styles.ts
index 182a5ce61a6..7db6312a4b6 100644
--- a/superset-frontend/src/features/databases/DatabaseModal/styles.ts
+++ b/superset-frontend/src/features/databases/DatabaseModal/styles.ts
@@ -26,8 +26,6 @@ const EXPOSE_IN_SQLLAB_FORM_HEIGHT = CTAS_CVAS_SCHEMA_FORM_HEIGHT + 153;
const EXPOSE_ALL_FORM_HEIGHT = EXPOSE_IN_SQLLAB_FORM_HEIGHT + 102;
const MODAL_BODY_HEIGHT = 180.5;
-const anticonHeight = 12;
-
export const no_margin_bottom = css`
margin-bottom: 0;
`;
@@ -83,30 +81,6 @@ export const StyledFormHeader = styled.header`
}
`;
-export const antdCollapseStyles = (theme: SupersetTheme) => css`
- .ant-collapse-header {
- background-color: ${theme.colorBgLayout};
- padding-top: ${theme.sizeUnit * 3.5}px;
- padding-bottom: ${theme.sizeUnit * 2.5}px;
-
- .anticon.ant-collapse-arrow {
- top: calc(50% - ${anticonHeight / 2}px);
- }
- .helper {
- color: ${theme.colors.grayscale.base};
- }
- }
- h4 {
- font-size: 16px;
- margin-top: 0;
- margin-bottom: ${theme.sizeUnit}px;
- }
- p.helper {
- margin: ${theme.sizeUnit * 3}px ${theme.sizeUnit * 4}px;
- margin-left: 0px;
- }
-`;
-
export const antDTabsStyles = css`
.antd5-tabs-top {
margin-top: 0;
diff --git a/superset-frontend/src/features/databases/UploadDataModel/index.tsx b/superset-frontend/src/features/databases/UploadDataModel/index.tsx
index 7be9e56940f..21e24d44fa3 100644
--- a/superset-frontend/src/features/databases/UploadDataModel/index.tsx
+++ b/superset-frontend/src/features/databases/UploadDataModel/index.tsx
@@ -44,7 +44,6 @@ import rison from 'rison';
import withToasts from 'src/components/MessageToasts/withToasts';
import { Form } from 'src/components/Form';
import {
- antdCollapseStyles,
antDModalNoPaddingStyles,
antDModalStyles,
formStyles,
@@ -594,440 +593,473 @@ const UploadDataModal: FunctionComponent = ({
expandIconPosition="right"
accordion
defaultActiveKey="general"
- css={(theme: SupersetTheme) => antdCollapseStyles(theme)}
- >
-
- {t('General information')}
- {t('Upload a file to a database.')}
-
- }
- key="general"
- >
-
-
-
- {}}
- >
- }
- loading={fileLoading}
- >
- {t('Select')}
-
-
-
-
-
-
-
-
-
-
-
-
- {previewUploadedFile && (
-
-
-
-
-
- )}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {isFieldATypeSpecificField('delimiter', type) && (
-
-
-
-
-
-
-
- )}
- {isFieldATypeSpecificField('sheet_name', type) && (
-
-
-
-
-
-
-
- )}
-
-
- {t('File settings')}
-
- {t(
- 'Adjust how spaces, blank lines, null values are handled and other file wide settings.',
+ items={[
+ {
+ key: 'general',
+ label: (
+
+
{t('General information')}
+
{t('Upload a file to a database.')}
+
+ ),
+ children: (
+ <>
+
+
+
+ {}}
+ >
+ }
+ loading={fileLoading}
+ >
+ {t('Select')}
+
+
+
+
+
+
+
+
+
+
+
+
+ {previewUploadedFile && (
+
+
+
+
+
)}
-
-
- }
- key="2"
- >
-
-
-
- {}}
- />
-
-
-
- {isFieldATypeSpecificField('column_dates', type) && (
-
-
-
-
-
-
-
- )}
- {isFieldATypeSpecificField('decimal_character', type) && (
-
-
-
-
-
-
-
- )}
- {isFieldATypeSpecificField('null_values', type) && (
-
-
-
-
-
-
-
- )}
- {isFieldATypeSpecificField('skip_initial_space', type) && (
-
-
-
-
-
-
-
- )}
- {isFieldATypeSpecificField('skip_blank_lines', type) && (
-
-
-
-
-
-
-
- )}
- {isFieldATypeSpecificField('day_first', type) && (
-
-
-
-
-
-
-
- )}
-
-
- {t('Columns')}
-
- {t(
- 'Adjust column settings such as specifying the columns to read, how duplicates are handled, column data types, and more.',
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {isFieldATypeSpecificField('delimiter', type) && (
+
+
+
+
+
+
+
)}
-
-
- }
- key="3"
- >
-
-
-
-
+
+
+
+
+
+
+ )}
+ >
+ ),
+ },
+ {
+ key: 'file-settings',
+ label: (
+
+
{t('File settings')}
+
+ {t(
+ 'Adjust how spaces, blank lines, null values are handled and other file wide settings.',
)}
- />
-
-
-
- {isFieldATypeSpecificField('column_data_types', type) && (
-
-
-
+
+ ),
+ children: (
+ <>
+
+
+
+ {}}
+ />
+
+
+
+ {isFieldATypeSpecificField('column_dates', type) && (
+
+
+
+
+
+
+
+ )}
+ {isFieldATypeSpecificField('decimal_character', type) && (
+
+
+
+
+
+
+
+ )}
+ {isFieldATypeSpecificField('null_values', type) && (
+
+
+
+
+
+
+
+ )}
+ {isFieldATypeSpecificField('skip_initial_space', type) && (
+
+
+
+
+
+
+
+ )}
+ {isFieldATypeSpecificField('skip_blank_lines', type) && (
+
+
+
+
+
+
+
+ )}
+ {isFieldATypeSpecificField('day_first', type) && (
+
+
+
+
+
+
+
+ )}
+ >
+ ),
+ },
+ {
+ key: 'columns',
+ label: (
+
+
{t('Columns')}
+
+ {t(
+ 'Adjust column settings such as specifying the columns to read, how duplicates are handled, column data types, and more.',
)}
- name="column_data_types"
- >
-
-
-
-
- )}
-
-
-
-
-
-
-
- {currentDataframeIndex &&
- isFieldATypeSpecificField('index_column', type) && (
-
-
-
- ({
- value: column,
- label: column,
- }))}
- allowClear
- allowNewOptions
- />
-
-
-
- )}
- {currentDataframeIndex && (
-
-
-
+
+ ),
+ children: (
+ <>
+
+
+
+
+
+
+
+ {isFieldATypeSpecificField('column_data_types', type) && (
+
+
+
+
+
+
+
+ )}
+
+
+
+
+
+
+
+ {currentDataframeIndex &&
+ isFieldATypeSpecificField('index_column', type) && (
+
+
+
+ ({
+ value: column,
+ label: column,
+ }))}
+ allowClear
+ allowNewOptions
+ />
+
+
+
)}
- name="index_label"
- >
-
-
-
-
- )}
-
- {isFieldATypeSpecificField('header_row', type) &&
+ {currentDataframeIndex && (
+
+
+
+
+
+
+
+ )}
+ >
+ ),
+ },
+ ...(isFieldATypeSpecificField('header_row', type) &&
isFieldATypeSpecificField('rows_to_read', type) &&
- isFieldATypeSpecificField('skip_rows', type) && (
-
- {t('Rows')}
-
- {t(
- 'Set header rows and the number of rows to read or skip.',
- )}
-
-
- }
- key="4"
- >
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- )}
-
+ isFieldATypeSpecificField('skip_rows', type)
+ ? [
+ {
+ key: 'rows',
+ label: (
+
+
{t('Rows')}
+
+ {t(
+ 'Set header rows and the number of rows to read or skip.',
+ )}
+
+
+ ),
+ children: (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ),
+ },
+ ]
+ : []),
+ ]}
+ />
);
diff --git a/superset-frontend/src/features/databases/UploadDataModel/styles.ts b/superset-frontend/src/features/databases/UploadDataModel/styles.ts
index da1ced245ca..744a8892e9e 100644
--- a/superset-frontend/src/features/databases/UploadDataModel/styles.ts
+++ b/superset-frontend/src/features/databases/UploadDataModel/styles.ts
@@ -20,7 +20,6 @@ import { FormItem } from 'src/components/Form';
import { css, styled, SupersetTheme } from '@superset-ui/core';
const MODAL_BODY_HEIGHT = 180.5;
-const antIconHeight = 12;
export const StyledFormItem = styled(FormItem)`
${({ theme }) => css`
@@ -37,29 +36,6 @@ export const StyledSwitchContainer = styled.div`
margin-top: 0;
`;
-export const antdCollapseStyles = (theme: SupersetTheme) => css`
- .ant-collapse-header {
- padding-top: ${theme.sizeUnit * 3.5}px;
- padding-bottom: ${theme.sizeUnit * 2.5}px;
- .anticon.ant-collapse-arrow {
- top: calc(50% - ${antIconHeight / 2}px);
- }
- .helper {
- color: ${theme.colors.grayscale.base};
- font-size: ${theme.fontSizeSM}px;
- }
- }
- h4 {
- font-size: ${theme.fontSizeLG}px;
- margin-top: 0;
- margin-bottom: ${theme.sizeUnit}px;
- }
- p.helper {
- margin-bottom: 0;
- padding: 0;
- }
-`;
-
export const antDModalNoPaddingStyles = css`
.antd5-modal-body {
padding-left: 0;
diff --git a/superset-frontend/src/pages/Home/Home.test.tsx b/superset-frontend/src/pages/Home/Home.test.tsx
index e9dd039cbdb..96c4a0cceaf 100644
--- a/superset-frontend/src/pages/Home/Home.test.tsx
+++ b/superset-frontend/src/pages/Home/Home.test.tsx
@@ -177,7 +177,7 @@ test('With sql role - renders all panels on the page on page load', async () =>
test('With sql role - renders distinct recent activities', async () => {
await renderWelcome();
- const recentPanel = screen.getByRole('button', { name: 'right Recents' });
+ const recentPanel = screen.getByRole('button', { name: 'collapsed Recents' });
userEvent.click(recentPanel);
await waitFor(() =>
expect(
diff --git a/superset-frontend/src/pages/Home/index.tsx b/superset-frontend/src/pages/Home/index.tsx
index 52c81c92a5d..e41471533ab 100644
--- a/superset-frontend/src/pages/Home/index.tsx
+++ b/superset-frontend/src/pages/Home/index.tsx
@@ -75,11 +75,12 @@ interface LoadingProps {
cover?: boolean;
}
-const DEFAULT_TAB_ARR = ['2', '3'];
+const DEFAULT_TAB_ARR = ['dashboards', 'charts'];
const WelcomeContainer = styled.div`
.ant-row.menu {
margin-top: -15px;
+
&:after {
content: '';
display: block;
@@ -87,33 +88,29 @@ const WelcomeContainer = styled.div`
margin: 0px ${({ theme }) => theme.sizeUnit * 6}px;
position: relative;
width: 100%;
+
${mq[1]} {
margin-top: 5px;
margin: 0px 2px;
}
}
+
button {
padding: 3px 21px;
}
}
+
.antd5-card-meta-description {
margin-top: ${({ theme }) => theme.sizeUnit}px;
}
+
.antd5-card.ant-card-bordered {
border: 1px solid ${({ theme }) => theme.colors.grayscale.light2};
}
- .ant-collapse-item .ant-collapse-content {
- margin-bottom: ${({ theme }) => theme.sizeUnit * -6}px;
- }
- div.ant-collapse-item:last-child.ant-collapse-item-active
- .ant-collapse-header {
- padding-bottom: ${({ theme }) => theme.sizeUnit * 3}px;
- }
- div.ant-collapse-item:last-child .ant-collapse-header {
- padding-bottom: ${({ theme }) => theme.sizeUnit * 9}px;
- }
+
.loading-cards {
margin-top: ${({ theme }) => theme.sizeUnit * 8}px;
+
.antd5-card-cover > div {
height: 168px;
}
@@ -363,68 +360,81 @@ function Welcome({ user, addDangerToast }: WelcomeProps) {
activeKey={activeState}
onChange={handleCollapse}
ghost
- bigger
- >
-
- {activityData &&
- (activityData[TableTab.Viewed] ||
- activityData[TableTab.Other] ||
- activityData[TableTab.Created]) &&
- activeChild !== 'Loading' ? (
-
- ) : (
-
- )}
-
-
- {!dashboardData || isRecentActivityLoading ? (
-
- ) : (
-
- )}
-
-
- {!chartData || isRecentActivityLoading ? (
-
- ) : (
-
- )}
-
- {canReadSavedQueries && (
-
- {!queryData ? (
-
- ) : (
-
- )}
-
- )}
-
+ items={[
+ {
+ key: 'recents',
+ label: t('Recents'),
+ children:
+ activityData &&
+ (activityData[TableTab.Viewed] ||
+ activityData[TableTab.Other] ||
+ activityData[TableTab.Created]) &&
+ activeChild !== 'Loading' ? (
+
+ ) : (
+
+ ),
+ },
+ {
+ key: 'dashboards',
+ label: t('Dashboards'),
+ children:
+ !dashboardData || isRecentActivityLoading ? (
+
+ ) : (
+
+ ),
+ },
+ {
+ key: 'charts',
+ label: t('Charts'),
+ children:
+ !chartData || isRecentActivityLoading ? (
+
+ ) : (
+
+ ),
+ },
+ ...(canReadSavedQueries
+ ? [
+ {
+ key: 'saved-queries',
+ label: t('Saved queries'),
+ children: !queryData ? (
+
+ ) : (
+
+ ),
+ },
+ ]
+ : []),
+ ]}
+ />
>
)}