#11 Implement edit question

This commit is contained in:
Christoph Lienhard 2020-12-29 00:33:27 +01:00
parent b6358c357b
commit 96e78eb7f5
Signed by: christoph.lienhard
GPG key ID: 6B98870DDC270884
7 changed files with 76 additions and 22 deletions

View file

@ -1,4 +1,4 @@
import {ApolloClient, createHttpLink, InMemoryCache} from "@apollo/client";
import {ApolloClient, createHttpLink, defaultDataIdFromObject, InMemoryCache} from "@apollo/client";
import {setContext} from "@apollo/client/link/context";
@ -17,6 +17,12 @@ const authLink = setContext((_, { headers }) => {
});
export const client = new ApolloClient({
cache: new InMemoryCache(),
cache: new InMemoryCache({
dataIdFromObject(responseObject) {
return responseObject.nodeId
? responseObject.nodeId as string
: defaultDataIdFromObject(responseObject);
}
}),
link: authLink.concat(httpLink),
});

View file

@ -10,6 +10,7 @@ export const EDIT_QUESTION = gql`
description
categoryByCategoryId {
nodeId
id
title
}
}
@ -21,7 +22,9 @@ export interface EditQuestionVariables {
nodeId: string,
text?: string,
description?: string,
categoryId?: number,
categoryId?: number | null,
}
export interface EditQuestionResponse extends GetQuestionResponse {}
export interface EditQuestionResponse {
updateQuestion?: GetQuestionResponse
}

View file

@ -4,15 +4,15 @@ import {GetCategoryResponse} from "../backend/queries/category";
interface CategorySelectionMenuProps {
selectedCategoryId?: string
selectedCategoryId: number | null
categories?: Array<GetCategoryResponse>,
handleCategoryChange(categoryId: string): void
handleCategoryChange(categoryId: number | null): void
}
export default function CategorySelectionMenu(props: CategorySelectionMenuProps) {
const onCategoryIdChange = (e: ChangeEvent<{ name?: string, value: unknown }>) => {
const newValue = e.target.value as string;
const newValue = e.target.value === undefined ? null : e.target.value as number;
props.handleCategoryChange(newValue);
}
@ -20,14 +20,14 @@ export default function CategorySelectionMenu(props: CategorySelectionMenuProps)
<FormControl fullWidth variant="outlined">
<InputLabel>Kategorie</InputLabel>
<Select
value={props.selectedCategoryId ? props.selectedCategoryId : ""}
value={props.selectedCategoryId ? props.selectedCategoryId : undefined}
label="Kategorie"
onChange={onCategoryIdChange}
>
<MenuItem value={""}>
<MenuItem value={undefined}>
<em>None</em>
</MenuItem>
{props.categories?.map(category => <MenuItem key={category.nodeId} value={category.nodeId}>
{props.categories?.map(category => <MenuItem key={category.nodeId} value={category.id}>
{category.title}
</MenuItem>)}
</Select>

View file

@ -42,6 +42,7 @@ export default function ChangeCategoryDialog(props: ChangeCategoryDialogProps) {
onCancelButtonClick={props.handleClose}
onConfirmButtonClick={props.handleConfirmButtonClick}
confirmButtonText={props.confirmButtonText}
loading={false}
/>
</Dialog>
);

View file

@ -12,7 +12,7 @@ export interface ChangeQuestionDialogContent {
id: string
title: string,
details?: string,
categoryId?: string,
categoryId: number | null,
}
interface ChangeQuestionDialogProps {
@ -20,6 +20,7 @@ interface ChangeQuestionDialogProps {
confirmButtonText: string,
open: boolean,
content: ChangeQuestionDialogContent,
loading: boolean,
categories?: Array<GetCategoryResponse>,
handleContentChange(content: ChangeQuestionDialogContent): void
@ -51,6 +52,7 @@ export default function ChangeQuestionDialog(props: ChangeQuestionDialogProps) {
/>
</DialogContent>
<DialogActionBar
loading={props.loading}
onCancelButtonClick={props.handleClose}
onConfirmButtonClick={props.handleConfirmButtonClick}
confirmButtonText={props.confirmButtonText}

View file

@ -1,9 +1,11 @@
import DialogActions from "@material-ui/core/DialogActions";
import Button from "@material-ui/core/Button";
import React from "react";
import ButtonWithSpinner from "./ButtonWithSpinner";
interface DialogActionBarProps {
confirmButtonText?: string,
loading: boolean,
onCancelButtonClick?(): void,
@ -15,8 +17,8 @@ export function DialogActionBar(props: DialogActionBarProps) {
<Button onClick={props.onCancelButtonClick} color="primary">
Abbrechen
</Button>
<Button onClick={props.onConfirmButtonClick} color="primary">
<ButtonWithSpinner loading={props.loading} handleClick={props.onConfirmButtonClick} >
{props.confirmButtonText ? props.confirmButtonText : "Ok"}
</Button>
</ButtonWithSpinner>
</DialogActions>;
}

View file

@ -1,12 +1,14 @@
import {Paper, Typography} from "@material-ui/core";
import {Paper, Snackbar, Typography} from "@material-ui/core";
import React, {useState} from "react";
import {makeStyles} from "@material-ui/core/styles";
import {useQuery} from "@apollo/client";
import {useMutation, useQuery} from "@apollo/client";
import AddCard from "./AddCard";
import AccordionWithEdit from "./AccordionWithEdit";
import {GET_ALL_QUESTIONS, GetAllQuestionsResponse, GetQuestionResponse} from "../backend/queries/question";
import ChangeQuestionDialog, {ChangeQuestionDialogContent} from "./ChangeQuestionDialog";
import {GET_ALL_CATEGORIES, GetAllCategoriesResponse} from "../backend/queries/category";
import {EDIT_QUESTION, EditQuestionResponse, EditQuestionVariables} from "../backend/mutations/question";
import {Alert, Color} from "@material-ui/lab";
const useStyles = makeStyles((theme) => ({
root: {
@ -20,7 +22,13 @@ const emptyChangeQuestionDialog: ChangeQuestionDialogContent = {
id: "",
title: "",
details: "",
categoryId: "",
categoryId: null,
}
interface SnackbarProps {
open: boolean,
message?: string,
severity?: Color,
}
export default function QuestionList() {
@ -28,9 +36,11 @@ export default function QuestionList() {
const [dialogTitle, setDialogTitle] = useState("");
const [dialogConfirmButtonText, setDialogConfirmButtonText] = useState("");
const [dialogContent, setDialogContent] = useState(emptyChangeQuestionDialog);
const [snackbarProps, setSnackbarProps] = useState<SnackbarProps>({open: false});
const questions = useQuery<GetAllQuestionsResponse, null>(GET_ALL_QUESTIONS).data?.allQuestions.nodes;
const categories = useQuery<GetAllCategoriesResponse, null>(GET_ALL_CATEGORIES).data?.allCategories.nodes;
const classes = useStyles();
const [editQuestion, {loading}] = useMutation<EditQuestionResponse, EditQuestionVariables>(EDIT_QUESTION);
const handleAddClick = () => {
setDialogTitle("Neue Frage erstellen");
@ -49,7 +59,7 @@ export default function QuestionList() {
id: question.nodeId,
title: question.text,
details: question.description,
categoryId: question.categoryByCategoryId?.nodeId,
categoryId: question.categoryByCategoryId ? question.categoryByCategoryId.id : null,
})
}
setDialogOpen(true);
@ -59,6 +69,29 @@ export default function QuestionList() {
setDialogContent(content)
}
const handleConfirmButtonClick = async () => {
if (dialogContent.id !== "") {
const response = await editQuestion({
variables: {
nodeId: dialogContent.id,
text: dialogContent.title,
description: dialogContent.details,
categoryId: dialogContent.categoryId
}
})
if (response.data?.updateQuestion) {
setSnackbarProps({
message: "Frage erfolgreich geändert",
open: true,
severity: 'success',
})
setDialogOpen(false);
}
}
};
const handleSnackbarClose = () => setSnackbarProps({...snackbarProps, open: false})
return (
<Paper className={classes.root}>
<Typography component={"h2"} variant="h6" color="primary" gutterBottom>Fragen</Typography>
@ -79,12 +112,19 @@ export default function QuestionList() {
open={dialogOpen}
content={dialogContent}
categories={categories}
loading={loading}
handleContentChange={handleDialogContentChange}
handleConfirmButtonClick={() => {
console.log("go for question mutation");
setDialogOpen(false);
}}
handleClose={() => setDialogOpen(false)}/>
handleConfirmButtonClick={handleConfirmButtonClick}
handleClose={() => setDialogOpen(false)}
/>
<Snackbar
anchorOrigin={{vertical: 'bottom', horizontal: "right"}}
open={snackbarProps.open}
onClose={handleSnackbarClose}
autoHideDuration={6000}
>
<Alert onClose={handleSnackbarClose} severity={snackbarProps.severity}>{snackbarProps.message}</Alert>
</Snackbar>
</Paper>
)
}