mirror of
https://github.com/OHTU-German-learning-website/OHTU-German-learning-website.git
synced 2026-10-12 19:13:51 +03:00
Merge branch '384-migrate-communications-texts-to-db' into 416-fix-conflicts-with-new-code-and-older-tests
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
|
||||
CREATE TABLE communications_pages_html (
|
||||
id SERIAL PRIMARY KEY,
|
||||
content TEXT NOT NULL
|
||||
);
|
||||
+64
-203
@@ -1,113 +1,5 @@
|
||||
import Link from "next/link";
|
||||
import Image from "next/image";
|
||||
import { Container, Column } from "@/components/ui/layout/container";
|
||||
import { GlossaryParagraph } from "@/components/ui/glossary/GlossaryText";
|
||||
import "../../themes/lessons.css";
|
||||
|
||||
export const chapters = [
|
||||
{
|
||||
id: "1",
|
||||
title: "1. Über Vergangenes sprechen",
|
||||
content: Chapter1,
|
||||
link: "/grammar/communications/1",
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
title: "2. Anleitungen formulieren",
|
||||
content: Chapter2,
|
||||
link: "/grammar/communications/2",
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
title: "3. Offizielle Mitteilungen (Nachrichten usw.) formulieren",
|
||||
content: Chapter3,
|
||||
link: "/grammar/communications/3",
|
||||
},
|
||||
{
|
||||
id: "4",
|
||||
title:
|
||||
"4. Höflich mit anderen Menschen umgehen (Sich vorstellen, Gäste empfangen und betreuen, Small Talk)",
|
||||
content: Chapter4,
|
||||
link: "/grammar/communications/4",
|
||||
},
|
||||
{
|
||||
id: "5",
|
||||
title: "5. Menschen beschreiben / Ich und meine Familie",
|
||||
content: Chapter5,
|
||||
link: "/grammar/communications/5",
|
||||
},
|
||||
{
|
||||
id: "6",
|
||||
title: "6. Über Hobbys und Freizeit sprechen",
|
||||
content: Chapter6,
|
||||
link: "/grammar/communications/6",
|
||||
},
|
||||
{
|
||||
id: "7",
|
||||
title: "7. Über Beruf und Arbeitsplatz sprechen",
|
||||
content: Chapter7,
|
||||
link: "/grammar/communications/7",
|
||||
},
|
||||
{
|
||||
id: "8",
|
||||
title: "8. Firmen und Produkte beschreiben",
|
||||
content: Chapter8,
|
||||
link: "/grammar/communications/8",
|
||||
},
|
||||
{
|
||||
id: "9",
|
||||
title: "9. Werbung machen",
|
||||
content: Chapter9,
|
||||
link: "/grammar/communications/9",
|
||||
},
|
||||
{
|
||||
id: "10",
|
||||
title: "10. Einkaufen privat und geschäftlich",
|
||||
content: Chapter10,
|
||||
link: "/grammar/communications/10",
|
||||
},
|
||||
{
|
||||
id: "11",
|
||||
title: "11. Räume beschreiben",
|
||||
content: Chapter11,
|
||||
link: "/grammar/communications/11",
|
||||
},
|
||||
{
|
||||
id: "12",
|
||||
title: "12. Über historische Ereignisse sprechen",
|
||||
content: Chapter12,
|
||||
link: "/grammar/communications/12",
|
||||
},
|
||||
{
|
||||
id: "13",
|
||||
title: "13. Pläne machen",
|
||||
content: Chapter13,
|
||||
link: "/grammar/communications/13",
|
||||
},
|
||||
{
|
||||
id: "14",
|
||||
title:
|
||||
"14. an Versammlungen und Geschäftstreffen teilnehmen und sie leiten",
|
||||
content: Chapter14,
|
||||
link: "/grammar/communications/14",
|
||||
},
|
||||
{
|
||||
id: "15",
|
||||
title: "15. Jemandem gratulieren",
|
||||
content: Chapter15,
|
||||
link: "/grammar/communications/15",
|
||||
},
|
||||
{
|
||||
id: "16",
|
||||
title: "16. Sich beschweren / etw. reklamieren",
|
||||
content: Chapter16,
|
||||
link: "/grammar/communications/16",
|
||||
},
|
||||
];
|
||||
|
||||
function Chapter1() {
|
||||
return (
|
||||
<Container className="chapter-content">
|
||||
INSERT INTO communications_pages_html (id, content)
|
||||
VALUES (1, '<Container className="chapter-content">
|
||||
<ul>
|
||||
<li>
|
||||
<Link href="/grammar/themes/perfekt">Perfekt</Link>
|
||||
@@ -201,83 +93,69 @@ function Chapter1() {
|
||||
width={872}
|
||||
height={387}
|
||||
/>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
</Container>')
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
|
||||
function Chapter2() {
|
||||
return (
|
||||
<Column className="chapter-content">
|
||||
INSERT INTO communications_pages_html (id, content)
|
||||
VALUES (2, '<Column className="chapter-content">
|
||||
<ul>
|
||||
<li>Passiv</li>
|
||||
<li>Infinitivkonstruktionen</li>
|
||||
<li>Finalsätze u. a.</li>
|
||||
</ul>
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
</Column>')
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
|
||||
function Chapter3() {
|
||||
return (
|
||||
<Column className="chapter-content">
|
||||
INSERT INTO communications_pages_html (id, content)
|
||||
VALUES (3, '<Column className="chapter-content">
|
||||
<ul>
|
||||
<li>Konjunktiv I bei indirekten Zitaten</li>
|
||||
<li>indirekte Frage- und Aussagesätze</li>
|
||||
<li>subjektive Modalität</li>
|
||||
<li>Futur II u. a. Vermutungen</li>
|
||||
</ul>
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
</Column>')
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
|
||||
function Chapter4() {
|
||||
return (
|
||||
<Column className="chapter-content">
|
||||
INSERT INTO communications_pages_html (id, content)
|
||||
VALUES (4, '<Column className="chapter-content">
|
||||
<ul>
|
||||
<li>Konjunktiv II als Höflichkeitsform</li>
|
||||
<li>Das Pronomen es (z. B. bei Witterungsverben)</li>
|
||||
<li>Dativ-Verben (geben, schenken usw.)</li>
|
||||
</ul>
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
</Column>')
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
|
||||
function Chapter5() {
|
||||
return (
|
||||
<Column className="chapter-content">
|
||||
INSERT INTO communications_pages_html (id, content)
|
||||
VALUES (5, '<Column className="chapter-content">
|
||||
<ul>
|
||||
<li>Vergleiche (wie und als)</li>
|
||||
<li>Adjektivdeklination</li>
|
||||
</ul>
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
</Column>')
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
|
||||
function Chapter6() {
|
||||
return (
|
||||
<Column className="chapter-content">
|
||||
INSERT INTO communications_pages_html (id, content)
|
||||
VALUES (6, '<Column className="chapter-content">
|
||||
<ul>
|
||||
<li>Adjektivdeklination</li>
|
||||
<li>Temporalangaben, -adverbien, -sätze</li>
|
||||
</ul>
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
</Column>')
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
|
||||
function Chapter7() {
|
||||
return (
|
||||
<Column className="chapter-content">
|
||||
INSERT INTO communications_pages_html (id, content)
|
||||
VALUES (7, '<Column className="chapter-content">
|
||||
<ul>
|
||||
<li>Hilfsverben</li>
|
||||
<li>Artikelverwendung</li>
|
||||
</ul>
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
</Column>')
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
|
||||
function Chapter8() {
|
||||
return (
|
||||
<Column className="chapter-content">
|
||||
INSERT INTO communications_pages_html (id, content)
|
||||
VALUES (8, '<Column className="chapter-content">
|
||||
<ul>
|
||||
<li>Adjektivdeklination</li>
|
||||
<li>Lokalangaben, -adverbien, -sätze</li>
|
||||
@@ -286,25 +164,21 @@ function Chapter8() {
|
||||
Adverbien zur Darstellung von Chronologie in Prozessbeschreibungen
|
||||
</li>
|
||||
</ul>
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
</Column>')
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
|
||||
function Chapter9() {
|
||||
return (
|
||||
<Column className="chapter-content">
|
||||
INSERT INTO communications_pages_html (id, content)
|
||||
VALUES (9, '<Column className="chapter-content">
|
||||
<ul>
|
||||
<li>Adjektivdeklination</li>
|
||||
<li>Vergleiche</li>
|
||||
<li>Präpositionen bei der Beschreibung von Leistungen und Produkten</li>
|
||||
</ul>
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
</Column>')
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
|
||||
function Chapter10() {
|
||||
return (
|
||||
<Column className="chapter-content">
|
||||
INSERT INTO communications_pages_html (id, content)
|
||||
VALUES (10, '<Column className="chapter-content">
|
||||
<ul>
|
||||
<li>Genuszuordnung</li>
|
||||
<li>Formen der Artikel</li>
|
||||
@@ -312,13 +186,11 @@ function Chapter10() {
|
||||
<li>andere Artikelwörter</li>
|
||||
<li>Akkusativ Bildung und Verwendung</li>
|
||||
</ul>
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
</Column>')
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
|
||||
function Chapter11() {
|
||||
return (
|
||||
<Column className="chapter-content">
|
||||
INSERT INTO communications_pages_html (id, content)
|
||||
VALUES (11, '<Column className="chapter-content">
|
||||
<ul>
|
||||
<li>
|
||||
Lokalpräpositionen (Wechsel- und ausgewählte lokale
|
||||
@@ -326,49 +198,41 @@ function Chapter11() {
|
||||
</li>
|
||||
<li>Lokaladverbien (insb. Verwendung im Satz)</li>
|
||||
</ul>
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
</Column>')
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
|
||||
function Chapter12() {
|
||||
return (
|
||||
<Column className="chapter-content">
|
||||
INSERT INTO communications_pages_html (id, content)
|
||||
VALUES (12, '<Column className="chapter-content">
|
||||
<ul>
|
||||
<li>Vergangenheitstempora, auch (hyster.) Präsens</li>
|
||||
<li>Temporaladverbien</li>
|
||||
</ul>
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
</Column>')
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
|
||||
function Chapter13() {
|
||||
return (
|
||||
<Column className="chapter-content">
|
||||
INSERT INTO communications_pages_html (id, content)
|
||||
VALUES (13, '<Column className="chapter-content">
|
||||
<ul>
|
||||
<li>Präsens + Temporaladverbien</li>
|
||||
<li>Temporalangaben und -sätze</li>
|
||||
<li>Konditionalsätze (real/irreal mit Konjunktiv II und würde)</li>
|
||||
<li>Futur I</li>
|
||||
</ul>
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
</Column>')
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
|
||||
function Chapter14() {
|
||||
return (
|
||||
<Column className="chapter-content">
|
||||
INSERT INTO communications_pages_html (id, content)
|
||||
VALUES (14, '<Column className="chapter-content">
|
||||
<ul>
|
||||
<li>Temporaladverbien</li>
|
||||
<li>Versch. Konjunktionalsätze</li>
|
||||
<li>Uneingeleitete Nebensätze</li>
|
||||
</ul>
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
</Column>')
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
|
||||
function Chapter15() {
|
||||
return (
|
||||
<Column className="chapter-content">
|
||||
INSERT INTO communications_pages_html (id, content)
|
||||
VALUES (15, '<Column className="chapter-content">
|
||||
<ul>
|
||||
<li>Komparation der Adjektive</li>
|
||||
<li>Anrede (du/Sie)</li>
|
||||
@@ -376,18 +240,15 @@ function Chapter15() {
|
||||
<Link href="/grammar/themes/perfekt">Perfekt</Link> / Präteritum
|
||||
</li>
|
||||
</ul>
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
</Column>')
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
|
||||
function Chapter16() {
|
||||
return (
|
||||
<Column className="chapter-content">
|
||||
INSERT INTO communications_pages_html (id, content)
|
||||
VALUES (16, '<Column className="chapter-content">
|
||||
<ul>
|
||||
<li>Konjunktiv</li>
|
||||
<li>Imperativ</li>
|
||||
<li>Rektion der Verben</li>
|
||||
</ul>
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
</Column>')
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
@@ -119,6 +119,15 @@ ALTER TABLE public.click_to_exercises
|
||||
ADD CONSTRAINT click_to_exercises_exercise_id_fkey
|
||||
FOREIGN KEY (exercise_id) REFERENCES exercises(id);
|
||||
|
||||
CREATE SEQUENCE public.communications_pages_html_id_seq;
|
||||
|
||||
CREATE TABLE public.communications_pages_html (
|
||||
id integer PRIMARY KEY NOT NULL DEFAULT nextval('communications_pages_html_id_seq'::regclass),
|
||||
content text NOT NULL
|
||||
);
|
||||
|
||||
ALTER SEQUENCE public.communications_pages_html_id_seq OWNED BY public.communications_pages_html.id;
|
||||
|
||||
CREATE TABLE public.dnd_categories (
|
||||
id bigint PRIMARY KEY NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
||||
created_at timestamp with time zone NOT NULL DEFAULT now(),
|
||||
|
||||
@@ -4,7 +4,7 @@ import { JSDOM } from "jsdom";
|
||||
import DOMPurify from "dompurify";
|
||||
|
||||
/*
|
||||
This route fetches html content from db according to id
|
||||
This route fetches html content from db according to id and page type
|
||||
*/
|
||||
export async function GET(req) {
|
||||
// create URL-object from request
|
||||
@@ -13,11 +13,24 @@ export async function GET(req) {
|
||||
// split path to segments
|
||||
const pathSegments = url.pathname.split("/");
|
||||
|
||||
// get page type from url parameters
|
||||
const type = url.searchParams.get("type");
|
||||
|
||||
// get last segment, which is the correct id of the page
|
||||
const id = pathSegments[pathSegments.length - 1];
|
||||
|
||||
// get content from db based on id
|
||||
const content = await getHTMLContent(id);
|
||||
// returns correct db table based on url. Prevents malicious code
|
||||
const getTableType = (type) => {
|
||||
if (type == "resources") {
|
||||
return "learning_pages_html";
|
||||
} else if (type == "communications") {
|
||||
return "communications_pages_html";
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
const content = await getHTMLContent(id, getTableType(type));
|
||||
|
||||
// returns the fetched html as json
|
||||
return new Response(JSON.stringify({ content }), {
|
||||
|
||||
@@ -5,7 +5,7 @@ import "../../../resources/[chapter]/chapters.css";
|
||||
import layout from "@/shared/styles/layout.module.css";
|
||||
import { useParams, useRouter } from "next/navigation";
|
||||
import { LinkButton } from "@/components/ui/linkbutton";
|
||||
import { chapters } from "./chapters";
|
||||
import RenderHTML, { PageType } from "@/app/html-renderer";
|
||||
|
||||
export default function Chapters() {
|
||||
const { chapter } = useParams();
|
||||
@@ -33,7 +33,7 @@ export default function Chapters() {
|
||||
erklärt.
|
||||
</p>
|
||||
<p>Folgende Grammatik-Themen sind damit verbunden: </p>
|
||||
<Chapter.content />
|
||||
<RenderHTML contentId={Chapter.id} type="communications" />
|
||||
</>
|
||||
)}
|
||||
<Row justify="space-between" pb="xl">
|
||||
@@ -51,3 +51,88 @@ export default function Chapters() {
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
|
||||
export const chapters = [
|
||||
{
|
||||
id: "1",
|
||||
title: "1. Über Vergangenes sprechen",
|
||||
link: "/grammar/communications/1",
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
title: "2. Anleitungen formulieren",
|
||||
link: "/grammar/communications/2",
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
title: "3. Offizielle Mitteilungen (Nachrichten usw.) formulieren",
|
||||
link: "/grammar/communications/3",
|
||||
},
|
||||
{
|
||||
id: "4",
|
||||
title:
|
||||
"4. Höflich mit anderen Menschen umgehen (Sich vorstellen, Gäste empfangen und betreuen, Small Talk)",
|
||||
link: "/grammar/communications/4",
|
||||
},
|
||||
{
|
||||
id: "5",
|
||||
title: "5. Menschen beschreiben / Ich und meine Familie",
|
||||
link: "/grammar/communications/5",
|
||||
},
|
||||
{
|
||||
id: "6",
|
||||
title: "6. Über Hobbys und Freizeit sprechen",
|
||||
link: "/grammar/communications/6",
|
||||
},
|
||||
{
|
||||
id: "7",
|
||||
title: "7. Über Beruf und Arbeitsplatz sprechen",
|
||||
link: "/grammar/communications/7",
|
||||
},
|
||||
{
|
||||
id: "8",
|
||||
title: "8. Firmen und Produkte beschreiben",
|
||||
link: "/grammar/communications/8",
|
||||
},
|
||||
{
|
||||
id: "9",
|
||||
title: "9. Werbung machen",
|
||||
link: "/grammar/communications/9",
|
||||
},
|
||||
{
|
||||
id: "10",
|
||||
title: "10. Einkaufen privat und geschäftlich",
|
||||
link: "/grammar/communications/10",
|
||||
},
|
||||
{
|
||||
id: "11",
|
||||
title: "11. Räume beschreiben",
|
||||
link: "/grammar/communications/11",
|
||||
},
|
||||
{
|
||||
id: "12",
|
||||
title: "12. Über historische Ereignisse sprechen",
|
||||
link: "/grammar/communications/12",
|
||||
},
|
||||
{
|
||||
id: "13",
|
||||
title: "13. Pläne machen",
|
||||
link: "/grammar/communications/13",
|
||||
},
|
||||
{
|
||||
id: "14",
|
||||
title:
|
||||
"14. an Versammlungen und Geschäftstreffen teilnehmen und sie leiten",
|
||||
link: "/grammar/communications/14",
|
||||
},
|
||||
{
|
||||
id: "15",
|
||||
title: "15. Jemandem gratulieren",
|
||||
link: "/grammar/communications/15",
|
||||
},
|
||||
{
|
||||
id: "16",
|
||||
title: "16. Sich beschweren / etw. reklamieren",
|
||||
link: "/grammar/communications/16",
|
||||
},
|
||||
];
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { chapters } from "./[chapter]/chapters";
|
||||
import { chapters } from "./[chapter]/page";
|
||||
import Link from "next/link";
|
||||
import "@/app/grammar/themes/lessons.css";
|
||||
|
||||
|
||||
@@ -6,15 +6,14 @@ The returned content can be used by js functions that are used to render individ
|
||||
|
||||
parameter contentId: id of the HTML content in db
|
||||
|
||||
NOTE: Currently this function fetches content corresponding to id. This is ok when rendering
|
||||
lesson pages, since they are named 1-n. This function could be used to render any page content,
|
||||
if the fetching function was changed in backend to find content based on some other identifier.
|
||||
This function probably doens't need any changes, but at this moment it is only used to render chapter pages.
|
||||
parameter type: page type
|
||||
|
||||
|
||||
|
||||
NOTE: This function could be enhanced by providing HTML sanitizing before returning content.
|
||||
One option for this would be using dompurify sanitizer
|
||||
*/
|
||||
export default function RenderHTML({ contentId }) {
|
||||
export default function RenderHTML({ contentId, type }) {
|
||||
// create state for HTML content
|
||||
const [html, setHtml] = useState("");
|
||||
|
||||
@@ -23,7 +22,7 @@ export default function RenderHTML({ contentId }) {
|
||||
// function to fetch HTML content using html-services, and set it to state html
|
||||
async function fetchHTML() {
|
||||
// fetch response through next.js route using getHTMLContent function
|
||||
const res = await fetch(`/api/html-content/${contentId}`);
|
||||
const res = await fetch(`/api/html-content/${contentId}?type=${type}`);
|
||||
|
||||
// chnages the response to proper json
|
||||
const data = await res.json();
|
||||
|
||||
@@ -8,8 +8,9 @@ import { useParams, useRouter } from "next/navigation";
|
||||
import { LinkButton } from "@/components/ui/linkbutton";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import Editor from "@/components/ui/editor";
|
||||
import RenderHTML from "@/app/html-renderer";
|
||||
import RenderHTML, { PageType } from "@/app/html-renderer";
|
||||
import { checkUseIsAdmin } from "@/context/user.context";
|
||||
import { PAGE_TYPES } from "next/dist/lib/page-types";
|
||||
|
||||
export default function Chapters() {
|
||||
const { chapter } = useParams();
|
||||
@@ -91,7 +92,7 @@ export default function Chapters() {
|
||||
{checkUseIsAdmin() == true && (
|
||||
<Button onClick={() => setEditorActive(true)}>Open editor</Button>
|
||||
)}
|
||||
<RenderHTML contentId={Chapter.id} />
|
||||
<RenderHTML contentId={Chapter.id} type="resources" />
|
||||
{/*<Chapter.content />*/}
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -5,6 +5,8 @@ This function fetches html content from database
|
||||
|
||||
parameter id: id of the content in table learning_pages_html
|
||||
|
||||
parameter type: PageType enum denoting the sql table name
|
||||
|
||||
NOTE: This function could be used to fetch html content to all pages, not just
|
||||
for chapter pages, e.g. gradesa/resources/*. In that case, the database table
|
||||
should be updated to include some kind of identifier other than id number
|
||||
@@ -13,11 +15,12 @@ NOTE: This function could be used to fetch html content to all pages, not just
|
||||
other identifier as parameter for this function.
|
||||
|
||||
*/
|
||||
export async function getHTMLContent(id) {
|
||||
export async function getHTMLContent(id, type) {
|
||||
try {
|
||||
console.log("Table type: ", type);
|
||||
// get content from db using parameterized query
|
||||
const result = await DB.pool(
|
||||
"SELECT content FROM learning_pages_html WHERE id = $1",
|
||||
"SELECT content FROM " + type + " WHERE id = $1",
|
||||
[id]
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user