Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(app): Refactor LPC flows in preparation for LPC redesign #17279

Open
wants to merge 34 commits into
base: edge
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
2d910f5
refactor(app): dupe LegacyLPC -> LPC
mjhuff Dec 18, 2024
067e2b3
refactor(app): wire up the non-legacy LPC flows behind FFs
mjhuff Dec 18, 2024
c8c3835
merge LPC component and hook into same file
mjhuff Dec 18, 2024
5c4db0b
refactor(app): create flex & ot2 specific lpc containers
mjhuff Jan 2, 2025
615f570
refactor(app, api-client, react-api-client): GET run defs rather than…
mjhuff Jan 2, 2025
179c9a7
consolidate maintenance run mgmt logic in the lpc hook
mjhuff Jan 2, 2025
ad42b78
refactor(app): refactor lpc redux
mjhuff Jan 3, 2025
fbd9be2
refactor(app): roughly split the presentation and data layers
mjhuff Jan 6, 2025
28bd24f
refactor(app): remove all OT-2/Flex conditional logic from the Flex f…
mjhuff Jan 6, 2025
2b422fb
refactor(app): name space steps and shared components, removing OT2 s…
mjhuff Jan 6, 2025
b3ad7ca
refactor(app): make TerseOffsetTable an organism
mjhuff Jan 6, 2025
6370491
refactor(app): remove the get labware display util
mjhuff Jan 6, 2025
17a856d
refactor(app): reduce command iteration in LPC
mjhuff Jan 6, 2025
a9deeb4
refactor(app): inject all commands into the presentation layer
mjhuff Jan 7, 2025
d85419a
refactor(app): remove multiple instances of isOnDevice
mjhuff Jan 7, 2025
769986a
refactor(app): hoist RobotMotionLoader out of every step component
mjhuff Jan 7, 2025
713240f
refactor(app): encapsulate robot commands
mjhuff Jan 8, 2025
410fec5
refactor(app): componentize views in LPC steps
mjhuff Jan 8, 2025
d88966f
refactor(app): move all state inside redux
mjhuff Jan 8, 2025
0a0ef08
refactor(app): hoist refactored components out of shared
mjhuff Jan 9, 2025
01bf56e
refactor(app): move the remaining components out of shared
mjhuff Jan 9, 2025
4ae76cd
refactor(app): relocate general utils
mjhuff Jan 9, 2025
f33f9ff
refactor(app): remove tip pickup offset from redux store
mjhuff Jan 13, 2025
e39650a
refactor(app): move all state derivation logic to selectors
mjhuff Jan 13, 2025
a36ef27
refactor(app): add an error-handled build finalized offsets selector
mjhuff Jan 13, 2025
8be24d9
clean up
mjhuff Jan 14, 2025
da584ad
refactor(app): promise chain commands
mjhuff Jan 15, 2025
3ee2308
nicer command errors (and test cleanup)
mjhuff Jan 15, 2025
391edd8
nullish coalescence is a thing
mjhuff Jan 16, 2025
f4e3109
namespacing for the protocol-runs store
mjhuff Jan 16, 2025
d7bc992
wire up to the global store
mjhuff Jan 17, 2025
494e45f
new todo
mjhuff Jan 17, 2025
2beed9d
Merge branch 'edge' into app_split-data-presentation-lpc
mjhuff Jan 17, 2025
ffd9b08
lint
mjhuff Jan 17, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,20 @@ import { POST, request } from '../request'
import type { ResponsePromise } from '../request'
import type { HostConfig } from '../types'
import type { LabwareDefinitionSummary } from './types'
import type { LabwareDefinition2 } from '@opentrons/shared-data'
import type {
LabwareDefinition2,
LabwareDefinition3,
} from '@opentrons/shared-data'

