Generated project
This commit is contained in:
23
src/main/frontend/index.html
Normal file
23
src/main/frontend/index.html
Normal 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>
|
||||
0
src/main/frontend/themes/default/styles.css
Normal file
0
src/main/frontend/themes/default/styles.css
Normal file
9
src/main/frontend/themes/default/theme.json
Normal file
9
src/main/frontend/themes/default/theme.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"lumoImports": [
|
||||
"typography",
|
||||
"color",
|
||||
"spacing",
|
||||
"badge",
|
||||
"utility"
|
||||
]
|
||||
}
|
||||
24
src/main/java/de/assecutor/emulatorstation/Application.java
Normal file
24
src/main/java/de/assecutor/emulatorstation/Application.java
Normal file
@@ -0,0 +1,24 @@
|
||||
package de.assecutor.emulatorstation;
|
||||
|
||||
import com.vaadin.flow.component.page.AppShellConfigurator;
|
||||
import com.vaadin.flow.theme.Theme;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
import java.time.Clock;
|
||||
|
||||
@SpringBootApplication
|
||||
@Theme("default")
|
||||
public class Application implements AppShellConfigurator {
|
||||
|
||||
@Bean
|
||||
public Clock clock() {
|
||||
return Clock.systemDefaultZone(); // You can also use Clock.systemUTC()
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package de.assecutor.emulatorstation.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());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* This package contains reusable domain classes.
|
||||
*/
|
||||
@NullMarked
|
||||
package de.assecutor.emulatorstation.base.domain;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
@@ -0,0 +1,41 @@
|
||||
package de.assecutor.emulatorstation.base.ui.component;
|
||||
|
||||
import com.vaadin.flow.component.Component;
|
||||
import com.vaadin.flow.component.Composite;
|
||||
import com.vaadin.flow.component.applayout.DrawerToggle;
|
||||
import com.vaadin.flow.component.html.Div;
|
||||
import com.vaadin.flow.component.html.H1;
|
||||
import com.vaadin.flow.component.html.Header;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility.*;
|
||||
|
||||
public final class ViewToolbar extends Composite<Header> {
|
||||
|
||||
public ViewToolbar(String viewTitle, Component... components) {
|
||||
addClassNames(Display.FLEX, FlexDirection.COLUMN, JustifyContent.BETWEEN, AlignItems.STRETCH, Gap.MEDIUM,
|
||||
FlexDirection.Breakpoint.Medium.ROW, AlignItems.Breakpoint.Medium.CENTER);
|
||||
|
||||
var drawerToggle = new DrawerToggle();
|
||||
drawerToggle.addClassNames(Margin.NONE);
|
||||
|
||||
var title = new H1(viewTitle);
|
||||
title.addClassNames(FontSize.XLARGE, Margin.NONE, FontWeight.LIGHT);
|
||||
|
||||
var toggleAndTitle = new Div(drawerToggle, title);
|
||||
toggleAndTitle.addClassNames(Display.FLEX, AlignItems.CENTER);
|
||||
getContent().add(toggleAndTitle);
|
||||
|
||||
if (components.length > 0) {
|
||||
var actions = new Div(components);
|
||||
actions.addClassNames(Display.FLEX, FlexDirection.COLUMN, JustifyContent.BETWEEN, Flex.GROW, Gap.SMALL,
|
||||
FlexDirection.Breakpoint.Medium.ROW);
|
||||
getContent().add(actions);
|
||||
}
|
||||
}
|
||||
|
||||
public static Component group(Component... components) {
|
||||
var group = new Div(components);
|
||||
group.addClassNames(Display.FLEX, FlexDirection.COLUMN, AlignItems.STRETCH, Gap.SMALL,
|
||||
FlexDirection.Breakpoint.Medium.ROW, AlignItems.Breakpoint.Medium.CENTER);
|
||||
return group;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* This package contains reusable UI components.
|
||||
*/
|
||||
@NullMarked
|
||||
package de.assecutor.emulatorstation.base.ui.component;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
@@ -0,0 +1,32 @@
|
||||
package de.assecutor.emulatorstation.base.ui.view;
|
||||
|
||||
import com.vaadin.flow.component.Component;
|
||||
import com.vaadin.flow.component.notification.Notification;
|
||||
import com.vaadin.flow.component.notification.NotificationVariant;
|
||||
import com.vaadin.flow.server.VaadinServiceInitListener;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
class MainErrorHandler {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(MainErrorHandler.class);
|
||||
|
||||
@Bean
|
||||
public VaadinServiceInitListener errorHandlerInitializer() {
|
||||
return (event) -> event.getSource().addSessionInitListener(
|
||||
sessionInitEvent -> sessionInitEvent.getSession().setErrorHandler(errorEvent -> {
|
||||
log.error("An unexpected error occurred", errorEvent.getThrowable());
|
||||
errorEvent.getComponent().flatMap(Component::getUI).ifPresent(ui -> {
|
||||
var notification = new Notification(
|
||||
"An unexpected error has occurred. Please try again later.");
|
||||
notification.addThemeVariants(NotificationVariant.LUMO_ERROR);
|
||||
notification.setPosition(Notification.Position.TOP_CENTER);
|
||||
notification.setDuration(3000);
|
||||
ui.access(notification::open);
|
||||
});
|
||||
}));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package de.assecutor.emulatorstation.base.ui.view;
|
||||
|
||||
import com.vaadin.flow.component.Component;
|
||||
import com.vaadin.flow.component.applayout.AppLayout;
|
||||
import com.vaadin.flow.component.avatar.Avatar;
|
||||
import com.vaadin.flow.component.avatar.AvatarVariant;
|
||||
import com.vaadin.flow.component.html.Div;
|
||||
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.menubar.MenuBar;
|
||||
import com.vaadin.flow.component.menubar.MenuBarVariant;
|
||||
import com.vaadin.flow.component.orderedlayout.Scroller;
|
||||
import com.vaadin.flow.component.sidenav.SideNav;
|
||||
import com.vaadin.flow.component.sidenav.SideNavItem;
|
||||
import com.vaadin.flow.router.Layout;
|
||||
import com.vaadin.flow.server.menu.MenuConfiguration;
|
||||
import com.vaadin.flow.server.menu.MenuEntry;
|
||||
import jakarta.annotation.security.PermitAll;
|
||||
|
||||
import static com.vaadin.flow.theme.lumo.LumoUtility.*;
|
||||
|
||||
@Layout
|
||||
@PermitAll // When security is enabled, allow all authenticated users
|
||||
public final class MainLayout extends AppLayout {
|
||||
|
||||
MainLayout() {
|
||||
setPrimarySection(Section.DRAWER);
|
||||
addToDrawer(createHeader(), new Scroller(createSideNav()), createUserMenu());
|
||||
}
|
||||
|
||||
private Div createHeader() {
|
||||
// TODO Replace with real application logo and name
|
||||
var appLogo = VaadinIcon.CUBES.create();
|
||||
appLogo.addClassNames(TextColor.PRIMARY, IconSize.LARGE);
|
||||
|
||||
var appName = new Span("Emulatorstation");
|
||||
appName.addClassNames(FontWeight.SEMIBOLD, FontSize.LARGE);
|
||||
|
||||
var header = new Div(appLogo, appName);
|
||||
header.addClassNames(Display.FLEX, Padding.MEDIUM, Gap.MEDIUM, AlignItems.CENTER);
|
||||
return header;
|
||||
}
|
||||
|
||||
private SideNav createSideNav() {
|
||||
var nav = new SideNav();
|
||||
nav.addClassNames(Margin.Horizontal.MEDIUM);
|
||||
MenuConfiguration.getMenuEntries().forEach(entry -> nav.addItem(createSideNavItem(entry)));
|
||||
return nav;
|
||||
}
|
||||
|
||||
private SideNavItem createSideNavItem(MenuEntry menuEntry) {
|
||||
if (menuEntry.icon() != null) {
|
||||
return new SideNavItem(menuEntry.title(), menuEntry.path(), new Icon(menuEntry.icon()));
|
||||
} else {
|
||||
return new SideNavItem(menuEntry.title(), menuEntry.path());
|
||||
}
|
||||
}
|
||||
|
||||
private Component createUserMenu() {
|
||||
// TODO Replace with real user information and actions
|
||||
var avatar = new Avatar("John Smith");
|
||||
avatar.addThemeVariants(AvatarVariant.LUMO_XSMALL);
|
||||
avatar.addClassNames(Margin.Right.SMALL);
|
||||
avatar.setColorIndex(5);
|
||||
|
||||
var userMenu = new MenuBar();
|
||||
userMenu.addThemeVariants(MenuBarVariant.LUMO_TERTIARY_INLINE);
|
||||
userMenu.addClassNames(Margin.MEDIUM);
|
||||
|
||||
var userMenuItem = userMenu.addItem(avatar);
|
||||
userMenuItem.add("John Smith");
|
||||
userMenuItem.getSubMenu().addItem("View Profile").setEnabled(false);
|
||||
userMenuItem.getSubMenu().addItem("Manage Settings").setEnabled(false);
|
||||
userMenuItem.getSubMenu().addItem("Logout").setEnabled(false);
|
||||
|
||||
return userMenu;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package de.assecutor.emulatorstation.base.ui.view;
|
||||
|
||||
import de.assecutor.emulatorstation.base.ui.component.ViewToolbar;
|
||||
|
||||
import com.vaadin.flow.component.UI;
|
||||
import com.vaadin.flow.component.html.Div;
|
||||
import com.vaadin.flow.component.html.Main;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility;
|
||||
import jakarta.annotation.security.PermitAll;
|
||||
|
||||
/**
|
||||
* This view shows up when a user navigates to the root ('/') of the application.
|
||||
*/
|
||||
@Route
|
||||
@PermitAll // When security is enabled, allow all authenticated users
|
||||
public final class MainView extends Main {
|
||||
|
||||
// TODO Replace with your own main view.
|
||||
|
||||
MainView() {
|
||||
addClassName(LumoUtility.Padding.MEDIUM);
|
||||
add(new ViewToolbar("Main"));
|
||||
add(new Div("Please select a view from the menu on the left."));
|
||||
}
|
||||
|
||||
/**
|
||||
* Navigates to the main view.
|
||||
*/
|
||||
public static void showMainView() {
|
||||
UI.getCurrent().navigate(MainView.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* This package contains reusable or cross-cutting view-related classes.
|
||||
*/
|
||||
@NullMarked
|
||||
package de.assecutor.emulatorstation.base.ui.view;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
@@ -0,0 +1,61 @@
|
||||
package de.assecutor.emulatorstation.taskmanagement.domain;
|
||||
|
||||
import de.assecutor.emulatorstation.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 = "task")
|
||||
public class Task extends AbstractEntity<Long> {
|
||||
|
||||
public static final int DESCRIPTION_MAX_LENGTH = 255;
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "task_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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package de.assecutor.emulatorstation.taskmanagement.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 TaskRepository extends JpaRepository<Task, Long>, JpaSpecificationExecutor<Task> {
|
||||
|
||||
// If you don't need a total row count, Slice is better than Page.
|
||||
Slice<Task> findAllBy(Pageable pageable);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* This package contains the domain model of the Task Management sample feature.
|
||||
* <p>
|
||||
* You can add as many domain model artifacts (such as entities, value objects, repositories, domain events, and domain
|
||||
* services) to this package, as long as they belong to the same feature.
|
||||
* </p>
|
||||
* <p>
|
||||
* If you have domain classes that are re-usable across multiple features, add them to the {@code base.domain} package.
|
||||
* </p>
|
||||
*/
|
||||
@NullMarked
|
||||
package de.assecutor.emulatorstation.taskmanagement.domain;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* This is a feature package for the Task Management sample feature. Its purpose is to demonstrate how you typically
|
||||
* structure Vaadin business applications, and how the different building blocks interact.
|
||||
* <p>
|
||||
* A feature package represents a self-contained unit of functionality, including UI components, business logic, and
|
||||
* data access. It could be a subdomain or bounded context (e.g., "Billing"), a specific use case (e.g., "User
|
||||
* Registration"), or even a complex UI view (e.g., "Dashboard").
|
||||
* </p>
|
||||
* <p>
|
||||
* If your application is very small, you may not need dedicated feature packages. In that case, move the subpackages
|
||||
* directly to the application package.
|
||||
* </p>
|
||||
*/
|
||||
package de.assecutor.emulatorstation.taskmanagement;
|
||||
// TODO Remove this package once you have added real features
|
||||
@@ -0,0 +1,43 @@
|
||||
package de.assecutor.emulatorstation.taskmanagement.service;
|
||||
|
||||
import de.assecutor.emulatorstation.taskmanagement.domain.Task;
|
||||
import de.assecutor.emulatorstation.taskmanagement.domain.TaskRepository;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
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.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
public class TaskService {
|
||||
|
||||
private final TaskRepository taskRepository;
|
||||
|
||||
private final Clock clock;
|
||||
|
||||
TaskService(TaskRepository taskRepository, Clock clock) {
|
||||
this.taskRepository = taskRepository;
|
||||
this.clock = clock;
|
||||
}
|
||||
|
||||
public void createTask(String description, @Nullable LocalDate dueDate) {
|
||||
if ("fail".equals(description)) {
|
||||
throw new RuntimeException("This is for testing the error handler");
|
||||
}
|
||||
var task = new Task();
|
||||
task.setDescription(description);
|
||||
task.setCreationDate(clock.instant());
|
||||
task.setDueDate(dueDate);
|
||||
taskRepository.saveAndFlush(task);
|
||||
}
|
||||
|
||||
public List<Task> list(Pageable pageable) {
|
||||
return taskRepository.findAllBy(pageable).toList();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* This package contains the application services of the Task Management sample feature.
|
||||
* <p>
|
||||
* You can add as many application services as you want to this package, as long as they belong to the same feature. If
|
||||
* any of them use Data Transfer Objects (DTO), you can add them here as well.
|
||||
* </p>
|
||||
*/
|
||||
@NullMarked
|
||||
package de.assecutor.emulatorstation.taskmanagement.service;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
@@ -0,0 +1,85 @@
|
||||
package de.assecutor.emulatorstation.taskmanagement.ui.view;
|
||||
|
||||
import de.assecutor.emulatorstation.base.ui.component.ViewToolbar;
|
||||
import de.assecutor.emulatorstation.taskmanagement.domain.Task;
|
||||
import de.assecutor.emulatorstation.taskmanagement.service.TaskService;
|
||||
import com.vaadin.flow.component.button.Button;
|
||||
import com.vaadin.flow.component.button.ButtonVariant;
|
||||
import com.vaadin.flow.component.datepicker.DatePicker;
|
||||
import com.vaadin.flow.component.grid.Grid;
|
||||
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.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 jakarta.annotation.security.PermitAll;
|
||||
|
||||
import java.time.Clock;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.FormatStyle;
|
||||
import java.util.Optional;
|
||||
|
||||
import static com.vaadin.flow.spring.data.VaadinSpringDataHelpers.toSpringPageRequest;
|
||||
|
||||
@Route("task-list")
|
||||
@PageTitle("Task List")
|
||||
@Menu(order = 0, icon = "vaadin:clipboard-check", title = "Task List")
|
||||
@PermitAll // When security is enabled, allow all authenticated users
|
||||
public class TaskListView extends Main {
|
||||
|
||||
private final TaskService taskService;
|
||||
|
||||
final TextField description;
|
||||
final DatePicker dueDate;
|
||||
final Button createBtn;
|
||||
final Grid<Task> taskGrid;
|
||||
|
||||
public TaskListView(TaskService taskService, Clock clock) {
|
||||
this.taskService = taskService;
|
||||
|
||||
description = new TextField();
|
||||
description.setPlaceholder("What do you want to do?");
|
||||
description.setAriaLabel("Task description");
|
||||
description.setMaxLength(Task.DESCRIPTION_MAX_LENGTH);
|
||||
description.setMinWidth("20em");
|
||||
|
||||
dueDate = new DatePicker();
|
||||
dueDate.setPlaceholder("Due date");
|
||||
dueDate.setAriaLabel("Due date");
|
||||
|
||||
createBtn = new Button("Create", event -> createTask());
|
||||
createBtn.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
|
||||
|
||||
var dateTimeFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM).withZone(clock.getZone())
|
||||
.withLocale(getLocale());
|
||||
var dateFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM).withLocale(getLocale());
|
||||
|
||||
taskGrid = new Grid<>();
|
||||
taskGrid.setItems(query -> taskService.list(toSpringPageRequest(query)).stream());
|
||||
taskGrid.addColumn(Task::getDescription).setHeader("Description");
|
||||
taskGrid.addColumn(task -> Optional.ofNullable(task.getDueDate()).map(dateFormatter::format).orElse("Never"))
|
||||
.setHeader("Due Date");
|
||||
taskGrid.addColumn(task -> dateTimeFormatter.format(task.getCreationDate())).setHeader("Creation Date");
|
||||
taskGrid.setSizeFull();
|
||||
|
||||
setSizeFull();
|
||||
addClassNames(LumoUtility.BoxSizing.BORDER, LumoUtility.Display.FLEX, LumoUtility.FlexDirection.COLUMN,
|
||||
LumoUtility.Padding.MEDIUM, LumoUtility.Gap.SMALL);
|
||||
|
||||
add(new ViewToolbar("Task List", ViewToolbar.group(description, dueDate, createBtn)));
|
||||
add(taskGrid);
|
||||
}
|
||||
|
||||
private void createTask() {
|
||||
taskService.createTask(description.getValue(), dueDate.getValue());
|
||||
taskGrid.getDataProvider().refreshAll();
|
||||
description.clear();
|
||||
dueDate.clear();
|
||||
Notification.show("Task added", 3000, Notification.Position.BOTTOM_END)
|
||||
.addThemeVariants(NotificationVariant.LUMO_SUCCESS);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* This package contains the views of the Task Management sample feature.
|
||||
* <p>
|
||||
* You can add as many views as you want to this package, as long as they belong to the same feature.
|
||||
* </p>
|
||||
* <p>
|
||||
* For smaller UI-components, consider creating a separate {@code ui.component} package. If the components are re-usable
|
||||
* across multiple features, add them to the {@code base.ui.component} package.
|
||||
* </p>
|
||||
*/
|
||||
@NullMarked
|
||||
package de.assecutor.emulatorstation.taskmanagement.ui.view;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
14
src/main/resources/application.properties
Normal file
14
src/main/resources/application.properties
Normal file
@@ -0,0 +1,14 @@
|
||||
server.port=${PORT:8080}
|
||||
logging.level.org.atmosphere=warn
|
||||
|
||||
# Launch the default browser when starting the application in development mode
|
||||
vaadin.launch-browser=true
|
||||
# To improve the performance during development.
|
||||
# For more information https://vaadin.com/docs/latest/flow/integrations/spring/configuration#special-configuration-parameters
|
||||
vaadin.allowed-packages=com.vaadin,org.vaadin,com.flowingcode,de.assecutor.emulatorstation
|
||||
|
||||
# Open-in-view is only needed if you use lazy-loaded entities in your Flow views.
|
||||
spring.jpa.open-in-view=false
|
||||
|
||||
# Initialize the JPA Entity Manager before considering data.sql so that the EM can create the schema and data.sql contain data
|
||||
spring.jpa.defer-datasource-initialization = true
|
||||
Reference in New Issue
Block a user