From 92ec33fea443ee47f0805e70d6bcbcf97c0f2353 Mon Sep 17 00:00:00 2001 From: Janis Date: Sun, 22 Jan 2023 21:22:48 +0100 Subject: [PATCH] asd --- .vscode/settings.json | 2 +- .../{create => editor/[articleId]}/layout.tsx | 0 .../{create => editor/[articleId]}/page.tsx | 153 ++++++++++++----- .../[categoryName]/[articleName]/page.tsx | 2 +- docker_data/servers.json | 24 +-- pages/api/articles/[articleId].ts | 38 +++++ pages/api/articles/create.tsx | 48 ------ pages/api/articles/index.ts | 155 ++++++++++++++---- .../api/articles/{ => name}/[articleName].ts | 7 +- prisma/schema.prisma | 2 +- ....module.scss => ArticleEditor.module.scss} | 6 +- types/api.ts | 21 +++ types/postData.ts | 11 -- 13 files changed, 319 insertions(+), 150 deletions(-) rename app/admin/articles/{create => editor/[articleId]}/layout.tsx (100%) rename app/admin/articles/{create => editor/[articleId]}/page.tsx (60%) create mode 100644 pages/api/articles/[articleId].ts delete mode 100644 pages/api/articles/create.tsx rename pages/api/articles/{ => name}/[articleName].ts (85%) rename styles/modules/{AdminArticlesCreate.module.scss => ArticleEditor.module.scss} (91%) create mode 100644 types/api.ts delete mode 100644 types/postData.ts diff --git a/.vscode/settings.json b/.vscode/settings.json index bd3337f..1bd4de1 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,4 @@ { "typescript.tsdk": "node_modules\\typescript\\lib", "typescript.enablePromptUseWorkspaceTsdk": true -} \ No newline at end of file +} diff --git a/app/admin/articles/create/layout.tsx b/app/admin/articles/editor/[articleId]/layout.tsx similarity index 100% rename from app/admin/articles/create/layout.tsx rename to app/admin/articles/editor/[articleId]/layout.tsx diff --git a/app/admin/articles/create/page.tsx b/app/admin/articles/editor/[articleId]/page.tsx similarity index 60% rename from app/admin/articles/create/page.tsx rename to app/admin/articles/editor/[articleId]/page.tsx index 8e98100..963efcf 100644 --- a/app/admin/articles/create/page.tsx +++ b/app/admin/articles/editor/[articleId]/page.tsx @@ -1,33 +1,30 @@ "use client"; import React from "react"; - import { useState, useRef, useEffect } from "react"; -import styles from "../../../../styles/modules/AdminArticlesCreate.module.scss"; -import { PostArticle } from "../../../../types/postData"; -import Markdown from "../../../Markdown"; -import { Article, Category, Prisma } from "@prisma/client"; -import "../../../../styles/inputs.scss"; -import "../../../../styles/buttons.scss"; -import Select, { GroupBase, OptionsOrGroups } from "react-select"; -import { apiUrl } from "../../../global"; -import urlJoin from "url-join"; -import { formatTextToUrlName } from "../../../../utils"; -import { isValidText } from "../../../../validators"; +import styles from "../../../../../styles/modules/ArticleEditor.module.scss"; +import { Prisma } from "@prisma/client"; +import "../../../../../styles/inputs.scss"; +import "../../../../../styles/buttons.scss"; +import Select from "react-select"; import { useRouter } from "next/navigation"; -import ContentTable from "../../../articles/[categoryName]/[articleName]/ContentTable"; -import { IContentTableEntry } from "../../../../types/contentTable"; +import urlJoin from "url-join"; +import { IContentTableEntry } from "../../../../../types/contentTable"; +import { CreateArticle, UpdateArticle } from "../../../../../types/api"; +import { formatTextToUrlName } from "../../../../../utils"; +import { isValidText } from "../../../../../validators"; +import { apiUrl } from "../../../../global"; +import Markdown from "../../../../Markdown"; type ArticleWithCategory = Prisma.ArticleGetPayload<{ include: { category: true } }>; -export default function AdminArticlesCreate() { +export default function ArticleEditor({ params }: { params: { articleId: string } }) { const router = useRouter(); - const [title, setTitle] = useState(""); const [selectCategoriesOptions, setSelectCategoriesOptions] = useState([]); const [introduction, setIntroduction] = useState(""); const [markdown, setMarkdown] = useState(""); - const [contentTable, setContentTable] = useState([]); + const [contentTable, setContentTable] = useState([]); const titleRef = useRef(null); const categorySelectRef = useRef(null); @@ -52,40 +49,102 @@ export default function AdminArticlesCreate() { }); } + function removeEntry(index: number) { + let newArray = [...contentTable]; + newArray.splice(index, 1); + setContentTable(newArray); + } + function handleFormChange() { setMarkdown(markdownTextAreaRef.current.value); setTitle(titleRef.current.value); setIntroduction(introductionRef.current.value); } - async function postData() { - const formData: PostArticle = { + // Create or update article + async function handleResponse(res: Response) { + const json = await res.json(); + errorTextRef.current.innerText = json.error ?? ""; + if (json.success) { + const newArticle: ArticleWithCategory = json.data; + router.push(urlJoin(`/articles/`, newArticle.category.name, newArticle.name)); + } + } + + async function updateArticle() { + console.log("Update article"); + const payload: UpdateArticle = { + id: params.articleId, title: titleRef.current.value, introduction: introductionRef.current.value, markdown: markdown, categoryId: Number(categorySelectRef?.current?.getValue()[0]?.value), contentTable: contentTable, }; - console.log(formData); - const result = await fetch("/api/articles/create", { + console.log(payload); + + await fetch("/api/articles/", { + method: "PUT", + headers: { + Accept: "application/json", + "Content-Type": "application/json", + }, + cache: "no-cache", + body: JSON.stringify(payload), + }) + .then(handleResponse) + .catch(console.error); + } + + async function createArticle() { + console.log("Create article"); + const payload: CreateArticle = { + title: titleRef.current.value, + introduction: introductionRef.current.value, + markdown: markdown, + categoryId: Number(categorySelectRef?.current?.getValue()[0]?.value), + contentTable: contentTable, + }; + console.log(payload); + + await fetch("/api/articles/", { method: "POST", headers: { Accept: "application/json", "Content-Type": "application/json", }, - body: JSON.stringify(formData), - }); - - const response = await result.json(); - console.log(response); - errorTextRef.current.innerText = response.error ?? ""; - if (response.success) { - const newArticle: ArticleWithCategory = response.data; - router.push(urlJoin(`/articles/`, newArticle.category.name, newArticle.name)); - } + cache: "no-cache", + body: JSON.stringify(payload), + }) + .then(handleResponse) + .catch(console.error); } + // App useEffect(() => { + const fetchExistingArticle = async () => { + const result: Response = await fetch(urlJoin(apiUrl, `articles/${params.articleId}`), { + cache: "no-cache", + next: { revalidate: 60 * 1 }, + }); + + const article = await result.json(); + console.log(article); + if (article.code == "404") { + router.push(urlJoin(`/admin/articles/editor/0`)); + } else { + titleRef.current.value = article.title; + introductionRef.current.value = article.introduction; + markdownTextAreaRef.current.value = article.markdown; + categorySelectRef.current.setValue({ value: article.category.id, label: article.category.title }); + + setTitle(article.title); + setIntroduction(article.introduction); + setMarkdown(article.markdown); + setContentTable(article.contentTable); + } + }; + const fetchCategoryOptions = async () => { const result: Response = await fetch(urlJoin(apiUrl, `categories`), { cache: "no-cache", @@ -100,23 +159,34 @@ export default function AdminArticlesCreate() { }); setSelectCategoriesOptions(newSelectCategoriesOptions); }; + fetchCategoryOptions().catch((err) => { console.log(err); }); + + if (params.articleId != "0") { + fetchExistingArticle().catch((err) => { + console.log(err); + }); + } }, []); return (
-

Create a new article

+

{params.articleId == "0" ? "Create new article" : "Update article"}

@@ -177,7 +247,7 @@ export default function AdminArticlesCreate() {
- {contentTable.map((entry: IContentTableEntry, i: number) => { + {contentTable?.map((entry: IContentTableEntry, i: number) => { return (
{ @@ -193,14 +264,22 @@ export default function AdminArticlesCreate() { }} type="text" placeholder={"Title"} - /> + defaultValue={entry.title} + />{" "} +
); })}