feat: tags list.
This commit is contained in:
parent
9490d874a9
commit
c5ca8819e7
@ -230,6 +230,33 @@
|
|||||||
"enumValues": null,
|
"enumValues": null,
|
||||||
"possibleTypes": null
|
"possibleTypes": null
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"kind": "INPUT_OBJECT",
|
||||||
|
"name": "CreateTagInput",
|
||||||
|
"description": null,
|
||||||
|
"fields": null,
|
||||||
|
"inputFields": [
|
||||||
|
{
|
||||||
|
"name": "name",
|
||||||
|
"description": null,
|
||||||
|
"type": {
|
||||||
|
"kind": "NON_NULL",
|
||||||
|
"name": null,
|
||||||
|
"ofType": {
|
||||||
|
"kind": "SCALAR",
|
||||||
|
"name": "String",
|
||||||
|
"ofType": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"defaultValue": null,
|
||||||
|
"isDeprecated": false,
|
||||||
|
"deprecationReason": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"interfaces": null,
|
||||||
|
"enumValues": null,
|
||||||
|
"possibleTypes": null
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"kind": "SCALAR",
|
"kind": "SCALAR",
|
||||||
"name": "DateTime",
|
"name": "DateTime",
|
||||||
@ -370,6 +397,105 @@
|
|||||||
},
|
},
|
||||||
"isDeprecated": false,
|
"isDeprecated": false,
|
||||||
"deprecationReason": null
|
"deprecationReason": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "createTag",
|
||||||
|
"description": null,
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"name": "createTagInput",
|
||||||
|
"description": null,
|
||||||
|
"type": {
|
||||||
|
"kind": "NON_NULL",
|
||||||
|
"name": null,
|
||||||
|
"ofType": {
|
||||||
|
"kind": "INPUT_OBJECT",
|
||||||
|
"name": "CreateTagInput",
|
||||||
|
"ofType": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"defaultValue": null,
|
||||||
|
"isDeprecated": false,
|
||||||
|
"deprecationReason": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": {
|
||||||
|
"kind": "NON_NULL",
|
||||||
|
"name": null,
|
||||||
|
"ofType": {
|
||||||
|
"kind": "OBJECT",
|
||||||
|
"name": "Tag",
|
||||||
|
"ofType": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"isDeprecated": false,
|
||||||
|
"deprecationReason": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "updateTag",
|
||||||
|
"description": null,
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"name": "updateTagInput",
|
||||||
|
"description": null,
|
||||||
|
"type": {
|
||||||
|
"kind": "NON_NULL",
|
||||||
|
"name": null,
|
||||||
|
"ofType": {
|
||||||
|
"kind": "INPUT_OBJECT",
|
||||||
|
"name": "UpdateTagInput",
|
||||||
|
"ofType": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"defaultValue": null,
|
||||||
|
"isDeprecated": false,
|
||||||
|
"deprecationReason": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": {
|
||||||
|
"kind": "NON_NULL",
|
||||||
|
"name": null,
|
||||||
|
"ofType": {
|
||||||
|
"kind": "OBJECT",
|
||||||
|
"name": "Tag",
|
||||||
|
"ofType": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"isDeprecated": false,
|
||||||
|
"deprecationReason": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "removeTag",
|
||||||
|
"description": null,
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"description": null,
|
||||||
|
"type": {
|
||||||
|
"kind": "NON_NULL",
|
||||||
|
"name": null,
|
||||||
|
"ofType": {
|
||||||
|
"kind": "SCALAR",
|
||||||
|
"name": "String",
|
||||||
|
"ofType": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"defaultValue": null,
|
||||||
|
"isDeprecated": false,
|
||||||
|
"deprecationReason": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": {
|
||||||
|
"kind": "NON_NULL",
|
||||||
|
"name": null,
|
||||||
|
"ofType": {
|
||||||
|
"kind": "OBJECT",
|
||||||
|
"name": "Tag",
|
||||||
|
"ofType": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"isDeprecated": false,
|
||||||
|
"deprecationReason": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"inputFields": null,
|
"inputFields": null,
|
||||||
@ -464,6 +590,106 @@
|
|||||||
},
|
},
|
||||||
"isDeprecated": false,
|
"isDeprecated": false,
|
||||||
"deprecationReason": null
|
"deprecationReason": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "tags",
|
||||||
|
"description": null,
|
||||||
|
"args": [],
|
||||||
|
"type": {
|
||||||
|
"kind": "NON_NULL",
|
||||||
|
"name": null,
|
||||||
|
"ofType": {
|
||||||
|
"kind": "LIST",
|
||||||
|
"name": null,
|
||||||
|
"ofType": {
|
||||||
|
"kind": "NON_NULL",
|
||||||
|
"name": null,
|
||||||
|
"ofType": {
|
||||||
|
"kind": "OBJECT",
|
||||||
|
"name": "Tag",
|
||||||
|
"ofType": null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"isDeprecated": false,
|
||||||
|
"deprecationReason": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "tag",
|
||||||
|
"description": null,
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"description": null,
|
||||||
|
"type": {
|
||||||
|
"kind": "NON_NULL",
|
||||||
|
"name": null,
|
||||||
|
"ofType": {
|
||||||
|
"kind": "SCALAR",
|
||||||
|
"name": "String",
|
||||||
|
"ofType": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"defaultValue": null,
|
||||||
|
"isDeprecated": false,
|
||||||
|
"deprecationReason": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": {
|
||||||
|
"kind": "NON_NULL",
|
||||||
|
"name": null,
|
||||||
|
"ofType": {
|
||||||
|
"kind": "OBJECT",
|
||||||
|
"name": "Tag",
|
||||||
|
"ofType": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"isDeprecated": false,
|
||||||
|
"deprecationReason": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"inputFields": null,
|
||||||
|
"interfaces": [],
|
||||||
|
"enumValues": null,
|
||||||
|
"possibleTypes": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "OBJECT",
|
||||||
|
"name": "Tag",
|
||||||
|
"description": null,
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"description": null,
|
||||||
|
"args": [],
|
||||||
|
"type": {
|
||||||
|
"kind": "NON_NULL",
|
||||||
|
"name": null,
|
||||||
|
"ofType": {
|
||||||
|
"kind": "SCALAR",
|
||||||
|
"name": "ID",
|
||||||
|
"ofType": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"isDeprecated": false,
|
||||||
|
"deprecationReason": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "name",
|
||||||
|
"description": null,
|
||||||
|
"args": [],
|
||||||
|
"type": {
|
||||||
|
"kind": "NON_NULL",
|
||||||
|
"name": null,
|
||||||
|
"ofType": {
|
||||||
|
"kind": "SCALAR",
|
||||||
|
"name": "String",
|
||||||
|
"ofType": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"isDeprecated": false,
|
||||||
|
"deprecationReason": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"inputFields": null,
|
"inputFields": null,
|
||||||
@ -554,6 +780,45 @@
|
|||||||
"enumValues": null,
|
"enumValues": null,
|
||||||
"possibleTypes": null
|
"possibleTypes": null
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"kind": "INPUT_OBJECT",
|
||||||
|
"name": "UpdateTagInput",
|
||||||
|
"description": null,
|
||||||
|
"fields": null,
|
||||||
|
"inputFields": [
|
||||||
|
{
|
||||||
|
"name": "name",
|
||||||
|
"description": null,
|
||||||
|
"type": {
|
||||||
|
"kind": "SCALAR",
|
||||||
|
"name": "String",
|
||||||
|
"ofType": null
|
||||||
|
},
|
||||||
|
"defaultValue": null,
|
||||||
|
"isDeprecated": false,
|
||||||
|
"deprecationReason": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"description": null,
|
||||||
|
"type": {
|
||||||
|
"kind": "NON_NULL",
|
||||||
|
"name": null,
|
||||||
|
"ofType": {
|
||||||
|
"kind": "SCALAR",
|
||||||
|
"name": "String",
|
||||||
|
"ofType": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"defaultValue": null,
|
||||||
|
"isDeprecated": false,
|
||||||
|
"deprecationReason": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"interfaces": null,
|
||||||
|
"enumValues": null,
|
||||||
|
"possibleTypes": null
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"kind": "SCALAR",
|
"kind": "SCALAR",
|
||||||
"name": "Boolean",
|
"name": "Boolean",
|
||||||
|
@ -32,6 +32,10 @@ export type CreateArticleInput = {
|
|||||||
tags: Array<Scalars['String']>;
|
tags: Array<Scalars['String']>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type CreateTagInput = {
|
||||||
|
name: Scalars['String'];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
export type Hello = {
|
export type Hello = {
|
||||||
__typename?: 'Hello';
|
__typename?: 'Hello';
|
||||||
@ -43,6 +47,9 @@ export type Mutation = {
|
|||||||
createArticle: Article;
|
createArticle: Article;
|
||||||
updateArticle: Article;
|
updateArticle: Article;
|
||||||
removeArticle: Scalars['Int'];
|
removeArticle: Scalars['Int'];
|
||||||
|
createTag: Tag;
|
||||||
|
updateTag: Tag;
|
||||||
|
removeTag: Tag;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -60,11 +67,28 @@ export type MutationRemoveArticleArgs = {
|
|||||||
id: Scalars['String'];
|
id: Scalars['String'];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type MutationCreateTagArgs = {
|
||||||
|
createTagInput: CreateTagInput;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type MutationUpdateTagArgs = {
|
||||||
|
updateTagInput: UpdateTagInput;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type MutationRemoveTagArgs = {
|
||||||
|
id: Scalars['String'];
|
||||||
|
};
|
||||||
|
|
||||||
export type Query = {
|
export type Query = {
|
||||||
__typename?: 'Query';
|
__typename?: 'Query';
|
||||||
hello: Hello;
|
hello: Hello;
|
||||||
articles: Array<Article>;
|
articles: Array<Article>;
|
||||||
article: Article;
|
article: Article;
|
||||||
|
tags: Array<Tag>;
|
||||||
|
tag: Tag;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -72,6 +96,17 @@ export type QueryArticleArgs = {
|
|||||||
id: Scalars['String'];
|
id: Scalars['String'];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type QueryTagArgs = {
|
||||||
|
id: Scalars['String'];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Tag = {
|
||||||
|
__typename?: 'Tag';
|
||||||
|
id: Scalars['ID'];
|
||||||
|
name: Scalars['String'];
|
||||||
|
};
|
||||||
|
|
||||||
export type UpdateArticleInput = {
|
export type UpdateArticleInput = {
|
||||||
title?: Maybe<Scalars['String']>;
|
title?: Maybe<Scalars['String']>;
|
||||||
content?: Maybe<Scalars['String']>;
|
content?: Maybe<Scalars['String']>;
|
||||||
@ -79,3 +114,8 @@ export type UpdateArticleInput = {
|
|||||||
tags?: Maybe<Array<Scalars['String']>>;
|
tags?: Maybe<Array<Scalars['String']>>;
|
||||||
id: Scalars['String'];
|
id: Scalars['String'];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type UpdateTagInput = {
|
||||||
|
name?: Maybe<Scalars['String']>;
|
||||||
|
id: Scalars['String'];
|
||||||
|
};
|
||||||
|
@ -33,7 +33,7 @@ export default prepareRoutes([
|
|||||||
import(/* webpackChunkName: "article-editor" */ "./articles").then(
|
import(/* webpackChunkName: "article-editor" */ "./articles").then(
|
||||||
(m) => m.ArticleEditor
|
(m) => m.ArticleEditor
|
||||||
),
|
),
|
||||||
client.query<{article: Article}, { id: string }>({
|
client.query<{ article: Article }, { id: string }>({
|
||||||
query: ARTICLE,
|
query: ARTICLE,
|
||||||
variables: { id: matched!.params.id },
|
variables: { id: matched!.params.id },
|
||||||
}),
|
}),
|
||||||
@ -62,8 +62,13 @@ export default prepareRoutes([
|
|||||||
{
|
{
|
||||||
name: "tags",
|
name: "tags",
|
||||||
path: "tags",
|
path: "tags",
|
||||||
respond() {
|
resolve() {
|
||||||
return { body: () => <div>Tags</div> };
|
return import(/* webpackChunkName: "tags" */ "./tags").then(
|
||||||
|
(m) => m.TagsIndex
|
||||||
|
);
|
||||||
|
},
|
||||||
|
respond({ resolved }) {
|
||||||
|
return { body: resolved };
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
201
src/tags/article-editor.tsx
Normal file
201
src/tags/article-editor.tsx
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
import {
|
||||||
|
Button,
|
||||||
|
createStyles,
|
||||||
|
Grid,
|
||||||
|
makeStyles,
|
||||||
|
Paper,
|
||||||
|
} from "@material-ui/core";
|
||||||
|
import { Field, Form, Formik, FormikHelpers } from "formik";
|
||||||
|
import { FC } from "react";
|
||||||
|
import { Editor } from "../commons/editor/vditor";
|
||||||
|
import * as Yup from "yup";
|
||||||
|
import { Article, CreateArticleInput, UpdateArticleInput } from "../generated/graphql";
|
||||||
|
import { DateTimePicker } from "formik-material-ui-pickers";
|
||||||
|
import { gql, useMutation } from "@apollo/client";
|
||||||
|
import { useRouter } from "@curi/react-universal";
|
||||||
|
|
||||||
|
const CREATE_ARTICLE = gql`
|
||||||
|
mutation createArticle($createArticleInput: CreateArticleInput!) {
|
||||||
|
createArticle(createArticleInput: $createArticleInput) {
|
||||||
|
id
|
||||||
|
title
|
||||||
|
content
|
||||||
|
publishedAt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const UPDATE_ARTICLE = gql`
|
||||||
|
mutation updateArticle($updateArticleInput: UpdateArticleInput!) {
|
||||||
|
updateArticle(updateArticleInput: $updateArticleInput) {
|
||||||
|
id
|
||||||
|
title
|
||||||
|
content
|
||||||
|
publishedAt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const useStyles = makeStyles((theme) =>
|
||||||
|
createStyles({
|
||||||
|
form: {
|
||||||
|
padding: "15px 30px",
|
||||||
|
},
|
||||||
|
editor: {
|
||||||
|
height: "700px",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
type Values = CreateArticleInput | UpdateArticleInput;
|
||||||
|
interface Props {
|
||||||
|
article?: Values;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ArticleEditor: FC<Props> = ({ article }) => {
|
||||||
|
const classes = useStyles();
|
||||||
|
|
||||||
|
const validationSchema = Yup.object({
|
||||||
|
content: Yup.string()
|
||||||
|
.max(65535, "文章内容不得超过 65535 个字符")
|
||||||
|
.required("文章内容不得为空"),
|
||||||
|
publishedAt: Yup.date(),
|
||||||
|
});
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
const [createArticle] = useMutation<{createArticle: Article} ,{
|
||||||
|
createArticleInput: CreateArticleInput;
|
||||||
|
}>(CREATE_ARTICLE, {
|
||||||
|
update(cache, { data }) {
|
||||||
|
cache.modify({
|
||||||
|
fields: {
|
||||||
|
articles(existingArticles = []) {
|
||||||
|
const newArticleRef = cache.writeFragment({
|
||||||
|
data: data!.createArticle,
|
||||||
|
fragment: gql`
|
||||||
|
fragment NewArticle on Article {
|
||||||
|
id
|
||||||
|
title
|
||||||
|
content
|
||||||
|
publishedAt
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
});
|
||||||
|
return [newArticleRef, ...existingArticles];
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const [updateArticle] = useMutation<{
|
||||||
|
updateArticleInput: UpdateArticleInput;
|
||||||
|
}>(UPDATE_ARTICLE);
|
||||||
|
|
||||||
|
const SubmitForm = (
|
||||||
|
values: Values,
|
||||||
|
{ setSubmitting }: FormikHelpers<Values>
|
||||||
|
) => {
|
||||||
|
if ("id" in article!) {
|
||||||
|
const title = /# (.+)$/m.exec(values.content ?? "")?.[1];
|
||||||
|
if (!title) {
|
||||||
|
console.log("no title");
|
||||||
|
setSubmitting(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
updateArticle({
|
||||||
|
variables: {
|
||||||
|
updateArticleInput: {
|
||||||
|
...values,
|
||||||
|
title,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
router.navigate({
|
||||||
|
url: router.url({ name: "articles" }),
|
||||||
|
method: "replace",
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
setSubmitting(false);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const title = /# (.+)$/m.exec(values.content ?? "")?.[1];
|
||||||
|
if (!title) {
|
||||||
|
console.log("no title");
|
||||||
|
setSubmitting(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
createArticle({
|
||||||
|
variables: {
|
||||||
|
createArticleInput: {
|
||||||
|
...values as CreateArticleInput,
|
||||||
|
title,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
router.navigate({
|
||||||
|
url: router.url({ name: "articles" }),
|
||||||
|
method: "replace",
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
setSubmitting(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
setSubmitting(false);
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<Paper>
|
||||||
|
<Formik
|
||||||
|
initialValues={article!}
|
||||||
|
validationSchema={validationSchema}
|
||||||
|
autoComplete="off"
|
||||||
|
onSubmit={SubmitForm}
|
||||||
|
>
|
||||||
|
{({ submitForm, isSubmitting }) => (
|
||||||
|
<Form className={classes.form}>
|
||||||
|
<Grid container spacing={3}>
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<Editor
|
||||||
|
className={classes.editor}
|
||||||
|
name="content"
|
||||||
|
label="Content"
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<Field
|
||||||
|
ampm={false}
|
||||||
|
component={DateTimePicker}
|
||||||
|
label="Published At"
|
||||||
|
name="publishedAt"
|
||||||
|
format="yyyy-MM-dd HH:mm:ss"
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
color="primary"
|
||||||
|
disabled={isSubmitting}
|
||||||
|
onClick={submitForm}
|
||||||
|
>
|
||||||
|
Submit
|
||||||
|
</Button>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Form>
|
||||||
|
)}
|
||||||
|
</Formik>
|
||||||
|
</Paper>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
ArticleEditor.defaultProps = {
|
||||||
|
article: {
|
||||||
|
title: "",
|
||||||
|
content: "",
|
||||||
|
publishedAt: new Date(),
|
||||||
|
tags: [],
|
||||||
|
} as CreateArticleInput,
|
||||||
|
};
|
3
src/tags/index.ts
Normal file
3
src/tags/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export * from "./article-editor";
|
||||||
|
export * from "./tags-index";
|
||||||
|
export * from "./tags.constants";
|
80
src/tags/tags-index.tsx
Normal file
80
src/tags/tags-index.tsx
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
import { useMutation, useQuery } from "@apollo/client";
|
||||||
|
import {
|
||||||
|
IconButton,
|
||||||
|
Paper,
|
||||||
|
Table,
|
||||||
|
TableBody,
|
||||||
|
TableCell,
|
||||||
|
TableContainer,
|
||||||
|
TableHead,
|
||||||
|
TableRow,
|
||||||
|
} from "@material-ui/core";
|
||||||
|
import { FC } from "react";
|
||||||
|
import { Tag } from "../generated/graphql";
|
||||||
|
import EditIcon from "@material-ui/icons/Edit";
|
||||||
|
import { useRouter } from "@curi/react-dom";
|
||||||
|
import { Delete } from "@material-ui/icons";
|
||||||
|
import { REMOVE_TAG, TAGS } from "./tags.constants";
|
||||||
|
|
||||||
|
export const TagsIndex: FC = () => {
|
||||||
|
const { data } = useQuery<{
|
||||||
|
tags: Tag[];
|
||||||
|
}>(TAGS, {});
|
||||||
|
|
||||||
|
const [removeArticle] = useMutation<any, { id: string }>(REMOVE_TAG);
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section>
|
||||||
|
<TableContainer component={Paper}>
|
||||||
|
<Table aria-label="articles table">
|
||||||
|
<TableHead>
|
||||||
|
<TableRow>
|
||||||
|
<TableCell>Tag Name</TableCell>
|
||||||
|
<TableCell>Views</TableCell>
|
||||||
|
<TableCell>Articles</TableCell>
|
||||||
|
<TableCell>Actions</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
</TableHead>
|
||||||
|
<TableBody>
|
||||||
|
{data?.tags.map((tag) => (
|
||||||
|
<TableRow key={tag.id}>
|
||||||
|
<TableCell component="th" scope="row">
|
||||||
|
{tag.name}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell align="right"> -- </TableCell>
|
||||||
|
<TableCell align="right"> -- </TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<IconButton
|
||||||
|
aria-label="edit"
|
||||||
|
onClick={() =>
|
||||||
|
router.navigate({
|
||||||
|
url: router.url({
|
||||||
|
name: "modify-tag",
|
||||||
|
params: tag,
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<EditIcon />
|
||||||
|
</IconButton>
|
||||||
|
<IconButton
|
||||||
|
aria-label="delete"
|
||||||
|
onClick={() =>
|
||||||
|
removeArticle({
|
||||||
|
variables: tag,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Delete />
|
||||||
|
</IconButton>
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
))}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</TableContainer>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
16
src/tags/tags.constants.tsx
Normal file
16
src/tags/tags.constants.tsx
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { gql } from "@apollo/client";
|
||||||
|
|
||||||
|
export const TAGS = gql`
|
||||||
|
query Tags {
|
||||||
|
tags {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const REMOVE_TAG = gql`
|
||||||
|
mutation RemoveTag($id: ID!) {
|
||||||
|
removeTag(id: $id)
|
||||||
|
}
|
||||||
|
`;
|
Loading…
Reference in New Issue
Block a user