Skip to content

Commit

Permalink
[ui] Add Automation History to asset checks
Browse files Browse the repository at this point in the history
  • Loading branch information
hellendag committed Dec 31, 2024
1 parent 958bf49 commit f53b43c
Show file tree
Hide file tree
Showing 9 changed files with 611 additions and 5 deletions.
3 changes: 2 additions & 1 deletion js_modules/dagster-ui/packages/ui-core/client.json

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
@@ -0,0 +1,118 @@
import {Box, CursorHistoryControls} from '@dagster-io/ui-components';
import {useMemo} from 'react';

import {EvaluationList} from '../AutoMaterializePolicyPage/EvaluationList';
import {AssetKey} from '../types';
import {
AssetCheckAutomationListQuery,
AssetCheckAutomationListQueryVariables,
} from './types/AssetCheckAutomationList.types';
import {gql} from '../../apollo-client';
import {useCursorPaginatedQuery} from '../../runs/useCursorPaginatedQuery';
import {ASSET_CONDITION_EVALUATION_RECORD_FRAGMENT} from '../AutoMaterializePolicyPage/GetEvaluationsQuery';
import {AssetCheckKeyFragment} from './types/AssetChecksQuery.types';

interface Props {
assetCheck: AssetCheckKeyFragment;
checkName: string;
}

export const AssetCheckAutomationList = ({assetCheck, checkName}: Props) => {
const {queryResult, paginationProps} = useEvaluationsQueryResult({
assetKey: assetCheck.assetKey,
checkName,
});

const evaluations = useMemo(() => {
if (
queryResult?.data?.assetConditionEvaluationRecordsOrError?.__typename ===
'AssetConditionEvaluationRecords'
) {
return queryResult.data.assetConditionEvaluationRecordsOrError.records;
}
return [];
}, [queryResult]);

return (
<>
<Box
padding={{vertical: 12, horizontal: 20}}
flex={{direction: 'row', justifyContent: 'flex-end'}}
>
<CursorHistoryControls {...paginationProps} style={{marginTop: 0}} />
</Box>
<EvaluationList
assetKey={assetCheck.assetKey}
isPartitioned={false}
assetCheckName={checkName}
evaluations={evaluations}
/>
</>
);
};

export const PAGE_SIZE = 30;

// This function exists mostly to use the return type later
export function useEvaluationsQueryResult({
assetKey,
checkName,
}: {
assetKey: AssetKey;
checkName: string;
}) {
const result = useCursorPaginatedQuery<
AssetCheckAutomationListQuery,
AssetCheckAutomationListQueryVariables
>({
nextCursorForResult: (data) => {
if (
data.assetConditionEvaluationRecordsOrError?.__typename ===
'AssetConditionEvaluationRecords'
) {
return data.assetConditionEvaluationRecordsOrError.records[PAGE_SIZE - 1]?.evaluationId;
}
return undefined;
},
getResultArray: (data) => {
if (
data?.assetConditionEvaluationRecordsOrError?.__typename ===
'AssetConditionEvaluationRecords'
) {
return data.assetConditionEvaluationRecordsOrError.records;
}
return [];
},
variables: {
assetCheckKey: {
assetKey: {path: assetKey.path},
name: checkName,
},
},
query: ASSET_CHECK_AUTOMATION_LIST_QUERY,
pageSize: PAGE_SIZE,
});
return result;
}

const ASSET_CHECK_AUTOMATION_LIST_QUERY = gql`
query AssetCheckAutomationListQuery(
$assetCheckKey: AssetCheckHandleInput!
$limit: Int!
$cursor: String
) {
assetConditionEvaluationRecordsOrError(
assetKey: null
assetCheckKey: $assetCheckKey
limit: $limit
cursor: $cursor
) {
... on AssetConditionEvaluationRecords {
records {
...AssetConditionEvaluationRecordFragment
}
}
}
}
${ASSET_CONDITION_EVALUATION_RECORD_FRAGMENT}
`;
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {useVirtualizer} from '@tanstack/react-virtual';
import React, {useMemo, useState} from 'react';
import styled from 'styled-components';

