summaryrefslogtreecommitdiff
diff refs
from: back
to: back
| flip
diff options
context:
space:
mode:
-rw-r--r--internal/factgiver/factgiver.go14
-rw-r--r--internal/router/api-v1-blog-search.go13
-rw-r--r--internal/router/api-v1-general-page-body.go26
-rw-r--r--internal/router/api-v1-general-page-bottom-embeds.go25
-rw-r--r--internal/router/api-v1-general-page-footer.go25
-rw-r--r--internal/router/api-v1-general-page-header.go26
-rw-r--r--internal/router/api-v1-general-page-top-embeds.go25
-rw-r--r--internal/router/api-v1-general-page.go23
-rw-r--r--internal/router/lang-blog-title.go13
-rw-r--r--internal/router/lang-blog.go12
-rw-r--r--internal/router/lang-map.go13
-rw-r--r--main.go6
-rw-r--r--static/input.css11
-rw-r--r--views/layouts/general-page.html53
-rw-r--r--views/pages/blog-catalogue.html20
-rw-r--r--views/pages/blog-page.html2
-rw-r--r--views/pages/global-map.html29
-rw-r--r--views/pages/home-page.html11
-rw-r--r--views/pages/language-pick.html16
-rw-r--r--views/partials/general-page-header.html8
20 files changed, 248 insertions, 123 deletions
diff --git a/internal/factgiver/factgiver.go b/internal/factgiver/factgiver.go
index 6f77403..5b418ee 100644
--- a/internal/factgiver/factgiver.go
+++ b/internal/factgiver/factgiver.go
@@ -14,13 +14,13 @@ import (
type FactGiver struct {
b2Client *b2.B2Client
cache map[string][]string
- langs []string
+ langs []config.AvailableLanguageConfig
factsFileName string
nlRe *regexp.Regexp
randGen *rand.Rand
}
-func NewFactGiver(cfg *config.FactGiverConfig, langs []string) (*FactGiver, error) {
+func NewFactGiver(cfg *config.FactGiverConfig, langs []config.AvailableLanguageConfig) (*FactGiver, error) {
b2Client, err := b2.NewB2Client(&cfg.Storage.Config)
if err != nil {
return nil, fmt.Errorf("fail to init b2 client for a new fact giver: %s", err.Error())
@@ -52,15 +52,15 @@ func (g *FactGiver) Give(lang string) [3]string {
func (g *FactGiver) initCache() error {
for _, lang := range g.langs {
- localFacts := strings.Replace(g.factsFileName, "*", lang, 1)
+ localFacts := strings.Replace(g.factsFileName, "*", lang.Name, 1)
factsContentBytes, err := g.b2Client.ReadAll(localFacts)
if err != nil {
- return fmt.Errorf("fail to read '%s' facts file: %s", lang, err.Error())
+ return fmt.Errorf("fail to read '%s' facts file: %s", lang.Name, err.Error())
}
factsContent := string(factsContentBytes)
- g.cache[lang] = g.nlRe.Split(factsContent, -1)
- if g.cache[lang][len(g.cache[lang])-1] == "" {
- g.cache[lang] = g.cache[lang][:len(g.cache[lang])-1]
+ g.cache[lang.Name] = g.nlRe.Split(factsContent, -1)
+ if g.cache[lang.Name][len(g.cache[lang.Name])-1] == "" {
+ g.cache[lang.Name] = g.cache[lang.Name][:len(g.cache[lang.Name])-1]
}
}
return nil
diff --git a/internal/router/api-v1-blog-search.go b/internal/router/api-v1-blog-search.go
index 69be651..ab5425c 100644
--- a/internal/router/api-v1-blog-search.go
+++ b/internal/router/api-v1-blog-search.go
@@ -10,6 +10,7 @@ import (
"strings"
"time"
+ "github.com/SayaAndy/saya-today-web/config"
"github.com/SayaAndy/saya-today-web/internal/b2"
"github.com/SayaAndy/saya-today-web/locale"
"github.com/gofiber/fiber/v2"
@@ -19,17 +20,21 @@ func init() {
tm.Add("catalogue-blog-cards", "views/partials/catalogue-blog-cards.html", "views/partials/catalogue-blog-card-tags.html")
}
-func Api_V1_BlogSearch(l map[string]*locale.LocaleConfig, langs []string, b2Client *b2.B2Client) func(c *fiber.Ctx) error {
+func Api_V1_BlogSearch(l map[string]*locale.LocaleConfig, langs []config.AvailableLanguageConfig, b2Client *b2.B2Client) func(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error {
sort := c.Query("sort")
lang := c.Query("lang")
tz := c.Query("tz")
- if !slices.Contains(langs, lang) {
- c.Set(fiber.HeaderContentType, fiber.MIMETextPlainCharsetUTF8)
- return c.Status(fiber.ErrNotFound.Code).SendString(fmt.Sprintf("server does not support '%s' language", lang))
+ for _, availableLang := range langs {
+ if availableLang.Name == lang {
+ goto langIsAvailable
+ }
}
+ c.Set(fiber.HeaderContentType, fiber.MIMETextPlainCharsetUTF8)
+ return c.Status(fiber.ErrNotFound.Code).SendString(fmt.Sprintf("server does not support '%s' language", lang))
+ langIsAvailable:
loc, err := time.LoadLocation(tz)
if err != nil {
loc = time.UTC
diff --git a/internal/router/api-v1-general-page-body.go b/internal/router/api-v1-general-page-body.go
index c1a4a9f..fe21957 100644
--- a/internal/router/api-v1-general-page-body.go
+++ b/internal/router/api-v1-general-page-body.go
@@ -11,6 +11,7 @@ import (
"strings"
"time"
+ "github.com/SayaAndy/saya-today-web/config"
"github.com/SayaAndy/saya-today-web/internal/b2"
"github.com/SayaAndy/saya-today-web/internal/factgiver"
"github.com/SayaAndy/saya-today-web/locale"
@@ -24,7 +25,7 @@ func init() {
tm.Add("general-page-body", "views/partials/general-page-body.html")
}
-func Api_V1_GeneralPage_Body(l map[string]*locale.LocaleConfig, langs []string, b2Client *b2.B2Client, md goldmark.Markdown) func(c *fiber.Ctx) error {
+func Api_V1_GeneralPage_Body(l map[string]*locale.LocaleConfig, langs []config.AvailableLanguageConfig, b2Client *b2.B2Client, md goldmark.Markdown) func(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error {
c.Set(fiber.HeaderContentType, fiber.MIMETextPlainCharsetUTF8)
@@ -45,19 +46,26 @@ func Api_V1_GeneralPage_Body(l map[string]*locale.LocaleConfig, langs []string,
return c.Status(fiber.StatusOK).Type("html").Send(val)
}
+ lang := ""
pathParts := strings.Split(strings.Trim(path, "/"), "/")
- if len(pathParts) == 0 {
- return c.Status(fiber.ErrBadRequest.Code).SendString("'Referer' header is invalid: expect format '/{lang}/...'")
+ if len(pathParts) == 1 && pathParts[0] == "" {
+ pathParts = []string{}
}
-
- lang := pathParts[0]
- if !slices.Contains(langs, lang) {
- return c.Status(fiber.ErrNotFound.Code).SendString(fmt.Sprintf("server does not support '%s' language... yet??", lang))
+ if len(pathParts) > 0 {
+ lang = pathParts[0]
+ for _, availableLang := range langs {
+ if availableLang.Name == lang {
+ goto langIsAvailable
+ }
+ }
+ return c.Status(fiber.ErrBadRequest.Code).SendString("'Referer' header is invalid: expect format '/{lang}/...'")
}
+ langIsAvailable:
values := fiber.Map{
"L": l[lang],
"Lang": lang,
+ "Path": strings.Trim(path, "/"),
"QueryString": string(c.Request().URI().QueryString()),
}
var additionalTemplates []string
@@ -149,6 +157,10 @@ func Api_V1_GeneralPage_Body(l map[string]*locale.LocaleConfig, langs []string,
values["GifName"] = fmt.Sprintf("otter-%d.gif", rand.Int()%3+1)
values["FunFacts"] = FactGiver.Give(lang)
additionalTemplates = append(additionalTemplates, "views/pages/home-page.html")
+ } else if len(pathParts) == 0 {
+ values["Title"] = "Choose Your Language"
+ values["AvailableLanguages"] = langs
+ additionalTemplates = append(additionalTemplates, "views/pages/language-pick.html")
}
content, err := tm.Render("general-page-body", values, additionalTemplates...)
diff --git a/internal/router/api-v1-general-page-bottom-embeds.go b/internal/router/api-v1-general-page-bottom-embeds.go
index c4d9543..0a2030f 100644
--- a/internal/router/api-v1-general-page-bottom-embeds.go
+++ b/internal/router/api-v1-general-page-bottom-embeds.go
@@ -4,10 +4,10 @@ import (
"fmt"
"log/slog"
"net/url"
- "slices"
"strings"
"time"
+ "github.com/SayaAndy/saya-today-web/config"
"github.com/SayaAndy/saya-today-web/internal/b2"
"github.com/SayaAndy/saya-today-web/locale"
"github.com/gofiber/fiber/v2"
@@ -17,7 +17,7 @@ func init() {
tm.Add("general-page-bottom-embeds", "views/partials/general-page-bottom-embeds.html")
}
-func Api_V1_GeneralPage_BottomEmbeds(l map[string]*locale.LocaleConfig, langs []string, b2Client *b2.B2Client) func(c *fiber.Ctx) error {
+func Api_V1_GeneralPage_BottomEmbeds(l map[string]*locale.LocaleConfig, langs []config.AvailableLanguageConfig, b2Client *b2.B2Client) func(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error {
c.Set(fiber.HeaderContentType, fiber.MIMETextPlainCharsetUTF8)
@@ -37,19 +37,26 @@ func Api_V1_GeneralPage_BottomEmbeds(l map[string]*locale.LocaleConfig, langs []
return c.Status(fiber.StatusOK).Type("html").Send(val)
}
+ lang := ""
pathParts := strings.Split(strings.Trim(path, "/"), "/")
- if len(pathParts) == 0 {
- return c.Status(fiber.ErrBadRequest.Code).SendString("'Referer' header is invalid: expect format '/{lang}/...'")
+ if len(pathParts) == 1 && pathParts[0] == "" {
+ pathParts = []string{}
}
-
- lang := pathParts[0]
- if !slices.Contains(langs, lang) {
- return c.Status(fiber.ErrNotFound.Code).SendString(fmt.Sprintf("server does not support '%s' language... yet??", lang))
+ if len(pathParts) > 0 {
+ lang = pathParts[0]
+ for _, availableLang := range langs {
+ if availableLang.Name == lang {
+ goto langIsAvailable
+ }
+ }
+ return c.Status(fiber.ErrBadRequest.Code).SendString("'Referer' header is invalid: expect format '/{lang}/...'")
}
+ langIsAvailable:
values := fiber.Map{
"L": l[lang],
"Lang": lang,
+ "Path": strings.Trim(path, "/"),
"QueryString": string(c.Request().URI().QueryString()),
}
var additionalTemplates []string
@@ -60,6 +67,8 @@ func Api_V1_GeneralPage_BottomEmbeds(l map[string]*locale.LocaleConfig, langs []
additionalTemplates = append(additionalTemplates, "views/pages/blog-page.html")
} else if len(pathParts) == 1 {
additionalTemplates = append(additionalTemplates, "views/pages/home-page.html")
+ } else if len(pathParts) == 0 {
+ additionalTemplates = append(additionalTemplates, "views/pages/language-pick.html")
}
content, err := tm.Render("general-page-bottom-embeds", values, additionalTemplates...)
diff --git a/internal/router/api-v1-general-page-footer.go b/internal/router/api-v1-general-page-footer.go
index 003f54c..2030b3b 100644
--- a/internal/router/api-v1-general-page-footer.go
+++ b/internal/router/api-v1-general-page-footer.go
@@ -4,10 +4,10 @@ import (
"fmt"
"log/slog"
"net/url"
- "slices"
"strings"
"time"
+ "github.com/SayaAndy/saya-today-web/config"
"github.com/SayaAndy/saya-today-web/locale"
"github.com/gofiber/fiber/v2"
)
@@ -16,7 +16,7 @@ func init() {
tm.Add("general-page-footer", "views/partials/general-page-footer.html")
}
-func Api_V1_GeneralPage_Footer(l map[string]*locale.LocaleConfig, langs []string) func(c *fiber.Ctx) error {
+func Api_V1_GeneralPage_Footer(l map[string]*locale.LocaleConfig, langs []config.AvailableLanguageConfig) func(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error {
c.Set(fiber.HeaderContentType, fiber.MIMETextPlainCharsetUTF8)
@@ -37,19 +37,26 @@ func Api_V1_GeneralPage_Footer(l map[string]*locale.LocaleConfig, langs []string
return c.Status(fiber.StatusOK).Type("html").Send(val)
}
+ lang := ""
pathParts := strings.Split(strings.Trim(path, "/"), "/")
- if len(pathParts) == 0 {
- return c.Status(fiber.ErrBadRequest.Code).SendString("'Referer' header is invalid: expect format '/{lang}/...'")
+ if len(pathParts) == 1 && pathParts[0] == "" {
+ pathParts = []string{}
}
-
- lang := pathParts[0]
- if !slices.Contains(langs, lang) {
- return c.Status(fiber.ErrNotFound.Code).SendString(fmt.Sprintf("server does not support '%s' language... yet??", lang))
+ if len(pathParts) > 0 {
+ lang = pathParts[0]
+ for _, availableLang := range langs {
+ if availableLang.Name == lang {
+ goto langIsAvailable
+ }
+ }
+ return c.Status(fiber.ErrBadRequest.Code).SendString("'Referer' header is invalid: expect format '/{lang}/...'")
}
+ langIsAvailable:
values := fiber.Map{
"L": l[lang],
"Lang": lang,
+ "Path": strings.Trim(path, "/"),
"QueryString": string(c.Request().URI().QueryString()),
}
var additionalTemplates []string
@@ -60,6 +67,8 @@ func Api_V1_GeneralPage_Footer(l map[string]*locale.LocaleConfig, langs []string
additionalTemplates = append(additionalTemplates, "views/pages/blog-page.html")
} else if len(pathParts) == 1 {
additionalTemplates = append(additionalTemplates, "views/pages/home-page.html")
+ } else if len(pathParts) == 0 {
+ additionalTemplates = append(additionalTemplates, "views/pages/language-pick.html")
}
content, err := tm.Render("general-page-footer", values, additionalTemplates...)
diff --git a/internal/router/api-v1-general-page-header.go b/internal/router/api-v1-general-page-header.go
index 80228f7..a2c832b 100644
--- a/internal/router/api-v1-general-page-header.go
+++ b/internal/router/api-v1-general-page-header.go
@@ -4,10 +4,10 @@ import (
"fmt"
"log/slog"
"net/url"
- "slices"
"strings"
"time"
+ "github.com/SayaAndy/saya-today-web/config"
"github.com/SayaAndy/saya-today-web/internal/b2"
"github.com/SayaAndy/saya-today-web/locale"
"github.com/gofiber/fiber/v2"
@@ -17,7 +17,7 @@ func init() {
tm.Add("general-page-header", "views/partials/general-page-header.html")
}
-func Api_V1_GeneralPage_Header(l map[string]*locale.LocaleConfig, langs []string, b2Client *b2.B2Client) func(c *fiber.Ctx) error {
+func Api_V1_GeneralPage_Header(l map[string]*locale.LocaleConfig, langs []config.AvailableLanguageConfig, b2Client *b2.B2Client) func(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error {
c.Set(fiber.HeaderContentType, fiber.MIMETextPlainCharsetUTF8)
@@ -38,19 +38,26 @@ func Api_V1_GeneralPage_Header(l map[string]*locale.LocaleConfig, langs []string
return c.Status(fiber.StatusOK).Type("html").Send(val)
}
+ lang := ""
pathParts := strings.Split(strings.Trim(path, "/"), "/")
- if len(pathParts) == 0 {
- return c.Status(fiber.ErrBadRequest.Code).SendString("'Referer' header is invalid: expect format '/{lang}/...'")
+ if len(pathParts) == 1 && pathParts[0] == "" {
+ pathParts = []string{}
}
-
- lang := pathParts[0]
- if !slices.Contains(langs, lang) {
- return c.Status(fiber.ErrNotFound.Code).SendString(fmt.Sprintf("server does not support '%s' language... yet??", lang))
+ if len(pathParts) > 0 {
+ lang = pathParts[0]
+ for _, availableLang := range langs {
+ if availableLang.Name == lang {
+ goto langIsAvailable
+ }
+ }
+ return c.Status(fiber.ErrBadRequest.Code).SendString("'Referer' header is invalid: expect format '/{lang}/...'")
}
+ langIsAvailable:
values := fiber.Map{
"L": l[lang],
"Lang": lang,
+ "Path": strings.Trim(path, "/"),
"QueryString": string(c.Request().URI().QueryString()),
}
var additionalTemplates []string
@@ -70,6 +77,9 @@ func Api_V1_GeneralPage_Header(l map[string]*locale.LocaleConfig, langs []string
} else if len(pathParts) == 1 {
values["Title"] = l[lang].HomePage.Header
additionalTemplates = append(additionalTemplates, "views/pages/home-page.html")
+ } else if len(pathParts) == 0 {
+ values["Title"] = "Choose Your Language"
+ additionalTemplates = append(additionalTemplates, "views/pages/language-pick.html")
}
content, err := tm.Render("general-page-header", values, additionalTemplates...)
diff --git a/internal/router/api-v1-general-page-top-embeds.go b/internal/router/api-v1-general-page-top-embeds.go
index 78021b2..544e3a4 100644
--- a/internal/router/api-v1-general-page-top-embeds.go
+++ b/internal/router/api-v1-general-page-top-embeds.go
@@ -4,10 +4,10 @@ import (
"fmt"
"log/slog"
"net/url"
- "slices"
"strings"
"time"
+ "github.com/SayaAndy/saya-today-web/config"
"github.com/SayaAndy/saya-today-web/locale"
"github.com/gofiber/fiber/v2"
)
@@ -16,7 +16,7 @@ func init() {
tm.Add("general-page-top-embeds", "views/partials/general-page-top-embeds.html")
}
-func Api_V1_GeneralPage_TopEmbeds(l map[string]*locale.LocaleConfig, langs []string) func(c *fiber.Ctx) error {
+func Api_V1_GeneralPage_TopEmbeds(l map[string]*locale.LocaleConfig, langs []config.AvailableLanguageConfig) func(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error {
c.Set(fiber.HeaderContentType, fiber.MIMETextPlainCharsetUTF8)
@@ -37,19 +37,26 @@ func Api_V1_GeneralPage_TopEmbeds(l map[string]*locale.LocaleConfig, langs []str
return c.Status(fiber.StatusOK).Type("html").Send(val)
}
+ lang := ""
pathParts := strings.Split(strings.Trim(path, "/"), "/")
- if len(pathParts) == 0 {
- return c.Status(fiber.ErrBadRequest.Code).SendString("'Referer' header is invalid: expect format '/{lang}/...'")
+ if len(pathParts) == 1 && pathParts[0] == "" {
+ pathParts = []string{}
}
-
- lang := pathParts[0]
- if !slices.Contains(langs, lang) {
- return c.Status(fiber.ErrNotFound.Code).SendString(fmt.Sprintf("server does not support '%s' language... yet??", lang))
+ if len(pathParts) > 0 {
+ lang = pathParts[0]
+ for _, availableLang := range langs {
+ if availableLang.Name == lang {
+ goto langIsAvailable
+ }
+ }
+ return c.Status(fiber.ErrBadRequest.Code).SendString("'Referer' header is invalid: expect format '/{lang}/...'")
}
+ langIsAvailable:
values := fiber.Map{
"L": l[lang],
"Lang": lang,
+ "Path": strings.Trim(path, "/"),
"QueryString": string(c.Request().URI().QueryString()),
}
var additionalTemplates []string
@@ -60,6 +67,8 @@ func Api_V1_GeneralPage_TopEmbeds(l map[string]*locale.LocaleConfig, langs []str
additionalTemplates = append(additionalTemplates, "views/pages/blog-page.html")
} else if len(pathParts) == 1 {
additionalTemplates = append(additionalTemplates, "views/pages/home-page.html")
+ } else if len(pathParts) == 0 {
+ additionalTemplates = append(additionalTemplates, "views/pages/language-pick.html")
}
content, err := tm.Render("general-page-top-embeds", values, additionalTemplates...)
diff --git a/internal/router/api-v1-general-page.go b/internal/router/api-v1-general-page.go
index d0ea559..a77fc5e 100644
--- a/internal/router/api-v1-general-page.go
+++ b/internal/router/api-v1-general-page.go
@@ -1,11 +1,10 @@
package router
import (
- "fmt"
"log/slog"
- "slices"
"strings"
+ "github.com/SayaAndy/saya-today-web/config"
"github.com/SayaAndy/saya-today-web/locale"
"github.com/gofiber/fiber/v2"
)
@@ -14,21 +13,27 @@ func init() {
tm.Add("general-page", "views/layouts/general-page.html")
}
-func Api_V1_GeneralPage(l map[string]*locale.LocaleConfig, langs []string) func(c *fiber.Ctx) error {
+func Api_V1_GeneralPage(l map[string]*locale.LocaleConfig, langs []config.AvailableLanguageConfig) func(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error {
c.Set(fiber.HeaderContentType, fiber.MIMETextPlainCharsetUTF8)
path := c.Path()
+ lang := ""
pathParts := strings.Split(strings.Trim(path, "/"), "/")
- if len(pathParts) == 0 {
- return c.Status(fiber.ErrBadRequest.Code).SendString("url path is invalid: expect format '/{lang}/...'")
+ if len(pathParts) == 1 && pathParts[0] == "" {
+ pathParts = []string{}
}
-
- lang := pathParts[0]
- if !slices.Contains(langs, lang) {
- return c.Status(fiber.ErrNotFound.Code).SendString(fmt.Sprintf("server does not support '%s' language... yet??", lang))
+ if len(pathParts) > 0 {
+ lang = pathParts[0]
+ for _, availableLang := range langs {
+ if availableLang.Name == lang {
+ goto langIsAvailable
+ }
+ }
+ return c.Status(fiber.ErrBadRequest.Code).SendString("'Referer' header is invalid: expect format '/{lang}/...'")
}
+ langIsAvailable:
cacheKey := "general-page." + lang
if val, ok := PCache.Get(cacheKey); val != nil && ok {
c.Set(fiber.HeaderContentType, fiber.MIMETextHTMLCharsetUTF8)
diff --git a/internal/router/lang-blog-title.go b/internal/router/lang-blog-title.go
index d6ca917..6e80671 100644
--- a/internal/router/lang-blog-title.go
+++ b/internal/router/lang-blog-title.go
@@ -5,10 +5,10 @@ import (
"fmt"
"html/template"
"log/slog"
- "slices"
"strconv"
"strings"
+ "github.com/SayaAndy/saya-today-web/config"
"github.com/SayaAndy/saya-today-web/internal/b2"
"github.com/SayaAndy/saya-today-web/internal/frontmatter"
"github.com/SayaAndy/saya-today-web/locale"
@@ -20,17 +20,20 @@ func init() {
tm.Add("blog-page", "views/layouts/general-page.html", "views/pages/blog-page.html")
}
-func Lang_Blog_Title(l map[string]*locale.LocaleConfig, langs []string, b2Client *b2.B2Client, md goldmark.Markdown) func(c *fiber.Ctx) error {
+func Lang_Blog_Title(l map[string]*locale.LocaleConfig, langs []config.AvailableLanguageConfig, b2Client *b2.B2Client, md goldmark.Markdown) func(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error {
ip := c.IP()
slog.Debug("client entering blog page", slog.String("ip", ip), slog.String("page", c.Path()))
lang := c.Params("lang")
- if !slices.Contains(langs, lang) {
- c.Set(fiber.HeaderContentType, fiber.MIMETextPlainCharsetUTF8)
- return c.Status(fiber.ErrNotFound.Code).SendString(fmt.Sprintf("server does not support '%s' language... yet??", lang))
+ for _, availableLang := range langs {
+ if availableLang.Name == lang {
+ goto langIsAvailable
+ }
}
+ return c.Status(fiber.ErrNotFound.Code).SendString(fmt.Sprintf("server does not support '%s' language", lang))
+ langIsAvailable:
metadata, parsedMarkdown, err := readBlogPost(md, b2Client, lang+"/"+c.Params("title"))
if err != nil {
c.Set(fiber.HeaderContentType, fiber.MIMETextPlainCharsetUTF8)
diff --git a/internal/router/lang-blog.go b/internal/router/lang-blog.go
index 38a6597..960ac3d 100644
--- a/internal/router/lang-blog.go
+++ b/internal/router/lang-blog.go
@@ -8,6 +8,7 @@ import (
"slices"
"strings"
+ "github.com/SayaAndy/saya-today-web/config"
"github.com/SayaAndy/saya-today-web/internal/b2"
"github.com/SayaAndy/saya-today-web/locale"
"github.com/gofiber/fiber/v2"
@@ -17,14 +18,17 @@ func init() {
tm.Add("blog-catalogue", "views/layouts/general-page.html", "views/pages/blog-catalogue.html")
}
-func Lang_Blog(l map[string]*locale.LocaleConfig, langs []string, b2Client *b2.B2Client) func(c *fiber.Ctx) error {
+func Lang_Blog(l map[string]*locale.LocaleConfig, langs []config.AvailableLanguageConfig, b2Client *b2.B2Client) func(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error {
lang := c.Params("lang")
- if !slices.Contains(langs, lang) {
- c.Set(fiber.HeaderContentType, fiber.MIMETextPlainCharsetUTF8)
- return c.Status(fiber.ErrNotFound.Code).SendString(fmt.Sprintf("server does not support '%s' language... yet??", lang))
+ for _, availableLang := range langs {
+ if availableLang.Name == lang {
+ goto langIsAvailable
+ }
}
+ return c.Status(fiber.ErrNotFound.Code).SendString(fmt.Sprintf("server does not support '%s' language", lang))
+ langIsAvailable:
querySort := c.Query("sort")
if querySort == "" {
querySort = "publicationDateDesc"
diff --git a/internal/router/lang-map.go b/internal/router/lang-map.go
index e94d756..a744f02 100644
--- a/internal/router/lang-map.go
+++ b/internal/router/lang-map.go
@@ -3,10 +3,10 @@ package router
import (
"fmt"
"log/slog"
- "slices"
"strconv"
"strings"
+ "github.com/SayaAndy/saya-today-web/config"
"github.com/SayaAndy/saya-today-web/internal/b2"
"github.com/SayaAndy/saya-today-web/locale"
"github.com/gofiber/fiber/v2"
@@ -16,14 +16,17 @@ func init() {
tm.Add("global-map", "views/pages/global-map.html")
}
-func Lang_Map(l map[string]*locale.LocaleConfig, langs []string, b2Client *b2.B2Client) func(c *fiber.Ctx) error {
+func Lang_Map(l map[string]*locale.LocaleConfig, langs []config.AvailableLanguageConfig, b2Client *b2.B2Client) func(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error {
lang := c.Params("lang")
- if !slices.Contains(langs, lang) {
- c.Set(fiber.HeaderContentType, fiber.MIMETextPlainCharsetUTF8)
- return c.Status(fiber.ErrNotFound.Code).SendString(fmt.Sprintf("server does not support '%s' language... yet??", lang))
+ for _, availableLang := range langs {
+ if availableLang.Name == lang {
+ goto langIsAvailable
+ }
}
+ return c.Status(fiber.ErrNotFound.Code).SendString(fmt.Sprintf("server does not support '%s' language", lang))
+ langIsAvailable:
pages, err := b2Client.Scan(lang + "/")
status := fiber.StatusOK
if err != nil {
diff --git a/main.go b/main.go
index a6a30b0..39fa0ab 100644
--- a/main.go
+++ b/main.go
@@ -52,7 +52,7 @@ var (
)
b2Client *b2.B2Client
configPath = flag.String("c", "config.yaml", "Path to the configuration file (in YAML format)")
- availableLanguages = make([]string, 0)
+ availableLanguages = make([]config.AvailableLanguageConfig, 0)
localization = make(map[string]*locale.LocaleConfig)
)
@@ -108,7 +108,7 @@ func main() {
slog.Warn("fail to initialize a locale", slog.String("locale", lang.Name), slog.String("error", err.Error()))
continue
}
- availableLanguages = append(availableLanguages, lang.Name)
+ availableLanguages = append(availableLanguages, lang)
localization[lang.Name] = localeCfg
}
@@ -144,7 +144,7 @@ func main() {
os.Exit(1)
}
- app.Get("/", router.Root(cfg.AvailableLanguages))
+ app.Get("/", router.Api_V1_GeneralPage(localization, availableLanguages))
app.Get("/:lang<len(2)>", router.Api_V1_GeneralPage(localization, availableLanguages))
app.Get("/:lang/map", router.Lang_Map(localization, availableLanguages, b2Client))
app.Get("/:lang/blog", router.Api_V1_GeneralPage(localization, availableLanguages))
diff --git a/static/input.css b/static/input.css
index 6e5cf3f..eae6620 100644
--- a/static/input.css
+++ b/static/input.css
@@ -9,6 +9,7 @@
html {
font-size: 12px;
+ --noise-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAMAAAAp4XiDAAAAUVBMVEWFhYWDg4N3d3dtbW17e3t1dXWBgYGHh4d5eXlzc3OLi4ubm5uVlZWPj4+NjY19fX2JiYl/f39ra2uRkZGZmZlpaWmXl5dvb29xcXGTk5NnZ2c8TV1mAAAAG3RSTlNAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAvEOwtAAAFVklEQVR4XpWWB67c2BUFb3g557T/hRo9/WUMZHlgr4Bg8Z4qQgQJlHI4A8SzFVrapvmTF9O7dmYRFZ60YiBhJRCgh1FYhiLAmdvX0CzTOpNE77ME0Zty/nWWzchDtiqrmQDeuv3powQ5ta2eN0FY0InkqDD73lT9c9lEzwUNqgFHs9VQce3TVClFCQrSTfOiYkVJQBmpbq2L6iZavPnAPcoU0dSw0SUTqz/GtrGuXfbyyBniKykOWQWGqwwMA7QiYAxi+IlPdqo+hYHnUt5ZPfnsHJyNiDtnpJyayNBkF6cWoYGAMY92U2hXHF/C1M8uP/ZtYdiuj26UdAdQQSXQErwSOMzt/XWRWAz5GuSBIkwG1H3FabJ2OsUOUhGC6tK4EMtJO0ttC6IBD3kM0ve0tJwMdSfjZo+EEISaeTr9P3wYrGjXqyC1krcKdhMpxEnt5JetoulscpyzhXN5FRpuPHvbeQaKxFAEB6EN+cYN6xD7RYGpXpNndMmZgM5Dcs3YSNFDHUo2LGfZuukSWyUYirJAdYbF3MfqEKmjM+I2EfhA94iG3L7uKrR+GdWD73ydlIB+6hgref1QTlmgmbM3/LeX5GI1Ux1RWpgxpLuZ2+I+IjzZ8wqE4nilvQdkUdfhzI5QDWy+kw5Wgg2pGpeEVeCCA7b85BO3F9DzxB3cdqvBzWcmzbyMiqhzuYqtHRVG2y4x+KOlnyqla8AoWWpuBoYRxzXrfKuILl6SfiWCbjxoZJUaCBj1CjH7GIaDbc9kqBY3W/Rgjda1iqQcOJu2WW+76pZC9QG7M00dffe9hNnseupFL53r8F7YHSwJWUKP2q+k7RdsxyOB11n0xtOvnW4irMMFNV4H0uqwS5ExsmP9AxbDTc9JwgneAT5vTiUSm1E7BSflSt3bfa1tv8Di3R8n3Af7MNWzs49hmauE2wP+ttrq+AsWpFG2awvsuOqbipWHgtuvuaAE+A1Z/7gC9hesnr+7wqCwG8c5yAg3AL1fm8T9AZtp/bbJGwl1pNrE7RuOX7PeMRUERVaPpEs+yqeoSmuOlokqw49pgomjLeh7icHNlG19yjs6XXOMedYm5xH2YxpV2tc0Ro2jJfxC50ApuxGob7lMsxfTbeUv07TyYxpeLucEH1gNd4IKH2LAg5TdVhlCafZvpskfncCfx8pOhJzd76bJWeYFnFciwcYfubRc12Ip/ppIhA1/mSZ/RxjFDrJC5xifFjJpY2Xl5zXdguFqYyTR1zSp1Y9p+tktDYYSNflcxI0iyO4TPBdlRcpeqjK/piF5bklq77VSEaA+z8qmJTFzIWiitbnzR794USKBUaT0NTEsVjZqLaFVqJoPN9ODG70IPbfBHKK+/q/AWR0tJzYHRULOa4MP+W/HfGadZUbfw177G7j/OGbIs8TahLyynl4X4RinF793Oz+BU0saXtUHrVBFT/DnA3ctNPoGbs4hRIjTok8i+algT1lTHi4SxFvONKNrgQFAq2/gFnWMXgwffgYMJpiKYkmW3tTg3ZQ9Jq+f8XN+A5eeUKHWvJWJ2sgJ1Sop+wwhqFVijqWaJhwtD8MNlSBeWNNWTa5Z5kPZw5+LbVT99wqTdx29lMUH4OIG/D86ruKEauBjvH5xy6um/Sfj7ei6UUVk4AIl3MyD4MSSTOFgSwsH/QJWaQ5as7ZcmgBZkzjjU1UrQ74ci1gWBCSGHtuV1H2mhSnO3Wp/3fEV5a+4wz//6qy8JxjZsmxxy5+4w9CDNJY09T072iKG0EnOS0arEYgXqYnXcYHwjTtUNAcMelOd4xpkoqiTYICWFq0JSiPfPDQdnt+4/wuqcXY47QILbgAAAABJRU5ErkJggg==);
}
@media screen and (min-width: 640px) and (min-height: 640px) {
@@ -191,22 +192,32 @@ a:hover, .linklike:hover {
.bg-main-hard {
background-color: var(--main-hard-color);
+ background-image: url(data:image/png;base64,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);
}
.bg-main-medium {
background-color: var(--main-medium-color);
+ background-image: url(data:image/png;base64,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);
}
.bg-main-soft {
background-color: var(--main-soft-color);
+ background-image: url(data:image/png;base64,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);
}
.bg-background-dark {
background-color: var(--background-dark-color);
+ background-image: url(data:image/png;base64,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);
+}
+
+.bg-background-medium {
+ background-color: var(--background-medium-color);
+ background-image: var(--noise-image);
}
.bg-background-light {
background-color: var(--background-light-color);
+ background-image: url(data:image/png;base64,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);
}
.border-main-hard {
diff --git a/views/layouts/general-page.html b/views/layouts/general-page.html
index 487f63a..49c0fae 100644
--- a/views/layouts/general-page.html
+++ b/views/layouts/general-page.html
@@ -17,14 +17,11 @@
<script>
function changeUrl(path, toAppend = false) {
- const urlParams = new URLSearchParams(window.location.search);
+ const urlParams = new URLSearchParams(window.location.search);
const newPathname = location.pathname.endsWith('/') ? location.pathname.slice(0, -1) : location.pathname;
const newPath = toAppend ? `${newPathname}${path}` : `${path}`;
-
+
history.pushState({}, '', `${newPath}${urlParams.entries.length == 0 ? '' : '?' + urlParams.toString()}`);
- if (location.pathname == "" || location.pathname == "/") {
- return true;
- }
window.dispatchEvent(new Event('popstate'));
return false;
};
@@ -171,19 +168,20 @@
const clientTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
</script>
- <div id="sidebar" class="bg-sidebar flex sticky flex-col shadow-2xl z-20 w-[100dvw] xs:w-[90dvw] sm:w-[80dvw] md:w-[75dvw] lg:w-[70dvw] xl:w-[65dvw] 2xl:w-[60dvw] [@media(max-height:32rem)]:w-[5rem] h-[5rem] [@media(max-height:32rem)]:h-[100dvh] mx-auto [@media(max-height:32rem)]:mx-0">
+ <div id="sidebar" class="bg-sidebar flex sticky flex-col z-20 w-[100dvw] xs:w-[90dvw] sm:w-[80dvw] md:w-[75dvw] lg:w-[70dvw] xl:w-[65dvw] 2xl:w-[60dvw] [@media(max-height:32rem)]:w-[5rem] h-[5rem] [@media(max-height:32rem)]:h-[100dvh] mx-auto [@media(max-height:32rem)]:mx-0
+ shadow-[0_0_1rem_black]">
<div class="text-[3rem] text-stroke-(--sidebar-stroke-color) text-stroke-[0.1dvw] flex flex-row [@media(max-height:32rem)]:flex-col gap-0 relative z-20">
- <a href="/{{ .Lang }}" class="w-[5rem] h-[5rem]">
+ <a href="/{{ .Lang }}" id="sidebar-home-button" class="w-[5rem] h-[5rem]">
<i onclick="return changeUrl('/{{ .Lang }}');" class="fas fa-home flex w-full h-full content-center text-center text-sidebar hover:bg-background-dark transition-colors duration-300 rounded-lg"></i>
</a>
- <a href="/{{ .Lang }}/blog" class="w-[5rem] h-[5rem]">
+ <a href="/{{ .Lang }}/blog" id="sidebar-blog-button" class="w-[5rem] h-[5rem]">
<i onclick="return changeUrl('/{{ .Lang }}/blog');" class="fas fa-search flex w-full h-full content-center text-center text-sidebar hover:bg-background-dark transition-colors duration-300 rounded-lg"></i>
</a>
- <a href="/{{ .Lang }}/map" class="w-[5rem] h-[5rem]">
+ <a href="/{{ .Lang }}/map" id="sidebar-map-button" class="w-[5rem] h-[5rem]">
<i class="fas fa-map flex w-full h-full content-center text-center text-sidebar hover:bg-background-dark transition-colors duration-300 rounded-lg"></i>
</a>
- <i onclick="toggleThemeWheel();" id="theme-button" class="fas fa-swatchbook flex w-[5rem] h-[5rem] content-center text-center text-sidebar hover:bg-background-dark cursor-pointer transition-colors duration-300 rounded-lg"></i>
- <a href="./" class="hidden max-xs:block [@media(max-height:32rem)]:block w-[5rem] h-[5rem]">
+ <i onclick="toggleThemeWheel();" id="sidebar-theme-button" class="fas fa-swatchbook flex w-[5rem] h-[5rem] content-center text-center text-sidebar hover:bg-background-dark cursor-pointer transition-colors duration-300 rounded-lg"></i>
+ <a href="./" id="sidebar-back-button" class="w-[5rem] h-[5rem]">
<i onclick="return changeUrl('/../', true);" class="fas fa-circle-left flex w-full h-full content-center text-center text-sidebar hover:bg-background-dark transition-colors duration-300 rounded-lg"></i>
</a>
</div>
@@ -194,9 +192,38 @@
<div class="theme-icon" data-theme="ram"></div>
<div class="theme-pin"></div>
</div>
+ <script>
+ sidebarHomeButton = document.getElementById("sidebar-home-button");
+ sidebarMapButton = document.getElementById("sidebar-map-button");
+ sidebarBlogButton = document.getElementById("sidebar-blog-button");
+ sidebarBackButton = document.getElementById("sidebar-back-button");
+
+ function updateSidebar() {
+ if (location.pathname == "" || location.pathname == "/") {
+ sidebarHomeButton.classList.add('hidden');
+ sidebarMapButton.classList.add('hidden');
+ sidebarBlogButton.classList.add('hidden');
+ sidebarBackButton.classList.add('hidden');
+ } else {
+ sidebarHomeButton.classList.remove('hidden');
+ sidebarMapButton.classList.remove('hidden');
+ sidebarBlogButton.classList.remove('hidden');
+ sidebarBackButton.classList.remove('hidden');
+ lang = location.pathname.split("/")[1];
+ sidebarHomeButton.setAttribute('href', `/${lang}`);
+ sidebarHomeButton.firstElementChild.setAttribute('onclick', `return changeUrl('/${lang}', false);`);
+ sidebarMapButton.setAttribute('href', `/${lang}/map`);
+ sidebarBlogButton.setAttribute('href', `/${lang}/blog`);
+ sidebarBlogButton.firstElementChild.setAttribute('onclick', `return changeUrl('/${lang}/blog', false);`);
+ }
+ }
+ window.addEventListener("popstate", updateSidebar);
+ window.addEventListener("load", updateSidebar, {once: true});
+ </script>
</div>
- <div class="bg-background-dark @container/main flex z-10 w-[100dvw] xs:w-[90dvw] sm:w-[80dvw] md:w-[75dvw] lg:w-[70dvw] xl:w-[65dvw] 2xl:w-[60dvw] grow-0 h-[calc(100dvh-5rem)] [@media(max-height:32rem)]:h-[100dvh] mx-auto [@media(max-height:32rem)]:mx-0">
+ <div class="bg-background-dark @container/main flex z-10 w-[100dvw] xs:w-[90dvw] sm:w-[80dvw] md:w-[75dvw] lg:w-[70dvw] xl:w-[65dvw] 2xl:w-[60dvw] grow-0 h-[calc(100dvh-5rem)] [@media(max-height:32rem)]:h-[100dvh] mx-auto [@media(max-height:32rem)]:mx-0
+ shadow-[0_0_1rem_black]">
<div class="bg-background-dark border-r-2 border-dashed border-main-hard"></div>
<div class="max-h-100% flex flex-col grow bg-background-dark relative pt-4 ml-8 pr-4">
@@ -235,7 +262,7 @@
<script>
const themeWheel = document.getElementById('theme-wheel');
- const themeButton = document.getElementById('theme-button');
+ const themeButton = document.getElementById('sidebar-theme-button');
const themeIcons = document.querySelectorAll('.theme-icon');
const themeWheelRadius = convertRemToPixels(6);
diff --git a/views/pages/blog-catalogue.html b/views/pages/blog-catalogue.html
index 8c2a5fc..8e91798 100644
--- a/views/pages/blog-catalogue.html
+++ b/views/pages/blog-catalogue.html
@@ -1,16 +1,16 @@
{{ define "body" }}
<div class="flex flex-row ar-lt-0.8:flex-col text-base h-[100%]">
<form hx-get="/api/v1/blog-search" hx-vals='{"lang": "{{ .Lang }}"}' hx-target=".blog-cards" hx-swap="innerHTML"
- class="tags-list ar-gt-0.8:min-w-[10dvh] ar-gt-0.8:max-w-[20dvh] ar-gt-0.8:w-fit ar-lt-0.8:w-[100%] ar-lt-0.8:max-h-[30%] flex shrink-0 flex-col ar-gt-0.8:mr-6 bg-background-dark ar-lt-0.8:bg-background-light inset-shadow">
+ class="tags-list ar-gt-0.8:min-w-[10dvh] ar-gt-0.8:max-w-[20dvh] ar-gt-0.8:w-fit ar-lt-0.8:w-[100%] ar-lt-0.8:max-h-[30%] flex shrink-0 flex-col ar-gt-0.8:mr-6 bg-background-light inset-shadow-[0_0_0.4rem_black]">
<div class="flex flex-col overflow-y-auto">
<fieldset>
<legend class="font-bold w-[100%] text-center">{{ .L.BlogSearch.TagsHeader }}</legend>
<div class="flex flex-col ar-lt-0.8:grid grid-cols-3 xs:grid-cols-4 sm:grid-cols-5 grid-flow-row-dense">
- <div class="m-0.5">
+ <div class="m-1">
<label class="font-bold"><input type="checkbox" id="tagsAllCheckbox" onclick="selectAll();"> {{ .L.BlogSearch.ChooseAllTags }}</label>
</div>
{{- range .Tags }}
- <div class="m-0.5">
+ <div class="m-1">
<label><input type="checkbox" id="tag{{ .Name }}Checkbox" name="tags[]" value="{{ .Name }}" onclick="contextAll();" {{ if contains $.QueryTags .Name }}checked{{ end }}> {{ .Name }} <span class="text-secondary italic">{{ .Count }}</span></label>
</div>
{{- end }}
@@ -19,22 +19,22 @@
<fieldset class="mt-1">
<legend class="font-bold w-[100%] text-center">{{ .L.BlogSearch.OrderByHeader }}</legend>
<div class="flex flex-col ar-lt-0.8:grid grid-cols-3 grid-rows-2 grid-flow-col">
- <div class="m-0.5">
+ <div class="m-1">
<label><input type="radio" id="sortTitleAsc" name="sort" value="titleAsc" {{ if eq .QuerySort "titleAsc" }}checked{{ end }}> {{ .L.BlogSearch.TitleOrdered }} <i class="fas fa-arrow-down-a-z"></i></label>
</div>
- <div class="m-0.5">
+ <div class="m-1">
<label><input type="radio" id="sortTitleDesc" name="sort" value="titleDesc" {{ if eq .QuerySort "titleDesc" }}checked{{ end }}> {{ .L.BlogSearch.TitleOrdered }} <i class="fas fa-arrow-down-z-a"></i></label>
</div>
- <div class="m-0.5">
+ <div class="m-1">
<label><input type="radio" id="sortActionDateAsc" name="sort" value="actionDateAsc" {{ if eq .QuerySort "actionDateAsc" }}checked{{ end }}> {{ .L.BlogSearch.ActionDateOrdered }} <i class="fas fa-arrow-down-1-9"></i></label>
</div>
- <div class="m-0.5">
+ <div class="m-1">
<label><input type="radio" id="sortActionDateDesc" name="sort" value="actionDateDesc" {{ if eq .QuerySort "actionDateDesc" }}checked{{ end }}> {{ .L.BlogSearch.ActionDateOrdered }} <i class="fas fa-arrow-down-9-1"></i></label>
</div>
- <div class="m-0.5">
+ <div class="m-1">
<label><input type="radio" id="sortPublicationDateAsc" name="sort" value="publicationDateAsc" {{ if eq .QuerySort "publicationDateAsc" }}checked{{ end }}> {{ .L.BlogSearch.PublicationDateOrdered }} <i class="fas fa-arrow-down-1-9"></i></label>
</div>
- <div class="m-0.5">
+ <div class="m-1">
<label><input type="radio" id="sortPublicationDateDesc" name="sort" value="publicationDateDesc" {{ if eq .QuerySort "publicationDateDesc" }}checked{{ end }}> {{ .L.BlogSearch.PublicationDateOrdered }} <i class="fas fa-arrow-down-9-1"></i></label>
</div>
</div>
@@ -53,7 +53,7 @@
<div class="w-[0.5dvh] border-r-2 border-dotted border-main-hard bg-background-dark"></div>
<div hx-get="/api/v1/blog-search" hx-vals='js:{lang: "{{ .Lang }}", tz: clientTimeZone}' hx-target="this" hx-swap="innerHTML" hx-trigger="load" hx-include=".tags-list"
- class="blog-cards grow flex flex-col overflow-y-auto bg-background-light inset-shadow p-6">
+ class="blog-cards grow flex flex-col overflow-y-auto bg-background-light inset-shadow-[0_0_0.4rem_black] p-6">
Loading...
</div>
</div>
diff --git a/views/pages/blog-page.html b/views/pages/blog-page.html
index d4b52a6..7170ad8 100644
--- a/views/pages/blog-page.html
+++ b/views/pages/blog-page.html
@@ -1,5 +1,5 @@
{{ define "body" }}
-<div class="bg-background-light flex flex-col inset-shadow px-8 py-4 overflow-y-auto">
+<div class="bg-background-light flex flex-col inset-shadow-[0_0_0.4rem_black] px-8 py-4 overflow-y-auto">
<p class="max-xs:block [@media(max-height:32rem)]:block hidden font-andika text-2xl font-bold italic text-main-hard tracking-[.0125rem] mb-1">{{ .Title }}</p>
<p class="max-xs:block [@media(max-height:32rem)]:block hidden grow text-lg font-andika text-secondary">{{ .L.Metadata.Published }}: {{ .PublishedDate }}</p>
<p class="max-xs:block [@media(max-height:32rem)]:block hidden grow text-lg font-andika text-secondary">{{ .L.Metadata.Action }}: {{ .ActionDate }}</p>
diff --git a/views/pages/global-map.html b/views/pages/global-map.html
index 4b17d16..cd3c2d5 100644
--- a/views/pages/global-map.html
+++ b/views/pages/global-map.html
@@ -12,7 +12,7 @@
<link rel="stylesheet" href="https://f003.backblazeb2.com/file/sayana-static/libs/leaflet.markercluster/1.4.1/MarkerCluster.Default.css">
</head>
-<body data-theme="ram" class="font-andika text-main-hard overflow-hidden bg-interlocked-hexagons h-[100dvh] flex flex-row ar-lt-0.8:flex-col">
+<body data-theme="ram" class="font-andika text-main-hard overflow-hidden bg-interlocked-hexagons h-[100dvh]">
<script>
function switchTheme(theme) {
@@ -41,21 +41,21 @@
}
</script>
- <div id="sidebar" class="bg-sidebar flex sticky flex-col ar-gt-0.8:items-center shadow-2xl z-20 w-[5rem] ar-lt-0.8:w-[100dvw] h-[100dvh] ar-lt-0.8:h-[8dvh]">
- <div class="logo-custom ar-lt-0.8:hidden text-sidebar font-andika font-extrabold text-center relative z-20">
- saya.today
- </div>
- <div class="text-[3rem] ar-lt-0.8:text-[5dvh] text-stroke-(--sidebar-stroke-color) text-stroke-[0.1dvw] flex flex-col ar-lt-0.8:flex-row gap-0 relative z-20">
- <a href="/{{ .Lang }}" class="w-[5rem] ar-lt-0.8:w-[8dvh] h-[5rem] ar-lt-0.8:h-[8dvh]">
+ <div id="sidebar" class="bg-sidebar block fixed shadow-[0_0_0.4rem_black] z-1001 w-[5rem] h-auto">
+ <div class="text-[3rem] text-stroke-(--sidebar-stroke-color) text-stroke-[0.1dvw] flex flex-col gap-0 relative z-1001">
+ <a href="/{{ .Lang }}" class="w-[5rem] h-[5rem]">
<i class="fas fa-home flex w-full h-full content-center text-center text-sidebar hover:bg-background-dark transition-colors duration-300 rounded-lg"></i>
</a>
- <a href="/{{ .Lang }}/blog" class="w-[5rem] ar-lt-0.8:w-[8dvh] h-[5rem] ar-lt-0.8:h-[8dvh]">
+ <a href="/{{ .Lang }}/blog" class="w-[5rem] h-[5rem]">
<i class="fas fa-search flex w-full h-full content-center text-center text-sidebar hover:bg-background-dark transition-colors duration-300 rounded-lg"></i>
</a>
- <a href="/{{ .Lang }}/map" class="w-[5rem] ar-lt-0.8:w-[8dvh] h-[5rem] ar-lt-0.8:h-[8dvh]">
+ <a href="/{{ .Lang }}/map" class="w-[5rem] h-[5rem]">
<i class="fas fa-map flex w-full h-full content-center text-center text-sidebar hover:bg-background-dark transition-colors duration-300 rounded-lg"></i>
</a>
- <i onclick="toggleThemeWheel();" id="theme-button" class="fas fa-swatchbook flex w-[5rem] ar-lt-0.8:w-[8dvh] h-[5rem] ar-lt-0.8:h-[8dvh] content-center text-center text-sidebar hover:bg-background-dark cursor-pointer transition-colors duration-300 rounded-lg"></i>
+ <i onclick="toggleThemeWheel();" id="theme-button" class="fas fa-swatchbook flex w-[5rem] h-[5rem] content-center text-center text-sidebar hover:bg-background-dark cursor-pointer transition-colors duration-300 rounded-lg"></i>
+ <a href="./" class="w-[5rem] h-[5rem]">
+ <i class="fas fa-circle-left flex w-full h-full content-center text-center text-sidebar hover:bg-background-dark transition-colors duration-300 rounded-lg"></i>
+ </a>
</div>
<div class="theme-wheel" id="theme-wheel">
<div class="theme-icon" data-theme="olive"></div>
@@ -66,7 +66,7 @@
</div>
</div>
- <div id="map-container" class="bg-background-dark flex z-10 w-[calc(100dvw-5rem)] ar-lt-0.8:w-[100dvw] h-[100dvh] ar-lt-0.8:h-[92dvh]"></div>
+ <div id="map-container" class="bg-background-dark flex z-10 w-full h-full"></div>
<script src="https://f003.backblazeb2.com/file/sayana-static/libs/htmx/2.0.6/htmx.min.js"></script>
<script src="https://f003.backblazeb2.com/file/sayana-static/libs/leaflet/1.9.4/leaflet.js"></script>
@@ -225,7 +225,12 @@
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 18,
- attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
+ attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>',
+ zoomControl: false
+ }).addTo(map);
+
+ L.control.zoom({
+ position: 'topright'
}).addTo(map);
map.addLayer(markers);
diff --git a/views/pages/home-page.html b/views/pages/home-page.html
index 0ebc86e..11d0f7b 100644
--- a/views/pages/home-page.html
+++ b/views/pages/home-page.html
@@ -1,9 +1,9 @@
{{ define "body" }}
-<div class="bg-background-light flex flex-row ar-lt-0.6:flex-col w-full h-full inset-shadow overflow-y-auto text-base/[2] tracking-wide">
+<div class="bg-background-light flex flex-row ar-lt-0.6:flex-col w-full h-full inset-shadow-[0_0_0.4rem_black] overflow-y-auto text-base/[2] tracking-wide">
<div class="ar-gt-0.6:flex-3/5 justify-center content-start p-8">
- <div class="flex flex-col justify-start items-start bg-background-dark mb-8">
- <p class="text-3xl/[2] sm:text-4xl/[2] lg:text-5xl/[2] ml-4 tracking-widest uppercase w-full font-andika italic text-left
- border-l-1.5 border-solid border-(--background-dark-color)
+ <div class="flex flex-col justify-start items-start bg-background-dark mb-8 shadow-[0.4rem_0.4rem_0.4rem_black]">
+ <p class="text-3xl/[2] sm:text-4xl/[2] lg:text-5xl/[2] tracking-widest uppercase w-full font-andika italic text-left
+ border-l-4 border-solid border-(--background-dark-color)
bg-gradient-to-r from-(--background-dark-color) to-(--background-light-color)">{{ .L.HomePage.Hymn1 }}</p>
<hr class="w-full border-t-2 border-dotted border-main-hard mb-1">
<p class="text-xl/[2] sm:text-2xl/[2] lg:text-3xl/[2] -indent-8 ml-12 p-1">{{ .L.HomePage.Hymn2 }}</p>
@@ -29,6 +29,7 @@
<p class="text-xl sm:text-2xl lg:text-3xl p-1 w-full font-andika italic text-left
border-l-1.5 border-solid border-(--background-dark-color)
bg-gradient-to-r from-(--background-dark-color) to-(--background-light-color)">{{ .L.HomePage.Contacts }}</p>
+ <hr class="w-full border-t-2 border-dotted border-main-hard mb-1">
<a href="https://t.me/EarlInisMona">
<i class="fa-brands fa-telegram w-4 h-4 mr-1"></i>
<span class="font-bold">Telegram:</span>
@@ -105,7 +106,7 @@
bg-gradient-to-r from-(--background-dark-color) to-(--background-light-color)">{{ .L.HomePage.SidebarDescription }}</p>
<hr class="w-full border-t-2 border-dotted border-main-hard mb-1">
<div class="w-full grid grid-cols-[1fr_4fr] content-center items-center
- [&>*:nth-child(4n+2)]:bg-(--background-medium-color) [&>*:nth-child(4n+3)]:bg-(--background-medium-color)" style="container-type: inline-size;">
+ [&>*:nth-child(4n+2)]:bg-(--background-medium-color)/50 [&>*:nth-child(4n+3)]:bg-(--background-medium-color)/50" style="container-type: inline-size;">
<i class="fas fa-home w-full h-full text-[10cqi] content-center text-center text-main-hard"></i>
<p class="p-1">{{ .L.HomePage.HomePageDescription }}</p>
<i class="fas fa-search w-full h-full text-[10cqi] content-center text-center text-main-hard"></i>
diff --git a/views/pages/language-pick.html b/views/pages/language-pick.html
new file mode 100644
index 0000000..5a9d229
--- /dev/null
+++ b/views/pages/language-pick.html
@@ -0,0 +1,16 @@
+{{ define "body" }}
+<div class="flex flex-col justify-center text-3xl h-[100%]">
+ {{- range .AvailableLanguages }}
+ <hr class="border-t-2 border-dotted border-main-hard">
+ <div class="nth-[2n+1_of_div]:bg-(--background-medium-color)/50 nth-[2n_of_div]:bg-(--background-light-color)/50 p-2.5 flex flex-row justify-center justify-items-center">
+ <a href="/{{ .Name }}" class="w-12 h-12 basis-12 shrink-0 mr-4">
+ <img onclick="return changeUrl('{{ .Name }}');" class="w-full h-full aspect-square cursor-pointer object-cover rounded-md select-none" src="{{ .Flag }}">
+ </a>
+ <a href="/{{ .Name }}" onclick="return changeUrl('{{ .Name }}');" class="cursor-pointer">
+ {{ .Alt }}
+ </a>
+ </div>
+ {{- end }}
+ <hr class="border-t-2 border-dotted border-main-hard">
+</div>
+{{ end }}
diff --git a/views/partials/general-page-header.html b/views/partials/general-page-header.html
index df75bb3..a29d40b 100644
--- a/views/partials/general-page-header.html
+++ b/views/partials/general-page-header.html
@@ -1,10 +1,6 @@
<div {{ if .PublishedDate }} hx-get="/api/v1/tz" hx-vals='js:{timestamp: "{{ .PublishedDate }}", tz: clientTimeZone}' hx-target="#published-date" hx-swap="innerHTML" hx-trigger="load" {{ end }}
class="flex flex-row mb-2">
- <a href="./" class="w-(--text-4xl) h-(--text-4xl) mx-1 my-auto">
- <i onclick="return changeUrl('/../', true);" class="fas fa-circle-left hover:bg-main-hard hover:bg-opacity-10 cursor-pointer transition-colors duration-300 rounded-md text-4xl"></i>
- </a>
- <p class="text-4xl font-andika italic font-extrabold select-none my-auto pl-3 pr-3">//</p>
- <p class="text-4xl font-andika italic text-left mt-auto">{{ .Title }}</p>
- <p id="published-date" class="grow text-2xl font-andika text-secondary text-right mt-auto">{{ .PublishedDate }}</p>
+ <p class="text-4xl font-andika font-light italic text-shadow-[0_2px_2px_var(--main-soft-color)] text-left mt-auto">{{ .Title }}</p>
+ <p id="published-date" class="grow text-2xl font-andika italic text-secondary text-right mt-auto">{{ .PublishedDate }}</p>
</div>
{{ block "header" . }}{{ end }}