From e65c677f5e3818ca8e7a4c739472cb7b20ec6612 Mon Sep 17 00:00:00 2001 From: benpankow Date: Wed, 21 Aug 2024 14:02:01 -0700 Subject: [PATCH] [ui] Replace compute kind, storage kind filters + tags with generic kind --- .../src/asset-graph/AssetGraphExplorer.tsx | 45 ++++++------ .../ui-core/src/asset-graph/AssetNode.tsx | 21 +++--- .../src/asset-graph/types/AssetNode.types.ts | 1 + .../types/useAssetGraphData.types.ts | 2 + .../useAssetGraphExplorerFilters.oss.tsx | 4 +- .../src/assets/AssetNodeDefinition.tsx | 1 + .../ui-core/src/assets/AssetTable.tsx | 6 +- .../ui-core/src/assets/AssetTableFragment.tsx | 1 + .../ui-core/src/assets/AssetsCatalogTable.tsx | 4 +- .../__tests__/filterAssetDefinition.test.tsx | 26 ++++++- .../assets/types/AssetNodeDefinition.types.ts | 1 + .../assets/types/AssetTableFragment.types.ts | 2 + .../src/assets/types/AssetView.types.ts | 2 + .../assets/types/AssetsCatalogTable.types.ts | 3 + .../assets/useAssetCatalogFiltering.oss.tsx | 39 +++++----- .../useAssetDefinitionFilterState.oss.tsx | 38 ++++------ .../packages/ui-core/src/graph/KindTags.tsx | 73 ++++++++++++++++--- .../ui-core/src/search/useGlobalSearch.tsx | 16 ++-- .../src/ui/Filters/useAssetTagFilter.tsx | 17 +++++ .../ui/Filters/useComputeKindTagFilter.tsx | 60 --------------- .../ui-core/src/ui/Filters/useKindFilter.tsx | 54 ++++++++++++++ .../packages/ui-core/src/ui/Filters/util.ts | 6 +- .../src/workspace/VirtualizedAssetRow.tsx | 40 +++++----- .../src/workspace/VirtualizedAssetTable.tsx | 6 +- .../types/WorkspaceAssetsQuery.types.ts | 2 + 25 files changed, 276 insertions(+), 194 deletions(-) delete mode 100644 js_modules/dagster-ui/packages/ui-core/src/ui/Filters/useComputeKindTagFilter.tsx create mode 100644 js_modules/dagster-ui/packages/ui-core/src/ui/Filters/useKindFilter.tsx diff --git a/js_modules/dagster-ui/packages/ui-core/src/asset-graph/AssetGraphExplorer.tsx b/js_modules/dagster-ui/packages/ui-core/src/asset-graph/AssetGraphExplorer.tsx index 3447c462cf519..b9bc63da9ab82 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/asset-graph/AssetGraphExplorer.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/asset-graph/AssetGraphExplorer.tsx @@ -101,25 +101,24 @@ export const AssetGraphExplorer = (props: Props) => { const {explorerPath, onChangeExplorerPath} = props; - const {button, filterBar, groupsFilter, computeKindTagsFilter, filterFn} = - useAssetGraphExplorerFilters({ - nodes: React.useMemo( - () => (fullAssetGraphData ? Object.values(fullAssetGraphData.nodes) : []), - [fullAssetGraphData], - ), - loading: fetchResult.loading, - isGlobalGraph: !!props.isGlobalGraph, - explorerPath: explorerPath.opsQuery, - clearExplorerPath: React.useCallback(() => { - onChangeExplorerPath( - { - ...explorerPath, - opsQuery: '', - }, - 'push', - ); - }, [explorerPath, onChangeExplorerPath]), - }); + const {button, filterBar, groupsFilter, kindFilter, filterFn} = useAssetGraphExplorerFilters({ + nodes: React.useMemo( + () => (fullAssetGraphData ? Object.values(fullAssetGraphData.nodes) : []), + [fullAssetGraphData], + ), + loading: fetchResult.loading, + isGlobalGraph: !!props.isGlobalGraph, + explorerPath: explorerPath.opsQuery, + clearExplorerPath: React.useCallback(() => { + onChangeExplorerPath( + { + ...explorerPath, + opsQuery: '', + }, + 'push', + ); + }, [explorerPath, onChangeExplorerPath]), + }); useEffect(() => { setHideNodesMatching(() => (node: AssetNodeForGraphQueryFragment) => !filterFn(node)); @@ -152,7 +151,7 @@ export const AssetGraphExplorer = (props: Props) => { graphQueryItems={graphQueryItems} filterBar={filterBar} filterButton={button} - computeKindTagsFilter={computeKindTagsFilter} + kindFilter={kindFilter} groupsFilter={groupsFilter} {...props} /> @@ -172,7 +171,7 @@ type WithDataProps = Props & { filterBar: React.ReactNode; isGlobalGraph?: boolean; - computeKindTagsFilter: StaticSetFilter; + kindFilter: StaticSetFilter; groupsFilter: StaticSetFilter; }; @@ -190,7 +189,7 @@ const AssetGraphExplorerWithData = ({ filterButton, filterBar, isGlobalGraph = false, - computeKindTagsFilter, + kindFilter, groupsFilter, }: WithDataProps) => { const findAssetLocation = useFindAssetLocation(); @@ -626,7 +625,7 @@ const AssetGraphExplorerWithData = ({ )} diff --git a/js_modules/dagster-ui/packages/ui-core/src/asset-graph/AssetNode.tsx b/js_modules/dagster-ui/packages/ui-core/src/asset-graph/AssetNode.tsx index 6be0f94f6440d..4b0f4b03699e7 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/asset-graph/AssetNode.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/asset-graph/AssetNode.tsx @@ -18,17 +18,16 @@ import {ChangedReasonsTag, MinimalNodeChangedDot} from '../assets/ChangedReasons import {MinimalNodeStaleDot, StaleReasonsTag, isAssetStale} from '../assets/Stale'; import {AssetChecksStatusSummary} from '../assets/asset-checks/AssetChecksStatusSummary'; import {assetDetailsPathForKey} from '../assets/assetDetailsPathForKey'; -import {AssetComputeKindTag} from '../graph/KindTags'; +import {AssetKind} from '../graph/KindTags'; import {StaticSetFilter} from '../ui/BaseFilters/useStaticSetFilter'; import {markdownToPlaintext} from '../ui/markdownToPlaintext'; - interface Props { definition: AssetNodeFragment; selected: boolean; - computeKindTagsFilter?: StaticSetFilter; + kindFilter?: StaticSetFilter; } -export const AssetNode = React.memo(({definition, selected, computeKindTagsFilter}: Props) => { +export const AssetNode = React.memo(({definition, selected, kindFilter}: Props) => { const {liveData} = useAssetLiveData(definition.assetKey); return ( @@ -64,11 +63,14 @@ export const AssetNode = React.memo(({definition, selected, computeKindTagsFilte )} - + {definition.kinds.map((kind) => ( + + ))} @@ -260,6 +262,7 @@ export const ASSET_NODE_FRAGMENT = gql` key value } + kinds } fragment AssetNodeKey on AssetKey { diff --git a/js_modules/dagster-ui/packages/ui-core/src/asset-graph/types/AssetNode.types.ts b/js_modules/dagster-ui/packages/ui-core/src/asset-graph/types/AssetNode.types.ts index d068cf77d286d..aab92df914a4a 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/asset-graph/types/AssetNode.types.ts +++ b/js_modules/dagster-ui/packages/ui-core/src/asset-graph/types/AssetNode.types.ts @@ -16,6 +16,7 @@ export type AssetNodeFragment = { isPartitioned: boolean; isObservable: boolean; isMaterializable: boolean; + kinds: Array; assetKey: {__typename: 'AssetKey'; path: Array}; tags: Array<{__typename: 'DefinitionTag'; key: string; value: string}>; }; diff --git a/js_modules/dagster-ui/packages/ui-core/src/asset-graph/types/useAssetGraphData.types.ts b/js_modules/dagster-ui/packages/ui-core/src/asset-graph/types/useAssetGraphData.types.ts index 39ce22fc1d9f7..758ae3ad834df 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/asset-graph/types/useAssetGraphData.types.ts +++ b/js_modules/dagster-ui/packages/ui-core/src/asset-graph/types/useAssetGraphData.types.ts @@ -25,6 +25,7 @@ export type AssetGraphQuery = { isPartitioned: boolean; isObservable: boolean; isMaterializable: boolean; + kinds: Array; tags: Array<{__typename: 'DefinitionTag'; key: string; value: string}>; owners: Array< {__typename: 'TeamAssetOwner'; team: string} | {__typename: 'UserAssetOwner'; email: string} @@ -57,6 +58,7 @@ export type AssetNodeForGraphQueryFragment = { isPartitioned: boolean; isObservable: boolean; isMaterializable: boolean; + kinds: Array; tags: Array<{__typename: 'DefinitionTag'; key: string; value: string}>; owners: Array< {__typename: 'TeamAssetOwner'; team: string} | {__typename: 'UserAssetOwner'; email: string} diff --git a/js_modules/dagster-ui/packages/ui-core/src/asset-graph/useAssetGraphExplorerFilters.oss.tsx b/js_modules/dagster-ui/packages/ui-core/src/asset-graph/useAssetGraphExplorerFilters.oss.tsx index dd138e5e63476..9dd21aa074b28 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/asset-graph/useAssetGraphExplorerFilters.oss.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/asset-graph/useAssetGraphExplorerFilters.oss.tsx @@ -18,7 +18,7 @@ export function useAssetGraphExplorerFilters({ loading, clearExplorerPath, }: Props) { - const {filterButton, computeKindFilter, groupsFilter, activeFiltersJsx, filterFn} = + const {filterButton, groupsFilter, activeFiltersJsx, kindFilter, filterFn} = useAssetCatalogFiltering({ assets: nodes, includeRepos: isGlobalGraph, @@ -26,7 +26,7 @@ export function useAssetGraphExplorerFilters({ }); return { - computeKindTagsFilter: computeKindFilter, + kindFilter, groupsFilter, button: filterButton, filterFn, diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/AssetNodeDefinition.tsx b/js_modules/dagster-ui/packages/ui-core/src/assets/AssetNodeDefinition.tsx index ab03d5e7b49fe..fe709aa4970ef 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/AssetNodeDefinition.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/AssetNodeDefinition.tsx @@ -317,6 +317,7 @@ export const ASSET_NODE_DEFINITION_FRAGMENT = gql` key value } + kinds owners { ... on TeamAssetOwner { team diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/AssetTable.tsx b/js_modules/dagster-ui/packages/ui-core/src/assets/AssetTable.tsx index 2f46f431bc6e6..3b7d0b9c68e4c 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/AssetTable.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/AssetTable.tsx @@ -39,7 +39,7 @@ interface Props { displayPathForAsset: (asset: Asset) => string[]; searchPath: string; isFiltered: boolean; - computeKindFilter?: StaticSetFilter; + kindFilter?: StaticSetFilter; } export const AssetTable = ({ @@ -52,7 +52,7 @@ export const AssetTable = ({ searchPath, isFiltered, view, - computeKindFilter, + kindFilter, }: Props) => { const groupedByDisplayKey = useMemo( () => groupBy(assets, (a) => JSON.stringify(displayPathForAsset(a))), @@ -137,7 +137,7 @@ export const AssetTable = ({ onRefresh={() => refreshState.refetch()} showRepoColumn view={view} - computeKindFilter={computeKindFilter} + kindFilter={kindFilter} /> ); }; diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/AssetTableFragment.tsx b/js_modules/dagster-ui/packages/ui-core/src/assets/AssetTableFragment.tsx index beb7217d26e3b..24fd7e850c5ab 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/AssetTableFragment.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/AssetTableFragment.tsx @@ -31,6 +31,7 @@ export const ASSET_TABLE_DEFINITION_FRAGMENT = gql` key value } + kinds repository { id name diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/AssetsCatalogTable.tsx b/js_modules/dagster-ui/packages/ui-core/src/assets/AssetsCatalogTable.tsx index c3d66e27002d7..74b1a57ace8f5 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/AssetsCatalogTable.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/AssetsCatalogTable.tsx @@ -207,7 +207,7 @@ export const AssetsCatalogTable = ({ isFiltered, filterButton, activeFiltersJsx, - computeKindFilter, + kindFilter, } = useAssetCatalogFiltering({assets}); const {searchPath, filterInput, filtered} = useBasicAssetSearchInput( @@ -284,7 +284,7 @@ export const AssetsCatalogTable = ({ prefixPath={prefixPath || emptyArray} searchPath={searchPath} displayPathForAsset={displayPathForAsset} - computeKindFilter={computeKindFilter} + kindFilter={kindFilter} /> ); }; diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/__tests__/filterAssetDefinition.test.tsx b/js_modules/dagster-ui/packages/ui-core/src/assets/__tests__/filterAssetDefinition.test.tsx index 81e4676f54f09..4c6332bf675e9 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/__tests__/filterAssetDefinition.test.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/__tests__/filterAssetDefinition.test.tsx @@ -58,12 +58,32 @@ describe('filterAssetDefinition', () => { expect(filterAssetDefinition(filters, definition)).toBe(false); }); - it('returns false when computeKindTags filter does not match the definition', () => { + it('returns false when kinds filter does not match the definition', () => { const filters = { - computeKindTags: ['computeKind2'], + kinds: ['computeKind2'], }; const definition = { - computeKind: 'computeKind1', + kinds: ['computeKind1'], + }; + expect(filterAssetDefinition(filters, definition)).toBe(false); + }); + + it('returns true when kinds filter does match the definition', () => { + const filters = { + kinds: ['computeKind1'], + }; + const definition = { + kinds: ['computeKind1', 'computeKind2'], + }; + expect(filterAssetDefinition(filters, definition)).toBe(true); + }); + + it('returns false when kinds filter overspecifies the definition', () => { + const filters = { + kinds: ['computeKind1', 'computeKind3'], + }; + const definition = { + kinds: ['computeKind1'], }; expect(filterAssetDefinition(filters, definition)).toBe(false); }); diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/types/AssetNodeDefinition.types.ts b/js_modules/dagster-ui/packages/ui-core/src/assets/types/AssetNodeDefinition.types.ts index ff88269a3661d..7d0b8c4b309d4 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/types/AssetNodeDefinition.types.ts +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/types/AssetNodeDefinition.types.ts @@ -13,6 +13,7 @@ export type AssetNodeDefinitionFragment = { jobNames: Array; isMaterializable: boolean; isExecutable: boolean; + kinds: Array; hasMaterializePermission: boolean; changedReasons: Array; computeKind: string | null; diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/types/AssetTableFragment.types.ts b/js_modules/dagster-ui/packages/ui-core/src/assets/types/AssetTableFragment.types.ts index 629a6d663e639..f55d9e6f32ddf 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/types/AssetTableFragment.types.ts +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/types/AssetTableFragment.types.ts @@ -14,6 +14,7 @@ export type AssetTableDefinitionFragment = { computeKind: string | null; hasMaterializePermission: boolean; description: string | null; + kinds: Array; partitionDefinition: { __typename: 'PartitionDefinition'; description: string; @@ -51,6 +52,7 @@ export type AssetTableFragment = { computeKind: string | null; hasMaterializePermission: boolean; description: string | null; + kinds: Array; partitionDefinition: { __typename: 'PartitionDefinition'; description: string; diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/types/AssetView.types.ts b/js_modules/dagster-ui/packages/ui-core/src/assets/types/AssetView.types.ts index 8979f4e15fafa..112c18da92433 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/types/AssetView.types.ts +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/types/AssetView.types.ts @@ -29,6 +29,7 @@ export type AssetViewDefinitionQuery = { jobNames: Array; isMaterializable: boolean; isExecutable: boolean; + kinds: Array; hasMaterializePermission: boolean; changedReasons: Array; computeKind: string | null; @@ -16308,6 +16309,7 @@ export type AssetViewDefinitionNodeFragment = { jobNames: Array; isMaterializable: boolean; isExecutable: boolean; + kinds: Array; hasMaterializePermission: boolean; changedReasons: Array; computeKind: string | null; diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/types/AssetsCatalogTable.types.ts b/js_modules/dagster-ui/packages/ui-core/src/assets/types/AssetsCatalogTable.types.ts index 65d02719286ca..4afa6862f898e 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/types/AssetsCatalogTable.types.ts +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/types/AssetsCatalogTable.types.ts @@ -29,6 +29,7 @@ export type AssetCatalogTableQuery = { computeKind: string | null; hasMaterializePermission: boolean; description: string | null; + kinds: Array; partitionDefinition: { __typename: 'PartitionDefinition'; description: string; @@ -82,6 +83,7 @@ export type AssetCatalogGroupTableQuery = { computeKind: string | null; hasMaterializePermission: boolean; description: string | null; + kinds: Array; assetKey: {__typename: 'AssetKey'; path: Array}; partitionDefinition: { __typename: 'PartitionDefinition'; @@ -117,6 +119,7 @@ export type AssetCatalogGroupTableNodeFragment = { computeKind: string | null; hasMaterializePermission: boolean; description: string | null; + kinds: Array; assetKey: {__typename: 'AssetKey'; path: Array}; partitionDefinition: { __typename: 'PartitionDefinition'; diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/useAssetCatalogFiltering.oss.tsx b/js_modules/dagster-ui/packages/ui-core/src/assets/useAssetCatalogFiltering.oss.tsx index ef50a9936a71c..1f51d5bc02327 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/useAssetCatalogFiltering.oss.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/useAssetCatalogFiltering.oss.tsx @@ -12,13 +12,14 @@ import {useFilters} from '../ui/BaseFilters'; import {FilterObject} from '../ui/BaseFilters/useFilter'; import {useAssetGroupFilter} from '../ui/Filters/useAssetGroupFilter'; import {useAssetOwnerFilter, useAssetOwnersForAssets} from '../ui/Filters/useAssetOwnerFilter'; -import {useAssetTagFilter, useAssetTagsForAssets} from '../ui/Filters/useAssetTagFilter'; +import { + useAssetKindsForAssets, + useAssetTagFilter, + useAssetTagsForAssets, +} from '../ui/Filters/useAssetTagFilter'; import {useChangedFilter} from '../ui/Filters/useChangedFilter'; import {useCodeLocationFilter} from '../ui/Filters/useCodeLocationFilter'; -import { - useAssetKindTagsForAssets, - useComputeKindTagFilter, -} from '../ui/Filters/useComputeKindTagFilter'; +import {useKindFilter} from '../ui/Filters/useKindFilter'; import {WorkspaceContext} from '../workspace/WorkspaceContext'; import {buildRepoAddress} from '../workspace/buildRepoAddress'; @@ -47,15 +48,14 @@ export function useAssetCatalogFiltering< filterFn, setAssetTags, setChangedInBranch, - setComputeKindTags, setGroups, setOwners, setCodeLocations, + setKinds, setSelectAllFilters, } = useAssetDefinitionFilterState({isEnabled}); const allAssetGroupOptions = useAssetGroupSelectorsForAssets(assets); - const allComputeKindTags = useAssetKindTagsForAssets(assets); const allAssetOwners = useAssetOwnersForAssets(assets); const groupsFilter = useAssetGroupFilter({ @@ -71,13 +71,7 @@ export function useAssetCatalogFiltering< : filters.changedInBranch, setChangedInBranch, }); - const computeKindFilter = useComputeKindTagFilter({ - allComputeKindTags, - computeKindTags: filters.selectAllFilters.includes('computeKindTags') - ? allComputeKindTags - : filters.computeKindTags, - setComputeKindTags, - }); + const ownersFilter = useAssetOwnerFilter({ allAssetOwners, owners: filters.selectAllFilters.includes('owners') ? allAssetOwners : filters.owners, @@ -92,6 +86,13 @@ export function useAssetCatalogFiltering< setTags: setAssetTags, }); + const allKinds = useAssetKindsForAssets(assets); + const kindFilter = useKindFilter({ + allAssetKinds: allKinds, + kinds: filters.selectAllFilters.includes('kinds') ? [] : filters.kinds, + setKinds, + }); + const {isBranchDeployment} = React.useContext(CloudOSSContext); const {allRepos} = React.useContext(WorkspaceContext); @@ -109,7 +110,7 @@ export function useAssetCatalogFiltering< }); const uiFilters = React.useMemo(() => { - const uiFilters: FilterObject[] = [groupsFilter, computeKindFilter, ownersFilter, tagsFilter]; + const uiFilters: FilterObject[] = [groupsFilter, kindFilter, ownersFilter, tagsFilter]; if (isBranchDeployment) { uiFilters.push(changedInBranchFilter); } @@ -120,11 +121,11 @@ export function useAssetCatalogFiltering< }, [ allRepos.length, changedInBranchFilter, - computeKindFilter, groupsFilter, includeRepos, isBranchDeployment, ownersFilter, + kindFilter, reposFilter, tagsFilter, ]); @@ -155,7 +156,7 @@ export function useAssetCatalogFiltering< [ ['owners', filters.owners, allAssetOwners] as const, ['tags', filters.tags, tags] as const, - ['computeKindTags', filters.computeKindTags, allComputeKindTags] as const, + ['kinds', filters.kinds, allKinds] as const, ['groups', filters.groups, allAssetGroupOptions] as const, ['changedInBranch', filters.changedInBranch, Object.values(ChangeReason)] as const, ['codeLocations', filters.codeLocations, allRepos] as const, @@ -182,11 +183,11 @@ export function useAssetCatalogFiltering< }, [ allAssetGroupOptions, allAssetOwners, - allComputeKindTags, allRepos, didWaitAfterLoading, filters, loading, + allKinds, tags, setSelectAllFilters, isEnabled, @@ -203,7 +204,7 @@ export function useAssetCatalogFiltering< isFiltered, filterFn, filtered, - computeKindFilter, + kindFilter, groupsFilter, renderFilterButton: components.renderButton, }; diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/useAssetDefinitionFilterState.oss.tsx b/js_modules/dagster-ui/packages/ui-core/src/assets/useAssetDefinitionFilterState.oss.tsx index 2e6de5c517064..5620f84df7b68 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/useAssetDefinitionFilterState.oss.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/useAssetDefinitionFilterState.oss.tsx @@ -20,7 +20,10 @@ type Nullable = { export type FilterableAssetDefinition = Nullable< Partial< - Pick & { + Pick< + AssetNode, + 'changedReasons' | 'owners' | 'groupName' | 'tags' | 'computeKind' | 'kinds' + > & { repository: Pick & { location: Pick; }; @@ -30,7 +33,7 @@ export type FilterableAssetDefinition = Nullable< export type AssetFilterBaseType = { groups: AssetGroupSelector[]; - computeKindTags: string[]; + kinds: string[]; changedInBranch: ChangeReason[]; owners: AssetOwner[]; tags: DefinitionTag[]; @@ -44,17 +47,9 @@ export type AssetFilterType = AssetFilterBaseType & { export const useAssetDefinitionFilterState = ({isEnabled = true}: {isEnabled?: boolean}) => { const [filters, setFilters] = useQueryPersistedState({ encode: isEnabled - ? ({ - groups, - computeKindTags, - changedInBranch, - owners, - tags, - codeLocations, - selectAllFilters, - }) => ({ + ? ({groups, kinds, changedInBranch, owners, tags, codeLocations, selectAllFilters}) => ({ groups: groups?.length ? JSON.stringify(groups) : undefined, - computeKindTags: computeKindTags?.length ? JSON.stringify(computeKindTags) : undefined, + kinds: kinds?.length ? JSON.stringify(kinds) : undefined, changedInBranch: changedInBranch?.length ? JSON.stringify(changedInBranch) : undefined, owners: owners?.length ? JSON.stringify(owners) : undefined, tags: tags?.length ? JSON.stringify(tags) : undefined, @@ -64,7 +59,7 @@ export const useAssetDefinitionFilterState = ({isEnabled = true}: {isEnabled?: b : () => ({}), decode: (qs) => ({ groups: qs.groups && isEnabled ? JSON.parse(qs.groups) : [], - computeKindTags: qs.computeKindTags && isEnabled ? JSON.parse(qs.computeKindTags) : [], + kinds: qs.kinds && isEnabled ? JSON.parse(qs.kinds) : [], changedInBranch: qs.changedInBranch && isEnabled ? JSON.parse(qs.changedInBranch) : [], owners: qs.owners && isEnabled ? JSON.parse(qs.owners) : [], tags: qs.tags && isEnabled ? JSON.parse(qs.tags) : [], @@ -84,7 +79,7 @@ export const useAssetDefinitionFilterState = ({isEnabled = true}: {isEnabled?: b ); const { - setComputeKindTags, + setKinds, setGroups, setChangedInBranch, setOwners, @@ -101,7 +96,7 @@ export const useAssetDefinitionFilterState = ({isEnabled = true}: {isEnabled?: b }; } return { - setComputeKindTags: makeSetter('computeKindTags'), + setKinds: makeSetter('kinds'), setGroups: makeSetter('groups'), setChangedInBranch: makeSetter('changedInBranch'), setOwners: makeSetter('owners'), @@ -115,7 +110,7 @@ export const useAssetDefinitionFilterState = ({isEnabled = true}: {isEnabled?: b filters, setFilters, filterFn, - setComputeKindTags, + setKinds, setGroups, setChangedInBranch, setOwners, @@ -176,14 +171,13 @@ export function filterAssetDefinition( } } - const isAllComputeKindTagsSelected = filters.selectAllFilters?.includes('computeKindTags'); - if (isAllComputeKindTagsSelected) { - if (!definition?.computeKind?.length) { + const isAllKindsSelected = filters.selectAllFilters?.includes('kinds'); + if (isAllKindsSelected) { + if (!definition?.kinds?.length) { return false; } - } else if (filters.computeKindTags?.length) { - const lowercased = new Set(filters.computeKindTags.map((c) => c.toLowerCase())); - if (!definition?.computeKind || !lowercased.has(definition.computeKind.toLowerCase())) { + } else if (filters.kinds?.length) { + if (!definition?.kinds || !doesFilterArrayMatchValueArray(filters.kinds, definition.kinds)) { return false; } } diff --git a/js_modules/dagster-ui/packages/ui-core/src/graph/KindTags.tsx b/js_modules/dagster-ui/packages/ui-core/src/graph/KindTags.tsx index bfca16bbd2dbf..4f99c735818db 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/graph/KindTags.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/graph/KindTags.tsx @@ -2,11 +2,8 @@ import {CaptionMono, Tooltip} from '@dagster-io/ui-components'; import * as React from 'react'; import {OpTags} from './OpTags'; -import {DefinitionTag, buildDefinitionTag} from '../graphql/types'; -import { - linkToAssetTableWithComputeKindFilter, - linkToAssetTableWithStorageKindFilter, -} from '../search/useGlobalSearch'; +import {DefinitionTag} from '../graphql/types'; +import {linkToAssetTableWithKindFilter} from '../search/useGlobalSearch'; import {StaticSetFilter} from '../ui/BaseFilters/useStaticSetFilter'; export const LEGACY_COMPUTE_KIND_TAG = 'kind'; @@ -17,8 +14,8 @@ export const STORAGE_KIND_TAG = 'dagster/storage_kind'; export const isCanonicalComputeKindTag = (tag: DefinitionTag) => tag.key === COMPUTE_KIND_TAG || tag.key === LEGACY_COMPUTE_KIND_TAG; export const isCanonicalStorageKindTag = (tag: DefinitionTag) => tag.key === STORAGE_KIND_TAG; -export const buildStorageKindTag = (storageKind: string): DefinitionTag => - buildDefinitionTag({key: 'dagster/storage_kind', value: storageKind}); + +export const isKindTag = (tag: DefinitionTag) => tag.key.startsWith(`${HIDDEN_TAG_PREFIX}kind/`); export const AssetComputeKindTag = ({ definition, @@ -68,7 +65,7 @@ export const AssetComputeKindTag = ({ ? () => currentPageFilter.setState(new Set([definition.computeKind || ''])) : shouldLink ? () => { - window.location.href = linkToAssetTableWithComputeKindFilter( + window.location.href = linkToAssetTableWithKindFilter( definition.computeKind || '', ); } @@ -93,7 +90,7 @@ export const AssetStorageKindTag = ({ reduceText?: boolean; reversed?: boolean; linkToFilteredAssetsTable?: boolean; - currentPageFilter?: StaticSetFilter; + currentPageFilter?: StaticSetFilter; }) => { return ( currentPageFilter.setState(new Set([buildStorageKindTag(storageKind)])) + ? () => currentPageFilter.setState(new Set(storageKind)) + : shouldLink + ? () => { + window.location.href = linkToAssetTableWithKindFilter(storageKind); + } + : () => {}, + }, + ]} + /> + + ); +}; + +export const AssetKind = ({ + kind, + style, + linkToFilteredAssetsTable: shouldLink, + currentPageFilter, + ...rest +}: { + kind: string; + style: React.CSSProperties; + reduceColor?: boolean; + reduceText?: boolean; + reversed?: boolean; + linkToFilteredAssetsTable?: boolean; + currentPageFilter?: StaticSetFilter; +}) => { + return ( + + Filter to {kind} assets + + ) : shouldLink ? ( + <> + View all {kind} assets + + ) : ( + <> + Storage kind {kind} + + ) + } + placement="bottom" + > + currentPageFilter.setState(new Set([kind, ...currentPageFilter.state])) : shouldLink ? () => { - window.location.href = linkToAssetTableWithStorageKindFilter(storageKind); + window.location.href = linkToAssetTableWithKindFilter(kind); } : () => {}, }, diff --git a/js_modules/dagster-ui/packages/ui-core/src/search/useGlobalSearch.tsx b/js_modules/dagster-ui/packages/ui-core/src/search/useGlobalSearch.tsx index 723cd9ec841f4..02db22699a1f4 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/search/useGlobalSearch.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/search/useGlobalSearch.tsx @@ -17,7 +17,7 @@ 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, isCanonicalStorageKindTag} from '../graph/KindTags'; +import {isCanonicalStorageKindTag} from '../graph/KindTags'; import {AssetOwner, DefinitionTag, buildDefinitionTag} from '../graphql/types'; import {buildTagString} from '../ui/tagAsString'; import {buildRepoPathForHuman} from '../workspace/buildRepoAddress'; @@ -29,15 +29,9 @@ export const linkToAssetTableWithGroupFilter = (groupMetadata: GroupMetadata) => return `/assets?${qs.stringify({groups: JSON.stringify([groupMetadata])})}`; }; -export const linkToAssetTableWithComputeKindFilter = (computeKind: string) => { +export const linkToAssetTableWithKindFilter = (kind: string) => { return `/assets?${qs.stringify({ - computeKindTags: JSON.stringify([computeKind]), - })}`; -}; - -export const linkToAssetTableWithStorageKindFilter = (storageKind: string) => { - return `/assets?${qs.stringify({ - storageKindTags: JSON.stringify([buildStorageKindTag(storageKind)]), + kinds: JSON.stringify([kind]), })}`; }; @@ -239,7 +233,7 @@ const secondaryDataToSearchResults = ( label: computeKind, description: '', type: AssetFilterSearchResultType.ComputeKind, - href: linkToAssetTableWithComputeKindFilter(computeKind), + href: linkToAssetTableWithKindFilter(computeKind), numResults: assetCount, }), ); @@ -248,7 +242,7 @@ const secondaryDataToSearchResults = ( label: storageKind, description: '', type: AssetFilterSearchResultType.StorageKind, - href: linkToAssetTableWithStorageKindFilter(storageKind), + href: linkToAssetTableWithKindFilter(storageKind), numResults: assetCount, }), ); diff --git a/js_modules/dagster-ui/packages/ui-core/src/ui/Filters/useAssetTagFilter.tsx b/js_modules/dagster-ui/packages/ui-core/src/ui/Filters/useAssetTagFilter.tsx index 00e3a09dac634..077774a75e73e 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/ui/Filters/useAssetTagFilter.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/ui/Filters/useAssetTagFilter.tsx @@ -68,6 +68,23 @@ export function useAssetTagsForAssets( ); } +export function useAssetKindsForAssets( + assets: {definition?: {kinds?: string[] | null} | null}[], +): string[] { + return useMemo( + () => + Array.from( + new Set( + assets + .map((a) => a?.definition?.kinds) + .filter((o) => o) + .flatMap((a) => a as string[]), + ), + ).sort(), + [assets], + ); +} + export function doesFilterArrayMatchValueArray( filterArray: T[], valueArray: V[], diff --git a/js_modules/dagster-ui/packages/ui-core/src/ui/Filters/useComputeKindTagFilter.tsx b/js_modules/dagster-ui/packages/ui-core/src/ui/Filters/useComputeKindTagFilter.tsx deleted file mode 100644 index bac2073295a3e..0000000000000 --- a/js_modules/dagster-ui/packages/ui-core/src/ui/Filters/useComputeKindTagFilter.tsx +++ /dev/null @@ -1,60 +0,0 @@ -import {Box, Icon} from '@dagster-io/ui-components'; -import uniqBy from 'lodash/uniqBy'; -import {useMemo} from 'react'; - -import {TruncatedTextWithFullTextOnHover} from '../../nav/getLeftNavItemsForOption'; -import {StaticBaseConfig, useStaticSetFilter} from '../BaseFilters/useStaticSetFilter'; - -const emptyArray: any[] = []; - -export const useComputeKindTagFilter = ({ - allComputeKindTags, - computeKindTags, - setComputeKindTags, -}: { - allComputeKindTags: string[]; - computeKindTags?: null | string[]; - setComputeKindTags?: null | ((s: string[]) => void); -}) => { - return useStaticSetFilter({ - ...BaseConfig, - allValues: useMemo( - () => - allComputeKindTags.map((value) => ({ - value, - match: [value], - })), - [allComputeKindTags], - ), - menuWidth: '300px', - state: computeKindTags ?? emptyArray, - onStateChanged: (values) => { - setComputeKindTags?.(Array.from(values)); - }, - }); -}; - -export function useAssetKindTagsForAssets( - assets: {definition?: {computeKind?: string | null} | null}[], -): string[] { - return useMemo( - () => - uniqBy( - assets.map((a) => a.definition?.computeKind).filter((x): x is string => !!x), - (c) => c.toLowerCase(), - ), - [assets], - ); -} - -export const BaseConfig: StaticBaseConfig = { - name: 'Compute kind', - icon: 'compute_kind', - renderLabel: ({value}: {value: string}) => ( - - - - - ), - getStringValue: (value: string) => value, -}; diff --git a/js_modules/dagster-ui/packages/ui-core/src/ui/Filters/useKindFilter.tsx b/js_modules/dagster-ui/packages/ui-core/src/ui/Filters/useKindFilter.tsx new file mode 100644 index 0000000000000..7c9574f226289 --- /dev/null +++ b/js_modules/dagster-ui/packages/ui-core/src/ui/Filters/useKindFilter.tsx @@ -0,0 +1,54 @@ +import {Box, Icon} from '@dagster-io/ui-components'; +import {useMemo} from 'react'; + +import {TruncatedTextWithFullTextOnHover} from '../../nav/getLeftNavItemsForOption'; +import {StaticBaseConfig, useStaticSetFilter} from '../BaseFilters/useStaticSetFilter'; + +const emptyArray: any[] = []; + +export const useKindFilter = ({ + allAssetKinds, + kinds, + setKinds, +}: { + allAssetKinds: string[]; + kinds?: null | string[]; + setKinds?: null | ((s: string[]) => void); +}) => { + const memoizedState = useMemo(() => kinds?.map((kind) => kind), [kinds]); + return useStaticSetFilter({ + allValues: useMemo( + () => + allAssetKinds.map((value) => ({ + value, + match: [value], + })), + [allAssetKinds], + ), + menuWidth: '300px', + state: memoizedState ?? emptyArray, + onStateChanged: (values) => { + setKinds?.(Array.from(values)); + }, + canSelectAll: false, + ...BaseConfig, + }); +}; + +export const getStringValue = (value: string) => value; + +export const BaseConfig: StaticBaseConfig = { + name: 'Kind', + icon: 'compute_kind', + renderLabel: (value) => { + return ( + + + + + ); + }, + getStringValue, + getKey: getStringValue, + matchType: 'all-of', +}; diff --git a/js_modules/dagster-ui/packages/ui-core/src/ui/Filters/util.ts b/js_modules/dagster-ui/packages/ui-core/src/ui/Filters/util.ts index 7d2c7aa711209..76adad19784d3 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/ui/Filters/util.ts +++ b/js_modules/dagster-ui/packages/ui-core/src/ui/Filters/util.ts @@ -3,21 +3,21 @@ import {BaseConfig as AssetOwnerFilterBaseConfig} from './useAssetOwnerFilter'; import {BaseConfig as AssetTagFilterBaseConfig} from './useAssetTagFilter'; import {BaseConfig as ChangedFilterBaseConfig} from './useChangedFilter'; import {BaseConfig as CodeLocationFilterBaseConfig} from './useCodeLocationFilter'; -import {BaseConfig as ComputeKindTagFilterBaseConfig} from './useComputeKindTagFilter'; +import {BaseConfig as KindFilterBaseConfig} from './useKindFilter'; import {AssetGroupSelector, AssetOwner, ChangeReason, DefinitionTag} from '../../graphql/types'; import {RepoAddress} from '../../workspace/types'; import {StaticBaseConfig} from '../BaseFilters/useStaticSetFilter'; export const STATIC_FILTER_CONFIGS: { groups: StaticBaseConfig; - computeKindTags: StaticBaseConfig; + kinds: StaticBaseConfig; changedInBranch: StaticBaseConfig; owners: StaticBaseConfig; tags: StaticBaseConfig; codeLocations: StaticBaseConfig; } = { groups: AssetGroupsFilterBaseConfig, - computeKindTags: ComputeKindTagFilterBaseConfig, + kinds: KindFilterBaseConfig, changedInBranch: ChangedFilterBaseConfig, owners: AssetOwnerFilterBaseConfig, tags: AssetTagFilterBaseConfig, diff --git a/js_modules/dagster-ui/packages/ui-core/src/workspace/VirtualizedAssetRow.tsx b/js_modules/dagster-ui/packages/ui-core/src/workspace/VirtualizedAssetRow.tsx index 735262d0543e2..140f7a23f9d3b 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/workspace/VirtualizedAssetRow.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/workspace/VirtualizedAssetRow.tsx @@ -21,11 +21,7 @@ import {StaleReasonsLabel} from '../assets/Stale'; import {assetDetailsPathForKey} from '../assets/assetDetailsPathForKey'; import {AssetTableDefinitionFragment} from '../assets/types/AssetTableFragment.types'; import {AssetViewType} from '../assets/useAssetView'; -import { - AssetComputeKindTag, - AssetStorageKindTag, - isCanonicalStorageKindTag, -} from '../graph/KindTags'; +import {AssetKind, isCanonicalStorageKindTag} from '../graph/KindTags'; import {AssetKeyInput} from '../graphql/types'; import {RepositoryLink} from '../nav/RepositoryLink'; import {TimestampDisplay} from '../schedules/TimestampDisplay'; @@ -50,7 +46,7 @@ interface AssetRowProps { height: number; start: number; onRefresh: () => void; - computeKindFilter?: StaticSetFilter; + kindFilter?: StaticSetFilter; } export const VirtualizedAssetRow = (props: AssetRowProps) => { @@ -67,7 +63,7 @@ export const VirtualizedAssetRow = (props: AssetRowProps) => { showCheckboxColumn = false, showRepoColumn, view = 'flat', - computeKindFilter, + kindFilter, } = props; const liveData = useLiveDataOrLatestMaterializationDebounced(path, type); @@ -88,6 +84,7 @@ export const VirtualizedAssetRow = (props: AssetRowProps) => { }; const storageKindTag = definition?.tags.find(isCanonicalStorageKindTag); + const kinds = definition?.kinds; return ( @@ -108,22 +105,19 @@ export const VirtualizedAssetRow = (props: AssetRowProps) => { textStyle="middle-truncate" /> - {definition && ( - - )} - {storageKindTag && ( - + {kinds && ( + <> + {kinds?.map((kind) => ( + + ))} + )}
void; showRepoColumn: boolean; view?: AssetViewType; - computeKindFilter?: StaticSetFilter; + kindFilter?: StaticSetFilter; } export const VirtualizedAssetTable = (props: Props) => { @@ -34,7 +34,7 @@ export const VirtualizedAssetTable = (props: Props) => { onRefresh, showRepoColumn, view = 'flat', - computeKindFilter, + kindFilter, } = props; const parentRef = React.useRef(null); const count = Object.keys(groups).length; @@ -96,7 +96,7 @@ export const VirtualizedAssetTable = (props: Props) => { checked={checkedDisplayKeys.has(row.displayKey)} onToggleChecked={onToggleFactory(row.displayKey)} onRefresh={onRefresh} - computeKindFilter={computeKindFilter} + kindFilter={kindFilter} /> ); })} diff --git a/js_modules/dagster-ui/packages/ui-core/src/workspace/types/WorkspaceAssetsQuery.types.ts b/js_modules/dagster-ui/packages/ui-core/src/workspace/types/WorkspaceAssetsQuery.types.ts index a523ac6373615..42150ff5e4e9e 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/workspace/types/WorkspaceAssetsQuery.types.ts +++ b/js_modules/dagster-ui/packages/ui-core/src/workspace/types/WorkspaceAssetsQuery.types.ts @@ -14,6 +14,7 @@ export type RepoAssetTableFragment = { computeKind: string | null; hasMaterializePermission: boolean; description: string | null; + kinds: Array; assetKey: {__typename: 'AssetKey'; path: Array}; partitionDefinition: { __typename: 'PartitionDefinition'; @@ -69,6 +70,7 @@ export type WorkspaceAssetsQuery = { computeKind: string | null; hasMaterializePermission: boolean; description: string | null; + kinds: Array; assetKey: {__typename: 'AssetKey'; path: Array}; partitionDefinition: { __typename: 'PartitionDefinition';