diff --git a/app/scodoc/sco_logos.py b/app/scodoc/sco_logos.py index d2814fe6f..5808945f0 100644 --- a/app/scodoc/sco_logos.py +++ b/app/scodoc/sco_logos.py @@ -160,7 +160,7 @@ class Logo: "Not inited: call the select or create function before access" ) self.density = "Not inited: call the select or create function before access" - self.cm = "Not inited: call the select or create function before access" + self.mm = "Not inited: call the select or create function before access" def _set_format(self, fmt): self.suffix = fmt @@ -199,21 +199,21 @@ class Logo: unit = 1 if self.density is None: # no dpi found try jfif infos self.density = img.info.get("jfif_density", None) - unit = img.info.get("jfif_unit", 0) # 0 = no unit ; 1 = inch ; 2 = cm + unit = img.info.get("jfif_unit", 0) # 0 = no unit ; 1 = inch ; 2 = mm if self.density is not None: x_density, y_density = self.density if unit != 0: - unit2cm = [0, 1 / 2.54, 1][unit] - x_cm = round(x_size * unit2cm / x_density, 2) - y_cm = round(y_size * unit2cm / y_density, 2) - self.cm = (x_cm, y_cm) + unit2mm = [0, 1 / 0.254, 0.1][unit] + x_mm = round(x_size * unit2mm / x_density, 2) + y_mm = round(y_size * unit2mm / y_density, 2) + self.mm = (x_mm, y_mm) else: - self.cm = None + self.mm = None else: - self.cm = None + self.mm = None self.size = (x_size, y_size) - self.aspect_ratio = float(x_size) / y_size + self.aspect_ratio = round(float(x_size) / y_size, 2) def select(self): """ @@ -250,6 +250,12 @@ class Logo: global_if_not_found=False, ) + def get_usage(self): + if self.mm is None: + return f'' + else: + return f'' + def guess_image_type(stream) -> str: "guess image type from header in stream" diff --git a/app/templates/configuration.html b/app/templates/configuration.html index 88f1fd814..077c094db 100644 --- a/app/templates/configuration.html +++ b/app/templates/configuration.html @@ -16,38 +16,66 @@ {% endmacro %} +{% macro render_logo(logo_form, titre=None) %} + {% if titre %} + + +

{{ titre }}

+ + + {% endif %} + + +

{{ logo_form.form.description }} Image actuelle:

+
pas de logo chargé
+ + + Nom: {{ logo_form.form.logo.logoname }}
+ {{ logo_form.form.description }}
+ Format: {{ logo_form.logo.suffix }}
+ Taille en px: {{ logo_form.logo.size }}
+ {% if logo_form.logo.mm %} + Taile en mm: {{ logo_form.logo.mm }}
+ {% endif %} + Aspect ratio: {{ logo_form.logo.aspect_ratio }}
+ Usage: {{ logo_form.logo.get_usage() }} + {{ logo_form.action()|safe }} + {{ render_field(logo_form.upload) }} + {% if logo_form.can_delete %} + {{ render_field(logo_form.do_delete) }} + {% endif %} + + +{% endmacro %} + + {% block app_content %} {% if scodoc_dept %}

Logos du département {{ scodoc_dept }}

{% else %} -

Configuration générale {{ scodoc_dept }}

+

Configuration générale

