aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/components/Form.astro7
-rw-r--r--src/components/Image.astro21
-rw-r--r--src/components/Post.astro28
-rw-r--r--src/components/Thread.astro82
-rw-r--r--src/components/Thread.svelte105
-rw-r--r--src/layouts/Default.astro4
-rw-r--r--src/layouts/ThreadLayout.astro22
-rw-r--r--src/lib/api.ts2
-rw-r--r--src/lib/image.ts4
-rw-r--r--src/lib/thread.ts42
-rw-r--r--src/pages/board/[board].astro22
-rw-r--r--src/pages/board/[board]/[tid].astro28
-rw-r--r--src/pages/create/[board].astro5
-rw-r--r--src/pages/create/[board]/[tid].astro27
-rw-r--r--src/pages/create/comment.ts17
-rw-r--r--src/pages/create/thread.ts5
-rw-r--r--src/styles/blackbox.css4
-rw-r--r--src/styles/thread.css4
18 files changed, 273 insertions, 156 deletions
diff --git a/src/components/Form.astro b/src/components/Form.astro
index 417b569..540a4d4 100644
--- a/src/components/Form.astro
+++ b/src/components/Form.astro
@@ -1,7 +1,11 @@
---
-import '../styles/blackbox.css';
import { sha256 } from 'js-sha256';
+export interface Props {
+ board: string;
+ tid?: string
+}
+
const { board, tid } = Astro.props;
const iphash = sha256(Astro.clientAddress);
---
@@ -31,6 +35,7 @@ const iphash = sha256(Astro.clientAddress);
if(r.status == 200) {
alert('Thread Successfuly Posted');
let id = await r.text();
+ if(id == 'close') window.top.close();
window.location.assign(`/board/${board}/${id}`);
}
else alert('An Error has Accured');
diff --git a/src/components/Image.astro b/src/components/Image.astro
new file mode 100644
index 0000000..07dbadf
--- /dev/null
+++ b/src/components/Image.astro
@@ -0,0 +1,21 @@
+---
+export interface Props {
+ image: string;
+ fileType: string;
+}
+
+const { image, fileType } = Astro.props;
+---
+
+{(image!= null) && (
+ (fileType == 'image') ? (
+ <a href={image} target="_blank" rel="noopener noreferrer">
+ <img src={image} alt={image} height="300px" width="300px"> <br>
+ </a>
+ ) : (
+ (fileType == 'image') && (
+ <video width="320" height="240" controls muted>
+ <source src={image}>
+ </video>
+ ))
+)} \ No newline at end of file
diff --git a/src/components/Post.astro b/src/components/Post.astro
new file mode 100644
index 0000000..6805846
--- /dev/null
+++ b/src/components/Post.astro
@@ -0,0 +1,28 @@
+---
+import { creatorColor, formatTime } from '../lib/util';
+
+export interface Props {
+ id: string;
+ date: number;
+ creator: string;
+ box: string;
+ board: string
+}
+
+const { id, date, creator, box, board = '' } = Astro.props;
+---
+<div class={box} id={id}>
+ <span style="line-height: 2rem;">
+ {(board != '') ? (
+ <a href=`/board/${board}/${id}` style="font-family: mono">{id}</a>
+ ) : (
+ <span style="font=family: mono">{id}</span>
+ )}
+
+ at {formatTime(date)} <br>
+ -> <span style=`${creatorColor(creator)}; font-family: mono`>
+ {creator}
+ </span> <br>
+ </span> <hr>
+ <slot />
+</div>
diff --git a/src/components/Thread.astro b/src/components/Thread.astro
new file mode 100644
index 0000000..6fae3de
--- /dev/null
+++ b/src/components/Thread.astro
@@ -0,0 +1,82 @@
+---
+import type Thread from '../models/Thread';
+import Post from './Post.astro';
+import Image from './Image.astro';
+
+export interface Props {
+ thread: Thread;
+ board: string;
+ comments: boolean;
+}
+
+const { thread, board, comments = false } = Astro.props;
+
+let replies: string[] = [];
+const listReplies = (id: string, getReplies: boolean = false): any => {
+ if(getReplies) return replies;
+
+ replies = [];
+ thread.comments.forEach(comment => {
+ if(comment.commentText.includes(id))
+ replies.push(comment.id);
+ })
+
+ if(replies.length <= 0) return false;
+ return true;
+}
+---
+
+{(thread.id != "rules") && ( <>
+ <Post id={thread.id} date={thread.creationDate} creator={thread.threadCreator} box="threadbox" board={(!comments) ? board : ''}>
+
+ {comments && (listReplies(thread.id) && (
+ <span class="small-mono">
+ {listReplies(thread.id, true).map((id) => ( <>
+ <a href=`/board/${board}/${thread.id}#${id}` onmouseover=`onMouseOver('${id}')` onmouseleave=`onMouseLeave('${id}')`>>>{id}</a>&#65279;
+ </> ))}
+ </span> <hr>
+ ))}
+
+
+ <h3>{thread.threadName}</h3>
+ <Image image={thread.imageId} fileType={thread.fileType} />
+ <p set:html={thread.threadText} />
+
+ {comments && ( <>
+ {thread.comments.map((comment) => ( <>
+ <Post id={comment.id} date={comment.creationDate} creator={comment.commentCreator} box="commentbox">
+
+ {listReplies(comment.id) && (
+ <span class="small-mono">
+ {listReplies(comment.id, true).map((id) => ( <>
+ <a href=`/board/${board}/${thread.id}#${id}` onmouseover=`onMouseOver('${id}')` onmouseleave=`onMouseLeave('${id}')`>>>{id}</a>&#65279;
+ </> ))}
+ </span> <hr>
+ )}
+
+ <Image image={comment.imageId} fileType={comment.fileType} />
+ <p set:html={comment.commentText} />
+
+ </Post>
+ </> ))}
+ </> )}
+
+ </Post>
+</> )}
+
+{comments && ( <>
+ <script is:inline>
+ function onMouseOver(id) {
+ document.getElementById(id).classList.add('targeted');
+ }
+ function onMouseLeave(id) {
+ document.getElementById(id).classList.remove('targeted');
+ }
+ </script>
+
+ <style is:inline>
+ .small-mono {
+ display:inline-block; line-height: 2ch; font-size: 0.8rem; font-family: monospace;
+ }
+ </style>
+</> )}
diff --git a/src/components/Thread.svelte b/src/components/Thread.svelte
deleted file mode 100644
index 0321b8d..0000000
--- a/src/components/Thread.svelte
+++ /dev/null
@@ -1,105 +0,0 @@
-<script lang="ts">
- import { creatorColor, formatTime} from '../lib/util';
- import type Thread from '../models/Thread';
-
- export let thread: Thread;
- export let board: string;
- export let comments: boolean = false;
-
- let replies: string[] = [];
- const listReplies = (id: string, getReplies: boolean = false): any => {
- if(getReplies) return replies;
-
- replies = [];
- thread.comments.forEach(comment => {
- if(comment.commentText.includes(id))
- replies.push(comment.id);
- })
-
- if(replies.length <= 0) return false;
- return true
- }
-
-</script>
-
-{#if thread.id != "rules"}
- <div class="threadbox" id="{thread.id}">
- <span style="line-height: 2rem;">
- <a href="/board/{board}/{thread.id}" style="font-family: mono">{thread.id}</a>
- at {formatTime(thread.creationDate)} <br>
-
- -> <span style="{creatorColor(thread.threadCreator )}; font-family: mono">
- {thread.threadCreator}
- </span > <br>
- <hr>
-
- {#if comments}
- {#if listReplies(thread.id) }
- <span style=" display:inline-block; line-height: 2ch; font-size: 0.8rem; font-family: monospace;">
- {#each listReplies(thread.id, true) as id}
- <a href="/board/{board}/{thread.id}#{id}" onmouseover="document.getElementById('{id}').classList.add('targeted')" onmouseleave="document.getElementById('{id}').classList.remove('targeted')">>>{id}</a> &#xfeff
- {/each}
- </span> <hr>
- {/if}
- {/if}
-
- </span>
-
- <h3>{thread.threadName}</h3>
-
- {#if thread.imageId!= null && thread.imageId != undefined}
- {#if thread.fileType == 'image'}
- <a href="{thread.imageId}" target="_blank" rel="noopener noreferrer">
- <img src="{thread.imageId}" alt="{thread.imageId}" height="300px" width="300px"> <br>
- </a>
- {:else if thread.fileType == 'video'}
- <video width="320" height="240" controls muted>
- <source src="{thread.imageId}">
- </video>
- {/if}
- {/if}
-
-<p>{@html thread.threadText}</p>
-
-{#if comments}
- {#each thread.comments as comment}
- <div class="commentbox" id="{comment.id}">
- <span style="line-height: 2rem;">
- <span style="font-family: mono">{comment.id}</span>
- at {formatTime(comment.creationDate)} <br>
-
- -> <span style="{creatorColor(comment.commentCreator)}; font-family: mono">
- {comment.commentCreator}
- </span> <br>
- <hr>
-
- {#if listReplies(comment.id)}
- <span style=" display:inline-block; line-height: 2ch; font-size: 0.8rem; font-family: monospace;">
- {#each listReplies(comment.id, true) as id}
- <a href="/board/{board}/{thread.id}#{id}" onmouseover="document.getElementById('{id}').classList.add('targeted')" onmouseleave="document.getElementById('{id}').classList.remove('targeted')">>>{id}</a> &#xfeff
- {/each}
- </span> <hr>
- {/if}
-
- </span>
-
- {#if comment.imageId!= null && comment.imageId != undefined}
- {#if comment.fileType == 'image'}
- <a href="{comment.imageId}" target="_blank" rel="noopener noreferrer">
- <img src="{comment.imageId}" alt="{comment.imageId}" height="300px" width="300px"> <br>
- </a>
- {:else if comment.fileType == 'video'}
- <video width="320" height="240" controls muted>
- <source src="{comment.imageId}">
- </video>
- {/if}
- {/if}
-
-<p>{@html comment.commentText}</p>
-
- </div>
- {/each}
-{/if}
-
- </div>
-{/if}
diff --git a/src/layouts/Default.astro b/src/layouts/Default.astro
index 3c0b6ff..ae59edb 100644
--- a/src/layouts/Default.astro
+++ b/src/layouts/Default.astro
@@ -2,13 +2,10 @@
const { title } = Astro.props as Props;
---
-<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
- <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
- <meta name="generator" content={Astro.generator} />
<title>{title}</title>
</head>
<body>
@@ -19,6 +16,5 @@ const { title } = Astro.props as Props;
<style>
html {
font-family: sans-serif;
- padding-left: 1em;
}
</style>
diff --git a/src/layouts/ThreadLayout.astro b/src/layouts/ThreadLayout.astro
new file mode 100644
index 0000000..24aba41
--- /dev/null
+++ b/src/layouts/ThreadLayout.astro
@@ -0,0 +1,22 @@
+---
+const { title } = Astro.props as Props;
+---
+
+<html lang="en">
+ <head>
+ <meta charset="UTF-8" />
+ <meta name="viewport" content="width=device-width" />
+ <title>{title}</title>
+ </head>
+ <body>
+ <div style="max-width: 70%;">
+ <slot />
+ </div>
+ </body>
+</html>
+
+<style>
+ html {
+ font-family: sans-serif;
+ }
+</style>
diff --git a/src/lib/api.ts b/src/lib/api.ts
index 645fc23..e6ac0f1 100644
--- a/src/lib/api.ts
+++ b/src/lib/api.ts
@@ -1,7 +1,7 @@
const base = 'https://localhost:5001/api'
export async function api(method: string, resource: string, data?: any) {
- console.log("API USED", method, resource, data);
+ // console.log("API USED", method, resource, data);
return await fetch(`${base}/${method}/${resource}`, {
method,
headers: {
diff --git a/src/lib/image.ts b/src/lib/image.ts
index c7d4d49..6ab20a5 100644
--- a/src/lib/image.ts
+++ b/src/lib/image.ts
@@ -20,8 +20,8 @@ export async function postImg(img: string) {
let filename = `${uuidV4()}.${fileExt}`;
//save file in this server
- writeFileSync(`dist/client/images/${filename}`, img_b64, "base64");
- // writeFileSync(`public/images/${filename}`, img_b64, "base64");
+ // writeFileSync(`dist/client/images/${filename}`, img_b64, "base64");
+ writeFileSync(`public/images/${filename}`, img_b64, "base64");
let data = {
'name': filename,
diff --git a/src/lib/thread.ts b/src/lib/thread.ts
index e0f0aa4..2199318 100644
--- a/src/lib/thread.ts
+++ b/src/lib/thread.ts
@@ -8,8 +8,8 @@ export async function processThreadIn(board: string, thread: Thread, comments =
if(!thread || !board) return;
let imageId: string = thread.imageId;
- if(existsSync(`dist/client/images/${imageId}`))
- // if(existsSync(`public/images/${imageId}`))
+ // if(existsSync(`dist/client/images/${imageId}`))
+ if(existsSync(`public/images/${imageId}`))
thread.imageId = `/images/${imageId}`;
else
thread.imageId = await getImg(imageId);
@@ -21,8 +21,8 @@ export async function processThreadIn(board: string, thread: Thread, comments =
for(let comment of thread.comments)
{
let cimageId = comment.imageId;
- if(existsSync(`dist/client/images/${cimageId}`))
- // if(existsSync(`public/images/${cimageId}`))
+ // if(existsSync(`dist/client/images/${cimageId}`))
+ if(existsSync(`public/images/${cimageId}`))
comment.imageId = `/images/${cimageId}`;
else
comment.imageId = await getImg(cimageId);
@@ -32,22 +32,34 @@ export async function processThreadIn(board: string, thread: Thread, comments =
}
export async function processThreadOut(form: any): Thread {
- let img = form.get('image').toString();
-
- let t: Thread = {};
- t.id = uuidV4();
- t.ThreadName = form.get('ThreadName').toString();
- t.ThreadCreator = uuidV5(form.get('iphash'), uuidNIL);
- t.ThreadText = form.get('ThreadText').toString();
- t.Comments = [];
- t.CreationDate = Date.now();
- t.ImageId = await postImg(img);
- t.FileType = getImgType(img);
+ let img = form.get('image');
+
+ let t: Thread = {
+ id: uuidV4(),
+ threadName: form.get('ThreadName'),
+ threadCreator: uuidV5(form.get('iphash'), uuidNIL),
+ threadText: form.get('ThreadText'),
+ comments: [],
+ creationDate: Date.now(),
+ imageId: await postImg(img),
+ fileType: getImgType(img),
+ }
return t;
}
export async function processCommentOut(form: any): Comment {
+ let img = form.get('image');
+
+ let c: Comment = {};
+ c.id = uuidV4();
+ c.commentCreator = uuidV5(form.get('iphash'), uuidNIL);
+ c.commentText = form.get('CommentText');
+ c.creationDate = Date.now();
+ c.imageId = await postImg(img);
+ c.fileType = getImgType(img);
+
+ return c;
}
function replaceURLs(text: string, board: string, OPtid?: string): string {
diff --git a/src/pages/board/[board].astro b/src/pages/board/[board].astro
index a529d3c..eaea03e 100644
--- a/src/pages/board/[board].astro
+++ b/src/pages/board/[board].astro
@@ -1,8 +1,9 @@
---
-import Default from '../../layouts/Default.astro';
-import Thread from '../../components/Thread.svelte'
import '../../styles/thread.css'
-import '../../styles/blackbox.css?'
+import '../../styles/blackbox.css'
+
+import ThreadLayout from '../../layouts/ThreadLayout.astro';
+import Thread from '../../components/Thread.astro'
import type Thread from '../../models/Thread';
import { api } from '../../lib/api.ts';
@@ -18,8 +19,11 @@ for(let thread of threads)
await processThreadIn(board, thread);
---
-<Default>
- <h1><a href="/boards"> {board} </a></h1>
+<ThreadLayout>
+ <h1 style="text-align:center">
+ <a href=`/boards`>{board}</a>
+ </h1>
+
<div class="blackbox">
<button style="left: 50%; position: relative; transform: translate(-50%, 0);" onclick=`window.location='/create/${board}'`>Create Thread</button>
</div>
@@ -27,10 +31,4 @@ for(let thread of threads)
{threads.map((thread) => (
<Thread thread={thread} board={board} />
))}
-</Default>
-
-<style is:inline>
- :root {
- --wdt: 600px;
- }
-</style>
+</ThreadLayout>
diff --git a/src/pages/board/[board]/[tid].astro b/src/pages/board/[board]/[tid].astro
index 4aa34ef..e9b345a 100644
--- a/src/pages/board/[board]/[tid].astro
+++ b/src/pages/board/[board]/[tid].astro
@@ -1,14 +1,16 @@
---
-import Default from '../../../layouts/Default.astro';
-import Thread from '../../../components/Thread.svelte'
-import '../../../styles/thread.css'
-import type Thread from '../../../models/Thread';
+import '../../../styles/thread.css';
+import '../../../styles/blackbox.css';
+
+import ThreadLayout from '../../../layouts/ThreadLayout.astro';
+import Thread from '../../../components/Thread.astro'
+import type Thread from '../../../models/Thread';;
import { api } from '../../../lib/api';
import { processThreadIn } from '../../../lib/thread';
-const { board } = Astro.params;
-const data = await api('get', `thread/${board}/${Astro.params.tid}`);
+const { board, tid } = Astro.params;
+const data = await api('get', `thread/${board}/${tid}`);
if(data.status === 404) return Astro.redirect('/404');
@@ -16,6 +18,16 @@ const thread: Thread = await data.json();
await processThreadIn(board, thread, true);
---
-<Default>
+<ThreadLayout>
+ <h1 style="text-align:center">
+ <a href=`/board/${board}`>{board}</a>
+ </h1>
+
+ <div class="blackbox">
+ <button style="left: 50%; position: relative; transform: translate(-50%, 0);" onclick=`window.open('/create/${board}/${tid}','popUpWindow','height=500,width=600')`>
+ Create Comment
+ </button>
+ </div>
+
<Thread thread={thread} board={board} comments=true />
-</Default> \ No newline at end of file
+</ThreadLayout> \ No newline at end of file
diff --git a/src/pages/create/[board].astro b/src/pages/create/[board].astro
index 9c2308f..152277c 100644
--- a/src/pages/create/[board].astro
+++ b/src/pages/create/[board].astro
@@ -1,4 +1,6 @@
---
+import '../../styles/blackbox.css';
+
import Default from '../../layouts/Default.astro';
import Form from '../../components/Form.astro';
@@ -8,7 +10,7 @@ const { board } = Astro.params;
<Default>
<h1>{board}</h1>
- <Form board={board} tid="niggers">
+ <Form board={board} tid="">
<form id="form" method="post" action="/create/thread" onsubmit="document.getElementById('submit-button').disabled = true">
<textarea name="ThreadName" placeholder="Thread Name" style="height: 1.5rem; width: 350px;"></textarea> <br>
<textarea name="ThreadText" placeholder="Thread Contents" style="height: 150px; width: 350px;"></textarea>
@@ -21,5 +23,6 @@ const { board } = Astro.params;
<style>
:root {
--wdt: 360px;
+ --ml: 0px;
}
</style>
diff --git a/src/pages/create/[board]/[tid].astro b/src/pages/create/[board]/[tid].astro
new file mode 100644
index 0000000..ccc95ca
--- /dev/null
+++ b/src/pages/create/[board]/[tid].astro
@@ -0,0 +1,27 @@
+---
+import '../../../styles/blackbox.css';
+
+import Default from '../../../layouts/Default.astro';
+import Form from '../../../components/Form.astro';
+
+const { board, tid } = Astro.params;
+---
+
+<Default>
+ <h1>Comment</h1>
+
+ <Form board={board} tid={tid}>
+ <form id="form" method="post" action="/create/comment" onsubmit="document.getElementById('submit-button').disabled = true">
+ <textarea name="CommentText" placeholder="Comment Contents" style="height: 150px; width: 350px;"></textarea>
+ <br> <input id="submit-button" type="submit" value="Create Thread" />
+ <input id="image" type="file" accept=".png,.jpg,.gif,.bmp,.mp4" />
+ </form>
+ </Form>
+</Default>
+
+<style>
+ :root {
+ --wdt: 360px;
+ --ml: 0px;
+ }
+</style>
diff --git a/src/pages/create/comment.ts b/src/pages/create/comment.ts
new file mode 100644
index 0000000..f8d4c82
--- /dev/null
+++ b/src/pages/create/comment.ts
@@ -0,0 +1,17 @@
+import { api } from '../../lib/api';
+import { processCommentOut } from '../../lib/thread';
+import Comment from '../../models/Thread';
+
+export async function post({ request }) {
+ const form = await request.formData();
+
+ let c: Comment = await processCommentOut(form);
+
+ console.log(c);
+
+ await api('post', `comment/${form.get('board')}/${form.get('tid')}`, JSON.stringify(c));
+
+ return new Response('close', {
+ status: 200
+ });
+}
diff --git a/src/pages/create/thread.ts b/src/pages/create/thread.ts
index 0a0b7d1..b3a02be 100644
--- a/src/pages/create/thread.ts
+++ b/src/pages/create/thread.ts
@@ -1,13 +1,14 @@
import { api } from '../../lib/api';
import { processThreadOut } from '../../lib/thread';
+import Thread from '../../models/Thread';
export async function post({ request }) {
const form = await request.formData();
- console.log(form);
-
let t: Thread = await processThreadOut(form);
+ console.log(t);
+
await api('post', `thread/${form.get('board')}`, JSON.stringify(t));
return new Response(t.id, {
diff --git a/src/styles/blackbox.css b/src/styles/blackbox.css
index 4a0e63f..4ddcb85 100644
--- a/src/styles/blackbox.css
+++ b/src/styles/blackbox.css
@@ -1,8 +1,8 @@
.blackbox {
- width: var(--wdt);
+ max-width: var(--wdt, 100%);
border: 10px solid black;
padding: 10px;
margin: 10px;
- margin-left: 0px;
+ margin-left: var(--ml, 10px);
background-color: white;
}
diff --git a/src/styles/thread.css b/src/styles/thread.css
index 14997de..2667d6f 100644
--- a/src/styles/thread.css
+++ b/src/styles/thread.css
@@ -1,13 +1,11 @@
.threadbox {
- width: 600px;
border: 10px solid green;
padding: 10px;
margin: 10px;
- margin-left: 0px;
background-color: white;
}
.commentbox {
- width: 500px;
+ max-width: 90%;
border: 5px solid green;
padding: 10px;
margin: 10px;