Skip to content

Commit

Permalink
add manual tick button to rows in automation table
Browse files Browse the repository at this point in the history
  • Loading branch information
dliu27 committed Dec 9, 2024
1 parent 772d0d6 commit 4e845e6
Show file tree
Hide file tree
Showing 6 changed files with 185 additions and 70 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
} from '@dagster-io/ui-components';
import {forwardRef, useMemo} from 'react';
import {Link} from 'react-router-dom';
import styled from 'styled-components';

import {AutomationTargetList} from './AutomationTargetList';
import {AutomationRowGrid} from './VirtualizedAutomationRow';
Expand All @@ -24,6 +25,7 @@ import {
ScheduleAssetSelectionQuery,
ScheduleAssetSelectionQueryVariables,
} from '../schedules/types/ScheduleAssetSelectionsQuery.types';
import {EvaluateTickButtonSchedule} from '../ticks/EvaluateTickButtonSchedule';
import {TickStatusTag} from '../ticks/TickStatusTag';
import {RowCell} from '../ui/VirtualizedTable';
import {SINGLE_SCHEDULE_QUERY} from '../workspace/VirtualizedScheduleRow';
Expand Down Expand Up @@ -138,22 +140,37 @@ export const VirtualizedAutomationScheduleRow = forwardRef(
</Tooltip>
</RowCell>
<RowCell>
<Box flex={{direction: 'row', gap: 8, alignItems: 'flex-start'}}>
{scheduleData ? (
<Box flex={{direction: 'column', gap: 4}}>
{/* Keyed so that a new switch is always rendered, otherwise it's reused and animates on/off */}
<ScheduleSwitch key={name} repoAddress={repoAddress} schedule={scheduleData} />
{errorDisplay(
scheduleData.scheduleState.status,
scheduleData.scheduleState.runningCount,
)}
</Box>
) : (
<div style={{width: 30}} />
)}
<Link to={workspacePathFromAddress(repoAddress, `/schedules/${name}`)}>
<MiddleTruncate text={name} />
</Link>
<Box
flex={{
direction: 'row',
gap: 8,
alignItems: 'flex-start',
justifyContent: 'space-between',
}}
>
<Box flex={{grow: 1, gap: 8}}>
{scheduleData ? (
<>
<ScheduleSwitch key={name} repoAddress={repoAddress} schedule={scheduleData} />
{errorDisplay(
scheduleData.scheduleState.status,
scheduleData.scheduleState.runningCount,
)}
</>
) : (
<div style={{width: 30}} />
)}
<Link to={workspacePathFromAddress(repoAddress, `/schedules/${name}`)}>
<MiddleTruncate text={name} />
</Link>
</Box>
<EvaluateTickButtonScheduleWrapper>
<EvaluateTickButtonSchedule
name={scheduleData?.name || ''}
repoAddress={repoAddress}
jobName={scheduleData?.pipelineName || ''}
/>
</EvaluateTickButtonScheduleWrapper>
</Box>
</RowCell>
<RowCell>
Expand Down Expand Up @@ -225,3 +242,9 @@ export const VirtualizedAutomationScheduleRow = forwardRef(
);
},
);

const EvaluateTickButtonScheduleWrapper = styled.div`
button {
height: 24px;
}
`;
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
} from '@dagster-io/ui-components';
import {forwardRef, useMemo} from 'react';
import {Link} from 'react-router-dom';
import styled from 'styled-components';

import {AutomationTargetList} from './AutomationTargetList';
import {AutomationRowGrid} from './VirtualizedAutomationRow';
Expand All @@ -21,6 +22,7 @@ import {
SensorAssetSelectionQuery,
SensorAssetSelectionQueryVariables,
} from '../sensors/types/SensorRoot.types';
import {EvaluateTickButtonSensor} from '../ticks/EvaluateTickButtonSensor';
import {TickStatusTag} from '../ticks/TickStatusTag';
import {RowCell} from '../ui/VirtualizedTable';
import {SENSOR_TYPE_META, SINGLE_SENSOR_QUERY} from '../workspace/VirtualizedSensorRow';
Expand Down Expand Up @@ -88,6 +90,12 @@ export const VirtualizedAutomationSensorRow = forwardRef(
return data.sensorOrError;
}, [data]);

const cursor =
sensorData &&
sensorData.sensorState.typeSpecificData &&
sensorData.sensorState.typeSpecificData.__typename === 'SensorData' &&
sensorData.sensorState.typeSpecificData.lastCursor;

