├── Answers └── .gitkeep ├── Chapter01 ├── .gitignore ├── .mvn │ └── wrapper │ │ ├── MavenWrapperDownloader.java │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── mvnw ├── mvnw.cmd ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── packt │ │ │ └── cardatabase │ │ │ └── CardatabaseApplication.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── packt │ └── cardatabase │ └── CardatabaseApplicationTests.java ├── Chapter02 └── Readme.md ├── Chapter03 ├── .gitignore ├── .mvn │ └── wrapper │ │ ├── MavenWrapperDownloader.java │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── mvnw ├── mvnw.cmd ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── packt │ │ │ └── cardatabase │ │ │ ├── CardatabaseApplication.java │ │ │ └── domain │ │ │ ├── Car.java │ │ │ ├── CarRepository.java │ │ │ ├── Owner.java │ │ │ └── OwnerRepository.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── packt │ └── cardatabase │ └── CardatabaseApplicationTests.java ├── Chapter04 ├── .gitignore ├── .mvn │ └── wrapper │ │ ├── MavenWrapperDownloader.java │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── mvnw ├── mvnw.cmd ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── packt │ │ │ └── cardatabase │ │ │ ├── CardatabaseApplication.java │ │ │ ├── domain │ │ │ ├── Car.java │ │ │ ├── CarRepository.java │ │ │ ├── Owner.java │ │ │ └── OwnerRepository.java │ │ │ └── web │ │ │ └── CarController.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── packt │ └── cardatabase │ └── CardatabaseApplicationTests.java ├── Chapter05 ├── .gitignore ├── .mvn │ └── wrapper │ │ ├── MavenWrapperDownloader.java │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── README.md ├── mvnw ├── mvnw.cmd ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── packt │ │ │ └── cardatabase │ │ │ ├── AuthEntryPoint.java │ │ │ ├── AuthenticationFilter.java │ │ │ ├── CardatabaseApplication.java │ │ │ ├── SecurityConfig.java │ │ │ ├── domain │ │ │ ├── AccountCredentials.java │ │ │ ├── Car.java │ │ │ ├── CarRepository.java │ │ │ ├── Owner.java │ │ │ ├── OwnerRepository.java │ │ │ ├── User.java │ │ │ └── UserRepository.java │ │ │ ├── service │ │ │ ├── JwtService.java │ │ │ └── UserDetailsServiceImpl.java │ │ │ └── web │ │ │ ├── CarController.java │ │ │ └── LoginController.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── packt │ └── cardatabase │ ├── CarRestTest.java │ ├── CardatabaseApplicationTests.java │ └── OwnerRepositoryTest.java ├── Chapter06 └── Readme.md ├── Chapter07 ├── MyForm │ ├── .gitignore │ ├── README.md │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── logo192.png │ │ ├── logo512.png │ │ ├── manifest.json │ │ └── robots.txt │ └── src │ │ ├── App.css │ │ ├── App.js │ │ ├── App.test.js │ │ ├── MyForm.js │ │ ├── index.css │ │ ├── index.js │ │ ├── logo.svg │ │ ├── reportWebVitals.js │ │ └── setupTests.js ├── MyList │ ├── .gitignore │ ├── README.md │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── logo192.png │ │ ├── logo512.png │ │ ├── manifest.json │ │ └── robots.txt │ └── src │ │ ├── App.css │ │ ├── App.js │ │ ├── App.test.js │ │ ├── MyList.js │ │ ├── index.css │ │ ├── index.js │ │ ├── logo.svg │ │ ├── reportWebVitals.js │ │ └── setupTests.js └── MyTable │ ├── .gitignore │ ├── README.md │ ├── package.json │ ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt │ └── src │ ├── App.css │ ├── App.js │ ├── App.test.js │ ├── MyTable.js │ ├── index.css │ ├── index.js │ ├── logo.svg │ ├── reportWebVitals.js │ └── setupTests.js ├── Chapter08 ├── restgithub │ ├── .gitignore │ ├── README.md │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── logo192.png │ │ ├── logo512.png │ │ ├── manifest.json │ │ └── robots.txt │ └── src │ │ ├── App.css │ │ ├── App.js │ │ ├── App.test.js │ │ ├── index.css │ │ ├── index.js │ │ ├── logo.svg │ │ ├── reportWebVitals.js │ │ └── setupTests.js └── weatherapp │ ├── .gitignore │ ├── README.md │ ├── package.json │ ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt │ └── src │ ├── App.css │ ├── App.js │ ├── App.test.js │ ├── index.css │ ├── index.js │ ├── logo.svg │ ├── reportWebVitals.js │ └── setupTests.js ├── Chapter09 └── shoppinglist │ ├── .gitignore │ ├── README.md │ ├── package.json │ ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt │ └── src │ ├── AddItem.js │ ├── App.css │ ├── App.js │ ├── App.test.js │ ├── index.css │ ├── index.js │ ├── logo.svg │ ├── reportWebVitals.js │ └── setupTests.js ├── Chapter10 ├── .gitignore ├── README.md ├── package.json ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt └── src │ ├── App.css │ ├── App.js │ ├── App.test.js │ ├── index.css │ ├── index.js │ ├── logo.svg │ ├── reportWebVitals.js │ └── setupTests.js ├── Chapter11 ├── .gitignore ├── README.md ├── package.json ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt └── src │ ├── App.css │ ├── App.js │ ├── App.test.js │ ├── components │ ├── AddCar.js │ ├── Carlist.js │ └── EditCar.js │ ├── constants.js │ ├── index.css │ ├── index.js │ ├── logo.svg │ ├── reportWebVitals.js │ └── setupTests.js ├── Chapter12 ├── .gitignore ├── README.md ├── package.json ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt └── src │ ├── App.css │ ├── App.js │ ├── App.test.js │ ├── components │ ├── AddCar.js │ ├── Carlist.js │ └── EditCar.js │ ├── constants.js │ ├── index.css │ ├── index.js │ ├── logo.svg │ ├── reportWebVitals.js │ └── setupTests.js ├── Chapter13 ├── .gitignore ├── README.md ├── package.json ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt └── src │ ├── App.css │ ├── App.js │ ├── App.test.js │ ├── __snapshots__ │ └── App.test.js.snap │ ├── components │ ├── AddCar.js │ ├── Carlist.js │ └── EditCar.js │ ├── constants.js │ ├── index.css │ ├── index.js │ ├── logo.svg │ ├── reportWebVitals.js │ └── setupTests.js ├── Chapter14 ├── .gitignore ├── README.md ├── package.json ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt └── src │ ├── App.css │ ├── App.js │ ├── App.test.js │ ├── components │ ├── AddCar.js │ ├── Carlist.js │ ├── EditCar.js │ └── Login.js │ ├── constants.js │ ├── index.css │ ├── index.js │ ├── logo.svg │ ├── reportWebVitals.js │ └── setupTests.js ├── Chapter15 └── Dockerfile ├── LICENSE └── README.md /Answers/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Full-Stack-Development-with-Spring-Boot-and-React/f2f6d3034bb30f1d0faa5d6133047e5dd298a672/Answers/.gitkeep -------------------------------------------------------------------------------- /Chapter01/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /Chapter01/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Full-Stack-Development-with-Spring-Boot-and-React/f2f6d3034bb30f1d0faa5d6133047e5dd298a672/Chapter01/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /Chapter01/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.1/apache-maven-3.8.1-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /Chapter01/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 2.5.3 9 | 10 | 11 | com.packt 12 | cardatabase 13 | 0.0.1-SNAPSHOT 14 | cardatabase 15 | Demo project for Spring Boot 16 | 17 | 11 18 | 19 | 20 | 21 | org.springframework.boot 22 | spring-boot-starter-web 23 | 24 | 25 | 26 | org.springframework.boot 27 | spring-boot-devtools 28 | runtime 29 | true 30 | 31 | 32 | org.springframework.boot 33 | spring-boot-starter-test 34 | test 35 | 36 | 37 | 38 | 39 | 40 | 41 | org.springframework.boot 42 | spring-boot-maven-plugin 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /Chapter01/src/main/java/com/packt/cardatabase/CardatabaseApplication.java: -------------------------------------------------------------------------------- 1 | package com.packt.cardatabase; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.boot.SpringApplication; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | 8 | @SpringBootApplication 9 | public class CardatabaseApplication { 10 | private static final Logger logger = LoggerFactory.getLogger(CardatabaseApplication.class); 11 | 12 | public static void main(String[] args) { 13 | SpringApplication.run(CardatabaseApplication.class, args); 14 | logger.info("Application started"); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /Chapter01/src/main/resources/application.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Full-Stack-Development-with-Spring-Boot-and-React/f2f6d3034bb30f1d0faa5d6133047e5dd298a672/Chapter01/src/main/resources/application.properties -------------------------------------------------------------------------------- /Chapter01/src/test/java/com/packt/cardatabase/CardatabaseApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.packt.cardatabase; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class CardatabaseApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /Chapter02/Readme.md: -------------------------------------------------------------------------------- 1 | # Code snippets 2 | 3 | ```java 4 | public class Car { 5 | private Owner owner; 6 | 7 | public Car() { 8 | owner = new Owner(); 9 | } 10 | } 11 | ``` 12 | 13 | ```java 14 | public class Car { 15 | private Owner owner; 16 | 17 | public Car(Owner owner) { 18 | this.owner = owner; 19 | } 20 | } 21 | ``` 22 | 23 | ```java 24 | public class Car { 25 | private Owner owner; 26 | 27 | public void setOwner(Owner owner) { 28 | this.owner = owner; 29 | } 30 | } 31 | ``` 32 | 33 | ```java 34 | public class Car { 35 | @Autowired 36 | private Owner owner; 37 | 38 | // continues 39 | } 40 | ``` 41 | 42 | ```java 43 | public class Car { 44 | @Autowired 45 | private CarRepository carRepository; 46 | 47 | // Fetch all cars from db 48 | carRepositoty.findAll(); 49 | //Continues 50 | } 51 | ``` 52 | 53 | ```java 54 | @Configuration 55 | public class ConfigFileResource { 56 | 57 | @Bean(name="configFile") 58 | public File configFile() { 59 | File configFile = new File("configFile.xml"); 60 | return configFile; 61 | } 62 | } 63 | ``` 64 | 65 | ```java 66 | // By bean name 67 | @Resource(name="configFile") 68 | private ConfigFile cFile 69 | 70 | OR 71 | 72 | 73 | // Without name 74 | @Resource 75 | private ConfigFile cFile 76 | ``` 77 | -------------------------------------------------------------------------------- /Chapter03/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /Chapter03/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Full-Stack-Development-with-Spring-Boot-and-React/f2f6d3034bb30f1d0faa5d6133047e5dd298a672/Chapter03/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /Chapter03/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.1/apache-maven-3.8.1-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /Chapter03/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 2.5.3 9 | 10 | 11 | com.packt 12 | cardatabase 13 | 0.0.1-SNAPSHOT 14 | cardatabase 15 | Demo project for Spring Boot 16 | 17 | 11 18 | 19 | 20 | 21 | org.springframework.boot 22 | spring-boot-starter-web 23 | 24 | 25 | 26 | org.springframework.boot 27 | spring-boot-starter-data-jpa 28 | 29 | 30 | org.mariadb.jdbc 31 | mariadb-java-client 32 | 33 | 34 | org.springframework.boot 35 | spring-boot-devtools 36 | runtime 37 | true 38 | 39 | 40 | org.springframework.boot 41 | spring-boot-starter-test 42 | test 43 | 44 | 45 | 46 | 47 | 48 | 49 | org.springframework.boot 50 | spring-boot-maven-plugin 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /Chapter03/src/main/java/com/packt/cardatabase/CardatabaseApplication.java: -------------------------------------------------------------------------------- 1 | package com.packt.cardatabase; 2 | 3 | import java.util.Arrays; 4 | 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.boot.CommandLineRunner; 9 | import org.springframework.boot.SpringApplication; 10 | import org.springframework.boot.autoconfigure.SpringBootApplication; 11 | 12 | import com.packt.cardatabase.domain.Car; 13 | import com.packt.cardatabase.domain.CarRepository; 14 | import com.packt.cardatabase.domain.Owner; 15 | import com.packt.cardatabase.domain.OwnerRepository; 16 | 17 | @SpringBootApplication 18 | public class CardatabaseApplication implements CommandLineRunner { 19 | private static final Logger logger = 20 | LoggerFactory.getLogger(CardatabaseApplication.class); 21 | 22 | @Autowired 23 | private CarRepository repository; 24 | 25 | 26 | @Autowired 27 | private OwnerRepository orepository; 28 | 29 | 30 | public static void main(String[] args) { 31 | SpringApplication.run(CardatabaseApplication.class, args); 32 | } 33 | 34 | @Override 35 | public void run(String... args) throws Exception { 36 | // Add owner objects and save these to db 37 | Owner owner1 = new Owner("John" , "Johnson"); 38 | Owner owner2 = new Owner("Mary" , "Robinson"); 39 | orepository.saveAll(Arrays.asList(owner1, owner2)); 40 | 41 | // Add car object and link to owners and save these to db 42 | Car car1 = new Car("Ford", "Mustang", "Red", 43 | "ADF-1121", 2021, 59000, owner1); 44 | Car car2 = new Car("Nissan", "Leaf", "White", 45 | "SSJ-3002", 2019, 29000, owner2); 46 | Car car3 = new Car("Toyota", "Prius", "Silver", 47 | "KKO-0212", 2020, 39000, owner2); 48 | repository.saveAll(Arrays.asList(car1, car2, car3)); 49 | 50 | for (Car car : repository.findAll()) { 51 | logger.info(car.getBrand() + " " + car.getModel()); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Chapter03/src/main/java/com/packt/cardatabase/domain/Car.java: -------------------------------------------------------------------------------- 1 | package com.packt.cardatabase.domain; 2 | 3 | import javax.persistence.Entity; 4 | import javax.persistence.FetchType; 5 | import javax.persistence.GeneratedValue; 6 | import javax.persistence.GenerationType; 7 | import javax.persistence.Id; 8 | import javax.persistence.JoinColumn; 9 | import javax.persistence.ManyToOne; 10 | 11 | @Entity 12 | public class Car { 13 | @Id 14 | @GeneratedValue(strategy=GenerationType.AUTO) 15 | private long id; 16 | private String brand, model, color, registerNumber; 17 | @Column(name="`year`") 18 | private int year; 19 | private int price; 20 | 21 | public Car() {} 22 | 23 | public Car(String brand, String model, String color, 24 | String registerNumber, int year, int price, Owner owner) { 25 | super(); 26 | this.brand = brand; 27 | this.model = model; 28 | this.color = color; 29 | this.registerNumber = registerNumber; 30 | this.year = year; 31 | this.price = price; 32 | this.owner = owner; 33 | } 34 | 35 | @ManyToOne(fetch = FetchType.LAZY) 36 | @JoinColumn(name = "owner") 37 | private Owner owner; 38 | 39 | //Getter and setter 40 | public Owner getOwner() { 41 | return owner; 42 | } 43 | 44 | public void setOwner(Owner owner) { 45 | this.owner = owner; 46 | } 47 | 48 | 49 | public long getId() { 50 | return id; 51 | } 52 | 53 | public void setId(long id) { 54 | this.id = id; 55 | } 56 | 57 | public String getBrand() { 58 | return brand; 59 | } 60 | 61 | public void setBrand(String brand) { 62 | this.brand = brand; 63 | } 64 | 65 | public String getModel() { 66 | return model; 67 | } 68 | 69 | public void setModel(String model) { 70 | this.model = model; 71 | } 72 | 73 | public String getColor() { 74 | return color; 75 | } 76 | 77 | public void setColor(String color) { 78 | this.color = color; 79 | } 80 | 81 | public String getRegisterNumber() { 82 | return registerNumber; 83 | } 84 | 85 | public void setRegisterNumber(String registerNumber) { 86 | this.registerNumber = registerNumber; 87 | } 88 | 89 | public int getYear() { 90 | return year; 91 | } 92 | 93 | public void setYear(int year) { 94 | this.year = year; 95 | } 96 | 97 | public int getPrice() { 98 | return price; 99 | } 100 | 101 | public void setPrice(int price) { 102 | this.price = price; 103 | } 104 | 105 | } 106 | -------------------------------------------------------------------------------- /Chapter03/src/main/java/com/packt/cardatabase/domain/CarRepository.java: -------------------------------------------------------------------------------- 1 | package com.packt.cardatabase.domain; 2 | 3 | import org.springframework.data.repository.CrudRepository; 4 | 5 | public interface CarRepository extends CrudRepository { 6 | } 7 | -------------------------------------------------------------------------------- /Chapter03/src/main/java/com/packt/cardatabase/domain/Owner.java: -------------------------------------------------------------------------------- 1 | package com.packt.cardatabase.domain; 2 | 3 | import java.util.List; 4 | 5 | import javax.persistence.CascadeType; 6 | import javax.persistence.Entity; 7 | import javax.persistence.GeneratedValue; 8 | import javax.persistence.GenerationType; 9 | import javax.persistence.Id; 10 | import javax.persistence.OneToMany; 11 | 12 | @Entity 13 | public class Owner { 14 | @Id 15 | @GeneratedValue(strategy=GenerationType.AUTO) 16 | private long ownerid; 17 | private String firstname, lastname; 18 | 19 | public Owner() {} 20 | 21 | public Owner(String firstname, String lastname) { 22 | super(); 23 | this.firstname = firstname; 24 | this.lastname = lastname; 25 | } 26 | 27 | @OneToMany(cascade=CascadeType.ALL, mappedBy="owner") 28 | private List cars; 29 | 30 | public List getCars() { 31 | return cars; 32 | } 33 | 34 | public void setCars(List cars) { 35 | this.cars = cars; 36 | } 37 | 38 | public long getOwnerid() { 39 | return ownerid; 40 | } 41 | 42 | public void setOwnerid(long ownerid) { 43 | this.ownerid = ownerid; 44 | } 45 | 46 | public String getFirstname() { 47 | return firstname; 48 | } 49 | 50 | public void setFirstname(String firstname) { 51 | this.firstname = firstname; 52 | } 53 | 54 | public String getLastname() { 55 | return lastname; 56 | } 57 | 58 | public void setLastname(String lastname) { 59 | this.lastname = lastname; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /Chapter03/src/main/java/com/packt/cardatabase/domain/OwnerRepository.java: -------------------------------------------------------------------------------- 1 | package com.packt.cardatabase.domain; 2 | 3 | import org.springframework.data.repository.CrudRepository; 4 | 5 | public interface OwnerRepository extends CrudRepository { 6 | } 7 | -------------------------------------------------------------------------------- /Chapter03/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.datasource.url=jdbc:mariadb://localhost:3306/cardb 2 | spring.datasource.username=root 3 | spring.datasource.password=root 4 | spring.datasource.driver-class-name=org.mariadb.jdbc.Driver 5 | spring.jpa.generate-ddl=true 6 | spring.jpa.hibernate.ddl-auto=create-drop 7 | 8 | spring.jpa.show-sql=true 9 | -------------------------------------------------------------------------------- /Chapter03/src/test/java/com/packt/cardatabase/CardatabaseApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.packt.cardatabase; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class CardatabaseApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /Chapter04/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /Chapter04/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Full-Stack-Development-with-Spring-Boot-and-React/f2f6d3034bb30f1d0faa5d6133047e5dd298a672/Chapter04/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /Chapter04/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.1/apache-maven-3.8.1-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /Chapter04/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 2.5.3 9 | 10 | 11 | com.packt 12 | cardatabase 13 | 0.0.1-SNAPSHOT 14 | cardatabase 15 | Demo project for Spring Boot 16 | 17 | 11 18 | 19 | 20 | 21 | org.springframework.boot 22 | spring-boot-starter-web 23 | 24 | 25 | org.springframework.boot 26 | spring-boot-starter-data-rest 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter-data-jpa 31 | 32 | 33 | org.mariadb.jdbc 34 | mariadb-java-client 35 | 36 | 37 | org.springframework.boot 38 | spring-boot-devtools 39 | runtime 40 | true 41 | 42 | 43 | org.springframework.boot 44 | spring-boot-starter-test 45 | test 46 | 47 | 48 | 49 | 50 | 51 | 52 | org.springframework.boot 53 | spring-boot-maven-plugin 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /Chapter04/src/main/java/com/packt/cardatabase/CardatabaseApplication.java: -------------------------------------------------------------------------------- 1 | package com.packt.cardatabase; 2 | 3 | import java.util.Arrays; 4 | 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.boot.CommandLineRunner; 9 | import org.springframework.boot.SpringApplication; 10 | import org.springframework.boot.autoconfigure.SpringBootApplication; 11 | 12 | import com.packt.cardatabase.domain.Car; 13 | import com.packt.cardatabase.domain.CarRepository; 14 | import com.packt.cardatabase.domain.Owner; 15 | import com.packt.cardatabase.domain.OwnerRepository; 16 | 17 | @SpringBootApplication 18 | public class CardatabaseApplication implements CommandLineRunner { 19 | private static final Logger logger = 20 | LoggerFactory.getLogger(CardatabaseApplication.class); 21 | 22 | @Autowired 23 | private CarRepository repository; 24 | 25 | @Autowired 26 | private OwnerRepository orepository; 27 | 28 | 29 | public static void main(String[] args) { 30 | SpringApplication.run(CardatabaseApplication.class, args); 31 | } 32 | 33 | @Override 34 | public void run(String... args) throws Exception { 35 | // Add owner objects and save these to db 36 | Owner owner1 = new Owner("John" , "Johnson"); 37 | Owner owner2 = new Owner("Mary" , "Robinson"); 38 | orepository.saveAll(Arrays.asList(owner1, owner2)); 39 | 40 | // Add car object and link to owners and save these to db 41 | Car car1 = new Car("Ford", "Mustang", "Red", 42 | "ADF-1121", 2021, 59000, owner1); 43 | Car car2 = new Car("Nissan", "Leaf", "White", 44 | "SSJ-3002", 2019, 29000, owner2); 45 | Car car3 = new Car("Toyota", "Prius", "Silver", 46 | "KKO-0212", 2020, 39000, owner2); 47 | repository.saveAll(Arrays.asList(car1, car2, car3)); 48 | 49 | for (Car car : repository.findAll()) { 50 | logger.info(car.getBrand() + " " + car.getModel()); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Chapter04/src/main/java/com/packt/cardatabase/domain/Car.java: -------------------------------------------------------------------------------- 1 | package com.packt.cardatabase.domain; 2 | 3 | import javax.persistence.Entity; 4 | import javax.persistence.FetchType; 5 | import javax.persistence.GeneratedValue; 6 | import javax.persistence.GenerationType; 7 | import javax.persistence.Id; 8 | import javax.persistence.JoinColumn; 9 | import javax.persistence.ManyToOne; 10 | 11 | @Entity 12 | public class Car { 13 | @Id 14 | @GeneratedValue(strategy=GenerationType.AUTO) 15 | private long id; 16 | private String brand, model, color, registerNumber; 17 | private int year, price; 18 | 19 | public Car() {} 20 | 21 | public Car(String brand, String model, String color, 22 | String registerNumber, int year, int price, Owner owner) { 23 | super(); 24 | this.brand = brand; 25 | this.model = model; 26 | this.color = color; 27 | this.registerNumber = registerNumber; 28 | this.year = year; 29 | this.price = price; 30 | this.owner = owner; 31 | } 32 | 33 | @ManyToOne(fetch = FetchType.LAZY) 34 | @JoinColumn(name = "owner") 35 | private Owner owner; 36 | 37 | //Getter and setter 38 | public Owner getOwner() { 39 | return owner; 40 | } 41 | 42 | public void setOwner(Owner owner) { 43 | this.owner = owner; 44 | } 45 | 46 | 47 | public long getId() { 48 | return id; 49 | } 50 | 51 | public void setId(long id) { 52 | this.id = id; 53 | } 54 | 55 | public String getBrand() { 56 | return brand; 57 | } 58 | 59 | public void setBrand(String brand) { 60 | this.brand = brand; 61 | } 62 | 63 | public String getModel() { 64 | return model; 65 | } 66 | 67 | public void setModel(String model) { 68 | this.model = model; 69 | } 70 | 71 | public String getColor() { 72 | return color; 73 | } 74 | 75 | public void setColor(String color) { 76 | this.color = color; 77 | } 78 | 79 | public String getRegisterNumber() { 80 | return registerNumber; 81 | } 82 | 83 | public void setRegisterNumber(String registerNumber) { 84 | this.registerNumber = registerNumber; 85 | } 86 | 87 | public int getYear() { 88 | return year; 89 | } 90 | 91 | public void setYear(int year) { 92 | this.year = year; 93 | } 94 | 95 | public int getPrice() { 96 | return price; 97 | } 98 | 99 | public void setPrice(int price) { 100 | this.price = price; 101 | } 102 | 103 | } 104 | -------------------------------------------------------------------------------- /Chapter04/src/main/java/com/packt/cardatabase/domain/CarRepository.java: -------------------------------------------------------------------------------- 1 | package com.packt.cardatabase.domain; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.data.repository.CrudRepository; 6 | import org.springframework.data.repository.query.Param; 7 | import org.springframework.data.rest.core.annotation.RepositoryRestResource; 8 | 9 | @RepositoryRestResource 10 | public interface CarRepository extends CrudRepository { 11 | // Fetch cars by brand 12 | List findByBrand(@Param("brand") String brand); 13 | 14 | // Fetch cars by color 15 | List findByColor(@Param("color") String color); 16 | } 17 | -------------------------------------------------------------------------------- /Chapter04/src/main/java/com/packt/cardatabase/domain/Owner.java: -------------------------------------------------------------------------------- 1 | package com.packt.cardatabase.domain; 2 | 3 | import java.util.List; 4 | 5 | import javax.persistence.CascadeType; 6 | import javax.persistence.Entity; 7 | import javax.persistence.GeneratedValue; 8 | import javax.persistence.GenerationType; 9 | import javax.persistence.Id; 10 | import javax.persistence.OneToMany; 11 | 12 | import com.fasterxml.jackson.annotation.JsonIgnore; 13 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 14 | 15 | @Entity 16 | @JsonIgnoreProperties({"hibernateLazyInitializer", "handler"}) 17 | public class Owner { 18 | @Id 19 | @GeneratedValue(strategy=GenerationType.AUTO) 20 | private long ownerid; 21 | private String firstname, lastname; 22 | 23 | public Owner() {} 24 | 25 | public Owner(String firstname, String lastname) { 26 | super(); 27 | this.firstname = firstname; 28 | this.lastname = lastname; 29 | } 30 | 31 | @JsonIgnore 32 | @OneToMany(cascade=CascadeType.ALL, mappedBy="owner") 33 | private List cars; 34 | 35 | public List getCars() { 36 | return cars; 37 | } 38 | 39 | public void setCars(List cars) { 40 | this.cars = cars; 41 | } 42 | 43 | public long getOwnerid() { 44 | return ownerid; 45 | } 46 | 47 | public void setOwnerid(long ownerid) { 48 | this.ownerid = ownerid; 49 | } 50 | 51 | public String getFirstname() { 52 | return firstname; 53 | } 54 | 55 | public void setFirstname(String firstname) { 56 | this.firstname = firstname; 57 | } 58 | 59 | public String getLastname() { 60 | return lastname; 61 | } 62 | 63 | public void setLastname(String lastname) { 64 | this.lastname = lastname; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /Chapter04/src/main/java/com/packt/cardatabase/domain/OwnerRepository.java: -------------------------------------------------------------------------------- 1 | package com.packt.cardatabase.domain; 2 | 3 | import org.springframework.data.repository.CrudRepository; 4 | 5 | public interface OwnerRepository extends CrudRepository { 6 | } 7 | -------------------------------------------------------------------------------- /Chapter04/src/main/java/com/packt/cardatabase/web/CarController.java: -------------------------------------------------------------------------------- 1 | package com.packt.cardatabase.web; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | import com.packt.cardatabase.domain.Car; 8 | import com.packt.cardatabase.domain.CarRepository; 9 | 10 | @RestController 11 | public class CarController { 12 | @Autowired 13 | private CarRepository repository; 14 | 15 | @RequestMapping("/cars") 16 | public Iterable getCars() { 17 | return repository.findAll(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Chapter04/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.datasource.url=jdbc:mariadb://localhost:3306/cardb 2 | spring.datasource.username=root 3 | spring.datasource.password=YOUR_PASSWORD 4 | spring.datasource.driver-class-name=org.mariadb.jdbc.Driver 5 | spring.jpa.generate-ddl=true 6 | spring.jpa.hibernate.ddl-auto=create-drop 7 | 8 | spring.jpa.show-sql=true 9 | spring.data.rest.basePath=/api 10 | -------------------------------------------------------------------------------- /Chapter04/src/test/java/com/packt/cardatabase/CardatabaseApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.packt.cardatabase; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class CardatabaseApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /Chapter05/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /Chapter05/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Full-Stack-Development-with-Spring-Boot-and-React/f2f6d3034bb30f1d0faa5d6133047e5dd298a672/Chapter05/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /Chapter05/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.1/apache-maven-3.8.1-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /Chapter05/README.md: -------------------------------------------------------------------------------- 1 | ## Important note 2 | 3 | The `WebSecurityConfigurerAdapter` is deprecated in Spring Boot version 2.7. 4 | You can still use Spring Boot version 2.6.x by changing the version in your pom.xml file, for example 5 | ``` 6 | 4.0.0 7 | 8 | org.springframework.boot 9 | spring-boot-starter-parent 10 | 2.6.12 11 | 12 | 13 | ``` 14 | You can also see how this is done without `WebSecurityConfigurerAdapter` from the Baeldung blog https://www.baeldung.com/spring-deprecated-websecurityconfigureradapter 15 | -------------------------------------------------------------------------------- /Chapter05/src/main/java/com/packt/cardatabase/AuthEntryPoint.java: -------------------------------------------------------------------------------- 1 | package com.packt.cardatabase; 2 | 3 | import java.io.IOException; 4 | import java.io.PrintWriter; 5 | 6 | import javax.servlet.ServletException; 7 | import javax.servlet.http.HttpServletRequest; 8 | import javax.servlet.http.HttpServletResponse; 9 | 10 | import org.springframework.http.MediaType; 11 | import org.springframework.security.core.AuthenticationException; 12 | import org.springframework.security.web.AuthenticationEntryPoint; 13 | import org.springframework.stereotype.Component; 14 | 15 | @Component 16 | public class AuthEntryPoint implements AuthenticationEntryPoint { 17 | @Override 18 | public void commence(HttpServletRequest request, HttpServletResponse response, 19 | AuthenticationException authException) throws IOException, ServletException { 20 | response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); 21 | response.setContentType(MediaType.APPLICATION_JSON_VALUE); 22 | PrintWriter writer = response.getWriter(); 23 | writer.println("Error: " + authException.getMessage()); 24 | } 25 | } -------------------------------------------------------------------------------- /Chapter05/src/main/java/com/packt/cardatabase/AuthenticationFilter.java: -------------------------------------------------------------------------------- 1 | package com.packt.cardatabase; 2 | 3 | import java.io.IOException; 4 | 5 | import javax.servlet.FilterChain; 6 | import javax.servlet.ServletException; 7 | import javax.servlet.http.HttpServletRequest; 8 | import javax.servlet.http.HttpServletResponse; 9 | 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.http.HttpHeaders; 12 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 13 | import org.springframework.security.core.Authentication; 14 | import org.springframework.security.core.context.SecurityContextHolder; 15 | import org.springframework.stereotype.Component; 16 | import org.springframework.web.filter.OncePerRequestFilter; 17 | 18 | import com.packt.cardatabase.service.JwtService; 19 | 20 | @Component 21 | public class AuthenticationFilter extends OncePerRequestFilter { 22 | @Autowired 23 | private JwtService jwtService; 24 | 25 | @Override 26 | protected void doFilterInternal(HttpServletRequest request, 27 | HttpServletResponse response, 28 | FilterChain filterChain) 29 | throws ServletException, IOException { 30 | 31 | // Get token from Authorization header 32 | String jws = request.getHeader(HttpHeaders.AUTHORIZATION); 33 | 34 | if (jws != null) { 35 | // Verify token and get user 36 | String user = jwtService.getAuthUser(request); 37 | 38 | // Authenticate 39 | Authentication authentication = 40 | new UsernamePasswordAuthenticationToken(user, null, java.util.Collections.emptyList()); 41 | 42 | SecurityContextHolder.getContext().setAuthentication(authentication); 43 | 44 | } 45 | 46 | filterChain.doFilter(request, response); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Chapter05/src/main/java/com/packt/cardatabase/CardatabaseApplication.java: -------------------------------------------------------------------------------- 1 | package com.packt.cardatabase; 2 | 3 | import java.util.Arrays; 4 | 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.boot.CommandLineRunner; 9 | import org.springframework.boot.SpringApplication; 10 | import org.springframework.boot.autoconfigure.SpringBootApplication; 11 | 12 | import com.packt.cardatabase.domain.Car; 13 | import com.packt.cardatabase.domain.CarRepository; 14 | import com.packt.cardatabase.domain.Owner; 15 | import com.packt.cardatabase.domain.OwnerRepository; 16 | import com.packt.cardatabase.domain.User; 17 | import com.packt.cardatabase.domain.UserRepository; 18 | 19 | @SpringBootApplication 20 | public class CardatabaseApplication implements CommandLineRunner { 21 | private static final Logger logger = 22 | LoggerFactory.getLogger(CardatabaseApplication.class); 23 | 24 | @Autowired 25 | private CarRepository repository; 26 | 27 | @Autowired 28 | private OwnerRepository orepository; 29 | 30 | @Autowired 31 | private UserRepository urepository; 32 | 33 | public static void main(String[] args) { 34 | SpringApplication.run(CardatabaseApplication.class, args); 35 | } 36 | 37 | @Override 38 | public void run(String... args) throws Exception { 39 | // Add owner objects and save these to db 40 | Owner owner1 = new Owner("John" , "Johnson"); 41 | Owner owner2 = new Owner("Mary" , "Robinson"); 42 | orepository.saveAll(Arrays.asList(owner1, owner2)); 43 | 44 | // Add car object and link to owners and save these to db 45 | Car car1 = new Car("Ford", "Mustang", "Red", 46 | "ADF-1121", 2021, 59000, owner1); 47 | Car car2 = new Car("Nissan", "Leaf", "White", 48 | "SSJ-3002", 2019, 29000, owner2); 49 | Car car3 = new Car("Toyota", "Prius", "Silver", 50 | "KKO-0212", 2020, 39000, owner2); 51 | repository.saveAll(Arrays.asList(car1, car2, car3)); 52 | 53 | for (Car car : repository.findAll()) { 54 | logger.info(car.getBrand() + " " + car.getModel()); 55 | } 56 | 57 | urepository.save(new User("user", 58 | "$2a$10$NVM0n8ElaRgg7zWO1CxUdei7vWoPg91Lz2aYavh9.f9q0e4bRadue","USER")); 59 | urepository.save(new User("admin", 60 | "$2a$10$8cjz47bjbR4Mn8GMg9IZx.vyjhLXR/SKKMSZ9.mP9vpMu0ssKi8GW", "ADMIN")); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Chapter05/src/main/java/com/packt/cardatabase/domain/AccountCredentials.java: -------------------------------------------------------------------------------- 1 | package com.packt.cardatabase.domain; 2 | 3 | public class AccountCredentials { 4 | private String username; 5 | private String password; 6 | 7 | public String getUsername() { 8 | return username; 9 | } 10 | 11 | public void setUsername(String username) { 12 | this.username = username; 13 | } 14 | 15 | public String getPassword() { 16 | return password; 17 | } 18 | 19 | public void setPassword(String password) { 20 | this.password = password; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Chapter05/src/main/java/com/packt/cardatabase/domain/Car.java: -------------------------------------------------------------------------------- 1 | package com.packt.cardatabase.domain; 2 | 3 | import javax.persistence.Entity; 4 | import javax.persistence.FetchType; 5 | import javax.persistence.GeneratedValue; 6 | import javax.persistence.GenerationType; 7 | import javax.persistence.Id; 8 | import javax.persistence.JoinColumn; 9 | import javax.persistence.ManyToOne; 10 | 11 | @Entity 12 | public class Car { 13 | @Id 14 | @GeneratedValue(strategy=GenerationType.AUTO) 15 | private long id; 16 | private String brand, model, color, registerNumber; 17 | private int year, price; 18 | 19 | public Car() {} 20 | 21 | public Car(String brand, String model, String color, 22 | String registerNumber, int year, int price, Owner owner) { 23 | super(); 24 | this.brand = brand; 25 | this.model = model; 26 | this.color = color; 27 | this.registerNumber = registerNumber; 28 | this.year = year; 29 | this.price = price; 30 | this.owner = owner; 31 | } 32 | 33 | @ManyToOne(fetch = FetchType.LAZY) 34 | @JoinColumn(name = "owner") 35 | private Owner owner; 36 | 37 | //Getter and setter 38 | public Owner getOwner() { 39 | return owner; 40 | } 41 | 42 | public void setOwner(Owner owner) { 43 | this.owner = owner; 44 | } 45 | 46 | 47 | public long getId() { 48 | return id; 49 | } 50 | 51 | public void setId(long id) { 52 | this.id = id; 53 | } 54 | 55 | public String getBrand() { 56 | return brand; 57 | } 58 | 59 | public void setBrand(String brand) { 60 | this.brand = brand; 61 | } 62 | 63 | public String getModel() { 64 | return model; 65 | } 66 | 67 | public void setModel(String model) { 68 | this.model = model; 69 | } 70 | 71 | public String getColor() { 72 | return color; 73 | } 74 | 75 | public void setColor(String color) { 76 | this.color = color; 77 | } 78 | 79 | public String getRegisterNumber() { 80 | return registerNumber; 81 | } 82 | 83 | public void setRegisterNumber(String registerNumber) { 84 | this.registerNumber = registerNumber; 85 | } 86 | 87 | public int getYear() { 88 | return year; 89 | } 90 | 91 | public void setYear(int year) { 92 | this.year = year; 93 | } 94 | 95 | public int getPrice() { 96 | return price; 97 | } 98 | 99 | public void setPrice(int price) { 100 | this.price = price; 101 | } 102 | 103 | } 104 | -------------------------------------------------------------------------------- /Chapter05/src/main/java/com/packt/cardatabase/domain/CarRepository.java: -------------------------------------------------------------------------------- 1 | package com.packt.cardatabase.domain; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.data.repository.CrudRepository; 6 | import org.springframework.data.repository.query.Param; 7 | import org.springframework.data.rest.core.annotation.RepositoryRestResource; 8 | 9 | @RepositoryRestResource 10 | public interface CarRepository extends CrudRepository { 11 | // Fetch cars by brand 12 | List findByBrand(@Param("brand") String brand); 13 | 14 | // Fetch cars by color 15 | List findByColor(@Param("color") String color); 16 | } 17 | -------------------------------------------------------------------------------- /Chapter05/src/main/java/com/packt/cardatabase/domain/Owner.java: -------------------------------------------------------------------------------- 1 | package com.packt.cardatabase.domain; 2 | 3 | import java.util.List; 4 | 5 | import javax.persistence.CascadeType; 6 | import javax.persistence.Entity; 7 | import javax.persistence.GeneratedValue; 8 | import javax.persistence.GenerationType; 9 | import javax.persistence.Id; 10 | import javax.persistence.OneToMany; 11 | 12 | import com.fasterxml.jackson.annotation.JsonIgnore; 13 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 14 | 15 | @Entity 16 | @JsonIgnoreProperties({"hibernateLazyInitializer", "handler"}) 17 | public class Owner { 18 | @Id 19 | @GeneratedValue(strategy=GenerationType.AUTO) 20 | private long ownerid; 21 | private String firstname, lastname; 22 | 23 | public Owner() {} 24 | 25 | public Owner(String firstname, String lastname) { 26 | super(); 27 | this.firstname = firstname; 28 | this.lastname = lastname; 29 | } 30 | 31 | @JsonIgnore 32 | @OneToMany(cascade=CascadeType.ALL, mappedBy="owner") 33 | private List cars; 34 | 35 | public List getCars() { 36 | return cars; 37 | } 38 | 39 | public void setCars(List cars) { 40 | this.cars = cars; 41 | } 42 | 43 | public long getOwnerid() { 44 | return ownerid; 45 | } 46 | 47 | public void setOwnerid(long ownerid) { 48 | this.ownerid = ownerid; 49 | } 50 | 51 | public String getFirstname() { 52 | return firstname; 53 | } 54 | 55 | public void setFirstname(String firstname) { 56 | this.firstname = firstname; 57 | } 58 | 59 | public String getLastname() { 60 | return lastname; 61 | } 62 | 63 | public void setLastname(String lastname) { 64 | this.lastname = lastname; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /Chapter05/src/main/java/com/packt/cardatabase/domain/OwnerRepository.java: -------------------------------------------------------------------------------- 1 | package com.packt.cardatabase.domain; 2 | 3 | import java.util.Optional; 4 | 5 | import org.springframework.data.repository.CrudRepository; 6 | import org.springframework.data.rest.core.annotation.RepositoryRestResource; 7 | 8 | @RepositoryRestResource 9 | public interface OwnerRepository extends CrudRepository { 10 | Optional findByFirstname(String firstName); 11 | } 12 | -------------------------------------------------------------------------------- /Chapter05/src/main/java/com/packt/cardatabase/domain/User.java: -------------------------------------------------------------------------------- 1 | package com.packt.cardatabase.domain; 2 | 3 | import javax.persistence.Column; 4 | import javax.persistence.Entity; 5 | import javax.persistence.GeneratedValue; 6 | import javax.persistence.GenerationType; 7 | import javax.persistence.Id; 8 | 9 | import com.fasterxml.jackson.annotation.JsonIgnore; 10 | 11 | @Entity 12 | public class User { 13 | @Id 14 | @GeneratedValue(strategy=GenerationType.IDENTITY) 15 | @Column(nullable=false, updatable=false) 16 | private Long id; 17 | 18 | @Column(nullable=false, unique=true) 19 | private String username; 20 | 21 | @Column(nullable=false) 22 | private String password; 23 | 24 | @Column(nullable=false) 25 | private String role; 26 | 27 | public User() { 28 | } 29 | 30 | public User(String username, String password, String role) { 31 | super(); 32 | this.username = username; 33 | this.password = password; 34 | this.role = role; 35 | } 36 | 37 | public Long getId() { 38 | return id; 39 | } 40 | 41 | public void setId(Long id) { 42 | this.id = id; 43 | } 44 | 45 | public String getUsername() { 46 | return username; 47 | } 48 | 49 | public void setUsername(String username) { 50 | this.username = username; 51 | } 52 | 53 | public String getPassword() { 54 | return password; 55 | } 56 | 57 | public void setPassword(String password) { 58 | this.password = password; 59 | } 60 | 61 | public String getRole() { 62 | return role; 63 | } 64 | 65 | public void setRole(String role) { 66 | this.role = role; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /Chapter05/src/main/java/com/packt/cardatabase/domain/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.packt.cardatabase.domain; 2 | 3 | import java.util.Optional; 4 | 5 | import org.springframework.data.repository.CrudRepository; 6 | import org.springframework.data.rest.core.annotation.RepositoryRestResource; 7 | 8 | @RepositoryRestResource(exported = false) 9 | public interface UserRepository extends CrudRepository { 10 | Optional findByUsername(String username); 11 | } 12 | -------------------------------------------------------------------------------- /Chapter05/src/main/java/com/packt/cardatabase/service/JwtService.java: -------------------------------------------------------------------------------- 1 | package com.packt.cardatabase.service; 2 | 3 | import io.jsonwebtoken.Jwts; 4 | import io.jsonwebtoken.SignatureAlgorithm; 5 | import io.jsonwebtoken.security.Keys; 6 | import java.security.Key; 7 | import org.springframework.http.HttpHeaders; 8 | import org.springframework.stereotype.Component; 9 | import javax.servlet.http.HttpServletRequest; 10 | import java.util.Date; 11 | 12 | @Component 13 | public class JwtService { 14 | static final long EXPIRATIONTIME = 86400000; // 1 day in ms 15 | static final String PREFIX = "Bearer"; 16 | // Generate secret key. Only for the demonstration 17 | // You should read it from the application configuration 18 | static final Key key = Keys.secretKeyFor(SignatureAlgorithm.HS256); 19 | 20 | // Generate JWT token 21 | public String getToken(String username) { 22 | String token = Jwts.builder() 23 | .setSubject(username) 24 | .setExpiration(new Date(System.currentTimeMillis() + EXPIRATIONTIME)) 25 | .signWith(key) 26 | .compact(); 27 | return token; 28 | } 29 | 30 | // Get a token from request Authorization header, 31 | // parse a token and get username 32 | public String getAuthUser(HttpServletRequest request) { 33 | String token = request.getHeader(HttpHeaders.AUTHORIZATION); 34 | 35 | if (token != null) { 36 | String user = Jwts.parserBuilder() 37 | .setSigningKey(key) 38 | .build() 39 | .parseClaimsJws(token.replace(PREFIX, "")) 40 | .getBody() 41 | .getSubject(); 42 | 43 | if (user != null) 44 | return user; 45 | } 46 | 47 | return null; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Chapter05/src/main/java/com/packt/cardatabase/service/UserDetailsServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.packt.cardatabase.service; 2 | 3 | import java.util.Optional; 4 | 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.security.core.userdetails.User.UserBuilder; 7 | import org.springframework.security.core.userdetails.UserDetails; 8 | import org.springframework.security.core.userdetails.UserDetailsService; 9 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 10 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 11 | import org.springframework.stereotype.Service; 12 | import com.packt.cardatabase.domain.User; 13 | 14 | import com.packt.cardatabase.domain.UserRepository; 15 | 16 | @Service 17 | public class UserDetailsServiceImpl implements UserDetailsService { 18 | @Autowired 19 | private UserRepository repository; 20 | 21 | @Override 22 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 23 | Optional user = repository.findByUsername(username); 24 | 25 | UserBuilder builder = null; 26 | if (user.isPresent()) { 27 | User currentUser = user.get(); 28 | builder = org.springframework.security.core.userdetails.User.withUsername(username); 29 | builder.password(currentUser.getPassword()); 30 | builder.roles(currentUser.getRole()); 31 | } else { 32 | throw new UsernameNotFoundException("User not found."); 33 | } 34 | 35 | return builder.build(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Chapter05/src/main/java/com/packt/cardatabase/web/CarController.java: -------------------------------------------------------------------------------- 1 | package com.packt.cardatabase.web; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | import com.packt.cardatabase.domain.Car; 8 | import com.packt.cardatabase.domain.CarRepository; 9 | 10 | @RestController 11 | public class CarController { 12 | @Autowired 13 | private CarRepository repository; 14 | 15 | @RequestMapping("/cars") 16 | public Iterable getCars() { 17 | return repository.findAll(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Chapter05/src/main/java/com/packt/cardatabase/web/LoginController.java: -------------------------------------------------------------------------------- 1 | package com.packt.cardatabase.web; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.http.HttpHeaders; 5 | import org.springframework.http.MediaType; 6 | import org.springframework.http.ResponseEntity; 7 | import org.springframework.security.authentication.AuthenticationManager; 8 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 9 | import org.springframework.security.core.Authentication; 10 | import org.springframework.web.bind.annotation.RequestBody; 11 | import org.springframework.web.bind.annotation.RequestMapping; 12 | import org.springframework.web.bind.annotation.RequestMethod; 13 | import org.springframework.web.bind.annotation.RestController; 14 | 15 | import com.packt.cardatabase.domain.AccountCredentials; 16 | import com.packt.cardatabase.service.JwtService; 17 | 18 | @RestController 19 | public class LoginController { 20 | @Autowired 21 | private JwtService jwtService; 22 | 23 | @Autowired 24 | AuthenticationManager authenticationManager; 25 | 26 | @RequestMapping(value="/login", method=RequestMethod.POST) 27 | public ResponseEntity getToken(@RequestBody AccountCredentials credentials) { 28 | UsernamePasswordAuthenticationToken creds = 29 | new UsernamePasswordAuthenticationToken( 30 | credentials.getUsername(), 31 | credentials.getPassword()); 32 | 33 | Authentication auth = authenticationManager.authenticate(creds); 34 | 35 | // Generate token 36 | String jwts = jwtService.getToken(auth.getName()); 37 | 38 | // Build response with the generated token 39 | return ResponseEntity.ok() 40 | .header(HttpHeaders.AUTHORIZATION, "Bearer " + jwts) 41 | .header(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, "Authorization") 42 | .build(); 43 | 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Chapter05/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.datasource.url=jdbc:mariadb://localhost:3306/cardb 2 | spring.datasource.username=root 3 | spring.datasource.password=root 4 | spring.datasource.driver-class-name=org.mariadb.jdbc.Driver 5 | spring.jpa.generate-ddl=true 6 | spring.jpa.hibernate.ddl-auto=create-drop 7 | 8 | spring.jpa.show-sql=true 9 | spring.jackson.serialization.FAIL_ON_EMPTY_BEANS=false 10 | spring.data.rest.basePath=/api -------------------------------------------------------------------------------- /Chapter05/src/test/java/com/packt/cardatabase/CarRestTest.java: -------------------------------------------------------------------------------- 1 | package com.packt.cardatabase; 2 | 3 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; 4 | import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; 5 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 6 | 7 | import org.junit.jupiter.api.Test; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; 10 | import org.springframework.boot.test.context.SpringBootTest; 11 | import org.springframework.http.HttpHeaders; 12 | import org.springframework.test.web.servlet.MockMvc; 13 | 14 | @SpringBootTest 15 | @AutoConfigureMockMvc 16 | public class CarRestTest { 17 | @Autowired 18 | private MockMvc mockMvc; 19 | 20 | @Test 21 | public void testAuthentication() throws Exception { 22 | // Testing authentication with correct credentials 23 | this.mockMvc.perform(post("/login").content("{\"username\":\"admin\", \"password\":\"admin\"}"). 24 | header(HttpHeaders.CONTENT_TYPE, "application/json")). 25 | andDo(print()).andExpect(status().isOk()); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /Chapter05/src/test/java/com/packt/cardatabase/CardatabaseApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.packt.cardatabase; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | 5 | import org.junit.jupiter.api.Test; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.boot.test.context.SpringBootTest; 8 | 9 | import com.packt.cardatabase.web.CarController; 10 | 11 | @SpringBootTest 12 | class CardatabaseApplicationTests { 13 | @Autowired 14 | private CarController controller; 15 | 16 | @Test 17 | void contextLoads() { 18 | assertThat(controller).isNotNull(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Chapter05/src/test/java/com/packt/cardatabase/OwnerRepositoryTest.java: -------------------------------------------------------------------------------- 1 | package com.packt.cardatabase; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | import org.junit.jupiter.api.Test; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; 7 | 8 | import com.packt.cardatabase.domain.Owner; 9 | import com.packt.cardatabase.domain.OwnerRepository; 10 | 11 | @DataJpaTest 12 | public class OwnerRepositoryTest { 13 | @Autowired 14 | private OwnerRepository repository; 15 | 16 | @Test 17 | void saveOwner() { 18 | repository.save(new Owner("Lucy", "Smith")); 19 | assertThat(repository.findByFirstname("Lucy").isPresent()).isTrue(); 20 | } 21 | 22 | @Test 23 | void deleteOwners() { 24 | repository.save(new Owner("Lisa", "Morrison")); 25 | repository.deleteAll(); 26 | assertThat(repository.count()).isEqualTo(0); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /Chapter06/Readme.md: -------------------------------------------------------------------------------- 1 | ## Commands used in chapter 6 2 | 3 | These commands prints out the version of npm and node 4 | 5 | ``` 6 | npm -v 7 | node -v 8 | ``` 9 | 10 | This command creates React app named myapp: 11 | 12 | ``` 13 | npx create-react-app myapp 14 | ``` 15 | 16 | This command starts React app (execute in the project root folder) 17 | 18 | ``` 19 | npm start 20 | ``` 21 | 22 | OR if you are using yarn 23 | 24 | ``` 25 | yarn start 26 | ``` 27 | -------------------------------------------------------------------------------- /Chapter07/MyForm/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /Chapter07/MyForm/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "myform", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.16.4", 7 | "@testing-library/react": "^13.1.1", 8 | "@testing-library/user-event": "^13.5.0", 9 | "react": "^18.0.0", 10 | "react-dom": "^18.0.0", 11 | "react-scripts": "5.0.1", 12 | "web-vitals": "^2.1.4" 13 | }, 14 | "scripts": { 15 | "start": "react-scripts start", 16 | "build": "react-scripts build", 17 | "test": "react-scripts test", 18 | "eject": "react-scripts eject" 19 | }, 20 | "eslintConfig": { 21 | "extends": [ 22 | "react-app", 23 | "react-app/jest" 24 | ] 25 | }, 26 | "browserslist": { 27 | "production": [ 28 | ">0.2%", 29 | "not dead", 30 | "not op_mini all" 31 | ], 32 | "development": [ 33 | "last 1 chrome version", 34 | "last 1 firefox version", 35 | "last 1 safari version" 36 | ] 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Chapter07/MyForm/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Full-Stack-Development-with-Spring-Boot-and-React/f2f6d3034bb30f1d0faa5d6133047e5dd298a672/Chapter07/MyForm/public/favicon.ico -------------------------------------------------------------------------------- /Chapter07/MyForm/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /Chapter07/MyForm/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Full-Stack-Development-with-Spring-Boot-and-React/f2f6d3034bb30f1d0faa5d6133047e5dd298a672/Chapter07/MyForm/public/logo192.png -------------------------------------------------------------------------------- /Chapter07/MyForm/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Full-Stack-Development-with-Spring-Boot-and-React/f2f6d3034bb30f1d0faa5d6133047e5dd298a672/Chapter07/MyForm/public/logo512.png -------------------------------------------------------------------------------- /Chapter07/MyForm/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /Chapter07/MyForm/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /Chapter07/MyForm/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Chapter07/MyForm/src/App.js: -------------------------------------------------------------------------------- 1 | import './App.css'; 2 | import MyForm from './MyForm'; 3 | 4 | function App() { 5 | return ( 6 | 7 | ); 8 | } 9 | 10 | export default App; 11 | -------------------------------------------------------------------------------- /Chapter07/MyForm/src/App.test.js: -------------------------------------------------------------------------------- 1 | import { render, screen } from '@testing-library/react'; 2 | import App from './App'; 3 | 4 | test('renders learn react link', () => { 5 | render(); 6 | const linkElement = screen.getByText(/learn react/i); 7 | expect(linkElement).toBeInTheDocument(); 8 | }); 9 | -------------------------------------------------------------------------------- /Chapter07/MyForm/src/MyForm.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | 3 | function MyForm() { 4 | const [firstName, setFirstName] = useState(''); 5 | const [lastName, setLastName] = useState(''); 6 | const [email, setEmail] = useState(''); 7 | 8 | const handleSubmit = (event) => { 9 | alert(`Hello ${firstName} ${lastName}`); 10 | event.preventDefault(); 11 | } 12 | 13 | return ( 14 |
15 | 16 | setFirstName(e.target.value)} 18 | value={firstName}/>
19 | 20 | setLastName(e.target.value)} 22 | value={lastName}/>
23 | 24 | setEmail(e.target.value)} 26 | value={email}/>
27 | 28 |
29 | ); 30 | } 31 | 32 | export default MyForm; -------------------------------------------------------------------------------- /Chapter07/MyForm/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /Chapter07/MyForm/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom/client'; 3 | import './index.css'; 4 | import App from './App'; 5 | import reportWebVitals from './reportWebVitals'; 6 | 7 | const root = ReactDOM.createRoot(document.getElementById('root')); 8 | root.render( 9 | 10 | 11 | 12 | ); 13 | 14 | // If you want to start measuring performance in your app, pass a function 15 | // to log results (for example: reportWebVitals(console.log)) 16 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 17 | reportWebVitals(); 18 | -------------------------------------------------------------------------------- /Chapter07/MyForm/src/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Chapter07/MyForm/src/reportWebVitals.js: -------------------------------------------------------------------------------- 1 | const reportWebVitals = onPerfEntry => { 2 | if (onPerfEntry && onPerfEntry instanceof Function) { 3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 4 | getCLS(onPerfEntry); 5 | getFID(onPerfEntry); 6 | getFCP(onPerfEntry); 7 | getLCP(onPerfEntry); 8 | getTTFB(onPerfEntry); 9 | }); 10 | } 11 | }; 12 | 13 | export default reportWebVitals; 14 | -------------------------------------------------------------------------------- /Chapter07/MyForm/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /Chapter07/MyList/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /Chapter07/MyList/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mylist", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.16.4", 7 | "@testing-library/react": "^13.1.1", 8 | "@testing-library/user-event": "^13.5.0", 9 | "react": "^18.0.0", 10 | "react-dom": "^18.0.0", 11 | "react-scripts": "5.0.1", 12 | "web-vitals": "^2.1.4" 13 | }, 14 | "scripts": { 15 | "start": "react-scripts start", 16 | "build": "react-scripts build", 17 | "test": "react-scripts test", 18 | "eject": "react-scripts eject" 19 | }, 20 | "eslintConfig": { 21 | "extends": [ 22 | "react-app", 23 | "react-app/jest" 24 | ] 25 | }, 26 | "browserslist": { 27 | "production": [ 28 | ">0.2%", 29 | "not dead", 30 | "not op_mini all" 31 | ], 32 | "development": [ 33 | "last 1 chrome version", 34 | "last 1 firefox version", 35 | "last 1 safari version" 36 | ] 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Chapter07/MyList/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Full-Stack-Development-with-Spring-Boot-and-React/f2f6d3034bb30f1d0faa5d6133047e5dd298a672/Chapter07/MyList/public/favicon.ico -------------------------------------------------------------------------------- /Chapter07/MyList/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /Chapter07/MyList/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Full-Stack-Development-with-Spring-Boot-and-React/f2f6d3034bb30f1d0faa5d6133047e5dd298a672/Chapter07/MyList/public/logo192.png -------------------------------------------------------------------------------- /Chapter07/MyList/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Full-Stack-Development-with-Spring-Boot-and-React/f2f6d3034bb30f1d0faa5d6133047e5dd298a672/Chapter07/MyList/public/logo512.png -------------------------------------------------------------------------------- /Chapter07/MyList/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /Chapter07/MyList/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /Chapter07/MyList/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Chapter07/MyList/src/App.js: -------------------------------------------------------------------------------- 1 | import './App.css'; 2 | import MyList from './MyList'; 3 | 4 | function App() { 5 | return ( 6 | 7 | ); 8 | } 9 | 10 | export default App; 11 | -------------------------------------------------------------------------------- /Chapter07/MyList/src/App.test.js: -------------------------------------------------------------------------------- 1 | import { render, screen } from '@testing-library/react'; 2 | import App from './App'; 3 | 4 | test('renders learn react link', () => { 5 | render(); 6 | const linkElement = screen.getByText(/learn react/i); 7 | expect(linkElement).toBeInTheDocument(); 8 | }); 9 | -------------------------------------------------------------------------------- /Chapter07/MyList/src/MyList.js: -------------------------------------------------------------------------------- 1 | function MyList() { 2 | const data = [1, 2, 3, 4, 5]; 3 | 4 | return ( 5 |
6 |
    7 | { 8 | data.map((number, index) => 9 |
  • Listitem {number}
  • ) 10 | } 11 |
