1
0
forked from PGL/Clyde

Compare commits

...

2 Commits

Author SHA1 Message Date
3281bf1d7e patch Researcher Profile and researches 2024-04-17 23:00:37 +02:00
47f1bffb24 backend fixed Patch Research 2024-04-17 23:00:00 +02:00
10 changed files with 432 additions and 39 deletions

View File

@ -80,9 +80,10 @@ public class ResearcherController {
Researcher researcher = researchesServ.getResearcherById(id); Researcher researcher = researchesServ.getResearcherById(id);
if (authServ.isNotIn(new Role[]{Role.Secretary,Role.Admin}, token) if (authServ.isNotIn(new Role[]{Role.Secretary,Role.Admin}, token)
|| researcher == researchesServ.getResearcherByUser(authServ.getUserFromToken(token))) && researcher.getId() != researchesServ.getResearcherByUser(authServ.getUserFromToken(token)).getId())
return new UnauthorizedResponse<>(null); return new UnauthorizedResponse<>(null);
if (researcher == null) return new ResponseEntity<>(HttpStatus.BAD_REQUEST); if (researcher == null) return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
researchesServ.modifyResearcherData(researcher,updates); researchesServ.modifyResearcherData(researcher,updates);

View File

@ -83,18 +83,9 @@ public class ResearchesService {
case "title": case "title":
research.setTitle((String) entry.getValue()); research.setTitle((String) entry.getValue());
break; break;
case "date":
research.setReleaseDate((Date) entry.getValue());
break;
case "paperType": case "paperType":
research.setPaperType((PaperType) entry.getValue()); research.setPaperType((PaperType) entry.getValue());
break; break;
case "PdfLocation":
research.setPdfLocation((String) entry.getValue());
break;
case "bibtexLocation":
research.setBibTexLocation((String) entry.getValue());
break;
case "language": case "language":
research.setLanguage((String) entry.getValue()); research.setLanguage((String) entry.getValue());
break; break;
@ -104,6 +95,9 @@ public class ResearchesService {
case "summary": case "summary":
research.setSummary((String) entry.getValue()); research.setSummary((String) entry.getValue());
break; break;
case "access":
research.setAccess(Access.valueOf((String) entry.getValue()));
break;
} }
} }
articleRepo.save(research); articleRepo.save(research);
@ -175,12 +169,15 @@ public class ResearchesService {
for (Map.Entry<String, Object> entry : updates.entrySet()){ for (Map.Entry<String, Object> entry : updates.entrySet()){
switch (entry.getKey()){ switch (entry.getKey()){
case "orcidId": case "orcidId":
if (entry.getValue() != null)
researcher.setOrcidId((String) entry.getValue()); researcher.setOrcidId((String) entry.getValue());
break; break;
case "domain": case "domain":
if (entry.getValue() != null)
researcher.setDomain((String) entry.getValue()); researcher.setDomain((String) entry.getValue());
break; break;
case "site": case "site":
if (entry.getValue() != null)
researcher.setSite((String) entry.getValue()); researcher.setSite((String) entry.getValue());
break; break;
} }

View File

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

View File

@ -5,13 +5,15 @@
Description: Pop Up summarizing Description: Pop Up summarizing
-----------------------------------------------------> ----------------------------------------------------->
<script setup> <script setup xmlns="http://www.w3.org/1999/html">
import {ref } from "vue"; import {ref } from "vue";
import {onClickOutside} from '@vueuse/core' import {onClickOutside} from '@vueuse/core'
import {patchArticle, deleteArticle} from "@/rest/ScientificPublications/ManageResearch.js";
const props = defineProps({ const props = defineProps({
isOpen: Boolean, isOpen: Boolean,
article: ref(Object) article: ref(Object),
manage:Boolean,
}); });
function format(date){ function format(date){
let split = date.split("-") let split = date.split("-")
@ -21,19 +23,37 @@ function format(date){
return day +"/"+ month +"/"+ year return day +"/"+ month +"/"+ year
} }
const emit = defineEmits(["modal-close","downloadPdf","downloadBibTex"]); const emit = defineEmits(["modal-close","downloadPdf","downloadBibTex"]);
const target = ref(null) const target = ref(null)
onClickOutside(target, ()=>emit('modal-close')) onClickOutside(target, ()=>emit('modal-close'))
let toModify= Object.assign({}, {});
function cancelChanges(){
toModify= Object.assign({}, {});
emit('modal-close')
}
function confirmChanges(){
patchArticle(props.article.id, toModify)
toModify= Object.assign({}, {});
emit('modal-close')
}
function deleteThisArticle(){
deleteArticle(props.article.id)
emit('modal-close')
}
</script> </script>
<template> <template>
<div v-if="isOpen" class="modal-mask"> <div v-if="isOpen" class="modal-mask">
<div class="modal-wrapper"> <div class="modal-wrapper">
<div class="modal-container" ref="target"> <div class="modal-container" ref="target">
<ul> <div ><ul>
<li>Article Id : {{article.id}}</li> <li>Article Id : {{article.id}}</li>
<li>Title : {{article.title}}</li> <li>Title : {{article.title}}</li>
<li>Author : {{article.researcher.user.lastName + " " + article.researcher.user.firstName}}</li> <li>Author : {{article.researcher.user.lastName + " " + article.researcher.user.firstName}}</li>
@ -49,6 +69,27 @@ onClickOutside(target, ()=>emit('modal-close'))
<button @click.stop="emit('downloadBibTex')">Download BibTex</button> <button @click.stop="emit('downloadBibTex')">Download BibTex</button>
<button @click.stop="emit('downloadPdf')">Download Research</button> <button @click.stop="emit('downloadPdf')">Download Research</button>
</div> </div>
</div>
<div v-if="manage">
<div>
<ul>
<li>Title : <input v-model="toModify.title"></li>
<li>Language : <input v-model="toModify.language"></li>
<li>Summary : <input v-model="toModify.summary"></li>
<li>Domain : <input v-model="toModify.domain"></li>
<li>Access :
<select @change="update()" id="classed-select" v-model="toModify.access">
<option value="OpenSource">OpenSource</option>
<option value="Restricted">Restricted</option>
<option value="Private">Private</option>
</select></li>
</ul>
</div>
<button id="confirmButton" @click="confirmChanges">Confirm Changes</button>
<button id="cancelButton" @click="cancelChanges">Cancel Changes</button>
<button id="deleteButton" @click="deleteThisArticle">Delete Research </button>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -95,4 +136,44 @@ onClickOutside(target, ()=>emit('modal-close'))
background: rgba(191, 64, 191); background: rgba(191, 64, 191);
} }
#deleteButton{
margin-left: 80%;
align-self: center;
text-align: center;
border: 2px solid black;
color: white;
font-size: large;
border-radius: 20px;
background-color: red;
}
#deleteButton:hover{
background: #ff2d55;
}
#cancelButton{
align-self: center;
text-align: center;
border: 2px solid black;
color: white;
font-size: x-large;
background-color:rgba(191, 64, 191,0.5);
border-radius: 20px;
}
#cancelButton:hover{
background:rgba(191,64,191)
}
#confirmButton{
align-self: center;
text-align: center;
border: 2px solid black;
color: white;
font-size: x-large;
background-color: #07bc0c;
border-radius: 20px;
}
#confirmButton:hover{
background: #4cd964;
}
</style> </style>

