From 1412bf6232787b4b1c0dfc5517f0440ca784bfa3 Mon Sep 17 00:00:00 2001 From: Keith Grant Date: Fri, 6 Mar 2020 15:53:37 -0800 Subject: [PATCH] add survey form --- awx/ui_next/package-lock.json | 41 +++- .../src/screens/Template/TemplateSurvey.jsx | 14 +- .../Template/shared/SurveyQuestionAdd.jsx | 27 ++ .../Template/shared/SurveyQuestionForm.jsx | 231 ++++++++++++++++++ .../screens/Template/shared/SurveyToolbar.jsx | 4 +- awx/ui_next/src/util/validators.jsx | 21 ++ awx/ui_next/src/util/validators.test.js | 29 ++- 7 files changed, 352 insertions(+), 15 deletions(-) create mode 100644 awx/ui_next/src/screens/Template/shared/SurveyQuestionAdd.jsx create mode 100644 awx/ui_next/src/screens/Template/shared/SurveyQuestionForm.jsx diff --git a/awx/ui_next/package-lock.json b/awx/ui_next/package-lock.json index 31d60bcd10..4f294b6abd 100644 --- a/awx/ui_next/package-lock.json +++ b/awx/ui_next/package-lock.json @@ -10625,7 +10625,8 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -10646,12 +10647,14 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -10666,17 +10669,20 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -10793,7 +10799,8 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -10805,6 +10812,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -10819,6 +10827,7 @@ "version": "3.0.4", "bundled": true, "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -10826,12 +10835,14 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -10850,6 +10861,7 @@ "version": "0.5.1", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -10930,7 +10942,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -10942,6 +10955,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -11027,7 +11041,8 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -11063,6 +11078,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -11082,6 +11098,7 @@ "version": "3.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -11125,12 +11142,14 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true } } }, diff --git a/awx/ui_next/src/screens/Template/TemplateSurvey.jsx b/awx/ui_next/src/screens/Template/TemplateSurvey.jsx index 5c3a3657a6..7ffe646c6c 100644 --- a/awx/ui_next/src/screens/Template/TemplateSurvey.jsx +++ b/awx/ui_next/src/screens/Template/TemplateSurvey.jsx @@ -8,6 +8,7 @@ import AlertModal from '@components/AlertModal'; import ErrorDetail from '@components/ErrorDetail'; import useRequest, { useDismissableError } from '@util/useRequest'; import SurveyList from './shared/SurveyList'; +import SurveyQuestionAdd from './shared/SurveyQuestionAdd'; function TemplateSurvey({ template, i18n }) { const [surveyEnabled, setSurveyEnabled] = useState(template.survey_enabled); @@ -37,6 +38,12 @@ function TemplateSurvey({ template, i18n }) { [template.id, setSurvey] ) ); + const updateSurveySpec = spec => { + updateSurvey({ + ...survey, + spec, + }); + }; const { request: deleteSurvey, error: deleteError } = useRequest( useCallback(async () => { @@ -64,13 +71,16 @@ function TemplateSurvey({ template, i18n }) { return ( <> - + + + + updateSurvey({ ...survey, spec })} + updateSurvey={updateSurveySpec} deleteSurvey={deleteSurvey} /> diff --git a/awx/ui_next/src/screens/Template/shared/SurveyQuestionAdd.jsx b/awx/ui_next/src/screens/Template/shared/SurveyQuestionAdd.jsx new file mode 100644 index 0000000000..3f420ef375 --- /dev/null +++ b/awx/ui_next/src/screens/Template/shared/SurveyQuestionAdd.jsx @@ -0,0 +1,27 @@ +import React, { useState } from 'react'; +import { useHistory, useRouteMatch } from 'react-router-dom'; +import { CardBody } from '@components/Card'; +import SurveyQuestionForm from './SurveyQuestionForm'; + +export default function SurveyQuestionAdd({ template }) { + const [formError, setFormError] = useState(null); + const history = useHistory(); + const match = useRouteMatch(); + + const handleSubmit = async formData => { + // + }; + + const handleCancel = () => { + history.push(match.url.replace('/add', '')); + }; + + return ( + + + + ); +} diff --git a/awx/ui_next/src/screens/Template/shared/SurveyQuestionForm.jsx b/awx/ui_next/src/screens/Template/shared/SurveyQuestionForm.jsx new file mode 100644 index 0000000000..61b20187b3 --- /dev/null +++ b/awx/ui_next/src/screens/Template/shared/SurveyQuestionForm.jsx @@ -0,0 +1,231 @@ +import React from 'react'; +import { func, string, bool, number, shape } from 'prop-types'; +import { Formik, useField } from 'formik'; +import { withI18n } from '@lingui/react'; +import { t } from '@lingui/macro'; +import { Form, FormGroup } from '@patternfly/react-core'; +import { FormColumnLayout } from '@components/FormLayout'; +import FormActionGroup from '@components/FormActionGroup/FormActionGroup'; +import FormField, { + CheckboxField, + PasswordField, + FormSubmitError, + FieldTooltip, +} from '@components/FormField'; +import AnsibleSelect from '@components/AnsibleSelect'; +import { required, noWhiteSpace, combine } from '@util/validators'; + +function AnswerType({ i18n }) { + const [field] = useField({ + name: 'type', + validate: required(i18n._(t`Select a value for this field`), i18n), + }); + + return ( + + + + + ); +} + +function SurveyQuestionForm({ + question, + handleSubmit, + handleCancel, + submitError, + i18n, +}) { + return ( + + {formik => ( +
+ + + + + + + + + {['text', 'textarea', 'password'].includes(formik.values.type) && ( + <> + + + + )} + {['integer', 'float'].includes(formik.values.type) && ( + <> + + + + )} + {['text', 'integer', 'float'].includes(formik.values.type) && ( + + )} + {formik.values.type === 'textarea' && ( + + )} + {formik.values.type === 'password' && ( + + )} + {['multiplechoice', 'multiselect'].includes(formik.values.type) && ( + <> + + + + )} + + + + + )} +
+ ); +} + +SurveyQuestionForm.propTypes = { + question: shape({ + question_name: string.isRequired, + question_description: string.isRequired, + required: bool, + type: string.isRequired, + min: number, + max: number, + }), + handleSubmit: func.isRequired, + handleCancel: func.isRequired, + submitError: shape({}), +}; + +SurveyQuestionForm.defaultProps = { + question: null, + submitError: null, +}; + +export default withI18n()(SurveyQuestionForm); diff --git a/awx/ui_next/src/screens/Template/shared/SurveyToolbar.jsx b/awx/ui_next/src/screens/Template/shared/SurveyToolbar.jsx index f3d880cefd..fa2e171615 100644 --- a/awx/ui_next/src/screens/Template/shared/SurveyToolbar.jsx +++ b/awx/ui_next/src/screens/Template/shared/SurveyToolbar.jsx @@ -1,4 +1,5 @@ import React from 'react'; +import { useRouteMatch } from 'react-router-dom'; import { t } from '@lingui/macro'; import { withI18n } from '@lingui/react'; @@ -20,6 +21,7 @@ function SurveyToolbar({ isDeleteDisabled, onToggleDeleteModal, }) { + const match = useRouteMatch(); return ( @@ -45,7 +47,7 @@ function SurveyToolbar({ - +