feat: Post indexes

This commit is contained in:
Damillora 2021-05-10 09:45:40 +07:00
parent ba4ebe1793
commit 9624a408b2
9 changed files with 193 additions and 4726 deletions

View File

@ -8,7 +8,9 @@ RUN CGO_ENABLED=0 GOOS=linux go build -o /shioriko
RUN mkdir -p /web && cp -r web/static web/template /web RUN mkdir -p /web && cp -r web/static web/template /web
FROM scratch AS runtime FROM scratch AS runtime
WORKDIR /
COPY --from=build /shioriko / COPY --from=build /shioriko /
COPY --from=build /web / COPY --from=build /web /web
ENTRYPOINT ["/shioriko"] ENTRYPOINT ["/shioriko"]

View File

@ -2,6 +2,7 @@ package app
import ( import (
"net/http" "net/http"
"os"
"path/filepath" "path/filepath"
"github.com/Damillora/Shioriko/pkg/config" "github.com/Damillora/Shioriko/pkg/config"
@ -32,9 +33,18 @@ func uploadBlob(c *gin.Context) {
}) })
} }
id := uuid.NewString() id := uuid.NewString()
folder1 := id[0:2]
if _, err := os.Stat(filepath.Join(dataDir, folder1)); os.IsNotExist(err) {
os.Mkdir(filepath.Join(dataDir, folder1), 0755)
}
folder2 := id[2:4]
if _, err := os.Stat(filepath.Join(dataDir, folder1, folder2)); os.IsNotExist(err) {
os.Mkdir(filepath.Join(dataDir, folder1, folder2), 0755)
}
filename := id + filepath.Ext(file.Filename) filename := id + filepath.Ext(file.Filename)
err = c.SaveUploadedFile(file, filepath.Join(dataDir, filename)) err = c.SaveUploadedFile(file, filepath.Join(dataDir, folder1, folder2, filename))
if err != nil { if err != nil {
c.JSON(http.StatusBadRequest, models.ErrorResponse{ c.JSON(http.StatusBadRequest, models.ErrorResponse{
Code: http.StatusBadRequest, Code: http.StatusBadRequest,
@ -44,7 +54,7 @@ func uploadBlob(c *gin.Context) {
blob := database.Blob{ blob := database.Blob{
ID: id, ID: id,
FilePath: filename, FilePath: filepath.Join(folder1, folder2, filename),
} }
database.DB.Create(&blob) database.DB.Create(&blob)

View File

@ -18,6 +18,7 @@
"svelte": "^3.0.0" "svelte": "^3.0.0"
}, },
"dependencies": { "dependencies": {
"query-string": "^7.0.0",
"sirv-cli": "^1.0.0", "sirv-cli": "^1.0.0",
"svelte-routing": "^1.6.0" "svelte-routing": "^1.6.0"
} }

View File

@ -9,6 +9,13 @@
post = data; post = data;
} }
const trimUrl = (str) => {
if(str.length > 30) {
return str.substring(0,30) + "...";
}
return str;
}
onMount(() => {getData()}); onMount(() => {getData()});
</script> </script>
@ -25,19 +32,23 @@
{#if post} {#if post}
<div class="container"> <div class="container">
<section class="section"> <section class="section">
<div class="tile is-ancestor"> <div class="columns">
<div class="tile is-child is-4 box"> <div class="column is-one-third box">
<p> <p>
Source URL: <a href="//{post.source_url}">{post.source_url}</a> Source URL: <a href="{post.source_url}">{trimUrl(post.source_url)}</a>
</p> </p>
<p> <p>
Tags: Tags:
{#each post.tags as tag (tag)} {#each post.tags as tag (tag)}
<Link to="/tag/{tag}">{tag}</Link> <ul>
<li>
<Link to="/tag/{tag}">{tag}</Link>
</li>
</ul>
{/each} {/each}
</p> </p>
</div> </div>
<div class="tile is-child"> <div class="column">
<figure class="image"> <figure class="image">
<img src="{post.image_path}"> <img src="{post.image_path}">
</figure> </figure>

View File

@ -2,16 +2,34 @@
import { onMount } from "svelte"; import { onMount } from "svelte";
import { getPosts } from "../api.js"; import { getPosts } from "../api.js";
import { Link} from "svelte-routing"; import { Link} from "svelte-routing";
import queryString from "query-string";
export let location;
let page = 1; let page = 1;
let totalPages = 1; let totalPages = 1;
let posts = []; let posts = [];
const getData = async () => { const getData = async () => {
const data = await getPosts({page}); const data = await getPosts({page});
posts = data.posts; if(Array.isArray(data.posts)) {
posts = data.posts;
}
} }
onMount(() => { getData(); }) onMount(() => {
let queryParams;
$: queryParams = queryString.parse(location.search);
if(queryParams.page) {
page = queryParams.page;
}
getData();
})
const handlePage = (i) => {
return () => {
page = 1;
getData();
}
}
</script> </script>
<section class="hero is-primary"> <section class="hero is-primary">
@ -24,9 +42,48 @@
<section class="section"> <section class="section">
<div class="container"> <div class="container">
<div class="tile is-ancestor"> <nav class="pagination" role="navigation" aria-label="pagination">
{#if page > 1}
<a class="pagination-previous">Previous</a>
{/if}
{#if page < totalPages}
<a class="pagination-next">Next page</a>
{/if}
<ul class="pagination-list">
{#if page > 2}
<li>
<Link on:click="{handlePage(1)}" to="/posts?page={1}" class="pagination-link" aria-label="Goto page 1">1</Link>
</li>
<li>
<span class="pagination-ellipsis">&hellip;</span>
</li>
{/if}
{#each [...Array(5).keys()].map(x => x + page - 2) as i }
{#if i >= 1 && i <= totalPages}
{#if i == page}
<li>
<Link on:click="{handlePage(i)}" to="/posts?page={i}" class="pagination-link is-current" aria-label="Goto page {i}">{i}</Link>
</li>
{:else}
<li>
<Link on:click="{handlePage(i)}" to="/posts?page={i}" class="pagination-link" aria-label="Goto page {i}">{i}</Link>
</li>
{/if}
{/if}
{/each}
{#if (totalPages - page) > 2}
<li>
<span class="pagination-ellipsis">&hellip;</span>
</li>
<li>
<Link on:click="{handlePage(totalPages)}" to="/posts?page={totalPages}" class="pagination-link" aria-label="Goto page {totalPages}">{totalPages}</Link>
</li>
{/if}
</ul>
</nav>
<div class="columns is-multiline">
{#each posts as post (post.id)} {#each posts as post (post.id)}
<div class="tile is-child is-4 card"> <div class="column is-one-quarter card">
<div class="card-image"> <div class="card-image">
<figure class="image"> <figure class="image">
<Link to="/post/{post.id}"> <Link to="/post/{post.id}">
@ -37,7 +94,9 @@
<div class="card-content"> <div class="card-content">
<div class="content"> <div class="content">
{#each post.tags as tag (tag)} {#each post.tags as tag (tag)}
<Link to="/tag/{tag}">{tag}</Link> <p>
<Link to="/tag/{tag}">{tag}</Link>
</p>
{/each} {/each}
</div> </div>
</div> </div>

View File

@ -2,6 +2,9 @@
import { onMount } from "svelte"; import { onMount } from "svelte";
import { getPostsTag } from "../api.js"; import { getPostsTag } from "../api.js";
import { Link} from "svelte-routing"; import { Link} from "svelte-routing";
import queryString from "query-string";
export let location;
export let id; export let id;
@ -10,10 +13,25 @@
let posts = []; let posts = [];
const getData = async () => { const getData = async () => {
const data = await getPostsTag({page, tag: id}); const data = await getPostsTag({page, tag: id});
posts = data.posts; if(Array.isArray(data.posts)) {
posts = data.posts;
}
} }
onMount(() => { getData(); }) onMount(() => {
let queryParams;
queryParams = queryString.parse(location.search);
if(queryParams.page) {
page = queryParams.page;
}
getData();
})
const handlePage = (i) => {
return () => {
page = 1;
getData();
}
}
</script> </script>
<section class="hero is-primary"> <section class="hero is-primary">
@ -22,16 +40,55 @@
{id} {id}
</p> </p>
<p class="subtitle"> <p class="subtitle">
Tag Tag
</p> </p>
</div> </div>
</section> </section>
<section class="section"> <section class="section">
<div class="container"> <div class="container">
<div class="tile is-ancestor"> <nav class="pagination" role="navigation" aria-label="pagination">
{#if page > 1}
<a class="pagination-previous">Previous</a>
{/if}
{#if page < totalPages}
<a class="pagination-next">Next page</a>
{/if}
<ul class="pagination-list">
{#if page > 2}
<li>
<Link on:click="{handlePage(1)}" to="/tag/{id}?page={1}" class="pagination-link" aria-label="Goto page 1">1</Link>
</li>
<li>
<span class="pagination-ellipsis">&hellip;</span>
</li>
{/if}
{#each [...Array(5).keys()].map(x => x + page - 2) as i }
{#if i >= 1 && i <= totalPages}
{#if i == page}
<li>
<Link on:click="{handlePage(i)}" to="/tag/{id}?page={i}" class="pagination-link is-current" aria-label="Goto page {i}">{i}</Link>
</li>
{:else}
<li>
<Link on:click="{handlePage(i)}" to="/tag/{id}?page={i}" class="pagination-link" aria-label="Goto page {i}">{i}</Link>
</li>
{/if}
{/if}
{/each}
{#if (totalPages - page) > 2}
<li>
<span class="pagination-ellipsis">&hellip;</span>
</li>
<li>
<Link on:click="{handlePage(totalPages)}" to="/tag/{id}?page={totalPages}" class="pagination-link" aria-label="Goto page {totalPages}">{totalPages}</Link>
</li>
{/if}
</ul>
</nav>
<div class="columns is-multiline">
{#each posts as post (post.id)} {#each posts as post (post.id)}
<div class="tile is-child is-4 card"> <div class="column is-one-quarter card">
<div class="card-image"> <div class="card-image">
<figure class="image"> <figure class="image">
<Link to="/post/{post.id}"> <Link to="/post/{post.id}">
@ -42,7 +99,9 @@
<div class="card-content"> <div class="card-content">
<div class="content"> <div class="content">
{#each post.tags as tag (tag)} {#each post.tags as tag (tag)}
<Link to="/tag/{tag}">{tag}</Link> <p>
<Link to="/tag/{tag}">{tag}</Link>
</p>
{/each} {/each}
</div> </div>
</div> </div>

View File

@ -198,6 +198,11 @@ console-clear@^1.1.0:
resolved "https://registry.yarnpkg.com/console-clear/-/console-clear-1.1.1.tgz#995e20cbfbf14dd792b672cde387bd128d674bf7" resolved "https://registry.yarnpkg.com/console-clear/-/console-clear-1.1.1.tgz#995e20cbfbf14dd792b672cde387bd128d674bf7"
integrity sha512-pMD+MVR538ipqkG5JXeOEbKWS5um1H4LUUccUQG68qpeqBYbzYy79Gh55jkd2TtPdRfUaLWdv6LPP//5Zt0aPQ== integrity sha512-pMD+MVR538ipqkG5JXeOEbKWS5um1H4LUUccUQG68qpeqBYbzYy79Gh55jkd2TtPdRfUaLWdv6LPP//5Zt0aPQ==
decode-uri-component@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=
dedent-js@^1.0.1: dedent-js@^1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/dedent-js/-/dedent-js-1.0.1.tgz#bee5fb7c9e727d85dffa24590d10ec1ab1255305" resolved "https://registry.yarnpkg.com/dedent-js/-/dedent-js-1.0.1.tgz#bee5fb7c9e727d85dffa24590d10ec1ab1255305"
@ -235,6 +240,11 @@ fill-range@^7.0.1:
dependencies: dependencies:
to-regex-range "^5.0.1" to-regex-range "^5.0.1"
filter-obj@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/filter-obj/-/filter-obj-1.1.0.tgz#9b311112bc6c6127a16e016c6c5d7f19e0805c5b"
integrity sha1-mzERErxsYSehbgFsbF1/GeCAXFs=
fs.realpath@^1.0.0: fs.realpath@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
@ -470,6 +480,16 @@ picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2:
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.3.tgz#465547f359ccc206d3c48e46a1bcb89bf7ee619d" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.3.tgz#465547f359ccc206d3c48e46a1bcb89bf7ee619d"
integrity sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg== integrity sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg==
query-string@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/query-string/-/query-string-7.0.0.tgz#aaad2c8d5c6a6d0c6afada877fecbd56af79e609"
integrity sha512-Iy7moLybliR5ZgrK/1R3vjrXq03S13Vz4Rbm5Jg3EFq1LUmQppto0qtXz4vqZ386MSRjZgnTSZ9QC+NZOSd/XA==
dependencies:
decode-uri-component "^0.2.0"
filter-obj "^1.1.0"
split-on-first "^1.0.0"
strict-uri-encode "^2.0.0"
randombytes@^2.1.0: randombytes@^2.1.0:
version "2.1.0" version "2.1.0"
resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
@ -613,6 +633,16 @@ sourcemap-codec@^1.4.4:
resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4"
integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==
split-on-first@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f"
integrity sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==
strict-uri-encode@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546"
integrity sha1-ucczDHBChi9rFC3CdLvMWGbONUY=
supports-color@^5.3.0: supports-color@^5.3.0:
version "5.5.0" version "5.5.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long