View File

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

View File

@ -0,0 +1,8 @@
import { restGet, restPost, restDelete, restPatch } from '../restConsumer.js'
export async function deleteArticle(id){
await restDelete("/research/" + id)
}
export async function patchArticle(id, data){
await restPatch("/research/" + id, data)
}

View File

@ -0,0 +1,9 @@
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

@ -19,7 +19,3 @@ 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" const restURL = import.meta.env.VITE_CLYDE_MODE === 'container' ? "http://localhost:8000": import.meta.env.DEV ? "http://localhost:5173" : "https://clyde.herisson.ovh/api"
await fetch(restURL + "/"+url, {method: "GET"}) await fetch(restURL + "/"+url, {method: "GET"})
} }
export async function getSelf(){
return restGet("/researcher")
}

View File

@ -9,7 +9,6 @@ import Profil from "@/Apps/Profil.vue"
import Courses from "@/Apps/ManageCourses.vue" import Courses from "@/Apps/ManageCourses.vue"
import Users from "@/Apps/UsersList.vue" import Users from "@/Apps/UsersList.vue"
import Students from "@/Apps/StudentsList.vue" import Students from "@/Apps/StudentsList.vue"
import ResearcherProfile from "@/Apps/ScientificPublications/ResearcherProfile.vue";
import AboutStudent from "@/Apps/Inscription/AboutStudent.vue"; import AboutStudent from "@/Apps/Inscription/AboutStudent.vue";
import Msg from "@/Apps/Msg.vue" import Msg from "@/Apps/Msg.vue"
import ManageRequests from "@/Apps/Inscription/ManageRequests.vue"; import ManageRequests from "@/Apps/Inscription/ManageRequests.vue";
@ -35,7 +34,7 @@ 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:'#/researcher-profile',icon:'fa-book-bookmark',text:i18n("app.manage.researcherProfile")}, 'ManageResearcherProfile':{path:'#/manage-researcher-profile',icon:'fa-book-bookmark',text:i18n("app.manage.researcherProfile")},
} }
const currentPath = ref(window.location.hash) const currentPath = ref(window.location.hash)

View File

@ -8,7 +8,6 @@ import { restGet, restPost, restDelete, restPatch } from './restConsumer.js'
* Create a new course * Create a new course
*/ */
export async function createCourse(name, credits, owner){ export async function createCourse(name, credits, owner){
console.log(owner);
return restPost("/course", {title: name, credits: credits, owner} ) return restPost("/course", {title: name, credits: credits, owner} )
} }