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
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 { useField } from 'formik';
import { Form, FormGroup } from '@patternfly/react-core'; import { Form, FormGroup } from '@patternfly/react-core';
import { CredentialsAPI } from '../../api'; import { CredentialsAPI } from '../../api';
import { FieldTooltip } from '../FormField'; import Popover from '../Popover';
import { getQSConfig, parseQueryString, mergeParams } from '../../util/qs'; import { getQSConfig, parseQueryString, mergeParams } from '../../util/qs';
import useRequest from '../../util/useRequest'; import useRequest from '../../util/useRequest';
@@ -72,7 +72,7 @@ function AdHocCredentialStep({ i18n, credentialTypeId, onEnableLaunch }) {
} }
helperTextInvalid={credentialMeta.error} helperTextInvalid={credentialMeta.error}
labelIcon={ labelIcon={
<FieldTooltip <Popover
content={i18n._( 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.` 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 { BrandName } from '../../variables';
import AnsibleSelect from '../AnsibleSelect'; import AnsibleSelect from '../AnsibleSelect';
import FormField, { FieldTooltip } from '../FormField'; import FormField from '../FormField';
import { VariablesField } from '../CodeMirrorInput'; import { VariablesField } from '../CodeMirrorInput';
import { import {
FormColumnLayout, FormColumnLayout,
FormFullWidthLayout, FormFullWidthLayout,
FormCheckboxLayout, FormCheckboxLayout,
} from '../FormLayout'; } from '../FormLayout';
import Popover from '../Popover';
import { required } from '../../util/validators'; import { required } from '../../util/validators';
const TooltipWrapper = styled.div` const TooltipWrapper = styled.div`
@@ -68,7 +69,7 @@ function AdHocDetailsStep({ i18n, verbosityOptions, moduleOptions }) {
: 'error' : 'error'
} }
labelIcon={ labelIcon={
<FieldTooltip <Popover
content={i18n._( content={i18n._(
t`These are the modules that ${brandName} supports running commands against.` t`These are the modules that ${brandName} supports running commands against.`
)} )}
@@ -146,7 +147,7 @@ function AdHocDetailsStep({ i18n, verbosityOptions, moduleOptions }) {
} }
helperTextInvalid={verbosityMeta.error} helperTextInvalid={verbosityMeta.error}
labelIcon={ labelIcon={
<FieldTooltip <Popover
content={i18n._( content={i18n._(
t`These are the verbosity levels for standard out of the command run that are supported.` 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`)} label={i18n._(t`Show changes`)}
aria-label={i18n._(t`Show changes`)} aria-label={i18n._(t`Show changes`)}
labelIcon={ labelIcon={
<FieldTooltip <Popover
content={i18n._( content={i18n._(
t`If enabled, show the changes made by Ansible tasks, where supported. This is equivalent to Ansibles --diff mode.` 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> <span>
{i18n._(t`Enable privilege escalation`)} {i18n._(t`Enable privilege escalation`)}
&nbsp; &nbsp;
<FieldTooltip <Popover
content={ content={
<p> <p>
{i18n._(t`Enables creation of a provisioning {i18n._(t`Enables creation of a provisioning

View File

@@ -12,7 +12,7 @@ import {
import { useField } from 'formik'; import { useField } from 'formik';
import { FormGroup } from '@patternfly/react-core'; import { FormGroup } from '@patternfly/react-core';
import CodeMirrorInput from './CodeMirrorInput'; import CodeMirrorInput from './CodeMirrorInput';
import { FieldTooltip } from '../FormField'; import Popover from '../Popover';
function CodeMirrorField({ function CodeMirrorField({
id, id,
@@ -37,7 +37,7 @@ function CodeMirrorField({
isRequired={isRequired} isRequired={isRequired}
validated={isValid ? 'default' : 'error'} validated={isValid ? 'default' : 'error'}
label={label} label={label}
labelIcon={<FieldTooltip content={tooltip} />} labelIcon={<Popover content={tooltip} />}
> >
<CodeMirrorInput <CodeMirrorInput
id={id} 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 { Split, SplitItem, TextListItemVariants } from '@patternfly/react-core';
import { DetailName, DetailValue } from '../DetailList'; import { DetailName, DetailValue } from '../DetailList';
import MultiButtonToggle from '../MultiButtonToggle'; import MultiButtonToggle from '../MultiButtonToggle';
import DetailPopover from '../DetailPopover'; import Popover from '../Popover';
import { import {
yamlToJson, yamlToJson,
jsonToYaml, jsonToYaml,
@@ -69,7 +69,7 @@ function VariablesDetail({ dataCy, helpText, value, label, rows, fullHeight }) {
{label} {label}
</span> </span>
{helpText && ( {helpText && (
<DetailPopover header={label} content={helpText} id={dataCy} /> <Popover header={label} content={helpText} id={dataCy} />
)} )}
</div> </div>
</SplitItem> </SplitItem>
@@ -122,9 +122,13 @@ VariablesDetail.propTypes = {
value: oneOfType([shape({}), arrayOf(string), string]).isRequired, value: oneOfType([shape({}), arrayOf(string), string]).isRequired,
label: node.isRequired, label: node.isRequired,
rows: number, rows: number,
dataCy: string,
helpText: string,
}; };
VariablesDetail.defaultProps = { VariablesDetail.defaultProps = {
rows: null, rows: null,
dataCy: '',
helpText: '',
}; };
export default VariablesDetail; export default VariablesDetail;

View File

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

View File

@@ -83,7 +83,7 @@ describe('VariablesField', () => {
)} )}
</Formik> </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 () => { it('should submit value through Formik', async () => {

View File

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

View File

@@ -2,7 +2,7 @@ import React from 'react';
import { node, bool, string } from 'prop-types'; import { node, bool, string } from 'prop-types';
import { TextListItem, TextListItemVariants } from '@patternfly/react-core'; import { TextListItem, TextListItemVariants } from '@patternfly/react-core';
import styled from 'styled-components'; import styled from 'styled-components';
import DetailPopover from '../DetailPopover'; import Popover from '../Popover';
const DetailName = styled(({ fullWidth, ...props }) => ( const DetailName = styled(({ fullWidth, ...props }) => (
<TextListItem {...props} /> <TextListItem {...props} />
@@ -61,9 +61,7 @@ const Detail = ({
id={dataCy} id={dataCy}
> >
{label} {label}
{helpText && ( {helpText && <Popover header={label} content={helpText} id={dataCy} />}
<DetailPopover header={label} content={helpText} id={dataCy} />
)}
</DetailName> </DetailName>
<DetailValue <DetailValue
className={className} 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 { withI18n } from '@lingui/react';
import { t } from '@lingui/macro'; import { t } from '@lingui/macro';
import styled from 'styled-components'; import styled from 'styled-components';
import { CheckboxField, FieldTooltip } from '../FormField'; import { CheckboxField } from '../FormField';
import Popover from '../Popover';
const FieldHeader = styled.div` const FieldHeader = styled.div`
display: flex; display: flex;
@@ -38,7 +39,7 @@ function FieldWithPrompt({
</span> </span>
)} )}
</label> </label>
{tooltip && <FieldTooltip content={tooltip} />} {tooltip && <Popover content={tooltip} id={fieldId} />}
</div> </div>
<StyledCheckboxField <StyledCheckboxField
isDisabled={isDisabled} isDisabled={isDisabled}

View File

@@ -10,7 +10,7 @@ describe('FieldWithPrompt', () => {
wrapper.unmount(); 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( wrapper = mountWithContexts(
<Formik <Formik
initialValues={{ initialValues={{
@@ -33,10 +33,10 @@ describe('FieldWithPrompt', () => {
</Formik> </Formik>
); );
expect(wrapper.find('.pf-c-form__label-required')).toHaveLength(0); 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( wrapper = mountWithContexts(
<Formik <Formik
initialValues={{ initialValues={{
@@ -61,6 +61,8 @@ describe('FieldWithPrompt', () => {
</Formik> </Formik>
); );
expect(wrapper.find('.pf-c-form__label-required')).toHaveLength(1); 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 PropTypes from 'prop-types';
import { useField } from 'formik'; import { useField } from 'formik';
import { FormGroup, TextArea } from '@patternfly/react-core'; import { FormGroup, TextArea } from '@patternfly/react-core';
import FieldTooltip from './FieldTooltip'; import Popover from '../Popover';
function ArrayTextField(props) { function ArrayTextField(props) {
const { const {
@@ -30,7 +30,7 @@ function ArrayTextField(props) {
isRequired={isRequired} isRequired={isRequired}
validated={isValid ? 'default' : 'error'} validated={isValid ? 'default' : 'error'}
label={label} label={label}
labelIcon={<FieldTooltip content={tooltip} maxWidth={tooltipMaxWidth} />} labelIcon={<Popover content={tooltip} maxWidth={tooltipMaxWidth} />}
> >
<TextArea <TextArea
id={id} id={id}

View File

@@ -1,13 +1,8 @@
import React from 'react'; import React from 'react';
import { string, func, node } from 'prop-types'; import { string, func, node } from 'prop-types';
import { useField } from 'formik'; import { useField } from 'formik';
import { Checkbox, Tooltip } from '@patternfly/react-core'; import { Checkbox } from '@patternfly/react-core';
import { QuestionCircleIcon as PFQuestionCircleIcon } from '@patternfly/react-icons'; import Popover from '../Popover';
import styled from 'styled-components';
const QuestionCircleIcon = styled(PFQuestionCircleIcon)`
margin-left: 10px;
`;
function CheckboxField({ function CheckboxField({
id, id,
@@ -27,11 +22,7 @@ function CheckboxField({
<span> <span>
{label} {label}
&nbsp; &nbsp;
{tooltip && ( {tooltip && <Popover content={tooltip} />}
<Tooltip position="right" content={tooltip}>
<QuestionCircleIcon />
</Tooltip>
)}
</span> </span>
} }
id={id} 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 PropTypes from 'prop-types';
import { useField } from 'formik'; import { useField } from 'formik';
import { FormGroup, TextInput, TextArea } from '@patternfly/react-core'; import { FormGroup, TextInput, TextArea } from '@patternfly/react-core';
import FieldTooltip from './FieldTooltip'; import Popover from '../Popover';
function FormField(props) { function FormField(props) {
const { const {
@@ -31,9 +31,7 @@ function FormField(props) {
isRequired={isRequired} isRequired={isRequired}
validated={isValid ? 'default' : 'error'} validated={isValid ? 'default' : 'error'}
label={label} label={label}
labelIcon={ labelIcon={<Popover content={tooltip} maxWidth={tooltipMaxWidth} />}
<FieldTooltip content={tooltip} maxWidth={tooltipMaxWidth} />
}
> >
<TextArea <TextArea
id={id} id={id}
@@ -55,9 +53,7 @@ function FormField(props) {
isRequired={isRequired} isRequired={isRequired}
validated={isValid ? 'default' : 'error'} validated={isValid ? 'default' : 'error'}
label={label} label={label}
labelIcon={ labelIcon={<Popover content={tooltip} maxWidth={tooltipMaxWidth} />}
<FieldTooltip content={tooltip} maxWidth={tooltipMaxWidth} />
}
> >
<TextInput <TextInput
id={id} id={id}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -6,7 +6,7 @@ import { t } from '@lingui/macro';
import { FormGroup } from '@patternfly/react-core'; import { FormGroup } from '@patternfly/react-core';
import { ProjectsAPI } from '../../api'; import { ProjectsAPI } from '../../api';
import { Project } from '../../types'; import { Project } from '../../types';
import { FieldTooltip } from '../FormField'; import Popover from '../Popover';
import OptionsList from '../OptionsList'; import OptionsList from '../OptionsList';
import useAutoPopulateLookup from '../../util/useAutoPopulateLookup'; import useAutoPopulateLookup from '../../util/useAutoPopulateLookup';
import useRequest from '../../util/useRequest'; import useRequest from '../../util/useRequest';
@@ -80,7 +80,7 @@ function ProjectLookup({
isRequired={required} isRequired={required}
validated={isValid ? 'default' : 'error'} validated={isValid ? 'default' : 'error'}
label={i18n._(t`Project`)} label={i18n._(t`Project`)}
labelIcon={tooltip && <FieldTooltip content={tooltip} />} labelIcon={tooltip && <Popover content={tooltip} />}
> >
<Lookup <Lookup
id="project" 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 PropTypes from 'prop-types';
import { required } from '../../../util/validators'; import { required } from '../../../util/validators';
import FormField, { import FormField, { FormSubmitError } from '../../../components/FormField';
FormSubmitError,
FieldTooltip,
} from '../../../components/FormField';
import { FormColumnLayout } from '../../../components/FormLayout'; import { FormColumnLayout } from '../../../components/FormLayout';
import FormActionGroup from '../../../components/FormActionGroup/FormActionGroup'; import FormActionGroup from '../../../components/FormActionGroup/FormActionGroup';
import OrganizationLookup from '../../../components/Lookup/OrganizationLookup'; import OrganizationLookup from '../../../components/Lookup/OrganizationLookup';
import AnsibleSelect from '../../../components/AnsibleSelect'; import AnsibleSelect from '../../../components/AnsibleSelect';
import Popover from '../../../components/Popover';
function ApplicationFormFields({ function ApplicationFormFields({
i18n, i18n,
@@ -85,7 +83,7 @@ function ApplicationFormFields({
isRequired isRequired
label={i18n._(t`Authorization grant type`)} label={i18n._(t`Authorization grant type`)}
labelIcon={ labelIcon={
<FieldTooltip <Popover
content={i18n._( content={i18n._(
t`The Grant type the user must use for acquire tokens for this application` t`The Grant type the user must use for acquire tokens for this application`
)} )}
@@ -129,7 +127,7 @@ function ApplicationFormFields({
isRequired isRequired
label={i18n._(t`Client type`)} label={i18n._(t`Client type`)}
labelIcon={ labelIcon={
<FieldTooltip <Popover
content={i18n._( content={i18n._(
t`Set to Public or Confidential depending on how secure the client device is.` t`Set to Public or Confidential depending on how secure the client device is.`
)} )}

View File

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

View File

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

View File

@@ -11,8 +11,8 @@ import {
Tooltip, Tooltip,
} from '@patternfly/react-core'; } from '@patternfly/react-core';
import { KeyIcon } from '@patternfly/react-icons'; import { KeyIcon } from '@patternfly/react-icons';
import { FieldTooltip } from '../../../../components/FormField';
import FieldWithPrompt from '../../../../components/FieldWithPrompt'; import FieldWithPrompt from '../../../../components/FieldWithPrompt';
import Popover from '../../../../components/Popover';
import { CredentialPluginPrompt } from './CredentialPluginPrompt'; import { CredentialPluginPrompt } from './CredentialPluginPrompt';
import CredentialPluginSelected from './CredentialPluginSelected'; import CredentialPluginSelected from './CredentialPluginSelected';
@@ -130,7 +130,7 @@ function CredentialPluginField(props) {
label={fieldOptions.label} label={fieldOptions.label}
labelIcon={ labelIcon={
fieldOptions.help_text && ( 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 React, { useCallback, useEffect } from 'react';
import { withI18n } from '@lingui/react'; import { withI18n } from '@lingui/react';
import { useField, useFormikContext } from 'formik'; import { useField, useFormikContext } from 'formik';
import styled from 'styled-components'; import { Form, FormGroup } from '@patternfly/react-core';
import { Form, FormGroup, Tooltip } from '@patternfly/react-core';
import { QuestionCircleIcon as PFQuestionCircleIcon } from '@patternfly/react-icons';
import { CredentialTypesAPI } from '../../../../../api'; import { CredentialTypesAPI } from '../../../../../api';
import AnsibleSelect from '../../../../../components/AnsibleSelect'; import AnsibleSelect from '../../../../../components/AnsibleSelect';
import ContentError from '../../../../../components/ContentError'; import ContentError from '../../../../../components/ContentError';
import ContentLoading from '../../../../../components/ContentLoading'; import ContentLoading from '../../../../../components/ContentLoading';
import FormField from '../../../../../components/FormField'; import FormField from '../../../../../components/FormField';
import { FormFullWidthLayout } from '../../../../../components/FormLayout'; import { FormFullWidthLayout } from '../../../../../components/FormLayout';
import Popover from '../../../../../components/Popover';
import useRequest from '../../../../../util/useRequest'; import useRequest from '../../../../../util/useRequest';
import { required } from '../../../../../util/validators'; import { required } from '../../../../../util/validators';
const QuestionCircleIcon = styled(PFQuestionCircleIcon)`
margin-left: 10px;
`;
function MetadataStep({ i18n }) { function MetadataStep({ i18n }) {
const form = useFormikContext(); const form = useFormikContext();
const [selectedCredential] = useField('credential'); const [selectedCredential] = useField('credential');
@@ -82,12 +77,10 @@ function MetadataStep({ i18n }) {
fieldId={`credential-${field.id}`} fieldId={`credential-${field.id}`}
label={field.label} label={field.label}
isRequired={field.required} 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 <AnsibleSelect
name={`inputs.${field.id}`} name={`inputs.${field.id}`}
value={form.values.inputs[field.id]} value={form.values.inputs[field.id]}

View File

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

View File

@@ -11,7 +11,6 @@ import ContentError from '../../../components/ContentError';
import ContentLoading from '../../../components/ContentLoading'; import ContentLoading from '../../../components/ContentLoading';
import CredentialChip from '../../../components/CredentialChip'; import CredentialChip from '../../../components/CredentialChip';
import DeleteButton from '../../../components/DeleteButton'; import DeleteButton from '../../../components/DeleteButton';
import { FieldTooltip } from '../../../components/FormField';
import InventorySourceSyncButton from '../shared/InventorySourceSyncButton'; import InventorySourceSyncButton from '../shared/InventorySourceSyncButton';
import { import {
DetailList, DetailList,
@@ -19,6 +18,7 @@ import {
UserDateDetail, UserDateDetail,
} from '../../../components/DetailList'; } from '../../../components/DetailList';
import ErrorDetail from '../../../components/ErrorDetail'; import ErrorDetail from '../../../components/ErrorDetail';
import Popover from '../../../components/Popover';
import useRequest from '../../../util/useRequest'; import useRequest from '../../../util/useRequest';
import { InventorySourcesAPI } from '../../../api'; import { InventorySourcesAPI } from '../../../api';
@@ -112,7 +112,7 @@ function InventorySourceDetail({ inventorySource, i18n }) {
{overwrite && ( {overwrite && (
<ListItem> <ListItem>
{i18n._(t`Overwrite`)} {i18n._(t`Overwrite`)}
<FieldTooltip <Popover
content={ content={
<> <>
{i18n._(t`If checked, any hosts and groups that were {i18n._(t`If checked, any hosts and groups that were
@@ -135,7 +135,7 @@ function InventorySourceDetail({ inventorySource, i18n }) {
{overwrite_vars && ( {overwrite_vars && (
<ListItem> <ListItem>
{i18n._(t`Overwrite variables`)} {i18n._(t`Overwrite variables`)}
<FieldTooltip <Popover
content={ content={
<> <>
{i18n._(t`If checked, all variables for child groups {i18n._(t`If checked, all variables for child groups
@@ -154,7 +154,7 @@ function InventorySourceDetail({ inventorySource, i18n }) {
{update_on_launch && ( {update_on_launch && (
<ListItem> <ListItem>
{i18n._(t`Update on launch`)} {i18n._(t`Update on launch`)}
<FieldTooltip <Popover
content={i18n._(t`Each time a job runs using this inventory, content={i18n._(t`Each time a job runs using this inventory,
refresh the inventory from the selected source before refresh the inventory from the selected source before
executing job tasks.`)} executing job tasks.`)}
@@ -164,7 +164,7 @@ function InventorySourceDetail({ inventorySource, i18n }) {
{update_on_project_update && ( {update_on_project_update && (
<ListItem> <ListItem>
{i18n._(t`Update on project update`)} {i18n._(t`Update on project update`)}
<FieldTooltip <Popover
content={i18n._(t`After every project update where the SCM revision content={i18n._(t`After every project update where the SCM revision
changes, refresh the inventory from the selected source changes, refresh the inventory from the selected source
before executing job tasks. This is intended for static content, 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 ContentError from '../../../components/ContentError';
import ContentLoading from '../../../components/ContentLoading'; import ContentLoading from '../../../components/ContentLoading';
import FormActionGroup from '../../../components/FormActionGroup/FormActionGroup'; import FormActionGroup from '../../../components/FormActionGroup/FormActionGroup';
import FormField, { import FormField, { FormSubmitError } from '../../../components/FormField';
FieldTooltip,
FormSubmitError,
} from '../../../components/FormField';
import { import {
FormColumnLayout, FormColumnLayout,
SubFormLayout, SubFormLayout,
} from '../../../components/FormLayout'; } from '../../../components/FormLayout';
import Popover from '../../../components/Popover';
import { import {
AzureSubForm, AzureSubForm,
@@ -145,7 +143,7 @@ const InventorySourceFormFields = ({ source, sourceOptions, i18n }) => {
fieldId="custom-virtualenv" fieldId="custom-virtualenv"
label={i18n._(t`Ansible Environment`)} label={i18n._(t`Ansible Environment`)}
labelIcon={ labelIcon={
<FieldTooltip <Popover
content={i18n._(t`Select the custom content={i18n._(t`Select the custom
Python virtual environment for this Python virtual environment for this
inventory source sync to run on.`)} inventory source sync to run on.`)}

View File

@@ -8,9 +8,9 @@ import useRequest from '../../../../util/useRequest';
import { required } from '../../../../util/validators'; import { required } from '../../../../util/validators';
import AnsibleSelect from '../../../../components/AnsibleSelect'; import AnsibleSelect from '../../../../components/AnsibleSelect';
import { FieldTooltip } from '../../../../components/FormField';
import CredentialLookup from '../../../../components/Lookup/CredentialLookup'; import CredentialLookup from '../../../../components/Lookup/CredentialLookup';
import ProjectLookup from '../../../../components/Lookup/ProjectLookup'; import ProjectLookup from '../../../../components/Lookup/ProjectLookup';
import Popover from '../../../../components/Popover';
import { import {
OptionsField, OptionsField,
SourceVarsField, SourceVarsField,
@@ -99,7 +99,7 @@ const SCMSubForm = ({ autoPopulateProject, i18n }) => {
isRequired isRequired
label={i18n._(t`Inventory file`)} label={i18n._(t`Inventory file`)}
labelIcon={ labelIcon={
<FieldTooltip <Popover
content={i18n._(t`Select the inventory file content={i18n._(t`Select the inventory file
to be synced by this source. You can select from to be synced by this source. You can select from
the dropdown or enter a file within the input.`)} 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 { minMaxValue, regExp } from '../../../../util/validators';
import AnsibleSelect from '../../../../components/AnsibleSelect'; import AnsibleSelect from '../../../../components/AnsibleSelect';
import { VariablesField } from '../../../../components/CodeMirrorInput'; import { VariablesField } from '../../../../components/CodeMirrorInput';
import FormField, { import FormField, { CheckboxField } from '../../../../components/FormField';
CheckboxField,
FieldTooltip,
} from '../../../../components/FormField';
import { import {
FormFullWidthLayout, FormFullWidthLayout,
FormCheckboxLayout, FormCheckboxLayout,
} from '../../../../components/FormLayout'; } from '../../../../components/FormLayout';
import Popover from '../../../../components/Popover';
export const SourceVarsField = withI18n()(({ i18n }) => ( export const SourceVarsField = withI18n()(({ i18n }) => (
<FormFullWidthLayout> <FormFullWidthLayout>
@@ -39,7 +37,7 @@ export const VerbosityField = withI18n()(({ i18n }) => {
validated={isValid ? 'default' : 'error'} validated={isValid ? 'default' : 'error'}
label={i18n._(t`Verbosity`)} label={i18n._(t`Verbosity`)}
labelIcon={ labelIcon={
<FieldTooltip <Popover
content={i18n._(t`Control the level of output Ansible content={i18n._(t`Control the level of output Ansible
will produce for inventory source update jobs.`)} will produce for inventory source update jobs.`)}
/> />

View File

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

View File

@@ -6,7 +6,8 @@ import { useField } from 'formik';
import { FormGroup, Alert } from '@patternfly/react-core'; import { FormGroup, Alert } from '@patternfly/react-core';
import { required } from '../../../../util/validators'; import { required } from '../../../../util/validators';
import AnsibleSelect from '../../../../components/AnsibleSelect'; 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'; import { BrandName } from '../../../../variables';
// Setting BrandName to a variable here is necessary to get the jest tests // 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'} validated={!pathMeta.touched || !pathMeta.error ? 'default' : 'error'}
label={i18n._(t`Playbook Directory`)} label={i18n._(t`Playbook Directory`)}
labelIcon={ labelIcon={
<FieldTooltip <Popover
content={i18n._(t`Select from the list of directories found in content={i18n._(t`Select from the list of directories found in
the Project Base Path. Together the base path and the playbook the Project Base Path. Together the base path and the playbook
directory provide the full path used to locate playbooks.`)} 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 { t } from '@lingui/macro';
import { Detail } from '../../../components/DetailList'; import { Detail } from '../../../components/DetailList';
import { VariablesDetail } from '../../../components/CodeMirrorInput'; import { VariablesDetail } from '../../../components/CodeMirrorInput';
// import DetailPopover from '../../../components/DetailList/DetailPopover';
export default withI18n()( export default withI18n()(
({ i18n, helpText, id, label, type, unit = '', value }) => { ({ i18n, helpText, id, label, type, unit = '', value }) => {

View File

@@ -10,9 +10,9 @@ import FormField, {
CheckboxField, CheckboxField,
PasswordField, PasswordField,
FormSubmitError, FormSubmitError,
FieldTooltip,
} from '../../../components/FormField'; } from '../../../components/FormField';
import AnsibleSelect from '../../../components/AnsibleSelect'; import AnsibleSelect from '../../../components/AnsibleSelect';
import Popover from '../../../components/Popover';
import { import {
required, required,
noWhiteSpace, noWhiteSpace,
@@ -30,7 +30,7 @@ function AnswerTypeField({ i18n }) {
<FormGroup <FormGroup
label={i18n._(t`Answer Type`)} label={i18n._(t`Answer Type`)}
labelIcon={ labelIcon={
<FieldTooltip <Popover
content={i18n._( content={i18n._(
t`Choose an answer type or format you want as the prompt for the user. t`Choose an answer type or format you want as the prompt for the user.
Refer to the Ansible Tower Documentation for more additional 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 FormActionGroup from '../../../components/FormActionGroup';
import FormField, { import FormField, {
CheckboxField, CheckboxField,
FieldTooltip,
FormSubmitError, FormSubmitError,
} from '../../../components/FormField'; } from '../../../components/FormField';
import FieldWithPrompt from '../../../components/FieldWithPrompt'; import FieldWithPrompt from '../../../components/FieldWithPrompt';
@@ -39,6 +38,7 @@ import {
ProjectLookup, ProjectLookup,
MultiCredentialsLookup, MultiCredentialsLookup,
} from '../../../components/Lookup'; } from '../../../components/Lookup';
import Popover from '../../../components/Popover';
import { JobTemplatesAPI } from '../../../api'; import { JobTemplatesAPI } from '../../../api';
import LabelSelect from './LabelSelect'; import LabelSelect from './LabelSelect';
import PlaybookSelect from './PlaybookSelect'; import PlaybookSelect from './PlaybookSelect';
@@ -295,7 +295,7 @@ function JobTemplateForm({
isRequired isRequired
label={i18n._(t`Playbook`)} label={i18n._(t`Playbook`)}
labelIcon={ labelIcon={
<FieldTooltip <Popover
content={i18n._( content={i18n._(
t`Select the playbook to be executed by this job.` t`Select the playbook to be executed by this job.`
)} )}
@@ -333,7 +333,7 @@ function JobTemplateForm({
<FormGroup <FormGroup
label={i18n._(t`Labels`)} label={i18n._(t`Labels`)}
labelIcon={ labelIcon={
<FieldTooltip <Popover
content={i18n._(t`Optional labels that describe this job template, content={i18n._(t`Optional labels that describe this job template,
such as 'dev' or 'test'. Labels can be used to group and filter such as 'dev' or 'test'. Labels can be used to group and filter
job templates and completed jobs.`)} job templates and completed jobs.`)}
@@ -505,7 +505,7 @@ function JobTemplateForm({
<span> <span>
{i18n._(t`Provisioning Callbacks`)} {i18n._(t`Provisioning Callbacks`)}
&nbsp; &nbsp;
<FieldTooltip <Popover
content={i18n._(t`Enables creation of a provisioning content={i18n._(t`Enables creation of a provisioning
callback URL. Using the URL a host can contact BRAND_NAME callback URL. Using the URL a host can contact BRAND_NAME
and request a configuration update using this job and request a configuration update using this job
@@ -525,7 +525,7 @@ function JobTemplateForm({
<span> <span>
{i18n._(t`Enable Webhook`)} {i18n._(t`Enable Webhook`)}
&nbsp; &nbsp;
<FieldTooltip <Popover
content={i18n._(t`Enable webhook for this template.`)} content={i18n._(t`Enable webhook for this template.`)}
/> />
</span> </span>

View File

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

View File

@@ -14,10 +14,7 @@ import {
import { required } from '../../../util/validators'; import { required } from '../../../util/validators';
import FieldWithPrompt from '../../../components/FieldWithPrompt'; import FieldWithPrompt from '../../../components/FieldWithPrompt';
import FormField, { import FormField, { FormSubmitError } from '../../../components/FormField';
FieldTooltip,
FormSubmitError,
} from '../../../components/FormField';
import { import {
FormColumnLayout, FormColumnLayout,
FormFullWidthLayout, FormFullWidthLayout,
@@ -30,6 +27,7 @@ import { VariablesField } from '../../../components/CodeMirrorInput';
import FormActionGroup from '../../../components/FormActionGroup'; import FormActionGroup from '../../../components/FormActionGroup';
import ContentError from '../../../components/ContentError'; import ContentError from '../../../components/ContentError';
import CheckboxField from '../../../components/FormField/CheckboxField'; import CheckboxField from '../../../components/FormField/CheckboxField';
import Popover from '../../../components/Popover';
import LabelSelect from './LabelSelect'; import LabelSelect from './LabelSelect';
import WebhookSubForm from './WebhookSubForm'; import WebhookSubForm from './WebhookSubForm';
import { WorkFlowJobTemplate } from '../../../types'; import { WorkFlowJobTemplate } from '../../../types';
@@ -186,7 +184,7 @@ function WorkflowJobTemplateForm({
<FormGroup <FormGroup
label={i18n._(t`Labels`)} label={i18n._(t`Labels`)}
labelIcon={ labelIcon={
<FieldTooltip <Popover
content={i18n._(t`Optional labels that describe this job template, content={i18n._(t`Optional labels that describe this job template,
such as 'dev' or 'test'. Labels can be used to group and filter such as 'dev' or 'test'. Labels can be used to group and filter
job templates and completed jobs.`)} job templates and completed jobs.`)}
@@ -221,7 +219,7 @@ function WorkflowJobTemplateForm({
<span> <span>
{i18n._(t`Enable Webhook`)} {i18n._(t`Enable Webhook`)}
&nbsp; &nbsp;
<FieldTooltip <Popover
content={i18n._( content={i18n._(
t`Enable Webhook for this workflow job template.` 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 { Form, FormGroup } from '@patternfly/react-core';
import AnsibleSelect from '../../../components/AnsibleSelect'; import AnsibleSelect from '../../../components/AnsibleSelect';
import FormActionGroup from '../../../components/FormActionGroup/FormActionGroup'; import FormActionGroup from '../../../components/FormActionGroup/FormActionGroup';
import FormField, { import FormField, { FormSubmitError } from '../../../components/FormField';
FormSubmitError,
FieldTooltip,
} from '../../../components/FormField';
import ApplicationLookup from '../../../components/Lookup/ApplicationLookup'; import ApplicationLookup from '../../../components/Lookup/ApplicationLookup';
import Popover from '../../../components/Popover';
import { required } from '../../../util/validators'; import { required } from '../../../util/validators';
import { FormColumnLayout } from '../../../components/FormLayout'; import { FormColumnLayout } from '../../../components/FormLayout';
@@ -44,7 +42,7 @@ function UserTokenFormFields({ i18n }) {
label={ label={
<span> <span>
{i18n._(t`Application`)} {i18n._(t`Application`)}
<FieldTooltip <Popover
content={i18n._( content={i18n._(
t`Select the application that this token will belong to.` t`Select the application that this token will belong to.`
)} )}
@@ -69,7 +67,7 @@ function UserTokenFormFields({ i18n }) {
validated={!scopeMeta.touched || !scopeMeta.error ? 'default' : 'error'} validated={!scopeMeta.touched || !scopeMeta.error ? 'default' : 'error'}
label={i18n._(t`Scope`)} label={i18n._(t`Scope`)}
labelIcon={ labelIcon={
<FieldTooltip <Popover
content={i18n._(t`Specify a scope for the token's access`)} content={i18n._(t`Specify a scope for the token's access`)}
/> />
} }