From 0cbb525d5b1c336c0f2a0436aae84ad766e87b8e Mon Sep 17 00:00:00 2001 From: koji Date: Tue, 9 Apr 2024 13:04:55 -0400 Subject: [PATCH 1/4] fix(shared-data,app): fix range display when the number of options is two fix range display when the number --- .../src/molecules/ParametersTable/index.tsx | 3 +- shared-data/js/helpers/index.ts | 1 + .../orderRuntimeParameterRangeOptions.test.ts | 39 +++++++++++++++++ .../orderRuntimeParameterRangeOptions.ts | 42 +++++++++++++++++++ shared-data/js/types.ts | 2 +- 5 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 shared-data/js/helpers/orderRuntimeParameterRangeOptions.test.ts create mode 100644 shared-data/js/helpers/orderRuntimeParameterRangeOptions.ts diff --git a/components/src/molecules/ParametersTable/index.tsx b/components/src/molecules/ParametersTable/index.tsx index 485a5efc6e5..5ae0d36d550 100644 --- a/components/src/molecules/ParametersTable/index.tsx +++ b/components/src/molecules/ParametersTable/index.tsx @@ -3,6 +3,7 @@ import styled, { css } from 'styled-components' import { formatRunTimeParameterDefaultValue, formatRunTimeParameterMinMax, + orderRuntimeParameterRangeOptions, } from '@opentrons/shared-data' import { BORDERS, COLORS } from '../../helix-design-system' import { SPACING, TYPOGRAPHY } from '../../ui-style-constants/index' @@ -38,7 +39,7 @@ export function ParametersTable({ ? t != null ? t('num_options', { num: count }) : `${count} options` - : choices.map(choice => choice.displayName).join(', ') + : orderRuntimeParameterRangeOptions(choices) } switch (type) { diff --git a/shared-data/js/helpers/index.ts b/shared-data/js/helpers/index.ts index 854b82d5133..0cb4ec7d88a 100644 --- a/shared-data/js/helpers/index.ts +++ b/shared-data/js/helpers/index.ts @@ -31,6 +31,7 @@ export * from './getSimplestFlexDeckConfig' export * from './formatRunTimeParameterDefaultValue' export * from './formatRunTimeParameterValue' export * from './formatRunTimeParameterMinMax' +export * from './orderRuntimeParameterRangeOptions' export const getLabwareDefIsStandard = (def: LabwareDefinition2): boolean => def?.namespace === OPENTRONS_LABWARE_NAMESPACE diff --git a/shared-data/js/helpers/orderRuntimeParameterRangeOptions.test.ts b/shared-data/js/helpers/orderRuntimeParameterRangeOptions.test.ts new file mode 100644 index 00000000000..7c8529146d7 --- /dev/null +++ b/shared-data/js/helpers/orderRuntimeParameterRangeOptions.test.ts @@ -0,0 +1,39 @@ +import { describe, it, expect } from 'vitest' +import type { Choice } from '../types' + +import { + isNumeric, + orderRuntimeParameterRangeOptions, +} from './orderRuntimeParameterRangeOptions' + +describe('isNumeric', () => { + it('should return true when input is "2"', () => { + const result = isNumeric('2') + expect(result).toBeTruthy() + }) + + it('should return false when input is "opentrons"', () => { + const result = isNumeric('opentrons') + expect(result).toBeFalsy() + }) +}) + +describe('orderRuntimeParameterRangeOptions', () => { + it('should return numerical order when choices are number', () => { + const mockChoices: Choice[] = [ + { displayName: '20', value: 20 }, + { displayName: '16', value: 16 }, + ] + const result = orderRuntimeParameterRangeOptions(mockChoices) + expect(result).toEqual('16, 20') + }) + + it('should return alphabetical order when choices are number', () => { + const mockChoices: Choice[] = [ + { displayName: 'Single channel 50µL', value: 'flex_1channel_50' }, + { displayName: 'Eight Channel 50µL', value: 'flex_8channel_50' }, + ] + const result = orderRuntimeParameterRangeOptions(mockChoices) + expect(result).toEqual('Eight Channel 50µL, Single channel 50µL') + }) +}) diff --git a/shared-data/js/helpers/orderRuntimeParameterRangeOptions.ts b/shared-data/js/helpers/orderRuntimeParameterRangeOptions.ts new file mode 100644 index 00000000000..dd705cf28c8 --- /dev/null +++ b/shared-data/js/helpers/orderRuntimeParameterRangeOptions.ts @@ -0,0 +1,42 @@ +import type { Choice } from '../types' + +export const isNumeric = (str: string): boolean => { + return !isNaN(Number(str)) +} + +/** + * This function sorts an array of strings in numerical and alphabetical order. + * @param {Choice[]} - The array of Choice + * Choice is an object like {displayName: 'Single channel 50µL', value: 'flex_1channel_50' } + * @returns {string} The ordered string with "," + * + * examples + * [ + { displayName: '20', value: 20 }, + { displayName: '16', value: 16 }, + ] + return 16, 20 + + [ + { displayName: 'Single channel 50µL', value: 'flex_1channel_50' }, + { displayName: 'Eight Channel 50µL', value: 'flex_8channel_50' }, + ] + return Eight Channel 50µL, Single channel 50µL + */ +export const orderRuntimeParameterRangeOptions = ( + choices: Choice[] +): string => { + // when this function is called, the array length is always 2 + const displayNames = [choices[0].displayName, choices[1].displayName] + if (isNumeric(displayNames[0])) { + return displayNames + .sort((a, b) => { + const numA = Number(a) + const numB = Number(b) + return numA - numB + }) + .join(', ') + } else { + return displayNames.sort().join(', ') + } +} diff --git a/shared-data/js/types.ts b/shared-data/js/types.ts index 13fa4491a43..75466e7558e 100644 --- a/shared-data/js/types.ts +++ b/shared-data/js/types.ts @@ -597,7 +597,7 @@ export interface NumberParameter { default: number } -interface Choice { +export interface Choice { displayName: string value: number | boolean | string } From 49f9cfa34105065f062c6d7963109989f7dc0bea Mon Sep 17 00:00:00 2001 From: koji Date: Tue, 9 Apr 2024 13:09:08 -0400 Subject: [PATCH 2/4] add the order function to ODD --- app/src/pages/ProtocolDetails/Parameters.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/src/pages/ProtocolDetails/Parameters.tsx b/app/src/pages/ProtocolDetails/Parameters.tsx index b908b5b84d7..0b280a2af3d 100644 --- a/app/src/pages/ProtocolDetails/Parameters.tsx +++ b/app/src/pages/ProtocolDetails/Parameters.tsx @@ -4,6 +4,7 @@ import styled from 'styled-components' import { formatRunTimeParameterDefaultValue, formatRunTimeParameterMinMax, + orderRuntimeParameterRangeOptions, } from '@opentrons/shared-data' import { BORDERS, @@ -62,13 +63,13 @@ export const Parameters = (props: { protocolId: string }): JSX.Element => { makeSnackbar(t('start_setup_customize_values')) } - const getRange = (parameter: RunTimeParameter): string => { + const formatRange = (parameter: RunTimeParameter): string => { const { type } = parameter const numChoices = 'choices' in parameter ? parameter.choices.length : 0 const minMax = formatRunTimeParameterMinMax(parameter) let range: string | null = null if (numChoices === 2 && 'choices' in parameter) { - range = `${parameter.choices[0].displayName}, ${parameter.choices[1].displayName}` + range = orderRuntimeParameterRangeOptions(parameter.choices) } switch (type) { @@ -125,7 +126,7 @@ export const Parameters = (props: { protocolId: string }): JSX.Element => { - {getRange(parameter)} + {formatRange(parameter)} From 47bed771e777c8c64cae9da19077085cf3f5e834 Mon Sep 17 00:00:00 2001 From: koji Date: Tue, 9 Apr 2024 13:51:47 -0400 Subject: [PATCH 3/4] address feedback --- .../orderRuntimeParameterRangeOptions.test.ts | 15 +++++++++++++-- .../helpers/orderRuntimeParameterRangeOptions.ts | 4 ++++ 2 files changed, 17 insertions(+), 2 deletions(-) rename shared-data/js/helpers/{ => __tests__}/orderRuntimeParameterRangeOptions.test.ts (74%) diff --git a/shared-data/js/helpers/orderRuntimeParameterRangeOptions.test.ts b/shared-data/js/helpers/__tests__/orderRuntimeParameterRangeOptions.test.ts similarity index 74% rename from shared-data/js/helpers/orderRuntimeParameterRangeOptions.test.ts rename to shared-data/js/helpers/__tests__/orderRuntimeParameterRangeOptions.test.ts index 7c8529146d7..2a5b62b265d 100644 --- a/shared-data/js/helpers/orderRuntimeParameterRangeOptions.test.ts +++ b/shared-data/js/helpers/__tests__/orderRuntimeParameterRangeOptions.test.ts @@ -1,10 +1,11 @@ import { describe, it, expect } from 'vitest' -import type { Choice } from '../types' import { isNumeric, orderRuntimeParameterRangeOptions, -} from './orderRuntimeParameterRangeOptions' +} from '../orderRuntimeParameterRangeOptions' + +import type { Choice } from '../../types' describe('isNumeric', () => { it('should return true when input is "2"', () => { @@ -36,4 +37,14 @@ describe('orderRuntimeParameterRangeOptions', () => { const result = orderRuntimeParameterRangeOptions(mockChoices) expect(result).toEqual('Eight Channel 50µL, Single channel 50µL') }) + + it('should return empty string choices > 3', () => { + const mockChoices: Choice[] = [ + { displayName: '20', value: 20 }, + { displayName: '16', value: 16 }, + { displayName: '18', value: 18 }, + ] + const result = orderRuntimeParameterRangeOptions(mockChoices) + expect(result).toEqual('') + }) }) diff --git a/shared-data/js/helpers/orderRuntimeParameterRangeOptions.ts b/shared-data/js/helpers/orderRuntimeParameterRangeOptions.ts index dd705cf28c8..6b73f6cb360 100644 --- a/shared-data/js/helpers/orderRuntimeParameterRangeOptions.ts +++ b/shared-data/js/helpers/orderRuntimeParameterRangeOptions.ts @@ -27,6 +27,10 @@ export const orderRuntimeParameterRangeOptions = ( choices: Choice[] ): string => { // when this function is called, the array length is always 2 + if (choices.length > 2) { + console.error('expected to have length 2 but has length ${choices.length}') + return '' + } const displayNames = [choices[0].displayName, choices[1].displayName] if (isNumeric(displayNames[0])) { return displayNames From d17c498c179b2068cdd534274a7734b2daa0d888 Mon Sep 17 00:00:00 2001 From: koji Date: Tue, 9 Apr 2024 14:24:07 -0400 Subject: [PATCH 4/4] fix lint error --- shared-data/js/helpers/orderRuntimeParameterRangeOptions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared-data/js/helpers/orderRuntimeParameterRangeOptions.ts b/shared-data/js/helpers/orderRuntimeParameterRangeOptions.ts index 6b73f6cb360..c372e992a2b 100644 --- a/shared-data/js/helpers/orderRuntimeParameterRangeOptions.ts +++ b/shared-data/js/helpers/orderRuntimeParameterRangeOptions.ts @@ -28,7 +28,7 @@ export const orderRuntimeParameterRangeOptions = ( ): string => { // when this function is called, the array length is always 2 if (choices.length > 2) { - console.error('expected to have length 2 but has length ${choices.length}') + console.error(`expected to have length 2 but has length ${choices.length}`) return '' } const displayNames = [choices[0].displayName, choices[1].displayName]