Skip to content

Commit

Permalink
feat(catalog): visualize compute and storage kind tags in asset searc…
Browse files Browse the repository at this point in the history
…h results (#22298)

## Summary & Motivation
Use the asset's visual icons (compute/storage kind) to give more flavor
to the asset's search result display. This way, users can start to
differentiate results from a glance, rather than thoroughly inspecting
the fuzzy match and full asset key name.

## How I Tested These Changes
local

### Before
<img width="813" alt="Screenshot 2024-06-07 at 1 21 47 PM"
src="https://github.com/dagster-io/dagster/assets/16431325/ccc49646-eb94-4599-a5c8-e3d2e3d2196c">

### After
<img width="809" alt="Screenshot 2024-06-07 at 1 20 59 PM"
src="https://github.com/dagster-io/dagster/assets/16431325/247b1c1a-4d5e-421b-9d8e-eb26267b5fe7">

### For compute kinds without a special tag

<img width="1350" alt="Screenshot 2024-06-07 at 2 30 23 PM"
src="https://github.com/dagster-io/dagster/assets/16431325/c4d27b08-b642-4278-a4e9-6372968e8855">
  • Loading branch information
rexledesma authored Jun 7, 2024
1 parent a7bdb7a commit a21e0f5
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
linkToAssetTableWithStorageKindFilter,
} from '../search/useGlobalSearch';

export const isCanonicalComputeKindTag = (tag: DefinitionTag) => tag.key === 'dagster/compute_kind';
export const isCanonicalStorageKindTag = (tag: DefinitionTag) => tag.key === 'dagster/storage_kind';
export const buildStorageKindTag = (storageKind: string): DefinitionTag =>
buildDefinitionTag({key: 'dagster/storage_kind', value: storageKind});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import {
SearchResultType,
isAssetFilterSearchResultType,
} from './types';
import {isCanonicalComputeKindTag, isCanonicalStorageKindTag} from '../graph/KindTags';
import {KNOWN_TAGS, TagIcon} from '../graph/OpTags';

const iconForType = (type: SearchResultType | AssetFilterSearchResultType): IconName => {
switch (type) {
Expand Down Expand Up @@ -121,6 +123,47 @@ function buildSearchLabel(result: Fuse.FuseResult<SearchResult>): JSX.Element[]
return labelComponents;
}

function buildSearchIcons(item: SearchResult, isHighlight: boolean): JSX.Element[] {
const icons = [];

if (item.type === SearchResultType.Asset) {
const computeKindTag = item.tags?.find(isCanonicalComputeKindTag);
if (computeKindTag && KNOWN_TAGS[computeKindTag.value]) {
const computeKindSearchIcon = <TagIcon label={computeKindTag.value} />;

icons.push(computeKindSearchIcon);
}

const storageKindTag = item.tags?.find(isCanonicalStorageKindTag);
if (storageKindTag && KNOWN_TAGS[storageKindTag.value]) {
const storageKindSearchIcon = <TagIcon label={storageKindTag.value} />;

icons.push(storageKindSearchIcon);
}
}

if (item.type === AssetFilterSearchResultType.ComputeKind) {
if (KNOWN_TAGS[item.label]) {
const computeKindSearchIcon = <TagIcon label={item.label} />;

icons.push(computeKindSearchIcon);
}
}

if (icons.length === 0) {
const defaultSearchIcon = (
<Icon
name={iconForType(item.type)}
color={isHighlight ? Colors.textDefault() : Colors.textLight()}
/>
);

icons.push(defaultSearchIcon);
}

return icons;
}

export const SearchResultItem = React.memo(({isHighlight, onClickResult, result}: ItemProps) => {
const {item} = result;
const element = React.useRef<HTMLLIElement>(null);
Expand Down Expand Up @@ -152,11 +195,8 @@ export const SearchResultItem = React.memo(({isHighlight, onClickResult, result}
$interactive={false}
$textColor={Colors.textDefault()}
>
<Box flex={{gap: 4}}>
<Icon
name={iconForType(item.type)}
color={isHighlight ? Colors.textDefault() : Colors.textLight()}
/>
<Box flex={{direction: 'row', gap: 4, alignItems: 'center'}}>
{buildSearchIcons(item, isHighlight)}
{isAssetFilterSearchResultType(item.type) && (
<Caption>{assetFilterPrefixString(item.type)}:</Caption>
)}
Expand Down
4 changes: 3 additions & 1 deletion js_modules/dagster-ui/packages/ui-core/src/search/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import Fuse from 'fuse.js';

import {DefinitionTag} from '../graphql/types';

export enum SearchResultType {
AssetGroup,
Asset,
Expand Down Expand Up @@ -43,7 +45,7 @@ export type SearchResult = {
description: string;
href: string;
type: SearchResultType | AssetFilterSearchResultType;
tags?: string;
tags?: DefinitionTag[];
numResults?: number;
repoPath?: string;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ import {CloudOSSContext} from '../app/CloudOSSContext';
import {PYTHON_ERROR_FRAGMENT} from '../app/PythonErrorFragment';
import {displayNameForAssetKey, isHiddenAssetGroupJob} from '../asset-graph/Utils';
import {assetDetailsPathForKey} from '../assets/assetDetailsPathForKey';
import {buildStorageKindTag} from '../graph/KindTags';
import {DefinitionTag} from '../graphql/types';
import {buildStorageKindTag, isCanonicalStorageKindTag} from '../graph/KindTags';
import {DefinitionTag, buildDefinitionTag} from '../graphql/types';
import {buildTagString} from '../ui/tagAsString';
import {buildRepoPathForHuman} from '../workspace/buildRepoAddress';
import {repoAddressAsURLString} from '../workspace/repoAddressAsString';
Expand Down Expand Up @@ -192,20 +192,24 @@ const secondaryDataToSearchResults = (

const {nodes} = data.assetsOrError;

const assets = nodes
const assets: SearchResult[] = nodes
.filter(({definition}) => definition !== null)
.map(({key, definition}) => {
return {
label: displayNameForAssetKey(key),
href: assetDetailsPathForKey(key),
segments: key.path,
description: `Asset in ${buildRepoPathForHuman(
definition!.repository.name,
definition!.repository.location.name,
)}`,
type: SearchResultType.Asset,
};
});
.map(({key, definition}) => ({
label: displayNameForAssetKey(key),
description: `Asset in ${buildRepoPathForHuman(
definition!.repository.name,
definition!.repository.location.name,
)}`,
href: assetDetailsPathForKey(key),
type: SearchResultType.Asset,
tags: definition!.tags
.filter(isCanonicalStorageKindTag)
.concat(
definition!.computeKind
? buildDefinitionTag({key: 'dagster/compute_kind', value: definition!.computeKind})
: [],
),
}));

if (!includeAssetFilters) {
return [...assets];
Expand Down

0 comments on commit a21e0f5

Please sign in to comment.