From 03668be6843201a6704ecae2549eb91f47070ba6 Mon Sep 17 00:00:00 2001 From: Jethary Rader <66035149+jerader@users.noreply.github.com> Date: Fri, 6 Oct 2023 08:51:32 -0400 Subject: [PATCH] feat(protocol-designer): wire up loadFixture for waste chute in fileCreator (#13716) closes RAUT-687 RAUT-723 --- .../file-data/__tests__/createFile.test.ts | 5 +- .../src/file-data/selectors/fileCreator.ts | 36 +++++++++++- .../src/step-forms/reducers/index.ts | 58 +++++++++++++++---- protocol-designer/typings/reselect.d.ts | 10 +++- 4 files changed, 93 insertions(+), 16 deletions(-) diff --git a/protocol-designer/src/file-data/__tests__/createFile.test.ts b/protocol-designer/src/file-data/__tests__/createFile.test.ts index a8181c017d5..d7b1d0bebe3 100644 --- a/protocol-designer/src/file-data/__tests__/createFile.test.ts +++ b/protocol-designer/src/file-data/__tests__/createFile.test.ts @@ -83,7 +83,10 @@ describe('createFile selector', () => { v7Fixture.moduleEntities, pipetteEntities, labwareNicknamesById, - labwareDefsByURI + labwareDefsByURI, + // TODO(jr, 10/3/23): add additionalEquipmentEntities when the schemaV7 supports + // loadFixture + {} ) expectResultToMatchSchema(result) diff --git a/protocol-designer/src/file-data/selectors/fileCreator.ts b/protocol-designer/src/file-data/selectors/fileCreator.ts index 5fdd4561e43..b7761db26a5 100644 --- a/protocol-designer/src/file-data/selectors/fileCreator.ts +++ b/protocol-designer/src/file-data/selectors/fileCreator.ts @@ -12,6 +12,7 @@ import { FLEX_STANDARD_DECKID, PipetteName, SPAN7_8_10_11_SLOT, + Cutout, } from '@opentrons/shared-data' import { getFileMetadata, getRobotType } from './fileFields' import { getInitialRobotState, getRobotStateTimeline } from './commands' @@ -37,6 +38,7 @@ import type { LabwareEntities, PipetteEntities, RobotState, + AdditionalEquipmentEntity, } from '@opentrons/step-generation' import type { CreateCommand, @@ -47,7 +49,9 @@ import type { LoadLabwareCreateCommand, LoadModuleCreateCommand, LoadPipetteCreateCommand, + LoadFixtureCreateCommand, } from '@opentrons/shared-data/protocol/types/schemaV7/command/setup' +import { getAdditionalEquipmentEntities } from '../../step-forms/selectors' // TODO: BC: 2018-02-21 uncomment this assert, causes test failures // assert(!isEmpty(process.env.OT_PD_VERSION), 'Could not find application version!') if (isEmpty(process.env.OT_PD_VERSION)) @@ -100,6 +104,7 @@ export const createFile: Selector = createSelector( stepFormSelectors.getPipetteEntities, uiLabwareSelectors.getLabwareNicknamesById, labwareDefSelectors.getLabwareDefsByURI, + getAdditionalEquipmentEntities, ( fileMetadata, @@ -115,7 +120,8 @@ export const createFile: Selector = createSelector( moduleEntities, pipetteEntities, labwareNicknamesById, - labwareDefsByURI + labwareDefsByURI, + additionalEquipmentEntities ) => { const { author, description, created } = fileMetadata const name = fileMetadata.protocolName || 'untitled' @@ -265,7 +271,8 @@ export const createFile: Selector = createSelector( key: uuid(), commandType: 'loadLabware' as const, params: { - displayName: def.metadata.displayName, + displayName: + labwareNicknamesById[labwareId] ?? def.metadata.displayName, labwareId: labwareId, loadName, namespace: namespace, @@ -283,6 +290,30 @@ export const createFile: Selector = createSelector( [] ) + // TODO(jr, 10/3/23): add staging area, standard slot, and trash bin loadFixtures + const loadFixtureCommands = reduce< + AdditionalEquipmentEntity, + LoadFixtureCreateCommand[] + >( + Object.values(additionalEquipmentEntities), + (acc, additionalEquipment): LoadFixtureCreateCommand[] => { + if (additionalEquipment.name === 'gripper') return acc + + const loadFixtureCommands = { + key: uuid(), + commandType: 'loadFixture' as const, + params: { + fixtureId: additionalEquipment.id, + location: { cutout: additionalEquipment.location as Cutout }, + loadName: additionalEquipment.name, + }, + } + + return [...acc, loadFixtureCommands] + }, + [] + ) + const loadLiquidCommands = getLoadLiquidCommands( ingredients, ingredLocations @@ -315,6 +346,7 @@ export const createFile: Selector = createSelector( labwareDefsByURI ) const loadCommands: CreateCommand[] = [ + ...loadFixtureCommands, ...loadPipetteCommands, ...loadModuleCommands, ...loadAdapterCommands, diff --git a/protocol-designer/src/step-forms/reducers/index.ts b/protocol-designer/src/step-forms/reducers/index.ts index bf879c30118..8d881bf638d 100644 --- a/protocol-designer/src/step-forms/reducers/index.ts +++ b/protocol-designer/src/step-forms/reducers/index.ts @@ -19,6 +19,10 @@ import { MAGNETIC_MODULE_V1, PipetteName, THERMOCYCLER_MODULE_TYPE, + LoadFixtureCreateCommand, + STAGING_AREA_LOAD_NAME, + STANDARD_SLOT_LOAD_NAME, + TRASH_BIN_LOAD_NAME, } from '@opentrons/shared-data' import type { RootState as LabwareDefsRootState } from '../../labware-defs' import { rootReducer as labwareDefsRootReducer } from '../../labware-defs' @@ -1309,23 +1313,57 @@ export const additionalEquipmentInvariantProperties = handleActions { const { file } = action.payload - const gripper = Object.values(file.commands).filter( + const gripperCommands = Object.values(file.commands).filter( (command): command is MoveLabwareCreateCommand => command.commandType === 'moveLabware' && command.params.strategy === 'usingGripper' ) - // TODO(jr, 9/18/23): add wasteChute when loadFixture commands exist - const hasGripper = gripper.length > 0 - const isOt3 = file.robot.model === FLEX_ROBOT_TYPE - const additionalEquipmentId = `${uuid()}:gripper` - const updatedEquipment = { - [additionalEquipmentId]: { + const fixtureCommands = Object.values(file.commands).filter( + (command): command is LoadFixtureCreateCommand => + command.commandType === 'loadFixture' + ) + const fixtures = fixtureCommands.reduce( + ( + acc: NormalizedAdditionalEquipmentById, + command: LoadFixtureCreateCommand + ) => { + const { fixtureId, loadName, location } = command.params + const id = fixtureId ?? '' + // TODO(jr, 10/03/23): filtering out staging area for now + // until it is supported + if ( + loadName === STAGING_AREA_LOAD_NAME || + loadName === STANDARD_SLOT_LOAD_NAME || + loadName === TRASH_BIN_LOAD_NAME + ) { + return acc + } + return { + ...acc, + [id]: { + id: id, + name: loadName, + location: location.cutout, + }, + } + }, + {} + ) + const hasGripper = gripperCommands.length > 0 + const isFlex = file.robot.model === FLEX_ROBOT_TYPE + const gripperId = `${uuid()}:gripper` + const gripper = { + [gripperId]: { name: 'gripper' as const, - id: additionalEquipmentId, + id: gripperId, }, } - if (hasGripper && isOt3) { - return { ...state, ...updatedEquipment } + if (isFlex) { + if (hasGripper) { + return { ...state, ...gripper, ...fixtures } + } else { + return { ...state, ...fixtures } + } } else { return { ...state } } diff --git a/protocol-designer/typings/reselect.d.ts b/protocol-designer/typings/reselect.d.ts index c905b8139c4..b6828c1ba7d 100644 --- a/protocol-designer/typings/reselect.d.ts +++ b/protocol-designer/typings/reselect.d.ts @@ -1,6 +1,6 @@ import { OutputSelector, Selector } from 'reselect' declare module 'reselect' { - // declaring type for createSelector with 14 selectors because the reselect types only support up to 12 selectors + // declaring type for createSelector with 15 selectors because the reselect types only support up to 12 selectors export function createSelector< S, R1, @@ -17,6 +17,7 @@ declare module 'reselect' { R12, R13, R14, + R15, T >( selector1: Selector, @@ -33,6 +34,7 @@ declare module 'reselect' { selector12: Selector, selector13: Selector, selector14: Selector, + selector15: Selector, combiner: ( res1: R1, res2: R2, @@ -47,7 +49,8 @@ declare module 'reselect' { res11: R11, res12: R12, res13: R13, - res14: R14 + res14: R14, + res15: R15 ) => T ): OutputSelector< S, @@ -66,7 +69,8 @@ declare module 'reselect' { res11: R11, res12: R12, res13: R13, - res14: R14 + res14: R14, + res15: R15 ) => T > }