Release v0

Optimisations finales
This commit is contained in:
Theal0 2021-05-11 17:46:17 +02:00
parent c6c2f25c80
commit deab35b121
9 changed files with 176 additions and 118 deletions

13
package-lock.json generated
View File

@ -13305,6 +13305,14 @@
}
}
},
"react-device-detect": {
"version": "1.17.0",
"resolved": "https://registry.npmjs.org/react-device-detect/-/react-device-detect-1.17.0.tgz",
"integrity": "sha512-bBblIStwpHmoS281JFIVqeimcN3LhpoP5YKDWzxQdBIUP8S2xPvHDgizLDhUq2ScguLfVPmwfF5y268EEQR60w==",
"requires": {
"ua-parser-js": "^0.7.24"
}
},
"react-dom": {
"version": "17.0.2",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz",
@ -15844,6 +15852,11 @@
"is-typedarray": "^1.0.0"
}
},
"ua-parser-js": {
"version": "0.7.28",
"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.28.tgz",
"integrity": "sha512-6Gurc1n//gjp9eQNXjD9O3M/sMwVtN5S8Lv9bvOYBfKfDNiIIhqiyi01vMBO45u4zkDE420w/e0se7Vs+sIg+g=="
},
"unbox-primitive": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz",

View File

@ -13,6 +13,7 @@
"js-cookies": "^1.0.4",
"react": "^17.0.2",
"react-bootstrap": "^1.5.2",
"react-device-detect": "^1.17.0",
"react-dom": "^17.0.2",
"react-router-dom": "^5.2.0",
"react-scripts": "4.0.3",

View File

