refactor(Popover): Upgrade Popover to Antd5 (#31973)
Co-authored-by: Geido <60598000+geido@users.noreply.github.com>
This commit is contained in:
parent
06f8f8e608
commit
0030f46d2d
|
|
@ -161,7 +161,7 @@ describe('Horizontal FilterBar', () => {
|
||||||
cy.getBySel('filter-control-name')
|
cy.getBySel('filter-control-name')
|
||||||
.contains('test_12')
|
.contains('test_12')
|
||||||
.should('not.be.visible');
|
.should('not.be.visible');
|
||||||
cy.get('.ant-popover-inner-content').scrollTo('bottom');
|
cy.get('.antd5-popover-inner').scrollTo('bottom');
|
||||||
cy.getBySel('filter-control-name').contains('test_12').should('be.visible');
|
cy.getBySel('filter-control-name').contains('test_12').should('be.visible');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -226,7 +226,7 @@ describe('Horizontal FilterBar', () => {
|
||||||
cy.getBySel('slice-header').within(() => {
|
cy.getBySel('slice-header').within(() => {
|
||||||
cy.get('.filter-counts').trigger('mouseover');
|
cy.get('.filter-counts').trigger('mouseover');
|
||||||
});
|
});
|
||||||
cy.get('.filterStatusPopover').contains('test_9').click();
|
cy.getBySel('filter-status-popover').contains('test_9').click();
|
||||||
cy.getBySel('dropdown-content').should('be.visible');
|
cy.getBySel('dropdown-content').should('be.visible');
|
||||||
cy.get('.ant-select-focused').should('be.visible');
|
cy.get('.ant-select-focused').should('be.visible');
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -456,19 +456,19 @@ export function applyAdvancedTimeRangeFilterOnDashboard(
|
||||||
endRange?: string,
|
endRange?: string,
|
||||||
) {
|
) {
|
||||||
cy.get('.control-label').contains('RANGE TYPE').should('be.visible');
|
cy.get('.control-label').contains('RANGE TYPE').should('be.visible');
|
||||||
cy.get('.ant-popover-content .ant-select-selector')
|
cy.get('.antd5-popover-content .ant-select-selector')
|
||||||
.should('be.visible')
|
.should('be.visible')
|
||||||
.click();
|
.click();
|
||||||
cy.get(`[label="Advanced"]`).should('be.visible').click();
|
cy.get(`[label="Advanced"]`).should('be.visible').click();
|
||||||
cy.get('.section-title').contains('Advanced Time Range').should('be.visible');
|
cy.get('.section-title').contains('Advanced Time Range').should('be.visible');
|
||||||
if (startRange) {
|
if (startRange) {
|
||||||
cy.get('.ant-popover-inner-content')
|
cy.get('.antd5-popover-inner-content')
|
||||||
.find('[class^=ant-input]')
|
.find('[class^=ant-input]')
|
||||||
.first()
|
.first()
|
||||||
.type(`${startRange}`);
|
.type(`${startRange}`);
|
||||||
}
|
}
|
||||||
if (endRange) {
|
if (endRange) {
|
||||||
cy.get('.ant-popover-inner-content')
|
cy.get('.antd5-popover-inner-content')
|
||||||
.find('[class^=ant-input]')
|
.find('[class^=ant-input]')
|
||||||
.last()
|
.last()
|
||||||
.type(`${endRange}`);
|
.type(`${endRange}`);
|
||||||
|
|
|
||||||
|
|
@ -555,7 +555,7 @@ export const exploreView = {
|
||||||
timeSection: {
|
timeSection: {
|
||||||
timeRangeFilter: dataTestLocator('time-range-trigger'),
|
timeRangeFilter: dataTestLocator('time-range-trigger'),
|
||||||
timeRangeFilterModal: {
|
timeRangeFilterModal: {
|
||||||
container: '.ant-popover-content',
|
container: '.antd5-popover-content',
|
||||||
footer: '.footer',
|
footer: '.footer',
|
||||||
cancelButton: dataTestLocator('cancel-button'),
|
cancelButton: dataTestLocator('cancel-button'),
|
||||||
configureLastTimeRange: {
|
configureLastTimeRange: {
|
||||||
|
|
|
||||||
|
|
@ -17,9 +17,9 @@
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { Popover } from 'antd';
|
import { Popover } from 'antd-v5';
|
||||||
import type ReactAce from 'react-ace';
|
import type ReactAce from 'react-ace';
|
||||||
import type { PopoverProps } from 'antd/lib/popover';
|
import type { PopoverProps } from 'antd-v5/lib/popover';
|
||||||
import { CalculatorOutlined } from '@ant-design/icons';
|
import { CalculatorOutlined } from '@ant-design/icons';
|
||||||
import { css, styled, useTheme, t } from '@superset-ui/core';
|
import { css, styled, useTheme, t } from '@superset-ui/core';
|
||||||
|
|
||||||
|
|
@ -72,7 +72,7 @@ export const SQLPopover = (props: PopoverProps & { sqlExpression: string }) => {
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
placement="bottomLeft"
|
placement="bottomLeft"
|
||||||
arrowPointAtCenter
|
arrow={{ pointAtCenter: true }}
|
||||||
title={t('SQL expression')}
|
title={t('SQL expression')}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -39,14 +39,18 @@ export const GlobalStyles = () => (
|
||||||
.echarts-tooltip[style*='visibility: hidden'] {
|
.echarts-tooltip[style*='visibility: hidden'] {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ant Design is applying inline z-index styles causing troubles
|
// Ant Design is applying inline z-index styles causing troubles
|
||||||
// TODO: Remove z-indexes when Ant Design is fully upgraded to v5
|
// TODO: Remove z-indexes when Ant Design is fully upgraded to v5
|
||||||
// Prefer vanilla Ant Design z-indexes that should work out of the box
|
// Prefer vanilla Ant Design z-indexes that should work out of the box
|
||||||
.ant-popover,
|
.antd5-dropdown,
|
||||||
|
.ant-dropdown,
|
||||||
.ant-select-dropdown,
|
.ant-select-dropdown,
|
||||||
.antd5-modal-wrap,
|
.antd5-modal-wrap,
|
||||||
.antd5-modal-mask,
|
.antd5-modal-mask,
|
||||||
.antd5-picker-dropdown {
|
.antd5-picker-dropdown,
|
||||||
|
.ant-popover,
|
||||||
|
.antd5-popover {
|
||||||
z-index: ${theme.zIndex.max} !important;
|
z-index: ${theme.zIndex.max} !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -137,7 +137,6 @@ const DropdownContainer = forwardRef(
|
||||||
const { current } = ref;
|
const { current } = ref;
|
||||||
const [itemsWidth, setItemsWidth] = useState<number[]>([]);
|
const [itemsWidth, setItemsWidth] = useState<number[]>([]);
|
||||||
const [popoverVisible, setPopoverVisible] = useState(false);
|
const [popoverVisible, setPopoverVisible] = useState(false);
|
||||||
|
|
||||||
// We use React.useState to be able to mock the state in Jest
|
// We use React.useState to be able to mock the state in Jest
|
||||||
const [overflowingIndex, setOverflowingIndex] = useState<number>(-1);
|
const [overflowingIndex, setOverflowingIndex] = useState<number>(-1);
|
||||||
|
|
||||||
|
|
@ -181,11 +180,13 @@ const DropdownContainer = forwardRef(
|
||||||
);
|
);
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
|
if (popoverVisible) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const container = current?.children.item(0);
|
const container = current?.children.item(0);
|
||||||
if (container) {
|
if (container) {
|
||||||
const { children } = container;
|
const { children } = container;
|
||||||
const childrenArray = Array.from(children);
|
const childrenArray = Array.from(children);
|
||||||
|
|
||||||
// If items length change, add all items to the container
|
// If items length change, add all items to the container
|
||||||
// and recalculate the widths
|
// and recalculate the widths
|
||||||
if (itemsWidth.length !== items.length) {
|
if (itemsWidth.length !== items.length) {
|
||||||
|
|
@ -341,11 +342,7 @@ const DropdownContainer = forwardRef(
|
||||||
<>
|
<>
|
||||||
<Global
|
<Global
|
||||||
styles={css`
|
styles={css`
|
||||||
.ant-popover-inner-content {
|
.antd5-popover-inner {
|
||||||
max-height: ${MAX_HEIGHT}px;
|
|
||||||
overflow: ${showOverflow ? 'auto' : 'visible'};
|
|
||||||
padding: ${theme.gridUnit * 3}px ${theme.gridUnit * 4}px;
|
|
||||||
|
|
||||||
// Some OS versions only show the scroll when hovering.
|
// Some OS versions only show the scroll when hovering.
|
||||||
// These settings will make the scroll always visible.
|
// These settings will make the scroll always visible.
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
|
|
@ -365,11 +362,16 @@ const DropdownContainer = forwardRef(
|
||||||
}
|
}
|
||||||
`}
|
`}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Popover
|
<Popover
|
||||||
|
overlayInnerStyle={{
|
||||||
|
maxHeight: `${MAX_HEIGHT}px`,
|
||||||
|
overflow: showOverflow ? 'auto' : 'visible',
|
||||||
|
}}
|
||||||
content={popoverContent}
|
content={popoverContent}
|
||||||
trigger="click"
|
trigger="click"
|
||||||
visible={popoverVisible}
|
open={popoverVisible}
|
||||||
onVisibleChange={visible => setPopoverVisible(visible)}
|
onOpenChange={visible => setPopoverVisible(visible)}
|
||||||
placement="bottom"
|
placement="bottom"
|
||||||
forceRender={forceRender}
|
forceRender={forceRender}
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,7 @@
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import Button from 'src/components/Button';
|
import Button from 'src/components/Button';
|
||||||
import { PopoverProps } from 'antd/lib/popover';
|
import Popover, { PopoverProps } from 'src/components/Popover';
|
||||||
import Popover from '.';
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Popover',
|
title: 'Popover',
|
||||||
|
|
@ -66,6 +65,8 @@ const TRIGGERS = {
|
||||||
InteractivePopover.args = {
|
InteractivePopover.args = {
|
||||||
content: 'Popover sample content',
|
content: 'Popover sample content',
|
||||||
title: 'Popover title',
|
title: 'Popover title',
|
||||||
|
arrow: true,
|
||||||
|
color: '#fff',
|
||||||
};
|
};
|
||||||
|
|
||||||
InteractivePopover.argTypes = {
|
InteractivePopover.argTypes = {
|
||||||
|
|
@ -79,4 +80,14 @@ InteractivePopover.argTypes = {
|
||||||
control: { type: 'select' },
|
control: { type: 'select' },
|
||||||
options: TRIGGERS.options,
|
options: TRIGGERS.options,
|
||||||
},
|
},
|
||||||
|
arrow: {
|
||||||
|
name: 'arrow',
|
||||||
|
control: { type: 'boolean' },
|
||||||
|
description: "Change arrow's visible state",
|
||||||
|
},
|
||||||
|
color: {
|
||||||
|
name: 'color',
|
||||||
|
control: { type: 'color' },
|
||||||
|
description: 'The background color of the popover.',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ import userEvent from '@testing-library/user-event';
|
||||||
import { supersetTheme } from '@superset-ui/core';
|
import { supersetTheme } from '@superset-ui/core';
|
||||||
import Icons from 'src/components/Icons';
|
import Icons from 'src/components/Icons';
|
||||||
import Button from 'src/components/Button';
|
import Button from 'src/components/Button';
|
||||||
import Popover from '.';
|
import Popover from 'src/components/Popover';
|
||||||
|
|
||||||
test('should render', () => {
|
test('should render', () => {
|
||||||
const { container } = render(<Popover />);
|
const { container } = render(<Popover />);
|
||||||
|
|
@ -29,12 +29,12 @@ test('should render', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should render a title when visible', () => {
|
test('should render a title when visible', () => {
|
||||||
render(<Popover title="Popover title" visible />);
|
render(<Popover title="Popover title" open />);
|
||||||
expect(screen.getByText('Popover title')).toBeInTheDocument();
|
expect(screen.getByText('Popover title')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should render some content when visible', () => {
|
test('should render some content when visible', () => {
|
||||||
render(<Popover content="Content sample" visible />);
|
render(<Popover content="Content sample" open />);
|
||||||
expect(screen.getByText('Content sample')).toBeInTheDocument();
|
expect(screen.getByText('Content sample')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -61,22 +61,22 @@ test('renders with icon child', async () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test('fires an event when visibility is changed', async () => {
|
test('fires an event when visibility is changed', async () => {
|
||||||
const onVisibleChange = jest.fn();
|
const onOpenChange = jest.fn();
|
||||||
render(
|
render(
|
||||||
<Popover
|
<Popover
|
||||||
content="Content sample"
|
content="Content sample"
|
||||||
title="Popover title"
|
title="Popover title"
|
||||||
onVisibleChange={onVisibleChange}
|
onOpenChange={onOpenChange}
|
||||||
>
|
>
|
||||||
<Button>Hover me</Button>
|
<Button>Hover me</Button>
|
||||||
</Popover>,
|
</Popover>,
|
||||||
);
|
);
|
||||||
userEvent.hover(screen.getByRole('button'));
|
userEvent.hover(screen.getByRole('button'));
|
||||||
await waitFor(() => expect(onVisibleChange).toHaveBeenCalledTimes(1));
|
await waitFor(() => expect(onOpenChange).toHaveBeenCalledTimes(1));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('renders with theme', () => {
|
test('renders with theme', () => {
|
||||||
render(<Popover content="Content sample" title="Popover title" visible />);
|
render(<Popover content="Content sample" title="Popover title" open />);
|
||||||
const title = screen.getByText('Popover title');
|
const title = screen.getByText('Popover title');
|
||||||
expect(title).toHaveStyle({
|
expect(title).toHaveStyle({
|
||||||
fontSize: supersetTheme.gridUnit * 3.5,
|
fontSize: supersetTheme.gridUnit * 3.5,
|
||||||
|
|
|
||||||
|
|
@ -1,27 +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 { Popover as AntdPopover } from 'antd';
|
|
||||||
import type { PopoverProps as AntdPopoverProps } from 'antd/lib/popover';
|
|
||||||
|
|
||||||
export interface PopoverProps extends AntdPopoverProps {
|
|
||||||
forceRender?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const Popover = (props: PopoverProps) => <AntdPopover {...props} />;
|
|
||||||
|
|
@ -16,9 +16,13 @@
|
||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
export type { PopoverProps } from 'antd/lib/popover';
|
import { Popover as AntdPopover } from 'antd-v5';
|
||||||
export type { TooltipPlacement } from 'antd/lib/tooltip';
|
import { PopoverProps as AntdPopoverProps } from 'antd-v5/lib/popover';
|
||||||
|
|
||||||
// Eventually Popover can be wrapped and customized in this file
|
export interface PopoverProps extends AntdPopoverProps {
|
||||||
// for now we're just redirecting
|
forceRender?: boolean;
|
||||||
export { Popover as default } from './Popover';
|
}
|
||||||
|
|
||||||
|
const Popover = (props: PopoverProps) => <AntdPopover {...props} />;
|
||||||
|
|
||||||
|
export default Popover;
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ function HeaderWithRadioGroup(props: HeaderWithRadioGroupProps) {
|
||||||
>
|
>
|
||||||
<Popover
|
<Popover
|
||||||
trigger="click"
|
trigger="click"
|
||||||
visible={popoverVisible}
|
open={popoverVisible}
|
||||||
content={
|
content={
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
|
|
@ -72,7 +72,7 @@ function HeaderWithRadioGroup(props: HeaderWithRadioGroupProps) {
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
placement="bottomLeft"
|
placement="bottomLeft"
|
||||||
arrowPointAtCenter
|
arrow={{ pointAtCenter: true }}
|
||||||
>
|
>
|
||||||
<Icons.SettingOutlined
|
<Icons.SettingOutlined
|
||||||
iconSize="m"
|
iconSize="m"
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,6 @@ import {
|
||||||
useTheme,
|
useTheme,
|
||||||
useElementOnScreen,
|
useElementOnScreen,
|
||||||
} from '@superset-ui/core';
|
} from '@superset-ui/core';
|
||||||
import { Global } from '@emotion/react';
|
|
||||||
import { useDispatch, useSelector } from 'react-redux';
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
import ErrorBoundary from 'src/components/ErrorBoundary';
|
import ErrorBoundary from 'src/components/ErrorBoundary';
|
||||||
import BuilderComponentPane from 'src/dashboard/components/BuilderComponentPane';
|
import BuilderComponentPane from 'src/dashboard/components/BuilderComponentPane';
|
||||||
|
|
@ -653,13 +652,6 @@ const DashboardBuilder = () => {
|
||||||
</Droppable>
|
</Droppable>
|
||||||
</StyledHeader>
|
</StyledHeader>
|
||||||
<StyledContent fullSizeChartId={fullSizeChartId}>
|
<StyledContent fullSizeChartId={fullSizeChartId}>
|
||||||
<Global
|
|
||||||
styles={css`
|
|
||||||
// @z-index-above-dashboard-header (100) + 1 = 101
|
|
||||||
${fullSizeChartId &&
|
|
||||||
`div > .filterStatusPopover.ant-popover{z-index: 101}`}
|
|
||||||
`}
|
|
||||||
/>
|
|
||||||
{!editMode &&
|
{!editMode &&
|
||||||
!topLevelTabs &&
|
!topLevelTabs &&
|
||||||
dashboardLayout[DASHBOARD_GRID_ID]?.children?.length === 0 && (
|
dashboardLayout[DASHBOARD_GRID_ID]?.children?.length === 0 && (
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,7 @@
|
||||||
import { RefObject, useEffect, useRef, KeyboardEvent } from 'react';
|
import { RefObject, useEffect, useRef, KeyboardEvent } from 'react';
|
||||||
|
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
import { Global, css } from '@emotion/react';
|
import { t, useTheme } from '@superset-ui/core';
|
||||||
import { t } from '@superset-ui/core';
|
|
||||||
import Popover from 'src/components/Popover';
|
import Popover from 'src/components/Popover';
|
||||||
import {
|
import {
|
||||||
FiltersContainer,
|
FiltersContainer,
|
||||||
|
|
@ -120,7 +119,7 @@ const DetailsPanelPopover = ({
|
||||||
|
|
||||||
const indicatorKey = (indicator: Indicator): string =>
|
const indicatorKey = (indicator: Indicator): string =>
|
||||||
`${indicator.column} - ${indicator.name}`;
|
`${indicator.column} - ${indicator.name}`;
|
||||||
|
const theme = useTheme();
|
||||||
const content = (
|
const content = (
|
||||||
<FiltersDetailsContainer
|
<FiltersDetailsContainer
|
||||||
ref={popoverContentRef}
|
ref={popoverContentRef}
|
||||||
|
|
@ -129,54 +128,6 @@ const DetailsPanelPopover = ({
|
||||||
onKeyDown={handleKeyDown}
|
onKeyDown={handleKeyDown}
|
||||||
role="menu"
|
role="menu"
|
||||||
>
|
>
|
||||||
<Global
|
|
||||||
styles={theme => css`
|
|
||||||
.filterStatusPopover {
|
|
||||||
.ant-popover-inner {
|
|
||||||
background-color: ${theme.colors.grayscale.dark2}cc;
|
|
||||||
.ant-popover-inner-content {
|
|
||||||
padding: ${theme.gridUnit * 2}px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&.ant-popover-placement-bottom,
|
|
||||||
&.ant-popover-placement-bottomLeft,
|
|
||||||
&.ant-popover-placement-bottomRight {
|
|
||||||
& > .ant-popover-content > .ant-popover-arrow {
|
|
||||||
border-top-color: ${theme.colors.grayscale.dark2}cc;
|
|
||||||
border-left-color: ${theme.colors.grayscale.dark2}cc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&.ant-popover-placement-top,
|
|
||||||
&.ant-popover-placement-topLeft,
|
|
||||||
&.ant-popover-placement-topRight {
|
|
||||||
& > .ant-popover-content > .ant-popover-arrow {
|
|
||||||
border-bottom-color: ${theme.colors.grayscale.dark2}cc;
|
|
||||||
border-right-color: ${theme.colors.grayscale.dark2}cc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&.ant-popover-placement-left,
|
|
||||||
&.ant-popover-placement-leftTop,
|
|
||||||
&.ant-popover-placement-leftBottom {
|
|
||||||
& > .ant-popover-content > .ant-popover-arrow {
|
|
||||||
border-top-color: ${theme.colors.grayscale.dark2}cc;
|
|
||||||
border-right-color: ${theme.colors.grayscale.dark2}cc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&.ant-popover-placement-right,
|
|
||||||
&.ant-popover-placement-rightTop,
|
|
||||||
&.ant-popover-placement-rightBottom {
|
|
||||||
& > .ant-popover-content > .ant-popover-arrow {
|
|
||||||
border-bottom-color: ${theme.colors.grayscale.dark2}cc;
|
|
||||||
border-left-color: ${theme.colors.grayscale.dark2}cc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&.ant-popover {
|
|
||||||
color: ${theme.colors.grayscale.light4};
|
|
||||||
z-index: 99;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`}
|
|
||||||
/>
|
|
||||||
<div>
|
<div>
|
||||||
{appliedCrossFilterIndicators.length ? (
|
{appliedCrossFilterIndicators.length ? (
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -224,12 +175,13 @@ const DetailsPanelPopover = ({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Popover
|
<Popover
|
||||||
overlayClassName="filterStatusPopover"
|
color={`${theme.colors.grayscale.dark2}cc`}
|
||||||
content={content}
|
content={content}
|
||||||
visible={popoverVisible}
|
open={popoverVisible}
|
||||||
onVisibleChange={handleVisibility}
|
onOpenChange={handleVisibility}
|
||||||
placement="bottomRight"
|
placement="bottomRight"
|
||||||
trigger={['hover']}
|
trigger={['hover']}
|
||||||
|
data-test="filter-status-popover"
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</Popover>
|
</Popover>
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,6 @@ export const FilterCard = ({
|
||||||
placement,
|
placement,
|
||||||
}: FilterCardProps) => {
|
}: FilterCardProps) => {
|
||||||
const [internalIsVisible, setInternalIsVisible] = useState(false);
|
const [internalIsVisible, setInternalIsVisible] = useState(false);
|
||||||
|
|
||||||
const hidePopover = () => {
|
const hidePopover = () => {
|
||||||
setInternalIsVisible(false);
|
setInternalIsVisible(false);
|
||||||
};
|
};
|
||||||
|
|
@ -43,15 +42,18 @@ export const FilterCard = ({
|
||||||
return (
|
return (
|
||||||
<Popover
|
<Popover
|
||||||
placement={placement}
|
placement={placement}
|
||||||
overlayClassName="filter-card-popover"
|
overlayStyle={{
|
||||||
|
width: '240px',
|
||||||
|
}}
|
||||||
mouseEnterDelay={0.2}
|
mouseEnterDelay={0.2}
|
||||||
mouseLeaveDelay={0.2}
|
mouseLeaveDelay={0.2}
|
||||||
onVisibleChange={visible => {
|
onOpenChange={visible => {
|
||||||
setInternalIsVisible(externalIsVisible && visible);
|
setInternalIsVisible(externalIsVisible && visible);
|
||||||
}}
|
}}
|
||||||
visible={externalIsVisible && internalIsVisible}
|
open={externalIsVisible && internalIsVisible}
|
||||||
content={<FilterCardContent filter={filter} hidePopover={hidePopover} />}
|
content={<FilterCardContent filter={filter} hidePopover={hidePopover} />}
|
||||||
getPopupContainer={getPopupContainer ?? (() => document.body)}
|
getPopupContainer={getPopupContainer ?? (() => document.body)}
|
||||||
|
arrow={false}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</Popover>
|
</Popover>
|
||||||
|
|
|
||||||
|
|
@ -66,32 +66,6 @@ export const chartHeaderStyles = (theme: SupersetTheme) => css`
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const filterCardPopoverStyle = (theme: SupersetTheme) => css`
|
export const filterCardPopoverStyle = (theme: SupersetTheme) => css`
|
||||||
.filter-card-popover {
|
|
||||||
width: 240px;
|
|
||||||
padding: 0;
|
|
||||||
border-radius: 4px;
|
|
||||||
|
|
||||||
&.ant-popover-placement-bottom {
|
|
||||||
padding-top: ${theme.gridUnit}px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.ant-popover-placement-left {
|
|
||||||
padding-right: ${theme.gridUnit * 3}px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ant-popover-inner {
|
|
||||||
box-shadow: 0 0 8px rgb(0 0 0 / 10%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.ant-popover-inner-content {
|
|
||||||
padding: ${theme.gridUnit * 4}px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ant-popover-arrow {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.filter-card-tooltip {
|
.filter-card-tooltip {
|
||||||
&.antd5-tooltip-placement-bottom {
|
&.antd5-tooltip-placement-bottom {
|
||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,6 @@ import {
|
||||||
TimeFormats,
|
TimeFormats,
|
||||||
useTheme,
|
useTheme,
|
||||||
} from '@superset-ui/core';
|
} from '@superset-ui/core';
|
||||||
import { Global } from '@emotion/react';
|
|
||||||
import { Column } from 'react-table';
|
import { Column } from 'react-table';
|
||||||
import { debounce } from 'lodash';
|
import { debounce } from 'lodash';
|
||||||
import { Input } from 'src/components/Input';
|
import { Input } from 'src/components/Input';
|
||||||
|
|
@ -195,13 +194,6 @@ const DataTableTemporalHeaderCell = ({
|
||||||
datasourceId ? ( // eslint-disable-next-line jsx-a11y/no-static-element-interactions
|
datasourceId ? ( // eslint-disable-next-line jsx-a11y/no-static-element-interactions
|
||||||
<FormatPickerContainer onClick={e => e.stopPropagation()}>
|
<FormatPickerContainer onClick={e => e.stopPropagation()}>
|
||||||
{/* hack to disable click propagation from popover content to table header, which triggers sorting column */}
|
{/* hack to disable click propagation from popover content to table header, which triggers sorting column */}
|
||||||
<Global
|
|
||||||
styles={css`
|
|
||||||
.column-formatting-popover .ant-popover-inner-content {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
`}
|
|
||||||
/>
|
|
||||||
<FormatPickerLabel>{t('Column Formatting')}</FormatPickerLabel>
|
<FormatPickerLabel>{t('Column Formatting')}</FormatPickerLabel>
|
||||||
<FormatPicker
|
<FormatPicker
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
|
|
@ -219,11 +211,10 @@ const DataTableTemporalHeaderCell = ({
|
||||||
return datasourceId ? (
|
return datasourceId ? (
|
||||||
<span>
|
<span>
|
||||||
<Popover
|
<Popover
|
||||||
overlayClassName="column-formatting-popover"
|
|
||||||
trigger="click"
|
trigger="click"
|
||||||
content={overlayContent}
|
content={overlayContent}
|
||||||
placement="bottomLeft"
|
placement="bottomLeft"
|
||||||
arrowPointAtCenter
|
arrow={{ pointAtCenter: true }}
|
||||||
>
|
>
|
||||||
<Icons.SettingOutlined
|
<Icons.SettingOutlined
|
||||||
iconSize="m"
|
iconSize="m"
|
||||||
|
|
|
||||||
|
|
@ -231,8 +231,8 @@ class AnnotationLayerControl extends PureComponent<Props, PopoverState> {
|
||||||
anno,
|
anno,
|
||||||
this.props.annotationError[anno.name],
|
this.props.annotationError[anno.name],
|
||||||
)}
|
)}
|
||||||
visible={this.state.popoverVisible[i]}
|
open={this.state.popoverVisible[i]}
|
||||||
onVisibleChange={visible => this.handleVisibleChange(visible, i)}
|
onOpenChange={visible => this.handleVisibleChange(visible, i)}
|
||||||
>
|
>
|
||||||
<CustomListItem selectable>
|
<CustomListItem selectable>
|
||||||
<span>{anno.name}</span>
|
<span>{anno.name}</span>
|
||||||
|
|
@ -254,9 +254,9 @@ class AnnotationLayerControl extends PureComponent<Props, PopoverState> {
|
||||||
'',
|
'',
|
||||||
)}
|
)}
|
||||||
title={t('Add annotation layer')}
|
title={t('Add annotation layer')}
|
||||||
visible={this.state.popoverVisible[addLayerPopoverKey]}
|
open={this.state.popoverVisible[addLayerPopoverKey]}
|
||||||
destroyTooltipOnHide
|
destroyTooltipOnHide
|
||||||
onVisibleChange={visible =>
|
onOpenChange={visible =>
|
||||||
this.handleVisibleChange(visible, addLayerPopoverKey)
|
this.handleVisibleChange(visible, addLayerPopoverKey)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -51,8 +51,8 @@ export const FormattingPopover = ({
|
||||||
extraColorChoices={extraColorChoices}
|
extraColorChoices={extraColorChoices}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
visible={visible}
|
open={visible}
|
||||||
onVisibleChange={setVisible}
|
onOpenChange={setVisible}
|
||||||
trigger={['click']}
|
trigger={['click']}
|
||||||
overlayStyle={{ width: '450px' }}
|
overlayStyle={{ width: '450px' }}
|
||||||
{...props}
|
{...props}
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ReactNode } from 'react';
|
import { ReactNode } from 'react';
|
||||||
import { PopoverProps } from 'antd/lib/popover';
|
import { PopoverProps } from 'src/components/Popover';
|
||||||
import { Comparator, ControlComponentProps } from '@superset-ui/chart-controls';
|
import { Comparator, ControlComponentProps } from '@superset-ui/chart-controls';
|
||||||
|
|
||||||
export type ConditionalFormattingConfig = {
|
export type ConditionalFormattingConfig = {
|
||||||
|
|
|
||||||
|
|
@ -47,9 +47,9 @@ const ContourPopoverTrigger = ({
|
||||||
<ControlPopover
|
<ControlPopover
|
||||||
trigger="click"
|
trigger="click"
|
||||||
content={popoverContent}
|
content={popoverContent}
|
||||||
defaultVisible={visible}
|
defaultOpen={visible}
|
||||||
visible={visible}
|
open={visible}
|
||||||
onVisibleChange={setVisibility}
|
onOpenChange={setVisibility}
|
||||||
destroyTooltipOnHide
|
destroyTooltipOnHide
|
||||||
>
|
>
|
||||||
{props.children}
|
{props.children}
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@ test('Should lock the vertical scroll when the popover is visible', () => {
|
||||||
test('Should place popover at the top', async () => {
|
test('Should place popover at the top', async () => {
|
||||||
const { setStateMock } = setupTest({
|
const { setStateMock } = setupTest({
|
||||||
...createProps(),
|
...createProps(),
|
||||||
getVisibilityRatio: () => 0.2,
|
getVisibilityRatio: () => ({ yRatio: 0.2, xRatio: 0.3 }),
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(screen.getByTestId('control-popover')).toBeInTheDocument();
|
expect(screen.getByTestId('control-popover')).toBeInTheDocument();
|
||||||
|
|
@ -102,21 +102,21 @@ test('Should place popover at the top', async () => {
|
||||||
test('Should place popover at the center', async () => {
|
test('Should place popover at the center', async () => {
|
||||||
const { setStateMock } = setupTest({
|
const { setStateMock } = setupTest({
|
||||||
...createProps(),
|
...createProps(),
|
||||||
getVisibilityRatio: () => 0.5,
|
getVisibilityRatio: () => ({ yRatio: 0.5, xRatio: 0.7 }),
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(screen.getByTestId('control-popover')).toBeInTheDocument();
|
expect(screen.getByTestId('control-popover')).toBeInTheDocument();
|
||||||
userEvent.click(screen.getByTestId('control-popover'));
|
userEvent.click(screen.getByTestId('control-popover'));
|
||||||
|
|
||||||
await waitFor(() => {
|
await waitFor(() => {
|
||||||
expect(setStateMock).toHaveBeenCalledWith('right');
|
expect(setStateMock).toHaveBeenCalledWith('left');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Should place popover at the bottom', async () => {
|
test('Should place popover at the bottom', async () => {
|
||||||
const { setStateMock } = setupTest({
|
const { setStateMock } = setupTest({
|
||||||
...createProps(),
|
...createProps(),
|
||||||
getVisibilityRatio: () => 0.7,
|
getVisibilityRatio: () => ({ yRatio: 0.9, xRatio: 0.2 }),
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(screen.getByTestId('control-popover')).toBeInTheDocument();
|
expect(screen.getByTestId('control-popover')).toBeInTheDocument();
|
||||||
|
|
@ -162,7 +162,7 @@ test('Controlled mode', async () => {
|
||||||
const baseProps = {
|
const baseProps = {
|
||||||
...createProps(),
|
...createProps(),
|
||||||
destroyTooltipOnHide: true,
|
destroyTooltipOnHide: true,
|
||||||
visible: false,
|
open: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
const { rerender } = setupTest(baseProps);
|
const { rerender } = setupTest(baseProps);
|
||||||
|
|
@ -170,7 +170,7 @@ test('Controlled mode', async () => {
|
||||||
expect(screen.getByTestId('control-popover')).toBeInTheDocument();
|
expect(screen.getByTestId('control-popover')).toBeInTheDocument();
|
||||||
expect(screen.queryByText('Control Popover Test')).not.toBeInTheDocument();
|
expect(screen.queryByText('Control Popover Test')).not.toBeInTheDocument();
|
||||||
|
|
||||||
rerender(<TestComponent {...baseProps} visible />);
|
rerender(<TestComponent {...baseProps} open />);
|
||||||
expect(await screen.findByText('Control Popover Test')).toBeInTheDocument();
|
expect(await screen.findByText('Control Popover Test')).toBeInTheDocument();
|
||||||
|
|
||||||
rerender(<TestComponent {...baseProps} />);
|
rerender(<TestComponent {...baseProps} />);
|
||||||
|
|
|
||||||
|
|
@ -21,49 +21,70 @@ import React, { FC, useCallback, useRef, useEffect, useState } from 'react';
|
||||||
|
|
||||||
import Popover, {
|
import Popover, {
|
||||||
PopoverProps as BasePopoverProps,
|
PopoverProps as BasePopoverProps,
|
||||||
TooltipPlacement,
|
|
||||||
} from 'src/components/Popover';
|
} from 'src/components/Popover';
|
||||||
|
|
||||||
|
import { TooltipPlacement } from 'src/components/Tooltip';
|
||||||
|
|
||||||
const sectionContainerId = 'controlSections';
|
const sectionContainerId = 'controlSections';
|
||||||
export const getSectionContainerElement = () =>
|
export const getSectionContainerElement = () =>
|
||||||
document.getElementById(sectionContainerId)?.lastElementChild as HTMLElement;
|
document.getElementById(sectionContainerId)?.lastElementChild as HTMLElement;
|
||||||
|
|
||||||
const getElementYVisibilityRatioOnContainer = (node: HTMLElement) => {
|
const getElementVisibilityRatio = (node?: HTMLElement) => {
|
||||||
const containerHeight = window?.innerHeight;
|
const containerHeight = window?.innerHeight;
|
||||||
const nodePositionInViewport = node?.getBoundingClientRect()?.top;
|
const containerWidth = window?.innerWidth;
|
||||||
if (!containerHeight || !nodePositionInViewport) {
|
|
||||||
return 0;
|
const rect = node?.getBoundingClientRect();
|
||||||
|
if (!containerHeight || !containerWidth || !rect?.top) {
|
||||||
|
return { yRatio: 0, xRatio: 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
return nodePositionInViewport / containerHeight;
|
const yRatio = rect.top / containerHeight;
|
||||||
|
const xRatio = rect.left / containerWidth;
|
||||||
|
return { yRatio, xRatio };
|
||||||
};
|
};
|
||||||
|
|
||||||
export type PopoverProps = BasePopoverProps & {
|
export type PopoverProps = BasePopoverProps & {
|
||||||
getVisibilityRatio?: typeof getElementYVisibilityRatioOnContainer;
|
getVisibilityRatio?: typeof getElementVisibilityRatio;
|
||||||
};
|
};
|
||||||
|
|
||||||
const ControlPopover: FC<PopoverProps> = ({
|
const ControlPopover: FC<PopoverProps> = ({
|
||||||
getPopupContainer,
|
getPopupContainer,
|
||||||
getVisibilityRatio = getElementYVisibilityRatioOnContainer,
|
getVisibilityRatio = getElementVisibilityRatio,
|
||||||
visible: visibleProp,
|
open: visibleProp,
|
||||||
destroyTooltipOnHide = false,
|
destroyTooltipOnHide = false,
|
||||||
|
placement: initialPlacement = 'right',
|
||||||
...props
|
...props
|
||||||
}) => {
|
}) => {
|
||||||
const triggerElementRef = useRef<HTMLElement>();
|
const triggerElementRef = useRef<HTMLElement>();
|
||||||
|
|
||||||
const [visible, setVisible] = useState(
|
const [visible, setVisible] = useState(
|
||||||
visibleProp === undefined ? props.defaultVisible : visibleProp,
|
visibleProp === undefined ? props.defaultOpen : visibleProp,
|
||||||
);
|
);
|
||||||
const [placement, setPlacement] = React.useState<TooltipPlacement>('right');
|
const [placement, setPlacement] =
|
||||||
|
React.useState<TooltipPlacement>(initialPlacement);
|
||||||
|
|
||||||
const calculatePlacement = useCallback(() => {
|
const calculatePlacement = useCallback(() => {
|
||||||
const visibilityRatio = getVisibilityRatio(triggerElementRef.current!);
|
if (!triggerElementRef.current) return;
|
||||||
if (visibilityRatio < 0.35 && placement !== 'rightTop') {
|
|
||||||
setPlacement('rightTop');
|
const { yRatio, xRatio } = getVisibilityRatio(triggerElementRef.current);
|
||||||
} else if (visibilityRatio > 0.65 && placement !== 'rightBottom') {
|
|
||||||
setPlacement('rightBottom');
|
const horizontalPlacement =
|
||||||
} else {
|
xRatio < 0.35 ? 'right' : xRatio > 0.65 ? 'left' : '';
|
||||||
setPlacement('right');
|
|
||||||
|
const verticalPlacement = (() => {
|
||||||
|
if (yRatio < 0.35) return horizontalPlacement ? 'top' : 'bottom';
|
||||||
|
if (yRatio > 0.65) return horizontalPlacement ? 'bottom' : 'top';
|
||||||
|
return '';
|
||||||
|
})();
|
||||||
|
|
||||||
|
const newPlacement =
|
||||||
|
((horizontalPlacement
|
||||||
|
? horizontalPlacement +
|
||||||
|
verticalPlacement.charAt(0).toUpperCase() +
|
||||||
|
verticalPlacement.slice(1)
|
||||||
|
: verticalPlacement) as TooltipPlacement) || 'left';
|
||||||
|
if (newPlacement !== placement) {
|
||||||
|
setPlacement(newPlacement);
|
||||||
}
|
}
|
||||||
}, [getVisibilityRatio]);
|
}, [getVisibilityRatio]);
|
||||||
|
|
||||||
|
|
@ -97,7 +118,7 @@ const ControlPopover: FC<PopoverProps> = ({
|
||||||
}
|
}
|
||||||
|
|
||||||
setVisible(!!visible);
|
setVisible(!!visible);
|
||||||
props.onVisibleChange?.(!!visible);
|
props.onOpenChange?.(!!visible);
|
||||||
},
|
},
|
||||||
[props, changeContainerScrollStatus],
|
[props, changeContainerScrollStatus],
|
||||||
);
|
);
|
||||||
|
|
@ -106,7 +127,7 @@ const ControlPopover: FC<PopoverProps> = ({
|
||||||
(event: KeyboardEvent) => {
|
(event: KeyboardEvent) => {
|
||||||
if (event.key === 'Escape') {
|
if (event.key === 'Escape') {
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
props.onVisibleChange?.(false);
|
props.onOpenChange?.(false);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[props],
|
[props],
|
||||||
|
|
@ -143,10 +164,10 @@ const ControlPopover: FC<PopoverProps> = ({
|
||||||
return (
|
return (
|
||||||
<Popover
|
<Popover
|
||||||
{...props}
|
{...props}
|
||||||
visible={visible}
|
open={visible}
|
||||||
arrowPointAtCenter
|
arrow={{ pointAtCenter: true }}
|
||||||
placement={placement}
|
placement={placement}
|
||||||
onVisibleChange={handleOnVisibleChange}
|
onOpenChange={handleOnVisibleChange}
|
||||||
getPopupContainer={handleGetPopupContainer}
|
getPopupContainer={handleGetPopupContainer}
|
||||||
destroyTooltipOnHide={destroyTooltipOnHide}
|
destroyTooltipOnHide={destroyTooltipOnHide}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -355,23 +355,24 @@ export default function DateFilterLabel(props: DateFilterControlProps) {
|
||||||
<span className="text">{t('Edit time range')}</span>
|
<span className="text">{t('Edit time range')}</span>
|
||||||
</IconWrapper>
|
</IconWrapper>
|
||||||
);
|
);
|
||||||
|
|
||||||
const popoverContent = (
|
const popoverContent = (
|
||||||
<ControlPopover
|
<ControlPopover
|
||||||
placement="right"
|
autoAdjustOverflow={false}
|
||||||
trigger="click"
|
trigger="click"
|
||||||
|
placement="right"
|
||||||
content={overlayContent}
|
content={overlayContent}
|
||||||
title={title}
|
title={title}
|
||||||
defaultVisible={show}
|
defaultOpen={show}
|
||||||
visible={show}
|
open={show}
|
||||||
onVisibleChange={toggleOverlay}
|
onOpenChange={toggleOverlay}
|
||||||
overlayStyle={{ width: '600px' }}
|
overlayStyle={{ width: '600px' }}
|
||||||
getPopupContainer={triggerNode =>
|
destroyTooltipOnHide
|
||||||
|
getPopupContainer={nodeTrigger =>
|
||||||
isOverflowingFilterBar
|
isOverflowingFilterBar
|
||||||
? (triggerNode.parentNode as HTMLElement)
|
? (nodeTrigger.parentNode as HTMLElement)
|
||||||
: document.body
|
: document.body
|
||||||
}
|
}
|
||||||
destroyTooltipOnHide
|
overlayClassName="time-range-popover"
|
||||||
>
|
>
|
||||||
<Tooltip placement="top" title={tooltipTitle}>
|
<Tooltip placement="top" title={tooltipTitle}>
|
||||||
<DateLabel
|
<DateLabel
|
||||||
|
|
|
||||||
|
|
@ -165,9 +165,9 @@ const ColumnSelectPopoverTrigger = ({
|
||||||
<ControlPopover
|
<ControlPopover
|
||||||
trigger="click"
|
trigger="click"
|
||||||
content={overlayContent}
|
content={overlayContent}
|
||||||
defaultVisible={visible}
|
defaultOpen={visible}
|
||||||
visible={visible}
|
open={visible}
|
||||||
onVisibleChange={handleTogglePopover}
|
onOpenChange={handleTogglePopover}
|
||||||
title={popoverTitle}
|
title={popoverTitle}
|
||||||
destroyTooltipOnHide
|
destroyTooltipOnHide
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -106,9 +106,9 @@ class AdhocFilterPopoverTrigger extends PureComponent<
|
||||||
<ControlPopover
|
<ControlPopover
|
||||||
trigger="click"
|
trigger="click"
|
||||||
content={overlayContent}
|
content={overlayContent}
|
||||||
defaultVisible={visible}
|
defaultOpen={visible}
|
||||||
visible={visible}
|
open={visible}
|
||||||
onVisibleChange={togglePopover}
|
onOpenChange={togglePopover}
|
||||||
destroyTooltipOnHide
|
destroyTooltipOnHide
|
||||||
>
|
>
|
||||||
{this.props.children}
|
{this.props.children}
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
*/
|
*/
|
||||||
import { ControlHeader } from '@superset-ui/chart-controls';
|
import { ControlHeader } from '@superset-ui/chart-controls';
|
||||||
import { css, styled, t } from '@superset-ui/core';
|
import { css, styled, t } from '@superset-ui/core';
|
||||||
import { Popover } from 'antd';
|
import Popover from 'src/components/Popover';
|
||||||
import { FC, useState } from 'react';
|
import { FC, useState } from 'react';
|
||||||
import { EditItem, LayerConf, LayerConfigsControlProps } from './types';
|
import { EditItem, LayerConf, LayerConfigsControlProps } from './types';
|
||||||
import LayerConfigsPopoverContent from './LayerConfigsPopoverContent';
|
import LayerConfigsPopoverContent from './LayerConfigsPopoverContent';
|
||||||
|
|
@ -160,7 +160,7 @@ export const LayerConfigsControl: FC<LayerConfigsControlProps> = ({
|
||||||
<div>
|
<div>
|
||||||
<ControlHeader {...controlHeaderProps} />
|
<ControlHeader {...controlHeaderProps} />
|
||||||
<Popover
|
<Popover
|
||||||
visible={popoverVisible}
|
open={popoverVisible}
|
||||||
trigger="click"
|
trigger="click"
|
||||||
title={popoverTitle}
|
title={popoverTitle}
|
||||||
placement="right"
|
placement="right"
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,8 @@
|
||||||
*/
|
*/
|
||||||
import { ControlHeader } from '@superset-ui/chart-controls';
|
import { ControlHeader } from '@superset-ui/chart-controls';
|
||||||
import { css, styled, t } from '@superset-ui/core';
|
import { css, styled, t } from '@superset-ui/core';
|
||||||
import { Button, Popover } from 'antd';
|
import Button from 'src/components/Button';
|
||||||
|
import Popover from 'src/components/Popover';
|
||||||
import { FC, useState } from 'react';
|
import { FC, useState } from 'react';
|
||||||
import { mix } from 'polished';
|
import { mix } from 'polished';
|
||||||
import { MapViewConfigs, MapViewConfigsControlProps } from './types';
|
import { MapViewConfigs, MapViewConfigsControlProps } from './types';
|
||||||
|
|
@ -159,7 +160,7 @@ export const MapViewControl: FC<MapViewConfigsControlProps> = ({
|
||||||
|
|
||||||
{isCustomMode() && value && (
|
{isCustomMode() && value && (
|
||||||
<Popover
|
<Popover
|
||||||
visible={popoverVisible}
|
open={popoverVisible}
|
||||||
trigger="click"
|
trigger="click"
|
||||||
title={popoverTitle}
|
title={popoverTitle}
|
||||||
placement="right"
|
placement="right"
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,8 @@
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import { css, styled, t } from '@superset-ui/core';
|
import { css, styled, t } from '@superset-ui/core';
|
||||||
import { Button, Form } from 'antd';
|
import { Form } from 'src/components/Form';
|
||||||
|
import Button from 'src/components/Button';
|
||||||
import { FC, useEffect, useState } from 'react';
|
import { FC, useEffect, useState } from 'react';
|
||||||
import { mix } from 'polished';
|
import { mix } from 'polished';
|
||||||
import { MapViewConfigs, MapViewPopoverContentProps } from './types';
|
import { MapViewConfigs, MapViewPopoverContentProps } from './types';
|
||||||
|
|
|
||||||
|
|
@ -259,9 +259,9 @@ class AdhocMetricPopoverTrigger extends PureComponent<
|
||||||
placement="right"
|
placement="right"
|
||||||
trigger="click"
|
trigger="click"
|
||||||
content={overlayContent}
|
content={overlayContent}
|
||||||
defaultVisible={visible}
|
defaultOpen={visible}
|
||||||
visible={visible}
|
open={visible}
|
||||||
onVisibleChange={togglePopover}
|
onOpenChange={togglePopover}
|
||||||
title={popoverTitle}
|
title={popoverTitle}
|
||||||
destroyTooltipOnHide
|
destroyTooltipOnHide
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -361,8 +361,8 @@ export default class TimeSeriesColumnControl extends Component {
|
||||||
trigger="click"
|
trigger="click"
|
||||||
content={this.renderPopover()}
|
content={this.renderPopover()}
|
||||||
title={t('Column Configuration')}
|
title={t('Column Configuration')}
|
||||||
visible={this.state.popoverVisible}
|
open={this.state.popoverVisible}
|
||||||
onVisibleChange={this.onPopoverVisibleChange}
|
onOpenChange={this.onPopoverVisibleChange}
|
||||||
>
|
>
|
||||||
<InfoTooltipWithTrigger
|
<InfoTooltipWithTrigger
|
||||||
icon="edit"
|
icon="edit"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue