Skip to content

Commit 1cea210

Browse files
authored
feat(app): anonymize pipette wizard flows (#15055)
anonymizes pipette name in ODD pipette wizard flows and firmware update result modal closes PLAT-297
1 parent 044be7a commit 1cea210

File tree

7 files changed

+75
-52
lines changed

7 files changed

+75
-52
lines changed

app/src/organisms/Devices/hooks/__tests__/useAttachedPipettesFromInstrumentsQuery.test.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,22 @@
11
import * as React from 'react'
2-
import { vi, it, expect, describe } from 'vitest'
2+
import { vi, it, expect, describe, beforeEach } from 'vitest'
33
import { renderHook } from '@testing-library/react'
44
import { useInstrumentsQuery } from '@opentrons/react-api-client'
55
import {
66
instrumentsResponseLeftPipetteFixture,
77
instrumentsResponseRightPipetteFixture,
88
} from '@opentrons/api-client'
9+
import { useIsOEMMode } from '../../../../resources/robot-settings/hooks'
910
import { useAttachedPipettesFromInstrumentsQuery } from '..'
1011

1112
vi.mock('@opentrons/react-api-client')
13+
vi.mock('../../../../resources/robot-settings/hooks')
1214

1315
describe('useAttachedPipettesFromInstrumentsQuery hook', () => {
16+
beforeEach(() => {
17+
vi.mocked(useIsOEMMode).mockReturnValue(false)
18+
})
19+
1420
let wrapper: React.FunctionComponent<{ children: React.ReactNode }>
1521
it('returns attached pipettes', () => {
1622
vi.mocked(useInstrumentsQuery).mockReturnValue({
Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,43 @@
11
import { useInstrumentsQuery } from '@opentrons/react-api-client'
2-
import { getPipetteModelSpecs, PipetteModel } from '@opentrons/shared-data'
2+
import { LEFT, RIGHT } from '@opentrons/shared-data'
3+
import { usePipetteModelSpecs } from '../../../resources/instruments/hooks'
4+
35
import type { PipetteData } from '@opentrons/api-client'
46
import type { Mount } from '@opentrons/components'
7+
import type { PipetteModel } from '@opentrons/shared-data'
58

69
export interface PipetteInformation extends PipetteData {
710
displayName: string
811
}
912
export type AttachedPipettesFromInstrumentsQuery = {
1013
[mount in Mount]: null | PipetteInformation
1114
}
12-
1315
export function useAttachedPipettesFromInstrumentsQuery(): AttachedPipettesFromInstrumentsQuery {
14-
const { data: attachedInstruments } = useInstrumentsQuery()
15-
return (attachedInstruments?.data ?? []).reduce(
16-
(acc, instrumentData) => {
17-
if (instrumentData.instrumentType !== 'pipette' || !instrumentData.ok) {
18-
return acc
19-
}
20-
const { mount, instrumentModel } = instrumentData
21-
return {
22-
...acc,
23-
[mount as Mount]: {
24-
...instrumentData,
25-
displayName:
26-
instrumentModel != null
27-
? getPipetteModelSpecs(instrumentModel as PipetteModel)
28-
?.displayName ?? ''
29-
: '',
30-
},
31-
}
32-
},
33-
{ left: null, right: null }
16+
const attachedInstruments = useInstrumentsQuery()?.data?.data ?? []
17+
18+
const okPipettes = attachedInstruments.filter(
19+
(instrument): instrument is PipetteData =>
20+
instrument.instrumentType === 'pipette' && instrument.ok
3421
)
22+
23+
const leftPipette = okPipettes.find(({ mount }) => mount === LEFT) ?? null
24+
const rightPipette = okPipettes.find(({ mount }) => mount === RIGHT) ?? null
25+
26+
const leftDisplayName =
27+
usePipetteModelSpecs(leftPipette?.instrumentModel as PipetteModel)
28+
?.displayName ?? ''
29+
const rightDisplayName =
30+
usePipetteModelSpecs(rightPipette?.instrumentModel as PipetteModel)
31+
?.displayName ?? ''
32+
33+
return {
34+
[LEFT]:
35+
leftPipette != null
36+
? { ...leftPipette, displayName: leftDisplayName }
37+
: null,
38+
[RIGHT]:
39+
rightPipette != null
40+
? { ...rightPipette, displayName: rightDisplayName }
41+
: null,
42+
}
3543
}

app/src/organisms/FirmwareUpdateModal/UpdateResultsModal.tsx

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import * as React from 'react'
22
import { useTranslation, Trans } from 'react-i18next'
3-
import { getPipetteModelSpecs } from '@opentrons/shared-data'
43
import {
54
ALIGN_CENTER,
65
BORDERS,
@@ -14,8 +13,9 @@ import {
1413
} from '@opentrons/components'
1514
import { SmallButton } from '../../atoms/buttons'
1615
import { Modal } from '../../molecules/Modal'
16+
import { usePipetteModelSpecs } from '../../resources/instruments/hooks'
1717

18-
import type { InstrumentData } from '@opentrons/api-client'
18+
import type { InstrumentData, PipetteData } from '@opentrons/api-client'
1919
import type { ModalHeaderBaseProps } from '../../molecules/Modal/types'
2020

2121
interface UpdateResultsModalProps {
@@ -36,12 +36,16 @@ export function UpdateResultsModal(
3636
iconName: 'ot-alert',
3737
iconColor: COLORS.red50,
3838
}
39+
40+
const pipetteDisplayName = usePipetteModelSpecs(
41+
(instrument as PipetteData)?.instrumentModel
42+
)?.displayName
43+
3944
let instrumentName = 'instrument'
4045
if (instrument?.ok) {
4146
instrumentName =
4247
instrument?.instrumentType === 'pipette'
43-
? getPipetteModelSpecs(instrument.instrumentModel)?.displayName ??
44-
'pipette'
48+
? pipetteDisplayName ?? 'pipette'
4549
: 'Flex Gripper'
4650
}
4751
return (

app/src/organisms/InstrumentMountItem/LabeledMount.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ interface LabeledMountProps {
4040
export function LabeledMount(props: LabeledMountProps): JSX.Element {
4141
const { t } = useTranslation('device_details')
4242
const { mount, instrumentName, handleClick } = props
43-
const ninetySixDisplayName = 'Flex 96-Channel 1000 μL'
43+
const isNinetySixChannel = instrumentName?.includes('96-Channel') ?? false
4444

4545
return (
4646
<MountButton onClick={handleClick} isAttached={instrumentName != null}>
@@ -62,9 +62,7 @@ export function LabeledMount(props: LabeledMountProps): JSX.Element {
6262
fontSize={TYPOGRAPHY.fontSize28}
6363
width="15.625rem"
6464
>
65-
{instrumentName === ninetySixDisplayName
66-
? t('left_right')
67-
: t('mount', { side: mount })}
65+
{isNinetySixChannel ? t('left_right') : t('mount', { side: mount })}
6866
</StyledText>
6967
<StyledText
7068
flex="5"

app/src/organisms/PipetteWizardFlows/BeforeBeginning.tsx

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,14 @@ import {
1313
RIGHT,
1414
SINGLE_MOUNT_PIPETTES,
1515
WEIGHT_OF_96_CHANNEL,
16-
LoadedPipette,
17-
getPipetteNameSpecs,
1816
WASTE_CHUTE_CUTOUT,
1917
} from '@opentrons/shared-data'
2018
import { Banner } from '../../atoms/Banner'
2119
import { SimpleWizardBody } from '../../molecules/SimpleWizardBody'
2220
import { GenericWizardTile } from '../../molecules/GenericWizardTile'
2321
import { InProgressModal } from '../../molecules/InProgressModal/InProgressModal'
2422
import { WizardRequiredEquipmentList } from '../../molecules/WizardRequiredEquipmentList'
23+
import { usePipetteNameSpecs } from '../../resources/instruments/hooks'
2524
import {
2625
CALIBRATION_PROBE,
2726
FLOWS,
@@ -35,7 +34,11 @@ import { getIsGantryEmpty } from './utils'
3534
import { useNotifyDeckConfigurationQuery } from '../../resources/deck_configuration'
3635

3736
import type { AxiosError } from 'axios'
38-
import type { CreateCommand } from '@opentrons/shared-data'
37+
import type {
38+
CreateCommand,
39+
LoadedPipette,
40+
PipetteName,
41+
} from '@opentrons/shared-data'
3942
import type {
4043
CreateMaintenanceRunData,
4144
MaintenanceRun,
@@ -90,6 +93,10 @@ export const BeforeBeginning = (
9093
deckConfig?.find(fixture => fixture.cutoutId === WASTE_CHUTE_CUTOUT) ??
9194
false
9295

96+
const pipetteDisplayName = usePipetteNameSpecs(
97+
requiredPipette?.pipetteName as PipetteName
98+
)?.displayName
99+
93100
if (
94101
pipetteId == null &&
95102
(flowType === FLOWS.CALIBRATE || flowType === FLOWS.DETACH)
@@ -109,9 +116,7 @@ export const BeforeBeginning = (
109116
bodyTranslationKey = 'remove_labware'
110117
let displayName: string | undefined
111118
if (requiredPipette != null) {
112-
displayName =
113-
getPipetteNameSpecs(requiredPipette.pipetteName)?.displayName ??
114-
requiredPipette.pipetteName
119+
displayName = pipetteDisplayName ?? requiredPipette.pipetteName
115120
}
116121
if (selectedPipette === SINGLE_MOUNT_PIPETTES) {
117122
equipmentList = [
@@ -134,9 +139,7 @@ export const BeforeBeginning = (
134139
}
135140
case FLOWS.DETACH: {
136141
if (requiredPipette != null) {
137-
const displayName =
138-
getPipetteNameSpecs(requiredPipette.pipetteName)?.displayName ??
139-
requiredPipette.pipetteName
142+
const displayName = pipetteDisplayName ?? requiredPipette.pipetteName
140143
bodyTranslationKey = 'remove_labware'
141144

142145
if (requiredPipette.pipetteName === 'p1000_96') {

app/src/organisms/PipetteWizardFlows/Results.tsx

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,19 @@ import {
1212
StyledText,
1313
TYPOGRAPHY,
1414
} from '@opentrons/components'
15-
import {
16-
getPipetteNameSpecs,
17-
LEFT,
18-
RIGHT,
19-
LoadedPipette,
20-
MotorAxes,
21-
NINETY_SIX_CHANNEL,
22-
} from '@opentrons/shared-data'
15+
import { LEFT, RIGHT, NINETY_SIX_CHANNEL } from '@opentrons/shared-data'
16+
import { SmallButton } from '../../atoms/buttons'
2317
import { InProgressModal } from '../../molecules/InProgressModal/InProgressModal'
2418
import { SimpleWizardBody } from '../../molecules/SimpleWizardBody'
25-
import { SmallButton } from '../../atoms/buttons'
19+
import { usePipetteNameSpecs } from '../../resources/instruments/hooks'
2620
import { CheckPipetteButton } from './CheckPipetteButton'
2721
import { FLOWS } from './constants'
22+
23+
import type {
24+
LoadedPipette,
25+
MotorAxes,
26+
PipetteName,
27+
} from '@opentrons/shared-data'
2828
import type { PipetteWizardStepProps } from './types'
2929

3030
interface ResultsProps extends PipetteWizardStepProps {
@@ -71,10 +71,11 @@ export const Results = (props: ResultsProps): JSX.Element => {
7171
const isCorrectPipette =
7272
requiredPipette != null &&
7373
requiredPipette.pipetteName === attachedPipettes[mount]?.instrumentName
74+
7475
const requiredPipDisplayName =
75-
requiredPipette != null
76-
? getPipetteNameSpecs(requiredPipette.pipetteName)?.displayName
77-
: null
76+
usePipetteNameSpecs(requiredPipette?.pipetteName as PipetteName)
77+
?.displayName ?? null
78+
7879
const [numberOfTryAgains, setNumberOfTryAgains] = React.useState<number>(0)
7980
let header: string = 'unknown results screen'
8081
let iconColor: string = COLORS.green50

app/src/organisms/PipetteWizardFlows/__tests__/Results.test.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { useInstrumentsQuery } from '@opentrons/react-api-client'
1212

1313
import { renderWithProviders } from '../../../__testing-utils__'
1414
import { mockAttachedPipetteInformation } from '../../../redux/pipettes/__fixtures__'
15+
import { useIsOEMMode } from '../../../resources/robot-settings/hooks'
1516
import { i18n } from '../../../i18n'
1617
import { RUN_ID_1 } from '../../RunTimeControl/__fixtures__'
1718
import { Results } from '../Results'
@@ -20,6 +21,7 @@ import { FLOWS } from '../constants'
2021
import type { Mock } from 'vitest'
2122

2223
vi.mock('@opentrons/react-api-client')
24+
vi.mock('../../../resources/robot-settings/hooks')
2325

2426
const render = (props: React.ComponentProps<typeof Results>) => {
2527
return renderWithProviders(<Results {...props} />, {
@@ -57,6 +59,7 @@ describe('Results', () => {
5759
vi.mocked(useInstrumentsQuery).mockReturnValue({
5860
refetch: mockRefetchInstruments,
5961
} as any)
62+
vi.mocked(useIsOEMMode).mockReturnValue(false)
6063
})
6164
it('renders the correct information when pipette cal is a success for calibrate flow', () => {
6265
props = {

0 commit comments

Comments
 (0)