forked from eric.li/EditionPN
Update
This commit is contained in:
parent
2c470cfdeb
commit
4e9c35b9e6
@ -5,6 +5,7 @@
|
||||
pip install flask-wtf
|
||||
pip install flask-sqlalchemy
|
||||
pip install flask-migrate
|
||||
pip install wtforms-alchemy
|
||||
|
||||
### Pour lancer l'app
|
||||
|
||||
|
280
app/forms.py
280
app/forms.py
@ -1,8 +1,11 @@
|
||||
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 import StringField, SubmitField, FileField, TextAreaField, RadioField, SelectMultipleField, widgets, FieldList, FormField, HiddenField
|
||||
from wtforms.validators import DataRequired, Regexp, Optional, ValidationError
|
||||
from wtforms_alchemy import model_form_factory, ClassMap
|
||||
from wtforms_alchemy.fields import QuerySelectMultipleField
|
||||
from sqlalchemy_utils import ChoiceType
|
||||
from app import db
|
||||
import app.models as models
|
||||
|
||||
@ -15,14 +18,40 @@ 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
|
||||
categorie_liste = ["saes","ressources","acs"]
|
||||
categorie_to_model = {"saes": "SAE", "ressources": "Ressource", "acs": "AC"}
|
||||
separateur = None
|
||||
|
||||
class Form(FlaskForm):
|
||||
BaseModelForm = model_form_factory(FlaskForm, include_primary_keys=True)
|
||||
|
||||
class ModelForm(BaseModelForm):
|
||||
@classmethod
|
||||
def get_session(self):
|
||||
return db.session
|
||||
|
||||
class RefListField(QuerySelectMultipleField):
|
||||
option_widget=widgets.CheckboxInput()
|
||||
|
||||
class AccueilForm(FlaskForm):
|
||||
ajouter = SubmitField("Ajouter")
|
||||
reset = SubmitField("Reset")
|
||||
exporter = SubmitField("Exporter")
|
||||
importer = SubmitField("Importer")
|
||||
|
||||
class UEForm(FlaskForm):
|
||||
ue = HiddenField("Competence")
|
||||
acs = RefListField("Liste des ACs", query_factory=lambda: models.AC.query.all(), get_label=lambda ref: ref.getLabel())
|
||||
ressources = RefListField("Liste des Ressources inclus dans les ACs", query_factory=lambda: [], get_label=lambda ref: ref.getLabel())
|
||||
saes = RefListField("Liste des SAEs inclus dans les ACs", query_factory=lambda: [], get_label=lambda ref: ref.getLabel())
|
||||
|
||||
class SemestreForm(FlaskForm):
|
||||
ues = RefListField("Liste des UEs", query_factory=lambda: models.Competence.query.all(), get_label=lambda ref: ref.getLabel())
|
||||
ueform = FieldList(FormField(UEForm))
|
||||
update = SubmitField("Update")
|
||||
|
||||
class Form(ModelForm):
|
||||
class Meta:
|
||||
not_null_validator_type_map = ClassMap({db.String: [DataRequired()]})
|
||||
|
||||
sauvegarder = SubmitField("Sauvegarder")
|
||||
charger = SubmitField("Charger")
|
||||
@ -32,154 +61,105 @@ class Form(FlaskForm):
|
||||
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) ]
|
||||
def chargerRef(self):
|
||||
if self.referentiel.data == None:
|
||||
self.referentiel.errors.append("Aucun référentiel n'a été selectionné!")
|
||||
return False
|
||||
else:
|
||||
output[categorie] = valeur
|
||||
fichier = REPERTOIRE_YAML + form.code.data + ".yml"
|
||||
return True
|
||||
|
||||
def chargerBDD(self, referentiel):
|
||||
for categorie in list(self.data.keys())[7:-1]:
|
||||
self[categorie].process_data(referentiel.__dict__[categorie])
|
||||
self.referentiel.process_data(referentiel)
|
||||
|
||||
def importerRef(self):
|
||||
if len(self.fichier.errors) == 0:
|
||||
if self.fichier.data.filename == "":
|
||||
self.fichier.errors.append("Aucun fichier selectioné.")
|
||||
return
|
||||
if re.match(self.regex, self.fichier.data.filename[:-4]) == None:
|
||||
self.fichier.errors.append("Mauvais type de référentiel!")
|
||||
return
|
||||
fichier_Yaml = yaml.safe_load(self.fichier.data.read())
|
||||
for categorie, valeur in fichier_Yaml.items():
|
||||
if categorie in categorie_liste:
|
||||
model = getattr(models, categorie_to_model[categorie])
|
||||
self[categorie].process_data([model.query.filter_by(code=ref).first() for ref in valeur])
|
||||
else:
|
||||
self[categorie].process_data(valeur)
|
||||
self.validate()
|
||||
|
||||
def exporterRef(self):
|
||||
""" Exporte dans un fichier yaml les informations du formulaire rempli """
|
||||
output = {}
|
||||
for categorie, valeur in list(self.data.items())[7:-1]:
|
||||
if categorie in categorie_liste:
|
||||
output[categorie] = [ referentiel.code for referentiel in valeur ]
|
||||
else:
|
||||
output[categorie] = valeur
|
||||
fichier = REPERTOIRE_YAML + self.code.data + ".yml"
|
||||
with open(fichier, "w", encoding="utf8") as fid:
|
||||
fid.write(yaml.dump(output))
|
||||
print(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é!")
|
||||
def supprimerRef(self):
|
||||
if self.referentiel.data == None:
|
||||
self.referentiel.erros.append("Aucun référentiel n'a été selectionné!")
|
||||
return False
|
||||
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()
|
||||
temp = self.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
|
||||
return True
|
||||
|
||||
def sauvegarderRef(self):
|
||||
model = getattr(models, self.__class__.__name__[:-4])
|
||||
referentiel = model.query.filter_by(code=self.code.data).first()
|
||||
if referentiel == None: referentiel = model()
|
||||
self.populate_obj(referentiel)
|
||||
db.session.add(referentiel)
|
||||
db.session.commit()
|
||||
|
||||
class PNForm(Form):
|
||||
regex = "^PN\d$"
|
||||
|
||||
class Meta:
|
||||
model = models.PN
|
||||
type_map = ClassMap({ChoiceType: RadioField})
|
||||
|
||||
|
||||
class ACForm(Form):
|
||||
regex = "^AC\d{4}$"
|
||||
|
||||
class Meta:
|
||||
model = models.AC
|
||||
|
||||
saes = RefListField("Liste des SAEs", query_factory=lambda: models.SAE.query.all(), get_label=lambda ref: ref.getLabel())
|
||||
ressources = RefListField("Liste des Ressources", query_factory=lambda: models.Ressource.query.all(), get_label=lambda ref: ref.getLabel())
|
||||
|
||||
class SAEForm(Form):
|
||||
regex = "^SAE\d{2}$"
|
||||
|
||||
class Meta:
|
||||
model = models.SAE
|
||||
|
||||
acs = RefListField("Liste des ACs", query_factory=lambda: models.AC.query.all(), get_label=lambda ref: ref.getLabel())
|
||||
ressources = RefListField("Liste des Ressources", query_factory=lambda: models.Ressource.query.all(), get_label=lambda ref: ref.getLabel())
|
||||
|
||||
class RessourceForm(Form):
|
||||
regex = "^R\d{3}$"
|
||||
|
||||
class Meta:
|
||||
model = models.Ressource
|
||||
|
||||
acs = RefListField("Liste des ACs", query_factory=lambda: models.AC.query.all(), get_label=lambda ref: ref.getLabel())
|
||||
saes = RefListField("Liste des SAEs", query_factory=lambda: models.SAE.query.all(), get_label=lambda ref: ref.getLabel())
|
||||
|
||||
class CompetenceForm(Form):
|
||||
regex = "^RT\d$"
|
||||
|
||||
class Meta:
|
||||
model = models.Competence
|
133
app/models.py
133
app/models.py
@ -1,4 +1,25 @@
|
||||
from app import db
|
||||
from sqlalchemy_utils import ChoiceType
|
||||
|
||||
Semestres_Competences = db.Table("Semestres_Competences",
|
||||
db.Column("Semestre_num", db.String(1), db.ForeignKey("semestre.num")),
|
||||
db.Column("Competence_code", db.String(3), db.ForeignKey("competence.code"))
|
||||
)
|
||||
|
||||
ACs_Competences = db.Table("ACs_Competences",
|
||||
db.Column("AC_code", db.String(6), db.ForeignKey("AC.code")),
|
||||
db.Column("Competence_code", db.String(3), db.ForeignKey("competence.code"))
|
||||
)
|
||||
|
||||
SAEs_Competences = db.Table("SAEs_Competences",
|
||||
db.Column("SAE_code", db.String(6), db.ForeignKey("SAE.code")),
|
||||
db.Column("Competence_code", db.String(3), db.ForeignKey("competence.code"))
|
||||
)
|
||||
|
||||
Ressources_Competences = db.Table("Ressources_Competences",
|
||||
db.Column("Ressource_code", db.String(6), db.ForeignKey("ressource.code")),
|
||||
db.Column("Competence_code", db.String(3), db.ForeignKey("competence.code"))
|
||||
)
|
||||
|
||||
Ressources_ACs = db.Table("Ressources_ACs",
|
||||
db.Column("Ressource_code", db.String(4), db.ForeignKey("ressource.code")),
|
||||
@ -15,64 +36,90 @@ SAEs_ACs = db.Table("SAEs_ACs",
|
||||
db.Column("AC_code", db.String(6), db.ForeignKey("AC.code"))
|
||||
)
|
||||
|
||||
class PN(db.Model):
|
||||
code = db.Column(db.String(3), primary_key = True)
|
||||
nom = db.Column(db.String(255))
|
||||
diminutif = db.Column(db.String(30))
|
||||
description = db.Column(db.Text())
|
||||
type = db.Column(db.String(1))
|
||||
class Semestre(db.Model):
|
||||
num = db.Column(db.String(1), primary_key = True)
|
||||
ues = db.relationship("Competence", order_by="Competence.code", secondary=Semestres_Competences, lazy=False, backref=db.backref("semestres", lazy=False))
|
||||
|
||||
def __repr__(self):
|
||||
return "<PN {}>".format(self.code)
|
||||
return "<Semestre {}>".format(self.num)
|
||||
|
||||
class Competence(db.Model):
|
||||
code = db.Column(db.String(3), primary_key = True, info={'label': 'Code'})
|
||||
nom = db.Column(db.String(255), info={'label': 'Nom'})
|
||||
diminutif = db.Column(db.String(30), info={'label': 'Diminutif'})
|
||||
description = db.Column(db.Text(), info={'label': 'Description'})
|
||||
composantes = db.Column(db.Text(), info={'label': 'Composantes'})
|
||||
situations = db.Column(db.Text(), info={'label': 'Situations'})
|
||||
niveaux = db.Column(db.Text(), info={'label': 'Niveaux'})
|
||||
acs = db.relationship("AC", order_by="AC.code", secondary=ACs_Competences, lazy=False, backref=db.backref("competences", lazy=False))
|
||||
#objets de formation
|
||||
saes = db.relationship("SAE", secondary=SAEs_Competences, lazy=False, backref=db.backref("competences", lazy=False))
|
||||
ressources = db.relationship("Ressource", secondary=Ressources_Competences, lazy=False, backref=db.backref("competences", lazy=False))
|
||||
|
||||
def getLabel(self):
|
||||
return self.code + " - " + self.nom
|
||||
|
||||
def __repr__(self):
|
||||
return "<Competence {}>".format(self.code)
|
||||
|
||||
class AC(db.Model):
|
||||
code = db.Column(db.String(6), primary_key = True)
|
||||
titre = db.Column(db.String(255))
|
||||
saes = db.relationship("SAE", secondary=SAEs_ACs, cascade="all, delete", lazy=False, backref=db.backref("acs", lazy=False))
|
||||
ressources = db.relationship("Ressource", secondary=Ressources_ACs, cascade="all, delete", lazy=False, backref=db.backref("acs", lazy=False))
|
||||
code = db.Column(db.String(6), primary_key = True, info={'label': 'Code'})
|
||||
titre = db.Column(db.String(255), info={'label': 'Titre'})
|
||||
saes = db.relationship("SAE", secondary=SAEs_ACs, lazy=False, backref=db.backref("acs", lazy=False))
|
||||
ressources = db.relationship("Ressource", order_by="Ressource.code", secondary=Ressources_ACs, lazy=False, backref=db.backref("acs", lazy=False))
|
||||
|
||||
def getLabel(self):
|
||||
return self.code + " - " + self.titre
|
||||
|
||||
def __repr__(self):
|
||||
return "<AC {}>".format(self.code)
|
||||
|
||||
class PN(db.Model):
|
||||
code = db.Column(db.String(3), primary_key = True, info={'label': 'Code'})
|
||||
nom = db.Column(db.String(255), info={'label': 'Nom'})
|
||||
diminutif = db.Column(db.String(30), info={'label': 'Diminutif'})
|
||||
description = db.Column(db.Text(), info={'label': 'Description'})
|
||||
|
||||
TYPES = [("1","1"),("2","2"),("3","3")]
|
||||
type = db.Column(ChoiceType(TYPES))
|
||||
|
||||
def __repr__(self):
|
||||
return "<PN {}>".format(self.code)
|
||||
|
||||
class SAE(db.Model):
|
||||
code = db.Column(db.String(5), primary_key = True)
|
||||
titre = db.Column(db.String(255))
|
||||
semestre = db.Column(db.String(255))
|
||||
heures_encadrees = db.Column(db.String(3))
|
||||
heures_tp = db.Column(db.String(3))
|
||||
projet = db.Column(db.String(3))
|
||||
description = db.Column(db.Text())
|
||||
coef = db.Column(db.String(255))
|
||||
ressources = db.relationship("Ressource", secondary=Ressources_SAEs, cascade="all, delete", lazy=False, backref=db.backref("saes", lazy=False))
|
||||
livrables = db.Column(db.Text())
|
||||
motscles = db.Column(db.String(255))
|
||||
code = db.Column(db.String(5), primary_key = True, info={'label': 'Code'})
|
||||
titre = db.Column(db.String(255), info={'label': 'Titre'})
|
||||
semestre = db.Column(db.String(255), info={'label': 'Semestre'})
|
||||
heures_encadrees = db.Column(db.String(3), info={'label': 'Heures Encadrées'})
|
||||
heures_tp = db.Column(db.String(3), info={'label': 'Heures TP'})
|
||||
projet = db.Column(db.String(3), info={'label': 'Projet'})
|
||||
description = db.Column(db.Text(), info={'label': 'Description'})
|
||||
coef = db.Column(db.String(255), info={'label': 'Coef.'})
|
||||
ressources = db.relationship("Ressource", order_by="Ressource.code", secondary=Ressources_SAEs, lazy=False, backref=db.backref("saes", lazy=False))
|
||||
livrables = db.Column(db.Text(), info={'label': 'Livrables'})
|
||||
motscles = db.Column(db.String(255), info={'label': 'Mots Clés'})
|
||||
|
||||
def getLabel(self):
|
||||
return self.code + " - " + self.titre
|
||||
|
||||
def __repr__(self):
|
||||
return "<SAE {}>".format(self.code)
|
||||
|
||||
class Ressource(db.Model):
|
||||
code = db.Column(db.String(4), primary_key = True)
|
||||
nom = db.Column(db.String(255))
|
||||
semestre = db.Column(db.String(255))
|
||||
heures_formation = db.Column(db.String(3))
|
||||
heures_tp = db.Column(db.String(3))
|
||||
coef = db.Column(db.String(255))
|
||||
prerequis = db.Column(db.String(255))
|
||||
contexte = db.Column(db.Text())
|
||||
contenu = db.Column(db.Text())
|
||||
motscles = db.Column(db.String(255))
|
||||
code = db.Column(db.String(4), primary_key = True, info={'label': 'Code'})
|
||||
nom = db.Column(db.String(255), info={'label': 'Nom'})
|
||||
semestre = db.Column(db.String(255), info={'label': 'Semestre'})
|
||||
heures_formation = db.Column(db.String(3), info={'label': 'Heures Formation'})
|
||||
heures_tp = db.Column(db.String(3), info={'label': 'Heures TP'})
|
||||
coef = db.Column(db.String(255), info={'label': 'Coef.'})
|
||||
prerequis = db.Column(db.String(255), info={'label': 'Prerequis'})
|
||||
contexte = db.Column(db.Text(), info={'label': 'Contexte'})
|
||||
contenu = db.Column(db.Text(), info={'label': 'Contenu'})
|
||||
motscles = db.Column(db.String(255), info={'label': 'Mots Clés'})
|
||||
|
||||
def getLabel(self):
|
||||
return self.code + " - " + self.nom
|
||||
|
||||
def __repr__(self):
|
||||
return "<Ressource {}>".format(self.code)
|
||||
|
||||
class Competence(db.Model):
|
||||
code = db.Column(db.String(3), primary_key = True)
|
||||
nom = db.Column(db.String(255))
|
||||
diminutif = db.Column(db.String(30))
|
||||
description = db.Column(db.Text())
|
||||
composantes = db.Column(db.Text())
|
||||
situations = db.Column(db.Text())
|
||||
niveaux = db.Column(db.Text())
|
||||
|
||||
def __repr__(self):
|
||||
return "<Compétence {}>".format(self.code)
|
206
app/routes.py
206
app/routes.py
@ -6,96 +6,178 @@ import app.models as models
|
||||
import yaml
|
||||
|
||||
@app.route("/")
|
||||
@app.route("/index")
|
||||
@app.route("/index", methods=["GET","POST"])
|
||||
def index():
|
||||
return render_template("base.html")
|
||||
form = AccueilForm()
|
||||
if form.ajouter.data:
|
||||
for i in range(1,7):
|
||||
semestre = models.Semestre(num=i)
|
||||
db.session.add(semestre)
|
||||
db.session.commit()
|
||||
elif form.reset.data:
|
||||
for semestre in models.Semestre.query.all():
|
||||
db.session.delete(semestre)
|
||||
db.session.commit()
|
||||
semestres = sorted(models.Semestre.query.all(), key=lambda semestre: semestre.num)
|
||||
return render_template("index.html", semestres=semestres, form=form)
|
||||
|
||||
@app.route("/PN", methods=["GET","POST"])
|
||||
def PN():
|
||||
@app.route("/Semestre<num>", methods=["GET","POST"])
|
||||
def Semestre(num):
|
||||
form = SemestreForm()
|
||||
semestre = models.Semestre.query.filter_by(num=num).first()
|
||||
for i, ue in enumerate(semestre.ues):
|
||||
if form.ueform.__len__() < len(semestre.ues): form.ueform.append_entry(data={"ue": ue.code})
|
||||
# Donne aux dropdowns la liste des objets de formations que les ACs possèdent sans doublons
|
||||
querySAE = []
|
||||
queryRessource = []
|
||||
for ac in ue.acs:
|
||||
for sae in ac.saes:
|
||||
if sae not in querySAE: querySAE.append(sae)
|
||||
for ressource in ac.ressources:
|
||||
if ressource not in queryRessource: queryRessource.append(ressource)
|
||||
form.ueform.__getitem__(i).saes.query=querySAE
|
||||
form.ueform.__getitem__(i).ressources.query=queryRessource
|
||||
# Appuie sur Update
|
||||
if form.update.data:
|
||||
semestre.ues = [ue for ue in form.ues.data]
|
||||
for i, field in enumerate(form.ueform):
|
||||
ue = models.Competence.query.filter_by(code=field.ue.data).first()
|
||||
ue.acs = field.acs.data
|
||||
ue.saes = field.saes.data
|
||||
ue.ressources = field.ressources.data
|
||||
db.session.commit()
|
||||
return redirect(url_for("Semestre", num=num))
|
||||
# Coche les référentiels que l'ue possède
|
||||
for i, ue in enumerate(semestre.ues):
|
||||
form.ueform.__getitem__(i).acs.process_data(ue.acs)
|
||||
form.ueform.__getitem__(i).saes.process_data(ue.saes)
|
||||
form.ueform.__getitem__(i).ressources.process_data(ue.ressources)
|
||||
# Coche les ues que le semestre possède
|
||||
form.ues.process_data(semestre.ues)
|
||||
|
||||
return render_template("semestre.html", semestre=semestre, form=form)
|
||||
|
||||
@app.route("/PN", defaults={"code":None}, methods=["GET","POST"])
|
||||
@app.route("/PN<code>", methods=["GET","POST"])
|
||||
def PN(code):
|
||||
form = PNForm()
|
||||
form.referentiel.choices = [x for x in models.PN.query.all()]
|
||||
form_validation = form.validate_on_submit()
|
||||
form = form_import(form)
|
||||
form = form_charger(form)
|
||||
temp = form_supprimer(form)
|
||||
if temp[0] == True: return temp[1]
|
||||
else: form = temp[1]
|
||||
if form_validation and not form.charger.data:
|
||||
form.validate_on_submit()
|
||||
if form.charger.data:
|
||||
if form.chargerRef(): return redirect(url_for("PN", code=form.referentiel.data.split()[1][2:-1]))
|
||||
elif form.importer.data:
|
||||
form.importerRef()
|
||||
elif form.supprimer.data:
|
||||
if form.supprimerRef(): return redirect(url_for("PN"))
|
||||
elif form.validate_on_submit() and not form.charger.data:
|
||||
if form.exporter.data:
|
||||
flash("Ajout du référentiel PN: {} ".format(form.code.data))
|
||||
form_export(form)
|
||||
form_sauvegarder(form)
|
||||
flash("Export du référentiel PN: {} ".format(form.code.data))
|
||||
form.exporterRef()
|
||||
elif form.sauvegarder.data:
|
||||
form.sauvegarderRef()
|
||||
return redirect(url_for("PN"))
|
||||
elif code:
|
||||
referentiel = models.PN.query.filter_by(code="PN"+code).first()
|
||||
if referentiel == None: return redirect(url_for("PN"))
|
||||
else: form.chargerBDD(referentiel)
|
||||
return render_template("PN.html", form = form)
|
||||
|
||||
@app.route("/AC", methods=["GET","POST"])
|
||||
def AC():
|
||||
@app.route("/AC", defaults={"code":None}, methods=["GET","POST"])
|
||||
@app.route("/AC<code>", methods=["GET","POST"])
|
||||
def AC(code):
|
||||
form = ACForm()
|
||||
form.referentiel.choices = [x for x in models.AC.query.all()]
|
||||
form_validation = form.validate_on_submit()
|
||||
form = form_import(form)
|
||||
form = form_charger(form)
|
||||
temp = form_supprimer(form)
|
||||
if temp[0] == True: return temp[1]
|
||||
else: form = temp[1]
|
||||
if form_validation and not form.charger.data:
|
||||
form.validate_on_submit()
|
||||
if form.charger.data:
|
||||
if form.chargerRef(): return redirect(url_for("AC", code=form.referentiel.data.split()[1][2:-1]))
|
||||
elif form.importer.data:
|
||||
form.importerRef()
|
||||
elif form.supprimer.data:
|
||||
if form.supprimerRef(): return redirect(url_for("AC"))
|
||||
elif form.validate_on_submit() and not form.charger.data:
|
||||
if form.exporter.data:
|
||||
flash("Ajout du référentiel AC: {} ".format(form.code.data))
|
||||
form_export(form)
|
||||
form_sauvegarder(form)
|
||||
flash("Export du référentiel AC: {} ".format(form.code.data))
|
||||
form.exporterRef()
|
||||
elif form.sauvegarder.data:
|
||||
form.sauvegarderRef()
|
||||
return redirect(url_for("AC"))
|
||||
elif code:
|
||||
referentiel = models.AC.query.filter_by(code="AC"+code).first()
|
||||
if referentiel == None: return redirect(url_for("AC"))
|
||||
else: form.chargerBDD(referentiel)
|
||||
return render_template("AC.html", form = form)
|
||||
|
||||
@app.route("/SAE", methods=["GET","POST"])
|
||||
def SAE():
|
||||
@app.route("/SAE", defaults={"code":None}, methods=["GET","POST"])
|
||||
@app.route("/SAE<code>", methods=["GET","POST"])
|
||||
def SAE(code):
|
||||
form = SAEForm()
|
||||
form.referentiel.choices = [x for x in models.SAE.query.all()]
|
||||
form_validation = form.validate_on_submit()
|
||||
form = form_import(form)
|
||||
form = form_charger(form)
|
||||
temp = form_supprimer(form)
|
||||
if temp[0] == True: return temp[1]
|
||||
else: form = temp[1]
|
||||
if form_validation and not form.charger.data:
|
||||
form.validate_on_submit()
|
||||
if form.charger.data:
|
||||
if form.chargerRef(): return redirect(url_for("SAE", code=form.referentiel.data.split()[1][3:-1]))
|
||||
elif form.importer.data:
|
||||
form.importerRef()
|
||||
elif form.supprimer.data:
|
||||
if form.supprimerRef(): return redirect(url_for("SAE"))
|
||||
elif form.validate_on_submit() and not form.charger.data:
|
||||
if form.exporter.data:
|
||||
flash("Ajout du référentiel SAE: {} ".format(form.code.data))
|
||||
form_export(form)
|
||||
form_sauvegarder(form)
|
||||
flash("Export du référentiel SAE: {} ".format(form.code.data))
|
||||
form.exporterRef()
|
||||
elif form.sauvegarder.data:
|
||||
form.sauvegarderRef()
|
||||
return redirect(url_for("SAE"))
|
||||
elif code:
|
||||
referentiel = models.SAE.query.filter_by(code="SAE"+code).first()
|
||||
if referentiel == None: return redirect(url_for("SAE"))
|
||||
else: form.chargerBDD(referentiel)
|
||||
return render_template("SAE.html", form = form)
|
||||
|
||||
@app.route("/Ressource", methods=["GET","POST"])
|
||||
def Ressource():
|
||||
@app.route("/Ressource", defaults={"code":None}, methods=["GET","POST"])
|
||||
@app.route("/Ressource<code>", methods=["GET","POST"])
|
||||
def Ressource(code):
|
||||
form = RessourceForm()
|
||||
form.referentiel.choices = [x for x in models.Ressource.query.all()]
|
||||
form_validation = form.validate_on_submit()
|
||||
form = form_import(form)
|
||||
form = form_charger(form)
|
||||
temp = form_supprimer(form)
|
||||
if temp[0] == True: return temp[1]
|
||||
else: form = temp[1]
|
||||
if form_validation and not form.charger.data:
|
||||
form.validate_on_submit()
|
||||
if form.charger.data:
|
||||
if form.chargerRef(): return redirect(url_for("Ressource", code=form.referentiel.data.split()[1][1:-1]))
|
||||
elif form.importer.data:
|
||||
form.importerRef()
|
||||
elif form.supprimer.data:
|
||||
if form.supprimerRef(): return redirect(url_for("Ressource"))
|
||||
elif form.validate_on_submit() and not form.charger.data:
|
||||
if form.exporter.data:
|
||||
flash("Ajout du référentiel Ressource: {} ".format(form.code.data))
|
||||
form_export(form)
|
||||
form_sauvegarder(form)
|
||||
flash("Export du référentiel Ressource: {} ".format(form.code.data))
|
||||
form.exporterRef()
|
||||
elif form.sauvegarder.data:
|
||||
form.sauvegarderRef()
|
||||
return redirect(url_for("Ressource"))
|
||||
elif code:
|
||||
referentiel = models.Ressource.query.filter_by(code="R"+code).first()
|
||||
if referentiel == None: return redirect(url_for("Ressource"))
|
||||
else: form.chargerBDD(referentiel)
|
||||
return render_template("Ressource.html", form = form)
|
||||
|
||||
@app.route("/Competence", methods=["GET","POST"])
|
||||
def Competence():
|
||||
@app.route("/Competence", defaults={"code":None}, methods=["GET","POST"])
|
||||
@app.route("/Competence<code>", methods=["GET","POST"])
|
||||
def Competence(code):
|
||||
form = CompetenceForm()
|
||||
form.referentiel.choices = [x for x in models.Competence.query.all()]
|
||||
form_validation = form.validate_on_submit()
|
||||
form = form_import(form)
|
||||
form = form_charger(form)
|
||||
temp = form_supprimer(form)
|
||||
if temp[0] == True: return temp[1]
|
||||
else: form = temp[1]
|
||||
if form_validation and not form.charger.data:
|
||||
form.validate_on_submit()
|
||||
if form.charger.data:
|
||||
if form.chargerRef(): return redirect(url_for("Competence", code=form.referentiel.data.split()[1][2:-1]))
|
||||
elif form.importer.data:
|
||||
form.importerRef()
|
||||
elif form.supprimer.data:
|
||||
if form.supprimerRef(): return redirect(url_for("Compentence"))
|
||||
elif form.validate_on_submit() and not form.charger.data:
|
||||
if form.exporter.data:
|
||||
flash("Ajout du référentielCompetence: {} ".format(form.code.data))
|
||||
form_export(form)
|
||||
form_sauvegarder(form)
|
||||
flash("Export du référentielCompetence: {} ".format(form.code.data))
|
||||
form.exporterRef()
|
||||
if form.sauvegarder.data:
|
||||
form.sauvegarderRef()
|
||||
return redirect(url_for("Competence"))
|
||||
elif code:
|
||||
referentiel = models.Competence.query.filter_by(code="RT"+code).first()
|
||||
if referentiel == None: return redirect(url_for("Competence"))
|
||||
else: form.chargerBDD(referentiel)
|
||||
return render_template("Competence.html", form = form)
|
12
app/static/js/base.js
Normal file
12
app/static/js/base.js
Normal file
@ -0,0 +1,12 @@
|
||||
$("document").ready(function() {
|
||||
// Affichage mobile du menu | affiche/cache le menu contenant la liste des catégories
|
||||
// en appuyant sur le burger/les trois traits
|
||||
$(".navbar-burger").click(function() {
|
||||
$(".navbar-burger").toggleClass("is-active");
|
||||
$(".navbar-menu").toggleClass("is-active");
|
||||
});
|
||||
|
||||
$(".navbar-item.has-dropdown").click(function() {
|
||||
$(this).toggleClass("is-active");
|
||||
});
|
||||
});
|
@ -7,7 +7,9 @@
|
||||
|
||||
{{ render_field(form.code,"input") }}
|
||||
{{ render_field(form.titre,"input") }}
|
||||
{{ render_field(form.saes,"input") }}
|
||||
{{ render_field(form.ressources,"input") }}
|
||||
{{ render_list(form.saes) }}
|
||||
<div class="field">{{ render_dropdown(form.saes) }}</div>
|
||||
{{ render_list(form.ressources) }}
|
||||
<div class="field">{{ render_dropdown(form.ressources) }}</div>
|
||||
|
||||
{% endblock %}
|
@ -11,8 +11,10 @@
|
||||
{{ render_field(form.heures_formation,"input") }}
|
||||
{{ render_field(form.heures_tp,"input") }}
|
||||
{{ render_field(form.coef,"input") }}
|
||||
{{ render_field(form.acs,"input") }}
|
||||
{{ render_field(form.saes,"input") }}
|
||||
{{ render_list(form.acs) }}
|
||||
<div class="field">{{ render_dropdown(form.acs) }}</div>
|
||||
{{ render_list(form.saes) }}
|
||||
<div class="field">{{ render_dropdown(form.saes) }}</div>
|
||||
{{ render_field(form.prerequis,"input") }}
|
||||
{{ render_field(form.contexte,"textarea") }}
|
||||
{{ render_field(form.contenu,"textarea") }}
|
||||
|
@ -13,8 +13,10 @@
|
||||
{{ render_field(form.projet,"input") }}
|
||||
{{ render_field(form.description,"textarea") }}
|
||||
{{ render_field(form.coef,"input") }}
|
||||
{{ render_field(form.acs,"input") }}
|
||||
{{ render_field(form.ressources,"input") }}
|
||||
{{ render_list(form.acs) }}
|
||||
<div class="field">{{ render_dropdown(form.acs) }}</div>
|
||||
{{ render_list(form.ressources) }}
|
||||
<div class="field">{{ render_dropdown(form.ressources) }}</div>
|
||||
{{ render_field(form.livrables,"textarea") }}
|
||||
{{ render_field(form.motscles,"input") }}
|
||||
|
||||
|
@ -1,3 +1,47 @@
|
||||
{% macro render_dropdown(field) %}
|
||||
<div class="control is-expanded">
|
||||
<div class="dropdown is-hoverable" style="width: 100%">
|
||||
<div class="dropdown-trigger" style="width: 100%">
|
||||
<span class="button is-fullwidth" aria-controls="dropdown-menu">
|
||||
<span>{{ field.label }}</span>
|
||||
<span class="icon is-small">
|
||||
<i class="fas fa-angle-down"></i>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="dropdown-menu" style="width: 100%">
|
||||
<div class="dropdown-content">
|
||||
{% for val in field %}
|
||||
<div class="dropdown-item">
|
||||
{{ val }} {{ val.label }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro render_field(field,class) %}
|
||||
<div class="field">
|
||||
<label class="label">{{ field.label }}</label>
|
||||
<div class="control">
|
||||
{{ field(class=class)}}
|
||||
</div>
|
||||
{% for error in field.errors %}
|
||||
<p class="help is-danger">{{error}}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro render_list(field) %}
|
||||
<ul>
|
||||
{% for ref in field.data %}
|
||||
<li>{{ ref.code }} - {{ ref.titre }}{{ ref.nom }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endmacro %}
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html class="has-navbar-fixed-top">
|
||||
<head>
|
||||
@ -7,6 +51,7 @@
|
||||
<link type="text/css" rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.2/css/bulma.min.css">
|
||||
<link type="text/css" rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css">
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
|
||||
<script src="{{ url_for('static', filename='js/base.js') }}"></script>
|
||||
{% block head %}{% endblock %}
|
||||
</head>
|
||||
<body>
|
||||
@ -25,6 +70,18 @@
|
||||
<div class="navbar-menu">
|
||||
<div class="navbar-start">
|
||||
<!-- Liste des catégories -->
|
||||
<a class="navbar-item" href="{{ url_for('index') }}">Accueil</a>
|
||||
<div class="navbar-item has-dropdown">
|
||||
<a class="navbar-link">Semestres</a>
|
||||
<div class="navbar-dropdown">
|
||||
<a class="navbar-item" href="{{ url_for('Semestre', num=1) }}">Semestre 1</a>
|
||||
<a class="navbar-item" href="{{ url_for('Semestre', num=2) }}">Semestre 2</a>
|
||||
<a class="navbar-item" href="{{ url_for('Semestre', num=3) }}">Semestre 3</a>
|
||||
<a class="navbar-item" href="{{ url_for('Semestre', num=4) }}">Semestre 4</a>
|
||||
<a class="navbar-item" href="{{ url_for('Semestre', num=5) }}">Semestre 5</a>
|
||||
<a class="navbar-item" href="{{ url_for('Semestre', num=6) }}">Semestre 6</a>
|
||||
</div>
|
||||
</div>
|
||||
<a class="navbar-item" href="{{ url_for('PN') }}">PN</a>
|
||||
<a class="navbar-item" href="{{ url_for('AC') }}">AC</a>
|
||||
<a class="navbar-item" href="{{ url_for('SAE') }}">SAÉ</a>
|
||||
@ -52,3 +109,4 @@
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
@ -1,14 +1,3 @@
|
||||
{% macro render_field(field,class) %}
|
||||
<div class="field">
|
||||
<label class="label">{{ field.label }}</label>
|
||||
<div class="control">
|
||||
{{ field(class=class)}}
|
||||
</div>
|
||||
{% for error in field.errors %}
|
||||
<p class="help is-danger">{{error}}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endmacro %}
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
@ -49,7 +38,7 @@
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% for error in form.charger.errors %}
|
||||
{% for error in form.referentiel.errors %}
|
||||
<p class="help is-danger">{{error}}</p>
|
||||
{% endfor %}
|
||||
{% if form.referentiel.choices|length != 0 %}
|
||||
|
35
app/templates/index.html
Normal file
35
app/templates/index.html
Normal file
@ -0,0 +1,35 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}Accueil{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="content">
|
||||
{% for semestre in semestres %}
|
||||
<h1 class="title"><a style="color: inherit;" href="{{ url_for('Semestre', num=semestre.num) }}">Semestre {{ semestre.num }} <i class="far fa-edit fa-sm"></i></a></h1>
|
||||
<ul>
|
||||
{% for competence in semestre.ues %}
|
||||
<li><h2 class="title is-4"><a style="color: inherit;" href="{{ url_for('Competence', code=competence.code[-1]) }}">UE{{ semestre.num }}.{{ competence.code[-1] }} - {{ competence.nom }} <i class="far fa-edit fa-sm"></i></a></h2></li>
|
||||
<ul>
|
||||
{% for ac in competence.acs %}
|
||||
<li><a style="color: inherit;" href="{{ url_for('AC', code=ac.code[2:]) }}"><span class="tag is-info">{{ ac.code }}</span> - {{ ac.titre }} <i class="far fa-edit fa-sm"></i></a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<form action="" method="post" novalidate>
|
||||
{{ form.hidden_tag() }}
|
||||
<div class="buttons">
|
||||
{% if not semestres %}
|
||||
{{ form.ajouter(class="button") }}
|
||||
{{ form.reset(class="button is-static") }}
|
||||
{% else %}
|
||||
{{ form.ajouter(class="button is-static") }}
|
||||
{{ form.reset(class="button") }}
|
||||
{% endif %}
|
||||
{{ form.exporter(class="button is-static") }}
|
||||
{{ form.importer(class="button is-static") }}
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
41
app/templates/semestre.html
Normal file
41
app/templates/semestre.html
Normal file
@ -0,0 +1,41 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Semestre 1{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<form action="" method="post" novalidate>
|
||||
{{ form.hidden_tag() }}
|
||||
<div class="content">
|
||||
{% for competence in semestre.ues %}
|
||||
<h2 class="title"><a style="color: inherit;" href="{{ url_for('Competence', code=competence.code[-1]) }}">UE{{ semestre.num }}.{{ competence.code[-1] }} - {{ competence.nom }} <i class="far fa-edit fa-sm"></i></a></h2>
|
||||
<ul>
|
||||
{% for ac in competence.acs %}
|
||||
<li><a style="color: inherit;" href="{{ url_for('AC', code=ac.code[2:]) }}"><span class="tag is-info">{{ ac.code }}</span> - {{ ac.titre }} <i class="far fa-edit fa-sm"></i></a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{{ form.ueform.__getitem__(loop.index0).ue }}
|
||||
{{ render_dropdown(form.ueform.__getitem__(loop.index0).acs) }}
|
||||
<p>Objets de formation</p>
|
||||
<ul>
|
||||
{% for sae in competence.saes %}
|
||||
<li><a style="color: inherit;" href="{{ url_for('SAE', code=sae.code[3:]) }}"><span class="tag is-info">{{ sae.code }}</span> - {{ sae.titre }} <i class="far fa-edit fa-sm"></i></a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{{ render_dropdown(form.ueform.__getitem__(loop.index0).saes) }}
|
||||
<ul>
|
||||
{% for ressource in competence.ressources %}
|
||||
<li><a style="color: inherit;" href="{{ url_for('Ressource', code=ressource.code[1:]) }}"><span class="tag is-info">{{ ressource.code }}</span> - {{ ressource.nom }} <i class="far fa-edit fa-sm"></i></a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{{ render_dropdown(form.ueform.__getitem__(loop.index0).ressources) }}
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="field is-grouped">
|
||||
{{ render_dropdown(form.ues) }}
|
||||
<div class="control">
|
||||
{{ form.update(class="button") }}
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
38
migrations/versions/03ec797adcc8_.py
Normal file
38
migrations/versions/03ec797adcc8_.py
Normal file
@ -0,0 +1,38 @@
|
||||
"""empty message
|
||||
|
||||
Revision ID: 03ec797adcc8
|
||||
Revises: 15feabeae315
|
||||
Create Date: 2021-05-12 12:41:11.703242
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '03ec797adcc8'
|
||||
down_revision = '15feabeae315'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.create_table('semestre',
|
||||
sa.Column('num', sa.String(length=1), nullable=False),
|
||||
sa.PrimaryKeyConstraint('num')
|
||||
)
|
||||
op.create_table('Semestres_Competences',
|
||||
sa.Column('Semestre_num', sa.String(length=1), nullable=True),
|
||||
sa.Column('Competence_code', sa.String(length=3), nullable=True),
|
||||
sa.ForeignKeyConstraint(['Competence_code'], ['competence.code'], ),
|
||||
sa.ForeignKeyConstraint(['Semestre_num'], ['semestre.num'], )
|
||||
)
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_table('Semestres_Competences')
|
||||
op.drop_table('semestre')
|
||||
# ### end Alembic commands ###
|
40
migrations/versions/8b0862eb0856_.py
Normal file
40
migrations/versions/8b0862eb0856_.py
Normal file
@ -0,0 +1,40 @@
|
||||
"""empty message
|
||||
|
||||
Revision ID: 8b0862eb0856
|
||||
Revises: cff96c022884
|
||||
Create Date: 2021-06-01 18:50:16.604312
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '8b0862eb0856'
|
||||
down_revision = 'cff96c022884'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.create_table('Ressources_Competences',
|
||||
sa.Column('Ressource_code', sa.String(length=6), nullable=True),
|
||||
sa.Column('Competence_code', sa.String(length=3), nullable=True),
|
||||
sa.ForeignKeyConstraint(['Competence_code'], ['competence.code'], ),
|
||||
sa.ForeignKeyConstraint(['Ressource_code'], ['ressource.code'], )
|
||||
)
|
||||
op.create_table('SAEs_Competences',
|
||||
sa.Column('SAE_code', sa.String(length=6), nullable=True),
|
||||
sa.Column('Competence_code', sa.String(length=3), nullable=True),
|
||||
sa.ForeignKeyConstraint(['Competence_code'], ['competence.code'], ),
|
||||
sa.ForeignKeyConstraint(['SAE_code'], ['SAE.code'], )
|
||||
)
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_table('SAEs_Competences')
|
||||
op.drop_table('Ressources_Competences')
|
||||
# ### end Alembic commands ###
|
33
migrations/versions/cff96c022884_.py
Normal file
33
migrations/versions/cff96c022884_.py
Normal file
@ -0,0 +1,33 @@
|
||||
"""empty message
|
||||
|
||||
Revision ID: cff96c022884
|
||||
Revises: 03ec797adcc8
|
||||
Create Date: 2021-05-13 15:30:50.203249
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = 'cff96c022884'
|
||||
down_revision = '03ec797adcc8'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.create_table('ACs_Competences',
|
||||
sa.Column('AC_code', sa.String(length=6), nullable=True),
|
||||
sa.Column('Competence_code', sa.String(length=3), nullable=True),
|
||||
sa.ForeignKeyConstraint(['AC_code'], ['AC.code'], ),
|
||||
sa.ForeignKeyConstraint(['Competence_code'], ['competence.code'], )
|
||||
)
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_table('ACs_Competences')
|
||||
# ### end Alembic commands ###
|
Loading…
Reference in New Issue
Block a user