forked from ScoDoc/ScoDoc
Edition en ligne des codes étapes Apogée des semestre
This commit is contained in:
parent
2dbaacf460
commit
2e6e7675bf
@ -146,7 +146,8 @@ class Formation(db.Model):
|
|||||||
db.session.add(ue)
|
db.session.add(ue)
|
||||||
|
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
app.clear_scodoc_cache()
|
if change:
|
||||||
|
app.clear_scodoc_cache()
|
||||||
|
|
||||||
|
|
||||||
class Matiere(db.Model):
|
class Matiere(db.Model):
|
||||||
|
@ -286,7 +286,7 @@ class FormSemestre(db.Model):
|
|||||||
"""
|
"""
|
||||||
if not self.etapes:
|
if not self.etapes:
|
||||||
return ""
|
return ""
|
||||||
return ", ".join([str(x.etape_apo) for x in self.etapes])
|
return ", ".join(sorted([str(x.etape_apo) for x in self.etapes]))
|
||||||
|
|
||||||
def responsables_str(self, abbrev_prenom=True) -> str:
|
def responsables_str(self, abbrev_prenom=True) -> str:
|
||||||
"""chaîne "J. Dupond, X. Martin"
|
"""chaîne "J. Dupond, X. Martin"
|
||||||
@ -433,7 +433,7 @@ notes_formsemestre_responsables = db.Table(
|
|||||||
|
|
||||||
|
|
||||||
class FormSemestreEtape(db.Model):
|
class FormSemestreEtape(db.Model):
|
||||||
"""Étape Apogée associées au semestre"""
|
"""Étape Apogée associée au semestre"""
|
||||||
|
|
||||||
__tablename__ = "notes_formsemestre_etapes"
|
__tablename__ = "notes_formsemestre_etapes"
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
@ -121,6 +121,7 @@ class GenTable(object):
|
|||||||
html_with_td_classes=False, # put class=column_id in each <td>
|
html_with_td_classes=False, # put class=column_id in each <td>
|
||||||
html_before_table="", # html snippet to put before the <table> in the page
|
html_before_table="", # html snippet to put before the <table> in the page
|
||||||
html_empty_element="", # replace table when empty
|
html_empty_element="", # replace table when empty
|
||||||
|
html_table_attrs="", # for html
|
||||||
base_url=None,
|
base_url=None,
|
||||||
origin=None, # string added to excel and xml versions
|
origin=None, # string added to excel and xml versions
|
||||||
filename="table", # filename, without extension
|
filename="table", # filename, without extension
|
||||||
@ -146,6 +147,7 @@ class GenTable(object):
|
|||||||
self.html_header = html_header
|
self.html_header = html_header
|
||||||
self.html_before_table = html_before_table
|
self.html_before_table = html_before_table
|
||||||
self.html_empty_element = html_empty_element
|
self.html_empty_element = html_empty_element
|
||||||
|
self.html_table_attrs = html_table_attrs
|
||||||
self.page_title = page_title
|
self.page_title = page_title
|
||||||
self.pdf_link = pdf_link
|
self.pdf_link = pdf_link
|
||||||
self.xls_link = xls_link
|
self.xls_link = xls_link
|
||||||
@ -413,8 +415,7 @@ class GenTable(object):
|
|||||||
cls = ' class="%s"' % " ".join(tablclasses)
|
cls = ' class="%s"' % " ".join(tablclasses)
|
||||||
else:
|
else:
|
||||||
cls = ""
|
cls = ""
|
||||||
|
H = [self.html_before_table, f"<table{hid}{cls} {self.html_table_attrs}>"]
|
||||||
H = [self.html_before_table, "<table%s%s>" % (hid, cls)]
|
|
||||||
|
|
||||||
line_num = 0
|
line_num = 0
|
||||||
# thead
|
# thead
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from flask import g, request
|
from flask import g, request
|
||||||
|
from flask import url_for
|
||||||
from flask_login import current_user
|
from flask_login import current_user
|
||||||
|
|
||||||
import app
|
import app
|
||||||
@ -79,7 +80,7 @@ def index_html(showcodes=0, showsemtable=0):
|
|||||||
sco_formsemestre.sem_set_responsable_name(sem)
|
sco_formsemestre.sem_set_responsable_name(sem)
|
||||||
|
|
||||||
if showcodes:
|
if showcodes:
|
||||||
sem["tmpcode"] = "<td><tt>%s</tt></td>" % sem["formsemestre_id"]
|
sem["tmpcode"] = f"<td><tt>{sem['formsemestre_id']}</tt></td>"
|
||||||
else:
|
else:
|
||||||
sem["tmpcode"] = ""
|
sem["tmpcode"] = ""
|
||||||
# Nombre d'inscrits:
|
# Nombre d'inscrits:
|
||||||
@ -121,26 +122,27 @@ def index_html(showcodes=0, showsemtable=0):
|
|||||||
|
|
||||||
if showsemtable:
|
if showsemtable:
|
||||||
H.append(
|
H.append(
|
||||||
"""<hr/>
|
f"""<hr>
|
||||||
<h2>Semestres de %s</h2>
|
<h2>Semestres de {sco_preferences.get_preference("DeptName")}</h2>
|
||||||
"""
|
"""
|
||||||
% sco_preferences.get_preference("DeptName")
|
|
||||||
)
|
)
|
||||||
H.append(_sem_table_gt(sems, showcodes=showcodes).html())
|
H.append(_sem_table_gt(sems, showcodes=showcodes).html())
|
||||||
H.append("</table>")
|
H.append("</table>")
|
||||||
if not showsemtable:
|
if not showsemtable:
|
||||||
H.append(
|
H.append(
|
||||||
'<hr/><p><a href="%s?showsemtable=1">Voir tous les semestres</a></p>'
|
f"""<hr>
|
||||||
% request.base_url
|
<p><a class="stdlink" href="{url_for('scolar.index_html', scodoc_dept=g.scodoc_dept, showsemtable=1)
|
||||||
|
}">Voir tous les semestres ({len(othersems)} verrouillés)</a>
|
||||||
|
</p>"""
|
||||||
)
|
)
|
||||||
|
|
||||||
H.append(
|
H.append(
|
||||||
"""<p><form action="%s/view_formsemestre_by_etape">
|
f"""<p>
|
||||||
Chercher étape courante: <input name="etape_apo" type="text" size="8" spellcheck="false"></input>
|
<form action="{url_for('notes.view_formsemestre_by_etape', scodoc_dept=g.scodoc_dept)}">
|
||||||
</form
|
Chercher étape courante:
|
||||||
</p>
|
<input name="etape_apo" type="text" size="8" spellcheck="false"></input>
|
||||||
"""
|
</form>
|
||||||
% scu.NotesURL()
|
</p>"""
|
||||||
)
|
)
|
||||||
#
|
#
|
||||||
if current_user.has_permission(Permission.ScoEtudInscrit):
|
if current_user.has_permission(Permission.ScoEtudInscrit):
|
||||||
@ -148,23 +150,26 @@ Chercher étape courante: <input name="etape_apo" type="text" size="8" spellchec
|
|||||||
"""<hr>
|
"""<hr>
|
||||||
<h3>Gestion des étudiants</h3>
|
<h3>Gestion des étudiants</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a class="stdlink" href="etudident_create_form">créer <em>un</em> nouvel étudiant</a></li>
|
<li><a class="stdlink" href="etudident_create_form">créer <em>un</em> nouvel étudiant</a>
|
||||||
<li><a class="stdlink" href="form_students_import_excel">importer de nouveaux étudiants</a> (ne pas utiliser sauf cas particulier, utilisez plutôt le lien dans
|
</li>
|
||||||
le tableau de bord semestre si vous souhaitez inscrire les
|
<li><a class="stdlink" href="form_students_import_excel">importer de nouveaux étudiants</a>
|
||||||
étudiants importés à un semestre)</li>
|
(ne pas utiliser sauf cas particulier, utilisez plutôt le lien dans
|
||||||
|
le tableau de bord semestre si vous souhaitez inscrire les
|
||||||
|
étudiants importés à un semestre)
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
#
|
#
|
||||||
if current_user.has_permission(Permission.ScoEditApo):
|
if current_user.has_permission(Permission.ScoEditApo):
|
||||||
H.append(
|
H.append(
|
||||||
"""<hr>
|
f"""<hr>
|
||||||
<h3>Exports Apogée</h3>
|
<h3>Exports Apogée</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a class="stdlink" href="%s/semset_page">Années scolaires / exports Apogée</a></li>
|
<li><a class="stdlink" href="{url_for('notes.semset_page', scodoc_dept=g.scodoc_dept)
|
||||||
|
}">Années scolaires / exports Apogée</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
"""
|
"""
|
||||||
% scu.NotesURL()
|
|
||||||
)
|
)
|
||||||
#
|
#
|
||||||
H.append(
|
H.append(
|
||||||
@ -176,7 +181,13 @@ Chercher étape courante: <input name="etape_apo" type="text" size="8" spellchec
|
|||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
#
|
#
|
||||||
return html_sco_header.sco_header() + "\n".join(H) + html_sco_header.sco_footer()
|
return (
|
||||||
|
html_sco_header.sco_header(
|
||||||
|
page_title=f"ScoDoc {g.scodoc_dept}", javascripts=["js/scolar_index.js"]
|
||||||
|
)
|
||||||
|
+ "\n".join(H)
|
||||||
|
+ html_sco_header.sco_footer()
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def _sem_table(sems):
|
def _sem_table(sems):
|
||||||
@ -213,7 +224,9 @@ def _sem_table(sems):
|
|||||||
|
|
||||||
|
|
||||||
def _sem_table_gt(sems, showcodes=False):
|
def _sem_table_gt(sems, showcodes=False):
|
||||||
"""Nouvelle version de la table des semestres"""
|
"""Nouvelle version de la table des semestres
|
||||||
|
Utilise une datatables.
|
||||||
|
"""
|
||||||
_style_sems(sems)
|
_style_sems(sems)
|
||||||
columns_ids = (
|
columns_ids = (
|
||||||
"lockimg",
|
"lockimg",
|
||||||
@ -236,14 +249,16 @@ def _sem_table_gt(sems, showcodes=False):
|
|||||||
"mois_debut": "Début",
|
"mois_debut": "Début",
|
||||||
"dash_mois_fin": "Année",
|
"dash_mois_fin": "Année",
|
||||||
"titre_resp": "Semestre",
|
"titre_resp": "Semestre",
|
||||||
"nb_inscrits": "N", # groupicon,
|
"nb_inscrits": "N",
|
||||||
},
|
},
|
||||||
columns_ids=columns_ids,
|
columns_ids=columns_ids,
|
||||||
rows=sems,
|
rows=sems,
|
||||||
html_class="table_leftalign semlist",
|
table_id="semlist",
|
||||||
|
html_class_ignore_default=True,
|
||||||
|
html_class="stripe cell-border compact hover order-column table_leftalign semlist",
|
||||||
html_sortable=True,
|
html_sortable=True,
|
||||||
# base_url = '%s?formsemestre_id=%s' % (request.base_url, formsemestre_id),
|
html_table_attrs=f"""data-apo_save_url="{url_for('notes.formsemestre_set_apo_etapes', scodoc_dept=g.scodoc_dept)}" """,
|
||||||
# caption='Maquettes enregistrées',
|
html_with_td_classes=True,
|
||||||
preferences=sco_preferences.SemPreferences(),
|
preferences=sco_preferences.SemPreferences(),
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -276,6 +291,10 @@ def _style_sems(sems):
|
|||||||
sem["semestre_id_n"] = ""
|
sem["semestre_id_n"] = ""
|
||||||
else:
|
else:
|
||||||
sem["semestre_id_n"] = sem["semestre_id"]
|
sem["semestre_id_n"] = sem["semestre_id"]
|
||||||
|
# pour édition codes Apogée:
|
||||||
|
sem[
|
||||||
|
"_etapes_apo_str_td_attrs"
|
||||||
|
] = f""" data-oid="{sem['formsemestre_id']}" data-value="{sem['etapes_apo_str']}" """
|
||||||
|
|
||||||
|
|
||||||
def delete_dept(dept_id: int):
|
def delete_dept(dept_id: int):
|
||||||
|
@ -34,8 +34,6 @@ from zipfile import ZipFile
|
|||||||
import flask
|
import flask
|
||||||
from flask import url_for, g, send_file, request
|
from flask import url_for, g, send_file, request
|
||||||
|
|
||||||
# from werkzeug.utils import send_file
|
|
||||||
|
|
||||||
import app.scodoc.sco_utils as scu
|
import app.scodoc.sco_utils as scu
|
||||||
from app import log
|
from app import log
|
||||||
from app.scodoc import html_sco_header
|
from app.scodoc import html_sco_header
|
||||||
|
@ -141,7 +141,6 @@ def _formsemestre_enrich(sem):
|
|||||||
"""Ajoute champs souvent utiles: titre + annee et dateord (pour tris)"""
|
"""Ajoute champs souvent utiles: titre + annee et dateord (pour tris)"""
|
||||||
# imports ici pour eviter refs circulaires
|
# imports ici pour eviter refs circulaires
|
||||||
from app.scodoc import sco_formsemestre_edit
|
from app.scodoc import sco_formsemestre_edit
|
||||||
from app.scodoc import sco_etud
|
|
||||||
|
|
||||||
F = sco_formations.formation_list(args={"formation_id": sem["formation_id"]})[0]
|
F = sco_formations.formation_list(args={"formation_id": sem["formation_id"]})[0]
|
||||||
parcours = sco_codes_parcours.get_parcours_from_code(F["type_parcours"])
|
parcours = sco_codes_parcours.get_parcours_from_code(F["type_parcours"])
|
||||||
@ -350,6 +349,7 @@ def read_formsemestre_etapes(formsemestre_id): # OBSOLETE
|
|||||||
"""SELECT etape_apo
|
"""SELECT etape_apo
|
||||||
FROM notes_formsemestre_etapes
|
FROM notes_formsemestre_etapes
|
||||||
WHERE formsemestre_id = %(formsemestre_id)s
|
WHERE formsemestre_id = %(formsemestre_id)s
|
||||||
|
ORDER BY etape_apo
|
||||||
""",
|
""",
|
||||||
{"formsemestre_id": formsemestre_id},
|
{"formsemestre_id": formsemestre_id},
|
||||||
)
|
)
|
||||||
|
@ -728,15 +728,13 @@ def sendResult(
|
|||||||
|
|
||||||
def send_file(data, filename="", suffix="", mime=None, attached=None):
|
def send_file(data, filename="", suffix="", mime=None, attached=None):
|
||||||
"""Build Flask Response for file download of given type
|
"""Build Flask Response for file download of given type
|
||||||
By default (attached is None), json and xml are inlined and otrher types are attached.
|
By default (attached is None), json and xml are inlined and other types are attached.
|
||||||
"""
|
"""
|
||||||
if attached is None:
|
if attached is None:
|
||||||
if mime == XML_MIMETYPE or mime == JSON_MIMETYPE:
|
if mime == XML_MIMETYPE or mime == JSON_MIMETYPE:
|
||||||
attached = False
|
attached = False
|
||||||
else:
|
else:
|
||||||
attached = True
|
attached = True
|
||||||
# if attached and not filename:
|
|
||||||
# raise ValueError("send_file: missing attachement filename")
|
|
||||||
if filename:
|
if filename:
|
||||||
if suffix:
|
if suffix:
|
||||||
filename += suffix
|
filename += suffix
|
||||||
@ -755,7 +753,7 @@ def send_docx(document, filename):
|
|||||||
buffer.seek(0)
|
buffer.seek(0)
|
||||||
return flask.send_file(
|
return flask.send_file(
|
||||||
buffer,
|
buffer,
|
||||||
attachment_filename=sanitize_filename(filename),
|
download_name=sanitize_filename(filename),
|
||||||
mimetype=DOCX_MIMETYPE,
|
mimetype=DOCX_MIMETYPE,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -427,8 +427,8 @@ table.semlist tr td {
|
|||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
table.semlist tr a.stdlink,
|
table.semlist tbody tr a.stdlink,
|
||||||
table.semlist tr a.stdlink:visited {
|
table.semlist tbody tr a.stdlink:visited {
|
||||||
color: navy;
|
color: navy;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
@ -442,32 +442,86 @@ table.semlist tr td.semestre_id {
|
|||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
table.semlist tr td.modalite {
|
table.semlist tbody tr td.modalite {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
padding-right: 1em;
|
padding-right: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
div#gtrcontent table.semlist tr.css_S-1 {
|
/***************************/
|
||||||
|
/* Statut des cellules */
|
||||||
|
/***************************/
|
||||||
|
.sco_selected {
|
||||||
|
outline: 1px solid #c09;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sco_modifying {
|
||||||
|
outline: 2px dashed #c09;
|
||||||
|
background-color: white !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sco_wait {
|
||||||
|
outline: 2px solid #c90;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sco_good {
|
||||||
|
outline: 2px solid #9c0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sco_modified {
|
||||||
|
font-weight: bold;
|
||||||
|
color: indigo
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************/
|
||||||
|
/* Message */
|
||||||
|
/***************************/
|
||||||
|
.message {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 100%;
|
||||||
|
left: 50%;
|
||||||
|
z-index: 10;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 0 0 10px 10px;
|
||||||
|
background: #ec7068;
|
||||||
|
background: #90c;
|
||||||
|
color: #FFF;
|
||||||
|
font-size: 24px;
|
||||||
|
animation: message 3s;
|
||||||
|
transform: translate(-50%, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes message {
|
||||||
|
20% {
|
||||||
|
transform: translate(-50%, 100%)
|
||||||
|
}
|
||||||
|
|
||||||
|
80% {
|
||||||
|
transform: translate(-50%, 100%)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
div#gtrcontent table.semlist tbody tr.css_S-1 td {
|
||||||
background-color: rgb(251, 250, 216);
|
background-color: rgb(251, 250, 216);
|
||||||
}
|
}
|
||||||
|
|
||||||
div#gtrcontent table.semlist tr.css_S1 {
|
div#gtrcontent table.semlist tbody tr.css_S1 td {
|
||||||
background-color: rgb(92%, 95%, 94%);
|
background-color: rgb(92%, 95%, 94%);
|
||||||
}
|
}
|
||||||
|
|
||||||
div#gtrcontent table.semlist tr.css_S2 {
|
div#gtrcontent table.semlist tbody tr.css_S2 td {
|
||||||
background-color: rgb(214, 223, 236);
|
background-color: rgb(214, 223, 236);
|
||||||
}
|
}
|
||||||
|
|
||||||
div#gtrcontent table.semlist tr.css_S3 {
|
div#gtrcontent table.semlist tbody tr.css_S3 td {
|
||||||
background-color: rgb(167, 216, 201);
|
background-color: rgb(167, 216, 201);
|
||||||
}
|
}
|
||||||
|
|
||||||
div#gtrcontent table.semlist tr.css_S4 {
|
div#gtrcontent table.semlist tbody tr.css_S4 td {
|
||||||
background-color: rgb(131, 225, 140);
|
background-color: rgb(131, 225, 140);
|
||||||
}
|
}
|
||||||
|
|
||||||
div#gtrcontent table.semlist tr.css_MEXT {
|
div#gtrcontent table.semlist tbody tr.css_MEXT td {
|
||||||
color: #0b6e08;
|
color: #0b6e08;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,3 +133,134 @@ function readOnlyTags(nodes) {
|
|||||||
node.after('<span class="ro_tags"><span class="ro_tag">' + tags.join('</span><span class="ro_tag">') + '</span></span>');
|
node.after('<span class="ro_tags"><span class="ro_tag">' + tags.join('</span><span class="ro_tag">') + '</span></span>');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Editeur pour champs
|
||||||
|
* Usage: créer un élément avec data-oid (object id)
|
||||||
|
* La méthode d'URL save sera appelée en POST avec deux arguments: oid et value,
|
||||||
|
* value contenant la valeur du champs.
|
||||||
|
* Inspiré par les codes et conseils de Seb. L.
|
||||||
|
*/
|
||||||
|
class ScoFieldEditor {
|
||||||
|
constructor(selector, save_url, read_only) {
|
||||||
|
this.save_url = save_url;
|
||||||
|
this.read_only = read_only;
|
||||||
|
this.selector = selector;
|
||||||
|
this.installListeners();
|
||||||
|
}
|
||||||
|
// Enregistre l'élément obj
|
||||||
|
save(obj) {
|
||||||
|
var value = obj.innerText.trim();
|
||||||
|
if (value.length == 0) {
|
||||||
|
value = "";
|
||||||
|
}
|
||||||
|
if (value == obj.dataset.value) {
|
||||||
|
return true; // Aucune modification, pas d'enregistrement mais on continue normalement
|
||||||
|
}
|
||||||
|
obj.classList.add("sco_wait");
|
||||||
|
// DEBUG
|
||||||
|
// console.log(`
|
||||||
|
// data : ${value},
|
||||||
|
// id: ${obj.dataset.oid}
|
||||||
|
// `);
|
||||||
|
|
||||||
|
$.post(this.save_url,
|
||||||
|
{
|
||||||
|
oid: obj.dataset.oid,
|
||||||
|
value: value,
|
||||||
|
},
|
||||||
|
function (result) {
|
||||||
|
obj.classList.remove("sco_wait");
|
||||||
|
obj.classList.add("sco_modified");
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
/*****************************/
|
||||||
|
/* Gestion des évènements */
|
||||||
|
/*****************************/
|
||||||
|
installListeners() {
|
||||||
|
if (this.read_only) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
document.body.addEventListener("keydown", this.key);
|
||||||
|
let editor = this;
|
||||||
|
this.handleSelectCell = (event) => { editor.selectCell(event) };
|
||||||
|
this.handleModifCell = (event) => { editor.modifCell(event) };
|
||||||
|
this.handleBlur = (event) => { editor.blurCell(event) };
|
||||||
|
this.handleKeyCell = (event) => { editor.keyCell(event) };
|
||||||
|
document.querySelectorAll(this.selector).forEach(cellule => {
|
||||||
|
cellule.addEventListener("click", this.handleSelectCell);
|
||||||
|
cellule.addEventListener("dblclick", this.handleModifCell);
|
||||||
|
cellule.addEventListener("blur", this.handleBlur);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/*********************************/
|
||||||
|
/* Interaction avec les cellules */
|
||||||
|
/*********************************/
|
||||||
|
blurCell(event) {
|
||||||
|
let currentModif = document.querySelector(".sco_modifying");
|
||||||
|
if (currentModif) {
|
||||||
|
if (!this.save(currentModif)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
selectCell(event) {
|
||||||
|
let obj = event.currentTarget;
|
||||||
|
if (obj) {
|
||||||
|
if (obj.classList.contains("sco_modifying")) {
|
||||||
|
return; // Cellule en cours de modification, ne pas sélectionner.
|
||||||
|
}
|
||||||
|
let currentModif = document.querySelector(".sco_modifying");
|
||||||
|
if (currentModif) {
|
||||||
|
if (!this.save(currentModif)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.unselectCell();
|
||||||
|
obj.classList.add("sco_selected");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unselectCell() {
|
||||||
|
document.querySelectorAll(".sco_selected, .sco_modifying").forEach(cellule => {
|
||||||
|
cellule.classList.remove("sco_selected", "sco_modifying");
|
||||||
|
cellule.removeAttribute("contentEditable");
|
||||||
|
cellule.removeEventListener("keydown", this.handleKeyCell);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
modifCell(event) {
|
||||||
|
let obj = event.currentTarget;
|
||||||
|
if (obj) {
|
||||||
|
obj.classList.add("sco_modifying");
|
||||||
|
obj.contentEditable = true;
|
||||||
|
obj.addEventListener("keydown", this.handleKeyCell);
|
||||||
|
obj.focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
key(event) {
|
||||||
|
switch (event.key) {
|
||||||
|
case "Enter":
|
||||||
|
this.modifCell(document.querySelector(".sco_selected"));
|
||||||
|
event.preventDefault();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
keyCell(event) {
|
||||||
|
let obj = event.currentTarget;
|
||||||
|
if (obj) {
|
||||||
|
if (event.key == "Enter") {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
if (!this.save(obj)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
obj.classList.remove("sco_modifying");
|
||||||
|
// ArrowMove(0, 1);
|
||||||
|
// modifCell(document.querySelector(".sco_selected"));
|
||||||
|
this.unselectCell();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
22
app/static/js/scolar_index.js
Normal file
22
app/static/js/scolar_index.js
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
/* Page accueil département */
|
||||||
|
var apo_editor = null;
|
||||||
|
|
||||||
|
$(document).ready(function () {
|
||||||
|
var table_options = {
|
||||||
|
"paging": false,
|
||||||
|
"searching": false,
|
||||||
|
"info": false,
|
||||||
|
/* "autoWidth" : false, */
|
||||||
|
"fixedHeader": {
|
||||||
|
"header": true,
|
||||||
|
"footer": true
|
||||||
|
},
|
||||||
|
"orderCellsTop": true, // cellules ligne 1 pour tri
|
||||||
|
"aaSorting": [], // Prevent initial sorting
|
||||||
|
};
|
||||||
|
$('table.semlist').DataTable(table_options);
|
||||||
|
let apo_save_url = document.querySelector("table#semlist").dataset.apo_save_url;
|
||||||
|
apo_editor = new ScoFieldEditor(".etapes_apo_str", apo_save_url, false);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
@ -2410,6 +2410,33 @@ sco_publish(
|
|||||||
Permission.ScoEditApo,
|
Permission.ScoEditApo,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route("/formsemestre_set_apo_etapes", methods=["POST"])
|
||||||
|
@scodoc
|
||||||
|
@permission_required(Permission.ScoEditApo)
|
||||||
|
def formsemestre_set_apo_etapes():
|
||||||
|
"""Change les codes étapes du semestre indiqué.
|
||||||
|
Args: oid=formsemestre_id, value=chaine "V1RT, V1RT2", codes séparés par des virgules
|
||||||
|
"""
|
||||||
|
formsemestre_id = int(request.form.get("oid"))
|
||||||
|
etapes_apo_str = request.form.get("value")
|
||||||
|
formsemestre: FormSemestre = FormSemestre.query.get_or_404(formsemestre_id)
|
||||||
|
current_etapes = {e.etape_apo for e in formsemestre.etapes}
|
||||||
|
new_etapes = {s.strip() for s in etapes_apo_str.split(",")}
|
||||||
|
|
||||||
|
if new_etapes != current_etapes:
|
||||||
|
formsemestre.etapes = []
|
||||||
|
for etape_apo in new_etapes:
|
||||||
|
etape = models.FormSemestreEtape(
|
||||||
|
formsemestre_id=formsemestre_id, etape_apo=etape_apo
|
||||||
|
)
|
||||||
|
formsemestre.etapes.append(etape)
|
||||||
|
db.session.add(formsemestre)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
return ("", 204)
|
||||||
|
|
||||||
|
|
||||||
# sco_semset
|
# sco_semset
|
||||||
sco_publish("/semset_page", sco_semset.semset_page, Permission.ScoEditApo)
|
sco_publish("/semset_page", sco_semset.semset_page, Permission.ScoEditApo)
|
||||||
sco_publish(
|
sco_publish(
|
||||||
|
@ -327,6 +327,7 @@ def showEtudLog(etudid, format="html"):
|
|||||||
|
|
||||||
@bp.route("/")
|
@bp.route("/")
|
||||||
@bp.route("/index_html")
|
@bp.route("/index_html")
|
||||||
|
@bp.route("/index")
|
||||||
@scodoc
|
@scodoc
|
||||||
@permission_required(Permission.ScoView)
|
@permission_required(Permission.ScoView)
|
||||||
@scodoc7func
|
@scodoc7func
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# -*- mode: python -*-
|
# -*- mode: python -*-
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
SCOVERSION = "9.2.2"
|
SCOVERSION = "9.2.3"
|
||||||
|
|
||||||
SCONAME = "ScoDoc"
|
SCONAME = "ScoDoc"
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user