Compare commits

..

No commits in common. "master" and "master" have entirely different histories.

90 changed files with 389 additions and 3451 deletions

View File

@ -14,26 +14,26 @@ on:
workflow_dispatch: workflow_dispatch:
jobs: jobs:
# deploy-frontend: deploy-frontend:
# runs-on: ubuntu-latest runs-on: ubuntu-latest
# steps: steps:
# - uses: actions/checkout@v4 - uses: actions/checkout@v4
# - name: Use Node.js ${{ matrix.node-version }} - name: Use Node.js ${{ matrix.node-version }}
# uses: actions/setup-node@v3 uses: actions/setup-node@v3
# working-directory: ./frontend working-directory: ./frontend
# - run: npm ci - run: npm ci
# name: clean install name: clean install
# working-directory: ./frontend working-directory: ./frontend
# - name: building - name: building
# working-directory: ./frontend working-directory: ./frontend
# run: npm run build run: npm run build
# - name: pushing to the server - name: pushing to the server
# working-directory: ./frontend working-directory: ./frontend
# run: | run: |
# echo "${{ secrets.SSH_KEY }}" > key echo "${{ secrets.SSH_KEY }}" > key
# chmod 0600 key chmod 0600 key
# scp -o "StrictHostKeyChecking=no" -o "LogLevel=ERROR" -i key -r dist/ ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }}: scp -o "StrictHostKeyChecking=no" -o "LogLevel=ERROR" -i key -r dist/ ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }}:
# - run: echo "The website has been deployed. visit https://clyde.herisson.ovh/" - run: echo "The website has been deployed. visit https://clyde.herisson.ovh/"
deploy-backend: deploy-backend:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@ -46,5 +46,5 @@ jobs:
scp -o "StrictHostKeyChecking=no" -o "LogLevel=ERROR" -i key -r * ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }}:api/ scp -o "StrictHostKeyChecking=no" -o "LogLevel=ERROR" -i key -r * ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }}:api/
- name: restarting the backend - name: restarting the backend
run: | run: |
ssh -o "StrictHostKeyChecking=no" -o "LogLevel=ERROR" -i key ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} 'cd api/ && sed -i compose.yaml -e "s/8080:8080/4001:8080/" -e "s/8000:8080/4000:8080/" && sed -e "8d" -i frontend/Dockerfile && docker-compose up --force-recreate --build -d' ssh -o "StrictHostKeyChecking=no" -o "LogLevel=ERROR" -i key ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} 'cd api/ && sed -i compose.yaml -e "s/8080:8080/4001:8080/" -e "s/8000:8080/4000:8080/" && docker-compose up --force-recreate --build -d'
- run: echo "The backend has been deployed. running at https://clyde.herisson.ovh/api" - run: echo "The backend has been deployed. running at https://clyde.herisson.ovh/api"

View File

