#11 Add create/edit/delete functionality for categories
This commit is contained in:
parent
9a1dc02a7f
commit
101817276f
68
redaktions-app/src/backend/mutations/category.ts
Normal file
68
redaktions-app/src/backend/mutations/category.ts
Normal file
|
@ -0,0 +1,68 @@
|
|||
import {gql} from "@apollo/client";
|
||||
import {BasicCategoryFragment, BasicCategoryResponse} from "../queries/category";
|
||||
|
||||
export const EDIT_CATEGORY = gql`
|
||||
mutation UpdateCategory($id: ID!, $title: String, $description: String) {
|
||||
updateCategory(input: {id: $id, categoryPatch: {description: $description, title: $title}}) {
|
||||
category {
|
||||
...BasicCategoryFragment
|
||||
}
|
||||
}
|
||||
}
|
||||
${BasicCategoryFragment}
|
||||
`
|
||||
|
||||
export interface EditCategoryResponse {
|
||||
updateCategory?: BasicCategoryResponse
|
||||
}
|
||||
|
||||
export interface EditCategoryVariables {
|
||||
id: string,
|
||||
title?: string,
|
||||
description?: string,
|
||||
}
|
||||
|
||||
export const ADD_CATEGORY = gql`
|
||||
mutation AddCategory($title: String!, $description: String) {
|
||||
createCategory(input: {category: {title: $title, description: $description}}) {
|
||||
category {
|
||||
...BasicCategoryFragment
|
||||
}
|
||||
}
|
||||
}
|
||||
${BasicCategoryFragment}
|
||||
`
|
||||
|
||||
export interface AddCategoryResponse {
|
||||
createCategory?: {
|
||||
category: BasicCategoryResponse
|
||||
}
|
||||
}
|
||||
|
||||
export interface AddCategoryVariables {
|
||||
title: string,
|
||||
description?: string,
|
||||
}
|
||||
|
||||
export const DELETE_CATEGORY = gql`
|
||||
mutation DeleteCategory($id: ID!) {
|
||||
deleteCategory(input: { id: $id }) {
|
||||
category {
|
||||
...BasicCategoryFragment
|
||||
}
|
||||
}
|
||||
}
|
||||
${BasicCategoryFragment}
|
||||
`
|
||||
|
||||
export interface DeleteCategoryResponse {
|
||||
deleteCategory?: {
|
||||
category: BasicCategoryResponse
|
||||
}
|
||||
}
|
||||
|
||||
export interface DeleteCategoryVariables {
|
||||
id: string,
|
||||
}
|
||||
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import {gql} from "@apollo/client";
|
||||
|
||||
export const BasicCategoryFragment = gql`
|
||||
fragment BasicCategory on Category {
|
||||
fragment BasicCategoryFragment on Category {
|
||||
id
|
||||
rowId
|
||||
title
|
||||
|
@ -20,7 +20,7 @@ export const GET_ALL_CATEGORIES = gql`
|
|||
query AllCategories {
|
||||
allCategories {
|
||||
nodes {
|
||||
...BasicCategory
|
||||
...BasicCategoryFragment
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,29 @@
|
|||
import {Paper, Typography} from "@material-ui/core";
|
||||
import React, {useState} from "react";
|
||||
import {makeStyles} from "@material-ui/core/styles";
|
||||
import {useQuery} from "@apollo/client";
|
||||
import {Reference, useMutation, useQuery} from "@apollo/client";
|
||||
import AddCard from "./AddCard";
|
||||
import AccordionWithEdit from "./AccordionWithEdit";
|
||||
import {GET_ALL_CATEGORIES, GetAllCategoriesResponse, BasicCategoryResponse} from "../backend/queries/category";
|
||||
import {
|
||||
BasicCategoryFragment,
|
||||
BasicCategoryResponse,
|
||||
GET_ALL_CATEGORIES,
|
||||
GetAllCategoriesResponse
|
||||
} 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";
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
root: {
|
||||
|
@ -21,62 +39,174 @@ const emptyChangeCategoryDialog: ChangeCategoryDialogContent = {
|
|||
details: "",
|
||||
}
|
||||
|
||||
const emptyDeleteConfirmationDialogContent: DeleteConfirmationDialogContent = {
|
||||
id: "",
|
||||
type: "Kategorie",
|
||||
title: "",
|
||||
}
|
||||
|
||||
export default function CategoryList() {
|
||||
const {data} = useQuery<GetAllCategoriesResponse, null>(GET_ALL_CATEGORIES);
|
||||
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(emptyChangeCategoryDialog);
|
||||
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, {
|
||||
onError: (e) => enqueueSnackbar(`Ein Fehler ist aufgetreten: ${e.message}`, { variant: "error"}),
|
||||
onCompleted: (response) => {
|
||||
if (response.updateCategory) {
|
||||
enqueueSnackbar("Kategorie erfolgreich geändert.", { variant: "success"})
|
||||
setChangeDialogOpen(false);
|
||||
} else {
|
||||
enqueueSnackbar("Ein Fehler ist aufgetreten, versuche es erneut.", { variant: "error"})
|
||||
}
|
||||
}
|
||||
});
|
||||
const [addCategory, {loading: addLoading}] = useMutation<AddCategoryResponse, AddCategoryVariables>(ADD_CATEGORY, {
|
||||
onError: (e) => enqueueSnackbar(`Ein Fehler ist aufgetreten: ${e.message}`, { variant: "error"}),
|
||||
onCompleted: (response) => {
|
||||
if (response.createCategory) {
|
||||
enqueueSnackbar("Kategorie erfolgreich hinzugefügt.", { variant: "success"})
|
||||
setChangeDialogOpen(false);
|
||||
} else {
|
||||
enqueueSnackbar("Ein Fehler ist aufgetreten, versuche es erneut.", { variant: "error"})
|
||||
}
|
||||
},
|
||||
update: (cache, { data }) => {
|
||||
cache.modify({
|
||||
fields: {
|
||||
allCategories(existingCategories = { nodes: []}) {
|
||||
const newCategoryRef = cache.writeFragment<BasicCategoryResponse | undefined>({
|
||||
data: data?.createCategory?.category,
|
||||
fragment: BasicCategoryFragment,
|
||||
fragmentName: "BasicCategoryFragment",
|
||||
});
|
||||
return {nodes: [...existingCategories.nodes, newCategoryRef]};
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
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;
|
||||
|
||||
const handleAddClick = () => {
|
||||
setDialogTitle("Neue Kategorie erstellen");
|
||||
setDialogConfirmButtonText("Erstellen");
|
||||
if (dialogContent.id !== "") {
|
||||
setDialogContent(emptyChangeCategoryDialog);
|
||||
if (changeDialogContent.id !== "") {
|
||||
setChangeDialogContent(emptyChangeCategoryDialog);
|
||||
}
|
||||
setDialogOpen(true);
|
||||
setChangeDialogOpen(true);
|
||||
}
|
||||
|
||||
const handleEditButtonClick = (category: BasicCategoryResponse) => {
|
||||
setDialogTitle("Kategorie bearbeiten");
|
||||
setDialogConfirmButtonText("Speichern")
|
||||
if (dialogContent.id !== category.id) {
|
||||
setDialogContent({
|
||||
if (changeDialogContent.id !== category.id) {
|
||||
setChangeDialogContent({
|
||||
id: category.id,
|
||||
title: category.title,
|
||||
details: category.description,
|
||||
})
|
||||
}
|
||||
setDialogOpen(true);
|
||||
setChangeDialogOpen(true);
|
||||
};
|
||||
|
||||
const handleDialogContentChange = (content: ChangeCategoryDialogContent) => {
|
||||
setDialogContent(content)
|
||||
const handleDeleteButtonClick = (category: BasicCategoryResponse) => {
|
||||
setDeleteDialogContent({
|
||||
...deleteDialogContent,
|
||||
id: category.id,
|
||||
title: category.title,
|
||||
});
|
||||
setDeleteDialogOpen(true);
|
||||
}
|
||||
|
||||
const handleDialogContentChange = (content: ChangeCategoryDialogContent) => {
|
||||
setChangeDialogContent(content)
|
||||
}
|
||||
|
||||
const handleChangeConfirmButtonClick = () => {
|
||||
if (changeDialogContent.id !== "") {
|
||||
editCategory({
|
||||
variables: {
|
||||
id: changeDialogContent.id,
|
||||
title: changeDialogContent.title,
|
||||
description: changeDialogContent.details,
|
||||
}
|
||||
})
|
||||
} else {
|
||||
addCategory({
|
||||
variables: {
|
||||
title: changeDialogContent.title,
|
||||
description: changeDialogContent.details,
|
||||
}
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
const handleDeleteConfirmButtonClick = () => {
|
||||
deleteCategory({
|
||||
variables: {
|
||||
id: deleteDialogContent.id
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
return (
|
||||
<Paper className={classes.root}>
|
||||
<Typography component={"h2"} variant="h6" color="primary" gutterBottom>Kategorien</Typography>
|
||||
{data?.allCategories.nodes.map(category => <AccordionWithEdit
|
||||
{categories?.map(category => <AccordionWithEdit
|
||||
key={category.id}
|
||||
title={category.title}
|
||||
description={category.description}
|
||||
onEditButtonClick={() => handleEditButtonClick(category)}
|
||||
onDeleteButtonClick={() => handleDeleteButtonClick(category)}
|
||||
/>
|
||||
)}
|
||||
<AddCard handleClick={handleAddClick}/>
|
||||
<ChangeCategoryDialog
|
||||
title={dialogTitle}
|
||||
confirmButtonText={dialogConfirmButtonText}
|
||||
open={dialogOpen}
|
||||
content={dialogContent}
|
||||
open={changeDialogOpen}
|
||||
content={changeDialogContent}
|
||||
loading={loading}
|
||||
handleContentChange={handleDialogContentChange}
|
||||
handleConfirmButtonClick={() => {
|
||||
console.log("go for category mutation");
|
||||
setDialogOpen(false);
|
||||
}}
|
||||
handleClose={() => setDialogOpen(false)}/>
|
||||
handleConfirmButtonClick={handleChangeConfirmButtonClick}
|
||||
handleClose={() => setChangeDialogOpen(false)}
|
||||
/>
|
||||
<DeleteConfirmationDialog
|
||||
content={deleteDialogContent}
|
||||
open={deleteDialogOpen}
|
||||
loading={deleteLoading}
|
||||
handleConfirmButtonClick={handleDeleteConfirmButtonClick}
|
||||
handleClose={() => setDeleteDialogOpen(false)}
|
||||
/>
|
||||
</Paper>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ interface ChangeCategoryDialogProps {
|
|||
confirmButtonText: string,
|
||||
open: boolean,
|
||||
content: ChangeCategoryDialogContent,
|
||||
loading: boolean,
|
||||
|
||||
handleContentChange(content: ChangeCategoryDialogContent): void
|
||||
|
||||
|
@ -42,7 +43,7 @@ export default function ChangeCategoryDialog(props: ChangeCategoryDialogProps) {
|
|||
onCancelButtonClick={props.handleClose}
|
||||
onConfirmButtonClick={props.handleConfirmButtonClick}
|
||||
confirmButtonText={props.confirmButtonText}
|
||||
loading={false}
|
||||
loading={props.loading}
|
||||
/>
|
||||
</Dialog>
|
||||
);
|
||||
|
|
|
@ -183,19 +183,18 @@ export default function QuestionList() {
|
|||
}
|
||||
})
|
||||
};
|
||||
|
||||
return (
|
||||
<Paper className={classes.root}>
|
||||
<Typography component={"h2"} variant="h6" color="primary" gutterBottom>Fragen</Typography>
|
||||
{questions?.map(question => {
|
||||
return <AccordionWithEdit
|
||||
{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
|
||||
|
|
Loading…
Reference in a new issue