Skip to content

Commit

Permalink
Merge pull request #1119 from yaacov/handle-different-secret-data-types
Browse files Browse the repository at this point in the history
🧼  Update fields clipboard copy to handle boolean and long texts
  • Loading branch information
yaacov authored Apr 17, 2024
2 parents ea92afa + 5bba6a2 commit 642ffd3
Show file tree
Hide file tree
Showing 11 changed files with 134 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"{{dateLabel}} Failed: {{value}}": "{{dateLabel}} Failed: {{value}}",
"{{dateLabel}} Running: {{value}}": "{{dateLabel}} Running: {{value}}",
"{{dateLabel}} Succeeded: {{value}}": "{{dateLabel}} Succeeded: {{value}}",
"{{label}} field is missing from the secret data.": "{{label}} field is missing from the secret data.",
"{{name}} Details": "{{name}} Details",
"{{selectedLength}} hosts selected.": "{{selectedLength}} hosts selected.",
"{{success}} of {{total}} VMs migrated": "{{success}} of {{total}} VMs migrated",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import React from 'react';
import { useForkliftTranslation } from 'src/utils/i18n';

import { ClipboardCopy, Switch, TextInput, Tooltip } from '@patternfly/react-core';

import { Field } from './components/list/Fields';

export interface ShowFieldWithClipboardCopyProps {
value: string;
field?: Field;
}

