build logo form (header & footer)

This commit is contained in:
Jean-Marie Place 2021-11-16 18:48:56 +01:00
parent d8091b4efb
commit 483c22678a
6 changed files with 175 additions and 72 deletions

View File

@ -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'<logo name="{self.logoname}" width="?? mm" height="?? mm">'
else:
return f'<logo name="{self.logoname}" width="{self.mm[0]}mm" height="{self.mm[1]}mm">'
def guess_image_type(stream) -> str:
"guess image type from header in stream"

View File

@ -16,38 +16,66 @@
</div>
{% endmacro %}
{% macro render_logo(logo_form, titre=None) %}
{% if titre %}
<tr>
<td colspan="2">
<h3>{{ titre }}</h3>
</td>
</tr>
{% endif %}
<tr>
<td style="padding-right: 20px">
<p class="help">{{ logo_form.form.description }} Image actuelle:</p>
<div class="img-container"><img src="{{ logo_form.logo.get_url_small() }}"
alt="pas de logo chargé" /></div>
</td>
<td>
Nom: {{ logo_form.form.logo.logoname }}<br/>
{{ logo_form.form.description }}<br/>
Format: {{ logo_form.logo.suffix }}<br/>
Taille en px: {{ logo_form.logo.size }}<br/>
{% if logo_form.logo.mm %}
Taile en mm: {{ logo_form.logo.mm }}<br/>
{% endif %}
Aspect ratio: {{ logo_form.logo.aspect_ratio }}<br/>
Usage: {{ logo_form.logo.get_usage() }}
<span class="wtf-field">{{ logo_form.action()|safe }}</span>
<span class="wtf-field">{{ render_field(logo_form.upload) }}</span>
{% if logo_form.can_delete %}
{{ render_field(logo_form.do_delete) }}
{% endif %}
</td>
</tr>
{% endmacro %}
{% block app_content %}
{% if scodoc_dept %}
<h1>Logos du département {{ scodoc_dept }}</h1>
{% else %}
<h1>Configuration générale {{ scodoc_dept }}</h1>
<h1>Configuration générale</h1>
{% endif %}
<form class="sco-form" action="" method="post" enctype="multipart/form-data" novalidate>
{{ form.hidden_tag() }}
{% if not scodoc_dept %}
<div class="sco_help">Les paramètres donnés ici s'appliquent à tout ScoDoc (tous les départements):</div>
{{ render_field(form.bonus_sport_func_name)}}
{{ render_field(form.bonus_sport_func_name)}}
<div class="configuration_logo">
<table>
{{ form.footer.form.breakpoint(form) }}
{{ render_logo(form.header, 'Logo en-tête') }}
{{ render_logo(form.footer, 'Logo pied de page') }}
</table>
</div>
{% endif %}
<div class="configuration_logo">
<h3>Logo en-tête</h3>
<p class="help">image placée en haut de certains documents documents PDF. Image actuelle:</p>
<div class="img-container"><img src="{{ url_for('scodoc.get_logo_small', name="header") }}"
alt="pas de logo chargé" /></div>
{{ render_field(form.logo_header) }}
<h3>Logo pied de page</h3>
<p class="help">image placée en pied de page de certains documents documents PDF. Image actuelle:</p>
<div class="img-container"><img src="{{ url_for('scodoc.get_logo_small', name="footer") }}"
alt="pas de logo chargé" /></div>
{{ render_field(form.logo_footer) }}
</div>
<!-- <div class="sco_help">Les paramètres ci-dessous peuvent être changés dans chaque département
(paramétrage).<br />On indique ici les valeurs initiales par défaut:
</div> -->
<div class="sco-submit">{{ form.submit() }}</div>
</form>
{% endblock %}

View File

@ -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 <tt>{','.join([e for e in scu.LOGOS_IMAGES_ALLOWED_TYPES])}</tt>",
)
],
)
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 <tt>{','.join([e for e in scu.LOGOS_IMAGES_ALLOWED_TYPES])}</tt>",
)
],
)
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/<scodoc_dept>/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/<scodoc_dept>/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():

View File

@ -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 <tt>{','.join([e for e in scu.LOGOS_IMAGES_ALLOWED_TYPES])}</tt>",
)
],
)
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 <tt>{','.join([e for e in scu.LOGOS_IMAGES_ALLOWED_TYPES])}</tt>",
)
],
)
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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -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):