const onChange = (e: React.FormEvent<HTMLInputElement>) => {
if (onToggleChecked && e.target instanceof HTMLInputElement) {
const {checked} = e.target;
Expand Down Expand Up @@ -136,16 +144,38 @@ export const VirtualizedAutomationSensorRow = forwardRef(
</Tooltip>
</RowCell>
<RowCell>
<Box flex={{direction: 'row', gap: 8, alignItems: 'flex-start'}}>
{/* Keyed so that a new switch is always rendered, otherwise it's reused and animates on/off */}
<Box
flex={{
direction: 'row',
gap: 8,
alignItems: 'flex-start',
justifyContent: 'space-between',
}}
>
<Box flex={{grow: 1, gap: 8}}>
{/* Keyed so that a new switch is always rendered, otherwise it's reused and animates on/off */}
{sensorData ? (
<SensorSwitch key={name} repoAddress={repoAddress} sensor={sensorData} />
) : (
<div style={{width: 30}} />
)}
<Link to={workspacePathFromAddress(repoAddress, `/sensors/${name}`)}>
<MiddleTruncate text={name} />
</Link>
</Box>
{sensorData ? (
<SensorSwitch key={name} repoAddress={repoAddress} sensor={sensorData} />
<EvaluateTickButtonSensorWrapper>
<EvaluateTickButtonSensor
cursor={cursor || ''}
name={sensorData?.name || ''}
repoAddress={repoAddress}
jobName={sensorData?.targets?.[0]?.pipelineName || ''}
sensorType={sensorData.sensorType}
/>
</EvaluateTickButtonSensorWrapper>
) : (
<div style={{width: 30}} />
)}
<Link to={workspacePathFromAddress(repoAddress, `/sensors/${name}`)}>
<MiddleTruncate text={name} />
</Link>
</Box>
</RowCell>
<RowCell>
Expand Down Expand Up @@ -205,3 +235,9 @@ export const VirtualizedAutomationSensorRow = forwardRef(
);
},
);

const EvaluateTickButtonSensorWrapper = styled.div`
button {
height: 24px;
}
`;
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import {
Box,
Button,
Code,
Group,
Heading,
MetadataTableWIP,
PageHeader,
Tag,
} from '@dagster-io/ui-components';
import {useState} from 'react';
import {Link} from 'react-router-dom';
import styled from 'styled-components';

Expand All @@ -23,7 +21,7 @@ import {AutomationTargetList} from '../automation/AutomationTargetList';
import {AutomationAssetSelectionFragment} from '../automation/types/AutomationAssetSelectionFragment.types';
import {InstigationStatus} from '../graphql/types';
import {RepositoryLink} from '../nav/RepositoryLink';
import {EvaluateScheduleDialog} from '../ticks/EvaluateScheduleDialog';
import {EvaluateTickButtonSchedule} from '../ticks/EvaluateTickButtonSchedule';
import {TickStatusTag} from '../ticks/TickStatusTag';
import {RepoAddress} from '../workspace/types';

Expand All @@ -42,8 +40,6 @@ export const ScheduleDetails = (props: {
const latestTick = ticks.length > 0 ? ticks[0] : null;
const running = status === InstigationStatus.RUNNING;

const [showTestTickDialog, setShowTestTickDialog] = useState(false);

return (
<>
<PageHeader
Expand All @@ -62,26 +58,14 @@ export const ScheduleDetails = (props: {
right={
<Box flex={{direction: 'row', alignItems: 'center', gap: 8}}>
<QueryRefreshCountdown refreshState={refreshState} />
<Button
onClick={() => {
setShowTestTickDialog(true);
}}
>
Evaluate tick
</Button>
<EvaluateTickButtonSchedule
name={schedule.name}
repoAddress={repoAddress}
jobName={pipelineName}
/>
</Box>
}
/>
<EvaluateScheduleDialog
key={showTestTickDialog ? '1' : '0'} // change key to reset dialog state
isOpen={showTestTickDialog}
onClose={() => {
setShowTestTickDialog(false);
}}
name={schedule.name}
repoAddress={repoAddress}
jobName={pipelineName}
/>
<MetadataTableWIP>
<tbody>
{schedule.description ? (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {EditCursorDialog} from './EditCursorDialog';
import {SensorMonitoredAssets} from './SensorMonitoredAssets';
import {SensorResetButton} from './SensorResetButton';
import {SensorSwitch} from './SensorSwitch';
import {EvaluateTickButtonSensor} from '../ticks/EvaluateTickButtonSensor';
import {SensorFragment} from './types/SensorFragment.types';
import {usePermissionsForLocation} from '../app/Permissions';
import {QueryRefreshCountdown, QueryRefreshState} from '../app/QueryRefresh';
Expand All @@ -25,7 +26,6 @@ import {AutomationAssetSelectionFragment} from '../automation/types/AutomationAs
import {InstigationStatus, SensorType} from '../graphql/types';
import {RepositoryLink} from '../nav/RepositoryLink';
import {TimestampDisplay} from '../schedules/TimestampDisplay';
import {SensorDryRunDialog} from '../ticks/SensorDryRunDialog';
import {TickStatusTag} from '../ticks/TickStatusTag';
import {RepoAddress} from '../workspace/types';

Expand Down Expand Up @@ -92,7 +92,6 @@ export const SensorDetails = ({
sensor.sensorState.typeSpecificData.__typename === 'SensorData' &&
sensor.sensorState.typeSpecificData.lastCursor;

const [showTestTickDialog, setShowTestTickDialog] = useState(false);
const running = status === InstigationStatus.RUNNING;

return (
Expand All @@ -114,33 +113,16 @@ export const SensorDetails = ({
right={
<Box margin={{top: 4}} flex={{direction: 'row', alignItems: 'center', gap: 8}}>
<QueryRefreshCountdown refreshState={refreshState} />
<Tooltip
canShow={sensor.sensorType !== SensorType.STANDARD}
content="Testing not available for this sensor type"
placement="top-end"
>
<Button
disabled={sensor.sensorType !== SensorType.STANDARD}
onClick={() => {
setShowTestTickDialog(true);
}}
>
Evaluate tick
</Button>
</Tooltip>
<EvaluateTickButtonSensor
cursor={cursor || ''}
name={sensor.name}
repoAddress={repoAddress}
jobName={sensor.targets?.[0]?.pipelineName || ''}
sensorType={sensor.sensorType}
/>
</Box>
}
/>
<SensorDryRunDialog
isOpen={showTestTickDialog}
onClose={() => {
setShowTestTickDialog(false);
}}
currentCursor={cursor || ''}
name={sensor.name}
repoAddress={repoAddress}
jobName={sensor.targets?.[0]?.pipelineName || ''}
/>
<MetadataTableWIP>
<tbody>
{sensor.description ? (
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import {Box, Button} from '@dagster-io/ui-components';
import {useState} from 'react';

import {EvaluateScheduleDialog} from './EvaluateScheduleDialog';
import {RepoAddress} from '../workspace/types';

interface EvaluateTickButtonScheduleProps {
name: string;
repoAddress: RepoAddress;
jobName: string;
}

export const EvaluateTickButtonSchedule = ({
name,
repoAddress,
jobName,
}: EvaluateTickButtonScheduleProps) => {
const [showTestTickDialog, setShowTestTickDialog] = useState(false);

return (
<Box flex={{direction: 'row', alignItems: 'center', gap: 8}}>
<Button
onClick={() => {
setShowTestTickDialog(true);
}}
>
Evaluate tick
</Button>
<EvaluateScheduleDialog
key={showTestTickDialog ? '1' : '0'} // change key to reset dialog state
isOpen={showTestTickDialog}
onClose={() => {
setShowTestTickDialog(false);
}}
name={name}
repoAddress={repoAddress}
jobName={jobName}
/>
</Box>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import {Box, Button, Tooltip} from '@dagster-io/ui-components';
import {useState} from 'react';

import {SensorDryRunDialog} from './SensorDryRunDialog';
import {SensorType} from '../graphql/types';
import {RepoAddress} from '../workspace/types';

interface EvaluateTickButtonSensorProps {
cursor: string;
name: string;
repoAddress: RepoAddress;
jobName: string;
sensorType: SensorType;
}

export const EvaluateTickButtonSensor = ({
cursor,
name,
repoAddress,
jobName,
sensorType,
}: EvaluateTickButtonSensorProps) => {
const [showTestTickDialog, setShowTestTickDialog] = useState(false);

return (
<Box flex={{direction: 'row', alignItems: 'center', gap: 8}}>
<Tooltip
canShow={sensorType !== SensorType.STANDARD}
content="Testing not available for this sensor type"
placement="top-end"
>
<Button
disabled={sensorType !== SensorType.STANDARD}
onClick={() => setShowTestTickDialog(true)}
>
Evaluate tick
</Button>
</Tooltip>
<SensorDryRunDialog
isOpen={showTestTickDialog}
onClose={() => setShowTestTickDialog(false)}
currentCursor={cursor}
name={name}
repoAddress={repoAddress}
jobName={jobName}
/>
</Box>
);
};

0 comments on commit 4e845e6

Please sign in to comment.