Initial commit

This commit is contained in:
Pit Friedrich
2026-07-05 17:06:59 +02:00
parent 0935b7a98a
commit 23b392a19b
11 changed files with 5144 additions and 0 deletions
+32
View File
@@ -0,0 +1,32 @@
This directory is automatically generated by Vaadin and contains the pre-compiled
frontend files/resources for your project (frontend development bundle).
It should be added to Version Control System and committed, so that other developers
do not have to compile it again.
Frontend development bundle is automatically updated when needed:
- an npm/pnpm package is added with @NpmPackage or directly into package.json
- CSS, JavaScript or TypeScript files are added with @CssImport, @JsModule or @JavaScript
- Vaadin add-on with front-end customizations is added
- Custom theme imports/assets added into 'theme.json' file
- Exported web component is added.
If your project development needs a hot deployment of the frontend changes,
you can switch Flow to use Vite development server:
- set `vaadin.frontend.hotdeploy=true` in `application.properties`
- configure `vaadin-maven-plugin`:
```
<configuration>
<frontendHotdeploy>true</frontendHotdeploy>
</configuration>
```
- configure `jetty-maven-plugin`:
```
<configuration>
<systemProperties>
<vaadin.frontend.hotdeploy>true</vaadin.frontend.hotdeploy>
</systemProperties>
</configuration>
```
Read more [about Vaadin development mode](https://vaadin.com/docs/latest/flow/configuration/development-mode#precompiled-bundle).
Binary file not shown.
@@ -0,0 +1,43 @@
import { html, LitElement } from 'lit';
import { customElement } from 'lit/decorators.js';
import ApexCharts from 'apexcharts';
@customElement('apex-chart')
export class ApexChart extends LitElement {
private chart?: ApexCharts;
protected createRenderRoot() {
return this;
}
render() {
return html`<div id="container" style="width:100%;height:100%"></div>`;
}
async renderChart(optionsJson: string) {
await this.updateComplete;
const options = JSON.parse(optionsJson);
options.chart = {
...options.chart,
events: {
dataPointSelection: (_e: unknown, _ctx: unknown, cfg: any) => {
(this as any).$server.onPointClick(cfg.seriesIndex, cfg.dataPointIndex);
},
},
};
const container = this.querySelector('#container') as HTMLElement;
if (this.chart) {
await this.chart.updateOptions(options);
} else {
this.chart = new ApexCharts(container, options);
await this.chart.render();
}
}
disconnectedCallback() {
super.disconnectedCallback();
this.chart?.destroy();
}
}
+39
View File
@@ -0,0 +1,39 @@
<!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, viewport-fit=cover" />
<style>
html, body, #outlet {
height: 100%;
width: 100%;
margin: 0;
}
/*
Fix app height for iOS home screen apps:
- 100% doesn't cover the entire screen.
- 100vh would work on iOS 18 but not on iOS 17 (too tall in Safari, correct in standalone mode).
- 100lvh is too tall in Safari. 100svh is too short in standalone apps.
- 100dvh doesn't seem to work on first render when launched from home screen (initially like 100svh, then changes to 100lvh when you try to scroll the view).
- So, we use 100% for the regular case (Safari and other browsers), and 100lvh for iOS home screen apps. Note, that the `display-mode: standalone` media query only works if the webmanifest defines `"display": "standalone"`.
*/
@supports (-webkit-touch-callout: none) {
@media (display-mode: standalone) {
html {
height: 100lvh;
}
}
}
</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>
@@ -0,0 +1,57 @@
package com.example.components;
import com.vaadin.flow.component.*;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.dependency.JsModule;
import com.vaadin.flow.component.dependency.NpmPackage;
import com.vaadin.flow.shared.Registration;
import tools.jackson.databind.json.JsonMapper;
import java.util.List;
import java.util.Map;
@Tag("apex-chart")
@NpmPackage(value = "apexcharts", version = "5.15.2")
@JsModule("./components/apex-chart.ts")
public class ApexChart extends Component implements HasSize {
private static final JsonMapper MAPPER = JsonMapper.builder().build();
public void setData(String seriesName, List<Double> values, List<String> categories) {
Map<String, Object> options = Map.of(
"chart", Map.of("type", "bar", "height", "100%"),
"series", List.of(Map.of("name", seriesName, "data", values)),
"xaxis", Map.of("categories", categories)
);
getElement().callJsFunction("renderChart", MAPPER.writeValueAsString(options));
}
@ClientCallable
private void onPointClick(int seriesIndex, int dataPointIndex) {
fireEvent(new PointClickEvent(this, true, seriesIndex, dataPointIndex));
}
public Registration addPointClickListener(ComponentEventListener<PointClickEvent> listener) {
return addListener(PointClickEvent.class, listener);
}
public static class PointClickEvent extends ComponentEvent<ApexChart> {
private final int seriesIndex;
private final int dataPointIndex;
PointClickEvent(ApexChart source, boolean fromClient, int seriesIndex, int dataPointIndex) {
super(source, fromClient);
this.seriesIndex = seriesIndex;
this.dataPointIndex = dataPointIndex;
}
public int getDataPointIndex() {
return dataPointIndex;
}
public int getSeriesIndex() {
return seriesIndex;
}
}
}
@@ -0,0 +1,28 @@
package com.example.views;
import com.example.components.ApexChart;
import com.vaadin.flow.component.notification.Notification;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.router.Route;
import java.util.List;
@Route("")
public class DashboardView extends VerticalLayout {
public DashboardView() {
ApexChart chart = new ApexChart();
chart.setWidthFull();
chart.setHeight("400px");
chart.setData("Umsatz 2026",
List.of(30.0, 40.0, 35.0, 50.0, 49.0, 60.0),
List.of("Jan", "Feb", "Mär", "Apr", "Mai", "Jun"));
chart.addPointClickListener(e -> {
Notification.show("Serie %d, Punkt %d"
.formatted(e.getSeriesIndex(), e.getDataPointIndex()));
});
add(chart);
}
}