Compare commits
No commits in common. "80ecfd67471527843e29329cbd51d85c923427a3" and "54cafaa1da0a93fe12f6c5863725abe3ce90934f" have entirely different histories.
80ecfd6747
...
54cafaa1da
23 changed files with 85 additions and 376 deletions
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "@yusurko/vigil",
|
||||
"private": true,
|
||||
"version": "0.1.0-dev43",
|
||||
"version": "0.1.0-dev42",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
|
|
|
|||
2
src/app.d.ts
vendored
2
src/app.d.ts
vendored
|
|
@ -14,7 +14,7 @@ declare global {
|
|||
site: ServerHealth | null,
|
||||
me: UserEntry | null,
|
||||
results?: object[],
|
||||
query?: string,
|
||||
query?: string
|
||||
}
|
||||
// interface PageState {}
|
||||
// interface Platform {}
|
||||
|
|
|
|||
|
|
@ -1,24 +0,0 @@
|
|||
|
||||
<script lang="ts">
|
||||
import { RiChat3Line } from "svelte-remixicon";
|
||||
|
||||
|
||||
let { count } = $props();
|
||||
</script>
|
||||
|
||||
<div class="comment-count">
|
||||
<RiChat3Line />
|
||||
<strong>{count??'-'}</strong>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.comment-count {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.comment-count :global(svg) {
|
||||
color: var(--border);
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
<script lang="ts">
|
||||
import type { CommentEntry } from "./backend";
|
||||
import Centered from "./Centered.svelte";
|
||||
|
||||
|
||||
let comments: null | CommentEntry = $state(null);
|
||||
|
||||
let { post } = $props();
|
||||
|
||||
</script>
|
||||
|
||||
{#if comments === null}
|
||||
<Centered>
|
||||
<button class="inline">Show comments</button>
|
||||
</Centered>
|
||||
{/if}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
<script lang="ts">
|
||||
import PrivacySelect from "./PrivacySelect.svelte";
|
||||
|
||||
let { content = $bindable(""), privacy = $bindable(0) } = $props();
|
||||
|
||||
let contentLength = $derived(content.length);
|
||||
</script>
|
||||
|
||||
|
||||
<label>
|
||||
<input type="text" name="title" maxlength=256 placeholder="An interesting title"/>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
<textarea bind:value={content}></textarea>
|
||||
<output><small class="faint">{contentLength} chars</small></output>
|
||||
</label>
|
||||
|
||||
<PrivacySelect bind:value={privacy} />
|
||||
|
||||
<style>
|
||||
textarea {
|
||||
width: 100%;
|
||||
background-color: inherit;
|
||||
color: var(--text-primary);
|
||||
min-height: 10em;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
input[name="title"] {
|
||||
width: 100%;
|
||||
margin: 6px 0;
|
||||
font-size: 1.25em;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,68 +1,25 @@
|
|||
<script lang="ts">
|
||||
import { DateTime } from "luxon";
|
||||
import { RiHashtag, RiHistoryLine, RiUserLine } from "svelte-remixicon";
|
||||
import type { PostEntry } from "./backend";
|
||||
import PostMeta from "./PostMeta.svelte";
|
||||
import { SvelteShowdown } from "svelte-showdown";
|
||||
import VoteButton from "./VoteButton.svelte";
|
||||
import CommentCount from "./CommentCount.svelte";
|
||||
|
||||
let { post }: { post: PostEntry } = $props();
|
||||
let { id, title, content = "", votes, my_vote, comment_count } = post;
|
||||
|
||||
let { id, title, created_at, content } = post;
|
||||
</script>
|
||||
|
||||
<article class="card">
|
||||
<div class="post-frame">
|
||||
<h3 class="post-title">
|
||||
<a href="/={id}">{title}</a>
|
||||
</h3>
|
||||
<PostMeta {post} />
|
||||
<div class="post-content shorten">
|
||||
<SvelteShowdown { content } />
|
||||
</div>
|
||||
<aside class="message-stats">
|
||||
<VoteButton score={votes} vote={my_vote} {id} />
|
||||
<CommentCount count={comment_count} />
|
||||
</aside>
|
||||
<card class="post-frame">
|
||||
<h3 class="post-title">
|
||||
<a href="/={id}">{title}</a>
|
||||
</h3>
|
||||
<PostMeta {post} />
|
||||
<!-- TODO pist content -->
|
||||
<div class="post-content shorten">
|
||||
<SvelteShowdown content={ content || "" } />
|
||||
</div>
|
||||
</article>
|
||||
</card>
|
||||
|
||||
<style>
|
||||
.post-frame {
|
||||
padding-inline-start: 2em;
|
||||
position: relative;
|
||||
}
|
||||
.message-stats {
|
||||
position: absolute;
|
||||
inset-inline-start: 0;
|
||||
top: 0;
|
||||
width: 2em;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.post-title {
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.shorten {
|
||||
max-height: 18em;
|
||||
overflow-y: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.shorten::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
top: 16em;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 2em;
|
||||
display: block;
|
||||
background: linear-gradient(to bottom, rgba(0,0,0,0) 0%, var(--background) 100%);
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
<script lang="ts">
|
||||
import { RiEditLine, RiFlagLine } from "svelte-remixicon";
|
||||
import { DateTime } from "luxon";
|
||||
|
||||
import { RiEditLine, RiFlagLine, RiHistoryLine, RiHome2Line, RiUserLine } from "svelte-remixicon";
|
||||
import type { PostEntry } from "./backend";
|
||||
import SLayout from "./SLayout.svelte";
|
||||
import GuildAbout from "./GuildAbout.svelte";
|
||||
|
|
@ -10,15 +12,13 @@
|
|||
import { SvelteShowdown } from "svelte-showdown";
|
||||
import VoteButton from "./VoteButton.svelte";
|
||||
import { getMe } from "./globals.svelte";
|
||||
import CommentCount from "./CommentCount.svelte";
|
||||
import CommentSection from "./CommentSection.svelte";
|
||||
|
||||
|
||||
|
||||
let { post }: { post: PostEntry } = $props();
|
||||
|
||||
let me = getMe();
|
||||
let { title, id, content = '', to, votes, my_vote, comment_count } = post;
|
||||
let { title, created_at, id, content = '', to } = post;
|
||||
</script>
|
||||
|
||||
<SLayout title={to.display_name + (to.type === 'guild' ? ` (+${to.name})` : to.type === 'user' ? ` (@${to.username})` : '')}>
|
||||
|
|
@ -34,24 +34,21 @@ let { title, id, content = '', to, votes, my_vote, comment_count } = post;
|
|||
<!-- content, formatted as markdown -->
|
||||
</div>
|
||||
</div><!-- .post-body -->
|
||||
<aside class="message-stats">
|
||||
<div class="message-stats">
|
||||
<!-- upvotes / downvotes -->
|
||||
<VoteButton score={votes} vote={my_vote} {id} />
|
||||
<CommentCount count={comment_count} />
|
||||
</aside>
|
||||
<VoteButton />
|
||||
</div>
|
||||
<ul class="message-options row">
|
||||
{#if me && me.id !== post.author?.id}
|
||||
<li><a href="/report/post/{id}"><RiFlagLine/> Report</a></li>
|
||||
{/if}
|
||||
{#if me && me.id === post.author?.id }
|
||||
<li><a href="/edit/={id}"><RiEditLine/> Edit</a></li>
|
||||
<li><a href="/edit/post/{id}"><RiEditLine/> Edit</a></li>
|
||||
{/if}
|
||||
</ul>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<CommentSection {post} />
|
||||
|
||||
{#snippet left()}
|
||||
{#if to.type === 'guild'}
|
||||
<GuildMenu guild={to} />
|
||||
|
|
@ -77,13 +74,13 @@ let { title, id, content = '', to, votes, my_vote, comment_count } = post;
|
|||
overflow-x: auto;
|
||||
}
|
||||
.post-body {
|
||||
margin-inline-start: 2em;
|
||||
margin-inline-start: 3em;
|
||||
}
|
||||
.message-stats {
|
||||
position: absolute;
|
||||
inset-inline-start: 0;
|
||||
top: 0;
|
||||
width: 2em;
|
||||
width: 3em;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ let { guild }: { guild: GuildEntry } = $props();
|
|||
</script>
|
||||
|
||||
|
||||
|
||||
{#if guild}
|
||||
<AsideCard title={'About ' + (guild.display_name? `${guild.display_name} (+${guild.name})`: `+${guild.name}`)}>
|
||||
<ul>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
import { backend, type GuildEntry } from "./backend";
|
||||
|
||||
|
||||
let { value = $bindable("") } = $props();
|
||||
let value = $state("");
|
||||
|
||||
let suggestions: Promise<GuildEntry[]> = $derived(getSuggestions(value));
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<script lang="ts">
|
||||
|
||||
import { RiAddLine, RiLoginBoxLine, RiLogoutBoxLine, RiSearch2Line, RiSearchLine, RiSettings3Line, RiShieldStarLine, RiUserLine } from "svelte-remixicon";
|
||||
import { RiLoginBoxLine, RiLogoutBoxLine, RiSearch2Line, RiSearchLine, RiSettings3Line } from "svelte-remixicon";
|
||||
import { activePostCount } from "./globals.svelte";
|
||||
import type { UserEntry } from "./backend";
|
||||
|
||||
|
|
@ -35,23 +35,7 @@ let enable_search = $derived(user !== null);
|
|||
<span><a href="/@{user.username}">@{user.username}</a></span>
|
||||
<span>{user.karma || 0} karma</span>
|
||||
</div>
|
||||
<a class="mobileonly" href="/@{user.username}">
|
||||
<RiUserLine />
|
||||
</a>
|
||||
</li>
|
||||
<li class="nomobile">
|
||||
<a href="/create">
|
||||
<button>Create post</button>
|
||||
</a>
|
||||
</li>
|
||||
{#if user.badges && user.badges.indexOf("administrator") >= 0}
|
||||
<li>
|
||||
<a href="/admin/">
|
||||
<RiShieldStarLine />
|
||||
</a>
|
||||
</li>
|
||||
{/if}
|
||||
|
||||
<li><a href="/logout" aria-label="Log out" title="Log out"><RiLogoutBoxLine /></a></li>
|
||||
{:else}
|
||||
<li><a href="/login" aria-label="Log in" title="Log in"><RiLoginBoxLine /></a></li>
|
||||
|
|
@ -114,9 +98,7 @@ let enable_search = $derived(user !== null);
|
|||
overflow: hidden;
|
||||
}
|
||||
|
||||
button {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,28 +1,23 @@
|
|||
<script lang="ts">
|
||||
import { browser } from "$app/environment";
|
||||
import { RiAddCircleLine, RiChat2Line, RiCompassDiscoverLine, RiHome2Line, RiHomeLine, RiNotificationLine, RiUserLine } from "svelte-remixicon";
|
||||
import { getMe } from "./globals.svelte";
|
||||
import { RiAddCircleLine, RiChat2Line, RiCompassDiscoverLine, RiHome2Line, RiHomeLine, RiNotificationLine } from "svelte-remixicon";
|
||||
|
||||
function rickroll (){
|
||||
if (browser) {
|
||||
window.open( "https://youtu.be/dQw4w9WgXcQ" );
|
||||
}
|
||||
}
|
||||
|
||||
let me = $derived(getMe());
|
||||
</script>
|
||||
|
||||
{#if me}
|
||||
<footer class="mobileonly">
|
||||
<ul class="row">
|
||||
<li><a href="/" title="Homepage"><RiHome2Line size="2em" /></a></li>
|
||||
<li><a href="/" title="Discover"><RiCompassDiscoverLine size="2em" /></a></li>
|
||||
<li><a href="/create" title="Create"><RiAddCircleLine size="2em" /></a></li>
|
||||
<li><a href="/@{me.username}" title="Profile"><RiUserLine size="2em" /></a></li>
|
||||
<li><a href="/new" title="Create"><RiAddCircleLine size="2em" /></a></li>
|
||||
<li><a href="/user/yusur" title="Messages"><RiChat2Line size="2em" /></a></li>
|
||||
<li><a href="?" onclick={rickroll} title="Notifications"><RiNotificationLine size="2em" /></a></li>
|
||||
</ul>
|
||||
</footer>
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,46 +1,31 @@
|
|||
<script lang="ts">
|
||||
import { RiHeartFill, RiHeartLine, RiThumbDownFill, RiThumbDownLine } from "svelte-remixicon";
|
||||
import { backend } from "./backend";
|
||||
|
||||
|
||||
let { score = $bindable(null), vote = $bindable(0), id } : { score?: number | null, vote?: 0 | 1 | -1, id: string } = $props();
|
||||
let vote = $state(0);
|
||||
let { score } : { score?: number | null } = $props();
|
||||
|
||||
async function castVote(v: 0 | 1 | -1) {
|
||||
let readyBackend = await backend.withEvent(null).oath();
|
||||
let result = await readyBackend.submitJson(`post/${id}/upvote`, {
|
||||
vote: v
|
||||
});
|
||||
if (score === null) { return; }
|
||||
if (result.status >= 400) {
|
||||
// TODO toast error?
|
||||
console.error("error:", (await result.json()));
|
||||
return;
|
||||
}
|
||||
let {votes} = await result.json();
|
||||
vote = v;
|
||||
score = votes;
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="upvote-button">
|
||||
{#if vote > 0}
|
||||
<button class="inline up" onclick={() => { castVote(0).then(() => {}); }}>
|
||||
<button class="inline">
|
||||
<RiHeartFill />
|
||||
</button>
|
||||
{:else}
|
||||
<button class="inline" onclick={() => { castVote(1).then(() => {}); }}>
|
||||
<button class="inline">
|
||||
<RiHeartLine />
|
||||
</button>
|
||||
{/if}
|
||||
|
||||
<strong>{score ?? '-'}</strong>
|
||||
|
||||
{#if vote < 0}
|
||||
<button class="inline down" onclick={() => { castVote(0).then(() => {}); }}>
|
||||
{#if vote > 0}
|
||||
<button class="inline">
|
||||
<RiThumbDownFill />
|
||||
</button>
|
||||
{:else}
|
||||
<button class="inline" onclick={() => { castVote(-1).then(() => {}); }}>
|
||||
<button class="inline">
|
||||
<RiThumbDownLine />
|
||||
</button>
|
||||
{/if}
|
||||
|
|
@ -52,18 +37,5 @@ async function castVote(v: 0 | 1 | -1) {
|
|||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
button.inline {
|
||||
color: var(--border);
|
||||
}
|
||||
button.inline.up {
|
||||
color: var(--accent);
|
||||
}
|
||||
button.inline.down {
|
||||
color: var(--c11-accent);
|
||||
}
|
||||
:global(.color-theme-11) button.inline.down, :global(.color-theme-9) button.inline.down {
|
||||
color: var(--c14-accent);
|
||||
}
|
||||
</style>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
<script lang="ts">
|
||||
import { RiBarricadeLine } from "svelte-remixicon";
|
||||
import Centered from "./Centered.svelte";
|
||||
|
||||
</script>
|
||||
<Centered>
|
||||
<faint><RiBarricadeLine /></faint>
|
||||
</Centered>
|
||||
|
|
@ -29,21 +29,8 @@ export type PostEntry = {
|
|||
title: string,
|
||||
created_at: string,
|
||||
author?: UserEntry | null,
|
||||
content?: string,
|
||||
to: UserEntry | GuildEntry ,
|
||||
privacy?: number,
|
||||
votes?: number | null,
|
||||
my_vote?: 1 | -1 | 0,
|
||||
comment_count?: number | null
|
||||
};
|
||||
|
||||
export type CommentEntry = {
|
||||
id: string,
|
||||
parent?: {id: string},
|
||||
locked?: boolean,
|
||||
removed?: number | true,
|
||||
content?: string,
|
||||
created_at: string
|
||||
content?: string | null,
|
||||
to: UserEntry | GuildEntry
|
||||
};
|
||||
|
||||
export type ServerHealth = {
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ export function setHealth ({ name, version, post_count, user_count, color_theme
|
|||
health.color_theme = color_theme;
|
||||
}
|
||||
|
||||
|
||||
|
||||
export function setMe (me: UserEntry | null) {
|
||||
health.me = me;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ let colorThemeCls = $derived(`color-scheme-${colorScheme} color-theme-${colorThe
|
|||
<!-- end SEO tags -->
|
||||
</svelte:head>
|
||||
|
||||
<div class="{colorThemeCls} contents">
|
||||
<global-wrapper class={colorThemeCls}>
|
||||
<header>
|
||||
<h1>
|
||||
<a href="/">{appName()}</a>
|
||||
|
|
@ -54,7 +54,7 @@ let colorThemeCls = $derived(`color-scheme-${colorScheme} color-theme-${colorThe
|
|||
</main>
|
||||
|
||||
<MobileFooter />
|
||||
</div>
|
||||
</global-wrapper>
|
||||
|
||||
|
||||
<style>
|
||||
|
|
@ -88,13 +88,8 @@ let colorThemeCls = $derived(`color-scheme-${colorScheme} color-theme-${colorThe
|
|||
|
||||
@media screen and (max-width: 799px) {
|
||||
main {
|
||||
min-height: 100vh;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
}
|
||||
}
|
||||
|
||||
.contents {
|
||||
position: relative;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,19 +1,18 @@
|
|||
<script lang="ts">
|
||||
import Centered from "$lib/Centered.svelte";
|
||||
import EditPost from "$lib/EditPost.svelte";
|
||||
import { getMe } from "$lib/globals.svelte";
|
||||
import GuildSelect from "$lib/GuildSelect.svelte";
|
||||
import PrivacySelect from "$lib/PrivacySelect.svelte";
|
||||
import SLayout from "$lib/SLayout.svelte";
|
||||
import Wip from "$lib/Wip.svelte";
|
||||
import { RiErrorWarningLine } from "svelte-remixicon";
|
||||
|
||||
let me = getMe();
|
||||
|
||||
let content = $state("");
|
||||
let privacy = $state(0);
|
||||
let guildName = $state("");
|
||||
|
||||
let enablePost = $derived(!!content && !!guildName && false);
|
||||
let contentLength = $derived(content.length);
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
|
|
@ -23,26 +22,34 @@
|
|||
<p>Posting as <strong>@{me.username}</strong></p>
|
||||
|
||||
<label>
|
||||
Post to:
|
||||
<GuildSelect bind:value={guildName} />
|
||||
Post to: <!-- TODO autocomplete! -->
|
||||
<GuildSelect />
|
||||
</label>
|
||||
|
||||
<EditPost bind:content bind:privacy />
|
||||
<label>
|
||||
<input type="text" name="title" maxlength=256 placeholder="An interesting title"/>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
<textarea bind:value={content}></textarea>
|
||||
<output><small class="faint">{contentLength} chars</small></output>
|
||||
</label>
|
||||
|
||||
<PrivacySelect bind:value={privacy} />
|
||||
{#if privacy === 0}
|
||||
<span class="warning"><RiErrorWarningLine /> Your post will be PUBLIC!</span>
|
||||
{/if}
|
||||
|
||||
<button class="card primary" disabled={!enablePost}>Create</button>
|
||||
<button class="card primary" disabled>Create</button>
|
||||
|
||||
</form>
|
||||
|
||||
{#snippet left()}
|
||||
<Wip />
|
||||
...
|
||||
{/snippet}
|
||||
|
||||
{#snippet right()}
|
||||
<Wip />
|
||||
...
|
||||
{/snippet}
|
||||
</SLayout>
|
||||
{:else}
|
||||
|
|
@ -53,10 +60,22 @@
|
|||
|
||||
<style>
|
||||
|
||||
textarea {
|
||||
width: 100%;
|
||||
background-color: inherit;
|
||||
color: var(--text-primary);
|
||||
min-height: 10em;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
|
||||
input[name="title"] {
|
||||
width: 100%;
|
||||
margin: 6px 0;
|
||||
font-size: 1.25em;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
<script lang="ts">
|
||||
import type { PostEntry } from "$lib/backend";
|
||||
import Centered from "$lib/Centered.svelte";
|
||||
import EditPost from "$lib/EditPost.svelte";
|
||||
import { getMe } from "$lib/globals.svelte";
|
||||
import GuildSelect from "$lib/GuildSelect.svelte";
|
||||
import SLayout from "$lib/SLayout.svelte";
|
||||
import Wip from "$lib/Wip.svelte";
|
||||
import { RiErrorWarningLine } from "svelte-remixicon";
|
||||
|
||||
let me = getMe();
|
||||
|
||||
let { data }: { data: PostEntry } = $props();
|
||||
let post = $state(data) ;
|
||||
|
||||
let { content = "", privacy } = $derived(post);
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
{#if me?.id === post.author?.id}
|
||||
<SLayout title="New post">
|
||||
<form method="POST" class="card">
|
||||
<p>Posting as <strong>@{me?.username}</strong></p>
|
||||
|
||||
<label>
|
||||
Post to:
|
||||
<GuildSelect />
|
||||
</label>
|
||||
|
||||
<EditPost bind:content bind:privacy />
|
||||
|
||||
{#if privacy === 0}
|
||||
<span class="warning"><RiErrorWarningLine /> Your post will be PUBLIC!</span>
|
||||
{/if}
|
||||
|
||||
<button class="card primary" disabled>Create</button>
|
||||
|
||||
</form>
|
||||
|
||||
{#snippet left()}
|
||||
<Wip />
|
||||
{/snippet}
|
||||
|
||||
{#snippet right()}
|
||||
<Wip />
|
||||
{/snippet}
|
||||
</SLayout>
|
||||
{:else if me}
|
||||
You can't edit posts that are not your own.
|
||||
{:else}
|
||||
<Centered>
|
||||
You must be <a href="login">logged in</a> in order to edit your own posts.
|
||||
</Centered>
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
import { backend, type GuildEntry } from '$lib/backend.js';
|
||||
import { getMe } from '$lib/globals.svelte';
|
||||
import { error, isHttpError, redirect } from '@sveltejs/kit';
|
||||
|
||||
export async function load(event) {
|
||||
|
||||
const { params } = event;
|
||||
const { id } = params;
|
||||
|
||||
const resp = await backend.withEvent(event).fetch('post/' + encodeURIComponent(id));
|
||||
|
||||
if(resp.status === 404) {
|
||||
error(404);
|
||||
}
|
||||
|
||||
let post;
|
||||
|
||||
try{
|
||||
const respJ = await resp.json();
|
||||
|
||||
let { posts } = respJ;
|
||||
post = posts[id];
|
||||
|
||||
let me = getMe();
|
||||
|
||||
if (!me) {
|
||||
redirect(303, "/login?next=" + encodeURIComponent(event.url.pathname));
|
||||
}
|
||||
if ( post.author.id !== me?.id) {
|
||||
error(403);
|
||||
}
|
||||
|
||||
if (post?.to && post.to.type === 'guild') {
|
||||
const guild: GuildEntry = post.to;
|
||||
const guildResp = await backend.withEvent(event).fetch('guild/' + encodeURIComponent(guild.id));
|
||||
const guildJson = await guildResp.json();
|
||||
const guildInfo = guildJson?.guilds?.[guild.id];
|
||||
guildInfo.type = 'guild';
|
||||
post.to = guildInfo || guild;
|
||||
console.log(post.to);
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
if (isHttpError(e)) throw e;
|
||||
|
||||
console.error(e);
|
||||
error(502);
|
||||
}
|
||||
|
||||
return post;
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ import { redirect } from 'sveltekit-flash-message/server';
|
|||
|
||||
export const actions = {
|
||||
default: async (event) => {
|
||||
// TODO login
|
||||
|
||||
const { request } = event;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
<script lang="ts">
|
||||
import { enhance } from "$app/forms";
|
||||
import Centered from "$lib/Centered.svelte";
|
||||
import Wip from "$lib/Wip.svelte";
|
||||
import { RiInformationLine, RiUserLine } from "svelte-remixicon";
|
||||
|
||||
let username = $state("");
|
||||
|
|
@ -26,7 +25,7 @@ let disabled = $derived(username.length < 2 || username.length > 30 ||
|
|||
<small class="faint">Must be a working e-mail address <abbr title="Will be used for password recovery and important communications"><RiInformationLine /></abbr></small>
|
||||
<input type="text" name="username" bind:value={email} />
|
||||
</label>
|
||||
<Wip />
|
||||
...
|
||||
|
||||
<button class="primary" disabled={disabled}>Sign up</button>
|
||||
</form>
|
||||
|
|
|
|||
|
|
@ -32,12 +32,14 @@ export const actions = {
|
|||
event.locals.results = results;
|
||||
event.locals.query = query;
|
||||
console.log(event.locals);
|
||||
return
|
||||
}
|
||||
} satisfies Actions;
|
||||
|
||||
export function load (event) {
|
||||
const { results, query } = event.locals;
|
||||
export async function load (event) {
|
||||
const { results, query } = event.locals;
|
||||
|
||||
return { results, query };
|
||||
console.log({ results, query });
|
||||
return { results, query };
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@
|
|||
import type { PageProps } from "./$types";
|
||||
|
||||
let { data }: PageProps = $props();
|
||||
console.log(data);
|
||||
let { query, results } = $derived(data);
|
||||
</script>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue