mirror of
https://github.com/ZwareBear/awx.git
synced 2026-05-17 16:38:36 -05:00
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();
|
||||
|
||||
|
||||
+3435
File diff suppressed because it is too large
Load Diff
+3088
File diff suppressed because it is too large
Load Diff
+6498
File diff suppressed because it is too large
Load Diff
+6916
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