Overhauled post creation

Made the menu significantly better and made it possible to upload files directly from the post page
This commit is contained in:
Xodrium 2023-02-10 18:17:40 -05:00
parent b2ce13eea1
commit 2b8158f666
11 changed files with 219 additions and 125 deletions

View file

@ -25,6 +25,8 @@
#main { #main {
min-height: 250px; min-height: 250px;
max-height: 500px;
overflow-y: scroll;
} }
#main.tiny { #main.tiny {

View file

@ -0,0 +1,27 @@
<style>
.button {
padding: 0.5rem;
background-color: var(--dark-3);
border: none;
font-family: 'Open Sans';
border-radius: 0.5rem;
margin: 0.2rem;
}
.button a {
color: var(--light-1);
}
</style>
<script>
export let clickFunc = () => {};
export let button = '';
</script>
<button on:click={clickFunc} class='button'>
<a href='#'><slot/></a>
</button>

View file

@ -0,0 +1,55 @@
<script>
import Button from '$lib/components/Button.svelte';
export let form;
let fileInput;
let files;
let preview;
function getBase64(image) {
const reader = new FileReader();
reader.readAsDataURL(image);
reader.onload = e => {
preview = e.target.result;
uploadFunction(e.target.result);
};
};
async function uploadFunction(imgBase64) {
const imgData = imgBase64.split(',').pop();
var fData = (new FormData());
fData.append('img',imgData);
fData.append('extension',fileInput.value.split('.').pop());
form = await fetch(`/api/fileCreate`, {
method: 'POST',
body: fData
}).then(x => x.json());
};
</script>
<style>
.hidden {
display: none;
}
img {
max-width: 250px;
}
</style>
<form action='/api/postCreate' method='POST' >
{#if preview}
<img src={preview} alt="Image preview"/>
{:else}
<img src='/icon_sanifae.svg' alt="Image preview"/>
{/if}
<input class="hidden" id="file-to-upload" type="file" bind:files bind:this={fileInput} on:change={() => getBase64(files[0])}/>
<p>
<Button class="upload-btn" clickFunc={ () => fileInput.click() }>Upload</Button>
</p>
</form>

View file

@ -1,14 +1,12 @@
<script> <script>
import Area from '$lib/components/Area.svelte'; import Area from '$lib/components/Area.svelte';
import PostButton from '$lib/components/PostButton.svelte';
import {formatPost} from '$lib/util.js'; import PostBody from '$lib/components/PostBody.svelte';
export let success, username, content, upvotes, downvotes, id; export let success, username, content, upvotes, downvotes, id;
let query = (id) ? `/post/${id}` : ''; let query = (id) ? `/post/${id}` : '';
let contentSplit = formatPost(content || '');
let fData; let fData;
function vote(v) { function vote(v) {
@ -29,10 +27,7 @@
</script> </script>
<style> <style>
.button {
width: auto;
height: 35px;
}
.votes { .votes {
font-weight: bold; font-weight: bold;
font-size: 1.5rem; font-size: 1.5rem;
@ -59,44 +54,31 @@
</p> </p>
</Area> </Area>
{:else} {:else}
<Area tiny='{!!id}'> <Area>
<span slot="header"> <span slot="header">
<a href='/user/{username}'> <a href='/user/{username}'>
{username} {username}
</a> </a>
</span> </span>
<span slot="main"> <span slot="main">
{#each contentSplit as line} <PostBody content={content} />
{#if line && line.type == 'img'}
<img src={line.url} alt='Image preview'>
{:else}
<p>{line}</p>
{/if}
{/each}
</span> </span>
<span slot="footer"> <span slot="footer">
<span class='vote-area'> <PostButton
<a on:click={() => vote('up')} href=''> clickFunc={() => vote('up')}
<img src='/upvote.svg' class='button' alt='Upvote'> data={upvotes * 1}
</a> icon='/upvote.svg'
<span class='votes'> />
{upvotes + 0} <PostButton
</span> clickFunc={() => vote('down')}
</span> data={downvotes * 1}
<span class='vote-area'> icon='/downvote.svg'
<a on:click={() => vote('down')} href=''> />
<img src='/downvote.svg' class='button' alt='Downvote'>
</a>
<span class='votes'>
{downvotes + 0}
</span>
</span>
{#if id} {#if id}
<span class='vote-area'> <PostButton
<a href='/post/{id}'> href='/post/{id}'
<img src='/view.svg' class='button' alt='View'> icon='/view.svg'
</a> />
</span>
{/if} {/if}
</span> </span>
</Area> </Area>

View file

@ -0,0 +1,27 @@
<style>
img {
max-width: 250px;
display: block;
}
</style>
<script>
import {formatPost} from '$lib/util.js';
export let content = '';
let contentSplit;
$: contentSplit = formatPost(content || '');
console.log(contentSplit);
</script>
<span>
{#each contentSplit as line}
{#if line && line.type == 'img'}
<img src={line.url} alt='Image preview'>
{:else}
<p>{line}</p>
{/if}
{/each}
</span>

View file

@ -0,0 +1,31 @@
<style>
.votes {
font-weight: bold;
font-size: 1.5rem;
}
.vote-area {
margin-right: 30px;
}
.button {
width: auto;
height: 35px;
}
</style>
<script>
export let clickFunc = () => {};
export let href = '#';
export let data = ' ';
export let icon = '/upvote.svg';
</script>
<span class='vote-area'>
<a on:click={clickFunc} href='{href}'>
<img src='{icon}' class='button' alt='Vote button'>
</a>
<span class='votes'>
{data}
</span>
</span>

View file

@ -81,11 +81,16 @@ let formatPost = function(post) {
return post; return post;
} }
function block(bool) {
return (bool) ? 'block' : 'inline';
}
export { export {
checkLength, checkLength,
checkRegex, checkRegex,
calcVote, calcVote,
handleSubmit, handleSubmit,
calcVoteUser, calcVoteUser,
formatPost formatPost,
block
}; };

View file

@ -2,6 +2,7 @@
:global(:root) { :global(:root) {
--dark-1: #1a1b1d; --dark-1: #1a1b1d;
--dark-2: #22242b; --dark-2: #22242b;
--dark-3: #5d606b;
--light-1: #ffffff; --light-1: #ffffff;
@ -83,9 +84,6 @@
<a href='/new_post'> <a href='/new_post'>
Create Create
</a> </a>
<a href='/new_file'>
Create file
</a>
{:else} {:else}
<a href='/account'> <a href='/account'>
Log in / Register Log in / Register

View file

@ -1,75 +0,0 @@
<script>
import Area from '$lib/components/Area.svelte';
/** @type {import('./$types').ActionData} */
export let form;
let fileInput;
let files;
let preview;
function getBase64(image) {
const reader = new FileReader();
reader.readAsDataURL(image);
reader.onload = e => {
preview = e.target.result;
uploadFunction(e.target.result);
};
};
async function uploadFunction(imgBase64) {
const imgData = imgBase64.split(',').pop();
var fData = (new FormData());
fData.append('img',imgData);
fData.append('extension',fileInput.value.split('.').pop());
form = await fetch(`/api/fileCreate`, {
method: 'POST',
body: fData
}).then(x => x.json());
};
</script>
<style>
textarea {
width: 10rem;
height: 10rem;
}
.hidden {
display: none;
}
img {
max-width: 250px;
}
</style>
<Area>
<p slot="header">
Upload File
</p>
<form slot="main" action='/api/postCreate' method='POST' >
{#if preview}
<img src={preview} alt="Image preview"/>
{:else}
<img src='/icon_sanifae.svg' alt="Image preview"/>
{/if}
<input class="hidden" id="file-to-upload" type="file" bind:files bind:this={fileInput} on:change={() => getBase64(files[0])}/>
<p>
<a href='#' class="upload-btn" on:click={ () => fileInput.click() }>Upload</a>
</p>
</form>
<p slot="footer">
{#if form?.success}
{#if form?.href}
<a href='{form?.href}'>{form?.success}</a>
{:else}
{form?.success}
{/if}
{/if}
Create an image for the world to see.
</p>
</Area>

View file

@ -1,10 +1,30 @@
<script> <script>
import Area from '$lib/components/Area.svelte'; import Area from '$lib/components/Area.svelte';
import FileUpload from '$lib/components/FileUpload.svelte';
import PostBody from '$lib/components/PostBody.svelte';
import Button from '$lib/components/Button.svelte';
import { handleSubmit } from '$lib/util.js'; import { handleSubmit, formatPost } from '$lib/util.js';;
/** @type {import('./$types').ActionData} */ /** @type {import('./$types').ActionData} */
export let form; export let form;
let uploadForm = {};
let formContent = '';
let formBody;
let currentState = 'editor';
function setState(editor) {
currentState = editor;
}
$: if (uploadForm.href) {
currentState = 'editor';
formContent += `\nimg||${uploadForm.href.split('/').pop()}`;
uploadForm.href = false;
}
</script> </script>
<style> <style>
@ -12,21 +32,42 @@
width: 10rem; width: 10rem;
height: 10rem; height: 10rem;
} }
.wrapper {
display: flex;
flex-direction: row;
}
</style> </style>
<Area> <Area>
<p slot="header"> <p slot="header">
Create Post Create Post
</p> </p>
<form slot="main" action='/api/postCreate' method='POST' on:submit|preventDefault={async e => form = JSON.parse(await handleSubmit(e)) }> <div class='main' slot='main'>
<p> <form action='/api/postCreate'
<textarea name='content'></textarea> method='POST'
</p> on:submit|preventDefault={async e => form = JSON.parse(await handleSubmit(e)) }
<p> >
<input formaction="?/create" type='submit' value='Post'> <textarea name='content' style='display: none;' value={formContent}></textarea
</p> </form>
</form> <input formaction="?/create" type='submit' value='Post' bind:this={formBody} style='display: none;'>
{#if currentState == 'editor'}
<p>
<textarea name='content' bind:value={formContent}></textarea>
</p>
{:else if currentState == 'visual'}
<PostBody content={formContent} />
{:else}
<FileUpload bind:form={uploadForm} />
{/if}
</div>
<span slot="footer"> <span slot="footer">
<div class='wrapper'>
<Button clickFunc={() => { setState('editor')}}>Edit</Button>
<Button clickFunc={() => { setState('visual')}}>View</Button>
<Button clickFunc={() => { setState('upload')}}>Upload file</Button>
<Button clickFunc={() => formBody.click()}>Create</Button>
</div>
<p> <p>
{#if form?.success} {#if form?.success}
{#if form?.href} {#if form?.href}

View file

@ -11,4 +11,5 @@
content={data.content} content={data.content}
upvotes={data.upvotes} upvotes={data.upvotes}
downvotes={data.downvotes} downvotes={data.downvotes}
id={data.id}
></Post> ></Post>