From c07da125bc5b0bb65f58c4edce912874e46f6ed8 Mon Sep 17 00:00:00 2001 From: SayaAndy Date: Fri, 15 May 2026 21:09:56 +0700 Subject: feat: subheader for blog pages with medley-related ones fix: inline shadow now sticks to scrolling feat: multitone backgrounds implementation refactor: convert color vars into oklch --- views/partials/catalogue-blog-cards.html | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'views/partials/catalogue-blog-cards.html') diff --git a/views/partials/catalogue-blog-cards.html b/views/partials/catalogue-blog-cards.html index 0a93797..3eebd58 100644 --- a/views/partials/catalogue-blog-cards.html +++ b/views/partials/catalogue-blog-cards.html @@ -1,6 +1,6 @@ {{- range .BlogPages }}
-
+
@@ -20,10 +20,20 @@ {{ .Title }} [{{ .ActionDate }}] + {{- if not $.HidePublishedTime }}

{{ .PublishedTime }}

+ {{- end }}

{{ .ShortDescription }}

+ {{- if not $.HideTags }}

{{ $.L.TagsLabel }} {{ template "catalogue-blog-card-tags.html" . }}

+ {{- end }}
-{{- end }} \ No newline at end of file +{{- if .ToHighlight }} + +{{- end }} +{{- end }} -- cgit v1.3.1+17 From 44b72cbc80fb89788470bda75eeb9c0bb3dee2f5 Mon Sep 17 00:00:00 2001 From: SayaAndy Date: Sat, 16 May 2026 13:18:08 +0700 Subject: feat: all color themes now have light & dark variations depending on preference feat: color all leaflet elements depending on color theme & scheme feat: change font to m-plus for short description fix: theme wheel position on different dpi screens in global map --- static/input.css | 266 ++++++++++++++++++++++--------- views/layouts/general-page.html | 13 +- views/pages/global-map.html | 2 +- views/partials/catalogue-blog-cards.html | 2 +- 4 files changed, 202 insertions(+), 81 deletions(-) (limited to 'views/partials/catalogue-blog-cards.html') diff --git a/static/input.css b/static/input.css index 8b71614..8b18579 100644 --- a/static/input.css +++ b/static/input.css @@ -42,10 +42,6 @@ html { font-size: 12px; --crossed-out: url("data:image/svg+xml,"); --bg-paper: url(data:image/webp;base64,UklGRi4BAABXRUJQVlA4ICIBAABQCQCdASqAAIAAPm02lUmkIqIkIImIgA2JaW3rMFmGDAOKLAoJtP591ByFR74Tun2DP+Lygpfsz5FH7+cKgxi2Islfd03i5AJdXUfU0SDc8SXYAAD++hlzeYAJWQEF8ZdkJdlcA+5btZg0FMGaso8SHoBph0qAOQysElJ5C5SJFNoKIV1J550UyL7Y9Gh0/c/uzLnBmr8lvz7k1WeA81H4S5ViU/wBqa7aM1m8D9rDtrk8cSTqx+xWF6MS8UfZGSsks6CT/igtgv6syFN9uNA3LjnjiCJKYOvFcMkX+jB2578GWVo3nyLaM1QNPYCxn3TiUbnf7U0MdD2NsBpg1+Jd1wu6yW/U+goN+IQS6Nt4RMWltVcZHlxrneKJi0SobO0AAA==); - --split-left-background: unset; - --split-left-repeat: no-repeat; - --split-left-size: cover; - --split-left-position: left; --split-right-background: unset; --split-right-repeat: no-repeat; --split-right-size: cover; @@ -133,6 +129,22 @@ body { --squares-and-triangles-background-height-coef: 10; } +@media (prefers-color-scheme: dark) { + [data-theme="olive"] { + --color-accent-light: var(--color-lime-600); + --color-accent-deep: var(--color-lime-300); + --color-main: var(--color-main-light-hard); + --color-main-hard: var(--color-main-light-hard); + --color-main-medium: var(--color-main-light-medium); + --color-main-soft: var(--color-main-light-soft); + --color-background: var(--color-main-dark-hard); + --color-background-dark: var(--color-main-dark-hard); + --color-background-medium: var(--color-main-dark-medium); + --color-background-light: var(--color-main-dark-soft); + --color-sidebar-stroke: var(--color-main-light-hard); + } +} + [data-theme="lettuce"] { --color-accent-light: var(--color-lime-300); --color-accent-deep: var(--color-lime-600); @@ -167,66 +179,76 @@ body { --squares-and-triangles-background-height-coef: 10; } +@media (prefers-color-scheme: dark) { + [data-theme="lettuce"] { + --color-accent-light: var(--color-lime-600); + --color-accent-deep: var(--color-lime-300); + --color-main: var(--color-main-light-hard); + --color-main-hard: var(--color-main-light-hard); + --color-main-medium: var(--color-main-light-medium); + --color-main-soft: var(--color-main-light-soft); + --color-background: var(--color-main-dark-hard); + --color-background-dark: var(--color-main-dark-hard); + --color-background-medium: var(--color-main-dark-medium); + --color-background-light: var(--color-main-dark-soft); + --color-sidebar-stroke: var(--color-main-light-hard); + } +} + [data-theme="night"] { - --color-accent-light: var(--color-indigo-900); - --color-accent-deep: var(--color-indigo-500); - --color-main-light-hard: var(--color-sky-100); - --color-main-light-medium: var(--color-sky-200); - --color-main-light-soft: var(--color-sky-300); + --color-accent-light: var(--color-indigo-500); + --color-accent-deep: var(--color-indigo-800); + --color-main-light-hard: var(--color-indigo-300); + --color-main-light-medium: var(--color-indigo-200); + --color-main-light-soft: var(--color-indigo-200); --color-main-dark-hard: oklch(19.064% 0.01614 284.757); --color-main-dark-medium: var(--color-main-dark-hard); --color-main-dark-soft: oklch(25.846% 0.02619 284.414); - --color-main: var(--color-main-light-hard); - --color-main-hard: var(--color-main-light-hard); - --color-main-medium: var(--color-main-light-medium); - --color-main-soft: var(--color-main-light-soft); - --color-background: var(--color-main-dark-soft); - --color-background-dark: var(--color-main-dark-hard); - --color-background-medium: var(--color-main-dark-medium); - --color-background-light: var(--color-main-dark-soft); + --color-main: var(--color-main-dark-hard); + --color-main-hard: var(--color-main-dark-hard); + --color-main-medium: var(--color-main-dark-medium); + --color-main-soft: var(--color-main-dark-soft); + --color-background: var(--color-main-light-soft); + --color-background-dark: var(--color-main-light-hard); + --color-background-medium: var(--color-main-light-medium); + --color-background-light: var(--color-main-light-soft); --color-sidebar-text: var(--color-main-hard); - --color-sidebar-stroke: var(--color-main-light-soft); + --color-sidebar-stroke: var(--color-main-dark-soft); --color-secondary: var(--color-main-soft); --color-leaflet-text: var(--color-background-dark); --color-leaflet-link: var(--color-background-dark); --color-leaflet-link-hover: var(--color-background-light); --interlocked-hexagons-background: - radial-gradient( - 33.5% 25% at 100% 82%, - rgba(190, 227, 248, 0.2) 0%, - rgba(197, 179, 246, 0.13) 33.33%, - rgba(255, 0, 0, 0) 100% - ), - radial-gradient( - 54% 25% at 55% 100%, - rgba(190, 227, 248, 0.2) 0%, - rgba(197, 179, 246, 0.13) 33.33%, - rgba(255, 0, 0, 0) 100% - ), - radial-gradient( - 37% 19.5% at 20% 100%, - rgba(176, 220, 248, 0.3) 0%, - rgba(197, 172, 247, 0.2) 33.33%, - rgba(255, 0, 0, 0) 100% + linear-gradient( + 180deg, + #4c51bf 0%, + rgba(89, 108, 214, 0.75) 12%, + rgba(107, 136, 231, 0.5) 24%, + rgba(163, 191, 250, 0) 48% ), radial-gradient( - 63% 34.5% at 66% 77%, - rgba(190, 227, 248, 0.15) 0%, - rgba(197, 179, 246, 0.1) 33.33%, - rgba(255, 0, 0, 0) 100% + 100% 37.5% at 50% 100%, + #f687b3 0%, + rgba(245, 151, 227, 0.75) 25%, + rgba(217, 182, 245, 0.5) 50%, + rgba(190, 227, 248, 0) 100% + ), + linear-gradient( + 360deg, + #f6ad55 0%, + rgba(247, 183, 98, 0.75) 14%, + rgba(249, 192, 112, 0.5) 28%, + rgba(251, 211, 141, 0) 56% ), linear-gradient( - 0deg, - #2f5883 0%, - #2f4e7a 4.75%, - #2e4472 9.5%, - #2a3065 19%, - #272e57 26.5%, - #242b4b 34%, - #1f2437 49%, - #1c2030 57.75%, - #1a1b29 66.5%, - #13131b 84% + 90deg, + #bee3f8 0%, + #b7e0f7 14.29%, + #b1ddf7 28.57%, + #aadaf6 42.86%, + #a4d7f6 57.14%, + #9dd3f5 71.43%, + #90cdf4 100% ); --interlocked-hexagons-background-repeat: no-repeat; --interlocked-hexagons-background-size: 100dvw 100dvh; @@ -236,25 +258,79 @@ body { --squares-and-triangles-background-height-coef: 5; } +@media (prefers-color-scheme: dark) { + [data-theme="night"] { + --color-accent-light: var(--color-indigo-900); + --color-accent-deep: var(--color-indigo-500); + --color-main: var(--color-main-light-hard); + --color-main-hard: var(--color-main-light-hard); + --color-main-medium: var(--color-main-light-medium); + --color-main-soft: var(--color-main-light-soft); + --color-background: var(--color-main-dark-soft); + --color-background-dark: var(--color-main-dark-hard); + --color-background-medium: var(--color-main-dark-medium); + --color-background-light: var(--color-main-dark-soft); + --color-sidebar-stroke: var(--color-main-light-soft); + --interlocked-hexagons-background: + radial-gradient( + 33.5% 25% at 100% 82%, + rgba(190, 227, 248, 0.2) 0%, + rgba(197, 179, 246, 0.13) 33.33%, + rgba(255, 0, 0, 0) 100% + ), + radial-gradient( + 54% 25% at 55% 100%, + rgba(190, 227, 248, 0.2) 0%, + rgba(197, 179, 246, 0.13) 33.33%, + rgba(255, 0, 0, 0) 100% + ), + radial-gradient( + 37% 19.5% at 20% 100%, + rgba(176, 220, 248, 0.3) 0%, + rgba(197, 172, 247, 0.2) 33.33%, + rgba(255, 0, 0, 0) 100% + ), + radial-gradient( + 63% 34.5% at 66% 77%, + rgba(190, 227, 248, 0.15) 0%, + rgba(197, 179, 246, 0.1) 33.33%, + rgba(255, 0, 0, 0) 100% + ), + linear-gradient( + 0deg, + #2f5883 0%, + #2f4e7a 4.75%, + #2e4472 9.5%, + #2a3065 19%, + #272e57 26.5%, + #242b4b 34%, + #1f2437 49%, + #1c2030 57.75%, + #1a1b29 66.5%, + #13131b 84% + ); + } +} + [data-theme="ram"] { - --color-accent-light: var(--color-orange-800); - --color-accent-deep: var(--color-orange-300); + --color-accent-light: var(--color-orange-300); + --color-accent-deep: var(--color-orange-800); --color-main-light-hard: oklch(97.95% 0.0443 101.66); --color-main-light-medium: oklch(92.541% 0.04519 81.305); --color-main-light-soft: oklch(87.909% 0.04338 76.287); --color-main-dark-hard: oklch(35.615% 0.01442 71.558); --color-main-dark-medium: oklch(46.724% 0.01927 64.275); --color-main-dark-soft: oklch(50.352% 0.02092 64.558); - --color-main: var(--color-main-light-hard); - --color-main-hard: var(--color-main-light-hard); - --color-main-medium: var(--color-main-light-medium); - --color-main-soft: var(--color-main-light-soft); - --color-background: var(--color-main-dark-soft); - --color-background-dark: var(--color-main-dark-hard); - --color-background-medium: var(--color-main-dark-medium); - --color-background-light: var(--color-main-dark-soft); + --color-main: var(--color-main-dark-hard); + --color-main-hard: var(--color-main-dark-hard); + --color-main-medium: var(--color-main-dark-medium); + --color-main-soft: var(--color-main-dark-soft); + --color-background: var(--color-main-light-hard); + --color-background-dark: var(--color-main-light-hard); + --color-background-medium: var(--color-main-light-medium); + --color-background-light: var(--color-main-light-soft); --color-sidebar-text: var(--color-main-hard); - --color-sidebar-stroke: var(--color-main-light-soft); + --color-sidebar-stroke: var(--color-main-dark-soft); --color-secondary: var(--color-main-soft); --color-leaflet-text: var(--color-background-dark); --color-leaflet-link: var(--color-background-dark); @@ -268,6 +344,22 @@ body { --squares-and-triangles-background-height-coef: 15; } +@media (prefers-color-scheme: dark) { + [data-theme="ram"] { + --color-accent-light: var(--color-orange-800); + --color-accent-deep: var(--color-orange-300); + --color-main: var(--color-main-light-hard); + --color-main-hard: var(--color-main-light-hard); + --color-main-medium: var(--color-main-light-medium); + --color-main-soft: var(--color-main-light-soft); + --color-background: var(--color-main-dark-soft); + --color-background-dark: var(--color-main-dark-hard); + --color-background-medium: var(--color-main-dark-medium); + --color-background-light: var(--color-main-dark-soft); + --color-sidebar-stroke: var(--color-main-light-soft); + } +} + [data-theme="lilac"] { --color-accent-light: var(--color-indigo-300); --color-accent-deep: var(--color-indigo-800); @@ -298,8 +390,24 @@ body { --squares-and-triangles-background-repeat: repeat; --squares-and-triangles-background-width-coef: 5; --squares-and-triangles-background-height-coef: 5; - --split-left-background: url("https://storage.yandexcloud.kz/sayauz-static/themes/lilac/split-left.webp"); - --split-right-background: url("https://storage.yandexcloud.kz/sayauz-static/themes/lilac/split-right.webp"); + --split-right-background: url("https://storage.yandexcloud.kz/sayauz-static/themes/lilac/split-right-light.webp"); +} + +@media (prefers-color-scheme: dark) { + [data-theme="lilac"] { + --color-accent-light: var(--color-indigo-800); + --color-accent-deep: var(--color-indigo-300); + --color-main: var(--color-main-light-hard); + --color-main-hard: var(--color-main-light-hard); + --color-main-medium: var(--color-main-light-medium); + --color-main-soft: var(--color-main-light-soft); + --color-background: var(--color-main-dark-hard); + --color-background-dark: var(--color-main-dark-hard); + --color-background-medium: var(--color-main-dark-medium); + --color-background-light: var(--color-main-dark-soft); + --color-sidebar-stroke: var(--color-main-dark-hard); + --split-right-background: url("https://storage.yandexcloud.kz/sayauz-static/themes/lilac/split-right-dark.webp"); + } } a, @@ -314,16 +422,16 @@ a:hover, } #map-container { - color: var(--color-leaflet-text) !important; + color: var(--color-main-hard) !important; } #map-container a { - color: var(--color-leaflet-link) !important; + color: var(--color-main-medium) !important; text-decoration: underline; } #map-container a:hover { - color: var(--color-leaflet-link-hover) !important; + color: var(--color-main-soft) !important; text-decoration: underline; } @@ -379,13 +487,6 @@ form.crossable.htmx-request input { background-repeat: var(--squares-and-triangles-background-repeat); } -.bg-split-left { - background-image: var(--split-left-background); - background-repeat: var(--split-left-repeat); - background-size: var(--split-left-size); - background-position: var(--split-left-position); -} - .bg-split-right { background-image: var(--split-right-background); background-repeat: var(--split-right-repeat); @@ -738,9 +839,22 @@ form.crossable.htmx-request input { height: 100% !important; } -body[data-theme~="night"] .leaflet-tile, -body[data-theme~="ram"] .leaflet-tile { - filter: invert(1) hue-rotate(190deg) contrast(1.1) brightness(1.2) !important; +.leaflet-container .leaflet-control-attribution { + background: color-mix(in oklch, var(--color-background-medium) 80%, transparent) !important; +} + +.leaflet-popup-content-wrapper, .leaflet-popup-tip { + background: var(--color-background-medium) !important; +} + +.leaflet-bar a { + background-color: var(--color-background-medium) !important; +} + +@media (prefers-color-scheme: dark) { + .leaflet-tile { + filter: invert(1) hue-rotate(190deg) contrast(1.1) brightness(1.2) !important; + } } .home-page-heart { diff --git a/views/layouts/general-page.html b/views/layouts/general-page.html index 2d125ae..491c652 100644 --- a/views/layouts/general-page.html +++ b/views/layouts/general-page.html @@ -401,15 +401,22 @@ localStorage.setItem("theme", theme); document.body.setAttribute("data-theme", theme); switchThemeDecor(theme); - if (theme == "ram" || theme == "night") { + } + + const savedTheme = localStorage.getItem("theme") || "lilac"; + switchTheme(savedTheme); + + function switchColorScheme(isNightMode) { + if (isNightMode) { makeMultitoneOklch('multitone', 4, '--color-background-dark', '--color-accent-light', '--color-background-light'); } else { makeMultitoneOklch('multitone', 4, '--color-background-light', '--color-accent-light', '--color-background-dark'); } } - const savedTheme = localStorage.getItem("theme") || "lilac"; - switchTheme(savedTheme); + const mq = matchMedia('(prefers-color-scheme: dark)'); + switchColorScheme(mq.matches); + mq.addEventListener('change', (e) => switchColorScheme(e.matches)); diff --git a/views/pages/global-map.html b/views/pages/global-map.html index a6dc006..788eac9 100644 --- a/views/pages/global-map.html +++ b/views/pages/global-map.html @@ -229,7 +229,6 @@ const themeWheel = document.getElementById("theme-wheel"); const themeButton = document.getElementById("sidebar-theme-button"); const themeIcons = document.querySelectorAll(".theme-icon"); - const themeWheelRadius = convertRemToPixels(6); const THUMB_BASE = "{{ .ThumbnailBaseUrl }}"; themeIcons.forEach((icon) => { @@ -294,6 +293,7 @@ const buttonRect = themeButton.getBoundingClientRect(); const buttonCenterX = buttonRect.left + buttonRect.width / 2; const buttonCenterY = buttonRect.top + buttonRect.height / 2; + const themeWheelRadius = convertRemToPixels(6); const margin = 0; diff --git a/views/partials/catalogue-blog-cards.html b/views/partials/catalogue-blog-cards.html index 3eebd58..799955f 100644 --- a/views/partials/catalogue-blog-cards.html +++ b/views/partials/catalogue-blog-cards.html @@ -24,7 +24,7 @@

{{ .PublishedTime }}

{{- end }}
-

{{ .ShortDescription }}

+

{{ .ShortDescription }}

{{- if not $.HideTags }}

{{ $.L.TagsLabel }} {{ template "catalogue-blog-card-tags.html" . }}

{{- end }} -- cgit v1.3.1+17 From 6418da32d978a8b70d38f1911a154e4dcc33202e Mon Sep 17 00:00:00 2001 From: SayaAndy Date: Mon, 18 May 2026 00:15:41 +0700 Subject: feat: combined map widget feat: migrate all static to cdn feat: use 560p thumbnails for multitone backgrounds --- config/config.go | 12 ++- config/config.local.yaml | 5 +- config/config.prod.yaml | 5 +- config/config.stage.yaml | 6 +- internal/router/handlers/api-v1-map-get.go | 116 +++++++++++++++++++++++++++ internal/router/handlers/lang-map.go | 65 +--------------- internal/router/router.go | 38 ++++----- internal/templatemanager/templatemanager.go | 1 + static/input.css | 21 +++-- views/layouts/general-page.html | 31 +++++--- views/messages/new-post.html | 2 +- views/pages/blog-page.html | 44 +---------- views/pages/global-map.html | 117 +++------------------------- views/partials/catalogue-blog-cards.html | 2 +- views/partials/global-map-widget.html | 109 ++++++++++++++++++++++++++ 15 files changed, 319 insertions(+), 255 deletions(-) create mode 100644 internal/router/handlers/api-v1-map-get.go create mode 100644 views/partials/global-map-widget.html (limited to 'views/partials/catalogue-blog-cards.html') diff --git a/config/config.go b/config/config.go index 0b1570a..8ab1bfc 100644 --- a/config/config.go +++ b/config/config.go @@ -22,7 +22,7 @@ type Config struct { CanonicalEndpoint string `json:"CanonicalEndpoint" yaml:"canonicalEndpoint" validate:"required"` Meta MetaConfig `json:"Meta" yaml:"meta"` PhotoStorage PhotoStorageConfig `json:"PhotoStorage" yaml:"photoStorage"` - StaticStorage PhotoTypeConfig `json:"StaticStorage" yaml:"staticStorage"` + StaticStorage StaticStorageConfig `json:"StaticStorage" yaml:"staticStorage" validate:"required"` AllowOrigins []string `json:"AllowOrigins" yaml:"allowOrigins"` } @@ -261,6 +261,16 @@ type HomePageGifsConfig struct { Indexes []string `json:"Indexes" yaml:"indexes"` } +type StaticStorageConfig struct { + BaseUrl string `json:"BaseUrl" yaml:"baseUrl" validate:"url,required"` + Map MapStorageConfig `json:"Map" yaml:"map" validate:"required"` +} + +type MapStorageConfig struct { + BaseUrl string `json:"BaseUrl" yaml:"baseUrl" validate:"url,required"` + PMTiles string `json:"PMTiles" yaml:"pmTiles" validate:"required"` +} + func LoadConfig(path string, config *Config) error { fileBytes, err := os.ReadFile(path) if err != nil { diff --git a/config/config.local.yaml b/config/config.local.yaml index 80eb8f7..7fe612b 100644 --- a/config/config.local.yaml +++ b/config/config.local.yaml @@ -74,8 +74,9 @@ photoStorage: indexes: ["1", "2", "3"] staticStorage: baseUrl: https://cdn.saya.uz/static -mapStorage: - baseUrl: https://cdn.saya.uz/map + map: + baseUrl: https://cdn.saya.uz/map + pmTiles: global.pmtiles allowOrigins: - https://storage.yandexcloud.kz - https://cdn.saya.uz diff --git a/config/config.prod.yaml b/config/config.prod.yaml index ad4864a..5df5422 100644 --- a/config/config.prod.yaml +++ b/config/config.prod.yaml @@ -77,8 +77,9 @@ photoStorage: indexes: ["1", "2", "3"] staticStorage: baseUrl: https://cdn.saya.uz/static -mapStorage: - baseUrl: https://cdn.saya.uz/map + map: + baseUrl: https://cdn.saya.uz/map + pmTiles: global.pmtiles allowOrigins: - https://storage.yandexcloud.kz - https://cdn.saya.uz diff --git a/config/config.stage.yaml b/config/config.stage.yaml index 4b46c6c..f593fef 100644 --- a/config/config.stage.yaml +++ b/config/config.stage.yaml @@ -74,9 +74,9 @@ photoStorage: indexes: ["1", "2", "3"] staticStorage: baseUrl: https://cdn.saya.uz/static -mapStorage: - baseUrl: https://cdn.saya.uz/map + map: + baseUrl: https://cdn.saya.uz/map + pmTiles: global.pmtiles allowOrigins: - https://storage.yandexcloud.kz - https://cdn.saya.uz - diff --git a/internal/router/handlers/api-v1-map-get.go b/internal/router/handlers/api-v1-map-get.go new file mode 100644 index 0000000..e19c54a --- /dev/null +++ b/internal/router/handlers/api-v1-map-get.go @@ -0,0 +1,116 @@ +package handlers + +import ( + "fmt" + "log/slog" + "slices" + "strconv" + "strings" + + "github.com/SayaAndy/saya-today-web/internal/blog" + "github.com/SayaAndy/saya-today-web/internal/router" + "github.com/gofiber/fiber/v2" +) + +type GetMapHandler struct { + router.BasicHandler +} + +func init() { + router.Routes = append(router.Routes, &GetMapHandler{}) +} + +func (r *GetMapHandler) Filter() (method string, path string) { + return "GET", "/api/v1/map" +} + +func (r *GetMapHandler) IsTemplated() bool { + return false +} + +func (r *GetMapHandler) TemplatesToInject() []string { + return []string{"views/partials/global-map-widget.html"} +} + +func (r *GetMapHandler) ToCache() router.CacheSetting { + return router.ByUrlAndQuery +} + +func (r *GetMapHandler) ToValidateLang() router.LangSetting { + return router.InReferer +} + +func (r *GetMapHandler) Render(c *fiber.Ctx, supplements *router.Supplements, lang string, templateMap fiber.Map) (statusCode int, err error) { + codename := c.Query("codename") + zoom := c.QueryInt("zoom", 4) + zoomPosition := c.Query("zoomPosition") + + pages, err := supplements.BlogClient.Scan(lang + "/") + status := fiber.StatusOK + if err != nil { + slog.Error("received an error while scanning blog pages", + slog.String("error", err.Error()), + slog.String("lang", lang), + ) + status = fiber.StatusPartialContent + pages = []*blog.Page{} + } + slices.SortFunc(pages, func(a *blog.Page, b *blog.Page) int { + return a.Metadata.PublishedTime.Compare(b.Metadata.PublishedTime) + }) + + type MapMarker struct { + Index int `json:"Index"` + Title string `json:"Title"` + PageLink string `json:"PageLink"` + Lat float64 `json:"Lat"` + Long float64 `json:"Long"` + AccuracyMeters int64 `json:"AccuracyMeters"` + Thumbnail string `json:"Thumbnail"` + ToHighlight bool `json:"ToHighlight"` + } + + templateMap["MapLocationLat"] = 45.4507 + templateMap["MapLocationLong"] = 68.8319 + templateMap["MapLocationZoom"] = zoom + templateMap["ZoomPosition"] = zoomPosition + + mapMarkers := make([]*MapMarker, 0, len(pages)) + for i, page := range pages { + geolocationParts := strings.Split(page.Metadata.Geolocation, " ") + if len(geolocationParts) < 2 { + continue + } + + var x, y float64 + var areaError int64 + if len(geolocationParts) >= 2 { + x, _ = strconv.ParseFloat(geolocationParts[0], 64) + y, _ = strconv.ParseFloat(geolocationParts[1], 64) + } + if len(geolocationParts) >= 3 { + areaError, _ = strconv.ParseInt(geolocationParts[2], 10, 64) + } + + toHighlight := page.FileName == codename + if toHighlight { + templateMap["MapLocationLat"] = x + templateMap["MapLocationLong"] = y + } + + mapMarkers = append(mapMarkers, &MapMarker{ + Index: i, + Title: page.Metadata.Title, + PageLink: fmt.Sprintf("/%s/blog/%s", lang, page.FileName), + Lat: x, + Long: y, + AccuracyMeters: areaError, + Thumbnail: page.Metadata.Thumbnail, + ToHighlight: toHighlight, + }) + } + + templateMap["MapMarkers"] = mapMarkers + + return status, nil +} diff --git a/internal/router/handlers/lang-map.go b/internal/router/handlers/lang-map.go index d452bc7..32ab35e 100644 --- a/internal/router/handlers/lang-map.go +++ b/internal/router/handlers/lang-map.go @@ -1,13 +1,6 @@ package handlers import ( - "fmt" - "log/slog" - "slices" - "strconv" - "strings" - - "github.com/SayaAndy/saya-today-web/internal/blog" "github.com/SayaAndy/saya-today-web/internal/router" "github.com/gofiber/fiber/v2" ) @@ -49,61 +42,5 @@ func (r *MapHandler) SitemapInfo(supplements *router.Supplements) []router.Sitem } func (r *MapHandler) Render(c *fiber.Ctx, supplements *router.Supplements, lang string, templateMap fiber.Map) (statusCode int, err error) { - pages, err := supplements.BlogClient.Scan(lang + "/") - slices.SortFunc(pages, func(a *blog.Page, b *blog.Page) int { - return a.Metadata.PublishedTime.Compare(b.Metadata.PublishedTime) - }) - status := fiber.StatusOK - if err != nil { - slog.Error("received an error while scanning b2 pages", - slog.String("error", err.Error()), - slog.String("lang", lang), - ) - status = fiber.StatusPartialContent - pages = []*blog.Page{} - } - - type MapMarker struct { - Index int `json:"Index"` - Title string `json:"Title"` - PageLink string `json:"PageLink"` - Lat float64 `json:"Lat"` - Long float64 `json:"Long"` - AccuracyMeters int64 `json:"AccuracyMeters"` - Thumbnail string `json:"Thumbnail"` - } - - mapMarkers := make([]*MapMarker, 0, len(pages)) - for i, page := range pages { - geolocationParts := strings.Split(page.Metadata.Geolocation, " ") - if len(geolocationParts) < 2 { - continue - } - - var x, y float64 - var areaError int64 - if len(geolocationParts) >= 2 { - x, _ = strconv.ParseFloat(geolocationParts[0], 64) - y, _ = strconv.ParseFloat(geolocationParts[1], 64) - } - if len(geolocationParts) >= 3 { - areaError, _ = strconv.ParseInt(geolocationParts[2], 10, 64) - } - - mapMarkers = append(mapMarkers, &MapMarker{ - Index: i, - Title: page.Metadata.Title, - PageLink: fmt.Sprintf("/%s/blog/%s", lang, page.FileName), - Lat: x, - Long: y, - AccuracyMeters: areaError, - Thumbnail: page.Metadata.Thumbnail, - }) - } - - templateMap["MapMarkers"] = mapMarkers - templateMap["MapLocationLat"] = 45.4507 - templateMap["MapLocationLong"] = 68.8319 - - return status, nil + return fiber.StatusOK, nil } diff --git a/internal/router/router.go b/internal/router/router.go index 43d6138..c8b5686 100644 --- a/internal/router/router.go +++ b/internal/router/router.go @@ -104,7 +104,7 @@ type Supplements struct { MarkdownRenderer goldmark.Markdown Meta config.MetaConfig PhotoStorage config.PhotoStorageConfig - StaticStorage config.PhotoTypeConfig + StaticStorage config.StaticStorageConfig } type Router struct { @@ -303,12 +303,12 @@ func (r *Router) InitRoutes() (err error) { } defaultMap := fiber.Map{ - "Lang": lang, - "Path": trimmedPath, - "QueryString": queryString, - "CanonicalEndpoint": r.canonicalEndpoint, - "StaticStorageBaseUrl": r.supplements.StaticStorage.BaseUrl, - "ThumbnailBaseUrl": r.supplements.PhotoStorage.Thumbnail320p.BaseUrl, + "Lang": lang, + "Path": trimmedPath, + "QueryString": queryString, + "CanonicalEndpoint": r.canonicalEndpoint, + "StaticStorage": r.supplements.StaticStorage, + "PhotoStorage": r.supplements.PhotoStorage, } statusCode, err := currentRoute.Render(c, r.supplements, lang, defaultMap) @@ -455,12 +455,12 @@ func (r *Router) generalPage(c *fiber.Ctx, route Route, lang string) error { } valueMap := fiber.Map{ - "Lang": lang, - "Path": trimmedPath, - "QueryString": queryString, - "CanonicalEndpoint": r.canonicalEndpoint, - "StaticStorageBaseUrl": r.supplements.StaticStorage.BaseUrl, - "ThumbnailBaseUrl": r.supplements.PhotoStorage.Thumbnail320p.BaseUrl, + "Lang": lang, + "Path": trimmedPath, + "QueryString": queryString, + "CanonicalEndpoint": r.canonicalEndpoint, + "StaticStorage": r.supplements.StaticStorage, + "PhotoStorage": r.supplements.PhotoStorage, } var err error @@ -580,12 +580,12 @@ func (r *Router) generalPageSegment(c *fiber.Ctx, part string) error { var statusCode int defaultMap := fiber.Map{ - "Lang": lang, - "Path": strings.Trim(path, "/"), - "QueryString": queryString, - "CanonicalEndpoint": r.canonicalEndpoint, - "StaticStorageBaseUrl": r.supplements.StaticStorage.BaseUrl, - "ThumbnailBaseUrl": r.supplements.PhotoStorage.Thumbnail320p.BaseUrl, + "Lang": lang, + "Path": strings.Trim(path, "/"), + "QueryString": queryString, + "CanonicalEndpoint": r.canonicalEndpoint, + "StaticStorage": r.supplements.StaticStorage, + "PhotoStorage": r.supplements.PhotoStorage, } switch part { diff --git a/internal/templatemanager/templatemanager.go b/internal/templatemanager/templatemanager.go index 5c84418..ff1214a 100644 --- a/internal/templatemanager/templatemanager.go +++ b/internal/templatemanager/templatemanager.go @@ -43,6 +43,7 @@ var templateFuncMap = template.FuncMap{ "l": func(path ...any) any { return l10n.T.GetPath(path...) }, + "join": strings.Join, } func NewTemplateManager(templates ...TemplateManagerTemplates) (*TemplateManager, error) { diff --git a/static/input.css b/static/input.css index 602b5d9..98caaad 100644 --- a/static/input.css +++ b/static/input.css @@ -169,8 +169,8 @@ body { --color-leaflet-link: var(--color-main-medium); --color-leaflet-link-hover: var(--color-main-soft); --interlocked-hexagons-background: - url("https://storage.yandexcloud.kz/sayauz-static/themes/lettuce/linen-fabric.webp"), - url("https://storage.yandexcloud.kz/sayauz-static/themes/lettuce/lettuce-tiles.svg"); + url("https://cdn.saya.uz/static/themes/lettuce/linen-fabric.webp"), + url("https://cdn.saya.uz/static/themes/lettuce/lettuce-tiles.svg"); --interlocked-hexagons-background-repeat: repeat, repeat; --interlocked-hexagons-background-size: 11dvh, 20dvh; --squares-and-triangles-background: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22100%22%20height%3D%22100%22%3E%3Crect%20width%3D%22100%25%22%20height%3D%22100%25%22%20fill%3D%22%23bbd095%22%2F%3E%3Cpath%20fill%3D%22%23f5ede1%22%20d%3D%22M0%200v6.77L6.72%200zm8.91%200L0%208.96v3.86L12.83%200zm6.11%200L0%2015.06v3.87L18.9%200zm6.11%200L0%2021.12v3.92L25%200zM25%200l25%2024.99v-3.87L28.87%200zm25%2024.99%2025%2024.98L100%2025%2075%200zm-50%20.05v3.87l21.13%2021.12H25l-25-25zm25%2024.99h3.87L50%2028.9v-3.87zm0%200L0%2075l25%2025%2025-24.99zM50%2075l25-24.98h-3.87L50%2071.14v3.87zm0%200v3.87L71.13%20100H75L50%2075.01zm25%2025h3.87L100%2078.88v-3.87zm25-24.99v-3.87L78.87%2050.03H75L100%2075zM31.1%200%2050%2018.93v-3.87L34.98%200h-3.87zm6.07%200L50%2012.82V8.96L41.04%200zm6.1%200L50%206.77V0h-6.72zM25%202.19%202.14%2025.04H25zm0%2022.85v22.8l22.81-22.8zM75%203.92l21.13%2021.12L75%2046.16%2053.87%2025.04zm0%202.19L56.06%2025.04l18.89%2018.88%2018.94-18.88L75%206.1zm0%203.92%2015.07%2015L75%2040.06%2059.98%2025.04zm0%202.18L62.17%2025.04%2075%2037.86l12.83-12.82L75%2012.2zm0%203.82%208.96%209L75%2033.95%2066.04%2025zm0%202.24-6.72%206.77L75%2031.76l6.77-6.72h-.05zM0%2031.09v3.87l15.02%2015.07h3.87zm50%200L31.1%2050.03h3.88L50%2034.96V31.1zM0%2037.2v3.87l8.91%208.96h3.92zm50%200L37.17%2050.03h3.87L50%2041.07zM0%2043.3v6.73h6.72zm50%200-6.72%206.73H50zm0%206.73v6.71l6.72-6.71zm8.96%200L50%2058.93v3.92l12.83-12.82zm6.06%200L50%2065.03v3.88l18.94-18.88zm16.09%200L100%2068.9v-3.87l-15.02-15zm6.11%200L100%2062.85v-3.92l-8.91-8.9zm6.06%200%206.72%206.71v-6.71zM75%2052.2%2052.19%2075H75zM75%2075v22.8L97.81%2075zM25%2053.9l21.13%2021.12L25%2096.13%203.87%2075.01zm0%202.2L6.1%2074.95l18.95%2018.88%2018.9-18.88L25%2056.08zm0%203.9%2015.02%2015.01L25%2090.03%209.98%2075zm0%202.19L12.17%2075%2025%2087.84%2037.83%2075%2025%2062.2zm0%203.87L33.96%2075%2025%2083.97%2016.04%2075zm0%202.23-6.72%206.72L25%2081.73l6.72-6.72L25%2068.3zm25%2012.83v3.87L65.02%20100h3.87zm50%200L81.1%20100h3.88L100%2084.99zm-50%206.06v3.86l8.96%208.96h3.87zm50%200L87.22%20100h3.87l8.91-8.96zm-50%206.1V100h6.72zm50%200L93.28%20100H100z%22%2F%3E%3C%2Fsvg%3E"); @@ -335,10 +335,10 @@ body { --color-leaflet-text: var(--color-background-dark); --color-leaflet-link: var(--color-background-dark); --color-leaflet-link-hover: var(--color-background-light); - --interlocked-hexagons-background: url("https://storage.yandexcloud.kz/sayauz-static/themes/ram/ram-background.webp"); + --interlocked-hexagons-background: url("https://cdn.saya.uz/static/themes/ram/ram-background.webp"); --interlocked-hexagons-background-repeat: repeat; --interlocked-hexagons-background-size: auto; - --squares-and-triangles-background: url("https://storage.yandexcloud.kz/sayauz-static/themes/ram/ram-sidebar.webp"); + --squares-and-triangles-background: url("https://cdn.saya.uz/static/themes/ram/ram-sidebar.webp"); --squares-and-triangles-background-repeat: repeat; --squares-and-triangles-background-width-coef: 5; --squares-and-triangles-background-height-coef: 15; @@ -390,7 +390,7 @@ body { --squares-and-triangles-background-repeat: repeat; --squares-and-triangles-background-width-coef: 5; --squares-and-triangles-background-height-coef: 5; - --split-right-background: url("https://storage.yandexcloud.kz/sayauz-static/themes/lilac/split-right-light.webp"); + --split-right-background: url("https://cdn.saya.uz/static/themes/lilac/split-right-light.webp"); } @media (prefers-color-scheme: dark) { @@ -406,7 +406,7 @@ body { --color-background-medium: var(--color-main-dark-medium); --color-background-light: var(--color-main-dark-soft); --color-sidebar-stroke: var(--color-main-dark-hard); - --split-right-background: url("https://storage.yandexcloud.kz/sayauz-static/themes/lilac/split-right-dark.webp"); + --split-right-background: url("https://cdn.saya.uz/static/themes/lilac/split-right-dark.webp"); } } @@ -855,6 +855,15 @@ form.crossable.htmx-request input { color: var(--color-main-medium) !important; } +.leaflet-marker-icon.marker-cluster { + color: var(--color-main-dark-hard) !important; +} + +.leaflet-attribution-flag { + visibility: hidden; + width: 0; +} + .home-page-heart { position: absolute; color: var(--color-pink-700); diff --git a/views/layouts/general-page.html b/views/layouts/general-page.html index e380ef3..908a78c 100644 --- a/views/layouts/general-page.html +++ b/views/layouts/general-page.html @@ -22,15 +22,23 @@ {{- end }} {{- end }} + + {{- end }} + + + + + - - - - - - - + + + + + + -
- - - - - +
+
- - diff --git a/views/partials/catalogue-blog-cards.html b/views/partials/catalogue-blog-cards.html index 799955f..b066a9e 100644 --- a/views/partials/catalogue-blog-cards.html +++ b/views/partials/catalogue-blog-cards.html @@ -2,7 +2,7 @@
- +
diff --git a/views/partials/global-map-widget.html b/views/partials/global-map-widget.html new file mode 100644 index 0000000..f50020f --- /dev/null +++ b/views/partials/global-map-widget.html @@ -0,0 +1,109 @@ +
+ + -- cgit v1.3.1+17