Compare commits
2 Commits
6b57a0c5e5
...
44672876be
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
44672876be | ||
|
|
e828e83991 |
@@ -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);
|
||||||
|
|||||||
@@ -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"));
|
||||||
|
|||||||
Reference in New Issue
Block a user