Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(app): create utils to format value for rtp #14720

Merged
merged 5 commits into from
Mar 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions app/src/assets/localization/en/protocol_setup.json
Original file line number Diff line number Diff line change
Expand Up @@ -175,15 +175,15 @@
"not_calibrated": "Not calibrated yet",
"not_configured": "not configured",
"off_deck": "Off deck",
"off": "off",
"off": "Off",
"offset_data": "Offset Data",
"offsets_applied_plural": "{{count}} offsets applied",
"offsets_applied": "{{count}} offset applied",
"on_adapter_in_mod": "on {{adapterName}} in {{moduleName}}",
"on_adapter": "on {{adapterName}}",
"on_deck": "On deck",
"on-deck_labware": "{{count}} on-deck labware",
"on": "on",
"on": "On",
"opening": "Opening...",
"parameters": "Parameters",
"pipette_mismatch": "Pipette generation mismatch.",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { Divider } from '../../../atoms/structure'
// import { Chip } from '../../../atoms/Chip'
import { NoParameter } from '../../ProtocolDetails/ProtocolParameters/NoParameter'
import { useMostRecentCompletedAnalysis } from '../../LabwarePositionCheck/useMostRecentCompletedAnalysis'
import { formatRunTimeParameterValue } from '../../ProtocolDetails/ProtocolParameters/utils'

import type { RunTimeParameter } from '@opentrons/shared-data'

