feat: another UI change

This commit is contained in:
Damillora 2025-02-24 13:03:20 +00:00
parent 4c2fb159a9
commit 1fd9e364bb
16 changed files with 373 additions and 281 deletions

View File

@ -112,6 +112,7 @@ func postGetOne(c *gin.Context) {
Width: post.Blob.Width, Width: post.Blob.Width,
Height: post.Blob.Height, Height: post.Blob.Height,
Uploader: post.User.Username, Uploader: post.User.Username,
UploadDate: post.CreatedAt,
}) })
} }

View File

@ -1,5 +1,7 @@
package models package models
import "time"
type PostReadModel struct { type PostReadModel struct {
ID string `json:"id"` ID string `json:"id"`
ImagePreviewPath string `json:"preview_path"` ImagePreviewPath string `json:"preview_path"`
@ -9,6 +11,7 @@ type PostReadModel struct {
Width int `json:"width"` Width int `json:"width"`
Height int `json:"height"` Height int `json:"height"`
Uploader string `json:"uploader"` Uploader string `json:"uploader"`
UploadDate time.Time `json:"upload_date"`
} }
type TagReadModel struct { type TagReadModel struct {

View File

@ -10,6 +10,7 @@
"dependencies": { "dependencies": {
"axios": "^1.4.0", "axios": "^1.4.0",
"bulma": "^1.0.3", "bulma": "^1.0.3",
"date-fns": "^4.1.0",
"query-string": "^8.1.0" "query-string": "^8.1.0"
}, },
"devDependencies": { "devDependencies": {
@ -1853,6 +1854,16 @@
"node": ">=4" "node": ">=4"
} }
}, },
"node_modules/date-fns": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz",
"integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/kossnocorp"
}
},
"node_modules/debug": { "node_modules/debug": {
"version": "4.4.0", "version": "4.4.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",

View File

@ -30,6 +30,7 @@
"dependencies": { "dependencies": {
"axios": "^1.4.0", "axios": "^1.4.0",
"bulma": "^1.0.3", "bulma": "^1.0.3",
"date-fns": "^4.1.0",
"query-string": "^8.1.0" "query-string": "^8.1.0"
} }
} }

View File

