diff --git a/app/src/organisms/ProtocolSetup/LabwarePositionCheck/GenericStepScreen.tsx b/app/src/organisms/ProtocolSetup/LabwarePositionCheck/GenericStepScreen.tsx index eb865f7bb45..28be75d9c5c 100644 --- a/app/src/organisms/ProtocolSetup/LabwarePositionCheck/GenericStepScreen.tsx +++ b/app/src/organisms/ProtocolSetup/LabwarePositionCheck/GenericStepScreen.tsx @@ -1,5 +1,14 @@ import * as React from 'react' +import { + ALIGN_CENTER, + Box, + Flex, + JUSTIFY_SPACE_BETWEEN, + SPACING_3, +} from '@opentrons/components' import { LabwarePositionCheckStepDetail } from './LabwarePositionCheckStepDetail' +import { SectionList } from './SectionList' +import { useIntroInfo } from './hooks' import type { LabwarePositionCheckStep } from './types' interface GenericStepScreenProps { @@ -9,5 +18,24 @@ interface GenericStepScreenProps { export const GenericStepScreen = ( props: GenericStepScreenProps ): JSX.Element | null => { - return + const introInfo = useIntroInfo() + const [sectionIndex] = React.useState(0) + if (introInfo == null) return null + const { sections, primaryPipetteMount, secondaryPipetteMount } = introInfo + return ( + + + + + + + + + ) } diff --git a/app/src/organisms/ProtocolSetup/LabwarePositionCheck/IntroScreen.tsx b/app/src/organisms/ProtocolSetup/LabwarePositionCheck/IntroScreen.tsx index d5f9cdcfca2..f224471a89d 100644 --- a/app/src/organisms/ProtocolSetup/LabwarePositionCheck/IntroScreen.tsx +++ b/app/src/organisms/ProtocolSetup/LabwarePositionCheck/IntroScreen.tsx @@ -17,7 +17,7 @@ import { SPACING_4, FONT_SIZE_BODY_2, } from '@opentrons/components' -import { PositionCheckNav } from './PositionCheckNav' +import { SectionList } from './SectionList' import { DeckMap } from './DeckMap' import { useIntroInfo, useLabwareIdsBySection } from './hooks' @@ -63,7 +63,7 @@ export const IntroScreen = (props: { }} > - - {sections.map((section, index) => ( - - - {index + 1} - - - - {t(`${section.toLowerCase()}_section`, { - primary_mount: capitalize(primaryPipetteMount), - secondary_mount: capitalize(secondaryPipetteMount), - })} - - - - ))} - - ) -} diff --git a/app/src/organisms/ProtocolSetup/LabwarePositionCheck/SectionList.tsx b/app/src/organisms/ProtocolSetup/LabwarePositionCheck/SectionList.tsx new file mode 100644 index 00000000000..34dbb931bba --- /dev/null +++ b/app/src/organisms/ProtocolSetup/LabwarePositionCheck/SectionList.tsx @@ -0,0 +1,111 @@ +import * as React from 'react' +import { useTranslation } from 'react-i18next' +import capitalize from 'lodash/capitalize' +import { + Flex, + Box, + ALIGN_CENTER, + SIZE_1, + SPACING_2, + SPACING_5, + C_WHITE, + C_NEAR_WHITE, + C_DARK_GRAY, + TEXT_ALIGN_CENTER, + FONT_SIZE_CAPTION, + Text, + C_DISABLED, + Icon, + SPACING_3, + COLOR_SUCCESS, + C_SELECTED_DARK, +} from '@opentrons/components' +import type { Section } from './types' +interface Props { + sections: Section[] + currentSection: Section + primaryPipetteMount: string + secondaryPipetteMount: string + completedSections?: Section[] +} + +export function SectionList(props: Props): JSX.Element { + const { + currentSection, + sections, + primaryPipetteMount, + secondaryPipetteMount, + completedSections, + } = props + const { t } = useTranslation('labware_position_check') + + return ( + + {sections.map((section, index) => { + const sectionTextColor = + completedSections != null && !completedSections.includes(section) + ? C_DISABLED + : C_DARK_GRAY + const isCompleted = + completedSections != null && completedSections.includes(section) + let backgroundColor = C_DISABLED + if (section === currentSection) { + backgroundColor = C_SELECTED_DARK + } else if (isCompleted === true) { + backgroundColor = 'transparent' + } else { + backgroundColor = sectionTextColor + } + return ( + + + {isCompleted ? ( + + ) : ( + index + 1 + )} + + + + {t(`${section.toLowerCase()}_section`, { + primary_mount: capitalize(primaryPipetteMount), + secondary_mount: capitalize(secondaryPipetteMount), + })} + + + + ) + })} + + ) +} diff --git a/app/src/organisms/ProtocolSetup/LabwarePositionCheck/__tests__/GenericStepScreen.test.tsx b/app/src/organisms/ProtocolSetup/LabwarePositionCheck/__tests__/GenericStepScreen.test.tsx index 8c9bd03ffd3..09b3485120d 100644 --- a/app/src/organisms/ProtocolSetup/LabwarePositionCheck/__tests__/GenericStepScreen.test.tsx +++ b/app/src/organisms/ProtocolSetup/LabwarePositionCheck/__tests__/GenericStepScreen.test.tsx @@ -7,15 +7,27 @@ import { import { i18n } from '../../../../i18n' import { GenericStepScreen } from '../GenericStepScreen' import { LabwarePositionCheckStepDetail } from '../LabwarePositionCheckStepDetail' +import { SectionList } from '../SectionList' +import { useIntroInfo } from '../hooks' +import { Section } from '../types' jest.mock('../LabwarePositionCheckStepDetail') +jest.mock('../SectionList') +jest.mock('../hooks') const mockLabwarePositionCheckStepDetail = LabwarePositionCheckStepDetail as jest.MockedFunction< typeof LabwarePositionCheckStepDetail > +const mockSectionList = SectionList as jest.MockedFunction +const mockUseIntroInfo = useIntroInfo as jest.MockedFunction< + typeof useIntroInfo +> + const PICKUP_TIP_LABWARE_ID = 'PICKUP_TIP_LABWARE_ID' const PRIMARY_PIPETTE_ID = 'PRIMARY_PIPETTE_ID' -const mockLabwarePositionCheckStepTipRack = { +const MOCK_SECTIONS = ['PRIMARY_PIPETTE_TIPRACKS' as Section] + +const MOCK_LABWARE_POSITION_CHECK_STEP_TIPRACK = { labwareId: '1d57fc10-67ad-11ea-9f8b-3b50068bd62d:opentrons/opentrons_96_filtertiprack_200ul/1', section: '', @@ -41,19 +53,39 @@ describe('GenericStepScreen', () => { beforeEach(() => { props = { - selectedStep: mockLabwarePositionCheckStepTipRack, + selectedStep: MOCK_LABWARE_POSITION_CHECK_STEP_TIPRACK, setCurrentLabwareCheckStep: () => {}, } when(mockLabwarePositionCheckStepDetail) .calledWith( partialComponentPropsMatcher({ - selectedStep: mockLabwarePositionCheckStepTipRack, + selectedStep: MOCK_LABWARE_POSITION_CHECK_STEP_TIPRACK, }) ) .mockReturnValue(
Mock Labware Position Check Step Detail
) + + mockSectionList.mockReturnValue(
Mock SectionList
) + when(mockUseIntroInfo).calledWith().mockReturnValue({ + primaryTipRackSlot: '1', + primaryTipRackName: 'Opentrons 96 Filter Tip Rack 200 µL', + primaryPipetteMount: 'left', + secondaryPipetteMount: '', + numberOfTips: 1, + firstStepLabwareSlot: '2', + sections: MOCK_SECTIONS, + }) }) it('renders LabwarePositionCheckStepDetail component', () => { const { getByText } = render(props) expect(getByText('Mock Labware Position Check Step Detail')).toBeTruthy() }) + it('renders GenericStepScreenNav component', () => { + const { getByText } = render(props) + getByText('Mock SectionList') + }) + it('renders null if useIntroInfo is null', () => { + mockUseIntroInfo.mockReturnValue(null) + const { container } = render(props) + expect(container.firstChild).toBeNull() + }) }) diff --git a/app/src/organisms/ProtocolSetup/LabwarePositionCheck/__tests__/IntroScreen.test.tsx b/app/src/organisms/ProtocolSetup/LabwarePositionCheck/__tests__/IntroScreen.test.tsx index 9e576a475f7..4866d0956b5 100644 --- a/app/src/organisms/ProtocolSetup/LabwarePositionCheck/__tests__/IntroScreen.test.tsx +++ b/app/src/organisms/ProtocolSetup/LabwarePositionCheck/__tests__/IntroScreen.test.tsx @@ -11,14 +11,14 @@ import standardDeckDef from '@opentrons/shared-data/deck/definitions/2/ot2_stand import { LabwareDefinition2 } from '@opentrons/shared-data' import fixture_tiprack_300_ul from '@opentrons/shared-data/labware/fixtures/2/fixture_tiprack_300_ul.json' import { useModuleRenderInfoById, useLabwareRenderInfoById } from '../../hooks' -import { PositionCheckNav } from '../PositionCheckNav' +import { SectionList } from '../SectionList' import { useIntroInfo, useLabwareIdsBySection } from '../hooks' import { IntroScreen, INTERVAL_MS } from '../IntroScreen' import type { Section } from '../types' import { fireEvent } from '@testing-library/dom' jest.mock('../hooks') -jest.mock('../PositionCheckNav') +jest.mock('../SectionList') jest.mock('../../hooks') jest.mock('@opentrons/components', () => { const actualComponents = jest.requireActual('@opentrons/components') @@ -42,9 +42,7 @@ const mockUseIntroInfo = useIntroInfo as jest.MockedFunction< typeof useIntroInfo > const mockUseInterval = useInterval as jest.MockedFunction -const mockPositionCheckNav = PositionCheckNav as jest.MockedFunction< - typeof PositionCheckNav -> +const mockSectionList = SectionList as jest.MockedFunction const mockRobotWorkSpace = RobotWorkSpace as jest.MockedFunction< typeof RobotWorkSpace > @@ -107,7 +105,7 @@ describe('IntroScreen', () => { firstStepLabwareSlot: '2', sections: MOCK_SECTIONS, }) - mockPositionCheckNav.mockReturnValue(
Mock Position Check Nav
) + mockSectionList.mockReturnValue(
Mock Section List
) }) afterEach(() => { resetAllWhenMocks() @@ -125,7 +123,7 @@ describe('IntroScreen', () => { getByText( 'When you check a labware, the OT-2’s pipette nozzle or attached tip will stop at the center of the A1 well. If the pipette nozzle or tip is not centered, you can reveal the OT-2’s jog controls to make an adjustment. This Labware Offset will be applied to the entire labware. Offset data is measured to the nearest 1/10th mm and can be made in the X, Y and/or Z directions.' ) - getByText('Mock Position Check Nav') + getByText('Mock Section List') }) it('should call setCurrentLabwareCheckStep when the CTA button is pressed', () => { const { getByRole } = render(props) diff --git a/app/src/organisms/ProtocolSetup/LabwarePositionCheck/__tests__/SectionList.test.tsx b/app/src/organisms/ProtocolSetup/LabwarePositionCheck/__tests__/SectionList.test.tsx new file mode 100644 index 00000000000..6cdde906bbc --- /dev/null +++ b/app/src/organisms/ProtocolSetup/LabwarePositionCheck/__tests__/SectionList.test.tsx @@ -0,0 +1,94 @@ +import { renderWithProviders } from '@opentrons/components' +import * as React from 'react' +import { i18n } from '../../../../i18n' +import { SectionList } from '../SectionList' +import { Section } from '../types' + +const MOCK_SECTIONS_1_PIPETTE_2_STEPS = [ + 'PRIMARY_PIPETTE_TIPRACKS', + 'RETURN_TIP', +] as Section[] +const MOCK_SECTIONS_2_PIPETTES_3_STEPS = [ + 'PRIMARY_PIPETTE_TIPRACKS', + 'SECONDARY_PIPETTE_TIPRACKS', + 'RETURN_TIP', +] as Section[] +const MOCK_SECTIONS_2_PIPETTES_4_STEPS = [ + 'PRIMARY_PIPETTE_TIPRACKS', + 'SECONDARY_PIPETTE_TIPRACKS', + 'CHECK_REMAINING_LABWARE_WITH_PRIMARY_PIPETTE', + 'RETURN_TIP', +] as Section[] + +const render = (props: React.ComponentProps) => { + return renderWithProviders(, { + i18nInstance: i18n, + })[0] +} + +describe('SectionList', () => { + let props: React.ComponentProps + + beforeEach(() => { + props = { + sections: MOCK_SECTIONS_1_PIPETTE_2_STEPS, + currentSection: 'PRIMARY_PIPETTE_TIPRACKS', + primaryPipetteMount: 'left', + secondaryPipetteMount: '', + } + }) + it('renders a 2 step Nav with 1 pipette', () => { + const { getByText } = render(props) + expect(getByText('1')).toHaveStyle('backgroundColor: C_SELECTED_DARK') + getByText('Check tipracks with Left Pipette') + expect(getByText('2')).toHaveStyle('backgroundColor: C_DISABLED') + getByText('Return tip') + }) + it('renders a 3 step Nav with 2 pipettes', () => { + props = { + sections: MOCK_SECTIONS_2_PIPETTES_3_STEPS, + currentSection: 'PRIMARY_PIPETTE_TIPRACKS', + primaryPipetteMount: 'left', + secondaryPipetteMount: 'right', + } + const { getByText } = render(props) + expect(getByText('1')).toHaveStyle('backgroundColor: C_SELECTED_DARK') + getByText('Check tipracks with Left Pipette') + expect(getByText('2')).toHaveStyle('backgroundColor: C_DISABLED') + getByText('Check tipracks with Right Pipette') + expect(getByText('3')).toHaveStyle('backgroundColor: C_DISABLED') + getByText('Return tip') + }) + it('renders a 4 step Nav with 2 pipettes', () => { + props = { + sections: MOCK_SECTIONS_2_PIPETTES_4_STEPS, + currentSection: 'PRIMARY_PIPETTE_TIPRACKS', + primaryPipetteMount: 'left', + secondaryPipetteMount: 'right', + } + const { getByText } = render(props) + expect(getByText('1')).toHaveStyle('backgroundColor: C_SELECTED_DARK') + getByText('Check tipracks with Left Pipette') + expect(getByText('2')).toHaveStyle('backgroundColor: C_DISABLED') + getByText('Check tipracks with Right Pipette') + expect(getByText('3')).toHaveStyle('backgroundColor: C_DISABLED') + getByText('Check remaining labware with Left Pipette') + expect(getByText('4')).toHaveStyle('backgroundColor: C_DISABLED') + getByText('Return tip') + }) + it('renders a 3 step Nav with 2 pipettes and on the second step', () => { + props = { + sections: MOCK_SECTIONS_2_PIPETTES_3_STEPS, + currentSection: 'SECONDARY_PIPETTE_TIPRACKS', + primaryPipetteMount: 'left', + secondaryPipetteMount: 'right', + completedSections: ['PRIMARY_PIPETTE_TIPRACKS'], + } + const { getByText } = render(props) + getByText('Check tipracks with Left Pipette') + expect(getByText('2')).toHaveStyle('backgroundColor: C_SELECTED_DARK') + getByText('Check tipracks with Right Pipette') + expect(getByText('3')).toHaveStyle('backgroundColor: C_DISABLED') + getByText('Return tip') + }) +}) diff --git a/app/src/organisms/ProtocolSetup/LabwarePositionCheck/index.tsx b/app/src/organisms/ProtocolSetup/LabwarePositionCheck/index.tsx index ccbf517f46c..0b7b1f3e498 100644 --- a/app/src/organisms/ProtocolSetup/LabwarePositionCheck/index.tsx +++ b/app/src/organisms/ProtocolSetup/LabwarePositionCheck/index.tsx @@ -20,8 +20,6 @@ export const LabwarePositionCheck = ( const [currentLabwareCheckStep, setCurrentLabwareCheckStep] = React.useState< number | null >(null) - // placeholder for next steps - console.log(currentLabwareCheckStep) return (