forked from e621ng/e621ng
Compare commits
23 Commits
9e2396eb5f
...
a128837b1f
Author | SHA1 | Date | |
---|---|---|---|
![]() |
a128837b1f | ||
![]() |
0ee3307743 | ||
![]() |
ef3f43cf27 | ||
![]() |
7df12ce443 | ||
![]() |
17bac8c93f | ||
![]() |
76f64b2229 | ||
![]() |
200f064e2d | ||
![]() |
af6ab947d1 | ||
![]() |
09b46b0766 | ||
![]() |
b690d82adc | ||
![]() |
f6e9f44aef | ||
![]() |
8136799546 | ||
![]() |
5a2a4d438a | ||
![]() |
07c5ba8700 | ||
![]() |
9cca923ced | ||
![]() |
551ee23eb7 | ||
![]() |
d16361a926 | ||
![]() |
654023250f | ||
![]() |
c3e0dd6588 | ||
![]() |
fe4f51b82b | ||
![]() |
92125ea7be | ||
![]() |
4548e9e452 | ||
![]() |
97dfa98e93 |
@ -24,7 +24,7 @@ module ApplicationHelper
|
||||
|
||||
tag.li(id: id, class: klass) do
|
||||
link_to(url, id: "#{id}-link", **options) do
|
||||
concat tag.i(class: icon)
|
||||
concat svg_icon(icon)
|
||||
concat " "
|
||||
concat tag.span(text)
|
||||
end
|
||||
@ -189,6 +189,21 @@ module ApplicationHelper
|
||||
end
|
||||
end
|
||||
|
||||
def simple_avatar(user, **options)
|
||||
return "" if user.nil?
|
||||
post_id = user.avatar_id
|
||||
deferred_post_ids.add(post_id) if post_id
|
||||
|
||||
klass = options.delete(:class)
|
||||
named = options.delete(:named)
|
||||
tag.a href: user_path(user), class: "simple-avatar #{klass}", data: { id: post_id, name: user.name } do
|
||||
tag.span(class: "simple-avatar-button") do
|
||||
concat tag.span(user.pretty_name, class: "simple-avatar-name") if named
|
||||
concat tag.span(class: "simple-avatar-image", data: { name: user.name[0].capitalize })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def unread_dmails(user)
|
||||
if user.has_mail?
|
||||
"(#{user.unread_dmail_count})"
|
||||
|
49
app/helpers/icon_helper.rb
Normal file
49
app/helpers/icon_helper.rb
Normal file
@ -0,0 +1,49 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module IconHelper
|
||||
# https://lucide.dev/
|
||||
PATHS = {
|
||||
# Navigation
|
||||
hamburger: %(<line x1="4" x2="20" y1="12" y2="12"/><line x1="4" x2="20" y1="6" y2="6"/><line x1="4" x2="20" y1="18" y2="18"/>),
|
||||
brush: %(<path d="m9.06 11.9 8.07-8.06a2.85 2.85 0 1 1 4.03 4.03l-8.06 8.08"/><path d="M7.07 14.94c-1.66 0-3 1.35-3 3.02 0 1.33-2.5 1.52-2 2.02 1.08 1.1 2.49 2.02 4 2.02 2.2 0 4-1.8 4-4.04a3.01 3.01 0 0 0-3-3.02z"/>),
|
||||
images: %(<path d="M18 22H4a2 2 0 0 1-2-2V6"/><path d="m22 13-1.296-1.296a2.41 2.41 0 0 0-3.408 0L11 18"/><circle cx="12" cy="8" r="2"/><rect width="16" height="16" x="6" y="2" rx="2"/>),
|
||||
library: %(<path d="m16 6 4 14"/><path d="M12 6v14"/><path d="M8 8v12"/><path d="M4 4v16"/>),
|
||||
group: %(<path d="M3 7V5c0-1.1.9-2 2-2h2"/><path d="M17 3h2c1.1 0 2 .9 2 2v2"/><path d="M21 17v2c0 1.1-.9 2-2 2h-2"/><path d="M7 21H5c-1.1 0-2-.9-2-2v-2"/><rect width="7" height="5" x="7" y="7" rx="1"/><rect width="7" height="5" x="10" y="12" rx="1"/>),
|
||||
tags: %(<path d="m15 5 6.3 6.3a2.4 2.4 0 0 1 0 3.4L17 19"/><path d="M9.586 5.586A2 2 0 0 0 8.172 5H3a1 1 0 0 0-1 1v5.172a2 2 0 0 0 .586 1.414L8.29 18.29a2.426 2.426 0 0 0 3.42 0l3.58-3.58a2.426 2.426 0 0 0 0-3.42z"/><circle cx="6.5" cy="9.5" r=".5" fill="currentColor"/>),
|
||||
megaphone: %(<path d="m3 11 18-5v12L3 14v-3z"/><path d="M11.6 16.8a3 3 0 1 1-5.8-1.6"/>),
|
||||
message_square: %(<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/>),
|
||||
lectern: %(<path d="M16 12h3a2 2 0 0 0 1.902-1.38l1.056-3.333A1 1 0 0 0 21 6H3a1 1 0 0 0-.958 1.287l1.056 3.334A2 2 0 0 0 5 12h3"/><path d="M18 6V3a1 1 0 0 0-1-1h-3"/><rect width="8" height="12" x="8" y="10" rx="1"/>),
|
||||
|
||||
swatch: %(<path d="M11 17a4 4 0 0 1-8 0V5a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2Z"/><path d="M16.7 13H19a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2H7"/><path d="M 7 17h.01"/><path d="m11 8 2.3-2.3a2.4 2.4 0 0 1 3.404.004L18.6 7.6a2.4 2.4 0 0 1 .026 3.434L9.9 19.8"/>),
|
||||
settings: %(<path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z"/><circle cx="12" cy="12" r="3"/>),
|
||||
log_in: %(<path d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4"/><polyline points="10 17 15 12 10 7"/><line x1="15" x2="3" y1="12" y2="12"/>),
|
||||
|
||||
# Pagination
|
||||
chevron_left: %(<path d="m15 18-6-6 6-6"/>),
|
||||
chevron_right: %(<path d="m9 18 6-6-6-6"/>),
|
||||
ellipsis: %(<circle cx="12" cy="12" r="1"/><circle cx="19" cy="12" r="1"/><circle cx="5" cy="12" r="1"/>),
|
||||
|
||||
# Posts
|
||||
fullscreen: %(<path d="M3 7V5a2 2 0 0 1 2-2h2"/><path d="M17 3h2a2 2 0 0 1 2 2v2"/><path d="M21 17v2a2 2 0 0 1-2 2h-2"/><path d="M7 21H5a2 2 0 0 1-2-2v-2"/><rect width="10" height="8" x="7" y="8" rx="1"/>),
|
||||
}.freeze
|
||||
|
||||
def svg_icon(name, *args)
|
||||
options = args.extract_options!
|
||||
width = options[:width] || 24
|
||||
height = options[:height] || 24
|
||||
|
||||
tag.svg(
|
||||
"xmlns": "http://www.w3.org/2000/svg",
|
||||
"width": width,
|
||||
"height": height,
|
||||
"viewbox": "0 0 24 24",
|
||||
"fill": "none",
|
||||
"stroke": "currentColor",
|
||||
"stroke-width": 2,
|
||||
"stroke-linecap": "round",
|
||||
"stroke-linejoin": "round",
|
||||
) do
|
||||
raw(PATHS[name]) # rubocop:disable Rails/OutputSafety
|
||||
end
|
||||
end
|
||||
end
|
@ -2,17 +2,23 @@
|
||||
|
||||
module PaginationHelper
|
||||
def sequential_paginator(records)
|
||||
with_paginator_wrapper do
|
||||
tag.div(class: "paginator") do
|
||||
return "" if records.try(:none?)
|
||||
|
||||
html = "".html_safe
|
||||
unless records.is_first_page?
|
||||
html << tag.li(link_to("< Previous", nav_params_for("a#{records[0].id}"), rel: "prev", id: "paginator-prev", data: { shortcut: "a left" }))
|
||||
|
||||
# Previous
|
||||
html << link_to(records.is_first_page? ? "#" : nav_params_for("a#{records[0].id}"), class: "prev", id: "paginator-prev", rel: "prev", data: { shortcut: "a left", disabled: records.is_first_page? }) do
|
||||
concat svg_icon(:chevron_left)
|
||||
concat tag.span("Prev")
|
||||
end
|
||||
|
||||
unless records.is_last_page?
|
||||
html << tag.li(link_to("Next >", nav_params_for("b#{records[-1].id}"), rel: "next", id: "paginator-next", data: { shortcut: "d right" }))
|
||||
# Next
|
||||
html << link_to(records.is_last_page? ? "#" : nav_params_for("b#{records[-1].id}"), class: "next", id: "paginator-next", rel: "next", data: { shortcut: "d right", disabled: records.is_last_page? }) do
|
||||
concat tag.span("Next")
|
||||
concat svg_icon(:chevron_right)
|
||||
end
|
||||
|
||||
html
|
||||
end
|
||||
end
|
||||
@ -22,64 +28,73 @@ module PaginationHelper
|
||||
return sequential_paginator(records)
|
||||
end
|
||||
|
||||
with_paginator_wrapper do
|
||||
tag.div(class: "paginator", data: { total: [records.total_pages, records.max_numbered_pages].min, current: records.current_page }) do
|
||||
html = "".html_safe
|
||||
icon_left = tag.i(class: "fa-solid fa-chevron-left")
|
||||
if records.current_page >= 2
|
||||
html << tag.li(class: "arrow") { link_to(icon_left, nav_params_for(records.current_page - 1), rel: "prev", id: "paginator-prev", data: { shortcut: "a left" }) }
|
||||
else
|
||||
html << tag.li(class: "arrow") { tag.span(icon_left) }
|
||||
|
||||
# Previous
|
||||
has_prev = records.current_page < 2
|
||||
html << link_to(has_prev ? "#" : nav_params_for(records.current_page - 1), class: "prev", id: "paginator-prev", rel: "prev", data: { shortcut: "a left", disabled: has_prev }) do
|
||||
concat svg_icon(:chevron_left)
|
||||
concat tag.span("Prev")
|
||||
end
|
||||
|
||||
paginator_pages(records).each do |page|
|
||||
html << numbered_paginator_item(page, records)
|
||||
# Break
|
||||
html << tag.div(class: "break")
|
||||
|
||||
# Numbered
|
||||
paginator_pages(records).each do |page, klass|
|
||||
html << numbered_paginator_item(page, klass, records)
|
||||
end
|
||||
|
||||
icon_right = tag.i(class: "fa-solid fa-chevron-right")
|
||||
if records.current_page < records.total_pages
|
||||
html << tag.li(class: "arrow") { link_to(icon_right, nav_params_for(records.current_page + 1), rel: "next", id: "paginator-next", data: { shortcut: "d right" }) }
|
||||
else
|
||||
html << tag.li(class: "arrow") { tag.span(icon_right) }
|
||||
# Next
|
||||
has_next = records.current_page >= records.total_pages
|
||||
html << link_to(has_next ? "#" : nav_params_for(records.current_page + 1), class: "next", id: "paginator-next", rel: "next", data: { shortcut: "d right", disabled: has_next }) do
|
||||
concat tag.span("Next")
|
||||
concat svg_icon(:chevron_right)
|
||||
end
|
||||
|
||||
html
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def with_paginator_wrapper(&)
|
||||
tag.div(class: "paginator") do
|
||||
tag.menu(&)
|
||||
end
|
||||
end
|
||||
|
||||
def paginator_pages(records)
|
||||
window = 4
|
||||
small_window = 2
|
||||
large_window = 4
|
||||
|
||||
last_page = [records.total_pages, records.max_numbered_pages].min
|
||||
left = [2, records.current_page - window].max
|
||||
right = [records.current_page + window, last_page - 1].min
|
||||
left_sm = [2, records.current_page - small_window].max
|
||||
left_lg = [2, records.current_page - large_window].max
|
||||
right_sm = [records.current_page + small_window, last_page - 1].min
|
||||
right_lg = [records.current_page + large_window, last_page - 1].min
|
||||
small_range = left_sm..right_sm
|
||||
|
||||
[
|
||||
1,
|
||||
("..." unless left == 2),
|
||||
(left..right).to_a,
|
||||
("..." unless right == last_page - 1),
|
||||
(last_page unless last_page <= 1),
|
||||
].flatten.compact
|
||||
result = [
|
||||
[1, "first"],
|
||||
]
|
||||
result.push([0, "spacer"]) unless left_lg == 2
|
||||
(left_lg..right_lg).each do |page|
|
||||
result.push([page, small_range.member?(page) ? "sm" : "lg"])
|
||||
end
|
||||
result.push([0, "spacer"]) unless right_lg == last_page - 1
|
||||
result.push([last_page, "last"]) unless last_page <= 1
|
||||
|
||||
result
|
||||
end
|
||||
|
||||
def numbered_paginator_item(page, records)
|
||||
def numbered_paginator_item(page, klass, records)
|
||||
return "" if page.to_i > records.max_numbered_pages
|
||||
|
||||
html = "".html_safe
|
||||
if page == "..."
|
||||
html << tag.li(class: "more") { tag.i(class: "fa-solid fa-ellipsis") }
|
||||
if page == 0
|
||||
html << link_to(svg_icon(:ellipsis), nav_params_for(0), class: "spacer")
|
||||
elsif page == records.current_page
|
||||
html << tag.li(class: "current-page") { tag.span(page) }
|
||||
html << tag.span(page, class: "page current")
|
||||
else
|
||||
html << tag.li(class: "numbered-page") { link_to(page, nav_params_for(page)) }
|
||||
html << link_to(page, nav_params_for(page), class: "page #{klass}")
|
||||
end
|
||||
|
||||
html
|
||||
end
|
||||
|
||||
|
43
app/javascript/src/javascripts/home.js
Normal file
43
app/javascript/src/javascripts/home.js
Normal file
@ -0,0 +1,43 @@
|
||||
import Page from "./utility/page";
|
||||
|
||||
const Home = {};
|
||||
|
||||
Home.init = function () {
|
||||
|
||||
const $form = $("#home-search-form");
|
||||
const $tags = $("#tags");
|
||||
|
||||
let isEmpty = !$tags.val();
|
||||
let wasEmpty = isEmpty;
|
||||
if (isEmpty) $form.addClass("empty");
|
||||
|
||||
$tags.on("input", () => {
|
||||
wasEmpty = isEmpty;
|
||||
isEmpty = !$tags.val();
|
||||
|
||||
if (isEmpty && !wasEmpty) $form.addClass("empty");
|
||||
else if (!isEmpty && wasEmpty) $form.removeClass("empty");
|
||||
});
|
||||
|
||||
$(".home-buttons a").on("click", (event) => {
|
||||
if (isEmpty) return; // Act like regular links
|
||||
|
||||
event.preventDefault();
|
||||
const extraTags = $(event.currentTarget).attr("tags");
|
||||
if (extraTags) {
|
||||
$tags.val((index, value) => {
|
||||
return value + " " + extraTags;
|
||||
});
|
||||
}
|
||||
|
||||
$form.trigger("submit");
|
||||
return false;
|
||||
});
|
||||
};
|
||||
|
||||
$(() => {
|
||||
if (!Page.matches("static", "home")) return;
|
||||
Home.init();
|
||||
});
|
||||
|
||||
export default Home;
|
@ -2,7 +2,7 @@ const Navigation = {};
|
||||
|
||||
Navigation.init = function () {
|
||||
const wrapper = $("html");
|
||||
$("#nav-toggle, .nav-offset-left, .nav-offset-bottom").on("click", (event) => {
|
||||
$("#nav-toggle, .nav-offset-left, .nav-offset-bott").on("click", (event) => {
|
||||
event.preventDefault();
|
||||
|
||||
wrapper.toggleClass("nav-toggled");
|
||||
|
@ -10,7 +10,6 @@ NewsUpdate.initialize = function () {
|
||||
let newsOpen = false;
|
||||
$("#news-header, #news-show").on("click", (event) => {
|
||||
event.preventDefault();
|
||||
console.log("click");
|
||||
|
||||
newsOpen = !newsOpen;
|
||||
$("#news").toggleClass("open", newsOpen);
|
||||
|
19
app/javascript/src/javascripts/paginator.js
Normal file
19
app/javascript/src/javascripts/paginator.js
Normal file
@ -0,0 +1,19 @@
|
||||
const Paginator = {};
|
||||
|
||||
Paginator.init_fasttravel = function (button) {
|
||||
button.on("click", (event) => {
|
||||
event.preventDefault();
|
||||
|
||||
const value = prompt("Navigate to page");
|
||||
if (!value) return;
|
||||
|
||||
window.location.replace(button.attr("href").replace("page=0", "page=" + value));
|
||||
});
|
||||
};
|
||||
|
||||
$(() => {
|
||||
for (const one of $(".paginator a.spacer").get())
|
||||
Paginator.init_fasttravel($(one));
|
||||
});
|
||||
|
||||
export default Paginator;
|
@ -35,12 +35,10 @@ PostModeMenu.change_tag_script = function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
const newScriptID = Number(e.key);
|
||||
console.log(newScriptID, LStorage.Posts.TagScript.ID);
|
||||
if (!newScriptID || newScriptID == LStorage.Posts.TagScript.ID)
|
||||
return;
|
||||
|
||||
LStorage.Posts.TagScript.ID = newScriptID;
|
||||
console.log("settings", LStorage.Posts.TagScript.ID, LStorage.Posts.TagScript.Content);
|
||||
$("#tag-script-field").val(LStorage.Posts.TagScript.Content);
|
||||
PostModeMenu.show_notice(newScriptID);
|
||||
};
|
||||
|
@ -1,4 +1,5 @@
|
||||
import LStorage from "./utility/storage";
|
||||
import Page from "./utility/page";
|
||||
|
||||
const PostSearch = {};
|
||||
|
||||
@ -10,6 +11,8 @@ PostSearch.init = function () {
|
||||
$(".wiki-excerpt").each((index, element) => {
|
||||
PostSearch.initialize_wiki_preview($(element));
|
||||
});
|
||||
|
||||
PostSearch.initialize_controls();
|
||||
};
|
||||
|
||||
PostSearch.initialize_input = function ($form) {
|
||||
@ -39,21 +42,35 @@ PostSearch.initialize_input = function ($form) {
|
||||
|
||||
PostSearch.initialize_wiki_preview = function ($preview) {
|
||||
let visible = LStorage.Posts.WikiExcerpt;
|
||||
if (visible)
|
||||
$preview.removeClass("hidden");
|
||||
if (visible) $preview.addClass("open");
|
||||
window.setTimeout(() => { // Disable the rollout on first load
|
||||
$preview.removeClass("loading");
|
||||
}, 250);
|
||||
|
||||
$($preview.find("a.wiki-excerpt-toggle")).on("click", (event) => {
|
||||
$($preview.find("h3.wiki-excerpt-toggle")).on("click", (event) => {
|
||||
event.preventDefault();
|
||||
|
||||
visible = !visible;
|
||||
$preview.toggleClass("hidden", !visible);
|
||||
$preview.toggleClass("open", visible);
|
||||
LStorage.Posts.WikiExcerpt = visible;
|
||||
|
||||
return false;
|
||||
});
|
||||
};
|
||||
|
||||
PostSearch.initialize_controls = function () {
|
||||
let fullscreen = LStorage.Posts.Fullscreen;
|
||||
$("#search-fullscreen").on("click", () => {
|
||||
fullscreen = !fullscreen;
|
||||
$("body").attr("data-st-fullscreen", fullscreen);
|
||||
LStorage.Posts.Fullscreen = fullscreen;
|
||||
});
|
||||
};
|
||||
|
||||
$(() => {
|
||||
if (!Page.matches("posts", "index") && !Page.matches("favorites"))
|
||||
return;
|
||||
|
||||
PostSearch.init();
|
||||
});
|
||||
|
||||
|
@ -28,6 +28,7 @@ Shortcuts.initialize_data_shortcuts = function () {
|
||||
|
||||
Shortcuts.keydown(keys, namespace, event => {
|
||||
const e = $(`[data-shortcut="${keys}"]`).get(0);
|
||||
if ($e.data("disabled")) return;
|
||||
if ($e.is("input, textarea")) {
|
||||
$e.trigger("focus").selectEnd();
|
||||
} else {
|
||||
|
@ -3,7 +3,7 @@ import LStorage from "./utility/storage";
|
||||
|
||||
const Theme = {};
|
||||
|
||||
Theme.Values = ["Main", "Extra", "StickyHeader", "Palette", "Navbar", "Gestures"];
|
||||
Theme.Values = ["Main", "Extra", "StickyHeader", "ForumNotif", "Palette", "Navbar", "Gestures"];
|
||||
|
||||
for (const one of Theme.Values) {
|
||||
Object.defineProperty(Theme, one, {
|
||||
|
@ -8,6 +8,23 @@ Thumbnails.initialize = function () {
|
||||
const posts = $(".post-thumb.placeholder, .thumb-placeholder-link");
|
||||
const replacedPosts = [];
|
||||
|
||||
// Avatar special case
|
||||
for (const post of $(".simple-avatar")) {
|
||||
const $post = $(post);
|
||||
|
||||
const postID = $post.data("id");
|
||||
if (!postID) continue;
|
||||
|
||||
const postData = postsData[postID];
|
||||
if (!postData || !postData["preview_url"]) continue;
|
||||
|
||||
$("<img>")
|
||||
.attr("src", postData["preview_url"])
|
||||
.appendTo($post.find("span.simple-avatar-image"));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Reset of the deferred posts
|
||||
for (const post of posts) {
|
||||
const $post = $(post);
|
||||
|
||||
|
@ -161,6 +161,7 @@
|
||||
Related:
|
||||
<a href="#" @click.prevent="findRelated()">Tags</a> |
|
||||
<a href="#" @click.prevent="findRelated(1)">Artists</a> |
|
||||
<a href="#" @click.prevent="findRelated(2)">Contributors</a> |
|
||||
<a href="#" @click.prevent="findRelated(3)">Copyrights</a> |
|
||||
<a href="#" @click.prevent="findRelated(4)">Characters</a> |
|
||||
<a href="#" @click.prevent="findRelated(5)">Species</a> |
|
||||
|
@ -65,6 +65,9 @@ LStorage.Theme = {
|
||||
|
||||
/** @returns {boolean} True if the sticky header is enabled */
|
||||
StickyHeader: ["theme-sheader", false],
|
||||
|
||||
/** @returns {boolean} True if the forum notification dot is enabled */
|
||||
ForumNotif: ["theme-forumnotif", false],
|
||||
};
|
||||
StorageUtils.bootstrapMany(LStorage.Theme);
|
||||
|
||||
@ -85,6 +88,9 @@ LStorage.Posts = {
|
||||
|
||||
/** @returns {boolean} True if the wiki excerpt should be visible */
|
||||
WikiExcerpt: ["e6.posts.wiki", true],
|
||||
|
||||
/** @returns {boolean} True if the search should be displayed in fullscreen */
|
||||
Fullscreen: ["e6.posts.fusk", false],
|
||||
};
|
||||
StorageUtils.bootstrapMany(LStorage.Posts);
|
||||
|
||||
|
@ -9,6 +9,9 @@
|
||||
@import "base/links";
|
||||
@import "base/fontawesome";
|
||||
|
||||
@import "common/standard_variables";
|
||||
@import "common/standard_elements";
|
||||
|
||||
@import "common/footer";
|
||||
@import "common/helper_classes";
|
||||
@import "common/helper_palette";
|
||||
|
@ -1,73 +1,84 @@
|
||||
footer#page-footer {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 2fr;
|
||||
gap: 0.5rem 0;
|
||||
|
||||
padding: 0.5rem 0 1rem;
|
||||
margin: 1rem 0 0;
|
||||
|
||||
footer.footer-wrapper {
|
||||
background: var(--color-foreground);
|
||||
margin-top: 1rem;
|
||||
|
||||
.footer-grid {
|
||||
display: grid;
|
||||
grid-template-columns: min-content min-content;
|
||||
grid-template-areas:
|
||||
"logo . "
|
||||
"left right";
|
||||
justify-items: center;
|
||||
gap: 0.5rem 0;
|
||||
|
||||
width: min-content;
|
||||
margin: 0 auto;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.footer-logo {
|
||||
grid-area: logo;
|
||||
width: 100%;
|
||||
text-align: right;
|
||||
|
||||
img {
|
||||
width: 5rem;
|
||||
height: auto;
|
||||
|
||||
// Aligning the logo with the line below
|
||||
margin-right: -3.25rem;
|
||||
|
||||
background: themed("color-background") themed("image-background");
|
||||
border-radius: 50%;
|
||||
padding: 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.footer-left, .footer-right {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
gap: 0.25em;
|
||||
padding: 0 0.5rem;
|
||||
|
||||
font-size: 1.25em;
|
||||
|
||||
a, span {
|
||||
line-height: 1.25em;
|
||||
}
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
gap: 0.25rem;
|
||||
|
||||
font-size: 1rem;
|
||||
|
||||
a, span { white-space: nowrap; }
|
||||
span { line-height: 1.25em; }
|
||||
}
|
||||
|
||||
.footer-left {
|
||||
align-items: end;
|
||||
border-right: 1px solid var(--color-section);
|
||||
grid-area: left;
|
||||
padding-right: 1rem;
|
||||
|
||||
text-align: right;
|
||||
border-right: 1px solid var(--color-section-lighten-5);
|
||||
}
|
||||
|
||||
.footer-logo {
|
||||
grid-column: 1 / -1;
|
||||
grid-row: 1;
|
||||
text-align: center;
|
||||
|
||||
img {
|
||||
width: 5rem;
|
||||
height: 5rem;
|
||||
}
|
||||
.footer-right {
|
||||
grid-area: right;
|
||||
padding-left: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Desktop
|
||||
footer#page-footer {
|
||||
@include window-larger-than(800px) {
|
||||
grid-template-columns: 1fr min-content 1fr;
|
||||
|
||||
.footer-left, .footer-right {
|
||||
font-size: unset;
|
||||
flex-flow: row;
|
||||
align-items: center;
|
||||
border: 0;
|
||||
gap: 0;
|
||||
|
||||
a:not(:last-child)::after {
|
||||
content: "";
|
||||
width: 4px;
|
||||
height: 4px;
|
||||
background: white;
|
||||
display: inline-block;
|
||||
border-radius: 2px;
|
||||
margin: 0.125rem 0.5rem;
|
||||
}
|
||||
|
||||
span.footer-running { display: none; }
|
||||
// Desktop-ish
|
||||
footer.footer-wrapper {
|
||||
@include window-larger-than(450px) {
|
||||
.footer-grid {
|
||||
grid-template-areas: "logo left right";
|
||||
padding: 1rem 0;
|
||||
}
|
||||
|
||||
.footer-left { justify-content: right; }
|
||||
|
||||
.footer-logo {
|
||||
grid-column: unset;
|
||||
grid-row: unset;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-right: 2rem;
|
||||
box-sizing: border-box;
|
||||
|
||||
img {
|
||||
width: 6rem;
|
||||
margin-right: unset;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
59
app/javascript/src/styles/common/_standard_elements.scss
Normal file
59
app/javascript/src/styles/common/_standard_elements.scss
Normal file
@ -0,0 +1,59 @@
|
||||
// Standard button
|
||||
// Could be applied to either a button or a link
|
||||
// Semi-expected to have an icon
|
||||
.st-button {
|
||||
$button-font-size: st-value(100);
|
||||
$button-background: themed("color-section-lighten-5");
|
||||
$button-background-hover: themed("color-section-lighten-10");
|
||||
$button-text-color: themed("color-text");
|
||||
|
||||
display: flex;
|
||||
gap: st-value(100) / 4;
|
||||
border-radius: radius(025);
|
||||
|
||||
// Button final size
|
||||
// Font 1rem
|
||||
// Padding 2 * 0.5rem
|
||||
font-size: st-value(100);
|
||||
line-height: st-value(100);
|
||||
padding: st-value(100) / 2;
|
||||
height: st-value(100) * 2;
|
||||
|
||||
// TODO What if button is on a light background
|
||||
background: $button-background;
|
||||
color: $button-text-color;
|
||||
&:hover { background: $button-background-hover; }
|
||||
|
||||
& > svg {
|
||||
// Icon should be slightly larger than text,
|
||||
// with padding to fill the entire button height
|
||||
height: st-value(100) * 1.5; // 1.5rem
|
||||
width: st-value(100) * 1.5; // 1.5rem
|
||||
margin: -#{st-value(100) / 2} 0; // 0.5rem
|
||||
padding: st-value(100) / 4; // 0.25rem
|
||||
|
||||
border-radius: radius(025);
|
||||
}
|
||||
& > span {
|
||||
text-align: left;
|
||||
|
||||
// Do not overflow text
|
||||
overflow: hidden;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
// Full width button
|
||||
&.w100 { width: 100%; }
|
||||
|
||||
&.stealth {
|
||||
background: none;
|
||||
padding: (st-value(100) / 2) 0;
|
||||
|
||||
svg { background: $button-background; }
|
||||
span { color: themed("color-link"); }
|
||||
&:hover {
|
||||
svg { background: $button-background-hover; }
|
||||
span { color: themed("color-link-hover"); }
|
||||
}
|
||||
}
|
||||
}
|
21
app/javascript/src/styles/common/_standard_variables.scss
Normal file
21
app/javascript/src/styles/common/_standard_variables.scss
Normal file
@ -0,0 +1,21 @@
|
||||
@use "sass:map";
|
||||
|
||||
// Standard variables for typography and UI elements
|
||||
|
||||
$st-values: (
|
||||
000: 0rem,
|
||||
025: 0.25rem,
|
||||
050: 0.50rem,
|
||||
075: 0.75rem,
|
||||
100: 1rem,
|
||||
);
|
||||
|
||||
@function st-value($name) {
|
||||
@return map-get($map: $st-values, $key: $name);
|
||||
}
|
||||
|
||||
@function padding($value) { @return st-value(($value)); }
|
||||
@mixin st-padding($value) { padding: padding(($value)); }
|
||||
|
||||
@function radius($value) { @return st-value($value); }
|
||||
@mixin st-radius($value) { border-radius: radius($value); }
|
@ -6,6 +6,7 @@ nav.navigation {
|
||||
|
||||
width: 100%; // otherwise narrow when fixed
|
||||
z-index: 20; // otherwise post labels layered above
|
||||
position: relative;
|
||||
|
||||
|
||||
/* Top bar, always visible */
|
||||
@ -13,16 +14,18 @@ nav.navigation {
|
||||
grid-area: logo;
|
||||
|
||||
background-color: themed("color-background");
|
||||
height: 3.75rem;
|
||||
|
||||
a.nav-logo-link {
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
|
||||
// Height: 3.75rem
|
||||
// - padding 0.25 * 2 = 0.5
|
||||
// - image 3.25
|
||||
height: 3.25rem;
|
||||
width: 3.25rem;
|
||||
margin: 0.25rem;
|
||||
// - padding 0.125 * 2 = 0.25
|
||||
// - image 3.5
|
||||
height: 3.5rem;
|
||||
width: 4rem;
|
||||
margin: 0.125rem;
|
||||
|
||||
background-image: url("main-logo.svg");
|
||||
background-repeat: no-repeat;
|
||||
@ -37,160 +40,208 @@ nav.navigation {
|
||||
display: flex;
|
||||
flex-flow: row-reverse;
|
||||
align-items: center;
|
||||
gap: 0.5em;
|
||||
|
||||
font-size: 1.15rem;
|
||||
padding-right: 0.5em;
|
||||
background-color: themed("color-background");
|
||||
padding-right: 0.25rem;
|
||||
height: 3.75rem;
|
||||
|
||||
// Height: 3.75rem
|
||||
// - wrapper padding 0.875 * 2 = 1.75
|
||||
// - link padding 0.25 * 2 = 0.5
|
||||
// - font size 1.5
|
||||
padding: 0.875rem;
|
||||
|
||||
// - link padding 0.625 * 2 = 1.25
|
||||
// - internal size 2.5
|
||||
& > a {
|
||||
display: flex;
|
||||
gap: 0.25em;
|
||||
padding: 0.625rem 0.5rem;
|
||||
|
||||
padding: 0.25rem 0.5rem;
|
||||
background: themed("color-foreground");
|
||||
border-radius: 6px;
|
||||
& > span {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
gap: 0.5rem;
|
||||
|
||||
height: 2.5rem;
|
||||
min-width: 2.5rem;
|
||||
line-height: 1.5rem;
|
||||
padding: 0 0.5rem;
|
||||
|
||||
& > i {
|
||||
font-size: 1.5rem;
|
||||
background: themed("color-foreground");
|
||||
color: themed("color-link-active");
|
||||
border-radius: 0.25rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
&:hover > span, &:active > span { background: themed("color-section"); }
|
||||
&:focus { outline: none; }
|
||||
}
|
||||
|
||||
a.simple-avatar {
|
||||
.simple-avatar-button {
|
||||
padding: 0;
|
||||
gap: 0;
|
||||
|
||||
.simple-avatar-name {
|
||||
padding: 0.5rem;
|
||||
|
||||
@include window-smaller-than(32rem) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.simple-avatar-image {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
|
||||
width: 2.5rem;
|
||||
height: 2.5rem;
|
||||
|
||||
box-sizing: border-box;
|
||||
border-radius: 0.25rem;
|
||||
background: themed("color-section");
|
||||
|
||||
img {
|
||||
width: 2.5rem;
|
||||
height: 2.5rem;
|
||||
|
||||
border-radius: 0.25rem;
|
||||
object-fit: cover;
|
||||
|
||||
z-index: 1; // above the letter
|
||||
}
|
||||
|
||||
&::before {
|
||||
content: attr(data-name);
|
||||
position: absolute;
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
@include window-smaller-than(32rem) {
|
||||
&.sign-in .simple-avatar-image {
|
||||
background: themed("color-foreground");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Prevent toggled menus from being too wide */
|
||||
.nav-offset-left {
|
||||
grid-area: offleft;
|
||||
display: none; // flex
|
||||
background: #00000050;
|
||||
}
|
||||
|
||||
.nav-offset-bottom {
|
||||
grid-area: offbott;
|
||||
display: none; // flex
|
||||
background: #00000050;
|
||||
/* Offset elements on the left and bottom */
|
||||
// Needed to track clicks outside the menu area
|
||||
@each $name in ("left", "bott") {
|
||||
.nav-offset-#{$name} {
|
||||
grid-area: off#{$name};
|
||||
display: none; // flex
|
||||
background: #00000050;
|
||||
}
|
||||
}
|
||||
|
||||
/* Toggled menus, hidden by default */
|
||||
.nav-primary {
|
||||
grid-area: primary;
|
||||
display: none; // flex
|
||||
flex-flow: column;
|
||||
// Naming areas
|
||||
@each $name in (primary, secondary, tools, help) {
|
||||
.nav-#{$name} {
|
||||
grid-area: $name;
|
||||
display: none;
|
||||
|
||||
background-color: themed("color-section");
|
||||
font-size: 1.5em;
|
||||
li {
|
||||
padding: 0;
|
||||
|
||||
li {
|
||||
padding: 0;
|
||||
a {
|
||||
display: block;
|
||||
border-bottom: 1px solid themed("color-foreground");
|
||||
padding: 0.5em;
|
||||
& > a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
|
||||
// "Comments" is usually the longest and might wrap
|
||||
white-space: nowrap;
|
||||
white-space: nowrap;
|
||||
|
||||
i {
|
||||
width: 1.5rem;
|
||||
color: themed("color-link-active");
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
&.current a { background-color: themed("color-foreground"); }
|
||||
&.forum-updated {
|
||||
position: relative;
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
border-radius: 3px;
|
||||
|
||||
background: var(--palette-text-red);
|
||||
|
||||
position: absolute;
|
||||
right: 0.2em;
|
||||
top: 1em;
|
||||
svg {
|
||||
margin: -0.25rem 0;
|
||||
color: themed("color-link-active");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nav-secondary {
|
||||
grid-area: secondary;
|
||||
display: none; // flex
|
||||
// Common top
|
||||
.nav-primary, .nav-secondary {
|
||||
flex-flow: column;
|
||||
|
||||
background-color: themed("color-foreground");
|
||||
font-size: 1.35em;
|
||||
height: 440px;
|
||||
|
||||
// Prevent the tools / help buttons from being pushed
|
||||
// way too low on pages with a lot of secondary links
|
||||
overflow: scroll;
|
||||
height: 422px;
|
||||
overflow-y: scroll;
|
||||
|
||||
li a {
|
||||
justify-content: start;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-primary {
|
||||
background-color: themed("color-section");
|
||||
font-size: 1.25rem;
|
||||
|
||||
li > a {
|
||||
border-bottom: 1px solid themed("color-foreground");
|
||||
line-height: 1.25rem;
|
||||
padding: 1rem 0.5rem;
|
||||
}
|
||||
li.current a { background-color: themed("color-foreground"); }
|
||||
}
|
||||
|
||||
.nav-secondary {
|
||||
background-color: themed("color-foreground");
|
||||
font-size: 1.2rem;
|
||||
|
||||
li {
|
||||
padding: 0;
|
||||
a {
|
||||
display: block;
|
||||
& > a {
|
||||
border-bottom: 1px solid themed("color-section");
|
||||
padding: 0.5em;
|
||||
line-height: 1.2rem;
|
||||
padding: 0.7rem;
|
||||
|
||||
white-space: wrap; // forum menus are long
|
||||
}
|
||||
|
||||
&.divider {
|
||||
border-bottom: 1px solid themed("color-section");
|
||||
height: 0.25em;
|
||||
height: 0.25rem;
|
||||
}
|
||||
|
||||
form input[type="text"] {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
|
||||
// Reduced font size to make the search
|
||||
// box less claustrophobic
|
||||
font-size: 1em;
|
||||
padding: 0.25em 0.5em;
|
||||
font-size: 1.25rem;
|
||||
padding: 0.5rem 0.5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nav-tools {
|
||||
grid-area: tools;
|
||||
|
||||
display: none; // grid
|
||||
grid-template-columns: 1fr 1fr;
|
||||
// Common bottom
|
||||
.nav-tools, .nav-help {
|
||||
grid-template-rows: min-content;
|
||||
|
||||
padding: 1rem;
|
||||
font-size: 1.1rem;
|
||||
gap: 1rem;
|
||||
|
||||
background-color: themed("color-section");
|
||||
|
||||
li > a {
|
||||
justify-content: center;
|
||||
border-radius: 0.25rem;
|
||||
|
||||
padding: 0.7rem 1rem;
|
||||
line-height: 1.1rem;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-tools {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
border-top: 1px solid themed("color-foreground");
|
||||
padding: 1rem 1rem 0.5rem;
|
||||
|
||||
li {
|
||||
padding: 0;
|
||||
|
||||
a { background: themed("color-section-lighten-5"); }
|
||||
&.nav-tools-login { grid-column: 1 / -1; }
|
||||
|
||||
& > a {
|
||||
display: block;
|
||||
|
||||
background: themed("color-section-lighten-5");
|
||||
border-radius: 6px;
|
||||
|
||||
font-size: 125%;
|
||||
padding: 0.5rem 1rem;
|
||||
text-align: center;
|
||||
|
||||
i { color: themed("color-link-active"); }
|
||||
}
|
||||
}
|
||||
|
||||
&.anonymous li.nav-tools-themes {
|
||||
@ -199,42 +250,19 @@ nav.navigation {
|
||||
}
|
||||
|
||||
.nav-help {
|
||||
grid-area: help;
|
||||
|
||||
display: none; // grid
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
grid-template-rows: min-content;
|
||||
|
||||
padding: 1rem;
|
||||
gap: 1rem;
|
||||
|
||||
background: themed("color-section");
|
||||
padding: 0.5rem 1rem 1rem;
|
||||
|
||||
li {
|
||||
padding: 0;
|
||||
|
||||
a { background: themed("color-section-darken-5"); }
|
||||
&.nav-help-discord,
|
||||
&.nav-help-subscribestar {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
|
||||
& > a {
|
||||
display: flex;
|
||||
|
||||
background: themed("color-section-darken-5");
|
||||
border-radius: 6px;
|
||||
|
||||
font-size: 125%;
|
||||
padding: 0.5rem 1rem;
|
||||
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 0.25em;
|
||||
|
||||
img {
|
||||
height: 1.25em;
|
||||
margin: -0.5em 0;
|
||||
}
|
||||
& > a img {
|
||||
height: 1.5rem;
|
||||
margin: -0.2rem 0;
|
||||
}
|
||||
|
||||
// Hack to put the wiki/help links before discord/sstar on mobile
|
||||
@ -255,6 +283,29 @@ body[data-th-sheader="true"] nav.navigation {
|
||||
}
|
||||
|
||||
|
||||
// Forum notification
|
||||
body[data-th-forumnotif="true"] nav.navigation .nav-primary li.forum-updated {
|
||||
position: relative;
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
border-radius: 3px;
|
||||
|
||||
background: palette("text-red");
|
||||
|
||||
position: absolute;
|
||||
right: 0.2rem;
|
||||
top: 1.25rem;
|
||||
|
||||
@include window-larger-than(800px) {
|
||||
top: 0.2rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Mobile toggle
|
||||
html.nav-toggled {
|
||||
|
||||
@ -279,14 +330,14 @@ html.nav-toggled {
|
||||
// Allow scrolling when the menu is too long
|
||||
overflow-y: scroll;
|
||||
|
||||
.nav-primary, .nav-secondary, .nav-offset-left, .nav-offset-bottom {
|
||||
.nav-primary, .nav-secondary, .nav-offset-left, .nav-offset-bott {
|
||||
display: flex;
|
||||
}
|
||||
.nav-tools, .nav-help {
|
||||
display: grid;
|
||||
}
|
||||
.nav-primary, .nav-tools, .nav-help {
|
||||
box-shadow: -1px 0 5px -1px var(--color-background);
|
||||
box-shadow: -3px 3px 5px -1px themed("color-background");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -294,74 +345,68 @@ html.nav-toggled {
|
||||
|
||||
// Desktop
|
||||
nav.navigation, html.nav-toggled nav.navigation {
|
||||
@include window-larger-than(800px) {
|
||||
@include window-larger-than(50rem) {
|
||||
grid-template-areas:
|
||||
"logo primary help tools "
|
||||
"logo secondary secondary secondary"
|
||||
;
|
||||
grid-template-columns: min-content min-content minmax(0, 1fr) min-content;
|
||||
grid-template-rows: 1.75em 2em;
|
||||
"logo primary help help controls"
|
||||
"logo secondary secondary tools controls";
|
||||
grid-template-columns: min-content min-content minmax(0, 1fr) min-content 3.25rem;
|
||||
grid-template-rows: 1.5rem 1.75rem;
|
||||
|
||||
padding: 0 1em 0.5em;
|
||||
padding: 0 1rem 0.5rem;
|
||||
box-sizing: border-box;
|
||||
height: unset;
|
||||
|
||||
background: var(--color-background);
|
||||
background: themed("color-background");
|
||||
overflow-y: hidden; // overrides mobile hack allowing the menu scrolling
|
||||
|
||||
.nav-logo {
|
||||
a.nav-logo-link { margin: 0.25rem 0.5rem 0 0; }
|
||||
.nav-logo a.nav-logo-link {
|
||||
height: 3.25rem;
|
||||
width: 3.25rem;
|
||||
margin: 0.25rem 0.5rem 0 0;
|
||||
}
|
||||
|
||||
.nav-offset-left, .nav-offset-bottom, .nav-controls { display: none; }
|
||||
.mobile { display: none; }
|
||||
|
||||
.nav-primary {
|
||||
// All link ribbons
|
||||
.desktop {
|
||||
display: flex;
|
||||
flex-flow: row;
|
||||
|
||||
background: unset;
|
||||
font-size: 1.05em;
|
||||
padding: 0 0.25em;
|
||||
font-size: 0.875rem;
|
||||
box-shadow: unset;
|
||||
|
||||
li {
|
||||
li a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
|
||||
a {
|
||||
align-content: center;
|
||||
padding: 0 0.625rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
border-bottom: 0;
|
||||
padding: 0 0.75em;
|
||||
i { display: none; }
|
||||
}
|
||||
.nav-primary {
|
||||
background: unset;
|
||||
height: unset;
|
||||
padding-left: 0.25rem;
|
||||
|
||||
&.forum-updated::after {
|
||||
top: 0.2em;
|
||||
}
|
||||
li a {
|
||||
border-bottom: 0;
|
||||
svg { display: none; }
|
||||
}
|
||||
}
|
||||
|
||||
.nav-secondary {
|
||||
display: flex;
|
||||
flex-flow: row;
|
||||
height: unset;
|
||||
|
||||
padding: 0 0.25em;
|
||||
font-size: 1.05em;
|
||||
border-radius: 6px;
|
||||
padding: 0 0.25rem;
|
||||
border-radius: 0.25rem 0 0 0.25rem;
|
||||
|
||||
// Silly fix for too many links
|
||||
overflow: hidden;
|
||||
overflow: hidden; // Silly fix for too many links
|
||||
z-index: 1; // above the avatar
|
||||
|
||||
li {
|
||||
display: flex;
|
||||
|
||||
a {
|
||||
align-content: center;
|
||||
|
||||
border-bottom: 0;
|
||||
padding: 0 0.75em;
|
||||
white-space: nowrap;
|
||||
}
|
||||
a { border-bottom: 0; }
|
||||
|
||||
&.divider {
|
||||
display: flex;
|
||||
@ -371,50 +416,46 @@ nav.navigation, html.nav-toggled nav.navigation {
|
||||
&::after { content: "|"; }
|
||||
}
|
||||
|
||||
form {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
input[type="text"] { min-width: 10em; }
|
||||
form input[type="text"] {
|
||||
width: 12rem;
|
||||
padding: 0.25rem 0.5rem;
|
||||
font-size: 1rem;
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nav-tools, .nav-help {
|
||||
display: flex;
|
||||
|
||||
padding: 0;
|
||||
background: unset;
|
||||
border: none;
|
||||
gap: 0;
|
||||
|
||||
li {
|
||||
display: flex;
|
||||
li a {
|
||||
gap: 0.25rem;
|
||||
|
||||
a {
|
||||
align-content: center;
|
||||
|
||||
background: unset;
|
||||
font-size: 1.05em;
|
||||
padding: 0 0.75em;
|
||||
text-align: unset;
|
||||
white-space: nowrap;
|
||||
border-radius: 0;
|
||||
}
|
||||
background: unset;
|
||||
text-align: unset;
|
||||
border-radius: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-tools {
|
||||
|
||||
// Otherwise help gets layered above it
|
||||
// When the viewport is narrow (but not mobile)
|
||||
background: themed("color-foreground");
|
||||
z-index: 1;
|
||||
background: var(--color-background);
|
||||
border-radius: 0 0.25rem 0.25rem 0;
|
||||
margin-right: 0.25rem;
|
||||
|
||||
li {
|
||||
a {
|
||||
i { color: themed("color-link"); }
|
||||
&:hover i { color: themed("color-link-hover"); }
|
||||
padding: 0 0.5rem;
|
||||
|
||||
svg {
|
||||
color: themed("color-link");
|
||||
height: 1.25rem;
|
||||
width: 1.25rem;
|
||||
}
|
||||
&:hover svg { color: themed("color-link-hover"); }
|
||||
}
|
||||
|
||||
&.nav-tools-themes, &.nav-tools-settings {
|
||||
@ -422,26 +463,123 @@ nav.navigation, html.nav-toggled nav.navigation {
|
||||
}
|
||||
}
|
||||
}
|
||||
.nav-help {
|
||||
li a img { display: none; }
|
||||
|
||||
.nav-help {
|
||||
|
||||
// At small resolutions, overflow can
|
||||
// cause scrollbars to appear
|
||||
overflow: hidden;
|
||||
|
||||
li a img { display: none; }
|
||||
li.current a {
|
||||
background-color: themed("color-foreground");
|
||||
}
|
||||
}
|
||||
|
||||
.nav-primary, .nav-tools, .nav-help { box-shadow: unset; }
|
||||
.nav-controls {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
|
||||
height: 3.25rem;
|
||||
box-sizing: border-box;
|
||||
padding: 0.25rem 0 0;
|
||||
|
||||
#nav-toggle { display: none; }
|
||||
|
||||
a.simple-avatar {
|
||||
padding: 0;
|
||||
height: 100%;
|
||||
|
||||
.simple-avatar-button {
|
||||
background: none;
|
||||
color: inherit;
|
||||
align-items: start;
|
||||
font-size: 0.875rem;
|
||||
line-height: 0.875rem;
|
||||
|
||||
.simple-avatar-name {
|
||||
padding: 0 0.5rem;
|
||||
}
|
||||
|
||||
.simple-avatar-image {
|
||||
height: 3rem;
|
||||
width: 3rem;
|
||||
background: themed("color-foreground");
|
||||
|
||||
img {
|
||||
width: 2.75rem;
|
||||
height: 2.75rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Icon collapse
|
||||
// Stage 1: discord and subscribestar buttons
|
||||
.collapse-1 { display: none; }
|
||||
@include window-larger-than(77rem) {
|
||||
.collapse-1 { display: flex; }
|
||||
}
|
||||
|
||||
// Stage 2: account label
|
||||
.collapse-2 .simple-avatar-name { display: none; }
|
||||
@include window-larger-than(65rem) {
|
||||
.collapse-2 .simple-avatar-name { display: unset; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tweak for the secondary menu on desktop
|
||||
body.c-static.a-home {
|
||||
@include window-larger-than(800px) {
|
||||
nav.navigation, menu.nav-logo, menu.nav-secondary {
|
||||
@include window-larger-than(50rem) {
|
||||
|
||||
nav.navigation {
|
||||
|
||||
// Center and align the navbar
|
||||
grid-template-areas: "logo primary help controls";
|
||||
grid-template-columns: repeat(4, min-content);
|
||||
justify-content: center;
|
||||
|
||||
// Remove padding to prevent a scrollbar
|
||||
// at low desktop resolutions
|
||||
padding: 0 0 0.5rem;
|
||||
|
||||
#nav-subscribestar, #nav-discord, .nav-secondary, .nav-tools { display: none; }
|
||||
}
|
||||
|
||||
// Match the background colors
|
||||
nav.navigation, menu.nav-logo, menu.nav-secondary, menu.nav-controls {
|
||||
background: unset;
|
||||
}
|
||||
menu.nav-tools {
|
||||
background: var(--bg-color);
|
||||
}
|
||||
menu.nav-controls {
|
||||
position: static;
|
||||
height: unset;
|
||||
padding: 0;
|
||||
.simple-avatar-button {
|
||||
height: unset;
|
||||
align-items: center;
|
||||
.simple-avatar-image { display: none; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include window-smaller-than(50rem) {
|
||||
// Only show the primary navbar on mobile
|
||||
// since the secondary is empty anyways
|
||||
nav.navigation {
|
||||
grid-template-areas:
|
||||
"logo logo controls"
|
||||
"offleft primary primary "
|
||||
"offleft tools tools "
|
||||
"offleft help help "
|
||||
"offleft offbott offbott ";
|
||||
|
||||
.nav-secondary { display: none; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,8 @@ div#page div#news {
|
||||
|
||||
&.open {
|
||||
max-height: none;
|
||||
|
||||
#news-body { pointer-events: unset; }
|
||||
}
|
||||
|
||||
#news-header {
|
||||
@ -26,26 +28,27 @@ div#page div#news {
|
||||
cursor: pointer;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
padding: 0.5rem 0.5rem 0;
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
#news-body {
|
||||
display: block;
|
||||
box-sizing: border-box;
|
||||
|
||||
margin-top: 5px;
|
||||
max-width: 800px;
|
||||
padding: 0 0.5rem 0.5rem;
|
||||
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
#news-dismiss {
|
||||
position: absolute;
|
||||
right: 0.5rem;
|
||||
top: 0.25rem;
|
||||
right: 0;
|
||||
top: 0;
|
||||
padding: 0.25rem 1rem;
|
||||
|
||||
cursor: pointer;
|
||||
font-size: 1.15rem;
|
||||
font-size: 1.25rem;
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
|
@ -1,35 +1,101 @@
|
||||
.paginator {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
justify-content: space-evenly;
|
||||
background-color: themed("color-foreground");
|
||||
border-radius: 0.25rem;
|
||||
|
||||
div.paginator {
|
||||
display: block;
|
||||
padding: 2em 0 1em 0;
|
||||
text-align: center;
|
||||
clear: both;
|
||||
width: max-content;
|
||||
margin: 0 auto;
|
||||
|
||||
menu {
|
||||
& > a, & > span {
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-width: 2.15rem;
|
||||
|
||||
font-size: 1rem;
|
||||
line-height: 1rem;
|
||||
padding: 0.75rem 0.3rem; // otherwise large page numbers wrap
|
||||
|
||||
border-radius: 0.25rem;
|
||||
|
||||
&:hover {
|
||||
background: themed("color-section");
|
||||
}
|
||||
}
|
||||
|
||||
li {
|
||||
a {
|
||||
margin: 0 0.25em;
|
||||
padding: 0.25em 0.75em;
|
||||
& > a[data-disabled="true"] {
|
||||
color: var(--color-text);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
// Ordering
|
||||
// Oh boy
|
||||
.page {
|
||||
order: 20;
|
||||
&.lg { display: none; }
|
||||
&.current { cursor: default; }
|
||||
}
|
||||
.prev {
|
||||
order: 1;
|
||||
margin-right: auto;
|
||||
}
|
||||
.spacer {
|
||||
order: 20;
|
||||
padding: 0;
|
||||
|
||||
&:last-child { display: none; }
|
||||
svg {
|
||||
height: 1rem;
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
}
|
||||
.next {
|
||||
order: 9;
|
||||
margin-left: auto;
|
||||
}
|
||||
.break {
|
||||
order: 10;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
// Tablet
|
||||
@include window-larger-than(35rem) {
|
||||
justify-content: center;
|
||||
gap: 0.125rem;
|
||||
|
||||
a, span {
|
||||
order: 0 !important;
|
||||
min-width: 2.25rem;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
background: $paginator-hover-background;
|
||||
color: $paginator-hover-color;
|
||||
.break { display: none; }
|
||||
.spacer {
|
||||
padding: inherit;
|
||||
svg { transform: unset; }
|
||||
}
|
||||
|
||||
&.more {
|
||||
color: $paginator-more-color;
|
||||
.prev { margin-right: 1rem; }
|
||||
.next { margin-left: 1rem; }
|
||||
}
|
||||
|
||||
@include window-larger-than(50rem) {
|
||||
a, span {
|
||||
padding: 0.75rem 0.5rem;
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
span {
|
||||
margin: 0 0.25em;
|
||||
padding: 0.25em 0.75em;
|
||||
font-weight: bold;
|
||||
.prev, .next {
|
||||
span { display: none; }
|
||||
}
|
||||
}
|
||||
|
||||
@include window-larger-than(65rem) {
|
||||
a.page.lg { display: flex; }
|
||||
}
|
||||
}
|
||||
|
@ -59,14 +59,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.guest-warning {
|
||||
.guest-warning-dialog {
|
||||
top: 5vh;
|
||||
height: 90vh;
|
||||
width: 80vw;
|
||||
}
|
||||
}
|
||||
|
||||
div#page {
|
||||
|
||||
> div /* div#c-$controller */
|
||||
|
@ -1,33 +1,55 @@
|
||||
.guest-warning {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
z-index: 500;
|
||||
background-color: themed("color-background");
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 1000;
|
||||
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
background: themed("color-background");
|
||||
|
||||
.guest-warning-dialog {
|
||||
z-index: 500;
|
||||
position: relative;
|
||||
top: 20vh;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
height: 40vh;
|
||||
width: 40vw;
|
||||
overflow-x: scroll;
|
||||
background-color: themed("color-section");
|
||||
margin: 20vh 0.5em 0;
|
||||
|
||||
height: min-content;
|
||||
max-width: 360px;
|
||||
|
||||
.dialog-header {
|
||||
padding: $padding-050 $base-padding;
|
||||
background-color: themed("color-section-lighten-5");
|
||||
border-bottom: 1px solid themed("color-background");
|
||||
padding: 0 0.5em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
.dialog-content {
|
||||
padding: $padding-050 $base-padding;
|
||||
background: var(--color-foreground);
|
||||
padding: 2em 1em 1em;
|
||||
border-radius: 3px 3px 0 0;
|
||||
|
||||
p:last-child { margin-bottom: 0; }
|
||||
}
|
||||
|
||||
.dialog-footer {
|
||||
padding: $padding-050 $base-padding;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.5em;
|
||||
|
||||
background: var(--color-foreground);
|
||||
padding: 1em 1em 2em;
|
||||
border-radius: 0 0 3px 3px;
|
||||
|
||||
button {
|
||||
background: var(--color-section-lighten-5);
|
||||
color: var(--color-link);
|
||||
padding: 0.5em 1em;
|
||||
border-radius: 3px;
|
||||
|
||||
&:hover {
|
||||
background: var(--color-section-lighten-10);
|
||||
color: var(--color-link-hover);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,12 @@ body.c-static.a-home {
|
||||
background-color: var(--bg-color);
|
||||
background-image: var(--bg-image);
|
||||
|
||||
background-position-y: 3.75rem;
|
||||
|
||||
@include window-larger-than(800px) {
|
||||
background-position-y: unset;
|
||||
}
|
||||
|
||||
#page {
|
||||
background: none;
|
||||
margin: 25rem auto 0;
|
||||
@ -20,7 +26,7 @@ body.c-static.a-home {
|
||||
|
||||
padding: 1rem;
|
||||
margin: 0.5rem;
|
||||
border-radius: 0.5rem;
|
||||
border-radius: 0.25rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@ -69,6 +75,10 @@ body.c-static.a-home {
|
||||
}
|
||||
}
|
||||
|
||||
#home-search-form:not(.empty) .home-buttons a span::before {
|
||||
content: "Search ";
|
||||
}
|
||||
|
||||
|
||||
// Footer
|
||||
.home-footer-top {
|
||||
@ -82,7 +92,7 @@ body.c-static.a-home {
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
border-radius: 0.5rem 0.5rem 0 0;
|
||||
border-radius: 0.25rem 0.25rem 0 0;
|
||||
|
||||
@include window-larger-than(480px) {
|
||||
margin: 0.5rem 0.5rem 0;
|
||||
@ -103,7 +113,7 @@ body.c-static.a-home {
|
||||
margin: 0;
|
||||
padding: 0.5rem;
|
||||
|
||||
border-radius: 0 0 0.5rem 0.5rem;
|
||||
border-radius: 0 0 0.25rem 0.25rem;
|
||||
|
||||
@include window-larger-than(480px) {
|
||||
margin: 0 0.5rem;
|
||||
|
@ -1,3 +1,22 @@
|
||||
body.c-posts.a-index, body.c-favorites.a-index {
|
||||
#page {
|
||||
// Override the theme to instead
|
||||
// project it upon the content area
|
||||
background: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
// Exhibit A
|
||||
// Makes the content area take up the
|
||||
// full height of the page. Yes, really.
|
||||
#page, #c-posts, #c-favorites, #a-index {
|
||||
// I hate both this and myself
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.post-index {
|
||||
display: grid;
|
||||
|
||||
@ -7,24 +26,46 @@
|
||||
"sidebar";
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: min-content 1fr min-content;
|
||||
gap: 1em;
|
||||
|
||||
flex: 1; // See Exhibit A
|
||||
|
||||
// 1. Searchbox
|
||||
.search {
|
||||
grid-area: search;
|
||||
|
||||
padding: 0.5rem 0.25rem;
|
||||
background-color: #152f56;
|
||||
background-color: themed("color-foreground");
|
||||
box-shadow: inset 0px -0.25rem 0.25rem -0.25rem themed("color-background");
|
||||
|
||||
h1 {
|
||||
font-size: $h3-size;
|
||||
}
|
||||
|
||||
.search-controls {
|
||||
display: none;
|
||||
flex-flow: column;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Content
|
||||
.content {
|
||||
display: flex; // See Exhibit A
|
||||
flex-flow: column;
|
||||
|
||||
grid-area: content;
|
||||
|
||||
// Imported from #page
|
||||
padding: 0.5rem 0.25rem themed("content-padding-bottom");
|
||||
background-color: #152f56;
|
||||
background-color: themed("color-foreground");
|
||||
background-image: themed("image-foreground");
|
||||
background-position: themed("image-foreground-position");
|
||||
background-repeat: themed("image-foreground-repeat");
|
||||
|
||||
// Quick tag edit
|
||||
#edit-dialog textarea {
|
||||
margin-bottom: 0.25em;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
// Actual content area:
|
||||
@ -32,86 +73,13 @@
|
||||
.post-index-gallery {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
gap: 1em;
|
||||
gap: 1rem;
|
||||
|
||||
.wiki-excerpt {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
position: relative;
|
||||
padding: 1em 1em 0;
|
||||
gap: 0.5em;
|
||||
flex: 1; // See Exhibit A
|
||||
|
||||
background: var(--color-section);
|
||||
max-width: 60em;
|
||||
|
||||
.wiki-excerpt-toggle {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
padding: 1em;
|
||||
outline: none;
|
||||
|
||||
transition: transform 0.25s;
|
||||
|
||||
&::after {
|
||||
@include font-awesome-icon;
|
||||
content: unicode("f0d8");
|
||||
}
|
||||
}
|
||||
|
||||
.styled-dtext {
|
||||
background: linear-gradient(to top, var(--color-section), var(--color-text));
|
||||
-webkit-background-clip: text;
|
||||
background-clip: text;
|
||||
color: transparent;
|
||||
max-height: 10em;
|
||||
overflow: hidden;
|
||||
|
||||
transition: max-height 0.25s;
|
||||
|
||||
// Disable links
|
||||
pointer-events: none;
|
||||
cursor: unset;
|
||||
|
||||
a {
|
||||
color: unset;
|
||||
text-decoration: underline;
|
||||
&::after { content: none; }
|
||||
}
|
||||
}
|
||||
|
||||
.wiki-excerpt-readmore {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 3em;
|
||||
|
||||
// Makes the button appear in the middle of the animation
|
||||
transition: visibility 0s 0.125s;
|
||||
|
||||
span {
|
||||
padding: 0.5em 1em;
|
||||
background: var(--color-section);
|
||||
border-radius: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
&.hidden{
|
||||
.wiki-excerpt-toggle { transform: rotate(-90deg); }
|
||||
.styled-dtext {
|
||||
max-height: 0;
|
||||
}
|
||||
.wiki-excerpt-readmore { visibility: hidden; }
|
||||
}
|
||||
}
|
||||
|
||||
.paginator {
|
||||
padding: 1em 0;
|
||||
.posts-container {
|
||||
flex: 1; // See Exhibit A
|
||||
grid-auto-rows: min-content;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -124,6 +92,11 @@
|
||||
flex-flow: column;
|
||||
gap: 1em;
|
||||
|
||||
padding: 0.5rem 0.25rem;
|
||||
background-color: #152f56;
|
||||
background-color: themed("color-foreground");
|
||||
box-shadow: inset 0px 0.25rem 0.25rem -0.25rem themed("color-background");
|
||||
|
||||
// Mode selection
|
||||
#mode-box-mode, #mode-box #set-id {
|
||||
width: 100%;
|
||||
@ -139,11 +112,170 @@
|
||||
|
||||
// Desktop
|
||||
.post-index {
|
||||
@include window-larger-than(800px) {
|
||||
@include window-larger-than(50rem) {
|
||||
grid-template-areas:
|
||||
"search content"
|
||||
"sidebar content";
|
||||
grid-template-columns: 15em 1fr;
|
||||
grid-template-columns: 14rem 1fr;
|
||||
grid-template-rows: min-content 1fr;
|
||||
|
||||
.search {
|
||||
box-shadow: inset -0.25rem 0px 0.25rem -0.25rem themed("color-background");
|
||||
margin-top: 0.25rem;
|
||||
border-top-left-radius: 0.25rem;
|
||||
padding: 0.5rem;
|
||||
|
||||
.search-controls {
|
||||
display: flex;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
box-shadow: inset -0.25rem 0px 0.25rem -0.25rem themed("color-background");
|
||||
margin-bottom: 0.25rem;
|
||||
border-bottom-left-radius: 0.25rem;
|
||||
padding: 0.5rem
|
||||
}
|
||||
|
||||
.content {
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Fullscreen
|
||||
body.c-posts.a-index[data-st-fullscreen="true"] {
|
||||
// Desktop-only, for obvious reasons
|
||||
@include window-larger-than(50rem) {
|
||||
.post-index {
|
||||
grid-template-areas:
|
||||
"search "
|
||||
"content";
|
||||
grid-template-columns: 1fr;
|
||||
|
||||
.search {
|
||||
display: flex;
|
||||
|
||||
border-radius: 0.25rem 0.25rem 0 0;
|
||||
box-shadow: inset 0px -0.25rem 0.25rem -0.25rem themed("color-background");
|
||||
|
||||
.post-search {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.search-controls {
|
||||
display: flex;
|
||||
justify-content: right;
|
||||
align-self: end;
|
||||
margin: 0 0 0 0.5rem;
|
||||
|
||||
.st-button.w100 {
|
||||
width: unset;
|
||||
span { display: none; }
|
||||
}
|
||||
}
|
||||
}
|
||||
.sidebar { display: none; }
|
||||
.content {
|
||||
border-radius: 0 0 0.25rem 0.25rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// FEATURES
|
||||
// Wiki Excerpt
|
||||
.wiki-excerpt {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
position: relative;
|
||||
|
||||
background: themed("color-section");
|
||||
border-radius: 0.25rem;
|
||||
|
||||
// header
|
||||
h3 {
|
||||
cursor: pointer;
|
||||
padding: 0.5rem 1rem 0.5rem 1.5rem;
|
||||
|
||||
&::after {
|
||||
@include font-awesome-icon;
|
||||
content: unicode("f0da");
|
||||
|
||||
transition: transform 0.25s;
|
||||
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
padding: 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
// body
|
||||
.styled-dtext {
|
||||
background: linear-gradient(to top, themed("color-section"), themed("color-text"));
|
||||
-webkit-background-clip: text;
|
||||
background-clip: text;
|
||||
color: transparent;
|
||||
|
||||
max-height: 0rem;
|
||||
max-width: 50rem;
|
||||
overflow: hidden;
|
||||
padding: 0 0.5rem;
|
||||
|
||||
transition: max-height 0.25s;
|
||||
|
||||
// Disable links
|
||||
pointer-events: none;
|
||||
cursor: unset;
|
||||
|
||||
a {
|
||||
color: unset;
|
||||
text-decoration: underline;
|
||||
&::after { content: none; }
|
||||
}
|
||||
|
||||
p:last-child { margin-bottom: 0; }
|
||||
}
|
||||
|
||||
// wiki link
|
||||
.wiki-excerpt-readmore {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
|
||||
height: 3rem;
|
||||
max-width: 50rem;
|
||||
box-sizing: border-box;
|
||||
|
||||
// Makes the button appear in the middle of the animation
|
||||
transition: visibility 0s 0.125s;
|
||||
visibility: hidden;
|
||||
|
||||
span {
|
||||
padding: 0.5rem 1rem;
|
||||
background: themed("color-section");
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
}
|
||||
|
||||
&.open{
|
||||
.wiki-excerpt-toggle::after { transform: rotate(90deg); }
|
||||
.styled-dtext {
|
||||
max-height: 10rem;
|
||||
}
|
||||
.wiki-excerpt-readmore { visibility: visible; }
|
||||
}
|
||||
|
||||
&.loading {
|
||||
h3::after, .styled-dtext { transition: none; }
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ $modes: (
|
||||
);
|
||||
|
||||
@each $mode, $color in $modes {
|
||||
#page[data-mode-menu="#{$mode}"] {
|
||||
#page[data-mode-menu="#{$mode}"] .content {
|
||||
background-color: $color;
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
|
||||
#has-parent-relationship-preview, #has-children-relationship-preview {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
|
||||
|
@ -1,20 +1,12 @@
|
||||
|
||||
|
||||
div#c-static {
|
||||
div#a-site-map {
|
||||
width: 80em;
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
max-width: 80em;
|
||||
|
||||
section {
|
||||
width: 20em;
|
||||
float: left;
|
||||
|
||||
h1 {
|
||||
font-size: $h3-size;
|
||||
}
|
||||
|
||||
ul {
|
||||
margin-bottom: 1.5em;
|
||||
}
|
||||
ul { margin-bottom: 1.5em; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -249,8 +249,9 @@ div#c-users {
|
||||
|
||||
div.input {
|
||||
input[type="text"], input[type="email"], input[type="password"], select {
|
||||
width: 100%;
|
||||
max-width: unset;
|
||||
// z_responsive is the absolute worst
|
||||
width: 100% !important;
|
||||
max-width: unset !important;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
|
@ -3,14 +3,27 @@
|
||||
module GitHelper
|
||||
def self.init
|
||||
if Rails.root.join("REVISION").exist?
|
||||
@hash = Rails.root.join("REVISION").read.strip
|
||||
@hash = @tag = Rails.root.join("REVISION").read.strip
|
||||
elsif system("type git > /dev/null && git rev-parse --show-toplevel > /dev/null")
|
||||
@hash = `git rev-parse HEAD`.strip
|
||||
@tag = `git describe --abbrev=0`
|
||||
else
|
||||
@hash = ""
|
||||
@hash = @tag = ""
|
||||
end
|
||||
end
|
||||
|
||||
def self.tag
|
||||
@tag
|
||||
end
|
||||
|
||||
def self.hash
|
||||
@hash
|
||||
end
|
||||
|
||||
def self.version
|
||||
@tag.presence || short_hash
|
||||
end
|
||||
|
||||
def self.short_hash
|
||||
@hash[0..8]
|
||||
end
|
||||
@ -18,4 +31,13 @@ module GitHelper
|
||||
def self.commit_url(commit_hash)
|
||||
"#{Danbooru.config.source_code_url}/commit/#{commit_hash}"
|
||||
end
|
||||
|
||||
def self.release_url(tag_name)
|
||||
"#{Danbooru.config.source_code_url}/releases/tag/#{tag_name}"
|
||||
end
|
||||
|
||||
def self.version_url
|
||||
return release_url(@tag) if @tag.present?
|
||||
commit_url(@hash)
|
||||
end
|
||||
end
|
||||
|
@ -61,7 +61,8 @@ class StatsUpdater
|
||||
|
||||
stats[:total_forum_threads] = ForumTopic.count
|
||||
stats[:total_forum_posts] = ForumPost.maximum("id") || 0
|
||||
stats[:average_posts_per_thread] = (stats[:total_forum_posts] / stats[:total_forum_threads]).round
|
||||
stats[:average_posts_per_thread] = 0
|
||||
stats[:average_posts_per_thread] = (stats[:total_forum_posts] / stats[:total_forum_threads]).round if stats[:total_forum_threads] > 0
|
||||
stats[:average_forum_posts_per_day] = daily_average.call(stats[:total_forum_posts])
|
||||
|
||||
### Blips ###
|
||||
|
@ -38,9 +38,6 @@ class UserFeedback < ApplicationRecord
|
||||
|
||||
def log_destroy
|
||||
ModAction.log(:user_feedback_destroy, { user_id: user_id, reason: body, type: category, record_id: id })
|
||||
deletion_user = "\"#{CurrentUser.name}\":/users/#{CurrentUser.id}"
|
||||
creator_user = "\"#{creator.name}\":/users/#{creator.id}"
|
||||
StaffNote.create(body: "#{deletion_user} deleted #{category} feedback, created #{created_at.to_date} by #{creator_user}: #{body}", user_id: user_id, creator: User.system)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
<% if comment.should_see?(CurrentUser.user) || (current_page?(:controller => "comments", :action => "show") && CurrentUser.id == comment.creator_id) %>
|
||||
<% if comment.should_see?(CurrentUser.user) || (params[:controller] == "comments" && params[:action] == "show" && CurrentUser.id == comment.creator_id) %>
|
||||
<article class="comment comment-post-grid <%= "below-threshold" if comment.below_threshold? %>" data-post-id="<%= comment.post_id %>"
|
||||
data-comment-id="<%= comment.id %>" data-score="<%= comment.score %>"
|
||||
data-creator="<%= comment.creator&.name.downcase %>" data-is-sticky="<%= comment.is_sticky %>" data-creator-id="<%= comment.creator_id %>"
|
||||
|
@ -1,7 +1,8 @@
|
||||
<%= decorated_nav_link_to("Posts", "fas fa-images", posts_path) %>
|
||||
<%= decorated_nav_link_to("Pools", "fas fa-book", gallery_pools_path) %>
|
||||
<%= decorated_nav_link_to("Sets", "fas fa-clone", post_sets_path) %>
|
||||
<%= decorated_nav_link_to("Tags", "fas fa-tags", tags_path) %>
|
||||
<%= decorated_nav_link_to("Blips", "fas fa-bullhorn", blips_path) %>
|
||||
<%= decorated_nav_link_to("Comments", "fas fa-comment-alt", comments_path(group_by: "post")) %>
|
||||
<%= decorated_nav_link_to("Forum", "fas fa-chalkboard", forum_topics_path, class: (CurrentUser.has_forum_been_updated? ? "forum-updated" : nil)) %>
|
||||
<%= decorated_nav_link_to("Artists", :brush, artists_path) %>
|
||||
<%= decorated_nav_link_to("Posts", :images, posts_path) %>
|
||||
<%= decorated_nav_link_to("Pools", :library, gallery_pools_path) %>
|
||||
<%= decorated_nav_link_to("Sets", :group, post_sets_path) %>
|
||||
<%= decorated_nav_link_to("Tags", :tags, tags_path) %>
|
||||
<%= decorated_nav_link_to("Blips", :megaphone, blips_path) %>
|
||||
<%= decorated_nav_link_to("Comments", :message_square, comments_path(group_by: "post")) %>
|
||||
<%= decorated_nav_link_to("Forum", :lectern, forum_topics_path, class: (CurrentUser.has_forum_been_updated? ? "forum-updated" : nil)) %>
|
||||
|
@ -3,51 +3,51 @@
|
||||
<a href="/" class="nav-logo-link"></a>
|
||||
</menu>
|
||||
|
||||
<menu class="nav-primary">
|
||||
<menu class="nav-primary desktop">
|
||||
<%= render "layouts/main_links" %>
|
||||
</menu>
|
||||
|
||||
<menu class="nav-offset-left"></menu>
|
||||
<menu class="nav-offset-bottom"></menu>
|
||||
<menu class="nav-offset-left mobile"></menu>
|
||||
<menu class="nav-offset-bott mobile"></menu>
|
||||
|
||||
<menu class="nav-secondary <%= "empty" unless content_for(:secondary_links) %>">
|
||||
<menu class="nav-secondary desktop <%= "empty" unless content_for(:secondary_links) %>">
|
||||
<%= yield :secondary_links %>
|
||||
</menu>
|
||||
|
||||
<menu class="nav-controls">
|
||||
<a href="" id="nav-toggle">
|
||||
<i class="fas fa-bars"></i>
|
||||
<menu class="nav-controls desktop">
|
||||
<a role="button" href="" id="nav-toggle" class="nav-controls-toggle">
|
||||
<span><%= svg_icon(:hamburger) %></span>
|
||||
</a>
|
||||
<% if CurrentUser.is_anonymous? %>
|
||||
<%= link_to(new_session_path, class: "nav-tools-login") do %>
|
||||
<i class="fas fa-sign-in-alt"></i>
|
||||
Sign in
|
||||
<% end %>
|
||||
<a href="<%= new_session_path %>" class="simple-avatar nav-controls-profile collapse-2">
|
||||
<span class="simple-avatar-button sign-in">
|
||||
<span class="simple-avatar-name">
|
||||
Sign In
|
||||
</span>
|
||||
<span class="simple-avatar-image">
|
||||
<%= svg_icon(:log_in) %>
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
<% else %>
|
||||
<%= link_to(user_path(CurrentUser.user), class: "nav-tools-login") do %>
|
||||
<i class="far fa-user-circle"></i>
|
||||
Profile
|
||||
<% end %>
|
||||
<%= simple_avatar(CurrentUser.user, named: true, class: "nav-controls-profile collapse-2") %>
|
||||
<% end %>
|
||||
</menu>
|
||||
|
||||
<menu class="nav-tools <%= CurrentUser.is_anonymous? ? "anonymous" : "" %>">
|
||||
<%= decorated_nav_link_to("Themes", "fas fa-swatchbook", theme_path, class: "nav-tools-themes") %>
|
||||
<% if CurrentUser.is_anonymous? %>
|
||||
<%= decorated_nav_link_to("Sign in", "fas fa-sign-in-alt", new_session_path, class: "nav-tools-login") %>
|
||||
<% else %>
|
||||
<%= decorated_nav_link_to("Settings", "fas fa-cog", edit_user_path(CurrentUser.user), class: "nav-tools-settings") %>
|
||||
<%= decorated_nav_link_to("Account #{unread_dmails(CurrentUser.user)}", "far fa-user-circle", user_path(CurrentUser.user), class: "nav-tools-login") %>
|
||||
<menu class="nav-tools desktop <%= CurrentUser.is_anonymous? ? "anonymous" : "" %>">
|
||||
<%= decorated_nav_link_to("Themes", :swatch, theme_path, class: "nav-tools-themes") %>
|
||||
<% unless CurrentUser.is_anonymous? %>
|
||||
<%= decorated_nav_link_to("Settings", :settings, edit_user_path(CurrentUser.user), class: "nav-tools-settings") %>
|
||||
<% end %>
|
||||
</menu>
|
||||
|
||||
<menu class="nav-help <%= CurrentUser.is_anonymous? ? "anonymous" : "" %>">
|
||||
<menu class="nav-help desktop <%= CurrentUser.is_anonymous? ? "anonymous" : "" %>">
|
||||
<%= nav_link_to("Wiki", wiki_pages_path(title: "help:home"), class: "nav-help-wiki") %>
|
||||
<%= nav_link_to("Help", help_pages_path, class: "nav-help-help") %>
|
||||
<% if !CurrentUser.is_anonymous? %>
|
||||
<%= custom_image_nav_link_to("Discord", "discord.com.png", discord_get_path, class: "nav-help-discord") %>
|
||||
<% unless CurrentUser.is_anonymous? %>
|
||||
<%= custom_image_nav_link_to("Discord", "discord.com.png", discord_get_path, class: "nav-help-discord collapse-1") %>
|
||||
<% end %>
|
||||
<%= custom_image_nav_link_to("SubscribeStar", "subscribestar.adult.png", subscribestar_path, class: "nav-help-subscribestar") %>
|
||||
<%= custom_image_nav_link_to("SubscribeStar", "subscribestar.adult.png", subscribestar_path, class: "nav-help-subscribestar collapse-1") %>
|
||||
<%= nav_link_to("More", site_map_path, class: "nav-help-map") %>
|
||||
</menu>
|
||||
|
||||
|
@ -1,17 +1,23 @@
|
||||
<%= javascript_tag nonce: true do -%>
|
||||
(function() {
|
||||
try {
|
||||
var theme = localStorage.getItem('theme') || 'hexagon';
|
||||
var extra = localStorage.getItem('theme-extra') || 'hexagon';
|
||||
var sheader = localStorage.getItem('theme-sheader') || false;
|
||||
var palette = localStorage.getItem('theme-palette') || 'default';
|
||||
var nav = localStorage.getItem('theme-nav') || 'top';
|
||||
const values = {
|
||||
// Theme
|
||||
"th-main": localStorage.getItem("theme") || "hexagon",
|
||||
"th-extra": localStorage.getItem("theme-extra") || "hexagon",
|
||||
"th-sheader": localStorage.getItem("theme-sheader") || false,
|
||||
"th-forumnotif": localStorage.getItem("theme-forumnotif") || false,
|
||||
"th-palette": localStorage.getItem("theme-palette") || "default",
|
||||
"th-nav": localStorage.getItem("theme-nav") || "top",
|
||||
|
||||
// Settings
|
||||
"st-fullscreen": localStorage.getItem("e6.posts.fusk") || false,
|
||||
};
|
||||
|
||||
var b = document.body;
|
||||
b.setAttribute('data-th-main', theme);
|
||||
b.setAttribute('data-th-extra', extra);
|
||||
b.setAttribute('data-th-sheader', sheader);
|
||||
b.setAttribute('data-th-palette', palette);
|
||||
b.setAttribute('data-th-nav', nav);
|
||||
for (const [name, value] of Object.entries(values)) {
|
||||
b.setAttribute("data-" + name, value);
|
||||
}
|
||||
} catch(e) {}
|
||||
})();
|
||||
<% end -%>
|
||||
|
@ -10,8 +10,11 @@
|
||||
<% if CurrentUser.is_anonymous? %>
|
||||
<%= render "static/guest_warning" %>
|
||||
<% end %>
|
||||
|
||||
<div id="page">
|
||||
<%= yield :layout %>
|
||||
</div>
|
||||
|
||||
<%= render "static/deferred_posts" %>
|
||||
<% end %>
|
||||
</html>
|
||||
|
@ -1,8 +1,8 @@
|
||||
<% if news_update.present? %>
|
||||
<div class="ui-state-highlight site-notice" style="display: none;" id="news" data-id="<%= news_update.id %>">
|
||||
<a href="" id="news-dismiss" title="Dismiss"><i class="fas fa-times"></i></a>
|
||||
<a href="" role="button" id="news-dismiss" title="Dismiss"><i class="fas fa-times"></i></a>
|
||||
<h6 id="news-header">News: <%= news_update.created_at.strftime("%b %d, %Y") %>
|
||||
<a href="" id="news-show">Show</a>
|
||||
<a href="" role="button" id="news-show">Show</a>
|
||||
</h6>
|
||||
<div id="news-body" class="dtext-container"><%= format_text(news_update.message) %></div>
|
||||
</div>
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
<div class="search">
|
||||
<%= render "posts/partials/common/search", title: "Posts", tags: params[:tags] %>
|
||||
<%= render "posts/partials/index/controls" %>
|
||||
</div>
|
||||
|
||||
<div class="sidebar">
|
||||
|
6
app/views/posts/partials/index/_controls.html.erb
Normal file
6
app/views/posts/partials/index/_controls.html.erb
Normal file
@ -0,0 +1,6 @@
|
||||
<div class="search-controls">
|
||||
<button id="search-fullscreen" class="st-button w100 stealth">
|
||||
<%= svg_icon(:fullscreen) %>
|
||||
<span>Fullscreen</span>
|
||||
</button>
|
||||
</div>
|
@ -33,9 +33,7 @@
|
||||
<% if CurrentUser.is_privileged? %>
|
||||
<span id="tag-script-ui" style="display: none;">
|
||||
<input id="tag-script-field" data-autocomplete="tag-edit" placeholder="Enter tag script" style="display: none;"/>
|
||||
<% if CurrentUser.is_staff? %>
|
||||
<button id="tag-script-all">All</button>
|
||||
<% end %>
|
||||
<button id="tag-script-all">All</button>
|
||||
</span>
|
||||
<input id="quick-mode-reason" placeholder="Reason" style="display: none;"/>
|
||||
<% end %>
|
||||
|
@ -1,8 +1,7 @@
|
||||
<div id="posts" class="post-index-gallery user-disable-cropped-<%= Danbooru.config.enable_image_cropping? && CurrentUser.user.disable_cropped_thumbnails? %>">
|
||||
<% if @wiki_text.present? %>
|
||||
<section class="wiki-excerpt hidden">
|
||||
<h3><%= @wiki_page.pretty_title %></h3>
|
||||
<a href="" class="wiki-excerpt-toggle" role="button"></a>
|
||||
<section class="wiki-excerpt loading">
|
||||
<h3 role="button" class="wiki-excerpt-toggle"><%= @wiki_page.pretty_title %></h3>
|
||||
<%= format_text(@wiki_text, allow_color: true, max_thumbs: 0) %>
|
||||
<a href="<%= wiki_page_path(@wiki_page) %>" class="wiki-excerpt-readmore"><span>Read More</span></a>
|
||||
</section>
|
||||
|
@ -1,20 +1,29 @@
|
||||
<footer id="page-footer">
|
||||
<span class="footer-left">
|
||||
<%= link_to "Rules", terms_of_service_path %>
|
||||
<%= link_to "Takedowns", takedown_static_path %>
|
||||
<%= link_to "Privacy", privacy_policy_path %>
|
||||
<%= link_to "Contact", contact_path %>
|
||||
<%= link_to "Advertising", help_page_path(id: "advertising") %>
|
||||
</span>
|
||||
<span class="footer-logo">
|
||||
<a href="/"><%= image_pack_tag("main-logo.svg", class: "footer-logo") %></a>
|
||||
</span>
|
||||
<span class="footer-right">
|
||||
<span class="footer-running">Running e621ng</span>
|
||||
<%= link_to "Themes / Gestures", theme_path %>
|
||||
<% if CurrentUser.user.enable_keyboard_navigation %>
|
||||
<%= link_to "Keyboard Shortcuts", keyboard_shortcuts_path %>
|
||||
<% end %>
|
||||
<%= link_to disable_mobile_mode? ? "Mobile mode: OFF": "Mobile mode: ON", disable_mobile_mode_path, :rel => "nofollow" %>
|
||||
</span>
|
||||
<footer class="footer-wrapper">
|
||||
<div class="footer-grid">
|
||||
<span class="footer-logo">
|
||||
<a href="/"><%= image_pack_tag("main-logo.svg") %></a>
|
||||
</span>
|
||||
<span class="footer-left">
|
||||
<%= link_to "Rules", terms_of_service_path %>
|
||||
<%= link_to "Takedowns", takedown_static_path %>
|
||||
<%= link_to "Privacy", privacy_policy_path %>
|
||||
<%= link_to "Contact", contact_path %>
|
||||
<%= link_to "Advertising", help_page_path(id: "advertising") %>
|
||||
</span>
|
||||
<span class="footer-right">
|
||||
<span class="footer-running">Running e621ng</span>
|
||||
<span class="footer-version">
|
||||
<% if GitHelper.version.empty? %>
|
||||
v. unknown
|
||||
<% else %>
|
||||
v. <%= link_to GitHelper.version, GitHelper.version_url %>
|
||||
<% end %>
|
||||
</span>
|
||||
<%= link_to "Themes / Gestures", theme_path %>
|
||||
<% if CurrentUser.user.enable_keyboard_navigation %>
|
||||
<%= link_to "Keyboard Shortcuts", keyboard_shortcuts_path %>
|
||||
<% end %>
|
||||
<%= link_to disable_mobile_mode? ? "Mobile mode: OFF": "Mobile mode: ON", disable_mobile_mode_path, :rel => "nofollow" %>
|
||||
</span>
|
||||
</div>
|
||||
</footer>
|
||||
|
@ -3,12 +3,11 @@
|
||||
<h1 class="dialog-header">Over 18?</h1>
|
||||
<div class="dialog-content">
|
||||
<p>
|
||||
You must be over the age of 18 and agree
|
||||
to <%= link_to "the terms of service", terms_of_service_path, target: "_blank" %> to access this page.
|
||||
You must be <b>18 years or older</b> and agree to the <%= link_to "terms of service", terms_of_service_path, target: "_blank" %> to access this website.
|
||||
</p>
|
||||
<p>
|
||||
By default a limited blacklist has been applied hiding content that is commonly objected to. You may remove
|
||||
items from this blacklist by using the blacklist menu item.
|
||||
Content that is commonly considered objectionable is blacklisted by default.
|
||||
You may remove tags from this blacklist using the corresponding menu item.
|
||||
</p>
|
||||
</div>
|
||||
<div class="dialog-footer">
|
||||
|
@ -4,21 +4,26 @@
|
||||
<% end -%>
|
||||
|
||||
<section class="home-section">
|
||||
<%= form_tag(posts_path, method: "get", class: "home-search") do %>
|
||||
<%= text_field_tag("tags", "", autofocus: "autofocus", placeholder: "Search posts by tag", data: { shortcut: "q", autocomplete: "tag-query" }) %>
|
||||
<%= tag.button(tag.i(class: "fa-solid fa-magnifying-glass"), type: "submit") %>
|
||||
<% end %>
|
||||
<%= form_tag(posts_path, method: "get", id: "home-search-form") do %>
|
||||
|
||||
<div class="home-buttons">
|
||||
<a href="/posts">
|
||||
<i class="fas fa-splotch"></i>
|
||||
Latest
|
||||
</a>
|
||||
<a href="/popular">
|
||||
<i class="fas fa-fire-alt"></i>
|
||||
Popular
|
||||
</a>
|
||||
</div>
|
||||
<!-- Primary Searchbar -->
|
||||
<div class="home-search">
|
||||
<%= text_field_tag("tags", "", autofocus: "autofocus", placeholder: "Search posts by tag", data: { shortcut: "q", autocomplete: "tag-query" }) %>
|
||||
<%= tag.button(tag.i(class: "fa-solid fa-magnifying-glass"), type: "submit") %>
|
||||
</div>
|
||||
|
||||
<!-- Secondary search buttons -->
|
||||
<div class="home-buttons">
|
||||
<a href="<%= posts_path %>" tags="">
|
||||
<i class="fas fa-splotch"></i>
|
||||
<span>Latest</span>
|
||||
</a>
|
||||
<a href="<%= posts_path(tags: "order:rank") %>" tags="order:rank">
|
||||
<i class="fas fa-fire-alt"></i>
|
||||
<span>Popular</span>
|
||||
</a>
|
||||
</div>
|
||||
<% end %>
|
||||
</section>
|
||||
|
||||
<% if news_update = NewsUpdate.recent %>
|
||||
|
@ -2,7 +2,7 @@
|
||||
<div id="a-site-map">
|
||||
<section>
|
||||
<ul>
|
||||
<li><h1>Posts</h1></li>
|
||||
<li><h3>Posts</h3></li>
|
||||
<li><%= link_to("Listing", posts_path) %></li>
|
||||
<li><%= link_to("Upload", new_upload_path) %></li>
|
||||
<% if CurrentUser.is_janitor? %>
|
||||
@ -17,7 +17,7 @@
|
||||
<li><%= link_to("Help", help_page_path(id: "posts")) %></li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><h1>Post Events</h1></li>
|
||||
<li><h3>Post Events</h3></li>
|
||||
<li><%= link_to("Listing", post_events_path) %></li>
|
||||
<li><%= link_to("Tag Changes", post_versions_path) %></li>
|
||||
<li><%= link_to("Approvals", post_approvals_path) %></li>
|
||||
@ -25,7 +25,7 @@
|
||||
<li><%= link_to("Replacements", post_replacements_path) %></li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><h1>Tools</h1></li>
|
||||
<li><h3>Tools</h3></li>
|
||||
<li><%= link_to("News Updates", news_updates_path) %></li>
|
||||
<li><%= link_to("Mascots", mascots_path) %></li>
|
||||
<li><%= link_to("Source Code", Danbooru.config.source_code_url) %></li>
|
||||
@ -35,7 +35,7 @@
|
||||
<li><%= link_to("DB Export", "/db_export/") %></li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><h1>Artists</h1></li>
|
||||
<li><h3>Artists</h3></li>
|
||||
<li><%= link_to("Listing", artists_path) %></li>
|
||||
<li><%= link_to("Avoid Posting Entries", avoid_postings_path) %></li>
|
||||
<li><%= link_to("Avoid Posting List", avoid_posting_static_path) %></li>
|
||||
@ -45,7 +45,7 @@
|
||||
</section>
|
||||
<section>
|
||||
<ul>
|
||||
<li><h1>Tags</h1></li>
|
||||
<li><h3>Tags</h3></li>
|
||||
<li><%= link_to("Listing", tags_path) %></li>
|
||||
<li><%= link_to("Aliases", tag_aliases_path) %></li>
|
||||
<li><%= link_to("Implications", tag_implications_path) %></li>
|
||||
@ -53,13 +53,13 @@
|
||||
<li><%= link_to("Help", help_page_path(id: "tags")) %></li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><h1>Notes</h1></li>
|
||||
<li><h3>Notes</h3></li>
|
||||
<li><%= link_to("Listing", notes_path) %></li>
|
||||
<li><%= link_to("Changes", note_versions_path) %></li>
|
||||
<li><%= link_to("Help", help_page_path(id: "notes")) %></li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><h1>Pools</h1></li>
|
||||
<li><h3>Pools</h3></li>
|
||||
<li><%= link_to("Listing", gallery_pools_path) %></li>
|
||||
<li><%= link_to("Changes", pool_versions_path) %></li>
|
||||
<li><%= link_to("Help", help_page_path(id: "pools")) %></li>
|
||||
@ -67,30 +67,30 @@
|
||||
</section>
|
||||
<section>
|
||||
<ul>
|
||||
<li><h1>Comments</h1></li>
|
||||
<li><h3>Comments</h3></li>
|
||||
<li><%= link_to("Listing", comments_path) %></li>
|
||||
<li><%= link_to("Help", help_page_path(id: "comments")) %></li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><h1>Forum</h1></li>
|
||||
<li><h3>Forum</h3></li>
|
||||
<li><%= link_to("Listing", forum_topics_path) %></li>
|
||||
<li><%= link_to("Help", help_page_path(id: "forum")) %></li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><h1>Wiki</h1></li>
|
||||
<li><h3>Wiki</h3></li>
|
||||
<li><%= link_to("Listing", wiki_pages_path) %></li>
|
||||
<li><%= link_to("Changes", wiki_page_versions_path) %></li>
|
||||
<li><%= link_to("Help", help_page_path(id: "wiki")) %></li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><h1>Blips</h1></li>
|
||||
<li><h3>Blips</h3></li>
|
||||
<li><%= link_to("Listing", blips_path) %></li>
|
||||
<li><%= link_to("Help", help_page_path(id: "blips")) %></li>
|
||||
</ul>
|
||||
</section>
|
||||
<section>
|
||||
<ul>
|
||||
<li><h1>Users</h1></li>
|
||||
<li><h3>Users</h3></li>
|
||||
<li><%= link_to("Listing", users_path) %></li>
|
||||
<li><%= link_to("Bans", bans_path) %></li>
|
||||
<% if CurrentUser.is_anonymous? %>
|
||||
@ -105,7 +105,7 @@
|
||||
<li><%= link_to("Help", help_page_path(id: "accounts")) %></li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><h1>Admin</h1></li>
|
||||
<li><h3>Admin</h3></li>
|
||||
<% if CurrentUser.is_moderator? %>
|
||||
<li><%= link_to("Mod Dashboard", moderator_dashboard_path) %></li>
|
||||
<% end %>
|
||||
|
@ -43,6 +43,12 @@
|
||||
<option value="true">Enabled</option>
|
||||
</select>
|
||||
|
||||
<label for="theme_forumnotif">Forum Activity Dot</label>
|
||||
<select id="theme_forumnotif">
|
||||
<option value="false">Disabled</option>
|
||||
<option value="true">Enabled</option>
|
||||
</select>
|
||||
|
||||
<h3>Accessibility</h3>
|
||||
<label for="theme_palette">Palette</label>
|
||||
<select id="theme_palette">
|
||||
|
@ -12,7 +12,13 @@
|
||||
<td><%= data_title %></td>
|
||||
<td><%= del(@stats[data_or_stats_key]) || data_or_stats_key %></td>
|
||||
<% if data_total_key %>
|
||||
<td class="stats-pct"><%= (@stats[data_or_stats_key].to_f / @stats[data_total_key] * 100).round %>%</td>
|
||||
<td class="stats-pct">
|
||||
<% if @stats[data_total_key] > 0 %>
|
||||
<%= (@stats[data_or_stats_key].to_f / @stats[data_total_key] * 100).round %>%
|
||||
<% else %>
|
||||
0%
|
||||
<% end %>
|
||||
</td>
|
||||
<% else %>
|
||||
<td></td>
|
||||
<% end %>
|
||||
|
56
db/fixes/123_convert_staffnote_to_deleted_feedback.rb
Executable file
56
db/fixes/123_convert_staffnote_to_deleted_feedback.rb
Executable file
@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env ruby
|
||||
# frozen_string_literal: true
|
||||
|
||||
require File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "config", "environment"))
|
||||
|
||||
destroyed_feedback_ids = []
|
||||
|
||||
CurrentUser.as_system do
|
||||
ModAction.where(action: "user_feedback_destroy")
|
||||
# On July 24, 2024, we deployed the ability to soft-delete feedback records.
|
||||
# We only care about restoring destroyed feedbacks that were destroyed before this date.
|
||||
# Any entries after this are "real" destructions, that do not need to be restored.
|
||||
.where("created_at < ?", CUTOFF_DATE = Date.new(2024, 8, 1))
|
||||
.find_in_batches(batch_size: 10_000) do |batch|
|
||||
feedback_data = batch.map do |mod_action|
|
||||
record_id = mod_action.values["record_id"].to_i
|
||||
destroyed_feedback_ids << record_id
|
||||
|
||||
{
|
||||
id: record_id,
|
||||
user_id: mod_action.values["user_id"].to_i,
|
||||
creator_id: User.system.id, # placeholder
|
||||
category: mod_action.values["type"],
|
||||
body: mod_action.values["reason"]&.strip,
|
||||
created_at: Date.new(1970, 1, 1), # placeholder
|
||||
updated_at: mod_action.created_at,
|
||||
updater_id: mod_action.creator_id,
|
||||
is_deleted: true,
|
||||
}
|
||||
end
|
||||
|
||||
UserFeedback.insert_all(feedback_data) if feedback_data.any?
|
||||
end
|
||||
end
|
||||
|
||||
CurrentUser.as_system do
|
||||
ModAction.where(action: "user_feedback_create")
|
||||
.where("values->>'record_id' IN (?)", destroyed_feedback_ids.map(&:to_s))
|
||||
.find_in_batches(batch_size: 10_000) do |batch|
|
||||
batch.each do |mod_action|
|
||||
record_id = mod_action.values["record_id"].to_i
|
||||
next unless destroyed_feedback_ids.include?(record_id)
|
||||
|
||||
UserFeedback.where(id: record_id).update_all(
|
||||
creator_id: mod_action.creator_id,
|
||||
created_at: mod_action.created_at,
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
StaffNote.where(creator: User.system)
|
||||
.where("body LIKE ?", "%deleted%feedback%")
|
||||
.find_in_batches(batch_size: 10_000) do |batch|
|
||||
StaffNote.where(id: batch.map(&:id)).delete_all
|
||||
end
|
@ -93,7 +93,7 @@ class UserFeedbacksControllerTest < ActionDispatch::IntegrationTest
|
||||
end
|
||||
|
||||
should "delete a feedback" do
|
||||
assert_difference({ "UserFeedback.count" => -1, "ModAction.count" => 2 }) do
|
||||
assert_difference({ "UserFeedback.count" => -1, "ModAction.count" => 1 }) do
|
||||
delete_auth user_feedback_path(@user_feedback), @critic
|
||||
end
|
||||
end
|
||||
@ -101,7 +101,7 @@ class UserFeedbacksControllerTest < ActionDispatch::IntegrationTest
|
||||
context "by a moderator" do
|
||||
should "allow destroying feedbacks they created" do
|
||||
as(@mod) { @user_feedback = create(:user_feedback, user: @user) }
|
||||
assert_difference({ "UserFeedback.count" => -1, "ModAction.count" => 2 }) do
|
||||
assert_difference({ "UserFeedback.count" => -1, "ModAction.count" => 1 }) do
|
||||
delete_auth user_feedback_path(@user_feedback), @mod
|
||||
end
|
||||
end
|
||||
@ -126,13 +126,13 @@ class UserFeedbacksControllerTest < ActionDispatch::IntegrationTest
|
||||
context "by an admin" do
|
||||
should "allow destroying feedbacks they created" do
|
||||
as(@admin) { @user_feedback = create(:user_feedback, user: @user) }
|
||||
assert_difference({ "UserFeedback.count" => -1, "ModAction.count" => 2 }) do
|
||||
assert_difference({ "UserFeedback.count" => -1, "ModAction.count" => 1 }) do
|
||||
delete_auth user_feedback_path(@user_feedback), @admin
|
||||
end
|
||||
end
|
||||
|
||||
should "allow destroying feedbacks they did not create" do
|
||||
assert_difference({ "UserFeedback.count" => -1, "ModAction.count" => 2 }) do
|
||||
assert_difference({ "UserFeedback.count" => -1, "ModAction.count" => 1 }) do
|
||||
delete_auth user_feedback_path(@user_feedback, format: :json), @admin
|
||||
end
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user