Reorganisation form configuration globale. Doc bonus.

This commit is contained in:
Emmanuel Viennet 2022-01-25 23:48:39 +01:00
parent 417cb53603
commit 08e9d2449a
10 changed files with 267 additions and 152 deletions

View File

@ -28,7 +28,6 @@
""" """
Formulaires configuration Exports Apogée (codes) Formulaires configuration Exports Apogée (codes)
""" """
import re
from flask import flash, url_for, redirect, render_template from flask import flash, url_for, redirect, render_template
from flask_wtf import FlaskForm from flask_wtf import FlaskForm

View File

@ -47,7 +47,6 @@ from app.scodoc.sco_config_actions import (
LogoDelete, LogoDelete,
LogoUpdate, LogoUpdate,
LogoInsert, LogoInsert,
BonusSportUpdate,
) )
from flask_login import current_user from flask_login import current_user
@ -296,23 +295,15 @@ def _make_depts_data(modele):
return data return data
def _make_data(bonus_sport, modele): def _make_data(modele):
data = { data = {
"bonus_sport_func_name": bonus_sport,
"depts": _make_depts_data(modele=modele), "depts": _make_depts_data(modele=modele),
} }
return data return data
class ScoDocConfigurationForm(FlaskForm): class LogosConfigurationForm(FlaskForm):
"Panneau de configuration général" "Panneau de configuration des logos"
bonus_sport_func_name = SelectField(
label="Fonction de calcul des bonus sport&culture",
choices=[
(x, x if x else "Aucune")
for x in ScoDocSiteConfig.get_bonus_sport_class_names()
],
)
depts = FieldList(FormField(DeptForm)) depts = FieldList(FormField(DeptForm))
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
@ -361,11 +352,6 @@ class ScoDocConfigurationForm(FlaskForm):
return dept_form.get_form(logoname) return dept_form.get_form(logoname)
def select_action(self): def select_action(self):
if (
self.data["bonus_sport_func_name"]
!= ScoDocSiteConfig.get_bonus_sport_class_name()
):
return BonusSportUpdate(self.data)
for dept_entry in self.depts: for dept_entry in self.depts:
dept_form = dept_entry.form dept_form = dept_entry.form
action = dept_form.select_action() action = dept_form.select_action()
@ -374,14 +360,11 @@ class ScoDocConfigurationForm(FlaskForm):
return None return None
def configuration(): def config_logos():
"""Panneau de configuration général""" "Page de configuration des logos"
auth_name = str(current_user) # nb: le contrôle d'accès (SuperAdmin) doit être fait dans la vue
if not current_user.is_administrator(): form = LogosConfigurationForm(
raise AccessDenied("invalid user (%s) must be SuperAdmin" % auth_name)
form = ScoDocConfigurationForm(
data=_make_data( data=_make_data(
bonus_sport=ScoDocSiteConfig.get_bonus_sport_class_name(),
modele=sco_logos.list_logos(), modele=sco_logos.list_logos(),
) )
) )
@ -392,11 +375,11 @@ def configuration():
flash(action.message) flash(action.message)
return redirect( return redirect(
url_for( url_for(
"scodoc.configuration", "scodoc.configure_logos",
) )
) )
return render_template( return render_template(
"configuration.html", "config_logos.html",
scodoc_dept=None, scodoc_dept=None,
title="Configuration ScoDoc", title="Configuration ScoDoc",
form=form, form=form,

View File

@ -0,0 +1,76 @@
# -*- mode: python -*-
# -*- coding: utf-8 -*-
##############################################################################
#
# ScoDoc
#
# Copyright (c) 1999 - 2022 Emmanuel Viennet. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# Emmanuel Viennet emmanuel.viennet@viennet.net
#
##############################################################################
"""
Formulaires configuration Exports Apogée (codes)
"""
from flask import flash, url_for, redirect, request, render_template
from flask_wtf import FlaskForm
from wtforms import SelectField, SubmitField
import app
from app.models import ScoDocSiteConfig
class ScoDocConfigurationForm(FlaskForm):
"Panneau de configuration des logos"
bonus_sport_func_name = SelectField(
label="Fonction de calcul des bonus sport&culture",
choices=[
(x, x if x else "Aucune")
for x in ScoDocSiteConfig.get_bonus_sport_class_names()
],
)
submit = SubmitField("Valider")
cancel = SubmitField("Annuler", render_kw={"formnovalidate": True})
def configuration():
"Page de configuration principale"
# nb: le contrôle d'accès (SuperAdmin) doit être fait dans la vue
form = ScoDocConfigurationForm(
data={
"bonus_sport_func_name": ScoDocSiteConfig.get_bonus_sport_class_name(),
}
)
if request.method == "POST" and form.cancel.data: # cancel button
return redirect(url_for("scodoc.index"))
if form.validate_on_submit():
if (
form.data["bonus_sport_func_name"]
!= ScoDocSiteConfig.get_bonus_sport_class_name()
):
ScoDocSiteConfig.set_bonus_sport_class(form.data["bonus_sport_func_name"])
app.clear_scodoc_cache()
flash(f"Fonction bonus sport&culture configurée.")
return redirect(url_for("scodoc.index"))
return render_template(
"configuration.html",
form=form,
)

View File

@ -152,28 +152,3 @@ class LogoInsert(Action):
name=self.parameters["name"], name=self.parameters["name"],
dept_id=dept_id, dept_id=dept_id,
) )
class BonusSportUpdate(Action):
"""Action: Change bonus_sport_function_name.
bonus_sport_function_name: the new value"""
def __init__(self, parameters):
super().__init__(
f"Changement du calcul de bonus sport pour ({parameters['bonus_sport_func_name']}).",
parameters,
)
@staticmethod
def build_action(parameters):
if (
parameters["bonus_sport_func_name"]
!= ScoDocSiteConfig.get_bonus_sport_class_name()
):
return [BonusSportUpdate(parameters)]
return []
def execute(self):
current_app.logger.info(self.message)
ScoDocSiteConfig.set_bonus_sport_func(self.parameters["bonus_sport_func_name"])
app.clear_scodoc_cache()