@ -1,7 +1,6 @@
import {Link} from "react-router-dom";
import React, {Component} from "react";
import {Link} from "react-router-dom";
import './Style.css'
import SearchStudent from "./SearchStudent";
class ChoixDept extends Component {
constructor(props) {
@ -31,7 +30,7 @@ class ChoixDept extends Component {
render() {
return (
<div className="wrapper">
<h1>Choix du département</h1>
<h1 id="pageTitle">Choix du département</h1>
{this.state.depts.map((dept, index) => {
return (
<div id="wrapDept">

View File

@ -77,10 +77,10 @@ class Etudiant extends Component {
this.state.etud.email !== "" || this.state.etud.emailperso !== "" ?
<div className="col-sm">
<h4>Contact</h4>
{this.state.etud.telephone !== "" && "Téléphone: " + this.state.etud.telephone}<br/>
{this.state.etud.telephonemobile !== "" && "Mobile: " + this.state.etud.telephonemobile}<br/>
{this.state.etud.email !== "" && "Mail étudiant: " + this.state.etud.email}<br/>
{this.state.etud.emailperso !== "" && "Mail perso: " + this.state.etud.emailperso}<br/>
{this.state.etud.telephone !== "" && <a href={'tel:' + this.state.etud.telephone}>Téléphone: {this.state.etud.telephone}</a>}<br/>
{this.state.etud.telephonemobile !== "" && <a href={'tel:' + this.state.etud.telephonemobile}>Mobile: {this.state.etud.telephonemobile}</a>}<br/>
{this.state.etud.email !== "" && <a href={'mailto:' + this.state.etud.email}>Mail étudiant: {this.state.etud.email}</a>}<br/>
{this.state.etud.emailperso !== "" && <a href={'mailto:' + this.state.etud.emailperso}>Mail personnel: {this.state.etud.emailperso}</a>}<br/>
</div>
:
<div className="col-sm">Aucun contact disponible</div>

View File

@ -5,22 +5,63 @@ import Absences from "./GestionSemestre/Absences";
import Eleves from "./GestionSemestre/Eleves";
import ScoNavBar from "./ScoNavBar";
import Bulletin from "./GestionSemestre/Bulletin";
import Select from "react-select";
class GestionSemestre extends Component {
constructor(props){
super(props)
this.state = {
selectOptions: [],
id: "",
name: '',
}
}
componentWillMount() {
let dept = window.location.href.split('/')[6]
let sem = window.location.href.split('/')[8]
let BASE_URL = window.$api_url
fetch(BASE_URL + dept +
'/Scolarite/Notes/groups_view?with_codes=1&format=json&formsemestre_id=' + sem, {
method: 'GET',
verify: false,
credentials: 'include',
})
.then(response =>
response.json().then(data => ({
data: data,
})
).then(res => {
res.data.map((student, index) => {
let joined = this.state.selectOptions.concat({label: student.nom_disp + " " + student.prenom, value: student.etudid});
this.setState({selectOptions: joined})
})
})
);
}
handleSelectChange(e){
this.setState({id:e.value, name:e.label})
}
render() {
return (
<div>
<ScoNavBar/>
<div id="wrapDept">
Choix de l'étudiant
<Select className="mySelect" options={this.state.selectOptions} onChange={this.handleSelectChange.bind(this)}/>
</div>
<div>
<Tabs defaultActiveKey="Accueil" id="controlled-tab-example">
<Tab eventKey="Accueil" title="Acceuil">
<Tab eventKey="Accueil" title="Acceuil" >
<Accueil />
</Tab>
<Tab eventKey="Absences" title="Absences">
<Absences />
<Absences id={this.state.id} name={this.state.name}/>
</Tab>
<Tab eventKey="Bulletin" title="Bulletins">
<Bulletin />
<Bulletin id={this.state.id} name={this.state.name}/>
</Tab>
<Tab eventKey="Eleves" title="Eleves">
<Eleves />

View File

@ -1,50 +1,29 @@
import React, {Component} from "react";
import '../Style.css'
import Select from 'react-select'
class Absences extends Component {
constructor(props){
super(props)
this.state = {
selectOptions: [],
id: "",
name: '',
abs: []
}
}
componentWillMount() {
let dept = window.location.href.split('/')[6]
let sem = window.location.href.split('/')[8]
let BASE_URL = window.$api_url
fetch(BASE_URL + dept +
'/Scolarite/Notes/groups_view?with_codes=1&format=json&formsemestre_id=' + sem, {
method: 'GET',
verify: false,
credentials: 'include',
})
.then(response =>
response.json().then(data => ({
data: data,
})
).then(res => {
res.data.map((student, index) => {
let joined = this.state.selectOptions.concat({label: student.nom_disp + " " + student.prenom, value: student.etudid});
this.setState({selectOptions: joined})
})
})
);
componentDidUpdate(prevProps) {
if (prevProps.id !== this.props.id) {
this.getData();
}
}
handleSelectChange(e){
this.setState({id:e.value, name:e.label}, () => {this.getData()})
componentDidMount() {
if (this.props.id !== "") {this.getData()}
}
getData() {
let dept = window.location.href.split('/')[6]
let BASE_URL = window.$api_url
if (this.state.id !== "") {
fetch(BASE_URL + dept + "/Scolarite/Absences/ListeAbsEtud?format=json&etudid=" + this.state.id, {
fetch(BASE_URL + dept + "/Scolarite/Absences/ListeAbsEtud?format=json&etudid=" + this.props.id, {
method: 'GET',
verify: false,
credentials: 'include',
@ -64,25 +43,26 @@ class Absences extends Component {
return (
<div className="wrapper">
<h1 id="pageTitle">Gestion des absences</h1>
<Select className="mySelect" options={this.state.selectOptions} onChange={this.handleSelectChange.bind(this)}/>
{this.props.name !== "" &&
<div className="col-sm" id="wrapDept">
{this.state.name !== "" && <h4>Absences de {this.state.name}</h4>}
{(this.state.abs.length === 0 && this.state.name !== "") &&
<h6>Aucune absence de l'élève</h6>
<h4>Absences de {this.props.name}</h4>
{(this.state.abs.length === 0 && this.props.name !== "") &&
<h6>Aucune absence de l'élève</h6>
}
{this.state.abs.map((abs, index) => {
return (
<div className="col-sm" id="wrapDept">
<h6>{abs.datedmy} | {abs.matin}</h6>
{abs.motif !== "" &&
<span>Motif: {abs.motif }</span>
<span>Motif: {abs.motif}</span>
} {abs.exams !== "" &&
<span>Exam a rattraper: {abs.exams}</span>
}
<span>Exam a rattraper: {abs.exams}</span>
}
</div>
)
})}
</div>
}
</div>
)
}

View File

@ -1,15 +1,12 @@
import React, {Component} from "react";
import Select from "react-select";
import {Table} from "react-bootstrap"
import {Table, Button, Dropdown} from "react-bootstrap"
import '../Style.css'
class Bulletin extends Component {
constructor(props) {
super(props);
this.state = {
selectOptions: [],
id: "",
name: '',
bltn: {},
datue: {},
loaded: false
@ -18,29 +15,6 @@ class Bulletin extends Component {
this.getJsonData = this.getJsonData.bind(this);
}
componentWillMount() {
let dept = window.location.href.split('/')[6]
let sem = window.location.href.split('/')[8]
let BASE_URL = window.$api_url
fetch(BASE_URL + dept +
'/Scolarite/Notes/groups_view?with_codes=1&format=json&formsemestre_id=' + sem, {
method: 'GET',
verify: false,
credentials: 'include',
})
.then(response =>
response.json().then(data => ({
data: data,
})
).then(res => {
res.data.map((student, index) => {
let joined = this.state.selectOptions.concat({label: student.nom_disp + " " + student.prenom, value: student.etudid});
this.setState({selectOptions: joined})
})
})
);
}
getJsonData () {
this.setState({bltn: require('..\\..\\json\\bltn.json')}, () => {
let ls = {}
@ -60,7 +34,7 @@ class Bulletin extends Component {
let sem = window.location.href.split('/')[8]
let BASE_URL = window.$api_url
fetch(BASE_URL + dept + '/Scolarite/Notes/formsemestre_bulletinetud?formsemestre_id=' +
sem +'&etudid=' + this.state.id +'&format=json', {
sem +'&etudid=' + this.props.id +'&format=json', {
method: 'GET',
verify: false,
credentials: 'include',
@ -85,40 +59,62 @@ class Bulletin extends Component {
);
}
handleSelectChange(e){
this.setState({id:e.value, name:e.label}, () => {this.getData()})
getPdf() {
let BASE_URL = window.$api_url
let dept = window.location.href.split('/')[6]
let sem = window.location.href.split('/')[8]
fetch( BASE_URL + dept + "/Scolarite/Notes/formsemestre_bulletinetud?" +
"formsemestre_id=" + sem + "&etudid=" + this.props.id + "&format=pdf&version=selectedevals", {
method: 'GET',
verify: false,
credentials: 'include',
})
.then( res => res.blob() )
.then( blob => {
let file = window.URL.createObjectURL(blob);
window.location.assign(file);
});
}
componentDidUpdate(prevProps) {
if (prevProps.id !== this.props.id) {
this.getData();
}
}
componentDidMount() {
if (this.props.id !== "") {this.getData()}
}
render() {
return (
<div className="wrapper">
<h1 id="pageTitle">Bulletins de notes</h1>
<Select className="mySelect" options={this.state.selectOptions} onChange={this.handleSelectChange.bind(this)}/>
<div style={{"margin-bottom": "20px"}}>
<h1 id="pageTitle">Bulletins de notes</h1>
</div>
{this.state.loaded === true &&
<div>
<h2>Bulletin de {this.state.name}</h2>
<Table responsive="sm">
<thead>
<tr>
<th colSpan="3"/>
<th>Rang</th>
<th colSpan="2">Promotion</th>
<th>Note/20</th>
<th>Coef.</th>
</tr>
<tr className="smallRow">
<th colSpan="4"/>
<th>Mini</th>
<th>Maxi</th>
<th colSpan="2"/>
</tr>
<tr className="bigRow">
<th colSpan="3">Moyenne générale</th>
<th>{this.state.bltn.rang.value}/{this.state.bltn.rang.ninscrits}</th>
<th>{this.state.bltn.note.min}</th>
<th>{this.state.bltn.note.max}</th>
<th>{this.state.bltn.note.value}</th>
<th/>
<th>
<Dropdown>
<Dropdown.Toggle variant="primary" size="sm" id="dropdown-basic">
{this.state.bltn.note.value}
</Dropdown.Toggle>
<Dropdown.Menu>
<Dropdown.Item href="#">Min: {this.state.bltn.note.min}</Dropdown.Item>
<Dropdown.Item href="#">Max: {this.state.bltn.note.max}</Dropdown.Item>
<Dropdown.Item href="#">Classement: {this.state.bltn.rang.value}/{this.state.bltn.rang.ninscrits}</Dropdown.Item>
</Dropdown.Menu>
</Dropdown>
</th>
</tr>
</thead>
{this.state.bltn.ue.map((ue, index) => {
@ -126,21 +122,38 @@ class Bulletin extends Component {
<tbody>
<tr className="ueRow">
<td colSpan="3">{ue.acronyme} - {this.state.datue[ue.acronyme]}</td>
<td>{ue.rang}/{this.state.bltn.rang.ninscrits}</td>
<td>{ue.note.min}</td>
<td>{ue.note.max}</td>
<td>{ue.note.value}</td>
<td>{/*Coef*/}</td>
<td>
<Dropdown>
<Dropdown.Toggle variant="primary" size="sm" id={ue.acronyme}>
{ue.note.value}
</Dropdown.Toggle>
<Dropdown.Menu>
<Dropdown.Item href="#">Min: {ue.note.min}</Dropdown.Item>
<Dropdown.Item href="#">Max: {ue.note.max}</Dropdown.Item>
<Dropdown.Item href="#">Classement: {ue.rang}/{this.state.bltn.rang.ninscrits}</Dropdown.Item>
</Dropdown.Menu>
</Dropdown>
</td>
</tr>
{ue.module.map((mod, index) => {
return (
<tr>
<td colSpan="3">{mod.titre.replace("&apos;", "'")}</td>
<td>{mod.rang.value}/{this.state.bltn.rang.ninscrits}</td>
<td>{mod.note.min}</td>
<td>{mod.note.max}</td>
<td>{mod.note.value}</td>
<td>{mod.coefficient}</td>
<td>
<Dropdown>
<Dropdown.Toggle variant="primary" size="sm" id={mod.code}>
{mod.note.value}
</Dropdown.Toggle>
<Dropdown.Menu>
<Dropdown.Item href="#">Min: {mod.note.min}</Dropdown.Item>
<Dropdown.Item href="#">Max: {mod.note.max}</Dropdown.Item>
<Dropdown.Item href="#">Classement: {mod.rang.value}/{this.state.bltn.rang.ninscrits}</Dropdown.Item>
<Dropdown.Item href="#">Coefficient: {mod.coefficient}</Dropdown.Item>
</Dropdown.Menu>
</Dropdown>
</td>
</tr>
)
})}
@ -148,6 +161,9 @@ class Bulletin extends Component {
)
})}
</Table>
<div>
<Button className="btn-primary" onClick={() => {this.getPdf()}}>Version PDF</Button>
</div>
</div>
}
</div>

View File

@ -1,4 +1,6 @@
import React, {Component} from "react";
import React, {Component, useState} from "react";
import { isMobile } from 'react-device-detect';
import {Modal, Button} from 'react-bootstrap'
import './Style.css'
import ChoixDept from "./ChoixDept";
import ScoNavBar from "./ScoNavBar";
@ -9,7 +11,7 @@ class Login extends Component {
this.state = {
login: "",
pass: "",
status: 0
status: 0,
};
this.handleChangeLogin = this.handleChangeLogin.bind(this);
this.handleChangePass = this.handleChangePass.bind(this);
@ -25,6 +27,8 @@ class Login extends Component {
}
checkCredentials(e) {
e.preventDefault();
let login = this.state.login
let pass = this.state.pass
@ -41,17 +45,18 @@ class Login extends Component {
})
.then(res => {
this.setState({ status: res["status"] });
console.log("Cookie (get): " + res.headers.get('Set-Cookie'));
console.log("Cookie (doc): " + document.cookie);
})
.catch(console.log)
e.preventDefault()
}
render() {
return (
<div>
{!isMobile &&
// TODO: Redirection mobile/desktop
<span/>
}
{(this.state.status !== 0 && this.state.status !== 200) &&
<div className="wrapper">
<div id="errorMsg">
@ -59,7 +64,7 @@ class Login extends Component {
</div>
</div>
}
{this.state.status !== 200 &&
{document.cookie === "" &&
<div className="wrapper">
<div id="formContent">
<h2 id="loginTitle">Connexion a ScoDoc</h2>
@ -73,9 +78,9 @@ class Login extends Component {
</div>
}
<div>
{this.state.status === 200 &&
{document.cookie !== "" &&
<ScoNavBar/>
}{this.state.status === 200 &&
}{document.cookie !== "" &&
<ChoixDept/>
}
</div>

View File

@ -1,7 +1,7 @@
import React, {Component} from "react";
import {Link, Redirect} from "react-router-dom";
import './Style.css'
import {Nav, Navbar, Button, Container} from 'react-bootstrap'
import { Redirect } from 'react-router-dom';
import './Style.css'
class ScoNavBar extends Component {
constructor(props) {
@ -9,6 +9,7 @@ class ScoNavBar extends Component {
this.state = {
login: {},
semestre: {},
logout: false
};
}
@ -16,7 +17,7 @@ class ScoNavBar extends Component {
let BASE_URL = window.$api_url
fetch(BASE_URL + "acl_users/logout")
.then(res => {return <Redirect to="/" />})
.then(res => {this.setState({logout: true})})
.catch(console.log)
}
@ -24,7 +25,7 @@ class ScoNavBar extends Component {
return (
<Navbar bg="light" expand="sm">
<Container>
<Navbar.Brand>
<Navbar.Brand href={window.$api_url + "static/mobile/"}>
<img
alt="ScodocLogo"
src="/ScoDoc/static/icons/scologo_img.png"
@ -37,12 +38,14 @@ class ScoNavBar extends Component {
<Navbar.Toggle aria-controls="basic-navbar-nav" />
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="ml-auto">
<Link to="/ScoDoc/static/mobile/">
<Button variant="primary" onClick={() => {this.logout()}}>Déconnexion</Button>
</Link>
<Nav.Link href="/ScoDoc">Version Desktop</Nav.Link>
<Button variant="primary" onClick={() => {this.logout()}}>Déconnexion</Button>
</Nav>
</Navbar.Collapse>
</Container>
{this.state.logout === true &&
<Redirect push to={window.$api_url + 'static/mobile/'}/>
}
</Navbar>
)
}