From fc6a86e3d50aefe9b8c490dde6692f9614f7396e Mon Sep 17 00:00:00 2001 From: bengotow Date: Mon, 18 Mar 2024 16:12:26 -0500 Subject: [PATCH] Visual polish --- .../src/asset-graph/AssetColumnsNode.tsx | 27 ++++++++++++++----- .../src/asset-graph/SidebarAssetInfo.tsx | 8 +++++- .../ui-core/src/asset-graph/layout.ts | 4 +++ .../src/assets/AssetColumnLineageGraph.tsx | 5 ++++ .../ui-core/src/assets/AssetNodeOverview.tsx | 14 ++++++---- .../packages/ui-core/src/assets/AssetView.tsx | 2 +- .../lineage/useColumnLineageDataForAssets.tsx | 22 ++++++++------- .../src/assets/useColumnLineageLayout.tsx | 3 ++- .../ui-core/src/metadata/MetadataEntry.tsx | 4 ++- .../ui-core/src/metadata/TableSchema.tsx | 25 ++++++++++------- 10 files changed, 80 insertions(+), 34 deletions(-) diff --git a/js_modules/dagster-ui/packages/ui-core/src/asset-graph/AssetColumnsNode.tsx b/js_modules/dagster-ui/packages/ui-core/src/asset-graph/AssetColumnsNode.tsx index 8e748fcc6ae2f..96db8139d59c9 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/asset-graph/AssetColumnsNode.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/asset-graph/AssetColumnsNode.tsx @@ -1,4 +1,4 @@ -import {Box, Caption, Colors, StyledTag, Tooltip} from '@dagster-io/ui-components'; +import {Box, Caption, Colors, Icon, StyledTag, Tooltip} from '@dagster-io/ui-components'; import {Link} from 'react-router-dom'; import styled from 'styled-components'; @@ -9,18 +9,22 @@ import { AssetNodeContainer, } from './AssetNode'; import {AssetNodeFragment} from './types/AssetNode.types'; +import {Timestamp} from '../app/time/Timestamp'; import {assetDetailsPathForKey} from '../assets/assetDetailsPathForKey'; -import {AssetColumnLineageLocal} from '../assets/lineage/useColumnLineageDataForAssets'; +import {AssetColumnLineageLocalColumn} from '../assets/lineage/useColumnLineageDataForAssets'; +import {AssetComputeKindTag} from '../graph/OpTags'; import {AssetKeyInput} from '../graphql/types'; -import {TypeTag} from '../metadata/TableSchema'; +import {iconForColumnType} from '../metadata/TableSchema'; export const AssetColumnsGroupNode = ({ selected, definition, height, + asOf, }: { selected: boolean; definition: AssetNodeFragment; + asOf: string | undefined; height: number; }) => { return ( @@ -30,7 +34,15 @@ export const AssetColumnsGroupNode = ({ + + {asOf ? ( + + + + ) : undefined} + + ); @@ -42,9 +54,11 @@ export const AssetColumnNode = ({ selected, }: { assetKey: AssetKeyInput; - column: AssetColumnLineageLocal['']; + column: AssetColumnLineageLocalColumn; selected: boolean; }) => { + const icon = iconForColumnType(column.type ?? ''); + return ( @@ -52,10 +66,10 @@ export const AssetColumnNode = ({ to={assetDetailsPathForKey(assetKey, {view: 'lineage', column: column.name})} $selected={selected} > + {icon ? : } {column.name} - @@ -65,11 +79,10 @@ export const AssetColumnNode = ({ const ColumnLink = styled(Link)<{$selected: boolean}>` height: 28px; margin: 2px 0; - padding-left: 8px; + padding-left: 2px; padding-right: 4px; display: flex; gap: 4px; - justify-content: space-between; align-items: center; transition: background 100ms linear; border-radius: 8px; diff --git a/js_modules/dagster-ui/packages/ui-core/src/asset-graph/SidebarAssetInfo.tsx b/js_modules/dagster-ui/packages/ui-core/src/asset-graph/SidebarAssetInfo.tsx index ad59c99f3ef33..5bb53749f3079 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/asset-graph/SidebarAssetInfo.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/asset-graph/SidebarAssetInfo.tsx @@ -32,6 +32,7 @@ import { import {DagsterTypeSummary} from '../dagstertype/DagsterType'; import {DagsterTypeFragment} from '../dagstertype/types/DagsterType.types'; import {METADATA_ENTRY_FRAGMENT} from '../metadata/MetadataEntry'; +import {TableSchemaLineageContext} from '../metadata/TableSchema'; import {Description} from '../pipelines/Description'; import {SidebarSection, SidebarTitle} from '../pipelines/SidebarComponents'; import {ResourceContainer, ResourceHeader} from '../pipelines/SidebarOpHelpers'; @@ -159,7 +160,12 @@ export const SidebarAssetInfo = ({graphNode}: {graphNode: GraphNode}) => { {assetMetadata.length > 0 && ( - + + + )} diff --git a/js_modules/dagster-ui/packages/ui-core/src/asset-graph/layout.ts b/js_modules/dagster-ui/packages/ui-core/src/asset-graph/layout.ts index 10c1ae050636a..30500c555a6a2 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/asset-graph/layout.ts +++ b/js_modules/dagster-ui/packages/ui-core/src/asset-graph/layout.ts @@ -46,6 +46,10 @@ export type LayoutAssetGraphConfig = dagre.GraphLabel & { groupPaddingTop: number; groupPaddingBottom: number; groupRendering: 'if-varied' | 'always'; + + /** Supported in Dagre, just not documented. Additional spacing between group nodes */ + clusterpaddingtop?: number; + clusterpaddingbottom?: number; }; export type LayoutAssetGraphOptions = { diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/AssetColumnLineageGraph.tsx b/js_modules/dagster-ui/packages/ui-core/src/assets/AssetColumnLineageGraph.tsx index 29408889fc719..613356af3971f 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/AssetColumnLineageGraph.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/AssetColumnLineageGraph.tsx @@ -75,6 +75,9 @@ export const AssetColumnLineageGraph = ({ node: graphNode!, }; + const cols = columnLineageData[groupAssetGraphId] || {}; + const colsAsOf = Object.values(cols)[0]?.asOf; + return ( @@ -117,6 +121,7 @@ export const AssetColumnLineageGraph = ({ description: 'Not found in column metadata', type: null, upstream: [], + asOf: undefined, }; return ( diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/AssetNodeOverview.tsx b/js_modules/dagster-ui/packages/ui-core/src/assets/AssetNodeOverview.tsx index 59ef786b68fe8..7f0e6d299b501 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/AssetNodeOverview.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/AssetNodeOverview.tsx @@ -57,6 +57,7 @@ import {useStateWithStorage} from '../hooks/useStateWithStorage'; import {useLaunchPadHooks} from '../launchpad/LaunchpadHooksContext'; import { TableSchema, + TableSchemaLineageContext, isCanonicalColumnLineageEntry, isCanonicalColumnSchemaEntry, } from '../metadata/TableSchema'; @@ -363,11 +364,14 @@ export const AssetNodeOverview = ({ {tableSchema && ( - + + + )} diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/AssetView.tsx b/js_modules/dagster-ui/packages/ui-core/src/assets/AssetView.tsx index 7cab1ca1627da..653e9efb2c3ea 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/AssetView.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/AssetView.tsx @@ -366,7 +366,7 @@ function getQueryForVisibleAssets( return {query: `+"${token}"+`, requestedDepth: 1}; } if (view === 'lineage') { - const defaultDepth = lineageScope === 'neighbors' ? 2 : 5; + const defaultDepth = 1; const requestedDepth = Number(lineageDepth) || defaultDepth; const depthStr = '+'.repeat(requestedDepth); diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/lineage/useColumnLineageDataForAssets.tsx b/js_modules/dagster-ui/packages/ui-core/src/assets/lineage/useColumnLineageDataForAssets.tsx index 53c0afecfebe2..663731a6c53ac 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/lineage/useColumnLineageDataForAssets.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/lineage/useColumnLineageDataForAssets.tsx @@ -21,16 +21,19 @@ export type AssetColumnLineageServer = { }[]; }; +export type AssetColumnLineageLocalColumn = { + name: string; + type: string | null; + description: string | null; + asOf: string | undefined; // materialization timestamp + upstream: { + assetKey: AssetKeyInput; + columnName: string; + }[]; +}; + export type AssetColumnLineageLocal = { - [column: string]: { - name: string; - type: string | null; - description: string | null; - upstream: { - assetKey: AssetKeyInput; - columnName: string; - }[]; - }; + [column: string]: AssetColumnLineageLocalColumn; }; export type AssetColumnLineages = {[graphId: string]: AssetColumnLineageLocal | undefined}; @@ -64,6 +67,7 @@ const getColumnLineage = ( column, { name: column, + asOf: materialization?.timestamp, type: schemaParsed[column]?.type || null, description: schemaParsed[column]?.description || null, upstream: m.map((u) => ({ diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/useColumnLineageLayout.tsx b/js_modules/dagster-ui/packages/ui-core/src/assets/useColumnLineageLayout.tsx index 084cb9267abe0..376b60e6a069a 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/useColumnLineageLayout.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/useColumnLineageLayout.tsx @@ -11,7 +11,8 @@ const LINEAGE_GRAPH_COLUMN_LAYOUT_OPTIONS: LayoutAssetGraphOptions = { nodeHeight: 32, nodesep: 0, edgesep: 0, - groupPaddingBottom: -5, + clusterpaddingtop: 50, + groupPaddingBottom: -3, groupPaddingTop: 68, groupRendering: 'always', }, diff --git a/js_modules/dagster-ui/packages/ui-core/src/metadata/MetadataEntry.tsx b/js_modules/dagster-ui/packages/ui-core/src/metadata/MetadataEntry.tsx index c3a488af02d54..70c4c9cbaefb5 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/metadata/MetadataEntry.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/metadata/MetadataEntry.tsx @@ -208,6 +208,7 @@ export const MetadataEntry = ({ ) : ( JSON.stringify(entry.schema, null, 2)} content={() => ( React.ReactNode; copyContent: () => string; }) => { @@ -359,7 +361,7 @@ const MetadataEntryModalAction = (props: { setOpen(true)}>{props.children} setOpen(false)} isOpen={open} diff --git a/js_modules/dagster-ui/packages/ui-core/src/metadata/TableSchema.tsx b/js_modules/dagster-ui/packages/ui-core/src/metadata/TableSchema.tsx index e736eec582225..f002a1cfb143e 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/metadata/TableSchema.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/metadata/TableSchema.tsx @@ -11,7 +11,7 @@ import { Tooltip, } from '@dagster-io/ui-components'; import {Spacing} from '@dagster-io/ui-components/src/components/types'; -import {useState} from 'react'; +import {createContext, useContext, useState} from 'react'; import {TableSchemaFragment} from './types/TableSchema.types'; import {Timestamp} from '../app/time/Timestamp'; @@ -23,6 +23,7 @@ import { MaterializationEvent, TableSchemaMetadataEntry, } from '../graphql/types'; +import {Description} from '../pipelines/Description'; import {AnchorButton} from '../ui/AnchorButton'; type ITableSchema = TableSchemaFragment; @@ -33,7 +34,6 @@ interface ITableSchemaProps { schema: ITableSchema; schemaLoadTimestamp?: number | undefined; itemHorizontalPadding?: Spacing; - assetKeyForColumnSchema?: AssetKeyInput; } export const isCanonicalColumnSchemaEntry = ( @@ -45,12 +45,17 @@ export const isCanonicalColumnLineageEntry = ( m: Pick, ): m is JsonMetadataEntry => m.__typename === 'JsonMetadataEntry' && m.label === 'lineage'; +export const TableSchemaLineageContext = createContext<{assetKey: AssetKeyInput | null}>({ + assetKey: null, +}); + export const TableSchema = ({ schema, schemaLoadTimestamp, itemHorizontalPadding, - assetKeyForColumnSchema, }: ITableSchemaProps) => { + const {assetKey} = useContext(TableSchemaLineageContext); + const multiColumnConstraints = schema.constraints?.other || []; const [filter, setFilter] = useState(''); const rows = schema.columns.filter( @@ -89,7 +94,7 @@ export const TableSchema = ({ Column name Type Description - {assetKeyForColumnSchema ? : undefined} + {assetKey ? : undefined} @@ -106,13 +111,15 @@ export const TableSchema = ({ ))} - {column.description} - {assetKeyForColumnSchema ? ( + + + + {assetKey ? ( } - to={assetDetailsPathForKey(assetKeyForColumnSchema, { + to={assetDetailsPathForKey(assetKey, { view: 'lineage', column: column.name, })} @@ -135,7 +142,7 @@ export const TableSchema = ({ ); }; -const iconForType = (type: string): IconName | null => { +export const iconForColumnType = (type: string): IconName | null => { const lower = type.toLowerCase(); if (lower.includes('bool')) { return 'datatype_bool'; @@ -161,7 +168,7 @@ export const TypeTag = ({type = ''}: {type: string}) => { return ; } - const icon = iconForType(type); + const icon = iconForColumnType(type); return (