Diffstat (limited to 'views/layouts/general-page.html')
| -rw-r--r-- | views/layouts/general-page.html | 148 |
1 files changed, 108 insertions, 40 deletions
diff --git a/views/layouts/general-page.html b/views/layouts/general-page.html index 920640e..2f949a3 100644 --- a/views/layouts/general-page.html +++ b/views/layouts/general-page.html @@ -3,13 +3,30 @@ <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> - <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css"> - <link rel="stylesheet" href="https://f003.backblazeb2.com/file/sayana-static/libs/leaflet/1.9.4/leaflet.css"> - <link rel="stylesheet" href="https://f003.backblazeb2.com/file/sayana-static/libs/glightbox/3.3.0/css/glightbox.min.css"> - <link href="/output.css" rel="stylesheet"> + {{- range .Meta }} + <meta {{with .Name}}name="{{.}}" {{end}}{{with .Property}}property="{{.}}" {{end}}{{with .Content}}content="{{.}}"{{end}}> + {{- if eq .Property "og:description" }} + <meta name="description" content="{{.Content}}"> + {{- end }} + {{- if eq .Property "og:url" }} + <link rel="canonical" href="{{.Content}}"> + {{- end }} + {{- end }} + <link rel="stylesheet" href="{{ .StaticStorageBaseUrl }}/fonts/fonts.css"> + <link rel="stylesheet" href="{{ .StaticStorageBaseUrl }}/libs/font-awesome/7.2.0/css/fontawesome.min.css"> + <link rel="stylesheet" href="{{ .StaticStorageBaseUrl }}/libs/font-awesome/7.2.0/css/brands.min.css"> + <link rel="stylesheet" href="{{ .StaticStorageBaseUrl }}/libs/font-awesome/7.2.0/css/solid.min.css"> + <link rel="stylesheet" href="{{ .StaticStorageBaseUrl }}/libs/leaflet/1.9.4/leaflet.css"> + <link rel="stylesheet" href="{{ .StaticStorageBaseUrl }}/libs/glightbox/3.3.0/css/glightbox.min.css"> + <link rel="stylesheet" href="/output.css"> + {{- with .LinkedData }} + <script type="application/ld+json"> + {{ . }} + </script> + {{- end }} </head> -<body data-theme="ram" class="font-andika text-main-hard overflow-hidden bg-interlocked-hexagons h-[100dvh] flex flex-row"> +<body data-theme="ram" class="font-m-plus text-main-hard overflow-hidden bg-interlocked-hexagons h-dvh flex flex-row"> <script> let map = null; @@ -18,7 +35,11 @@ <script> function changeUrl(path, toAppend = false) { const urlParams = new URLSearchParams(window.location.search); - const newPathname = location.pathname.endsWith('/') ? location.pathname.slice(0, -1) : location.pathname; + newPathname = location.pathname.endsWith('/') ? location.pathname.slice(0, -1) : location.pathname; + while (path.slice(-3) == '/..' && toAppend) { + newPathname = newPathname.replace(/\/[^\/]+$/, ''); + path = path.slice(0, -3); + } const newPath = toAppend ? `${newPathname}${path}` : `${path}`; history.pushState({}, '', `${newPath}${urlParams.entries.length == 0 ? '' : '?' + urlParams.toString()}`); @@ -31,7 +52,7 @@ } </script> - <script src="https://f003.backblazeb2.com/file/sayana-static/libs/glightbox/3.3.0/js/glightbox.min.js"></script> + <script src="{{ .StaticStorageBaseUrl }}/libs/glightbox/3.3.0/js/glightbox.min.js"></script> <script> function sfc32(a, b, c, d) { @@ -115,7 +136,7 @@ const frameCenters = new Array(4); for (i = 1; i <= 4; i++) { let frame = document.createElement("img"); - frame.src = `https://f003.backblazeb2.com/file/sayana-static/themes/ram/ram-frame${i}.webp`; + frame.src = `{{ .StaticStorageBaseUrl }}/themes/ram/ram-frame${i}.webp`; frame.classList.add("ram-frame", "theme-decor", "z-0", "absolute"); let x, y; outerLoop: @@ -137,6 +158,7 @@ document.body.append(frame); } break; + case "lilac": break; } } @@ -156,7 +178,7 @@ switchThemeDecor(theme); } - const savedTheme = localStorage.getItem('theme') || 'ram'; + const savedTheme = localStorage.getItem('theme') || 'lilac'; switchTheme(savedTheme); </script> @@ -171,23 +193,31 @@ <div class="grow bg-split-left"></div> - <div class="flex flex-col [@media(max-height:32rem)]:flex-row"> - <div id="sidebar" class="bg-sidebar flex sticky flex-col z-20 w-[100dvw] xs:w-[90dvw] sm:w-[80dvw] md:w-[75dvw] lg:w-[70dvw] xl:w-[65dvw] 2xl:w-[60dvw] [@media(max-height:32rem)]:w-[5rem] h-[5rem] [@media(max-height:32rem)]:h-[100dvh] shadow-[0_0_1rem_black]"> - <div class="text-[3rem] text-stroke-(--sidebar-stroke-color) text-stroke-[0.1dvw] flex flex-row [@media(max-height:32rem)]:flex-col gap-0 relative z-20"> - <a href="/{{ .Lang }}" id="sidebar-home-button" class="w-[5rem] h-[5rem]"> - <i onclick="return changeUrl('/{{ .Lang }}');" class="fas fa-home flex w-full h-full content-center text-center text-sidebar hover:bg-background-dark transition-colors duration-300 rounded-lg"></i> + <div class="flex flex-col sm:flex-row"> + <div id="sidebar" class="bg-sidebar flex + flex-row sticky w-dvw h-fit xs:w-[90dvw] + sm:left-0 sm:flex-col sm:fixed sm:w-fit + z-20 shadow-[0_0_1rem_black]"> + <nav aria-label="Main navigation" class="text-[3rem] flex flex-row sm:flex-col gap-0 relative z-20"> + <a onclick="return changeUrl('/..', true);" href="../" id="sidebar-back-button" class="themed-button themed-button-sidebar w-fit h-fit hidden" draggable="false"> + <i class="fas fa-circle-left flex faw-18 h-18 content-center text-center text-sidebar"></i> </a> - <a href="/{{ .Lang }}/blog" id="sidebar-blog-button" class="w-[5rem] h-[5rem]"> - <i onclick="return changeUrl('/{{ .Lang }}/blog');" class="fas fa-search flex w-full h-full content-center text-center text-sidebar hover:bg-background-dark transition-colors duration-300 rounded-lg"></i> + <a onclick="return changeUrl('/{{ .Lang }}');" href="/{{ .Lang }}" id="sidebar-home-button" class="themed-button themed-button-sidebar w-fit h-fit hidden" draggable="false"> + <i class="fas fa-home flex faw-18 h-18 content-center text-center text-sidebar"></i> </a> - <a href="/{{ .Lang }}/map" id="sidebar-map-button" class="w-[5rem] h-[5rem]"> - <i class="fas fa-map flex w-full h-full content-center text-center text-sidebar hover:bg-background-dark transition-colors duration-300 rounded-lg"></i> + <a onclick="return changeUrl('/{{ .Lang }}/blog');" href="/{{ .Lang }}/blog" id="sidebar-blog-button" class="themed-button themed-button-sidebar w-fit h-fit hidden" draggable="false"> + <i class="fas fa-search flex faw-18 h-18 content-center text-center text-sidebar"></i> </a> - <i onclick="toggleThemeWheel();" id="sidebar-theme-button" class="fas fa-swatchbook flex w-[5rem] h-[5rem] content-center text-center text-sidebar hover:bg-background-dark cursor-pointer transition-colors duration-300 rounded-lg"></i> - <a href="./" id="sidebar-back-button" class="w-[5rem] h-[5rem]"> - <i onclick="return changeUrl('/../', true);" class="fas fa-circle-left flex w-full h-full content-center text-center text-sidebar hover:bg-background-dark transition-colors duration-300 rounded-lg"></i> + <a href="/{{ .Lang }}/map" id="sidebar-map-button" class="themed-button themed-button-sidebar w-fit h-fit hidden" draggable="false"> + <i class="fas fa-map flex faw-18 h-18 content-center text-center text-sidebar"></i> </a> - </div> + <div id="toolbar-theme-button" onclick="toggleThemeWheel();" class="themed-button themed-button-sidebar w-fit h-fit" draggable="false"> + <i id="toolbar-theme-button-content" class="fas fa-swatchbook flex faw-18 h-18 content-center text-center text-sidebar"></i> + </div> + <a onclick="return changeUrl('/{{ .Lang }}/user');" href="/{{ .Lang }}/user" id="sidebar-user-button" class="themed-button themed-button-sidebar w-fit h-fit hidden" draggable="false"> + <i class="fas fa-user flex faw-18 h-18 content-center text-center text-sidebar"></i> + </a> + </nav> <div class="theme-wheel" id="theme-wheel"> <div class="theme-icon" data-theme="olive"></div> <div class="theme-icon" data-theme="lettuce"></div> @@ -201,6 +231,7 @@ sidebarMapButton = document.getElementById("sidebar-map-button"); sidebarBlogButton = document.getElementById("sidebar-blog-button"); sidebarBackButton = document.getElementById("sidebar-back-button"); + sidebarUserButton = document.getElementById("sidebar-user-button"); function updateSidebar() { if (location.pathname == "" || location.pathname == "/") { @@ -208,17 +239,21 @@ sidebarMapButton.classList.add('hidden'); sidebarBlogButton.classList.add('hidden'); sidebarBackButton.classList.add('hidden'); + sidebarUserButton.classList.add('hidden'); } else { sidebarHomeButton.classList.remove('hidden'); sidebarMapButton.classList.remove('hidden'); sidebarBlogButton.classList.remove('hidden'); sidebarBackButton.classList.remove('hidden'); + sidebarUserButton.classList.remove('hidden'); lang = location.pathname.split("/")[1]; sidebarHomeButton.setAttribute('href', `/${lang}`); - sidebarHomeButton.firstElementChild.setAttribute('onclick', `return changeUrl('/${lang}', false);`); + sidebarHomeButton.setAttribute('onclick', `return changeUrl('/${lang}', false);`); sidebarMapButton.setAttribute('href', `/${lang}/map`); sidebarBlogButton.setAttribute('href', `/${lang}/blog`); - sidebarBlogButton.firstElementChild.setAttribute('onclick', `return changeUrl('/${lang}/blog', false);`); + sidebarBlogButton.setAttribute('onclick', `return changeUrl('/${lang}/blog', false);`); + sidebarUserButton.setAttribute('href', `/${lang}/user`); + sidebarUserButton.setAttribute('onclick', `return changeUrl('/${lang}/user', false);`); } } window.addEventListener("popstate", updateSidebar); @@ -226,40 +261,73 @@ </script> </div> - <div class="bg-background-dark @container/main flex z-10 w-[100dvw] xs:w-[90dvw] sm:w-[80dvw] md:w-[75dvw] lg:w-[70dvw] xl:w-[65dvw] 2xl:w-[60dvw] grow-0 h-[calc(100dvh-5rem)] [@media(max-height:32rem)]:h-[100dvh] shadow-[0_0_1rem_black]"> - <div class="bg-background-dark border-r-2 border-dashed border-main-hard"></div> + <div class="bg-paper bg-background-dark @container/main flex z-10 w-dvw xs:w-[90dvw] sm:w-[85dvw] md:w-[80dvw] lg:w-[75dvw] xl:w-[70dvw] 2xl:w-[60dvw] 3xl:w-[50dvw] grow-0 h-[calc(100dvh-5rem)] sm:h-dvh shadow-[0_0_1rem_black]"> + <div class="bg-paper bg-background-dark border-r-2 border-dashed border-main-hard"></div> - <div class="max-h-100% flex flex-col grow bg-background-dark relative pt-4 ml-8 pr-4"> - <div id="general-page-header" class="max-xs:hidden [@media(max-height:32rem)]:hidden flex flex-col basis-8" + <div class="max-h-full max-w-full flex flex-col grow bg-paper bg-background-dark relative pt-4 ml-8 pr-4"> + <header id="general-page-header" class="max-xs:hidden [@media(max-height:32rem)]:hidden flex flex-col basis-8" hx-get="/api/v1/general-page/header{{ if .QueryString }}?{{ .QueryString }}{{ end }}" hx-trigger="load" hx-target="this" hx-swap="innerHTML"> - </div> + </header> <div id="general-page-header-trigger" hx-get="/api/v1/general-page/header{{ if .QueryString }}?{{ .QueryString }}{{ end }}" hx-trigger="popstate from:window" hx-target="#general-page-header" hx-swap="innerHTML"></div> <hr class="max-xs:hidden [@media(max-height:32rem)]:hidden border-t-4 border-dotted border-main-hard mb-2"> - <div id="general-page-body" class="flex flex-col grow overflow-y-auto" + <main id="general-page-body" class="relative flex flex-col grow overflow-y-auto" hx-get="/api/v1/general-page/body{{ if .QueryString }}?{{ .QueryString }}{{ end }}" hx-trigger="load" hx-target="this" hx-swap="innerHTML"> - </div> + </main> <div id="general-page-body-trigger" hx-get="/api/v1/general-page/body{{ if .QueryString }}?{{ .QueryString }}{{ end }}" hx-trigger="popstate from:window" hx-target="#general-page-body" hx-swap="innerHTML"></div> - <div id="general-page-footer" class="flex flex-row basis-4 my-1" + <footer id="general-page-footer" class="flex flex-row basis-4 my-1" hx-get="/api/v1/general-page/footer{{ if .QueryString }}?{{ .QueryString }}{{ end }}" hx-trigger="load" hx-target="this" hx-swap="innerHTML"> - </div> + </footer> <div id="general-page-footer-trigger" hx-get="/api/v1/general-page/footer{{ if .QueryString }}?{{ .QueryString }}{{ end }}" hx-trigger="popstate from:window" hx-target="#general-page-footer" hx-swap="innerHTML"></div> <hr class="border-t-4 border-dotted border-main-hard mb-2"> </div> - <div class="pr-[0.5dvw] bg-background-dark shadow-2xl border-l-2 border-dotted border-main-hard"></div> + <div class="pr-[0.5dvw] bg-paper bg-background-dark shadow-2xl border-l-2 border-dotted border-main-hard"></div> </div> </div> <div class="grow bg-split-right"></div> - <script src="https://f003.backblazeb2.com/file/sayana-static/libs/htmx/2.0.6/htmx.min.js"></script> - <script src="https://f003.backblazeb2.com/file/sayana-static/libs/leaflet/1.9.4/leaflet.js"></script> - <script src="https://f003.backblazeb2.com/file/sayana-static/libs/imagesloaded/5.0.0/imagesloaded.pkgd.min.js"></script> - <script src="https://f003.backblazeb2.com/file/sayana-static/libs/masonry-layout/4.2.2/masonry.pkgd.min.js"></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> + // Enable fitWidth-like attribute for Packery. Source: https://codepen.io/desandro/pen/kVmLYz + var __resetLayout = Packery.prototype._resetLayout; + Packery.prototype._resetLayout = function() { + __resetLayout.call( this ); + var parentSize = getSize( this.element.parentNode ); + var colW = this.columnWidth + this.gutter; + this.fitWidth = Math.floor( ( parentSize.innerWidth + this.gutter ) / colW ) * colW; + this.packer.width = this.fitWidth; + this.packer.height = Number.POSITIVE_INFINITY; + this.packer.reset(); + }; + + Packery.prototype._getContainerSize = function() { + var emptyWidth = 0; + for ( var i=0, len = this.packer.spaces.length; i < len; i++ ) { + var space = this.packer.spaces[i]; + if ( space.y === 0 && space.height === Number.POSITIVE_INFINITY ) { + emptyWidth += space.width; + } + } + + return { + width: this.fitWidth - this.gutter - emptyWidth, + height: this.maxY - this.gutter + }; + }; + + Packery.prototype.needsResizeLayout = function() { + return true; + }; + </script> <div id="general-page-bottom-embeds" class="flex" hx-get="/api/v1/general-page/bottom-embeds{{ if .QueryString }}?{{ .QueryString }}{{ end }}" hx-trigger="load" hx-target="this" hx-swap="innerHTML"> @@ -268,7 +336,7 @@ <script> const themeWheel = document.getElementById('theme-wheel'); - const themeButton = document.getElementById('sidebar-theme-button'); + const themeButton = document.getElementById('toolbar-theme-button'); const themeIcons = document.querySelectorAll('.theme-icon'); const themeWheelRadius = convertRemToPixels(6); @@ -384,7 +452,7 @@ themeWheel.addEventListener('mouseleave', hideThemeWheel); document.addEventListener('click', (e) => { - if (!themeWheel.contains(e.target) && e.target !== themeButton) { + if (!themeWheel.contains(e.target) && e.target !== themeButton && !e.target.classList.contains("toolbar-theme-button-content")) { hideThemeWheel(); } }); |