From f39b7d27106f629897ad5ba8799a03013eeffad5 Mon Sep 17 00:00:00 2001 From: Jeff Puzzo Date: Mon, 23 Sep 2024 10:11:58 -0400 Subject: [PATCH] [RHOAIENG-11751] [RFE] Description field character limit validation for 'create experiment' form --- frontend/src/components/CharLimitHelperText.tsx | 12 ++++++++++++ .../src/concepts/k8s/NameDescriptionField.tsx | 15 ++++----------- frontend/src/concepts/pipelines/content/const.ts | 3 +++ .../pipelines/content/createRun/RunForm.tsx | 15 +++++++-------- .../concepts/pipelines/content/createRun/const.ts | 3 --- .../content/experiment/CreateExperimentModal.tsx | 15 +++++++++++++-- 6 files changed, 39 insertions(+), 24 deletions(-) create mode 100644 frontend/src/components/CharLimitHelperText.tsx diff --git a/frontend/src/components/CharLimitHelperText.tsx b/frontend/src/components/CharLimitHelperText.tsx new file mode 100644 index 0000000000..f1926fa83d --- /dev/null +++ b/frontend/src/components/CharLimitHelperText.tsx @@ -0,0 +1,12 @@ +import { HelperText, HelperTextItem } from '@patternfly/react-core'; +import React from 'react'; + +interface CharLimitHelperTextProps { + limit: number; +} + +export const CharLimitHelperText: React.FC = ({ limit }) => ( + + {`Cannot exceed ${limit} characters`} + +); diff --git a/frontend/src/concepts/k8s/NameDescriptionField.tsx b/frontend/src/concepts/k8s/NameDescriptionField.tsx index e1a8aa7ec0..70eada9274 100644 --- a/frontend/src/concepts/k8s/NameDescriptionField.tsx +++ b/frontend/src/concepts/k8s/NameDescriptionField.tsx @@ -13,6 +13,7 @@ import { ExclamationCircleIcon } from '@patternfly/react-icons'; import { NameDescType } from '~/pages/projects/types'; import { isValidK8sName, translateDisplayNameForK8s } from '~/concepts/k8s/utils'; import ResourceNameDefinitionTooltip from '~/concepts/k8s/ResourceNameDefinitionTooltip'; +import { CharLimitHelperText } from '~/components/CharLimitHelperText'; type NameDescriptionFieldProps = { nameFieldId: string; @@ -82,12 +83,7 @@ const NameDescriptionField: React.FC = ({ maxLength={maxLengthName} /> - {maxLengthName && ( - - {`Cannot exceed ${maxLengthName} characters`} - - )} - + {maxLengthName && } {nameHelperText} @@ -146,11 +142,8 @@ const NameDescriptionField: React.FC = ({ onChange={setData ? (e, description) => setData({ ...data, description }) : undefined} maxLength={maxLengthDesc} /> - {maxLengthDesc && ( - - {`Cannot exceed ${maxLengthDesc} characters`} - - )} + + {maxLengthDesc && } diff --git a/frontend/src/concepts/pipelines/content/const.ts b/frontend/src/concepts/pipelines/content/const.ts index c0d9ca3b76..8e6b4cbc12 100644 --- a/frontend/src/concepts/pipelines/content/const.ts +++ b/frontend/src/concepts/pipelines/content/const.ts @@ -8,3 +8,6 @@ export const PIPELINE_CREATE_SCHEDULE_TOOLTIP_ARGO_ERROR = export const PIPELINE_CREATE_RUN_TOOLTIP_ARGO_ERROR = 'Cannot create run for Kubeflow v1 SDK pipelines'; + +export const NAME_CHARACTER_LIMIT = 255; +export const DESCRIPTION_CHARACTER_LIMIT = 255; diff --git a/frontend/src/concepts/pipelines/content/createRun/RunForm.tsx b/frontend/src/concepts/pipelines/content/createRun/RunForm.tsx index e649d99dbd..2d6df265e5 100644 --- a/frontend/src/concepts/pipelines/content/createRun/RunForm.tsx +++ b/frontend/src/concepts/pipelines/content/createRun/RunForm.tsx @@ -19,14 +19,13 @@ import { DuplicateNameHelperText } from '~/concepts/pipelines/content/DuplicateN import { usePipelinesAPI } from '~/concepts/pipelines/context'; import useDebounceCallback from '~/utilities/useDebounceCallback'; import { isArgoWorkflow } from '~/concepts/pipelines/content/tables/utils'; +import { + NAME_CHARACTER_LIMIT, + DESCRIPTION_CHARACTER_LIMIT, +} from '~/concepts/pipelines/content/const'; import PipelineSection from './contentSections/PipelineSection'; import { RunTypeSection } from './contentSections/RunTypeSection'; -import { - CreateRunPageSections, - RUN_DESCRIPTION_CHARACTER_LIMIT, - RUN_NAME_CHARACTER_LIMIT, - runPageSectionTitles, -} from './const'; +import { CreateRunPageSections, runPageSectionTitles } from './const'; import { getInputDefinitionParams } from './utils'; type RunFormProps = { @@ -126,8 +125,8 @@ const RunForm: React.FC = ({ data, onValueChange, isCloned }) => { descriptionFieldId="run-description" data={data.nameDesc} setData={(nameDesc) => onValueChange('nameDesc', nameDesc)} - maxLengthName={RUN_NAME_CHARACTER_LIMIT} - maxLengthDesc={RUN_DESCRIPTION_CHARACTER_LIMIT} + maxLengthName={NAME_CHARACTER_LIMIT} + maxLengthDesc={DESCRIPTION_CHARACTER_LIMIT} onNameChange={(value) => { setHasDuplicateName(false); checkForDuplicateName(value); diff --git a/frontend/src/concepts/pipelines/content/createRun/const.ts b/frontend/src/concepts/pipelines/content/createRun/const.ts index 0cc0dfeb43..5f693fe1c6 100644 --- a/frontend/src/concepts/pipelines/content/createRun/const.ts +++ b/frontend/src/concepts/pipelines/content/createRun/const.ts @@ -34,6 +34,3 @@ export const runPageSectionTitles: Record = { [CreateRunPageSections.PIPELINE]: 'Pipeline', [CreateRunPageSections.PARAMS]: 'Parameters', }; - -export const RUN_NAME_CHARACTER_LIMIT = 255; -export const RUN_DESCRIPTION_CHARACTER_LIMIT = 255; diff --git a/frontend/src/concepts/pipelines/content/experiment/CreateExperimentModal.tsx b/frontend/src/concepts/pipelines/content/experiment/CreateExperimentModal.tsx index 2600a287f9..ab073f5da6 100644 --- a/frontend/src/concepts/pipelines/content/experiment/CreateExperimentModal.tsx +++ b/frontend/src/concepts/pipelines/content/experiment/CreateExperimentModal.tsx @@ -13,6 +13,11 @@ import { usePipelinesAPI } from '~/concepts/pipelines/context'; import useCreateExperimentData from '~/concepts/pipelines/content/experiment/useCreateExperimentData'; import { ExperimentKFv2 } from '~/concepts/pipelines/kfTypes'; import { getDisplayNameFromK8sResource } from '~/concepts/k8s/utils'; +import { + NAME_CHARACTER_LIMIT, + DESCRIPTION_CHARACTER_LIMIT, +} from '~/concepts/pipelines/content/const'; +import { CharLimitHelperText } from '~/components/CharLimitHelperText'; type CreateExperimentModalProps = { isOpen: boolean; @@ -80,8 +85,11 @@ const CreateExperimentModal: React.FC = ({ isOpen, o id="experiment-name" name="experiment-name" value={name} - onChange={(e, value) => setData('name', value)} + onChange={(_, value) => setData('name', value)} + maxLength={NAME_CHARACTER_LIMIT} /> + + @@ -92,8 +100,11 @@ const CreateExperimentModal: React.FC = ({ isOpen, o id="experiment-description" name="experiment-description" value={description} - onChange={(e, value) => setData('description', value)} + onChange={(_, value) => setData('description', value)} + maxLength={DESCRIPTION_CHARACTER_LIMIT} /> + + {error && (