Skip to content

Commit

Permalink
Asset checks UI revamp (#19934)
Browse files Browse the repository at this point in the history
## Summary & Motivation


https://www.figma.com/file/1aaOz2e8PiCOGPGF82vsvw/Asset-Checks?node-id=749%3A1840&mode=dev

Things omitted from the designs: 

- Durations because we don't support that on the backend atm
- Partitions also because we don't support that yet
- Check dependencies, also because we don't support that yet

## How I Tested These Changes

<img width="2560" alt="Screenshot 2024-02-20 at 11 56 50 PM"
src="https://github.com/dagster-io/dagster/assets/2286579/842ef87f-2a4f-4844-a218-d848c0e89e17">
<img width="2558" alt="Screenshot 2024-02-20 at 11 53 26 PM"
src="https://github.com/dagster-io/dagster/assets/2286579/5940dae0-731d-4497-91d4-32b9053a953a">
<img width="2560" alt="Screenshot 2024-02-20 at 11 52 37 PM"
src="https://github.com/dagster-io/dagster/assets/2286579/212f6ca4-43f7-401e-b822-53f804eeab77">
  • Loading branch information
salazarm authored Feb 23, 2024
1 parent f4e9d6f commit ecba104
Show file tree
Hide file tree
Showing 15 changed files with 686 additions and 450 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React from 'react';

import {Box} from './Box';
import {Icon} from './Icon';

export const CollapsibleSection = ({
header,
headerWrapperProps,
children,
isInitiallyCollapsed = false,
}: {
header: React.ReactNode;
headerWrapperProps?: React.ComponentProps<typeof Box>;
children: React.ReactNode;
isInitiallyCollapsed?: boolean;
}) => {
const [isCollapsed, setIsCollapsed] = React.useState(isInitiallyCollapsed);
return (
<Box flex={{direction: 'column'}}>
<Box
{...headerWrapperProps}
flex={{direction: 'row', alignItems: 'center', gap: 6, ...(headerWrapperProps?.flex || {})}}
onClick={() => {
setIsCollapsed(!isCollapsed);
headerWrapperProps?.onClick?.();
}}
>
<Icon
name="arrow_drop_down"
style={{transform: isCollapsed ? 'rotate(-90deg)' : 'rotate(0deg)'}}
/>
<div>{header}</div>
</Box>
{isCollapsed ? null : children}
</Box>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export const Inner = styled.div.attrs<InnerProps>(({$totalHeight}) => ({
width: 100%;
`;

type RowProps = {$height: number; $start: number};
export type RowProps = {$height: number; $start: number};

export const Row = styled.div.attrs<RowProps>(({$height, $start}) => ({
style: {
Expand Down
1 change: 1 addition & 0 deletions js_modules/dagster-ui/packages/ui-components/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export * from './components/Button';
export * from './components/ButtonGroup';
export * from './components/ButtonLink';
export * from './components/Checkbox';
export * from './components/CollapsibleSection';
export * from './components/ConfigEditorDialog';
export * from './components/ConfigEditorWithSchema';
export * from './components/ConfigTypeSchema';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export type AssetViewFeatureInput = {
type AssetFeatureContextType = {
tabBuilder: (input: AssetTabConfigInput) => AssetTabConfig[];
renderFeatureView: (input: AssetViewFeatureInput) => React.ReactNode;
AssetChecksBanner: React.ComponentType<Record<string, never>>;
AssetChecksBanner: React.ComponentType<{onClose: () => void}>;
};

export const AssetFeatureContext = React.createContext<AssetFeatureContextType>({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ export const buildAssetTabMap = (input: AssetTabConfigInput): Record<string, Ass
id: 'checks',
title: 'Checks',
to: buildAssetViewParams({...params, view: 'checks'}),
hidden: !definition?.hasAssetChecks,
},
events: {
id: 'events',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,6 @@ export const ASSET_VIEW_DEFINITION_QUERY = gql`
name
}
}
hasAssetChecks
...AssetNodeInstigatorsFragment
...AssetNodeDefinitionFragment
Expand Down
Original file line number Diff line number Diff line change
@@ -1,184 +1,145 @@
import {MockedResponse} from '@apollo/client/testing';

import {AssetGraphQuery} from '../../asset-graph/types/useAssetGraphData.types';
import {ASSET_GRAPH_QUERY} from '../../asset-graph/useAssetGraphData';
import {buildMaterializationEvent} from '../../graphql/types';
import {
buildAsset,
buildAssetKey,
buildAssetNode,
buildMaterializationEvent,
buildRepository,
buildRepositoryLocation,
buildResourceRequirement,
} from '../../graphql/types';
import {ASSET_VIEW_DEFINITION_QUERY} from '../AssetView';
import {buildQueryMock} from '../AutoMaterializePolicyPage/__fixtures__/AutoMaterializePolicyPage.fixtures';
import {AssetViewDefinitionQuery} from '../types/AssetView.types';
import {
AssetViewDefinitionQuery,
AssetViewDefinitionQueryVariables,
} from '../types/AssetView.types';

export const LatestMaterializationTimestamp = '1671568270073';

export const AssetGraphEmpty: MockedResponse<AssetGraphQuery> = {
request: {
query: ASSET_GRAPH_QUERY,
variables: {},
},
result: {
data: {
__typename: 'Query',
assetNodes: [],
},
},
};

export const AssetViewDefinitionNonSDA: MockedResponse<AssetViewDefinitionQuery> = buildQueryMock({
export const AssetViewDefinitionNonSDA = buildQueryMock<
AssetViewDefinitionQuery,
AssetViewDefinitionQueryVariables
>({
query: ASSET_VIEW_DEFINITION_QUERY,
variables: {
assetKey: {path: ['non_sda_asset']},
},
data: {
assetOrError: {
assetOrError: buildAsset({
id: '["non_sda_asset"]',
key: {
key: buildAssetKey({
path: ['non_sda_asset'],
__typename: 'AssetKey',
},
}),
assetMaterializations: [
buildMaterializationEvent({
timestamp: LatestMaterializationTimestamp,
}),
],
definition: null,
__typename: 'Asset',
},
}),
},
});

export const AssetViewDefinitionSourceAsset: MockedResponse<AssetViewDefinitionQuery> = {
request: {
query: ASSET_VIEW_DEFINITION_QUERY,
variables: {
assetKey: {path: ['observable_source_asset']},
},
export const AssetViewDefinitionSourceAsset = buildQueryMock<
AssetViewDefinitionQuery,
AssetViewDefinitionQueryVariables
>({
query: ASSET_VIEW_DEFINITION_QUERY,
variables: {
assetKey: {path: ['observable_source_asset']},
},
result: {
data: {
__typename: 'Query',
assetOrError: {
data: {
assetOrError: buildAsset({
id: 'test.py.repo.["observable_source_asset"]',
key: buildAssetKey({
path: ['observable_source_asset'],
}),
assetMaterializations: [],
definition: buildAssetNode({
id: 'test.py.repo.["observable_source_asset"]',
key: {
path: ['observable_source_asset'],
__typename: 'AssetKey',
},
assetMaterializations: [],
definition: {
hasAssetChecks: false,
id: 'test.py.repo.["observable_source_asset"]',
groupName: 'GROUP3',
backfillPolicy: null,
partitionDefinition: null,
partitionKeysByDimension: [],
repository: {
id: '4d0b1967471d9a4682ccc97d12c1c508d0d9c2e1',
name: 'repo',
location: {
id: 'test.py',
name: 'test.py',
__typename: 'RepositoryLocation',
},
__typename: 'Repository',
},
__typename: 'AssetNode',
description: null,
graphName: null,
opNames: [],
opVersion: null,
jobNames: ['__ASSET_JOB'],
configField: null,
autoMaterializePolicy: null,
freshnessPolicy: null,
hasMaterializePermission: true,
computeKind: null,
isPartitioned: false,
isObservable: true,
isExecutable: true,
isSource: true,
assetKey: {
path: ['observable_source_asset'],
__typename: 'AssetKey',
},
metadataEntries: [],
type: null,
requiredResources: [
{
__typename: 'ResourceRequirement',
resourceKey: 'foo',
},
],
targetingInstigators: [],
},
__typename: 'Asset',
},
},
groupName: 'GROUP3',
backfillPolicy: null,
partitionDefinition: null,

partitionKeysByDimension: [],
repository: buildRepository({
id: '4d0b1967471d9a4682ccc97d12c1c508d0d9c2e1',
name: 'repo',
location: buildRepositoryLocation({
id: 'test.py',
name: 'test.py',
}),
}),
description: null,
graphName: null,
opNames: [],
opVersion: null,
jobNames: ['__ASSET_JOB'],
configField: null,
autoMaterializePolicy: null,
freshnessPolicy: null,
hasMaterializePermission: true,
computeKind: null,
isPartitioned: false,
isObservable: true,
isExecutable: true,
isSource: true,
metadataEntries: [],
type: null,
requiredResources: [buildResourceRequirement({resourceKey: 'foo'})],
targetingInstigators: [],
}),
}),
},
};
});

export const AssetViewDefinitionSDA: MockedResponse<AssetViewDefinitionQuery> = {
request: {
query: ASSET_VIEW_DEFINITION_QUERY,
variables: {
assetKey: {path: ['sda_asset']},
},
export const AssetViewDefinitionSDA = buildQueryMock<
AssetViewDefinitionQuery,
AssetViewDefinitionQueryVariables
>({
query: ASSET_VIEW_DEFINITION_QUERY,
variables: {
assetKey: {path: ['sda_asset']},
},
result: {
data: {
__typename: 'Query',
assetOrError: {
data: {
assetOrError: buildAsset({
id: 'test.py.repo.["sda_asset"]',
key: buildAssetKey({
path: ['sda_asset'],
}),
assetMaterializations: [],
definition: buildAssetNode({
id: 'test.py.repo.["sda_asset"]',
key: {
path: ['sda_asset'],
__typename: 'AssetKey',
},
assetMaterializations: [],
definition: {
hasAssetChecks: false,
id: 'test.py.repo.["sda_asset"]',
groupName: 'GROUP3',
backfillPolicy: null,
partitionDefinition: null,
partitionKeysByDimension: [],
repository: {
id: '4d0b1967471d9a4682ccc97d12c1c508d0d9c2e1',
name: 'repo',
location: {
id: 'test.py',
name: 'test.py',
__typename: 'RepositoryLocation',
},
__typename: 'Repository',
},
__typename: 'AssetNode',
description: null,
graphName: null,
opNames: [],
opVersion: null,
jobNames: ['__ASSET_JOB'],
configField: null,
autoMaterializePolicy: null,
freshnessPolicy: null,
hasMaterializePermission: true,
computeKind: null,
isPartitioned: false,
isObservable: false,
isExecutable: true,
isSource: false,
assetKey: {
path: ['sda_asset'],
__typename: 'AssetKey',
},
metadataEntries: [],
type: null,
requiredResources: [
{
__typename: 'ResourceRequirement',
resourceKey: 'foo',
},
],
targetingInstigators: [],
},
__typename: 'Asset',
},
},
groupName: 'GROUP3',
backfillPolicy: null,
partitionDefinition: null,
partitionKeysByDimension: [],
repository: buildRepository({
id: '4d0b1967471d9a4682ccc97d12c1c508d0d9c2e1',
name: 'repo',
location: buildRepositoryLocation({
id: 'test.py',
name: 'test.py',
}),
}),
description: null,
graphName: null,
opNames: [],
opVersion: null,
jobNames: ['__ASSET_JOB'],
configField: null,
autoMaterializePolicy: null,
freshnessPolicy: null,
hasMaterializePermission: true,
computeKind: null,
isPartitioned: false,
isObservable: false,
isExecutable: true,
isSource: false,
metadataEntries: [],
type: null,
requiredResources: [buildResourceRequirement({resourceKey: 'foo'})],
targetingInstigators: [],
}),
}),
},
};
});
Loading

2 comments on commit ecba104

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deploy preview for dagit-storybook ready!

✅ Preview
https://dagit-storybook-m5qvwsi6l-elementl.vercel.app

Built with commit ecba104.
This pull request is being automatically deployed with vercel-action

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deploy preview for dagit-core-storybook ready!

✅ Preview
https://dagit-core-storybook-1grqxtwl5-elementl.vercel.app

Built with commit ecba104.
This pull request is being automatically deployed with vercel-action

Please sign in to comment.