diff --git a/app/src/assets/localization/en/run_details.json b/app/src/assets/localization/en/run_details.json
index a785feb6658..0c27a4dc232 100644
--- a/app/src/assets/localization/en/run_details.json
+++ b/app/src/assets/localization/en/run_details.json
@@ -44,6 +44,7 @@
"cancel_run_module_info": "Additionally, any hardware modules used within the protocol will remain active and maintain their current states until deactivated.",
"protocol_setup": "Protocol Setup",
"load_pipette_protocol_setup": "Load {{pipette_name}} in {{mount_name}} Mount",
+ "load_liquids_info_protocol_setup": "Load {{liquid}} into {{labware}}",
"load_modules_protocol_setup": "Load {{module}} in Slot {{slot_name}}",
"load_modules_protocol_setup_plural": "Load {{module}}",
"load_labware_info_protocol_setup_no_module": "Load {{labware_loadname}} v{{labware_version}} in Slot {{slot_number}}",
@@ -128,5 +129,15 @@
"latching_hs_latch": "Latching labware on Heater-Shaker",
"deactivate_hs_shake": "Deactivating shaker",
"wait_for_duration": "Pause for {{seconds}} seconds",
- "tc_run_profile_steps": "temperature: {{celsius}}°C, seconds: {{seconds}}"
+ "tc_run_profile_steps": "temperature: {{celsius}}°C, seconds: {{seconds}}",
+ "aspirate": "Aspirating {{volume}} uL from {{well_name}} of {{labware}} in {{labware_location}} at {{flow_rate}} uL/sec",
+ "dispense": "Dispensing {{volume}} uL into {{well_name}} of {{labware}} in {{labware_location}} at {{flow_rate}} uL/sec",
+ "blowout": "Blowing out at {{well_name}} of {{labware}} in {{labware_location}} at {{flow_rate}} uL/sec",
+ "touch_tip": "Touching tip",
+ "move_to_slot": "Moving to {{slot_name}}",
+ "move_to_well": "Moving to {{well_name}} of {{labware}} in {{labware_location}}",
+ "move_relative": "Moving {{distance}} mm along {{axis}} axis",
+ "move_to_coordinates": "Moving to (X: {{x}}, Y: {{y}}, Z: {{z}})",
+ "home_gantry": "Homing all gantry, pipette, and plunger axes",
+ "save_position": "Saving position"
}
diff --git a/app/src/organisms/Devices/ProtocolRun/RunLogProtocolSetupInfo.tsx b/app/src/organisms/Devices/ProtocolRun/RunLogProtocolSetupInfo.tsx
index 685bde166f3..97a370e49b9 100644
--- a/app/src/organisms/Devices/ProtocolRun/RunLogProtocolSetupInfo.tsx
+++ b/app/src/organisms/Devices/ProtocolRun/RunLogProtocolSetupInfo.tsx
@@ -2,10 +2,18 @@ import * as React from 'react'
import { Trans, useTranslation } from 'react-i18next'
import { SPACING } from '@opentrons/components'
-import { getModuleDisplayName } from '@opentrons/shared-data'
+import {
+ getModuleDisplayName,
+ getLabwareDisplayName,
+} from '@opentrons/shared-data'
+import { parseLiquidsInLoadOrder } from '@opentrons/api-client'
import { StyledText } from '../../../atoms/text'
-import { useProtocolDetailsForRun, useRunPipetteInfoByMount } from '../hooks'
+import {
+ useProtocolDetailsForRun,
+ useRunPipetteInfoByMount,
+ useLabwareRenderInfoForRunById,
+} from '../hooks'
import type { RunCommandSummary } from '@opentrons/api-client'
import type { Mount } from '@opentrons/components'
@@ -26,6 +34,7 @@ export const RunLogProtocolSetupInfo = ({
const { t } = useTranslation('run_details')
const { protocolData } = useProtocolDetailsForRun(runId)
const protocolPipetteData = useRunPipetteInfoByMount(robotName, runId)
+ const labwareRenderInfoById = useLabwareRenderInfoForRunById(runId)
if (protocolData == null) return null
if (setupCommand === undefined) return null
@@ -123,6 +132,25 @@ export const RunLogProtocolSetupInfo = ({
}}
/>
)
+ } else if (setupCommand.commandType === 'loadLiquid') {
+ const liquidInfo = parseLiquidsInLoadOrder()
+ const { liquidId, labwareId } = setupCommand.params
+ const liquidDisplayName = liquidInfo.find(
+ liquid => liquid.liquidId === liquidId
+ )?.displayName
+ setupCommandText = (
+
+ )
}
return (
diff --git a/app/src/organisms/Devices/ProtocolRun/StepText.tsx b/app/src/organisms/Devices/ProtocolRun/StepText.tsx
index 67d76a27dee..3e369e7459b 100644
--- a/app/src/organisms/Devices/ProtocolRun/StepText.tsx
+++ b/app/src/organisms/Devices/ProtocolRun/StepText.tsx
@@ -1,8 +1,7 @@
import * as React from 'react'
-import { Trans, useTranslation } from 'react-i18next'
+import { useTranslation } from 'react-i18next'
import { Flex, ALIGN_CENTER, SPACING, TYPOGRAPHY } from '@opentrons/components'
import { getLabwareDisplayName } from '@opentrons/shared-data'
-
import { StyledText } from '../../../atoms/text'
import { getLabwareLocation } from '../ProtocolRun/utils/getLabwareLocation'
import {
@@ -72,24 +71,18 @@ export function StepText(props: Props): JSX.Element | null {
if (!('slotName' in labwareLocation)) {
throw new Error('expected tip rack to be in a slot')
}
- messageNode = (
-
- )
+ messageNode = t('drop_tip', {
+ well_name: wellName,
+ labware:
+ labwareId === TRASH_ID
+ ? 'Opentrons Fixed Trash'
+ : getLabwareDisplayName(
+ protocolData.labwareDefinitions[
+ protocolData.labware[labwareId].definitionId
+ ]
+ ),
+ labware_location: labwareLocation.slotName,
+ })
break
}
case 'pickUpTip': {
@@ -101,19 +94,13 @@ export function StepText(props: Props): JSX.Element | null {
if (!('slotName' in labwareLocation)) {
throw new Error('expected tip rack to be in a slot')
}
- messageNode = (
-
- )
+ messageNode = t('pickup_tip', {
+ well_name: wellName,
+ labware: getLabwareDisplayName(
+ labwareRenderInfoById[labwareId].labwareDef
+ ),
+ labware_location: labwareLocation.slotName,
+ })
break
}
case 'pause':
@@ -123,7 +110,8 @@ export function StepText(props: Props): JSX.Element | null {
}
case 'loadLabware':
case 'loadPipette':
- case 'loadModule': {
+ case 'loadModule':
+ case 'loadLiquid': {
messageNode = (
{
})
getByText('Pause for 60 seconds')
})
+ it('renders correct command text for aspirate', () => {
+ const labwareId = 'labwareId'
+ when(mockGetLabwareDisplayName)
+ .calledWith('fake_def' as any)
+ .mockReturnValue('fake_display_name')
+ when(mockGetLabwareLocation)
+ .calledWith(labwareId, [])
+ .mockReturnValue({ slotName: 'fake_labware_location' })
+ mockUseLabwareRenderInfoForRunById.mockReturnValue({
+ labwareId: {
+ labwareDef: 'fake_def',
+ },
+ } as any)
+ const { getByText } = render({
+ robotName: ROBOT_NAME,
+ runId: RUN_ID,
+ analysisCommand: null,
+ runCommand: {
+ ...MOCK_COMMAND_SUMMARY,
+ commandType: 'aspirate',
+ params: {
+ volume: 100,
+ flowRate: 130,
+ wellName: 'wellName',
+ labwareId: 'labwareId',
+ },
+ },
+ })
+ getByText(
+ 'Aspirating 100 uL from wellName of fake_display_name in fake_labware_location at 130 uL/sec'
+ )
+ })
+ it('renders correct command text for dispense', () => {
+ const labwareId = 'labwareId'
+ when(mockGetLabwareDisplayName)
+ .calledWith('fake_def' as any)
+ .mockReturnValue('fake_display_name')
+ when(mockGetLabwareLocation)
+ .calledWith(labwareId, [])
+ .mockReturnValue({ slotName: 'fake_labware_location' })
+ mockUseLabwareRenderInfoForRunById.mockReturnValue({
+ labwareId: {
+ labwareDef: 'fake_def',
+ },
+ } as any)
+ const { getByText } = render({
+ robotName: ROBOT_NAME,
+ runId: RUN_ID,
+ analysisCommand: null,
+ runCommand: {
+ ...MOCK_COMMAND_SUMMARY,
+ commandType: 'dispense',
+ params: {
+ volume: 100,
+ flowRate: 130,
+ wellName: 'wellName',
+ labwareId: 'labwareId',
+ },
+ },
+ })
+ getByText(
+ 'Dispensing 100 uL into wellName of fake_display_name in fake_labware_location at 130 uL/sec'
+ )
+ })
+ it('renders correct command text for blowout', () => {
+ const labwareId = 'labwareId'
+ when(mockGetLabwareDisplayName)
+ .calledWith('fake_def' as any)
+ .mockReturnValue('fake_display_name')
+ when(mockGetLabwareLocation)
+ .calledWith(labwareId, [])
+ .mockReturnValue({ slotName: 'fake_labware_location' })
+ mockUseLabwareRenderInfoForRunById.mockReturnValue({
+ labwareId: {
+ labwareDef: 'fake_def',
+ },
+ } as any)
+ const { getByText } = render({
+ robotName: ROBOT_NAME,
+ runId: RUN_ID,
+ analysisCommand: null,
+ runCommand: {
+ ...MOCK_COMMAND_SUMMARY,
+ commandType: 'blowout',
+ params: {
+ flowRate: 130,
+ wellName: 'wellName',
+ labwareId: 'labwareId',
+ },
+ },
+ })
+ getByText(
+ 'Blowing out at wellName of fake_display_name in fake_labware_location at 130 uL/sec'
+ )
+ })
+ it('renders correct command text for touchTip', () => {
+ const { getByText } = render({
+ robotName: ROBOT_NAME,
+ runId: RUN_ID,
+ analysisCommand: null,
+ runCommand: {
+ ...MOCK_COMMAND_SUMMARY,
+ commandType: 'touchTip',
+ },
+ })
+ getByText('Touching tip')
+ })
+ it('renders correct command text for moveToSlot', () => {
+ const { getByText } = render({
+ robotName: ROBOT_NAME,
+ runId: RUN_ID,
+ analysisCommand: null,
+ runCommand: {
+ ...MOCK_COMMAND_SUMMARY,
+ commandType: 'moveToSlot',
+ params: { slotName: 'slot 5' },
+ },
+ })
+ getByText('Moving to slot 5')
+ })
+ it('renders correct command text for moveToWell', () => {
+ const labwareId = 'labwareId'
+ when(mockGetLabwareDisplayName)
+ .calledWith('fake_def' as any)
+ .mockReturnValue('fake_display_name')
+ when(mockGetLabwareLocation)
+ .calledWith(labwareId, [])
+ .mockReturnValue({ slotName: 'fake_labware_location' })
+ mockUseLabwareRenderInfoForRunById.mockReturnValue({
+ labwareId: {
+ labwareDef: 'fake_def',
+ },
+ } as any)
+ const { getByText } = render({
+ robotName: ROBOT_NAME,
+ runId: RUN_ID,
+ analysisCommand: null,
+ runCommand: {
+ ...MOCK_COMMAND_SUMMARY,
+ commandType: 'moveToWell',
+ params: {
+ wellName: 'wellName',
+ labwareId: 'labwareId',
+ },
+ },
+ })
+ getByText(
+ 'Moving to wellName of fake_display_name in fake_labware_location'
+ )
+ })
+ it('renders correct command text for moveRelative', () => {
+ const { getByText } = render({
+ robotName: ROBOT_NAME,
+ runId: RUN_ID,
+ analysisCommand: null,
+ runCommand: {
+ ...MOCK_COMMAND_SUMMARY,
+ commandType: 'moveRelative',
+ params: { distance: '4', axis: 'y' },
+ },
+ })
+ getByText('Moving 4 mm along y axis')
+ })
+ it('renders correct command text for moveToCoordinates', () => {
+ const { getByText } = render({
+ robotName: ROBOT_NAME,
+ runId: RUN_ID,
+ analysisCommand: null,
+ runCommand: {
+ ...MOCK_COMMAND_SUMMARY,
+ commandType: 'moveToCoordinates',
+ params: { coordinates: { x: '4', y: '5', z: '2' } },
+ },
+ })
+ getByText('Moving to (X: 4, Y: 5, Z: 2)')
+ })
+
+ it('renders correct command text for home', () => {
+ const { getByText } = render({
+ robotName: ROBOT_NAME,
+ runId: RUN_ID,
+ analysisCommand: null,
+ runCommand: {
+ ...MOCK_COMMAND_SUMMARY,
+ commandType: 'home',
+ params: {
+ axes: ['x', 'y', 'leftZ', 'rightZ', 'leftPLunger', 'rightPlunger'],
+ },
+ },
+ })
+ getByText('Homing all gantry, pipette, and plunger axes')
+ })
+
+ it('renders correct command text for savingPosition', () => {
+ const { getByText } = render({
+ robotName: ROBOT_NAME,
+ runId: RUN_ID,
+ analysisCommand: null,
+ runCommand: {
+ ...MOCK_COMMAND_SUMMARY,
+ commandType: 'savePosition',
+ params: {
+ pipetteId: 'pipetteId',
+ },
+ },
+ })
+ getByText('Saving position')
+ })
})
diff --git a/robot-server/simulators/test.json b/robot-server/simulators/test.json
index 0a75ffa5dc6..6c08374a67a 100644
--- a/robot-server/simulators/test.json
+++ b/robot-server/simulators/test.json
@@ -54,4 +54,4 @@
}
]
}
-}
\ No newline at end of file
+}