update dockerfile

Signed-off-by: Peter Siegmund <developer@mars3142.org>
This commit is contained in:
2024-05-27 23:35:13 +02:00
parent 9350ed6c25
commit 35ebc02877
6 changed files with 56 additions and 299 deletions

View File

@@ -1,4 +1,33 @@
FROM eclipse-temurin:21-jre FROM maven:3-eclipse-temurin-21-jammy as build
COPY target/*.jar app.jar
# Install nodejs
RUN apt-get update
RUN apt-get install -y ca-certificates curl gnupg
RUN mkdir -p /etc/apt/keyrings
RUN curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg
RUN echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_18.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list
RUN apt-get update
RUN apt-get install nodejs -y
# Stop running as root at this point
RUN useradd -m vaadin
WORKDIR /usr/src/app/
RUN chown vaadin:vaadin /usr/src/app/
USER vaadin
# Copy pom.xml and prefetch dependencies so a repeated build can continue from the next step with existing dependencies
COPY --chown=vaadin pom.xml ./
# Copy all needed project files to a folder
COPY --chown=vaadin:vaadin src src
# Build the production package, assuming that we validated the version before so no need for running tests again
RUN mvn clean package -DskipTests -Pproduction --batch-mode
# Running stage: the part that is used for running the application
FROM eclipse-temurin:21-jre-jammy
COPY --from=build /usr/src/app/target/*.jar /usr/app/app.jar
RUN useradd -m vaadin
USER vaadin
EXPOSE 8080 EXPOSE 8080
ENTRYPOINT ["java", "-jar", "/app.jar"] CMD java -jar /usr/app/app.jar

View File

@@ -0,0 +1,23 @@
<!DOCTYPE html>
<!--
This file is auto-generated by Vaadin.
-->
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style>
body, #outlet {
height: 100vh;
width: 100%;
margin: 0;
}
</style>
<!-- index.ts is included here automatically (either by the dev server or during the build) -->
</head>
<body>
<!-- This outlet div is where the views are rendered -->
<div id="outlet"></div>
</body>
</html>

View File

@@ -27,7 +27,6 @@ import com.vaadin.flow.theme.lumo.LumoUtility.TextColor;
import com.vaadin.flow.theme.lumo.LumoUtility.Whitespace; import com.vaadin.flow.theme.lumo.LumoUtility.Whitespace;
import com.vaadin.flow.theme.lumo.LumoUtility.Width; import com.vaadin.flow.theme.lumo.LumoUtility.Width;
import dev.mars3142.fhq.views.checkoutform.CheckoutFormView; import dev.mars3142.fhq.views.checkoutform.CheckoutFormView;
import dev.mars3142.fhq.views.dashboard.DashboardView;
import dev.mars3142.fhq.views.myview.MyViewView; import dev.mars3142.fhq.views.myview.MyViewView;
import org.vaadin.lineawesome.LineAwesomeIcon; import org.vaadin.lineawesome.LineAwesomeIcon;
@@ -102,8 +101,6 @@ public class MainLayout extends AppLayout {
private MenuItemInfo[] createMenuItems() { private MenuItemInfo[] createMenuItems() {
return new MenuItemInfo[]{ // 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("Checkout Form", LineAwesomeIcon.CREDIT_CARD.create(), CheckoutFormView.class), //
new MenuItemInfo("My View", LineAwesomeIcon.PENCIL_RULER_SOLID.create(), MyViewView.class), // new MenuItemInfo("My View", LineAwesomeIcon.PENCIL_RULER_SOLID.create(), MyViewView.class), //

View File

@@ -38,7 +38,7 @@ import java.util.LinkedHashSet;
import java.util.Set; import java.util.Set;
@PageTitle("Checkout Form") @PageTitle("Checkout Form")
@Route(value = "checkout-form", layout = MainLayout.class) @Route(value = "", layout = MainLayout.class)
public class CheckoutFormView extends Div { public class CheckoutFormView extends Div {
private static final Set<String> states = new LinkedHashSet<>(); private static final Set<String> states = new LinkedHashSet<>();

View File

@@ -1,227 +0,0 @@
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;
}
}

View File

@@ -1,65 +0,0 @@
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;
}
}