mirror of https://github.com/apache/superset.git
chore: fix explore pills (#19866)
* chore: fix explore pills * fix tests * address comments * add test and remove redundant div * switch to dark text
This commit is contained in:
parent
e4fca89217
commit
3d2fec9604
|
@ -122,12 +122,12 @@ describe('Test datatable', () => {
|
|||
});
|
||||
it('Data Pane opens and loads results', () => {
|
||||
cy.contains('Results').click();
|
||||
cy.get('[data-test="row-count-label"]').contains('26 rows retrieved');
|
||||
cy.get('[data-test="row-count-label"]').contains('26 rows');
|
||||
cy.get('.ant-empty-description').should('not.exist');
|
||||
});
|
||||
it('Datapane loads view samples', () => {
|
||||
cy.contains('Samples').click();
|
||||
cy.get('[data-test="row-count-label"]').contains('1k rows retrieved');
|
||||
cy.get('[data-test="row-count-label"]').contains('1k rows');
|
||||
cy.get('.ant-empty-description').should('not.exist');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { isEqual, isEmpty } from 'lodash';
|
||||
import { t } from '@superset-ui/core';
|
||||
import { styled, t } from '@superset-ui/core';
|
||||
import { sanitizeFormData } from 'src/explore/exploreUtils/formData';
|
||||
import getControlsForVizType from 'src/utils/getControlsForVizType';
|
||||
import { safeStringify } from 'src/utils/safeStringify';
|
||||
|
@ -32,6 +32,18 @@ const propTypes = {
|
|||
currentFormData: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
const StyledLabel = styled.span`
|
||||
${({ theme }) => `
|
||||
font-size: ${theme.typography.sizes.s}px;
|
||||
color: ${theme.colors.grayscale.dark1};
|
||||
background-color: ${theme.colors.alert.base};
|
||||
|
||||
&: hover {
|
||||
background-color: ${theme.colors.alert.dark1};
|
||||
}
|
||||
`}
|
||||
`;
|
||||
|
||||
function alterForComparison(value) {
|
||||
// Considering `[]`, `{}`, `null` and `undefined` as identical
|
||||
// for this purpose
|
||||
|
@ -183,9 +195,7 @@ export default class AlteredSliceTag extends React.Component {
|
|||
renderTriggerNode() {
|
||||
return (
|
||||
<Tooltip id="difference-tooltip" title={t('Click to see difference')}>
|
||||
<span className="label label-warning" style={{ fontSize: '12px' }}>
|
||||
{t('Altered')}
|
||||
</span>
|
||||
<StyledLabel className="label">{t('Altered')}</StyledLabel>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ const CacheLabel: React.FC<CacheLabelProps> = ({
|
|||
onMouseOver={() => setHovered(true)}
|
||||
onMouseOut={() => setHovered(false)}
|
||||
>
|
||||
{t('cached')} <i className="fa fa-refresh" />
|
||||
{t('Cached')} <i className="fa fa-refresh" />
|
||||
</Label>
|
||||
</Tooltip>
|
||||
);
|
||||
|
|
|
@ -26,8 +26,9 @@ export default {
|
|||
excludeStories: 'options',
|
||||
};
|
||||
|
||||
export const options = [
|
||||
export const options: Type[] = [
|
||||
'default',
|
||||
'alert',
|
||||
'info',
|
||||
'success',
|
||||
'warning',
|
||||
|
|
|
@ -23,6 +23,7 @@ import { useTheme } from '@superset-ui/core';
|
|||
export type OnClickHandler = React.MouseEventHandler<HTMLElement>;
|
||||
|
||||
export type Type =
|
||||
| 'alert'
|
||||
| 'success'
|
||||
| 'warning'
|
||||
| 'danger'
|
||||
|
@ -44,9 +45,17 @@ export interface LabelProps extends React.HTMLAttributes<HTMLSpanElement> {
|
|||
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;
|
||||
const { type = 'default', onClick, children, ...rest } = props;
|
||||
const {
|
||||
alert,
|
||||
primary,
|
||||
secondary,
|
||||
grayscale,
|
||||
success,
|
||||
warning,
|
||||
error,
|
||||
info,
|
||||
} = colors;
|
||||
|
||||
let backgroundColor = grayscale.light3;
|
||||
let backgroundColorHover = onClick ? primary.light2 : grayscale.light3;
|
||||
|
@ -54,11 +63,14 @@ export default function Label(props: LabelProps) {
|
|||
let borderColorHover = onClick ? primary.light1 : 'transparent';
|
||||
let color = grayscale.dark1;
|
||||
|
||||
if (type && type !== 'default') {
|
||||
if (type !== 'default') {
|
||||
color = grayscale.light4;
|
||||
|
||||
let baseColor;
|
||||
if (type === 'success') {
|
||||
if (type === 'alert') {
|
||||
color = grayscale.dark1;
|
||||
baseColor = alert;
|
||||
} else if (type === 'success') {
|
||||
baseColor = success;
|
||||
} else if (type === 'warning') {
|
||||
baseColor = warning;
|
||||
|
|
|
@ -20,9 +20,14 @@ import React from 'react';
|
|||
import { render, screen } from 'spec/helpers/testing-library';
|
||||
import { RowCount } from '.';
|
||||
|
||||
test('Render a RowCount', () => {
|
||||
test('Render a RowCount with a single row', () => {
|
||||
render(<RowCount data={[{}]} loading={false} />);
|
||||
expect(screen.getByText('1 row')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('Render a RowCount with multiple rows', () => {
|
||||
render(<RowCount data={[{}, {}, {}]} loading={false} />);
|
||||
expect(screen.getByText('3 rows retrieved')).toBeInTheDocument();
|
||||
expect(screen.getByText('3 rows')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('Render a RowCount on loading', () => {
|
||||
|
|
|
@ -127,13 +127,7 @@ export const RowCount = ({
|
|||
}: {
|
||||
data?: Record<string, any>[];
|
||||
loading: boolean;
|
||||
}) => (
|
||||
<RowCountLabel
|
||||
rowcount={data?.length ?? 0}
|
||||
loading={loading}
|
||||
suffix={t('rows retrieved')}
|
||||
/>
|
||||
);
|
||||
}) => <RowCountLabel rowcount={data?.length ?? 0} loading={loading} />;
|
||||
|
||||
enum FormatPickerValue {
|
||||
Formatted,
|
||||
|
|
|
@ -103,7 +103,7 @@ describe('DataTablesPane', () => {
|
|||
useRedux: true,
|
||||
});
|
||||
userEvent.click(screen.getByText('Results'));
|
||||
expect(await screen.findByText('0 rows retrieved')).toBeVisible();
|
||||
expect(await screen.findByText('0 rows')).toBeVisible();
|
||||
expect(await screen.findByLabelText('Collapse data panel')).toBeVisible();
|
||||
localStorage.clear();
|
||||
});
|
||||
|
@ -114,7 +114,7 @@ describe('DataTablesPane', () => {
|
|||
useRedux: true,
|
||||
});
|
||||
userEvent.click(screen.getByText('Samples'));
|
||||
expect(await screen.findByText('0 rows retrieved')).toBeVisible();
|
||||
expect(await screen.findByText('0 rows')).toBeVisible();
|
||||
expect(await screen.findByLabelText('Collapse data panel')).toBeVisible();
|
||||
});
|
||||
|
||||
|
@ -158,7 +158,7 @@ describe('DataTablesPane', () => {
|
|||
},
|
||||
);
|
||||
userEvent.click(screen.getByText('Results'));
|
||||
expect(await screen.findByText('1 rows retrieved')).toBeVisible();
|
||||
expect(await screen.findByText('1 row')).toBeVisible();
|
||||
|
||||
userEvent.click(screen.getByLabelText('Copy'));
|
||||
expect(copyToClipboardSpy).toHaveBeenCalledWith(
|
||||
|
@ -210,7 +210,7 @@ describe('DataTablesPane', () => {
|
|||
},
|
||||
);
|
||||
userEvent.click(screen.getByText('Results'));
|
||||
expect(await screen.findByText('2 rows retrieved')).toBeVisible();
|
||||
expect(await screen.findByText('2 rows')).toBeVisible();
|
||||
expect(screen.getByText('Action')).toBeVisible();
|
||||
expect(screen.getByText('Horror')).toBeVisible();
|
||||
|
||||
|
|
|
@ -17,17 +17,21 @@
|
|||
* under the License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import RowCountLabel from '.';
|
||||
import RowCountLabel, { RowCountLabelProps } from '.';
|
||||
|
||||
export default {
|
||||
title: 'RowCountLabel',
|
||||
component: RowCountLabel,
|
||||
};
|
||||
|
||||
const options = {
|
||||
const options: { [key in string]: RowCountLabelProps } = {
|
||||
loading: {
|
||||
loading: true,
|
||||
},
|
||||
single: {
|
||||
rowcount: 1,
|
||||
limit: 100,
|
||||
},
|
||||
full: {
|
||||
rowcount: 100,
|
||||
limit: 100,
|
||||
|
@ -36,10 +40,6 @@ const options = {
|
|||
rowcount: 50,
|
||||
limit: 100,
|
||||
},
|
||||
suffix: {
|
||||
rowcount: 1,
|
||||
suffix: 'suffix',
|
||||
},
|
||||
};
|
||||
|
||||
export const RowCountLabelGallery = () => (
|
||||
|
@ -51,7 +51,6 @@ export const RowCountLabelGallery = () => (
|
|||
loading={options[name].loading}
|
||||
rowcount={options[name].rowcount}
|
||||
limit={options[name].limit}
|
||||
suffix={options[name].suffix}
|
||||
/>
|
||||
</>
|
||||
))}
|
||||
|
|
|
@ -1,50 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import Label from 'src/components/Label';
|
||||
import { Tooltip } from 'src/components/Tooltip';
|
||||
import RowCountLabel from '.';
|
||||
|
||||
describe('RowCountLabel', () => {
|
||||
const defaultProps = {
|
||||
rowcount: 51,
|
||||
limit: 100,
|
||||
};
|
||||
|
||||
it('is valid', () => {
|
||||
expect(React.isValidElement(<RowCountLabel {...defaultProps} />)).toBe(
|
||||
true,
|
||||
);
|
||||
});
|
||||
it('renders a Label and a Tooltip', () => {
|
||||
const wrapper = shallow(<RowCountLabel {...defaultProps} />);
|
||||
expect(wrapper.find(Label)).toExist();
|
||||
expect(wrapper.find(Tooltip)).toExist();
|
||||
});
|
||||
it('renders a danger when limit is reached', () => {
|
||||
const props = {
|
||||
rowcount: 100,
|
||||
limit: 100,
|
||||
};
|
||||
const wrapper = shallow(<RowCountLabel {...props} />);
|
||||
expect(wrapper.find(Label).first().props().type).toBe('danger');
|
||||
});
|
||||
});
|
|
@ -0,0 +1,65 @@
|
|||
/**
|
||||
* 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 RowCountLabel from '.';
|
||||
|
||||
test('RowCountLabel renders singular result', () => {
|
||||
render(<RowCountLabel rowcount={1} limit={100} />);
|
||||
const expectedText = '1 row';
|
||||
expect(screen.getByText(expectedText)).toBeInTheDocument();
|
||||
userEvent.hover(screen.getByText(expectedText));
|
||||
expect(screen.queryByRole('tooltip')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('RowCountLabel renders plural result', () => {
|
||||
render(<RowCountLabel rowcount={2} limit={100} />);
|
||||
const expectedText = '2 rows';
|
||||
expect(screen.getByText(expectedText)).toBeInTheDocument();
|
||||
userEvent.hover(screen.getByText(expectedText));
|
||||
expect(screen.queryByRole('tooltip')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('RowCountLabel renders formatted result', () => {
|
||||
render(<RowCountLabel rowcount={1000} limit={10000} />);
|
||||
const expectedText = '1k rows';
|
||||
expect(screen.getByText(expectedText)).toBeInTheDocument();
|
||||
userEvent.hover(screen.getByText(expectedText));
|
||||
expect(screen.queryByRole('tooltip')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('RowCountLabel renders limit with danger and tooltip', async () => {
|
||||
render(<RowCountLabel rowcount={100} limit={100} />);
|
||||
const expectedText = '100 rows';
|
||||
expect(screen.getByText(expectedText)).toBeInTheDocument();
|
||||
userEvent.hover(screen.getByText(expectedText));
|
||||
const tooltip = await screen.findByRole('tooltip');
|
||||
expect(tooltip).toHaveTextContent('Limit reached');
|
||||
expect(tooltip).toHaveStyle('background: rgba(0, 0, 0, 0.902);');
|
||||
});
|
||||
|
||||
test('RowCountLabel renders loading', () => {
|
||||
render(<RowCountLabel loading />);
|
||||
const expectedText = 'Loading...';
|
||||
expect(screen.getByText(expectedText)).toBeInTheDocument();
|
||||
userEvent.hover(screen.getByText(expectedText));
|
||||
expect(screen.queryByRole('tooltip')).not.toBeInTheDocument();
|
||||
});
|
|
@ -17,36 +17,36 @@
|
|||
* under the License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { getNumberFormatter, t } from '@superset-ui/core';
|
||||
import { getNumberFormatter, t, tn } from '@superset-ui/core';
|
||||
|
||||
import Label from 'src/components/Label';
|
||||
import { Tooltip } from 'src/components/Tooltip';
|
||||
|
||||
type RowCountLabelProps = {
|
||||
rowcount: number;
|
||||
rowcount?: number;
|
||||
limit?: number;
|
||||
suffix?: string;
|
||||
loading?: boolean;
|
||||
};
|
||||
|
||||
export default function RowCountLabel(props: RowCountLabelProps) {
|
||||
const { rowcount = 0, limit, suffix = t('rows'), loading } = props;
|
||||
const { rowcount = 0, limit, loading } = props;
|
||||
const limitReached = rowcount === limit;
|
||||
const type =
|
||||
limitReached || (rowcount === 0 && !loading) ? 'danger' : 'default';
|
||||
const formattedRowCount = getNumberFormatter()(rowcount);
|
||||
const tooltip = (
|
||||
<span>
|
||||
{limitReached && <div>{t('Limit reached')}</div>}
|
||||
{loading ? 'Loading' : rowcount}
|
||||
</span>
|
||||
const label = (
|
||||
<Label type={type} data-test="row-count-label">
|
||||
{loading
|
||||
? t('Loading...')
|
||||
: tn('%s row', '%s rows', rowcount, formattedRowCount)}
|
||||
</Label>
|
||||
);
|
||||
return (
|
||||
<Tooltip id="tt-rowcount-tooltip" title={tooltip}>
|
||||
<Label type={type} data-test="row-count-label">
|
||||
{loading ? 'Loading...' : `${formattedRowCount} ${suffix}`}
|
||||
</Label>
|
||||
return limitReached ? (
|
||||
<Tooltip id="tt-rowcount-tooltip" title={<span>{t('Limit reached')}</span>}>
|
||||
{label}
|
||||
</Tooltip>
|
||||
) : (
|
||||
label
|
||||
);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue