diff --git a/app/src/assets/localization/en/protocol_setup.json b/app/src/assets/localization/en/protocol_setup.json index 084debdb5f0..371ce03a791 100644 --- a/app/src/assets/localization/en/protocol_setup.json +++ b/app/src/assets/localization/en/protocol_setup.json @@ -167,6 +167,7 @@ "no_modules_specified": "no modules are specified for this protocol.", "no_modules_used_in_this_protocol": "No hardware used in this protocol", "no_parameters_specified": "No parameters specified", + "no_parameters_specified_in_protocol": "No parameters specified in this protocol", "no_tiprack_loaded": "Protocol must load a tip rack", "no_tiprack_used": "Protocol must pick up a tip", "no_usb_connection_required": "No USB connection required", diff --git a/app/src/organisms/ChooseRobotSlideout/index.tsx b/app/src/organisms/ChooseRobotSlideout/index.tsx index ef5bb8c9368..1732adee134 100644 --- a/app/src/organisms/ChooseRobotSlideout/index.tsx +++ b/app/src/organisms/ChooseRobotSlideout/index.tsx @@ -112,7 +112,7 @@ interface ChooseRobotSlideoutProps isAnalysisError?: boolean isAnalysisStale?: boolean showIdleOnly?: boolean - multiSlideout?: { currentPage: number } + multiSlideout?: { currentPage: number } | null } export function ChooseRobotSlideout( @@ -135,7 +135,7 @@ export function ChooseRobotSlideout( setSelectedRobot, robotType, showIdleOnly = false, - multiSlideout, + multiSlideout = null, runTimeParametersOverrides, setRunTimeParametersOverrides, } = props diff --git a/app/src/organisms/ChooseRobotToRunProtocolSlideout/index.tsx b/app/src/organisms/ChooseRobotToRunProtocolSlideout/index.tsx index cc94ee94457..ff94a3ecec2 100644 --- a/app/src/organisms/ChooseRobotToRunProtocolSlideout/index.tsx +++ b/app/src/organisms/ChooseRobotToRunProtocolSlideout/index.tsx @@ -36,7 +36,6 @@ interface ChooseRobotToRunProtocolSlideoutProps extends StyleProps { storedProtocolData: StoredProtocolData onCloseClick: () => void showSlideout: boolean - runTimeParameters?: RunTimeParameter[] } export function ChooseRobotToRunProtocolSlideoutComponent( @@ -63,6 +62,8 @@ export function ChooseRobotToRunProtocolSlideoutComponent( ) // TODO: (nd: 3/20/24) remove stubs and pull parameters from analysis + // const runTimeParameters = + // storedProtocolData.mostRecentAnalysis?.runTimeParameters ?? [] const mockRunTimeParameters: RunTimeParameter[] = [ { displayName: 'Dry Run', @@ -230,18 +231,19 @@ export function ChooseRobotToRunProtocolSlideoutComponent( ) + const hasRunTimeParameters = + enableRunTimeParametersFF && runTimeParameters.length > 0 + return ( 0 && - currentPage === 2 + hasRunTimeParameters && currentPage === 2 ? t('select_parameters_for_robot', { robot_name: selectedRobot?.name, }) @@ -253,7 +255,7 @@ export function ChooseRobotToRunProtocolSlideoutComponent( setRunTimeParametersOverrides={setRunTimeParametersOverrides} footer={ - {enableRunTimeParametersFF && runTimeParameters.length > 0 ? ( + {hasRunTimeParameters ? ( currentPage === 1 ? ( <> 0 - // ToDo (kk:03/19/2024) this will be replaced with the boolean from values check result - const dummyBoolean = true + const hasCustomValues = runTimeParameters.some( + parameter => parameter.value !== parameter.default + ) - // ToDO (kk:03/18/2024) Need to add Chip to updated runTime parameter value - // This part will be implemented in a following PR since need to runTime parameter slideout return ( <> {hasParameter ? ( - {dummyBoolean ? t('custom_values') : t('default_values')} + {hasCustomValues ? t('custom_values') : t('default_values')} ) : null} @@ -221,55 +79,28 @@ export function ProtocolRunRuntimeParameters({ {!hasParameter ? ( - + ) : ( <> - + {t('name')} {t('value')} - + {runTimeParameters.map( - (parameter: RunTimeParameter, index: number) => { - return ( - - - - {parameter.displayName} - - - - - - {formatRunTimeParameterValue(parameter, t)} - - {/* ToDo (kk:03/19/2024) need to implement a logic when be is ready */} - {index % 2 === 0 ? ( - - ) : null} - - - - ) - } + (parameter: RunTimeParameter, index: number) => ( + + ) )} @@ -280,16 +111,77 @@ export function ProtocolRunRuntimeParameters({ ) } +interface StyledTableRowComponentProps { + parameter: RunTimeParameter + index: number + runTimeParametersLength: number + t: any +} + +const StyledTableRowComponent = ( + props: StyledTableRowComponentProps +): JSX.Element => { + const { parameter, index, runTimeParametersLength, t } = props + const [targetProps, tooltipProps] = useHoverTooltip() + return ( + + + + {parameter.displayName} + {parameter.description != null ? ( + <> + + + + + {parameter.description} + + + ) : null} + + + + + + {formatRunTimeParameterValue(parameter, t)} + + {parameter.value !== parameter.default ? ( + + ) : null} + + + + ) +} + const StyledTable = styled.table` width: 100%; border-collapse: collapse; text-align: left; ` +const StyledTableHeaderContainer = styled.thead` + display: grid; + grid-template-columns: 1fr 1fr; + grid-gap: 48px; + border-bottom: ${BORDERS.lineBorder}; +` const StyledTableHeader = styled.th` ${TYPOGRAPHY.labelSemiBold} padding: ${SPACING.spacing8}; - border-bottom: ${BORDERS.lineBorder}; ` interface StyledTableRowProps { @@ -297,8 +189,13 @@ interface StyledTableRowProps { } const StyledTableRow = styled.tr` - padding: ${SPACING.spacing8}; + display: grid; + grid-template-columns: 1fr 1fr; + grid-gap: 48px; + padding-top: ${SPACING.spacing8}; + padding-bottom: ${SPACING.spacing8}; border-bottom: ${props => (props.isLast ? 'none' : BORDERS.lineBorder)}; + align-items: ${ALIGN_CENTER}; ` interface StyledTableCellProps { @@ -307,6 +204,5 @@ interface StyledTableCellProps { const StyledTableCell = styled.td` padding-left: ${SPACING.spacing8}; - padding-top: ${SPACING.spacing12}; - padding-bottom: ${props => (props.isLast ? 0 : SPACING.spacing12)}; + height: 1.25rem; ` diff --git a/app/src/organisms/Devices/ProtocolRun/__tests__/ProtocolRunRuntimeParameters.test.tsx b/app/src/organisms/Devices/ProtocolRun/__tests__/ProtocolRunRuntimeParameters.test.tsx index 8844f551d08..ba8b39e64a2 100644 --- a/app/src/organisms/Devices/ProtocolRun/__tests__/ProtocolRunRuntimeParameters.test.tsx +++ b/app/src/organisms/Devices/ProtocolRun/__tests__/ProtocolRunRuntimeParameters.test.tsx @@ -106,7 +106,30 @@ describe('ProtocolRunRuntimeParameters', () => { vi.resetAllMocks() }) - it('should render title, and banner when RunTimeParameters are note empty', () => { + it('should render title, and banner when RunTimeParameters are note empty and all values are default', () => { + render(props) + screen.getByText('Parameters') + screen.getByText('Default values') + screen.getByText('Values are view-only') + screen.getByText('Cancel the run and restart setup to edit') + screen.getByText('Name') + screen.getByText('Value') + }) + + it('should render title, and banner when RunTimeParameters are note empty and some value is changed', () => { + vi.mocked(useMostRecentCompletedAnalysis).mockReturnValue({ + runTimeParameters: [ + ...mockRunTimeParameterData, + { + displayName: 'Dry Run', + variableName: 'DRYRUN', + description: 'Is this a dry or wet run? Wet is true, dry is false', + type: 'boolean', + default: false, + value: true, + }, + ], + } as CompletedProtocolAnalysis) render(props) screen.getByText('Parameters') screen.getByText('Custom values') diff --git a/app/src/organisms/ProtocolDetails/ProtocolParameters/__tests__/ProtocolParameters.test.tsx b/app/src/organisms/ProtocolDetails/ProtocolParameters/__tests__/ProtocolParameters.test.tsx index 707aa5256cf..727ca022890 100644 --- a/app/src/organisms/ProtocolDetails/ProtocolParameters/__tests__/ProtocolParameters.test.tsx +++ b/app/src/organisms/ProtocolDetails/ProtocolParameters/__tests__/ProtocolParameters.test.tsx @@ -7,6 +7,17 @@ import { i18n } from '../../../../i18n' import { ProtocolParameters } from '..' import type { RunTimeParameter } from '@opentrons/shared-data' +import type * as Components from '@opentrons/components' + +vi.mock('@opentrons/components', async importOriginal => { + const actual = await importOriginal() + return { + ...actual, + NoParameters: vi.fn(() => ( +
No parameters specified in this protocol
+ )), + } +}) const mockRunTimeParameter: RunTimeParameter[] = [ { diff --git a/app/src/organisms/ProtocolDetails/ProtocolParameters/index.tsx b/app/src/organisms/ProtocolDetails/ProtocolParameters/index.tsx index d7a64fd2396..69be8a3a468 100644 --- a/app/src/organisms/ProtocolDetails/ProtocolParameters/index.tsx +++ b/app/src/organisms/ProtocolDetails/ProtocolParameters/index.tsx @@ -48,7 +48,7 @@ export function ProtocolParameters({
) : ( - + )} ) diff --git a/app/src/organisms/ProtocolDetails/index.tsx b/app/src/organisms/ProtocolDetails/index.tsx index 9329b6329b3..02d897c3b4e 100644 --- a/app/src/organisms/ProtocolDetails/index.tsx +++ b/app/src/organisms/ProtocolDetails/index.tsx @@ -394,7 +394,6 @@ export function ProtocolDetails( onCloseClick={() => setShowChooseRobotToRunProtocolSlideout(false)} showSlideout={showChooseRobotToRunProtocolSlideout} storedProtocolData={props} - runTimeParameters={runTimeParameters} /> - {t != null - ? t('no_parameters') - : 'No parameters specified in this protocol'} + No parameters specified in this protocol ) diff --git a/components/src/molecules/ParametersTable/__tests__/NoParameters.test.tsx b/components/src/molecules/ParametersTable/__tests__/NoParameters.test.tsx index 5b2e7f2927d..660a6936d51 100644 --- a/components/src/molecules/ParametersTable/__tests__/NoParameters.test.tsx +++ b/components/src/molecules/ParametersTable/__tests__/NoParameters.test.tsx @@ -6,21 +6,19 @@ import { renderWithProviders } from '../../../testing/utils' import { BORDERS, COLORS } from '../../../helix-design-system' import { NoParameters } from '../NoParameters' -const render = (props: React.ComponentProps) => { - return renderWithProviders() +const render = () => { + return renderWithProviders() } -const tMock = (key: string) => key - describe('NoParameters', () => { it('should render text and icon with proper color', () => { - render({}) + render() screen.getByLabelText('alert') screen.getByText('No parameters specified in this protocol') }) it('should have proper styles', () => { - render({}) + render() expect(screen.getByTestId('NoRunTimeParameter')).toHaveStyle( `background-color: ${COLORS.grey30}` ) @@ -31,11 +29,4 @@ describe('NoParameters', () => { `color: ${COLORS.grey60}` ) }) - - it('should render the raw i18n value if a t is provided', () => { - render({ - t: tMock, - }) - screen.getByText('no_parameters') - }) })