Skip to content

Commit

Permalink
[ui] Ability to report asset materializations from the actions dropdo…
Browse files Browse the repository at this point in the history
…wn (#22691)

Related https://linear.app/dagster-labs/issue/FE-397/asset-health-polish

- Check tag names truncate correctly

- The checks that have failed appear in a popover

- Asset dropdowns now allow for Report Materialization and View Checks.

Co-authored-by: bengotow <[email protected]>
  • Loading branch information
bengotow and bengotow authored Jun 27, 2024
1 parent 354b8b1 commit f7f2272
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ import email from '../icon-svgs/email.svg';
import error from '../icon-svgs/error.svg';
import error_outline from '../icon-svgs/error_outline.svg';
import execute from '../icon-svgs/execute.svg';
import executing from '../icon-svgs/executing.svg';
import expand from '../icon-svgs/expand.svg';
import expand_arrows from '../icon-svgs/expand_arrows.svg';
import expand_less from '../icon-svgs/expand_less.svg';
Expand Down Expand Up @@ -205,6 +206,7 @@ export const Icons = {
datatype_number,
expectation,
execute,
executing,
materialization,
observation,
job,
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
import {Button, Icon, Menu, MenuItem, Popover, Spinner, Tooltip} from '@dagster-io/ui-components';
import {
Button,
Icon,
Menu,
MenuDivider,
MenuItem,
Popover,
Spinner,
Tooltip,
} from '@dagster-io/ui-components';
import {useContext} from 'react';

import {
Expand All @@ -8,6 +17,7 @@ import {
import {useObserveAction} from './LaunchAssetObservationButton';
import {assetDetailsPathForKey} from './assetDetailsPathForKey';
import {AssetTableDefinitionFragment} from './types/AssetTableFragment.types';
import {useReportEventsModal} from './useReportEventsModal';
import {CloudOSSContext} from '../app/CloudOSSContext';
import {showSharedToaster} from '../app/DomUtils';
import {usePermissionsForLocation} from '../app/Permissions';
Expand All @@ -30,14 +40,24 @@ export const AssetActionMenu = (props: Props) => {
} = usePermissionsForLocation(repoAddress?.location);

const {
featureContext: {canSeeWipeMaterializationAction},
featureContext: {canSeeWipeMaterializationAction, canSeeMaterializeAction},
} = useContext(CloudOSSContext);

const {executeItem, launchpadElement} = useExecuteAssetMenuItem(path, definition);

const reportEvents = useReportEventsModal(
repoAddress
? {
assetKey: {path},
isPartitioned: !!definition?.partitionDefinition,
repository: {name: repoAddress.name, location: {name: repoAddress.location}},
}
: null,
);
return (
<>
{launchpadElement}
{reportEvents.element}
<Popover
position="bottom-right"
content={
Expand All @@ -55,7 +75,13 @@ export const AssetActionMenu = (props: Props) => {
icon="asset_group"
/>
<MenuLink
text="View neighbors"
text="View checks"
to={assetDetailsPathForKey({path}, {view: 'checks'})}
disabled={!definition}
icon="asset_check"
/>
<MenuLink
text="View lineage"
to={assetDetailsPathForKey({path}, {view: 'lineage', lineageScope: 'neighbors'})}
disabled={!definition}
icon="graph_neighbors"
Expand All @@ -72,6 +98,17 @@ export const AssetActionMenu = (props: Props) => {
disabled={!definition}
icon="graph_downstream"
/>
{canSeeMaterializeAction && definition?.hasMaterializePermission
? reportEvents.dropdownOptions.map((option) => (
<MenuItem
key={option.label}
text={option.label}
icon={option.icon}
onClick={option.onClick}
/>
))
: undefined}
{canSeeWipeMaterializationAction ? <MenuDivider /> : undefined}
{canSeeWipeMaterializationAction ? (
<MenuItem
text="Wipe materializations"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,23 @@ import {
Box,
Colors,
Icon,
MiddleTruncate,
Popover,
Spinner,
Tag,
intentToFillColor,
} from '@dagster-io/ui-components';
import {Link} from 'react-router-dom';

import {ChecksSummaryPopover} from './AssetChecksStatusSummary';
import {assertUnreachable} from '../../app/Util';
import {AssetCheckLiveFragment} from '../../asset-data/types/AssetBaseDataProvider.types';
import {
AssetCheckEvaluation,
AssetCheckExecution,
AssetCheckExecutionResolvedStatus,
AssetCheckSeverity,
AssetKey,
AssetKeyInput,
} from '../../graphql/types';
import {linkToRunEvent} from '../../runs/RunUtils';
import {TimestampDisplay} from '../../schedules/TimestampDisplay';
Expand All @@ -31,7 +34,7 @@ const CheckRow = ({
}: {
icon: JSX.Element;
checkName: string;
assetKey: AssetKey;
assetKey: AssetKeyInput;
timestamp?: number;
}) => (
<Box
Expand All @@ -56,7 +59,7 @@ export const CheckStatusRow = ({
assetKey,
}: {
assetCheck: AssetCheckLiveFragment;
assetKey: AssetKey;
assetKey: AssetKeyInput;
}) => {
const {executionForLatestMaterialization: execution} = assetCheck;

Expand Down Expand Up @@ -228,29 +231,56 @@ export const AssetCheckStatusTag = ({
export const AssetCheckErrorsTag = ({
checks,
severity,
assetKey,
}: {
checks: AssetCheckLiveFragment[];
severity: AssetCheckSeverity;
assetKey: AssetKeyInput;
}) => {
const actions: TagAction[] = [];
const execution = checks[0]?.executionForLatestMaterialization;
if (execution) {
const tagIcon = severity === AssetCheckSeverity.ERROR ? 'cancel' : 'warning_outline';
const tagIntent = severity === AssetCheckSeverity.ERROR ? 'danger' : 'warning';

if (checks.length === 1) {
const actions: TagAction[] = [];
const execution = checks[0]!.executionForLatestMaterialization;

actions.push({
label: 'View in run logs',
to: linkToRunEvent(
{id: execution.runId},
{stepKey: execution.stepKey, timestamp: execution.timestamp},
),
label: 'View details',
to: assetDetailsPathForAssetCheck({assetKey, name: checks[0]!.name}),
});
if (execution) {
actions.push({
label: 'View in run logs',
to: linkToRunEvent(
{id: execution.runId},
{stepKey: execution.stepKey, timestamp: execution.timestamp},
),
});
}

return (
<TagActionsPopover
data={{key: '', value: ''}}
actions={actions}
childrenMiddleTruncate={checks.length === 1}
>
<Tag icon={tagIcon} intent={tagIntent}>
<MiddleTruncate text={checks[0]!.name} />
</Tag>
</TagActionsPopover>
);
}

return (
<TagActionsPopover data={{key: '', value: ''}} actions={actions}>
<Tag
icon={severity === AssetCheckSeverity.ERROR ? 'cancel' : 'warning_outline'}
intent={severity === AssetCheckSeverity.ERROR ? 'danger' : 'warning'}
>
{checks.length === 1 ? checks[0]!.name : `${checks.length} failed`}
<Popover
content={<ChecksSummaryPopover type={severity} assetKey={assetKey} assetChecks={checks} />}
position="top-left"
interactionKind="hover"
className="chunk-popover-target"
>
<Tag icon={tagIcon} intent={tagIntent}>
{`${checks.length} failed`}
</Tag>
</TagActionsPopover>
</Popover>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@ import {CheckStatusRow} from './AssetCheckStatusTag';
import {assertUnreachable} from '../../app/Util';
import {AssetCheckLiveFragment} from '../../asset-data/types/AssetBaseDataProvider.types';
import {LiveDataForNode} from '../../asset-graph/Utils';
import {AssetCheckExecutionResolvedStatus, AssetCheckSeverity, AssetKey} from '../../graphql/types';
import {
AssetCheckExecutionResolvedStatus,
AssetCheckSeverity,
AssetKeyInput,
} from '../../graphql/types';

type AssetCheckIconType =
| Exclude<
Expand Down Expand Up @@ -82,13 +86,13 @@ const titlePerCheckType = (type: AssetCheckIconType) => {
}
};

const ChecksSummaryPopover = ({
export const ChecksSummaryPopover = ({
type,
assetKey,
assetChecks,
}: {
type: AssetCheckIconType;
assetKey: AssetKey;
assetKey: AssetKeyInput;
assetChecks: AssetCheckLiveFragment[];
}) => {
return (
Expand Down Expand Up @@ -123,7 +127,7 @@ export const AssetChecksStatusSummary = ({
}: {
liveData: LiveDataForNode;
rendering: 'dag' | 'tags';
assetKey: AssetKey;
assetKey: AssetKeyInput;
}) => {
const byIconType = countBy(liveData.assetChecks, iconTypeFromCheck);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ type Asset = {
repository: {name: string; location: {name: string}};
};

export function useReportEventsModal(asset: Asset | null, onEventReported: () => void) {
export function useReportEventsModal(asset: Asset | null, onEventReported?: () => void) {
const [isOpen, setIsOpen] = useState(false);

const dropdownOptions = useMemo(
Expand Down Expand Up @@ -85,7 +85,7 @@ const ReportEventDialogBody = ({
repoAddress: RepoAddress;
isOpen: boolean;
setIsOpen: (open: boolean) => void;
onEventReported: () => void;
onEventReported?: () => void;
}) => {
const [description, setDescription] = useState('');
const {
Expand Down Expand Up @@ -159,7 +159,7 @@ const ReportEventDialogBody = ({
icon: 'materialization',
intent: 'success',
});
onEventReported();
onEventReported?.();
setIsOpen(false);
}
};
Expand Down
3 changes: 3 additions & 0 deletions js_modules/dagster-ui/packages/ui-core/src/ui/TagActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,19 @@ export const TagActionsPopover = ({
data,
actions,
children,
childrenMiddleTruncate,
}: {
data: TagType;
actions: TagAction[];
children: React.ReactNode;
childrenMiddleTruncate?: boolean;
}) => {
return (
<Popover
content={<TagActions actions={actions} data={data} />}
hoverOpenDelay={100}
hoverCloseDelay={100}
targetProps={childrenMiddleTruncate ? {style: {minWidth: 0, maxWidth: '100%'}} : {}}
placement="top"
interactionKind="hover"
>
Expand Down

2 comments on commit f7f2272

@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-ch3mp2j17-elementl.vercel.app

Built with commit f7f2272.
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-n63s92327-elementl.vercel.app

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

Please sign in to comment.