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