parent
fc085f8ba3
commit
903453bf41
@ -0,0 +1,32 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<classpath> |
||||
<classpathentry kind="src" output="target/classes" path="src/main/java"> |
||||
<attributes> |
||||
<attribute name="optional" value="true"/> |
||||
<attribute name="maven.pomderived" value="true"/> |
||||
</attributes> |
||||
</classpathentry> |
||||
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"> |
||||
<attributes> |
||||
<attribute name="maven.pomderived" value="true"/> |
||||
</attributes> |
||||
</classpathentry> |
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java"> |
||||
<attributes> |
||||
<attribute name="optional" value="true"/> |
||||
<attribute name="maven.pomderived" value="true"/> |
||||
<attribute name="test" value="true"/> |
||||
</attributes> |
||||
</classpathentry> |
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11"> |
||||
<attributes> |
||||
<attribute name="maven.pomderived" value="true"/> |
||||
</attributes> |
||||
</classpathentry> |
||||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER"> |
||||
<attributes> |
||||
<attribute name="maven.pomderived" value="true"/> |
||||
</attributes> |
||||
</classpathentry> |
||||
<classpathentry kind="output" path="target/classes"/> |
||||
</classpath> |
||||
@ -0,0 +1,6 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<project version="4"> |
||||
<component name="PackageJsonUpdateNotifier"> |
||||
<dismissed value="$PROJECT_DIR$/package.json" /> |
||||
</component> |
||||
</project> |
||||
@ -0,0 +1,118 @@ |
||||
/* |
||||
* Copyright 2007-present the original author or 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 |
||||
* |
||||
* http://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. |
||||
*/ |
||||
import java.io.*; |
||||
import java.net.*; |
||||
import java.nio.channels.*; |
||||
import java.util.Properties; |
||||
|
||||
public class MavenWrapperDownloader { |
||||
|
||||
private static final String WRAPPER_VERSION = "0.5.6"; |
||||
/** |
||||
* Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is |
||||
* provided. |
||||
*/ |
||||
private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" |
||||
+ WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; |
||||
|
||||
/** |
||||
* Path to the maven-wrapper.properties file, which might contain a downloadUrl |
||||
* property to use instead of the default one. |
||||
*/ |
||||
private static final String MAVEN_WRAPPER_PROPERTIES_PATH = ".mvn/wrapper/maven-wrapper.properties"; |
||||
|
||||
/** |
||||
* Path where the maven-wrapper.jar will be saved to. |
||||
*/ |
||||
private static final String MAVEN_WRAPPER_JAR_PATH = ".mvn/wrapper/maven-wrapper.jar"; |
||||
|
||||
/** |
||||
* Name of the property which should be used to override the default download |
||||
* url for the wrapper. |
||||
*/ |
||||
private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; |
||||
|
||||
public static void main(String args[]) { |
||||
System.out.println("- Downloader started"); |
||||
File baseDirectory = new File(args[0]); |
||||
System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); |
||||
|
||||
// If the maven-wrapper.properties exists, read it and check if it contains a
|
||||
// custom
|
||||
// wrapperUrl parameter.
|
||||
File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); |
||||
String url = DEFAULT_DOWNLOAD_URL; |
||||
if (mavenWrapperPropertyFile.exists()) { |
||||
FileInputStream mavenWrapperPropertyFileInputStream = null; |
||||
try { |
||||
mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); |
||||
Properties mavenWrapperProperties = new Properties(); |
||||
mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); |
||||
url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); |
||||
} catch (IOException e) { |
||||
System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); |
||||
} finally { |
||||
try { |
||||
if (mavenWrapperPropertyFileInputStream != null) { |
||||
mavenWrapperPropertyFileInputStream.close(); |
||||
} |
||||
} catch (IOException e) { |
||||
// Ignore ...
|
||||
} |
||||
} |
||||
} |
||||
System.out.println("- Downloading from: " + url); |
||||
|
||||
File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); |
||||
if (!outputFile.getParentFile().exists()) { |
||||
if (!outputFile.getParentFile().mkdirs()) { |
||||
System.out.println( |
||||
"- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); |
||||
} |
||||
} |
||||
System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); |
||||
try { |
||||
downloadFileFromURL(url, outputFile); |
||||
System.out.println("Done"); |
||||
System.exit(0); |
||||
} catch (Throwable e) { |
||||
System.out.println("- Error downloading"); |
||||
e.printStackTrace(); |
||||
System.exit(1); |
||||
} |
||||
} |
||||
|
||||
private static void downloadFileFromURL(String urlString, File destination) throws Exception { |
||||
if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { |
||||
String username = System.getenv("MVNW_USERNAME"); |
||||
char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); |
||||
Authenticator.setDefault(new Authenticator() { |
||||
@Override |
||||
protected PasswordAuthentication getPasswordAuthentication() { |
||||
return new PasswordAuthentication(username, password); |
||||
} |
||||
}); |
||||
} |
||||
URL website = new URL(urlString); |
||||
ReadableByteChannel rbc; |
||||
rbc = Channels.newChannel(website.openStream()); |
||||
FileOutputStream fos = new FileOutputStream(destination); |
||||
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); |
||||
fos.close(); |
||||
rbc.close(); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,2 @@ |
||||
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.1/apache-maven-3.8.1-bin.zip |
||||
wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar |
||||
@ -0,0 +1,6 @@ |
||||
# |
||||
# NOTICE: this is an auto-generated file |
||||
# |
||||
# This file sets the default parameters for manual `pnpm install`. |
||||
# |
||||
shamefully-hoist=true |
||||
@ -0,0 +1,4 @@ |
||||
module.exports = { |
||||
singleQuote: true, |
||||
printWidth: 120, |
||||
}; |
||||
@ -0,0 +1,28 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<projectDescription> |
||||
<name>trainerinvoice</name> |
||||
<comment></comment> |
||||
<projects> |
||||
</projects> |
||||
<buildSpec> |
||||
<buildCommand> |
||||
<name>org.eclipse.jdt.core.javabuilder</name> |
||||
<arguments> |
||||
</arguments> |
||||
</buildCommand> |
||||
<buildCommand> |
||||
<name>org.eclipse.m2e.core.maven2Builder</name> |
||||
<arguments> |
||||
</arguments> |
||||
</buildCommand> |
||||
<buildCommand> |
||||
<name>org.springframework.ide.eclipse.boot.validation.springbootbuilder</name> |
||||
<arguments> |
||||
</arguments> |
||||
</buildCommand> |
||||
</buildSpec> |
||||
<natures> |
||||
<nature>org.eclipse.jdt.core.javanature</nature> |
||||
<nature>org.eclipse.m2e.core.maven2Nature</nature> |
||||
</natures> |
||||
</projectDescription> |
||||
@ -0,0 +1,4 @@ |
||||
eclipse.preferences.version=1 |
||||
encoding//src/main/java=UTF-8 |
||||
encoding//src/main/resources=UTF-8 |
||||
encoding/<project>=UTF-8 |
||||
@ -0,0 +1,9 @@ |
||||
eclipse.preferences.version=1 |
||||
org.eclipse.jdt.core.compiler.codegen.methodParameters=generate |
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=11 |
||||
org.eclipse.jdt.core.compiler.compliance=11 |
||||
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled |
||||
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning |
||||
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore |
||||
org.eclipse.jdt.core.compiler.release=disabled |
||||
org.eclipse.jdt.core.compiler.source=11 |
||||
@ -0,0 +1,4 @@ |
||||
activeProfiles= |
||||
eclipse.preferences.version=1 |
||||
resolveWorkspaceProjects=true |
||||
version=1 |
||||
@ -0,0 +1,2 @@ |
||||
boot.validation.initialized=true |
||||
eclipse.preferences.version=1 |
||||
@ -0,0 +1,8 @@ |
||||
{ |
||||
"recommendations": [ |
||||
"runem.lit-plugin", |
||||
"vscjava.vscode-java-pack", |
||||
"pivotal.vscode-spring-boot" |
||||
], |
||||
"unwantedRecommendations": [] |
||||
} |
||||
@ -0,0 +1,3 @@ |
||||
{ |
||||
"lit-plugin.strict": true |
||||
} |
||||
@ -0,0 +1,34 @@ |
||||
# Stage that builds the application, a prerequisite for the running stage |
||||
FROM maven:3-openjdk-17-slim as build |
||||
RUN curl -sL https://deb.nodesource.com/setup_14.x | bash - |
||||
RUN apt-get update -qq && apt-get install -qq --no-install-recommends nodejs |
||||
|
||||
# Stop running as root at this point |
||||
RUN useradd -m myuser |
||||
WORKDIR /usr/src/app/ |
||||
RUN chown myuser:myuser /usr/src/app/ |
||||
USER myuser |
||||
|
||||
# Copy pom.xml and prefetch dependencies so a repeated build can continue from the next step with existing dependencies |
||||
COPY --chown=myuser pom.xml ./ |
||||
RUN mvn dependency:go-offline -Pproduction |
||||
|
||||
# Copy all needed project files to a folder |
||||
COPY --chown=myuser:myuser src src |
||||
COPY --chown=myuser:myuser frontend frontend |
||||
COPY --chown=myuser:myuser package.json ./ |
||||
|
||||
# Using * after the files that are autogenerated so that so build won't fail if they are not yet created |
||||
COPY --chown=myuser:myuser package-lock.json* pnpm-lock.yaml* webpack.config.js* ./ |
||||
|
||||
|
||||
# Build the production package, assuming that we validated the version before so no need for running tests again |
||||
RUN mvn clean package -DskipTests -Pproduction |
||||
|
||||
# Running stage: the part that is used for running the application |
||||
FROM openjdk:17-jdk-slim |
||||
COPY --from=build /usr/src/app/target/*.jar /usr/app/app.jar |
||||
RUN useradd -m myuser |
||||
USER myuser |
||||
EXPOSE 8080 |
||||
CMD java -jar /usr/app/app.jar |
||||
@ -0,0 +1,310 @@ |
||||
#!/bin/sh |
||||
# ---------------------------------------------------------------------------- |
||||
# Licensed to the Apache Software Foundation (ASF) under one |
||||
# or more contributor license agreements. See the NOTICE file |
||||
# distributed with this work for additional information |
||||
# regarding copyright ownership. The ASF licenses this file |
||||
# to you 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 |
||||
# |
||||
# http://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. |
||||
# ---------------------------------------------------------------------------- |
||||
|
||||
# ---------------------------------------------------------------------------- |
||||
# Maven Start Up Batch script |
||||
# |
||||
# Required ENV vars: |
||||
# ------------------ |
||||
# JAVA_HOME - location of a JDK home dir |
||||
# |
||||
# Optional ENV vars |
||||
# ----------------- |
||||
# M2_HOME - location of maven2's installed home dir |
||||
# MAVEN_OPTS - parameters passed to the Java VM when running Maven |
||||
# e.g. to debug Maven itself, use |
||||
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 |
||||
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files |
||||
# ---------------------------------------------------------------------------- |
||||
|
||||
if [ -z "$MAVEN_SKIP_RC" ] ; then |
||||
|
||||
if [ -f /etc/mavenrc ] ; then |
||||
. /etc/mavenrc |
||||
fi |
||||
|
||||
if [ -f "$HOME/.mavenrc" ] ; then |
||||
. "$HOME/.mavenrc" |
||||
fi |
||||
|
||||
fi |
||||
|
||||
# OS specific support. $var _must_ be set to either true or false. |
||||
cygwin=false; |
||||
darwin=false; |
||||
mingw=false |
||||
case "`uname`" in |
||||
CYGWIN*) cygwin=true ;; |
||||
MINGW*) mingw=true;; |
||||
Darwin*) darwin=true |
||||
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home |
||||
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html |
||||
if [ -z "$JAVA_HOME" ]; then |
||||
if [ -x "/usr/libexec/java_home" ]; then |
||||
export JAVA_HOME="`/usr/libexec/java_home`" |
||||
else |
||||
export JAVA_HOME="/Library/Java/Home" |
||||
fi |
||||
fi |
||||
;; |
||||
esac |
||||
|
||||
if [ -z "$JAVA_HOME" ] ; then |
||||
if [ -r /etc/gentoo-release ] ; then |
||||
JAVA_HOME=`java-config --jre-home` |
||||
fi |
||||
fi |
||||
|
||||
if [ -z "$M2_HOME" ] ; then |
||||
## resolve links - $0 may be a link to maven's home |
||||
PRG="$0" |
||||
|
||||
# need this for relative symlinks |
||||
while [ -h "$PRG" ] ; do |
||||
ls=`ls -ld "$PRG"` |
||||
link=`expr "$ls" : '.*-> \(.*\)$'` |
||||
if expr "$link" : '/.*' > /dev/null; then |
||||
PRG="$link" |
||||
else |
||||
PRG="`dirname "$PRG"`/$link" |
||||
fi |
||||
done |
||||
|
||||
saveddir=`pwd` |
||||
|
||||
M2_HOME=`dirname "$PRG"`/.. |
||||
|
||||
# make it fully qualified |
||||
M2_HOME=`cd "$M2_HOME" && pwd` |
||||
|
||||
cd "$saveddir" |
||||
# echo Using m2 at $M2_HOME |
||||
fi |
||||
|
||||
# For Cygwin, ensure paths are in UNIX format before anything is touched |
||||
if $cygwin ; then |
||||
[ -n "$M2_HOME" ] && |
||||
M2_HOME=`cygpath --unix "$M2_HOME"` |
||||
[ -n "$JAVA_HOME" ] && |
||||
JAVA_HOME=`cygpath --unix "$JAVA_HOME"` |
||||
[ -n "$CLASSPATH" ] && |
||||
CLASSPATH=`cygpath --path --unix "$CLASSPATH"` |
||||
fi |
||||
|
||||
# For Mingw, ensure paths are in UNIX format before anything is touched |
||||
if $mingw ; then |
||||
[ -n "$M2_HOME" ] && |
||||
M2_HOME="`(cd "$M2_HOME"; pwd)`" |
||||
[ -n "$JAVA_HOME" ] && |
||||
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" |
||||
fi |
||||
|
||||
if [ -z "$JAVA_HOME" ]; then |
||||
javaExecutable="`which javac`" |
||||
if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then |
||||
# readlink(1) is not available as standard on Solaris 10. |
||||
readLink=`which readlink` |
||||
if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then |
||||
if $darwin ; then |
||||
javaHome="`dirname \"$javaExecutable\"`" |
||||
javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" |
||||
else |
||||
javaExecutable="`readlink -f \"$javaExecutable\"`" |
||||
fi |
||||
javaHome="`dirname \"$javaExecutable\"`" |
||||
javaHome=`expr "$javaHome" : '\(.*\)/bin'` |
||||
JAVA_HOME="$javaHome" |
||||
export JAVA_HOME |
||||
fi |
||||
fi |
||||
fi |
||||
|
||||
if [ -z "$JAVACMD" ] ; then |
||||
if [ -n "$JAVA_HOME" ] ; then |
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then |
||||
# IBM's JDK on AIX uses strange locations for the executables |
||||
JAVACMD="$JAVA_HOME/jre/sh/java" |
||||
else |
||||
JAVACMD="$JAVA_HOME/bin/java" |
||||
fi |
||||
else |
||||
JAVACMD="`which java`" |
||||
fi |
||||
fi |
||||
|
||||
if [ ! -x "$JAVACMD" ] ; then |
||||
echo "Error: JAVA_HOME is not defined correctly." >&2 |
||||
echo " We cannot execute $JAVACMD" >&2 |
||||
exit 1 |
||||
fi |
||||
|
||||
if [ -z "$JAVA_HOME" ] ; then |
||||
echo "Warning: JAVA_HOME environment variable is not set." |
||||
fi |
||||
|
||||
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher |
||||
|
||||
# traverses directory structure from process work directory to filesystem root |
||||
# first directory with .mvn subdirectory is considered project base directory |
||||
find_maven_basedir() { |
||||
|
||||
if [ -z "$1" ] |
||||
then |
||||
echo "Path not specified to find_maven_basedir" |
||||
return 1 |
||||
fi |
||||
|
||||
basedir="$1" |
||||
wdir="$1" |
||||
while [ "$wdir" != '/' ] ; do |
||||
if [ -d "$wdir"/.mvn ] ; then |
||||
basedir=$wdir |
||||
break |
||||
fi |
||||
# workaround for JBEAP-8937 (on Solaris 10/Sparc) |
||||
if [ -d "${wdir}" ]; then |
||||
wdir=`cd "$wdir/.."; pwd` |
||||
fi |
||||
# end of workaround |
||||
done |
||||
echo "${basedir}" |
||||
} |
||||
|
||||
# concatenates all lines of a file |
||||
concat_lines() { |
||||
if [ -f "$1" ]; then |
||||
echo "$(tr -s '\n' ' ' < "$1")" |
||||
fi |
||||
} |
||||
|
||||
BASE_DIR=`find_maven_basedir "$(pwd)"` |
||||
if [ -z "$BASE_DIR" ]; then |
||||
exit 1; |
||||
fi |
||||
|
||||
########################################################################################## |
||||
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central |
||||
# This allows using the maven wrapper in projects that prohibit checking in binary data. |
||||
########################################################################################## |
||||
if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then |
||||
if [ "$MVNW_VERBOSE" = true ]; then |
||||
echo "Found .mvn/wrapper/maven-wrapper.jar" |
||||
fi |
||||
else |
||||
if [ "$MVNW_VERBOSE" = true ]; then |
||||
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." |
||||
fi |
||||
if [ -n "$MVNW_REPOURL" ]; then |
||||
jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" |
||||
else |
||||
jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" |
||||
fi |
||||
while IFS="=" read key value; do |
||||
case "$key" in (wrapperUrl) jarUrl="$value"; break ;; |
||||
esac |
||||
done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" |
||||
if [ "$MVNW_VERBOSE" = true ]; then |
||||
echo "Downloading from: $jarUrl" |
||||
fi |
||||
wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" |
||||
if $cygwin; then |
||||
wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` |
||||
fi |
||||
|
||||
if command -v wget > /dev/null; then |
||||
if [ "$MVNW_VERBOSE" = true ]; then |
||||
echo "Found wget ... using wget" |
||||
fi |
||||
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then |
||||
wget "$jarUrl" -O "$wrapperJarPath" |
||||
else |
||||
wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" |
||||
fi |
||||
elif command -v curl > /dev/null; then |
||||
if [ "$MVNW_VERBOSE" = true ]; then |
||||
echo "Found curl ... using curl" |
||||
fi |
||||
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then |
||||
curl -o "$wrapperJarPath" "$jarUrl" -f |
||||
else |
||||
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f |
||||
fi |
||||
|
||||
else |
||||
if [ "$MVNW_VERBOSE" = true ]; then |
||||
echo "Falling back to using Java to download" |
||||
fi |
||||
javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" |
||||
# For Cygwin, switch paths to Windows format before running javac |
||||
if $cygwin; then |
||||
javaClass=`cygpath --path --windows "$javaClass"` |
||||
fi |
||||
if [ -e "$javaClass" ]; then |
||||
if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then |
||||
if [ "$MVNW_VERBOSE" = true ]; then |
||||
echo " - Compiling MavenWrapperDownloader.java ..." |
||||
fi |
||||
# Compiling the Java class |
||||
("$JAVA_HOME/bin/javac" "$javaClass") |
||||
fi |
||||
if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then |
||||
# Running the downloader |
||||
if [ "$MVNW_VERBOSE" = true ]; then |
||||
echo " - Running MavenWrapperDownloader.java ..." |
||||
fi |
||||
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") |
||||
fi |
||||
fi |
||||
fi |
||||
fi |
||||
########################################################################################## |
||||
# End of extension |
||||
########################################################################################## |
||||
|
||||
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} |
||||
if [ "$MVNW_VERBOSE" = true ]; then |
||||
echo $MAVEN_PROJECTBASEDIR |
||||
fi |
||||
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" |
||||
|
||||
# For Cygwin, switch paths to Windows format before running java |
||||
if $cygwin; then |
||||
[ -n "$M2_HOME" ] && |
||||
M2_HOME=`cygpath --path --windows "$M2_HOME"` |
||||
[ -n "$JAVA_HOME" ] && |
||||
JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` |
||||
[ -n "$CLASSPATH" ] && |
||||
CLASSPATH=`cygpath --path --windows "$CLASSPATH"` |
||||
[ -n "$MAVEN_PROJECTBASEDIR" ] && |
||||
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` |
||||
fi |
||||
|
||||
# Provide a "standardized" way to retrieve the CLI args that will |
||||
# work with both Windows and non-Windows executions. |
||||
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" |
||||
export MAVEN_CMD_LINE_ARGS |
||||
|
||||
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain |
||||
|
||||
exec "$JAVACMD" \ |
||||
$MAVEN_OPTS \ |
||||
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ |
||||
"-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ |
||||
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" |
||||
@ -0,0 +1,182 @@ |
||||
@REM ---------------------------------------------------------------------------- |
||||
@REM Licensed to the Apache Software Foundation (ASF) under one |
||||
@REM or more contributor license agreements. See the NOTICE file |
||||
@REM distributed with this work for additional information |
||||
@REM regarding copyright ownership. The ASF licenses this file |
||||
@REM to you under the Apache License, Version 2.0 (the |
||||
@REM "License"); you may not use this file except in compliance |
||||
@REM with the License. You may obtain a copy of the License at |
||||
@REM |
||||
@REM http://www.apache.org/licenses/LICENSE-2.0 |
||||
@REM |
||||
@REM Unless required by applicable law or agreed to in writing, |
||||
@REM software distributed under the License is distributed on an |
||||
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
||||
@REM KIND, either express or implied. See the License for the |
||||
@REM specific language governing permissions and limitations |
||||
@REM under the License. |
||||
@REM ---------------------------------------------------------------------------- |
||||
|
||||
@REM ---------------------------------------------------------------------------- |
||||
@REM Maven Start Up Batch script |
||||
@REM |
||||
@REM Required ENV vars: |
||||
@REM JAVA_HOME - location of a JDK home dir |
||||
@REM |
||||
@REM Optional ENV vars |
||||
@REM M2_HOME - location of maven2's installed home dir |
||||
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands |
||||
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending |
||||
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven |
||||
@REM e.g. to debug Maven itself, use |
||||
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 |
||||
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files |
||||
@REM ---------------------------------------------------------------------------- |
||||
|
||||
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' |
||||
@echo off |
||||
@REM set title of command window |
||||
title %0 |
||||
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' |
||||
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% |
||||
|
||||
@REM set %HOME% to equivalent of $HOME |
||||
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") |
||||
|
||||
@REM Execute a user defined script before this one |
||||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre |
||||
@REM check for pre script, once with legacy .bat ending and once with .cmd ending |
||||
if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" |
||||
if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" |
||||
:skipRcPre |
||||
|
||||
@setlocal |
||||
|
||||
set ERROR_CODE=0 |
||||
|
||||
@REM To isolate internal variables from possible post scripts, we use another setlocal |
||||
@setlocal |
||||
|
||||
@REM ==== START VALIDATION ==== |
||||
if not "%JAVA_HOME%" == "" goto OkJHome |
||||
|
||||
echo. |
||||
echo Error: JAVA_HOME not found in your environment. >&2 |
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2 |
||||
echo location of your Java installation. >&2 |
||||
echo. |
||||
goto error |
||||
|
||||
:OkJHome |
||||
if exist "%JAVA_HOME%\bin\java.exe" goto init |
||||
|
||||
echo. |
||||
echo Error: JAVA_HOME is set to an invalid directory. >&2 |
||||
echo JAVA_HOME = "%JAVA_HOME%" >&2 |
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2 |
||||
echo location of your Java installation. >&2 |
||||
echo. |
||||
goto error |
||||
|
||||
@REM ==== END VALIDATION ==== |
||||
|
||||
:init |
||||
|
||||
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". |
||||
@REM Fallback to current working directory if not found. |
||||
|
||||
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% |
||||
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir |
||||
|
||||
set EXEC_DIR=%CD% |
||||
set WDIR=%EXEC_DIR% |
||||
:findBaseDir |
||||
IF EXIST "%WDIR%"\.mvn goto baseDirFound |
||||
cd .. |
||||
IF "%WDIR%"=="%CD%" goto baseDirNotFound |
||||
set WDIR=%CD% |
||||
goto findBaseDir |
||||
|
||||
:baseDirFound |
||||
set MAVEN_PROJECTBASEDIR=%WDIR% |
||||
cd "%EXEC_DIR%" |
||||
goto endDetectBaseDir |
||||
|
||||
:baseDirNotFound |
||||
set MAVEN_PROJECTBASEDIR=%EXEC_DIR% |
||||
cd "%EXEC_DIR%" |
||||
|
||||
:endDetectBaseDir |
||||
|
||||
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig |
||||
|
||||
@setlocal EnableExtensions EnableDelayedExpansion |
||||
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a |
||||
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% |
||||
|
||||
:endReadAdditionalConfig |
||||
|
||||
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" |
||||
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" |
||||
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain |
||||
|
||||
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" |
||||
|
||||
FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( |
||||
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B |
||||
) |
||||
|
||||
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central |
||||
@REM This allows using the maven wrapper in projects that prohibit checking in binary data. |
||||
if exist %WRAPPER_JAR% ( |
||||
if "%MVNW_VERBOSE%" == "true" ( |
||||
echo Found %WRAPPER_JAR% |
||||
) |
||||
) else ( |
||||
if not "%MVNW_REPOURL%" == "" ( |
||||
SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" |
||||
) |
||||
if "%MVNW_VERBOSE%" == "true" ( |
||||
echo Couldn't find %WRAPPER_JAR%, downloading it ... |
||||
echo Downloading from: %DOWNLOAD_URL% |
||||
) |
||||
|
||||
powershell -Command "&{"^ |
||||
"$webclient = new-object System.Net.WebClient;"^ |
||||
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ |
||||
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ |
||||
"}"^ |
||||
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ |
||||
"}" |
||||
if "%MVNW_VERBOSE%" == "true" ( |
||||
echo Finished downloading %WRAPPER_JAR% |
||||
) |
||||
) |
||||
@REM End of extension |
||||
|
||||
@REM Provide a "standardized" way to retrieve the CLI args that will |
||||
@REM work with both Windows and non-Windows executions. |
||||
set MAVEN_CMD_LINE_ARGS=%* |
||||
|
||||
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* |
||||
if ERRORLEVEL 1 goto error |
||||
goto end |
||||
|
||||
:error |
||||
set ERROR_CODE=1 |
||||
|
||||
:end |
||||
@endlocal & set ERROR_CODE=%ERROR_CODE% |
||||
|
||||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost |
||||
@REM check for post script, once with legacy .bat ending and once with .cmd ending |
||||
if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" |
||||
if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" |
||||
:skipRcPost |
||||
|
||||
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' |
||||
if "%MAVEN_BATCH_PAUSE%" == "on" pause |
||||
|
||||
if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% |
||||
|
||||
exit /B %ERROR_CODE% |
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,404 @@ |
||||
{ |
||||
"name": "no-name", |
||||
"license": "UNLICENSED", |
||||
"dependencies": { |
||||
"@polymer/iron-icon": "3.0.1", |
||||
"@polymer/iron-iconset-svg": "3.0.1", |
||||
"@polymer/iron-list": "3.1.0", |
||||
"@polymer/iron-meta": "3.0.1", |
||||
"@polymer/iron-resizable-behavior": "3.0.1", |
||||
"@polymer/polymer": "3.4.1", |
||||
"@vaadin/accordion": "23.0.7", |
||||
"@vaadin/app-layout": "23.0.7", |
||||
"@vaadin/avatar": "23.0.7", |
||||
"@vaadin/avatar-group": "23.0.7", |
||||
"@vaadin/board": "23.0.7", |
||||
"@vaadin/bundles": "23.0.7", |
||||
"@vaadin/button": "23.0.7", |
||||
"@vaadin/charts": "23.0.7", |
||||
"@vaadin/checkbox": "23.0.7", |
||||
"@vaadin/checkbox-group": "23.0.7", |
||||
"@vaadin/combo-box": "23.0.7", |
||||
"@vaadin/common-frontend": "0.0.17", |
||||
"@vaadin/component-base": "23.0.7", |
||||
"@vaadin/confirm-dialog": "23.0.7", |
||||
"@vaadin/context-menu": "23.0.7", |
||||
"@vaadin/cookie-consent": "23.0.7", |
||||
"@vaadin/crud": "23.0.7", |
||||
"@vaadin/custom-field": "23.0.7", |
||||
"@vaadin/date-picker": "23.0.7", |
||||
"@vaadin/date-time-picker": "23.0.7", |
||||
"@vaadin/details": "23.0.7", |
||||
"@vaadin/dialog": "23.0.7", |
||||
"@vaadin/email-field": "23.0.7", |
||||
"@vaadin/field-base": "23.0.7", |
||||
"@vaadin/field-highlighter": "23.0.7", |
||||
"@vaadin/flow-frontend": "./target/flow-frontend", |
||||
"@vaadin/form-layout": "23.0.7", |
||||
"@vaadin/grid": "23.0.7", |
||||
"@vaadin/grid-pro": "23.0.7", |
||||
"@vaadin/horizontal-layout": "23.0.7", |
||||
"@vaadin/icon": "23.0.7", |
||||
"@vaadin/icons": "23.0.7", |
||||
"@vaadin/input-container": "23.0.7", |
||||
"@vaadin/integer-field": "23.0.7", |
||||
"@vaadin/item": "23.0.7", |
||||
"@vaadin/list-box": "23.0.7", |
||||
"@vaadin/login": "23.0.7", |
||||
"@vaadin/map": "23.0.7", |
||||
"@vaadin/menu-bar": "23.0.7", |
||||
"@vaadin/message-input": "23.0.7", |
||||
"@vaadin/message-list": "23.0.7", |
||||
"@vaadin/notification": "23.0.7", |
||||
"@vaadin/number-field": "23.0.7", |
||||
"@vaadin/password-field": "23.0.7", |
||||
"@vaadin/polymer-legacy-adapter": "23.0.7", |
||||
"@vaadin/progress-bar": "23.0.7", |
||||
"@vaadin/radio-group": "23.0.7", |
||||
"@vaadin/rich-text-editor": "23.0.7", |
||||
"@vaadin/router": "1.7.4", |
||||
"@vaadin/scroller": "23.0.7", |
||||
"@vaadin/select": "23.0.7", |
||||
"@vaadin/split-layout": "23.0.7", |
||||
"@vaadin/tabs": "23.0.7", |
||||
"@vaadin/text-area": "23.0.7", |
||||
"@vaadin/text-field": "23.0.7", |
||||
"@vaadin/time-picker": "23.0.7", |
||||
"@vaadin/upload": "23.0.7", |
||||
"@vaadin/vaadin-accordion": "23.0.7", |
||||
"@vaadin/vaadin-app-layout": "23.0.7", |
||||
"@vaadin/vaadin-avatar": "23.0.7", |
||||
"@vaadin/vaadin-board": "23.0.7", |
||||
"@vaadin/vaadin-button": "23.0.7", |
||||
"@vaadin/vaadin-charts": "23.0.7", |
||||
"@vaadin/vaadin-checkbox": "23.0.7", |
||||
"@vaadin/vaadin-combo-box": "23.0.7", |
||||
"@vaadin/vaadin-confirm-dialog": "23.0.7", |
||||
"@vaadin/vaadin-context-menu": "23.0.7", |
||||
"@vaadin/vaadin-cookie-consent": "23.0.7", |
||||
"@vaadin/vaadin-crud": "23.0.7", |
||||
"@vaadin/vaadin-custom-field": "23.0.7", |
||||
"@vaadin/vaadin-date-picker": "23.0.7", |
||||
"@vaadin/vaadin-date-time-picker": "23.0.7", |
||||
"@vaadin/vaadin-details": "23.0.7", |
||||
"@vaadin/vaadin-development-mode-detector": "2.0.5", |
||||
"@vaadin/vaadin-dialog": "23.0.7", |
||||
"@vaadin/vaadin-form-layout": "23.0.7", |
||||
"@vaadin/vaadin-grid": "23.0.7", |
||||
"@vaadin/vaadin-grid-pro": "23.0.7", |
||||
"@vaadin/vaadin-icon": "23.0.7", |
||||
"@vaadin/vaadin-icons": "23.0.7", |
||||
"@vaadin/vaadin-item": "23.0.7", |
||||
"@vaadin/vaadin-list-box": "23.0.7", |
||||
"@vaadin/vaadin-list-mixin": "23.0.7", |
||||
"@vaadin/vaadin-login": "23.0.7", |
||||
"@vaadin/vaadin-lumo-styles": "23.0.7", |
||||
"@vaadin/vaadin-material-styles": "23.0.7", |
||||
"@vaadin/vaadin-menu-bar": "23.0.7", |
||||
"@vaadin/vaadin-messages": "23.0.7", |
||||
"@vaadin/vaadin-notification": "23.0.7", |
||||
"@vaadin/vaadin-ordered-layout": "23.0.7", |
||||
"@vaadin/vaadin-overlay": "23.0.7", |
||||
"@vaadin/vaadin-progress-bar": "23.0.7", |
||||
"@vaadin/vaadin-radio-button": "23.0.7", |
||||
"@vaadin/vaadin-rich-text-editor": "23.0.7", |
||||
"@vaadin/vaadin-select": "23.0.7", |
||||
"@vaadin/vaadin-split-layout": "23.0.7", |
||||
"@vaadin/vaadin-tabs": "23.0.7", |
||||
"@vaadin/vaadin-template-renderer": "23.0.7", |
||||
"@vaadin/vaadin-text-field": "23.0.7", |
||||
"@vaadin/vaadin-themable-mixin": "23.0.7", |
||||
"@vaadin/vaadin-time-picker": "23.0.7", |
||||
"@vaadin/vaadin-upload": "23.0.7", |
||||
"@vaadin/vaadin-usage-statistics": "2.1.2", |
||||
"@vaadin/vaadin-virtual-list": "23.0.7", |
||||
"@vaadin/vertical-layout": "23.0.7", |
||||
"@vaadin/virtual-list": "23.0.7", |
||||
"construct-style-sheets-polyfill": "3.0.4", |
||||
"date-fns": "2.28.0", |
||||
"line-awesome": "1.3.0", |
||||
"lit": "2.1.4" |
||||
}, |
||||
"devDependencies": { |
||||
"chokidar": "^3.5.0", |
||||
"compression-webpack-plugin": "4.0.1", |
||||
"css-loader": "5.2.7", |
||||
"esbuild-loader": "2.15.1", |
||||
"extra-watch-webpack-plugin": "1.0.3", |
||||
"extract-loader": "5.1.0", |
||||
"file-loader": "6.2.0", |
||||
"fork-ts-checker-webpack-plugin": "6.2.1", |
||||
"glob": "7.1.6", |
||||
"html-webpack-plugin": "4.5.1", |
||||
"lit-css-loader": "0.1.0", |
||||
"loader-utils": "2.0.0", |
||||
"typescript": "4.5.3", |
||||
"webpack": "4.46.0", |
||||
"webpack-cli": "4.9.2", |
||||
"webpack-dev-server": "4.8.1", |
||||
"webpack-merge": "4.2.2", |
||||
"workbox-core": "6.5.0", |
||||
"workbox-precaching": "6.5.0", |
||||
"workbox-webpack-plugin": "6.5.0" |
||||
}, |
||||
"overrides": { |
||||
"@vaadin/accordion": "$@vaadin/accordion", |
||||
"@vaadin/app-layout": "$@vaadin/app-layout", |
||||
"@vaadin/avatar": "$@vaadin/avatar", |
||||
"@vaadin/avatar-group": "$@vaadin/avatar-group", |
||||
"@vaadin/button": "$@vaadin/button", |
||||
"@vaadin/checkbox": "$@vaadin/checkbox", |
||||
"@vaadin/checkbox-group": "$@vaadin/checkbox-group", |
||||
"@vaadin/combo-box": "$@vaadin/combo-box", |
||||
"@vaadin/component-base": "$@vaadin/component-base", |
||||
"@vaadin/context-menu": "$@vaadin/context-menu", |
||||
"@vaadin/custom-field": "$@vaadin/custom-field", |
||||
"@vaadin/date-picker": "$@vaadin/date-picker", |
||||
"@vaadin/date-time-picker": "$@vaadin/date-time-picker", |
||||
"@vaadin/details": "$@vaadin/details", |
||||
"@vaadin/dialog": "$@vaadin/dialog", |
||||
"@vaadin/email-field": "$@vaadin/email-field", |
||||
"@vaadin/field-base": "$@vaadin/field-base", |
||||
"@vaadin/field-highlighter": "$@vaadin/field-highlighter", |
||||
"@vaadin/form-layout": "$@vaadin/form-layout", |
||||
"@vaadin/grid": "$@vaadin/grid", |
||||
"@vaadin/horizontal-layout": "$@vaadin/horizontal-layout", |
||||
"@vaadin/icon": "$@vaadin/icon", |
||||
"@vaadin/icons": "$@vaadin/icons", |
||||
"@vaadin/input-container": "$@vaadin/input-container", |
||||
"@vaadin/integer-field": "$@vaadin/integer-field", |
||||
"@polymer/iron-icon": "$@polymer/iron-icon", |
||||
"@polymer/iron-iconset-svg": "$@polymer/iron-iconset-svg", |
||||
"@polymer/iron-list": "$@polymer/iron-list", |
||||
"@polymer/iron-meta": "$@polymer/iron-meta", |
||||
"@polymer/iron-resizable-behavior": "$@polymer/iron-resizable-behavior", |
||||
"@vaadin/item": "$@vaadin/item", |
||||
"@vaadin/list-box": "$@vaadin/list-box", |
||||
"@vaadin/login": "$@vaadin/login", |
||||
"@vaadin/menu-bar": "$@vaadin/menu-bar", |
||||
"@vaadin/message-input": "$@vaadin/message-input", |
||||
"@vaadin/message-list": "$@vaadin/message-list", |
||||
"@vaadin/notification": "$@vaadin/notification", |
||||
"@vaadin/number-field": "$@vaadin/number-field", |
||||
"@vaadin/password-field": "$@vaadin/password-field", |
||||
"@vaadin/polymer-legacy-adapter": "$@vaadin/polymer-legacy-adapter", |
||||
"@vaadin/progress-bar": "$@vaadin/progress-bar", |
||||
"@vaadin/radio-group": "$@vaadin/radio-group", |
||||
"@vaadin/scroller": "$@vaadin/scroller", |
||||
"@vaadin/select": "$@vaadin/select", |
||||
"@vaadin/split-layout": "$@vaadin/split-layout", |
||||
"@vaadin/tabs": "$@vaadin/tabs", |
||||
"@vaadin/text-area": "$@vaadin/text-area", |
||||
"@vaadin/text-field": "$@vaadin/text-field", |
||||
"@vaadin/time-picker": "$@vaadin/time-picker", |
||||
"@vaadin/upload": "$@vaadin/upload", |
||||
"@vaadin/vaadin-accordion": "$@vaadin/vaadin-accordion", |
||||
"@vaadin/vaadin-app-layout": "$@vaadin/vaadin-app-layout", |
||||
"@vaadin/vaadin-avatar": "$@vaadin/vaadin-avatar", |
||||
"@vaadin/vaadin-button": "$@vaadin/vaadin-button", |
||||
"@vaadin/vaadin-checkbox": "$@vaadin/vaadin-checkbox", |
||||
"@vaadin/vaadin-combo-box": "$@vaadin/vaadin-combo-box", |
||||
"@vaadin/vaadin-context-menu": "$@vaadin/vaadin-context-menu", |
||||
"@vaadin/vaadin-custom-field": "$@vaadin/vaadin-custom-field", |
||||
"@vaadin/vaadin-date-picker": "$@vaadin/vaadin-date-picker", |
||||
"@vaadin/vaadin-date-time-picker": "$@vaadin/vaadin-date-time-picker", |
||||
"@vaadin/vaadin-details": "$@vaadin/vaadin-details", |
||||
"@vaadin/vaadin-development-mode-detector": "$@vaadin/vaadin-development-mode-detector", |
||||
"@vaadin/vaadin-dialog": "$@vaadin/vaadin-dialog", |
||||
"@vaadin/vaadin-form-layout": "$@vaadin/vaadin-form-layout", |
||||
"@vaadin/vaadin-grid": "$@vaadin/vaadin-grid", |
||||
"@vaadin/vaadin-icon": "$@vaadin/vaadin-icon", |
||||
"@vaadin/vaadin-icons": "$@vaadin/vaadin-icons", |
||||
"@vaadin/vaadin-item": "$@vaadin/vaadin-item", |
||||
"@vaadin/vaadin-list-box": "$@vaadin/vaadin-list-box", |
||||
"@vaadin/vaadin-list-mixin": "$@vaadin/vaadin-list-mixin", |
||||
"@vaadin/vaadin-login": "$@vaadin/vaadin-login", |
||||
"@vaadin/vaadin-lumo-styles": "$@vaadin/vaadin-lumo-styles", |
||||
"@vaadin/vaadin-material-styles": "$@vaadin/vaadin-material-styles", |
||||
"@vaadin/vaadin-menu-bar": "$@vaadin/vaadin-menu-bar", |
||||
"@vaadin/vaadin-messages": "$@vaadin/vaadin-messages", |
||||
"@vaadin/vaadin-notification": "$@vaadin/vaadin-notification", |
||||
"@vaadin/vaadin-ordered-layout": "$@vaadin/vaadin-ordered-layout", |
||||
"@vaadin/vaadin-overlay": "$@vaadin/vaadin-overlay", |
||||
"@vaadin/vaadin-progress-bar": "$@vaadin/vaadin-progress-bar", |
||||
"@vaadin/vaadin-radio-button": "$@vaadin/vaadin-radio-button", |
||||
"@vaadin/router": "$@vaadin/router", |
||||
"@vaadin/vaadin-select": "$@vaadin/vaadin-select", |
||||
"@vaadin/vaadin-split-layout": "$@vaadin/vaadin-split-layout", |
||||
"@vaadin/vaadin-tabs": "$@vaadin/vaadin-tabs", |
||||
"@vaadin/vaadin-template-renderer": "$@vaadin/vaadin-template-renderer", |
||||
"@vaadin/vaadin-text-field": "$@vaadin/vaadin-text-field", |
||||
"@vaadin/vaadin-themable-mixin": "$@vaadin/vaadin-themable-mixin", |
||||
"@vaadin/vaadin-time-picker": "$@vaadin/vaadin-time-picker", |
||||
"@vaadin/vaadin-upload": "$@vaadin/vaadin-upload", |
||||
"@vaadin/vaadin-usage-statistics": "$@vaadin/vaadin-usage-statistics", |
||||
"@vaadin/vaadin-virtual-list": "$@vaadin/vaadin-virtual-list", |
||||
"@vaadin/vertical-layout": "$@vaadin/vertical-layout", |
||||
"@vaadin/virtual-list": "$@vaadin/virtual-list", |
||||
"@vaadin/board": "$@vaadin/board", |
||||
"@vaadin/charts": "$@vaadin/charts", |
||||
"@vaadin/confirm-dialog": "$@vaadin/confirm-dialog", |
||||
"@vaadin/cookie-consent": "$@vaadin/cookie-consent", |
||||
"@vaadin/crud": "$@vaadin/crud", |
||||
"@vaadin/grid-pro": "$@vaadin/grid-pro", |
||||
"@vaadin/rich-text-editor": "$@vaadin/rich-text-editor", |
||||
"@vaadin/vaadin-board": "$@vaadin/vaadin-board", |
||||
"@vaadin/vaadin-charts": "$@vaadin/vaadin-charts", |
||||
"@vaadin/vaadin-confirm-dialog": "$@vaadin/vaadin-confirm-dialog", |
||||
"@vaadin/vaadin-cookie-consent": "$@vaadin/vaadin-cookie-consent", |
||||
"@vaadin/vaadin-crud": "$@vaadin/vaadin-crud", |
||||
"@vaadin/vaadin-grid-pro": "$@vaadin/vaadin-grid-pro", |
||||
"@vaadin/vaadin-rich-text-editor": "$@vaadin/vaadin-rich-text-editor", |
||||
"@vaadin/bundles": "$@vaadin/bundles", |
||||
"@vaadin/map": "$@vaadin/map", |
||||
"@polymer/polymer": "$@polymer/polymer", |
||||
"@vaadin/common-frontend": "$@vaadin/common-frontend", |
||||
"construct-style-sheets-polyfill": "$construct-style-sheets-polyfill", |
||||
"date-fns": "$date-fns", |
||||
"lit": "$lit", |
||||
"chokidar": "$chokidar", |
||||
"line-awesome": "$line-awesome" |
||||
}, |
||||
"vaadin": { |
||||
"dependencies": { |
||||
"@polymer/iron-icon": "3.0.1", |
||||
"@polymer/iron-iconset-svg": "3.0.1", |
||||
"@polymer/iron-list": "3.1.0", |
||||
"@polymer/iron-meta": "3.0.1", |
||||
"@polymer/iron-resizable-behavior": "3.0.1", |
||||
"@polymer/polymer": "3.4.1", |
||||
"@vaadin/accordion": "23.0.7", |
||||
"@vaadin/app-layout": "23.0.7", |
||||
"@vaadin/avatar": "23.0.7", |
||||
"@vaadin/avatar-group": "23.0.7", |
||||
"@vaadin/board": "23.0.7", |
||||
"@vaadin/bundles": "23.0.7", |
||||
"@vaadin/button": "23.0.7", |
||||
"@vaadin/charts": "23.0.7", |
||||
"@vaadin/checkbox": "23.0.7", |
||||
"@vaadin/checkbox-group": "23.0.7", |
||||
"@vaadin/combo-box": "23.0.7", |
||||
"@vaadin/common-frontend": "0.0.17", |
||||
"@vaadin/component-base": "23.0.7", |
||||
"@vaadin/confirm-dialog": "23.0.7", |
||||
"@vaadin/context-menu": "23.0.7", |
||||
"@vaadin/cookie-consent": "23.0.7", |
||||
"@vaadin/crud": "23.0.7", |
||||
"@vaadin/custom-field": "23.0.7", |
||||
"@vaadin/date-picker": "23.0.7", |
||||
"@vaadin/date-time-picker": "23.0.7", |
||||
"@vaadin/details": "23.0.7", |
||||
"@vaadin/dialog": "23.0.7", |
||||
"@vaadin/email-field": "23.0.7", |
||||
"@vaadin/field-base": "23.0.7", |
||||
"@vaadin/field-highlighter": "23.0.7", |
||||
"@vaadin/form-layout": "23.0.7", |
||||
"@vaadin/grid": "23.0.7", |
||||
"@vaadin/grid-pro": "23.0.7", |
||||
"@vaadin/horizontal-layout": "23.0.7", |
||||
"@vaadin/icon": "23.0.7", |
||||
"@vaadin/icons": "23.0.7", |
||||
"@vaadin/input-container": "23.0.7", |
||||
"@vaadin/integer-field": "23.0.7", |
||||
"@vaadin/item": "23.0.7", |
||||
"@vaadin/list-box": "23.0.7", |
||||
"@vaadin/login": "23.0.7", |
||||
"@vaadin/map": "23.0.7", |
||||
"@vaadin/menu-bar": "23.0.7", |
||||
"@vaadin/message-input": "23.0.7", |
||||
"@vaadin/message-list": "23.0.7", |
||||
"@vaadin/notification": "23.0.7", |
||||
"@vaadin/number-field": "23.0.7", |
||||
"@vaadin/password-field": "23.0.7", |
||||
"@vaadin/polymer-legacy-adapter": "23.0.7", |
||||
"@vaadin/progress-bar": "23.0.7", |
||||
"@vaadin/radio-group": "23.0.7", |
||||
"@vaadin/rich-text-editor": "23.0.7", |
||||
"@vaadin/router": "1.7.4", |
||||
"@vaadin/scroller": "23.0.7", |
||||
"@vaadin/select": "23.0.7", |
||||
"@vaadin/split-layout": "23.0.7", |
||||
"@vaadin/tabs": "23.0.7", |
||||
"@vaadin/text-area": "23.0.7", |
||||
"@vaadin/text-field": "23.0.7", |
||||
"@vaadin/time-picker": "23.0.7", |
||||
"@vaadin/upload": "23.0.7", |
||||
"@vaadin/vaadin-accordion": "23.0.7", |
||||
"@vaadin/vaadin-app-layout": "23.0.7", |
||||
"@vaadin/vaadin-avatar": "23.0.7", |
||||
"@vaadin/vaadin-board": "23.0.7", |
||||
"@vaadin/vaadin-button": "23.0.7", |
||||
"@vaadin/vaadin-charts": "23.0.7", |
||||
"@vaadin/vaadin-checkbox": "23.0.7", |
||||
"@vaadin/vaadin-combo-box": "23.0.7", |
||||
"@vaadin/vaadin-confirm-dialog": "23.0.7", |
||||
"@vaadin/vaadin-context-menu": "23.0.7", |
||||
"@vaadin/vaadin-cookie-consent": "23.0.7", |
||||
"@vaadin/vaadin-crud": "23.0.7", |
||||
"@vaadin/vaadin-custom-field": "23.0.7", |
||||
"@vaadin/vaadin-date-picker": "23.0.7", |
||||
"@vaadin/vaadin-date-time-picker": "23.0.7", |
||||
"@vaadin/vaadin-details": "23.0.7", |
||||
"@vaadin/vaadin-development-mode-detector": "2.0.5", |
||||
"@vaadin/vaadin-dialog": "23.0.7", |
||||
"@vaadin/vaadin-form-layout": "23.0.7", |
||||
"@vaadin/vaadin-grid": "23.0.7", |
||||
"@vaadin/vaadin-grid-pro": "23.0.7", |
||||
"@vaadin/vaadin-icon": "23.0.7", |
||||
"@vaadin/vaadin-icons": "23.0.7", |
||||
"@vaadin/vaadin-item": "23.0.7", |
||||
"@vaadin/vaadin-list-box": "23.0.7", |
||||
"@vaadin/vaadin-list-mixin": "23.0.7", |
||||
"@vaadin/vaadin-login": "23.0.7", |
||||
"@vaadin/vaadin-lumo-styles": "23.0.7", |
||||
"@vaadin/vaadin-material-styles": "23.0.7", |
||||
"@vaadin/vaadin-menu-bar": "23.0.7", |
||||
"@vaadin/vaadin-messages": "23.0.7", |
||||
"@vaadin/vaadin-notification": "23.0.7", |
||||
"@vaadin/vaadin-ordered-layout": "23.0.7", |
||||
"@vaadin/vaadin-overlay": "23.0.7", |
||||
"@vaadin/vaadin-progress-bar": "23.0.7", |
||||
"@vaadin/vaadin-radio-button": "23.0.7", |
||||
"@vaadin/vaadin-rich-text-editor": "23.0.7", |
||||
"@vaadin/vaadin-select": "23.0.7", |
||||
"@vaadin/vaadin-split-layout": "23.0.7", |
||||
"@vaadin/vaadin-tabs": "23.0.7", |
||||
"@vaadin/vaadin-template-renderer": "23.0.7", |
||||
"@vaadin/vaadin-text-field": "23.0.7", |
||||
"@vaadin/vaadin-themable-mixin": "23.0.7", |
||||
"@vaadin/vaadin-time-picker": "23.0.7", |
||||
"@vaadin/vaadin-upload": "23.0.7", |
||||
"@vaadin/vaadin-usage-statistics": "2.1.2", |
||||
"@vaadin/vaadin-virtual-list": "23.0.7", |
||||
"@vaadin/vertical-layout": "23.0.7", |
||||
"@vaadin/virtual-list": "23.0.7", |
||||
"construct-style-sheets-polyfill": "3.0.4", |
||||
"date-fns": "2.28.0", |
||||
"line-awesome": "1.3.0", |
||||
"lit": "2.1.4" |
||||
}, |
||||
"devDependencies": { |
||||
"chokidar": "^3.5.0", |
||||
"compression-webpack-plugin": "4.0.1", |
||||
"css-loader": "5.2.7", |
||||
"esbuild-loader": "2.15.1", |
||||
"extra-watch-webpack-plugin": "1.0.3", |
||||
"extract-loader": "5.1.0", |
||||
"file-loader": "6.2.0", |
||||
"fork-ts-checker-webpack-plugin": "6.2.1", |
||||
"glob": "7.1.6", |
||||
"html-webpack-plugin": "4.5.1", |
||||
"lit-css-loader": "0.1.0", |
||||
"loader-utils": "2.0.0", |
||||
"typescript": "4.5.3", |
||||
"webpack": "4.46.0", |
||||
"webpack-cli": "4.9.2", |
||||
"webpack-dev-server": "4.8.1", |
||||
"webpack-merge": "4.2.2", |
||||
"workbox-core": "6.5.0", |
||||
"workbox-precaching": "6.5.0", |
||||
"workbox-webpack-plugin": "6.5.0" |
||||
}, |
||||
"hash": "17b0ef070c22faffba8f8497c5326037e3d1e25619539613895dd4034ed50603" |
||||
} |
||||
} |
||||
@ -0,0 +1,275 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" |
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
||||
<modelVersion>4.0.0</modelVersion> |
||||
<!-- Project from https://start.vaadin.com/project/21111318-49ac-485b-92f4-892e176b446f --> |
||||
<groupId>de.kreth.invoice</groupId> |
||||
<artifactId>trainerinvoice</artifactId> |
||||
<name>Übungsleiterabrechnungen</name> |
||||
<version>1.0.0-SNAPSHOT</version> |
||||
<packaging>jar</packaging> |
||||
|
||||
<properties> |
||||
<java.version>11</java.version> |
||||
<vaadin.version>23.0.8</vaadin.version> |
||||
<org.keycloak.version>11.0.1</org.keycloak.version> |
||||
</properties> |
||||
|
||||
<parent> |
||||
<groupId>org.springframework.boot</groupId> |
||||
<artifactId>spring-boot-starter-parent</artifactId> |
||||
<version>2.6.7</version> |
||||
</parent> |
||||
|
||||
<repositories> |
||||
<!-- The order of definitions matters. Explicitly defining central here to make sure it has the highest priority. --> |
||||
|
||||
<!-- Main Maven repository --> |
||||
<repository> |
||||
<id>central</id> |
||||
<url>https://repo.maven.apache.org/maven2</url> |
||||
<snapshots> |
||||
<enabled>false</enabled> |
||||
</snapshots> |
||||
</repository> |
||||
<repository> |
||||
<id>vaadin-prereleases</id> |
||||
<url> |
||||
https://maven.vaadin.com/vaadin-prereleases/ |
||||
</url> |
||||
</repository> |
||||
<!-- Repository used by many Vaadin add-ons --> |
||||
<repository> |
||||
<id>Vaadin Directory</id> |
||||
<url>https://maven.vaadin.com/vaadin-addons</url> |
||||
<snapshots> |
||||
<enabled>false</enabled> |
||||
</snapshots> |
||||
</repository> |
||||
</repositories> |
||||
|
||||
<pluginRepositories> |
||||
<!-- The order of definitions matters. Explicitly defining central here to make sure it has the highest priority. --> |
||||
<pluginRepository> |
||||
<id>central</id> |
||||
<url>https://repo.maven.apache.org/maven2</url> |
||||
<snapshots> |
||||
<enabled>false</enabled> |
||||
</snapshots> |
||||
</pluginRepository> |
||||
<pluginRepository> |
||||
<id>vaadin-prereleases</id> |
||||
<url> |
||||
https://maven.vaadin.com/vaadin-prereleases/ |
||||
</url> |
||||
</pluginRepository> |
||||
</pluginRepositories> |
||||
|
||||
<dependencyManagement> |
||||
<dependencies> |
||||
<dependency> |
||||
<groupId>com.vaadin</groupId> |
||||
<artifactId>vaadin-bom</artifactId> |
||||
<version>${vaadin.version}</version> |
||||
<type>pom</type> |
||||
<scope>import</scope> |
||||
</dependency> |
||||
|
||||
<dependency> |
||||
<groupId>org.keycloak.bom</groupId> |
||||
<artifactId>keycloak-adapter-bom</artifactId> |
||||
<version>${org.keycloak.version}</version> |
||||
<type>pom</type> |
||||
<scope>import</scope> |
||||
</dependency> |
||||
</dependencies> |
||||
</dependencyManagement> |
||||
|
||||
<dependencies> |
||||
<dependency> |
||||
<groupId>com.vaadin</groupId> |
||||
<!-- Replace artifactId with vaadin-core to use only free components --> |
||||
<artifactId>vaadin</artifactId> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>com.vaadin</groupId> |
||||
<artifactId>vaadin-spring-boot-starter</artifactId> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>com.h2database</groupId> |
||||
<artifactId>h2</artifactId> |
||||
<scope>runtime</scope> |
||||
</dependency> |
||||
|
||||
<dependency> |
||||
<groupId>com.vaadin</groupId> |
||||
<artifactId>exampledata</artifactId> |
||||
<version>4.1.4</version> |
||||
</dependency> |
||||
|
||||
<dependency> |
||||
<groupId>org.springframework.boot</groupId> |
||||
<artifactId>spring-boot-starter-data-jpa</artifactId> |
||||
</dependency> |
||||
|
||||
<dependency> |
||||
<groupId>org.springframework.boot</groupId> |
||||
<artifactId>spring-boot-starter-validation</artifactId> |
||||
</dependency> |
||||
|
||||
<dependency> |
||||
<groupId>org.springframework.boot</groupId> |
||||
<artifactId>spring-boot-starter-security</artifactId> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>org.keycloak</groupId> |
||||
<artifactId>keycloak-spring-boot-starter</artifactId> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>org.keycloak</groupId> |
||||
<artifactId>keycloak-spring-security-adapter</artifactId> |
||||
</dependency> |
||||
|
||||
<dependency> |
||||
<groupId>org.springframework.boot</groupId> |
||||
<artifactId>spring-boot-devtools</artifactId> |
||||
<optional>true</optional> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>org.springframework.boot</groupId> |
||||
<artifactId>spring-boot-starter-test</artifactId> |
||||
<scope>test</scope> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>com.vaadin</groupId> |
||||
<artifactId>vaadin-testbench</artifactId> |
||||
<scope>test</scope> |
||||
</dependency> |
||||
<!-- Include JUnit 4 support for TestBench and others --> |
||||
<dependency> |
||||
<groupId>org.junit.vintage</groupId> |
||||
<artifactId>junit-vintage-engine</artifactId> |
||||
<scope>test</scope> |
||||
<exclusions> |
||||
<exclusion> |
||||
<groupId>org.hamcrest</groupId> |
||||
<artifactId>hamcrest-core</artifactId> |
||||
</exclusion> |
||||
</exclusions> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>io.github.bonigarcia</groupId> |
||||
<artifactId>webdrivermanager</artifactId> |
||||
<version>5.0.3</version> |
||||
<scope>test</scope> |
||||
</dependency> |
||||
</dependencies> |
||||
|
||||
<build> |
||||
<defaultGoal>spring-boot:run</defaultGoal> |
||||
<plugins> |
||||
<plugin> |
||||
<groupId>org.springframework.boot</groupId> |
||||
<artifactId>spring-boot-maven-plugin</artifactId> |
||||
<!-- Clean build and startup time for Vaadin apps sometimes may exceed |
||||
the default Spring Boot's 30sec timeout. --> |
||||
<configuration> |
||||
<wait>500</wait> |
||||
<maxAttempts>240</maxAttempts> |
||||
</configuration> |
||||
</plugin> |
||||
|
||||
<!-- |
||||
Take care of synchronizing java dependencies and imports in |
||||
package.json and main.js files. |
||||
It also creates webpack.config.js if not exists yet. |
||||
--> |
||||
<plugin> |
||||
<groupId>com.vaadin</groupId> |
||||
<artifactId>vaadin-maven-plugin</artifactId> |
||||
<version>${vaadin.version}</version> |
||||
<executions> |
||||
<execution> |
||||
<goals> |
||||
<goal>prepare-frontend</goal> |
||||
</goals> |
||||
</execution> |
||||
</executions> |
||||
</plugin> |
||||
</plugins> |
||||
</build> |
||||
|
||||
<profiles> |
||||
<profile> |
||||
<!-- Production mode is activated using -Pproduction --> |
||||
<id>production</id> |
||||
<build> |
||||
<plugins> |
||||
<plugin> |
||||
<groupId>com.vaadin</groupId> |
||||
<artifactId>vaadin-maven-plugin</artifactId> |
||||
<version>${vaadin.version}</version> |
||||
<executions> |
||||
<execution> |
||||
<goals> |
||||
<goal>build-frontend</goal> |
||||
</goals> |
||||
<phase>compile</phase> |
||||
</execution> |
||||
</executions> |
||||
<configuration> |
||||
<productionMode>true</productionMode> |
||||
</configuration> |
||||
</plugin> |
||||
</plugins> |
||||
</build> |
||||
</profile> |
||||
|
||||
<profile> |
||||
<id>it</id> |
||||
<build> |
||||
<plugins> |
||||
<plugin> |
||||
<groupId>org.springframework.boot</groupId> |
||||
<artifactId>spring-boot-maven-plugin</artifactId> |
||||
<executions> |
||||
<execution> |
||||
<id>start-spring-boot</id> |
||||
<phase>pre-integration-test</phase> |
||||
<goals> |
||||
<goal>start</goal> |
||||
</goals> |
||||
</execution> |
||||
<execution> |
||||
<id>stop-spring-boot</id> |
||||
<phase>post-integration-test</phase> |
||||
<goals> |
||||
<goal>stop</goal> |
||||
</goals> |
||||
</execution> |
||||
</executions> |
||||
</plugin> |
||||
|
||||
<!-- Runs the integration tests (*IT) after the server is started --> |
||||
<plugin> |
||||
<groupId>org.apache.maven.plugins</groupId> |
||||
<artifactId>maven-failsafe-plugin</artifactId> |
||||
<executions> |
||||
<execution> |
||||
<goals> |
||||
<goal>integration-test</goal> |
||||
<goal>verify</goal> |
||||
</goals> |
||||
</execution> |
||||
</executions> |
||||
<configuration> |
||||
<trimStackTrace>false</trimStackTrace> |
||||
<enableAssertions>true</enableAssertions> |
||||
</configuration> |
||||
</plugin> |
||||
</plugins> |
||||
</build> |
||||
</profile> |
||||
|
||||
</profiles> |
||||
</project> |
||||
@ -0,0 +1,31 @@ |
||||
package de.kreth.invoice; |
||||
|
||||
import org.springframework.boot.SpringApplication; |
||||
import org.springframework.boot.autoconfigure.SpringBootApplication; |
||||
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; |
||||
|
||||
import com.vaadin.flow.component.dependency.NpmPackage; |
||||
import com.vaadin.flow.component.page.AppShellConfigurator; |
||||
import com.vaadin.flow.server.PWA; |
||||
import com.vaadin.flow.theme.Theme; |
||||
|
||||
/** |
||||
* The entry point of the Spring Boot application. |
||||
* |
||||
* Use the @PWA annotation make the application installable on phones, tablets |
||||
* and some desktop browsers. |
||||
* |
||||
*/ |
||||
@SpringBootApplication |
||||
@Theme(value = "trainerinvoice") |
||||
@PWA(name = "trainerinvoice", shortName = "trainerinvoice", offlineResources = {}) |
||||
@NpmPackage(value = "line-awesome", version = "1.3.0") |
||||
public class Application extends SpringBootServletInitializer implements AppShellConfigurator { |
||||
|
||||
private static final long serialVersionUID = 8632833774084603989L; |
||||
|
||||
public static void main(String[] args) { |
||||
SpringApplication.run(Application.class, args); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,32 @@ |
||||
package de.kreth.invoice.components; |
||||
|
||||
import java.text.NumberFormat; |
||||
import java.time.format.DateTimeFormatter; |
||||
import java.time.format.FormatStyle; |
||||
|
||||
import com.vaadin.flow.component.grid.Grid; |
||||
import com.vaadin.flow.data.renderer.LocalDateTimeRenderer; |
||||
import com.vaadin.flow.data.renderer.NumberRenderer; |
||||
|
||||
import de.kreth.invoice.data.Invoice; |
||||
|
||||
public class InvoiceGrid extends Grid<Invoice> { |
||||
|
||||
private static final long serialVersionUID = 662980245990122807L; |
||||
|
||||
public InvoiceGrid() { |
||||
addClassName("bordered"); |
||||
|
||||
Column<Invoice> invoiceIdCol = addColumn(Invoice::getInvoiceId); |
||||
invoiceIdCol.setHeader("Rechnungsnummer"); |
||||
|
||||
Column<Invoice> invoiceDateCol = addColumn(new LocalDateTimeRenderer<>(Invoice::getInvoiceDate, |
||||
DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM))); |
||||
invoiceDateCol.setHeader("Rechnungsdatum"); |
||||
|
||||
Column<Invoice> invoiceSum = addColumn(new NumberRenderer<>(Invoice::getSum, |
||||
NumberFormat.getCurrencyInstance())); |
||||
invoiceSum.setHeader("Summe"); |
||||
|
||||
} |
||||
} |
||||
@ -0,0 +1,119 @@ |
||||
package de.kreth.invoice.components; |
||||
|
||||
import java.time.LocalDate; |
||||
import java.time.LocalDateTime; |
||||
import java.time.LocalTime; |
||||
import java.util.List; |
||||
|
||||
import com.vaadin.flow.component.ClickEvent; |
||||
import com.vaadin.flow.component.button.Button; |
||||
import com.vaadin.flow.component.combobox.ComboBox; |
||||
import com.vaadin.flow.component.datepicker.DatePicker; |
||||
import com.vaadin.flow.component.dialog.Dialog; |
||||
import com.vaadin.flow.component.dialog.GeneratedVaadinDialog.OpenedChangeEvent; |
||||
import com.vaadin.flow.component.orderedlayout.HorizontalLayout; |
||||
import com.vaadin.flow.component.textfield.TextField; |
||||
import com.vaadin.flow.component.timepicker.TimePicker; |
||||
import com.vaadin.flow.data.provider.Query; |
||||
|
||||
import de.kreth.invoice.data.Article; |
||||
import de.kreth.invoice.data.InvoiceItem; |
||||
|
||||
public class InvoiceItemDialog { |
||||
|
||||
private final Dialog dialog = new Dialog(); |
||||
private ComboBox<Article> article; |
||||
private DatePicker startDate; |
||||
private TimePicker startTime; |
||||
private TimePicker endTime; |
||||
private TextField participants; |
||||
private boolean closedWithOk; |
||||
private DialogCloseListener listener; |
||||
|
||||
public InvoiceItemDialog(InvoiceItem item, List<Article> articles, DialogCloseListener listener) { |
||||
this(articles, listener); |
||||
readFrom(item); |
||||
} |
||||
|
||||
public InvoiceItemDialog(List<Article> articles, DialogCloseListener listener) { |
||||
|
||||
this.listener = listener; |
||||
this.startDate = new DatePicker(LocalDate.now()); |
||||
startDate.setLabel("Datum"); |
||||
this.startTime = new TimePicker(LocalTime.of(17, 0)); |
||||
startTime.setLabel("Startzeit"); |
||||
this.endTime = new TimePicker(LocalTime.of(20, 0)); |
||||
this.participants = new TextField(); |
||||
this.participants.setLabel("Teilnehmer"); |
||||
article = new ComboBox<Article>("Artikel", articles); |
||||
article.setItemLabelGenerator(Article::getTitle); |
||||
|
||||
Button ok = new Button("Speichern", this::closeWithOk); |
||||
Button discard = new Button("Abbrechen", ev -> dialog.close()); |
||||
|
||||
dialog.add(article, startDate, startTime, endTime, participants, new HorizontalLayout(ok, discard)); |
||||
|
||||
dialog.addOpenedChangeListener(this::dialogCloseCalled); |
||||
} |
||||
|
||||
private void dialogCloseCalled(OpenedChangeEvent<Dialog> ev) { |
||||
if (!ev.isOpened()) { |
||||
listener.dialogClosed(this); |
||||
} |
||||
} |
||||
|
||||
public void setVisible() { |
||||
closedWithOk = false; |
||||
dialog.open(); |
||||
} |
||||
|
||||
private void closeWithOk(ClickEvent<Button> ev) { |
||||
closedWithOk = true; |
||||
dialog.close(); |
||||
} |
||||
|
||||
public boolean isClosedWithOk() { |
||||
return closedWithOk; |
||||
} |
||||
|
||||
public void readFrom(InvoiceItem item) { |
||||
|
||||
if (item.getArticle() != null) { |
||||
article.setValue(item.getArticle()); |
||||
} else if (article.getDataProvider().size(new Query<>()) == 1) { |
||||
article.getDataProvider().fetch(new Query<>()) |
||||
.findAny().ifPresent(article::setValue); |
||||
} |
||||
if (item.getStart() != null) { |
||||
startDate.setValue(item.getStart().toLocalDate()); |
||||
startTime.setValue(item.getStart().toLocalTime()); |
||||
} |
||||
if (item.getEnd() != null) { |
||||
endTime.setValue(item.getEnd().toLocalTime()); |
||||
} else if (item.getStart() != null) { |
||||
endTime.setValue(item.getStart().toLocalTime().plusHours(1)); |
||||
} |
||||
if (item.getParticipants() != null) { |
||||
this.participants.setValue(item.getParticipants()); |
||||
} |
||||
} |
||||
|
||||
public void writeTo(InvoiceItem item) { |
||||
if (!closedWithOk) { |
||||
throw new IllegalStateException("Dialog was not closed by OK Button, writing is not possible."); |
||||
} |
||||
item.setArticle(article.getValue()); |
||||
item.setChangeDate(LocalDateTime.now()); |
||||
if (item.getCreatedDate() == null) { |
||||
item.setCreatedDate(item.getChangeDate()); |
||||
} |
||||
item.setStart(LocalDateTime.of(startDate.getValue(), startTime.getValue())); |
||||
item.setEnd(LocalDateTime.of(startDate.getValue(), endTime.getValue())); |
||||
item.setParticipants(participants.getValue()); |
||||
|
||||
} |
||||
|
||||
public interface DialogCloseListener { |
||||
void dialogClosed(InvoiceItemDialog source); |
||||
} |
||||
} |
||||
@ -0,0 +1,177 @@ |
||||
package de.kreth.invoice.components; |
||||
|
||||
import java.math.BigDecimal; |
||||
import java.text.NumberFormat; |
||||
import java.time.LocalDate; |
||||
import java.time.format.DateTimeFormatter; |
||||
import java.time.format.FormatStyle; |
||||
import java.util.ArrayList; |
||||
import java.util.Collection; |
||||
import java.util.List; |
||||
|
||||
import com.vaadin.flow.component.grid.FooterRow; |
||||
import com.vaadin.flow.component.grid.FooterRow.FooterCell; |
||||
import com.vaadin.flow.component.grid.Grid; |
||||
import com.vaadin.flow.component.grid.GridSelectionModel; |
||||
import com.vaadin.flow.data.provider.DataChangeEvent; |
||||
import com.vaadin.flow.data.provider.DataProvider; |
||||
import com.vaadin.flow.data.provider.DataProviderListener; |
||||
import com.vaadin.flow.data.provider.ListDataProvider; |
||||
import com.vaadin.flow.data.renderer.LocalDateTimeRenderer; |
||||
import com.vaadin.flow.data.renderer.NumberRenderer; |
||||
|
||||
import de.kreth.invoice.data.InvoiceItem; |
||||
import de.kreth.invoice.persistence.InvoiceItemRepository; |
||||
|
||||
class InvoiceItemGrid extends Grid<InvoiceItem> { |
||||
|
||||
private static final long serialVersionUID = -8653320112619816426L; |
||||
|
||||
private final DateTimeFormatter ofLocalizedDateFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM); |
||||
|
||||
private FooterCell priceSumCell; |
||||
|
||||
private FooterCell countCell; |
||||
|
||||
private FooterCell dateSpan; |
||||
|
||||
private final List<InvoiceItem> items = new ArrayList<>(); |
||||
|
||||
private InvoiceItemRepository repository; |
||||
|
||||
public InvoiceItemGrid(InvoiceItemRepository invoiceItemRepository) { |
||||
|
||||
this.repository = invoiceItemRepository; |
||||
addClassName("bordered"); |
||||
Column<InvoiceItem> titleCol = addColumn(InvoiceItem::getTitle); |
||||
titleCol.setId("Article"); |
||||
titleCol.setHeader("Artikel"); |
||||
|
||||
Column<InvoiceItem> dateColumn = addColumn(new LocalDateTimeRenderer<>(InvoiceItem::getStart, |
||||
DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM))); |
||||
dateColumn.setId("Date"); |
||||
dateColumn.setHeader("Datum"); |
||||
|
||||
Column<InvoiceItem> startColumn = addColumn(new LocalDateTimeRenderer<>(InvoiceItem::getStart, |
||||
DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT))); |
||||
startColumn.setId("Start"); |
||||
startColumn.setHeader("Beginn"); |
||||
|
||||
Column<InvoiceItem> endColumn = addColumn(new LocalDateTimeRenderer<>(InvoiceItem::getEnd, |
||||
DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT))); |
||||
endColumn.setId("Ende"); |
||||
endColumn.setHeader("Ende"); |
||||
|
||||
Column<InvoiceItem> participantColumn = addColumn(InvoiceItem::getParticipants); |
||||
participantColumn.setHeader("Teilnehmer"); |
||||
|
||||
Column<InvoiceItem> sumPriceColumn = addColumn( |
||||
new NumberRenderer<>(InvoiceItem::getSumPrice, NumberFormat.getCurrencyInstance())); |
||||
sumPriceColumn.setId("price"); |
||||
sumPriceColumn.setHeader("Betrag"); |
||||
|
||||
// setSortOrder(GridSortOrder.asc(dateColumn).thenAsc(startColumn));
|
||||
FooterRow footer = appendFooterRow(); |
||||
|
||||
priceSumCell = footer.getCell(sumPriceColumn); |
||||
// dateSpan = footer.join(dateColumn, startColumn, endColumn);
|
||||
dateSpan = footer.getCell(dateColumn); |
||||
countCell = footer.getCell(titleCol); |
||||
|
||||
// addSelectionListener(this::selectionChanged);
|
||||
|
||||
items.addAll(repository.findByInvoiceIsNull()); |
||||
|
||||
ListDataProvider<InvoiceItem> dataProvider = new ListDataProvider<InvoiceItem>(items); |
||||
setDataProvider(dataProvider); |
||||
dataProvider.addDataProviderListener(new InnerDataProviderListener()); |
||||
} |
||||
|
||||
public void refreshData() { |
||||
items.clear(); |
||||
items.addAll(repository.findByInvoiceIsNull()); |
||||
} |
||||
|
||||
@Override |
||||
public GridSelectionModel<InvoiceItem> setSelectionMode(SelectionMode selectionMode) { |
||||
GridSelectionModel<InvoiceItem> setSelectionMode = super.setSelectionMode(selectionMode); |
||||
// setSelectionMode.addSelectionListener(this::selectionChanged);
|
||||
return setSelectionMode; |
||||
} |
||||
|
||||
// @SuppressWarnings("unchecked")
|
||||
// private void selectionChanged(SelectionEvent<T> event) {
|
||||
// if (event.getAllSelectedItems().isEmpty()) {
|
||||
// updateFooterWith(((ListDataProvider<T>) getDataProvider()).getItems());
|
||||
// } else {
|
||||
// updateFooterWith(event.getAllSelectedItems());
|
||||
// }
|
||||
// }
|
||||
|
||||
protected void internalSetDataProvider(DataProvider<InvoiceItem, ?> dataProvider) { |
||||
|
||||
if (!(dataProvider instanceof ListDataProvider)) { |
||||
throw new IllegalArgumentException("dataProvider must be an instance of ListDataProvider"); |
||||
} |
||||
// super.internalSetDataProvider(dataProvider);
|
||||
dataProvider.addDataProviderListener(new InnerDataProviderListener()); |
||||
updateFooterWith(((ListDataProvider<InvoiceItem>) getDataProvider()).getItems()); |
||||
} |
||||
|
||||
private void updateFooterWith(Collection<InvoiceItem> selected) { |
||||
BigDecimal priceSum = BigDecimal.ZERO; |
||||
LocalDate min = null; |
||||
LocalDate max = null; |
||||
|
||||
for (InvoiceItem t : selected) { |
||||
priceSum = priceSum.add(t.getSumPrice()); |
||||
min = getMin(min, t.getStart().toLocalDate()); |
||||
max = getMax(max, t.getEnd().toLocalDate()); |
||||
} |
||||
|
||||
priceSumCell.setText(NumberFormat.getCurrencyInstance().format(priceSum)); |
||||
if (min != null && max != null) { |
||||
dateSpan.setText(min.format(ofLocalizedDateFormatter) + " - " + max.format(ofLocalizedDateFormatter)); |
||||
} else { |
||||
dateSpan.setText(""); |
||||
} |
||||
countCell.setText("Anzahl: " + selected.size()); |
||||
} |
||||
|
||||
private LocalDate getMax(LocalDate max, LocalDate localDate) { |
||||
if (max == null) { |
||||
max = localDate; |
||||
} else { |
||||
if (max.isBefore(localDate)) { |
||||
max = localDate; |
||||
} |
||||
} |
||||
return max; |
||||
} |
||||
|
||||
private LocalDate getMin(LocalDate min, LocalDate localDate) { |
||||
if (min == null) { |
||||
min = localDate; |
||||
} else { |
||||
if (min.isAfter(localDate)) { |
||||
min = localDate; |
||||
} |
||||
} |
||||
return min; |
||||
} |
||||
|
||||
private class InnerDataProviderListener implements DataProviderListener<InvoiceItem> { |
||||
|
||||
private static final long serialVersionUID = -6094992880488082586L; |
||||
|
||||
@Override |
||||
public void onDataChange(DataChangeEvent<InvoiceItem> event) { |
||||
if (event.getSource() == getDataProvider()) { |
||||
@SuppressWarnings("unchecked") |
||||
ListDataProvider<InvoiceItem> provider = (ListDataProvider<InvoiceItem>) getDataProvider(); |
||||
updateFooterWith(provider.getItems()); |
||||
} |
||||
} |
||||
|
||||
} |
||||
} |
||||
@ -0,0 +1,53 @@ |
||||
package de.kreth.invoice.components; |
||||
|
||||
import java.util.List; |
||||
|
||||
import com.vaadin.flow.component.ClickEvent; |
||||
import com.vaadin.flow.component.button.Button; |
||||
import com.vaadin.flow.component.html.H3; |
||||
import com.vaadin.flow.component.orderedlayout.HorizontalLayout; |
||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout; |
||||
|
||||
import de.kreth.invoice.data.Article; |
||||
import de.kreth.invoice.data.InvoiceItem; |
||||
import de.kreth.invoice.data.User; |
||||
import de.kreth.invoice.persistence.ArticleRepository; |
||||
import de.kreth.invoice.persistence.InvoiceItemRepository; |
||||
|
||||
public class InvoiceItemOverviewComponent extends VerticalLayout { |
||||
|
||||
private static final long serialVersionUID = -4486121981960039L; |
||||
private final InvoiceItemGrid grid; |
||||
private final InvoiceItemRepository invoiceItemRepository; |
||||
private final ArticleRepository articleRepository; |
||||
private final User user; |
||||
|
||||
public InvoiceItemOverviewComponent(InvoiceItemRepository invoiceItemRepository, |
||||
ArticleRepository articleRepository, User user) { |
||||
this.invoiceItemRepository = invoiceItemRepository; |
||||
this.articleRepository = articleRepository; |
||||
this.user = user; |
||||
Button addButton = new Button("Hinzufügen", this::createNewitem); |
||||
add(new HorizontalLayout(new H3("Rechnungspositionen"), addButton)); |
||||
grid = new InvoiceItemGrid(invoiceItemRepository); |
||||
add(grid); |
||||
} |
||||
|
||||
public void refreshData() { |
||||
grid.refreshData(); |
||||
} |
||||
|
||||
private void createNewitem(ClickEvent<Button> ev) { |
||||
InvoiceItem item = new InvoiceItem(); |
||||
List<Article> articles = articleRepository.findByUserId(user.getId()); |
||||
InvoiceItemDialog dialog = new InvoiceItemDialog(articles, dlg -> { |
||||
if (dlg.isClosedWithOk()) { |
||||
dlg.writeTo(item); |
||||
invoiceItemRepository.save(item); |
||||
} |
||||
}); |
||||
dialog.readFrom(item); |
||||
dialog.setVisible(); |
||||
|
||||
} |
||||
} |
||||
@ -0,0 +1,18 @@ |
||||
package de.kreth.invoice.components; |
||||
|
||||
import com.vaadin.flow.component.html.H2; |
||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout; |
||||
|
||||
public class InvoiceOverviewComponent extends VerticalLayout { |
||||
|
||||
private static final long serialVersionUID = 1067257075519373200L; |
||||
private final InvoiceGrid grid; |
||||
|
||||
public InvoiceOverviewComponent() { |
||||
|
||||
addClassName("bordered"); |
||||
|
||||
this.grid = new InvoiceGrid(); |
||||
add(new H2("Rechnungen"), grid); |
||||
} |
||||
} |
||||
@ -0,0 +1,43 @@ |
||||
package de.kreth.invoice.config; |
||||
|
||||
import org.springframework.stereotype.Component; |
||||
|
||||
import com.vaadin.flow.component.UI; |
||||
import com.vaadin.flow.router.BeforeEnterEvent; |
||||
import com.vaadin.flow.server.ServiceInitEvent; |
||||
import com.vaadin.flow.server.VaadinServiceInitListener; |
||||
|
||||
import de.kreth.invoice.views.View; |
||||
|
||||
@Component |
||||
public class ConfigureUIServiceInitListener implements VaadinServiceInitListener { |
||||
|
||||
private static final long serialVersionUID = 1L; |
||||
|
||||
@Override |
||||
public void serviceInit(ServiceInitEvent event) { |
||||
event.getSource().addUIInitListener(uiEvent -> { |
||||
final UI ui = uiEvent.getUI(); |
||||
ui.addBeforeEnterListener(this::beforeEnter); |
||||
}); |
||||
|
||||
} |
||||
|
||||
/** |
||||
* Reroutes the user if (s)he is not authorized to access the view. |
||||
* |
||||
* @param event before navigation event with event details |
||||
*/ |
||||
private void beforeEnter(BeforeEnterEvent event) { |
||||
Class<?> navigationTarget = event.getNavigationTarget(); |
||||
|
||||
if (isSecureAndNotAuthentificated(navigationTarget)) { |
||||
event.rerouteTo(""); |
||||
} |
||||
} |
||||
|
||||
private boolean isSecureAndNotAuthentificated(Class<?> navigationTarget) { |
||||
boolean userLoggedIn = SecurityUtils.isUserLoggedIn(); |
||||
return View.class.equals(navigationTarget) && !userLoggedIn; |
||||
} |
||||
} |
||||
@ -0,0 +1,16 @@ |
||||
package de.kreth.invoice.config; |
||||
|
||||
import org.keycloak.adapters.KeycloakConfigResolver; |
||||
import org.keycloak.adapters.springboot.KeycloakSpringBootConfigResolver; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
|
||||
@Configuration |
||||
public class KeycloakConfigResolverLocal { |
||||
|
||||
@Bean |
||||
public KeycloakConfigResolver keyCloakConfigResolver() { |
||||
return new KeycloakSpringBootConfigResolver(); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,36 @@ |
||||
package de.kreth.invoice.config; |
||||
|
||||
import java.util.stream.Stream; |
||||
|
||||
import javax.servlet.http.HttpServletRequest; |
||||
|
||||
import org.springframework.security.authentication.AnonymousAuthenticationToken; |
||||
import org.springframework.security.core.Authentication; |
||||
import org.springframework.security.core.context.SecurityContextHolder; |
||||
|
||||
import com.vaadin.flow.shared.ApplicationConstants; |
||||
|
||||
public class SecurityUtils { |
||||
/** |
||||
* Tests if the request is an internal framework request. The test consists of |
||||
* checking if the request parameter is present and if its value is consistent |
||||
* with any of the request types know. |
||||
* |
||||
* @param request {@link HttpServletRequest} |
||||
* @return true if is an internal framework request. False otherwise. |
||||
*/ |
||||
static boolean isFrameworkInternalRequest(HttpServletRequest request) { |
||||
final String parameterValue = request.getParameter(ApplicationConstants.REQUEST_TYPE_PARAMETER); |
||||
|
||||
return parameterValue != null |
||||
&& Stream.of(com.vaadin.flow.server.HandlerHelper.RequestType.values()) |
||||
.anyMatch(r -> r.getIdentifier().equals(parameterValue)); |
||||
} |
||||
|
||||
static boolean isUserLoggedIn() { |
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); //
|
||||
return authentication != null //
|
||||
&& !(authentication instanceof AnonymousAuthenticationToken) //
|
||||
&& authentication.isAuthenticated(); //
|
||||
} |
||||
} |
||||
@ -0,0 +1,81 @@ |
||||
package de.kreth.invoice.config; |
||||
|
||||
import org.keycloak.adapters.KeycloakConfigResolver; |
||||
import org.keycloak.adapters.springboot.KeycloakSpringBootConfigResolver; |
||||
import org.keycloak.adapters.springsecurity.KeycloakConfiguration; |
||||
import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider; |
||||
import org.keycloak.adapters.springsecurity.client.KeycloakClientRequestFactory; |
||||
import org.keycloak.adapters.springsecurity.client.KeycloakRestTemplate; |
||||
import org.keycloak.adapters.springsecurity.config.KeycloakWebSecurityConfigurerAdapter; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Scope; |
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; |
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity; |
||||
import org.springframework.security.config.annotation.web.builders.WebSecurity; |
||||
import org.springframework.security.config.http.SessionCreationPolicy; |
||||
import org.springframework.security.core.authority.mapping.SimpleAuthorityMapper; |
||||
import org.springframework.security.core.session.SessionRegistryImpl; |
||||
import org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy; |
||||
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy; |
||||
|
||||
@KeycloakConfiguration |
||||
public class UiSecurityConfig extends KeycloakWebSecurityConfigurerAdapter { |
||||
@Autowired |
||||
private KeycloakClientRequestFactory factory; |
||||
|
||||
@Autowired |
||||
public void configureGlobal(AuthenticationManagerBuilder auth) { |
||||
KeycloakAuthenticationProvider keyCloakAuthProvider = keycloakAuthenticationProvider(); |
||||
keyCloakAuthProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper()); |
||||
auth.authenticationProvider(keyCloakAuthProvider); |
||||
} |
||||
|
||||
@Bean |
||||
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) |
||||
public KeycloakRestTemplate restTemplate() { |
||||
return new KeycloakRestTemplate(factory); |
||||
} |
||||
|
||||
@Bean |
||||
@Override |
||||
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() { |
||||
return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl()); |
||||
} |
||||
|
||||
@Override |
||||
public void configure(HttpSecurity http) throws Exception { |
||||
super.configure(http); |
||||
http.cors().disable() |
||||
.csrf().disable() |
||||
.anonymous().disable() |
||||
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED).and() |
||||
.authorizeRequests().requestMatchers(SecurityUtils::isFrameworkInternalRequest).permitAll() |
||||
.anyRequest().hasAnyRole("ROLE_trainer", "ROLE_admin"); |
||||
} |
||||
|
||||
@Override |
||||
public void configure(WebSecurity web) throws Exception { |
||||
web.ignoring().antMatchers( |
||||
// Vaadin Flow static resources //
|
||||
"/VAADIN/**", |
||||
// the standard favicon URI
|
||||
"/favicon.ico", |
||||
// the robots exclusion standard
|
||||
"/robots.txt", |
||||
// web application manifest //
|
||||
"/manifest.webmanifest", "/sw.js", "/offline-page.html", |
||||
// (development mode) static resources //
|
||||
"/frontend/**", |
||||
// (development mode) webjars //
|
||||
"/webjars/**", |
||||
// (production mode) static resources //
|
||||
"/frontend-es5/**", "/frontend-es6/**"); |
||||
} |
||||
|
||||
@Bean |
||||
public static KeycloakConfigResolver keycloakConfigResolver() { |
||||
return new KeycloakSpringBootConfigResolver(); |
||||
} |
||||
} |
||||
@ -0,0 +1,112 @@ |
||||
package de.kreth.invoice.data; |
||||
|
||||
import javax.persistence.Column; |
||||
import javax.persistence.DiscriminatorColumn; |
||||
import javax.persistence.DiscriminatorType; |
||||
import javax.persistence.Entity; |
||||
import javax.persistence.Inheritance; |
||||
import javax.persistence.InheritanceType; |
||||
import javax.persistence.Table; |
||||
|
||||
@Entity |
||||
@Table(name = "ADRESS") |
||||
@Inheritance(strategy = InheritanceType.SINGLE_TABLE) |
||||
@DiscriminatorColumn(name = "adress_type", discriminatorType = DiscriminatorType.STRING) |
||||
public class Adress extends BaseEntity { |
||||
|
||||
private static final long serialVersionUID = 8331249424121577387L; |
||||
@Column(nullable = false, length = 255) |
||||
private String adress1; |
||||
@Column(nullable = true, length = 255) |
||||
private String adress2; |
||||
@Column(nullable = true, length = 45) |
||||
private String zip; |
||||
@Column(nullable = true, length = 155) |
||||
private String city; |
||||
|
||||
public String getAdress1() { |
||||
return adress1; |
||||
} |
||||
|
||||
public void setAdress1(String adress1) { |
||||
this.adress1 = adress1; |
||||
} |
||||
|
||||
public String getAdress2() { |
||||
return adress2; |
||||
} |
||||
|
||||
public void setAdress2(String adress2) { |
||||
this.adress2 = adress2; |
||||
} |
||||
|
||||
public String getZip() { |
||||
return zip; |
||||
} |
||||
|
||||
public void setZip(String zip) { |
||||
this.zip = zip; |
||||
} |
||||
|
||||
public String getCity() { |
||||
return city; |
||||
} |
||||
|
||||
public void setCity(String city) { |
||||
this.city = city; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "Adress [adress1=" + adress1 + ", adress2=" + adress2 + ", zip=" |
||||
+ zip + ", city=" + city + "]"; |
||||
} |
||||
|
||||
public boolean isValid() { |
||||
return adress1 != null && !adress1.isBlank(); |
||||
} |
||||
|
||||
@Override |
||||
public int hashCode() { |
||||
final int prime = 31; |
||||
int result = 1; |
||||
result = prime * result + ((adress1 == null) ? 0 : adress1.hashCode()); |
||||
result = prime * result + ((adress2 == null) ? 0 : adress2.hashCode()); |
||||
result = prime * result + ((city == null) ? 0 : city.hashCode()); |
||||
result = prime * result + ((zip == null) ? 0 : zip.hashCode()); |
||||
return result; |
||||
} |
||||
|
||||
@Override |
||||
public boolean equals(Object obj) { |
||||
if (this == obj) |
||||
return true; |
||||
if (obj == null) |
||||
return false; |
||||
if (getClass() != obj.getClass()) |
||||
return false; |
||||
Adress other = (Adress) obj; |
||||
if (adress1 == null) { |
||||
if (other.adress1 != null) |
||||
return false; |
||||
} else if (!adress1.equals(other.adress1)) |
||||
return false; |
||||
if (adress2 == null) { |
||||
if (other.adress2 != null) |
||||
return false; |
||||
} else if (!adress2.equals(other.adress2)) |
||||
return false; |
||||
if (city == null) { |
||||
if (other.city != null) |
||||
return false; |
||||
} else if (!city.equals(other.city)) |
||||
return false; |
||||
if (zip == null) { |
||||
if (other.zip != null) |
||||
return false; |
||||
} else if (!zip.equals(other.zip)) |
||||
return false; |
||||
return true; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,104 @@ |
||||
package de.kreth.invoice.data; |
||||
|
||||
import java.math.BigDecimal; |
||||
|
||||
import javax.persistence.Column; |
||||
import javax.persistence.Entity; |
||||
import javax.persistence.Table; |
||||
|
||||
@Entity |
||||
@Table(name = "ARTICLE") |
||||
public class Article extends BaseEntity { |
||||
|
||||
private static final long serialVersionUID = 6777704420363536698L; |
||||
@Column(name = "price") |
||||
private BigDecimal pricePerHour; |
||||
@Column(nullable = false, length = 50) |
||||
private String title; |
||||
@Column(nullable = true, length = 255) |
||||
private String description; |
||||
|
||||
@Column(name = "user_id") |
||||
private int userId; |
||||
|
||||
public BigDecimal getPricePerHour() { |
||||
return pricePerHour; |
||||
} |
||||
|
||||
public void setPricePerHour(BigDecimal pricePerHour) { |
||||
this.pricePerHour = pricePerHour; |
||||
} |
||||
|
||||
public String getTitle() { |
||||
return title; |
||||
} |
||||
|
||||
public void setTitle(String title) { |
||||
this.title = title; |
||||
} |
||||
|
||||
public String getDescription() { |
||||
return description; |
||||
} |
||||
|
||||
public void setDescription(String description) { |
||||
this.description = description; |
||||
} |
||||
|
||||
public int getUserId() { |
||||
return userId; |
||||
} |
||||
|
||||
public void setUserId(int userId) { |
||||
this.userId = userId; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "Article [pricePerHour=" + pricePerHour + ", title=" + title |
||||
+ ", description=" + description + "]"; |
||||
} |
||||
|
||||
@Override |
||||
public int hashCode() { |
||||
final int prime = 31; |
||||
int result = 1; |
||||
result = prime * result |
||||
+ ((description == null) ? 0 : description.hashCode()); |
||||
result = prime * result |
||||
+ ((pricePerHour == null) ? 0 : pricePerHour.hashCode()); |
||||
result = prime * result + ((title == null) ? 0 : title.hashCode()); |
||||
result = prime * result + userId; |
||||
return result; |
||||
} |
||||
|
||||
@Override |
||||
public boolean equals(Object obj) { |
||||
if (this == obj) |
||||
return true; |
||||
if (obj == null) |
||||
return false; |
||||
if (getClass() != obj.getClass()) |
||||
return false; |
||||
Article other = (Article) obj; |
||||
if (description == null) { |
||||
if (other.description != null) |
||||
return false; |
||||
} else if (!description.equals(other.description)) |
||||
return false; |
||||
if (pricePerHour == null) { |
||||
if (other.pricePerHour != null) |
||||
return false; |
||||
} else if (!pricePerHour.equals(other.pricePerHour)) |
||||
return false; |
||||
if (title == null) { |
||||
if (other.title != null) |
||||
return false; |
||||
} else if (!title.equals(other.title)) |
||||
return false; |
||||
if (userId != other.userId) |
||||
return false; |
||||
return true; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,83 @@ |
||||
package de.kreth.invoice.data; |
||||
|
||||
import javax.persistence.Column; |
||||
import javax.persistence.DiscriminatorColumn; |
||||
import javax.persistence.DiscriminatorType; |
||||
import javax.persistence.Entity; |
||||
import javax.persistence.Inheritance; |
||||
import javax.persistence.InheritanceType; |
||||
import javax.persistence.Table; |
||||
|
||||
@Entity |
||||
@Table(name = "BANKING_CONNECTION") |
||||
@Inheritance(strategy = InheritanceType.SINGLE_TABLE) |
||||
@DiscriminatorColumn(name = "owner_type", discriminatorType = DiscriminatorType.STRING) |
||||
public class BankingConnection extends BaseEntity { |
||||
|
||||
private static final long serialVersionUID = -6168631092559375156L; |
||||
@Column(nullable = false, length = 150) |
||||
private String bankName; |
||||
@Column(nullable = false, length = 150) |
||||
private String iban; |
||||
@Column(nullable = true, length = 150) |
||||
private String bic; |
||||
|
||||
public String getBankName() { |
||||
return bankName; |
||||
} |
||||
|
||||
public void setBankName(String bankName) { |
||||
this.bankName = bankName; |
||||
} |
||||
|
||||
public String getIban() { |
||||
return iban; |
||||
} |
||||
|
||||
public void setIban(String iban) { |
||||
this.iban = iban; |
||||
} |
||||
|
||||
public String getBic() { |
||||
return bic; |
||||
} |
||||
|
||||
public void setBic(String bic) { |
||||
this.bic = bic; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return iban; |
||||
} |
||||
|
||||
public boolean isValid() { |
||||
return iban != null; |
||||
} |
||||
|
||||
@Override |
||||
public int hashCode() { |
||||
final int prime = 31; |
||||
int result = 1; |
||||
result = prime * result + ((iban == null) ? 0 : iban.hashCode()); |
||||
return result; |
||||
} |
||||
|
||||
@Override |
||||
public boolean equals(Object obj) { |
||||
if (this == obj) |
||||
return true; |
||||
if (obj == null) |
||||
return false; |
||||
if (getClass() != obj.getClass()) |
||||
return false; |
||||
BankingConnection other = (BankingConnection) obj; |
||||
if (iban == null) { |
||||
if (other.iban != null) |
||||
return false; |
||||
} else if (!iban.equals(other.iban)) |
||||
return false; |
||||
return true; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,90 @@ |
||||
package de.kreth.invoice.data; |
||||
|
||||
import java.io.Serializable; |
||||
import java.time.LocalDateTime; |
||||
|
||||
import javax.persistence.Column; |
||||
import javax.persistence.GeneratedValue; |
||||
import javax.persistence.GenerationType; |
||||
import javax.persistence.Id; |
||||
import javax.persistence.MappedSuperclass; |
||||
import javax.persistence.PrePersist; |
||||
|
||||
@MappedSuperclass |
||||
public class BaseEntity implements Serializable { |
||||
|
||||
private static final long serialVersionUID = 6953593432069408729L; |
||||
|
||||
@Id |
||||
@GeneratedValue(strategy = GenerationType.IDENTITY) |
||||
private int id; |
||||
@Column(name = "created") |
||||
private LocalDateTime createdDate; |
||||
@Column(name = "updated") |
||||
private LocalDateTime changeDate; |
||||
|
||||
public int getId() { |
||||
return id; |
||||
} |
||||
|
||||
public void setId(int id) { |
||||
this.id = id; |
||||
} |
||||
|
||||
public LocalDateTime getCreatedDate() { |
||||
return createdDate; |
||||
} |
||||
|
||||
public void setCreatedDate(LocalDateTime createdDate) { |
||||
this.createdDate = createdDate; |
||||
} |
||||
|
||||
public LocalDateTime getChangeDate() { |
||||
return changeDate; |
||||
} |
||||
|
||||
public void setChangeDate(LocalDateTime changeDate) { |
||||
this.changeDate = changeDate; |
||||
} |
||||
|
||||
@PrePersist |
||||
void prePersist() { |
||||
if (this.createdDate == null) { |
||||
LocalDateTime now = LocalDateTime.now(); |
||||
this.createdDate = now; |
||||
this.changeDate = now; |
||||
} else { |
||||
this.changeDate = LocalDateTime.now(); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public int hashCode() { |
||||
final int prime = 31; |
||||
int result = 1; |
||||
result = prime * result |
||||
+ ((createdDate == null) ? 0 : createdDate.hashCode()); |
||||
result = prime * result + id; |
||||
return result; |
||||
} |
||||
|
||||
@Override |
||||
public boolean equals(Object obj) { |
||||
if (this == obj) |
||||
return true; |
||||
if (obj == null) |
||||
return false; |
||||
if (getClass() != obj.getClass()) |
||||
return false; |
||||
BaseEntity other = (BaseEntity) obj; |
||||
if (createdDate == null) { |
||||
if (other.createdDate != null) |
||||
return false; |
||||
} else if (!createdDate.equals(other.createdDate)) |
||||
return false; |
||||
if (id != other.id) |
||||
return false; |
||||
return true; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,77 @@ |
||||
package de.kreth.invoice.data; |
||||
|
||||
import java.math.BigDecimal; |
||||
import java.time.LocalDateTime; |
||||
import java.util.ArrayList; |
||||
import java.util.Collection; |
||||
import java.util.List; |
||||
|
||||
import javax.persistence.Column; |
||||
import javax.persistence.Entity; |
||||
import javax.persistence.OneToMany; |
||||
import javax.persistence.Table; |
||||
|
||||
@Entity |
||||
@Table(name = "INVOICE") |
||||
public class Invoice extends BaseEntity { |
||||
|
||||
private static final long serialVersionUID = 736651954892271409L; |
||||
|
||||
@Column(name = "invoiceid", nullable = false, length = 150) |
||||
private String invoiceId; |
||||
private LocalDateTime invoiceDate; |
||||
|
||||
@OneToMany(mappedBy = "invoice") |
||||
private List<InvoiceItem> items; |
||||
|
||||
// @ManyToOne(cascade = CascadeType.REFRESH)
|
||||
// @JoinColumn(name = "user_id", nullable = false, updatable = false)
|
||||
private User user; |
||||
|
||||
public String getInvoiceId() { |
||||
return invoiceId; |
||||
} |
||||
|
||||
public void setInvoiceId(String invoiceId) { |
||||
this.invoiceId = invoiceId; |
||||
} |
||||
|
||||
public LocalDateTime getInvoiceDate() { |
||||
return invoiceDate; |
||||
} |
||||
|
||||
public void setInvoiceDate(LocalDateTime invoiceDate) { |
||||
this.invoiceDate = invoiceDate; |
||||
} |
||||
|
||||
public List<InvoiceItem> getItems() { |
||||
return items; |
||||
} |
||||
|
||||
public void setItems(Collection<InvoiceItem> items) { |
||||
this.items = new ArrayList<>(items); |
||||
} |
||||
|
||||
public User getUser() { |
||||
return user; |
||||
} |
||||
|
||||
public void setUser(User user) { |
||||
this.user = user; |
||||
} |
||||
|
||||
public BigDecimal getSum() { |
||||
if (items == null || items.isEmpty()) { |
||||
return BigDecimal.ZERO; |
||||
} |
||||
return items.stream().map(i -> i.getSumPrice()).reduce(BigDecimal.ZERO, |
||||
BigDecimal::add); |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "Invoice [invoiceId=" + invoiceId + ", itemscount=" |
||||
+ items.size() + ", sum=" + getSum() + "]"; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,147 @@ |
||||
package de.kreth.invoice.data; |
||||
|
||||
import java.math.BigDecimal; |
||||
import java.math.RoundingMode; |
||||
import java.time.LocalDateTime; |
||||
import java.time.temporal.ChronoUnit; |
||||
|
||||
import javax.persistence.Column; |
||||
import javax.persistence.Entity; |
||||
import javax.persistence.JoinColumn; |
||||
import javax.persistence.ManyToOne; |
||||
import javax.persistence.Table; |
||||
|
||||
@Entity |
||||
@Table(name = "INVOICE_ITEM") |
||||
public class InvoiceItem extends BaseEntity { |
||||
|
||||
private static final long serialVersionUID = 3142997452876778041L; |
||||
|
||||
private LocalDateTime start; |
||||
private LocalDateTime end; |
||||
@Column(nullable = true, length = 15) |
||||
private String participants; |
||||
|
||||
@ManyToOne(optional = false) |
||||
@JoinColumn(name = "article_id", nullable = false, updatable = false) |
||||
private Article article; |
||||
|
||||
@ManyToOne(optional = true) |
||||
@JoinColumn(name = "invoice_id", nullable = true, updatable = true) |
||||
private Invoice invoice; |
||||
|
||||
@Column(name = "sum_price") |
||||
private BigDecimal sumPrice; |
||||
|
||||
public String getTitle() { |
||||
return getArticle().getTitle(); |
||||
} |
||||
|
||||
public LocalDateTime getStart() { |
||||
return start; |
||||
} |
||||
|
||||
public void setStart(LocalDateTime start) { |
||||
this.start = start; |
||||
getSumPrice(); |
||||
} |
||||
|
||||
public LocalDateTime getEnd() { |
||||
return end; |
||||
} |
||||
|
||||
public void setEnd(LocalDateTime end) { |
||||
this.end = end; |
||||
getSumPrice(); |
||||
} |
||||
|
||||
public String getParticipants() { |
||||
return participants; |
||||
} |
||||
|
||||
public void setParticipants(String participants) { |
||||
this.participants = participants; |
||||
} |
||||
|
||||
public Article getArticle() { |
||||
return article; |
||||
} |
||||
|
||||
public void setArticle(Article article) { |
||||
this.article = article; |
||||
getSumPrice(); |
||||
} |
||||
|
||||
public BigDecimal getSumPrice() { |
||||
if (article == null || start == null || end == null) { |
||||
sumPrice = null; |
||||
return null; |
||||
} |
||||
|
||||
sumPrice = BigDecimal.valueOf(getDurationInMinutes()) |
||||
.setScale(2, RoundingMode.HALF_UP) |
||||
.divide(BigDecimal.valueOf(60), RoundingMode.HALF_UP) |
||||
.multiply(article.getPricePerHour()) |
||||
.setScale(2, RoundingMode.HALF_UP); |
||||
return sumPrice; |
||||
} |
||||
|
||||
public Invoice getInvoice() { |
||||
return invoice; |
||||
} |
||||
|
||||
public void setInvoice(Invoice invoice) { |
||||
this.invoice = invoice; |
||||
} |
||||
|
||||
public long getDurationInMinutes() { |
||||
if (start == null || end == null) { |
||||
return -1L; |
||||
} |
||||
return start.until(end, ChronoUnit.MINUTES); |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "InvoiceItem [id=" + getId() + ", start=" + start + ", end=" |
||||
+ end + ", article=" + article + "]"; |
||||
} |
||||
|
||||
@Override |
||||
public int hashCode() { |
||||
final int prime = 31; |
||||
int result = 1; |
||||
result = prime * result + ((article == null) ? 0 : article.hashCode()); |
||||
result = prime * result + ((end == null) ? 0 : end.hashCode()); |
||||
result = prime * result + ((start == null) ? 0 : start.hashCode()); |
||||
return result; |
||||
} |
||||
|
||||
@Override |
||||
public boolean equals(Object obj) { |
||||
if (this == obj) |
||||
return true; |
||||
if (obj == null) |
||||
return false; |
||||
if (getClass() != obj.getClass()) |
||||
return false; |
||||
InvoiceItem other = (InvoiceItem) obj; |
||||
if (article == null) { |
||||
if (other.article != null) |
||||
return false; |
||||
} else if (!article.equals(other.article)) |
||||
return false; |
||||
if (end == null) { |
||||
if (other.end != null) |
||||
return false; |
||||
} else if (!end.equals(other.end)) |
||||
return false; |
||||
if (start == null) { |
||||
if (other.start != null) |
||||
return false; |
||||
} else if (!start.equals(other.start)) |
||||
return false; |
||||
return true; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,58 @@ |
||||
package de.kreth.invoice.data; |
||||
|
||||
import java.util.Objects; |
||||
|
||||
import javax.persistence.Column; |
||||
import javax.persistence.Entity; |
||||
import javax.persistence.Inheritance; |
||||
import javax.persistence.InheritanceType; |
||||
import javax.persistence.Table; |
||||
|
||||
import org.keycloak.representations.AccessToken; |
||||
|
||||
@Entity |
||||
@Table(name = "USER") |
||||
@Inheritance(strategy = InheritanceType.SINGLE_TABLE) |
||||
public class User extends BaseEntity { |
||||
|
||||
private static final long serialVersionUID = -2458030336216327580L; |
||||
private String principalId; |
||||
private String givenName; |
||||
private String familyName; |
||||
private String email; |
||||
|
||||
@Column(name = "PRINCIPAL_ID", nullable = false, length = 40, updatable = false, insertable = true, unique = true) |
||||
public String getPrincipalId() { |
||||
return principalId; |
||||
} |
||||
|
||||
public void setPrincipal(final AccessToken token) { |
||||
final AccessToken accessToken = Objects.requireNonNull(token); |
||||
if (this.principalId != null) { |
||||
if (!principalId.contentEquals(accessToken.getSubject())) { |
||||
throw new IllegalArgumentException("Non updateable value principalId does not match: this.principalId=" |
||||
+ this.principalId + ", token.principalId=" + accessToken.getSubject()); |
||||
} |
||||
} |
||||
principalId = accessToken.getSubject(); |
||||
givenName = accessToken.getGivenName(); |
||||
familyName = accessToken.getFamilyName(); |
||||
email = accessToken.getEmail(); |
||||
} |
||||
|
||||
@Column(nullable = false, length = 50, updatable = false, insertable = true) |
||||
public String getGivenName() { |
||||
return givenName; |
||||
} |
||||
|
||||
@Column(nullable = false, length = 50, updatable = false, insertable = true) |
||||
public String getFamilyName() { |
||||
return familyName; |
||||
} |
||||
|
||||
@Column(nullable = false, length = 100, updatable = false, insertable = true) |
||||
public String getEmail() { |
||||
return email; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,24 @@ |
||||
package de.kreth.invoice.data; |
||||
|
||||
import javax.persistence.Entity; |
||||
import javax.persistence.FetchType; |
||||
import javax.persistence.OneToOne; |
||||
import javax.persistence.PrimaryKeyJoinColumn; |
||||
|
||||
@Entity |
||||
public class UserAdress extends Adress { |
||||
|
||||
private static final long serialVersionUID = -8104370538500175340L; |
||||
@OneToOne(fetch = FetchType.LAZY) |
||||
@PrimaryKeyJoinColumn |
||||
private User user; |
||||
|
||||
public User getUser() { |
||||
return user; |
||||
} |
||||
|
||||
public void setUser(User user) { |
||||
this.user = user; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,32 @@ |
||||
package de.kreth.invoice.data; |
||||
|
||||
import javax.persistence.Entity; |
||||
import javax.persistence.FetchType; |
||||
import javax.persistence.OneToOne; |
||||
import javax.persistence.PrimaryKeyJoinColumn; |
||||
|
||||
@Entity |
||||
public class UserBank extends BankingConnection { |
||||
|
||||
private static final long serialVersionUID = -7356424394007978241L; |
||||
@OneToOne(fetch = FetchType.LAZY) |
||||
@PrimaryKeyJoinColumn |
||||
private User user; |
||||
|
||||
public User getUser() { |
||||
return user; |
||||
} |
||||
|
||||
public void setUser(User user) { |
||||
this.user = user; |
||||
// if (user.getBank() == null) {
|
||||
// user.setBank(this);
|
||||
// } else {
|
||||
// if (user.getBank().equals(this) == false) {
|
||||
// throw new IllegalArgumentException(
|
||||
// "User already set, but other than this.");
|
||||
// }
|
||||
// }
|
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,5 @@ |
||||
/** |
||||
* @author markus |
||||
* |
||||
*/ |
||||
package de.kreth.invoice.data; |
||||
@ -0,0 +1,12 @@ |
||||
package de.kreth.invoice.persistence; |
||||
|
||||
import java.util.List; |
||||
|
||||
import org.springframework.data.repository.CrudRepository; |
||||
|
||||
import de.kreth.invoice.data.Article; |
||||
|
||||
public interface ArticleRepository extends CrudRepository<Article, Integer> { |
||||
|
||||
List<Article> findByUserId(int userId); |
||||
} |
||||
@ -0,0 +1,13 @@ |
||||
package de.kreth.invoice.persistence; |
||||
|
||||
import java.util.List; |
||||
|
||||
import org.springframework.data.repository.CrudRepository; |
||||
|
||||
import de.kreth.invoice.data.InvoiceItem; |
||||
|
||||
public interface InvoiceItemRepository extends CrudRepository<InvoiceItem, Integer> { |
||||
|
||||
List<InvoiceItem> findByInvoiceIsNull(); |
||||
|
||||
} |
||||
@ -0,0 +1,11 @@ |
||||
package de.kreth.invoice.persistence; |
||||
|
||||
import org.springframework.data.repository.CrudRepository; |
||||
|
||||
import de.kreth.invoice.data.User; |
||||
import de.kreth.invoice.data.UserAdress; |
||||
|
||||
public interface UserAdressRepository extends CrudRepository<UserAdress, Integer> { |
||||
|
||||
UserAdress findByUser(User user); |
||||
} |
||||
@ -0,0 +1,11 @@ |
||||
package de.kreth.invoice.persistence; |
||||
|
||||
import org.springframework.data.repository.CrudRepository; |
||||
|
||||
import de.kreth.invoice.data.User; |
||||
import de.kreth.invoice.data.UserBank; |
||||
|
||||
public interface UserBankRepository extends CrudRepository<UserBank, Integer> { |
||||
|
||||
UserBank findByUser(User user); |
||||
} |
||||
@ -0,0 +1,10 @@ |
||||
package de.kreth.invoice.persistence; |
||||
|
||||
import org.springframework.data.repository.CrudRepository; |
||||
|
||||
import de.kreth.invoice.data.User; |
||||
|
||||
public interface UserRepository extends CrudRepository<User, Long> { |
||||
|
||||
User findByPrincipalId(String tokenSubject); |
||||
} |
||||
@ -0,0 +1,55 @@ |
||||
package de.kreth.invoice.security; |
||||
|
||||
import org.keycloak.KeycloakPrincipal; |
||||
import org.keycloak.KeycloakSecurityContext; |
||||
import org.keycloak.representations.AccessToken; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.security.core.Authentication; |
||||
import org.springframework.security.core.context.SecurityContextHolder; |
||||
import org.springframework.stereotype.Component; |
||||
|
||||
import de.kreth.invoice.data.User; |
||||
import de.kreth.invoice.persistence.UserRepository; |
||||
|
||||
@Component |
||||
public class UserManager { |
||||
|
||||
private UserRepository userRepository; |
||||
|
||||
@Autowired |
||||
public void setUserRepository(UserRepository userRepository) { |
||||
this.userRepository = userRepository; |
||||
} |
||||
|
||||
private AccessToken getAccessToken() { |
||||
Authentication authentication = getAuthentication(); |
||||
KeycloakPrincipal<?> principal = (KeycloakPrincipal<?>) authentication.getPrincipal(); |
||||
KeycloakSecurityContext context = principal.getKeycloakSecurityContext(); |
||||
return context.getToken(); |
||||
} |
||||
|
||||
public User getLoggedInUser() { |
||||
AccessToken accessToken = getAccessToken(); |
||||
if (accessToken != null) { |
||||
return userRepository.findByPrincipalId(accessToken.getSubject()); |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
public User save(User entity) { |
||||
return userRepository.save(entity); |
||||
} |
||||
|
||||
private Authentication getAuthentication() { |
||||
|
||||
return SecurityContextHolder.getContext().getAuthentication(); |
||||
} |
||||
|
||||
public User create() { |
||||
User user = new User(); |
||||
AccessToken accessToken = getAccessToken(); |
||||
user.setPrincipal(accessToken); |
||||
return user; |
||||
|
||||
} |
||||
} |
||||
@ -0,0 +1,144 @@ |
||||
package de.kreth.invoice.views; |
||||
|
||||
import java.math.BigDecimal; |
||||
import java.time.LocalDateTime; |
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.security.access.prepost.PreAuthorize; |
||||
|
||||
import com.vaadin.flow.component.ClickEvent; |
||||
import com.vaadin.flow.component.Text; |
||||
import com.vaadin.flow.component.button.Button; |
||||
import com.vaadin.flow.component.contextmenu.ContextMenu; |
||||
import com.vaadin.flow.component.contextmenu.MenuItem; |
||||
import com.vaadin.flow.component.dialog.Dialog; |
||||
import com.vaadin.flow.component.html.H1; |
||||
import com.vaadin.flow.component.html.Label; |
||||
import com.vaadin.flow.component.icon.VaadinIcon; |
||||
import com.vaadin.flow.component.orderedlayout.HorizontalLayout; |
||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout; |
||||
import com.vaadin.flow.router.BeforeEnterEvent; |
||||
import com.vaadin.flow.router.BeforeEnterObserver; |
||||
import com.vaadin.flow.router.PageTitle; |
||||
import com.vaadin.flow.router.Route; |
||||
|
||||
import de.kreth.invoice.components.InvoiceItemOverviewComponent; |
||||
import de.kreth.invoice.data.Article; |
||||
import de.kreth.invoice.data.User; |
||||
import de.kreth.invoice.data.UserAdress; |
||||
import de.kreth.invoice.data.UserBank; |
||||
import de.kreth.invoice.persistence.ArticleRepository; |
||||
import de.kreth.invoice.persistence.InvoiceItemRepository; |
||||
import de.kreth.invoice.persistence.UserAdressRepository; |
||||
import de.kreth.invoice.persistence.UserBankRepository; |
||||
import de.kreth.invoice.security.UserManager; |
||||
|
||||
@PageTitle("") |
||||
@Route(value = "") |
||||
@PreAuthorize("hasRole('ROLE_TRAINER')") |
||||
public class View extends VerticalLayout implements BeforeEnterObserver { |
||||
|
||||
private static final long serialVersionUID = 1L; |
||||
private final UserManager userRepository; |
||||
private final UserBankRepository bankRepository; |
||||
private final UserAdressRepository adressRepository; |
||||
private final InvoiceItemRepository invoiceItemRepository; |
||||
private final ArticleRepository articleRepository; |
||||
private InvoiceItemOverviewComponent invoiceItems; |
||||
private User user; |
||||
|
||||
public View(@Autowired UserManager userRepository, @Autowired UserBankRepository userBankRepository, |
||||
@Autowired UserAdressRepository adressRepository, |
||||
@Autowired InvoiceItemRepository invoiceItemRepository, |
||||
@Autowired ArticleRepository articleRepository) { |
||||
this.userRepository = userRepository; |
||||
this.bankRepository = userBankRepository; |
||||
this.adressRepository = adressRepository; |
||||
this.invoiceItemRepository = invoiceItemRepository; |
||||
this.articleRepository = articleRepository; |
||||
} |
||||
|
||||
@Override |
||||
public void beforeEnter(BeforeEnterEvent event) { |
||||
|
||||
user = userRepository.getLoggedInUser(); |
||||
if (user == null) { |
||||
user = userRepository.create(); |
||||
} |
||||
|
||||
// UserBank bank = bankRepository.findByUser(user);
|
||||
// UserAdress adress = adressRepository.findByUser(user);
|
||||
|
||||
// if (isBankOrAdressInvalid(bank, adress)) {
|
||||
// event.getUI().navigate(LoginDataView.class);
|
||||
// } else {
|
||||
// checkArticle();
|
||||
// createUi();
|
||||
// }
|
||||
|
||||
checkArticle(); |
||||
createUi(); |
||||
} |
||||
|
||||
private void checkArticle() { |
||||
if (articleRepository.count() <= 0) { |
||||
|
||||
Article article = new Article(); |
||||
LocalDateTime now = LocalDateTime.now(); |
||||
article.setChangeDate(now); |
||||
article.setCreatedDate(now); |
||||
article.setDescription("Dummy Übungsleiter"); |
||||
article.setTitle("Dummy"); |
||||
article.setPricePerHour(BigDecimal.valueOf(7.5)); |
||||
article.setUserId(user.getId()); |
||||
articleRepository.save(article); |
||||
} |
||||
} |
||||
|
||||
private boolean isBankOrAdressInvalid(UserBank bank, UserAdress adress) { |
||||
return bank == null || adress == null || !bank.isValid() || !adress.isValid(); |
||||
} |
||||
|
||||
private void createUi() { |
||||
|
||||
Button menuButton = new Button(VaadinIcon.MENU.create()); |
||||
menuButton.addClickListener(this::onMenuButtonClick); |
||||
|
||||
HorizontalLayout l = new HorizontalLayout(menuButton, new H1("Übungsleiter Abrechnung")); |
||||
l.setAlignItems(Alignment.CENTER); |
||||
add(l); |
||||
|
||||
Label name = new Label(user.getGivenName() + " " + user.getFamilyName()); |
||||
Label email = new Label(user.getEmail()); |
||||
add(name, email); |
||||
|
||||
invoiceItems = new InvoiceItemOverviewComponent(invoiceItemRepository, articleRepository, user); |
||||
add(invoiceItems); |
||||
|
||||
} |
||||
|
||||
public void onMenuButtonClick(ClickEvent<Button> event) { |
||||
ContextMenu menu = new ContextMenu(); |
||||
menu.setTarget(event.getSource()); |
||||
menu.addItem("Einstellungen", this::onSettingsButtonClick); |
||||
menu.addItem("Über", this::onAboutButtonClick); |
||||
menu.setVisible(true); |
||||
} |
||||
|
||||
public void onSettingsButtonClick(ClickEvent<MenuItem> event) { |
||||
Dialog dlg = new Dialog(); |
||||
dlg.add(new H1("Einstellungen")); |
||||
dlg.add(new Text("Einstellugen für diese App. Noch nicht implementiert.")); |
||||
dlg.open(); |
||||
} |
||||
|
||||
public void onAboutButtonClick(ClickEvent<MenuItem> event) { |
||||
|
||||
Dialog dlg = new Dialog(); |
||||
dlg.add(new H1("Personeneditor")); |
||||
dlg.add(new Text( |
||||
"Personeneditor ist eine App zur Erfassung und Änderung von Personen im Trampolin des MTV Groß-Buchholz.")); |
||||
dlg.open(); |
||||
} |
||||
|
||||
} |
||||
|
After Width: | Height: | Size: 2.4 KiB |
@ -0,0 +1,9 @@ |
||||
server.port=${PORT:8080} |
||||
logging.level.org.atmosphere = warn |
||||
spring.mustache.check-template-location = false |
||||
|
||||
# Launch the default browser when starting the application in development mode |
||||
vaadin.launch-browser=true |
||||
# To improve the performance during development. |
||||
# For more information https://vaadin.com/docs/flow/spring/tutorial-spring-configuration.html#special-configuration-parameters |
||||
vaadin.whitelisted-packages = com.vaadin,org.vaadin,dev.hilla,de.kreth.invoice |
||||
@ -0,0 +1,6 @@ |
||||
_ _ _ _ |
||||
| |_ _ __ __ _ (_) _ __ ___ _ __ (_) _ __ __ __ ___ (_) ___ ___ |
||||
| __|| '__| / _` || || '_ \ / _ \| '__|| || '_ \ \ \ / / / _ \ | | / __| / _ \ |
||||
| |_ | | | (_| || || | | || __/| | | || | | | \ V / | (_) || || (__ | __/ |
||||
\__||_| \__,_||_||_| |_| \___||_| |_||_| |_| \_/ \___/ |_| \___| \___| |
||||
|
||||
@ -0,0 +1,34 @@ |
||||
// This TypeScript configuration file is generated by vaadin-maven-plugin. |
||||
// This is needed for TypeScript compiler to compile your TypeScript code in the project. |
||||
// It is recommended to commit this file to the VCS. |
||||
// You might want to change the configurations to fit your preferences |
||||
// For more information about the configurations, please refer to http://www.typescriptlang.org/docs/handbook/tsconfig-json.html |
||||
{ |
||||
"compilerOptions": { |
||||
"sourceMap": true, |
||||
"inlineSources": true, |
||||
"module": "esNext", |
||||
"target": "es2019", |
||||
"moduleResolution": "node", |
||||
"strict": true, |
||||
"noFallthroughCasesInSwitch": true, |
||||
"noImplicitReturns": true, |
||||
"noImplicitAny": true, |
||||
"noImplicitThis": true, |
||||
"noUnusedLocals": false, |
||||
"noUnusedParameters": false, |
||||
"experimentalDecorators": true, |
||||
"baseUrl": "frontend", |
||||
"paths": { |
||||
"Frontend/*": [ |
||||
"*" |
||||
] |
||||
} |
||||
}, |
||||
"include": [ |
||||
"frontend/**/*.ts", |
||||
"frontend/index.js", |
||||
"types.d.ts" |
||||
], |
||||
"exclude": [] |
||||
} |
||||
@ -0,0 +1,5 @@ |
||||
declare module '*.css' { |
||||
import { CSSResultGroup } from 'lit'; |
||||
const content: CSSResultGroup; |
||||
export default content; |
||||
} |
||||
@ -0,0 +1,37 @@ |
||||
/** |
||||
* This file has been autogenerated as it didn't exist or was made for an older incompatible version. |
||||
* This file can be used for manual configuration will not be modified if the flowDefaults constant exists. |
||||
*/ |
||||
const merge = require('webpack-merge'); |
||||
const flowDefaults = require('./webpack.generated.js'); |
||||
|
||||
module.exports = merge(flowDefaults, { |
||||
|
||||
}); |
||||
|
||||
/** |
||||
* This file can be used to configure the flow plugin defaults. |
||||
* <code> |
||||
* // Add a custom plugin
|
||||
* flowDefaults.plugins.push(new MyPlugin()); |
||||
* |
||||
* // Update the rules to also transpile `.mjs` files
|
||||
* if (!flowDefaults.module.rules[0].test) { |
||||
* throw "Unexpected structure in generated webpack config"; |
||||
* } |
||||
* flowDefaults.module.rules[0].test = /\.m?js$/ |
||||
* |
||||
* // Include a custom JS in the entry point in addition to generated-flow-imports.js
|
||||
* if (typeof flowDefaults.entry.index != "string") { |
||||
* throw "Unexpected structure in generated webpack config"; |
||||
* } |
||||
* flowDefaults.entry.index = [flowDefaults.entry.index, "myCustomFile.js"]; |
||||
* </code> |
||||
* or add new configuration in the merge block. |
||||
* <code> |
||||
* module.exports = merge(flowDefaults, { |
||||
* mode: 'development', |
||||
* devtool: 'inline-source-map' |
||||
* }); |
||||
* </code> |
||||
*/ |
||||
@ -0,0 +1,379 @@ |
||||
/** |
||||
* NOTICE: this is an auto-generated file |
||||
* |
||||
* This file has been generated by the `flow:prepare-frontend` maven goal. |
||||
* This file will be overwritten on every run. Any custom changes should be made to webpack.config.js |
||||
*/ |
||||
const fs = require('fs'); |
||||
const HtmlWebpackPlugin = require('html-webpack-plugin'); |
||||
const CompressionPlugin = require('compression-webpack-plugin'); |
||||
const { InjectManifest } = require('workbox-webpack-plugin'); |
||||
const { DefinePlugin } = require('webpack'); |
||||
const ExtraWatchWebpackPlugin = require('extra-watch-webpack-plugin'); |
||||
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin'); |
||||
|
||||
const path = require('path'); |
||||
|
||||
// this matches /themes/my-theme/ and is used to check css url handling and file path build.
|
||||
const themePartRegex = /(\\|\/)themes\1[\s\S]*?\1/; |
||||
|
||||
// the folder of app resources:
|
||||
// - flow templates for classic Flow
|
||||
// - client code with index.html and index.[ts/js] for CCDM
|
||||
const frontendFolder = path.resolve(__dirname, 'frontend'); |
||||
const frontendGeneratedFolder = path.resolve(__dirname, 'frontend/generated'); |
||||
const fileNameOfTheFlowGeneratedMainEntryPoint = path.resolve(__dirname, 'target/frontend/generated-flow-imports.js'); |
||||
const mavenOutputFolderForFlowBundledFiles = path.resolve(__dirname, 'target/classes/META-INF/VAADIN/webapp'); |
||||
const mavenOutputFolderForResourceFiles = path.resolve(__dirname, 'target/classes/META-INF/VAADIN'); |
||||
const useClientSideIndexFileForBootstrapping = true; |
||||
const clientSideIndexHTML = './index.html'; |
||||
const clientSideIndexEntryPoint = path.resolve(__dirname, 'frontend', 'generated/', 'vaadin.ts');; |
||||
const pwaEnabled = true; |
||||
const offlinePath = '.'; |
||||
const clientServiceWorkerEntryPoint = path.resolve(__dirname, 'target/sw'); |
||||
// public path for resources, must match Flow VAADIN_BUILD
|
||||
const VAADIN = 'VAADIN'; |
||||
const build = 'build'; |
||||
// public path for resources, must match the request used in flow to get the /build/stats.json file
|
||||
const config = 'config'; |
||||
const outputFolder = mavenOutputFolderForFlowBundledFiles; |
||||
const indexHtmlPath = 'index.html'; |
||||
// folder for outputting vaadin-bundle and other fragments
|
||||
const buildFolder = path.resolve(outputFolder, VAADIN, build); |
||||
// folder for outputting stats.json
|
||||
const confFolder = path.resolve(mavenOutputFolderForResourceFiles, config); |
||||
const serviceWorkerPath = 'sw.js'; |
||||
// file which is used by flow to read templates for server `@Id` binding
|
||||
const statsFile = `${confFolder}/stats.json`; |
||||
|
||||
const buildDirectory = path.resolve(__dirname, 'target'); |
||||
|
||||
// Flow plugins
|
||||
const BuildStatusPlugin = require(buildDirectory + '/plugins/build-status-plugin'); |
||||
const ThemeLiveReloadPlugin = require(buildDirectory + '/plugins/theme-live-reload-plugin'); |
||||
const { |
||||
ApplicationThemePlugin, |
||||
processThemeResources, |
||||
extractThemeName, |
||||
findParentThemes |
||||
} = require(buildDirectory + '/plugins/application-theme-plugin'); |
||||
const themeLoader = buildDirectory + '/plugins/theme-loader'; |
||||
|
||||
// Folders in the project which can contain static assets.
|
||||
const projectStaticAssetsFolders = [ |
||||
path.resolve(__dirname, 'src', 'main', 'resources', 'META-INF', 'resources'), |
||||
path.resolve(__dirname, 'src', 'main', 'resources', 'static'), |
||||
frontendFolder |
||||
]; |
||||
|
||||
const projectStaticAssetsOutputFolder = path.resolve(__dirname, 'target/classes/META-INF/VAADIN/webapp/VAADIN/static'); |
||||
|
||||
// Folders in the project which can contain application themes
|
||||
const themeProjectFolders = projectStaticAssetsFolders.map((folder) => path.resolve(folder, 'themes')); |
||||
|
||||
const tsconfigJsonFile = path.resolve(__dirname, 'tsconfig.json'); |
||||
const enableTypeScript = fs.existsSync(tsconfigJsonFile); |
||||
|
||||
// Target flow-fronted auto generated to be the actual target folder
|
||||
const flowFrontendFolder = path.resolve(__dirname, 'target/flow-frontend'); |
||||
|
||||
const statsSetViaCLI = process.argv.find((v) => v.indexOf('--stats') >= 0); |
||||
const devMode = process.argv.find((v) => v.indexOf('webpack-dev-server') >= 0); |
||||
if (!devMode) { |
||||
// make sure that build folder exists before outputting anything
|
||||
const mkdirp = require('mkdirp'); |
||||
mkdirp(buildFolder); |
||||
mkdirp(confFolder); |
||||
} |
||||
|
||||
let stats; |
||||
|
||||
// Open a connection with the Java dev-mode handler in order to finish
|
||||
// webpack-dev-mode when it exits or crashes.
|
||||
const watchDogPort = devMode && process.env.watchDogPort; |
||||
const watchDogHost = (devMode && process.env.watchDogHost) || 'localhost'; |
||||
if (watchDogPort) { |
||||
const runWatchDog = () => { |
||||
const client = new require('net').Socket(); |
||||
client.setEncoding('utf8'); |
||||
client.on('error', function (err) { |
||||
console.log('Watchdog connection error. Terminating webpack process...', err); |
||||
client.destroy(); |
||||
process.exit(0); |
||||
}); |
||||
client.on('close', function () { |
||||
client.destroy(); |
||||
runWatchDog(); |
||||
}); |
||||
client.connect(watchDogPort, watchDogHost); |
||||
}; |
||||
runWatchDog(); |
||||
} |
||||
|
||||
// Compute the entries that webpack have to visit
|
||||
const webPackEntries = {}; |
||||
if (useClientSideIndexFileForBootstrapping) { |
||||
webPackEntries.bundle = clientSideIndexEntryPoint; |
||||
const dirName = path.dirname(fileNameOfTheFlowGeneratedMainEntryPoint); |
||||
const baseName = path.basename(fileNameOfTheFlowGeneratedMainEntryPoint, '.js'); |
||||
if ( |
||||
fs |
||||
.readdirSync(dirName) |
||||
.filter((fileName) => !fileName.startsWith(baseName) && fileName.endsWith('.js') && fileName.includes('-')).length |
||||
) { |
||||
// if there are vaadin exported views, add a second entry
|
||||
webPackEntries.export = fileNameOfTheFlowGeneratedMainEntryPoint; |
||||
} |
||||
} else { |
||||
webPackEntries.bundle = fileNameOfTheFlowGeneratedMainEntryPoint; |
||||
} |
||||
|
||||
const appShellUrl = '.'; |
||||
let appShellManifestEntry = undefined; |
||||
|
||||
const swManifestTransform = (manifestEntries) => { |
||||
const warnings = []; |
||||
const manifest = manifestEntries; |
||||
if (useClientSideIndexFileForBootstrapping) { |
||||
// `index.html` is a special case: in contrast with the JS bundles produced by webpack
|
||||
// it's not served as-is directly from the webpack output at `/index.html`.
|
||||
// It goes through IndexHtmlRequestHandler and is served at `/`.
|
||||
//
|
||||
// TODO: calculate the revision based on the IndexHtmlRequestHandler-processed content
|
||||
// of the index.html file
|
||||
const indexEntryIdx = manifest.findIndex((entry) => entry.url === 'index.html'); |
||||
if (indexEntryIdx !== -1) { |
||||
manifest[indexEntryIdx].url = appShellUrl; |
||||
appShellManifestEntry = manifest[indexEntryIdx]; |
||||
} else { |
||||
// Index entry is only emitted on first compilation. Make sure it is cached also for incremental builds
|
||||
manifest.push(appShellManifestEntry); |
||||
} |
||||
} |
||||
return { manifest, warnings }; |
||||
}; |
||||
|
||||
const createServiceWorkerPlugin = function () { |
||||
return new InjectManifest({ |
||||
swSrc: clientServiceWorkerEntryPoint, |
||||
swDest: serviceWorkerPath, |
||||
manifestTransforms: [swManifestTransform], |
||||
maximumFileSizeToCacheInBytes: 100 * 1024 * 1024, |
||||
dontCacheBustURLsMatching: /.*-[a-z0-9]{20}\.cache\.js/, |
||||
include: [ |
||||
(chunk) => { |
||||
return true; |
||||
} |
||||
], |
||||
webpackCompilationPlugins: [ |
||||
new DefinePlugin({ |
||||
OFFLINE_PATH: JSON.stringify(offlinePath) |
||||
}) |
||||
] |
||||
}); |
||||
}; |
||||
|
||||
const flowFrontendThemesFolder = path.resolve(flowFrontendFolder, 'themes'); |
||||
const themeOptions = { |
||||
devMode: devMode, |
||||
// The following matches folder 'target/flow-frontend/themes/'
|
||||
// (not 'frontend/themes') for theme in JAR that is copied there
|
||||
themeResourceFolder: flowFrontendThemesFolder, |
||||
themeProjectFolders: themeProjectFolders, |
||||
projectStaticAssetsOutputFolder: projectStaticAssetsOutputFolder, |
||||
frontendGeneratedFolder: frontendGeneratedFolder |
||||
}; |
||||
let themeName = undefined; |
||||
let themeWatchFolders = undefined; |
||||
if (devMode) { |
||||
// Current theme name is being extracted from theme.js located in frontend
|
||||
// generated folder
|
||||
themeName = extractThemeName(frontendGeneratedFolder); |
||||
const parentThemePaths = findParentThemes(themeName, themeOptions); |
||||
const currentThemeFolders = [ |
||||
...projectStaticAssetsFolders.map((folder) => path.resolve(folder, 'themes', themeName)), |
||||
path.resolve(flowFrontendThemesFolder, themeName) |
||||
]; |
||||
// Watch the components folders for component styles update in both
|
||||
// current theme and parent themes. Other folders or CSS files except
|
||||
// 'styles.css' should be referenced from `styles.css` anyway, so no need
|
||||
// to watch them.
|
||||
themeWatchFolders = [...currentThemeFolders, ...parentThemePaths].map((themeFolder) => |
||||
path.resolve(themeFolder, 'components') |
||||
); |
||||
} |
||||
|
||||
const processThemeResourcesCallback = (logger) => processThemeResources(themeOptions, logger); |
||||
|
||||
exports = { |
||||
frontendFolder: `${frontendFolder}`, |
||||
buildFolder: `${buildFolder}`, |
||||
confFolder: `${confFolder}` |
||||
}; |
||||
|
||||
module.exports = { |
||||
mode: 'production', |
||||
context: frontendFolder, |
||||
entry: webPackEntries, |
||||
|
||||
output: { |
||||
filename: `${VAADIN}/${build}/vaadin-[name]-[contenthash].cache.js`, |
||||
path: outputFolder |
||||
}, |
||||
|
||||
resolve: { |
||||
// Search for import 'x/y' inside these folders, used at least for importing an application theme
|
||||
modules: ['node_modules', flowFrontendFolder, ...projectStaticAssetsFolders], |
||||
extensions: [enableTypeScript && '.ts', '.js'].filter(Boolean), |
||||
alias: { |
||||
Frontend: frontendFolder |
||||
} |
||||
}, |
||||
|
||||
stats: devMode && !statsSetViaCLI ? 'errors-warnings' : 'normal', // Unclutter output in dev mode
|
||||
|
||||
devServer: { |
||||
hot: false, // disable HMR
|
||||
client: false, // disable wds client as we handle reloads and errors better
|
||||
// webpack-dev-server serves ./, webpack-generated, and java webapp
|
||||
static: [outputFolder, path.resolve(__dirname, 'src', 'main', 'webapp')], |
||||
setupMiddlewares: function (middlewares, devServer) { |
||||
devServer.app.get(`/assetsByChunkName`, function (req, res) { |
||||
res.json(stats.assetsByChunkName); |
||||
}); |
||||
devServer.app.get(`/stop`, function (req, res) { |
||||
// eslint-disable-next-line no-console
|
||||
console.log("Stopped 'webpack-dev-server'"); |
||||
process.exit(0); |
||||
}); |
||||
return middlewares; |
||||
} |
||||
}, |
||||
|
||||
module: { |
||||
rules: [ |
||||
enableTypeScript && { |
||||
test: /\.ts$/, |
||||
loader: 'esbuild-loader', |
||||
options: { |
||||
loader: 'ts', |
||||
target: 'es2019' |
||||
} |
||||
}, |
||||
{ |
||||
test: /\.css$/i, |
||||
use: [ |
||||
{ |
||||
loader: 'lit-css-loader', |
||||
options: { |
||||
import: 'lit' |
||||
} |
||||
}, |
||||
{ |
||||
loader: 'extract-loader' |
||||
}, |
||||
{ |
||||
loader: 'css-loader', |
||||
options: { |
||||
url: (url, resourcePath) => { |
||||
// Only translate files from node_modules
|
||||
const resolve = resourcePath.match(/(\\|\/)node_modules\1/); |
||||
const themeResource = resourcePath.match(themePartRegex) && url.match(/^themes\/[\s\S]*?\//); |
||||
return resolve || themeResource; |
||||
}, |
||||
// use theme-loader to also handle any imports in css files
|
||||
importLoaders: 1 |
||||
} |
||||
}, |
||||
{ |
||||
// theme-loader will change any url starting with './' to start with 'VAADIN/static' instead
|
||||
// NOTE! this loader should be here so it's run before css-loader as loaders are applied Right-To-Left
|
||||
loader: themeLoader, |
||||
options: { |
||||
devMode: devMode |
||||
} |
||||
} |
||||
] |
||||
}, |
||||
{ |
||||
// File-loader only copies files used as imports in .js files or handled by css-loader
|
||||
test: /\.(png|gif|jpg|jpeg|svg|eot|woff|woff2|otf|ttf)$/, |
||||
use: [ |
||||
{ |
||||
loader: 'file-loader', |
||||
options: { |
||||
outputPath: 'VAADIN/static/', |
||||
name(resourcePath, resourceQuery) { |
||||
if (resourcePath.match(/(\\|\/)node_modules\1/)) { |
||||
return /(\\|\/)node_modules\1(?!.*node_modules)([\S]+)/.exec(resourcePath)[2].replace(/\\/g, '/'); |
||||
} |
||||
if (resourcePath.match(/(\\|\/)flow-frontend\1/)) { |
||||
return /(\\|\/)flow-frontend\1(?!.*flow-frontend)([\S]+)/.exec(resourcePath)[2].replace(/\\/g, '/'); |
||||
} |
||||
return '[path][name].[ext]'; |
||||
} |
||||
} |
||||
} |
||||
] |
||||
} |
||||
].filter(Boolean) |
||||
}, |
||||
performance: { |
||||
maxEntrypointSize: 2097152, // 2MB
|
||||
maxAssetSize: 2097152 // 2MB
|
||||
}, |
||||
plugins: [ |
||||
new ApplicationThemePlugin(themeOptions), |
||||
|
||||
...(devMode && themeName |
||||
? [ |
||||
new ExtraWatchWebpackPlugin({ |
||||
files: [], |
||||
dirs: themeWatchFolders |
||||
}), |
||||
new ThemeLiveReloadPlugin(processThemeResourcesCallback) |
||||
] |
||||
: []), |
||||
|
||||
function (compiler) { |
||||
// V14 bootstrapping needs the bundle names
|
||||
compiler.hooks.afterEmit.tapAsync("FlowStatsHelper", (compilation, done) => { |
||||
let miniStats = { |
||||
assetsByChunkName: compilation.getStats().toJson().assetsByChunkName |
||||
}; |
||||
if (!devMode) { |
||||
fs.writeFile(statsFile, JSON.stringify(miniStats, null, 1), |
||||
() => done()); |
||||
} else { |
||||
stats = miniStats; |
||||
done(); |
||||
} |
||||
}); |
||||
}, |
||||
|
||||
// Includes JS output bundles into "index.html"
|
||||
useClientSideIndexFileForBootstrapping && |
||||
new HtmlWebpackPlugin({ |
||||
template: clientSideIndexHTML, |
||||
filename: indexHtmlPath, |
||||
inject: 'head', |
||||
scriptLoading: 'defer', |
||||
chunks: ['bundle'] |
||||
}), |
||||
|
||||
// Service worker for offline
|
||||
pwaEnabled && createServiceWorkerPlugin(), |
||||
|
||||
// Generate compressed bundles when not devMode
|
||||
!devMode && new CompressionPlugin(), |
||||
|
||||
enableTypeScript && |
||||
new ForkTsCheckerWebpackPlugin({ |
||||
typescript: { |
||||
configFile: tsconfigJsonFile |
||||
} |
||||
}), |
||||
|
||||
new BuildStatusPlugin() |
||||
].filter(Boolean) |
||||
}; |
||||
Loading…
Reference in new issue