# HG changeset patch # User Mike Becker # Date 1731149240 -3600 # Node ID 1eed60b779da976941d489e6f182c813fabfdab9 # Parent 2696337baa3d0c42a5891605d72de0d971bcba79 change language menu to settings menu and add timezone settings - fixes #402 diff -r 2696337baa3d -r 1eed60b779da src/main/kotlin/de/uapcore/lightpit/AbstractServlet.kt --- a/src/main/kotlin/de/uapcore/lightpit/AbstractServlet.kt Sat Nov 09 10:54:57 2024 +0100 +++ b/src/main/kotlin/de/uapcore/lightpit/AbstractServlet.kt Sat Nov 09 11:47:20 2024 +0100 @@ -33,12 +33,15 @@ import jakarta.servlet.http.HttpServletRequest import jakarta.servlet.http.HttpServletResponse import java.sql.SQLException +import java.time.ZoneId import java.util.* abstract class AbstractServlet : HttpServlet() { companion object { + const val COOKIE_MAX_AGE = 2592000 // 30 days const val LANGUAGE_COOKIE_NAME = "lpit_language" + const val TIMEZONE_COOKIE_NAME = "lpit_timezone" } protected val logger = MyLogger() @@ -138,6 +141,18 @@ logger.trace("Continuing session {0} with language {1}", session.id, sessionLocale) } + // determine the timezone + if (session.getAttribute(Constants.SESSION_ATTR_TIMEZONE) == null) { + // timezone selection stored in cookie + val cookieTimezone = cookieTimezone(http) + + // if no cookie, fall back to server's timezone (the browser does not transmit one) + val timezone = cookieTimezone ?: ZoneId.systemDefault() + + selectTimezone(http, timezone) + logger.debug("Timezone for session {0} set to {1}", session.id, timezone) + } + // if this is an error path, bypass the normal flow if (fullPath.startsWith("/error/")) { http.styleSheets = listOf("error") @@ -198,6 +213,23 @@ http.request.cookies?.firstOrNull { c -> c.name == LANGUAGE_COOKIE_NAME } ?.runCatching {Locale.forLanguageTag(this.value)}?.getOrNull() + protected fun sessionLanguage(http: HttpRequest) = http.session.getAttribute(Constants.SESSION_ATTR_LANGUAGE) as Locale + + private fun cookieTimezone(http: HttpRequest): ZoneId? = + http.request.cookies?.firstOrNull { c -> c.name == TIMEZONE_COOKIE_NAME } + ?.runCatching { ZoneId.of(this.value)}?.getOrNull() + + protected fun sessionTimezone(http: HttpRequest) = http.session.getAttribute(Constants.SESSION_ATTR_TIMEZONE) as String + + protected fun selectTimezone(http: HttpRequest, zoneId: ZoneId) { + http.session.setAttribute(Constants.SESSION_ATTR_TIMEZONE, zoneId.id) + val cookie = Cookie(TIMEZONE_COOKIE_NAME, zoneId.id) + cookie.isHttpOnly = true + cookie.path = http.request.contextPath + cookie.maxAge = COOKIE_MAX_AGE + http.response.addCookie(cookie) + } + protected fun selectLanguage(http: HttpRequest, locale: Locale) { http.response.locale = locale http.session.setAttribute(Constants.SESSION_ATTR_LANGUAGE, locale) @@ -209,7 +241,7 @@ cookie.maxAge = 0 } else { cookie.value = locale.language - cookie.maxAge = 2592000 // 30 days + cookie.maxAge = COOKIE_MAX_AGE } http.response.addCookie(cookie) } diff -r 2696337baa3d -r 1eed60b779da src/main/kotlin/de/uapcore/lightpit/Constants.kt --- a/src/main/kotlin/de/uapcore/lightpit/Constants.kt Sat Nov 09 10:54:57 2024 +0100 +++ b/src/main/kotlin/de/uapcore/lightpit/Constants.kt Sat Nov 09 11:47:20 2024 +0100 @@ -106,4 +106,9 @@ * Key for the current language selection within the session. */ const val SESSION_ATTR_LANGUAGE = "language" + + /** + * Key for the current timezone selection within the session. + */ + const val SESSION_ATTR_TIMEZONE = "timezone" } diff -r 2696337baa3d -r 1eed60b779da src/main/kotlin/de/uapcore/lightpit/servlet/LanguageServlet.kt --- a/src/main/kotlin/de/uapcore/lightpit/servlet/LanguageServlet.kt Sat Nov 09 10:54:57 2024 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,68 +0,0 @@ -/* - * Copyright 2021 Mike Becker. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package de.uapcore.lightpit.servlet - -import de.uapcore.lightpit.AbstractServlet -import de.uapcore.lightpit.Constants -import de.uapcore.lightpit.HttpRequest -import de.uapcore.lightpit.dao.DataAccessObject -import de.uapcore.lightpit.viewmodel.LanguageView -import jakarta.servlet.annotation.WebServlet -import java.util.* - -@WebServlet(urlPatterns = ["/language/*"]) -class LanguageServlet : AbstractServlet() { - - init { - get("/", this::viewLanguages) - post("/", this::selectLanguage) - } - - private fun viewLanguages(http: HttpRequest, dao: DataAccessObject) { - with(http) { - view = LanguageView( - availableLanguages(), - session.getAttribute(Constants.SESSION_ATTR_LANGUAGE) as Locale, - request.locale - ) - styleSheets = listOf("language") - render("language") - } - } - - private fun selectLanguage(http: HttpRequest, dao: DataAccessObject) { - val lang = http.param("language") - if (lang != null) { - val locale = Locale.forLanguageTag(lang) - if (!locale.language.isNullOrBlank()) { - super.selectLanguage(http, locale) - } - } - - viewLanguages(http, dao) - } - -} \ No newline at end of file diff -r 2696337baa3d -r 1eed60b779da src/main/kotlin/de/uapcore/lightpit/servlet/SettingsServlet.kt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main/kotlin/de/uapcore/lightpit/servlet/SettingsServlet.kt Sat Nov 09 11:47:20 2024 +0100 @@ -0,0 +1,72 @@ +/* + * Copyright 2021 Mike Becker. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package de.uapcore.lightpit.servlet + +import de.uapcore.lightpit.AbstractServlet +import de.uapcore.lightpit.HttpRequest +import de.uapcore.lightpit.dao.DataAccessObject +import de.uapcore.lightpit.viewmodel.SettingsView +import jakarta.servlet.annotation.WebServlet +import java.time.ZoneId +import java.util.* + +@WebServlet(urlPatterns = ["/settings/*"]) +class SettingsServlet : AbstractServlet() { + + init { + get("/", this::viewSettings) + post("/", this::selectSettings) + } + + private fun viewSettings(http: HttpRequest, dao: DataAccessObject) { + with(http) { + view = SettingsView( + availableLanguages(), + sessionLanguage(http), + request.locale, + sessionTimezone(http) + ) + styleSheets = listOf("settings") + render("settings") + } + } + + private fun selectSettings(http: HttpRequest, dao: DataAccessObject) { + val lang = http.param("language") + if (lang != null) { + val locale = Locale.forLanguageTag(lang) + if (!locale.language.isNullOrBlank()) { + super.selectLanguage(http, locale) + } + } + + val timezone = http.param("timezone") + timezone?.runCatching { ZoneId.of(this) }?.onSuccess { selectTimezone(http, it) } + + viewSettings(http, dao) + } + +} \ No newline at end of file diff -r 2696337baa3d -r 1eed60b779da src/main/kotlin/de/uapcore/lightpit/viewmodel/LanguageView.kt --- a/src/main/kotlin/de/uapcore/lightpit/viewmodel/LanguageView.kt Sat Nov 09 10:54:57 2024 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -/* - * Copyright 2021 Mike Becker. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package de.uapcore.lightpit.viewmodel - -import java.util.* - -class LanguageView( - val languages: List, - val currentLanguage: Locale, - val browserLanguage: Locale -) : View() \ No newline at end of file diff -r 2696337baa3d -r 1eed60b779da src/main/kotlin/de/uapcore/lightpit/viewmodel/SettingsView.kt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main/kotlin/de/uapcore/lightpit/viewmodel/SettingsView.kt Sat Nov 09 11:47:20 2024 +0100 @@ -0,0 +1,38 @@ +/* + * Copyright 2021 Mike Becker. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package de.uapcore.lightpit.viewmodel + +import java.time.ZoneId +import java.util.* + +class SettingsView( + val languages: List, + val currentLanguage: Locale, + val browserLanguage: Locale, + val currentTimezone: String +) : View() { + val timezones: List = ZoneId.getAvailableZoneIds().sorted() +} \ No newline at end of file diff -r 2696337baa3d -r 1eed60b779da src/main/resources/localization/strings.properties --- a/src/main/resources/localization/strings.properties Sat Nov 09 10:54:57 2024 +0100 +++ b/src/main/resources/localization/strings.properties Sat Nov 09 11:47:20 2024 +0100 @@ -36,7 +36,6 @@ button.issue.create.another=Create another Issue button.issue.create=New Issue button.issue.edit=Edit -button.language.submit = Switch language button.okay=OK button.project.create=New Project button.project.details=Project Details @@ -138,8 +137,8 @@ language.browser.unavailable = Browser language not available. menu.about=About menu.issues=Issues -menu.languages=Language menu.projects=Projects +menu.settings=Settings menu.users=Developer navmenu.all=all navmenu.components=Components @@ -165,6 +164,8 @@ project.vcs=Version Control project.vcs.none=Do not analyze repository project=Project +settings.language=Language +settings.timezone=Timezone user.displayname=Developer user.givenname=Given Name user.lastname=Last Name diff -r 2696337baa3d -r 1eed60b779da src/main/resources/localization/strings_de.properties --- a/src/main/resources/localization/strings_de.properties Sat Nov 09 10:54:57 2024 +0100 +++ b/src/main/resources/localization/strings_de.properties Sat Nov 09 11:47:20 2024 +0100 @@ -36,7 +36,6 @@ button.issue.create.another=Weiteren Vorgang erstellen button.issue.create=Neuer Vorgang button.issue.edit=Bearbeiten -button.language.submit = Sprache ausw\u00e4hlen button.okay=OK button.project.create=Neues Projekt button.project.details=Projektdetails @@ -138,8 +137,8 @@ language.browser.unavailable = Browsersprache nicht verf\u00fcgbar. menu.about=Info menu.issues=Vorg\u00e4nge -menu.languages=Sprache menu.projects=Projekte +menu.settings=Einstellungen menu.users=Entwickler navmenu.all=Alle navmenu.components=Komponenten @@ -165,6 +164,8 @@ project.vcs=Versionskontrolle project.vcs.none=Keine Analyse durchf\u00fchren project=Projekt +settings.language=Sprache +settings.timezone=Zeitzone user.displayname=Entwickler user.givenname=Vorname user.lastname=Nachname diff -r 2696337baa3d -r 1eed60b779da src/main/webapp/WEB-INF/changelogs/changelog-de.jspf --- a/src/main/webapp/WEB-INF/changelogs/changelog-de.jspf Sat Nov 09 10:54:57 2024 +0100 +++ b/src/main/webapp/WEB-INF/changelogs/changelog-de.jspf Sat Nov 09 11:47:20 2024 +0100 @@ -27,6 +27,7 @@

