Skip to content

Commit

Permalink
feat(app): include current labware offsets in touchscreen LPC, implem…
Browse files Browse the repository at this point in the history
…ent lpc protocol setup designs (#13445)

Include a link to "view current offsets" in the intro screen of LPC on the ODD. Also fully implement
the designs for the LPC setup step in desktop

Closes RAUT-480
  • Loading branch information
b-cooper authored Sep 1, 2023
1 parent 557d742 commit 7a90fd1
Show file tree
Hide file tree
Showing 10 changed files with 347 additions and 114 deletions.
1 change: 1 addition & 0 deletions app/src/assets/localization/en/labware_position_check.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@
"stored_offsets_for_this_protocol": "Stored Labware Offset data that applies to this protocol",
"table_view": "Table View",
"tip_rack": "tip rack",
"view_current_offsets": "view current offsets",
"view_data": "View data",
"what_is_labware_offset_data": "What is labware offset data?"
}
2 changes: 1 addition & 1 deletion app/src/assets/localization/en/protocol_setup.json
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@
"must_have_labware_and_pip": "Protocol must load labware and a pipette",
"n_a": "N/A",
"no_data": "no data",
"no_labware_offset_data": "No Labware Offset Data yet",
"no_labware_offset_data": "no labware offset data yet",
"no_modules_specified": "no modules are specified for this protocol.",
"no_modules_used_in_this_protocol": "No modules used in this protocol",
"no_tiprack_loaded": "Protocol must load a tip rack",
Expand Down
57 changes: 32 additions & 25 deletions app/src/molecules/WizardRequiredEquipmentList/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ export function WizardRequiredEquipmentList(
>
{t('you_will_need')}
</StyledText>

<Flex
backgroundColor="#16212D33"
flexDirection={DIRECTION_COLUMN}
Expand Down Expand Up @@ -77,14 +76,19 @@ export function WizardRequiredEquipmentList(
</>
) : (
<>
<StyledText as="h3" fontWeight={TYPOGRAPHY.fontWeightSemiBold}>
<StyledText
as="h3"
fontWeight={TYPOGRAPHY.fontWeightSemiBold}
marginBottom={SPACING.spacing8}
>
{t('you_will_need')}
</StyledText>
<Divider />
{equipmentList.map(requiredEquipmentProps => (
{equipmentList.length > 1 ? <Divider /> : null}
{equipmentList.map((requiredEquipmentProps, index) => (
<RequiredEquipmentCard
key={requiredEquipmentProps.loadName}
{...requiredEquipmentProps}
bottomDivider={equipmentList.length - 1 !== index}
/>
))}
{footer != null ? (
Expand All @@ -106,12 +110,13 @@ interface RequiredEquipmentCardProps {
loadName: string
displayName: string
subtitle?: string
bottomDivider?: boolean
}

function RequiredEquipmentCard(props: RequiredEquipmentCardProps): JSX.Element {
const { loadName, displayName, subtitle } = props
const { loadName, displayName, subtitle, bottomDivider = true } = props

let imageSrc: string = labwareImages.generic_custom_tiprack
let imageSrc: string | null = null
if (loadName in labwareImages) {
imageSrc = labwareImages[loadName as keyof typeof labwareImages]
} else if (loadName in equipmentImages) {
Expand All @@ -125,24 +130,26 @@ function RequiredEquipmentCard(props: RequiredEquipmentCardProps): JSX.Element {
alignItems={ALIGN_CENTER}
width="100%"
>
<Flex
height={loadName in equipmentImages ? '3.5rem' : '6rem'}
flex="0 1 30%"
justifyContent={JUSTIFY_CENTER}
alignItems={ALIGN_CENTER}
marginRight={SPACING.spacing16}
>
<img
css={css`
max-width: 100%;
max-height: 100%;
flex: ${loadName in equipmentImages ? `0` : `0 1 5rem`};
display: block;
`}
src={imageSrc}
alt={displayName}
/>
</Flex>
{imageSrc != null ? (
<Flex
height={loadName in equipmentImages ? '3.5rem' : '6rem'}
flex="0 1 30%"
justifyContent={JUSTIFY_CENTER}
alignItems={ALIGN_CENTER}
marginRight={SPACING.spacing16}
>
<img
css={css`
max-width: 100%;
max-height: 100%;
flex: ${loadName in equipmentImages ? `0` : `0 1 5rem`};
display: block;
`}
src={imageSrc}
alt={displayName}
/>
</Flex>
) : null}
<Flex
flex="0 1 70%"
flexDirection={DIRECTION_COLUMN}
Expand All @@ -156,7 +163,7 @@ function RequiredEquipmentCard(props: RequiredEquipmentCardProps): JSX.Element {
) : null}
</Flex>
</Flex>
<Divider />
{bottomDivider ? <Divider /> : null}
</>
)
}
82 changes: 78 additions & 4 deletions app/src/organisms/Devices/ProtocolRun/ProtocolRunSetup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ import {
COLORS,
DIRECTION_COLUMN,
SPACING,
Icon,
SIZE_1,
DIRECTION_ROW,
TYPOGRAPHY,
Link,
} from '@opentrons/components'

import { Line } from '../../../atoms/structure'
Expand All @@ -20,6 +25,7 @@ import {
useRunHasStarted,
useProtocolAnalysisErrors,
useStoredProtocolAnalysis,
ProtocolCalibrationStatus,
} from '../hooks'
import { useMostRecentCompletedAnalysis } from '../../LabwarePositionCheck/useMostRecentCompletedAnalysis'
import { SetupLabware } from './SetupLabware'
Expand All @@ -29,6 +35,7 @@ import { SetupModules } from './SetupModules'
import { SetupStep } from './SetupStep'
import { SetupLiquids } from './SetupLiquids'
import { EmptySetupStep } from './EmptySetupStep'
import { HowLPCWorksModal } from './SetupLabwarePositionCheck/HowLPCWorksModal'

const ROBOT_CALIBRATION_STEP_KEY = 'robot_calibration_step' as const
const MODULE_SETUP_KEY = 'module_setup_step' as const
Expand Down Expand Up @@ -207,10 +214,10 @@ export function ProtocolRunSetup({
? setExpandedStepKey(null)
: setExpandedStepKey(stepKey)
}
calibrationStatusComplete={
stepKey === ROBOT_CALIBRATION_STEP_KEY && !runHasStarted
? calibrationStatus.complete
: null
rightElement={
<StepRightElement
{...{ stepKey, runHasStarted, calibrationStatus }}
/>
}
>
{StepDetailMap[stepKey].stepInternals}
Expand All @@ -231,3 +238,70 @@ export function ProtocolRunSetup({
</Flex>
)
}

interface StepRightElementProps {
stepKey: StepKey
calibrationStatus: ProtocolCalibrationStatus
runHasStarted: boolean
}
function StepRightElement(props: StepRightElementProps): JSX.Element | null {
const { stepKey, calibrationStatus, runHasStarted } = props
const { t } = useTranslation('protocol_setup')

if (stepKey === ROBOT_CALIBRATION_STEP_KEY && !runHasStarted) {
return (
<Flex flexDirection={DIRECTION_ROW} alignItems={ALIGN_CENTER}>
<Icon
size={SIZE_1}
color={
calibrationStatus.complete
? COLORS.successEnabled
: COLORS.warningEnabled
}
marginRight={SPACING.spacing8}
name={calibrationStatus.complete ? 'ot-check' : 'alert-circle'}
id="RunSetupCard_calibrationIcon"
/>
<StyledText
color={COLORS.black}
css={TYPOGRAPHY.pSemiBold}
marginRight={SPACING.spacing16}
textTransform={TYPOGRAPHY.textTransformCapitalize}
id="RunSetupCard_calibrationText"
>
{calibrationStatus.complete
? t('calibration_ready')
: t('calibration_needed')}
</StyledText>
</Flex>
)
} else if (stepKey === LPC_KEY) {
return <LearnAboutLPC />
} else {
return null
}
}

function LearnAboutLPC(): JSX.Element {
const { t } = useTranslation('protocol_setup')
const [showLPCHelpModal, setShowLPCHelpModal] = React.useState(false)
return (
<>
<Link
css={TYPOGRAPHY.linkPSemiBold}
marginRight={SPACING.spacing16}
onClick={e => {
// clicking link shouldn't toggle step expanded state
e.preventDefault()
e.stopPropagation()
setShowLPCHelpModal(true)
}}
>
{t('learn_how_it_works')}
</Link>
{showLPCHelpModal ? (
<HowLPCWorksModal onCloseClick={() => setShowLPCHelpModal(false)} />
) : null}
</>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import {
DIRECTION_COLUMN,
ALIGN_CENTER,
TYPOGRAPHY,
Link,
TOOLTIP_LEFT,
useHoverTooltip,
SecondaryButton,
PrimaryButton,
COLORS,
} from '@opentrons/components'
import { useRunQuery } from '@opentrons/react-api-client'
import { useMostRecentCompletedAnalysis } from '../../../LabwarePositionCheck/useMostRecentCompletedAnalysis'
Expand All @@ -20,7 +20,6 @@ import { Tooltip } from '../../../../atoms/Tooltip'
import { useLPCDisabledReason, useStoredProtocolAnalysis } from '../../hooks'
import { CurrentOffsetsTable } from './CurrentOffsetsTable'
import { useLaunchLPC } from '../../../LabwarePositionCheck/useLaunchLPC'
import { HowLPCWorksModal } from './HowLPCWorksModal'
import { StyledText } from '../../../../atoms/text'

interface SetupLabwarePositionCheckProps {
Expand All @@ -33,15 +32,14 @@ export function SetupLabwarePositionCheck(
props: SetupLabwarePositionCheckProps
): JSX.Element {
const { robotName, runId, expandLabwareStep } = props
const { t } = useTranslation('protocol_setup')
const { t, i18n } = useTranslation('protocol_setup')

const { data: runRecord } = useRunQuery(runId, { staleTime: Infinity })
const currentOffsets = runRecord?.data?.labwareOffsets ?? []
const lpcDisabledReason = useLPCDisabledReason({ robotName, runId })
const robotProtocolAnalysis = useMostRecentCompletedAnalysis(runId)
const storedProtocolAnalysis = useStoredProtocolAnalysis(runId)
const protocolData = robotProtocolAnalysis ?? storedProtocolAnalysis
const [showHelpModal, setShowHelpModal] = React.useState(false)
const [targetProps, tooltipProps] = useHoverTooltip({
placement: TOOLTIP_LEFT,
})
Expand All @@ -56,18 +54,27 @@ export function SetupLabwarePositionCheck(
marginTop={SPACING.spacing16}
gridGap={SPACING.spacing16}
>
<Flex
alignItems={ALIGN_CENTER}
justifyContent={JUSTIFY_CENTER}
flex="1 0 auto"
gridGap={SPACING.spacing16}
>
<Link
css={TYPOGRAPHY.linkPSemiBold}
onClick={() => setShowHelpModal(true)}
{currentOffsets.length > 0 ? (
<CurrentOffsetsTable
currentOffsets={currentOffsets}
commands={protocolData?.commands ?? []}
labware={protocolData?.labware ?? []}
modules={protocolData?.modules ?? []}
/>
) : (
<Flex
paddingY={SPACING.spacing8}
marginY={SPACING.spacing24}
backgroundColor={COLORS.fundamentalsBackground}
alignItems={ALIGN_CENTER}
justifyContent={JUSTIFY_CENTER}
>
{t('learn_how_it_works')}
</Link>
<StyledText as="p">
{i18n.format(t('no_labware_offset_data'), 'capitalize')}
</StyledText>
</Flex>
)}
<Flex justifyContent={JUSTIFY_CENTER} gridGap={SPACING.spacing8}>
<SecondaryButton
textTransform={TYPOGRAPHY.textTransformCapitalize}
title={t('run_labware_position_check')}
Expand All @@ -84,25 +91,6 @@ export function SetupLabwarePositionCheck(
{lpcDisabledReason !== null ? (
<Tooltip tooltipProps={tooltipProps}>{lpcDisabledReason}</Tooltip>
) : null}
</Flex>
{currentOffsets.length > 0 ? (
<CurrentOffsetsTable
currentOffsets={currentOffsets}
commands={protocolData?.commands ?? []}
labware={protocolData?.labware ?? []}
modules={protocolData?.modules ?? []}
/>
) : (
<Flex
paddingY={SPACING.spacing32}
alignItems={ALIGN_CENTER}
justifyContent={JUSTIFY_CENTER}
>
<StyledText as="p">{t('no_labware_offset_data')}</StyledText>
</Flex>
)}

<Flex justifyContent={JUSTIFY_CENTER}>
<PrimaryButton
onClick={expandLabwareStep}
id="ModuleSetup_proceedToLabwareSetup"
Expand All @@ -112,9 +100,6 @@ export function SetupLabwarePositionCheck(
</PrimaryButton>
</Flex>
{LPCWizard}
{showHelpModal ? (
<HowLPCWorksModal onCloseClick={() => setShowHelpModal(false)} />
) : null}
</Flex>
)
}
Loading

0 comments on commit 7a90fd1

Please sign in to comment.