Skip to content

Commit

Permalink
[ui] Show backfill policies, preview of backfill partition ranges
Browse files Browse the repository at this point in the history
  • Loading branch information
bengotow committed Oct 31, 2023
1 parent f5933ef commit 3c7e80f
Show file tree
Hide file tree
Showing 21 changed files with 786 additions and 343 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,5 @@ export const calculateMiddleTruncation = (
end = mid - 1;
}
}

return `${text.slice(0, end)}${text.slice(-end)}`;
};
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,9 @@ const SIDEBAR_ASSET_FRAGMENT = gql`
description
}
}
backfillPolicy {
description
}
partitionDefinition {
description
}
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export const AssetLink: React.FC<{
style={{maxWidth: '100%'}}
>
{icon ? (
<Box margin={{right: 8, top: 2}}>
<Box margin={{right: 8, top: 2}} style={{width: 16}}>
<Icon name={icon} color={Colors.Gray400} />
</Box>
) : null}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ export const AssetNodeDefinition: React.FC<{
</Box>
</>
)}

{assetNode.freshnessPolicy && (
<>
<Box padding={{vertical: 16, horizontal: 24}} border="top-and-bottom">
Expand Down Expand Up @@ -127,6 +128,21 @@ export const AssetNodeDefinition: React.FC<{
</Box>
</>
)}

{assetNode.backfillPolicy && (
<>
<Box padding={{vertical: 16, horizontal: 24}} border="top-and-bottom">
<Subheading>Backfill policy</Subheading>
</Box>
<Box
padding={{vertical: 16, horizontal: 24}}
flex={{gap: 12, alignItems: 'flex-start'}}
>
<Body style={{flex: 1}}>{assetNode.backfillPolicy.description}</Body>
</Box>
</>
)}

<Box
padding={{vertical: 16, horizontal: 24}}
border="top-and-bottom"
Expand Down Expand Up @@ -326,7 +342,9 @@ export const ASSET_NODE_DEFINITION_FRAGMENT = gql`
cronSchedule
cronScheduleTimezone
}
backfillPolicy {
description
}
partitionDefinition {
description
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,14 @@ export const AssetSidebarActivitySummary: React.FC<Props> = ({
</SidebarSection>
)}

{asset.backfillPolicy && (
<SidebarSection title="Backfill policy">
<Box margin={{horizontal: 24, vertical: 12}} flex={{gap: 12, alignItems: 'flex-start'}}>
<Body style={{flex: 1}}>{asset.backfillPolicy.description}</Body>
</Box>
</SidebarSection>
)}

{loadedPartitionKeys.length > 1 ? null : (
<>
<SidebarSection
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
import {gql, useQuery} from '@apollo/client';
import {Box, Button, Colors, Dialog, DialogFooter, Spinner} from '@dagster-io/ui-components';
import {useVirtualizer} from '@tanstack/react-virtual';
import React from 'react';
import styled from 'styled-components';

import {tokenForAssetKey} from '../asset-graph/Utils';
import {TargetPartitionsDisplay} from '../instance/backfill/TargetPartitionsDisplay';
import {testId} from '../testing/testId';
import {Container, HeaderCell, Inner, Row, RowCell} from '../ui/VirtualizedTable';

import {AssetLink} from './AssetLink';
import {asAssetKeyInput} from './asInput';
import {AssetKey} from './types';
import {
BackfillPreviewQuery,
BackfillPreviewQueryVariables,
} from './types/BackfillPreviewModal.types';
import {
BackfillPolicyForLaunchAssetFragment,
PartitionDefinitionForLaunchAssetFragment,
} from './types/LaunchAssetExecutionButton.types';

interface BackfillPreviewModalProps {
isOpen: boolean;
assets: {
assetKey: AssetKey;
partitionDefinition: PartitionDefinitionForLaunchAssetFragment | null;
backfillPolicy: BackfillPolicyForLaunchAssetFragment | null;
}[];
keysFiltered: string[];
setOpen: (isOpen: boolean) => void;
}
const TEMPLATE_COLUMNS = '1fr 1fr 1fr 1fr';

export const BackfillPreviewModal = ({
isOpen,
setOpen,
assets,
keysFiltered,
}: BackfillPreviewModalProps) => {
const assetKeys = React.useMemo(() => assets.map(asAssetKeyInput), [assets]);
const parentRef = React.useRef<HTMLDivElement | null>(null);

const rowVirtualizer = useVirtualizer({
count: assets.length,
getScrollElement: () => parentRef.current,
estimateSize: () => 60,
overscan: 10,
});
const totalHeight = rowVirtualizer.getTotalSize();
const items = rowVirtualizer.getVirtualItems();

const {data} = useQuery<BackfillPreviewQuery, BackfillPreviewQueryVariables>(
BACKFILL_PREVIEW_QUERY,
{
variables: {partitionNames: keysFiltered, assetKeys},
skip: !isOpen,
},
);

const partitionsByAssetToken = React.useMemo(() => {
return Object.fromEntries(
(data?.assetBackfillPreview || []).map((d) => [tokenForAssetKey(d.assetKey), d.partitions]),
);
}, [data]);

// BG Note: The transform: scale(1) below fixes a bug with MiddleTruncate where the text size
// is measured while the dialog is animating open and the scale is < 1, causing it to think
// it needs to truncate. A more general fix for this seems like it'll require a lot of testing.

return (
<Dialog
title="Backfill preview"
isOpen={isOpen}
onClose={() => setOpen(false)}
style={{width: '90vw', maxWidth: 1100, transform: 'scale(1)'}}
>
<Container
ref={parentRef}
style={{maxHeight: '50vh'}}
data-testid={testId('backfill-preview-modal-content')}
>
<BackfillPreviewTableHeader />
<Inner $totalHeight={totalHeight}>
{items.map(({index, size, start}) => {
const {assetKey, partitionDefinition, backfillPolicy} = assets[index]!;
const token = tokenForAssetKey(assetKey);
const partitions = partitionsByAssetToken[token];

return (
<Row key={token} $height={size} $start={start}>
<RowGrid border={index < assets.length - 1 ? 'bottom' : undefined}>
<RowCell>
<AssetLink path={assetKey.path} textStyle="middle-truncate" icon="asset" />
</RowCell>
{backfillPolicy ? (
<RowCell style={{color: Colors.Dark}}>{backfillPolicy?.description}</RowCell>
) : (
<RowCell>{'\u2013'}</RowCell>
)}
{partitionDefinition ? (
<RowCell style={{color: Colors.Dark}}>
{partitionDefinition?.description}
</RowCell>
) : (
<RowCell>{'\u2013'}</RowCell>
)}
<RowCell style={{color: Colors.Dark, alignItems: 'flex-start'}}>
{partitions ? (
<TargetPartitionsDisplay targetPartitions={partitions} />
) : (
<Spinner purpose="body-text" />
)}
</RowCell>
</RowGrid>
</Row>
);
})}
</Inner>
</Container>
<DialogFooter topBorder>
<Button intent="primary" autoFocus={true} onClick={() => setOpen(false)}>
OK
</Button>
</DialogFooter>
</Dialog>
);
};

const RowGrid = styled(Box)`
display: grid;
grid-template-columns: ${TEMPLATE_COLUMNS};
height: 100%;
`;

export const BackfillPreviewTableHeader = () => {
return (
<Box
border="bottom"
style={{
display: 'grid',
gridTemplateColumns: TEMPLATE_COLUMNS,
height: '32px',
fontSize: '12px',
color: Colors.Gray600,
}}
>
<HeaderCell>Asset key</HeaderCell>
<HeaderCell>Backfill policy</HeaderCell>
<HeaderCell>Partition definition</HeaderCell>
<HeaderCell>Partitions to launch</HeaderCell>
</Box>
);
};

export const BACKFILL_PREVIEW_QUERY = gql`
query BackfillPreviewQuery($partitionNames: [String!]!, $assetKeys: [AssetKeyInput!]!) {
assetBackfillPreview(params: {partitionNames: $partitionNames, assetSelection: $assetKeys}) {
assetKey {
path
}
partitions {
partitionKeys
ranges {
start
end
}
}
}
}
`;
Loading

0 comments on commit 3c7e80f

Please sign in to comment.