Merge branch 'master' of https://scodoc.org/git/viennet/ScoDoc into refactor_nt

This commit is contained in:
Emmanuel Viennet 2021-12-24 00:09:40 +01:00
commit adaef9fd24
11 changed files with 156 additions and 20 deletions

View File

@ -89,7 +89,8 @@ CSSSTYLES = html_sco_header.BOOTSTRAP_MULTISELECT_CSS
# - only one operation found: execute and go to main page
# - more than 1 operation found. asked form confirmation (and execution if confirmed)
#
# Someday we'll have time to refactor as abstract classes but Abstract FieldList makes this a bit complicated
# Someday we'll have time to refactor as abstract classes but Abstract FieldList makes this
# a bit complicated
# """
# Terminology:

View File

@ -0,0 +1,64 @@
# -*- mode: python -*-
# -*- coding: utf-8 -*-
##############################################################################
#
# ScoDoc
#
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# Emmanuel Viennet emmanuel.viennet@viennet.net
#
##############################################################################
"""
Formulaires création département
"""
from flask import flash, url_for, redirect, render_template
from flask_wtf import FlaskForm
from wtforms import SelectField, SubmitField, FormField, validators, FieldList
from wtforms.fields.simple import StringField, HiddenField
from app import AccessDenied
from app.models import Departement
from app.models import ScoPreference
from app.models import SHORT_STR_LEN
from app.scodoc import sco_utils as scu
from flask_login import current_user
class CreateDeptForm(FlaskForm):
"""Formulaire permettant l'ajout d'un département"""
acronym = StringField(
label="Acronyme",
validators=[
validators.regexp(
r"^[a-zA-Z0-9_\-]*$",
message="Ne doit comporter que lettres, chiffres ou -",
),
validators.Length(
max=SHORT_STR_LEN,
message=f"L'acronyme ne doit pas dépasser {SHORT_STR_LEN} caractères",
),
validators.DataRequired("acronyme du département requis"),
],
)
submit = SubmitField("Valider")
cancel = SubmitField("Annuler", render_kw={"formnovalidate": True})

View File

@ -47,3 +47,15 @@ class Departement(db.Model):
def from_acronym(cls, acronym):
dept = cls.query.filter_by(acronym=acronym).first_or_404()
return dept
def create_dept(acronym: str) -> Departement:
"Create new departement"
from app.models import ScoPreference
departement = Departement(acronym=acronym)
p1 = ScoPreference(name="DeptName", value=acronym, departement=departement)
db.session.add(p1)
db.session.add(departement)
db.session.commit()
return departement

View File

