mirror of
https://github.com/ansible/awx.git
synced 2026-03-11 14:39:30 -02:30
This puts the formatted default and choice values on the formik object.
When we go to submit the form to the api we format it again in a way the api will recognize. Allowing formik to manage updating, the choices and the default values this way cleans up the code and removes a bunch of unnecessary splitting and joining of the choices an default choices strings
This commit is contained in:
@@ -29,7 +29,6 @@ function FormField(props) {
|
||||
helperText={helperText}
|
||||
helperTextInvalid={meta.error}
|
||||
isRequired={isRequired}
|
||||
validated={isValid ? 'default' : 'error'}
|
||||
label={label}
|
||||
labelIcon={<Popover content={tooltip} maxWidth={tooltipMaxWidth} />}
|
||||
>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { useField } from 'formik';
|
||||
import { t } from '@lingui/macro';
|
||||
import { t, Plural } from '@lingui/macro';
|
||||
import {
|
||||
FormGroup,
|
||||
TextInput,
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
import PFCheckIcon from '@patternfly/react-icons/dist/js/icons/check-icon';
|
||||
import styled from 'styled-components';
|
||||
import Popover from '../Popover';
|
||||
import { required } from '../../util/validators';
|
||||
|
||||
const InputGroup = styled(PFInputGroup)`
|
||||
padding-bottom: 5px;
|
||||
@@ -21,72 +22,103 @@ const CheckIcon = styled(PFCheckIcon)`
|
||||
props.isSelected &&
|
||||
`color: var(--pf-c-button--m-secondary--active--Color)`};
|
||||
`;
|
||||
function TextAndCheckboxField({ label, helperText, tooltip }) {
|
||||
const [choicesField, choicesMeta, choicesHelpers] = useField('choices');
|
||||
function TextAndCheckboxField({ label, tooltip }) {
|
||||
const [
|
||||
formattedChoicesField,
|
||||
formattedChoicesMeta,
|
||||
formattedChoicesHelpers,
|
||||
] = useField({
|
||||
name: 'formattedChoices',
|
||||
validate: required(null),
|
||||
});
|
||||
const [typeField] = useField('type');
|
||||
const [defaultField, , defaultHelpers] = useField('default');
|
||||
const isValid =
|
||||
!(formattedChoicesMeta.touched && formattedChoicesMeta.error) ||
|
||||
formattedChoicesField.value.trim().length > 0;
|
||||
|
||||
const handleCheckboxChange = v =>
|
||||
defaultSplit.includes(v)
|
||||
? defaultHelpers.setValue(defaultSplit.filter(d => d !== v).join('\n'))
|
||||
: defaultHelpers.setValue(defaultField.value.concat(`\n${v}`));
|
||||
const choicesSplit = choicesField.value.split('\n');
|
||||
const defaultSplit = defaultField.value?.split('\n');
|
||||
return (
|
||||
<FormGroup
|
||||
helperText={helperText}
|
||||
helperTextInvalid={choicesMeta.error}
|
||||
helperText={
|
||||
<Plural
|
||||
value={typeField.value === 'multiselect' ? 2 : 1}
|
||||
one="Click checkbox next to an option to mark it as the default value."
|
||||
other="Click checkbox next to an option to mark it as a default value."
|
||||
/>
|
||||
}
|
||||
hasNoPaddingTop
|
||||
helperTextInvalid={formattedChoicesMeta.error}
|
||||
label={label}
|
||||
isRequired
|
||||
onBlur={formattedChoicesHelpers.setTouched}
|
||||
validated={isValid ? 'default' : 'error'}
|
||||
labelIcon={<Popover content={tooltip} />}
|
||||
>
|
||||
{choicesSplit.map((v, i) => (
|
||||
{formattedChoicesField.value.map(({ choice, isDefault }, i) => (
|
||||
<InputGroup>
|
||||
<TextInput
|
||||
onKeyDown={e => {
|
||||
if (e.key === 'Enter' && i === choicesSplit.length - 1) {
|
||||
choicesHelpers.setValue(choicesField.value.concat('\n'));
|
||||
onKeyUp={e => {
|
||||
if (
|
||||
e.key === 'Enter' &&
|
||||
choice.trim().length > 0 &&
|
||||
i === formattedChoicesField.value.length - 1
|
||||
) {
|
||||
formattedChoicesHelpers.setValue(
|
||||
formattedChoicesField.value.concat({
|
||||
choice: '',
|
||||
isDefault: false,
|
||||
})
|
||||
);
|
||||
}
|
||||
// Remove empty string values from formattedChoices from formik and
|
||||
// remove the field from the UI.
|
||||
if (e.key === 'Backspace' && !choice.trim().length) {
|
||||
const removeEmptyField = formattedChoicesField.value.filter(
|
||||
(c, index) => index !== i
|
||||
);
|
||||
|
||||
if (e.key === 'Backspace' && v.length <= 1) {
|
||||
const removeEmptyField = choicesSplit
|
||||
.filter((choice, index) => index !== i)
|
||||
.join('\n');
|
||||
choicesHelpers.setValue(removeEmptyField);
|
||||
formattedChoicesHelpers.setValue(removeEmptyField);
|
||||
}
|
||||
}}
|
||||
value={v}
|
||||
value={choice}
|
||||
onChange={value => {
|
||||
defaultHelpers.setValue(
|
||||
defaultSplit.filter(d => d !== v).join('\n')
|
||||
const newValues = formattedChoicesField.value.map((cfv, index) =>
|
||||
i === index ? { choice: value, isDefault: false } : cfv
|
||||
);
|
||||
|
||||
const newFields = choicesSplit
|
||||
.map((choice, index) => (i === index ? value : choice))
|
||||
.join('\n');
|
||||
|
||||
return value === ''
|
||||
? choicesHelpers.setValue(
|
||||
choicesSplit.filter(d => d !== v).join('\n')
|
||||
)
|
||||
: choicesHelpers.setValue(newFields);
|
||||
formattedChoicesHelpers.setValue(newValues);
|
||||
}}
|
||||
/>
|
||||
<Tooltip
|
||||
content={t`Click to select this answer as a default answer.`}
|
||||
content={
|
||||
choice
|
||||
? t`Click to select this answer as a default answer.`
|
||||
: t`Must type an answer choice before a default value can be selected`
|
||||
}
|
||||
position="right"
|
||||
trigger="mouseenter"
|
||||
>
|
||||
<Button
|
||||
variant="control"
|
||||
aria-label={t`Click to toggle default value`}
|
||||
ouiaId={v}
|
||||
onClick={() =>
|
||||
typeField.value === 'multiselect'
|
||||
? handleCheckboxChange(v)
|
||||
: defaultHelpers.setValue(`${v}`)
|
||||
}
|
||||
ouiaId={choice}
|
||||
onClick={() => {
|
||||
const newValues = formattedChoicesField.value.map(
|
||||
(cfv, index) =>
|
||||
i === index
|
||||
? { choice: cfv.choice, isDefault: !cfv.isDefault }
|
||||
: cfv
|
||||
);
|
||||
const singleSelectValues = formattedChoicesField.value.map(
|
||||
(cfv, index) =>
|
||||
i === index
|
||||
? { choice: cfv.choice, isDefault: !cfv.isDefault }
|
||||
: { choice: cfv.choice, isDefault: false }
|
||||
);
|
||||
return typeField.value === 'multiplechoice'
|
||||
? formattedChoicesHelpers.setValue(singleSelectValues)
|
||||
: formattedChoicesHelpers.setValue(newValues);
|
||||
}}
|
||||
>
|
||||
<CheckIcon isSelected={defaultSplit?.includes(v) || false} />
|
||||
<CheckIcon isSelected={isDefault} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</InputGroup>
|
||||
|
||||
@@ -12,8 +12,11 @@ describe('<TextAndCheckboxField/>', () => {
|
||||
wrapper = mountWithContexts(
|
||||
<Formik
|
||||
initialValues={{
|
||||
choices: 'alex\napollo\nathena',
|
||||
default: 'alex\napollo',
|
||||
formattedChoices: [
|
||||
{ choice: 'apollo', isDefault: true },
|
||||
{ choice: 'alex', isDefault: true },
|
||||
{ choice: 'athena', isDefault: false },
|
||||
],
|
||||
type: 'multiselect',
|
||||
}}
|
||||
>
|
||||
@@ -21,21 +24,13 @@ describe('<TextAndCheckboxField/>', () => {
|
||||
</Formik>
|
||||
);
|
||||
});
|
||||
await act(async () =>
|
||||
wrapper
|
||||
.find('TextAndCheckboxField')
|
||||
.find('TextAndCheckboxField')
|
||||
.find('TextInput')
|
||||
.at(0)
|
||||
.prop('onChange')('alex')
|
||||
);
|
||||
wrapper.update();
|
||||
|
||||
expect(
|
||||
wrapper
|
||||
.find('Button[ouiaId="alex"]')
|
||||
.find('CheckIcon')
|
||||
.prop('isSelected')
|
||||
).toBe(false);
|
||||
).toBe(true);
|
||||
await act(() => wrapper.find('Button[ouiaId="alex"]').prop('onClick')());
|
||||
wrapper.update();
|
||||
expect(
|
||||
@@ -43,14 +38,13 @@ describe('<TextAndCheckboxField/>', () => {
|
||||
.find('Button[ouiaId="alex"]')
|
||||
.find('CheckIcon')
|
||||
.prop('isSelected')
|
||||
).toBe(true);
|
||||
).toBe(false);
|
||||
await act(async () =>
|
||||
wrapper
|
||||
.find('TextAndCheckboxField')
|
||||
.find('TextAndCheckboxField')
|
||||
.find('TextInput')
|
||||
.at(0)
|
||||
.prop('onKeyDown')({ key: 'Enter' })
|
||||
.prop('onKeyUp')({ key: 'Enter' })
|
||||
);
|
||||
wrapper.update();
|
||||
expect(wrapper.find('TextAndCheckboxField').find('InputGroup').length).toBe(
|
||||
@@ -58,16 +52,13 @@ describe('<TextAndCheckboxField/>', () => {
|
||||
);
|
||||
await act(async () =>
|
||||
wrapper
|
||||
.find('TextAndCheckboxField')
|
||||
.find('TextAndCheckboxField')
|
||||
.find('TextInput')
|
||||
.at(1)
|
||||
.at(2)
|
||||
.prop('onChange')('spencer')
|
||||
);
|
||||
wrapper.update();
|
||||
expect(wrapper.find('TextAndCheckboxField').find('InputGroup').length).toBe(
|
||||
3
|
||||
);
|
||||
|
||||
await act(() => wrapper.find('Button[ouiaId="spencer"]').prop('onClick')());
|
||||
wrapper.update();
|
||||
expect(
|
||||
@@ -83,7 +74,7 @@ describe('<TextAndCheckboxField/>', () => {
|
||||
.find('Button[ouiaId="alex"]')
|
||||
.find('CheckIcon')
|
||||
.prop('isSelected')
|
||||
).toBe(false);
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
test('should select default, multiplechoice', async () => {
|
||||
@@ -93,8 +84,11 @@ describe('<TextAndCheckboxField/>', () => {
|
||||
wrapper = mountWithContexts(
|
||||
<Formik
|
||||
initialValues={{
|
||||
choices: 'alex\napollo\nathena',
|
||||
default: 'alex\napollo',
|
||||
formattedChoices: [
|
||||
{ choice: 'alex', isDefault: true },
|
||||
{ choice: 'apollo', isDefault: false },
|
||||
{ choice: 'athena', isDefault: false },
|
||||
],
|
||||
type: 'multiplechoice',
|
||||
}}
|
||||
>
|
||||
@@ -102,21 +96,13 @@ describe('<TextAndCheckboxField/>', () => {
|
||||
</Formik>
|
||||
);
|
||||
});
|
||||
await act(async () =>
|
||||
wrapper
|
||||
.find('TextAndCheckboxField')
|
||||
.find('TextAndCheckboxField')
|
||||
.find('TextInput')
|
||||
.at(0)
|
||||
.prop('onChange')('alex')
|
||||
);
|
||||
wrapper.update();
|
||||
|
||||
expect(
|
||||
wrapper
|
||||
.find('Button[ouiaId="alex"]')
|
||||
.find('CheckIcon')
|
||||
.prop('isSelected')
|
||||
).toBe(false);
|
||||
).toBe(true);
|
||||
await act(() => wrapper.find('Button[ouiaId="alex"]').prop('onClick')());
|
||||
wrapper.update();
|
||||
expect(
|
||||
@@ -124,31 +110,27 @@ describe('<TextAndCheckboxField/>', () => {
|
||||
.find('Button[ouiaId="alex"]')
|
||||
.find('CheckIcon')
|
||||
.prop('isSelected')
|
||||
).toBe(true);
|
||||
).toBe(false);
|
||||
expect(wrapper.find('TextAndCheckboxField').find('InputGroup').length).toBe(
|
||||
3
|
||||
);
|
||||
await act(async () =>
|
||||
wrapper
|
||||
.find('TextAndCheckboxField')
|
||||
.find('TextAndCheckboxField')
|
||||
.find('TextInput')
|
||||
.at(0)
|
||||
.prop('onKeyDown')({ key: 'Enter' })
|
||||
.prop('onKeyUp')({ key: 'Enter' })
|
||||
);
|
||||
wrapper.update();
|
||||
await act(async () =>
|
||||
wrapper
|
||||
.find('TextAndCheckboxField')
|
||||
.find('TextAndCheckboxField')
|
||||
.find('TextInput')
|
||||
.at(1)
|
||||
.at(2)
|
||||
.prop('onChange')('spencer')
|
||||
);
|
||||
wrapper.update();
|
||||
expect(wrapper.find('TextAndCheckboxField').find('InputGroup').length).toBe(
|
||||
3
|
||||
);
|
||||
|
||||
await act(() => wrapper.find('Button[ouiaId="spencer"]').prop('onClick')());
|
||||
wrapper.update();
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -518,7 +518,7 @@ msgstr "Ansible Tower Documentation."
|
||||
#~ msgid "Ansible environment"
|
||||
#~ msgstr "Ansible environment"
|
||||
|
||||
#: screens/Template/Survey/SurveyQuestionForm.jsx:33
|
||||
#: screens/Template/Survey/SurveyQuestionForm.jsx:63
|
||||
msgid "Answer type"
|
||||
msgstr "Answer type"
|
||||
|
||||
@@ -1195,6 +1195,14 @@ msgstr "Click this button to verify connection to the secret management system u
|
||||
msgid "Click to create a new link to this node."
|
||||
msgstr "Click to create a new link to this node."
|
||||
|
||||
#: components/FormField/TextAndCheckboxField.jsx:99
|
||||
msgid "Click to select this answer as a default answer."
|
||||
msgstr "Click to select this answer as a default answer."
|
||||
|
||||
#: components/FormField/TextAndCheckboxField.jsx:107
|
||||
msgid "Click to toggle default value"
|
||||
msgstr "Click to toggle default value"
|
||||
|
||||
#: components/Workflow/WorkflowNodeHelp.jsx:168
|
||||
msgid "Click to view job details"
|
||||
msgstr "Click to view job details"
|
||||
@@ -5283,6 +5291,10 @@ msgstr "Multiple Choice (single select)"
|
||||
msgid "Multiple Choice Options"
|
||||
msgstr "Multiple Choice Options"
|
||||
|
||||
#: components/FormField/TextAndCheckboxField.jsx:100
|
||||
msgid "Must type an answer choice before a default value can be selected"
|
||||
msgstr "Must type an answer choice before a default value can be selected"
|
||||
|
||||
#: src/index.jsx:110
|
||||
#: src/pages/Portal.jsx:19
|
||||
#~ msgid "My View"
|
||||
@@ -6306,6 +6318,14 @@ msgstr "Preconditions for running this node when there are multiple parents. Ref
|
||||
msgid "Press Enter to edit. Press ESC to stop editing."
|
||||
msgstr "Press Enter to edit. Press ESC to stop editing."
|
||||
|
||||
#: screens/Template/Survey/SurveyQuestionForm.jsx:239
|
||||
msgid "Press Enter to get additional inputs. Refer to the"
|
||||
msgstr "Press Enter to get additional inputs. Refer to the"
|
||||
|
||||
#: screens/Template/Survey/SurveyQuestionForm.jsx:239
|
||||
#~ msgid "Press enter to get additional inputs. Refer to the"
|
||||
#~ msgstr "Press enter to get additional inputs. Refer to the"
|
||||
|
||||
#: components/LaunchPrompt/steps/usePreviewStep.jsx:23
|
||||
#: screens/Template/Survey/SurveyList.jsx:160
|
||||
#: screens/Template/Survey/SurveyList.jsx:162
|
||||
@@ -10032,6 +10052,10 @@ msgstr "expiration"
|
||||
msgid "for more info."
|
||||
msgstr "for more info."
|
||||
|
||||
#: screens/Template/Survey/SurveyQuestionForm.jsx:247
|
||||
msgid "for more information."
|
||||
msgstr "for more information."
|
||||
|
||||
#: src/screens/Inventory/shared/InventoryGroupsDeleteModal.jsx:117
|
||||
#~ msgid "group"
|
||||
#~ msgstr "group"
|
||||
|
||||
@@ -485,7 +485,7 @@ msgstr ""
|
||||
#~ msgid "Ansible environment"
|
||||
#~ msgstr ""
|
||||
|
||||
#: screens/Template/Survey/SurveyQuestionForm.jsx:33
|
||||
#: screens/Template/Survey/SurveyQuestionForm.jsx:63
|
||||
msgid "Answer type"
|
||||
msgstr ""
|
||||
|
||||
@@ -1127,6 +1127,14 @@ msgstr ""
|
||||
msgid "Click to create a new link to this node."
|
||||
msgstr ""
|
||||
|
||||
#: components/FormField/TextAndCheckboxField.jsx:99
|
||||
msgid "Click to select this answer as a default answer."
|
||||
msgstr ""
|
||||
|
||||
#: components/FormField/TextAndCheckboxField.jsx:107
|
||||
msgid "Click to toggle default value"
|
||||
msgstr ""
|
||||
|
||||
#: components/Workflow/WorkflowNodeHelp.jsx:168
|
||||
msgid "Click to view job details"
|
||||
msgstr ""
|
||||
@@ -6018,6 +6026,14 @@ msgstr ""
|
||||
msgid "Press Enter to edit. Press ESC to stop editing."
|
||||
msgstr ""
|
||||
|
||||
#: screens/Template/Survey/SurveyQuestionForm.jsx:239
|
||||
msgid "Press Enter to get additional inputs. Refer to the"
|
||||
msgstr ""
|
||||
|
||||
#: screens/Template/Survey/SurveyQuestionForm.jsx:239
|
||||
#~ msgid "Press enter to get additional inputs. Refer to the"
|
||||
#~ msgstr ""
|
||||
|
||||
#: components/LaunchPrompt/steps/usePreviewStep.jsx:23
|
||||
#: screens/Template/Survey/SurveyList.jsx:160
|
||||
#: screens/Template/Survey/SurveyList.jsx:162
|
||||
@@ -9543,6 +9559,10 @@ msgstr ""
|
||||
msgid "for more info."
|
||||
msgstr ""
|
||||
|
||||
#: screens/Template/Survey/SurveyQuestionForm.jsx:247
|
||||
msgid "for more information."
|
||||
msgstr ""
|
||||
|
||||
#: src/screens/Inventory/shared/InventoryGroupsDeleteModal.jsx:117
|
||||
#~ msgid "group"
|
||||
#~ msgstr ""
|
||||
|
||||
@@ -484,7 +484,7 @@ msgstr "Documentation Ansible Tower"
|
||||
#~ msgid "Ansible environment"
|
||||
#~ msgstr "Environnement Ansible"
|
||||
|
||||
#: screens/Template/Survey/SurveyQuestionForm.jsx:33
|
||||
#: screens/Template/Survey/SurveyQuestionForm.jsx:63
|
||||
msgid "Answer type"
|
||||
msgstr "Type de réponse"
|
||||
|
||||
@@ -1126,6 +1126,14 @@ msgstr "Cliquez sur ce bouton pour vérifier la connexion au système de gestion
|
||||
msgid "Click to create a new link to this node."
|
||||
msgstr "Cliquez pour créer un nouveau lien vers ce nœud."
|
||||
|
||||
#: components/FormField/TextAndCheckboxField.jsx:99
|
||||
msgid "Click to select this answer as a default answer."
|
||||
msgstr ""
|
||||
|
||||
#: components/FormField/TextAndCheckboxField.jsx:107
|
||||
msgid "Click to toggle default value"
|
||||
msgstr ""
|
||||
|
||||
#: components/Workflow/WorkflowNodeHelp.jsx:168
|
||||
msgid "Click to view job details"
|
||||
msgstr "Cliquez pour voir les détails de ce Job"
|
||||
@@ -6013,6 +6021,14 @@ msgstr ""
|
||||
msgid "Press Enter to edit. Press ESC to stop editing."
|
||||
msgstr ""
|
||||
|
||||
#: screens/Template/Survey/SurveyQuestionForm.jsx:239
|
||||
msgid "Press Enter to get additional inputs. Refer to the"
|
||||
msgstr ""
|
||||
|
||||
#: screens/Template/Survey/SurveyQuestionForm.jsx:239
|
||||
#~ msgid "Press enter to get additional inputs. Refer to the"
|
||||
#~ msgstr ""
|
||||
|
||||
#: components/LaunchPrompt/steps/usePreviewStep.jsx:23
|
||||
#: screens/Template/Survey/SurveyList.jsx:160
|
||||
#: screens/Template/Survey/SurveyList.jsx:162
|
||||
|
||||
@@ -484,7 +484,7 @@ msgstr "Ansible Tower ドキュメント。"
|
||||
#~ msgid "Ansible environment"
|
||||
#~ msgstr "Ansible 環境"
|
||||
|
||||
#: screens/Template/Survey/SurveyQuestionForm.jsx:33
|
||||
#: screens/Template/Survey/SurveyQuestionForm.jsx:63
|
||||
msgid "Answer type"
|
||||
msgstr "回答タイプ"
|
||||
|
||||
@@ -1126,6 +1126,14 @@ msgstr "このボタンをクリックして、選択した認証情報と指定
|
||||
msgid "Click to create a new link to this node."
|
||||
msgstr "クリックして、このノードへの新しいリンクを作成します。"
|
||||
|
||||
#: components/FormField/TextAndCheckboxField.jsx:99
|
||||
msgid "Click to select this answer as a default answer."
|
||||
msgstr ""
|
||||
|
||||
#: components/FormField/TextAndCheckboxField.jsx:107
|
||||
msgid "Click to toggle default value"
|
||||
msgstr ""
|
||||
|
||||
#: components/Workflow/WorkflowNodeHelp.jsx:168
|
||||
msgid "Click to view job details"
|
||||
msgstr "クリックしてジョブの詳細を表示"
|
||||
@@ -6009,6 +6017,14 @@ msgstr ""
|
||||
msgid "Press Enter to edit. Press ESC to stop editing."
|
||||
msgstr ""
|
||||
|
||||
#: screens/Template/Survey/SurveyQuestionForm.jsx:239
|
||||
msgid "Press Enter to get additional inputs. Refer to the"
|
||||
msgstr ""
|
||||
|
||||
#: screens/Template/Survey/SurveyQuestionForm.jsx:239
|
||||
#~ msgid "Press enter to get additional inputs. Refer to the"
|
||||
#~ msgstr ""
|
||||
|
||||
#: components/LaunchPrompt/steps/usePreviewStep.jsx:23
|
||||
#: screens/Template/Survey/SurveyList.jsx:160
|
||||
#: screens/Template/Survey/SurveyList.jsx:162
|
||||
|
||||
@@ -485,7 +485,7 @@ msgstr ""
|
||||
#~ msgid "Ansible environment"
|
||||
#~ msgstr ""
|
||||
|
||||
#: screens/Template/Survey/SurveyQuestionForm.jsx:33
|
||||
#: screens/Template/Survey/SurveyQuestionForm.jsx:63
|
||||
msgid "Answer type"
|
||||
msgstr ""
|
||||
|
||||
@@ -1127,6 +1127,14 @@ msgstr ""
|
||||
msgid "Click to create a new link to this node."
|
||||
msgstr ""
|
||||
|
||||
#: components/FormField/TextAndCheckboxField.jsx:99
|
||||
msgid "Click to select this answer as a default answer."
|
||||
msgstr ""
|
||||
|
||||
#: components/FormField/TextAndCheckboxField.jsx:107
|
||||
msgid "Click to toggle default value"
|
||||
msgstr ""
|
||||
|
||||
#: components/Workflow/WorkflowNodeHelp.jsx:168
|
||||
msgid "Click to view job details"
|
||||
msgstr ""
|
||||
@@ -6018,6 +6026,14 @@ msgstr ""
|
||||
msgid "Press Enter to edit. Press ESC to stop editing."
|
||||
msgstr ""
|
||||
|
||||
#: screens/Template/Survey/SurveyQuestionForm.jsx:239
|
||||
msgid "Press Enter to get additional inputs. Refer to the"
|
||||
msgstr ""
|
||||
|
||||
#: screens/Template/Survey/SurveyQuestionForm.jsx:239
|
||||
#~ msgid "Press enter to get additional inputs. Refer to the"
|
||||
#~ msgstr ""
|
||||
|
||||
#: components/LaunchPrompt/steps/usePreviewStep.jsx:23
|
||||
#: screens/Template/Survey/SurveyList.jsx:160
|
||||
#: screens/Template/Survey/SurveyList.jsx:162
|
||||
@@ -9543,6 +9559,10 @@ msgstr ""
|
||||
msgid "for more info."
|
||||
msgstr ""
|
||||
|
||||
#: screens/Template/Survey/SurveyQuestionForm.jsx:247
|
||||
msgid "for more information."
|
||||
msgstr ""
|
||||
|
||||
#: src/screens/Inventory/shared/InventoryGroupsDeleteModal.jsx:117
|
||||
#~ msgid "group"
|
||||
#~ msgstr ""
|
||||
|
||||
@@ -484,7 +484,7 @@ msgstr "Ansible Tower 文档"
|
||||
#~ msgid "Ansible environment"
|
||||
#~ msgstr "Ansible 环境"
|
||||
|
||||
#: screens/Template/Survey/SurveyQuestionForm.jsx:33
|
||||
#: screens/Template/Survey/SurveyQuestionForm.jsx:63
|
||||
msgid "Answer type"
|
||||
msgstr "Answer 类型"
|
||||
|
||||
@@ -1126,6 +1126,14 @@ msgstr "点击这个按钮使用所选凭证和指定的输入验证到 secret
|
||||
msgid "Click to create a new link to this node."
|
||||
msgstr "点击以创建到此节点的新链接。"
|
||||
|
||||
#: components/FormField/TextAndCheckboxField.jsx:99
|
||||
msgid "Click to select this answer as a default answer."
|
||||
msgstr ""
|
||||
|
||||
#: components/FormField/TextAndCheckboxField.jsx:107
|
||||
msgid "Click to toggle default value"
|
||||
msgstr ""
|
||||
|
||||
#: components/Workflow/WorkflowNodeHelp.jsx:168
|
||||
msgid "Click to view job details"
|
||||
msgstr "点击以查看作业详情"
|
||||
@@ -6009,6 +6017,14 @@ msgstr ""
|
||||
msgid "Press Enter to edit. Press ESC to stop editing."
|
||||
msgstr ""
|
||||
|
||||
#: screens/Template/Survey/SurveyQuestionForm.jsx:239
|
||||
msgid "Press Enter to get additional inputs. Refer to the"
|
||||
msgstr ""
|
||||
|
||||
#: screens/Template/Survey/SurveyQuestionForm.jsx:239
|
||||
#~ msgid "Press enter to get additional inputs. Refer to the"
|
||||
#~ msgstr ""
|
||||
|
||||
#: components/LaunchPrompt/steps/usePreviewStep.jsx:23
|
||||
#: screens/Template/Survey/SurveyList.jsx:160
|
||||
#: screens/Template/Survey/SurveyList.jsx:162
|
||||
|
||||
@@ -450,7 +450,7 @@ msgstr ""
|
||||
msgid "Ansible Tower Documentation."
|
||||
msgstr ""
|
||||
|
||||
#: screens/Template/Survey/SurveyQuestionForm.jsx:33
|
||||
#: screens/Template/Survey/SurveyQuestionForm.jsx:63
|
||||
msgid "Answer type"
|
||||
msgstr ""
|
||||
|
||||
@@ -1068,6 +1068,14 @@ msgstr ""
|
||||
msgid "Click to create a new link to this node."
|
||||
msgstr ""
|
||||
|
||||
#: components/FormField/TextAndCheckboxField.jsx:99
|
||||
msgid "Click to select this answer as a default answer."
|
||||
msgstr ""
|
||||
|
||||
#: components/FormField/TextAndCheckboxField.jsx:107
|
||||
msgid "Click to toggle default value"
|
||||
msgstr ""
|
||||
|
||||
#: components/Workflow/WorkflowNodeHelp.jsx:168
|
||||
msgid "Click to view job details"
|
||||
msgstr ""
|
||||
@@ -5797,6 +5805,14 @@ msgstr ""
|
||||
msgid "Press Enter to edit. Press ESC to stop editing."
|
||||
msgstr ""
|
||||
|
||||
#: screens/Template/Survey/SurveyQuestionForm.jsx:239
|
||||
msgid "Press Enter to get additional inputs. Refer to the"
|
||||
msgstr ""
|
||||
|
||||
#: screens/Template/Survey/SurveyQuestionForm.jsx:239
|
||||
#~ msgid "Press enter to get additional inputs. Refer to the"
|
||||
#~ msgstr ""
|
||||
|
||||
#: components/LaunchPrompt/steps/usePreviewStep.jsx:23
|
||||
#: screens/Template/Survey/SurveyList.jsx:160
|
||||
#: screens/Template/Survey/SurveyList.jsx:162
|
||||
|
||||
@@ -18,6 +18,28 @@ export default function SurveyQuestionAdd({ survey, updateSurvey }) {
|
||||
);
|
||||
return;
|
||||
}
|
||||
let choices = '';
|
||||
let defaultAnswers = '';
|
||||
if (
|
||||
question.type === 'multiselect' ||
|
||||
question.type === 'multiplechoice'
|
||||
) {
|
||||
question.formattedChoices.forEach(({ question: q, isDefault }, i) => {
|
||||
choices =
|
||||
i === question.formattedChoices.length - 1
|
||||
? choices.concat(`${q}`)
|
||||
: choices.concat(`${q}\n`);
|
||||
if (isDefault) {
|
||||
defaultAnswers =
|
||||
i === question.formattedChoices.length - 1
|
||||
? defaultAnswers.concat(`${q}`)
|
||||
: defaultAnswers.concat(`${q}\n`);
|
||||
}
|
||||
});
|
||||
question.default = defaultAnswers;
|
||||
question.choices = choices;
|
||||
}
|
||||
|
||||
if (question.type === 'multiselect') {
|
||||
question.default = question.default
|
||||
.split('\n')
|
||||
|
||||
@@ -55,6 +55,28 @@ export default function SurveyQuestionEdit({ survey, updateSurvey }) {
|
||||
if (questionIndex === -1) {
|
||||
throw new Error('Question not found in spec');
|
||||
}
|
||||
let choices = '';
|
||||
let defaultAnswers = '';
|
||||
if (
|
||||
formData.type === 'multiselect' ||
|
||||
formData.type === 'multiplechoice'
|
||||
) {
|
||||
formData.formattedChoices.forEach(({ question: q, isDefault }, i) => {
|
||||
choices =
|
||||
i === formData.formattedChoices.length - 1
|
||||
? choices.concat(`${q}`)
|
||||
: choices.concat(`${q}\n`);
|
||||
if (isDefault) {
|
||||
defaultAnswers =
|
||||
i === formData.formattedChoices.length - 1
|
||||
? defaultAnswers.concat(`${q}`)
|
||||
: defaultAnswers.concat(`${q}\n`);
|
||||
}
|
||||
});
|
||||
formData.default = defaultAnswers;
|
||||
formData.choices = choices;
|
||||
}
|
||||
|
||||
if (formData.type === 'multiselect') {
|
||||
formData.default = formData.default
|
||||
.split('\n')
|
||||
|
||||
@@ -12,7 +12,8 @@ import FormField, {
|
||||
FormSubmitError,
|
||||
TextAndCheckboxField,
|
||||
} from '../../../components/FormField';
|
||||
|
||||
import { useConfig } from '../../../contexts/Config';
|
||||
import getDocsBaseUrl from '../../../util/getDocsBaseUrl';
|
||||
import AnsibleSelect from '../../../components/AnsibleSelect';
|
||||
import Popover from '../../../components/Popover';
|
||||
import {
|
||||
@@ -25,37 +26,10 @@ import {
|
||||
} from '../../../util/validators';
|
||||
|
||||
function AnswerTypeField() {
|
||||
const [field, meta, helpers] = useField({
|
||||
const [field] = useField({
|
||||
name: 'type',
|
||||
validate: required(t`Select a value for this field`),
|
||||
});
|
||||
const [defaultField, defaultMeta, defaultHelpers] = useField('default');
|
||||
const [choicesField] = useField('choices');
|
||||
|
||||
const handleTypeChange = value => {
|
||||
helpers.setValue(value);
|
||||
|
||||
const firstElementInBoth = choicesField.value
|
||||
?.split('\n')
|
||||
.map(d =>
|
||||
defaultField.value?.split('\n').find(c => (c === d ? c : false))
|
||||
);
|
||||
|
||||
if (value === 'multiplechoice' && meta.initialValue === 'multiselect') {
|
||||
defaultHelpers.setValue(
|
||||
firstElementInBoth.length > 0
|
||||
? firstElementInBoth[0]
|
||||
: defaultField.value
|
||||
);
|
||||
}
|
||||
if (
|
||||
field.value === 'multiplechoice' &&
|
||||
value === 'multiselect' &&
|
||||
meta.initialValue === 'multiselect'
|
||||
) {
|
||||
defaultHelpers.setValue(defaultMeta.initialValue);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<FormGroup
|
||||
@@ -73,9 +47,6 @@ function AnswerTypeField() {
|
||||
<AnsibleSelect
|
||||
id="question-type"
|
||||
{...field}
|
||||
onChange={(event, value) => {
|
||||
handleTypeChange(value);
|
||||
}}
|
||||
data={[
|
||||
{ key: 'text', value: 'text', label: t`Text` },
|
||||
{ key: 'textarea', value: 'textarea', label: t`Textarea` },
|
||||
@@ -104,21 +75,44 @@ function SurveyQuestionForm({
|
||||
handleCancel,
|
||||
submitError,
|
||||
}) {
|
||||
const config = useConfig();
|
||||
let initialValues = {
|
||||
question_name: question?.question_name || '',
|
||||
question_description: question?.question_description || '',
|
||||
required: question ? question?.required : true,
|
||||
type: question?.type || 'text',
|
||||
variable: question?.variable || '',
|
||||
min: question?.min || 0,
|
||||
max: question?.max || 1024,
|
||||
default: question?.default || '',
|
||||
formattedChoices: question?.choices || [{ choice: '', isDefault: false }],
|
||||
new_question: !question,
|
||||
};
|
||||
if (question?.type === 'multiselect' || question?.type === 'multiplechoice') {
|
||||
const newQuestions = question.choices.split('\n').map(c => {
|
||||
if (question.default.split('\n').includes(c)) {
|
||||
return { choice: c, isDefault: true };
|
||||
}
|
||||
return { choice: c, isDefault: false };
|
||||
});
|
||||
|
||||
initialValues = {
|
||||
question_name: question?.question_name || '',
|
||||
question_description: question?.question_description || '',
|
||||
required: question ? question?.required : true,
|
||||
type: question?.type || 'text',
|
||||
variable: question?.variable || '',
|
||||
min: question?.min || 0,
|
||||
max: question?.max || 1024,
|
||||
formattedChoices: newQuestions,
|
||||
new_question: !question,
|
||||
};
|
||||
}
|
||||
|
||||
return (
|
||||
<Formik
|
||||
enableReinitialize
|
||||
initialValues={{
|
||||
question_name: question?.question_name || '',
|
||||
question_description: question?.question_description || '',
|
||||
required: question ? question?.required : true,
|
||||
type: question?.type || 'text',
|
||||
variable: question?.variable || '',
|
||||
min: question?.min || 0,
|
||||
max: question?.max || 1024,
|
||||
default: question?.default || '',
|
||||
choices: question?.choices || '',
|
||||
new_question: !question,
|
||||
}}
|
||||
initialValues={initialValues}
|
||||
onSubmit={handleSubmit}
|
||||
>
|
||||
{formik => (
|
||||
@@ -227,7 +221,19 @@ function SurveyQuestionForm({
|
||||
name="choices"
|
||||
label={t`Multiple Choice Options`}
|
||||
validate={required()}
|
||||
tooltip={t`Type answer choices and click the check next the default choice(s). Multiple Choice (multi select) can have more than 1 default answer. Multiple Choice (single select) can only have 1 default answer. Press enter to get additional inputs`}
|
||||
tooltip={
|
||||
<>
|
||||
{t`Press Enter to get additional inputs. Refer to the `}{' '}
|
||||
<a
|
||||
href={`${getDocsBaseUrl(
|
||||
config
|
||||
)}/html/userguide/job_templates.html#surveys`}
|
||||
>
|
||||
{t`documentation`}{' '}
|
||||
</a>
|
||||
{t`for more information.`}
|
||||
</>
|
||||
}
|
||||
isRequired
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -272,11 +272,10 @@ describe('<SurveyQuestionForm />', () => {
|
||||
).toBe(true);
|
||||
await act(async () =>
|
||||
wrapper
|
||||
.find('TextAndCheckboxField')
|
||||
.find('TextAndCheckboxField')
|
||||
.find('TextInput')
|
||||
.at(0)
|
||||
.prop('onKeyDown')({ key: 'Enter' })
|
||||
.prop('onKeyUp')({ key: 'Enter' })
|
||||
);
|
||||
wrapper.update();
|
||||
expect(wrapper.find('TextAndCheckboxField').find('InputGroup').length).toBe(
|
||||
@@ -284,7 +283,6 @@ describe('<SurveyQuestionForm />', () => {
|
||||
);
|
||||
await act(async () =>
|
||||
wrapper
|
||||
.find('TextAndCheckboxField')
|
||||
.find('TextAndCheckboxField')
|
||||
.find('TextInput')
|
||||
.at(1)
|
||||
@@ -327,7 +325,6 @@ describe('<SurveyQuestionForm />', () => {
|
||||
await selectType(wrapper, 'multiplechoice');
|
||||
await act(async () =>
|
||||
wrapper
|
||||
.find('TextAndCheckboxField')
|
||||
.find('TextAndCheckboxField')
|
||||
.find('TextInput')
|
||||
.at(0)
|
||||
@@ -353,16 +350,14 @@ describe('<SurveyQuestionForm />', () => {
|
||||
);
|
||||
await act(async () =>
|
||||
wrapper
|
||||
.find('TextAndCheckboxField')
|
||||
.find('TextAndCheckboxField')
|
||||
.find('TextInput')
|
||||
.at(0)
|
||||
.prop('onKeyDown')({ key: 'Enter' })
|
||||
.prop('onKeyUp')({ key: 'Enter' })
|
||||
);
|
||||
wrapper.update();
|
||||
await act(async () =>
|
||||
wrapper
|
||||
.find('TextAndCheckboxField')
|
||||
.find('TextAndCheckboxField')
|
||||
.find('TextInput')
|
||||
.at(1)
|
||||
|
||||
Reference in New Issue
Block a user