diff --git a/.gitignore b/.gitignore
index 98f3619..d7dcf6f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,15 +1,6 @@
-# Compiled class file
-*.class
-
# Log file
*.log
-# BlueJ files
-*.ctxt
-
-# Mobile Tools for Java (J2ME)
-.mtj.tmp/
-
# Package Files #
*.jar
*.war
diff --git a/pom.xml b/pom.xml
index 225d154..e716569 100644
--- a/pom.xml
+++ b/pom.xml
@@ -46,11 +46,6 @@
org.liquibase
liquibase-core
-
- org.liquibase
- liquibase-maven-plugin
- 3.5.3
-
mysql
@@ -63,6 +58,12 @@
test
+
+ com.github.javafaker
+ javafaker
+ 0.15
+
+
org.webjars
bootstrap
@@ -80,7 +81,7 @@
org.liquibase
liquibase-maven-plugin
- 3.5.3
+ 3.6.2
src/main/resources/liquibase.properties
diff --git a/src/main/java/com/github/prominence/carrepair/CarRepairApplication.java b/src/main/java/com/github/prominence/carrepair/CarRepairApplication.java
index f0394bf..52296f1 100644
--- a/src/main/java/com/github/prominence/carrepair/CarRepairApplication.java
+++ b/src/main/java/com/github/prominence/carrepair/CarRepairApplication.java
@@ -10,8 +10,10 @@ import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
@SpringBootApplication
public class CarRepairApplication {
- public static void main(String[] args) {
- SpringApplication.run(CarRepairApplication.class, args);
- }
+ public static void main(String[] args) {
+ SpringApplication.run(CarRepairApplication.class, args);
+ }
-}
\ No newline at end of file
+}
+// TODO: logging
+// TODO: DTO
\ No newline at end of file
diff --git a/src/main/java/com/github/prominence/carrepair/controller/ClientController.java b/src/main/java/com/github/prominence/carrepair/controller/ClientController.java
index 34c5489..74ca59a 100644
--- a/src/main/java/com/github/prominence/carrepair/controller/ClientController.java
+++ b/src/main/java/com/github/prominence/carrepair/controller/ClientController.java
@@ -1,16 +1,87 @@
package com.github.prominence.carrepair.controller;
+import com.github.prominence.carrepair.model.Client;
+import com.github.prominence.carrepair.service.ClientService;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
-import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.ui.ModelMap;
+import org.springframework.validation.BindingResult;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+import java.util.Optional;
@Controller
@RequestMapping("/client")
public class ClientController {
- @RequestMapping
- public String index(Model model) {
+ private ClientService clientService;
+
+ public ClientController(ClientService clientService) {
+ this.clientService = clientService;
+ }
+
+ @GetMapping
+ public String index(ModelMap modelMap) {
+ Page clientList = clientService.findAll((Pageable) modelMap.get("pagination"));
+
+ modelMap.addAttribute("clientList", clientList.getContent());
+ modelMap.addAttribute("totalPages", clientList.getTotalPages());
return "client/index";
}
+
+ @GetMapping(value = "/create")
+ public String create(Model model) {
+ model.addAttribute("client", new Client());
+
+ return "client/edit";
+ }
+
+ @GetMapping(value = "/edit/{id}")
+ public String edit(@PathVariable Long id, Model model) {
+ Optional clientOptional = clientService.findById(id);
+ if (clientOptional.isPresent()) {
+ model.addAttribute("client", clientOptional.get());
+ return "client/edit";
+ } else {
+ // TODO: need to show warning
+ return "redirect:/client";
+ }
+ }
+
+ @PostMapping(value = "/update/{id}")
+ public String update(@Valid Client client, BindingResult bindingResult, @PathVariable long id) {
+ if (bindingResult.hasErrors()) {
+ client.setId(id); // why should we do this?
+ return "client/edit";
+ }
+
+ clientService.save(client);
+ return "redirect:/client";
+ }
+
+ @PostMapping(value = "/create")
+ public String save(@Valid Client client, BindingResult bindingResult) {
+ if (bindingResult.hasErrors()) {
+ return "client/edit";
+ }
+
+ clientService.save(client);
+ return "redirect:/client";
+ }
+
+ @DeleteMapping(value = "/delete/{id}")
+ public ResponseEntity delete(@PathVariable Long id) {
+ boolean deleteSuccess = clientService.deleteClientById(id);
+
+ if (deleteSuccess) {
+ return ResponseEntity.ok().build();
+ } else {
+ return ResponseEntity.notFound().build();
+ }
+ }
}
diff --git a/src/main/java/com/github/prominence/carrepair/controller/advice/PaginationAdvice.java b/src/main/java/com/github/prominence/carrepair/controller/advice/PaginationAdvice.java
new file mode 100644
index 0000000..5d9d482
--- /dev/null
+++ b/src/main/java/com/github/prominence/carrepair/controller/advice/PaginationAdvice.java
@@ -0,0 +1,24 @@
+package com.github.prominence.carrepair.controller.advice;
+
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ModelAttribute;
+import org.springframework.web.bind.annotation.RequestParam;
+
+@ControllerAdvice
+public class PaginationAdvice {
+
+ private static final int DEFAULT_PAGE_SIZE = 10;
+
+ @ModelAttribute("pagination")
+ public void addPagination(@RequestParam(required = false) Integer size, @RequestParam(required = false) Integer page, Model model) {
+ final int pageValue = page == null ? 0 : page;
+ final int sizeValue = size == null ? DEFAULT_PAGE_SIZE : size;
+ Pageable pagination = PageRequest.of(pageValue, sizeValue);
+
+ model.addAttribute("pagination", pagination);
+ model.addAttribute("page", pageValue);
+ }
+}
diff --git a/src/main/java/com/github/prominence/carrepair/demo/DemoDataPopulator.java b/src/main/java/com/github/prominence/carrepair/demo/DemoDataPopulator.java
new file mode 100644
index 0000000..21febfe
--- /dev/null
+++ b/src/main/java/com/github/prominence/carrepair/demo/DemoDataPopulator.java
@@ -0,0 +1,37 @@
+package com.github.prominence.carrepair.demo;
+
+import com.github.javafaker.Faker;
+import com.github.prominence.carrepair.model.Client;
+import com.github.prominence.carrepair.repository.ClientRepository;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.context.annotation.Bean;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+@Component
+public class DemoDataPopulator {
+ private static final int COUNT = 10;
+
+ @Bean
+ public CommandLineRunner demoData(ClientRepository clientRepository) {
+ Faker faker = new Faker();
+
+ List demoClientList = Stream.generate(() -> {
+ Client client = new Client();
+ client.setFirstName(faker.name().firstName());
+ client.setLastName(faker.name().lastName());
+ client.setMiddleName(faker.name().username());
+ client.setPhoneNo(faker.phoneNumber().phoneNumber());
+ System.out.println(client); // demo output
+ return client;
+ }).limit(COUNT).collect(Collectors.toList());
+
+ return args -> {
+ demoClientList.forEach(clientRepository::save);
+ };
+ }
+
+}
diff --git a/src/main/java/com/github/prominence/carrepair/model/Client.java b/src/main/java/com/github/prominence/carrepair/model/Client.java
index b146499..95ad174 100644
--- a/src/main/java/com/github/prominence/carrepair/model/Client.java
+++ b/src/main/java/com/github/prominence/carrepair/model/Client.java
@@ -3,11 +3,14 @@ package com.github.prominence.carrepair.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
+import javax.validation.constraints.Size;
+import java.util.Objects;
@Entity
@Table(name = "client")
public class Client extends Person {
+ @Size(max = 32)
@Column(name = "phoneNo")
private String phoneNo;
@@ -26,4 +29,29 @@ public class Client extends Person {
public void setPhoneNo(String phoneNo) {
this.phoneNo = phoneNo;
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof Client)) return false;
+ if (!super.equals(o)) return false;
+ Client client = (Client) o;
+ return Objects.equals(phoneNo, client.phoneNo);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(super.hashCode(), phoneNo);
+ }
+
+ @Override
+ public String toString() {
+ return "Client{" +
+ "id=" + id +
+ ", firstName='" + firstName + '\'' +
+ ", middleName='" + middleName + '\'' +
+ ", lastName='" + lastName + '\'' +
+ ", phoneNo='" + phoneNo + '\'' +
+ '}';
+ }
}
diff --git a/src/main/java/com/github/prominence/carrepair/model/Person.java b/src/main/java/com/github/prominence/carrepair/model/Person.java
index 28924d3..d877caa 100644
--- a/src/main/java/com/github/prominence/carrepair/model/Person.java
+++ b/src/main/java/com/github/prominence/carrepair/model/Person.java
@@ -2,24 +2,29 @@ package com.github.prominence.carrepair.model;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import java.util.Objects;
@MappedSuperclass
abstract public class Person {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
- private long id;
+ protected long id;
@NotNull
+ @Size(max = 64)
@Column(name = "firstName")
- private String firstName;
+ protected String firstName;
+ @Size(max = 64)
@Column(name = "middleName")
- private String middleName;
+ protected String middleName;
@NotNull
+ @Size(max = 64)
@Column(name = "lastName")
- private String lastName;
+ protected String lastName;
public Person(String firstName, String middleName, String lastName) {
this.firstName = firstName;
@@ -61,4 +66,20 @@ abstract public class Person {
public void setLastName(String lastName) {
this.lastName = lastName;
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof Person)) return false;
+ Person person = (Person) o;
+ return id == person.id &&
+ Objects.equals(firstName, person.firstName) &&
+ Objects.equals(middleName, person.middleName) &&
+ Objects.equals(lastName, person.lastName);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id, firstName, middleName, lastName);
+ }
}
diff --git a/src/main/java/com/github/prominence/carrepair/service/ClientService.java b/src/main/java/com/github/prominence/carrepair/service/ClientService.java
new file mode 100644
index 0000000..6fa19b9
--- /dev/null
+++ b/src/main/java/com/github/prominence/carrepair/service/ClientService.java
@@ -0,0 +1,40 @@
+package com.github.prominence.carrepair.service;
+
+import com.github.prominence.carrepair.model.Client;
+import com.github.prominence.carrepair.repository.ClientRepository;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.stereotype.Service;
+
+import java.util.Optional;
+
+@Service
+public class ClientService {
+
+ private ClientRepository clientRepository;
+
+ public ClientService(ClientRepository clientRepository) {
+ this.clientRepository = clientRepository;
+ }
+
+ public Page findAll(Pageable pageable) {
+ return clientRepository.findAll(pageable);
+ }
+
+ public Optional findById(Long id) {
+ return clientRepository.findById(id);
+ }
+
+ public Client save(Client client) {
+ return clientRepository.save(client);
+ }
+
+ public boolean deleteClientById(Long id) {
+ try {
+ clientRepository.deleteById(id);
+ return true;
+ } catch (Exception e) {
+ return false;
+ }
+ }
+}
diff --git a/src/main/resources/static/css/main.css b/src/main/resources/static/css/main.css
index 47e1dc8..01e225a 100644
--- a/src/main/resources/static/css/main.css
+++ b/src/main/resources/static/css/main.css
@@ -1,2 +1,6 @@
body {
+}
+
+.fieldError {
+ border: 1px solid red;
}
\ No newline at end of file
diff --git a/src/main/resources/templates/client/edit.html b/src/main/resources/templates/client/edit.html
new file mode 100644
index 0000000..7a32bf9
--- /dev/null
+++ b/src/main/resources/templates/client/edit.html
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/resources/templates/client/index.html b/src/main/resources/templates/client/index.html
index f6deaf3..2c61b0f 100644
--- a/src/main/resources/templates/client/index.html
+++ b/src/main/resources/templates/client/index.html
@@ -3,11 +3,58 @@
layout:decorate="~{main}">
+
+
+
+
+
+
+
+ | First Name |
+ Middle Name |
+ Last Name |
+ Phone No |
+ |
+
+
+
+
+ |
+ |
+ |
+ |
+
+
+ |
+
+
+
+
diff --git a/src/main/resources/templates/common.html b/src/main/resources/templates/common.html
new file mode 100644
index 0000000..bfbe2b3
--- /dev/null
+++ b/src/main/resources/templates/common.html
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/resources/templates/main.html b/src/main/resources/templates/main.html
index bf6257d..60494c1 100644
--- a/src/main/resources/templates/main.html
+++ b/src/main/resources/templates/main.html
@@ -51,6 +51,7 @@
+