Skip to content

Commit

Permalink
refactor(app): refactor CommandText
Browse files Browse the repository at this point in the history
Decouple the logic that generates command text from the component that renders it.
  • Loading branch information
mjhuff committed Jul 17, 2024
1 parent 67097d7 commit 75aea30
Show file tree
Hide file tree
Showing 28 changed files with 919 additions and 566 deletions.
491 changes: 94 additions & 397 deletions app/src/molecules/Command/CommandText.tsx

Large diffs are not rendered by default.

70 changes: 0 additions & 70 deletions app/src/molecules/Command/MoveLabwareCommandText.tsx

This file was deleted.

7 changes: 7 additions & 0 deletions app/src/molecules/Command/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export { useCommandTextString } from './useCommandTextString'

export type {
UseCommandTextStringParams,
GetCommandText,
GetCommandTextResult,
} from './useCommandTextString'
220 changes: 220 additions & 0 deletions app/src/molecules/Command/hooks/useCommandTextString/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
import { useTranslation } from 'react-i18next'
import * as utils from './utils'

import type { TFunction } from 'i18next'
import type { RunTimeCommand } from '@opentrons/shared-data/command'
import type { RobotType } from '@opentrons/shared-data/lib/js'
import type { CommandTextData } from '../../types'

export interface UseCommandTextStringParams {
command: RunTimeCommand | null
commandTextData: CommandTextData | null
robotType: RobotType
}

export type GetCommandText = UseCommandTextStringParams & { t: TFunction }
export interface GetCommandTextResult {
/* The actual command text. Ex "Homing all gantry, pipette, and plunger axes" */
commandText: string
/* The TC run profile steps. */
stepTexts?: string[]
}

// TODO(jh, 07-18-24): Move the testing that covers this from CommandText to a new file, and verify that all commands are
// properly tested.

