added everything
.
This commit is contained in:
parent
dcae12453c
commit
fcd279884c
15 changed files with 309 additions and 136 deletions
|
@ -26,15 +26,26 @@
|
|||
#main {
|
||||
min-height: 250px;
|
||||
}
|
||||
|
||||
#main.tiny {
|
||||
min-height: initial;
|
||||
height: 100px;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
<script>
|
||||
export let tiny = false;
|
||||
</script>
|
||||
|
||||
<div id='content'>
|
||||
<div id='header'>
|
||||
<slot name="header">
|
||||
Header
|
||||
</slot>
|
||||
</div>
|
||||
<div id='main'>
|
||||
<div id='main' class='{tiny ? "tiny" : ""}'>
|
||||
<slot name="main">
|
||||
<p>Content</p>
|
||||
</slot>
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
<script>
|
||||
import Area from '$lib/Area.svelte';
|
||||
</script>
|
||||
|
||||
<Area>
|
||||
<p slot="header">
|
||||
Welcome to SvelteKit
|
||||
</p>
|
||||
<p slot="main">
|
||||
Visit <a href="https://kit.svelte.dev">kit.svelte.dev</a> to read the documentation
|
||||
</p>
|
||||
<p slot="footer">
|
||||
|
||||
</p>
|
||||
</Area>
|
|
@ -1,15 +1,75 @@
|
|||
<script>
|
||||
import Area from '$lib/Area.svelte';
|
||||
|
||||
export let success, username, content, upvotes, downvotes, id;
|
||||
|
||||
let query = (id) ? `/post/${id}` : '';
|
||||
|
||||
let contentSplit = content.split('\n');
|
||||
</script>
|
||||
|
||||
<Area>
|
||||
<p slot="header">
|
||||
Welcome to SvelteKit
|
||||
</p>
|
||||
<p slot="main">
|
||||
Visit <a href="https://kit.svelte.dev">kit.svelte.dev</a> to read the documentation
|
||||
</p>
|
||||
<p slot="footer">
|
||||
|
||||
</p>
|
||||
</Area>
|
||||
<style>
|
||||
.button {
|
||||
width: auto;
|
||||
height: 35px;
|
||||
}
|
||||
.votes {
|
||||
font-weight: bold;
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
.vote-area {
|
||||
margin-right: 30px;
|
||||
}
|
||||
</style>
|
||||
|
||||
{#if success}
|
||||
<Area>
|
||||
<p slot="header">
|
||||
Error
|
||||
</p>
|
||||
<p slot="main">
|
||||
{success}
|
||||
</p>
|
||||
<p slot="footer">
|
||||
Failed to get post.
|
||||
</p>
|
||||
</Area>
|
||||
{:else}
|
||||
<Area tiny='{!!id}'>
|
||||
<span slot="header">
|
||||
<a href='/users/{username}'>
|
||||
{username}
|
||||
</a>
|
||||
</span>
|
||||
<span slot="main">
|
||||
{#each contentSplit as line}
|
||||
<p>{line}</p>
|
||||
{/each}
|
||||
</span>
|
||||
<span slot="footer">
|
||||
<span class='vote-area'>
|
||||
<a data-sveltekit-reload href='{query}?vote=up'>
|
||||
<img src='/upvote.svg' class='button' alt='Upvote'>
|
||||
</a>
|
||||
<span class='votes'>
|
||||
{upvotes + 0}
|
||||
</span>
|
||||
</span>
|
||||
<span class='vote-area'>
|
||||
<a data-sveltekit-reload href='{query}?vote=down'>
|
||||
<img src='/downvote.svg' class='button' alt='Downvote'>
|
||||
</a>
|
||||
<span class='votes'>
|
||||
{downvotes + 0}
|
||||
</span>
|
||||
</span>
|
||||
{#if id}
|
||||
<span class='vote-area'>
|
||||
<a href='/post/{id}'>
|
||||
<img src='/view.svg' class='button' alt='View'>
|
||||
</a>
|
||||
</span>
|
||||
{/if}
|
||||
</span>
|
||||
</Area>
|
||||
{/if}
|
|
@ -1,6 +1,7 @@
|
|||
import sqlite3 from 'sqlite3'
|
||||
import { open } from 'sqlite'
|
||||
import { hash, compare } from 'bcrypt'
|
||||
import { calcVote } from './util.js';
|
||||
|
||||
const {
|
||||
randomBytes
|
||||
|
@ -15,7 +16,7 @@ async function initDb() {
|
|||
|
||||
await db.run('CREATE TABLE IF NOT EXISTS auth (username CHAR(64), password CHAR(1024))');
|
||||
await db.run('CREATE TABLE IF NOT EXISTS token (username CHAR(64), token CHAR(1024))');
|
||||
await db.run('CREATE TABLE IF NOT EXISTS post (username CHAR(64), id CHAR(64), content CHAR(10240), upvotes INTEGER, downvotes INTEGER)');
|
||||
await db.run('CREATE TABLE IF NOT EXISTS post (username CHAR(64), id CHAR(64), content CHAR(10240), upvotes INTEGER, downvotes INTEGER, rating REAL)');
|
||||
await db.run('CREATE TABLE IF NOT EXISTS vote (id CHAR(64), username CHAR(64), type INTEGER)');
|
||||
}
|
||||
|
||||
|
@ -67,10 +68,11 @@ async function loginBackend({user, pass}) {
|
|||
async function postCreateBackend({user, content}) {
|
||||
var id = randomBytes(10).toString('hex');
|
||||
|
||||
await db.run('INSERT INTO post (username, id, content) VALUES (?, ?, ?)', [
|
||||
await db.run('INSERT INTO post (username, id, content, rating) VALUES (?, ?, ?, ?)', [
|
||||
user,
|
||||
id,
|
||||
content
|
||||
content,
|
||||
calcVote(0,0)
|
||||
])
|
||||
}
|
||||
|
||||
|
@ -86,6 +88,46 @@ async function postGetBackend({id}) {
|
|||
return posts[0];
|
||||
}
|
||||
|
||||
async function postGetBulkBackend({page, rows}) {
|
||||
var posts = await db.all('SELECT * from post ORDER BY rating DESC LIMIT ?, ?', [
|
||||
page*rows,
|
||||
rows
|
||||
])
|
||||
|
||||
return posts;
|
||||
}
|
||||
|
||||
async function voteBackend({user, id, vote}) {
|
||||
if (!user || !id || user == '' || (vote != 'down' && vote != 'up')) return {};
|
||||
|
||||
await db.run('DELETE FROM vote WHERE username = ? AND id = ?', [
|
||||
user,
|
||||
id
|
||||
]);
|
||||
|
||||
await db.run('INSERT INTO vote (id, username, type) VALUES (?,?,?)', [
|
||||
id,
|
||||
user,
|
||||
vote == 'up' ? 1 : 2
|
||||
]);
|
||||
|
||||
var votes = await db.all('SELECT type from vote WHERE id = ?', [
|
||||
id
|
||||
]) || [];
|
||||
|
||||
var up = votes.filter(x => x.type == 1).length;
|
||||
var down = votes.filter(x => x.type == 2).length;
|
||||
|
||||
await db.run('UPDATE post SET upvotes = ?, downvotes = ?, rating = ? WHERE id = ?', [
|
||||
up,
|
||||
down,
|
||||
calcVote(up,down),
|
||||
id
|
||||
]);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
async function tokenBackend({token}) {
|
||||
if (!db) await initDb();
|
||||
|
||||
|
@ -104,5 +146,7 @@ export {
|
|||
loginBackend,
|
||||
tokenBackend,
|
||||
postCreateBackend,
|
||||
postGetBackend
|
||||
postGetBackend,
|
||||
voteBackend,
|
||||
postGetBulkBackend
|
||||
}
|
|
@ -20,7 +20,23 @@ let checkRegex = function(string, field, regex) {
|
|||
return false;
|
||||
}
|
||||
|
||||
let calcVote = function(up,down) {
|
||||
var upPadded = up + 3;
|
||||
var downPadded = down + 3;
|
||||
var totalPadded = Math.max(up + down, 3);
|
||||
|
||||
var rating = -Math.log((1 / ((((upPadded - downPadded) / (upPadded + downPadded)) + 1) / 2)) - 1) / Math.log(Math.E);
|
||||
|
||||
rating = Math.min(rating,10);
|
||||
rating = Math.max(rating,-10);
|
||||
|
||||
rating = (rating + 10) / 2;
|
||||
|
||||
return rating * Math.log(totalPadded);
|
||||
}
|
||||
|
||||
export {
|
||||
checkLength,
|
||||
checkRegex
|
||||
checkRegex,
|
||||
calcVote
|
||||
};
|
|
@ -46,6 +46,9 @@
|
|||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
|
||||
position: sticky;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
#logo a {
|
||||
|
|
15
src/routes/+page.js
Normal file
15
src/routes/+page.js
Normal file
|
@ -0,0 +1,15 @@
|
|||
/** @type {import('./$types').PageLoad} */
|
||||
export async function load({ fetch, params, url }) {
|
||||
var search = url.searchParams;
|
||||
|
||||
var voteType = search.get('vote');
|
||||
|
||||
var id = search.get('page') * 1;
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 100));
|
||||
|
||||
const res = await fetch(`/api/explore?page=${id}`);
|
||||
const postJson = await res.json();
|
||||
|
||||
return { postJson, id };
|
||||
}
|
|
@ -1,15 +1,22 @@
|
|||
<script>
|
||||
import Area from '$lib/Area.svelte';
|
||||
import Post from '$lib/Post.svelte';
|
||||
|
||||
/** @type {import('./$types').PageData} */
|
||||
export let data;
|
||||
</script>
|
||||
|
||||
<Area>
|
||||
<p slot="header">
|
||||
Welcome to SvelteKit
|
||||
</p>
|
||||
<p slot="main">
|
||||
Visit <a href="https://kit.svelte.dev">kit.svelte.dev</a> to read the documentation
|
||||
</p>
|
||||
<p slot="footer">
|
||||
|
||||
</p>
|
||||
</Area>
|
||||
{#each data.postJson as post}
|
||||
<Post
|
||||
success={post.success}
|
||||
username={post.username}
|
||||
content={post.content}
|
||||
upvotes={post.upvotes}
|
||||
downvotes={post.downvotes}
|
||||
id={post.id}
|
||||
></Post>
|
||||
{/each}
|
||||
|
||||
<p>
|
||||
<a data-sveltekit-reload href='?page={data.id+1}'>Next page</a>
|
||||
</p>
|
||||
<p></p>
|
10
src/routes/api/explore/+server.js
Normal file
10
src/routes/api/explore/+server.js
Normal file
|
@ -0,0 +1,10 @@
|
|||
import { postGetBulkBackend } from '../../../lib/db.js';
|
||||
|
||||
/** @type {import('./$types').RequestHandler} */
|
||||
export async function GET({ url, cookies }) {
|
||||
var page = url.searchParams.get('page') * 1;
|
||||
|
||||
var postData = await postGetBulkBackend({ rows: 5, page });
|
||||
|
||||
return new Response(JSON.stringify(postData));
|
||||
};
|
17
src/routes/api/vote/+server.js
Normal file
17
src/routes/api/vote/+server.js
Normal file
|
@ -0,0 +1,17 @@
|
|||
import { tokenBackend, voteBackend } from '../../../lib/db.js';
|
||||
|
||||
/** @type {import('./$types').RequestHandler} */
|
||||
export async function GET({ url, cookies }) {
|
||||
var token = cookies.get('token') || '';
|
||||
|
||||
var user = await tokenBackend({token});
|
||||
|
||||
if (!user) return;
|
||||
|
||||
var id = url.searchParams.get('post');
|
||||
var vote = url.searchParams.get('vote');
|
||||
|
||||
voteBackend({user,id,vote});
|
||||
|
||||
return new Response();
|
||||
};
|
|
@ -1,12 +1,19 @@
|
|||
/** @type {import('./$types').PageLoad} */
|
||||
export async function load({ fetch, params, url }) {
|
||||
var search = url.searchParams;
|
||||
|
||||
var voteType = search.get('vote');
|
||||
|
||||
var id = params.post;
|
||||
|
||||
if (voteType) {
|
||||
await fetch(`/api/vote?post=${id}&vote=${voteType}`);
|
||||
}
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 100));
|
||||
|
||||
const res = await fetch(`/api/post?post=${id}`);
|
||||
const postJson = await res.json();
|
||||
|
||||
var search = url.searchParams;
|
||||
|
||||
var voteType = (search.get('upvote')) ? 1 : ((search.get('downvote')) ? 2 : 0);
|
||||
|
||||
return { postJson };
|
||||
return postJson;
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
<script>
|
||||
import Area from '$lib/Area.svelte';
|
||||
import Post from '$lib/Post.svelte';
|
||||
|
||||
/** @type {import('./$types').PageData} */
|
||||
export let data;
|
||||
|
@ -7,59 +7,10 @@
|
|||
export let form;
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.button {
|
||||
width: auto;
|
||||
height: 75px;
|
||||
}
|
||||
.votes {
|
||||
font-weight: bold;
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
.vote-area {
|
||||
margin-right: 30px;
|
||||
}
|
||||
</style>
|
||||
|
||||
{#if data.postJson.success}
|
||||
<Area>
|
||||
<p slot="header">
|
||||
Error
|
||||
</p>
|
||||
<p slot="main">
|
||||
{data.postJson.success}
|
||||
</p>
|
||||
<p slot="footer">
|
||||
Failed to get post.
|
||||
</p>
|
||||
</Area>
|
||||
{:else}
|
||||
<Area>
|
||||
<p slot="header">
|
||||
<a href='/users/{data.postJson.username}'>
|
||||
{data.postJson.username}
|
||||
</a>
|
||||
</p>
|
||||
<p slot="main">
|
||||
{data.postJson.content}
|
||||
</p>
|
||||
<p slot="footer">
|
||||
<span class='vote-area'>
|
||||
<a href='?upvote'>
|
||||
<img src='/upvote.svg' class='button' alt='Upvote'>
|
||||
</a>
|
||||
<span class='votes'>
|
||||
{data.postJson.upvotes + 0}
|
||||
</span>
|
||||
</span>
|
||||
<span class='vote-area'>
|
||||
<a href='?downvote'>
|
||||
<img src='/downvote.svg' class='button' alt='Downvote'>
|
||||
</a>
|
||||
<span class='votes'>
|
||||
{data.postJson.downvotes + 0}
|
||||
</span>
|
||||
</span>
|
||||
</p>
|
||||
</Area>
|
||||
{/if}
|
||||
<Post
|
||||
success={data.success}
|
||||
username={data.username}
|
||||
content={data.content}
|
||||
upvotes={data.upvotes}
|
||||
downvotes={data.downvotes}
|
||||
></Post>
|
Loading…
Add table
Add a link
Reference in a new issue