various changes
This commit is contained in:
parent
c3a8469371
commit
adc02f2e5b
@ -7,21 +7,16 @@ import { cookies } from "next/headers";
|
||||
|
||||
|
||||
async function tryCreatePost(request: Request) {
|
||||
|
||||
// Make sure the DB is ready
|
||||
const sync = await dbSync;
|
||||
|
||||
// Prepare data
|
||||
const requestBody = await request.json();
|
||||
const authCkie = await cookies().get("auth");
|
||||
|
||||
// Sanity check auth cookie
|
||||
if ( !authCkie || !authCkie.value) throw new APIError({ status: 500, responseText: "missing auth cookie" });
|
||||
|
||||
// Get JSON from the Cookie
|
||||
const cookieJSON = authCkie.value;
|
||||
const authObject = JSON.parse(cookieJSON);
|
||||
|
||||
// Fetch User Auth from the database
|
||||
const auth = await Auth.findOne({
|
||||
include: [
|
||||
@ -42,6 +37,7 @@ async function tryCreatePost(request: Request) {
|
||||
if (!requestBody) throw new APIError({ status: 500, responseText: "Empty request body" });
|
||||
if (!requestBody.title) throw new APIError({ status: 500, responseText: "Missing post title" });
|
||||
if (!requestBody.content) throw new APIError({ status: 500, responseText: "Missing post content" });
|
||||
if (!requestBody.description) throw new APIError({ status: 500, responseText: "Missing post description" });
|
||||
if (!auth.user.id) throw new APIError({ status: 500, responseText: "Missing user id" });
|
||||
if (!auth.user.perms || !auth.user.perms.isAdmin) throw new APIError({ status: 401, responseText: `Unauthorized ${JSON.stringify(auth.user)}` });
|
||||
|
||||
@ -49,6 +45,7 @@ async function tryCreatePost(request: Request) {
|
||||
const post = await Post.create(
|
||||
{
|
||||
content: requestBody.content,
|
||||
description: requestBody.description,
|
||||
user_id: auth.user.id,
|
||||
title: requestBody.title,
|
||||
},{
|
||||
|
||||
8
src/app/attachment/[...slug]/route.ts
Normal file
8
src/app/attachment/[...slug]/route.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import { open, openSync, readFileSync } from "fs";
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
import path from "path";
|
||||
|
||||
export async function GET(req:NextRequest, { params }: {params:{slug: string}}){
|
||||
const fp = path.resolve('.',`bucket`,...params.slug);
|
||||
return new Response(readFileSync(fp));
|
||||
}
|
||||
@ -28,127 +28,132 @@ body {
|
||||
|
||||
@layer base {
|
||||
:root {
|
||||
--text-50: #f3eff5;
|
||||
--text-100: #e7dfec;
|
||||
--text-200: #cfbfd9;
|
||||
--text-300: #b89fc6;
|
||||
--text-400: #a080b3;
|
||||
--text-500: #88609f;
|
||||
--text-600: #6d4d80;
|
||||
--text-700: #523960;
|
||||
--text-800: #362640;
|
||||
--text-900: #1b1320;
|
||||
--text-950: #0e0a10;
|
||||
--text: #ffffff;
|
||||
--text-50: #f2f2f2;
|
||||
--text-100: #e6e6e6;
|
||||
--text-200: #cccccc;
|
||||
--text-300: #b3b3b3;
|
||||
--text-400: #999999;
|
||||
--text-500: #808080;
|
||||
--text-600: #666666;
|
||||
--text-700: #4d4d4d;
|
||||
--text-800: #333333;
|
||||
--text-900: #1a1a1a;
|
||||
--text-950: #0d0d0d;
|
||||
|
||||
--background-50: #f4eef6;
|
||||
--background-100: #e8ddee;
|
||||
--background-200: #d2bbdd;
|
||||
--background-300: #bb99cc;
|
||||
--background-400: #a477bb;
|
||||
--background-500: #8e55aa;
|
||||
--background-600: #714488;
|
||||
--background-700: #553366;
|
||||
--background-800: #392244;
|
||||
--background-900: #1c1122;
|
||||
--background-950: #0e0911;
|
||||
--background: #1e546b;
|
||||
--background-50: #ebf5f9;
|
||||
--background-100: #d7ebf4;
|
||||
--background-200: #afd7e9;
|
||||
--background-300: #88c4dd;
|
||||
--background-400: #60b0d2;
|
||||
--background-500: #389cc7;
|
||||
--background-600: #2d7d9f;
|
||||
--background-700: #225e77;
|
||||
--background-800: #163e50;
|
||||
--background-900: #0b1f28;
|
||||
--background-950: #061014;
|
||||
|
||||
--primary-50: #f3edf8;
|
||||
--primary-100: #e6daf1;
|
||||
--primary-200: #ceb5e3;
|
||||
--primary-300: #b590d5;
|
||||
--primary-400: #9c6bc7;
|
||||
--primary-500: #8346b9;
|
||||
--primary-600: #693894;
|
||||
--primary-700: #4f2a6f;
|
||||
--primary-800: #351c4a;
|
||||
--primary-900: #1a0e25;
|
||||
--primary-950: #0d0712;
|
||||
--primary: #008bc7;
|
||||
--primary-50: #e5f7ff;
|
||||
--primary-100: #ccf0ff;
|
||||
--primary-200: #99e0ff;
|
||||
--primary-300: #66d1ff;
|
||||
--primary-400: #33c2ff;
|
||||
--primary-500: #00b2ff;
|
||||
--primary-600: #008fcc;
|
||||
--primary-700: #006b99;
|
||||
--primary-800: #004766;
|
||||
--primary-900: #002433;
|
||||
--primary-950: #00121a;
|
||||
|
||||
--secondary-50: #f3ebf9;
|
||||
--secondary-100: #e7d7f4;
|
||||
--secondary-200: #cfb0e8;
|
||||
--secondary-300: #b788dd;
|
||||
--secondary-400: #9f61d1;
|
||||
--secondary-500: #8739c6;
|
||||
--secondary-600: #6c2e9e;
|
||||
--secondary-700: #512277;
|
||||
--secondary-800: #36174f;
|
||||
--secondary-900: #1b0b28;
|
||||
--secondary-950: #0d0614;
|
||||
--secondary: #136d94;
|
||||
--secondary-50: #e8f6fc;
|
||||
--secondary-100: #d2edf9;
|
||||
--secondary-200: #a5dcf3;
|
||||
--secondary-300: #78caed;
|
||||
--secondary-400: #4ab8e8;
|
||||
--secondary-500: #1da7e2;
|
||||
--secondary-600: #1785b5;
|
||||
--secondary-700: #126487;
|
||||
--secondary-800: #0c435a;
|
||||
--secondary-900: #06212d;
|
||||
--secondary-950: #031117;
|
||||
|
||||
--accent-50: #f3eafb;
|
||||
--accent-100: #e7d5f6;
|
||||
--accent-200: #cfaaee;
|
||||
--accent-300: #b880e5;
|
||||
--accent-400: #a056dc;
|
||||
--accent-500: #882bd4;
|
||||
--accent-600: #6d23a9;
|
||||
--accent-700: #521a7f;
|
||||
--accent-800: #361155;
|
||||
--accent-900: #1b092a;
|
||||
--accent-950: #0e0415;
|
||||
--accent: #42aedc;
|
||||
--accent-50: #e9f6fb;
|
||||
--accent-100: #d4edf7;
|
||||
--accent-200: #a9daef;
|
||||
--accent-300: #7ec8e7;
|
||||
--accent-400: #53b5df;
|
||||
--accent-500: #28a3d7;
|
||||
--accent-600: #2082ac;
|
||||
--accent-700: #186281;
|
||||
--accent-800: #104156;
|
||||
--accent-900: #08212b;
|
||||
--accent-950: #041016;
|
||||
|
||||
}
|
||||
.dark {
|
||||
--text-50: #0e0910;
|
||||
--text-100: #1b1320;
|
||||
--text-200: #362541;
|
||||
--text-300: #513861;
|
||||
--text-400: #6c4a82;
|
||||
--text-500: #885da2;
|
||||
--text-600: #9f7db5;
|
||||
--text-700: #b79ec7;
|
||||
--text-800: #cfbeda;
|
||||
--text-900: #e7dfec;
|
||||
--text-950: #f3eff6;
|
||||
--text-50: #0d0d0d;
|
||||
--text-100: #1a1a1a;
|
||||
--text-200: #333333;
|
||||
--text-300: #4d4d4d;
|
||||
--text-400: #666666;
|
||||
--text-500: #808080;
|
||||
--text-600: #999999;
|
||||
--text-700: #b3b3b3;
|
||||
--text-800: #cccccc;
|
||||
--text-900: #e6e6e6;
|
||||
--text-950: #f2f2f2;
|
||||
|
||||
--background-50: #0d0911;
|
||||
--background-100: #1b1122;
|
||||
--background-200: #352244;
|
||||
--background-300: #503366;
|
||||
--background-400: #6a4488;
|
||||
--background-500: #8555aa;
|
||||
--background-600: #9d77bb;
|
||||
--background-700: #b699cc;
|
||||
--background-800: #cebbdd;
|
||||
--background-900: #e7ddee;
|
||||
--background-950: #f3eef6;
|
||||
--background-50: #061014;
|
||||
--background-100: #0b1f28;
|
||||
--background-200: #163e50;
|
||||
--background-300: #225e77;
|
||||
--background-400: #2d7d9f;
|
||||
--background-500: #389cc7;
|
||||
--background-600: #60b0d2;
|
||||
--background-700: #88c4dd;
|
||||
--background-800: #afd7e9;
|
||||
--background-900: #d7ebf4;
|
||||
--background-950: #ebf5f9;
|
||||
|
||||
--primary-50: #0d0712;
|
||||
--primary-100: #1a0e25;
|
||||
--primary-200: #351c4a;
|
||||
--primary-300: #4f2a6f;
|
||||
--primary-400: #693894;
|
||||
--primary-500: #8346b9;
|
||||
--primary-600: #9c6bc7;
|
||||
--primary-700: #b590d5;
|
||||
--primary-800: #ceb5e3;
|
||||
--primary-900: #e6daf1;
|
||||
--primary-950: #f3edf8;
|
||||
--primary-50: #00121a;
|
||||
--primary-100: #002433;
|
||||
--primary-200: #004766;
|
||||
--primary-300: #006b99;
|
||||
--primary-400: #008fcc;
|
||||
--primary-500: #00b2ff;
|
||||
--primary-600: #33c2ff;
|
||||
--primary-700: #66d1ff;
|
||||
--primary-800: #99e0ff;
|
||||
--primary-900: #ccf0ff;
|
||||
--primary-950: #e5f7ff;
|
||||
|
||||
--secondary-50: #0d0614;
|
||||
--secondary-100: #1b0b28;
|
||||
--secondary-200: #36174f;
|
||||
--secondary-300: #512277;
|
||||
--secondary-400: #6c2e9e;
|
||||
--secondary-500: #8739c6;
|
||||
--secondary-600: #9f61d1;
|
||||
--secondary-700: #b788dd;
|
||||
--secondary-800: #cfb0e8;
|
||||
--secondary-900: #e7d7f4;
|
||||
--secondary-950: #f3ebf9;
|
||||
--secondary-50: #031117;
|
||||
--secondary-100: #06212d;
|
||||
--secondary-200: #0c435a;
|
||||
--secondary-300: #126487;
|
||||
--secondary-400: #1785b5;
|
||||
--secondary-500: #1da7e2;
|
||||
--secondary-600: #4ab8e8;
|
||||
--secondary-700: #78caed;
|
||||
--secondary-800: #a5dcf3;
|
||||
--secondary-900: #d2edf9;
|
||||
--secondary-950: #e8f6fc;
|
||||
|
||||
--accent-50: #0e0415;
|
||||
--accent-100: #1b092a;
|
||||
--accent-200: #361155;
|
||||
--accent-300: #521a7f;
|
||||
--accent-400: #6d23a9;
|
||||
--accent-500: #882bd4;
|
||||
--accent-600: #a056dc;
|
||||
--accent-700: #b880e5;
|
||||
--accent-800: #cfaaee;
|
||||
--accent-900: #e7d5f6;
|
||||
--accent-950: #f3eafb;
|
||||
--accent-50: #041016;
|
||||
--accent-100: #08212b;
|
||||
--accent-200: #104156;
|
||||
--accent-300: #186281;
|
||||
--accent-400: #2082ac;
|
||||
--accent-500: #28a3d7;
|
||||
--accent-600: #53b5df;
|
||||
--accent-700: #7ec8e7;
|
||||
--accent-800: #a9daef;
|
||||
--accent-900: #d4edf7;
|
||||
--accent-950: #e9f6fb;
|
||||
|
||||
}
|
||||
}
|
||||
@ -1,11 +1,10 @@
|
||||
'use server';
|
||||
|
||||
import { revalidatePath, revalidateTag } from 'next/cache'
|
||||
import { Post } from "@/model/Post";
|
||||
import { Bucket, Post, PostBucket, User, dbSync } from "@/model/Models";
|
||||
import { Attributes, where } from "@sequelize/core";
|
||||
import { cookies } from 'next/headers';
|
||||
import { getCookieAuth, userIsAdmin } from '../actions';
|
||||
import { User } from '@/model/User';
|
||||
import { ActionResult } from '../ActionResult';
|
||||
|
||||
|
||||
@ -13,6 +12,7 @@ import { ActionResult } from '../ActionResult';
|
||||
|
||||
|
||||
export async function deletePost(postID: number): Promise<ActionResult<boolean>> {
|
||||
await dbSync;
|
||||
// revalidatePath("/admin/man-post","page")
|
||||
if(! await userIsAdmin()) return {error:"Unauthorized, not deleting Post", result: false}
|
||||
const destroy = await Post.destroy({ where: { id: postID } });
|
||||
@ -21,12 +21,14 @@ export async function deletePost(postID: number): Promise<ActionResult<boolean>>
|
||||
|
||||
|
||||
export async function getPosts(): Promise<ActionResult<Attributes<Post>[]>> {
|
||||
await dbSync;
|
||||
if(! await userIsAdmin()) return {error:"Unauthorized, not fetching Posts."}
|
||||
const posts = await Post.findAll();
|
||||
const posts = await Post.findAll({include: {association: Post.associations.postBuckets, include: Bucket.associations.attachments}},);
|
||||
return {result:JSON.parse(JSON.stringify(posts))};
|
||||
}
|
||||
|
||||
export async function updatePost(postAttributes: Partial<Attributes<Post>>): Promise<ActionResult<Attributes<Post>[]>> {
|
||||
await dbSync;
|
||||
if(! await userIsAdmin()) return {error:"Unauthorized, not updating Post."}
|
||||
const post = await Post.update(postAttributes, {where:{id:postAttributes.id}});
|
||||
return {result:JSON.parse(JSON.stringify(post))};
|
||||
|
||||
39
src/app/lib/jsxtostring.ts
Normal file
39
src/app/lib/jsxtostring.ts
Normal file
@ -0,0 +1,39 @@
|
||||
import React, { ReactElement, ReactNode } from 'react';
|
||||
|
||||
function renderAttributes(props: Record<string, any>): string {
|
||||
return Object.keys(props)
|
||||
.map((key) => {
|
||||
const value = props[key];
|
||||
if (key === 'children' || value === undefined || value === null) {
|
||||
return '';
|
||||
}
|
||||
return `${key}="${value}"`;
|
||||
})
|
||||
.filter(Boolean)
|
||||
.join(' ');
|
||||
}
|
||||
|
||||
function renderElement(element: ReactNode): string {
|
||||
if (typeof element === 'string' || typeof element === 'number') {
|
||||
return String(element);
|
||||
}
|
||||
|
||||
if (React.isValidElement(element)) {
|
||||
const { type, props } = element;
|
||||
const mapped = React.Children.map(props.children, renderElement)
|
||||
const cilds = mapped? mapped.join('') : props.children;
|
||||
const attributes = renderAttributes(props);
|
||||
return `<${type}${attributes ? ' ' + attributes : ''}>${cilds}</${type}>`;
|
||||
}
|
||||
|
||||
if (Array.isArray(element)) {
|
||||
return element.map(renderElement).join('');
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
export function jsxToString(element: JSX.Element): string {
|
||||
console.log(element);
|
||||
return renderElement(element);
|
||||
}
|
||||
@ -34,7 +34,7 @@ export default async function Test() {
|
||||
<main>
|
||||
{articles.map((article, i) => {
|
||||
// Return the element. Also pass key
|
||||
return (<ArticlePreview key={article?.id} id={article?.id?.toString()} content={article?.content} title={article?.title}></ArticlePreview>)
|
||||
return (<ArticlePreview key={article?.id} post={article}></ArticlePreview>)
|
||||
})}
|
||||
</main>
|
||||
</PageContainer>
|
||||
|
||||
@ -1,18 +1,26 @@
|
||||
import { ActionResult } from "@/app/lib/actions/ActionResult";
|
||||
import { handleActionResult } from "@/app/lib/actions/clientActionHandler";
|
||||
import { Post } from "@/model/Post";
|
||||
import { Project } from "@/model/Project";
|
||||
import { Post, Project, Bucket, PostBucket, Attachment } from "@/model/Models";
|
||||
import { Attributes } from "@sequelize/core";
|
||||
import { UUID } from "crypto";
|
||||
import { ChangeEventHandler, MouseEventHandler, useLayoutEffect, useRef, useState } from "react";
|
||||
import { Accordion, AccordionBody, AccordionHeader, AccordionItem } from "react-bootstrap";
|
||||
|
||||
export type PostTableCallbacks = {
|
||||
savePost: (p:Partial<Attributes<Post>>)=>any;
|
||||
closeEditor: ()=>any;
|
||||
}
|
||||
type PostEditorBucket = Partial<Attributes<Bucket>> & {
|
||||
attachments:Partial<Attributes<Attachment>>[]
|
||||
}
|
||||
|
||||
type PostEditorPost = Partial<Attributes<Post>> & {
|
||||
buckets:PostEditorBucket[]
|
||||
}
|
||||
|
||||
export type EditorProps = {
|
||||
open:boolean;
|
||||
post:Partial<Attributes<Post>>;
|
||||
post:PostEditorPost;
|
||||
projects?:Attributes<Project>[];
|
||||
callbacks:PostTableCallbacks;
|
||||
}
|
||||
@ -23,7 +31,7 @@ export default function PostEditor(props:EditorProps){
|
||||
let [title,setTitle] = useState(props.post?.title)
|
||||
let [projectID,setProjectID] = useState(props.post?.project_id)
|
||||
let textbox:any = useRef(undefined);
|
||||
|
||||
|
||||
function adjustHeight() {
|
||||
if(!textbox.current || !textbox.current.style) return
|
||||
textbox.current.style.height = "fit-content";
|
||||
@ -55,6 +63,31 @@ export default function PostEditor(props:EditorProps){
|
||||
<option value={0}>unassigned</option>
|
||||
{props.projects?.map(p=><option value={p.id}>{p.readableIdentifier}</option>)}
|
||||
</select>
|
||||
<h2>Attachments</h2>
|
||||
<table className="table table-striped">
|
||||
<thead>
|
||||
<tr><td>Buckets</td></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{
|
||||
(()=>{
|
||||
let bucketMap:Map<UUID,PostEditorBucket> = new Map(props.post.buckets.map((b)=>[b.id as UUID,b]));
|
||||
let bucketList = [...props.post.buckets.map((b)=>b.id)];
|
||||
return bucketList.map((e)=>{
|
||||
return <tr><Accordion><AccordionItem eventKey={bucketList.indexOf(e).toString()}><AccordionHeader>{e}</AccordionHeader><AccordionBody><ul>{bucketMap.get(e as UUID)?.attachments.map((attachment)=><li>{attachment.filename}</li>)}</ul></AccordionBody></AccordionItem></Accordion></tr>
|
||||
})
|
||||
})()
|
||||
}
|
||||
<tr>
|
||||
<td colSpan={4}>
|
||||
<table className="table mb-0">
|
||||
...
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
...
|
||||
</tbody>
|
||||
</table>
|
||||
<button type="button" className="m-2 btn btn-primary">Preview</button>
|
||||
<button type="button" className="m-2 btn btn-success" onClick={onClickSaveButton}>Save</button>
|
||||
<button type="button" className="m-2 btn btn-danger" onClick={onClickCancelButton}>Cancel</button>
|
||||
|
||||
@ -1,14 +1,13 @@
|
||||
cache: 'no-store'
|
||||
|
||||
import { tryFetchPosts } from "@/app/api/post/route";
|
||||
import { Post } from "@/model/Post";
|
||||
import { constructAPIUrl } from "@/util/Utils";
|
||||
import { ReactNode, useEffect } from "react";
|
||||
import TableGen from "../../../client/TableGen";
|
||||
import PostTable from "@/components/client/admin/PostTable";
|
||||
import { deletePost, getPosts, updatePost } from "@/app/lib/actions/entityManagement/postActions";
|
||||
import { getProjects } from "@/app/lib/actions/entityManagement/projectActions";
|
||||
import { Project } from "@/model/Project";
|
||||
import { Bucket, Project, Post, dbSync, Attachment } from "@/model/Models";
|
||||
|
||||
type Props = {
|
||||
children?:ReactNode
|
||||
@ -16,6 +15,8 @@ type Props = {
|
||||
|
||||
|
||||
export default async function PostView(props:Props){
|
||||
await dbSync;
|
||||
|
||||
const headings = [
|
||||
'#',
|
||||
'Title',
|
||||
@ -32,7 +33,8 @@ export default async function PostView(props:Props){
|
||||
getProjects,
|
||||
savePost:updatePost
|
||||
};
|
||||
const posts:Post[] = await Post.findAll().then(posts=>posts.map((e)=>JSON.parse(JSON.stringify(e))));
|
||||
|
||||
const posts:Post[] = await Post.findAll({include: {model: Bucket, include: {model: Attachment}}}).then(posts=>posts.map((e)=>JSON.parse(JSON.stringify(e))));
|
||||
const projects = await Project.findAll().then(projects=>projects.map((e)=>JSON.parse(JSON.stringify(e))));
|
||||
|
||||
return (
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
.header{
|
||||
display: flex;
|
||||
background-color: #008BC7;
|
||||
/* background-color: #008BC7; */
|
||||
flex-direction: row;
|
||||
flex-grow: 0;
|
||||
}
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import styles from "./header.module.css"
|
||||
|
||||
export default function Header() {
|
||||
return <div className={`${styles.header} pp`}>
|
||||
return <div className={`${styles.header} pp bg-primary`}>
|
||||
|
||||
<img src="/logo.png" width="80px" height="auto" alt="" />
|
||||
<div className={styles.headertitle}>
|
||||
<div className={`${styles.headertitle}`}>
|
||||
<div style={{flexGrow:1}}>Andreas<br/>Schaafsma</div>
|
||||
<div>>Software Developer</div>
|
||||
</div>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
.navbar{
|
||||
background-color: #136D94;
|
||||
/* background-color: #136D94; */
|
||||
flex-grow: 0;
|
||||
}
|
||||
.navItem{
|
||||
|
||||
@ -5,7 +5,7 @@ const navList = navItems.map(value => <a key={value} className={styles.navItem}>
|
||||
|
||||
|
||||
export default function Navbar() {
|
||||
return <nav className={`${styles.navbar}`}>
|
||||
return <nav className={`${styles.navbar} bg-secondary`}>
|
||||
<ul>{navList}</ul>
|
||||
</nav>
|
||||
}
|
||||
@ -2,25 +2,50 @@ import Tagbar from "@/components/shared/news/tagbar";
|
||||
import styles from "@/components/shared/news/article-preview.module.css"
|
||||
|
||||
import bg from "public/placeholder-square.png"
|
||||
import { ReactNode } from "react"
|
||||
import { DOMElement, JSXElementConstructor, ReactNode } from "react"
|
||||
import { Style } from "util";
|
||||
import Link from "next/link";
|
||||
import { redirect } from 'next/navigation';
|
||||
import { Router } from "next/router";
|
||||
import { useRouter } from 'next/navigation'
|
||||
import { truncateString } from "@/util/Utils";
|
||||
import { MDXRemote } from "next-mdx-remote/rsc";
|
||||
import { ExampleComponent } from "./article";
|
||||
import ReactDOM from "react-dom";
|
||||
import renderToString from 'react-dom/server'
|
||||
import { jsxToString } from "@/app/lib/jsxtostring";
|
||||
import remarkMdx from "remark-mdx";
|
||||
import { remark } from "remark";
|
||||
import strip from 'remark-mdx-to-plain-text';
|
||||
import { Post } from "@/model/Post";
|
||||
import { Attributes } from "@sequelize/core";
|
||||
|
||||
|
||||
type ArticlePreviewPost = Attributes<Post>
|
||||
type Props = {
|
||||
id?:string
|
||||
title?:string
|
||||
content?:string
|
||||
date?:string
|
||||
post:ArticlePreviewPost;
|
||||
}
|
||||
|
||||
|
||||
export default async function ArticlePreview(props:Props){
|
||||
const components = { ExampleComponent }
|
||||
const content = ["import ExampleComponent from './article';\n",props.post.content].join('\n');
|
||||
let stripped = ''
|
||||
remark()
|
||||
.use(remarkMdx)
|
||||
.use(strip)
|
||||
.process(content, (err:any, file:any):any => {
|
||||
if (err) throw err
|
||||
// console.log(String(file));
|
||||
stripped=String(file)
|
||||
return String(file)
|
||||
} )
|
||||
console.log(stripped)
|
||||
|
||||
export default function ArticlePreview(props:Props){
|
||||
// const parsedMDX = await MDXRemote({source:props.content,components:components});
|
||||
// const b = new ReactDOM.contain
|
||||
// const renderedMDX = ReactDOM.render(parsedMDX,)
|
||||
// console.log(eval(parsedMDX as any))
|
||||
// const a = jsxToString(renderedMDX);
|
||||
// console.log(parsedMDX);
|
||||
// if (!props.content)
|
||||
return (
|
||||
<section className={styles.previewbox}>
|
||||
@ -28,8 +53,8 @@ export default function ArticlePreview(props:Props){
|
||||
|
||||
<div className={`${styles.summary} flex flex-col justify-between p-0`}>
|
||||
<section className="w-[100%]">
|
||||
<span className="inline-block"><h2><Link href={`/article/${props.id}`}>{props.title}</Link></h2></span>
|
||||
<p>{truncateString(props.content,255)}</p>
|
||||
<span className="inline-block"><h2><Link href={`/article/${props.post.id}`}>{props.post.title}</Link></h2></span>
|
||||
<p>{truncateString(props.post.description? props.post.description : "No Description",255)}</p>
|
||||
</section>
|
||||
<Tagbar/>
|
||||
</div>
|
||||
|
||||
@ -4,7 +4,6 @@ import "/public/global.css"
|
||||
import "@/app/index.css"
|
||||
import styles from "./article.module.css"
|
||||
|
||||
import { serialize } from 'next-mdx-remote/serialize'
|
||||
import { MDXComponents, MDXContent } from "mdx/types";
|
||||
import { MDXRemote } from 'next-mdx-remote/rsc'
|
||||
|
||||
@ -20,14 +19,15 @@ export default async function Article(params: { id: string|undefined, title: str
|
||||
const components = { ExampleComponent }
|
||||
|
||||
return (
|
||||
<article id={`post-${params.id}`}>
|
||||
<h1 className=".article-title pl-5 pr-5">{params.title}</h1>
|
||||
<div className={`${styles.imagecontainer} m-5`}/>
|
||||
<div className="pl-5 pr-5"><Tagbar/></div>
|
||||
<div className=".article-content p-5">
|
||||
<MDXRemote
|
||||
source={params.content?params.content:""} components={components}
|
||||
/>
|
||||
<article id={`post-${params.id}`} className="bg-background-800 w-[80%] m-auto">
|
||||
<div id="image-container" className={`${styles.imagecontainer} flex flex-col`}>
|
||||
<h1 id="article-title" className=".article-title p-5 self-start">{params.title}</h1>
|
||||
<div id="spacer" className="flex flex-grow"></div>
|
||||
<div id="tagbar" className="p-5 self-start"><Tagbar/></div>
|
||||
|
||||
</div>
|
||||
<div className=".article-content p-5 whitespace-pre">
|
||||
<MDXRemote source={params.content?params.content:""} components={components}/>
|
||||
</div>
|
||||
<section className=".article-date">{params.date}</section> <br/>
|
||||
</article>
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
color: #C0F0FF;
|
||||
display:flex;
|
||||
flex-direction: row;
|
||||
background-color: #1E536A;
|
||||
/* background-color: #1E536A; */
|
||||
padding:8px;
|
||||
flex-grow: 1;
|
||||
}
|
||||
@ -6,7 +6,7 @@ interface Props {
|
||||
}
|
||||
|
||||
export default function PageContainer(props:Props) {
|
||||
return <div className={`${styles.pagecontainer}`}>
|
||||
return <div className={`${styles.pagecontainer} bg-background`}>
|
||||
{props.children}
|
||||
</div>;
|
||||
}
|
||||
@ -20,7 +20,7 @@ const sequelize = new Sequelize({
|
||||
});
|
||||
|
||||
|
||||
const dbSync = (async ()=> await sequelize.sync())().then(()=>{
|
||||
const dbSync = (async ()=> await sequelize.sync({alter:true}))().then(()=>{
|
||||
addUserScopes();
|
||||
addUserPermsScopes();
|
||||
});
|
||||
|
||||
@ -20,9 +20,11 @@ export class Post extends Model<InferAttributes<Post>, InferCreationAttributes<P
|
||||
declare id: CreationOptional<number>;
|
||||
|
||||
@Attribute(DataTypes.STRING)
|
||||
declare title:string
|
||||
declare title:string;
|
||||
@Attribute(DataTypes.STRING)
|
||||
declare content:string
|
||||
declare content:string;
|
||||
@Attribute(DataTypes.STRING)
|
||||
declare description?:CreationOptional<string>;
|
||||
|
||||
// Date thingies
|
||||
@CreatedAt
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user