From e9353a66bf51486f702eaa0f591dea54c9bd4cd1 Mon Sep 17 00:00:00 2001 From: SayaAndy Date: Sun, 17 May 2026 17:13:32 +0700 Subject: refactor: rewrite localization for dynamic set and get feat: medley localnames feat: integrate package minor updates fix: on errors with blog client init write correct type --- views/messages/new-post.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'views/messages/new-post.html') diff --git a/views/messages/new-post.html b/views/messages/new-post.html index 98f0b52..e956253 100644 --- a/views/messages/new-post.html +++ b/views/messages/new-post.html @@ -1,5 +1,5 @@ {{ define "body" }} -

{{ .L.Mail.NewPost.Intro }}

+

{{ l $.Lang "Mail" "NewPost" "Intro" }}

@@ -9,7 +9,7 @@ - +
{{ .Post.Metadata.ShortDescription }}
{{ .L.Mail.NewPost.CapturedOn }} {{ .Post.Metadata.ActionDate }}{{ l $.Lang "Mail" "NewPost" "CapturedOn" }} {{ .Post.Metadata.ActionDate }}
{{ end }} -- cgit v1.3.1+13 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/messages/new-post.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+13