diff --git a/superset-frontend/package-lock.json b/superset-frontend/package-lock.json index 063b4377fadd8..59582524ea16a 100644 --- a/superset-frontend/package-lock.json +++ b/superset-frontend/package-lock.json @@ -58471,6 +58471,7 @@ "prop-types": "^15.7.2" }, "peerDependencies": { + "@ant-design/icons": "^4.2.2", "@emotion/react": "^11.4.1", "@superset-ui/core": "*", "@testing-library/dom": "^7.29.4", diff --git a/superset-frontend/packages/superset-ui-chart-controls/package.json b/superset-frontend/packages/superset-ui-chart-controls/package.json index f875295ce52f1..bdb6be4daf846 100644 --- a/superset-frontend/packages/superset-ui-chart-controls/package.json +++ b/superset-frontend/packages/superset-ui-chart-controls/package.json @@ -28,6 +28,7 @@ "prop-types": "^15.7.2" }, "peerDependencies": { + "@ant-design/icons": "^4.2.2", "@emotion/react": "^11.4.1", "@superset-ui/core": "*", "@testing-library/dom": "^7.29.4", diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/components/CertifiedIconWithTooltip.tsx b/superset-frontend/packages/superset-ui-chart-controls/src/components/CertifiedIconWithTooltip.tsx index 194a415082d69..07492a181841c 100644 --- a/superset-frontend/packages/superset-ui-chart-controls/src/components/CertifiedIconWithTooltip.tsx +++ b/superset-frontend/packages/superset-ui-chart-controls/src/components/CertifiedIconWithTooltip.tsx @@ -53,9 +53,9 @@ function CertifiedIconWithTooltip({ theme.gridUnit}px; } @@ -54,15 +56,16 @@ export function ColumnOption({ return ( {showType && type !== undefined && } - {column.is_certified && ( - - )} - + + css` + margin-right: ${theme.gridUnit}px; + ` + } + ref={labelRef} + > {getColumnLabelText(column)} @@ -76,6 +79,14 @@ export function ColumnOption({ placement="top" /> )} + + {column.is_certified && ( + + )} ); } diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/components/ColumnTypeLabel.tsx b/superset-frontend/packages/superset-ui-chart-controls/src/components/ColumnTypeLabel.tsx deleted file mode 100644 index d9a3c8c117049..0000000000000 --- a/superset-frontend/packages/superset-ui-chart-controls/src/components/ColumnTypeLabel.tsx +++ /dev/null @@ -1,58 +0,0 @@ -/* eslint-disable no-nested-ternary */ -/** - * 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 { GenericDataType } from '@superset-ui/core'; -import React from 'react'; - -type StringIcon = '?' | 'ƒ' | 'AGG' | 'ABC' | '#' | 'T/F' | 'time'; - -export type ColumnLabelExtendedType = 'expression' | 'aggregate' | ''; - -export type ColumnTypeLabelProps = { - type?: ColumnLabelExtendedType | GenericDataType; -}; - -export function ColumnTypeLabel({ type }: ColumnTypeLabelProps) { - let stringIcon: StringIcon = '?'; - - if (type === '' || type === 'expression') { - stringIcon = 'ƒ'; - } else if (type === 'aggregate') { - stringIcon = 'AGG'; - } else if (type === GenericDataType.STRING) { - stringIcon = 'ABC'; - } else if (type === GenericDataType.NUMERIC) { - stringIcon = '#'; - } else if (type === GenericDataType.BOOLEAN) { - stringIcon = 'T/F'; - } else if (type === GenericDataType.TEMPORAL) { - stringIcon = 'time'; - } - - const typeIcon = - stringIcon === 'time' ? ( - - ) : ( -
{stringIcon}
- ); - - return {typeIcon}; -} - -export default ColumnTypeLabel; diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/components/ColumnTypeLabel/ColumnTypeLabel.tsx b/superset-frontend/packages/superset-ui-chart-controls/src/components/ColumnTypeLabel/ColumnTypeLabel.tsx new file mode 100644 index 0000000000000..772807e0f0599 --- /dev/null +++ b/superset-frontend/packages/superset-ui-chart-controls/src/components/ColumnTypeLabel/ColumnTypeLabel.tsx @@ -0,0 +1,71 @@ +/* eslint-disable no-nested-ternary */ +/** + * 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, { ReactNode } from 'react'; +import { css, GenericDataType, styled, t } from '@superset-ui/core'; +import { ClockCircleOutlined, QuestionOutlined } from '@ant-design/icons'; +// TODO: move all icons to superset-ui/core +import FunctionSvg from './type-icons/field_derived.svg'; +import BooleanSvg from './type-icons/field_boolean.svg'; +import StringSvg from './type-icons/field_abc.svg'; +import NumSvg from './type-icons/field_num.svg'; + +export type ColumnLabelExtendedType = 'expression' | ''; + +export type ColumnTypeLabelProps = { + type?: ColumnLabelExtendedType | GenericDataType; +}; + +const TypeIconWrapper = styled.div` + ${({ theme }) => css` + display: flex; + justify-content: center; + align-items: center; + width: ${theme.gridUnit * 6}px; + height: ${theme.gridUnit * 6}px; + margin-right: ${theme.gridUnit}px; + + && svg { + margin-right: 0; + margin-left: 0; + } + `}; +`; + +export function ColumnTypeLabel({ type }: ColumnTypeLabelProps) { + let typeIcon: ReactNode = ( + + ); + + if (type === '' || type === 'expression') { + typeIcon = ; + } else if (type === GenericDataType.STRING) { + typeIcon = ; + } else if (type === GenericDataType.NUMERIC) { + typeIcon = ; + } else if (type === GenericDataType.BOOLEAN) { + typeIcon = ; + } else if (type === GenericDataType.TEMPORAL) { + typeIcon = ; + } + + return {typeIcon}; +} + +export default ColumnTypeLabel; diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/components/ColumnTypeLabel/type-icons/field_abc.svg b/superset-frontend/packages/superset-ui-chart-controls/src/components/ColumnTypeLabel/type-icons/field_abc.svg new file mode 100644 index 0000000000000..ce519516c8803 --- /dev/null +++ b/superset-frontend/packages/superset-ui-chart-controls/src/components/ColumnTypeLabel/type-icons/field_abc.svg @@ -0,0 +1,21 @@ + + + + diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/components/ColumnTypeLabel/type-icons/field_boolean.svg b/superset-frontend/packages/superset-ui-chart-controls/src/components/ColumnTypeLabel/type-icons/field_boolean.svg new file mode 100644 index 0000000000000..a804e7d9faa5a --- /dev/null +++ b/superset-frontend/packages/superset-ui-chart-controls/src/components/ColumnTypeLabel/type-icons/field_boolean.svg @@ -0,0 +1,21 @@ + + + + diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/components/ColumnTypeLabel/type-icons/field_date.svg b/superset-frontend/packages/superset-ui-chart-controls/src/components/ColumnTypeLabel/type-icons/field_date.svg new file mode 100644 index 0000000000000..cf796fab70b9b --- /dev/null +++ b/superset-frontend/packages/superset-ui-chart-controls/src/components/ColumnTypeLabel/type-icons/field_date.svg @@ -0,0 +1,21 @@ + + + + diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/components/ColumnTypeLabel/type-icons/field_derived.svg b/superset-frontend/packages/superset-ui-chart-controls/src/components/ColumnTypeLabel/type-icons/field_derived.svg new file mode 100644 index 0000000000000..00e2115bf4863 --- /dev/null +++ b/superset-frontend/packages/superset-ui-chart-controls/src/components/ColumnTypeLabel/type-icons/field_derived.svg @@ -0,0 +1,21 @@ + + + + diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/components/ColumnTypeLabel/type-icons/field_num.svg b/superset-frontend/packages/superset-ui-chart-controls/src/components/ColumnTypeLabel/type-icons/field_num.svg new file mode 100644 index 0000000000000..69b6aa2e337ed --- /dev/null +++ b/superset-frontend/packages/superset-ui-chart-controls/src/components/ColumnTypeLabel/type-icons/field_num.svg @@ -0,0 +1,21 @@ + + + + diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/components/ColumnTypeLabel/type-icons/svgType.d.ts b/superset-frontend/packages/superset-ui-chart-controls/src/components/ColumnTypeLabel/type-icons/svgType.d.ts new file mode 100644 index 0000000000000..5885d9d8fc077 --- /dev/null +++ b/superset-frontend/packages/superset-ui-chart-controls/src/components/ColumnTypeLabel/type-icons/svgType.d.ts @@ -0,0 +1,22 @@ +/** + * 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. + */ +declare module '*.svg' { + const content: any; + export default content; +} diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/components/InfoTooltipWithTrigger.tsx b/superset-frontend/packages/superset-ui-chart-controls/src/components/InfoTooltipWithTrigger.tsx index 747a6535fe453..86a4a3d1d1d28 100644 --- a/superset-frontend/packages/superset-ui-chart-controls/src/components/InfoTooltipWithTrigger.tsx +++ b/superset-frontend/packages/superset-ui-chart-controls/src/components/InfoTooltipWithTrigger.tsx @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import React from 'react'; +import React, { CSSProperties } from 'react'; import { kebabCase } from 'lodash'; import { TooltipPlacement } from 'antd/lib/tooltip'; import { t } from '@superset-ui/core'; @@ -30,6 +30,7 @@ export interface InfoTooltipWithTriggerProps { placement?: TooltipPlacement; bsStyle?: string; className?: string; + iconsStyle?: CSSProperties; } export function InfoTooltipWithTrigger({ @@ -40,6 +41,7 @@ export function InfoTooltipWithTrigger({ icon = 'info-circle', className = 'text-muted', placement = 'right', + iconsStyle = {}, }: InfoTooltipWithTriggerProps) { const iconClass = `fa fa-${icon} ${className} ${ bsStyle ? `text-${bsStyle}` : '' @@ -50,7 +52,7 @@ export function InfoTooltipWithTrigger({ aria-label={t('Show info tooltip')} tabIndex={0} className={iconClass} - style={{ cursor: onClick ? 'pointer' : undefined }} + style={{ cursor: onClick ? 'pointer' : undefined, ...iconsStyle }} onClick={onClick} onKeyPress={ onClick && diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/components/MetricOption.tsx b/superset-frontend/packages/superset-ui-chart-controls/src/components/MetricOption.tsx index 0d0754abc14e4..1052d1ec7e591 100644 --- a/superset-frontend/packages/superset-ui-chart-controls/src/components/MetricOption.tsx +++ b/superset-frontend/packages/superset-ui-chart-controls/src/components/MetricOption.tsx @@ -17,9 +17,15 @@ * under the License. */ import React, { useState, ReactNode, useLayoutEffect } from 'react'; -import { styled, Metric, SafeMarkdown } from '@superset-ui/core'; +import { + css, + styled, + Metric, + SafeMarkdown, + SupersetTheme, +} from '@superset-ui/core'; import InfoTooltipWithTrigger from './InfoTooltipWithTrigger'; -import { ColumnTypeLabel } from './ColumnTypeLabel'; +import { ColumnTypeLabel } from './ColumnTypeLabel/ColumnTypeLabel'; import CertifiedIconWithTooltip from './CertifiedIconWithTooltip'; import Tooltip from './Tooltip'; import { getMetricTooltipNode } from './labelUtils'; @@ -70,32 +76,41 @@ export function MetricOption({ return ( {showType && } - {metric.is_certified && ( - - )} - + + css` + margin-right: ${theme.gridUnit}px; + ` + } + ref={labelRef} + > {link} {showFormula && ( )} + {metric.is_certified && ( + + )} {warningMarkdown && ( } label={`warn-${metric.metric_name}`} + iconsStyle={{ marginLeft: 0 }} /> )} diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/index.ts b/superset-frontend/packages/superset-ui-chart-controls/src/index.ts index 6f19d0e4686a2..8a151d10e2a4f 100644 --- a/superset-frontend/packages/superset-ui-chart-controls/src/index.ts +++ b/superset-frontend/packages/superset-ui-chart-controls/src/index.ts @@ -27,7 +27,7 @@ export const sections = sectionsModule; export * from './components/InfoTooltipWithTrigger'; export * from './components/ColumnOption'; -export * from './components/ColumnTypeLabel'; +export * from './components/ColumnTypeLabel/ColumnTypeLabel'; export * from './components/MetricOption'; // React control components diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/shared-controls/components/ColumnConfigControl/ColumnConfigItem.tsx b/superset-frontend/packages/superset-ui-chart-controls/src/shared-controls/components/ColumnConfigControl/ColumnConfigItem.tsx index ee9c1ea17b417..06429ef593a5b 100644 --- a/superset-frontend/packages/superset-ui-chart-controls/src/shared-controls/components/ColumnConfigControl/ColumnConfigItem.tsx +++ b/superset-frontend/packages/superset-ui-chart-controls/src/shared-controls/components/ColumnConfigControl/ColumnConfigItem.tsx @@ -19,7 +19,7 @@ import React from 'react'; import { useTheme } from '@superset-ui/core'; import { Popover } from 'antd'; -import ColumnTypeLabel from '../../../components/ColumnTypeLabel'; +import ColumnTypeLabel from '../../../components/ColumnTypeLabel/ColumnTypeLabel'; import ColumnConfigPopover, { ColumnConfigPopoverProps, } from './ColumnConfigPopover'; diff --git a/superset-frontend/packages/superset-ui-chart-controls/test/components/ColumnTypeLabel.test.tsx b/superset-frontend/packages/superset-ui-chart-controls/test/components/ColumnTypeLabel.test.tsx index 04f76edca99a0..8369a790968f0 100644 --- a/superset-frontend/packages/superset-ui-chart-controls/test/components/ColumnTypeLabel.test.tsx +++ b/superset-frontend/packages/superset-ui-chart-controls/test/components/ColumnTypeLabel.test.tsx @@ -17,7 +17,8 @@ * under the License. */ import React from 'react'; -import { shallow } from 'enzyme'; +import { render, screen } from '@testing-library/react'; +import '@testing-library/jest-dom'; import { GenericDataType } from '@superset-ui/core'; import { ColumnTypeLabel, ColumnTypeLabelProps } from '../../src'; @@ -29,9 +30,8 @@ describe('ColumnOption', () => { const props = { ...defaultProps }; - function getWrapper(overrides: Partial) { - const wrapper = shallow(); - return wrapper; + function renderColumnTypeLabel(overrides: Partial) { + render(); } it('is a valid element', () => { @@ -40,40 +40,27 @@ describe('ColumnOption', () => { ); }); it('string type shows ABC icon', () => { - const lbl = getWrapper({ type: GenericDataType.STRING }).find( - '.type-label', - ); - expect(lbl).toHaveLength(1); - expect(lbl.first().text()).toBe('ABC'); + renderColumnTypeLabel({ type: GenericDataType.STRING }); + expect(screen.getByLabelText('string type icon')).toBeVisible(); }); it('int type shows # icon', () => { - const lbl = getWrapper({ type: GenericDataType.NUMERIC }).find( - '.type-label', - ); - expect(lbl).toHaveLength(1); - expect(lbl.first().text()).toBe('#'); + renderColumnTypeLabel({ type: GenericDataType.NUMERIC }); + expect(screen.getByLabelText('numeric type icon')).toBeVisible(); }); - it('bool type shows T/F icon', () => { - const lbl = getWrapper({ type: GenericDataType.BOOLEAN }).find( - '.type-label', - ); - expect(lbl).toHaveLength(1); - expect(lbl.first().text()).toBe('T/F'); + it('bool type shows 1|0 icon', () => { + renderColumnTypeLabel({ type: GenericDataType.BOOLEAN }); + expect(screen.getByLabelText('boolean type icon')).toBeVisible(); }); it('expression type shows function icon', () => { - const lbl = getWrapper({ type: 'expression' }).find('.type-label'); - expect(lbl).toHaveLength(1); - expect(lbl.first().text()).toBe('ƒ'); + renderColumnTypeLabel({ type: 'expression' }); + expect(screen.getByLabelText('function type icon')).toBeVisible(); }); it('unknown type shows question mark', () => { - const lbl = getWrapper({ type: undefined }).find('.type-label'); - expect(lbl).toHaveLength(1); - expect(lbl.first().text()).toBe('?'); + renderColumnTypeLabel({ type: undefined }); + expect(screen.getByLabelText('unknown type icon')).toBeVisible(); }); it('datetime type displays', () => { - const lbl = getWrapper({ type: GenericDataType.TEMPORAL }).find( - '.fa-clock-o', - ); - expect(lbl).toHaveLength(1); + renderColumnTypeLabel({ type: GenericDataType.TEMPORAL }); + expect(screen.getByLabelText('temporal type icon')).toBeVisible(); }); }); diff --git a/superset-frontend/src/assets/images/icons/drag.svg b/superset-frontend/src/assets/images/icons/drag.svg index dd2946cd13d12..9d4aa0a5f941d 100644 --- a/superset-frontend/src/assets/images/icons/drag.svg +++ b/superset-frontend/src/assets/images/icons/drag.svg @@ -16,9 +16,7 @@ KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> - - - + + + diff --git a/superset-frontend/src/dashboard/components/dnd/DragHandle.tsx b/superset-frontend/src/dashboard/components/dnd/DragHandle.tsx index 08a224e4b80a3..5209c99fee728 100644 --- a/superset-frontend/src/dashboard/components/dnd/DragHandle.tsx +++ b/superset-frontend/src/dashboard/components/dnd/DragHandle.tsx @@ -17,33 +17,35 @@ * under the License. */ import React, { LegacyRef } from 'react'; -import cx from 'classnames'; +import { css, styled } from '@superset-ui/core'; +import Icons from 'src/components/Icons'; interface DragHandleProps { position: 'left' | 'top'; - innerRef: LegacyRef | undefined; - dotCount: number; + innerRef?: LegacyRef | undefined; } +const DragHandleContainer = styled.div<{ position: 'left' | 'top' }>` + ${({ theme, position }) => css` + height: ${theme.gridUnit * 5}px; + overflow: hidden; + cursor: move; + ${position === 'top' && + css` + transform: rotate(90deg); + `} + & path { + fill: ${theme.colors.grayscale.base}; + } + `} +`; export default function DragHandle({ position = 'left', innerRef = null, - dotCount = 8, }: DragHandleProps) { return ( -
- {Array(dotCount) - .fill(null) - .map((_, i) => ( -
- ))} -
+ + + ); } diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/DraggableFilter.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/DraggableFilter.tsx index 7a4827c80bcf0..556e3ed32df7b 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/DraggableFilter.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/DraggableFilter.tsx @@ -132,7 +132,12 @@ export const DraggableFilter: React.FC = ({ drag(drop(ref)); return ( - +
{children}
); diff --git a/superset-frontend/src/dashboard/stylesheets/dnd.less b/superset-frontend/src/dashboard/stylesheets/dnd.less index 2cc990217033e..3c179a439694c 100644 --- a/superset-frontend/src/dashboard/stylesheets/dnd.less +++ b/superset-frontend/src/dashboard/stylesheets/dnd.less @@ -91,33 +91,6 @@ min-height: 16px; } -/* drag handles */ -.drag-handle { - overflow: hidden; - width: 16px; - cursor: move; -} - -.drag-handle--left { - width: 8px; -} - -.drag-handle-dot { - float: left; - height: 2px; - margin: 1px; - width: 2px; - - &:after { - content: ''; - background: @gray; - float: left; - height: 2px; - margin: -1px; - width: 2px; - } -} - /* empty drop targets */ .dashboard-component-tabs-content { & > .empty-droptarget { diff --git a/superset-frontend/src/explore/components/DatasourcePanel/DatasourcePanelDragOption/index.tsx b/superset-frontend/src/explore/components/DatasourcePanel/DatasourcePanelDragOption/index.tsx index 518f7ebabc8be..613a58e15d6d3 100644 --- a/superset-frontend/src/explore/components/DatasourcePanel/DatasourcePanelDragOption/index.tsx +++ b/superset-frontend/src/explore/components/DatasourcePanel/DatasourcePanelDragOption/index.tsx @@ -18,29 +18,36 @@ */ import React from 'react'; import { useDrag } from 'react-dnd'; -import { Metric, styled } from '@superset-ui/core'; +import { css, Metric, styled } from '@superset-ui/core'; +import { ColumnMeta } from '@superset-ui/chart-controls'; import { DndItemType } from 'src/explore/components/DndItemType'; import { StyledColumnOption, StyledMetricOption, } from 'src/explore/components/optionRenderers'; -import { ColumnMeta } from '@superset-ui/chart-controls'; +import Icons from 'src/components/Icons'; + import { DatasourcePanelDndItem } from '../types'; const DatasourceItemContainer = styled.div` - display: flex; - align-items: center; - width: 100%; - height: ${({ theme }) => theme.gridUnit * 6}px; - cursor: pointer; - - > div { + ${({ theme }) => css` + display: flex; + align-items: center; + justify-content: space-between; width: 100%; - } + height: ${theme.gridUnit * 6}px; + padding: 0 ${theme.gridUnit}px; + + // hack to make the drag preview image corners rounded + transform: translate(0, 0); + background-color: inherit; + border-radius: 4px; - :hover { - background-color: ${({ theme }) => theme.colors.grayscale.light2}; - } + > div { + min-width: 0; + margin-right: ${theme.gridUnit * 2}px; + } + `} `; interface DatasourcePanelDragOptionProps extends DatasourcePanelDndItem { @@ -79,6 +86,7 @@ export default function DatasourcePanelDragOption( ) : ( )} + ); } diff --git a/superset-frontend/src/explore/components/DatasourcePanel/index.tsx b/superset-frontend/src/explore/components/DatasourcePanel/index.tsx index b15ce16c4733e..70e3ae06517c3 100644 --- a/superset-frontend/src/explore/components/DatasourcePanel/index.tsx +++ b/superset-frontend/src/explore/components/DatasourcePanel/index.tsx @@ -17,6 +17,7 @@ * under the License. */ import React, { useEffect, useMemo, useRef, useState } from 'react'; +import { css, styled, t } from '@superset-ui/core'; import { ColumnMeta, ControlConfig, @@ -24,7 +25,6 @@ import { } from '@superset-ui/chart-controls'; import { debounce } from 'lodash'; import { matchSorter, rankings } from 'match-sorter'; -import { css, styled, t } from '@superset-ui/core'; import Collapse from 'src/components/Collapse'; import { Input } from 'src/components/Input'; import { FAST_DEBOUNCE } from 'src/constants'; @@ -49,6 +49,10 @@ export interface Props { shouldForceUpdate?: number; } +const enableExploreDnd = isFeatureEnabled( + FeatureFlag.ENABLE_EXPLORE_DRAG_AND_DROP, +); + const Button = styled.button` background: none; border: none; @@ -63,7 +67,7 @@ const ButtonContainer = styled.div` const DatasourceContainer = styled.div` ${({ theme }) => css` - background-color: ${theme.colors.grayscale.light4}; + background-color: ${theme.colors.grayscale.light5}; position: relative; height: 100%; display: flex; @@ -97,26 +101,55 @@ const DatasourceContainer = styled.div` `; const LabelWrapper = styled.div` - overflow: hidden; - text-overflow: ellipsis; + ${({ theme }) => css` + overflow: hidden; + text-overflow: ellipsis; + font-size: ${theme.typography.sizes.s}px; + background-color: ${theme.colors.grayscale.light4}; + margin: ${theme.gridUnit * 2}px 0; + border-radius: 4px; + padding: 0 ${theme.gridUnit}px; - & > span { - white-space: nowrap; - } + &:first-of-type { + margin-top: 0; + } + &:last-of-type { + margin-bottom: 0; + } - .option-label { - display: inline; - } + ${enableExploreDnd && + css` + padding: 0; + cursor: pointer; + &:hover { + background-color: ${theme.colors.grayscale.light3}; + } + `} - .metric-option { - & > svg { - min-width: ${({ theme }) => `${theme.gridUnit * 4}px`}; + & > span { + white-space: nowrap; } - & > .option-label { - overflow: hidden; - text-overflow: ellipsis; + + .option-label { + display: inline; + } + + .metric-option { + & > svg { + min-width: ${theme.gridUnit * 4}px; + } + & > .option-label { + overflow: hidden; + text-overflow: ellipsis; + } } - } + `} +`; + +const SectionHeader = styled.span` + ${({ theme }) => css` + font-size: ${theme.typography.sizes.s}px; + `} `; const LabelContainer = (props: { @@ -134,10 +167,6 @@ const LabelContainer = (props: { ); }; -const enableExploreDnd = isFeatureEnabled( - FeatureFlag.ENABLE_EXPLORE_DRAG_AND_DROP, -); - export default function DataSourcePanel({ datasource, controls: { datasource: datasourceControl }, @@ -273,13 +302,12 @@ export default function DataSourcePanel({ />
{t('Metrics')}} + header={{t('Metrics')}} key="metrics" >
@@ -315,7 +343,7 @@ export default function DataSourcePanel({ )} {t('Columns')}} + header={{t('Columns')}} key="column" >
diff --git a/superset-frontend/src/explore/components/ExploreViewContainer/index.jsx b/superset-frontend/src/explore/components/ExploreViewContainer/index.jsx index bf9afd0f039dc..c59f2cd0fe33e 100644 --- a/superset-frontend/src/explore/components/ExploreViewContainer/index.jsx +++ b/superset-frontend/src/explore/components/ExploreViewContainer/index.jsx @@ -101,7 +101,7 @@ const Styles = styled.div` max-height: 100%; } .data-source-selection { - background-color: ${({ theme }) => theme.colors.grayscale.light4}; + background-color: ${({ theme }) => theme.colors.grayscale.light5}; padding: ${({ theme }) => 2 * theme.gridUnit}px 0; border-right: 1px solid ${({ theme }) => theme.colors.grayscale.light2}; } diff --git a/superset-frontend/src/explore/components/controls/MetricControl/FilterDefinitionOption.test.jsx b/superset-frontend/src/explore/components/controls/MetricControl/FilterDefinitionOption.test.jsx index 0e36348d0028c..3b302ef530d0d 100644 --- a/superset-frontend/src/explore/components/controls/MetricControl/FilterDefinitionOption.test.jsx +++ b/superset-frontend/src/explore/components/controls/MetricControl/FilterDefinitionOption.test.jsx @@ -18,14 +18,12 @@ */ /* eslint-disable no-unused-expressions */ import React from 'react'; -import { shallow } from 'enzyme'; -import { styledMount as mount } from 'spec/helpers/theming'; +import { render, screen } from 'spec/helpers/testing-library'; import FilterDefinitionOption from 'src/explore/components/controls/MetricControl/FilterDefinitionOption'; import { AGGREGATES } from 'src/explore/constants'; import AdhocMetric, { EXPRESSION_TYPES, } from 'src/explore/components/controls/MetricControl/AdhocMetric'; -import { StyledColumnOption } from 'src/explore/components/optionRenderers'; const sumValueAdhocMetric = new AdhocMetric({ expressionType: EXPRESSION_TYPES.SIMPLE, @@ -35,25 +33,21 @@ const sumValueAdhocMetric = new AdhocMetric({ describe('FilterDefinitionOption', () => { it('renders a StyledColumnOption given a column', () => { - const wrapper = shallow( - , - ); - expect(wrapper.find(StyledColumnOption)).toExist(); + render(); + expect(screen.getByText('a_column')).toBeVisible(); }); it('renders a StyledColumnOption given an adhoc metric', () => { - const wrapper = shallow( - , - ); - expect(wrapper.find(StyledColumnOption)).toExist(); + render(); + expect(screen.getByText('SUM(source)')).toBeVisible(); }); it('renders the metric name given a saved metric', () => { - const wrapper = mount( + render( , ); - expect(wrapper.find('.option-label').text()).toBe('my_custom_metric'); + expect(screen.getByText('my_custom_metric')).toBeVisible(); }); }); diff --git a/superset-frontend/src/explore/components/controls/OptionControls/index.tsx b/superset-frontend/src/explore/components/controls/OptionControls/index.tsx index fe1d4aeaa1a7c..ad06871849fd8 100644 --- a/superset-frontend/src/explore/components/controls/OptionControls/index.tsx +++ b/superset-frontend/src/explore/components/controls/OptionControls/index.tsx @@ -56,7 +56,6 @@ export const Label = styled.div` padding-left: ${theme.gridUnit}px; svg { margin-right: ${theme.gridUnit}px; - margin-left: ${theme.gridUnit}px; } .type-label { margin-right: ${theme.gridUnit * 2}px; @@ -306,7 +305,7 @@ export const OptionControlLabel = ({ {isExtra && ( diff --git a/superset-frontend/webpack.config.js b/superset-frontend/webpack.config.js index f33cc62d7f451..4cf902e1f3bc0 100644 --- a/superset-frontend/webpack.config.js +++ b/superset-frontend/webpack.config.js @@ -418,6 +418,7 @@ const config = { svgoConfig: { plugins: { removeViewBox: false, + icon: true, }, }, },