Initial progress on styling

This commit is contained in:
Bad Manners 2025-04-12 18:15:03 -03:00
parent c650c27825
commit 2c44a69ec3
38 changed files with 748 additions and 412 deletions

View file

@ -0,0 +1,25 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Create pool - {{ application_name }}</title>
{% include "fragments/common_headers.html" %}
</head>
<body>
<div><a href="/">&lt; To home</a></div>
<main>
<h1>Create pool</h1>
<form method="post" action="/pool">
<input
class="pool"
type="text"
id="pool"
name="pool"
maxlength="100"
placeholder="Name"
autofocus
/>
<button type="submit">Create</button>
</form>
</main>
</body>
</html>

View file

@ -0,0 +1,50 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>{{ application_name }}</title>
{% include "fragments/common_headers.html" %}
</head>
<body>
<main>
<h1>{{ application_name }}</h1>
<article>
<h2>Search</h2>
<form method="get" action="/posts/1">
{% let tags_value = "" %} {% include "fragments/tags_input.html" %}
<ul class="tags-autocomplete" id="search-autocomplete"></ul>
<button type="submit">Search</button>
</form>
</article>
<nav>
<ul>
<li>
<a href="/posts/1">Posts</a>
</li>
<li>
<a href="/pools/1">Pools</a>
</li>
{% if let Some(user) = user %}
<li>
<a href="/upload">Upload media</a>
</li>
<li>
<a href="/create_pool">Create pool</a>
</li>
{% if user.is_admin %}
<li>
<a href="/settings">Settings</a>
</li>
{% endif %}
<li>
<a href="/logout">Log out ({{ user.username }})</a>
</li>
{% else %}
<li>
<a href="/login">Login</a>
</li>
{% endif %}
</ul>
</nav>
</main>
</body>
</html>

View file

@ -0,0 +1,24 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Login - {{ application_name }}</title>
{% include "fragments/common_headers.html" %}
</head>
<body>
<div><a href="/">&lt; To home</a></div>
<main>
<h1>Login</h1>
<form method="post" action="/login">
<div>
<label>Username</label>
<input id="username" type="text" name="username" autofocus />
</div>
<div>
<label>Password</label>
<input id="password" type="password" name="password" />
</div>
<button type="submit">Submit</button>
</form>
</main>
</body>
</html>

View file

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Not found</title>
{% include "fragments/common_headers.html" %}
</head>
<body>
<div><a href="/">&lt; To home</a></div>
<main>
<h1>Not found</h1>
<p>The requested resource could not be found.</p>
</main>
</body>
</html>

95
templates/pages/pool.html Normal file
View file

@ -0,0 +1,95 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Pool - {{ pool.name }} - {{ application_name }}</title>
{% include "fragments/common_headers.html" %}
<script src="/static/sortable.js"></script>
<meta property="og:title" content="{{ pool.name }}" />
<meta property="og:url" content="/pool/{{ pool.id }}" />
<meta property="twitter:title" content="{{ pool.name }}" />
<meta
property="og:description"
content="Pool with {{ posts.len() }} post(s)."
/>
{% if let Some(post) = posts.first() %}
<meta property="og:image" content="/files/{{ post.thumbnail }}" />
<meta property="twitter:image:src" content="/files/{{ post.thumbnail }}" />
{% endif %} {% if can_edit %}
<script>
htmx.onLoad(function (content) {
var sortables = content.querySelectorAll(".sortable");
for (var i = 0; i < sortables.length; i++) {
var sortable = sortables[i];
var sortableInstance = new Sortable(sortable, {
animation: 150,
ghostClass: "blue-background-class",
// Make the `.htmx-indicator` unsortable
filter: ".htmx-indicator",
onMove: function (evt) {
return evt.related.className.indexOf("htmx-indicator") === -1;
},
// Disable sorting on the `end` event
onEnd: function (evt) {
console.log(evt);
this.option("disabled", true);
},
});
// Re-enable sorting on the `htmx:afterSwap` event
sortable.addEventListener("htmx:afterSwap", function () {
sortableInstance.option("disabled", false);
});
}
});
</script>
{% endif %}
</head>
<body>
<div><a href="/">&lt; To home</a></div>
<main>
<h1>Pool - {{ pool.name }}</h1>
</main>
<article>
<h2>Posts</h2>
{% include "fragments/pool_posts.html" %}
</article>
{% if can_edit %}
<article>
<form
hx-post="/pool/{{ pool.id }}/post"
hx-target="#pool-posts"
hx-swap="outerHTML"
>
<div>
<label>Add post</label>
<input
id="add-post-input"
type="text"
name="post_id"
placeholder="Post ID"
pattern="[0-9]*"
/>
<button>Add</button>
</div>
</form>
<div>
<label>Is public pool?</label>
<input
name="is_public"
type="checkbox"
hx-put="/pool/{{ pool.id }}/public"
{%
if
pool.is_public
%}checked{%
endif
%}
value="true"
/>
</div>
</article>
{% endif %}
</body>
</html>