12 |
13 | ); 14 | }; 15 | 16 | export default MyList; 17 | -------------------------------------------------------------------------------- /Chapter07/MyList/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /Chapter07/MyList/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom/client'; 3 | import './index.css'; 4 | import App from './App'; 5 | import reportWebVitals from './reportWebVitals'; 6 | 7 | const root = ReactDOM.createRoot(document.getElementById('root')); 8 | root.render( 9 | 10 | 11 | 12 | ); 13 | 14 | // If you want to start measuring performance in your app, pass a function 15 | // to log results (for example: reportWebVitals(console.log)) 16 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 17 | reportWebVitals(); 18 | -------------------------------------------------------------------------------- /Chapter07/MyList/src/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Chapter07/MyList/src/reportWebVitals.js: -------------------------------------------------------------------------------- 1 | const reportWebVitals = onPerfEntry => { 2 | if (onPerfEntry && onPerfEntry instanceof Function) { 3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 4 | getCLS(onPerfEntry); 5 | getFID(onPerfEntry); 6 | getFCP(onPerfEntry); 7 | getLCP(onPerfEntry); 8 | getTTFB(onPerfEntry); 9 | }); 10 | } 11 | }; 12 | 13 | export default reportWebVitals; 14 | -------------------------------------------------------------------------------- /Chapter07/MyList/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /Chapter07/MyTable/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /Chapter07/MyTable/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mytable", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.16.4", 7 | "@testing-library/react": "^13.1.1", 8 | "@testing-library/user-event": "^13.5.0", 9 | "react": "^18.0.0", 10 | "react-dom": "^18.0.0", 11 | "react-scripts": "5.0.1", 12 | "web-vitals": "^2.1.4" 13 | }, 14 | "scripts": { 15 | "start": "react-scripts start", 16 | "build": "react-scripts build", 17 | "test": "react-scripts test", 18 | "eject": "react-scripts eject" 19 | }, 20 | "eslintConfig": { 21 | "extends": [ 22 | "react-app", 23 | "react-app/jest" 24 | ] 25 | }, 26 | "browserslist": { 27 | "production": [ 28 | ">0.2%", 29 | "not dead", 30 | "not op_mini all" 31 | ], 32 | "development": [ 33 | "last 1 chrome version", 34 | "last 1 firefox version", 35 | "last 1 safari version" 36 | ] 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Chapter07/MyTable/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Full-Stack-Development-with-Spring-Boot-and-React/f2f6d3034bb30f1d0faa5d6133047e5dd298a672/Chapter07/MyTable/public/favicon.ico -------------------------------------------------------------------------------- /Chapter07/MyTable/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /Chapter07/MyTable/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Full-Stack-Development-with-Spring-Boot-and-React/f2f6d3034bb30f1d0faa5d6133047e5dd298a672/Chapter07/MyTable/public/logo192.png -------------------------------------------------------------------------------- /Chapter07/MyTable/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Full-Stack-Development-with-Spring-Boot-and-React/f2f6d3034bb30f1d0faa5d6133047e5dd298a672/Chapter07/MyTable/public/logo512.png -------------------------------------------------------------------------------- /Chapter07/MyTable/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /Chapter07/MyTable/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /Chapter07/MyTable/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Chapter07/MyTable/src/App.js: -------------------------------------------------------------------------------- 1 | import MyTable from './MyTable'; 2 | 3 | function App() { 4 | return ( 5 | 6 | ); 7 | } 8 | 9 | export default App; 10 | -------------------------------------------------------------------------------- /Chapter07/MyTable/src/App.test.js: -------------------------------------------------------------------------------- 1 | import { render, screen } from '@testing-library/react'; 2 | import App from './App'; 3 | 4 | test('renders learn react link', () => { 5 | render(); 6 | const linkElement = screen.getByText(/learn react/i); 7 | expect(linkElement).toBeInTheDocument(); 8 | }); 9 | -------------------------------------------------------------------------------- /Chapter07/MyTable/src/MyTable.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | function MyTable() { 4 | const data = [ 5 | {brand: 'Ford', model: 'Mustang'}, 6 | {brand: 'VW', model: 'Beetle'}, 7 | {brand: 'Tesla', model: 'Model S'}]; 8 | 9 | return ( 10 |
11 | 12 | 13 | { 14 | data.map((item, index) => 15 | 16 | 17 | ) 18 | } 19 | 20 |
{item.brand}{item.model}
21 |
22 | ); 23 | }; 24 | 25 | export default MyTable; 26 | -------------------------------------------------------------------------------- /Chapter07/MyTable/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /Chapter07/MyTable/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom/client'; 3 | import './index.css'; 4 | import App from './App'; 5 | import reportWebVitals from './reportWebVitals'; 6 | 7 | const root = ReactDOM.createRoot(document.getElementById('root')); 8 | root.render( 9 | 10 | 11 | 12 | ); 13 | 14 | // If you want to start measuring performance in your app, pass a function 15 | // to log results (for example: reportWebVitals(console.log)) 16 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 17 | reportWebVitals(); 18 | -------------------------------------------------------------------------------- /Chapter07/MyTable/src/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Chapter07/MyTable/src/reportWebVitals.js: -------------------------------------------------------------------------------- 1 | const reportWebVitals = onPerfEntry => { 2 | if (onPerfEntry && onPerfEntry instanceof Function) { 3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 4 | getCLS(onPerfEntry); 5 | getFID(onPerfEntry); 6 | getFCP(onPerfEntry); 7 | getLCP(onPerfEntry); 8 | getTTFB(onPerfEntry); 9 | }); 10 | } 11 | }; 12 | 13 | export default reportWebVitals; 14 | -------------------------------------------------------------------------------- /Chapter07/MyTable/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /Chapter08/restgithub/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /Chapter08/restgithub/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "restgithub", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.16.4", 7 | "@testing-library/react": "^13.1.1", 8 | "@testing-library/user-event": "^13.5.0", 9 | "react": "^18.0.0", 10 | "react-dom": "^18.0.0", 11 | "react-scripts": "5.0.1", 12 | "web-vitals": "^2.1.4" 13 | }, 14 | "scripts": { 15 | "start": "react-scripts start", 16 | "build": "react-scripts build", 17 | "test": "react-scripts test", 18 | "eject": "react-scripts eject" 19 | }, 20 | "eslintConfig": { 21 | "extends": [ 22 | "react-app", 23 | "react-app/jest" 24 | ] 25 | }, 26 | "browserslist": { 27 | "production": [ 28 | ">0.2%", 29 | "not dead", 30 | "not op_mini all" 31 | ], 32 | "development": [ 33 | "last 1 chrome version", 34 | "last 1 firefox version", 35 | "last 1 safari version" 36 | ] 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Chapter08/restgithub/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Full-Stack-Development-with-Spring-Boot-and-React/f2f6d3034bb30f1d0faa5d6133047e5dd298a672/Chapter08/restgithub/public/favicon.ico -------------------------------------------------------------------------------- /Chapter08/restgithub/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /Chapter08/restgithub/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Full-Stack-Development-with-Spring-Boot-and-React/f2f6d3034bb30f1d0faa5d6133047e5dd298a672/Chapter08/restgithub/public/logo192.png -------------------------------------------------------------------------------- /Chapter08/restgithub/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Full-Stack-Development-with-Spring-Boot-and-React/f2f6d3034bb30f1d0faa5d6133047e5dd298a672/Chapter08/restgithub/public/logo512.png -------------------------------------------------------------------------------- /Chapter08/restgithub/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /Chapter08/restgithub/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /Chapter08/restgithub/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Chapter08/restgithub/src/App.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import './App.css'; 3 | 4 | function App() { 5 | const [keyword, setKeyword] = useState(''); 6 | const [data, setData] = useState([]); 7 | 8 | const fetchData = () => { 9 | fetch(`https://api.github.com/search/repositories?q=${keyword}`) 10 | .then(response => response.json()) 11 | .then(data => setData(data.items)) 12 | .catch(err => console.error(err)) 13 | } 14 | 15 | return ( 16 |
17 | setKeyword(e.target.value)} /> 19 | 20 | 21 | 22 | { 23 | data.map(repo => 24 | 25 | 26 | 29 | 30 | ) 31 | } 32 | 33 |
{repo.full_name} 27 | {repo.html_url} 28 |
34 |
35 | ); 36 | } 37 | 38 | export default App; 39 | -------------------------------------------------------------------------------- /Chapter08/restgithub/src/App.test.js: -------------------------------------------------------------------------------- 1 | import { render, screen } from '@testing-library/react'; 2 | import App from './App'; 3 | 4 | test('renders learn react link', () => { 5 | render(); 6 | const linkElement = screen.getByText(/learn react/i); 7 | expect(linkElement).toBeInTheDocument(); 8 | }); 9 | -------------------------------------------------------------------------------- /Chapter08/restgithub/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /Chapter08/restgithub/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom/client'; 3 | import './index.css'; 4 | import App from './App'; 5 | import reportWebVitals from './reportWebVitals'; 6 | 7 | const root = ReactDOM.createRoot(document.getElementById('root')); 8 | root.render( 9 | 10 | 11 | 12 | ); 13 | 14 | // If you want to start measuring performance in your app, pass a function 15 | // to log results (for example: reportWebVitals(console.log)) 16 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 17 | reportWebVitals(); 18 | -------------------------------------------------------------------------------- /Chapter08/restgithub/src/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Chapter08/restgithub/src/reportWebVitals.js: -------------------------------------------------------------------------------- 1 | const reportWebVitals = onPerfEntry => { 2 | if (onPerfEntry && onPerfEntry instanceof Function) { 3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 4 | getCLS(onPerfEntry); 5 | getFID(onPerfEntry); 6 | getFCP(onPerfEntry); 7 | getLCP(onPerfEntry); 8 | getTTFB(onPerfEntry); 9 | }); 10 | } 11 | }; 12 | 13 | export default reportWebVitals; 14 | -------------------------------------------------------------------------------- /Chapter08/restgithub/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /Chapter08/weatherapp/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /Chapter08/weatherapp/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "weatherapp", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.16.4", 7 | "@testing-library/react": "^13.1.1", 8 | "@testing-library/user-event": "^13.5.0", 9 | "react": "^18.0.0", 10 | "react-dom": "^18.0.0", 11 | "react-scripts": "5.0.1", 12 | "web-vitals": "^2.1.4" 13 | }, 14 | "scripts": { 15 | "start": "react-scripts start", 16 | "build": "react-scripts build", 17 | "test": "react-scripts test", 18 | "eject": "react-scripts eject" 19 | }, 20 | "eslintConfig": { 21 | "extends": [ 22 | "react-app", 23 | "react-app/jest" 24 | ] 25 | }, 26 | "browserslist": { 27 | "production": [ 28 | ">0.2%", 29 | "not dead", 30 | "not op_mini all" 31 | ], 32 | "development": [ 33 | "last 1 chrome version", 34 | "last 1 firefox version", 35 | "last 1 safari version" 36 | ] 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Chapter08/weatherapp/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Full-Stack-Development-with-Spring-Boot-and-React/f2f6d3034bb30f1d0faa5d6133047e5dd298a672/Chapter08/weatherapp/public/favicon.ico -------------------------------------------------------------------------------- /Chapter08/weatherapp/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /Chapter08/weatherapp/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Full-Stack-Development-with-Spring-Boot-and-React/f2f6d3034bb30f1d0faa5d6133047e5dd298a672/Chapter08/weatherapp/public/logo192.png -------------------------------------------------------------------------------- /Chapter08/weatherapp/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Full-Stack-Development-with-Spring-Boot-and-React/f2f6d3034bb30f1d0faa5d6133047e5dd298a672/Chapter08/weatherapp/public/logo512.png -------------------------------------------------------------------------------- /Chapter08/weatherapp/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /Chapter08/weatherapp/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /Chapter08/weatherapp/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Chapter08/weatherapp/src/App.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import './App.css'; 3 | 4 | function App() { 5 | const [temp, setTemp] = useState(''); 6 | const [desc, setDesc] = useState(''); 7 | const [icon, setIcon] = useState(''); 8 | const [isReady, setReady] = useState(false); 9 | 10 | React.useEffect(() => { 11 | fetch(`http://api.openweathermap.org/data/2.5/weather?q=London&APPID=YOUR_API_KEY&units=metric`) 12 | .then(result => result.json()) 13 | .then(jsonresult => { 14 | setTemp(jsonresult.main.temp); 15 | setDesc(jsonresult.weather[0].main); 16 | setIcon(jsonresult.weather[0].icon); 17 | setReady(true); 18 | }) 19 | .catch(err => console.error(err)) 20 | }, []) 21 | 22 | if (isReady) { 23 | return ( 24 |
25 |

