Skip to content

Commit f9f6c18

Browse files
authoredMar 19, 2025··
Merge pull request #1527 from avivtur/unique-chars-plan-name
MTV-2197: Plan name error text wrong for special characters
2 parents 34ac206 + 71cb12d commit f9f6c18

File tree

8 files changed

+42
-6
lines changed

8 files changed

+42
-6
lines changed
 

‎packages/forklift-console-plugin/locales/en/plugin__forklift-console-plugin.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,6 @@
334334
"Multiple NICs on the same network": "Multiple NICs on the same network",
335335
"Name": "Name",
336336
"Name is primarily intended for creation idempotence and configuration definition. Cannot be updated.": "Name is primarily intended for creation idempotence and configuration definition. Cannot be updated.",
337-
"Name is required and must be a unique within a namespace and valid Kubernetes name.": "Name is required and must be a unique within a namespace and valid Kubernetes name.",
338337
"Namespace": "Namespace",
339338
"Namespace defines the space within which each name must be unique.\n An empty namespace is equivalent to the \"default\" namespace, but \"default\" is the canonical representation.\n Not all objects are required to be scoped to a namespace - the value of this field for those objects will be empty.": "Namespace defines the space within which each name must be unique.\n An empty namespace is equivalent to the \"default\" namespace, but \"default\" is the canonical representation.\n Not all objects are required to be scoped to a namespace - the value of this field for those objects will be empty.",
340339
"Namespace defines the space within which each name must be unique.\n An empty namespace is equivalent to the \"default\" namespace, but \"default\" is the canonical representation.\n Not all objects are required to be scoped to a namespace -\n the value of this field for those objects will be empty.": "Namespace defines the space within which each name must be unique.\n An empty namespace is equivalent to the \"default\" namespace, but \"default\" is the canonical representation.\n Not all objects are required to be scoped to a namespace -\n the value of this field for those objects will be empty.",
@@ -429,6 +428,9 @@
429428
"Pipeline status": "Pipeline status",
430429
"Plan details": "Plan details",
431430
"Plan name": "Plan name",
431+
"Plan name must be a unique within a namespace.": "Plan name must be a unique within a namespace.",
432+
"Plan name must contain only lowercase alphanumeric characters or '-'": "Plan name must contain only lowercase alphanumeric characters or '-'",
433+
"Plan name must not be empty": "Plan name must not be empty",
432434
"Plans": "Plans",
433435
"Plans for virtualization": "Plans for virtualization",
434436
"Plans wizard": "Plans wizard",

‎packages/forklift-console-plugin/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
"devDependencies": {
5454
"@openshift-console/dynamic-plugin-sdk-webpack": "1.3.0",
5555
"@types/ejs": "^3.1.5",
56+
"@types/i18next": "^11.9.3",
5657
"@types/jsonpath": "^0.2.4",
5758
"@types/jsrsasign": "10.5.14",
5859
"@types/luxon": "^3.4.2",

‎packages/forklift-console-plugin/src/modules/Plans/views/create/components/PlanCreateForm.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@ import {
2727

2828
import { PlanCreatePageState } from '../states';
2929

30+
import { PlanNameTextField } from './PlanName/PlanNameTextField';
3031
import { ChipsToolbarProviders } from './ChipsToolbarProviders';
3132
import { createProviderCardItems } from './createProviderCardItems';
3233
import { FiltersToolbarProviders } from './FiltersToolbarProviders';
33-
import { PlanNameTextField } from './PlanNameTextField';
3434
import { ProviderCardEmptyState } from './ProvidersEmptyState';
3535

3636
export type PlanCreateFormProps = {

‎packages/forklift-console-plugin/src/modules/Plans/views/create/components/PlanNameTextField.tsx ‎packages/forklift-console-plugin/src/modules/Plans/views/create/components/PlanName/PlanNameTextField.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import { useForkliftTranslation } from 'src/utils';
55
import { FormGroupWithHelpText } from '@kubev2v/common';
66
import { TextInput } from '@patternfly/react-core';
77

8+
import { getInvalidHelperText } from './utils/utils';
9+
810
interface PlanNameTextFieldProps {
911
value: string;
1012
validated: Validation;
@@ -30,9 +32,7 @@ export const PlanNameTextField: React.FC<PlanNameTextFieldProps> = ({
3032
fieldId="planName"
3133
{...(isUpdated && {
3234
validated: validated,
33-
helperTextInvalid: t(
34-
'Name is required and must be a unique within a namespace and valid Kubernetes name.',
35-
),
35+
helperTextInvalid: getInvalidHelperText(validated, value),
3636
})}
3737
>
3838
<TextInput
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { Validation } from 'src/modules/Providers/utils/types/Validation';
2+
import { validateK8sName } from 'src/modules/Providers/utils/validators/common';
3+
4+
import { ValidatedOptions } from '@patternfly/react-core';
5+
import { t } from '@utils/i18n';
6+
7+
export const getInvalidHelperText = (validated: Validation, nameInput: string) => {
8+
if (validated !== ValidatedOptions.error) return null;
9+
10+
if (!nameInput) {
11+
return t('Plan name must not be empty');
12+
}
13+
if (!validateK8sName(nameInput)) {
14+
return t("Plan name must contain only lowercase alphanumeric characters or '-'");
15+
}
16+
17+
return t('Plan name must be a unique within a namespace.');
18+
};

‎packages/forklift-console-plugin/src/utils/i18n.tsx

+10-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React, { ReactNode } from 'react';
2-
import { Trans, useTranslation } from 'react-i18next';
2+
import { getI18n, Trans, useTranslation } from 'react-i18next';
3+
import { TranslationOptions } from 'i18next';
34

45
export function useForkliftTranslation() {
56
return useTranslation('plugin__forklift-console-plugin');
@@ -14,3 +15,11 @@ export const ForkliftTrans: React.FC<{ children?: ReactNode }> = ({ children })
1415
</Trans>
1516
);
1617
};
18+
19+
/**
20+
* Performs translation to 'plugin__forklift-console-plugin' namespace for usage outside of component functions.
21+
* @param value string to translate
22+
* @param options (optional) options for translations
23+
*/
24+
export const t = (value: string, options?: TranslationOptions) =>
25+
getI18n().t(value, { ns: 'plugin__forklift-console-plugin', ...options });

‎packages/forklift-console-plugin/tsconfig.json

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
"outDir": "./dist",
2525

2626
"paths": {
27+
"@utils/*": ["./src/utils/*"],
2728
"src/*": ["./src/*"],
2829
"common/src/*": ["../common/src/*"]
2930
}

‎yarn.lock

+5
Original file line numberDiff line numberDiff line change
@@ -2433,6 +2433,11 @@
24332433
dependencies:
24342434
"@types/node" "*"
24352435

2436+
"@types/i18next@^11.9.3":
2437+
version "11.9.3"
2438+
resolved "https://registry.yarnpkg.com/@types/i18next/-/i18next-11.9.3.tgz#04d84c6539908ad69665d26d8967f942d1638550"
2439+
integrity sha512-snM7bMKy6gt7UYdpjsxycqSCAy0fr2JVPY0B8tJ2vp9bN58cE7C880k20PWFM4KXxQ3KsstKM8DLCawGCIH0tg==
2440+
24362441
"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1":
24372442
version "2.0.6"
24382443
resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz#7739c232a1fee9b4d3ce8985f314c0c6d33549d7"

0 commit comments

Comments
 (0)
Please sign in to comment.