View file

@ -0,0 +1,37 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Pools - {{ application_name }}</title>
{% include "fragments/common_headers.html" %}
</head>
<body>
<div><a href="/">&lt; To home</a></div>
<main>
<h1>Pools</h1>
{% if pools.is_empty() %}
<div>No pools found!</div>
{% else %}
<ul>
{% for pool in pools %}
<li>
<a href="/pool/{{ pool.id }}"> {{ pool.name }} </a>
</li>
{% endfor %}
</ul>
<div>
<ul>
{% for i in 1..=page_count %}
<li>
{% if i == page as u64 %}
<b>{{ i }}</b>
{% else %}
<a href="/pools/{{ i }}">{{ i }}</a>
{% endif %}
</li>
{% endfor %}
</ul>
</div>
{% endif %}
</main>
</body>
</html>

View file

@ -0,0 +1,79 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Posts - {{ application_name }}</title>
{% include "fragments/common_headers.html" %}
</head>
<body>
<div><a href="/">&lt; To home</a></div>
<article>
<h2>Search</h2>
<form method="get" action="/posts">
<input
class="tags"
type="text"
id="search-tags"
name="tags"
placeholder="Tags"
hx-post="/search_tags"
hx-trigger="input changed"
hx-target="next .tags-autocomplete"
hx-vals="js:{selection_end: event.target.selectionEnd}"
hx-on::after-settle="this.focus(); this.setSelectionRange(-1, -1);"
value="{% if let Some(tags_text) = tags_text %}{{ tags_text }}{% endif %}"
autofocus
/>
<ul class="tags-autocomplete" id="search-autocomplete"></ul>
<button type="submit">Search</button>
</form>
</article>
{% if let Some(tags) = tags %}
{% if !tags.is_empty() %}
<article>
<h2>Tags</h2>
<ul>
{% for tag in tags %}
<li><a href="/posts?tags={{ tag }}">{{ tag }}</a></li>
{% endfor %}
</ul>
</article>
{% endif %}
{% endif %}
<main>
<h1>Posts</h1>
{% if posts.is_empty() %}
<div>No posts found!</div>
{% else %}
<div>
<ul>
{% for post in posts %}
<li>
<a
href="{% if let Some(tags_text) = tags_text %}/post/{{ post.id }}?tags={{ tags_text.replace(' ', "+") }}{% else %}/post/{{ post.id }}{% endif %}"
title="{% if let Some(tags) = post.tags %}{{ tags }}{% endif %}"
>
<img src="/files/{{ post.thumbnail }}" />
<div>{{ post.rating | upper }}</div>
<div>{{ post.media_type }}</div>
</a>
</li>
{% endfor %}
</ul>
</div>
<div>
<ul>
{% for i in 1..=page_count %}
<li>
{% if i == page as u64 %}
<b>{{ i }}</b>
{% else %}
<a href="{% if let Some(tags_text) = tags_text %}/posts/{{ i }}?tags={{ tags_text.replace(' ', "+") }}{% else %}/posts/{{ i }}{% endif %}">{{ i }}</a>
{% endif %}
</li>
{% endfor %}
</ul>
</div>
{% endif %}
</main>
</body>
</html>

View file

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Settings - {{ application_name }}</title>
{% include "fragments/common_headers.html" %}
</head>
<body>
<div><a href="/">&lt; To home</a></div>
<main>
<h1>Settings</h1>
<form hx-put="/settings" hx-swap="none">
<label>Application name</label>
<input
name="application_name"
type="text"
value="{{ application_name }}"
/>
<button>Submit</button>
</form>
</main>
</body>
</html>

View file

@ -0,0 +1,24 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Upload media - {{ application_name }}</title>
{% include "fragments/common_headers.html" %}
</head>
<body>
<div><a href="/">&lt; To home</a></div>
<main>
<h1>Upload media</h1>
<form method="post" action="/upload" enctype="multipart/form-data">
{% let tags_value = "" %} {% include "fragments/tags_input.html" %}
<ul class="tags-autocomplete" id="upload-autocomplete"></ul>
<input
type="file"
id="media-file"
name="media-file"
accept=".jpg, .jpeg, .png, .webp, .gif, .mp4, .webm, .mkv, .mov"
/>
<button type="submit">Submit</button>
</form>
</main>
</body>
</html>

