Compare commits

...

4 Commits

Author SHA1 Message Date
31763528bf feat: add image resize percent 2022-04-15 04:19:05 +07:00
2c56336c4f feat: add login expiry check 2022-04-15 03:50:03 +07:00
afbdc56b71 feat: adjust pagination delta 2022-04-15 03:42:56 +07:00
316e52cb72 feat: some adjustments to frontend 2022-04-15 03:38:53 +07:00
14 changed files with 221 additions and 121 deletions

View File

@ -1,9 +1,10 @@
<script>
import { token } from "./stores.js";
import { isTokenExpired } from "./login-check.js";
let loggedIn = false;
token.subscribe((value) => {
loggedIn = value !== "";
loggedIn = !isTokenExpired(value);
});
</script>

View File

@ -2,10 +2,11 @@
import { token } from "./stores.js";
import { navigate } from "svelte-routing";
import { onMount } from "svelte";
import { isTokenExpired } from "./login-check.js";
let loggedIn = false;
token.subscribe((value) => {
loggedIn = value !== "";
loggedIn = !isTokenExpired(value);
});
onMount(() => {

View File

@ -18,7 +18,7 @@
const getData = async () => {
form.source_url = post.source_url;
form.tags = post.tags;
form.tags = post.tags.map(x => x.tagType+":"+x.tagName);
};
const onTagChange = (value) => {
@ -47,7 +47,29 @@
<p class="panel-heading">Edit Post</p>
<div class="panel-block column">
<div class="row">
<label for="source" class="label">Source URL</label>
<strong>Uploader:</strong>
</div>
<div class="row">{post.uploader}</div>
</div>
<div class="panel-block column">
<div class="row">
<strong>Original:</strong>
</div>
<div class="row">
<a href={post.image_path} target="_blank">Image</a>
</div>
</div>
<div class="panel-block column">
<div class="row">
<strong>Dimensions:</strong>
</div>
<div class="row">
{post.width}x{post.height}
</div>
</div>
<div class="panel-block column">
<div class="row">
<label for="source" class="label">Source URL:</label>
</div>
<div class="row">
<div class="field">
@ -65,7 +87,7 @@
</div>
<div class="panel-block column">
<div class="row">
<label for="tags" class="label">Tags</label>
<label for="tags" class="label">Tags:</label>
</div>
<div class="row">
<div class="field">

View File

@ -1,12 +1,13 @@
<script>
import { Link } from "svelte-routing";
import { token } from "./stores.js";
import { isTokenExpired } from "./login-check.js";
let menu_shown = false;
let loggedIn = false;
token.subscribe((value) => {
loggedIn = value !== "";
loggedIn = !isTokenExpired(value);
});
const toggleMenu = () => {

View File

@ -7,7 +7,8 @@
let tagType = tag.split(":")[0] ?? "";
let tagName = tag.split(":")[1] ?? "";
let tagDisplay = tagName.split("_").join(" ");
</script>
<Link to="/posts?tags={tagName}">{tagDisplay} <span class="is-pulled-right">{num}</span></Link>
<Link to="/posts?tags={tagName}"
>{tagDisplay} <span class="is-pulled-right">{num}</span></Link
>

View File

@ -21,20 +21,12 @@
</div>
<div class="row">{post.uploader}</div>
</div>
<div class="panel-block column">
<div class="row">
<strong>Source URL:</strong>
</div>
<div class="row">
<a href={post.source_url}>{trimUrl(post.source_url)}</a>
</div>
</div>
<div class="panel-block column">
<div class="row">
<strong>Original:</strong>
</div>
<div class="row">
<a href={post.image_path}>Image</a>
<a href={post.image_path} target="_blank">Image</a>
</div>
</div>
<div class="panel-block column">
@ -45,6 +37,14 @@
{post.width}x{post.height}
</div>
</div>
<div class="panel-block column">
<div class="row">
<strong>Source URL:</strong>
</div>
<div class="row">
<a href={post.source_url}>{trimUrl(post.source_url)}</a>
</div>
</div>
<div class="panel-block column">
<div class="row">
<p><strong>Tags:</strong></p>

View File

@ -0,0 +1,8 @@
const isTokenExpired = (token) => {
if (token === "") return true;
const expiry = (JSON.parse(atob(token.split('.')[1]))).exp;
return (Math.floor((new Date).getTime() / 1000)) >= expiry;
}
export { isTokenExpired }

View File

@ -1,9 +1,54 @@
<script>
import Tags from "svelte-tags-input";
import { getTagAutocomplete } from "../api.js";
import { navigate } from "svelte-routing";
let searchTerms = [];
const onTagChange = (value) => {
searchTerms = value.detail.tags;
};
const onAutocomplete = async () => {
const list = await getTagAutocomplete();
return list;
};
const onSearch = (i) => {
if (searchTerms.length > 0) {
navigate(`/posts?tags=${searchTerms.join("+")}`);
} else {
navigate(`/posts`);
}
};
</script>
<section class="hero is-primary is-medium">
<section class="hero is-small">
<div class="hero-body">
<p class="title">Shioriko</p>
<p class="subtitle">Booru-style gallery written in Go and Svelte</p>
<div class="container has-text-centered">
<p class="title">Shioriko</p>
<p class="subtitle">Booru-style gallery written in Go and Svelte</p>
</div>
</div>
<div class="hero-foot">
<div class="container has-text-centered">
<form on:submit|preventDefault={onSearch}>
<div class="field has-addons">
<div class="control is-expanded">
<div class="control" id="tags">
<Tags
tags={searchTerms}
addKeys={[9, 32]}
on:tags={onTagChange}
autoComplete={onAutocomplete}
/>
</div>
</div>
<div class="control">
<button type="submit" class="button is-primary"> Search </button>
</div>
</div>
</form>
</div>
</div>
</section>

View File

@ -5,7 +5,7 @@
let username = "";
let password = "";
let error = "";
const doLogin = async () => {
error = "";
try {
@ -24,43 +24,45 @@
</div>
</section>
<div class="container">
<form on:submit|preventDefault={doLogin}>
<div class="field">
<label for="username" class="label">Username</label>
<div class="control">
<input
id="username"
class="input"
type="text"
placeholder="Username"
bind:value={username}
required
/>
</div>
</div>
<div class="field">
<label for="password" class="label">Password</label>
<div class="control">
<input
id="password"
class="input"
type="password"
placeholder="Password"
bind:value={password}
required
/>
</div>
</div>
{#if error}
<section class="section">
<div class="container">
<form on:submit|preventDefault={doLogin}>
<div class="field">
<p class="has-text-danger">{error}</p>
<label for="username" class="label">Username</label>
<div class="control">
<input
id="username"
class="input"
type="text"
placeholder="Username"
bind:value={username}
required
/>
</div>
</div>
{/if}
<div class="field">
<div class="control">
<button class="button is-link">Login</button>
<div class="field">
<label for="password" class="label">Password</label>
<div class="control">
<input
id="password"
class="input"
type="password"
placeholder="Password"
bind:value={password}
required
/>
</div>
</div>
</div>
</form>
</div>
{#if error}
<div class="field">
<p class="has-text-danger">{error}</p>
</div>
{/if}
<div class="field">
<div class="control">
<button class="button is-link">Login</button>
</div>
</div>
</form>
</div>
</section>

View File

@ -40,6 +40,13 @@
const toggleEditMenu = () => {
editMenuShown = !editMenuShown;
};
let imagePercentage = "0%";
$: {
if (post)
imagePercentage = ((1000 * 100) / post.width).toFixed(0) + "%";
}
</script>
{#if post}
@ -82,8 +89,10 @@
<div class="column box">
{#if post.width > 1000}
<div class="notification is-info">
The image has been resized due to size. The original
image link is in the sidebar
Resized to {imagePercentage} of the original image.
<a href={post.image_path} target="_blank"
>View original</a
>
</div>
<figure class="image">
<img alt={post.id} src={post.preview_path} />
@ -97,5 +106,4 @@
</div>
</section>
</div>
{/if}

View File

@ -2,7 +2,6 @@
import { onMount } from "svelte";
import { getPostSearchTag, getTagAutocomplete } from "../api.js";
import { Link, navigate } from "svelte-routing";
import InfiniteScroll from "svelte-infinite-scroll";
import TagLinkNumbered from "../TagLinkNumbered.svelte";
import queryString from "query-string";
import Tags from "svelte-tags-input";
@ -17,6 +16,7 @@
let totalPages = 1;
let pagination = [];
let posts = [];
let postCount = 0;
let tags = [];
let categorizedTags = {};
@ -26,11 +26,13 @@
posts = data.posts;
tags = data.tags.sort((a, b) => b.postCount - a.postCount);
totalPages = data.totalPage;
postCount = data.postCount;
pagination = paginate(page, totalPages);
} else {
posts = [];
tags = [];
totalPages = 0;
postCount = 0;
pagination = paginate(page, totalPages);
}
};
@ -65,36 +67,43 @@
};
const changePage = (i) => {
page = i;
getData();
}
if (i >= 1 && i <= totalPages) {
page = i;
getData();
}
};
</script>
<section class="section">
<div class="container">
<div class="block">
<form on:submit|preventDefault={onSearch}>
<div class="field has-addons">
<div class="control is-expanded">
<div class="control" id="tags">
<Tags
tags={searchTerms}
addKeys={[9, 32]}
on:tags={onTagChange}
autoComplete={onAutocomplete}
/>
</div>
</div>
<div class="control">
<button type="submit" class="button is-primary">
Search
</button>
<div class="columns is-multiline">
<div class="column is-full">
<div class="block">
<form on:submit|preventDefault={onSearch}>
<div class="field has-addons">
<div class="control is-expanded">
<div class="control" id="tags">
<Tags
tags={searchTerms}
addKeys={[9, 32]}
on:tags={onTagChange}
autoComplete={onAutocomplete}
/>
</div>
</div>
<div class="control">
<button
type="submit"
class="button is-primary"
>
Search
</button>
</div>
</div>
</form>
</div>
</div>
</form>
</div>
<div class="block">
<div class="columns">
<div class="column is-one-third">
<div class="panel is-primary">
<div class="panel-heading">Tags</div>
@ -105,7 +114,9 @@
<li>
<TagLinkNumbered
class=""
tag={tag.tagType+":"+tag.tagName}
tag={tag.tagType +
":" +
tag.tagName}
num={tag.postCount}
/>
</li>
@ -115,8 +126,33 @@
</div>
</div>
</div>
<div class="column is-two-thirds">
<div class="column is-two-thirds">
<div class="columns is-multiline">
<div class="column is-full">
<div class="columns is-multiline">
{#each posts as post, i (post.id)}
<div class="column is-one-quarter">
<div class="block">
<div class="card">
<div class="card-image">
<figure class="image">
<Link
to="/post/{post.id}"
>
<img
alt={post.id}
src={post.thumbnail_path}
/>
</Link>
</figure>
</div>
</div>
</div>
</div>
{/each}
</div>
</div>
<div class="column is-full">
<nav
class="pagination is-centered"
@ -126,12 +162,15 @@
<a
href={null}
on:click={changePage(page - 1)}
class="pagination-previous">Previous</a
class="pagination-previous"
class:is-disabled={page == 1}>Previous</a
>
<a
href={null}
on:click={changePage(page + 1)}
class="pagination-next">Next page</a
class="pagination-next"
class:is-disabled={page == totalPages}
>Next</a
>
<ul class="pagination-list">
{#each pagination as pageEntry}
@ -147,7 +186,7 @@
<a
href={null}
on:click={() =>
(changePage(pageEntry))}
changePage(pageEntry)}
class="pagination-link"
class:is-current={page ==
pageEntry}
@ -160,39 +199,9 @@
</ul>
</nav>
</div>
<div class="column is-full">
<div class="columns is-multiline">
{#each posts as post, i (post.id)}
<div class="column is-one-third">
<div class="block">
<div class="card">
<div class="card-image">
<figure class="image">
<Link
to="/post/{post.id}"
>
<img
alt={post.id}
src={post.thumbnail_path}
/>
</Link>
</figure>
</div>
<div class="card-content" />
</div>
</div>
</div>
{/each}
</div>
</div>
</div>
</div>
</div>
</div>
{#if page >= totalPages}
<div class="notification is-primary">
<p class="has-text-centered">End of posts</p>
</div>
{/if}
</div>
</section>

View File

@ -16,6 +16,7 @@
<section class="section">
<div class="container">
<h1 class="title">Tag List</h1>
<table class="table is-fullwidth">
<thead>
<tr>

View File

@ -53,6 +53,7 @@
<section class="section">
<div class="container">
<h1 class="title">Upload Image</h1>
<form on:submit|preventDefault={onSubmit}>
<div class="field">
<label for="file" class="label">Image File</label>

View File

@ -4,7 +4,7 @@
const paginate = (c, m) => {
let current = c,
last = m,
delta = 2,
delta = 1,
left = current - delta,
right = current + delta + 1,
range = [],