Compare commits

...

4 Commits
1.3 ... master

Author SHA1 Message Date
Theal0 58756dcc22 Release 1.7
Ajout d'un bouton "Retour au choix de semestre" dans la navbar
2021-06-28 22:33:53 +02:00
Theal0 5e00bd068c Release 1.6
Améliorations mineures de l'interface
Fix: "Absences de undefined" + Erreur
2021-06-11 12:53:42 +02:00
Theal0 ef3c3ce7b8 Release 1.5
Ajout de filtrage par groupe de TD/TP sur la page des étudiants inscrits au semestre
2021-06-11 02:02:21 +02:00
Theal0 3725d508ab Release 1.4
Erreur de la page blanche liée a une valeur de rang inexistant résolu
2021-06-10 12:47:28 +02:00
6 changed files with 124 additions and 25 deletions

View File

@ -2,13 +2,13 @@
## Description
Version mobile de l'application web ScoDoc (v1.3)
Version mobile de l'application web ScoDoc (v1.7)
### Fonctionnalités:
- Login
- Choix de département / formation
- Affichage des profils étudiants
- Recherche d'élèves
- Recherche d'élèves | Filtrage par groupe de TD/TP
- Affichage des bulletins de notes
- Gestion des absences

View File

@ -115,16 +115,18 @@ class Etudiant extends Component {
<Link to={{
pathname: `/${window.location.href.split('/')[7]}/Scolarite/${sem.formsemestre_id}/GestionSem`,
tab: "Absences",
etudid: window.location.href.split('/')[10]
etudid: window.location.href.split('/')[10],
name: this.state.etud.nomprenom
}}>
<Button variant="primary" style={{"margin-right": "2px"}}>Vers Absences</Button>
<Button variant="primary" style={{"margin-right": "2px", "margin-bottom": "2px"}}>Vers Absences</Button>
</Link>
<Link to={{
pathname: `/${window.location.href.split('/')[7]}/Scolarite/${sem.formsemestre_id}/GestionSem`,
tab: "Bulletin",
etudid: window.location.href.split('/')[10]
etudid: window.location.href.split('/')[10],
name: this.state.etud.nomprenom
}}>
<Button variant="primary" style={{"margin-left": "2px"}}>Vers bulletin</Button>
<Button variant="primary" style={{"margin-left": "2px", "margin-bottom": "2px"}}>Vers bulletin</Button>
</Link>
</div>
)

View File

