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:
Alex Corey
2021-04-21 15:52:07 -04:00
parent 98375a0328
commit 9dde854baa
18 changed files with 20266 additions and 143 deletions

View File

@@ -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} />}
>

View File

@@ -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>

View File

@@ -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();

View File

@@ -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"

View File

@@ -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 ""

View File

@@ -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

View File

@@ -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

View File

@@ -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 ""

View File

@@ -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

View File

@@ -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

View File

@@ -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')

View File

@@ -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')

View File

@@ -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
/>
)}

View File

@@ -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)