// Get the full user-facing command text string from a given command.
export function useCommandTextString(
params: UseCommandTextStringParams
): GetCommandTextResult {
const { command } = params
const { t } = useTranslation('protocol_command_text')

const fullParams = { ...params, t }

switch (command?.commandType) {
case 'touchTip':
case 'home':
case 'savePosition':
case 'magneticModule/engage':
case 'magneticModule/disengage':
case 'temperatureModule/deactivate':
case 'thermocycler/waitForBlockTemperature':
case 'thermocycler/waitForLidTemperature':
case 'thermocycler/openLid':
case 'thermocycler/closeLid':
case 'thermocycler/deactivateBlock':
case 'thermocycler/deactivateLid':
case 'thermocycler/awaitProfileComplete':
case 'heaterShaker/deactivateHeater':
case 'heaterShaker/openLabwareLatch':
case 'heaterShaker/closeLabwareLatch':
case 'heaterShaker/deactivateShaker':
case 'heaterShaker/waitForTemperature':
return {
commandText: utils.getDirectTranslationCommandText(fullParams),
}

case 'aspirate':
case 'aspirateInPlace':
case 'dispense':
case 'dispenseInPlace':
case 'blowout':
case 'blowOutInPlace':
case 'dropTip':
case 'dropTipInPlace':
case 'pickUpTip':
return {
commandText: utils.getPipettingCommandText(fullParams),
}

case 'loadLabware':
case 'loadPipette':
case 'loadModule':
case 'loadLiquid':
return {
commandText: utils.getLoadCommandText(fullParams),
}

case 'temperatureModule/setTargetTemperature':
case 'temperatureModule/waitForTemperature':
case 'thermocycler/setTargetBlockTemperature':
case 'thermocycler/setTargetLidTemperature':
case 'heaterShaker/setTargetTemperature':
return {
commandText: utils.getTemperatureCommandText({
...fullParams,
command,
}),
}

case 'thermocycler/runProfile':
return utils.getTCRunProfileCommandText({ ...fullParams, command })

case 'heaterShaker/setAndWaitForShakeSpeed':
return {
commandText: utils.getHSShakeSpeedCommandText({
...fullParams,
command,
}),
}

case 'moveToSlot':
return {
commandText: utils.getMoveToSlotCommandText({ ...fullParams, command }),
}

case 'moveRelative':
return {
commandText: utils.getMoveRelativeCommandText({
...fullParams,
command,
}),
}

case 'moveToCoordinates':
return {
commandText: utils.getMoveToCoordinatesCommandText({
...fullParams,
command,
}),
}

case 'moveToWell':
return {
commandText: utils.getMoveToWellCommandText({ ...fullParams, command }),
}

case 'moveLabware':
return {
commandText: utils.getMoveLabwareCommandText({
...fullParams,
command,
}),
}

case 'configureForVolume':
return {
commandText: utils.getConfigureForVolumeCommandText({
...fullParams,
command,
}),
}

case 'configureNozzleLayout':
return {
commandText: utils.getConfigureNozzleLayoutCommandText({
...fullParams,
command,
}),
}

case 'prepareToAspirate':
return {
commandText: utils.getPrepareToAspirateCommandText({
...fullParams,
command,
}),
}

case 'moveToAddressableArea':
return {
commandText: utils.getMoveToAddressableAreaCommandText({
...fullParams,
command,
}),
}

case 'moveToAddressableAreaForDropTip':
return {
commandText: utils.getMoveToAddressableAreaForDropTipCommandText({
...fullParams,
command,
}),
}

case 'waitForDuration':
return {
commandText: utils.getWaitForDurationCommandText({
...fullParams,
command,
}),
}

case 'pause': // legacy pause command
case 'waitForResume':
return {
commandText: utils.getWaitForResumeCommandText({
...fullParams,
command,
}),
}

case 'delay':
return {
commandText: utils.getDelayCommandText({ ...fullParams, command }),
}

case 'comment':
return {
commandText: utils.getCommentCommandText({ ...fullParams, command }),
}

case 'custom':
return {
commandText: utils.getCustomCommandText({ ...fullParams, command }),
}

case null:
return { commandText: '' }

default:
console.warn(
'CommandText encountered a command with an unrecognized commandType: ',
command
)
return {
commandText: utils.getUnknownCommandText({ ...fullParams, command }),
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import type { CommentRunTimeCommand } from '@opentrons/shared-data/command'
import type { GetCommandText } from '..'

type GetCommentCommandText = Omit<GetCommandText, 'command'> & {
command: CommentRunTimeCommand
}

export function getCommentCommandText({
command,
}: GetCommentCommandText): string {
const { message } = command.params

return message
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { getPipetteNameSpecs } from '@opentrons/shared-data'

import type { ConfigureForVolumeRunTimeCommand } from '@opentrons/shared-data/command'
import type { GetCommandText } from '..'

type GetConfigureForVolumeCommandText = Omit<GetCommandText, 'command'> & {
command: ConfigureForVolumeRunTimeCommand
}

export function getConfigureForVolumeCommandText({
command,
commandTextData,
t,
}: GetConfigureForVolumeCommandText): string {
const { volume, pipetteId } = command.params
const pipetteName = commandTextData?.pipettes.find(
pip => pip.id === pipetteId
)?.pipetteName

return t('configure_for_volume', {
volume,
pipette:
pipetteName != null ? getPipetteNameSpecs(pipetteName)?.displayName : '',
})
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { getPipetteNameSpecs } from '@opentrons/shared-data'

import type { ConfigureNozzleLayoutRunTimeCommand } from '@opentrons/shared-data/command'
import type { GetCommandText } from '..'

type GetConfigureNozzleLayoutCommandText = Omit<GetCommandText, 'command'> & {
command: ConfigureNozzleLayoutRunTimeCommand
}

export function getConfigureNozzleLayoutCommandText({
command,
commandTextData,
t,
}: GetConfigureNozzleLayoutCommandText): string {
const { configurationParams, pipetteId } = command.params
const pipetteName = commandTextData?.pipettes.find(
pip => pip.id === pipetteId
)?.pipetteName

return t('configure_nozzle_layout', {
amount: configurationParams.style === 'COLUMN' ? '8' : 'all',
pipette:
pipetteName != null ? getPipetteNameSpecs(pipetteName)?.displayName : '',
})
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import type { CustomRunTimeCommand } from '@opentrons/shared-data/command'
import type { GetCommandText } from '..'

type GetCustomCommandText = Omit<GetCommandText, 'command'> & {
command: CustomRunTimeCommand
}

export function getCustomCommandText({
command,
}: GetCustomCommandText): string {
const { legacyCommandText } = command.params ?? {}
const sanitizedCommandText =
typeof legacyCommandText === 'object'
? JSON.stringify(legacyCommandText)
: String(legacyCommandText)

return legacyCommandText != null
? sanitizedCommandText
: `${command.commandType}: ${JSON.stringify(command.params)}`
}
Loading

0 comments on commit 75aea30

Please sign in to comment.