Skip to content

Commit

Permalink
[ui] For runs targeting assets, show >1 asset in the Target column
Browse files Browse the repository at this point in the history
We’ve had reports that users who launch small N numbers of assets together find the new run feed UI difficult to use, since it shows either “asset name” or “2 assets” in the Target column. This PR:

- Expands the target column a bit
- Shows as many asset / check tags as will fit in the available space, and then “X more”

The implementation of this uses a new hook `useAdjustChildVisibilityToFill`. The idea is that your component renders some reasonable max number of tags (10) and a more tag, and the hook uses a resize observer + layout effect to show/hide the tags to fit the available space.  I tried doing this using React state, but it looks bad if you can see it adding / removing tags. I think the other approach would be to write a tag “measure” function, or otherwise repeatedly render + size them offscreen, but that’d still force layouts, and in this case the tags are not identical react components (the “4 more” tag is slightly different)

I added a storybook that makes it easy to test what this looks like in a bunch of scenarios.

Sidenote: There’s a bunch of cruft here because the “Target” column components all have to support a “tags” rendering and a “plain” rendering.  This is going away soon when we remove the FF allowing users to revert to the old runs page, and I think it’ll clean up this code!
  • Loading branch information
bengotow committed Nov 24, 2024
1 parent 6898a4d commit dfe7d60
Show file tree
Hide file tree
Showing 7 changed files with 450 additions and 175 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {FIFTEEN_SECONDS, useQueryRefreshAtInterval} from '../../app/QueryRefresh
import {isHiddenAssetGroupJob} from '../../asset-graph/Utils';
import {RunStatus} from '../../graphql/types';
import {PartitionStatus, PartitionStatusHealthSourceOps} from '../../partitions/PartitionStatus';
import {PipelineReference} from '../../pipelines/PipelineReference';
import {PipelineReference, PipelineTag} from '../../pipelines/PipelineReference';
import {AssetKeyTagCollection} from '../../runs/AssetTagCollections';
import {CreatedByTagCell} from '../../runs/CreatedByTag';
import {getBackfillPath} from '../../runs/RunsFeedUtils';
Expand Down Expand Up @@ -118,7 +118,7 @@ export const BackfillRowContent = ({
</td>
{showBackfillTarget ? (
<td style={{width: '20%'}}>
<BackfillTarget backfill={backfill} repoAddress={repoAddress} />
<BackfillTarget backfill={backfill} repoAddress={repoAddress} useTags={false} />
</td>
) : null}
<td style={{width: allPartitions ? 300 : 140}}>
Expand Down Expand Up @@ -146,9 +146,11 @@ export const BackfillRowContent = ({
export const BackfillTarget = ({
backfill,
repoAddress,
useTags,
}: {
backfill: Pick<BackfillTableFragment, 'assetSelection' | 'partitionSet' | 'partitionSetName'>;
repoAddress: RepoAddress | null;
useTags: boolean;
}) => {
const repo = useRepository(repoAddress);
const {assetSelection, partitionSet, partitionSetName} = backfill;
Expand All @@ -160,22 +162,30 @@ export const BackfillTarget = ({
return null;
}
if (partitionSet && repo) {
const link = workspacePipelinePath({
repoName: partitionSet.repositoryOrigin.repositoryName,
repoLocation: partitionSet.repositoryOrigin.repositoryLocationName,
pipelineName: partitionSet.pipelineName,
isJob: isThisThingAJob(repo, partitionSet.pipelineName),
path: `/partitions?partitionSet=${encodeURIComponent(partitionSet.name)}`,
});
if (useTags) {
return (
<Tag icon="partition_set">
<Link to={link}>{partitionSet.name}</Link>
</Tag>
);
}
return (
<Link
style={{fontWeight: 500}}
to={workspacePipelinePath({
repoName: partitionSet.repositoryOrigin.repositoryName,
repoLocation: partitionSet.repositoryOrigin.repositoryLocationName,
pipelineName: partitionSet.pipelineName,
isJob: isThisThingAJob(repo, partitionSet.pipelineName),
path: `/partitions?partitionSet=${encodeURIComponent(partitionSet.name)}`,
})}
>
<Link style={{fontWeight: 500}} to={link}>
{partitionSet.name}
</Link>
);
}
if (partitionSetName) {
if (useTags) {
return <Tag icon="partition_set">{partitionSetName}</Tag>;
}
return <span style={{fontWeight: 500}}>{partitionSetName}</span>;
}
return null;
Expand All @@ -193,10 +203,28 @@ export const BackfillTarget = ({

const buildPipelineOrAssets = () => {
if (assetSelection?.length) {
return <AssetKeyTagCollection assetKeys={assetSelection} dialogTitle="Assets in backfill" />;
return (
<AssetKeyTagCollection
assetKeys={assetSelection}
dialogTitle="Assets in backfill"
useTags={useTags}
maxRows={2}
/>
);
}
if (partitionSet && repo) {
return (
return useTags ? (
<PipelineTag
showIcon
size="small"
pipelineName={partitionSet.pipelineName}
pipelineHrefContext={{
name: partitionSet.repositoryOrigin.repositoryName,
location: partitionSet.repositoryOrigin.repositoryLocationName,
}}
isJob={isThisThingAJob(repo, partitionSet.pipelineName)}
/>
) : (
<PipelineReference
showIcon
size="small"
Expand All @@ -215,11 +243,11 @@ export const BackfillTarget = ({
const repoLink = buildRepoLink();
const pipelineOrAssets = buildPipelineOrAssets();
return (
<Box flex={{direction: 'column', gap: 8}}>
<Box flex={{direction: 'column', gap: 8, alignItems: 'start'}}>
{buildHeader()}
{(pipelineOrAssets || repoLink) && (
<Box flex={{direction: 'column', gap: 4}} style={{fontSize: '12px'}}>
{repoLink}
{repoLink && useTags ? <Tag>{repoLink}</Tag> : repoLink}
{pipelineOrAssets}
</Box>
)}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import {Box, Colors, Icon, Tag} from '@dagster-io/ui-components';
import {Link} from 'react-router-dom';
import styled from 'styled-components';

import {PipelineSnapshotLink} from './PipelinePathUtils';
import {RepoAddress} from '../workspace/types';
Expand Down Expand Up @@ -54,7 +53,7 @@ export const PipelineReference = ({
return (
<Box flex={{direction: 'row', alignItems: 'center', display: 'inline-flex'}}>
{showIcon && (
<Box margin={{right: 8}}>
<Box margin={{right: 4}}>
<Icon color={Colors.accentGray()} name="job" />
</Box>
)}
Expand All @@ -71,16 +70,8 @@ export const PipelineReference = ({

export const PipelineTag = (props: Props) => {
return (
<PipelineTagWrap>
<Tag tooltipText={props.pipelineName}>
<PipelineReference {...props} />
</Tag>
</PipelineTagWrap>
<Tag tooltipText={props.pipelineName} icon="job">
<PipelineReference {...props} showIcon={false} />
</Tag>
);
};

const PipelineTagWrap = styled.span`
span {
line-height: 0;
}
`;
Loading

0 comments on commit dfe7d60

Please sign in to comment.