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

feat(app): setup advanced settings/tip management state for quick transfer #15192

Merged
merged 6 commits into from
May 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
18 changes: 11 additions & 7 deletions app/src/organisms/QuickTransferFlow/Overview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ import {
import { ListItem } from '../../atoms/ListItem'
import { CONSOLIDATE, DISTRIBUTE } from './constants'

import type { QuickTransferSetupState } from './types'
import type { QuickTransferSummaryState } from './types'

interface OverviewProps {
state: QuickTransferSetupState
state: QuickTransferSummaryState
}

export function Overview(props: OverviewProps): JSX.Element | null {
Expand All @@ -33,18 +33,22 @@ export function Overview(props: OverviewProps): JSX.Element | null {
const displayItems = [
{
option: t('pipette'),
value: state.pipette?.displayName,
value: state.pipette.displayName,
},
{
option: t('tip_rack'),
value: state.tipRack.metadata.displayName,
},
{
option: t('source_labware'),
value: state.source?.metadata.displayName,
value: state.source.metadata.displayName,
},
{
option: t('destination_labware'),
value:
state.destination === 'source'
? state.source?.metadata.displayName
: state.destination?.metadata.displayName,
? state.source.metadata.displayName
: state.destination.metadata.displayName,
},
{
option: transferCopy,
Expand All @@ -61,7 +65,7 @@ export function Overview(props: OverviewProps): JSX.Element | null {
{displayItems.map(displayItem => (
<ListItem type="noActive" key={displayItem.option}>
<Flex justifyContent={JUSTIFY_SPACE_BETWEEN} width="100%">
<StyledText css={TYPOGRAPHY.level4HeaderSemiBold} width="30rem">
<StyledText css={TYPOGRAPHY.level4HeaderSemiBold} width="20rem">
{displayItem.option}
</StyledText>
<StyledText
Expand Down
4 changes: 2 additions & 2 deletions app/src/organisms/QuickTransferFlow/SelectDestLabware.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@ import type { LabwareDefinition2 } from '@opentrons/shared-data'
import type { SmallButton } from '../../atoms/buttons'
import type { LabwareFilter } from '../../pages/Labware/types'
import type {
QuickTransferSetupState,
QuickTransferWizardState,
QuickTransferWizardAction,
} from './types'

interface SelectDestLabwareProps {
onNext: () => void
onBack: () => void
exitButtonProps: React.ComponentProps<typeof SmallButton>
state: QuickTransferSetupState
state: QuickTransferWizardState
dispatch: React.Dispatch<QuickTransferWizardAction>
}

Expand Down
4 changes: 2 additions & 2 deletions app/src/organisms/QuickTransferFlow/SelectDestWells.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ import { ChildNavigation } from '../ChildNavigation'

import type { SmallButton } from '../../atoms/buttons'
import type {
QuickTransferSetupState,
QuickTransferWizardState,
QuickTransferWizardAction,
} from './types'

interface SelectDestWellsProps {
onNext: () => void
onBack: () => void
exitButtonProps: React.ComponentProps<typeof SmallButton>
state: QuickTransferSetupState
state: QuickTransferWizardState
dispatch: React.Dispatch<QuickTransferWizardAction>
}

Expand Down
4 changes: 2 additions & 2 deletions app/src/organisms/QuickTransferFlow/SelectPipette.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ import { ChildNavigation } from '../ChildNavigation'
import type { PipetteData, Mount } from '@opentrons/api-client'
import type { SmallButton } from '../../atoms/buttons'
import type {
QuickTransferSetupState,
QuickTransferWizardState,
QuickTransferWizardAction,
} from './types'

interface SelectPipetteProps {
onNext: () => void
onBack: () => void
exitButtonProps: React.ComponentProps<typeof SmallButton>
state: QuickTransferSetupState
state: QuickTransferWizardState
dispatch: React.Dispatch<QuickTransferWizardAction>
}

Expand Down
4 changes: 2 additions & 2 deletions app/src/organisms/QuickTransferFlow/SelectSourceLabware.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@ import type { LabwareDefinition2 } from '@opentrons/shared-data'
import type { SmallButton } from '../../atoms/buttons'
import type { LabwareFilter } from '../../pages/Labware/types'
import type {
QuickTransferSetupState,
QuickTransferWizardState,
QuickTransferWizardAction,
} from './types'

interface SelectSourceLabwareProps {
onNext: () => void
onBack: () => void
exitButtonProps: React.ComponentProps<typeof SmallButton>
state: QuickTransferSetupState
state: QuickTransferWizardState
dispatch: React.Dispatch<QuickTransferWizardAction>
}

Expand Down
4 changes: 2 additions & 2 deletions app/src/organisms/QuickTransferFlow/SelectSourceWells.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ import { ChildNavigation } from '../ChildNavigation'

import type { SmallButton } from '../../atoms/buttons'
import type {
QuickTransferSetupState,
QuickTransferWizardState,
QuickTransferWizardAction,
} from './types'

interface SelectSourceWellsProps {
onNext: () => void
onBack: () => void
exitButtonProps: React.ComponentProps<typeof SmallButton>
state: QuickTransferSetupState
state: QuickTransferWizardState
dispatch: React.Dispatch<QuickTransferWizardAction>
}

Expand Down
4 changes: 2 additions & 2 deletions app/src/organisms/QuickTransferFlow/SelectTipRack.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ import { ChildNavigation } from '../ChildNavigation'
import type { LabwareDefinition2 } from '@opentrons/shared-data'
import type { SmallButton } from '../../atoms/buttons'
import type {
QuickTransferSetupState,
QuickTransferWizardState,
QuickTransferWizardAction,
} from './types'

interface SelectTipRackProps {
onNext: () => void
onBack: () => void
exitButtonProps: React.ComponentProps<typeof SmallButton>
state: QuickTransferSetupState
state: QuickTransferWizardState
dispatch: React.Dispatch<QuickTransferWizardAction>
}

Expand Down
17 changes: 13 additions & 4 deletions app/src/organisms/QuickTransferFlow/SummaryAndSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,22 @@ import {
import { TabbedButton } from '../../atoms/buttons'
import { ChildNavigation } from '../ChildNavigation'
import { Overview } from './Overview'
import { getInitialSummaryState } from './utils'
import { quickTransferSummaryReducer } from './reducers'

import type { SmallButton } from '../../atoms/buttons'
import type { QuickTransferSetupState } from './types'
import type { QuickTransferWizardState } from './types'

interface SummaryAndSettingsProps {
onNext: () => void
exitButtonProps: React.ComponentProps<typeof SmallButton>
state: QuickTransferSetupState
state: QuickTransferWizardState
}

export function SummaryAndSettings(
props: SummaryAndSettingsProps
): JSX.Element | null {
const { onNext, exitButtonProps, state } = props
const { onNext, exitButtonProps, state: wizardFlowState } = props
const { t } = useTranslation(['quick_transfer', 'shared'])
const displayCategory: string[] = [
'overview',
Expand All @@ -36,11 +38,18 @@ export function SummaryAndSettings(
const [selectedCategory, setSelectedCategory] = React.useState<string>(
'overview'
)
// @ts-expect-error TODO figure out how to make this type non-null as we know
// none of these values will be undefined
const initialSummaryState = getInitialSummaryState(wizardFlowState)
const [state] = React.useReducer(
quickTransferSummaryReducer,
initialSummaryState
)

return (
<Flex>
<ChildNavigation
header={t('quick_transfer_volume', { volume: state.volume })}
header={t('quick_transfer_volume', { volume: wizardFlowState.volume })}
buttonText={t('create_transfer')}
onClickButton={onNext}
secondaryButtonProps={exitButtonProps}
Expand Down
8 changes: 4 additions & 4 deletions app/src/organisms/QuickTransferFlow/VolumeEntry.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,20 @@ import {
import { ChildNavigation } from '../ChildNavigation'
import { InputField } from '../../atoms/InputField'
import { NumericalKeyboard } from '../../atoms/SoftwareKeyboard'
import { getVolumeLimits } from './utils'
import { getVolumeRange } from './utils'
import { CONSOLIDATE, DISTRIBUTE } from './constants'

import type { SmallButton } from '../../atoms/buttons'
import type {
QuickTransferSetupState,
QuickTransferWizardState,
QuickTransferWizardAction,
} from './types'

interface VolumeEntryProps {
onNext: () => void
onBack: () => void
exitButtonProps: React.ComponentProps<typeof SmallButton>
state: QuickTransferSetupState
state: QuickTransferWizardState
dispatch: React.Dispatch<QuickTransferWizardAction>
}

Expand All @@ -35,7 +35,7 @@ export function VolumeEntry(props: VolumeEntryProps): JSX.Element {
const [volume, setVolume] = React.useState<string>(
state.volume ? state.volume.toString() : ''
)
const volumeRange = getVolumeLimits(state)
const volumeRange = getVolumeRange(state)
let headerCopy = t('set_transfer_volume')
let textEntryCopy = t('volume_per_well_µL')
if (state.transferType === CONSOLIDATE) {
Expand Down
23 changes: 20 additions & 3 deletions app/src/organisms/QuickTransferFlow/__tests__/Overview.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ describe('Overview', () => {
pipette: {
displayName: 'Pipette display name',
} as any,
tipRack: {
metadata: {
displayName: 'Tip rack display name',
},
} as any,
source: {
metadata: {
displayName: 'Source labware name',
Expand All @@ -33,7 +38,7 @@ describe('Overview', () => {
} as any,
transferType: 'transfer',
volume: 25,
},
} as any,
}
})
afterEach(() => {
Expand All @@ -44,6 +49,8 @@ describe('Overview', () => {
render(props)
screen.getByText('Pipette')
screen.getByText('Pipette display name')
screen.getByText('Tip rack')
screen.getByText('Tip rack display name')
screen.getByText('Source labware')
screen.getByText('Source labware name')
screen.getByText('Destination labware')
Expand All @@ -57,6 +64,11 @@ describe('Overview', () => {
pipette: {
displayName: 'Pipette display name',
} as any,
tipRack: {
metadata: {
displayName: 'Tip rack display name',
},
} as any,
source: {
metadata: {
displayName: 'Source labware name',
Expand All @@ -69,7 +81,7 @@ describe('Overview', () => {
} as any,
transferType: 'consolidate',
volume: 25,
},
} as any,
}
render(props)
screen.getByText('Aspirate volume per well')
Expand All @@ -80,6 +92,11 @@ describe('Overview', () => {
pipette: {
displayName: 'Pipette display name',
} as any,
tipRack: {
metadata: {
displayName: 'Tip rack display name',
},
} as any,
source: {
metadata: {
displayName: 'Source labware name',
Expand All @@ -92,7 +109,7 @@ describe('Overview', () => {
} as any,
transferType: 'distribute',
volume: 25,
},
} as any,
}
render(props)
screen.getByText('Dispense volume per well')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ import { SummaryAndSettings } from '../SummaryAndSettings'
import { Overview } from '../Overview'

vi.mock('../Overview')
vi.mock('../utils', async () => {
const actual = await vi.importActual('../utils')
return {
...actual,
getInitialSummaryState: vi.fn(),
}
})

const render = (props: React.ComponentProps<typeof SummaryAndSettings>) => {
return renderWithProviders(<SummaryAndSettings {...props} />, {
Expand All @@ -27,6 +34,14 @@ describe('SummaryAndSettings', () => {
onClick: vi.fn(),
},
state: {
pipette: {} as any,
mount: 'left',
tipRack: {} as any,
source: {} as any,
sourceWells: ['A1'],
destination: {} as any,
destinationWells: ['A1'],
transferType: 'transfer',
volume: 25,
},
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { renderWithProviders } from '../../../__testing-utils__'
import { i18n } from '../../../i18n'
import { InputField } from '../../../atoms/InputField'
import { NumericalKeyboard } from '../../../atoms/SoftwareKeyboard'
import { getVolumeLimits } from '../utils'
import { getVolumeRange } from '../utils'
import { VolumeEntry } from '../VolumeEntry'

vi.mock('../../../atoms/InputField')
Expand Down Expand Up @@ -42,7 +42,7 @@ describe('VolumeEntry', () => {
},
dispatch: vi.fn(),
}
vi.mocked(getVolumeLimits).mockReturnValue({ min: 5, max: 50 })
vi.mocked(getVolumeRange).mockReturnValue({ min: 5, max: 50 })
})
afterEach(() => {
vi.resetAllMocks()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { describe, it, expect } from 'vitest'
import { generateCompatibleLabwareForPipette } from '../../utils'
import {
SINGLE_CHANNEL_COMPATIBLE_LABWARE,
EIGHT_CHANNEL_COMPATIBLE_LABWARE,
NINETY_SIX_CHANNEL_COMPATIBLE_LABWARE,
} from '../../constants'

// if one of these fails, it is likely that a new definition has been added
// and you need to regenerate the lists stored at ../constants
describe('generateCompatibleLabwareForPipette', () => {
it('generates the list for single channel pipettes', () => {
const compatibleLabwareUris = generateCompatibleLabwareForPipette({
channels: 1,
} as any)
expect(compatibleLabwareUris).toEqual(SINGLE_CHANNEL_COMPATIBLE_LABWARE)
})
it('generates the list for eight channel pipettes', () => {
const compatibleLabwareUris = generateCompatibleLabwareForPipette({
channels: 8,
} as any)
expect(compatibleLabwareUris).toEqual(EIGHT_CHANNEL_COMPATIBLE_LABWARE)
})
it('generates the list for 96 channel pipettes', () => {
const compatibleLabwareUris = generateCompatibleLabwareForPipette({
channels: 96,
} as any)
expect(compatibleLabwareUris).toEqual(NINETY_SIX_CHANNEL_COMPATIBLE_LABWARE)
})
})
Loading
Loading