Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7555cfd51d | |||
| ea038ec70c | |||
| ecfa0eb6d8 |
@@ -1,3 +0,0 @@
|
||||
/gradlew text eol=lf
|
||||
*.bat text eol=crlf
|
||||
*.jar binary
|
||||
@@ -1,37 +0,0 @@
|
||||
HELP.md
|
||||
.gradle
|
||||
build/
|
||||
!gradle/wrapper/gradle-wrapper.jar
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
bin/
|
||||
!**/src/main/**/bin/
|
||||
!**/src/test/**/bin/
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
out/
|
||||
!**/src/main/**/out/
|
||||
!**/src/test/**/out/
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
@@ -1,51 +0,0 @@
|
||||
plugins {
|
||||
id 'java'
|
||||
id 'org.springframework.boot' version '4.0.7'
|
||||
id 'io.spring.dependency-management' version '1.1.7'
|
||||
alias(libs.plugins.lombok)
|
||||
}
|
||||
|
||||
group = 'de.thpeetz.kontor'
|
||||
version = '0.3.0-SNAPSHOT'
|
||||
|
||||
java {
|
||||
toolchain {
|
||||
languageVersion = JavaLanguageVersion.of(21)
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven { setUrl("https://repo.spring.io/milestone") }
|
||||
}
|
||||
|
||||
dependencyManagement {
|
||||
imports {
|
||||
mavenBom libs.camel.bom.get().toString()
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'org.springframework.boot:spring-boot-starter-actuator'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-artemis'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-webmvc'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
|
||||
implementation 'org.apache.camel.springboot:camel-spring-boot-starter:4.20.0'
|
||||
implementation 'org.apache.camel.springboot:camel-jms-starter'
|
||||
implementation 'io.micrometer:micrometer-registry-prometheus'
|
||||
implementation 'org.apache.activemq:artemis-jakarta-client'
|
||||
implementation 'org.postgresql:postgresql'
|
||||
implementation libs.jackson
|
||||
implementation libs.gson
|
||||
runtimeOnly 'io.micrometer:micrometer-registry-prometheus'
|
||||
compileOnly 'org.projectlombok:lombok'
|
||||
annotationProcessor 'org.projectlombok:lombok'
|
||||
testImplementation 'org.apache.camel:camel-test-spring-junit5'
|
||||
testImplementation 'org.springframework.boot:spring-boot-starter-artemis-test'
|
||||
testImplementation 'org.springframework.boot:spring-boot-starter-webmvc-test'
|
||||
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
|
||||
}
|
||||
|
||||
tasks.named('test') {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
[versions]
|
||||
gradle = "8.6"
|
||||
args4j = "2.33"
|
||||
commonscli = "1.5.0"
|
||||
junit = "5.8.2"
|
||||
logback = "1.1.2"
|
||||
mockito = "1.9.5"
|
||||
picoli = "4.7.0"
|
||||
slf4j = "1.7.22"
|
||||
hsqldb = "2.7.1"
|
||||
sqlite = "3.25.2"
|
||||
spotbugs = "6.0.7"
|
||||
asciidoctor = "4.0.2"
|
||||
rouge = "3.15.0"
|
||||
#diagram = "2.2.2"
|
||||
diagram = "2.3.1"
|
||||
sonarqube = "3.3"
|
||||
cimtConventions = "1.0.0-SNAPSHOT"
|
||||
springboot = "3.2.5"
|
||||
springdependencies = "1.1.4"
|
||||
vaadin = "24.3.8"
|
||||
camel = "4.10.6"
|
||||
artemis = "2.41.0"
|
||||
lombok = "8.6"
|
||||
gson = "2.9.0"
|
||||
jackson = "2.16.1"
|
||||
json_simple = "1.1.1"
|
||||
mail = "1.6.2"
|
||||
hypersistence = "3.9.10"
|
||||
|
||||
[libraries]
|
||||
args4j = { module = "args4j:args4j", version.ref = "args4j" }
|
||||
commonscli = { module = "commons-cli:commons-cli", version.ref = "commonscli" }
|
||||
junit = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit" }
|
||||
logbackCore = { module = "ch.qos.logback:logback-core", version.ref = "logback" }
|
||||
logbackClassic = { module = "ch.qos.logback:logback-classic", version.ref = "logback" }
|
||||
mockito = { module = "org.mockito:mockito-all", version.ref = "mockito" }
|
||||
picocli = { module = "info.picocli:picocli", version.ref = "picoli" }
|
||||
slf4j = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" }
|
||||
hsqldb = { module = "org.hsqldb:hsqldb", version.ref = "hsqldb" }
|
||||
gson = { module = "com.google.code.gson:gson", version.ref = "gson" }
|
||||
jackson = { module = "com.fasterxml.jackson.core:jackson-databind", version.ref = "jackson" }
|
||||
json = { module = "com.googlecode.json-simple:json-simple", version.ref ="json_simple" }
|
||||
mail = { module = "com.sun.mail:javax.mail", version.ref ="mail" }
|
||||
sqlite-jdbc = { module = "org.xerial:sqlite-jdbc", version.ref = "sqlite" }
|
||||
hypersistence = { module = "io.hypersistence:hypersistence-utils-hibernate-63", version.ref = "hypersistence" }
|
||||
vaadin-bom = { module = "com.vaadin:vaadin-bom", version.ref = "vaadin" }
|
||||
camel-bom = { module = "org.apache.camel.springboot:camel-spring-boot-bom", version.ref = "camel"}
|
||||
artemis = { module = "org.apache.activemq:artemis-jms-server", version.ref = "artemis" }
|
||||
asciidoctorGradleJvmGems = { module = "org.asciidoctor:asciidoctor-gradle-jvm-gems", version.ref= "asciidoctor" }
|
||||
asciidoctorGradleJvm = { module = "org.asciidoctor:asciidoctor-gradle-jvm", version.ref= "asciidoctor" }
|
||||
asciidoctorGradleJvmPdf = { module = "org.asciidoctor:asciidoctor-gradle-jvm-pdf", version.ref= "asciidoctor" }
|
||||
rouge = { module = "rubygems:rouge", version.ref = "rouge" }
|
||||
diagram = { module = "rubygems:asciidoctor-diagram", version.ref = "diagram" }
|
||||
|
||||
[bundles]
|
||||
logback = ["logbackCore", "logbackClassic"]
|
||||
|
||||
[plugins]
|
||||
spotbugs = { id = "com.github.spotbugs", version.ref = "spotbugs" }
|
||||
sonarqube = { id = "org.sonarqube", version.ref = "sonarqube" }
|
||||
asciidoctorPdf = { id = "org.asciidoctor.jvm.pdf", version.ref = "asciidoctor" }
|
||||
asciidoctorConvert = { id = "org.asciidoctor.jvm.convert", version.ref = "asciidoctor" }
|
||||
asciidoctorGems = { id = "org.asciidoctor.jvm.gems", version.ref = "asciidoctor" }
|
||||
javaConvention = { id = "de.cimt.java-conventions", version.ref = "cimtConventions" }
|
||||
applicationConvention = { id = "de.cimt.application-conventions", version.ref = "cimtConventions" }
|
||||
libraryConvention = { id = "de.cimt.library-conventions", version.ref = "cimtConventions" }
|
||||
asciidoctorConvention = { id = "de.cimt.asciidoctor-conventions", version.ref = "cimtConventions" }
|
||||
spring-boot = { id = "org.springframework.boot", version.ref = "springboot"}
|
||||
spring-dependencies = { id = "io.spring.dependency-management", version.ref = "springdependencies" }
|
||||
vaadin = { id = "com.vaadin", version.ref = "vaadin" }
|
||||
lombok = { id = "io.freefair.lombok", version.ref = "lombok" }
|
||||
BIN
Binary file not shown.
@@ -1,9 +0,0 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip
|
||||
networkTimeout=10000
|
||||
retries=0
|
||||
retryBackOffMs=500
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
Vendored
-248
@@ -1,248 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright © 2015 the original authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Gradle start up script for POSIX generated by Gradle.
|
||||
#
|
||||
# Important for running:
|
||||
#
|
||||
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||
# noncompliant, but you have some other compliant shell such as ksh or
|
||||
# bash, then to run this script, type that shell name before the whole
|
||||
# command line, like:
|
||||
#
|
||||
# ksh Gradle
|
||||
#
|
||||
# Busybox and similar reduced shells will NOT work, because this script
|
||||
# requires all of these POSIX shell features:
|
||||
# * functions;
|
||||
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||
# * compound commands having a testable exit status, especially «case»;
|
||||
# * various built-in commands including «command», «set», and «ulimit».
|
||||
#
|
||||
# Important for patching:
|
||||
#
|
||||
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||
#
|
||||
# The "traditional" practice of packing multiple parameters into a
|
||||
# space-separated string is a well documented source of bugs and security
|
||||
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||
# options in "$@", and eventually passing that to Java.
|
||||
#
|
||||
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||
# see the in-line comments for details.
|
||||
#
|
||||
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/3d91ce3b8caaf77ad09f381f43615b715b53f72c/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
|
||||
# Resolve links: $0 may be a link
|
||||
app_path=$0
|
||||
|
||||
# Need this for daisy-chained symlinks.
|
||||
while
|
||||
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||
[ -h "$app_path" ]
|
||||
do
|
||||
ls=$( ls -ld "$app_path" )
|
||||
link=${ls#*' -> '}
|
||||
case $link in #(
|
||||
/*) app_path=$link ;; #(
|
||||
*) app_path=$APP_HOME$link ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# This is normally unused
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
} >&2
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
} >&2
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "$( uname )" in #(
|
||||
CYGWIN* ) cygwin=true ;; #(
|
||||
Darwin* ) darwin=true ;; #(
|
||||
MSYS* | MINGW* ) msys=true ;; #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
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
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD=java
|
||||
if ! command -v java >/dev/null 2>&1
|
||||
then
|
||||
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
case $MAX_FD in #(
|
||||
max*)
|
||||
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
case $MAX_FD in #(
|
||||
'' | soft) :;; #(
|
||||
*)
|
||||
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command, stacking in reverse order:
|
||||
# * args from the command line
|
||||
# * the main class name
|
||||
# * -classpath
|
||||
# * -D...appname settings
|
||||
# * --module-path (only if needed)
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if "$cygwin" || "$msys" ; then
|
||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||
|
||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
for arg do
|
||||
if
|
||||
case $arg in #(
|
||||
-*) false ;; # don't mess with options #(
|
||||
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||
[ -e "$t" ] ;; #(
|
||||
*) false ;;
|
||||
esac
|
||||
then
|
||||
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||
fi
|
||||
# Roll the args list around exactly as many times as the number of
|
||||
# args, so each arg winds up back in the position where it started, but
|
||||
# possibly modified.
|
||||
#
|
||||
# NB: a `for` loop captures its iteration list before it begins, so
|
||||
# changing the positional parameters here affects neither the number of
|
||||
# iterations, nor the values presented in `arg`.
|
||||
shift # remove old arg
|
||||
set -- "$@" "$arg" # push replacement arg
|
||||
done
|
||||
fi
|
||||
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Collect all arguments for the java command:
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||
# and any embedded shellness will be escaped.
|
||||
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||
# treated as '${Hostname}' itself on the command line.
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
|
||||
"$@"
|
||||
|
||||
# Stop when "xargs" is not available.
|
||||
if ! command -v xargs >/dev/null 2>&1
|
||||
then
|
||||
die "xargs is not available"
|
||||
fi
|
||||
|
||||
# Use "xargs" to parse quoted args.
|
||||
#
|
||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||
#
|
||||
# In Bash we could simply go:
|
||||
#
|
||||
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||
# set -- "${ARGS[@]}" "$@"
|
||||
#
|
||||
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||
# character that might be a shell metacharacter, then use eval to reverse
|
||||
# that process (while maintaining the separation between arguments), and wrap
|
||||
# the whole thing up as a single "set" statement.
|
||||
#
|
||||
# This will of course break if any of these variables contains a newline or
|
||||
# an unmatched quote.
|
||||
#
|
||||
|
||||
eval "set -- $(
|
||||
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||
xargs -n1 |
|
||||
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||
tr '\n' ' '
|
||||
)" '"$@"'
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
Vendored
-82
@@ -1,82 +0,0 @@
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
@rem SPDX-License-Identifier: Apache-2.0
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables, and ensure extensions are enabled
|
||||
setlocal EnableExtensions
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
@rem This is normally unused
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
"%COMSPEC%" /c exit 1
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
"%COMSPEC%" /c exit 1
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
@rem endlocal doesn't take effect until after the line is parsed and variables are expanded
|
||||
@rem which allows us to clear the local environment before executing the java command
|
||||
endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel
|
||||
|
||||
:exitWithErrorLevel
|
||||
@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts
|
||||
"%COMSPEC%" /c exit %ERRORLEVEL%
|
||||
@@ -1 +0,0 @@
|
||||
rootProject.name = 'integration'
|
||||
@@ -1,13 +0,0 @@
|
||||
package de.thpeetz.kontor.integration;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class IntegrationApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(IntegrationApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package de.thpeetz.kontor.integration.routes;
|
||||
|
||||
import de.thpeetz.kontor.integration.services.AddLinkProcessor;
|
||||
import de.thpeetz.kontor.media.services.MediaFileService;
|
||||
import org.apache.camel.builder.RouteBuilder;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class AddLinkFromQueue extends RouteBuilder {
|
||||
|
||||
@Autowired
|
||||
private final MediaFileService mediaFileService;
|
||||
|
||||
@Autowired
|
||||
public AddLinkFromQueue(MediaFileService mediaFileService) {
|
||||
this.mediaFileService = mediaFileService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure() throws Exception {
|
||||
from("jms:queue:add_link_file")
|
||||
.routeId("read-queue-add-link_file")
|
||||
.log("${body}")
|
||||
.process(new AddLinkProcessor(mediaFileService))
|
||||
.to("jms:queue:update_title");
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package de.thpeetz.kontor.integration.routes;
|
||||
import de.thpeetz.kontor.media.services.MediaFileService;
|
||||
import org.apache.camel.builder.RouteBuilder;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class QueueMediaLinkAdd extends RouteBuilder {
|
||||
|
||||
@Autowired
|
||||
private final MediaFileService mediaFileService;
|
||||
|
||||
@Autowired
|
||||
public QueueMediaLinkAdd(MediaFileService mediaFileService) {
|
||||
this.mediaFileService = mediaFileService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure() throws Exception {
|
||||
from("jms:queue:media.link.add")
|
||||
.routeId("read-queue-media-link-add")
|
||||
.log("${body}")
|
||||
.to("jms:queue:media.link.add.processed");
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package de.thpeetz.kontor.integration.routes;
|
||||
|
||||
import org.apache.camel.builder.RouteBuilder;
|
||||
import de.thpeetz.kontor.media.services.MediaFileService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class QueueMediaLoFiAdd extends RouteBuilder {
|
||||
|
||||
@Autowired
|
||||
private final MediaFileService mediaFileService;
|
||||
|
||||
@Autowired
|
||||
public QueueMediaLoFiAdd(MediaFileService mediaFileService) {
|
||||
this.mediaFileService = mediaFileService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure() throws Exception {
|
||||
from("jms:queue:media.lofi.add")
|
||||
.routeId("read-queue-media-lofi-add")
|
||||
.log("${body}")
|
||||
.to("jms:queue:media.lofi.add.processed");
|
||||
}
|
||||
}
|
||||
-26
@@ -1,26 +0,0 @@
|
||||
package de.thpeetz.kontor.integration.routes;
|
||||
|
||||
import org.apache.camel.builder.RouteBuilder;
|
||||
import de.thpeetz.kontor.media.services.MediaFileService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class QueueMediaVideoAdd extends RouteBuilder {
|
||||
|
||||
@Autowired
|
||||
private final MediaFileService mediaFileService;
|
||||
|
||||
@Autowired
|
||||
public QueueMediaVideoAdd(MediaFileService mediaFileService) {
|
||||
this.mediaFileService = mediaFileService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure() throws Exception {
|
||||
from("jms:queue:media.video.add")
|
||||
.routeId("read-queue-media-video-add")
|
||||
.log("${body}")
|
||||
.to("jms:queue:media.video.add.processed");
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package de.thpeetz.kontor.integration.routes;
|
||||
|
||||
import org.apache.camel.builder.RouteBuilder;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class ReadQueueRoute extends RouteBuilder {
|
||||
|
||||
@Override
|
||||
public void configure() throws Exception {
|
||||
from("jms:queue:KontorMediaFile")
|
||||
.routeId("add-link-from-queue")
|
||||
.trace(true)
|
||||
.log(">>> ${body}");
|
||||
}
|
||||
}
|
||||
-53
@@ -1,53 +0,0 @@
|
||||
package de.thpeetz.kontor.integration.services;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import de.thpeetz.kontor.media.data.MediaFile;
|
||||
import de.thpeetz.kontor.media.services.MediaFileService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.camel.Exchange;
|
||||
import org.apache.camel.Processor;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Slf4j
|
||||
public class AddLinkProcessor implements Processor {
|
||||
|
||||
private final MediaFileService mediaFileService;
|
||||
|
||||
public AddLinkProcessor(MediaFileService mediaFileService) {
|
||||
this.mediaFileService = mediaFileService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process(Exchange exchange) throws Exception {
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
HashMap<String, String> myMap = objectMapper.readValue(exchange.getIn().getBody().toString(),
|
||||
new TypeReference<HashMap<String, String>>() {
|
||||
});
|
||||
String url = myMap.get("url");
|
||||
log.info("found url: {}", url);
|
||||
MediaFile mediaFile = mediaFileService.findAllMediaFilesByUrl(url);
|
||||
if (mediaFile == null) {
|
||||
log.info("URL not found, create MediaFile");
|
||||
mediaFile = new MediaFile();
|
||||
mediaFile.setUrl(url);
|
||||
mediaFile.setPath("");
|
||||
mediaFile.setCloudLink("");
|
||||
mediaFile.setFileName("");
|
||||
mediaFile.setTitle("");
|
||||
mediaFile.setReview(true);
|
||||
mediaFile.setShouldDownload(true);
|
||||
MediaFile mediaFileResult = mediaFileService.saveMediaFile(mediaFile);
|
||||
log.info("created MediaFile with {}", mediaFileResult.getId());
|
||||
exchange.getMessage().getHeaders().put("mediafile_id", mediaFileResult.getId());
|
||||
} else {
|
||||
log.info("found MediaFile with {}", mediaFile.getId());
|
||||
exchange.getMessage().getHeaders().put("mediafile_id", mediaFile.getId());
|
||||
}
|
||||
log.info("found MediaFile: {}", mediaFile);
|
||||
Map<String, Object> map = exchange.getMessage().getHeaders();
|
||||
log.info("Headers: {}", map);
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package de.thpeetz.kontor.integration.services;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class AddLinkService {
|
||||
|
||||
public void fromQueue(String messageBody) throws JsonProcessingException {
|
||||
log.info("get body: {}", messageBody);
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
HashMap<String,String> myMap = objectMapper.readValue(messageBody, new TypeReference<HashMap<String,String>>() {});
|
||||
String url = myMap.get("url");
|
||||
log.info("found url: {}", url);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
spring:
|
||||
application:
|
||||
name: integration
|
||||
server:
|
||||
port:
|
||||
8110
|
||||
@@ -1,39 +0,0 @@
|
||||
plugins {
|
||||
id 'java'
|
||||
id 'java-library'
|
||||
id 'maven-publish'
|
||||
id 'jacoco'
|
||||
id 'test-report-aggregation'
|
||||
id 'jacoco-report-aggregation'
|
||||
alias(libs.plugins.lombok)
|
||||
}
|
||||
|
||||
repositories {
|
||||
//maven { setUrl("https://nexus.thpeetz.de/repository/maven-central") }
|
||||
mavenCentral()
|
||||
maven { setUrl("https://repo.spring.io/milestone") }
|
||||
}
|
||||
|
||||
java {
|
||||
sourceCompatibility = JavaVersion.VERSION_21
|
||||
}
|
||||
|
||||
configurations {
|
||||
developmentOnly
|
||||
runtimeClasspath {
|
||||
extendsFrom developmentOnly
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
//implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
|
||||
//implementation 'org.postgresql:postgresql'
|
||||
//implementation 'org.hibernate.orm:hibernate-community-dialects'
|
||||
compileOnly libs.spring.data
|
||||
compileOnly 'org.projectlombok:lombok'
|
||||
annotationProcessor 'org.projectlombok:lombok'
|
||||
}
|
||||
|
||||
wrapper {
|
||||
gradleVersion = "8.6"
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
[versions]
|
||||
gradle = "8.6"
|
||||
args4j = "2.33"
|
||||
commonscli = "1.5.0"
|
||||
junit = "5.8.2"
|
||||
logback = "1.1.2"
|
||||
mockito = "1.9.5"
|
||||
picoli = "4.7.0"
|
||||
slf4j = "1.7.22"
|
||||
hsqldb = "2.7.1"
|
||||
sqlite = "3.25.2"
|
||||
spotbugs = "6.0.7"
|
||||
asciidoctor = "4.0.2"
|
||||
rouge = "3.15.0"
|
||||
#diagram = "2.2.2"
|
||||
diagram = "2.3.1"
|
||||
sonarqube = "3.3"
|
||||
cimtConventions = "1.0.0-SNAPSHOT"
|
||||
springboot = "3.2.5"
|
||||
springdependencies = "1.1.4"
|
||||
vaadin = "24.3.8"
|
||||
camel = "4.10.6"
|
||||
artemis = "2.41.0"
|
||||
lombok = "8.6"
|
||||
gson = "2.9.0"
|
||||
jackson = "2.16.1"
|
||||
json_simple = "1.1.1"
|
||||
mail = "1.6.2"
|
||||
hypersistence = "3.9.10"
|
||||
|
||||
[libraries]
|
||||
args4j = { module = "args4j:args4j", version.ref = "args4j" }
|
||||
commonscli = { module = "commons-cli:commons-cli", version.ref = "commonscli" }
|
||||
junit = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit" }
|
||||
logbackCore = { module = "ch.qos.logback:logback-core", version.ref = "logback" }
|
||||
logbackClassic = { module = "ch.qos.logback:logback-classic", version.ref = "logback" }
|
||||
mockito = { module = "org.mockito:mockito-all", version.ref = "mockito" }
|
||||
picocli = { module = "info.picocli:picocli", version.ref = "picoli" }
|
||||
slf4j = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" }
|
||||
hsqldb = { module = "org.hsqldb:hsqldb", version.ref = "hsqldb" }
|
||||
gson = { module = "com.google.code.gson:gson", version.ref = "gson" }
|
||||
jackson = { module = "com.fasterxml.jackson.core:jackson-databind", version.ref = "jackson" }
|
||||
json = { module = "com.googlecode.json-simple:json-simple", version.ref ="json_simple" }
|
||||
mail = { module = "com.sun.mail:javax.mail", version.ref ="mail" }
|
||||
sqlite-jdbc = { module = "org.xerial:sqlite-jdbc", version.ref = "sqlite" }
|
||||
hypersistence = { module = "io.hypersistence:hypersistence-utils-hibernate-63", version.ref = "hypersistence" }
|
||||
vaadin-bom = { module = "com.vaadin:vaadin-bom", version.ref = "vaadin" }
|
||||
camel-bom = { module = "org.apache.camel.springboot:camel-spring-boot-bom", version.ref = "camel"}
|
||||
spring-data = { module = "org.springframework.data:spring-data-jpa", version.ref = "springboot" }
|
||||
artemis = { module = "org.apache.activemq:artemis-jms-server", version.ref = "artemis" }
|
||||
asciidoctorGradleJvmGems = { module = "org.asciidoctor:asciidoctor-gradle-jvm-gems", version.ref= "asciidoctor" }
|
||||
asciidoctorGradleJvm = { module = "org.asciidoctor:asciidoctor-gradle-jvm", version.ref= "asciidoctor" }
|
||||
asciidoctorGradleJvmPdf = { module = "org.asciidoctor:asciidoctor-gradle-jvm-pdf", version.ref= "asciidoctor" }
|
||||
rouge = { module = "rubygems:rouge", version.ref = "rouge" }
|
||||
diagram = { module = "rubygems:asciidoctor-diagram", version.ref = "diagram" }
|
||||
|
||||
[bundles]
|
||||
logback = ["logbackCore", "logbackClassic"]
|
||||
|
||||
[plugins]
|
||||
spotbugs = { id = "com.github.spotbugs", version.ref = "spotbugs" }
|
||||
sonarqube = { id = "org.sonarqube", version.ref = "sonarqube" }
|
||||
asciidoctorPdf = { id = "org.asciidoctor.jvm.pdf", version.ref = "asciidoctor" }
|
||||
asciidoctorConvert = { id = "org.asciidoctor.jvm.convert", version.ref = "asciidoctor" }
|
||||
asciidoctorGems = { id = "org.asciidoctor.jvm.gems", version.ref = "asciidoctor" }
|
||||
javaConvention = { id = "de.cimt.java-conventions", version.ref = "cimtConventions" }
|
||||
applicationConvention = { id = "de.cimt.application-conventions", version.ref = "cimtConventions" }
|
||||
libraryConvention = { id = "de.cimt.library-conventions", version.ref = "cimtConventions" }
|
||||
asciidoctorConvention = { id = "de.cimt.asciidoctor-conventions", version.ref = "cimtConventions" }
|
||||
spring-boot = { id = "org.springframework.boot", version.ref = "springboot"}
|
||||
spring-dependencies = { id = "io.spring.dependency-management", version.ref = "springdependencies" }
|
||||
vaadin = { id = "com.vaadin", version.ref = "vaadin" }
|
||||
lombok = { id = "io.freefair.lombok", version.ref = "lombok" }
|
||||
BIN
Binary file not shown.
@@ -1,7 +0,0 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
Vendored
-248
@@ -1,248 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright © 2015 the original authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Gradle start up script for POSIX generated by Gradle.
|
||||
#
|
||||
# Important for running:
|
||||
#
|
||||
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||
# noncompliant, but you have some other compliant shell such as ksh or
|
||||
# bash, then to run this script, type that shell name before the whole
|
||||
# command line, like:
|
||||
#
|
||||
# ksh Gradle
|
||||
#
|
||||
# Busybox and similar reduced shells will NOT work, because this script
|
||||
# requires all of these POSIX shell features:
|
||||
# * functions;
|
||||
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||
# * compound commands having a testable exit status, especially «case»;
|
||||
# * various built-in commands including «command», «set», and «ulimit».
|
||||
#
|
||||
# Important for patching:
|
||||
#
|
||||
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||
#
|
||||
# The "traditional" practice of packing multiple parameters into a
|
||||
# space-separated string is a well documented source of bugs and security
|
||||
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||
# options in "$@", and eventually passing that to Java.
|
||||
#
|
||||
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||
# see the in-line comments for details.
|
||||
#
|
||||
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/3d91ce3b8caaf77ad09f381f43615b715b53f72c/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
|
||||
# Resolve links: $0 may be a link
|
||||
app_path=$0
|
||||
|
||||
# Need this for daisy-chained symlinks.
|
||||
while
|
||||
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||
[ -h "$app_path" ]
|
||||
do
|
||||
ls=$( ls -ld "$app_path" )
|
||||
link=${ls#*' -> '}
|
||||
case $link in #(
|
||||
/*) app_path=$link ;; #(
|
||||
*) app_path=$APP_HOME$link ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# This is normally unused
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
} >&2
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
} >&2
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "$( uname )" in #(
|
||||
CYGWIN* ) cygwin=true ;; #(
|
||||
Darwin* ) darwin=true ;; #(
|
||||
MSYS* | MINGW* ) msys=true ;; #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
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
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD=java
|
||||
if ! command -v java >/dev/null 2>&1
|
||||
then
|
||||
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
case $MAX_FD in #(
|
||||
max*)
|
||||
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
case $MAX_FD in #(
|
||||
'' | soft) :;; #(
|
||||
*)
|
||||
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command, stacking in reverse order:
|
||||
# * args from the command line
|
||||
# * the main class name
|
||||
# * -classpath
|
||||
# * -D...appname settings
|
||||
# * --module-path (only if needed)
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if "$cygwin" || "$msys" ; then
|
||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||
|
||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
for arg do
|
||||
if
|
||||
case $arg in #(
|
||||
-*) false ;; # don't mess with options #(
|
||||
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||
[ -e "$t" ] ;; #(
|
||||
*) false ;;
|
||||
esac
|
||||
then
|
||||
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||
fi
|
||||
# Roll the args list around exactly as many times as the number of
|
||||
# args, so each arg winds up back in the position where it started, but
|
||||
# possibly modified.
|
||||
#
|
||||
# NB: a `for` loop captures its iteration list before it begins, so
|
||||
# changing the positional parameters here affects neither the number of
|
||||
# iterations, nor the values presented in `arg`.
|
||||
shift # remove old arg
|
||||
set -- "$@" "$arg" # push replacement arg
|
||||
done
|
||||
fi
|
||||
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Collect all arguments for the java command:
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||
# and any embedded shellness will be escaped.
|
||||
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||
# treated as '${Hostname}' itself on the command line.
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
|
||||
"$@"
|
||||
|
||||
# Stop when "xargs" is not available.
|
||||
if ! command -v xargs >/dev/null 2>&1
|
||||
then
|
||||
die "xargs is not available"
|
||||
fi
|
||||
|
||||
# Use "xargs" to parse quoted args.
|
||||
#
|
||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||
#
|
||||
# In Bash we could simply go:
|
||||
#
|
||||
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||
# set -- "${ARGS[@]}" "$@"
|
||||
#
|
||||
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||
# character that might be a shell metacharacter, then use eval to reverse
|
||||
# that process (while maintaining the separation between arguments), and wrap
|
||||
# the whole thing up as a single "set" statement.
|
||||
#
|
||||
# This will of course break if any of these variables contains a newline or
|
||||
# an unmatched quote.
|
||||
#
|
||||
|
||||
eval "set -- $(
|
||||
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||
xargs -n1 |
|
||||
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||
tr '\n' ' '
|
||||
)" '"$@"'
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
Vendored
-82
@@ -1,82 +0,0 @@
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
@rem SPDX-License-Identifier: Apache-2.0
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables, and ensure extensions are enabled
|
||||
setlocal EnableExtensions
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
@rem This is normally unused
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
"%COMSPEC%" /c exit 1
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
"%COMSPEC%" /c exit 1
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
@rem endlocal doesn't take effect until after the line is parsed and variables are expanded
|
||||
@rem which allows us to clear the local environment before executing the java command
|
||||
endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel
|
||||
|
||||
:exitWithErrorLevel
|
||||
@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts
|
||||
"%COMSPEC%" /c exit %ERRORLEVEL%
|
||||
@@ -1,24 +0,0 @@
|
||||
pluginManagement {
|
||||
resolutionStrategy {
|
||||
eachPlugin {
|
||||
if (requested.id.id == 'org.springframework.boot') {
|
||||
useModule("org.springframework.boot:spring-boot-gradle-plugin:${requested.version}")
|
||||
}
|
||||
if (requested.id.id == 'org.gradle.toolchains.foojay-resolver') {
|
||||
useModule("org.gradle.toolchains.foojay-resolver-convention:0.4.0")
|
||||
}
|
||||
}
|
||||
}
|
||||
repositories {
|
||||
gradlePluginPortal()
|
||||
mavenCentral()
|
||||
maven { setUrl("https://maven.vaadin.com/vaadin-prereleases") }
|
||||
maven { setUrl("https://repo.spring.io/milestone") }
|
||||
maven { url 'https://plugins.gradle.org/m2/' }
|
||||
}
|
||||
// plugins {
|
||||
// id 'com.vaadin' version "${vaadinVersion}"
|
||||
// }
|
||||
}
|
||||
|
||||
rootProject.name = 'kontor-spring'
|
||||
@@ -1,34 +0,0 @@
|
||||
package de.thpeetz.kontor.admin.data;
|
||||
|
||||
import de.thpeetz.kontor.common.data.AbstractEntity;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Entity
|
||||
public class Assignment extends AbstractEntity {
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "profile_id")
|
||||
@NotNull
|
||||
private Profile profile;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "permission_id")
|
||||
@NotNull
|
||||
private Permission permission;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuffer sb = new StringBuffer("Assignment{");
|
||||
sb.append("profile=").append(profile.getUserName());
|
||||
sb.append(", permission=").append(permission.getName());
|
||||
sb.append('}');
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
package de.thpeetz.kontor.admin.data;
|
||||
|
||||
import de.thpeetz.kontor.common.data.AbstractEntity;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.OneToMany;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Getter
|
||||
@Setter
|
||||
@ToString
|
||||
@Entity
|
||||
public class Permission extends AbstractEntity {
|
||||
|
||||
@NotEmpty
|
||||
private String name;
|
||||
|
||||
@OneToMany(fetch = FetchType.EAGER, mappedBy = "permission")
|
||||
@Nullable
|
||||
private List<Assignment> assignments;
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
package de.thpeetz.kontor.admin.data;
|
||||
|
||||
import de.thpeetz.kontor.common.data.AbstractEntity;
|
||||
import jakarta.persistence.*;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Getter
|
||||
@Setter
|
||||
@ToString
|
||||
@Entity
|
||||
@Table(indexes = @Index(columnList = "userName"), uniqueConstraints = @UniqueConstraint(columnNames = {"userName"}))
|
||||
public class Profile extends AbstractEntity {
|
||||
|
||||
private String firstName;
|
||||
|
||||
private String lastName;
|
||||
|
||||
@NotEmpty
|
||||
private String userName;
|
||||
|
||||
private String email;
|
||||
|
||||
private String password;
|
||||
|
||||
private boolean enabled;
|
||||
|
||||
@OneToMany(fetch = FetchType.EAGER, mappedBy = "profile")
|
||||
@Nullable
|
||||
private List<Assignment> assignments = new LinkedList<>();
|
||||
|
||||
@OneToMany(fetch = FetchType.EAGER, mappedBy = "profile")
|
||||
@Nullable
|
||||
private List<Token> tokens = new LinkedList<>();
|
||||
|
||||
public String getFullName() {
|
||||
StringBuilder fullNameBuilder = new StringBuilder();
|
||||
if (firstName != null) {
|
||||
fullNameBuilder.append(firstName);
|
||||
}
|
||||
if (lastName != null) {
|
||||
if (!fullNameBuilder.isEmpty()) {
|
||||
fullNameBuilder.append(" ");
|
||||
}
|
||||
fullNameBuilder.append(lastName);
|
||||
}
|
||||
return fullNameBuilder.toString();
|
||||
}
|
||||
}
|
||||
-13
@@ -1,13 +0,0 @@
|
||||
package de.thpeetz.kontor.admin.repository;
|
||||
|
||||
import de.thpeetz.kontor.admin.data.*;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface AssignmentRepository extends JpaRepository<Assignment, String> {
|
||||
|
||||
List<Assignment> findByProfile(Profile profile);
|
||||
|
||||
List<Assignment> findByPermission(Permission permission);
|
||||
}
|
||||
-8
@@ -1,8 +0,0 @@
|
||||
package de.thpeetz.kontor.admin.repository;
|
||||
|
||||
import de.thpeetz.kontor.mailclient.data.MailAccount;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
|
||||
public interface MailAccountRepository extends JpaRepository<MailAccount, String> {
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
package de.thpeetz.kontor.bookshelf.data;
|
||||
|
||||
import de.thpeetz.kontor.common.data.AbstractEntity;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Index;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.persistence.UniqueConstraint;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Entity
|
||||
@Table(indexes = @Index(columnList = "author_id, article_id"), uniqueConstraints = @UniqueConstraint(columnNames = {"author_id", "article_id"}))
|
||||
public class ArticleAuthor extends AbstractEntity {
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "author_id")
|
||||
@NotNull
|
||||
private Author author;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "article_id")
|
||||
@NotNull
|
||||
private Article article;
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
package de.thpeetz.kontor.bookshelf.data;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import de.thpeetz.kontor.common.data.AbstractEntity;
|
||||
import jakarta.annotation.Nullable;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.Index;
|
||||
import jakarta.persistence.OneToMany;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.persistence.UniqueConstraint;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@ToString
|
||||
@Entity
|
||||
@Table(indexes = {
|
||||
@Index(columnList = "firstName, lastName"),
|
||||
@Index(columnList = "lastName, firstName")
|
||||
}, uniqueConstraints = {
|
||||
@UniqueConstraint(columnNames = { "firstName", "lastName" })
|
||||
})
|
||||
public class Author extends AbstractEntity {
|
||||
|
||||
@NotEmpty
|
||||
private String firstName;
|
||||
|
||||
@NotEmpty
|
||||
private String lastName;
|
||||
|
||||
@OneToMany(fetch = FetchType.EAGER, mappedBy = "author")
|
||||
@Nullable
|
||||
private List<BookAuthor> bookAuthors = new LinkedList<>();
|
||||
|
||||
@OneToMany(fetch = FetchType.EAGER, mappedBy = "author")
|
||||
@Nullable
|
||||
private List<ArticleAuthor> articleAuthors = new LinkedList<>();
|
||||
}
|
||||
-12
@@ -1,12 +0,0 @@
|
||||
package de.thpeetz.kontor.bookshelf.data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
public interface BookAuthorRepository extends JpaRepository<BookAuthor, String> {
|
||||
|
||||
List<BookAuthor> findByAuthor(Author author);
|
||||
|
||||
List<BookAuthor> findByBook(Book book);
|
||||
}
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
package de.thpeetz.kontor.bookshelf.data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
|
||||
public interface BookshelfPublisherRepository extends JpaRepository<BookshelfPublisher, String> {
|
||||
|
||||
@Query("select p from BookshelfPublisher p " +
|
||||
"where lower(p.name) like lower(concat('%', :searchTerm, '%')) ")
|
||||
List<BookshelfPublisher> search(@Param("searchTerm") String searchTerm);
|
||||
|
||||
BookshelfPublisher findByName(String name);
|
||||
|
||||
List<BookshelfPublisher> findByNameIgnoreCase(String name);
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
package de.thpeetz.kontor.comics.data;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
||||
import de.thpeetz.kontor.common.data.AbstractEntity;
|
||||
import jakarta.annotation.*;
|
||||
import jakarta.persistence.CascadeType;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.OneToMany;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Entity
|
||||
public class Volume extends AbstractEntity {
|
||||
|
||||
@NotEmpty
|
||||
private String name;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "comic_id")
|
||||
@NotNull
|
||||
@JsonIgnoreProperties({ "volumes" })
|
||||
private Comic comic;
|
||||
|
||||
@OneToMany(fetch = FetchType.EAGER, mappedBy = "volume", cascade = CascadeType.REMOVE, orphanRemoval = true)
|
||||
@Nullable
|
||||
private List<StoryArc> storyArcs = new LinkedList<>();
|
||||
|
||||
@OneToMany(fetch = FetchType.EAGER, mappedBy = "volume", cascade = CascadeType.REMOVE, orphanRemoval = true)
|
||||
@Nullable
|
||||
private List<Issue> issues = new LinkedList<>();
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder result = new StringBuilder("Volume{");
|
||||
result.append("name=");
|
||||
result.append(name);
|
||||
result.append("comic=Comic{title=");
|
||||
result.append(comic.getTitle());
|
||||
result.append("}}");
|
||||
return result.toString();
|
||||
}
|
||||
}
|
||||
-39
@@ -1,39 +0,0 @@
|
||||
package de.thpeetz.kontor.comics.repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import de.thpeetz.kontor.comics.data.*;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
|
||||
public interface ComicRepository extends JpaRepository<Comic, String> {
|
||||
@Query("select c from Comic c " +
|
||||
"where lower(c.title) like lower(concat('%', :searchTerm, '%')) ")
|
||||
List<Comic> search(@Param("searchTerm") String searchTerm);
|
||||
|
||||
@Query("select c from Comic c " +
|
||||
"where lower(c.title) like lower(concat('%', :searchTerm, '%')) " +
|
||||
"AND c.currentOrder=:currentOrder AND c.completed=:completed")
|
||||
List<Comic> search(@Param("searchTerm") String searchTerm, Boolean currentOrder, Boolean completed);
|
||||
|
||||
Comic findByTitleAndPublisher(String title, Publisher publisher);
|
||||
|
||||
List<Comic> findByTitle(String title);
|
||||
|
||||
List<Comic> findByTitleIgnoreCase(String title);
|
||||
|
||||
List<Comic> findByCurrentOrderAndCompleted(Boolean currentOrder, Boolean completed);
|
||||
|
||||
List<Comic> findByCurrentOrder(Boolean currentOrder);
|
||||
|
||||
List<Comic> findByCompleted(Boolean completed);
|
||||
|
||||
@Query("select c from Comic c " +
|
||||
"where lower(c.title) like lower(concat('%', :searchTerm, '%')) AND c.currentOrder=:currentOrder")
|
||||
List<Comic> searchAndFilterByCurrentOrder(String searchTerm, Boolean currentOrder);
|
||||
|
||||
@Query("select c from Comic c " +
|
||||
"where lower(c.title) like lower(concat('%', :searchTerm, '%')) AND c.completed=:completed")
|
||||
List<Comic> searchAndFilterByCompleted(String searchTerm, Boolean completed);
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
package de.thpeetz.kontor.common.data;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.annotation.CreatedDate;
|
||||
import org.springframework.data.annotation.LastModifiedDate;
|
||||
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Slf4j
|
||||
@Getter
|
||||
@Setter
|
||||
@EqualsAndHashCode
|
||||
@MappedSuperclass
|
||||
@EntityListeners(AuditingEntityListener.class)
|
||||
public abstract class AbstractEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.UUID)
|
||||
private String id;
|
||||
|
||||
@Version
|
||||
private int version;
|
||||
|
||||
@CreatedDate
|
||||
private Date createdDate;
|
||||
|
||||
@LastModifiedDate
|
||||
private Date lastModifiedDate;
|
||||
|
||||
public void updateVersion(String value) {
|
||||
if (value == null) {
|
||||
log.info("value not given");
|
||||
return;
|
||||
}
|
||||
if (version != Integer.valueOf(value).intValue()) {
|
||||
log.info("update version");
|
||||
version = Integer.valueOf(value).intValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
package de.thpeetz.kontor.common.data;
|
||||
|
||||
import jakarta.annotation.Nullable;
|
||||
import jakarta.persistence.*;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.annotation.CreatedDate;
|
||||
import org.springframework.data.annotation.LastModifiedDate;
|
||||
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Slf4j
|
||||
@Getter
|
||||
@Setter
|
||||
@EqualsAndHashCode
|
||||
@MappedSuperclass
|
||||
@EntityListeners(AuditingEntityListener.class)
|
||||
public abstract class AbstractLinkEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.UUID)
|
||||
private String id;
|
||||
|
||||
@Version
|
||||
private int version;
|
||||
|
||||
@CreatedDate
|
||||
private Date createdDate;
|
||||
|
||||
@LastModifiedDate
|
||||
private Date lastModifiedDate;
|
||||
|
||||
@Nullable
|
||||
private String url;
|
||||
|
||||
private boolean review;
|
||||
|
||||
private boolean shouldDownload;
|
||||
|
||||
@Nullable
|
||||
private String title;
|
||||
|
||||
@Nullable
|
||||
private String cloudLink;
|
||||
|
||||
@Nullable
|
||||
private String fileName;
|
||||
|
||||
@Nullable
|
||||
private String path;
|
||||
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
package de.thpeetz.kontor.mailclient.data;
|
||||
|
||||
import de.thpeetz.kontor.common.data.AbstractEntity;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@Getter
|
||||
@Setter
|
||||
@Entity
|
||||
public class MailAccount extends AbstractEntity {
|
||||
|
||||
@NotEmpty
|
||||
private String host;
|
||||
|
||||
private Integer port;
|
||||
|
||||
@NotEmpty
|
||||
private String protocol;
|
||||
|
||||
private String userName;
|
||||
|
||||
private String password;
|
||||
|
||||
private Boolean startTls;
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package de.thpeetz.kontor.media.data;
|
||||
|
||||
import de.thpeetz.kontor.common.data.AbstractEntity;
|
||||
import jakarta.annotation.Nullable;
|
||||
import jakarta.persistence.*;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Slf4j
|
||||
@Entity
|
||||
public class MediaActor extends AbstractEntity {
|
||||
|
||||
@NotEmpty
|
||||
private String name;
|
||||
|
||||
@Nullable
|
||||
@Column(unique = true)
|
||||
private String url;
|
||||
|
||||
@OneToMany(fetch = FetchType.EAGER, mappedBy = "media_actor", cascade = CascadeType.REFRESH, orphanRemoval = true)
|
||||
@Nullable
|
||||
List<MediaActorFile> mediaActorFiles = new LinkedList<>();
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
package de.thpeetz.kontor.media.data;
|
||||
|
||||
import de.thpeetz.kontor.common.data.AbstractEntity;
|
||||
import jakarta.annotation.Nullable;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Index;
|
||||
import jakarta.persistence.OneToOne;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.persistence.UniqueConstraint;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@Getter
|
||||
@Setter
|
||||
@Entity
|
||||
@Table(indexes = @Index(columnList = "url"), uniqueConstraints = @UniqueConstraint(columnNames = {"url"}))
|
||||
public class MediaArticle extends AbstractEntity {
|
||||
|
||||
@NotEmpty
|
||||
private String url;
|
||||
|
||||
private boolean review;
|
||||
|
||||
@Nullable
|
||||
private String title;
|
||||
}
|
||||
-19
@@ -1,19 +0,0 @@
|
||||
package de.thpeetz.kontor.media.repository;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
|
||||
import de.thpeetz.kontor.media.data.MediaActor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface MediaActorRepository extends JpaRepository<MediaActor, String> {
|
||||
@Query("select m from MediaActor m " +
|
||||
"where lower(m.name) like lower(concat('%', :searchTerm, '%')) ")
|
||||
List<MediaActor> search(@Param("searchTerm") String searchTerm);
|
||||
|
||||
List<MediaActor> findByNameIgnoreCase(String name);
|
||||
|
||||
MediaActor findByName(String name);
|
||||
}
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
package de.thpeetz.kontor.media.repository;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
|
||||
import de.thpeetz.kontor.media.data.MediaArticle;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface MediaArticleRepository extends JpaRepository<MediaArticle, String> {
|
||||
@Query("select m from MediaArticle m " +
|
||||
"where lower(m.url) like lower(concat('%', :searchTerm, '%')) or lower(m.title) like lower(concat('%', :searchTerm, '%'))")
|
||||
List<MediaArticle> search(@Param("searchTerm") String searchTerm);
|
||||
}
|
||||
-31
@@ -1,31 +0,0 @@
|
||||
package de.thpeetz.kontor.media.repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
|
||||
import de.thpeetz.kontor.media.data.MediaFile;
|
||||
|
||||
public interface MediaFileRepository extends JpaRepository<MediaFile, String> {
|
||||
@Query("select m from MediaFile m " +
|
||||
"where lower(m.url) like lower(concat('%', :searchTerm, '%')) or lower(m.title) like lower(concat('%', :searchTerm, '%'))")
|
||||
List<MediaFile> search(@Param("searchTerm") String searchTerm);
|
||||
|
||||
List<MediaFile> findByShouldDownload(Boolean shouldDownload);
|
||||
|
||||
List<MediaFile> findByReview(Boolean review);
|
||||
|
||||
List<MediaFile> findByReviewAndShouldDownload(Boolean review, Boolean shouldDownload);
|
||||
|
||||
MediaFile findByUrl(String url);
|
||||
|
||||
@Query("select m from MediaFile m " +
|
||||
"where lower(m.url) like lower(concat('%', :searchTerm, '%')) or lower(m.title) like lower(concat('%', :searchTerm, '%')) " +
|
||||
"AND m.review=:review AND m.shouldDownload=:download")
|
||||
List<MediaFile> search(
|
||||
@Param("searchTerm") String searchTerm,
|
||||
@Param("review") boolean searchReview,
|
||||
@Param("download") boolean searchDownload);
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
package de.thpeetz.kontor.tysc.data;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
||||
import de.thpeetz.kontor.common.data.AbstractEntity;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Index;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.persistence.UniqueConstraint;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@ToString
|
||||
@EqualsAndHashCode(callSuper=false)
|
||||
@Entity
|
||||
@Table(indexes = {@Index(columnList = "cardNumber, year")},
|
||||
uniqueConstraints = {@UniqueConstraint(columnNames = { "cardNumber", "year", "vendor_id", "cardSet_id" })}
|
||||
)
|
||||
public class Card extends AbstractEntity {
|
||||
|
||||
private int cardNumber;
|
||||
|
||||
private int year;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "vendor_id")
|
||||
@NotNull
|
||||
@JsonIgnoreProperties({ "cards" })
|
||||
private Vendor vendor;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "cardSet_id")
|
||||
@NotNull
|
||||
@JsonIgnoreProperties({ "cards" })
|
||||
private CardSet cardSet;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "rooster_id")
|
||||
@NotNull
|
||||
@JsonIgnoreProperties({ "cards" })
|
||||
private Rooster rooster;
|
||||
|
||||
public String getVendorName() {
|
||||
return this.vendor.getName();
|
||||
}
|
||||
|
||||
public String getCardSetName() {
|
||||
return this.cardSet.getName();
|
||||
}
|
||||
|
||||
public String getPlayerName() {
|
||||
return this.rooster.getPlayer().getFullName();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
package de.thpeetz.kontor.tysc.data;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
||||
import de.thpeetz.kontor.common.data.AbstractEntity;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Index;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.persistence.UniqueConstraint;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@ToString
|
||||
@EqualsAndHashCode(callSuper=false)
|
||||
@Entity
|
||||
@Table(indexes = {@Index(columnList = "name, vendor_id")},
|
||||
uniqueConstraints = {@UniqueConstraint(columnNames = { "name", "vendor_id" })}
|
||||
)
|
||||
public class CardSet extends AbstractEntity {
|
||||
|
||||
@NotEmpty
|
||||
private String name;
|
||||
|
||||
@ManyToOne()
|
||||
@JoinColumn(name = "vendor_id")
|
||||
@NotNull
|
||||
@JsonIgnoreProperties({ "cardSets" })
|
||||
private Vendor vendor;
|
||||
|
||||
private boolean parallelSet = false;
|
||||
|
||||
private boolean insertSet = false;
|
||||
|
||||
public String getVendorName() {
|
||||
return vendor.getName();
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
package de.thpeetz.kontor.tysc.data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
||||
import de.thpeetz.kontor.common.data.AbstractEntity;
|
||||
import jakarta.annotation.Nullable;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.Index;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.OneToMany;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.persistence.UniqueConstraint;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@ToString
|
||||
@EqualsAndHashCode(callSuper=false)
|
||||
@Entity
|
||||
@Table(indexes = {@Index(columnList = "name, sport_id")},
|
||||
uniqueConstraints = {
|
||||
@UniqueConstraint(columnNames = { "name", "sport_id" }),
|
||||
@UniqueConstraint(columnNames = { "shortName", "sport_id" })
|
||||
}
|
||||
)
|
||||
public class FieldPosition extends AbstractEntity {
|
||||
|
||||
@NotEmpty
|
||||
private String name;
|
||||
|
||||
@NotEmpty
|
||||
private String shortName;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "sport_id")
|
||||
@NotNull
|
||||
@JsonIgnoreProperties({ "positions" })
|
||||
private Sport sport;
|
||||
|
||||
@OneToMany(fetch = FetchType.EAGER, mappedBy = "position")
|
||||
@Nullable
|
||||
private List<Rooster> roosters;
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
package de.thpeetz.kontor.tysc.data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import de.thpeetz.kontor.common.data.AbstractEntity;
|
||||
import jakarta.annotation.Nullable;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.Index;
|
||||
import jakarta.persistence.OneToMany;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.persistence.UniqueConstraint;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@ToString
|
||||
@EqualsAndHashCode(callSuper=false)
|
||||
@Entity
|
||||
@Table(indexes = {
|
||||
@Index(columnList = "firstName, lastName"),
|
||||
@Index(columnList = "lastName, firstName")
|
||||
}, uniqueConstraints = {
|
||||
@UniqueConstraint(columnNames = { "firstName", "lastName" })
|
||||
})
|
||||
public class Player extends AbstractEntity {
|
||||
|
||||
@NotNull
|
||||
private String firstName;
|
||||
|
||||
@NotNull
|
||||
private String lastName;
|
||||
|
||||
@OneToMany(fetch = FetchType.EAGER, mappedBy = "player")
|
||||
@Nullable
|
||||
private List<Rooster> roosters;
|
||||
|
||||
public String getFullName() {
|
||||
StringBuilder fullName = new StringBuilder();
|
||||
fullName.append(this.lastName);
|
||||
fullName.append(", ");
|
||||
fullName.append(this.firstName);
|
||||
return fullName.toString();
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
package de.thpeetz.kontor.tysc.data;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import de.thpeetz.kontor.common.data.AbstractEntity;
|
||||
import jakarta.annotation.Nullable;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.Index;
|
||||
import jakarta.persistence.OneToMany;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.persistence.UniqueConstraint;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@Getter
|
||||
@Setter
|
||||
@ToString
|
||||
@EqualsAndHashCode(callSuper=false)
|
||||
@Entity
|
||||
@Table(indexes = {@Index(columnList = "name")},
|
||||
uniqueConstraints = {@UniqueConstraint(columnNames = { "name" })}
|
||||
)
|
||||
public class Sport extends AbstractEntity {
|
||||
|
||||
@NotEmpty
|
||||
@Column(unique = true)
|
||||
private String name;
|
||||
|
||||
@OneToMany(fetch = FetchType.EAGER, mappedBy = "sport")
|
||||
@Nullable
|
||||
private List<Team> teams = new LinkedList<>();
|
||||
|
||||
@OneToMany(fetch = FetchType.EAGER, mappedBy = "sport")
|
||||
@Nullable
|
||||
private List<FieldPosition> positions = new LinkedList<>();
|
||||
|
||||
public String updateName(String value) {
|
||||
if (!this.getName().equals(value)) {
|
||||
this.setName(value);
|
||||
log.info("update name");
|
||||
return "updated " + this.getId() + " with " + value;
|
||||
}
|
||||
return "no changes for " + this.getId();
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
package de.thpeetz.kontor.tysc.data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import de.thpeetz.kontor.common.data.AbstractEntity;
|
||||
import jakarta.annotation.Nullable;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.Index;
|
||||
import jakarta.persistence.OneToMany;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.persistence.UniqueConstraint;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* Represents a vendor entity.
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Entity
|
||||
@Table(indexes = { @Index(columnList = "name") }, uniqueConstraints = { @UniqueConstraint(columnNames = "name") })
|
||||
public class Vendor extends AbstractEntity {
|
||||
|
||||
@NotEmpty
|
||||
private String name;
|
||||
|
||||
@OneToMany(fetch = FetchType.EAGER, mappedBy = "vendor")
|
||||
@Nullable
|
||||
private List<CardSet> cardSets;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Vendor{id=" + this.getId() + ", name=" + name + '}';
|
||||
}
|
||||
}
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
package de.thpeetz.kontor.tysc.repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import de.thpeetz.kontor.tysc.data.Player;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
|
||||
public interface PlayerRepository extends JpaRepository<Player, String> {
|
||||
|
||||
@Query("select p from Player p " +
|
||||
"where lower(p.firstName) like lower(concat('%', :searchTerm, '%')) " +
|
||||
"or lower(p.lastName) like lower(concat('%', :searchTerm, '%'))")
|
||||
List<Player> search(@Param("searchTerm") String searchTerm);
|
||||
|
||||
Player findByFirstNameAndLastName(String firstName, String lastName);
|
||||
}
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
package de.thpeetz.kontor.tysc.repository;
|
||||
|
||||
import de.thpeetz.kontor.tysc.data.FieldPosition;
|
||||
import de.thpeetz.kontor.tysc.data.Player;
|
||||
import de.thpeetz.kontor.tysc.data.Rooster;
|
||||
import de.thpeetz.kontor.tysc.data.Team;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
|
||||
public interface RoosterRepository extends JpaRepository<Rooster, String>{
|
||||
|
||||
@Query("SELECT r FROM Rooster r WHERE r.player = ?1 AND r.team = ?2 AND r.position = ?3 AND r.year = ?4")
|
||||
Rooster findByReferences(Player player, Team team, FieldPosition position, int year);
|
||||
}
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
package de.thpeetz.kontor.tysc.repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import de.thpeetz.kontor.tysc.data.Team;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
|
||||
/**
|
||||
* The repository interface for managing teams.
|
||||
*/
|
||||
public interface TeamRepository extends JpaRepository<Team, String> {
|
||||
|
||||
/**
|
||||
* Searches for teams based on a search term.
|
||||
*
|
||||
* @param searchTerm the search term to match against team names
|
||||
* @return a list of teams matching the search term
|
||||
*/
|
||||
@Query("select t from Team t " +
|
||||
"where lower(t.name) like lower(concat('%', :searchTerm, '%')) ")
|
||||
List<Team> search(@Param("searchTerm") String searchTerm);
|
||||
|
||||
Team findByName(String name);
|
||||
|
||||
List<Team> findByNameIgnoreCase(String name);
|
||||
}
|
||||
@@ -1,9 +1,3 @@
|
||||
#
|
||||
# https://help.github.com/articles/dealing-with-line-endings/
|
||||
#
|
||||
# Linux start script should use lf
|
||||
/gradlew text eol=lf
|
||||
|
||||
# These are Windows script files and should use crlf
|
||||
*.bat text eol=crlf
|
||||
|
||||
*.jar binary
|
||||
|
||||
+34
-29
@@ -1,33 +1,38 @@
|
||||
.gradle/
|
||||
.settings/
|
||||
node_modules
|
||||
HELP.md
|
||||
.gradle
|
||||
build/
|
||||
bin/
|
||||
!gradle/wrapper/gradle-wrapper.jar
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
# Ignore Gradle GUI config
|
||||
gradle-app.setting
|
||||
|
||||
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
|
||||
!gradle-wrapper.jar
|
||||
|
||||
.project
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
bin/
|
||||
!**/src/main/**/bin/
|
||||
!**/src/test/**/bin/
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
out/
|
||||
!**/src/main/**/out/
|
||||
!**/src/test/**/out/
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
.idea/
|
||||
*.lock
|
||||
logs/
|
||||
frontend/generated
|
||||
frontend/index.html
|
||||
package*.json
|
||||
tsconfig.json
|
||||
types.d.ts
|
||||
node_modules/
|
||||
vite.*
|
||||
kontor*Db
|
||||
tags*
|
||||
kontorHSQLDB*
|
||||
.vs/
|
||||
.winget
|
||||
src/main/resources/application-local.properties
|
||||
src/main/resources/application-prod.properties
|
||||
src/main/resources/application-*.yml
|
||||
/uploaded-files/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# ----------------------------------------------------------------------- #
|
||||
FROM docker.io/library/gradle:8.7-jdk AS builder
|
||||
FROM docker.io/library/gradle:9.5-jdk AS builder
|
||||
WORKDIR /
|
||||
COPY ./src/main/ ./src/main/
|
||||
COPY ./frontend/ ./frontend/
|
||||
@@ -10,7 +10,7 @@ COPY ./gradle/libs.versions.toml ./gradle/
|
||||
RUN gradle bootJar --no-daemon
|
||||
|
||||
# ----------------------------------------------------------------------- #
|
||||
FROM docker.io/alpine/java:21-jdk AS run
|
||||
FROM docker.io/alpine/java:25-jdk AS run
|
||||
|
||||
RUN mkdir -p /logs
|
||||
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
.PYHONY: all
|
||||
|
||||
all:
|
||||
./gradlew build
|
||||
|
||||
docker:
|
||||
./gradlew dockerImage
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
# kontor-spring
|
||||
|
||||
Kontor Anwendung mit Spring Boot und Vaadin
|
||||
+29
-169
@@ -1,97 +1,54 @@
|
||||
buildscript {
|
||||
configurations.classpath {
|
||||
resolutionStrategy.eachDependency { DependencyResolveDetails details ->
|
||||
if (details.requested.group == 'com.burgstaller' && details.requested.name == 'okhttp-digest' && details.requested.version == '1.10') {
|
||||
details.useTarget "io.github.rburgst:${details.requested.name}:1.21"
|
||||
details.because 'Dependency has moved'
|
||||
}
|
||||
}
|
||||
}
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven { setUrl("https://nexus.thpeetz.de/repository/maven-central") }
|
||||
maven { setUrl("https://maven.vaadin.com/vaadin-prereleases") }
|
||||
maven { setUrl("https://repo.spring.io/milestone") }
|
||||
}
|
||||
}
|
||||
|
||||
plugins {
|
||||
id 'java'
|
||||
id 'application'
|
||||
id 'maven-publish'
|
||||
id "com.google.cloud.artifactregistry.gradle-plugin" version "2.2.0"
|
||||
id 'jvm-test-suite'
|
||||
id 'jacoco'
|
||||
id 'test-report-aggregation'
|
||||
id 'jacoco-report-aggregation'
|
||||
alias(libs.plugins.spring.boot)
|
||||
alias(libs.plugins.spring.dependencies)
|
||||
alias(libs.plugins.vaadin)
|
||||
alias(libs.plugins.lombok)
|
||||
//alias(libs.plugins.asciidoctorPdf)
|
||||
//alias(libs.plugins.asciidoctorConvert)
|
||||
//alias(libs.plugins.asciidoctorGems)
|
||||
//id "de.infolektuell.typst" version "0.8.0"
|
||||
}
|
||||
|
||||
java {
|
||||
toolchain {
|
||||
languageVersion = JavaLanguageVersion.of(25)
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven { setUrl("https://nexus.thpeetz.de/repository/maven-central") }
|
||||
mavenCentral()
|
||||
//ruby.gems()
|
||||
maven { setUrl("https://maven.vaadin.com/vaadin-prereleases") }
|
||||
maven { setUrl("https://repo.spring.io/milestone") }
|
||||
maven { setUrl("https://maven.vaadin.com/vaadin-addons") }
|
||||
}
|
||||
|
||||
java {
|
||||
sourceCompatibility = JavaVersion.VERSION_21
|
||||
}
|
||||
|
||||
configurations {
|
||||
developmentOnly
|
||||
runtimeClasspath {
|
||||
extendsFrom developmentOnly
|
||||
}
|
||||
ext {
|
||||
set('vaadinVersion', "25.2.6")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.vaadin:vaadin-core'
|
||||
implementation 'com.vaadin:vaadin-spring-boot-starter'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-actuator'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-artemis'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-security'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-validation'
|
||||
implementation 'org.apache.camel.springboot:camel-spring-boot-starter'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-security'
|
||||
developmentOnly 'com.vaadin:vaadin-dev'
|
||||
implementation 'com.vaadin:vaadin-spring-boot-starter'
|
||||
implementation 'org.apache.camel.springboot:camel-spring-boot-starter:4.22.0'
|
||||
implementation 'org.apache.camel.springboot:camel-jms-starter'
|
||||
implementation 'org.apache.activemq:artemis-jakarta-client'
|
||||
//implementation libs.artemis
|
||||
implementation 'org.springframework.boot:spring-boot-starter-actuator'
|
||||
developmentOnly 'org.springframework.boot:spring-boot-devtools'
|
||||
implementation 'io.micrometer:micrometer-registry-prometheus'
|
||||
implementation 'org.springframework.security:spring-security-oauth2-jose'
|
||||
implementation 'org.springframework.security:spring-security-oauth2-resource-server'
|
||||
implementation 'com.h2database:h2'
|
||||
implementation libs.hsqldb
|
||||
implementation 'org.postgresql:postgresql'
|
||||
//runtimeOnly 'org.mariadb.jdbc:mariadb-java-client'
|
||||
implementation libs.hypersistence
|
||||
implementation libs.mail
|
||||
implementation libs.jackson
|
||||
implementation libs.gson
|
||||
implementation libs.json
|
||||
implementation 'org.hibernate.orm:hibernate-community-dialects'
|
||||
testImplementation('org.springframework.boot:spring-boot-starter-test') {
|
||||
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
|
||||
}
|
||||
testImplementation 'org.springframework.security:spring-security-test'
|
||||
testImplementation 'com.vaadin:vaadin-testbench-junit5'
|
||||
testImplementation 'io.projectreactor:reactor-test'
|
||||
testImplementation 'org.apache.camel:camel-test-spring-junit5'
|
||||
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
|
||||
compileOnly 'org.projectlombok:lombok'
|
||||
developmentOnly 'org.springframework.boot:spring-boot-devtools'
|
||||
runtimeOnly 'io.micrometer:micrometer-registry-prometheus'
|
||||
implementation 'org.springframework.security:spring-security-oauth2-jose'
|
||||
implementation 'org.springframework.security:spring-security-oauth2-resource-server'
|
||||
runtimeOnly 'org.postgresql:postgresql'
|
||||
runtimeOnly 'org.xerial:sqlite-jdbc'
|
||||
//implementation 'org.hibernate.orm:hibernate-community-dialects'
|
||||
annotationProcessor 'org.projectlombok:lombok'
|
||||
//asciidoctorGems libs.rouge
|
||||
//asciidoctorGems libs.diagram
|
||||
annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
|
||||
testImplementation 'org.springframework.boot:spring-boot-starter-artemis-test'
|
||||
testImplementation 'org.springframework.boot:spring-boot-starter-data-jpa-test'
|
||||
testImplementation 'org.springframework.boot:spring-boot-starter-security-test'
|
||||
testCompileOnly 'org.projectlombok:lombok'
|
||||
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
|
||||
testAnnotationProcessor 'org.projectlombok:lombok'
|
||||
}
|
||||
|
||||
dependencyManagement {
|
||||
@@ -117,112 +74,15 @@ publishing {
|
||||
password = project.findProperty('nexusPassword')
|
||||
}
|
||||
}
|
||||
// maven {
|
||||
// name = "gitlabPackageRegistry"
|
||||
// url = uri("https://gitlab.com/api/v4/projects/64726715/packages/maven")
|
||||
// credentials(PasswordCredentials)
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
application {
|
||||
mainClass = 'de.thpeetz.kontor.Application'
|
||||
}
|
||||
|
||||
bootRun {
|
||||
args = ["--spring.profiles.active=${project.properties['profile'] ?: 'prod'}"]
|
||||
}
|
||||
|
||||
task dockerImage(type: Exec) {
|
||||
dependsOn(bootJar)
|
||||
commandLine "docker", "build", ".", "-t", "kontor:${project.version}"
|
||||
}
|
||||
|
||||
vaadin {
|
||||
productionMode = true
|
||||
}
|
||||
|
||||
testing {
|
||||
suites {
|
||||
configureEach {
|
||||
useJUnitJupiter()
|
||||
dependencies {
|
||||
implementation project()
|
||||
implementation 'com.vaadin:vaadin-core'
|
||||
implementation 'com.vaadin:vaadin-spring-boot-starter'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
|
||||
implementation 'com.h2database:h2'
|
||||
implementation libs.hsqldb
|
||||
implementation libs.sqlite.jdbc
|
||||
//runtimeOnly 'com.mysql:mysql-connector-j'
|
||||
runtimeOnly 'org.mariadb.jdbc:mariadb-java-client'
|
||||
implementation('org.springframework.boot:spring-boot-starter-test') {
|
||||
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
|
||||
}
|
||||
implementation 'org.springframework.security:spring-security-test'
|
||||
implementation 'com.vaadin:vaadin-testbench-junit5'
|
||||
implementation 'io.projectreactor:reactor-test'
|
||||
runtimeOnly 'org.junit.platform:junit-platform-launcher'
|
||||
}
|
||||
}
|
||||
test(JvmTestSuite) {
|
||||
testType = TestSuiteType.UNIT_TEST
|
||||
targets {
|
||||
all {
|
||||
testTask.configure {
|
||||
reports {
|
||||
junitXml {
|
||||
outputPerTestCase = true // defaults to false
|
||||
mergeReruns = true // defaults to false
|
||||
}
|
||||
}
|
||||
finalizedBy(jacocoTestReport)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
integrationTest(JvmTestSuite) {
|
||||
testType = "view-test"
|
||||
targets {
|
||||
all {
|
||||
testTask.configure {
|
||||
shouldRunAfter(test)
|
||||
finalizedBy(jacocoTestReport)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.named('check') {
|
||||
dependsOn(testing.suites.integrationTest)
|
||||
dependsOn(testing.suites.test)
|
||||
dependsOn tasks.named('testAggregateTestReport', TestReport)
|
||||
dependsOn tasks.named('integrationTestAggregateTestReport', TestReport)
|
||||
}
|
||||
|
||||
|
||||
jacocoTestReport {
|
||||
dependsOn test, integrationTest
|
||||
reports {
|
||||
xml.required = true
|
||||
csv.required = false
|
||||
}
|
||||
}
|
||||
|
||||
reporting {
|
||||
reports {
|
||||
testAggregateTestReport(AggregateTestReport) {
|
||||
testType = TestSuiteType.UNIT_TEST
|
||||
}
|
||||
integrationTestAggregateTestReport(AggregateTestReport) {
|
||||
testType = "view-test"
|
||||
}
|
||||
integrationTestCodeCoverageReport(JacocoCoverageReport) {
|
||||
testType = "view-test"
|
||||
}
|
||||
}
|
||||
tasks.named('test') {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
|
||||
wrapper {
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"lumoImports" : [ "typography", "color", "spacing", "badge", "utility" ]
|
||||
}
|
||||
@@ -3,3 +3,4 @@ version=0.3.0-SNAPSHOT
|
||||
group=de.thpeetz
|
||||
nexusUser=kontor
|
||||
nexusPassword=kontorNexus
|
||||
profile=local
|
||||
@@ -1,24 +1,15 @@
|
||||
[versions]
|
||||
gradle = "8.6"
|
||||
args4j = "2.33"
|
||||
commonscli = "1.5.0"
|
||||
gradle = "9.5.1"
|
||||
springdependencies = "1.1.7"
|
||||
springboot = "4.1.0"
|
||||
vaadin = "25.2.6"
|
||||
junit = "5.8.2"
|
||||
logback = "1.1.2"
|
||||
mockito = "1.9.5"
|
||||
picoli = "4.7.0"
|
||||
slf4j = "1.7.22"
|
||||
hsqldb = "2.7.1"
|
||||
sqlite = "3.25.2"
|
||||
spotbugs = "6.0.7"
|
||||
#asciidoctor = "4.0.2"
|
||||
#rouge = "3.15.0"
|
||||
#diagram = "2.2.2"
|
||||
#diagram = "2.3.1"
|
||||
sonarqube = "3.3"
|
||||
cimtConventions = "1.0.0-SNAPSHOT"
|
||||
springboot = "3.2.5"
|
||||
springdependencies = "1.1.4"
|
||||
vaadin = "24.4.23"
|
||||
camel = "4.10.6"
|
||||
artemis = "2.41.0"
|
||||
lombok = "8.11"
|
||||
@@ -26,16 +17,15 @@ gson = "2.9.0"
|
||||
jackson = "2.16.1"
|
||||
json_simple = "1.1.1"
|
||||
mail = "1.6.2"
|
||||
hypersistence = "3.9.10"
|
||||
hypersistence = "3.15.4"
|
||||
|
||||
[libraries]
|
||||
args4j = { module = "args4j:args4j", version.ref = "args4j" }
|
||||
commonscli = { module = "commons-cli:commons-cli", version.ref = "commonscli" }
|
||||
vaadin-bom = { group = "com.vaadin", name = "vaadin-bom", version.ref = "vaadin" }
|
||||
camel-bom = { module = "org.apache.camel.springboot:camel-spring-boot-bom", version.ref = "camel"}
|
||||
artemis = { module = "org.apache.activemq:artemis-jms-server", version.ref = "artemis" }
|
||||
junit = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit" }
|
||||
logbackCore = { module = "ch.qos.logback:logback-core", version.ref = "logback" }
|
||||
logbackClassic = { module = "ch.qos.logback:logback-classic", version.ref = "logback" }
|
||||
mockito = { module = "org.mockito:mockito-all", version.ref = "mockito" }
|
||||
picocli = { module = "info.picocli:picocli", version.ref = "picoli" }
|
||||
slf4j = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" }
|
||||
hsqldb = { module = "org.hsqldb:hsqldb", version.ref = "hsqldb" }
|
||||
gson = { module = "com.google.code.gson:gson", version.ref = "gson" }
|
||||
@@ -43,15 +33,7 @@ jackson = { module = "com.fasterxml.jackson.core:jackson-databind", version.ref
|
||||
json = { module = "com.googlecode.json-simple:json-simple", version.ref ="json_simple" }
|
||||
mail = { module = "com.sun.mail:javax.mail", version.ref ="mail" }
|
||||
sqlite-jdbc = { module = "org.xerial:sqlite-jdbc", version.ref = "sqlite" }
|
||||
hypersistence = { module = "io.hypersistence:hypersistence-utils-hibernate-63", version.ref = "hypersistence" }
|
||||
vaadin-bom = { module = "com.vaadin:vaadin-bom", version.ref = "vaadin" }
|
||||
camel-bom = { module = "org.apache.camel.springboot:camel-spring-boot-bom", version.ref = "camel"}
|
||||
artemis = { module = "org.apache.activemq:artemis-jms-server", version.ref = "artemis" }
|
||||
#asciidoctorGradleJvmGems = { module = "org.asciidoctor:asciidoctor-gradle-jvm-gems", version.ref= "asciidoctor" }
|
||||
#asciidoctorGradleJvm = { module = "org.asciidoctor:asciidoctor-gradle-jvm", version.ref= "asciidoctor" }
|
||||
#asciidoctorGradleJvmPdf = { module = "org.asciidoctor:asciidoctor-gradle-jvm-pdf", version.ref= "asciidoctor" }
|
||||
#rouge = { module = "rubygems:rouge", version.ref = "rouge" }
|
||||
#diagram = { module = "rubygems:asciidoctor-diagram", version.ref = "diagram" }
|
||||
hypersistence = { module = "io.hypersistence:hypersistence-utils-hibernate-73", version.ref = "hypersistence" }
|
||||
|
||||
[bundles]
|
||||
logback = ["logbackCore", "logbackClassic"]
|
||||
@@ -59,13 +41,6 @@ logback = ["logbackCore", "logbackClassic"]
|
||||
[plugins]
|
||||
spotbugs = { id = "com.github.spotbugs", version.ref = "spotbugs" }
|
||||
sonarqube = { id = "org.sonarqube", version.ref = "sonarqube" }
|
||||
#asciidoctorPdf = { id = "org.asciidoctor.jvm.pdf", version.ref = "asciidoctor" }
|
||||
#asciidoctorConvert = { id = "org.asciidoctor.jvm.convert", version.ref = "asciidoctor" }
|
||||
#asciidoctorGems = { id = "org.asciidoctor.jvm.gems", version.ref = "asciidoctor" }
|
||||
javaConvention = { id = "de.cimt.java-conventions", version.ref = "cimtConventions" }
|
||||
applicationConvention = { id = "de.cimt.application-conventions", version.ref = "cimtConventions" }
|
||||
libraryConvention = { id = "de.cimt.library-conventions", version.ref = "cimtConventions" }
|
||||
#asciidoctorConvention = { id = "de.cimt.asciidoctor-conventions", version.ref = "cimtConventions" }
|
||||
spring-boot = { id = "org.springframework.boot", version.ref = "springboot"}
|
||||
spring-dependencies = { id = "io.spring.dependency-management", version.ref = "springdependencies" }
|
||||
vaadin = { id = "com.vaadin", version.ref = "vaadin" }
|
||||
|
||||
BIN
Binary file not shown.
+3
-1
@@ -1,7 +1,9 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip
|
||||
networkTimeout=10000
|
||||
retries=0
|
||||
retryBackOffMs=500
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
||||
Vendored
+7
-8
@@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright © 2015-2021 the original authors.
|
||||
# Copyright © 2015 the original authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
@@ -15,6 +15,8 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
@@ -55,7 +57,7 @@
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# https://github.com/gradle/gradle/blob/3d91ce3b8caaf77ad09f381f43615b715b53f72c/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
@@ -84,7 +86,7 @@ done
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
||||
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
@@ -112,7 +114,6 @@ case "$( uname )" in #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
@@ -170,7 +171,6 @@ fi
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if "$cygwin" || "$msys" ; then
|
||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||
|
||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||
|
||||
@@ -203,15 +203,14 @@ fi
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Collect all arguments for the java command:
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||
# and any embedded shellness will be escaped.
|
||||
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||
# treated as '${Hostname}' itself on the command line.
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-classpath "$CLASSPATH" \
|
||||
org.gradle.wrapper.GradleWrapperMain \
|
||||
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
|
||||
"$@"
|
||||
|
||||
# Stop when "xargs" is not available.
|
||||
|
||||
Vendored
+12
-22
@@ -13,6 +13,8 @@
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
@rem SPDX-License-Identifier: Apache-2.0
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@@ -21,8 +23,8 @@
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
@rem Set local scope for the variables, and ensure extensions are enabled
|
||||
setlocal EnableExtensions
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
@@ -49,7 +51,7 @@ echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
"%COMSPEC%" /c exit 1
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
@@ -63,30 +65,18 @@ echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
"%COMSPEC%" /c exit 1
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
@rem endlocal doesn't take effect until after the line is parsed and variables are expanded
|
||||
@rem which allows us to clear the local environment before executing the java command
|
||||
endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
:exitWithErrorLevel
|
||||
@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts
|
||||
"%COMSPEC%" /c exit %ERRORLEVEL%
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,25 +1 @@
|
||||
pluginManagement {
|
||||
resolutionStrategy {
|
||||
eachPlugin {
|
||||
if (requested.id.id == 'org.springframework.boot') {
|
||||
useModule("org.springframework.boot:spring-boot-gradle-plugin:${requested.version}")
|
||||
}
|
||||
if (requested.id.id == 'org.gradle.toolchains.foojay-resolver') {
|
||||
useModule("org.gradle.toolchains.foojay-resolver-convention:0.4.0")
|
||||
}
|
||||
}
|
||||
}
|
||||
repositories {
|
||||
gradlePluginPortal()
|
||||
maven { setUrl("https://nexus.thpeetz.de/repository/maven-central") }
|
||||
mavenCentral()
|
||||
maven { setUrl("https://maven.vaadin.com/vaadin-prereleases") }
|
||||
maven { setUrl("https://repo.spring.io/milestone") }
|
||||
maven { url 'https://plugins.gradle.org/m2/' }
|
||||
}
|
||||
// plugins {
|
||||
// id 'com.vaadin' version "${vaadinVersion}"
|
||||
// }
|
||||
}
|
||||
|
||||
rootProject.name = 'kontor-spring'
|
||||
|
||||
-41
@@ -1,41 +0,0 @@
|
||||
package de.thpeetz.kontor.comics.views;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import com.vaadin.flow.component.grid.Grid;
|
||||
|
||||
import de.thpeetz.kontor.comics.data.Artist;
|
||||
|
||||
@SpringBootTest
|
||||
class ArtistViewTest {
|
||||
|
||||
@Autowired
|
||||
private ArtistView artistView;
|
||||
|
||||
@Test
|
||||
void formShownWhenArtistSelected() {
|
||||
Grid<Artist> grid = artistView.getGrid();
|
||||
Artist firstArtist = getFirstItem(grid);
|
||||
|
||||
ArtistForm form = artistView.getForm();
|
||||
|
||||
assertFalse(form.isVisible());
|
||||
grid.asSingleSelect().setValue(firstArtist);
|
||||
assertTrue(form.isVisible());
|
||||
assertEquals(firstArtist.getName(), form.name.getValue());
|
||||
}
|
||||
|
||||
private Artist getFirstItem(Grid<Artist> grid) {
|
||||
int count = grid.getListDataView().getItemCount();
|
||||
List<Artist> artists = grid.getListDataView().getItems().collect(Collectors.toList());
|
||||
assertEquals(5, count);
|
||||
return artists.get(0);
|
||||
}
|
||||
}
|
||||
-63
@@ -1,63 +0,0 @@
|
||||
package de.thpeetz.kontor.comics.views;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import de.thpeetz.kontor.comics.data.Artist;
|
||||
|
||||
@SpringBootTest
|
||||
class ArtistformTest {
|
||||
|
||||
private Artist artist1;
|
||||
private static final String ARTISTNAME= "Lee, Stan";
|
||||
|
||||
@BeforeEach
|
||||
void setupData() {
|
||||
artist1 = new Artist();
|
||||
artist1.setName(ARTISTNAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
void formFieldsPopulated() {
|
||||
ArtistForm form = new ArtistForm();
|
||||
form.setArtist(artist1);
|
||||
assertEquals(ARTISTNAME, form.name.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveEventHasCorrectValues() {
|
||||
ArtistForm form = new ArtistForm();
|
||||
Artist artist = new Artist();
|
||||
form.setArtist(artist);
|
||||
form.name.setValue(ARTISTNAME);
|
||||
|
||||
AtomicReference<Artist> savedArtistReference = new AtomicReference<>(null);
|
||||
form.addSaveListener(e -> {
|
||||
savedArtistReference.set(e.getArtist());
|
||||
});
|
||||
form.save.click();
|
||||
Artist savedArtist = savedArtistReference.get();
|
||||
assertEquals(ARTISTNAME, savedArtist.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
void deleteEventHasCorrectValues() {
|
||||
ArtistForm form = new ArtistForm();
|
||||
Artist artist = new Artist();
|
||||
form.setArtist(artist);
|
||||
form.name.setValue(ARTISTNAME);
|
||||
|
||||
AtomicReference<Artist> deletedArtistReference = new AtomicReference<>(null);
|
||||
form.addDeleteListener(e -> {
|
||||
deletedArtistReference.set(e.getArtist());
|
||||
});
|
||||
form.delete.click();
|
||||
Artist deletedArtist = deletedArtistReference.get();
|
||||
assertEquals(ARTISTNAME, deletedArtist.getName());
|
||||
}
|
||||
}
|
||||
-43
@@ -1,43 +0,0 @@
|
||||
package de.thpeetz.kontor.comics.views;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import com.vaadin.flow.component.grid.Grid;
|
||||
|
||||
import de.thpeetz.kontor.comics.data.Comic;
|
||||
|
||||
@SpringBootTest
|
||||
public class ComicViewTest {
|
||||
|
||||
@Autowired
|
||||
private ComicView comicView;
|
||||
|
||||
@Test
|
||||
void formShownWhenComicSelected() {
|
||||
Grid<Comic> grid = comicView.getGrid();
|
||||
Comic firstComic = getFirstItem(grid);
|
||||
|
||||
ComicForm form = comicView.getForm();
|
||||
|
||||
assertFalse(form.isVisible());
|
||||
grid.asSingleSelect().setValue(firstComic);
|
||||
assertTrue(form.isVisible());
|
||||
assertEquals(firstComic.getTitle(), form.title.getValue());
|
||||
}
|
||||
|
||||
private Comic getFirstItem(Grid<Comic> grid) {
|
||||
int count = grid.getListDataView().getItemCount();
|
||||
List<Comic> comics = grid.getListDataView().getItems().collect(Collectors.toList());
|
||||
assertEquals(169, count);
|
||||
return comics.get(0);
|
||||
}
|
||||
}
|
||||
-43
@@ -1,43 +0,0 @@
|
||||
package de.thpeetz.kontor.comics.views;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import com.vaadin.flow.component.grid.Grid;
|
||||
|
||||
import de.thpeetz.kontor.comics.data.ComicWork;
|
||||
|
||||
@SpringBootTest
|
||||
class ComicWorkViewTest {
|
||||
|
||||
@Autowired
|
||||
private ComicWorkView comicWorkView;
|
||||
|
||||
@Test
|
||||
void formShownWhenComicSelected() {
|
||||
Grid<ComicWork> grid = comicWorkView.getGrid();
|
||||
ComicWork firstComicWork = getFirstItem(grid);
|
||||
|
||||
ComicWorkForm form = comicWorkView.getForm();
|
||||
|
||||
assertFalse(form.isVisible());
|
||||
grid.asSingleSelect().setValue(firstComicWork);
|
||||
assertTrue(form.isVisible());
|
||||
assertEquals(firstComicWork.getComic(), form.comic.getValue());
|
||||
}
|
||||
|
||||
private ComicWork getFirstItem(Grid<ComicWork> grid) {
|
||||
int count = grid.getListDataView().getItemCount();
|
||||
List<ComicWork> comicWorks = grid.getListDataView().getItems().collect(Collectors.toList());
|
||||
assertEquals(18, count);
|
||||
return comicWorks.get(0);
|
||||
}
|
||||
}
|
||||
-43
@@ -1,43 +0,0 @@
|
||||
package de.thpeetz.kontor.comics.views;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import com.vaadin.flow.component.grid.Grid;
|
||||
|
||||
import de.thpeetz.kontor.comics.data.Issue;
|
||||
|
||||
@SpringBootTest
|
||||
public class IssueViewTest {
|
||||
|
||||
@Autowired
|
||||
private IssueView issueView;
|
||||
|
||||
@Test
|
||||
void formShownWhenIssueSelected() {
|
||||
Grid<Issue> grid = issueView.getGrid();
|
||||
Issue firstIssue = getFirstItem(grid);
|
||||
|
||||
IssueForm form = issueView.getForm();
|
||||
|
||||
assertFalse(form.isVisible());
|
||||
grid.asSingleSelect().setValue(firstIssue);
|
||||
assertTrue(form.isVisible());
|
||||
assertEquals(firstIssue.getIssueNumber(), form.issueNumber.getValue());
|
||||
}
|
||||
|
||||
private Issue getFirstItem(Grid<Issue> grid) {
|
||||
int count = grid.getListDataView().getItemCount();
|
||||
List<Issue> issues = grid.getListDataView().getItems().collect(Collectors.toList());
|
||||
assertEquals(750, count);
|
||||
return issues.get(0);
|
||||
}
|
||||
}
|
||||
-41
@@ -1,41 +0,0 @@
|
||||
package de.thpeetz.kontor.comics.views;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import com.vaadin.flow.component.grid.Grid;
|
||||
|
||||
import de.thpeetz.kontor.comics.data.Publisher;
|
||||
|
||||
@SpringBootTest
|
||||
class PublisherViewTest {
|
||||
|
||||
@Autowired
|
||||
private PublisherView publisherView;
|
||||
|
||||
@Test
|
||||
void formShownWhenPublisherSelected() {
|
||||
Grid<Publisher> grid = publisherView.getGrid();
|
||||
Publisher firstPublisher = getFirstItem(grid);
|
||||
|
||||
PublisherForm form = publisherView.getForm();
|
||||
|
||||
assertFalse(form.isVisible());
|
||||
grid.asSingleSelect().setValue(firstPublisher);
|
||||
assertTrue(form.isVisible());
|
||||
assertEquals(firstPublisher.getName(), form.name.getValue());
|
||||
}
|
||||
|
||||
private Publisher getFirstItem(Grid<Publisher> grid) {
|
||||
int count = grid.getListDataView().getItemCount();
|
||||
List<Publisher> publishers = grid.getListDataView().getItems().collect(Collectors.toList());
|
||||
assertEquals(18, count);
|
||||
return publishers.get(0);
|
||||
}
|
||||
}
|
||||
-43
@@ -1,43 +0,0 @@
|
||||
package de.thpeetz.kontor.comics.views;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import com.vaadin.flow.component.grid.Grid;
|
||||
|
||||
import de.thpeetz.kontor.comics.data.StoryArc;
|
||||
|
||||
@SpringBootTest
|
||||
class StoryArcViewTest {
|
||||
|
||||
@Autowired
|
||||
private StoryArcView storyArcView;
|
||||
|
||||
@Test
|
||||
void formShownWhenStoryArcSelected() {
|
||||
Grid<StoryArc> grid = storyArcView.getGrid();
|
||||
StoryArc firstStoryArc = getFirstItem(grid);
|
||||
|
||||
StoryArcForm form = storyArcView.getForm();
|
||||
|
||||
assertFalse(form.isVisible());
|
||||
grid.asSingleSelect().setValue(firstStoryArc);
|
||||
assertTrue(form.isVisible());
|
||||
assertEquals(firstStoryArc.getName(), form.name.getValue());
|
||||
}
|
||||
|
||||
private StoryArc getFirstItem(Grid<StoryArc> grid) {
|
||||
int count = grid.getListDataView().getItemCount();
|
||||
List<StoryArc> storyArcs = grid.getListDataView().getItems().collect(Collectors.toList());
|
||||
assertEquals(3, count);
|
||||
return storyArcs.get(0);
|
||||
}
|
||||
}
|
||||
-46
@@ -1,46 +0,0 @@
|
||||
package de.thpeetz.kontor.comics.views;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import com.vaadin.flow.component.grid.Grid;
|
||||
|
||||
import de.thpeetz.kontor.comics.data.TradePaperback;
|
||||
|
||||
@SpringBootTest
|
||||
class TradePaperbackViewTest {
|
||||
|
||||
@Autowired
|
||||
private TradePaperbackView tradePaperbackView;
|
||||
|
||||
@Test
|
||||
void formShownWhenVolumeSelected() {
|
||||
Grid<TradePaperback> grid = tradePaperbackView.getGrid();
|
||||
|
||||
TradePaperback firstTradePaperback = getFirstItem(grid);
|
||||
|
||||
TradePaperBackForm form = tradePaperbackView.getForm();
|
||||
assertFalse(form.isVisible());
|
||||
|
||||
if (firstTradePaperback != null) {
|
||||
grid.asSingleSelect().setValue(firstTradePaperback);
|
||||
assertTrue(form.isVisible());
|
||||
assertEquals(firstTradePaperback.getName(), form.name.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
private TradePaperback getFirstItem(Grid<TradePaperback> grid) {
|
||||
int count = grid.getListDataView().getItemCount();
|
||||
List<TradePaperback> tradePaperbacks = grid.getListDataView().getItems().collect(Collectors.toList());
|
||||
assertEquals(40, count);
|
||||
return tradePaperbacks.get(0);
|
||||
}
|
||||
}
|
||||
-50
@@ -1,50 +0,0 @@
|
||||
package de.thpeetz.kontor.comics.views;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import com.vaadin.flow.component.grid.Grid;
|
||||
|
||||
import de.thpeetz.kontor.comics.data.Volume;
|
||||
|
||||
@SpringBootTest
|
||||
class VolumeViewTest {
|
||||
|
||||
@Autowired
|
||||
private VolumeView volumeView;
|
||||
|
||||
@Test
|
||||
void formShownWhenVolumeSelected() {
|
||||
Grid<Volume> grid = volumeView.getGrid();
|
||||
|
||||
Volume firstVolume = getFirstItem(grid);
|
||||
|
||||
VolumeForm form = volumeView.getForm();
|
||||
assertFalse(form.isVisible());
|
||||
|
||||
if (firstVolume != null) {
|
||||
grid.asSingleSelect().setValue(firstVolume);
|
||||
assertTrue(form.isVisible());
|
||||
assertEquals(firstVolume.getName(), form.name.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
private Volume getFirstItem(Grid<Volume> grid) {
|
||||
int count = grid.getListDataView().getItemCount();
|
||||
List<Volume> volumes = grid.getListDataView().getItems().collect(Collectors.toList());
|
||||
assertEquals(0, count);
|
||||
if (count > 0) {
|
||||
return volumes.get(0);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
-49
@@ -1,49 +0,0 @@
|
||||
package de.thpeetz.kontor.comics.views;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import com.vaadin.flow.component.grid.Grid;
|
||||
|
||||
import de.thpeetz.kontor.comics.data.Worktype;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@SpringBootTest
|
||||
class WorktypeViewTest {
|
||||
|
||||
@Autowired
|
||||
private WorktypeView worktypeView;
|
||||
|
||||
@Test
|
||||
void formShownWhenWorktypeSelected() {
|
||||
Grid<Worktype> grid = worktypeView.getGrid();
|
||||
|
||||
Worktype firstWorktype = getFirstItem(grid);
|
||||
|
||||
WorktypeForm form = worktypeView.getForm();
|
||||
assertFalse(form.isVisible());
|
||||
|
||||
if (firstWorktype != null) {
|
||||
grid.asSingleSelect().setValue(firstWorktype);
|
||||
assertTrue(form.isVisible());
|
||||
assertEquals(firstWorktype.getName(), form.name.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
private Worktype getFirstItem(Grid<Worktype> grid) {
|
||||
int count = grid.getListDataView().getItemCount();
|
||||
List<Worktype> worktypes = grid.getListDataView().getItems().collect(Collectors.toList());
|
||||
log.info("found worktypes: {}", worktypes);
|
||||
assertEquals(3, count);
|
||||
return worktypes.get(0);
|
||||
}
|
||||
}
|
||||
-43
@@ -1,43 +0,0 @@
|
||||
package de.thpeetz.kontor.tysc.views;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import com.vaadin.flow.component.grid.Grid;
|
||||
|
||||
import de.thpeetz.kontor.tysc.data.CardSet;
|
||||
|
||||
@SpringBootTest
|
||||
class CardSetViewTest {
|
||||
|
||||
@Autowired
|
||||
private CardSetView cardSetView;
|
||||
|
||||
@Test
|
||||
void formShownWhenCardSetSelected() {
|
||||
Grid<CardSet> grid = cardSetView.getGrid();
|
||||
CardSet firstCardSet = getFirstItem(grid);
|
||||
|
||||
CardSetForm form = cardSetView.getForm();
|
||||
|
||||
assertFalse(form.isVisible());
|
||||
grid.asSingleSelect().setValue(firstCardSet);
|
||||
assertTrue(form.isVisible());
|
||||
assertEquals(firstCardSet.getName(), form.name.getValue());
|
||||
}
|
||||
|
||||
private CardSet getFirstItem(Grid<CardSet> grid) {
|
||||
int count = grid.getListDataView().getItemCount();
|
||||
List<CardSet> cardSets = grid.getListDataView().getItems().collect(Collectors.toList());
|
||||
assertEquals(15, count);
|
||||
return cardSets.get(0);
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
package de.thpeetz.kontor.tysc.views;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import com.vaadin.flow.component.grid.Grid;
|
||||
|
||||
import de.thpeetz.kontor.tysc.data.Card;
|
||||
|
||||
@SpringBootTest
|
||||
class CardViewTest {
|
||||
|
||||
@Autowired
|
||||
private CardView cardView;
|
||||
|
||||
@Test
|
||||
void formShownWhenCardSelected() {
|
||||
Grid<Card> grid = cardView.getGrid();
|
||||
Card firstCard = getFirstItem(grid);
|
||||
|
||||
CardForm form = cardView.getForm();
|
||||
|
||||
assertFalse(form.isVisible());
|
||||
grid.asSingleSelect().setValue(firstCard);
|
||||
assertTrue(form.isVisible());
|
||||
assertEquals(String.valueOf(firstCard.getCardNumber()), form.cardNumber.getValue());
|
||||
}
|
||||
|
||||
private Card getFirstItem(Grid<Card> grid) {
|
||||
int count = grid.getListDataView().getItemCount();
|
||||
List<Card> cards = grid.getListDataView().getItems().collect(Collectors.toList());
|
||||
assertEquals(10, count);
|
||||
return cards.get(0);
|
||||
}
|
||||
}
|
||||
-43
@@ -1,43 +0,0 @@
|
||||
package de.thpeetz.kontor.tysc.views;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import com.vaadin.flow.component.grid.Grid;
|
||||
|
||||
import de.thpeetz.kontor.tysc.data.FieldPosition;
|
||||
|
||||
@SpringBootTest
|
||||
class FieldPositionViewTest {
|
||||
|
||||
@Autowired
|
||||
private PositionView positionView;
|
||||
|
||||
@Test
|
||||
void formShownWhenPositionSelected() {
|
||||
Grid<FieldPosition> grid = positionView.getGrid();
|
||||
FieldPosition firstFieldPosition = getFirstItem(grid);
|
||||
|
||||
PositionForm form = positionView.getForm();
|
||||
|
||||
assertFalse(form.isVisible());
|
||||
grid.asSingleSelect().setValue(firstFieldPosition);
|
||||
assertTrue(form.isVisible());
|
||||
assertEquals(firstFieldPosition.getName(), form.name.getValue());
|
||||
}
|
||||
|
||||
private FieldPosition getFirstItem(Grid<FieldPosition> grid) {
|
||||
int count = grid.getListDataView().getItemCount();
|
||||
List<FieldPosition> positions = grid.getListDataView().getItems().collect(Collectors.toList());
|
||||
assertEquals(44, count);
|
||||
return positions.get(0);
|
||||
}
|
||||
}
|
||||
-44
@@ -1,44 +0,0 @@
|
||||
package de.thpeetz.kontor.tysc.views;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import com.vaadin.flow.component.grid.Grid;
|
||||
|
||||
import de.thpeetz.kontor.tysc.data.Player;
|
||||
|
||||
@SpringBootTest
|
||||
class PlayerViewTest {
|
||||
|
||||
@Autowired
|
||||
private PlayerView playerView;
|
||||
|
||||
@Test
|
||||
void formShownWhenPlayerSelected() {
|
||||
Grid<Player> grid = playerView.getGrid();
|
||||
Player firstPlayer = getFirstItem(grid);
|
||||
|
||||
PlayerForm form = playerView.getForm();
|
||||
|
||||
assertFalse(form.isVisible());
|
||||
grid.asSingleSelect().setValue(firstPlayer);
|
||||
assertTrue(form.isVisible());
|
||||
assertEquals(firstPlayer.getLastName(), form.lastName.getValue());
|
||||
assertEquals(firstPlayer.getFirstName(), form.firstName.getValue());
|
||||
}
|
||||
|
||||
private Player getFirstItem(Grid<Player> grid) {
|
||||
int count = grid.getListDataView().getItemCount();
|
||||
List<Player> players = grid.getListDataView().getItems().collect(Collectors.toList());
|
||||
assertEquals(38, count);
|
||||
return players.get(0);
|
||||
}
|
||||
}
|
||||
-43
@@ -1,43 +0,0 @@
|
||||
package de.thpeetz.kontor.tysc.views;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import com.vaadin.flow.component.grid.Grid;
|
||||
|
||||
import de.thpeetz.kontor.tysc.data.Rooster;
|
||||
|
||||
@SpringBootTest
|
||||
class RoosterViewTest {
|
||||
|
||||
@Autowired
|
||||
private RoosterView roosterView;
|
||||
|
||||
@Test
|
||||
void formShownWhenRoosterSelected() {
|
||||
Grid<Rooster> grid = roosterView.getGrid();
|
||||
Rooster firstRooster = getFirstItem(grid);
|
||||
|
||||
RoosterForm form = roosterView.getForm();
|
||||
|
||||
assertFalse(form.isVisible());
|
||||
grid.asSingleSelect().setValue(firstRooster);
|
||||
assertTrue(form.isVisible());
|
||||
assertEquals(firstRooster.getYear(), form.year.getValue());
|
||||
}
|
||||
|
||||
private Rooster getFirstItem(Grid<Rooster> grid) {
|
||||
int count = grid.getListDataView().getItemCount();
|
||||
List<Rooster> roosters = grid.getListDataView().getItems().collect(Collectors.toList());
|
||||
assertEquals(11, count);
|
||||
return roosters.get(0);
|
||||
}
|
||||
}
|
||||
-43
@@ -1,43 +0,0 @@
|
||||
package de.thpeetz.kontor.tysc.views;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import com.vaadin.flow.component.grid.Grid;
|
||||
|
||||
import de.thpeetz.kontor.tysc.data.Sport;
|
||||
|
||||
@SpringBootTest
|
||||
class SportViewTest {
|
||||
|
||||
@Autowired
|
||||
private SportView sportView;
|
||||
|
||||
@Test
|
||||
void formShownWhenSportSelected() {
|
||||
Grid<Sport> grid = sportView.getGrid();
|
||||
Sport firstSport = getFirstItem(grid);
|
||||
|
||||
SportForm form = sportView.getForm();
|
||||
|
||||
assertFalse(form.isVisible());
|
||||
grid.asSingleSelect().setValue(firstSport);
|
||||
assertTrue(form.isVisible());
|
||||
assertEquals(firstSport.getName(), form.name.getValue());
|
||||
}
|
||||
|
||||
private Sport getFirstItem(Grid<Sport> grid) {
|
||||
int count = grid.getListDataView().getItemCount();
|
||||
List<Sport> sports = grid.getListDataView().getItems().collect(Collectors.toList());
|
||||
assertEquals(4, count);
|
||||
return sports.get(0);
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
package de.thpeetz.kontor.tysc.views;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import com.vaadin.flow.component.grid.Grid;
|
||||
|
||||
import de.thpeetz.kontor.tysc.data.Team;
|
||||
|
||||
@SpringBootTest
|
||||
class TeamViewTest {
|
||||
|
||||
@Autowired
|
||||
private TeamView teamView;
|
||||
|
||||
@Test
|
||||
void formShownWhenTeamSelected() {
|
||||
Grid<Team> grid = teamView.getGrid();
|
||||
Team firstTeam = getFirstItem(grid);
|
||||
|
||||
TeamForm form = teamView.getForm();
|
||||
|
||||
assertFalse(form.isVisible());
|
||||
grid.asSingleSelect().setValue(firstTeam);
|
||||
assertTrue(form.isVisible());
|
||||
assertEquals(firstTeam.getName(), form.name.getValue());
|
||||
}
|
||||
|
||||
private Team getFirstItem(Grid<Team> grid) {
|
||||
int count = grid.getListDataView().getItemCount();
|
||||
List<Team> teams = grid.getListDataView().getItems().collect(Collectors.toList());
|
||||
assertEquals(122, count);
|
||||
return teams.get(0);
|
||||
}
|
||||
}
|
||||
-43
@@ -1,43 +0,0 @@
|
||||
package de.thpeetz.kontor.tysc.views;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import com.vaadin.flow.component.grid.Grid;
|
||||
|
||||
import de.thpeetz.kontor.tysc.data.Vendor;
|
||||
|
||||
@SpringBootTest
|
||||
class VendorViewTest {
|
||||
|
||||
@Autowired
|
||||
private VendorView vendorView;
|
||||
|
||||
@Test
|
||||
void formShownWhenVendorSelected() {
|
||||
Grid<Vendor> grid = vendorView.getGrid();
|
||||
Vendor firstVendor = getFirstItem(grid);
|
||||
|
||||
VendorForm form = vendorView.getForm();
|
||||
|
||||
assertFalse(form.isVisible());
|
||||
grid.asSingleSelect().setValue(firstVendor);
|
||||
assertTrue(form.isVisible());
|
||||
assertEquals(firstVendor.getName(), form.name.getValue());
|
||||
}
|
||||
|
||||
private Vendor getFirstItem(Grid<Vendor> grid) {
|
||||
int count = grid.getListDataView().getItemCount();
|
||||
List<Vendor> vendors = grid.getListDataView().getItems().collect(Collectors.toList());
|
||||
assertEquals(9, count);
|
||||
return vendors.get(0);
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
server.port=8085
|
||||
|
||||
spring.hibernate.dialect=org.hibernate.dialect.HSQLDialect
|
||||
spring.jpa.database-platform=org.hibernate.dialect.HSQLDialect
|
||||
spring.datasource.driverClassName=org.hsqldb.jdbc.JDBCDriver
|
||||
spring.datasource.url=jdbc:hsqldb:mem:itDb
|
||||
spring.datasource.username=sa
|
||||
spring.datasource.password=sa
|
||||
|
||||
#spring.jpa.database-platform=org.hibernate.community.dialect.SQLiteDialect
|
||||
#spring.datasource.driverClassName=org.sqlite.JDBC
|
||||
#spring.datasource.url=jdbc:sqlite:file:./kontorITDb?cache=shared
|
||||
#spring.datasource.username=sa
|
||||
#spring.datasource.password=sa
|
||||
|
||||
spring.jpa.defer-datasource-initialization = true
|
||||
#spring.jpa.hibernate.ddl-auto=create-drop
|
||||
spring.jpa.hibernate.ddl-auto=update
|
||||
spring.jpa.show-sql=false
|
||||
spring.sql.init.mode=always
|
||||
|
||||
spring.mustache.check-template-location = false
|
||||
|
||||
logging.level.org.atmosphere=INFO
|
||||
logging.level.org.springframework.web=INFO
|
||||
logging.level.guru.springframework.controllers=DEBUG
|
||||
logging.level.org.hibernate=INFO
|
||||
logging.level.de.thpeetz=DEBUG
|
||||
|
||||
jwt.auth.secret=J6GOtcwC2NJI1l0VkHu20PacPFGTxpirBxWwynoHjsc=
|
||||
@@ -0,0 +1 @@
|
||||
export {}
|
||||
@@ -0,0 +1 @@
|
||||
export declare const applyCss: (target: Node) => void;
|
||||
@@ -0,0 +1,707 @@
|
||||
/*
|
||||
* Copyright 2000-2026 Vaadin Ltd.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
/// <reference lib="es2018" />
|
||||
import { Flow as _Flow } from 'Frontend/generated/jar-resources/Flow.js';
|
||||
import React, { useCallback, useEffect, useReducer, useRef, useState, type ReactNode } from 'react';
|
||||
import { matchRoutes, useBlocker, useLocation, useNavigate, type NavigateOptions, useHref } from 'react-router';
|
||||
import { createPortal } from 'react-dom';
|
||||
|
||||
const flow = new _Flow({
|
||||
imports: () => import('Frontend/generated/flow/generated-flow-imports.js')
|
||||
});
|
||||
|
||||
const router = {
|
||||
render() {
|
||||
return Promise.resolve();
|
||||
}
|
||||
};
|
||||
|
||||
const flowReact : { active: boolean } = {
|
||||
active: false,
|
||||
}
|
||||
|
||||
// ClickHandler for vaadin-router-go event is copied from vaadin/router click.js
|
||||
// @ts-ignore
|
||||
function getAnchorOrigin(anchor) {
|
||||
// IE11: on HTTP and HTTPS the default port is not included into
|
||||
// window.location.origin, so won't include it here either.
|
||||
const port = anchor.port;
|
||||
const protocol = anchor.protocol;
|
||||
const defaultHttp = protocol === 'http:' && port === '80';
|
||||
const defaultHttps = protocol === 'https:' && port === '443';
|
||||
const host =
|
||||
defaultHttp || defaultHttps
|
||||
? anchor.hostname // does not include the port number (e.g. www.example.org)
|
||||
: anchor.host; // does include the port number (e.g. www.example.org:80)
|
||||
return `${protocol}//${host}`;
|
||||
}
|
||||
|
||||
function normalizeURL(url: URL): void | string {
|
||||
// ignore click if baseURI does not match the document (external)
|
||||
if (!url.href.startsWith(document.baseURI)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Normalize path against baseURI
|
||||
return '/' + url.href.slice(document.baseURI.length);
|
||||
}
|
||||
|
||||
function extractURL(event: MouseEvent): void | URL {
|
||||
// ignore the click if the default action is prevented
|
||||
if (event.defaultPrevented) {
|
||||
return;
|
||||
}
|
||||
|
||||
// ignore the click if not with the primary mouse button
|
||||
if (event.button !== 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// ignore the click if a modifier key is pressed
|
||||
if (event.shiftKey || event.ctrlKey || event.altKey || event.metaKey) {
|
||||
return;
|
||||
}
|
||||
|
||||
// find the <a> element that the click is at (or within)
|
||||
let maybeAnchor = event.target;
|
||||
const path = event.composedPath
|
||||
? event.composedPath()
|
||||
: // @ts-ignore
|
||||
event.path || [];
|
||||
|
||||
// example to check: `for...of` loop here throws the "Not yet implemented" error
|
||||
for (let i = 0; i < path.length; i++) {
|
||||
const target = path[i];
|
||||
if (target.nodeName && target.nodeName.toLowerCase() === 'a') {
|
||||
maybeAnchor = target;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
while (maybeAnchor && maybeAnchor.nodeName.toLowerCase() !== 'a') {
|
||||
// @ts-ignore
|
||||
maybeAnchor = maybeAnchor.parentNode;
|
||||
}
|
||||
|
||||
// ignore the click if not at an <a> element
|
||||
// @ts-ignore
|
||||
if (!maybeAnchor || maybeAnchor.nodeName.toLowerCase() !== 'a') {
|
||||
return;
|
||||
}
|
||||
|
||||
const anchor = maybeAnchor as HTMLAnchorElement;
|
||||
|
||||
// ignore the click if the <a> element has a non-default target
|
||||
if (anchor.target && anchor.target.toLowerCase() !== '_self') {
|
||||
return;
|
||||
}
|
||||
|
||||
// ignore the click if the <a> element has the 'download' attribute
|
||||
if (anchor.hasAttribute('download')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// ignore the click if the <a> element has the 'router-ignore' attribute
|
||||
if (anchor.hasAttribute('router-ignore')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// ignore the click if the target URL is a fragment on the current page
|
||||
if (anchor.pathname === window.location.pathname && anchor.hash !== '') {
|
||||
// @ts-ignore
|
||||
window.location.hash = anchor.hash;
|
||||
return;
|
||||
}
|
||||
|
||||
// ignore the click if the target is external to the app
|
||||
// In IE11 HTMLAnchorElement does not have the `origin` property
|
||||
// @ts-ignore
|
||||
const origin = anchor.origin || getAnchorOrigin(anchor);
|
||||
if (origin !== window.location.origin) {
|
||||
return;
|
||||
}
|
||||
|
||||
return new URL(anchor.href, anchor.baseURI);
|
||||
}
|
||||
|
||||
function extractPath(event: MouseEvent): void | string {
|
||||
const url = extractURL(event);
|
||||
if (!url) {
|
||||
return;
|
||||
}
|
||||
return normalizeURL(url);
|
||||
}
|
||||
|
||||
export const registerGlobalClickHandler = () => {
|
||||
window.addEventListener('click', (event: MouseEvent) => {
|
||||
if (flowReact.active) {
|
||||
return;
|
||||
}
|
||||
const url = extractURL(event);
|
||||
if (!url) {
|
||||
return;
|
||||
}
|
||||
// ignore click if baseURI does not match the document (external)
|
||||
if (!url.href.startsWith(document.baseURI)) {
|
||||
return;
|
||||
}
|
||||
if (event && event.preventDefault) {
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
// Normalize path against baseURI
|
||||
const path = url.pathname + url.search + url.hash;
|
||||
const state = {...window.history.state}
|
||||
if (state.idx !== undefined) {
|
||||
state.idx = state.idx + 1;
|
||||
}
|
||||
window.history.pushState(state, '', path);
|
||||
window.dispatchEvent(new PopStateEvent('popstate'));
|
||||
}, { capture: false });
|
||||
};
|
||||
|
||||
/**
|
||||
* Fire 'vaadin-navigated' event to inform components of navigation.
|
||||
* @param pathname pathname of navigation
|
||||
* @param search search of navigation
|
||||
*/
|
||||
function fireNavigated(pathname: string, search: string) {
|
||||
setTimeout(() => {
|
||||
window.dispatchEvent(
|
||||
new CustomEvent('vaadin-navigated', {
|
||||
detail: {
|
||||
pathname,
|
||||
search
|
||||
}
|
||||
})
|
||||
);
|
||||
// @ts-ignore
|
||||
delete window.Vaadin.Flow.navigation;
|
||||
});
|
||||
}
|
||||
|
||||
function postpone() {}
|
||||
|
||||
const prevent = () => postpone;
|
||||
|
||||
type RouterContainer = Awaited<ReturnType<(typeof flow.serverSideRoutes)[0]['action']>>;
|
||||
|
||||
type PortalEntry = {
|
||||
readonly children: ReactNode;
|
||||
readonly domNode: HTMLElement;
|
||||
};
|
||||
|
||||
type FlowPortalProps = React.PropsWithChildren<
|
||||
Readonly<{
|
||||
domNode: HTMLElement;
|
||||
onRemove(): void;
|
||||
}>
|
||||
>;
|
||||
|
||||
function FlowPortal({ children, domNode, onRemove }: FlowPortalProps) {
|
||||
useEffect(() => {
|
||||
domNode.addEventListener(
|
||||
'flow-portal-remove',
|
||||
(event: Event) => {
|
||||
event.preventDefault();
|
||||
onRemove();
|
||||
},
|
||||
{ once: true }
|
||||
);
|
||||
}, []);
|
||||
|
||||
return createPortal(children, domNode);
|
||||
}
|
||||
|
||||
const ADD_FLOW_PORTAL = 'ADD_FLOW_PORTAL';
|
||||
|
||||
type AddFlowPortalAction = Readonly<{
|
||||
type: typeof ADD_FLOW_PORTAL;
|
||||
portal: React.ReactElement<FlowPortalProps>;
|
||||
}>;
|
||||
|
||||
function addFlowPortal(portal: React.ReactElement<FlowPortalProps>): AddFlowPortalAction {
|
||||
return {
|
||||
type: ADD_FLOW_PORTAL,
|
||||
portal
|
||||
};
|
||||
}
|
||||
|
||||
const REMOVE_FLOW_PORTAL = 'REMOVE_FLOW_PORTAL';
|
||||
|
||||
type RemoveFlowPortalAction = Readonly<{
|
||||
type: typeof REMOVE_FLOW_PORTAL;
|
||||
key: string;
|
||||
}>;
|
||||
|
||||
function removeFlowPortal(key: string): RemoveFlowPortalAction {
|
||||
return {
|
||||
type: REMOVE_FLOW_PORTAL,
|
||||
key
|
||||
};
|
||||
}
|
||||
|
||||
function flowPortalsReducer(
|
||||
portals: readonly React.ReactElement<FlowPortalProps>[],
|
||||
action: AddFlowPortalAction | RemoveFlowPortalAction
|
||||
) {
|
||||
switch (action.type) {
|
||||
case ADD_FLOW_PORTAL:
|
||||
return [...portals, action.portal];
|
||||
case REMOVE_FLOW_PORTAL:
|
||||
return portals.filter(({ key }) => key !== action.key);
|
||||
default:
|
||||
return portals;
|
||||
}
|
||||
}
|
||||
|
||||
type NavigateOpts = {
|
||||
to: string;
|
||||
callback: boolean;
|
||||
opts?: NavigateOptions;
|
||||
};
|
||||
|
||||
type NavigateFn = (to: string, callback: boolean, opts?: NavigateOptions) => void;
|
||||
|
||||
let navigateInProgress = false;
|
||||
/**
|
||||
* A hook providing the `navigate(path: string, opts?: NavigateOptions)` function
|
||||
* with React Router API that has more consistent history updates. Uses internal
|
||||
* queue for processing navigate calls.
|
||||
*/
|
||||
function useQueuedNavigate(
|
||||
waitReference: React.MutableRefObject<Promise<void> | undefined>,
|
||||
navigated: React.MutableRefObject<boolean>
|
||||
): NavigateFn {
|
||||
const navigate = useNavigate();
|
||||
const navigateQueue = useRef<NavigateOpts[]>([]).current;
|
||||
const [navigateQueueLength, setNavigateQueueLength] = useState(0);
|
||||
|
||||
const dequeueNavigation = useCallback(() => {
|
||||
if (navigateInProgress) {
|
||||
dequeueNavigationAfterCurrentTask();
|
||||
return;
|
||||
}
|
||||
|
||||
const navigateArgs = navigateQueue.shift();
|
||||
if (navigateArgs === undefined) {
|
||||
// Empty queue, do nothing.
|
||||
return;
|
||||
}
|
||||
|
||||
const blockingNavigate = async () => {
|
||||
if (waitReference.current) {
|
||||
await waitReference.current;
|
||||
waitReference.current = undefined;
|
||||
}
|
||||
navigated.current = !navigateArgs.callback;
|
||||
navigateInProgress = true;
|
||||
navigate(navigateArgs.to, navigateArgs.opts);
|
||||
setNavigateQueueLength(navigateQueue.length);
|
||||
};
|
||||
blockingNavigate();
|
||||
}, [navigate, setNavigateQueueLength]);
|
||||
|
||||
const dequeueNavigationAfterCurrentTask = useCallback(() => {
|
||||
setTimeout(dequeueNavigation, 0);
|
||||
}, [dequeueNavigation]);
|
||||
|
||||
const enqueueNavigation = useCallback(
|
||||
(to: string, callback: boolean, opts?: NavigateOptions) => {
|
||||
navigateQueue.push({ to: to, callback: callback, opts: opts });
|
||||
setNavigateQueueLength(navigateQueue.length);
|
||||
if (navigateQueue.length === 1) {
|
||||
// The first navigation can be started right after any pending sync
|
||||
// jobs, which could add more navigations to the queue.
|
||||
dequeueNavigationAfterCurrentTask();
|
||||
}
|
||||
},
|
||||
[setNavigateQueueLength, dequeueNavigationAfterCurrentTask]
|
||||
);
|
||||
|
||||
useEffect(
|
||||
() => () => {
|
||||
// The Flow component has rendered, but history might not be
|
||||
// updated yet, as React Router does it asynchronously.
|
||||
// Use microtask callback for history consistency.
|
||||
dequeueNavigationAfterCurrentTask();
|
||||
},
|
||||
[navigateQueueLength, dequeueNavigationAfterCurrentTask]
|
||||
);
|
||||
|
||||
return enqueueNavigation;
|
||||
}
|
||||
|
||||
const flowNavigation = () => {
|
||||
// @ts-ignore
|
||||
window.Vaadin.Flow.navigation = true;
|
||||
};
|
||||
|
||||
function Flow() {
|
||||
const ref = useRef<HTMLOutputElement>(null);
|
||||
const navigate = useNavigate();
|
||||
const blocker = useBlocker(({ currentLocation, nextLocation }) => {
|
||||
navigated.current =
|
||||
navigated.current ||
|
||||
(nextLocation.pathname === currentLocation.pathname &&
|
||||
nextLocation.search === currentLocation.search &&
|
||||
nextLocation.hash === currentLocation.hash);
|
||||
return true;
|
||||
});
|
||||
const location = useLocation();
|
||||
const navigated = useRef<boolean>(false);
|
||||
const blockerHandled = useRef<boolean>(false);
|
||||
const fromAnchor = useRef<boolean>(false);
|
||||
const containerRef = useRef<RouterContainer | undefined>(undefined);
|
||||
const roundTrip = useRef<Promise<void> | undefined>(undefined);
|
||||
const queuedNavigate = useQueuedNavigate(roundTrip, navigated);
|
||||
const basename = useHref('/');
|
||||
|
||||
// portalsReducer function is used as state outside the Flow component.
|
||||
const [portals, dispatchPortalAction] = useReducer(flowPortalsReducer, []);
|
||||
|
||||
const addPortalEventHandler = useCallback(
|
||||
(event: CustomEvent<PortalEntry>) => {
|
||||
event.preventDefault();
|
||||
|
||||
const key = Math.random().toString(36).slice(2);
|
||||
dispatchPortalAction(
|
||||
addFlowPortal(
|
||||
<FlowPortal
|
||||
key={key}
|
||||
domNode={event.detail.domNode}
|
||||
onRemove={() => dispatchPortalAction(removeFlowPortal(key))}
|
||||
>
|
||||
{event.detail.children}
|
||||
</FlowPortal>
|
||||
)
|
||||
);
|
||||
},
|
||||
[dispatchPortalAction]
|
||||
);
|
||||
|
||||
const navigateEventHandler = useCallback(
|
||||
(event: MouseEvent) => {
|
||||
const path = extractPath(event);
|
||||
if (!path) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event && event.preventDefault) {
|
||||
event.preventDefault();
|
||||
}
|
||||
navigated.current = false;
|
||||
// When navigation is triggered by click on a link, fromAnchor is set to true
|
||||
// in order to get a server round-trip even when navigating to the same URL again
|
||||
fromAnchor.current = true;
|
||||
// @ts-ignore
|
||||
window.Vaadin.Flow.navigation = true;
|
||||
navigate(path);
|
||||
// Dispatch close event for overlay drawer on click navigation.
|
||||
window.dispatchEvent(new CustomEvent('close-overlay-drawer'));
|
||||
},
|
||||
[navigate]
|
||||
);
|
||||
|
||||
const vaadinRouterGoEventHandler = useCallback(
|
||||
(event: CustomEvent<URL>) => {
|
||||
const url = event.detail;
|
||||
const path = normalizeURL(url);
|
||||
if (!path) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
navigate(path);
|
||||
},
|
||||
[navigate]
|
||||
);
|
||||
|
||||
const vaadinNavigateEventHandler = useCallback(
|
||||
(event: CustomEvent<{ state: unknown; url: string; replace?: boolean; callback: boolean }>) => {
|
||||
// @ts-ignore
|
||||
window.Vaadin.Flow.navigation = true;
|
||||
// clean base uri away if for instance redirected to http://localhost/path/user?id=10
|
||||
// else the whole http... will be appended to the url see #19580
|
||||
const path = event.detail.url.startsWith(document.baseURI)
|
||||
? '/' + event.detail.url.slice(document.baseURI.length)
|
||||
: '/' + event.detail.url;
|
||||
fromAnchor.current = false;
|
||||
queuedNavigate(path, event.detail.callback, { state: event.detail.state, replace: event.detail.replace });
|
||||
},
|
||||
[navigate]
|
||||
);
|
||||
|
||||
const redirect = useCallback(
|
||||
(path: string) => {
|
||||
return () => {
|
||||
navigate(path, { replace: true });
|
||||
};
|
||||
},
|
||||
[navigate]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
// @ts-ignore
|
||||
window.addEventListener('vaadin-router-go', vaadinRouterGoEventHandler);
|
||||
// @ts-ignore
|
||||
window.addEventListener('vaadin-navigate', vaadinNavigateEventHandler);
|
||||
|
||||
return () => {
|
||||
// @ts-ignore
|
||||
window.removeEventListener('vaadin-router-go', vaadinRouterGoEventHandler);
|
||||
// @ts-ignore
|
||||
window.removeEventListener('vaadin-navigate', vaadinNavigateEventHandler);
|
||||
};
|
||||
}, [vaadinRouterGoEventHandler, vaadinNavigateEventHandler]);
|
||||
|
||||
useEffect(() => {
|
||||
// @ts-ignore
|
||||
window.addEventListener("popstate", flowNavigation);
|
||||
window.addEventListener('click', navigateEventHandler);
|
||||
flowReact.active = true;
|
||||
|
||||
return () => {
|
||||
containerRef.current?.parentNode?.removeChild(containerRef.current);
|
||||
containerRef.current?.removeEventListener('flow-portal-add', addPortalEventHandler as EventListener);
|
||||
containerRef.current = undefined;
|
||||
// @ts-ignore
|
||||
window.removeEventListener("popstate", flowNavigation);
|
||||
window.removeEventListener('click', navigateEventHandler);
|
||||
flowReact.active = false;
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (blocker.state === 'blocked') {
|
||||
if (blockerHandled.current) {
|
||||
// Blocker is handled and the new navigation
|
||||
// gets queued to be executed after the current handling ends.
|
||||
const { pathname, state } = blocker.location;
|
||||
// Clear base name to not get /baseName/basename/path
|
||||
const pathNoBase = pathname.substring(basename.length);
|
||||
// path should always start with / else react-router will append to current url
|
||||
queuedNavigate(pathNoBase.startsWith('/') ? pathNoBase : '/' + pathNoBase, true, {
|
||||
state: state,
|
||||
replace: true
|
||||
});
|
||||
return;
|
||||
}
|
||||
blockerHandled.current = true;
|
||||
let blockingPromise: any;
|
||||
roundTrip.current = new Promise<void>(
|
||||
(resolve, reject) => (blockingPromise = { resolve: resolve, reject: reject })
|
||||
);
|
||||
// Release blocker handling after promise is fulfilled
|
||||
roundTrip.current.then(
|
||||
() => (blockerHandled.current = false),
|
||||
() => (blockerHandled.current = false)
|
||||
);
|
||||
|
||||
// Proceed to the blocked location, unless the navigation originates from a click on a link.
|
||||
// In that case continue with function execution and perform a server round-trip
|
||||
if (navigated.current && !fromAnchor.current) {
|
||||
blocker.proceed();
|
||||
blockingPromise.resolve();
|
||||
navigateInProgress = false;
|
||||
return;
|
||||
}
|
||||
fromAnchor.current = false;
|
||||
const { pathname, search } = blocker.location;
|
||||
const routes = ((window as any)?.Vaadin?.routesConfig || []) as any[];
|
||||
let matched = matchRoutes(Array.from(routes), pathname);
|
||||
|
||||
// Navigation between server routes
|
||||
// @ts-ignore
|
||||
if (matched && matched.filter((path) => path.route?.element?.type?.name === Flow.name).length != 0) {
|
||||
containerRef.current?.onBeforeEnter?.call(
|
||||
containerRef?.current,
|
||||
{ pathname, search },
|
||||
{
|
||||
prevent() {
|
||||
blocker.reset();
|
||||
blockingPromise.resolve();
|
||||
navigateInProgress = false;
|
||||
navigated.current = false;
|
||||
},
|
||||
redirect,
|
||||
continue() {
|
||||
blocker.proceed();
|
||||
blockingPromise.resolve();
|
||||
navigateInProgress = false;
|
||||
}
|
||||
},
|
||||
router
|
||||
);
|
||||
navigated.current = true;
|
||||
} else {
|
||||
// For covering the 'server -> client' use case
|
||||
Promise.resolve(
|
||||
containerRef.current?.onBeforeLeave?.call(
|
||||
containerRef?.current,
|
||||
{
|
||||
pathname,
|
||||
search
|
||||
},
|
||||
{ prevent },
|
||||
router
|
||||
)
|
||||
).then((cmd: unknown) => {
|
||||
if (cmd === postpone && containerRef.current) {
|
||||
// postponed navigation: expose existing blocker to Flow
|
||||
containerRef.current.serverConnected = (cancel) => {
|
||||
if (cancel) {
|
||||
blocker.reset();
|
||||
} else {
|
||||
blocker.proceed();
|
||||
}
|
||||
blockingPromise.resolve();
|
||||
navigateInProgress = false;
|
||||
};
|
||||
} else {
|
||||
// permitted navigation: proceed with the blocker
|
||||
blocker.proceed();
|
||||
blockingPromise.resolve();
|
||||
navigateInProgress = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}, [blocker.state, blocker.location]);
|
||||
|
||||
useEffect(() => {
|
||||
if (blocker.state === 'blocked') {
|
||||
return;
|
||||
}
|
||||
if (navigated.current) {
|
||||
navigated.current = false;
|
||||
fireNavigated(location.pathname, location.search);
|
||||
return;
|
||||
}
|
||||
flow.serverSideRoutes[0]
|
||||
.action({ pathname: location.pathname, search: location.search })
|
||||
.then((container) => {
|
||||
const outlet = ref.current?.parentNode;
|
||||
if (outlet && outlet !== container.parentNode) {
|
||||
outlet.append(container);
|
||||
container.addEventListener('flow-portal-add', addPortalEventHandler as EventListener);
|
||||
containerRef.current = container;
|
||||
}
|
||||
return container.onBeforeEnter?.call(
|
||||
container,
|
||||
// Always add base to path as it is cleaned in getFlowRoutePath and will break a route starting with basename
|
||||
{ pathname: basename + location.pathname, search: location.search },
|
||||
{
|
||||
prevent,
|
||||
redirect,
|
||||
continue() {
|
||||
fireNavigated(location.pathname, location.search);
|
||||
}
|
||||
},
|
||||
router
|
||||
);
|
||||
})
|
||||
.then((result: unknown) => {
|
||||
if (typeof result === 'function') {
|
||||
result();
|
||||
}
|
||||
});
|
||||
}, [location]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<output ref={ref} style={{ display: 'none' }} />
|
||||
{portals}
|
||||
</>
|
||||
);
|
||||
}
|
||||
Flow.type = 'FlowContainer'; // This is for copilot to recognize this
|
||||
|
||||
export const serverSideRoutes = [{ path: '/*', element: <Flow /> }];
|
||||
|
||||
/**
|
||||
* Load the script for an exported WebComponent with the given tag
|
||||
*
|
||||
* @param tag name of the exported web-component to load
|
||||
*
|
||||
* @returns Promise(resolve, reject) that is fulfilled on script load
|
||||
*/
|
||||
export const loadComponentScript = (tag: String): Promise<void> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
useEffect(() => {
|
||||
const script = document.createElement('script');
|
||||
script.src = `/web-component/${tag}.js`;
|
||||
script.onload = function () {
|
||||
resolve();
|
||||
};
|
||||
script.onerror = function (err) {
|
||||
reject(err);
|
||||
};
|
||||
document.head.appendChild(script);
|
||||
|
||||
return () => {
|
||||
document.head.removeChild(script);
|
||||
};
|
||||
}, []);
|
||||
});
|
||||
};
|
||||
|
||||
interface Properties {
|
||||
[key: string]: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load WebComponent script and create a React element for the WebComponent.
|
||||
*
|
||||
* @param tag custom web-component tag name.
|
||||
* @param props optional Properties object to create element attributes with
|
||||
* @param onload optional callback to be called for script onload
|
||||
* @param onerror optional callback for error loading the script
|
||||
*/
|
||||
export const reactElement = (tag: string, props?: Properties, onload?: () => void, onerror?: (err: any) => void) => {
|
||||
loadComponentScript(tag).then(
|
||||
() => onload?.(),
|
||||
(err) => {
|
||||
if (onerror) {
|
||||
onerror(err);
|
||||
} else {
|
||||
console.error(`Failed to load script for ${tag}.`, err);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
if (props) {
|
||||
return React.createElement(tag, props);
|
||||
}
|
||||
return React.createElement(tag);
|
||||
};
|
||||
|
||||
export default Flow;
|
||||
|
||||
// @ts-ignore
|
||||
if (import.meta.hot) {
|
||||
// @ts-ignore
|
||||
import.meta.hot.accept((newModule) => {
|
||||
// A hot module replace for Flow.tsx happens when any JS/TS imported through @JsModule
|
||||
// or similar is updated because this updates generated-flow-imports.js and that in turn
|
||||
// is imported by this file. We have no means of hot replacing those files, e.g. some
|
||||
// custom lit element so we need to reload the page. */
|
||||
if (newModule) {
|
||||
window.location.reload();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,329 @@
|
||||
/*
|
||||
* Copyright 2000-2026 Vaadin Ltd.
|
||||
*
|
||||
* 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 { createRoot, Root } from 'react-dom/client';
|
||||
import { createElement, type Dispatch, type ReactElement, type ReactNode, useEffect, useReducer } from 'react';
|
||||
|
||||
type FlowStateKeyChangedAction<K extends string, V> = Readonly<{
|
||||
type: 'stateKeyChanged';
|
||||
key: K;
|
||||
value: V;
|
||||
}>;
|
||||
|
||||
type FlowStateReducerAction = FlowStateKeyChangedAction<string, unknown>;
|
||||
|
||||
function stateReducer<S extends Readonly<Record<string, unknown>>>(state: S, action: FlowStateReducerAction): S {
|
||||
switch (action.type) {
|
||||
case 'stateKeyChanged':
|
||||
const { value } = action;
|
||||
return {
|
||||
...state,
|
||||
key: value
|
||||
} as S;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
type DispatchEvent<T> = T extends undefined ? () => boolean : (value: T) => boolean;
|
||||
|
||||
const emptyAction: Dispatch<unknown> = () => {};
|
||||
|
||||
/**
|
||||
* An object with APIs exposed for using in the {@link ReactAdapterElement#render}
|
||||
* implementation.
|
||||
*/
|
||||
export type RenderHooks = {
|
||||
/**
|
||||
* A hook API for using stateful JS properties of the Web Component from
|
||||
* the React `render()`.
|
||||
*
|
||||
* @typeParam T - Type of the state value
|
||||
*
|
||||
* @param key - Web Component property name, which is used for two-way
|
||||
* value propagation from the server and back.
|
||||
* @param initialValue - Fallback initial value (optional). Only applies if
|
||||
* the Java component constructor does not invoke `setState`.
|
||||
* @returns A tuple with two values:
|
||||
* 1. The current state.
|
||||
* 2. The `set` function for changing the state and triggering render
|
||||
* @protected
|
||||
*/
|
||||
readonly useState: ReactAdapterElement['useState'];
|
||||
|
||||
/**
|
||||
* A hook helper to simplify dispatching a `CustomEvent` on the Web
|
||||
* Component from React.
|
||||
*
|
||||
* @typeParam T - The type for `event.detail` value (optional).
|
||||
*
|
||||
* @param type - The `CustomEvent` type string.
|
||||
* @param options - The settings for the `CustomEvent`.
|
||||
* @returns The `dispatch` function. The function parameters change
|
||||
* depending on the `T` generic type:
|
||||
* - For `undefined` type (default), has no parameters.
|
||||
* - For other types, has one parameter for the `event.detail` value of that type.
|
||||
* @protected
|
||||
*/
|
||||
readonly useCustomEvent: ReactAdapterElement['useCustomEvent'];
|
||||
|
||||
/**
|
||||
* A hook helper to generate the content element with name attribute to bind
|
||||
* the server-side Flow element for this component.
|
||||
*
|
||||
* This is used together with {@link ReactAdapterComponent::getContentElement}
|
||||
* to have server-side component attach to the correct client element.
|
||||
*
|
||||
* Usage as follows:
|
||||
*
|
||||
* const content = hooks.useContent('content');
|
||||
* return <>
|
||||
* {content}
|
||||
* </>;
|
||||
*
|
||||
* Note! Not adding the 'content' element into the dom will have the
|
||||
* server throw a IllegalStateException for element with tag name not found.
|
||||
*
|
||||
* @param name - The name attribute of the element
|
||||
*/
|
||||
readonly useContent: ReactAdapterElement['useContent'];
|
||||
};
|
||||
|
||||
interface ReadyCallbackFunction {
|
||||
(): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* A base class for Web Components that render using React. Enables creating
|
||||
* adapters for integrating React components with Flow. Intended for use with
|
||||
* `ReactAdapterComponent` Flow Java class.
|
||||
*/
|
||||
export abstract class ReactAdapterElement extends HTMLElement {
|
||||
#root: Root | undefined = undefined;
|
||||
#rootRendered: boolean = false;
|
||||
#rendering: ReactNode | undefined = undefined;
|
||||
|
||||
#state: Record<string, unknown> = Object.create(null);
|
||||
#stateSetters = new Map<string, Dispatch<unknown>>();
|
||||
#customEvents = new Map<string, DispatchEvent<unknown>>();
|
||||
#dispatchFlowState: Dispatch<FlowStateReducerAction> = emptyAction;
|
||||
|
||||
#readyCallback = new Map<string, ReadyCallbackFunction>();
|
||||
|
||||
readonly #renderHooks: RenderHooks;
|
||||
|
||||
readonly #Wrapper: () => ReactElement | null;
|
||||
|
||||
#unmounting?: Promise<void>;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.#renderHooks = {
|
||||
useState: this.useState.bind(this),
|
||||
useCustomEvent: this.useCustomEvent.bind(this),
|
||||
useContent: this.useContent.bind(this)
|
||||
};
|
||||
this.#Wrapper = this.#renderWrapper.bind(this);
|
||||
this.#markAsUsed();
|
||||
}
|
||||
|
||||
public async connectedCallback() {
|
||||
this.#rendering = createElement(this.#Wrapper);
|
||||
const createNewRoot = this.dispatchEvent(
|
||||
new CustomEvent('flow-portal-add', {
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
composed: true,
|
||||
detail: {
|
||||
children: this.#rendering,
|
||||
domNode: this
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
if (!createNewRoot || this.#root) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this.#unmounting;
|
||||
|
||||
this.#root = createRoot(this);
|
||||
this.#maybeRenderRoot();
|
||||
this.#root.render(this.#rendering);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a callback for specified element identifier to be called when
|
||||
* react element is ready.
|
||||
* <p>
|
||||
* For internal use only. May be renamed or removed in a future release.
|
||||
*
|
||||
* @param id element identifier that callback is for
|
||||
* @param readyCallback callback method to be informed on element ready state
|
||||
* @internal
|
||||
*/
|
||||
public addReadyCallback(id: string, readyCallback: ReadyCallbackFunction) {
|
||||
this.#readyCallback.set(id, readyCallback);
|
||||
}
|
||||
|
||||
public async disconnectedCallback() {
|
||||
if (!this.#root) {
|
||||
this.dispatchEvent(
|
||||
new CustomEvent('flow-portal-remove', {
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
composed: true,
|
||||
detail: {
|
||||
children: this.#rendering,
|
||||
domNode: this
|
||||
}
|
||||
})
|
||||
);
|
||||
} else {
|
||||
this.#unmounting = Promise.resolve();
|
||||
await this.#unmounting;
|
||||
this.#root.unmount();
|
||||
this.#root = undefined;
|
||||
}
|
||||
this.#rootRendered = false;
|
||||
this.#rendering = undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* A hook API for using stateful JS properties of the Web Component from
|
||||
* the React `render()`.
|
||||
*
|
||||
* @typeParam T - Type of the state value
|
||||
*
|
||||
* @param key - Web Component property name, which is used for two-way
|
||||
* value propagation from the server and back.
|
||||
* @param initialValue - Fallback initial value (optional). Only applies if
|
||||
* the Java component constructor does not invoke `setState`.
|
||||
* @returns A tuple with two values:
|
||||
* 1. The current state.
|
||||
* 2. The `set` function for changing the state and triggering render
|
||||
* @protected
|
||||
*/
|
||||
protected useState<T>(key: string, initialValue?: T): [value: T, setValue: Dispatch<T>] {
|
||||
if (this.#stateSetters.has(key)) {
|
||||
return [this.#state[key] as T, this.#stateSetters.get(key)!];
|
||||
}
|
||||
|
||||
const value = ((this as Record<string, unknown>)[key] as T) ?? initialValue!;
|
||||
this.#state[key] = value;
|
||||
Object.defineProperty(this, key, {
|
||||
enumerable: true,
|
||||
get(): T {
|
||||
return this.#state[key];
|
||||
},
|
||||
set(nextValue: T) {
|
||||
this.#state[key] = nextValue;
|
||||
this.#dispatchFlowState({ type: 'stateKeyChanged', key, value });
|
||||
}
|
||||
});
|
||||
|
||||
const dispatchChangedEvent = this.useCustomEvent<{ value: T }>(`${key}-changed`, { detail: { value } });
|
||||
const setValue = (value: T) => {
|
||||
this.#state[key] = value;
|
||||
dispatchChangedEvent({ value });
|
||||
this.#dispatchFlowState({ type: 'stateKeyChanged', key, value });
|
||||
};
|
||||
this.#stateSetters.set(key, setValue as Dispatch<unknown>);
|
||||
return [value, setValue];
|
||||
}
|
||||
|
||||
/**
|
||||
* A hook helper to simplify dispatching a `CustomEvent` on the Web
|
||||
* Component from React.
|
||||
*
|
||||
* @typeParam T - The type for `event.detail` value (optional).
|
||||
*
|
||||
* @param type - The `CustomEvent` type string.
|
||||
* @param options - The settings for the `CustomEvent`.
|
||||
* @returns The `dispatch` function. The function parameters change
|
||||
* depending on the `T` generic type:
|
||||
* - For `undefined` type (default), has no parameters.
|
||||
* - For other types, has one parameter for the `event.detail` value of that type.
|
||||
* @protected
|
||||
*/
|
||||
protected useCustomEvent<T = undefined>(type: string, options: CustomEventInit<T> = {}): DispatchEvent<T> {
|
||||
if (!this.#customEvents.has(type)) {
|
||||
const dispatch = ((detail?: T) => {
|
||||
const eventInitDict =
|
||||
detail === undefined
|
||||
? options
|
||||
: {
|
||||
...options,
|
||||
detail
|
||||
};
|
||||
const event = new CustomEvent(type, eventInitDict);
|
||||
return this.dispatchEvent(event);
|
||||
}) as DispatchEvent<T>;
|
||||
this.#customEvents.set(type, dispatch as DispatchEvent<unknown>);
|
||||
return dispatch;
|
||||
}
|
||||
return this.#customEvents.get(type)! as DispatchEvent<T>;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Web Component render function. To be implemented by users with React.
|
||||
*
|
||||
* @param hooks - the adapter APIs exposed for the implementation.
|
||||
* @protected
|
||||
*/
|
||||
protected abstract render(hooks: RenderHooks): ReactElement | null;
|
||||
|
||||
/**
|
||||
* Prepare content container for Flow to bind server Element to.
|
||||
*
|
||||
* @param name container name attribute matching server name attribute
|
||||
* @protected
|
||||
*/
|
||||
protected useContent(name: string): ReactElement | null {
|
||||
useEffect(() => {
|
||||
this.#readyCallback.get(name)?.();
|
||||
}, []);
|
||||
return createElement('flow-content-container', { name, style: { display: 'contents' } });
|
||||
}
|
||||
|
||||
#maybeRenderRoot() {
|
||||
if (this.#rootRendered || !this.#root) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.#root.render(createElement(this.#Wrapper));
|
||||
this.#rootRendered = true;
|
||||
}
|
||||
|
||||
#renderWrapper(): ReactElement | null {
|
||||
const [state, dispatchFlowState] = useReducer(stateReducer, this.#state);
|
||||
this.#state = state;
|
||||
this.#dispatchFlowState = dispatchFlowState;
|
||||
return this.render(this.#renderHooks);
|
||||
}
|
||||
|
||||
#markAsUsed(): void {
|
||||
// @ts-ignore
|
||||
let vaadinObject = window.Vaadin || {};
|
||||
// @ts-ignore
|
||||
if (vaadinObject.developmentMode) {
|
||||
vaadinObject.registrations = vaadinObject.registrations || [];
|
||||
vaadinObject.registrations.push({
|
||||
is: 'ReactAdapterElement',
|
||||
version: '25.2.6'
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export {}
|
||||
@@ -0,0 +1,105 @@
|
||||
import '@vaadin/field-highlighter/src/vaadin-field-highlighter.js';
|
||||
import '@vaadin/common-frontend/ConnectionIndicator.js';
|
||||
import '@vaadin/accordion/src/vaadin-accordion.js';
|
||||
import '@vaadin/details/src/vaadin-details.js';
|
||||
import '@vaadin/accordion/src/vaadin-accordion-panel.js';
|
||||
import '@vaadin/app-layout/src/vaadin-app-layout.js';
|
||||
import '@vaadin/button/src/vaadin-button.js';
|
||||
import '@vaadin/app-layout/src/vaadin-drawer-toggle.js';
|
||||
import '@vaadin/avatar/src/vaadin-avatar.js';
|
||||
import '@vaadin/avatar-group/src/vaadin-avatar-group.js';
|
||||
import '@vaadin/badge/src/vaadin-badge.js';
|
||||
import '@vaadin/breadcrumbs/src/vaadin-breadcrumbs-item.js';
|
||||
import '@vaadin/card/src/vaadin-card.js';
|
||||
import '@vaadin/checkbox/src/vaadin-checkbox.js';
|
||||
import '@vaadin/checkbox-group/src/vaadin-checkbox-group.js';
|
||||
import '@vaadin/combo-box/src/vaadin-combo-box.js';
|
||||
import 'Frontend/generated/jar-resources/flow-component-renderer.js';
|
||||
import 'Frontend/generated/jar-resources/flow-component-directive.js';
|
||||
import 'Frontend/generated/jar-resources/comboBoxConnector.js';
|
||||
import '@vaadin/multi-select-combo-box/src/vaadin-multi-select-combo-box.js';
|
||||
import '@vaadin/confirm-dialog/src/vaadin-confirm-dialog.js';
|
||||
import '@vaadin/context-menu/src/vaadin-context-menu.js';
|
||||
import '@vaadin/tooltip/src/vaadin-tooltip.js';
|
||||
import 'Frontend/generated/jar-resources/contextMenuConnector.js';
|
||||
import 'Frontend/generated/jar-resources/contextMenuTargetConnector.js';
|
||||
import '@vaadin/custom-field/src/vaadin-custom-field.js';
|
||||
import '@vaadin/date-picker/src/vaadin-date-picker.js';
|
||||
import 'Frontend/generated/jar-resources/datepickerConnector.js';
|
||||
import '@vaadin/date-time-picker/src/vaadin-date-time-picker.js';
|
||||
import '@vaadin/time-picker/src/vaadin-time-picker.js';
|
||||
import 'Frontend/generated/jar-resources/vaadin-time-picker/timepickerConnector.js';
|
||||
import 'Frontend/generated/jar-resources/vaadin-time-picker/helpers.js';
|
||||
import '@vaadin/dialog/src/vaadin-dialog.js';
|
||||
import 'Frontend/generated/jar-resources/dndConnector.js';
|
||||
import '@vaadin/form-layout/src/vaadin-form-layout.js';
|
||||
import '@vaadin/form-layout/src/vaadin-form-item.js';
|
||||
import '@vaadin/form-layout/src/vaadin-form-row.js';
|
||||
import '@vaadin/grid/src/vaadin-grid-column-group.js';
|
||||
import '@vaadin/grid/src/vaadin-grid.js';
|
||||
import '@vaadin/grid/src/vaadin-grid-column.js';
|
||||
import '@vaadin/grid/src/vaadin-grid-sorter.js';
|
||||
import 'Frontend/generated/jar-resources/gridConnector.ts';
|
||||
import 'Frontend/generated/jar-resources/vaadin-grid-flow-selection-column.js';
|
||||
import '@vaadin/icon/src/vaadin-icon.js';
|
||||
import '@vaadin/icons/vaadin-iconset.js';
|
||||
import '@vaadin/list-box/src/vaadin-list-box.js';
|
||||
import '@vaadin/item/src/vaadin-item.js';
|
||||
import '@vaadin/login/src/vaadin-login-form.js';
|
||||
import '@vaadin/login/src/vaadin-login-overlay.js';
|
||||
import '@vaadin/markdown/src/vaadin-markdown.js';
|
||||
import '@vaadin/master-detail-layout/src/vaadin-master-detail-layout.js';
|
||||
import 'Frontend/generated/jar-resources/menubarConnector.js';
|
||||
import '@vaadin/menu-bar/src/vaadin-menu-bar.js';
|
||||
import '@vaadin/message-input/src/vaadin-message-input.js';
|
||||
import 'Frontend/generated/jar-resources/messageListConnector.js';
|
||||
import '@vaadin/message-list/src/vaadin-message-list.js';
|
||||
import '@vaadin/notification/src/vaadin-notification.js';
|
||||
import '@vaadin/horizontal-layout/src/vaadin-horizontal-layout.js';
|
||||
import '@vaadin/scroller/src/vaadin-scroller.js';
|
||||
import '@vaadin/vertical-layout/src/vaadin-vertical-layout.js';
|
||||
import '@vaadin/popover/src/vaadin-popover.js';
|
||||
import 'Frontend/generated/jar-resources/vaadin-popover/popover.ts';
|
||||
import '@vaadin/progress-bar/src/vaadin-progress-bar.js';
|
||||
import '@vaadin/radio-group/src/vaadin-radio-button.js';
|
||||
import '@vaadin/radio-group/src/vaadin-radio-group.js';
|
||||
import 'Frontend/generated/jar-resources/ReactRouterOutletElement.tsx';
|
||||
import '@vaadin/select/src/vaadin-select.js';
|
||||
import 'Frontend/generated/jar-resources/selectConnector.js';
|
||||
import 'Frontend/generated/jar-resources/tooltip.ts';
|
||||
import 'Frontend/generated/jar-resources/disableOnClickFunctions.js';
|
||||
import '@vaadin/side-nav/src/vaadin-side-nav.js';
|
||||
import '@vaadin/side-nav/src/vaadin-side-nav-item.js';
|
||||
import '@vaadin/slider/src/vaadin-range-slider.js';
|
||||
import '@vaadin/slider/src/vaadin-slider.js';
|
||||
import '@vaadin/split-layout/src/vaadin-split-layout.js';
|
||||
import '@vaadin/tabs/src/vaadin-tab.js';
|
||||
import '@vaadin/tabsheet/src/vaadin-tabsheet.js';
|
||||
import '@vaadin/tabs/src/vaadin-tabs.js';
|
||||
import 'Frontend/generated/jar-resources/vaadin-big-decimal-field.js';
|
||||
import '@vaadin/email-field/src/vaadin-email-field.js';
|
||||
import '@vaadin/integer-field/src/vaadin-integer-field.js';
|
||||
import '@vaadin/number-field/src/vaadin-number-field.js';
|
||||
import '@vaadin/password-field/src/vaadin-password-field.js';
|
||||
import '@vaadin/text-area/src/vaadin-text-area.js';
|
||||
import '@vaadin/text-field/src/vaadin-text-field.js';
|
||||
import 'Frontend/generated/jar-resources/lit-renderer.ts';
|
||||
import '@vaadin/grid/src/vaadin-grid-tree-toggle.js';
|
||||
import 'Frontend/generated/jar-resources/treeGridConnector.ts';
|
||||
import '@vaadin/upload/src/vaadin-upload.js';
|
||||
import '@vaadin/upload/src/vaadin-upload-button.js';
|
||||
import '@vaadin/upload/src/vaadin-upload-drop-zone.js';
|
||||
import '@vaadin/upload/src/vaadin-upload-file-list.js';
|
||||
import 'Frontend/generated/jar-resources/vaadin-upload-manager-connector.ts';
|
||||
import '@vaadin/virtual-list/src/vaadin-virtual-list.js';
|
||||
import 'Frontend/generated/jar-resources/virtualListConnector.js';
|
||||
import '@vaadin/vaadin-lumo-styles/vaadin-iconset.js';
|
||||
const loadOnDemand = (key) => { return Promise.resolve(0); }
|
||||
window.Vaadin = window.Vaadin || {};
|
||||
window.Vaadin.Flow = window.Vaadin.Flow || {};
|
||||
window.Vaadin.Flow.loadOnDemand = loadOnDemand;
|
||||
window.Vaadin.Flow.resetFocus = () => {
|
||||
let ae=document.activeElement;
|
||||
while(ae&&ae.shadowRoot) ae = ae.shadowRoot.activeElement;
|
||||
return !ae || ae.blur() || ae.focus() || true;
|
||||
}
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
import { injectGlobalWebcomponentCss } from 'Frontend/generated/jar-resources/theme-util.js';
|
||||
|
||||
import '@vaadin/field-highlighter/src/vaadin-field-highlighter.js';
|
||||
import '@vaadin/common-frontend/ConnectionIndicator.js';
|
||||
import '@vaadin/accordion/src/vaadin-accordion.js';
|
||||
import '@vaadin/details/src/vaadin-details.js';
|
||||
import '@vaadin/accordion/src/vaadin-accordion-panel.js';
|
||||
import '@vaadin/app-layout/src/vaadin-app-layout.js';
|
||||
import '@vaadin/button/src/vaadin-button.js';
|
||||
import '@vaadin/app-layout/src/vaadin-drawer-toggle.js';
|
||||
import '@vaadin/avatar/src/vaadin-avatar.js';
|
||||
import '@vaadin/avatar-group/src/vaadin-avatar-group.js';
|
||||
import '@vaadin/badge/src/vaadin-badge.js';
|
||||
import '@vaadin/breadcrumbs/src/vaadin-breadcrumbs-item.js';
|
||||
import '@vaadin/card/src/vaadin-card.js';
|
||||
import '@vaadin/checkbox/src/vaadin-checkbox.js';
|
||||
import '@vaadin/checkbox-group/src/vaadin-checkbox-group.js';
|
||||
import '@vaadin/combo-box/src/vaadin-combo-box.js';
|
||||
import 'Frontend/generated/jar-resources/flow-component-renderer.js';
|
||||
import 'Frontend/generated/jar-resources/flow-component-directive.js';
|
||||
import 'Frontend/generated/jar-resources/comboBoxConnector.js';
|
||||
import '@vaadin/multi-select-combo-box/src/vaadin-multi-select-combo-box.js';
|
||||
import '@vaadin/confirm-dialog/src/vaadin-confirm-dialog.js';
|
||||
import '@vaadin/context-menu/src/vaadin-context-menu.js';
|
||||
import '@vaadin/tooltip/src/vaadin-tooltip.js';
|
||||
import 'Frontend/generated/jar-resources/contextMenuConnector.js';
|
||||
import 'Frontend/generated/jar-resources/contextMenuTargetConnector.js';
|
||||
import '@vaadin/custom-field/src/vaadin-custom-field.js';
|
||||
import '@vaadin/date-picker/src/vaadin-date-picker.js';
|
||||
import 'Frontend/generated/jar-resources/datepickerConnector.js';
|
||||
import '@vaadin/date-time-picker/src/vaadin-date-time-picker.js';
|
||||
import '@vaadin/time-picker/src/vaadin-time-picker.js';
|
||||
import 'Frontend/generated/jar-resources/vaadin-time-picker/timepickerConnector.js';
|
||||
import 'Frontend/generated/jar-resources/vaadin-time-picker/helpers.js';
|
||||
import '@vaadin/dialog/src/vaadin-dialog.js';
|
||||
import 'Frontend/generated/jar-resources/dndConnector.js';
|
||||
import '@vaadin/form-layout/src/vaadin-form-layout.js';
|
||||
import '@vaadin/form-layout/src/vaadin-form-item.js';
|
||||
import '@vaadin/form-layout/src/vaadin-form-row.js';
|
||||
import '@vaadin/grid/src/vaadin-grid-column-group.js';
|
||||
import '@vaadin/grid/src/vaadin-grid.js';
|
||||
import '@vaadin/grid/src/vaadin-grid-column.js';
|
||||
import '@vaadin/grid/src/vaadin-grid-sorter.js';
|
||||
import 'Frontend/generated/jar-resources/gridConnector.ts';
|
||||
import 'Frontend/generated/jar-resources/vaadin-grid-flow-selection-column.js';
|
||||
import '@vaadin/icon/src/vaadin-icon.js';
|
||||
import '@vaadin/icons/vaadin-iconset.js';
|
||||
import '@vaadin/list-box/src/vaadin-list-box.js';
|
||||
import '@vaadin/item/src/vaadin-item.js';
|
||||
import '@vaadin/login/src/vaadin-login-form.js';
|
||||
import '@vaadin/login/src/vaadin-login-overlay.js';
|
||||
import '@vaadin/markdown/src/vaadin-markdown.js';
|
||||
import '@vaadin/master-detail-layout/src/vaadin-master-detail-layout.js';
|
||||
import 'Frontend/generated/jar-resources/menubarConnector.js';
|
||||
import '@vaadin/menu-bar/src/vaadin-menu-bar.js';
|
||||
import '@vaadin/message-input/src/vaadin-message-input.js';
|
||||
import 'Frontend/generated/jar-resources/messageListConnector.js';
|
||||
import '@vaadin/message-list/src/vaadin-message-list.js';
|
||||
import '@vaadin/notification/src/vaadin-notification.js';
|
||||
import '@vaadin/horizontal-layout/src/vaadin-horizontal-layout.js';
|
||||
import '@vaadin/scroller/src/vaadin-scroller.js';
|
||||
import '@vaadin/vertical-layout/src/vaadin-vertical-layout.js';
|
||||
import '@vaadin/popover/src/vaadin-popover.js';
|
||||
import 'Frontend/generated/jar-resources/vaadin-popover/popover.ts';
|
||||
import '@vaadin/progress-bar/src/vaadin-progress-bar.js';
|
||||
import '@vaadin/radio-group/src/vaadin-radio-button.js';
|
||||
import '@vaadin/radio-group/src/vaadin-radio-group.js';
|
||||
import 'Frontend/generated/jar-resources/ReactRouterOutletElement.tsx';
|
||||
import '@vaadin/select/src/vaadin-select.js';
|
||||
import 'Frontend/generated/jar-resources/selectConnector.js';
|
||||
import 'Frontend/generated/jar-resources/tooltip.ts';
|
||||
import 'Frontend/generated/jar-resources/disableOnClickFunctions.js';
|
||||
import '@vaadin/side-nav/src/vaadin-side-nav.js';
|
||||
import '@vaadin/side-nav/src/vaadin-side-nav-item.js';
|
||||
import '@vaadin/slider/src/vaadin-range-slider.js';
|
||||
import '@vaadin/slider/src/vaadin-slider.js';
|
||||
import '@vaadin/split-layout/src/vaadin-split-layout.js';
|
||||
import '@vaadin/tabs/src/vaadin-tab.js';
|
||||
import '@vaadin/tabsheet/src/vaadin-tabsheet.js';
|
||||
import '@vaadin/tabs/src/vaadin-tabs.js';
|
||||
import 'Frontend/generated/jar-resources/vaadin-big-decimal-field.js';
|
||||
import '@vaadin/email-field/src/vaadin-email-field.js';
|
||||
import '@vaadin/integer-field/src/vaadin-integer-field.js';
|
||||
import '@vaadin/number-field/src/vaadin-number-field.js';
|
||||
import '@vaadin/password-field/src/vaadin-password-field.js';
|
||||
import '@vaadin/text-area/src/vaadin-text-area.js';
|
||||
import '@vaadin/text-field/src/vaadin-text-field.js';
|
||||
import 'Frontend/generated/jar-resources/lit-renderer.ts';
|
||||
import '@vaadin/grid/src/vaadin-grid-tree-toggle.js';
|
||||
import 'Frontend/generated/jar-resources/treeGridConnector.ts';
|
||||
import '@vaadin/upload/src/vaadin-upload.js';
|
||||
import '@vaadin/upload/src/vaadin-upload-button.js';
|
||||
import '@vaadin/upload/src/vaadin-upload-drop-zone.js';
|
||||
import '@vaadin/upload/src/vaadin-upload-file-list.js';
|
||||
import 'Frontend/generated/jar-resources/vaadin-upload-manager-connector.ts';
|
||||
import '@vaadin/virtual-list/src/vaadin-virtual-list.js';
|
||||
import 'Frontend/generated/jar-resources/virtualListConnector.js';
|
||||
import '@vaadin/vaadin-lumo-styles/vaadin-iconset.js';
|
||||
const loadOnDemand = (key) => { return Promise.resolve(0); }
|
||||
window.Vaadin = window.Vaadin || {};
|
||||
window.Vaadin.Flow = window.Vaadin.Flow || {};
|
||||
window.Vaadin.Flow.loadOnDemand = loadOnDemand;
|
||||
window.Vaadin.Flow.resetFocus = () => {
|
||||
let ae=document.activeElement;
|
||||
while(ae&&ae.shadowRoot) ae = ae.shadowRoot.activeElement;
|
||||
return !ae || ae.blur() || ae.focus() || true;
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
app-shell-imports.d.ts
|
||||
app-shell-imports.js
|
||||
css.generated.d.ts
|
||||
flow/Flow.tsx
|
||||
flow/ReactAdapter.tsx
|
||||
flow/generated-flow-imports.d.ts
|
||||
flow/generated-flow-imports.js
|
||||
flow/generated-flow-webcomponent-imports.js
|
||||
index.tsx
|
||||
jar-resources/Clipboard.d.ts
|
||||
jar-resources/Clipboard.js
|
||||
jar-resources/Clipboard.js.map
|
||||
jar-resources/Download.d.ts
|
||||
jar-resources/Download.js
|
||||
jar-resources/Download.js.map
|
||||
jar-resources/ElementResize.d.ts
|
||||
jar-resources/ElementResize.js
|
||||
jar-resources/ElementResize.js.map
|
||||
jar-resources/Flow.d.ts
|
||||
jar-resources/Flow.js
|
||||
jar-resources/Flow.js.map
|
||||
jar-resources/FlowBootstrap.d.ts
|
||||
jar-resources/FlowBootstrap.js
|
||||
jar-resources/FlowClient.d.ts
|
||||
jar-resources/FlowClient.js
|
||||
jar-resources/FlowShortcut.js
|
||||
jar-resources/Fullscreen.d.ts
|
||||
jar-resources/Fullscreen.js
|
||||
jar-resources/Fullscreen.js.map
|
||||
jar-resources/Geolocation.d.ts
|
||||
jar-resources/Geolocation.js
|
||||
jar-resources/Geolocation.js.map
|
||||
jar-resources/PageVisibility.d.ts
|
||||
jar-resources/PageVisibility.js
|
||||
jar-resources/PageVisibility.js.map
|
||||
jar-resources/ReactRouterOutletElement.tsx
|
||||
jar-resources/ScreenOrientation.d.ts
|
||||
jar-resources/ScreenOrientation.js
|
||||
jar-resources/ScreenOrientation.js.map
|
||||
jar-resources/WakeLock.d.ts
|
||||
jar-resources/WakeLock.js
|
||||
jar-resources/WakeLock.js.map
|
||||
jar-resources/WebShare.d.ts
|
||||
jar-resources/WebShare.js
|
||||
jar-resources/WebShare.js.map
|
||||
jar-resources/comboBoxConnector.js
|
||||
jar-resources/contextMenuConnector.js
|
||||
jar-resources/contextMenuTargetConnector.js
|
||||
jar-resources/copilot-version.js
|
||||
jar-resources/copilot.d.ts
|
||||
jar-resources/copilot.js
|
||||
jar-resources/copilot/base-panel-Fr0D1ZcU.js
|
||||
jar-resources/copilot/chunk-DiqZc92J.js
|
||||
jar-resources/copilot/consts-CSALuSsm.js
|
||||
jar-resources/copilot/copilot-development-setup-user-guide-Db31eO1T.js
|
||||
jar-resources/copilot/copilot-development-setup-user-guide-utils-DzEVQbWO.js
|
||||
jar-resources/copilot/copilot-devtools-CYwy4U79.js
|
||||
jar-resources/copilot/copilot-error-handler-9OpssAH1.js
|
||||
jar-resources/copilot/copilot-features-plugin-DwQSwtbQ.js
|
||||
jar-resources/copilot/copilot-feedback-plugin-JMYrBCmQ.js
|
||||
jar-resources/copilot/copilot-focus-trap-CaZw1c70.js
|
||||
jar-resources/copilot/copilot-global-vars-later-CWkvR40X.js
|
||||
jar-resources/copilot/copilot-impersonator-plugin-iN25IekB.js
|
||||
jar-resources/copilot/copilot-info-plugin-9l6uSELy.js
|
||||
jar-resources/copilot/copilot-init-step2-tqpZOWcn.js
|
||||
jar-resources/copilot/copilot-log-plugin-CmwIHcBw.js
|
||||
jar-resources/copilot/copilot-message-box-CVAh5PSs.js
|
||||
jar-resources/copilot/copilot-modes-wJyMqHUb.js
|
||||
jar-resources/copilot/copilot-notification-CCNJdNg4.js
|
||||
jar-resources/copilot/copilot-notification-UcomqPI8.js
|
||||
jar-resources/copilot/copilot-server-communicator-impl-B7YDzJpM.js
|
||||
jar-resources/copilot/copilot-settings-panel-qUN2f6RH.js
|
||||
jar-resources/copilot/copilot-shortcuts-BzZuUtjW.js
|
||||
jar-resources/copilot/copilot-stored-machine-state-D6qB_Peh.js
|
||||
jar-resources/copilot/copilot-tree-impl-DxBvMTRa.js
|
||||
jar-resources/copilot/copilot-ui-state-Dc6l_5DA.js
|
||||
jar-resources/copilot/copilot-userinfo-C0s6T_kB.js
|
||||
jar-resources/copilot/copilot-vaadin-versions-CkxDkDmp.js
|
||||
jar-resources/copilot/copy-to-clipboard-4Y12mBRr.js
|
||||
jar-resources/copilot/directive-DWLihZIi.js
|
||||
jar-resources/copilot/directive-helpers-BTt8P8-5.js
|
||||
jar-resources/copilot/dom-utils-Cuv93-tQ.js
|
||||
jar-resources/copilot/early-project-state-LGwavSyI.js
|
||||
jar-resources/copilot/figma-public/figma-api.d.ts
|
||||
jar-resources/copilot/icons-CwakCZgK.js
|
||||
jar-resources/copilot/lit-renderer-fa_B9boC.js
|
||||
jar-resources/copilot/section-panel-ui-state-hOj_RfX_.js
|
||||
jar-resources/copilot/shared/copilot-plugin-support.d.ts
|
||||
jar-resources/copilot/shared/flow-utils.d.ts
|
||||
jar-resources/copilot/stats-CRkPKCLQ.js
|
||||
jar-resources/copilot/track-active-mode-event-DkX0nsC6.js
|
||||
jar-resources/copilot/typescript-BkEBjsia.js
|
||||
jar-resources/datepickerConnector.js
|
||||
jar-resources/disableOnClickFunctions.js
|
||||
jar-resources/dndConnector.js
|
||||
jar-resources/flow-component-directive.js
|
||||
jar-resources/flow-component-renderer.js
|
||||
jar-resources/gridConnector.ts
|
||||
jar-resources/index.d.ts
|
||||
jar-resources/index.js
|
||||
jar-resources/index.js.map
|
||||
jar-resources/lit-renderer.ts
|
||||
jar-resources/menubarConnector.js
|
||||
jar-resources/messageListConnector.js
|
||||
jar-resources/selectConnector.js
|
||||
jar-resources/theme-util.js
|
||||
jar-resources/tooltip.ts
|
||||
jar-resources/treeGridConnector.ts
|
||||
jar-resources/vaadin-big-decimal-field.js
|
||||
jar-resources/vaadin-dev-tools/License.d.ts
|
||||
jar-resources/vaadin-dev-tools/connection.d.ts
|
||||
jar-resources/vaadin-dev-tools/hotswap-scroll.d.ts
|
||||
jar-resources/vaadin-dev-tools/live-reload-connection.d.ts
|
||||
jar-resources/vaadin-dev-tools/pre-trial-splash-screen.d.ts
|
||||
jar-resources/vaadin-dev-tools/vaadin-dev-tools.d.ts
|
||||
jar-resources/vaadin-dev-tools/vaadin-dev-tools.js
|
||||
jar-resources/vaadin-dev-tools/vaadin-dev-tools.js.map
|
||||
jar-resources/vaadin-dev-tools/websocket-connection.d.ts
|
||||
jar-resources/vaadin-grid-flow-selection-column.js
|
||||
jar-resources/vaadin-popover/popover.ts
|
||||
jar-resources/vaadin-time-picker/helpers.js
|
||||
jar-resources/vaadin-time-picker/timepickerConnector.js
|
||||
jar-resources/vaadin-upload-manager-connector.ts
|
||||
jar-resources/virtualListConnector.js
|
||||
jsx-dev-transform/index.ts
|
||||
jsx-dev-transform/jsx-dev-runtime.ts
|
||||
jsx-dev-transform/jsx-runtime.ts
|
||||
layouts.json
|
||||
routes.tsx
|
||||
vaadin-featureflags.js
|
||||
vaadin-react.tsx
|
||||
vaadin.ts
|
||||
@@ -0,0 +1,26 @@
|
||||
/******************************************************************************
|
||||
* This file is auto-generated by Vaadin.
|
||||
* If you want to customize the entry point, you can copy this file or create
|
||||
* your own `index.tsx` in your frontend directory.
|
||||
* By default, the `index.tsx` file should be in `./frontend/` folder.
|
||||
*
|
||||
* NOTE:
|
||||
* - You need to restart the dev-server after adding the new `index.tsx` file.
|
||||
* After that, all modifications to `index.tsx` are recompiled automatically.
|
||||
* - `index.js` is also supported if you don't want to use TypeScript.
|
||||
******************************************************************************/
|
||||
|
||||
import { createElement } from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import { RouterProvider } from 'react-router';
|
||||
import { router } from 'Frontend/generated/routes.js';
|
||||
|
||||
function App() {
|
||||
return <RouterProvider router={router} />;
|
||||
}
|
||||
|
||||
const outlet = document.getElementById('outlet')!;
|
||||
let root = (outlet as any)._root ?? createRoot(outlet);
|
||||
(outlet as any)._root = root;
|
||||
root.render(createElement(App));
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export {};
|
||||
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
* Copyright 2000-2026 Vaadin Ltd.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
/**
|
||||
* Reads the first item from the system clipboard and returns its text/plain
|
||||
* and text/html representations. Either field is {@code null} if the
|
||||
* corresponding MIME type is not present.
|
||||
*
|
||||
* The caller is expected to be inside a transient user gesture and to have
|
||||
* been granted the {@code clipboard-read} permission; otherwise
|
||||
* {@code navigator.clipboard.read} rejects and this function propagates the
|
||||
* rejection.
|
||||
*/
|
||||
async function readClipboardPayload() {
|
||||
const items = await navigator.clipboard.read();
|
||||
if (!items.length) {
|
||||
return null;
|
||||
}
|
||||
const item = items[0];
|
||||
const get = async (type) => item.types.includes(type) ? (await item.getType(type)).text() : null;
|
||||
return {
|
||||
text: await get('text/plain'),
|
||||
html: await get('text/html')
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Re-encodes the given {@code <img>} as {@code image/png} via a canvas
|
||||
* round-trip. The source can be any rasterisable format the browser already
|
||||
* decodes ({@code image/png}, {@code image/jpeg}, {@code image/svg+xml}, ...);
|
||||
* the output is always a {@code Promise<Blob>} of {@code image/png}, the only
|
||||
* image MIME type every browser's asynchronous Clipboard API accepts on write.
|
||||
*
|
||||
* Cross-origin images need {@code crossorigin="anonymous"} on the {@code <img>}
|
||||
* plus matching CORS headers, otherwise the canvas is tainted and
|
||||
* {@code toBlob} throws.
|
||||
*/
|
||||
function imageToPngBlob(img) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const draw = () => {
|
||||
try {
|
||||
const width = img.naturalWidth || img.width;
|
||||
const height = img.naturalHeight || img.height;
|
||||
if (!width || !height) {
|
||||
reject(new Error('image has no intrinsic size'));
|
||||
return;
|
||||
}
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
const ctx = canvas.getContext('2d');
|
||||
if (!ctx) {
|
||||
reject(new Error('2D canvas context not available'));
|
||||
return;
|
||||
}
|
||||
ctx.drawImage(img, 0, 0, width, height);
|
||||
canvas.toBlob((png) => (png ? resolve(png) : reject(new Error('canvas.toBlob returned null'))), 'image/png');
|
||||
}
|
||||
catch (err) {
|
||||
reject(err);
|
||||
}
|
||||
};
|
||||
if (img.complete) {
|
||||
// `complete` is also true for an image that already failed to load or has
|
||||
// an empty src; those have naturalWidth === 0 and their load/error events
|
||||
// have already fired and will never fire again, so we must settle here
|
||||
// rather than wait for an event that never comes.
|
||||
if (img.naturalWidth > 0) {
|
||||
draw();
|
||||
}
|
||||
else {
|
||||
reject(new Error('image failed to load or has empty src'));
|
||||
}
|
||||
}
|
||||
else {
|
||||
img.addEventListener('load', draw, { once: true });
|
||||
img.addEventListener('error', () => reject(new Error('image load failed')), { once: true });
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Writes any combination of text/plain, text/html and image/png to the system
|
||||
* clipboard as a single ClipboardItem. Any argument may be {@code null} to omit
|
||||
* that MIME type; at least one is expected to be non-null (the caller enforces
|
||||
* this). The image argument is the source {@code <img>}; it is re-encoded as
|
||||
* {@code image/png} via {@link imageToPngBlob} and the resulting
|
||||
* {@code Promise<Blob>} is fed directly to {@code ClipboardItem} so the
|
||||
* {@code navigator.clipboard.write} call stays synchronous inside the user
|
||||
* gesture (Safari otherwise loses activation on the first await).
|
||||
*
|
||||
* The caller is expected to be inside a transient user gesture; otherwise
|
||||
* {@code navigator.clipboard.write} rejects and this function propagates the
|
||||
* rejection.
|
||||
*
|
||||
* Resolves with the {@code text/plain} value if present, otherwise with the
|
||||
* {@code text/html} value, otherwise with {@code null} (image-only case).
|
||||
*/
|
||||
async function writeClipboardPayload(text, html, image) {
|
||||
const entries = {};
|
||||
if (text !== null) {
|
||||
entries['text/plain'] = text;
|
||||
}
|
||||
if (html !== null) {
|
||||
entries['text/html'] = html;
|
||||
}
|
||||
if (image !== null) {
|
||||
entries['image/png'] = imageToPngBlob(image);
|
||||
}
|
||||
await navigator.clipboard.write([new ClipboardItem(entries)]);
|
||||
return text !== null ? text : html;
|
||||
}
|
||||
/**
|
||||
* Posts each file from a {@code paste} event's {@code clipboardData.files} as
|
||||
* its own XHR to the URL stored as the named attribute on {@code element}. The
|
||||
* wire format matches vaadin-upload: raw body, percent-encoded {@code X-Filename}
|
||||
* header, MIME type in {@code Content-Type}.
|
||||
*
|
||||
* Each upload is processed in its own HTTP request, so the UI changes the
|
||||
* server-side UploadHandler makes through {@code UI.access} are applied to the
|
||||
* state tree but not sent to the client by the upload response itself. Once
|
||||
* every upload of the paste has settled this helper dispatches a
|
||||
* {@code vaadin-paste-upload-finished} event back on {@code element}; a
|
||||
* server-side listener for that event triggers a normal Flow round trip that
|
||||
* flushes those pending UI changes — so the API works without {@code @Push},
|
||||
* exactly like a regular upload completing through the Upload component.
|
||||
*
|
||||
* Editable targets ({@code <input>}, {@code <textarea>}, {@code contentEditable})
|
||||
* are not given any special treatment here: browsers do not paste files into
|
||||
* those elements, so a paste containing a file in a focused text field is
|
||||
* still a "the user tried to drop a file on the page" event from the
|
||||
* application's point of view.
|
||||
*/
|
||||
// Monotonic counter incremented once per paste gesture so server-side
|
||||
// handlers can correlate the parallel fetch POSTs that belong to the same
|
||||
// paste, and order pastes against each other. Scoped to the browser tab —
|
||||
// a different tab gets its own counter, but no server-side state crosses
|
||||
// tabs in this flow.
|
||||
let pasteSequence = 0;
|
||||
function uploadPastedFiles(event, element, urlAttribute) {
|
||||
const files = event.clipboardData?.files;
|
||||
if (!files || files.length === 0) {
|
||||
return;
|
||||
}
|
||||
const url = element.getAttribute(urlAttribute);
|
||||
if (!url) {
|
||||
return;
|
||||
}
|
||||
pasteSequence += 1;
|
||||
const pasteId = String(pasteSequence);
|
||||
// Surface the file count too: the batch server handler needs it to know
|
||||
// when the paste has been fully delivered (one fetch per file means the
|
||||
// server only observes arrivals, not the total).
|
||||
const fileCount = String(files.length);
|
||||
const uploads = [];
|
||||
for (const file of files) {
|
||||
const headers = {
|
||||
'X-Filename': encodeURIComponent(file.name),
|
||||
'X-Paste-Id': pasteId,
|
||||
'X-Paste-File-Count': fileCount
|
||||
};
|
||||
if (file.type) {
|
||||
headers['Content-Type'] = file.type;
|
||||
}
|
||||
// The per-file UploadHandler callback runs as each POST is processed;
|
||||
// log network/connectivity failures the server will never see otherwise.
|
||||
uploads.push(fetch(url, { method: 'POST', headers: headers, body: file }).catch((err) => {
|
||||
console.error('Vaadin clipboard file upload failed', err);
|
||||
}));
|
||||
}
|
||||
// Tell the server the paste's uploads are done so it can flush the queued
|
||||
// UI updates without requiring @Push. The upload response is written only
|
||||
// after the handler's UI.access task has applied its changes to the state
|
||||
// tree, so by the time a fetch settles those changes are guaranteed to be
|
||||
// picked up by this round trip.
|
||||
Promise.allSettled(uploads).then(() => {
|
||||
element.dispatchEvent(new CustomEvent('vaadin-paste-upload-finished'));
|
||||
});
|
||||
}
|
||||
const $wnd = window;
|
||||
$wnd.Vaadin ??= {};
|
||||
$wnd.Vaadin.Flow ??= {};
|
||||
$wnd.Vaadin.Flow.clipboard = {
|
||||
readPayload: readClipboardPayload,
|
||||
writePayload: writeClipboardPayload,
|
||||
uploadPastedFiles: uploadPastedFiles
|
||||
};
|
||||
export {};
|
||||
//# sourceMappingURL=Clipboard.js.map
|
||||
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user