{% endif %}
{{ form.hidden_tag() }} - {% if not scodoc_dept %}
Les paramètres donnés ici s'appliquent à tout ScoDoc (tous les départements):
- - {{ render_field(form.bonus_sport_func_name)}} + {{ render_field(form.bonus_sport_func_name)}} + {% endif %} - +
{{ form.submit() }}
{% endblock %} \ No newline at end of file diff --git a/app/views/scodoc.py b/app/views/scodoc.py index 0def371c2..704330250 100644 --- a/app/views/scodoc.py +++ b/app/views/scodoc.py @@ -32,6 +32,8 @@ Emmanuel Viennet, 2021 """ import io +import wtforms.validators + from app.auth.models import User import os @@ -44,9 +46,9 @@ from flask_login.utils import login_required, current_user from flask_wtf import FlaskForm from flask_wtf.file import FileField, FileAllowed from werkzeug.exceptions import BadRequest, NotFound -from wtforms import SelectField, SubmitField +from wtforms import SelectField, SubmitField, FormField, validators, Form from wtforms.fields import IntegerField -from wtforms.fields.simple import BooleanField, StringField, TextAreaField +from wtforms.fields.simple import BooleanField, StringField, TextAreaField, HiddenField from wtforms.validators import ValidationError, DataRequired, Email, EqualTo import app @@ -64,6 +66,7 @@ from app.decorators import ( permission_required_compat_scodoc7, ) from app.scodoc.sco_exceptions import AccessDenied +from app.scodoc.sco_logos import find_logo from app.scodoc.sco_permissions import Permission from app.views import scodoc_bp as bp @@ -178,6 +181,34 @@ def about(scodoc_dept=None): # ---- CONFIGURATION +class LogoForm(FlaskForm): + action = HiddenField("action") + upload = FileField( + label="Modifier l'image:", + validators=[ + FileAllowed( + scu.LOGOS_IMAGES_ALLOWED_TYPES, + f"n'accepte que les fichiers image {','.join([e for e in scu.LOGOS_IMAGES_ALLOWED_TYPES])}", + ) + ], + ) + do_delete = SubmitField("Supprimer") + + def set_infos(self, logo, description=None, can_delete=None): + self.logo = logo + self.description = description + self.can_delete = can_delete + + def breakpoint(self, form): + breakpoint() + + def __init__(self, *args, **kwargs): + super(LogoForm, self).__init__(*args, **kwargs) + self.logo = None + self.description = None + self.can_delete = None + + class ScoDocConfigurationForm(FlaskForm): "Panneau de configuration général" @@ -188,31 +219,24 @@ class ScoDocConfigurationForm(FlaskForm): for x in ScoDocSiteConfig.get_bonus_sport_func_names() ], ) - - logo_header = FileField( - label="Modifier l'image:", - description="logo placé en haut des documents PDF", - validators=[ - FileAllowed( - scu.LOGOS_IMAGES_ALLOWED_TYPES, - f"n'accepte que les fichiers image {','.join([e for e in scu.LOGOS_IMAGES_ALLOWED_TYPES])}", - ) - ], - ) - - logo_footer = FileField( - label="Modifier l'image:", - description="logo placé en pied des documents PDF", - validators=[ - FileAllowed( - scu.LOGOS_IMAGES_ALLOWED_TYPES, - f"n'accepte que les fichiers image {','.join([e for e in scu.LOGOS_IMAGES_ALLOWED_TYPES])}", - ) - ], - ) - + header = FormField(LogoForm) + footer = FormField(LogoForm) submit = SubmitField("Enregistrer") + def __init__(self, *args, **kwargs): + super(ScoDocConfigurationForm, self).__init__(*args, **kwargs) + breakpoint() + self.header.form.set_infos( + logo=find_logo("header", dept_id=None).select(), + description="image placée en haut de certains documents documents PDF.", + can_delete=False, + ) + self.footer.form.set_infos( + logo=find_logo("footer", dept_id=None).select(), + description="image placée en pied de page de certains documents documents PDF.", + can_delete=False, + ) + # Notes pour variables config: (valeurs par défaut des paramètres de département) # Chaines simples @@ -241,10 +265,10 @@ def configuration(): ) if form.validate_on_submit(): ScoDocSiteConfig.set_bonus_sport_func(form.bonus_sport_func_name.data) - if form.logo_header.data: - sco_logos.write_logo(stream=form.logo_header.data, name="header") - if form.logo_footer.data: - sco_logos.write_logo(stream=form.logo_footer.data, name="footer") + if form.header.data: + sco_logos.write_logo(stream=form.header.data, name="header") + if form.footer.data: + sco_logos.write_logo(stream=form.footer.data, name="footer") app.clear_scodoc_cache() flash(f"Configuration enregistrée") return redirect(url_for("scodoc.index")) @@ -313,20 +337,6 @@ def get_logo(name: str, dept_id: int): ) -# @bp.route("/ScoDoc/logo_header") -# @bp.route("/ScoDoc//logo_header") -# def logo_header(scodoc_dept=""): -# "Image logo header" -# return _return_logo(name="header", scodoc_dept=scodoc_dept) - - -# @bp.route("/ScoDoc/logo_footer") -# @bp.route("/ScoDoc//logo_footer") -# def logo_footer(scodoc_dept=""): -# "Image logo footer" -# return _return_logo(name="footer", scodoc_dept=scodoc_dept) - - # essais # @bp.route("/testlog") # def testlog(): diff --git a/app/views/scolar.py b/app/views/scolar.py index d284b04e1..c708495aa 100644 --- a/app/views/scolar.py +++ b/app/views/scolar.py @@ -39,7 +39,7 @@ from flask import current_app, g, request from flask_login import current_user from flask_wtf import FlaskForm from flask_wtf.file import FileField, FileAllowed -from wtforms import SubmitField, FormField +from wtforms import SubmitField from app.decorators import ( scodoc, @@ -49,7 +49,6 @@ from app.decorators import ( admin_required, login_required, ) -from app.scodoc.sco_logos import find_logo from app.views import scolar_bp as bp @@ -166,6 +165,66 @@ def doc_preferences(): return response +class DeptLogosConfigurationForm(FlaskForm): + "Panneau de configuration logos dept" + + logo_header = FileField( + label="Modifier l'image:", + description="logo placé en haut des documents PDF", + validators=[ + FileAllowed( + scu.LOGOS_IMAGES_ALLOWED_TYPES, + f"n'accepte que les fichiers image {','.join([e for e in scu.LOGOS_IMAGES_ALLOWED_TYPES])}", + ) + ], + ) + + logo_footer = FileField( + label="Modifier l'image:", + description="logo placé en pied des documents PDF", + validators=[ + FileAllowed( + scu.LOGOS_IMAGES_ALLOWED_TYPES, + f"n'accepte que les fichiers image {','.join([e for e in scu.LOGOS_IMAGES_ALLOWED_TYPES])}", + ) + ], + ) + + submit = SubmitField("Enregistrer") + + +@bp.route("/config_logos", methods=["GET", "POST"]) +@permission_required(Permission.ScoChangePreferences) +def config_logos(scodoc_dept): + "Panneau de configuration général" + form = DeptLogosConfigurationForm() + if form.validate_on_submit(): + if form.logo_header.data: + sco_logos.store_image( + form.logo_header.data, + os.path.join( + scu.SCODOC_LOGOS_DIR, "logos_" + scodoc_dept, "logo_header" + ), + ) + if form.logo_footer.data: + sco_logos.store_image( + form.logo_footer.data, + os.path.join( + scu.SCODOC_LOGOS_DIR, "logos_" + scodoc_dept, "logo_footer" + ), + ) + app.clear_scodoc_cache() + flash(f"Logos enregistrés") + return flask.redirect(url_for("scolar.index_html", scodoc_dept=scodoc_dept)) + + return render_template( + "configuration.html", + title="Configuration Logos du département", + form=form, + scodoc_dept=scodoc_dept, + ) + + # -------------------------------------------------------------------- # # ETUDIANTS diff --git a/tests/ressources/test_logos/logo_D.png b/tests/ressources/test_logos/logo_D.png index 7ac56e168..8239e535c 100644 Binary files a/tests/ressources/test_logos/logo_D.png and b/tests/ressources/test_logos/logo_D.png differ diff --git a/tests/unit/test_logos.py b/tests/unit/test_logos.py index 8cf2e275b..1ed62a493 100644 --- a/tests/unit/test_logos.py +++ b/tests/unit/test_logos.py @@ -124,7 +124,7 @@ def test_get_jpg_data(create_dept, create_logos): assert logo.suffix == "jpg" assert logo.filename == "A.jpg" assert logo.size == (1200, 600) - assert logo.cm == approx((4.0, 3.0), 0.01) + assert logo.mm == approx((40, 30), 0.1) def test_get_png_without_data(create_dept, create_logos): @@ -136,7 +136,7 @@ def test_get_png_without_data(create_dept, create_logos): assert logo.filename == "D.png" assert logo.size == (121, 121) assert logo.density is None - assert logo.cm is None + assert logo.mm is None def test_create_globale_jpg_logo(create_dept, create_logos):