diff --git a/superset-frontend/.storybook/preview.jsx b/superset-frontend/.storybook/preview.jsx
index ee216575f9ae4..e20ff6c5e237b 100644
--- a/superset-frontend/.storybook/preview.jsx
+++ b/superset-frontend/.storybook/preview.jsx
@@ -27,8 +27,8 @@ import { supersetTheme, ThemeProvider } from '@superset-ui/core';
import '../src/theme.ts';
import './storybook.css';
-const themeDecorator = storyFn => (
- {storyFn()}
+const themeDecorator = Story => (
+ { }
);
addDecorator(jsxDecorator);
diff --git a/superset-frontend/spec/javascripts/sqllab/TableElement_spec.jsx b/superset-frontend/spec/javascripts/sqllab/TableElement_spec.jsx
index e1426e20b8514..d8b5646d34448 100644
--- a/superset-frontend/spec/javascripts/sqllab/TableElement_spec.jsx
+++ b/superset-frontend/spec/javascripts/sqllab/TableElement_spec.jsx
@@ -21,12 +21,13 @@ import { mount, shallow } from 'enzyme';
import { Provider } from 'react-redux';
import configureStore from 'redux-mock-store';
import { supersetTheme, ThemeProvider } from '@superset-ui/core';
+import Collapse from 'src/common/components/Collapse';
import { IconTooltip } from 'src/components/IconTooltip';
import Fade from 'src/common/components/Fade';
import TableElement from 'src/SqlLab/components/TableElement';
import ColumnElement from 'src/SqlLab/components/ColumnElement';
-
+import waitForComponentToPaint from 'spec/helpers/waitForComponentToPaint';
import { mockedActions, table } from './fixtures';
describe('TableElement', () => {
@@ -43,9 +44,19 @@ describe('TableElement', () => {
it('renders with props', () => {
expect(React.isValidElement( )).toBe(true);
});
- it('has 2 IconTooltip elements', () => {
- const wrapper = shallow( );
- expect(wrapper.find(IconTooltip)).toHaveLength(2);
+ it('has 4 IconTooltip elements', () => {
+ const wrapper = mount(
+
+
+ ,
+ {
+ wrappingComponent: ThemeProvider,
+ wrappingComponentProps: {
+ theme: supersetTheme,
+ },
+ },
+ );
+ expect(wrapper.find(IconTooltip)).toHaveLength(4);
});
it('has 14 columns', () => {
const wrapper = shallow( );
@@ -64,20 +75,45 @@ describe('TableElement', () => {
},
);
});
- it('fades table', () => {
- const wrapper = shallow( );
- expect(wrapper.state().hovered).toBe(false);
+ it('fades table', async () => {
+ const wrapper = mount(
+
+
+ ,
+ {
+ wrappingComponent: ThemeProvider,
+ wrappingComponentProps: {
+ theme: supersetTheme,
+ },
+ },
+ );
+ expect(wrapper.find(TableElement).state().hovered).toBe(false);
expect(wrapper.find(Fade).props().hovered).toBe(false);
- wrapper.find('div.TableElement').simulate('mouseEnter');
- expect(wrapper.state().hovered).toBe(true);
+ wrapper.find('.header-container').hostNodes().simulate('mouseEnter');
+ await waitForComponentToPaint(wrapper, 300);
+ expect(wrapper.find(TableElement).state().hovered).toBe(true);
expect(wrapper.find(Fade).props().hovered).toBe(true);
});
it('sorts columns', () => {
- const wrapper = shallow( );
- expect(wrapper.state().sortColumns).toBe(false);
+ const wrapper = mount(
+
+
+
+
+ ,
+ {
+ wrappingComponent: ThemeProvider,
+ wrappingComponentProps: {
+ theme: supersetTheme,
+ },
+ },
+ );
+ expect(wrapper.find(TableElement).state().sortColumns).toBe(false);
+ wrapper.find('.header-container').hostNodes().simulate('click');
expect(wrapper.find(ColumnElement).first().props().column.name).toBe('id');
- wrapper.find('.sort-cols').simulate('click');
- expect(wrapper.state().sortColumns).toBe(true);
+ wrapper.find('.header-container').simulate('mouseEnter');
+ wrapper.find('.sort-cols').hostNodes().simulate('click');
+ expect(wrapper.find(TableElement).state().sortColumns).toBe(true);
expect(wrapper.find(ColumnElement).first().props().column.name).toBe(
'active',
);
@@ -99,10 +135,18 @@ describe('TableElement', () => {
expect(mockedActions.collapseTable.called).toBe(true);
});
it('removes the table', () => {
- const wrapper = shallow( );
- expect(wrapper.state().expanded).toBe(true);
- wrapper.find('.table-remove').simulate('click');
- expect(wrapper.state().expanded).toBe(false);
+ const wrapper = mount(
+
+
+ ,
+ {
+ wrappingComponent: ThemeProvider,
+ wrappingComponentProps: {
+ theme: supersetTheme,
+ },
+ },
+ );
+ wrapper.find('.table-remove').hostNodes().simulate('click');
expect(mockedActions.removeDataPreview.called).toBe(true);
});
});
diff --git a/superset-frontend/src/SqlLab/components/SqlEditorLeftBar.jsx b/superset-frontend/src/SqlLab/components/SqlEditorLeftBar.jsx
index 7136ab0370e48..3c46e4cf848df 100644
--- a/superset-frontend/src/SqlLab/components/SqlEditorLeftBar.jsx
+++ b/superset-frontend/src/SqlLab/components/SqlEditorLeftBar.jsx
@@ -19,7 +19,8 @@
import React from 'react';
import PropTypes from 'prop-types';
import Button from 'src/components/Button';
-import { t, styled } from '@superset-ui/core';
+import { t, styled, css } from '@superset-ui/core';
+import Collapse from 'src/common/components/Collapse';
import TableElement from './TableElement';
import TableSelector from '../../components/TableSelector';
@@ -145,13 +146,38 @@ export default class SqlEditorLeftBar extends React.PureComponent {
- {this.props.tables.map(table => (
-
- ))}
+ css`
+ .ant-collapse-item {
+ margin-bottom: ${theme.gridUnit * 3}px;
+ }
+ .ant-collapse-header {
+ padding: 0px !important;
+ display: flex;
+ align-items: center;
+ }
+ .ant-collapse-content-box {
+ padding: 0px ${theme.gridUnit * 4}px 0px 0px !important;
+ }
+ .ant-collapse-arrow {
+ top: ${theme.gridUnit * 2}px !important;
+ color: ${theme.colors.primary.dark1} !important;
+ &: hover {
+ color: ${theme.colors.primary.dark2} !important;
+ }
+ }
+ `}
+ >
+ {this.props.tables.map(table => (
+
+ ))}
+
{shouldShowReset && (
diff --git a/superset-frontend/src/SqlLab/components/TableElement.jsx b/superset-frontend/src/SqlLab/components/TableElement.jsx
index 7abdf7ef7eea3..abc9b8c7a02d8 100644
--- a/superset-frontend/src/SqlLab/components/TableElement.jsx
+++ b/superset-frontend/src/SqlLab/components/TableElement.jsx
@@ -18,10 +18,12 @@
*/
import React from 'react';
import PropTypes from 'prop-types';
-import { Collapse, Well } from 'react-bootstrap';
+import { Well } from 'react-bootstrap';
+import Collapse from 'src/common/components/Collapse';
import ButtonGroup from 'src/components/ButtonGroup';
import shortid from 'shortid';
import { t, styled } from '@superset-ui/core';
+import { debounce } from 'lodash';
import Fade from 'src/common/components/Fade';
import { Tooltip } from 'src/common/components/Tooltip';
@@ -35,13 +37,11 @@ import Loading from '../../components/Loading';
const propTypes = {
table: PropTypes.object,
actions: PropTypes.object,
- timeout: PropTypes.number, // used for tests
};
const defaultProps = {
actions: {},
table: null,
- timeout: 500,
};
const StyledSpan = styled.span`
@@ -57,13 +57,11 @@ class TableElement extends React.PureComponent {
super(props);
this.state = {
sortColumns: false,
- expanded: true,
hovered: false,
};
- this.removeFromStore = this.removeFromStore.bind(this);
this.toggleSortColumns = this.toggleSortColumns.bind(this);
this.removeTable = this.removeTable.bind(this);
- this.setHover = this.setHover.bind(this);
+ this.setHover = debounce(this.setHover.bind(this), 100);
}
setHover(hovered) {
@@ -91,18 +89,14 @@ class TableElement extends React.PureComponent {
}
removeTable() {
- this.setState({ expanded: false });
this.props.actions.removeDataPreview(this.props.table);
+ this.props.actions.removeTable(this.props.table);
}
toggleSortColumns() {
this.setState(prevState => ({ sortColumns: !prevState.sortColumns }));
}
- removeFromStore() {
- this.props.actions.removeTable(this.props.table);
- }
-
renderWell() {
const { table } = this.props;
let header;
@@ -208,7 +202,11 @@ class TableElement extends React.PureComponent {
renderHeader() {
const { table } = this.props;
return (
-
+
this.setHover(true)}
+ onMouseLeave={() => this.setHover(false)}
+ >
) : (
- {this.renderControls()}
+ e.stopPropagation()}
+ >
+ {this.renderControls()}
+
)}
- {
- this.toggleTable(e);
- }}
- className={
- 'text-primary pointer m-l-10 ' +
- 'fa fa-lg ' +
- `fa-angle-${table.expanded ? 'up' : 'down'}`
- }
- />
);
@@ -270,39 +260,36 @@ class TableElement extends React.PureComponent {
});
}
}
+
const metadata = (
-
+ this.setHover(true)}
+ onMouseLeave={() => this.setHover(false)}
+ css={{ paddingTop: 6 }}
+ >
+ {this.renderWell()}
- {this.renderWell()}
-
- {cols &&
- cols.map(col => )}
-
+ {cols &&
+ cols.map(col =>
)}
-
+
);
return metadata;
}
render() {
return (
-
- this.setHover(true)}
- onMouseLeave={() => this.setHover(false)}
- >
- {this.renderHeader()}
-
{this.renderBody()}
-
-
+ {this.renderBody()}
+
);
}
}
+
TableElement.propTypes = propTypes;
TableElement.defaultProps = defaultProps;
diff --git a/superset-frontend/src/SqlLab/main.less b/superset-frontend/src/SqlLab/main.less
index dad051b448e73..02106e4fd2a32 100644
--- a/superset-frontend/src/SqlLab/main.less
+++ b/superset-frontend/src/SqlLab/main.less
@@ -414,8 +414,6 @@ div.tablePopover {
}
.TableElement {
- margin-right: 10px;
-
.well {
margin-top: 5px;
margin-bottom: 5px;
@@ -429,18 +427,22 @@ div.tablePopover {
.header-container {
display: flex;
+ flex: 1;
+ align-items: center;
.table-name {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-size: 16px;
+ flex: 1;
}
.header-right-side {
margin-left: auto;
display: flex;
align-items: center;
+ margin-right: 33px;
}
}
}
diff --git a/superset-frontend/src/common/components/.eslintrc b/superset-frontend/src/common/components/.eslintrc
new file mode 100644
index 0000000000000..e7c30d4809b56
--- /dev/null
+++ b/superset-frontend/src/common/components/.eslintrc
@@ -0,0 +1,23 @@
+/**
+ * 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.
+ */
+{
+ "rules": {
+ "no-restricted-imports": 0
+ }
+}
diff --git a/superset-frontend/src/common/components/Collapse/Collapse.stories.tsx b/superset-frontend/src/common/components/Collapse/Collapse.stories.tsx
new file mode 100644
index 0000000000000..f6636a81ccf0e
--- /dev/null
+++ b/superset-frontend/src/common/components/Collapse/Collapse.stories.tsx
@@ -0,0 +1,71 @@
+/**
+ * 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 React from 'react';
+import { useTheme } from '@superset-ui/core';
+import Collapse, { CollapseProps } from '.';
+
+export default {
+ title: 'Collapse',
+ component: Collapse,
+};
+
+export const InteractiveCollapse = (args: CollapseProps) => {
+ const theme = useTheme();
+ return (
+
+
+ Content 1
+
+
+ Content 2
+
+
+ );
+};
+
+InteractiveCollapse.args = {
+ ghost: false,
+ bordered: true,
+ accordion: false,
+};
+
+InteractiveCollapse.argTypes = {
+ theme: {
+ table: {
+ disable: true,
+ },
+ },
+};
+
+InteractiveCollapse.story = {
+ parameters: {
+ actions: {
+ disabled: true,
+ },
+ knobs: {
+ disabled: true,
+ },
+ },
+};
diff --git a/superset-frontend/src/common/components/Collapse/Collapse.test.tsx b/superset-frontend/src/common/components/Collapse/Collapse.test.tsx
new file mode 100644
index 0000000000000..2d9355956ebad
--- /dev/null
+++ b/superset-frontend/src/common/components/Collapse/Collapse.test.tsx
@@ -0,0 +1,110 @@
+/**
+ * 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 React from 'react';
+import { render, screen } from 'spec/helpers/testing-library';
+import userEvent from '@testing-library/user-event';
+import { supersetTheme } from '@superset-ui/core';
+import { hexToRgb } from 'src/utils/colorUtils';
+import Collapse, { CollapseProps } from '.';
+
+function renderCollapse(props?: CollapseProps) {
+ return render(
+
+
+ Content 1
+
+
+ Content 2
+
+ ,
+ );
+}
+
+test('renders collapsed with default props', () => {
+ renderCollapse();
+
+ const headers = screen.getAllByRole('button');
+
+ expect(headers[0]).toHaveTextContent('Header 1');
+ expect(headers[1]).toHaveTextContent('Header 2');
+ expect(screen.queryByText('Content 1')).not.toBeInTheDocument();
+ expect(screen.queryByText('Content 2')).not.toBeInTheDocument();
+});
+
+test('renders with one item expanded by default', () => {
+ renderCollapse({ defaultActiveKey: ['1'] });
+
+ const headers = screen.getAllByRole('button');
+
+ expect(headers[0]).toHaveTextContent('Header 1');
+ expect(headers[1]).toHaveTextContent('Header 2');
+ expect(screen.getByText('Content 1')).toBeInTheDocument();
+ expect(screen.queryByText('Content 2')).not.toBeInTheDocument();
+});
+
+test('expands on click', () => {
+ renderCollapse();
+
+ expect(screen.queryByText('Content 1')).not.toBeInTheDocument();
+ expect(screen.queryByText('Content 2')).not.toBeInTheDocument();
+
+ userEvent.click(screen.getAllByRole('button')[0]);
+
+ expect(screen.getByText('Content 1')).toBeInTheDocument();
+ expect(screen.queryByText('Content 2')).not.toBeInTheDocument();
+});
+
+test('collapses on click', () => {
+ renderCollapse({ defaultActiveKey: ['1'] });
+
+ expect(screen.getByText('Content 1')).toBeInTheDocument();
+ expect(screen.queryByText('Content 2')).not.toBeInTheDocument();
+
+ userEvent.click(screen.getAllByRole('button')[0]);
+
+ expect(screen.getByText('Content 1').parentNode).toHaveClass(
+ 'ant-collapse-content-hidden',
+ );
+ 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.typography.weights.bold.toString(),
+ );
+ expect(headerStyle.fontSize).toBe(`${supersetTheme.gridUnit * 4}px`);
+ expect(headerStyle.color).toBe(
+ hexToRgb(supersetTheme.colors.grayscale.light4),
+ );
+ expect(arrowStyle.transition).toBe('transform 0.24s');
+});
diff --git a/superset-frontend/src/common/components/Collapse.tsx b/superset-frontend/src/common/components/Collapse/index.tsx
similarity index 90%
rename from superset-frontend/src/common/components/Collapse.tsx
rename to superset-frontend/src/common/components/Collapse/index.tsx
index c6daa77cd1755..26d9c81412acf 100644
--- a/superset-frontend/src/common/components/Collapse.tsx
+++ b/superset-frontend/src/common/components/Collapse/index.tsx
@@ -18,11 +18,10 @@
*/
import React from 'react';
import { styled } from '@superset-ui/core';
-// eslint-disable-next-line no-restricted-imports
import { Collapse as AntdCollapse } from 'antd';
import { CollapseProps as AntdCollapseProps } from 'antd/lib/collapse';
-interface CollapseProps extends AntdCollapseProps {
+export interface CollapseProps extends AntdCollapseProps {
light?: boolean;
bigger?: boolean;
bold?: boolean;
@@ -34,13 +33,7 @@ const Collapse = Object.assign(
styled(({ light, bigger, bold, animateArrows, ...props }: CollapseProps) => (
))`
- height: 100%;
.ant-collapse-item {
- border: 0;
- height: 100%;
- &:last-of-type.ant-collapse-item-active {
- padding-bottom: ${({ theme }) => theme.gridUnit * 3}px;
- }
.ant-collapse-header {
font-weight: ${({ bold, theme }) =>
bold
@@ -80,9 +73,7 @@ const Collapse = Object.assign(
`}
}
.ant-collapse-content {
- height: 100%;
.ant-collapse-content-box {
- height: 100%;
.loading.inline {
margin: ${({ theme }) => theme.gridUnit * 12}px auto;
display: block;
diff --git a/superset-frontend/src/common/components/Radio/index.tsx b/superset-frontend/src/common/components/Radio/index.tsx
index a80662adc17e8..9ab656e4aa80b 100644
--- a/superset-frontend/src/common/components/Radio/index.tsx
+++ b/superset-frontend/src/common/components/Radio/index.tsx
@@ -17,9 +17,9 @@
* under the License.
*/
import { styled } from '@superset-ui/core';
-import { Radio as BaseRadio } from 'src/common/components';
+import { Radio as AntdRadio } from 'antd';
-const StyledRadio = styled(BaseRadio)`
+const StyledRadio = styled(AntdRadio)`
.ant-radio-inner {
top: -1px;
left: 2px;
@@ -51,7 +51,7 @@ const StyledRadio = styled(BaseRadio)`
}
}
`;
-const StyledGroup = styled(BaseRadio.Group)`
+const StyledGroup = styled(AntdRadio.Group)`
font-size: inherit;
`;
diff --git a/superset-frontend/src/common/components/Tooltip/index.tsx b/superset-frontend/src/common/components/Tooltip/index.tsx
index aecf19f945397..5ec24bb3a60ff 100644
--- a/superset-frontend/src/common/components/Tooltip/index.tsx
+++ b/superset-frontend/src/common/components/Tooltip/index.tsx
@@ -18,13 +18,13 @@
*/
import React from 'react';
import { useTheme } from '@superset-ui/core';
-import { Tooltip as BaseTooltip } from 'src/common/components';
+import { Tooltip as AntdTooltip } from 'antd';
import { TooltipProps } from 'antd/lib/tooltip';
export const Tooltip = (props: TooltipProps) => {
const theme = useTheme();
return (
- ;
export const BadgeError = () => ;
export const BadgeSmall = () => ;
-export const CollapseDefault = () => (
-
-
- Hi! I am a sample content
-
-
- Hi! I am another sample content
-
-
-);
-export const CollapseGhost = () => (
-
-
- Hi! I am a sample content
-
-
- Hi! I am another sample content
-
-
-);
-export const CollapseBold = () => (
-
-
- Hi! I am a sample content
-
-
- Hi! I am another sample content
-
-
-);
-export const CollapseBigger = () => (
-
-
- Hi! I am a sample content
-
-
- Hi! I am another sample content
-
-
-);
-export const CollapseTextLight = () => (
-
-
- Hi! I am a sample content
-
-
- Hi! I am another sample content
-
-
-);
-export const CollapseAnimateArrows = () => (
-
-
- Hi! I am a sample content
-
-
- Hi! I am another sample content
-
-
-);
-
export function StyledCronPicker() {
// @ts-ignore
const inputRef = useRef (null);
diff --git a/superset-frontend/src/common/components/index.tsx b/superset-frontend/src/common/components/index.tsx
index 65591e597ae85..bc0eb71a055f3 100644
--- a/superset-frontend/src/common/components/index.tsx
+++ b/superset-frontend/src/common/components/index.tsx
@@ -18,7 +18,6 @@
*/
import React from 'react';
import { styled } from '@superset-ui/core';
-// eslint-disable-next-line no-restricted-imports
import { Dropdown, Menu as AntdMenu, Input as AntdInput, Skeleton } from 'antd';
import { DropDownProps } from 'antd/lib/dropdown';
/*
@@ -26,11 +25,9 @@ import { DropDownProps } from 'antd/lib/dropdown';
For documentation, see https://ant.design/components/overview/
*/
-// eslint-disable-next-line no-restricted-imports
export {
AutoComplete,
Avatar,
- Button,
Card,
Checkbox,
Col,
@@ -45,7 +42,6 @@ export {
Tree,
Popover,
Slider,
- Radio,
Row,
Space,
Select,
@@ -60,7 +56,7 @@ export { default as Alert, AlertProps } from 'antd/lib/alert';
export { TreeProps } from 'antd/lib/tree';
export { FormInstance } from 'antd/lib/form';
export { RadioChangeEvent } from 'antd/lib/radio';
-export { default as Collapse } from './Collapse';
+
export { default as Badge } from './Badge';
export { default as Progress } from './ProgressBar';
diff --git a/superset-frontend/src/components/.eslintrc b/superset-frontend/src/components/.eslintrc
new file mode 100644
index 0000000000000..e7c30d4809b56
--- /dev/null
+++ b/superset-frontend/src/components/.eslintrc
@@ -0,0 +1,23 @@
+/**
+ * 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.
+ */
+{
+ "rules": {
+ "no-restricted-imports": 0
+ }
+}
diff --git a/superset-frontend/src/components/Button/index.tsx b/superset-frontend/src/components/Button/index.tsx
index cb500cccb0aa2..fa60cd043f842 100644
--- a/superset-frontend/src/components/Button/index.tsx
+++ b/superset-frontend/src/components/Button/index.tsx
@@ -20,7 +20,7 @@ import React, { CSSProperties, Children, ReactElement } from 'react';
import { kebabCase } from 'lodash';
import { mix } from 'polished';
import cx from 'classnames';
-import { Button as AntdButton } from 'src/common/components';
+import { Button as AntdButton } from 'antd';
import { useTheme } from '@superset-ui/core';
import { Tooltip } from 'src/common/components/Tooltip';
diff --git a/superset-frontend/src/dashboard/components/FiltersBadge/DetailsPanel.tsx b/superset-frontend/src/dashboard/components/FiltersBadge/DetailsPanel.tsx
index 27e7efeab8a73..c68477daec2dd 100644
--- a/superset-frontend/src/dashboard/components/FiltersBadge/DetailsPanel.tsx
+++ b/superset-frontend/src/dashboard/components/FiltersBadge/DetailsPanel.tsx
@@ -24,7 +24,8 @@ import {
CheckCircleFilled,
ExclamationCircleFilled,
} from '@ant-design/icons';
-import { Collapse, Popover } from 'src/common/components/index';
+import { Popover } from 'src/common/components/index';
+import Collapse from 'src/common/components/Collapse';
import { Global } from '@emotion/core';
import {
Indent,
@@ -173,7 +174,7 @@ const DetailsPanelPopover = ({
}
>
-
+
{appliedIndicators.map(indicator => (
}
>
-
+
{incompatibleIndicators.map(indicator => (
-
+
{unsetIndicators.map(indicator => (
-
+
({
- expanded: !prevState.expanded,
- }));
- }
-
render() {
const value = this.props.value || this.props.default;
const type = value.type || controlTypes.fixed;
@@ -107,67 +101,88 @@ export default class FixedOrMetricControl extends React.Component {
return (
-
- {this.state.type === controlTypes.fixed && (
- {this.state.fixedValue}
- )}
- {this.state.type === controlTypes.metric && (
-
- metric:
-
- {this.state.metricValue ? this.state.metricValue.label : null}
-
-
- )}
-
-
css`
+ &.ant-collapse
+ > .ant-collapse-item.ant-collapse-no-arrow
+ > .ant-collapse-header {
+ border: 0px;
+ padding: 0px 0px ${theme.gridUnit * 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.gridUnit * 2}px;
+ }
+ }
+ `}
>
-
-
-
-
{
+ undefined}>
+ {this.state.type === controlTypes.fixed && (
+ {this.state.fixedValue}
+ )}
+ {this.state.type === controlTypes.metric && (
+
+ metric:
+
+ {this.state.metricValue
+ ? this.state.metricValue.label
+ : null}
+
+
+ )}
+
+ }
+ >
+
+
{
+ this.setType(controlTypes.fixed);
+ }}
+ >
+ {
this.setType(controlTypes.fixed);
}}
- >
- {
- this.setType(controlTypes.fixed);
- }}
- value={this.state.fixedValue}
- />
-
-
{
+ value={this.state.fixedValue}
+ />
+
+
{
+ this.setType(controlTypes.metric);
+ }}
+ >
+ {
this.setType(controlTypes.metric);
}}
- >
- {
- this.setType(controlTypes.metric);
- }}
- onChange={this.setMetric}
- value={this.state.metricValue}
- />
-
-
-
-
-
+ onChange={this.setMetric}
+ value={this.state.metricValue}
+ />
+
+
+
+
);
}
diff --git a/superset-frontend/src/explore/main.less b/superset-frontend/src/explore/main.less
index 7dd47e115bcbd..f30435fb28a49 100644
--- a/superset-frontend/src/explore/main.less
+++ b/superset-frontend/src/explore/main.less
@@ -233,15 +233,3 @@ h2.section-header {
margin-top: 0;
padding-bottom: 5px;
}
-
-.panel-spreaded,
-.panel-spreaded .panel-body {
- padding: 0;
- margin: 0;
-}
-
-.panel-spreaded .well {
- margin-top: 8px;
- margin-bottom: 0;
- padding: 8px;
-}
diff --git a/superset-frontend/src/utils/colorUtils.ts b/superset-frontend/src/utils/colorUtils.ts
new file mode 100644
index 0000000000000..f30828df97c71
--- /dev/null
+++ b/superset-frontend/src/utils/colorUtils.ts
@@ -0,0 +1,50 @@
+/**
+ * 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.
+ */
+export function hexToRgb(h: string) {
+ let r = '0';
+ let g = '0';
+ let b = '0';
+
+ // 3 digits
+ if (h.length === 4) {
+ r = `0x${h[1]}${h[1]}`;
+ g = `0x${h[2]}${h[2]}`;
+ b = `0x${h[3]}${h[3]}`;
+
+ // 6 digits
+ } else if (h.length === 7) {
+ r = `0x${h[1]}${h[2]}`;
+ g = `0x${h[3]}${h[4]}`;
+ b = `0x${h[5]}${h[6]}`;
+ }
+
+ return `rgb(${+r}, ${+g}, ${+b})`;
+}
+
+export function rgbToHex(red: number, green: number, blue: number) {
+ let r = red.toString(16);
+ let g = green.toString(16);
+ let b = blue.toString(16);
+
+ if (r.length === 1) r = `0${r}`;
+ if (g.length === 1) g = `0${g}`;
+ if (b.length === 1) b = `0${b}`;
+
+ return `#${r}${g}${b}`;
+}
diff --git a/superset-frontend/src/views/CRUD/welcome/Welcome.tsx b/superset-frontend/src/views/CRUD/welcome/Welcome.tsx
index 836da13cb48b7..50fbe6fad1c35 100644
--- a/superset-frontend/src/views/CRUD/welcome/Welcome.tsx
+++ b/superset-frontend/src/views/CRUD/welcome/Welcome.tsx
@@ -18,7 +18,7 @@
*/
import React, { useEffect, useState } from 'react';
import { styled, t } from '@superset-ui/core';
-import { Collapse } from 'src/common/components';
+import Collapse from 'src/common/components/Collapse';
import { User } from 'src/types/bootstrapTypes';
import { reject } from 'lodash';
import withToasts from 'src/messageToasts/enhancers/withToasts';