From 7810601057280eb79c22ff53317aa9efebc558f0 Mon Sep 17 00:00:00 2001 From: Dominik Hebeler <dominik@suma-ev.de> Date: Wed, 19 Jun 2024 17:20:07 +0200 Subject: [PATCH] introduce settings menu --- app/lang/en.json | 9 ++++++- app/resources/js/Config.js | 35 ++++++++++++++++++++++++ app/resources/js/SearchModule.js | 14 +++++++++- app/resources/js/Theme.js | 2 +- app/resources/js/UrlGenerator.js | 1 + app/resources/js/app.js | 11 +++++++- app/resources/less/map.less | 1 + app/resources/less/settings.less | 44 +++++++++++++++++++++++++++++++ app/resources/views/map.blade.php | 28 ++++++++++++++++++-- 9 files changed, 139 insertions(+), 6 deletions(-) create mode 100644 app/resources/less/settings.less diff --git a/app/lang/en.json b/app/lang/en.json index 3b63df2..4a55883 100644 --- a/app/lang/en.json +++ b/app/lang/en.json @@ -49,5 +49,12 @@ "longer": "longer", "shorter": "shorter", "own position": "Own Position", - "add own position": "Add Own Position" + "add own position": "Add Own Position", + "settings": "Settings", + "usage of cookies in settings": "All changed settings are stored in your browser using cookies.", + "close": "Close", + "language": "Language", + "en": "English", + "de": "German", + "theme": "Theme" } \ No newline at end of file diff --git a/app/resources/js/Config.js b/app/resources/js/Config.js index 1633f6d..37f3f1b 100644 --- a/app/resources/js/Config.js +++ b/app/resources/js/Config.js @@ -1,6 +1,8 @@ import { bbox, bboxPolygon, circle } from "@turf/turf"; import { LngLatBounds, CenterZoomBearing, LngLat } from "maplibre-gl"; import { gpsManager } from "./GpsManager"; +import { UrlGenerator } from "./UrlGenerator"; +import { detectTheme, toggleTheme } from "./Theme"; export const config = { localization: { @@ -130,3 +132,36 @@ let module = document.querySelector("meta[name=module]"); if (module) { config.init.module = module.content; } + +(() => { + let settings_container = document.getElementById("settings"); + if ((new URLSearchParams(location.search)).has("settings")) { + settings_container.showModal(); + } + // Make settings close button work + settings_container.querySelector("button.close").addEventListener("click", e => { + settings_container.close(); + }); + + // Make Language switcher work + let language_switch_select = settings_container.querySelector(".settings-container #language"); + if (language_switch_select) { + language_switch_select.value = config.localization.current_locale; + language_switch_select.addEventListener("change", e => { + let new_language = e.target.value; + if (new_language != config.localization.current_locale) { + let new_url = UrlGenerator.to(location.pathname + location.search, new_language); + location.replace(new_url); + } + }); + } else { console.error("Language switch is not present") } + + // Make theme option work + let theme_switch_select = settings_container.querySelector(".settings-container #theme"); + if (theme_switch_select) { + theme_switch_select.value = detectTheme(); + theme_switch_select.addEventListener("change", e => { + toggleTheme(); + }); + } else { console.error("Theme switch is not present") } +})(); diff --git a/app/resources/js/SearchModule.js b/app/resources/js/SearchModule.js index 9404c16..d8285fd 100644 --- a/app/resources/js/SearchModule.js +++ b/app/resources/js/SearchModule.js @@ -667,9 +667,20 @@ class SearchModule { }/${JSON.stringify(current_pos.toArray())}`; } + let options = {}; + let params = {}; if (["enabled", "disabled"].includes(this.bounded)) { - url += "?bounded=" + this.bounded; + params.bounded = this.bounded; } + options.settings = document.getElementById("settings").open; + if (options.settings) { + params.settings = ""; + } + + if (Object.keys(params).length > 0) { + url += "?" + (new URLSearchParams(params).toString()) + } + let state = { module: "search", @@ -679,6 +690,7 @@ class SearchModule { reverse: this.reverse, bounded: this.bounded, timestamp: Date.now(), + options: options }; if ( diff --git a/app/resources/js/Theme.js b/app/resources/js/Theme.js index 5014da1..d8c7eb6 100644 --- a/app/resources/js/Theme.js +++ b/app/resources/js/Theme.js @@ -42,7 +42,7 @@ function getDefaultTheme() { } } -function toggleTheme() { +export function toggleTheme() { let theme = detectTheme(); if (theme == "light") { theme = "dark"; diff --git a/app/resources/js/UrlGenerator.js b/app/resources/js/UrlGenerator.js index f10f74e..057456a 100644 --- a/app/resources/js/UrlGenerator.js +++ b/app/resources/js/UrlGenerator.js @@ -13,6 +13,7 @@ export class UrlGenerator { if (!config.localization.supported_locales.includes(locale)) { locale = config.localization.fallback_locale; } + for (let supported_locale of config.localization.supported_locales) { supported_locale = supported_locale.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&"); // Regex escape let reg = new RegExp(`^\/${supported_locale}`); diff --git a/app/resources/js/app.js b/app/resources/js/app.js index 5256d04..2e09ee0 100644 --- a/app/resources/js/app.js +++ b/app/resources/js/app.js @@ -76,6 +76,15 @@ function initializeInterface() { window.addEventListener("popstate", (event) => { event.preventDefault(); + if (event.state.hasOwnProperty("options") && event.state.options.hasOwnProperty("settings")) { + if (document.getElementById("settings").open != event.state.options.settings) { + if (event.state.options.settings) { + document.getElementById("settings").showModal(); + } else { + document.getElementById("settings").close(); + } + } + } // Check which module the state is based on switch (event.state.module) { case "search": @@ -236,4 +245,4 @@ export function switchModule(name, args) { default: return; } -} +} \ No newline at end of file diff --git a/app/resources/less/map.less b/app/resources/less/map.less index d20d136..bdd9a7f 100644 --- a/app/resources/less/map.less +++ b/app/resources/less/map.less @@ -3,6 +3,7 @@ @import "../../node_modules/ol-popup/src/ol-popup.css"; @import "./openlayers/controls.less"; @import "./openlayers/popups.less"; +@import "./settings.less"; .maplibregl-popup-content { background-color: var(--background-color); diff --git a/app/resources/less/settings.less b/app/resources/less/settings.less new file mode 100644 index 0000000..46ae56c --- /dev/null +++ b/app/resources/less/settings.less @@ -0,0 +1,44 @@ +#settings { + margin: 1rem 0 0 auto; + padding: 1rem; + width: 320px; + height: 100vh; + display: flex; + flex-direction: column; + row-gap: 1rem; + + &::backdrop { + background-color: #0006; + } + + >h1 { + font-size: 1.5rem; + text-align: center; + border-bottom: 1px solid; + padding-bottom: .5rem; + } + + >.settings-container { + flex-grow: 1; + overflow-y: scroll; + padding: .25rem; + display: flex; + flex-direction: column; + row-gap: 1rem; + + >.setting { + display: flex; + justify-content: space-between; + align-items: center; + + >select { + padding: .5rem 1rem; + } + } + } + + >button.close { + cursor: pointer; + padding: .5rem 1rem; + } +} \ No newline at end of file diff --git a/app/resources/views/map.blade.php b/app/resources/views/map.blade.php index 8ec4893..6295364 100644 --- a/app/resources/views/map.blade.php +++ b/app/resources/views/map.blade.php @@ -85,6 +85,28 @@ target="_blank">@lang('why?')</a> </div> </main> + <dialog id="settings"> + <h1>@lang("settings")</h1> + <p>@lang("usage of cookies in settings")</p> + <div class="settings-container"> + <div class="setting"> + <label for="language">@lang("language")</label> + <select name="language" id="language"> + @foreach(App\Http\Middleware\Localization::SUPPORTED_LOCALES as $supported_locale) + <option value="{{$supported_locale}}" @if(App::currentLocale() === $supported_locale)selected @endif>@lang($supported_locale)</option> + @endforeach + </select> + </div> + <div class="setting"> + <label for="theme">@lang("theme")</label> + <select name="theme" id="theme"> + <option value="light">@lang("light mode")</option> + <option value="dark">@lang("dark mode")</option> + </select> + </div> + </div> + <button class="close">@lang("close")</button> + </dialog> <div id="nav-menu"> <input type="checkbox" name="nav-opener" id="nav-opener"> <label for="nav-opener">≡</label> @@ -105,9 +127,11 @@ <div class="updates"> <label>@lang('last openstreetmap update')</label> <div>@lang('timezone'): <span class="data-date-timezone"></span></div> - <div>@lang('map'): <span class="data-date-tiles"><img src="/img/ajax-loader.gif" alt="@lang('loading data...')"></span> + <div>@lang('map'): <span class="data-date-tiles"><img src="/img/ajax-loader.gif" +a lt="@lang('loading data...')"></span> </div> - <div>@lang('search'): <span class="data-date-search"><img src="/img/ajax-loader.gif" alt="@lang('loading data...')"></span> + <div>@lang('search'): <span class="data-date-search"><img src="/img/ajax-loader.gif" + alt="@lang('loading data...')"></span> </div> <div>@lang('routes'): <span class="data-date-routing"><img src="/img/ajax-loader.gif" alt="@lang('loading data...')"></span></div> -- GitLab