mirror of
https://github.com/ansible/awx.git
synced 2026-02-25 23:16:01 -03:30
updates tooltip component, fixes formik configuration on ad hoc qizard
This commit is contained in:
@@ -65,7 +65,7 @@ function AdHocCommands({ children, apiModule, adHocItems, itemId, i18n }) {
|
||||
useCallback(
|
||||
async values => {
|
||||
const { data } = await apiModule.launchAdHocCommands(itemId, values);
|
||||
history.push(`/jobs/${data.module_name}/${data.id}/output`);
|
||||
history.push(`/jobs/command/${data.id}/output`);
|
||||
},
|
||||
|
||||
[apiModule, itemId, history]
|
||||
|
||||
@@ -157,12 +157,12 @@ describe('<AdHocCommands />', () => {
|
||||
).toBe(true);
|
||||
|
||||
await act(async () => {
|
||||
wrapper.find('AnsibleSelect[name="module_args"]').prop('onChange')(
|
||||
wrapper.find('AnsibleSelect[name="module_name"]').prop('onChange')(
|
||||
{},
|
||||
'command'
|
||||
);
|
||||
wrapper.find('input#arguments').simulate('change', {
|
||||
target: { value: 'foo', name: 'arguments' },
|
||||
wrapper.find('input#module_args').simulate('change', {
|
||||
target: { value: 'foo', name: 'module_args' },
|
||||
});
|
||||
wrapper.find('AnsibleSelect[name="verbosity"]').prop('onChange')({}, 1);
|
||||
});
|
||||
@@ -194,14 +194,15 @@ describe('<AdHocCommands />', () => {
|
||||
);
|
||||
|
||||
expect(InventoriesAPI.launchAdHocCommands).toBeCalledWith(1, {
|
||||
arguments: 'foo',
|
||||
changes: false,
|
||||
module_args: 'foo',
|
||||
diff_mode: false,
|
||||
credential: 4,
|
||||
escalation: false,
|
||||
job_type: 'run',
|
||||
become_enabled: '',
|
||||
extra_vars: '---',
|
||||
forks: 0,
|
||||
limit: 'Inventory 1 Org 0, Inventory 2 Org 0',
|
||||
module_args: 'command',
|
||||
module_name: 'command',
|
||||
verbosity: 1,
|
||||
});
|
||||
|
||||
@@ -271,12 +272,12 @@ describe('<AdHocCommands />', () => {
|
||||
).toBe(true);
|
||||
|
||||
await act(async () => {
|
||||
wrapper.find('AnsibleSelect[name="module_args"]').prop('onChange')(
|
||||
wrapper.find('AnsibleSelect[name="module_name"]').prop('onChange')(
|
||||
{},
|
||||
'command'
|
||||
);
|
||||
wrapper.find('input#arguments').simulate('change', {
|
||||
target: { value: 'foo', name: 'arguments' },
|
||||
wrapper.find('input#module_args').simulate('change', {
|
||||
target: { value: 'foo', name: 'module_args' },
|
||||
});
|
||||
wrapper.find('AnsibleSelect[name="verbosity"]').prop('onChange')({}, 1);
|
||||
});
|
||||
|
||||
@@ -22,12 +22,12 @@ function AdHocCommandsWizard({
|
||||
const { values } = useFormikContext();
|
||||
|
||||
const enabledNextOnDetailsStep = () => {
|
||||
if (!values.module_args) {
|
||||
if (!values.module_name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (values.module_args === 'shell' || values.module_args === 'command') {
|
||||
if (values.arguments) {
|
||||
if (values.module_name === 'shell' || values.module_name === 'command') {
|
||||
if (values.module_args) {
|
||||
return true;
|
||||
// eslint-disable-next-line no-else-return
|
||||
} else {
|
||||
@@ -90,15 +90,16 @@ const FormikApp = withFormik({
|
||||
mapPropsToValues({ adHocItems, verbosityOptions }) {
|
||||
const adHocItemStrings = adHocItems.map(item => item.name).join(', ');
|
||||
return {
|
||||
limit: adHocItemStrings || [],
|
||||
limit: adHocItemStrings || 'all',
|
||||
credential: [],
|
||||
module_args: '',
|
||||
arguments: '',
|
||||
verbosity: verbosityOptions[0].value,
|
||||
forks: 0,
|
||||
changes: false,
|
||||
escalation: false,
|
||||
diff_mode: false,
|
||||
become_enabled: '',
|
||||
module_name: '',
|
||||
extra_vars: '---',
|
||||
job_type: 'run',
|
||||
};
|
||||
},
|
||||
})(AdHocCommandsWizard);
|
||||
|
||||
@@ -73,12 +73,12 @@ describe('<AdHocCommandsWizard/>', () => {
|
||||
await waitForElement(wrapper, 'WizardNavItem', el => el.length > 0);
|
||||
|
||||
await act(async () => {
|
||||
wrapper.find('AnsibleSelect[name="module_args"]').prop('onChange')(
|
||||
wrapper.find('AnsibleSelect[name="module_name"]').prop('onChange')(
|
||||
{},
|
||||
'command'
|
||||
);
|
||||
wrapper.find('input#arguments').simulate('change', {
|
||||
target: { value: 'foo', name: 'arguments' },
|
||||
wrapper.find('input#module_args').simulate('change', {
|
||||
target: { value: 'foo', name: 'module_args' },
|
||||
});
|
||||
wrapper.find('AnsibleSelect[name="verbosity"]').prop('onChange')({}, 1);
|
||||
});
|
||||
@@ -105,12 +105,12 @@ describe('<AdHocCommandsWizard/>', () => {
|
||||
await waitForElement(wrapper, 'WizardNavItem', el => el.length > 0);
|
||||
|
||||
await act(async () => {
|
||||
wrapper.find('AnsibleSelect[name="module_args"]').prop('onChange')(
|
||||
wrapper.find('AnsibleSelect[name="module_name"]').prop('onChange')(
|
||||
{},
|
||||
'command'
|
||||
);
|
||||
wrapper.find('input#arguments').simulate('change', {
|
||||
target: { value: 'foo', name: 'arguments' },
|
||||
wrapper.find('input#module_args').simulate('change', {
|
||||
target: { value: 'foo', name: 'module_args' },
|
||||
});
|
||||
wrapper.find('AnsibleSelect[name="verbosity"]').prop('onChange')({}, 1);
|
||||
});
|
||||
@@ -165,12 +165,12 @@ describe('<AdHocCommandsWizard/>', () => {
|
||||
await waitForElement(wrapper, 'WizardNavItem', el => el.length > 0);
|
||||
|
||||
await act(async () => {
|
||||
wrapper.find('AnsibleSelect[name="module_args"]').prop('onChange')(
|
||||
wrapper.find('AnsibleSelect[name="module_name"]').prop('onChange')(
|
||||
{},
|
||||
'command'
|
||||
);
|
||||
wrapper.find('input#arguments').simulate('change', {
|
||||
target: { value: 'foo', name: 'arguments' },
|
||||
wrapper.find('input#module_args').simulate('change', {
|
||||
target: { value: 'foo', name: 'module_args' },
|
||||
});
|
||||
wrapper.find('AnsibleSelect[name="verbosity"]').prop('onChange')({}, 1);
|
||||
});
|
||||
|
||||
@@ -28,29 +28,36 @@ const TooltipWrapper = styled.div`
|
||||
const brandName = BrandName;
|
||||
|
||||
function CredentialStep({ i18n, verbosityOptions, moduleOptions }) {
|
||||
const [moduleField, moduleMeta, moduleHelpers] = useField({
|
||||
const [module_nameField, module_nameMeta, module_nameHelpers] = useField({
|
||||
name: 'module_name',
|
||||
validate: required(null, i18n),
|
||||
});
|
||||
const [module_argsField] = useField({
|
||||
name: 'module_args',
|
||||
validate: required(null, i18n),
|
||||
});
|
||||
const [variablesField] = useField('extra_vars');
|
||||
const [changesField, , changesHelpers] = useField('changes');
|
||||
const [escalationField, , escalationHelpers] = useField('escalation');
|
||||
const [diff_modeField, , diff_modeHelpers] = useField('diff_mode');
|
||||
const [become_enabledField, , become_enabledHelpers] = useField(
|
||||
'become_enabled'
|
||||
);
|
||||
const [verbosityField, verbosityMeta, verbosityHelpers] = useField({
|
||||
name: 'verbosity',
|
||||
validate: required(null, i18n),
|
||||
});
|
||||
|
||||
return (
|
||||
<Form>
|
||||
<FormColumnLayout>
|
||||
<FormFullWidthLayout>
|
||||
<FormGroup
|
||||
fieldId="module"
|
||||
fieldId="module_name"
|
||||
label={i18n._(t`Module`)}
|
||||
isRequired
|
||||
helperTextInvalid={moduleMeta.error}
|
||||
helperTextInvalid={module_nameMeta.error}
|
||||
validated={
|
||||
!moduleMeta.touched || !moduleMeta.error ? 'default' : 'error'
|
||||
!module_nameMeta.touched || !module_nameMeta.error
|
||||
? 'default'
|
||||
: 'error'
|
||||
}
|
||||
labelIcon={
|
||||
<FieldTooltip
|
||||
@@ -61,26 +68,43 @@ function CredentialStep({ i18n, verbosityOptions, moduleOptions }) {
|
||||
}
|
||||
>
|
||||
<AnsibleSelect
|
||||
{...moduleField}
|
||||
isValid={!moduleMeta.touched || !moduleMeta.error}
|
||||
id="module"
|
||||
{...module_nameField}
|
||||
isValid={!module_nameMeta.touched || !module_nameMeta.error}
|
||||
id="module_name"
|
||||
data={moduleOptions || []}
|
||||
onChange={(event, value) => {
|
||||
moduleHelpers.setValue(value);
|
||||
module_nameHelpers.setValue(value);
|
||||
}}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormField
|
||||
id="arguments"
|
||||
name="arguments"
|
||||
id="module_args"
|
||||
name="module_args"
|
||||
type="text"
|
||||
label={i18n._(t`Arguments`)}
|
||||
isRequired={
|
||||
moduleField.value === 'command' || moduleField.value === 'shell'
|
||||
module_nameField.value === 'command' ||
|
||||
module_nameField.value === 'shell'
|
||||
}
|
||||
tooltip={
|
||||
module_nameField.value ? (
|
||||
<>
|
||||
{i18n._(
|
||||
t`These arguments are used with the specified module. You can find information about the ${module_argsField.value} by clicking `
|
||||
)}
|
||||
<a
|
||||
href={`https://docs.ansible.com/ansible/latest/modules/${module_argsField.value}_module.html`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
{' '}
|
||||
{i18n._(t`here.`)}
|
||||
</a>
|
||||
</>
|
||||
) : (
|
||||
i18n._(t`These arguments are used with the specified module.`)
|
||||
)
|
||||
}
|
||||
tooltip={i18n._(
|
||||
t`These arguments are used with the specified module.`
|
||||
)}
|
||||
/>
|
||||
<FormGroup
|
||||
fieldId="verbosity"
|
||||
@@ -106,7 +130,7 @@ function CredentialStep({ i18n, verbosityOptions, moduleOptions }) {
|
||||
id="verbosity"
|
||||
data={verbosityOptions || []}
|
||||
onChange={(event, value) => {
|
||||
verbosityHelpers.setValue(value);
|
||||
verbosityHelpers.setValue(parseInt(value, 10));
|
||||
}}
|
||||
/>
|
||||
</FormGroup>
|
||||
@@ -164,20 +188,17 @@ function CredentialStep({ i18n, verbosityOptions, moduleOptions }) {
|
||||
>
|
||||
<Switch
|
||||
css="display: inline-flex;"
|
||||
id="changes"
|
||||
id="diff_mode"
|
||||
label={i18n._(t`On`)}
|
||||
labelOff={i18n._(t`Off`)}
|
||||
isChecked={changesField.value}
|
||||
isChecked={diff_modeField.value}
|
||||
onChange={() => {
|
||||
changesHelpers.setValue(!changesField.value);
|
||||
diff_modeHelpers.setValue(!diff_modeField.value);
|
||||
}}
|
||||
aria-label={i18n._(t`toggle changes`)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
name={i18n._(t`enable privilege escalation`)}
|
||||
fieldId="escalation"
|
||||
>
|
||||
<FormGroup name="become_enabled" fieldId="become_enabled">
|
||||
<FormCheckboxLayout>
|
||||
<Checkbox
|
||||
aria-label={i18n._(t`Enable privilege escalation`)}
|
||||
@@ -202,10 +223,10 @@ function CredentialStep({ i18n, verbosityOptions, moduleOptions }) {
|
||||
/>
|
||||
</span>
|
||||
}
|
||||
id="escalation"
|
||||
isChecked={escalationField.value}
|
||||
id="become_enabled"
|
||||
isChecked={become_enabledField.value}
|
||||
onChange={checked => {
|
||||
escalationHelpers.setValue(checked);
|
||||
become_enabledHelpers.setValue(checked);
|
||||
}}
|
||||
/>
|
||||
</FormCheckboxLayout>
|
||||
|
||||
@@ -29,7 +29,7 @@ const initialValues = {
|
||||
extra_vars: '---',
|
||||
};
|
||||
|
||||
describe('<DetailsStep />', () => {
|
||||
describe('<AdHocDetailsStep />', () => {
|
||||
let wrapper;
|
||||
|
||||
afterEach(() => {
|
||||
@@ -64,14 +64,12 @@ describe('<DetailsStep />', () => {
|
||||
);
|
||||
});
|
||||
expect(wrapper.find('FormGroup[label="Module"]').length).toBe(1);
|
||||
expect(wrapper.find('FormField[name="arguments"]').length).toBe(1);
|
||||
expect(wrapper.find('FormField[label="Arguments"]').length).toBe(1);
|
||||
expect(wrapper.find('FormGroup[label="Verbosity"]').length).toBe(1);
|
||||
expect(wrapper.find('FormField[label="Limit"]').length).toBe(1);
|
||||
expect(wrapper.find('FormField[name="forks"]').length).toBe(1);
|
||||
expect(wrapper.find('FormGroup[label="Show changes"]').length).toBe(1);
|
||||
expect(
|
||||
wrapper.find('FormGroup[name="enable privilege escalation"]').length
|
||||
).toBe(1);
|
||||
expect(wrapper.find('FormGroup[name="become_enabled"]').length).toBe(1);
|
||||
expect(wrapper.find('VariablesField').length).toBe(1);
|
||||
});
|
||||
|
||||
@@ -89,12 +87,12 @@ describe('<DetailsStep />', () => {
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
wrapper.find('AnsibleSelect[name="module_args"]').prop('onChange')(
|
||||
wrapper.find('AnsibleSelect[name="module_name"]').prop('onChange')(
|
||||
{},
|
||||
'command'
|
||||
);
|
||||
wrapper.find('input#arguments').simulate('change', {
|
||||
target: { value: 'foo', name: 'arguments' },
|
||||
wrapper.find('input#module_args').simulate('change', {
|
||||
target: { value: 'foo', name: 'module_args' },
|
||||
});
|
||||
wrapper.find('input#limit').simulate('change', {
|
||||
target: {
|
||||
@@ -116,9 +114,9 @@ describe('<DetailsStep />', () => {
|
||||
});
|
||||
wrapper.update();
|
||||
expect(
|
||||
wrapper.find('AnsibleSelect[name="module_args"]').prop('value')
|
||||
wrapper.find('AnsibleSelect[name="module_name"]').prop('value')
|
||||
).toBe('command');
|
||||
expect(wrapper.find('input#arguments').prop('value')).toBe('foo');
|
||||
expect(wrapper.find('input#module_args').prop('value')).toBe('foo');
|
||||
expect(wrapper.find('AnsibleSelect[name="verbosity"]').prop('value')).toBe(
|
||||
1
|
||||
);
|
||||
|
||||
@@ -83,7 +83,7 @@ describe('VariablesField', () => {
|
||||
)}
|
||||
</Formik>
|
||||
);
|
||||
expect(wrapper.find('Tooltip').length).toBe(1);
|
||||
expect(wrapper.find('Popover').length).toBe(1);
|
||||
});
|
||||
|
||||
it('should submit value through Formik', async () => {
|
||||
|
||||
@@ -61,6 +61,6 @@ describe('FieldWithPrompt', () => {
|
||||
</Formik>
|
||||
);
|
||||
expect(wrapper.find('.pf-c-form__label-required')).toHaveLength(1);
|
||||
expect(wrapper.find('Tooltip')).toHaveLength(1);
|
||||
expect(wrapper.find('Popover')).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import React, { useState } from 'react';
|
||||
import { node } from 'prop-types';
|
||||
import { Tooltip } from '@patternfly/react-core';
|
||||
import { Popover } from '@patternfly/react-core';
|
||||
import { QuestionCircleIcon as PFQuestionCircleIcon } from '@patternfly/react-icons';
|
||||
import styled from 'styled-components';
|
||||
|
||||
@@ -9,18 +9,20 @@ const QuestionCircleIcon = styled(PFQuestionCircleIcon)`
|
||||
`;
|
||||
|
||||
function FieldTooltip({ content, ...rest }) {
|
||||
const [showTooltip, setShowTooltip] = useState(false);
|
||||
if (!content) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<Tooltip
|
||||
position="right"
|
||||
content={content}
|
||||
trigger="click mouseenter focus"
|
||||
<Popover
|
||||
bodyContent={content}
|
||||
isVisible={showTooltip}
|
||||
hideOnOutsideClick
|
||||
shouldClose={() => setShowTooltip(false)}
|
||||
{...rest}
|
||||
>
|
||||
<QuestionCircleIcon />
|
||||
</Tooltip>
|
||||
<QuestionCircleIcon onClick={() => setShowTooltip(!showTooltip)} />
|
||||
</Popover>
|
||||
);
|
||||
}
|
||||
FieldTooltip.propTypes = {
|
||||
|
||||
Reference in New Issue
Block a user