@ -0,0 +1,38 @@
<script>
import { postDelete } from "$lib/api";
let { id, toggleDeleteMenu, onDelete } = $props();
let deleteLoading = $state(false);
const deletePost = async (e) => {
e.preventDefault();
deleteLoading = true;
const success = await postDelete({ id });
deleteLoading = false;
toggleDeleteMenu(e);
onDelete(success);
};
</script>
<div class="block">
<div class="panel is-danger">
<p class="panel-heading">Delete Post</p>
{#if !deleteLoading}
<div class="panel-block">
Are you sure to delete post {id}?
</div>
<div class="panel-block column">
<button onclick={deletePost} class="button is-danger"
>Delete</button
>
<button class="button" onclick={toggleDeleteMenu}>Cancel</button
>
</div>
{:else}
<div class="panel-block column">
<progress class="progress is-small is-danger" max="100"
></progress>
</div>
{/if}
</div>
</div>

View File

@ -11,6 +11,8 @@
let { isActive = $bindable(false), post, onSubmit }: Props = $props(); let { isActive = $bindable(false), post, onSubmit }: Props = $props();
let editLoading = $state(false);
const toggleEditModal = (e) => { const toggleEditModal = (e) => {
e.preventDefault(); e.preventDefault();
isActive = !isActive; isActive = !isActive;
@ -37,9 +39,10 @@
const onFormSubmit = async (e) => { const onFormSubmit = async (e) => {
e.preventDefault(); e.preventDefault();
editLoading = true;
const response = await postUpdate(post.id, form); const response = await postUpdate(post.id, form);
toggleEditModal(); editLoading = false;
toggleEditModal(e);
onSubmit(); onSubmit();
}; };
@ -51,6 +54,7 @@
<form onsubmit={onFormSubmit}> <form onsubmit={onFormSubmit}>
<div class="panel is-warning"> <div class="panel is-warning">
<p class="panel-heading">Edit Post</p> <p class="panel-heading">Edit Post</p>
{#if !editLoading}
<div class="panel-block column"> <div class="panel-block column">
<div class="row"> <div class="row">
<strong>Uploader:</strong> <strong>Uploader:</strong>
@ -115,5 +119,10 @@
>Cancel</button >Cancel</button
> >
</div> </div>
{:else}
<div class="panel-block column">
<progress class="progress is-small is-warning" max="100"></progress>
</div>
{/if}
</div> </div>
</form> </form>

View File

@ -2,16 +2,12 @@
import { onMount } from "svelte"; import { onMount } from "svelte";
import { updateTagNotes } from "$lib/api"; import { updateTagNotes } from "$lib/api";
let { let { tag, data, toggleEditMenu, onSubmit } = $props();
tag,
data,
toggleEditMenu,
onSubmit
} = $props();
let form = $state({ let form = $state({
note: "", note: "",
}); });
let editNotesLoading = $state(false);
const getData = async () => { const getData = async () => {
form.note = data.tagNote; form.note = data.tagNote;
@ -19,7 +15,9 @@
const onFormSubmit = async (e) => { const onFormSubmit = async (e) => {
e.preventDefault(); e.preventDefault();
editNotesLoading = true;
await updateTagNotes(tag, form); await updateTagNotes(tag, form);
editNotesLoading = false;
toggleEditMenu(); toggleEditMenu();
onSubmit(); onSubmit();
@ -33,18 +31,21 @@
<form onsubmit={onFormSubmit}> <form onsubmit={onFormSubmit}>
<div class="panel is-warning"> <div class="panel is-warning">
<p class="panel-heading">Edit Notes</p> <p class="panel-heading">Edit Notes</p>
<div class="panel-block column"> {#if !editNotesLoading}
<textarea <div class="panel-block column">
bind:value={form.note} <textarea bind:value={form.note} class="textarea has-fixed-size"
class="textarea has-fixed-size" ></textarea>
></textarea> <div class="content"></div>
<div class="content"></div> </div>
</div> <div class="panel-block column">
<div class="panel-block column"> <button type="submit" class="button is-primary">Save</button>
<button type="submit" class="button is-primary">Save</button> <button onclick={toggleEditMenu} class="button">Cancel</button>
<button onclick={toggleEditMenu} class="button" </div>
>Cancel</button {:else}
> <div class="panel-block column">
</div> <progress class="progress is-small is-warning" max="100"
></progress>
</div>
{/if}
</div> </div>
</form> </form>

View File

@ -2,19 +2,16 @@
import { onMount } from "svelte"; import { onMount } from "svelte";
import { getTagTypes, updateTag } from "$lib/api"; import { getTagTypes, updateTag } from "$lib/api";
import { goto } from "$app/navigation";
let { let { tag, data, toggleRenameMenu, onSubmit } = $props();
tag,
data,
toggleRenameMenu,
onSubmit
} = $props();
let tagTypes = $state([]); let tagTypes = $state([]);
let form = $state({ let form = $state({
name: "", name: "",
tagTypeId: 1, tagTypeId: 1,
}); });
let editTagLoading = $state(false);
const getData = async () => { const getData = async () => {
tagTypes = await getTagTypes(); tagTypes = await getTagTypes();
@ -25,10 +22,9 @@
const onFormSubmit = async (e) => { const onFormSubmit = async (e) => {
e.preventDefault(); e.preventDefault();
editTagLoading = true;
await updateTag(tag, form); await updateTag(tag, form);
editTagLoading = false;
goto("/tags/" + form.name);
onSubmit(form.name); onSubmit(form.name);
}; };
@ -40,56 +36,54 @@
<form onsubmit={onFormSubmit}> <form onsubmit={onFormSubmit}>
<div class="panel is-warning"> <div class="panel is-warning">
<p class="panel-heading">Edit Tag</p> <p class="panel-heading">Edit Tag</p>
<div class="panel-block column"> {#if !editTagLoading}
<div class="row"> <div class="panel-block column">
<strong>Name:</strong> <div class="row">
</div> <strong>Name:</strong>
<div class="row"> </div>
<div class="field"> <div class="row">
<div class="control"> <div class="field">
<input <div class="control">
class="input" <input
type="text" class="input"
bind:value={form.name} type="text"
/> bind:value={form.name}
/>
</div>
</div> </div>
</div> </div>
</div> </div>
</div> <div class="panel-block column">
<div class="panel-block column"> <div class="row">
<div class="row"> <strong>Category:</strong>
<strong>Category:</strong> </div>
</div> <div class="row">
<div class="row"> <div class="field">
<div class="field"> <div class="select">
<div class="select"> <select bind:value={form.tagTypeId}>
<select bind:value={form.tagTypeId}> {#each tagTypes as tagType}
{#each tagTypes as tagType} <option
<option value={tagType.id}
value={tagType.id} selected={form.tagTypeId === tagType.id}
selected={form.tagTypeId === tagType.id} >
> {tagType.name}
{tagType.name} </option>
</option> {/each}
{/each} </select>
</select> </div>
</div> </div>
</div> </div>
</div> </div>
</div> <div class="panel-block column">
<div class="panel-block column"> <button class="button is-primary" type="submit">Submit</button>
<div class="row"> <button onclick={toggleRenameMenu} class="button">Cancel</button
<strong>Posts:</strong> >
</div> </div>
<div class="row"> {:else}
{data.postCount} (<a href="/posts?tags={tag}">Browse</a>) <div class="panel-block column">
<progress class="progress is-small is-warning" max="100"
></progress>
</div> </div>
</div> {/if}
<div class="panel-block column">
<button class="button is-primary" type="submit">Submit</button>
<button onclick={toggleRenameMenu} class="button"
>Cancel</button
>
</div>
</div> </div>
</form> </form>

View File

@ -1,8 +1,14 @@
<script lang="ts"> <script lang="ts">
import AuthCheck from "$lib/components/checks/AuthCheck.svelte"; import AuthCheck from "$lib/components/checks/AuthCheck.svelte";
import TagLinkNumbered from "$lib/components/ui/TagLinkNumbered.svelte"; import TagLinkNumbered from "$lib/components/ui/TagLinkNumbered.svelte";
let { post, toggleEditMenu, toggleDeleteMenu } = $props(); import { format, formatDistanceToNow } from "date-fns";
let { post } = $props();
let tabPage = $state(1);
const changeTab = (tab) => {
tabPage = tab;
}
const trimUrl = (str) => { const trimUrl = (str) => {
if (str.length > 30) { if (str.length > 30) {
return str.substring(0, 30) + "..."; return str.substring(0, 30) + "...";
@ -13,6 +19,27 @@
<div class="panel is-primary"> <div class="panel is-primary">
<p class="panel-heading">Post</p> <p class="panel-heading">Post</p>
<div class="panel-tabs">
<a href={"#"} class:is-active="{tabPage == 1}" onclick={() => changeTab(1)}>Tags</a>
<a href={"#"} class:is-active="{tabPage == 2}" onclick={() => changeTab(2)}>Information</a>
</div>
{#if tabPage === 1}
{#if post.tags}
{#each post.tags as tag (tag)}
<TagLinkNumbered
tag={tag.tagType + ":" + tag.tagName}
num={tag.postCount}
/>
{/each}
{/if}
{:else if tabPage == 2}
<div class="panel-block column">
<div class="row">
<strong>Upload Date:</strong>
</div>
<div class="row"><time title={format(post.upload_date, "dd MMMM yyyy HH:mm:ss")} datetime={post.upload_date} >{formatDistanceToNow(post.upload_date, {addSuffix: true })}</time></div>
</div>
<div class="panel-block column"> <div class="panel-block column">
<div class="row"> <div class="row">
<strong>Uploader:</strong> <strong>Uploader:</strong>
@ -43,38 +70,5 @@
<a href={post.source_url}>{trimUrl(post.source_url)}</a> <a href={post.source_url}>{trimUrl(post.source_url)}</a>
</div> </div>
</div> </div>
<div class="panel-block column"> {/if}
<div class="row">
<p><strong>Tags:</strong></p>
</div>
<div class="row">
<div class="menu">
<ul class="menu-list">
{#if post.tags}
{#each post.tags as tag (tag)}
<li>
<TagLinkNumbered
class=""
tag={tag.tagType + ":" + tag.tagName}
num={tag.postCount}
/>
</li>
{/each}
{/if}
</ul>
</div>
</div>
</div>
<AuthCheck>
<p class="panel-block column">
<button
onclick={toggleEditMenu}
class="button is-primary">Edit</button
>
<button
onclick={toggleDeleteMenu}
class="button is-danger">Delete</button
>
</p>
</AuthCheck>
</div> </div>

View File

@ -8,6 +8,12 @@
let { tag, data, toggleRenameMenu } = $props(); let { tag, data, toggleRenameMenu } = $props();
let related_tags = $state([]); let related_tags = $state([]);
let tabPage = $state(1);
const changeTab = (tab) => {
tabPage = tab;
};
const getData = async () => { const getData = async () => {
related_tags = await getRelatedTags({ tag }); related_tags = await getRelatedTags({ tag });
related_tags = related_tags related_tags = related_tags
@ -21,52 +27,45 @@
<div class="panel is-primary"> <div class="panel is-primary">
<p class="panel-heading">Tag</p> <p class="panel-heading">Tag</p>
<div class="panel-block column"> <div class="panel-tabs">
<div class="row"> <a
<strong>Name:</strong> href={"#"}
</div> class:is-active={tabPage == 1}
<div class="row">{data.tagName}</div> onclick={() => changeTab(1)}>Information</a
>
<a
href={"#"}
class:is-active={tabPage == 2}
onclick={() => changeTab(2)}>Related Tags</a
>
</div> </div>
<div class="panel-block column"> {#if tabPage === 1}
<div class="row"> <div class="panel-block column">
<strong>Category:</strong> <div class="row">
<strong>Name:</strong>
</div>
<div class="row">{data.tagName}</div>
</div> </div>
<div class="row"><TagTypeIndicator tagType={data.tagType} /></div> <div class="panel-block column">
</div> <div class="row">
<div class="panel-block column"> <strong>Category:</strong>
<div class="row"> </div>
<strong>Posts:</strong> <div class="row"><TagTypeIndicator tagType={data.tagType} /></div>
</div> </div>
<div class="row"> <div class="panel-block column">
{data.postCount} (<a href="/posts?tags={tag}">Browse</a>) <div class="row">
</div> <strong>Posts:</strong>
</div> </div>
<div class="panel-block column"> <div class="row">
<div class="row"> {data.postCount}
<strong>Related Tags:</strong>
</div>
<div class="row">
<div class="menu">
<ul class="menu-list">
{#each related_tags as tag (tag)}
<li>
<TagLinkNumbered
class=""
tag={tag.tagType + ":" + tag.tagName}
num={tag.postCount}
/>
</li>
{/each}
</ul>
</div> </div>
</div> </div>
</div> {:else if tabPage === 2}
<AuthCheck> {#each related_tags as tag (tag)}
<div class="panel-block column"> <TagLinkNumbered
<button tag={tag.tagType + ":" + tag.tagName}
onclick={toggleRenameMenu} num={tag.postCount}
class="button is-primary">Rename</button />
> {/each}
</div> {/if}
</AuthCheck>
</div> </div>

View File

@ -8,10 +8,10 @@
let tagDisplay = tagName.split("_").join(" "); let tagDisplay = tagName.split("_").join(" ");
</script> </script>
<a href="/posts?tags={tagName}"> <a class="panel-block is-block" href="/posts?tags={tagName}">
<span> <span>
{tagDisplay} {tagDisplay}
</span> </span>
<TagTypeIndicator tagType={tagType}></TagTypeIndicator> <TagTypeIndicator {tagType}></TagTypeIndicator>
<span class="is-pulled-right">{num}</span> <span class="is-pulled-right">{num}</span>
</a> </a>

View File

@ -7,15 +7,17 @@
import { page } from "$app/stores"; import { page } from "$app/stores";
import ShiorikoImage from "$lib/components/ui/ShiorikoImage.svelte"; import ShiorikoImage from "$lib/components/ui/ShiorikoImage.svelte";
import AuthCheck from "$lib/components/checks/AuthCheck.svelte";
import DeletePostPanel from "$lib/components/panels/DeletePostPanel.svelte";
const { id } = $page.params; const { id } = $page.params;
let post: any = $state(); let post: any = $state();
const getData = async () => { const getData = async () => {
post = null;
const data = await getPost({ id }); const data = await getPost({ id });
post = data; post = data;
imagePercentage = ((1000 * 100) / post.width).toFixed(0) + "%"; imagePercentage = ((1000 * 100) / post.width).toFixed(0) + "%";
}; };
let loading = $state(false);
let isOriginal = $state(false); let isOriginal = $state(false);
const trimUrl = (str: string) => { const trimUrl = (str: string) => {
@ -25,25 +27,22 @@
return str; return str;
}; };
let deleteMenuShown = $state(false); let deleteMenuShown = $state(false);
const onSubmitEdit = () => { const onSubmitEdit = () => {
getData(); getData();
editMenuShown = false; editMenuShown = false;
} };
onMount(() => { onMount(() => {
getData(); getData();
}); });
const deletePost = async (e) => { const onDelete = async (success) => {
e.preventDefault();
toggleDeleteMenu(e);
const success = await postDelete({ id });
if (success) { if (success) {
goto("/posts"); goto("/posts");
} }
}; };
const toggleDeleteMenu = (e) => { const toggleDeleteMenu = (e) => {
e.preventDefault(); e.preventDefault();
deleteMenuShown = !deleteMenuShown; deleteMenuShown = !deleteMenuShown;
@ -64,68 +63,85 @@
<div class="columns"> <div class="columns">
<div class="column is-one-third"> <div class="column is-one-third">
{#if post} {#if post}
{#if editMenuShown == false && deleteMenuShown == false} <div class="block">
<ViewPostPanel <ViewPostPanel {post} />
{post} </div>
{toggleDeleteMenu} {#if editMenuShown == true && deleteMenuShown == false}
{toggleEditMenu} <div class="block">
/> <EditPostPanel
{:else if editMenuShown == true} bind:isActive={editMenuShown}
<EditPostPanel {post}
bind:isActive={editMenuShown} onSubmit={onSubmitEdit}
{post} />
onSubmit={onSubmitEdit}
/>
{:else if deleteMenuShown == true}
<div class="panel is-danger">
<p class="panel-heading">Delete Post</p>
<div class="panel-block">
Are you sure to delete post {post.id}?
</div>
<div class="panel-block column">
<button
onclick={deletePost}
class="button is-danger">Delete</button
>
<button
class="button"
onclick={toggleDeleteMenu}>Cancel</button
>
</div>
</div> </div>
{:else if deleteMenuShown == true}
<DeletePostPanel
id={post.id}
{toggleDeleteMenu}
{onDelete}
/>
{:else}
<AuthCheck>
<div class="panel is-info">
<div class="panel-heading">Post Actions</div>
<a
class="panel-block"
href={post.image_path}
target="_blank">View Original</a
>
<a
href={"#"}
onclick={toggleEditMenu}
class="panel-block">Edit</a
>
<a
href={"#"}
onclick={toggleDeleteMenu}
class="panel-block">Delete</a
>
</div>
</AuthCheck>
{/if} {/if}
{:else} {:else}
<div class="skeleton-block"></div> <div class="skeleton-block"></div>
{/if} {/if}
</div> </div>
<div class="column box"> <div class="column is-two-thirds">
{#if post} {#if post}
{#if post.width > 1000 && isOriginal == false} <div class="block">
<div class="notification is-info"> {#if post.width > 1000 && isOriginal == false}
Resized to {imagePercentage} of the original image. <div class="notification is-info">
<a Resized to {imagePercentage} of the original image.
onclick={() => { <a
isOriginal = true; href={"#"}
}}>View original</a onclick={() => {
> isOriginal = true;
</div> }}>View original</a
<figure class="image"> >
<ShiorikoImage </div>
alt={post.id} <div class="box">
src={post.preview_path} <figure class="image">
/> <ShiorikoImage
</figure> alt={post.id}
{:else} src={post.preview_path}
<div class="notification is-primary"> />
Currently viewing original image. </figure>
</div> </div>
<figure class="image"> {:else}
<ShiorikoImage <div class="notification is-primary">
alt={post.id} Currently viewing original image.
src={post.image_path} </div>
/> <div class="box">
</figure> <figure class="image">
{/if} <ShiorikoImage
alt={post.id}
src={post.image_path}
/>
</figure>
</div>
{/if}
</div>
{:else} {:else}
<div class="skeleton-block"></div> <div class="skeleton-block"></div>
{/if} {/if}

View File

@ -127,32 +127,17 @@
</div> </div>
</form> </form>
</div> </div>
<div class="panel-block column"> {#if !loading}
{#if !loading} {#each tags as tag (tag)}
<div class="row"> <TagLinkNumbered
<strong>Tags:</strong> class=""
</div> tag={tag.tagType + ":" + tag.tagName}
<div class="row"> num={tag.postCount}
<div class="menu"> />
<ul class="menu-list"> {/each}
{#each tags as tag (tag)} {:else}
<li> <div class="skeleton-block"></div>
<TagLinkNumbered {/if}
class=""
tag={tag.tagType +
":" +
tag.tagName}
num={tag.postCount}
/>
</li>
{/each}
</ul>
</div>
</div>
{:else}
<div class="skeleton-block"></div>
{/if}
</div>
</div> </div>
{#if tagInfo} {#if tagInfo}
<div class="panel is-info"> <div class="panel is-info">

View File

@ -1,52 +1,63 @@
<script> <script>
import { run } from 'svelte/legacy'; import { run } from "svelte/legacy";
import { getTags } from "$lib/api"; import { getTags } from "$lib/api";
import { afterNavigate } from '$app/navigation'; import { afterNavigate } from "$app/navigation";
import TagTypeIndicator from '$lib/components/ui/TagTypeIndicator.svelte'; import TagTypeIndicator from "$lib/components/ui/TagTypeIndicator.svelte";
let tags = $state([]); let tags = $state([]);
let loading = $state(false); let loading = $state(false);
let highestCount = $state(1);
const getData = async () => { const getData = async () => {
const data = await getTags(); const data = await getTags();
tags = data; tags = data;
loading = false; loading = false;
highestCount = Math.max(...data.map((x) => x.postCount));
if (highestCount <= 0) {
highestCount = 1;
}
}; };
afterNavigate(() => { afterNavigate(() => {
loading = true; loading = true;
getData(); getData();
}) });
</script> </script>
<section class="section"> <section class="section">
<div class="container"> <div class="container">
<h1 class="title">Tag List</h1> <h1 class="title">Tag List</h1>
{#if !loading} {#if !loading}
<table class="table is-fullwidth"> <table class="table is-fullwidth">
<thead> <thead>
<tr>
<th >Tag</th>
<th style="width: 30%;">Tag Type</th>
<th style="width: 10%;">Post Count</th>
</tr>
</thead>
<tbody>
{#each tags as tag}
<tr> <tr>
<td> <th>Tag</th>
<a href="/tags/{tag.tagName}">{tag.tagName}</a> <th>Post Count</th>
</td>
<td><TagTypeIndicator tagType={tag.tagType} /></td>
<td>{tag.postCount}</td>
</tr> </tr>
{/each} </thead>
</tbody> <tbody>
</table> {#each tags as tag}
<tr>
<td>
<a href="/tags/{tag.tagName}"
>{tag.tagName}
<TagTypeIndicator
tagType={tag.tagType}
/></a
>
</td>
<td>
<span class="is-pulled-right"
>{tag.postCount}</span
></td
>
</tr>
{/each}
</tbody>
</table>
{:else} {:else}
<div class="skeleton-block"></div> <div class="skeleton-block"></div>
{/if} {/if}
</div> </div>
</section> </section>

View File

@ -9,6 +9,7 @@
import PostGallery from "$lib/components/ui/PostGallery.svelte"; import PostGallery from "$lib/components/ui/PostGallery.svelte";
import { page } from "$app/stores"; import { page } from "$app/stores";
import AuthCheck from "$lib/components/checks/AuthCheck.svelte";
let { tag } = $state($page.params); let { tag } = $state($page.params);
let data = $state(); let data = $state();
@ -16,6 +17,7 @@
const getData = async () => { const getData = async () => {
if (tag) { if (tag) {
data = null;
data = await getTag({ tag }); data = await getTag({ tag });
const response = await getPosts({ const response = await getPosts({
page: 1, page: 1,
@ -40,6 +42,7 @@
const onTagSubmit = (newName) => { const onTagSubmit = (newName) => {
tag = newName; tag = newName;
toggleEditMenu();
getData(); getData();
}; };
@ -53,15 +56,28 @@
<div class="columns"> <div class="columns">
<div class="column is-one-third"> <div class="column is-one-third">
{#if data} {#if data}
<div class="block">
<ViewTagPanel {tag} {data} />
</div>
{#if renameMenuShown} {#if renameMenuShown}
<div class="block">
<EditTagPanel <EditTagPanel
{tag} {tag}
{data} {data}
{toggleRenameMenu} {toggleRenameMenu}
onSubmit={onTagSubmit} onSubmit={onTagSubmit}
/> />
</div>
{:else} {:else}
<ViewTagPanel {tag} {data} {toggleRenameMenu} /> <AuthCheck>
<div class="panel is-info">
<div class="panel-heading">Tag Actions</div>
<a class="panel-block" href="/posts?tags={tag}">Browse Posts</a>
<a onclick={toggleRenameMenu} class="panel-block"
>Rename</a
>
</div>
</AuthCheck>
{/if} {/if}
{:else} {:else}
<div class="skeleton-block"></div> <div class="skeleton-block"></div>

View File

@ -10,6 +10,7 @@
let fileName = $state(""); let fileName = $state("");
let similar = $state([]); let similar = $state([]);
let previewUrl = $state(""); let previewUrl = $state("");
let loading = $state(false);
let form = $state({ let form = $state({
blob_id: "", blob_id: "",
@ -23,6 +24,7 @@
}; };
const onFileChange = async (e) => { const onFileChange = async (e) => {
loading = true;
var file = e.target.files[0]; var file = e.target.files[0];
fileName = ""; fileName = "";
previewUrl = ""; previewUrl = "";
@ -38,6 +40,7 @@
fileName = file.name; fileName = file.name;
previewUrl = response.previewUrl; previewUrl = response.previewUrl;
} }
loading = false;
}; };
const onTagChange = (value) => { const onTagChange = (value) => {
@ -94,6 +97,17 @@
</div> </div>
</div> </div>
</div> </div>
{#if currentProgress > 0 && currentProgress < 100}
<div class="panel-block column">
<progress
class="progress is-primary is-small"
value={currentProgress}
max="100"
>
{currentProgress}%
</progress>
</div>
{/if}
<div class="panel-block column"> <div class="panel-block column">
<div class="row"> <div class="row">
<label for="source" class="label" <label for="source" class="label"
@ -143,7 +157,7 @@
</div> </div>
</div> </div>
<div class="column is-two-thirds"> <div class="column is-two-thirds">
<div class="box"> <div class="block">
{#if fileName} {#if fileName}
{#if similar.length > 0} {#if similar.length > 0}
<div class="notification is-warning"> <div class="notification is-warning">
@ -157,21 +171,11 @@
{/each} {/each}
</div> </div>
{:else} {:else}
<div class="notification is-primary"> <div class="notification is-success">
{fileName} has been succesfully uploaded. {fileName} has been succesfully uploaded.
</div> </div>
{/if} {/if}
<figure class="image">
<ShiorikoImage alt={fileName} src={previewUrl} />
</figure>
{:else if currentProgress > 0 && currentProgress < 100} {:else if currentProgress > 0 && currentProgress < 100}
<progress
class="progress is-primary"
value={currentProgress}
max="100"
>
{currentProgress}%
</progress>
<div class="notification is-info"> <div class="notification is-info">
Your image is currently uploading... Your image is currently uploading...
</div> </div>
@ -181,6 +185,15 @@
</div> </div>
{/if} {/if}
</div> </div>
{#if fileName}
<div class="box">
<figure class="image">
<ShiorikoImage alt={fileName} src={previewUrl} />
</figure>
</div>
{:else if loading && !(currentProgress > 0 && currentProgress < 100)}
<div class="skeleton-block"></div>
{/if}
</div> </div>
</div> </div>
</div> </div>