View File

@ -2019,7 +2019,7 @@ class BasePreferences(object):
H = [ H = [
html_sco_header.sco_header(page_title="Préférences"), html_sco_header.sco_header(page_title="Préférences"),
"<h2>Préférences globales pour %s</h2>" % scu.ScoURL(), "<h2>Préférences globales pour %s</h2>" % scu.ScoURL(),
# f"""<p><a href="{url_for("scolar.config_logos", scodoc_dept=g.scodoc_dept) # f"""<p><a href="{url_for("scodoc.configure_logos", scodoc_dept=g.scodoc_dept)
# }">modification des logos du département (pour documents pdf)</a></p>""" # }">modification des logos du département (pour documents pdf)</a></p>"""
# if current_user.is_administrator() # if current_user.is_administrator()
# else "", # else "",

View File

@ -1,5 +1,5 @@
function submit_form() { function submit_form() {
$("#configuration_form").submit(); $("#config_logos_form").submit();
} }
$(function () { $(function () {

View File

@ -0,0 +1,125 @@
{# -*- mode: jinja-html -*- #}
{% extends 'base.html' %}
{% import 'bootstrap/wtf.html' as wtf %}
{% macro render_field(field, with_label=True) %}
<div>
{% if with_label %}
<span class="wtf-field">{{ field.label }} :</span>
{% endif %}
<span class="wtf-field">{{ field(**kwargs)|safe }}
{% if field.errors %}
<ul class=errors>
{% for error in field.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
</span>
</div>
{% endmacro %}
{% macro render_add_logo(add_logo_form) %}
<div class="logo-add">
<h3>Ajouter un logo</h3>
{{ add_logo_form.hidden_tag() }}
{{ render_field(add_logo_form.name) }}
{{ render_field(add_logo_form.upload) }}
{{ render_field(add_logo_form.do_insert, False, onSubmit="submit_form") }}
</div>
{% endmacro %}
{% macro render_logo(dept_form, logo_form) %}
<div class="logo-edit">
{{ logo_form.hidden_tag() }}
{% if logo_form.titre %}
<tr class="logo-edit">
<td colspan="3" class="titre">
<div class="nom">
<h3>{{ logo_form.titre }}</h3>
</div>
<div class="description">{{ logo_form.description or "" }}</div>
</td>
</tr>
{% else %}
<tr class="logo-edit">
<td colspan="3" class="titre">
<span class="nom">
<h3>Logo personalisé: {{ logo_form.logo_id.data }}</h3>
</span>
<span class="description">{{ logo_form.description or "" }}</span>
</td>
</tr>
{% endif %}
<tr>
<td style="padding-right: 20px; ">
<div class="img-container">
<img src="{{ logo_form.logo.get_url_small() }}" alt="pas de logo chargé" />
</div>
</td>
<td class="img-data">
<h3>{{ logo_form.logo.logoname }} (Format: {{ logo_form.logo.suffix }})</h3>
Taille: {{ logo_form.logo.size }} px
{% if logo_form.logo.mm %} &nbsp; / &nbsp; {{ logo_form.logo.mm }} mm {% endif %}<br />
Aspect ratio: {{ logo_form.logo.aspect_ratio }}<br />
Usage: <span style="font-family: system-ui">{{ logo_form.logo.get_usage() }}</span>
</td>
<td class="" img-action">
<p>Modifier l'image</p>
<span class="wtf-field">{{ render_field(logo_form.upload, False, onchange="submit_form()") }}</span>
{% if logo_form.can_delete %}
<p>Supprimer l'image</p>
{{ render_field(logo_form.do_delete, False, onSubmit="submit_form()") }}
{% endif %}
</td>
</tr>
</div>
{% endmacro %}
{% macro render_logos(dept_form) %}
<table>
{% for logo_entry in dept_form.logos.entries %}
{% set logo_form = logo_entry.form %}
{{ render_logo(dept_form, logo_form) }}
{% else %}
<p class="logo-edit">
<h3>Aucun logo défini en propre à ce département</h3>
</p>
{% endfor %}
</table>
{% endmacro %}
{% block app_content %}
<script src="/ScoDoc/static/jQuery/jquery.js"></script>
<script src="/ScoDoc/static/js/config_logos.js"></script>
<form id="config_logos_form" class="sco-form" action="" method="post" enctype="multipart/form-data" novalidate>
{{ form.hidden_tag() }}
<div class="configuration_logo">
<h1>Bibliothèque de logos</h1>
{% for dept_entry in form.depts.entries %}
{% set dept_form = dept_entry.form %}
{{ dept_entry.form.hidden_tag() }}
{% if dept_entry.form.is_local() %}
<div class="departement">
<h2>Département {{ dept_form.dept_name.data }}</h2>
<h3>Logos locaux</h3>
<div class="sco_help">Les paramètres donnés sont spécifiques à ce département.<br />
Les logos du département se substituent aux logos de même nom définis globalement:</div>
</div>
{% else %}
<div class="departement">
<h2>Logos généraux</h2>
<div class="sco_help">Les images de cette section sont utilisé pour tous les départements,
mais peuvent être redéfinies localement au niveau de chaque département
(il suffit de définir un logo local de même nom)</div>
</div>
{% endif %}
{{ render_logos(dept_form) }}
{{ render_add_logo(dept_form.add_logo.form) }}
{% endfor %}
</div>
</form>
{% endblock %}

View File

@ -19,104 +19,46 @@
</div> </div>
{% endmacro %} {% endmacro %}
{% macro render_add_logo(add_logo_form) %}
<div class="logo-add">
<h3>Ajouter un logo</h3>
{{ add_logo_form.hidden_tag() }}
{{ render_field(add_logo_form.name) }}
{{ render_field(add_logo_form.upload) }}
{{ render_field(add_logo_form.do_insert, False, onSubmit="submit_form") }}
</div>
{% endmacro %}
{% macro render_logo(dept_form, logo_form) %}
<div class="logo-edit">
{{ logo_form.hidden_tag() }}
{% if logo_form.titre %}
<tr class="logo-edit">
<td colspan="3" class="titre">
<div class="nom"><h3>{{ logo_form.titre }}</h3></div>
<div class="description">{{ logo_form.description or "" }}</div>
</td>
</tr>
{% else %}
<tr class="logo-edit">
<td colspan="3" class="titre">
<span class="nom"><h3>Logo personalisé: {{ logo_form.logo_id.data }}</h3></span>
<span class="description">{{ logo_form.description or "" }}</span>
</td>
</tr>
{% endif %}
<tr>
<td style="padding-right: 20px; ">
<div class="img-container">
<img src="{{ logo_form.logo.get_url_small() }}" alt="pas de logo chargé" /></div>
</td><td class="img-data">
<h3>{{ logo_form.logo.logoname }} (Format: {{ logo_form.logo.suffix }})</h3>
Taille: {{ logo_form.logo.size }} px
{% if logo_form.logo.mm %} &nbsp; / &nbsp; {{ logo_form.logo.mm }} mm {% endif %}<br/>
Aspect ratio: {{ logo_form.logo.aspect_ratio }}<br/>
Usage: <span style="font-family: system-ui">{{ logo_form.logo.get_usage() }}</span>
</td><td class=""img-action">
<p>Modifier l'image</p>
<span class="wtf-field">{{ render_field(logo_form.upload, False, onchange="submit_form()") }}</span>
{% if logo_form.can_delete %}
<p>Supprimer l'image</p>
{{ render_field(logo_form.do_delete, False, onSubmit="submit_form()") }}
{% endif %}
</td>
</tr>
</div>
{% endmacro %}
{% macro render_logos(dept_form) %}
<table>
{% for logo_entry in dept_form.logos.entries %}
{% set logo_form = logo_entry.form %}
{{ render_logo(dept_form, logo_form) }}
{% else %}
<p class="logo-edit"><h3>Aucun logo défini en propre à ce département</h3></p>
{% endfor %}
</table>
{% endmacro %}
{% block app_content %} {% block app_content %}
<script src="/ScoDoc/static/jQuery/jquery.js"></script>
<script src="/ScoDoc/static/js/configuration.js"></script>
<form id="configuration_form" class="sco-form" action="" method="post" enctype="multipart/form-data" novalidate> <form id="configuration_form" class="sco-form" action="" method="post" enctype="multipart/form-data" novalidate>
{{ form.hidden_tag() }} {{ form.hidden_tag() }}
<div class="configuration_logo"> <h1>Configuration générale</h1>
<h1>Configuration générale</h1> <div class="sco_help">Les paramètres donnés ici s'appliquent à tout ScoDoc (tous les départements):</div>
<div class="sco_help">Les paramètres donnés ici s'appliquent à tout ScoDoc (tous les départements):</div> <div class="row">
{{ render_field(form.bonus_sport_func_name, onChange="submit_form()")}} <div class="col-md-4">
{{ wtf.quick_form(form) }}
</div>
<div class="help" id="bonus_description"></div>
</div>
<h1>Gestion des images: logos, signatures, ...</h1>
<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 href="{{url_for('scodoc.configure_logos')}}">configuration des images et logos</a>
</p>
<h1>Exports Apogée</h1>
<p><a href="{{url_for('scodoc.config_codes_decisions')}}">configuration des codes de décision</a></p>
<h1>Exports Apogée</h1>
<p><a href="{{url_for('scodoc.config_codes_decisions')}}">configuration des codes de décision</a></p>
<h1>Bibliothèque de logos</h1>
{% for dept_entry in form.depts.entries %}
{% set dept_form = dept_entry.form %}
{{ dept_entry.form.hidden_tag() }}
{% if dept_entry.form.is_local() %}
<div class="departement">
<h2>Département {{ dept_form.dept_name.data }}</h2>
<h3>Logos locaux</h3>
<div class="sco_help">Les paramètres donnés sont spécifiques à ce département.<br/>
Les logos du département se substituent aux logos de même nom définis globalement:</div>
</div>
{% else %}
<div class="departement">
<h2>Logos généraux</h2>
<div class="sco_help">Les images de cette section sont utilisé pour tous les départements,
mais peuvent être redéfinies localement au niveau de chaque département
(il suffit de définir un logo local de même nom)</div>
</div>
{% endif %}
{{ render_logos(dept_form) }}
{{ render_add_logo(dept_form.add_logo.form) }}
{% endfor %}
</div> </div>
</form> </form>
{% endblock %}
{% block scripts %}
{{ super() }}
<script>
$(function()
{
$("#configuration_form select").change(function(){
var query = "/ScoDoc/get_bonus_description/" + $("#configuration_form select")[0].value;
$.get(query, '', function (data) {
$("#bonus_description").html(data);
});
});
});
</script>
{% endblock %} {% endblock %}

View File

@ -45,7 +45,7 @@ from werkzeug.exceptions import BadRequest, NotFound
from app import db from app import db
from app.auth.models import User from app.auth.models import User
from app.forms.main import config_forms from app.forms.main import config_logos, config_main
from app.forms.main.create_dept import CreateDeptForm from app.forms.main.create_dept import CreateDeptForm
from app.forms.main.config_apo import CodesDecisionsForm from app.forms.main.config_apo import CodesDecisionsForm
from app import models from app import models
@ -250,10 +250,26 @@ def about(scodoc_dept=None):
@bp.route("/ScoDoc/configuration", methods=["GET", "POST"]) @bp.route("/ScoDoc/configuration", methods=["GET", "POST"])
@admin_required @admin_required
def configuration(): def configuration():
auth_name = str(current_user) "Page de configuration globale"
if not current_user.is_administrator(): if not current_user.is_administrator():
raise AccessDenied("invalid user (%s) must be SuperAdmin" % auth_name) raise AccessDenied("invalid user (%s) must be SuperAdmin" % current_user)
return config_forms.configuration() return config_main.configuration()
@bp.route("/ScoDoc/get_bonus_description/<bonus_name>", methods=["GET"])
def get_bonus_description(bonus_name: str):
"description text/html du bonus"
bonus_class = ScoDocSiteConfig.get_bonus_sport_class_from_name(bonus_name)
return bonus_class.__doc__
@bp.route("/ScoDoc/configure_logos", methods=["GET", "POST"])
@admin_required
def configure_logos():
"Page de configuration des logos (globale)"
if not current_user.is_administrator():
raise AccessDenied("invalid user (%s) must be SuperAdmin" % current_user)
return config_logos.config_logos()
SMALL_SIZE = (200, 200) SMALL_SIZE = (200, 200)

View File

@ -21,7 +21,6 @@ from app import clear_scodoc_cache
from app import models from app import models
from app.auth.models import User, Role, UserRole from app.auth.models import User, Role, UserRole
from app.models import ScoPreference
from app.scodoc.sco_logos import make_logo_local from app.scodoc.sco_logos import make_logo_local
from app.models import Formation, UniteEns, Module from app.models import Formation, UniteEns, Module
from app.models import FormSemestre, FormSemestreInscription from app.models import FormSemestre, FormSemestreInscription