#11 Refactor: Introduce apollo reactive variables for global state

Use it to streamline entangle the delete dialog(s) from the list(s)
This commit is contained in:
Christoph Lienhard 2020-12-30 18:26:19 +01:00
parent 42dc7f285d
commit fc8bc6724b
Signed by: christoph.lienhard
GPG Key ID: 6B98870DDC270884
8 changed files with 233 additions and 181 deletions

View File

@ -5,20 +5,21 @@
"requires": true,
"dependencies": {
"@apollo/client": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.1.3.tgz",
"integrity": "sha512-zXMiaj+dX0sgXIwEV5d/PI6B8SZT2bqlKNjZWcEXRY7NjESF5J3nd4v8KOsrhHe+A3YhNv63tIl35Sq7uf41Pg==",
"version": "3.3.6",
"resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.3.6.tgz",
"integrity": "sha512-XSm/STyNS8aHdDigLLACKNMHwI0qaQmEHWHtTP+jHe/E1wZRnn66VZMMgwKLy2V4uHISHfmiZ4KpUKDPeJAKqg==",
"requires": {
"@graphql-typed-document-node/core": "^3.0.0",
"@types/zen-observable": "^0.8.0",
"@wry/context": "^0.5.2",
"@wry/equality": "^0.2.0",
"@wry/equality": "^0.3.0",
"fast-json-stable-stringify": "^2.0.0",
"graphql-tag": "^2.11.0",
"hoist-non-react-statics": "^3.3.2",
"optimism": "^0.12.1",
"optimism": "^0.13.1",
"prop-types": "^15.7.2",
"symbol-observable": "^1.2.0",
"ts-invariant": "^0.4.4",
"symbol-observable": "^2.0.0",
"ts-invariant": "^0.6.0",
"tslib": "^1.10.0",
"zen-observable": "^0.8.14"
}
@ -1171,6 +1172,11 @@
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz",
"integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow=="
},
"@graphql-typed-document-node/core": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.1.0.tgz",
"integrity": "sha512-wYn6r8zVZyQJ6rQaALBEln5B1pzxb9shV5Ef97kTvn6yVGrqyXVnDqnU24MXnFubR+rZjBY9NWuxX3FB2sTsjg=="
},
"@hapi/address": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/@hapi/address/-/address-2.1.4.tgz",
@ -2066,6 +2072,11 @@
"@types/jest": "*"
}
},
"@types/ungap__global-this": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/@types/ungap__global-this/-/ungap__global-this-0.3.1.tgz",
"integrity": "sha512-+/DsiV4CxXl6ZWefwHZDXSe1Slitz21tom38qPCaG0DYCS1NnDPIQDTKcmQ/tvK/edJUKkmuIDBJbmKDiB0r/g=="
},
"@types/yargs": {
"version": "13.0.10",
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.10.tgz",
@ -2080,9 +2091,9 @@
"integrity": "sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw=="
},
"@types/zen-observable": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/@types/zen-observable/-/zen-observable-0.8.0.tgz",
"integrity": "sha512-te5lMAWii1uEJ4FwLjzdlbw3+n0FZNOvFXHxQDKeT0dilh7HOzdMzV2TrJVUzq8ep7J4Na8OUYPRLSQkJHAlrg=="
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/@types/zen-observable/-/zen-observable-0.8.2.tgz",
"integrity": "sha512-HrCIVMLjE1MOozVoD86622S7aunluLb2PJdPfb3nYiEtohm8mIB/vyv0Fd37AdeMFrTUQXEunw78YloMA3Qilg=="
},
"@typescript-eslint/eslint-plugin": {
"version": "2.34.0",
@ -2138,6 +2149,11 @@
}
}
},
"@ungap/global-this": {
"version": "0.4.3",
"resolved": "https://registry.npmjs.org/@ungap/global-this/-/global-this-0.4.3.tgz",
"integrity": "sha512-MuHEpDBurNVeD6mV9xBcAN2wfTwuaFQhHuhWkJuXmyVJ5P5sBCw+nnFpdfb0tAvgWkfefWCsAoAsh7MTUr3LPg=="
},
"@webassemblyjs/ast": {
"version": "1.8.5",
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz",
@ -2297,19 +2313,33 @@
}
},
"@wry/context": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/@wry/context/-/context-0.5.2.tgz",
"integrity": "sha512-B/JLuRZ/vbEKHRUiGj6xiMojST1kHhu4WcreLfNN7q9DqQFrb97cWgf/kiYsPSUCAMVN0HzfFc8XjJdzgZzfjw==",
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/@wry/context/-/context-0.5.3.tgz",
"integrity": "sha512-n0uKHiWpf2ArHhmcHcUsKA+Dj0gtye/h56VmsDcoMRuK/ZPFeHKi8ck5L/ftqtF12ZbQR9l8xMPV7y+xybaRDA==",
"requires": {
"tslib": "^1.9.3"
"tslib": "^1.14.1"
},
"dependencies": {
"tslib": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
}
}
},
"@wry/equality": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/@wry/equality/-/equality-0.2.0.tgz",
"integrity": "sha512-Y4d+WH6hs+KZJUC8YKLYGarjGekBrhslDbf/R20oV+AakHPINSitHfDRQz3EGcEWc1luXYNUvMhawWtZVWNGvQ==",
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/@wry/equality/-/equality-0.3.1.tgz",
"integrity": "sha512-8/Ftr3jUZ4EXhACfSwPIfNsE8V6WKesdjp+Dxi78Bej6qlasAxiz0/F8j0miACRj9CL4vC5Y5FsfwwEYAuhWbg==",
"requires": {
"tslib": "^1.9.3"
"tslib": "^1.14.1"
},
"dependencies": {
"tslib": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
}
}
},
"@xtuc/ieee754": {
@ -9607,7 +9637,6 @@
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/notistack/-/notistack-1.0.3.tgz",
"integrity": "sha512-bRGF/eg2qNQ8BwagPLkHiqrz+W00PYtGY5Xl33I0Of1BTm7arksZO1JxssPTlti0qw127CxuWxm637ipn0eZ9g==",
"dev": true,
"requires": {
"clsx": "^1.1.0",
"hoist-non-react-statics": "^3.3.0"
@ -9909,9 +9938,9 @@
}
},
"optimism": {
"version": "0.12.1",
"resolved": "https://registry.npmjs.org/optimism/-/optimism-0.12.1.tgz",
"integrity": "sha512-t8I7HM1dw0SECitBYAqFOVHoBAHEQBTeKjIL9y9ImHzAVkdyPK4ifTgM4VJRDtTUY4r/u5Eqxs4XcGPHaoPkeQ==",
"version": "0.13.2",
"resolved": "https://registry.npmjs.org/optimism/-/optimism-0.13.2.tgz",
"integrity": "sha512-kJkpDUEs/Rp8HsAYYlDzyvQHlT6YZa95P+2GGNR8p/VvsIkt6NilAk7oeTvMRKCq7BeclB7+bmdIexog2859GQ==",
"requires": {
"@wry/context": "^0.5.2"
}
@ -13378,9 +13407,9 @@
}
},
"symbol-observable": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz",
"integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ=="
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-2.0.3.tgz",
"integrity": "sha512-sQV7phh2WCYAn81oAkakC5qjq2Ml0g8ozqz03wOGnx9dDlG1de6yrF+0RAzSJD8fPUow3PTSMf2SAbOGxb93BA=="
},
"symbol-tree": {
"version": "3.2.4",
@ -13704,10 +13733,12 @@
}
},
"ts-invariant": {
"version": "0.4.4",
"resolved": "https://registry.npmjs.org/ts-invariant/-/ts-invariant-0.4.4.tgz",
"integrity": "sha512-uEtWkFM/sdZvRNNDL3Ehu4WVpwaulhwQszV8mrtcdeE8nN00BV9mAmQ88RkrBhFgl9gMgvjJLAQcZbnPXI9mlA==",
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/ts-invariant/-/ts-invariant-0.6.0.tgz",
"integrity": "sha512-caoafsfgb8QxdrKzFfjKt627m4i8KTtfAiji0DYJfWI4A/S9ORNNpzYuD9br64kyKFgxn9UNaLLbSupam84mCA==",
"requires": {
"@types/ungap__global-this": "^0.3.1",
"@ungap/global-this": "^0.4.2",
"tslib": "^1.9.3"
}
},