Expand Down Expand Up @@ -171,40 +172,12 @@ interface ProtocolRunRuntimeParametersProps {
export function ProtocolRunRuntimeParameters({
runId,
}: ProtocolRunRuntimeParametersProps): JSX.Element {
const { i18n, t } = useTranslation('protocol_setup')
const { t } = useTranslation('protocol_setup')
const mostRecentAnalysis = useMostRecentCompletedAnalysis(runId)
// ToDo (kk:03/18/2024) mockData will be replaced with []
const runTimeParameters = mostRecentAnalysis?.runTimeParameters ?? mockData
const hasParameter = runTimeParameters.length > 0

const formattedValue = (runTimeParameter: RunTimeParameter): string => {
const { type, default: defaultValue } = runTimeParameter
const suffix =
'suffix' in runTimeParameter && runTimeParameter.suffix != null
? runTimeParameter.suffix
: ''
switch (type) {
case 'int':
case 'float':
return `${defaultValue.toString()} ${suffix}`
case 'boolean':
return Boolean(defaultValue)
? i18n.format(t('on'), 'capitalize')
: i18n.format(t('off'), 'capitalize')
case 'str':
if ('choices' in runTimeParameter && runTimeParameter.choices != null) {
const choice = runTimeParameter.choices.find(
choice => choice.value === defaultValue
)
if (choice != null) {
return choice.displayName
}
}
break
}
return ''
}

// ToDo (kk:03/19/2024) this will be replaced with the boolean from values check result
const dummyBoolean = true

Expand Down Expand Up @@ -282,7 +255,7 @@ export function ProtocolRunRuntimeParameters({
gridGap={SPACING.spacing16}
>
<StyledText as="p">
{formattedValue(parameter)}
{formatRunTimeParameterValue(parameter, t)}
</StyledText>
{/* ToDo (kk:03/19/2024) chip will be here with conditional render */}
{/* {index % 2 === 0 ? (
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { useTranslation } from 'react-i18next'
import { describe, it, expect, vi } from 'vitest'
import { formatRunTimeParameterValue } from '../utils'

import type { RunTimeParameter } from '@opentrons/shared-data'

const capitalizeFirstLetter = (str: string): string => {
return str.charAt(0).toUpperCase() + str.slice(1)
}

const mockTFunction = vi.fn(str => capitalizeFirstLetter(str))

vi.mock('react-i18next', async importOriginal => {
const actual = await importOriginal<typeof useTranslation>()
return {
...actual,
t: mockTFunction,
}
})

describe('utils-formatRunTimeParameterValue', () => {
it('should return value with suffix when type is int', () => {
const mockData = {
value: 6,
displayName: 'PCR Cycles',
variableName: 'PCR_CYCLES',
description: 'number of PCR cycles on a thermocycler',
type: 'int',
min: 1,
max: 10,
default: 6,
} as RunTimeParameter
const result = formatRunTimeParameterValue(mockData, mockTFunction)
expect(result).toEqual('6')
})

it('should return value with suffix when type is float', () => {
const mockData = {
value: 6.5,
displayName: 'EtoH Volume',
variableName: 'ETOH_VOLUME',
description: '70% ethanol volume',
type: 'float',
suffix: 'mL',
min: 1.5,
max: 10.0,
default: 6.5,
} as RunTimeParameter
const result = formatRunTimeParameterValue(mockData, mockTFunction)
expect(result).toEqual('6.5 mL')
})

it('should return value with suffix when type is str', () => {
const mockData = {
value: 'left',
displayName: 'pipette mount',
variableName: 'mont',
description: 'pipette mount',
type: 'str',
choices: [
{
displayName: 'Left',
value: 'left',
},
{
displayName: 'Right',
value: 'right',
},
],
default: 'left',
} as RunTimeParameter
const result = formatRunTimeParameterValue(mockData, mockTFunction)
expect(result).toEqual('Left')
})

it('should return value with suffix when type is boolean true', () => {
const mockData = {
value: true,
displayName: 'Deactivate Temperatures',
variableName: 'DEACTIVATE_TEMP',
description: 'deactivate temperature on the module',
type: 'boolean',
default: true,
} as RunTimeParameter
const result = formatRunTimeParameterValue(mockData, mockTFunction)
expect(result).toEqual('On')
})

it('should return value with suffix when type is boolean false', () => {
const mockData = {
value: false,
displayName: 'Dry Run',
variableName: 'DRYRUN',
description: 'Is this a dry or wet run? Wet is true, dry is false',
type: 'boolean',
default: false,
} as RunTimeParameter
const result = formatRunTimeParameterValue(mockData, mockTFunction)
expect(result).toEqual('Off')
})
})
32 changes: 4 additions & 28 deletions app/src/organisms/ProtocolDetails/ProtocolParameters/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
import { StyledText } from '../../../atoms/text'
import { Banner } from '../../../atoms/Banner'
import { NoParameter } from './NoParameter'
import { formatRunTimeParameterValue } from './utils'

import type { RunTimeParameter } from '@opentrons/shared-data'

Expand Down Expand Up @@ -63,33 +64,6 @@ function ProtocolParameterItems({
runTimeParameters,
}: ProtocolParameterItemsProps): JSX.Element {
const { t } = useTranslation('protocol_details')

const formattedValue = (runTimeParameter: RunTimeParameter): string => {
const { type, default: defaultValue } = runTimeParameter
const suffix =
'suffix' in runTimeParameter && runTimeParameter.suffix != null
? runTimeParameter.suffix
: ''
switch (type) {
case 'int':
case 'float':
return `${defaultValue.toString()} ${suffix}`
case 'boolean':
return Boolean(defaultValue) ? t('on') : t('off')
case 'str':
if ('choices' in runTimeParameter && runTimeParameter.choices != null) {
const choice = runTimeParameter.choices.find(
choice => choice.value === defaultValue
)
if (choice != null) {
return choice.displayName
}
}
break
}
return ''
}

const formatRange = (
runTimeParameter: RunTimeParameter,
minMax: string
Expand Down Expand Up @@ -135,7 +109,9 @@ function ProtocolParameterItems({
<StyledText as="p">{parameter.displayName}</StyledText>
</StyledTableCell>
<StyledTableCell isLast={index === runTimeParameters.length - 1}>
<StyledText as="p">{formattedValue(parameter)}</StyledText>
<StyledText as="p">
{formatRunTimeParameterValue(parameter, t)}
</StyledText>
</StyledTableCell>
<StyledTableCell isLast={index === runTimeParameters.length - 1}>
<StyledText as="p">
Expand Down
33 changes: 33 additions & 0 deletions app/src/organisms/ProtocolDetails/ProtocolParameters/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { useTranslation } from 'react-i18next'
import type { RunTimeParameter } from '@opentrons/shared-data'

export const formatRunTimeParameterValue = (
runTimeParameter: RunTimeParameter,
t: ReturnType<typeof useTranslation>['t']
): string => {
const { type, default: defaultValue } = runTimeParameter
const suffix =
'suffix' in runTimeParameter && runTimeParameter.suffix != null
? runTimeParameter.suffix
: null
switch (type) {
case 'int':
case 'float':
return suffix !== null
? `${defaultValue.toString()} ${suffix}`
: defaultValue.toString()
case 'boolean':
return Boolean(defaultValue) ? t('on') : t('off')
case 'str':
if ('choices' in runTimeParameter && runTimeParameter.choices != null) {
const choice = runTimeParameter.choices.find(
choice => choice.value === defaultValue
)
if (choice != null) {
return choice.displayName
}
}
break
}
return ''
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ import { StyledText } from '../../atoms/text'
import { Chip } from '../../atoms/Chip'
import { useToaster } from '../ToasterOven'
import { mockData } from './index'
import { formatRunTimeParameterValue } from '../ProtocolDetails/ProtocolParameters/utils'

import type { RunTimeParameter } from '@opentrons/shared-data'
import type { SetupScreens } from '../../pages/ProtocolSetup'

export interface ViewOnlyParametersProps {
Expand All @@ -29,7 +29,7 @@ export function ViewOnlyParameters({
runId,
setSetupScreen,
}: ViewOnlyParametersProps): JSX.Element {
const { t, i18n } = useTranslation('protocol_setup')
const { t } = useTranslation('protocol_setup')
const { makeSnackbar } = useToaster()
const mostRecentAnalysis = useMostRecentCompletedAnalysis(runId)
const handleOnClick = (): void => {
Expand All @@ -39,32 +39,6 @@ export function ViewOnlyParameters({
// TODO(jr, 3/18/24): remove mockData
const parameters = mostRecentAnalysis?.runTimeParameters ?? mockData

const getDefault = (parameter: RunTimeParameter): string => {
const { type, default: defaultValue } = parameter
const suffix =
'suffix' in parameter && parameter.suffix != null ? parameter.suffix : ''
switch (type) {
case 'int':
case 'float':
return `${defaultValue.toString()} ${suffix}`
case 'boolean':
return Boolean(defaultValue)
? i18n.format(t('on'), 'capitalize')
: i18n.format(t('off'), 'capitalize')
case 'str':
if ('choices' in parameter && parameter.choices != null) {
const choice = parameter.choices.find(
choice => choice.value === defaultValue
)
if (choice != null) {
return choice.displayName
}
}
break
}
return ''
}

return (
<>
<ChildNavigation
Expand Down Expand Up @@ -120,7 +94,7 @@ export function ViewOnlyParameters({
gridGap={SPACING.spacing8}
>
<StyledText as="p" maxWidth="15rem" color={COLORS.grey60}>
{getDefault(parameter)}
{formatRunTimeParameterValue(parameter, t)}
</StyledText>
{hasCustomValue ? (
<Chip type="success" text={t('updated')} hasIcon={false} />
Expand Down
31 changes: 3 additions & 28 deletions app/src/organisms/ProtocolSetupParameters/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
import { ProtocolSetupStep } from '../../pages/ProtocolSetup'
import { ChildNavigation } from '../ChildNavigation'
import { ResetValuesModal } from './ResetValuesModal'
import { formatRunTimeParameterValue } from '../ProtocolDetails/ProtocolParameters/utils'

import type { RunTimeParameter } from '@opentrons/shared-data'
import type { LabwareOffsetCreateData } from '@opentrons/api-client'
Expand Down Expand Up @@ -171,7 +172,7 @@ export function ProtocolSetupParameters({
labwareOffsets,
runTimeParameters,
}: ProtocolSetupParametersProps): JSX.Element {
const { t, i18n } = useTranslation('protocol_setup')
const { t } = useTranslation('protocol_setup')
const history = useHistory()
const host = useHost()
const queryClient = useQueryClient()
Expand All @@ -193,32 +194,6 @@ export function ProtocolSetupParameters({
createRun({ protocolId, labwareOffsets })
}

const getDefault = (parameter: RunTimeParameter): string => {
const { type, default: defaultValue } = parameter
const suffix =
'suffix' in parameter && parameter.suffix != null ? parameter.suffix : ''
switch (type) {
case 'int':
case 'float':
return `${defaultValue.toString()} ${suffix}`
case 'boolean':
return Boolean(defaultValue)
? i18n.format(t('on'), 'capitalize')
: i18n.format(t('off'), 'capitalize')
case 'str':
if ('choices' in parameter && parameter.choices != null) {
const choice = parameter.choices.find(
choice => choice.value === defaultValue
)
if (choice != null) {
return choice.displayName
}
}
break
}
return ''
}

return (
<>
{resetValuesModal ? (
Expand Down Expand Up @@ -253,7 +228,7 @@ export function ProtocolSetupParameters({
status="general"
title={parameter.displayName}
onClickSetupStep={() => console.log('TODO: wire this up')}
detail={getDefault(parameter)}
detail={formatRunTimeParameterValue(parameter, t)}
description={parameter.description}
fontSize="h4"
/>
Expand Down
Loading
Loading