diff --git a/web/server/handlers.go b/web/server/handlers.go index 1ecc674..8015ea0 100644 --- a/web/server/handlers.go +++ b/web/server/handlers.go @@ -9,8 +9,17 @@ import ( func root(c *gin.Context) { authorized := c.GetBool("authorized") if authorized { - c.HTML(http.StatusOK, "quotes.html", nil) + c.Redirect(http.StatusSeeOther, "/quotes") } else { c.HTML(http.StatusOK, "auth.html", nil) } } + +func quotes(c *gin.Context) { + authorized := c.GetBool("authorized") + if authorized { + c.HTML(http.StatusOK, "quotes.html", nil) + } else { + c.Redirect(http.StatusSeeOther, "/") + } +} diff --git a/web/server/server.go b/web/server/server.go index 712058a..c2836b4 100644 --- a/web/server/server.go +++ b/web/server/server.go @@ -20,6 +20,7 @@ func Serve(addr string) { r.Static("/static", "./static") r.GET("/", api.MiddlewareAuth, root) + r.GET("/quotes", api.MiddlewareAuth, quotes) r.Run(addr) } diff --git a/web/static/css/skazanull.css b/web/static/css/skazanull.css new file mode 100644 index 0000000..a8b5116 --- /dev/null +++ b/web/static/css/skazanull.css @@ -0,0 +1,5 @@ +.loader { + display: block; + margin: 0 auto; + max-width: 20%; +} diff --git a/web/static/images/loader.gif b/web/static/images/loader.gif new file mode 100644 index 0000000..d15dcdb Binary files /dev/null and b/web/static/images/loader.gif differ diff --git a/web/static/js/quotes.js b/web/static/js/quotes.js new file mode 100644 index 0000000..d0b677f --- /dev/null +++ b/web/static/js/quotes.js @@ -0,0 +1,161 @@ +const PAGE_SIZE = 10; +var totalPages; +var currPage = +sessionStorage.getItem("page"); +if (currPage == 0) { + currPage = 1; +} +var search = sessionStorage.getItem("search"); +if (search == null) { + search = ""; +} +var sorting = sessionStorage.getItem("sort"); +if (sorting == null) { + sorting = "-datetime"; +} + +function escapedString(str) { + return str + .replace("&", "&") + .replace("<", "<") + .replace(">", ">") + .replace("\n", "
"); +} + +function renderBlockQuote(quote) { + return ` +
+
+
+

${escapedString(quote.text)}

+

${escapedString(quote.author)}

+

${quote.datetime}

+
+
+ + +
+
+
+ `; +} + +function load() { + var quotesCount; + failed = false; + $.ajax({ + async: false, + url: "/api/quotes/count", + type: "GET", + dataType: "json", + success: function (resp) { + quotesCount = resp.count; + }, + error: function (err) { + $("#error-message").text(err.responseJSON.error); + $("#error").removeClass("hidden"); + failed = true; + $("#block-quotes-loader").addClass("hidden"); + }, + }); + if (failed) { + return; + } + totalPages = Math.ceil(quotesCount / PAGE_SIZE); + $("#input-search").val(search); + $("#input-sorting").val(sorting); + $("#btn-page-curr").text(currPage); + if (currPage > 1) { + $("#btn-page-first").removeClass("hidden"); + if (currPage > 2) { + $("#btn-page-prev").text(currPage - 1); + $("#btn-page-prev").removeClass("hidden"); + if (currPage > 3) { + $("#pages-prev").removeClass("hidden"); + } + } + } + if (currPage < totalPages) { + $("#btn-page-last").text(totalPages); + $("#btn-page-last").removeClass("hidden"); + if (currPage < totalPages - 1) { + $("#btn-page-next").text(currPage + 1); + $("#btn-page-next").removeClass("hidden"); + if (currPage < totalPages - 2) { + $("#pages-next").removeClass("hidden"); + } + } + } + container = $("#block-quotes"); + $.ajax({ + url: `/api/quotes?filter=${encodeURIComponent(search)}&sort=${encodeURIComponent(sorting)}&limit=${PAGE_SIZE}&offset=${(currPage - 1)*PAGE_SIZE}`, + type: "GET", + dataType: "json", + success: function (resp) { + resp.forEach((quote) => { + container.append(renderBlockQuote(quote)); + }); + }, + error: function (err) { + $("#error-message").text(err.responseJSON.error); + $("#error").removeClass("hidden"); + }, + complete: function () { + $("#block-quotes-loader").addClass("hidden"); + }, + }); +} + +function reload() { + container = $("#block-quotes"); + loader = $("#block-quotes-loader"); + loader.removeClass("hidden"); + container.html(loader); + $("#error").addClass("hidden"); + $("#btn-page-first").addClass("hidden"); + $("#pages-prev").addClass("hidden"); + $("#btn-page-prev").addClass("hidden"); + $("#btn-page-next").addClass("hidden"); + $("#pages-next").addClass("hidden"); + $("#btn-page-last").addClass("hidden"); + load(); +} + +$(window).on("load", function (e) { + load(); +}); + +$(document).on("click", "#btn-refresh", function (e) { + search = $("#input-search").val(); + sorting = $("#input-sorting option:selected").val(); + reload(); + sessionStorage.setItem("search", search); + sessionStorage.setItem("sort", sorting); +}); + +$(document).on("click", "#btn-page-first", function (e) { + currPage = 1; + reload(); + sessionStorage.setItem("page", currPage); +}); + +$(document).on("click", "#btn-page-prev", function (e) { + currPage--; + reload(); + sessionStorage.setItem("page", currPage); +}); + +$(document).on("click", "#btn-page-next", function (e) { + currPage++; + reload(); + sessionStorage.setItem("page", currPage); +}); + +$(document).on("click", "#btn-page-last", function (e) { + currPage = totalPages; + reload(); + sessionStorage.setItem("page", currPage); +}); diff --git a/web/templates/head.html b/web/templates/head.html index f023714..5c86c5d 100644 --- a/web/templates/head.html +++ b/web/templates/head.html @@ -4,6 +4,7 @@ + diff --git a/web/templates/quotes.html b/web/templates/quotes.html new file mode 100644 index 0000000..ffb0d8b --- /dev/null +++ b/web/templates/quotes.html @@ -0,0 +1,62 @@ + + + + + {{ template "head" . }} + Цитаты | SkazaNull + + + +
+
+ +

Пацанские цитаты

+

Читайте и угорайте :)

+
+ +
+
+ + + +
+ +
+
+ Loading... +
+
+ + + + + + + +
+
+

+ + © Masahiko AMANO (H1K0), 2025—present + +

+
+
+ + + +