@ -98,6 +98,10 @@ section>div:nth-child(1){
/************/
/* Etudiant */
/************/
.info_etudiant{
color: #000;
text-decoration: none;
}
.etudiant{
display: flex;
align-items: center;
@ -194,6 +198,9 @@ h3{
.info{
opacity: 0.9;
}
.syntheseModule{
cursor: pointer;
}
.eval, .syntheseModule{
position: relative;
display: flex;

View File

@ -27,6 +27,10 @@ class releveBUT extends HTMLElement {
moduleOnOff(){
this.parentElement.classList.toggle("moduleOnOff");
}
goTo(){
let module = this.dataset.module;
this.parentElement.parentElement.parentElement.parentElement.querySelector("#Module_" + module).scrollIntoView();
}
set setConfig(config){
this.config.showURL = config.showURL ?? this.config.showURL;
@ -46,6 +50,9 @@ class releveBUT extends HTMLElement {
this.shadow.querySelectorAll(".ue, .module").forEach(e => {
e.addEventListener("click", this.moduleOnOff)
})
this.shadow.querySelectorAll(".syntheseModule").forEach(e => {
e.addEventListener("click", this.goTo)
})
this.shadow.children[0].classList.add("ready");
}
@ -132,8 +139,15 @@ class releveBUT extends HTMLElement {
showInformations(data) {
this.shadow.querySelector(".studentPic").src = data.etudiant.photo_url || "default_Student.svg";
let output = `
<div class=info_etudiant>
let output = '';
if(this.config.showURL){
output += `<a href="${data.etudiant.fiche_url}" class=info_etudiant>`;
} else {
output += `<div class=info_etudiant>`;
}
output += `
<div class=civilite>
${this.civilite(data.etudiant.civilite)}
${data.etudiant.nom}
@ -150,8 +164,12 @@ class releveBUT extends HTMLElement {
Code INE : ${data.etudiant.code_ine}
</div>
<div>${data.formation.titre}</div>
</div>
`;
if(this.config.showURL){
output += `</a>`;
} else {
output += `</div>`;
}
this.shadow.querySelector(".infoEtudiant").innerHTML = output;
}
@ -226,8 +244,8 @@ class releveBUT extends HTMLElement {
let titre = data.ressources[module]?.titre || data.saes[module]?.titre;
let url = data.ressources[module]?.url || data.saes[module]?.url;
output += `
<div class=syntheseModule>
<div>${this.URL(url, `${module}&nbsp;- ${titre}`)}</div>
<div class=syntheseModule data-module="${module.replace(/[^a-zA-Z0-9]/g, "")}">
<div>${module}&nbsp;- ${titre}</div>
<div>
${dataModule.moyenne}
<em>Coef.&nbsp;${dataModule.coef}</em>
@ -249,7 +267,7 @@ class releveBUT extends HTMLElement {
let output = "";
Object.entries(module).forEach(([numero, content]) => {
output += `
<div>
<div id="Module_${numero.replace(/[^a-zA-Z0-9]/g, "")}">
<div class=module>
<h3>${this.URL(content.url, `${numero} - ${content.titre}`)}</h3>
<div>

View File

@ -25,6 +25,7 @@
display: none;
}`;
releve.shadowRoot.appendChild(style);
})
});
document.querySelector("html").style.scrollBehavior = "smooth";
</script>
{% endblock %}

View File

@ -0,0 +1,14 @@
{% extends "base.html" %}
{% import 'bootstrap/wtf.html' as wtf %}
{% block app_content %}
<h1>Créer un département</h1>
<div class="row">
<div class="col-md-4">
{{ wtf.quick_form(form) }}
</div>
</div>
{% endblock %}

View File

@ -22,6 +22,9 @@
<b>Aucun département défini !</b>
</li>
{% endfor %}
{% if current_user.is_administrator() %}
<li><a href="{{ url_for('scodoc.create_dept') }}">créer un nouveau département</a></li>
{% endif %}
</ul>

View File

@ -53,11 +53,13 @@ from wtforms.fields.simple import BooleanField, StringField, TextAreaField, Hidd
from wtforms.validators import ValidationError, DataRequired, Email, EqualTo
import app
from app.forms.main import config_forms
from app.forms.main.create_dept import CreateDeptForm
from app.models import Departement, Identite
from app.models import departements
from app.models import FormSemestre, FormSemestreInscription
from app.models import ScoDocSiteConfig
import sco_version
from app.scodoc import sco_logos, sco_config_form
from app.scodoc import sco_logos
from app.scodoc import sco_find_etud
from app.scodoc import sco_utils as scu
from app.decorators import (
@ -67,7 +69,6 @@ from app.decorators import (
permission_required_compat_scodoc7,
permission_required,
)
from app.scodoc.sco_config_form import configuration
from app.scodoc.sco_exceptions import AccessDenied
from app.scodoc.sco_logos import find_logo
from app.scodoc.sco_permissions import Permission
@ -99,6 +100,24 @@ def index_dept(scodoc_dept):
return redirect(url_for("scolar.index_html", scodoc_dept=scodoc_dept))
@bp.route("/ScoDoc/create_dept", methods=["GET", "POST"])
@admin_required
def create_dept():
"""Form création département"""
form = CreateDeptForm()
if request.method == "POST" and form.cancel.data: # cancel button
return redirect(url_for("scodoc.index"))
if form.validate_on_submit():
departements.create_dept(form.acronym.data)
flash(f"Département {form.acronym.data} créé.")
return redirect(url_for("scodoc.index"))
return render_template(
"create_dept.html",
form=form,
title="Création d'un nouveau département",
)
@bp.route("/ScoDoc/table_etud_in_accessible_depts", methods=["POST"])
@login_required
def table_etud_in_accessible_depts():
@ -134,7 +153,7 @@ def get_etud_dept():
last_etud = None
last_date = None
for etud in etuds:
inscriptions = FormsemestreInscription.query.filter_by(etudid=etud.id).all()
inscriptions = FormSemestreInscription.query.filter_by(etudid=etud.id).all()
for ins in inscriptions:
date_fin = FormSemestre.query.get(ins.formsemestre_id).date_fin
if (last_date is None) or date_fin > last_date:
@ -207,7 +226,7 @@ def configuration():
auth_name = str(current_user)
if not current_user.is_administrator():
raise AccessDenied("invalid user (%s) must be SuperAdmin" % auth_name)
return sco_config_form.configuration()
return config_forms.configuration()
SMALL_SIZE = (200, 200)

View File

@ -1,7 +1,7 @@
# -*- mode: python -*-
# -*- coding: utf-8 -*-
SCOVERSION = "9.1.13"
SCOVERSION = "9.1.16"
SCONAME = "ScoDoc"

View File

@ -27,6 +27,7 @@ from app.models import Formation, UniteEns, Module
from app.models import FormSemestre, FormSemestreInscription
from app.models import ModuleImpl, ModuleImplInscription
from app.models import Identite
from app.models import departements
from app.models.evaluations import Evaluation
from app.scodoc.sco_etud import identite_create
from app.scodoc.sco_permissions import Permission
@ -306,11 +307,7 @@ def delete_dept(dept): # delete-dept
@click.argument("dept")
def create_dept(dept): # create-dept
"Create new departement"
d = models.Departement(acronym=dept)
p1 = ScoPreference(name="DeptName", value=dept, departement=d)
db.session.add(p1)
db.session.add(d)
db.session.commit()
_ = departements.create_dept(dept)
return 0