Erweiterungen

This commit is contained in:
2025-05-05 11:47:10 +02:00
parent e0e60be428
commit 6a4f5f5e84
58 changed files with 676 additions and 288 deletions

25
pom.xml
View File

@@ -47,18 +47,6 @@
<artifactId>vaadin-spring-boot-starter</artifactId>
</dependency>
<!-- Persistence -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<!-- Replace with the database you will be using in production -->
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<!-- Additional Spring Dependencies -->
<dependency>
<groupId>org.springframework.boot</groupId>
@@ -74,17 +62,16 @@
<optional>true</optional>
</dependency>
<!-- Testing -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>com.tngtech.archunit</groupId>
<artifactId>archunit-junit5</artifactId>
<version>${archunit.version}</version>
<scope>test</scope>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
<scope>provided</scope>
</dependency>
</dependencies>

View File

@@ -1,44 +0,0 @@
package de.assecutor.votianlt.base.domain;
import jakarta.persistence.MappedSuperclass;
import org.jspecify.annotations.Nullable;
import org.springframework.data.util.ProxyUtils;
@MappedSuperclass
public abstract class AbstractEntity<ID> {
public abstract @Nullable ID getId();
@Override
public String toString() {
return "%s{id=%s}".formatted(getClass().getSimpleName(), getId());
}
@Override
public int hashCode() {
// Hashcode should never change during the lifetime of an object. Because of
// this we can't use getId() to calculate the hashcode. Unless you have sets
// with lots of entities in them, returning the same hashcode should not be a
// problem.
return ProxyUtils.getUserClass(getClass()).hashCode();
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
} else if (obj == this) {
return true;
}
var thisUserClass = ProxyUtils.getUserClass(getClass());
var otherUserClass = ProxyUtils.getUserClass(obj);
if (thisUserClass != otherUserClass) {
return false;
}
var id = getId();
return id != null && id.equals(((AbstractEntity<?>) obj).getId());
}
}

View File

@@ -1,4 +0,0 @@
@NullMarked
package de.assecutor.votianlt.base.domain;
import org.jspecify.annotations.NullMarked;

View File

@@ -1,4 +0,0 @@
@NullMarked
package de.assecutor.votianlt.base.ui.component;
import org.jspecify.annotations.NullMarked;

View File

@@ -1,4 +0,0 @@
@NullMarked
package de.assecutor.votianlt.base.ui.view;
import org.jspecify.annotations.NullMarked;

View File

@@ -0,0 +1,12 @@
package de.assecutor.votianlt.model;
public class address {
public int ad_id;
public String ad_street;
public String ad_add;
public String ad_zipcode;
public String ad_city;
public String ad_country;
public String ad_lat;
public String ad_lng;
}

View File

@@ -0,0 +1,13 @@
package de.assecutor.votianlt.model;
public class address_book {
public int adb_id;
public int usr_id;
public int ad_b_ad_id;
public String deliverHsno;
public String deliverCompany;
public String deliverTitle;
public String deliverFirstname;
public String deliverLastname;
public String deliverPhone;
}

View File

@@ -0,0 +1,9 @@
package de.assecutor.votianlt.model;
public class address_book_addresses
{
public int ad_b_ad_id;
public String deliverStreet;
public String deliverPlz;
public String deliverCity;
}

View File

@@ -0,0 +1,17 @@
package de.assecutor.votianlt.model;
public class company
{
public int cmp_id;
public String cmp_comp;
public String cmp_comp2;
public String cmp_hsno;
public String cmp_Ustid;
public String cmp_Taxid;
public String cmp_Iban;
public String cmp_homepage;
public String votian_cmp_id;
public String votian_ad_id;
public String votian_tx_id;
public String votian_br_id;
}

View File

@@ -0,0 +1,11 @@
package de.assecutor.votianlt.model;
public class contractor
{
public int cr_id;
public int cmp_id;
public int usr_id;
public String votian_cr_id;
public String votian_cr_eid;
public String votian_hq_id;
}

View File

@@ -0,0 +1,9 @@
package de.assecutor.votianlt.model;
public class contractor_relation
{
public int cr_r_id;
public int usr_id;
public int cr_id;
public String cr_filter_json;
}

View File

