2 Commits

Author SHA1 Message Date
Nils Burghardt
44672876be upgrade clean code ChartJsComponent 2025-07-13 18:35:03 +02:00
Nils Burghardt
e828e83991 upgrade clean code MainLayout 2025-07-13 18:34:31 +02:00
2 changed files with 61 additions and 46 deletions

View File

@@ -1,11 +1,10 @@
package de.nilzbu.mytimetracker.ui.component; package de.nilzbu.mytimetracker.ui.component;
import com.vaadin.flow.component.HasSize; import com.vaadin.flow.component.AttachEvent;
import com.vaadin.flow.component.html.Div; import com.vaadin.flow.component.Tag;
import com.vaadin.flow.component.dependency.JsModule; import com.vaadin.flow.component.dependency.JsModule;
import com.vaadin.flow.component.dependency.NpmPackage; import com.vaadin.flow.component.dependency.NpmPackage;
import com.vaadin.flow.component.Tag; import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.AttachEvent;
import elemental.json.Json; import elemental.json.Json;
import elemental.json.JsonArray; import elemental.json.JsonArray;
import elemental.json.JsonObject; import elemental.json.JsonObject;
@@ -31,10 +30,14 @@ public class ChartJsComponent extends Div {
@Override @Override
protected void onAttach(AttachEvent attachEvent) { protected void onAttach(AttachEvent attachEvent) {
renderChart();
}
private void renderChart() {
getElement().executeJs( getElement().executeJs(
""" """
const canvas = document.createElement('canvas'); const canvas = document.createElement('canvas');
this.appendChild(canvas); appendChild(canvas);
const ctx = canvas.getContext('2d'); const ctx = canvas.getContext('2d');
new Chart(ctx, { new Chart(ctx, {
type: $0, type: $0,
@@ -54,47 +57,55 @@ public class ChartJsComponent extends Div {
} }
}); });
""", """,
getChartTypeFromData(chartData), detectChartType(chartData),
chartData, chartData,
chartTitle chartTitle
); );
} }
private String getChartTypeFromData(JsonObject data) { /**
// Default zu bar wenn keine sinnvolle Bestimmung möglich ist * Detects chart type based on chart data.
* If no definitive type can be determined, defaults to "bar".
*/
private String detectChartType(JsonObject data) {
try { try {
JsonArray datasets = data.getArray("datasets"); JsonArray datasets = data.getArray("datasets");
if (datasets.length() > 0) { if (datasets.length() > 0) {
JsonObject first = datasets.getObject(0); JsonObject firstDataset = datasets.getObject(0);
if (first.hasKey("fill") && !first.getBoolean("fill")) { if (firstDataset.hasKey("fill") && !firstDataset.getBoolean("fill")) {
return "line"; return "line";
} }
} }
} catch (Exception ignored) {} } catch (Exception ignored) {
}
return "bar"; return "bar";
} }
// Balkendiagramm für Kategorien /**
* Creates JSON chart data for a bar chart based on category counts.
*/
public static JsonObject generateBarChartData(Map<String, Long> categoryCounts) { public static JsonObject generateBarChartData(Map<String, Long> categoryCounts) {
JsonObject data = Json.createObject(); JsonObject data = Json.createObject();
JsonArray labels = Json.createArray(); JsonArray labels = Json.createArray();
JsonArray values = Json.createArray(); JsonArray values = Json.createArray();
JsonArray backgroundColors = Json.createArray(); JsonArray colors = Json.createArray();
String[] defaultColors = {"#1e7e34", "#138496", "#ffc107", "#dc3545", "#6f42c1", "#20c997"}; String[] defaultColors = {
"#1e7e34", "#138496", "#ffc107", "#dc3545", "#6f42c1", "#20c997"
};
int i = 0; int index = 0;
for (Map.Entry<String, Long> entry : categoryCounts.entrySet()) { for (Map.Entry<String, Long> entry : categoryCounts.entrySet()) {
labels.set(i, Json.create(entry.getKey())); labels.set(index, Json.create(entry.getKey()));
values.set(i, Json.create(entry.getValue())); values.set(index, Json.create(entry.getValue()));
backgroundColors.set(i, Json.create(defaultColors[i % defaultColors.length])); colors.set(index, Json.create(defaultColors[index % defaultColors.length]));
i++; index++;
} }
JsonObject dataset = Json.createObject(); JsonObject dataset = Json.createObject();
dataset.put("label", "Einträge nach Kategorie"); dataset.put("label", "Entries by Category");
dataset.put("data", values); dataset.put("data", values);
dataset.put("backgroundColor", backgroundColors); dataset.put("backgroundColor", colors);
JsonArray datasets = Json.createArray(); JsonArray datasets = Json.createArray();
datasets.set(0, dataset); datasets.set(0, dataset);
@@ -105,19 +116,21 @@ public class ChartJsComponent extends Div {
return data; return data;
} }
// Liniendiagramm für Überstunden-Saldo (in Stunden) /**
public static JsonObject generateLineChartData(List<LocalDate> dates, List<Double> saldoValues) { * Creates JSON chart data for a line chart showing overtime balance.
*/
public static JsonObject generateLineChartData(List<LocalDate> dates, List<Double> balanceValues) {
JsonObject data = Json.createObject(); JsonObject data = Json.createObject();
JsonArray labels = Json.createArray(); JsonArray labels = Json.createArray();
JsonArray values = Json.createArray(); JsonArray values = Json.createArray();
for (int i = 0; i < dates.size(); i++) { for (int i = 0; i < dates.size(); i++) {
labels.set(i, Json.create(dates.get(i).toString())); labels.set(i, Json.create(dates.get(i).toString()));
values.set(i, Json.create(saldoValues.get(i))); values.set(i, Json.create(balanceValues.get(i)));
} }
JsonObject dataset = Json.createObject(); JsonObject dataset = Json.createObject();
dataset.put("label", "Überstunden-Saldo (h)"); dataset.put("label", "Overtime Balance (hours)");
dataset.put("data", values); dataset.put("data", values);
dataset.put("borderColor", "rgb(54, 162, 235)"); dataset.put("borderColor", "rgb(54, 162, 235)");
dataset.put("tension", 0.1); dataset.put("tension", 0.1);

View File

@@ -10,7 +10,7 @@ import com.vaadin.flow.server.VaadinServletRequest;
import com.vaadin.flow.server.VaadinServletResponse; import com.vaadin.flow.server.VaadinServletResponse;
import de.nilzbu.mytimetracker.ui.view.MainView; import de.nilzbu.mytimetracker.ui.view.MainView;
import de.nilzbu.mytimetracker.ui.view.TimeEntryView; import de.nilzbu.mytimetracker.ui.view.TimeEntryView;
import de.nilzbu.mytimetracker.ui.view.UserAdminView; import de.nilzbu.mytimetracker.ui.view.UserManagementView;
import jakarta.annotation.security.PermitAll; import jakarta.annotation.security.PermitAll;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
@@ -19,44 +19,46 @@ import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler; import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
@PermitAll @PermitAll
public class MainLayout extends AppLayout { public class MainLayout extends AppLayout {
public MainLayout() { public MainLayout() {
createHeader(); buildHeader();
} }
private void createHeader() { private void buildHeader() {
H1 logo = new H1("Time Tracker"); H1 title = new H1("Time Tracker");
logo.getStyle() title.getStyle()
.set("font-size", "var(--lumo-font-size-l)") .set("font-size", "var(--lumo-font-size-l)")
.set("margin", "0"); .set("margin", "0");
RouterLink homeLink = new RouterLink("Dashboard", MainView.class); RouterLink dashboardLink = new RouterLink("Dashboard", MainView.class);
RouterLink bookingsLink = new RouterLink("Bookings", TimeEntryView.class); RouterLink bookingsLink = new RouterLink("Bookings", TimeEntryView.class);
RouterLink userAdminView = new RouterLink("Admin", UserAdminView.class); RouterLink adminLink = new RouterLink("Admin", UserManagementView.class);
homeLink.getStyle().set("margin-left", "2em");
dashboardLink.getStyle().set("margin-left", "2em");
bookingsLink.getStyle().set("margin-left", "2em"); bookingsLink.getStyle().set("margin-left", "2em");
userAdminView.getStyle().set("margin-left", "2em"); adminLink.getStyle().set("margin-left", "2em");
Button logoutButton = new Button("Logout", event -> handleLogout()); Button logoutButton = new Button("Logout", event -> performLogout());
HorizontalLayout header = new HorizontalLayout(logo, homeLink, bookingsLink, userAdminView, logoutButton); HorizontalLayout headerLayout = new HorizontalLayout(
header.setDefaultVerticalComponentAlignment(FlexComponent.Alignment.CENTER); title, dashboardLink, bookingsLink, adminLink, logoutButton
header.setWidthFull(); );
header.setPadding(true); headerLayout.setDefaultVerticalComponentAlignment(FlexComponent.Alignment.CENTER);
header.setSpacing(true); headerLayout.setWidthFull();
headerLayout.setPadding(true);
headerLayout.setSpacing(true);
addToNavbar(header); addToNavbar(headerLayout);
} }
private void handleLogout() { private void performLogout() {
HttpServletRequest request = VaadinServletRequest.getCurrent().getHttpServletRequest(); HttpServletRequest request = VaadinServletRequest.getCurrent().getHttpServletRequest();
HttpServletResponse response = VaadinServletResponse.getCurrent().getHttpServletResponse(); HttpServletResponse response = VaadinServletResponse.getCurrent().getHttpServletResponse();
Authentication auth = SecurityContextHolder.getContext().getAuthentication(); Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (auth != null) { if (authentication != null) {
new SecurityContextLogoutHandler().logout(request, response, auth); new SecurityContextLogoutHandler().logout(request, response, authentication);
} }
getUI().ifPresent(ui -> ui.getPage().setLocation("/login")); getUI().ifPresent(ui -> ui.getPage().setLocation("/login"));