#11 Implement delete question

This commit is contained in:
Christoph Lienhard 2020-12-29 17:26:52 +01:00
parent 7370a7c493
commit dd48494ca9
Signed by: christoph.lienhard
GPG key ID: 6B98870DDC270884
4 changed files with 142 additions and 30 deletions

View file

@ -27,10 +27,11 @@ const useStyles = makeStyles((theme: Theme) =>
interface ButtonWithSpinnerProps {
children: string,
handleClick?: () => void,
loading: boolean
onClick?: () => void,
loading?: boolean
type?: "button" | "submit",
fullWidth?: boolean,
autoFocus?: boolean
}
export default function ButtonWithSpinner(props: ButtonWithSpinnerProps) {
@ -45,7 +46,8 @@ export default function ButtonWithSpinner(props: ButtonWithSpinnerProps) {
fullWidth={!!props.fullWidth}
type={props.type}
disabled={props.loading}
onClick={props.handleClick}
onClick={props.onClick}
autoFocus={props.autoFocus}
>
{props.children}
</Button>

View file

@ -0,0 +1,52 @@
import React from 'react';
import Dialog from '@material-ui/core/Dialog';
import DialogContent from '@material-ui/core/DialogContent';
import DialogTitle from '@material-ui/core/DialogTitle';
import {Button, DialogActions, DialogContentText} from "@material-ui/core";
import ButtonWithSpinner from "./ButtonWithSpinner";
export interface DeleteConfirmationDialogContent {
id: string,
type: string,
title: string,
}
interface DeleteConfirmationDialogProps {
content: DeleteConfirmationDialogContent,
open: boolean,
loading?: boolean,
handleConfirmButtonClick(): void,
handleClose(): void,
}
export default function DeleteConfirmationDialog(props: DeleteConfirmationDialogProps) {
return (
<Dialog
open={props.open}
onClose={props.handleClose}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
>
<DialogTitle id="alert-dialog-title">{props.content.type} löschen?</DialogTitle>
<DialogContent>
<DialogContentText id="alert-dialog-description">
Möchten Sie die {props.content.type}
"{props.content.title}"
wirklich löschen?
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={props.handleClose} color="primary">
Abbrechen
</Button>
<ButtonWithSpinner onClick={props.handleConfirmButtonClick} autoFocus loading={props.loading}>
Löschen
</ButtonWithSpinner>
</DialogActions>
</Dialog>
);
}

View file

@ -17,7 +17,7 @@ export function DialogActionBar(props: DialogActionBarProps) {
<Button onClick={props.onCancelButtonClick} color="primary">
Abbrechen
</Button>
<ButtonWithSpinner loading={props.loading} handleClick={props.onConfirmButtonClick} >
<ButtonWithSpinner loading={props.loading} onClick={props.onConfirmButtonClick} >
{props.confirmButtonText ? props.confirmButtonText : "Ok"}
</ButtonWithSpinner>
</DialogActions>;

View file

@ -1,7 +1,7 @@
import {Paper, Typography} from "@material-ui/core";
import React, {useState} from "react";
import {makeStyles} from "@material-ui/core/styles";
import {useMutation, useQuery} from "@apollo/client";
import {Reference, useMutation, useQuery} from "@apollo/client";
import AddCard from "./AddCard";
import AccordionWithEdit from "./AccordionWithEdit";
import {
@ -16,11 +16,15 @@ import {
ADD_QUESTION,
AddQuestionResponse,
AddQuestionVariables,
DELETE_QUESTION,
DeleteQuestionResponse,
DeleteQuestionVariables,
EDIT_QUESTION,
EditQuestionResponse,
EditQuestionVariables
} from "../backend/mutations/question";
import {useSnackbar} from 'notistack';
import DeleteConfirmationDialog, {DeleteConfirmationDialogContent} from "./DeleteConfirmationDialog";
const useStyles = makeStyles((theme) => ({
root: {
@ -37,11 +41,19 @@ const emptyChangeQuestionDialog: ChangeQuestionDialogContent = {
categoryId: null,
}
const emptyDeleteConfirmationDialogContent: DeleteConfirmationDialogContent = {
id: "",
type: "Frage",
title: "",
}
export default function QuestionList() {
const [dialogOpen, setDialogOpen] = useState(false);
const [changeDialogOpen, setChangeDialogOpen] = useState(false);
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
const [dialogTitle, setDialogTitle] = useState("");
const [dialogConfirmButtonText, setDialogConfirmButtonText] = useState("");
const [dialogContent, setDialogContent] = useState(emptyChangeQuestionDialog);
const [changeDialogContent, setChangeDialogContent] = useState(emptyChangeQuestionDialog);
const [deleteDialogContent, setDeleteDialogContent] = useState(emptyDeleteConfirmationDialogContent);
const { enqueueSnackbar } = useSnackbar();
const questions = useQuery<GetAllQuestionsResponse, null>(GET_ALL_QUESTIONS).data?.allQuestions.nodes;
const categories = useQuery<GetAllCategoriesResponse, null>(GET_ALL_CATEGORIES).data?.allCategories.nodes;
@ -50,7 +62,7 @@ export default function QuestionList() {
onCompleted: (response) => {
if (response.updateQuestion) {
enqueueSnackbar("Frage erfolgreich geändert.", { variant: "success"})
setDialogOpen(false);
setChangeDialogOpen(false);
} else {
enqueueSnackbar("Ein Fehler ist aufgetreten, versuche es erneut.", { variant: "error"})
}
@ -61,7 +73,7 @@ export default function QuestionList() {
onCompleted: (response) => {
if (response.createQuestion) {
enqueueSnackbar("Frage erfolgreich hinzugefügt.", { variant: "success"})
setDialogOpen(false);
setChangeDialogOpen(false);
} else {
enqueueSnackbar("Ein Fehler ist aufgetreten, versuche es erneut.", { variant: "error"})
}
@ -81,6 +93,28 @@ export default function QuestionList() {
});
}
});
const [deleteQuestion, {loading: deleteLoading}] = useMutation<DeleteQuestionResponse, DeleteQuestionVariables>(DELETE_QUESTION, {
onError: (e) => enqueueSnackbar(`Ein Fehler ist aufgetreten: ${e.message}`, { variant: "error"}),
onCompleted: (response) => {
if (response.deleteQuestion) {
enqueueSnackbar("Frage erfolgreich gelöscht.", { variant: "success"})
setDeleteDialogOpen(false);
} else {
enqueueSnackbar("Ein Fehler ist aufgetreten, versuche es erneut.", { variant: "error"})
}
},
update: (cache, { data }) => {
const idToRemove = data?.deleteQuestion?.question.id;
cache.modify({
fields: {
allQuestions(existingQuestionsRef: { nodes: Array<Reference>} = { nodes: []}, {readField}) {
console.log("existingQuestion: ", existingQuestionsRef)
return {nodes: existingQuestionsRef.nodes.filter(questionRef => readField('id', questionRef) !== idToRemove)};
}
}
});
}
});
const classes = useStyles();
const loading = editLoading || addLoading;
@ -88,51 +122,67 @@ export default function QuestionList() {
const handleAddClick = () => {
setDialogTitle("Neue Frage erstellen");
setDialogConfirmButtonText("Erstellen");
if (dialogContent.id !== "") {
setDialogContent(emptyChangeQuestionDialog);
if (changeDialogContent.id !== "") {
setChangeDialogContent(emptyChangeQuestionDialog);
}
setDialogOpen(true);
setChangeDialogOpen(true);
}
const handleEditButtonClick = (question: BasicQuestionResponse) => {
setDialogTitle("Frage bearbeiten");
setDialogConfirmButtonText("Speichern")
if (dialogContent.id !== question.id) {
setDialogContent({
if (changeDialogContent.id !== question.id) {
setChangeDialogContent({
id: question.id,
title: question.text,
details: question.description,
categoryId: question.categoryByCategoryRowId ? question.categoryByCategoryRowId.rowId : null,
})
}
setDialogOpen(true);
setChangeDialogOpen(true);
};
const handleDialogContentChange = (content: ChangeQuestionDialogContent) => {
setDialogContent(content)
const handleDeleteButtonClick = (question: BasicQuestionResponse) => {
setDeleteDialogContent({
...deleteDialogContent,
id: question.id,
title: question.text,
});
setDeleteDialogOpen(true);
}
const handleConfirmButtonClick = () => {
if (dialogContent.id !== "") {
const handleDialogContentChange = (content: ChangeQuestionDialogContent) => {
setChangeDialogContent(content)
}
const handleChangeConfirmButtonClick = () => {
if (changeDialogContent.id !== "") {
editQuestion({
variables: {
id: dialogContent.id,
text: dialogContent.title,
description: dialogContent.details,
categoryRowId: dialogContent.categoryId,
id: changeDialogContent.id,
text: changeDialogContent.title,
description: changeDialogContent.details,
categoryRowId: changeDialogContent.categoryId,
}
})
} else {
addQuestion({
variables: {
text: dialogContent.title,
description: dialogContent.details,
categoryRowId: dialogContent.categoryId,
text: changeDialogContent.title,
description: changeDialogContent.details,
categoryRowId: changeDialogContent.categoryId,
}
})
}
};
const handleDeleteConfirmButtonClick = () => {
deleteQuestion({
variables: {
id: deleteDialogContent.id
}
})
};
return (
<Paper className={classes.root}>
<Typography component={"h2"} variant="h6" color="primary" gutterBottom>Fragen</Typography>
@ -143,6 +193,7 @@ export default function QuestionList() {
subTitle={question.categoryByCategoryRowId?.title}
description={question.description}
onEditButtonClick={() => handleEditButtonClick(question)}
onDeleteButtonClick={() => handleDeleteButtonClick(question)}
/>;
}
)}
@ -150,13 +201,20 @@ export default function QuestionList() {
<ChangeQuestionDialog
title={dialogTitle}
confirmButtonText={dialogConfirmButtonText}
open={dialogOpen}
content={dialogContent}
open={changeDialogOpen}
content={changeDialogContent}
categories={categories}
loading={loading}
handleContentChange={handleDialogContentChange}
handleConfirmButtonClick={handleConfirmButtonClick}
handleClose={() => setDialogOpen(false)}
handleConfirmButtonClick={handleChangeConfirmButtonClick}
handleClose={() => setChangeDialogOpen(false)}
/>
<DeleteConfirmationDialog
content={deleteDialogContent}
open={deleteDialogOpen}
loading={deleteLoading}
handleConfirmButtonClick={handleDeleteConfirmButtonClick}
handleClose={() => setDeleteDialogOpen(false)}
/>
</Paper>
)