Big commit:

make some changes to profile to provide an interface for a student to manage his courses.

implements the submission of exemptions request
This commit is contained in:
LeoMoulin 2024-04-06 16:12:11 +02:00
parent 648b73b585
commit 3c721de18b
14 changed files with 360 additions and 74 deletions

View File

@ -135,4 +135,5 @@ public class CourseController {
courseServ.delete(courseServ.findById(id));
return new ResponseEntity<>(HttpStatus.OK);
}
}

View File

@ -120,11 +120,11 @@ public class CurriculumController {
}
@GetMapping("/externalcurriculum/{inscriptionRequestId}")
public ResponseEntity<Map<String,Object>> getInscriptionRequestExternalCurriculum(@RequestHeader("Authorization") String token, @PathVariable String inscriptionRequestId){
public ResponseEntity<Map<String,Object>> getInscriptionRequestExternalCurriculum(@RequestHeader("Authorization") String token, @PathVariable long inscriptionRequestId){
if (authServ.isNotIn(new Role[]{Role.Secretary,Role.Admin, Role.Teacher},token))
return new UnauthorizedResponse<>(null);
HashMap<String,Object> toReturn = userCurriculumServ.findAllExternalCurriculumByInscriptionRequestId(Long.parseLong(inscriptionRequestId));
HashMap<String,Object> toReturn = userCurriculumServ.findAllExternalCurriculumByInscriptionRequestId(inscriptionRequestId);
if (toReturn == null)
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);

View File

@ -79,6 +79,7 @@ public class MockController {
ucr.save(new UserCurriculum(joe, infoBab1, 2022));
ucr.save(new UserCurriculum(joe, chemistryBab1, 2023));
ucr.save(new UserCurriculum(joe, infoBab1, 2023));
ucr.save(new UserCurriculum(joe, psychologyBab1, 2020));
ucr.save(new UserCurriculum(popo, infoBab1, 2022));
ucr.save(new UserCurriculum(popo, infoBab2, 2023));
@ -96,7 +97,7 @@ public class MockController {
CurriculumCourseService.save(new CurriculumCourse(infoBab1,progra1));
CurriculumCourseService.save(new CurriculumCourse(infoBab1,commun));
CurriculumCourseService.save(new CurriculumCourse(infoBab1, psycho1));
CurriculumCourseService.save(new CurriculumCourse(psychologyBab1,psycho1));
CurriculumCourseService.save(new CurriculumCourse(psychologyBab1,commun));

View File

@ -0,0 +1,32 @@
package ovh.herisson.Clyde.EndPoints;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import ovh.herisson.Clyde.Repositories.ExemptionsRequestRepository;
import ovh.herisson.Clyde.Tables.ExemptionsRequest;
import ovh.herisson.Clyde.Tables.RequestState;
@RestController
@CrossOrigin(originPatterns = "*", allowCredentials = "true")
public class RequestsController {
public final ExemptionsRequestRepository err;
public RequestsController(ExemptionsRequestRepository err) {
this.err = err;
}
@PostMapping(value="/exemptionreq")
public ResponseEntity<String> register(@RequestBody ExemptionsRequest exemptionsRequest){
exemptionsRequest.setState(RequestState.Pending);
err.save(exemptionsRequest);
return new ResponseEntity<>(HttpStatus.CREATED);
}
}

View File

@ -0,0 +1,8 @@
package ovh.herisson.Clyde.Repositories;
import org.springframework.data.repository.CrudRepository;
import ovh.herisson.Clyde.Tables.ExemptionsRequest;
public interface ExemptionsRequestRepository extends CrudRepository<ExemptionsRequest, Long> {
}

View File

@ -9,21 +9,16 @@ public class ExemptionsRequest {
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
@ManyToOne
@JoinColumn(name = "Users")
private User user;
@ManyToOne
@JoinColumn(name = "Course")
private Course course;
private long userRegNo;
private long courseId;
private String justifDocument;
private RequestState state;
public ExemptionsRequest(User user, Course course, String justifDocument, RequestState state){
this.user = user;
this.course = course;
public ExemptionsRequest(Long userRegNo, long courseId, String justifDocument, RequestState state){
this.userRegNo = userRegNo;
this.courseId = courseId;
this.justifDocument = justifDocument;
this.state = state;
}
@ -31,20 +26,20 @@ public class ExemptionsRequest {
public ExemptionsRequest(){}
public User getUser() {
return user;
public Long getUserRegNo() {
return userRegNo;
}
public void setUser(User user) {
this.user = user;
public void setUserRegNo(Long userRegNo) {
this.userRegNo = userRegNo;
}
public Course getCourse() {
return course;
public long getCourseId() {
return courseId;
}
public void setCourse(Course course) {
this.course = course;
public void setCourseId(long courseId) {
this.courseId = courseId;
}
public String getJustifDocument() {

View File

@ -1,8 +1,7 @@
package ovh.herisson.Clyde.Tables;
public enum FileType {
ProfilePicture,
EducationCertificate
EducationCertificate,
JustificationDocument
}

View File

@ -1,13 +1,15 @@
<script setup>
import i18n from "@/i18n.js"
import {getUser} from '../rest/Users.js'
import {getcurriculum, getSomeonesCurriculumList} from "@/rest/curriculum.js";
import {getcurriculum, getExternalCurriculumListByInscrReq, getSomeonesCurriculumList} from "@/rest/curriculum.js";
import {getRegisters} from "@/rest/ServiceInscription.js";
import {get} from "jsdom/lib/jsdom/named-properties-tracker.js";
const props = defineProps(['target']);
let request = await getRegisters(props.target);
const cursus = await getcurriculum(request.curriculum);
const externalCurriculum = await getExternalCurriculumListByInscrReq(request.id)
console.log(externalCurriculum)
function getPP(){
if(request.profilePictureUrl === null){
return "/Clyde.png"
@ -44,6 +46,19 @@ function getPP(){
</div>
</div>
</div>
<div class="moreInfos">
<div class = "oldcursus">
<div class="listTitle">
Cursus extérieurs a l'univesité
</div>
<div class="listElement">
<div class=" containerElement" v-for="item in externalCurriculum">
<div class="formation">item.formation</div>
<div class="school">item.school</div>
</div>
</div>
</div>
</div>
</div>
</div>
@ -152,4 +167,42 @@ button{
border-radius:20px;
}
.moreInfos {
display:grid;
grid-template-rows:200px auto;
column-gap:50px;
row-gap:45px;
grid-template-areas:
"minfos minfos";
grid-template-columns:600px 600px;
align-items:center;
justify-content:center;
margin-left: 320%;
}
.listTitle{
display: flex;
justify-content: center;
align-items: center;
width:250px;
margin-left:auto;
margin-right:auto;
border:2px solid black;
font-size:25px;
color:white;
padding:20px;
background-color:rgb(50,50,50);
border-radius:20px;margin-bottom:10px;
}
.listElement{
border:2px solid black;
font-size:25px;
color:white;
padding:20px;
background-color:rgb(50,50,50);
border-radius:20px;
margin-bottom:10px;
}
</style>

View File

@ -64,7 +64,7 @@
</div>
</div>
</div>
<div class="newcursus" >
<div class="newcursus">
<div class="listTitle">
Cursus Actuel
</div>

View File

@ -0,0 +1,145 @@
<script setup>
import {reactive, ref} from "vue";
import i18n from "@/i18n.js";
import {getCourse} from "@/rest/courses.js";
import {getcurriculum} from "@/rest/curriculum.js";
import {uploadFile, uploadProfilePicture} from "@/rest/uploads.js";
import {createExemptionsRequest} from "@/rest/requests.js";
import {getSelf} from "@/rest/Users.js";
const props = defineProps(["cursuslist"])
const selectedCurriculum = ref(props.cursuslist[0])
const user = await getSelf()
const courseslist = ref(await getcurriculum(selectedCurriculum.value.curriculumId))
const list = ref(true)
const ppData = ref({})
async function updateCourseList(){
courseslist.value = await getcurriculum(selectedCurriculum.value.curriculumId)
}
async function uploadfileandgetpath(file, type){
const a = await uploadFile(file, type);
exemptReq.justifDocument = a.url
}
async function postExemptionRequest(file, type){
const a = await uploadFile(file, type);
exemptReq.justifDocument = a.url
await createExemptionsRequest(exemptReq)
}
const exemptReq = reactive({
userRegNo : user.regNo,
courseId : null,
justifDocument : "e",
state : null
})
</script>
<template style="margin-top:5%;">
<div v-if="list == true">
<span>Selected Cursus : </span>
<select v-model="selectedCurriculum" @change="updateCourseList">
<option v-for="item in props.cursuslist" :value="item">Bac {{item.year}} {{item.option}}</option>
</select>
<div style="display:flex; justify-content:center;" v-for="item in courseslist.courses">
<div class="bodu">
<div class="container">
<div class="title">{{item.title}}</div>
<div class="firstname">{{item.owner.firstName}}</div>
<div class="lastname">{{item.owner.lastName}}</div>
<div class="credits">credits : {{item.credits}}</div>
<div class="askexemption"><button style="background-color:rgb(105,0,0);" @click="list= !list;exemptReq.courseId=item.courseId">Ask exemption</button></div>
</div>
</div>
</div>
</div>
<div v-else>
<p>Please upload the justification document for the exemption </p>
<label class="browser">
<input type="file" @change="ppData.value = $event.target.files" accept="image/*" ref="filepath">
</label>
<button style="width:15%; margin-top: 5%;" @click="postExemptionRequest(ppData.value, 'JustificationDocument');">
Submit exemption request
</button>
</div>
</template>
<style scoped>
.container{
color:white;
height:100px;
font-size:30px;
display:grid;
grid-template-columns:30% 20% 15% 15% 15%;
grid-template-areas:"title firstname lastname credits askexemption";
column-gap:10px;
}
.title {
grid-area:title;
align-self:center;
white-space: nowrap;
overflow: hidden;
text-overflow:ellipsis;
font-size: 50%;
margin-left:30px;
}
.credits {
grid-area:credits;
align-self:center;
white-space: nowrap;
overflow: hidden;
text-overflow:ellipsis;
font-size: 50%;
}
.askexemption {
grid-area:askexemption;
align-self:center;
white-space: nowrap;
overflow: hidden;
text-overflow:ellipsis;
}
.lastname{
grid-area:lastname;
align-self:center;
white-space: nowrap;
overflow: hidden;
text-overflow:ellipsis;
font-size: 50%;
}
.firstname{
grid-area:firstname;
align-self:center;
white-space: nowrap;
overflow: hidden;
text-overflow:ellipsis;
font-size: 50%;
padding-left: 30%;
}
.bodu {
margin-top:2%;
width:100%;
border:2px solid black;
border-radius:9px;
background-color:rgb(50,50,50);
}
button{
border:none;
background-color:rgb(239, 60, 168);
border-radius:10px;
height:35px;
margin-top:10px;
}
</style>

View File

@ -1,16 +1,18 @@
<script setup>
import {reactive, ref } from 'vue'
import {getSelf,alterSelf,disconnect,deleteUser} from '../rest/Users.js'
import {getSelfCurriculum, getAllCurriculums} from '../rest/curriculum.js'
import {getSelfCurriculum, getAllCurriculums, getSomeonesCurriculumList} from '../rest/curriculum.js'
import {getCourses} from "../rest/courses.js"
import i18n from "@/i18n.js"
import { uploadProfilePicture } from '@/rest/uploads.js'
import CourseList from "@/Apps/CourseList.vue";
const user = ref(await getSelf());
const UserCurriculum = ref("");
const curricula = ref (await getAllCurriculums());
if(user.value.role === "Student"){
UserCurriculum.value = await getSelfCurriculum();
UserCurriculum.value = await getSomeonesCurriculumList(user.value.regNo);
}
if(user.role === "Teacher"){
@ -19,6 +21,7 @@
const modif = ref(false);
const curric = ref(false);
const reg = ref(false);
const courseslist = ref(false);
const pattern = {
profilPictureUrl:null,
@ -86,17 +89,35 @@
}
return user.profilePictureUrl
}
function getYear(){
let date = new Date();
if (date.getMonth() <= 6){
return date.getFullYear()-1
}
return date.getFullYear()
}
//This function travels through the student cursus array and extract the current cursus of the student
function getActualCurriculumList(){
let actualCurriculumList = [];
for (let i = 0; i < UserCurriculum.value.curriculumList.length; i++){
if (UserCurriculum.value.curriculumList[i].dateyear === getYear()){
actualCurriculumList.push(UserCurriculum.value.curriculumList[i]);
}
}
return actualCurriculumList
}
</script>
<template>
<div class="body">
<div class="container">
<div class="container" v-if="courseslist == false">
<div class="profilPic">
<img class="subContainter" :src=getPP()>
</div>
<div class="globalInfos">
<div v-if="modif==false && curric==false && reg==false " class="infosContainer" >
<div v-if="modif==false && curric==false && reg==false" class="infosContainer">
<div>
{{user.firstName}} {{user.lastName}}
</div>
@ -119,6 +140,9 @@
<div v-if="(user.role==='Student')">
<button @click="curric=!curric">{{i18n("profile.change.curriculum")}}</button>
</div>
<div v-if="(user.role==='Student')">
<button @click="courseslist=!courseslist">Manage Courses</button>
</div>
</div>
<div v-else-if="modif" class="infosContainer">
<div>
@ -182,29 +206,38 @@
<button @click=" reg=!reg; resetInputs(personnalInfos,patternInfos);" style="float:right;">{{i18n("courses.back")}}</button>
</div>
</div>
</div>
<div v-if="modif==false && curric==false && reg==false "class="moreInfos">
<div v-if="(user.role ==='Student')">
<div class="listTitle">
{{i18n("profile.course.list")}}
<div class = "oldcursus">
<div class="listTitle">
Anciens Cursus
</div>
<div class="listElement">
<div class=" containerElement" v-for="item in UserCurriculum.curriculumList">
<div class="year" v-if="parseInt(item.dateyear) !== getYear()">Bac {{item.year}}</div>
<div class="option" v-if="parseInt(item.dateyear) !== getYear()">{{item.option}}</div>
<div class="dateyear" v-if="parseInt(item.dateyear) !== getYear()">Année {{item.dateyear}}-{{item.dateyear+1}}</div>
</div>
</div>
</div>
<div class="listElement" v-for="item in UserCurriculum.courses">
<div class=" containerElement">
<div class="name"> {{item.title}} </div>
<div class="teacher">{{item.owner.lastName}}</div>
<div class="credits">Credits:{{item.credits}}</div>
<div class="actualcursus">
<div class="listTitle">
Cursus Actuel
</div>
<div class="listElement">
<div class=" containerElement" v-for="item in UserCurriculum.curriculumList" >
<div class="year" v-if="parseInt(item.dateyear) === getYear()">Bac {{item.year}}</div>
<div class="option" v-if="parseInt(item.dateyear) === getYear()">{{item.option}}</div>
<div class="dateyear" v-if="parseInt(item.dateyear) === getYear()">Année {{item.dateyear}}-{{item.dateyear+1}}</div>
</div>
</div>
</div>
</div>
</div>
<div>
</div>
</div>
</div>
<div v-if="courseslist === true" style="width: 80%">
<CourseList :cursuslist="getActualCurriculumList()"/>
<button style="width: 10%; margin-top: 5%" @click="courseslist = false">Return to profile</button>
</div>
</div>
</template>
<style scoped>
@ -240,7 +273,32 @@
}
.moreInfos {
grid-area:minfos;
margin-top: 50%;
display:grid;
grid-template-rows:200px auto;
column-gap:50px;
row-gap:45px;
grid-template-areas:
"minfos minfos";
grid-template-columns:600px 600px;
align-items:center;
justify-content:center;
margin-left: 320%;
}
.listTitle{
display: flex;
justify-content: center;
align-items: center;
width:250px;
margin-left:auto;
margin-right:auto;
border:2px solid black;
font-size:25px;
color:white;
padding:20px;
background-color:rgb(50,50,50);
border-radius:20px;margin-bottom:10px;
}
.body {
min-width:960px;
@ -250,16 +308,17 @@
justify-content:center;
margin-top:5%;
}
.containerElement{
.containerElement{
justify-content:center;
display:grid;
grid-template-columns:38.8% 38.8% 22.4%;
grid-template-areas:
"name teacher credits";
column-gap:10px;
display:grid;
grid-template-columns:100px 100px 300px;
grid-template-areas:
"year option dateyear";
column-gap:40px;
padding-left: 25px;
}
.name {
grid-area:name;
align-self:center;
@ -275,24 +334,8 @@
align-self:center;
}
.listTitle{
min-width:197px;
display: flex;
justify-content: center;
align-items: center;
width:8vw;
margin-left:auto;
margin-right:auto;
border:2px solid black;
font-size:25px;
color:white;
padding:20px;
background-color:rgb(50,50,50);
border-radius:20px;margin-bottom:10px;
}
.listElement{
min-width:625px;
border:2px solid black;
font-size:25px;
color:white;

View File

@ -3,7 +3,7 @@
*
* TODO: On time of writing, the backend doesn't support these endpoints so it could be modified in the future.
*/
import {restGet, restPatch} from './restConsumer.js'
import {restGet, restPatch, restPost} from './restConsumer.js'
/**
* create a new register requests that can be recovered by the registering service

View File

@ -64,3 +64,7 @@ export async function createExternalCurriculum(inscriptionRequestId,school, form
justifdocUrl : justifdocUrl
})
}
export async function getExternalCurriculumListByInscrReq(inscriptionRequestId){
return restGet("/externalCurriculum/"+parseInt(inscriptionRequestId))
}

View File

@ -0,0 +1,5 @@
import {restPost} from "@/rest/restConsumer.js";
export async function createExemptionsRequest(exempReq){
return restPost("/exemptionreq", exempReq)
}