@ -1,7 +1,5 @@
# Clyde project # Clyde project
Système de gestion d'universitée (dévelopé dans le cadre du cours de projet de génie logiciel de l'Umons 2024)
## Signature ## Signature
Projet du groupe 01: Projet du groupe 01:
@ -13,28 +11,21 @@ Projet du groupe 01:
## Running ## Running
**Attention**: Vous devez avoir installé docker-compose pour lancer ce projet.
Le projet peut être lancé grace à docker compose. Le projet peut être lancé grace à docker compose.
```sh ```sh
$ docker compose up $ docker compose up
``` ```
Dans le cas ou vous modifiez des fichiers, pour éviter que les images de docker ne soient réutilisés sans les Dans le cas ou vous modifiers des fichiers, pour éviter que les images de docker soient recrées avec les changement
changements.
```sh ```sh
$ docker compose up --force-recreate --build $ docker compose up --force-recreate --build
``` ```
Vous pouvez alors accéder au frontend à l'adresse [http://localhost:5173](http://localhost:5173)
Une version finie du site construite automatiquement à l'aide de gitea actions tourne à l'adresse
[https://clyde.herisson.ovh/](https://clyde.herisson.ovh/)
## Dévelopement ## 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 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! **Attention**: Ce mode n'est pas fait pour être utilisé en production!
```sh ```sh
@ -47,3 +38,4 @@ Ceci requière également docker pour lancer une instance de postgresql pris en
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 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` 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) (cette configuration peut également être changée dans le fichier resources/application.properties de spring)

View File

@ -1,63 +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 ovh.herisson.Clyde.Tables.ScientificPublications.Researcher;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
@Data
public class ResearchDTO {
private long id;
private String title;
private ResearcherDTO researcher;
private final Set<ResearcherDTO> coAuthors;
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 long views;
private ResearchDTO(String title, ResearcherDTO researcherDTO, Date releaseDate, PaperType paperType, String pdfLocation, String language, Access access, String domain, String bibTexLocation, String summary, Set<Researcher> coAuthors, 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.bibTexLocation = bibTexLocation;
this.coAuthors = new HashSet<>();
for (Researcher coAuthor: coAuthors) {
this.coAuthors.add(ResearcherDTO.construct(coAuthor));
}
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.getBibTexLocation(), research.getSummary(), research.getCoAuthors(),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

@ -8,7 +8,6 @@ import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import ovh.herisson.Clyde.Services.AuthenticatorService; import ovh.herisson.Clyde.Services.AuthenticatorService;
import ovh.herisson.Clyde.Services.ScientificPublications.ResearchesService;
import ovh.herisson.Clyde.Tables.Applications; import ovh.herisson.Clyde.Tables.Applications;
import ovh.herisson.Clyde.Tables.Role; import ovh.herisson.Clyde.Tables.Role;
import ovh.herisson.Clyde.Tables.User; import ovh.herisson.Clyde.Tables.User;
@ -21,10 +20,7 @@ public class ApplicationsController {
AuthenticatorService authServ; AuthenticatorService authServ;
ResearchesService researchesServ; public ApplicationsController(AuthenticatorService authServ){
public ApplicationsController(AuthenticatorService authServ, ResearchesService researchesServ){
this.researchesServ = researchesServ;
this.authServ = authServ; this.authServ = authServ;
} }
@ -51,7 +47,6 @@ public class ApplicationsController {
//if unAuthed //if unAuthed
authorizedApps.add(Applications.Login); authorizedApps.add(Applications.Login);
authorizedApps.add(Applications.ListResearches);
authorizedApps.add(Applications.Schedule); authorizedApps.add(Applications.Schedule);
User user = authServ.getUserFromToken(token); User user = authServ.getUserFromToken(token);
@ -76,15 +71,10 @@ public class ApplicationsController {
authorizedApps.add(Applications.Requests); authorizedApps.add(Applications.Requests);
authorizedApps.add(Applications.StudentsList);} authorizedApps.add(Applications.StudentsList);}
if (researchesServ.getResearcherByUser(user) != null)
authorizedApps.add(Applications.ManageResearcherProfile);
if (!authServ.isNotIn(new Role[]{Role.Secretary,Role.Admin},token)){ if (!authServ.isNotIn(new Role[]{Role.Secretary,Role.Admin},token)){
authorizedApps.add(Applications.UsersList); authorizedApps.add(Applications.UsersList);
authorizedApps.add(Applications.ManageSchedules); authorizedApps.add(Applications.ManageSchedules);
authorizedApps.add(Applications.LessonRequests); authorizedApps.add(Applications.LessonRequests);}
authorizedApps.add(Applications.CreateUser);
}
if (!authServ.isNotIn(new Role[]{Role.Secretary,Role.Admin, Role.InscriptionService},token)){ if (!authServ.isNotIn(new Role[]{Role.Secretary,Role.Admin, Role.InscriptionService},token)){
authorizedApps.add(Applications.Payments);} authorizedApps.add(Applications.Payments);}

View File

@ -6,7 +6,10 @@ import org.springframework.web.bind.annotation.*;
import ovh.herisson.Clyde.Repositories.CurriculumCourseRepository; import ovh.herisson.Clyde.Repositories.CurriculumCourseRepository;
import ovh.herisson.Clyde.Responses.UnauthorizedResponse; import ovh.herisson.Clyde.Responses.UnauthorizedResponse;
import ovh.herisson.Clyde.Services.*; import ovh.herisson.Clyde.Services.*;
import ovh.herisson.Clyde.Tables.*; import ovh.herisson.Clyde.Tables.Course;
import ovh.herisson.Clyde.Tables.Role;
import ovh.herisson.Clyde.Tables.User;
import ovh.herisson.Clyde.Tables.UserCurriculum;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
@ -25,18 +28,15 @@ public class CourseController {
private final UserService userService; private final UserService userService;
private final CurriculumService curriculumService;
private final UserCurriculumService userCurriculumService; private final UserCurriculumService userCurriculumService;
private final CurriculumCourseRepository curriculumCourseRepository; private final CurriculumCourseRepository curriculumCourseRepository;
private final CurriculumCourseService curriculumCourseService; private final CurriculumCourseService curriculumCourseService;
public CourseController(CourseService courseServ, TeacherCourseService teacherCourseServ, AuthenticatorService authServ, UserService userService, CurriculumService curriculumService, UserCurriculumService userCurriculumService, CurriculumCourseRepository curriculumCourseRepository, CurriculumCourseService curriculumCourseService) { public CourseController(CourseService courseServ, TeacherCourseService teacherCourseServ, AuthenticatorService authServ, UserService userService, UserCurriculumService userCurriculumService, CurriculumCourseRepository curriculumCourseRepository, CurriculumCourseService curriculumCourseService) {
this.courseServ = courseServ; this.courseServ = courseServ;
this.teacherCourseServ = teacherCourseServ; this.teacherCourseServ = teacherCourseServ;
this.authServ = authServ; this.authServ = authServ;
this.userService = userService; this.userService = userService;
this.curriculumService = curriculumService;
this.userCurriculumService = userCurriculumService; this.userCurriculumService = userCurriculumService;
this.curriculumCourseRepository = curriculumCourseRepository; this.curriculumCourseRepository = curriculumCourseRepository;
this.curriculumCourseService = curriculumCourseService; this.curriculumCourseService = curriculumCourseService;
@ -82,18 +82,16 @@ public class CourseController {
} }
@PostMapping("/course/curriculum/{id}") @PostMapping("/course")
public ResponseEntity<Map<String ,Object>> postCourse(@RequestHeader("Authorization") String token, public ResponseEntity<Map<String ,Object>> postCourse(@RequestHeader("Authorization") String token,
@RequestBody Course course,@PathVariable long id) @RequestBody Course course)
{ {
if (authServ.isNotIn(new Role[]{Role.Secretary,Role.Admin},token)) if (authServ.isNotIn(new Role[]{Role.Secretary,Role.Admin},token))
return new UnauthorizedResponse<>(null); return new UnauthorizedResponse<>(null);
Course createdCourse = courseServ.save(course); Course createdCourse = courseServ.save(course);
Curriculum curriculum = curriculumService.findById(id); if (createdCourse == null)
if (createdCourse == null || curriculum == null)
return new ResponseEntity<>(null,HttpStatus.BAD_REQUEST); return new ResponseEntity<>(null,HttpStatus.BAD_REQUEST);
CurriculumCourse curriculumCourse = new CurriculumCourse(curriculum,course);
curriculumCourseService.save(curriculumCourse);
return new ResponseEntity<>(ProtectionService.courseWithoutPassword(createdCourse), HttpStatus.CREATED); return new ResponseEntity<>(ProtectionService.courseWithoutPassword(createdCourse), HttpStatus.CREATED);
} }

View File

@ -19,7 +19,6 @@ public class CurriculumController {
private final CurriculumService curriculumServ; private final CurriculumService curriculumServ;
private final CourseService courseServ;
private final AuthenticatorService authServ; private final AuthenticatorService authServ;
private final UserCurriculumService userCurriculumServ; private final UserCurriculumService userCurriculumServ;
@ -28,9 +27,8 @@ public class CurriculumController {
private final UserService userServ; private final UserService userServ;
private final ExternalCurriculumRepository ecr; private final ExternalCurriculumRepository ecr;
public CurriculumController(CurriculumService curriculumServ, CourseService courseServ, AuthenticatorService authServ, UserCurriculumService userCurriculumServ, CurriculumCourseService curriculumCourseServ, InscriptionRepository ir, UserService userServ, ExternalCurriculumRepository ecr){ public CurriculumController(CurriculumService curriculumServ, AuthenticatorService authServ, UserCurriculumService userCurriculumServ, CurriculumCourseService curriculumCourseServ, InscriptionRepository ir, UserService userServ, ExternalCurriculumRepository ecr){
this.curriculumServ = curriculumServ; this.curriculumServ = curriculumServ;
this.courseServ = courseServ;
this.authServ = authServ; this.authServ = authServ;
this.userCurriculumServ = userCurriculumServ; this.userCurriculumServ = userCurriculumServ;
this.curriculumCourseServ = curriculumCourseServ; this.curriculumCourseServ = curriculumCourseServ;
@ -62,18 +60,6 @@ public class CurriculumController {
return new ResponseEntity<>(curriculumCourseServ.getDepthCurriculum(curriculum),HttpStatus.OK); return new ResponseEntity<>(curriculumCourseServ.getDepthCurriculum(curriculum),HttpStatus.OK);
} }
@GetMapping("/course/curriculum/{id}")
public ResponseEntity<Iterable<Curriculum>> getCurriculumsByCourse(@RequestHeader("Authorization") String token, @PathVariable long id){
if(authServ.isNotIn(new Role[]{Role.Admin, Role.Secretary},token))
return new UnauthorizedResponse<>(null);
Course course = courseServ.findById(id);
if(course == null)
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
Iterable<Curriculum> curriculum = curriculumCourseServ.findCurriculumByCourses(course);
return new ResponseEntity<>(curriculum, HttpStatus.OK);
}
//Return the list of all curicullums of an user //Return the list of all curicullums of an user
@GetMapping("/onescurriculum/{userId}") @GetMapping("/onescurriculum/{userId}")
@ -105,20 +91,17 @@ public class CurriculumController {
} }
@PostMapping("/curriculum/{id}") @PostMapping("/curriculum/{id}")
public ResponseEntity<String> postCourseToCurriculum(@RequestHeader("Authorization") String token, public ResponseEntity<String> postCoursesToCurriculum(@RequestHeader("Authorization") String token,
@RequestBody long coursesId, @RequestBody Iterable<Long> coursesIds,
@PathVariable long id){ @PathVariable long id)
{
if (authServ.isNotIn(new Role[]{Role.Admin,Role.Secretary},token)) if (authServ.isNotIn(new Role[]{Role.Admin,Role.Secretary},token))
return new UnauthorizedResponse<>(null); return new UnauthorizedResponse<>(null);
CurriculumCourse curriculumCourse = new CurriculumCourse(curriculumServ.findById(id), courseServ.findById(coursesId)); if (!curriculumCourseServ.saveAll(coursesIds, curriculumServ.findById(id)))
if(curriculumCourse.getCourse() == null || curriculumCourse.getCurriculum() == null)
return new ResponseEntity<>(HttpStatus.BAD_REQUEST); return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
curriculumCourseServ.save(curriculumCourse);
return new ResponseEntity<>(HttpStatus.OK); return new ResponseEntity<>(HttpStatus.OK);
} }

View File

@ -13,7 +13,10 @@ import ovh.herisson.Clyde.Services.AuthenticatorService;
import ovh.herisson.Clyde.Services.TokenService; import ovh.herisson.Clyde.Services.TokenService;
import ovh.herisson.Clyde.Services.UserService; import ovh.herisson.Clyde.Services.UserService;
import ovh.herisson.Clyde.Tables.*; import ovh.herisson.Clyde.Tables.*;
import ovh.herisson.Clyde.Tables.Inscription.*; import ovh.herisson.Clyde.Tables.Inscription.ExemptionsRequest;
import ovh.herisson.Clyde.Tables.Inscription.Minerval;
import ovh.herisson.Clyde.Tables.Inscription.ScholarshipRequest;
import ovh.herisson.Clyde.Tables.Inscription.UnregisterRequest;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
@ -325,7 +328,7 @@ public class RequestsController {
return new ResponseEntity<>(HttpStatus.OK); return new ResponseEntity<>(HttpStatus.OK);
} }
toEdit.setTeacherApprovalState(newteacherstate); toEdit.setState(newteacherstate);
changeCurriculumRequestRepository.save(toEdit); changeCurriculumRequestRepository.save(toEdit);
if (newteacherstate == RequestState.Accepted && toEdit.getState() == RequestState.Accepted){ if (newteacherstate == RequestState.Accepted && toEdit.getState() == RequestState.Accepted){

View File

@ -12,8 +12,14 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import ovh.herisson.Clyde.Responses.UnauthorizedResponse; import ovh.herisson.Clyde.Responses.UnauthorizedResponse;
import ovh.herisson.Clyde.Services.*; import ovh.herisson.Clyde.Services.AuthenticatorService;
import ovh.herisson.Clyde.Tables.*; import ovh.herisson.Clyde.Services.LessonRequestService;
import ovh.herisson.Clyde.Services.LessonService;
import ovh.herisson.Clyde.Services.ProtectionService;
import ovh.herisson.Clyde.Tables.LessonChangesRequest;
import ovh.herisson.Clyde.Tables.RequestState;
import ovh.herisson.Clyde.Tables.Role;
import ovh.herisson.Clyde.Tables.User;
import java.util.Map; import java.util.Map;
@ -22,13 +28,11 @@ import java.util.Map;
public class LessonRequestsController { public class LessonRequestsController {
private final LessonRequestService lessonRequestServ; private final LessonRequestService lessonRequestServ;
private final AuthenticatorService authServ; private final AuthenticatorService authServ;
private final UserService userServ;
private final LessonService lessonServ; private final LessonService lessonServ;
public LessonRequestsController(LessonRequestService lessonRequestServer, AuthenticatorService authServ, UserService userServ, LessonService lessonServ) { public LessonRequestsController(LessonRequestService lessonRequestServer, AuthenticatorService authServ, LessonService lessonServ) {
this.lessonRequestServ = lessonRequestServer; this.lessonRequestServ = lessonRequestServer;
this.authServ = authServ; this.authServ = authServ;
this.userServ = userServ;
this.lessonServ = lessonServ; this.lessonServ = lessonServ;
} }
/** /**
@ -109,7 +113,6 @@ public class LessonRequestsController {
if(lessonRequest.getRequestType() == 0 ) { if(lessonRequest.getRequestType() == 0 ) {
if (!lessonRequestServ.modifyCreateRequestState(lessonRequest, state, local)) if (!lessonRequestServ.modifyCreateRequestState(lessonRequest, state, local))
return new ResponseEntity<>(HttpStatus.BAD_REQUEST); return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
userServ.Notify(lessonRequest.getUser(), new Notification("Request took in charge","Request"+ state + ":" + lessonRequest.getCourse().getTitle(), "#/manage-owned-lessons"));
} }
else if(lessonRequest.getRequestType() == 1){ else if(lessonRequest.getRequestType() == 1){
@ -119,14 +122,12 @@ public class LessonRequestsController {
if(!lessonRequestServ.modifyChangeRequestState(infos,lessonRequest.getLessonId(),state)) if(!lessonRequestServ.modifyChangeRequestState(infos,lessonRequest.getLessonId(),state))
return new ResponseEntity<>(HttpStatus.BAD_REQUEST); return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
lessonRequest.setState(state); lessonRequest.setState(state);
userServ.Notify(lessonRequest.getUser(), new Notification("Request took in charge","Request"+ state + ":" + lessonServ.findById(lessonRequest.getLessonId()).getCourse().getTitle(), "#/manage-owned-lessons"));
} }
else{ else{
userServ.Notify(lessonRequest.getUser(), new Notification("Request took in charge","Request"+ state + ":" + lessonServ.findById(lessonRequest.getLessonId()).getCourse().getTitle(), "#/manage-owned-lessons"));
lessonRequestServ.modifyDeleteRequest(lessonRequest, state); lessonRequestServ.modifyDeleteRequest(lessonRequest, state);
lessonRequest.setState(state); lessonRequest.setState(state);
} }
lessonRequestServ.save(lessonRequest); lessonRequestServ.save(lessonRequest);
return new ResponseEntity<>(HttpStatus.OK); return new ResponseEntity<>(HttpStatus.OK);

View File

@ -1,5 +1,6 @@
package ovh.herisson.Clyde.EndPoints; package ovh.herisson.Clyde.EndPoints;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import ovh.herisson.Clyde.Repositories.*; import ovh.herisson.Clyde.Repositories.*;
import ovh.herisson.Clyde.Repositories.Inscription.ExternalCurriculumRepository; import ovh.herisson.Clyde.Repositories.Inscription.ExternalCurriculumRepository;
@ -7,24 +8,19 @@ import ovh.herisson.Clyde.Repositories.Inscription.MinervalRepository;
import ovh.herisson.Clyde.Repositories.Inscription.ScholarshipRequestRepository; import ovh.herisson.Clyde.Repositories.Inscription.ScholarshipRequestRepository;
import ovh.herisson.Clyde.Repositories.Inscription.UnregisterRequestRepository; import ovh.herisson.Clyde.Repositories.Inscription.UnregisterRequestRepository;
import ovh.herisson.Clyde.Services.*; 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.Services.Inscription.InscriptionService;
import ovh.herisson.Clyde.Tables.Inscription.ExternalCurriculum; import ovh.herisson.Clyde.Tables.*;
import ovh.herisson.Clyde.Tables.Inscription.InscriptionRequest;
import ovh.herisson.Clyde.Tables.Inscription.Minerval;
import ovh.herisson.Clyde.Tables.Inscription.ScholarshipRequest;
import ovh.herisson.Clyde.Tables.Inscription.*; import ovh.herisson.Clyde.Tables.Inscription.*;
import java.util.*; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
@RestController @RestController
@CrossOrigin(originPatterns = "*", allowCredentials = "true") @CrossOrigin(originPatterns = "*", allowCredentials = "true")
public class MockController { public class MockController {
private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
public final UserService userService; public final UserService userService;
public final UserRepository userRepo; public final UserRepository userRepo;
public final TokenRepository tokenRepo; public final TokenRepository tokenRepo;
@ -42,14 +38,14 @@ public class MockController {
public final LessonRequestService lessonRequestService; public final LessonRequestService lessonRequestService;
ArrayList<User> mockUsers; ArrayList<User> mockUsers;
public static boolean isMocked = false;
public final ResearchesService researchesService;
public final UserCurriculumRepository ucr; public final UserCurriculumRepository ucr;
public final MinervalRepository minervalRepository; public final MinervalRepository minervalRepository;
public final ScholarshipRequestRepository scholarshipRequestRepository; public final ScholarshipRequestRepository scholarshipRequestRepository;
public final UnregisterRequestRepository uninscriptionRequestRepository; public final UnregisterRequestRepository uninscriptionRequestRepository;
public MockController(UserService userService, UserRepository userRepo, TokenRepository tokenRepo, TokenService tokenService, CurriculumCourseService CurriculumCourseService, CurriculumService curriculumService, CourseService courseService, ExternalCurriculumRepository externalCurriculumRepository, ResearchesService researchesService, InscriptionService inscriptionService, UserCurriculumRepository ucr, MinervalRepository minervalRepository, ScholarshipRequestRepository scholarshipRequestRepository, UnregisterRequestRepository unregisterRequestRepository, LessonService lessonService, ScheduleService scheduleService, ScheduleLessonService scheduleLessonService, LessonRequestService lessonRequestService){ public MockController(UserService userService, UserRepository userRepo, TokenRepository tokenRepo, TokenService tokenService, CurriculumCourseService CurriculumCourseService, CurriculumService curriculumService, CourseService courseService, ExternalCurriculumRepository externalCurriculumRepository, InscriptionService inscriptionService, UserCurriculumRepository ucr, MinervalRepository minervalRepository, ScholarshipRequestRepository scholarshipRequestRepository, UnregisterRequestRepository unregisterRequestRepository, LessonService lessonService, ScheduleService scheduleService, ScheduleLessonService scheduleLessonService, LessonRequestService lessonRequestService){
this.userService = userService; this.userService = userService;
this.tokenRepo = tokenRepo; this.tokenRepo = tokenRepo;
this.userRepo = userRepo; this.userRepo = userRepo;
@ -59,7 +55,6 @@ public class MockController {
this.courseService = courseService; this.courseService = courseService;
this.externalCurriculumRepository = externalCurriculumRepository; this.externalCurriculumRepository = externalCurriculumRepository;
this.inscriptionService = inscriptionService; this.inscriptionService = inscriptionService;
this.researchesService = researchesService;
this.lessonService = lessonService; this.lessonService = lessonService;
this.scheduleService = scheduleService; this.scheduleService = scheduleService;
this.scheduleLessonService = scheduleLessonService; this.scheduleLessonService = scheduleLessonService;
@ -77,17 +72,16 @@ public class MockController {
*/ */
@PostMapping("/mock") @PostMapping("/mock")
public void postMock() { public void postMock(){
if(!isMocked){
// user part // user part
User herobrine = new User("brine","hero","admin@admin.com","behind","ShadowsLand",new Date(0), null,Role.Admin,"admin"); User herobrine = new User("brine","hero","admin@admin.com","behind","ShadowsLand",new Date(0), null,Role.Admin,passwordEncoder.encode("admin"));
User joe = new User("Piplo","Joe","student@student.com","roundabout","England",new Date(0), null,Role.Student,"student"); 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,"secretary"); 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,"teacher"); 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,"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,"inscriptionService"); 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, "jesuispaulleroi"); 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)); mockUsers = new ArrayList<>(Arrays.asList(herobrine,joe,meh,joke,lena,jojo, popo));
userService.saveAll(mockUsers); userService.saveAll(mockUsers);
@ -95,9 +89,9 @@ public class MockController {
ExternalCurriculum externalCurriculum = new ExternalCurriculum(null, "HEH", "Bachelier en ingénieur", "completed", 2015, 2017, null, joe); ExternalCurriculum externalCurriculum = new ExternalCurriculum(null, "HEH", "Bachelier en ingénieur", "completed", 2015, 2017, null, joe);
externalCurriculumRepository.save(externalCurriculum); externalCurriculumRepository.save(externalCurriculum);
Minerval minerval = new Minerval(joe.getRegNo(), 0, 852, 2023); Minerval minerval = new Minerval(joe.getRegNo(), 0, 852, 2023);
minervalRepository.save(minerval); minervalRepository.save(minerval);
// Course / Curriculum part // Course / Curriculum part
Curriculum infoBab1 = new Curriculum(1,"info", false); Curriculum infoBab1 = new Curriculum(1,"info", false);
Curriculum chemistryBab1 = new Curriculum(1,"chemistry", false); Curriculum chemistryBab1 = new Curriculum(1,"chemistry", false);
@ -129,14 +123,13 @@ public class MockController {
Course psycho1 = new Course(21, "Neuroreaction of isolated brain cells",joke); Course psycho1 = new Course(21, "Neuroreaction of isolated brain cells",joke);
Course commun = new Course(2, "cours commun",joke); Course commun = new Course(2, "cours commun",joke);
courseService.save(progra1); courseService.save(progra1);
courseService.save(chemistry1); courseService.save(chemistry1);
courseService.save(psycho1); courseService.save(psycho1);
courseService.save(commun); courseService.save(commun);
ScholarshipRequest ssr1 = new ScholarshipRequest(joe, RequestState.Pending, 0, new Date(), "test", "test");
scholarshipRequestRepository.save(ssr1);
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,progra1));
CurriculumCourseService.save(new CurriculumCourse(infoBab1,commun)); CurriculumCourseService.save(new CurriculumCourse(infoBab1,commun));
@ -145,51 +138,21 @@ public class MockController {
CurriculumCourseService.save(new CurriculumCourse(psychologyBab1,commun)); CurriculumCourseService.save(new CurriculumCourse(psychologyBab1,commun));
CurriculumCourseService.save(new CurriculumCourse(chemistryBab1, chemistry1)); CurriculumCourseService.save(new CurriculumCourse(chemistryBab1, chemistry1));
CurriculumCourseService.save(new CurriculumCourse(chemistryBab1, commun)); CurriculumCourseService.save(new CurriculumCourse(chemistryBab1,commun));
CurriculumCourseService.save(new CurriculumCourse(chemistryBab1, chemistry1)); CurriculumCourseService.save(new CurriculumCourse(chemistryBab1,chemistry1));
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, null); 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, null);
inscriptionService.save(inscriptionRequest); inscriptionService.save(inscriptionRequest);
///////////////////////////
// extension Publications Scientifiques
Researcher jojoResearcherAccount = new Researcher(jojo, "3363-22555-AB33-T", null, "IT");
Researcher joResearchAccount = new Researcher(joe,"N555-321213-BED-DD",null, "Physics");
Researcher output = researchesService.saveResearcher(jojoResearcherAccount);
Researcher joOutput = researchesService.saveResearcher(joResearchAccount);
Set<Researcher> coAuthor = new HashSet<>();
coAuthor.add(joOutput);
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",coAuthor);
Research restrictedResearch = new Research("the great Constantinople war", output, new Date(1111111111),
PaperType.Article, "restricted", null, "Portuguese",
Access.Restricted, "history", "this is a summary", new HashSet<>());
Research privateResearch = new Research("the great Potato War", output, new Date(),
PaperType.Article, "private", null, "english",
Access.Private, "agriculture", "my life is potato",null);
researchesService.saveResearch(restrictedResearch);
researchesService.saveResearch(privateResearch);
researchesService.saveResearch(jojoResearch);
//Schedule part //Schedule part
Lesson lesson_0_progra1 = new Lesson(progra1, "Mon Apr 22 2024 08:15", "Mon Apr 22 2024 10:15","rgb(255,36,175)","A0B2","Course"); Lesson lesson_0_progra1 = new Lesson(progra1, "Mon Apr 22 2024 08:15", "Mon Apr 22 2024 10:15","rgb(0,50,100)","A0B2","Course");
Lesson lesson_0_chemistry1 = new Lesson(chemistry1, "Wed Mar 27 2024 08:15", "Wed Mar 27 2024 09:15","rgb(36,175,255)","A0B2","TP"); Lesson lesson_0_chemistry1 = new Lesson(chemistry1, "Wed Mar 27 2024 08:15", "Wed Mar 27 2024 09:15","rgb(100,50,0)","A0B2","TP");
Lesson lesson_0_psycho1 = new Lesson(psycho1, "Sun Mar 24 2024 10:30 ","Sun Mar 24 2024 12:30 ","rgb(255,36,175)", "A0B2","TD"); Lesson lesson_0_psycho1 = new Lesson(psycho1, "Sun Mar 24 2024 10:30 ","Sun Mar 24 2024 12:30 ","rgb(100,50,100)", "A0B2","TD");
Lesson lesson_1_progra1 = new Lesson(progra1, "Mon Apr 02 2024 13:30", "Mon Apr 02 2024 15:30","rgb(36,175,255)","A0B2","TP"); Lesson lesson_1_progra1 = new Lesson(progra1, "Mon Apr 02 2024 13:30", "Mon Apr 02 2024 15:30","rgb(0,50,100)","A0B2","TP");
Lesson lesson_0_commun = new Lesson(commun, "Mon Apr 01 2024 10:30", "Mon Apr 01 2024 12:30","rgb(255,36,175)","A0B2","Course"); Lesson lesson_0_commun = new Lesson(commun, "Mon Apr 01 2024 10:30", "Mon Apr 01 2024 12:30","rgb(0,50,100)","A0B2","Course");
LessonChangesRequest request1 = new LessonChangesRequest(joke,RequestState.Pending,null,null,null,null,2,null,1); LessonChangesRequest request1 = new LessonChangesRequest(joke,RequestState.Pending,null,null,null,null,2,null,1);
LessonChangesRequest request2 = new LessonChangesRequest(joke,RequestState.Pending,"Fri Apr 19 2024 10:30 ","Fri Apr 19 2024 12:30 ",null,null,1,null,2); LessonChangesRequest request2 = new LessonChangesRequest(joke,RequestState.Pending,"Fri Apr 19 2024 10:30 ","Fri Apr 19 2024 12:30 ",null,null,1,null,2);
@ -231,9 +194,6 @@ public class MockController {
externalCurriculum = new ExternalCurriculum(inscriptionRequest, "HEH", "Bachelier en informatique", "Completed", 2015, 2018, null, null); externalCurriculum = new ExternalCurriculum(inscriptionRequest, "HEH", "Bachelier en informatique", "Completed", 2015, 2018, null, null);
externalCurriculumRepository.save(externalCurriculum); externalCurriculumRepository.save(externalCurriculum);
isMocked = true;
}
} }
} }

View File

@ -80,7 +80,7 @@ public class ForumController {
public ResponseEntity<Topic> postTopicToForum(@RequestHeader("Authorization") String token, @PathVariable long id, @RequestBody Topic data){ public ResponseEntity<Topic> postTopicToForum(@RequestHeader("Authorization") String token, @PathVariable long id, @RequestBody Topic data){
User u = authServ.getUserFromToken(token); User u = authServ.getUserFromToken(token);
Forum f = forumRepo.findById(id).orElse(null); Forum f = forumRepo.findById(id).orElse(null);
if(!(f.getWriters().contains(u) || f.getCourse().getOwner().equals(u) || u.getRole() == Role.Admin)){ if(!(f.getWriters().contains(u) || u.getRole() == Role.Admin)){
return new UnauthorizedResponse<>(null); return new UnauthorizedResponse<>(null);
} }
forumServ.createTopic(f, data); forumServ.createTopic(f, data);

View File

@ -1,61 +0,0 @@
package ovh.herisson.Clyde.EndPoints;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
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.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import lombok.AllArgsConstructor;
import ovh.herisson.Clyde.Repositories.NotificationRepository;
import ovh.herisson.Clyde.Responses.UnauthorizedResponse;
import ovh.herisson.Clyde.Services.AuthenticatorService;
import ovh.herisson.Clyde.Tables.Notification;
import ovh.herisson.Clyde.Tables.User;
import ovh.herisson.Clyde.Tables.Notification.Status;
@RestController
@AllArgsConstructor
@CrossOrigin(originPatterns = "*", allowCredentials = "true")
public class NotificationController {
private AuthenticatorService authServ;
private NotificationRepository notifRepo;
@GetMapping("/notifications")
public ResponseEntity<List<Notification>> getNotifications(@RequestHeader("Authorization") String token){
User u = authServ.getUserFromToken(token);
if(u == null){
return new UnauthorizedResponse<>(null);
}
ArrayList<Notification> ret = new ArrayList<>();
for (Notification n : u.getNotifications()) {
if(!n.getStatus().equals(Status.Archived)){
ret.add(n);
}
}
return new ResponseEntity<>(ret, HttpStatus.OK);
}
@PostMapping("/notifications/{id}")
public ResponseEntity<Notification> archiveNotification(@RequestHeader("Authorization") String token, @PathVariable long id){
User u = authServ.getUserFromToken(token);
Notification n = notifRepo.findById(id).orElse(null);
if(u == null || n.getUser() != u){
return new UnauthorizedResponse<>(null);
}
n.setStatus(Status.Archived);
notifRepo.save(n);
return new ResponseEntity<>(HttpStatus.OK);
}
}

View File

@ -1,167 +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
* in the updates, the coAuthors have to be referenced by their ids
*
*/
@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);
}
///////
//views part
@PostMapping("/addview/cdn/{url}")
public ResponseEntity<ResearchDTO> addView(@PathVariable String url){
System.out.println(url);
Research research = researchesServ.getResearchByUrl("cdn/" + url);
if (research ==null) return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
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,47 +0,0 @@
package ovh.herisson.Clyde.EndPoints.ScientificPublications;
/******************************************************
* @file StatController.java
* @author Bartha Maxime
* @scope Publications Scientifiques
*
* Api class for handling statistics
******************************************************/
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

@ -44,7 +44,7 @@ public class UserController {
@GetMapping("/user/{id}") @GetMapping("/user/{id}")
public ResponseEntity<HashMap<String ,Object>> getUserById(@RequestHeader("Authorization") String token, @PathVariable Long id){ public ResponseEntity<HashMap<String ,Object>> getUserById(@RequestHeader("Authorization") String token, @PathVariable Long id){
if (authServ.isNotIn(new Role[]{Role.Admin,Role.Secretary,Role.InscriptionService, Role.Teacher},token)) if (authServ.isNotIn(new Role[]{Role.Admin,Role.Secretary,Role.InscriptionService},token))
return new UnauthorizedResponse<>(null); return new UnauthorizedResponse<>(null);
return new ResponseEntity<>(ProtectionService.userWithoutPassword(userService.getUserById(id)), HttpStatus.OK); return new ResponseEntity<>(ProtectionService.userWithoutPassword(userService.getUserById(id)), HttpStatus.OK);
@ -86,20 +86,19 @@ public class UserController {
* @return a string clarifying the issue (if there is any) * @return a string clarifying the issue (if there is any)
*/ */
@PatchMapping("/user/{id}") @PatchMapping("/user/{id}")
public ResponseEntity<Map<String,Object>> patchUser(@RequestHeader("Authorization") String token, public ResponseEntity<String> patchUser(@RequestHeader("Authorization") String token,
@RequestBody Map<String,Object> updates, @RequestBody Map<String,Object> updates,
@PathVariable Long id) { @PathVariable Long id) {
if (token == null) return new UnauthorizedResponse<>(null); if (token == null) return new UnauthorizedResponse<>(null);
User poster = authServ.getUserFromToken(token); User poster = authServ.getUserFromToken(token);
if (poster == null) {return new UnauthorizedResponse<>(null);} if (poster == null) {return new UnauthorizedResponse<>("bad token");}
User modified = userService.modifyData(id,updates,poster); if (!userService.modifyData(id, updates, poster))
if (modified ==null) return new UnauthorizedResponse<>("there was an issue with the updates requested");
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
return new ResponseEntity<>(ProtectionService.userWithoutPassword(modified), HttpStatus.OK); return new ResponseEntity<>(null, HttpStatus.OK);
} }
@GetMapping("/teachers") @GetMapping("/teachers")

View File

@ -1,7 +1,5 @@
package ovh.herisson.Clyde.Repositories; package ovh.herisson.Clyde.Repositories;
import jakarta.transaction.Transactional;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query; import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.CrudRepository;
import ovh.herisson.Clyde.Tables.Course; import ovh.herisson.Clyde.Tables.Course;
@ -13,15 +11,7 @@ public interface CurriculumCourseRepository extends CrudRepository<CurriculumCou
@Query("select distinct cc.course from CurriculumCourse cc where cc.curriculum = ?1") @Query("select distinct cc.course from CurriculumCourse cc where cc.curriculum = ?1")
Iterable<Course> findCoursesByCurriculum(Curriculum curriculum); Iterable<Course> findCoursesByCurriculum(Curriculum curriculum);
@Query("select distinct cc.curriculum from CurriculumCourse cc where cc.course = ?1")
Iterable<Curriculum> findCurriculumByCourses(Course course);
@Query("select distinct cc.curriculum from CurriculumCourse cc") @Query("select distinct cc.curriculum from CurriculumCourse cc")
Iterable<Curriculum> findDistinctCurriculums(); Iterable<Curriculum> findDistinctCurriculums();
@Modifying
@Transactional
@Query("delete from CurriculumCourse cc where cc.course =?1")
void delete(Course course);
} }

View File

@ -1,7 +1,7 @@
package ovh.herisson.Clyde.Repositories.Inscription; package ovh.herisson.Clyde.Repositories.Inscription;
import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.CrudRepository;
import ovh.herisson.Clyde.Tables.Inscription.ChangeCurriculumRequest; import ovh.herisson.Clyde.Tables.ChangeCurriculumRequest;
public interface ChangeCurriculumRequestRepository extends CrudRepository<ChangeCurriculumRequest, Long> { public interface ChangeCurriculumRequestRepository extends CrudRepository<ChangeCurriculumRequest, Long> {
ChangeCurriculumRequest findById(long id); ChangeCurriculumRequest findById(long id);

View File

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

View File

@ -22,9 +22,6 @@ public interface ScheduleLessonRepository extends CrudRepository<ScheduleLesson,
@Query("select distinct sl.schedule from ScheduleLesson sl where sl.schedule.curriculum = ?1") @Query("select distinct sl.schedule from ScheduleLesson sl where sl.schedule.curriculum = ?1")
Schedule findScheduleByCurriculum(Curriculum curriculum); Schedule findScheduleByCurriculum(Curriculum curriculum);
@Query("select distinct sl from ScheduleLesson sl where sl.lesson = ?1")
ScheduleLesson findByLesson(Lesson lesson);
@Modifying @Modifying
@Transactional @Transactional
@Query("delete from ScheduleLesson sl where sl.lesson =?1") @Query("delete from ScheduleLesson sl where sl.lesson =?1")

View File

@ -1,26 +0,0 @@
package ovh.herisson.Clyde.Repositories.ScientificPublications;
/******************************************************
* @file ResearchRepository.java
* @author Bartha Maxime
* @scope Publications Scientifiques
*
* Repository handling communication with Reseach table
******************************************************/
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 java.util.Map;
public interface ResearchRepository extends CrudRepository<Research,Long> {
Research findById(long id);
Iterable<Research> findByAuthor(Researcher author);
@Query("select r from Research r where r.pdfLocation = ?1")
Research findByPdfLocation(String url);
}

View File

@ -1,23 +0,0 @@
package ovh.herisson.Clyde.Repositories.ScientificPublications;
/******************************************************
* @file ResearcherRepository.java
* @author Bartha Maxime
* @scope Publications Scientifiques
*
* Repository handling communication with Reseacher table
******************************************************/
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,47 +0,0 @@
package ovh.herisson.Clyde.Repositories.ScientificPublications;
/******************************************************
* @file StatsRepository.java
* @author Bartha Maxime
* @scope Publications Scientifiques
*
* Repository handling communication with Reseach table for making statistics
******************************************************/
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 where r.author.id = ?1 group by to_char(r.releaseDate, 'month')")
Iterable<Map<String ,Integer>> viewsByMonths(long researcherId);
@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(long researcherId);
@Query("select new map(r.domain as label, sum(r.views) as y) from Research r where r.author.id = ?1 group by r.domain")
Iterable<Map<String ,Integer>> viewsByTopics(long researcherId);
@Query("select new map(r.domain as label, count(distinct r.language) as y) from Research r where r.author.id = ?1 group by r.domain")
Iterable<Map<String ,Integer>> languageByTopics(long researcherId);
@Query("select new map(to_char(r.releaseDate,'YYYY') as label, count(distinct r.language) as y) from Research r where r.author.id = ?1 group by to_char(r.releaseDate,'YYYY')")
Iterable<Map<String ,Integer>> languageByYears(long researcherId);
@Query("select new map(to_char(r.releaseDate, 'month') as label, count(distinct r.language) as y) from Research r where r.author.id = ?1 group by to_char(r.releaseDate, 'month')")
Iterable<Map<String ,Integer>> languageByMonths(long researcherId);
@Query("select new map(to_char(r.releaseDate,'YYYY') as label, count(distinct r) as y) from Research r where r.author.id = ?1 group by to_char(r.releaseDate,'YYYY')")
Iterable<Map<String ,Integer>> researchesByYears(long researcherId);
@Query("select new map(r.domain as label, count(distinct r) as y) from Research r where r.author.id = ?1 group by r.domain")
Iterable<Map<String ,Integer>> researchesByTopics(long researcherId);
@Query("select new map(to_char(r.releaseDate, 'month') as label, count(distinct r) as y) from Research r where r.author.id = ?1 group by to_char(r.releaseDate, 'month')")
Iterable<Map<String ,Integer>> researchesByMonth(long researcherId);
}

View File

@ -13,11 +13,9 @@ public interface UserCurriculumRepository extends CrudRepository<UserCurriculum,
@Query("select uc.curriculum from UserCurriculum uc where uc.user = ?1") @Query("select uc.curriculum from UserCurriculum uc where uc.user = ?1")
Curriculum findByUser(User student); Curriculum findByUser(User student);
@Query("select distinct uc.user from UserCurriculum uc where uc.curriculum = ?1")
Iterable<User> findUsersByCurriculum(Curriculum curriculum);
ArrayList<UserCurriculum> findByUserOrderByCurriculum(User student); ArrayList<UserCurriculum> findByUserOrderByCurriculum(User student);
UserCurriculum findByUserAndCurriculumAndActual(User user, Curriculum curriculum, boolean actual); UserCurriculum findByUserAndCurriculumAndActual(User user, Curriculum curriculum, boolean actual);
ArrayList<UserCurriculum> findByUserAndActual(User user, boolean actual); ArrayList<UserCurriculum> findByUserAndActual(User user, boolean actual);
} }

View File

@ -24,6 +24,7 @@ public class AuthenticatorService {
return tokenService.getUserFromToken(token); return tokenService.getUserFromToken(token);
} }
public String login(String identifier, String password, Date expirationDate){ public String login(String identifier, String password, Date expirationDate){
User user = userService.getUser(identifier); User user = userService.getUser(identifier);
if (user == null){return null;} if (user == null){return null;}

View File

@ -51,10 +51,6 @@ public class CurriculumCourseService {
return toReturn; return toReturn;
} }
public Iterable<Curriculum> findCurriculumByCourses(Course course){
return curriculumCourseRepo.findCurriculumByCourses(course);
}
public Iterable<Map<String, Object>> getAllDepthCurriculum(){ public Iterable<Map<String, Object>> getAllDepthCurriculum(){
ArrayList<Map<String,Object>> toReturn = new ArrayList<>(); ArrayList<Map<String,Object>> toReturn = new ArrayList<>();

View File

@ -1,5 +1,6 @@
package ovh.herisson.Clyde.Services.Inscription; package ovh.herisson.Clyde.Services.Inscription;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import ovh.herisson.Clyde.Repositories.*; import ovh.herisson.Clyde.Repositories.*;
import ovh.herisson.Clyde.Repositories.Inscription.ExternalCurriculumRepository; import ovh.herisson.Clyde.Repositories.Inscription.ExternalCurriculumRepository;
@ -26,9 +27,9 @@ public class InscriptionService {
private final CurriculumRepository curriculumRepo; private final CurriculumRepository curriculumRepo;
private final MinervalRepository minervalRepository; private final MinervalRepository minervalRepository;
private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
private final ExternalCurriculumRepository externalCurriculumRepository; private final ExternalCurriculumRepository externalCurriculumRepository;
private final UserService userService; private final UserService userService;
public InscriptionService(InscriptionRepository inscriptionRepo, UserRepository userRepo, UserCurriculumRepository userCurriculumRepo, CurriculumRepository curriculumRepo, MinervalRepository minervalRepository, ExternalCurriculumRepository externalCurriculumRepository, UserService userService){ public InscriptionService(InscriptionRepository inscriptionRepo, UserRepository userRepo, UserCurriculumRepository userCurriculumRepo, CurriculumRepository curriculumRepo, MinervalRepository minervalRepository, ExternalCurriculumRepository externalCurriculumRepository, UserService userService){
this.inscriptionRepo = inscriptionRepo; this.inscriptionRepo = inscriptionRepo;
this.userRepo = userRepo; this.userRepo = userRepo;
@ -40,6 +41,7 @@ public class InscriptionService {
} }
public InscriptionRequest save(InscriptionRequest inscriptionRequest){ public InscriptionRequest save(InscriptionRequest inscriptionRequest){
inscriptionRequest.setPassword(passwordEncoder.encode(inscriptionRequest.getPassword()));
return inscriptionRepo.save(inscriptionRequest); return inscriptionRepo.save(inscriptionRequest);
} }

View File

@ -7,7 +7,10 @@ package ovh.herisson.Clyde.Services;
* @scope Extension Horaire * @scope Extension Horaire
******************************************************/ ******************************************************/
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import ovh.herisson.Clyde.Repositories.*; import ovh.herisson.Clyde.Repositories.CourseRepository;
import ovh.herisson.Clyde.Repositories.CurriculumCourseRepository;
import ovh.herisson.Clyde.Repositories.LessonRepository;
import ovh.herisson.Clyde.Repositories.UserCurriculumRepository;
import ovh.herisson.Clyde.Tables.*; import ovh.herisson.Clyde.Tables.*;
import java.util.ArrayList; import java.util.ArrayList;
@ -16,17 +19,12 @@ import java.util.Map;
@Service @Service
public class LessonService { public class LessonService {
private final LessonRepository lessonRepo; private final LessonRepository lessonRepo;
private final ScheduleLessonRepository scheduleLessonRepo;
private final UserCurriculumRepository userCurriculumRepo; private final UserCurriculumRepository userCurriculumRepo;
private final UserService userServ;
private final CourseRepository courseRepo; private final CourseRepository courseRepo;
private final CurriculumCourseRepository curriculumCourseRepo; private final CurriculumCourseRepository curriculumCourseRepo;
public LessonService(LessonRepository lessonRepo, ScheduleLessonRepository scheduleLessonRepo, UserCurriculumRepository userCurriculumRepo, UserService userServ, CourseRepository courseRepo, CurriculumCourseRepository curriculumCourseRepo){ public LessonService(LessonRepository lessonRepo, UserCurriculumRepository userCurriculumRepo, CourseRepository courseRepo, CurriculumCourseRepository curriculumCourseRepo){
this.lessonRepo = lessonRepo; this.lessonRepo = lessonRepo;
this.scheduleLessonRepo = scheduleLessonRepo;
this.userCurriculumRepo = userCurriculumRepo; this.userCurriculumRepo = userCurriculumRepo;
this.userServ = userServ;
this.courseRepo = courseRepo; this.courseRepo = courseRepo;
this.curriculumCourseRepo = curriculumCourseRepo; this.curriculumCourseRepo = curriculumCourseRepo;
} }
@ -138,12 +136,7 @@ public class LessonService {
break; break;
} }
} }
Lesson lesson = lessonRepo.save(target); lessonRepo.save(target);
ScheduleLesson scheduleLesson = scheduleLessonRepo.findByLesson(lesson);
Iterable<User> users = userCurriculumRepo.findUsersByCurriculum(scheduleLesson.getSchedule().getCurriculum());
for(User user: users){
userServ.Notify(user, new Notification("Course modified in the schedule", "Course Modified " + lesson.getCourse().getTitle() , "/#/schedule"));
}
return true; return true;
} }
/** /**

View File

@ -17,8 +17,6 @@ import org.springframework.stereotype.Service;
import com.fasterxml.jackson.databind.util.JSONPObject; import com.fasterxml.jackson.databind.util.JSONPObject;
import ovh.herisson.Clyde.Repositories.Msg.DiscussionRepository; import ovh.herisson.Clyde.Repositories.Msg.DiscussionRepository;
import ovh.herisson.Clyde.Services.UserService;
import ovh.herisson.Clyde.Tables.Notification;
import ovh.herisson.Clyde.Tables.User; import ovh.herisson.Clyde.Tables.User;
import ovh.herisson.Clyde.Tables.Msg.Discussion; import ovh.herisson.Clyde.Tables.Msg.Discussion;
import ovh.herisson.Clyde.Tables.Msg.Message; import ovh.herisson.Clyde.Tables.Msg.Message;
@ -28,8 +26,6 @@ public class DiscussionService {
@Autowired @Autowired
private DiscussionRepository discRepo; private DiscussionRepository discRepo;
@Autowired
private UserService userServ;
public Discussion create(String name, User author){ public Discussion create(String name, User author){
return discRepo.save(new Discussion(name, author)); return discRepo.save(new Discussion(name, author));
@ -46,9 +42,6 @@ public class DiscussionService {
* Create a message and link it to it's discussion * Create a message and link it to it's discussion
*/ */
public Discussion CreateMessage(Discussion disc, Message msg){ public Discussion CreateMessage(Discussion disc, Message msg){
for(User u: disc.getMembers()){
userServ.Notify(u, new Notification("msg.notification.new", msg.getContent(), "/#/msg"));
}
disc.addMessage(msg); disc.addMessage(msg);
return discRepo.save(disc); return discRepo.save(disc);
} }

View File

@ -6,9 +6,7 @@ import lombok.AllArgsConstructor;
import ovh.herisson.Clyde.Repositories.CourseRepository; import ovh.herisson.Clyde.Repositories.CourseRepository;
import ovh.herisson.Clyde.Repositories.Msg.ForumRepository; import ovh.herisson.Clyde.Repositories.Msg.ForumRepository;
import ovh.herisson.Clyde.Repositories.Msg.TopicRepository; import ovh.herisson.Clyde.Repositories.Msg.TopicRepository;
import ovh.herisson.Clyde.Services.UserService;
import ovh.herisson.Clyde.Tables.Course; import ovh.herisson.Clyde.Tables.Course;
import ovh.herisson.Clyde.Tables.Notification;
import ovh.herisson.Clyde.Tables.User; import ovh.herisson.Clyde.Tables.User;
import ovh.herisson.Clyde.Tables.Msg.Answer; import ovh.herisson.Clyde.Tables.Msg.Answer;
import ovh.herisson.Clyde.Tables.Msg.Forum; import ovh.herisson.Clyde.Tables.Msg.Forum;
@ -18,24 +16,17 @@ import ovh.herisson.Clyde.Tables.Msg.Topic;
@AllArgsConstructor @AllArgsConstructor
public class ForumService { public class ForumService {
private UserService userServ;
private CourseRepository courseRepo; private CourseRepository courseRepo;
private ForumRepository forumRepo; private ForumRepository forumRepo;
private TopicRepository topicRepo; private TopicRepository topicRepo;
public void createForum(Course c, Forum f){ public void createForum(Course c, Forum f){
c.addForum(f); c.addForum(f);
for (User u: f.getRegister()) {
userServ.Notify(u, new Notification("forum.notification.forum.new", f.getName(), "/#/Forum"));
}
courseRepo.save(c); courseRepo.save(c);
} }
public void createTopic(Forum f, Topic data) { public void createTopic(Forum f, Topic data) {
f.addTopic(data); f.addTopic(data);
for (User u: f.getRegister()) {
userServ.Notify(u, new Notification("forum.notification.topic.new", data.getSubject(), "/#/Forum"));
}
forumRepo.save(f); forumRepo.save(f);
} }

View File

@ -1,9 +0,0 @@
package ovh.herisson.Clyde.Services;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class NotificationService {
}

View File

@ -117,7 +117,6 @@ public class ProtectionService {
toReturn.put("identityCard", inscriptionRequest.getIdentityCard()); toReturn.put("identityCard", inscriptionRequest.getIdentityCard());
toReturn.put("submissionDate", inscriptionRequest.getSubmissionDate()); toReturn.put("submissionDate", inscriptionRequest.getSubmissionDate());
toReturn.put("equivalenceState", inscriptionRequest.getEquivalenceState()); toReturn.put("equivalenceState", inscriptionRequest.getEquivalenceState());
toReturn.put("admissionDocUrl", inscriptionRequest.getAdmissionDocUrl());
return toReturn; return toReturn;
} }

View File

@ -9,26 +9,22 @@ import org.springframework.stereotype.Service;
import ovh.herisson.Clyde.Repositories.LessonRepository; import ovh.herisson.Clyde.Repositories.LessonRepository;
import ovh.herisson.Clyde.Repositories.ScheduleLessonRepository; import ovh.herisson.Clyde.Repositories.ScheduleLessonRepository;
import ovh.herisson.Clyde.Repositories.ScheduleRepository; import ovh.herisson.Clyde.Repositories.ScheduleRepository;
import ovh.herisson.Clyde.Repositories.UserCurriculumRepository;
import ovh.herisson.Clyde.Tables.*; import ovh.herisson.Clyde.Tables.*;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Optional;
@Service @Service
public class ScheduleLessonService { public class ScheduleLessonService {
private final ScheduleLessonRepository scheduleLessonRepo; private final ScheduleLessonRepository scheduleLessonRepo;
private final UserCurriculumRepository userCurriculumRepo;
private final UserService userServ;
private final LessonRepository lessonRepo; private final LessonRepository lessonRepo;
private final ScheduleRepository scheduleRepo; private final ScheduleRepository scheduleRepo;
public ScheduleLessonService(ScheduleLessonRepository scheduleLessonRepo, UserCurriculumRepository userCurriculumRepo, UserService userServ, LessonRepository lessonRepo, ScheduleRepository scheduleRepo) { public ScheduleLessonService(ScheduleLessonRepository scheduleLessonRepo, LessonRepository lessonRepo, ScheduleRepository scheduleRepo) {
this.scheduleLessonRepo = scheduleLessonRepo; this.scheduleLessonRepo = scheduleLessonRepo;
this.userCurriculumRepo = userCurriculumRepo;
this.userServ = userServ;
this.lessonRepo = lessonRepo; this.lessonRepo = lessonRepo;
this.scheduleRepo = scheduleRepo; this.scheduleRepo = scheduleRepo;
} }
@ -36,22 +32,19 @@ public class ScheduleLessonService {
if(scheduleLesson == null) if(scheduleLesson == null)
return false; return false;
scheduleLessonRepo.save(scheduleLesson); scheduleLessonRepo.save(scheduleLesson);
Iterable<User> users = userCurriculumRepo.findUsersByCurriculum(scheduleLesson.getSchedule().getCurriculum());
for(User user: users){
userServ.Notify(user, new Notification("New course in the schedule", "Course added " + scheduleLesson.getLesson().getCourse().getTitle(), "/#/schedule"));
}
return true; return true;
} }
/** /**
* Save a lesson to all the schedule it is linked * Save a lesson to all the schedule it is linked
*/ */
public void saveToAllSchedule(Lesson lesson){ public boolean saveToAllSchedule(Lesson lesson){
Iterable<Schedule> schedules = scheduleRepo.findAllLessonSchedule(lesson.getCourse()); Iterable<Schedule> schedules = scheduleRepo.findAllLessonSchedule(lesson.getCourse());
if(schedules == null) if(schedules == null)
return; return false;
for (Schedule schedule : schedules){ for (Schedule schedule : schedules){
save(new ScheduleLesson(schedule, lesson)); save(new ScheduleLesson(schedule, lesson));
} }
return true;
} }
/** /**
* Delete a scheduleLesson via its lesson * Delete a scheduleLesson via its lesson
@ -59,11 +52,6 @@ public class ScheduleLessonService {
public boolean delete(long lessonId){ public boolean delete(long lessonId){
if(lessonId == 0) if(lessonId == 0)
return false; return false;
ScheduleLesson scheduleLesson = scheduleLessonRepo.findByLesson(lessonRepo.findById(lessonId));
Iterable<User> users = userCurriculumRepo.findUsersByCurriculum(scheduleLesson.getSchedule().getCurriculum());
for(User user: users){
userServ.Notify(user, new Notification("Course deleted in the schedule","Course deleted " + scheduleLesson.getLesson().getCourse().getTitle(), "/#/schedule"));
}
scheduleLessonRepo.delete(lessonRepo.findById(lessonId)); scheduleLessonRepo.delete(lessonRepo.findById(lessonId));
return true; return true;
} }

View File

@ -1,178 +0,0 @@
package ovh.herisson.Clyde.Services.ScientificPublications;
/******************************************************
* @file ResearchesService.java
* @author Bartha Maxime
* @scope Publications Scientifiques
*
* Service for managing researcher and researches
******************************************************/
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.Tables.Role;
import ovh.herisson.Clyde.Tables.ScientificPublications.*;
import ovh.herisson.Clyde.Tables.User;
import java.util.*;
@Service
@AllArgsConstructor
@SuppressWarnings("unchecked")
public class ResearchesService {
private final ResearcherRepository researcherRepo;
private final ResearchRepository articleRepo;
// researches Part
public Research getResearchById(long id) {
return articleRepo.findById(id);
}
public Research getResearchByUrl(String url) {
return articleRepo.findByPdfLocation(url);
}
public Iterable<Research> getResearchesByAuthor(long authorId){
Researcher researcher = researcherRepo.findById(authorId);
if (researcher == null) return null;
return researcherRepo.findAllByAuthorId(researcher);
}
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;
case "coAuthors":
Set<Researcher> set = new HashSet<>();
for (int id : (List<Integer>) entry.getValue()) {
Researcher r = researcherRepo.findById(id);
if (r != null){
set.add(r);
}
}
research.setCoAuthors(set);
break;
}
}
articleRepo.save(research);
}
public void deleteResearch(Research research) {
articleRepo.delete(research);
}
// Researchers Part
public Researcher getResearcherByUser(User user){
return researcherRepo.findByUser(user);
}
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) {
articleRepo.findAll();
for (Research r: articleRepo.findAll())
{
if (r.getCoAuthors().contains(researcher)){
r.getCoAuthors().remove(researcher);
articleRepo.save(r);
}
}
researcherRepo.delete(researcher);
}
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);
}
// Other stuff
public Research addView(Research research) {
research.setViews(research.getViews()+1);
return articleRepo.save(research);
}
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;
Researcher researcher = getResearcherByUser(user);
if (researcher !=null ){
if (research.getAuthor().getId() == researcher.getId())
return false;
for (Researcher coAuthor: research.getCoAuthors()){
if (coAuthor.getId() == researcher.getId())
return false;
}
}
return research.getAccess() != Access.Restricted || (user.getRole() != Role.Secretary &&
user.getRole() != Role.Teacher && user.getRole() != Role.InscriptionService);
// if the access is restricted only the staff member (above) can access the research
}
}

View File

@ -1,50 +0,0 @@
package ovh.herisson.Clyde.Services.ScientificPublications;
/******************************************************
* @file StatisticsService
* @author Bartha Maxime
* @scope Publications Scientifiques
*
* Service for managing statistics
******************************************************/
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import ovh.herisson.Clyde.Repositories.ScientificPublications.ResearchRepository;
import ovh.herisson.Clyde.Repositories.ScientificPublications.StatsRepository;
import ovh.herisson.Clyde.Tables.ScientificPublications.Research;
import ovh.herisson.Clyde.Tables.ScientificPublications.Researcher;
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(researcher.getId()));
toReturn.add(statsRepo.viewsByMonths(researcher.getId()));
toReturn.add(statsRepo.viewsByTopics(researcher.getId()));
toReturn.add(statsRepo.researchesByYears(researcher.getId()));
toReturn.add(statsRepo.researchesByMonth(researcher.getId()));
toReturn.add(statsRepo.researchesByTopics(researcher.getId()));
toReturn.add(statsRepo.languageByYears(researcher.getId()));
toReturn.add(statsRepo.languageByMonths(researcher.getId()));
toReturn.add(statsRepo.languageByTopics(researcher.getId()));
return toReturn;
}
}

View File

@ -51,8 +51,8 @@ public class TokenService {
ArrayList<Token> tokenList = tokenRepo.getByUserOrderByExpirationDate(token.getUser()); ArrayList<Token> tokenList = tokenRepo.getByUserOrderByExpirationDate(token.getUser());
while(tokenList.size() >= 5){ while(tokenList.size() >= 5){
tokenRepo.delete(tokenList.get(0)); tokenRepo.delete(tokenList.getFirst());
tokenList.remove(tokenList.get(0)); tokenList.remove(tokenList.getFirst());
} }
tokenRepo.save(token); tokenRepo.save(token);
} }

View File

@ -4,7 +4,6 @@ import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import ovh.herisson.Clyde.Tables.RegNoGenerator; import ovh.herisson.Clyde.Tables.RegNoGenerator;
import ovh.herisson.Clyde.Repositories.UserRepository; import ovh.herisson.Clyde.Repositories.UserRepository;
import ovh.herisson.Clyde.Tables.Notification;
import ovh.herisson.Clyde.Tables.Role; import ovh.herisson.Clyde.Tables.Role;
import ovh.herisson.Clyde.Tables.User; import ovh.herisson.Clyde.Tables.User;
import java.util.*; import java.util.*;
@ -45,55 +44,61 @@ public class UserService {
* @param targetId the id of the user to update * @param targetId the id of the user to update
* @return if the changes were done or not * @return if the changes were done or not
*/ */
public User modifyData(long targetId, Map<String ,Object> updates, User poster){ public boolean modifyData(long targetId, Map<String ,Object> updates, User poster){
User target = userRepo.findById(targetId); User target = userRepo.findById(targetId);
if (target == null) if (target == null)
return null; return false;
if (!target.getRegNo().equals(poster.getRegNo()) && !(poster.getRole() == Role.Secretary) && if (poster.getRegNo().equals(target.getRegNo())){
!(poster.getRole() == Role.Admin)) for (Map.Entry<String, Object> entry : updates.entrySet()){
return null;
for (Map.Entry<String, Object> entry : updates.entrySet()){ switch (entry.getKey()){
System.out.println(entry.getValue()); case "firstName":
switch (entry.getKey()){ target.setFirstName((String) entry.getValue());
case "firstName": break;
target.setFirstName((String) entry.getValue()); case "lastName":
break; target.setLastName((String) entry.getValue());
case "lastName": break;
target.setLastName((String) entry.getValue()); case "email":
break; target.setEmail((String) entry.getValue());
case "email": break;
target.setEmail((String) entry.getValue()); case "address":
break; target.setAddress((String) entry.getValue());
case "address": break;
target.setAddress((String) entry.getValue()); case "country":
break; target.setCountry((String) entry.getValue());
case "country": break;
target.setCountry((String) entry.getValue()); case "birthDate":
break; target.setBirthDate((Date) entry.getValue());
case "birthDate": break;
target.setBirthDate((Date) entry.getValue()); case "profilePictureUrl":
break; target.setProfilePictureUrl((String) entry.getValue());
case "profilePictureUrl": break;
target.setProfilePictureUrl((String) entry.getValue()); case "password":
break; target.setPassword(passwordEncoder.encode((String) entry.getValue()));
case "password": break;
target.setPassword((String) entry.getValue()); }
break; }
case "role": userRepo.save(target);
//a user can't change his own role return true;
if (poster.getRole()==Role.Secretary || poster.getRole() == Role.Admin){ }
Role wanted = Role.valueOf((String) entry.getValue()); // the secretary can change roles (for example if a student becomes a teacher)
if (wanted == Role.Admin && poster.getRole() != Role.Admin) else if (poster.getRole() == Role.Secretary)
return null; {
target.setRole(wanted); for (Map.Entry<String, Object> entry : updates.entrySet()){
}
if ( entry.getKey().equals("role")) {
if (entry.getValue() == Role.Admin) {return false;}
target.setRole((Role) entry.getValue());
userRepo.save(target);
return true;
}
} }
} }
userRepo.save(target); return false;
return target;
} }
@ -103,6 +108,7 @@ public class UserService {
public User save(User user){ public User save(User user){
RegNoGenerator.resetCount(); RegNoGenerator.resetCount();
user.setPassword(passwordEncoder.encode(user.getPassword()));
return userRepo.save(user); return userRepo.save(user);
} }
@ -133,10 +139,4 @@ public class UserService {
public void delete(User user) { public void delete(User user) {
userRepo.delete(user); userRepo.delete(user);
} }
public void Notify(User u, Notification n){
n.setUser(u);
u.getNotifications().add(n);
userRepo.save(u);
}
} }

View File

@ -8,6 +8,7 @@ public enum Applications {
// with any token // with any token
Profile, Profile,
// Students and higher authorization // Students and higher authorization
Msg, Msg,
Forum, Forum,
@ -26,13 +27,6 @@ public enum Applications {
// InscriptionService authorization // InscriptionService authorization
Requests, Requests,
// profile of a researcher StudentsList,
ResearcherProfile,
ManageResearcherProfile,
//the list of all researches (filterable)
ListResearches,
CreateUser,
StudentsList,
Payments Payments
} }

View File

@ -1,9 +1,6 @@
package ovh.herisson.Clyde.Tables.Inscription; package ovh.herisson.Clyde.Tables;
import jakarta.persistence.*; import jakarta.persistence.*;
import ovh.herisson.Clyde.Tables.Curriculum;
import ovh.herisson.Clyde.Tables.RequestState;
import ovh.herisson.Clyde.Tables.User;
import java.util.Date; import java.util.Date;

View File

@ -28,11 +28,10 @@ public class Course {
private User owner; private User owner;
//// Extension Messagerie ///// //// Extension Messagerie /////
@OneToMany(mappedBy = "course", cascade = CascadeType.ALL) @OneToMany(cascade = CascadeType.ALL)
private List<Forum> forums; private List<Forum> forums;
public void addForum(Forum f){ public void addForum(Forum f){
f.setCourse(this);
forums.add(f); forums.add(f);
} }
/////////////////////////////// ///////////////////////////////

View File

@ -3,8 +3,6 @@ package ovh.herisson.Clyde.Tables;
public enum FileType { public enum FileType {
ProfilePicture, ProfilePicture,
EducationCertificate, EducationCertificate,
Research,
ResearchBibTex,
JustificationDocument, JustificationDocument,
IdentityCard, IdentityCard,
} }

View File

@ -2,6 +2,8 @@ package ovh.herisson.Clyde.Tables.Inscription;
import jakarta.persistence.*; import jakarta.persistence.*;
import org.hibernate.annotations.OnDelete;
import org.hibernate.annotations.OnDeleteAction;
import ovh.herisson.Clyde.Tables.Course; import ovh.herisson.Clyde.Tables.Course;
import ovh.herisson.Clyde.Tables.RequestState; import ovh.herisson.Clyde.Tables.RequestState;
import ovh.herisson.Clyde.Tables.User; import ovh.herisson.Clyde.Tables.User;

View File

@ -7,6 +7,7 @@ import ovh.herisson.Clyde.Tables.RequestState;
import ovh.herisson.Clyde.Tables.User; import ovh.herisson.Clyde.Tables.User;
import java.util.Date; import java.util.Date;
import java.util.Map;
@Entity @Entity
public class ScholarshipRequest { public class ScholarshipRequest {

View File

@ -3,6 +3,7 @@ package ovh.herisson.Clyde.Tables.Inscription;
import jakarta.persistence.*; import jakarta.persistence.*;
import ovh.herisson.Clyde.Tables.Curriculum; import ovh.herisson.Clyde.Tables.Curriculum;
import ovh.herisson.Clyde.Tables.RequestState; import ovh.herisson.Clyde.Tables.RequestState;
import ovh.herisson.Clyde.Tables.User;
import java.util.Date; import java.util.Date;

View File

@ -2,8 +2,6 @@ package ovh.herisson.Clyde.Tables.Msg;
import java.util.List; import java.util.List;
import com.fasterxml.jackson.annotation.JsonIgnore;
import jakarta.persistence.*; import jakarta.persistence.*;
import lombok.Data; import lombok.Data;
import ovh.herisson.Clyde.Tables.Course; import ovh.herisson.Clyde.Tables.Course;
@ -18,7 +16,6 @@ public class Forum {
private int id; private int id;
@ManyToOne @ManyToOne
@JsonIgnore
private Course course; private Course course;
private String name; private String name;

View File

@ -1,53 +0,0 @@
package ovh.herisson.Clyde.Tables;
import java.util.Date;
import org.hibernate.annotations.CreationTimestamp;
import com.fasterxml.jackson.annotation.JsonIgnore;
import jakarta.annotation.Nullable;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.ManyToOne;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@Entity
public class Notification {
public enum Status {
Unread,
Read,
Archived
}
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String subject;
private String body;
private Status status = Status.Unread;
private String link;
@ManyToOne
@JsonIgnore
private User user;
@CreationTimestamp
private Date creation;
public Notification(String subject, @Nullable String body, @Nullable String link){
this.subject = subject;
this.body = body;
this.link = link;
}
}

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,79 +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;
import java.util.List;
import java.util.Set;
@Getter
@Setter
@NoArgsConstructor
@Entity
@Table(name = "Research")
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;
@ManyToMany(cascade = {CascadeType.MERGE})
@JoinTable(name = "ResearchCoAuhors",
joinColumns = @JoinColumn(name = "research_id"),
inverseJoinColumns = @JoinColumn(name = "researcher_id")
)
private Set<Researcher> coAuthors;
public Research(String title, Researcher author, Date releaseDate, PaperType paperType,
String pdfLocation, String bibTexLocation, String language, Access access, String domain, String summary,Set<Researcher> coauthors){
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;
this.coAuthors = coauthors;
}
}

View File

@ -1,40 +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 org.hibernate.annotations.OnDelete;
import ovh.herisson.Clyde.Tables.User;
@Getter
@Setter
@NoArgsConstructor
@Entity
@Table(name = "Researcher")
public class Researcher {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@OneToOne
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

@ -2,26 +2,18 @@ package ovh.herisson.Clyde.Tables;
import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnore;
import jakarta.persistence.*; import jakarta.persistence.*;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.OnDelete; import org.hibernate.annotations.OnDelete;
import org.hibernate.annotations.OnDeleteAction; import org.hibernate.annotations.OnDeleteAction;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.hibernate.annotations.GenericGenerator; import org.hibernate.annotations.GenericGenerator;
import ovh.herisson.Clyde.Tables.Msg.Discussion; import ovh.herisson.Clyde.Tables.Msg.Discussion;
import ovh.herisson.Clyde.Tables.Msg.Message; import ovh.herisson.Clyde.Tables.Msg.Message;
import ovh.herisson.Clyde.Tables.Notification.Status;
import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnore;
@Entity @Entity
@Table(name = "Users") @Table(name = "Users")
@NoArgsConstructor
@Data
public class User { public class User {
@Id @Id
@GenericGenerator(name = "userGen", type = ovh.herisson.Clyde.Tables.RegNoGenerator.class) @GenericGenerator(name = "userGen", type = ovh.herisson.Clyde.Tables.RegNoGenerator.class)
@ -40,21 +32,14 @@ public class User {
@JsonIgnore @JsonIgnore
private String password; private String password;
@JsonIgnore
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
private List<Notification> notifications = new ArrayList<>();
////// Extension Messagerie ///// ////// Extension Messagerie /////
@JsonIgnore
@OneToMany(mappedBy = "author", cascade = CascadeType.ALL) @OneToMany(mappedBy = "author", cascade = CascadeType.ALL)
private List<Message> msgs; private List<Message> msgs;
@JsonIgnore
@ManyToMany( mappedBy = "members" )
private List<Discussion> discussions;
///////////////////////////////// /////////////////////////////////
///////////////////////////////// @ManyToMany( mappedBy = "members" )
private List<Discussion> discussions;
public User(String lastName, String firstName, String email, String address, public User(String lastName, String firstName, String email, String address,
String country, Date birthDate, String profilePictureUrl, Role role, String password) String country, Date birthDate, String profilePictureUrl, Role role, String password)
{ {
@ -66,7 +51,7 @@ public class User {
this.birthDate = birthDate; this.birthDate = birthDate;
this.profilePictureUrl = profilePictureUrl; this.profilePictureUrl = profilePictureUrl;
this.role = role; this.role = role;
this.password = (new BCryptPasswordEncoder()).encode(password); this.password = password;
} }
@ -81,12 +66,88 @@ public class User {
this.country = country; this.country = country;
this.birthDate = birthDate; this.birthDate = birthDate;
this.profilePictureUrl = profilePictureUrl; this.profilePictureUrl = profilePictureUrl;
this.password = (new BCryptPasswordEncoder()).encode(password); this.password = password;
this.role = Role.Student; this.role = Role.Student;
this.identityCardUrl = identityCardUrl; this.identityCardUrl = identityCardUrl;
} }
public User() {}
public void setPassword(String password) { public Long getRegNo(){
this.password = (new BCryptPasswordEncoder()).encode(password); return this.regNo;
} }
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public Date getBirthDate() {
return birthDate;
}
public void setBirthDate(Date birthDate) {
this.birthDate = birthDate;
}
public String getProfilePictureUrl(){return this.profilePictureUrl;}
public void setProfilePictureUrl(String profilePictureUrl){
this.profilePictureUrl = profilePictureUrl;
}
public ovh.herisson.Clyde.Tables.Role getRole() {
return role;
}
public void setRole(ovh.herisson.Clyde.Tables.Role role) {
this.role = role;
}
public String getPassword(){
return password;
}
public void setPassword(String password) {
this.password = password;
}
public void setIdentityCardUrl(String identityCardUrl) {
this.identityCardUrl = identityCardUrl;
}
public String getIdentityCardUrl() {
return identityCardUrl;
}
} }

View File

@ -23,7 +23,6 @@ import ovh.herisson.Clyde.Repositories.TokenRepository;
import ovh.herisson.Clyde.Repositories.UserRepository; import ovh.herisson.Clyde.Repositories.UserRepository;
import ovh.herisson.Clyde.Responses.UnauthorizedResponse; import ovh.herisson.Clyde.Responses.UnauthorizedResponse;
import ovh.herisson.Clyde.Services.TokenService; import ovh.herisson.Clyde.Services.TokenService;
import ovh.herisson.Clyde.Services.UserService;
import ovh.herisson.Clyde.Tables.Role; import ovh.herisson.Clyde.Tables.Role;
import ovh.herisson.Clyde.Tables.Token; import ovh.herisson.Clyde.Tables.Token;
import ovh.herisson.Clyde.Tables.User; import ovh.herisson.Clyde.Tables.User;
@ -47,8 +46,7 @@ public class UserControllerTest {
@Autowired @Autowired
private TokenService tokenService; private TokenService tokenService;
@Autowired
private UserService userService;
@Autowired @Autowired
private UserRepository userRepository; private UserRepository userRepository;
@Autowired @Autowired
@ -74,7 +72,6 @@ public class UserControllerTest {
@BeforeEach @BeforeEach
void setup(){ void setup(){
RestAssured.baseURI = "http://localhost:" + port; RestAssured.baseURI = "http://localhost:" + port;
userRepository.deleteAll();
} }
@AfterEach @AfterEach
@ -87,7 +84,7 @@ public class UserControllerTest {
public void userPostTest(){ public void userPostTest(){
User god = new User("god","god","admin@admin.com","everywhere","every",new Date(0), null, Role.Admin,"goddoesntneedpassword"); 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()); Token godToken = new Token(god, tokenService.generateNewToken(), new Date());
userService.save(god); userRepository.save(god);
tokenService.saveToken(godToken); tokenService.saveToken(godToken);
//Can god post herobrine himself ? //Can god post herobrine himself ?

View File

@ -70,7 +70,7 @@ class TokenServiceTest {
ArrayList<Token> tokenList = new ArrayList<>(); ArrayList<Token> tokenList = new ArrayList<>();
GregorianCalendar gc = new GregorianCalendar(); GregorianCalendar gc = new GregorianCalendar();
User malveillant = new User("Cargo", "John", "CargoJ@mail.com", "secret", "secret", new Date(), null, "secret", null); User malveillant = new User("Cargo", "John", "CargoJ@mail.com", "secret", "secret", null, null, null, "secret");
userRepository.save(malveillant); userRepository.save(malveillant);
for (int i = 0; i < 20; i++){ for (int i = 0; i < 20; i++){

View File

@ -8,8 +8,6 @@
"name": "clyde", "name": "clyde",
"version": "0.0.0", "version": "0.0.0",
"dependencies": { "dependencies": {
"@canvasjs/vue-charts": "^1.0.4",
"@vueuse/core": "^10.9.0",
"vite-plugin-top-level-await": "^1.4.1", "vite-plugin-top-level-await": "^1.4.1",
"vue": "^3.4.15", "vue": "^3.4.15",
"vue3-toastify": "^0.2.1" "vue3-toastify": "^0.2.1"
@ -31,20 +29,6 @@
"node": ">=6.0.0" "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": { "node_modules/@esbuild/aix-ppc64": {
"version": "0.19.12", "version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz", "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", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
"integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" "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": { "node_modules/@vitejs/plugin-vue": {
"version": "5.0.4", "version": "5.0.4",
"resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.0.4.tgz", "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", "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.19.tgz",
"integrity": "sha512-/KliRRHMF6LoiThEy+4c1Z4KB/gbPrGjWwJR+crg2otgrf/egKzRaCPvJ51S5oetgsgXLfc4Rm5ZgrKHZrtMSw==" "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": { "node_modules/agent-base": {
"version": "7.1.0", "version": "7.1.0",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz",

View File

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

View File

@ -36,9 +36,6 @@ app.language=Language
app.manage.profile=Manage profile app.manage.profile=Manage profile
app.studentList=Students List app.studentList=Students List
app.users=Users app.users=Users
app.manage.researcherProfile=Manage researcher profile
app.list.researches=List researches
app.Create.User=Create User
app.manageOwnLessons=Manage Owned Courses Schedule app.manageOwnLessons=Manage Owned Courses Schedule
app.lessonRequests=Schedule Requests app.lessonRequests=Schedule Requests
app.payments=Payments app.payments=Payments
@ -50,7 +47,6 @@ Delete=Delete
Modify=Modify Modify=Modify
Create=Créer Create=Créer
requestType=Request Type requestType=Request Type
lessonType=Course Type
day=Day day=Day
start=Start start=Start
end=End end=End
@ -109,7 +105,6 @@ courses.modify=Modify
courses.toDelete=Course to Delete courses.toDelete=Course to Delete
courses.confirm=Confirm courses.confirm=Confirm
courses.back=Back courses.back=Back
courses.AddToCurriculum=Add to a new Curriculum
profile.modify.data=Modify personnal data profile.modify.data=Modify personnal data
profile.reRegister=Re-register profile.reRegister=Re-register
profile.unRegister=Unregister profile.unRegister=Unregister
@ -125,87 +120,9 @@ Curriculum=curriculum
Credits=Credits Credits=Credits
InscriptionService=I.S. InscriptionService=I.S.
faculty=Faculty faculty=Faculty
Year=Year
Access=Access
Access.Restricted=Restricted
Access.OpenSource=OpenSource
Access.Private=Private
Language=Language
Month=Month
Month.01=january
Month.02=february
Month.03=march
Month.04=april
Month.05=may
Month.06=june
Month.07=july
Month.08=august
Month.09=september
Month.10=october
Month.11=november
Month.12=december
Domain=Domain
PaperType=PaperType
Submit=Submit
Search.Researches=Search For Researches
Search.Researchers=Search For Researchers
Filters=Filters
Toggle.Researcher=Toggle Researcher Search
Untoggle.Researcher=Toggle Research Search
MoreInfo=More Info
Modify.Research=Modify Research
To.Change.In.Options=To change in regular account options
Modify.Data=Modify Data
Confirm.Changes=Confirm Changes
Cancel.Changes=Cancel Changes
Post.Research=Post a new Research
Summary=Summary
Title=Title
Views=Number of Views
See.Research=See Research
SeeBibTex=See BibTex
Author=Author
CoAuthors=Co-Authors
ReleaseDate=ReleaseDate
Article.Id=Article Id
Delete.Research=Delete Research
Here=Here
Stat.Type=Stat Type
Researches=Researches
Please.Select.Option=Please Select an Option
Class.By=Class By
PaperType.Article=Article
PaperType.Book=Book
PaperType.Book.Chapter=Book Chapter
PaperType.Paper=Paper
Research.Pdf=Research Pdf
BibTex.Pdf=BibTex Pdf
CoAuthors.List=Co-Author List
Confirm.Publish=Confirm Publishing
Cancel.Publish=Cancel Publishing
Years=Years
Months=Months
By=By
RegNo=RegNo
Address=Address
Country=Country
BirthDate=Birth Date
Researcher.Delete=Delete Researcher Profile
Researcher.Add=Create Researcher Profile
Confirm=Confirm
Cancel=Cancel
LastName=Last Name
FirstName=First Name
Profile.Picture=Profile Picture
Role=Role
Password=Password
Create.User=Create User
msg.notification.new=You have a new message
forum.create=Create forum forum.create=Create forum
forum.create.name=New forum's name forum.create.name=New forum's name
forum.post.create.name=New post's title forum.post.create.name=New post's title
forum.notification.topic.new=New topic created
forum.notification.forum.new=New Forum created
firstname/name=Firstname/Name firstname/name=Firstname/Name
regNo=regNo regNo=regNo
From=From From=From
@ -285,9 +202,8 @@ rereg=Reregister in the next year of one of my cursus
reregsup=Register in a supplementary cursus reregsup=Register in a supplementary cursus
chcur=Change from a cursus to another chcur=Change from a cursus to another
iwouldlike=I would like to : iwouldlike=I would like to :
newcurr=Actual curriculums newcurr=New curriculum
cursusprereq=The cursus you selected has some prerequisites ensure that your external curriculum data is updated in your profile cursusprereq=The cursus you selected has some prerequisites ensure that your external curriculum data is updated in your profile
imposecurriculum=Impose a curriculum imposecurriculum=Impose a curriculum
impose=Impose impose=Impose
gotimposed=The selected curriculum has been imposed gotimposed=The selected curriculum has been imposed
DifferentLanguage=Different Languages

View File

@ -36,9 +36,6 @@ app.language=Langue
app.manage.profile=Gérer le profil app.manage.profile=Gérer le profil
app.studentList=Liste des étudiants app.studentList=Liste des étudiants
app.users=Utilisateurs app.users=Utilisateurs
app.manage.researcherProfile= gérer son profil de chercheur
app.list.researches=Lister les recherches
app.Create.User=créer un utilisateur
app.manageOwnLessons=Gérer ses horaires de cours app.manageOwnLessons=Gérer ses horaires de cours
app.lessonRequests=Requêtes d'horaire app.lessonRequests=Requêtes d'horaire
app.payments=Payements app.payments=Payements
@ -50,7 +47,6 @@ Delete=Supprimer
Modify=Modifier Modify=Modifier
Create=Créer Create=Créer
requestType=Type de Requête requestType=Type de Requête
lessonType=Type de cours
day=Jour day=Jour
start=Début start=Début
end=Fin end=Fin
@ -109,7 +105,6 @@ courses.modify=Modifier
courses.toDelete=Cours à supprimer courses.toDelete=Cours à supprimer
courses.confirm=Confirmer courses.confirm=Confirmer
courses.back=Retour courses.back=Retour
courses.AddToCurriculum=Ajouter à un cursus
profile.modify.data=Modifier données personnelles profile.modify.data=Modifier données personnelles
profile.reRegister=Réinsciption profile.reRegister=Réinsciption
profile.unRegister=Désinscription profile.unRegister=Désinscription
@ -125,85 +120,9 @@ Curriculum=Cursus
Credits=Credits Credits=Credits
InscriptionService=S.I. InscriptionService=S.I.
faculty=Faculté faculty=Faculté
Year=Année
Access=Accès
Access.Restricted=Restreint
Access.OpenSource=Libre
Access.Private=Privé
Language=Langue
Month=Mois
Month.01=janvier
Month.02=fevrier
Month.03=mars
Month.04=avril
Month.05=mai
Month.06=juin
Month.07=juillet
Month.08=août
Month.09=septembre
Month.10=octobre
Month.11=novembre
Month.12=decembre
Domain=Domaine
PaperType=Type de recherche
Submit=Envoyer
Search.Researches=Chercher Par Recherche
Search.Researchers=Chercher Par Chercheur
Filters=Filtres
Toggle.Researcher=Activer la recherche par chercheur
Untoggle.Researcher=Désactiver la recherche par chercheur
MoreInfo=Plus d'info
Modify.Research=Modifer l'article
To.Change.In.Options=À changer dans les options
Modify.Data=Modifier
Confirm.Changes=Confirmer les Changements
Cancel.Changes=Abandonner les Changements
Post.Research=Poster un nouvel article
Summary=Résumé
Title=Titre
Views=Nombre de Vues
See.Research=Ouvrir l'article
SeeBibTex=Ouvrir le BibTex
Author=Autheur
CoAuthors=Co-Autheurs
ReleaseDate=Date de Parution
Article.Id=Id de l'article
Delete.Research=Supprimer l'article
Here=Ici
Stat.Type=Type de Stat
Researches=Recherches
Please.Select.Option=Selectionnez des Options
Class.By=Classifer Par
PaperType.Article=Article
PaperType.Book=Livre
PaperType.Book.Chapter=Chapitre de Livre
PaperType.Paper=Papier
Research.Pdf=Pdf de la Recherche
BibTex.Pdf=BibTex de la Recherche
CoAuthors.List=Liste des Co-Autheurs
Confirm.Publish=Confirmer la Publication
Cancel.Publish=Annuler la Publication
Years=Années
Months=Mois
By=par
RegNo=Matricule
Address=Adresse
Country=Pays
BirthDate=Date de Naissance
Confirm=Confirmer
Cancel=Annuler
LastName=Nom de Famille
FirstName=Prénom
Profile.Picture=Photo de Profil
Role=Role
Password=Mot de Passe
Create.User=Créer l'utilisateur
msg.notification.new=Vous avez un nouveau message!
forum.create=Créer un forum forum.create=Créer un forum
forum.create.name=Nom du forum forum.create.name=Nom du forum
forum.post.create.name=Titre du post forum.post.create.name=Titre du post
forum.notification.topic.new=Nouveau Topic crée
forum.notification.forum.new=Nouveau forum crée
firstname/name=Prénom/Nom firstname/name=Prénom/Nom
regNo=Matricule regNo=Matricule
From=De From=De
@ -283,9 +202,8 @@ rereg=Me réinscrire dans l'année supérieure
reregsup=M'inscrire dans un cursus supplémentaire reregsup=M'inscrire dans un cursus supplémentaire
chcur=Changer d'un cursus vers un autre chcur=Changer d'un cursus vers un autre
iwouldlike=Je voudrais : iwouldlike=Je voudrais :
newcurr=Cursus actuels newcurr=Nouveau cursus
cursusprereq=Le cursus que vous avez selectionné a des prérequis assurez vous que votre dossier de parcours est a jour dans votre profil cursusprereq=Le cursus que vous avez selectionné a des prérequis assurez vous que votre dossier de parcours est a jour dans votre profil
imposecurriculum=Imposer un cursusgotimposed imposecurriculum=Imposer un cursusgotimposed
impose=Imposer impose=Imposer
gotimposed=Le cursus selectionné a été imposé gotimposed=Le cursus selectionné a été imposé
DifferentLanguage=Langues différentes

View File

@ -1,24 +1,18 @@
<script setup> <script setup>
import { toast } from 'vue3-toastify';
import { ref } from 'vue' import { ref } from 'vue'
import i18n, { setLang } from './i18n.js' import i18n, { setLang } from './i18n.js'
import { isLogged, getSelf } from '@/rest/Users.js' import { isLogged } from '@/rest/Users.js'
import { notifications, fetchNotifications, archiveNotification } from '@/rest/notifications.js'
import {postMock} from "@/rest/restConsumer.js";
import { appList, currentView } from '@/rest/apps.js' import { appList, currentView } from '@/rest/apps.js'
var prevURL; var prevURL;
var currentURL = window.location.hash; var currentURL = window.location.hash;
postMock()
window.onhashchange = function() { window.onhashchange = function() {
prevURL = currentURL; prevURL = currentURL;
currentURL = window.location.hash; currentURL = window.location.hash;
} }
const Logged = ref(isLogged()); const Logged = ref(isLogged());
const user = ref();
if(Logged.value){
fetchNotifications();
getSelf().then(e => user.value = e);
}
window.addEventListener('hashchange', () => { window.addEventListener('hashchange', () => {
if((location.hash === "#/home" && prevURL === "#/login") || (location.hash === "#/home" && prevURL === "#/profil")){ if((location.hash === "#/home" && prevURL === "#/login") || (location.hash === "#/home" && prevURL === "#/profil")){
@ -26,10 +20,10 @@ window.addEventListener('hashchange', () => {
} }
}); });
const home=ref(i18n("app.home")) const home=ref(i18n("app.home"))
const notifications=ref(i18n("app.notifications"))
const settings=ref(i18n("app.settings")) const settings=ref(i18n("app.settings"))
const login=ref(i18n("app.login")) const login=ref(i18n("app.login"))
const active=ref(false) const active=ref(false)
const notification = ref(false)
const apps = ref([]) const apps = ref([])
appList().then(e => apps.value = e) appList().then(e => apps.value = e)
@ -41,7 +35,7 @@ window.addEventListener('hashchange', () => {
<div class="topBar"> <div class="topBar">
<ul class="horizontal"> <ul class="horizontal">
<li title=home> <li title=home>
<a class="icon" href="#home"> <a class="icon" href="#home">
<img class="clyde" src="/Clyde.png" style="width: 40px; height: auto; margin-top:4px"> <img class="clyde" src="/Clyde.png" style="width: 40px; height: auto; margin-top:4px">
</a></li> </a></li>
<li title=home> <li title=home>
@ -50,17 +44,14 @@ window.addEventListener('hashchange', () => {
</a></li> </a></li>
<li style="float: right;" title=login> <li style="float: right;" title=login>
<a class="icon" href="#/login"> <a class="icon" href="#/login">
<div class="fa-solid fa-user" :style="Logged ? 'color: red' : ''" style="margin-top: 7px; margin-bottom: 3px; "></div> <div class="fa-solid fa-user" :style="Logged ? 'color: orange' : 'haha'" style="margin-top: 7px; margin-bottom: 3px; "></div>
</a></li> </a></li>
<li style="float: right;" title=notifications @click="notification = !notification"> <li style="float: right;" title=notifications>
<a class="icon"> <a class="icon" href="#Notifications">
<div class="fa-solid fa-bell" :style="notifications.length != 0 ? 'color:orange': '' " style="margin-top: 7px; margin-bottom: 3px;"></div> <div class="fa-solid fa-bell" style="margin-top: 7px; margin-bottom: 3px;"></div>
<ul v-if=notification id="notification">
<li v-for="notif in notifications" @click="archiveNotification(notif.id)"> {{ i18n(notif.subject) }} - {{ notif.body }}</li>
</ul>
</a></li> </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"> <a class="icon" >
<div class="fa-solid fa-gear" style="margin-top: 7px; margin-bottom: 3px;"></div> <div class="fa-solid fa-gear" style="margin-top: 7px; margin-bottom: 3px;"></div>
<div v-if="active" class="dropdown"> <div v-if="active" class="dropdown">
<div class="dropdown-content">{{i18n("app.language")}}</div> <div class="dropdown-content">{{i18n("app.language")}}</div>
@ -76,7 +67,6 @@ window.addEventListener('hashchange', () => {
{{i18n("app.manage.profile")}} {{i18n("app.manage.profile")}}
</a> </a>
</div> </div>
<span v-if=Logged>RegNo - {{ user.regNo }}</span>
</div> </div>
</a></li> </a></li>
</ul> </ul>
@ -135,12 +125,10 @@ window.addEventListener('hashchange', () => {
.dropdown { .dropdown {
color:black;
margin-top:55px; margin-top:55px;
width:160px; width:160px;
display: inline-block; display: inline-block;
/* height:110px; */ height:110px;
text-align: center;
font-size: 13px; font-size: 13px;
position: absolute; position: absolute;
z-index: 1; z-index: 1;
@ -166,14 +154,14 @@ window.addEventListener('hashchange', () => {
margin-top: var(--header-size); margin-top: var(--header-size);
top:0; top:0;
left:0; left:0;
padding: 25px 0; padding: 25px 0 0;
width: 70px ; width: 70px ;
background-color: rgb(53, 53, 53); background-color: rgb(53, 53, 53);
border-right:5px; border-right:5px;
border-color:black; border-color:black;
height: calc( 95% - var(--header-size) ) ; height: 100%;
position: fixed; position: fixed;
overflow: scroll; overflow:;
transition-duration: .3s; transition-duration: .3s;
} }
@ -227,6 +215,8 @@ window.addEventListener('hashchange', () => {
background-color: black; background-color: black;
border-radius:6px; border-radius:6px;
color:white; color:white;
transform: translate(0px ,1px);
} }
ul.vertical:hover { ul.vertical:hover {
@ -241,7 +231,8 @@ window.addEventListener('hashchange', () => {
.text { .text {
right: 0%; right: 0%;
width: 0%; width: 0%;
display:none; visibility: collapse;
opacity: 0;
color: white; color: white;
font-size: 1.2em; font-size: 1.2em;
font-weight: 600; font-weight: 600;
@ -250,7 +241,7 @@ window.addEventListener('hashchange', () => {
ul.vertical:hover .text { ul.vertical:hover .text {
opacity:1; opacity:1;
display: inline; visibility:visible;
width: 60%; width: 60%;
transition-duration: .3s; transition-duration: .3s;
padding-left: 15px; padding-left: 15px;
@ -259,32 +250,6 @@ window.addEventListener('hashchange', () => {
.clyde:hover{ .clyde:hover{
content: url("./assets/angry_clyde.png") content: url("./assets/angry_clyde.png")
} }
#notification{
position: absolute;
top: 61px;
right: 0;
background-color: white;
width: 300px;
height: 600px;
border-radius: 10px;
margin: 10px;
}
#notification > li{
color: black;
list-style: none;
font-size: 0.4em;
display: block;
background-color: #00FF00A0;
margin: 1px;
border-radius: 42px;
padding: 10px;
}
#notification > li:hover{
background-color: #00FF0000
}
</style> </style>

View File

@ -1,215 +0,0 @@
<script setup>
import i18n from "../i18n.js";
import {ref} from "vue";
import {fetchAllResearchers} from "@/rest/ScientificPublications/ManageResearch.js";
import {deleteResearcher, postResearcher} from "@/rest/ScientificPublications/ResearcherProfile.js";
import {patchUser} from "@/rest/Users.js";
const props = defineProps(['user'])
const modifying =ref(false)
const toModify = Object.assign({},{})
const toCreate = Object.assign({},{})
const allResearcher = ref( await fetchAllResearchers())
const researcher = ref()
const user = ref(props.user)
const isResearcher = ref(false)
const creating = ref(false)
for (let i = 0; i < allResearcher.value.length; i++) {
if (user.value.regNo === allResearcher.value[i].user.regNo){
researcher.value = allResearcher.value[i]
isResearcher.value = true
}
}
function getPP(){
if(user.value.profilePictureUrl === null){
return "/Clyde.png"
}
return user.value.profilePictureUrl
}
async function createResearcher(){
toCreate.user = user.value
await postResearcher(toCreate)
creating.value = false
allResearcher.value = await fetchAllResearchers()
for (let i = 0; i < allResearcher.value.length; i++) {
if (user.value.regNo === allResearcher.value[i].user.regNo){
researcher.value = allResearcher.value[i]
isResearcher.value = true
}
}
toCreate.value = Object.assign({},{})
}
async function deleteResearcherById(){
isResearcher.value = false
await deleteResearcher(researcher.value.id)
allResearcher.value = await fetchAllResearchers()
}
async function modify(){
if (modifying.value){
user.value = await patchUser(user.value.regNo, toModify)
}
modifying.value =!modifying.value
}
</script>
<template>
<div class="body">
<div class="container">
<div class="profilPic">
<img class="subContainer" :src=getPP()>
</div>
<div class = "globalInfos">
<div class="infosContainer">
<div>
{{i18n("RegNo")}} : {{user.regNo}}
</div>
<div>
{{i18n("name")}} : {{user.firstName}} {{user.lastName}}
</div>
<div>
Role :
<span v-if="!modifying"> {{i18n(user.role)}}</span>
<select v-else v-model="toModify.role">
<option value="Student">{{i18n("Student")}}</option>
<option value="Teacher">{{i18n("Teacher")}}</option>
<option value="Secretary">{{i18n("Secretary")}}</option>
<option value="InscriptionService">{{i18n("InscriptionService")}}</option>
</select>
</div>
<div>
E-mail: {{user.email}}
</div>
<div>
{{i18n("Address")}} :
<span v-if="!modifying"> {{user.address}}</span>
<input v-else type="text" v-model="toModify.address">
</div>
<div>
{{i18n("Country")}} : {{user.country}}
</div>
<div>
{{i18n("BirthDate")}} : {{user.birthDate.split("T")[0]}}
</div>
</div>
</div>
<div></div>
<button id="ModifyButton" @click="modify"> {{i18n("Modify.Data")}}</button>
<div></div>
<div>
<button v-if="isResearcher" id="deleteButton" @click="deleteResearcherById"> {{i18n("Researcher.Delete")}}</button>
<button v-else id="createButton" @click="creating = !creating"> {{i18n("Researcher.Add")}}</button>
</div>
<div v-if="creating">
<button id="createButton" @click="createResearcher"> {{i18n("Confirm")}}</button>
<button id="deleteButton" @click="creating = !creating"> {{i18n("Cancel")}}</button>
</div>
<div v-if="creating" style="color: white">
<ul>
<li>
Orcid :
<input type="text" v-model="toCreate.orcid"></li>
<li>
Site :
<input type="text" v-model="toCreate.site"></li>
<li>
{{i18n("Domain")}} :
<input type="text" v-model="toCreate.domain"></li>
</ul>
</div>
</div>
</div>
</template>
<style scoped>
#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)
}
.container{
margin-top: 25px;
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";
}
.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-right: auto;
margin-left: auto;
}
.subContainer{
width:100%;
background-color:rgb(50,50,50);
border-radius:20px;
border:4px solid black;
}
.infosContainer {
border:2px solid black;
font-size:23px;
color:white;
background-color:rgb(50,50,50);
border-radius:10px;
}
#deleteButton{
align-self: center;
text-align: center;
border: 2px solid black;
color: white;
font-size: x-large;
background-color: red;
border-radius: 20px;
}
#deleteButton:hover{
background: #ff2d55;
}
#createButton{
align-self: center;
text-align: center;
border: 2px solid black;
color: white;
font-size: x-large;
background-color: #07bc0c;
border-radius: 20px
}
#createButton:hover{
background: #4cd964;
}
</style>

View File

@ -1,117 +0,0 @@
<script setup>
import i18n from "@/i18n.js";
import {uploadProfilePicture} from "@/rest/uploads.js";
import {postUser} from "@/rest/Users.js";
import {ref} from "vue";
let toCreate = Object.assign({},{})
const today = new Date()
const date = today.getFullYear() +"-" + ("0" + (today.getMonth()+1)).slice(-2) + "-" + ("0" + today.getDate()).slice(-2);
async function createUser(){
if (toCreate.lastName === null || toCreate.birthDate === null || toCreate.firstName === null ||
toCreate.email === null || toCreate.address === null || toCreate.role === null || toCreate.password === null)
return
await postUser(toCreate)
toCreate = Object.assign({},{})
}
async function getProfilePic(data){
const pp= await uploadProfilePicture(data)
toCreate.profilePictureUrl = pp.url
}
</script>
<template>
<div class="body">
<div class="container">
<div class = "globalInfos">
<div class="infosContainer">
<ul>
<li>{{i18n("LastName")}} : <input type="text" v-model="toCreate.lastName"></li>
<li>{{i18n("FirstName")}} : <input type="text" v-model="toCreate.firstName"></li>
<li> E-mail : <input type="text" v-model="toCreate.email"></li>
<li>{{i18n("Country")}} : <input type="text" v-model="toCreate.country"></li>
<li>{{i18n("Address")}} : <input type="text" v-model="toCreate.address"></li>
<li>{{i18n("BirthDate")}} : <input type="date" min="1924-01-01" :max="date" v-model="toCreate.birthDate"></li>
<li>{{i18n("Profile.Picture")}} :
<input type="file" @change="getProfilePic($event.target.files);" accept="image/*">
</li>
<li>{{i18n("Role")}} :
<select v-model="toCreate.role">
<option value="Student">{{i18n("Student")}}</option>
<option value="Teacher">{{i18n("Teacher")}}</option>
<option value="Secretary">{{i18n("Secretary")}}</option>
<option value="InscriptionService">{{i18n("InscriptionService")}}</option>
</select>
</li>
<li>{{i18n("Password")}} : <input type="password" v-model="toCreate.password"></li>
</ul>
<div style="text-align: end"> <button id="createButton" @click="createUser"> {{i18n("Create.User")}}</button></div>
</div>
</div>
</div>
</div>
</template>
<style scoped>
.container{
margin-top: 25px;
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";
}
.globalInfos {
grid-area:globalInfos;
align-self :center;
}
.body {
min-width:960px;
width:100%;
display:flex;
align-items:center;
justify-content:center;
margin-top:5%;
}
.infosContainer {
border:2px solid black;
font-size:23px;
color:white;
background-color:rgb(50,50,50);
border-radius:10px;
}
#createButton{
align-self: center;
text-align: center;
border: 2px solid black;
color: white;
font-size: x-large;
background-color: #07bc0c;
border-radius: 20px
}
#createButton:hover{
background: #4cd964;
}
</style>

View File

@ -15,7 +15,7 @@ import { fetchedPost, fetchPost, sendAnswer } from '@/rest/forum.js'
import { getSelf } from '@/rest/Users.js' import { getSelf } from '@/rest/Users.js'
const Role = (await getSelf()).role; const Role = (await getSelf()).role;
const courses = Role === 'Admin' || Role === 'Secretary' || Role === 'Teacher' ? await reactive(getCourses(Role)) : await reactive(getUserActualCourses()); const courses = Role === 'Admin' || Role === 'Secretary' ? await reactive(getCourses()) : await reactive(getUserActualCourses());
const selectedCourse = ref(); const selectedCourse = ref();
const selectedForum = ref(); const selectedForum = ref();

View File

@ -51,12 +51,12 @@ async function editChangeCurrReqTeacherApproval(state){
<div> <div>
<button @click="localwindowstate++"> {{ i18n("seeprofile") }} </button> <button @click="localwindowstate++"> {{ i18n("seeprofile") }} </button>
</div> </div>
<div v-if="user.role === 'InscriptionService' || user.role==='Admin'"> <div>
<button v-if="req.state === 'Pending'" @click="req.state='Accepted';uploadandrefreshChangeRequest('Accepted')">{{ i18n("request.accept") }}</button> <button v-if="req.state === 'Pending'" @click="req.state='Accepted';uploadandrefreshChangeRequest('Accepted')">{{ i18n("request.accept") }}</button>
<button v-if="req.state === 'Pending'" @click="req.state='Refused';uploadandrefreshChangeRequest('Refused')" style="margin-left: 2%;">{{i18n("request.refuse")}}</button> <button v-if="req.state === 'Pending'" @click="req.state='Refused';uploadandrefreshChangeRequest('Refused')" style="margin-left: 2%;">{{i18n("request.refuse")}}</button>
</div> </div>
<div v-if="user.role === 'Teacher' || user.role === 'Admin'"> <div v-if="user.role === 'Teacher' || user.role === 'Admin'">
<button v-if="req.teacherApprovalState === 'Pending'" @click="req.teacherApprovalState='Accepted';editChangeCurrReqTeacherApproval('Accepted')" style="margin-right: 2%">{{i18n("acceptequiv")}}</button> <button v-if="req.teacherApprovalState === 'Pending'" @click="req.teacherApprovalState='Accepted';editChangeCurrReqTeacherApproval('Accepted')">{{i18n("acceptequiv")}}</button>
<button v-if="req.teacherApprovalState === 'Pending'" @click="req.teacherApprovalState='Refused';editChangeCurrReqTeacherApproval('Refused')">{{i18n("refuseequiv")}}</button> <button v-if="req.teacherApprovalState === 'Pending'" @click="req.teacherApprovalState='Refused';editChangeCurrReqTeacherApproval('Refused')">{{i18n("refuseequiv")}}</button>
</div> </div>
</div> </div>

View File

@ -58,17 +58,17 @@ async function refreshCursus(){
{{ i18n("login.guest.country") }} : {{request.country}} {{ i18n("login.guest.country") }} : {{request.country}}
</div> </div>
<div> <div>
{{ i18n("login.guest.birthday") }} : {{request.birthDate.slice(0,10)}} {{ i18n("login.guest.birthday") }} : {{request.birthDate}}
</div> </div>
<div> <div>
{{ i18n("WantedCursus") }} : BAB {{cursus.year}} {{cursus.option}} {{ i18n("WantedCursus") }} : BAB {{cursus.year}} {{cursus.option}}
</div> </div>
<div style="margin-top: 3%"> <div style="margin-top: 3%">
<button><a :href="request.identityCard">{{ i18n("dlidentitycard") }}</a></button> <button><a :href="request.identityCard">{{ i18n("dlidentitycard") }}</a></button>
<button style="margin-left: 3%" v-if="request.admissionDocUrl != null"><a :href="request.admissionDocUrl">{{ i18n("dladmissiondoc") }}</a></button> <button v-if="request.admissionDocUrl != null"><a :href="request.admissionDocUrl">{{ i18n("dladmissiondoc") }}</a></button>
</div> </div>
<div> <div v-if="externalCurriculum.length !== 0">
<button style="background-color:rgb(105,05,105);margin-top: 3%" @click="list=!list" v-if="(user.role === 'Teacher' || user.role === 'Admin')">{{ i18n("seeextcur") }}</button> <button style="background-color:rgb(105,05,105);margin-top: 3%" @click="list=!list" v-if="(user.role == 'Teacher' || user.role == 'Admin')">{{ i18n("seeextcur") }}</button>
</div> </div>
</div> </div>
</div> </div>

View File

@ -32,9 +32,6 @@
<div> <div>
{{ i18n("firstname/name") }} : {{user.firstName}} {{user.lastName}} {{ i18n("firstname/name") }} : {{user.firstName}} {{user.lastName}}
</div> </div>
<div>
{{ i18n("regNo") }} : {{user.regNo}}
</div>
<div> <div>
{{ i18n("login.guest.email") }}: {{user.email}} {{ i18n("login.guest.email") }}: {{user.email}}
</div> </div>

View File

@ -80,7 +80,7 @@ function isExempted(course){
</div> </div>
</div> </div>
<div v-if="list === false"> <div v-if="list === false">
<button @click="list=!list;submitted=false">{{ i18n("courses.back") }}</button> <button @click="list=!list;submitted=!submitted">{{ i18n("courses.back") }}</button>
</div> </div>
</template> </template>

View File

@ -115,7 +115,7 @@
<div class="studentfirstname">{{item.user.firstName}}</div> <div class="studentfirstname">{{item.user.firstName}}</div>
<div class="studentlastname">{{item.user.lastName}}</div> <div class="studentlastname">{{item.user.lastName}}</div>
<div class="reqState">{{ i18n("approval")}}{{item.state}}</div> <div class="reqState">{{ i18n("approval")}}{{item.state}}</div>
<div class="teacherApproval">{{ i18n("teacherapproval") }} {{item.teacherApprovalState}}</div> <div class="teacherApproval">{{ i18n("teacherapproval") }} : {{item.teacherApprovalState}}</div>
<div class="infos"><button @click="windowsState=5;targetId=item.id">{{ i18n("request.moreInfos") }}</button></div> <div class="infos"><button @click="windowsState=5;targetId=item.id">{{ i18n("request.moreInfos") }}</button></div>
</div> </div>
</div> </div>

View File

@ -18,7 +18,7 @@ const AcceptMod = ref(false);
const moreInfosMod = ref(false); const moreInfosMod = ref(false);
const requestTypes = ["Create", "Modify", "Delete"] const requestTypes = ["Create", "Modify", "Delete"]
const editElementID = ref(''); const editElementID = ref('');
const chosenLocal = ref(); const chosenLocal = ref("");
const locals = ["A0B1","A1B1","A2B1","A0B2"]; const locals = ["A0B1","A1B1","A2B1","A0B2"];
const moreInfos = ref({}); const moreInfos = ref({});
@ -30,7 +30,6 @@ const moreInfos = ref({});
async function upPage(id,review){ async function upPage(id,review){
await changeRequestState(id, review) ; await changeRequestState(id, review) ;
requests.value = await getAllRequests(); requests.value = await getAllRequests();
chosenLocal.value = null;
} }
/* /*

View File

@ -16,7 +16,7 @@
surname:null, surname:null,
firstname:null, firstname:null,
password:null, password:null,
birthday:"1990-01-01", birthday:null,
email:null, email:null,
address:null, address:null,
country:null, country:null,
@ -36,7 +36,7 @@
const ppData = ref({}) const ppData = ref({})
const idcardfile = ref({}) const idcardfile = ref({})
const justifcardfile = ref({}) const justifcardfile = ref({})
const allfileshere = ref(0)
const curricula= await getAllCurriculums(); const curricula= await getAllCurriculums();
function goBackHome(){ function goBackHome(){
@ -73,13 +73,7 @@
//We upload the two files and we get their paths on the server //We upload the two files and we get their paths on the server
const identityCardFile = await uploadFile(idcardfile.value, "IdentityCard") const identityCardFile = await uploadFile(idcardfile.value, "IdentityCard")
const justifFile = ref(null) const justifFile = ref(null)
const profilepic = await uploadProfilePicture(ppData.value)
const profilepic = ref(null)
if (imageSaved){
profilepic.value = await uploadProfilePicture(ppData.value)
}
if (curricula[outputs.curriculum-1].requireCertificate){ if (curricula[outputs.curriculum-1].requireCertificate){
justifFile.value = await uploadFile(justifcardfile.value, "JustificationDocument") justifFile.value = await uploadFile(justifcardfile.value, "JustificationDocument")
@ -92,7 +86,7 @@
justif = null justif = null
} }
const val = await register(outputs.firstname, outputs.surname, outputs.birthday, outputs.password, outputs.email, outputs.address, outputs.country, outputs.curriculum, profilepic.value.url, identityCardFile.url, new Date(), outputs.equivalenceState, justif); const val = await register(outputs.firstname, outputs.surname, outputs.birthday, outputs.password, outputs.email, outputs.address, outputs.country, outputs.curriculum, profilepic.url, identityCardFile.url, new Date(), outputs.equivalenceState, justif);
for (let item in externalCurrTab.value){ for (let item in externalCurrTab.value){
const temp = await uploadFile(externalCurrTab.value[item].justifdocUrl, "JustificationDocument") const temp = await uploadFile(externalCurrTab.value[item].justifdocUrl, "JustificationDocument")
@ -100,13 +94,6 @@
} }
} }
function everyfilehere(){
if(allfileshere.value === 2 || (allfileshere.value === 1 && curricula[outputs.curriculum-1].requireCertificate === false)){
return true
}else{
return false
}
}
</script> </script>
<template> <template>
@ -151,7 +138,7 @@
</div> </div>
<div class="inputBox"> <div class="inputBox">
<p>{{i18n("login.guest.birthday")}}</p> <p>{{i18n("login.guest.birthday")}}</p>
<input type="date" v-model="outputs.birthday" value="1990-01-05" min="1912-01-01" max="2024-01-01"> <input type="date" v-model="outputs.birthday">
</div> </div>
<div class="inputBox"> <div class="inputBox">
<p>{{i18n("login.guest.password")}}</p> <p>{{i18n("login.guest.password")}}</p>
@ -163,7 +150,7 @@
</div> </div>
<div class="switchpage"> <div class="switchpage">
<button @click="verifyInputs(outputs.password);idcardfile={};justifcardfile={}">{{i18n("login.guest.nextpage")}}</button> <button @click="verifyInputs(outputs.password);">{{i18n("login.guest.nextpage")}}</button>
</div> </div>
<div @click="(loginPage=!loginPage) && (page=0)" class="register"> <div @click="(loginPage=!loginPage) && (page=0)" class="register">
@ -186,7 +173,13 @@
<form class="inputBox" novalidate enctype="multipart/form-data"> <form class="inputBox" novalidate enctype="multipart/form-data">
<p>{{i18n("profile.picture").toUpperCase()}}</p> <p>{{i18n("profile.picture").toUpperCase()}}</p>
</form> </form>
<input style="color:rgb(239,60,168);" type="file" name="picture" @change="ppData = $event.target.files;imageSaved=true" accept="image/*"> <label class="browser">
{{i18n("login.guest.browse")}}
<input type="file" :disabled="imageSaved" @change="ppData = $event.target.files; imageSaved = true;" accept="image/*">
</label>
<form novalidate enctype="multipart/form-data" class="inputBox">
<input type="file" @change="imageSaved = true;" accept="image/*">
</form>
<div class="inputBox"> <div class="inputBox">
<p>{{i18n("Curriculum").toUpperCase()}}</p> <p>{{i18n("Curriculum").toUpperCase()}}</p>
<select v-model="outputs.curriculum"> <select v-model="outputs.curriculum">
@ -210,16 +203,21 @@
</div> </div>
<div v-if="page === 2"> <div v-if="page === 2">
<p style="color:rgb(239,60,168);">{{i18n("login.guest.identityCard")}}</p> <p style="color:rgb(239,60,168);">{{i18n("login.guest.identityCard")}}</p>
<input style="color:rgb(239,60,168);margin-bottom: 3%" type="file" @change="idcardfile = $event.target.files;allfileshere = Math.min(allfileshere+1, 2)"> <label class="browser">
{{i18n("login.guest.browse")}}
<input type="file" @change="idcardfile = $event.target.files">
</label>
<div v-if="curricula[outputs.curriculum-1].requireCertificate === true" style="margin-top: 3%; margin-bottom: 4%"> <div v-if="curricula[outputs.curriculum-1].requireCertificate === true" style="margin-top: 3%; margin-bottom: 4%">
<p style="color:rgb(239,60,168);">{{ i18n("login.guest.attestationdisclaimer") }}</p> <p style="color:rgb(239,60,168);">{{ i18n("login.guest.attestationdisclaimer") }}</p>
<div style="margin-top: 2%"> <div style="margin-top: 2%">
<p style="color:rgb(239,60,168);">Attestation:</p> <p style="color:rgb(239,60,168);">Attestation:</p>
<input style=" color:rgb(239,60,168);" type="file" @change="justifcardfile = $event.target.files;allfileshere = Math.min(allfileshere+1, 2)"> <label class="browser">
{{i18n("login.guest.browse")}}
<input type="file" @change="justifcardfile = $event.target.files">
</label>
</div> </div>
</div> </div>
<div v-if="everyfilehere()"><button @click="page++;" style="margin-top: 10%">{{i18n("login.guest.nextpage")}}</button></div> <button @click="page++;" style="margin-top: 10%">{{i18n("login.guest.nextpage")}}</button>
<div v-else style="color: rgb(239,60,168); margin-top: 5%; margin-bottom: 5%">Please upload all the required files</div>
</div> </div>
<div v-if="page === 3"> <div v-if="page === 3">
<p style="color:rgb(239,60,168);margin-bottom: 5%"> <p style="color:rgb(239,60,168);margin-bottom: 5%">
@ -322,6 +320,9 @@ input[type=submit],button,select{
} }
input[type=file]{
display:none;
}
.browser{ .browser{
display:inline-block; display:inline-block;

View File

@ -3,27 +3,26 @@
import {reactive , ref} from 'vue' import {reactive , ref} from 'vue'
import { getCourses,deleteCourse,alterCourse,createCourse } from "@/rest/courses.js" import { getCourses,deleteCourse,alterCourse,createCourse } from "@/rest/courses.js"
import {getUser, getSelf, getTeachers } from "@/rest/Users.js" import {getUser, getSelf, getTeachers } from "@/rest/Users.js"
import {addCourseToCurriculum, getAllCurriculums, getCurriculumsByCourse} from "@/rest/curriculum.js";
const self = await getSelf(); const self = await getSelf();
const curriculum = ref(await getCourses(self.role)); const curriculum = ref(await getCourses(self.role));
const profList = await getTeachers(); const profList = await getTeachers();
const allCurriculums = ref(await getAllCurriculums());
const curriculumToAdd = ref();
const createMod = ref(false) const createMod = ref(false)
const deleteMod = ref(false) const deleteMod = ref(false)
const editElementID = ref("") const editElementID = ref("")
const editAddCourse = ref("");
function editItem(id){
editElementID.value = id;
}
const curriculumToAddId = ref() //Juste pour montrer le Create Mode
const pattern = { const pattern = {
"id":null,
"title":null, "title":null,
"credits":null, "credits":null,
"owner":null, "owner":null,
@ -42,40 +41,14 @@
} }
if (!isnull){ if (!isnull){
await createCourse(toAdd.id,toAdd.title,toAdd.credits,toAdd.owner); await createCourse(toAdd.title,toAdd.credits,toAdd.owner);
toAdd= Object.assign({},pattern); toAdd= Object.assign({},pattern);
curriculum.value = await getCourses(self.role); curriculum.value = await getCourses(self.role);
}} }}
async function setAddToCurriculum(item){
let temp = [];
let courseCurriculum = await getCurriculumsByCourse(item.courseID);
let isIn = false;
for (let element in allCurriculums.value){
for (let item in courseCurriculum){
if((courseCurriculum[item].option == allCurriculums.value[element].option) && (courseCurriculum[item].year == allCurriculums.value[element].year) ){
isIn = true;
break;
}
}
if(!isIn){
temp.push(allCurriculums.value[element])
}
isIn = false;
}
curriculumToAdd.value = temp.slice();
}
async function addToCurriculum(item){
await addCourseToCurriculum(curriculumToAddId.value,item.courseID);
curriculumToAddId.value = null;
curriculumToAdd.value = null;
allCurriculums.value = await getAllCurriculums();
}
function setModify(item){ function setModify(item){
for(const el in profList){ for(const el in profList){
@ -123,18 +96,13 @@
<button class="create" @click="editElementID= '';createMod = true;"> <button class="create" @click="editElementID= '';createMod = true;">
{{i18n("courses.createCourse")}} {{i18n("courses.createCourse")}}
</button> </button>
<button class="delete" @click="deleteMod=true"> <button class="delete" @click="deleteMod=true" >
{{i18n("courses.deleteCourse")}} {{i18n("courses.deleteCourse")}}
</button> </button>
</div> </div>
<div v-if="createMod"> <div v-if="createMod">
<form class="listElement" style="width:40%;margin-right:auto;margin-left:auto;"> <form class="listElement" style="width:40%;margin-right:auto;margin-left:auto;">
<div style="margin-bottom: 20px">
{{i18n("Curriculum")}}
<select v-model="toAdd.id">
<option v-for="element in allCurriculums" :value="element.curriculumId">{{element.option}}-{{element.year}}</option>
</select>
</div>
<div style="margin-bottom:20px;"> <div style="margin-bottom:20px;">
{{i18n("name")}} : {{i18n("name")}} :
<input v-model="toAdd.title"> <input v-model="toAdd.title">
@ -168,37 +136,24 @@
</div> </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" style="width:50%;margin-left:auto; margin-right:auto;">
<div v-if="editElementID !== item.title && editAddCourse !== item.title" style="display:flex;"> <div v-if="editElementID !== item.title" style ="padding:15px 15px 15px 15px;">
<button @click="editElementID = item.title; editAddCourse = ''; setModify(item);">{{i18n("courses.modify")}}</button> <button @click="editElementID = item.title; setModify(item); ">
<button v-if="self.role !== 'Teacher'"@click="editAddCourse = item.title; editElementID ='';setAddToCurriculum(item)">{{i18n("courses.AddToCurriculum")}}</button> {{i18n("courses.modify")}}
</button>
</div> </div>
<div v-if="editElementID == item.title"> <div v-else>
<button @click="editElementID= '';patchCourse(item)"> {{i18n("courses.confirm")}} </button> <button @click="editElementID= '';patchCourse(item)"> {{i18n("courses.confirm")}} </button>
<button @click="editElementID= '';"> {{i18n("courses.back")}} </button> <button @click="editElementID= '';"> {{i18n("courses.back")}} </button>
</div> </div>
<div v-if="editAddCourse == item.title"> <div class="listElement" >
<button @click="editAddCourse= '';addToCurriculum(item)"> {{i18n("courses.confirm")}} </button>
<button @click="editAddCourse= '';"> {{i18n("courses.back")}} </button>
</div>
<div class="listElement">
<div class="containerElement" v-if="editElementID !== item.title && editAddCourse !== item.title" > <div class="containerElement" v-if="editElementID !== item.title" >
<div class="name"> {{item.title}} </div> <div class="name"> {{item.title}} </div>
<div class="teacher">{{item.owner.lastName}}</div> <div class="teacher">{{item.owner.lastName}}</div>
<div class="credits">{{i18n("Credits")}}:{{item.credits}}</div> <div class="credits">{{i18n("Credits")}}:{{item.credits}}</div>
</div> </div>
<div class="containerElement"v-else>
<div class="containerElement" v-if="editAddCourse == item.title" >
{{i18n("Curriculum")}}:
<select v-model="curriculumToAddId">
<option v-for="element in curriculumToAdd" :value="element.curriculumId">
{{element.option}}-{{element.year}}
</option>
</select>
</div>
<div class="containerElement" v-if="editElementID == item.title">
<input style="max-width:200px;" class="name" v-model="toModify.title"> <input style="max-width:200px;" class="name" v-model="toModify.title">
<select v-if="self.role != 'Secretary'" style="max-width:200px;" class="teacher" v-model="toModify.owner"> <select v-if="self.role != 'Secretary'" style="max-width:200px;" class="teacher" v-model="toModify.owner">
<option v-for="(item,index) in profList" :value='item'>{{item.lastName}}</option> <option v-for="(item,index) in profList" :value='item'>{{item.lastName}}</option>
@ -207,8 +162,6 @@
<input v-if="self.role !='Secretary'"style="max-width:100px;"class="credits" v-model="toModify.credits"> <input v-if="self.role !='Secretary'"style="max-width:100px;"class="credits" v-model="toModify.credits">
<div v-else class="credits">{{i18n("Credits")}}:{{item.credits}}</div> <div v-else class="credits">{{i18n("Credits")}}:{{item.credits}}</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -136,7 +136,7 @@ async function askChanges(i){
<div style="margin-bottom:20px;"> <div style="margin-bottom:20px;">
{{i18n("schedule")}} : {{i18n("schedule")}} :
<select @change="setCourses()"v-model="curriculum"> <select @change="setCourses()"v-model="curriculum">
<option v-for="item in allSchedules" :value='item.curriculum'>{{item.curriculum.option}}-{{item.curriculum.year}}</option> <option v-for="item in allSchedules" :value='item.curriculum'>{{item.curriculum.option}}</option>
</select> </select>
</div> </div>
<div style="margin-bottom:20px;"> <div style="margin-bottom:20px;">

View File

@ -221,8 +221,6 @@ async function setCourses(){
lessonBuffer.value = Object.assign({}, pattern); lessonBuffer.value = Object.assign({}, pattern);
lessonFinder.value = null; lessonFinder.value = null;
lessonCreatorBuffer.value = Object.assign({},lessonCreator) lessonCreatorBuffer.value = Object.assign({},lessonCreator)
allSchedules.value = await getAllSchedule();
schedule.value = null;
trueSchedule.value = null; trueSchedule.value = null;
} }

View File

@ -93,14 +93,12 @@
async function ChangeInfos(){ async function ChangeInfos(){
for (let element in toModify){ for (let element in toModify){
console.log(element)
console.log(toModify[element])
if (element ==="email" && (toModify[element] !== null)){ if (element ==="email" && (toModify[element] !== null)){
await alterSelf(user.value.regNo,{email : toModify[element]}); await alterSelf(user.value.regNo,{email : toModify[element]});
} }
if (element ==="profilePictureUrl" && (toModify[element] !== null)){ if (element ==="profilPictureUrl" && (toModify[element] !== null)){
await alterSelf(user.value.regNo,{ profilePictureUrl : toModify[element]}); await alterSelf(user.value.regNo,{ profilPictureUrl : toModify[element]});
} }
else if(element === "address" && (toModify[element] !== null)){ else if(element === "address" && (toModify[element] !== null)){
await alterSelf(user.value.regNo,{address : toModify[element]}); await alterSelf(user.value.regNo,{address : toModify[element]});
@ -118,14 +116,14 @@
toModify.address = item.address; toModify.address = item.address;
toModify.profilPictureUrl = item.profilPictureUrl; toModify.profilPictureUrl = item.profilPictureUrl;
toModify.email= item.email; toModify.email= item.email;
toModify.password= item.password toModify.password= item.password;
} }
function getPP(){ function getPP(){
if(user.value.profilePictureUrl === null){ if(user.value.profilePictureUrl === null){
return "/Clyde.png" return "/Clyde.png"
} }
return user.value.profilePictureUrl return user.profilePictureUrl
} }
async function refreshExtCurrList(){ async function refreshExtCurrList(){
@ -178,13 +176,6 @@
} }
} }
async function getProfilePic(data){
const pp= await uploadProfilePicture(data)
toModify.profilePictureUrl = pp.url
}
</script> </script>
<template> <template>
@ -201,10 +192,10 @@
<div> <div>
{{ i18n("login.guest.email") }}: {{user.email}} {{ i18n("login.guest.email") }}: {{user.email}}
</div> </div>
<div> <div v-if="user.role==='Student'">
{{ i18n("regNo") }} : {{user.regNo}} {{ i18n("regNo") }} : {{user.regNo}}
</div> </div>
<div> <div v-else>
{{ i18n("role") }}: {{i18n((user.role))}} {{ i18n("role") }}: {{i18n((user.role))}}
</div> </div>
<div> <div>
@ -262,7 +253,7 @@
{{ i18n("alreadypaid") }} {{ i18n("alreadypaid") }}
</div> </div>
<div> <div>
<button @click="windowState=7" v-if="minerv.value.toPay >= 0">{{ i18n("askscholarship") }}</button> <button @click="windowState=7" v-if="minerv.value.toPay <= 0">{{ i18n("askscholarship") }}</button>
</div> </div>
</div> </div>
<div v-if="windowState === 5"> <div v-if="windowState === 5">
@ -315,7 +306,7 @@
<div v-else-if="windowState === 1" class="infosContainer"> <div v-else-if="windowState === 1" class="infosContainer">
<div> <div>
{{i18n("profile.picture")}}: {{i18n("profile.picture")}}:
<input type="file" @change="getProfilePic($event.target.files)" accept="image/*"> <input type="file" @change="user.profilPicture = uploadProfilePicture($event.target.files);" accept="image/*">
</div> </div>
<div> <div>
{{ i18n("login.guest.email")}} {{ i18n("login.guest.email")}}
@ -352,19 +343,19 @@
<select v-model="changecurrdata.actualcursus" style="margin-right: 3%"> <select v-model="changecurrdata.actualcursus" style="margin-right: 3%">
<option v-for="item in getActualCurriculumList()" style="font-size:20px;" :value="item.curriculumId">Bac {{item.year}} {{item.option}}</option> <option v-for="item in getActualCurriculumList()" style="font-size:20px;" :value="item.curriculumId">Bac {{item.year}} {{item.option}}</option>
</select> </select>
{{ i18n("newcursus") }} : {{ i18n("newcurr") }} :
<select v-model="changecurrdata.newcursus"> <select v-model="changecurrdata.newcursus">
<option v-for="item in curricula" :value="item.curriculumId">Bac {{item.year}} {{item.option}}</option> <option v-for="item in curricula" :value="item.curriculumId">Bac {{item.year}} {{item.option}}</option>
</select> </select>
</div> </div>
<div style="height:40px;" v-if="reRegState === 2"> <div style="height:40px;" v-if="reRegState === 2">
{{ i18n("newcursus") }} : {{ i18n("newcurr") }} :
<select v-model="changecurrdata.newcursus"> <select v-model="changecurrdata.newcursus">
<option v-for="item in curricula" :value="item.curriculumId">Bac {{item.year}} {{item.option}}</option> <option v-for="item in curricula" :value="item.curriculumId">Bac {{item.year}} {{item.option}}</option>
</select> </select>
</div> </div>
<div style="height:40px;" v-if="reRegState === 1"> <div style="height:40px;" v-if="reRegState === 1">
{{ i18n("newcursus") }} : {{ i18n("newcurr") }} :
<select v-model="changecurrdata.newcursus" @change="getActualCurr(changecurrdata.newcursus);"> <select v-model="changecurrdata.newcursus" @change="getActualCurr(changecurrdata.newcursus);">
<option v-for="item in getCurriculumsNextYear()" :value="item.curriculumId">Bac {{item.year}} {{item.option}}</option> <option v-for="item in getCurriculumsNextYear()" :value="item.curriculumId">Bac {{item.year}} {{item.option}}</option>
</select> </select>
@ -378,7 +369,7 @@
</div> </div>
</div> </div>
</div> </div>
<div v-if="windowState === 0 && user.role==='Student'" class="moreInfos"> <div v-if="windowState === 0" class="moreInfos">
<div class = "oldcursus"> <div class = "oldcursus">
<div class="listTitle"> <div class="listTitle">
{{ i18n("oldcursus") }} {{ i18n("oldcursus") }}

View File

@ -8,7 +8,7 @@
<script setup> <script setup>
import { ref } from 'vue' import { ref } from 'vue'
import {getDifferenceTime,lastDateOfMonth,formatDate,getFirstDay,sortByDate,weekFromList,sundayToTheEnd,getMarginTop,getHoursMinutes, monthFromList} from '../scheduleFunctions.js' import {getDifferenceTime,lastDateOfMonth,formatDate,getFirstDay,sortByDate,weekFromList,sundayToTheEnd,getMarginTop,getHoursMinutes, monthFromList, durationCourse} from '../scheduleFunctions.js'
import {getAllSchedule} from "@/rest/scheduleRest.js"; import {getAllSchedule} from "@/rest/scheduleRest.js";
import {getOnesLessons, getOwnedLessons } from "@/rest/lessonSchedule.js" import {getOnesLessons, getOwnedLessons } from "@/rest/lessonSchedule.js"
import {isLogged, getSelf,getTeachers} from "@/rest/Users.js" import {isLogged, getSelf,getTeachers} from "@/rest/Users.js"
@ -76,6 +76,8 @@
} }
const days = ["monday","tuesday","wednesday","thursday","friday","saturday","sunday"]; const days = ["monday","tuesday","wednesday","thursday","friday","saturday","sunday"];
const months = ["january","february","march","april",'may',"june","july","august","september","october","november","december"] const months = ["january","february","march","april",'may',"june","july","august","september","october","november","december"]
const firstDayOfMonth = ref(getFirstDay(new Date()))
const monthDone = ref(false);
function getMonday(d) { function getMonday(d) {
d = new Date(d); d = new Date(d);
d.setHours(0,0,0); d.setHours(0,0,0);
@ -532,7 +534,7 @@
<option v-for="item in allSchedules" :value='item'>{{item.curriculum.option}}-{{item.curriculum.year}}</option> <option v-for="item in allSchedules" :value='item'>{{item.curriculum.option}}-{{item.curriculum.year}}</option>
</select> </select>
<button v-if="display=='Week'" @click="display='Month'">{{i18n("Week")}}</button> <button v-if="display=='Week'" @click="display='Month'">{{i18n("Week")}}</button>
<button v-if="display=='Month'" @click="display='Week'; value=1;">{{i18n("Month")}}</button> <button v-if="display=='Month'" @click="display='Week'; value=1;">{{i18("Month")}}</button>
<button v-if="format == 'Grid'" @click="format ='List'">{{i18n("Grid")}}</button> <button v-if="format == 'Grid'" @click="format ='List'">{{i18n("Grid")}}</button>
<button v-if="format == 'List'" @click ="format = 'Grid'">{{i18n("List")}}</button> <button v-if="format == 'List'" @click ="format = 'Grid'">{{i18n("List")}}</button>
<button v-if="verifUser()" @click="jsonMod=false ;displayOwnSchedule();">{{i18n("OwnSchedule")}}</button> <button v-if="verifUser()" @click="jsonMod=false ;displayOwnSchedule();">{{i18n("OwnSchedule")}}</button>
@ -575,7 +577,6 @@
</div> </div>
<div class="body" style="background-color:rgb(50,50,50);">{{i18n("schedule.courses")}}</div> <div class="body" style="background-color:rgb(50,50,50);">{{i18n("schedule.courses")}}</div>
<div class="body" style="background-color:#484848;"v-for="lesson in focusLessons"> <div class="body" style="background-color:#484848;"v-for="lesson in focusLessons">
{{formatDate(lesson.lessonStart)}}
{{ getHoursMinutes(lesson.lessonStart)}}-{{getHoursMinutes(lesson.lessonEnd)}} {{ getHoursMinutes(lesson.lessonStart)}}-{{getHoursMinutes(lesson.lessonEnd)}}
{{ lesson.local}} {{ lesson.local}}
{{i18n(lesson.lessonType.toString())}} {{i18n(lesson.lessonType.toString())}}

View File

@ -1,153 +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 i18n from "@/i18n.js";
const yearList = ref([])
const yearCheckedList = ref([])
const monthList = ref([])
const monthCheckedList = ref([])
const accessList = ref([])
const accessCheckedList = ref([])
const languageList = ref([])
const languageCheckedList = ref([])
const domainList = ref([])
const domainCheckedList = ref([])
const paperTypeList = ref([])
const paperTypCheckedList = ref([])
const filters = Object.assign({},{
year:[],
month:[],
access:[],
language:[],
domain:[],
paperType:[],
})
const props = defineProps({
isOpen: Boolean,
allArticles: ref([Object])
});
function submit(){
filters.paperType = paperTypCheckedList.value
filters.year = yearCheckedList.value
filters.month = monthCheckedList.value
filters.access = accessCheckedList.value
filters.language = languageCheckedList.value
filters.domain = domainCheckedList.value
emit("modal-close")
emit("submit", filters)
}
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) && year !== null) yearList.value.push(year);
if (!monthList.value.includes(month) && month !== null) monthList.value.push(month);
if (!accessList.value.includes(r.access) && r.access !== null ) accessList.value.push(r.access);
if (!languageList.value.includes(r.language) && r.language !== null) languageList.value.push(r.language);
if (!domainList.value.includes(r.domain) && r.domain !== null) domainList.value.push(r.domain);
if (!paperTypeList.value.includes(r.paperType) && r.paperType !== null) paperTypeList.value.push(r.paperType);
}
const emit = defineEmits(["modal-close", "submit"]);
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> {{i18n("Year")}} :<ul class="checkers"> <li v-for="n in yearList"> <input type="checkbox" :value=n v-model="yearCheckedList"> {{n}} </li> </ul> </div>
<div class="vl"> {{i18n("Access")}}:<ul class="checkers"> <li v-for="n in accessList"> <input type="checkbox" :value=n v-model="accessCheckedList"> {{i18n("Access."+n)}} </li> </ul> </div>
<div class="vl"> {{i18n("Language")}} :<ul class="checkers"> <li v-for="n in languageList"> <input type="checkbox" :value=n v-model="languageCheckedList"> {{n}} </li> </ul> </div>
<div> {{i18n("Month")}} :<ul class="checkers"> <li v-for="n in monthList"> <input type="checkbox" :value=n v-model="monthCheckedList"> {{i18n("Month." + n)}} </li> </ul> </div>
<div class="vl"> {{i18n("Domain")}} :<ul class="checkers"> <li v-for="n in domainList"> <input type="checkbox" :value=n v-model="domainCheckedList"> {{n}} </li> </ul> </div>
<div class="vl"> {{i18n("PaperType")}} :<ul class="checkers"> <li v-for="n in paperTypeList"> <input type="checkbox" :value=n v-model="paperTypCheckedList"> {{n}} </li> </ul> </div>
</div>
<div id="submit">
<button @click.stop="submit">{{i18n("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,235 +0,0 @@
<!----------------------------------------------------
File: ListResearches.vue
Author: Maxime Bartha
Scope: Extension Publicatons scientifiquess
Description: Listing of the researches with filters
----------------------------------------------------->
<script setup>
import {ref, watch} from "vue";
import FilterComponent from "@/Apps/ScientificPublications/FilterComponent.vue";
import ArticleComponent from "@/Apps/ScientificPublications/ResearchComponent.vue";
import {fetchAllResearches} from "@/rest/ScientificPublications/ManageResearch.js";
import i18n from "../../i18n.js";
const input = ref("")
const isFilterOpened = ref(false);
const isResearchOpened = ref(false);
const articleToDisplay = ref(Object)
const isResearcher = ref(false)
const filters = ref(null)
const researchList = ref(await fetchAllResearches())
const props = defineProps({
researchList:ref(),
manage:Boolean,
allResearcher:ref()
});
if (typeof props.researchList !== 'undefined'){
researchList.value = props.researchList
}
watch(
() => props.researchList,
(newValue) => {
researchList.value = newValue
}
);
async function modified(){
if (typeof props.researchList === 'undefined'){
researchList.value = await fetchAllResearches()
}
else {
emit('modified')
}
}
const openFilter = () => {
isFilterOpened.value = true;
};
const closeFilter = () => {
isFilterOpened.value = false;
};
const submitFilters = (receivedFilters)=>{
filters.value = receivedFilters
}
const openResearch = (article) => {
isResearchOpened.value = true;
articleToDisplay.value = article;
}
const closeResearch = () => {
isResearchOpened.value =false;
articleToDisplay.value = null;
}
function searchInList(list, searchInput) {
let retList = []
for (let i = 0; i < list.length; i++) {
let researcher = list[i].researcher.user.firstName + " " +list[i].researcher.user.lastName
if (isResearcher.value && (lDistance(researcher, searchInput) < 5 || researcher.toUpperCase().indexOf(searchInput.toUpperCase()) > -1)){
retList.push(list[i])
}
if (!isResearcher.value && (lDistance(list[i].title, searchInput) < 10 || list[i].title.toUpperCase().indexOf(searchInput.toUpperCase()) > -1)){
if (filters.value === null) {
retList.push(list[i])
continue;
}
if ( (filters.value.access.length === 0 || filters.value.access.includes(list[i].access))
&& ( filters.value.domain.length === 0|| filters.value.domain.includes(list[i].domain))
&& ( filters.value.paperType.length === 0 || filters.value.paperType.includes(list[i].paperType))
&& ( filters.value.year.length === 0|| filters.value.year.includes(list[i].releaseDate.split("-")[0]))
&& ( filters.value.month.length === 0|| filters.value.month.includes(list[i].releaseDate.split("-")[1]))
&& ( filters.value.language.length === 0|| filters.value.language.includes(list[i].language)))
{
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 emit = defineEmits(["modified"]);
</script>
<template>
<div id="researches">
<FilterComponent :isOpen="isFilterOpened" :allArticles="researchList" @modal-close="closeFilter" @submit="submitFilters"></FilterComponent>
<ArticleComponent :allResearcher="allResearcher" :article="articleToDisplay" :isOpen="isResearchOpened" :manage="props.manage" @modal-close="closeResearch" @modified="modified"></ArticleComponent>
<div id="search">
<input v-if="!isResearcher" type="text" id="search-input" :placeholder="i18n('Search.Researches')" v-model="input"/>
<input v-else type="text" id="search-input" :placeholder="i18n('Search.Researchers')" v-model="input"/>
<button v-if="!isResearcher" id="filterButton" @click="openFilter"> {{i18n("Filters")}} </button>
<button v-if="!isResearcher" id="unToggledResearchButton" @click="isResearcher = !isResearcher"> {{i18n("Toggle.Researcher")}}</button>
<button v-if="isResearcher" id="toggledResearchButton" @click="isResearcher = !isResearcher"> {{i18n("Untoggle.Researcher")}}</button>
</div>
<div id="researches">
<ul id="researchUL">
<li id="researchLi" v-for="n in searchInList(researchList,input)">
<div class="vl"> {{n.title}}</div>
<div class="vl"> <a :href="'#/researcher-profile?id=' + n.researcher.id"> {{ n.researcher.user.firstName +" "+ n.researcher.user.lastName }}</a>
</div>
<a v-if="!manage" @click="openResearch(n)"> {{i18n("MoreInfo")}}</a>
<a v-else @click="openResearch(n)"> {{i18n("Modify.Research")}}</a></li>
</ul>
</div>
</div>
</template>
<style scoped>
#researches{
padding-top: 15px;
width: 100%;
height: 100%;
overflow: scroll;
}
#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: 100%;
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;
}
#unToggledResearchButton{
align-self: center;
margin-left: 2px;
font-size:16px ;
color: white;
background: #2a1981;
border:2px solid black;
}
#unToggledResearchButton:hover{
background: #5ac8fa;
}
#toggledResearchButton {
align-self: center;
margin-left: 2px;
font-size: large;
color: white;
background: crimson;
border:2px solid black;
}
#toggledResearchButton:hover{
background: #ff2d55;
}
</style>

View File

@ -1,184 +0,0 @@
<!----------------------------------------------------
File: ManageResearchesProfile.vue
Author: Maxime Bartha
Scope: Extension Publicatons scientifiquess
Description: Managing Researcher Profile page
----------------------------------------------------->
<script setup>
import { ref} from "vue";
import {fetchResearches, } from "@/rest/ScientificPublications/ResearcherProfile.js";
import {getSelf, patchProfile} from "@/rest/ScientificPublications/ManageResearcherProfile.js";
import ResearchPostComponent from "@/Apps/ScientificPublications/ResearchPostComponent.vue";
import ListResearches from "@/Apps/ScientificPublications/ListResearches.vue";
import i18n from "../../i18n.js";
import {fetchAllResearchers} from "@/rest/ScientificPublications/ManageResearch.js";
const input = ref("");
const isPostResearchOpened = ref(false);
const changing = ref(false);
let toModify= Object.assign({}, {});
const researcher = ref(await getSelf());
const researchList = ref(await fetchResearches(researcher.value.id));
const allResearcher = ref(await fetchAllResearchers())
function openPostResearch(){
isPostResearchOpened.value = true
}
function cancelChanges(){
changing.value = false
toModify= Object.assign({}, {});
}
async function confirmChanges(){
await patchProfile(researcher.value.id, toModify)
changing.value = false
toModify= Object.assign({}, {});
researcher.value = await getSelf();
}
async function modifiedResearch(){
researchList.value = await fetchResearches(researcher.value.id)
}
function getPP(){
if(researcher.value.user.profilePictureUrl === null){
return "/Clyde.png"
}
return researcher.value.user.profilePictureUrl
}
</script>
<template> <div class="body"><div id="main">
<ResearchPostComponent :allResearcher="allResearcher" :researcher="researcher" :isOpen="isPostResearchOpened" @modal-close="isPostResearchOpened = false" @posted="modifiedResearch"></ResearchPostComponent>
<div id="profilePicture" >
<img :src=getPP() style="border-radius: 20%"/>
</div>
<div id="researcherInfos">
<div class="surrounded" v-if="!changing">{{researcher.user.lastName}} {{researcher.user.firstName}}</div>
<div class="surrounded" v-else> {{i18n("To.Change.In.Options")}}</div>
<div class="surrounded" v-if="!changing">Orcid : {{researcher.orcidId}}</div>
<div class="surrounded" v-else>Orcid : <input v-model="toModify.orcidId"> </div>
<div class="surrounded" v-if="!changing">Email : {{researcher.user.email}}</div>
<div class="surrounded" v-else> {{i18n("To.Change.In.Options")}}</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"></div>
<div class="surrounded" v-if="!changing">{{i18n("Domain")}} : {{researcher.domain}}</div>
<div class="surrounded" v-else>Domain : <input v-model="toModify.domain"></div>
<div style="text-align: center; align-self: center" v-if="!changing"> <button class="modifyButton" @click="changing = !changing">{{i18n("Modify.Data")}}</button></div>
<div v-else style="text-align: center; align-self: center">
<button id="confirmButton" @click="confirmChanges"> {{i18n("Confirm.Changes")}}</button>
<button id="cancelButton" @click="cancelChanges"> {{i18n("Cancel.Changes")}}</button>
</div>
</div>
<div class="postArticle" style="text-align: center">
<button class="modifyButton" @click="openPostResearch">{{i18n("Post.Research")}}</button>
</div>
<div> <ListResearches :allResearcher="allResearcher" :research-list="researchList" :manage="true" @modified="modifiedResearch"></ListResearches> </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;
margin-bottom: 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;
}
a{
color:#007aff;
text-decoration: underline;
cursor: pointer;
}
</style>

View File

@ -1,242 +0,0 @@
<!----------------------------------------------------
File: ResearchComponent.vue
Author: Maxime Bartha
Scope: Extension Publicatons scientifiquess
Description: Pop Up summarizing a research infos
----------------------------------------------------->
<script setup xmlns="http://www.w3.org/1999/html">
import {ref, watch} from "vue";
import {onClickOutside} from '@vueuse/core'
import {
patchArticle,
deleteArticle,
addView,
} from "@/rest/ScientificPublications/ManageResearch.js";
import i18n from "../../i18n.js";
const coAuthors = ref()
const restURL = import.meta.env.VITE_CLYDE_MODE === 'container' ? "http://localhost:8000": import.meta.env.DEV ? "http://localhost:5173" : "https://clyde.herisson.ovh/api"
const props = defineProps({
isOpen: Boolean,
article: ref(Object),
manage:Boolean,
allResearcher: ref()
});
watch(
() => props.article,
(newValue) => {
if (newValue !== null)
coAuthors.value = newValue.coAuthors
}
);
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","modified"]);
const target = ref(null)
onClickOutside(target, ()=>{emit('modal-close'); })
let toModify= Object.assign({}, {});
function cancelChanges(){
toModify= Object.assign({}, {});
emit('modal-close')
}
async function confirmChanges(){
let coAuthorsId =[]
coAuthors.value.forEach(n => (coAuthorsId.push(n.id)))
toModify.coAuthors = coAuthorsId
await patchArticle(props.article.id, toModify)
toModify= Object.assign({}, {});
emit('modal-close')
emit("modified")
}
async function deleteThisArticle(){
await deleteArticle(props.article.id)
emit('modal-close')
emit("modified")
}
function downloadPdf(){
return (restURL + "/" + props.article.pdfLocation)
}
function downloadBibTex(){
return (restURL + "/" + props.article.bibTexLocation)
}
async function articleClicked(){
await addView(props.article.pdfLocation)
emit('modal-close')
emit('modified')
}
</script>
<template>
<div v-if="isOpen" class="modal-mask">
<div class="modal-wrapper">
<div class="modal-container" ref="target">
<div><ul>
<li>{{i18n("Article.Id")}} : {{article.id}}</li>
<li>{{i18n("Title")}} : {{article.title}}</li>
<li>{{i18n("Author")}} : {{article.researcher.user.lastName + " " + article.researcher.user.firstName}}</li>
<li>{{i18n("CoAuthors")}} : <ul id="coAuthors" v-for="n in article.coAuthors"> <li id="coAuthorsLi"> {{n.user.firstName}} {{n.user.lastName}}, </li></ul></li>
<li>{{i18n("Summary")}} : {{article.summary}}</li>
<li>{{i18n("ReleaseDate")}} : {{format(article.releaseDate)}}</li>
<li>{{i18n("Language")}} : {{article.language}}</li>
<li>{{i18n("PaperType")}} : {{article.paperType}}</li>
<li>{{i18n("Domain")}} : {{article.domain}}</li>
<li>{{i18n("Views")}} : {{article.views}}</li>
<li>{{i18n("Access")}} : {{i18n("Access."+article.access)}}</li>
</ul>
<div id="downloads" v-if="article.pdfLocation !== null && !manage">
<a :href=downloadPdf() @click.stop="articleClicked" target="_blank">{{i18n("See.Research")}}</a>
<a v-if="article.bibTexLocation !== null" :href=downloadBibTex() @click.stop="emit('modal-close')" target="_blank">{{i18n("SeeBibTex")}}</a> </div>
</div>
<div v-if="manage" id="manage">
<div>
<ul>
<li>{{i18n("Title")}} : <input v-model="toModify.title"></li>
<li>{{i18n("Language")}} : <input v-model="toModify.language"></li>
<li>{{i18n("Summary")}} : <input v-model="toModify.summary"></li>
<li>{{i18n("Domain")}} : <input v-model="toModify.domain"></li>
<li>{{i18n("Access")}} :
<select id="classed-select" v-model="toModify.access">
<option value="OpenSource">{{i18n("Access.OpenSource")}}</option>
<option value="Restricted">{{i18n("Access.Restricted")}}</option>
<option value="Private">{{i18n("Access.Private")}}</option>
</select></li>
</ul>
</div>
<div> {{i18n("CoAuthors.List")}} :
<ul id="coAuthorListUl" style="list-style-type: none;" v-for="n in props.allResearcher">
<li v-if="n.id !== props.article.researcher.id"> <input type="checkbox" :value=n v-model="coAuthors"> {{n.id}} : {{n.user.firstName}} {{n.user.lastName}}</li>
</ul>
</div>
<div>
<button id="confirmButton" @click="confirmChanges"> {{i18n("Confirm.Changes")}}</button>
<button id="cancelButton" @click="cancelChanges">{{i18n("Cancel.Changes")}}</button>
</div>
<div style="text-align: end">
<button id="deleteButton" @click="deleteThisArticle">{{i18n("Delete.Research")}} </button>
</div>
</div>
</div>
</div>
</div>
</template>
<style scoped>
.modal-mask {
position: fixed;
z-index: 9998;
top: 0;
left: 0;
width: 100%;
height: 120%;
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;
}
#manage{
display: grid;
grid-template-columns: auto auto;
}
#coAuthors{
list-style: none;
display: inline;
padding: 0;
}
#coAuthorsLi{
display: inline;
margin-right: 2px;
}
#downloads {
text-align: end;
}
#coAuthorListUl{
overflow: scroll;
}
#downloads a {
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;
text-underline-mode: none;
text-decoration: none;
}
#downloads button:hover{
background: rgba(191, 64, 191);
}
#deleteButton{
align-self: end;
text-align: end;
border: 2px solid black;
color: white;
font-size: x-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,177 +0,0 @@
<!----------------------------------------------------
File: ResearchPostComponent.vue
Author: Maxime Bartha
Scope: Extension Publicatons scientifiquess
Description: pop up for posting a research
----------------------------------------------------->
<script setup>
import { ref } from "vue";
import {onClickOutside} from '@vueuse/core'
import {uploadFile, postResearch} from "@/rest/ScientificPublications/ManageResearch.js";
import i18n from "../../i18n.js";
const coAuthors = ref([])
let toPost = Object.assign({}, {coAuthors:[]});
const props = defineProps({
isOpen: Boolean,
researcher: ref(Object),
allResearcher:ref()
});
async function uploadResearchPdf(pdf){
const data = await uploadFile(pdf);
toPost.pdfLocation = data.url;
}
async function uploadBibTex(pdf){
const data = await uploadFile(pdf);
toPost.bibTexLocation = data.url;
}
async function postNewResearch(){
toPost.releaseDate = new Date()
toPost.author = props.researcher
toPost.coAuthors = coAuthors.value
//the Pdf and a title are required
if (toPost.pdfLocation == null || toPost.title == null || toPost.title === "") {
emit("modal-close")
return;
}
await postResearch(toPost)
toPost = Object.assign({}, {});
coAuthors.value = []
emit("modal-close")
emit("posted")
}
function cancelPost(){
emit("modal-close")
toPost = Object.assign({}, {});
}
const emit = defineEmits(["modal-close","posted"]);
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 ><ul>
<li>{{i18n("Title")}} : <input v-model="toPost.title"></li>
<li>{{i18n("Summary")}} : <input v-model="toPost.summary"></li>
<li>{{i18n("Language")}} : <input v-model="toPost.language"></li>
<li>{{i18n("Domain")}} : <input v-model="toPost.domain"></li>
<li>{{i18n("PaperType")}} : <select id="classed-select" v-model="toPost.paperType">
<option value="Article">{{i18n("PaperType.Article")}}</option>
<option value="Book">{{i18n("PaperType.Book")}}</option>
<option value="BookChapter">{{i18n("PaperType.Book.Chapter")}}</option>
<option value="Paper">{{i18n("PaperType.Paper")}}Paper</option>
</select></li>
<li>{{i18n("Access")}} : <select id="classed-select" v-model="toPost.access">
<option value="OpenSource">{{i18n("Access.OpenSource")}}</option>
<option value="Restricted">{{i18n("Access.Restricted")}}</option>
<option value="Private">{{i18n("Access.Private")}}</option>
</select></li>
<li> {{i18n("Research.Pdf")}} :
<form novalidate enctype="multipart/form-data" class="inputBox">
<input type="file" @change="uploadResearchPdf($event.target.files);" accept="application/pdf">
</form></li>
<li> {{i18n("BibTex.Pdf")}}
<form novalidate enctype="multipart/form-data" class="inputBox">
<input type="file" @change="uploadBibTex($event.target.files);" accept=".bib">
</form></li>
</ul>
</div>
<div id="CoAuthorList"> {{i18n("CoAuthors.List")}} :
<ul style="list-style-type: none;" v-for="n in props.allResearcher">
<li v-if="n.id !== props.researcher.id"> <input type="checkbox" :value=n v-model="coAuthors"> {{n.id}} : {{n.user.firstName}} {{n.user.lastName}}</li>
</ul>
</div>
<div></div>
<div>
<button id="confirmButton" @click="postNewResearch">{{i18n("Confirm.Publish")}}</button>
<button id="cancelButton" @click="cancelPost">{{i18n("Cancel.Publish")}}</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 {
display: grid;
grid-template-columns: 40% 60%;
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 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);
}
#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,174 +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 {fetchResearcher, fetchResearches, fetchStats} from "@/rest/ScientificPublications/ResearcherProfile.js";
import ListResearches from "@/Apps/ScientificPublications/ListResearches.vue";
import i18n from "../../i18n.js";
const input = ref("");
const statsOf = ref();
const statsBy = ref();
let chart;
const researcherId = window.location.href.split("=")[1]
function getPP(){
if(researcher.value.user.profilePictureUrl === null){
return "/Clyde.png"
}
return researcher.value.user.profilePictureUrl
}
const researchList = ref(await fetchResearches(researcherId));
const researcher = ref(await fetchResearcher(researcherId));
const stats = ref(await fetchStats(researcherId))
function downloadCoAuthors(){
let coAuthors = []
for (let i in researchList.value) {
for (const j in researchList.value[i].coAuthors){
const coAuthor = researchList.value[i].coAuthors[j]
coAuthors.push(coAuthor)
}
}
const data = JSON.stringify(coAuthors);
const blob = new Blob([data], {type:"application/json"});
return URL.createObjectURL(blob);
}
const options = reactive({
backgroundColor:null,
theme: "light2",
animationEnabled: true,
title: {
fontColor: "white",
text : i18n("Please.Select.Option"),
},
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",
}
let index = (statsOf.value === "Views"?0:(statsOf.value === "Researches"?3:6)) + (statsBy.value ==="Years"?0:(statsBy.value==="Months"?1:2))
if (typeof statsBy.value !== 'undefined' && typeof statsOf.value !== 'undefined'){
options.data[0].dataPoints = stats.value[index]
options.title.text = i18n(statsOf.value) +" "+ i18n("By") +" " + i18n(statsBy.value);
chart.render();
}
}
async function modifiedResearch(){
researchList.value = await fetchResearches(researcher.value.id)
}
</script>
<template>
<div id="main">
<div id="profilePicture">
<img :src=getPP() style="border-radius: 20%"/>
</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">{{i18n("Domain")}} : {{researcher.domain}}</div>
<div id="coAuthorList" class="surrounded">Co-authors list : <a :href=downloadCoAuthors() download="coAuthors.json">{{i18n("Here")}}</a></div>
</div>
<div id="stats">
<div class="surrounded">
{{i18n("Stat.Type")}} :
<select @change="update()" id="stats-select" v-model="statsOf">
<option value="Views">{{i18n("Views")}}</option>
<option value="Researches">{{i18n("Researches")}}</option>
<option value="DifferentLanguage">{{i18n("DifferentLanguage")}}</option>
</select>
</div>
<div class="surrounded">
{{i18n("Class.By")}} :
<select @change="update()" id="classed-select" v-model="statsBy">
<option value="Years">{{i18n("Years")}}</option>
<option value="Months">{{i18n("Months")}}</option>
<option value="Domain">{{i18n("Domain")}}</option>
</select>
</div>
<div id="statsPie">
<CanvasJSChart :options="options" id=chart @chart-ref="c => chart = c "/>
</div>
</div>
<div id="researches" style="margin-top: -15px"><list-researches :researchList="researchList" @modified="modifiedResearch"></list-researches></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;
}
a{
color:#007aff;
text-decoration: underline;
cursor: pointer;
}
</style>

View File

@ -1,30 +1,20 @@
<script setup> <script setup>
import i18n from "@/i18n.js" import i18n from "@/i18n.js"
import { reactive } from 'vue'
import { getAllUsers } from '../rest/Users.js' import { getAllUsers } from '../rest/Users.js'
import {ref} from "vue";
import AboutUser from "@/Apps/AboutUser.vue";
const list = ref(true)
const targetRegNo =ref()
const users = await getAllUsers(); const users = await getAllUsers();
</script> </script>
<template style="margin-top:5%;"> <template style="margin-top:5%;">
<div v-if="list === false"> <div style="display:flex; justify-content:center; min-width:1140px;" v-for="item in users">
<AboutUser :user=target /> <div class="bodu">
<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; min-width:1140px;" v-for="item in users" v-if="list">
<div class="body">
<div class="container"> <div class="container">
<div class="role"><a style="margin-left:30px">{{i18n(item.role)}}</a></div> <div class="role"><a style="margin-left:30px">{{i18n(item.role)}}</a></div>
<div class="surname"><a>{{item.lastName}}</a></div> <div class="surname"><a>{{item.lastName}}</a></div>
<div class="firstname"><a>{{item.firstName}}</a></div> <div class="firstname"><a>{{item.firstName}}</a></div>
<div class="infos"> <div class="infos"><button style="background-color:rgb(105,05,105);" >{{i18n("request.moreInfos")}} </button></div>
<button style="background-color:rgb(105,05,105);" @click="list = false; target = item;">{{i18n("request.moreInfos")}} </button>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -80,7 +70,7 @@
} }
.body { .bodu {
margin-top:2%; margin-top:2%;
width:66%; width:66%;
border:2px solid black; border:2px solid black;

View File

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

View File

@ -1,32 +0,0 @@
import {restGet, restPost, restDelete, restPatch, restPostFile} from '../restConsumer.js'
export async function deleteArticle(id){
await restDelete("/research/" + id)
}
export async function patchArticle(id, data){
await restPatch("/research/" + id, data)
}
export async function uploadFile(file){
const formData = new FormData();
formData.append("file", file[0]);
return restPostFile("/upload/Research", formData);
}
export async function postResearch(data){
return restPost("/research", data)
}
export async function fetchAllResearches(){
return restGet("/researches")
}
export async function getFile(url){
const restURL = import.meta.env.VITE_CLYDE_MODE === 'container' ? "http://localhost:8000": import.meta.env.DEV ? "http://localhost:5173" : "https://clyde.herisson.ovh/api"
return await fetch(restURL + "/" + url, {method: "GET"})
}
export async function addView(url){
return restPost("/addview/" + url)
}
export async function fetchAllResearchers(){
return await restGet("/researchers")
}

View File

@ -1,9 +0,0 @@
import { restGet, restPost, restDelete, restPatch } from '../restConsumer.js'
export async function getSelf(){
return restGet("/researcher")
}
export async function patchProfile(id, data){
return restPatch("/researcher/" + id, data)
}

View File

@ -1,25 +0,0 @@
import { restGet, restPost, restDelete, restPatch } from '../restConsumer.js'
export async function fetchResearcher(id){
return restGet("/researcher/" + id)
}
export async function fetchResearches(id){
return restGet("/researches/" + id)
}
export async function fetchStats(id){
return restGet("/stats/" +id)
}
export async function fetchResearch(id){
return restGet("/research/" +id)
}
export async function deleteResearcher(id){
return restDelete("/researcher/" + id)
}
export async function postResearcher(data){
return restPost("/researcher", data)
}

View File

@ -13,10 +13,6 @@ export function disconnect(){
setCookie("session_token", ";expires= Thu, 01 Jan 1970 00:00:01 GMT") setCookie("session_token", ";expires= Thu, 01 Jan 1970 00:00:01 GMT")
} }
export async function patchUser(id,data){
return restPatch("/user/" +id, data)
}
/** /**
* Register a user (tokenless) * Register a user (tokenless)
* *
@ -48,8 +44,31 @@ export async function register(firstname, lastname, birthDate, password, email,
}); });
} }
export async function postUser(data){ /**
return restPost("/user", data) * Register a user (by secretary)
*
* @param firstname
* @param lastname
* @param birthdate
* @param password
* @param mail
* @param address
* @param country
* @param imageId id of the image in database returned when uploaded
*
* PS: the password is not required as it is generated by the backend and sent to the user
* by mail. it's up to the user to change it if he cares about security
*/
export async function createUser(firstname, lastname, birthDate, email, address, country, role, imageId){
return restPost("/user", {
firstname: firstname,
lastname: lastname,
birthDate: birthDate,
password: password,
email: email,
address: address,
country: country,
});
} }
/** /**

View File

@ -16,10 +16,6 @@ import Msg from "@/Apps/Msg.vue"
import Forums from '@/Apps/Forums.vue' import Forums from '@/Apps/Forums.vue'
import Payments from "@/Apps/Inscription/PaymentInfo.vue"; import Payments from "@/Apps/Inscription/PaymentInfo.vue";
import ManageRequests from "@/Apps/Inscription/ManageRequests.vue"; import ManageRequests from "@/Apps/Inscription/ManageRequests.vue";
import ManageResearcherProfile from "@/Apps/ScientificPublications/ManageResearcherProfile.vue";
import ListResearches from "@/Apps/ScientificPublications/ListResearches.vue";
import ResearcherProfile from "@/Apps/ScientificPublications/ResearcherProfile.vue";
import CreateUser from "@/Apps/CreateUser.vue";
const apps = { const apps = {
'/schedule': Schedule, '/schedule': Schedule,
@ -30,10 +26,6 @@ const apps = {
'/manage-courses' : Courses, '/manage-courses' : Courses,
'/users-list' : Users, '/users-list' : Users,
'/students-list' : Students, '/students-list' : Students,
'/manage-researcher-profile' : ManageResearcherProfile,
'/researches' : ListResearches,
'/researcher-profile': ResearcherProfile,
'/create-user': CreateUser,
'/manage-owned-lessons': ManageOwnedLessons, '/manage-owned-lessons': ManageOwnedLessons,
'/manage-schedule-requests' : LessonRequests, '/manage-schedule-requests' : LessonRequests,
'/msg' : Msg, '/msg' : Msg,
@ -42,7 +34,6 @@ const apps = {
} }
const appsList = { const appsList = {
'ListResearches': {path:'#/researches', icon:'fa-book-bookmark',text:i18n("app.list.researches")},
'Msg': { path: '#/msg', icon: 'fa-comment', text: i18n("app.messages") }, 'Msg': { path: '#/msg', icon: 'fa-comment', text: i18n("app.messages") },
'Notification': { path: '#/notifs', icon: 'fa-bell', text: i18n("app.notifications") }, 'Notification': { path: '#/notifs', icon: 'fa-bell', text: i18n("app.notifications") },
'Forum': { path: '#/forums', icon: 'fa-envelope', text: i18n("app.forum") }, 'Forum': { path: '#/forums', icon: 'fa-envelope', text: i18n("app.forum") },
@ -51,8 +42,6 @@ const appsList = {
'ManageCourses': { path: '#/manage-courses', icon: 'fa-book', text: i18n("app.manage.courses") }, 'ManageCourses': { path: '#/manage-courses', icon: 'fa-book', text: i18n("app.manage.courses") },
'StudentsList':{ path: '#/students-list',icon: 'fa-users',text: i18n("app.studentList")}, 'StudentsList':{ path: '#/students-list',icon: 'fa-users',text: i18n("app.studentList")},
'UsersList':{ path: '#/users-list',icon: 'fa-users',text: i18n("app.users")}, 'UsersList':{ path: '#/users-list',icon: 'fa-users',text: i18n("app.users")},
'ManageResearcherProfile':{path:'#/manage-researcher-profile',icon:'fa-book-bookmark',text:i18n("app.manage.researcherProfile")},
'CreateUser':{path:'#/create-user',icon:'fa-plus', text:i18n("app.Create.User")},
'ManageOwnedLessons':{path: '#/manage-owned-lessons',icon:'fa-calendar-days',text: i18n("app.manageOwnLessons")}, 'ManageOwnedLessons':{path: '#/manage-owned-lessons',icon:'fa-calendar-days',text: i18n("app.manageOwnLessons")},
'LessonRequests':{path: '#/manage-schedule-requests', icon:'fa-book', text: i18n("app.lessonRequests")}, 'LessonRequests':{path: '#/manage-schedule-requests', icon:'fa-book', text: i18n("app.lessonRequests")},
'Requests': { path: '#/requests', icon: 'fa-users', text: "Requests" }, 'Requests': { path: '#/requests', icon: 'fa-users', text: "Requests" },
@ -62,7 +51,7 @@ const appsList = {
const currentPath = ref(window.location.hash) const currentPath = ref(window.location.hash)
export const currentView = computed(() => { export const currentView = computed(() => {
return apps[currentPath.value.split("?")[0].slice(1) || '/'] return apps[currentPath.value.slice(1) || '/']
}) })
/** /**

View File

@ -7,8 +7,8 @@ import { restGet, restPost, restDelete, restPatch } from './restConsumer.js'
/** /**
* Create a new course * Create a new course
*/ */
export async function createCourse(id,name, credits, owner){ export async function createCourse(name, credits, owner){
return restPost("/course/curriculum/" + id, {title: name, credits: credits, owner} ) return restPost("/course", {title: name, credits: credits, owner} )
} }
/** /**
@ -19,7 +19,7 @@ export async function deleteCourse(id){
} }
/** /**
* Get information on a particular course * Get informations on a particular course
* *
* @param id identification of the course * @param id identification of the course
* *

View File

@ -23,9 +23,6 @@ export async function getAllCurriculums(){
return restGet("/curriculums"); return restGet("/curriculums");
} }
export async function getCurriculumsByCourse(id){
return restGet("/course/curriculum/"+ id);
}
/** /**
* Get informations on a particular curriculum * Get informations on a particular curriculum
* *
@ -56,7 +53,4 @@ export async function getSomeonesCurriculumList(user){
return restGet("/onescurriculum/"+user) return restGet("/onescurriculum/"+user)
} }
export async function addCourseToCurriculum(id,courseID){
return restPost("/curriculum/"+id, courseID);
}

View File

@ -1,17 +0,0 @@
import { ref } from 'vue'
import { restGet, restPost } from '@/rest/restConsumer.js'
export const notifications = ref([]);
let timerSet = false
export function fetchNotifications(){
restGet("/notifications").then( e => notifications.value = e );
if(!timerSet){
timerSet = true;
setTimeout(() => {timerSet = false; fetchNotifications()}, 5000);
}
}
export function archiveNotification(id){
restPost("/notifications/" + id).then( e => fetchNotifications() );
}

View File

@ -27,9 +27,6 @@ export function restPatch(endPoint, data) {
return _rest(endPoint, {method: "PATCH", credentials: 'include', body: JSON.stringify(data)}); return _rest(endPoint, {method: "PATCH", credentials: 'include', body: JSON.stringify(data)});
} }
export function postMock(){
return restPost("/mock")
}
/** /**
* backbone for the request made by the frontend * backbone for the request made by the frontend
* *