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 (
- - 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';