add prisma

This commit is contained in:
Janis
2022-12-27 01:57:49 +01:00
parent df3942bcbd
commit ff723b2402
91 changed files with 1323 additions and 1704 deletions

7
.env Normal file
View File

@@ -0,0 +1,7 @@
# Environment variables declared in this file are automatically made available to Prisma.
# See the documentation for more detail: https://pris.ly/d/prisma-schema#accessing-environment-variables-from-the-schema
# Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB.
# See the documentation for all the connection string options: https://pris.ly/d/connection-strings
DATABASE_URL="postgresql://postgres:postgres@localhost:5432/postgres?schema=explainegy"

View File

@@ -1,18 +1,19 @@
import React from "react"; import React from "react";
import { TutorialMeta } from "./page"; import prisma from "../../../lib/prisma";
import styles from "../../../styles/TutorialContentTable.module.scss"; import styles from "../../../styles/TutorialContentTable.module.scss";
import { Article, ContentTableEntry } from "@prisma/client";
export default function ContentTable({ export default function ContentTable({
tutorialMeta, contentTableEntries,
}: { }: {
tutorialMeta: TutorialMeta; contentTableEntries: ContentTableEntry[];
}) { }) {
return ( return (
<div className={styles.tutorialContentTable}> <div className={styles.tutorialContentTable}>
<div className={styles.stickyContainer}> <div className={styles.stickyContainer}>
<div className={styles.list}> <div className={styles.list}>
<h2>Contents</h2> <h2>Contents</h2>
{tutorialMeta?.contentTable?.map((e, i) => { {contentTableEntries?.map((e, i) => {
return ( return (
<a key={i} href={"#" + e.anchor}> <a key={i} href={"#" + e.anchor}>
{e.title} {e.title}
@@ -20,7 +21,7 @@ export default function ContentTable({
); );
})} })}
</div> </div>
{tutorialMeta?.contentTable?.length < 15 ? ( {contentTableEntries?.length < 15 ? (
<div className={styles.adContainer}>Future advertisement</div> <div className={styles.adContainer}>Future advertisement</div>
) : ( ) : (
"" ""

View File

@@ -0,0 +1,17 @@
import { Article } from "@prisma/client";
import { GetArticle } from "./page";
export default async function Head({
params,
}: {
params: { articleName: 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" />
</>
);
}

View File

@@ -0,0 +1,73 @@
import { marked } from "marked";
import ContentTable from "./ContentTable";
import Sidebar from "./Sidebar";
import styles from "../../../styles/Tutorial.module.scss";
import LoadMarkdown from "./LoadMarkdown";
import prisma from "../../../lib/prisma";
import { Article, ContentTableEntry } from "@prisma/client";
export async function GetContentTableEntries(
article: Article
): Promise<ContentTableEntry[]> {
const entries = await prisma.contentTableEntry.findMany({
where: { article: article },
orderBy: { orderIndex: "asc" },
});
return entries;
}
export async function GetArticle(articleName: string) {
const article = await prisma.article.findUnique({
where: { name: articleName.toLowerCase() },
});
return article;
}
function ParseMarkdown(markdown: string): string {
let result = marked.parse(markdown);
return result;
}
//* MAIN
export default async function Tutorial({
params,
}: {
params: { articleName: string };
}) {
const articleName: string = params.articleName;
const article: Article = await GetArticle(articleName);
const markdown: string = article.markdown;
const contentTableEntries: ContentTableEntry[] = await GetContentTableEntries(
article
);
return (
<div className={styles.tutorial}>
<ContentTable contentTableEntries={contentTableEntries} />
<div className={styles.tutorialContent}>
<div className={styles.head}>
<h1>{article.title}</h1>
</div>
<div
className="markdown"
dangerouslySetInnerHTML={{
__html: ParseMarkdown(markdown),
}}
></div>
<LoadMarkdown />
</div>
<Sidebar />
</div>
);
}
export async function generateStaticParams() {
const articles = await prisma.article.findMany();
return articles.map((article) => ({
articleName: article.name ?? "",
}));
}

View File

@@ -1,15 +0,0 @@
import { GetTutorialMeta, TutorialMeta } from "./page";
export default async function Head({
params,
}: {
params: { tutorialId: string };
}) {
const tutorialId: string = params.tutorialId;
const tutorialMeta: TutorialMeta = await GetTutorialMeta(tutorialId);
return (
<>
<title>{tutorialMeta.title}</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
</>
);
}

View File

@@ -1,92 +0,0 @@
import { marked } from "marked";
import { db, storage } from "../../../firebase-config";
import { collection, doc, getDoc, getDocs } from "firebase/firestore";
import { getDownloadURL, ref } from "firebase/storage";
import ContentTable from "./ContentTable";
import Sidebar from "./Sidebar";
import styles from "../../../styles/Tutorial.module.scss";
import LoadMarkdown from "./LoadMarkdown";
import Head from "next/head";
export type ContentTable = {
anchor: string;
title: string;
};
export type TutorialMeta = {
id: string;
title: string;
contentTable: ContentTable[];
};
export async function GetTutorialMeta(
tutorialId: string
): Promise<TutorialMeta> {
const firebaseData = await getDoc(doc(db, "tutorials", tutorialId));
const firebaseJsonData = firebaseData.data();
const tutorial: TutorialMeta = {
id: tutorialId,
title: firebaseJsonData?.title ?? "Tutorial not found!",
contentTable: firebaseJsonData?.contentTable ?? [],
};
return tutorial;
}
async function FetchTutorialMarkdown(tutorialId: string) {
try {
const url = await getDownloadURL(
ref(storage, `markdowns/${tutorialId}.md`)
);
const data = await fetch(url, {
next: { revalidate: 30 * 60 },
});
return await data.text();
} catch {
return "";
}
}
function ParseMarkdown(markdown: string): string {
let result = marked.parse(markdown);
return result;
}
//* MAIN
export default async function Tutorial({
params,
}: {
params: { tutorialId: string };
}) {
const tutorialId: string = params.tutorialId;
const tutorialMeta: TutorialMeta = await GetTutorialMeta(tutorialId);
const markdown: string = await FetchTutorialMarkdown(tutorialId);
return (
<div className={styles.tutorial}>
<ContentTable tutorialMeta={tutorialMeta} />
<div className={styles.tutorialContent}>
<div className={styles.head}>
<h1>{tutorialMeta.title}</h1>
</div>
<div
className="markdown"
dangerouslySetInnerHTML={{
__html: ParseMarkdown(markdown),
}}
></div>
<LoadMarkdown />
</div>
<Sidebar />
</div>
);
}
export async function generateStaticParams() {
const data = await getDocs(collection(db, "tutorials"));
return data.docs.map((doc) => ({
tutorialId: doc.id,
}));
}

View File

@@ -1,7 +1,7 @@
version: "3.9" version: "3.9"
services: services:
postgres: postgres:
image: postgres image: postgres:latest
container_name: explainegy_postgres container_name: explainegy_postgres
volumes: volumes:
- ./docker_data/postgres:/var/lib/postgresql/data - ./docker_data/postgres:/var/lib/postgresql/data
@@ -17,7 +17,7 @@ services:
test: "exit 0" test: "exit 0"
pgadmin: pgadmin:
image: dpage/pgadmin4 image: dpage/pgadmin4:latest
container_name: explainegy_pgadmin container_name: explainegy_pgadmin
restart: always restart: always
environment: environment:
@@ -26,7 +26,7 @@ services:
ports: ports:
- "5050:80" - "5050:80"
volumes: volumes:
- ./docker/servers.json:/pgadmin4/servers.json # preconfigured servers/connections - ./docker_data/servers.json:/pgadmin4/servers.json # preconfigured servers/connections
- ./docker/pgpass:/pgpass # passwords for the connections in this file - ./docker_data/pgpass:/pgpass # passwords for the connections in this file
depends_on: depends_on:
- "postgres" - "postgres"

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,8 +1,8 @@
1 1
/var/lib/postgresql/data /var/lib/postgresql/data
1671907198 1672100396
5432 5432
/var/run/postgresql /var/run/postgresql
* *
699789 5 699789 0
ready ready

View File

@@ -1,8 +1,8 @@
{ {
"Servers": { "Servers": {
"1": { "1": {
"Name": "trading_postgis", "Name": "explainegy_postgres",
"Group": "trading_postgis_group", "Group": "explainegy_postgres_group",
"Host": "host.docker.internal", "Host": "host.docker.internal",
"Port": 5432, "Port": 5432,
"MaintenanceDB": "postgres", "MaintenanceDB": "postgres",

View File

@@ -1,17 +0,0 @@
import { getFirestore } from "@firebase/firestore";
import { getStorage } from "firebase/storage";
import { initializeApp } from "firebase/app";
const firebaseConfig = {
apiKey: "AIzaSyB4U9wobUn7hpqt-gVuNQJPdhfpVdSGPIg",
authDomain: "next-tutorials-7e130.firebaseapp.com",
projectId: "next-tutorials-7e130",
storageBucket: "next-tutorials-7e130.appspot.com",
messagingSenderId: "500863392288",
appId: "1:500863392288:web:4f2f667fef3a571b1d3a45",
};
const app = initializeApp(firebaseConfig);
export const db = getFirestore();
export const storage = getStorage(app);

14
lib/prisma.ts Normal file
View File

@@ -0,0 +1,14 @@
import { PrismaClient } from '@prisma/client';
let prisma: PrismaClient;
if (process.env.NODE_ENV === 'production') {
prisma = new PrismaClient();
} else {
if (!global.prisma) {
global.prisma = new PrismaClient();
}
prisma = global.prisma;
}
export default prisma;

2720
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{ {
"name": "explainegy", "name": "explainegy",
"version": "0.1.0", "version": "0.2.0",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "next dev", "dev": "next dev",
@@ -10,25 +10,31 @@
}, },
"dependencies": { "dependencies": {
"@next/font": "13.0.7", "@next/font": "13.0.7",
"@prisma/client": "^4.8.0",
"@types/marked": "^4.0.8", "@types/marked": "^4.0.8",
"@types/node": "18.11.17", "@types/pg-promise": "^5.4.3",
"@types/react": "18.0.26", "@types/react": "18.0.26",
"@types/react-dom": "18.0.9", "@types/react-dom": "18.0.9",
"encoding": "^0.1.13", "encoding": "^0.1.13",
"eslint": "8.30.0", "eslint": "8.30.0",
"eslint-config-next": "13.0.7", "eslint-config-next": "13.0.7",
"firebase": "^9.15.0",
"marked": "^4.2.4", "marked": "^4.2.4",
"next": "^13.0.8-canary.0", "next": "^13.1.1-canary.1",
"node-html-parser": "^6.1.4", "node-html-parser": "^6.1.4",
"pg": "^8.8.0",
"pg-promise": "^10.15.4",
"prismjs": "^1.29.0", "prismjs": "^1.29.0",
"react": "18.2.0", "react": "18.2.0",
"react-code-blocks": "^0.0.9-0", "react-code-blocks": "^0.0.9-0",
"react-dom": "18.2.0", "react-dom": "18.2.0",
"reflect-metadata": "^0.1.13",
"sass": "^1.57.0", "sass": "^1.57.0",
"typeorm": "^0.3.11",
"typescript": "4.9.4" "typescript": "4.9.4"
}, },
"devDependencies": { "devDependencies": {
"@types/prismjs": "^1.26.0" "@types/node": "^18.11.17",
"@types/prismjs": "^1.26.0",
"prisma": "^4.8.0"
} }
} }

29
prisma/schema.prisma Normal file
View File

@@ -0,0 +1,29 @@
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model Article {
id Int @id @default(autoincrement())
name String @unique
title String @unique
markdown String
contentTableEntries ContentTableEntry[]
dateCreated DateTime @default(now())
dateUpdated DateTime @default(now())
}
model ContentTableEntry {
id Int @id @default(autoincrement())
title String
anchor String
orderIndex Int
articleId Int
article Article @relation(fields: [articleId], references: [id])
dateCreated DateTime @default(now())
dateUpdated DateTime @default(now())
}