1
0
forked from PGL/Clyde

5 Commits

115 changed files with 599 additions and 5434 deletions

View File

@ -9,33 +9,10 @@ Projet du groupe 01:
- William Karpinski: Extension gestion des horaires
- Léo Moulin: Extension inscription des étudiants
## Running
Le projet peut être lancé grace à docker compose.
```sh
$ docker compose up
```
Dans le cas ou vous modifiers des fichiers, pour éviter que les images de docker soient recrées avec les changement
```sh
$ docker compose up --force-recreate --build
```
## Dévelopement
Dans le cas ou vous êtes dans une phase de développement, il est plus simple d'utiliser gradle pour lancer le backend et frontend dans un mode de développement.
**Attention**: Ce mode n'est pas fait pour être utilisé en production!
```sh
$ ./gradlew run --parallel
```
$ ./gradlew backend:run frontend:run --parallel
```
permet de lancer le frontend sur [http://localhost:5173](http://localhost:5173) ansi que le frontend sur [http://localhost:8080](http://localhost:8080)
Ceci requière également docker pour lancer une instance de postgresql pris en charge par spring.
Il est possible de se passer entièrement de docker en supprimant la dépendance dans le fichier `backend/build.gradle.kts`: ~~`developmentOnly("org.springframework.boot:spring-boot-docker-compose")`~~
Il est alors nécéssaire d'avoir une instance de postgresql tournant sur `localhost:5432` avec une table `clyde`, utilisateur: `devel` et password: `devel`
(cette configuration peut également être changée dans le fichier resources/application.properties de spring)

View File

@ -1,15 +1,6 @@
## Building phase
FROM gradle:jdk21-alpine AS BUILD
WORKDIR /backend
COPY . .
RUN gradle build -x test
## Running Phase
FROM eclipse-temurin:21-jdk-alpine
WORKDIR /backend
VOLUME /tmp
VOLUME /cdn
# ENV SPRING_PROFILES_ACTIVE=prod
COPY --from=BUILD /backend/build/libs/Clyde-0.0.1-SNAPSHOT.jar /backend/app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "/backend/app.jar"]
ENV SPRING_PROFILES_ACTIVE=prod
COPY build/libs/backend-0.0.1-SNAPSHOT.jar /app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]

View File

@ -16,8 +16,6 @@ repositories {
}
dependencies {
compileOnly("org.projectlombok:lombok")
annotationProcessor("org.projectlombok:lombok")
implementation("org.springframework.boot:spring-boot-starter-jdbc")
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
implementation("org.springframework.boot:spring-boot-starter-mail")
@ -27,7 +25,7 @@ dependencies {
implementation("com.kohlschutter.junixsocket:junixsocket-core:2.9.0")
// implementation("org.springframework.session:spring-session-jdbc")
developmentOnly("org.springframework.boot:spring-boot-devtools")
// developmentOnly("org.springframework.boot:spring-boot-docker-compose")
developmentOnly("org.springframework.boot:spring-boot-docker-compose")
runtimeOnly("org.postgresql:postgresql")
testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation("org.springframework.boot:spring-boot-testcontainers")

View File

@ -1,13 +0,0 @@
/*
* This file was generated by the Gradle 'init' task.
*
* The settings file is used to specify which projects to include in your build.
* For more detailed information on multi-project builds, please refer to https://docs.gradle.org/8.6/userguide/multi_project_builds.html in the Gradle documentation.
*/
plugins {
// Apply the foojay-resolver plugin to allow automatic download of JDKs
id("org.gradle.toolchains.foojay-resolver-convention") version "0.7.0"
}
rootProject.name = "Clyde"

View File

@ -1,34 +0,0 @@
package ovh.herisson.Clyde.DTO.Msg;
/******************************************************
* @file DiscussionDTO.java
* @author Anthony Debucquoy
* @scope Extension messagerie
*
* File to format a discussion using messageDTO
******************************************************/
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import lombok.AllArgsConstructor;
import lombok.Data;
import ovh.herisson.Clyde.Tables.User;
import ovh.herisson.Clyde.Tables.Msg.Discussion;
import ovh.herisson.Clyde.DTO.Msg.MessagesDTO;
@Data
@AllArgsConstructor
public class DiscussionDTO {
private long id;
private String name;
private List<User> members;
private List<MessagesDTO> msgs;
public static DiscussionDTO construct(Discussion d, User u){
List<MessagesDTO> msgsdto = new ArrayList<>();
d.getMsgs().forEach(x -> msgsdto.add(MessagesDTO.construct(x, u)));
return new DiscussionDTO(d.getId(), d.getName(), d.getMembers(), msgsdto);
}
}

View File

@ -1,33 +0,0 @@
package ovh.herisson.Clyde.DTO.Msg;
/******************************************************
* @file MessagesDTO.java
* @author Anthony Debucquoy
* @scope Extension messagerie
*
* File to Format the response adding the sender field
******************************************************/
import lombok.AllArgsConstructor;
import lombok.Data;
import ovh.herisson.Clyde.Tables.User;
import ovh.herisson.Clyde.Tables.Msg.Message;
import java.util.Date;
@Data
@AllArgsConstructor
public class MessagesDTO {
private long id;
private String content;
private User author;
private boolean sender;
private Date created;
//TODO: Attachment
public static MessagesDTO construct(Message m, User user){
boolean sender = false;
if(m.getAuthor().equals(user))
sender = true;
return new MessagesDTO(m.getId(), m.getContent(), m.getAuthor(), sender, m.getCreated());
}
}

View File

@ -1,53 +0,0 @@
package ovh.herisson.Clyde.DTO.ScientificPublications;
/******************************************************
* @file ResearchDTO.java
* @author Bartha Maxime
* @scope Publications Scientifiques
*
* Research format to return to front (without author's password)
******************************************************/
import lombok.Data;
import ovh.herisson.Clyde.Tables.ScientificPublications.Access;
import ovh.herisson.Clyde.Tables.ScientificPublications.PaperType;
import ovh.herisson.Clyde.Tables.ScientificPublications.Research;
import java.util.Date;
@Data
public class ResearchDTO {
private long id;
private String title;
private ResearcherDTO researcher;
private Date releaseDate;
private PaperType paperType;
private String pdfLocation;
private String language;
private Access access;
private String domain;
private String summary;
private long views;
private ResearchDTO(String title, ResearcherDTO researcherDTO, Date releaseDate, PaperType paperType, String pdfLocation, String language, Access access, String domain, String summary, long id,long views) {
this.title = title;
this.researcher = researcherDTO;
this.releaseDate = releaseDate;
this.paperType = paperType;
this.pdfLocation = pdfLocation;
this.language = language;
this.access = access;
this.domain = domain;
this.summary = summary;
this.id = id;
this.views = views;
}
public static ResearchDTO construct(Research research){
return new ResearchDTO(research.getTitle(), ResearcherDTO.construct(research.getAuthor()), research.getReleaseDate(),
research.getPaperType(),research.getPdfLocation(),research.getLanguage(),research.getAccess(),
research.getDomain(), research.getSummary(), research.getId(), research.getViews());
}
}

View File

@ -1,38 +0,0 @@
package ovh.herisson.Clyde.DTO.ScientificPublications;
/******************************************************
* @file ResearcherDTO.java
* @author Bartha Maxime
* @scope Publications Scientifiques
*
* Researcher Format to return to front (without user password)
******************************************************/
import lombok.Data;
import ovh.herisson.Clyde.Services.ProtectionService;
import ovh.herisson.Clyde.Tables.ScientificPublications.Researcher;
import java.util.Map;
@Data
public class ResearcherDTO {
private long id;
private Map<String,Object> user;
private String site;
private String domain;
private String orcidId;
private ResearcherDTO(long id, Map<String ,Object> user, String site,String domain,String orcidId){
this.domain = domain;
this.orcidId = orcidId;
this.site = site;
this.user = user;
this.id = id;
}
public static ResearcherDTO construct(Researcher researcher){
return new ResearcherDTO(researcher.getId(), ProtectionService.userWithoutPassword(researcher.getUser()),researcher.getSite(),
researcher.getDomain(),researcher.getOrcidId());
}
}

View File

@ -1,6 +1,5 @@
package ovh.herisson.Clyde.EndPoints;
import lombok.AllArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
@ -9,7 +8,6 @@ import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;
import ovh.herisson.Clyde.Services.AuthenticatorService;
import ovh.herisson.Clyde.Services.ScientificPublications.ResearchesService;
import ovh.herisson.Clyde.Tables.Applications;
import ovh.herisson.Clyde.Tables.Role;
import ovh.herisson.Clyde.Tables.User;
@ -22,10 +20,7 @@ public class ApplicationsController {
AuthenticatorService authServ;
ResearchesService researchesServ;
public ApplicationsController(AuthenticatorService authServ, ResearchesService researchesServ){
this.researchesServ = researchesServ;
public ApplicationsController(AuthenticatorService authServ){
this.authServ = authServ;
}
@ -69,15 +64,12 @@ public class ApplicationsController {
if (!authServ.isNotIn(new Role[]{Role.Teacher,Role.Secretary,Role.Admin},token))
authorizedApps.add(Applications.ManageCourses);
if (!authServ.isNotIn(new Role[]{Role.InscriptionService,Role.Admin, Role.Teacher},token)){
authorizedApps.add(Applications.Requests);
if (!authServ.isNotIn(new Role[]{Role.InscriptionService,Role.Admin},token)){
authorizedApps.add(Applications.Inscription);
authorizedApps.add(Applications.StudentsList);}
if (!authServ.isNotIn(new Role[]{Role.Secretary,Role.Admin},token)){
authorizedApps.add(Applications.UsersList);}
if (researchesServ.getResearcherByUser(user) != null)
authorizedApps.add(Applications.ManageResearcherProfile);
return authorizedApps;
}
}

View File

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

View File

@ -4,13 +4,11 @@ package ovh.herisson.Clyde.EndPoints;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import ovh.herisson.Clyde.Repositories.Inscription.ExternalCurriculumRepository;
import ovh.herisson.Clyde.Repositories.Inscription.InscriptionRepository;
import ovh.herisson.Clyde.Responses.UnauthorizedResponse;
import ovh.herisson.Clyde.Services.*;
import ovh.herisson.Clyde.Tables.*;
import ovh.herisson.Clyde.Tables.Curriculum;
import ovh.herisson.Clyde.Tables.Role;
import java.util.HashMap;
import java.util.Map;
@RestController
@ -23,18 +21,12 @@ public class CurriculumController {
private final UserCurriculumService userCurriculumServ;
private final CurriculumCourseService curriculumCourseServ;
private final InscriptionRepository ir;
private final UserService userServ;
private final ExternalCurriculumRepository ecr;
public CurriculumController(CurriculumService curriculumServ, AuthenticatorService authServ, UserCurriculumService userCurriculumServ, CurriculumCourseService curriculumCourseServ, InscriptionRepository ir, UserService userServ, ExternalCurriculumRepository ecr){
public CurriculumController(CurriculumService curriculumServ, AuthenticatorService authServ, UserCurriculumService userCurriculumServ, CurriculumCourseService curriculumCourseServ){
this.curriculumServ = curriculumServ;
this.authServ = authServ;
this.userCurriculumServ = userCurriculumServ;
this.curriculumCourseServ = curriculumCourseServ;
this.ir = ir;
this.userServ = userServ;
this.ecr = ecr;
}
@GetMapping("/curriculum/{id}")
@ -60,22 +52,6 @@ public class CurriculumController {
return new ResponseEntity<>(curriculumCourseServ.getDepthCurriculum(curriculum),HttpStatus.OK);
}
//Return the list of all curicullums of an user
@GetMapping("/onescurriculum/{userId}")
public ResponseEntity<Map<String ,Object>> findOnesCurriculum(@RequestHeader("Authorization") String token, @PathVariable String userId){
if (authServ.getUserFromToken(token) == null)
return new UnauthorizedResponse<>(null);
User u = userServ.getUserById(Long.parseLong(userId));
HashMap<String,Object> toReturn = userCurriculumServ.findAllCurriculumByStudent(u);
if (toReturn == null)
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
return new ResponseEntity<>(toReturn,HttpStatus.OK);
}
@GetMapping("/curriculums")
public ResponseEntity<Iterable<Map<String, Object>>> findAllIndDepth(){
return new ResponseEntity<>(curriculumCourseServ.getAllDepthCurriculum(),HttpStatus.OK);
@ -118,5 +94,4 @@ public class CurriculumController {
curriculumServ.delete(toDelete);
return new ResponseEntity<>(HttpStatus.OK);
}
}

View File

@ -1,55 +0,0 @@
package ovh.herisson.Clyde.EndPoints.Inscription;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import ovh.herisson.Clyde.Repositories.Inscription.ExternalCurriculumRepository;
import ovh.herisson.Clyde.Repositories.Inscription.InscriptionRepository;
import ovh.herisson.Clyde.Repositories.UserRepository;
import ovh.herisson.Clyde.Tables.Inscription.ExternalCurriculum;
import ovh.herisson.Clyde.Tables.Inscription.InscriptionRequest;
import ovh.herisson.Clyde.Tables.User;
import java.util.ArrayList;
import java.util.Map;
@RestController
@CrossOrigin(originPatterns = "*", allowCredentials = "true")
public class ExternalCurriculumController {
public final ExternalCurriculumRepository ecr;
public final InscriptionRepository inscriptionRepository;
public final UserRepository userRepository;
public ExternalCurriculumController(ExternalCurriculumRepository ecr, InscriptionRepository inscriptionRepository, UserRepository userRepository) {
this.ecr = ecr;
this.inscriptionRepository = inscriptionRepository;
this.userRepository = userRepository;
}
//everyone can post some externalcurriculums (the validity of the elements is assured by the inscription service)
@PostMapping("/externalcurriculum")
public ResponseEntity<ExternalCurriculum> postExternalCurriculum(@RequestBody Map<String, Object> externalCurrInfos){
InscriptionRequest ir = inscriptionRepository.findById((Integer) externalCurrInfos.get("inscriptionRequestId"));
ExternalCurriculum toSave = new ExternalCurriculum(ir, (String) externalCurrInfos.get("school"),(String) externalCurrInfos.get("formation"),(String) externalCurrInfos.get("completion"), (Integer)externalCurrInfos.get("startYear"), (Integer)externalCurrInfos.get("endYear"), (String)externalCurrInfos.get("justifDocUrl"), null);
return new ResponseEntity<>(ecr.save(toSave), HttpStatus.OK);
}
@GetMapping("/externalcurriculum/{inscReqId}")
public ResponseEntity<ArrayList<ExternalCurriculum>> getExternalCurrListByInscrReq(@PathVariable long inscReqId){
InscriptionRequest ir = inscriptionRepository.findById(inscReqId);
ArrayList<ExternalCurriculum> toReturn = ecr.getExternalCurriculumByInscriptionRequest(ir);
return new ResponseEntity<>(toReturn, HttpStatus.OK);
}
@GetMapping("/externalcurriculumbyuser/{userId}")
public ResponseEntity<ArrayList<ExternalCurriculum>> getExternalCurrByUser(@PathVariable long userId){
User user = userRepository.findById(userId);
ArrayList<ExternalCurriculum> toReturn = ecr.getExternalCurriculumByUser(user);
return new ResponseEntity<>(toReturn, HttpStatus.OK);
}
}

View File

@ -1,55 +0,0 @@
package ovh.herisson.Clyde.EndPoints.Inscription;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import ovh.herisson.Clyde.Repositories.Inscription.MinervalRepository;
import ovh.herisson.Clyde.Responses.UnauthorizedResponse;
import ovh.herisson.Clyde.Services.AuthenticatorService;
import ovh.herisson.Clyde.Tables.Inscription.Minerval;
import ovh.herisson.Clyde.Tables.Role;
import java.util.*;
@RestController
@CrossOrigin(originPatterns = "*", allowCredentials = "true")
public class MinervalController {
private final AuthenticatorService authServ;
private final MinervalRepository mr;
public MinervalController(AuthenticatorService authServ, MinervalRepository mr) {
this.authServ = authServ;
this.mr = mr;
}
//A new minerval entry is posted when the inscription service accept a registration request
@PostMapping("/minerval/{studentRegNo}")
public ResponseEntity<Object> postMinerval(@RequestHeader("Authorization") String token, @PathVariable long studentRegNo){
if (authServ.isNotIn(new Role[]{Role.Admin,Role.Secretary,Role.InscriptionService},token))
return new UnauthorizedResponse<>(null);
Calendar c = new GregorianCalendar();
mr.save(new Minerval(studentRegNo, 0, 835, c.get(Calendar.YEAR)));
return new ResponseEntity<>(HttpStatus.OK);
}
@GetMapping("/minerval/{studentRegNo}")
public ResponseEntity<Minerval> getCurrentMinervalbyRegNo(@PathVariable long studentRegNo){
ArrayList<Minerval> mlist = mr.getMinervalsByStudentRegNoOrderByYearDesc(studentRegNo);
//The list is ordered by year in descending order then the index 0 contains the actual minerval (for this year)
Minerval m = mlist.get(0);
return new ResponseEntity<>(m, HttpStatus.OK);
}
@PatchMapping("/minerval")
public ResponseEntity<Object> updateMinerval(@RequestBody Minerval updatedMinerval){
Minerval minerval = mr.findById(updatedMinerval.getId());
minerval.setPaidAmount(updatedMinerval.getPaidAmount());
minerval.setToPay(updatedMinerval.getToPay());
mr.save(minerval);
return new ResponseEntity<>(HttpStatus.OK);
}
}

View File

@ -1,37 +0,0 @@
package ovh.herisson.Clyde.EndPoints.Inscription;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import ovh.herisson.Clyde.Repositories.Inscription.PaymentRepository;
import ovh.herisson.Clyde.Tables.Inscription.Payment;
import java.util.ArrayList;
@RestController
@CrossOrigin(originPatterns = "*", allowCredentials = "true")
public class PaymentController {
private final PaymentRepository paymentRepository;
public PaymentController(PaymentRepository paymentRepository){
this.paymentRepository = paymentRepository;
}
//Post a payment record
@PostMapping("/payment")
public ResponseEntity<Object> postPayment(@RequestBody Payment payment){
paymentRepository.save(payment);
return new ResponseEntity<>(HttpStatus.OK);
}
//Get all payment records of a student
@GetMapping("/payment/{studentRegNo}")
public ResponseEntity<ArrayList<Payment>> getPaymentsByUser(@PathVariable long studentRegNo){
ArrayList<Payment> toReturn = paymentRepository.getPaymentsByStudentRegNo(studentRegNo);
return new ResponseEntity<>(toReturn, HttpStatus.OK);
}
}

View File

@ -1,97 +0,0 @@
package ovh.herisson.Clyde.EndPoints.Inscription;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import ovh.herisson.Clyde.Repositories.CourseRepository;
import ovh.herisson.Clyde.Repositories.Inscription.ExemptionsRequestRepository;
import ovh.herisson.Clyde.Repositories.Inscription.ScholarshipRequestRepository;
import ovh.herisson.Clyde.Repositories.Inscription.UninscriptionRequestRepository;
import ovh.herisson.Clyde.Repositories.UserRepository;
import ovh.herisson.Clyde.Responses.UnauthorizedResponse;
import ovh.herisson.Clyde.Services.AuthenticatorService;
import ovh.herisson.Clyde.Tables.*;
import ovh.herisson.Clyde.Tables.Inscription.ExemptionsRequest;
import ovh.herisson.Clyde.Tables.Inscription.ScholarshipRequest;
import ovh.herisson.Clyde.Tables.Inscription.UninscriptionRequest;
import java.util.ArrayList;
import java.util.Date;
import java.util.Map;
@RestController
@CrossOrigin(originPatterns = "*", allowCredentials = "true")
public class RequestsController {
public final ExemptionsRequestRepository err;
public final ScholarshipRequestRepository srr;
public final UserRepository userRepository;
public final AuthenticatorService authServ;
public final UninscriptionRequestRepository uninscriptionRequestRepository;
public final CourseRepository courseRepository;
public RequestsController(ExemptionsRequestRepository err, ScholarshipRequestRepository srr, UserRepository userRepository, AuthenticatorService authServ, UninscriptionRequestRepository uninscriptionRequestRepository, CourseRepository courseRepository) {
this.err = err;
this.srr = srr;
this.userRepository = userRepository;
this.authServ = authServ;
this.uninscriptionRequestRepository = uninscriptionRequestRepository;
this.courseRepository = courseRepository;
}
@PostMapping(value="/exemptionreq")
public ResponseEntity<String> createExemptionReq(@RequestBody Map<String, Object> exemptionsRequestInfo){
User user = userRepository.findById((Integer) exemptionsRequestInfo.get("userRegNo"));
Course course = courseRepository.findById((Integer) exemptionsRequestInfo.get("courseId"));
ExemptionsRequest exemptionsRequest = new ExemptionsRequest(user, course, (String) exemptionsRequestInfo.get("justifDocument"), RequestState.Pending, new Date());
err.save(exemptionsRequest);
return new ResponseEntity<>(HttpStatus.CREATED);
}
@PostMapping(value="/scholarshipreq")
public ResponseEntity<String> createScholarshipReq(@RequestBody Map<String, Object> scholarshipRequestInfo){
User user = userRepository.findById((Integer)scholarshipRequestInfo.get("userId"));
ScholarshipRequest toCreate = new ScholarshipRequest(user, RequestState.Pending, 0, new Date(), (String) scholarshipRequestInfo.get("taxDocUrl"), (String) scholarshipRequestInfo.get("residencyDocUrl"));
srr.save(toCreate);
return new ResponseEntity<>(HttpStatus.CREATED);
}
//Get all the exemptions Request
@GetMapping(value = "/exemptionsreq")
public ResponseEntity<ArrayList<ExemptionsRequest>> getAllExemptionsRequests(@RequestHeader("Authorization") String token){
if (authServ.isNotIn(new Role[]{Role.Admin,Role.Secretary,Role.InscriptionService},token))
return new UnauthorizedResponse<>(null);
ArrayList<ExemptionsRequest> toReturn = new ArrayList<>();
err.findAll().forEach(toReturn::add);
return new ResponseEntity<>(toReturn, HttpStatus.OK);
}
//Get all the scholarships requests
@GetMapping(value = "/scholarshipreq")
public ResponseEntity<ArrayList<ScholarshipRequest>> getAllScholarshipRequests(@RequestHeader("Authorization") String token){
if (authServ.isNotIn(new Role[]{Role.Admin,Role.Secretary,Role.InscriptionService},token))
return new UnauthorizedResponse<>(null);
ArrayList<ScholarshipRequest> toReturn = new ArrayList<>();
srr.findAll().forEach(toReturn::add);
return new ResponseEntity<>(toReturn, HttpStatus.OK);
}
@PostMapping(value = "/uninscriptionreq")
public ResponseEntity<String> postUnregReq(@RequestBody Map<String,Object> uninscr){
User u = userRepository.findById((int) uninscr.get("userId"));
UninscriptionRequest ur = new UninscriptionRequest(RequestState.Pending, (String) uninscr.get("reason"), new Date(), u);
uninscriptionRequestRepository.save(ur);
return new ResponseEntity<>(HttpStatus.OK);
}
}

View File

@ -1,13 +1,13 @@
package ovh.herisson.Clyde.EndPoints.Inscription;
package ovh.herisson.Clyde.EndPoints;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import ovh.herisson.Clyde.Responses.UnauthorizedResponse;
import ovh.herisson.Clyde.Services.AuthenticatorService;
import ovh.herisson.Clyde.Services.Inscription.InscriptionService;
import ovh.herisson.Clyde.Services.InscriptionService;
import ovh.herisson.Clyde.Services.ProtectionService;
import ovh.herisson.Clyde.Tables.Inscription.InscriptionRequest;
import ovh.herisson.Clyde.Tables.InscriptionRequest;
import ovh.herisson.Clyde.Tables.RequestState;
import ovh.herisson.Clyde.Tables.Role;
import java.util.Map;
@ -79,22 +79,4 @@ public class InscriptionController {
return new ResponseEntity<>(HttpStatus.OK);
}
//Allow teacher or admin to accept or refuse the equivalence
@PatchMapping("/request/registerequiv/{id}/{newstate}")
public ResponseEntity<Object> editRegisterEquiv(@RequestHeader("Authorization") String token, @PathVariable long id, @PathVariable RequestState newstate){
if (authServ.isNotIn(new Role[]{Role.Admin,Role.Teacher}, token))
return new UnauthorizedResponse<>(null);
InscriptionRequest toEdit = inscriptionServ.getById(id);
toEdit.setEquivalenceState(newstate);
inscriptionServ.save(toEdit);
if (toEdit.getState() == RequestState.Accepted && (toEdit.getEquivalenceState() == RequestState.Accepted || toEdit.getEquivalenceState() == RequestState.Unrequired))
{
inscriptionServ.createUser(toEdit);
}
return new ResponseEntity<>(HttpStatus.OK);
}
}

View File

@ -5,14 +5,10 @@ import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import ovh.herisson.Clyde.Repositories.CurriculumRepository;
import ovh.herisson.Clyde.Responses.UnauthorizedResponse;
import ovh.herisson.Clyde.Services.AuthenticatorService;
import ovh.herisson.Clyde.Services.ProtectionService;
import ovh.herisson.Clyde.Tables.Curriculum;
import ovh.herisson.Clyde.Tables.Inscription.InscriptionRequest;
import ovh.herisson.Clyde.Tables.RequestState;
import ovh.herisson.Clyde.Tables.InscriptionRequest;
import java.util.Date;
import java.util.Map;
@ -20,7 +16,7 @@ import java.util.Map;
@CrossOrigin(originPatterns = "*", allowCredentials = "true")
public class LoginController {
private final AuthenticatorService authServ;
private final CurriculumRepository curriculumRepository;
static public class RequestLogin{
private final String identifier;
private final String password;
@ -33,9 +29,8 @@ public class LoginController {
}
}
public LoginController(AuthenticatorService authServ, CurriculumRepository curriculumRepository){
public LoginController(AuthenticatorService authServ){
this.authServ = authServ;
this.curriculumRepository = curriculumRepository;
}
@PostMapping(value = "/login")
@ -53,18 +48,9 @@ public class LoginController {
@PostMapping("/register")
public ResponseEntity<Map<String,Object>> register(@RequestBody InscriptionRequest inscriptionRequest){
//We ensure here that if the targeted cursus year is more than first grade then we need the teacher equivalence approval
Curriculum curr = curriculumRepository.findById(inscriptionRequest.getCurriculumId());
if (curr.getYear() > 1){
inscriptionRequest.setEquivalenceState(RequestState.Pending);
}else{
inscriptionRequest.setEquivalenceState(RequestState.Unrequired);
}
InscriptionRequest returnedInscriptionRequest = authServ.register(inscriptionRequest);
return new ResponseEntity<>(ProtectionService.requestWithoutPassword(returnedInscriptionRequest), HttpStatus.CREATED);
}
}

View File

@ -2,60 +2,40 @@ package ovh.herisson.Clyde.EndPoints;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.*;
import ovh.herisson.Clyde.Repositories.*;
import ovh.herisson.Clyde.Repositories.Inscription.ExternalCurriculumRepository;
import ovh.herisson.Clyde.Repositories.Inscription.MinervalRepository;
import ovh.herisson.Clyde.Repositories.Inscription.ScholarshipRequestRepository;
import ovh.herisson.Clyde.Repositories.TokenRepository;
import ovh.herisson.Clyde.Repositories.UserRepository;
import ovh.herisson.Clyde.Services.*;
import ovh.herisson.Clyde.Services.ScientificPublications.ResearchesService;
import ovh.herisson.Clyde.Tables.*;
import ovh.herisson.Clyde.Tables.ScientificPublications.Access;
import ovh.herisson.Clyde.Tables.ScientificPublications.PaperType;
import ovh.herisson.Clyde.Tables.ScientificPublications.Research;
import ovh.herisson.Clyde.Tables.ScientificPublications.Researcher;
import ovh.herisson.Clyde.Services.Inscription.InscriptionService;
import ovh.herisson.Clyde.Tables.Inscription.ExternalCurriculum;
import ovh.herisson.Clyde.Tables.Inscription.InscriptionRequest;
import ovh.herisson.Clyde.Tables.Inscription.Minerval;
import ovh.herisson.Clyde.Tables.Inscription.ScholarshipRequest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
@RestController
@CrossOrigin(originPatterns = "*", allowCredentials = "true")
public class MockController {
private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
public final UserService userService;
public final UserRepository userRepo;
public final TokenRepository tokenRepo;
public final TokenService tokenService;
public final CurriculumCourseService CurriculumCourseService;
public final CurriculumService curriculumService;
public final CourseService courseService;
public final ExternalCurriculumRepository externalCurriculumRepository;
public final InscriptionService inscriptionService;
public final ResearchesService researchesService;
public final UserCurriculumRepository ucr;
public final MinervalRepository minervalRepository;
public final ScholarshipRequestRepository scholarshipRequestRepository;
ArrayList<User> mockUsers;
public MockController(UserRepository userRepo, TokenRepository tokenRepo, TokenService tokenService, CurriculumCourseService CurriculumCourseService, CurriculumService curriculumService, CourseService courseService, ExternalCurriculumRepository externalCurriculumRepository, ResearchesService researchesService, InscriptionService inscriptionService, UserCurriculumRepository ucr, MinervalRepository minervalRepository, ScholarshipRequestRepository scholarshipRequestRepository){
public MockController(UserService userService, UserRepository userRepo, TokenRepository tokenRepo, TokenService tokenService, CurriculumCourseService CurriculumCourseService, CurriculumService curriculumService, CourseService courseService, InscriptionService inscriptionService){
this.userService = userService;
this.tokenRepo = tokenRepo;
this.userRepo = userRepo;
this.tokenService = tokenService;
this.CurriculumCourseService = CurriculumCourseService;
this.curriculumService = curriculumService;
this.courseService = courseService;
this.externalCurriculumRepository = externalCurriculumRepository;
this.inscriptionService = inscriptionService;
this.researchesService = researchesService;
this.ucr = ucr;
this.minervalRepository = minervalRepository;
this.scholarshipRequestRepository = scholarshipRequestRepository;
}
/** Saves an example of each user type by :
@ -65,99 +45,58 @@ public class MockController {
*/
@PostMapping("/mock")
public void postMock() {
public void postMock(){
// user part
// user part
User herobrine = new User("brine", "hero", "admin@admin.com", "behind", "ShadowsLand", new Date(0), null, Role.Admin, passwordEncoder.encode("admin"));
User joe = new User("Mama", "Joe", "student@student.com", "roundabout", "England", new Date(0), null, Role.Student, passwordEncoder.encode("student"));
User meh = new User("Polo", "Marco", "secretary@secretary.com", "a Box", "Monaco", new Date(0), null, Role.Secretary, passwordEncoder.encode("secretary"));
User joke = new User("Gaillard", "Corentin", "teacher@teacher.com", "lab", "faculty", new Date(0), null, Role.Teacher, passwordEncoder.encode("teacher"));
User jojo = new User("Bridoux", "Justin", "teacher2@teacher2.com", "lab", "faculty", new Date(0), null, Role.Teacher, passwordEncoder.encode("teacher"));
User lena = new User("Louille", "Lena", "inscriptionService@InscriptionService.com", "no", "yes", new Date(0), null, Role.InscriptionService, passwordEncoder.encode("inscriptionService"));
User popo = new User("Smith", "Paul", "paulsmith@gmail.com", "306 rue du poulet", "belgique", new Date(0), null, Role.Student, passwordEncoder.encode("jesuispaulleroi"));
mockUsers = new ArrayList<>(Arrays.asList(herobrine, joe, meh, joke, lena, jojo, popo));
User herobrine = new User("brine","hero","admin@admin.com","behind","ShadowsLand",new Date(0), null,Role.Admin,passwordEncoder.encode("admin"));
User joe = new User("Mama","Joe","student@student.com","roundabout","England",new Date(0), null,Role.Student,passwordEncoder.encode("student"));
User meh = new User("Polo","Marco","secretary@secretary.com","a Box","Monaco",new Date(0), null,Role.Secretary,passwordEncoder.encode("secretary"));
User joke = new User("Gaillard","Corentin","teacher@teacher.com","lab","faculty",new Date(0), null,Role.Teacher,passwordEncoder.encode("teacher"));
User jojo = new User("Bridoux","Justin","teacher2@teacher2.com","lab","faculty",new Date(0), null,Role.Teacher,passwordEncoder.encode("teacher"));
User lena = new User("Louille","Lena","inscriptionService@InscriptionService.com","no","yes",new Date(0), null,Role.InscriptionService,passwordEncoder.encode("inscriptionService"));
userRepo.saveAll(mockUsers);
Minerval minerval = new Minerval(joe.getRegNo(), 0, 852, 2023);
minervalRepository.save(minerval);
// Course / Curriculum part
Curriculum infoBab1 = new Curriculum(1, "info");
Curriculum chemistryBab1 = new Curriculum(1, "chemistry");
Curriculum psychologyBab1 = new Curriculum(1, "psychology");
Curriculum infoBab2 = new Curriculum(2, "info");
Curriculum masterinfo1 = new Curriculum(4, "info");
Curriculum masterinfo2 = new Curriculum(5, "info");
curriculumService.save(infoBab1);
curriculumService.save(chemistryBab1);
curriculumService.save(psychologyBab1);
curriculumService.save(infoBab2);
curriculumService.save(masterinfo1);
curriculumService.save(masterinfo2);
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));
Course progra1 = new Course(5, "Programmation et algorithmique 1", joke);
Course chemistry1 = new Course(12, "Thermochimie", joke);
Course psycho1 = new Course(21, "Neuroreaction of isolated brain cells", joke);
Course commun = new Course(2, "cours commun", joke);
courseService.save(progra1);
courseService.save(chemistry1);
courseService.save(psycho1);
courseService.save(commun);
ScholarshipRequest ssr1 = new ScholarshipRequest(joe, RequestState.Pending, 0, new Date(), "test", "test");
scholarshipRequestRepository.save(ssr1);
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));
mockUsers = new ArrayList<>(Arrays.asList(joke, herobrine, joe, meh, jojo));
userService.saveAll(mockUsers);
userService.save(lena);
CurriculumCourseService.save(new CurriculumCourse(chemistryBab1, commun));
CurriculumCourseService.save(new CurriculumCourse(chemistryBab1, chemistry1));
//Course / Curriculum part
Curriculum infoBab1 = new Curriculum(1,"info");
Curriculum chemistryBab1 = new Curriculum(1,"chemistry");
Curriculum psychologyBab1 = new Curriculum(1,"psychology");
curriculumService.save(infoBab1);
curriculumService.save(chemistryBab1);
curriculumService.save(psychologyBab1);
InscriptionRequest inscriptionRequest = new InscriptionRequest("helen", "prenom", "non", "helen@gmail.com", "america", new Date(), (long) 4, RequestState.Pending, "yes.png", "password", null, new Date(), RequestState.Pending);
Course progra1 = new Course(5,"Programmation et algorithmique 1",joke);
Course chemistry1 = new Course(12, "Thermochimie",joke);
Course psycho1 = new Course(21, "Neuroreaction of isolated brain cells",joke);
Course commun = new Course(2, "cours commun",joke);
inscriptionService.save(inscriptionRequest);
ExternalCurriculum externalCurriculum = new ExternalCurriculum(inscriptionRequest, "HEH", "Bachelier en informatique", "Completed", 2015, 2018, null, null);
externalCurriculumRepository.save(externalCurriculum);
///////////////////////////
// extension Publications Scientifiques
Researcher jojoResearcherAccount = new Researcher(jojo, "3363-22555-AB33-T", null, "IT");
Researcher output = researchesService.saveResearcher(jojoResearcherAccount);
Research jojoResearch = new Research("Graphs : Advanced Search Algorithms", output, new Date(0),
PaperType.Article, "test.pdf", null, "english",
Access.OpenSource, "IT", "This Article's title speaks for itself \n We'll discuss about advanced Graph search Algorithms");
Research restrictedResearch = new Research("just another Name", output, new Date(1111111111),
PaperType.Article, "restricted", null, "english",
Access.Restricted, "Restricted", "This Article's title speaks for itself\n We'll discuss about advanced Graph search Algorithms");
Research privateResearch = new Research("the great Potato War", output, new Date(),
PaperType.Article, "private", null, "english",
Access.Private, "private", "This Article's title speaks for itself\n We'll discuss about advanced Graph search Algorithms");
courseService.save(progra1);
courseService.save(chemistry1);
courseService.save(psycho1);
courseService.save(commun);
researchesService.saveResearch(restrictedResearch);
researchesService.saveResearch(privateResearch);
CurriculumCourseService.save(new CurriculumCourse(infoBab1,progra1));
CurriculumCourseService.save(new CurriculumCourse(infoBab1,commun));
researchesService.saveResearch(jojoResearch);
CurriculumCourseService.save(new CurriculumCourse(psychologyBab1,psycho1));
CurriculumCourseService.save(new CurriculumCourse(psychologyBab1,commun));
CurriculumCourseService.save(new CurriculumCourse(chemistryBab1,commun));
CurriculumCourseService.save(new CurriculumCourse(chemistryBab1,chemistry1));
InscriptionRequest inscriptionRequest = new InscriptionRequest("helen","prenom","non","helen@gmail.com","america",new Date(),(long) 1,RequestState.Pending,"yes.png","password");
inscriptionService.save(inscriptionRequest);
}
}

View File

@ -1,126 +0,0 @@
package ovh.herisson.Clyde.EndPoints.Msg;
/******************************************************
* @file MessagesController.java
* @author Anthony Debucquoy
* @scope Extension messagerie
*
* Entry point for the messages application
******************************************************/
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;
import lombok.AllArgsConstructor;
import ovh.herisson.Clyde.DTO.Msg.DiscussionDTO;
import ovh.herisson.Clyde.Repositories.UserRepository;
import ovh.herisson.Clyde.Repositories.Msg.DiscussionRepository;
import ovh.herisson.Clyde.Responses.UnauthorizedResponse;
import ovh.herisson.Clyde.Services.AuthenticatorService;
import ovh.herisson.Clyde.Services.UserService;
import ovh.herisson.Clyde.Services.Msg.DiscussionService;
import ovh.herisson.Clyde.Tables.User;
import ovh.herisson.Clyde.Tables.Msg.Discussion;
import ovh.herisson.Clyde.Tables.Msg.Message;
@RestController
@CrossOrigin(originPatterns = "*", allowCredentials = "true")
@AllArgsConstructor
public class MessagesController {
private AuthenticatorService authServ;
private DiscussionService discServ;
private DiscussionRepository discRepo;
private UserService userServ;
@GetMapping("/discussions")
public ResponseEntity<Iterable<Discussion>> getDiscussions(@RequestHeader("Authorization") String token ){
User user = authServ.getUserFromToken(token);
if(user == null){
return new UnauthorizedResponse<>(null);
}
Iterable<Discussion> mock = discServ.getOwned(authServ.getUserFromToken(token));
return new ResponseEntity<>(mock, HttpStatus.OK);
}
@GetMapping("/discussion/{id}")
public ResponseEntity<DiscussionDTO> getDiscussion(@RequestHeader("Authorization") String token, @PathVariable long id){
User user = authServ.getUserFromToken(token);
if(user == null || !discServ.hasDiscussion(user, id) ){
return new UnauthorizedResponse<>(null);
}
return new ResponseEntity<>(DiscussionDTO.construct(discRepo.findById(id).orElse(null), authServ.getUserFromToken(token)), HttpStatus.OK);
}
@PatchMapping("/discussion/{id}")
public ResponseEntity<Discussion> AlterDiscussion(@RequestHeader("Authorization") String token, @PathVariable long id, @RequestBody Discussion data){
User user = authServ.getUserFromToken(token);
if(user == null){
return new UnauthorizedResponse<>(null);
}
Discussion disc = discRepo.findById(id).orElse(null);
disc.setName(data.getName());
discRepo.save(disc);
return new ResponseEntity<>(disc, HttpStatus.OK);
}
@PatchMapping("/discussion/{id}/add")
public ResponseEntity<Discussion> invite(@RequestHeader("Authorization") String token, @PathVariable long id, @RequestBody User data){
User user = authServ.getUserFromToken(token);
if(user == null){
return new UnauthorizedResponse<>(null);
}
Discussion disc = discRepo.findById(id).orElse(null);
User invited = userServ.getUserById(data.getRegNo());
disc.addMember(invited);
discRepo.save(disc);
return new ResponseEntity<>(disc, HttpStatus.OK);
}
@PatchMapping("/discussion/{id}/remove")
public ResponseEntity<Discussion> removeMember(@RequestHeader("Authorization") String token, @PathVariable long id, @RequestBody User data){
User user = authServ.getUserFromToken(token);
if(user == null){
return new UnauthorizedResponse<>(null);
}
Discussion disc = discRepo.findById(id).orElse(null);
User member = userServ.getUserById(data.getRegNo());
disc.delMember(member);
discRepo.save(disc);
return new ResponseEntity<>(disc, HttpStatus.OK);
}
@PostMapping("/discussion/{id}")
public ResponseEntity<Discussion> sendMessage(@RequestHeader("Authorization") String token, @PathVariable long id, @RequestBody Message msg){
User user = authServ.getUserFromToken(token);
if(user == null){
return new UnauthorizedResponse<>(null);
}
Discussion disc = discRepo.findById(id).orElse(null);
msg.setAuthor(user);
if(disc != null)
discServ.CreateMessage(disc, msg);
return new ResponseEntity<>(disc, HttpStatus.OK);
}
@PostMapping("/discussion")
public ResponseEntity<Discussion> createDiscussion(@RequestHeader("Authorization") String token, @RequestBody Discussion data){
return new ResponseEntity<>(discServ.create(data.getName(), authServ.getUserFromToken(token)), HttpStatus.OK);
}
}

View File

@ -1,240 +0,0 @@
package ovh.herisson.Clyde.EndPoints.ScientificPublications;
/******************************************************
* @file ResearchController.java
* @author Bartha Maxime
* @scope Publications Scientifiques
*
* API class for the researches
******************************************************/
import lombok.AllArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import ovh.herisson.Clyde.DTO.ScientificPublications.ResearchDTO;
import ovh.herisson.Clyde.DTO.ScientificPublications.ResearcherDTO;
import ovh.herisson.Clyde.Responses.UnauthorizedResponse;
import ovh.herisson.Clyde.Services.AuthenticatorService;
import ovh.herisson.Clyde.Services.ScientificPublications.ResearchesService;
import ovh.herisson.Clyde.Tables.Role;
import ovh.herisson.Clyde.Tables.ScientificPublications.Research;
import ovh.herisson.Clyde.Tables.ScientificPublications.Researcher;
import java.util.ArrayList;
import java.util.Map;
@RestController
@CrossOrigin(originPatterns = "*", allowCredentials = "true")
@AllArgsConstructor
public class ResearchController {
private final ResearchesService researchesServ;
private final AuthenticatorService authServ;
/** Is accessible by anyone
* but if the user doesn't have the permission to download the research
* the return Research Download URL will be null
*/
@GetMapping("/research/{id}")
public ResponseEntity<ResearchDTO> getResearch(@RequestHeader(value = "Authorization", required = false) String token, @PathVariable long id){
Research research = researchesServ.getResearchById(id);
if (research == null)
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
if (researchesServ.hasNoAccessTo(research,authServ.getUserFromToken(token))){
research.setPdfLocation(null);
}// If the user doesn't have access to the document he can't download the pdf
return new ResponseEntity<>(ResearchDTO.construct(research), HttpStatus.OK);
}
/**
* @param token used to know if the user can download or not the research pdf
* @return every research
*/
@GetMapping("/researches")
public ResponseEntity<Iterable<ResearchDTO>> getResearches(@RequestHeader(value = "Authorization",required = false) String token){
Iterable<Research> researches = researchesServ.getAllResearches();
ArrayList<ResearchDTO> toReturnResearches = new ArrayList<>();
for (Research research: researches){
if (researchesServ.hasNoAccessTo(research,authServ.getUserFromToken(token))){
research.setPdfLocation(null);
}
toReturnResearches.add(ResearchDTO.construct(research));
}
return new ResponseEntity<>(toReturnResearches,HttpStatus.OK);
}
@GetMapping("/researches/{id}")
public ResponseEntity<Iterable<ResearchDTO>> getResearchesFromResearcher(@RequestHeader(value = "Authorization",required = false) String token,
@PathVariable Long id
){
Iterable<Research> researches = researchesServ.getResearchesByAuthor(id);
if (researches == null) return new ResponseEntity<>(HttpStatus.NOT_FOUND);
ArrayList<ResearchDTO> toReturnResearches = new ArrayList<>();
for (Research research: researches){
if (researchesServ.hasNoAccessTo(research,authServ.getUserFromToken(token))){
research.setPdfLocation(null);
}
toReturnResearches.add(ResearchDTO.construct(research));
}
return new ResponseEntity<>(toReturnResearches,HttpStatus.OK);
}
/** post a new research
*
* @return the research saved
*/
@PostMapping("/research")
public ResponseEntity<Research> postResearch(@RequestHeader("Authorization") String token, @RequestBody Research research){
if (authServ.isNotIn(new Role[]{Role.Admin},token) &&
researchesServ.getResearcherByUser(authServ.getUserFromToken(token)) == null){
return new UnauthorizedResponse<>(null);
} // if the poster isn't a researcher
return new ResponseEntity<>(researchesServ.saveResearch(research), HttpStatus.OK);
}
/** post updates to the research
*
*/
@PatchMapping("/research/{id}")
public ResponseEntity<String> patchResearch(@RequestHeader("Authorization") String token,
@RequestBody Map<String,Object> updates,
@PathVariable long id
)
{
Research research = researchesServ.getResearchById(id);
Researcher researcher = researchesServ.getResearcherByUser(authServ.getUserFromToken(token));
if (research == null)
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
if (authServ.isNotIn(new Role[]{Role.Admin,Role.Secretary},token) &&
researcher != research.getAuthor()) {
return new UnauthorizedResponse<>(null);
}
researchesServ.modifyResearchData(research, updates);
return new ResponseEntity<>(HttpStatus.OK);
}
/** Only Admin, Secretary and author can delete a research
*
*/
@DeleteMapping("/research/{id}")
public ResponseEntity<String> deleteResearch(@RequestHeader("Authorization") String token, @PathVariable long id){
Research research = researchesServ.getResearchById(id);
Researcher researcher = researchesServ.getResearcherByUser(authServ.getUserFromToken(token));
if (research == null)
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
if (authServ.isNotIn(new Role[]{Role.Admin, Role.Secretary},token) &&
researcher != research.getAuthor()){
return new UnauthorizedResponse<>(null);
}
researchesServ.deleteResearch(research);
return new ResponseEntity<>(HttpStatus.OK);
}
/////////////
// Co-authors Part
/** get all the co-authors in a research
*
* @param id the research id
* @return all the co-authors associated with the research
*/
@GetMapping("/research/{id}/co-authors")
public ResponseEntity<Iterable<ResearcherDTO>> getCoAuthors(@PathVariable long id){
Research research = researchesServ.getResearchById(id);
if (research == null) return new ResponseEntity<>(HttpStatus.NOT_FOUND);
Iterable<Researcher> researchers= researchesServ.getCoAuthors(research);
ArrayList<ResearcherDTO> toReturn = new ArrayList<>();
for (Researcher researcher: researchers){
toReturn.add(ResearcherDTO.construct(researcher));
}
return new ResponseEntity<>(toReturn,HttpStatus.OK);
}
/** post co-authors to the research
*
* @param token the Authorization header
* @param researchersId the co-authors ids
* @param id the research id
* @return the added researchers
*/
@PostMapping("/research/{id}/co-authors")
public ResponseEntity<Iterable<ResearcherDTO>> postCoAuthor(@RequestHeader("Authorization") String token,
@RequestBody Iterable<Long> researchersId,
@PathVariable long id)
{
Research research = researchesServ.getResearchById(id);
if (research == null) return new ResponseEntity<>(HttpStatus.NOT_FOUND);
if (authServ.isNotIn(new Role[]{Role.Admin}, token) || research.getAuthor() != researchesServ.getResearcherByUser(authServ.getUserFromToken(token)))
return new UnauthorizedResponse<>(null);
if (!researchesServ.saveCoAuthors(researchersId,research))
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
ArrayList<ResearcherDTO> toReturn = new ArrayList<>();
for (Long reId: researchersId){
toReturn.add(ResearcherDTO.construct(researchesServ.getResearcherById(reId)));
}
return new ResponseEntity<>(toReturn,HttpStatus.OK);
}
/** deletes the co-author with *coAuthorId* from the research with the *researchId*
*/
@DeleteMapping("/research/{researchId}/co-author/{coAuthorId}")
public ResponseEntity<String> deleteCoAuthor(@RequestHeader("Authorization") String token,
@PathVariable long researchId,
@PathVariable long coAuthorId)
{
Research research = researchesServ.getResearchById(researchId);
Researcher coAuthor = researchesServ.getResearcherById(coAuthorId);
if (authServ.isNotIn(new Role[]{Role.Admin}, token) || research.getAuthor() != researchesServ.getResearcherByUser(authServ.getUserFromToken(token)))
return new UnauthorizedResponse<>(null);
if (coAuthor == null) return new ResponseEntity<>(HttpStatus.NOT_FOUND);
if (!researchesServ.deleteCoAuthor(research, coAuthor))
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
return new ResponseEntity<>(HttpStatus.OK);
}
///////
//views part
@PostMapping("/addview/{url}")
public ResponseEntity<ResearchDTO> addView(@PathVariable String url){
Research research = researchesServ.getResearchByUrl(url);
if (research ==null) return new ResponseEntity<>(HttpStatus.NOT_FOUND);
return new ResponseEntity<>(ResearchDTO.construct(researchesServ.addView(research)), HttpStatus.OK);
}
}

View File

@ -1,102 +0,0 @@
package ovh.herisson.Clyde.EndPoints.ScientificPublications;
/******************************************************
* @file ResearcherController.java
* @author Bartha Maxime
* @scope Publications Scientifiques
*
* API class for the researchers
******************************************************/
import lombok.AllArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import ovh.herisson.Clyde.DTO.ScientificPublications.ResearcherDTO;
import ovh.herisson.Clyde.Responses.UnauthorizedResponse;
import ovh.herisson.Clyde.Services.AuthenticatorService;
import ovh.herisson.Clyde.Services.ScientificPublications.ResearchesService;
import ovh.herisson.Clyde.Tables.Role;
import ovh.herisson.Clyde.Tables.ScientificPublications.Researcher;
import java.util.ArrayList;
import java.util.Map;
@RestController
@CrossOrigin(originPatterns = "*", allowCredentials = "true")
@AllArgsConstructor
public class ResearcherController {
ResearchesService researchesServ;
AuthenticatorService authServ;
@GetMapping("/researcher/{id}")
public ResponseEntity<ResearcherDTO> getResearcher(@PathVariable long id){
Researcher researcher = researchesServ.getResearcherById(id);
return new ResponseEntity<>(ResearcherDTO.construct(researcher),HttpStatus.OK);
}
/**
* Everyone can access every researcher Account
* @return all the researchers accounts
*/
@GetMapping("/researchers")
public ResponseEntity<Iterable<ResearcherDTO>> getAllResearchers(){
Iterable<Researcher> researchers = researchesServ.getAllResearchers();
ArrayList<ResearcherDTO> toReturnResearchersDTO = new ArrayList<>();
for (Researcher researcher: researchers){
toReturnResearchersDTO.add(ResearcherDTO.construct(researcher));
}
return new ResponseEntity<>(toReturnResearchersDTO, HttpStatus.OK);
}
@GetMapping("/researcher")
public ResponseEntity<ResearcherDTO> getSelf(@RequestHeader("Authorization") String token){
Researcher self = researchesServ.getResearcherByUser(authServ.getUserFromToken(token));
if (self ==null) return new UnauthorizedResponse<>(null);
return new ResponseEntity<>(ResearcherDTO.construct(self), HttpStatus.OK);
}
@PostMapping("/researcher")
public ResponseEntity<ResearcherDTO> postResearcher(@RequestHeader("Authorization") String token, @RequestBody Researcher researcher){
if (authServ.isNotIn(new Role[]{Role.Admin,Role.Secretary}, token)){
return new UnauthorizedResponse<>(null);
}
Researcher posted = researchesServ.saveResearcher(researcher);
if (posted == null) return new ResponseEntity<>(null, HttpStatus.BAD_REQUEST);
return new ResponseEntity<>(ResearcherDTO.construct(posted), HttpStatus.CREATED);
}
@PatchMapping("/researcher/{id}")
public ResponseEntity<ResearcherDTO> patchResearcher(@RequestHeader("Authorization") String token,
@PathVariable long id,
@RequestBody Map<String ,Object> updates){
Researcher researcher = researchesServ.getResearcherById(id);
if (authServ.isNotIn(new Role[]{Role.Secretary,Role.Admin}, token)
&& researcher.getId() != researchesServ.getResearcherByUser(authServ.getUserFromToken(token)).getId())
return new UnauthorizedResponse<>(null);
if (researcher == null) return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
researchesServ.modifyResearcherData(researcher,updates);
return new ResponseEntity<>(ResearcherDTO.construct(researcher),HttpStatus.OK);
}
@DeleteMapping("/researcher/{id}")
public ResponseEntity<String> deleteResearcher(@RequestHeader ("Authorization") String token, @PathVariable long id){
if (authServ.isNotIn(new Role[]{Role.Admin,Role.Secretary},token))
return new UnauthorizedResponse<>(null);
researchesServ.deleteResearcher(researchesServ.getResearcherById(id));
return new ResponseEntity<>(HttpStatus.OK);
}
}

View File

@ -1,40 +0,0 @@
package ovh.herisson.Clyde.EndPoints.ScientificPublications;
import lombok.AllArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import ovh.herisson.Clyde.Services.ScientificPublications.ResearchesService;
import ovh.herisson.Clyde.Services.ScientificPublications.StatisticsService;
import ovh.herisson.Clyde.Tables.ScientificPublications.Researcher;
import java.util.Map;
@RestController
@CrossOrigin(originPatterns = "*", allowCredentials = "true")
@AllArgsConstructor
public class StatController {
private StatisticsService statServ;
private ResearchesService researchesServ;
/** returns all the statistics in a 2D array
*
* @param id the researcher's id
* @return all the stats in a 2D array
*/
@GetMapping("/stats/{id}")
public ResponseEntity<Iterable<Iterable<Map<String, Integer>>>> getStat(@PathVariable Long id){
Researcher researcher = researchesServ.getResearcherById(id);
if (researcher == null) return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
Iterable<Iterable<Map<String,Integer>>> stats = statServ.generateStats(researcher);
if (stats == null) return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
return new ResponseEntity<>(stats,HttpStatus.OK);
}
}

View File

@ -96,7 +96,7 @@ public class UserController {
if (poster == null) {return new UnauthorizedResponse<>("bad token");}
if (!userService.modifyData(id, updates, poster))
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
return new UnauthorizedResponse<>("there was an issue with the updates requested");
return new ResponseEntity<>(null, HttpStatus.OK);
}

View File

@ -0,0 +1,37 @@
package ovh.herisson.Clyde;
import javax.sql.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.scheduling.annotation.EnableScheduling;
@Configuration
@EnableScheduling
public class JdbcConfig {
@Bean
@Profile("!prod")
public DataSource psqlSource(){
DriverManagerDataSource source = new DriverManagerDataSource();
source.setDriverClassName("org.postgresql.Driver");
source.setUrl("jdbc:postgresql://localhost:5442/clyde");
source.setUsername("devel");
source.setPassword("devel");
return source;
}
@Bean
@Profile("prod")
public DataSource psqlSourceProd(){
DriverManagerDataSource source = new DriverManagerDataSource();
source.setDriverClassName("org.postgresql.Driver");
source.setUrl("jdbc:postgresql:clyde?socketFactory=org.newsclub.net.unix.AFUNIXSocketFactory$FactoryArg&socketFactoryArg=/var/run/postgresql/.s.PGSQL.5432");
source.setUsername("clyde");
return source;
}
}

View File

@ -0,0 +1,43 @@
package ovh.herisson.Clyde;
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.id.IdentifierGenerator;
import java.sql.*;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
public class RegNoGenerator implements IdentifierGenerator {
private final UserSaveCounter usv = UserSaveCounter.getInstance();
@Override
public Object generate(SharedSessionContractImplementor session, Object object) {
try{
JdbcConnectionAccess jdbccon = session.getJdbcConnectionAccess();
Connection conn = jdbccon.obtainConnection();
Statement statement = conn.createStatement();
int n = usv.getCount();
Calendar c = new GregorianCalendar();
int y = c.get(Calendar.YEAR);
String query = "select count(reg_no) + "+n+" from Users where reg_no/10000 = " + y%1000;
ResultSet set = statement.executeQuery(query);
long resp = 0;
if(set.next()){
resp = set.getLong(1)+((y%1000)*10000);
usv.increment();
}
conn.close();
statement.close();
return resp;
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}

View File

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

View File

@ -1,15 +0,0 @@
package ovh.herisson.Clyde.Repositories.Inscription;
import org.springframework.data.repository.CrudRepository;
import ovh.herisson.Clyde.Tables.Inscription.ExternalCurriculum;
import ovh.herisson.Clyde.Tables.Inscription.InscriptionRequest;
import ovh.herisson.Clyde.Tables.User;
import java.util.ArrayList;
public interface ExternalCurriculumRepository extends CrudRepository<ExternalCurriculum, Long> {
ArrayList<ExternalCurriculum> getExternalCurriculumByInscriptionRequest(InscriptionRequest ir);
ArrayList<ExternalCurriculum> getExternalCurriculumByUser(User user);
ExternalCurriculum getExternalCurriculumById(long id);
}

View File

@ -1,12 +0,0 @@
package ovh.herisson.Clyde.Repositories.Inscription;
import org.springframework.data.repository.CrudRepository;
import ovh.herisson.Clyde.Tables.Inscription.Minerval;
import java.util.ArrayList;
public interface MinervalRepository extends CrudRepository<Minerval, Long> {
public ArrayList<Minerval> getMinervalsByStudentRegNoOrderByYearDesc(Long studentRegNo);
public Minerval findById(long id);
}

View File

@ -1,10 +0,0 @@
package ovh.herisson.Clyde.Repositories.Inscription;
import org.springframework.data.repository.CrudRepository;
import ovh.herisson.Clyde.Tables.Inscription.Payment;
import java.util.ArrayList;
public interface PaymentRepository extends CrudRepository<Payment, Long> {
public ArrayList<Payment> getPaymentsByStudentRegNo(long regNo);
}

View File

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

View File

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

View File

@ -1,7 +1,7 @@
package ovh.herisson.Clyde.Repositories.Inscription;
package ovh.herisson.Clyde.Repositories;
import org.springframework.data.repository.CrudRepository;
import ovh.herisson.Clyde.Tables.Inscription.InscriptionRequest;
import ovh.herisson.Clyde.Tables.InscriptionRequest;
public interface InscriptionRepository extends CrudRepository<InscriptionRequest,Long> {

View File

@ -1,23 +0,0 @@
package ovh.herisson.Clyde.Repositories.Msg;
/******************************************************
* @file DiscussionRepository.java
* @author Anthony Debucquoy
* @scope Extension messagerie
*
* Repository of Discussion allowing to fetch discussion by user
******************************************************/
import java.util.List;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import ovh.herisson.Clyde.Tables.Msg.Discussion;
public interface DiscussionRepository extends CrudRepository<Discussion, Long>{
@Query("SELECT d FROM Discussion d INNER JOIN FETCH d.members dm WHERE dm.id = ?1")
List<Discussion> findByMembership(long userid);
}

View File

@ -1,14 +0,0 @@
package ovh.herisson.Clyde.Repositories.Msg;
/******************************************************
* @file MessageRepository.java
* @author Anthony Debucquoy
* @scope Extension messagerie
******************************************************/
import org.springframework.data.repository.CrudRepository;
import ovh.herisson.Clyde.Tables.Msg.Message;
public interface MessageRepository extends CrudRepository<Message, Long> {}

View File

@ -1,18 +0,0 @@
package ovh.herisson.Clyde.Repositories.ScientificPublications;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import ovh.herisson.Clyde.Tables.Course;
import ovh.herisson.Clyde.Tables.Curriculum;
import ovh.herisson.Clyde.Tables.ScientificPublications.Research;
import ovh.herisson.Clyde.Tables.ScientificPublications.ResearchCoAuthors;
import ovh.herisson.Clyde.Tables.ScientificPublications.Researcher;
public interface ResearchCoAuthorsRepository extends CrudRepository<ResearchCoAuthors,Long> {
@Query("select distinct rca.coAuthor from ResearchCoAuthors rca where rca.research = ?1")
Iterable<Researcher> findResearchCoAuthors(Research research);
@Query("select rca from ResearchCoAuthors rca where rca.research = ?1 and rca.coAuthor =?2")
ResearchCoAuthors findResearchCoAuthors(Research research, Researcher researcher);
}

View File

@ -1,17 +0,0 @@
package ovh.herisson.Clyde.Repositories.ScientificPublications;
import org.springframework.data.repository.CrudRepository;
import ovh.herisson.Clyde.Tables.ScientificPublications.Research;
import ovh.herisson.Clyde.Tables.ScientificPublications.Researcher;
import java.util.Map;
public interface ResearchRepository extends CrudRepository<Research,Long> {
Research findById(long id);
Iterable<Research> findByAuthor(Researcher author);
Research findByPdfLocation(String url);
}

View File

@ -1,16 +0,0 @@
package ovh.herisson.Clyde.Repositories.ScientificPublications;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import ovh.herisson.Clyde.Tables.ScientificPublications.Research;
import ovh.herisson.Clyde.Tables.ScientificPublications.Researcher;
import ovh.herisson.Clyde.Tables.User;
public interface ResearcherRepository extends CrudRepository<Researcher,Long> {
Researcher findByUser(User user);
Researcher findById(long id);
@Query("select r from Research r where r.author = ?1")
Iterable<Research> findAllByAuthorId(Researcher author);
}

View File

@ -1,40 +0,0 @@
package ovh.herisson.Clyde.Repositories.ScientificPublications;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import ovh.herisson.Clyde.Tables.ScientificPublications.Research;
import java.util.Map;
public interface StatsRepository extends CrudRepository<Research,Long> {
@Query("select new map(to_char(r.releaseDate, 'month') as label, sum(r.views) as y) from Research r group by to_char(r.releaseDate, 'month')")
Iterable<Map<String ,Integer>> viewsByMonths();
@Query("select new map(to_char(r.releaseDate,'YYYY') as label, sum (r.views) as y) from Research r group by to_char(r.releaseDate,'YYYY')")
Iterable<Map<String ,Integer>> viewsByYears();
@Query("select new map(r.domain as label, sum(r.views) as y) from Research r group by r.domain")
Iterable<Map<String ,Integer>> viewsByTopics();
@Query("select new map(r.domain as label, count(distinct r.language) as y) from Research r group by r.domain")
Iterable<Map<String ,Integer>> languageByTopics();
@Query("select new map(to_char(r.releaseDate,'YYYY') as label, count(distinct r.language) as y) from Research r group by to_char(r.releaseDate,'YYYY')")
Iterable<Map<String ,Integer>> languageByYears();
@Query("select new map(to_char(r.releaseDate, 'month') as label, count(distinct r.language) as y) from Research r group by to_char(r.releaseDate, 'month')")
Iterable<Map<String ,Integer>> languageByMonths();
@Query("select new map(to_char(r.releaseDate,'YYYY') as label, count(distinct r) as y) from Research r group by to_char(r.releaseDate,'YYYY')")
Iterable<Map<String ,Integer>> researchesByYears();
@Query("select new map(r.domain as label, count(distinct r) as y) from Research r group by r.domain")
Iterable<Map<String ,Integer>> researchesByTopics();
@Query("select new map(to_char(r.releaseDate, 'month') as label, count(distinct r) as y) from Research r group by to_char(r.releaseDate, 'month')")
Iterable<Map<String ,Integer>> researchesByMonth();
}

View File

@ -6,12 +6,8 @@ import ovh.herisson.Clyde.Tables.Curriculum;
import ovh.herisson.Clyde.Tables.User;
import ovh.herisson.Clyde.Tables.UserCurriculum;
import java.util.ArrayList;
public interface UserCurriculumRepository extends CrudRepository<UserCurriculum, Long> {
@Query("select uc.curriculum from UserCurriculum uc where uc.user = ?1")
Curriculum findByUser(User student);
ArrayList<UserCurriculum> findByUserOrderByCurriculum(User student);
}

View File

@ -5,13 +5,10 @@ import org.springframework.data.repository.CrudRepository;
import ovh.herisson.Clyde.Tables.User;
public interface UserRepository extends CrudRepository<User, Long> {
User findById(long id);
User findByEmail(String email);
@Query("select u from User u where u.role = ovh.herisson.Clyde.Tables.Role.Teacher")
Iterable<User> findAllTeachers();

View File

@ -1,10 +1,7 @@
package ovh.herisson.Clyde.Services;
import org.springframework.stereotype.Service;
import ovh.herisson.Clyde.Services.Inscription.InscriptionService;
import ovh.herisson.Clyde.Tables.*;
import ovh.herisson.Clyde.Tables.Inscription.InscriptionRequest;
import java.util.Date;
@Service

View File

@ -18,6 +18,7 @@ public class CurriculumService {
public Curriculum findById(long id){
return curriculumRepo.findById(id);
}
public void delete(Curriculum curriculum) {
curriculumRepo.delete(curriculum);
}

View File

@ -1,105 +0,0 @@
package ovh.herisson.Clyde.Services.Inscription;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import ovh.herisson.Clyde.Repositories.*;
import ovh.herisson.Clyde.Repositories.Inscription.ExternalCurriculumRepository;
import ovh.herisson.Clyde.Repositories.Inscription.InscriptionRepository;
import ovh.herisson.Clyde.Repositories.Inscription.MinervalRepository;
import ovh.herisson.Clyde.Tables.*;
import ovh.herisson.Clyde.Tables.Inscription.ExternalCurriculum;
import ovh.herisson.Clyde.Tables.Inscription.InscriptionRequest;
import ovh.herisson.Clyde.Tables.Inscription.Minerval;
import java.util.ArrayList;
@Service
public class InscriptionService {
private final InscriptionRepository inscriptionRepo;
private final UserRepository userRepo;
private final UserCurriculumRepository userCurriculumRepo;
private final CurriculumRepository curriculumRepo;
private final MinervalRepository minervalRepository;
private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
private final ExternalCurriculumRepository externalCurriculumRepository;
public InscriptionService(InscriptionRepository inscriptionRepo, UserRepository userRepo, UserCurriculumRepository userCurriculumRepo, CurriculumRepository curriculumRepo, MinervalRepository minervalRepository, ExternalCurriculumRepository externalCurriculumRepository){
this.inscriptionRepo = inscriptionRepo;
this.userRepo = userRepo;
this.userCurriculumRepo = userCurriculumRepo;
this.curriculumRepo = curriculumRepo;
this.minervalRepository = minervalRepository;
this.externalCurriculumRepository = externalCurriculumRepository;
}
public InscriptionRequest save(InscriptionRequest inscriptionRequest){
inscriptionRequest.setPassword(passwordEncoder.encode(inscriptionRequest.getPassword()));
return inscriptionRepo.save(inscriptionRequest);
}
public InscriptionRequest getById(long id){
return inscriptionRepo.findById(id);
}
public Iterable<InscriptionRequest> getAll(){
return inscriptionRepo.findAll();
}
public boolean modifyState(long id, RequestState requestState) {
InscriptionRequest inscrRequest = getById(id);
if (inscrRequest == null)
return false;
inscrRequest.setState(requestState);
save(inscrRequest);
//saves the user from the request if accepted from teacher and inscription services
if (requestState == RequestState.Accepted && (inscrRequest.getEquivalenceState() == RequestState.Accepted || inscrRequest.getEquivalenceState() == RequestState.Unrequired))
{
return createUser(inscrRequest);
}
return true;
}
public boolean createUser(InscriptionRequest inscrRequest){
//We must send an email here
if (curriculumRepo.findById(inscrRequest.getCurriculumId()) == null)
return false;
User userFromRequest = new User(
inscrRequest.getLastName(),
inscrRequest.getFirstName(),
inscrRequest.getEmail(),
inscrRequest.getAddress(),
inscrRequest.getCountry(),
inscrRequest.getBirthDate(),
inscrRequest.getProfilePicture(),
inscrRequest.getPassword()
);
userRepo.save(userFromRequest);
userCurriculumRepo.save(new UserCurriculum(userFromRequest, curriculumRepo.findById(inscrRequest.getCurriculumId()),0));
//Create a minerval for the new student
Minerval minerval = new Minerval(userFromRequest.getRegNo(), 0, 852, 2023);
minervalRepository.save(minerval);
//Assign the externals curriculums from the inscription request to newly created student
ArrayList<ExternalCurriculum> extCurrList = externalCurriculumRepository.getExternalCurriculumByInscriptionRequest(inscrRequest);
for (int i = 0; i < extCurrList.size(); i++){
extCurrList.get(i).setUser(userFromRequest);
externalCurriculumRepository.save(extCurrList.get(i));
}
return true;
}
public void delete(InscriptionRequest toDelete) {
inscriptionRepo.delete(toDelete);
}
}

View File

@ -0,0 +1,94 @@
package ovh.herisson.Clyde.Services;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import ovh.herisson.Clyde.Repositories.CurriculumRepository;
import ovh.herisson.Clyde.Repositories.InscriptionRepository;
import ovh.herisson.Clyde.Repositories.UserCurriculumRepository;
import ovh.herisson.Clyde.Repositories.UserRepository;
import ovh.herisson.Clyde.Tables.InscriptionRequest;
import ovh.herisson.Clyde.Tables.RequestState;
import ovh.herisson.Clyde.Tables.User;
import ovh.herisson.Clyde.Tables.UserCurriculum;
@Service
public class InscriptionService {
private final InscriptionRepository inscriptionRepo;
private final UserRepository userRepo;
private final UserCurriculumRepository userCurriculumRepo;
private final CurriculumRepository curriculumRepo;
private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
public InscriptionService(InscriptionRepository inscriptionRepo, UserRepository userRepo, UserCurriculumRepository userCurriculumRepo, CurriculumRepository curriculumRepo){
this.inscriptionRepo = inscriptionRepo;
this.userRepo = userRepo;
this.userCurriculumRepo = userCurriculumRepo;
this.curriculumRepo = curriculumRepo;
}
public InscriptionRequest save(InscriptionRequest inscriptionRequest){
inscriptionRequest.setPassword(passwordEncoder.encode(inscriptionRequest.getPassword()));
return inscriptionRepo.save(inscriptionRequest);
}
public InscriptionRequest getById(long id){
return inscriptionRepo.findById(id);
}
public Iterable<InscriptionRequest> getAll(){
return inscriptionRepo.findAll();
}
public boolean modifyState(long id, RequestState requestState) {
InscriptionRequest inscrRequest = getById(id);
if (inscrRequest == null)
return false;
// if th state is the same we don't send an email
if (requestState == inscrRequest.getState())
return false;
/** todo send an email to tell the poster of the inscrRequest (inscrRequest.getEmail())
* to notify them that the state of their request changed
* FooEmailFormat toSend = (String.format("Your request state changed from %s to %s"),
* inscrRequest.getState(), requestState)
* FooEmailSender.send(toSend, inscrRequest.getEmail())
*/
//saves the user from the request if accepted
if (requestState == RequestState.Accepted)
{
if (curriculumRepo.findById(inscrRequest.getCurriculumId()) == null)
return false;
User userFromRequest = new User(
inscrRequest.getLastName(),
inscrRequest.getFirstName(),
inscrRequest.getEmail(),
inscrRequest.getAddress(),
inscrRequest.getCountry(),
inscrRequest.getBirthDate(),
inscrRequest.getProfilePicture(),
inscrRequest.getPassword()
);
userRepo.save(userFromRequest);
userCurriculumRepo.save(new UserCurriculum(userFromRequest, curriculumRepo.findById(inscrRequest.getCurriculumId())));
}
inscrRequest.setState(requestState);
save(inscrRequest);
return true;
}
public void delete(InscriptionRequest toDelete) {
inscriptionRepo.delete(toDelete);
}
}

View File

@ -1,57 +0,0 @@
package ovh.herisson.Clyde.Services.Msg;
import java.util.List;
/******************************************************
* @file DiscussionService.java
* @author Anthony Debucquoy
* @scope Extension messagerie
*
* Various function utilised by the messages application
******************************************************/
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.fasterxml.jackson.databind.util.JSONPObject;
import ovh.herisson.Clyde.Repositories.Msg.DiscussionRepository;
import ovh.herisson.Clyde.Tables.User;
import ovh.herisson.Clyde.Tables.Msg.Discussion;
import ovh.herisson.Clyde.Tables.Msg.Message;
@Service
public class DiscussionService {
@Autowired
private DiscussionRepository discRepo;
public Discussion create(String name, User author){
return discRepo.save(new Discussion(name, author));
}
/**
* list discussions owned by a certain user
*/
public Iterable<Discussion> getOwned(User author){
return discRepo.findByMembership(author.getRegNo());
}
/**
* Create a message and link it to it's discussion
*/
public Discussion CreateMessage(Discussion disc, Message msg){
disc.addMessage(msg);
return discRepo.save(disc);
}
/**
* Check if a user is in a discussion
*/
public boolean hasDiscussion(User user, long id) {
Discussion disc = discRepo.findById(id).orElse(null);
List<User> members = disc.getMembers();
return members.contains(user);
}
}

View File

@ -1,7 +1,7 @@
package ovh.herisson.Clyde.Services;
import ovh.herisson.Clyde.Tables.Course;
import ovh.herisson.Clyde.Tables.Inscription.InscriptionRequest;
import ovh.herisson.Clyde.Tables.InscriptionRequest;
import ovh.herisson.Clyde.Tables.User;
import java.util.ArrayList;
@ -87,9 +87,7 @@ public class ProtectionService {
toReturn.put("curriculum", inscriptionRequest.getCurriculumId());
toReturn.put("state", inscriptionRequest.getState());
toReturn.put("profilePictureUrl", inscriptionRequest.getProfilePicture());
toReturn.put("identityCard", inscriptionRequest.getIdentityCard());
toReturn.put("submissionDate", inscriptionRequest.getSubmissionDate());
toReturn.put("equivalenceState", inscriptionRequest.getEquivalenceState());
return toReturn;
}

View File

@ -1,196 +0,0 @@
package ovh.herisson.Clyde.Services.ScientificPublications;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import ovh.herisson.Clyde.DTO.ScientificPublications.ResearchDTO;
import ovh.herisson.Clyde.Repositories.ScientificPublications.ResearchCoAuthorsRepository;
import ovh.herisson.Clyde.Repositories.ScientificPublications.ResearchRepository;
import ovh.herisson.Clyde.Repositories.ScientificPublications.ResearcherRepository;
import ovh.herisson.Clyde.Tables.Role;
import ovh.herisson.Clyde.Tables.ScientificPublications.*;
import ovh.herisson.Clyde.Tables.User;
import java.util.ArrayList;
import java.util.Date;
import java.util.Map;
@Service
@AllArgsConstructor
public class ResearchesService {
private final ResearcherRepository researcherRepo;
private final ResearchCoAuthorsRepository researchCoAuthorsRepo;
private final ResearchRepository articleRepo;
// Researchers Part
public Researcher getResearcherByUser(User user){
return researcherRepo.findByUser(user);
}
public boolean isCoAuthor(Research research, Researcher researcher){
Iterable<Researcher> coAuthors = researchCoAuthorsRepo.findResearchCoAuthors(research);
for (Researcher coAuthor : coAuthors){
if (researcher == coAuthor){
return true;
}
}
return false;
}
// researches Part
public Research getResearchById(long id) {
return articleRepo.findById(id);
}
public Iterable<Research> getResearchesByAuthor(long authorId){
Researcher researcher = researcherRepo.findById(authorId);
if (researcher == null) return null;
return researcherRepo.findAllByAuthorId(researcher);
}
public boolean hasNoAccessTo(Research research, User user){
if (research.getAccess() == Access.OpenSource) return false; // if the access is open source even non-users can see it
if (user == null) return true; // else you need at least to be a user
if (user.getRole() == Role.Admin) return false;
if (research.getAccess() == Access.Restricted &&
user.getRole() == Role.Secretary ||
user.getRole() == Role.Teacher || user.getRole() == Role.InscriptionService)
return false; // if the access is restricted only the staff member (above) can access the research
Researcher researcher = getResearcherByUser(user);
if (researcher==null)
return true;
return (research.getAccess() != Access.Private || research.getAuthor() != researcher) &&
(research.getAccess() != Access.Private || !isCoAuthor(research, researcher));
// if the researcher is the author or one of the co-authors of the research will return false
}
public Research saveResearch(Research research) {
return articleRepo.save(research);
}
public void modifyResearchData(Research research, Map<String, Object> updates) {
for (Map.Entry<String, Object> entry : updates.entrySet()){
switch (entry.getKey()){
case "title":
research.setTitle((String) entry.getValue());
break;
case "paperType":
research.setPaperType((PaperType) entry.getValue());
break;
case "language":
research.setLanguage((String) entry.getValue());
break;
case "domain":
research.setDomain((String) entry.getValue());
break;
case "summary":
research.setSummary((String) entry.getValue());
break;
case "access":
research.setAccess(Access.valueOf((String) entry.getValue()));
break;
}
}
articleRepo.save(research);
}
public void deleteResearch(Research research) {
articleRepo.delete(research);
}
public Iterable<Research> getAllResearches() {
return articleRepo.findAll();
}
public Researcher saveResearcher(Researcher researcher) {
if (researcherRepo.findByUser(researcher.getUser()) != null) return null;
return researcherRepo.save(researcher);
}
public Iterable<Researcher> getAllResearchers() {
return researcherRepo.findAll();
}
public Researcher getResearcherById(long id) {
return researcherRepo.findById(id);
}
public void deleteResearcher(Researcher researcher) {
researcherRepo.delete(researcher);
}
public boolean saveCoAuthors(Iterable<Long> researchersId, Research research) {
if (researchersId == null) return false;
ArrayList<Researcher> toAdd = new ArrayList<>();
for (long researcherId : researchersId){
Researcher researcher= researcherRepo.findById(researcherId);
if (research== null){
return false;
}
if (!toAdd.contains(researcher))
{
toAdd.add(researcher);
}
}
for (Researcher researcher: toAdd){
researchCoAuthorsRepo.save(new ResearchCoAuthors(researcher,research));
}
return true;
}
public Iterable<Researcher> getCoAuthors(Research research) {
return researchCoAuthorsRepo.findResearchCoAuthors(research);
}
public boolean deleteCoAuthor(Research research,Researcher coAuthor) {
ResearchCoAuthors result = researchCoAuthorsRepo.findResearchCoAuthors(research,coAuthor);
if (result ==null)
return false;
researchCoAuthorsRepo.delete(result);
return true;
}
public void modifyResearcherData(Researcher researcher, Map<String, Object> updates) {
for (Map.Entry<String, Object> entry : updates.entrySet()){
switch (entry.getKey()){
case "orcidId":
if (entry.getValue() != null)
researcher.setOrcidId((String) entry.getValue());
break;
case "domain":
if (entry.getValue() != null)
researcher.setDomain((String) entry.getValue());
break;
case "site":
if (entry.getValue() != null)
researcher.setSite((String) entry.getValue());
break;
}
}
researcherRepo.save(researcher);
}
public Research getResearchByUrl(String url) {
return articleRepo.findByPdfLocation(url);
}
public Research addView(Research research) {
research.setViews(research.getViews()+1);
return articleRepo.save(research);
}
}

View File

@ -1,45 +0,0 @@
package ovh.herisson.Clyde.Services.ScientificPublications;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import ovh.herisson.Clyde.Repositories.ScientificPublications.ResearchRepository;
import ovh.herisson.Clyde.Repositories.ScientificPublications.ResearcherRepository;
import ovh.herisson.Clyde.Repositories.ScientificPublications.StatsRepository;
import ovh.herisson.Clyde.Tables.ScientificPublications.Research;
import ovh.herisson.Clyde.Tables.ScientificPublications.Researcher;
import java.security.Key;
import java.util.*;
@Service
@AllArgsConstructor
public class StatisticsService {
private ResearchRepository articleRepo;
private StatsRepository statsRepo;
public Iterable<Iterable<Map<String, Integer>>> generateStats(Researcher researcher){
Iterable<Research> researches = articleRepo.findByAuthor(researcher);
if (researches == null) return null;
ArrayList<Iterable<Map<String,Integer>>> toReturn = new ArrayList<>();
toReturn.add(statsRepo.viewsByYears());
toReturn.add(statsRepo.viewsByMonths());
toReturn.add(statsRepo.viewsByTopics());
toReturn.add(statsRepo.researchesByYears());
toReturn.add(statsRepo.researchesByMonth());
toReturn.add(statsRepo.researchesByTopics());
toReturn.add(statsRepo.languageByYears());
toReturn.add(statsRepo.languageByMonths());
toReturn.add(statsRepo.languageByTopics());
return toReturn;
}
}

View File

@ -1,52 +1,20 @@
package ovh.herisson.Clyde.Services;
import org.springframework.stereotype.Service;
import ovh.herisson.Clyde.Repositories.CurriculumRepository;
import ovh.herisson.Clyde.Repositories.Inscription.ExternalCurriculumRepository;
import ovh.herisson.Clyde.Repositories.UserCurriculumRepository;
import ovh.herisson.Clyde.Tables.*;
import java.util.ArrayList;
import java.util.HashMap;
import ovh.herisson.Clyde.Tables.Curriculum;
import ovh.herisson.Clyde.Tables.User;
@Service
public class UserCurriculumService {
private final UserCurriculumRepository userCurriculumRepository;
private final CurriculumRepository curriculumRepo;
private final ExternalCurriculumRepository externalCurriculumRepo;
public UserCurriculumService(UserCurriculumRepository userCurriculumRepository, CurriculumRepository curriculumRepo, ExternalCurriculumRepository externalCurriculumRepo) {
public UserCurriculumService(UserCurriculumRepository userCurriculumRepository) {
this.userCurriculumRepository = userCurriculumRepository;
this.curriculumRepo = curriculumRepo;
this.externalCurriculumRepo = externalCurriculumRepo;
}
public Curriculum findByUser(User student){
return userCurriculumRepository.findByUser(student);
}
public HashMap<String,Object> findAllCurriculumByStudent(User student) {
ArrayList<UserCurriculum> list = userCurriculumRepository.findByUserOrderByCurriculum(student);
ArrayList<HashMap<String, Object>> curriculumlist = new ArrayList<HashMap<String, Object>>();
for (int i = 0; i < list.size(); i++) {
HashMap<String, Object> element = new HashMap<>();
Curriculum c = list.get(i).getCurriculum();
element.put("curriculumId", c.getCurriculumId());
element.put("year", c.getYear());
element.put("option", c.getOption());
element.put("dateyear", list.get(i).getYear());
curriculumlist.add(element);
}
HashMap<String, Object> toReturn = new HashMap<String, Object>();
toReturn.put("curriculumList", curriculumlist);
return toReturn;
}
}

View File

@ -5,13 +5,15 @@ import org.springframework.stereotype.Service;
import ovh.herisson.Clyde.Repositories.UserRepository;
import ovh.herisson.Clyde.Tables.Role;
import ovh.herisson.Clyde.Tables.User;
import ovh.herisson.Clyde.UserSaveCounter;
import java.util.*;
@Service
public class UserService {
private final UserRepository userRepo;
private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
private final UserSaveCounter usc = UserSaveCounter.getInstance();
public UserService(UserRepository userRepo){
this.userRepo = userRepo;
}
@ -106,10 +108,19 @@ public class UserService {
}
public User save(User user){
usc.reset();
user.setPassword(passwordEncoder.encode(user.getPassword()));
return userRepo.save(user);
}
public void saveAll(ArrayList<User> list){
//S'assure que le compteur est bien a 0
usc.reset();
userRepo.saveAll(list);
//Reset le compteur a zero pour les futurs ajouts
usc.reset();
}
public Iterable<User> getAll(){
return userRepo.findAll();
}
@ -131,4 +142,5 @@ public class UserService {
public void delete(User user) {
userRepo.delete(user);
}
}

View File

@ -7,6 +7,7 @@ public enum Applications {
// with any token
Profile,
// Students and higher authorization
Msg,
Forum,
@ -17,9 +18,6 @@ public enum Applications {
UsersList,
// InscriptionService authorization
Requests,
// profile of a researcher
ResearcherProfile,
ManageResearcherProfile,
Inscription,
StudentsList
}

View File

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

View File

@ -1,83 +0,0 @@
package ovh.herisson.Clyde.Tables.Inscription;
import jakarta.persistence.*;
import org.hibernate.annotations.OnDelete;
import org.hibernate.annotations.OnDeleteAction;
import ovh.herisson.Clyde.Tables.Course;
import ovh.herisson.Clyde.Tables.RequestState;
import ovh.herisson.Clyde.Tables.User;
import java.util.Date;
@Entity
public class ExemptionsRequest {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
@JoinColumn(name = "Users")
@ManyToOne(fetch = FetchType.EAGER)
private User user;
@JoinColumn(name = "Course")
@ManyToOne(fetch = FetchType.EAGER)
private Course course;
private String justifDocument;
private RequestState state;
private Date date;
public ExemptionsRequest(User user, Course course, String justifDocument, RequestState state, Date date){
this.user = user;
this.course = course;
this.justifDocument = justifDocument;
this.state = state;
this.date = date;
}
public ExemptionsRequest(){}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Course getCourse() {
return course;
}
public void setCourse(Course course) {
this.course = course;
}
public String getJustifDocument() {
return justifDocument;
}
public void setJustifDocument(String justifDocument) {
this.justifDocument = justifDocument;
}
public RequestState getState() {
return state;
}
public void setState(RequestState state) {
this.state = state;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
}

View File

@ -1,114 +0,0 @@
package ovh.herisson.Clyde.Tables.Inscription;
import jakarta.persistence.*;
import ovh.herisson.Clyde.Tables.User;
//This table stores a student's curriculum from another university
@Entity
public class ExternalCurriculum {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
//An external curriculum is first linked to an inscription request and when it is accepted and the user is created we link it to the user
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name="InscriptionRequest")
private InscriptionRequest inscriptionRequest;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name="Users")
private User user;
private String school;
private String formation;
//This string denotes the completion of the external formation or the last year completed by the student in this formation
private String completion;
private int startYear;
private int endYear;
private String justifdocUrl;
public ExternalCurriculum(){}
public ExternalCurriculum(InscriptionRequest ir, String school, String formation, String completion, int startYear, int endYear, String justifdocUrl,User user){
this.inscriptionRequest = ir;
this.school = school;
this.formation = formation;
this.completion = completion;
this.startYear = startYear;
this.endYear = endYear;
this.justifdocUrl = justifdocUrl;
this.user = user;
}
public int getId() {
return id;
}
public InscriptionRequest getInscriptionRequest() {
return inscriptionRequest;
}
public void setInscriptionRequest(InscriptionRequest inscriptionRequest) {
this.inscriptionRequest = inscriptionRequest;
}
public String getSchool() {
return school;
}
public void setSchool(String school) {
this.school = school;
}
public String getFormation() {
return formation;
}
public void setFormation(String formation) {
this.formation = formation;
}
public String getCompletion(){
return completion;
}
public void setCompletion(String completion) {
this.completion = completion;
}
public int getStartYear() {
return startYear;
}
public void setStartYear(int startYear) {
this.startYear = startYear;
}
public int getEndYear() {
return endYear;
}
public void setEndYear(int endYear) {
this.endYear = endYear;
}
public void setJustifdocUrl(String justifdocUrl) {
this.justifdocUrl = justifdocUrl;
}
public String getJustifdocUrl() {
return justifdocUrl;
}
public void setUser(User user) {
this.user = user;
}
public User getUser() {
return user;
}
}

View File

@ -1,64 +0,0 @@
package ovh.herisson.Clyde.Tables.Inscription;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
@Entity
public class Minerval {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private long studentRegNo;
private int paidAmount;
private int toPay;
//If the academic year is 2023-2024 then 2023 will be stored here (we take the lowest year)
private int year;
public Minerval(){}
public Minerval(long studentRegNo, int paidAmount, int toPay, int year){
this.studentRegNo = studentRegNo;
this.paidAmount = paidAmount;
this.toPay = toPay;
this.year = year;
}
public long getStudentRegNo() {
return studentRegNo;
}
public void setStudentRegNo(long studentRegNo) {
this.studentRegNo = studentRegNo;
}
public int getPaidAmount() {
return paidAmount;
}
public void setPaidAmount(int paidAmount) {
this.paidAmount = paidAmount;
}
public int getToPay() {
return toPay;
}
public void setToPay(int toPay) {
this.toPay = toPay;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public long getId() {
return id;
}
}

View File

@ -1,84 +0,0 @@
package ovh.herisson.Clyde.Tables.Inscription;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import java.util.Date;
@Entity
public class Payment {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private long studentRegNo;
private String card;
private String client;
private Date expDate;
private int amount;
private Date date;
public Payment(){}
public Payment(long studentRegNo, String card, String client, Date expDate, int amount, Date date){
this.studentRegNo = studentRegNo;
this.card = card;
this.client = client;
this.expDate = expDate;
this.amount = amount;
this.date = date;
}
public long getStudentRegNo() {
return studentRegNo;
}
public void setStudentRegNo(long studentRegNo) {
this.studentRegNo = studentRegNo;
}
public String getCard() {
return card;
}
public void setCard(String card) {
this.card = card;
}
public String getClient() {
return client;
}
public void setClient(String client) {
this.client = client;
}
public Date getExpDate() {
return expDate;
}
public void setExpDate(Date expDate) {
this.expDate = expDate;
}
public int getAmount() {
return amount;
}
public void setAmount(int amount) {
this.amount = amount;
}
public long getId() {
return id;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
}

View File

@ -1,88 +0,0 @@
package ovh.herisson.Clyde.Tables.Inscription;
import jakarta.persistence.*;
import org.hibernate.annotations.OnDelete;
import org.hibernate.annotations.OnDeleteAction;
import ovh.herisson.Clyde.Tables.RequestState;
import ovh.herisson.Clyde.Tables.User;
import java.util.Date;
@Entity
public class ScholarshipRequest {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@JoinColumn(name="Users")
@ManyToOne(fetch = FetchType.EAGER)
private User user;
private RequestState state;
private Date date;
private int amount;
private String taxDocUrl;
private String residencyDocUrl;
public ScholarshipRequest(User user, RequestState state, int amount, Date date, String taxDocUrl, String residencyDocUrl){
this.user = user;
this.state = state;
this.amount = amount;
this.date = date;
this.taxDocUrl = taxDocUrl;
this.residencyDocUrl = residencyDocUrl;
}
public ScholarshipRequest(){}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public RequestState getState() {
return state;
}
public void setState(RequestState state) {
this.state = state;
}
public int getAmount() {
return amount;
}
public void setAmount(int amount) {
this.amount = amount;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public long getId() {
return id;
}
public String getResidencyDocUrl() {
return residencyDocUrl;
}
public void setResidencyDocUrl(String residencyDocUrl) {
this.residencyDocUrl = residencyDocUrl;
}
public String getTaxDocUrl() {
return taxDocUrl;
}
public void setTaxDocUrl(String taxDocUrl) {
this.taxDocUrl = taxDocUrl;
}
}

View File

@ -1,67 +0,0 @@
package ovh.herisson.Clyde.Tables.Inscription;
import jakarta.persistence.*;
import ovh.herisson.Clyde.Tables.RequestState;
import ovh.herisson.Clyde.Tables.User;
import java.util.Date;
@Entity
public class UninscriptionRequest {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private RequestState state;
private String reason;
private Date date;
@JoinColumn(name = "Users")
@ManyToOne(fetch = FetchType.EAGER)
private User user;
public UninscriptionRequest(RequestState state,String reason, Date date, User user){
this.state = state;
this.reason = reason;
this.date = date;
this.user = user;
}
public UninscriptionRequest(){}
public RequestState getState() {
return state;
}
public void setState(RequestState state) {
this.state = state;
}
public String getReason() {
return reason;
}
public void setReason(String reason) {
this.reason = reason;
}
public long getId() {
return id;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public void setDate(Date date) {
this.date = date;
}
public Date getDate() {
return date;
}
}

View File

@ -1,8 +1,6 @@
package ovh.herisson.Clyde.Tables.Inscription;
package ovh.herisson.Clyde.Tables;
import jakarta.persistence.*;
import ovh.herisson.Clyde.Tables.RequestState;
import java.util.Date;
@ -17,16 +15,14 @@ public class InscriptionRequest {
private String email;
private String country;
private Date birthDate;
private Long curriculumId;
private RequestState state;
private String profilePicture;
private String password;
private String identityCard;
private Date submissionDate;
private RequestState equivalenceState;
public InscriptionRequest(){}
public InscriptionRequest(String lastName, String firstName, String address, String email, String country, Date birthDate,Long curriculumId, RequestState state, String profilePicture, String password, String identityCard, Date submissionDate, RequestState equivalenceState){
private String password;
public InscriptionRequest(){}
public InscriptionRequest(String lastName, String firstName, String address, String email, String country, Date birthDate,Long curriculumId, RequestState state, String profilePicture, String password){
this.lastName = lastName;
this.firstName = firstName;
this.address = address;
@ -37,9 +33,6 @@ public class InscriptionRequest {
this.state = state;
this.profilePicture = profilePicture;
this.password = password;
this.identityCard = identityCard;
this.submissionDate = submissionDate;
this.equivalenceState = equivalenceState;
}
public int getId() {
@ -125,28 +118,4 @@ public class InscriptionRequest {
public void setPassword(String password) {
this.password = password;
}
public String getIdentityCard() {
return identityCard;
}
public void setIdentityCard(String identityCard) {
this.identityCard = identityCard;
}
public Date getSubmissionDate() {
return submissionDate;
}
public void setSubmissionDate(Date submissionDate) {
this.submissionDate = submissionDate;
}
public RequestState getEquivalenceState() {
return equivalenceState;
}
public void setEquivalenceState(RequestState equivalenceState) {
this.equivalenceState = equivalenceState;
}
}

View File

@ -1,72 +0,0 @@
package ovh.herisson.Clyde.Tables.Msg;
/******************************************************
* @file Discussion.java
* @author Anthony Debucquoy
* @scope Extension messagerie
*
* Discussion allow to regroupe multiple user in and message together
* for the messages application to work
******************************************************/
import java.util.List;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.JoinTable;
import jakarta.persistence.ManyToMany;
import jakarta.persistence.OneToMany;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import ovh.herisson.Clyde.Tables.User;
@Entity
@Getter
@Setter
@NoArgsConstructor
public class Discussion{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String name;
@ManyToMany
@JoinTable(
name = "discussion_members",
joinColumns = @JoinColumn(name = "discussion_id"),
inverseJoinColumns = @JoinColumn(name = "user_id")
)
private List<User> members;
@OneToMany(mappedBy="discussion", orphanRemoval = true, cascade = CascadeType.ALL)
private List<Message> msgs;
public Discussion(String name){
this.name = name;
}
public Discussion(String name, User user){
this.name = name;
this.members = List.of(user);
}
public void addMessage(Message msg){
msg.setDiscussion(this);
msgs.add(msg);
}
public void addMember(User user) {
members.add(user);
}
public void delMember(User user) {
members.remove(user);
}
}

View File

@ -1,66 +0,0 @@
package ovh.herisson.Clyde.Tables.Msg;
/******************************************************
* @file Message.java
* @author Anthony Debucquoy
* @scope Extension messagerie
*
* Represent a message sent to a discussion
******************************************************/
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;
import com.fasterxml.jackson.annotation.JsonIgnore;
import java.util.Date;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import jakarta.persistence.OneToOne;
import jakarta.persistence.PrePersist;
import jakarta.persistence.Temporal;
import jakarta.persistence.TemporalType;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import ovh.herisson.Clyde.Tables.User;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Entity
public class Message {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String content;
@CreationTimestamp
@Column(nullable = false)
private Date created;
@ManyToOne
private User author;
public User getAuthor() {
return author;
}
@OneToOne
private Message response;
@ManyToOne(optional = false)
@JsonIgnore
private Discussion discussion;
}

View File

@ -1,11 +1,8 @@
package ovh.herisson.Clyde.Tables.Inscription;
package ovh.herisson.Clyde.Tables;
import jakarta.persistence.*;
import org.hibernate.annotations.OnDelete;
import org.hibernate.annotations.OnDeleteAction;
import ovh.herisson.Clyde.Tables.Curriculum;
import ovh.herisson.Clyde.Tables.RequestState;
import ovh.herisson.Clyde.Tables.User;
@Entity
public class ReInscriptionRequest {

View File

@ -3,6 +3,5 @@ package ovh.herisson.Clyde.Tables;
public enum RequestState {
Accepted,
Refused,
Pending,
Unrequired
Pending
}

View File

@ -1,15 +0,0 @@
package ovh.herisson.Clyde.Tables.ScientificPublications;
/******************************************************
* @file Access.java
* @author Maxime Bartha
* @scope Extension Publications scientifiques
*
* Access Type for the Articles
*
******************************************************/
public enum Access {
OpenSource, // everyone can see
Restricted, // only Researchers and Staff Members (secretary, teachers and Inscription Service)
Private, // only authors and co-authors
}

View File

@ -1,16 +0,0 @@
package ovh.herisson.Clyde.Tables.ScientificPublications;
/******************************************************
* @file PaperType.java
* @author Maxime Bartha
* @scope Extension Publications scientifiques
*
* Type of the scientific paper
*
******************************************************/
public enum PaperType {
Article,
Paper,
Book,
BookChapter,
}

View File

@ -1,68 +0,0 @@
package ovh.herisson.Clyde.Tables.ScientificPublications;
/******************************************************
* @file Research.java
* @author Maxime Bartha
* @scope Extension Publications scientifiques
*
* Research entity
*
******************************************************/
import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.OnDelete;
import org.hibernate.annotations.OnDeleteAction;
import java.util.Date;
@Getter
@Setter
@NoArgsConstructor
@Entity
public class Research {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String title;
@ManyToOne(fetch = FetchType.EAGER)
@OnDelete(action = OnDeleteAction.CASCADE)
@JoinColumn(name ="Researcher")
private Researcher author;
@Column(nullable = false)
private Date releaseDate;
private PaperType paperType;
private String pdfLocation;
private String bibTexLocation;
private String language;
private Access access;
private String domain;
private String summary;
private int views;
public Research(String title, Researcher author, Date releaseDate, PaperType paperType,
String pdfLocation, String bibTexLocation, String language, Access access, String domain, String summary){
this.author = author;
this.title = title;
this.releaseDate = releaseDate;
this.paperType = paperType;
this.pdfLocation = pdfLocation;
this.bibTexLocation = bibTexLocation;
this.language = language;
this.access = access;
this.domain = domain;
this.summary = summary;
}
}

View File

@ -1,42 +0,0 @@
package ovh.herisson.Clyde.Tables.ScientificPublications;
/******************************************************
* @file ResearchCoAuthors
* @author Maxime Bartha
* @scope Extension Publications scientifiques
*
* Co-Authors List entity (will be accessed by Articles)
*
******************************************************/
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.hibernate.annotations.OnDelete;
import org.hibernate.annotations.OnDeleteAction;
@Getter
@Setter
@NoArgsConstructor
@Entity
public class ResearchCoAuthors {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
Long id;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "Researcher")
private Researcher coAuthor;
@ManyToOne(fetch = FetchType.EAGER)
@OnDelete(action = OnDeleteAction.CASCADE)
@JoinColumn(name = "Article")
private Research research;
public ResearchCoAuthors(Researcher coAuthor, Research research){
this.coAuthor = coAuthor;
this.research = research;
}
}

View File

@ -1,39 +0,0 @@
package ovh.herisson.Clyde.Tables.ScientificPublications;
/******************************************************
* @file Researcher.java
* @author Maxime Bartha
* @scope Extension Publications scientifiques
*
* Researcher entity
*
******************************************************/
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import ovh.herisson.Clyde.Tables.User;
@Getter
@Setter
@NoArgsConstructor
@Entity
public class Researcher {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@OneToOne(cascade=CascadeType.REMOVE, optional=true)
private User user;
private String orcidId;
private String site;
private String domain;
public Researcher(User user, String orcidId, String site, String domain){
this.user = user;
this.orcidId = orcidId;
this.site = site;
this.domain = domain;
}
}

View File

@ -1,18 +1,17 @@
package ovh.herisson.Clyde.Tables;
import jakarta.persistence.*;
import ovh.herisson.Clyde.Tables.Msg.Discussion;
import ovh.herisson.Clyde.Tables.Msg.Message;
import org.hibernate.annotations.GenericGenerator;
import java.util.Date;
import java.util.List;
@Entity
@Table(name = "Users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@GenericGenerator(name = "userGen", type = ovh.herisson.Clyde.RegNoGenerator.class)
@GeneratedValue(generator = "userGen")
private Long regNo;
private String lastName;
private String firstName;
@ -24,15 +23,6 @@ public class User {
private String profilePictureUrl;
private ovh.herisson.Clyde.Tables.Role role;
private String password;
////// Extension Messagerie /////
@OneToMany(mappedBy = "author", cascade = CascadeType.ALL)
private List<Message> msgs;
@ManyToMany( mappedBy = "members" )
private List<Discussion> discussions;
/////////////////////////////////
public User(String lastName, String firstName, String email, String address,
String country, Date birthDate, String profilePictureUrl, Role role, String password)
{

View File

@ -21,12 +21,9 @@ public class UserCurriculum {
@OnDelete(action = OnDeleteAction.CASCADE)
private Curriculum curriculum;
private int year;
public UserCurriculum(User user, Curriculum curriculum, int year){
public UserCurriculum(User user, Curriculum curriculum){
this.user = user;
this.curriculum = curriculum;
this.year = year;
}
public UserCurriculum() {}
@ -50,12 +47,4 @@ public class UserCurriculum {
public void setCurriculum(Curriculum curriculum) {
this.curriculum = curriculum;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
}

View File

@ -0,0 +1,25 @@
package ovh.herisson.Clyde;
public final class UserSaveCounter {
private static UserSaveCounter instance;
private int count = 0;
public void increment() {
this.count+=1;
}
public int getCount() {
return count;
}
public void reset(){
this.count = 0;
}
public static UserSaveCounter getInstance(){
if (instance == null){
instance = new UserSaveCounter();
return instance;
}
return instance;
}
}

View File

@ -1,12 +1,2 @@
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
spring.sql.init.mode=always
# spring.datasource.url=jdbc:postgresql://localhost:5442/clyde
spring.datasource.url=jdbc:postgresql://db:5432/clyde
spring.datasource.username=devel
spring.datasource.password=devel
# spring.config.activate.on-profile=prod
# spring.datasource.url=jdbc:postgresql:clyde?socketFactory=org.newsclub.net.unix.AFUNIXSocketFactory$FactoryArg&socketFactoryArg=/var/run/postgresql/.s.PGSQL.5432
# spring.datasource.username=clyde

View File

@ -23,6 +23,7 @@ import ovh.herisson.Clyde.Repositories.TokenRepository;
import ovh.herisson.Clyde.Repositories.UserRepository;
import ovh.herisson.Clyde.Responses.UnauthorizedResponse;
import ovh.herisson.Clyde.Services.TokenService;
import ovh.herisson.Clyde.Services.UserService;
import ovh.herisson.Clyde.Tables.Role;
import ovh.herisson.Clyde.Tables.Token;
import ovh.herisson.Clyde.Tables.User;
@ -47,6 +48,8 @@ public class UserControllerTest {
@Autowired
private TokenService tokenService;
@Autowired
private UserService userService;
@Autowired
private UserRepository userRepository;
@Autowired
@ -79,12 +82,13 @@ public class UserControllerTest {
tokenRepository.deleteAll();
userRepository.deleteAll();
}
@Test
//Verifie qu'un user qui n'a pas les permissions admin ou secretaire ne peut pas post
public void userPostTest(){
User god = new User("god","god","admin@admin.com","everywhere","every",new Date(0), null, Role.Admin,"goddoesntneedpassword");
Token godToken = new Token(god, tokenService.generateNewToken(), new Date());
userRepository.save(god);
userService.save(god);
tokenService.saveToken(godToken);
//Can god post herobrine himself ?
@ -97,7 +101,7 @@ public class UserControllerTest {
//Can noob post herobrine without authorizations (no)
User noob = new User("boon","noob","noob@student.com","everywhere","every",new Date(0), null, Role.Student,"noob");
Token noobToken = new Token(noob, tokenService.generateNewToken(), new Date());
userRepository.save(noob);
userService.save(noob);
tokenService.saveToken(noobToken);
with().body(herobrine).contentType(ContentType.JSON).header("Authorization", noobToken.getToken()).when().request("POST", "/user").then().statusCode(401);

View File

@ -7,6 +7,7 @@ import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.test.context.TestPropertySource;
import ovh.herisson.Clyde.Services.UserService;
import ovh.herisson.Clyde.Tables.Role;
import ovh.herisson.Clyde.Tables.User;
@ -24,6 +25,7 @@ public class UserRepoTest {
@BeforeEach
public void setup(){
userRepo.deleteAll();
User herobrine = new User("brine","hero","admin@admin.com","in your WalLs","ShadowsLand", new GregorianCalendar(2005, 4, 3).getTime(), null, Role.Admin,"admin");
userRepo.save(herobrine);
}
@ -34,8 +36,8 @@ public class UserRepoTest {
}
@Test
public void usertest(){
Assert.assertEquals("brine", userRepo.findById(1).getLastName());
Assert.assertTrue(new GregorianCalendar(2005, 4, 3).getTime().equals(userRepo.findById(1).getBirthDate()));
Assert.assertEquals("brine", userRepo.findByEmail("admin@admin.com").getLastName());
Assert.assertTrue(new GregorianCalendar(2005, 4, 3).getTime().equals(userRepo.findByEmail("admin@admin.com").getBirthDate()));
}
}

View File

@ -1,29 +0,0 @@
services:
db:
image: 'postgres:16'
environment:
- 'POSTGRES_DB=clyde'
- 'POSTGRES_USER=devel'
- 'POSTGRES_PASSWORD=devel'
# Uncomment this to allow connections to the db from outside the container
# ports:
# - '5442:5432'
back:
build: backend/.
ports:
- "8080:8080"
volumes:
- cdn:/backend/cdn
ulimits:
nofile:
soft: 65536
hard: 65536
front:
build: frontend/.
volumes:
- cdn:/app/front/dist/cdn
ports:
- "8000:8080"
volumes:
cdn:

View File

@ -1,11 +0,0 @@
# https://v2.vuejs.org/v2/cookbook/dockerize-vuejs-app
FROM node:lts-alpine
RUN npm install -g http-server
WORKDIR /app/front
COPY package*.json ./
RUN npm install
COPY . .
ENV VITE_CLYDE_MODE=container
RUN npm run build
EXPOSE 8080
CMD [ "http-server", "dist" ]

View File

@ -8,8 +8,6 @@
"name": "clyde",
"version": "0.0.0",
"dependencies": {
"@canvasjs/vue-charts": "^1.0.4",
"@vueuse/core": "^10.9.0",
"vite-plugin-top-level-await": "^1.4.1",
"vue": "^3.4.15",
"vue3-toastify": "^0.2.1"
@ -31,20 +29,6 @@
"node": ">=6.0.0"
}
},
"node_modules/@canvasjs/charts": {
"version": "3.7.45",
"resolved": "https://registry.npmjs.org/@canvasjs/charts/-/charts-3.7.45.tgz",
"integrity": "sha512-FPMX8wn+PEHzAa/GLBsL5lWB81AzKZLw51t7SiSUjMbtUN5/OIrmDcwUTw+53/Bbdd9gm2LLmxAdZsQ75JI31g=="
},
"node_modules/@canvasjs/vue-charts": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@canvasjs/vue-charts/-/vue-charts-1.0.4.tgz",
"integrity": "sha512-PzOA8xeb/f68a39uoFZNn843dGPU36bsqmbO5DWjP7k6FwkK5AeGkYa/H3RHC02Xc6mG68vg9aFNj2Fyqhu4UQ==",
"dependencies": {
"@canvasjs/charts": "^3.7.5",
"vue": ">=3.0.0"
}
},
"node_modules/@esbuild/aix-ppc64": {
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz",
@ -769,11 +753,6 @@
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
"integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw=="
},
"node_modules/@types/web-bluetooth": {
"version": "0.0.20",
"resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz",
"integrity": "sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow=="
},
"node_modules/@vitejs/plugin-vue": {
"version": "5.0.4",
"resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.0.4.tgz",
@ -887,89 +866,6 @@
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.19.tgz",
"integrity": "sha512-/KliRRHMF6LoiThEy+4c1Z4KB/gbPrGjWwJR+crg2otgrf/egKzRaCPvJ51S5oetgsgXLfc4Rm5ZgrKHZrtMSw=="
},
"node_modules/@vueuse/core": {
"version": "10.9.0",
"resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.9.0.tgz",
"integrity": "sha512-/1vjTol8SXnx6xewDEKfS0Ra//ncg4Hb0DaZiwKf7drgfMsKFExQ+FnnENcN6efPen+1kIzhLQoGSy0eDUVOMg==",
"dependencies": {
"@types/web-bluetooth": "^0.0.20",
"@vueuse/metadata": "10.9.0",
"@vueuse/shared": "10.9.0",
"vue-demi": ">=0.14.7"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@vueuse/core/node_modules/vue-demi": {
"version": "0.14.7",
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.7.tgz",
"integrity": "sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==",
"hasInstallScript": true,
"bin": {
"vue-demi-fix": "bin/vue-demi-fix.js",
"vue-demi-switch": "bin/vue-demi-switch.js"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@vue/composition-api": "^1.0.0-rc.1",
"vue": "^3.0.0-0 || ^2.6.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
}
}
},
"node_modules/@vueuse/metadata": {
"version": "10.9.0",
"resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.9.0.tgz",
"integrity": "sha512-iddNbg3yZM0X7qFY2sAotomgdHK7YJ6sKUvQqbvwnf7TmaVPxS4EJydcNsVejNdS8iWCtDk+fYXr7E32nyTnGA==",
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@vueuse/shared": {
"version": "10.9.0",
"resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.9.0.tgz",
"integrity": "sha512-Uud2IWncmAfJvRaFYzv5OHDli+FbOzxiVEQdLCKQKLyhz94PIyFC3CHcH7EDMwIn8NPtD06+PNbC/PiO0LGLtw==",
"dependencies": {
"vue-demi": ">=0.14.7"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@vueuse/shared/node_modules/vue-demi": {
"version": "0.14.7",
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.7.tgz",
"integrity": "sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==",
"hasInstallScript": true,
"bin": {
"vue-demi-fix": "bin/vue-demi-fix.js",
"vue-demi-switch": "bin/vue-demi-switch.js"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@vue/composition-api": "^1.0.0-rc.1",
"vue": "^3.0.0-0 || ^2.6.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
}
}
},
"node_modules/agent-base": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz",

View File

@ -9,8 +9,6 @@
"preview": "vite preview"
},
"dependencies": {
"@canvasjs/vue-charts": "^1.0.4",
"@vueuse/core": "^10.9.0",
"vite-plugin-top-level-await": "^1.4.1",
"vue": "^3.4.15",
"vue3-toastify": "^0.2.1"

View File

@ -28,7 +28,6 @@ app.language=Language
app.manage.profile=Manage profile
app.studentList=Students List
app.users=Users
app.manage.researcherProfile=Manage researcher profile
request.moreInfos=More Infos
request.accept=Accept
request.refuse=Refuse

View File

@ -28,7 +28,6 @@ app.language=Langue
app.manage.profile=Gérer le profil
app.studentList=Liste des étudiants
app.users=Utilisateurs
app.manage.researcherProfile= gérer son profil de chercheur
request.moreInfos=Plus d'Infos
request.accept=Accepter
request.refuse=Refuser

View File

@ -52,7 +52,7 @@ window.addEventListener('hashchange', () => {
<a class="icon" href="#Notifications">
<div class="fa-solid fa-bell" style="margin-top: 7px; margin-bottom: 3px;"></div>
</a></li>
<li @click="active=!active" class="option"style="float: right;" title=settings>
<li @click="active=!active" class="option"style="float: right;" title=settings>
<a class="icon" >
<div class="fa-solid fa-gear" style="margin-top: 7px; margin-bottom: 3px;"></div>
<div v-if="active" class="dropdown">
@ -86,9 +86,12 @@ window.addEventListener('hashchange', () => {
</ul>
</div>
<div class="page">
<div style=" margin:50px;">
<Suspense>
<component :is="currentView" />
<component :is="currentView" />
</Suspense>
</div>
</div>
</div>
</template>
@ -96,8 +99,6 @@ window.addEventListener('hashchange', () => {
<style scoped>
.container{
height: 100%;
width: 100%;
display:grid;
grid-template-columns:[firstCol-start]70px[firstCol-end secondCol-start]auto[endCol];
grid-template-rows:[firstRow-start]61px[firstRow-end secondRow-start] auto [endRow];
@ -110,8 +111,6 @@ window.addEventListener('hashchange', () => {
.page {
grid-area:page;
height: 100%;
width: 100%;
place-self:center;
}

View File

@ -0,0 +1,113 @@
<script setup>
import i18n from "@/i18n.js"
import {ref} from 'vue'
import {validateRegister, getAllRegisters } from '@/rest/ServiceInscription.js'
const requests = ref(await getAllRegisters());
console.log(requests);
async function upPage(id,review){
await validateRegister(id,review);
requests.value = await getAllRegisters();
}
</script>
<template>
<div v-for="item of requests">
<div class="bodu" v-if="item.state === 'Pending'">
<div class="container">
<div class="id"><a>{{item.id}}</a></div>
<div class="surname"><a>{{item.lastName}}</a></div>
<div class="firstname"><a>{{item.firstName}}</a></div>
<div class="infos"><button style="background-color:rgb(105,05,105);" >{{i18n("request.moreInfos")}}</button></div>
<div class="accept"><button @click="upPage(item.id,'Accepted')" style="background-color:rgb(0,105,50);">{{i18n("request.accept")}}</button></div>
<div class="refuse"><button @click="upPage(item.id,'Refused')" style="background-color:rgb(105,0,0);">{{i18n("request.refuse")}}</button></div>
</div>
</div>
</div>
</template>
<style scoped>
.container{
color:white;
height:100px;
font-size:20px;
display:grid;
grid-template-columns:[firstCol-start]100px[firstCol-end secondCol-start]150px[secondCol-end thirdCol-start]200px[thirdCol-end fourthCol-start]150px[fourthCol-end]150px[fifthCol-end]150px[sixthCol-end]150px[endCol];
grid-template-areas:
"id type surname firstname infos accept refuse";
column-gap:10px;
}
.infos {
grid-area:infos;
align-self:center;
}
.accept{
grid-area:accept;
align-self:center;
}
.refuse{
grid-area:refuse;
align-self:center;
}
.titles {
grid-area:titles;
background-color:rgb(215,215,215);
}
.id{
grid-area:id;
margin-left:40px;
align-self:center;
}
.type{
grid-area:type;
align-self:center;
}
.surname{
grid-area:surname;
align-self:center;
white-space: nowrap;
overflow: hidden;
text-overflow:ellipsis;
}
.firstname{
grid-area:firstname;
align-self:center;
white-space: nowrap;
overflow: hidden;
text-overflow:ellipsis;
}
button{
font-size:15px;
height:50px;
width:100px;
border:none;
border-radius:20px;
}
.bodu {
width:100%;
margin-bottom:10px;
border:2px solid black;
border-radius:9px;
background-color:rgb(50,50,50);
}
</style>

View File

@ -1,132 +0,0 @@
<script setup>
import i18n from "@/i18n.js"
import {getSelf, getUser} from '../../rest/Users.js'
import {getcurriculum,getSomeonesCurriculumList} from "@/rest/curriculum.js";
import {getRegisters} from "@/rest/ServiceInscription.js";
import {get} from "jsdom/lib/jsdom/named-properties-tracker.js";
import {getExternalCurriculumByInscrReq} from "@/rest/externalCurriculum.js";
import {ref} from "vue";
import ExternalCurriculumList from "@/Apps/Inscription/ExternalCurriculumList.vue";
import {editEquivalenceState} from "@/rest/requests.js";
const props = defineProps(['target']);
const request = await getRegisters(props.target);
const cursus = await getcurriculum(request.curriculum);
const user = await getSelf();
const list = ref(false);
const externalCurriculum = await getExternalCurriculumByInscrReq(request.id)
function getPP(){
if(request.profilePictureUrl === null){
return "/Clyde.png"
}
return request.profilePictureUrl;
}
async function editEquivalence(id, newstate){
await editEquivalenceState(id, newstate)
}
</script>
<template>
<div class="body" v-if="list == false">
<div class="container">
<div class="profilPic">
<img class="subContainter" :src=getPP()>
</div>
<div class = "globalInfos">
<div class="infosContainer">
<div>
FirstName/Name : {{request.firstName}} {{request.lastName}}
</div>
<div>
E-mail: {{request.email}}
</div>
<div>
Adresse : {{request.address}}
</div>
<div>
Pays : {{request.country}}
</div>
<div>
Date de naissance : {{request.birthDate}}
</div>
<div>
Cursus voulu : BAB {{cursus.year}} {{cursus.option}}
</div>
<div v-if="cursus.year > 1">
<button style="background-color:rgb(105,05,105);margin-left: 5%" @click="list=!list" v-if="(user.role == 'Teacher' || user.role == 'Admin')&& request.equivalenceState == 'Pending'">See external curriculums</button>
</div>
</div>
</div>
</div>
</div>
<div v-if="list==true">
<ExternalCurriculumList :ext-curr-list="externalCurriculum" :inscr-req-id="request.id"></ExternalCurriculumList>
<div style="margin-left: 15%;margin-top: 5%;">
<button style="margin-left: 2%" @click="list = false;editEquivalence(request.id, 'Accepted'); request.equivalenceState='Accepted'">Accept Equivalence</button>
<button style="margin-left: 2%" @click="list = false;editEquivalence(request.id, 'Refused'); request.equivalenceState='Refused'">Refuse Equivalence</button>
<button style="margin-left: 2%" @click="list=false">Return to profile</button>
</div>
</div>
</template>
<style scoped>
.container{
min-width:675px;
display:grid;
grid-template-columns:10vw 50vw;
grid-template-rows:200px auto;
column-gap:2.7%;
row-gap:45px;
grid-template-areas:
"profilPic globalInfos"
"minfos minfos";
}
.profilPic{
grid-area:profilPic;
width:100%;
}
.globalInfos {
grid-area:globalInfos;
align-self :center;
}
.body {
min-width:960px;
width:100%;
display:flex;
align-items:center;
justify-content:center;
margin-top:5%;
}
.subContainter{
width:100%;
background-color:rgb(50,50,50);
border-radius:20px;
border:4px solid black;
}
.infosContainer {
padding-bottom:50px;
border:2px solid black;
font-size:25px;
color:white;
padding:20px;
background-color:rgb(50,50,50);
border-radius:20px;
}
button{
font-size:15px;
height:50px;
width:100px;
border:none;
border-radius:20px;
}
</style>

View File

@ -1,192 +0,0 @@
<script setup>
import i18n from "@/i18n.js"
import {getUser} from '../../rest/Users.js'
import {getSomeonesCurriculumList} from "@/rest/curriculum.js";
import {ref} from "vue";
import ExternalCurriculumList from "@/Apps/Inscription/ExternalCurriculumList.vue";
import {getExternalCurriculumByUser} from "@/rest/externalCurriculum.js";
const props = defineProps(['target'])
const user = await getUser(props.target)
const UserCurriculum = await getSomeonesCurriculumList(props.target)
const externalcurrlist = await getExternalCurriculumByUser(user.regNo)
const extercurrlist = ref(false)
function getPP(){
if(user.profilePictureUrl === null){
return "/Clyde.png"
}
return user.profilePictureUrl
}
//Cette function renvoie l'année académique concernée si on est dans l'année 2023-2024 elle renvoie 2023
//car dans la db l'année scolaire 2023-2024 est representée juste par 2023 (le même système s'applique pour chaque années on prend la borne inférieure
function getYear(){
let date = new Date();
if (date.getMonth() <= 6){
return date.getFullYear()-1
}
return date.getFullYear()
}
</script>
<template>
<div class="body" v-if="extercurrlist==false">
<div class="container">
<div class="profilPic">
<img class="subContainter" :src=getPP()>
</div>
<div class = "globalInfos">
<div class="infosContainer">
<div>
FirstName/Name : {{user.firstName}} {{user.lastName}}
</div>
<div>
E-mail: {{user.email}}
</div>
<div>
Adresse : {{user.address}}
</div>
<div>
Pays : {{user.country}}
</div>
<div>
Date de naissance : {{user.birthDate}}
</div>
<div>
<button @click="extercurrlist=!extercurrlist">See external curriculums</button>
</div>
</div>
</div>
<div class="moreInfos">
<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="newcursus">
<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 v-if="extercurrlist==true">
<ExternalCurriculumList :ext-curr-list="externalcurrlist"></ExternalCurriculumList>
</div>
</template>
<style scoped>
.container{
min-width:675px;
display:grid;
grid-template-columns:10vw 50vw;
grid-template-rows:200px auto;
column-gap:2.7%;
row-gap:45px;
grid-template-areas:
"profilPic globalInfos"
"minfos minfos";
}
.profilPic{
grid-area:profilPic;
}
.globalInfos {
grid-area:globalInfos;
align-self :center;
}
.body {
min-width:960px;
width:100%;
display:flex;
align-items:center;
justify-content:center;
margin-top:5%;
}
.subContainter{
width:100%;
background-color:rgb(50,50,50);
border-radius:20px;
border:4px solid black;
}
.infosContainer {
padding-bottom:50px;
border:2px solid black;
font-size:25px;
color:white;
padding:20px;
background-color:rgb(50,50,50);
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;
}
.containerElement{
justify-content:center;
display:grid;
grid-template-columns:100px 100px 300px;
grid-template-areas:
"year option dateyear";
column-gap:40px;
padding-left: 25px;
}
</style>

View File

@ -1,139 +0,0 @@
<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 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 : "",
})
</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,87 +0,0 @@
<script setup>
import i18n from "@/i18n.js";
import {ref} from "vue";
const props = defineProps(["extCurrList"])
const extCurrList = ref(props.extCurrList)
console.log(extCurrList)
</script>
<template style="margin-top:5%;">
<div style="display:flex; justify-content:center; " v-for="item in extCurrList">
<div class="bodu">
<div class="container">
<div class="status"><a style="margin-left:30px">{{item.state}}</a></div>
<div class="school"><a>{{item.school}}</a></div>
<div class="formation"><a>{{item.formation}}</a></div>
<div class="completion"><a>{{item.completion}}</a></div>
<div class="download"><button>Download document</button></div>
</div>
</div>
</div>
</template>
<style scoped>
.container{
color:white;
height:100px;
font-size:30px;
display:grid;
grid-template-columns:15% 10% 20% 15% 13.1%;
grid-template-areas:
"status school formation completion download";
column-gap:10px;
}
.status {
grid-area:status;
align-self:center;
font-size: 70%;
}
.school{
grid-area:school;
align-self:center;
font-size: 70%;
}
.formation{
grid-area:formation;
align-self:center;
font-size: 70%;
}
.completion{
grid-area:completion;
align-self:center;
white-space: nowrap;
overflow: hidden;
text-overflow:ellipsis;
font-size: 70%;
}
.download{
grid-area: download;
align-self:center;
}
button{
font-size:15px;
height:50px;
width:75%;
border:none;
border-radius:20px;
}
.bodu {
margin-top:2%;
width:66%;
border:2px solid black;
border-radius:9px;
background-color:rgb(50,50,50);
}
</style>

View File

@ -1,196 +0,0 @@
<script setup>
import i18n from "@/i18n.js"
import {ref} from 'vue'
import {validateRegister, getAllRegisters } from '@/rest/ServiceInscription.js'
import AboutRequest from "@/Apps/Inscription/AboutRequest.vue";
import {getAllExemptionsRequest, getAllScholarShipsRequest} from "@/rest/requests.js";
const requests = ref(await getAllRegisters());
let targetId = "";
const requestType = ref("inscription");
const filterType = ref("None");
//0 = liste, 1 = détails, 2 = sure?
let windowsState = ref(0);
async function upPage(id,review){
await validateRegister(id,review);
requests.value = await getAllRegisters();
}
async function loadRequests(){
if (requestType.value === "inscription"){
requests.value = await getAllRegisters();
}
if (requestType.value === "scholarship"){
requests.value = await getAllScholarShipsRequest();
}
if(requestType.value === "exemption"){
requests.value = await getAllExemptionsRequest();
}
}
</script>
<template>
<div v-if="windowsState === 1">
<AboutRequest :target="targetId"></AboutRequest>
</div>
<div v-if="windowsState === 0">
<div style="margin-top: 2%;margin-left: 2%">
<span>Request type : </span>
<select v-model="requestType" @change="loadRequests()">
<option>inscription</option>
<option>scholarship</option>
<option>exemption</option>
</select>
<span style="margin-left: 5%">
Filter :
<select v-model="filterType">
<option>None</option>
<option>Pending</option>
<option>Accepted</option>
<option>Refused</option>
</select>
</span>
</div>
<div style='display:flex; justify-content:center; min-width:1140px;' v-for="item of requests">
<div class="bodu" style="width: 95%" v-if="filterType == 'None' || filterType == item.state">
<div class="container" style="grid-template-columns:11% 15% 20% 10% 10% 9% 9%;grid-template-areas:'date state equivalencestate surname firstname accept refuse infos';" v-if="requestType === 'inscription'">
<!--
The condition below avoids an error occuring because loadRequests() finishes after the vue refresh
then submissionDate is undefined an it triggers an error in the console despite the fact that it is working
properly at the end.
-->
<div class="date" v-if="item.submissionDate !== undefined">{{item.submissionDate.slice(0, 10)}}</div>
<div class="state" style="font-size: 80%">Approval : {{item.state}}</div>
<div class="equivalencestate" style="font-size: 80%">Teacher approval : {{item.equivalenceState}}</div>
<div class="surname">{{item.lastName}}</div>
<div class="firstname">{{item.firstName}}</div>
<div class="accept" v-if="item.state === 'Pending'"><button @click="windowsState=2;targetId=item.id;" style="background-color:rgb(0,105,50);">{{i18n("request.accept")}}</button></div>
<div class="refuse" v-if="item.state === 'Pending'"><button @click="upPage(item.id,'Refused')" style="background-color:rgb(105,0,0);">{{i18n("request.refuse")}}</button></div>
<div class="infos"><button style="background-color:rgb(105,05,105);" @click="targetId=item.id;windowsState=1;">{{i18n("request.moreInfos")}}</button></div>
</div>
<div class="container" style="grid-template-columns:25% 15% 15% 25% 14.2%;grid-template-areas:'date reqState studentfirstname studentlastname infos';" v-if="requestType === 'scholarship'">
<div class="date" v-if="item.date !== undefined"> {{item.date.slice(0,10)}}</div>
<div class="studentfirstname">{{item.user.firstName}}</div>
<div class="studentlastname">{{item.user.lastName}}</div>
<div class="reqState">{{item.state}}</div>
<div class="infos"><button>More infos</button></div>
</div>
<div class="container" style="grid-template-columns:17% 15% 12% 15% 25%;grid-template-areas:'date reqState studentfirstname studentlastname course infos';"v-if="requestType === 'exemption'">
<div class="date" v-if="item.date != undefined">{{item.date.slice(0,10)}}</div>
<div class="studentfirstname">{{item.user.firstName}}</div>
<div class="studentlastname">{{item.user.lastName}}</div>
<div class="course">{{item.course.title}}</div>
<div class="reqState">{{item.state}}</div>
<div class="infos"><button>More infos</button></div>
</div>
</div>
</div>
</div>
<div style='display:flex; justify-content:center; min-width:1140px;margin-top: 10%' v-if="windowsState === 2">
<p>Etes vous sur de vouloir accepter cette demande ?</p>
<button style="background-color:rgb(105,05,105);" @click="upPage(targetId,'Accepted');windowsState=0;">Valider</button>
<button style="background-color:rgb(105,05,105);" @click="windowsState=0;">Retour</button>
</div>
</template>
<style scoped>
.container{
color:white;
height:100px;
font-size:20px;
display:grid;
column-gap:10px;
}
.equivalencestate{
grid-area: equivalencestate;
align-self: center;
}
.studentfirstname{
grid-area: studentfirstname;
align-self: center;
}
.studentlastname{
grid-area: studentlastname;
align-self: center;
}
.course{
grid-area: course;
align-self: center;
}
.reqState{
grid-area: reqState;
align-self: center;
}
.infos {
grid-area:infos;
align-self:center;
}
.accept{
grid-area:accept;
align-self:center;
}
.refuse{
grid-area:refuse;
align-self:center;
}
.date{
grid-area:date;
margin-left:40px;
align-self:center;
}
.state{
grid-area:state;
margin-left:40px;
align-self:center;
}
.surname{
grid-area:surname;
align-self:center;
white-space: nowrap;
overflow: hidden;
text-overflow:ellipsis;
}
.firstname{
grid-area:firstname;
align-self:center;
white-space: nowrap;
overflow: hidden;
text-overflow:ellipsis;
}
button{
font-size:15px;
height:50px;
width:100px;
border:none;
border-radius:20px;
}
.bodu {
margin-top:2%;
width:66%;
border:2px solid black;
border-radius:9px;
background-color:rgb(50,50,50);
}
</style>

View File

@ -1,16 +1,16 @@
<script setup>
import {reactive, ref } from 'vue'
import i18n from '@/i18n.js'
import {login, register, disconnect, isLogged} from '@/rest/Users.js'
import {getAllCurriculums, getcurriculum} from '@/rest/curriculum.js'
import { login , register , disconnect, isLogged} from '@/rest/Users.js'
import { getAllCurriculums } from '@/rest/curriculum.js'
import { uploadProfilePicture } from '@/rest/uploads.js'
import {toast} from 'vue3-toastify'
import 'vue3-toastify/dist/index.css';
import {createExternalCurriculum} from "@/rest/externalCurriculum.js";
const loginPage= ref(true)
const page = ref(0)
const outputs = reactive({
surname:null,
firstname:null,
@ -20,32 +20,13 @@
address:null,
country:null,
curriculum:null,
equivalenceState: "Unrequired"
})
const notcompletedCheck = ref(false);
const externalCurr = reactive({
inscriptionRequestId : null,
school:null,
formation :null,
completion : null,
startYear : null,
endYear: null,
justifdocUrl : null
})
//Stores some externalCurriculums in order to upload them all at the confirmation of the registration request
const externalCurrTab = ref([]);
const submitValue= ref(i18n("login.guest.submit"))
const passwordConfirm=ref("")
const imageSaved = ref(false)
let ppData = ""
//Contains the id of the newly created request (useful to link the student's formations informations to the request)
let requestId = ""
const ppData = ref(false)
const curricula= await getAllCurriculums();
@ -69,47 +50,16 @@
disconnect();
window.location.reload();}
async function uploadPP(arg){
const data = await uploadProfilePicture(arg);
ppData = data.url;
}
//This functions makes the distinction between a master cursus (year 4 or more) and a bachelor cursus (year 3 or less)
function getCursusDisplay(cursus){
if (cursus.year <= 3){
return "BAB " + cursus.year + " " + cursus.option;
}else{
return "MA" + (parseInt(cursus.year)-3).toString() + " " + cursus.option;
}
}
async function getCurriculumYear(curriculumId){
const curriculum = await getcurriculum(curriculumId);
return parseInt(curriculum.year);
}
//Post the register request and return the id of the newly created request and also post the external curriculum list in the database
async function postRegisterReq(){
const val = await register(outputs.firstname, outputs.surname, outputs.birthday, outputs.password, outputs.email, outputs.address, outputs.country, outputs.curriculum, ppData, null, new Date(), outputs.equivalenceState);
for (let item in externalCurrTab.value){
await createExternalCurriculum(val.id, externalCurrTab.value[item].school, externalCurrTab.value[item].formation, externalCurrTab.value[item].completion, externalCurrTab.value[item].startYear, externalCurrTab.value[item].endYear, externalCurrTab.value[item].justifdocUrl);
}
}
function deleteExtCursus(extcursus){
externalCurrTab.value.splice(externalCurrTab.value.indexOf(extcursus),1)
}
</script>
<template>
<div class="setup">
<div class='loginBox'>
<div v-if="loginPage">
<div class='loginBox' style="margin-top:30%;">
<form @submit.prevent="login(outputs.email,outputs.password);goBackHome();"class="form">
<form @submit.prevent=" login(outputs.email,outputs.password);goBackHome();"class="form">
<h1 style="color:rgb(239,60,168); font-family: sans-serif;">
{{i18n("login.guest.signin")}}
</h1>
@ -124,15 +74,14 @@
<div class="register">
<a @click="loginPage=!loginPage">{{i18n("login.guest.register")}}</a>
</div>
<div class="inputBox" style="margin-bottom:35px;">
<div class="inputBox">
<input type="submit" v-model="submitValue">
</div>
</form>
</div>
</div>
<div v-else>
<div class='loginBox' style="margin-top:30%; margin-bottom:50%;">
<form class="form">
<form class="form">
<h1 style="color:rgb(239,60,168); font-family: sans-serif; text-align:center;">
{{i18n("login.guest.welcome")}}
</h1>
@ -166,7 +115,7 @@
<a>{{i18n("login.guest.alregister")}}</a>
</div>
</div>
<div v-if="page === 1">
<div v-else>
<div class="inputBox">
<p>{{i18n("login.guest.email")}}</p>
<input type="mail" v-model="outputs.email">
@ -179,30 +128,20 @@
<p>{{i18n("login.guest.country")}}</p>
<input type="text" v-model="outputs.country">
</div>
<form class="inputBox" novalidate enctype="multipart/form-data">
<p>{{i18n("profile.picture").toUpperCase()}}</p>
</form>
<label class="browser">
Parcourir . . .
<input type="file" :disabled="imageSaved" @change="ppData = uploadProfilePicture($event.target.files); imageSaved = true;" accept="image/*">
</label>
<form novalidate enctype="multipart/form-data" class="inputBox">
<p>{{i18n("profile.picture").toUpperCase()}}</p>
<input type="file" @change="uploadPP($event.target.files); imageSaved = true;" accept="image/*">
<p>{{i18n("profile.picture").toUpperCase()}}</p>
<input type="file" :disabled="imageSaved" @change="ppData = uploadProfilePicture($event.target.files); imageSaved = true;" accept="image/*">
</form>
<div class="inputBox">
<p>{{i18n("Curriculum").toUpperCase()}}</p>
<select v-model="outputs.curriculum">
<option v-for="item in curricula" :value="item.curriculumId">{{getCursusDisplay(item)}}</option>
<option v-for="item in curricula">{{item.curriculumId}}</option>
</select>
</div>
<p style="color:rgb(239,60,168);">
Si vous êtes déja inscrits dans cette université veuillez vous connecter a votre compte et utilisez les fonctions
changer de cursus/réinscription sinon continuez ici.
</p>
<div style="align-self:center;" class="inputBox">
<button style="margin-top:25px;" @click="page++;">
{{i18n("login.guest.nextpage")}}
<button style="margin-top:25px;" @click="register(outputs.firstname, outputs.surname, outputs.birthday, outputs.password, outputs.email, outputs.address, outputs.country, outputs.curriculum, ppData);">
{{i18n("login.guest.submit")}}
</button>
</div>
<div class="switchpage">
@ -212,79 +151,27 @@
<a>{{i18n("login.guest.alregister")}}</a>
</div>
</div>
<div v-if="page === 2">
<form novalidate enctype="multipart/form-data" class="inputBox">
Carte d'identité :
</form>
<button @click="page++">{{i18n("login.guest.nextpage")}}</button>
</div>
<div v-if="page === 3">
<p>
Vous avez séléctionné un cursus qui possède des prérequis veuillez ajouter vos formations antérieures
dans l'enseignement supérieur, votre dossier sera vérifié par un membre du service d'inscription.
</p>
<button @click="page++">Ajouter une formation</button>
<button @click="postRegisterReq();">Envoyer la demande d'inscription</button>
</div>
<div v-if="page===4">
<form @submit.prevent=""class="form">
<div class="inputBox">
<p>Ecole</p>
<input type="text" v-model="externalCurr.school">
</div>
<div class="inputBox">
<p>Formation</p>
<input type="text" v-model="externalCurr.formation">
</div>
<div class="inputBox">
<p>Cochez la case si vous n'avez terminé cette formation</p>
<input v-model="notcompletedCheck" type="checkbox" id="checkboxformation">
<div v-if="notcompletedCheck">
<p>En quelle année de la formation vous êtes vous arrété (exemple: 3ème) ?</p>
<input type="text" v-model="externalCurr.completion">
</div>
</div>
<div class="inputBox">
<p>Année de début</p>
<input type="text" v-model="externalCurr.startYear">
</div>
<div class="inputBox">
<p>Année de fin</p>
<input type="text" v-model="externalCurr.endYear">
</div>
<div class="inputBox" style="margin-bottom:35px;">
<input type="submit" v-model="submitValue" @click="externalCurrTab.push({inscriptionReqId:null, school:externalCurr.school, formation:externalCurr.formation, completion:externalCurr.completion, startYear:externalCurr.startYear, endYear:externalCurr.endYear, justifdocUrl:externalCurr.justifdocUrl});console.log(externalCurrTab);page--;">
</div>
</form>
</div>
</form>
</div>
</div>
</div>
<div style="display:flex; justify-content:center; " v-for="item in externalCurrTab" v-if="page===3">
<div class="bodu">
<div class="container">
<div class="school"><a style="margin-left:30px;">{{item.school}}</a></div>
<div class="formation"><a>{{item.formation}}</a></div>
<div class="edit">
<button style="background-color:rgb(105,05,105);font-size:15px;height:50px;width:75%;border:none;border-radius:20px;" @click="externalCurr.school=item.school; externalCurr.completion=item.completion; externalCurr.formation=item.formation;externalCurr.endYear=item.endYear; externalCurr.startYear=item.startYear; externalCurr.justifdocUrl;page++;">Edit </button>
</div>
<div class="remove">
<button style="background-color:rgb(105,05,105);font-size:15px;height:50px;width:75%;border:none;border-radius:20px;" @click="deleteExtCursus(item)">Remove </button>
</div>
</div>
</div>
</div>
</template>
<style scoped>
.Home{
position:absolute;
display: flex;
z-index: 100;
padding: 8px 16px;
color:rgb(255, 255, 255);
text-decoration: none;
}
.setup {
margin-left: auto;
margin-right:auto;
min-width:400px;
width:25%;
height:50%;
.Home:hover{
width:40px;
background-color: black;
border-radius:6px;
color:white;
transform: translate(0px ,1px);
}
@ -293,7 +180,8 @@
width: 400px;
display:flex;
justify-content: center;
border-radius: 5%;
padding: 40px;
border-radius: 20px;
box-shadow:0 5px 25px #000000;
}
@ -302,8 +190,9 @@
width:100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items:center;
gap: 3%;
gap: 15px;
}
@ -311,12 +200,12 @@
width:100%;
border: none;
margin-right: 12.5%;
padding-left: 2.5%;
padding-top:2.5%;
padding-bottom:2.5%;
margin-right: 50px;
padding-left: 10px;
padding-top:10px;
padding-bottom:10px;
outline:none;
border-radius: 10px;
border-radius: 4px;
font-size:1.35em;
}
@ -325,28 +214,20 @@
z-index: 100;
font-family:sans-serif ;
color:rgb(239,60,168);
transition: 0.5;
transition:0.5;
}
.register{
color:rgb(239,60,168);
width:70%;
margin-bottom:20px;
margin-top:20px;
width: 100%;
display:flex;
cursor: pointer;
}
.bodu {
margin-top:2%;
width:50%;
border:2px solid black;
border-radius:9px;
background-color:rgb(50,50,50);
}
.switchpage{
width:100px;
background:rgb(255, 0 255);
border: none;
padding-right:0;
padding-top:10px;
@ -354,7 +235,7 @@
outline:none;
border-radius: 4px;
font-size:0.8em;
align-self: right;
align-self:right;
}
@ -369,37 +250,11 @@ input[type=submit],button,select{
}
input[type=file]{
display:none;
}
.browser{
display:inline-block;
cursor:pointer;
border-radius:20px;
background-color:rgb(239,60,168);
padding:5%;
font-size:1.35em;
font-family:sans-serif;
background:#FFFFFF;
}
.container{
margin-top: 2%;
color:white;
height:60px;
font-size:30px;
display:grid;
grid-template-columns:30% 30% 20% 20%;
grid-template-areas:
"school formation completion edit remove";
column-gap:10px;
}
button:active ,.switchpage:active{
opacity:0.8;
}
</style>

View File

@ -105,8 +105,7 @@
</button>
</div>
<div v-if="createMod">
<form class="listElement" style="width:40%;margin-right:auto;margin-left:auto;">
<form class="listElement">
<div style="margin-bottom:20px;">
{{i18n("name")}} :
<input v-model="toAdd.title">
@ -126,7 +125,7 @@
</form>
</div>
<div v-if="deleteMod">
<form class="listElement" style="width:40%;margin-right:auto;margin-left:auto;">
<form class="listElement">
<div style="margin-bottom:20px;">
{{i18n("courses.toDelete")}} :
<select style="max-width:200px;" class="teacher" v-model="toRemove">
@ -139,7 +138,7 @@
</form>
</div>
<div v-if="!createMod && !deleteMod" v-for="item in curriculum" :key="item.title" style="width:50%;margin-left:auto; margin-right:auto;">
<div v-if="!createMod && !deleteMod" v-for="item in curriculum" :key="item.title">
<div v-if="editElementID !== item.title" style ="padding:15px 15px 15px 15px;">
<button @click="editElementID = item.title; setModify(item); ">
{{i18n("courses.modify")}}
@ -149,8 +148,7 @@
<button @click="editElementID= '';patchCourse(item)"> {{i18n("courses.confirm")}} </button>
<button @click="editElementID= '';"> {{i18n("courses.back")}} </button>
</div>
<div class="listElement" >
<div class="listElement" >
<div class="containerElement" v-if="editElementID !== item.title" >
<div class="name"> {{item.title}} </div>
@ -174,27 +172,17 @@
<style scoped>
.body {
width:100%;
margin-top:3.5%;
margin-bottom:10px;
}
.infosContainer {
min-width:350px;
padding-bottom:50px;
border:2px solid black;
font-size:25px;
color:white;
padding:20px;
background-color:rgb(50,50,50);
border-radius:20px;
}
.containerElement{
justify-content:center;
justify-content:center;
display:grid;
grid-template-columns:38.8% 38.8% 22.4%;
grid-template-columns:350px 350px 200px;
grid-template-areas:
"name teacher credits";
column-gap:10px; }
column-gap:10px;
}
.name {
grid-area:name;
@ -212,7 +200,6 @@
}
.listElement{
min-width:625px;
border:2px solid black;
font-size:25px;
color:white;
@ -220,7 +207,6 @@
background-color:rgb(50,50,50);
border-radius:20px;
margin-bottom:10px;
}
.modify{
@ -269,11 +255,10 @@
}
.listTitle{
min-width:380px;
display: flex;
justify-content: center;
align-items: center;
width:25%;
width:400px;
margin-left:auto;
margin-right:auto;
border:2px solid black;
@ -281,8 +266,7 @@
color:white;
padding:20px;
background-color:rgb(50,50,50);
border-radius:20px;
margin-bottom:10px;
border-radius:20px;margin-bottom:10px;
button:hover{
opacity:0.8;

View File

@ -1,213 +0,0 @@
<!----------------------------------------------------
File: Msg.vue
Author: Anthony Debucquoy
Scope: Extension messagerie
Description: Main msg page
----------------------------------------------------->
<script setup>
import { ref, reactive } from 'vue'
import { discussionsList, currentDiscussion, fetchDiscussion, createDiscussion, sendMessage, updateDiscussionName, invite, removeMember} from '@/rest/msg.js'
const msgContent = ref("");
const addMember = ref(false);
const currentTitle = ref("");
function formatTime(date){
return date.getHours() + ":" + date.getMinutes() + " " + date.getDate() + "/" + date.getMonth();
}
</script>
<template>
<div id="msg">
<div id="discList">
<div @click="fetchDiscussion(discussion.id).then(e => currentTitle = currentDiscussion.name)" class="discItem" v-for="discussion in discussionsList" :key="discussion.id">{{ discussion.name }}</div>
<button id="createDiscussion" @click="createDiscussion('New Discussion')">+</button>
</div>
<div id="discussion" v-if="currentDiscussion.length != 0">
<h1 id=msgName ><input class="InputTitle" type="text" @change="updateDiscussionName(currentDiscussion.id, currentTitle)" v-model="currentTitle"></h1>
<div id=msgs>
<div class="msg" v-for="msg in currentDiscussion.msgs" :sender="msg.sender" :key="msg.id">
{{ msg.content }}<br/>
<span class="sender"><span v-if="!msg.sender">{{ msg.author.firstName }} {{ msg.author.lastName.toUpperCase() }}</span> {{formatTime(new Date(msg.created))}}</span>
</div>
</div>
<div id=messageBox>
<input type="text" @keyup.enter="sendMessage(currentDiscussion.id, msgContent, null); msgContent = ''" v-model="msgContent">
<input type="submit" @click="sendMessage(currentDiscussion.id, msgContent, null); msgContent = ''" value="send">
</div>
</div>
<div id="members" v-if="currentDiscussion.length != 0">
<div class="memberItem" v-for="member in currentDiscussion.members" @click="removeMember(currentDiscussion.id, member.regNo)" :key="member.id"><span>{{ member.firstName }} {{ member.lastName.toUpperCase() }}</span></div>
<input type=text id="addMembers" @focus="addMember = true" @blur="addMember = false;$event.target.value = ''" @change="invite(currentDiscussion.id, $event.target.value)" :placeholder="addMember ? 'Regno' : '+'"/>
</div>
</div>
</template>
<style scoped>
div#msg{
position: relative;
width: 100%;
height: 100%;
display: grid;
grid-template-columns: 20% auto 10%;
}
div#discList{
margin: 30px 0 30px 30px;
background-color: rgba(255, 255, 255, 0.05);
border-radius: 10px;
overflow: hidden;
padding: 10px;
display: flex;
flex-direction: column;
}
div#members{
margin: 30px 0;
border-radius: 10px 0 0 10px;
background-color: red;
background-color: rgba(255, 255, 255, 0.05);
overflow: hidden;
display: flex;
padding: 10px 0 0 10px;
flex-direction: column;
}
.InputTitle{
all: inherit;
margin: auto;
}
.discItem{
color: darkorange;
display: flex;
font-family: sans-serif;
font-weight: bold;
height: 4vh;
margin: 5px;
border-radius: 0 30px 30px 0;
align-items: center;
justify-content: center;
border: 1px solid darkorange;
}
.memberItem{
color: darkorange;
display: flex;
font-family: sans-serif;
font-weight: bold;
height: 4vh;
margin: 5px;
border-radius: 30px 0 0 30px;
align-items: center;
justify-content: center;
border: 1px solid darkorange;
}
.memberItem:hover span{
display: none;
}
.memberItem:hover{
background-color: red;
}
.memberItem:hover:before{
color: white;
content: "X"
}
#createDiscussion{
height: 4vh;
margin: 5px;
color: white;
background-color: green;
border-radius: 0 30px 30px 0;
border: none;
font-weight: 900;
font-size: 2em;
}
#addMembers{
height: 4vh;
margin: 5px;
text-align: center;
color: white;
background-color: green;
border-radius: 30px 0 0 30px;
border: none;
font-weight: 900;
font-size: 2em;
}
div#discussion{
display: flex;
flex-direction: column;
margin: 30px;
background-color: rgba(255, 255, 255, 0.05);
border-radius: 10px;
overflow: hidden;
}
#msgName{
text-align: center;
display: block;
background-color: #2a1981;
border-radius: 5px;
color: white;
width: 75%;
margin: 30px auto;
}
.discItem:hover{
background-color: gray;
}
#msgs{
display: flex;
flex-grow: 1;
flex-direction: column;
}
.msg {
background-color: aliceblue;
font-family: sans-serif;
margin: 10px;
padding: 5px;
border-radius: 3px;
max-width: 50%;
align-self: start;
}
.sender{
display: inline-block;
color: gray;
font-size: 0.5em;
}
.msg[sender=true]{
background-color: darkorange;
align-self: end;
}
#messageBox{
width: 100%;
height: 30px;
background-color: white;
display: flex;
}
#messageBox input[type="text"]{
all: inherit;
padding: 0 10px;
}
#messageBox input[type="submit"]{
border: inherit;
padding: 0 10px;
}
</style>

View File

@ -1,22 +1,16 @@
<script setup>
import {reactive, ref } from 'vue'
import {getSelf,alterSelf,disconnect,deleteUser} from '../rest/Users.js'
import {getSelfCurriculum, getAllCurriculums, getSomeonesCurriculumList} from '../rest/curriculum.js'
import {getSelfCurriculum, getAllCurriculums} from '../rest/curriculum.js'
import {getCourses} from "../rest/courses.js"
import i18n from "@/i18n.js"
import {uploadFile, uploadProfilePicture} from '@/rest/uploads.js'
import CourseList from "@/Apps/Inscription/CourseList.vue";
import {editMinerval, getCurrentMinerval} from "@/rest/minerval.js";
import {postPayment} from "@/rest/payment.js";
import {addUninscReq, createScholarshipRequest} from "@/rest/requests.js";
import { uploadProfilePicture } from '@/rest/uploads.js'
const user = ref(await getSelf());
const UserCurriculum = ref("");
const curricula = ref (await getAllCurriculums());
const minerv = ref({});
if(user.value.role === "Student"){
minerv.value = ref(await getCurrentMinerval(user.value.regNo));
UserCurriculum.value = await getSomeonesCurriculumList(user.value.regNo);
UserCurriculum.value = await getSelfCurriculum();
}
if(user.role === "Teacher"){
@ -25,13 +19,6 @@
const modif = ref(false);
const curric = ref(false);
const reg = ref(false);
const courseslist = ref(false);
const minerval = ref(false);
const paymentPage = ref(false);
const scholarship = ref(false);
const scholarshipinfos = ref(false);
const uninscr = ref(false);
const sure = ref(0);
const pattern = {
profilPictureUrl:null,
@ -47,32 +34,7 @@
id:null,
}
//Used to modelize a payment
const paymentData={
studentRegNo: user.value.regNo,
date:null,
card:null,
client:null,
expDate:null,
amount: null
}
//Used to modelize a scholarship request
const scholarshipData=reactive({
userId: user.value.regNo,
state:null,
date:null,
amount:0,
taxDocUrl : "",
residencyDocUrl : ""
})
//Used to post a uninscription request
const uninscriptionData = reactive({
reason : null,
userId : user.value.regNo
})
const paymentAmount = ref(0);
let toModify= Object.assign({}, pattern);
let personnalInfos = Object.assign({}, patternInfos);
@ -124,47 +86,17 @@
}
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
}
async function postScholarshipRequest(file1, type1, file2, type2){
const a = await uploadFile(file1, type1)
scholarshipData.taxDocUrl = a.url;
const b = await uploadFile(file2, type2)
scholarshipData.residencyDocUrl = b.url;
scholarshipData.date = Date.now();
await createScholarshipRequest(scholarshipData)
}
</script>
<template>
<div class="body">
<div class="container" v-if="courseslist == false">
<div class="container">
<div class="profilPic">
<img class="subContainter" :src=getPP()>
</div>
<div class="globalInfos">
<div v-if="modif==false && curric==false && reg==false && minerval==false && paymentPage == false && scholarship==false && uninscr == false" class="infosContainer">
<div v-if="modif==false && curric==false && reg==false " class="infosContainer" >
<div>
{{user.firstName}} {{user.lastName}}
</div>
@ -182,87 +114,11 @@
</div>
<div v-if="(user.role==='Student')">
<button @click="reg=!reg">{{i18n("profile.reRegister")}}</button>
<button @click="uninscr = !uninscr" style="float:right;background-color:rgb(150,0,0);">{{i18n("profile.unRegister")}}</button>
<button @click="unRegister()" style="float:right;background-color:rgb(150,0,0);">{{i18n("profile.unRegister")}}</button>
</div>
<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>
<button @click="minerval = !minerval" style="margin-left: 2%">Manage minerval</button>
</div>
</div>
<div v-else-if="uninscr" class="infosContainer">
<div v-if="sure != 2">Please enter the reason you leave the university</div>
<textarea v-if="sure != 2" v-model="uninscriptionData.reason"></textarea>
<div v-if="sure != 2">
<button @click="sure++">Submit</button>
</div>
<div v-if="sure==1">
Are you sure that you want to unregister ?
<button @click="addUninscReq(uninscriptionData.userId, uninscriptionData.reason);sure++">Yes</button>
<button @click="sure=0">No</button>
</div>
<p v-if="sure==2">You request has been send !</p>
</div>
<div v-else-if="minerval" class="infosContainer">
<div v-if="minerv.value.toPay != 0">
Payment : {{minerv.value.toPay}} left to pay
<div v-if="minerv.value.paidAmount <= 50">
<button @click="minerval = !minerval; paymentPage = !paymentPage; paymentAmount = 50">Pay deposit (50)</button>
</div>
<div>
<button @click="minerval = !minerval; paymentPage = !paymentPage; paymentAmount = minerv.value.toPay">Pay all the rest ({{minerv.value.toPay}})</button>
</div>
</div>
<div v-else>
Payment : School fees have already been paid this year
</div>
<div>
<button @click="scholarship=!scholarship; minerval=!minerval">Ask for a scholarship</button>
</div>
</div>
<div v-else-if="scholarship && !scholarshipinfos" class="infosContainer">
<p>Please upload the required documents</p>
<div>
Tax justification document :
<input type="file" @change="scholarshipData.taxDocUrl = $event.target.files">
</div>
<div>
Residency justification document :
<input type="file" style="margin-top:2%" @change="scholarshipData.residencyDocUrl = $event.target.files">
</div>
<button style="margin-top: 5%" @click="scholarshipinfos = !scholarshipinfos;postScholarshipRequest(scholarshipData.taxDocUrl, 'JustificationDocument',scholarshipData.residencyDocUrl, 'JustificationDocument');">Submit scholarship request</button>
</div>
<div v-else-if="scholarship && scholarshipinfos" class="infosContainer">
<div>
Your request has been sent to the inscription service you will get notified when
the request is reviewed.
</div>
<button @click="scholarshipinfos=!scholarshipinfos; scholarship=!scholarship">
Go back to profile
</button>
</div>
<div v-else-if="paymentPage" class="infosContainer">
Proceed to payment of {{paymentAmount}}
<div style="margin-top: 1%">
Client:
<input type="text" v-model="paymentData.client">
</div>
<div style="margin-top: 1%">
Card:
<input type="text" v-model="paymentData.card">
</div>
<div style="margin-top: 1%">
ExpDate:
<input type="date" v-model="paymentData.expDate">
</div>
<div style="margin-top: 1%">
<button @click="paymentPage=!paymentPage;minerval=!minerval;paymentData.amount=paymentAmount;paymentData.date=new Date();postPayment(paymentData);minerv.value.toPay -= paymentAmount; minerv.value.paidAmount += paymentAmount; editMinerval(minerv.value)">Process Payment</button>
</div>
<div>
<button @click="minerval = !minerval; paymentPage = !paymentPage;">Back</button>
</div>
</div>
<div v-else-if="modif" class="infosContainer">
<div>
@ -326,48 +182,39 @@
<button @click=" reg=!reg; resetInputs(personnalInfos,patternInfos);" style="float:right;">{{i18n("courses.back")}}</button>
</div>
</div>
</div>
<div v-if="user.role == 'Student' && modif==false && curric==false && reg==false && minerval==false && scholarship == false && uninscr == false" class="moreInfos">
<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 v-if="modif==false && curric==false && reg==false "class="moreInfos">
<div v-if="(user.role ==='Student')">
<div class="listTitle">
{{i18n("profile.course.list")}}
</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 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>
</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>
.container{
min-width:675px;
display:grid;
grid-template-columns:10vw 50vw;
grid-template-columns:200px 900px;
grid-template-rows:200px auto;
column-gap:2.7%;
column-gap:30px;
row-gap:45px;
grid-template-areas:
"profilPic globalInfos"
@ -375,7 +222,6 @@
}
.profilPic{
width:100%;
grid-area:profilPic;
}
@ -393,52 +239,22 @@
}
.moreInfos {
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;
grid-area:minfos;
}
.body {
min-width:960px;
width:100%;
display:flex;
align-items:center;
justify-content:center;
margin-top:7%;
margin-bottom:10px;
}
.containerElement{
.containerElement{
justify-content:center;
display:grid;
grid-template-columns:100px 100px 300px;
grid-template-areas:
"year option dateyear";
column-gap:40px;
padding-left: 25px;
display:grid;
grid-template-columns:350px 350px 200px;
grid-template-areas:
"name teacher credits";
column-gap:10px;
}
.name {
grid-area:name;
align-self:center;
@ -454,6 +270,20 @@
align-self:center;
}
.listTitle{
display: flex;
justify-content: center;
align-items: center;
width:200px;
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;
@ -466,7 +296,6 @@
}
.infosContainer {
min-width:350px;
padding-bottom:50px;
border:2px solid black;
font-size:25px;

View File

@ -1,158 +0,0 @@
<!----------------------------------------------------
File: ResearchComponent.vue
Author: Maxime Bartha
Scope: Extension Publicatons scientifiquess
Description: Pop Up for selecting search Filters
----------------------------------------------------->
<script setup>
import { ref } from "vue";
import {onClickOutside} from '@vueuse/core'
import {w} from "../../../dist/assets/_plugin-vue_export-helper-Bvj9NrzX.js";
let checked = ref([])
const yearList = ref([])
const monthList = ref([])
const accessList = ref([])
const languageList = ref([])
const domainList = ref([])
const paperTypeList = ref([])
const props = defineProps({
isOpen: Boolean,
allArticles: ref([Object])
});
for (let i=0;i< props.allArticles.length;i++) {
let r = props.allArticles[i];
let year = r.releaseDate.split("-")[0]
let month = r.releaseDate.split("-")[1]
if (!yearList.value.includes(year)) yearList.value.push(year);
if (!monthList.value.includes(month)) monthList.value.push(month);
if (!accessList.value.includes(r.access)) accessList.value.push(r.access);
if (!languageList.value.includes(r.language)) languageList.value.push(r.language);
if (!domainList.value.includes(r.domain)) domainList.value.push(r.domain);
if (!paperTypeList.value.includes(r.paperType)) paperTypeList.value.push(r.paperType);
}
function monthToString(month){
switch (month){
case "01":
return "january"
case "02":
return "february"
case "03":
return "march"
case "04":
return "april"
case "05":
return "may"
case "06":
return "june"
case "07":
return "july"
case "08":
return "august"
case "09":
return "september"
case "10":
return "november"
case "11":
return "october"
case "12":
return "december"
default:
return "unknown"
}
}
const emit = defineEmits(["modal-close"]);
const target = ref(null)
onClickOutside(target, ()=>emit('modal-close'))
</script>
<template>
<div v-if="isOpen" class="modal-mask">
<div class="modal-wrapper">
<div class="modal-container" ref="target">
<div id="filterGrid">
<div> Year :<ul class="checkers"> <li v-for="n in yearList"> <input type="checkbox" :value=n v-model="checked"> {{n}} </li> </ul> </div>
<div class="vl"> Access :<ul class="checkers"> <li v-for="n in accessList"> <input type="checkbox" :value=n v-model="checked"> {{n}} </li> </ul> </div>
<div class="vl"> Language :<ul class="checkers"> <li v-for="n in languageList"> <input type="checkbox" :value=n v-model="checked"> {{n}} </li> </ul> </div>
<div> Month :<ul class="checkers"> <li v-for="n in monthList"> <input type="checkbox" :value=n v-model="checked"> {{monthToString(n)}} </li> </ul> </div>
<div class="vl"> Domain :<ul class="checkers"> <li v-for="n in domainList"> <input type="checkbox" :value=n v-model="checked"> {{n}} </li> </ul> </div>
<div class="vl"> PaperType :<ul class="checkers"> <li v-for="n in paperTypeList"> <input type="checkbox" :value=n v-model="checked"> {{n}} </li> </ul> </div>
</div>
<div id="submit">
<button @click.stop="emit('modal-close', 'submit')">Submit</button>
</div>
</div>
</div>
</div>
</template>
<style scoped>
.modal-mask {
position: fixed;
z-index: 9998;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
}
.modal-container {
width: 70%;
margin: 150px auto;
padding: 20px 30px;
background: rgba(157, 99, 205);
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.33);
}
#filterGrid {
display: grid;
grid-template-columns: auto auto auto;
column-gap: 5px;
grid-template-rows: auto auto;
}
#filterGrid ul {
list-style-type: none;
padding: 15px;
height: 100px;
overflow: scroll;
scrollbar-color: #8a2be2 rgb(255,255,255,0.04);
background-color: rgba(255, 255, 255, 0.09);
border-radius: 6px;
}
.vl {
border-left: 6px solid #8a2be2;
}
#submit {
text-align: end;
}
#submit button {
margin-left: 2px;
font-size: large;
color: white;
background: rgba(191, 64, 191,0.5);
border:2px solid black;
border-radius: 5px;
}
#submit button:hover{
background: rgba(191, 64, 191);
}
</style>

View File

@ -1,292 +0,0 @@
<script setup>
import { ref, reactive } from "vue";
import FilterComponent from "@/Apps/ScientificPublications/FilterComponent.vue";
import ArticleComponent from "@/Apps/ScientificPublications/ResearchComponent.vue";
import {fetchResearches, } from "@/rest/ScientificPublications/ResearcherProfile.js";
import {getSelf, patchProfile} from "@/rest/ScientificPublications/ManageResearcherProfile.js";
import {c, f} from "../../../dist/assets/_plugin-vue_export-helper-Bvj9NrzX.js";
import ResearchPostComponent from "@/Apps/ScientificPublications/ResearchPostComponent.vue";
const input = ref("");
const isFilterOpened = ref(false);
const isResearchOpened = ref(false);
const isPostResearchOpened = ref(false);
const articleToDisplay = ref()
const filters = ref([]);
const changing = ref(false);
let toModify= Object.assign({}, {});
const researcher = ref(await getSelf());
const researchList = ref(await fetchResearches(researcher.value.id));
const props = defineProps({
filters: ref([]),
});
const openFilter = () => {
isFilterOpened.value = true;
};
const closeFilter = () => {
isFilterOpened.value = false;
};
const submitFilters = ()=>{
}
const openResearch = (article) => {
isResearchOpened.value = true;
articleToDisplay.value = article;
}
const closeResearch = () => {
isResearchOpened.value =false;
articleToDisplay.value = null;
}
function openPostResearch(){
isPostResearchOpened.value = true
}
function searchInList(list, searchInput) {
let retList = []
for (let i = 0; i < list.length; i++) {
if (lDistance(list[i].title, searchInput) < 10 || list[i].title.toUpperCase().indexOf(searchInput.toUpperCase()) > -1){
retList.push(list[i])
}
}
return retList
}
function lDistance(s,t){
if (!s.length) return t.length;
if (!t.length) return s.length;
const arr = [];
for (let i = 0; i <= t.length; i++) {
arr[i] = [i];
for (let j = 1; j <= s.length; j++) {
arr[i][j] =
i === 0
? j
: Math.min(
arr[i - 1][j] + 1,
arr[i][j - 1] + 1,
arr[i - 1][j - 1] + (s[j - 1] === t[i - 1] ? 0 : 1)
);
}
}
return arr[t.length][s.length];
}
function cancelChanges(){
changing.value = false
toModify= Object.assign({}, {});
}
function confirmChanges(){
patchProfile(researcher.value.id, toModify)
changing.value = false
toModify= Object.assign({}, {});
}
</script>
<template> <div class="body"><div id="main">
<FilterComponent :isOpen="isFilterOpened" :allArticles="researchList" @modal-close="closeFilter" @submit="submitFilters()"></FilterComponent>
<ArticleComponent :article="articleToDisplay" :isOpen="isResearchOpened" :manage=true @modal-close="closeResearch"></ArticleComponent>
<ResearchPostComponent :researcher="researcher" :isOpen="isPostResearchOpened"></ResearchPostComponent>
<div id="profilePicture">
<img src="/Clyde.png" />
</div>
<div id="researcherInfos">
<div class="surrounded" v-if="!changing">{{researcher.user.lastName}} {{researcher.user.firstName}}</div>
<div class="surrounded" v-else> To Be changed in manage (simple) Profile</div>
<div class="surrounded" v-if="!changing">Orcid : {{researcher.orcidId}}</div>
<div class="surrounded" v-else>Orcid : <input v-model="toModify.orcidId"> </input></div>
<div class="surrounded" v-if="!changing">Email : {{researcher.user.email}}</div>
<div class="surrounded" v-else> To Be changed in manage (simple) Profile</div>
<div class="surrounded" v-if="!changing">
site : <a :href=researcher.site style="color: #007aff"> {{researcher.site}}</a>
</div>
<div class="surrounded" v-else>Site : <input v-model="toModify.site"></input></div>
<div class="surrounded" v-if="!changing">Domain : {{researcher.domain}}</div>
<div class="surrounded" v-else>Domain : <input v-model="toModify.domain"> </input></div>
<div style="text-align: center; align-self: center" v-if="!changing"> <button class="modifyButton" @click="changing = !changing">Modify Data</button></div>
<div v-else style="text-align: center; align-self: center">
<button id="confirmButton" @click="confirmChanges">Confirm Changes</button>
<button id="cancelButton" @click="cancelChanges">Cancel Changes</button>
</div>
</div>
<div class="postArticle" style="text-align: center">
<button class="modifyButton" @click="post">Post a Research</button>
</div>
<div id="researches">
<div id="search">
<input type="text" id="search-input" placeholder="search for researches" v-model="input"/>
<button id="filterButton" @click="openFilter"> Filters </button>
</div>
<ul id="researchUL">
<li id="researchLi" v-for="n in searchInList(researchList,input)">
<div class="vl"> {{n.title}}</div>
<div class="vl"> {{ n.researcher.user.firstName +" "+ n.researcher.user.lastName }}</div>
<a @click="openResearch(n)"> Modify Research</a></li>
</ul>
</div>
</div>
</div>
</template>
<style scoped>
#main {
display: grid;
grid-template-columns: 22% auto;
grid-template-rows: 26% auto;
height: 100%;
width: 100%;
}
#profilePicture {
display: flex;
justify-content: center;
}
#profilePicture img {
align-self: center;
justify-self: center;
width: 60%;
}
#researcherInfos {
display: grid;
grid-template-columns: auto auto auto;
column-gap: 5px;
grid-template-rows: auto auto;
}
.surrounded {
border: 2px solid black;
color: white;
font-size: x-large;
align-self: center;
text-align: center;
background-color: rgba(255, 255, 255, 0.09);
border-radius: 20px;
margin-bottom: 10px;
}
.surrounded select {
margin-top: 2px;
margin-bottom: 2px;
border: 1px solid black;
color: white;
background-color: rgb(255, 255, 255, 0.1);
font-size: large;
}
.modifyButton{
align-self: center;
text-align: center;
border: 2px solid black;
color: white;
font-size: xx-large;
background-color:rgba(191, 64, 191,0.5);
border-radius: 20px;
}
.modifyButton:hover{
background:rgba(191,64,191)
}
#cancelButton{
align-self: center;
text-align: center;
border: 2px solid black;
color: white;
font-size: x-large;
background-color: red;
border-radius: 20px;
}
#cancelButton:hover{
background: #ff2d55;
}
#confirmButton{
align-self: center;
text-align: center;
border: 2px solid black;
color: white;
font-size: x-large;
background-color: #07bc0c;
border-radius: 20px;
}
#confirmButton:hover{
background: #4cd964;
}
#search{
width: 100%;
height: 10%;
display: inline-flex;
}
#search-input {
margin-left: 25px;
width: 75%;
font-size: 16px;
padding: 12px 20px 12px 40px;
border: 1px solid #ddd;
height: 20px;
align-self: center;
}
#filterButton {
align-self: center;
margin-left: 2px;
font-size: xx-large;
color: white;
background: rgba(191, 64, 191,0.5);
border:2px solid black;
}
#filterButton:hover{
background: rgba(191, 64, 191);
}
#researchUL {
list-style-type: none;
color: white;
padding: 12px;
margin: 5px;
height: 400px;
overflow: scroll;
}
#researchLi{
display: grid;
grid-template-columns: auto auto auto;
border: 2px solid black;
color: white;
font-size: x-large;
text-align: center;
text-indent: 7px;
background-color: rgba(255, 255, 255, 0.09);
border-radius: 18px;
margin-bottom: 15px;
}
a{
color:#007aff;
text-decoration: underline;
cursor: pointer;
}
.vl {
border-right: 2px solid black;
}
</style>

View File

@ -1,179 +0,0 @@
<!----------------------------------------------------
File: ResearchComponent.vue
Author: Maxime Bartha
Scope: Extension Publicatons scientifiquess
Description: Pop Up summarizing
----------------------------------------------------->
<script setup xmlns="http://www.w3.org/1999/html">
import {ref } from "vue";
import {onClickOutside} from '@vueuse/core'
import {patchArticle, deleteArticle} from "@/rest/ScientificPublications/ManageResearch.js";
const props = defineProps({
isOpen: Boolean,
article: ref(Object),
manage:Boolean,
});
function format(date){
let split = date.split("-")
let month = split[1]
let day = split[2].split("T")[0]
let year = split[0]
return day +"/"+ month +"/"+ year
}
const emit = defineEmits(["modal-close","downloadPdf","downloadBibTex"]);
const target = ref(null)
onClickOutside(target, ()=>emit('modal-close'))
let toModify= Object.assign({}, {});
function cancelChanges(){
toModify= Object.assign({}, {});
emit('modal-close')
}
function confirmChanges(){
patchArticle(props.article.id, toModify)
toModify= Object.assign({}, {});
emit('modal-close')
}
function deleteThisArticle(){
deleteArticle(props.article.id)
emit('modal-close')
}
</script>
<template>
<div v-if="isOpen" class="modal-mask">
<div class="modal-wrapper">
<div class="modal-container" ref="target">
<div ><ul>
<li>Article Id : {{article.id}}</li>
<li>Title : {{article.title}}</li>
<li>Author : {{article.researcher.user.lastName + " " + article.researcher.user.firstName}}</li>
<li>Summary : {{article.summary}}</li>
<li>ReleaseDate: {{format(article.releaseDate)}}</li>
<li>Language : {{article.language}}</li>
<li>PaperType : {{article.paperType}}</li>
<li>Domain : {{article.domain}}</li>
<li>Views : {{article.views}}</li>
<li>Access : {{article.access}}</li>
</ul>
<div id="downloads" v-if="article.pdfLocation !== null">
<button @click.stop="emit('downloadBibTex')">Download BibTex</button>
<button @click.stop="emit('downloadPdf')">Download Research</button>
</div>
</div>
<div v-if="manage">
<div>
<ul>
<li>Title : <input v-model="toModify.title"></li>
<li>Language : <input v-model="toModify.language"></li>
<li>Summary : <input v-model="toModify.summary"></li>
<li>Domain : <input v-model="toModify.domain"></li>
<li>Access :
<select @change="update()" id="classed-select" v-model="toModify.access">
<option value="OpenSource">OpenSource</option>
<option value="Restricted">Restricted</option>
<option value="Private">Private</option>
</select></li>
</ul>
</div>
<button id="confirmButton" @click="confirmChanges">Confirm Changes</button>
<button id="cancelButton" @click="cancelChanges">Cancel Changes</button>
<button id="deleteButton" @click="deleteThisArticle">Delete Research </button>
</div>
</div>
</div>
</div>
</template>
<style scoped>
.modal-mask {
position: fixed;
z-index: 9998;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
}
.modal-container {
width: 70%;
margin: 150px auto;
padding: 20px 30px;
background: rgba(157, 99, 205);
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.33);
}
.modal-container ul{
margin-top: 9px;
}
#downloads {
text-align: end;
}
#downloads button {
align-self: center;
margin-left: 2px;
font-size: large;
color: white;
background: rgba(191, 64, 191,0.5);
border:2px solid black;
border-radius: 5px;
}
#downloads button:hover{
background: rgba(191, 64, 191);
}
#deleteButton{
margin-left: 80%;
align-self: center;
text-align: center;
border: 2px solid black;
color: white;
font-size: large;
border-radius: 20px;
background-color: red;
}
#deleteButton:hover{
background: #ff2d55;
}
#cancelButton{
align-self: center;
text-align: center;
border: 2px solid black;
color: white;
font-size: x-large;
background-color:rgba(191, 64, 191,0.5);
border-radius: 20px;
}
#cancelButton:hover{
background:rgba(191,64,191)
}
#confirmButton{
align-self: center;
text-align: center;
border: 2px solid black;
color: white;
font-size: x-large;
background-color: #07bc0c;
border-radius: 20px;
}
#confirmButton:hover{
background: #4cd964;
}
</style>

View File

@ -1,11 +0,0 @@
<script setup>
</script>
<template>
</template>
<style scoped>
</style>

View File

@ -1,293 +0,0 @@
<!----------------------------------------------------
File: ResearcherProfile.vue
Author: Maxime Bartha
Scope: Extension Publicatons scientifiquess
Description: Researcher Profile Page containing his articles and his statistics
----------------------------------------------------->
<script setup>
import { ref, reactive } from "vue";
import FilterComponent from "@/Apps/ScientificPublications/FilterComponent.vue";
import ArticleComponent from "@/Apps/ScientificPublications/ResearchComponent.vue";
import {fetchResearcher, fetchResearches, fetchStats, addView, getFile} from "@/rest/ScientificPublications/ResearcherProfile.js";
const input = ref("");
const statsOf = ref("");
const statsBy = ref("");
const isFilterOpened = ref(false);
const isResearchOpened = ref(false);
const articleToDisplay = ref(Object)
const filters = ref([]);
let chart;
const researchList = ref(await fetchResearches(1));
//todo changer dynamiquement le 1 ici en fct de sur quel profil on est
const researcher = ref(await fetchResearcher(1));
const stats = ref(await fetchStats(1))
const props = defineProps({
researcherId: ref(), //int
filters: ref([""]),
});
const openFilter = () => {
isFilterOpened.value = true;
};
const closeFilter = () => {
isFilterOpened.value = false;
};
const submitFilters = ()=>{
}
const openResearch = (article) => {
isResearchOpened.value = true;
articleToDisplay.value = article;
}
const closeResearch = () => {
isResearchOpened.value =false;
articleToDisplay.value = null;
}
const downloadBibTex = (research) => {
getFile(research.bibTexLocation)
}
const downloadArticle = (research) => {
addView(research.pdfLocation)
getFile(research.pdfLocation)
}
function downloadCoAuthors(){
const data = JSON.stringify(researcher.value);
const blob = new Blob([data], {type:"application/json"});
return URL.createObjectURL(blob);
}
function searchInList(list, searchInput) {
let retList = []
for (let i = 0; i < list.length; i++) {
if (lDistance(list[i].title, searchInput) < 10 || list[i].title.toUpperCase().indexOf(searchInput.toUpperCase()) > -1){
retList.push(list[i])
}
}
return retList
}
function lDistance(s,t){
if (!s.length) return t.length;
if (!t.length) return s.length;
const arr = [];
for (let i = 0; i <= t.length; i++) {
arr[i] = [i];
for (let j = 1; j <= s.length; j++) {
arr[i][j] =
i === 0
? j
: Math.min(
arr[i - 1][j] + 1,
arr[i][j - 1] + 1,
arr[i - 1][j - 1] + (s[j - 1] === t[i - 1] ? 0 : 1)
);
}
}
return arr[t.length][s.length];
}
const options = reactive({
backgroundColor:null,
theme: "light2",
animationEnabled: true,
title: {
fontColor: "white",
text : "please select options",
},
data: [
{
type: "pie",
indexLabel: "{label} (#percent%)",
yValueFormatString: "#,##0",
indexLabelFontColor: "white",
toolTipContent:
"<span style='\"'color: {color};'\"'>{label}</span> {y}(#percent%)",
}]
});
function update(){
options.title = {
fontColor: "white",
text: statsOf.value + " By "+ statsBy.value,
}
let index = (statsOf.value === "views"?0:(statsOf.value === "researches"?3:6)) + (statsBy.value ==="years"?0:(statsBy.value==="months"?1:2))
if (statsOf.value !== "" && statsBy.value !== "")
options.data[0].dataPoints = stats.value[index]
options.title.text = statsOf.value + " By "+ statsBy.value;
chart.render();
}
</script>
<template>
<div id="main">
<FilterComponent :isOpen="isFilterOpened" :allArticles="researchList" @modal-close="closeFilter" @submit="submitFilters()"></FilterComponent>
<ArticleComponent :article="articleToDisplay" :isOpen="isResearchOpened" @modal-close="closeResearch" @downloadPdf="downloadArticle(articleToDisplay)" @downloadBibTex="downloadBibTex(articleToDisplay)"></ArticleComponent>
<div id="profilePicture">
<img src="/Clyde.png" />
</div>
<div id="researcherInfos">
<div class="surrounded">{{researcher.user.lastName}} {{researcher.user.firstName}}</div>
<div class="surrounded">Orcid : {{researcher.orcidId}}</div>
<div class="surrounded">Email : {{researcher.user.email}}</div>
<div class="surrounded">
site : <a :href=researcher.site style="color: #007aff"> {{researcher.site}}</a>
</div>
<div class="surrounded">Domain : {{researcher.domain}}</div>
<div id="coAuthorList" class="surrounded">Co-authors list : <a :href=downloadCoAuthors() download="coAuthors.json"> here </a></div>
</div>
<div id="stats">
<div class="surrounded">
Stat type :
<select @change="update()" id="stats-select" v-model="statsOf">
<option value="views">Views</option>
<option value="researches">Researches</option>
<option value="languages">Languages</option>
</select>
</div>
<div class="surrounded">
Class by:
<select @change="update()" id="classed-select" v-model="statsBy">
<option value="years">Years</option>
<option value="months">Months</option>
<option value="topics">Topics</option>
</select>
</div>
<div id="statsPie">
<CanvasJSChart :options="options" id=chart @chart-ref="c => chart = c "/>
</div>
</div>
<div id="researches">
<div id="search">
<input type="text" id="search-input" placeholder="search for researches" v-model="input"/>
<button id="filterButton" @click="openFilter"> Filters </button>
</div>
<ul id="researchUL">
<li id="researchLi" v-for="n in searchInList(researchList,input)">
<div class="vl"> {{n.title}}</div>
<div class="vl"> {{ n.researcher.user.firstName +" "+ n.researcher.user.lastName }}</div>
<a @click="openResearch(n)"> MoreInfo </a></li>
</ul>
</div>
</div>
</template>
<style scoped>
#main {
display: grid;
grid-template-columns: 22% auto;
grid-template-rows: 26% auto;
height: 100%;
width: 100%;
}
#profilePicture {
display: flex;
justify-content: center;
}
#profilePicture img {
align-self: center;
justify-self: center;
width: 60%;
}
#researcherInfos {
display: grid;
grid-template-columns: auto auto auto;
column-gap: 5px;
grid-template-rows: auto auto;
}
.surrounded {
border: 2px solid black;
color: white;
font-size: x-large;
align-self: center;
text-align: center;
background-color: rgba(255, 255, 255, 0.09);
border-radius: 20px;
margin-bottom: 10px;
}
.surrounded select {
margin-top: 2px;
margin-bottom: 2px;
border: 1px solid black;
color: white;
background-color: rgb(255, 255, 255, 0.1);
font-size: large;
}
#statsPie {
}
#search{
width: 100%;
height: 10%;
display: inline-flex;
}
#search-input {
margin-left: 25px;
width: 75%;
font-size: 16px;
padding: 12px 20px 12px 40px;
border: 1px solid #ddd;
height: 20px;
align-self: center;
}
#filterButton {
align-self: center;
margin-left: 2px;
font-size: xx-large;
color: white;
background: rgba(191, 64, 191,0.5);
border:2px solid black;
}
#filterButton:hover{
background: rgba(191, 64, 191);
}
#researchUL {
list-style-type: none;
color: white;
padding: 12px;
margin: 5px;
height: 400px;
overflow: scroll;
}
#researchLi{
display: grid;
grid-template-columns: auto auto auto;
border: 2px solid black;
color: white;
font-size: x-large;
text-align: center;
text-indent: 7px;
background-color: rgba(255, 255, 255, 0.09);
border-radius: 18px;
margin-bottom: 15px;
}
a{
color:#007aff;
text-decoration: underline;
cursor: pointer;
}
.vl {
border-right: 2px solid black;
}
</style>

View File

@ -1,29 +1,19 @@
<script setup>
import i18n from "@/i18n.js"
import {provide, reactive, ref} from 'vue'
import { reactive } from 'vue'
import { getStudents } from '../rest/Users.js'
import AboutStudent from "@/Apps/Inscription/AboutStudent.vue";
const users = await getStudents();
let targetRegNo = "";
let list = ref(true);
</script>
<template style="margin-top:5%;">
<div v-if="list === false">
<AboutStudent :target=targetRegNo />
<button style="background-color:rgb(105,05,105);width:5%; margin-left: 10%;" @click="list = true;">Back</button>
</div>
<div style="display:flex; justify-content:center; " v-for="item in users" v-if="list === true">
</script>
<template>
<div v-for="item in users">
<div class="bodu">
<div class="container">
<div class="status"><a style="margin-left:30px">{{item.status}}</a></div>
<div class="option"><a>{{item.role}}</a></div>
<div class="surname"><a>{{item.lastName}}</a></div>
<div class="firstname"><a>{{item.firstName}}</a></div>
<div class="infos">
<button style="background-color:rgb(105,05,105);" @click="list = false; targetRegNo = item.regNo;">{{i18n("request.moreInfos")}} </button>
</div>
<div class="infos"><button style="background-color:rgb(105,05,105);" >{{i18n("request.moreInfos")}} </button></div>
</div>
</div>
</div>
@ -35,10 +25,11 @@
height:100px;
font-size:30px;
display:grid;
grid-template-columns:21.7% 21.7% 21.7% 20% 13.1%;
grid-template-columns:250px 250px 250px 250px 150px;
grid-template-areas:
"status option surname firstname infos";
column-gap:10px;
}
.infos {
@ -51,6 +42,21 @@
align-self:center;
}
.refuse{
grid-area:refuse;
align-self:center;
}
.titles {
grid-area:titles;
background-color:rgb(215,215,215);
}
.id{
grid-area:id;
margin-left:40px;
align-self:center;
}
.status{
grid-area:status;
align-self:center;
@ -74,16 +80,16 @@
button{
font-size:15px;
height:50px;
width:75%;
height:50px;
width:100px;
border:none;
border-radius:20px;
}
.bodu {
margin-top:2%;
width:66%;
width:100%;
margin-bottom:10px;
border:2px solid black;
border-radius:9px;
background-color:rgb(50,50,50);

View File

@ -7,8 +7,8 @@
const users = await getAllUsers();
</script>
<template style="margin-top:5%;">
<div style="display:flex; justify-content:center; min-width:1140px;" v-for="item in users">
<template>
<div v-for="item in users">
<div class="bodu">
<div class="container">
<div class="role"><a style="margin-left:30px">{{i18n(item.role)}}</a></div>
@ -22,20 +22,23 @@
<style scoped>
.container{
justify-content:center;
align-items:center;
color:white;
height:100px;
font-size:30px;
display:grid;
grid-template-columns:27.7% 27.7% 27.7% 16.9%;
grid-template-columns:250px 250px 250px 150px;
grid-template-areas:
"role surname firstname infos";
column-gap:10px;
}
.infos {
grid-area:infos;
align-self:center;
align-items:center;
}
.role {
@ -64,18 +67,20 @@
button{
font-size:15px;
height:50px;
width:75%;
width:100px;
border:none;
border-radius:20px;
}
.bodu {
margin-top:2%;
width:66%;
width:100%;
margin-bottom:10px;
border:2px solid black;
border-radius:9px;
background-color:rgb(50,50,50);
}
</style>

View File

@ -1,11 +1,4 @@
body {
background-color: rgb(53, 25, 60);
margin:0;
width: 100vw;
height: 100vh;
}
#app {
width: 100%;
height: 100%;
}

View File

@ -4,8 +4,5 @@ import 'https://kit.fontawesome.com/fb3bbd0a95.js'
import { createApp } from 'vue'
import App from './App.vue'
import CanvasJSChart from '@canvasjs/vue-charts';
const app = createApp(App);
app.use(CanvasJSChart);
app.mount('#app');
createApp(App).mount('#app')

Some files were not shown because too many files have changed in this diff Show More