diff --git a/superset-frontend/packages/superset-ui-core/src/chart/models/ChartMetadata.ts b/superset-frontend/packages/superset-ui-core/src/chart/models/ChartMetadata.ts index 8b1c4590a3e9..1013eeee2d3b 100644 --- a/superset-frontend/packages/superset-ui-core/src/chart/models/ChartMetadata.ts +++ b/superset-frontend/packages/superset-ui-core/src/chart/models/ChartMetadata.ts @@ -17,7 +17,7 @@ * under the License. */ -import { Behavior } from '../types/Base'; +import { Behavior, ChartLabel } from '../types/Base'; interface LookupTable { [key: string]: boolean; @@ -40,10 +40,13 @@ export interface ChartMetadataConfig { thumbnail: string; useLegacyApi?: boolean; behaviors?: Behavior[]; - deprecated?: boolean; exampleGallery?: ExampleImage[]; tags?: string[]; category?: string | null; + label?: { + name?: ChartLabel; + description?: string; + } | null; } export default class ChartMetadata { @@ -71,14 +74,17 @@ export default class ChartMetadata { enableNoResults: boolean; - deprecated: boolean; - exampleGallery: ExampleImage[]; tags: string[]; category: string | null; + label?: { + name?: ChartLabel; + description?: string; + } | null; + constructor(config: ChartMetadataConfig) { const { name, @@ -92,10 +98,10 @@ export default class ChartMetadata { behaviors = [], datasourceCount = 1, enableNoResults = true, - deprecated = false, exampleGallery = [], tags = [], category = null, + label = null, } = config; this.name = name; @@ -118,10 +124,10 @@ export default class ChartMetadata { this.behaviors = behaviors; this.datasourceCount = datasourceCount; this.enableNoResults = enableNoResults; - this.deprecated = deprecated; this.exampleGallery = exampleGallery; this.tags = tags; this.category = category; + this.label = label; } canBeAnnotationType(type: string): boolean { diff --git a/superset-frontend/packages/superset-ui-core/src/chart/types/Base.ts b/superset-frontend/packages/superset-ui-core/src/chart/types/Base.ts index a3fe0f70a3fa..aad547ca2aa5 100644 --- a/superset-frontend/packages/superset-ui-core/src/chart/types/Base.ts +++ b/superset-frontend/packages/superset-ui-core/src/chart/types/Base.ts @@ -52,4 +52,22 @@ export interface PlainObject { [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 {}; diff --git a/superset-frontend/src/explore/components/controls/VizTypeControl/VizTypeGallery.tsx b/superset-frontend/src/explore/components/controls/VizTypeControl/VizTypeGallery.tsx index 7b9ada5d9d8c..dc7afacb6c08 100644 --- a/superset-frontend/src/explore/components/controls/VizTypeControl/VizTypeGallery.tsx +++ b/superset-frontend/src/explore/components/controls/VizTypeControl/VizTypeGallery.tsx @@ -33,8 +33,11 @@ import { ChartMetadata, SupersetTheme, useTheme, + ChartLabel, + ChartLabelWeight, } from '@superset-ui/core'; import { AntdCollapse } from 'src/components'; +import { Tooltip } from 'src/components/Tooltip'; import { Input } from 'src/components/Input'; import Label from 'src/components/Label'; import { usePluginContext } from 'src/components/DynamicPlugins'; @@ -310,6 +313,7 @@ const Examples = styled.div` const thumbnailContainerCss = (theme: SupersetTheme) => css` cursor: pointer; width: ${theme.gridUnit * THUMBNAIL_GRID_UNITS}px; + position: relative; img { 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) { if (typesWithDefaultOrder.has(entry.key)) { return DEFAULT_ORDER.indexOf(entry.key); @@ -378,6 +414,13 @@ const Thumbnail: React.FC = ({ > {type.name} + {type.label?.name && ( + + +
{t(type.label?.name)}
+
+
+ )} ); }; @@ -460,7 +503,8 @@ export default function VizTypeGallery(props: VizTypeGalleryProps) { .map(([key, value]) => ({ key, value })) .filter( ({ value }) => - nativeFilterGate(value.behaviors || []) && !value.deprecated, + nativeFilterGate(value.behaviors || []) && + value.label?.name !== ChartLabel.DEPRECATED, ); result.sort((a, b) => vizSortFactor(a) - vizSortFactor(b)); return result; @@ -545,7 +589,18 @@ export default function VizTypeGallery(props: VizTypeGalleryProps) { if (searchInputValue.trim() === '') { 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]); const focusSearch = useCallback(() => { @@ -739,9 +794,23 @@ export default function VizTypeGallery(props: VizTypeGalleryProps) { {selectedVizMetadata?.name} + {selectedVizMetadata?.label?.name && ( + + + +
{t(selectedVizMetadata.label?.name)}
+
+
+
+ )}
{selectedVizMetadata?.tags.map(tag => (