@@ -0,0 +1,12 @@
package de.assecutor.votianlt.model;
public class costcenter
{
public int cs_id;
public int csc_id;
public String csc_comp;
public String csc_comp2;
public String csc_hsno;
public String csc_usr_name;
public String csc_usr_firstname;
}

View File

@@ -0,0 +1,8 @@
package de.assecutor.votianlt.model;
public class costcenter_address
{
public int csc_id;
public int ad_id;
public int adt_id;
}

View File

@@ -0,0 +1,11 @@
package de.assecutor.votianlt.model;
public class country
{
public String cou_iso_3;
public String cou_iso_no;
public String cou_mnemonic;
public String cou_name;
public String cou_iso_2;
public byte cou_continent;
}

View File

@@ -0,0 +1,15 @@
package de.assecutor.votianlt.model;
public class customer
{
public int cs_id;
public int cmp_id;
public int csc_id;
public int emp_id;
public String votian_cs_id;
public String votian_cs_eid;
public String votian_cs_admin;
public String votian_hq_id;
public String votian_cs_id_parent;
public String votian_cs_id_related;
}

View File

@@ -0,0 +1,8 @@
package de.assecutor.votianlt.model;
public class customer_relation
{
public int cs_r_id;
public int usr_id;
public int cr_id;
}

View File

@@ -0,0 +1,15 @@
package de.assecutor.votianlt.model;
public class device
{
public int d_id;
public int usr_id;
public int d_details;
public String d_name;
public int votian_dv_id;
public String device_name;
public String uuid;
public String code;
public int cust_id;
public int cust_acc_group;
}

View File

@@ -0,0 +1,11 @@
package de.assecutor.votianlt.model;
public class devices_invoice
{
public int d_i_id;
public String d_i_create;
public String d_i_delete;
public int d_id;
public int vlt_i_id;
public int usr_id;
}

View File

@@ -0,0 +1,7 @@
package de.assecutor.votianlt.model;
public class employee
{
public int emp_id;
public int usr_id;
}

View File

@@ -0,0 +1,9 @@
package de.assecutor.votianlt.model;
public class filter
{
public int f_id;
public int f_type;
public String f_short;
public String f_status;
}

View File

@@ -0,0 +1,7 @@
package de.assecutor.votianlt.model;
public class help
{
public int h_id;
public String h_language;
}

View File

@@ -0,0 +1,12 @@
package de.assecutor.votianlt.model;
public class invoice
{
public int i_id;
public int usr_id;
public int cr_id;
public String i_export_time;
public int i_create_date;
public String invoiceNumber;
public String fileName;
}

View File

@@ -0,0 +1,13 @@
package de.assecutor.votianlt.model;
public class invoice_credit
{
public int i_c_id;
public String i_c_date;
public int usr_id;
public double i_c_amount;
public String purpose;
public String iban;
public String currency;
public double diff;
}

View File

@@ -0,0 +1,27 @@
package de.assecutor.votianlt.model;
public class job
{
public int jb_id;
public int cs_id;
public int cr_id;
public int jb_votian_id;
public java.sql.Date jb_ordertime;
public int jb_status;
public int jb_type;
public int jb_invoice_data;
public String useApp;
public String customerID;
public String datepickerPickup;
public String timepickerPickup;
public String datepickerDel;
public String timepickerDel;
public String remark;
public String price;
public String submit;
public String appUserID;
public String cargo_type;
public String cargo_weight;
public String cargo_volume;
public String jobdetail_instruction;
}

View File

@@ -0,0 +1,16 @@
package de.assecutor.votianlt.model;
public class log
{
public int logo_id;
public String log_createtime;
public int hq_id;
public int jb_id;
public int usr_id;
public int cr_id;
public int cr_sid;
public int cs_id;
public int at_id;
public int pt_id;
public int emp_id;
}

View File

@@ -0,0 +1,10 @@
package de.assecutor.votianlt.model;
public class log_invoice
{
public int l_i_id;
public int i_id;
public String i_date;
public int i_export_time_1;
public String i_export_time_2;
}

View File

@@ -0,0 +1,10 @@
package de.assecutor.votianlt.model;
public class notification
{
public int n_id;
public String n_date;
public int n_info_id;
public int usr_id;
public byte n_new;
}

View File

@@ -0,0 +1,6 @@
package de.assecutor.votianlt.model;
public class notification_info
{
public int n_i_id;
}

