Merge FieldTooltip and DetailPopover into single Popover component

This commit is contained in:
Marliana Lara 2020-10-07 13:21:41 -04:00
parent 677fb594e8
commit 35ba74d265
No known key found for this signature in database
GPG Key ID: 38C73B40DFA809EE
44 changed files with 193 additions and 249 deletions

View File

@ -6,7 +6,7 @@ import PropTypes from 'prop-types';
import { useField } from 'formik';
import { Form, FormGroup } from '@patternfly/react-core';
import { CredentialsAPI } from '../../api';
import { FieldTooltip } from '../FormField';
import Popover from '../Popover';
import { getQSConfig, parseQueryString, mergeParams } from '../../util/qs';
import useRequest from '../../util/useRequest';
@ -72,7 +72,7 @@ function AdHocCredentialStep({ i18n, credentialTypeId, onEnableLaunch }) {
}
helperTextInvalid={credentialMeta.error}
labelIcon={
<FieldTooltip
<Popover
content={i18n._(
t`Select the credential you want to use when accessing the remote hosts to run the command. Choose the credential containing the username and SSH key or password that Ansible will need to log into the remote hosts.`
)}

View File

@ -9,13 +9,14 @@ import styled from 'styled-components';
import { BrandName } from '../../variables';
import AnsibleSelect from '../AnsibleSelect';
import FormField, { FieldTooltip } from '../FormField';
import FormField from '../FormField';
import { VariablesField } from '../CodeMirrorInput';
import {
FormColumnLayout,
FormFullWidthLayout,
FormCheckboxLayout,
} from '../FormLayout';
import Popover from '../Popover';
import { required } from '../../util/validators';
const TooltipWrapper = styled.div`
@ -68,7 +69,7 @@ function AdHocDetailsStep({ i18n, verbosityOptions, moduleOptions }) {
: 'error'
}
labelIcon={
<FieldTooltip
<Popover
content={i18n._(
t`These are the modules that ${brandName} supports running commands against.`
)}
@ -146,7 +147,7 @@ function AdHocDetailsStep({ i18n, verbosityOptions, moduleOptions }) {
}
helperTextInvalid={verbosityMeta.error}
labelIcon={
<FieldTooltip
<Popover
content={i18n._(
t`These are the verbosity levels for standard out of the command run that are supported.`
)}
@ -211,7 +212,7 @@ function AdHocDetailsStep({ i18n, verbosityOptions, moduleOptions }) {
label={i18n._(t`Show changes`)}
aria-label={i18n._(t`Show changes`)}
labelIcon={
<FieldTooltip
<Popover
content={i18n._(
t`If enabled, show the changes made by Ansible tasks, where supported. This is equivalent to Ansibles --diff mode.`
)}
@ -238,7 +239,7 @@ function AdHocDetailsStep({ i18n, verbosityOptions, moduleOptions }) {
<span>
{i18n._(t`Enable privilege escalation`)}
&nbsp;
<FieldTooltip
<Popover
content={
<p>
{i18n._(t`Enables creation of a provisioning

View File

@ -12,7 +12,7 @@ import {
import { useField } from 'formik';
import { FormGroup } from '@patternfly/react-core';
import CodeMirrorInput from './CodeMirrorInput';
import { FieldTooltip } from '../FormField';
import Popover from '../Popover';
function CodeMirrorField({
id,
@ -37,7 +37,7 @@ function CodeMirrorField({
isRequired={isRequired}
validated={isValid ? 'default' : 'error'}
label={label}
labelIcon={<FieldTooltip content={tooltip} />}
labelIcon={<Popover content={tooltip} />}
>
<CodeMirrorInput
id={id}

View File

@ -4,7 +4,7 @@ import { node, number, oneOfType, shape, string, arrayOf } from 'prop-types';
import { Split, SplitItem, TextListItemVariants } from '@patternfly/react-core';
import { DetailName, DetailValue } from '../DetailList';
import MultiButtonToggle from '../MultiButtonToggle';
import DetailPopover from '../DetailPopover';
import Popover from '../Popover';
import {
yamlToJson,
jsonToYaml,
@ -69,7 +69,7 @@ function VariablesDetail({ dataCy, helpText, value, label, rows, fullHeight }) {
{label}
</span>
{helpText && (
<DetailPopover header={label} content={helpText} id={dataCy} />
<Popover header={label} content={helpText} id={dataCy} />
)}
</div>
</SplitItem>
@ -122,9 +122,13 @@ VariablesDetail.propTypes = {
value: oneOfType([shape({}), arrayOf(string), string]).isRequired,
label: node.isRequired,
rows: number,
dataCy: string,
helpText: string,
};
VariablesDetail.defaultProps = {
rows: null,
dataCy: '',
helpText: '',
};
export default VariablesDetail;

View File

@ -5,10 +5,11 @@ import { t } from '@lingui/macro';
import { useField } from 'formik';
import styled from 'styled-components';
import { Split, SplitItem } from '@patternfly/react-core';
import { CheckboxField, FieldTooltip } from '../FormField';
import { CheckboxField } from '../FormField';
import MultiButtonToggle from '../MultiButtonToggle';
import { yamlToJson, jsonToYaml, isJsonString } from '../../util/yaml';
import CodeMirrorInput from './CodeMirrorInput';
import Popover from '../Popover';
import { JSON_MODE, YAML_MODE } from './constants';
const FieldHeader = styled.div`
@ -43,7 +44,7 @@ function VariablesField({
<label htmlFor={id} className="pf-c-form__label">
<span className="pf-c-form__label-text">{label}</span>
</label>
{tooltip && <FieldTooltip content={tooltip} />}
{tooltip && <Popover content={tooltip} id={id} />}
</SplitItem>
<SplitItem>
<MultiButtonToggle

View File

@ -83,7 +83,7 @@ describe('VariablesField', () => {
)}
</Formik>
);
expect(wrapper.find('Popover').length).toBe(1);
expect(wrapper.find('Popover[data-cy="the-field"]').length).toBe(1);
});
it('should submit value through Formik', async () => {

View File

@ -1,17 +1,30 @@
import 'styled-components/macro';
import React from 'react';
import { shape, node, number, oneOf } from 'prop-types';
import { shape, node, number, oneOf, string } from 'prop-types';
import { TextListItemVariants } from '@patternfly/react-core';
import { DetailName, DetailValue } from './Detail';
import CodeMirrorInput from '../CodeMirrorInput';
import Popover from '../Popover';
function CodeDetail({
value,
label,
mode,
rows,
fullHeight,
helpText,
dataCy,
}) {
const labelCy = dataCy ? `${dataCy}-label` : null;
const valueCy = dataCy ? `${dataCy}-value` : null;
function CodeDetail({ value, label, mode, rows, fullHeight }) {
return (
<>
<DetailName
component={TextListItemVariants.dt}
fullWidth
css="grid-column: 1 / -1"
data-cy={labelCy}
>
<div className="pf-c-form__label">
<span
@ -20,12 +33,16 @@ function CodeDetail({ value, label, mode, rows, fullHeight }) {
>
{label}
</span>
{helpText && (
<Popover header={label} content={helpText} id={dataCy} />
)}
</div>
</DetailName>
<DetailValue
component={TextListItemVariants.dd}
fullWidth
css="grid-column: 1 / -1; margin-top: -20px"
data-cy={valueCy}
>
<CodeMirrorInput
mode={mode}
@ -42,11 +59,15 @@ function CodeDetail({ value, label, mode, rows, fullHeight }) {
CodeDetail.propTypes = {
value: shape.isRequired,
label: node.isRequired,
dataCy: string,
helpText: string,
rows: number,
mode: oneOf(['json', 'yaml', 'jinja2']).isRequired,
};
CodeDetail.defaultProps = {
rows: null,
helpText: '',
dataCy: '',
};
export default CodeDetail;

View File

@ -2,7 +2,7 @@ import React from 'react';
import { node, bool, string } from 'prop-types';
import { TextListItem, TextListItemVariants } from '@patternfly/react-core';
import styled from 'styled-components';
import DetailPopover from '../DetailPopover';
import Popover from '../Popover';
const DetailName = styled(({ fullWidth, ...props }) => (
<TextListItem {...props} />
@ -61,9 +61,7 @@ const Detail = ({
id={dataCy}
>
{label}
{helpText && (
<DetailPopover header={label} content={helpText} id={dataCy} />
)}
{helpText && <Popover header={label} content={helpText} id={dataCy} />}
</DetailName>
<DetailValue
className={className}

View File

@ -1,51 +0,0 @@
import React, { useState } from 'react';
import { node, string } from 'prop-types';
import { Button as _Button, Popover } from '@patternfly/react-core';
import { OutlinedQuestionCircleIcon } from '@patternfly/react-icons';
import styled from 'styled-components';
const Button = styled(_Button)`
--pf-c-button--PaddingTop: 0;
--pf-c-button--PaddingBottom: 0;
`;
function DetailPopover({ header, content, id }) {
const [showPopover, setShowPopover] = useState(false);
if (!content) {
return null;
}
return (
<Popover
bodyContent={content}
headerContent={header}
hideOnOutsideClick
id={id}
isVisible={showPopover}
shouldClose={() => setShowPopover(false)}
>
<Button
onClick={() => setShowPopover(!showPopover)}
variant="plain"
aria-haspopup="true"
aria-expanded={showPopover}
>
<OutlinedQuestionCircleIcon
onClick={() => setShowPopover(!showPopover)}
/>
</Button>
</Popover>
);
}
DetailPopover.propTypes = {
content: node,
header: node,
id: string,
};
DetailPopover.defaultProps = {
content: null,
header: null,
id: 'detail-popover',
};
export default DetailPopover;

View File

@ -1 +0,0 @@
export { default } from './DetailPopover';

View File

@ -3,7 +3,8 @@ import { bool, node, string } from 'prop-types';
import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro';
import styled from 'styled-components';
import { CheckboxField, FieldTooltip } from '../FormField';
import { CheckboxField } from '../FormField';
import Popover from '../Popover';
const FieldHeader = styled.div`
display: flex;
@ -38,7 +39,7 @@ function FieldWithPrompt({
</span>
)}
</label>
{tooltip && <FieldTooltip content={tooltip} />}
{tooltip && <Popover content={tooltip} id={fieldId} />}
</div>
<StyledCheckboxField
isDisabled={isDisabled}

View File

@ -10,7 +10,7 @@ describe('FieldWithPrompt', () => {
wrapper.unmount();
});
test('Required asterisk and Tooltip hidden when not required and tooltip not provided', () => {
test('Required asterisk and Popover hidden when not required and tooltip not provided', () => {
wrapper = mountWithContexts(
<Formik
initialValues={{
@ -33,10 +33,10 @@ describe('FieldWithPrompt', () => {
</Formik>
);
expect(wrapper.find('.pf-c-form__label-required')).toHaveLength(0);
expect(wrapper.find('Tooltip')).toHaveLength(0);
expect(wrapper.find('Popover')).toHaveLength(0);
});
test('Required asterisk and Tooltip shown when required and tooltip provided', () => {
test('Required asterisk and Popover shown when required and tooltip provided', () => {
wrapper = mountWithContexts(
<Formik
initialValues={{
@ -61,6 +61,8 @@ describe('FieldWithPrompt', () => {
</Formik>
);
expect(wrapper.find('.pf-c-form__label-required')).toHaveLength(1);
expect(wrapper.find('Popover')).toHaveLength(1);
expect(wrapper.find('Popover[data-cy="job-template-limit"]').length).toBe(
1
);
});
});

View File

@ -2,7 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import { useField } from 'formik';
import { FormGroup, TextArea } from '@patternfly/react-core';
import FieldTooltip from './FieldTooltip';
import Popover from '../Popover';
function ArrayTextField(props) {
const {
@ -30,7 +30,7 @@ function ArrayTextField(props) {
isRequired={isRequired}
validated={isValid ? 'default' : 'error'}
label={label}
labelIcon={<FieldTooltip content={tooltip} maxWidth={tooltipMaxWidth} />}
labelIcon={<Popover content={tooltip} maxWidth={tooltipMaxWidth} />}
>
<TextArea
id={id}

View File

@ -1,13 +1,8 @@
import React from 'react';
import { string, func, node } from 'prop-types';
import { useField } from 'formik';
import { Checkbox, Tooltip } from '@patternfly/react-core';
import { QuestionCircleIcon as PFQuestionCircleIcon } from '@patternfly/react-icons';
import styled from 'styled-components';
const QuestionCircleIcon = styled(PFQuestionCircleIcon)`
margin-left: 10px;
`;
import { Checkbox } from '@patternfly/react-core';
import Popover from '../Popover';
function CheckboxField({
id,
@ -27,11 +22,7 @@ function CheckboxField({
<span>
{label}
&nbsp;
{tooltip && (
<Tooltip position="right" content={tooltip}>
<QuestionCircleIcon />
</Tooltip>
)}
{tooltip && <Popover content={tooltip} />}
</span>
}
id={id}

View File

@ -1,35 +0,0 @@
import React, { useState } from 'react';
import { node } from 'prop-types';
import { Popover } from '@patternfly/react-core';
import { QuestionCircleIcon as PFQuestionCircleIcon } from '@patternfly/react-icons';
import styled from 'styled-components';
const QuestionCircleIcon = styled(PFQuestionCircleIcon)`
margin-left: 10px;
`;
function FieldTooltip({ content, ...rest }) {
const [showTooltip, setShowTooltip] = useState(false);
if (!content) {
return null;
}
return (
<Popover
bodyContent={content}
isVisible={showTooltip}
hideOnOutsideClick
shouldClose={() => setShowTooltip(false)}
{...rest}
>
<QuestionCircleIcon onClick={() => setShowTooltip(!showTooltip)} />
</Popover>
);
}
FieldTooltip.propTypes = {
content: node,
};
FieldTooltip.defaultProps = {
content: null,
};
export default FieldTooltip;

View File

@ -2,7 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import { useField } from 'formik';
import { FormGroup, TextInput, TextArea } from '@patternfly/react-core';
import FieldTooltip from './FieldTooltip';
import Popover from '../Popover';
function FormField(props) {
const {
@ -31,9 +31,7 @@ function FormField(props) {
isRequired={isRequired}
validated={isValid ? 'default' : 'error'}
label={label}
labelIcon={
<FieldTooltip content={tooltip} maxWidth={tooltipMaxWidth} />
}
labelIcon={<Popover content={tooltip} maxWidth={tooltipMaxWidth} />}
>
<TextArea
id={id}
@ -55,9 +53,7 @@ function FormField(props) {
isRequired={isRequired}
validated={isValid ? 'default' : 'error'}
label={label}
labelIcon={
<FieldTooltip content={tooltip} maxWidth={tooltipMaxWidth} />
}
labelIcon={<Popover content={tooltip} maxWidth={tooltipMaxWidth} />}
>
<TextInput
id={id}

View File

@ -2,10 +2,11 @@ import React from 'react';
import PropTypes from 'prop-types';
import { useField } from 'formik';
import { FormGroup, InputGroup } from '@patternfly/react-core';
import Popover from '../Popover';
import PasswordInput from './PasswordInput';
function PasswordField(props) {
const { id, name, label, validate, isRequired } = props;
const { id, name, label, validate, isRequired, helperText } = props;
const [, meta] = useField({ name, validate });
const isValid = !(meta.touched && meta.error);
@ -16,6 +17,7 @@ function PasswordField(props) {
isRequired={isRequired}
validated={isValid ? 'default' : 'error'}
label={label}
labelIcon={helperText && <Popover content={helperText} />}
>
<InputGroup>
<PasswordInput {...props} />

View File

@ -1,6 +1,5 @@
export { default } from './FormField';
export { default as CheckboxField } from './CheckboxField';
export { default as FieldTooltip } from './FieldTooltip';
export { default as PasswordField } from './PasswordField';
export { default as PasswordInput } from './PasswordInput';
export { default as FormSubmitError } from './FormSubmitError';

View File

@ -5,11 +5,12 @@ import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro';
import { Form, FormGroup } from '@patternfly/react-core';
import FormField, { FormSubmitError, FieldTooltip } from '../FormField';
import FormField, { FormSubmitError } from '../FormField';
import FormActionGroup from '../FormActionGroup/FormActionGroup';
import { VariablesField } from '../CodeMirrorInput';
import { InventoryLookup } from '../Lookup';
import { FormColumnLayout, FormFullWidthLayout } from '../FormLayout';
import Popover from '../Popover';
import { required } from '../../util/validators';
const InventoryLookupField = withI18n()(({ i18n, host }) => {
@ -26,7 +27,7 @@ const InventoryLookupField = withI18n()(({ i18n, host }) => {
<FormGroup
label={i18n._(t`Inventory`)}
labelIcon={
<FieldTooltip
<Popover
content={i18n._(
t`Select the inventory that this host will belong to.`
)}

View File

@ -4,10 +4,11 @@ import { t } from '@lingui/macro';
import { useField } from 'formik';
import { Form, FormGroup, Switch } from '@patternfly/react-core';
import styled from 'styled-components';
import FormField, { FieldTooltip } from '../../FormField';
import FormField from '../../FormField';
import { TagMultiSelect } from '../../MultiSelect';
import AnsibleSelect from '../../AnsibleSelect';
import { VariablesField } from '../../CodeMirrorInput';
import Popover from '../../Popover';
const FieldHeader = styled.div`
display: flex;
@ -104,7 +105,7 @@ function JobTypeField({ i18n }) {
fieldId="propmt-job-type"
label={i18n._(t`Job Type`)}
labelIcon={
<FieldTooltip
<Popover
content={i18n._(t`For job templates, select run to execute the playbook.
Select check to only check playbook syntax, test environment setup,
and report problems without executing the playbook.`)}
@ -141,7 +142,7 @@ function VerbosityField({ i18n }) {
validated={isValid ? 'default' : 'error'}
label={i18n._(t`Verbosity`)}
labelIcon={
<FieldTooltip
<Popover
content={i18n._(t`Control the level of output ansible
will produce as the playbook executes.`)}
/>
@ -166,7 +167,7 @@ function ShowChangesToggle({ i18n }) {
<label className="pf-c-form__label" htmlFor="prompt-show-changes">
<span className="pf-c-form__label-text">
{i18n._(t`Show Changes`)}
<FieldTooltip
<Popover
content={i18n._(t`If enabled, show the changes made
by Ansible tasks, where supported. This is equivalent to Ansibles
--diff mode.`)}
@ -192,7 +193,7 @@ function TagField({ id, name, label, tooltip }) {
<FormGroup
fieldId={id}
label={label}
labelIcon={<FieldTooltip content={tooltip} />}
labelIcon={<Popover content={tooltip} />}
>
<TagMultiSelect value={field.value} onChange={helpers.setValue} />
</FormGroup>

View File

@ -9,8 +9,9 @@ import {
SelectOption,
SelectVariant,
} from '@patternfly/react-core';
import FormField, { FieldTooltip } from '../../FormField';
import FormField from '../../FormField';
import AnsibleSelect from '../../AnsibleSelect';
import Popover from '../../Popover';
import {
required,
minMaxValue,
@ -99,7 +100,7 @@ function MultipleChoiceField({ question }) {
isRequired={question.required}
validated={isValid ? 'default' : 'error'}
label={question.question_name}
labelIcon={<FieldTooltip content={question.question_description} />}
labelIcon={<Popover content={question.question_description} />}
>
<AnsibleSelect
id={id}
@ -134,7 +135,7 @@ function MultiSelectField({ question, i18n }) {
isRequired={question.required}
validated={isValid ? 'default' : 'error'}
label={question.question_name}
labelIcon={<FieldTooltip content={question.question_description} />}
labelIcon={<Popover content={question.question_description} />}
>
<Select
variant={SelectVariant.typeaheadMulti}

View File

@ -15,7 +15,7 @@ import { FormGroup } from '@patternfly/react-core';
import { CredentialsAPI } from '../../api';
import { Credential } from '../../types';
import { getQSConfig, parseQueryString, mergeParams } from '../../util/qs';
import { FieldTooltip } from '../FormField';
import Popover from '../Popover';
import Lookup from './Lookup';
import OptionsList from '../OptionsList';
import useAutoPopulateLookup from '../../util/useAutoPopulateLookup';
@ -117,7 +117,7 @@ function CredentialLookup({
isRequired={required}
validated={isValid ? 'default' : 'error'}
label={label}
labelIcon={tooltip && <FieldTooltip content={tooltip} />}
labelIcon={tooltip && <Popover content={tooltip} />}
helperTextInvalid={helperTextInvalid}
>
<Lookup

View File

@ -6,7 +6,7 @@ import { t } from '@lingui/macro';
import { FormGroup } from '@patternfly/react-core';
import { InstanceGroupsAPI } from '../../api';
import { getQSConfig, parseQueryString } from '../../util/qs';
import { FieldTooltip } from '../FormField';
import Popover from '../Popover';
import OptionsList from '../OptionsList';
import useRequest from '../../util/useRequest';
import Lookup from './Lookup';
@ -68,7 +68,7 @@ function InstanceGroupsLookup(props) {
<FormGroup
className={className}
label={i18n._(t`Instance Groups`)}
labelIcon={tooltip && <FieldTooltip content={tooltip} />}
labelIcon={tooltip && <Popover content={tooltip} />}
fieldId="org-instance-groups"
>
<Lookup

View File

@ -6,7 +6,7 @@ import { t } from '@lingui/macro';
import { FormGroup } from '@patternfly/react-core';
import { ProjectsAPI } from '../../api';
import { Project } from '../../types';
import { FieldTooltip } from '../FormField';
import Popover from '../Popover';
import OptionsList from '../OptionsList';
import useAutoPopulateLookup from '../../util/useAutoPopulateLookup';
import useRequest from '../../util/useRequest';
@ -80,7 +80,7 @@ function ProjectLookup({
isRequired={required}
validated={isValid ? 'default' : 'error'}
label={i18n._(t`Project`)}
labelIcon={tooltip && <FieldTooltip content={tooltip} />}
labelIcon={tooltip && <Popover content={tooltip} />}
>
<Lookup
id="project"

View File

@ -0,0 +1,51 @@
import React from 'react';
import { node, string } from 'prop-types';
import { Popover as PFPopover } from '@patternfly/react-core';
import { HelpIcon } from '@patternfly/react-icons';
import styled from 'styled-components';
const PopoverButton = styled.button`
padding: var(--pf-global--spacer--xs);
margin: -(var(--pf-global--spacer--xs));
`;
function Popover({ content, header, id, maxWidth, ...rest }) {
if (!content) {
return null;
}
return (
<PFPopover
bodyContent={content}
headerContent={header}
hideOnOutsideClick
id={id}
data-cy={id}
maxWidth={maxWidth}
{...rest}
>
<PopoverButton
aria-haspopup="true"
className="pf-c-form__group-label-help"
onClick={e => e.preventDefault()}
type="button"
>
<HelpIcon noVerticalAlign />
</PopoverButton>
</PFPopover>
);
}
Popover.propTypes = {
content: node,
header: node,
id: string,
maxWidth: string,
};
Popover.defaultProps = {
content: null,
header: null,
id: '',
maxWidth: '',
};
export default Popover;

View File

@ -0,0 +1 @@
export { default } from './Popover';

View File

@ -7,14 +7,12 @@ import { Form, FormGroup } from '@patternfly/react-core';
import PropTypes from 'prop-types';
import { required } from '../../../util/validators';
import FormField, {
FormSubmitError,
FieldTooltip,
} from '../../../components/FormField';
import FormField, { FormSubmitError } from '../../../components/FormField';
import { FormColumnLayout } from '../../../components/FormLayout';
import FormActionGroup from '../../../components/FormActionGroup/FormActionGroup';
import OrganizationLookup from '../../../components/Lookup/OrganizationLookup';
import AnsibleSelect from '../../../components/AnsibleSelect';
import Popover from '../../../components/Popover';
function ApplicationFormFields({
i18n,
@ -85,7 +83,7 @@ function ApplicationFormFields({
isRequired
label={i18n._(t`Authorization grant type`)}
labelIcon={
<FieldTooltip
<Popover
content={i18n._(
t`The Grant type the user must use for acquire tokens for this application`
)}
@ -129,7 +127,7 @@ function ApplicationFormFields({
isRequired
label={i18n._(t`Client type`)}
labelIcon={
<FieldTooltip
<Popover
content={i18n._(
t`Set to Public or Confidential depending on how secure the client device is.`
)}

View File

@ -7,7 +7,7 @@ import {
SelectOption,
SelectVariant,
} from '@patternfly/react-core';
import { FieldTooltip } from '../../../../components/FormField';
import Popover from '../../../../components/Popover';
function BecomeMethodField({ fieldOptions, isRequired }) {
const [isOpen, setIsOpen] = useState(false);
@ -36,9 +36,7 @@ function BecomeMethodField({ fieldOptions, isRequired }) {
helperTextInvalid={meta.error}
label={fieldOptions.label}
labelIcon={
fieldOptions.help_text && (
<FieldTooltip content={fieldOptions.help_text} />
)
fieldOptions.help_text && <Popover content={fieldOptions.help_text} />
}
isRequired={isRequired}
validated={!(meta.touched && meta.error) ? 'default' : 'error'}

View File

@ -10,8 +10,9 @@ import {
InputGroup,
TextInput,
} from '@patternfly/react-core';
import { FieldTooltip, PasswordInput } from '../../../../components/FormField';
import { PasswordInput } from '../../../../components/FormField';
import AnsibleSelect from '../../../../components/AnsibleSelect';
import Popover from '../../../../components/Popover';
import { CredentialType } from '../../../../types';
import { required } from '../../../../util/validators';
import { CredentialPluginField } from '../CredentialPlugins';
@ -140,9 +141,7 @@ function CredentialField({ credentialType, fieldOptions, i18n }) {
helperTextInvalid={meta.error}
label={fieldOptions.label}
labelIcon={
fieldOptions.help_text && (
<FieldTooltip content={fieldOptions.help_text} />
)
fieldOptions.help_text && <Popover content={fieldOptions.help_text} />
}
isRequired={isRequired}
validated={isValid ? 'default' : 'error'}

View File

@ -11,8 +11,8 @@ import {
Tooltip,
} from '@patternfly/react-core';
import { KeyIcon } from '@patternfly/react-icons';
import { FieldTooltip } from '../../../../components/FormField';
import FieldWithPrompt from '../../../../components/FieldWithPrompt';
import Popover from '../../../../components/Popover';
import { CredentialPluginPrompt } from './CredentialPluginPrompt';
import CredentialPluginSelected from './CredentialPluginSelected';
@ -130,7 +130,7 @@ function CredentialPluginField(props) {
label={fieldOptions.label}
labelIcon={
fieldOptions.help_text && (
<FieldTooltip content={fieldOptions.help_text} />
<Popover content={fieldOptions.help_text} />
)
}
>

View File

@ -1,22 +1,17 @@
import React, { useCallback, useEffect } from 'react';
import { withI18n } from '@lingui/react';
import { useField, useFormikContext } from 'formik';
import styled from 'styled-components';
import { Form, FormGroup, Tooltip } from '@patternfly/react-core';
import { QuestionCircleIcon as PFQuestionCircleIcon } from '@patternfly/react-icons';
import { Form, FormGroup } from '@patternfly/react-core';
import { CredentialTypesAPI } from '../../../../../api';
import AnsibleSelect from '../../../../../components/AnsibleSelect';
import ContentError from '../../../../../components/ContentError';
import ContentLoading from '../../../../../components/ContentLoading';
import FormField from '../../../../../components/FormField';
import { FormFullWidthLayout } from '../../../../../components/FormLayout';
import Popover from '../../../../../components/Popover';
import useRequest from '../../../../../util/useRequest';
import { required } from '../../../../../util/validators';
const QuestionCircleIcon = styled(PFQuestionCircleIcon)`
margin-left: 10px;
`;
function MetadataStep({ i18n }) {
const form = useFormikContext();
const [selectedCredential] = useField('credential');
@ -82,12 +77,10 @@ function MetadataStep({ i18n }) {
fieldId={`credential-${field.id}`}
label={field.label}
isRequired={field.required}
labelIcon={
field.help_text && <Popover content={field.help_text} />
}
>
{field.help_text && (
<Tooltip content={field.help_text} position="right">
<QuestionCircleIcon />
</Tooltip>
)}
<AnsibleSelect
name={`inputs.${field.id}`}
value={form.values.inputs[field.id]}

View File

@ -1,29 +1,18 @@
import React, { useCallback } from 'react';
import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro';
import styled from 'styled-components';
import { func, shape } from 'prop-types';
import { Formik } from 'formik';
import {
Button,
Form,
FormGroup,
Modal,
Tooltip,
} from '@patternfly/react-core';
import { QuestionCircleIcon as PFQuestionCircleIcon } from '@patternfly/react-icons';
import { Button, Form, FormGroup, Modal } from '@patternfly/react-core';
import { CredentialsAPI, CredentialTypesAPI } from '../../../api';
import AnsibleSelect from '../../../components/AnsibleSelect';
import FormField from '../../../components/FormField';
import { FormFullWidthLayout } from '../../../components/FormLayout';
import Popover from '../../../components/Popover';
import { required } from '../../../util/validators';
import useRequest from '../../../util/useRequest';
import { CredentialPluginTestAlert } from './CredentialPlugins';
const QuestionCircleIcon = styled(PFQuestionCircleIcon)`
margin-left: 10px;
`;
function ExternalTestModal({
i18n,
credential,
@ -124,12 +113,7 @@ function ExternalTestModal({
label={field.label}
labelIcon={
field.help_text && (
<Tooltip
content={field.help_text}
position="right"
>
<QuestionCircleIcon />
</Tooltip>
<Popover content={field.help_text} />
)
}
isRequired={isRequired}

View File

@ -11,7 +11,6 @@ import ContentError from '../../../components/ContentError';
import ContentLoading from '../../../components/ContentLoading';
import CredentialChip from '../../../components/CredentialChip';
import DeleteButton from '../../../components/DeleteButton';
import { FieldTooltip } from '../../../components/FormField';
import InventorySourceSyncButton from '../shared/InventorySourceSyncButton';
import {
DetailList,
@ -19,6 +18,7 @@ import {
UserDateDetail,
} from '../../../components/DetailList';
import ErrorDetail from '../../../components/ErrorDetail';
import Popover from '../../../components/Popover';
import useRequest from '../../../util/useRequest';
import { InventorySourcesAPI } from '../../../api';
@ -112,7 +112,7 @@ function InventorySourceDetail({ inventorySource, i18n }) {
{overwrite && (
<ListItem>
{i18n._(t`Overwrite`)}
<FieldTooltip
<Popover
content={
<>
{i18n._(t`If checked, any hosts and groups that were
@ -135,7 +135,7 @@ function InventorySourceDetail({ inventorySource, i18n }) {
{overwrite_vars && (
<ListItem>
{i18n._(t`Overwrite variables`)}
<FieldTooltip
<Popover
content={
<>
{i18n._(t`If checked, all variables for child groups
@ -154,7 +154,7 @@ function InventorySourceDetail({ inventorySource, i18n }) {
{update_on_launch && (
<ListItem>
{i18n._(t`Update on launch`)}
<FieldTooltip
<Popover
content={i18n._(t`Each time a job runs using this inventory,
refresh the inventory from the selected source before
executing job tasks.`)}
@ -164,7 +164,7 @@ function InventorySourceDetail({ inventorySource, i18n }) {
{update_on_project_update && (
<ListItem>
{i18n._(t`Update on project update`)}
<FieldTooltip
<Popover
content={i18n._(t`After every project update where the SCM revision
changes, refresh the inventory from the selected source
before executing job tasks. This is intended for static content,

View File

@ -13,14 +13,12 @@ import AnsibleSelect from '../../../components/AnsibleSelect';
import ContentError from '../../../components/ContentError';
import ContentLoading from '../../../components/ContentLoading';
import FormActionGroup from '../../../components/FormActionGroup/FormActionGroup';
import FormField, {
FieldTooltip,
FormSubmitError,
} from '../../../components/FormField';
import FormField, { FormSubmitError } from '../../../components/FormField';
import {
FormColumnLayout,
SubFormLayout,
} from '../../../components/FormLayout';
import Popover from '../../../components/Popover';
import {
AzureSubForm,
@ -145,7 +143,7 @@ const InventorySourceFormFields = ({ source, sourceOptions, i18n }) => {
fieldId="custom-virtualenv"
label={i18n._(t`Ansible Environment`)}
labelIcon={
<FieldTooltip
<Popover
content={i18n._(t`Select the custom
Python virtual environment for this
inventory source sync to run on.`)}

View File

@ -8,9 +8,9 @@ import useRequest from '../../../../util/useRequest';
import { required } from '../../../../util/validators';
import AnsibleSelect from '../../../../components/AnsibleSelect';
import { FieldTooltip } from '../../../../components/FormField';
import CredentialLookup from '../../../../components/Lookup/CredentialLookup';
import ProjectLookup from '../../../../components/Lookup/ProjectLookup';
import Popover from '../../../../components/Popover';
import {
OptionsField,
SourceVarsField,
@ -99,7 +99,7 @@ const SCMSubForm = ({ autoPopulateProject, i18n }) => {
isRequired
label={i18n._(t`Inventory file`)}
labelIcon={
<FieldTooltip
<Popover
content={i18n._(t`Select the inventory file
to be synced by this source. You can select from
the dropdown or enter a file within the input.`)}

View File

@ -6,14 +6,12 @@ import { FormGroup } from '@patternfly/react-core';
import { minMaxValue, regExp } from '../../../../util/validators';
import AnsibleSelect from '../../../../components/AnsibleSelect';
import { VariablesField } from '../../../../components/CodeMirrorInput';
import FormField, {
CheckboxField,
FieldTooltip,
} from '../../../../components/FormField';
import FormField, { CheckboxField } from '../../../../components/FormField';
import {
FormFullWidthLayout,
FormCheckboxLayout,
} from '../../../../components/FormLayout';
import Popover from '../../../../components/Popover';
export const SourceVarsField = withI18n()(({ i18n }) => (
<FormFullWidthLayout>
@ -39,7 +37,7 @@ export const VerbosityField = withI18n()(({ i18n }) => {
validated={isValid ? 'default' : 'error'}
label={i18n._(t`Verbosity`)}
labelIcon={
<FieldTooltip
<Popover
content={i18n._(t`Control the level of output Ansible
will produce for inventory source update jobs.`)}
/>

View File

@ -10,10 +10,7 @@ import AnsibleSelect from '../../../components/AnsibleSelect';
import ContentError from '../../../components/ContentError';
import ContentLoading from '../../../components/ContentLoading';
import FormActionGroup from '../../../components/FormActionGroup/FormActionGroup';
import FormField, {
FieldTooltip,
FormSubmitError,
} from '../../../components/FormField';
import FormField, { FormSubmitError } from '../../../components/FormField';
import OrganizationLookup from '../../../components/Lookup/OrganizationLookup';
import { CredentialTypesAPI, ProjectsAPI } from '../../../api';
import { required } from '../../../util/validators';
@ -21,6 +18,7 @@ import {
FormColumnLayout,
SubFormLayout,
} from '../../../components/FormLayout';
import Popover from '../../../components/Popover';
import {
GitSubForm,
HgSubForm,
@ -283,7 +281,7 @@ function ProjectFormFields({
fieldId="project-custom-virtualenv"
label={i18n._(t`Ansible Environment`)}
labelIcon={
<FieldTooltip
<Popover
content={i18n._(t`Select the playbook to be executed by
this job.`)}
/>

View File

@ -6,7 +6,8 @@ import { useField } from 'formik';
import { FormGroup, Alert } from '@patternfly/react-core';
import { required } from '../../../../util/validators';
import AnsibleSelect from '../../../../components/AnsibleSelect';
import FormField, { FieldTooltip } from '../../../../components/FormField';
import FormField from '../../../../components/FormField';
import Popover from '../../../../components/Popover';
import { BrandName } from '../../../../variables';
// Setting BrandName to a variable here is necessary to get the jest tests
@ -84,7 +85,7 @@ const ManualSubForm = ({
validated={!pathMeta.touched || !pathMeta.error ? 'default' : 'error'}
label={i18n._(t`Playbook Directory`)}
labelIcon={
<FieldTooltip
<Popover
content={i18n._(t`Select from the list of directories found in
the Project Base Path. Together the base path and the playbook
directory provide the full path used to locate playbooks.`)}

View File

@ -3,7 +3,6 @@ import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro';
import { Detail } from '../../../components/DetailList';
import { VariablesDetail } from '../../../components/CodeMirrorInput';
// import DetailPopover from '../../../components/DetailList/DetailPopover';
export default withI18n()(
({ i18n, helpText, id, label, type, unit = '', value }) => {

View File

@ -10,9 +10,9 @@ import FormField, {
CheckboxField,
PasswordField,
FormSubmitError,
FieldTooltip,
} from '../../../components/FormField';
import AnsibleSelect from '../../../components/AnsibleSelect';
import Popover from '../../../components/Popover';
import {
required,
noWhiteSpace,
@ -30,7 +30,7 @@ function AnswerTypeField({ i18n }) {
<FormGroup
label={i18n._(t`Answer Type`)}
labelIcon={
<FieldTooltip
<Popover
content={i18n._(
t`Choose an answer type or format you want as the prompt for the user.
Refer to the Ansible Tower Documentation for more additional

View File

@ -20,7 +20,6 @@ import useRequest from '../../../util/useRequest';
import FormActionGroup from '../../../components/FormActionGroup';
import FormField, {
CheckboxField,
FieldTooltip,
FormSubmitError,
} from '../../../components/FormField';
import FieldWithPrompt from '../../../components/FieldWithPrompt';
@ -39,6 +38,7 @@ import {
ProjectLookup,
MultiCredentialsLookup,
} from '../../../components/Lookup';
import Popover from '../../../components/Popover';
import { JobTemplatesAPI } from '../../../api';
import LabelSelect from './LabelSelect';
import PlaybookSelect from './PlaybookSelect';
@ -295,7 +295,7 @@ function JobTemplateForm({
isRequired
label={i18n._(t`Playbook`)}
labelIcon={
<FieldTooltip
<Popover
content={i18n._(
t`Select the playbook to be executed by this job.`
)}
@ -333,7 +333,7 @@ function JobTemplateForm({
<FormGroup
label={i18n._(t`Labels`)}
labelIcon={
<FieldTooltip
<Popover
content={i18n._(t`Optional labels that describe this job template,
such as 'dev' or 'test'. Labels can be used to group and filter
job templates and completed jobs.`)}
@ -505,7 +505,7 @@ function JobTemplateForm({
<span>
{i18n._(t`Provisioning Callbacks`)}
&nbsp;
<FieldTooltip
<Popover
content={i18n._(t`Enables creation of a provisioning
callback URL. Using the URL a host can contact BRAND_NAME
and request a configuration update using this job
@ -525,7 +525,7 @@ function JobTemplateForm({
<span>
{i18n._(t`Enable Webhook`)}
&nbsp;
<FieldTooltip
<Popover
content={i18n._(t`Enable webhook for this template.`)}
/>
</span>

View File

@ -16,7 +16,7 @@ import useRequest from '../../../util/useRequest';
import { FormColumnLayout } from '../../../components/FormLayout';
import { CredentialLookup } from '../../../components/Lookup';
import AnsibleSelect from '../../../components/AnsibleSelect';
import { FieldTooltip } from '../../../components/FormField';
import Popover from '../../../components/Popover';
import {
JobTemplatesAPI,
WorkflowJobTemplatesAPI,
@ -129,9 +129,7 @@ function WebhookSubForm({ i18n, templateType }) {
fieldId="webhook_service"
helperTextInvalid={webhookServiceMeta.error}
label={i18n._(t`Webhook Service`)}
labelIcon={
<FieldTooltip content={i18n._(t`Select a webhook service.`)} />
}
labelIcon={<Popover content={i18n._(t`Select a webhook service.`)} />}
>
<AnsibleSelect
{...webhookServiceField}
@ -168,7 +166,7 @@ function WebhookSubForm({ i18n, templateType }) {
fieldId="jt-webhookURL"
label={i18n._(t`Webhook URL`)}
labelIcon={
<FieldTooltip
<Popover
content={i18n._(
t`Webhook services can launch jobs with this workflow job template by making a POST request to this URL.`
)}
@ -186,7 +184,7 @@ function WebhookSubForm({ i18n, templateType }) {
<FormGroup
label={i18n._(t`Webhook Key`)}
labelIcon={
<FieldTooltip
<Popover
content={i18n._(
t`Webhook services can use this as a shared secret.`
)}

View File

@ -14,10 +14,7 @@ import {
import { required } from '../../../util/validators';
import FieldWithPrompt from '../../../components/FieldWithPrompt';
import FormField, {
FieldTooltip,
FormSubmitError,
} from '../../../components/FormField';
import FormField, { FormSubmitError } from '../../../components/FormField';
import {
FormColumnLayout,
FormFullWidthLayout,
@ -30,6 +27,7 @@ import { VariablesField } from '../../../components/CodeMirrorInput';
import FormActionGroup from '../../../components/FormActionGroup';
import ContentError from '../../../components/ContentError';
import CheckboxField from '../../../components/FormField/CheckboxField';
import Popover from '../../../components/Popover';
import LabelSelect from './LabelSelect';
import WebhookSubForm from './WebhookSubForm';
import { WorkFlowJobTemplate } from '../../../types';
@ -186,7 +184,7 @@ function WorkflowJobTemplateForm({
<FormGroup
label={i18n._(t`Labels`)}
labelIcon={
<FieldTooltip
<Popover
content={i18n._(t`Optional labels that describe this job template,
such as 'dev' or 'test'. Labels can be used to group and filter
job templates and completed jobs.`)}
@ -221,7 +219,7 @@ function WorkflowJobTemplateForm({
<span>
{i18n._(t`Enable Webhook`)}
&nbsp;
<FieldTooltip
<Popover
content={i18n._(
t`Enable Webhook for this workflow job template.`
)}

View File

@ -5,11 +5,9 @@ import { Formik, useField } from 'formik';
import { Form, FormGroup } from '@patternfly/react-core';
import AnsibleSelect from '../../../components/AnsibleSelect';
import FormActionGroup from '../../../components/FormActionGroup/FormActionGroup';
import FormField, {
FormSubmitError,
FieldTooltip,
} from '../../../components/FormField';
import FormField, { FormSubmitError } from '../../../components/FormField';
import ApplicationLookup from '../../../components/Lookup/ApplicationLookup';
import Popover from '../../../components/Popover';
import { required } from '../../../util/validators';
import { FormColumnLayout } from '../../../components/FormLayout';
@ -44,7 +42,7 @@ function UserTokenFormFields({ i18n }) {
label={
<span>
{i18n._(t`Application`)}
<FieldTooltip
<Popover
content={i18n._(
t`Select the application that this token will belong to.`
)}
@ -69,7 +67,7 @@ function UserTokenFormFields({ i18n }) {
validated={!scopeMeta.touched || !scopeMeta.error ? 'default' : 'error'}
label={i18n._(t`Scope`)}
labelIcon={
<FieldTooltip
<Popover
content={i18n._(t`Specify a scope for the token's access`)}
/>
}