mirror of
https://github.com/ansible/awx.git
synced 2026-01-13 19:10:07 -03:30
fix keys, clean up surveylist
This commit is contained in:
parent
07565b5efc
commit
eea80c45d1
@ -16,7 +16,6 @@ import JobTemplateDetail from './JobTemplateDetail';
|
||||
import JobTemplateEdit from './JobTemplateEdit';
|
||||
import { JobTemplatesAPI, OrganizationsAPI } from '@api';
|
||||
import TemplateSurvey from './TemplateSurvey';
|
||||
// import SurveyList from './shared/SurveyList';
|
||||
|
||||
class Template extends Component {
|
||||
constructor(props) {
|
||||
|
||||
@ -28,11 +28,7 @@ function TemplateSurvey({ template, i18n }) {
|
||||
fetchSurvey();
|
||||
}, [fetchSurvey]);
|
||||
|
||||
const {
|
||||
request: updateSurvey,
|
||||
isLoading: isUpdateLoading,
|
||||
error: updateError,
|
||||
} = useRequest(
|
||||
const { request: updateSurvey, error: updateError } = useRequest(
|
||||
useCallback(
|
||||
async updatedSurvey => {
|
||||
await JobTemplatesAPI.updateSurvey(template.id, updatedSurvey);
|
||||
@ -42,22 +38,14 @@ function TemplateSurvey({ template, i18n }) {
|
||||
)
|
||||
);
|
||||
|
||||
const {
|
||||
request: deleteSurvey,
|
||||
isLoading: isDeleteLoading,
|
||||
error: deleteError,
|
||||
} = useRequest(
|
||||
const { request: deleteSurvey, error: deleteError } = useRequest(
|
||||
useCallback(async () => {
|
||||
await JobTemplatesAPI.destroySurvey(template.id);
|
||||
setSurvey(null);
|
||||
}, [template.id, setSurvey])
|
||||
);
|
||||
|
||||
const {
|
||||
request: toggleSurvey,
|
||||
isLoading: isToggleLoading,
|
||||
error: toggleError,
|
||||
} = useRequest(
|
||||
const { request: toggleSurvey, error: toggleError } = useRequest(
|
||||
useCallback(async () => {
|
||||
await JobTemplatesAPI.update(template.id, {
|
||||
survey_enabled: !surveyEnabled,
|
||||
@ -78,6 +66,7 @@ function TemplateSurvey({ template, i18n }) {
|
||||
<Switch>
|
||||
<Route path="/templates/:templateType/:id/survey">
|
||||
<SurveyList
|
||||
isLoading={isLoading}
|
||||
survey={survey}
|
||||
surveyEnabled={surveyEnabled}
|
||||
toggleSurvey={toggleSurvey}
|
||||
|
||||
@ -1,18 +1,15 @@
|
||||
import React, { useState } from 'react';
|
||||
import { withI18n } from '@lingui/react';
|
||||
import { t } from '@lingui/macro';
|
||||
|
||||
import { Button } from '@patternfly/react-core';
|
||||
|
||||
import ContentError from '@components/ContentError';
|
||||
import { DataList, Button } from '@patternfly/react-core';
|
||||
import ContentLoading from '@components/ContentLoading';
|
||||
import ErrorDetail from '@components/ErrorDetail';
|
||||
import ContentEmpty from '@components/ContentEmpty';
|
||||
import AlertModal from '@components/AlertModal';
|
||||
import SurveyListItem from './SurveyListItem';
|
||||
import SurveyToolbar from './SurveyToolbar';
|
||||
|
||||
function SurveyList({
|
||||
isLoading,
|
||||
survey,
|
||||
surveyEnabled,
|
||||
toggleSurvey,
|
||||
@ -32,8 +29,8 @@ function SurveyList({
|
||||
};
|
||||
|
||||
const handleSelect = item => {
|
||||
if (selected.some(s => s.id === item.id)) {
|
||||
setSelected(selected.filter(s => s.id !== item.id));
|
||||
if (selected.some(q => q.variable === item.variable)) {
|
||||
setSelected(selected.filter(q => q.variable !== item.variable));
|
||||
} else {
|
||||
setSelected(selected.concat(item));
|
||||
}
|
||||
@ -71,8 +68,7 @@ function SurveyList({
|
||||
};
|
||||
|
||||
let content;
|
||||
// TODO
|
||||
if (false) {
|
||||
if (isLoading) {
|
||||
content = <ContentLoading />;
|
||||
} else if (!questions || questions?.length <= 0) {
|
||||
content = (
|
||||
@ -82,37 +78,24 @@ function SurveyList({
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
content = questions?.map((question, index) => (
|
||||
<SurveyListItem
|
||||
key={question.variable}
|
||||
isLast={index === questions.length - 1}
|
||||
isFirst={index === 0}
|
||||
question={question}
|
||||
isChecked={selected.some(s => s.id === question.id)}
|
||||
onSelect={() => handleSelect(question)}
|
||||
onMoveUp={moveUp}
|
||||
onMoveDown={moveDown}
|
||||
/>
|
||||
));
|
||||
content = (
|
||||
<DataList aria-label={i18n._(t`Survey List`)}>
|
||||
{questions?.map((question, index) => (
|
||||
<SurveyListItem
|
||||
key={question.variable}
|
||||
isLast={index === questions.length - 1}
|
||||
isFirst={index === 0}
|
||||
question={question}
|
||||
isChecked={selected.some(q => q.variable === question.variable)}
|
||||
onSelect={() => handleSelect(question)}
|
||||
onMoveUp={moveUp}
|
||||
onMoveDown={moveDown}
|
||||
/>
|
||||
))}
|
||||
</DataList>
|
||||
);
|
||||
}
|
||||
|
||||
// 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 (
|
||||
<>
|
||||
<SurveyToolbar
|
||||
@ -135,7 +118,6 @@ function SurveyList({
|
||||
isOpen={isDeleteModalOpen}
|
||||
onClose={() => {
|
||||
setIsDeleteModalOpen(false);
|
||||
setSelected([]);
|
||||
}}
|
||||
actions={[
|
||||
<Button
|
||||
@ -152,7 +134,6 @@ function SurveyList({
|
||||
aria-label={i18n._(t`cancel delete`)}
|
||||
onClick={() => {
|
||||
setIsDeleteModalOpen(false);
|
||||
setSelected([]);
|
||||
}}
|
||||
>
|
||||
{i18n._(t`Cancel`)}
|
||||
@ -160,25 +141,15 @@ function SurveyList({
|
||||
]}
|
||||
>
|
||||
<div>{i18n._(t`This action will delete the following:`)}</div>
|
||||
{selected.map(question => (
|
||||
<span key={question.id}>
|
||||
<strong>{question.question_name}</strong>
|
||||
<br />
|
||||
</span>
|
||||
))}
|
||||
<ul>
|
||||
{selected.map(question => (
|
||||
<li key={question.variable}>
|
||||
<strong>{question.question_name}</strong>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</AlertModal>
|
||||
)}
|
||||
{/* {showError && (
|
||||
<AlertModal
|
||||
isOpen={showError}
|
||||
variant="error"
|
||||
title={i18n._(t`Error!`)}
|
||||
onClose={() => setShowError(false)}
|
||||
>
|
||||
{errorMessage}
|
||||
<ErrorDetail error={error} />
|
||||
</AlertModal>
|
||||
)} */}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,255 +0,0 @@
|
||||
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 = <ContentLoading />;
|
||||
} else if (contentError) {
|
||||
content = <ContentError error={contentError} />;
|
||||
} else if (!questions || questions?.length <= 0) {
|
||||
content = (
|
||||
<ContentEmpty
|
||||
title={i18n._(t`No Survey Questions Found`)}
|
||||
message={i18n._(t`Please add survey questions.`)}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
content = questions?.map((question, index) => (
|
||||
<SurveyListItem
|
||||
key={question.id}
|
||||
isLast={index === questions.length - 1}
|
||||
isFirst={index === 0}
|
||||
question={question}
|
||||
isChecked={selected.some(s => 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 (
|
||||
<>
|
||||
<SurveyToolbar
|
||||
isAllSelected={isAllSelected}
|
||||
onSelectAll={handleSelectAll}
|
||||
surveyEnabled={surveyEnabled}
|
||||
onToggleSurvey={toggleSurvey}
|
||||
isDeleteDisabled={selected?.length === 0}
|
||||
onToggleDeleteModal={() => setIsDeleteModalOpen(true)}
|
||||
/>
|
||||
{content}
|
||||
{isDeleteModalOpen && (
|
||||
<AlertModal
|
||||
variant="danger"
|
||||
title={
|
||||
isAllSelected
|
||||
? i18n._(t`Delete Survey`)
|
||||
: i18n._(t`Delete Questions`)
|
||||
}
|
||||
isOpen={isDeleteModalOpen}
|
||||
onClose={() => {
|
||||
setIsDeleteModalOpen(false);
|
||||
setSelected([]);
|
||||
}}
|
||||
actions={[
|
||||
<Button
|
||||
key="delete"
|
||||
variant="danger"
|
||||
aria-label={i18n._(t`confirm delete`)}
|
||||
onClick={handleDelete}
|
||||
>
|
||||
{i18n._(t`Delete`)}
|
||||
</Button>,
|
||||
<Button
|
||||
key="cancel"
|
||||
variant="secondary"
|
||||
aria-label={i18n._(t`cancel delete`)}
|
||||
onClick={() => {
|
||||
setIsDeleteModalOpen(false);
|
||||
setSelected([]);
|
||||
}}
|
||||
>
|
||||
{i18n._(t`Cancel`)}
|
||||
</Button>,
|
||||
]}
|
||||
>
|
||||
<div>{i18n._(t`This action will delete the following:`)}</div>
|
||||
{selected.map(question => (
|
||||
<span key={question.id}>
|
||||
<strong>{question.question_name}</strong>
|
||||
<br />
|
||||
</span>
|
||||
))}
|
||||
</AlertModal>
|
||||
)}
|
||||
{showError && (
|
||||
<AlertModal
|
||||
isOpen={showError}
|
||||
variant="error"
|
||||
title={i18n._(t`Error!`)}
|
||||
onClose={() => setShowError(false)}
|
||||
>
|
||||
{errorMessage}
|
||||
<ErrorDetail error={error} />
|
||||
</AlertModal>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default withI18n()(SurveyList);
|
||||
@ -1,10 +1,8 @@
|
||||
import React from 'react';
|
||||
import { t } from '@lingui/macro';
|
||||
import { withI18n } from '@lingui/react';
|
||||
|
||||
import {
|
||||
Button as _Button,
|
||||
DataList,
|
||||
DataListAction as _DataListAction,
|
||||
DataListCheck,
|
||||
DataListItemCells,
|
||||
@ -28,6 +26,7 @@ const Button = styled(_Button)`
|
||||
padding-bottom: 0;
|
||||
padding-left: 0;
|
||||
`;
|
||||
|
||||
function SurveyListItem({
|
||||
question,
|
||||
i18n,
|
||||
@ -39,56 +38,54 @@ function SurveyListItem({
|
||||
onMoveDown,
|
||||
}) {
|
||||
return (
|
||||
<DataList aria-label={i18n._(t`Survey List`)}>
|
||||
<DataListItem aria-labelledby={i18n._(t`Survey questions`)}>
|
||||
<DataListItemRow css="padding-left:16px">
|
||||
<DataListAction
|
||||
id="sortQuestions"
|
||||
aria-labelledby={i18n._(t`Sort question order`)}
|
||||
aria-label={i18n._(t`Sort question order`)}
|
||||
>
|
||||
<Stack>
|
||||
<StackItem>
|
||||
<Button
|
||||
variant="plain"
|
||||
aria-label={i18n._(t`move up`)}
|
||||
isDisabled={isFirst}
|
||||
onClick={() => onMoveUp(question)}
|
||||
>
|
||||
<CaretUpIcon />
|
||||
</Button>
|
||||
</StackItem>
|
||||
<StackItem>
|
||||
<Button
|
||||
variant="plain"
|
||||
aria-label={i18n._(t`move down`)}
|
||||
isDisabled={isLast}
|
||||
onClick={() => onMoveDown(question)}
|
||||
>
|
||||
<CaretDownIcon />
|
||||
</Button>
|
||||
</StackItem>
|
||||
</Stack>
|
||||
</DataListAction>
|
||||
<DataListCheck
|
||||
checked={isChecked}
|
||||
onChange={onSelect}
|
||||
aria-labelledby="survey check"
|
||||
/>
|
||||
<DataListItemCells
|
||||
dataListCells={[
|
||||
<DataListCell key={question.question_name}>
|
||||
{question.question_name}
|
||||
</DataListCell>,
|
||||
<DataListCell key={question.type}>{question.type}</DataListCell>,
|
||||
<DataListCell key={question.default}>
|
||||
{question.default}
|
||||
</DataListCell>,
|
||||
]}
|
||||
/>
|
||||
</DataListItemRow>
|
||||
</DataListItem>
|
||||
</DataList>
|
||||
<DataListItem aria-labelledby={i18n._(t`Survey questions`)}>
|
||||
<DataListItemRow css="padding-left:16px">
|
||||
<DataListAction
|
||||
id="sortQuestions"
|
||||
aria-labelledby={i18n._(t`Sort question order`)}
|
||||
aria-label={i18n._(t`Sort question order`)}
|
||||
>
|
||||
<Stack>
|
||||
<StackItem>
|
||||
<Button
|
||||
variant="plain"
|
||||
aria-label={i18n._(t`move up`)}
|
||||
isDisabled={isFirst}
|
||||
onClick={() => onMoveUp(question)}
|
||||
>
|
||||
<CaretUpIcon />
|
||||
</Button>
|
||||
</StackItem>
|
||||
<StackItem>
|
||||
<Button
|
||||
variant="plain"
|
||||
aria-label={i18n._(t`move down`)}
|
||||
isDisabled={isLast}
|
||||
onClick={() => onMoveDown(question)}
|
||||
>
|
||||
<CaretDownIcon />
|
||||
</Button>
|
||||
</StackItem>
|
||||
</Stack>
|
||||
</DataListAction>
|
||||
<DataListCheck
|
||||
checked={isChecked}
|
||||
onChange={onSelect}
|
||||
aria-labelledby="survey check"
|
||||
/>
|
||||
<DataListItemCells
|
||||
dataListCells={[
|
||||
<DataListCell key={question.question_name}>
|
||||
{question.question_name}
|
||||
</DataListCell>,
|
||||
<DataListCell key={question.type}>{question.type}</DataListCell>,
|
||||
<DataListCell key={question.default}>
|
||||
{question.default}
|
||||
</DataListCell>,
|
||||
]}
|
||||
/>
|
||||
</DataListItemRow>
|
||||
</DataListItem>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user