Temperature: {temp} °C

26 |

Description: {desc}

27 | Weather icon 30 |
31 | ); 32 | } 33 | else { 34 | return
Loading...
35 | } 36 | } 37 | export default App; 38 | -------------------------------------------------------------------------------- /Chapter08/weatherapp/src/App.test.js: -------------------------------------------------------------------------------- 1 | import { render, screen } from '@testing-library/react'; 2 | import App from './App'; 3 | 4 | test('renders learn react link', () => { 5 | render(); 6 | const linkElement = screen.getByText(/learn react/i); 7 | expect(linkElement).toBeInTheDocument(); 8 | }); 9 | -------------------------------------------------------------------------------- /Chapter08/weatherapp/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /Chapter08/weatherapp/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom/client'; 3 | import './index.css'; 4 | import App from './App'; 5 | import reportWebVitals from './reportWebVitals'; 6 | 7 | const root = ReactDOM.createRoot(document.getElementById('root')); 8 | root.render( 9 | 10 | 11 | 12 | ); 13 | 14 | // If you want to start measuring performance in your app, pass a function 15 | // to log results (for example: reportWebVitals(console.log)) 16 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 17 | reportWebVitals(); 18 | -------------------------------------------------------------------------------- /Chapter08/weatherapp/src/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Chapter08/weatherapp/src/reportWebVitals.js: -------------------------------------------------------------------------------- 1 | const reportWebVitals = onPerfEntry => { 2 | if (onPerfEntry && onPerfEntry instanceof Function) { 3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 4 | getCLS(onPerfEntry); 5 | getFID(onPerfEntry); 6 | getFCP(onPerfEntry); 7 | getLCP(onPerfEntry); 8 | getTTFB(onPerfEntry); 9 | }); 10 | } 11 | }; 12 | 13 | export default reportWebVitals; 14 | -------------------------------------------------------------------------------- /Chapter08/weatherapp/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /Chapter09/shoppinglist/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /Chapter09/shoppinglist/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "shoppinglist", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@emotion/react": "^11.8.2", 7 | "@emotion/styled": "^11.8.1", 8 | "@mui/material": "^5.6.0", 9 | "@testing-library/jest-dom": "^5.11.4", 10 | "@testing-library/react": "^11.1.0", 11 | "@testing-library/user-event": "^12.1.10", 12 | "react": "^18.0.0", 13 | "react-dom": "^18.0.0", 14 | "react-scripts": "4.0.3", 15 | "web-vitals": "^1.0.1" 16 | }, 17 | "scripts": { 18 | "start": "react-scripts start", 19 | "build": "react-scripts build", 20 | "test": "react-scripts test", 21 | "eject": "react-scripts eject" 22 | }, 23 | "eslintConfig": { 24 | "extends": [ 25 | "react-app", 26 | "react-app/jest" 27 | ] 28 | }, 29 | "browserslist": { 30 | "production": [ 31 | ">0.2%", 32 | "not dead", 33 | "not op_mini all" 34 | ], 35 | "development": [ 36 | "last 1 chrome version", 37 | "last 1 firefox version", 38 | "last 1 safari version" 39 | ] 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Chapter09/shoppinglist/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Full-Stack-Development-with-Spring-Boot-and-React/f2f6d3034bb30f1d0faa5d6133047e5dd298a672/Chapter09/shoppinglist/public/favicon.ico -------------------------------------------------------------------------------- /Chapter09/shoppinglist/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /Chapter09/shoppinglist/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Full-Stack-Development-with-Spring-Boot-and-React/f2f6d3034bb30f1d0faa5d6133047e5dd298a672/Chapter09/shoppinglist/public/logo192.png -------------------------------------------------------------------------------- /Chapter09/shoppinglist/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Full-Stack-Development-with-Spring-Boot-and-React/f2f6d3034bb30f1d0faa5d6133047e5dd298a672/Chapter09/shoppinglist/public/logo512.png -------------------------------------------------------------------------------- /Chapter09/shoppinglist/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /Chapter09/shoppinglist/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /Chapter09/shoppinglist/src/AddItem.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Button from '@mui/material/Button'; 3 | import TextField from '@mui/material/TextField'; 4 | import Dialog from '@mui/material/Dialog'; 5 | import DialogActions from '@mui/material/DialogActions'; 6 | import DialogContent from '@mui/material/DialogContent'; 7 | import DialogTitle from '@mui/material/DialogTitle'; 8 | 9 | function AddItem(props) { 10 | const [open, setOpen] = React.useState(false); 11 | const [item, setItem] = React.useState({ 12 | product: '', 13 | amount:'' 14 | }); 15 | 16 | const handleOpen = () => { 17 | setOpen(true); 18 | } 19 | 20 | const handleClose = () => { 21 | setOpen(false); 22 | } 23 | 24 | const handleChange = (e) => { 25 | setItem({...item, [e.target.name]: e.target.value}) 26 | } 27 | 28 | const addItem = () => { 29 | props.addItem(item); 30 | setItem({product: '', amount: ''}); 31 | handleClose(); 32 | } 33 | 34 | return( 35 |
36 | 39 | 40 | New Item 41 | 42 | 44 | 46 | 47 | 48 | 51 | 54 | 55 | 56 |
57 | ); 58 | } 59 | 60 | export default AddItem; -------------------------------------------------------------------------------- /Chapter09/shoppinglist/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Chapter09/shoppinglist/src/App.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import Container from '@mui/material/Container'; 3 | import AppBar from '@mui/material/AppBar'; 4 | import Toolbar from '@mui/material/Toolbar'; 5 | import Typography from '@mui/material/Typography'; 6 | import Stack from '@mui/material/Stack'; 7 | import List from '@mui/material/List'; 8 | import ListItem from '@mui/material/ListItem'; 9 | import ListItemText from '@mui/material/ListItemText'; 10 | import AddItem from './AddItem'; 11 | 12 | function App() { 13 | const [items, setItems] = useState([]); 14 | 15 | const addItem = (item) => { 16 | setItems([item, ...items]); 17 | } 18 | 19 | return ( 20 | 21 | 22 | 23 | 24 | Shopping List 25 | 26 | 27 | 28 | 29 | 30 | 31 | { 32 | items.map((item, index) => 33 | 34 | 35 | 36 | ) 37 | } 38 | 39 | 40 | 41 | ); 42 | } 43 | 44 | export default App; 45 | -------------------------------------------------------------------------------- /Chapter09/shoppinglist/src/App.test.js: -------------------------------------------------------------------------------- 1 | import { render, screen } from '@testing-library/react'; 2 | import App from './App'; 3 | 4 | test('renders learn react link', () => { 5 | render(); 6 | const linkElement = screen.getByText(/learn react/i); 7 | expect(linkElement).toBeInTheDocument(); 8 | }); 9 | -------------------------------------------------------------------------------- /Chapter09/shoppinglist/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /Chapter09/shoppinglist/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import * as ReactDOMClient from 'react-dom/client'; 3 | import './index.css'; 4 | import App from './App'; 5 | import reportWebVitals from './reportWebVitals'; 6 | 7 | const container = document.getElementById('root'); 8 | 9 | // Create a root. 10 | const root = ReactDOMClient.createRoot(container); 11 | 12 | root.render( 13 | 14 | 15 | 16 | ); 17 | 18 | // If you want to start measuring performance in your app, pass a function 19 | // to log results (for example: reportWebVitals(console.log)) 20 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 21 | reportWebVitals(); 22 | -------------------------------------------------------------------------------- /Chapter09/shoppinglist/src/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Chapter09/shoppinglist/src/reportWebVitals.js: -------------------------------------------------------------------------------- 1 | const reportWebVitals = onPerfEntry => { 2 | if (onPerfEntry && onPerfEntry instanceof Function) { 3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 4 | getCLS(onPerfEntry); 5 | getFID(onPerfEntry); 6 | getFCP(onPerfEntry); 7 | getLCP(onPerfEntry); 8 | getTTFB(onPerfEntry); 9 | }); 10 | } 11 | }; 12 | 13 | export default reportWebVitals; 14 | -------------------------------------------------------------------------------- /Chapter09/shoppinglist/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /Chapter10/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /Chapter10/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "carfront", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@emotion/react": "^11.9.0", 7 | "@emotion/styled": "^11.8.1", 8 | "@mui/material": "^5.6.2", 9 | "@testing-library/jest-dom": "^5.16.1", 10 | "@testing-library/react": "^13.1.1", 11 | "@testing-library/user-event": "^13.5.0", 12 | "react": "^18.0.0", 13 | "react-dom": "^18.0.0", 14 | "react-scripts": "^5.0.1", 15 | "web-vitals": "^2.1.4" 16 | }, 17 | "scripts": { 18 | "start": "react-scripts start", 19 | "build": "react-scripts build", 20 | "test": "react-scripts test", 21 | "eject": "react-scripts eject" 22 | }, 23 | "eslintConfig": { 24 | "extends": [ 25 | "react-app", 26 | "react-app/jest" 27 | ] 28 | }, 29 | "browserslist": { 30 | "production": [ 31 | ">0.2%", 32 | "not dead", 33 | "not op_mini all" 34 | ], 35 | "development": [ 36 | "last 1 chrome version", 37 | "last 1 firefox version", 38 | "last 1 safari version" 39 | ] 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Chapter10/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Full-Stack-Development-with-Spring-Boot-and-React/f2f6d3034bb30f1d0faa5d6133047e5dd298a672/Chapter10/public/favicon.ico -------------------------------------------------------------------------------- /Chapter10/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /Chapter10/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Full-Stack-Development-with-Spring-Boot-and-React/f2f6d3034bb30f1d0faa5d6133047e5dd298a672/Chapter10/public/logo192.png -------------------------------------------------------------------------------- /Chapter10/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Full-Stack-Development-with-Spring-Boot-and-React/f2f6d3034bb30f1d0faa5d6133047e5dd298a672/Chapter10/public/logo512.png -------------------------------------------------------------------------------- /Chapter10/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /Chapter10/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /Chapter10/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Chapter10/src/App.js: -------------------------------------------------------------------------------- 1 | import './App.css'; 2 | import AppBar from '@mui/material/AppBar'; 3 | import Toolbar from '@mui/material/Toolbar'; 4 | import Typography from '@mui/material/Typography'; 5 | 6 | function App() { 7 | return ( 8 |
9 | 10 | 11 | 12 | Carshop 13 | 14 | 15 | 16 |
17 | ); 18 | } 19 | 20 | export default App; 21 | -------------------------------------------------------------------------------- /Chapter10/src/App.test.js: -------------------------------------------------------------------------------- 1 | import { render, screen } from '@testing-library/react'; 2 | import App from './App'; 3 | 4 | test('renders learn react link', () => { 5 | render(); 6 | const linkElement = screen.getByText(/learn react/i); 7 | expect(linkElement).toBeInTheDocument(); 8 | }); 9 | -------------------------------------------------------------------------------- /Chapter10/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /Chapter10/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import * as ReactDOMClient from 'react-dom/client'; 3 | import './index.css'; 4 | import App from './App'; 5 | import reportWebVitals from './reportWebVitals'; 6 | 7 | const container = document.getElementById('root'); 8 | 9 | // Create a root. 10 | const root = ReactDOMClient.createRoot(container); 11 | 12 | root.render( 13 | 14 | 15 | 16 | ); 17 | 18 | // If you want to start measuring performance in your app, pass a function 19 | // to log results (for example: reportWebVitals(console.log)) 20 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 21 | reportWebVitals(); 22 | -------------------------------------------------------------------------------- /Chapter10/src/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Chapter10/src/reportWebVitals.js: -------------------------------------------------------------------------------- 1 | const reportWebVitals = onPerfEntry => { 2 | if (onPerfEntry && onPerfEntry instanceof Function) { 3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 4 | getCLS(onPerfEntry); 5 | getFID(onPerfEntry); 6 | getFCP(onPerfEntry); 7 | getLCP(onPerfEntry); 8 | getTTFB(onPerfEntry); 9 | }); 10 | } 11 | }; 12 | 13 | export default reportWebVitals; 14 | -------------------------------------------------------------------------------- /Chapter10/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /Chapter11/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /Chapter11/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "carmuigrid", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@emotion/react": "^11.9.0", 7 | "@emotion/styled": "^11.8.1", 8 | "@mui/material": "^5.6.2", 9 | "@mui/x-data-grid": "^5.9.0", 10 | "@testing-library/jest-dom": "^5.16.1", 11 | "@testing-library/react": "^13.1.1", 12 | "@testing-library/user-event": "^13.5.0", 13 | "react": "^18.0.0", 14 | "react-dom": "^18.0.0", 15 | "react-scripts": "^5.0.1", 16 | "web-vitals": "^2.1.2" 17 | }, 18 | "scripts": { 19 | "start": "react-scripts start", 20 | "build": "react-scripts build", 21 | "test": "react-scripts test", 22 | "eject": "react-scripts eject" 23 | }, 24 | "eslintConfig": { 25 | "extends": [ 26 | "react-app", 27 | "react-app/jest" 28 | ] 29 | }, 30 | "browserslist": { 31 | "production": [ 32 | ">0.2%", 33 | "not dead", 34 | "not op_mini all" 35 | ], 36 | "development": [ 37 | "last 1 chrome version", 38 | "last 1 firefox version", 39 | "last 1 safari version" 40 | ] 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Chapter11/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Full-Stack-Development-with-Spring-Boot-and-React/f2f6d3034bb30f1d0faa5d6133047e5dd298a672/Chapter11/public/favicon.ico -------------------------------------------------------------------------------- /Chapter11/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /Chapter11/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Full-Stack-Development-with-Spring-Boot-and-React/f2f6d3034bb30f1d0faa5d6133047e5dd298a672/Chapter11/public/logo192.png -------------------------------------------------------------------------------- /Chapter11/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Full-Stack-Development-with-Spring-Boot-and-React/f2f6d3034bb30f1d0faa5d6133047e5dd298a672/Chapter11/public/logo512.png -------------------------------------------------------------------------------- /Chapter11/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /Chapter11/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /Chapter11/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Chapter11/src/App.js: -------------------------------------------------------------------------------- 1 | import './App.css'; 2 | import AppBar from '@mui/material/AppBar'; 3 | import Toolbar from '@mui/material/Toolbar'; 4 | import Typography from '@mui/material/Typography'; 5 | import Carlist from './components/Carlist'; 6 | 7 | function App() { 8 | return ( 9 |
10 | 11 | 12 | 13 | Carshop 14 | 15 | 16 | 17 | 18 |
19 | ); 20 | } 21 | 22 | export default App; 23 | -------------------------------------------------------------------------------- /Chapter11/src/App.test.js: -------------------------------------------------------------------------------- 1 | import { render, screen } from '@testing-library/react'; 2 | import App from './App'; 3 | 4 | test('renders learn react link', () => { 5 | render(); 6 | const linkElement = screen.getByText(/learn react/i); 7 | expect(linkElement).toBeInTheDocument(); 8 | }); 9 | -------------------------------------------------------------------------------- /Chapter11/src/components/AddCar.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import Dialog from '@mui/material/Dialog'; 3 | import DialogActions from '@mui/material/DialogActions'; 4 | import DialogContent from '@mui/material/DialogContent'; 5 | import DialogTitle from '@mui/material/DialogTitle'; 6 | 7 | function AddCar(props) { 8 | const [open, setOpen] = useState(false); 9 | const [car, setCar] = useState({ 10 | brand: '', 11 | model: '', 12 | color: '', 13 | year: '', 14 | fuel: '', 15 | price: '' 16 | }); 17 | 18 | // Open the modal form 19 | const handleClickOpen = () => { 20 | setOpen(true); 21 | }; 22 | 23 | // Close the modal form 24 | const handleClose = () => { 25 | setOpen(false); 26 | }; 27 | 28 | // Save car and close modal form 29 | const handleSave = () => { 30 | props.addCar(car); 31 | handleClose(); 32 | } 33 | 34 | const handleChange = (event) => { 35 | setCar({...car, [event.target.name]: event.target.value}); 36 | } 37 | 38 | return( 39 |
40 | 41 | 42 | New car 43 | 44 |
46 |
48 |
50 |
52 |
54 |
55 | 56 | 57 | 58 | 59 |
60 |
61 | ); 62 | } 63 | 64 | export default AddCar; 65 | -------------------------------------------------------------------------------- /Chapter11/src/components/EditCar.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import Dialog from '@mui/material/Dialog'; 3 | import DialogActions from '@mui/material/DialogActions'; 4 | import DialogContent from '@mui/material/DialogContent'; 5 | import DialogTitle from '@mui/material/DialogTitle'; 6 | 7 | function EditCar(props) { 8 | const [open, setOpen] = useState(false); 9 | const [car, setCar] = useState({ 10 | brand: '', model: '', color: '', 11 | year: '', fuel:'', price: '' 12 | }); 13 | 14 | // Open the modal form and update the car state 15 | const handleClickOpen = () => { 16 | setCar({ 17 | brand: props.data.row.brand, 18 | model: props.data.row.model, 19 | color: props.data.row.color, 20 | year: props.data.row.year, 21 | fuel: props.data.row.fuel, 22 | price: props.data.row.price 23 | }) 24 | setOpen(true); 25 | } 26 | 27 | // Close the modal form 28 | const handleClose = () => { 29 | setOpen(false); 30 | }; 31 | 32 | const handleChange = (event) => { 33 | setCar({...car, 34 | [event.target.name]: event.target.value}); 35 | } 36 | 37 | // Update car and close modal form 38 | const handleSave = () => { 39 | props.updateCar(car, props.data.id); 40 | handleClose(); 41 | } 42 | 43 | return( 44 |
45 | 46 | 47 | Edit car 48 | 49 |
51 |
53 |
55 |
57 |
59 |
60 | 61 | 62 | 63 | 64 |
65 |
66 | ); 67 | } 68 | 69 | export default EditCar; 70 | -------------------------------------------------------------------------------- /Chapter11/src/constants.js: -------------------------------------------------------------------------------- 1 | export const SERVER_URL='http://localhost:8080/'; -------------------------------------------------------------------------------- /Chapter11/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /Chapter11/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import * as ReactDOMClient from 'react-dom/client'; 3 | import './index.css'; 4 | import App from './App'; 5 | import reportWebVitals from './reportWebVitals'; 6 | 7 | const container = document.getElementById('root'); 8 | 9 | // Create a root. 10 | const root = ReactDOMClient.createRoot(container); 11 | 12 | root.render( 13 | 14 | 15 | 16 | ); 17 | 18 | // If you want to start measuring performance in your app, pass a function 19 | // to log results (for example: reportWebVitals(console.log)) 20 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 21 | reportWebVitals(); 22 | -------------------------------------------------------------------------------- /Chapter11/src/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Chapter11/src/reportWebVitals.js: -------------------------------------------------------------------------------- 1 | const reportWebVitals = onPerfEntry => { 2 | if (onPerfEntry && onPerfEntry instanceof Function) { 3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 4 | getCLS(onPerfEntry); 5 | getFID(onPerfEntry); 6 | getFCP(onPerfEntry); 7 | getLCP(onPerfEntry); 8 | getTTFB(onPerfEntry); 9 | }); 10 | } 11 | }; 12 | 13 | export default reportWebVitals; 14 | -------------------------------------------------------------------------------- /Chapter11/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /Chapter12/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /Chapter12/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "carmuigrid", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@emotion/react": "^11.9.0", 7 | "@emotion/styled": "^11.8.1", 8 | "@mui/icons-material": "^5.6.2", 9 | "@mui/material": "^5.6.2", 10 | "@mui/x-data-grid": "^5.9.0", 11 | "@testing-library/jest-dom": "^5.16.1", 12 | "@testing-library/react": "^13.1.1", 13 | "@testing-library/user-event": "^13.5.0", 14 | "react": "^18.0.0", 15 | "react-dom": "^18.0.0", 16 | "react-scripts": "^5.0.1", 17 | "web-vitals": "^2.1.2" 18 | }, 19 | "scripts": { 20 | "start": "react-scripts start", 21 | "build": "react-scripts build", 22 | "test": "react-scripts test", 23 | "eject": "react-scripts eject" 24 | }, 25 | "eslintConfig": { 26 | "extends": [ 27 | "react-app", 28 | "react-app/jest" 29 | ] 30 | }, 31 | "browserslist": { 32 | "production": [ 33 | ">0.2%", 34 | "not dead", 35 | "not op_mini all" 36 | ], 37 | "development": [ 38 | "last 1 chrome version", 39 | "last 1 firefox version", 40 | "last 1 safari version" 41 | ] 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Chapter12/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Full-Stack-Development-with-Spring-Boot-and-React/f2f6d3034bb30f1d0faa5d6133047e5dd298a672/Chapter12/public/favicon.ico -------------------------------------------------------------------------------- /Chapter12/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /Chapter12/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Full-Stack-Development-with-Spring-Boot-and-React/f2f6d3034bb30f1d0faa5d6133047e5dd298a672/Chapter12/public/logo192.png -------------------------------------------------------------------------------- /Chapter12/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Full-Stack-Development-with-Spring-Boot-and-React/f2f6d3034bb30f1d0faa5d6133047e5dd298a672/Chapter12/public/logo512.png -------------------------------------------------------------------------------- /Chapter12/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /Chapter12/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /Chapter12/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Chapter12/src/App.js: -------------------------------------------------------------------------------- 1 | import './App.css'; 2 | import AppBar from '@mui/material/AppBar'; 3 | import Toolbar from '@mui/material/Toolbar'; 4 | import Typography from '@mui/material/Typography'; 5 | import Carlist from './components/Carlist'; 6 | 7 | function App() { 8 | return ( 9 |
10 | 11 | 12 | 13 | Carshop 14 | 15 | 16 | 17 | 18 |
19 | ); 20 | } 21 | 22 | export default App; 23 | -------------------------------------------------------------------------------- /Chapter12/src/App.test.js: -------------------------------------------------------------------------------- 1 | import { render, screen } from '@testing-library/react'; 2 | import App from './App'; 3 | 4 | test('renders learn react link', () => { 5 | render(); 6 | const linkElement = screen.getByText(/learn react/i); 7 | expect(linkElement).toBeInTheDocument(); 8 | }); 9 | -------------------------------------------------------------------------------- /Chapter12/src/components/AddCar.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import Dialog from '@mui/material/Dialog'; 3 | import DialogActions from '@mui/material/DialogActions'; 4 | import DialogContent from '@mui/material/DialogContent'; 5 | import DialogTitle from '@mui/material/DialogTitle'; 6 | import Button from '@mui/material/Button'; 7 | import TextField from '@mui/material/TextField'; 8 | import Stack from '@mui/material/Stack'; 9 | 10 | function AddCar(props) { 11 | const [open, setOpen] = useState(false); 12 | const [car, setCar] = useState({ 13 | brand: '', 14 | model: '', 15 | color: '', 16 | year: '', 17 | fuel: '', 18 | price: '' 19 | }); 20 | 21 | // Open the modal form 22 | const handleClickOpen = () => { 23 | setOpen(true); 24 | }; 25 | 26 | // Close the modal form 27 | const handleClose = () => { 28 | setOpen(false); 29 | }; 30 | 31 | // Save car and close modal form 32 | const handleSave = () => { 33 | props.addCar(car); 34 | handleClose(); 35 | } 36 | 37 | const handleChange = (event) => { 38 | setCar({...car, [event.target.name]: event.target.value}); 39 | } 40 | 41 | return( 42 |
43 | 46 | 47 | New car 48 | 49 | 50 | 53 | 56 | 59 | 62 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 |
73 | ); 74 | } 75 | 76 | export default AddCar; 77 | -------------------------------------------------------------------------------- /Chapter12/src/components/EditCar.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import Dialog from '@mui/material/Dialog'; 3 | import DialogActions from '@mui/material/DialogActions'; 4 | import DialogContent from '@mui/material/DialogContent'; 5 | import DialogTitle from '@mui/material/DialogTitle'; 6 | import Button from '@mui/material/Button'; 7 | import IconButton from '@mui/material/IconButton'; 8 | import EditIcon from '@mui/icons-material/Edit'; 9 | import TextField from '@mui/material/TextField'; 10 | import Stack from '@mui/material/Stack'; 11 | 12 | function EditCar(props) { 13 | const [open, setOpen] = useState(false); 14 | const [car, setCar] = useState({ 15 | brand: '', model: '', color: '', 16 | year: '', fuel:'', price: '' 17 | }); 18 | 19 | // Open the modal form and update the car state 20 | const handleClickOpen = () => { 21 | setCar({ 22 | brand: props.data.row.brand, 23 | model: props.data.row.model, 24 | color: props.data.row.color, 25 | year: props.data.row.year, 26 | fuel: props.data.row.fuel, 27 | price: props.data.row.price 28 | }) 29 | setOpen(true); 30 | } 31 | 32 | // Close the modal form 33 | const handleClose = () => { 34 | setOpen(false); 35 | }; 36 | 37 | const handleChange = (event) => { 38 | setCar({...car, 39 | [event.target.name]: event.target.value}); 40 | } 41 | 42 | // Update car and close modal form 43 | const handleSave = () => { 44 | props.updateCar(car, props.data.id); 45 | handleClose(); 46 | } 47 | 48 | return( 49 |
50 | 51 | 52 | 53 | 54 | Edit car 55 | 56 | 57 | 60 | 63 | 66 | 69 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 |
80 | ); 81 | } 82 | 83 | export default EditCar; 84 | -------------------------------------------------------------------------------- /Chapter12/src/constants.js: -------------------------------------------------------------------------------- 1 | export const SERVER_URL='http://localhost:8080/'; -------------------------------------------------------------------------------- /Chapter12/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /Chapter12/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import * as ReactDOMClient from 'react-dom/client'; 3 | import './index.css'; 4 | import App from './App'; 5 | import reportWebVitals from './reportWebVitals'; 6 | 7 | const container = document.getElementById('root'); 8 | 9 | // Create a root. 10 | const root = ReactDOMClient.createRoot(container); 11 | 12 | root.render( 13 | 14 | 15 | 16 | ); 17 | 18 | // If you want to start measuring performance in your app, pass a function 19 | // to log results (for example: reportWebVitals(console.log)) 20 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 21 | reportWebVitals(); 22 | -------------------------------------------------------------------------------- /Chapter12/src/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Chapter12/src/reportWebVitals.js: -------------------------------------------------------------------------------- 1 | const reportWebVitals = onPerfEntry => { 2 | if (onPerfEntry && onPerfEntry instanceof Function) { 3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 4 | getCLS(onPerfEntry); 5 | getFID(onPerfEntry); 6 | getFCP(onPerfEntry); 7 | getLCP(onPerfEntry); 8 | getTTFB(onPerfEntry); 9 | }); 10 | } 11 | }; 12 | 13 | export default reportWebVitals; 14 | -------------------------------------------------------------------------------- /Chapter12/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /Chapter13/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /Chapter13/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "carmuigrid", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@emotion/react": "^11.9.0", 7 | "@emotion/styled": "^11.8.1", 8 | "@mui/icons-material": "^5.6.2", 9 | "@mui/material": "^5.6.2", 10 | "@mui/x-data-grid": "^5.9.0", 11 | "@testing-library/jest-dom": "^5.16.1", 12 | "@testing-library/react": "^13.1.1", 13 | "@testing-library/user-event": "^13.5.0", 14 | "react": "^18.0.0", 15 | "react-dom": "^18.0.0", 16 | "react-scripts": "^5.0.1", 17 | "web-vitals": "^2.1.2" 18 | }, 19 | "scripts": { 20 | "start": "react-scripts start", 21 | "build": "react-scripts build", 22 | "test": "react-scripts test", 23 | "eject": "react-scripts eject" 24 | }, 25 | "eslintConfig": { 26 | "extends": [ 27 | "react-app", 28 | "react-app/jest" 29 | ] 30 | }, 31 | "browserslist": { 32 | "production": [ 33 | ">0.2%", 34 | "not dead", 35 | "not op_mini all" 36 | ], 37 | "development": [ 38 | "last 1 chrome version", 39 | "last 1 firefox version", 40 | "last 1 safari version" 41 | ] 42 | }, 43 | "devDependencies": { 44 | "react-test-renderer": "^18.0.0" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Chapter13/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Full-Stack-Development-with-Spring-Boot-and-React/f2f6d3034bb30f1d0faa5d6133047e5dd298a672/Chapter13/public/favicon.ico -------------------------------------------------------------------------------- /Chapter13/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /Chapter13/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Full-Stack-Development-with-Spring-Boot-and-React/f2f6d3034bb30f1d0faa5d6133047e5dd298a672/Chapter13/public/logo192.png -------------------------------------------------------------------------------- /Chapter13/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Full-Stack-Development-with-Spring-Boot-and-React/f2f6d3034bb30f1d0faa5d6133047e5dd298a672/Chapter13/public/logo512.png -------------------------------------------------------------------------------- /Chapter13/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /Chapter13/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /Chapter13/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Chapter13/src/App.js: -------------------------------------------------------------------------------- 1 | import './App.css'; 2 | import AppBar from '@mui/material/AppBar'; 3 | import Toolbar from '@mui/material/Toolbar'; 4 | import Typography from '@mui/material/Typography'; 5 | import Carlist from './components/Carlist'; 6 | 7 | function App() { 8 | return ( 9 |
10 | 11 | 12 | 13 | Carshop 14 | 15 | 16 | 17 | 18 |
19 | ); 20 | } 21 | 22 | export default App; 23 | -------------------------------------------------------------------------------- /Chapter13/src/App.test.js: -------------------------------------------------------------------------------- 1 | import { render, screen, fireEvent } from '@testing-library/react'; 2 | import App from './App'; 3 | import AddCar from './components/AddCar'; 4 | import TestRenderer from 'react-test-renderer'; 5 | 6 | test('renders a snapshot', () => { 7 | const tree = TestRenderer.create().toJSON(); 8 | expect(tree).toMatchSnapshot(); 9 | }); 10 | 11 | test('open add car modal form', async () => { 12 | render(); 13 | fireEvent.click(screen.getByText('New Car')); 14 | expect(screen.getByRole('dialog')).toHaveTextContent('New car'); 15 | }); 16 | 17 | 18 | -------------------------------------------------------------------------------- /Chapter13/src/__snapshots__/App.test.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`renders a snapshot 1`] = ` 4 |
5 | 26 |
27 | `; 28 | -------------------------------------------------------------------------------- /Chapter13/src/components/AddCar.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import Dialog from '@mui/material/Dialog'; 3 | import DialogActions from '@mui/material/DialogActions'; 4 | import DialogContent from '@mui/material/DialogContent'; 5 | import DialogTitle from '@mui/material/DialogTitle'; 6 | import Button from '@mui/material/Button'; 7 | import TextField from '@mui/material/TextField'; 8 | import Stack from '@mui/material/Stack'; 9 | 10 | function AddCar(props) { 11 | const [open, setOpen] = useState(false); 12 | const [car, setCar] = useState({ 13 | brand: '', 14 | model: '', 15 | color: '', 16 | year: '', 17 | fuel: '', 18 | price: '' 19 | }); 20 | 21 | // Open the modal form 22 | const handleClickOpen = () => { 23 | setOpen(true); 24 | }; 25 | 26 | // Close the modal form 27 | const handleClose = () => { 28 | setOpen(false); 29 | }; 30 | 31 | // Save car and close modal form 32 | const handleSave = () => { 33 | props.addCar(car); 34 | handleClose(); 35 | } 36 | 37 | const handleChange = (event) => { 38 | setCar({...car, [event.target.name]: event.target.value}); 39 | } 40 | 41 | return( 42 |
43 | 46 | 47 | New car 48 | 49 | 50 | 53 | 56 | 59 | 62 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 |
73 | ); 74 | } 75 | 76 | export default AddCar; 77 | -------------------------------------------------------------------------------- /Chapter13/src/constants.js: -------------------------------------------------------------------------------- 1 | export const SERVER_URL='http://localhost:8080/'; -------------------------------------------------------------------------------- /Chapter13/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /Chapter13/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import * as ReactDOMClient from 'react-dom/client'; 3 | import './index.css'; 4 | import App from './App'; 5 | import reportWebVitals from './reportWebVitals'; 6 | 7 | const container = document.getElementById('root'); 8 | 9 | // Create a root. 10 | const root = ReactDOMClient.createRoot(container); 11 | 12 | root.render( 13 | 14 | 15 | 16 | ); 17 | 18 | // If you want to start measuring performance in your app, pass a function 19 | // to log results (for example: reportWebVitals(console.log)) 20 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 21 | reportWebVitals(); 22 | -------------------------------------------------------------------------------- /Chapter13/src/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Chapter13/src/reportWebVitals.js: -------------------------------------------------------------------------------- 1 | const reportWebVitals = onPerfEntry => { 2 | if (onPerfEntry && onPerfEntry instanceof Function) { 3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 4 | getCLS(onPerfEntry); 5 | getFID(onPerfEntry); 6 | getFCP(onPerfEntry); 7 | getLCP(onPerfEntry); 8 | getTTFB(onPerfEntry); 9 | }); 10 | } 11 | }; 12 | 13 | export default reportWebVitals; 14 | -------------------------------------------------------------------------------- /Chapter13/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /Chapter14/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /Chapter14/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "carmuigrid", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@emotion/react": "^11.9.0", 7 | "@emotion/styled": "^11.8.1", 8 | "@mui/icons-material": "^5.6.2", 9 | "@mui/material": "^5.6.2", 10 | "@mui/x-data-grid": "^5.9.0", 11 | "@testing-library/jest-dom": "^5.16.1", 12 | "@testing-library/react": "^13.1.1", 13 | "@testing-library/user-event": "^13.5.0", 14 | "react": "^18.0.0", 15 | "react-dom": "^18.0.0", 16 | "react-scripts": "^5.0.1", 17 | "web-vitals": "^2.1.2" 18 | }, 19 | "scripts": { 20 | "start": "react-scripts start", 21 | "build": "react-scripts build", 22 | "test": "react-scripts test", 23 | "eject": "react-scripts eject" 24 | }, 25 | "eslintConfig": { 26 | "extends": [ 27 | "react-app", 28 | "react-app/jest" 29 | ] 30 | }, 31 | "browserslist": { 32 | "production": [ 33 | ">0.2%", 34 | "not dead", 35 | "not op_mini all" 36 | ], 37 | "development": [ 38 | "last 1 chrome version", 39 | "last 1 firefox version", 40 | "last 1 safari version" 41 | ] 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Chapter14/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Full-Stack-Development-with-Spring-Boot-and-React/f2f6d3034bb30f1d0faa5d6133047e5dd298a672/Chapter14/public/favicon.ico -------------------------------------------------------------------------------- /Chapter14/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /Chapter14/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Full-Stack-Development-with-Spring-Boot-and-React/f2f6d3034bb30f1d0faa5d6133047e5dd298a672/Chapter14/public/logo192.png -------------------------------------------------------------------------------- /Chapter14/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Full-Stack-Development-with-Spring-Boot-and-React/f2f6d3034bb30f1d0faa5d6133047e5dd298a672/Chapter14/public/logo512.png -------------------------------------------------------------------------------- /Chapter14/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /Chapter14/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /Chapter14/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Chapter14/src/App.js: -------------------------------------------------------------------------------- 1 | import './App.css'; 2 | import AppBar from '@mui/material/AppBar'; 3 | import Toolbar from '@mui/material/Toolbar'; 4 | import Typography from '@mui/material/Typography'; 5 | import Login from './components/Login'; 6 | 7 | function App() { 8 | return ( 9 |
10 | 11 | 12 | 13 | Carshop 14 | 15 | 16 | 17 | 18 |
19 | ); 20 | } 21 | 22 | export default App; 23 | -------------------------------------------------------------------------------- /Chapter14/src/App.test.js: -------------------------------------------------------------------------------- 1 | import { render, screen } from '@testing-library/react'; 2 | import App from './App'; 3 | 4 | test('renders learn react link', () => { 5 | render(); 6 | const linkElement = screen.getByText(/learn react/i); 7 | expect(linkElement).toBeInTheDocument(); 8 | }); 9 | -------------------------------------------------------------------------------- /Chapter14/src/components/AddCar.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import Dialog from '@mui/material/Dialog'; 3 | import DialogActions from '@mui/material/DialogActions'; 4 | import DialogContent from '@mui/material/DialogContent'; 5 | import DialogTitle from '@mui/material/DialogTitle'; 6 | import Button from '@mui/material/Button'; 7 | import TextField from '@mui/material/TextField'; 8 | import Stack from '@mui/material/Stack'; 9 | 10 | function AddCar(props) { 11 | const [open, setOpen] = useState(false); 12 | const [car, setCar] = useState({ 13 | brand: '', 14 | model: '', 15 | color: '', 16 | year: '', 17 | fuel: '', 18 | price: '' 19 | }); 20 | 21 | // Open the modal form 22 | const handleClickOpen = () => { 23 | setOpen(true); 24 | }; 25 | 26 | // Close the modal form 27 | const handleClose = () => { 28 | setOpen(false); 29 | }; 30 | 31 | const handleChange = (event) => { 32 | setCar({...car, [event.target.name]: event.target.value}); 33 | } 34 | 35 | // Save car and close modal form 36 | const handleSave = () => { 37 | props.addCar(car); 38 | handleClose(); 39 | } 40 | 41 | return( 42 |
43 | 46 | 47 | New car 48 | 49 | 50 | 53 | 56 | 59 | 62 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 |
73 | ); 74 | } 75 | 76 | export default AddCar; 77 | -------------------------------------------------------------------------------- /Chapter14/src/components/EditCar.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import Dialog from '@mui/material/Dialog'; 3 | import DialogActions from '@mui/material/DialogActions'; 4 | import DialogContent from '@mui/material/DialogContent'; 5 | import DialogTitle from '@mui/material/DialogTitle'; 6 | import Button from '@mui/material/Button'; 7 | import IconButton from '@mui/material/IconButton'; 8 | import EditIcon from '@mui/icons-material/Edit'; 9 | import TextField from '@mui/material/TextField'; 10 | import Stack from '@mui/material/Stack'; 11 | 12 | function EditCar(props) { 13 | const [open, setOpen] = useState(false); 14 | const [car, setCar] = useState({ 15 | brand: '', model: '', color: '', 16 | year: '', fuel:'', price: '' 17 | }); 18 | 19 | // Open the modal form and update the car state 20 | const handleClickOpen = () => { 21 | setCar({ 22 | brand: props.data.row.brand, 23 | model: props.data.row.model, 24 | color: props.data.row.color, 25 | year: props.data.row.year, 26 | fuel: props.data.row.fuel, 27 | price: props.data.row.price 28 | }) 29 | setOpen(true); 30 | } 31 | 32 | // Close the modal form 33 | const handleClose = () => { 34 | setOpen(false); 35 | }; 36 | 37 | const handleChange = (event) => { 38 | setCar({...car, 39 | [event.target.name]: event.target.value}); 40 | } 41 | 42 | // Update car and close modal form 43 | const handleSave = () => { 44 | props.updateCar(car, props.data.id); 45 | handleClose(); 46 | } 47 | 48 | return( 49 |
50 | 51 | 52 | 53 | 54 | Edit car 55 | 56 | 57 | 60 | 63 | 66 | 69 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 |
80 | ); 81 | } 82 | 83 | export default EditCar; -------------------------------------------------------------------------------- /Chapter14/src/components/Login.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import Button from '@mui/material/Button'; 3 | import TextField from '@mui/material/TextField'; 4 | import Stack from '@mui/material/Stack'; 5 | import Carlist from './Carlist'; 6 | import Snackbar from '@mui/material/Snackbar'; 7 | 8 | import { SERVER_URL } from '../constants.js'; 9 | 10 | function Login() { 11 | const [user, setUser] = useState({ 12 | username: '', 13 | password: '' 14 | }); 15 | const [isAuthenticated, setAuth] = useState(false); 16 | const [open, setOpen] = useState(false); 17 | 18 | const handleChange = (event) => { 19 | setUser({...user, [event.target.name] : event.target.value}); 20 | } 21 | 22 | const login = () => { 23 | fetch(SERVER_URL + 'login', { 24 | method: 'POST', 25 | headers: { 'Content-Type':'application/json' }, 26 | body: JSON.stringify(user) 27 | }) 28 | .then(res => { 29 | const jwtToken = res.headers.get('Authorization'); 30 | if (jwtToken !== null) { 31 | sessionStorage.setItem("jwt", jwtToken); 32 | setAuth(true); 33 | } 34 | else { 35 | setOpen(true); 36 | } 37 | }) 38 | .catch(err => console.error(err)) 39 | } 40 | 41 | if (isAuthenticated) { 42 | return ; 43 | } 44 | else { 45 | return( 46 |
47 | 48 | 52 | 57 | 63 | 64 | setOpen(false)} 68 | message="Login failed: Check your username and password" 69 | /> 70 |
71 | ); 72 | } 73 | } 74 | 75 | export default Login; 76 | -------------------------------------------------------------------------------- /Chapter14/src/constants.js: -------------------------------------------------------------------------------- 1 | export const SERVER_URL='http://localhost:8080/'; -------------------------------------------------------------------------------- /Chapter14/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /Chapter14/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import * as ReactDOMClient from 'react-dom/client'; 3 | import './index.css'; 4 | import App from './App'; 5 | import reportWebVitals from './reportWebVitals'; 6 | 7 | const container = document.getElementById('root'); 8 | // Create a root. 9 | const root = ReactDOMClient.createRoot(container); 10 | 11 | root.render( 12 | 13 | 14 | 15 | ); 16 | 17 | // If you want to start measuring performance in your app, pass a function 18 | // to log results (for example: reportWebVitals(console.log)) 19 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 20 | reportWebVitals(); 21 | -------------------------------------------------------------------------------- /Chapter14/src/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Chapter14/src/reportWebVitals.js: -------------------------------------------------------------------------------- 1 | const reportWebVitals = onPerfEntry => { 2 | if (onPerfEntry && onPerfEntry instanceof Function) { 3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 4 | getCLS(onPerfEntry); 5 | getFID(onPerfEntry); 6 | getFCP(onPerfEntry); 7 | getLCP(onPerfEntry); 8 | getTTFB(onPerfEntry); 9 | }); 10 | } 11 | }; 12 | 13 | export default reportWebVitals; 14 | -------------------------------------------------------------------------------- /Chapter14/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /Chapter15/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM adoptopenjdk/openjdk11:latest 2 | VOLUME /tmp 3 | EXPOSE 8080 4 | ARG JAR FILE 5 | COPY target/cardatabase-0.0.1-SNAPSHOT.jar app.jar 6 | ENTRYPOINT ["java","-jar","/app.jar"] -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Packt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | --------------------------------------------------------------------------------