Diary page selector
This commit is contained in:
parent
bd3fe1518d
commit
6a8c1265fa
@ -1,52 +1,58 @@
|
|||||||
import type { NextPage } from "next";
|
import type { NextPage } from "next";
|
||||||
import { useContext, useEffect, useRef, useState } from "react";
|
import { useRef, useState } from "react";
|
||||||
import asciidoctor from "asciidoctor";
|
|
||||||
import styles from "../styles/ProjectModal.module.css";
|
import styles from "../styles/ProjectModal.module.css";
|
||||||
import type { Project, Diary } from "../lib/content/types";
|
import type { Project, Diary } from "../lib/content/types";
|
||||||
import { useCommands } from "./contexts/CommandInterface";
|
import { useCommands } from "./contexts/CommandInterface";
|
||||||
import { generateContent, projectEmpty } from "../lib/content/generate";
|
import { generateContent, projectEmpty } from "../lib/content/generate";
|
||||||
import { useModalFunctions } from "./contexts/ModalFunctions";
|
import { useModalFunctions } from "./contexts/ModalFunctions";
|
||||||
//import Link from "next/link";
|
|
||||||
|
|
||||||
const ProjectModal: NextPage = () => {
|
const ProjectModal: NextPage = () => {
|
||||||
const [visible, setVisible] = useState<boolean>(false);
|
const [visible, setVisible] = useState<boolean>(false);
|
||||||
const [diaryPages, setDiaryPages] = useState<string[]>([]);
|
const [currentContent, setCurrentContent] = useState<Project | Diary | undefined>(undefined);
|
||||||
const [content, setContent] = useState<string>(projectEmpty);
|
const [currentPage, setCurrentPage] = useState<number>(0);
|
||||||
|
const [HTMLContent, setHTMLContent] = useState<string>(projectEmpty);
|
||||||
|
|
||||||
const setModalContent = async (content: Project|Diary, selectedPage?: number) => {
|
const setModalContent = async (content: Project | Diary, selectedPage?: number) => {
|
||||||
if (content.type === "diary") setDiaryPages(content.entries.map(entry => entry.title));
|
setCurrentContent(content);
|
||||||
setContent(await generateContent(content, selectedPage));
|
if (content.type === "diary") setCurrentPage(selectedPage === undefined ? 0 : selectedPage);
|
||||||
|
setHTMLContent(await generateContent(content, selectedPage));
|
||||||
};
|
};
|
||||||
|
|
||||||
const { updateCallbacks: updateCmdCallbacks } = useCommands();
|
const { updateCallbacks: updateCmdCallbacks } = useCommands();
|
||||||
const { updateCallbacks: updateModalCallbacks } = useModalFunctions();
|
const { updateCallbacks: updateModalCallbacks } = useModalFunctions();
|
||||||
updateCmdCallbacks({ setModalVisible: setVisible, setModalContent, setModalHTML: setContent });
|
updateCmdCallbacks({ setModalVisible: setVisible, setModalContent, setModalHTML: setHTMLContent });
|
||||||
updateModalCallbacks({ setVisible, setContent: setModalContent, setHtml: setContent });
|
updateModalCallbacks({ setVisible, setContent: setModalContent, setHtml: setHTMLContent });
|
||||||
|
|
||||||
const containerRef = useRef<HTMLDivElement>(null);
|
const containerRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
/*useEffect(() => {
|
|
||||||
console.log(content);
|
|
||||||
if (content && containerRef.current) {
|
|
||||||
containerRef.current.innerHTML = content;
|
|
||||||
}
|
|
||||||
}, [content]);*/
|
|
||||||
|
|
||||||
if (!visible) return <></>;
|
if (!visible) return <></>;
|
||||||
|
|
||||||
|
const nextPageSelector = (() => {
|
||||||
|
if (!currentContent || currentContent?.type !== "diary" || currentContent.entries.length === 0) return null;
|
||||||
|
|
||||||
|
const prev = <span className={styles.leftSelectSpace}>{currentPage > 0 ? <a href="#" onClick={() => setModalContent(currentContent, currentPage - 1)}>< {currentPage - 1 > 0 ? currentContent.entries[currentPage - 2].title : "Main page"}</a> : null}</span>;
|
||||||
|
const next = <span className={styles.rightSelectSpace}>{currentPage < currentContent.entries.length ? <a href="#" onClick={() => setModalContent(currentContent, currentPage + 1)}>{currentContent.entries[currentPage].title} ></a> : null}</span>;
|
||||||
|
|
||||||
|
const select = (
|
||||||
|
<select onChange={(e) => setModalContent(currentContent, Number.parseInt(e.target.value))} value={currentPage}>
|
||||||
|
<option key={-1} value={0}>Main page</option>
|
||||||
|
{currentContent.entries.map((entry, i) => <option key={i} value={i + 1}>{entry.title}</option>)}
|
||||||
|
</select>
|
||||||
|
);
|
||||||
|
|
||||||
|
return <div className={styles.pageSelector}>{prev}{currentPage > 0 ? <span> | </span> : null}{select}{currentPage < currentContent.entries.length ? <span> | </span> : null}{next}</div>;
|
||||||
|
})();
|
||||||
|
|
||||||
return <div className={styles.modal}>
|
return <div className={styles.modal}>
|
||||||
<a onClick={() => setVisible(false)}>
|
<a onClick={() => setVisible(false)}>
|
||||||
<div className={styles.modalClose}><div className={styles.modalCloseAlign}>X</div></div>
|
<div className={styles.modalClose}><div className={styles.modalCloseAlign}>X</div></div>
|
||||||
</a>
|
</a>
|
||||||
<div className={styles.modalContainer}>
|
<div className={styles.modalContainer}>
|
||||||
{
|
{nextPageSelector}
|
||||||
// TODO
|
<div className={`${styles.modalText} asciidoc`} ref={containerRef} dangerouslySetInnerHTML={{ __html: HTMLContent ? HTMLContent : projectEmpty }}>
|
||||||
// If diaryPages
|
|
||||||
// Show page selector
|
|
||||||
}
|
|
||||||
<div className={`${styles.modalText} asciidoc`} ref={containerRef} dangerouslySetInnerHTML={{__html: content ? content : projectEmpty}}>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
{nextPageSelector}
|
||||||
</div>
|
</div>
|
||||||
</div>;
|
</div>;
|
||||||
};
|
};
|
||||||
|
@ -26,21 +26,24 @@ async function generateProjectHTML(project: Project): Promise<string> {
|
|||||||
<hr>
|
<hr>
|
||||||
<div id="footer">
|
<div id="footer">
|
||||||
<div id="footer-text">
|
<div id="footer-text">
|
||||||
Last updated: ${adDoc.getAttribute("docdatetime")} | <a href="https://git.c0ntroller.de/c0ntroller/frontpage-content/src/branch/senpai/projects/${project.name}.adoc">Document source</a>
|
Last updated: ${adDoc.getAttribute("docdatetime")} | <a href="https://git.c0ntroller.de/c0ntroller/frontpage-content/src/branch/senpai/projects/${project.name}.adoc" target="_blank">Document source</a>
|
||||||
</div>
|
</div>
|
||||||
</div>`;
|
</div>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function generateDiaryHTML(diary: Diary, selectedPage?: number): Promise<string> {
|
async function generateDiaryHTML(diary: Diary, selectedPage?: number): Promise<string> {
|
||||||
const resp = selectedPage === undefined ? await fetch(`/content/diaries/${diary.name}.adoc`) : await fetch(`/content/diaries/${diary.name}/${diary.entries[selectedPage].filename}.adoc`);
|
const page: number = Number.parseInt(selectedPage?.toString() || "0") - 1;
|
||||||
|
const resp = page === -1 ? await fetch(`/content/diaries/${diary.name}.adoc`) : await fetch(`/content/diaries/${diary.name}/${diary.entries[page].filename}.adoc`);
|
||||||
if (resp.status !== 200) return projectServerErrorHtml;
|
if (resp.status !== 200) return projectServerErrorHtml;
|
||||||
const adDoc = ad.load(await resp.text(), { attributes: { showtitle: true } });
|
const rawAd = await resp.text();
|
||||||
const gitfile = selectedPage === undefined ? `${diary.name}.adoc` : `${diary.name}/${diary.entries[selectedPage].filename}.adoc`;
|
const pathsCorrected = rawAd.replace(/(image[:]{1,2})(.*\.[a-zA-Z]+)\[/g, "$1/content/diaries/$2[");
|
||||||
|
const adDoc = ad.load(pathsCorrected, { attributes: { showtitle: true } });
|
||||||
|
const gitfile = page === -1 ? `${diary.name}.adoc` : `${diary.name}/${diary.entries[page].filename}.adoc`;
|
||||||
return `${adDoc.convert(adDoc).toString()}
|
return `${adDoc.convert(adDoc).toString()}
|
||||||
<hr>
|
<hr>
|
||||||
<div id="footer">
|
<div id="footer">
|
||||||
<div id="footer-text">
|
<div id="footer-text">
|
||||||
Last updated: ${adDoc.getAttribute("docdatetime")} | <a href="https://git.c0ntroller.de/c0ntroller/frontpage-content/src/branch/senpai/diaries/${gitfile}">Document source</a>
|
Last updated: ${adDoc.getAttribute("docdatetime")} | <a href="https://git.c0ntroller.de/c0ntroller/frontpage-content/src/branch/senpai/diaries/${gitfile}" target="_blank">Document source</a>
|
||||||
</div>
|
</div>
|
||||||
</div>`;
|
</div>`;
|
||||||
}
|
}
|
@ -74,3 +74,40 @@
|
|||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.pageSelector {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
font-family: sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pageSelector:last-of-type {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pageSelector select {
|
||||||
|
background: var(--modal-gray); /* Transparent does not work for the dropdown */
|
||||||
|
color: var(--repl-color-link);
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pageSelector a:link, .pageSelector a:visited, .pageSelector a:hover, .pageSelector a:active {
|
||||||
|
color: var(--repl-color-link);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pageSelector a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leftSelectSpace, .rightSelectSpace {
|
||||||
|
flex-grow: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leftSelectSpace {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rightSelectSpace {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
@ -1,15 +1,19 @@
|
|||||||
.asciidoc {
|
.asciidoc {
|
||||||
/*@import "../node_modules/@asciidoctor/core/dist/css/asciidoctor.css";*/
|
font-family: sans-serif;
|
||||||
|
|
||||||
@import "./asciidocBootSlate";
|
@import "./asciidocBootSlate";
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
color: var(--repl-color-link, #2ac02a);
|
color: var(--repl-color-link, #2ac02a);
|
||||||
font-size: 3em;
|
font-size: 3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
h2,
|
h2,
|
||||||
h3 {
|
h3 {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
h2,
|
h2,
|
||||||
h3,
|
h3,
|
||||||
h4,
|
h4,
|
||||||
@ -17,18 +21,21 @@
|
|||||||
h6 {
|
h6 {
|
||||||
color: var(--repl-color, #188a18);
|
color: var(--repl-color, #188a18);
|
||||||
}
|
}
|
||||||
font-family: sans-serif;
|
|
||||||
#preamble {
|
#preamble {
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
font-size: 120%;
|
font-size: 120%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.paragraph {
|
.paragraph {
|
||||||
line-height: 1.3;
|
line-height: 1.3;
|
||||||
}
|
}
|
||||||
tbody>tr:nth-of-type(odd), #footer {
|
|
||||||
|
tbody>tr:nth-of-type(odd),
|
||||||
|
#footer {
|
||||||
background-color: #1f2420;
|
background-color: #1f2420;
|
||||||
}
|
}
|
||||||
|
|
||||||
tbody>tr:hover {
|
tbody>tr:hover {
|
||||||
background-color: #364239;
|
background-color: #364239;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user