implemented post management dashboard and started work on projects

This commit is contained in:
Andreas Schaafsma 2024-06-02 00:58:11 +02:00
parent 8c56a9421e
commit a0a938021d
29 changed files with 969 additions and 595 deletions

815
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,75 @@
'use server'
import { getCookieAuth } from "@/app/lib/actions";
import AdminPanel from "@/components/server/admin/adminPanel";
import ServerAdminPanel from "@/components/server/admin/ServerAdminPanel";
import AuthHandler from "@/components/server/admin/authHandler";
import Sidebar from "@/components/server/admin/views/sidebar";
import { cookies } from "next/headers";
import PostView from "@/components/server/admin/views/PostView";
import { ReactNode } from "react";
type Props = {
params: {
slug: string[]
};
}
export type SidebarEntry = {
label:string;
view:string;
}
function Home(){
return <div>home</div>
}
function PostManager(){
return <div>posts</div>
}
async function getViewMap():Promise<Map<string, JSX.Element>>{
return new Map([
['home', <Home></Home>],
['man-post', <PostView></PostView>]
]);
}
async function getSidebarEntries():Promise<Array<SidebarEntry>>{
return [
{ label: 'Home', view: 'home'},
{ label: 'Post Management', view: 'man-post'},
{ label: 'Project Management', view: 'man-proj'},
{ label: 'Tag Management', view: 'man-tags'},
{ label: 'User Management', view: 'man-user'},
]
}
async function getCurrentView(view:string):Promise<JSX.Element>{
const viewMap = await getViewMap();
const viewJSX = viewMap.get(view);
return viewJSX ? viewJSX : <Home></Home>;
}
export default async function Page(props:Props){
const sidebarEntries:Array<SidebarEntry> = await getSidebarEntries();
const slug:string|string[] = props.params.slug ? props.params.slug : 'home';
return (
<main className="h-screen w-screen flex flex-col p-0 bg-gray-300 box-border m-0">
<AuthHandler params={null}>
<Sidebar sidebarEntries={sidebarEntries} slug={slug.toString()}></Sidebar>
<AdminPanel slug={slug.toString()} auth={await getCookieAuth()}>
{await getCurrentView(slug.toString())}
</AdminPanel>
</AuthHandler>
{/* <section>{JSON.stringify(cookies().getAll())}</section> */}
</main>
);
}

View File

@ -1,4 +1,4 @@
import '../globals.css'
// import '../globals.css'
import { Inter } from 'next/font/google'
import StyledJsxRegistry from '../registry';
import Providers from '@/providers/providers';

View File