View File

@@ -0,0 +1,12 @@
package de.assecutor.votianlt.model;
public class offer
{
public int o_id;
public int jb_id;
public int usr_id;
public int cr_id;
public java.sql.Date offer_time;
public String price;
public String remark;
}

View File

@@ -0,0 +1,11 @@
package de.assecutor.votianlt.model;
public class parameter
{
public int par_id;
public String par_key;
public int md_id;
public int hq_id;
public int emp_id;
public String par_value;
}

View File

@@ -0,0 +1,7 @@
package de.assecutor.votianlt.model;
public class price_table
{
public int pt_id;
public double pt_price;
}

View File

@@ -0,0 +1,16 @@
package de.assecutor.votianlt.model;
public class station
{
public int station_id;
public int jb_id;
public String station_type;
public int ad_id;
public int station_order;
public String station_name;
public String station_contact;
public String station_phone;
public java.sql.Date station_arrival_est;
public java.sql.Date station_departure_est;
public String instructions;
}

View File

@@ -0,0 +1,16 @@
package de.assecutor.votianlt.model;
public class transportorder
{
public int tr_id;
public int jb_id;
public int usr_id;
public String tr_comment;
public String tr_state;
public String tr_driver_lat;
public String tr_driver_lng;
public String tr_driver_accuracy;
public String tr_driver_last_update;
public String tr_created;
public String tr_updated;
}

View File

@@ -0,0 +1,8 @@
package de.assecutor.votianlt.model;
public class two_way
{
public int t_w_id;
public int usr_id;
public String t_w_secret;
}

View File

@@ -0,0 +1,38 @@
package de.assecutor.votianlt.model;
public class user
{
public int usr_id;
public int hq_id;
public short usr_type;
public String usr_title;
public String usr_name;
public String usr_firstname;
public java.sql.Date usr_birthdate;
public int ad_id;
public String usr_hsno;
public String usr_email;
public String usr_inv_email;
public String usr_phone;
public String usr_phone2;
public String usr_fax;
public String usr_account;
public String usr_password;
public String usr_modify;
public byte usr_is_activated;
public String usr_activation_code;
public byte usr_is_email_confirmed;
public String usr_code;
public int usr_code_timestamp;
public byte usr_is_password_lost;
public String usr_password_code;
public int usr_password_timestamp;
public byte usr_app;
public String votian_usr_id;
public String auth_customer;
public String auth_account;
public String auth_password;
public String auth_session_id;
public long activationDate;
public double balance;
}

View File

@@ -0,0 +1,18 @@
package de.assecutor.votianlt.model;
public class vehicle
{
public int vh_id;
public int usr_parent_id;
public int cr_id;
public int vh_details;
public int d_id;
public String title;
public String code;
public String votian_vht_id;
public String votian_vht_id_inv;
public String votian_cr_ar_jb_id;
public String votian_crvh_id;
public String votian_cr_id;
public String votian_crvh_sid;
}

View File

@@ -0,0 +1,21 @@
package de.assecutor.votianlt.model;
public class vlt_invoice
{
public int vlt_i_id;
public int usr_id;
public String vlt_i_price;
public String vlt_i_date;
public int vlt_i_status;
public String vlt_i_html;
public String totalPriceNet;
public String totalPrice;
public String payedDays;
public String daysInMonth;
public String devicePrice;
public String basePrice;
public String systemVat;
public String basePricePayed;
public String vatPrice;
public String invoiceNumber;
}

View File

@@ -1,4 +1,4 @@
package de.assecutor.votianlt.base.ui.component;
package de.assecutor.votianlt.pages.base.ui.component;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.Composite;

View File

@@ -1,4 +1,4 @@
package de.assecutor.votianlt.base.ui.view;
package de.assecutor.votianlt.pages.base.ui.view;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.notification.Notification;

View File

