feat(viz-gallery): add 'feature' tag and fuzzy search weighting (#18662)
* feat(viz-gallery): add 'feature' tag and fuzzy search weighting * add search weight * Update superset-frontend/src/explore/components/controls/VizTypeControl/VizTypeGallery.tsx Co-authored-by: Evan Rusackas <evan@preset.io> * Update superset-frontend/src/explore/components/controls/VizTypeControl/VizTypeGallery.tsx Co-authored-by: Evan Rusackas <evan@preset.io> * Update superset-frontend/src/explore/components/controls/VizTypeControl/VizTypeGallery.tsx Co-authored-by: Evan Rusackas <evan@preset.io> * Update superset-frontend/src/explore/components/controls/VizTypeControl/VizTypeGallery.tsx Co-authored-by: Evan Rusackas <evan@preset.io> * some improvements * take metadata out * use chartLabel enum to unify * add test chart * fix cache * Resolving TS Lint issue * Appeasing the linter * Removing one example implementation * Removing another example label implementation * Removing the third example label implementation Co-authored-by: Evan Rusackas <evan@preset.io>
This commit is contained in:
parent
3a78165d13
commit
7524e1e3c8
|
|
@ -17,7 +17,7 @@
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Behavior } from '../types/Base';
|
import { Behavior, ChartLabel } from '../types/Base';
|
||||||
|
|
||||||
interface LookupTable {
|
interface LookupTable {
|
||||||
[key: string]: boolean;
|
[key: string]: boolean;
|
||||||
|
|
@ -40,10 +40,13 @@ export interface ChartMetadataConfig {
|
||||||
thumbnail: string;
|
thumbnail: string;
|
||||||
useLegacyApi?: boolean;
|
useLegacyApi?: boolean;
|
||||||
behaviors?: Behavior[];
|
behaviors?: Behavior[];
|
||||||
deprecated?: boolean;
|
|
||||||
exampleGallery?: ExampleImage[];
|
exampleGallery?: ExampleImage[];
|
||||||
tags?: string[];
|
tags?: string[];
|
||||||
category?: string | null;
|
category?: string | null;
|
||||||
|
label?: {
|
||||||
|
name?: ChartLabel;
|
||||||
|
description?: string;
|
||||||
|
} | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class ChartMetadata {
|
export default class ChartMetadata {
|
||||||
|
|
@ -71,14 +74,17 @@ export default class ChartMetadata {
|
||||||
|
|
||||||
enableNoResults: boolean;
|
enableNoResults: boolean;
|
||||||
|
|
||||||
deprecated: boolean;
|
|
||||||
|
|
||||||
exampleGallery: ExampleImage[];
|
exampleGallery: ExampleImage[];
|
||||||
|
|
||||||
tags: string[];
|
tags: string[];
|
||||||
|
|
||||||
category: string | null;
|
category: string | null;
|
||||||
|
|
||||||
|
label?: {
|
||||||
|
name?: ChartLabel;
|
||||||
|
description?: string;
|
||||||
|
} | null;
|
||||||
|
|
||||||
constructor(config: ChartMetadataConfig) {
|
constructor(config: ChartMetadataConfig) {
|
||||||
const {
|
const {
|
||||||
name,
|
name,
|
||||||
|
|
@ -92,10 +98,10 @@ export default class ChartMetadata {
|
||||||
behaviors = [],
|
behaviors = [],
|
||||||
datasourceCount = 1,
|
datasourceCount = 1,
|
||||||
enableNoResults = true,
|
enableNoResults = true,
|
||||||
deprecated = false,
|
|
||||||
exampleGallery = [],
|
exampleGallery = [],
|
||||||
tags = [],
|
tags = [],
|
||||||
category = null,
|
category = null,
|
||||||
|
label = null,
|
||||||
} = config;
|
} = config;
|
||||||
|
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
|
@ -118,10 +124,10 @@ export default class ChartMetadata {
|
||||||
this.behaviors = behaviors;
|
this.behaviors = behaviors;
|
||||||
this.datasourceCount = datasourceCount;
|
this.datasourceCount = datasourceCount;
|
||||||
this.enableNoResults = enableNoResults;
|
this.enableNoResults = enableNoResults;
|
||||||
this.deprecated = deprecated;
|
|
||||||
this.exampleGallery = exampleGallery;
|
this.exampleGallery = exampleGallery;
|
||||||
this.tags = tags;
|
this.tags = tags;
|
||||||
this.category = category;
|
this.category = category;
|
||||||
|
this.label = label;
|
||||||
}
|
}
|
||||||
|
|
||||||
canBeAnnotationType(type: string): boolean {
|
canBeAnnotationType(type: string): boolean {
|
||||||
|
|
|
||||||
|
|
@ -52,4 +52,22 @@ export interface PlainObject {
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum ChartLabel {
|
||||||
|
VERIFIED = 'VERIFIED',
|
||||||
|
DEPRECATED = 'DEPRECATED',
|
||||||
|
FEATURED = 'FEATURED',
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ChartLabelWeight = {
|
||||||
|
[ChartLabel.DEPRECATED]: {
|
||||||
|
weight: -0.1,
|
||||||
|
},
|
||||||
|
[ChartLabel.VERIFIED]: {
|
||||||
|
weight: 0.2,
|
||||||
|
},
|
||||||
|
[ChartLabel.FEATURED]: {
|
||||||
|
weight: 0.1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
export default {};
|
export default {};
|
||||||
|
|
|
||||||
|
|
@ -33,8 +33,11 @@ import {
|
||||||
ChartMetadata,
|
ChartMetadata,
|
||||||
SupersetTheme,
|
SupersetTheme,
|
||||||
useTheme,
|
useTheme,
|
||||||
|
ChartLabel,
|
||||||
|
ChartLabelWeight,
|
||||||
} from '@superset-ui/core';
|
} from '@superset-ui/core';
|
||||||
import { AntdCollapse } from 'src/components';
|
import { AntdCollapse } from 'src/components';
|
||||||
|
import { Tooltip } from 'src/components/Tooltip';
|
||||||
import { Input } from 'src/components/Input';
|
import { Input } from 'src/components/Input';
|
||||||
import Label from 'src/components/Label';
|
import Label from 'src/components/Label';
|
||||||
import { usePluginContext } from 'src/components/DynamicPlugins';
|
import { usePluginContext } from 'src/components/DynamicPlugins';
|
||||||
|
|
@ -310,6 +313,7 @@ const Examples = styled.div`
|
||||||
const thumbnailContainerCss = (theme: SupersetTheme) => css`
|
const thumbnailContainerCss = (theme: SupersetTheme) => css`
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
width: ${theme.gridUnit * THUMBNAIL_GRID_UNITS}px;
|
width: ${theme.gridUnit * THUMBNAIL_GRID_UNITS}px;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
img {
|
img {
|
||||||
min-width: ${theme.gridUnit * THUMBNAIL_GRID_UNITS}px;
|
min-width: ${theme.gridUnit * THUMBNAIL_GRID_UNITS}px;
|
||||||
|
|
@ -333,6 +337,38 @@ const thumbnailContainerCss = (theme: SupersetTheme) => css`
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const HighlightLabel = styled.div`
|
||||||
|
${({ theme }) => `
|
||||||
|
border: 1px solid ${theme.colors.primary.dark1};
|
||||||
|
box-sizing: border-box;
|
||||||
|
border-radius: ${theme.gridUnit}px;
|
||||||
|
background: ${theme.colors.grayscale.light5};
|
||||||
|
line-height: ${theme.gridUnit * 2.5}px;
|
||||||
|
color: ${theme.colors.primary.dark1};
|
||||||
|
font-size: ${theme.typography.sizes.s}px;
|
||||||
|
font-weight: ${theme.typography.weights.bold};
|
||||||
|
text-align: center;
|
||||||
|
padding: ${theme.gridUnit * 0.5}px ${theme.gridUnit}px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
div {
|
||||||
|
transform: scale(0.83,0.83);
|
||||||
|
}
|
||||||
|
`}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const ThumbnailLabelWrapper = styled.div`
|
||||||
|
position: absolute;
|
||||||
|
right: ${({ theme }) => theme.gridUnit}px;
|
||||||
|
top: ${({ theme }) => theme.gridUnit * 19}px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const TitleLabelWrapper = styled.div`
|
||||||
|
display: inline-block !important;
|
||||||
|
margin-left: ${({ theme }) => theme.gridUnit * 2}px;
|
||||||
|
`;
|
||||||
|
|
||||||
function vizSortFactor(entry: VizEntry) {
|
function vizSortFactor(entry: VizEntry) {
|
||||||
if (typesWithDefaultOrder.has(entry.key)) {
|
if (typesWithDefaultOrder.has(entry.key)) {
|
||||||
return DEFAULT_ORDER.indexOf(entry.key);
|
return DEFAULT_ORDER.indexOf(entry.key);
|
||||||
|
|
@ -378,6 +414,13 @@ const Thumbnail: React.FC<ThumbnailProps> = ({
|
||||||
>
|
>
|
||||||
{type.name}
|
{type.name}
|
||||||
</div>
|
</div>
|
||||||
|
{type.label?.name && (
|
||||||
|
<ThumbnailLabelWrapper>
|
||||||
|
<HighlightLabel>
|
||||||
|
<div>{t(type.label?.name)}</div>
|
||||||
|
</HighlightLabel>
|
||||||
|
</ThumbnailLabelWrapper>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
@ -460,7 +503,8 @@ export default function VizTypeGallery(props: VizTypeGalleryProps) {
|
||||||
.map(([key, value]) => ({ key, value }))
|
.map(([key, value]) => ({ key, value }))
|
||||||
.filter(
|
.filter(
|
||||||
({ value }) =>
|
({ value }) =>
|
||||||
nativeFilterGate(value.behaviors || []) && !value.deprecated,
|
nativeFilterGate(value.behaviors || []) &&
|
||||||
|
value.label?.name !== ChartLabel.DEPRECATED,
|
||||||
);
|
);
|
||||||
result.sort((a, b) => vizSortFactor(a) - vizSortFactor(b));
|
result.sort((a, b) => vizSortFactor(a) - vizSortFactor(b));
|
||||||
return result;
|
return result;
|
||||||
|
|
@ -545,7 +589,18 @@ export default function VizTypeGallery(props: VizTypeGalleryProps) {
|
||||||
if (searchInputValue.trim() === '') {
|
if (searchInputValue.trim() === '') {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
return fuse.search(searchInputValue).map(result => result.item);
|
return fuse
|
||||||
|
.search(searchInputValue)
|
||||||
|
.map(result => result.item)
|
||||||
|
.sort((a, b) => {
|
||||||
|
const aName = a.value?.label?.name;
|
||||||
|
const bName = b.value?.label?.name;
|
||||||
|
const aOrder =
|
||||||
|
aName && ChartLabelWeight[aName] ? ChartLabelWeight[aName].weight : 0;
|
||||||
|
const bOrder =
|
||||||
|
bName && ChartLabelWeight[bName] ? ChartLabelWeight[bName].weight : 0;
|
||||||
|
return bOrder - aOrder;
|
||||||
|
});
|
||||||
}, [searchInputValue, fuse]);
|
}, [searchInputValue, fuse]);
|
||||||
|
|
||||||
const focusSearch = useCallback(() => {
|
const focusSearch = useCallback(() => {
|
||||||
|
|
@ -739,9 +794,23 @@ export default function VizTypeGallery(props: VizTypeGalleryProps) {
|
||||||
<SectionTitle
|
<SectionTitle
|
||||||
css={css`
|
css={css`
|
||||||
grid-area: viz-name;
|
grid-area: viz-name;
|
||||||
|
position: relative;
|
||||||
`}
|
`}
|
||||||
>
|
>
|
||||||
{selectedVizMetadata?.name}
|
{selectedVizMetadata?.name}
|
||||||
|
{selectedVizMetadata?.label?.name && (
|
||||||
|
<Tooltip
|
||||||
|
id="viz-badge-tooltip"
|
||||||
|
placement="top"
|
||||||
|
title={selectedVizMetadata.label?.description}
|
||||||
|
>
|
||||||
|
<TitleLabelWrapper>
|
||||||
|
<HighlightLabel>
|
||||||
|
<div>{t(selectedVizMetadata.label?.name)}</div>
|
||||||
|
</HighlightLabel>
|
||||||
|
</TitleLabelWrapper>
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
</SectionTitle>
|
</SectionTitle>
|
||||||
<TagsWrapper>
|
<TagsWrapper>
|
||||||
{selectedVizMetadata?.tags.map(tag => (
|
{selectedVizMetadata?.tags.map(tag => (
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue