diff --git a/back-skeleton/.mvn/wrapper/maven-wrapper.jar b/back-skeleton/.mvn/wrapper/maven-wrapper.jar deleted file mode 100644 index cb28b0e37c7d206feb564310fdeec0927af4123a..0000000000000000000000000000000000000000 Binary files a/back-skeleton/.mvn/wrapper/maven-wrapper.jar and /dev/null differ diff --git a/back-skeleton/.mvn/wrapper/maven-wrapper.properties b/back-skeleton/.mvn/wrapper/maven-wrapper.properties deleted file mode 100644 index 2e76e189d2c795e3959d558905c2f111f053d7d2..0000000000000000000000000000000000000000 --- a/back-skeleton/.mvn/wrapper/maven-wrapper.properties +++ /dev/null @@ -1,2 +0,0 @@ -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.4/apache-maven-3.9.4-bin.zip -wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar diff --git a/back-skeleton/initdb/2_DEFAULT_ENTRIES.sql b/back-skeleton/initdb/2_DEFAULT_ENTRIES.sql index ae5925afbdbdd1ba3f9bb0a635c2fc7bfcd1d9e5..709ae5f17e1efe69b397acbc146690e082e6cf2a 100644 --- a/back-skeleton/initdb/2_DEFAULT_ENTRIES.sql +++ b/back-skeleton/initdb/2_DEFAULT_ENTRIES.sql @@ -1,8 +1,25 @@ -INSERT INTO majors (id, name, description) VALUES (1, 'MIN', 'Ouaiiis du code partout'); +INSERT INTO majors (id, name, description) VALUES (1, 'Ingéniérie du Numérique', 'Ouaiiis du code partout'); +INSERT INTO majors (id, name, description) VALUES (2, 'Structure & Matériaux', 'Beaucoup de béton et des poutres (snif elle a été renomée)'); +INSERT INTO majors (id, name, description) VALUES (3, 'Aéronautique & Espace', 'Vive le vent'); +INSERT INTO majors (id, name, description) VALUES (4, 'Data Engineering', 'Trop cool plein de données à ordonner'); +INSERT INTO majors (id, name, description) VALUES (5, 'Energie & Environnement', 'On est full green'); +INSERT INTO majors (id, name, description) VALUES (6, 'Engineering Management', 'Des managers de qualité'); +INSERT INTO majors (id, name, description) VALUES (7, 'Ingénierie & Santé', 'On connait tous les os et tous les muscles du corps humain'); +INSERT INTO majors (id, name, description) VALUES (8, 'Ingénierie & Architecture durable', 'Objectif 0 carbon'); +INSERT INTO majors (id, name, description) VALUES (9, 'Design Industriel Durable', 'Ca existait pas pour la P2022 ça'); -INSERT INTO students (id, first_name, last_name, birthdate, major_id, image) VALUES (1, 'Paul', 'Harrohide', '2002-06-15', 1, null); +INSERT INTO students (id, first_name, last_name, birthdate, major_id) VALUES (1, 'Paul', 'Harrohide', '2002-06-15', 1); +INSERT INTO students (id, first_name, last_name, birthdate, major_id) VALUES (2, 'Jean', 'Bonbeur', '2001-08-21', 1); +INSERT INTO students (id, first_name, last_name, birthdate, major_id) VALUES (3, 'Alain', 'Térieur', '2000-01-11', 1); -INSERT INTO courses (id, name, hours) VALUES (1, 'Java', 30); -INSERT INTO student_course (id, student_id, course_id) VALUES (1, 1, 1); +INSERT INTO courses (id, name, hours) VALUES (1, 'Spanish', 30); +INSERT INTO courses (id, name, hours) VALUES (2, 'German', 30); +INSERT INTO courses (id, name, hours) VALUES (3, 'Internet of Things', 30); +INSERT INTO courses (id, name, hours) VALUES (4, 'Thermodynamic', 30); +INSERT INTO courses (id, name, hours) VALUES (5, 'Anatomy', 30); +INSERT INTO courses (id, name, hours) VALUES (6, 'Maths', 30); +INSERT INTO courses (id, name, hours) VALUES (7, 'Java', 30); +INSERT INTO courses (id, name, hours) VALUES (8, 'Lean Management', 30); +INSERT INTO student_course (id, student_id, course_id) VALUES (1, 1, 7); diff --git a/back-skeleton/src/main/java/com/takima/backskeleton/DAO/CourseDao.java b/back-skeleton/src/main/java/com/takima/backskeleton/DAO/CourseDao.java new file mode 100644 index 0000000000000000000000000000000000000000..97657ed4e359b6a7ad61b2ce7c08fb838303a65f --- /dev/null +++ b/back-skeleton/src/main/java/com/takima/backskeleton/DAO/CourseDao.java @@ -0,0 +1,9 @@ +package com.takima.backskeleton.DAO; + +import com.takima.backskeleton.models.Course; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface CourseDao extends JpaRepository<Course, Long> { +} diff --git a/back-skeleton/src/main/java/com/takima/backskeleton/DTO/StudentDto.java b/back-skeleton/src/main/java/com/takima/backskeleton/DTO/StudentDto.java index f92a77828934868723bc4a490c0d8938260006c9..f0a938e4e71220209be8dac51139331a4cdb4d3d 100644 --- a/back-skeleton/src/main/java/com/takima/backskeleton/DTO/StudentDto.java +++ b/back-skeleton/src/main/java/com/takima/backskeleton/DTO/StudentDto.java @@ -17,5 +17,4 @@ public class StudentDto { private Instant birthdate; private List<Course> courses; private Major major; - private MultipartFile image; } diff --git a/back-skeleton/src/main/java/com/takima/backskeleton/DTO/StudentMapper.java b/back-skeleton/src/main/java/com/takima/backskeleton/DTO/StudentMapper.java index f2f8aab8bbdbe4cb3fc66a2e61fc225785ad0cd6..17a583bdab7c46bb0ec5ce602ff7bcdd87fe8ff9 100644 --- a/back-skeleton/src/main/java/com/takima/backskeleton/DTO/StudentMapper.java +++ b/back-skeleton/src/main/java/com/takima/backskeleton/DTO/StudentMapper.java @@ -13,7 +13,6 @@ public class StudentMapper { .birthdate(dto.getBirthdate()) .courses(dto.getCourses()) .major(dto.getMajor()) - .image(dto.getImage().isEmpty() ? dto.getImage().getBytes() : null) .build(); } diff --git a/back-skeleton/src/main/java/com/takima/backskeleton/controllers/CourseController.java b/back-skeleton/src/main/java/com/takima/backskeleton/controllers/CourseController.java new file mode 100644 index 0000000000000000000000000000000000000000..b7425bf7a017facb226767951d6f47b29089e1b2 --- /dev/null +++ b/back-skeleton/src/main/java/com/takima/backskeleton/controllers/CourseController.java @@ -0,0 +1,24 @@ +package com.takima.backskeleton.controllers; + +import com.takima.backskeleton.models.Course; +import com.takima.backskeleton.services.CourseService; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +@CrossOrigin +@RequestMapping("courses") +@RestController +@RequiredArgsConstructor +public class CourseController { + private final CourseService courseService; + + @GetMapping("") + public List<Course> getAllCourses() { + return courseService.findAll(); + } +} diff --git a/back-skeleton/src/main/java/com/takima/backskeleton/controllers/StudentController.java b/back-skeleton/src/main/java/com/takima/backskeleton/controllers/StudentController.java index 91fac9fce148445704a630ac8a0dafa851e3ded6..4508fa5334c0b32c39e9232cbdcb9d822fc5aec3 100644 --- a/back-skeleton/src/main/java/com/takima/backskeleton/controllers/StudentController.java +++ b/back-skeleton/src/main/java/com/takima/backskeleton/controllers/StudentController.java @@ -5,6 +5,7 @@ import com.takima.backskeleton.models.Student; import com.takima.backskeleton.services.StudentService; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; import java.util.List; @@ -22,6 +23,11 @@ public class StudentController { return studentService.findAll(); } + @GetMapping("/{id}") + public Student getStudentById(@PathVariable Long id) { + return studentService.getById(id); + } + @DeleteMapping("/{id}") public void deleteStudent(@PathVariable Long id) { studentService.deleteById(id); diff --git a/back-skeleton/src/main/java/com/takima/backskeleton/models/Student.java b/back-skeleton/src/main/java/com/takima/backskeleton/models/Student.java index 894e4ec00a7ec6e93d63d42ab3c526f5725c9a5c..59e05c03efb417b06549999a0f82e2e14e6f7e98 100644 --- a/back-skeleton/src/main/java/com/takima/backskeleton/models/Student.java +++ b/back-skeleton/src/main/java/com/takima/backskeleton/models/Student.java @@ -24,11 +24,9 @@ public class Student { joinColumns = @JoinColumn(name = "student_id"), inverseJoinColumns = @JoinColumn(name = "course_id")) private List<Course> courses; - @ManyToOne() + @ManyToOne(cascade = CascadeType.MERGE) @JoinColumn(name = "major_id") private Major major; - @Column(name = "image") - private byte[] image; private Student(Builder builder) { this.id = builder.id; @@ -37,7 +35,6 @@ public class Student { this.birthdate = builder.birthdate; this.courses = builder.courses; this.major = builder.major; - this.image = builder.image; } public Student() { } @@ -49,7 +46,6 @@ public class Student { private Instant birthdate; private List<Course> courses; private Major major; - private byte[] image; public Builder id (Long id) { this.id = id; @@ -76,10 +72,6 @@ public class Student { this.birthdate = birthdate; return this; } - public Builder image(byte[] image) { - this.image = image; - return this; - } public Student build() { return new Student(this); diff --git a/back-skeleton/src/main/java/com/takima/backskeleton/services/CourseService.java b/back-skeleton/src/main/java/com/takima/backskeleton/services/CourseService.java new file mode 100644 index 0000000000000000000000000000000000000000..68a553c6e7b69b8a648caa22515ec22cc1598be9 --- /dev/null +++ b/back-skeleton/src/main/java/com/takima/backskeleton/services/CourseService.java @@ -0,0 +1,20 @@ +package com.takima.backskeleton.services; + +import com.takima.backskeleton.DAO.CourseDao; +import com.takima.backskeleton.models.Course; +import com.takima.backskeleton.models.Major; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; + +@Component +@RequiredArgsConstructor +public class CourseService { + private final CourseDao courseDao; + + public List<Course> findAll() { + return courseDao.findAll(); + } +} diff --git a/back-skeleton/src/main/java/com/takima/backskeleton/services/StudentService.java b/back-skeleton/src/main/java/com/takima/backskeleton/services/StudentService.java index 21cb0d1fe765562d8fd54a7bbd22889634fe3e8c..cc1e205bb02d50f5582d630d017db84fd1e7f5d4 100644 --- a/back-skeleton/src/main/java/com/takima/backskeleton/services/StudentService.java +++ b/back-skeleton/src/main/java/com/takima/backskeleton/services/StudentService.java @@ -6,13 +6,15 @@ import com.takima.backskeleton.DTO.StudentMapper; import com.takima.backskeleton.models.Student; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.NoSuchElementException; -@Component +@Service @RequiredArgsConstructor public class StudentService { private final StudentDao studentDao; @@ -24,10 +26,16 @@ public class StudentService { return users ; } + public Student getById(Long id) { + return studentDao.findById(id).orElseThrow(); + } + + @Transactional public void deleteById(Long id) { studentDao.deleteById(id); } + @Transactional public void addStudent(StudentDto studentDto) { Student student; try { @@ -35,9 +43,11 @@ public class StudentService { } catch (IOException e) { throw new RuntimeException("Error with Student image", e); } + studentDao.save(student); } + @Transactional public void updateStudent(StudentDto studentDto, Long id) { studentDao.findById(id) .orElseThrow(() -> new NoSuchElementException("Student doesn't exist")); diff --git a/back-skeleton/src/main/resources/application.properties b/back-skeleton/src/main/resources/application.properties index ac2ecdf2a50f49d3b5d285f39d058ee3aa3ec43e..fa51bd1222e8582f6ce7ce4505355d904e98ea46 100644 --- a/back-skeleton/src/main/resources/application.properties +++ b/back-skeleton/src/main/resources/application.properties @@ -1,3 +1,5 @@ spring.datasource.url=jdbc:postgresql://localhost:5432/${DATABASE_NAME} spring.datasource.username=${DATABASE_USER} spring.datasource.password=${DATABASE_PASSWORD} +spring.servlet.multipart.max-file-size=10MB +spring.servlet.multipart.max-request-size=10MB \ No newline at end of file diff --git a/epf-front-skeleton-main/src/app/app-routing.module.ts b/epf-front-skeleton-main/src/app/app-routing.module.ts index 544f3a97e0c9b0d7865dabc28c7e7228c8cc3163..8c70ab9e03e7a2240fe7f755a195626ec105b66b 100644 --- a/epf-front-skeleton-main/src/app/app-routing.module.ts +++ b/epf-front-skeleton-main/src/app/app-routing.module.ts @@ -1,14 +1,14 @@ import { NgModule } from "@angular/core" import { RouterModule, Routes } from "@angular/router" -import { HomeComponent } from "./home/home.component" -import { StudentsComponent } from "./students/students.component" -import { StudentsResolver } from "./students/students.resolver" -import { StudentDetailsComponent } from "./students/student-details/student-details.component" -import { StudentDetailsResolver } from "./students/student-details/student-details.resolver" -import { MajorsComponent } from "./majors/majors.component" -import { MajorsResolver } from "./majors/majors.resolver" -import { MajorStudentsResolver } from "./majors/major-students/major-students.resolver" -import { MajorStudentsComponent } from "./majors/major-students/major-students.component" +import { HomeComponent } from "home/home.component" +import { StudentsComponent } from "students/students.component" +import { StudentsResolver } from "students/students.resolver" +import { StudentDetailsComponent } from "students/student-details/student-details.component" +import { StudentDetailsResolver } from "students/student-details/student-details.resolver" +import { MajorsComponent } from "majors/majors.component" +import { MajorsResolver } from "majors/majors.resolver" +import { MajorStudentsResolver } from "majors/major-students/major-students.resolver" +import { MajorStudentsComponent } from "majors/major-students/major-students.component" const routes: Routes = [ { path: "", component: HomeComponent }, @@ -46,4 +46,5 @@ const routes: Routes = [ imports: [RouterModule.forRoot(routes)], exports: [RouterModule], }) -export class AppRoutingModule {} +export class AppRoutingModule { +} diff --git a/epf-front-skeleton-main/src/app/app.component.ts b/epf-front-skeleton-main/src/app/app.component.ts index 3a4f5713e3f058b0f2cd1d0aecbd4b74ca1c18f4..ced496c121cc4cfcb44cc2d381e224f8331ee9c3 100644 --- a/epf-front-skeleton-main/src/app/app.component.ts +++ b/epf-front-skeleton-main/src/app/app.component.ts @@ -1,10 +1,10 @@ -import { Component } from '@angular/core'; +import { Component } from "@angular/core" @Component({ - selector: 'epf-root', - templateUrl: './app.component.html', - styleUrls: ['./app.component.scss'] + selector: "epf-root", + templateUrl: "./app.component.html", + styleUrls: ["./app.component.scss"], }) export class AppComponent { - title = 'epf-front-skeleton'; + title = "epf-front-skeleton" } diff --git a/epf-front-skeleton-main/src/app/app.module.ts b/epf-front-skeleton-main/src/app/app.module.ts index 29b78a663b1188ccb3be6743c03a471c51e920ec..9369f0eea830a0fe0576e511d3fe5de2b8e8d35e 100644 --- a/epf-front-skeleton-main/src/app/app.module.ts +++ b/epf-front-skeleton-main/src/app/app.module.ts @@ -1,20 +1,20 @@ import { NgModule } from "@angular/core" import { BrowserModule } from "@angular/platform-browser" -import { AppRoutingModule } from "./app-routing.module" -import { AppComponent } from "./app.component" +import { AppRoutingModule } from "app-routing.module" +import { AppComponent } from "app.component" import { BrowserAnimationsModule } from "@angular/platform-browser/animations" -import { NavbarComponent } from "./navbar/navbar.component" +import { NavbarComponent } from "navbar/navbar.component" import { MatListModule } from "@angular/material/list" -import { HomeComponent } from "./home/home.component" -import { StudentsComponent } from "./students/students.component" -import { StudentDetailsComponent } from "./students/student-details/student-details.component" +import { HomeComponent } from "home/home.component" +import { StudentsComponent } from "students/students.component" +import { StudentDetailsComponent } from "students/student-details/student-details.component" import { FormsModule } from "@angular/forms" import { MatIconModule } from "@angular/material/icon" import { MatButtonModule } from "@angular/material/button" -import { MajorsComponent } from "./majors/majors.component" -import { MajorStudentsComponent } from "./majors/major-students/major-students.component" -import { ResearchComponent } from "./students/research/research.component" +import { MajorsComponent } from "majors/majors.component" +import { MajorStudentsComponent } from "majors/major-students/major-students.component" +import { HttpClientModule } from "@angular/common/http" @NgModule({ declarations: [ @@ -25,7 +25,6 @@ import { ResearchComponent } from "./students/research/research.component" StudentDetailsComponent, MajorsComponent, MajorStudentsComponent, - ResearchComponent, ], imports: [ BrowserModule, @@ -35,8 +34,10 @@ import { ResearchComponent } from "./students/research/research.component" FormsModule, MatIconModule, MatButtonModule, + HttpClientModule, ], providers: [], bootstrap: [AppComponent], }) -export class AppModule {} +export class AppModule { +} diff --git a/epf-front-skeleton-main/src/app/home/home.component.html b/epf-front-skeleton-main/src/app/home/home.component.html index f77490567020a6e7017325d5c267ee20a533bbe2..8b7b71e2c6de813301ca91347fe03c31e42192d6 100644 --- a/epf-front-skeleton-main/src/app/home/home.component.html +++ b/epf-front-skeleton-main/src/app/home/home.component.html @@ -24,7 +24,8 @@ </div> </div> </div> - <p>Nous sommes là pour t'aider et t'accompagner pendant 4 journées de TP. N'hésite pas si tu as la moindre question ! </p> + <p>Nous sommes là pour t'aider et t'accompagner pendant 4 journées de TP. N'hésite pas si tu as la moindre question + ! </p> </div> <div class="right"> <img src="assets/homepage-cat.png"> diff --git a/epf-front-skeleton-main/src/app/home/home.component.scss b/epf-front-skeleton-main/src/app/home/home.component.scss index ef32192602d13edcfb7e95403e01c771dc825a11..9da57dfe5dc1507bdf2f0246e38e498a4e528532 100644 --- a/epf-front-skeleton-main/src/app/home/home.component.scss +++ b/epf-front-skeleton-main/src/app/home/home.component.scss @@ -1,7 +1,8 @@ -:host{ +:host { display: flex; align-items: center; - margin : 25px ; + margin: 25px; + .title { text-align: center; font-family: Caveat, sans-serif; @@ -9,16 +10,19 @@ font-weight: 700; margin: 30px 0; } + p { text-align: center; margin-top: 30px; - font-size : 1.3em; + font-size: 1.3em; } + .left { width: 50%; height: 100%; display: flex; flex-direction: column; + .sun { width: 90px; margin-left: 35px; @@ -28,17 +32,20 @@ border: none; display: flex; align-items: baseline; + .card-text { font-family: "Dancing Script", sans-serif; - font-size : x-large; - margin-top : 0 + font-size: x-large; + margin-top: 0 } } } + .right { width: 50%; display: flex; justify-content: center; + img { width: 80%; } diff --git a/epf-front-skeleton-main/src/app/home/home.component.ts b/epf-front-skeleton-main/src/app/home/home.component.ts index c577f9c83ed708192c142cbfdbd28eccc34404d3..43c55fdb8e5923640d3c890c6139a315924df033 100644 --- a/epf-front-skeleton-main/src/app/home/home.component.ts +++ b/epf-front-skeleton-main/src/app/home/home.component.ts @@ -1,13 +1,14 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit } from "@angular/core" @Component({ - selector: 'epf-home', - templateUrl: './home.component.html', - styleUrls: ['./home.component.scss'] + selector: "epf-home", + templateUrl: "./home.component.html", + styleUrls: ["./home.component.scss"], }) export class HomeComponent implements OnInit { - constructor() { } + constructor() { + } ngOnInit(): void { } diff --git a/epf-front-skeleton-main/src/app/majors/major-students/major-students.component.html b/epf-front-skeleton-main/src/app/majors/major-students/major-students.component.html index a6eb493b52b03b73741c499466f81208478de766..eaa1ff0d97c57817e5081b817545804f6a416464 100644 --- a/epf-front-skeleton-main/src/app/majors/major-students/major-students.component.html +++ b/epf-front-skeleton-main/src/app/majors/major-students/major-students.component.html @@ -12,12 +12,13 @@ </thead> <tbody> <ng-container *ngIf="studentsFromMajor$ | async; let studentsFromMajor"> - <tr *ngFor="let student of (studentsFromMajor.students)"> - <td>{{ student.firstName }}</td> - <td>{{ student.lastName }}</td> - <td>{{ student.birthDate | date : "dd/MM/yyyy" }}</td> - <td>{{ student.major!!.name }}</td> - </tr> + <h2 *ngIf="studentsFromMajor.length === 0">Aucun étudiant dans cette Majeure</h2> + <tr *ngFor="let student of (studentsFromMajor)"> + <td>{{ student.firstName }}</td> + <td>{{ student.lastName }}</td> + <td>{{ student.birthdate | date : "dd/MM/yyyy" }}</td> + <td>{{ student.major!!.name }}</td> + </tr> </ng-container> </tbody> </table> diff --git a/epf-front-skeleton-main/src/app/majors/major-students/major-students.component.scss b/epf-front-skeleton-main/src/app/majors/major-students/major-students.component.scss index 0a06e685db80451a6e5ed00a0acc9f7a939389e4..40587319a61ca639a34eb096a3539aeef2fcc5d5 100644 --- a/epf-front-skeleton-main/src/app/majors/major-students/major-students.component.scss +++ b/epf-front-skeleton-main/src/app/majors/major-students/major-students.component.scss @@ -3,7 +3,7 @@ :host { display: flex; flex-direction: column; - padding : 30px; + padding: 30px; h1 { display: flex; @@ -12,7 +12,8 @@ margin-right: 50px; margin-bottom: 0; } - table{ + + table { margin-top: 20px; } } diff --git a/epf-front-skeleton-main/src/app/majors/major-students/major-students.component.ts b/epf-front-skeleton-main/src/app/majors/major-students/major-students.component.ts index 9d0f23d195e9bff5927c9662057aae43b7a51438..82c251f06ecdf7e1443c7d2e0d4dfe157d453d79 100644 --- a/epf-front-skeleton-main/src/app/majors/major-students/major-students.component.ts +++ b/epf-front-skeleton-main/src/app/majors/major-students/major-students.component.ts @@ -1,8 +1,8 @@ import { Component, OnInit } from "@angular/core" import { map, Observable } from "rxjs" -import { Student } from "../../models/student.model" import { ActivatedRoute } from "@angular/router" import { MajorStudentsDto } from "../../models/dto/MajorStudentsDto" +import { Student } from "../../models/student.model" @Component({ selector: "epf-major-students", @@ -10,9 +10,11 @@ import { MajorStudentsDto } from "../../models/dto/MajorStudentsDto" styleUrls: ["./major-students.component.scss"], }) export class MajorStudentsComponent implements OnInit { - studentsFromMajor$: Observable<MajorStudentsDto> = this._route.data.pipe(map((data) => data["studentsFromMajor"])) + studentsFromMajor$: Observable<Student[]> = this._route.data.pipe(map((data) => data["studentsFromMajor"])) - constructor(private _route: ActivatedRoute) {} + constructor(private _route: ActivatedRoute) { + } - ngOnInit(): void {} + ngOnInit(): void { + } } diff --git a/epf-front-skeleton-main/src/app/majors/major-students/major-students.resolver.ts b/epf-front-skeleton-main/src/app/majors/major-students/major-students.resolver.ts index 758a16c94730356dd2493acd1ba8385600a8cbd8..71c08449811ca4549e09db1d403cdea76bfbef89 100644 --- a/epf-front-skeleton-main/src/app/majors/major-students/major-students.resolver.ts +++ b/epf-front-skeleton-main/src/app/majors/major-students/major-students.resolver.ts @@ -1,17 +1,17 @@ import { Injectable } from "@angular/core" import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from "@angular/router" import { Observable } from "rxjs" -import { Student } from "../../models/student.model" import { MajorService } from "../../services/major.service" -import { MajorStudentsDto } from "../../models/dto/MajorStudentsDto" +import { Student } from "../../models/student.model" @Injectable({ providedIn: "root", }) -export class MajorStudentsResolver implements Resolve<MajorStudentsDto> { - constructor(private majorService: MajorService) {} +export class MajorStudentsResolver implements Resolve<Student[]> { + constructor(private majorService: MajorService) { + } - resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<MajorStudentsDto> { + resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Student[]> { return this.majorService.findStudentsFromMajor(route.params["id"]) } } diff --git a/epf-front-skeleton-main/src/app/majors/majors.component.html b/epf-front-skeleton-main/src/app/majors/majors.component.html index ba79aa86da69ced7b1b4a043eb71835dc0d4b131..7c3a077676811c626043bed354d254e9c5c03777 100644 --- a/epf-front-skeleton-main/src/app/majors/majors.component.html +++ b/epf-front-skeleton-main/src/app/majors/majors.component.html @@ -1,6 +1,5 @@ <div class="d-flex align-items-center"> <h1>Majors</h1> - <a mat-raised-button color="primary" routerLink="/major-details/new">New</a> </div> <table class="table table-hover"> <thead> diff --git a/epf-front-skeleton-main/src/app/majors/majors.component.scss b/epf-front-skeleton-main/src/app/majors/majors.component.scss index 4c8c0f3c208a6894f365c957cb6fcac974bbfb89..0f9d16a1c2f2ff6ff6e345650325eab907cceda8 100644 --- a/epf-front-skeleton-main/src/app/majors/majors.component.scss +++ b/epf-front-skeleton-main/src/app/majors/majors.component.scss @@ -3,7 +3,7 @@ :host { display: flex; flex-direction: column; - padding : 30px; + padding: 30px; h1 { display: flex; @@ -12,8 +12,10 @@ margin-right: 50px; margin-bottom: 0; } - table{ + + table { margin-top: 20px; + tbody { :hover { cursor: pointer; diff --git a/epf-front-skeleton-main/src/app/majors/majors.component.ts b/epf-front-skeleton-main/src/app/majors/majors.component.ts index 5b2328c46a3df385bea1d1d45d3c063f9bce3ebf..7fc3b527a0a2b0f751ba92892fb947edaaa65117 100644 --- a/epf-front-skeleton-main/src/app/majors/majors.component.ts +++ b/epf-front-skeleton-main/src/app/majors/majors.component.ts @@ -1,6 +1,6 @@ -import { Component, OnInit } from "@angular/core" +import { Component } from "@angular/core" import { map, Observable } from "rxjs" -import { Major } from "../models/major.model" +import { Major } from "models/major.model" import { ActivatedRoute } from "@angular/router" @Component({ @@ -11,5 +11,6 @@ import { ActivatedRoute } from "@angular/router" export class MajorsComponent { majors$: Observable<Major[]> = this._route.data.pipe(map((data) => data["majors"])) - constructor(private _route: ActivatedRoute) {} + constructor(private _route: ActivatedRoute) { + } } diff --git a/epf-front-skeleton-main/src/app/majors/majors.resolver.ts b/epf-front-skeleton-main/src/app/majors/majors.resolver.ts index f0dd21af05ff19a3f1f5e883bc2ccc953756c52e..64c2209012def8e367bd370625c2cff5634356a9 100644 --- a/epf-front-skeleton-main/src/app/majors/majors.resolver.ts +++ b/epf-front-skeleton-main/src/app/majors/majors.resolver.ts @@ -1,13 +1,15 @@ import { Injectable } from "@angular/core" -import { Resolve, RouterStateSnapshot, ActivatedRouteSnapshot } from "@angular/router" +import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from "@angular/router" import { Observable } from "rxjs" -import { MajorService } from "../services/major.service" -import { Major } from "../models/major.model" +import { MajorService } from "services/major.service" +import { Major } from "models/major.model" + @Injectable({ providedIn: "root", }) export class MajorsResolver implements Resolve<Major[]> { - constructor(private majorService: MajorService) {} + constructor(private majorService: MajorService) { + } resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Major[]> { return this.majorService.findAll() diff --git a/epf-front-skeleton-main/src/app/models/course.model.ts b/epf-front-skeleton-main/src/app/models/course.model.ts index dc3734a1412a73b6aa837948700d76e0c15b32f5..1a1b7664725f2cf16bd22f4cdb7736cf46ab4d8e 100644 --- a/epf-front-skeleton-main/src/app/models/course.model.ts +++ b/epf-front-skeleton-main/src/app/models/course.model.ts @@ -1,9 +1,4 @@ -export class Course { +export interface Course { name: string hours: number - - constructor(name: string, hours: number) { - this.name = name - this.hours = hours - } } diff --git a/epf-front-skeleton-main/src/app/models/links.model.ts b/epf-front-skeleton-main/src/app/models/links.model.ts index cadd02dc0d504150070a7f0fb953c73aa38918ac..891c05bf1e89e603fed7605138a136fb4858f50d 100644 --- a/epf-front-skeleton-main/src/app/models/links.model.ts +++ b/epf-front-skeleton-main/src/app/models/links.model.ts @@ -1,9 +1,4 @@ -export class Link { - name : string; - href : string; - - constructor(name: string, href: string) { - this.name = name; - this.href = href; - } +export interface Link { + name: string + href: string } diff --git a/epf-front-skeleton-main/src/app/models/major.model.ts b/epf-front-skeleton-main/src/app/models/major.model.ts index f572a9a24587605f5cafa4a6468b6feaa552b3b2..658cc04efb748a0882682c0872df15ddb6c6429b 100644 --- a/epf-front-skeleton-main/src/app/models/major.model.ts +++ b/epf-front-skeleton-main/src/app/models/major.model.ts @@ -1,14 +1,8 @@ import { Student } from "./student.model" -export class Major { +export interface Major { id?: bigint name: string description: string - students: Student[] = [] - - constructor(name: string, description: string, id?: bigint) { - this.name = name - this.description = description - this.id = id - } + students: Student[] } diff --git a/epf-front-skeleton-main/src/app/models/student.model.ts b/epf-front-skeleton-main/src/app/models/student.model.ts index 0a107361630575cc5dad4c1ed5c572dd42276b12..c9d7f015b6709569af44e16fd22b8cad56aa4ad0 100644 --- a/epf-front-skeleton-main/src/app/models/student.model.ts +++ b/epf-front-skeleton-main/src/app/models/student.model.ts @@ -1,20 +1,12 @@ import { Course } from "./course.model" import { Major } from "./major.model" -export class Student { +export interface Student { id?: bigint + image?: string firstName: string lastName: string - birthDate?: Date + birthdate?: Date courses?: Course[] major: Major - - constructor(firstName: string, lastName: string, major: Major, birthDate?: Date, courses?: Course[], id?: bigint) { - this.id = id - this.firstName = firstName - this.lastName = lastName - this.birthDate = birthDate - this.courses = courses - this.major = major - } } diff --git a/epf-front-skeleton-main/src/app/navbar/navbar.component.html b/epf-front-skeleton-main/src/app/navbar/navbar.component.html index 96ce638825bbe3256b05ffbcbe3734cb08ecbd39..49ca134367dc164f50d59c7bbd694fc5941e876f 100644 --- a/epf-front-skeleton-main/src/app/navbar/navbar.component.html +++ b/epf-front-skeleton-main/src/app/navbar/navbar.component.html @@ -1,8 +1,9 @@ <nav> <div> - <img src="assets/logo-epf.png" routerLink="" > + <img src="assets/logo-epf.png" routerLink=""> <mat-nav-list> - <a mat-list-item routerLink="{{link.href}}" routerLinkActive="active" *ngFor="let link of links">{{ link.name }}</a> + <a mat-list-item routerLink="{{link.href}}" routerLinkActive="active" + *ngFor="let link of links">{{ link.name }}</a> </mat-nav-list> </div> </nav> diff --git a/epf-front-skeleton-main/src/app/navbar/navbar.component.scss b/epf-front-skeleton-main/src/app/navbar/navbar.component.scss index 95867e767c0ce6bd4eaf6f995a3c9031d542002b..52fb8fe1c3c4ac8a062dc3924cf696292f45e37a 100644 --- a/epf-front-skeleton-main/src/app/navbar/navbar.component.scss +++ b/epf-front-skeleton-main/src/app/navbar/navbar.component.scss @@ -1,4 +1,5 @@ @use "src/theme"; + nav { height: 80px; background: linear-gradient(to right, theme.$common-purple, theme.$common-red); @@ -11,10 +12,13 @@ nav { img { margin-left: 20px; height: 60px; - &:hover{ + transition: .3s; + + &:hover { transform: scale(1.1); } } + .active { text-decoration: underline; } @@ -23,13 +27,16 @@ nav { .mat-nav-list { margin-left: 50px; - padding : 0; + padding: 0; display: flex; } + .mat-list-base .mat-list-item { - font-size : large; - color : theme.$white; - &:hover{ + font-size: large; + color: theme.$white; + transition: .3s; + + &:hover { transform: scale(1.2); } } diff --git a/epf-front-skeleton-main/src/app/navbar/navbar.component.ts b/epf-front-skeleton-main/src/app/navbar/navbar.component.ts index babf8ab397ce8c796c9581d37135f0660efb072c..fdc532d657c0444aa00fa895dd457e3d0ad4e8a9 100644 --- a/epf-front-skeleton-main/src/app/navbar/navbar.component.ts +++ b/epf-front-skeleton-main/src/app/navbar/navbar.component.ts @@ -1,17 +1,16 @@ import { Component, OnInit } from "@angular/core" -import { Link } from "../models/links.model" +import { Link } from "models/links.model" + @Component({ selector: "epf-navbar", templateUrl: "./navbar.component.html", styleUrls: ["./navbar.component.scss"], }) -export class NavbarComponent implements OnInit { +export class NavbarComponent { links: Link[] = [] constructor() { - this.links.push(new Link("Students", "students")) - this.links.push(new Link("Majors", "majors")) + this.links.push({ name: "Students", href: "students" }) + this.links.push({ name: "Majors", href: "majors" }) } - - ngOnInit(): void {} } diff --git a/epf-front-skeleton-main/src/app/services/constantsMock.service.ts b/epf-front-skeleton-main/src/app/services/constantsMock.service.ts deleted file mode 100644 index 10f77af86d8e02191f06e2f3022783625918d177..0000000000000000000000000000000000000000 --- a/epf-front-skeleton-main/src/app/services/constantsMock.service.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { Injectable } from "@angular/core" -import { Student } from "../models/student.model" -import { Course } from "../models/course.model" -import { Major } from "../models/major.model" - -@Injectable({ - providedIn: "root", -}) -export class ConstantsMockService { - constructor() {} - private spanish = new Course("Spanish", 2) - private german = new Course("German", 2) - private ioT = new Course("Internet Of Things", 15) - private termo = new Course("Thermodynamic", 10) - private anatomie = new Course("Anatomy", 7) - private java = new Course("Java", 15) - private math = new Course("Maths", 30) - private management = new Course("Lean Management", 30) - - private min = new Major("Ingéniérie du Numérique", "Des lignes de code partout !!", 1n) - private msm = new Major("Structure & Matériaux", "Beaucoup de béton et des poutres (snif elle a été renomée)", 2n) - - private mae = new Major("Aéronautique & Espace", "Vive le vent", 3n) - private mde = new Major("Data Engineering", "Trop cool plein de données à ordonner", 4n) - private mee = new Major("Energie & Environnement", "On est full green", 5n) - private mem = new Major("Engineering Management", "Des managers de qualité", 6n) - private mis = new Major("Ingénierie & Santé", "On connait tous les os et tous les muscles du corps humain", 7n) - private miad = new Major("Ingénierie & Architecture durable", "Objectif 0 carbon", 8n) - private mdid = new Major("Design Industriel Durable", "Ca existait pas pour la P2022 ça", 9n) - - student1 = new Student("Harry", "Cover", this.mem, new Date("1998-10-10"), [this.spanish, this.management], 1n) - student2 = new Student("Jacques", "Climate", this.mee, new Date("1999-11-07"), [this.german, this.termo], 2n) - student3 = new Student("Alain", "Parfait", this.min, new Date("1999-04-12"), [this.german, this.ioT, this.java], 3n) - student4 = new Student("Cathy", "Mini", this.mde, new Date("1999-05-12"), [this.spanish, this.math, this.java], 4n) - student5 = new Student( - "Côme", - "Toulemonde", - this.mis, - new Date("1999-07-16"), - [this.spanish, this.anatomie, this.math], - 5n, - ) - - students: Student[] = [this.student1, this.student2, this.student3, this.student4, this.student5] - majors: Major[] = [this.min, this.msm, this.mae, this.mde, this.mee, this.mem, this.mis, this.miad, this.mdid] - courses: Course[] = [this.spanish, this.german, this.ioT, this.termo, this.anatomie, this.math, this.java, this.management] -} diff --git a/epf-front-skeleton-main/src/app/services/course.service.ts b/epf-front-skeleton-main/src/app/services/course.service.ts index 7fa6f5371bf4845a4fe33b1518ac56ba4ff60153..8f59125187895823146a0367b6497f7c66fbbea1 100644 --- a/epf-front-skeleton-main/src/app/services/course.service.ts +++ b/epf-front-skeleton-main/src/app/services/course.service.ts @@ -1,16 +1,18 @@ import { Injectable } from "@angular/core" import { Observable } from "rxjs" -import { Course } from "../models/course.model" -import { ConstantsMockService } from "./constantsMock.service" +import { Course } from "models/course.model" +import { HttpClient } from "@angular/common/http" @Injectable({ providedIn: "root", }) export class CourseService { - constructor(private constantsMockService: ConstantsMockService) {} + constructor(private http: HttpClient) { + } + + private coursesUrl = "http://localhost:8080/courses" - // FIXME : change to api call with httpclient findAll(): Observable<Course[]> { - return new Observable((observer) => observer.next(this.constantsMockService.courses)) + return this.http.get<Course[]>(this.coursesUrl) } } diff --git a/epf-front-skeleton-main/src/app/services/major.service.ts b/epf-front-skeleton-main/src/app/services/major.service.ts index 39560216ad663317c4a69dfbc2f516c49decc211..5b3414033c0acab141cdbbefd9e1c7a723678f23 100644 --- a/epf-front-skeleton-main/src/app/services/major.service.ts +++ b/epf-front-skeleton-main/src/app/services/major.service.ts @@ -1,34 +1,26 @@ import { Injectable } from "@angular/core" import { Observable } from "rxjs" -import { Major } from "../models/major.model" -import { MajorStudentsDto } from "../models/dto/MajorStudentsDto" -import { Course } from "../models/course.model" -import { MajorsAndCoursesDto } from "../models/dto/majorsAndCoursesDto" -import { ConstantsMockService } from "./constantsMock.service" +import { Major } from "models/major.model" +import { MajorStudentsDto } from "models/dto/MajorStudentsDto" +import { MajorsAndCoursesDto } from "models/dto/majorsAndCoursesDto" +import { HttpClient } from "@angular/common/http" +import { Student } from "../models/student.model" @Injectable({ providedIn: "root", }) export class MajorService { - constructor(private constantsMockService: ConstantsMockService) {} - - findAll(): Observable<Major[]> { - return new Observable((observer) => observer.next(this.constantsMockService.majors)) + constructor(private http: HttpClient) { } - findStudentsFromMajor(majorId: string): Observable<MajorStudentsDto> { - let major = this.findById(BigInt(majorId)) - return new Observable((observer) => - observer.next(new MajorStudentsDto(major!!, this.constantsMockService.students.filter(s => s.major === major))), - ) - } + private majorUrl = "http://localhost:8080/majors" - findById(id: bigint) { - return this.constantsMockService.majors.find((m) => m.id === id) + findAll(): Observable<Major[]> { + return this.http.get<Major[]>(this.majorUrl) } - findAllMajorsAndAllCourses(): Observable<MajorsAndCoursesDto> { - return new Observable((observer) => observer.next(new MajorsAndCoursesDto(this.constantsMockService.majors, this.constantsMockService.courses))) + findStudentsFromMajor(majorId: string): Observable<Student[]> { + return this.http.get<Student[]>(this.majorUrl + `/${majorId}/students`) } } diff --git a/epf-front-skeleton-main/src/app/services/student.service.ts b/epf-front-skeleton-main/src/app/services/student.service.ts index c7536cbd509cf68077ac527c49b5dfb06b208022..968a2cce80e68462ec1ffd9435ca9817ff496c78 100644 --- a/epf-front-skeleton-main/src/app/services/student.service.ts +++ b/epf-front-skeleton-main/src/app/services/student.service.ts @@ -1,25 +1,36 @@ import { Injectable } from "@angular/core" import { Observable } from "rxjs" -import { Student } from "../models/student.model" -import { Course } from "../models/course.model" -import { Major } from "../models/major.model" -import {ConstantsMockService} from "./constantsMock.service"; -import {MajorsAndCoursesDto} from "../models/dto/majorsAndCoursesDto"; +import { Student } from "models/student.model" +import { Course } from "models/course.model" +import { HttpClient } from "@angular/common/http" @Injectable({ providedIn: "root", }) export class StudentService { - constructor(private constantsMockService : ConstantsMockService) {} + constructor(private http: HttpClient) { + } + + private studentsUrl = "http://localhost:8080/students" - // FIXME : change to api call with httpclient findAll(): Observable<Student[]> { - return new Observable((observer) => observer.next(this.constantsMockService.students)) + return this.http.get<Student[]>(this.studentsUrl) } - // FIXME : unmock me ! findById(id: number): Observable<Student> { - return new Observable((observer) => observer.next(this.constantsMockService.students.find((s) => s.id === BigInt(id)))) + return this.http.get<Student>(`${this.studentsUrl}/${id}`) + } + + update(id: number, student: Student): Observable<Student> { + return this.http.post<Student>(`${this.studentsUrl}/${id}`, student) + } + + create(student: Student): Observable<Student> { + return this.http.post<Student>(this.studentsUrl, student) + } + + delete(student: Student) { + return this.http.delete(`${this.studentsUrl}/${student.id}`) } addCourseToStudent(student: Student, course: Course) { @@ -39,25 +50,4 @@ export class StudentService { return student } - save(student: Student) { - const index = this.constantsMockService.students.indexOf(student) - if (index > -1) { - this.constantsMockService.students.splice(index, 1, student) - } else { - student.id = BigInt(this.constantsMockService.students.length + 1) - this.constantsMockService.students.push(student) - } - } - - delete(student: Student) { - const index = this.constantsMockService.students.indexOf(student) - if (index > -1) { - this.constantsMockService.students.splice(index, 1) - } - } - - searchByMajorAndCourse(majorsAndCoursesDto: MajorsAndCoursesDto) : Observable<Student[]> { - return new Observable((observer) => observer.next( this.constantsMockService.students.filter(s => s.major.id === majorsAndCoursesDto.majors[0].id && s.courses?.includes(majorsAndCoursesDto.courses[0])))) - } - } diff --git a/epf-front-skeleton-main/src/app/students/research/research.component.html b/epf-front-skeleton-main/src/app/students/research/research.component.html deleted file mode 100644 index ae9113366d332feee076a1aec3fb5d4ccbdbfd78..0000000000000000000000000000000000000000 --- a/epf-front-skeleton-main/src/app/students/research/research.component.html +++ /dev/null @@ -1,17 +0,0 @@ -<ng-container *ngIf="majorsAndCourses$ | async; let majorAndCourse"> -<form (ngSubmit)="search()" #researchForm="ngForm" class="d-flex"> - <div class="form-group"> - <select id="major" [(ngModel)]="majorModel" name="major" class="form-control"> - <option [ngValue]="null" [disabled]="true">Select a major</option> - <option *ngFor="let major of majorAndCourse.majors" [ngValue]="major">{{major.name}}</option> - </select> - </div> - <div class="form-group"> - <select id="course" [(ngModel)]="courseModel" name="course" class="form-control"> - <option [ngValue]="null" [disabled]="true">Select a course</option> - <option *ngFor="let course of majorAndCourse.courses" [ngValue]="course">{{course.name}}</option> - </select> - </div> - <button type="submit" mat-raised-button color="primary" [disabled]="majorModel == null || courseModel == null">Search</button> -</form> -</ng-container> diff --git a/epf-front-skeleton-main/src/app/students/research/research.component.scss b/epf-front-skeleton-main/src/app/students/research/research.component.scss deleted file mode 100644 index 8af74b6f6294a0963be8b5bfa7f8cb8db818370d..0000000000000000000000000000000000000000 --- a/epf-front-skeleton-main/src/app/students/research/research.component.scss +++ /dev/null @@ -1,7 +0,0 @@ -:host { - margin-left: 100px; - display: flex; - .form-group { - margin-right: 10px; - } -} diff --git a/epf-front-skeleton-main/src/app/students/research/research.component.ts b/epf-front-skeleton-main/src/app/students/research/research.component.ts deleted file mode 100644 index f7a377f5defd618f8bc860261658bc16876974e1..0000000000000000000000000000000000000000 --- a/epf-front-skeleton-main/src/app/students/research/research.component.ts +++ /dev/null @@ -1,30 +0,0 @@ -import {Component, EventEmitter, OnInit, Output} from "@angular/core" -import { Observable } from "rxjs" -import { MajorsAndCoursesDto } from "../../models/dto/majorsAndCoursesDto" -import { Major } from "../../models/major.model" -import { MajorService } from "../../services/major.service" -import { Course } from "../../models/course.model" -import { StudentService } from "../../services/student.service" -import {Student} from "../../models/student.model"; - -@Component({ - selector: "epf-research", - templateUrl: "./research.component.html", - styleUrls: ["./research.component.scss"], -}) -export class ResearchComponent implements OnInit { - majorsAndCourses$: Observable<MajorsAndCoursesDto> | undefined - majorModel: Major | null = null - courseModel: Course | null = null - @Output() searchEvent = new EventEmitter<Observable<Student[]>>(); - - constructor(private majorService: MajorService, private studentService: StudentService) {} - - ngOnInit(): void { - this.majorsAndCourses$ = this.majorService.findAllMajorsAndAllCourses() - } - - search() { - this.searchEvent.emit(this.studentService.searchByMajorAndCourse(new MajorsAndCoursesDto([this.majorModel!!], [this.courseModel!!]))) - } -} diff --git a/epf-front-skeleton-main/src/app/students/student-details/student-details.component.html b/epf-front-skeleton-main/src/app/students/student-details/student-details.component.html index 48ca113e87d08e00f4b0c50d158ed417f8c7f898..0ea9817b175596aba704984c71cf9f37e8dc4aab 100644 --- a/epf-front-skeleton-main/src/app/students/student-details/student-details.component.html +++ b/epf-front-skeleton-main/src/app/students/student-details/student-details.component.html @@ -2,7 +2,7 @@ <h1>Student's personal data</h1> <form (ngSubmit)="save(student)" #studentForm="ngForm"> <div class="form-group"> - <label for="firstName">Fist Name</label> + <label for="firstName">First Name</label> <input type="text" class="form-control" id="firstName" required [(ngModel)]="student.firstName" name="firstName" @@ -12,6 +12,7 @@ First Name is required </div> </div> + <div class="form-group"> <label for="lastName">Last Name</label> <input type="text" class="form-control" id="lastName" @@ -23,28 +24,27 @@ Last Name is required </div> </div> + <div class="form-group"> <label for="birthDate">Birthdate</label> <input type="date" class="form-control" id="birthDate" required - [ngModel]="student.birthDate | date:'yyyy-MM-dd'" name="birthDate" + [ngModel]="student.birthdate | date:'yyyy-MM-dd'" name="birthDate" #birthDate="ngModel" (ngModelChange)="updateBirthdate($event, student)"> <div [hidden]="birthDate.pristine && birthDate.untouched || birthDate.value !== today.toISOString().slice(0, 10)" class="alert alert-danger"> Birthdate is required </div> </div> - <div class="form-group"> + + <div *ngIf="allMajors$ | async; let allMajors" class="form-group"> <label for="major">Major</label> - <input type="text" class="form-control" id="major" - required - [(ngModel)]="student.major!!.name" name="major" - #major="ngModel"> - <div [hidden]="major.valid || major.pristine" - class="alert alert-danger"> - Major is required - </div> + <select id="major" [(ngModel)]="majorSelectModel" name="majors" class="form-control"> + <option [ngValue]="null" [disabled]="true">Select a major</option> + <option *ngFor="let major of allMajors" [ngValue]="major">{{major.name}}</option> + </select> </div> + <div class="student-courses"> <div class="d-flex align-items-center"> <h3 class="courses-title">Courses</h3> @@ -61,7 +61,8 @@ <div *ngIf="notSelectedCourse" class="alert alert-danger"> Course is required </div> - <button type="button" [disabled]="courseSelectModel==null" (click)="addCourseToStudent(student)" mat-raised-button + <button type="button" [disabled]="courseSelectModel==null" (click)="addCourseToStudent(student)" + mat-raised-button color="primary">Add course </button> </div> diff --git a/epf-front-skeleton-main/src/app/students/student-details/student-details.component.scss b/epf-front-skeleton-main/src/app/students/student-details/student-details.component.scss index 0ed5e7385558e9c7ff686d4c121c9d6272133ce1..d9bf7edba0d899ad4e299e2ed57899de1dff358c 100644 --- a/epf-front-skeleton-main/src/app/students/student-details/student-details.component.scss +++ b/epf-front-skeleton-main/src/app/students/student-details/student-details.component.scss @@ -1,30 +1,36 @@ @use "src/theme"; + :host { display: flex; flex-direction: column; padding: 30px; - color: theme.$white - h1 { + color: theme.$white h1 { color: theme.$common-purple; font-size: xx-large; } + label { font-size: large; margin: 10px 0; } + button { margin: 10px 0; } + .student-courses { .courses-title { font-size: large; margin: 10px 10px 10px 0; } + table { - border : 1px solid lightgray; + border: 1px solid lightgray; font-size: medium; + tr { display: flex; + td { width: 33%; display: flex; @@ -33,14 +39,16 @@ } } } + .new-course-div { :hover { cursor: pointer; } - .new-course-icon{ + + .new-course-icon { margin-left: 10px; - color: green ; + color: green; } } } diff --git a/epf-front-skeleton-main/src/app/students/student-details/student-details.component.ts b/epf-front-skeleton-main/src/app/students/student-details/student-details.component.ts index cdab378513a27bddfc8b01efcec0527bb94f9624..577b853e2c78ab6ca48f873726cc6c1cfdd5615d 100644 --- a/epf-front-skeleton-main/src/app/students/student-details/student-details.component.ts +++ b/epf-front-skeleton-main/src/app/students/student-details/student-details.component.ts @@ -1,11 +1,12 @@ import { Component, OnInit } from "@angular/core" import { map, Observable } from "rxjs" -import { Student } from "../../models/student.model" +import { Student } from "models/student.model" import { ActivatedRoute, Router } from "@angular/router" -import { FormControl } from "@angular/forms" -import { Course } from "../../models/course.model" -import { CourseService } from "../../services/course.service" -import { StudentService } from "../../services/student.service" +import { Course } from "models/course.model" +import { CourseService } from "services/course.service" +import { StudentService } from "services/student.service" +import { Major } from "../../models/major.model" +import { MajorService } from "../../services/major.service" @Component({ selector: "epf-student-details", @@ -14,16 +15,22 @@ import { StudentService } from "../../services/student.service" }) export class StudentDetailsComponent { student$: Observable<Student> = this._route.data.pipe(map((data) => data["student"])) + allMajors$: Observable<Major[]> | undefined allCourses$: Observable<Course[]> | undefined + majorSelectModel: Major | null = null courseSelectModel: Course | null = null notSelectedCourse: boolean | undefined today = new Date(Date.now()) + constructor( private _route: ActivatedRoute, private courseService: CourseService, private studentService: StudentService, + private majorService: MajorService, private router: Router, - ) {} + ) { + this.allMajors$ = this.majorService.findAll() + } courseClick() { this.allCourses$ = this.courseService.findAll() @@ -42,12 +49,25 @@ export class StudentDetailsComponent { } save(student: Student) { - this.studentService.save(student) - this.router.navigate(["students"]) + const id = this._route.snapshot.params["id"] + + if (this.majorSelectModel !== null) { + student.major = this.majorSelectModel + } + + if (id == "new") { + this.studentService.create(student).subscribe(() => { + this.router.navigate(["students"]) + }) + } else { + this.studentService.update(id, student).subscribe(() => { + this.router.navigate(["students"]) + }) + } } // because the format of the date doesn't fit date picker updateBirthdate($event: any, student: Student) { - student.birthDate = new Date($event) + student.birthdate = new Date($event) } } diff --git a/epf-front-skeleton-main/src/app/students/student-details/student-details.resolver.ts b/epf-front-skeleton-main/src/app/students/student-details/student-details.resolver.ts index 0cdd27e04489bf78fe669f728fa7c8b8598db64c..8616ba2c100be119979acc4f059e2803c8dcc7c0 100644 --- a/epf-front-skeleton-main/src/app/students/student-details/student-details.resolver.ts +++ b/epf-front-skeleton-main/src/app/students/student-details/student-details.resolver.ts @@ -1,19 +1,21 @@ import { Injectable } from "@angular/core" -import { Router, Resolve, RouterStateSnapshot, ActivatedRouteSnapshot } from "@angular/router" -import { first, mergeMap, Observable, of } from "rxjs" -import { StudentService } from "../../services/student.service" -import { Student } from "../../models/student.model" -import { Major } from "../../models/major.model" +import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from "@angular/router" +import { Observable } from "rxjs" +import { StudentService } from "services/student.service" +import { Student } from "models/student.model" +import { Major } from "models/major.model" @Injectable({ providedIn: "root", }) export class StudentDetailsResolver implements Resolve<Student> { - constructor(private studentService: StudentService) {} + constructor(private studentService: StudentService) { + } + resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Student> { if (route.params["id"] == "new") { - return new Observable((observer) => observer.next(new Student("", "", new Major("", "")))) + return new Observable((observer) => observer.next({firstName: "", lastName: "", major: {name: "", description: "", students: []}})) } - return this.studentService.findById(parseInt(route.paramMap.get("id")!!, 10)) + return this.studentService.findById(parseInt(route.params["id"], 10)) } } diff --git a/epf-front-skeleton-main/src/app/students/students.component.html b/epf-front-skeleton-main/src/app/students/students.component.html index d8bbc048a42a12d42dba22cbbff850ac69d188ff..72af817bb1e9bd740c2e95569a7cd89943c11965 100644 --- a/epf-front-skeleton-main/src/app/students/students.component.html +++ b/epf-front-skeleton-main/src/app/students/students.component.html @@ -1,7 +1,6 @@ <div class="d-flex align-items-center"> <h1>Students</h1> <a mat-raised-button color="primary" routerLink="/student-details/new">New</a> - <epf-research (searchEvent)="searchByMajorAndCourse($event)"></epf-research> </div> <table class="table table-hover"> <thead> @@ -17,10 +16,10 @@ <tr *ngFor="let student of (students$ | async)" routerLink="/student-details/{{student.id}}"> <td>{{ student.firstName }}</td> <td>{{ student.lastName }}</td> - <td>{{ student.birthDate | date : "dd/MM/yyyy" }}</td> + <td>{{ student.birthdate | date : "dd/MM/yyyy" }}</td> <td>{{ student.major!!.name }}</td> <td> - <button mat-icon-button color="warn" (click)="deleteStudent(student)"> + <button mat-icon-button color="warn" (click)="deleteStudent($event, student)"> <mat-icon>delete</mat-icon> </button> </td> diff --git a/epf-front-skeleton-main/src/app/students/students.component.scss b/epf-front-skeleton-main/src/app/students/students.component.scss index a16aff5e107ac31703c52b8ff0ae2a9a8e9624e6..584f56d9eaa572da4b946d71606a995cd4b90638 100644 --- a/epf-front-skeleton-main/src/app/students/students.component.scss +++ b/epf-front-skeleton-main/src/app/students/students.component.scss @@ -3,7 +3,7 @@ :host { display: flex; flex-direction: column; - padding : 30px; + padding: 30px; h1 { display: flex; @@ -12,13 +12,20 @@ margin-right: 100px; margin-bottom: 0; } - table{ + + table { margin-top: 20px; vertical-align: center; + tbody { :hover { cursor: pointer; } } } + + img { + height: 3rem; + width: auto; + } } diff --git a/epf-front-skeleton-main/src/app/students/students.component.ts b/epf-front-skeleton-main/src/app/students/students.component.ts index 3c091c2d6af124edef10b9cfadf851ad83faf471..7b41c903c04bb0ab3251570c24bbdf73f8cf35fe 100644 --- a/epf-front-skeleton-main/src/app/students/students.component.ts +++ b/epf-front-skeleton-main/src/app/students/students.component.ts @@ -1,8 +1,8 @@ -import { Component, OnInit } from "@angular/core" +import { Component } from "@angular/core" import { map, Observable } from "rxjs" -import { Student } from "../models/student.model" +import { Student } from "models/student.model" import { ActivatedRoute, Router } from "@angular/router" -import { StudentService } from "../services/student.service" +import { StudentService } from "services/student.service" @Component({ selector: "epf-students", @@ -11,13 +11,16 @@ import { StudentService } from "../services/student.service" }) export class StudentsComponent { students$: Observable<Student[]> = this._route.data.pipe(map((data) => data["students"])) - constructor(private _route: ActivatedRoute, private studentService: StudentService) {} - deleteStudent(student: Student) { - this.studentService.delete(student) + constructor(private _route: ActivatedRoute, private studentService: StudentService, private router: Router,) { + } + + deleteStudent(event: any, student: Student) { + event.stopPropagation() + this.studentService.delete(student).subscribe(() => this.router.navigate(["students"])) } searchByMajorAndCourse($event: Observable<Student[]>) { - this.students$ = $event; + this.students$ = $event } } diff --git a/epf-front-skeleton-main/src/app/students/students.resolver.ts b/epf-front-skeleton-main/src/app/students/students.resolver.ts index 9ed89a6a16b2a36b4a7fc5a762d3fa663644bf3e..a4a65422c287ce97dc1a26f096b1a89803492ee0 100644 --- a/epf-front-skeleton-main/src/app/students/students.resolver.ts +++ b/epf-front-skeleton-main/src/app/students/students.resolver.ts @@ -1,14 +1,16 @@ import { Injectable } from "@angular/core" import { Resolve } from "@angular/router" import { Observable } from "rxjs" -import { Student } from "../models/student.model" -import { StudentService } from "../services/student.service" +import { Student } from "models/student.model" +import { StudentService } from "services/student.service" @Injectable({ providedIn: "root", }) export class StudentsResolver implements Resolve<Student[]> { - constructor(private studentService: StudentService) {} + constructor(private studentService: StudentService) { + } + resolve(): Observable<Student[]> { return this.studentService.findAll() } diff --git a/epf-front-skeleton-main/src/assets/defaultPicture.svg b/epf-front-skeleton-main/src/assets/defaultPicture.svg new file mode 100644 index 0000000000000000000000000000000000000000..c935fa809c5f9fe0dc4bf18c75d016cba81d94db --- /dev/null +++ b/epf-front-skeleton-main/src/assets/defaultPicture.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 480 480" fill="none" shape-rendering="auto"><desc>"Custom Avatar" by "Ashley Seo", licensed under "CC BY 4.0". / Remix of the original. - Created with dicebear.com</desc><metadata xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><rdf:RDF><cc:Work><dc:title>Custom Avatar</dc:title><dc:creator><cc:Agent rdf:about="http://www.ashleyseo.com/"><dc:title>Ashley Seo</dc:title></cc:Agent></dc:creator><dc:source>https://www.figma.com/community/file/881358461963645496</dc:source><cc:license rdf:resource="https://creativecommons.org/licenses/by/4.0/" /></cc:Work></rdf:RDF></metadata><mask id="viewboxMask"><rect width="480" height="480" rx="0" ry="0" x="0" y="0" fill="#fff" /></mask><g mask="url(#viewboxMask)"><g transform="matrix(.85775 0 0 .85427 52 47)"><path d="M264 38.6s131.4 20.6 121.4 208.1c0 .7 15.2 10.9 16.4 12a77.1 77.1 0 0 1 23.4 36.3c13.9 51.3-35.7 104.2-75.8 118.2a155 155 0 0 1-46.7 8.3c-103.1 3-239.7-62.7-246.7-191a202.7 202.7 0 0 1 15.1-83.9c0 .1 57.4-142.5 192.9-108Z" fill="#efcc9f"/><path d="M388.7 248.7a57 57 0 0 0-3.2 10.5 40 40 0 0 0 8.5 30.4 42.3 42.3 0 0 0 33 15.7c-3.2-31.7-29-50.7-38.3-56.6ZM203.5 332c24.4-5.2 39.6-31 33.9-57.5-5.7-26.5-30.2-43.7-54.6-38.5-24.4 5.3-39.5 31-33.8 57.6 5.7 26.5 30.1 43.7 54.5 38.5Z" fill="#DC2400" style="mix-blend-mode:multiply" opacity=".1"/><path opacity=".1" d="M323 257.9s20.9-19.9 37-1.2Z" fill="#000"/><path d="M128.7 356.9C59.3 391.7-3.7 304.4 16.5 255.3c12.9-31.4 50.4-33.8 72.1-5.2a185 185 0 0 1 29.1 59.1" fill="#efcc9f"/><path opacity=".1" d="M71.5 279c9 9 16.1 22.5 25 30-1.7-12.5-4.3-26-10.4-37.3-6.2-11.6-17.5-21-29-20.3-14.2 1-25.9 17.6-27.4 32.6 1-9 19-15 25.9-14.2 10.8 20.4 15 60.6 15 60.6 9-22.7 5.4-40.7 1-51.5Z" fill="#000"/></g><g transform="matrix(.85472 0 0 .855 19 -17)"><path d="M385.3 380.4c9.4.2 18.3-2.5 26-10.5 4-4.2 8.2-6.5 14-3 13.9 8.7 17.1 30.2 13.4 44.6a63.3 63.3 0 0 1-30.7 36.8c-38.2 22.4-67.6 17.4-106.8 3-30.8-11.2-72.5-33.9-62-72.9 13.2-48.3 69.6-25 101.4-12 13.5 5.5 29.6 13.5 44.7 14Z" fill="#fff"/><path d="m347 463.2-6-.8 22.7-86.7 5.7 1.9-22.3 85.6ZM426.9 433a68.7 68.7 0 0 1-5.1 5.3l-13-66 2.6-2.4c.8-.9 1.7-1.7 2.6-2.4l12.9 65.6ZM296.8 351.4 264.4 433a98.1 98.1 0 0 1-5-3.7l31.4-79 6 1.1Z" fill="#D1D3D4"/></g><g transform="matrix(.85472 0 0 .855 19 -17)"><path d="M397 294.3a80.4 80.4 0 0 0 16.9-8.1c3.1 3.5 5 9 5 14 0 8-3.6 16.6-12.8 15.6-7.7-.8-9.7-11-9.7-16 0-1.9.2-3.8.6-5.5ZM301.2 283.1c-2.8 3.8-4.6 9-4.6 15.4 0 12.5 6.1 19 15.4 21.5 13 2 19.1-7.6 19.1-19.5a26 26 0 0 0-.8-6.4 49 49 0 0 1-29-11Z" fill="#2A1200"/><path d="M332 270.3a43.9 43.9 0 0 1-38.3-12.6c-3.3-3.3-4.2-9.2-1-13 3-3.6 8.6-4.7 12-1.2l3.3 3c.3.3 1.3.8 1.6 1.2l.6.3a37.7 37.7 0 0 0 6 3c.5 0 1.2.3 1.7.5a34.8 34.8 0 0 0 6.3 1h2c1.5-.2 2.9-.3 4.3-.6 4.4-.8 9 3.5 9.3 8.3.2 5.2-3 9.3-7.7 10.1ZM421.7 261.4c-6 6-13.8 9.5-21.8 9.7a8.1 8.1 0 0 1-6-2.8 9.5 9.5 0 0 1-2.1-6.5 10 10 0 0 1 2.7-6.5 9 9 0 0 1 6.2-2.7h1.1l3.4-1c1.3-.6 2.5-1.4 3.7-2.2l1.2-1.1c1.6-1.7 4-2.7 6.1-2.7 2.1 0 4.6 1 6 2.8 1.4 1.8 2.4 4 2.2 6.5-.2 2.5-1 4.8-2.7 6.5Z" fill="#71472D"/></g><g transform="matrix(.85472 0 0 .85667 18 -15)"><path d="M366.8 170.9c-8 7.2-16.8 17.6-26.5 29.1-16.3 19.3-35.3 41.8-57.3 57.3a227.2 227.2 0 0 1-86.5 35.3 86.4 86.4 0 0 0-16.4 32c-3.2 9.9-5.5 17-13 17.4-9-20.6-25.4-54.2-71.1-39-38.5 12.8-40.4 56.3-28 78.5 7 12.4 35.3 40 81 34l29.5 25.5c-2.9 5.4-8.2 13.1-25.8 20.7-21.9 9.5-123.8 1-133.3-60.8-23.8-20.6-61.1-78.2-20-143.6 12.6-20 30.3-34.4 51.3-43.7-.2-8.2-.2-17.7.1-28.6 2-60 58.1-108.4 102-118.9 42.7-10.2 132.8-6.8 169.8 26.2C443 47.5 473.8 193.9 469.5 249.5c22.4 44 7 106.7-1 131.5-4-33.6-31.3-56-44-61.5 5.6-30.4-5-82-11-104a139 139 0 0 0-46.7-44.6Z" fill="#71472d"/></g><g transform="matrix(.85472 0 0 .85667 14 -12)"></g></g></svg> \ No newline at end of file diff --git a/epf-front-skeleton-main/tsconfig.json b/epf-front-skeleton-main/tsconfig.json index ff06eae10c542e0ecce4498ce0caef544483f0af..0769790d483e5d0e5f55b4700eb6804b176c01a9 100644 --- a/epf-front-skeleton-main/tsconfig.json +++ b/epf-front-skeleton-main/tsconfig.json @@ -2,7 +2,7 @@ { "compileOnSave": false, "compilerOptions": { - "baseUrl": "./", + "baseUrl": "src/app", "outDir": "./dist/out-tsc", "forceConsistentCasingInFileNames": true, "strict": true,