From 32a2f0a5a269a2724f669516303c35982c59a4b0 Mon Sep 17 00:00:00 2001 From: AliKaraman Date: Sat, 2 Oct 2021 12:08:39 +0000 Subject: [PATCH] injected --- .vscode/settings.json | 3 + pnpm-lock.yaml | 4 +- pom.xml | 78 +++++++ .../org/vaadin/example/AbstractEntity.java | 42 ++++ .../java/org/vaadin/example/Application.java | 1 - .../org/vaadin/example/DataGenerator.java | 46 ++++ .../java/org/vaadin/example/MainView.java | 11 +- .../org/vaadin/example/MasterDetailView.java | 216 ++++++++++++++++++ .../java/org/vaadin/example/SamplePerson.java | 61 +++++ .../example/SamplePersonRepository.java | 10 + .../vaadin/example/SamplePersonService.java | 24 ++ 11 files changed, 493 insertions(+), 3 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 src/main/java/org/vaadin/example/AbstractEntity.java create mode 100644 src/main/java/org/vaadin/example/DataGenerator.java create mode 100644 src/main/java/org/vaadin/example/MasterDetailView.java create mode 100644 src/main/java/org/vaadin/example/SamplePerson.java create mode 100644 src/main/java/org/vaadin/example/SamplePersonRepository.java create mode 100644 src/main/java/org/vaadin/example/SamplePersonService.java diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..c5f3f6b9 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "java.configuration.updateBuildConfiguration": "interactive" +} \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f5db5ec9..3d7d8427 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2199,7 +2199,7 @@ packages: resolution: integrity: sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= /core-js/2.6.11: - deprecated: 'core-js@<3 is no longer maintained and not recommended for usage due to the number of issues. Please, upgrade your dependencies to the actual version of core-js@3.' + deprecated: 'core-js@<3.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Please, upgrade your dependencies to the actual version of core-js.' dev: true requiresBuild: true resolution: @@ -4881,6 +4881,7 @@ packages: resolution: integrity: sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM= /querystring/0.2.0: + deprecated: The querystring API is considered Legacy. new code should use the URLSearchParams API instead. dev: true engines: node: '>=0.4.x' @@ -5910,6 +5911,7 @@ packages: resolution: integrity: sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= /uuid/3.4.0: + deprecated: 'Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.' dev: true hasBin: true resolution: diff --git a/pom.xml b/pom.xml index e05b375d..4a41e15a 100644 --- a/pom.xml +++ b/pom.xml @@ -69,21 +69,99 @@ com.vaadin vaadin + + + + com.vaadin.webjar + * + + + org.webjars.bowergithub.insites + * + + + org.webjars.bowergithub.polymer + * + + + org.webjars.bowergithub.polymerelements + * + + + org.webjars.bowergithub.vaadin + * + + + org.webjars.bowergithub.webcomponents + * + + com.vaadin vaadin-spring-boot-starter + + + + com.vaadin + vaadin-core + + + + org.vaadin.artur + a-vaadin-helper + 1.7.1 + + + + com.vaadin + exampledata + 4.0.0 + + + + com.h2database + h2 + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + + org.springframework.boot + spring-boot-starter-validation + + org.springframework.boot spring-boot-devtools true + + org.springframework.boot + spring-boot-starter-test + test + com.vaadin vaadin-testbench test + + + org.junit.vintage + junit-vintage-engine + test + + + org.hamcrest + hamcrest-core + + + io.github.bonigarcia webdrivermanager diff --git a/src/main/java/org/vaadin/example/AbstractEntity.java b/src/main/java/org/vaadin/example/AbstractEntity.java new file mode 100644 index 00000000..66fcc481 --- /dev/null +++ b/src/main/java/org/vaadin/example/AbstractEntity.java @@ -0,0 +1,42 @@ +package org.vaadin.example; + +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.MappedSuperclass; + +@MappedSuperclass +public abstract class AbstractEntity { + + @Id + @GeneratedValue + private Integer id; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + @Override + public int hashCode() { + if (id != null) { + return id.hashCode(); + } + return super.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof AbstractEntity)) { + return false; // null or other class + } + AbstractEntity other = (AbstractEntity) obj; + + if (id != null) { + return id.equals(other.id); + } + return super.equals(other); + } +} diff --git a/src/main/java/org/vaadin/example/Application.java b/src/main/java/org/vaadin/example/Application.java index 40f995c9..34eae9ef 100644 --- a/src/main/java/org/vaadin/example/Application.java +++ b/src/main/java/org/vaadin/example/Application.java @@ -6,7 +6,6 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; - /** * The entry point of the Spring Boot application. * diff --git a/src/main/java/org/vaadin/example/DataGenerator.java b/src/main/java/org/vaadin/example/DataGenerator.java new file mode 100644 index 00000000..410e47fa --- /dev/null +++ b/src/main/java/org/vaadin/example/DataGenerator.java @@ -0,0 +1,46 @@ +package org.vaadin.example; +import com.vaadin.flow.spring.annotation.SpringComponent; + + +import java.time.LocalDateTime; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.CommandLineRunner; +import org.springframework.context.annotation.Bean; +import com.vaadin.exampledata.DataType; +import com.vaadin.exampledata.ExampleDataGenerator; + +@SpringComponent +public class DataGenerator { + + @Bean + public CommandLineRunner loadData(SamplePersonRepository samplePersonRepository) { + return args -> { + Logger logger = LoggerFactory.getLogger(getClass()); + if (samplePersonRepository.count() != 0L) { + logger.info("Using existing database"); + return; + } + int seed = 123; + + logger.info("Generating demo data"); + + logger.info("... generating 100 Sample Person entities..."); + ExampleDataGenerator samplePersonRepositoryGenerator = new ExampleDataGenerator<>( + SamplePerson.class, LocalDateTime.of(2021, 10, 2, 0, 0, 0)); + samplePersonRepositoryGenerator.setData(SamplePerson::setId, DataType.ID); + samplePersonRepositoryGenerator.setData(SamplePerson::setFirstName, DataType.FIRST_NAME); + samplePersonRepositoryGenerator.setData(SamplePerson::setLastName, DataType.LAST_NAME); + samplePersonRepositoryGenerator.setData(SamplePerson::setEmail, DataType.EMAIL); + samplePersonRepositoryGenerator.setData(SamplePerson::setPhone, DataType.PHONE_NUMBER); + samplePersonRepositoryGenerator.setData(SamplePerson::setDateOfBirth, DataType.DATE_OF_BIRTH); + samplePersonRepositoryGenerator.setData(SamplePerson::setOccupation, DataType.OCCUPATION); + samplePersonRepositoryGenerator.setData(SamplePerson::setImportant, DataType.BOOLEAN_10_90); + samplePersonRepository.saveAll(samplePersonRepositoryGenerator.create(100, seed)); + + logger.info("Generated demo data"); + }; + } + +} \ No newline at end of file diff --git a/src/main/java/org/vaadin/example/MainView.java b/src/main/java/org/vaadin/example/MainView.java index c5ff678d..eeecaae7 100644 --- a/src/main/java/org/vaadin/example/MainView.java +++ b/src/main/java/org/vaadin/example/MainView.java @@ -5,7 +5,9 @@ import com.vaadin.flow.component.Key; import com.vaadin.flow.component.button.Button; import com.vaadin.flow.component.button.ButtonVariant; +import com.vaadin.flow.component.charts.model.Navigator; import com.vaadin.flow.component.dependency.CssImport; +import com.vaadin.flow.component.html.Div; import com.vaadin.flow.component.notification.Notification; import com.vaadin.flow.component.orderedlayout.VerticalLayout; import com.vaadin.flow.component.textfield.TextField; @@ -28,6 +30,7 @@ @CssImport(value = "./styles/vaadin-text-field-styles.css", themeFor = "vaadin-text-field") public class MainView extends VerticalLayout { + /** * Construct a new Vaadin view. *

@@ -37,7 +40,8 @@ public class MainView extends VerticalLayout { * The message service. Automatically injected Spring managed * bean. */ - public MainView(@Autowired GreetService service) { + + public MainView(@Autowired GreetService service, @Autowired MasterDetailView masterDetailView) { // Use TextField for standard text input TextField textField = new TextField("Your name"); @@ -60,6 +64,11 @@ public MainView(@Autowired GreetService service) { addClassName("centered-content"); add(textField, button); + //MasterDetailView masterDetailView = new MasterDetailView(null); + //add( masterDetailView ); + + add(masterDetailView); + } } diff --git a/src/main/java/org/vaadin/example/MasterDetailView.java b/src/main/java/org/vaadin/example/MasterDetailView.java new file mode 100644 index 00000000..b84894ad --- /dev/null +++ b/src/main/java/org/vaadin/example/MasterDetailView.java @@ -0,0 +1,216 @@ +package org.vaadin.example; +import java.util.Optional; + + +import com.vaadin.flow.component.Component; +import com.vaadin.flow.component.HasStyle; +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.formlayout.FormLayout; +import com.vaadin.flow.component.grid.Grid; +import com.vaadin.flow.component.grid.GridVariant; +import com.vaadin.flow.component.html.Div; +import com.vaadin.flow.component.notification.Notification; +import com.vaadin.flow.component.orderedlayout.HorizontalLayout; +import com.vaadin.flow.component.splitlayout.SplitLayout; +import com.vaadin.flow.data.binder.BeanValidationBinder; +import com.vaadin.flow.data.binder.ValidationException; +import com.vaadin.flow.router.BeforeEnterEvent; +import com.vaadin.flow.router.BeforeEnterObserver; + +import org.springframework.beans.factory.annotation.Autowired; +import org.vaadin.artur.helpers.CrudServiceDataProvider; +import com.vaadin.flow.router.Route; +import com.vaadin.flow.spring.annotation.SpringComponent; +import com.vaadin.flow.spring.annotation.UIScope; +import com.vaadin.flow.router.PageTitle; + +import com.vaadin.flow.component.dependency.Uses; +import com.vaadin.flow.data.renderer.TemplateRenderer; +import com.vaadin.flow.component.icon.Icon; +import com.vaadin.flow.component.datepicker.DatePicker; +import com.vaadin.flow.component.textfield.TextField; +import com.vaadin.flow.component.checkbox.Checkbox; + +@PageTitle("Master-Detail") +@Route(value = "master-detail/:samplePersonID?/:action?(edit)"/*, layout = MainLayout.class*/) +@Uses(Icon.class) + +@SpringComponent(value = "masterDetail") +@UIScope +public class MasterDetailView extends Div implements BeforeEnterObserver { + + private final String SAMPLEPERSON_ID = "samplePersonID"; + private final String SAMPLEPERSON_EDIT_ROUTE_TEMPLATE = "master-detail/%d/edit"; + + private Grid grid = new Grid<>(SamplePerson.class, false); + + private TextField firstName; + private TextField lastName; + private TextField email; + private TextField phone; + private DatePicker dateOfBirth; + private TextField occupation; + private Checkbox important; + + private Button cancel = new Button("Cancel"); + private Button save = new Button("Save"); + + private BeanValidationBinder binder; + + private SamplePerson samplePerson; + + private SamplePersonService samplePersonService; + + public MasterDetailView(@Autowired SamplePersonService samplePersonService) { + this.samplePersonService = samplePersonService; + addClassNames("master-detail-view", "flex", "flex-col", "h-full"); + // Create UI + SplitLayout splitLayout = new SplitLayout(); + splitLayout.setSizeFull(); + + createGridLayout(splitLayout); + createEditorLayout(splitLayout); + + add(splitLayout); + + // Configure Grid + grid.addColumn("firstName").setAutoWidth(true); + grid.addColumn("lastName").setAutoWidth(true); + grid.addColumn("email").setAutoWidth(true); + grid.addColumn("phone").setAutoWidth(true); + grid.addColumn("dateOfBirth").setAutoWidth(true); + grid.addColumn("occupation").setAutoWidth(true); + TemplateRenderer importantRenderer = TemplateRenderer.of( + "") + .withProperty("important", SamplePerson::isImportant); + grid.addColumn(importantRenderer).setHeader("Important").setAutoWidth(true); + + grid.setDataProvider(new CrudServiceDataProvider<>(samplePersonService)); + grid.addThemeVariants(GridVariant.LUMO_NO_BORDER); + grid.setHeightFull(); + + // when a row is selected or deselected, populate form + grid.asSingleSelect().addValueChangeListener(event -> { + if (event.getValue() != null) { + UI.getCurrent().navigate(String.format(SAMPLEPERSON_EDIT_ROUTE_TEMPLATE, event.getValue().getId())); + } else { + clearForm(); + UI.getCurrent().navigate(MasterDetailView.class); + } + }); + + // Configure Form + binder = new BeanValidationBinder<>(SamplePerson.class); + + // Bind fields. This where you'd define e.g. validation rules + + binder.bindInstanceFields(this); + + cancel.addClickListener(e -> { + clearForm(); + refreshGrid(); + }); + + save.addClickListener(e -> { + try { + if (this.samplePerson == null) { + this.samplePerson = new SamplePerson(); + } + binder.writeBean(this.samplePerson); + + samplePersonService.update(this.samplePerson); + clearForm(); + refreshGrid(); + Notification.show("SamplePerson details stored."); + UI.getCurrent().navigate(MasterDetailView.class); + } catch (ValidationException validationException) { + Notification.show("An exception happened while trying to store the samplePerson details."); + } + }); + + } + + @Override + public void beforeEnter(BeforeEnterEvent event) { + Optional samplePersonId = event.getRouteParameters().getInteger(SAMPLEPERSON_ID); + if (samplePersonId.isPresent()) { + Optional samplePersonFromBackend = samplePersonService.get(samplePersonId.get()); + if (samplePersonFromBackend.isPresent()) { + populateForm(samplePersonFromBackend.get()); + } else { + Notification.show( + String.format("The requested samplePerson was not found, ID = %d", samplePersonId.get()), 3000, + Notification.Position.BOTTOM_START); + // when a row is selected but the data is no longer available, + // refresh grid + refreshGrid(); + event.forwardTo(MasterDetailView.class); + } + } + } + + private void createEditorLayout(SplitLayout splitLayout) { + Div editorLayoutDiv = new Div(); + editorLayoutDiv.setClassName("flex flex-col"); + editorLayoutDiv.setWidth("400px"); + + Div editorDiv = new Div(); + editorDiv.setClassName("p-l flex-grow"); + editorLayoutDiv.add(editorDiv); + + FormLayout formLayout = new FormLayout(); + firstName = new TextField("First Name"); + lastName = new TextField("Last Name"); + email = new TextField("Email"); + phone = new TextField("Phone"); + dateOfBirth = new DatePicker("Date Of Birth"); + occupation = new TextField("Occupation"); + important = new Checkbox("Important"); + important.getStyle().set("padding-top", "var(--lumo-space-m)"); + Component[] fields = new Component[]{firstName, lastName, email, phone, dateOfBirth, occupation, important}; + + for (Component field : fields) { + ((HasStyle) field).addClassName("full-width"); + } + formLayout.add(fields); + editorDiv.add(formLayout); + createButtonLayout(editorLayoutDiv); + + splitLayout.addToSecondary(editorLayoutDiv); + } + + private void createButtonLayout(Div editorLayoutDiv) { + HorizontalLayout buttonLayout = new HorizontalLayout(); + buttonLayout.setClassName("w-full flex-wrap bg-contrast-5 py-s px-l"); + buttonLayout.setSpacing(true); + cancel.addThemeVariants(ButtonVariant.LUMO_TERTIARY); + save.addThemeVariants(ButtonVariant.LUMO_PRIMARY); + buttonLayout.add(save, cancel); + editorLayoutDiv.add(buttonLayout); + } + + private void createGridLayout(SplitLayout splitLayout) { + Div wrapper = new Div(); + wrapper.setId("grid-wrapper"); + wrapper.setWidthFull(); + splitLayout.addToPrimary(wrapper); + wrapper.add(grid); + } + + private void refreshGrid() { + grid.select(null); + grid.getDataProvider().refreshAll(); + } + + private void clearForm() { + populateForm(null); + } + + private void populateForm(SamplePerson value) { + this.samplePerson = value; + binder.readBean(this.samplePerson); + + } +} diff --git a/src/main/java/org/vaadin/example/SamplePerson.java b/src/main/java/org/vaadin/example/SamplePerson.java new file mode 100644 index 00000000..834782c3 --- /dev/null +++ b/src/main/java/org/vaadin/example/SamplePerson.java @@ -0,0 +1,61 @@ +package org.vaadin.example; + +import javax.persistence.Entity; + +import java.time.LocalDate; + +@Entity +public class SamplePerson extends AbstractEntity { + + private String firstName; + private String lastName; + private String email; + private String phone; + private LocalDate dateOfBirth; + private String occupation; + private boolean important; + + public String getFirstName() { + return firstName; + } + public void setFirstName(String firstName) { + this.firstName = firstName; + } + public String getLastName() { + return lastName; + } + public void setLastName(String lastName) { + this.lastName = lastName; + } + public String getEmail() { + return email; + } + public void setEmail(String email) { + this.email = email; + } + public String getPhone() { + return phone; + } + public void setPhone(String phone) { + this.phone = phone; + } + public LocalDate getDateOfBirth() { + return dateOfBirth; + } + public void setDateOfBirth(LocalDate dateOfBirth) { + this.dateOfBirth = dateOfBirth; + } + public String getOccupation() { + return occupation; + } + public void setOccupation(String occupation) { + this.occupation = occupation; + } + public boolean isImportant() { + return important; + } + public void setImportant(boolean important) { + this.important = important; + } + +} diff --git a/src/main/java/org/vaadin/example/SamplePersonRepository.java b/src/main/java/org/vaadin/example/SamplePersonRepository.java new file mode 100644 index 00000000..78f067fd --- /dev/null +++ b/src/main/java/org/vaadin/example/SamplePersonRepository.java @@ -0,0 +1,10 @@ +package org.vaadin.example; + + + +import org.springframework.data.jpa.repository.JpaRepository; +import java.time.LocalDate; + +public interface SamplePersonRepository extends JpaRepository { + +} \ No newline at end of file diff --git a/src/main/java/org/vaadin/example/SamplePersonService.java b/src/main/java/org/vaadin/example/SamplePersonService.java new file mode 100644 index 00000000..31f3d89e --- /dev/null +++ b/src/main/java/org/vaadin/example/SamplePersonService.java @@ -0,0 +1,24 @@ +package org.vaadin.example; + + + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.vaadin.artur.helpers.CrudService; + + +@Service +public class SamplePersonService extends CrudService { + + private SamplePersonRepository repository; + + public SamplePersonService(@Autowired SamplePersonRepository repository) { + this.repository = repository; + } + + @Override + protected SamplePersonRepository getRepository() { + return repository; + } + +} \ No newline at end of file