diff --git a/js_modules/dagster-ui/packages/ui-components/src/components/Suggest.tsx b/js_modules/dagster-ui/packages/ui-components/src/components/Suggest.tsx index 440b5a0edf20c..9990b40ede1c8 100644 --- a/js_modules/dagster-ui/packages/ui-components/src/components/Suggest.tsx +++ b/js_modules/dagster-ui/packages/ui-components/src/components/Suggest.tsx @@ -98,23 +98,25 @@ export const Suggest = (props: Props) => { } return ( - ( -
- {props.renderItem(props.filteredItems[a.index] as T, a.index)} -
- )} - width={menuWidth} - height={Math.min(props.filteredItems.length * itemHeight, itemHeight * VISIBLE_ITEMS)} - /> +
+ ( +
+ {props.renderItem(props.filteredItems[a.index] as T, a.index)} +
+ )} + width={menuWidth} + height={Math.min(props.filteredItems.length * itemHeight, itemHeight * VISIBLE_ITEMS)} + /> +
); }} popoverProps={allPopoverProps} diff --git a/js_modules/dagster-ui/packages/ui-components/src/components/TagSelector.tsx b/js_modules/dagster-ui/packages/ui-components/src/components/TagSelector.tsx index 0aa3892e42f04..3f17ff9f7f025 100644 --- a/js_modules/dagster-ui/packages/ui-components/src/components/TagSelector.tsx +++ b/js_modules/dagster-ui/packages/ui-components/src/components/TagSelector.tsx @@ -43,6 +43,8 @@ type Props = { dropdownStyles?: React.CSSProperties; rowWidth?: number; rowHeight?: number; + closeOnSelect?: boolean; + usePortal?: boolean; }; const defaultRenderTag = (tag: string, tagProps: TagSelectorTagProps) => { @@ -58,7 +60,7 @@ const defaultRenderTag = (tag: string, tagProps: TagSelectorTagProps) => { maxWidth: '120px', }} data-tooltip={tag} - data-tooltip-style={DefaultTagTooltipStyle} + data-tooltip-style={TagSelectorDefaultTagTooltipStyle} > @@ -101,6 +103,8 @@ export const TagSelector = ({ dropdownStyles, renderTagList, rowHeight = MENU_ITEM_HEIGHT, + closeOnSelect, + usePortal, }: Props) => { const [isDropdownOpen, setIsDropdownOpen] = React.useState(false); const {viewport, containerProps} = useViewport(); @@ -135,6 +139,9 @@ export const TagSelector = ({ setSelectedTags( selected ? selectedTags.filter((t) => t !== tag) : [...selectedTags, tag], ); + if (closeOnSelect) { + setIsDropdownOpen(false); + } }; if (renderDropdownItem) { return
{renderDropdownItem(tag, {toggle, selected})}
; @@ -156,6 +163,7 @@ export const TagSelector = ({ return {dropdownContent}; }, [ allTags, + closeOnSelect, dropdownStyles, items, renderDropdown, @@ -199,27 +207,28 @@ export const TagSelector = ({ } } }} - content={
{dropdown}
} + content={
{dropdown}
} targetTagName="div" onOpening={rowVirtualizer.measure} onOpened={rowVirtualizer.measure} + usePortal={usePortal} > - { setIsDropdownOpen((isOpen) => !isOpen); }} {...containerProps} > - {tagsContent} + {tagsContent}
-
+ ); }; -const Container = styled.div` +export const TagSelectorContainer = styled.div` display: flex; flex-direction: row; align-items: center; @@ -231,7 +240,7 @@ const Placeholder = styled.div` color: ${Colors.textDisabled()}; `; -const TagsContainer = styled(Box)` +export const TagSelectorTagsContainer = styled(Box)` overflow-x: auto; &::-webkit-scrollbar { @@ -297,7 +306,7 @@ export const TagSelectorWithSearch = ( ); }; -const DefaultTagTooltipStyle = JSON.stringify({ +export const TagSelectorDefaultTagTooltipStyle = JSON.stringify({ background: Colors.backgroundDefault(), border: `1px solid ${Colors.borderDefault()}`, color: Colors.textDefault(), diff --git a/js_modules/dagster-ui/packages/ui-core/src/app/Flags.tsx b/js_modules/dagster-ui/packages/ui-core/src/app/Flags.tsx index 9356449eda7e3..dec71268c281f 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/app/Flags.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/app/Flags.tsx @@ -11,6 +11,7 @@ export const FeatureFlag = { flagDisableWebsockets: 'flagDisableWebsockets' as const, flagSidebarResources: 'flagSidebarResources' as const, flagDisableAutoLoadDefaults: 'flagDisableAutoLoadDefaults' as const, + flagUseNewAutomationPage: 'flagUseNewAutomationPage' as const, }; export type FeatureFlagType = keyof typeof FeatureFlag; diff --git a/js_modules/dagster-ui/packages/ui-core/src/app/getVisibleFeatureFlagRows.tsx b/js_modules/dagster-ui/packages/ui-core/src/app/getVisibleFeatureFlagRows.tsx index d818c2dd468a4..ab0e88ce13de7 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/app/getVisibleFeatureFlagRows.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/app/getVisibleFeatureFlagRows.tsx @@ -20,4 +20,8 @@ export const getVisibleFeatureFlagRows = () => [ key: 'Debug console logging', flagType: FeatureFlag.flagDebugConsoleLogging, }, + { + key: 'Use new asset auto-materialize history page', + flagType: FeatureFlag.flagUseNewAutomationPage, + }, ]; diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/AssetEventMetadataEntriesTable.tsx b/js_modules/dagster-ui/packages/ui-core/src/assets/AssetEventMetadataEntriesTable.tsx index 0de2ab14e1c91..8af1e9ab70464 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/AssetEventMetadataEntriesTable.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/AssetEventMetadataEntriesTable.tsx @@ -19,7 +19,11 @@ export const AssetEventMetadataEntriesTable = ({ event, observations, }: { - event: AssetObservationFragment | AssetMaterializationFragment | null; + event: + | (Pick & { + timestamp?: string | number; + }) + | null; observations?: (AssetObservationFragment | AssetMaterializationFragment)[]; }) => { if (!event || (!event.metadataEntries.length && !observations?.length)) { diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/AssetSidebarActivitySummary.tsx b/js_modules/dagster-ui/packages/ui-core/src/assets/AssetSidebarActivitySummary.tsx index 98e7dd261d224..76ab625ced3fa 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/AssetSidebarActivitySummary.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/AssetSidebarActivitySummary.tsx @@ -82,8 +82,8 @@ export const AssetSidebarActivitySummary = ({ padding={{horizontal: 24, vertical: 12}} flex={{direction: 'row', gap: 4, alignItems: 'center'}} > - - View auto-materialize history + + View automation history
diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/AssetTabs.tsx b/js_modules/dagster-ui/packages/ui-core/src/assets/AssetTabs.tsx index 0babb439566ef..244b8fd19b244 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/AssetTabs.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/AssetTabs.tsx @@ -34,7 +34,7 @@ export const DEFAULT_ASSET_TAB_ORDER = [ 'plots', 'definition', 'lineage', - 'auto-materialize-history', + 'automation', ]; export type AssetTabConfigInput = { @@ -89,10 +89,10 @@ export const buildAssetTabMap = (input: AssetTabConfigInput): Record { ); }; + const {flagUseNewAutomationPage} = useFeatureFlags(); + const renderAutomaterializeHistoryTab = () => { if (definitionQueryResult.loading && !definitionQueryResult.previousData) { return ; } + if (flagUseNewAutomationPage) { + return ; + } return ( - @@ -214,7 +221,7 @@ export const AssetView = ({assetKey, trace}: Props) => { return renderEventsTab(); case 'plots': return renderPlotsTab(); - case 'auto-materialize-history': + case 'automation': return renderAutomaterializeHistoryTab(); case 'checks': return renderChecksTab(); diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/AssetAutomaterializePolicyPage.tsx b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/AssetAutomaterializePolicyPage.tsx index 4057761f3149b..75703fd5b73bf 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/AssetAutomaterializePolicyPage.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/AssetAutomaterializePolicyPage.tsx @@ -1,42 +1,39 @@ -import {Box, Colors, Subheading} from '@dagster-io/ui-components'; +import {Box, Colors, Spinner} from '@dagster-io/ui-components'; +import * as React from 'react'; import {useMemo} from 'react'; import styled from 'styled-components'; import {AutoMaterializeExperimentalBanner} from './AutoMaterializeExperimentalBanner'; import {AutomaterializeLeftPanel} from './AutomaterializeLeftPanel'; import {AutomaterializeMiddlePanel} from './AutomaterializeMiddlePanel'; -import {AutomaterializeRightPanel} from './AutomaterializeRightPanel'; import {useEvaluationsQueryResult} from './useEvaluationsQueryResult'; import {FIFTEEN_SECONDS, useQueryRefreshAtInterval} from '../../app/QueryRefresh'; import {useQueryPersistedState} from '../../hooks/useQueryPersistedState'; import {AssetKey} from '../types'; +import {AssetViewDefinitionNodeFragment} from '../types/AssetView.types'; export const AssetAutomaterializePolicyPage = ({ assetKey, - assetHasDefinedPartitions, + definition, }: { assetKey: AssetKey; - assetHasDefinedPartitions: boolean; + definition?: AssetViewDefinitionNodeFragment | null; }) => { const {queryResult, paginationProps} = useEvaluationsQueryResult({assetKey}); useQueryRefreshAtInterval(queryResult, FIFTEEN_SECONDS); - const {evaluations} = useMemo(() => { + const evaluations = useMemo(() => { if ( - queryResult.data?.autoMaterializeAssetEvaluationsOrError?.__typename === - 'AutoMaterializeAssetEvaluationRecords' && + queryResult.data?.assetConditionEvaluationRecordsOrError?.__typename === + 'AssetConditionEvaluationRecords' && queryResult.data?.assetNodeOrError?.__typename === 'AssetNode' ) { - return { - evaluations: queryResult.data?.autoMaterializeAssetEvaluationsOrError.records, - currentAutoMaterializeEvaluationId: - queryResult.data.assetNodeOrError.currentAutoMaterializeEvaluationId, - }; + return queryResult.data?.assetConditionEvaluationRecordsOrError.records; } - return {evaluations: [], currentAutoMaterializeEvaluationId: null}; + return []; }, [ - queryResult.data?.autoMaterializeAssetEvaluationsOrError, + queryResult.data?.assetConditionEvaluationRecordsOrError, queryResult.data?.assetNodeOrError, ]); @@ -63,49 +60,48 @@ export const AssetAutomaterializePolicyPage = ({ return evaluations.find((evaluation) => evaluation.evaluationId === selectedEvaluationId); }, [selectedEvaluationId, isFirstPage, evaluations]); + if (!queryResult.data && queryResult.loading) { + return ( + + + + ); + } + return ( - - - + - - - Evaluation history + + + { + setSelectedEvaluationId(evaluation.evaluationId); + }} + selectedEvaluation={selectedEvaluation} + /> - - - { - setSelectedEvaluationId(evaluation.evaluationId); - }} - selectedEvaluation={selectedEvaluation} - /> - - - - + + - - - ); diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/AutoMaterializeExperimentalBanner.tsx b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/AutoMaterializeExperimentalBanner.tsx index 941308e1dfdb1..3e81f920642c0 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/AutoMaterializeExperimentalBanner.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/AutoMaterializeExperimentalBanner.tsx @@ -1,24 +1,35 @@ -import {Alert, Colors, Icon, Tag, Tooltip} from '@dagster-io/ui-components'; +import {Alert, Box, Colors, Icon, Tag, Tooltip} from '@dagster-io/ui-components'; + +import {useStateWithStorage} from '../../hooks/useStateWithStorage'; const LearnMoreLink = 'https://docs.dagster.io/concepts/assets/asset-auto-execution#auto-materializing-assets-'; export const AutoMaterializeExperimentalBanner = () => { + const [closed, setClosed] = useStateWithStorage('automation-experimental', (value) => !!value); + if (closed) { + return null; + } return ( - } - description={ - - You can learn more about this new feature and provide feedback{' '} - - here - - . - - } - /> + + } + onClose={() => { + setClosed(true); + }} + description={ + + You can learn more about this new feature and provide feedback{' '} + + here + + . + + } + /> + ); }; diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/AutomaterializeLeftPanel.tsx b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/AutomaterializeLeftPanel.tsx index 45702a4c0f576..7a2d3e9036e0c 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/AutomaterializeLeftPanel.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/AutomaterializeLeftPanel.tsx @@ -1,18 +1,33 @@ -import {Box, Caption, Colors, CursorPaginationControls} from '@dagster-io/ui-components'; +import { + Body2, + Box, + Caption, + Colors, + CursorPaginationControls, + Icon, + MiddleTruncate, + Subtitle1, +} from '@dagster-io/ui-components'; +import React from 'react'; +import {Link} from 'react-router-dom'; import styled from 'styled-components'; -import {EvaluationCounts} from './EvaluationCounts'; -import {AutoMaterializeEvaluationRecordItemFragment} from './types/GetEvaluationsQuery.types'; +import {AssetConditionEvaluationRecordFragment} from './types/GetEvaluationsQuery.types'; import {useEvaluationsQueryResult} from './useEvaluationsQueryResult'; +import {SensorType} from '../../graphql/types'; import {TimestampDisplay} from '../../schedules/TimestampDisplay'; +import {numberFormatter} from '../../ui/formatters'; +import {buildRepoAddress} from '../../workspace/buildRepoAddress'; +import {workspacePathFromAddress} from '../../workspace/workspacePath'; +import {AssetViewDefinitionNodeFragment} from '../types/AssetView.types'; interface Props extends ListProps { - evaluations: AutoMaterializeEvaluationRecordItemFragment[]; + evaluations: AssetConditionEvaluationRecordFragment[]; paginationProps: ReturnType['paginationProps']; } export const AutomaterializeLeftPanel = ({ - assetHasDefinedPartitions, + definition, evaluations, paginationProps, onSelectEvaluation, @@ -21,7 +36,7 @@ export const AutomaterializeLeftPanel = ({ return ( void; - selectedEvaluation?: AutoMaterializeEvaluationRecordItemFragment; + definition?: AssetViewDefinitionNodeFragment | null; + evaluations: AssetConditionEvaluationRecordFragment[]; + onSelectEvaluation: (evaluation: AssetConditionEvaluationRecordFragment) => void; + selectedEvaluation?: AssetConditionEvaluationRecordFragment; } export const AutomaterializeLeftList = (props: ListProps) => { - const {assetHasDefinedPartitions, evaluations, onSelectEvaluation, selectedEvaluation} = props; + const {evaluations, onSelectEvaluation, selectedEvaluation, definition} = props; + + const sensorName = React.useMemo( + () => + definition?.targetingInstigators.find( + (instigator) => + instigator.__typename === 'Sensor' && + instigator.sensorType === SensorType.AUTOMATION_POLICY, + )?.name, + [definition], + ); + + const repoAddress = definition + ? buildRepoAddress(definition.repository.name, definition.repository.location.name) + : null; return ( - - {evaluations.map((evaluation) => { - const isSelected = selectedEvaluation?.evaluationId === evaluation.evaluationId; - const {numRequested, numSkipped, numDiscarded} = evaluation; - - return ( - { - onSelectEvaluation(evaluation); - }} - $selected={isSelected} - > - - - + + + Evaluations + + + + + + + {repoAddress && sensorName ? ( + + + + ) : ( + {sensorName ?? 'Automation'} + )} + + + + + {evaluations.length === 0 ? ( + + No evaluations - - ); - })} - - Evaluations are retained for 30 days + ) : null} + {evaluations.map((evaluation) => { + const isSelected = selectedEvaluation?.id === evaluation.id; + + const hasRequested = evaluation.numRequested > 0; + + function status() { + if (hasRequested) { + if (definition?.partitionDefinition) { + return ( + {numberFormatter.format(evaluation.numRequested)} Requested + ); + } + return requested; + } + return not requested; + } + + return ( + { + onSelectEvaluation(evaluation); + }} + $selected={isSelected} + > + + + + + + + +
{status()}
+
+
+ ); + })} +
+ + Evaluations are retained for 30 days +
); @@ -127,3 +201,11 @@ const EvaluationListItem = styled.button` padding: 8px 12px; `; + +export const StatusDot = styled.div<{$color: string}>` + background-color: ${({$color}) => $color}; + border-radius: 50%; + width: 10px; + height: 10px; + margin: 5px; +`; diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/AutomaterializeMiddlePanel.tsx b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/AutomaterializeMiddlePanel.tsx index 68b1e2645ccbb..2a340d93184f8 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/AutomaterializeMiddlePanel.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/AutomaterializeMiddlePanel.tsx @@ -1,59 +1,75 @@ -import {useQuery} from '@apollo/client'; -import {Box, NonIdealState, Subheading} from '@dagster-io/ui-components'; - -import {AutomaterializeRequestedPartitionsLink} from './AutomaterializeRequestedPartitionsLink'; -import {AutomaterializeRunTag} from './AutomaterializeRunTag'; -import {GET_EVALUATIONS_QUERY} from './GetEvaluationsQuery'; -import {RuleEvaluationOutcomes} from './RuleEvaluationOutcomes'; -import {EvaluationOrEmpty, NoConditionsMetEvaluation} from './types'; +import {gql, useQuery} from '@apollo/client'; import { - AutoMaterializeEvaluationRecordItemFragment, + BaseTag, + Body2, + Box, + Colors, + Icon, + MenuItem, + MiddleTruncate, + NonIdealState, + Popover, + Subheading, + Subtitle2, + Tag, + TagSelectorContainer, + TagSelectorDefaultTagTooltipStyle, + TagSelectorWithSearch, +} from '@dagster-io/ui-components'; +import React from 'react'; +import styled from 'styled-components'; + +import {StatusDot} from './AutomaterializeLeftPanel'; +import {AutomaterializeRunsTable} from './AutomaterializeRunsTable'; +import { + GET_EVALUATIONS_QUERY, + GET_EVALUATIONS_SPECIFIC_PARTITION_QUERY, +} from './GetEvaluationsQuery'; +import {PartitionSubsetList} from './PartitionSegmentWithPopover'; +import {PolicyEvaluationTable} from './PolicyEvaluationTable'; +import { + FullPartitionsQuery, + FullPartitionsQueryVariables, +} from './types/AutomaterializeMiddlePanel.types'; +import { + AssetConditionEvaluationRecordFragment, GetEvaluationsQuery, GetEvaluationsQueryVariables, - RuleWithEvaluationsFragment, + GetEvaluationsSpecificPartitionQuery, + GetEvaluationsSpecificPartitionQueryVariables, } from './types/GetEvaluationsQuery.types'; import {ErrorWrapper} from '../../app/PythonErrorInfo'; -import {AutoMaterializeDecisionType, AutoMaterializeRule} from '../../graphql/types'; +import {formatElapsedTimeWithMsec} from '../../app/Util'; +import {Timestamp} from '../../app/time/Timestamp'; +import {DimensionPartitionKeys, SensorType} from '../../graphql/types'; +import {useQueryPersistedState} from '../../hooks/useQueryPersistedState'; +import {AnchorButton} from '../../ui/AnchorButton'; +import {buildRepoAddress} from '../../workspace/buildRepoAddress'; +import {workspacePathFromAddress} from '../../workspace/workspacePath'; import {AssetKey} from '../types'; +import {AssetViewDefinitionNodeFragment} from '../types/AssetView.types'; interface Props { assetKey: AssetKey; - assetHasDefinedPartitions: boolean; selectedEvaluationId: number | undefined; + selectedEvaluation?: AssetConditionEvaluationRecordFragment; + definition?: AssetViewDefinitionNodeFragment | null; } -const EMPTY: EvaluationOrEmpty = { - __typename: 'no_conditions_met', - evaluationId: 0, - amount: 0, - endTimestamp: 0, - startTimestamp: 0, -}; +const emptyArray: any[] = []; -const extractRequestedPartitionKeys = (rulesWithEvaluations: RuleWithEvaluationsFragment[]) => { - let requested: string[] = []; - let skippedOrDiscarded: string[] = []; +export const AutomaterializeMiddlePanel = (props: Props) => { + const { + assetKey, + selectedEvaluationId, + selectedEvaluation: _selectedEvaluation, + definition, + } = props; - rulesWithEvaluations.forEach(({rule, ruleEvaluations}) => { - const partitionKeys = ruleEvaluations.flatMap((e) => - e.partitionKeysOrError?.__typename === 'PartitionKeys' - ? e.partitionKeysOrError.partitionKeys - : [], - ); - if (rule.decisionType === AutoMaterializeDecisionType.MATERIALIZE) { - requested = requested.concat(partitionKeys); - } else { - skippedOrDiscarded = skippedOrDiscarded.concat(partitionKeys); - } + const [selectedPartition, setSelectedPartition] = useQueryPersistedState({ + queryKey: 'selectedPartition', }); - const skippedOrDiscardedSet = new Set(skippedOrDiscarded); - return new Set(requested.filter((partitionKey) => !skippedOrDiscardedSet.has(partitionKey))); -}; - -export const AutomaterializeMiddlePanel = (props: Props) => { - const {assetKey, assetHasDefinedPartitions, selectedEvaluationId} = props; - // We receive the selected evaluation ID and retrieve it here because the middle panel // may be displaying an evaluation that was not retrieved at the page level for the // left panel, e.g. as we paginate away from it, we don't want to lose it. @@ -65,10 +81,33 @@ export const AutomaterializeMiddlePanel = (props: Props) => { cursor: selectedEvaluationId ? `${selectedEvaluationId + 1}` : undefined, limit: 2, }, + skip: !!_selectedEvaluation || !!selectedPartition, + }, + ); + + const {data: specificPartitionData, previousData: previousSpecificPartitionData} = useQuery< + GetEvaluationsSpecificPartitionQuery, + GetEvaluationsSpecificPartitionQueryVariables + >(GET_EVALUATIONS_SPECIFIC_PARTITION_QUERY, { + variables: { + assetKey, + evaluationId: selectedEvaluationId!, + partition: selectedPartition!, }, + skip: !selectedEvaluationId || !selectedPartition, + }); + + const sensorName = React.useMemo( + () => + definition?.targetingInstigators.find( + (instigator) => + instigator.__typename === 'Sensor' && + instigator.sensorType === SensorType.AUTOMATION_POLICY, + )?.name, + [definition], ); - if (loading && !data) { + if (!_selectedEvaluation && loading && !data) { return ( { } if ( - data?.autoMaterializeAssetEvaluationsOrError?.__typename === + data?.assetConditionEvaluationRecordsOrError?.__typename === 'AutoMaterializeAssetEvaluationNeedsMigrationError' ) { return ( @@ -103,69 +142,172 @@ export const AutomaterializeMiddlePanel = (props: Props) => { ); } - const currentRules = - (data?.assetNodeOrError.__typename === 'AssetNode' && - data.assetNodeOrError.autoMaterializePolicy?.rules) || - []; - - const evaluations = data?.autoMaterializeAssetEvaluationsOrError?.records || []; + const evaluations = data?.assetConditionEvaluationRecordsOrError?.records || []; const selectedEvaluation = - evaluations.find((evaluation) => evaluation.evaluationId === selectedEvaluationId) || EMPTY; + _selectedEvaluation ?? + evaluations.find((evaluation) => evaluation.evaluationId === selectedEvaluationId); + + if (!selectedEvaluationId && !evaluations.length) { + const repoAddress = definition + ? buildRepoAddress(definition.repository.name, definition.repository.location.name) + : null; + + return ( + + + + + + This asset’s automation policy has not been evaluated yet. Make sure your + automation sensor is running. + +
+ + Manage sensor + +
+ + Learn more about automation policies + +
+ + } + /> +
+
+ ); + } return ( ); }; export const AutomaterializeMiddlePanelWithData = ({ - currentRules, selectedEvaluation, - assetHasDefinedPartitions, + definition, + selectPartition, + specificPartitionData, + selectedPartition, }: { - currentRules: AutoMaterializeRule[]; - selectedEvaluation: NoConditionsMetEvaluation | AutoMaterializeEvaluationRecordItemFragment; - assetHasDefinedPartitions: boolean; + definition?: AssetViewDefinitionNodeFragment | null; + selectedEvaluation?: AssetConditionEvaluationRecordFragment; + selectPartition: (partitionKey: string | null) => void; + specificPartitionData?: GetEvaluationsSpecificPartitionQuery; + selectedPartition: string | null; }) => { - const runIds = - selectedEvaluation?.__typename === 'AutoMaterializeAssetEvaluationRecord' - ? selectedEvaluation.runIds - : []; - const rulesWithRuleEvaluations = - selectedEvaluation?.__typename === 'AutoMaterializeAssetEvaluationRecord' - ? selectedEvaluation.rulesWithRuleEvaluations - : []; - const rules = - selectedEvaluation?.__typename === 'AutoMaterializeAssetEvaluationRecord' && - selectedEvaluation.rules - ? selectedEvaluation.rules - : currentRules; - - const headerRight = () => { - if (runIds.length === 0) { - return null; - } - if (assetHasDefinedPartitions) { + const evaluation = selectedEvaluation?.evaluation; + const rootEvaluationNode = React.useMemo( + () => evaluation?.evaluationNodes.find((node) => node.uniqueId === evaluation.rootUniqueId), + [evaluation], + ); + const rootPartitionedEvaluationNode = + rootEvaluationNode?.__typename === 'PartitionedAssetConditionEvaluationNode' + ? rootEvaluationNode + : null; + + const statusTag = React.useMemo(() => { + if (selectedEvaluation?.numRequested) { + if (definition?.partitionDefinition) { + return ( + + } + > + + + + {selectedEvaluation.numRequested} Requested + + + + ); + } return ( - + + + + Requested + + ); } - return ; - }; + return ( + + + + Not Requested + + + ); + }, [ + definition?.partitionDefinition, + rootPartitionedEvaluationNode, + selectPartition, + selectedEvaluation?.numRequested, + ]); + + const {data} = useQuery( + FULL_PARTITIONS_QUERY, + { + variables: definition + ? { + assetKey: {path: definition.assetKey.path}, + } + : undefined, + skip: !definition?.assetKey, + }, + ); + + let partitionKeys: DimensionPartitionKeys[] = emptyArray; + if (data?.assetNodeOrError.__typename === 'AssetNode') { + partitionKeys = data.assetNodeOrError.partitionKeysByDimension; + } + + const allPartitions = React.useMemo(() => { + if (partitionKeys.length === 1) { + return partitionKeys[0]!.partitionKeys; + } else if (partitionKeys.length === 2) { + const firstSet = partitionKeys[0]!.partitionKeys; + const secondSet = partitionKeys[1]!.partitionKeys; + return firstSet.flatMap((key1) => secondSet.map((key2) => `${key1}|${key2}`)); + } else if (partitionKeys.length > 2) { + throw new Error('Only 2 dimensions are supported'); + } + return []; + }, [partitionKeys]); return ( @@ -176,13 +318,136 @@ export const AutomaterializeMiddlePanelWithData = ({ flex={{alignItems: 'center', justifyContent: 'space-between'}} > Result -
{headerRight()}
- + {selectedEvaluation ? ( + + +
+ + Evaluation Result +
{statusTag}
+
+ {selectedEvaluation?.timestamp ? ( + + Timestamp + + + ) : null} + + Duration +
+ {selectedEvaluation?.startTimestamp && selectedEvaluation?.endTimestamp + ? formatElapsedTimeWithMsec( + (selectedEvaluation.endTimestamp - selectedEvaluation.startTimestamp) * + 1000, + ) + : '\u2013'} +
+
+
+
+ + Runs launched ({selectedEvaluation.runIds.length}) + + + + Policy evaluation + + + + { + selectPartition(tags[tags.length - 1] || null); + }} + renderDropdownItem={(tag, props) => } + renderDropdown={(dropdown) => ( + + {dropdown} + + )} + renderTag={(tag, tagProps) => ( + } + label={ +
+ + + + +
+ } + /> + )} + usePortal={false} + /> + + + +
+
+ +
+ ) : null} ); }; + +const FULL_PARTITIONS_QUERY = gql` + query FullPartitionsQuery($assetKey: AssetKeyInput!) { + assetNodeOrError(assetKey: $assetKey) { + ... on AssetNode { + id + partitionKeysByDimension { + name + type + partitionKeys + } + } + } + } +`; +const TagSelectorWrapper = styled.div` + position: relative; + + ${TagSelectorContainer} { + width: 370px; + padding-left: 32px; + height: 36px; + } +`; + +const SearchIconWrapper = styled.div` + position: absolute; + left: 12px; + top: 0px; + bottom: 0px; + pointer-events: none; + display: flex; + align-items: center; +`; diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/AutomaterializeRunsTable.tsx b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/AutomaterializeRunsTable.tsx new file mode 100644 index 0000000000000..23b821e95f51c --- /dev/null +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/AutomaterializeRunsTable.tsx @@ -0,0 +1,111 @@ +import {gql, useQuery} from '@apollo/client'; +import {Body2, Box, Colors, Mono, Table} from '@dagster-io/ui-components'; +import {Link} from 'react-router-dom'; + +import { + AutomaterializeRunsQuery, + AutomaterializeRunsQueryVariables, +} from './types/AutomaterializeRunsTable.types'; +import {PYTHON_ERROR_FRAGMENT} from '../../app/PythonErrorFragment'; +import {PythonErrorInfo} from '../../app/PythonErrorInfo'; +import {RunStatusTagWithStats} from '../../runs/RunStatusTag'; +import {RUN_TIME_FRAGMENT, RunStateSummary, RunTime, titleForRun} from '../../runs/RunUtils'; + +export const AutomaterializeRunsTable = ({runIds}: {runIds: string[]}) => { + const {data, loading, error} = useQuery< + AutomaterializeRunsQuery, + AutomaterializeRunsQueryVariables + >(AUTOMATERIALIZE_RUNS_QUERY, { + variables: { + filter: { + runIds, + }, + }, + skip: !runIds.length, + }); + + if (!runIds.length) { + return ( + + None + + ); + } + + if (error) { + return An error occurred fetching runs. Check your network status; + } + + if (loading || !data) { + return null; + } + + if (data.runsOrError.__typename === 'PythonError') { + return ; + } + + if (data.runsOrError.__typename === 'InvalidPipelineRunsFilterError') { + return {data.runsOrError.message}; + } + + return ( + + + + + + + + + + + + {data.runsOrError.results.map((run) => ( + + + + + + + ))} + +
Run IDCreated dateStatusDuration
+ + {titleForRun(run)} + + + + + + + +
+
+ ); +}; + +const AUTOMATERIALIZE_RUNS_QUERY = gql` + query AutomaterializeRunsQuery($filter: RunsFilter) { + runsOrError(filter: $filter) { + ... on Runs { + results { + id + ...AutomaterializeRunFragment + } + } + ... on InvalidPipelineRunsFilterError { + message + } + ...PythonErrorFragment + } + } + + fragment AutomaterializeRunFragment on Run { + id + runId + ...RunTimeFragment + } + + ${PYTHON_ERROR_FRAGMENT} + ${RUN_TIME_FRAGMENT} +`; diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/GetEvaluationsQuery.tsx b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/GetEvaluationsQuery.tsx index a2ede01f651a4..728f3cfa2d50a 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/GetEvaluationsQuery.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/GetEvaluationsQuery.tsx @@ -1,5 +1,93 @@ import {gql} from '@apollo/client'; +import {METADATA_ENTRY_FRAGMENT} from '../../metadata/MetadataEntry'; + +const AssetSubsetFragment = gql` + fragment AssetSubsetFragment on AssetSubset { + subsetValue { + isPartitioned + partitionKeys + partitionKeyRanges { + start + end + } + } + } +`; + +const SpecificPartitionAssetConditionEvaluationNodeFragment = gql` + fragment SpecificPartitionAssetConditionEvaluationNodeFragment on SpecificPartitionAssetConditionEvaluationNode { + description + status + uniqueId + childUniqueIds + metadataEntries { + ...MetadataEntryFragment + } + } + ${METADATA_ENTRY_FRAGMENT} +`; + +const UnpartitionedAssetConditionEvaluationNodeFragment = gql` + fragment UnpartitionedAssetConditionEvaluationNodeFragment on UnpartitionedAssetConditionEvaluationNode { + description + startTimestamp + endTimestamp + status + uniqueId + childUniqueIds + metadataEntries { + ...MetadataEntryFragment + } + } + ${METADATA_ENTRY_FRAGMENT} +`; +const PartitionedAssetConditionEvaluationNodeFragment = gql` + fragment PartitionedAssetConditionEvaluationNodeFragment on PartitionedAssetConditionEvaluationNode { + description + startTimestamp + endTimestamp + numTrue + numFalse + numSkipped + trueSubset { + ...AssetSubsetFragment + } + candidateSubset { + ...AssetSubsetFragment + } + uniqueId + childUniqueIds + } + ${AssetSubsetFragment} +`; + +const AssetConditionEvaluationRecordFragment = gql` + fragment AssetConditionEvaluationRecordFragment on AssetConditionEvaluationRecord { + id + evaluationId + numRequested + assetKey { + path + } + runIds + timestamp + startTimestamp + endTimestamp + evaluation { + rootUniqueId + evaluationNodes { + ...UnpartitionedAssetConditionEvaluationNodeFragment + ...PartitionedAssetConditionEvaluationNodeFragment + ...SpecificPartitionAssetConditionEvaluationNodeFragment + } + } + } + ${UnpartitionedAssetConditionEvaluationNodeFragment} + ${PartitionedAssetConditionEvaluationNodeFragment} + ${SpecificPartitionAssetConditionEvaluationNodeFragment} +`; + export const GET_EVALUATIONS_QUERY = gql` query GetEvaluationsQuery($assetKey: AssetKeyInput!, $limit: Int!, $cursor: String) { assetNodeOrError(assetKey: $assetKey) { @@ -17,11 +105,11 @@ export const GET_EVALUATIONS_QUERY = gql` } } - autoMaterializeAssetEvaluationsOrError(assetKey: $assetKey, limit: $limit, cursor: $cursor) { - ... on AutoMaterializeAssetEvaluationRecords { + assetConditionEvaluationRecordsOrError(assetKey: $assetKey, limit: $limit, cursor: $cursor) { + ... on AssetConditionEvaluationRecords { records { id - ...AutoMaterializeEvaluationRecordItem + ...AssetConditionEvaluationRecordFragment } } ... on AutoMaterializeAssetEvaluationNeedsMigrationError { @@ -29,58 +117,30 @@ export const GET_EVALUATIONS_QUERY = gql` } } } + ${AssetConditionEvaluationRecordFragment} +`; - fragment AutoMaterializeEvaluationRecordItem on AutoMaterializeAssetEvaluationRecord { - id - evaluationId - numRequested - numSkipped - numDiscarded - timestamp - runIds - rulesWithRuleEvaluations { - ...RuleWithEvaluationsFragment - } - rules { - description - decisionType - className - } - } - - fragment RuleWithEvaluationsFragment on AutoMaterializeRuleWithRuleEvaluations { - rule { - description - decisionType - className - } - ruleEvaluations { - evaluationData { - ... on TextRuleEvaluationData { - text - } - ... on ParentMaterializedRuleEvaluationData { - updatedAssetKeys { - path - } - willUpdateAssetKeys { - path - } - } - ... on WaitingOnKeysRuleEvaluationData { - waitingOnAssetKeys { - path - } - } - } - partitionKeysOrError { - ... on PartitionKeys { - partitionKeys - } - ... on Error { - message - } +export const GET_EVALUATIONS_SPECIFIC_PARTITION_QUERY = gql` + query GetEvaluationsSpecificPartitionQuery( + $assetKey: AssetKeyInput! + $evaluationId: Int! + $partition: String! + ) { + assetConditionEvaluationForPartition( + assetKey: $assetKey + evaluationId: $evaluationId + partition: $partition + ) { + rootUniqueId + evaluationNodes { + ...UnpartitionedAssetConditionEvaluationNodeFragment + ...PartitionedAssetConditionEvaluationNodeFragment + ...SpecificPartitionAssetConditionEvaluationNodeFragment } } } + + ${UnpartitionedAssetConditionEvaluationNodeFragment} + ${PartitionedAssetConditionEvaluationNodeFragment} + ${SpecificPartitionAssetConditionEvaluationNodeFragment} `; diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/PartitionSegmentWithPopover.tsx b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/PartitionSegmentWithPopover.tsx index df7f0a467ffd7..140718f341fec 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/PartitionSegmentWithPopover.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/PartitionSegmentWithPopover.tsx @@ -1,8 +1,11 @@ import { Box, Colors, + Menu, + MenuItem, MiddleTruncate, Popover, + Tag, TextInput, TextInputContainer, } from '@dagster-io/ui-components'; @@ -11,9 +14,10 @@ import {useMemo, useRef, useState} from 'react'; import styled from 'styled-components'; import {PolicyEvaluationStatusTag} from './PolicyEvaluationStatusTag'; -import {AssetConditionEvaluationStatus, AssetSubset} from './types'; import {assertUnreachable} from '../../app/Util'; +import {AssetConditionEvaluationStatus, AssetSubsetValue} from '../../graphql/types'; import {Container, Inner, Row} from '../../ui/VirtualizedTable'; +import {numberFormatter} from '../../ui/formatters'; const statusToColors = (status: AssetConditionEvaluationStatus) => { switch (status) { @@ -28,49 +32,69 @@ const statusToColors = (status: AssetConditionEvaluationStatus) => { } }; +type AssetSusbsetWithoutTypenames = { + subsetValue: Omit; +}; + interface Props { description: string; - status: AssetConditionEvaluationStatus; - subset: AssetSubset | null; - width: number; + status: AssetConditionEvaluationStatus.TRUE; + subset: AssetSusbsetWithoutTypenames | null; + selectPartition: (partitionKey: string | null) => void; } -export const PartitionSegmentWithPopover = ({description, width, status, subset}: Props) => { - const {color, hoverColor} = useMemo(() => statusToColors(status), [status]); - const segment = ; +export const PartitionSegmentWithPopover = ({ + description, + selectPartition, + status, + subset, +}: Props) => { if (!subset) { - return segment; + return null; } + const count = subset.subsetValue.partitionKeys?.length || 0; + return ( - - } - > - {segment} - - + + } + > + 0 ? 'success' : 'none'} icon={count > 0 ? 'check_circle' : undefined}> + {numberFormatter.format(count)} {status.charAt(0) + status.toLowerCase().slice(1)} + + ); }; interface ListProps { description: string; - status: AssetConditionEvaluationStatus; - subset: AssetSubset; + status?: AssetConditionEvaluationStatus; + subset: AssetSusbsetWithoutTypenames; + selectPartition: (partitionKey: string | null) => void; } const ITEM_HEIGHT = 32; const MAX_ITEMS_BEFORE_TRUNCATION = 4; -const PartitionSubsetList = ({description, status, subset}: ListProps) => { +export const PartitionSubsetList = ({description, status, subset, selectPartition}: ListProps) => { const container = useRef(null); const [searchValue, setSearchValue] = useState(''); - const {color, hoverColor} = useMemo(() => statusToColors(status), [status]); + const {color, hoverColor} = useMemo( + () => statusToColors(status ?? AssetConditionEvaluationStatus.TRUE), + [status], + ); const partitionKeys = useMemo(() => subset.subsetValue.partitionKeys || [], [subset]); @@ -97,11 +121,12 @@ const PartitionSubsetList = ({description, status, subset}: ListProps) => { padding={{vertical: 8, left: 12, right: 8}} border="bottom" flex={{direction: 'row', alignItems: 'center', justifyContent: 'space-between'}} + style={{display: 'grid', gridTemplateColumns: 'minmax(0, 1fr) auto', gap: 8}} > - + {status ? : null} {partitionKeys.length > MAX_ITEMS_BEFORE_TRUNCATION ? ( @@ -115,46 +140,41 @@ const PartitionSubsetList = ({description, status, subset}: ListProps) => { ) : null}
MAX_ITEMS_BEFORE_TRUNCATION ? '150px' : count * ITEM_HEIGHT, + height: count > MAX_ITEMS_BEFORE_TRUNCATION ? '150px' : count * ITEM_HEIGHT + 16, overflow: 'hidden', }} > - - {virtualItems.map(({index, key, size, start}) => { - const partitionKey = filteredKeys[index]!; - return ( - - - -
- -
-
-
- ); - })} -
+ + + {virtualItems.map(({index, key, size, start}) => { + const partitionKey = filteredKeys[index]!; + return ( + + { + selectPartition(partitionKey); + }} + text={ + + +
+ +
+
+ } + /> +
+ ); + })} +
+
); }; -const SegmentContainer = styled.div.attrs<{$width: number}>(({$width}) => ({ - style: { - flexBasis: `${$width}px`, - }, -}))<{$width: number}>` - .bp4-popover2-target { - display: block; - } -`; - const SearchContainer = styled(Box)` display: flex; ${TextInputContainer} { @@ -162,27 +182,6 @@ const SearchContainer = styled(Box)` } `; -interface PartitionSegmentProps { - $color: string; - $hoverColor: string; - $width: number; -} - -const PartitionSegment = styled.div.attrs(({$width}) => ({ - style: { - flexBasis: `${$width}px`, - }, -}))` - background-color: ${({$color}) => $color}; - border-radius: 2px; - height: 20px; - transition: background-color 100ms linear; - - :hover { - background-color: ${({$hoverColor}) => $hoverColor}; - } -`; - const PartitionStatusDot = styled.div<{$color: string; $hoverColor: string}>` background-color: ${({$color}) => $color}; height: 8px; diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/PolicyEvaluationCondition.tsx b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/PolicyEvaluationCondition.tsx index 9ba65076d0b31..bd1b90f8cea6c 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/PolicyEvaluationCondition.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/PolicyEvaluationCondition.tsx @@ -10,10 +10,12 @@ interface Props { label: React.ReactNode; type: ConditionType; skipped?: boolean; + isCollapsed: boolean; + hasChildren: boolean; } export const PolicyEvaluationCondition = (props: Props) => { - const {depth, icon, label, type, skipped = false} = props; + const {depth, icon, label, type, skipped = false, isCollapsed, hasChildren} = props; const depthLines = React.useMemo(() => { return new Array(depth).fill(null).map((_, ii) => ); }, [depth]); @@ -25,6 +27,13 @@ export const PolicyEvaluationCondition = (props: Props) => { style={{height: '48px'}} > {depthLines} + + {hasChildren ? ( + + ) : null} {label} diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/PolicyEvaluationStatusTag.tsx b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/PolicyEvaluationStatusTag.tsx index 76c1b70dbfa5e..4e577d2108864 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/PolicyEvaluationStatusTag.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/PolicyEvaluationStatusTag.tsx @@ -1,7 +1,8 @@ import {Tag} from '@dagster-io/ui-components'; +import * as React from 'react'; -import {AssetConditionEvaluationStatus} from './types'; import {assertUnreachable} from '../../app/Util'; +import {AssetConditionEvaluationStatus} from '../../graphql/types'; export const PolicyEvaluationStatusTag = ({status}: {status: AssetConditionEvaluationStatus}) => { switch (status) { diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/PolicyEvaluationTable.tsx b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/PolicyEvaluationTable.tsx index c739a74d2a7d9..f481d386aa5bb 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/PolicyEvaluationTable.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/PolicyEvaluationTable.tsx @@ -1,60 +1,107 @@ -import {Box, Colors, Table} from '@dagster-io/ui-components'; -import {useMemo, useState} from 'react'; +import {Box, Button, Colors, Dialog, Icon, Table, Tooltip} from '@dagster-io/ui-components'; +import * as React from 'react'; import styled, {css} from 'styled-components'; import {PartitionSegmentWithPopover} from './PartitionSegmentWithPopover'; import {PolicyEvaluationCondition} from './PolicyEvaluationCondition'; import {PolicyEvaluationStatusTag} from './PolicyEvaluationStatusTag'; -import {flattenEvaluations} from './flattenEvaluations'; +import {FlattenedConditionEvaluation, flattenEvaluations} from './flattenEvaluations'; import { - AssetConditionEvaluation, - AssetConditionEvaluationStatus, - PartitionedAssetConditionEvaluation, - SpecificPartitionAssetConditionEvaluation, - UnpartitionedAssetConditionEvaluation, -} from './types'; -import {assertUnreachable} from '../../app/Util'; + AssetConditionEvaluationRecordFragment, + PartitionedAssetConditionEvaluationNodeFragment, + SpecificPartitionAssetConditionEvaluationNodeFragment, + UnpartitionedAssetConditionEvaluationNodeFragment, +} from './types/GetEvaluationsQuery.types'; +import {AssetConditionEvaluationStatus} from '../../graphql/types'; +import {MetadataEntryFragment} from '../../metadata/types/MetadataEntry.types'; import {TimeElapsed} from '../../runs/TimeElapsed'; +import {AssetEventMetadataEntriesTable} from '../AssetEventMetadataEntriesTable'; +import {AssetViewDefinitionNodeFragment} from '../types/AssetView.types'; -interface Props { - rootEvaluation: T; +interface Props { + evaluationRecord: Pick; + definition?: AssetViewDefinitionNodeFragment | null; + selectPartition: (partitionKey: string | null) => void; } -export const PolicyEvaluationTable = ({ - rootEvaluation, -}: Props) => { - switch (rootEvaluation.__typename) { - case 'UnpartitionedAssetConditionEvaluation': - case 'SpecificPartitionAssetConditionEvaluation': - return ; - case 'PartitionedAssetConditionEvaluation': - return ; - default: - return assertUnreachable(rootEvaluation); +export const PolicyEvaluationTable = ({evaluationRecord, definition, selectPartition}: Props) => { + const [collapsedRecords, setcollapsedRecords] = React.useState>(new Set()); + const flattened = React.useMemo( + () => flattenEvaluations(evaluationRecord, collapsedRecords), + [evaluationRecord, collapsedRecords], + ); + + const toggleCollapsed = React.useCallback((uniqueId: string) => { + setcollapsedRecords((collapsedRecords) => { + const copy = new Set(collapsedRecords); + if (copy.has(uniqueId)) { + copy.delete(uniqueId); + } else { + copy.add(uniqueId); + } + return copy; + }); + }, []); + if (flattened[0]?.evaluation.__typename === 'PartitionedAssetConditionEvaluationNode') { + return ( + [] + } + definition={definition} + selectPartition={selectPartition} + toggleCollapsed={toggleCollapsed} + collapsedRecords={collapsedRecords} + /> + ); } + + return ( + [] + | FlattenedConditionEvaluation[] + } + toggleCollapsed={toggleCollapsed} + collapsedRecords={collapsedRecords} + /> + ); }; const UnpartitionedPolicyEvaluationTable = ({ - rootEvaluation, + flattenedRecords, + collapsedRecords, + toggleCollapsed, }: { - rootEvaluation: UnpartitionedAssetConditionEvaluation | SpecificPartitionAssetConditionEvaluation; + collapsedRecords: Set; + toggleCollapsed: (id: string) => void; + flattenedRecords: + | FlattenedConditionEvaluation[] + | FlattenedConditionEvaluation[]; }) => { - const [hoveredKey, setHoveredKey] = useState(null); - const flattened = useMemo(() => flattenEvaluations(rootEvaluation), [rootEvaluation]); - const showDuration = rootEvaluation.__typename === 'UnpartitionedAssetConditionEvaluation'; + const [hoveredKey, setHoveredKey] = React.useState(null); + const isSpecificPartitionAssetConditionEvaluations = + flattenedRecords[0]?.evaluation.__typename === 'SpecificPartitionAssetConditionEvaluationNode'; + return ( Condition Result - {showDuration ? Duration : null} + {isSpecificPartitionAssetConditionEvaluations ? null : Duration} Details - {flattened.map(({evaluation, id, parentId, depth, type}) => { - const {description, status} = evaluation; + {flattenedRecords.map(({evaluation, id, parentId, depth, type}) => { + const {description, status, uniqueId} = evaluation; + let endTimestamp, startTimestamp; + if ('endTimestamp' in evaluation) { + endTimestamp = evaluation.endTimestamp; + startTimestamp = evaluation.startTimestamp; + } return ( setHoveredKey(id)} onMouseLeave={() => setHoveredKey(null)} + onClick={() => { + toggleCollapsed(uniqueId); + }} > 0} /> - {showDuration ? ( + {startTimestamp && endTimestamp ? ( - {evaluation.__typename === 'UnpartitionedAssetConditionEvaluation' ? ( - - ) : null} + ) : null} - + + {evaluation.metadataEntries?.length ? ( + + ) : null} + ); })} @@ -95,38 +146,65 @@ const UnpartitionedPolicyEvaluationTable = ({ ); }; +const ViewDetailsButton = ({ + evaluation, +}: { + evaluation: {metadataEntries: MetadataEntryFragment[]}; +}) => { + const [showDetails, setShowDetails] = React.useState(false); + return ( + <> + { + setShowDetails(false); + }} + > + + + + + ); +}; + const FULL_SEGMENTS_WIDTH = 200; const PartitionedPolicyEvaluationTable = ({ - rootEvaluation, + flattenedRecords, + selectPartition, + collapsedRecords, + toggleCollapsed, }: { - rootEvaluation: PartitionedAssetConditionEvaluation; + flattenedRecords: FlattenedConditionEvaluation[]; + definition?: AssetViewDefinitionNodeFragment | null; + selectPartition: (partitionKey: string | null) => void; + collapsedRecords: Set; + toggleCollapsed: (id: string) => void; }) => { - const [hoveredKey, setHoveredKey] = useState(null); - const flattened = useMemo(() => flattenEvaluations(rootEvaluation), [rootEvaluation]); + const [hoveredKey, setHoveredKey] = React.useState(null); + return ( Condition + Partitions evaluated Result Duration - {flattened.map(({evaluation, id, parentId, depth, type}) => { - const { - description, - endTimestamp, - startTimestamp, - numTrue, - numFalse, - numSkipped, - trueSubset, - falseSubset, - candidateSubset, - } = evaluation; - const total = numTrue + numFalse + numSkipped; + {flattenedRecords.map(({evaluation, id, parentId, depth, type}) => { + const {description, candidateSubset, endTimestamp, startTimestamp, trueSubset, uniqueId} = + evaluation; + const consideredPartitions = candidateSubset?.subsetValue.partitionKeys?.length; return ( setHoveredKey(id)} onMouseLeave={() => setHoveredKey(null)} + onClick={() => { + toggleCollapsed(uniqueId); + }} > 0} /> + + {consideredPartitions ? ( + consideredPartitions + ) : ( + + All + + + + + )} + - {numTrue > 0 ? ( - - ) : null} - {numFalse > 0 ? ( - - ) : null} - {numSkipped > 0 ? ( - - ) : null} + - + ); @@ -213,6 +290,7 @@ const VeryCompactTable = styled(Table)` type RowHighlightType = 'hovered' | 'highlighted' | 'none'; const EvaluationRow = styled.tr<{$highlight: RowHighlightType}>` + cursor: pointer; background-color: ${({$highlight}) => { switch ($highlight) { case 'hovered': diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/RuleEvaluationOutcomes.tsx b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/RuleEvaluationOutcomes.tsx index 646bfb24a3dd8..3df8f25f37cb3 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/RuleEvaluationOutcomes.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/RuleEvaluationOutcomes.tsx @@ -8,13 +8,13 @@ import {ParentUpdatedLink} from './ParentUpdatedLink'; import {ParentUpdatedPartitionLink} from './ParentUpdatedPartitionLink'; import {WaitingOnAssetKeysLink} from './WaitingOnAssetKeysLink'; import {WaitingOnAssetKeysPartitionLink} from './WaitingOnAssetKeysPartitionLink'; -import {RuleWithEvaluationsFragment} from './types/GetEvaluationsQuery.types'; import {assertUnreachable} from '../../app/Util'; import { AutoMaterializeDecisionType, AutoMaterializeRule, AutoMaterializeRuleEvaluation, } from '../../graphql/types'; +import {RuleWithEvaluationsFragment} from '../AutoMaterializePolicyPageOld/types/GetEvaluationsQuery.types'; interface RuleEvaluationOutcomeProps { text: string; diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/__fixtures__/AutoMaterializePolicyPage.fixtures.ts b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/__fixtures__/AutoMaterializePolicyPage.fixtures.ts index 1a8f82acd7a11..af636674f8688 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/__fixtures__/AutoMaterializePolicyPage.fixtures.ts +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/__fixtures__/AutoMaterializePolicyPage.fixtures.ts @@ -3,26 +3,21 @@ import {DocumentNode} from 'graphql'; import { AutoMaterializeDecisionType, - AutoMaterializePolicyType, + buildAssetConditionEvaluation, + buildAssetConditionEvaluationRecord, + buildAssetConditionEvaluationRecords, buildAssetKey, buildAssetNode, - buildAutoMaterializeAssetEvaluationNeedsMigrationError, buildAutoMaterializeAssetEvaluationRecord, - buildAutoMaterializeAssetEvaluationRecords, buildAutoMaterializePolicy, buildAutoMaterializeRule, buildAutoMaterializeRuleEvaluation, buildAutoMaterializeRuleWithRuleEvaluations, - buildFreshnessPolicy, buildParentMaterializedRuleEvaluationData, buildPartitionKeys, + buildUnpartitionedAssetConditionEvaluationNode, } from '../../../graphql/types'; -import {GET_POLICY_INFO_QUERY} from '../AutomaterializeRightPanel'; import {GET_EVALUATIONS_QUERY} from '../GetEvaluationsQuery'; -import { - GetPolicyInfoQuery, - GetPolicyInfoQueryVariables, -} from '../types/AutomaterializeRightPanel.types'; import { GetEvaluationsQuery, GetEvaluationsQueryVariables, @@ -69,20 +64,6 @@ export const buildGetEvaluationsQuery = ({ }); }; -export const buildGetPolicyInfoQuery = ({ - variables, - data, -}: { - variables: GetPolicyInfoQueryVariables; - data: Omit; -}): MockedResponse => { - return buildQueryMock({ - query: GET_POLICY_INFO_QUERY, - variables, - data, - }); -}; - const ONE_MINUTE = 1000 * 60; export const TEST_EVALUATION_ID = 27; @@ -90,61 +71,52 @@ export const TEST_EVALUATION_ID = 27; export const buildEvaluationRecordsWithPartitions = () => { const now = Date.now(); return [ - buildAutoMaterializeAssetEvaluationRecord({ - id: 'g', - evaluationId: TEST_EVALUATION_ID, - timestamp: (now - ONE_MINUTE * 6) / 1000, + buildAssetConditionEvaluationRecord({ numRequested: 2, - numSkipped: 2, - numDiscarded: 2, + evaluation: buildAssetConditionEvaluation({ + rootUniqueId: '1', + evaluationNodes: [ + buildUnpartitionedAssetConditionEvaluationNode({ + uniqueId: '1', + }), + ], + }), }), - buildAutoMaterializeAssetEvaluationRecord({ + buildAssetConditionEvaluationRecord({ id: 'f', evaluationId: 24, timestamp: (now - ONE_MINUTE * 5) / 1000, numRequested: 2, - numSkipped: 2, - numDiscarded: 0, }), - buildAutoMaterializeAssetEvaluationRecord({ + buildAssetConditionEvaluationRecord({ id: 'e', evaluationId: 20, timestamp: (now - ONE_MINUTE * 4) / 1000, numRequested: 0, - numSkipped: 2410, - numDiscarded: 3560, }), - buildAutoMaterializeAssetEvaluationRecord({ + buildAssetConditionEvaluationRecord({ id: 'd', evaluationId: 13, timestamp: (now - ONE_MINUTE * 3) / 1000, numRequested: 2, - numSkipped: 0, - numDiscarded: 2, }), - buildAutoMaterializeAssetEvaluationRecord({ + buildAssetConditionEvaluationRecord({ id: 'c', timestamp: (now - ONE_MINUTE * 2) / 1000, evaluationId: 12, numRequested: 0, - numSkipped: 0, - numDiscarded: 2, }), - buildAutoMaterializeAssetEvaluationRecord({ + buildAssetConditionEvaluationRecord({ id: 'b', evaluationId: 4, timestamp: (now - ONE_MINUTE) / 1000, numRequested: 0, - numSkipped: 2, - numDiscarded: 0, }), - buildAutoMaterializeAssetEvaluationRecord({ + buildAssetConditionEvaluationRecord({ id: 'a', evaluationId: 0, timestamp: now / 1000, numRequested: 2, - numSkipped: 0, - numDiscarded: 0, }), ]; }; @@ -152,29 +124,23 @@ export const buildEvaluationRecordsWithPartitions = () => { export const buildEvaluationRecordsWithoutPartitions = () => { const now = Date.now(); return [ - buildAutoMaterializeAssetEvaluationRecord({ + buildAssetConditionEvaluationRecord({ id: 'g', evaluationId: TEST_EVALUATION_ID, timestamp: (now - ONE_MINUTE * 6) / 1000, numRequested: 1, - numSkipped: 0, - numDiscarded: 0, }), - buildAutoMaterializeAssetEvaluationRecord({ + buildAssetConditionEvaluationRecord({ id: 'f', evaluationId: 24, timestamp: (now - ONE_MINUTE * 5) / 1000, numRequested: 0, - numSkipped: 1, - numDiscarded: 0, }), - buildAutoMaterializeAssetEvaluationRecord({ + buildAssetConditionEvaluationRecord({ id: 'e', evaluationId: 20, timestamp: (now - ONE_MINUTE * 4) / 1000, numRequested: 0, - numSkipped: 0, - numDiscarded: 1, }), ]; }; @@ -285,9 +251,7 @@ export const Evaluations = { }), currentAutoMaterializeEvaluationId: 1000, }), - autoMaterializeAssetEvaluationsOrError: buildAutoMaterializeAssetEvaluationRecords({ - records: [], - }), + assetConditionEvaluationRecordsOrError: buildAssetConditionEvaluationRecords(), }, }); }, @@ -304,10 +268,7 @@ export const Evaluations = { rules: BASE_AUTOMATERIALIZE_RULES, }), }), - autoMaterializeAssetEvaluationsOrError: - buildAutoMaterializeAssetEvaluationNeedsMigrationError({ - message: 'Test message', - }), + assetConditionEvaluationRecordsOrError: buildAssetConditionEvaluationRecords(), }, }); }, @@ -324,9 +285,7 @@ export const Evaluations = { rules: [...BASE_AUTOMATERIALIZE_RULES, DISCARD_RULE], }), }), - autoMaterializeAssetEvaluationsOrError: buildAutoMaterializeAssetEvaluationRecords({ - records: assetKeyPath ? [SINGLE_MATERIALIZE_RECORD_NO_PARTITIONS] : [], - }), + assetConditionEvaluationRecordsOrError: buildAssetConditionEvaluationRecords(), }, }); }, @@ -343,9 +302,7 @@ export const Evaluations = { rules: [...BASE_AUTOMATERIALIZE_RULES, DISCARD_RULE], }), }), - autoMaterializeAssetEvaluationsOrError: buildAutoMaterializeAssetEvaluationRecords({ - records: assetKeyPath ? [SINGLE_MATERIALIZE_RECORD_WITH_PARTITIONS] : [], - }), + assetConditionEvaluationRecordsOrError: buildAssetConditionEvaluationRecords(), }, }); }, @@ -362,74 +319,7 @@ export const Evaluations = { rules: [...BASE_AUTOMATERIALIZE_RULES, DISCARD_RULE], }), }), - autoMaterializeAssetEvaluationsOrError: buildAutoMaterializeAssetEvaluationRecords({ - records: buildEvaluationRecordsWithPartitions(), - }), - }, - }); - }, -}; - -export const Policies = { - YesAutomaterializeNoFreshnessPolicy: ( - assetKeyPath: string[], - policyType: AutoMaterializePolicyType = AutoMaterializePolicyType.EAGER, - ) => { - return buildGetPolicyInfoQuery({ - variables: { - assetKey: {path: assetKeyPath}, - }, - data: { - assetNodeOrError: buildAssetNode({ - freshnessPolicy: null, - autoMaterializePolicy: buildAutoMaterializePolicy({ - policyType, - }), - }), - }, - }); - }, - YesAutomaterializeYesFreshnessPolicy: ( - assetKeyPath: string[], - policyType: AutoMaterializePolicyType = AutoMaterializePolicyType.EAGER, - ) => { - return buildGetPolicyInfoQuery({ - variables: { - assetKey: {path: assetKeyPath}, - }, - data: { - assetNodeOrError: buildAssetNode({ - freshnessPolicy: buildFreshnessPolicy({}), - autoMaterializePolicy: buildAutoMaterializePolicy({ - policyType, - }), - }), - }, - }); - }, - NoAutomaterializeYesFreshnessPolicy: (assetKeyPath: string[]) => { - return buildGetPolicyInfoQuery({ - variables: { - assetKey: {path: assetKeyPath}, - }, - data: { - assetNodeOrError: buildAssetNode({ - freshnessPolicy: buildFreshnessPolicy(), - autoMaterializePolicy: null, - }), - }, - }); - }, - NoAutomaterializeNoFreshnessPolicy: (assetKeyPath: string[]) => { - return buildGetPolicyInfoQuery({ - variables: { - assetKey: {path: assetKeyPath}, - }, - data: { - assetNodeOrError: buildAssetNode({ - freshnessPolicy: null, - autoMaterializePolicy: null, - }), + assetConditionEvaluationRecordsOrError: buildAssetConditionEvaluationRecords(), }, }); }, diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/__fixtures__/AutomaterializeRequestedPartitionsLink.fixtures.ts b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/__fixtures__/AutomaterializeRequestedPartitionsLink.fixtures.ts deleted file mode 100644 index bdb09ec9d1ef8..0000000000000 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/__fixtures__/AutomaterializeRequestedPartitionsLink.fixtures.ts +++ /dev/null @@ -1,51 +0,0 @@ -import {MockedResponse} from '@apollo/client/testing'; -import faker from 'faker'; - -import {RunStatus, buildPipelineTag, buildRun, buildRuns} from '../../../graphql/types'; -import {DagsterTag} from '../../../runs/RunTag'; -import {RUN_STATUS_AND_PARTITION_KEY} from '../AutomaterializeRequestedPartitionsLink'; -import { - RunStatusAndPartitionKeyQuery, - RunStatusAndPartitionKeyQueryVariables, -} from '../types/AutomaterializeRequestedPartitionsLink.types'; - -const MOCKED_STATUSES = [ - RunStatus.CANCELED, - RunStatus.FAILURE, - RunStatus.STARTED, - RunStatus.SUCCESS, - RunStatus.QUEUED, -]; - -const pickStatus = () => { - const random = faker.datatype.number(MOCKED_STATUSES.length - 1); - return MOCKED_STATUSES[random]!; -}; - -export const buildRunStatusAndPartitionKeyQuery = ( - partitionKeys: string[], - runIds: string[], -): MockedResponse => { - return { - request: { - query: RUN_STATUS_AND_PARTITION_KEY, - variables: { - filter: {runIds}, - }, - }, - result: { - data: { - __typename: 'Query', - runsOrError: buildRuns({ - results: runIds.map((runId, ii) => { - return buildRun({ - id: runId, - status: pickStatus(), - tags: [buildPipelineTag({key: DagsterTag.Partition, value: partitionKeys[ii]!})], - }); - }), - }), - }, - }, - }; -}; diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/__fixtures__/RunStatusOnlyQuery.fixtures.ts b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/__fixtures__/RunStatusOnlyQuery.fixtures.ts deleted file mode 100644 index 2b62d5670f899..0000000000000 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/__fixtures__/RunStatusOnlyQuery.fixtures.ts +++ /dev/null @@ -1,29 +0,0 @@ -import {MockedResponse} from '@apollo/client/testing'; - -import {RunStatus, buildRun} from '../../../graphql/types'; -import {RUN_STATUS_ONLY} from '../AutomaterializeRunTag'; -import { - RunStatusOnlyQuery, - RunStatusOnlyQueryVariables, -} from '../types/AutomaterializeRunTag.types'; - -export const buildRunStatusOnlyQuery = ( - runId: string, - status: RunStatus, -): MockedResponse => { - return { - request: { - query: RUN_STATUS_ONLY, - variables: {runId}, - }, - result: { - data: { - __typename: 'Query', - runOrError: buildRun({ - id: runId, - status, - }), - }, - }, - }; -}; diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/__stories__/AutoMaterializePolicyPage.stories.tsx b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/__stories__/AutoMaterializePolicyPage.stories.tsx index a48e71ab31015..580fa172e3171 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/__stories__/AutoMaterializePolicyPage.stories.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/__stories__/AutoMaterializePolicyPage.stories.tsx @@ -1,10 +1,10 @@ import {MockedProvider} from '@apollo/client/testing'; import {Box, ButtonGroup, Checkbox, JoinedButtons} from '@dagster-io/ui-components'; -import {useMemo, useState} from 'react'; +import {useState} from 'react'; import {AutoMaterializePolicyType} from '../../../graphql/types'; import {AssetAutomaterializePolicyPage} from '../AssetAutomaterializePolicyPage'; -import {Evaluations, Policies} from '../__fixtures__/AutoMaterializePolicyPage.fixtures'; +import {Evaluations} from '../__fixtures__/AutoMaterializePolicyPage.fixtures'; // eslint-disable-next-line import/no-default-export export default { @@ -16,24 +16,16 @@ const path = ['test']; export const EmptyState = () => { return ( - - + + ); }; export const Errors = () => { return ( - - + + ); }; @@ -42,23 +34,10 @@ export const Controlled = () => { const [policyType, setPolicyType] = useState(AutoMaterializePolicyType.EAGER); const [freshnessPolicy, setFreshnessPolicy] = useState(true); - const policyMock = useMemo(() => { - if (policyType === 'None') { - return freshnessPolicy - ? Policies.NoAutomaterializeYesFreshnessPolicy(path) - : Policies.NoAutomaterializeNoFreshnessPolicy(path); - } else { - return freshnessPolicy - ? Policies.YesAutomaterializeYesFreshnessPolicy(path, policyType) - : Policies.NoAutomaterializeYesFreshnessPolicy(path); - } - }, [freshnessPolicy, policyType]); - return ( -
+
{ /> - +
diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/__stories__/AutomaterializeLeftList.stories.tsx b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/__stories__/AutomaterializeLeftList.stories.tsx index d83214ff96982..e8199f2820e9b 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/__stories__/AutomaterializeLeftList.stories.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/__stories__/AutomaterializeLeftList.stories.tsx @@ -5,7 +5,7 @@ import { buildEvaluationRecordsWithPartitions, buildEvaluationRecordsWithoutPartitions, } from '../__fixtures__/AutoMaterializePolicyPage.fixtures'; -import {AutoMaterializeEvaluationRecordItemFragment} from '../types/GetEvaluationsQuery.types'; +import {AssetConditionEvaluationRecordFragment} from '../types/GetEvaluationsQuery.types'; // eslint-disable-next-line import/no-default-export export default { @@ -15,7 +15,7 @@ export default { export const WithPartitions = () => { const [selectedEvaluation, setSelectedEvaluation] = useState< - AutoMaterializeEvaluationRecordItemFragment | undefined + AssetConditionEvaluationRecordFragment | undefined >(); const evaluations = buildEvaluationRecordsWithPartitions(); @@ -23,9 +23,8 @@ export const WithPartitions = () => { return (
+ evaluations={evaluations as any} + onSelectEvaluation={(evaluation: AssetConditionEvaluationRecordFragment) => setSelectedEvaluation(evaluation) } selectedEvaluation={selectedEvaluation} @@ -36,7 +35,7 @@ export const WithPartitions = () => { export const NoPartitions = () => { const [selectedEvaluation, setSelectedEvaluation] = useState< - AutoMaterializeEvaluationRecordItemFragment | undefined + AssetConditionEvaluationRecordFragment | undefined >(); const evaluations = buildEvaluationRecordsWithoutPartitions(); @@ -44,9 +43,8 @@ export const NoPartitions = () => { return (
+ evaluations={evaluations as any} + onSelectEvaluation={(evaluation: AssetConditionEvaluationRecordFragment) => setSelectedEvaluation(evaluation) } selectedEvaluation={selectedEvaluation} diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/__stories__/AutomaterializeMiddlePanel.stories.tsx b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/__stories__/AutomaterializeMiddlePanel.stories.tsx index d31705907620b..d0727ecc00d7d 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/__stories__/AutomaterializeMiddlePanel.stories.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/__stories__/AutomaterializeMiddlePanel.stories.tsx @@ -1,12 +1,18 @@ import {MockedProvider} from '@apollo/client/testing'; -import {RunStatus} from '../../../graphql/types'; +import { + buildAssetConditionEvaluation, + buildAssetConditionEvaluationRecord, + buildAssetNode, + buildDimensionPartitionKeys, + buildPartitionedAssetConditionEvaluationNode, + buildUnpartitionedAssetConditionEvaluationNode, +} from '../../../graphql/types'; import { AutomaterializeMiddlePanel, AutomaterializeMiddlePanelWithData, } from '../AutomaterializeMiddlePanel'; import {Evaluations, TEST_EVALUATION_ID} from '../__fixtures__/AutoMaterializePolicyPage.fixtures'; -import {buildRunStatusOnlyQuery} from '../__fixtures__/RunStatusOnlyQuery.fixtures'; // eslint-disable-next-line import/no-default-export export default { @@ -18,15 +24,9 @@ const path = ['test']; export const Empty = () => { return ( - +
- +
); @@ -34,16 +34,31 @@ export const Empty = () => { export const WithoutPartitions = () => { return ( - +
@@ -53,16 +68,31 @@ export const WithoutPartitions = () => { export const WithPartitions = () => { return ( - +
diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/__stories__/AutomaterializeRequestedPartitionsLink.stories.tsx b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/__stories__/AutomaterializeRequestedPartitionsLink.stories.tsx deleted file mode 100644 index 39bd812a5edd5..0000000000000 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/__stories__/AutomaterializeRequestedPartitionsLink.stories.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import {MockedProvider} from '@apollo/client/testing'; -import faker from 'faker'; - -import {AutomaterializeRequestedPartitionsLink} from '../AutomaterializeRequestedPartitionsLink'; -import {buildRunStatusAndPartitionKeyQuery} from '../__fixtures__/AutomaterializeRequestedPartitionsLink.fixtures'; - -// eslint-disable-next-line import/no-default-export -export default { - title: 'Asset Details/Automaterialize/AutomaterializeRequestedPartitionsLink', - component: AutomaterializeRequestedPartitionsLink, -}; - -export const ManyPartitionsAndRuns = () => { - const partitionKeys = new Array(40).fill(null).map((_) => faker.lorem.words(3)); - const runIds = new Array(40).fill(null).map((_) => faker.datatype.uuid()); - return ( - - - - ); -}; - -export const OnlyPartitions = () => { - const partitionKeys = new Array(40).fill(null).map((_) => faker.lorem.words(3)); - return ; -}; diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/__stories__/PartitionSegmentWithPopover.stories.tsx b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/__stories__/PartitionSegmentWithPopover.stories.tsx index b56f9d99b45b1..373c0b96cb068 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/__stories__/PartitionSegmentWithPopover.stories.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/__stories__/PartitionSegmentWithPopover.stories.tsx @@ -2,8 +2,8 @@ import {Box} from '@dagster-io/ui-components'; import faker from 'faker'; import {useMemo} from 'react'; +import {AssetConditionEvaluationStatus} from '../../../graphql/types'; import {PartitionSegmentWithPopover} from '../PartitionSegmentWithPopover'; -import {AssetConditionEvaluationStatus, AssetSubset} from '../types'; // eslint-disable-next-line import/no-default-export export default { @@ -14,7 +14,7 @@ export default { const PARTITION_COUNT = 300; export const TruePartitions = () => { - const subset: AssetSubset = useMemo(() => { + const subset = useMemo(() => { const partitionKeys = new Array(PARTITION_COUNT) .fill(null) .map(() => faker.random.words(2).toLowerCase().replace(/ /g, '-')); @@ -34,71 +34,15 @@ export const TruePartitions = () => { - - ); -}; - -export const FalsePartitions = () => { - const subset: AssetSubset = useMemo(() => { - const partitionKeys = new Array(PARTITION_COUNT) - .fill(null) - .map(() => faker.random.words(2).toLowerCase().replace(/ /g, '-')); - return { - assetKey: {path: ['foo', 'bar']}, - subsetValue: { - boolValue: false, - partitionKeys, - partitionKeyRanges: null, - isPartitioned: true, - }, - }; - }, []); - - return ( - - - - ); -}; - -export const SkippedPartitions = () => { - const subset: AssetSubset = useMemo(() => { - const partitionKeys = new Array(PARTITION_COUNT) - .fill(null) - .map(() => faker.random.words(2).toLowerCase().replace(/ /g, '-')); - return { - assetKey: {path: ['foo', 'bar']}, - subsetValue: { - boolValue: null, - partitionKeys, - partitionKeyRanges: null, - isPartitioned: true, - }, - }; - }, []); - - return ( - - {}} /> ); }; export const FewPartitions = () => { - const subset: AssetSubset = useMemo(() => { + const subset = useMemo(() => { const partitionKeys = new Array(2) .fill(null) .map(() => faker.random.words(2).toLowerCase().replace(/ /g, '-')); @@ -118,8 +62,8 @@ export const FewPartitions = () => { {}} /> ); diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/__stories__/PolicyEvaluationCondition.stories.tsx b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/__stories__/PolicyEvaluationCondition.stories.tsx index 544c314e508ba..c0a824a896a89 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/__stories__/PolicyEvaluationCondition.stories.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/__stories__/PolicyEvaluationCondition.stories.tsx @@ -19,6 +19,8 @@ export const Default = () => { icon="resource" label="All are true:" type="group" + isCollapsed={false} + hasChildren /> @@ -29,6 +31,8 @@ export const Default = () => { icon="resource" label="Any are true:" type="group" + isCollapsed={false} + hasChildren /> @@ -39,6 +43,8 @@ export const Default = () => { icon="wysiwyg" label="parent_updated" type="leaf" + isCollapsed={false} + hasChildren={false} /> @@ -50,12 +56,21 @@ export const Default = () => { label="is_missing" type="leaf" skipped + isCollapsed={false} + hasChildren={false} /> - + @@ -65,6 +80,8 @@ export const Default = () => { icon="wysiwyg" label="parent_updated" type="leaf" + isCollapsed={false} + hasChildren={false} /> diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/__stories__/PolicyEvaluationTable.stories.tsx b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/__stories__/PolicyEvaluationTable.stories.tsx index 81f3b688a2150..b25f1b6931876 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/__stories__/PolicyEvaluationTable.stories.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/__stories__/PolicyEvaluationTable.stories.tsx @@ -1,10 +1,5 @@ +import {buildAssetConditionEvaluationRecord} from '../../../graphql/types'; import {PolicyEvaluationTable} from '../PolicyEvaluationTable'; -import { - AssetConditionEvaluationStatus, - PartitionedAssetConditionEvaluation, - SpecificPartitionAssetConditionEvaluation, - UnpartitionedAssetConditionEvaluation, -} from '../types'; // eslint-disable-next-line import/no-default-export export default { @@ -13,416 +8,28 @@ export default { }; export const NonPartitioned = () => { - const evaluation: UnpartitionedAssetConditionEvaluation = { - __typename: 'UnpartitionedAssetConditionEvaluation' as const, - description: 'All are true:', + const evaluation = buildAssetConditionEvaluationRecord({ startTimestamp: 1, endTimestamp: 200, - status: AssetConditionEvaluationStatus.TRUE, - childEvaluations: [ - { - __typename: 'UnpartitionedAssetConditionEvaluation' as const, - description: 'Any are true:', - startTimestamp: 1, - endTimestamp: 4, - status: AssetConditionEvaluationStatus.TRUE, - childEvaluations: [ - { - __typename: 'UnpartitionedAssetConditionEvaluation' as const, - description: 'parent_updated', - startTimestamp: 1, - endTimestamp: 2, - // metadataEntries: [MetadataEntry!]! - status: AssetConditionEvaluationStatus.TRUE, - childEvaluations: null, - }, - { - __typename: 'UnpartitionedAssetConditionEvaluation' as const, - description: 'is_missing', - startTimestamp: 1, - endTimestamp: 2, - // metadataEntries: [MetadataEntry!]! - status: AssetConditionEvaluationStatus.SKIPPED, - childEvaluations: null, - }, - ], - }, - { - __typename: 'UnpartitionedAssetConditionEvaluation' as const, - description: 'Not:', - startTimestamp: 6, - endTimestamp: 12, - status: AssetConditionEvaluationStatus.TRUE, - childEvaluations: [ - { - __typename: 'UnpartitionedAssetConditionEvaluation' as const, - description: 'parent_updated', - startTimestamp: 6, - endTimestamp: 12, - // metadataEntries: [MetadataEntry!]! - status: AssetConditionEvaluationStatus.FALSE, - childEvaluations: null, - }, - ], - }, - { - __typename: 'UnpartitionedAssetConditionEvaluation' as const, - description: 'all_parents_up_to_date', - startTimestamp: 12, - endTimestamp: 14, - status: AssetConditionEvaluationStatus.TRUE, - childEvaluations: null, - }, - { - __typename: 'UnpartitionedAssetConditionEvaluation' as const, - description: 'not_any_parent_missing', - startTimestamp: 14, - endTimestamp: 28, - status: AssetConditionEvaluationStatus.TRUE, - childEvaluations: null, - }, - ], - }; + }); - return ; + return {}} />; }; export const Partitioned = () => { - const evaluation: PartitionedAssetConditionEvaluation = { - __typename: 'PartitionedAssetConditionEvaluation' as const, - description: 'All are true:', + const evaluation = buildAssetConditionEvaluationRecord({ startTimestamp: 1, endTimestamp: 200, - numTrue: 0, - numFalse: 100, - numSkipped: 0, - trueSubset: { - assetKey: {path: ['foo']}, - subsetValue: { - boolValue: true, - partitionKeys: [], - partitionKeyRanges: null, - isPartitioned: true, - }, - }, - falseSubset: { - assetKey: {path: ['foo']}, - subsetValue: { - boolValue: false, - partitionKeys: new Array(100).fill(null).map((_, ii) => `false-${ii}`), - partitionKeyRanges: null, - isPartitioned: true, - }, - }, - candidateSubset: null, - childEvaluations: [ - { - __typename: 'PartitionedAssetConditionEvaluation' as const, - description: 'Any are true:', - startTimestamp: 1, - endTimestamp: 4, - numTrue: 30, - numFalse: 70, - numSkipped: 0, - trueSubset: { - assetKey: {path: ['foo']}, - subsetValue: { - boolValue: true, - partitionKeys: new Array(30).fill(null).map((_, ii) => `true-${ii}`), - partitionKeyRanges: null, - isPartitioned: true, - }, - }, - falseSubset: { - assetKey: {path: ['foo']}, - subsetValue: { - boolValue: false, - partitionKeys: new Array(70).fill(null).map((_, ii) => `false-${ii}`), - partitionKeyRanges: null, - isPartitioned: true, - }, - }, - candidateSubset: null, - childEvaluations: [ - { - __typename: 'PartitionedAssetConditionEvaluation' as const, - description: 'parent_updated', - startTimestamp: 1, - endTimestamp: 2, - // metadataEntries: [MetadataEntry!]! - numTrue: 30, - numFalse: 20, - numSkipped: 50, - trueSubset: { - assetKey: {path: ['foo']}, - subsetValue: { - boolValue: true, - partitionKeys: new Array(30).fill(null).map((_, ii) => `true-${ii}`), - partitionKeyRanges: null, - isPartitioned: true, - }, - }, - falseSubset: { - assetKey: {path: ['foo']}, - subsetValue: { - boolValue: false, - partitionKeys: new Array(20).fill(null).map((_, ii) => `false-${ii}`), - partitionKeyRanges: null, - isPartitioned: true, - }, - }, - candidateSubset: { - assetKey: {path: ['foo']}, - subsetValue: { - boolValue: null, - partitionKeys: new Array(50).fill(null).map((_, ii) => `true-${ii}`), - partitionKeyRanges: null, - isPartitioned: true, - }, - }, - childEvaluations: null, - }, - { - __typename: 'PartitionedAssetConditionEvaluation' as const, - description: 'is_missing', - startTimestamp: 1, - endTimestamp: 2, - // metadataEntries: [MetadataEntry!]! - numTrue: 0, - numFalse: 30, - numSkipped: 70, - trueSubset: { - assetKey: {path: ['foo']}, - subsetValue: { - boolValue: true, - partitionKeys: new Array(30).fill(null).map((_, ii) => `true-${ii}`), - partitionKeyRanges: null, - isPartitioned: true, - }, - }, - falseSubset: { - assetKey: {path: ['foo']}, - subsetValue: { - boolValue: false, - partitionKeys: new Array(30).fill(null).map((_, ii) => `false-${ii}`), - partitionKeyRanges: null, - isPartitioned: true, - }, - }, - candidateSubset: { - assetKey: {path: ['foo']}, - subsetValue: { - boolValue: null, - partitionKeys: new Array(70).fill(null).map((_, ii) => `true-${ii}`), - partitionKeyRanges: null, - isPartitioned: true, - }, - }, - childEvaluations: null, - }, - ], - }, - { - __typename: 'PartitionedAssetConditionEvaluation' as const, - description: 'Not:', - startTimestamp: 6, - endTimestamp: 12, - numTrue: 30, - numFalse: 70, - numSkipped: 0, - trueSubset: { - assetKey: {path: ['foo']}, - subsetValue: { - boolValue: true, - partitionKeys: new Array(30).fill(null).map((_, ii) => `true-${ii}`), - partitionKeyRanges: null, - isPartitioned: true, - }, - }, - falseSubset: { - assetKey: {path: ['foo']}, - subsetValue: { - boolValue: false, - partitionKeys: new Array(70).fill(null).map((_, ii) => `false-${ii}`), - partitionKeyRanges: null, - isPartitioned: true, - }, - }, - candidateSubset: null, - childEvaluations: [ - { - __typename: 'PartitionedAssetConditionEvaluation' as const, - description: 'parent_updated', - startTimestamp: 6, - endTimestamp: 12, - // metadataEntries: [MetadataEntry!]! - numTrue: 80, - numFalse: 20, - numSkipped: 0, - trueSubset: { - assetKey: {path: ['foo']}, - subsetValue: { - boolValue: true, - partitionKeys: new Array(80).fill(null).map((_, ii) => `true-${ii}`), - partitionKeyRanges: null, - isPartitioned: true, - }, - }, - falseSubset: { - assetKey: {path: ['foo']}, - subsetValue: { - boolValue: false, - partitionKeys: new Array(20).fill(null).map((_, ii) => `false-${ii}`), - partitionKeyRanges: null, - isPartitioned: true, - }, - }, - candidateSubset: null, - childEvaluations: null, - }, - ], - }, - { - __typename: 'PartitionedAssetConditionEvaluation' as const, - description: 'all_parents_up_to_date', - startTimestamp: 12, - endTimestamp: 14, - numTrue: 0, - numFalse: 100, - numSkipped: 0, - trueSubset: { - assetKey: {path: ['foo']}, - subsetValue: { - boolValue: true, - partitionKeys: [], - partitionKeyRanges: null, - isPartitioned: true, - }, - }, - falseSubset: { - assetKey: {path: ['foo']}, - subsetValue: { - boolValue: false, - partitionKeys: new Array(100).fill(null).map((_, ii) => `false-${ii}`), - partitionKeyRanges: null, - isPartitioned: true, - }, - }, - candidateSubset: null, - childEvaluations: null, - }, - { - __typename: 'PartitionedAssetConditionEvaluation' as const, - description: 'not_any_parent_missing', - startTimestamp: 14, - endTimestamp: 28, - numTrue: 0, - numFalse: 0, - numSkipped: 100, - trueSubset: { - assetKey: {path: ['foo']}, - subsetValue: { - boolValue: true, - partitionKeys: [], - partitionKeyRanges: null, - isPartitioned: true, - }, - }, - falseSubset: { - assetKey: {path: ['foo']}, - subsetValue: { - boolValue: false, - partitionKeys: [], - partitionKeyRanges: null, - isPartitioned: true, - }, - }, - candidateSubset: { - assetKey: {path: ['foo']}, - subsetValue: { - boolValue: null, - partitionKeys: new Array(100).fill(null).map((_, ii) => `true-${ii}`), - partitionKeyRanges: null, - isPartitioned: true, - }, - }, - childEvaluations: null, - }, - ], - }; + }); - return ; + return {}} />; }; export const SpecificPartition = () => { - const evaluation: SpecificPartitionAssetConditionEvaluation = { - __typename: 'SpecificPartitionAssetConditionEvaluation' as const, - description: 'All are true:', - status: AssetConditionEvaluationStatus.TRUE, - childEvaluations: [ - { - __typename: 'UnpartitionedAssetConditionEvaluation' as const, - description: 'Any are true:', - startTimestamp: 1, - endTimestamp: 4, - status: AssetConditionEvaluationStatus.TRUE, - childEvaluations: [ - { - __typename: 'UnpartitionedAssetConditionEvaluation' as const, - description: 'parent_updated', - startTimestamp: 1, - endTimestamp: 2, - // metadataEntries: [MetadataEntry!]! - status: AssetConditionEvaluationStatus.TRUE, - childEvaluations: null, - }, - { - __typename: 'UnpartitionedAssetConditionEvaluation' as const, - description: 'is_missing', - startTimestamp: 1, - endTimestamp: 2, - // metadataEntries: [MetadataEntry!]! - status: AssetConditionEvaluationStatus.SKIPPED, - childEvaluations: null, - }, - ], - }, - { - __typename: 'UnpartitionedAssetConditionEvaluation' as const, - description: 'Not:', - startTimestamp: 6, - endTimestamp: 12, - status: AssetConditionEvaluationStatus.TRUE, - childEvaluations: [ - { - __typename: 'UnpartitionedAssetConditionEvaluation' as const, - description: 'parent_updated', - startTimestamp: 6, - endTimestamp: 12, - // metadataEntries: [MetadataEntry!]! - status: AssetConditionEvaluationStatus.FALSE, - childEvaluations: null, - }, - ], - }, - { - __typename: 'UnpartitionedAssetConditionEvaluation' as const, - description: 'all_parents_up_to_date', - startTimestamp: 12, - endTimestamp: 14, - status: AssetConditionEvaluationStatus.TRUE, - childEvaluations: null, - }, - { - __typename: 'UnpartitionedAssetConditionEvaluation' as const, - description: 'not_any_parent_missing', - startTimestamp: 14, - endTimestamp: 28, - status: AssetConditionEvaluationStatus.TRUE, - childEvaluations: null, - }, - ], - }; + const evaluation = buildAssetConditionEvaluationRecord({ + startTimestamp: 1, + endTimestamp: 200, + }); - return ; + return {}} />; }; diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/flattenEvaluations.tsx b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/flattenEvaluations.tsx index ce90826910bf1..e491d2c08c7b8 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/flattenEvaluations.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/flattenEvaluations.tsx @@ -1,7 +1,12 @@ import {ConditionType} from './PolicyEvaluationCondition'; -import {AssetConditionEvaluation} from './types'; +import { + AssetConditionEvaluationRecordFragment, + PartitionedAssetConditionEvaluationNodeFragment, + SpecificPartitionAssetConditionEvaluationNodeFragment, + UnpartitionedAssetConditionEvaluationNodeFragment, +} from './types/GetEvaluationsQuery.types'; -type FlattenedConditionEvaluation = { +export type FlattenedConditionEvaluation = { evaluation: T; id: number; parentId: number | null; @@ -9,15 +14,32 @@ type FlattenedConditionEvaluation = { type: ConditionType; }; -export const flattenEvaluations = (rootEvaluation: T) => { - const all: FlattenedConditionEvaluation[] = []; +type Evaluation = + | PartitionedAssetConditionEvaluationNodeFragment + | UnpartitionedAssetConditionEvaluationNodeFragment + | SpecificPartitionAssetConditionEvaluationNodeFragment; + +type FlattenedEvaluation = + | FlattenedConditionEvaluation + | FlattenedConditionEvaluation + | FlattenedConditionEvaluation; + +export const flattenEvaluations = ( + evaluationRecord: Pick, + collapsedRecords: Set, +) => { + const all: FlattenedEvaluation[] = []; let counter = 0; - const append = (evaluation: T, parentId: number | null, depth: number) => { + const recordsById = Object.fromEntries( + evaluationRecord.evaluation.evaluationNodes.map((node) => [node.uniqueId, node]), + ); + + const append = (evaluation: Evaluation, parentId: number | null, depth: number) => { const id = counter + 1; const type = - evaluation.childEvaluations && evaluation.childEvaluations.length > 0 ? 'group' : 'leaf'; + evaluation.childUniqueIds && evaluation.childUniqueIds.length > 0 ? 'group' : 'leaf'; all.push({ evaluation, @@ -25,18 +47,19 @@ export const flattenEvaluations = (rootEvalu parentId: parentId === null ? counter : parentId, depth, type, - } as FlattenedConditionEvaluation); + } as FlattenedEvaluation); counter = id; - if (evaluation.childEvaluations) { + if (evaluation.childUniqueIds && !collapsedRecords.has(evaluation.uniqueId)) { const parentCounter = counter; - evaluation.childEvaluations.forEach((child) => { - append(child as T, parentCounter, depth + 1); + evaluation.childUniqueIds.forEach((childId) => { + const child = recordsById[childId]!; + append(child, parentCounter, depth + 1); }); } }; - append(rootEvaluation, null, 0); + append(recordsById[evaluationRecord.evaluation.rootUniqueId]!, null, 0); return all; }; diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/types.tsx b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/types.tsx index 735a3446227c2..ddffad06859c6 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/types.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/types.tsx @@ -1,5 +1,5 @@ -import {AutoMaterializeEvaluationRecordItemFragment} from './types/GetEvaluationsQuery.types'; import {PartitionKeyRange} from '../../graphql/types'; +import {AutoMaterializeEvaluationRecordItemFragment} from '../AutoMaterializePolicyPageOld/types/GetEvaluationsQuery.types'; import {AssetKey} from '../types'; export type NoConditionsMetEvaluation = { diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/types/AutomaterializeMiddlePanel.types.ts b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/types/AutomaterializeMiddlePanel.types.ts new file mode 100644 index 0000000000000..c87f6f0c76e87 --- /dev/null +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/types/AutomaterializeMiddlePanel.types.ts @@ -0,0 +1,23 @@ +// Generated GraphQL types, do not edit manually. + +import * as Types from '../../../graphql/types'; + +export type FullPartitionsQueryVariables = Types.Exact<{ + assetKey: Types.AssetKeyInput; +}>; + +export type FullPartitionsQuery = { + __typename: 'Query'; + assetNodeOrError: + | { + __typename: 'AssetNode'; + id: string; + partitionKeysByDimension: Array<{ + __typename: 'DimensionPartitionKeys'; + name: string; + type: Types.PartitionDefinitionType; + partitionKeys: Array; + }>; + } + | {__typename: 'AssetNotFoundError'}; +}; diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/types/AutomaterializeRunsTable.types.ts b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/types/AutomaterializeRunsTable.types.ts new file mode 100644 index 0000000000000..d65ee354e0ee9 --- /dev/null +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/types/AutomaterializeRunsTable.types.ts @@ -0,0 +1,45 @@ +// Generated GraphQL types, do not edit manually. + +import * as Types from '../../../graphql/types'; + +export type AutomaterializeRunsQueryVariables = Types.Exact<{ + filter?: Types.InputMaybe; +}>; + +export type AutomaterializeRunsQuery = { + __typename: 'Query'; + runsOrError: + | {__typename: 'InvalidPipelineRunsFilterError'; message: string} + | { + __typename: 'PythonError'; + message: string; + stack: Array; + errorChain: Array<{ + __typename: 'ErrorChainLink'; + isExplicitLink: boolean; + error: {__typename: 'PythonError'; message: string; stack: Array}; + }>; + } + | { + __typename: 'Runs'; + results: Array<{ + __typename: 'Run'; + id: string; + runId: string; + status: Types.RunStatus; + startTime: number | null; + endTime: number | null; + updateTime: number | null; + }>; + }; +}; + +export type AutomaterializeRunFragment = { + __typename: 'Run'; + id: string; + runId: string; + status: Types.RunStatus; + startTime: number | null; + endTime: number | null; + updateTime: number | null; +}; diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/types/GetEvaluationsQuery.types.ts b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/types/GetEvaluationsQuery.types.ts index 5041a1fd939ed..5338ec52624d5 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/types/GetEvaluationsQuery.types.ts +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/types/GetEvaluationsQuery.types.ts @@ -2,6 +2,627 @@ import * as Types from '../../../graphql/types'; +export type AssetSubsetFragment = { + __typename: 'AssetSubset'; + subsetValue: { + __typename: 'AssetSubsetValue'; + isPartitioned: boolean; + partitionKeys: Array | null; + partitionKeyRanges: Array<{__typename: 'PartitionKeyRange'; start: string; end: string}> | null; + }; +}; + +export type SpecificPartitionAssetConditionEvaluationNodeFragment = { + __typename: 'SpecificPartitionAssetConditionEvaluationNode'; + description: string; + status: Types.AssetConditionEvaluationStatus; + uniqueId: string; + childUniqueIds: Array; + metadataEntries: Array< + | { + __typename: 'AssetMetadataEntry'; + label: string; + description: string | null; + assetKey: {__typename: 'AssetKey'; path: Array}; + } + | { + __typename: 'BoolMetadataEntry'; + boolValue: boolean | null; + label: string; + description: string | null; + } + | { + __typename: 'FloatMetadataEntry'; + floatValue: number | null; + label: string; + description: string | null; + } + | { + __typename: 'IntMetadataEntry'; + intValue: number | null; + intRepr: string; + label: string; + description: string | null; + } + | { + __typename: 'JobMetadataEntry'; + jobName: string; + repositoryName: string | null; + locationName: string; + label: string; + description: string | null; + } + | { + __typename: 'JsonMetadataEntry'; + jsonString: string; + label: string; + description: string | null; + } + | { + __typename: 'MarkdownMetadataEntry'; + mdStr: string; + label: string; + description: string | null; + } + | {__typename: 'NotebookMetadataEntry'; path: string; label: string; description: string | null} + | {__typename: 'NullMetadataEntry'; label: string; description: string | null} + | {__typename: 'PathMetadataEntry'; path: string; label: string; description: string | null} + | { + __typename: 'PipelineRunMetadataEntry'; + runId: string; + label: string; + description: string | null; + } + | { + __typename: 'PythonArtifactMetadataEntry'; + module: string; + name: string; + label: string; + description: string | null; + } + | { + __typename: 'TableMetadataEntry'; + label: string; + description: string | null; + table: { + __typename: 'Table'; + records: Array; + schema: { + __typename: 'TableSchema'; + columns: Array<{ + __typename: 'TableColumn'; + name: string; + description: string | null; + type: string; + constraints: { + __typename: 'TableColumnConstraints'; + nullable: boolean; + unique: boolean; + other: Array; + }; + }>; + constraints: {__typename: 'TableConstraints'; other: Array} | null; + }; + }; + } + | { + __typename: 'TableSchemaMetadataEntry'; + label: string; + description: string | null; + schema: { + __typename: 'TableSchema'; + columns: Array<{ + __typename: 'TableColumn'; + name: string; + description: string | null; + type: string; + constraints: { + __typename: 'TableColumnConstraints'; + nullable: boolean; + unique: boolean; + other: Array; + }; + }>; + constraints: {__typename: 'TableConstraints'; other: Array} | null; + }; + } + | {__typename: 'TextMetadataEntry'; text: string; label: string; description: string | null} + | {__typename: 'UrlMetadataEntry'; url: string; label: string; description: string | null} + >; +}; + +export type UnpartitionedAssetConditionEvaluationNodeFragment = { + __typename: 'UnpartitionedAssetConditionEvaluationNode'; + description: string; + startTimestamp: number | null; + endTimestamp: number | null; + status: Types.AssetConditionEvaluationStatus; + uniqueId: string; + childUniqueIds: Array; + metadataEntries: Array< + | { + __typename: 'AssetMetadataEntry'; + label: string; + description: string | null; + assetKey: {__typename: 'AssetKey'; path: Array}; + } + | { + __typename: 'BoolMetadataEntry'; + boolValue: boolean | null; + label: string; + description: string | null; + } + | { + __typename: 'FloatMetadataEntry'; + floatValue: number | null; + label: string; + description: string | null; + } + | { + __typename: 'IntMetadataEntry'; + intValue: number | null; + intRepr: string; + label: string; + description: string | null; + } + | { + __typename: 'JobMetadataEntry'; + jobName: string; + repositoryName: string | null; + locationName: string; + label: string; + description: string | null; + } + | { + __typename: 'JsonMetadataEntry'; + jsonString: string; + label: string; + description: string | null; + } + | { + __typename: 'MarkdownMetadataEntry'; + mdStr: string; + label: string; + description: string | null; + } + | {__typename: 'NotebookMetadataEntry'; path: string; label: string; description: string | null} + | {__typename: 'NullMetadataEntry'; label: string; description: string | null} + | {__typename: 'PathMetadataEntry'; path: string; label: string; description: string | null} + | { + __typename: 'PipelineRunMetadataEntry'; + runId: string; + label: string; + description: string | null; + } + | { + __typename: 'PythonArtifactMetadataEntry'; + module: string; + name: string; + label: string; + description: string | null; + } + | { + __typename: 'TableMetadataEntry'; + label: string; + description: string | null; + table: { + __typename: 'Table'; + records: Array; + schema: { + __typename: 'TableSchema'; + columns: Array<{ + __typename: 'TableColumn'; + name: string; + description: string | null; + type: string; + constraints: { + __typename: 'TableColumnConstraints'; + nullable: boolean; + unique: boolean; + other: Array; + }; + }>; + constraints: {__typename: 'TableConstraints'; other: Array} | null; + }; + }; + } + | { + __typename: 'TableSchemaMetadataEntry'; + label: string; + description: string | null; + schema: { + __typename: 'TableSchema'; + columns: Array<{ + __typename: 'TableColumn'; + name: string; + description: string | null; + type: string; + constraints: { + __typename: 'TableColumnConstraints'; + nullable: boolean; + unique: boolean; + other: Array; + }; + }>; + constraints: {__typename: 'TableConstraints'; other: Array} | null; + }; + } + | {__typename: 'TextMetadataEntry'; text: string; label: string; description: string | null} + | {__typename: 'UrlMetadataEntry'; url: string; label: string; description: string | null} + >; +}; + +export type PartitionedAssetConditionEvaluationNodeFragment = { + __typename: 'PartitionedAssetConditionEvaluationNode'; + description: string; + startTimestamp: number | null; + endTimestamp: number | null; + numTrue: number; + numFalse: number | null; + numSkipped: number | null; + uniqueId: string; + childUniqueIds: Array; + trueSubset: { + __typename: 'AssetSubset'; + subsetValue: { + __typename: 'AssetSubsetValue'; + isPartitioned: boolean; + partitionKeys: Array | null; + partitionKeyRanges: Array<{ + __typename: 'PartitionKeyRange'; + start: string; + end: string; + }> | null; + }; + }; + candidateSubset: { + __typename: 'AssetSubset'; + subsetValue: { + __typename: 'AssetSubsetValue'; + isPartitioned: boolean; + partitionKeys: Array | null; + partitionKeyRanges: Array<{ + __typename: 'PartitionKeyRange'; + start: string; + end: string; + }> | null; + }; + } | null; +}; + +export type AssetConditionEvaluationRecordFragment = { + __typename: 'AssetConditionEvaluationRecord'; + id: string; + evaluationId: number; + numRequested: number; + runIds: Array; + timestamp: number; + startTimestamp: number | null; + endTimestamp: number | null; + assetKey: {__typename: 'AssetKey'; path: Array}; + evaluation: { + __typename: 'AssetConditionEvaluation'; + rootUniqueId: string; + evaluationNodes: Array< + | { + __typename: 'PartitionedAssetConditionEvaluationNode'; + description: string; + startTimestamp: number | null; + endTimestamp: number | null; + numTrue: number; + numFalse: number | null; + numSkipped: number | null; + uniqueId: string; + childUniqueIds: Array; + trueSubset: { + __typename: 'AssetSubset'; + subsetValue: { + __typename: 'AssetSubsetValue'; + isPartitioned: boolean; + partitionKeys: Array | null; + partitionKeyRanges: Array<{ + __typename: 'PartitionKeyRange'; + start: string; + end: string; + }> | null; + }; + }; + candidateSubset: { + __typename: 'AssetSubset'; + subsetValue: { + __typename: 'AssetSubsetValue'; + isPartitioned: boolean; + partitionKeys: Array | null; + partitionKeyRanges: Array<{ + __typename: 'PartitionKeyRange'; + start: string; + end: string; + }> | null; + }; + } | null; + } + | { + __typename: 'SpecificPartitionAssetConditionEvaluationNode'; + description: string; + status: Types.AssetConditionEvaluationStatus; + uniqueId: string; + childUniqueIds: Array; + metadataEntries: Array< + | { + __typename: 'AssetMetadataEntry'; + label: string; + description: string | null; + assetKey: {__typename: 'AssetKey'; path: Array}; + } + | { + __typename: 'BoolMetadataEntry'; + boolValue: boolean | null; + label: string; + description: string | null; + } + | { + __typename: 'FloatMetadataEntry'; + floatValue: number | null; + label: string; + description: string | null; + } + | { + __typename: 'IntMetadataEntry'; + intValue: number | null; + intRepr: string; + label: string; + description: string | null; + } + | { + __typename: 'JobMetadataEntry'; + jobName: string; + repositoryName: string | null; + locationName: string; + label: string; + description: string | null; + } + | { + __typename: 'JsonMetadataEntry'; + jsonString: string; + label: string; + description: string | null; + } + | { + __typename: 'MarkdownMetadataEntry'; + mdStr: string; + label: string; + description: string | null; + } + | { + __typename: 'NotebookMetadataEntry'; + path: string; + label: string; + description: string | null; + } + | {__typename: 'NullMetadataEntry'; label: string; description: string | null} + | { + __typename: 'PathMetadataEntry'; + path: string; + label: string; + description: string | null; + } + | { + __typename: 'PipelineRunMetadataEntry'; + runId: string; + label: string; + description: string | null; + } + | { + __typename: 'PythonArtifactMetadataEntry'; + module: string; + name: string; + label: string; + description: string | null; + } + | { + __typename: 'TableMetadataEntry'; + label: string; + description: string | null; + table: { + __typename: 'Table'; + records: Array; + schema: { + __typename: 'TableSchema'; + columns: Array<{ + __typename: 'TableColumn'; + name: string; + description: string | null; + type: string; + constraints: { + __typename: 'TableColumnConstraints'; + nullable: boolean; + unique: boolean; + other: Array; + }; + }>; + constraints: {__typename: 'TableConstraints'; other: Array} | null; + }; + }; + } + | { + __typename: 'TableSchemaMetadataEntry'; + label: string; + description: string | null; + schema: { + __typename: 'TableSchema'; + columns: Array<{ + __typename: 'TableColumn'; + name: string; + description: string | null; + type: string; + constraints: { + __typename: 'TableColumnConstraints'; + nullable: boolean; + unique: boolean; + other: Array; + }; + }>; + constraints: {__typename: 'TableConstraints'; other: Array} | null; + }; + } + | { + __typename: 'TextMetadataEntry'; + text: string; + label: string; + description: string | null; + } + | { + __typename: 'UrlMetadataEntry'; + url: string; + label: string; + description: string | null; + } + >; + } + | { + __typename: 'UnpartitionedAssetConditionEvaluationNode'; + description: string; + startTimestamp: number | null; + endTimestamp: number | null; + status: Types.AssetConditionEvaluationStatus; + uniqueId: string; + childUniqueIds: Array; + metadataEntries: Array< + | { + __typename: 'AssetMetadataEntry'; + label: string; + description: string | null; + assetKey: {__typename: 'AssetKey'; path: Array}; + } + | { + __typename: 'BoolMetadataEntry'; + boolValue: boolean | null; + label: string; + description: string | null; + } + | { + __typename: 'FloatMetadataEntry'; + floatValue: number | null; + label: string; + description: string | null; + } + | { + __typename: 'IntMetadataEntry'; + intValue: number | null; + intRepr: string; + label: string; + description: string | null; + } + | { + __typename: 'JobMetadataEntry'; + jobName: string; + repositoryName: string | null; + locationName: string; + label: string; + description: string | null; + } + | { + __typename: 'JsonMetadataEntry'; + jsonString: string; + label: string; + description: string | null; + } + | { + __typename: 'MarkdownMetadataEntry'; + mdStr: string; + label: string; + description: string | null; + } + | { + __typename: 'NotebookMetadataEntry'; + path: string; + label: string; + description: string | null; + } + | {__typename: 'NullMetadataEntry'; label: string; description: string | null} + | { + __typename: 'PathMetadataEntry'; + path: string; + label: string; + description: string | null; + } + | { + __typename: 'PipelineRunMetadataEntry'; + runId: string; + label: string; + description: string | null; + } + | { + __typename: 'PythonArtifactMetadataEntry'; + module: string; + name: string; + label: string; + description: string | null; + } + | { + __typename: 'TableMetadataEntry'; + label: string; + description: string | null; + table: { + __typename: 'Table'; + records: Array; + schema: { + __typename: 'TableSchema'; + columns: Array<{ + __typename: 'TableColumn'; + name: string; + description: string | null; + type: string; + constraints: { + __typename: 'TableColumnConstraints'; + nullable: boolean; + unique: boolean; + other: Array; + }; + }>; + constraints: {__typename: 'TableConstraints'; other: Array} | null; + }; + }; + } + | { + __typename: 'TableSchemaMetadataEntry'; + label: string; + description: string | null; + schema: { + __typename: 'TableSchema'; + columns: Array<{ + __typename: 'TableColumn'; + name: string; + description: string | null; + type: string; + constraints: { + __typename: 'TableColumnConstraints'; + nullable: boolean; + unique: boolean; + other: Array; + }; + }>; + constraints: {__typename: 'TableConstraints'; other: Array} | null; + }; + } + | { + __typename: 'TextMetadataEntry'; + text: string; + label: string; + description: string | null; + } + | { + __typename: 'UrlMetadataEntry'; + url: string; + label: string; + description: string | null; + } + >; + } + >; + }; +}; + export type GetEvaluationsQueryVariables = Types.Exact<{ assetKey: Types.AssetKeyInput; limit: Types.Scalars['Int']; @@ -26,131 +647,685 @@ export type GetEvaluationsQuery = { } | null; } | {__typename: 'AssetNotFoundError'}; - autoMaterializeAssetEvaluationsOrError: - | {__typename: 'AutoMaterializeAssetEvaluationNeedsMigrationError'; message: string} + assetConditionEvaluationRecordsOrError: | { - __typename: 'AutoMaterializeAssetEvaluationRecords'; + __typename: 'AssetConditionEvaluationRecords'; records: Array<{ - __typename: 'AutoMaterializeAssetEvaluationRecord'; + __typename: 'AssetConditionEvaluationRecord'; id: string; evaluationId: number; numRequested: number; - numSkipped: number; - numDiscarded: number; - timestamp: number; runIds: Array; - rulesWithRuleEvaluations: Array<{ - __typename: 'AutoMaterializeRuleWithRuleEvaluations'; - rule: { - __typename: 'AutoMaterializeRule'; - description: string; - decisionType: Types.AutoMaterializeDecisionType; - className: string; - }; - ruleEvaluations: Array<{ - __typename: 'AutoMaterializeRuleEvaluation'; - evaluationData: - | { - __typename: 'ParentMaterializedRuleEvaluationData'; - updatedAssetKeys: Array<{__typename: 'AssetKey'; path: Array}> | null; - willUpdateAssetKeys: Array<{ - __typename: 'AssetKey'; - path: Array; - }> | null; - } - | {__typename: 'TextRuleEvaluationData'; text: string | null} - | { - __typename: 'WaitingOnKeysRuleEvaluationData'; - waitingOnAssetKeys: Array<{__typename: 'AssetKey'; path: Array}> | null; - } - | null; - partitionKeysOrError: - | {__typename: 'PartitionKeys'; partitionKeys: Array} - | {__typename: 'PartitionSubsetDeserializationError'; message: string} - | null; - }>; - }>; - rules: Array<{ - __typename: 'AutoMaterializeRule'; - description: string; - decisionType: Types.AutoMaterializeDecisionType; - className: string; - }> | null; + timestamp: number; + startTimestamp: number | null; + endTimestamp: number | null; + assetKey: {__typename: 'AssetKey'; path: Array}; + evaluation: { + __typename: 'AssetConditionEvaluation'; + rootUniqueId: string; + evaluationNodes: Array< + | { + __typename: 'PartitionedAssetConditionEvaluationNode'; + description: string; + startTimestamp: number | null; + endTimestamp: number | null; + numTrue: number; + numFalse: number | null; + numSkipped: number | null; + uniqueId: string; + childUniqueIds: Array; + trueSubset: { + __typename: 'AssetSubset'; + subsetValue: { + __typename: 'AssetSubsetValue'; + isPartitioned: boolean; + partitionKeys: Array | null; + partitionKeyRanges: Array<{ + __typename: 'PartitionKeyRange'; + start: string; + end: string; + }> | null; + }; + }; + candidateSubset: { + __typename: 'AssetSubset'; + subsetValue: { + __typename: 'AssetSubsetValue'; + isPartitioned: boolean; + partitionKeys: Array | null; + partitionKeyRanges: Array<{ + __typename: 'PartitionKeyRange'; + start: string; + end: string; + }> | null; + }; + } | null; + } + | { + __typename: 'SpecificPartitionAssetConditionEvaluationNode'; + description: string; + status: Types.AssetConditionEvaluationStatus; + uniqueId: string; + childUniqueIds: Array; + metadataEntries: Array< + | { + __typename: 'AssetMetadataEntry'; + label: string; + description: string | null; + assetKey: {__typename: 'AssetKey'; path: Array}; + } + | { + __typename: 'BoolMetadataEntry'; + boolValue: boolean | null; + label: string; + description: string | null; + } + | { + __typename: 'FloatMetadataEntry'; + floatValue: number | null; + label: string; + description: string | null; + } + | { + __typename: 'IntMetadataEntry'; + intValue: number | null; + intRepr: string; + label: string; + description: string | null; + } + | { + __typename: 'JobMetadataEntry'; + jobName: string; + repositoryName: string | null; + locationName: string; + label: string; + description: string | null; + } + | { + __typename: 'JsonMetadataEntry'; + jsonString: string; + label: string; + description: string | null; + } + | { + __typename: 'MarkdownMetadataEntry'; + mdStr: string; + label: string; + description: string | null; + } + | { + __typename: 'NotebookMetadataEntry'; + path: string; + label: string; + description: string | null; + } + | {__typename: 'NullMetadataEntry'; label: string; description: string | null} + | { + __typename: 'PathMetadataEntry'; + path: string; + label: string; + description: string | null; + } + | { + __typename: 'PipelineRunMetadataEntry'; + runId: string; + label: string; + description: string | null; + } + | { + __typename: 'PythonArtifactMetadataEntry'; + module: string; + name: string; + label: string; + description: string | null; + } + | { + __typename: 'TableMetadataEntry'; + label: string; + description: string | null; + table: { + __typename: 'Table'; + records: Array; + schema: { + __typename: 'TableSchema'; + columns: Array<{ + __typename: 'TableColumn'; + name: string; + description: string | null; + type: string; + constraints: { + __typename: 'TableColumnConstraints'; + nullable: boolean; + unique: boolean; + other: Array; + }; + }>; + constraints: { + __typename: 'TableConstraints'; + other: Array; + } | null; + }; + }; + } + | { + __typename: 'TableSchemaMetadataEntry'; + label: string; + description: string | null; + schema: { + __typename: 'TableSchema'; + columns: Array<{ + __typename: 'TableColumn'; + name: string; + description: string | null; + type: string; + constraints: { + __typename: 'TableColumnConstraints'; + nullable: boolean; + unique: boolean; + other: Array; + }; + }>; + constraints: { + __typename: 'TableConstraints'; + other: Array; + } | null; + }; + } + | { + __typename: 'TextMetadataEntry'; + text: string; + label: string; + description: string | null; + } + | { + __typename: 'UrlMetadataEntry'; + url: string; + label: string; + description: string | null; + } + >; + } + | { + __typename: 'UnpartitionedAssetConditionEvaluationNode'; + description: string; + startTimestamp: number | null; + endTimestamp: number | null; + status: Types.AssetConditionEvaluationStatus; + uniqueId: string; + childUniqueIds: Array; + metadataEntries: Array< + | { + __typename: 'AssetMetadataEntry'; + label: string; + description: string | null; + assetKey: {__typename: 'AssetKey'; path: Array}; + } + | { + __typename: 'BoolMetadataEntry'; + boolValue: boolean | null; + label: string; + description: string | null; + } + | { + __typename: 'FloatMetadataEntry'; + floatValue: number | null; + label: string; + description: string | null; + } + | { + __typename: 'IntMetadataEntry'; + intValue: number | null; + intRepr: string; + label: string; + description: string | null; + } + | { + __typename: 'JobMetadataEntry'; + jobName: string; + repositoryName: string | null; + locationName: string; + label: string; + description: string | null; + } + | { + __typename: 'JsonMetadataEntry'; + jsonString: string; + label: string; + description: string | null; + } + | { + __typename: 'MarkdownMetadataEntry'; + mdStr: string; + label: string; + description: string | null; + } + | { + __typename: 'NotebookMetadataEntry'; + path: string; + label: string; + description: string | null; + } + | {__typename: 'NullMetadataEntry'; label: string; description: string | null} + | { + __typename: 'PathMetadataEntry'; + path: string; + label: string; + description: string | null; + } + | { + __typename: 'PipelineRunMetadataEntry'; + runId: string; + label: string; + description: string | null; + } + | { + __typename: 'PythonArtifactMetadataEntry'; + module: string; + name: string; + label: string; + description: string | null; + } + | { + __typename: 'TableMetadataEntry'; + label: string; + description: string | null; + table: { + __typename: 'Table'; + records: Array; + schema: { + __typename: 'TableSchema'; + columns: Array<{ + __typename: 'TableColumn'; + name: string; + description: string | null; + type: string; + constraints: { + __typename: 'TableColumnConstraints'; + nullable: boolean; + unique: boolean; + other: Array; + }; + }>; + constraints: { + __typename: 'TableConstraints'; + other: Array; + } | null; + }; + }; + } + | { + __typename: 'TableSchemaMetadataEntry'; + label: string; + description: string | null; + schema: { + __typename: 'TableSchema'; + columns: Array<{ + __typename: 'TableColumn'; + name: string; + description: string | null; + type: string; + constraints: { + __typename: 'TableColumnConstraints'; + nullable: boolean; + unique: boolean; + other: Array; + }; + }>; + constraints: { + __typename: 'TableConstraints'; + other: Array; + } | null; + }; + } + | { + __typename: 'TextMetadataEntry'; + text: string; + label: string; + description: string | null; + } + | { + __typename: 'UrlMetadataEntry'; + url: string; + label: string; + description: string | null; + } + >; + } + >; + }; }>; } + | {__typename: 'AutoMaterializeAssetEvaluationNeedsMigrationError'; message: string} | null; }; -export type AutoMaterializeEvaluationRecordItemFragment = { - __typename: 'AutoMaterializeAssetEvaluationRecord'; - id: string; - evaluationId: number; - numRequested: number; - numSkipped: number; - numDiscarded: number; - timestamp: number; - runIds: Array; - rulesWithRuleEvaluations: Array<{ - __typename: 'AutoMaterializeRuleWithRuleEvaluations'; - rule: { - __typename: 'AutoMaterializeRule'; - description: string; - decisionType: Types.AutoMaterializeDecisionType; - className: string; - }; - ruleEvaluations: Array<{ - __typename: 'AutoMaterializeRuleEvaluation'; - evaluationData: - | { - __typename: 'ParentMaterializedRuleEvaluationData'; - updatedAssetKeys: Array<{__typename: 'AssetKey'; path: Array}> | null; - willUpdateAssetKeys: Array<{__typename: 'AssetKey'; path: Array}> | null; - } - | {__typename: 'TextRuleEvaluationData'; text: string | null} - | { - __typename: 'WaitingOnKeysRuleEvaluationData'; - waitingOnAssetKeys: Array<{__typename: 'AssetKey'; path: Array}> | null; - } - | null; - partitionKeysOrError: - | {__typename: 'PartitionKeys'; partitionKeys: Array} - | {__typename: 'PartitionSubsetDeserializationError'; message: string} - | null; - }>; - }>; - rules: Array<{ - __typename: 'AutoMaterializeRule'; - description: string; - decisionType: Types.AutoMaterializeDecisionType; - className: string; - }> | null; -}; +export type GetEvaluationsSpecificPartitionQueryVariables = Types.Exact<{ + assetKey: Types.AssetKeyInput; + evaluationId: Types.Scalars['Int']; + partition: Types.Scalars['String']; +}>; -export type RuleWithEvaluationsFragment = { - __typename: 'AutoMaterializeRuleWithRuleEvaluations'; - rule: { - __typename: 'AutoMaterializeRule'; - description: string; - decisionType: Types.AutoMaterializeDecisionType; - className: string; - }; - ruleEvaluations: Array<{ - __typename: 'AutoMaterializeRuleEvaluation'; - evaluationData: +export type GetEvaluationsSpecificPartitionQuery = { + __typename: 'Query'; + assetConditionEvaluationForPartition: { + __typename: 'AssetConditionEvaluation'; + rootUniqueId: string; + evaluationNodes: Array< + | { + __typename: 'PartitionedAssetConditionEvaluationNode'; + description: string; + startTimestamp: number | null; + endTimestamp: number | null; + numTrue: number; + numFalse: number | null; + numSkipped: number | null; + uniqueId: string; + childUniqueIds: Array; + trueSubset: { + __typename: 'AssetSubset'; + subsetValue: { + __typename: 'AssetSubsetValue'; + isPartitioned: boolean; + partitionKeys: Array | null; + partitionKeyRanges: Array<{ + __typename: 'PartitionKeyRange'; + start: string; + end: string; + }> | null; + }; + }; + candidateSubset: { + __typename: 'AssetSubset'; + subsetValue: { + __typename: 'AssetSubsetValue'; + isPartitioned: boolean; + partitionKeys: Array | null; + partitionKeyRanges: Array<{ + __typename: 'PartitionKeyRange'; + start: string; + end: string; + }> | null; + }; + } | null; + } | { - __typename: 'ParentMaterializedRuleEvaluationData'; - updatedAssetKeys: Array<{__typename: 'AssetKey'; path: Array}> | null; - willUpdateAssetKeys: Array<{__typename: 'AssetKey'; path: Array}> | null; + __typename: 'SpecificPartitionAssetConditionEvaluationNode'; + description: string; + status: Types.AssetConditionEvaluationStatus; + uniqueId: string; + childUniqueIds: Array; + metadataEntries: Array< + | { + __typename: 'AssetMetadataEntry'; + label: string; + description: string | null; + assetKey: {__typename: 'AssetKey'; path: Array}; + } + | { + __typename: 'BoolMetadataEntry'; + boolValue: boolean | null; + label: string; + description: string | null; + } + | { + __typename: 'FloatMetadataEntry'; + floatValue: number | null; + label: string; + description: string | null; + } + | { + __typename: 'IntMetadataEntry'; + intValue: number | null; + intRepr: string; + label: string; + description: string | null; + } + | { + __typename: 'JobMetadataEntry'; + jobName: string; + repositoryName: string | null; + locationName: string; + label: string; + description: string | null; + } + | { + __typename: 'JsonMetadataEntry'; + jsonString: string; + label: string; + description: string | null; + } + | { + __typename: 'MarkdownMetadataEntry'; + mdStr: string; + label: string; + description: string | null; + } + | { + __typename: 'NotebookMetadataEntry'; + path: string; + label: string; + description: string | null; + } + | {__typename: 'NullMetadataEntry'; label: string; description: string | null} + | { + __typename: 'PathMetadataEntry'; + path: string; + label: string; + description: string | null; + } + | { + __typename: 'PipelineRunMetadataEntry'; + runId: string; + label: string; + description: string | null; + } + | { + __typename: 'PythonArtifactMetadataEntry'; + module: string; + name: string; + label: string; + description: string | null; + } + | { + __typename: 'TableMetadataEntry'; + label: string; + description: string | null; + table: { + __typename: 'Table'; + records: Array; + schema: { + __typename: 'TableSchema'; + columns: Array<{ + __typename: 'TableColumn'; + name: string; + description: string | null; + type: string; + constraints: { + __typename: 'TableColumnConstraints'; + nullable: boolean; + unique: boolean; + other: Array; + }; + }>; + constraints: {__typename: 'TableConstraints'; other: Array} | null; + }; + }; + } + | { + __typename: 'TableSchemaMetadataEntry'; + label: string; + description: string | null; + schema: { + __typename: 'TableSchema'; + columns: Array<{ + __typename: 'TableColumn'; + name: string; + description: string | null; + type: string; + constraints: { + __typename: 'TableColumnConstraints'; + nullable: boolean; + unique: boolean; + other: Array; + }; + }>; + constraints: {__typename: 'TableConstraints'; other: Array} | null; + }; + } + | { + __typename: 'TextMetadataEntry'; + text: string; + label: string; + description: string | null; + } + | { + __typename: 'UrlMetadataEntry'; + url: string; + label: string; + description: string | null; + } + >; } - | {__typename: 'TextRuleEvaluationData'; text: string | null} | { - __typename: 'WaitingOnKeysRuleEvaluationData'; - waitingOnAssetKeys: Array<{__typename: 'AssetKey'; path: Array}> | null; + __typename: 'UnpartitionedAssetConditionEvaluationNode'; + description: string; + startTimestamp: number | null; + endTimestamp: number | null; + status: Types.AssetConditionEvaluationStatus; + uniqueId: string; + childUniqueIds: Array; + metadataEntries: Array< + | { + __typename: 'AssetMetadataEntry'; + label: string; + description: string | null; + assetKey: {__typename: 'AssetKey'; path: Array}; + } + | { + __typename: 'BoolMetadataEntry'; + boolValue: boolean | null; + label: string; + description: string | null; + } + | { + __typename: 'FloatMetadataEntry'; + floatValue: number | null; + label: string; + description: string | null; + } + | { + __typename: 'IntMetadataEntry'; + intValue: number | null; + intRepr: string; + label: string; + description: string | null; + } + | { + __typename: 'JobMetadataEntry'; + jobName: string; + repositoryName: string | null; + locationName: string; + label: string; + description: string | null; + } + | { + __typename: 'JsonMetadataEntry'; + jsonString: string; + label: string; + description: string | null; + } + | { + __typename: 'MarkdownMetadataEntry'; + mdStr: string; + label: string; + description: string | null; + } + | { + __typename: 'NotebookMetadataEntry'; + path: string; + label: string; + description: string | null; + } + | {__typename: 'NullMetadataEntry'; label: string; description: string | null} + | { + __typename: 'PathMetadataEntry'; + path: string; + label: string; + description: string | null; + } + | { + __typename: 'PipelineRunMetadataEntry'; + runId: string; + label: string; + description: string | null; + } + | { + __typename: 'PythonArtifactMetadataEntry'; + module: string; + name: string; + label: string; + description: string | null; + } + | { + __typename: 'TableMetadataEntry'; + label: string; + description: string | null; + table: { + __typename: 'Table'; + records: Array; + schema: { + __typename: 'TableSchema'; + columns: Array<{ + __typename: 'TableColumn'; + name: string; + description: string | null; + type: string; + constraints: { + __typename: 'TableColumnConstraints'; + nullable: boolean; + unique: boolean; + other: Array; + }; + }>; + constraints: {__typename: 'TableConstraints'; other: Array} | null; + }; + }; + } + | { + __typename: 'TableSchemaMetadataEntry'; + label: string; + description: string | null; + schema: { + __typename: 'TableSchema'; + columns: Array<{ + __typename: 'TableColumn'; + name: string; + description: string | null; + type: string; + constraints: { + __typename: 'TableColumnConstraints'; + nullable: boolean; + unique: boolean; + other: Array; + }; + }>; + constraints: {__typename: 'TableConstraints'; other: Array} | null; + }; + } + | { + __typename: 'TextMetadataEntry'; + text: string; + label: string; + description: string | null; + } + | { + __typename: 'UrlMetadataEntry'; + url: string; + label: string; + description: string | null; + } + >; } - | null; - partitionKeysOrError: - | {__typename: 'PartitionKeys'; partitionKeys: Array} - | {__typename: 'PartitionSubsetDeserializationError'; message: string} - | null; - }>; + >; + } | null; }; diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/useEvaluationsQueryResult.tsx b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/useEvaluationsQueryResult.tsx index dad3769bcc5d2..f6d7f70e4a29a 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/useEvaluationsQueryResult.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPage/useEvaluationsQueryResult.tsx @@ -10,10 +10,10 @@ export function useEvaluationsQueryResult({assetKey}: {assetKey: AssetKey}) { return useCursorPaginatedQuery({ nextCursorForResult: (data) => { if ( - data.autoMaterializeAssetEvaluationsOrError?.__typename === - 'AutoMaterializeAssetEvaluationRecords' + data.assetConditionEvaluationRecordsOrError?.__typename === + 'AssetConditionEvaluationRecords' ) { - return data.autoMaterializeAssetEvaluationsOrError.records[ + return data.assetConditionEvaluationRecordsOrError.records[ PAGE_SIZE - 1 ]?.evaluationId.toString(); } @@ -21,10 +21,10 @@ export function useEvaluationsQueryResult({assetKey}: {assetKey: AssetKey}) { }, getResultArray: (data) => { if ( - data?.autoMaterializeAssetEvaluationsOrError?.__typename === - 'AutoMaterializeAssetEvaluationRecords' + data?.assetConditionEvaluationRecordsOrError?.__typename === + 'AssetConditionEvaluationRecords' ) { - return data.autoMaterializeAssetEvaluationsOrError.records; + return data.assetConditionEvaluationRecordsOrError.records; } return []; }, diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPageOld/AssetAutomaterializePolicyPage.tsx b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPageOld/AssetAutomaterializePolicyPage.tsx index 4057761f3149b..b6556c1afe5e6 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPageOld/AssetAutomaterializePolicyPage.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/AutoMaterializePolicyPageOld/AssetAutomaterializePolicyPage.tsx @@ -11,7 +11,7 @@ import {FIFTEEN_SECONDS, useQueryRefreshAtInterval} from '../../app/QueryRefresh import {useQueryPersistedState} from '../../hooks/useQueryPersistedState'; import {AssetKey} from '../types'; -export const AssetAutomaterializePolicyPage = ({ +export const AssetAutomaterializePolicyPageOld = ({ assetKey, assetHasDefinedPartitions, }: { @@ -68,9 +68,7 @@ export const AssetAutomaterializePolicyPage = ({ style={{flex: 1, minHeight: 0, color: Colors.textLight(), overflow: 'hidden'}} flex={{direction: 'column'}} > - - - + ({ - assetKey, - detailType: AssetDetailType.Updated, - })), - ...(willUpdateAssetKeys[partitionName] || []).sort(sortAssetKeys).map((assetKey) => ({ - assetKey, - detailType: AssetDetailType.WillUpdate, - })), + ...(updatedAssetKeys[partitionName] || []) + .slice() + .sort(sortAssetKeys) + .map((assetKey) => ({ + assetKey, + detailType: AssetDetailType.Updated, + })), + ...(willUpdateAssetKeys[partitionName] || []) + .slice() + .sort(sortAssetKeys) + .map((assetKey) => ({ + assetKey, + detailType: AssetDetailType.WillUpdate, + })), ], ]; }), diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/AutomaterializeTagWithEvaluation.tsx b/js_modules/dagster-ui/packages/ui-core/src/assets/AutomaterializeTagWithEvaluation.tsx index be09d3a210237..a6ea56218f47b 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/AutomaterializeTagWithEvaluation.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/AutomaterializeTagWithEvaluation.tsx @@ -32,7 +32,7 @@ export const AutomaterializeTagWithEvaluation = ({assetKeys, evaluationId}: Prop > {sortedKeys.map((assetKey) => { const url = assetDetailsPathForKey(assetKey, { - view: 'auto-materialize-history', + view: 'automation', evaluation: evaluationId, }); return ( diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/__tests__/buildAssetTabs.test.tsx b/js_modules/dagster-ui/packages/ui-core/src/assets/__tests__/buildAssetTabs.test.tsx index 5ea8a4e3f2322..22e9ed65c46c6 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/__tests__/buildAssetTabs.test.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/__tests__/buildAssetTabs.test.tsx @@ -282,7 +282,7 @@ describe('buildAssetTabs', () => { 'plots', 'definition', 'lineage', - 'auto-materialize-history', + 'automation', ]); }); @@ -301,13 +301,7 @@ describe('buildAssetTabs', () => { params, }); const tabKeys = tabList.map(({id}) => id); - expect(tabKeys).toEqual([ - 'events', - 'plots', - 'definition', - 'lineage', - 'auto-materialize-history', - ]); + expect(tabKeys).toEqual(['events', 'plots', 'definition', 'lineage', 'automation']); }); it('hides partitions and auto-materialize tabs if no partitions or auto-materializing', () => { diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/auto-materialization/AutomaterializationTickDetailDialog.tsx b/js_modules/dagster-ui/packages/ui-core/src/assets/auto-materialization/AutomaterializationTickDetailDialog.tsx index 783089f2598ca..e6c57f6a750ba 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/auto-materialization/AutomaterializationTickDetailDialog.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/auto-materialization/AutomaterializationTickDetailDialog.tsx @@ -234,7 +234,7 @@ const AssetDetailRow = ({ diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/types/AssetNodeInstigatorTag.types.ts b/js_modules/dagster-ui/packages/ui-core/src/assets/types/AssetNodeInstigatorTag.types.ts index 65267a926ad83..c0128e7bc110a 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/types/AssetNodeInstigatorTag.types.ts +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/types/AssetNodeInstigatorTag.types.ts @@ -24,6 +24,7 @@ export type AssetNodeInstigatorsFragment = { id: string; jobOriginId: string; name: string; + sensorType: Types.SensorType; sensorState: { __typename: 'InstigationState'; id: string; diff --git a/js_modules/dagster-ui/packages/ui-core/src/assets/types/AssetView.types.ts b/js_modules/dagster-ui/packages/ui-core/src/assets/types/AssetView.types.ts index 1adc8ba6d364c..f962d210f0b1a 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/assets/types/AssetView.types.ts +++ b/js_modules/dagster-ui/packages/ui-core/src/assets/types/AssetView.types.ts @@ -61,6 +61,7 @@ export type AssetViewDefinitionQuery = { id: string; jobOriginId: string; name: string; + sensorType: Types.SensorType; sensorState: { __typename: 'InstigationState'; id: string; @@ -15882,6 +15883,7 @@ export type AssetViewDefinitionNodeFragment = { id: string; jobOriginId: string; name: string; + sensorType: Types.SensorType; sensorState: { __typename: 'InstigationState'; id: string; diff --git a/js_modules/dagster-ui/packages/ui-core/src/nav/types/JobMetadata.types.ts b/js_modules/dagster-ui/packages/ui-core/src/nav/types/JobMetadata.types.ts index b76c09453dbcb..e92382ddcf8e7 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/nav/types/JobMetadata.types.ts +++ b/js_modules/dagster-ui/packages/ui-core/src/nav/types/JobMetadata.types.ts @@ -35,6 +35,7 @@ export type JobMetadataQuery = { id: string; jobOriginId: string; name: string; + sensorType: Types.SensorType; targets: Array<{__typename: 'Target'; pipelineName: string; mode: string}> | null; sensorState: { __typename: 'InstigationState'; @@ -110,6 +111,7 @@ export type JobMetadataFragment = { id: string; jobOriginId: string; name: string; + sensorType: Types.SensorType; targets: Array<{__typename: 'Target'; pipelineName: string; mode: string}> | null; sensorState: { __typename: 'InstigationState'; diff --git a/js_modules/dagster-ui/packages/ui-core/src/overview/OverviewRoot.tsx b/js_modules/dagster-ui/packages/ui-core/src/overview/OverviewRoot.tsx index d558ec65bcc6f..0d51ee5818c03 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/overview/OverviewRoot.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/overview/OverviewRoot.tsx @@ -24,7 +24,7 @@ export const OverviewRoot = () => { - + diff --git a/js_modules/dagster-ui/packages/ui-core/src/overview/OverviewTabs.tsx b/js_modules/dagster-ui/packages/ui-core/src/overview/OverviewTabs.tsx index 5e3dd5cad9ad6..2f0de9c10677c 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/overview/OverviewTabs.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/overview/OverviewTabs.tsx @@ -48,7 +48,7 @@ export const OverviewTabs = >(props: Props } - to="/overview/automaterialize" + to="/overview/automation" /> ) : null} diff --git a/js_modules/dagster-ui/packages/ui-core/src/sensors/SensorSwitch.tsx b/js_modules/dagster-ui/packages/ui-core/src/sensors/SensorSwitch.tsx index 4ca0c5552defb..7c12732cfe555 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/sensors/SensorSwitch.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/sensors/SensorSwitch.tsx @@ -108,5 +108,6 @@ export const SENSOR_SWITCH_FRAGMENT = gql` selectorId status } + sensorType } `; diff --git a/js_modules/dagster-ui/packages/ui-core/src/sensors/types/SensorSwitch.types.ts b/js_modules/dagster-ui/packages/ui-core/src/sensors/types/SensorSwitch.types.ts index 8156160ac3c3d..9e019afae317f 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/sensors/types/SensorSwitch.types.ts +++ b/js_modules/dagster-ui/packages/ui-core/src/sensors/types/SensorSwitch.types.ts @@ -7,6 +7,7 @@ export type SensorSwitchFragment = { id: string; jobOriginId: string; name: string; + sensorType: Types.SensorType; sensorState: { __typename: 'InstigationState'; id: string; diff --git a/js_modules/dagster-ui/packages/ui-core/src/workspace/WorkspaceContext.tsx b/js_modules/dagster-ui/packages/ui-core/src/workspace/WorkspaceContext.tsx index 52ac11c44d3df..cd3a5865e57d9 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/workspace/WorkspaceContext.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/workspace/WorkspaceContext.tsx @@ -170,6 +170,7 @@ export const ROOT_WORKSPACE_QUERY = gql` selectorId status } + sensorType } ${PYTHON_ERROR_FRAGMENT} diff --git a/js_modules/dagster-ui/packages/ui-core/src/workspace/types/VirtualizedJobRow.types.ts b/js_modules/dagster-ui/packages/ui-core/src/workspace/types/VirtualizedJobRow.types.ts index 48ae1c65923d4..c6f1c60ed729b 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/workspace/types/VirtualizedJobRow.types.ts +++ b/js_modules/dagster-ui/packages/ui-core/src/workspace/types/VirtualizedJobRow.types.ts @@ -43,6 +43,7 @@ export type SingleJobQuery = { id: string; jobOriginId: string; name: string; + sensorType: Types.SensorType; sensorState: { __typename: 'InstigationState'; id: string; diff --git a/js_modules/dagster-ui/packages/ui-core/src/workspace/types/VirtualizedSensorRow.types.ts b/js_modules/dagster-ui/packages/ui-core/src/workspace/types/VirtualizedSensorRow.types.ts index 5f893b69e35e5..21689df2e7e16 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/workspace/types/VirtualizedSensorRow.types.ts +++ b/js_modules/dagster-ui/packages/ui-core/src/workspace/types/VirtualizedSensorRow.types.ts @@ -17,6 +17,7 @@ export type SingleSensorQuery = { name: string; minIntervalSeconds: number; jobOriginId: string; + sensorType: Types.SensorType; targets: Array<{__typename: 'Target'; pipelineName: string}> | null; metadata: { __typename: 'SensorMetadata'; diff --git a/js_modules/dagster-ui/packages/ui-core/src/workspace/types/WorkspaceContext.types.ts b/js_modules/dagster-ui/packages/ui-core/src/workspace/types/WorkspaceContext.types.ts index a5d84381f5b59..fc265346ab730 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/workspace/types/WorkspaceContext.types.ts +++ b/js_modules/dagster-ui/packages/ui-core/src/workspace/types/WorkspaceContext.types.ts @@ -82,6 +82,7 @@ export type RootWorkspaceQuery = { id: string; jobOriginId: string; name: string; + sensorType: Types.SensorType; targets: Array<{ __typename: 'Target'; mode: string; @@ -181,6 +182,7 @@ export type WorkspaceLocationNodeFragment = { id: string; jobOriginId: string; name: string; + sensorType: Types.SensorType; targets: Array<{__typename: 'Target'; mode: string; pipelineName: string}> | null; sensorState: { __typename: 'InstigationState'; @@ -257,6 +259,7 @@ export type WorkspaceLocationFragment = { id: string; jobOriginId: string; name: string; + sensorType: Types.SensorType; targets: Array<{__typename: 'Target'; mode: string; pipelineName: string}> | null; sensorState: { __typename: 'InstigationState'; @@ -310,6 +313,7 @@ export type WorkspaceRepositoryFragment = { id: string; jobOriginId: string; name: string; + sensorType: Types.SensorType; targets: Array<{__typename: 'Target'; mode: string; pipelineName: string}> | null; sensorState: { __typename: 'InstigationState'; @@ -351,6 +355,7 @@ export type WorkspaceSensorFragment = { id: string; jobOriginId: string; name: string; + sensorType: Types.SensorType; targets: Array<{__typename: 'Target'; mode: string; pipelineName: string}> | null; sensorState: { __typename: 'InstigationState'; diff --git a/python_modules/dagster-test/dagster_test/toys/auto_materializing/repo_1.py b/python_modules/dagster-test/dagster_test/toys/auto_materializing/repo_1.py index e19079d1dfe18..4e1dbc8e48855 100644 --- a/python_modules/dagster-test/dagster_test/toys/auto_materializing/repo_1.py +++ b/python_modules/dagster-test/dagster_test/toys/auto_materializing/repo_1.py @@ -1,4 +1,11 @@ -from dagster import AutoMaterializePolicy, DailyPartitionsDefinition, asset, repository +from dagster import ( + AutoMaterializePolicy, + DailyPartitionsDefinition, + DynamicPartitionsDefinition, + MultiPartitionsDefinition, + asset, + repository, +) ### Non partitioned ## @@ -42,6 +49,21 @@ def eager_downstream_1_partitioned(eager_upstream_partitioned): return eager_upstream_partitioned + 1 +customers_partitions_def = DynamicPartitionsDefinition(name="customers") +multipartition_w_dynamic_partitions_def = MultiPartitionsDefinition( + {"customers": customers_partitions_def, "daily": DailyPartitionsDefinition("2023-01-01")} +) + + +@asset( + auto_materialize_policy=AutoMaterializePolicy.eager(), + partitions_def=multipartition_w_dynamic_partitions_def, + deps=[eager_downstream_0_point_5_partitioned], +) +def eager_downstream_2_partitioned(eager_upstream_partitioned): + return eager_upstream_partitioned + 1 + + @repository def auto_materialize_repo_1(): return [ @@ -51,4 +73,5 @@ def auto_materialize_repo_1(): eager_upstream_partitioned, eager_downstream_1_partitioned, eager_downstream_0_point_5_partitioned, + eager_downstream_2_partitioned, ]