import {AssetCheckAutomationList} from './AssetCheckAutomationList';
import {
ASSET_CHECK_DETAILS_QUERY,
AgentUpgradeRequired,
Expand Down Expand Up @@ -52,6 +53,7 @@ export const AssetChecks = ({
const queryResult = useQuery<AssetChecksQuery, AssetChecksQueryVariables>(ASSET_CHECKS_QUERY, {
variables: {assetKey},
});

const {data} = queryResult;
useQueryRefreshAtInterval(queryResult, FIFTEEN_SECONDS);

Expand Down Expand Up @@ -101,6 +103,8 @@ export const AssetChecks = ({
return checks.find((check) => check.name === selectedCheckName) ?? checks[0];
}, [selectedCheckName, checks]);

const isSelectedCheckAutomated = !!selectedCheck?.automationCondition;

const {paginationProps, executions, executionsLoading} = useHistoricalCheckExecutions(
selectedCheck ? {assetKey, checkName: selectedCheck.name} : null,
);
Expand Down Expand Up @@ -189,6 +193,7 @@ export const AssetChecks = ({
$selected={selectedCheck === check}
onClick={() => {
setSelectedCheckName(check.name);
setActiveTab('overview');
}}
>
<Box flex={{direction: 'column', gap: 2}}>
Expand Down Expand Up @@ -237,6 +242,7 @@ export const AssetChecks = ({
<Box padding={{horizontal: 24}} border="bottom">
<AssetChecksTabs
activeTab={activeTab}
enableAutomationHistory={isSelectedCheckAutomated}
onChange={(tab) => {
setActiveTab(tab);
}}
Expand All @@ -257,6 +263,9 @@ export const AssetChecks = ({
paginationProps={paginationProps}
/>
) : null}
{activeTab === 'automation-history' ? (
<AssetCheckAutomationList assetCheck={selectedCheck} checkName={selectedCheck.name} />
) : null}
</Box>
</Box>
</Box>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,15 @@ import {
import {ASSET_CHECK_TABLE_FRAGMENT} from './VirtualizedAssetCheckTable';
import {gql} from '../../apollo-client';

const ASSET_CHECK_KEY_FRAGMENT = gql`
fragment AssetCheckKeyFragment on AssetCheck {
name
assetKey {
path
}
}
`;

export const ASSET_CHECKS_QUERY = gql`
query AssetChecksQuery($assetKey: AssetKeyInput!) {
assetNodeOrError(assetKey: $assetKey) {
Expand All @@ -18,6 +27,7 @@ export const ASSET_CHECKS_QUERY = gql`
}
... on AssetChecks {
checks {
...AssetCheckKeyFragment
...ExecuteChecksButtonCheckFragment
...AssetCheckTableFragment
}
Expand All @@ -26,7 +36,9 @@ export const ASSET_CHECKS_QUERY = gql`
}
}
}
${EXECUTE_CHECKS_BUTTON_ASSET_NODE_FRAGMENT}
${EXECUTE_CHECKS_BUTTON_CHECK_FRAGMENT}
${ASSET_CHECK_TABLE_FRAGMENT}
${ASSET_CHECK_KEY_FRAGMENT}
`;
Original file line number Diff line number Diff line change
@@ -1,17 +1,31 @@
import {Tab, Tabs} from '@dagster-io/ui-components';
import {Tab, Tabs, Tooltip} from '@dagster-io/ui-components';

export type AssetChecksTabType = 'overview' | 'execution-history';
export type AssetChecksTabType = 'overview' | 'execution-history' | 'automation-history';

interface Props {
activeTab: AssetChecksTabType;
enableAutomationHistory: boolean;
onChange: (tabId: AssetChecksTabType) => void;
}

export const AssetChecksTabs = ({activeTab, onChange}: Props) => {
export const AssetChecksTabs = ({activeTab, enableAutomationHistory, onChange}: Props) => {
return (
<Tabs selectedTabId={activeTab} onChange={onChange}>
<Tab id="overview" title="Overview" />
<Tab id="execution-history" title="Execution history" />
<Tab
id="automation-history"
title={
<Tooltip
content="This asset check does not have an automation condition configured."
canShow={!enableAutomationHistory}
placement="top"
>
Automation history
</Tooltip>
}
disabled={!enableAutomationHistory}
/>
</Tabs>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,10 @@ export const ASSET_CHECK_TABLE_FRAGMENT = gql`
name
description
canExecuteIndividually
automationCondition {
label
expandedLabel
}
...ExecuteChecksButtonCheckFragment
executionForLatestMaterialization {
...AssetCheckExecutionFragment
Expand Down
Loading

0 comments on commit f53b43c

Please sign in to comment.