Skip to content

Commit

Permalink
feat(app, components): add deck configuration section to device detai…
Browse files Browse the repository at this point in the history
…ls (#13732)

* feat(app, components): add deck configuration section to device details
  • Loading branch information
koji authored Oct 8, 2023
1 parent 1a301eb commit 6347454
Show file tree
Hide file tree
Showing 17 changed files with 576 additions and 224 deletions.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions app/src/assets/localization/en/device_details.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"about_module": "About {{name}}",
"about_pipette_name": "About {{name}} Pipette",
"about_pipette": "About pipette",
"add_fixture_description": "Add this fixture to your deck configuration. It will be referenced during protocol analysis.",
"add_to_slot_description": "Choose a fixture below to add to your deck configuration. It will be referenced during protocol analysis.",
"add_to_slot": "Add to slot {{slotName}}",
"add": "Add",
Expand Down Expand Up @@ -147,6 +148,7 @@
"set_target_temp_of_hs": "Set target temperature. This module actively heats but cools passively to room temperature.",
"set_temp_or_shake": "Set {{part}}",
"set_temperature": "Set temperature",
"setup_instructions": "Setup Instructions",
"shake_speed": "shake speed",
"shaker": "Shaker",
"staging_area_slot": "Staging area slot",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as React from 'react'
import { QueryClient, QueryClientProvider } from 'react-query'
import { touchScreenViewport } from '../../DesignTokens/constants'
import { AddDeckConfigurationModal } from './AddDeckConfigurationModal'
import type { Story, Meta } from '@storybook/react'
Expand All @@ -15,10 +16,18 @@ export default {
parameters: touchScreenViewport,
} as Meta

const queryClient = new QueryClient()
const Template: Story<
React.ComponentProps<typeof AddDeckConfigurationModal>
> = args => <AddDeckConfigurationModal {...args} />
> = args => (
<QueryClientProvider client={queryClient}>
<AddDeckConfigurationModal {...args} />
</QueryClientProvider>
)

export const Default = Template.bind({})
Default.args = {
slotName: 'D3',
fixtureLocation: 'D3',
setShowAddFixtureModal: () => {},
isOnDevice: true,
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,41 +13,124 @@ import {
SPACING,
TYPOGRAPHY,
} from '@opentrons/components'
import { useUpdateDeckConfigurationMutation } from '@opentrons/react-api-client'
import {
getFixtureDisplayName,
STAGING_AREA_LOAD_NAME,
// STANDARD_SLOT_LOAD_NAME,
TRASH_BIN_LOAD_NAME,
WASTE_CHUTE_LOAD_NAME,
} from '@opentrons/shared-data'

import { StyledText } from '../../atoms/text'
import { ODD_FOCUS_VISIBLE } from '../../atoms/buttons/constants'
import { TertiaryButton } from '../../atoms/buttons'
import { Modal } from '../../molecules/Modal'
import { LegacyModal } from '../../molecules/LegacyModal'

import type { FixtureLoadName } from '@opentrons/shared-data'
import type { ModalHeaderBaseProps } from '../../molecules/Modal/types'
import type { LegacyModalProps } from '../../molecules/LegacyModal'

interface AddDeckConfigurationModalProps {
slotName: string
fixtureLocation: string
setShowAddFixtureModal: (showAddFixtureModal: boolean) => void
isOnDevice?: boolean
}

// ToDo (kk:09/29/2023)
// update this component when Deck configuration component is ready
// Need to use getFixtureDisplayName
export function AddDeckConfigurationModal({
slotName,
fixtureLocation,
setShowAddFixtureModal,
isOnDevice = false,
}: AddDeckConfigurationModalProps): JSX.Element {
const { t } = useTranslation('device_details')

const modalHeader: ModalHeaderBaseProps = {
title: t('add_to_slot', { slotName: slotName }),
title: t('add_to_slot', { slotName: fixtureLocation }),
hasExitIcon: true,
}

const modalProps: LegacyModalProps = {
title: t('add_to_slot', { slotName: fixtureLocation }),
onClose: () => setShowAddFixtureModal(false),
closeOnOutsideClick: true,
childrenPadding: SPACING.spacing24,
width: '23.125rem',
}

const { updateDeckConfiguration } = useUpdateDeckConfigurationMutation()

const availableFixtures: FixtureLoadName[] = [TRASH_BIN_LOAD_NAME]
if (
fixtureLocation === 'A3' ||
fixtureLocation === 'B3' ||
fixtureLocation === 'C3'
) {
availableFixtures.push(STAGING_AREA_LOAD_NAME)
}
if (fixtureLocation === 'D3') {
availableFixtures.push(STAGING_AREA_LOAD_NAME, WASTE_CHUTE_LOAD_NAME)
}

const handleClickAdd = (fixtureLoadName: FixtureLoadName): void => {
updateDeckConfiguration({
fixtureLocation,
loadName: fixtureLoadName,
})
setShowAddFixtureModal(false)
}

return (
<Modal header={modalHeader}>
<Flex flexDirection={DIRECTION_COLUMN} gridGap={SPACING.spacing32}>
<StyledText as="p">{t('add_to_slot_description')}</StyledText>
<Flex flexDirection={DIRECTION_COLUMN} gridGap={SPACING.spacing8}>
<AddFixtureButton fixtureLoadName={t('staging_area_slot')} />
<AddFixtureButton fixtureLoadName={t('trash')} />
<AddFixtureButton fixtureLoadName={t('waste_chute')} />
</Flex>
</Flex>
</Modal>
<>
{isOnDevice ? (
<Modal header={modalHeader}>
<Flex flexDirection={DIRECTION_COLUMN} gridGap={SPACING.spacing32}>
<StyledText as="p">{t('add_to_slot_description')}</StyledText>
<Flex flexDirection={DIRECTION_COLUMN} gridGap={SPACING.spacing8}>
{/* ToDo (kk:10/05/2023) I will update this part later */}
{/* {availableFixtures.map((fixture, index) => (
<React.Fragment key={`fixture_${index}`}>
<AddFixtureButton fixtureLoadName={fixture} />
</React.Fragment>
))} */}
<AddFixtureButton fixtureLoadName={t('staging_area_slot')} />
<AddFixtureButton fixtureLoadName={t('trash')} />
<AddFixtureButton fixtureLoadName={t('waste_chute')} />
</Flex>
</Flex>
</Modal>
) : (
<LegacyModal {...modalProps}>
<Flex flexDirection={DIRECTION_COLUMN} gridGap={SPACING.spacing16}>
<StyledText as="p">{t('add_fixture_description')}</StyledText>
<Flex flexDirection={DIRECTION_COLUMN} gridGap={SPACING.spacing8}>
{availableFixtures.map(fixture => (
<React.Fragment key={`${fixture}`}>
<Flex
flexDirection={DIRECTION_ROW}
alignItems={ALIGN_CENTER}
justifyContent={JUSTIFY_SPACE_BETWEEN}
padding={`${SPACING.spacing8} ${SPACING.spacing16}`}
backgroundColor={COLORS.medGreyEnabled}
borderRadius={BORDERS.borderRadiusSize1}
>
<StyledText css={TYPOGRAPHY.pSemiBold}>
{getFixtureDisplayName(fixture)}
</StyledText>
<TertiaryButton onClick={() => handleClickAdd(fixture)}>
{t('add')}
</TertiaryButton>
</Flex>
</React.Fragment>
))}
</Flex>
</Flex>
</LegacyModal>
)}
</>
)
}

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import * as React from 'react'
import { useTranslation } from 'react-i18next'
import {
ALIGN_FLEX_END,
BORDERS,
COLORS,
DIRECTION_COLUMN,
DIRECTION_ROW,
Flex,
PrimaryButton,
SPACING,
TYPOGRAPHY,
} from '@opentrons/components'
import { StyledText } from '../../atoms/text'
import { ExternalLink } from '../../atoms/Link/ExternalLink'
import { Modal } from '../../molecules/Modal'
import { LegacyModal } from '../../molecules/LegacyModal'

import type { ModalHeaderBaseProps } from '../../molecules/Modal/types'
import type { LegacyModalProps } from '../../molecules/LegacyModal'

import imgSrc from '../../assets/images/on-device-display/deck_fixture_setup_qrcode.png'

const SETUP_INSTRUCTION_URL = 'www.opentrons.com/support/fixtures'
const SETUP_INSTRUCTION_EXTERNAL_URL =
'https://support.opentrons.com/s/article/Deck-configuration-on-Opentrons-Flex'
const IMG_ALT = 'QRCode for Deck fixture setup instructions page'

interface DeckFixtureSetupInstructionsModalProps {
setShowSetupInstructionsModal: (showSetupInstructionsModal: boolean) => void
isOnDevice?: boolean
}

export function DeckFixtureSetupInstructionsModal({
setShowSetupInstructionsModal,
isOnDevice = false,
}: DeckFixtureSetupInstructionsModalProps): JSX.Element {
const { i18n, t } = useTranslation(['device_details', 'shared'])
const modalHeader: ModalHeaderBaseProps = {
title: t('deck_fixture_setup_instructions'),
iconName: 'information',
iconColor: COLORS.darkBlack100,
hasExitIcon: true,
}

const modalProps: LegacyModalProps = {
title: t('deck_fixture_setup_instructions'),
onClose: () => setShowSetupInstructionsModal(false),
closeOnOutsideClick: true,
childrenPadding: SPACING.spacing24,
width: '39.3125rem',
}

return (
<>
{isOnDevice ? (
<Modal
header={modalHeader}
onOutsideClick={() => setShowSetupInstructionsModal(false)}
>
<Flex flexDirection={DIRECTION_ROW} gridGap={SPACING.spacing40}>
<Flex flexDirection={DIRECTION_COLUMN} gridGap={SPACING.spacing24}>
<Flex
flexDirection={DIRECTION_COLUMN}
gridGap={SPACING.spacing12}
>
<StyledText as="p">
{t('deck_fixture_setup_modal_top_description')}
</StyledText>
<StyledText as="p">
{t('deck_fixture_setup_modal_bottom_description')}
</StyledText>
</Flex>
<Flex
padding={`${SPACING.spacing16} ${SPACING.spacing24}`}
backgroundColor={COLORS.light1}
borderRadius={BORDERS.borderRadiusSize3}
>
<StyledText as="p" fontWeight={TYPOGRAPHY.fontWeightSemiBold}>
{SETUP_INSTRUCTION_URL}
</StyledText>
</Flex>
</Flex>
<Flex>
<img src={imgSrc} alt={IMG_ALT} width="178px" height="178px" />
</Flex>
</Flex>
</Modal>
) : (
<LegacyModal {...modalProps}>
<Flex flexDirection={DIRECTION_COLUMN} gridGap={SPACING.spacing24}>
<Flex flexDirection={DIRECTION_ROW} gridGap={SPACING.spacing24}>
<Flex
flexDirection={DIRECTION_COLUMN}
gridGap={SPACING.spacing16}
>
<Flex
flexDirection={DIRECTION_COLUMN}
gridGap={SPACING.spacing32}
>
<StyledText as="p">
{t('deck_fixture_setup_modal_top_description')}
</StyledText>
<StyledText as="p">
{t('deck_fixture_setup_modal_bottom_description')}
</StyledText>
</Flex>
<ExternalLink href={SETUP_INSTRUCTION_EXTERNAL_URL}>
{t('deck_fixture_setup_instructions')}
</ExternalLink>
</Flex>
<Flex paddingX={SPACING.spacing32}>
<img src={imgSrc} alt={IMG_ALT} width="194x" height="194px" />
</Flex>
</Flex>
<PrimaryButton
onClick={modalProps.onClose}
alignSelf={ALIGN_FLEX_END}
>
{i18n.format(t('shared:close'), 'capitalize')}
</PrimaryButton>
</Flex>
</LegacyModal>
)}
</>
)
}
Loading

0 comments on commit 6347454

Please sign in to comment.