@@ -1,4 +1,4 @@
package de.assecutor.votianlt.base.ui.view;
package de.assecutor.votianlt.pages.base.ui.view;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.applayout.AppLayout;
@@ -25,6 +25,8 @@ public final class MainLayout extends AppLayout {
public MainLayout() {
setPrimarySection(Section.DRAWER);
addToDrawer(createHeader(), new Scroller(createSideNav()), createUserMenu());
//setDrawerOpened(false);
}
private Div createHeader() {
@@ -32,7 +34,7 @@ public final class MainLayout extends AppLayout {
var appLogo = VaadinIcon.CUBES.create();
appLogo.addClassNames(TextColor.PRIMARY, IconSize.LARGE);
var appName = new Span("Votianlt");
var appName = new Span("VotianLT");
appName.addClassNames(FontWeight.SEMIBOLD, FontSize.LARGE);
var header = new Div(appLogo, appName);

View File

@@ -0,0 +1,19 @@
package de.assecutor.votianlt.pages.customers.domain;
import lombok.Data;
import org.springframework.data.mongodb.core.mapping.Document;
import java.time.Instant;
import java.time.LocalDate;
@Document(collection = "customer")
@Data
public class Customer {
private Long id;
private String description;
private Instant creationDate;
private LocalDate dueDate;
}

View File

@@ -0,0 +1,11 @@
package de.assecutor.votianlt.pages.customers.domain;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.mongodb.repository.MongoRepository;
public interface CustomerRepository extends MongoRepository<Customer, String> {
// If you don't need a total row count, Slice is better than Page.
Slice<Customer> findAllBy(Pageable pageable);
}

View File

@@ -1,7 +1,7 @@
package de.assecutor.votianlt.todo.service;
package de.assecutor.votianlt.pages.customers.service;
import de.assecutor.votianlt.todo.domain.Todo;
import de.assecutor.votianlt.todo.domain.TodoRepository;
import de.assecutor.votianlt.pages.customers.domain.Customer;
import de.assecutor.votianlt.pages.customers.domain.CustomerRepository;
import org.jspecify.annotations.Nullable;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
@@ -14,13 +14,13 @@ import java.util.List;
@Service
@Transactional(propagation = Propagation.REQUIRES_NEW)
public class TodoService {
public class CustomerService {
private final TodoRepository todoRepository;
private final CustomerRepository todoRepository;
private final Clock clock;
TodoService(TodoRepository todoRepository, Clock clock) {
CustomerService(CustomerRepository todoRepository, Clock clock) {
this.todoRepository = todoRepository;
this.clock = clock;
}
@@ -29,14 +29,14 @@ public class TodoService {
if ("fail".equals(description)) {
throw new RuntimeException("This is for testing the error handler");
}
var todo = new Todo();
var todo = new Customer();
todo.setDescription(description);
todo.setCreationDate(clock.instant());
todo.setDueDate(dueDate);
todoRepository.saveAndFlush(todo);
todoRepository.save(todo);
}
public List<Todo> list(Pageable pageable) {
public List<Customer> list(Pageable pageable) {
return todoRepository.findAllBy(pageable).toList();
}

View File

@@ -1,8 +1,5 @@
package de.assecutor.votianlt.todo.ui.view;
package de.assecutor.votianlt.pages.customers.ui.view;
import de.assecutor.votianlt.base.ui.component.ViewToolbar;
import de.assecutor.votianlt.todo.domain.Todo;
import de.assecutor.votianlt.todo.service.TodoService;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.button.ButtonVariant;
import com.vaadin.flow.component.datepicker.DatePicker;
@@ -15,6 +12,9 @@ import com.vaadin.flow.router.Menu;
import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.theme.lumo.LumoUtility;
import de.assecutor.votianlt.pages.base.ui.component.ViewToolbar;
import de.assecutor.votianlt.pages.customers.domain.Customer;
import de.assecutor.votianlt.pages.customers.service.CustomerService;
import java.time.Clock;
import java.time.format.DateTimeFormatter;
@@ -23,25 +23,25 @@ import java.util.Optional;
import static com.vaadin.flow.spring.data.VaadinSpringDataHelpers.toSpringPageRequest;
@Route("")
@PageTitle("Task List")
@Menu(order = 0, icon = "vaadin:clipboard-check", title = "Task List")
public class TodoView extends Main {
@Route("customer")
@PageTitle("Kunden")
@Menu(order = 0, icon = "vaadin:clipboard-check", title = "Kunden")
public class CustomersView extends Main {
private final TodoService todoService;
private final CustomerService todoService;
final TextField description;
final DatePicker dueDate;
final Button createBtn;
final Grid<Todo> todoGrid;
final Grid<Customer> todoGrid;
public TodoView(TodoService todoService, Clock clock) {
public CustomersView(CustomerService todoService, Clock clock) {
this.todoService = todoService;
description = new TextField();
description.setPlaceholder("What do you want to do?");
description.setAriaLabel("Task description");
description.setMaxLength(Todo.DESCRIPTION_MAX_LENGTH);
description.setMaxLength(255);
description.setMinWidth("20em");
dueDate = new DatePicker();
@@ -57,7 +57,7 @@ public class TodoView extends Main {
todoGrid = new Grid<>();
todoGrid.setItems(query -> todoService.list(toSpringPageRequest(query)).stream());
todoGrid.addColumn(Todo::getDescription).setHeader("Description");
todoGrid.addColumn(Customer::getDescription).setHeader("Description");
todoGrid.addColumn(todo -> Optional.ofNullable(todo.getDueDate()).map(dateFormatter::format).orElse("Never"))
.setHeader("Due Date");
todoGrid.addColumn(todo -> dateTimeFormatter.format(todo.getCreationDate())).setHeader("Creation Date");

View File

@@ -0,0 +1,21 @@
package de.assecutor.votianlt.pages.register.domain;
import jakarta.validation.constraints.Size;
import lombok.Data;
import org.jspecify.annotations.Nullable;
import org.springframework.data.mongodb.core.mapping.Document;
import java.time.Instant;
import java.time.LocalDate;
@Document(collection = "colors")
@Data
public class Order {
private Long id;
private String description;
private Instant creationDate;
private LocalDate dueDate;
}

View File

@@ -0,0 +1,12 @@
package de.assecutor.votianlt.pages.register.domain;
import de.assecutor.votianlt.pages.customers.domain.Customer;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.mongodb.repository.MongoRepository;
public interface RegisterRepository extends MongoRepository<Customer, String> {
// If you don't need a total row count, Slice is better than Page.
Slice<Order> findAllBy(Pageable pageable);
}

View File

@@ -0,0 +1,37 @@
package de.assecutor.votianlt.pages.register.service;
import de.assecutor.votianlt.pages.register.domain.RegisterRepository;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.time.Clock;
import java.util.List;
@Service
@Transactional(propagation = Propagation.REQUIRES_NEW)
public class RegisterService {
private final RegisterRepository registerRepository;
private final Clock clock;
RegisterService(RegisterRepository registerRepository, Clock clock) {
this.registerRepository = registerRepository;
this.clock = clock;
}
public void registerUser(String mail, String password) {
/*if ("fail".equals(description)) {
throw new RuntimeException("This is for testing the error handler");
}
var todo = new Todo();
todo.setDescription(description);
todo.setCreationDate(clock.instant());
todo.setDueDate(dueDate);
todoRepository.saveAndFlush(todo);*/
}
//public List<Order> list(Pageable pageable) { return todoRepository.findAllBy(pageable).toList();
}

View File

@@ -0,0 +1,66 @@
package de.assecutor.votianlt.pages.register.ui.view;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.applayout.AppLayout;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.button.ButtonVariant;
import com.vaadin.flow.component.html.Main;
import com.vaadin.flow.component.notification.Notification;
import com.vaadin.flow.component.notification.NotificationVariant;
import com.vaadin.flow.component.orderedlayout.FlexComponent;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.router.Menu;
import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.theme.lumo.LumoUtility;
import de.assecutor.votianlt.pages.base.ui.component.ViewToolbar;
import de.assecutor.votianlt.pages.register.service.RegisterService;
import de.assecutor.votianlt.util.Util;
import java.time.Clock;
@Route("register")
@PageTitle("Bei VotianLT registrieren")
//@Menu(order = 0, icon = "vaadin:clipboard-check", title = "Bei VotianLT registrieren")
public class RegisterView extends Main {
private final RegisterService registerService;
TextField usernameField = new TextField("E-Mail-Adresse");
TextField password1Field = new TextField("Passwort");
TextField password2Field = new TextField("Passwort wiederholen");
Button submitButton = new Button("Registrieren");
public RegisterView(RegisterService registerService, Clock clock) {
this.registerService = registerService;
// Setze den Button als primär
submitButton = new Button("Create", event -> submit());
submitButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
// Erstelle ein Div als Container (oder direkt ein Layout)
VerticalLayout formLayout = new VerticalLayout();
formLayout.add(usernameField, password1Field, password2Field, submitButton);
// Zentriere die Inhalte vertikal und horizontal
formLayout.setDefaultHorizontalComponentAlignment(FlexComponent.Alignment.CENTER);
formLayout.setSpacing(true);
formLayout.setSizeUndefined(); // Inhalt eng setzen
setSizeFull();
addClassNames(LumoUtility.BoxSizing.BORDER, LumoUtility.Display.FLEX, LumoUtility.FlexDirection.COLUMN,
LumoUtility.Padding.MEDIUM, LumoUtility.Gap.SMALL);
add(formLayout);
}
private void submit() {
Util.changeDrawerState(true);
}
private void createTodo() {
registerService.registerUser(usernameField.getValue(), password1Field.getValue());
Notification.show("Benutzer registriert", 3000, Notification.Position.BOTTOM_END).addThemeVariants(NotificationVariant.LUMO_SUCCESS);
}
}

View File

@@ -0,0 +1,42 @@
package de.assecutor.votianlt.pages.start.ui.view;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.button.ButtonVariant;
import com.vaadin.flow.component.html.Main;
import com.vaadin.flow.router.Menu;
import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.theme.lumo.LumoUtility;
@Route("")
@PageTitle("Start")
@Menu(order = 0, icon = "vaadin:clipboard-check", title = "Start")
public class OrdersView extends Main {
final Button registerBtn;
final Button loginBtn;
public OrdersView() {
registerBtn = new Button("Registrieren", event -> register());
registerBtn.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
add(registerBtn);
loginBtn = new Button("Anmelden", event -> login());
loginBtn.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
add(loginBtn);
setSizeFull();
addClassNames(LumoUtility.BoxSizing.BORDER, LumoUtility.Display.FLEX, LumoUtility.FlexDirection.COLUMN,
LumoUtility.Padding.MEDIUM, LumoUtility.Gap.SMALL);
}
private void register() {
UI.getCurrent().navigate("register");
}
private void login() {
}
}

View File

@@ -1,61 +0,0 @@
package de.assecutor.votianlt.todo.domain;
import de.assecutor.votianlt.base.domain.AbstractEntity;
import jakarta.persistence.*;
import jakarta.validation.constraints.Size;
import org.jspecify.annotations.Nullable;
import java.time.Instant;
import java.time.LocalDate;
@Entity
@Table(name = "todo")
public class Todo extends AbstractEntity<Long> {
public static final int DESCRIPTION_MAX_LENGTH = 255;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "todo_id")
private Long id;
@Column(name = "description", nullable = false, length = DESCRIPTION_MAX_LENGTH)
@Size(max = DESCRIPTION_MAX_LENGTH)
private String description;
@Column(name = "creation_date", nullable = false)
private Instant creationDate;
@Column(name = "due_date")
@Nullable
private LocalDate dueDate;
@Override
public @Nullable Long getId() {
return id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Instant getCreationDate() {
return creationDate;
}
public void setCreationDate(Instant creationDate) {
this.creationDate = creationDate;
}
public @Nullable LocalDate getDueDate() {
return dueDate;
}
public void setDueDate(@Nullable LocalDate dueDate) {
this.dueDate = dueDate;
}
}

View File

@@ -1,12 +0,0 @@
package de.assecutor.votianlt.todo.domain;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
public interface TodoRepository extends JpaRepository<Todo, Long>, JpaSpecificationExecutor<Todo> {
// If you don't need a total row count, Slice is better than Page.
Slice<Todo> findAllBy(Pageable pageable);
}

View File

@@ -1,4 +0,0 @@
@NullMarked
package de.assecutor.votianlt.todo.domain;
import org.jspecify.annotations.NullMarked;

View File

@@ -1,4 +0,0 @@
@NullMarked
package de.assecutor.votianlt.todo.service;
import org.jspecify.annotations.NullMarked;

View File

@@ -1,4 +0,0 @@
@NullMarked
package de.assecutor.votianlt.todo.ui.view;
import org.jspecify.annotations.NullMarked;

View File

@@ -0,0 +1,16 @@
package de.assecutor.votianlt.util;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.applayout.AppLayout;
public class Util {
public static void changeDrawerState(boolean drawerState) {
AppLayout appLayout = (AppLayout) UI.getCurrent().getChildren()
.filter(AppLayout.class::isInstance)
.findFirst().orElse(null);
if (appLayout != null) {
appLayout.setDrawerOpened(drawerState);
}
}
}

View File

@@ -10,3 +10,6 @@ vaadin.allowed-packages=com.vaadin,org.vaadin,de.assecutor.votianlt
# Open-in-view is only needed if you use lazy-loaded entities in your Flow views.
spring.jpa.open-in-view=false
# MongoDB
spring.data.mongodb.uri=mongodb://192.168.180.28:27017/votianlt

View File

@@ -1,48 +0,0 @@
package de.assecutor.votianlt;
import com.tngtech.archunit.junit.AnalyzeClasses;
import com.tngtech.archunit.junit.ArchTest;
import com.tngtech.archunit.lang.ArchRule;
import org.springframework.data.repository.Repository;
import org.springframework.transaction.annotation.Transactional;
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes;
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses;
import static com.tngtech.archunit.library.dependencies.SlicesRuleDefinition.slices;
@AnalyzeClasses(packages = ArchitectureTest.BASE_PACKAGE)
class ArchitectureTest {
static final String BASE_PACKAGE = "de.assecutor.votianlt";
// TODO Add your own rules and remove those that don't apply to your project
@ArchTest
public static final ArchRule domain_model_should_not_depend_on_application_services = noClasses().that()
.resideInAPackage(BASE_PACKAGE + "..domain..").should().dependOnClassesThat()
.resideInAPackage(BASE_PACKAGE + "..service..");
@ArchTest
public static final ArchRule domain_model_should_not_depend_on_the_user_interface = noClasses().that()
.resideInAPackage(BASE_PACKAGE + "..domain..").should().dependOnClassesThat()
.resideInAnyPackage(BASE_PACKAGE + "..ui..");
@ArchTest
public static final ArchRule repositories_should_only_be_used_by_application_services_and_other_domain_classes = classes()
.that().areAssignableTo(Repository.class).should().onlyHaveDependentClassesThat()
.resideInAnyPackage(BASE_PACKAGE + "..domain..", BASE_PACKAGE + "..service..");
@ArchTest
public static final ArchRule repositories_should_only_be_accessed_by_transactional_classes = classes().that()
.areAssignableTo(Repository.class).should().onlyBeAccessed().byClassesThat()
.areAnnotatedWith(Transactional.class);
@ArchTest
public static final ArchRule application_services_should_not_depend_on_the_user_interface = noClasses().that()
.resideInAPackage(BASE_PACKAGE + "..service..").should().dependOnClassesThat()
.resideInAnyPackage(BASE_PACKAGE + "..ui..");
@ArchTest
public static final ArchRule there_should_not_be_circular_dependencies_between_feature_packages = slices()
.matching(BASE_PACKAGE + ".(*)..").should().beFreeOfCycles();
}

View File

@@ -1,54 +0,0 @@
package de.assecutor.votianlt.todo.service;
import de.assecutor.votianlt.todo.domain.Todo;
import de.assecutor.votianlt.todo.domain.TodoRepository;
import jakarta.validation.ValidationException;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.PageRequest;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.time.Clock;
import java.time.LocalDate;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)
@Transactional(propagation = Propagation.NOT_SUPPORTED)
class TodoServiceIT {
@Autowired
TodoService todoService;
@Autowired
TodoRepository todoRepository;
@Autowired
Clock clock;
@AfterEach
void cleanUp() {
todoRepository.deleteAll();
}
@Test
public void todos_are_stored_in_the_database_with_the_current_timestamp() {
var now = clock.instant();
var due = LocalDate.of(2025, 2, 7);
todoService.createTodo("Do this", due);
assertThat(todoService.list(PageRequest.ofSize(1))).singleElement()
.matches(todo -> todo.getDescription().equals("Do this") && due.equals(todo.getDueDate())
&& todo.getCreationDate().isAfter(now));
}
@Test
public void todos_are_validated_before_they_are_stored() {
assertThatThrownBy(() -> todoService.createTodo("X".repeat(Todo.DESCRIPTION_MAX_LENGTH + 1), null))
.isInstanceOf(ValidationException.class);
assertThat(todoRepository.count()).isEqualTo(0);
}
}