Generated project
This commit is contained in:
21
.gitignore
vendored
Normal file
21
.gitignore
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
/target/
|
||||
.idea/
|
||||
.vscode/
|
||||
.settings
|
||||
.project
|
||||
.classpath
|
||||
|
||||
*.iml
|
||||
.DS_Store
|
||||
|
||||
# The following files are generated/updated by vaadin-maven-plugin
|
||||
node_modules/
|
||||
src/main/frontend/generated/
|
||||
pnpmfile.js
|
||||
vite.generated.ts
|
||||
|
||||
# Browser drivers for local integration tests
|
||||
drivers/
|
||||
# Error screenshots generated by TestBench for failed integration tests
|
||||
error-screenshots/
|
||||
webpack.generated.js
|
118
.mvn/wrapper/MavenWrapperDownloader.java
vendored
Normal file
118
.mvn/wrapper/MavenWrapperDownloader.java
vendored
Normal file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright 2007-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.nio.channels.*;
|
||||
import java.util.Properties;
|
||||
|
||||
public class MavenWrapperDownloader {
|
||||
|
||||
private static final String WRAPPER_VERSION = "0.5.6";
|
||||
/**
|
||||
* Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is
|
||||
* provided.
|
||||
*/
|
||||
private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
|
||||
+ WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
|
||||
|
||||
/**
|
||||
* Path to the maven-wrapper.properties file, which might contain a downloadUrl
|
||||
* property to use instead of the default one.
|
||||
*/
|
||||
private static final String MAVEN_WRAPPER_PROPERTIES_PATH = ".mvn/wrapper/maven-wrapper.properties";
|
||||
|
||||
/**
|
||||
* Path where the maven-wrapper.jar will be saved to.
|
||||
*/
|
||||
private static final String MAVEN_WRAPPER_JAR_PATH = ".mvn/wrapper/maven-wrapper.jar";
|
||||
|
||||
/**
|
||||
* Name of the property which should be used to override the default download
|
||||
* url for the wrapper.
|
||||
*/
|
||||
private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
|
||||
|
||||
public static void main(String args[]) {
|
||||
System.out.println("- Downloader started");
|
||||
File baseDirectory = new File(args[0]);
|
||||
System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
|
||||
|
||||
// If the maven-wrapper.properties exists, read it and check if it contains a
|
||||
// custom
|
||||
// wrapperUrl parameter.
|
||||
File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
|
||||
String url = DEFAULT_DOWNLOAD_URL;
|
||||
if (mavenWrapperPropertyFile.exists()) {
|
||||
FileInputStream mavenWrapperPropertyFileInputStream = null;
|
||||
try {
|
||||
mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
|
||||
Properties mavenWrapperProperties = new Properties();
|
||||
mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
|
||||
url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
|
||||
} catch (IOException e) {
|
||||
System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
|
||||
} finally {
|
||||
try {
|
||||
if (mavenWrapperPropertyFileInputStream != null) {
|
||||
mavenWrapperPropertyFileInputStream.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// Ignore ...
|
||||
}
|
||||
}
|
||||
}
|
||||
System.out.println("- Downloading from: " + url);
|
||||
|
||||
File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
|
||||
if (!outputFile.getParentFile().exists()) {
|
||||
if (!outputFile.getParentFile().mkdirs()) {
|
||||
System.out.println(
|
||||
"- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
|
||||
}
|
||||
}
|
||||
System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
|
||||
try {
|
||||
downloadFileFromURL(url, outputFile);
|
||||
System.out.println("Done");
|
||||
System.exit(0);
|
||||
} catch (Throwable e) {
|
||||
System.out.println("- Error downloading");
|
||||
e.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
private static void downloadFileFromURL(String urlString, File destination) throws Exception {
|
||||
if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
|
||||
String username = System.getenv("MVNW_USERNAME");
|
||||
char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
|
||||
Authenticator.setDefault(new Authenticator() {
|
||||
@Override
|
||||
protected PasswordAuthentication getPasswordAuthentication() {
|
||||
return new PasswordAuthentication(username, password);
|
||||
}
|
||||
});
|
||||
}
|
||||
URL website = new URL(urlString);
|
||||
ReadableByteChannel rbc;
|
||||
rbc = Channels.newChannel(website.openStream());
|
||||
FileOutputStream fos = new FileOutputStream(destination);
|
||||
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
|
||||
fos.close();
|
||||
rbc.close();
|
||||
}
|
||||
|
||||
}
|
BIN
.mvn/wrapper/maven-wrapper.jar
vendored
Normal file
BIN
.mvn/wrapper/maven-wrapper.jar
vendored
Normal file
Binary file not shown.
18
.mvn/wrapper/maven-wrapper.properties
vendored
Normal file
18
.mvn/wrapper/maven-wrapper.properties
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.4/apache-maven-3.8.4-bin.zip
|
||||
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar
|
4
Dockerfile
Normal file
4
Dockerfile
Normal file
@@ -0,0 +1,4 @@
|
||||
FROM eclipse-temurin:21-jre
|
||||
COPY target/*.jar app.jar
|
||||
EXPOSE 8080
|
||||
ENTRYPOINT ["java", "-jar", "/app.jar"]
|
24
LICENSE.md
Normal file
24
LICENSE.md
Normal file
@@ -0,0 +1,24 @@
|
||||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors
|
||||
of this software dedicate any and all copyright interest in the
|
||||
software to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of
|
||||
relinquishment in perpetuity of all present and future rights to this
|
||||
software under copyright law.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For more information, please refer to <http://unlicense.org>
|
105
README.md
Normal file
105
README.md
Normal file
@@ -0,0 +1,105 @@
|
||||
# Firmware HQ
|
||||
|
||||
This project can be used as a starting point to create your own Vaadin application with Spring Boot.
|
||||
It contains all the necessary configuration and some placeholder files to get you started.
|
||||
|
||||
## Running the application
|
||||
|
||||
The project is a standard Maven project. To run it from the command line,
|
||||
type `mvnw` (Windows), or `./mvnw` (Mac & Linux), then open
|
||||
http://localhost:8080 in your browser.
|
||||
|
||||
You can also import the project to your IDE of choice as you would with any
|
||||
Maven project. Read more on [how to import Vaadin projects to different IDEs](https://vaadin.com/docs/latest/guide/step-by-step/importing) (Eclipse, IntelliJ IDEA, NetBeans, and VS Code).
|
||||
|
||||
## Deploying to Production
|
||||
|
||||
To create a production build, call `mvnw clean package -Pproduction` (Windows),
|
||||
or `./mvnw clean package -Pproduction` (Mac & Linux).
|
||||
This will build a JAR file with all the dependencies and front-end resources,
|
||||
ready to be deployed. The file can be found in the `target` folder after the build completes.
|
||||
|
||||
Once the JAR file is built, you can run it using
|
||||
`java -jar target/website-1.0-SNAPSHOT.jar`
|
||||
|
||||
## Project structure
|
||||
|
||||
- `MainLayout.java` in `src/main/java` contains the navigation setup (i.e., the
|
||||
side/top bar and the main menu). This setup uses
|
||||
[App Layout](https://vaadin.com/docs/components/app-layout).
|
||||
- `views` package in `src/main/java` contains the server-side Java views of your application.
|
||||
- `views` folder in `src/main/frontend` contains the client-side JavaScript views of your application.
|
||||
- `themes` folder in `src/main/frontend` contains the custom CSS styles.
|
||||
|
||||
## Useful links
|
||||
|
||||
- Read the documentation at [vaadin.com/docs](https://vaadin.com/docs).
|
||||
- Follow the tutorial at [vaadin.com/docs/latest/tutorial/overview](https://vaadin.com/docs/latest/tutorial/overview).
|
||||
- Create new projects at [start.vaadin.com](https://start.vaadin.com/).
|
||||
- Search UI components and their usage examples at [vaadin.com/docs/latest/components](https://vaadin.com/docs/latest/components).
|
||||
- View use case applications that demonstrate Vaadin capabilities at [vaadin.com/examples-and-demos](https://vaadin.com/examples-and-demos).
|
||||
- Build any UI without custom CSS by discovering Vaadin's set of [CSS utility classes](https://vaadin.com/docs/styling/lumo/utility-classes).
|
||||
- Find a collection of solutions to common use cases at [cookbook.vaadin.com](https://cookbook.vaadin.com/).
|
||||
- Find add-ons at [vaadin.com/directory](https://vaadin.com/directory).
|
||||
- Ask questions on [Stack Overflow](https://stackoverflow.com/questions/tagged/vaadin) or join our [Discord channel](https://discord.gg/MYFq5RTbBn).
|
||||
- Report issues, create pull requests in [GitHub](https://github.com/vaadin).
|
||||
|
||||
|
||||
## Deploying using Docker
|
||||
|
||||
To build the Dockerized version of the project, run
|
||||
|
||||
```
|
||||
mvn clean package -Pproduction
|
||||
docker build . -t website:latest
|
||||
```
|
||||
|
||||
Once the Docker image is correctly built, you can test it locally using
|
||||
|
||||
```
|
||||
docker run -p 8080:8080 website:latest
|
||||
```
|
||||
|
||||
|
||||
## Deploying using Kubernetes
|
||||
|
||||
We assume here that you have the Kubernetes cluster from Docker Desktop running (can be enabled in the settings).
|
||||
|
||||
First build the Docker image for your application. You then need to make the Docker image available to you cluster. With Docker Desktop Kubernetes, this happens automatically. With Minikube, you can run `eval $(minikube docker-env)` and then build the image to make it available. For other clusters, you need to publish to a Docker repository or check the documentation for the cluster.
|
||||
|
||||
The included `kubernetes.yaml` sets up a deployment with 2 pods (server instances) and a load balancer service. You can deploy the application on a Kubernetes cluster using
|
||||
|
||||
```
|
||||
kubectl apply -f kubernetes.yaml
|
||||
```
|
||||
|
||||
If everything works, you can access your application by opening http://localhost:8000/.
|
||||
If you have something else running on port 8000, you need to change the load balancer port in `kubernetes.yaml`.
|
||||
|
||||
Tip: If you want to understand which pod your requests go to, you can add the value of `VaadinServletRequest.getCurrent().getLocalAddr()` somewhere in your UI.
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
If something is not working, you can try one of the following commands to see what is deployed and their status.
|
||||
|
||||
```
|
||||
kubectl get pods
|
||||
kubectl get services
|
||||
kubectl get deployments
|
||||
```
|
||||
|
||||
If the pods say `Container image "website:latest" is not present with pull policy of Never` then you have not built your application using Docker or there is a mismatch in the name. Use `docker images ls` to see which images are available.
|
||||
|
||||
If you need even more information, you can run
|
||||
|
||||
```
|
||||
kubectl cluster-info dump
|
||||
```
|
||||
|
||||
that will probably give you too much information but might reveal the cause of a problem.
|
||||
|
||||
If you want to remove your whole deployment and start over, run
|
||||
|
||||
```
|
||||
kubectl delete -f kubernetes.yaml
|
||||
```
|
40
kubernetes.yaml
Normal file
40
kubernetes.yaml
Normal file
@@ -0,0 +1,40 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: website
|
||||
namespace: default
|
||||
spec:
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: website
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: website
|
||||
spec:
|
||||
containers:
|
||||
- name: website
|
||||
image: website:latest
|
||||
imagePullPolicy: Never
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
resources:
|
||||
limits:
|
||||
memory: 512Mi
|
||||
cpu: '1'
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: website-balancer
|
||||
spec:
|
||||
selector:
|
||||
app: website
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 8000 # The port to expose to the outside
|
||||
targetPort: 8080 # The port the application is running on in the pods
|
||||
type: LoadBalancer
|
||||
sessionAffinity: ClientIP
|
316
mvnw
vendored
Executable file
316
mvnw
vendored
Executable file
@@ -0,0 +1,316 @@
|
||||
#!/bin/sh
|
||||
# ----------------------------------------------------------------------------
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Maven Start Up Batch script
|
||||
#
|
||||
# Required ENV vars:
|
||||
# ------------------
|
||||
# JAVA_HOME - location of a JDK home dir
|
||||
#
|
||||
# Optional ENV vars
|
||||
# -----------------
|
||||
# M2_HOME - location of maven2's installed home dir
|
||||
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||
# e.g. to debug Maven itself, use
|
||||
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
if [ -z "$MAVEN_SKIP_RC" ] ; then
|
||||
|
||||
if [ -f /usr/local/etc/mavenrc ] ; then
|
||||
. /usr/local/etc/mavenrc
|
||||
fi
|
||||
|
||||
if [ -f /etc/mavenrc ] ; then
|
||||
. /etc/mavenrc
|
||||
fi
|
||||
|
||||
if [ -f "$HOME/.mavenrc" ] ; then
|
||||
. "$HOME/.mavenrc"
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
# OS specific support. $var _must_ be set to either true or false.
|
||||
cygwin=false;
|
||||
darwin=false;
|
||||
mingw=false
|
||||
case "`uname`" in
|
||||
CYGWIN*) cygwin=true ;;
|
||||
MINGW*) mingw=true;;
|
||||
Darwin*) darwin=true
|
||||
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
|
||||
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
|
||||
if [ -z "$JAVA_HOME" ]; then
|
||||
if [ -x "/usr/libexec/java_home" ]; then
|
||||
export JAVA_HOME="`/usr/libexec/java_home`"
|
||||
else
|
||||
export JAVA_HOME="/Library/Java/Home"
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -z "$JAVA_HOME" ] ; then
|
||||
if [ -r /etc/gentoo-release ] ; then
|
||||
JAVA_HOME=`java-config --jre-home`
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$M2_HOME" ] ; then
|
||||
## resolve links - $0 may be a link to maven's home
|
||||
PRG="$0"
|
||||
|
||||
# need this for relative symlinks
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG="`dirname "$PRG"`/$link"
|
||||
fi
|
||||
done
|
||||
|
||||
saveddir=`pwd`
|
||||
|
||||
M2_HOME=`dirname "$PRG"`/..
|
||||
|
||||
# make it fully qualified
|
||||
M2_HOME=`cd "$M2_HOME" && pwd`
|
||||
|
||||
cd "$saveddir"
|
||||
# echo Using m2 at $M2_HOME
|
||||
fi
|
||||
|
||||
# For Cygwin, ensure paths are in UNIX format before anything is touched
|
||||
if $cygwin ; then
|
||||
[ -n "$M2_HOME" ] &&
|
||||
M2_HOME=`cygpath --unix "$M2_HOME"`
|
||||
[ -n "$JAVA_HOME" ] &&
|
||||
JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
|
||||
[ -n "$CLASSPATH" ] &&
|
||||
CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
|
||||
fi
|
||||
|
||||
# For Mingw, ensure paths are in UNIX format before anything is touched
|
||||
if $mingw ; then
|
||||
[ -n "$M2_HOME" ] &&
|
||||
M2_HOME="`(cd "$M2_HOME"; pwd)`"
|
||||
[ -n "$JAVA_HOME" ] &&
|
||||
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ]; then
|
||||
javaExecutable="`which javac`"
|
||||
if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
|
||||
# readlink(1) is not available as standard on Solaris 10.
|
||||
readLink=`which readlink`
|
||||
if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
|
||||
if $darwin ; then
|
||||
javaHome="`dirname \"$javaExecutable\"`"
|
||||
javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
|
||||
else
|
||||
javaExecutable="`readlink -f \"$javaExecutable\"`"
|
||||
fi
|
||||
javaHome="`dirname \"$javaExecutable\"`"
|
||||
javaHome=`expr "$javaHome" : '\(.*\)/bin'`
|
||||
JAVA_HOME="$javaHome"
|
||||
export JAVA_HOME
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$JAVACMD" ] ; then
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
else
|
||||
JAVACMD="`\\unset -f command; \\command -v java`"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
echo "Error: JAVA_HOME is not defined correctly." >&2
|
||||
echo " We cannot execute $JAVACMD" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ] ; then
|
||||
echo "Warning: JAVA_HOME environment variable is not set."
|
||||
fi
|
||||
|
||||
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
|
||||
|
||||
# traverses directory structure from process work directory to filesystem root
|
||||
# first directory with .mvn subdirectory is considered project base directory
|
||||
find_maven_basedir() {
|
||||
|
||||
if [ -z "$1" ]
|
||||
then
|
||||
echo "Path not specified to find_maven_basedir"
|
||||
return 1
|
||||
fi
|
||||
|
||||
basedir="$1"
|
||||
wdir="$1"
|
||||
while [ "$wdir" != '/' ] ; do
|
||||
if [ -d "$wdir"/.mvn ] ; then
|
||||
basedir=$wdir
|
||||
break
|
||||
fi
|
||||
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
|
||||
if [ -d "${wdir}" ]; then
|
||||
wdir=`cd "$wdir/.."; pwd`
|
||||
fi
|
||||
# end of workaround
|
||||
done
|
||||
echo "${basedir}"
|
||||
}
|
||||
|
||||
# concatenates all lines of a file
|
||||
concat_lines() {
|
||||
if [ -f "$1" ]; then
|
||||
echo "$(tr -s '\n' ' ' < "$1")"
|
||||
fi
|
||||
}
|
||||
|
||||
BASE_DIR=`find_maven_basedir "$(pwd)"`
|
||||
if [ -z "$BASE_DIR" ]; then
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
##########################################################################################
|
||||
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
|
||||
# This allows using the maven wrapper in projects that prohibit checking in binary data.
|
||||
##########################################################################################
|
||||
if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Found .mvn/wrapper/maven-wrapper.jar"
|
||||
fi
|
||||
else
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
|
||||
fi
|
||||
if [ -n "$MVNW_REPOURL" ]; then
|
||||
jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
|
||||
else
|
||||
jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
|
||||
fi
|
||||
while IFS="=" read key value; do
|
||||
case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
|
||||
esac
|
||||
done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Downloading from: $jarUrl"
|
||||
fi
|
||||
wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
|
||||
if $cygwin; then
|
||||
wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
|
||||
fi
|
||||
|
||||
if command -v wget > /dev/null; then
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Found wget ... using wget"
|
||||
fi
|
||||
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
|
||||
wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
|
||||
else
|
||||
wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
|
||||
fi
|
||||
elif command -v curl > /dev/null; then
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Found curl ... using curl"
|
||||
fi
|
||||
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
|
||||
curl -o "$wrapperJarPath" "$jarUrl" -f
|
||||
else
|
||||
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
|
||||
fi
|
||||
|
||||
else
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Falling back to using Java to download"
|
||||
fi
|
||||
javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
|
||||
# For Cygwin, switch paths to Windows format before running javac
|
||||
if $cygwin; then
|
||||
javaClass=`cygpath --path --windows "$javaClass"`
|
||||
fi
|
||||
if [ -e "$javaClass" ]; then
|
||||
if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo " - Compiling MavenWrapperDownloader.java ..."
|
||||
fi
|
||||
# Compiling the Java class
|
||||
("$JAVA_HOME/bin/javac" "$javaClass")
|
||||
fi
|
||||
if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
|
||||
# Running the downloader
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo " - Running MavenWrapperDownloader.java ..."
|
||||
fi
|
||||
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
##########################################################################################
|
||||
# End of extension
|
||||
##########################################################################################
|
||||
|
||||
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo $MAVEN_PROJECTBASEDIR
|
||||
fi
|
||||
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin; then
|
||||
[ -n "$M2_HOME" ] &&
|
||||
M2_HOME=`cygpath --path --windows "$M2_HOME"`
|
||||
[ -n "$JAVA_HOME" ] &&
|
||||
JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
|
||||
[ -n "$CLASSPATH" ] &&
|
||||
CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
|
||||
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
|
||||
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
|
||||
fi
|
||||
|
||||
# Provide a "standardized" way to retrieve the CLI args that will
|
||||
# work with both Windows and non-Windows executions.
|
||||
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
|
||||
export MAVEN_CMD_LINE_ARGS
|
||||
|
||||
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||
|
||||
exec "$JAVACMD" \
|
||||
$MAVEN_OPTS \
|
||||
$MAVEN_DEBUG_OPTS \
|
||||
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
|
||||
"-Dmaven.home=${M2_HOME}" \
|
||||
"-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
|
||||
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
|
188
mvnw.cmd
vendored
Normal file
188
mvnw.cmd
vendored
Normal file
@@ -0,0 +1,188 @@
|
||||
@REM ----------------------------------------------------------------------------
|
||||
@REM Licensed to the Apache Software Foundation (ASF) under one
|
||||
@REM or more contributor license agreements. See the NOTICE file
|
||||
@REM distributed with this work for additional information
|
||||
@REM regarding copyright ownership. The ASF licenses this file
|
||||
@REM to you under the Apache License, Version 2.0 (the
|
||||
@REM "License"); you may not use this file except in compliance
|
||||
@REM with the License. You may obtain a copy of the License at
|
||||
@REM
|
||||
@REM http://www.apache.org/licenses/LICENSE-2.0
|
||||
@REM
|
||||
@REM Unless required by applicable law or agreed to in writing,
|
||||
@REM software distributed under the License is distributed on an
|
||||
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
@REM KIND, either express or implied. See the License for the
|
||||
@REM specific language governing permissions and limitations
|
||||
@REM under the License.
|
||||
@REM ----------------------------------------------------------------------------
|
||||
|
||||
@REM ----------------------------------------------------------------------------
|
||||
@REM Maven Start Up Batch script
|
||||
@REM
|
||||
@REM Required ENV vars:
|
||||
@REM JAVA_HOME - location of a JDK home dir
|
||||
@REM
|
||||
@REM Optional ENV vars
|
||||
@REM M2_HOME - location of maven2's installed home dir
|
||||
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
|
||||
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
|
||||
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||
@REM e.g. to debug Maven itself, use
|
||||
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||
@REM ----------------------------------------------------------------------------
|
||||
|
||||
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
|
||||
@echo off
|
||||
@REM set title of command window
|
||||
title %0
|
||||
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
|
||||
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
|
||||
|
||||
@REM set %HOME% to equivalent of $HOME
|
||||
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
|
||||
|
||||
@REM Execute a user defined script before this one
|
||||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
|
||||
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
|
||||
if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
|
||||
if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
|
||||
:skipRcPre
|
||||
|
||||
@setlocal
|
||||
|
||||
set ERROR_CODE=0
|
||||
|
||||
@REM To isolate internal variables from possible post scripts, we use another setlocal
|
||||
@setlocal
|
||||
|
||||
@REM ==== START VALIDATION ====
|
||||
if not "%JAVA_HOME%" == "" goto OkJHome
|
||||
|
||||
echo.
|
||||
echo Error: JAVA_HOME not found in your environment. >&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||
echo location of your Java installation. >&2
|
||||
echo.
|
||||
goto error
|
||||
|
||||
:OkJHome
|
||||
if exist "%JAVA_HOME%\bin\java.exe" goto init
|
||||
|
||||
echo.
|
||||
echo Error: JAVA_HOME is set to an invalid directory. >&2
|
||||
echo JAVA_HOME = "%JAVA_HOME%" >&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||
echo location of your Java installation. >&2
|
||||
echo.
|
||||
goto error
|
||||
|
||||
@REM ==== END VALIDATION ====
|
||||
|
||||
:init
|
||||
|
||||
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
|
||||
@REM Fallback to current working directory if not found.
|
||||
|
||||
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
|
||||
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
|
||||
|
||||
set EXEC_DIR=%CD%
|
||||
set WDIR=%EXEC_DIR%
|
||||
:findBaseDir
|
||||
IF EXIST "%WDIR%"\.mvn goto baseDirFound
|
||||
cd ..
|
||||
IF "%WDIR%"=="%CD%" goto baseDirNotFound
|
||||
set WDIR=%CD%
|
||||
goto findBaseDir
|
||||
|
||||
:baseDirFound
|
||||
set MAVEN_PROJECTBASEDIR=%WDIR%
|
||||
cd "%EXEC_DIR%"
|
||||
goto endDetectBaseDir
|
||||
|
||||
:baseDirNotFound
|
||||
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
|
||||
cd "%EXEC_DIR%"
|
||||
|
||||
:endDetectBaseDir
|
||||
|
||||
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
|
||||
|
||||
@setlocal EnableExtensions EnableDelayedExpansion
|
||||
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
|
||||
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
|
||||
|
||||
:endReadAdditionalConfig
|
||||
|
||||
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
|
||||
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
|
||||
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||
|
||||
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
|
||||
|
||||
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
|
||||
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
|
||||
)
|
||||
|
||||
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
|
||||
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
|
||||
if exist %WRAPPER_JAR% (
|
||||
if "%MVNW_VERBOSE%" == "true" (
|
||||
echo Found %WRAPPER_JAR%
|
||||
)
|
||||
) else (
|
||||
if not "%MVNW_REPOURL%" == "" (
|
||||
SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
|
||||
)
|
||||
if "%MVNW_VERBOSE%" == "true" (
|
||||
echo Couldn't find %WRAPPER_JAR%, downloading it ...
|
||||
echo Downloading from: %DOWNLOAD_URL%
|
||||
)
|
||||
|
||||
powershell -Command "&{"^
|
||||
"$webclient = new-object System.Net.WebClient;"^
|
||||
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
|
||||
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
|
||||
"}"^
|
||||
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
|
||||
"}"
|
||||
if "%MVNW_VERBOSE%" == "true" (
|
||||
echo Finished downloading %WRAPPER_JAR%
|
||||
)
|
||||
)
|
||||
@REM End of extension
|
||||
|
||||
@REM Provide a "standardized" way to retrieve the CLI args that will
|
||||
@REM work with both Windows and non-Windows executions.
|
||||
set MAVEN_CMD_LINE_ARGS=%*
|
||||
|
||||
%MAVEN_JAVA_EXE% ^
|
||||
%JVM_CONFIG_MAVEN_PROPS% ^
|
||||
%MAVEN_OPTS% ^
|
||||
%MAVEN_DEBUG_OPTS% ^
|
||||
-classpath %WRAPPER_JAR% ^
|
||||
"-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
|
||||
%WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
|
||||
if ERRORLEVEL 1 goto error
|
||||
goto end
|
||||
|
||||
:error
|
||||
set ERROR_CODE=1
|
||||
|
||||
:end
|
||||
@endlocal & set ERROR_CODE=%ERROR_CODE%
|
||||
|
||||
if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
|
||||
@REM check for post script, once with legacy .bat ending and once with .cmd ending
|
||||
if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
|
||||
if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
|
||||
:skipRcPost
|
||||
|
||||
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
|
||||
if "%MAVEN_BATCH_PAUSE%"=="on" pause
|
||||
|
||||
if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
|
||||
|
||||
cmd /C exit /B %ERROR_CODE%
|
216
pom.xml
Normal file
216
pom.xml
Normal file
@@ -0,0 +1,216 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<!-- Project from https://start.vaadin.com/project/5dcf3df5-dbcb-4a18-897d-eb1a8285558c -->
|
||||
<groupId>dev.mars3142.fhq</groupId>
|
||||
<artifactId>website</artifactId>
|
||||
<name>website</name>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<properties>
|
||||
<java.version>21</java.version>
|
||||
<vaadin.version>24.4.0.beta4</vaadin.version>
|
||||
</properties>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>3.2.6</version>
|
||||
</parent>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>vaadin-prereleases</id>
|
||||
<url>https://maven.vaadin.com/vaadin-prereleases</url>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>Vaadin Directory</id>
|
||||
<url>https://maven.vaadin.com/vaadin-addons</url>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>vaadin-prereleases</id>
|
||||
<url>https://maven.vaadin.com/vaadin-prereleases</url>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.vaadin</groupId>
|
||||
<artifactId>vaadin-bom</artifactId>
|
||||
<version>${vaadin.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.vaadin</groupId>
|
||||
<!-- Replace artifactId with vaadin-core to use only free components -->
|
||||
<artifactId>vaadin</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.vaadin</groupId>
|
||||
<artifactId>vaadin-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.parttio</groupId>
|
||||
<artifactId>line-awesome</artifactId>
|
||||
<version>2.0.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-validation</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-devtools</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.vaadin</groupId>
|
||||
<artifactId>vaadin-testbench-junit5</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<defaultGoal>spring-boot:run</defaultGoal>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>com.vaadin</groupId>
|
||||
<artifactId>vaadin-maven-plugin</artifactId>
|
||||
<version>${vaadin.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>prepare-frontend</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<!-- Production mode is activated using -Pproduction -->
|
||||
<id>production</id>
|
||||
<dependencies>
|
||||
<!-- Exclude development dependencies from production -->
|
||||
<dependency>
|
||||
<groupId>com.vaadin</groupId>
|
||||
<artifactId>vaadin-core</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.vaadin</groupId>
|
||||
<artifactId>vaadin-dev</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>com.vaadin</groupId>
|
||||
<artifactId>vaadin-maven-plugin</artifactId>
|
||||
<version>${vaadin.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>build-frontend</goal>
|
||||
</goals>
|
||||
<phase>compile</phase>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
<id>it</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>start-spring-boot</id>
|
||||
<phase>pre-integration-test</phase>
|
||||
<goals>
|
||||
<goal>start</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>stop-spring-boot</id>
|
||||
<phase>post-integration-test</phase>
|
||||
<goals>
|
||||
<goal>stop</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<!-- Runs the integration tests (*IT) after the server is started -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>integration-test</goal>
|
||||
<goal>verify</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<trimStackTrace>false</trimStackTrace>
|
||||
<enableAssertions>true</enableAssertions>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
|
||||
</profiles>
|
||||
</project>
|
26
src/main/frontend/themes/website/main-layout.css
Normal file
26
src/main/frontend/themes/website/main-layout.css
Normal file
@@ -0,0 +1,26 @@
|
||||
header nav a:any-link {
|
||||
text-decoration: none;
|
||||
padding: 0 var(--lumo-space-s);
|
||||
border-radius: var(--lumo-border-radius-m);
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
header nav a:hover {
|
||||
color: var(--lumo-header-text-color);
|
||||
}
|
||||
|
||||
header nav a:active {
|
||||
background-color: var(--lumo-contrast-5pct);
|
||||
}
|
||||
|
||||
header nav a:focus-visible {
|
||||
box-shadow: 0 0 0 2px var(--lumo-primary-color-50pct);
|
||||
}
|
||||
|
||||
header nav a[highlight] vaadin-icon {
|
||||
color: var(--lumo-primary-text-color);
|
||||
}
|
||||
|
||||
header nav a[highlight] {
|
||||
background-color: var(--lumo-primary-color-10pct);
|
||||
}
|
30
src/main/frontend/themes/website/styles.css
Normal file
30
src/main/frontend/themes/website/styles.css
Normal file
@@ -0,0 +1,30 @@
|
||||
@import url('./main-layout.css');
|
||||
@import url('./views/dashboard-view.css');
|
||||
@import url('./views/checkout-form-view.css');
|
||||
@import url('./views/my-view-view.css'); html {
|
||||
--lumo-shade-5pct: rgba(33, 33, 33, 0.05);
|
||||
--lumo-shade-10pct: rgba(33, 33, 33, 0.1);
|
||||
--lumo-shade-20pct: rgba(33, 33, 33, 0.2);
|
||||
--lumo-shade-30pct: rgba(33, 33, 33, 0.3);
|
||||
--lumo-shade-40pct: rgba(33, 33, 33, 0.4);
|
||||
--lumo-shade-50pct: rgba(33, 33, 33, 0.5);
|
||||
--lumo-shade-60pct: rgba(33, 33, 33, 0.6);
|
||||
--lumo-shade-70pct: rgba(33, 33, 33, 0.7);
|
||||
--lumo-shade-80pct: rgba(33, 33, 33, 0.8);
|
||||
--lumo-shade-90pct: rgba(33, 33, 33, 0.9);
|
||||
--lumo-primary-color-50pct: rgba(235, 89, 5, 0.5);
|
||||
--lumo-primary-color-10pct: rgba(235, 89, 5, 0.1);
|
||||
--lumo-error-color-50pct: rgba(231, 24, 24, 0.5);
|
||||
--lumo-error-color-10pct: rgba(231, 24, 24, 0.1);
|
||||
--lumo-success-color-50pct: rgba(62, 229, 170, 0.5);
|
||||
--lumo-success-color-10pct: rgba(62, 229, 170, 0.1);
|
||||
--lumo-shade: hsl(0, 0%, 13%);
|
||||
--lumo-primary-color: hsl(22, 96%, 47%);
|
||||
--lumo-primary-text-color: hsl(22, 100%, 42%);
|
||||
--lumo-error-color: hsl(0, 81%, 50%);
|
||||
--lumo-error-text-color: hsl(0, 86%, 45%);
|
||||
--lumo-success-color: hsl(159, 76%, 57%);
|
||||
--lumo-success-contrast-color: hsl(159, 29%, 10%);
|
||||
--lumo-success-text-color: hsl(159, 61%, 40%);
|
||||
|
||||
}
|
3
src/main/frontend/themes/website/theme.json
Normal file
3
src/main/frontend/themes/website/theme.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"lumoImports" : [ "typography", "color", "spacing", "badge", "utility" ]
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
.checkout-form-view aside {
|
||||
top: calc(var(--lumo-space-xl) + var(--_vaadin-app-layout-navbar-offset-size));
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
.checkout-form-view main {
|
||||
grid-template-columns: auto 324px;
|
||||
}
|
||||
}
|
19
src/main/frontend/themes/website/views/dashboard-view.css
Normal file
19
src/main/frontend/themes/website/views/dashboard-view.css
Normal file
@@ -0,0 +1,19 @@
|
||||
/* Borders */
|
||||
|
||||
.dashboard-view vaadin-board-row > * {
|
||||
border-bottom: 1px solid var(--lumo-contrast-10pct);
|
||||
border-right: 1px solid var(--lumo-contrast-10pct);
|
||||
}
|
||||
|
||||
.dashboard-view vaadin-board-row.small > * {
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.dashboard-view vaadin-board-row.medium > *:nth-child(even),
|
||||
.dashboard-view vaadin-board-row.medium > *:only-child {
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.dashboard-view vaadin-board-row.large > *:last-child {
|
||||
border-right: none;
|
||||
}
|
166
src/main/frontend/themes/website/views/my-view-view.css
Normal file
166
src/main/frontend/themes/website/views/my-view-view.css
Normal file
@@ -0,0 +1,166 @@
|
||||
.my-view-view {
|
||||
padding: 2px;
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
position: relative;
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
--cv-blue: 212 96% 54%;
|
||||
--cv-purple: 259 97% 66%;
|
||||
--cv-dropzone-border-color: hsl(var(--cv-blue) / 0.5);
|
||||
--cv-dropzone-bg-color: hsl(var(--cv-blue) / 0.2);
|
||||
--cv-droptarget-border-color: hsl(var(--cv-purple) / 1);
|
||||
--cv-droptarget-bg-color: hsl(var(--cv-purple) / 0.4);
|
||||
--cv-stripe-width: 1.5px;
|
||||
--cv-stripe-gap: 9px;
|
||||
--cv-stripe-color: hsl(var(--cv-blue) / 0.2);
|
||||
--cv-layout-border-color: var(--lumo-contrast-40pct);
|
||||
--cv-checkerboard-color1: hsl(0 0% 0% / 0.05);
|
||||
--cv-checkerboard-color2: hsl(0 0% 100% / 0.05);
|
||||
--cv-checkerboard-size: 16px;
|
||||
}
|
||||
|
||||
.my-view-view[dragging] {
|
||||
--cv-checkerboard-color1: hsl(var(--cv-blue) / 0.2);
|
||||
--cv-checkerboard-color2: hsl(var(--cv-blue) / 0.1);
|
||||
--cv-layout-border-color: var(--cv-dropzone-border-color);
|
||||
}
|
||||
|
||||
.my-view-view .preview-container {
|
||||
display: contents;
|
||||
}
|
||||
|
||||
/* The root layout is not necessarily inside a flex box so width/height needs to be used */
|
||||
.my-view-view .preview-container > .layout[style*='align-self: stretch'] {
|
||||
width: 100%;
|
||||
}
|
||||
.my-view-view .preview-container > .layout[style*='flex-grow: 1'] {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* Apply some default gap and padding to layouts that don't have inline styles for them while dragging. */
|
||||
.my-view-view[dragging] .layout:not([style*='gap:']) {
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.my-view-view[dragging] .layout:not([style*='padding:'], [empty]) {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.my-view-view .cover-overlay {
|
||||
position: absolute;
|
||||
border-radius: 1px;
|
||||
}
|
||||
|
||||
.my-view-view:not([starting-drag]) .cover-overlay.editable-hovering {
|
||||
outline: 2px solid hsl(var(--cv-blue) / 1);
|
||||
outline-offset: -1px;
|
||||
}
|
||||
|
||||
.my-view-view:not([starting-drag]) .cover-overlay.editable-editing {
|
||||
outline: 1px solid hsl(var(--cv-blue) / 1);
|
||||
outline-offset: -1px;
|
||||
box-shadow: inset 0 0 0 2px var(--lumo-base-color);
|
||||
}
|
||||
|
||||
.my-view-view .overlays,
|
||||
.my-view-view .drop-zones {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.my-view-view:not([dragging]) .drop-zones {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.my-view-view .drop-zone {
|
||||
position: absolute;
|
||||
box-sizing: border-box;
|
||||
border-radius: 1px;
|
||||
min-height: 10px;
|
||||
min-width: 10px;
|
||||
}
|
||||
|
||||
.my-view-view[dragging] .drop-zone:not([empty-layout]) {
|
||||
outline: 1px dashed var(--cv-dropzone-border-color);
|
||||
outline-offset: -2px;
|
||||
background-color: var(--cv-dropzone-bg-color);
|
||||
}
|
||||
|
||||
.my-view-view .drop-zone[remaining-space] {
|
||||
background: repeating-linear-gradient(
|
||||
-45deg,
|
||||
var(--cv-stripe-color),
|
||||
var(--cv-stripe-color) var(--cv-stripe-width),
|
||||
transparent var(--cv-stripe-width),
|
||||
transparent var(--cv-stripe-gap)
|
||||
);
|
||||
}
|
||||
|
||||
.my-view-view[dragging] .drop-zone[drag-over] {
|
||||
background: var(--cv-droptarget-bg-color);
|
||||
outline: 1px solid var(--cv-droptarget-border-color);
|
||||
outline-offset: -1px;
|
||||
box-shadow: inset 0 0 0 2px var(--lumo-base-color);
|
||||
}
|
||||
|
||||
.drop-zone[empty-layout] {
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.my-view-view:not([readonly]) .layout[empty],vaadin-form-layout[empty] {
|
||||
border-radius: 1px;
|
||||
background: repeating-conic-gradient(var(--cv-checkerboard-color1) 0% 25%, var(--cv-checkerboard-color2) 0% 50%) 50% /
|
||||
var(--cv-checkerboard-size) var(--cv-checkerboard-size);
|
||||
background-clip: content-box;
|
||||
outline: 1px dashed var(--cv-layout-border-color);
|
||||
outline-offset: -2px;
|
||||
}
|
||||
.my-view-view[dragging]:not([readonly]) vaadin-form-layout[empty]{
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
|
||||
.my-view-view .layout[empty]::before {
|
||||
content: '';
|
||||
display: block;
|
||||
min-width: 64px;
|
||||
min-height: 32px;
|
||||
}
|
||||
|
||||
.my-view-view[readonly] .drop-zones,
|
||||
.my-view-view[readonly] .overlays {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.my-view-view[inline-editing] .drop-zones,
|
||||
.my-view-view[inline-editing] .overlays {
|
||||
display: none;
|
||||
}
|
||||
.my-view-view .content-wrapper[contenteditable='true']{
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
.my-view-view[dragging] vaadin-form-layout {
|
||||
padding: 8px;
|
||||
}
|
||||
.my-view-view vaadin-form-layout[empty]::before {
|
||||
content: '';
|
||||
display: block;
|
||||
min-width: 64px;
|
||||
min-height: 32px;
|
||||
}
|
||||
|
||||
.my-view-view[dragging] vaadin-form-layout:not([empty])::after {
|
||||
content: '';
|
||||
display: block;
|
||||
min-width: 64px;
|
||||
min-height: 32px;
|
||||
}
|
23
src/main/java/dev/mars3142/fhq/Application.java
Normal file
23
src/main/java/dev/mars3142/fhq/Application.java
Normal file
@@ -0,0 +1,23 @@
|
||||
package dev.mars3142.fhq;
|
||||
|
||||
import com.vaadin.flow.component.page.AppShellConfigurator;
|
||||
import com.vaadin.flow.theme.Theme;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
/**
|
||||
* The entry point of the Spring Boot application.
|
||||
*
|
||||
* Use the @PWA annotation make the application installable on phones, tablets
|
||||
* and some desktop browsers.
|
||||
*
|
||||
*/
|
||||
@SpringBootApplication
|
||||
@Theme(value = "website")
|
||||
public class Application implements AppShellConfigurator {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
|
||||
}
|
114
src/main/java/dev/mars3142/fhq/views/MainLayout.java
Normal file
114
src/main/java/dev/mars3142/fhq/views/MainLayout.java
Normal file
@@ -0,0 +1,114 @@
|
||||
package dev.mars3142.fhq.views;
|
||||
|
||||
|
||||
import com.vaadin.flow.component.Component;
|
||||
import com.vaadin.flow.component.applayout.AppLayout;
|
||||
import com.vaadin.flow.component.html.Div;
|
||||
import com.vaadin.flow.component.html.H1;
|
||||
import com.vaadin.flow.component.html.Header;
|
||||
import com.vaadin.flow.component.html.ListItem;
|
||||
import com.vaadin.flow.component.html.Nav;
|
||||
import com.vaadin.flow.component.html.Span;
|
||||
import com.vaadin.flow.component.html.UnorderedList;
|
||||
import com.vaadin.flow.router.RouterLink;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.AlignItems;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.BoxSizing;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.Display;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.FlexDirection;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.FontSize;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.FontWeight;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.Gap;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.Height;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.ListStyleType;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.Margin;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.Overflow;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.Padding;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.TextColor;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.Whitespace;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.Width;
|
||||
import dev.mars3142.fhq.views.checkoutform.CheckoutFormView;
|
||||
import dev.mars3142.fhq.views.dashboard.DashboardView;
|
||||
import dev.mars3142.fhq.views.myview.MyViewView;
|
||||
import org.vaadin.lineawesome.LineAwesomeIcon;
|
||||
|
||||
/**
|
||||
* The main view is a top-level placeholder for other views.
|
||||
*/
|
||||
public class MainLayout extends AppLayout {
|
||||
|
||||
/**
|
||||
* A simple navigation item component, based on ListItem element.
|
||||
*/
|
||||
public static class MenuItemInfo extends ListItem {
|
||||
|
||||
private final Class<? extends Component> view;
|
||||
|
||||
public MenuItemInfo(String menuTitle, Component icon, Class<? extends Component> view) {
|
||||
this.view = view;
|
||||
RouterLink link = new RouterLink();
|
||||
// Use Lumo classnames for various styling
|
||||
link.addClassNames(Display.FLEX, Gap.XSMALL, Height.MEDIUM, AlignItems.CENTER, Padding.Horizontal.SMALL,
|
||||
TextColor.BODY);
|
||||
link.setRoute(view);
|
||||
|
||||
Span text = new Span(menuTitle);
|
||||
// Use Lumo classnames for various styling
|
||||
text.addClassNames(FontWeight.MEDIUM, FontSize.MEDIUM, Whitespace.NOWRAP);
|
||||
|
||||
if (icon != null) {
|
||||
link.add(icon);
|
||||
}
|
||||
link.add(text);
|
||||
add(link);
|
||||
}
|
||||
|
||||
public Class<?> getView() {
|
||||
return view;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public MainLayout() {
|
||||
addToNavbar(createHeaderContent());
|
||||
}
|
||||
|
||||
private Component createHeaderContent() {
|
||||
Header header = new Header();
|
||||
header.addClassNames(BoxSizing.BORDER, Display.FLEX, FlexDirection.COLUMN, Width.FULL);
|
||||
|
||||
Div layout = new Div();
|
||||
layout.addClassNames(Display.FLEX, AlignItems.CENTER, Padding.Horizontal.LARGE);
|
||||
|
||||
H1 appName = new H1("Firmware HQ");
|
||||
appName.addClassNames(Margin.Vertical.MEDIUM, Margin.End.AUTO, FontSize.LARGE);
|
||||
layout.add(appName);
|
||||
|
||||
Nav nav = new Nav();
|
||||
nav.addClassNames(Display.FLEX, Overflow.AUTO, Padding.Horizontal.MEDIUM, Padding.Vertical.XSMALL);
|
||||
|
||||
// Wrap the links in a list; improves accessibility
|
||||
UnorderedList list = new UnorderedList();
|
||||
list.addClassNames(Display.FLEX, Gap.SMALL, ListStyleType.NONE, Margin.NONE, Padding.NONE);
|
||||
nav.add(list);
|
||||
|
||||
for (MenuItemInfo menuItem : createMenuItems()) {
|
||||
list.add(menuItem);
|
||||
|
||||
}
|
||||
|
||||
header.add(layout, nav);
|
||||
return header;
|
||||
}
|
||||
|
||||
private MenuItemInfo[] createMenuItems() {
|
||||
return new MenuItemInfo[]{ //
|
||||
new MenuItemInfo("Dashboard", LineAwesomeIcon.CHART_AREA_SOLID.create(), DashboardView.class), //
|
||||
|
||||
new MenuItemInfo("Checkout Form", LineAwesomeIcon.CREDIT_CARD.create(), CheckoutFormView.class), //
|
||||
|
||||
new MenuItemInfo("My View", LineAwesomeIcon.PENCIL_RULER_SOLID.create(), MyViewView.class), //
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,312 @@
|
||||
package dev.mars3142.fhq.views.checkoutform;
|
||||
|
||||
import com.vaadin.flow.component.Component;
|
||||
import com.vaadin.flow.component.button.Button;
|
||||
import com.vaadin.flow.component.button.ButtonVariant;
|
||||
import com.vaadin.flow.component.checkbox.Checkbox;
|
||||
import com.vaadin.flow.component.combobox.ComboBox;
|
||||
import com.vaadin.flow.component.html.*;
|
||||
import com.vaadin.flow.component.icon.Icon;
|
||||
import com.vaadin.flow.component.icon.VaadinIcon;
|
||||
import com.vaadin.flow.component.select.Select;
|
||||
import com.vaadin.flow.component.textfield.EmailField;
|
||||
import com.vaadin.flow.component.textfield.TextArea;
|
||||
import com.vaadin.flow.component.textfield.TextField;
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.AlignItems;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.Background;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.BorderRadius;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.BoxSizing;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.Display;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.Flex;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.FlexDirection;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.FlexWrap;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.FontSize;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.Gap;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.Height;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.JustifyContent;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.ListStyleType;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.Margin;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.MaxWidth;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.Padding;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.Position;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.TextColor;
|
||||
import dev.mars3142.fhq.views.MainLayout;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
@PageTitle("Checkout Form")
|
||||
@Route(value = "checkout-form", layout = MainLayout.class)
|
||||
public class CheckoutFormView extends Div {
|
||||
|
||||
private static final Set<String> states = new LinkedHashSet<>();
|
||||
private static final Set<String> countries = new LinkedHashSet<>();
|
||||
|
||||
static {
|
||||
states.addAll(Arrays.asList("Alabama", "Alaska", "Arizona", "Arkansas", "California", "Colorado", "Connecticut",
|
||||
"Delaware", "Florida", "Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", "Iowa", "Kansas",
|
||||
"Kentucky", "Louisiana", "Maine", "Maryland", "Massachusetts", "Michigan", "Minnesota", "Mississippi",
|
||||
"Missouri", "Montana", "Nebraska", "Nevada", "New Hampshire", "New Jersey", "New Mexico", "New York",
|
||||
"North Carolina", "North Dakota", "Ohio", "Oklahoma", "Oregon", "Pennsylvania", "Rhode Island",
|
||||
"South Carolina", "South Dakota", "Tennessee", "Texas", "Utah", "Vermont", "Virginia", "Washington",
|
||||
"West Virginia", "Wisconsin", "Wyoming"));
|
||||
|
||||
countries.addAll(Arrays.asList("Afghanistan", "Albania", "Algeria", "American Samoa", "Andorra", "Angola",
|
||||
"Anguilla", "Antarctica", "Antigua and Barbuda", "Argentina", "Armenia", "Aruba", "Australia",
|
||||
"Austria", "Azerbaijan", "Bahamas", "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium", "Belize",
|
||||
"Benin", "Bermuda", "Bhutan", "Bolivia", "Bosnia and Herzegovina", "Botswana", "Bouvet Island",
|
||||
"Brazil", "British Indian Ocean Territory", "British Virgin Islands", "Brunei Darussalam", "Bulgaria",
|
||||
"Burkina Faso", "Burundi", "Cambodia", "Cameroon", "Canada", "Cape Verde", "Cayman Islands",
|
||||
"Central African Republic", "Chad", "Chile", "China", "Christmas Island", "Cocos (Keeling) Islands",
|
||||
"Colombia", "Comoros", "Congo", "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus",
|
||||
"Czech Republic", "Denmark", "Djibouti", "Dominica", "Dominican Republic", "East Timor", "Ecuador",
|
||||
"Egypt", "El Salvador", "Equatorial Guinea", "Eritrea", "Estonia", "Ethiopia", "Falkland Islands",
|
||||
"Faroe Islands", "Federated States of Micronesia", "Fiji", "Finland", "France", "French Guiana",
|
||||
"French Polynesia", "French Southern Territories", "Gabon", "Gambia", "Georgia", "Germany", "Ghana",
|
||||
"Gibraltar", "Greece", "Greenland", "Grenada", "Guadeloupe", "Guam", "Guatemala", "Guinea",
|
||||
"Guinea-Bissau", "Guyana", "Haiti", "Heard Island and McDonald Islands", "Honduras", "Hong Kong",
|
||||
"Hungary", "Iceland", "India", "Indonesia", "Iran", "Iraq", "Ireland", "Israel", "Italy", "Ivory Coast",
|
||||
"Jamaica", "Japan", "Jordan", "Kazakhstan", "Kenya", "Kiribati", "Kuwait", "Kyrgyzstan", "Laos",
|
||||
"Latvia", "Lebanon", "Lesotho", "Liberia", "Libya", "Liechtenstein", "Lithuania", "Luxembourg", "Macau",
|
||||
"Macedonia", "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands",
|
||||
"Martinique", "Mauritania", "Mauritius", "Mayotte", "Mexico", "Moldova", "Monaco", "Mongolia",
|
||||
"Montserrat", "Morocco", "Mozambique", "Myanmar", "Namibia", "Nauru", "Nepal", "Netherlands",
|
||||
"Netherlands Antilles", "New Caledonia", "New Zealand", "Nicaragua", "Niger", "Nigeria", "Niue",
|
||||
"Norfolk Island", "North Korea", "Northern Mariana Islands", "Norway", "Oman", "Pakistan", "Palau",
|
||||
"Panama", "Papua New Guinea", "Paraguay", "Peru", "Philippines", "Pitcairn", "Poland", "Portugal",
|
||||
"Puerto Rico", "Qatar", "Reunion", "Romania", "Russian Federation", "Rwanda", "Saint Kitts and Nevis",
|
||||
"Saint Lucia", "Saint Vincent and the Grenadines", "Samoa", "San Marino", "Sao Tome and Principe",
|
||||
"Saudi Arabia", "Senegal", "Seychelles", "Sierra Leone", "Singapore", "Slovakia", "Slovenia",
|
||||
"Solomon Islands", "Somalia", "South Africa", "South Georgia and the South Sandwich Islands",
|
||||
"South Korea", "Spain", "Sri Lanka", "St. Helena", "St. Pierre and Miquelon", "Sudan", "Suriname",
|
||||
"Svalbard and Jan Mayen Islands", "Swaziland", "Sweden", "Switzerland", "Syrian Arab Republic",
|
||||
"Taiwan", "Tajikistan", "Tanzania", "Thailand", "Togo", "Tokelau", "Tonga", "Trinidad and Tobago",
|
||||
"Tunisia", "Turkey", "Turkmenistan", "Turks and Caicos Islands", "Tuvalu", "Uganda", "Ukraine",
|
||||
"United Arab Emirates", "United Kingdom", "United States", "United States Minor Outlying Islands",
|
||||
"United States Virgin Islands", "Uruguay", "Uzbekistan", "Vanuatu", "Vatican City State", "Venezuela",
|
||||
"Vietnam", "Wallis and Futuna Islands", "Western Sahara", "Yemen", "Yugoslavia", "Zaire", "Zambia",
|
||||
"Zimbabwe"));
|
||||
}
|
||||
|
||||
public CheckoutFormView() {
|
||||
addClassNames("checkout-form-view");
|
||||
addClassNames(Display.FLEX, FlexDirection.COLUMN, Height.FULL);
|
||||
|
||||
Main content = new Main();
|
||||
content.addClassNames(Display.GRID, Gap.XLARGE, AlignItems.START, JustifyContent.CENTER, MaxWidth.SCREEN_MEDIUM,
|
||||
Margin.Horizontal.AUTO, Padding.Bottom.LARGE, Padding.Horizontal.LARGE);
|
||||
|
||||
content.add(createCheckoutForm());
|
||||
content.add(createAside());
|
||||
add(content);
|
||||
}
|
||||
|
||||
private Component createCheckoutForm() {
|
||||
Section checkoutForm = new Section();
|
||||
checkoutForm.addClassNames(Display.FLEX, FlexDirection.COLUMN, Flex.GROW);
|
||||
|
||||
H2 header = new H2("Checkout");
|
||||
header.addClassNames(Margin.Bottom.NONE, Margin.Top.XLARGE, FontSize.XXXLARGE);
|
||||
Paragraph note = new Paragraph("All fields are required unless otherwise noted");
|
||||
note.addClassNames(Margin.Bottom.XLARGE, Margin.Top.NONE, TextColor.SECONDARY);
|
||||
checkoutForm.add(header, note);
|
||||
|
||||
checkoutForm.add(createPersonalDetailsSection());
|
||||
checkoutForm.add(createShippingAddressSection());
|
||||
checkoutForm.add(createPaymentInformationSection());
|
||||
checkoutForm.add(new Hr());
|
||||
checkoutForm.add(createFooter());
|
||||
|
||||
return checkoutForm;
|
||||
}
|
||||
|
||||
private Section createPersonalDetailsSection() {
|
||||
Section personalDetails = new Section();
|
||||
personalDetails.addClassNames(Display.FLEX, FlexDirection.COLUMN, Margin.Bottom.XLARGE, Margin.Top.MEDIUM);
|
||||
|
||||
Paragraph stepOne = new Paragraph("Checkout 1/3");
|
||||
stepOne.addClassNames(Margin.NONE, FontSize.SMALL, TextColor.SECONDARY);
|
||||
|
||||
H3 header = new H3("Personal details");
|
||||
header.addClassNames(Margin.Bottom.MEDIUM, Margin.Top.SMALL, FontSize.XXLARGE);
|
||||
|
||||
TextField name = new TextField("Name");
|
||||
name.setRequiredIndicatorVisible(true);
|
||||
name.setPattern("[\\p{L} \\-]+");
|
||||
name.addClassNames(Margin.Bottom.SMALL);
|
||||
|
||||
EmailField email = new EmailField("Email address");
|
||||
email.setRequiredIndicatorVisible(true);
|
||||
email.addClassNames(Margin.Bottom.SMALL);
|
||||
|
||||
TextField phone = new TextField("Phone number");
|
||||
phone.setRequiredIndicatorVisible(true);
|
||||
phone.setPattern("[\\d \\-\\+]+");
|
||||
phone.addClassNames(Margin.Bottom.SMALL);
|
||||
|
||||
Checkbox rememberDetails = new Checkbox("Remember personal details for next time");
|
||||
rememberDetails.addClassNames(Margin.Top.SMALL);
|
||||
|
||||
personalDetails.add(stepOne, header, name, email, phone, rememberDetails);
|
||||
return personalDetails;
|
||||
}
|
||||
|
||||
private Section createShippingAddressSection() {
|
||||
Section shippingDetails = new Section();
|
||||
shippingDetails.addClassNames(Display.FLEX, FlexDirection.COLUMN, Margin.Bottom.XLARGE, Margin.Top.MEDIUM);
|
||||
|
||||
Paragraph stepTwo = new Paragraph("Checkout 2/3");
|
||||
stepTwo.addClassNames(Margin.NONE, FontSize.SMALL, TextColor.SECONDARY);
|
||||
|
||||
H3 header = new H3("Shipping address");
|
||||
header.addClassNames(Margin.Bottom.MEDIUM, Margin.Top.SMALL, FontSize.XXLARGE);
|
||||
|
||||
ComboBox<String> countrySelect = new ComboBox<>("Country");
|
||||
countrySelect.setRequiredIndicatorVisible(true);
|
||||
countrySelect.addClassNames(Margin.Bottom.SMALL);
|
||||
|
||||
TextArea address = new TextArea("Street address");
|
||||
address.setMaxLength(200);
|
||||
address.setRequiredIndicatorVisible(true);
|
||||
address.addClassNames(Margin.Bottom.SMALL);
|
||||
|
||||
Div subSection = new Div();
|
||||
subSection.addClassNames(Display.FLEX, FlexWrap.WRAP, Gap.MEDIUM);
|
||||
|
||||
TextField postalCode = new TextField("Postal Code");
|
||||
postalCode.setRequiredIndicatorVisible(true);
|
||||
postalCode.setPattern("[\\d \\p{L}]*");
|
||||
postalCode.addClassNames(Margin.Bottom.SMALL);
|
||||
|
||||
TextField city = new TextField("City");
|
||||
city.setRequiredIndicatorVisible(true);
|
||||
city.addClassNames(Flex.GROW, Margin.Bottom.SMALL);
|
||||
|
||||
subSection.add(postalCode, city);
|
||||
|
||||
ComboBox<String> stateSelect = new ComboBox<>("State");
|
||||
stateSelect.setRequiredIndicatorVisible(true);
|
||||
|
||||
stateSelect.setItems(states);
|
||||
stateSelect.setVisible(false);
|
||||
countrySelect.setItems(countries);
|
||||
countrySelect
|
||||
.addValueChangeListener(e -> stateSelect.setVisible(countrySelect.getValue().equals("United States")));
|
||||
|
||||
Checkbox sameAddress = new Checkbox("Billing address is the same as shipping address");
|
||||
sameAddress.addClassNames(Margin.Top.SMALL);
|
||||
|
||||
Checkbox rememberAddress = new Checkbox("Remember address for next time");
|
||||
|
||||
shippingDetails.add(stepTwo, header, countrySelect, address, subSection, stateSelect, sameAddress,
|
||||
rememberAddress);
|
||||
return shippingDetails;
|
||||
}
|
||||
|
||||
private Component createPaymentInformationSection() {
|
||||
Section paymentInfo = new Section();
|
||||
paymentInfo.addClassNames(Display.FLEX, FlexDirection.COLUMN, Margin.Bottom.XLARGE, Margin.Top.MEDIUM);
|
||||
|
||||
Paragraph stepThree = new Paragraph("Checkout 3/3");
|
||||
stepThree.addClassNames(Margin.NONE, FontSize.SMALL, TextColor.SECONDARY);
|
||||
|
||||
H3 header = new H3("Personal details");
|
||||
header.addClassNames(Margin.Bottom.MEDIUM, Margin.Top.SMALL, FontSize.XXLARGE);
|
||||
|
||||
TextField cardHolder = new TextField("Cardholder name");
|
||||
cardHolder.setRequiredIndicatorVisible(true);
|
||||
cardHolder.setPattern("[\\p{L} \\-]+");
|
||||
cardHolder.addClassNames(Margin.Bottom.SMALL);
|
||||
|
||||
Div subSectionOne = new Div();
|
||||
subSectionOne.addClassNames(Display.FLEX, FlexWrap.WRAP, Gap.MEDIUM);
|
||||
|
||||
TextField cardNumber = new TextField("Card Number");
|
||||
cardNumber.setRequiredIndicatorVisible(true);
|
||||
cardNumber.setPattern("[\\d ]{12,23}");
|
||||
cardNumber.addClassNames(Margin.Bottom.SMALL);
|
||||
|
||||
TextField securityCode = new TextField("Security Code");
|
||||
securityCode.setRequiredIndicatorVisible(true);
|
||||
securityCode.setPattern("[0-9]{3,4}");
|
||||
securityCode.addClassNames(Flex.GROW, Margin.Bottom.SMALL);
|
||||
securityCode.setHelperText("What is this?");
|
||||
|
||||
subSectionOne.add(cardNumber, securityCode);
|
||||
|
||||
Div subSectionTwo = new Div();
|
||||
subSectionTwo.addClassNames(Display.FLEX, FlexWrap.WRAP, Gap.MEDIUM);
|
||||
|
||||
Select<String> expirationMonth = new Select<>();
|
||||
expirationMonth.setLabel("Expiration month");
|
||||
expirationMonth.setRequiredIndicatorVisible(true);
|
||||
expirationMonth.setItems("01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12");
|
||||
|
||||
Select<String> expirationYear = new Select<>();
|
||||
expirationYear.setLabel("Expiration year");
|
||||
expirationYear.setRequiredIndicatorVisible(true);
|
||||
expirationYear.setItems("22", "23", "24", "25", "26");
|
||||
|
||||
subSectionTwo.add(expirationMonth, expirationYear);
|
||||
|
||||
paymentInfo.add(stepThree, header, cardHolder, subSectionTwo);
|
||||
return paymentInfo;
|
||||
}
|
||||
|
||||
private Footer createFooter() {
|
||||
Footer footer = new Footer();
|
||||
footer.addClassNames(Display.FLEX, AlignItems.CENTER, JustifyContent.BETWEEN, Margin.Vertical.MEDIUM);
|
||||
|
||||
Button cancel = new Button("Cancel order");
|
||||
cancel.addThemeVariants(ButtonVariant.LUMO_TERTIARY);
|
||||
|
||||
Button pay = new Button("Pay securely", new Icon(VaadinIcon.LOCK));
|
||||
pay.addThemeVariants(ButtonVariant.LUMO_PRIMARY, ButtonVariant.LUMO_SUCCESS);
|
||||
|
||||
footer.add(cancel, pay);
|
||||
return footer;
|
||||
}
|
||||
|
||||
private Aside createAside() {
|
||||
Aside aside = new Aside();
|
||||
aside.addClassNames(Background.CONTRAST_5, BoxSizing.BORDER, Padding.LARGE, BorderRadius.LARGE,
|
||||
Position.STICKY);
|
||||
Header headerSection = new Header();
|
||||
headerSection.addClassNames(Display.FLEX, AlignItems.CENTER, JustifyContent.BETWEEN, Margin.Bottom.MEDIUM);
|
||||
H3 header = new H3("Order");
|
||||
header.addClassNames(Margin.NONE);
|
||||
Button edit = new Button("Edit");
|
||||
edit.addThemeVariants(ButtonVariant.LUMO_TERTIARY_INLINE);
|
||||
headerSection.add(header, edit);
|
||||
|
||||
UnorderedList ul = new UnorderedList();
|
||||
ul.addClassNames(ListStyleType.NONE, Margin.NONE, Padding.NONE, Display.FLEX, FlexDirection.COLUMN, Gap.MEDIUM);
|
||||
|
||||
ul.add(createListItem("Vanilla cracker", "With wholemeal flour", "$7.00"));
|
||||
ul.add(createListItem("Vanilla blueberry cake", "With blueberry jam", "$8.00"));
|
||||
ul.add(createListItem("Vanilla pastry", "With wholemeal flour", "$5.00"));
|
||||
|
||||
aside.add(headerSection, ul);
|
||||
return aside;
|
||||
}
|
||||
|
||||
private ListItem createListItem(String primary, String secondary, String price) {
|
||||
ListItem item = new ListItem();
|
||||
item.addClassNames(Display.FLEX, JustifyContent.BETWEEN);
|
||||
|
||||
Div subSection = new Div();
|
||||
subSection.addClassNames(Display.FLEX, FlexDirection.COLUMN);
|
||||
|
||||
subSection.add(new Span(primary));
|
||||
Span secondarySpan = new Span(secondary);
|
||||
secondarySpan.addClassNames(FontSize.SMALL, TextColor.SECONDARY);
|
||||
subSection.add(secondarySpan);
|
||||
|
||||
Span priceSpan = new Span(price);
|
||||
|
||||
item.add(subSection, priceSpan);
|
||||
return item;
|
||||
}
|
||||
}
|
@@ -0,0 +1,227 @@
|
||||
package dev.mars3142.fhq.views.dashboard;
|
||||
|
||||
|
||||
import com.vaadin.flow.component.Component;
|
||||
import com.vaadin.flow.component.board.Board;
|
||||
import com.vaadin.flow.component.charts.Chart;
|
||||
import com.vaadin.flow.component.charts.model.*;
|
||||
import com.vaadin.flow.component.grid.ColumnTextAlign;
|
||||
import com.vaadin.flow.component.grid.Grid;
|
||||
import com.vaadin.flow.component.grid.GridVariant;
|
||||
import com.vaadin.flow.component.html.H2;
|
||||
import com.vaadin.flow.component.html.Main;
|
||||
import com.vaadin.flow.component.html.Span;
|
||||
import com.vaadin.flow.component.icon.Icon;
|
||||
import com.vaadin.flow.component.icon.VaadinIcon;
|
||||
import com.vaadin.flow.component.orderedlayout.FlexComponent;
|
||||
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||
import com.vaadin.flow.component.select.Select;
|
||||
import com.vaadin.flow.data.renderer.ComponentRenderer;
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import com.vaadin.flow.router.RouteAlias;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.BoxSizing;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.FontSize;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.FontWeight;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.Margin;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.Padding;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.TextColor;
|
||||
import dev.mars3142.fhq.views.MainLayout;
|
||||
import dev.mars3142.fhq.views.dashboard.ServiceHealth.Status;
|
||||
|
||||
@PageTitle("Dashboard")
|
||||
@Route(value = "", layout = MainLayout.class)
|
||||
@RouteAlias(value = "", layout = MainLayout.class)
|
||||
public class DashboardView extends Main {
|
||||
|
||||
public DashboardView() {
|
||||
addClassName("dashboard-view");
|
||||
|
||||
Board board = new Board();
|
||||
board.addRow(createHighlight("Current users", "745", 33.7), createHighlight("View events", "54.6k", -112.45),
|
||||
createHighlight("Conversion rate", "18%", 3.9), createHighlight("Custom metric", "-123.45", 0.0));
|
||||
board.addRow(createViewEvents());
|
||||
board.addRow(createServiceHealth(), createResponseTimes());
|
||||
add(board);
|
||||
}
|
||||
|
||||
private Component createHighlight(String title, String value, Double percentage) {
|
||||
VaadinIcon icon = VaadinIcon.ARROW_UP;
|
||||
String prefix = "";
|
||||
String theme = "badge";
|
||||
|
||||
if (percentage == 0) {
|
||||
prefix = "±";
|
||||
} else if (percentage > 0) {
|
||||
prefix = "+";
|
||||
theme += " success";
|
||||
} else if (percentage < 0) {
|
||||
icon = VaadinIcon.ARROW_DOWN;
|
||||
theme += " error";
|
||||
}
|
||||
|
||||
H2 h2 = new H2(title);
|
||||
h2.addClassNames(FontWeight.NORMAL, Margin.NONE, TextColor.SECONDARY, FontSize.XSMALL);
|
||||
|
||||
Span span = new Span(value);
|
||||
span.addClassNames(FontWeight.SEMIBOLD, FontSize.XXXLARGE);
|
||||
|
||||
Icon i = icon.create();
|
||||
i.addClassNames(BoxSizing.BORDER, Padding.XSMALL);
|
||||
|
||||
Span badge = new Span(i, new Span(prefix + percentage.toString()));
|
||||
badge.getElement().getThemeList().add(theme);
|
||||
|
||||
VerticalLayout layout = new VerticalLayout(h2, span, badge);
|
||||
layout.addClassName(Padding.LARGE);
|
||||
layout.setPadding(false);
|
||||
layout.setSpacing(false);
|
||||
return layout;
|
||||
}
|
||||
|
||||
private Component createViewEvents() {
|
||||
// Header
|
||||
Select year = new Select();
|
||||
year.setItems("2011", "2012", "2013", "2014", "2015", "2016", "2017", "2018", "2019", "2020", "2021");
|
||||
year.setValue("2021");
|
||||
year.setWidth("100px");
|
||||
|
||||
HorizontalLayout header = createHeader("View events", "City/month");
|
||||
header.add(year);
|
||||
|
||||
// Chart
|
||||
Chart chart = new Chart(ChartType.AREASPLINE);
|
||||
Configuration conf = chart.getConfiguration();
|
||||
conf.getChart().setStyledMode(true);
|
||||
|
||||
XAxis xAxis = new XAxis();
|
||||
xAxis.setCategories("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec");
|
||||
conf.addxAxis(xAxis);
|
||||
|
||||
conf.getyAxis().setTitle("Values");
|
||||
|
||||
PlotOptionsAreaspline plotOptions = new PlotOptionsAreaspline();
|
||||
plotOptions.setPointPlacement(PointPlacement.ON);
|
||||
plotOptions.setMarker(new Marker(false));
|
||||
conf.addPlotOptions(plotOptions);
|
||||
|
||||
conf.addSeries(new ListSeries("Berlin", 189, 191, 291, 396, 501, 403, 609, 712, 729, 942, 1044, 1247));
|
||||
conf.addSeries(new ListSeries("London", 138, 246, 248, 348, 352, 353, 463, 573, 778, 779, 885, 887));
|
||||
conf.addSeries(new ListSeries("New York", 65, 65, 166, 171, 293, 302, 308, 317, 427, 429, 535, 636));
|
||||
conf.addSeries(new ListSeries("Tokyo", 0, 11, 17, 123, 130, 142, 248, 349, 452, 454, 458, 462));
|
||||
|
||||
// Add it all together
|
||||
VerticalLayout viewEvents = new VerticalLayout(header, chart);
|
||||
viewEvents.addClassName(Padding.LARGE);
|
||||
viewEvents.setPadding(false);
|
||||
viewEvents.setSpacing(false);
|
||||
viewEvents.getElement().getThemeList().add("spacing-l");
|
||||
return viewEvents;
|
||||
}
|
||||
|
||||
private Component createServiceHealth() {
|
||||
// Header
|
||||
HorizontalLayout header = createHeader("Service health", "Input / output");
|
||||
|
||||
// Grid
|
||||
Grid<ServiceHealth> grid = new Grid();
|
||||
grid.addThemeVariants(GridVariant.LUMO_NO_BORDER);
|
||||
grid.setAllRowsVisible(true);
|
||||
|
||||
grid.addColumn(new ComponentRenderer<>(serviceHealth -> {
|
||||
Span status = new Span();
|
||||
String statusText = getStatusDisplayName(serviceHealth);
|
||||
status.getElement().setAttribute("aria-label", "Status: " + statusText);
|
||||
status.getElement().setAttribute("title", "Status: " + statusText);
|
||||
status.getElement().getThemeList().add(getStatusTheme(serviceHealth));
|
||||
return status;
|
||||
})).setHeader("").setFlexGrow(0).setAutoWidth(true);
|
||||
grid.addColumn(ServiceHealth::getCity).setHeader("City").setFlexGrow(1);
|
||||
grid.addColumn(ServiceHealth::getInput).setHeader("Input").setAutoWidth(true).setTextAlign(ColumnTextAlign.END);
|
||||
grid.addColumn(ServiceHealth::getOutput).setHeader("Output").setAutoWidth(true)
|
||||
.setTextAlign(ColumnTextAlign.END);
|
||||
|
||||
grid.setItems(new ServiceHealth(Status.EXCELLENT, "Münster", 324, 1540),
|
||||
new ServiceHealth(Status.OK, "Cluj-Napoca", 311, 1320),
|
||||
new ServiceHealth(Status.FAILING, "Ciudad Victoria", 300, 1219));
|
||||
|
||||
// Add it all together
|
||||
VerticalLayout serviceHealth = new VerticalLayout(header, grid);
|
||||
serviceHealth.addClassName(Padding.LARGE);
|
||||
serviceHealth.setPadding(false);
|
||||
serviceHealth.setSpacing(false);
|
||||
serviceHealth.getElement().getThemeList().add("spacing-l");
|
||||
return serviceHealth;
|
||||
}
|
||||
|
||||
private Component createResponseTimes() {
|
||||
HorizontalLayout header = createHeader("Response times", "Average across all systems");
|
||||
|
||||
// Chart
|
||||
Chart chart = new Chart(ChartType.PIE);
|
||||
Configuration conf = chart.getConfiguration();
|
||||
conf.getChart().setStyledMode(true);
|
||||
chart.setThemeName("gradient");
|
||||
|
||||
DataSeries series = new DataSeries();
|
||||
series.add(new DataSeriesItem("System 1", 12.5));
|
||||
series.add(new DataSeriesItem("System 2", 12.5));
|
||||
series.add(new DataSeriesItem("System 3", 12.5));
|
||||
series.add(new DataSeriesItem("System 4", 12.5));
|
||||
series.add(new DataSeriesItem("System 5", 12.5));
|
||||
series.add(new DataSeriesItem("System 6", 12.5));
|
||||
conf.addSeries(series);
|
||||
|
||||
// Add it all together
|
||||
VerticalLayout serviceHealth = new VerticalLayout(header, chart);
|
||||
serviceHealth.addClassName(Padding.LARGE);
|
||||
serviceHealth.setPadding(false);
|
||||
serviceHealth.setSpacing(false);
|
||||
serviceHealth.getElement().getThemeList().add("spacing-l");
|
||||
return serviceHealth;
|
||||
}
|
||||
|
||||
private HorizontalLayout createHeader(String title, String subtitle) {
|
||||
H2 h2 = new H2(title);
|
||||
h2.addClassNames(FontSize.XLARGE, Margin.NONE);
|
||||
|
||||
Span span = new Span(subtitle);
|
||||
span.addClassNames(TextColor.SECONDARY, FontSize.XSMALL);
|
||||
|
||||
VerticalLayout column = new VerticalLayout(h2, span);
|
||||
column.setPadding(false);
|
||||
column.setSpacing(false);
|
||||
|
||||
HorizontalLayout header = new HorizontalLayout(column);
|
||||
header.setJustifyContentMode(FlexComponent.JustifyContentMode.BETWEEN);
|
||||
header.setSpacing(false);
|
||||
header.setWidthFull();
|
||||
return header;
|
||||
}
|
||||
|
||||
private String getStatusDisplayName(ServiceHealth serviceHealth) {
|
||||
Status status = serviceHealth.getStatus();
|
||||
if (status == Status.OK) {
|
||||
return "Ok";
|
||||
} else if (status == Status.FAILING) {
|
||||
return "Failing";
|
||||
} else if (status == Status.EXCELLENT) {
|
||||
return "Excellent";
|
||||
} else {
|
||||
return status.toString();
|
||||
}
|
||||
}
|
||||
|
||||
private String getStatusTheme(ServiceHealth serviceHealth) {
|
||||
Status status = serviceHealth.getStatus();
|
||||
String theme = "badge primary small";
|
||||
if (status == Status.EXCELLENT) {
|
||||
theme += " success";
|
||||
} else if (status == Status.FAILING) {
|
||||
theme += " error";
|
||||
}
|
||||
return theme;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,65 @@
|
||||
package dev.mars3142.fhq.views.dashboard;
|
||||
|
||||
/**
|
||||
* Simple DTO class for the inbox list to demonstrate complex object data
|
||||
*/
|
||||
public class ServiceHealth {
|
||||
|
||||
private Status status;
|
||||
|
||||
private String city;
|
||||
|
||||
private int input;
|
||||
|
||||
private int output;
|
||||
|
||||
private String theme;
|
||||
|
||||
enum Status {
|
||||
EXCELLENT, OK, FAILING;
|
||||
}
|
||||
|
||||
public ServiceHealth() {
|
||||
|
||||
}
|
||||
|
||||
public ServiceHealth(Status status, String city, int input, int output) {
|
||||
this.status = status;
|
||||
this.city = city;
|
||||
this.input = input;
|
||||
this.output = output;
|
||||
}
|
||||
|
||||
public Status getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(Status status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getCity() {
|
||||
return city;
|
||||
}
|
||||
|
||||
public void setCity(String city) {
|
||||
this.city = city;
|
||||
}
|
||||
|
||||
public int getInput() {
|
||||
return input;
|
||||
}
|
||||
|
||||
public void setInput(int input) {
|
||||
this.input = input;
|
||||
}
|
||||
|
||||
public int getOutput() {
|
||||
return output;
|
||||
}
|
||||
|
||||
public void setOutput(int output) {
|
||||
this.output = output;
|
||||
}
|
||||
|
||||
}
|
44
src/main/java/dev/mars3142/fhq/views/myview/MyViewView.java
Normal file
44
src/main/java/dev/mars3142/fhq/views/myview/MyViewView.java
Normal file
@@ -0,0 +1,44 @@
|
||||
package dev.mars3142.fhq.views.myview;
|
||||
|
||||
import com.vaadin.flow.component.Composite;
|
||||
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.Gap;
|
||||
import dev.mars3142.fhq.views.MainLayout;
|
||||
|
||||
@PageTitle("My View")
|
||||
@Route(value = "my-view", layout = MainLayout.class)
|
||||
public class MyViewView extends Composite<VerticalLayout> {
|
||||
|
||||
public MyViewView() {
|
||||
HorizontalLayout layoutRow2 = new HorizontalLayout();
|
||||
HorizontalLayout layoutRow = new HorizontalLayout();
|
||||
VerticalLayout layoutColumn2 = new VerticalLayout();
|
||||
VerticalLayout layoutColumn3 = new VerticalLayout();
|
||||
VerticalLayout layoutColumn4 = new VerticalLayout();
|
||||
HorizontalLayout layoutRow3 = new HorizontalLayout();
|
||||
getContent().setWidth("100%");
|
||||
getContent().getStyle().set("flex-grow", "1");
|
||||
layoutRow2.addClassName(Gap.MEDIUM);
|
||||
layoutRow2.setWidth("100%");
|
||||
layoutRow2.setHeight("min-content");
|
||||
layoutRow.addClassName(Gap.MEDIUM);
|
||||
layoutRow.setWidth("100%");
|
||||
layoutRow.getStyle().set("flex-grow", "1");
|
||||
layoutColumn2.getStyle().set("flex-grow", "1");
|
||||
layoutColumn3.setWidth("100%");
|
||||
layoutColumn3.getStyle().set("flex-grow", "1");
|
||||
layoutColumn4.getStyle().set("flex-grow", "1");
|
||||
layoutRow3.addClassName(Gap.MEDIUM);
|
||||
layoutRow3.setWidth("100%");
|
||||
layoutRow3.setHeight("min-content");
|
||||
getContent().add(layoutRow2);
|
||||
getContent().add(layoutRow);
|
||||
layoutRow.add(layoutColumn2);
|
||||
layoutRow.add(layoutColumn3);
|
||||
layoutRow.add(layoutColumn4);
|
||||
getContent().add(layoutRow3);
|
||||
}
|
||||
}
|
BIN
src/main/resources/META-INF/resources/icons/icon.png
Normal file
BIN
src/main/resources/META-INF/resources/icons/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.4 KiB |
15
src/main/resources/application.properties
Normal file
15
src/main/resources/application.properties
Normal file
@@ -0,0 +1,15 @@
|
||||
server.port=${PORT:8080}
|
||||
logging.level.org.atmosphere = warn
|
||||
spring.mustache.check-template-location = false
|
||||
|
||||
# Launch the default browser when starting the application in development mode
|
||||
vaadin.launch-browser=true
|
||||
# PostgreSQL configuration.
|
||||
spring.datasource.url = jdbc:postgresql://localhost:5432/vaadinstart
|
||||
spring.datasource.username = vaadinstart
|
||||
spring.datasource.password = vaadinstart
|
||||
spring.jpa.hibernate.ddl-auto = update
|
||||
# To improve the performance during development.
|
||||
# For more information https://vaadin.com/docs/latest/integrations/spring/configuration#special-configuration-parameters
|
||||
vaadin.allowed-packages = com.vaadin,org.vaadin,dev.hilla,dev.mars3142.fhq
|
||||
spring.jpa.defer-datasource-initialization = true
|
6
src/main/resources/banner.txt
Normal file
6
src/main/resources/banner.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
_____ _ _ _ ___
|
||||
| ___(_)_ __ _ __ _____ ____ _ _ __ ___ | | | |/ _ \
|
||||
| |_ | | '__| '_ ` _ \ \ /\ / / _` | '__/ _ \ | |_| | | | |
|
||||
| _| | | | | | | | | \ V V / (_| | | | __/ | _ | |_| |
|
||||
|_| |_|_| |_| |_| |_|\_/\_/ \__,_|_| \___| |_| |_|\__\_\
|
||||
|
Reference in New Issue
Block a user