Compare commits
29 Commits
0999d41d64
...
youthgroup
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3726b9172c | ||
|
|
08442dc7ea | ||
|
|
b68933b676 | ||
|
|
c692f7881b | ||
| 72b91dd8bc | |||
| 44498c5ea1 | |||
| faa8140b0c | |||
|
|
1733821102 | ||
|
|
30fb52a606 | ||
|
|
bdc0d84e69 | ||
|
|
5d61ae6013 | ||
|
|
6feecb06c3 | ||
|
|
eef6295bae | ||
|
|
ebb603b569 | ||
|
|
a0a32563cc | ||
|
|
3c90142162 | ||
|
|
9c10da579c | ||
|
|
634c0d7b1c | ||
|
|
bf88306d85 | ||
|
|
a1ad23920a | ||
|
|
8d5a493bf7 | ||
|
|
d28f6b45fc | ||
|
|
e3ebc387bb | ||
|
|
aadfdfa9b5 | ||
|
|
e568589181 | ||
|
|
cffe483969 | ||
|
|
f1f9a5be9b | ||
|
|
47bcd311ea | ||
|
|
6fdd4a57e0 |
@@ -19,7 +19,7 @@
|
|||||||
<attribute name="test" value="true"/>
|
<attribute name="test" value="true"/>
|
||||||
</attributes>
|
</attributes>
|
||||||
</classpathentry>
|
</classpathentry>
|
||||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17/"/>
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-21/"/>
|
||||||
<classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.web.container"/>
|
<classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.web.container"/>
|
||||||
<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer">
|
<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer">
|
||||||
<attributes>
|
<attributes>
|
||||||
|
|||||||
4
.settings/org.eclipse.jdt.core.prefs
Normal file
4
.settings/org.eclipse.jdt.core.prefs
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
eclipse.preferences.version=1
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
|
||||||
|
org.eclipse.jdt.core.compiler.compliance=21
|
||||||
|
org.eclipse.jdt.core.compiler.source=21
|
||||||
@@ -3,5 +3,5 @@
|
|||||||
<fixed facet="jst.java"/>
|
<fixed facet="jst.java"/>
|
||||||
<fixed facet="jst.web"/>
|
<fixed facet="jst.web"/>
|
||||||
<installed facet="jst.web" version="2.4"/>
|
<installed facet="jst.web" version="2.4"/>
|
||||||
<installed facet="jst.java" version="17"/>
|
<installed facet="jst.java" version="21"/>
|
||||||
</faceted-project>
|
</faceted-project>
|
||||||
|
|||||||
44
build.gradle
44
build.gradle
@@ -1,21 +1,24 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id 'java'
|
id 'java'
|
||||||
id 'org.springframework.boot' version '3.1.3'
|
id 'org.springframework.boot' version '3.5.0'
|
||||||
id "io.spring.dependency-management" version "1.1.2"
|
id "io.spring.dependency-management" version "1.1.6"
|
||||||
id 'war'
|
id 'war'
|
||||||
id 'eclipse'
|
id 'eclipse'
|
||||||
id 'application'
|
id 'application'
|
||||||
}
|
}
|
||||||
|
|
||||||
group = 'de.jottyfan.bico'
|
group = 'de.jottyfan.bico'
|
||||||
version = '0.0.4'
|
version = '0.2.8'
|
||||||
|
|
||||||
description = """BibleClassOrganizer"""
|
description = """BibleClassOrganizer"""
|
||||||
|
|
||||||
sourceCompatibility = 17
|
java {
|
||||||
targetCompatibility = 17
|
toolchain {
|
||||||
|
languageVersion = JavaLanguageVersion.of(21)
|
||||||
mainClassName = "de.jottyfan.bico.Main"
|
}
|
||||||
|
sourceCompatibility = 21
|
||||||
|
targetCompatibility = 21
|
||||||
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
@@ -35,24 +38,32 @@ war {
|
|||||||
"Implementation-Timestamp": new Date())
|
"Implementation-Timestamp": new Date())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
baseName = project.name
|
archiveBaseName = project.name
|
||||||
version = version
|
archiveVersion = version
|
||||||
archiveName = 'BiCO.war'
|
archiveFileName = 'BiCO.war'
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'de.jottyfan:bicolib:4'
|
implementation 'de.jottyfan:bicolib:9'
|
||||||
|
|
||||||
|
implementation 'org.mnode.ical4j:ical4j:4.2.2'
|
||||||
|
|
||||||
implementation 'org.springframework.boot:spring-boot-starter-jooq'
|
implementation 'org.springframework.boot:spring-boot-starter-jooq'
|
||||||
|
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
|
||||||
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
|
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
|
||||||
implementation 'org.springframework.boot:spring-boot-starter-web'
|
implementation 'org.springframework.boot:spring-boot-starter-web'
|
||||||
|
implementation 'org.springframework.boot:spring-boot-starter-security'
|
||||||
implementation 'org.springframework.boot:spring-boot-starter-validation'
|
implementation 'org.springframework.boot:spring-boot-starter-validation'
|
||||||
implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect:latest.release'
|
implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect:latest.release'
|
||||||
|
implementation 'org.springframework.security:spring-security-oauth2-client'
|
||||||
|
|
||||||
implementation 'org.webjars:bootstrap:5.3.1'
|
implementation 'org.webjars:bootstrap:5.3.8'
|
||||||
implementation 'org.webjars.npm:bootstrap-icons:1.10.5'
|
implementation 'org.webjars.npm:bootstrap-icons:1.13.1'
|
||||||
implementation 'org.webjars:jquery:3.7.1'
|
implementation 'org.webjars:jquery:3.7.1'
|
||||||
implementation 'org.webjars:datatables:1.13.5'
|
implementation 'org.webjars.npm:datatables.net:2.3.5'
|
||||||
|
implementation 'org.webjars.npm:datatables.net-buttons:3.2.5'
|
||||||
|
implementation 'org.webjars.npm:datatables.net-responsive:3.0.6'
|
||||||
|
implementation 'org.webjars.npm:datatables.net-bs5:2.3.5'
|
||||||
|
|
||||||
implementation 'org.springframework.boot:spring-boot-devtools'
|
implementation 'org.springframework.boot:spring-boot-devtools'
|
||||||
|
|
||||||
@@ -69,3 +80,8 @@ test {
|
|||||||
springBoot {
|
springBoot {
|
||||||
buildInfo()
|
buildInfo()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tasks.withType(JavaCompile).configureEach {
|
||||||
|
options.compilerArgs.add("-parameters")
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
4
gradle/wrapper/gradle-wrapper.properties
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,5 +1,7 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip
|
||||||
|
networkTimeout=10000
|
||||||
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
|||||||
309
gradlew
vendored
309
gradlew
vendored
@@ -1,78 +1,127 @@
|
|||||||
#!/usr/bin/env sh
|
#!/bin/sh
|
||||||
|
|
||||||
|
#
|
||||||
|
# Copyright © 2015-2021 the original authors.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
##
|
#
|
||||||
## Gradle start up script for UN*X
|
# Gradle start up script for POSIX generated by Gradle.
|
||||||
##
|
#
|
||||||
|
# Important for running:
|
||||||
|
#
|
||||||
|
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||||
|
# noncompliant, but you have some other compliant shell such as ksh or
|
||||||
|
# bash, then to run this script, type that shell name before the whole
|
||||||
|
# command line, like:
|
||||||
|
#
|
||||||
|
# ksh Gradle
|
||||||
|
#
|
||||||
|
# Busybox and similar reduced shells will NOT work, because this script
|
||||||
|
# requires all of these POSIX shell features:
|
||||||
|
# * functions;
|
||||||
|
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||||
|
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||||
|
# * compound commands having a testable exit status, especially «case»;
|
||||||
|
# * various built-in commands including «command», «set», and «ulimit».
|
||||||
|
#
|
||||||
|
# Important for patching:
|
||||||
|
#
|
||||||
|
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||||
|
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||||
|
#
|
||||||
|
# The "traditional" practice of packing multiple parameters into a
|
||||||
|
# space-separated string is a well documented source of bugs and security
|
||||||
|
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||||
|
# options in "$@", and eventually passing that to Java.
|
||||||
|
#
|
||||||
|
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||||
|
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||||
|
# see the in-line comments for details.
|
||||||
|
#
|
||||||
|
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||||
|
# Darwin, MinGW, and NonStop.
|
||||||
|
#
|
||||||
|
# (3) This script is generated from the Groovy template
|
||||||
|
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||||
|
# within the Gradle project.
|
||||||
|
#
|
||||||
|
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||||
|
#
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
# Attempt to set APP_HOME
|
# Attempt to set APP_HOME
|
||||||
|
|
||||||
# Resolve links: $0 may be a link
|
# Resolve links: $0 may be a link
|
||||||
PRG="$0"
|
app_path=$0
|
||||||
# Need this for relative symlinks.
|
|
||||||
while [ -h "$PRG" ] ; do
|
# Need this for daisy-chained symlinks.
|
||||||
ls=`ls -ld "$PRG"`
|
while
|
||||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||||
if expr "$link" : '/.*' > /dev/null; then
|
[ -h "$app_path" ]
|
||||||
PRG="$link"
|
do
|
||||||
else
|
ls=$( ls -ld "$app_path" )
|
||||||
PRG=`dirname "$PRG"`"/$link"
|
link=${ls#*' -> '}
|
||||||
fi
|
case $link in #(
|
||||||
|
/*) app_path=$link ;; #(
|
||||||
|
*) app_path=$APP_HOME$link ;;
|
||||||
|
esac
|
||||||
done
|
done
|
||||||
SAVED="`pwd`"
|
|
||||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
|
||||||
APP_HOME="`pwd -P`"
|
|
||||||
cd "$SAVED" >/dev/null
|
|
||||||
|
|
||||||
APP_NAME="Gradle"
|
# This is normally unused
|
||||||
APP_BASE_NAME=`basename "$0"`
|
# shellcheck disable=SC2034
|
||||||
|
APP_BASE_NAME=${0##*/}
|
||||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||||
DEFAULT_JVM_OPTS=""
|
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
||||||
|
|
||||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
MAX_FD="maximum"
|
MAX_FD=maximum
|
||||||
|
|
||||||
warn () {
|
warn () {
|
||||||
echo "$*"
|
echo "$*"
|
||||||
}
|
} >&2
|
||||||
|
|
||||||
die () {
|
die () {
|
||||||
echo
|
echo
|
||||||
echo "$*"
|
echo "$*"
|
||||||
echo
|
echo
|
||||||
exit 1
|
exit 1
|
||||||
}
|
} >&2
|
||||||
|
|
||||||
# OS specific support (must be 'true' or 'false').
|
# OS specific support (must be 'true' or 'false').
|
||||||
cygwin=false
|
cygwin=false
|
||||||
msys=false
|
msys=false
|
||||||
darwin=false
|
darwin=false
|
||||||
nonstop=false
|
nonstop=false
|
||||||
case "`uname`" in
|
case "$( uname )" in #(
|
||||||
CYGWIN* )
|
CYGWIN* ) cygwin=true ;; #(
|
||||||
cygwin=true
|
Darwin* ) darwin=true ;; #(
|
||||||
;;
|
MSYS* | MINGW* ) msys=true ;; #(
|
||||||
Darwin* )
|
NONSTOP* ) nonstop=true ;;
|
||||||
darwin=true
|
|
||||||
;;
|
|
||||||
MINGW* )
|
|
||||||
msys=true
|
|
||||||
;;
|
|
||||||
NONSTOP* )
|
|
||||||
nonstop=true
|
|
||||||
;;
|
|
||||||
esac
|
esac
|
||||||
|
|
||||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
||||||
|
|
||||||
# Determine the Java command to use to start the JVM.
|
# Determine the Java command to use to start the JVM.
|
||||||
if [ -n "$JAVA_HOME" ] ; then
|
if [ -n "$JAVA_HOME" ] ; then
|
||||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||||
# IBM's JDK on AIX uses strange locations for the executables
|
# IBM's JDK on AIX uses strange locations for the executables
|
||||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||||
else
|
else
|
||||||
JAVACMD="$JAVA_HOME/bin/java"
|
JAVACMD=$JAVA_HOME/bin/java
|
||||||
fi
|
fi
|
||||||
if [ ! -x "$JAVACMD" ] ; then
|
if [ ! -x "$JAVACMD" ] ; then
|
||||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||||
@@ -81,92 +130,120 @@ Please set the JAVA_HOME variable in your environment to match the
|
|||||||
location of your Java installation."
|
location of your Java installation."
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
JAVACMD="java"
|
JAVACMD=java
|
||||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
if ! command -v java >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
|
||||||
Please set the JAVA_HOME variable in your environment to match the
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
location of your Java installation."
|
location of your Java installation."
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Increase the maximum file descriptors if we can.
|
# Increase the maximum file descriptors if we can.
|
||||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||||
MAX_FD_LIMIT=`ulimit -H -n`
|
case $MAX_FD in #(
|
||||||
if [ $? -eq 0 ] ; then
|
max*)
|
||||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||||
MAX_FD="$MAX_FD_LIMIT"
|
# shellcheck disable=SC2039,SC3045
|
||||||
fi
|
MAX_FD=$( ulimit -H -n ) ||
|
||||||
ulimit -n $MAX_FD
|
warn "Could not query maximum file descriptor limit"
|
||||||
if [ $? -ne 0 ] ; then
|
esac
|
||||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
case $MAX_FD in #(
|
||||||
fi
|
'' | soft) :;; #(
|
||||||
else
|
*)
|
||||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||||
fi
|
# shellcheck disable=SC2039,SC3045
|
||||||
fi
|
ulimit -n "$MAX_FD" ||
|
||||||
|
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||||
# For Darwin, add options to specify how the application appears in the dock
|
|
||||||
if $darwin; then
|
|
||||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
|
||||||
fi
|
|
||||||
|
|
||||||
# For Cygwin, switch paths to Windows format before running java
|
|
||||||
if $cygwin ; then
|
|
||||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
|
||||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
|
||||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
|
||||||
|
|
||||||
# We build the pattern for arguments to be converted via cygpath
|
|
||||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
|
||||||
SEP=""
|
|
||||||
for dir in $ROOTDIRSRAW ; do
|
|
||||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
|
||||||
SEP="|"
|
|
||||||
done
|
|
||||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
|
||||||
# Add a user-defined pattern to the cygpath arguments
|
|
||||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
|
||||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
|
||||||
fi
|
|
||||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
|
||||||
i=0
|
|
||||||
for arg in "$@" ; do
|
|
||||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
|
||||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
|
||||||
|
|
||||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
|
||||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
|
||||||
else
|
|
||||||
eval `echo args$i`="\"$arg\""
|
|
||||||
fi
|
|
||||||
i=$((i+1))
|
|
||||||
done
|
|
||||||
case $i in
|
|
||||||
(0) set -- ;;
|
|
||||||
(1) set -- "$args0" ;;
|
|
||||||
(2) set -- "$args0" "$args1" ;;
|
|
||||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
|
||||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
|
||||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
|
||||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
|
||||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
|
||||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
|
||||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
|
||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Escape application args
|
# Collect all arguments for the java command, stacking in reverse order:
|
||||||
save () {
|
# * args from the command line
|
||||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
# * the main class name
|
||||||
echo " "
|
# * -classpath
|
||||||
}
|
# * -D...appname settings
|
||||||
APP_ARGS=$(save "$@")
|
# * --module-path (only if needed)
|
||||||
|
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||||
|
|
||||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||||
eval set -- $DEFAULT_JVM_OPTS --illegal-access=permit $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
if "$cygwin" || "$msys" ; then
|
||||||
|
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||||
|
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||||
|
|
||||||
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||||
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
|
||||||
cd "$(dirname "$0")"
|
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||||
|
for arg do
|
||||||
|
if
|
||||||
|
case $arg in #(
|
||||||
|
-*) false ;; # don't mess with options #(
|
||||||
|
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||||
|
[ -e "$t" ] ;; #(
|
||||||
|
*) false ;;
|
||||||
|
esac
|
||||||
|
then
|
||||||
|
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||||
|
fi
|
||||||
|
# Roll the args list around exactly as many times as the number of
|
||||||
|
# args, so each arg winds up back in the position where it started, but
|
||||||
|
# possibly modified.
|
||||||
|
#
|
||||||
|
# NB: a `for` loop captures its iteration list before it begins, so
|
||||||
|
# changing the positional parameters here affects neither the number of
|
||||||
|
# iterations, nor the values presented in `arg`.
|
||||||
|
shift # remove old arg
|
||||||
|
set -- "$@" "$arg" # push replacement arg
|
||||||
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||||
|
|
||||||
|
# Collect all arguments for the java command:
|
||||||
|
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||||
|
# and any embedded shellness will be escaped.
|
||||||
|
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||||
|
# treated as '${Hostname}' itself on the command line.
|
||||||
|
|
||||||
|
set -- \
|
||||||
|
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||||
|
-classpath "$CLASSPATH" \
|
||||||
|
org.gradle.wrapper.GradleWrapperMain \
|
||||||
|
"$@"
|
||||||
|
|
||||||
|
# Stop when "xargs" is not available.
|
||||||
|
if ! command -v xargs >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
die "xargs is not available"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Use "xargs" to parse quoted args.
|
||||||
|
#
|
||||||
|
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||||
|
#
|
||||||
|
# In Bash we could simply go:
|
||||||
|
#
|
||||||
|
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||||
|
# set -- "${ARGS[@]}" "$@"
|
||||||
|
#
|
||||||
|
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||||
|
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||||
|
# character that might be a shell metacharacter, then use eval to reverse
|
||||||
|
# that process (while maintaining the separation between arguments), and wrap
|
||||||
|
# the whole thing up as a single "set" statement.
|
||||||
|
#
|
||||||
|
# This will of course break if any of these variables contains a newline or
|
||||||
|
# an unmatched quote.
|
||||||
|
#
|
||||||
|
|
||||||
|
eval "set -- $(
|
||||||
|
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||||
|
xargs -n1 |
|
||||||
|
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||||
|
tr '\n' ' '
|
||||||
|
)" '"$@"'
|
||||||
|
|
||||||
exec "$JAVACMD" "$@"
|
exec "$JAVACMD" "$@"
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package de.jottyfan.bico;
|
package de.jottyfan.bico;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||||
@@ -12,6 +14,9 @@ import org.springframework.boot.web.servlet.support.SpringBootServletInitializer
|
|||||||
*/
|
*/
|
||||||
@SpringBootApplication
|
@SpringBootApplication
|
||||||
public class Main extends SpringBootServletInitializer {
|
public class Main extends SpringBootServletInitializer {
|
||||||
|
|
||||||
|
public static final Logger LOGGER = LogManager.getLogger(Main.class);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
|
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
|
||||||
return application.sources(Main.class);
|
return application.sources(Main.class);
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy;
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
public class DatabaseConfiguration {
|
public class DatabaseConfig {
|
||||||
@Autowired
|
@Autowired
|
||||||
private DataSource dataSource;
|
private DataSource dataSource;
|
||||||
|
|
||||||
26
src/main/java/de/jottyfan/bico/config/SecurityConfig.java
Normal file
26
src/main/java/de/jottyfan/bico/config/SecurityConfig.java
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package de.jottyfan.bico.config;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author jotty
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class SecurityConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||||
|
http.authorizeHttpRequests(
|
||||||
|
// @formatter:off
|
||||||
|
r -> r.requestMatchers("/", "/error", "/css/**", "/js/**", "/webjars/**", "/template").permitAll()
|
||||||
|
.requestMatchers("/**").authenticated())
|
||||||
|
.oauth2Login(l -> l.authorizationEndpoint(e -> e.baseUri("/oauth2/authorize-client")));
|
||||||
|
// @formatter:on
|
||||||
|
return http.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +1,16 @@
|
|||||||
package de.jottyfan.bico.modules;
|
package de.jottyfan.bico.modules;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import java.security.Principal;
|
||||||
import org.springframework.ui.Model;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
|
||||||
|
import org.springframework.security.oauth2.core.user.OAuth2User;
|
||||||
|
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||||
|
|
||||||
|
import de.jottyfan.bico.Main;
|
||||||
import de.jottyfan.bico.modules.profile.ProfileService;
|
import de.jottyfan.bico.modules.profile.ProfileService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -11,19 +19,88 @@ import de.jottyfan.bico.modules.profile.ProfileService;
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public abstract class CommonController {
|
public abstract class CommonController {
|
||||||
|
private static final List<String> admins = List.of("jotty");
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ProfileService profileService;
|
private ProfileService profileService;
|
||||||
|
|
||||||
|
@Value("${spring.security.oauth2.client.provider.nextcloud.issuer-uri}")
|
||||||
|
private String nextcloudUrl;
|
||||||
|
|
||||||
|
@ModelAttribute("isCampAdmin")
|
||||||
|
public Boolean isCampAdmin(Principal principal) {
|
||||||
|
return principal == null ? false : admins.contains(principal.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ModelAttribute("currentUserName")
|
||||||
|
public String getUserFullname(Principal principal) {
|
||||||
|
OAuth2AuthenticationToken token = (OAuth2AuthenticationToken) principal;
|
||||||
|
if (token != null) {
|
||||||
|
OAuth2User user = token.getPrincipal();
|
||||||
|
String nextcloudUsername = user.getName();
|
||||||
|
String name = nextcloudUsername.replace(".", " ").replace("oe", "ö").replace("ae", "ä").replace("ue", "ü");
|
||||||
|
return name;
|
||||||
|
} else {
|
||||||
|
Main.LOGGER.warn("Token is null, so no username can be found. Returned empty string instead.");
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ModelAttribute("hasBUrole")
|
||||||
|
public Boolean hasBURole(Principal principal) {
|
||||||
|
OAuth2AuthenticationToken token = (OAuth2AuthenticationToken) principal;
|
||||||
|
if (token != null) {
|
||||||
|
OAuth2User user = token.getPrincipal();
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
List<String> roles = (List<String>) user.getAttributes().get("roles");
|
||||||
|
return roles.contains("Bibelunterricht");
|
||||||
|
} else {
|
||||||
|
Main.LOGGER.warn("token is null, no roles can be detected");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ModelAttribute("hasDateRole")
|
||||||
|
public Boolean hasDateRole(Principal principal) {
|
||||||
|
OAuth2AuthenticationToken token = (OAuth2AuthenticationToken) principal;
|
||||||
|
if (token != null) {
|
||||||
|
OAuth2User user = token.getPrincipal();
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
List<String> roles = (List<String>) user.getAttributes().get("roles");
|
||||||
|
return roles.contains("Kinderstunde klein");
|
||||||
|
} else {
|
||||||
|
Main.LOGGER.warn("token is null, no roles can be detected");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ModelAttribute("hasAnyRole")
|
||||||
|
public Boolean hasAnyRole(Principal principal) {
|
||||||
|
OAuth2AuthenticationToken token = (OAuth2AuthenticationToken) principal;
|
||||||
|
if (token != null) {
|
||||||
|
OAuth2User user = token.getPrincipal();
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
List<String> roles = (List<String>) user.getAttributes().get("roles");
|
||||||
|
return roles.size() > 0;
|
||||||
|
} else {
|
||||||
|
Main.LOGGER.warn("token is null, no roles can be detected");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get the theme for the current session
|
* get the theme for the current session
|
||||||
*
|
*
|
||||||
* @return the theme; light or dark at the moment
|
* @return the theme; light or dark at the moment
|
||||||
*/
|
*/
|
||||||
public Model useThemedModel(Model model) {
|
@ModelAttribute("theme")
|
||||||
// TODO: add profile's user name
|
public String getTheme() {
|
||||||
String username = "jotty";
|
String username = SecurityContextHolder.getContext().getAuthentication().getName();
|
||||||
model.addAttribute("theme", profileService.getTheme(username));
|
return profileService.getTheme(username);
|
||||||
return model;
|
}
|
||||||
|
|
||||||
|
@ModelAttribute("nextcloudUrl")
|
||||||
|
public String getNextcloudUrl() {
|
||||||
|
return nextcloudUrl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package de.jottyfan.bico.modules.download;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||||
|
|
||||||
|
import de.jottyfan.bico.modules.CommonController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author jotty
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Controller
|
||||||
|
public class DownloadController extends CommonController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DownloadService service;
|
||||||
|
|
||||||
|
@GetMapping(value = "/download", produces = "text/csv")
|
||||||
|
@ResponseBody
|
||||||
|
@ResponseStatus(HttpStatus.OK)
|
||||||
|
public String download() {
|
||||||
|
return service.getCsv();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package de.jottyfan.bico.modules.download;
|
||||||
|
|
||||||
|
import static de.jottyfan.bico.db.Tables.V_CALENDAR;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.jooq.DSLContext;
|
||||||
|
import org.jooq.SelectWhereStep;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import de.jottyfan.bico.db.tables.records.VCalendarRecord;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author jotty
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Repository
|
||||||
|
public class DownloadRepository {
|
||||||
|
private static final Logger LOGGER = LogManager.getLogger(DownloadRepository.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DSLContext jooq;
|
||||||
|
|
||||||
|
public String getCsv() {
|
||||||
|
SelectWhereStep<VCalendarRecord> sql = jooq.selectFrom(V_CALENDAR);
|
||||||
|
LOGGER.trace(sql);
|
||||||
|
return sql.fetch().formatCSV();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package de.jottyfan.bico.modules.download;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author jotty
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class DownloadService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DownloadRepository repository;
|
||||||
|
|
||||||
|
public String getCsv() {
|
||||||
|
return repository.getCsv();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package de.jottyfan.bico.modules.ical;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
|
||||||
|
import de.jottyfan.bico.modules.CommonController;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author jotty
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Controller
|
||||||
|
public class IcalController extends CommonController{
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IcalService service;
|
||||||
|
|
||||||
|
@GetMapping("/ical")
|
||||||
|
public void getIcalExport(HttpServletResponse response) throws Exception {
|
||||||
|
response.setHeader("Content-Disposition", "attachment; filename=bico.ics");
|
||||||
|
response.setContentType("application/octet-stream");
|
||||||
|
response.setHeader("Content-Transfer-Encoding", "binary");
|
||||||
|
response.setHeader("Accept-Ranges", "bytes");
|
||||||
|
service.createCalendar(response.getOutputStream());
|
||||||
|
response.flushBuffer();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package de.jottyfan.bico.modules.ical;
|
||||||
|
|
||||||
|
import static de.jottyfan.bico.db.Tables.V_CALENDAR;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.jooq.DSLContext;
|
||||||
|
import org.jooq.SelectWhereStep;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import de.jottyfan.bico.db.tables.records.VCalendarRecord;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author jotty
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Repository
|
||||||
|
public class IcalRepository {
|
||||||
|
private static final Logger LOGGER = LogManager.getLogger(IcalRepository.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DSLContext jooq;
|
||||||
|
|
||||||
|
public VCalendarRecord[] getAllDates() {
|
||||||
|
SelectWhereStep<VCalendarRecord> sql = jooq.selectFrom(V_CALENDAR);
|
||||||
|
LOGGER.trace(sql);
|
||||||
|
return sql.fetchArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
43
src/main/java/de/jottyfan/bico/modules/ical/IcalService.java
Normal file
43
src/main/java/de/jottyfan/bico/modules/ical/IcalService.java
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
package de.jottyfan.bico.modules.ical;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.LocalTime;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import de.jottyfan.bico.db.tables.records.VCalendarRecord;
|
||||||
|
import net.fortuna.ical4j.data.CalendarOutputter;
|
||||||
|
import net.fortuna.ical4j.model.Calendar;
|
||||||
|
import net.fortuna.ical4j.model.component.VEvent;
|
||||||
|
import net.fortuna.ical4j.validate.ValidationException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author jotty
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class IcalService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IcalRepository repository;
|
||||||
|
|
||||||
|
public void createCalendar(OutputStream stream) throws ValidationException, IOException {
|
||||||
|
Calendar calendar = new Calendar();
|
||||||
|
CalendarOutputter out = new CalendarOutputter();
|
||||||
|
for (VCalendarRecord record : repository.getAllDates()) {
|
||||||
|
String groupname = "";
|
||||||
|
groupname = record.getBibleclass() ? "Bibelunterricht" : groupname;
|
||||||
|
groupname = record.getYouthgroup() ? "Jungschar" : groupname;
|
||||||
|
String summary = String.format("%s %s", record.getFullname(), groupname).trim();
|
||||||
|
LocalDateTime startEvent = LocalDateTime.of(record.getSlotDay(), LocalTime.of(10, 30));
|
||||||
|
LocalDateTime endEvent = LocalDateTime.of(record.getSlotDay(), LocalTime.of(12, 0));
|
||||||
|
VEvent event = new VEvent(startEvent, endEvent, summary);
|
||||||
|
calendar.add(event);
|
||||||
|
}
|
||||||
|
out.output(calendar, stream);;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
package de.jottyfan.bico.modules.index;
|
package de.jottyfan.bico.modules.index;
|
||||||
|
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.ui.Model;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
|
||||||
import de.jottyfan.bico.modules.CommonController;
|
import de.jottyfan.bico.modules.CommonController;
|
||||||
@@ -14,8 +13,7 @@ import de.jottyfan.bico.modules.CommonController;
|
|||||||
@Controller
|
@Controller
|
||||||
public class IndexController extends CommonController {
|
public class IndexController extends CommonController {
|
||||||
@GetMapping("/")
|
@GetMapping("/")
|
||||||
public String getIndex(Model model) {
|
public String getIndex() {
|
||||||
useThemedModel(model);
|
return "redirect:/next";
|
||||||
return "redirect:/sheet";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,10 +23,10 @@ import de.jottyfan.bico.db.tables.records.TLessonRecord;
|
|||||||
import de.jottyfan.bico.db.tables.records.TPersonRecord;
|
import de.jottyfan.bico.db.tables.records.TPersonRecord;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author jotty
|
* @author jotty
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@Repository
|
@Repository
|
||||||
public class LessonRepository {
|
public class LessonRepository {
|
||||||
private final static Logger LOGGER = LogManager.getLogger(LessonRepository.class);
|
private final static Logger LOGGER = LogManager.getLogger(LessonRepository.class);
|
||||||
@@ -50,7 +50,7 @@ public class LessonRepository {
|
|||||||
.values(slotId)
|
.values(slotId)
|
||||||
.returning(T_LESSON.PK_LESSON);
|
.returning(T_LESSON.PK_LESSON);
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
LOGGER.trace(sql);
|
LOGGER.info(sql);
|
||||||
Integer pkLesson = sql2.fetchOne(T_LESSON.PK_LESSON);
|
Integer pkLesson = sql2.fetchOne(T_LESSON.PK_LESSON);
|
||||||
r = new TLessonRecord();
|
r = new TLessonRecord();
|
||||||
r.setPkLesson(pkLesson);
|
r.setPkLesson(pkLesson);
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package de.jottyfan.bico.modules.next;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.ui.Model;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
|
||||||
|
import de.jottyfan.bico.modules.CommonController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author jotty
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Controller
|
||||||
|
public class NextController extends CommonController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private NextService service;
|
||||||
|
|
||||||
|
@GetMapping("/next")
|
||||||
|
public String getNext(Model model) {
|
||||||
|
model.addAttribute("list", service.getNext(LocalDate.now()));
|
||||||
|
return "/next";
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/next/{date}")
|
||||||
|
public String getNextForDate(@PathVariable("date") String dateStr, Model model) {
|
||||||
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
||||||
|
LocalDate date = LocalDate.parse(dateStr, formatter);
|
||||||
|
model.addAttribute("list", service.getNext(date));
|
||||||
|
return "/next";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
package de.jottyfan.bico.modules.next;
|
||||||
|
|
||||||
|
import static de.jottyfan.bico.db.Tables.V_CALENDAR;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.jooq.DSLContext;
|
||||||
|
import org.jooq.Record4;
|
||||||
|
import org.jooq.SelectSeekStep1;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import de.jottyfan.bico.modules.next.model.NextBean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author jotty
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Repository
|
||||||
|
public class NextRepository {
|
||||||
|
private static final Logger LOGGER = LogManager.getLogger(NextRepository.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DSLContext jooq;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the next dates from date on
|
||||||
|
*
|
||||||
|
* @param date the date
|
||||||
|
* @return the next dates as beans in a list; an empty list at least
|
||||||
|
*/
|
||||||
|
public List<NextBean> getNext(LocalDate date) {
|
||||||
|
SelectSeekStep1<Record4<String, LocalDate, Boolean, Boolean>, LocalDate> sql = jooq
|
||||||
|
// @formatter:off
|
||||||
|
.selectDistinct(V_CALENDAR.FULLNAME, V_CALENDAR.SLOT_DAY, V_CALENDAR.BIBLECLASS, V_CALENDAR.YOUTHGROUP)
|
||||||
|
.from(V_CALENDAR)
|
||||||
|
.where(V_CALENDAR.SLOT_DAY.ge(date))
|
||||||
|
.orderBy(V_CALENDAR.SLOT_DAY.asc());
|
||||||
|
// @formatter:on
|
||||||
|
LOGGER.trace(sql);
|
||||||
|
Iterator<Record4<String, LocalDate, Boolean, Boolean>> i = sql.fetch().iterator();
|
||||||
|
List<NextBean> list = new ArrayList<>();
|
||||||
|
while (i.hasNext()) {
|
||||||
|
Record4<String, LocalDate, Boolean, Boolean> r = i.next();
|
||||||
|
list.add(NextBean.of(r.get(V_CALENDAR.FULLNAME), r.get(V_CALENDAR.SLOT_DAY), r.get(V_CALENDAR.BIBLECLASS), r.get(V_CALENDAR.YOUTHGROUP)));
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
32
src/main/java/de/jottyfan/bico/modules/next/NextService.java
Normal file
32
src/main/java/de/jottyfan/bico/modules/next/NextService.java
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
package de.jottyfan.bico.modules.next;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import de.jottyfan.bico.modules.next.model.NextBean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author jotty
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class NextService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private NextRepository repository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the next dates
|
||||||
|
*
|
||||||
|
* @param date the date
|
||||||
|
* @return the list of next dates
|
||||||
|
*/
|
||||||
|
public List<NextBean> getNext(LocalDate date) {
|
||||||
|
return repository.getNext(date);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
package de.jottyfan.bico.modules.next.model;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author jotty
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class NextBean implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private String fullname;
|
||||||
|
private LocalDate day;
|
||||||
|
private Boolean isBibleclass;
|
||||||
|
private Boolean isYouthgroup;
|
||||||
|
|
||||||
|
private NextBean() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public final static NextBean of(String fullname, LocalDate day, Boolean isBibleclass, Boolean isYouthgroup) {
|
||||||
|
NextBean bean = new NextBean();
|
||||||
|
bean.setDay(day);
|
||||||
|
bean.setFullname(fullname);
|
||||||
|
bean.setIsBibleclass(isBibleclass);
|
||||||
|
bean.setIsYouthgroup(isYouthgroup);
|
||||||
|
return bean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the fullname
|
||||||
|
*/
|
||||||
|
public String getFullname() {
|
||||||
|
return fullname;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the day
|
||||||
|
*/
|
||||||
|
public LocalDate getDay() {
|
||||||
|
return day;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param fullname the fullname to set
|
||||||
|
*/
|
||||||
|
private void setFullname(String fullname) {
|
||||||
|
this.fullname = fullname;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param day the day to set
|
||||||
|
*/
|
||||||
|
private void setDay(LocalDate day) {
|
||||||
|
this.day = day;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the isBibleclass
|
||||||
|
*/
|
||||||
|
public Boolean getIsBibleclass() {
|
||||||
|
return isBibleclass;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param isBibleclass the isBibleclass to set
|
||||||
|
*/
|
||||||
|
public void setIsBibleclass(Boolean isBibleclass) {
|
||||||
|
this.isBibleclass = isBibleclass;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the isYouthgroup
|
||||||
|
*/
|
||||||
|
public Boolean getIsYouthgroup() {
|
||||||
|
return isYouthgroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param isYouthgroup the isYouthgroup to set
|
||||||
|
*/
|
||||||
|
public void setIsYouthgroup(Boolean isYouthgroup) {
|
||||||
|
this.isYouthgroup = isYouthgroup;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -25,7 +25,7 @@ public class ProfileController extends CommonController {
|
|||||||
* @param theme the theme
|
* @param theme the theme
|
||||||
*/
|
*/
|
||||||
@PostMapping("/updateTheme/{theme}")
|
@PostMapping("/updateTheme/{theme}")
|
||||||
public ResponseEntity<?> updateTheme(@PathVariable String theme) {
|
public ResponseEntity<?> updateTheme(@PathVariable("theme") String theme) {
|
||||||
// TODO: add profile's user name
|
// TODO: add profile's user name
|
||||||
String username = "jotty";
|
String username = "jotty";
|
||||||
service.updateTheme(username, theme);
|
service.updateTheme(username, theme);
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ public class SheetController extends CommonController {
|
|||||||
|
|
||||||
@GetMapping("/sheet")
|
@GetMapping("/sheet")
|
||||||
public String getSheet(Model model) {
|
public String getSheet(Model model) {
|
||||||
useThemedModel(model).addAttribute("list", service.getList());
|
model.addAttribute("list", service.getList());
|
||||||
return "/sheet";
|
return "/sheet";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ public class SheetRepository {
|
|||||||
private DSLContext jooq;
|
private DSLContext jooq;
|
||||||
|
|
||||||
public List<VCalendarRecord> getList() {
|
public List<VCalendarRecord> getList() {
|
||||||
SelectWhereStep<VCalendarRecord> sql = jooq.selectFrom(V_CALENDAR);
|
SelectWhereStep<VCalendarRecord> sql = jooq.selectFrom(V_CALENDAR);
|
||||||
LOGGER.trace(sql);
|
LOGGER.trace(sql);
|
||||||
return sql.fetch().stream().toList();
|
return sql.fetch().stream().toList();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
package de.jottyfan.bico.modules.slot;
|
package de.jottyfan.bico.modules.slot;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.ui.Model;
|
import org.springframework.ui.Model;
|
||||||
@@ -9,6 +12,7 @@ import org.springframework.web.bind.annotation.ModelAttribute;
|
|||||||
import org.springframework.web.bind.annotation.PathVariable;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
|
||||||
|
import de.jottyfan.bico.db.enums.EnumGroupname;
|
||||||
import de.jottyfan.bico.modules.CommonController;
|
import de.jottyfan.bico.modules.CommonController;
|
||||||
import de.jottyfan.bico.modules.slot.model.SlotBean;
|
import de.jottyfan.bico.modules.slot.model.SlotBean;
|
||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
@@ -30,20 +34,21 @@ public class SlotController extends CommonController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/slot/{id}")
|
@GetMapping("/slot/{id}")
|
||||||
public String load(@PathVariable Integer id, Model model) {
|
public String load(@PathVariable("id") Integer id, Model model) {
|
||||||
model.addAttribute("bean", id == null ? new SlotBean() : service.loadSlot(id));
|
model.addAttribute("bean", id == null ? new SlotBean() : service.loadSlot(id));
|
||||||
model.addAttribute("hasLesson", service.slotHasLesson(id));
|
model.addAttribute("hasLesson", service.slotHasLesson(id));
|
||||||
|
model.addAttribute("groupnames", EnumGroupname.values());
|
||||||
return "/slot/item";
|
return "/slot/item";
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/slot/{id}/delete")
|
@GetMapping("/slot/{id}/delete")
|
||||||
public String loadEnsurance(@PathVariable Integer id, Model model) {
|
public String loadEnsurance(@PathVariable("id") Integer id, Model model) {
|
||||||
model.addAttribute("bean", service.loadDeletableSlot(id));
|
model.addAttribute("bean", service.loadDeletableSlot(id));
|
||||||
return "/slot/delete";
|
return "/slot/delete";
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/slot/{id}/destroy")
|
@GetMapping("/slot/{id}/destroy")
|
||||||
public String destroy(@PathVariable Integer id, Model model) {
|
public String destroy(@PathVariable("id") Integer id, Model model) {
|
||||||
service.removeSlot(id);
|
service.removeSlot(id);
|
||||||
return "redirect:/";
|
return "redirect:/";
|
||||||
}
|
}
|
||||||
@@ -56,4 +61,12 @@ public class SlotController extends CommonController {
|
|||||||
service.saveSlot(bean);
|
service.saveSlot(bean);
|
||||||
return "redirect:/sheet";
|
return "redirect:/sheet";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ModelAttribute("groupnamemap")
|
||||||
|
public Map<String, String> getTranslations() {
|
||||||
|
Map<String, String> map = new HashMap<>();
|
||||||
|
map.put("bibleclass", "Bibelunterricht");
|
||||||
|
map.put("youthgroup", "Jungschar");
|
||||||
|
return map;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ public class SlotRepository {
|
|||||||
bean.setPkSlot(r.getPkSlot());
|
bean.setPkSlot(r.getPkSlot());
|
||||||
bean.setSlotDay(r.getSlotDay());
|
bean.setSlotDay(r.getSlotDay());
|
||||||
bean.setNote(r.getNote());
|
bean.setNote(r.getNote());
|
||||||
|
bean.setGroupname(r.getGroupname());
|
||||||
}
|
}
|
||||||
return bean;
|
return bean;
|
||||||
}
|
}
|
||||||
@@ -67,8 +68,9 @@ public class SlotRepository {
|
|||||||
// @formatter:off
|
// @formatter:off
|
||||||
.insertInto(T_SLOT,
|
.insertInto(T_SLOT,
|
||||||
T_SLOT.SLOT_DAY,
|
T_SLOT.SLOT_DAY,
|
||||||
|
T_SLOT.GROUPNAME,
|
||||||
T_SLOT.NOTE)
|
T_SLOT.NOTE)
|
||||||
.values(slot.getSlotDay(), slot.getNote())
|
.values(slot.getSlotDay(), slot.getGroupname(), slot.getNote())
|
||||||
.returning(T_SLOT.PK_SLOT);
|
.returning(T_SLOT.PK_SLOT);
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
LOGGER.trace(sql);
|
LOGGER.trace(sql);
|
||||||
@@ -86,6 +88,7 @@ public class SlotRepository {
|
|||||||
.update(T_SLOT)
|
.update(T_SLOT)
|
||||||
.set(T_SLOT.SLOT_DAY, slot.getSlotDay())
|
.set(T_SLOT.SLOT_DAY, slot.getSlotDay())
|
||||||
.set(T_SLOT.NOTE, slot.getNote())
|
.set(T_SLOT.NOTE, slot.getNote())
|
||||||
|
.set(T_SLOT.GROUPNAME, slot.getGroupname())
|
||||||
.where(T_SLOT.PK_SLOT.eq(slot.getPkSlot()));
|
.where(T_SLOT.PK_SLOT.eq(slot.getPkSlot()));
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
LOGGER.trace(sql);
|
LOGGER.trace(sql);
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import java.time.LocalDate;
|
|||||||
|
|
||||||
import org.springframework.format.annotation.DateTimeFormat;
|
import org.springframework.format.annotation.DateTimeFormat;
|
||||||
|
|
||||||
|
import de.jottyfan.bico.db.enums.EnumGroupname;
|
||||||
import jakarta.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -25,6 +26,8 @@ public class SlotBean implements Serializable {
|
|||||||
|
|
||||||
private String note;
|
private String note;
|
||||||
|
|
||||||
|
private EnumGroupname groupname;
|
||||||
|
|
||||||
public SlotBean withNote(String note) {
|
public SlotBean withNote(String note) {
|
||||||
this.note = note;
|
this.note = note;
|
||||||
return this;
|
return this;
|
||||||
@@ -71,4 +74,18 @@ public class SlotBean implements Serializable {
|
|||||||
public void setNote(String note) {
|
public void setNote(String note) {
|
||||||
this.note = note;
|
this.note = note;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the groupname
|
||||||
|
*/
|
||||||
|
public EnumGroupname getGroupname() {
|
||||||
|
return groupname;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param groupname the groupname to set
|
||||||
|
*/
|
||||||
|
public void setGroupname(EnumGroupname groupname) {
|
||||||
|
this.groupname = groupname;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"properties": [
|
||||||
|
{
|
||||||
|
"name": "nextcloud.url",
|
||||||
|
"type": "java.lang.String",
|
||||||
|
"description": "the URL to nextcloud for logout operations"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -9,17 +9,10 @@ spring.datasource.password = ${db.password}
|
|||||||
|
|
||||||
server.servlet.context-path = ${my.context-path:/BiCO}
|
server.servlet.context-path = ${my.context-path:/BiCO}
|
||||||
|
|
||||||
# security
|
# nextcloud open ID connection
|
||||||
spring.security.oauth2.client.registration.keycloak.client-id = ${keycloak.client-id}
|
spring.security.oauth2.client.provider.nextcloud.issuer-uri = ${nextcloud.issuer-uri}
|
||||||
spring.security.oauth2.client.registration.keycloak.scope = openid
|
spring.security.oauth2.client.registration.nextcloud.client-id = ${nextcloud.client-id}
|
||||||
spring.security.oauth2.client.registration.keycloak.authorization-grant-type = authorization_code
|
spring.security.oauth2.client.registration.nextcloud.client-secret = ${nextcloud.client-secret}
|
||||||
spring.security.oauth2.client.registration.keycloak.redirect-uri = ${keycloak.redirect-uri}
|
spring.security.oauth2.client.registration.nextcloud.authorization-grant-type = authorization_code
|
||||||
spring.security.oauth2.client.provider.keycloak.issuer-uri = ${keycloak.issuer-uri}
|
spring.security.oauth2.client.registration.nextcloud.redirect-uri = ${nextcloud.redirect-uri}
|
||||||
spring.security.oauth2.client.provider.keycloak.authorization-uri = ${keycloak.openid-url}/auth
|
spring.security.oauth2.client.registration.nextcloud.client-authentication-method = client_secret_post
|
||||||
spring.security.oauth2.client.provider.keycloak.token-uri = ${keycloak.openid-url}/token
|
|
||||||
spring.security.oauth2.client.provider.keycloak.user-info-uri = ${keycloak.openid-url}/userinfo
|
|
||||||
spring.security.oauth2.client.provider.keycloak.jwk-set-uri = ${keycloak.openid-url}/certs
|
|
||||||
spring.security.oauth2.client.provider.keycloak.user-name-attribute = preferred_username
|
|
||||||
|
|
||||||
# for development only
|
|
||||||
server.port = 8081
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.rightaligned {
|
.rightaligned {
|
||||||
right: 5px;
|
right: 20px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,3 +51,66 @@ body {
|
|||||||
width: 400px;
|
width: 400px;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.campbadge {
|
||||||
|
border: 1px solid #222;
|
||||||
|
color: #222;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-bs-theme=dark] .campbadge {
|
||||||
|
border-color: silver;
|
||||||
|
color: silver;
|
||||||
|
}
|
||||||
|
|
||||||
|
.full-size {
|
||||||
|
width: 100% !important;
|
||||||
|
max-width: inherit !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag {
|
||||||
|
transform: rotate(270deg);
|
||||||
|
-webkit-transform: rotate(270deg); /* Safari, Chrome */
|
||||||
|
-moz-transform: rotate(270deg); /* Firefox */
|
||||||
|
-ms-transform: rotate(270deg); /* IE 9 */
|
||||||
|
-o-transform: rotate(270deg); /* Opera */
|
||||||
|
font-size: small;
|
||||||
|
position: absolute;
|
||||||
|
left: -16px;
|
||||||
|
top: 24px;
|
||||||
|
border-bottom: 1px dashed silver;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tagbu {
|
||||||
|
background: linear-gradient(to bottom, yellow, white);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-bs-theme=dark] .tagbu {
|
||||||
|
background: none;
|
||||||
|
color: yellow;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tagju {
|
||||||
|
background: linear-gradient(to bottom, lime, white);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-bs-theme=dark] .tagju {
|
||||||
|
background: none;
|
||||||
|
color: lime;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tagfollow {
|
||||||
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tagemphasize {
|
||||||
|
font-weight: bolder;
|
||||||
|
color: #ff4444;
|
||||||
|
}
|
||||||
|
|
||||||
|
.smallbadge {
|
||||||
|
font-size: small;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-bs-theme=dark] .smallbadge {
|
||||||
|
font-size: small;
|
||||||
|
}
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 206 KiB |
BIN
src/main/resources/static/images/PastedGraphic-2.png
Normal file
BIN
src/main/resources/static/images/PastedGraphic-2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 55 KiB |
@@ -1,7 +1,7 @@
|
|||||||
toggleDarkMode = function() {
|
toggleDarkMode = function() {
|
||||||
var oldValue = $("html").attr("data-bs-theme");
|
var oldValue = $("html").attr("data-bs-theme");
|
||||||
var newValue = oldValue == "dark" ? "light" : "dark";
|
var newValue = oldValue == "dark" ? "light" : "dark";
|
||||||
var updateUrl = /*[[@{/updateTheme}]]*/ 'updateTheme';
|
var updateUrl = /*[[@{/updateTheme}]]*/ '/BiCO/updateTheme';
|
||||||
updateUrl = updateUrl + "/" + newValue;
|
updateUrl = updateUrl + "/" + newValue;
|
||||||
$("html").attr("data-bs-theme", newValue);
|
$("html").attr("data-bs-theme", newValue);
|
||||||
$.ajax({
|
$.ajax({
|
||||||
|
|||||||
122
src/main/resources/templates/camp/edit.html
Normal file
122
src/main/resources/templates/camp/edit.html
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html xmlns:th="http://www.thymeleaf.org" layout:decorate="~{template}" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
|
||||||
|
<body>
|
||||||
|
<th:block layout:fragment="content">
|
||||||
|
<div class="borderdist">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row g-2">
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<h2>Anmeldung zur Gemeindefreizeit 2025 bearbeiten</h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="alert alert-danger" th:unless="${bean}">Sie haben keine Berechtigung, die Anmeldung mit dieser URL zu ändern.</div>
|
||||||
|
<form th:action="@{/camp/registration/correct}" method="post" th:object="${bean}" th:if="${bean}">
|
||||||
|
<input type="hidden" th:field="*{pkRegistration}" />
|
||||||
|
<div class="row g-3">
|
||||||
|
|
||||||
|
<div class="col-sm-3">Vorname</div>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<span th:if="${#fields.hasErrors('forename')}" th:errors="*{forename}" class="text-danger"></span> <input type="text" th:field="*{forename}" class="form-control" />
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-3">Nachname</div>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<span th:if="${#fields.hasErrors('surname')}" th:errors="*{surname}" class="text-danger"></span> <input type="text" th:field="*{surname}" class="form-control" />
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-3">Geschlecht</div>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<span th:if="${#fields.hasErrors('sex')}" th:errors="*{sex}" class="text-danger"></span> <select th:field="*{sex}" class="form-select">
|
||||||
|
<option value="">--- bitte wählen ---</option>
|
||||||
|
<option th:each="s : ${sexes}" th:value="${s}" th:text="${s}"></option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-3">Alter</div>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<span th:if="${#fields.hasErrors('fkAge')}" th:errors="*{fkAge}" class="text-danger"></span>
|
||||||
|
<select th:field="*{fkAge}" class="form-select">
|
||||||
|
<option th:each="a : ${ages}" th:value="${a.pkAge}" th:label="${a.name} + ', ' + ${a.price} + ' € / Übernachtung'"></option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-3">Welche Tage</div>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="day0" type="checkbox" name="active" th:field="*{day0}" class="form-check-input" />
|
||||||
|
<label class="form-check-label" for="day0">Donnerstag</label>
|
||||||
|
<input id="day1" type="checkbox" name="active" th:field="*{day1}" class="form-check-input" />
|
||||||
|
<label class="form-check-label" for="day1">Freitag</label>
|
||||||
|
<input id="day2" type="checkbox" name="active" th:field="*{day2}" class="form-check-input" />
|
||||||
|
<label class="form-check-label" for="day2">Sonnabend</label>
|
||||||
|
<input id="day3" type="checkbox" name="active" th:field="*{day3}" class="form-check-input" />
|
||||||
|
<label class="form-check-label" for="day3">Sonntag</label>
|
||||||
|
<input id="day4" type="checkbox" name="active" th:field="*{day4}" class="form-check-input" />
|
||||||
|
<label class="form-check-label" for="day4">Montag</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-3">Sonderleistungen</div>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="towels" type="checkbox" name="active" th:field="*{towels}" class="form-check-input" />
|
||||||
|
<label class="form-check-label" for="towels">Handtücher: 2 € / Person</label><br />
|
||||||
|
<input id="bed_linen" type="checkbox" name="active" th:field="*{bedLinen}" class="form-check-input" />
|
||||||
|
<label class="form-check-label" for="bed_linen">Bettwäsche: 7 € / Person</label><br />
|
||||||
|
<input id="cot" type="checkbox" name="active" th:field="*{cot}" class="form-check-input" />
|
||||||
|
<label class="form-check-label" for="cot">Kinderbett: 10 € einmalig</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-3">Barrierefrei</div>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<span th:if="${#fields.hasErrors('barrierFree')}" th:errors="*{barrierFree}" class="text-danger"></span>
|
||||||
|
<select th:field="*{barrierFree}" class="form-select">
|
||||||
|
<option value="false">Nein</option>
|
||||||
|
<option value="true">Ja</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-3">Spezielle Ernährung (Allergien, Unverträglichkeiten)</div>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<textarea th:field="*{nutrition}" class="form-control"></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-3">Biete Plätze zum Mitfahren</div>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input th:field="*{driverProvidePlaces}" type="number" min="0" max="8" class="form-control" />
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-3">Benötige eine Mitfahrgelegenheit</div>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="wantPlaceInCar" type="checkbox" name="active" th:field="*{wantPlaceInCar}" class="form-check-input" />
|
||||||
|
<label class="form-check-label" for="wantPlaceInCar">Ja, brauche ich</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-3">Besonderheiten / Krankheiten</div>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<textarea th:field="*{diseases}" class="form-control"></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-3">Finanzierungsunterstützung</div>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="requirePayment" type="checkbox" name="active" th:field="*{requirePayment}" class="form-check-input" />
|
||||||
|
<label class="form-check-label" for="requirePayment">Ja, brauche ich</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-sm-3"></div>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<button type="submit" class="btn btn-outline-success">Korrigeren</button>
|
||||||
|
<a th:href="@{/camp/registration}" class="btn btn-outline-secondary">Abbrechen</a>
|
||||||
|
<button type="button" class="btn btn-outline-danger" data-bs-toggle="modal" data-bs-target="#deleteModal">Stornieren</button>
|
||||||
|
|
||||||
|
<div class="modal fade" id="deleteModal" tabindex="-1" aria-labelledby="deleteModalLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h1 class="modal-title fs-5" id="deleteModalLabel">Löschen einer Anmeldung</h1>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
Soll die Anmeldung von <span th:text="${bean.forename}"></span> <span th:text="${bean.surname}"></span> wirklich gelöscht werden?
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">Abbrechen</button>
|
||||||
|
<a th:href="@{/camp/registration/delete/{id}(id=${bean.pkRegistration})}" class="btn btn-outline-danger">Endgültig löschen</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</th:block>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
81
src/main/resources/templates/camp/list.html
Normal file
81
src/main/resources/templates/camp/list.html
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html xmlns:th="http://www.thymeleaf.org" layout:decorate="~{template}" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
|
||||||
|
<body>
|
||||||
|
<th:block layout:fragment="content">
|
||||||
|
<div class="borderdist">
|
||||||
|
<div class="container full-size">
|
||||||
|
<div class="row g-2">
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<h2>Anmeldungen zur Gemeindefreizeit 2025</h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="alert alert-danger" th:unless="${list}">Sie haben keine Berechtigung, die Anmeldungen einzusehen.</div>
|
||||||
|
<div th:if="${list}">
|
||||||
|
<table id="table" class="table table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Vorname</th>
|
||||||
|
<th>Nachname</th>
|
||||||
|
<th>Geschlecht</th>
|
||||||
|
<th>Alter</th>
|
||||||
|
<th>Tage dabei</th>
|
||||||
|
<th>Extras</th>
|
||||||
|
<th>Unverträglichkeit</th>
|
||||||
|
<th>Mitfahrplätze</th>
|
||||||
|
<th>Besonderheiten</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr th:each="l : ${list}">
|
||||||
|
<td th:text="${l.forename}"></td>
|
||||||
|
<td th:text="${l.surname}"></td>
|
||||||
|
<td th:text="${l.sex}"></td>
|
||||||
|
<td>
|
||||||
|
<th:block th:each="a : ${ages}">
|
||||||
|
<span th:text="${a.name}" th:if="${a.pkAge == l.fkAge}"></span>
|
||||||
|
</th:block>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span th:if="${l.day0}" class="badge campbadge">Donnerstag</span>
|
||||||
|
<span th:if="${l.day1}" class="badge campbadge">Freitag</span>
|
||||||
|
<span th:if="${l.day2}" class="badge campbadge">Sonnabend</span>
|
||||||
|
<span th:if="${l.day3}" class="badge campbadge">Sonntag</span>
|
||||||
|
<span th:if="${l.day4}" class="badge campbadge">Montag</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span th:if="${l.barrierFree}" class="badge campbadge">barrierefrei</span>
|
||||||
|
<span th:if="${l.towels}" class="badge campbadge">Handtücher</span>
|
||||||
|
<span th:if="${l.bedLinen}" class="badge campbadge">Bettwäsche</span>
|
||||||
|
<span th:if="${l.cot}" class="badge campbadge">Kinderbett</span>
|
||||||
|
<span th:if="${l.requirePayment}" class="badge campbadge">finanzielle Unterstützung erbeten</span>
|
||||||
|
</td>
|
||||||
|
<td th:text="${l.nutrition}"></td>
|
||||||
|
<td>
|
||||||
|
<span th:if="${l.driverProvidePlaces}">biete <span th:text="${l.driverProvidePlaces}"></span></span>
|
||||||
|
<span th:if="${l.wantPlaceInCar}">benötige 1</span>
|
||||||
|
</td>
|
||||||
|
<td th:text="${l.diseases}"></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<script th:inline="javascript">
|
||||||
|
/*<![CDATA[*/
|
||||||
|
$(document).ready(function() {
|
||||||
|
$("#table").DataTable({
|
||||||
|
"language" : locale_de,
|
||||||
|
"responsive" : true
|
||||||
|
});
|
||||||
|
});
|
||||||
|
/*]]>*/
|
||||||
|
</script>
|
||||||
|
</div>
|
||||||
|
<div class="row g-2" th:if="${list}">
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<a th:href="@{/camp/registration/admin/download}" class="btn btn-outline-primary">Download</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</th:block>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
170
src/main/resources/templates/camp/registration.html
Normal file
170
src/main/resources/templates/camp/registration.html
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html xmlns:th="http://www.thymeleaf.org" layout:decorate="~{template}" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
|
||||||
|
<body>
|
||||||
|
<th:block layout:fragment="content">
|
||||||
|
<div class="borderdist">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row g-2">
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<h2>Anmeldung zur Gemeindefreizeit 2025</h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script th:inline="javascript">
|
||||||
|
function toggleTo(opener, name) {
|
||||||
|
$('.nav-opener').removeClass('active');
|
||||||
|
$('.tabpanel').hide();
|
||||||
|
$(opener).addClass('active');
|
||||||
|
$(name).show();
|
||||||
|
}
|
||||||
|
|
||||||
|
$(document).ready(function() {
|
||||||
|
var regsize = parseInt(/*[[${registrations.size()}]]*/"0");
|
||||||
|
$("#details").hide();
|
||||||
|
if (regsize < 1) {
|
||||||
|
$("#open_new").addClass("active");
|
||||||
|
$("#new").show();
|
||||||
|
$("#open_found").removeClass("active");
|
||||||
|
$("#found").hide();
|
||||||
|
} else {
|
||||||
|
$("#open_new").removeClass("active");
|
||||||
|
$("#new").hide();
|
||||||
|
$("#open_found").addClass("active");
|
||||||
|
$("#found").show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<ul class="nav nav-tabs">
|
||||||
|
<li class="nav-item"><a id="open_new" class="nav-link active nav-opener" aria-current="page" href="#" onclick="toggleTo(this, '#new')">Neue Anmeldung</a></li>
|
||||||
|
<li class="nav-item"><a id="open_found" class="nav-link nav-opener" href="#" onclick="toggleTo(this, '#found')">Bisherige Anmeldungen</a></li>
|
||||||
|
<li class="nav-item"><a id="open_details" class="nav-link nav-opener" href="#" onclick="toggleTo(this, '#details')">Überweisung</a></li>
|
||||||
|
</ul>
|
||||||
|
<div class="tab-content">
|
||||||
|
<div id="new" class="tabpanel">
|
||||||
|
<div class="alert alert-info">Die Zeit für die Anmeldung zur Gemeindefreizeit 2025 ist vorbei.</div>
|
||||||
|
<form th:action="@{/camp/registration/submit}" method="post" th:object="${bean}" th:if="${oldie}">
|
||||||
|
<div class="row g-3">
|
||||||
|
|
||||||
|
<div class="col-sm-3">Vorname</div>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<span th:if="${#fields.hasErrors('forename')}" th:errors="*{forename}" class="text-danger"></span> <input type="text" th:field="*{forename}" class="form-control" />
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-3">Nachname</div>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<span th:if="${#fields.hasErrors('surname')}" th:errors="*{surname}" class="text-danger"></span> <input type="text" th:field="*{surname}" class="form-control" />
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-3">Geschlecht</div>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<span th:if="${#fields.hasErrors('sex')}" th:errors="*{sex}" class="text-danger"></span> <select th:field="*{sex}" class="form-select">
|
||||||
|
<option value="">--- bitte wählen ---</option>
|
||||||
|
<option th:each="s : ${sexes}" th:value="${s}" th:text="${s}"></option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-3">Alter</div>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<span th:if="${#fields.hasErrors('fkAge')}" th:errors="*{fkAge}" class="text-danger"></span>
|
||||||
|
<select th:field="*{fkAge}" class="form-select">
|
||||||
|
<option th:each="a : ${ages}" th:value="${a.pkAge}" th:label="${a.name} + ', ' + ${a.price} + ' € / Übernachtung'"></option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-3">Welche Tage</div>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="day0" type="checkbox" name="active" th:field="*{day0}" class="form-check-input" />
|
||||||
|
<label class="form-check-label" for="day0">Donnerstag</label>
|
||||||
|
<input id="day1" type="checkbox" name="active" th:field="*{day1}" class="form-check-input" />
|
||||||
|
<label class="form-check-label" for="day1">Freitag</label>
|
||||||
|
<input id="day2" type="checkbox" name="active" th:field="*{day2}" class="form-check-input" />
|
||||||
|
<label class="form-check-label" for="day2">Sonnabend</label>
|
||||||
|
<input id="day3" type="checkbox" name="active" th:field="*{day3}" class="form-check-input" />
|
||||||
|
<label class="form-check-label" for="day3">Sonntag</label>
|
||||||
|
<input id="day4" type="checkbox" name="active" th:field="*{day4}" class="form-check-input" />
|
||||||
|
<label class="form-check-label" for="day4">Montag</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-3">Sonderleistungen</div>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="towels" type="checkbox" name="active" th:field="*{towels}" class="form-check-input" />
|
||||||
|
<label class="form-check-label" for="towels">Handtücher: 2 € / Person</label><br />
|
||||||
|
<input id="bed_linen" type="checkbox" name="active" th:field="*{bedLinen}" class="form-check-input" />
|
||||||
|
<label class="form-check-label" for="bed_linen">Bettwäsche: 7 € / Person</label><br />
|
||||||
|
<input id="cot" type="checkbox" name="active" th:field="*{cot}" class="form-check-input" />
|
||||||
|
<label class="form-check-label" for="cot">Kinderbett: 10 € einmalig</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-3">Barrierefrei</div>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<span th:if="${#fields.hasErrors('barrierFree')}" th:errors="*{barrierFree}" class="text-danger"></span>
|
||||||
|
<select th:field="*{barrierFree}" class="form-select">
|
||||||
|
<option value="false">Nein</option>
|
||||||
|
<option value="true">Ja</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-3">Spezielle Ernährung (Allergien, Unverträglichkeiten)</div>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<textarea th:field="*{nutrition}" class="form-control"></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-3">Biete Plätze zum Mitfahren</div>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input th:field="*{driverProvidePlaces}" type="number" min="0" max="8" class="form-control" />
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-3">Benötige eine Mitfahrgelegenheit</div>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="wantPlaceInCar" type="checkbox" name="active" th:field="*{wantPlaceInCar}" class="form-check-input" />
|
||||||
|
<label class="form-check-label" for="wantPlaceInCar">Ja, brauche ich</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-3">Besonderheiten / Krankheiten</div>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<textarea th:field="*{diseases}" class="form-control"></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-3">Finanzierungsunterstützung</div>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="requirePayment" type="checkbox" name="active" th:field="*{requirePayment}" class="form-check-input" />
|
||||||
|
<label class="form-check-label" for="requirePayment">Ja, brauche ich</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-sm-3"></div>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<button type="submit" class="btn btn-outline-success">Speichern</button>
|
||||||
|
<a th:href="@{/camp/registration}" class="btn btn-outline-secondary">Abbrechen</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div id="found" class="tabpanel">
|
||||||
|
<table class="table table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Vorname</th>
|
||||||
|
<th>Nachname</th>
|
||||||
|
<th> </th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr th:each="r : ${registrations}">
|
||||||
|
<td th:text="${r.forename}"></td>
|
||||||
|
<td th:text="${r.surname}"></td>
|
||||||
|
<td><a th:href="@{/camp/registration/edit/{id}(id=${r.pkRegistration})}" class="btn btn-outline-secondary"><i class="bi bi-pencil"></i></a></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div id="details" class="tabpanel">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">Informationen zu den Kosten</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<i>Bitte überweise den Betrag, der sich aus Deiner Anmeldung ergibt, auf das Gemeindekonto:</i><br />
|
||||||
|
Kontoverbindung<br />
|
||||||
|
EFG Dresden Süd-Ost<br />
|
||||||
|
IBAN: DE40 8601 0090 0102 0449 00<br />
|
||||||
|
BIC: PBNKDEFF Konto 102 044 900<br />
|
||||||
|
Postbank Leipzig BLZ 860 100 90<br />
|
||||||
|
</div>
|
||||||
|
<div class="card-footer">
|
||||||
|
<img th:src="@{/images/Bildschirmfoto 2024-12-02 um 13.36.25.png}" style="max-width: 600px; width: 100%" /><br />
|
||||||
|
<img th:src="@{/images/PastedGraphic-2.png}" style="max-width: 600px; width: 100%" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</th:block>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
10
src/main/resources/templates/error.html
Normal file
10
src/main/resources/templates/error.html
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html xmlns:th="http://www.thymeleaf.org" layout:decorate="~{template}" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
|
||||||
|
<body>
|
||||||
|
<th:block layout:fragment="content">
|
||||||
|
<div class="borderdist">
|
||||||
|
<div class="alert alert-danger">Es ist ein Fehler aufgetreten. Wenden Sie sich bitte an Ihren Entwickler.</div>
|
||||||
|
</div>
|
||||||
|
</th:block>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
<body>
|
<body>
|
||||||
<th:block layout:fragment="content">
|
<th:block layout:fragment="content">
|
||||||
<div class="borderdist">
|
<div class="borderdist">
|
||||||
<div class="container">
|
<div class="container" sec:authorize="hasRole('Bibelunterricht')">
|
||||||
<div class="row g-2">
|
<div class="row g-2">
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
<h2>Dozent-Reservierung</h2>
|
<h2>Dozent-Reservierung</h2>
|
||||||
@@ -30,7 +30,8 @@
|
|||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<button type="submit" class="btn btn-outline-success">Speichern</button>
|
<button type="submit" class="btn btn-outline-success">Speichern</button>
|
||||||
<a th:href="@{/}" class="btn btn-outline-secondary">Abbrechen</a>
|
<a th:href="@{/}" class="btn btn-outline-secondary">Abbrechen</a>
|
||||||
<a th:href="@{/lesson/{id}/remove(id=${bean.pkLesson})}" class="btn btn-outline-danger">Löschen</a>
|
<a th:href="@{/lesson/{id}/remove(id=${bean.pkLesson})}" class="btn btn-outline-danger">Zuordnung löschen</a>
|
||||||
|
<a th:href="@{/slot/{id}(id=${bean.fkSlot})}" class="btn btn-outline-warning">Termin bearbeiten</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
20
src/main/resources/templates/next.html
Normal file
20
src/main/resources/templates/next.html
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html xmlns:th="http://www.thymeleaf.org" layout:decorate="~{template}" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
|
||||||
|
<body>
|
||||||
|
<th:block layout:fragment="content">
|
||||||
|
<div class="borderdist">
|
||||||
|
<div class="container" th:if="${hasDateRole || hasBUrole}">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-6 col-md-4 col-lg-2 card p-2 m-1" th:each="s : ${list}">
|
||||||
|
<div class="tag tagbu" th:if="${s.isBibleclass}">Bibelunt.</div>
|
||||||
|
<div class="tag tagju" th:if="${s.isYouthgroup}">Jungsch.</div>
|
||||||
|
<div class="tagfollow" th:text="${#temporals.format(s.day, 'dd.MM.yyyy')}"></div>
|
||||||
|
<div th:class="'tagfollow' + ${currentUserName == #strings.toLowerCase(s.fullname) ? ' tagemphasize' : ''}" th:text="${s.fullname}"></div>
|
||||||
|
</div>
|
||||||
|
<div class="alert alert-info" th:if="${list.size() < 1}">Es gibt noch keine neuen Termine oder Zusagen für Termine.</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</th:block>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
<body>
|
<body>
|
||||||
<th:block layout:fragment="content">
|
<th:block layout:fragment="content">
|
||||||
<div class="borderdist">
|
<div class="borderdist">
|
||||||
<table id="table" class="table table-striped">
|
<table id="table" class="table table-striped" sec:authorize="hasRole('Bibelunterricht')">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Tag</th>
|
<th>Tag</th>
|
||||||
@@ -14,7 +14,11 @@
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr th:each="s : ${list}">
|
<tr th:each="s : ${list}">
|
||||||
<td><span th:text="${#temporals.format(s.slotDay, 'yyyy-MM-dd')}"></span></td>
|
<td th:data-sort="${#temporals.format(s.slotDay, 'yyyy-MM-dd')}">
|
||||||
|
<a th:href="@{/slot/{id}(id=${s.pkSlot})}" th:text="${#temporals.format(s.slotDay, 'dd.MM.yyyy')}"></a><br />
|
||||||
|
<span class="smallbadge tagbu" th:if="${s.bibleclass}">Bibelunterricht</span>
|
||||||
|
<span class="smallbadge tagju" th:if="${s.youthgroup}">Jungschar</span>
|
||||||
|
</td>
|
||||||
<td><a th:href="@{/lesson?slotId={id}(id=${s.pkSlot})}" class="btn btn-outline-secondary"> <span th:text="${s.abbreviation}" th:if="${s.abbreviation}"></span> <i
|
<td><a th:href="@{/lesson?slotId={id}(id=${s.pkSlot})}" class="btn btn-outline-secondary"> <span th:text="${s.abbreviation}" th:if="${s.abbreviation}"></span> <i
|
||||||
class="bi bi-pencil" th:if="${s.abbreviation == null || s.abbreviation.isBlank()}"></i>
|
class="bi bi-pencil" th:if="${s.abbreviation == null || s.abbreviation.isBlank()}"></i>
|
||||||
</a></td>
|
</a></td>
|
||||||
@@ -32,8 +36,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td><a th:href="@{/slot/{id}(id=${s.pkSlot})}" class="btn btn-outline-secondary rightaligned"><i class="bi bi-pencil"></i></a>
|
<td><span th:text="${s.slotNotes}" class="rightpadding64"></span></td>
|
||||||
<span th:text="${s.slotNotes}" class="rightpadding64"></span></td>
|
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
<tfoot>
|
<tfoot>
|
||||||
@@ -48,10 +51,6 @@
|
|||||||
/*<![CDATA[*/
|
/*<![CDATA[*/
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
$("#table").DataTable({
|
$("#table").DataTable({
|
||||||
"columnDefs" : [ {
|
|
||||||
"targets" : 0,
|
|
||||||
"type" : "date-eu"
|
|
||||||
} ],
|
|
||||||
"order" : [ [ 0, 'desc' ] ],
|
"order" : [ [ 0, 'desc' ] ],
|
||||||
"language" : locale_de
|
"language" : locale_de
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<html xmlns:th="http://www.thymeleaf.org" layout:decorate="~{template}" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
|
<html xmlns:th="http://www.thymeleaf.org" layout:decorate="~{template}" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
|
||||||
<body>
|
<body>
|
||||||
<th:block layout:fragment="content">
|
<th:block layout:fragment="content">
|
||||||
<div class="borderdist">
|
<div class="borderdist" sec:authorize="hasRole('Bibelunterricht')">
|
||||||
<div class="alert alert-danger" th:if="${bean}">
|
<div class="alert alert-danger" th:if="${bean}">
|
||||||
Wollen Sie den Slot <span th:text="${#temporals.format(bean.slotDay, 'dd.MM.yyyy')}"></span> wirklich löschen?<br />
|
Wollen Sie den Slot <span th:text="${#temporals.format(bean.slotDay, 'dd.MM.yyyy')}"></span> wirklich löschen?<br />
|
||||||
<a th:href="@{/slot/{id}/destroy(id=${bean.pkSlot})}" class="btn btn-outline-danger" th:if="${bean.pkSlot}">Ja, definitiv</a>
|
<a th:href="@{/slot/{id}/destroy(id=${bean.pkSlot})}" class="btn btn-outline-danger" th:if="${bean.pkSlot}">Ja, definitiv</a>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<body>
|
<body>
|
||||||
<th:block layout:fragment="content">
|
<th:block layout:fragment="content">
|
||||||
<div class="borderdist">
|
<div class="borderdist">
|
||||||
<div class="container">
|
<div class="container" sec:authorize="hasRole('Bibelunterricht')">
|
||||||
<div class="row g-2">
|
<div class="row g-2">
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
<h2>Terminfestlegung</h2>
|
<h2>Terminfestlegung</h2>
|
||||||
@@ -17,6 +17,12 @@
|
|||||||
<input type="date" th:field="*{slotDay}" th:class="${#fields.hasErrors('slotDay') ? 'form-control bg-danger' : 'form-control'}" />
|
<input type="date" th:field="*{slotDay}" th:class="${#fields.hasErrors('slotDay') ? 'form-control bg-danger' : 'form-control'}" />
|
||||||
<div th:each="err : ${#fields.errors('slotDay')}" th:text="${err}" class="alert alert-danger"></div>
|
<div th:each="err : ${#fields.errors('slotDay')}" th:text="${err}" class="alert alert-danger"></div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-sm-2">Gruppenname</div>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<select class="form-control" th:field="*{groupname}">
|
||||||
|
<option th:each="g : ${groupnames}" th:value="${g}" th:text="${groupnamemap.get(g.literal)}"></option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
<div class="col-sm-2">Notiz</div>
|
<div class="col-sm-2">Notiz</div>
|
||||||
<div class="col-sm-10">
|
<div class="col-sm-10">
|
||||||
<textarea class="form-control" th:field="*{note}"></textarea>
|
<textarea class="form-control" th:field="*{note}"></textarea>
|
||||||
|
|||||||
@@ -4,14 +4,17 @@
|
|||||||
<title>Bible Class Organizer</title>
|
<title>Bible Class Organizer</title>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<link th:rel="stylesheet" type="text/css" media="all" th:href="@{/webjars/bootstrap/5.3.1/css/bootstrap.min.css}" />
|
<link rel="stylesheet" type="text/css" media="all" th:href="@{/webjars/bootstrap/5.3.8/css/bootstrap.min.css}" />
|
||||||
<link th:rel="stylesheet" type="text/css" media="all" th:href="@{/webjars/bootstrap-icons/1.10.5/font/bootstrap-icons.css}" />
|
<link rel="stylesheet" type="text/css" media="all" th:href="@{/webjars/bootstrap-icons/1.13.1/font/bootstrap-icons.css}" />
|
||||||
<link th:rel="stylesheet" type="text/css" media="all" th:href="@{/webjars/datatables/1.13.5/css/jquery.dataTables.min.css}" />
|
<link rel="stylesheet" type="text/css" media="all" th:href="@{/webjars/datatables.net-bs5/2.3.5/css/dataTables.bootstrap5.min.css}"/>
|
||||||
<link th:rel="stylesheet" type="text/css" media="all" th:href="@{/css/style.css}" />
|
<link rel="stylesheet" type="text/css" media="all" th:href="@{/css/style.css}" />
|
||||||
<script th:src="@{/webjars/bootstrap/5.3.1/js/bootstrap.bundle.min.js}"></script>
|
<script type="application/javascript" th:src="@{/webjars/bootstrap/5.3.8/js/bootstrap.bundle.min.js}"></script>
|
||||||
<script th:src="@{/webjars/jquery/3.7.1/jquery.min.js}"></script>
|
<script type="application/javascript" th:src="@{/webjars/jquery/3.7.1/jquery.min.js}"></script>
|
||||||
<script th:src="@{/webjars/datatables/1.13.5/js/jquery.dataTables.min.js}"></script>
|
<script type="application/javascript" th:src="@{/webjars/datatables.net/2.3.5/js/dataTables.min.js}"></script>
|
||||||
<script th:src="@{/js/dataTables.de.js}"></script>
|
<script type="application/javascript" th:src="@{/js/dataTables.de.js}"></script>
|
||||||
|
<script type="application/javascript" th:src="@{/webjars/datatables.net-bs5/2.3.5/js/dataTables.bootstrap5.min.js}"></script>
|
||||||
|
<script type="application/javascript" th:src="@{/webjars/datatables.net-responsive/3.0.6/js/dataTables.responsive.min.js}"></script>
|
||||||
|
<script type="application/javascript" th:src="@{/webjars/datatables.net-buttons/3.2.5/js/dataTables.buttons.min.js}"></script>
|
||||||
<script th:src="@{/js/stylehelp.js}"></script>
|
<script th:src="@{/js/stylehelp.js}"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@@ -21,21 +24,39 @@
|
|||||||
<span class="navbar-toggler-icon"></span>
|
<span class="navbar-toggler-icon"></span>
|
||||||
</button>
|
</button>
|
||||||
<div class="collapse navbar-collapse" id="navbarSupportedContent" style="margin-right: 20px">
|
<div class="collapse navbar-collapse" id="navbarSupportedContent" style="margin-right: 20px">
|
||||||
<ul class="navbar-nav mb-2 mb-lg-0">
|
<ul class="navbar-nav mb-2 mb-lg-0" th:if="${hasAnyRole}">
|
||||||
<li class="nav-item"><a class="btn btn-outline-secondary" th:href="@{/}" style="margin-left: 12px">Einteilung</a></li>
|
<!--
|
||||||
<li class="nav-item"><a class="btn btn-outline-secondary" th:href="@{/subject/list}" style="margin-left: 12px">Themen</a></li>
|
<li class="nav-item"><a class="btn btn-outline-secondary" th:href="@{/camp/registration}" style="margin-left: 12px">Anmeldung Gemeindefreizeit</a></li>
|
||||||
|
<li class="nav-item"><a class="btn btn-outline-secondary" th:href="@{/camp/registration/admin}" style="margin-left: 12px" th:if="${isCampAdmin}">Gemeindefreizeitliste</a></li>
|
||||||
|
-->
|
||||||
|
<li class="nav-item"><a class="btn btn-outline-secondary" th:href="@{/next}" style="margin-left: 12px" th:if="${hasDateRole || hasBUrole}">Dienstplan</a></li>
|
||||||
|
<li class="nav-item"><a class="btn btn-outline-secondary" th:href="@{/sheet}" style="margin-left: 12px" th:if="${hasBUrole}">Einteilung</a></li>
|
||||||
|
<li class="nav-item"><a class="btn btn-outline-secondary" th:href="@{/subject/list}" style="margin-left: 12px" th:if="${hasBUrole}">Themen</a></li>
|
||||||
|
<li class="nav-item"><a class="btn btn-outline-secondary" th:href="@{/download}" style="margin-left: 12px" th:if="${hasBUrole}">Download</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
<ul layout:fragment="header"></ul>
|
<ul layout:fragment="header"></ul>
|
||||||
<ul class="nav navbar-nav ms-auto">
|
<ul class="nav navbar-nav ms-auto">
|
||||||
|
<li class="nav-item" th:if="${hasDateRole}">
|
||||||
|
<a th:href="@{/ical}" class="btn btn-outline-secondary"><i class="bi bi-calendar-week"></i></a>
|
||||||
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a href="https://gitlab.com/jottyfan/bico/-/issues" class="btn btn-outline-secondary" target="_blank" th:text="${'v' + @manifestBean.getVersion()}"></a>
|
<a href="https://git.jottyfan.de/church/BiCO" class="btn btn-outline-secondary" target="_blank" th:text="${'v' + @manifestBean.getVersion()}"></a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a href="#" class="btn btn-outline-secondary" onclick="toggleDarkMode()"><i class="bi bi-moon"></i></a>
|
<a href="#" class="btn btn-outline-secondary" onclick="toggleDarkMode()"><i class="bi bi-moon"></i></a>
|
||||||
</li>
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a th:href="@{/logout}" class="btn btn-outline-secondary">⏼ Abmelden</a>
|
||||||
|
<a th:href="@{${nextcloudUrl}}" class="btn btn-outline-secondary">→ nextcloud</a>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
<div layout:fragment="content">content</div>
|
<div layout:fragment="content" th:if="${hasAnyRole}">content</div>
|
||||||
|
<div th:unless="${hasAnyRole}">
|
||||||
|
<div class="borderdist">
|
||||||
|
<div class="alert alert-danger">Leider fehlen Ihnen die Berechtigungen, um diese Anwendung nutzen zu können.</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
<body>
|
<body>
|
||||||
<th:block layout:fragment="content">
|
<th:block layout:fragment="content">
|
||||||
<div class="borderdist">
|
<div class="borderdist">
|
||||||
<div class="container">
|
<div class="container" sec:authorize="hasRole('Bibelunterricht')">
|
||||||
<div class="row g-2">
|
<div class="row g-2">
|
||||||
<h1>
|
<h1>
|
||||||
Themen für den <span th:text="${#temporals.format(day, 'dd.MM.yyyy')}"></span>
|
Themen für den <span th:text="${#temporals.format(day, 'dd.MM.yyyy')}"></span>
|
||||||
|
|||||||
Reference in New Issue
Block a user