@ -1,12 +1,45 @@
import AdminPanel from "@/components/client/admin/adminPanel";
'use server'
import { getCookieAuth } from "@/app/lib/actions";
import AdminPanel from "@/components/server/admin/adminPanel";
import ServerAdminPanel from "@/components/server/admin/ServerAdminPanel";
import AuthHandler from "@/components/server/admin/authHandler";
import Sidebar from "@/components/server/admin/views/sidebar";
import { cookies } from "next/headers";
type Props = {
params: {
slug: string[]
};
}
export default async function Page(){
export type SidebarEntry = {
label:string;
view:string;
}
async function getSidebarEntries():Promise<Array<SidebarEntry>>{
return [
{ label: 'Home', view: 'home'},
{ label: 'Post Management', view: 'man-post'},
{ label: 'Project Management', view: 'man-proj'},
{ label: 'Tag Management', view: 'man-tags'},
{ label: 'User Management', view: 'man-user'},
]
}
export default async function Page(props:Props){
const sidebarEntries:Array<SidebarEntry> = await getSidebarEntries();
const slug:string|string[] = props.params.slug ? props.params.slug : 'home';
return (
<main className="h-screen w-screen flex flex-col p-0 bg-background-500 box-border m-0">
<AuthHandler params={null}><AdminPanel></AdminPanel></AuthHandler>
<AuthHandler params={null}>
<Sidebar sidebarEntries={sidebarEntries} slug={""}></Sidebar>
<ServerAdminPanel slug={slug.toString()} auth={await getCookieAuth()}></ServerAdminPanel>
</AuthHandler>
{/* <section>{JSON.stringify(cookies().getAll())}</section> */}
</main>
);

View File

@ -0,0 +1,14 @@
import AdminPanel from "@/components/client/admin/adminPanel";
import AuthHandler from "@/components/server/admin/authHandler";
import { cookies } from "next/headers";
import { Router } from "next/router";
export default async function Page(){
return (
<main className="h-screen w-screen flex flex-col p-0 bg-background-500 box-border m-0">
<AuthHandler params={null}><AdminPanel></AdminPanel></AuthHandler>
{/* <section>{JSON.stringify(cookies().getAll())}</section> */}
</main>
);
}

View File

@ -0,0 +1,92 @@
'use server'
import { APIError, attemptAPIAction } from "@/util/api/error";
import { Auth, Post, PostTag, Tag, User } from "@/model/Models";
import { cookies } from "next/headers";
async function tryCreateAttachment(request: Request) {
// Make sure the DB is ready
await PostTag.sync();
await Tag.sync();
await Post.sync();
// 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: [
{
model: User.withScope(['withPerms']),
attributes: {
exclude: ['username', 'password', 'updatedAt', 'createdAt']
}
}
],
where: { token: authObject.token }
});
// Sanity check the auth and associated user
if (!auth || !auth.user) throw new APIError({ status: 401, responseText: "Authentication Error" });
// Handle incomplete data or other problems
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 (!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)}` });
// Create a new Post in the database
const post = await Post.create(
{
content: requestBody.content,
user_id: auth.user.id,
title: requestBody.title,
},{
include: {
association: Post.associations.user
}
}).then(post=>post.reload())
// Return the response
return new Response(JSON.stringify(post), { status: 200 });
}
export async function tryFetchAttachments(request: Request) {
await Post.sync();
const foundPosts = await Post.findAll({
include: [
{
association: Post.associations.user,
attributes: { exclude: ['password', 'createdAt', 'updatedAt'] }
},{
association: Post.associations.postTags
}]
});
return new Response(JSON.stringify(foundPosts), { status: 200 });
}
export async function GET(request: Request) {
return await attemptAPIAction(tryFetchAttachments,request);
}
export async function POST(request: Request) {
return await attemptAPIAction(tryCreateAttachment,request);
}

View File

@ -1,6 +1,6 @@
'use server'
import { APIError } from "@/app/lib/api/error";
import { APIError } from "@/util/api/error";
import { Post } from "@/model/Models";

View File

@ -66,7 +66,7 @@ async function tryCreatePost(request: Request) {
async function tryFetchPosts(request: Request) {
export async function tryFetchPosts(request: Request) {
await Post.sync();

View File

@ -5,8 +5,10 @@ import { cookies } from "next/headers"
import { parseSetCookie } from "@/util/parseSetCookie";
import makeFetchCookie from 'fetch-cookie';
import fetchCookie from "fetch-cookie";
import { Attributes } from "@sequelize/core";
import { Attribute, Attributes } from "@sequelize/core";
import { User } from "@/model/User";
import { AuthProps } from "@/providers/providers";
import { Auth } from "@/model/Auth";
type LoginReturn = {
cookie?:unknown,
@ -80,6 +82,48 @@ export async function serverValidateSessionCookie(koek:string):Promise<boolean>
export async function userIsAdmin(user:Partial<Attributes<User>>):Promise<boolean>
{
const cookieAuthValue = await cookies().get('auth')?.value;
const cookieAuthSanitized = decodeURIComponent(cookieAuthValue ? cookieAuthValue: "");
if(!cookieAuthSanitized) return false;
const parsedAuth = JSON.parse(cookieAuthSanitized);
if(!parsedAuth.id || !parsedAuth.token || !parsedAuth.user_id) return false
const p:AuthProps = {
auth: {
id:parsedAuth.id,
token:parsedAuth.token,
user_id:parsedAuth.user_id
}
};
const foundAuth = await Auth.findOne({where: { id: p.auth?.id}});
if(!foundAuth || foundAuth.token != p.auth?.token ) return false;
return true;
}
export async function getCookieAuth():Promise<AuthProps>
{
const cookieAuthValue = await cookies().get('auth')?.value;
const cookieAuthSanitized = decodeURIComponent(cookieAuthValue ? cookieAuthValue: "");
if(!cookieAuthSanitized) return {}
const kd = JSON.parse(cookieAuthSanitized);
if(!kd.id || !kd.token || !kd.user_id) return {};
const foundAuth = await Auth.findOne({where: { id: kd.id},include:{model:User}});
if(!foundAuth) return {};
const authObject:AuthProps = {
auth: {
id:kd.id,
token:kd.token,
user_id:kd.user_id
},
user: await foundAuth.user
}
return authObject;
}
return false;
}

View File

@ -0,0 +1,15 @@
'use server';
import { Post } from "@/model/Post";
import { Attributes } from "@sequelize/core";
export async function deletePost(postID: number): Promise<boolean> {
const destroy = await Post.destroy({ where: { id: postID } });
return true;
}
export async function getPosts(): Promise<string> {
const posts = await Post.findAll();
return JSON.stringify(posts);
}

View File

@ -0,0 +1,24 @@
'use client'
import { ReactNode } from "react";
type Props = {
headings:Array<string>;
children:ReactNode;
}
export default function TableGen(props:Props){
return <>
<table className="table overflow-scroll">
<thead>
<tr>
{props.headings.map((h)=>
<th key={h} scope="col">{h}</th>
)}
</tr>
</thead>
<tbody>
{props.children}
</tbody>
</table>
</>
}

View File

@ -0,0 +1,80 @@
'use client'
import { ReactNode } from "react"
import TableGen from "../TableGen"
import { Attributes } from "@sequelize/core";
import { Post } from "@/model/Post";
import { useState } from "react";
type Actions = {
deletePost:any
getPosts:()=>Promise<string>
}
type Props = {
children?:ReactNode;
headings:Array<string>;
data:any[];
actions?:Actions;
}
type EditorProps = {
open:boolean;
post?:Attributes<Post>;
}
function RenderEditor(props:EditorProps){
let [content,setContent] = useState(props.post?.content)
let [title,setTitle] = useState(props.post?.title)
return <form className="bg-light w-[100%] h-content p-1">
<h1 className="m-2">Edit Post</h1>
<h2 className="m-2">Title</h2>
<input value={title} onChange={e => setTitle(e.target.value)} type='text' className="m-2"></input>
<h2 className="m-2">Content</h2>
<textarea value={content} onChange={e => setContent(e.target.value)} className="w-[100%] h-content align-top text-start text-base line-clamp-6 m-2"></textarea>
<button type="button" className="m-2 btn btn-primary">Preview</button>
<button type="button" className="m-2 btn btn-success">Save</button>
<button type="button" className="m-2 btn btn-danger">Cancel</button>
</form>
}
export default function PostTable(props:Props){
function showEditor(entry:Attributes<Post>){
setEditor({
open: true,
post: entry
})
}
const initEditorState:EditorProps = {
open: false
}
const [posts, setPosts] = useState(props.data);
const [editor, setEditor] = useState(initEditorState)
function deletePost(entry:Attributes<Post>){
props.actions?.deletePost(entry.id);
props.actions?.getPosts().then((p)=>setPosts(JSON.parse(p)));
}
return <>
<TableGen headings={props.headings}>
{posts.map((d)=>{
return <><tr key={d.id}>
<th scope="row">{d.id}</th>
<td key='titlefield'>{d.title}</td>
<td key='contentfield'>{d.content.length<255 ? d.content :`${d.content.substring(0,255)}...`}</td>
<td key='createdatfield'>{d.createdAt}</td>
<td key='updatedatfield'>{d.updatedAt}</td>
<td key='btnedit'><button type="button" className="btn btn-primary" onClick={()=>showEditor(d)}>Edit</button></td>
<td key='btndelete'><button type="button" className="btn btn-danger" onClick={()=>deletePost(d)}> Delete</button></td>
</tr>
{(editor.open && editor.post && editor.post.id == d.id)?
<tr key={'activeEditor'}><th scope="row" colSpan={props.headings.length}><RenderEditor open={editor.open} post={editor.post}></RenderEditor></th></tr>:""}
</>
})}
</TableGen>
</>
}

View File

@ -1,76 +0,0 @@
'use client'
import { ReactNode, useContext, useState } from "react";
import { AuthContext, AuthProps } from "@/providers/providers";
import SomeServerSubComponent from "@/components/server/admin/serverContextUserTest";
import PostView from "@/components/server/admin/views/PostView";
import Sidebar from "./views/sidebar";
import ClientPostView from "./views/ClientPostView";
import ServerComponentTest from "@/components/server/ServerComponentTest";
interface Props {
children?: ReactNode;
auth?: AuthProps;
}
export type SidebarEntry = {
label:string;
view:string;
}
export const sidebarEntries:Array<SidebarEntry> = [
{ label: 'Home', view: 'home'},
{ label: 'Post Management', view: 'man-post'},
{ label: 'Project Management', view: 'man-proj'},
{ label: 'Tag Management', view: 'man-tags'},
{ label: 'User Management', view: 'man-user'},
]
function Home(){
return <div>home</div>
}
function PostManager(){
return <div>posts</div>
}
const viewMap = new Map<string, ReactNode>([
['home', <Home></Home>],
['man-post', <ClientPostView></ClientPostView>]
])
export default function AdminPanel(props:Props){
const [view, setView] = useState((<Home></Home>) as ReactNode);
const switchView = function (value:string){
setView(viewMap.get(value));
}
return (
<div className="AdminPanelWrapper w-[100%] h-[100%] flex flex-row">
{/* <h1>Super Secret Admin Panel!</h1> */}
{/* <h2>this is where we use the context test:<SomeSubComponent></SomeSubComponent></h2> */}
{/* <SomeServerSubComponent></SomeServerSubComponent> */}
{/* <section> */}
{/* {props.children} */}
{/* <PostView></PostView> */}
{/* </section> */}
<Sidebar sidebarEntries={sidebarEntries} switchView={switchView}></Sidebar>
<div>{view}</div>
<ServerComponentTest></ServerComponentTest>
</div>
)
}
function SomeSubComponent(props:Props){
let { test, auth } = useContext(AuthContext);
return (
<span>{test}{JSON.stringify(auth)}</span>
);
}

View File

@ -1,16 +0,0 @@
'use client'
import ServerComponentTest from "@/components/server/ServerComponentTest";
import { ReactNode } from "react";
type Props = {
children?:ReactNode
}
export default function ClientPostView(props:Props){
return (
<div>
test
</div>
);
}

View File

@ -1,30 +0,0 @@
import './sidebar.css'
import { Button, NavLink } from 'react-bootstrap';
import { SidebarEntry } from '../adminPanel';
import React, { ReactNode, useState } from 'react';
type Props = {
children?:ReactNode;
sidebarEntries:Array<SidebarEntry>;
switchView:any;
}
export default function Sidebar(props:Props){
return (
<div className='w[100%] h[100%] bg-secondary-800'>
<ul className='nav nav-pills flex-column mb-auto container-fluid'>
{props.sidebarEntries.map((sidebarEntry)=>{
return <li className='nav-item'><NavLink className='nav-link bg-purple-400 m-2' onClick={(e)=>{props.switchView(sidebarEntry.view)}}>
{sidebarEntry.label}
</NavLink></li>
})}
</ul>
</div>
);
}

View File

@ -0,0 +1,17 @@
'use server'
import AdminPanel from "@/components/server/admin/adminPanel";
import { AuthProps } from "@/providers/providers";
import { ReactNode } from "react";
interface Props {
children?: ReactNode;
auth?: AuthProps;
slug?: string;
}
export default async function ServerAdminPanel(props:Props){
return <AdminPanel slug={props.slug?props.slug:'home'} auth={props.auth}>{props.children}</AdminPanel>
}

View File

@ -0,0 +1,35 @@
'use server'
import { ReactNode, useContext, useState } from "react";
import { AuthProps } from "@/providers/providers";
import SomeServerSubComponent from "@/components/server/admin/serverContextUserTest";
import Sidebar from "./views/sidebar";
import PostView from "./views/PostView";
interface Props {
children?: ReactNode;
auth?: AuthProps;
slug?: string;
}
export default async function AdminPanel(props:Props){
const slug = props.slug ? props.slug : 'home'
return (
<div className="AdminPanelWrapper w-[100%] h-[100%] flex flex-row m-auto">
{/* <h1>Super Secret Admin Panel!</h1> */}
{/* <h2>this is where we use the context test:<SomeSubComponent></SomeSubComponent></h2> */}
{/* <SomeServerSubComponent></SomeServerSubComponent> */}
{/* <section> */}
{/* {props.children} */}
{/* <PostView></PostView> */}
{/* </section> */}
{props.children}
{/* <div>{JSON.stringify(props.auth)}</div> */}
</div>
)
}

View File

@ -2,7 +2,7 @@
import { cookies } from "next/headers";
import LoginForm from "@/components/client/admin/loginForm";
import AdminPanel from "@/components/client/admin/adminPanel";
import AdminPanel from "@/components/server/admin/adminPanel";
import ClientAuthHandler from "@/components/client/admin/clientAuthHandler";
import { serverValidateSessionCookie } from "@/app/lib/actions";
@ -23,13 +23,11 @@ export default async function AuthHandler(props: Props) {
const koek = decodeURIComponent(protoKoek ? protoKoek: "");
console.log("koekje:" + koek)
let p:AuthProps = {
test:"not pog"
};
if(koek){
const kd = JSON.parse(koek);
if(kd.id && kd.token && kd.user_id){
p = {
test:"success!",
auth: {
id:kd.id,
token:kd.token,

View File

@ -1,47 +0,0 @@
'use server'
import { cookies } from "next/headers";
import LoginForm from "@/components/client/admin/loginForm";
import AdminPanel from "@/components/client/admin/adminPanel";
import ClientAuthHandler from "@/components/client/admin/clientAuthHandler";
import { serverValidateSessionCookie } from "@/app/lib/actions";
import { constructAPIUrl } from "@/util/Utils";
import { ReactNode } from "react";
import { AuthContext, AuthProps } from "@/providers/providers";
interface Props {
children?: ReactNode;
params?: any;
requiredRole?: number;
} // We interfacing lads
export default async function AuthHandler(props: Props) {
const protoKoek = await cookies().get('auth')?.value;
const koek = decodeURIComponent(protoKoek ? protoKoek: "");
console.log("koekje:" + koek)
let p:AuthProps = {
test:"not pog"
};
if(koek){
const kd = JSON.parse(koek);
if(kd.id && kd.token && kd.user_id){
p = {
test:"success!",
auth: {
id:kd.id,
token:kd.token,
user_id:kd.user_id
}
}
}
}
return (
<div className="flex flex-row">
{!(koek && await serverValidateSessionCookie(koek)) ? <LoginForm>{ }</LoginForm> : <ClientAuthHandler authProps={p}><section>{props.children}</section></ClientAuthHandler>}
</div>
);
}

View File

@ -0,0 +1,10 @@
export default async function(){
<form className="bg-light w-[100%] h-[100%]">
<h1>Edit Post</h1>
<h2>Title</h2>
<input type='text'></input>
</form>
}

View File

@ -1,21 +1,35 @@
'use server'
import { ReactNode } from "react"
import AuthHandler from "../authHandler"
import { Post } from "@/model/Post"
import { constructAPIUrl } from "@/util/Utils"
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 } from "@/app/lib/postActions";
type Props = {
children?:ReactNode
}
export default async function PostView(props:Props){
// const posts = await Post.findAll();
export default async function PostView(props:Props){
const headings = [
'#',
'Title',
'Content',
'Date Created',
'Date Modified',
'Edit',
'Delete',
]
const data = await Post.findAll();
const passData:any[] = data.map((e)=>JSON.parse(JSON.stringify(e)));
return (
<div>
test
<div className="w-[100%] min-h-fit bg-gray-100 overflow-scroll">
<span className="flex flex-row flex-grow w-[100%] pl-2 pr-2"><h1 className="p-2 inline-block">Post Management</h1><section className="flex-grow"></section><button className='btn btn-success h-12 mt-auto mb-auto self-end'>New</button></span>
<div className="w-[100%] m-auto">
<PostTable data={passData} headings={headings} actions={{deletePost: deletePost, getPosts:getPosts}}></PostTable>
</div>
</div>
);
}

View File

@ -0,0 +1,33 @@
import './sidebar.css'
import { Button, NavLink } from 'react-bootstrap';
import { SidebarEntry } from '@/app/admin/page';
import React, { ReactNode, useState } from 'react';
import Link from 'next/link';
import { headers } from 'next/headers';
type Props = {
children?:ReactNode;
sidebarEntries:Array<SidebarEntry>;
slug:string
}
export default async function Sidebar(props:Props){
return (
<div className='w-fit h[100%]'>
<ul className={`navbar-light bg-light nav nav-pills flex-column mb-auto container-fluid h-[100%] items-start justify-start p-0 w-fit`}>
{props.sidebarEntries.map((sidebarEntry)=>{
return <li key={sidebarEntry.view} className='nav-item w-[100%]'><Link className={`nav-link m-2 whitespace-nowrap outline outline-1 ${(props.slug == sidebarEntry.view) ? 'active' : ''}`} href={`/admin/${sidebarEntry.view}`}>
{sidebarEntry.label}
</Link></li>
})}
</ul>
</div>
);
}

View File

@ -1,9 +1,10 @@
import { Association, BelongsToGetAssociationMixin, CreationOptional, DataTypes, ForeignKey, InferAttributes, InferCreationAttributes, Model, NonAttribute, Sequelize } from "@sequelize/core";import { User } from "./User";
import { SqliteDialect } from '@sequelize/sqlite3';
import { Attribute, AutoIncrement, BelongsTo, BelongsToMany, CreatedAt, HasMany, NotNull, PrimaryKey, Unique, UpdatedAt } from "@sequelize/core/decorators-legacy";
import { Attribute, AutoIncrement, BelongsTo, BelongsToMany, CreatedAt, Default, HasMany, NotNull, PrimaryKey, Unique, UpdatedAt } from "@sequelize/core/decorators-legacy";
import { Tag } from "./Tag";
import { PostTag } from "./PostTag";
import { Project } from "./Project";
export class Post extends Model<InferAttributes<Post>, InferCreationAttributes<Post>> {
@ -14,9 +15,7 @@ export class Post extends Model<InferAttributes<Post>, InferCreationAttributes<P
@AutoIncrement
@Unique
declare id: CreationOptional<number>;
@Attribute(DataTypes.INTEGER)
@NotNull
declare user_id:ForeignKey<User['id']>;
@Attribute(DataTypes.STRING)
declare title:string
@Attribute(DataTypes.STRING)
@ -31,10 +30,19 @@ export class Post extends Model<InferAttributes<Post>, InferCreationAttributes<P
// Associatoins
@Attribute(DataTypes.INTEGER)
@NotNull
declare user_id:ForeignKey<User['id']>;
@Attribute(DataTypes.INTEGER)
declare project_id?:CreationOptional<ForeignKey<User['id']>>;
@BelongsTo(()=>User, { foreignKey: 'user_id', inverse: { type: 'hasMany', as: 'posts' } })
declare user:NonAttribute<User>;
@BelongsTo(()=>Project, { inverse: { type: 'hasMany', as: 'posts' } })
declare project:NonAttribute<User>;
@BelongsToMany(()=>Tag, { through: { model: ()=>PostTag, unique: false}, inverse: {as: 'taggedPosts'} })
declare postTags?:NonAttribute<Tag[]>;
@ -42,6 +50,7 @@ export class Post extends Model<InferAttributes<Post>, InferCreationAttributes<P
declare static associations: {
user: Association<User, Post>;
project: Association<Project, Post>;
postTags: Association<Tag, Post>;
};
}

View File

@ -4,20 +4,7 @@ import { SqliteDialect } from '@sequelize/sqlite3';
import { Attribute, AutoIncrement, PrimaryKey, Unique } from "@sequelize/core/decorators-legacy";
import { Post } from "./Post";
export type ProjectAttributes = {
id: number;
title: string;
description: string;
date: number;
user_id:ForeignKey<User['id']>;
}
export type ProjectCreationAttributes = {
title: string;
description: string;
date: number;
user_id:number;
}
export class Project extends Model<ProjectAttributes, ProjectCreationAttributes> {
export class Project extends Model<InferAttributes<Project>, InferCreationAttributes<Project>> {
@Attribute(DataTypes.INTEGER) @PrimaryKey @Unique @AutoIncrement
declare id: number;
@Attribute(DataTypes.STRING) @Unique
@ -27,7 +14,6 @@ export class Project extends Model<ProjectAttributes, ProjectCreationAttributes>
declare static associations: {
posts: Association<Post, Project>;
};
}

View File

@ -7,13 +7,10 @@ import { Attributes, InferAttributes } from "@sequelize/core";
export type AuthProps = {
test: string;
auth?: Attributes<Auth>
user?: Attributes<User>
}
let p: AuthProps = {
test: "lorem",
}
let p: AuthProps = {}
export type AdminViewProps = {
view: string;
@ -27,7 +24,6 @@ export const AdminViewContext = createContext(avp);
export const AuthContext = createContext(p);
interface Props {
children?: ReactNode;
params?: any;
@ -35,6 +31,6 @@ interface Props {
export default function Providers(props:Props){
return (
<AuthContext.Provider value={{test:"freek"}}><AdminViewContext.Provider value={avp}>{props.children}</AdminViewContext.Provider></AuthContext.Provider>
<AuthContext.Provider value={{}}><AdminViewContext.Provider value={avp}>{props.children}</AdminViewContext.Provider></AuthContext.Provider>
)
}

View File

@ -1,3 +1,5 @@
'server only'
import { hash, compare } from "bcrypt";

View File

@ -1,5 +1,6 @@
'server only'
import Gens from "./gens";
import Auth from "./Auth";
// import Auth from "./Auth";
function getAPIEnv(){
@ -27,4 +28,4 @@ function truncateString(str:string = '', num:number = 255) {
}
export { Gens, Auth, constructAPIUrl, constructUrl, truncateString }
export { Gens, constructAPIUrl, constructUrl, truncateString }

View File

@ -24,6 +24,6 @@
"@/*": ["./src/*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", "src/app/admin/page.tsx.bak", "src/app/admin/[...slug]/page.tsx.bak"],
"exclude": ["node_modules"]
}