View file

@ -0,0 +1,115 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Post #{{ post.id }} - {{ application_name }}</title>
{% include "fragments/common_headers.html" %}
<meta property="og:site_name" content="{{ application_name }}" />
<meta
property="og:title"
content="{% if let Some(title) = post.title %}{{ title }}{% endif %}"
/>
<meta property="og:url" content="/post/{{ post.id }}" />
<meta
property="og:description"
content="{% if let Some(description) = post.description %}{{ description }}{% endif %}"
/>
<meta
property="twitter:title"
content="{% if let Some(title) = post.title %}{{ title }}{% endif %}"
/>
{% match post.media_type.as_ref() %} {% when "image" %}
<meta property="og:image" content="/files/{{ post.media }}" />
<meta property="og:image:width" content="{{ post.width }}" />
<meta property="og:image:height" content="{{ post.height }}" />
<meta property="og:image:alt" content="{{ tags_post }}" />
<meta property="twitter:card" content="summary_large_image" />
{% when "video" %}
<meta property="og:video" content="/files/{{ post.media }}" />
<meta property="og:video:width" content="{{ post.width }}" />
<meta property="og:video:height" content="{{ post.height }}" />
<meta property="og:video:alt" content="{{ tags_post }}" />
<meta property="og:video:type" content="video/mp4" />
<meta property="twitter:card" content="player" />
<meta name="twitter:player" content="/files/{{ post.media }}" />
<meta name="twitter:player:width" content="{{ post.width }}" />
<meta name="twitter:player:height" content="{{ post.height }}" />
<meta name="twitter:image" content="/files/{{ post.thumbnail }}" />
{% else %} {% endmatch %}
</head>
<body>
<div><a href="{% if let Some(tags_text) = tags_text %}/posts/1?tags={{ tags_text.replace(' ', "+") }}{% else %}/posts/1{% endif %}">&lt; To posts</a></div>
<article>
<h2>Search</h2>
<form method="get" action="/posts">
<input
class="tags"
type="text"
id="search-tags"
name="tags"
hx-post="/search_tags"
hx-trigger="input changed"
hx-target="next .tags-autocomplete"
hx-vals="js:{selection_end: event.target.selectionEnd}"
hx-on::after-settle="this.focus(); this.setSelectionRange(-1, -1);"
value="{% if let Some(tags_text) = tags_text %}{{ tags_text }}{% endif %}"
autofocus
/>
<ul class="tags-autocomplete" id="search-autocomplete"></ul>
<button type="submit">Search</button>
</form>
</article>
<article>
<h2>Tags</h2>
{% if tags.is_empty() %}
<p>No tags in post. Consider adding some!</p>
{% else %}
<ul id="tags-list">
{% for tag in tags %}
<li>
<a href="/posts?tags={{ tag.name }}">{{ tag.name }}</a>
</li>
{% endfor %}
</ul>
{% endif %}
</article>
<main>
<h1>View post #{{ post.id }}</h1>
<div>
{% match post.media_type.as_ref() %}{% when "image" %}{% include
"fragments/get_image_media.html" %}{% when "video" %}{% include
"fragments/get_video_media.html" %}{% else %}{% endmatch %}
</div>
</main>
<article>
<h2>Details</h2>
{% include "fragments/post_details.html" %}
</article>
{% if let Some(parent_post) = parent_post %}
<article id="parent-post">
<h2>Parent</h2>
<a href="/post/{{ parent_post.id }}" title="{% if let Some(tags) = parent_post.tags %}{{ tags }}{% endif %}">
<img src="/files/{{ parent_post.thumbnail }}" />
<div>{{ parent_post.rating }}</div>
<div>{{ parent_post.media_type }}</div>
</a>
</article>
{% else %}
<article id="parent-post" hidden></article>
{% endif %} {% if !children_posts.is_empty() %}
<article>
<h2>Child posts</h2>
<ul>
{% for child_post in children_posts %}
<li>
<a href="/post/{{ child_post.id }}" title="{% if let Some(tags) = child_post.tags %}{{ tags }}{% endif %}">
<img src="/files/{{ child_post.thumbnail }}" />
<div>{{ child_post.rating | upper }}</div>
<div>{{ child_post.media_type }}</div>
</a>
</li>
{% endfor %}
</ul>
</article>
{% endif %}
</body>
</html>