Skip to content
Open
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
1 change: 1 addition & 0 deletions .cursor/rules/translations.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ yarn workspace @openshift-assisted/locales run validate_translation_files
- **`lib/es/`, `lib/fr/`, `lib/ja/`, `lib/ko/`, `lib/zh/`** — Handled by a separate localization
process. **Do not edit** those `translation.json` files.
- **`libs/ui-lib/lib/ocm/**`** — No **`t('ai:…')`**; use plain English strings or text supplied via props.
- **Bare string literals in `i18nKey` or other translation props** — Always wrap `'ai:…'` strings with `t()` even when assigning to props like `i18nKey`.

## Allowed edits

Expand Down
3 changes: 2 additions & 1 deletion libs/locales/lib/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -742,6 +742,7 @@
"ai:Progress": "Progress",
"ai:Provide a comma separated list of valid DNS names or IP addresses.": "Provide a comma separated list of valid DNS names or IP addresses.",
"ai:Provide a valid DNS name or IP Address": "Provide a valid DNS name or IP Address",
"ai:Provide a valid HTTP or HTTPS URL.": "Provide a valid HTTP or HTTPS URL.",
"ai:Provide a valid HTTP URL.": "Provide a valid HTTP URL.",
"ai:Provide an SSH key to be able to connect to the hosts for debugging purposes during the discovery process": "Provide an SSH key to be able to connect to the hosts for debugging purposes during the discovery process",
"ai:Provide as many labels as you can to narrow the list to relevant hosts only.": "Provide as many labels as you can to narrow the list to relevant hosts.",
Expand Down Expand Up @@ -978,7 +979,7 @@
"ai:Upload a YAML file": "Upload a YAML file",
"ai:Upload a YAML file in NMstate format (not the entire NMstate config CR) that includes your network configuration (static IPs, bonds, etc.).": "Upload a YAML file in NMstate format (not the entire NMstate config CR) that includes your network configuration (static IPs, bonds, etc.).",
"ai:Upload a YAML file with BareMetalHost and Secret resource definitions. Use the provided template as a reference.": "Upload a YAML file with BareMetalHost and Secret resource definitions. Use the provided template as a reference.",
"ai:URL must start with <bold>http</bold> (https schemes are not currently supported).": "URL must start with <bold>http</bold> (https schemes are not currently supported).",
"ai:URL must start with <bold>http</bold> or <bold>https</bold>.": "URL must start with <bold>http</bold> or <bold>https</bold>.",
"ai:URL must start with <bold>http</bold>.": "URL must start with <bold>http</bold>.",
"ai:Use a comma to separate each listed domain. Preface a domain with <bold>.</bold> to include its subdomains. Use <bold>*</bold> to bypass the proxy for all destinations.": "Use a comma to separate each listed domain. Preface a domain with <bold>.</bold> to include its subdomains. Use <bold>*</bold> to bypass the proxy for all destinations.",
"ai:Use advanced networking": "Use advanced networking",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
CLUSTER_DEFAULT_NETWORK_SETTINGS,
clusterNetworksSchema,
serviceNetworksSchema,
httpsProxyValidationSchema,
} from '../../../common';
import { ClusterDeploymentNetworkingValues } from './types';
import { useTranslation } from '../../../common/hooks/use-translation-wrapper';
Expand Down Expand Up @@ -65,7 +66,7 @@ const getNetworkConfigurationValidationSchema = (
ingressVips: vipArrayValidationSchema(hostSubnets, values, t),
sshPublicKey: sshPublicKeyListValidationSchema(t),
httpProxy: httpProxyValidationSchema({ values, pairValueName: 'httpsProxy', t }),
httpsProxy: httpProxyValidationSchema({ values, pairValueName: 'httpProxy', t }), // share the schema, httpS is currently not supported
httpsProxy: httpsProxyValidationSchema({ values, pairValueName: 'httpProxy', t }),
noProxy: noProxyValidationSchema(t),
}),
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
day2ApiVipValidationSchema,
hostPrefixValidationSchema,
httpProxyValidationSchema,
httpsProxyValidationSchema,
ipBlockValidationSchema,
noProxyValidationSchema,
sshPublicKeyValidationSchema,
Expand All @@ -29,7 +30,7 @@ const getValidationSchema = (t: TFunction) =>
? hostPrefixValidationSchema(values.clusterNetworkCidr, t)
: Yup.number(),
httpProxy: httpProxyValidationSchema({ values, pairValueName: 'httpsProxy', t }),
httpsProxy: httpProxyValidationSchema({ values, pairValueName: 'httpProxy', t }), // share the schema, httpS is currently not supported
httpsProxy: httpsProxyValidationSchema({ values, pairValueName: 'httpProxy', t }), // share the schema, httpS is currently not supported
noProxy: noProxyValidationSchema(t),
nodePortAddress:
values.apiPublishingStrategy === 'NodePort'
Expand Down
3 changes: 2 additions & 1 deletion libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvFormPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import {
ntpSourceValidationSchema,
CpuArchitecture,
getOCPStaticIPDocLink,
httpsProxyValidationSchema,
} from '../../../common';

