Skip to content

Commit

Permalink
[ui] Refactoring to support asset health overview
Browse files Browse the repository at this point in the history
  • Loading branch information
bengotow committed Apr 8, 2024
1 parent 87aaa27 commit e8ac396
Show file tree
Hide file tree
Showing 18 changed files with 323 additions and 235 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@ export const CollapsibleSection = ({
name="arrow_drop_down"
style={{transform: isCollapsed ? 'rotate(-90deg)' : 'rotate(0deg)'}}
/>
<div>{header}</div>
<div style={{userSelect: 'none'}}>{header}</div>
</>
) : (
<Box flex={{justifyContent: 'space-between', alignItems: 'center'}}>
<div>{header}</div>
<Box style={{flex: 1}} flex={{justifyContent: 'space-between', alignItems: 'center'}}>
<div style={{userSelect: 'none'}}>{header}</div>
<Icon
name="arrow_drop_down"
style={{transform: isCollapsed ? 'rotate(-90deg)' : 'rotate(0deg)'}}
Expand Down
1 change: 1 addition & 0 deletions js_modules/dagster-ui/packages/ui-core/src/app/Flags.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export const FeatureFlag = {
flagUseNewAutomationPage: 'flagUseNewAutomationPage' as const,
flagUseNewOverviewPage: 'flagUseNewOverviewPage' as const,
flagExperimentalBranchDiff: 'flagExperimentalBranchDiff' as const,
flagUseNewAssetHealthOverviewPage: 'flagUseNewAssetHealthOverviewPage' as const,
flagSettingsPage: 'flagSettingsPage' as const,
};
export type FeatureFlagType = keyof typeof FeatureFlag;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {Box, Menu, MenuDivider, MenuItem, Spinner} from '@dagster-io/ui-components';
import * as React from 'react';

import {GraphData, GraphNode, tokenForAssetKey} from './Utils';
import {GraphData, tokenForAssetKey} from './Utils';
import {StatusDot} from './sidebar/StatusDot';
import {useAssetLiveData} from '../asset-data/AssetLiveDataProvider';
import {useExecuteAssetMenuItem} from '../assets/AssetActionMenu';
Expand All @@ -11,13 +11,24 @@ import {
AssetKeysDialogHeader,
} from '../assets/AutoMaterializePolicyPage/AssetKeysDialog';
import {assetDetailsPathForKey} from '../assets/assetDetailsPathForKey';
import {AssetKeyInput} from '../graphql/types';
import {ExplorerPath} from '../pipelines/PipelinePathUtils';
import {MenuLink} from '../ui/MenuLink';
import {VirtualizedItemListForDialog} from '../ui/VirtualizedItemListForDialog';

export type AssetNodeMenuNode = {
id: string;
assetKey: AssetKeyInput;
definition: {
isSource: boolean;
isExecutable: boolean;
hasMaterializePermission: boolean;
};
};

export type AssetNodeMenuProps = {
graphData: GraphData;
node: GraphNode;
node: AssetNodeMenuNode;
graphData?: GraphData;
explorerPath?: ExplorerPath;
onChangeExplorerPath?: (path: ExplorerPath, mode: 'replace' | 'push') => void;
selectNode?: (e: React.MouseEvent<any> | React.KeyboardEvent<any>, nodeId: string) => void;
Expand All @@ -30,8 +41,8 @@ export const useAssetNodeMenu = ({
explorerPath,
onChangeExplorerPath,
}: AssetNodeMenuProps) => {
const upstream = Object.keys(graphData.upstream[node.id] ?? {});
const downstream = Object.keys(graphData.downstream[node.id] ?? {});
const upstream = graphData ? Object.keys(graphData.upstream[node.id] ?? {}) : [];
const downstream = graphData ? Object.keys(graphData.downstream[node.id] ?? {}) : [];

const {executeItem, launchpadElement} = useExecuteAssetMenuItem(
node.assetKey.path,
Expand Down Expand Up @@ -80,7 +91,7 @@ export const useAssetNodeMenu = ({
<MenuDivider />
{executeItem}
{executeItem && (upstream.length || downstream.length) ? <MenuDivider /> : null}
{upstream.length ? (
{upstream.length && graphData ? (
<MenuItem
text={`View parents (${upstream.length})`}
icon="list"
Expand All @@ -89,14 +100,14 @@ export const useAssetNodeMenu = ({
}}
/>
) : null}
{upstream.length ? (
{upstream.length || !graphData ? (
<MenuItem
text="Show upstream graph"
icon="arrow_back"
onClick={() => showGraph(`*\"${tokenForAssetKey(node.assetKey)}\"`)}
/>
) : null}
{downstream.length ? (
{downstream.length || !graphData ? (
<MenuItem
text="Show downstream graph"
icon="arrow_forward"
Expand All @@ -107,14 +118,16 @@ export const useAssetNodeMenu = ({
),
dialog: (
<>
<UpstreamDownstreamDialog
title="Parent assets"
graphData={graphData}
assetKeys={upstream}
isOpen={showParents}
setIsOpen={setShowParents}
selectNode={selectNode}
/>
{graphData && (
<UpstreamDownstreamDialog
title="Parent assets"
graphData={graphData}
assetKeys={upstream}
isOpen={showParents}
setIsOpen={setShowParents}
selectNode={selectNode}
/>
)}
{launchpadElement}
</>
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ const LOADING_STATUS_CONTENT = {
),
};

type StatusContentArgs = {
export type StatusContentArgs = {
assetKey: AssetKeyInput;
definition: {opNames: string[]; isSource: boolean; isObservable: boolean};
liveData: LiveDataForNode | null | undefined;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,24 @@ export const ContextMenuWrapper = ({
wrapperInnerStyles?: React.CSSProperties;
}) => {
const [menuVisible, setMenuVisible] = React.useState(false);
const [menuPosition, setMenuPosition] = React.useState<{top: number; left: number}>({
top: 0,
left: 0,
const [menuPosition, setMenuPosition] = React.useState<{
x: number;
y: number;
anchor: 'left' | 'right';
}>({
anchor: 'left',
x: 0,
y: 0,
});

const showMenu = (e: React.MouseEvent) => {
const anchor = window.innerWidth - e.pageX < 240 ? 'right' : 'left';
e.preventDefault();
setMenuPosition({top: e.pageY, left: e.pageX});
setMenuPosition({
x: anchor === 'left' ? e.pageX : window.innerWidth - e.pageX,
y: e.pageY,
anchor,
});

if (!menuVisible) {
setMenuVisible(true);
Expand Down Expand Up @@ -78,8 +88,9 @@ export const ContextMenuWrapper = ({
<div
style={{
position: 'absolute',
top: menuPosition.top,
left: menuPosition.left,
top: menuPosition.y,
left: menuPosition.anchor === 'left' ? menuPosition.x : 'unset',
right: menuPosition.anchor === 'right' ? menuPosition.x : 'unset',
backgroundColor: Colors.popoverBackground(),
boxShadow: '0 2px 4px rgba(0, 0, 0, 0.1)',
zIndex: 10,
Expand All @@ -102,4 +113,5 @@ export const triggerContextMenu = (e: React.MouseEvent) => {
const evt = new MouseEvent('contextmenu', e.nativeEvent);
e.target.dispatchEvent(evt);
e.stopPropagation();
e.preventDefault();
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {Box, Colors, Icon, MiddleTruncate, UnstyledButton} from '@dagster-io/ui-
import * as React from 'react';
import styled from 'styled-components';

import {StatusDot} from './StatusDot';
import {StatusDot, StatusDotNode} from './StatusDot';
import {
FolderNodeCodeLocationType,
FolderNodeGroupType,
Expand All @@ -11,13 +11,13 @@ import {
} from './util';
import {ExplorerPath} from '../../pipelines/PipelinePathUtils';
import {AssetGroup} from '../AssetGraphExplorer';
import {useAssetNodeMenu} from '../AssetNodeMenu';
import {AssetNodeMenuProps, useAssetNodeMenu} from '../AssetNodeMenu';
import {useGroupNodeContextMenu} from '../CollapsedGroupNode';
import {ContextMenuWrapper, triggerContextMenu} from '../ContextMenuWrapper';
import {GraphData, GraphNode} from '../Utils';

type AssetSidebarNodeProps = {
fullAssetGraphData: GraphData;
fullAssetGraphData?: GraphData;
node: GraphNode | FolderNodeNonAssetType;
level: number;
toggleOpen: () => void;
Expand All @@ -42,10 +42,9 @@ export const AssetSidebarNode = (props: AssetSidebarNodeProps) => {
const showArrow = !isAssetNode;

return (
<Box ref={elementRef} padding={{left: 8}}>
<Box ref={elementRef} padding={{left: 8, right: 12}}>
<BoxWrapper level={level}>
<ItemContainer
padding={{right: 12}}
flex={{direction: 'row', alignItems: 'center'}}
onClick={selectThisNode}
onDoubleClick={(e) => !e.metaKey && toggleOpen()}
Expand Down Expand Up @@ -93,15 +92,27 @@ export const AssetSidebarNode = (props: AssetSidebarNodeProps) => {
);
};

const AssetSidebarAssetLabel = ({
type AssetSidebarAssetLabelProps = {
fullAssetGraphData?: GraphData;
showStatus?: boolean;
node: AssetNodeMenuProps['node'] & StatusDotNode;
selectNode: (e: React.MouseEvent<any> | React.KeyboardEvent<any>, nodeId: string) => void;
isLastSelected: boolean;
isSelected: boolean;
explorerPath: ExplorerPath;
onChangeExplorerPath: (path: ExplorerPath, mode: 'replace' | 'push') => void;
};

export const AssetSidebarAssetLabel = ({
node,
isSelected,
isLastSelected,
fullAssetGraphData,
selectNode,
explorerPath,
onChangeExplorerPath,
}: Omit<AssetSidebarNodeProps, 'node'> & {node: GraphNode}) => {
showStatus = true,
}: AssetSidebarAssetLabelProps) => {
const {menu, dialog} = useAssetNodeMenu({
graphData: fullAssetGraphData,
node,
Expand All @@ -115,7 +126,7 @@ const AssetSidebarAssetLabel = ({
<FocusableLabelContainer
isSelected={isSelected}
isLastSelected={isLastSelected}
icon={<StatusDot node={node} />}
icon={showStatus ? <StatusDot node={node} /> : null}
text={getDisplayName(node)}
/>
<ExpandMore onClick={triggerContextMenu}>
Expand Down Expand Up @@ -196,6 +207,7 @@ const FocusableLabelContainer = ({
<GrayOnHoverBox
ref={ref}
style={{
gridTemplateColumns: icon ? 'auto minmax(0, 1fr)' : 'minmax(0, 1fr)',
...(isSelected ? {background: Colors.backgroundBlue()} : {}),
}}
>
Expand Down Expand Up @@ -231,7 +243,7 @@ const BoxWrapper = ({level, children}: {level: number; children: React.ReactNode
const ExpandMore = styled(UnstyledButton)`
position: absolute;
top: 8px;
right: 20px;
right: 8px;
visibility: hidden;
`;

Expand All @@ -240,8 +252,8 @@ const GrayOnHoverBox = styled(UnstyledButton)`
user-select: none;
width: 100%;
display: grid;
grid-template-columns: auto minmax(0, 1fr);
flex-direction: row;
height: 32px;
align-items: center;
padding: 5px 8px;
justify-content: space-between;
Expand All @@ -251,7 +263,7 @@ const GrayOnHoverBox = styled(UnstyledButton)`
transition: background 100ms linear;
`;

const ItemContainer = styled(Box)`
export const ItemContainer = styled(Box)`
height: 32px;
position: relative;
cursor: pointer;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
import {StatusCaseDot} from './util';
import {useAssetLiveData} from '../../asset-data/AssetLiveDataProvider';
import {StatusCase, buildAssetNodeStatusContent} from '../AssetNodeStatusContent';
import {GraphNode} from '../Utils';
import {
StatusCase,
StatusContentArgs,
buildAssetNodeStatusContent,
} from '../AssetNodeStatusContent';
import {AssetKeyInput} from '../../graphql/types';

export function StatusDot({node}: {node: Pick<GraphNode, 'assetKey' | 'definition'>}) {
export type StatusDotNode = {assetKey: AssetKeyInput; definition: StatusContentArgs['definition']};

export function StatusDot({node}: {node: StatusDotNode}) {
const {liveData} = useAssetLiveData(node.assetKey);

if (!liveData) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import styled, {keyframes} from 'styled-components';

import {StatusCase} from '../AssetNodeStatusContent';
import {GraphNode} from '../Utils';
import {AssetKeyInput} from '../../graphql/types';

export type FolderNodeGroupType = {
id: string;
Expand All @@ -28,7 +29,7 @@ export function nodePathKey(node: {path: string; id: string} | {id: string}) {
return 'path' in node ? node.path : node.id;
}

export function getDisplayName(node: GraphNode) {
export function getDisplayName(node: {assetKey: AssetKeyInput}) {
return node.assetKey.path[node.assetKey.path.length - 1]!;
}

Expand Down
Loading

0 comments on commit e8ac396

Please sign in to comment.