From 2584f7359ebdf201628f65ffd727ec0e3e57ce66 Mon Sep 17 00:00:00 2001 From: Keith Grant Date: Wed, 11 Mar 2020 09:32:36 -0700 Subject: [PATCH] restructure TemplateSurvey & list components --- awx/ui_next/src/screens/Template/Template.jsx | 10 +- .../src/screens/Template/TemplateSurvey.jsx | 56 ++++ .../screens/Template/shared/SurveyList.jsx | 141 +++------- .../Template/shared/SurveyList.orig.jsx | 255 ++++++++++++++++++ .../screens/Template/shared/surveyReducer.js | 15 ++ 5 files changed, 370 insertions(+), 107 deletions(-) create mode 100644 awx/ui_next/src/screens/Template/TemplateSurvey.jsx create mode 100644 awx/ui_next/src/screens/Template/shared/SurveyList.orig.jsx create mode 100644 awx/ui_next/src/screens/Template/shared/surveyReducer.js diff --git a/awx/ui_next/src/screens/Template/Template.jsx b/awx/ui_next/src/screens/Template/Template.jsx index 6baa9eb041..71cab03f77 100644 --- a/awx/ui_next/src/screens/Template/Template.jsx +++ b/awx/ui_next/src/screens/Template/Template.jsx @@ -15,7 +15,8 @@ import { ResourceAccessList } from '@components/ResourceAccessList'; import JobTemplateDetail from './JobTemplateDetail'; import JobTemplateEdit from './JobTemplateEdit'; import { JobTemplatesAPI, OrganizationsAPI } from '@api'; -import SurveyList from './shared/SurveyList'; +import TemplateSurvey from './TemplateSurvey'; +// import SurveyList from './shared/SurveyList'; class Template extends Component { constructor(props) { @@ -246,10 +247,9 @@ class Template extends Component { )} {template && ( - } - /> + + + )} { + (async () => { + const { data } = await JobTemplatesAPI.readSurvey(template.id); + setSurvey(data); + })(); + }, [template.id]); + + const updateSurvey = async newQuestions => { + await JobTemplatesAPI.updateSurvey(template.id, { + ...survey, + spec: newQuestions, + }); + setSurvey({ + ...survey, + spec: newQuestions, + }); + }; + + const deleteSurvey = async () => { + await JobTemplatesAPI.destroySurvey(template.id); + setSurvey(null); + }; + + const toggleSurvey = async () => { + await JobTemplatesAPI.update(template.id, { + survey_enabled: !surveyEnabled, + }); + setSurveyEnabled(!surveyEnabled); + }; + + // TODO + // if (contentError) { + // return ; + return ( + + + + + + ); +} diff --git a/awx/ui_next/src/screens/Template/shared/SurveyList.jsx b/awx/ui_next/src/screens/Template/shared/SurveyList.jsx index abc5a2e59e..d13ad3a2b7 100644 --- a/awx/ui_next/src/screens/Template/shared/SurveyList.jsx +++ b/awx/ui_next/src/screens/Template/shared/SurveyList.jsx @@ -2,7 +2,7 @@ import React, { useEffect, useCallback, useState } from 'react'; import { withI18n } from '@lingui/react'; import { t } from '@lingui/macro'; -import useRequest, { useDeleteItems } from '@util/useRequest'; +import useRequest from '@util/useRequest'; import { Button } from '@patternfly/react-core'; import ContentError from '@components/ContentError'; @@ -14,68 +14,24 @@ import AlertModal from '@components/AlertModal'; import SurveyListItem from './SurveyListItem'; import SurveyToolbar from './SurveyToolbar'; -function SurveyList({ template, i18n }) { +// survey.name +// survey.description +// survey.spec +function SurveyList({ + survey, + surveyEnabled, + toggleSurvey, + updateSurvey, + deleteSurvey, + i18n, +}) { + const questions = survey?.spec || []; const [selected, setSelected] = useState([]); - // const [updated, setUpdated] = useState(null); - const [surveyEnabled, setSurveyEnabled] = useState(template.survey_enabled); - const [showError, setShowError] = useState(false); + // const [showError, setShowError] = useState(false); const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); - const [questions, setQuestions] = useState(null); - - const { - result: { fetchedQuestions, name, description }, - error: contentError, - isLoading, - request: fetchSurvey, - } = useRequest( - useCallback(async () => { - const { - data: { spec = [], description: surveyDescription, name: surveyName }, - } = await JobTemplatesAPI.readSurvey(template.id); - - return { - fetchedQuestions: spec?.map((s, index) => ({ ...s, id: index })), - description: surveyDescription, - name: surveyName, - }; - }, [template.id]), - { questions: [], name: '', description: '' } - ); - - useEffect(() => { - setQuestions(fetchedQuestions); - }, [fetchedQuestions]); - - useEffect(() => { - fetchSurvey(); - }, [fetchSurvey]); const isAllSelected = selected.length === questions?.length && selected.length > 0; - const { - isLoading: isDeleteLoading, - deleteItems: deleteSurvey, - deletionError, - } = useDeleteItems( - useCallback(async () => { - await JobTemplatesAPI.destroySurvey(template.id); - fetchSurvey(); - }, [template.id, fetchSurvey]) - ); - - const { - isToggleLoading, - error: toggleError, - request: toggleSurvey, - } = useRequest( - useCallback(async () => { - await JobTemplatesAPI.update(template.id, { - survey_enabled: !surveyEnabled, - }); - return setSurveyEnabled(!surveyEnabled); - }, [template, surveyEnabled]), - template.survey_enabled - ); const handleSelectAll = isSelected => { setSelected(isSelected ? [...questions] : []); @@ -92,28 +48,13 @@ function SurveyList({ template, i18n }) { const handleDelete = async () => { if (isAllSelected) { await deleteSurvey(); - setIsDeleteModalOpen(false); } else { - setQuestions(questions.filter(q => !selected.includes(q))); - setIsDeleteModalOpen(false); + await updateSurvey(questions.filter(q => !selected.includes(q))); } + setIsDeleteModalOpen(false); setSelected([]); }; - const { - isLoading: isUpdateLoading, - error: updateError, - // request: updateSurvey, - } = useRequest( - useCallback(async () => { - return JobTemplatesAPI.updateSurvey(template.id, { - name, - description, - spec: questions, - }); - }, [template.id, name, description, questions]) - ); - const moveUp = question => { const index = questions.indexOf(question); if (index < 1) { @@ -122,7 +63,7 @@ function SurveyList({ template, i18n }) { const beginning = questions.slice(0, index - 1); const swapWith = questions[index - 1]; const end = questions.slice(index + 1); - setQuestions([...beginning, question, swapWith, ...end]); + updateSurvey([...beginning, question, swapWith, ...end]); }; const moveDown = question => { const index = questions.indexOf(question); @@ -132,17 +73,13 @@ function SurveyList({ template, i18n }) { const beginning = questions.slice(0, index); const swapWith = questions[index + 1]; const end = questions.slice(index + 2); - setQuestions([...beginning, swapWith, question, ...end]); + updateSurvey([...beginning, swapWith, question, ...end]); }; let content; - if ( - (isLoading || isToggleLoading || isDeleteLoading || isUpdateLoading) && - questions?.length <= 0 - ) { + // TODO + if (false) { content = ; - } else if (contentError) { - content = ; } else if (!questions || questions?.length <= 0) { content = ( ( { - if (error) { - setShowError(true); - } - }, [error]); + // const error = deletionError || toggleError || updateError; + // let errorMessage = ''; + // if (updateError) { + // errorMessage = i18n._(t`Failed to update survey`); + // } + // if (toggleError) { + // errorMessage = i18n._(t`Failed to toggle survey`); + // } + // if (deletionError) { + // errorMessage = i18n._(t`Failed to delete survey`); + // } + // useEffect(() => { + // if (error) { + // setShowError(true); + // } + // }, [error]); return ( <> @@ -237,7 +174,7 @@ function SurveyList({ template, i18n }) { ))} )} - {showError && ( + {/* {showError && ( - )} + )} */} ); } diff --git a/awx/ui_next/src/screens/Template/shared/SurveyList.orig.jsx b/awx/ui_next/src/screens/Template/shared/SurveyList.orig.jsx new file mode 100644 index 0000000000..abc5a2e59e --- /dev/null +++ b/awx/ui_next/src/screens/Template/shared/SurveyList.orig.jsx @@ -0,0 +1,255 @@ +import React, { useEffect, useCallback, useState } from 'react'; +import { withI18n } from '@lingui/react'; +import { t } from '@lingui/macro'; + +import useRequest, { useDeleteItems } from '@util/useRequest'; +import { Button } from '@patternfly/react-core'; + +import ContentError from '@components/ContentError'; +import ContentLoading from '@components/ContentLoading'; +import ErrorDetail from '@components/ErrorDetail'; +import { JobTemplatesAPI } from '@api'; +import ContentEmpty from '@components/ContentEmpty'; +import AlertModal from '@components/AlertModal'; +import SurveyListItem from './SurveyListItem'; +import SurveyToolbar from './SurveyToolbar'; + +function SurveyList({ template, i18n }) { + const [selected, setSelected] = useState([]); + // const [updated, setUpdated] = useState(null); + const [surveyEnabled, setSurveyEnabled] = useState(template.survey_enabled); + const [showError, setShowError] = useState(false); + const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); + const [questions, setQuestions] = useState(null); + + const { + result: { fetchedQuestions, name, description }, + error: contentError, + isLoading, + request: fetchSurvey, + } = useRequest( + useCallback(async () => { + const { + data: { spec = [], description: surveyDescription, name: surveyName }, + } = await JobTemplatesAPI.readSurvey(template.id); + + return { + fetchedQuestions: spec?.map((s, index) => ({ ...s, id: index })), + description: surveyDescription, + name: surveyName, + }; + }, [template.id]), + { questions: [], name: '', description: '' } + ); + + useEffect(() => { + setQuestions(fetchedQuestions); + }, [fetchedQuestions]); + + useEffect(() => { + fetchSurvey(); + }, [fetchSurvey]); + + const isAllSelected = + selected.length === questions?.length && selected.length > 0; + const { + isLoading: isDeleteLoading, + deleteItems: deleteSurvey, + deletionError, + } = useDeleteItems( + useCallback(async () => { + await JobTemplatesAPI.destroySurvey(template.id); + fetchSurvey(); + }, [template.id, fetchSurvey]) + ); + + const { + isToggleLoading, + error: toggleError, + request: toggleSurvey, + } = useRequest( + useCallback(async () => { + await JobTemplatesAPI.update(template.id, { + survey_enabled: !surveyEnabled, + }); + return setSurveyEnabled(!surveyEnabled); + }, [template, surveyEnabled]), + template.survey_enabled + ); + + const handleSelectAll = isSelected => { + setSelected(isSelected ? [...questions] : []); + }; + + const handleSelect = item => { + if (selected.some(s => s.id === item.id)) { + setSelected(selected.filter(s => s.id !== item.id)); + } else { + setSelected(selected.concat(item)); + } + }; + + const handleDelete = async () => { + if (isAllSelected) { + await deleteSurvey(); + setIsDeleteModalOpen(false); + } else { + setQuestions(questions.filter(q => !selected.includes(q))); + setIsDeleteModalOpen(false); + } + setSelected([]); + }; + + const { + isLoading: isUpdateLoading, + error: updateError, + // request: updateSurvey, + } = useRequest( + useCallback(async () => { + return JobTemplatesAPI.updateSurvey(template.id, { + name, + description, + spec: questions, + }); + }, [template.id, name, description, questions]) + ); + + const moveUp = question => { + const index = questions.indexOf(question); + if (index < 1) { + return; + } + const beginning = questions.slice(0, index - 1); + const swapWith = questions[index - 1]; + const end = questions.slice(index + 1); + setQuestions([...beginning, question, swapWith, ...end]); + }; + const moveDown = question => { + const index = questions.indexOf(question); + if (index === -1 || index > questions.length - 1) { + return; + } + const beginning = questions.slice(0, index); + const swapWith = questions[index + 1]; + const end = questions.slice(index + 2); + setQuestions([...beginning, swapWith, question, ...end]); + }; + + let content; + if ( + (isLoading || isToggleLoading || isDeleteLoading || isUpdateLoading) && + questions?.length <= 0 + ) { + content = ; + } else if (contentError) { + content = ; + } else if (!questions || questions?.length <= 0) { + content = ( + + ); + } else { + content = questions?.map((question, index) => ( + s.id === question.id)} + onSelect={() => handleSelect(question)} + onMoveUp={moveUp} + onMoveDown={moveDown} + /> + )); + } + + const error = deletionError || toggleError || updateError; + let errorMessage = ''; + if (updateError) { + errorMessage = i18n._(t`Failed to update survey`); + } + if (toggleError) { + errorMessage = i18n._(t`Failed to toggle survey`); + } + if (deletionError) { + errorMessage = i18n._(t`Failed to delete survey`); + } + useEffect(() => { + if (error) { + setShowError(true); + } + }, [error]); + + return ( + <> + setIsDeleteModalOpen(true)} + /> + {content} + {isDeleteModalOpen && ( + { + setIsDeleteModalOpen(false); + setSelected([]); + }} + actions={[ + , + , + ]} + > +
{i18n._(t`This action will delete the following:`)}
+ {selected.map(question => ( + + {question.question_name} +
+
+ ))} +
+ )} + {showError && ( + setShowError(false)} + > + {errorMessage} + + + )} + + ); +} + +export default withI18n()(SurveyList); diff --git a/awx/ui_next/src/screens/Template/shared/surveyReducer.js b/awx/ui_next/src/screens/Template/shared/surveyReducer.js new file mode 100644 index 0000000000..418792a1e4 --- /dev/null +++ b/awx/ui_next/src/screens/Template/shared/surveyReducer.js @@ -0,0 +1,15 @@ +export default function surveyReducer(state, action) { + switch (action.type) { + case 'THING': + return state; + default: + throw new Error(`Unrecognized action type: ${action.type}`); + } +} + +// move up/down -> Update +// delete -> Update +// delete all -> destroySurvey +// toggle -> Update survey_enabled +// select +// select all