chore: small viz gallery tweaks (#15900)

* allow passing styles to selector component

* make onClear optional

* remove broken font-size declarations

* fix bad hook dependency

* move all charts selector outside of Collapse

* stop hiding all charts button

* slight copy change

* remove x

* min left pane size

* remove default p bottom margin

* remove unused import

* fix test
This commit is contained in:
David Aaron Suddjian 2021-07-27 18:21:19 -07:00 committed by GitHub
parent 2ce676d20d
commit a3f54a6c7b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 25 additions and 38 deletions

View File

@ -157,7 +157,7 @@ export default class AddSliceContainer extends React.PureComponent<
/> />
<span> <span>
{t( {t(
"If you can't find a dataset, follow the instructions on how to add it in the Superset tutorial.", 'Instructions to add a dataset are available in the Superset tutorial.',
)}{' '} )}{' '}
<a <a
href="https://superset.apache.org/docs/creating-charts-dashboards/first-dashboard#adding-a-new-table" href="https://superset.apache.org/docs/creating-charts-dashboards/first-dashboard#adding-a-new-table"

View File

@ -105,9 +105,7 @@ describe('VizTypeControl', () => {
const visualizations = screen.getByTestId(getTestId('viz-row')); const visualizations = screen.getByTestId(getTestId('viz-row'));
userEvent.click( userEvent.click(screen.getByRole('button', { name: 'ballot All charts' }));
screen.getByRole('button', { name: 'category Table close' }),
);
expect(visualizations).toHaveTextContent(/Time-series Table/); expect(visualizations).toHaveTextContent(/Time-series Table/);

View File

@ -25,6 +25,7 @@ import React, {
useState, useState,
} from 'react'; } from 'react';
import Fuse from 'fuse.js'; import Fuse from 'fuse.js';
import cx from 'classnames';
import { import {
t, t,
styled, styled,
@ -38,7 +39,6 @@ import Label from 'src/components/Label';
import { usePluginContext } from 'src/components/DynamicPlugins'; import { usePluginContext } from 'src/components/DynamicPlugins';
import Icons from 'src/components/Icons'; import Icons from 'src/components/Icons';
import { nativeFilterGate } from 'src/dashboard/components/nativeFilters/utils'; import { nativeFilterGate } from 'src/dashboard/components/nativeFilters/utils';
import { CloseOutlined } from '@ant-design/icons';
import scrollIntoView from 'scroll-into-view-if-needed'; import scrollIntoView from 'scroll-into-view-if-needed';
interface VizTypeGalleryProps { interface VizTypeGalleryProps {
@ -120,7 +120,8 @@ export const VIZ_TYPE_CONTROL_TEST_ID = 'viz-type-control';
const VizPickerLayout = styled.div` const VizPickerLayout = styled.div`
display: grid; display: grid;
grid-template-rows: auto minmax(100px, 1fr) minmax(200px, 35%); grid-template-rows: auto minmax(100px, 1fr) minmax(200px, 35%);
grid-template-columns: auto 5fr; // em is used here because the sidebar should be sized to fit the longest standard tag
grid-template-columns: minmax(14em, auto) 5fr;
grid-template-areas: grid-template-areas:
'sidebar search' 'sidebar search'
'sidebar main' 'sidebar main'
@ -171,9 +172,6 @@ const SearchWrapper = styled.div`
margin-bottom: ${theme.gridUnit}px; margin-bottom: ${theme.gridUnit}px;
margin-left: ${theme.gridUnit * 3}px; margin-left: ${theme.gridUnit * 3}px;
margin-right: ${theme.gridUnit * 3}px; margin-right: ${theme.gridUnit * 3}px;
input {
font-size: ${theme.typography.sizes.s};
}
.ant-input-affix-wrapper { .ant-input-affix-wrapper {
padding-left: ${theme.gridUnit * 2}px; padding-left: ${theme.gridUnit * 2}px;
} }
@ -196,12 +194,10 @@ const SelectorLabel = styled.button`
align-items: center; align-items: center;
cursor: pointer; cursor: pointer;
margin: ${theme.gridUnit}px 0; margin: ${theme.gridUnit}px 0;
padding: 0 ${theme.gridUnit * 6}px 0 ${theme.gridUnit}px; padding: 0 ${theme.gridUnit}px;
border-radius: ${theme.borderRadius}px; border-radius: ${theme.borderRadius}px;
line-height: 2em; line-height: 2em;
font-size: ${theme.typography.sizes.s};
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap; white-space: nowrap;
position: relative; position: relative;
@ -228,12 +224,6 @@ const SelectorLabel = styled.button`
margin-top: ${theme.gridUnit * 1.5}px; margin-top: ${theme.gridUnit * 1.5}px;
} }
& span:last-of-type svg {
position: absolute;
top: ${theme.gridUnit * 2}px;
right: ${theme.gridUnit * 2}px;
}
.cancel { .cancel {
visibility: hidden; visibility: hidden;
} }
@ -293,6 +283,7 @@ const Description = styled.p`
grid-area: description; grid-area: description;
overflow: auto; overflow: auto;
padding-right: ${({ theme }) => theme.gridUnit * 14}px; padding-right: ${({ theme }) => theme.gridUnit * 14}px;
margin: 0;
`; `;
const Examples = styled.div` const Examples = styled.div`
@ -408,8 +399,8 @@ const Selector: React.FC<{
icon: JSX.Element; icon: JSX.Element;
isSelected: boolean; isSelected: boolean;
onClick: (selector: string) => void; onClick: (selector: string) => void;
onClear: (e: React.MouseEvent) => void; className?: string;
}> = ({ selector, icon, isSelected, onClick, onClear }) => { }> = ({ selector, icon, isSelected, onClick, className }) => {
const btnRef = useRef<HTMLButtonElement>(null); const btnRef = useRef<HTMLButtonElement>(null);
// see Element.scrollIntoViewIfNeeded() // see Element.scrollIntoViewIfNeeded()
@ -431,12 +422,11 @@ const Selector: React.FC<{
ref={btnRef} ref={btnRef}
key={selector} key={selector}
name={selector} name={selector}
className={isSelected ? 'selected' : ''} className={cx(className, isSelected && 'selected')}
onClick={() => onClick(selector)} onClick={() => onClick(selector)}
> >
{icon} {icon}
{selector} {selector}
<CloseOutlined className="cancel" onClick={onClear} />
</SelectorLabel> </SelectorLabel>
); );
}; };
@ -515,7 +505,7 @@ export default function VizTypeGallery(props: VizTypeGalleryProps) {
a.localeCompare(b), a.localeCompare(b),
) )
.filter(tag => RECOMMENDED_TAGS.indexOf(tag) === -1), .filter(tag => RECOMMENDED_TAGS.indexOf(tag) === -1),
[chartsByCategory], [chartsByTags],
); );
const sortedMetadata = useMemo( const sortedMetadata = useMemo(
@ -587,15 +577,6 @@ export default function VizTypeGallery(props: VizTypeGalleryProps) {
], ],
); );
const clearSelector = useCallback(e => {
e.stopPropagation();
if (isSearchFocused) {
stopSearching();
}
// clear current selector and set all charts
setActiveSelector(ALL_CHARTS);
}, []);
const sectionMap = useMemo( const sectionMap = useMemo(
() => ({ () => ({
RECOMMENDED_TAGS: { RECOMMENDED_TAGS: {
@ -603,11 +584,6 @@ export default function VizTypeGallery(props: VizTypeGalleryProps) {
icon: <Icons.Tags />, icon: <Icons.Tags />,
selectors: RECOMMENDED_TAGS, selectors: RECOMMENDED_TAGS,
}, },
ALL: {
title: t('All'),
icon: <Icons.Ballot />,
selectors: [ALL_CHARTS],
},
CATEGORY: { CATEGORY: {
title: t('Category'), title: t('Category'),
icon: <Icons.Category />, icon: <Icons.Category />,
@ -631,6 +607,19 @@ export default function VizTypeGallery(props: VizTypeGalleryProps) {
return ( return (
<VizPickerLayout className={className}> <VizPickerLayout className={className}>
<LeftPane> <LeftPane>
<Selector
css={({ gridUnit }) =>
// adjust style for not being inside a collapse
css`
margin: ${gridUnit * 2}px;
margin-bottom: 0;
`
}
selector={ALL_CHARTS}
icon={<Icons.Ballot />}
isSelected={!isActivelySearching && ALL_CHARTS === activeSelector}
onClick={clickSelector}
/>
<Collapse <Collapse
expandIconPosition="right" expandIconPosition="right"
ghost ghost
@ -646,13 +635,13 @@ export default function VizTypeGallery(props: VizTypeGalleryProps) {
> >
{section.selectors.map((selector: string) => ( {section.selectors.map((selector: string) => (
<Selector <Selector
key={selector}
selector={selector} selector={selector}
icon={section.icon} icon={section.icon}
isSelected={ isSelected={
!isActivelySearching && selector === activeSelector !isActivelySearching && selector === activeSelector
} }
onClick={clickSelector} onClick={clickSelector}
onClear={clearSelector}
/> />
))} ))}
</Collapse.Panel> </Collapse.Panel>