Skip to content

Commit

Permalink
feat(app): add labware details modals on protocol detail (#16014)
Browse files Browse the repository at this point in the history
Implements the single labware modal, stacked labware modal, highlighting, and stacked badge on the deck tab of the ODD protocol details page. Factors out an ODD SingleLabwareModal component for use in this deck tab and the protocol setup labware screen. Moves the protocol command parsing utils from api-client to shared-data.

closes PLAT-396
  • Loading branch information
brenthagen authored Aug 16, 2024
1 parent ac21cee commit 529bbb5
Show file tree
Hide file tree
Showing 37 changed files with 494 additions and 275 deletions.
2 changes: 0 additions & 2 deletions api-client/src/protocols/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,3 @@ export { getProtocolIds } from './getProtocolIds'
export { getProtocols } from './getProtocols'

export * from './types'
export * from './utils'
export * from './__fixtures__'
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ import { vi, it, describe, expect, beforeEach } from 'vitest'
import { MemoryRouter } from 'react-router-dom'
import { fireEvent, screen, waitFor } from '@testing-library/react'

import { simpleAnalysisFileFixture } from '@opentrons/api-client'
import { OT2_ROBOT_TYPE } from '@opentrons/shared-data'
import {
OT2_ROBOT_TYPE,
simpleAnalysisFileFixture,
} from '@opentrons/shared-data'
import { renderWithProviders } from '../../../__testing-utils__'
import { i18n } from '../../../i18n'
import { getStoredProtocols } from '../../../redux/protocol-storage'
Expand Down
11 changes: 6 additions & 5 deletions app/src/organisms/Devices/ProtocolRun/ProtocolRunSetup.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
import * as React from 'react'
import { useTranslation } from 'react-i18next'

import {
parseAllRequiredModuleModels,
parseLiquidsInLoadOrder,
} from '@opentrons/api-client'
import {
ALIGN_CENTER,
COLORS,
Expand All @@ -18,7 +14,12 @@ import {
TYPOGRAPHY,
FLEX_MAX_CONTENT,
} from '@opentrons/components'
import { FLEX_ROBOT_TYPE, OT2_ROBOT_TYPE } from '@opentrons/shared-data'
import {
FLEX_ROBOT_TYPE,
OT2_ROBOT_TYPE,
parseAllRequiredModuleModels,
parseLiquidsInLoadOrder,
} from '@opentrons/shared-data'

import { Line } from '../../../atoms/structure'
import { InfoMessage } from '../../../molecules/InfoMessage'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import {
} from '@opentrons/components'
import { Modal } from '../../../../molecules/Modal'
import { getIsOnDevice } from '../../../../redux/config'
import { useMostRecentCompletedAnalysis } from '../../../LabwarePositionCheck/useMostRecentCompletedAnalysis'
import { LegacyModal } from '../../../../molecules/LegacyModal'
import { getLocationInfoNames } from '../utils/getLocationInfoNames'
import { getSlotLabwareDefinition } from '../utils/getSlotLabwareDefinition'
Expand All @@ -33,7 +32,7 @@ import {
} from '@opentrons/shared-data'
import tiprackAdapter from '../../../../assets/images/labware/opentrons_flex_96_tiprack_adapter.png'

import type { RobotType } from '@opentrons/shared-data'
import type { RobotType, RunTimeCommand } from '@opentrons/shared-data'

const HIDE_SCROLLBAR = css`
::-webkit-scrollbar {
Expand All @@ -60,22 +59,26 @@ const LIST_ITEM_STYLE = css`

interface LabwareStackModalProps {
labwareIdTop: string
runId: string
commands: RunTimeCommand[] | null
closeModal: () => void
robotType?: RobotType
}

export const LabwareStackModal = (
props: LabwareStackModalProps
): JSX.Element | null => {
const { labwareIdTop, runId, closeModal, robotType = FLEX_ROBOT_TYPE } = props
const {
labwareIdTop,
commands,
closeModal,
robotType = FLEX_ROBOT_TYPE,
} = props
const { t } = useTranslation('protocol_setup')
const isOnDevice = useSelector(getIsOnDevice)
const protocolData = useMostRecentCompletedAnalysis(runId)
if (protocolData == null) {

if (commands == null) {
return null
}
const commands = protocolData?.commands ?? []
const {
slotName,
adapterName,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import * as React from 'react'
import map from 'lodash/map'

import { parseInitialLoadedLabwareByAdapter } from '@opentrons/api-client'
import {
BaseDeck,
Flex,
Expand All @@ -13,6 +12,7 @@ import {
FLEX_ROBOT_TYPE,
getDeckDefFromRobotType,
getSimplestDeckConfigForProtocol,
parseInitialLoadedLabwareByAdapter,
THERMOCYCLER_MODULE_V1,
} from '@opentrons/shared-data'

Expand Down Expand Up @@ -128,7 +128,7 @@ export function SetupLabwareMap({

const labwareOnDeck = map(
labwareRenderInfo,
({ x, y, labwareDef, displayName, slotName }, labwareId) => {
({ labwareDef, displayName, slotName }, labwareId) => {
const labwareInAdapter = initialLoadedLabwareByAdapter[labwareId]
// only rendering the labware on top most layer so
// either the adapter or the labware are rendered but not both
Expand Down Expand Up @@ -199,7 +199,7 @@ export function SetupLabwareMap({
{labwareStackDetailsLabwareId != null && (
<LabwareStackModal
labwareIdTop={labwareStackDetailsLabwareId}
runId={runId}
commands={commands}
closeModal={() => {
setLabwareStackDetailsLabwareId(null)
}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@ import * as React from 'react'
import { useTranslation } from 'react-i18next'
import { useSelector } from 'react-redux'
import { css } from 'styled-components'
import {
parseLiquidsInLoadOrder,
parseLabwareInfoByLiquidId,
} from '@opentrons/api-client'

import {
Box,
COLORS,
Expand All @@ -17,6 +14,11 @@ import {
LegacyStyledText,
TYPOGRAPHY,
} from '@opentrons/components'
import {
parseLabwareInfoByLiquidId,
parseLiquidsInLoadOrder,
} from '@opentrons/shared-data'

import { Modal } from '../../../../molecules/Modal'
import { getIsOnDevice } from '../../../../redux/config'
import { useMostRecentCompletedAnalysis } from '../../../LabwarePositionCheck/useMostRecentCompletedAnalysis'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
import * as React from 'react'
import { useTranslation } from 'react-i18next'
import { css } from 'styled-components'
import {
parseLabwareInfoByLiquidId,
parseLiquidsInLoadOrder,
} from '@opentrons/api-client'

import {
ALIGN_CENTER,
Expand All @@ -23,7 +19,13 @@ import {
SPACING,
StyledText,
} from '@opentrons/components'
import { getModuleDisplayName, MICRO_LITERS } from '@opentrons/shared-data'
import {
getModuleDisplayName,
MICRO_LITERS,
parseLabwareInfoByLiquidId,
parseLiquidsInLoadOrder,
} from '@opentrons/shared-data'

import {
useTrackEvent,
ANALYTICS_EXPAND_LIQUID_SETUP_ROW,
Expand All @@ -35,7 +37,7 @@ import { getLocationInfoNames } from '../utils/getLocationInfoNames'
import { LiquidsLabwareDetailsModal } from './LiquidsLabwareDetailsModal'
import { getTotalVolumePerLiquidId, getVolumePerWell } from './utils'

import type { LabwareByLiquidId } from '@opentrons/api-client'
import type { LabwareByLiquidId } from '@opentrons/shared-data'

interface SetupLiquidsListProps {
runId: string
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
import * as React from 'react'
import map from 'lodash/map'
import isEmpty from 'lodash/isEmpty'
import {
parseInitialLoadedLabwareByAdapter,
parseLabwareInfoByLiquidId,
parseLiquidsInLoadOrder,
} from '@opentrons/api-client'

import {
ALIGN_CENTER,
BaseDeck,
Expand All @@ -18,6 +14,9 @@ import {
FLEX_ROBOT_TYPE,
getDeckDefFromRobotType,
getSimplestDeckConfigForProtocol,
parseInitialLoadedLabwareByAdapter,
parseLabwareInfoByLiquidId,
parseLiquidsInLoadOrder,
THERMOCYCLER_MODULE_V1,
} from '@opentrons/shared-data'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { describe, it, beforeEach, vi, afterEach, expect } from 'vitest'
import { screen } from '@testing-library/react'

import { LabwareRender } from '@opentrons/components'
import { parseLiquidsInLoadOrder } from '@opentrons/api-client'
import { parseLiquidsInLoadOrder } from '@opentrons/shared-data'

import {
nestedTextMatcher,
Expand All @@ -23,7 +23,7 @@ import { LiquidsLabwareDetailsModal } from '../LiquidsLabwareDetailsModal'
import { LiquidDetailCard } from '../LiquidDetailCard'

import type * as Components from '@opentrons/components'
import type { CompletedProtocolAnalysis } from '@opentrons/shared-data'
import type * as SharedData from '@opentrons/shared-data'

vi.mock('@opentrons/components', async importOriginal => {
const actualComponents = await importOriginal<typeof Components>()
Expand All @@ -32,7 +32,13 @@ vi.mock('@opentrons/components', async importOriginal => {
LabwareRender: vi.fn(() => <div>mock LabwareRender</div>),
}
})
vi.mock('@opentrons/api-client')
vi.mock('@opentrons/shared-data', async importOriginal => {
const actualSharedData = await importOriginal<typeof SharedData>()
return {
...actualSharedData,
parseLiquidsInLoadOrder: vi.fn(),
}
})
vi.mock('../../../../../redux/config')
vi.mock('../../../../LabwarePositionCheck/useMostRecentCompletedAnalysis')
vi.mock('../../../../Devices/hooks')
Expand Down Expand Up @@ -92,7 +98,7 @@ describe('LiquidsLabwareDetailsModal', () => {
vi.mocked(LiquidDetailCard).mockReturnValue(<div></div>)
vi.mocked(getDisabledWellFillFromLabwareId).mockReturnValue({})
vi.mocked(useMostRecentCompletedAnalysis).mockReturnValue(
{} as CompletedProtocolAnalysis
{} as SharedData.CompletedProtocolAnalysis
)
vi.mocked(getIsOnDevice).mockReturnValue(false)
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import { when } from 'vitest-when'
import { describe, it, beforeEach, vi, expect } from 'vitest'

import {
parseLiquidsInLoadOrder,
parseLabwareInfoByLiquidId,
} from '@opentrons/api-client'
parseLiquidsInLoadOrder,
} from '@opentrons/shared-data'

import {
nestedTextMatcher,
Expand All @@ -26,6 +26,7 @@ import { LiquidsLabwareDetailsModal } from '../LiquidsLabwareDetailsModal'
import { useNotifyRunQuery } from '../../../../../resources/runs'

import type { Mock } from 'vitest'
import type * as SharedData from '@opentrons/shared-data'

const MOCK_LIQUIDS_IN_LOAD_ORDER = [
{
Expand Down Expand Up @@ -58,7 +59,14 @@ vi.mock('../utils')
vi.mock('../../utils/getLocationInfoNames')
vi.mock('../../../hooks')
vi.mock('../LiquidsLabwareDetailsModal')
vi.mock('@opentrons/api-client')
vi.mock('@opentrons/shared-data', async importOriginal => {
const actualSharedData = await importOriginal<typeof SharedData>()
return {
...actualSharedData,
parseLabwareInfoByLiquidId: vi.fn(),
parseLiquidsInLoadOrder: vi.fn(),
}
})
vi.mock('../../../../../redux/analytics')
vi.mock('../../../../../resources/runs')

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,19 @@ import { describe, it, beforeEach, vi, afterEach, expect } from 'vitest'

import { BaseDeck, LabwareRender } from '@opentrons/components'
import {
fixtureTiprack300ul,
FLEX_ROBOT_TYPE,
FLEX_SIMPLEST_DECK_CONFIG_PROTOCOL_SPEC,
getDeckDefFromRobotType,
getSimplestDeckConfigForProtocol,
OT2_ROBOT_TYPE,
ot2StandardDeckV4 as ot2StandardDeckDef,
ot3StandardDeckV4 as ot3StandardDeckDef,
fixtureTiprack300ul,
} from '@opentrons/shared-data'
import {
parseInitialLoadedLabwareByAdapter,
parseLabwareInfoByLiquidId,
parseLiquidsInLoadOrder,
simpleAnalysisFileFixture,
} from '@opentrons/api-client'
} from '@opentrons/shared-data'

import { renderWithProviders } from '../../../../../__testing-utils__'
import { i18n } from '../../../../../i18n'
Expand Down Expand Up @@ -50,8 +48,6 @@ vi.mock('@opentrons/components', async importOriginal => {
})

vi.mock('@opentrons/components/src/hardware-sim/BaseDeck')
vi.mock('@opentrons/api-client')
vi.mock('@opentrons/shared-data/js/helpers')
vi.mock('../../LabwareInfoOverlay')
vi.mock('../../../hooks')
vi.mock('../utils')
Expand All @@ -65,6 +61,9 @@ vi.mock('@opentrons/shared-data', async importOriginal => {
...actual,
getSimplestDeckConfigForProtocol: vi.fn(),
getDeckDefFromRobotType: vi.fn(),
parseInitialLoadedLabwareByAdapter: vi.fn(),
parseLabwareInfoByLiquidId: vi.fn(),
parseLiquidsInLoadOrder: vi.fn(),
}
})
vi.mock('@opentrons/components', async importOriginal => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ import {
getWellRangeForLiquidLabwarePair,
getDisabledWellGroupForLiquidId,
} from '../utils'
import type { LabwareByLiquidId } from '@opentrons/api-client'
import type { Liquid } from '@opentrons/shared-data'
import type { LabwareByLiquidId, Liquid } from '@opentrons/shared-data'

const LABWARE_ID =
'60e8b050-3412-11eb-ad93-ed232a2337cf:opentrons/corning_24_wellplate_3.4ml_flat/1'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,9 @@ import { fireEvent, screen } from '@testing-library/react'
import { describe, it, beforeEach, vi, afterEach, expect } from 'vitest'

import {
getSimplestDeckConfigForProtocol,
parseAllRequiredModuleModels,
parseLiquidsInLoadOrder,
} from '@opentrons/api-client'
import {
getSimplestDeckConfigForProtocol,
STAGING_AREA_SLOT_WITH_WASTE_CHUTE_RIGHT_ADAPTER_NO_COVER_FIXTURE,
simple_v4 as noModulesProtocol,
test_modules_protocol as withModulesProtocol,
Expand Down Expand Up @@ -45,7 +43,6 @@ import { useNotifyRunQuery } from '../../../../resources/runs'

import type * as SharedData from '@opentrons/shared-data'

vi.mock('@opentrons/api-client')
vi.mock('../../hooks')
vi.mock('../SetupLabware')
vi.mock('../SetupRobotCalibration')
Expand All @@ -61,6 +58,8 @@ vi.mock('@opentrons/shared-data', async importOriginal => {
const actualSharedData = await importOriginal<typeof SharedData>()
return {
...actualSharedData,
parseAllRequiredModuleModels: vi.fn(),
parseLiquidsInLoadOrder: vi.fn(),
parseProtocolData: vi.fn(),
getSimplestDeckConfigForProtocol: vi.fn(),
}
Expand Down
Loading

0 comments on commit 529bbb5

Please sign in to comment.