Compare commits
2 Commits
master
...
edit_confi
Author | SHA1 | Date | |
---|---|---|---|
|
ba3832bf29 | ||
|
17611cad03 |
|
@ -21,6 +21,7 @@ import jwt
|
|||
from app import db, login
|
||||
from app.models import Departement
|
||||
from app.models import SHORT_STR_LEN
|
||||
from app.models.config import SiteConfig
|
||||
from app.scodoc.sco_exceptions import ScoValueError
|
||||
from app.scodoc.sco_permissions import Permission
|
||||
from app.scodoc.sco_roles_default import SCO_ROLES_DEFAULTS
|
||||
|
@ -36,8 +37,8 @@ def is_valid_password(cleartxt):
|
|||
"""
|
||||
if (
|
||||
hasattr(scu.CONFIG, "MIN_PASSWORD_LENGTH")
|
||||
and scu.CONFIG.MIN_PASSWORD_LENGTH > 0
|
||||
and len(cleartxt) < scu.CONFIG.MIN_PASSWORD_LENGTH
|
||||
and SiteConfig.MIN_PASSWORD_LENGTH.get_value() > 0
|
||||
and len(cleartxt) < SiteConfig.MIN_PASSWORD_LENGTH.get_value()
|
||||
):
|
||||
return False # invalid: too short
|
||||
try:
|
||||
|
|
|
@ -32,10 +32,12 @@ Formulaires configuration Exports Apogée (codes)
|
|||
from flask import flash, url_for, redirect, request, render_template
|
||||
from flask_wtf import FlaskForm
|
||||
from wtforms import BooleanField, SelectField, SubmitField
|
||||
from wtforms import SelectField, SubmitField, StringField, BooleanField, IntegerField
|
||||
|
||||
import app
|
||||
from app.models import ScoDocSiteConfig
|
||||
import app.scodoc.sco_utils as scu
|
||||
from app.models.config import SiteConfig
|
||||
|
||||
|
||||
class BonusConfigurationForm(FlaskForm):
|
||||
|
@ -56,6 +58,24 @@ class ScoDocConfigurationForm(FlaskForm):
|
|||
enable_entreprises = BooleanField("activer le module <em>entreprises</em>")
|
||||
submit_scodoc = SubmitField("Valider")
|
||||
cancel_scodoc = SubmitField("Annuler", render_kw={"formnovalidate": True})
|
||||
default_pdf_footer_template = StringField(label="Pied de page par défaut des documents PDF")
|
||||
|
||||
custom_html_header = StringField(label="Fichier d'entete html")
|
||||
custom_html_footer = StringField(label="fichier pied de page html")
|
||||
custom_html_header_cnx = StringField(label="Fichier d'entete html (connexion)")
|
||||
custom_html_footer_cnx = StringField(label="fichier pied de page html (connexion)")
|
||||
|
||||
capitalize_all_ues = BooleanField(label="Capitalise toutes les UE des semestres validés (règles DUT)")
|
||||
allow_null_prenom = BooleanField(label="Autorise les étudiants sans prénom (UCAC)")
|
||||
publish_portal_photo_url = BooleanField(label="Si pas de photo et portail, publie l'url (était vrai jusqu'en oct 2016)")
|
||||
|
||||
logo_header_height = IntegerField(label="hauteur en mm du logo d'entête")
|
||||
logo_footer_height = IntegerField(label="hauteur en mm du logo de pied de page")
|
||||
alwways_require_ine = BooleanField(label="Rendre l'INE obligatoire")
|
||||
etud_max_filesize = IntegerField(label="Taille maximale des fichiers archives étudiants en octets")
|
||||
|
||||
submit = SubmitField("Valider")
|
||||
cancel = SubmitField("Annuler", render_kw={"formnovalidate": True})
|
||||
|
||||
|
||||
def configuration():
|
||||
|
@ -72,6 +92,8 @@ def configuration():
|
|||
if request.method == "POST" and (
|
||||
form_bonus.cancel_bonus.data or form_scodoc.cancel_scodoc.data
|
||||
): # cancel button
|
||||
form = ScoDocConfigurationForm(data=SiteConfig.get_editable_data())
|
||||
if request.method == "POST" and form.cancel.data: # cancel button
|
||||
return redirect(url_for("scodoc.index"))
|
||||
if form_bonus.submit_bonus.data and form_bonus.validate():
|
||||
if (
|
||||
|
@ -83,6 +105,16 @@ def configuration():
|
|||
)
|
||||
app.clear_scodoc_cache()
|
||||
flash(f"Fonction bonus sport&culture configurée.")
|
||||
if form.validate_on_submit():
|
||||
modified = set()
|
||||
for c in SiteConfig:
|
||||
if c.editable():
|
||||
if form.data[c.db_name()] != c.get_value():
|
||||
c.set_value(form.data[c.db_name()])
|
||||
app.clear_scodoc_cache()
|
||||
modified.add(c)
|
||||
|
||||
flash(f"Fonction bonus sport&culture configurée.")
|
||||
return redirect(url_for("scodoc.index"))
|
||||
elif form_scodoc.submit_scodoc.data and form_scodoc.validate():
|
||||
if ScoDocSiteConfig.enable_entreprises(
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
"""Model : site config WORK IN PROGRESS #WIP
|
||||
"""
|
||||
from enum import Enum
|
||||
|
||||
from flask import flash
|
||||
from app import db, log
|
||||
|
@ -47,6 +48,264 @@ def code_scodoc_to_apo_default(code):
|
|||
return CODES_SCODOC_TO_APO.get(code, "DEF")
|
||||
|
||||
|
||||
class SiteConfig(Enum):
|
||||
BONUS_SPORT = {
|
||||
"editable": True,
|
||||
"db_name": "bonus_sport_func_name",
|
||||
"default": None,
|
||||
"type": str,
|
||||
}
|
||||
FOOTER_TEMPLATE = {
|
||||
"editable": True,
|
||||
"db_name": "default_pdf_footer_template",
|
||||
"default": "Edité par %(scodoc_name)s le %(day)s/%(month)s/%(year)s à %(hour)sh%(minute)s sur %(server_url)s",
|
||||
"type": str,
|
||||
}
|
||||
LOGO_HEADER_HEIGHT = {
|
||||
"editable": True,
|
||||
"db_name": "logo_header_height",
|
||||
"default": 28,
|
||||
"type": int,
|
||||
}
|
||||
LOGO_FOOTER_HEIGHT = {
|
||||
"editable": True,
|
||||
"db_name": "logo_footer_height",
|
||||
"default": 10,
|
||||
"type": str,
|
||||
}
|
||||
CUSTOM_HTML_HEADER = {
|
||||
"editable": True,
|
||||
"db_name": "custom_html_header",
|
||||
"default": "",
|
||||
"type": str,
|
||||
}
|
||||
CUSTOM_HTML_FOOTER = {
|
||||
"editable": True,
|
||||
"db_name": "custom_html_footer",
|
||||
"default": "",
|
||||
"type": str,
|
||||
}
|
||||
CUSTOM_HTML_HEADER_CNX = {
|
||||
"editable": True,
|
||||
"db_name": "custom_html_header_cnx",
|
||||
"default": "",
|
||||
"type": str,
|
||||
}
|
||||
CUSTOM_HTML_FOOTER_CNX = {
|
||||
"editable": True,
|
||||
"db_name": "custom_html_footer_cnx",
|
||||
"default": "",
|
||||
"type": str,
|
||||
}
|
||||
ETUD_MAX_FILE_SIZE = {
|
||||
"editable": True,
|
||||
"db_name": "etud_max_filesize",
|
||||
"default": 10 * 1024 * 1024,
|
||||
"type": int,
|
||||
}
|
||||
CAPITALIZE_ALL_UES = {
|
||||
"editable": True,
|
||||
"db_name": "capitalize_all_ues",
|
||||
"default": True,
|
||||
"type": bool,
|
||||
}
|
||||
ALLOW_NULL_PRENOM = {
|
||||
"editable": True,
|
||||
"db_name": "allow_null_prenom",
|
||||
"default": False,
|
||||
"type": bool,
|
||||
}
|
||||
ALWAYS_REQUIRE_INE = {
|
||||
"editable": True,
|
||||
"db_name": "alwways_require_ine",
|
||||
"default": False,
|
||||
"type": bool,
|
||||
}
|
||||
PUBLISH_PORTAL_PHOTO_URL = {
|
||||
"editable": True,
|
||||
"db_name": "publish_portal_photo_url",
|
||||
"default": False,
|
||||
"type": bool,
|
||||
}
|
||||
MIN_PASSWORD_LENGTH = {
|
||||
"editable": True,
|
||||
"db_name": "publish_portal_photo_url",
|
||||
"default": 0,
|
||||
"type": int,
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def get_editable_data(cls):
|
||||
data = {}
|
||||
for c in SiteConfig:
|
||||
if c.editable():
|
||||
data[c.value["db_name"]] = c.get_value()
|
||||
return data
|
||||
|
||||
def db_name(self):
|
||||
return self.value["db_name"]
|
||||
|
||||
def default(self):
|
||||
return self.value["default"]
|
||||
|
||||
def editable(self):
|
||||
return self.value["editable"]
|
||||
|
||||
def type(self):
|
||||
return self.value["type"]
|
||||
|
||||
def get_value(self):
|
||||
"""Lit valeur de configuration (sinon valeur par défaut)"""
|
||||
cfg = ScoDocSiteConfig.query.filter_by(name=self.value["db_name"]).first()
|
||||
if not cfg:
|
||||
return self.value["default"]
|
||||
else:
|
||||
value = cfg.value
|
||||
if self.value["type"] == str:
|
||||
return value
|
||||
if self.value["type"] == bool:
|
||||
return value.lower() == "true"
|
||||
if self.value["type"] == int:
|
||||
return int(value)
|
||||
|
||||
def set_value(self, value):
|
||||
"""Enregistre nouvelle valeur de configuration"""
|
||||
if value != self.get_value():
|
||||
cfg = ScoDocSiteConfig.query.filter_by(name=self.value["db_name"]).first()
|
||||
if cfg is None:
|
||||
cfg = ScoDocSiteConfig(self.value["db_name"], value)
|
||||
else:
|
||||
cfg.value = str(value)
|
||||
db.session.add(cfg)
|
||||
db.session.commit()
|
||||
|
||||
|
||||
NAMES = {c.db_name(): c for c in SiteConfig}
|
||||
|
||||
|
||||
class SiteConfig(Enum):
|
||||
BONUS_SPORT = {
|
||||
"editable": True,
|
||||
"db_name": "bonus_sport_func_name",
|
||||
"default": None,
|
||||
"type": str,
|
||||
}
|
||||
FOOTER_TEMPLATE = {
|
||||
"editable": True,
|
||||
"db_name": "default_pdf_footer_template",
|
||||
"default": "Edité par %(scodoc_name)s le %(day)s/%(month)s/%(year)s à %(hour)sh%(minute)s sur %(server_url)s",
|
||||
"type": str,
|
||||
}
|
||||
CUSTOM_HTML_HEADER = {
|
||||
"editable": True,
|
||||
"db_name": "custom_html_header",
|
||||
"default": "",
|
||||
"type": str,
|
||||
}
|
||||
CUSTOM_HTML_FOOTER = {
|
||||
"editable": True,
|
||||
"db_name": "custom_html_footer",
|
||||
"default": "",
|
||||
"type": str,
|
||||
}
|
||||
CUSTOM_HTML_HEADER_CNX = {
|
||||
"editable": True,
|
||||
"db_name": "custom_html_header_cnx",
|
||||
"default": "",
|
||||
"type": str,
|
||||
}
|
||||
CUSTOM_HTML_FOOTER_CNX = {
|
||||
"editable": True,
|
||||
"db_name": "custom_html_footer_cnx",
|
||||
"default": "",
|
||||
"type": str,
|
||||
}
|
||||
ETUD_MAX_FILE_SIZE = {
|
||||
"editable": True,
|
||||
"db_name": "etud_max_filesize",
|
||||
"default": 10 * 1024 * 1024,
|
||||
"type": int,
|
||||
}
|
||||
CAPITALIZE_ALL_UES = {
|
||||
"editable": True,
|
||||
"db_name": "capitalize_all_ues",
|
||||
"default": True,
|
||||
"type": bool,
|
||||
}
|
||||
ALLOW_NULL_PRENOM = {
|
||||
"editable": True,
|
||||
"db_name": "allow_null_prenom",
|
||||
"default": False,
|
||||
"type": bool,
|
||||
}
|
||||
ALWAYS_REQUIRE_INE = {
|
||||
"editable": True,
|
||||
"db_name": "alwways_require_ine",
|
||||
"default": False,
|
||||
"type": bool,
|
||||
}
|
||||
PUBLISH_PORTAL_PHOTO_URL = {
|
||||
"editable": True,
|
||||
"db_name": "publish_portal_photo_url",
|
||||
"default": False,
|
||||
"type": bool,
|
||||
}
|
||||
MIN_PASSWORD_LENGTH = {
|
||||
"editable": True,
|
||||
"db_name": "publish_portal_photo_url",
|
||||
"default": 0,
|
||||
"type": int,
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def get_editable_data(cls):
|
||||
data = {}
|
||||
for c in SiteConfig:
|
||||
if c.editable():
|
||||
data[c.value["db_name"]] = c.get_value()
|
||||
return data
|
||||
|
||||
def db_name(self):
|
||||
return self.value["db_name"]
|
||||
|
||||
def default(self):
|
||||
return self.value["default"]
|
||||
|
||||
def editable(self):
|
||||
return self.value["editable"]
|
||||
|
||||
def type(self):
|
||||
return self.value["type"]
|
||||
|
||||
def get_value(self):
|
||||
"""Lit valeur de configuration (sinon valeur par défaut)"""
|
||||
cfg = ScoDocSiteConfig.query.filter_by(name=self.value["db_name"]).first()
|
||||
if not cfg:
|
||||
return self.value["default"]
|
||||
else:
|
||||
value = cfg.value
|
||||
if self.value["type"] == str:
|
||||
return value
|
||||
if self.value["type"] == bool:
|
||||
return value.lower() == "true"
|
||||
if self.value["type"] == int:
|
||||
return int(value)
|
||||
|
||||
def set_value(self, value):
|
||||
"""Enregistre nouvelle valeur de configuration"""
|
||||
if value != self.get_value():
|
||||
cfg = ScoDocSiteConfig.query.filter_by(name=self.value["db_name"]).first()
|
||||
if cfg is None:
|
||||
cfg = ScoDocSiteConfig(self.value["db_name"], value)
|
||||
else:
|
||||
cfg.value = str(value)
|
||||
db.session.add(cfg)
|
||||
db.session.commit()
|
||||
|
||||
|
||||
NAMES = {c.db_name(): c for c in SiteConfig}
|
||||
|
||||
|
||||
class ScoDocSiteConfig(db.Model):
|
||||
"""Config. d'un site
|
||||
Nouveau en ScoDoc 9: va regrouper les paramètres qui dans les versions
|
||||
|
@ -84,7 +343,7 @@ class ScoDocSiteConfig(db.Model):
|
|||
def get_dict(cls) -> dict:
|
||||
"Returns all data as a dict name = value"
|
||||
return {
|
||||
c.name: cls.NAMES.get(c.name, lambda x: x)(c.value)
|
||||
c.name: NAMES.get(c.name, lambda x: x)(c.value)
|
||||
for c in ScoDocSiteConfig.query.all()
|
||||
}
|
||||
|
||||
|
@ -95,12 +354,12 @@ class ScoDocSiteConfig(db.Model):
|
|||
"""
|
||||
if class_name not in cls.get_bonus_sport_class_names():
|
||||
raise NameError("invalid class name for bonus_sport")
|
||||
c = ScoDocSiteConfig.query.filter_by(name=cls.BONUS_SPORT).first()
|
||||
c = ScoDocSiteConfig.query.filter_by(name=SiteConfig.BONUS_SPORT.db_name()).first()
|
||||
if c:
|
||||
log("setting to " + class_name)
|
||||
c.value = class_name
|
||||
else:
|
||||
c = ScoDocSiteConfig(cls.BONUS_SPORT, class_name)
|
||||
c = ScoDocSiteConfig(SiteConfig.BONUS_SPORT.db_name(), class_name)
|
||||
db.session.add(c)
|
||||
db.session.commit()
|
||||
|
||||
|
@ -127,7 +386,7 @@ class ScoDocSiteConfig(db.Model):
|
|||
and flash a warning.
|
||||
"""
|
||||
if not class_name: # None or ""
|
||||
c = ScoDocSiteConfig.query.filter_by(name=cls.BONUS_SPORT).first()
|
||||
c = ScoDocSiteConfig.query.filter_by(name=SiteConfig.BONUS_SPORT.db_name()).first()
|
||||
if c is None:
|
||||
return None
|
||||
class_name = c.value
|
||||
|
@ -136,7 +395,7 @@ class ScoDocSiteConfig(db.Model):
|
|||
klass = bonus_spo.get_bonus_class_dict().get(class_name)
|
||||
if klass is None:
|
||||
flash(
|
||||
f"""Fonction de calcul bonus sport inexistante: {class_name}.
|
||||
f"""Fonction de calcul bonus sport inexistante: {class_name}.
|
||||
Changez là ou contactez votre administrateur local."""
|
||||
)
|
||||
return klass
|
||||
|
@ -158,6 +417,43 @@ class ScoDocSiteConfig(db.Model):
|
|||
class_list.sort(key=lambda x: x[1].replace(" du ", " de "))
|
||||
return [("", "")] + class_list
|
||||
|
||||
@classmethod
|
||||
def get_bonus_sport_func(cls):
|
||||
"""Fonction bonus_sport ScoDoc 7 XXX
|
||||
Transitoire pour les tests durant la transition #sco92
|
||||
"""
|
||||
"""returns bonus func with specified name.
|
||||
If name not specified, return the configured function.
|
||||
None if no bonus function configured.
|
||||
Raises ScoValueError if func_name not found in module bonus_sport.
|
||||
"""
|
||||
from app.scodoc import bonus_sport
|
||||
|
||||
# c = ScoDocSiteConfig.query.filter_by(name=Config.BONUS_SPORT.db_name()).first()
|
||||
# if c is None:
|
||||
# return None
|
||||
# func_name = c.value
|
||||
func_name = ScoDocSiteConfig.get_config_value(SiteConfig.BONUS_SPORT)
|
||||
if func_name == "": # pas de bonus défini
|
||||
return None
|
||||
try:
|
||||
return getattr(bonus_sport, func_name)
|
||||
except AttributeError:
|
||||
raise ScoValueError(
|
||||
f"""Fonction de calcul de l'UE bonus inexistante: "{func_name}".
|
||||
(contacter votre administrateur local)."""
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def get_config_value(cls, conf: SiteConfig):
|
||||
"""Lit valeur de configuration (sinon valeur par défaut)"""
|
||||
return conf.get_value()
|
||||
|
||||
@classmethod
|
||||
def set_config_value(cls, conf: SiteConfig, value):
|
||||
"""Enregistre nouvelle valeur de configuration"""
|
||||
conf.set_value(value)
|
||||
|
||||
@classmethod
|
||||
def get_code_apo(cls, code: str) -> str:
|
||||
"""La représentation d'un code pour les exports Apogée.
|
||||
|
|
|
@ -35,6 +35,7 @@ from flask import g, request
|
|||
from flask_login import current_user
|
||||
|
||||
import app.scodoc.sco_utils as scu
|
||||
from app.models.config import SiteConfig
|
||||
from app.scodoc import sco_import_etuds
|
||||
from app.scodoc import sco_groups
|
||||
from app.scodoc import sco_trombino
|
||||
|
@ -150,7 +151,7 @@ def etud_upload_file_form(etudid):
|
|||
% etud,
|
||||
"""<p>Le fichier ne doit pas dépasser %sMo.</p>
|
||||
"""
|
||||
% (scu.CONFIG.ETUD_MAX_FILE_SIZE // (1024 * 1024)),
|
||||
% (SiteConfig.ETUD_MAX_FILE_SIZE.get_value() // (1024 * 1024)),
|
||||
]
|
||||
tf = TrivialFormulator(
|
||||
request.base_url,
|
||||
|
@ -193,7 +194,7 @@ def etud_upload_file_form(etudid):
|
|||
def _store_etud_file_to_new_archive(etud_archive_id, data, filename, description=""):
|
||||
"""Store data to new archive."""
|
||||
filesize = len(data)
|
||||
if filesize < 10 or filesize > scu.CONFIG.ETUD_MAX_FILE_SIZE:
|
||||
if filesize < 10 or filesize > SiteConfig.ETUD_MAX_FILE_SIZE.get_value():
|
||||
return 0, "Fichier image de taille invalide ! (%d)" % filesize
|
||||
archive_id = EtudsArchive.create_obj_archive(etud_archive_id, description)
|
||||
EtudsArchive.store(archive_id, filename, data)
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
mais éditer /opt/scodoc-data/config/scodoc_local.py
|
||||
"""
|
||||
|
||||
from app.scodoc import bonus_sport
|
||||
# from app.scodoc import bonus_sport
|
||||
|
||||
|
||||
class AttrDict(dict):
|
||||
|
@ -26,13 +26,13 @@ CONFIG.always_require_ine = 0
|
|||
|
||||
# Taille du l'image logo: largeur/hauteur (ne pas oublier le . !!!)
|
||||
# W/H XXX provisoire: utilisera PIL pour connaitre la taille de l'image
|
||||
CONFIG.LOGO_FOOTER_ASPECT = 326 / 96.0
|
||||
# CONFIG.LOGO_FOOTER_ASPECT = 326 / 96.0
|
||||
# Taille dans le document en millimetres
|
||||
CONFIG.LOGO_FOOTER_HEIGHT = 10
|
||||
# CONFIG.LOGO_FOOTER_HEIGHT = 10
|
||||
# Proportions logo (donné ici pour IUTV)
|
||||
CONFIG.LOGO_HEADER_ASPECT = 549 / 346.0
|
||||
# CONFIG.LOGO_HEADER_ASPECT = 549 / 346.0
|
||||
# Taille verticale dans le document en millimetres
|
||||
CONFIG.LOGO_HEADER_HEIGHT = 28
|
||||
# CONFIG.LOGO_HEADER_HEIGHT = 28
|
||||
|
||||
|
||||
# Pied de page PDF : un format Python, %(xxx)s est remplacé par la variable xxx.
|
||||
|
@ -59,22 +59,22 @@ CONFIG.DEFAULT_PDF_FOOTER_TEMPLATE = (
|
|||
# - règle "LMD": capitalisation uniquement des UE avec moy. > 10
|
||||
|
||||
# Si vrai, capitalise toutes les UE des semestres validés (règle "DUT").
|
||||
CONFIG.CAPITALIZE_ALL_UES = True
|
||||
# CONFIG.CAPITALIZE_ALL_UES = True
|
||||
|
||||
# -----------------------------------------------------
|
||||
# -------------- Personnalisation des pages
|
||||
# -----------------------------------------------------
|
||||
# Nom (chemin complet) d'un fichier .html à inclure juste après le <body>
|
||||
# le <body> des pages ScoDoc
|
||||
CONFIG.CUSTOM_HTML_HEADER = ""
|
||||
# CONFIG.CUSTOM_HTML_HEADER = ""
|
||||
|
||||
# Fichier html a inclure en fin des pages (juste avant le </body>)
|
||||
CONFIG.CUSTOM_HTML_FOOTER = ""
|
||||
# CONFIG.CUSTOM_HTML_FOOTER = ""
|
||||
|
||||
# Fichier .html à inclure dans la pages connexion/déconnexion (accueil)
|
||||
# si on veut que ce soit différent (par défaut la même chose)
|
||||
CONFIG.CUSTOM_HTML_HEADER_CNX = CONFIG.CUSTOM_HTML_HEADER
|
||||
CONFIG.CUSTOM_HTML_FOOTER_CNX = CONFIG.CUSTOM_HTML_FOOTER
|
||||
# CONFIG.CUSTOM_HTML_HEADER_CNX = CONFIG.CUSTOM_HTML_HEADER
|
||||
# CONFIG.CUSTOM_HTML_FOOTER_CNX = CONFIG.CUSTOM_HTML_FOOTER
|
||||
|
||||
# -----------------------------------------------------
|
||||
# -------------- Noms de Lycées
|
||||
|
@ -88,17 +88,17 @@ CONFIG.ETABL_FILENAME = "etablissements.csv"
|
|||
# -------------- Divers:
|
||||
# ----------------------------------------------------
|
||||
# True for UCAC (étudiants camerounais sans prénoms)
|
||||
CONFIG.ALLOW_NULL_PRENOM = False
|
||||
# CONFIG.ALLOW_NULL_PRENOM = False
|
||||
|
||||
# Taille max des fichiers archive etudiants (en octets)
|
||||
CONFIG.ETUD_MAX_FILE_SIZE = 10 * 1024 * 1024
|
||||
# CONFIG.ETUD_MAX_FILE_SIZE = 10 * 1024 * 1024
|
||||
|
||||
# Si pas de photo et portail, publie l'url (était vrai jusqu'en oct 2016)
|
||||
CONFIG.PUBLISH_PORTAL_PHOTO_URL = False
|
||||
# CONFIG.PUBLISH_PORTAL_PHOTO_URL = False
|
||||
|
||||
# Si > 0: longueur minimale requise des nouveaux mots de passe
|
||||
# (le test cracklib.FascistCheck s'appliquera dans tous les cas)
|
||||
CONFIG.MIN_PASSWORD_LENGTH = 0
|
||||
# CONFIG.MIN_PASSWORD_LENGTH = 0
|
||||
|
||||
# Ce dictionnaire est fusionné à celui de sco_codes_parcours
|
||||
# pour définir les codes jury et explications associées
|
||||
|
|
|
@ -78,6 +78,7 @@
|
|||
import re
|
||||
|
||||
import app.scodoc.sco_utils as scu
|
||||
from app.models.config import SiteConfig
|
||||
from app.scodoc import sco_archives
|
||||
from app.scodoc import sco_apogee_csv
|
||||
from app.scodoc.sco_exceptions import ScoValueError
|
||||
|
@ -110,7 +111,7 @@ def apo_csv_store(csv_data: str, annee_scolaire, sem_id):
|
|||
"""
|
||||
# sanity check
|
||||
filesize = len(csv_data)
|
||||
if filesize < 10 or filesize > scu.CONFIG.ETUD_MAX_FILE_SIZE:
|
||||
if filesize < 10 or filesize > SiteConfig.ETUD_MAX_FILE_SIZE.get_value():
|
||||
raise ScoValueError("Fichier csv de taille invalide ! (%d)" % filesize)
|
||||
|
||||
if not annee_scolaire:
|
||||
|
|
|
@ -37,6 +37,7 @@ from flask import url_for, g
|
|||
|
||||
from app import email
|
||||
from app import log
|
||||
from app.models.config import SiteConfig
|
||||
from app.models import Admission
|
||||
from app.models.etudiants import make_etud_args
|
||||
import app.scodoc.sco_utils as scu
|
||||
|
@ -266,7 +267,7 @@ def check_nom_prenom(cnx, nom="", prenom="", etudid=None):
|
|||
Returns:
|
||||
True | False, NbHomonyms
|
||||
"""
|
||||
if not nom or (not prenom and not scu.CONFIG.ALLOW_NULL_PRENOM):
|
||||
if not nom or (not prenom and not SiteConfig.ALLOW_NULL_PRENOM.get_value()):
|
||||
return False, 0
|
||||
nom = nom.lower().strip()
|
||||
if prenom:
|
||||
|
|
|
@ -49,6 +49,7 @@ from app.comp import res_sem
|
|||
from app.comp.res_compat import NotesTableCompat
|
||||
from app.models import FormSemestre, formsemestre
|
||||
from app.models import GROUPNAME_STR_LEN, SHORT_STR_LEN
|
||||
from app.models.config import SiteConfig
|
||||
from app.models.groups import Partition
|
||||
import app.scodoc.sco_utils as scu
|
||||
import app.scodoc.notesdb as ndb
|
||||
|
@ -257,7 +258,7 @@ def get_group_members(group_id, etat=None):
|
|||
|
||||
r.sort(key=operator.itemgetter("nom_disp", "prenom")) # tri selon nom_usuel ou nom
|
||||
|
||||
if scu.CONFIG.ALLOW_NULL_PRENOM:
|
||||
if SiteConfig.ALLOW_NULL_PRENOM.get_value():
|
||||
for x in r:
|
||||
x["prenom"] = x["prenom"] or ""
|
||||
|
||||
|
|
|
@ -285,6 +285,13 @@ class Logo:
|
|||
dt = path.stat().st_mtime
|
||||
return path.stat().st_mtime
|
||||
|
||||
def compute_width(self, height):
|
||||
if isinstance(self.aspect_ratio, str):
|
||||
return (
|
||||
"Logo not initialized: call the select or create function before access"
|
||||
)
|
||||
return self.aspect_ratio * height
|
||||
|
||||
|
||||
def guess_image_type(stream) -> str:
|
||||
"guess image type from header in stream"
|
||||
|
|
|
@ -55,6 +55,8 @@ from reportlab.lib import styles
|
|||
|
||||
from flask import g
|
||||
|
||||
import app.scodoc.sco_utils as scu
|
||||
from app.models.config import ScoDocSiteConfig, SiteConfig
|
||||
from app.scodoc.sco_utils import CONFIG
|
||||
from app import log
|
||||
from app.scodoc.sco_exceptions import ScoGenError, ScoValueError
|
||||
|
@ -64,9 +66,6 @@ PAGE_HEIGHT = defaultPageSize[1]
|
|||
PAGE_WIDTH = defaultPageSize[0]
|
||||
|
||||
|
||||
DEFAULT_PDF_FOOTER_TEMPLATE = CONFIG.DEFAULT_PDF_FOOTER_TEMPLATE
|
||||
|
||||
|
||||
def SU(s):
|
||||
"convert s from string to string suitable for ReportLab"
|
||||
if not s:
|
||||
|
@ -223,7 +222,7 @@ class ScoDocPageTemplate(PageTemplate):
|
|||
subject=None,
|
||||
margins=(0, 0, 0, 0), # additional margins in mm (left,top,right, bottom)
|
||||
server_name="",
|
||||
footer_template=DEFAULT_PDF_FOOTER_TEMPLATE,
|
||||
footer_template=None,
|
||||
filigranne=None,
|
||||
preferences=None, # dictionnary with preferences, required
|
||||
):
|
||||
|
@ -231,6 +230,10 @@ class ScoDocPageTemplate(PageTemplate):
|
|||
# defered import (solve circular dependency ->sco_logo ->scodoc, ->sco_pdf
|
||||
from app.scodoc.sco_logos import find_logo
|
||||
|
||||
if footer_template is None:
|
||||
footer_template = ScoDocSiteConfig.get_config_value(
|
||||
SiteConfig.FOOTER_TEMPLATE
|
||||
)
|
||||
self.preferences = preferences
|
||||
self.pagesbookmarks = pagesbookmarks or {}
|
||||
self.pdfmeta_author = author
|
||||
|
@ -416,7 +419,7 @@ def pdf_basic_page(
|
|||
document,
|
||||
title=title,
|
||||
author="%s %s (E. Viennet)" % (sco_version.SCONAME, sco_version.SCOVERSION),
|
||||
footer_template="Edité par %(scodoc_name)s le %(day)s/%(month)s/%(year)s à %(hour)sh%(minute)s",
|
||||
footer_template=ScoDocSiteConfig.get_default_pdf_footer_template(),
|
||||
preferences=preferences,
|
||||
)
|
||||
)
|
||||
|
|
|
@ -59,6 +59,7 @@ from flask.helpers import make_response, url_for
|
|||
from app import log
|
||||
from app import db
|
||||
from app.models import Identite
|
||||
from app.models.config import SiteConfig
|
||||
from app.scodoc import sco_etud
|
||||
from app.scodoc import sco_portal_apogee
|
||||
from app.scodoc import sco_preferences
|
||||
|
@ -117,7 +118,7 @@ def etud_photo_url(etud: dict, size="small", fast=False) -> str:
|
|||
if not new_path:
|
||||
# copy failed, can we use external url ?
|
||||
# nb: rarement utile, car le portail est rarement accessible sans authentification
|
||||
if scu.CONFIG.PUBLISH_PORTAL_PHOTO_URL:
|
||||
if SiteConfig.PUBLISH_PORTAL_PHOTO_URL.get_value():
|
||||
photo_url = ext_url
|
||||
else:
|
||||
photo_url = UNKNOWN_IMAGE_URL
|
||||
|
|
|
@ -43,6 +43,7 @@ from reportlab.lib.colors import Color
|
|||
from flask import g
|
||||
|
||||
import app.scodoc.sco_utils as scu
|
||||
from app.models.config import SiteConfig
|
||||
from app.scodoc import sco_bulletins_pdf
|
||||
from app.scodoc import sco_codes_parcours
|
||||
from app.scodoc import sco_formsemestre
|
||||
|
@ -53,13 +54,15 @@ import sco_version
|
|||
from app.scodoc.sco_logos import find_logo
|
||||
from app.scodoc.sco_pdf import SU
|
||||
|
||||
LOGO_FOOTER_ASPECT = scu.CONFIG.LOGO_FOOTER_ASPECT # XXX A AUTOMATISER
|
||||
LOGO_FOOTER_HEIGHT = scu.CONFIG.LOGO_FOOTER_HEIGHT * mm
|
||||
LOGO_FOOTER_WIDTH = LOGO_FOOTER_HEIGHT * scu.CONFIG.LOGO_FOOTER_ASPECT
|
||||
# LOGO_FOOTER_HEIGHT = SiteConfig.LOGO_FOOTER_HEIGHT.get_value() * mm
|
||||
LOGO_FOOTER_HEIGHT = 10 * mm
|
||||
# LOGO_FOOTER_ASPECT = scu.CONFIG.LOGO_FOOTER_ASPECT # XXX A AUTOMATISER
|
||||
# LOGO_FOOTER_WIDTH = LOGO_FOOTER_HEIGHT * scu.CONFIG.LOGO_FOOTER_ASPECT
|
||||
|
||||
LOGO_HEADER_ASPECT = scu.CONFIG.LOGO_HEADER_ASPECT # XXX logo IUTV (A AUTOMATISER)
|
||||
LOGO_HEADER_HEIGHT = scu.CONFIG.LOGO_HEADER_HEIGHT * mm
|
||||
LOGO_HEADER_WIDTH = LOGO_HEADER_HEIGHT * scu.CONFIG.LOGO_HEADER_ASPECT
|
||||
# LOGO_HEADER_HEIGHT = SiteConfig.LOGO_HEADER_HEIGHT.get_value() * mm
|
||||
LOGO_HEADER_HEIGHT = 28 * mm
|
||||
# LOGO_HEADER_ASPECT = scu.CONFIG.LOGO_HEADER_ASPECT # XXX logo IUTV (A AUTOMATISER)
|
||||
# LOGO_HEADER_WIDTH = LOGO_HEADER_HEIGHT * scu.CONFIG.LOGO_HEADER_ASPECT
|
||||
|
||||
|
||||
def pageFooter(canvas, doc, logo, preferences, with_page_numbers=True):
|
||||
|
@ -225,7 +228,7 @@ class CourrierIndividuelTemplate(PageTemplate):
|
|||
self.logo_footer = Image(
|
||||
footer.filepath,
|
||||
height=LOGO_FOOTER_HEIGHT,
|
||||
width=LOGO_FOOTER_WIDTH,
|
||||
width=footer.compute_width(LOGO_FOOTER_HEIGHT),
|
||||
)
|
||||
|
||||
header = find_logo(logoname="header", dept_id=g.scodoc_dept_id)
|
||||
|
@ -233,7 +236,7 @@ class CourrierIndividuelTemplate(PageTemplate):
|
|||
self.logo_header = Image(
|
||||
header.filepath,
|
||||
height=LOGO_HEADER_HEIGHT,
|
||||
width=LOGO_HEADER_WIDTH,
|
||||
width=header.compute_width(LOGO_HEADER_HEIGHT),
|
||||
)
|
||||
|
||||
def beforeDrawPage(self, canvas, doc):
|
||||
|
|
|
@ -61,7 +61,6 @@ from app.scodoc import sco_exceptions
|
|||
from app.scodoc import sco_xml
|
||||
import sco_version
|
||||
|
||||
|
||||
# ----- CALCUL ET PRESENTATION DES NOTES
|
||||
NOTES_PRECISION = 1e-4 # evite eventuelles erreurs d'arrondis
|
||||
NOTES_MIN = 0.0 # valeur minimale admise pour une note (sauf malus, dans [-20, 20])
|
||||
|
@ -119,7 +118,7 @@ IT_SITUATION_MISSING_STR = (
|
|||
"____" # shown on ficheEtud (devenir) in place of empty situation
|
||||
)
|
||||
|
||||
RANG_ATTENTE_STR = "(attente)" # rang affiché sur bulletins quand notes en attente
|
||||
RANG_ATTENTE_STR = "(attente)" # rang affiché sur bulletins quand notes en attente
|
||||
|
||||
# borne supérieure de chaque mention
|
||||
NOTES_MENTIONS_TH = (
|
||||
|
@ -316,7 +315,6 @@ LOGO_FILE_PREFIX = "logo_"
|
|||
# ----- Les outils distribués
|
||||
SCO_TOOLS_DIR = os.path.join(Config.SCODOC_DIR, "tools")
|
||||
|
||||
|
||||
# ----- Lecture du fichier de configuration
|
||||
from app.scodoc import sco_config
|
||||
from app.scodoc import sco_config_load
|
||||
|
@ -328,29 +326,30 @@ if hasattr(CONFIG, "CODES_EXPL"):
|
|||
CONFIG.CODES_EXPL
|
||||
) # permet de customiser les explications de codes
|
||||
|
||||
if CONFIG.CUSTOM_HTML_HEADER:
|
||||
CUSTOM_HTML_HEADER = open(CONFIG.CUSTOM_HTML_HEADER).read()
|
||||
else:
|
||||
CUSTOM_HTML_HEADER = ""
|
||||
|
||||
if CONFIG.CUSTOM_HTML_HEADER_CNX:
|
||||
CUSTOM_HTML_HEADER_CNX = open(CONFIG.CUSTOM_HTML_HEADER_CNX).read()
|
||||
else:
|
||||
CUSTOM_HTML_HEADER_CNX = ""
|
||||
def include_html(config):
|
||||
setting = config.get_value()
|
||||
if setting:
|
||||
return open(setting).read()
|
||||
else:
|
||||
return ""
|
||||
|
||||
if CONFIG.CUSTOM_HTML_FOOTER:
|
||||
CUSTOM_HTML_FOOTER = open(CONFIG.CUSTOM_HTML_FOOTER).read()
|
||||
else:
|
||||
CUSTOM_HTML_FOOTER = ""
|
||||
|
||||
if CONFIG.CUSTOM_HTML_FOOTER_CNX:
|
||||
CUSTOM_HTML_FOOTER_CNX = open(CONFIG.CUSTOM_HTML_FOOTER_CNX).read()
|
||||
else:
|
||||
CUSTOM_HTML_FOOTER_CNX = ""
|
||||
def get_custom_html():
|
||||
from app.models.config import SiteConfig
|
||||
|
||||
return ("", "", "", "")
|
||||
# TODO
|
||||
# return (
|
||||
# include_html(SiteConfig.CUSTOM_HTML_HEADER),
|
||||
# include_html(SiteConfig.CUSTOM_HTML_FOOTER),
|
||||
# include_html(SiteConfig.CUSTOM_HTML_HEADER_CNX),
|
||||
# include_html(SiteConfig.CUSTOM_HTML_FOOTER_CNX),
|
||||
# )
|
||||
|
||||
|
||||
SCO_ENCODING = "utf-8" # used by Excel, XML, PDF, ...
|
||||
|
||||
|
||||
SCO_DEFAULT_SQL_USER = "scodoc" # should match Zope process UID
|
||||
SCO_DEFAULT_SQL_PORT = "5432"
|
||||
SCO_DEFAULT_SQL_USERS_CNX = "dbname=SCOUSERS port=%s" % SCO_DEFAULT_SQL_PORT
|
||||
|
@ -415,6 +414,7 @@ TYPES_ADMISSION = (TYPE_ADMISSION_DEFAULT, "APB", "APB-PC", "CEF", "Direct")
|
|||
|
||||
BULLETINS_VERSIONS = ("short", "selectedevals", "long")
|
||||
|
||||
|
||||
# Support for ScoDoc7 compatibility
|
||||
|
||||
|
||||
|
|
|
@ -30,17 +30,38 @@
|
|||
{{ form_bonus.hidden_tag() }}
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
{{ wtf.quick_form(form_bonus) }}
|
||||
{{ render_field(form.bonus_sport_func_name) }}
|
||||
</div>
|
||||
</div>
|
||||
<div id="bonus_description"></div>
|
||||
</form>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
{{ render_field(form.default_pdf_footer_template) }}
|
||||
|
||||
{{ render_field(form.custom_html_header) }}
|
||||
{{ render_field(form.custom_html_header_cnx) }}
|
||||
{{ render_field(form.custom_html_footer) }}
|
||||
{{ render_field(form.custom_html_footer_cnx) }}
|
||||
|
||||
{{ render_field(form.capitalize_all_ues) }}
|
||||
{{ render_field(form.allow_null_prenom) }}
|
||||
{{ render_field(form.publish_portal_photo_url) }}
|
||||
{{ render_field(form.alwways_require_ine) }}
|
||||
|
||||
{{ render_field(form.etud_max_filesize) }}
|
||||
{{ render_field(form.logo_header_height) }}
|
||||
{{ render_field(form.logo_footer_height) }}
|
||||
|
||||
{{ render_field(form.submit, with_label=False) }}
|
||||
{{ render_field(form.cancel, with_label=False) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Gestion des images: logos, signatures, ...</h2>
|
||||
<div class="sco_help">Ces images peuvent être intégrées dans les documents
|
||||
<div class="sco_help">Ces images peuvent être intégrées dans les documents
|
||||
générés par ScoDoc: bulletins, PV, etc.
|
||||
</div>
|
||||
<p><a class="stdlink" href="{{url_for('scodoc.configure_logos')}}">configuration des images et logos</a>
|
||||
|
@ -54,7 +75,7 @@
|
|||
|
||||
<h2>Utilisateurs</h2>
|
||||
<section>
|
||||
<p><a class="stdlink" href="{{url_for('auth.reset_standard_roles_permissions')}}">remettre
|
||||
<p><a class="stdlink" href="{{url_for('auth.reset_standard_roles_permissions')}}">remettre
|
||||
les permissions des rôles standards à leurs valeurs par défaut</a> (efface les modifications apportées)
|
||||
</p>
|
||||
</section>
|
||||
|
|
|
@ -50,6 +50,7 @@ from app.decorators import (
|
|||
admin_required,
|
||||
login_required,
|
||||
)
|
||||
from app.models.config import SiteConfig
|
||||
from app.models.etudiants import Identite
|
||||
from app.models.etudiants import make_etud_args
|
||||
|
||||
|
@ -1325,7 +1326,7 @@ def _etudident_create_or_edit_form(edit):
|
|||
{
|
||||
"size": 25,
|
||||
"title": "Prénom",
|
||||
"allow_null": scu.CONFIG.ALLOW_NULL_PRENOM,
|
||||
"allow_null": SiteConfig.ALLOW_NULL_PRENOM.get_value(),
|
||||
},
|
||||
),
|
||||
(
|
||||
|
|
|
@ -66,6 +66,7 @@ CONFIG.LOGO_HEADER_HEIGHT = 28 # taille verticale dans le document en millimetr
|
|||
CONFIG.DEFAULT_PDF_FOOTER_TEMPLATE = (
|
||||
"Edité par %(scodoc_name)s le %(day)s/%(month)s/%(year)s à %(hour)sh%(minute)s"
|
||||
)
|
||||
# CONFIG.DEFAULT_PDF_FOOTER_TEMPLATE = "Edité par %(scodoc_name)s le %(day)s/%(month)s/%(year)s à %(hour)sh%(minute)s sur %(server_url)s"
|
||||
|
||||
|
||||
#
|
||||
|
|
Loading…
Reference in New Issue
Block a user