@ -1,5 +1,5 @@
import React, {Component} from "react";
import {Tabs, Tab} from "react-bootstrap"
import {Tabs, Tab, Nav, NavItem, NavLink} from "react-bootstrap"
import Accueil from "./GestionSemestre/Accueil";
import Absences from "./GestionSemestre/Absences";
import Etudiants from "./GestionSemestre/Etudiants";
@ -17,7 +17,8 @@ class GestionSemestre extends Component {
id: "",
name: '',
defaulttab: "Accueil",
defaultsel: ""
defaultsel: "",
loading: true
}
}
@ -26,7 +27,7 @@ class GestionSemestre extends Component {
if (this.props.location.tab) {
this.setState({defaulttab: this.props.location.tab, defaultsel: this.props.location.etudid,
id: this.props.location.etudid, name: this.state.selectOptions.find(option => option.value === this.state.id)
id: this.props.location.etudid, name: this.props.location.name
})
}
}
@ -44,7 +45,7 @@ class GestionSemestre extends Component {
// Création d'une liste pour le select
res.data.map((student) => {
let joined = this.state.selectOptions.concat({label: student.nom_disp + " " + student.prenom, value: student.etudid});
this.setState({selectOptions: joined})
this.setState({selectOptions: joined, loading: false})
})
})
}
@ -62,20 +63,23 @@ class GestionSemestre extends Component {
{/* Selection de l'étudiant pour les sous-composants */}
<div className="col-sm" id="wrapDept">
Choix de l'étudiant
<Select className="mySelect" options={this.state.selectOptions} onChange={this.handleSelectChange.bind(this)}
<Select className="mySelect"
isLoading={this.state.loading}
options={this.state.selectOptions}
onChange={this.handleSelectChange.bind(this)}
value={this.state.selectOptions.find(option => option.value === this.state.defaultsel)} />
</div>
</div>
</div>
<div>
<Tabs defaultActiveKey={this.state.defaulttab} id="controlled-tab-example">
<Tab eventKey="Accueil" title="Accueil" >
<Tabs fill defaultActiveKey={this.state.defaulttab} id="controlled-tab-example" variant="pills">
<Tab eventKey="Accueil" title="Accueil">
<Accueil />
</Tab>
<Tab eventKey="Absences" title="Absences">
<Absences id={this.state.id} name={this.state.name}/>
</Tab>
<Tab eventKey="Bulletin" title="Bulletin">
<Tab eventKey="Bulletin" title="Bulletins">
<Bulletin id={this.state.id} name={this.state.name}/>
</Tab>
<Tab eventKey="Etud" title="Etudiants">

View File

@ -99,7 +99,9 @@ class Bulletin extends Component {
<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>
{this.state.bltn.hasOwnProperty('rang') &&
<Dropdown.Item href="#">Classement: {this.state.bltn.rang.value}/{this.state.bltn.rang.ninscrits}</Dropdown.Item>
}
</Dropdown.Menu>
</Dropdown>
</th>
@ -119,7 +121,9 @@ class Bulletin extends Component {
<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>
{ue.hasOwnProperty('rang') &&
<Dropdown.Item href="#">Classement: {ue.rang}/{this.state.bltn.rang.ninscrits}</Dropdown.Item>
}
</Dropdown.Menu>
</Dropdown>
</td>
@ -137,7 +141,9 @@ class Bulletin extends Component {
<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>
{mod.hasOwnProperty('rang') &&
<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>

View File

@ -4,6 +4,33 @@ import '../Style.css'
import {Link} from "react-router-dom";
import {getJson} from "../Request";
import {Spinner} from "react-bootstrap";
import Select from "react-select";
// CONSTANTES DE STYLE SELECT GROUP
const groupStyles = {
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
};
const groupBadgeStyles = {
backgroundColor: '#EBECF0',
borderRadius: '2em',
color: '#172B4D',
display: 'inline-block',
fontSize: 12,
fontWeight: 'normal',
lineHeight: '1',
minWidth: 1,
padding: '0.16666666666667em 0.5em',
textAlign: 'center',
};
const formatGroupLabel = data => (
<div style={groupStyles}>
<span>{data.label}</span>
<span style={groupBadgeStyles}>{data.options.length}</span>
</div>
);
/** Page de présentation des étudiants inscrits au semestre */
class Etudiants extends Component {
@ -12,16 +39,21 @@ class Etudiants extends Component {
this.state = {
// Liste des étudiants inscrits au semestre
students: [],
// Gestion du select
selectOptions: [{label: "Groupe: Aucun", value: "Default"}],
id: "",
name: '',
};
}
componentWillMount() {
// this.getData()
this.getData()
}
componentDidUpdate(prevProps) {
if (prevProps !== this.props) {
if (this.props.students.length) {
if (this.props.students.length && this.state.students.length === 0) {
const dat = this.props.students.map((x,i) => {
return i % 2 === 0 ? this.props.students.slice(i, i+2) : null;
}).filter(x => x != null);
@ -31,27 +63,74 @@ class Etudiants extends Component {
}
/**
* Recupère la liste des étudiants inscrits au semestre depuis l'API
* Recupère la liste des groupes du semestre depuis l'API
*/
getData() {
let dept = window.location.href.split('/')[7]
let sem = window.location.href.split('/')[9]
let BASE_URL = window.$api_url
getJson(BASE_URL + dept + '/Scolarite/Notes/groups_view?with_codes=1&format=json&formsemestre_id=' + sem)
getJson(BASE_URL + dept + '/Scolarite/formsemestre_partition_list?format=json&formsemestre_id=' + sem)
.then(res => {
// eslint-disable-next-line array-callback-return
res.data.map((part) => {
// Ajout de la catégorie
let new_part = {label: part.partition_name, options: []}
// Ajout des groupes
// eslint-disable-next-line array-callback-return
part.group.map((group) => {
new_part.options.push({label: group.group_name, value: group.group_id})
})
// Ajout au state
let joined = this.state.selectOptions.concat(new_part);
this.setState({ selectOptions: joined})
})
})
}
/**
* Recupère la liste des étudiants dans un groupe depuis l'API
*/
getStudents() {
let dept = window.location.href.split('/')[7]
let group = this.state.id
let BASE_URL = window.$api_url
getJson(BASE_URL + dept + '/Scolarite/groups_view?with_codes=1&format=json&group_ids=' + group)
.then(res => {
// Gestion des données sous forme de tableau a deux colonnes
const dat = res.data.map((x,i) => {
return i % 2 === 0 ? res.data.slice(i, i+2) : null;
}).filter(x => x != null);
this.setState({ students: dat});
this.setState({students: dat});
})
}
/**
* Gestion des données du Select
*/
handleSelectChange(e){
this.setState({id:e.value, name:e.label}, () => {
if (this.state.id !== "Default") {this.getStudents()}
else {
if (this.props.students.length) {
const dat = this.props.students.map((x,i) => {
return i % 2 === 0 ? this.props.students.slice(i, i+2) : null;
}).filter(x => x != null);
this.setState({ students: dat});
}
}
})
}
render() {
return (
<div className="wrapper">
<h1 id="pageTitle">Liste des étudiants</h1>
<div className="container">
<Select
defaultValue={this.state.selectOptions[0]}
options={this.state.selectOptions}
formatGroupLabel={formatGroupLabel}
onChange={this.handleSelectChange.bind(this)}
/>
{this.state.students.length !== 0 ?
this.state.students.map((students) => {
// Creation du tableau de deux colonnes

View File

@ -37,8 +37,16 @@ class ScoNavBar extends Component {
<Navbar.Toggle aria-controls="basic-navbar-nav" />
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="ml-auto">
<Nav.Link href="/ScoDoc">Version Desktop</Nav.Link>
<Button variant="primary" onClick={() => {this.logout()}}>Déconnexion</Button>
<Button variant="outline-primary" href="/ScoDoc" style={{"margin": "1px"}}>Version Desktop</Button>
{window.location.href.split('/').length > 9 &&
<Button
variant="outline-primary"
href={"/ScoDoc/static/mobile/#/" + window.location.href.split('/')[7] + "/Scolarite"}
style={{"margin": "1px"}}>
Retour au choix de semestre
</Button>
}
<Button variant="primary" style={{"margin": "1px"}} onClick={() => {this.logout()}}>Déconnexion</Button>
</Nav>
</Navbar.Collapse>
</Container>