Skip to content

Commit

Permalink
fix(app): only prepare stored protocols in ChooseProtocolSlideout onc…
Browse files Browse the repository at this point in the history
…e slid out (#12721)
  • Loading branch information
b-cooper authored May 17, 2023
1 parent ae45f49 commit 4c97c8d
Show file tree
Hide file tree
Showing 2 changed files with 165 additions and 146 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ describe('ChooseProtocolSlideout', () => {
mockDeckThumbnail.mockReturnValue(<div>mock Deck Thumbnail</div>)
mockUseCreateRunFromProtocol.mockReturnValue({
createRunFromProtocolSource: mockCreateRunFromProtocol,
reset: jest.fn(),
} as any)
mockUseTrackCreateProtocolRunEvent.mockReturnValue({
trackCreateProtocolRunEvent: mockTrackCreateProtocolRunEvent,
Expand Down
310 changes: 164 additions & 146 deletions app/src/organisms/ChooseProtocolSlideout/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,15 @@ export function ChooseProtocolSlideoutComponent(
const logger = useLogger(__filename)
const { robot, showSlideout, onCloseClick } = props
const { name } = robot
const storedProtocols = useSelector((state: State) =>
getStoredProtocols(state)
)

const [
selectedProtocol,
setSelectedProtocol,
] = React.useState<StoredProtocolData | null>(first(storedProtocols) ?? null)

const { trackCreateProtocolRunEvent } = useTrackCreateProtocolRunEvent(
selectedProtocol
] = React.useState<StoredProtocolData | null>(null)
const [shouldApplyOffsets, setShouldApplyOffsets] = React.useState(true)
const offsetCandidates = useOffsetCandidatesForAnalysis(
selectedProtocol?.mostRecentAnalysis ?? null,
robot.ip
)

const srcFileObjects =
Expand All @@ -73,10 +72,8 @@ export function ChooseProtocolSlideoutComponent(
})
: []

const [shouldApplyOffsets, setShouldApplyOffsets] = React.useState(true)
const offsetCandidates = useOffsetCandidatesForAnalysis(
selectedProtocol?.mostRecentAnalysis ?? null,
robot.ip
const { trackCreateProtocolRunEvent } = useTrackCreateProtocolRunEvent(
selectedProtocol
)

const {
Expand Down Expand Up @@ -110,7 +107,6 @@ export function ChooseProtocolSlideoutComponent(
}))
: []
)

const handleProceed: React.MouseEventHandler<HTMLButtonElement> = () => {
if (selectedProtocol != null) {
trackCreateProtocolRunEvent({ name: 'createProtocolRecordRequest' })
Expand Down Expand Up @@ -156,140 +152,18 @@ export function ChooseProtocolSlideoutComponent(
</ApiHostProvider>
}
>
{storedProtocols.length > 0 ? (
<Flex flexDirection={DIRECTION_COLUMN} gridGap={SPACING.spacing8}>
{storedProtocols.map(storedProtocol => {
const isSelected =
selectedProtocol != null &&
storedProtocol.protocolKey === selectedProtocol.protocolKey
return (
<Flex
flexDirection={DIRECTION_COLUMN}
key={storedProtocol.protocolKey}
>
<MiniCard
isSelected={isSelected}
isError={runCreationError != null}
onClick={() => {
if (!isCreatingRun) {
resetCreateRun()
setSelectedProtocol(storedProtocol)
}
}}
>
<Box display="grid" gridTemplateColumns="1fr 3fr">
<Box
marginY={SPACING.spacingAuto}
backgroundColor={isSelected ? COLORS.white : 'inherit'}
marginRight={SPACING.spacing16}
height="4.25rem"
width="4.75rem"
>
<DeckThumbnail
commands={
storedProtocol.mostRecentAnalysis?.commands ?? []
}
labware={
storedProtocol.mostRecentAnalysis?.labware ?? []
}
/>
</Box>
<StyledText
as="p"
fontWeight={TYPOGRAPHY.fontWeightSemiBold}
overflowWrap="anywhere"
>
{storedProtocol.mostRecentAnalysis?.metadata
?.protocolName ??
first(storedProtocol.srcFileNames) ??
storedProtocol.protocolKey}
</StyledText>
</Box>
{runCreationError != null && isSelected ? (
<>
<Box flex="1 1 auto" />
<Icon
name="alert-circle"
size="1.25rem"
color={COLORS.errorEnabled}
/>
</>
) : null}
</MiniCard>
{runCreationError != null && isSelected ? (
<StyledText
as="label"
color={COLORS.errorText}
overflowWrap="anywhere"
display={DISPLAY_BLOCK}
marginTop={`-${SPACING.spacing4}`}
marginBottom={SPACING.spacing8}
>
{runCreationErrorCode === 409 ? (
<Trans
t={t}
i18nKey="shared:robot_is_busy_no_protocol_run_allowed"
components={{
robotLink: (
<NavLink
css={css`
color: ${COLORS.errorText};
text-decoration: ${TYPOGRAPHY.textDecorationUnderline};
`}
to={`/devices/${robot.name}`}
/>
),
}}
/>
) : (
runCreationError
)}
</StyledText>
) : null}
</Flex>
)
})}
</Flex>
) : (
<Flex
flexDirection={DIRECTION_COLUMN}
alignItems={ALIGN_CENTER}
justifyContent={JUSTIFY_CENTER}
width="100%"
minHeight="11rem"
padding={SPACING.spacing16}
css={BORDERS.cardOutlineBorder}
>
<Icon
size="1.25rem"
name="alert-circle"
color={COLORS.medGreyEnabled}
/>
<StyledText
as="p"
fontWeight={TYPOGRAPHY.fontWeightSemiBold}
marginTop={SPACING.spacing8}
role="heading"
>
{t('no_protocols_found')}
</StyledText>
<StyledText
as="p"
marginTop={SPACING.spacing8}
textAlign={TYPOGRAPHY.textAlignCenter}
>
<Trans
t={t}
i18nKey="to_run_protocol_go_to_protocols_page"
components={{
navlink: (
<Link to="/protocols" css={TYPOGRAPHY.linkPSemiBold} />
),
}}
/>
</StyledText>
</Flex>
)}
{showSlideout ? (
<StoredProtocolList
handleSelectProtocol={storedProtocol => {
if (!isCreatingRun) {
resetCreateRun()
setSelectedProtocol(storedProtocol)
}
}}
robotName={robot.name}
{...{ selectedProtocol, runCreationError, runCreationErrorCode }}
/>
) : null}
</Slideout>
)
}
Expand All @@ -299,3 +173,147 @@ export function ChooseProtocolSlideout(
): JSX.Element | null {
return <ChooseProtocolSlideoutComponent {...props} />
}

interface StoredProtocolListProps {
selectedProtocol: StoredProtocolData | null
handleSelectProtocol: (storedProtocol: StoredProtocolData | null) => void
runCreationError: string | null
runCreationErrorCode: number | null
robotName: string
}

function StoredProtocolList(props: StoredProtocolListProps): JSX.Element {
const {
selectedProtocol,
handleSelectProtocol,
runCreationError,
runCreationErrorCode,
robotName,
} = props
const { t } = useTranslation(['device_details', 'shared'])
const storedProtocols = useSelector((state: State) =>
getStoredProtocols(state)
)
React.useEffect(() => {
handleSelectProtocol(first(storedProtocols) ?? null)
}, [])

return storedProtocols.length > 0 ? (
<Flex flexDirection={DIRECTION_COLUMN} gridGap={SPACING.spacing8}>
{storedProtocols.map(storedProtocol => {
const isSelected =
selectedProtocol != null &&
storedProtocol.protocolKey === selectedProtocol.protocolKey
return (
<Flex
flexDirection={DIRECTION_COLUMN}
key={storedProtocol.protocolKey}
>
<MiniCard
isSelected={isSelected}
isError={runCreationError != null}
onClick={() => handleSelectProtocol(storedProtocol)}
>
<Box display="grid" gridTemplateColumns="1fr 3fr">
<Box
marginY={SPACING.spacingAuto}
backgroundColor={isSelected ? COLORS.white : 'inherit'}
marginRight={SPACING.spacing16}
height="4.25rem"
width="4.75rem"
>
<DeckThumbnail
commands={storedProtocol.mostRecentAnalysis?.commands ?? []}
labware={storedProtocol.mostRecentAnalysis?.labware ?? []}
/>
</Box>
<StyledText
as="p"
fontWeight={TYPOGRAPHY.fontWeightSemiBold}
overflowWrap="anywhere"
>
{storedProtocol.mostRecentAnalysis?.metadata?.protocolName ??
first(storedProtocol.srcFileNames) ??
storedProtocol.protocolKey}
</StyledText>
</Box>
{runCreationError != null && isSelected ? (
<>
<Box flex="1 1 auto" />
<Icon
name="alert-circle"
size="1.25rem"
color={COLORS.errorEnabled}
/>
</>
) : null}
</MiniCard>
{runCreationError != null && isSelected ? (
<StyledText
as="label"
color={COLORS.errorText}
overflowWrap="anywhere"
display={DISPLAY_BLOCK}
marginTop={`-${SPACING.spacing4}`}
marginBottom={SPACING.spacing8}
>
{runCreationErrorCode === 409 ? (
<Trans
t={t}
i18nKey="shared:robot_is_busy_no_protocol_run_allowed"
components={{
robotLink: (
<NavLink
css={css`
color: ${COLORS.errorText};
text-decoration: ${TYPOGRAPHY.textDecorationUnderline};
`}
to={`/devices/${robotName}`}
/>
),
}}
/>
) : (
runCreationError
)}
</StyledText>
) : null}
</Flex>
)
})}
</Flex>
) : (
<Flex
flexDirection={DIRECTION_COLUMN}
alignItems={ALIGN_CENTER}
justifyContent={JUSTIFY_CENTER}
width="100%"
minHeight="11rem"
padding={SPACING.spacing16}
css={BORDERS.cardOutlineBorder}
>
<Icon size="1.25rem" name="alert-circle" color={COLORS.medGreyEnabled} />
<StyledText
as="p"
fontWeight={TYPOGRAPHY.fontWeightSemiBold}
marginTop={SPACING.spacing8}
role="heading"
>
{t('no_protocols_found')}
</StyledText>
<StyledText
as="p"
marginTop={SPACING.spacing8}
textAlign={TYPOGRAPHY.textAlignCenter}
>
<Trans
t={t}
i18nKey="to_run_protocol_go_to_protocols_page"
components={{
navlink: <Link to="/protocols" css={TYPOGRAPHY.linkPSemiBold} />,
}}
/>
</StyledText>
</Flex>
)
}

0 comments on commit 4c97c8d

Please sign in to comment.