summaryrefslogtreecommitdiff
path: root/views
diff refs
from: back
to: back
| flip
diff options
context:
space:
mode:
Diffstat (limited to 'views')
-rw-r--r--views/layouts/general-page.html33
-rw-r--r--views/messages/new-post.html6
-rw-r--r--views/messages/verify-email.html10
-rw-r--r--views/pages/blog-catalogue.html20
-rw-r--r--views/pages/blog-page.html49
-rw-r--r--views/pages/global-map.html125
-rw-r--r--views/pages/home-page.html26
-rw-r--r--views/pages/unsubscribe-page.html2
-rw-r--r--views/pages/user-page.html24
-rw-r--r--views/partials/catalogue-blog-cards.html2
-rw-r--r--views/partials/general-page-body.html1
-rw-r--r--views/partials/global-map-widget.html109
12 files changed, 202 insertions, 205 deletions
diff --git a/views/layouts/general-page.html b/views/layouts/general-page.html
index 491c652..9220b7f 100644
--- a/views/layouts/general-page.html
+++ b/views/layouts/general-page.html
@@ -14,7 +14,7 @@
{{end}}
/>
{{- if eq .Property "og:title" }}
- <title>{{.Content}} // SAYA.UZ</title>
+ <title>{{.Content}}</title>
{{- end }} {{- if eq .Property "og:description" }}
<meta name="description" content="{{.Content}}" />
{{- end }} {{- if eq .Property "og:url" }}
@@ -22,15 +22,23 @@
{{- end }} {{- end }}
<link
rel="stylesheet"
- href="{{ .StaticStorageBaseUrl }}/fonts/fonts.css"
+ href="{{ .StaticStorage.BaseUrl }}/fonts/fonts.css"
/>
<link
rel="stylesheet"
- href="{{ .StaticStorageBaseUrl }}/libs/leaflet/1.9.4/leaflet.css"
+ href="{{ .StaticStorage.BaseUrl }}/libs/leaflet/1.9.4/leaflet.css"
/>
<link
rel="stylesheet"
- href="{{ .StaticStorageBaseUrl }}/libs/glightbox/3.3.0/css/glightbox.min.css"
+ href="{{ .StaticStorage.BaseUrl }}/libs/leaflet.markercluster/1.4.1/MarkerCluster.css"
+ />
+ <link
+ rel="stylesheet"
+ href="{{ .StaticStorage.BaseUrl }}/libs/leaflet.markercluster/1.4.1/MarkerCluster.Default.css"
+ />
+ <link
+ rel="stylesheet"
+ href="{{ .StaticStorage.BaseUrl }}/libs/glightbox/3.3.0/css/glightbox.min.css"
/>
<link rel="stylesheet" href="/output.css" />
<link
@@ -55,6 +63,11 @@
{{ . }}
</script>
{{- end }}
+ <script src="{{ .StaticStorage.BaseUrl }}/libs/htmx/2.0.6/htmx.min.js"></script>
+ <script src="{{ .StaticStorage.BaseUrl }}/libs/leaflet/1.9.4/leaflet.js"></script>
+ <script src="{{ .StaticStorage.BaseUrl }}/libs/protomaps-leaflet/5.0.0/dist/protomaps-leaflet.js"></script>
+ <script src="{{ .StaticStorage.BaseUrl }}/libs/leaflet.markercluster/1.4.1/leaflet.markercluster.js"></script>
+ <script src="{{ .StaticStorage.BaseUrl }}/libs/glightbox/3.3.0/js/glightbox.min.js"></script>
</head>
<body
@@ -160,8 +173,6 @@
}
</script>
- <script src="{{ .StaticStorageBaseUrl }}/libs/glightbox/3.3.0/js/glightbox.min.js"></script>
-
<script>
function sfc32(a, b, c, d) {
return function () {
@@ -342,7 +353,7 @@
const frameCenters = new Array(4);
for (i = 1; i <= 4; i++) {
let frame = document.createElement("img");
- frame.src = `{{ .StaticStorageBaseUrl }}/themes/ram/ram-frame${i}.webp`;
+ frame.src = `{{ .StaticStorage.BaseUrl }}/themes/ram/ram-frame${i}.webp`;
frame.classList.add(
"ram-frame",
"theme-decor",
@@ -419,10 +430,9 @@
mq.addEventListener('change', (e) => switchColorScheme(e.matches));
</script>
- <script src="{{ .StaticStorageBaseUrl }}/libs/htmx/2.0.6/htmx.min.js"></script>
- <script src="{{ .StaticStorageBaseUrl }}/libs/leaflet/1.9.4/leaflet.js"></script>
- <script src="{{ .StaticStorageBaseUrl }}/libs/imagesloaded/5.0.0/imagesloaded.pkgd.min.js"></script>
- <script src="{{ .StaticStorageBaseUrl }}/libs/packery/3.0.0/dist/packery.pkgd.min.js"></script>
+ <script src="{{ .StaticStorage.BaseUrl }}/libs/htmx/2.0.6/htmx.min.js"></script>
+ <script src="{{ .StaticStorage.BaseUrl }}/libs/imagesloaded/5.0.0/imagesloaded.pkgd.min.js"></script>
+ <script src="{{ .StaticStorage.BaseUrl }}/libs/packery/3.0.0/dist/packery.pkgd.min.js"></script>
<script>
// Enable fitWidth-like attribute for Packery. Source: https://codepen.io/desandro/pen/kVmLYz
@@ -659,6 +669,7 @@
hx-trigger="popstate from:window"
hx-target="#general-page-body"
hx-swap="innerHTML"
+ hx-include="#general-page-body .htmx-exit-trigger"
></div>
<footer
diff --git a/views/messages/new-post.html b/views/messages/new-post.html
index 98f0b52..4e586e2 100644
--- a/views/messages/new-post.html
+++ b/views/messages/new-post.html
@@ -1,15 +1,15 @@
{{ define "body" }}
-<p>{{ .L.Mail.NewPost.Intro }}</p>
+<p>{{ l $.Lang "Mail" "NewPost" "Intro" }}</p>
<table>
<tr>
- <td rowspan="3"><a href="https://{{ .ClientHost }}/{{ .Lang }}/blog/{{ .Post.FileName }}"><img src="{{ printf .ThumbnailBaseUrl .Post.Metadata.Thumbnail }}"></a></td>
+ <td rowspan="3"><a href="https://{{ .ClientHost }}/{{ .Lang }}/blog/{{ .Post.FileName }}"><img src="{{ printf .PhotoStorage.Thumbnail320p.BaseUrl .Post.Metadata.Thumbnail }}"></a></td>
<td class="darkened" style="font-size: 24px"><a style="color: #273de1 !important;" href="https://{{ .ClientHost }}/{{ .Lang }}/blog/{{ .Post.FileName }}">{{ .Post.Metadata.Title }}</a></td>
</tr>
<tr>
<td class="darkened" style="font-size: 16px">{{ .Post.Metadata.ShortDescription }}</td>
</tr>
<tr>
- <td class="darkened" style="font-size: 16px">{{ .L.Mail.NewPost.CapturedOn }} {{ .Post.Metadata.ActionDate }}</td>
+ <td class="darkened" style="font-size: 16px">{{ l $.Lang "Mail" "NewPost" "CapturedOn" }} {{ .Post.Metadata.ActionDate }}</td>
</tr>
</table>
{{ end }}
diff --git a/views/messages/verify-email.html b/views/messages/verify-email.html
index dd6ef33..e6fff76 100644
--- a/views/messages/verify-email.html
+++ b/views/messages/verify-email.html
@@ -1,10 +1,10 @@
{{ define "body" }}
-<p>{{ .L.Mail.VerifyEmail.Welcome }}</p>
-<p>{{ .L.Mail.VerifyEmail.Intro }}</p>
+<p>{{ l $.Lang "Mail" "VerifyEmail" "Welcome" }}</p>
+<p>{{ l $.Lang "Mail" "VerifyEmail" "Intro" }}</p>
<ol>
- <li>{{ .L.Mail.VerifyEmail.GotoLink }} <a href="https://{{ .ClientHost }}/{{ .Lang }}/user?email_code={{ .VerificationCode }}" class="outlier">&gt;&gt;&gt;</a></li>
- <li>{{ .L.Mail.VerifyEmail.InputCode }} <span class="outlier">{{ .VerificationCode }}</span><span></li>
+ <li>{{ l $.Lang "Mail" "VerifyEmail" "GotoLink" }} <a href="https://{{ .ClientHost }}/{{ .Lang }}/user?email_code={{ .VerificationCode }}" class="outlier">&gt;&gt;&gt;</a></li>
+ <li>{{ l $.Lang "Mail" "VerifyEmail" "InputCode" }} <span class="outlier">{{ .VerificationCode }}</span><span></li>
</ol>
-<p>{{ .L.Mail.VerifyEmail.IfRandom }}</p>
+<p>{{ l $.Lang "Mail" "VerifyEmail" "IfRandom" }}</p>
<a href="https://{{ .ClientHost }}" class="outlier">{{ .ClientHost }}</a>
{{ end }} \ No newline at end of file
diff --git a/views/pages/blog-catalogue.html b/views/pages/blog-catalogue.html
index 4a7d9bf..b2bb0a3 100644
--- a/views/pages/blog-catalogue.html
+++ b/views/pages/blog-catalogue.html
@@ -51,57 +51,57 @@
class="tags-list relative flex flex-col w-full bg-paper bg-background-light">
<div class="flex flex-col overflow-y-auto">
<fieldset>
- <legend class="font-bold w-full text-center">{{ .L.BlogSearch.OrderByHeader }}</legend>
+ <legend class="font-bold w-full text-center">{{ l $.Lang "BlogSearch" "OrderByHeader" }}</legend>
<div class="md:flex flex-col grid grid-cols-3 grid-rows-2 grid-flow-col">
<div>
<label class="flex justify-start gap-1 items-center">
<input type="radio" id="sortTitleAsc" name="sort" value="titleAsc" class="bg-accent-light border-transparent text-accent-deep focus:border-transparent focus:bg-accent-light focus:ring-1 focus:ring-offset-2 focus:ring-accent-deep" {{ if eq .QuerySort "titleAsc" }}checked{{ end }}>
- {{ .L.BlogSearch.TitleOrdered }}
+ {{ l $.Lang "BlogSearch" "TitleOrdered" }}
<svg viewBox="0 0 24 24" class="h-8"><use href="#icon-arrange-letter-asc"/></svg>
</label>
</div>
<div>
<label class="flex justify-start gap-1 items-center">
<input type="radio" id="sortTitleDesc" name="sort" value="titleDesc" class="bg-accent-light border-transparent text-accent-deep focus:border-transparent focus:bg-accent-light focus:ring-1 focus:ring-offset-2 focus:ring-accent-deep" {{ if eq .QuerySort "titleDesc" }}checked{{ end }}>
- {{ .L.BlogSearch.TitleOrdered }}
+ {{ l $.Lang "BlogSearch" "TitleOrdered" }}
<svg viewBox="0 0 24 24" class="h-8"><use href="#icon-arrange-letter-desc"/></svg>
</label>
</div>
<div>
<label class="flex justify-start gap-1 items-center">
<input type="radio" id="sortActionDateAsc" name="sort" value="actionDateAsc" class="bg-accent-light border-transparent text-accent-deep focus:border-transparent focus:bg-accent-light focus:ring-1 focus:ring-offset-2 focus:ring-accent-deep" {{ if eq .QuerySort "actionDateAsc" }}checked{{ end }}>
- {{ .L.BlogSearch.ActionDateOrdered }}
+ {{ l $.Lang "BlogSearch" "ActionDateOrdered" }}
<svg viewBox="0 0 24 24" class="h-8"><use href="#icon-arrange-number-asc"/></svg>
</label>
</div>
<div>
<label class="flex justify-start gap-1 items-center">
<input type="radio" id="sortActionDateDesc" name="sort" value="actionDateDesc" class="bg-accent-light border-transparent text-accent-deep focus:border-transparent focus:bg-accent-light focus:ring-1 focus:ring-offset-2 focus:ring-accent-deep" {{ if eq .QuerySort "actionDateDesc" }}checked{{ end }}>
- {{ .L.BlogSearch.ActionDateOrdered }}
+ {{ l $.Lang "BlogSearch" "ActionDateOrdered" }}
<svg viewBox="0 0 24 24" class="h-8"><use href="#icon-arrange-number-desc"/></svg>
</label>
</div>
<div>
<label class="flex justify-start gap-1 items-center">
<input type="radio" id="sortPublicationDateAsc" name="sort" value="publicationDateAsc" class="bg-accent-light border-transparent text-accent-deep focus:border-transparent focus:bg-accent-light focus:ring-1 focus:ring-offset-2 focus:ring-accent-deep" {{ if eq .QuerySort "publicationDateAsc" }}checked{{ end }}>
- {{ .L.BlogSearch.PublicationDateOrdered }}
+ {{ l $.Lang "BlogSearch" "PublicationDateOrdered" }}
<svg viewBox="0 0 24 24" class="h-8"><use href="#icon-arrange-number-asc"/></svg>
</label>
</div>
<div>
<label class="flex justify-start gap-1 items-center">
<input type="radio" id="sortPublicationDateDesc" name="sort" value="publicationDateDesc" class="bg-accent-light border-transparent text-accent-deep focus:border-transparent focus:bg-accent-light focus:ring-1 focus:ring-offset-2 focus:ring-accent-deep" {{ if eq .QuerySort "publicationDateDesc" }}checked{{ end }}>
- {{ .L.BlogSearch.PublicationDateOrdered }}
+ {{ l $.Lang "BlogSearch" "PublicationDateOrdered" }}
<svg viewBox="0 0 24 24" class="h-8"><use href="#icon-arrange-number-desc"/></svg>
</label>
</div>
</div>
</fieldset>
<fieldset class="mt-1">
- <legend class="font-bold w-full text-center">{{ .L.BlogSearch.TagsHeader }}</legend>
+ <legend class="font-bold w-full text-center">{{ l $.Lang "BlogSearch" "TagsHeader" }}</legend>
<div class="md:flex flex-col grid grid-cols-3 xs:grid-cols-4 sm:grid-cols-5 grid-flow-row-dense">
<div class="m-1">
- <label class="font-bold"><input type="checkbox" id="tagsAllCheckbox" onclick="selectAll();" class="bg-accent-light rounded border-transparent text-accent-deep focus:border-transparent focus:bg-background-dark focus:ring-1 focus:ring-offset-2 focus:ring-accent-deep"> {{ .L.BlogSearch.ChooseAllTags }}</label>
+ <label class="font-bold"><input type="checkbox" id="tagsAllCheckbox" onclick="selectAll();" class="bg-accent-light rounded border-transparent text-accent-deep focus:border-transparent focus:bg-background-dark focus:ring-1 focus:ring-offset-2 focus:ring-accent-deep"> {{ l $.Lang "BlogSearch" "ChooseAllTags" }}</label>
</div>
{{- range .Tags }}
<div class="m-1">
@@ -128,7 +128,7 @@
<div class="relative flex grow h-full">
<div class="absolute w-full h-full inset-0 inset-shadow-[0_0_0.4rem_black] pointer-events-none z-20"></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"
+ <div hx-get="/api/v1/blog-search" hx-vals='js:{lang: "{{ .Lang }}", tz: clientTimeZone, highlight: "{{ .PreviousBlogPage }}"}' hx-target="this" hx-swap="innerHTML" hx-trigger="load" hx-include=".tags-list"
class="blog-cards relative grow flex flex-col overflow-y-auto bg-paper bg-background-light pr-2">
Loading...
</div>
diff --git a/views/pages/blog-page.html b/views/pages/blog-page.html
index 2a1d5d4..c02c3f5 100644
--- a/views/pages/blog-page.html
+++ b/views/pages/blog-page.html
@@ -1,21 +1,22 @@
{{ define "body" }}
+<input class="htmx-exit-trigger" type="hidden" name="codename" value="{{ .Codename }}">
<div class="sticky top-0 left-0 w-full h-[100cqb] -mb-[100cqb] inset-shadow-[0_0_0.4rem_black] pointer-events-none z-20"></div>
<article class="relative bg-paper bg-background-light flex flex-col px-8 py-4 overflow-y-auto">
<div class="flex flex-col sm:flex-row h-[30cqb] sm:h-[15cqb]">
<div class="grow shrink-2 flex-1 overflow-y-auto -ml-8 -mt-4 {{if .Medley}}max-sm:-mr-8{{else}}-mr-8{{end}} z-1 shadow-elevation-2">
- <div class="multitone min-h-full" style="--multitone-bg: url({{ printf $.ThumbnailBaseUrl .Thumbnail }});">
+ <div class="multitone min-h-full" style="--multitone-bg: url({{ printf $.PhotoStorage.Thumbnail560p.BaseUrl .Thumbnail }});">
<div class="ml-8 py-4">
<h1 class="max-xs:flex flex-row content-center [@media(max-height:32rem)]:block hidden font-gentium text-2xl font-bold italic text-main-hard tracking-[.0125rem] mb-1">
<div hx-get="/api/v1/like" hx-target="this" hx-swap="outerHTML" hx-trigger="load"></div>
{{ .Title }}
</h1>
<p class="block grow text-lg font-gentium text-secondary">
- <b>{{ .L.Metadata.Published }}</b>:
+ <b>{{ l $.Lang "Metadata" "Published" }}</b>:
<time datetime="{{ .PublishedDate }}" hx-get="/api/v1/tz" hx-vals='js:{timestamp: "{{ .PublishedDate }}", tz: clientTimeZone}' hx-target="this" hx-swap="innerHTML" hx-trigger="load">
{{ .PublishedDate }}
</time>
</p>
- <p class="block grow text-lg font-gentium text-secondary"><b>{{ .L.Metadata.Action }}</b>: {{ .ActionDate }}</p>
+ <p class="block grow text-lg font-gentium text-secondary"><b>{{ l $.Lang "Metadata" "Action" }}</b>: {{ .ActionDate }}</p>
<p class="block grow text-md font-gentium font-thin text-main-hard">{{ .ShortDescription }}</p>
</div>
</div>
@@ -24,7 +25,7 @@
{{- if .Medley }}
<div class="overflow-y-auto grow-2 shrink-0 flex-1 bg-paper bg-background-dark shadow-elevation-2 -mr-8 sm:-mt-4 max-sm:-ml-8 z-2">
<h2 class="text-2xl font-gentium font-extrabold text-main-hard tracking-[.0125rem] ml-2">
- {{ .Medley }}
+ {{ l .Lang "Medleys" .Medley }}
</h2>
<hr class="block border-t-2 my-1 border-dotted border-main-hard w-full">
<div hx-get="/api/v1/blog-search" hx-vals='js:{lang: "{{ .Lang }}", tz: clientTimeZone, medley: "{{ .Medley }}", sort: "medley", hideTags: true, hidePublishedTime: true, highlight: "{{ .Codename }}"}' hx-target="this" hx-swap="innerHTML" hx-trigger="load"
@@ -38,46 +39,12 @@
{{ .ParsedMarkdown }}
{{- if .MapLocationX }}
<hr class="border-t-3 border-dotted border-main-hard mt-1 mb-2 w-[80%] ml-auto mr-auto">
- <div id="map-container" class="relative p-1 flex-none ml-auto mr-auto w-[80%] lg:w-[60%] h-[30dvh] md:h-[40dvh]"></div>
+ <div id="map-outer-container" class="relative p-1 flex-none ml-auto mr-auto w-[80%] lg:w-[60%] h-[30dvh] md:h-[40dvh]"
+ hx-get="/api/v1/map" hx-vals='{"lang": "{{ .Lang }}", "codename": "{{ .Codename }}", "zoom": 8}' hx-target="this" hx-swap="innerHTML" hx-trigger="load">
+ </div>
<hr class="border-t-3 border-dotted border-main-hard mt-1 mb-2 w-[80%] ml-auto mr-auto">
<script>
- function initLocationMap(id, x, y, relativeErrorMeters = 0) {
- map = L.map(id).setView([x, y], 8);
-
- L.tileLayer('https://tiles.stadiamaps.com/tiles/outdoors/{z}/{x}/{y}{r}.png', {
- maxZoom: 20,
- attribution: '&copy; <a href="https://stadiamaps.com/" target="_blank">Stadia Maps</a>, &copy; <a href="https://openmaptiles.org/" target="_blank">OpenMapTiles</a> &copy; <a href="https://www.openstreetmap.org/copyright" target="_blank">OpenStreetMap</a>',
- }).addTo(map);
-
- if (relativeErrorMeters != 0) {
- var circle = L.circle([x, y], {
- color: '#8a9d8a',
- fillColor: '#8a9d8a',
- fillOpacity: 0.15,
- radius: relativeErrorMeters
- }).addTo(map);
- }
-
- var marker = L.marker([x, y], {
- title: '{{ .Title }}',
- }).addTo(map)
- .bindPopup('<span><b>{{ .Title }}</b><br><a href="https://www.openstreetmap.org/#map=13/{{ .MapLocationX }}/{{ .MapLocationY }}">{{ .MapLocationX }}, {{ .MapLocationY }}</a></span>')
- .openPopup();
- }
-
- if (map) {
- map.remove();
- map = null;
- }
-
- setTimeout(() => initLocationMap(
- 'map-container',
- {{ .MapLocationX }},
- {{ .MapLocationY }},
- {{ .MapLocationAreaMeters }}
- ), 1000);
-
var lightbox = GLightbox({
selector: '.glightbox',
moreLength: 0
diff --git a/views/pages/global-map.html b/views/pages/global-map.html
index 788eac9..4d1853f 100644
--- a/views/pages/global-map.html
+++ b/views/pages/global-map.html
@@ -3,23 +3,23 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
- <meta name="description" content="{{ .L.GlobalMap.Description }}" />
- <title>{{ .L.GlobalMap.Header }} // SAYA.UZ</title>
- <meta property="og:title" content="{{ .L.GlobalMap.Header }}" />
+ <meta name="description" content="{{ l $.Lang "GlobalMap" "Description" }}" />
+ <title>{{ l $.Lang "GlobalMap" "Header" }} // SAYA.UZ</title>
+ <meta property="og:title" content="{{ l $.Lang "GlobalMap" "Header" }}" />
<meta
property="og:description"
- content="{{ .L.GlobalMap.Description }}"
+ content="{{ l $.Lang "GlobalMap" "Description" }}"
/>
<meta
property="og:url"
content="{{ .CanonicalEndpoint }}/{{ .Lang }}/map"
/>
<meta property="og:type" content="site" />
- <title>{{ .L.GlobalMap.Header }} // SAYA.UZ</title>
+ <title>{{ l $.Lang "GlobalMap" "Header" }} // SAYA.UZ</title>
<link rel="canonical" href="{{ .CanonicalEndpoint }}/{{ .Lang }}/map" />
<link
rel="stylesheet"
- href="{{ .StaticStorageBaseUrl }}/fonts/fonts.css"
+ href="{{ .StaticStorage.BaseUrl }}/fonts/fonts.css"
/>
{{ block "header" . }}{{ end }}
<link rel="stylesheet" href="/output.css" />
@@ -42,16 +42,20 @@
/>
<link
rel="stylesheet"
- href="{{ .StaticStorageBaseUrl }}/libs/leaflet/1.9.4/leaflet.css"
+ href="{{ .StaticStorage.BaseUrl }}/libs/leaflet/1.9.4/leaflet.css"
/>
<link
rel="stylesheet"
- href="{{ .StaticStorageBaseUrl }}/libs/leaflet.markercluster/1.4.1/MarkerCluster.css"
+ href="{{ .StaticStorage.BaseUrl }}/libs/leaflet.markercluster/1.4.1/MarkerCluster.css"
/>
<link
rel="stylesheet"
- href="{{ .StaticStorageBaseUrl }}/libs/leaflet.markercluster/1.4.1/MarkerCluster.Default.css"
+ href="{{ .StaticStorage.BaseUrl }}/libs/leaflet.markercluster/1.4.1/MarkerCluster.Default.css"
/>
+ <script src="{{ .StaticStorage.BaseUrl }}/libs/htmx/2.0.6/htmx.min.js"></script>
+ <script src="{{ .StaticStorage.BaseUrl }}/libs/leaflet/1.9.4/leaflet.js"></script>
+ <script src="{{ .StaticStorage.BaseUrl }}/libs/protomaps-leaflet/5.0.0/dist/protomaps-leaflet.js"></script>
+ <script src="{{ .StaticStorage.BaseUrl }}/libs/leaflet.markercluster/1.4.1/leaflet.markercluster.js"></script>
</head>
<body
@@ -216,20 +220,14 @@
</div>
</nav>
- <div
- id="map-container"
- class="bg-paper bg-background-dark flex z-10 w-full h-full"
- ></div>
-
- <script src="{{ .StaticStorageBaseUrl }}/libs/htmx/2.0.6/htmx.min.js"></script>
- <script src="{{ .StaticStorageBaseUrl }}/libs/leaflet/1.9.4/leaflet.js"></script>
- <script src="{{ .StaticStorageBaseUrl }}/libs/leaflet.markercluster/1.4.1/leaflet.markercluster.js"></script>
+ <div id="map-outer-container" class="bg-paper bg-background-dark flex z-10 w-full h-full"
+ hx-get="/api/v1/map" hx-vals='{"lang": "{{ .Lang }}", "codename": "{{ .Codename }}", "zoom": 4, "zoomPosition": "topright"}' hx-target="this" hx-swap="innerHTML" hx-trigger="load">
+ </div>
<script>
const themeWheel = document.getElementById("theme-wheel");
const themeButton = document.getElementById("sidebar-theme-button");
const themeIcons = document.querySelectorAll(".theme-icon");
- const THUMB_BASE = "{{ .ThumbnailBaseUrl }}";
themeIcons.forEach((icon) => {
if (icon.getAttribute("data-theme") == savedTheme) {
@@ -250,6 +248,7 @@
function positionThemeIcons() {
const sliceAngle = 360 / themeIcons.length;
+ const themeWheelRadius = convertRemToPixels(6);
themeIcons.forEach((icon, index) => {
const startAngle = index * sliceAngle;
@@ -367,95 +366,5 @@
}
});
</script>
-
- <script>
- var map;
- var markers = L.markerClusterGroup();
-
- function createCustomIcon(color, borderColor = "var(--color-main-soft)") {
- const svgIcon = `
- <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
- <path d="M12 1C7.5 1 4 4.5 4 9c0 6.5 8 14 8 14s8-7.5 8-14c0-4.5-3.5-8-8-8zm0 11c-1.5 0-3-1.5-3-3s1.5-3 3-3 3 1.5 3 3-1.5 3-3 3z"
- fill="${color}"
- stroke="${borderColor}"
- stroke-width="1"
- stroke-linejoin="round"/>
- </svg>
- `;
-
- return L.divIcon({
- html: svgIcon,
- className: 'custom-svg-marker',
- iconSize: [32, 32],
- iconAnchor: [16, 32],
- popupAnchor: [0, -32]
- });
- }
-
- function initLocationMap() {
- map = L.map('map-container').setView([{{ .MapLocationLat }}, {{ .MapLocationLong }}], 4);
-
- L.tileLayer('https://tiles.stadiamaps.com/tiles/outdoors/{z}/{x}/{y}{r}.png', {
- maxZoom: 20,
- attribution: '&copy; <a href="https://stadiamaps.com/" target="_blank">Stadia Maps</a>, &copy; <a href="https://openmaptiles.org/" target="_blank">OpenMapTiles</a> &copy; <a href="https://www.openstreetmap.org/copyright" target="_blank">OpenStreetMap</a>',
- zoomControl: false
- }).addTo(map);
-
- L.control.zoom({
- position: 'topright'
- }).addTo(map);
-
- map.addLayer(markers);
- }
-
- function markerToHsl(str, newCoef) {
- let hash = 0;
- for (let i = 0; i < str.length / 2; i++) {
- hash = str.charCodeAt(i) + ((hash << 5) - hash);
- hash = str.charCodeAt(str.length - i - 1) + ((hash << 5) - hash);
- hash %= 360;
- }
-
- return [hash, (20 + newCoef * 80).toFixed(0), (20 + newCoef * 75).toFixed(0)];
- }
-
- function mapAddMarker(x, y, relativeErrorMeters = 0, title = "", link = "", thumbnail = "", newCoef = 1) {
- const [h, s, l] = markerToHsl(title, newCoef);
- const color = `hsl(${h} ${s}% ${l}%)`;
-
- if (relativeErrorMeters != 0) {
- var circle = L.circle([x, y], {
- color: color,
- fillColor: color,
- fillOpacity: 0.15,
- radius: relativeErrorMeters
- }).addTo(map);
- }
-
- var marker = L.marker([x, y], {
- icon: createCustomIcon(color),
- title: title,
- }).bindPopup(`
- <div class="flex flex-row justify-center justify-items-center">
- <img onclick="location.href='${link}';" class="cursor-pointer object-cover rounded-[10%] select-none w-12 h-12 mr-1" src="${THUMB_BASE.replace('%s', thumbnail)}">
- <span><b><a href="${link}">${title}</a></b><br><a href="https://www.openstreetmap.org/#map=13/${x}/${y}">${x}, ${y}</a></span>
- </div>`);
-
- markers.addLayer(marker);
- }
-
- document.addEventListener('DOMContentLoaded', () => {
- initLocationMap();
- {{- range .MapMarkers }}
- mapAddMarker({{ .Lat }}, {{ .Long }}, {{ .AccuracyMeters }}, {{ .Title }}, {{ .PageLink }}, {{ .Thumbnail }}, {{ fdiv .Index (len $.MapMarkers) }});
- {{- end }}
- });
-
- window.addEventListener('resize', function() {
- setTimeout(() => {
- map.invalidateSize();
- }, 100);
- });
- </script>
</body>
</html>
diff --git a/views/pages/home-page.html b/views/pages/home-page.html
index 6e026aa..e89be39 100644
--- a/views/pages/home-page.html
+++ b/views/pages/home-page.html
@@ -23,17 +23,17 @@
<div class="flex flex-col justify-start items-start bg-paper bg-background-dark mb-8 shadow-[0.4rem_0.4rem_0.4rem_black]">
<p class="text-3xl/loose sm:text-4xl/loose lg:text-5xl/loose tracking-widest uppercase w-full font-m-plus font-thin italic text-left
border-l-4 border-solid border-background-dark
- bg-linear-to-r from-background-dark to-background-light">{{ .L.HomePage.Hymn1 }}</p>
+ bg-linear-to-r from-background-dark to-background-light">{{ l $.Lang "HomePage" "Hymn1" }}</p>
<hr class="w-full border-t-2 border-dotted border-main-hard mb-1">
- <p class="text-xl/loose sm:text-2xl/loose lg:text-3xl/loose -indent-8 ml-12 p-1">{{ .L.HomePage.Hymn2 }}</p>
- <p class="text-xl/loose sm:text-2xl/loose lg:text-3xl/loose -indent-8 ml-12 p-1">{{ .L.HomePage.Hymn3 }}</p>
- <p class="text-xl/loose sm:text-2xl/loose lg:text-3xl/loose -indent-8 ml-12 p-1">{{ .L.HomePage.Hymn4 }}</p>
+ <p class="text-xl/loose sm:text-2xl/loose lg:text-3xl/loose -indent-8 ml-12 p-1">{{ l $.Lang "HomePage" "Hymn2" }}</p>
+ <p class="text-xl/loose sm:text-2xl/loose lg:text-3xl/loose -indent-8 ml-12 p-1">{{ l $.Lang "HomePage" "Hymn3" }}</p>
+ <p class="text-xl/loose sm:text-2xl/loose lg:text-3xl/loose -indent-8 ml-12 p-1">{{ l $.Lang "HomePage" "Hymn4" }}</p>
</div>
<div class="flex flex-col justify-center items-center">
<p class="text-xl sm:text-2xl lg:text-3xl p-1 w-full font-m-plus font-thin italic text-left
border-l-1.5 border-solid border-background-dark
- bg-linear-to-r from-background-dark to-background-light">{{ .L.HomePage.DidYouKnowThat }}</p>
+ bg-linear-to-r from-background-dark to-background-light">{{ l $.Lang "HomePage" "DidYouKnowThat" }}</p>
<hr class="w-full border-t-2 border-dotted border-main-hard mb-1">
<ul class="w-full text-left list-[circle]">
<li class="ml-4 mb-1">{{ index .FunFacts 0 }}</li>
@@ -47,7 +47,7 @@
<div class="flex flex-col justify-center items-start mb-4">
<p class="text-xl sm:text-2xl lg:text-3xl p-1 w-full font-m-plus font-thin italic text-left
border-l-1.5 border-solid border-background-dark
- bg-linear-to-r from-background-dark to-background-light">{{ .L.HomePage.Contacts }}</p>
+ bg-linear-to-r from-background-dark to-background-light">{{ l $.Lang "HomePage" "Contacts" }}</p>
<hr class="w-full border-t-2 border-dotted border-main-hard mb-1">
<a href="https://t.me/EarlInisMona">
<svg class="w-4 h-4 mr-1 inline" viewBox="0 0 24 24"><use href="#icon-telegram"/></svg>
@@ -122,22 +122,22 @@
<div class="flex flex-col justify-center items-center">
<p class="text-xl sm:text-2xl lg:text-3xl p-1 w-full font-m-plus font-thin italic text-left
border-l-1.5 border-solid border-color-background-dark
- bg-linear-to-r from-background-dark to-background-light">{{ .L.HomePage.SidebarDescription }}</p>
+ bg-linear-to-r from-background-dark to-background-light">{{ l $.Lang "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/50 [&>*:nth-child(4n+3)]:bg-background-medium/50" style="container-type: inline-size;">
<svg viewBox="0 0 24 24" class="h-full w-[15cqi] context-center text-main-hard"><use href="#icon-back"/></svg>
- <p class="p-1 w-[85cqi]">{{ .L.HomePage.BackDescription }}</p>
+ <p class="p-1 w-[85cqi]">{{ l $.Lang "HomePage" "BackDescription" }}</p>
<svg viewBox="0 0 24 24" class="h-full w-[15cqi] context-center text-main-hard"><use href="#icon-logo"/></svg>
- <p class="p-1 w-[85cqi]">{{ .L.HomePage.HomePageDescription }}</p>
+ <p class="p-1 w-[85cqi]">{{ l $.Lang "HomePage" "HomePageDescription" }}</p>
<svg viewBox="0 0 24 24" class="h-full w-[15cqi] context-center text-main-hard"><use href="#icon-newspaper"/></svg>
- <p class="p-1 w-[85cqi]">{{ .L.HomePage.BlogSearchDescription }}</p>
+ <p class="p-1 w-[85cqi]">{{ l $.Lang "HomePage" "BlogSearchDescription" }}</p>
<svg viewBox="0 0 24 24" class="h-full w-[15cqi] context-center text-main-hard"><use href="#icon-map"/></svg>
- <p class="p-1 w-[85cqi]">{{ .L.HomePage.MarkerMapDescription }}</p>
+ <p class="p-1 w-[85cqi]">{{ l $.Lang "HomePage" "MarkerMapDescription" }}</p>
<svg viewBox="0 0 24 24" class="h-full w-[15cqi] context-center text-main-hard"><use href="#icon-palette"/></svg>
- <p class="p-1 w-[85cqi]">{{ .L.HomePage.ThemeSwitchDescription }}</p>
+ <p class="p-1 w-[85cqi]">{{ l $.Lang "HomePage" "ThemeSwitchDescription" }}</p>
<svg viewBox="0 0 24 24" class="h-full w-[15cqi] context-center text-main-hard"><use href="#icon-account"/></svg>
- <p class="p-1 w-[85cqi]">{{ .L.HomePage.AccountDescription }}</p>
+ <p class="p-1 w-[85cqi]">{{ l $.Lang "HomePage" "AccountDescription" }}</p>
</div>
</div>
</div>
diff --git a/views/pages/unsubscribe-page.html b/views/pages/unsubscribe-page.html
index 9a78488..12ff1f0 100644
--- a/views/pages/unsubscribe-page.html
+++ b/views/pages/unsubscribe-page.html
@@ -21,7 +21,7 @@
href="/favicon.ico"
type="image/x-icon"
/>
- <title>{{ .L.UnsubscribePage.Header }} // SAYA.UZ</title>
+ <title>{{ l $.Lang "UnsubscribePage" "Header" }} // SAYA.UZ</title>
<style>
.bg-paper {
background-image: url(data:image/webp;base64,UklGRi4BAABXRUJQVlA4ICIBAABQCQCdASqAAIAAPm02lUmkIqIkIImIgA2JaW3rMFmGDAOKLAoJtP591ByFR74Tun2DP+Lygpfsz5FH7+cKgxi2Islfd03i5AJdXUfU0SDc8SXYAAD++hlzeYAJWQEF8ZdkJdlcA+5btZg0FMGaso8SHoBph0qAOQysElJ5C5SJFNoKIV1J550UyL7Y9Gh0/c/uzLnBmr8lvz7k1WeA81H4S5ViU/wBqa7aM1m8D9rDtrk8cSTqx+xWF6MS8UfZGSsks6CT/igtgv6syFN9uNA3LjnjiCJKYOvFcMkX+jB2578GWVo3nyLaM1QNPYCxn3TiUbnf7U0MdD2NsBpg1+Jd1wu6yW/U+goN+IQS6Nt4RMWltVcZHlxrneKJi0SobO0AAA==);
diff --git a/views/pages/user-page.html b/views/pages/user-page.html
index 0dd006a..dc4966b 100644
--- a/views/pages/user-page.html
+++ b/views/pages/user-page.html
@@ -6,16 +6,16 @@
<div class="flex flex-row w-full mb-4 z-21">
<div class="flex flex-col w-full sm:flex-3/5 grow-0">
<label class="block text-main-medium font-bold mb-1 z-22">
- {{ .L.UserProfile.EmailHeader }}
+ {{ l $.Lang "UserProfile" "EmailHeader" }}
</label>
<input class="bg-background-medium appearance-none border-background-medium rounded ml-6 mr-4 py-2 px-4 text-main-medium leading-tight inset-shadow-[0_0_0.4rem_black] focus:outline-none focus:bg-background-light focus:text-main-hard z-22"
- id="email-input" name="email" type="text" value="{{ .Email }}" placeholder="{{ .L.UserProfile.TypeEmail }}" maxlength="64"
+ id="email-input" name="email" type="text" value="{{ .Email }}" placeholder="{{ l $.Lang "UserProfile" "TypeEmail" }}" maxlength="64"
data-validated-email="{{ .Email }}" onchange="checkIfValidated(this);">
</div>
</div>
<button class="w-max mx-auto bg-main-hard hover:bg-main-medium active:bg-main-soft active:inset-shadow-[0.2em_0.2em_0.2rem_black] transition-colors transition-300 text-background-light font-bold py-2 px-4 rounded z-22"
hx-post="/api/v1/email/send-verification-code" hx-target="#email-message" hx-swap="outerHTML" hx-indicator="#email-form">
- {{ .L.UserProfile.SendCodeButton }}
+ {{ l $.Lang "UserProfile" "SendCodeButton" }}
</button>
</form>
<div id="email-message" class="bg-paper bg-background-dark text-main-soft z-26 w-full inset-shadow-[0_0_0.4rem_black] py-2 px-4 text-center"></div>
@@ -27,7 +27,7 @@
<div class="flex flex-row w-full mb-4 z-21">
<div class="flex flex-col w-full sm:flex-2/5 grow-0">
<label class="block text-main-medium font-bold ml-1 z-22">
- {{ .L.UserProfile.VerificationCodeHeader }}
+ {{ l $.Lang "UserProfile" "VerificationCodeHeader" }}
</label>
<input class="bg-background-medium appearance-none border-background-medium rounded ml-6 mr-4 py-2 px-4 text-main-medium leading-tight inset-shadow-[0_0_0.4rem_black] focus:outline-none focus:bg-background-light focus:text-main-hard z-22"
name="email_code" type="text" value="{{ .EmailCode }}" placeholder="0123456789ABCDEF" maxlength="16" autocapitalize="characters">
@@ -35,7 +35,7 @@
</div>
<button class="w-max mx-auto bg-main-hard hover:bg-main-medium active:bg-main-soft active:inset-shadow-[0.2em_0.2em_0.2rem_black] transition-colors transition-300 text-background-light font-bold py-2 px-4 rounded z-22"
hx-post="/api/v1/email/verify" hx-target="#verification-message" hx-swap="outerHTML" hx-indicator="#email-verification-form">
- {{ .L.UserProfile.VerifyButton }}
+ {{ l $.Lang "UserProfile" "VerifyButton" }}
</button>
</form>
<div id="verification-message" class="bg-paper bg-background-dark text-main-soft z-26 w-full inset-shadow-[0_0_0.4rem_black] py-2 px-4 text-center"></div>
@@ -47,17 +47,17 @@
<form id="subs-form" class="w-full mb-2 flex flex-col relative crossable">
<div class="flex flex-col w-full mb-4 z-21">
<label class="block text-main-medium font-bold mb-1 z-22">
- {{ .L.UserProfile.SubscriptionHeader }}
+ {{ l $.Lang "UserProfile" "SubscriptionHeader" }}
</label>
<div class="flex flex-col sm:flex-row w-full">
<div class="m-1 w-1/3">
- <label><input class="mr-1" type="radio" id="tagsNone" name="tags" value="none" {{ if eq .TagsPicked "none" }}checked{{ end }} onclick="toggleTagsPick(this);">{{ .L.UserProfile.TagsNone }}</label>
+ <label><input class="mr-1" type="radio" id="tagsNone" name="tags" value="none" {{ if eq .TagsPicked "none" }}checked{{ end }} onclick="toggleTagsPick(this);">{{ l $.Lang "UserProfile" "TagsNone" }}</label>
</div>
<div class="m-1 w-1/3">
- <label><input class="mr-1" type="radio" id="tagsAll" name="tags" value="all" {{ if eq .TagsPicked "all" }}checked{{ end }} onclick="toggleTagsPick(this);">{{ .L.UserProfile.TagsAll }}</label>
+ <label><input class="mr-1" type="radio" id="tagsAll" name="tags" value="all" {{ if eq .TagsPicked "all" }}checked{{ end }} onclick="toggleTagsPick(this);">{{ l $.Lang "UserProfile" "TagsAll" }}</label>
</div>
<div class="m-1 w-1/3">
- <label><input class="mr-1" type="radio" id="tagsSpecific" name="tags" value="specific" {{ if eq .TagsPicked "specific" }}checked{{ end }} onclick="toggleTagsPick(this);">{{ .L.UserProfile.TagsSpecific }}</label>
+ <label><input class="mr-1" type="radio" id="tagsSpecific" name="tags" value="specific" {{ if eq .TagsPicked "specific" }}checked{{ end }} onclick="toggleTagsPick(this);">{{ l $.Lang "UserProfile" "TagsSpecific" }}</label>
</div>
</div>
<div id="pick-tags-form" class="flex flex-col w-full relative crossable">
@@ -80,7 +80,7 @@
</div>
<button class="w-max mx-auto bg-color-main-hard hover:bg-main-medium active:bg-color-main-soft active:inset-shadow-[0.2em_0.2em_0.2rem_black] transition-colors transition-300 text-background-light font-bold py-2 px-4 rounded z-22"
hx-put="/api/v1/subs" hx-target="#subs-message" hx-swap="outerHTML" hx-indicator="#subs-form">
- {{ .L.UserProfile.SaveButton }}
+ {{ l $.Lang "UserProfile" "SaveButton" }}
</button>
</div>
</form>
@@ -168,7 +168,7 @@ function addTag(name) {
found = [...existingTags].find(opt => opt.value===name);
if (!found) {
subsMessage.classList.remove("hidden");
- subsMessage.innerHTML = "{{ .L.UserProfile.TagDoesNotExist }}".replace("{}", name);
+ subsMessage.innerHTML = "{{ l $.Lang "UserProfile" "TagDoesNotExist" }}".replace("{}", name);
return;
}
@@ -177,7 +177,7 @@ function addTag(name) {
found = [...subscribedTags].find(opt => opt.value===name);
if (found) {
subsMessage.classList.remove("hidden");
- subsMessage.innerHTML = "{{ .L.UserProfile.TagAlreadyAdded }}".replace("{}", name);
+ subsMessage.innerHTML = "{{ l $.Lang "UserProfile" "TagAlreadyAdded" }}".replace("{}", name);
return;
}
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 @@
<hr class="first-of-type:hidden border-t-2 border-dotted border-main-hard">
<div {{ if .ToHighlight }}id="blog-page-highlighted"{{ end }} class="w-full flex flex-row items-stretch {{ if .ToHighlight }}bg-accent-light bg-paper{{ end }}">
<div class="relative min-h-24 flex flex-col w-28 overflow-hidden shrink-0 mask-r-from-70% mask-r-to-100%">
- <img onclick="return changeUrl('{{ .ArticleLink }}');" class="h-full min-h-24 w-full cursor-pointer select-none object-cover block absolute" src="{{ printf $.ThumbnailBaseUrl .Thumbnail }}">
+ <img onclick="return changeUrl('{{ .ArticleLink }}');" class="h-full min-h-24 w-full cursor-pointer select-none object-cover block absolute" src="{{ printf $.PhotoStorage.Thumbnail320p.BaseUrl .Thumbnail }}">
<div class="w-full h-6 flex flex-row mt-auto relative">
<div class="flex-1/2 flex flex-row justify-center select-none bg-linear-180 {{ if .Liked }}from-accent-deep/40 to-accent-deep/80 text-background-dark{{ else }}from-accent-light/40 to-accent-light/80 text-main-hard{{ end }}">
<svg viewBox="0 0 24 24"><use href="#icon-like"/></svg>
diff --git a/views/partials/general-page-body.html b/views/partials/general-page-body.html
index d697c14..b71a0d1 100644
--- a/views/partials/general-page-body.html
+++ b/views/partials/general-page-body.html
@@ -1 +1,2 @@
+<input class="htmx-exit-trigger" type="hidden" name="dummy" value="">
{{ block "body" . }}{{ end }} \ No newline at end of file
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 @@
+<div
+ id="map-container"
+ class="bg-paper bg-background-dark flex z-10 w-full h-full"
+></div>
+
+<script>
+(function() {
+ var map;
+ var markers = L.markerClusterGroup();
+ const THUMB_BASE = "{{ .PhotoStorage.Thumbnail320p.BaseUrl }}";
+
+ function createCustomIcon(color, borderColor = "var(--color-main-soft)") {
+ const svgIcon = `
+ <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
+ <path d="M12 1C7.5 1 4 4.5 4 9c0 6.5 8 14 8 14s8-7.5 8-14c0-4.5-3.5-8-8-8zm0 11c-1.5 0-3-1.5-3-3s1.5-3 3-3 3 1.5 3 3-1.5 3-3 3z"
+ fill="${color}"
+ stroke="${borderColor}"
+ stroke-width="1"
+ stroke-linejoin="round"/>
+ </svg>
+ `;
+
+ return L.divIcon({
+ html: svgIcon,
+ className: 'custom-svg-marker',
+ iconSize: [32, 32],
+ iconAnchor: [16, 32],
+ popupAnchor: [0, -32]
+ });
+ }
+
+ function initLocationMap() {
+ map = L.map('map-container').setView([{{ .MapLocationLat }}, {{ .MapLocationLong }}], {{ .MapLocationZoom }});
+
+ protomapsL.leafletLayer({
+ url: '{{ .StaticStorage.Map.BaseUrl }}/{{ .StaticStorage.Map.PMTiles }}',
+ maxZoom: 15,
+ flavor: window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light',
+ lang: '{{ .Lang }}'
+ }).addTo(map);
+
+ {{- with .ZoomPosition }}
+ L.control.zoom({
+ position: '{{ . }}'
+ }).addTo(map);
+ {{- end }}
+
+ map.addLayer(markers);
+ }
+
+ function markerToHsl(str, newCoef) {
+ let hash = 0;
+ for (let i = 0; i < str.length / 2; i++) {
+ hash = str.charCodeAt(i) + ((hash << 5) - hash);
+ hash = str.charCodeAt(str.length - i - 1) + ((hash << 5) - hash);
+ hash %= 360;
+ }
+
+ return [hash, (20 + newCoef * 80).toFixed(0), (20 + newCoef * 75).toFixed(0)];
+ }
+
+ function mapAddMarker(x, y, relativeErrorMeters = 0, title = "", link = "", thumbnail = "", newCoef = 1, toHighlight = false) {
+ const [h, s, l] = markerToHsl(title, newCoef);
+ const color = `hsl(${h} ${s}% ${l}%)`;
+
+ if (relativeErrorMeters != 0) {
+ var circle = L.circle([x, y], {
+ color: color,
+ fillColor: color,
+ fillOpacity: 0.15,
+ radius: relativeErrorMeters
+ }).addTo(map);
+ }
+
+ var marker = L.marker([x, y], {
+ icon: createCustomIcon(color),
+ title: title,
+ }).bindPopup(`
+ <div class="flex flex-row justify-center justify-items-center">
+ <img onclick="location.href='${link}';" class="cursor-pointer object-cover rounded-[10%] select-none w-12 h-12 mr-1" src="${THUMB_BASE.replace('%s', thumbnail)}">
+ <span><b><a href="${link}">${title}</a></b><br><a href="https://www.openstreetmap.org/#map=13/${x}/${y}">${x}, ${y}</a></span>
+ </div>`);
+
+ markers.addLayer(marker);
+
+ if (toHighlight) {
+ markers.zoomToShowLayer(marker, () => marker.openPopup());
+ }
+ }
+
+ initLocationMap();
+ {{- range .MapMarkers }}
+ mapAddMarker({{ .Lat }}, {{ .Long }}, {{ .AccuracyMeters }}, {{ .Title }}, {{ .PageLink }}, {{ .Thumbnail }}, {{ fdiv .Index (len $.MapMarkers) }}, {{ .ToHighlight }});
+ {{- end }}
+
+ function onResize() {
+ setTimeout(() => {
+ if (map) map.invalidateSize();
+ }, 300);
+ }
+ window.addEventListener('resize', onResize);
+ new MutationObserver((muts, obs) => {
+ if (!document.getElementById('map-container')) {
+ window.removeEventListener('resize', onResize);
+ obs.disconnect();
+ }
+ }).observe(document.body, { childList: true, subtree: true });
+})();
+</script>