You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by ru...@apache.org on 2021/02/02 06:15:57 UTC
[superset] branch master updated: Migrates Label component from
Bootstrap to AntD. (#12774)
This is an automated email from the ASF dual-hosted git repository.
rusackas pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git
The following commit(s) were added to refs/heads/master by this push:
new 2adfb85 Migrates Label component from Bootstrap to AntD. (#12774)
2adfb85 is described below
commit 2adfb8559736bff97b47c6fee2725b4344c4ebf3
Author: Michael S. Molina <70...@users.noreply.github.com>
AuthorDate: Tue Feb 2 03:15:07 2021 -0300
Migrates Label component from Bootstrap to AntD. (#12774)
---
.../cypress/integration/explore/control.test.ts | 2 +-
.../explore/visualizations/table.test.ts | 2 +-
.../spec/javascripts/components/Timer_spec.tsx | 5 +-
.../explore/components/RowCountLabel_spec.jsx | 2 +-
.../spec/javascripts/profile/Security_spec.tsx | 12 +-
.../src/SqlLab/components/QueryStateLabel.jsx | 6 +-
.../src/SqlLab/components/QueryTable.jsx | 2 +-
.../src/SqlLab/components/SouthPane.jsx | 7 +-
.../src/SqlLab/components/SqlEditor.jsx | 6 +-
superset-frontend/src/SqlLab/constants.ts | 2 +-
.../src/addSlice/AddSliceContainer.tsx | 2 +-
superset-frontend/src/common/components/index.tsx | 1 +
superset-frontend/src/components/CachedLabel.jsx | 4 +-
.../src/components/DatabaseSelector.tsx | 11 +-
.../src/components/Label/Label.stories.tsx | 63 +++----
.../src/components/Label/Label.test.tsx | 18 +-
superset-frontend/src/components/Label/index.tsx | 209 ++++++++-------------
superset-frontend/src/components/Timer.tsx | 9 +-
.../src/explore/components/RowCountLabel.jsx | 4 +-
.../explore/components/controls/VizTypeControl.jsx | 12 +-
.../src/views/CRUD/chart/ChartCard.tsx | 2 +-
21 files changed, 159 insertions(+), 222 deletions(-)
diff --git a/superset-frontend/cypress-base/cypress/integration/explore/control.test.ts b/superset-frontend/cypress-base/cypress/integration/explore/control.test.ts
index 70b0135..c65b5df 100644
--- a/superset-frontend/cypress-base/cypress/integration/explore/control.test.ts
+++ b/superset-frontend/cypress-base/cypress/integration/explore/control.test.ts
@@ -104,7 +104,7 @@ describe('VizType control', () => {
numScripts = nodes.length;
});
- cy.get('.Control .label').contains('Table').click();
+ cy.get('[data-test="visualization-type"]').contains('Table').click();
cy.get('[role="button"]').contains('Line Chart').click();
diff --git a/superset-frontend/cypress-base/cypress/integration/explore/visualizations/table.test.ts b/superset-frontend/cypress-base/cypress/integration/explore/visualizations/table.test.ts
index 868d2fe..0af7dce 100644
--- a/superset-frontend/cypress-base/cypress/integration/explore/visualizations/table.test.ts
+++ b/superset-frontend/cypress-base/cypress/integration/explore/visualizations/table.test.ts
@@ -161,7 +161,7 @@ describe('Visualization > Table', () => {
cy.verifySliceContainer('table');
expect(response?.body.result[0].data.length).to.eq(limit);
});
- cy.get('span.label-danger').contains('10 rows');
+ cy.get('[data-test="row-count-label"]').contains('10 rows');
});
it('Test table with columns and row limit', () => {
diff --git a/superset-frontend/spec/javascripts/components/Timer_spec.tsx b/superset-frontend/spec/javascripts/components/Timer_spec.tsx
index 4af7ae7..f37004a 100644
--- a/superset-frontend/spec/javascripts/components/Timer_spec.tsx
+++ b/superset-frontend/spec/javascripts/components/Timer_spec.tsx
@@ -21,7 +21,7 @@
*/
import React from 'react';
import { render, sleep, waitFor } from 'spec/helpers/testing-library';
-import Timer from 'src/components/Timer';
+import Timer, { TimerProps } from 'src/components/Timer';
import { now } from 'src/modules/dates';
function parseTime(text?: string | null) {
@@ -29,7 +29,7 @@ function parseTime(text?: string | null) {
}
describe('Timer', () => {
- const mockProps = {
+ const mockProps: TimerProps = {
startTime: now(),
endTime: undefined,
isRunning: true,
@@ -41,7 +41,6 @@ describe('Timer', () => {
const node = screen.getByRole('timer');
let text = node.textContent || '';
expect(node).toBeInTheDocument();
- expect(node).toHaveClass('label-warning');
expect(node).toHaveTextContent('00:00:00.00');
// should start running
await waitFor(() => {
diff --git a/superset-frontend/spec/javascripts/explore/components/RowCountLabel_spec.jsx b/superset-frontend/spec/javascripts/explore/components/RowCountLabel_spec.jsx
index 7776788..13de226 100644
--- a/superset-frontend/spec/javascripts/explore/components/RowCountLabel_spec.jsx
+++ b/superset-frontend/spec/javascripts/explore/components/RowCountLabel_spec.jsx
@@ -45,6 +45,6 @@ describe('RowCountLabel', () => {
limit: 100,
};
const wrapper = shallow(<RowCountLabel {...props} />);
- expect(wrapper.find(Label).first().props().bsStyle).toBe('danger');
+ expect(wrapper.find(Label).first().props().type).toBe('danger');
});
});
diff --git a/superset-frontend/spec/javascripts/profile/Security_spec.tsx b/superset-frontend/spec/javascripts/profile/Security_spec.tsx
index 6732e7b..31eda0a 100644
--- a/superset-frontend/spec/javascripts/profile/Security_spec.tsx
+++ b/superset-frontend/spec/javascripts/profile/Security_spec.tsx
@@ -19,7 +19,7 @@
import React from 'react';
import { styledMount as mount } from 'spec/helpers/theming';
import Security from 'src/profile/components/Security';
-
+import Label from 'src/components/Label';
import { user, userNoPerms } from './fixtures';
describe('Security', () => {
@@ -31,19 +31,19 @@ describe('Security', () => {
});
it('renders 2 role labels', () => {
const wrapper = mount(<Security {...mockedProps} />);
- expect(wrapper.find('.roles').find('.label')).toHaveLength(2);
+ expect(wrapper.find('.roles').find(Label)).toHaveLength(2);
});
it('renders 2 datasource labels', () => {
const wrapper = mount(<Security {...mockedProps} />);
- expect(wrapper.find('.datasources').find('.label')).toHaveLength(2);
+ expect(wrapper.find('.datasources').find(Label)).toHaveLength(2);
});
it('renders 3 database labels', () => {
const wrapper = mount(<Security {...mockedProps} />);
- expect(wrapper.find('.databases').find('.label')).toHaveLength(3);
+ expect(wrapper.find('.databases').find(Label)).toHaveLength(3);
});
it('renders no permission label when empty', () => {
const wrapper = mount(<Security user={userNoPerms} />);
- expect(wrapper.find('.datasources').find('.label')).not.toExist();
- expect(wrapper.find('.databases').find('.label')).not.toExist();
+ expect(wrapper.find('.datasources').find(Label)).not.toExist();
+ expect(wrapper.find('.databases').find(Label)).not.toExist();
});
});
diff --git a/superset-frontend/src/SqlLab/components/QueryStateLabel.jsx b/superset-frontend/src/SqlLab/components/QueryStateLabel.jsx
index 74b0d3f..5afb30b 100644
--- a/superset-frontend/src/SqlLab/components/QueryStateLabel.jsx
+++ b/superset-frontend/src/SqlLab/components/QueryStateLabel.jsx
@@ -20,16 +20,16 @@ import React from 'react';
import PropTypes from 'prop-types';
import Label from 'src/components/Label';
-import { STATE_BSSTYLE_MAP } from '../constants';
+import { STATE_TYPE_MAP } from '../constants';
const propTypes = {
query: PropTypes.object.isRequired,
};
export default function QueryStateLabel({ query }) {
- const bsStyle = STATE_BSSTYLE_MAP[query.state];
+ const type = STATE_TYPE_MAP[query.state];
return (
- <Label className="m-r-3" bsStyle={bsStyle}>
+ <Label className="m-r-3" type={type}>
{query.state}
</Label>
);
diff --git a/superset-frontend/src/SqlLab/components/QueryTable.jsx b/superset-frontend/src/SqlLab/components/QueryTable.jsx
index 6342f00..a4235d2 100644
--- a/superset-frontend/src/SqlLab/components/QueryTable.jsx
+++ b/superset-frontend/src/SqlLab/components/QueryTable.jsx
@@ -143,7 +143,7 @@ const QueryTable = props => {
<ModalTrigger
className="ResultsModal"
triggerNode={
- <Label bsStyle="info" className="pointer">
+ <Label type="info" className="pointer">
{t('View results')}
</Label>
}
diff --git a/superset-frontend/src/SqlLab/components/SouthPane.jsx b/superset-frontend/src/SqlLab/components/SouthPane.jsx
index 8abe498..e2ffa0a 100644
--- a/superset-frontend/src/SqlLab/components/SouthPane.jsx
+++ b/superset-frontend/src/SqlLab/components/SouthPane.jsx
@@ -33,7 +33,7 @@ import QueryHistory from './QueryHistory';
import ResultSet from './ResultSet';
import {
STATUS_OPTIONS,
- STATE_BSSTYLE_MAP,
+ STATE_TYPE_MAP,
LOCALSTORAGE_MAX_QUERY_AGE_MS,
} from '../constants';
@@ -97,10 +97,7 @@ export class SouthPane extends React.PureComponent {
render() {
if (this.props.offline) {
return (
- <Label
- className="m-r-3"
- bsStyle={STATE_BSSTYLE_MAP[STATUS_OPTIONS.offline]}
- >
+ <Label className="m-r-3" type={STATE_TYPE_MAP[STATUS_OPTIONS.offline]}>
{STATUS_OPTIONS.offline}
</Label>
);
diff --git a/superset-frontend/src/SqlLab/components/SqlEditor.jsx b/superset-frontend/src/SqlLab/components/SqlEditor.jsx
index 34bcc2d..ee89a0f 100644
--- a/superset-frontend/src/SqlLab/components/SqlEditor.jsx
+++ b/superset-frontend/src/SqlLab/components/SqlEditor.jsx
@@ -71,7 +71,7 @@ import ShareSqlLabQuery from './ShareSqlLabQuery';
import SqlEditorLeftBar from './SqlEditorLeftBar';
import AceEditorWrapper from './AceEditorWrapper';
import {
- STATE_BSSTYLE_MAP,
+ STATE_TYPE_MAP,
SQL_EDITOR_GUTTER_HEIGHT,
SQL_EDITOR_GUTTER_MARGIN,
SQL_TOOLBAR_HEIGHT,
@@ -575,7 +575,7 @@ class SqlEditor extends React.PureComponent {
this.props.latestQuery.rows,
)}
>
- <Label bsStyle="warning">LIMIT</Label>
+ <Label type="warning">LIMIT</Label>
</Tooltip>
);
}
@@ -670,7 +670,7 @@ class SqlEditor extends React.PureComponent {
<Timer
startTime={this.props.latestQuery.startDttm}
endTime={this.props.latestQuery.endDttm}
- state={STATE_BSSTYLE_MAP[this.props.latestQuery.state]}
+ state={STATE_TYPE_MAP[this.props.latestQuery.state]}
isRunning={this.props.latestQuery.state === 'running'}
/>
)}
diff --git a/superset-frontend/src/SqlLab/constants.ts b/superset-frontend/src/SqlLab/constants.ts
index e191ab9..7d0ea09 100644
--- a/superset-frontend/src/SqlLab/constants.ts
+++ b/superset-frontend/src/SqlLab/constants.ts
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-export const STATE_BSSTYLE_MAP = {
+export const STATE_TYPE_MAP = {
offline: 'danger',
failed: 'danger',
pending: 'info',
diff --git a/superset-frontend/src/addSlice/AddSliceContainer.tsx b/superset-frontend/src/addSlice/AddSliceContainer.tsx
index 0469461..9e99c20 100644
--- a/superset-frontend/src/addSlice/AddSliceContainer.tsx
+++ b/superset-frontend/src/addSlice/AddSliceContainer.tsx
@@ -134,7 +134,7 @@ export default class AddSliceContainer extends React.PureComponent<
name="select-vis-type"
onChange={this.changeVisType}
value={this.state.visType}
- labelBsStyle="primary"
+ labelType="primary"
/>
</div>
<br />
diff --git a/superset-frontend/src/common/components/index.tsx b/superset-frontend/src/common/components/index.tsx
index f56b09e..bfbccbe 100644
--- a/superset-frontend/src/common/components/index.tsx
+++ b/superset-frontend/src/common/components/index.tsx
@@ -52,6 +52,7 @@ export {
Select,
Skeleton,
Switch,
+ Tag,
Tabs,
Tooltip,
Input as AntdInput,
diff --git a/superset-frontend/src/components/CachedLabel.jsx b/superset-frontend/src/components/CachedLabel.jsx
index db4bd2e..a7bc720 100644
--- a/superset-frontend/src/components/CachedLabel.jsx
+++ b/superset-frontend/src/components/CachedLabel.jsx
@@ -67,12 +67,12 @@ class CacheLabel extends React.PureComponent {
}
render() {
- const labelStyle = this.state.hovered ? 'primary' : 'default';
+ const labelType = this.state.hovered ? 'primary' : 'default';
return (
<TooltipWrapper tooltip={this.state.tooltipContent} label="cache-desc">
<Label
className={`${this.props.className}`}
- bsStyle={labelStyle}
+ type={labelType}
onClick={this.props.onClick}
onMouseOver={this.mouseOver.bind(this)}
onMouseOut={this.mouseOut.bind(this)}
diff --git a/superset-frontend/src/components/DatabaseSelector.tsx b/superset-frontend/src/components/DatabaseSelector.tsx
index 0d565f9..4cc2e73 100644
--- a/superset-frontend/src/components/DatabaseSelector.tsx
+++ b/superset-frontend/src/components/DatabaseSelector.tsx
@@ -54,6 +54,11 @@ const DatabaseSelectorWrapper = styled.div`
}
`;
+const DatabaseOption = styled.span`
+ display: inline-flex;
+ align-items: center;
+`;
+
interface DatabaseSelectorProps {
dbId: number;
formMode?: boolean;
@@ -184,9 +189,9 @@ export default function DatabaseSelector({
function renderDatabaseOption(db: any) {
return (
- <span title={db.database_name}>
- <Label bsStyle="default">{db.backend}</Label> {db.database_name}
- </span>
+ <DatabaseOption title={db.database_name}>
+ <Label type="default">{db.backend}</Label> {db.database_name}
+ </DatabaseOption>
);
}
diff --git a/superset-frontend/src/components/Label/Label.stories.tsx b/superset-frontend/src/components/Label/Label.stories.tsx
index fe5dfdb..07fc7c0 100644
--- a/superset-frontend/src/components/Label/Label.stories.tsx
+++ b/superset-frontend/src/components/Label/Label.stories.tsx
@@ -18,59 +18,52 @@
*/
import React from 'react';
import { action } from '@storybook/addon-actions';
-import { withKnobs, select, boolean, text } from '@storybook/addon-knobs';
-import Label from './index';
+import Label, { Type } from './index';
export default {
title: 'Label',
component: Label,
- decorators: [withKnobs],
- excludeStories: /.*Knob$/,
+ excludeStories: 'options',
};
-export const bsStyleKnob = {
- label: 'Types',
- options: {
- default: 'default',
- info: 'info',
- success: 'success',
- warning: 'warning',
- danger: 'danger',
- secondary: 'secondary',
- primary: 'primary',
- },
- defaultValue: 'default',
-};
+export const options = [
+ 'default',
+ 'info',
+ 'success',
+ 'warning',
+ 'danger',
+ 'primary',
+ 'secondary',
+];
export const LabelGallery = () => (
<>
<h4>Non-interactive</h4>
- {Object.values(bsStyleKnob.options).map(opt => (
- <Label key={opt} bsStyle={opt}>
+ {Object.values(options).map((opt: Type) => (
+ <Label key={opt} type={opt}>
{`style: "${opt}"`}
</Label>
))}
<br />
<h4>Interactive</h4>
- {Object.values(bsStyleKnob.options).map(opt => (
- <Label key={opt} bsStyle={opt} onClick={action('clicked')}>
+ {Object.values(options).map((opt: Type) => (
+ <Label key={opt} type={opt} onClick={action('clicked')}>
{`style: "${opt}"`}
</Label>
))}
</>
);
-export const InteractiveLabel = () => (
- <Label
- bsStyle={select(
- bsStyleKnob.label,
- bsStyleKnob.options,
- bsStyleKnob.defaultValue,
- )}
- onClick={
- boolean('Has onClick action', false) ? action('clicked') : undefined
- }
- >
- {text('Label', 'Label!')}
- </Label>
-);
+export const InteractiveLabel = (args: any) => {
+ const { hasOnClick, label, ...rest } = args;
+ return (
+ <Label onClick={hasOnClick ? action('clicked') : undefined} {...rest}>
+ {label}
+ </Label>
+ );
+};
+
+InteractiveLabel.args = {
+ hasOnClick: true,
+ label: 'Example',
+};
diff --git a/superset-frontend/src/components/Label/Label.test.tsx b/superset-frontend/src/components/Label/Label.test.tsx
index 1535d4c..d1879d0 100644
--- a/superset-frontend/src/components/Label/Label.test.tsx
+++ b/superset-frontend/src/components/Label/Label.test.tsx
@@ -21,7 +21,7 @@ import React from 'react';
import { ReactWrapper } from 'enzyme';
import { styledMount as mount } from 'spec/helpers/theming';
import Label from '.';
-import { LabelGallery, bsStyleKnob } from './Label.stories';
+import { LabelGallery, options } from './Label.stories';
describe('Label', () => {
let wrapper: ReactWrapper;
@@ -34,23 +34,13 @@ describe('Label', () => {
it('works with an onClick handler', () => {
const mockAction = jest.fn();
wrapper = mount(<Label onClick={mockAction} />);
- wrapper.find('.label').simulate('click');
+ wrapper.find(Label).simulate('click');
expect(mockAction).toHaveBeenCalled();
});
// test stories from the storybook!
- it('renders all the sorybook gallery variants', () => {
+ it('renders all the storybook gallery variants', () => {
wrapper = mount(<LabelGallery />);
- Object.values(bsStyleKnob.options).forEach(opt => {
- expect(wrapper.find(`.label-${opt}`).at(0).text()).toEqual(
- `style: "${opt}"`,
- );
- });
- });
-
- // test things NOT in the storybook!
- it('renders custom label styles without melting', () => {
- wrapper = mount(<Label bsStyle="foobar" />);
- expect(wrapper.find('Label.label-foobar')).toHaveLength(1);
+ expect(wrapper.find(Label).length).toEqual(options.length * 2);
});
});
diff --git a/superset-frontend/src/components/Label/index.tsx b/superset-frontend/src/components/Label/index.tsx
index 18bd1d2..781e15f 100644
--- a/superset-frontend/src/components/Label/index.tsx
+++ b/superset-frontend/src/components/Label/index.tsx
@@ -17,149 +17,98 @@
* under the License.
*/
import React, { CSSProperties } from 'react';
-import { Label as BootstrapLabel } from 'react-bootstrap';
-import { styled } from '@superset-ui/core';
-import cx from 'classnames';
+import { Tag } from 'src/common/components';
+import { useTheme } from '@superset-ui/core';
-export type OnClickHandler = React.MouseEventHandler<BootstrapLabel>;
+export type OnClickHandler = React.MouseEventHandler<HTMLElement>;
+
+export type Type =
+ | 'success'
+ | 'warning'
+ | 'danger'
+ | 'info'
+ | 'default'
+ | 'primary'
+ | 'secondary';
export interface LabelProps {
key?: string;
className?: string;
- id?: string;
- tooltip?: string;
- placement?: string;
onClick?: OnClickHandler;
- bsStyle?: string;
+ type?: Type;
style?: CSSProperties;
children?: React.ReactNode;
role?: string;
}
-const SupersetLabel = styled(BootstrapLabel)`
- /* un-bunch them! */
- margin-right: ${({ theme }) => theme.gridUnit}px;
- max-width: 100%;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- vertical-align: middle;
+export default function Label(props: LabelProps) {
+ const theme = useTheme();
+ const { colors, transitionTiming } = theme;
+ const { type, onClick, children, ...rest } = props;
+ const {
+ primary,
+ secondary,
+ grayscale,
+ success,
+ warning,
+ error,
+ info,
+ } = colors;
- &:first-of-type {
- margin-left: 0;
- }
- &:last-of-type {
- margin-right: 0;
- }
- display: inline-block;
- border-width: 1px;
- border-style: solid;
- cursor: ${({ onClick }) => (onClick ? 'pointer' : 'default')};
- transition: background-color ${({ theme }) => theme.transitionTiming}s;
- &.label-warning {
- background-color: ${({ theme }) => theme.colors.warning.base};
- border-color: ${({ theme, onClick }) =>
- onClick ? theme.colors.warning.dark1 : 'transparent'};
- &:hover {
- background-color: ${({ theme, onClick }) =>
- onClick ? theme.colors.warning.dark1 : theme.colors.warning.base};
- border-color: ${({ theme, onClick }) =>
- onClick ? theme.colors.warning.dark2 : 'transparent'};
- }
- }
- &.label-danger {
- background-color: ${({ theme }) => theme.colors.error.base};
- border-color: ${({ theme, onClick }) =>
- onClick ? theme.colors.error.dark1 : 'transparent'};
- &:hover {
- background-color: ${({ theme, onClick }) =>
- onClick ? theme.colors.error.dark1 : theme.colors.error.base};
- border-color: ${({ theme, onClick }) =>
- onClick ? theme.colors.error.dark2 : 'transparent'};
- }
- }
- &.label-success {
- background-color: ${({ theme }) => theme.colors.success.base};
- border-color: ${({ theme, onClick }) =>
- onClick ? theme.colors.success.dark1 : 'transparent'};
- &:hover {
- background-color: ${({ theme, onClick }) =>
- onClick ? theme.colors.success.dark1 : theme.colors.success.base};
- border-color: ${({ theme, onClick }) =>
- onClick ? theme.colors.success.dark2 : 'transparent'};
- }
- }
- &.label-default {
- background-color: ${({ theme }) => theme.colors.grayscale.light3};
- color: ${({ theme }) => theme.colors.grayscale.dark1};
- border-color: ${({ theme, onClick }) =>
- onClick ? theme.colors.grayscale.light2 : 'transparent'};
- &:hover {
- background-color: ${({ theme, onClick }) =>
- onClick ? theme.colors.primary.light2 : theme.colors.grayscale.light3};
- border-color: ${({ theme, onClick }) =>
- onClick ? theme.colors.primary.light1 : 'transparent'};
- }
- }
- &.label-info {
- background-color: ${({ theme }) => theme.colors.info};
- border-color: ${({ theme, onClick }) =>
- onClick ? theme.colors.info.dark1 : 'transparent'};
- &:hover {
- background-color: ${({ theme, onClick }) =>
- onClick ? theme.colors.info.dark1 : theme.colors.info.base};
- border-color: ${({ theme, onClick }) =>
- onClick ? theme.colors.info.dark2 : 'transparent'};
- }
- }
- &.label-primary {
- background-color: ${({ theme }) => theme.colors.primary.base};
- border-color: ${({ theme, onClick }) =>
- onClick ? theme.colors.primary.dark1 : 'transparent'};
- &:hover {
- background-color: ${({ theme, onClick }) =>
- onClick ? theme.colors.primary.dark2 : theme.colors.primary.base};
- border-color: ${({ theme, onClick }) =>
- onClick
- ? theme.colors.primary.dark2
- : 'transparent'}; /* would be nice if we had a darker color, but that's the floor! */
- }
- }
- /* note this is NOT a supported bootstrap label Style... this overrides default */
- &.label-secondary {
- background-color: ${({ theme }) => theme.colors.secondary.base};
- color: ${({ theme }) => theme.colors.grayscale.light4};
- border-color: ${({ theme, onClick }) =>
- onClick ? theme.colors.secondary.dark1 : 'transparent'};
- &:hover {
- background-color: ${({ theme, onClick }) =>
- onClick ? theme.colors.secondary.dark1 : theme.colors.secondary.base};
- border-color: ${({ theme, onClick }) =>
- onClick ? theme.colors.secondary.dark2 : 'transparent'};
+ let backgroundColor = grayscale.light3;
+ let backgroundColorHover = onClick ? primary.light2 : grayscale.light3;
+ let borderColor = onClick ? grayscale.light2 : 'transparent';
+ let borderColorHover = onClick ? primary.light1 : 'transparent';
+ let color = grayscale.dark1;
+
+ if (type && type !== 'default') {
+ color = grayscale.light4;
+
+ let baseColor;
+ if (type === 'success') {
+ baseColor = success;
+ } else if (type === 'warning') {
+ baseColor = warning;
+ } else if (type === 'danger') {
+ baseColor = error;
+ } else if (type === 'info') {
+ baseColor = info;
+ } else if (type === 'secondary') {
+ baseColor = secondary;
+ } else {
+ baseColor = primary;
}
+
+ backgroundColor = baseColor.base;
+ backgroundColorHover = onClick ? baseColor.dark1 : baseColor.base;
+ borderColor = onClick ? baseColor.dark1 : 'transparent';
+ borderColorHover = onClick ? baseColor.dark2 : 'transparent';
}
-`;
-export default function Label(props: LabelProps) {
- const officialBootstrapStyles = [
- 'success',
- 'warning',
- 'danger',
- 'info',
- 'default',
- 'primary',
- ];
- const labelProps = {
- ...props,
- placement: props.placement || 'top',
- bsStyle: officialBootstrapStyles.includes(props.bsStyle || '')
- ? props.bsStyle
- : 'default',
- className: cx(props.className, {
- [`label-${props.bsStyle}`]: !officialBootstrapStyles.includes(
- props.bsStyle || '',
- ),
- }),
- };
- return <SupersetLabel {...labelProps}>{props.children}</SupersetLabel>;
+ return (
+ <Tag
+ css={{
+ transition: `background-color ${transitionTiming}s`,
+ whiteSpace: 'nowrap',
+ cursor: onClick ? 'pointer' : 'default',
+ overflow: 'hidden',
+ textOverflow: 'ellipsis',
+ backgroundColor,
+ borderColor,
+ borderRadius: 21,
+ padding: '0.35em 0.8em',
+ lineHeight: 1,
+ color,
+ '&:hover': {
+ backgroundColor: backgroundColorHover,
+ borderColor: borderColorHover,
+ opacity: 1,
+ },
+ }}
+ onClick={onClick}
+ {...rest}
+ >
+ {children}
+ </Tag>
+ );
}
diff --git a/superset-frontend/src/components/Timer.tsx b/superset-frontend/src/components/Timer.tsx
index 3b87755..612c78d 100644
--- a/superset-frontend/src/components/Timer.tsx
+++ b/superset-frontend/src/components/Timer.tsx
@@ -18,19 +18,18 @@
*/
import React, { useEffect, useRef, useState } from 'react';
import { styled } from '@superset-ui/core';
-import Label from 'src/components/Label';
+import Label, { Type } from 'src/components/Label';
import { now, fDuration } from 'src/modules/dates';
-interface TimerProps {
+export interface TimerProps {
endTime?: number;
isRunning: boolean;
startTime?: number;
- status?: string;
+ status?: Type;
}
const TimerLabel = styled(Label)`
- line-height: 13px;
text-align: left;
width: 91px;
`;
@@ -69,7 +68,7 @@ export default function Timer({
}, [endTime, isRunning, startTime]);
return (
- <TimerLabel bsStyle={status} role="timer">
+ <TimerLabel type={status} role="timer">
{clockStr}
</TimerLabel>
);
diff --git a/superset-frontend/src/explore/components/RowCountLabel.jsx b/superset-frontend/src/explore/components/RowCountLabel.jsx
index 8fce6f8..6bd38ba 100644
--- a/superset-frontend/src/explore/components/RowCountLabel.jsx
+++ b/superset-frontend/src/explore/components/RowCountLabel.jsx
@@ -37,7 +37,7 @@ const defaultProps = {
export default function RowCountLabel({ rowcount, limit, suffix, loading }) {
const limitReached = rowcount === limit;
- const bsStyle =
+ const type =
limitReached || (rowcount === 0 && !loading) ? 'danger' : 'default';
const formattedRowCount = getNumberFormatter()(rowcount);
const tooltip = (
@@ -48,7 +48,7 @@ export default function RowCountLabel({ rowcount, limit, suffix, loading }) {
);
return (
<TooltipWrapper label="tt-rowcount" tooltip={tooltip}>
- <Label bsStyle={bsStyle}>
+ <Label type={type} data-test="row-count-label">
{loading ? 'Loading...' : `${formattedRowCount} ${suffix}`}
</Label>
</TooltipWrapper>
diff --git a/superset-frontend/src/explore/components/controls/VizTypeControl.jsx b/superset-frontend/src/explore/components/controls/VizTypeControl.jsx
index c24c0c3..1f82080 100644
--- a/superset-frontend/src/explore/components/controls/VizTypeControl.jsx
+++ b/superset-frontend/src/explore/components/controls/VizTypeControl.jsx
@@ -34,12 +34,12 @@ const propTypes = {
name: PropTypes.string.isRequired,
onChange: PropTypes.func,
value: PropTypes.string.isRequired,
- labelBsStyle: PropTypes.string,
+ labelType: PropTypes.string,
};
const defaultProps = {
onChange: () => {},
- labelBsStyle: 'default',
+ labelType: 'default',
};
const registry = getChartMetadataRegistry();
@@ -162,7 +162,7 @@ const VizTypeControl = props => {
);
};
- const { value, labelBsStyle } = props;
+ const { value, labelType } = props;
const filterString = filter.toLowerCase();
const filteredTypes = DEFAULT_ORDER.filter(type => registry.has(type))
@@ -201,7 +201,11 @@ const VizTypeControl = props => {
title={t('Click to change visualization type')}
>
<>
- <Label onClick={toggleModal} bsStyle={labelBsStyle}>
+ <Label
+ onClick={toggleModal}
+ type={labelType}
+ data-test="visualization-type"
+ >
{registry.has(value) ? registry.get(value).name : `${value}`}
</Label>
<VizSupportValidation vizType={value} />
diff --git a/superset-frontend/src/views/CRUD/chart/ChartCard.tsx b/superset-frontend/src/views/CRUD/chart/ChartCard.tsx
index c6be62a..a87da37 100644
--- a/superset-frontend/src/views/CRUD/chart/ChartCard.tsx
+++ b/superset-frontend/src/views/CRUD/chart/ChartCard.tsx
@@ -137,7 +137,7 @@ export default function ChartCard({
description={t('Last modified %s', chart.changed_on_delta_humanized)}
coverLeft={<FacePile users={chart.owners || []} />}
coverRight={
- <Label bsStyle="secondary">{chart.datasource_name_text}</Label>
+ <Label type="secondary">{chart.datasource_name_text}</Label>
}
actions={
<ListViewCard.Actions