import './infra-env.css';
Expand Down Expand Up @@ -85,7 +86,7 @@ const validationSchema = (usedNames: string[], t: TFunction) =>
allowEmpty: true,
t,
}),
httpsProxy: httpProxyValidationSchema({
httpsProxy: httpsProxyValidationSchema({
values,
pairValueName: 'httpProxy',
allowEmpty: true,
Expand Down
3 changes: 2 additions & 1 deletion libs/ui-lib/lib/cim/components/modals/AddHostModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import {
ModalVariant,
Spinner,
} from '@patternfly/react-core';
import { DownloadIso, DiscoveryImageConfigForm, DiscoveryImageFormValues } from '../../../common';
import { DownloadIso } from '../../../common';
import { DiscoveryImageConfigForm, DiscoveryImageFormValues } from './DiscoveryImageConfigForm';
import { AddHostModalProps } from './types';
import { useTranslation } from '../../../common/hooks/use-translation-wrapper';
import { EnvironmentErrors } from '../InfraEnv/EnvironmentErrors';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import {
ModalBody,
ModalFooter,
} from '@patternfly/react-core';
import { ExternalLinkAltIcon } from '@patternfly/react-icons/dist/js/icons/external-link-alt-icon';
import { Formik, FormikHelpers } from 'formik';
import {
ImageCreateParams,
Expand All @@ -21,40 +20,16 @@ import {
import { AlertFormikError } from '../../../common/components/ui';
import {
httpProxyValidationSchema,
httpsProxyValidationSchema,
noProxyValidationSchema,
sshPublicKeyValidationSchema,
} from '../../validationSchemas';
import { ProxyFieldsType, StatusErrorType } from '../../types';
import ProxyFields from './ProxyFields';
import UploadSSH from './UploadSSH';
import DiscoveryImageTypeControlGroup from './DiscoveryImageTypeControlGroup';
import { getOCPStaticIPDocLink } from '../../config/docs_links';
import { useTranslation } from '../../hooks/use-translation-wrapper';

export const StaticIPInfo = ({ docVersion }: { docVersion?: string }) => {
const { t } = useTranslation();
return (
<Alert
title={t(
'ai:To use static network configuration, follow the steps listed in the documentation.',
)}
isInline
variant="info"
>
<Button
variant="link"
icon={<ExternalLinkAltIcon />}
iconPosition="right"
isInline
onClick={() =>
window.open(getOCPStaticIPDocLink(docVersion), '_blank', 'noopener,noreferrer')
}
>
{t('ai:View documentation')}
</Button>
</Alert>
);
};
} from '../../../common';
import { ProxyFieldsType, StatusErrorType } from '../../../common/types';
import ProxyFields from '../../../common/components/clusterConfiguration/ProxyFields';
import UploadSSH from '../../../common/components/clusterConfiguration/UploadSSH';
import DiscoveryImageTypeControlGroup from '../../../common/components/clusterConfiguration/DiscoveryImageTypeControlGroup';
import { StaticIPInfo } from '../../../common/components/clusterConfiguration/StaticIPInfo';
import { useTranslation } from '../../../common/hooks/use-translation-wrapper';

export type DiscoveryImageFormValues = ImageCreateParams & ProxyFieldsType;

Expand All @@ -63,7 +38,12 @@ const getValidationSchema = (allowEmpty: boolean, t: TFunction) =>
Yup.object<DiscoveryImageFormValues>().shape({
sshPublicKey: sshPublicKeyValidationSchema(t),
httpProxy: httpProxyValidationSchema({ values, pairValueName: 'httpsProxy', allowEmpty, t }),
httpsProxy: httpProxyValidationSchema({ values, pairValueName: 'httpProxy', allowEmpty, t }), // share the schema, httpS is currently not supported
httpsProxy: httpsProxyValidationSchema({
values,
pairValueName: 'httpProxy',
allowEmpty,
t,
}),
noProxy: noProxyValidationSchema(t),
}),
);
Expand Down
3 changes: 2 additions & 1 deletion libs/ui-lib/lib/cim/components/modals/EditProxyModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { ProxyInputFields } from '../../../common/components/clusterConfiguratio
import { Formik, useFormikContext } from 'formik';
import {
httpProxyValidationSchema,
httpsProxyValidationSchema,
noProxyValidationSchema,
ProxyFieldsType,
} from '../../../common';
Expand All @@ -35,7 +36,7 @@ const validationSchema = (t: TFunction) =>
allowEmpty: true,
t,
}),
httpsProxy: httpProxyValidationSchema({
httpsProxy: httpsProxyValidationSchema({
values,
pairValueName: 'httpProxy',
allowEmpty: true,
Expand Down
3 changes: 2 additions & 1 deletion libs/ui-lib/lib/cim/components/modals/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { DiscoveryImageFormValues, ProxyFieldsType } from '../../../common';
import { ProxyFieldsType } from '../../../common';
import { DiscoveryImageFormValues } from './DiscoveryImageConfigForm';
import { BMCFormProps } from '../Agent/types';
import {
BareMetalHostK8sResource,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
} from '@patternfly/react-core';
import { DetailItem, DetailList } from '../ui';
import DiscoveryInstructions from './DiscoveryInstructions';
import { StaticIPInfo } from './DiscoveryImageConfigForm';
import { StaticIPInfo } from './StaticIPInfo';
import { useTranslation } from '../../hooks/use-translation-wrapper';
import { ExternalLinkAltIcon } from '@patternfly/react-icons/dist/js/icons/external-link-alt-icon';
import { getCiscoIntersightLink } from '../../config';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export const ProxyInputFields = () => {
<Trans
t={t}
components={{ bold: <span className="pf-v6-u-font-weight-bold" /> }}
i18nKey="ai:URL must start with <bold>http</bold> (https schemes are not currently supported)."
i18nKey={'ai:URL must start with <bold>http</bold> or <bold>https</bold>.'}
/>
</div>
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from 'react';
import { Alert, Button } from '@patternfly/react-core';
import { ExternalLinkAltIcon } from '@patternfly/react-icons/dist/js/icons/external-link-alt-icon';
import { getOCPStaticIPDocLink } from '../../config/docs_links';
import { useTranslation } from '../../hooks/use-translation-wrapper';

export const StaticIPInfo = ({ docVersion }: { docVersion?: string }) => {
const { t } = useTranslation();
return (
<Alert
title={t(
'ai:To use static network configuration, follow the steps listed in the documentation.',
)}
isInline
variant="info"
>
<Button
variant="link"
icon={<ExternalLinkAltIcon />}
iconPosition="right"
isInline
onClick={() =>
window.open(getOCPStaticIPDocLink(docVersion), '_blank', 'noopener,noreferrer')
}
>
{t('ai:View documentation')}
</Button>
</Alert>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ export { default as SecurityFields } from './SecurityFields';

export * from './utils';
export * from './DiscoveryTroubleshootingModal';
export * from './DiscoveryImageConfigForm';
export * from './StaticIPInfo';
export * from './ExternalPlatformsDropdown';
43 changes: 43 additions & 0 deletions libs/ui-lib/lib/common/validationSchemas/proxyValidation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,49 @@ export const httpProxyValidationSchema = ({
);
};

export const httpsProxyValidationSchema = ({
values,
pairValueName,
allowEmpty,
t,
}: {
values: ProxyFieldsType;
pairValueName: 'httpProxy' | 'httpsProxy';
allowEmpty?: boolean;
t: TFunction;
}) => {
const validation = Yup.string().test(
'http-proxy-validation',
t('ai:Provide a valid HTTP or HTTPS URL.'),
(value?: string) => {
if (!value) {
return true;
}

if (!['http://', 'https://'].some((protocol) => value.startsWith(protocol))) {
return false;
}

try {
new URL(value);
} catch {
return false;
}
return true;
},
);

if (allowEmpty) {
return validation;
}

return validation.test(
'http-proxy-no-empty-validation',
t('ai:At least one of the HTTP or HTTPS proxy URLs is required.'),
(value) => !values.enableProxy || !!value || !!values[pairValueName],
);
};

export const noProxyValidationSchema = (t: TFunction) =>
Yup.string().test(
'no-proxy-validation',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import DiscoveryImageTypeDropdown, { discoveryImageTypes } from './DiscoveryImag
import CertificateFields from '../../../common/components/clusterConfiguration/CertificateFields';
import {
httpProxyValidationSchema,
httpsProxyValidationSchema,
noProxyValidationSchema,
sshPublicKeyValidationSchema,
} from '../../../common';
Expand All @@ -60,7 +61,7 @@ const validationSchema = (t: TFunction) =>
Yup.object<OcmDiscoveryImageFormValues>().shape({
sshPublicKey: sshPublicKeyValidationSchema(t),
httpProxy: httpProxyValidationSchema({ values, pairValueName: 'httpsProxy', t }),
httpsProxy: httpProxyValidationSchema({ values, pairValueName: 'httpProxy', t }), // share the schema, httpS is currently not supported
httpsProxy: httpsProxyValidationSchema({ values, pairValueName: 'httpProxy', t }),
noProxy: noProxyValidationSchema(t),
}),
);
Expand Down
Loading