from flask import redirect, url_for from flask_wtf import FlaskForm from flask_wtf.file import FileAllowed from wtforms import StringField, SubmitField, FileField, TextAreaField, RadioField from wtforms.validators import DataRequired, Regexp, Optional, ValidationError from app import db import app.models as models import yaml import os import re REPERTOIRE_YAML = "./export/" if not os.path.exists(REPERTOIRE_YAML): os.makedirs(REPERTOIRE_YAML) def validate_ref_list(regex, message): def _validate_ref_list(form, field): refs = field.data.strip() + " " if re.match(regex, refs) == None: raise ValidationError(message) return _validate_ref_list class Form(FlaskForm): sauvegarder = SubmitField("Sauvegarder") charger = SubmitField("Charger") supprimer = SubmitField("Supprimer") exporter = SubmitField("Exporter") fichier = FileField("Choisir fichier", validators=[FileAllowed(["yml"], "Fichier Yaml seulement!")]) importer = SubmitField("Importer") referentiel = RadioField("Liste des référentiels", validators=[Optional()]) class PNForm(Form): regex = "^PN\d$" code = StringField("Code", validators=[DataRequired(), Regexp("^PN\d$", message="Le code doit être de la forme PN0.")]) nom = StringField("Nom", validators=[DataRequired()] ) diminutif = StringField("Diminutif", validators=[DataRequired()] ) description = TextAreaField("Description", validators=[DataRequired()] ) type = RadioField("Type", choices=["1","2","3"], validators=[DataRequired()]) class ACForm(Form): regex = "^AC\d{4}$" code = StringField("Code", validators=[DataRequired(), Regexp("^AC\d{4}$", message="Le code doit être de la forme AC0000.")]) titre = StringField("Titre", validators=[DataRequired()] ) saes = StringField("SAEs", validators=[DataRequired(), validate_ref_list("^(\s*(SAE\d{2}\s+)*)$", message="Les saes doit être de la forme SAE00.")] ) ressources = StringField("Ressources", validators=[DataRequired(), validate_ref_list("^(\s*(R\d{3}\s+)*)$", message="Les ressources doit être de la forme R000.")] ) class SAEForm(Form): regex = "^SAE\d{2}$" code = StringField("Code", validators=[DataRequired(), Regexp("^SAE\d{2}$", message="Le code doit être de la forme SAE00.")]) titre = StringField("Titre", validators=[DataRequired()] ) semestre = StringField("Semestre", validators=[DataRequired()] ) heures_encadrees = StringField("Heures encadrées", validators=[DataRequired()] ) heures_tp = StringField("Heures TP", validators=[DataRequired()] ) projet = StringField("Projet", validators=[DataRequired()] ) description = TextAreaField("Description", validators=[DataRequired()] ) coef = StringField("Coef.", validators=[DataRequired()] ) acs = StringField("ACs", validators=[DataRequired(), validate_ref_list("^(\s*(AC\d{4}\s+)*)$", message="Les acs être de la forme AC0000.")] ) ressources = StringField("Ressources", validators=[DataRequired(), validate_ref_list("^(\s*(R\d{3}\s+)*)$", message="Les ressources doit être de la forme R000.")] ) livrables = TextAreaField("Livrables", validators=[DataRequired()] ) motscles = StringField("Mots clés", validators=[DataRequired()] ) class RessourceForm(Form): regex = "^R\{3}$" code = StringField("Code", validators=[DataRequired(), Regexp("^R\{3}$", message="Le code doit être de la forme R000.")]) nom = StringField("Nom", validators=[DataRequired()] ) semestre = StringField("Semestre", validators=[DataRequired()] ) heures_formation = StringField("Heures formation", validators=[DataRequired()] ) heures_tp = StringField("Heures TP", validators=[DataRequired()] ) coef = StringField("Coef.", validators=[DataRequired()] ) acs = StringField("ACs", validators=[DataRequired(), validate_ref_list("^(\s*(AC\d{4}\s+)*)$", message="Les acs doit être de la forme AC0000.")] ) saes = StringField("SAEs", validators=[DataRequired(), validate_ref_list("^(\s*(SAE\d{2}\s+)*)$", message="Les saes doit être de la forme SAE00.")] ) prerequis = StringField("Prérequis", validators=[DataRequired()] ) contexte = TextAreaField("Contexte", validators=[DataRequired()] ) contenu = TextAreaField("Contenu", validators=[DataRequired()] ) motscles = StringField("Mots clés", validators=[DataRequired()] ) class CompetenceForm(Form): regex = "^RT\d$" code = StringField("Code", validators=[DataRequired(), Regexp("^RT\d$", message="Le code doit être de la forme RT0.")]) nom = StringField("Nom", validators=[DataRequired()] ) diminutif = StringField("Diminutif", validators=[DataRequired()] ) description = TextAreaField("Description", validators=[DataRequired()] ) composantes = TextAreaField("Composantes", validators=[DataRequired()] ) situations = TextAreaField("Situations", validators=[DataRequired()] ) niveaux = TextAreaField("Niveaux", validators=[DataRequired()] ) categorie_liste = ["saes","ressources","acs"] categorie_to_model = {"saes": "SAE", "ressources": "Ressource", "acs": "AC"} separateur = None def form_import(form): """ Si le bouton import a été appuyé et qu'il n'y a pas d'erreur d'import => importe le fichier yaml""" # Bouton import appuyé et fichier yaml selectionné if form.importer.data and len(form.fichier.errors) == 0: if form.fichier.data.filename == "": form.fichier.errors.append("Aucun fichier selectioné.") return form if re.match(form.regex, form.fichier.data.filename[:-4]) == None: form.fichier.errors.append("Mauvais type de référentiel!") return form fichier_Yaml = yaml.safe_load(form.fichier.data.read()) for categorie, valeur in fichier_Yaml.items(): if categorie in categorie_liste: form[categorie].process_data(" ".join(valeur)) else: form[categorie].process_data(valeur) form.validate_on_submit() # Réinitialise les messages d'erreur return form def form_export(form): """ Si le formulaire est valide => exporte dans un fichier yaml avec les informations du formulaire """ output = {} for categorie, valeur in list(form.data.items())[7:-1]: if categorie in categorie_liste: output[categorie] = [ referentiel for referentiel in valeur.split(separateur) ] else: output[categorie] = valeur fichier = REPERTOIRE_YAML + form.code.data + ".yml" with open(fichier, "w", encoding="utf8") as fid: fid.write(yaml.dump(output)) def form_charger(form): """ Si le bouton charger est appuyé et qu'un référentiel du BDD a été selectionné => remplie le formulaire avec ses informations """ if form.charger.data: if form.referentiel.data == None: form.referentiel.errors.append("Aucun référentiel n'a été selectionné!") else: temp = form.referentiel.data[1:-1].split() model = getattr(models, temp[0]) referentiel = model.query.filter_by(code=temp[1]).first() for categorie in list(referentiel.__dict__)[1:]: if categorie in categorie_liste: form[categorie].process_data(" ".join(ref.code for ref in referentiel.__dict__[categorie])) else: form[categorie].process_data(referentiel.__dict__[categorie]) form.validate_on_submit() return form def form_sauvegarder(form): """ Si le bouton sauvegarder est appuyé et que le formulaire est valide => ajoute le référentiel dans la table respectif du base de données """ if form.sauvegarder.data: model = getattr(models, "".join( c for c in form.code.data if not c.isdigit())) referentiel = model.query.filter_by(code=form.code.data).first() if referentiel == None: referentiel = model() # Si le référentiel contient une catégorie avec une liste de référentiels for categorie, valeur in list(form.data.items())[7:-1]: if categorie in categorie_liste: resultat = [] refs = [ ref for ref in form[categorie].data.split(separateur) ] ref_model = getattr(models, categorie_to_model[categorie]) for ref in refs: ref_bdd = ref_model.query.filter_by(code=ref).first() if ref_bdd == None: ref_new = ref_model(code=ref) resultat.append(ref_new) db.session.add(ref_new) else: resultat.append(ref_bdd) form[categorie].process_data(resultat) form.populate_obj(referentiel) db.session.add(referentiel) db.session.commit() def form_supprimer(form): if form.supprimer.data: if form.referentiel.data == None: form.referentiel.errors.append("Aucun référentiel n'a été selectionné!") else: temp = form.referentiel.data[1:-1].split() model = getattr(models, temp[0]) referentiel = model.query.filter_by(code=temp[1]).first() db.session.delete(referentiel) db.session.commit() return True, redirect(url_for(temp[0])) return False, form