Skip to content

Commit

Permalink
Merge pull request #854 from sgratch/enhance-vSphere-provider-help-te…
Browse files Browse the repository at this point in the history
…xt-fields

🐾 Enhance vSphere provider help text fields
  • Loading branch information
yaacov authored Jan 29, 2024
2 parents 1e2d42d + 5d6e43e commit 4557cb8
Show file tree
Hide file tree
Showing 11 changed files with 316 additions and 57 deletions.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@
padding-top: var(--pf-c-form__helper-text--MarginTop);
}

.forklift--edit-modal-field-warning-validation {
color: var(--pf-c-form__helper-text--m-warning--Color);
font-size: small;
padding-top: var(--pf-c-form__helper-text--MarginTop);
}

.forklift-edit-modal-field-success-validation {
color: var(--pf-c-form__helper-text--m-success--Color);
font-size: small;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react';
import { Trans } from 'react-i18next';
import { useForkliftTranslation } from 'src/utils/i18n';

import { ProviderModel } from '@kubev2v/types';
Expand All @@ -14,14 +15,41 @@ export const VSphereEditURLModal: React.FC<EditProviderURLModalProps> = (props)
const { t } = useForkliftTranslation();

const helperTextMsgs = {
error: t(
'Error: The format of the provided URL is invalid. Ensure the URL includes a scheme, a domain name, and a path. For example: https://vCenter-host-example.com/sdk.',
error: (
<div className="forklift-edit-modal-field-error-validation">
<Trans t={t} ns="plugin__forklift-console-plugin">
{
'Error: The format of the provided URL is invalid. Ensure the URL includes a scheme, a domain name, and a path. For example: <strong>https://vCenter-host-example.com/sdk</strong> .'
}
</Trans>
</div>
),
warning: t(
'Warning: The provided URL does not end with the SDK endpoint path: "/sdk". Ensure the URL includes the correct path. For example: https://vCenter-host-example.com/sdk.',
warning: (
<div className="forklift--edit-modal-field-warning-validation">
<Trans t={t} ns="plugin__forklift-console-plugin">
{
'Warning: The provided URL does not end with the SDK endpoint path: <strong>"/sdk"</strong>. Ensure the URL includes the correct path. For example: <strong>https://vCenter-host-example.com/sdk</strong> .'
}
</Trans>
</div>
),
success: t(
'Ensure the URL includes the "/sdk" path. For example: https://vCenter-host-example.com/sdk.',
success: (
<div className="forklift-edit-modal-field-success-validation">
<Trans t={t} ns="plugin__forklift-console-plugin">
{
'Ensure the URL includes the <strong>"/sdk"</strong> path. For example: <strong>https://vCenter-host-example.com/sdk</strong> .'
}
</Trans>
</div>
),
default: (
<div className="forklift-edit-modal-field-default-validation">
<Trans t={t} ns="plugin__forklift-console-plugin">
{
'Ensure the URL includes the <strong>"/sdk"</strong> path. For example: <strong>https://vCenter-host-example.com/sdk</strong> .'
}
</Trans>
</div>
),
};

Expand Down Expand Up @@ -58,8 +86,8 @@ export const VSphereEditURLModal: React.FC<EditProviderURLModalProps> = (props)
label={props?.label || t('URL')}
model={ProviderModel}
variant={ModalVariant.large}
body={t('URL of the vCenter SDK endpoint.')}
helperText={helperTextMsgs.success}
body={t('URL of the vCenter API endpoint.')}
helperText={helperTextMsgs.default}
onConfirmHook={patchProviderURL}
validationHook={urlValidationHook}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react';
import { Trans } from 'react-i18next';
import { useForkliftTranslation } from 'src/utils/i18n';

import { Modify, ProviderModel, V1beta1Provider } from '@kubev2v/types';
Expand Down Expand Up @@ -56,19 +57,44 @@ export type EditProviderVDDKImageProps = Modify<
const EditProviderVDDKImage_: React.FC<EditProviderVDDKImageProps> = (props) => {
const { t } = useForkliftTranslation();

const vddkHelperTextMsgs = {
error: (
<div className="forklift-edit-modal-field-error-validation">
<Trans t={t} ns="plugin__forklift-console-plugin">
Error: The format of the provided VDDK init image is invalid. Ensure the path is a valid
container image path. For example: {'<strong>'}quay.io/kubev2v/vddk:latest{'</strong>'}.
</Trans>
</div>
),
success: (
<div className="forklift-edit-modal-field-success-validation">
<Trans t={t} ns="plugin__forklift-console-plugin">
The path must be empty or a valid container image path. For example: {'<strong>'}
quay.io/kubev2v/vddk:latest{'</strong>'}.
</Trans>
</div>
),
default: (
<div className="forklift-edit-modal-field-default-validation">
<Trans t={t} ns="plugin__forklift-console-plugin">
The path must be empty or a valid container image path. For example: {'<strong>'}
quay.io/kubev2v/vddk:latest{'</strong>'}.
</Trans>
</div>
),
};

const imageValidationHook: ValidationHookType = (value) => {
const trimmedValue = value.toString().trim();
const isValidImage = trimmedValue === '' || validateContainerImage(value.toString().trim());

return isValidImage
? {
validationHelpText: undefined,
validationHelpText: vddkHelperTextMsgs.success,
validated: 'success',
}
: {
validationHelpText: t(
'VDDK init image must be a valid container image, for example quay.io/kubev2v/example:latest',
),
validationHelpText: vddkHelperTextMsgs.error,
validated: 'error',
};
};
Expand All @@ -80,9 +106,14 @@ const EditProviderVDDKImage_: React.FC<EditProviderVDDKImageProps> = (props) =>
title={props?.title || t('Edit VDDK init image')}
label={props?.label || t('VDDK init image')}
model={ProviderModel}
body={t(
'Specify the VDDK image that you created. VDDK accelerates migrations significantly.',
)}
body={
<Trans t={t} ns="plugin__forklift-console-plugin">
{
'Virtual Disk Development Kit (VDDK) container init image path.<br><br>Note: It is strongly recommended to specify a VDDK init image to accelerate migrations.'
}
</Trans>
}
helperText={vddkHelperTextMsgs.default}
validationHook={imageValidationHook}
onConfirmHook={onConfirm}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Validation } from '../../types';
import { validateFingerprint, validateNoSpaces } from '../common';
import { validateFingerprint, validateNoSpaces, validateUsernameAndDomain } from '../common';

/**
* Validates form input fields based on their id.
Expand All @@ -11,6 +11,7 @@ import { validateFingerprint, validateNoSpaces } from '../common';
* 'default' - The default state of the form field, used when the field is empty or a value hasn't been entered yet.
* 'success' - The field's value has passed validation.
* 'error' - The field's value has failed validation.
* 'warning' - The field's value might fail the validation, but it's not mandatory and not disabling the form saving.
*/
export const vsphereSecretFieldValidator = (id: string, value: string) => {
const trimmedValue = value.trim();
Expand All @@ -19,7 +20,7 @@ export const vsphereSecretFieldValidator = (id: string, value: string) => {

switch (id) {
case 'user':
validationState = validateUser(trimmedValue) ? 'success' : 'error';
validationState = validateUser(trimmedValue);
break;
case 'password':
validationState = validatePassword(trimmedValue) ? 'success' : 'error';
Expand All @@ -39,7 +40,11 @@ export const vsphereSecretFieldValidator = (id: string, value: string) => {
};

const validateUser = (value: string) => {
return validateNoSpaces(value);
return validateNoSpaces(value)
? validateUsernameAndDomain(value)
? 'success'
: 'warning'
: 'error';
};

const validatePassword = (value: string) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@
padding-top: var(--pf-c-form__helper-text--MarginTop);
}

.forklift--create-provider-field-warning-validation {
color: var(--pf-c-form__helper-text--m-warning--Color);
font-size: small;
padding-top: var(--pf-c-form__helper-text--MarginTop);
}

.forklift--create-provider-field-success-validation {
color: var(--pf-c-form__helper-text--m-success--Color);
font-size: small;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import React, { useCallback, useReducer } from 'react';
import { Trans } from 'react-i18next';
import { validateContainerImage, validateURL, Validation } from 'src/modules/Providers/utils';
import { useForkliftTranslation } from 'src/utils/i18n';

import { V1beta1Provider } from '@kubev2v/types';
import { Form, FormGroup, TextInput } from '@patternfly/react-core';
import { Form, FormGroup, Popover, TextInput } from '@patternfly/react-core';
import HelpIcon from '@patternfly/react-icons/dist/esm/icons/help-icon';

export interface VSphereProviderCreateFormProps {
provider: V1beta1Provider;
Expand All @@ -19,23 +21,86 @@ export const VSphereProviderCreateForm: React.FC<VSphereProviderCreateFormProps>
const url = provider?.spec?.url || '';
const vddkInitImage = provider?.spec?.settings?.['vddkInitImage'] || '';

const helperTextMsgs = {
error: t(
'Error: The format of the provided URL is invalid. Ensure the URL includes a scheme, a domain name, and a path. For example: https://vCenter-host-example.com/sdk.',
const urlHelperTextMsgs = {
error: (
<div className="forklift--create-provider-field-error-validation">
<Trans t={t} ns="plugin__forklift-console-plugin">
{
'Error: The format of the provided URL is invalid. Ensure the URL includes a scheme, a domain name, and a path. For example: <strong>https://vCenter-host-example.com/sdk</strong> .'
}
</Trans>
</div>
),
warning: t(
'Warning: The provided URL does not end with the SDK endpoint path: "/sdk". Ensure the URL includes the correct path. For example: https://vCenter-host-example.com/sdk.',
warning: (
<div className="forklift--create-provider-field-warning-validation">
<Trans t={t} ns="plugin__forklift-console-plugin">
{
'Warning: The provided URL does not end with the SDK endpoint path: <strong>"/sdk"</strong>. Ensure the URL includes the correct path. For example: <strong>https://vCenter-host-example.com/sdk</strong> .'
}
</Trans>
</div>
),
success: t(
'URL of the vCenter SDK endpoint. Ensure the URL includes the "/sdk" path. For example: https://vCenter-host-example.com/sdk.',
success: (
<div className="forklift--create-provider-field-success-validation">
<Trans t={t} ns="plugin__forklift-console-plugin">
{
'URL of the vCenter API endpoint. Ensure the URL includes the <strong>"/sdk"</strong> path. For example: <strong>https://vCenter-host-example.com/sdk</strong> .'
}
</Trans>
</div>
),
default: (
<div className="forklift--create-provider-field-default-validation">
<Trans t={t} ns="plugin__forklift-console-plugin">
{
'URL of the vCenter API endpoint. Ensure the URL includes the <strong>"/sdk"</strong> path. For example: <strong>https://vCenter-host-example.com/sdk</strong> .'
}
</Trans>
</div>
),
};

const vddkHelperTextMsgs = {
error: (
<div className="forklift--create-provider-field-error-validation">
<Trans t={t} ns="plugin__forklift-console-plugin">
Error: The format of the provided VDDK init image is invalid. Ensure the path is a valid
container image path. For example: {'<strong>'}quay.io/kubev2v/vddk:latest{'</strong>'}.
</Trans>
</div>
),
success: (
<div className="forklift--create-provider-field-success-validation">
<Trans t={t} ns="plugin__forklift-console-plugin">
Virtual Disk Development Kit (VDDK) container init image path. The path must be empty or a
valid container image path. For example: {'<strong>'}quay.io/kubev2v/vddk:latest
{'</strong>'}.
</Trans>
</div>
),
default: (
<div className="forklift--create-provider-field-default-validation">
<Trans t={t} ns="plugin__forklift-console-plugin">
Virtual Disk Development Kit (VDDK) container init image path. The path must be empty or a
valid container image path. For example: {'<strong>'}quay.io/kubev2v/vddk:latest
{'</strong>'}.
</Trans>
</div>
),
};

const vddkHelperTextPopover = (
<Trans t={t} ns="plugin__forklift-console-plugin">
{'Note: It is strongly recommended to specify a VDDK init image to accelerate migrations.'}
</Trans>
);

const initialState = {
validation: {
url: 'default' as Validation,
urlHelperText: helperTextMsgs.success,
urlHelperText: urlHelperTextMsgs.default,
vddkInitImage: 'default' as Validation,
vddkHelperText: vddkHelperTextMsgs.default,
},
};

Expand Down Expand Up @@ -65,6 +130,14 @@ export const VSphereProviderCreateForm: React.FC<VSphereProviderCreateFormProps>
trimmedValue == '' || validateContainerImage(trimmedValue) ? 'success' : 'error';
dispatch({ type: 'SET_FIELD_VALIDATED', payload: { field: id, validationState } });

dispatch({
type: 'SET_FIELD_VALIDATED',
payload: {
field: 'vddkHelperText',
validationState: vddkHelperTextMsgs[validationState],
},
});

onChange({
...provider,
spec: {
Expand All @@ -88,7 +161,7 @@ export const VSphereProviderCreateForm: React.FC<VSphereProviderCreateFormProps>
type: 'SET_FIELD_VALIDATED',
payload: {
field: 'urlHelperText',
validationState: helperTextMsgs[validationState],
validationState: urlHelperTextMsgs[validationState],
},
});

Expand Down Expand Up @@ -128,11 +201,24 @@ export const VSphereProviderCreateForm: React.FC<VSphereProviderCreateFormProps>
<FormGroup
label={t('VDDK init image')}
fieldId="vddkInitImage"
helperText={t(
'VDDK container image. It is strongly recommended to specify a VDDK image to accelerate migrations.',
)}
helperText={state.validation.vddkHelperText}
validated={state.validation.vddkInitImage}
helperTextInvalid={t('Error: VDDK init image must be valid.')}
helperTextInvalid={state.validation.vddkHelperText}
labelIcon={
<Popover
headerContent={<div>VDDK init image</div>}
bodyContent={<div>{vddkHelperTextPopover}</div>}
alertSeverityVariant="info"
>
<button
type="button"
onClick={(e) => e.preventDefault()}
className="pf-c-form__group-label-help"
>
<HelpIcon noVerticalAlign />
</button>
</Popover>
}
>
<TextInput
type="text"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@
padding-top: var(--pf-c-form__helper-text--MarginTop);
}

.forklift-page-provider-field-warning-validation {
color: var(--pf-c-form__helper-text--m-warning--Color);
font-size: small;
padding-top: var(--pf-c-form__helper-text--MarginTop);
}

.forklift-page-provider-field-success-validation {
color: var(--pf-c-form__helper-text--m-success--Color);
font-size: small;
Expand Down
Loading

0 comments on commit 4557cb8

Please sign in to comment.