refactor to pages

This commit is contained in:
Janis
2023-01-29 20:01:56 +01:00
parent 976a11a78f
commit 0997e8fdb8
26 changed files with 2050 additions and 1252 deletions

View File

@@ -1,3 +1,3 @@
export default async function Layout({ children }) {
export default async function AdminArticleEditorLayout({ children }) {
return <div>{children}</div>;
}

View File

@@ -18,7 +18,7 @@ import Markdown from "../../../../../components/Markdown";
type ArticleWithCategory = Prisma.ArticleGetPayload<{ include: { category: true } }>;
export default function ArticleEditor({ params }: { params: { articleId: string } }) {
export default function AdminArticlesEditorPage({ params }: { params: { articleId: string } }) {
const router = useRouter();
const [title, setTitle] = useState<string>("");
const [selectCategoriesOptions, setSelectCategoriesOptions] = useState<any>([]);

View File

@@ -2,7 +2,7 @@
import React from "react";
function AdminArticlesPage() {
export default function AdminArticlesPage() {
return (
<div>
<h1>Page to manage articles</h1>
@@ -11,5 +11,3 @@ function AdminArticlesPage() {
</div>
);
}
export default AdminArticlesPage;

View File

@@ -1,3 +1,3 @@
export default async function Layout({ children }) {
export default async function AdminCategoriesEditorLayout({ children }) {
return <div>{children}</div>;
}

View File

@@ -14,7 +14,7 @@ import { apiUrl } from "../../../../../global";
type CategoryWithSvg = Prisma.CategoryGetPayload<{ include: { svg: true } }>;
export default function CategoryEditor({ params }: { params: { categoryId: string } }) {
export default function AdminCategoriesEditor({ params }: { params: { categoryId: string } }) {
const router = useRouter();
const [title, setTitle] = useState<string>("");
const [color, setColor] = useState<string>("");

View File

@@ -19,6 +19,6 @@ async function getImages(): Promise<GalleryImage[]> {
}));
}
export default async function page() {
export default async function AdminImagesPage() {
return <Gallery images={await getImages()} />;
}

View File

@@ -1,28 +0,0 @@
import React from "react";
import styles from "../../../../styles/modules/Sidebar.module.scss";
export default function Sidebar() {
return (
<div className={styles.sidebar}>
<div className={styles.stickyContainer}>
<div className={styles.sidebarContainer}>
<h3>Popular</h3>
<a href="#"> Set up Docker</a>
<a href="#"> Set up Docker</a>
<a href="#"> Set up Docker</a>
<a href="#"> Set up Docker</a>
<a href="#"> Set up Docker</a>
</div>
<div className={styles.sidebarContainer}>
<h3>Related</h3>
<a href="#"> Set up Docker</a>
<a href="#"> Set up Docker</a>
<a href="#"> Set up Docker</a>
<a href="#"> Set up Docker</a>
<a href="#"> Set up Docker</a>
</div>
<div className={styles.adContainer}>Future advertisement</div>
</div>
</div>
);
}

View File

@@ -1,17 +1,13 @@
import { Article } from "@prisma/client";
import { GetArticle } from "./page";
import { FetchManager } from "../../../../manager/fetchManager";
export default async function Head({
params,
}: {
params: { articleName: string; categoryName: string };
}) {
const articleName: string = params.articleName;
const article: Article = await GetArticle(articleName);
return (
<>
<title>{article?.title}</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
</>
);
export default async function ArticleHead({ params }: { params: { articleName: string; categoryName: string } }) {
const articleName: string = params.articleName;
const article: Article = await FetchManager.Article.getByName(articleName);
return (
<>
<title>{article?.title}</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
</>
);
}

View File

@@ -1,3 +1,3 @@
export default function Layout({ children }) {
export default function ArticleLayout({ children }) {
return <div>{children}</div>;
}

View File

@@ -1,31 +1,15 @@
import { marked } from "marked";
import ContentTable from "./ContentTable";
import Sidebar from "./Sidebar";
import ContentTable from "../../../../components/ContentTable";
import Sidebar from "../../../../components/Sidebar";
import styles from "../../../../styles/modules/Article.module.scss";
import Image from "next/image";
import urlJoin from "url-join";
import { apiUrl } from "../../../../global";
import { Prisma } from "@prisma/client";
import Markdown from "../../../../components/Markdown";
import { IContentTableEntry } from "../../../../types/contentTable";
type ArticleWithIncludes = Prisma.ArticleGetPayload<{
include: { category: true; image: true };
}>;
export async function GetArticle(articleName: string): Promise<any> {
const result: Response = await fetch(urlJoin(apiUrl, `articles/name/${articleName ?? ""}`), {
cache: "force-cache",
next: { revalidate: 60 * 10 },
});
return result.json();
}
import { ArticleWithIncludes, FetchManager } from "../../../../manager/fetchManager";
import { formatTextToUrlName } from "../../../../utils";
//* MAIN
export default async function ArticlePage({ params }: { params: { articleName: string; categoryName: string } }) {
const articleName: string = params.articleName.toLowerCase().replaceAll("%20", " ");
const article: ArticleWithIncludes = await GetArticle(articleName);
const articleName: string = formatTextToUrlName(params.articleName);
const article: ArticleWithIncludes = await FetchManager.Article.getByName(articleName);
const dateUpdated: Date = new Date(article.dateUpdated);
const dateCreated: Date = new Date(article.dateCreated);
@@ -60,14 +44,6 @@ export default async function ArticlePage({ params }: { params: { articleName: s
<p>{article?.introduction}</p>
</div>
<Markdown value={markdown} />
{/* <div
className="markdown"
dangerouslySetInnerHTML={{
__html: ParseMarkdown(markdown),
}}
></div>
<LoadMarkdown /> */}
</div>
<Sidebar />
</div>
@@ -75,12 +51,8 @@ export default async function ArticlePage({ params }: { params: { articleName: s
}
export async function generateStaticParams() {
const articles: ArticleWithIncludes[] = await (
await fetch(urlJoin(apiUrl, `articles/`), {
cache: "no-cache",
next: { revalidate: 60 * 10 },
})
).json();
// Fetchmanager does not work here
const articles: ArticleWithIncludes[] = await FetchManager.Article.list(false);
return await Promise.all(
articles.map(async (article) => ({

View File

@@ -1,22 +1,10 @@
import styles from "../../styles/modules/CategoryList.module.scss";
import Link from "next/link";
import { Category, Svg, Prisma } from "@prisma/client";
import urlJoin from "url-join";
import { apiUrl } from "../../global";
type CategoryWithSvg = Prisma.CategoryGetPayload<{ include: { svg: true } }>;
export async function GetCategories(): Promise<any> {
const result: Response = await fetch(urlJoin(apiUrl, `categories`), {
cache: "force-cache",
next: { revalidate: 3600 },
});
return result.json();
}
import { FetchManager } from "../../manager/fetchManager";
export default async function CategoryList() {
const categories = await GetCategories();
const categories = await FetchManager.Category.list();
return (
<div className={styles.categoryList}>
<h1>Overview</h1>

View File

@@ -1,7 +1,7 @@
export default async function Head() {
return (
<>
<meta name="viewport" content="width=device-width, initial-scale=1" />
</>
);
export default async function RootHead() {
return (
<>
<meta name="viewport" content="width=device-width, initial-scale=1" />
</>
);
}

View File

@@ -1,21 +1,10 @@
import "../styles/globals.scss";
import "../styles/variables_colors.scss";
import "../styles/variables.scss";
import { Category } from "@prisma/client";
import urlJoin from "url-join";
import { apiUrl } from "../global";
import Link from "next/link";
import Footer from "../components/Footer";
import Nav from "../components/Nav";
async function getCategories(): Promise<Category[]> {
const result: Response = await fetch(urlJoin(apiUrl, `categories`), {
cache: "no-cache",
next: { revalidate: 3600 },
});
return await result.json();
}
import { FetchManager } from "../manager/fetchManager";
export default async function RootLayout({ children }: { children: React.ReactNode }) {
return (
@@ -27,7 +16,7 @@ export default async function RootLayout({ children }: { children: React.ReactNo
<Link href={"/admin"}> Admin</Link>
</div>
<header>
<Nav categories={await getCategories()} />
<Nav categories={await FetchManager.Category.list()} />
</header>
<main>{children}</main>
<Footer />

View File

@@ -1,3 +1,3 @@
export default function Home() {
return <h1>Home</h1>;
export default function HomePage() {
return <h1>Home</h1>;
}

View File

@@ -1,23 +1,21 @@
import React from "react";
export default function Typograhy() {
return (
<div>
<h1>Testing this headline</h1>
<h2>Testing this headline</h2>
<h3>Testing this headline</h3>
<h4>Testing this headline</h4>
<h5>Testing this headline</h5>
<h6>Testing this headline</h6>
<br />
<p>
This is a paragraph Lorem ipsum dolor sit, amet consectetur adipisicing
elit. Dolores enim unde obcaecati ea harum voluptate, nisi quia. Quod,
et autem! Aperiam mollitia ullam ab eaque quidem facilis est ducimus
delectus.
</p>
<br />
<a href="#">This is a link</a>
</div>
);
export default function TypograhyPage() {
return (
<div>
<h1>Testing this headline</h1>
<h2>Testing this headline</h2>
<h3>Testing this headline</h3>
<h4>Testing this headline</h4>
<h5>Testing this headline</h5>
<h6>Testing this headline</h6>
<br />
<p>
This is a paragraph Lorem ipsum dolor sit, amet consectetur adipisicing elit. Dolores enim unde obcaecati ea
harum voluptate, nisi quia. Quod, et autem! Aperiam mollitia ullam ab eaque quidem facilis est ducimus delectus.
</p>
<br />
<a href="#">This is a link</a>
</div>
);
}

View File

@@ -1,7 +1,5 @@
import React from "react";
import styles from "../../../../styles/modules/ArticleContentTable.module.scss";
import { Article } from "@prisma/client";
import { IContentTableEntry } from "../../../../types/contentTable";
import styles from "../styles/modules/ArticleContentTable.module.scss";
export default function ContentTable({ contentTableData }: { contentTableData: any }) {
return (

View File

@@ -8,10 +8,9 @@ import styles from "../styles/modules/markdown.module.scss";
import remarkGfm from "remark-gfm";
import remarkGemoji from "remark-gemoji";
import remarkStringify from "remark-stringify";
import { useState, useEffect } from "react";
import { useLocalStorage } from "usehooks-ts";
import React from "react";
import Head from "../app/head";
import { formatTextToUrlName } from "../utils";
function flatten(text, child) {
@@ -31,6 +30,7 @@ export default function Markdown({ value }: { value: any }) {
className={styles.markdown}
//@ts-ignore
remarkPlugins={[remarkGfm, remarkGemoji, remarkStringify]}
//@ts-ignore
components={{
h1: HeadingRenderer,
h2: HeadingRenderer,

28
components/Sidebar.tsx Normal file
View File

@@ -0,0 +1,28 @@
import React from "react";
import styles from "../styles/modules/Sidebar.module.scss";
export default function Sidebar() {
return (
<div className={styles.sidebar}>
<div className={styles.stickyContainer}>
<div className={styles.sidebarContainer}>
<h3>Popular</h3>
<a href="#"> Set up Docker</a>
<a href="#"> Set up Docker</a>
<a href="#"> Set up Docker</a>
<a href="#"> Set up Docker</a>
<a href="#"> Set up Docker</a>
</div>
<div className={styles.sidebarContainer}>
<h3>Related</h3>
<a href="#"> Set up Docker</a>
<a href="#"> Set up Docker</a>
<a href="#"> Set up Docker</a>
<a href="#"> Set up Docker</a>
<a href="#"> Set up Docker</a>
</div>
<div className={styles.adContainer}>Future advertisement</div>
</div>
</div>
);
}

77
manager/fetchManager.ts Normal file
View File

@@ -0,0 +1,77 @@
import { Article, Category } from '@prisma/client';
import { Prisma } from "@prisma/client";
import urlJoin from "url-join";
import { apiUrl } from "../global";
const GLOBAL_NO_CACHE: boolean = true;
export type ArticleWithIncludes = Prisma.ArticleGetPayload<{ include: { category: true, image: true } }>
export type CategoryWithIncludes = Prisma.CategoryGetPayload<{ include: { svg: true } }>
export interface FetchError {
code: number;
message?: string;
data?: any;
}
export class FetchManager {
static Article = class {
static async list(noCache: boolean = false): Promise<ArticleWithIncludes[]> {
const response = await fetch(urlJoin(apiUrl, `articles`), {
cache: GLOBAL_NO_CACHE || noCache ? "no-cache" : "force-cache",
next: { revalidate: 60 * 10 },
})
return await response.json()
}
static async get(id: string, noCache: boolean = false): Promise<ArticleWithIncludes> {
const response = await fetch(urlJoin(apiUrl, `articles/${id}`), {
cache: GLOBAL_NO_CACHE || noCache ? "no-cache" : "force-cache",
next: { revalidate: 60 * 10 },
})
return await response.json()
}
static async getByName(name: string, noCache: boolean = false): Promise<ArticleWithIncludes> {
const response = await fetch(urlJoin(apiUrl, `articles/name/${name}`), {
cache: GLOBAL_NO_CACHE || noCache ? "no-cache" : "force-cache",
next: { revalidate: 60 * 10 },
})
return await response.json()
}
}
static Category = class {
static async list(noCache: boolean = false): Promise<CategoryWithIncludes[]> {
const response = await fetch(urlJoin(apiUrl, `categories`), {
cache: GLOBAL_NO_CACHE || noCache ? "no-cache" : "force-cache",
next: { revalidate: 60 * 10 },
})
return await response.json()
}
static async get(id: string, noCache: boolean = false): Promise<CategoryWithIncludes> {
const response = await fetch(urlJoin(apiUrl, `categories/${id}`), {
cache: GLOBAL_NO_CACHE || noCache ? "no-cache" : "force-cache",
next: { revalidate: 60 * 10 },
})
return await response.json()
}
static async getByName(name: string, noCache: boolean = false): Promise<CategoryWithIncludes> {
const response = await fetch(urlJoin(apiUrl, `categories/name/${name}`), {
cache: GLOBAL_NO_CACHE || noCache ? "no-cache" : "force-cache",
next: { revalidate: 60 * 10 },
})
return await response.json()
}
}
}

View File

@@ -1,26 +1,8 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
experimental: {
appDir: true,
},
typescript: {
// !! WARN !!
// Dangerously allow production builds to successfully complete even if your project has type errors.
ignoreBuildErrors: true,
},
images: {
remotePatterns: [
{
protocol: "https",
hostname: "c2.staticflickr.com",
},
{
protocol: "https",
hostname: "c4.staticflickr.com",
},
],
},
};
module.exports = nextConfig;

2962
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -5,7 +5,7 @@
"scripts": {
"prisma": "prisma generate && prisma db push && prisma studio",
"dev": "next dev",
"build": "prisma generate && prisma migrate deploy && next build",
"build": "next build",
"start": "next start",
"lint": "next lint",
"vercel-build": "prisma generate && prisma db push && next build",
@@ -23,7 +23,6 @@
"eslint-config-next": "13.0.7",
"marked": "^4.2.4",
"next": "^13.1.6",
"next-gallery": "^1.1.0",
"prismjs": "^1.29.0",
"react": "18.2.0",
"react-code-blocks": "^0.0.9-0",
@@ -41,8 +40,7 @@
"remark-stringify": "^10.0.2",
"sass": "^1.57.0",
"typescript": "4.9.4",
"url-join": "^5.0.0",
"usehooks-ts": "^2.9.1"
"url-join": "^5.0.0"
},
"devDependencies": {
"@fec/remark-a11y-emoji": "^3.1.0",

View File

@@ -1,6 +1,8 @@
import { Request, Response } from "express";
import prisma from "../../../lib/prisma";
//@ts-ignore
import { Prisma } from "@prisma/client";
//@ts-ignore
import { Article, Category } from "@prisma/client";
import { ResponseError } from "../../../types/responseErrors";
import { formatTextToUrlName } from "../../../utils";
@@ -111,9 +113,11 @@ export default async function handler(req: Request, res: Response) {
title: data.title,
name: formatTextToUrlName(data.title),
introduction: data.introduction,
//@ts-ignore
categoryId: data.categoryId,
contentTable: data.contentTable,
markdown: data.markdown,
//@ts-ignore
imageId: data.imageId,
}

View File