Skip to content

Commit

Permalink
feat(app): implement useCalibrationTaskList hook (#11894)
Browse files Browse the repository at this point in the history
* WIP: some scaffolding of files and refactoring of reused types

* fix some pipette model type discrepancies, refactor some task list related types to be reusable

* feat(app): implement useGenerateTaskList hook

useGenerateTaskList is a hook that aggregates deck calibrations and tip length and offset
calibrations for attached pipettes then builds the taskList object that is passed to the TaskList
component as props

closes RAUT-291

* use i18n for task text

* add namespace prefixes to i18 translations

* fix an active index bug, simplify some logic

* typo and linting fixes

* add tests for useGenerateTaskList hook

* increase patch code coverage numbers

* add test coverage for tip length calibration active index

* adjust mock pipette name in device utils test to satisfy typechecker

* update get offsetcalibrationForMount mock pipette model

* rename hook to useCalibrationTaskList

* fix type errors in pipette wizard flows tests
  • Loading branch information
jgbowser committed Jan 5, 2023
1 parent 4de19cf commit d1660b5
Show file tree
Hide file tree
Showing 12 changed files with 782 additions and 37 deletions.
7 changes: 7 additions & 0 deletions app/src/assets/localization/en/robot_calibration.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"attached_pipettes": "attached pipette calibrations",
"before_you_begin": "Before you begin",
"calibrate": "Calibrate",
"calibrate_deck": "calibrate deck",
"calibration_dashboard": "Calibration Dashboard",
"calibration_status": "Calibration Status",
Expand All @@ -14,6 +15,7 @@
"calibration_block_description": "<block>This block is a specially made tool that fits perfectly on your deck and helps with calibration. If you do not have a Calibration Block, please <supportLink>contact us</supportLink> so we can send you one.</block><block>While you wait for the block to arrive, you can use the flat surface on the trash bin of your robot instead.</block>",
"calibration_health_check": "Calibration Health Check",
"calibration_health_check_intro_body": "<block>Calibration Health Check diagnoses problems with Deck, Tip Length, and Pipette Offset Calibration.</block><block>You will move the pipettes to various positions, which will be compared against your existing calibration data.</block><block>If there is a large difference, you will be prompted to redo some or all of your calibrations.</block>",
"calibrate_tip_length": "Calibrate the length of a tip on this pipette.",
"change_tip_rack": "Change tip rack",
"check_tip_on_block": "Check tip on block",
"check_tip_on_trash": "Check tip on trash bin",
Expand Down Expand Up @@ -55,6 +57,7 @@
"jump_size": "jump size",
"large": "Large",
"last_calibrated": "Last calibrated",
"last_completed_on": "Last completed {{timestamp}}",
"last_migrated": "Last known calibration migrated",
"launch_calibration": "Launch calibration",
"manage_pipettes": "manage pipettes",
Expand All @@ -63,7 +66,9 @@
"no_pipette": "No pipette attached",
"no_tip_length": "Calibrate your pipette to see saved tip length",
"pick_up_tip": "Pick up tip",
"pipette_name_and_serial": "{{name}}, {{serial}}",
"pipette_offset_calibration": "Pipette Offset Calibration",
"pipette_offset_calibration_on_mount": "Calibrate this pipette's offset while attached to the robot's {{mount}} mount.",
"pipette_offset_description": "Calibrate the position for the the default tip and pipette combination.",
"pipette_offset_calibration_intro_body": "Calibrating pipette offset measures a pipette’s position relative to the pipette mount and the deck.",
"pipette_offset_requires_tip_length": "You don’t have a tip length saved with this pipette yet. You will need to calibrate tip length before calibrating your pipette offset.",
Expand All @@ -73,6 +78,7 @@
"position_pipette_over_tip": "Position pipette over A1",
"prepare_the_space": "Prepare the space",
"progress_will_be_lost": "{{sessionType}} progress will be lost",
"recalibrate": "Recalibrate",
"recalibrate_warning_body": "Performing a deck calibration will clear all of your pipette offset and tip length calibrations. You will need to recalibrate your pipette offset and tip length after completing a deck calibration.",
"recalibrate_warning_heading": "Are you sure you want to recalibrate your deck?",
"see_how_robot_calibration_works": "See how robot calibration works",
Expand All @@ -81,6 +87,7 @@
"starting_over_loses_progress": "Starting over will cancel your calibration progress.",
"start_over": "Start over",
"start_over_question": "Start over?",
"start_with_deck_calibration": "Start with Deck Calibration, which is the basis for the rest of calibration.",
"tiny": "Tiny",
"tip_length": "tip length calibration",
"tip_length_and_pipette_offset_calibration": "Tip Length and Pipette Offset Calibration",
Expand Down
4 changes: 2 additions & 2 deletions app/src/organisms/Devices/__tests__/utils.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ describe('getIs96ChannelPipetteAttached hook', () => {

it('returns false when there is no 96 channel pipette attached on the left mount', () => {
const mockLeftMountAttachedPipette = {
name: 'mock single channel',
name: 'p10_single_v1',
} as FetchPipettesResponsePipette

const result = getIs96ChannelPipetteAttached(mockLeftMountAttachedPipette)
Expand Down Expand Up @@ -99,7 +99,7 @@ describe('getOffsetCalibrationForMount', () => {
right: {
id: pipette,
name: `test-${pipette}`,
model: 'test model',
model: 'p10_single_v1',
tip_length: 0,
mount_axis: 'z',
plunger_axis: 'a',
Expand Down
242 changes: 242 additions & 0 deletions app/src/organisms/Devices/hooks/__fixtures__/taskListFixtures.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,242 @@
import { formatTimestamp } from '../../utils'

import { PipetteModelSpecs } from '@opentrons/shared-data'
import {
DeckCalibrationInfo,
TipLengthCalibration,
PipetteOffsetCalibration,
} from '../../../../redux/calibration/api-types'
import { AttachedPipettesByMount } from '../../../../redux/pipettes/types'
import { TaskListProps } from '../../../TaskList/types'

export const TASK_COUNT = 3

export const mockAttachedPipettesResponse: AttachedPipettesByMount = {
left: {
id: 'test-left',
name: 'test-left-name',
tip_length: 0,
mount_axis: 'x',
plunger_axis: 'z',
model: 'p1000_single_v1',
modelSpecs: {
displayName: 'Test Left Display Name',
} as PipetteModelSpecs,
},
right: {
id: 'test-right',
name: 'test-right-name',
tip_length: 0,
mount_axis: 'x',
plunger_axis: 'z',
model: 'p1000_single_v1',
modelSpecs: {
displayName: 'Test Right Display Name',
} as PipetteModelSpecs,
},
}

export const mockSingleAttachedPipetteResponse: AttachedPipettesByMount = {
left: {
id: 'test-left',
name: 'test-left-name',
tip_length: 0,
mount_axis: 'x',
plunger_axis: 'z',
model: 'p1000_single_v1',
modelSpecs: {
displayName: 'Test Left Display Name',
} as PipetteModelSpecs,
},
right: null,
}

export const mockCompleteDeckCalibration = {
isDeckCalibrated: true,
deckCalibrationData: {
lastModified: '2022-01-01T12:00:00.000000+00:00',
} as DeckCalibrationInfo,
}

export const mockIncompleteDeckCalibration = {
isDeckCalibrated: false,
deckCalibrationData: null,
}

export const mockCompleteTipLengthCalibrations: TipLengthCalibration[] = [
{
tipLength: 0,
lastModified: '2022-01-02T12:00:00.000000+00:00',
tiprack: 'test_tip_rack',
pipette: 'test-left',
source: 'user',
status: { markedBad: false, source: null, markedAt: null },
id: 'test-tip-length-id-1',
},
{
tipLength: 0,
lastModified: '2022-01-03T12:00:00.000000+00:00',
tiprack: 'test_tip_rack',
pipette: 'test-right',
source: 'user',
status: { markedBad: false, source: null, markedAt: null },
id: 'test-tip-length-id-2',
},
]

export const mockIncompleteTipLengthCalibrations: TipLengthCalibration[] = [
{
tipLength: 0,
lastModified: '2022-01-03T12:00:00.000000+00:00',
tiprack: 'test_tip_rack',
pipette: 'test-right',
source: 'user',
status: { markedBad: false, source: null, markedAt: null },
id: 'test-tip-length-id-2',
},
]

export const mockCompletePipetteOffsetCalibrations: PipetteOffsetCalibration[] = [
{
pipette: 'test-left',
mount: 'left',
offset: [0, 0, 0],
tiprack: 'test-tip-rack',
tiprackUri: 'test/tiprack/uri',
lastModified: '2022-01-04T12:00:00,000000+00:00',
source: 'user',
status: { markedBad: false, markedAt: null, source: null },
id: 'test-offset-id-1',
},
{
pipette: 'test-right',
mount: 'right',
offset: [0, 0, 0],
tiprack: 'test-tip-rack',
tiprackUri: 'test/tiprack/uri',
lastModified: '2022-01-05T12:00:00,000000+00:00',
source: 'user',
status: { markedBad: false, markedAt: null, source: null },
id: 'test-offset-id-2',
},
]

export const mockIncompletePipetteOffsetCalibrations: PipetteOffsetCalibration[] = [
{
pipette: 'test-left',
mount: 'left',
offset: [0, 0, 0],
tiprack: 'test-tip-rack',
tiprackUri: 'test/tiprack/uri',
lastModified: '2022-01-04T12:00:00,000000+00:00',
source: 'user',
status: { markedBad: false, markedAt: null, source: null },
id: 'test-offset-id-1',
},
{
pipette: 'test-right',
mount: 'right',
offset: [0, 0, 0],
tiprack: 'test-tip-rack',
tiprackUri: 'test/tiprack/uri',
lastModified: '2022-01-05T12:00:00,000000+00:00',
source: 'user',
status: { markedBad: true, markedAt: null, source: null },
id: 'test-offset-id-2',
},
]

export const expectedTaskList: TaskListProps = {
activeIndex: null,
taskList: [
// deck calibration task
{
subTasks: [],
taskListLength: TASK_COUNT,
activeIndex: null,
description: '',
title: 'Deck Calibration',
footer: `Last completed ${formatTimestamp(
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
mockCompleteDeckCalibration.deckCalibrationData.lastModified!
)}`,
cta: { label: 'Recalibrate', onClick: () => {} },
isComplete: true,
taskIndex: 0,
},
// left mount calibration task
{
subTasks: [
// tip length calibration subtask
{
activeIndex: null,
description: '',
title: 'Tip Length Calibration',
footer: `Last completed ${formatTimestamp(
mockCompleteTipLengthCalibrations[0].lastModified
)}`,
cta: { label: 'Recalibrate', onClick: () => {} },
isComplete: true,
taskIndex: 1,
subTaskIndex: 0,
},
// offset calibration subtask
{
activeIndex: null,
description: '',
title: 'Pipette Offset Calibration',
footer: `Last completed ${formatTimestamp(
mockCompletePipetteOffsetCalibrations[0].lastModified
)}`,
cta: { label: 'Recalibrate', onClick: () => {} },
isComplete: true,
taskIndex: 1,
subTaskIndex: 1,
},
],
isComplete: true,
taskListLength: TASK_COUNT,
activeIndex: null,
description: 'Test Left Display Name, test-left',
title: 'Left Mount',
taskIndex: 1,
},
// right mount calibration task
{
subTasks: [
// tip length calibration subtask
{
activeIndex: null,
description: '',
title: 'Tip Length Calibration',
footer: `Last completed ${formatTimestamp(
mockCompleteTipLengthCalibrations[1].lastModified
)}`,
cta: { label: 'Recalibrate', onClick: () => {} },
isComplete: true,
taskIndex: 2,
subTaskIndex: 0,
},
// offset calibration subtask
{
activeIndex: null,
description: '',
title: 'Pipette Offset Calibration',
footer: `Last completed ${formatTimestamp(
mockCompletePipetteOffsetCalibrations[1].lastModified
)}`,
cta: { label: 'Recalibrate', onClick: () => {} },
isComplete: true,
taskIndex: 2,
subTaskIndex: 1,
},
],
isComplete: true,
taskListLength: TASK_COUNT,
activeIndex: null,
description: 'Test Right Display Name, test-right',
title: 'Right Mount',
taskIndex: 2,
},
],
}
Loading

0 comments on commit d1660b5

Please sign in to comment.