export function createMaintenanceRunLabwareDefinition(
config: HostConfig,
maintenanceRunId: string,
data: LabwareDefinition2
data: LabwareDefinition2 | LabwareDefinition3
): ResponsePromise<LabwareDefinitionSummary> {
return request<LabwareDefinitionSummary, { data: LabwareDefinition2 }>(
return request<
LabwareDefinitionSummary,
{ data: LabwareDefinition2 | LabwareDefinition3 }
>(
POST,
`/maintenance_runs/${maintenanceRunId}/labware_definitions`,
{ data },
Expand Down
4 changes: 2 additions & 2 deletions app/src/organisms/Desktop/ChooseProtocolSlideout/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ export function ChooseProtocolSlideoutComponent(
const { robot, showSlideout, onCloseClick } = props
const { name } = robot

const isNewLpc = useFeatureFlag('lpcRedesign')
const isNewLPC = useFeatureFlag('lpcRedesign')

const [
selectedProtocol,
Expand Down Expand Up @@ -655,7 +655,7 @@ export function ChooseProtocolSlideoutComponent(
}
>
{currentPage === 1
? !isNewLpc && (
? !isNewLPC && (
<LegacyApplyHistoricOffsets
offsetCandidates={offsetCandidates}
shouldApplyOffsets={shouldApplyOffsets}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export function ChooseRobotToRunProtocolSlideoutComponent(
setSelectedRobot,
} = props
const navigate = useNavigate()
const isNewLpc = useFeatureFlag('lpcRedesign')
const isNewLPC = useFeatureFlag('lpcRedesign')
const [shouldApplyOffsets, setShouldApplyOffsets] = useState<boolean>(true)
const {
protocolKey,
Expand Down Expand Up @@ -221,7 +221,7 @@ export function ChooseRobotToRunProtocolSlideoutComponent(
</PrimaryButton>
)

const offsetsComponent = isNewLpc ? null : (
const offsetsComponent = isNewLPC ? null : (
<LegacyApplyHistoricOffsets
offsetCandidates={offsetCandidates}
shouldApplyOffsets={shouldApplyOffsets}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ export function ProtocolRunSetup({
orderedApplicableSteps,
} = useRequiredSetupStepsInOrder({ runId, protocolAnalysis })
const modules = parseAllRequiredModuleModels(protocolAnalysis?.commands ?? [])
const isNewLpc = useFeatureFlag('lpcRedesign')
const isNewLPC = useFeatureFlag('lpcRedesign')
const robot = useRobot(robotName)
const calibrationStatusRobot = useRunCalibrationStatus(robotName, runId)
const calibrationStatusModules = useModuleCalibrationStatus(robotName, runId)
Expand Down Expand Up @@ -225,7 +225,7 @@ export function ProtocolRunSetup({
}
}}
offsetsConfirmed={!missingSteps.includes(LPC_STEP_KEY)}
isNewLpc={isNewLpc}
isNewLPC={isNewLPC}
/>
),
description: t('labware_position_check_step_description'),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
useUnmatchedModulesForProtocol,
} from '/app/resources/runs'
import { useRobotType } from '/app/redux-resources/robots'
import { useLPCFlows } from '/app/organisms/LabwarePositionCheck'

import type { Mock } from 'vitest'

Expand All @@ -34,6 +35,7 @@ vi.mock('/app/redux/config')
vi.mock('../../../hooks/useLPCSuccessToast')
vi.mock('@opentrons/react-api-client')
vi.mock('/app/resources/runs')
vi.mock('/app/organisms/LabwarePositionCheck')

const DISABLED_REASON = 'MOCK_DISABLED_REASON'
const ROBOT_NAME = 'otie'
Expand All @@ -51,7 +53,7 @@ const render = () => {
setOffsetsConfirmed={confirmOffsets}
robotName={ROBOT_NAME}
runId={RUN_ID}
isNewLpc={false}
isNewLPC={false}
/>
</MemoryRouter>,
{
Expand Down Expand Up @@ -106,6 +108,7 @@ describe('SetupLabwarePositionCheck', () => {
vi.mocked(useProtocolAnalysisAsDocumentQuery).mockReturnValue({
data: null,
} as any)
vi.mocked(useLPCFlows).mockReturnValue({ launchLPC: mockLaunchLPC } as any)
})

afterEach(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,16 @@ import {
useLPCDisabledReason,
} from '/app/resources/runs'
import { useRobotType } from '/app/redux-resources/robots'
import { useLPCFlows, LPCFlows } from '/app/organisms/LabwarePositionCheck'

import type { LabwareOffset } from '@opentrons/api-client'

interface SetupLabwarePositionCheckProps {
offsetsConfirmed: boolean
setOffsetsConfirmed: (confirmed: boolean) => void
robotName: string
runId: string
isNewLpc: boolean
isNewLPC: boolean
}

export function SetupLabwarePositionCheck(
Expand All @@ -47,7 +49,7 @@ export function SetupLabwarePositionCheck(
runId,
setOffsetsConfirmed,
offsetsConfirmed,
isNewLpc,
isNewLPC,
} = props
const { t, i18n } = useTranslation('protocol_setup')

Expand Down Expand Up @@ -100,6 +102,11 @@ export function SetupLabwarePositionCheck(
robotType,
protocolName
)
const { launchLPC, lpcProps, showLPC } = useLPCFlows({
runId,
robotType,
protocolName,
})

const nonIdentityOffsets = getLatestCurrentOffsets(sortedOffsets)

Expand Down Expand Up @@ -155,7 +162,7 @@ export function SetupLabwarePositionCheck(
<PrimaryButton
textTransform={TYPOGRAPHY.textTransformCapitalize}
onClick={() => {
isNewLpc ? (() => null)() : launchLegacyLPC()
isNewLPC ? launchLPC() : launchLegacyLPC()
setIsShowingLPCSuccessToast(false)
}}
id="LabwareSetup_checkLabwarePositionsButton"
Expand All @@ -170,7 +177,8 @@ export function SetupLabwarePositionCheck(
</Tooltip>
) : null}
</Flex>
{isNewLpc ? null : LegacyLPCWizard}
{isNewLPC ? null : LegacyLPCWizard}
{showLPC && <LPCFlows {...lpcProps} />}
</Flex>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,6 @@ export function useRecoveryFullCommandText(
): string | null {
const { commandTextData, stepNumber } = props

// TODO TOME: I think you are looking one command to far, for some reason.
const relevantCmdIdx = stepNumber ?? -1
const relevantCmd = commandTextData?.commands[relevantCmdIdx - 1] ?? null

Expand Down
150 changes: 150 additions & 0 deletions app/src/organisms/LabwarePositionCheck/ExitConfirmation.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
import styled, { css } from 'styled-components'
import { useTranslation } from 'react-i18next'
import { useSelector } from 'react-redux'

import {
AlertPrimaryButton,
ALIGN_CENTER,
COLORS,
DIRECTION_COLUMN,
Flex,
Icon,
JUSTIFY_CENTER,
JUSTIFY_FLEX_END,
RESPONSIVENESS,
SecondaryButton,
SIZE_3,
SPACING,
LegacyStyledText,
TEXT_ALIGN_CENTER,
TYPOGRAPHY,
} from '@opentrons/components'

import { SmallButton } from '/app/atoms/buttons'
import { getIsOnDevice } from '/app/redux/config'

import type { LPCWizardContentProps } from '/app/organisms/LabwarePositionCheck/types'

export function ExitConfirmation({
commandUtils,
}: LPCWizardContentProps): JSX.Element {
const { i18n, t } = useTranslation(['labware_position_check', 'shared'])
const { confirmExitLPC, cancelExitLPC, toggleRobotMoving } = commandUtils
const isOnDevice = useSelector(getIsOnDevice)

const handleConfirmExit = (): void => {
toggleRobotMoving(true).then(() => {
confirmExitLPC()
})
}

return (
<Flex css={CONTAINER_STYLE}>
<Flex css={CONTENT_CONTAINER_STYLE}>
<Icon name="ot-alert" size={SIZE_3} color={COLORS.yellow50} />
{isOnDevice ? (
<>
<ConfirmationHeaderODD>
{t('remove_probe_before_exit')}
</ConfirmationHeaderODD>
<Flex textAlign={TEXT_ALIGN_CENTER}>
<ConfirmationBodyODD>
{t('exit_screen_subtitle')}
</ConfirmationBodyODD>
</Flex>
</>
) : (
<>
<ConfirmationHeader>
{t('remove_probe_before_exit')}
</ConfirmationHeader>
<LegacyStyledText as="p" marginTop={SPACING.spacing8}>
{t('exit_screen_subtitle')}
</LegacyStyledText>
</>
)}
</Flex>
{isOnDevice ? (
<Flex css={BUTTON_CONTAINER_STYLE_ODD}>
<SmallButton
onClick={cancelExitLPC}
buttonText={i18n.format(t('shared:go_back'), 'capitalize')}
buttonType="secondary"
/>
<SmallButton
onClick={handleConfirmExit}
buttonText={t('remove_calibration_probe')}
buttonType="alert"
/>
</Flex>
) : (
<Flex css={BUTTON_CONTAINER_STYLE}>
<Flex gridGap={SPACING.spacing8}>
<SecondaryButton onClick={cancelExitLPC}>
{t('shared:go_back')}
</SecondaryButton>
<AlertPrimaryButton
onClick={handleConfirmExit}
textTransform={TYPOGRAPHY.textTransformCapitalize}
>
{t('remove_calibration_probe')}
</AlertPrimaryButton>
</Flex>
</Flex>
)}
</Flex>
)
}

const CONTAINER_STYLE = css`
flex-direction: ${DIRECTION_COLUMN};
padding: ${SPACING.spacing32};
min-height: 29.5rem;
`

const CONTENT_CONTAINER_STYLE = css`
flex: 1;
flex-direction: ${DIRECTION_COLUMN};
justify-content: ${JUSTIFY_CENTER};
align-items: ${ALIGN_CENTER};
padding-left: ${SPACING.spacing32};
padding-right: ${SPACING.spacing32};
`

const BUTTON_CONTAINER_STYLE = css`
width: 100%;
margin-top: ${SPACING.spacing32};
justify-content: ${JUSTIFY_FLEX_END};
align-items: ${ALIGN_CENTER};
`

const BUTTON_CONTAINER_STYLE_ODD = css`
width: 100%;
justify-content: ${JUSTIFY_FLEX_END};
align-items: ${ALIGN_CENTER};
grid-gap: ${SPACING.spacing8};
`

const ConfirmationHeader = styled.h1`
margin-top: ${SPACING.spacing24};
${TYPOGRAPHY.h1Default}
@media ${RESPONSIVENESS.touchscreenMediaQuerySpecs} {
${TYPOGRAPHY.level4HeaderSemiBold}
}
`

const ConfirmationHeaderODD = styled.h1`
margin-top: ${SPACING.spacing24};
${TYPOGRAPHY.level3HeaderBold}
@media ${RESPONSIVENESS.touchscreenMediaQuerySpecs} {
${TYPOGRAPHY.level4HeaderSemiBold}
}
`

const ConfirmationBodyODD = styled.h1`
${TYPOGRAPHY.level4HeaderRegular}
@media ${RESPONSIVENESS.touchscreenMediaQuerySpecs} {
${TYPOGRAPHY.level4HeaderRegular}
}
color: ${COLORS.grey60};
`
Loading
Loading