Version 1.4.0 (Vorschau)

    +
  • Das Sprachmenü ist nun ein Einstellungsmenü, in dem auch die Zeitzone eingestellt werden kann.
  • Abbrechen-Button zum Kommentar-Editor hinzugefügt.
  • Die Vorgangsliste zeigt nun die Komponente, wenn kein Filter auf Komponenten aktiv ist.
  • Vorgangsstatus zur Vorschlagsliste für das Erstellen einer Vorgangsbeziehung hinzugefügt.
  • diff -r 2696337baa3d -r 1eed60b779da src/main/webapp/WEB-INF/changelogs/changelog.jspf --- a/src/main/webapp/WEB-INF/changelogs/changelog.jspf Sat Nov 09 10:54:57 2024 +0100 +++ b/src/main/webapp/WEB-INF/changelogs/changelog.jspf Sat Nov 09 11:47:20 2024 +0100 @@ -27,6 +27,7 @@

    Version 1.4.0 (snapshot)

      +
    • Change language menu to settings menu and add timezone settings.
    • Add cancel button to comment editor.
    • Add component tag to issue list when no component filter is active.
    • Add issue status to the suggestions for creating an issue relation.
    • diff -r 2696337baa3d -r 1eed60b779da src/main/webapp/WEB-INF/jsp/error.jsp --- a/src/main/webapp/WEB-INF/jsp/error.jsp Sat Nov 09 10:54:57 2024 +0100 +++ b/src/main/webapp/WEB-INF/jsp/error.jsp Sat Nov 09 11:47:20 2024 +0100 @@ -47,7 +47,7 @@ : - + <%--@elvariable id="exception" type="java.lang.Exception"--%> diff -r 2696337baa3d -r 1eed60b779da src/main/webapp/WEB-INF/jsp/issue-form.jsp --- a/src/main/webapp/WEB-INF/jsp/issue-form.jsp Sat Nov 09 10:54:57 2024 +0100 +++ b/src/main/webapp/WEB-INF/jsp/issue-form.jsp Sat Nov 09 11:47:20 2024 +0100 @@ -151,7 +151,7 @@ - " /> + " /> diff -r 2696337baa3d -r 1eed60b779da src/main/webapp/WEB-INF/jsp/issue-view.jsp --- a/src/main/webapp/WEB-INF/jsp/issue-view.jsp Sat Nov 09 10:54:57 2024 +0100 +++ b/src/main/webapp/WEB-INF/jsp/issue-view.jsp Sat Nov 09 11:47:20 2024 +0100 @@ -143,7 +143,7 @@ - + @@ -298,10 +298,10 @@
      - + - ( , ${comment.updateCount} ) + ( , ${comment.updateCount} )
      diff -r 2696337baa3d -r 1eed60b779da src/main/webapp/WEB-INF/jsp/language.jsp --- a/src/main/webapp/WEB-INF/jsp/language.jsp Sat Nov 09 10:54:57 2024 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -<%-- -DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - -Copyright 2021 Mike Becker. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright -notice, this list of conditions and the following disclaimer in the -documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---%> -<%@page pageEncoding="UTF-8" %> -<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> -<%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> - - - -
      - - - - - - - -
      diff -r 2696337baa3d -r 1eed60b779da src/main/webapp/WEB-INF/jsp/project-details.jsp --- a/src/main/webapp/WEB-INF/jsp/project-details.jsp Sat Nov 09 10:54:57 2024 +0100 +++ b/src/main/webapp/WEB-INF/jsp/project-details.jsp Sat Nov 09 11:47:20 2024 +0100 @@ -69,7 +69,7 @@

      - - () + ()

      diff -r 2696337baa3d -r 1eed60b779da src/main/webapp/WEB-INF/jsp/settings.jsp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main/webapp/WEB-INF/jsp/settings.jsp Sat Nov 09 11:47:20 2024 +0100 @@ -0,0 +1,59 @@ +<%-- +DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + +Copyright 2021 Mike Becker. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--%> +<%@page pageEncoding="UTF-8" %> +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> + + + +
      +

      +
      + + + + + + +
      +

      +
      + +
      + +
      diff -r 2696337baa3d -r 1eed60b779da src/main/webapp/WEB-INF/jsp/site.jsp --- a/src/main/webapp/WEB-INF/jsp/site.jsp Sat Nov 09 10:54:57 2024 +0100 +++ b/src/main/webapp/WEB-INF/jsp/site.jsp Sat Nov 09 11:47:20 2024 +0100 @@ -57,6 +57,9 @@ <%-- Define an alias for the optional JS file --%> +<%-- Define an alias for timezone --%> + + <%-- Load resource bundle --%> @@ -108,9 +111,9 @@