From 0a201de94327276489ea7a314b04a7d5089f5eb3 Mon Sep 17 00:00:00 2001 From: Brent Hagen <brent.hagen@opentrons.com> Date: Mon, 13 Nov 2023 17:49:48 -0500 Subject: [PATCH] update add fixture modal --- .../AddFixtureModal.tsx | 69 +++++++++---------- .../DeviceDetailsDeckConfiguration/index.tsx | 41 ++++++----- .../ProtocolSetupDeckConfiguration/index.tsx | 14 ++-- app/src/pages/DeckConfiguration/index.tsx | 34 +++++---- .../hardware-sim/DeckConfigurator/index.tsx | 16 ++--- shared-data/js/constants.ts | 28 +++++++- shared-data/js/fixtures.ts | 27 ++++++-- 7 files changed, 138 insertions(+), 91 deletions(-) diff --git a/app/src/organisms/DeviceDetailsDeckConfiguration/AddFixtureModal.tsx b/app/src/organisms/DeviceDetailsDeckConfiguration/AddFixtureModal.tsx index 3c37d6497ca..c3f62f4dd2a 100644 --- a/app/src/organisms/DeviceDetailsDeckConfiguration/AddFixtureModal.tsx +++ b/app/src/organisms/DeviceDetailsDeckConfiguration/AddFixtureModal.tsx @@ -18,9 +18,11 @@ import { useUpdateDeckConfigurationMutation } from '@opentrons/react-api-client' import { getCutoutDisplayName, getFixtureDisplayName, - STAGING_AREA_LOAD_NAME, - TRASH_BIN_LOAD_NAME, - WASTE_CHUTE_LOAD_NAME, + STAGING_AREA_CUTOUTS, + STAGING_AREA_RIGHT_SLOT_FIXTURE, + TRASH_BIN_ADAPTER_FIXTURE, + WASTE_CHUTE_CUTOUT, + WASTE_CHUTE_FIXTURES, } from '@opentrons/shared-data' import { StyledText } from '../../atoms/text' @@ -30,25 +32,24 @@ import { Modal } from '../../molecules/Modal' import { LegacyModal } from '../../molecules/LegacyModal' import type { - Cutout, + CutoutConfig, + CutoutId, + CutoutFixtureId, DeckConfiguration, - Fixture, - FixtureLoadName, } from '@opentrons/shared-data' import type { ModalHeaderBaseProps } from '../../molecules/Modal/types' import type { LegacyModalProps } from '../../molecules/LegacyModal' -import { CutoutConfig } from '../../resources/deck_configuration/utils' interface AddFixtureModalProps { - fixtureLocation: Cutout + cutoutId: CutoutId setShowAddFixtureModal: (showAddFixtureModal: boolean) => void setCurrentDeckConfig?: React.Dispatch<React.SetStateAction<CutoutConfig[]>> - providedFixtureOptions?: FixtureLoadName[] + providedFixtureOptions?: CutoutFixtureId[] isOnDevice?: boolean } export function AddFixtureModal({ - fixtureLocation, + cutoutId, setShowAddFixtureModal, setCurrentDeckConfig, providedFixtureOptions, @@ -59,7 +60,7 @@ export function AddFixtureModal({ const modalHeader: ModalHeaderBaseProps = { title: t('add_to_slot', { - slotName: getCutoutDisplayName(fixtureLocation), + slotName: getCutoutDisplayName(cutoutId), }), hasExitIcon: true, onClick: () => setShowAddFixtureModal(false), @@ -67,7 +68,7 @@ export function AddFixtureModal({ const modalProps: LegacyModalProps = { title: t('add_to_slot', { - slotName: getCutoutDisplayName(fixtureLocation), + slotName: getCutoutDisplayName(cutoutId), }), onClose: () => setShowAddFixtureModal(false), closeOnOutsideClick: true, @@ -75,26 +76,22 @@ export function AddFixtureModal({ width: '23.125rem', } - const availableFixtures: FixtureLoadName[] = [TRASH_BIN_LOAD_NAME] - if ( - fixtureLocation === 'cutoutA3' || - fixtureLocation === 'cutoutB3' || - fixtureLocation === 'cutoutC3' - ) { - availableFixtures.push(STAGING_AREA_LOAD_NAME) + const availableFixtures: CutoutFixtureId[] = [TRASH_BIN_ADAPTER_FIXTURE] + if (STAGING_AREA_CUTOUTS.includes(cutoutId)) { + availableFixtures.push(STAGING_AREA_RIGHT_SLOT_FIXTURE) } - if (fixtureLocation === 'cutoutD3') { - availableFixtures.push(STAGING_AREA_LOAD_NAME, WASTE_CHUTE_LOAD_NAME) + if (cutoutId === WASTE_CHUTE_CUTOUT) { + availableFixtures.push(...WASTE_CHUTE_FIXTURES) } // For Touchscreen app - const handleTapAdd = (fixtureLoadName: FixtureLoadName): void => { + const handleTapAdd = (requiredFixtureId: CutoutFixtureId): void => { if (setCurrentDeckConfig != null) setCurrentDeckConfig( (prevDeckConfig: DeckConfiguration): DeckConfiguration => - prevDeckConfig.map((fixture: Fixture) => - fixture.fixtureLocation === fixtureLocation - ? { ...fixture, loadName: fixtureLoadName } + prevDeckConfig.map((fixture: CutoutConfig) => + fixture.cutoutId === cutoutId + ? { ...fixture, cutoutFixtureId: requiredFixtureId } : fixture ) ) @@ -105,10 +102,10 @@ export function AddFixtureModal({ // For Desktop app const fixtureOptions = providedFixtureOptions ?? availableFixtures - const handleClickAdd = (fixtureLoadName: FixtureLoadName): void => { + const handleClickAdd = (requiredFixtureId: CutoutFixtureId): void => { updateDeckConfiguration({ - fixtureLocation, - loadName: fixtureLoadName, + cutoutId, + cutoutFixtureId: requiredFixtureId, }) setShowAddFixtureModal(false) } @@ -123,10 +120,10 @@ export function AddFixtureModal({ <Flex flexDirection={DIRECTION_COLUMN} gridGap={SPACING.spacing32}> <StyledText as="p">{t('add_to_slot_description')}</StyledText> <Flex flexDirection={DIRECTION_COLUMN} gridGap={SPACING.spacing8}> - {fixtureOptions.map(fixture => ( - <React.Fragment key={fixture}> + {fixtureOptions.map(cutoutFixtureId => ( + <React.Fragment key={cutoutFixtureId}> <AddFixtureButton - fixtureLoadName={fixture} + cutoutFixtureId={cutoutFixtureId} handleClickAdd={handleTapAdd} /> </React.Fragment> @@ -167,18 +164,18 @@ export function AddFixtureModal({ } interface AddFixtureButtonProps { - fixtureLoadName: FixtureLoadName - handleClickAdd: (fixtureLoadName: FixtureLoadName) => void + cutoutFixtureId: CutoutFixtureId + handleClickAdd: (cutoutFixtureId: CutoutFixtureId) => void } function AddFixtureButton({ - fixtureLoadName, + cutoutFixtureId, handleClickAdd, }: AddFixtureButtonProps): JSX.Element { const { t } = useTranslation('device_details') return ( <Btn - onClick={() => handleClickAdd(fixtureLoadName)} + onClick={() => handleClickAdd(cutoutFixtureId)} display="flex" justifyContent={JUSTIFY_SPACE_BETWEEN} flexDirection={DIRECTION_ROW} @@ -187,7 +184,7 @@ function AddFixtureButton({ css={FIXTURE_BUTTON_STYLE} > <StyledText as="p" fontWeight={TYPOGRAPHY.fontWeightSemiBold}> - {getFixtureDisplayName(fixtureLoadName)} + {getFixtureDisplayName(cutoutFixtureId)} </StyledText> <StyledText as="p">{t('add')}</StyledText> </Btn> diff --git a/app/src/organisms/DeviceDetailsDeckConfiguration/index.tsx b/app/src/organisms/DeviceDetailsDeckConfiguration/index.tsx index c57cef374f8..feafa3d2c2a 100644 --- a/app/src/organisms/DeviceDetailsDeckConfiguration/index.tsx +++ b/app/src/organisms/DeviceDetailsDeckConfiguration/index.tsx @@ -24,7 +24,10 @@ import { import { getCutoutDisplayName, getFixtureDisplayName, - STANDARD_SLOT_LOAD_NAME, + SINGLE_RIGHT_CUTOUTS, + SINGLE_SLOT_FIXTURES, + SINGLE_LEFT_SLOT_FIXTURE, + SINGLE_RIGHT_SLOT_FIXTURE, } from '@opentrons/shared-data' import { StyledText } from '../../atoms/text' @@ -33,7 +36,7 @@ import { DeckFixtureSetupInstructionsModal } from './DeckFixtureSetupInstruction import { AddFixtureModal } from './AddFixtureModal' import { useRunStatuses } from '../Devices/hooks' -import type { Cutout } from '@opentrons/shared-data' +import type { CutoutId } from '@opentrons/shared-data' const RUN_REFETCH_INTERVAL = 5000 @@ -52,10 +55,9 @@ export function DeviceDetailsDeckConfiguration({ const [showAddFixtureModal, setShowAddFixtureModal] = React.useState<boolean>( false ) - const [ - targetFixtureLocation, - setTargetFixtureLocation, - ] = React.useState<Cutout | null>(null) + const [targetCutoutId, setTargetCutoutId] = React.useState<CutoutId | null>( + null + ) const deckConfig = useDeckConfigurationQuery().data ?? [] const { updateDeckConfiguration } = useUpdateDeckConfigurationMutation() @@ -65,29 +67,32 @@ export function DeviceDetailsDeckConfiguration({ }) const isMaintenanceRunExisting = maintenanceRunData?.data?.id != null - const handleClickAdd = (fixtureLocation: Cutout): void => { - setTargetFixtureLocation(fixtureLocation) + const handleClickAdd = (cutoutId: CutoutId): void => { + setTargetCutoutId(cutoutId) setShowAddFixtureModal(true) } - const handleClickRemove = (fixtureLocation: Cutout): void => { - console.log('remove fixtureLocation', fixtureLocation) + const handleClickRemove = (cutoutId: CutoutId): void => { updateDeckConfiguration({ - fixtureLocation, - loadName: STANDARD_SLOT_LOAD_NAME, + cutoutId, + cutoutFixtureId: SINGLE_RIGHT_CUTOUTS.includes(cutoutId) + ? SINGLE_RIGHT_SLOT_FIXTURE + : SINGLE_LEFT_SLOT_FIXTURE, }) } // do not show standard slot in fixture display list const fixtureDisplayList = deckConfig.filter( - fixture => fixture.loadName !== STANDARD_SLOT_LOAD_NAME + fixture => + fixture.cutoutFixtureId != null && + !SINGLE_SLOT_FIXTURES.includes(fixture.cutoutFixtureId) ) return ( <> - {showAddFixtureModal && targetFixtureLocation != null ? ( + {showAddFixtureModal && targetCutoutId != null ? ( <AddFixtureModal - fixtureLocation={targetFixtureLocation} + cutoutId={targetCutoutId} setShowAddFixtureModal={setShowAddFixtureModal} /> ) : null} @@ -182,7 +187,7 @@ export function DeviceDetailsDeckConfiguration({ {fixtureDisplayList.map(fixture => { return ( <Flex - key={fixture.fixtureId} + key={fixture.cutoutId} backgroundColor={COLORS.fundamentalsBackground} gridGap={SPACING.spacing60} padding={SPACING.spacing8} @@ -190,10 +195,10 @@ export function DeviceDetailsDeckConfiguration({ css={TYPOGRAPHY.labelRegular} > <StyledText> - {getCutoutDisplayName(fixture.fixtureLocation)} + {getCutoutDisplayName(fixture.cutoutId)} </StyledText> <StyledText> - {getFixtureDisplayName(fixture.loadName)} + {getFixtureDisplayName(fixture.cutoutFixtureId)} </StyledText> </Flex> ) diff --git a/app/src/organisms/ProtocolSetupDeckConfiguration/index.tsx b/app/src/organisms/ProtocolSetupDeckConfiguration/index.tsx index c665af4d600..2a1be5e1994 100644 --- a/app/src/organisms/ProtocolSetupDeckConfiguration/index.tsx +++ b/app/src/organisms/ProtocolSetupDeckConfiguration/index.tsx @@ -19,21 +19,21 @@ import { getSimplestDeckConfigForProtocolCommands } from '../../resources/deck_c import { Portal } from '../../App/portal' import type { - Cutout, + CutoutFixtureId, + CutoutId, DeckConfiguration, - FixtureLoadName, } from '@opentrons/shared-data' import type { SetupScreens } from '../../pages/OnDeviceDisplay/ProtocolSetup' interface ProtocolSetupDeckConfigurationProps { - fixtureLocation: Cutout + cutoutId: CutoutId runId: string setSetupScreen: React.Dispatch<React.SetStateAction<SetupScreens>> - providedFixtureOptions: FixtureLoadName[] + providedFixtureOptions: CutoutFixtureId[] } export function ProtocolSetupDeckConfiguration({ - fixtureLocation, + cutoutId, runId, setSetupScreen, providedFixtureOptions, @@ -74,9 +74,9 @@ export function ProtocolSetupDeckConfiguration({ setShowConfirmationModal={setShowDiscardChangeModal} /> ) : null} - {showConfigurationModal && fixtureLocation != null ? ( + {showConfigurationModal && cutoutId != null ? ( <AddFixtureModal - fixtureLocation={fixtureLocation} + cutoutId={cutoutId} setShowAddFixtureModal={setShowConfigurationModal} providedFixtureOptions={providedFixtureOptions} setCurrentDeckConfig={setCurrentDeckConfig} diff --git a/app/src/pages/DeckConfiguration/index.tsx b/app/src/pages/DeckConfiguration/index.tsx index 8f1e84f8068..a9b83dfcc2e 100644 --- a/app/src/pages/DeckConfiguration/index.tsx +++ b/app/src/pages/DeckConfiguration/index.tsx @@ -14,7 +14,11 @@ import { useDeckConfigurationQuery, useCreateDeckConfigurationMutation, } from '@opentrons/react-api-client' -import { STANDARD_SLOT_LOAD_NAME } from '@opentrons/shared-data' +import { + SINGLE_RIGHT_CUTOUTS, + SINGLE_LEFT_SLOT_FIXTURE, + SINGLE_RIGHT_SLOT_FIXTURE, +} from '@opentrons/shared-data' import { SmallButton } from '../../atoms/buttons' import { ChildNavigation } from '../../organisms/ChildNavigation' @@ -23,7 +27,7 @@ import { DeckFixtureSetupInstructionsModal } from '../../organisms/DeviceDetails import { DeckConfigurationDiscardChangesModal } from '../../organisms/DeviceDetailsDeckConfiguration/DeckConfigurationDiscardChangesModal' import { Portal } from '../../App/portal' -import type { Cutout, DeckConfiguration } from '@opentrons/shared-data' +import type { CutoutId, DeckConfiguration } from '@opentrons/shared-data' export function DeckConfigurationEditor(): JSX.Element { const { t, i18n } = useTranslation([ @@ -40,10 +44,9 @@ export function DeckConfigurationEditor(): JSX.Element { showConfigurationModal, setShowConfigurationModal, ] = React.useState<boolean>(false) - const [ - targetFixtureLocation, - setTargetFixtureLocation, - ] = React.useState<Cutout | null>(null) + const [targetCutoutId, setTargetCutoutId] = React.useState<CutoutId | null>( + null + ) const [ showDiscardChangeModal, setShowDiscardChangeModal, @@ -57,16 +60,21 @@ export function DeckConfigurationEditor(): JSX.Element { setCurrentDeckConfig, ] = React.useState<DeckConfiguration>(deckConfig) - const handleClickAdd = (fixtureLocation: Cutout): void => { - setTargetFixtureLocation(fixtureLocation) + const handleClickAdd = (cutoutId: CutoutId): void => { + setTargetCutoutId(cutoutId) setShowConfigurationModal(true) } - const handleClickRemove = (fixtureLocation: Cutout): void => { + const handleClickRemove = (cutoutId: CutoutId): void => { setCurrentDeckConfig(prevDeckConfig => prevDeckConfig.map(fixture => - fixture.fixtureLocation === fixtureLocation - ? { ...fixture, loadName: STANDARD_SLOT_LOAD_NAME } + fixture.cutoutId === cutoutId + ? { + ...fixture, + cutoutFixtureId: SINGLE_RIGHT_CUTOUTS.includes(cutoutId) + ? SINGLE_RIGHT_SLOT_FIXTURE + : SINGLE_LEFT_SLOT_FIXTURE, + } : fixture ) ) @@ -114,9 +122,9 @@ export function DeckConfigurationEditor(): JSX.Element { isOnDevice /> ) : null} - {showConfigurationModal && targetFixtureLocation != null ? ( + {showConfigurationModal && targetCutoutId != null ? ( <AddFixtureModal - fixtureLocation={targetFixtureLocation} + cutoutId={targetCutoutId} setShowAddFixtureModal={setShowConfigurationModal} setCurrentDeckConfig={setCurrentDeckConfig} isOnDevice diff --git a/components/src/hardware-sim/DeckConfigurator/index.tsx b/components/src/hardware-sim/DeckConfigurator/index.tsx index a7280fad0d3..e468cb6d376 100644 --- a/components/src/hardware-sim/DeckConfigurator/index.tsx +++ b/components/src/hardware-sim/DeckConfigurator/index.tsx @@ -93,33 +93,33 @@ export function DeckConfigurator(props: DeckConfiguratorProps): JSX.Element { showExpansion={showExpansion} /> ))} - {stagingAreaFixtures.map(({ cutoutFixtureId, cutoutId }) => ( + {stagingAreaFixtures.map(({ cutoutId }) => ( <StagingAreaConfigFixture - key={cutoutFixtureId} + key={cutoutId} deckDefinition={deckDef} handleClickRemove={readOnly ? undefined : handleClickRemove} fixtureLocation={cutoutId} /> ))} - {emptyFixtures.map(({ cutoutFixtureId, cutoutId }) => ( + {emptyFixtures.map(({ cutoutId }) => ( <EmptyConfigFixture - key={cutoutFixtureId} + key={cutoutId} deckDefinition={deckDef} handleClickAdd={handleClickAdd} fixtureLocation={cutoutId} /> ))} - {wasteChuteFixtures.map(({ cutoutFixtureId, cutoutId }) => ( + {wasteChuteFixtures.map(({ cutoutId }) => ( <WasteChuteConfigFixture - key={cutoutFixtureId} + key={cutoutId} deckDefinition={deckDef} handleClickRemove={readOnly ? undefined : handleClickRemove} fixtureLocation={cutoutId} /> ))} - {trashBinFixtures.map(({ cutoutFixtureId, cutoutId }) => ( + {trashBinFixtures.map(({ cutoutId }) => ( <TrashBinConfigFixture - key={cutoutFixtureId} + key={cutoutId} deckDefinition={deckDef} handleClickRemove={readOnly ? undefined : handleClickRemove} fixtureLocation={cutoutId} diff --git a/shared-data/js/constants.ts b/shared-data/js/constants.ts index 10a6e8cecb0..8deb6f13a67 100644 --- a/shared-data/js/constants.ts +++ b/shared-data/js/constants.ts @@ -1,5 +1,5 @@ -import { CutoutFixtureId } from '../deck' -import type { Cutout, ModuleType } from './types' +import { CutoutFixtureId, CutoutId } from '../deck' +import type { ModuleType } from './types' // constants for dealing with robot coordinate system (eg in labwareTools) export const SLOT_LENGTH_MM = 127.76 // along X axis in robot coordinate system @@ -184,12 +184,34 @@ export const TC_MODULE_LOCATION_OT3: 'A1+B1' = 'A1+B1' export const WEIGHT_OF_96_CHANNEL: '~10kg' = '~10kg' -export const STAGING_AREA_CUTOUTS: Cutout[] = [ +export const SINGLE_LEFT_CUTOUTS: CutoutId[] = [ + 'cutoutA1', + 'cutoutB1', + 'cutoutC1', + 'cutoutD1', +] + +export const SINGLE_CENTER_CUTOUTS: CutoutId[] = [ + 'cutoutA2', + 'cutoutB2', + 'cutoutC2', + 'cutoutD2', +] + +export const SINGLE_RIGHT_CUTOUTS: CutoutId[] = [ 'cutoutA3', 'cutoutB3', 'cutoutC3', 'cutoutD3', ] + +export const STAGING_AREA_CUTOUTS: CutoutId[] = [ + 'cutoutA3', + 'cutoutB3', + 'cutoutC3', + 'cutoutD3', +] + export const WASTE_CHUTE_CUTOUT: 'cutoutD3' = 'cutoutD3' export const A1_ADDRESSABLE_AREA: 'A1' = 'A1' diff --git a/shared-data/js/fixtures.ts b/shared-data/js/fixtures.ts index 2c1bac74b9b..f5549408af7 100644 --- a/shared-data/js/fixtures.ts +++ b/shared-data/js/fixtures.ts @@ -2,7 +2,10 @@ import { FLEX_ROBOT_TYPE, STAGING_AREA_RIGHT_SLOT_FIXTURE, TRASH_BIN_ADAPTER_FIXTURE, - WASTE_CHUTE_FIXTURES, + WASTE_CHUTE_RIGHT_ADAPTER_COVERED_FIXTURE, + WASTE_CHUTE_RIGHT_ADAPTER_NO_COVER_FIXTURE, + STAGING_AREA_SLOT_WITH_WASTE_CHUTE_RIGHT_ADAPTER_COVERED_FIXTURE, + STAGING_AREA_SLOT_WITH_WASTE_CHUTE_RIGHT_ADAPTER_NO_COVER_FIXTURE, } from './constants' import type { CutoutFixtureId } from '../deck' import type { @@ -94,14 +97,26 @@ export function getAddressableAreaFromSlotId( } export function getFixtureDisplayName( - cutoutFixtureId: CutoutFixtureId + cutoutFixtureId: CutoutFixtureId | null ): string { if (cutoutFixtureId === STAGING_AREA_RIGHT_SLOT_FIXTURE) { - return 'Staging Area Slot' + return 'Staging area slot' } else if (cutoutFixtureId === TRASH_BIN_ADAPTER_FIXTURE) { - return 'Trash Bin' - } else if (WASTE_CHUTE_FIXTURES.includes(cutoutFixtureId)) { - return 'Waste Chute' + return 'Trash bin' + } else if (cutoutFixtureId === WASTE_CHUTE_RIGHT_ADAPTER_NO_COVER_FIXTURE) { + return 'Waste chute only' + } else if (cutoutFixtureId === WASTE_CHUTE_RIGHT_ADAPTER_COVERED_FIXTURE) { + return 'Waste chute only covered' + } else if ( + cutoutFixtureId === + STAGING_AREA_SLOT_WITH_WASTE_CHUTE_RIGHT_ADAPTER_NO_COVER_FIXTURE + ) { + return 'Waste chute with staging area slot' + } else if ( + cutoutFixtureId === + STAGING_AREA_SLOT_WITH_WASTE_CHUTE_RIGHT_ADAPTER_COVERED_FIXTURE + ) { + return 'Waste chute with staging area slot covered' } else { return 'Slot' }