/**
* Displays a field with its value. If the value is empty, shows a disabled text input with a tooltip indicating the field is missing.
* If the value is non-empty, displays the value in a read-only format with a clipboard copy functionality.
*
* @property {string} value - The value of the field to display.
* @property {object} field - Object containing details about the field such as label and display type.
*/
export const FieldWithClipboardCopy: React.FC<ShowFieldWithClipboardCopyProps> = ({
field,
value,
}) => {
const { t } = useForkliftTranslation();

// Render tooltip for missing value
if (!value) {
return (
<Tooltip
content={
<div>{t('{{label}} field is missing from the secret data.', { label: field.label })}</div>
}
>
<TextInput value="No value" type="text" isDisabled />
</Tooltip>
);
}

// Determine how to display the field based on its type
const renderFieldByType = () => {
switch (field.displayType) {
case 'textArea':
return (
<ClipboardCopy
isReadOnly
hoverTip={t('Copy')}
clickTip={t('Copied')}
isCode
variant="expansion"
>
{value}
</ClipboardCopy>
);
case 'switch':
return (
<Switch
aria-label={`Switch for ${field.label}`}
label={`${field.label} is set`}
labelOff={`${field.label} is not set`}
isChecked={value.toLocaleLowerCase() === 'true'}
hasCheckIcon
isDisabled
/>
);
default:
return (
<ClipboardCopy isReadOnly hoverTip={t('Copy')} clickTip={t('Copied')} isCode>
{value}
</ClipboardCopy>
);
}
};

return renderFieldByType();
};
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ import { TextInput } from '@patternfly/react-core';
/**
* Show a readable masked (hidden) field value.
*/
export const ShowMaskedField: React.FC = () => {
export const MaskedField: React.FC = () => {
return <TextInput value="&bull;&bull;&bull;&bull;&bull;" type="text" isDisabled />;
};

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { ReactNode } from 'react';

export type Field = {
label: string;
description: ReactNode;
helperTextPopover?: ReactNode;
cacertHelperTextPopover?: ReactNode;
displayType?: 'text' | 'textArea' | 'switch';
};

// Define the type for the object containing all fields
export type Fields = {
[key: string]: Field;
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@ import { ForkliftTrans, useForkliftTranslation } from 'src/utils/i18n';

import { Text, TextVariants } from '@patternfly/react-core';

import { ShowFieldWithClipboardCopy, ShowMaskedField } from '../../';
import { FieldWithClipboardCopy } from '../../FieldWithClipboardCopy';
import { MaskedField } from '../../MaskedField';
import { ListComponentProps } from '../BaseCredentialsSection';

import { Fields } from './Fields';

export const OpenshiftCredentialsList: React.FC<ListComponentProps> = ({ secret, reveal }) => {
const { t } = useForkliftTranslation();

Expand Down Expand Up @@ -36,7 +39,7 @@ export const OpenshiftCredentialsList: React.FC<ListComponentProps> = ({ secret,
</ForkliftTrans>
);

const fields = {
const fields: Fields = {
token: {
label: t('Service account bearer token'),
description: (
Expand All @@ -52,13 +55,15 @@ export const OpenshiftCredentialsList: React.FC<ListComponentProps> = ({ secret,
label: t('Skip certificate validation'),
description: t("If true, the provider's CA certificate won't be validated."),
helperTextPopover: insecureSkipVerifyHelperTextPopover,
displayType: 'switch',
},
cacert: {
label: t('CA certificate'),
description: t(
'A CA certificate to be trusted when connecting to Openshift API endpoint. Ensure the CA certificate format is in a PEM encoded X.509 format. To use a CA certificate, drag the file to the text box or browse for it. To use the system CA certificate, leave the field empty.',
),
helperTextPopover: cacertHelperTextPopover,
displayType: 'textArea',
},
};

Expand All @@ -78,7 +83,7 @@ export const OpenshiftCredentialsList: React.FC<ListComponentProps> = ({ secret,
</Text>
</div>
<div className="forklift-page-secret-content-div">
{reveal ? <ShowFieldWithClipboardCopy value={value} /> : <ShowMaskedField />}
{reveal ? <FieldWithClipboardCopy field={field} value={value} /> : <MaskedField />}
</div>
</>,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@ import { ForkliftTrans, useForkliftTranslation } from 'src/utils/i18n';

import { DescriptionList, Text, TextVariants } from '@patternfly/react-core';

import { ShowFieldWithClipboardCopy, ShowMaskedField } from '../../';
import { FieldWithClipboardCopy } from '../../FieldWithClipboardCopy';
import { MaskedField } from '../../MaskedField';
import { ListComponentProps } from '../BaseCredentialsSection';

import { Fields } from './Fields';

export const OpenstackCredentialsList: React.FC<ListComponentProps> = ({ secret, reveal }) => {
const { t } = useForkliftTranslation();

Expand All @@ -24,7 +27,7 @@ export const OpenstackCredentialsList: React.FC<ListComponentProps> = ({ secret,
</ForkliftTrans>
);

const fields = {
const fields: Record<string, Fields> = {
passwordSecretFields: {
authType: {
label: t('Authentication type'),
Expand All @@ -49,12 +52,14 @@ export const OpenstackCredentialsList: React.FC<ListComponentProps> = ({ secret,
label: t('Skip certificate validation'),
description: t('Migrate without validating a CA certificate'),
helperTextPopover: insecureSkipVerifyHelperTextPopover,
displayType: 'switch',
},
cacert: {
label: t('CA certificate'),
description: t(
'A CA certificate to be trusted when connecting to the OpenStack Identity (Keystone) endpoint. Ensure the CA certificate format is valid. To use a CA certificate, drag the file to the text box or browse for it. To use the system CA certificate, leave the field empty.',
),
displayType: 'textArea',
},
},

Expand All @@ -79,12 +84,14 @@ export const OpenstackCredentialsList: React.FC<ListComponentProps> = ({ secret,
label: t('Skip certificate validation'),
description: t('Migrate without validating a CA certificate'),
helperTextPopover: insecureSkipVerifyHelperTextPopover,
displayType: 'switch',
},
cacert: {
label: t('CA certificate'),
description: t(
'The Manager CA certificate unless it was replaced by a third-party certificate, in which case, enter the Manager Apache CA certificate.',
),
displayType: 'textArea',
},
},

Expand Down Expand Up @@ -112,12 +119,14 @@ export const OpenstackCredentialsList: React.FC<ListComponentProps> = ({ secret,
label: t('Skip certificate validation'),
description: t('Migrate without validating a CA certificate'),
helperTextPopover: insecureSkipVerifyHelperTextPopover,
displayType: 'switch',
},
cacert: {
label: t('CA certificate'),
description: t(
'The Manager CA certificate unless it was replaced by a third-party certificate, in which case, enter the Manager Apache CA certificate.',
),
displayType: 'textArea',
},
},

Expand Down Expand Up @@ -146,12 +155,14 @@ export const OpenstackCredentialsList: React.FC<ListComponentProps> = ({ secret,
label: t('Skip certificate validation'),
description: t('Migrate without validating a CA certificate'),
helperTextPopover: insecureSkipVerifyHelperTextPopover,
displayType: 'switch',
},
cacert: {
label: t('CA certificate'),
description: t(
'The Manager CA certificate unless it was replaced by a third-party certificate, in which case, enter the Manager Apache CA certificate.',
),
displayType: 'textArea',
},
},

Expand Down Expand Up @@ -187,12 +198,14 @@ export const OpenstackCredentialsList: React.FC<ListComponentProps> = ({ secret,
label: t('Skip certificate validation'),
description: t('Migrate without validating a CA certificate'),
helperTextPopover: insecureSkipVerifyHelperTextPopover,
displayType: 'switch',
},
cacert: {
label: t('CA certificate'),
description: t(
'The Manager CA certificate unless it was replaced by a third-party certificate, in which case, enter the Manager Apache CA certificate.',
),
displayType: 'textArea',
},
},
};
Expand Down Expand Up @@ -250,7 +263,7 @@ export const OpenstackCredentialsList: React.FC<ListComponentProps> = ({ secret,
</Text>
</div>
<div className="forklift-page-secret-content-div">
{reveal ? <ShowFieldWithClipboardCopy value={value} /> : <ShowMaskedField />}
{reveal ? <FieldWithClipboardCopy field={field} value={value} /> : <MaskedField />}
</div>
</>,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@ import { ForkliftTrans, useForkliftTranslation } from 'src/utils/i18n';

import { DescriptionList, Text, TextVariants } from '@patternfly/react-core';

import { ShowFieldWithClipboardCopy, ShowMaskedField } from '../../';
import { FieldWithClipboardCopy } from '../../FieldWithClipboardCopy';
import { MaskedField } from '../../MaskedField';
import { ListComponentProps } from '../BaseCredentialsSection';

import { Fields } from './Fields';

export const OvirtCredentialsList: React.FC<ListComponentProps> = ({ secret, reveal }) => {
const { t } = useForkliftTranslation();

Expand Down Expand Up @@ -39,7 +42,7 @@ export const OvirtCredentialsList: React.FC<ListComponentProps> = ({ secret, rev
</ForkliftTrans>
);

const fields = {
const fields: Fields = {
user: {
label: t('Username'),
description: t(
Expand All @@ -56,13 +59,15 @@ export const OvirtCredentialsList: React.FC<ListComponentProps> = ({ secret, rev
label: t('Skip certificate validation'),
description: t("If true, the provider's CA certificate won't be validated."),
helperTextPopover: insecureSkipVerifyHelperTextPopover,
displayType: 'switch',
},
cacert: {
label: t('CA certificate'),
description: t(
'A CA certificate to be trusted when connecting to the Red Hat Virtualization Manager (RHVM) API endpoint. Ensure the CA certificate format is in a PEM encoded X.509 format. To use a CA certificate, drag the file to the text box or browse for it. To use the system CA certificate, leave the field empty.',
),
helperTextPopover: cacertHelperTextPopover,
displayType: 'textArea',
},
};

Expand Down Expand Up @@ -91,7 +96,7 @@ export const OvirtCredentialsList: React.FC<ListComponentProps> = ({ secret, rev
</Text>
</div>
<div className="forklift-page-secret-content-div">
{reveal ? <ShowFieldWithClipboardCopy value={value} /> : <ShowMaskedField />}
{reveal ? <FieldWithClipboardCopy field={field} value={value} /> : <MaskedField />}
</div>
</>,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@ import { ForkliftTrans, useForkliftTranslation } from 'src/utils/i18n';

import { Text, TextVariants } from '@patternfly/react-core';

import { ShowFieldWithClipboardCopy, ShowMaskedField } from '../../';
import { FieldWithClipboardCopy } from '../../FieldWithClipboardCopy';
import { MaskedField } from '../../MaskedField';
import { ListComponentProps } from '../BaseCredentialsSection';

import { Fields } from './Fields';

export const VSphereCredentialsList: React.FC<ListComponentProps> = ({ secret, reveal }) => {
const { t } = useForkliftTranslation();

Expand Down Expand Up @@ -36,7 +39,7 @@ export const VSphereCredentialsList: React.FC<ListComponentProps> = ({ secret, r
</ForkliftTrans>
);

const fields = {
const fields: Fields = {
user: {
label: t('Username'),
description: (
Expand All @@ -56,13 +59,15 @@ export const VSphereCredentialsList: React.FC<ListComponentProps> = ({ secret, r
label: t('Skip certificate validation'),
description: t("If true, the provider's TLS certificate won't be validated."),
cacertHelperTextPopover: insecureSkipVerifyHelperTextPopover,
displayType: 'switch',
},
cacert: {
label: t('CA certificate'),
description: t(
'A CA certificate to be trusted when connecting to the vCenter API endpoint. Ensure the CA certificate format is in a PEM encoded X.509 format. To use a CA certificate, drag the file to the text box or browse for it. To use the system CA certificate, leave the field empty.',
),
helperTextPopover: cacertHelperTextPopover,
displayType: 'textArea',
},
};

Expand All @@ -82,7 +87,7 @@ export const VSphereCredentialsList: React.FC<ListComponentProps> = ({ secret, r
</Text>
</div>
<div className="forklift-page-secret-content-div">
{reveal ? <ShowFieldWithClipboardCopy value={value} /> : <ShowMaskedField />}
{reveal ? <FieldWithClipboardCopy field={field} value={value} /> : <MaskedField />}
</div>
</>,
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// @index('./*.tsx', f => `export * from '${f.path}';`)
export * from './Fields';
export * from './OpenshiftCredentialsList';
export * from './OpenstackCredentialsList';
export * from './OvirtCredentialsList';
Expand Down
Loading

0 comments on commit 642ffd3

Please sign in to comment.