Merge pull request 'master' (#173) from Maxime/Clyde:master into master
All checks were successful
All checks were successful
Reviewed-on: #173
This commit is contained in:
104
frontend/package-lock.json
generated
104
frontend/package-lock.json
generated
@ -8,6 +8,8 @@
|
||||
"name": "clyde",
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"@canvasjs/vue-charts": "^1.0.4",
|
||||
"@vueuse/core": "^10.9.0",
|
||||
"vite-plugin-top-level-await": "^1.4.1",
|
||||
"vue": "^3.4.15",
|
||||
"vue3-toastify": "^0.2.1"
|
||||
@ -29,6 +31,20 @@
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@canvasjs/charts": {
|
||||
"version": "3.7.45",
|
||||
"resolved": "https://registry.npmjs.org/@canvasjs/charts/-/charts-3.7.45.tgz",
|
||||
"integrity": "sha512-FPMX8wn+PEHzAa/GLBsL5lWB81AzKZLw51t7SiSUjMbtUN5/OIrmDcwUTw+53/Bbdd9gm2LLmxAdZsQ75JI31g=="
|
||||
},
|
||||
"node_modules/@canvasjs/vue-charts": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@canvasjs/vue-charts/-/vue-charts-1.0.4.tgz",
|
||||
"integrity": "sha512-PzOA8xeb/f68a39uoFZNn843dGPU36bsqmbO5DWjP7k6FwkK5AeGkYa/H3RHC02Xc6mG68vg9aFNj2Fyqhu4UQ==",
|
||||
"dependencies": {
|
||||
"@canvasjs/charts": "^3.7.5",
|
||||
"vue": ">=3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/aix-ppc64": {
|
||||
"version": "0.19.12",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz",
|
||||
@ -753,6 +769,11 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
|
||||
"integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw=="
|
||||
},
|
||||
"node_modules/@types/web-bluetooth": {
|
||||
"version": "0.0.20",
|
||||
"resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz",
|
||||
"integrity": "sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow=="
|
||||
},
|
||||
"node_modules/@vitejs/plugin-vue": {
|
||||
"version": "5.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.0.4.tgz",
|
||||
@ -866,6 +887,89 @@
|
||||
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.19.tgz",
|
||||
"integrity": "sha512-/KliRRHMF6LoiThEy+4c1Z4KB/gbPrGjWwJR+crg2otgrf/egKzRaCPvJ51S5oetgsgXLfc4Rm5ZgrKHZrtMSw=="
|
||||
},
|
||||
"node_modules/@vueuse/core": {
|
||||
"version": "10.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.9.0.tgz",
|
||||
"integrity": "sha512-/1vjTol8SXnx6xewDEKfS0Ra//ncg4Hb0DaZiwKf7drgfMsKFExQ+FnnENcN6efPen+1kIzhLQoGSy0eDUVOMg==",
|
||||
"dependencies": {
|
||||
"@types/web-bluetooth": "^0.0.20",
|
||||
"@vueuse/metadata": "10.9.0",
|
||||
"@vueuse/shared": "10.9.0",
|
||||
"vue-demi": ">=0.14.7"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/antfu"
|
||||
}
|
||||
},
|
||||
"node_modules/@vueuse/core/node_modules/vue-demi": {
|
||||
"version": "0.14.7",
|
||||
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.7.tgz",
|
||||
"integrity": "sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==",
|
||||
"hasInstallScript": true,
|
||||
"bin": {
|
||||
"vue-demi-fix": "bin/vue-demi-fix.js",
|
||||
"vue-demi-switch": "bin/vue-demi-switch.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/antfu"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@vue/composition-api": "^1.0.0-rc.1",
|
||||
"vue": "^3.0.0-0 || ^2.6.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@vue/composition-api": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@vueuse/metadata": {
|
||||
"version": "10.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.9.0.tgz",
|
||||
"integrity": "sha512-iddNbg3yZM0X7qFY2sAotomgdHK7YJ6sKUvQqbvwnf7TmaVPxS4EJydcNsVejNdS8iWCtDk+fYXr7E32nyTnGA==",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/antfu"
|
||||
}
|
||||
},
|
||||
"node_modules/@vueuse/shared": {
|
||||
"version": "10.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.9.0.tgz",
|
||||
"integrity": "sha512-Uud2IWncmAfJvRaFYzv5OHDli+FbOzxiVEQdLCKQKLyhz94PIyFC3CHcH7EDMwIn8NPtD06+PNbC/PiO0LGLtw==",
|
||||
"dependencies": {
|
||||
"vue-demi": ">=0.14.7"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/antfu"
|
||||
}
|
||||
},
|
||||
"node_modules/@vueuse/shared/node_modules/vue-demi": {
|
||||
"version": "0.14.7",
|
||||
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.7.tgz",
|
||||
"integrity": "sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==",
|
||||
"hasInstallScript": true,
|
||||
"bin": {
|
||||
"vue-demi-fix": "bin/vue-demi-fix.js",
|
||||
"vue-demi-switch": "bin/vue-demi-switch.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/antfu"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@vue/composition-api": "^1.0.0-rc.1",
|
||||
"vue": "^3.0.0-0 || ^2.6.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@vue/composition-api": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/agent-base": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz",
|
||||
|
@ -9,6 +9,8 @@
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@canvasjs/vue-charts": "^1.0.4",
|
||||
"@vueuse/core": "^10.9.0",
|
||||
"vite-plugin-top-level-await": "^1.4.1",
|
||||
"vue": "^3.4.15",
|
||||
"vue3-toastify": "^0.2.1"
|
||||
|
@ -36,6 +36,9 @@ app.language=Language
|
||||
app.manage.profile=Manage profile
|
||||
app.studentList=Students List
|
||||
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.lessonRequests=Schedule Requests
|
||||
app.payments=Payments
|
||||
@ -121,6 +124,81 @@ Curriculum=curriculum
|
||||
Credits=Credits
|
||||
InscriptionService=I.S.
|
||||
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.name=New forum's name
|
||||
|
@ -36,6 +36,9 @@ app.language=Langue
|
||||
app.manage.profile=Gérer le profil
|
||||
app.studentList=Liste des étudiants
|
||||
app.users=Utilisateurs
|
||||
app.manage.researcherProfile= gérer son profil de chercheur
|
||||
app.list.researches=Lister les recherches
|
||||
app.Create.User=créer un utilisateur
|
||||
app.manageOwnLessons=Gérer ses horaires de cours
|
||||
app.lessonRequests=Requêtes d'horaire
|
||||
app.payments=Payements
|
||||
@ -121,6 +124,79 @@ Curriculum=Cursus
|
||||
Credits=Credits
|
||||
InscriptionService=S.I.
|
||||
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.name=Nom du forum
|
||||
|
@ -169,7 +169,7 @@ window.addEventListener('hashchange', () => {
|
||||
border-color:black;
|
||||
height: 100%;
|
||||
position: fixed;
|
||||
overflow:;
|
||||
overflow: scroll;
|
||||
transition-duration: .3s;
|
||||
}
|
||||
|
||||
|
214
frontend/src/Apps/AboutUser.vue
Normal file
214
frontend/src/Apps/AboutUser.vue
Normal file
@ -0,0 +1,214 @@
|
||||
<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
|
||||
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"
|
||||
"minfos minfos";
|
||||
}
|
||||
|
||||
.profilPic{
|
||||
grid-area:profilPic;
|
||||
}
|
||||
|
||||
.globalInfos {
|
||||
grid-area:globalInfos;
|
||||
align-self :center;
|
||||
|
||||
}
|
||||
|
||||
.body {
|
||||
min-width:960px;
|
||||
width:100%;
|
||||
display:flex;
|
||||
align-items:center;
|
||||
justify-content:center;
|
||||
margin-top:5%;
|
||||
}
|
||||
|
||||
.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>
|
117
frontend/src/Apps/CreateUser.vue
Normal file
117
frontend/src/Apps/CreateUser.vue
Normal file
@ -0,0 +1,117 @@
|
||||
<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>
|
153
frontend/src/Apps/ScientificPublications/FilterComponent.vue
Normal file
153
frontend/src/Apps/ScientificPublications/FilterComponent.vue
Normal file
@ -0,0 +1,153 @@
|
||||
<!----------------------------------------------------
|
||||
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>
|
226
frontend/src/Apps/ScientificPublications/ListResearches.vue
Normal file
226
frontend/src/Apps/ScientificPublications/ListResearches.vue
Normal file
@ -0,0 +1,226 @@
|
||||
<!----------------------------------------------------
|
||||
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
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
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="emit('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{
|
||||
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>
|
@ -0,0 +1,184 @@
|
||||
<!----------------------------------------------------
|
||||
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() />
|
||||
</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>
|
242
frontend/src/Apps/ScientificPublications/ResearchComponent.vue
Normal file
242
frontend/src/Apps/ScientificPublications/ResearchComponent.vue
Normal file
@ -0,0 +1,242 @@
|
||||
<!----------------------------------------------------
|
||||
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(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("See.BibTex")}}</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>
|
@ -0,0 +1,177 @@
|
||||
<!----------------------------------------------------
|
||||
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>
|
171
frontend/src/Apps/ScientificPublications/ResearcherProfile.vue
Normal file
171
frontend/src/Apps/ScientificPublications/ResearcherProfile.vue
Normal file
@ -0,0 +1,171 @@
|
||||
<!----------------------------------------------------
|
||||
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",
|
||||
text: statsOf.value + " By "+ statsBy.value,
|
||||
}
|
||||
let index = (statsOf.value === "views"?0:(statsOf.value === "researches"?3:6)) + (statsBy.value ==="years"?0:(statsBy.value==="months"?1:2))
|
||||
|
||||
if (statsOf.value !== "" && statsBy.value !== "")
|
||||
options.data[0].dataPoints = stats.value[index]
|
||||
|
||||
|
||||
options.title.text = i18n(statsOf.value) +" "+ i18n("By") +" " + i18n(statsBy.value);
|
||||
chart.render();
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div id="main">
|
||||
<div id="profilePicture">
|
||||
<img :src=getPP() />
|
||||
</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="Languages">{{i18n("Language")}}</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="Topics">{{i18n("Domain")}}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div id="statsPie">
|
||||
<CanvasJSChart :options="options" id=chart @chart-ref="c => chart = c "/>
|
||||
</div>
|
||||
</div>
|
||||
<div id="researches"><list-researches :researchList="researchList"></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>
|
@ -1,20 +1,30 @@
|
||||
|
||||
<script setup>
|
||||
import i18n from "@/i18n.js"
|
||||
import { reactive } from 'vue'
|
||||
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();
|
||||
|
||||
</script>
|
||||
<template style="margin-top:5%;">
|
||||
<div style="display:flex; justify-content:center; min-width:1140px;" v-for="item in users">
|
||||
<div class="bodu">
|
||||
<div v-if="list === false">
|
||||
<AboutUser :user=target />
|
||||
<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="role"><a style="margin-left:30px">{{i18n(item.role)}}</a></div>
|
||||
<div class="surname"><a>{{item.lastName}}</a></div>
|
||||
<div class="firstname"><a>{{item.firstName}}</a></div>
|
||||
<div class="infos"><button style="background-color:rgb(105,05,105);" >{{i18n("request.moreInfos")}} </button></div>
|
||||
<div class="infos">
|
||||
<button style="background-color:rgb(105,05,105);" @click="list = false; target = item;">{{i18n("request.moreInfos")}} </button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -70,7 +80,7 @@
|
||||
|
||||
}
|
||||
|
||||
.bodu {
|
||||
.body {
|
||||
margin-top:2%;
|
||||
width:66%;
|
||||
border:2px solid black;
|
||||
|
@ -4,5 +4,8 @@ import 'https://kit.fontawesome.com/fb3bbd0a95.js'
|
||||
|
||||
import { createApp } from 'vue'
|
||||
import App from './App.vue'
|
||||
import CanvasJSChart from '@canvasjs/vue-charts';
|
||||
|
||||
createApp(App).mount('#app')
|
||||
const app = createApp(App);
|
||||
app.use(CanvasJSChart);
|
||||
app.mount('#app');
|
||||
|
32
frontend/src/rest/ScientificPublications/ManageResearch.js
Normal file
32
frontend/src/rest/ScientificPublications/ManageResearch.js
Normal file
@ -0,0 +1,32 @@
|
||||
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")
|
||||
}
|
@ -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)
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
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)
|
||||
}
|
@ -13,6 +13,10 @@ export function disconnect(){
|
||||
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)
|
||||
*
|
||||
@ -44,31 +48,8 @@ export async function register(firstname, lastname, birthDate, password, email,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 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,
|
||||
});
|
||||
export async function postUser(data){
|
||||
return restPost("/user", data)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -16,6 +16,10 @@ import Msg from "@/Apps/Msg.vue"
|
||||
import Forums from '@/Apps/Forums.vue'
|
||||
import Payments from "@/Apps/Inscription/PaymentInfo.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 = {
|
||||
'/schedule': Schedule,
|
||||
@ -26,6 +30,10 @@ const apps = {
|
||||
'/manage-courses' : Courses,
|
||||
'/users-list' : Users,
|
||||
'/students-list' : Students,
|
||||
'/manage-researcher-profile' : ManageResearcherProfile,
|
||||
'/researches' : ListResearches,
|
||||
'/researcher-profile': ResearcherProfile,
|
||||
'/create-user': CreateUser,
|
||||
'/manage-owned-lessons': ManageOwnedLessons,
|
||||
'/manage-schedule-requests' : LessonRequests,
|
||||
'/msg' : Msg,
|
||||
@ -34,6 +42,7 @@ const apps = {
|
||||
}
|
||||
|
||||
const appsList = {
|
||||
'ListResearches': {path:'#/researches', icon:'fa-book-bookmark',text:i18n("app.list.researches")},
|
||||
'Msg': { path: '#/msg', icon: 'fa-comment', text: i18n("app.messages") },
|
||||
'Notification': { path: '#/notifs', icon: 'fa-bell', text: i18n("app.notifications") },
|
||||
'Forum': { path: '#/forums', icon: 'fa-envelope', text: i18n("app.forum") },
|
||||
@ -42,6 +51,8 @@ const appsList = {
|
||||
'ManageCourses': { path: '#/manage-courses', icon: 'fa-book', text: i18n("app.manage.courses") },
|
||||
'StudentsList':{ path: '#/students-list',icon: 'fa-users',text: i18n("app.studentList")},
|
||||
'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")},
|
||||
'LessonRequests':{path: '#/manage-schedule-requests', icon:'fa-book', text: i18n("app.lessonRequests")},
|
||||
'Requests': { path: '#/requests', icon: 'fa-users', text: "Requests" },
|
||||
@ -51,7 +62,7 @@ const appsList = {
|
||||
const currentPath = ref(window.location.hash)
|
||||
|
||||
export const currentView = computed(() => {
|
||||
return apps[currentPath.value.slice(1) || '/']
|
||||
return apps[currentPath.value.split("?")[0].slice(1) || '/']
|
||||
})
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user