-
Notifications
You must be signed in to change notification settings - Fork 178
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(app): Add incompatible module notification modals (#15181)
We meant to add this for the launch of the Flex, but it got cut for scope; in the time since, people connecting modules like first-generation temperature modules to Flexes that don't support them has been a pretty consistent thorn in the side of support. This PR implements the modals designed by design for telling the user when there's incompatible modules. This PR is pretty big and might be best viewed by commit, since it has both the backend and the frontend, and both the ODD and the desktop - and a couple ancillary support PRs that I'll rebase out of here as they get merged. Specifically, ## Overview 90dc748 - Python, adds data to module configs to say what kinds of deck they're compatible with, and adds code to the api and robot server to expose a bool about whether the pipette's compatible or not in the HTTP API 788e022 - JS, adds the above to the api clients 2e49f61 - JS, adds a blocking modal to the ODD that pops up whenever modules are attached per [figma](https://www.figma.com/file/0kuPeCi1t2Auu2GPMnqRb2/Primary%3A-Flex?type=design&node-id=19961-155919&mode=design&t=pkbLPA9150bwQQNw-4) c5021ca - JS, adds a modal that blocks interaction with a robot but _not_ the navbar or breadcrumbs whenever modules are attached per [figma](https://www.figma.com/design/Nx7ORMnfyJNP4FQYxN4e5x/Primary%3A-Desktop-App?node-id=2032-304206&t=iat6IH7YQD4pMijc-4) ## Notes and Review requests 90dc748 - I'm pretty sure these are the module compatibility rules, but we'll need to make sure. This will get exposed via HTTP as soon as the module is plugged in. Review requests: - [ ] bool should be correct for plugged-in modules basically as soon as they appear in the app The above, and 788e022 - This is set up to support polling. Let me know if you think this should be notifications instead, will be another couple commits though. 2e49f61 - ODD modal. Is this according to design, is there something I'm missing? Is the testing approach OK? You can test by editing `robot-server/simulator/test-flex.env` to specify a `ThermocyclerModuleV1` instead of a `ThermocyclerModuleV2` and run with `make -C robot-server dev-flex`, as well as actually plugging stuff in to a real robot. c5021ca - Desktop modal, basically same questions and same testing approach. Note that this is the first ish time we've added a modal that doesn't inhibit interaction with navbar or breadcrumbs.
- Loading branch information
Showing
36 changed files
with
1,274 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"incompatible_modules_attached": "incompatible module detected", | ||
"remove_before_running_protocol": "Remove the following hardware before running a protocol:", | ||
"needs_your_assistance": "{{robot_name}} needs your assistance", | ||
"remove_before_using": "You must remove incompatible modules before using this robot.", | ||
"is_not_compatible": "{{module_name}} is not compatible with the {{robot_type}}" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
92 changes: 92 additions & 0 deletions
92
app/src/organisms/IncompatibleModule/IncompatibleModuleDesktopModalBody.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
import * as React from 'react' | ||
import { useTranslation, Trans } from 'react-i18next' | ||
import { | ||
DIRECTION_COLUMN, | ||
DIRECTION_ROW, | ||
ALIGN_CENTER, | ||
JUSTIFY_FLEX_START, | ||
Flex, | ||
SPACING, | ||
StyledText, | ||
TYPOGRAPHY, | ||
OVERFLOW_SCROLL, | ||
Icon, | ||
COLORS, | ||
} from '@opentrons/components' | ||
import { getModuleDisplayName } from '@opentrons/shared-data' | ||
import type { AttachedModule } from '@opentrons/api-client' | ||
import { useIsFlex } from '../Devices/hooks' | ||
import { InterventionModal } from '../../molecules/InterventionModal' | ||
export interface IncompatibleModuleDesktopModalBodyProps { | ||
modules: AttachedModule[] | ||
robotName: string | ||
} | ||
|
||
export function IncompatibleModuleDesktopModalBody({ | ||
modules, | ||
robotName, | ||
}: IncompatibleModuleDesktopModalBodyProps): JSX.Element { | ||
const { t } = useTranslation('incompatible_modules') | ||
const isFlex = useIsFlex(robotName) | ||
const displayName = isFlex ? 'Flex' : 'OT-2' | ||
return ( | ||
<InterventionModal | ||
heading={ | ||
<Trans | ||
as="h4" | ||
fontSize={TYPOGRAPHY.fontSizeH4} | ||
t={t} | ||
i18nKey="needs_your_assistance" | ||
values={{ robot_name: robotName }} | ||
/> | ||
} | ||
type="error" | ||
> | ||
<Flex flexDirection={DIRECTION_COLUMN} padding={SPACING.spacing32}> | ||
<Flex | ||
overflowY={OVERFLOW_SCROLL} | ||
flexDirection={DIRECTION_COLUMN} | ||
gridGap={SPACING.spacing12} | ||
maxHeight="196px" | ||
as="ul" | ||
> | ||
{modules.map(module => ( | ||
<li key={module.id}> | ||
<Flex | ||
flexDirection={DIRECTION_ROW} | ||
width="100%" | ||
justifyContent={JUSTIFY_FLEX_START} | ||
alignItems={ALIGN_CENTER} | ||
paddingBottom={SPACING.spacing12} | ||
> | ||
<Icon | ||
name="alert-circle" | ||
size={SPACING.spacing32} | ||
color={COLORS.red50} | ||
/> | ||
<StyledText | ||
as="p" | ||
key={module.id} | ||
fontWeight={TYPOGRAPHY.fontWeightSemiBold} | ||
paddingLeft={SPACING.spacing12} | ||
> | ||
<Trans | ||
i18nKey="is_not_compatible" | ||
values={{ | ||
module_name: getModuleDisplayName(module.moduleModel), | ||
robot_type: displayName, | ||
}} | ||
t={t} | ||
/> | ||
</StyledText> | ||
</Flex> | ||
</li> | ||
))} | ||
</Flex> | ||
<StyledText as="p" paddingTop={SPACING.spacing12}> | ||
<Trans t={t} i18nKey="remove_before_using" /> | ||
</StyledText> | ||
</Flex> | ||
</InterventionModal> | ||
) | ||
} |
55 changes: 55 additions & 0 deletions
55
app/src/organisms/IncompatibleModule/IncompatibleModuleODDModalBody.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import * as React from 'react' | ||
import { useTranslation, Trans } from 'react-i18next' | ||
import capitalize from 'lodash/capitalize' | ||
import { | ||
DIRECTION_COLUMN, | ||
Flex, | ||
SPACING, | ||
StyledText, | ||
TYPOGRAPHY, | ||
OVERFLOW_SCROLL, | ||
} from '@opentrons/components' | ||
import { getModuleDisplayName } from '@opentrons/shared-data' | ||
import type { AttachedModule } from '@opentrons/api-client' | ||
import { Modal } from '../../molecules/Modal' | ||
import { ListItem } from '../../atoms/ListItem' | ||
import type { ModalHeaderBaseProps } from '../../molecules/Modal/types' | ||
export interface IncompatibleModuleODDModalBodyProps { | ||
modules: AttachedModule[] | ||
} | ||
|
||
export function IncompatibleModuleODDModalBody({ | ||
modules, | ||
}: IncompatibleModuleODDModalBodyProps): JSX.Element { | ||
const { t } = useTranslation('incompatible_modules') | ||
const incompatibleModuleHeader: ModalHeaderBaseProps = { | ||
title: capitalize(t('incompatible_modules_attached')), | ||
} | ||
return ( | ||
<Modal header={incompatibleModuleHeader}> | ||
<Flex flexDirection={DIRECTION_COLUMN} width="100%"> | ||
<StyledText as="p" marginBottom={SPACING.spacing32}> | ||
<Trans t={t} i18nKey="remove_before_running_protocol" /> | ||
</StyledText> | ||
<Flex | ||
overflowY={OVERFLOW_SCROLL} | ||
flexDirection={DIRECTION_COLUMN} | ||
gridGap={SPACING.spacing8} | ||
maxHeight="196px" | ||
> | ||
{modules.map(module => ( | ||
<ListItem key={module.id} type="noActive"> | ||
<StyledText | ||
as="p" | ||
key={module.id} | ||
fontWeight={TYPOGRAPHY.fontWeightSemiBold} | ||
> | ||
{getModuleDisplayName(module.moduleModel)} | ||
</StyledText> | ||
</ListItem> | ||
))} | ||
</Flex> | ||
</Flex> | ||
</Modal> | ||
) | ||
} |
39 changes: 39 additions & 0 deletions
39
app/src/organisms/IncompatibleModule/IncompatibleModuleTakeover.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import * as React from 'react' | ||
import { createPortal } from 'react-dom' | ||
import { IncompatibleModuleODDModalBody } from './IncompatibleModuleODDModalBody' | ||
import { IncompatibleModuleDesktopModalBody } from './IncompatibleModuleDesktopModalBody' | ||
import { getTopPortalEl, getModalPortalEl } from '../../App/portal' | ||
import { useIncompatibleModulesAttached } from './hooks' | ||
|
||
const POLL_INTERVAL_MS = 5000 | ||
|
||
export interface IncompatibleModuleTakeoverProps { | ||
isOnDevice: boolean | ||
robotName?: string | ||
} | ||
|
||
export function IncompatibleModuleTakeover({ | ||
isOnDevice, | ||
robotName, | ||
}: IncompatibleModuleTakeoverProps): JSX.Element | null { | ||
const incompatibleModules = useIncompatibleModulesAttached({ | ||
refetchInterval: POLL_INTERVAL_MS, | ||
}) | ||
if (incompatibleModules.length === 0) { | ||
return null | ||
} | ||
if (isOnDevice) { | ||
return createPortal( | ||
<IncompatibleModuleODDModalBody modules={incompatibleModules} />, | ||
getTopPortalEl() | ||
) | ||
} else { | ||
return createPortal( | ||
<IncompatibleModuleDesktopModalBody | ||
modules={incompatibleModules} | ||
robotName={robotName ?? ''} | ||
/>, | ||
getModalPortalEl() | ||
) | ||
} | ||
} |
Oops, something went wrong.