Skip to content

Commit

Permalink
feat(app): ODD: confirm run modal for steps
Browse files Browse the repository at this point in the history
We need a nag modal that doesn't let you start a run unless you
acknowledge you haven't done some of the steps yet.

Fun fact we get intl for free inside i18next in 21, but we have 19.
  • Loading branch information
sfoster1 committed Aug 6, 2024
1 parent 64f68a6 commit 5ab7f03
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 15 deletions.
9 changes: 7 additions & 2 deletions app/src/assets/localization/en/protocol_setup.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
"add_to_slot": "Add to slot {{slotName}}",
"additional_labware": "{{count}} additional labware",
"additional_off_deck_labware": "Additional Off-Deck Labware",
"applied_labware_offsets": "applied labware offsets",
"are_you_sure_you_want_to_proceed": "Are you sure you want to proceed to run?",
"attach_gripper_failure_reason": "Attach the required gripper to continue",
"attach_gripper": "attach gripper",
"attach_module": "Attach module before calibrating",
Expand Down Expand Up @@ -104,6 +106,7 @@
"labware_latch": "Labware Latch",
"labware_location": "Labware Location",
"labware_name": "Labware name",
"labware_placement": "labware placement",
"labware_position_check_not_available_analyzing_on_robot": "Labware Position Check is not available while protocol is analyzing on robot",
"labware_position_check_not_available_empty_protocol": "Labware Position Check requires that the protocol loads labware and pipettes",
"labware_position_check_not_available": "Labware Position Check is not available after run has started",
Expand All @@ -121,11 +124,11 @@
"learn_more": "Learn more",
"liquid_information": "Liquid information",
"liquid_name": "Liquid name",
"liquids": "liquids",
"liquid_setup_step_description": "View liquid starting locations and volumes",
"liquid_setup_step_title": "Liquids",
"liquids_not_in_setup": "No liquids used in this protocol",
"liquids_not_in_the_protocol": "no liquids are specified for this protocol.",
"liquids": "Liquids",
"liquids_ready": "Liquids ready",
"liquids_confirmed": "Liquids confirmed",
"list_view": "List View",
Expand Down Expand Up @@ -270,6 +273,7 @@
"setup_is_view_only": "Setup is view-only once run has started",
"slot_location": "Slot {{slotName}}",
"slot_number": "Slot Number",
"start_run": "Start run",
"status": "Status",
"step": "STEP {{index}}",
"there_are_no_unconfigured_modules": "No {{module}} is connected. Attach one and place it in {{slot}}.",
Expand Down Expand Up @@ -297,5 +301,6 @@
"view_setup_instructions": "View setup instructions",
"volume": "Volume",
"what_labware_offset_is": "A Labware Offset is a type of positional adjustment that accounts for small, real-world variances in the overall position of the labware on a robot’s deck. Labware Offset data is unique to a specific combination of labware definition, deck slot, and robot.",
"with_the_chosen_value": "With the chosen values, the following error occurred:"
"with_the_chosen_value": "With the chosen values, the following error occurred:",
"you_havent_confirmed": "You haven't confirmed the {{missingSteps}} yet. Ensure these are correct before proceeding to run the protocol."
}
4 changes: 2 additions & 2 deletions app/src/organisms/ProtocolSetupLiquids/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export function ProtocolSetupLiquids({
isConfirmed,
setIsConfirmed,
}: ProtocolSetupLiquidsProps): JSX.Element {
const { t } = useTranslation('protocol_setup')
const { t, i18n } = useTranslation('protocol_setup')
const protocolData = useMostRecentCompletedAnalysis(runId)
const liquidsInLoadOrder = parseLiquidsInLoadOrder(
protocolData?.liquids ?? [],
Expand All @@ -56,7 +56,7 @@ export function ProtocolSetupLiquids({
justifyContent={JUSTIFY_SPACE_BETWEEN}
>
<ODDBackButton
label={t('liquids')}
label={i18n.format(t('liquids'), 'capitalize')}
onClick={() => {
setSetupScreen('prepare to run')
}}
Expand Down
68 changes: 68 additions & 0 deletions app/src/pages/ProtocolSetup/ConfirmSetupStepsCompleteModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import * as React from 'react'
import { useTranslation } from 'react-i18next'

import {
DIRECTION_COLUMN,
Flex,
SPACING,
LegacyStyledText,
} from '@opentrons/components'

import { SmallButton } from '../../atoms/buttons'
import { Modal } from '../../molecules/Modal'

import type { ModalHeaderBaseProps } from '../../molecules/Modal/types'

interface ConfirmSetupStepsCompleteModalProps {
onCloseClick: () => void
onConfirmClick: () => void
missingSteps: string[]
}

export function ConfirmSetupStepsCompleteModal({
onCloseClick,
missingSteps,
onConfirmClick,
}: ConfirmSetupStepsCompleteModalProps): JSX.Element {
const { i18n, t } = useTranslation(['protocol_setup', 'shared'])
const modalHeader: ModalHeaderBaseProps = {
title: t('are_you_sure_you_want_to_proceed'),
hasExitIcon: true,
}

const handleStartRun = (): void => {
onConfirmClick()
onCloseClick()
}

return (
<Modal header={modalHeader} onOutsideClick={onCloseClick}>
<Flex flexDirection={DIRECTION_COLUMN} gridGap={SPACING.spacing32}>
<LegacyStyledText as="p">
{t('you_havent_confirmed', {
missingSteps: new Intl.ListFormat('en', {
style: 'short',
type: 'conjunction',
}).format(missingSteps),
})}
</LegacyStyledText>
<Flex gridGap={SPACING.spacing8}>
<SmallButton
flex="1"
buttonType="secondary"
buttonText={i18n.format(t('shared:go_back'), 'capitalize')}
onClick={() => {
onCloseClick()
}}
/>
<SmallButton
flex="1"
buttonType="primary"
buttonText={t('start_run')}
onClick={handleStartRun}
/>
</Flex>
</Flex>
</Modal>
)
}
49 changes: 38 additions & 11 deletions app/src/pages/ProtocolSetup/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ import {
} from '../../redux/analytics'
import { getIsHeaterShakerAttached } from '../../redux/config'
import { ConfirmAttachedModal } from './ConfirmAttachedModal'
import { ConfirmSetupStepsCompleteModal } from './ConfirmSetupStepsCompleteModal'
import { getLatestCurrentOffsets } from '../../organisms/Devices/ProtocolRun/SetupLabwarePositionCheck/utils'
import { CloseButton, PlayButton } from './Buttons'
import { useDeckConfigurationCompatibility } from '../../resources/deck_configuration/hooks'
Expand Down Expand Up @@ -274,6 +275,7 @@ interface PrepareToRunProps {
runId: string
setSetupScreen: React.Dispatch<React.SetStateAction<SetupScreens>>
confirmAttachment: () => void
confirmStepsComplete: () => void
play: () => void
robotName: string
runRecord: Run | null
Expand All @@ -292,6 +294,7 @@ function PrepareToRun({
labwareConfirmed,
liquidsConfirmed,
offsetsConfirmed,
confirmStepsComplete,
}: PrepareToRunProps): JSX.Element {
const { t, i18n } = useTranslation(['protocol_setup', 'shared'])
const navigate = useNavigate()
Expand Down Expand Up @@ -516,12 +519,13 @@ function PrepareToRun({
if (isDoorOpen) {
makeSnackbar(t('shared:close_robot_door') as string)
} else {
if (
isHeaterShakerInProtocol &&
isReadyToRun &&
runStatus === RUN_STATUS_IDLE
) {
confirmAttachment()
if (isReadyToRun && runStatus === RUN_STATUS_IDLE) {
if (!(labwareConfirmed && offsetsConfirmed && liquidsConfirmed)) {
confirmStepsComplete()
}
if (isHeaterShakerInProtocol) {
confirmAttachment()
}
} else {
if (isReadyToRun) {
play()
Expand Down Expand Up @@ -793,7 +797,7 @@ function PrepareToRun({
onClickSetupStep={() => {
setSetupScreen('liquids')
}}
title={t('liquids')}
title={i18n.format(t('liquids'), 'capitalize')}
status={liquidsConfirmed ? 'ready' : 'general'}
detail={
liquidsInProtocol.length > 0
Expand Down Expand Up @@ -840,6 +844,7 @@ export function ProtocolSetup(): JSX.Element {
>() as OnDeviceRouteParams
const { data: runRecord } = useNotifyRunQuery(runId, { staleTime: Infinity })
const { analysisErrors } = useProtocolAnalysisErrors(runId)
const { t } = useTranslation(['protocol_setup'])
const localRobot = useSelector(getLocalRobot)
const robotName = localRobot?.name != null ? localRobot.name : 'no name'
const robotSerialNumber =
Expand Down Expand Up @@ -925,8 +930,8 @@ export function ProtocolSetup(): JSX.Element {
)
const {
confirm: confirmAttachment,
showConfirmation: showConfirmationModal,
cancel: cancelExit,
showConfirmation: showHSConfirmationModal,
cancel: cancelExitHSConfirmation,
} = useConditionalConfirm(
handleProceedToRunClick,
!configBypassHeaterShakerAttachmentConfirmation
Expand All @@ -938,6 +943,20 @@ export function ProtocolSetup(): JSX.Element {
const [labwareConfirmed, setLabwareConfirmed] = React.useState<boolean>(false)
const [liquidsConfirmed, setLiquidsConfirmed] = React.useState<boolean>(false)
const [offsetsConfirmed, setOffsetsConfirmed] = React.useState<boolean>(false)
const missingSteps = [
!offsetsConfirmed ? t('applied_labware_offsets') : null,
!labwareConfirmed ? t('labware_placement') : null,
!liquidsConfirmed ? t('liquids') : null,
].filter(s => s != null)
console.log(missingSteps)
const {
confirm: confirmMissingSteps,
showConfirmation: showMissingStepsConfirmation,
cancel: cancelExitMissingStepsConfirmation,
} = useConditionalConfirm(
handleProceedToRunClick,
!(labwareConfirmed && liquidsConfirmed && offsetsConfirmed)
)

// orchestrate setup subpages/components
const [setupScreen, setSetupScreen] = React.useState<SetupScreens>(
Expand All @@ -949,6 +968,7 @@ export function ProtocolSetup(): JSX.Element {
runId={runId}
setSetupScreen={setSetupScreen}
confirmAttachment={confirmAttachment}
confirmStepsComplete={confirmMissingSteps}
play={play}
robotName={robotName}
runRecord={runRecord ?? null}
Expand Down Expand Up @@ -1019,9 +1039,16 @@ export function ProtocolSetup(): JSX.Element {
errors={analysisErrors.map(error => error.detail)}
/>
) : null}
{showConfirmationModal ? (
{showMissingStepsConfirmation ? (
<ConfirmSetupStepsCompleteModal
onCloseClick={cancelExitMissingStepsConfirmation}
missingSteps={missingSteps}
onConfirmClick={handleProceedToRunClick}
/>
) : null}
{showHSConfirmationModal ? (
<ConfirmAttachedModal
onCloseClick={cancelExit}
onCloseClick={cancelExitHSConfirmation}
isProceedToRunModal={true}
onConfirmClick={handleProceedToRunClick}
/>
Expand Down

0 comments on commit 5ab7f03

Please sign in to comment.