View File

@ -3,7 +3,7 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@apollo/client": "^3.1.3",
"@apollo/client": "^3.2",
"@material-ui/core": "^4.11.0",
"@material-ui/icons": "^4.9.1",
"@material-ui/lab": "^4.0.0-alpha.57",

View File

@ -19,4 +19,5 @@ const authLink = setContext((_, { headers }) => {
export const client = new ApolloClient({
cache: new InMemoryCache(),
link: authLink.concat(httpLink),
connectToDevTools: true,
});

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 {Reference, useMutation, useQuery} from "@apollo/client";
import {useMutation, useQuery} from "@apollo/client";
import AddCard from "./AddCard";
import AccordionWithEdit from "./AccordionWithEdit";
import {
@ -12,18 +12,19 @@ import {
} from "../backend/queries/category";
import ChangeCategoryDialog, {ChangeCategoryDialogContent} from "./ChangeCategoryDialog";
import {useSnackbar} from "notistack";
import DeleteConfirmationDialog, {DeleteConfirmationDialogContent} from "./DeleteConfirmationDialog";
import {
ADD_CATEGORY,
AddCategoryResponse,
AddCategoryVariables,
DELETE_CATEGORY,
DeleteCategoryResponse,
DeleteCategoryVariables,
EDIT_CATEGORY,
EditCategoryResponse,
EditCategoryVariables
} from "../backend/mutations/category";
import DeleteCategoryDialog, {
deleteCategoryDialogId,
deleteCategoryDialogOpen,
deleteCategoryDialogTitle
} from "./DeleteCategoryDialog";
const useStyles = makeStyles((theme) => ({
root: {
@ -39,19 +40,11 @@ const emptyChangeCategoryDialog: ChangeCategoryDialogContent = {
details: "",
}
const emptyDeleteConfirmationDialogContent: DeleteConfirmationDialogContent = {
id: "",
type: "Kategorie",
title: "",
}
export default function CategoryList() {
const [changeDialogOpen, setChangeDialogOpen] = useState(false);
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
const [dialogTitle, setDialogTitle] = useState("");
const [dialogConfirmButtonText, setDialogConfirmButtonText] = useState("");
const [changeDialogContent, setChangeDialogContent] = useState(emptyChangeCategoryDialog);
const [deleteDialogContent, setDeleteDialogContent] = useState(emptyDeleteConfirmationDialogContent);
const { enqueueSnackbar } = useSnackbar();
const categories = useQuery<GetAllCategoriesResponse, null>(GET_ALL_CATEGORIES).data?.allCategories.nodes;
const [editCategory, {loading: editLoading}] = useMutation<EditCategoryResponse, EditCategoryVariables>(EDIT_CATEGORY, {
@ -90,28 +83,7 @@ export default function CategoryList() {
});
}
});
const [deleteCategory, {loading: deleteLoading}] = useMutation<DeleteCategoryResponse, DeleteCategoryVariables>(DELETE_CATEGORY, {
onError: (e) => enqueueSnackbar(`Ein Fehler ist aufgetreten: ${e.message}`, { variant: "error"}),
onCompleted: (response) => {
if (response.deleteCategory) {
enqueueSnackbar("Kategorie erfolgreich gelöscht.", { variant: "success"})
setDeleteDialogOpen(false);
} else {
enqueueSnackbar("Ein Fehler ist aufgetreten, versuche es erneut.", { variant: "error"})
}
},
update: (cache, { data }) => {
const idToRemove = data?.deleteCategory?.category.id;
cache.modify({
fields: {
allCategories(existingCategoriesRef: { nodes: Array<Reference>} = { nodes: []}, {readField}) {
console.log("existingCategory: ", existingCategoriesRef)
return {nodes: existingCategoriesRef.nodes.filter(categoryRef => readField('id', categoryRef) !== idToRemove)};
}
}
});
}
});
const classes = useStyles();
const loading = editLoading || addLoading;
@ -139,12 +111,9 @@ export default function CategoryList() {
};
const handleDeleteButtonClick = (category: BasicCategoryResponse) => {
setDeleteDialogContent({
...deleteDialogContent,
id: category.id,
title: category.title,
});
setDeleteDialogOpen(true);
deleteCategoryDialogTitle(category.title);
deleteCategoryDialogId(category.id);
deleteCategoryDialogOpen(true);
}
const handleDialogContentChange = (content: ChangeCategoryDialogContent) => {
@ -170,14 +139,6 @@ export default function CategoryList() {
}
};
const handleDeleteConfirmButtonClick = () => {
deleteCategory({
variables: {
id: deleteDialogContent.id
}
})
};
return (
<Paper className={classes.root}>
<Typography component={"h2"} variant="h6" color="primary" gutterBottom>Kategorien</Typography>
@ -200,13 +161,7 @@ export default function CategoryList() {
handleConfirmButtonClick={handleChangeConfirmButtonClick}
handleClose={() => setChangeDialogOpen(false)}
/>
<DeleteConfirmationDialog
content={deleteDialogContent}
open={deleteDialogOpen}
loading={deleteLoading}
handleConfirmButtonClick={handleDeleteConfirmButtonClick}
handleClose={() => setDeleteDialogOpen(false)}
/>
<DeleteCategoryDialog/>
</Paper>
)
}

View File

@ -0,0 +1,60 @@
import React from 'react';
import {makeVar, Reference, useMutation, useReactiveVar} from "@apollo/client";
import DeleteConfirmationDialog from "./DeleteConfirmationDialog";
import {useSnackbar} from "notistack";
import {DELETE_CATEGORY, DeleteCategoryResponse, DeleteCategoryVariables} from "../backend/mutations/category";
export const deleteCategoryDialogId = makeVar<string>("");
export const deleteCategoryDialogTitle = makeVar<string>("");
export const deleteCategoryDialogOpen = makeVar<boolean>(false);
export default function DeleteCategoryDialog() {
const {enqueueSnackbar} = useSnackbar();
const [deleteCategory, {loading}] = useMutation<DeleteCategoryResponse, DeleteCategoryVariables>(DELETE_CATEGORY, {
onError: (e) => enqueueSnackbar(`Ein Fehler ist aufgetreten: ${e.message}`, {variant: "error"}),
onCompleted: (response) => {
if (response.deleteCategory) {
enqueueSnackbar("Kategorie erfolgreich gelöscht.", {variant: "success"})
deleteCategoryDialogOpen(false);
} else {
enqueueSnackbar("Ein Fehler ist aufgetreten, versuche es erneut.", {variant: "error"})
}
},
update: (cache, {data}) => {
const idToRemove = data?.deleteCategory?.category.id;
cache.modify({
fields: {
allCategories(existingCategoriesRef: { nodes: Array<Reference> } = {nodes: []}, {readField}) {
console.log("existingCategory: ", existingCategoriesRef)
return {nodes: existingCategoriesRef.nodes.filter(categoryRef => readField('id', categoryRef) !== idToRemove)};
}
}
});
}
});
const open = useReactiveVar(deleteCategoryDialogOpen);
const title = useReactiveVar(deleteCategoryDialogTitle);
const id = useReactiveVar(deleteCategoryDialogId);
const handleConfirmButtonClick = () => {
deleteCategory({
variables: {
id
}
})
}
return (
<DeleteConfirmationDialog
open={open}
type={"Kategorie"}
title={title}
onConfirmButtonClick={handleConfirmButtonClick}
onClose={() => deleteCategoryDialogOpen(false)}
loading={loading}
/>
);
}

View File

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

View File

@ -0,0 +1,59 @@
import React from 'react';
import {makeVar, Reference, useMutation, useReactiveVar} from "@apollo/client";
import DeleteConfirmationDialog from "./DeleteConfirmationDialog";
import {DELETE_QUESTION, DeleteQuestionResponse, DeleteQuestionVariables} from "../backend/mutations/question";
import {useSnackbar} from "notistack";
export const deleteQuestionDialogId = makeVar<string>("");
export const deleteQuestionDialogTitle = makeVar<string>("");
export const deleteQuestionDialogOpen = makeVar<boolean>(false);
export default function DeleteQuestionDialog() {
const {enqueueSnackbar} = useSnackbar();
const [deleteQuestion, {loading}] = 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"})
deleteQuestionDialogOpen(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}) {
return {nodes: existingQuestionsRef.nodes.filter(questionRef => readField('id', questionRef) !== idToRemove)};
}
}
});
}
});
const open = useReactiveVar(deleteQuestionDialogOpen);
const title = useReactiveVar(deleteQuestionDialogTitle);
const id = useReactiveVar(deleteQuestionDialogId);
const handleConfirmButtonClick = () => {
deleteQuestion({
variables: {
id
}
})
}
return (
<DeleteConfirmationDialog
open={open}
type={"Frage"}
title={title}
onConfirmButtonClick={handleConfirmButtonClick}
onClose={() => deleteQuestionDialogOpen(false)}
loading={loading}
/>
);
}

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 {Reference, useMutation, useQuery} from "@apollo/client";
import {useMutation, useQuery} from "@apollo/client";
import AddCard from "./AddCard";
import AccordionWithEdit from "./AccordionWithEdit";
import {
@ -16,15 +16,12 @@ 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";
import DeleteQuestionDialog, {deleteQuestionDialogId, deleteQuestionDialogOpen, deleteQuestionDialogTitle} from "./DeleteQuestionDialog";
const useStyles = makeStyles((theme) => ({
root: {
@ -41,47 +38,39 @@ const emptyChangeQuestionDialog: ChangeQuestionDialogContent = {
categoryId: null,
}
const emptyDeleteConfirmationDialogContent: DeleteConfirmationDialogContent = {
id: "",
type: "Frage",
title: "",
}
export default function QuestionList() {
const [changeDialogOpen, setChangeDialogOpen] = useState(false);
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
const [dialogTitle, setDialogTitle] = useState("");
const [dialogConfirmButtonText, setDialogConfirmButtonText] = useState("");
const [changeDialogContent, setChangeDialogContent] = useState(emptyChangeQuestionDialog);
const [deleteDialogContent, setDeleteDialogContent] = useState(emptyDeleteConfirmationDialogContent);
const { enqueueSnackbar } = useSnackbar();
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;
const [editQuestion, {loading: editLoading}] = useMutation<EditQuestionResponse, EditQuestionVariables>(EDIT_QUESTION, {
onError: (e) => enqueueSnackbar(`Ein Fehler ist aufgetreten: ${e.message}`, { variant: "error"}),
onCompleted: (response) => {
if (response.updateQuestion) {
enqueueSnackbar("Frage erfolgreich geändert.", { variant: "success"})
setChangeDialogOpen(false);
} else {
enqueueSnackbar("Ein Fehler ist aufgetreten, versuche es erneut.", { variant: "error"})
}
}
});
const [addQuestion, {loading: addLoading}] = useMutation<AddQuestionResponse, AddQuestionVariables>(ADD_QUESTION, {
onError: (e) => enqueueSnackbar(`Ein Fehler ist aufgetreten: ${e.message}`, { variant: "error"}),
onError: (e) => enqueueSnackbar(`Ein Fehler ist aufgetreten: ${e.message}`, {variant: "error"}),
onCompleted: (response) => {
if (response.createQuestion) {
enqueueSnackbar("Frage erfolgreich hinzugefügt.", { variant: "success"})
if (response.updateQuestion) {
enqueueSnackbar("Frage erfolgreich geändert.", {variant: "success"})
setChangeDialogOpen(false);
} else {
enqueueSnackbar("Ein Fehler ist aufgetreten, versuche es erneut.", { variant: "error"})
enqueueSnackbar("Ein Fehler ist aufgetreten, versuche es erneut.", {variant: "error"})
}
}
});
const [addQuestion, {loading: addLoading}] = useMutation<AddQuestionResponse, AddQuestionVariables>(ADD_QUESTION, {
onError: (e) => enqueueSnackbar(`Ein Fehler ist aufgetreten: ${e.message}`, {variant: "error"}),
onCompleted: (response) => {
if (response.createQuestion) {
enqueueSnackbar("Frage erfolgreich hinzugefügt.", {variant: "success"})
setChangeDialogOpen(false);
} else {
enqueueSnackbar("Ein Fehler ist aufgetreten, versuche es erneut.", {variant: "error"})
}
},
update: (cache, { data }) => {
update: (cache, {data}) => {
cache.modify({
fields: {
allQuestions(existingQuestions = { nodes: []}) {
allQuestions(existingQuestions = {nodes: []}) {
const newQuestionRef = cache.writeFragment<BasicQuestionResponse | undefined>({
data: data?.createQuestion?.question,
fragment: BasicQuestionFragment,
@ -93,27 +82,6 @@ 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}) {
return {nodes: existingQuestionsRef.nodes.filter(questionRef => readField('id', questionRef) !== idToRemove)};
}
}
});
}
});
const classes = useStyles();
const loading = editLoading || addLoading;
@ -142,12 +110,9 @@ export default function QuestionList() {
};
const handleDeleteButtonClick = (question: BasicQuestionResponse) => {
setDeleteDialogContent({
...deleteDialogContent,
id: question.id,
title: question.title,
});
setDeleteDialogOpen(true);
deleteQuestionDialogTitle(question.title);
deleteQuestionDialogId(question.id);
deleteQuestionDialogOpen(true);
}
const handleDialogContentChange = (content: ChangeQuestionDialogContent) => {
@ -175,25 +140,17 @@ export default function QuestionList() {
}
};
const handleDeleteConfirmButtonClick = () => {
deleteQuestion({
variables: {
id: deleteDialogContent.id
}
})
};
return (
<Paper className={classes.root}>
<Typography component={"h2"} variant="h6" color="primary" gutterBottom>Fragen</Typography>
{questions?.map(question => <AccordionWithEdit
key={question.id}
title={question.title}
subTitle={question.categoryByCategoryRowId?.title}
description={question.description}
onEditButtonClick={() => handleEditButtonClick(question)}
onDeleteButtonClick={() => handleDeleteButtonClick(question)}
/>
{questions?.map(question => <AccordionWithEdit
key={question.id}
title={question.title}
subTitle={question.categoryByCategoryRowId?.title}
description={question.description}
onEditButtonClick={() => handleEditButtonClick(question)}
onDeleteButtonClick={() => handleDeleteButtonClick(question)}
/>
)}
<AddCard handleClick={handleAddClick}/>
<ChangeQuestionDialog
@ -207,13 +164,7 @@ export default function QuestionList() {
handleConfirmButtonClick={handleChangeConfirmButtonClick}
handleClose={() => setChangeDialogOpen(false)}
/>
<DeleteConfirmationDialog
content={deleteDialogContent}
open={deleteDialogOpen}
loading={deleteLoading}
handleConfirmButtonClick={handleDeleteConfirmButtonClick}
handleClose={() => setDeleteDialogOpen(false)}
/>
<DeleteQuestionDialog/>
</Paper>
)
}