avant tests
This commit is contained in:
parent
0d0ba5ae60
commit
3576847fb8
|
@ -202,7 +202,7 @@ def add_pe_stuff_to_zip(zipfile, ziproot):
|
||||||
add_local_file_to_zip(zipfile, ziproot, pathname, "avis/" + filename)
|
add_local_file_to_zip(zipfile, ziproot, pathname, "avis/" + filename)
|
||||||
|
|
||||||
# Logos: (add to logos/ directory in zip)
|
# Logos: (add to logos/ directory in zip)
|
||||||
logos_names = ["logo_header.jpg", "logo_footer.jpg"]
|
logos_names = ["header", "footer"]
|
||||||
for name in logos_names:
|
for name in logos_names:
|
||||||
logo = find_logo(logoname=name, dept_id=g.scodoc_dept_id)
|
logo = find_logo(logoname=name, dept_id=g.scodoc_dept_id)
|
||||||
if logo is not None:
|
if logo is not None:
|
||||||
|
|
|
@ -142,7 +142,6 @@ def process_field(field, cdict, style, suppress_empty_pars=False, format="pdf"):
|
||||||
return text
|
return text
|
||||||
# --- PDF format:
|
# --- PDF format:
|
||||||
# handle logos:
|
# handle logos:
|
||||||
breakpoint()
|
|
||||||
# la protection contre des noms malveillants est assuré par l'utilisation de secure_filename dans la classe Logo
|
# la protection contre des noms malveillants est assuré par l'utilisation de secure_filename dans la classe Logo
|
||||||
text = re.sub(
|
text = re.sub(
|
||||||
r"<(\s*)logo(.*?)src\s*=\s*(.*?)>", r"<\1logo\2\3>", text
|
r"<(\s*)logo(.*?)src\s*=\s*(.*?)>", r"<\1logo\2\3>", text
|
||||||
|
|
|
@ -48,44 +48,27 @@ from PIL import Image as PILImage
|
||||||
GLOBAL = "_SERVER" # category for server level logos
|
GLOBAL = "_SERVER" # category for server level logos
|
||||||
|
|
||||||
|
|
||||||
def find_logo(
|
def find_logo(logoname, dept_id=None, strict=False, prefix=scu.LOGO_FILE_PREFIX):
|
||||||
logoname, dept_id=None, global_if_not_found=True, prefix=scu.LOGO_FILE_PREFIX
|
|
||||||
):
|
|
||||||
"""
|
"""
|
||||||
"Recherche un logo 'name' existant.
|
"Recherche un logo 'name' existant.
|
||||||
Deux strategies:
|
Deux strategies:
|
||||||
si global_if_not_found:
|
si strict:
|
||||||
On recherche en local au dept d'abord puis si pas trouvé recherche globale
|
|
||||||
sinon
|
|
||||||
reherche uniquement dans le département puis si non trouvé au niveau global
|
reherche uniquement dans le département puis si non trouvé au niveau global
|
||||||
|
sinon
|
||||||
|
On recherche en local au dept d'abord puis si pas trouvé recherche globale
|
||||||
quelquesoit la stratégie, retourne None si pas trouvé
|
quelquesoit la stratégie, retourne None si pas trouvé
|
||||||
:param logoname: le nom recherche
|
:param logoname: le nom recherche
|
||||||
:param dept_id: l'id du département dans lequel se fait la recherche (None si global)
|
:param dept_id: l'id du département dans lequel se fait la recherche (None si global)
|
||||||
:param global_if_not_found: stratégie de recherche
|
:param strict: stratégie de recherche (strict = False => dept ou global)
|
||||||
:param prefix: le prefix utilisé (parmi scu.LOGO_FILE_PREFIX / scu.BACKGROUND_FILE_PREFIX)
|
:param prefix: le prefix utilisé (parmi scu.LOGO_FILE_PREFIX / scu.BACKGROUND_FILE_PREFIX)
|
||||||
:return: un objet Logo désignant le fichier image trouvé (ou None)
|
:return: un objet Logo désignant le fichier image trouvé (ou None)
|
||||||
"""
|
"""
|
||||||
try:
|
logo = Logo(logoname, dept_id, prefix).select()
|
||||||
logo = Logo(logoname, dept_id, prefix).read()
|
if logo is None and not strict:
|
||||||
except ScoValueError:
|
logo = Logo(logoname=logoname, dept_id=None, prefix=prefix).select()
|
||||||
logo = None
|
|
||||||
if logo is None and global_if_not_found:
|
|
||||||
try:
|
|
||||||
logo = Logo(logoname=logoname, dept_id=None), prefix.read()
|
|
||||||
except ScoValueError:
|
|
||||||
logo = None
|
|
||||||
return logo
|
return logo
|
||||||
|
|
||||||
|
|
||||||
def get_logo_filename(name, dept_id=None):
|
|
||||||
breakpoint()
|
|
||||||
return find_logo(name, dept_id).read().filepath
|
|
||||||
|
|
||||||
|
|
||||||
def get_logo_url(name, dept_id):
|
|
||||||
return find_logo(name, dept_id).read().get_url()
|
|
||||||
|
|
||||||
|
|
||||||
def write_logo(stream, name, dept_id=None):
|
def write_logo(stream, name, dept_id=None):
|
||||||
Logo(logoname=name, dept_id=dept_id).create(stream)
|
Logo(logoname=name, dept_id=dept_id).create(stream)
|
||||||
|
|
||||||
|
@ -117,7 +100,7 @@ def _list_dept_logos(dept_id=None, prefix=scu.LOGO_FILE_PREFIX):
|
||||||
result = filename_parser.match(entry.name)
|
result = filename_parser.match(entry.name)
|
||||||
if result:
|
if result:
|
||||||
logoname = result.group(1)
|
logoname = result.group(1)
|
||||||
logos[logoname] = Logo(logoname=logoname, dept_id=dept_id).read()
|
logos[logoname] = Logo(logoname=logoname, dept_id=dept_id).select()
|
||||||
return logos if len(logos.keys()) > 0 else None
|
return logos if len(logos.keys()) > 0 else None
|
||||||
|
|
||||||
|
|
||||||
|
@ -156,7 +139,7 @@ class Logo:
|
||||||
self.filepath = None
|
self.filepath = None
|
||||||
self.filename = None
|
self.filename = None
|
||||||
|
|
||||||
def set_format(self, fmt):
|
def _set_format(self, fmt):
|
||||||
self.suffix = fmt
|
self.suffix = fmt
|
||||||
self.filepath = self.basepath + "." + fmt
|
self.filepath = self.basepath + "." + fmt
|
||||||
self.filename = self.logoname + "." + fmt
|
self.filename = self.logoname + "." + fmt
|
||||||
|
@ -171,7 +154,7 @@ class Logo:
|
||||||
img_type = guess_image_type(stream)
|
img_type = guess_image_type(stream)
|
||||||
if img_type not in scu.LOGOS_IMAGES_ALLOWED_TYPES:
|
if img_type not in scu.LOGOS_IMAGES_ALLOWED_TYPES:
|
||||||
abort(400, "type d'image invalide")
|
abort(400, "type d'image invalide")
|
||||||
self.set_format(img_type)
|
self._set_format(img_type)
|
||||||
self._ensure_directory_exists()
|
self._ensure_directory_exists()
|
||||||
filename = self.basepath + "." + self.suffix
|
filename = self.basepath + "." + self.suffix
|
||||||
with open(filename, "wb") as f:
|
with open(filename, "wb") as f:
|
||||||
|
@ -184,7 +167,7 @@ class Logo:
|
||||||
except IOError:
|
except IOError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def read(self):
|
def select(self):
|
||||||
"""
|
"""
|
||||||
Récupération des données pour un logo existant (sinon -> Exception)
|
Récupération des données pour un logo existant (sinon -> Exception)
|
||||||
il doit exister un et un seul fichier image parmi les types autorisés
|
il doit exister un et un seul fichier image parmi les types autorisés
|
||||||
|
@ -194,19 +177,27 @@ class Logo:
|
||||||
for suffix in scu.LOGOS_IMAGES_ALLOWED_TYPES:
|
for suffix in scu.LOGOS_IMAGES_ALLOWED_TYPES:
|
||||||
path = Path(self.basepath + "." + suffix)
|
path = Path(self.basepath + "." + suffix)
|
||||||
if path.exists():
|
if path.exists():
|
||||||
self.set_format(suffix)
|
self._set_format(suffix)
|
||||||
with open(self.filepath, "rb") as f:
|
with open(self.filepath, "rb") as f:
|
||||||
img = PILImage.open(f)
|
img = PILImage.open(f)
|
||||||
self.dimensions = img.size
|
self.dimensions = img.size
|
||||||
return self
|
return self
|
||||||
# if no file found, raise exception
|
return None
|
||||||
raise ScoValueError(
|
|
||||||
"Logo %s not found for dept %s" % (self.logoname, self.scodoc_dept_id)
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_url(self):
|
def get_url(self):
|
||||||
return url_for(
|
return url_for(
|
||||||
"scodoc.logo_custom", scodoc_dept=self.scodoc_dept_id, name=self.logoname
|
"scodoc.get_logo",
|
||||||
|
scodoc_dept=self.scodoc_dept_id,
|
||||||
|
name=self.logoname,
|
||||||
|
global_if_not_found=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_url_small(self):
|
||||||
|
return url_for(
|
||||||
|
"scodoc.get_logo_small",
|
||||||
|
scodoc_dept=self.scodoc_dept_id,
|
||||||
|
name=self.logoname,
|
||||||
|
global_if_not_found=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -61,11 +61,7 @@ from flask import g
|
||||||
|
|
||||||
import app.scodoc.sco_utils as scu
|
import app.scodoc.sco_utils as scu
|
||||||
from app.scodoc.sco_logos import find_logo
|
from app.scodoc.sco_logos import find_logo
|
||||||
from app.scodoc.sco_utils import (
|
from app.scodoc.sco_utils import CONFIG
|
||||||
CONFIG,
|
|
||||||
SCODOC_LOGOS_DIR,
|
|
||||||
LOGOS_IMAGES_ALLOWED_TYPES,
|
|
||||||
)
|
|
||||||
from app import log
|
from app import log
|
||||||
from app.scodoc.sco_exceptions import ScoGenError, ScoValueError
|
from app.scodoc.sco_exceptions import ScoGenError, ScoValueError
|
||||||
import sco_version
|
import sco_version
|
||||||
|
|
|
@ -202,43 +202,36 @@ class CourrierIndividuelTemplate(PageTemplate):
|
||||||
self.logo_footer = None
|
self.logo_footer = None
|
||||||
self.logo_header = None
|
self.logo_header = None
|
||||||
# Search logos in dept specific dir, then in global scu.CONFIG dir
|
# Search logos in dept specific dir, then in global scu.CONFIG dir
|
||||||
for image_dir in (
|
if template_name == "PVJuryTemplate":
|
||||||
scu.SCODOC_LOGOS_DIR + "/logos_" + g.scodoc_dept,
|
background = find_logo(
|
||||||
scu.SCODOC_LOGOS_DIR, # global logos
|
logoname="pvjury_background",
|
||||||
):
|
dept_id=g.scodoc_dept_id,
|
||||||
for suffix in scu.LOGOS_IMAGES_ALLOWED_TYPES:
|
prefix="",
|
||||||
if template_name == "PVJuryTemplate":
|
)
|
||||||
background = find_logo(
|
else:
|
||||||
logoname="pvjury_background",
|
background = find_logo(
|
||||||
dept_id=g.scodoc_dept_id,
|
logoname="letter_background",
|
||||||
prefix="",
|
dept_id=g.scodoc_dept_id,
|
||||||
global_if_not_found=True,
|
prefix="",
|
||||||
)
|
)
|
||||||
else:
|
if not self.background_image_filename and background is not None:
|
||||||
background = find_logo(
|
self.background_image_filename = background.filepath
|
||||||
logoname="letter_background",
|
|
||||||
dept_id=g.scodoc_dept_id,
|
|
||||||
prefix="",
|
|
||||||
global_if_not_found=True,
|
|
||||||
)
|
|
||||||
if not self.background_image_filename and background is not None:
|
|
||||||
self.background_image_filename = background.filepath
|
|
||||||
|
|
||||||
footer = find_logo(logoname="footer", dept_id=g.scodoc_dept_id)
|
footer = find_logo(logoname="footer", dept_id=g.scodoc_dept_id)
|
||||||
if footer is not None:
|
if footer is not None:
|
||||||
self.logo_footer = Image(
|
self.logo_footer = Image(
|
||||||
footer.filepath,
|
footer.filepath,
|
||||||
height=LOGO_FOOTER_HEIGHT,
|
height=LOGO_FOOTER_HEIGHT,
|
||||||
width=LOGO_FOOTER_WIDTH,
|
width=LOGO_FOOTER_WIDTH,
|
||||||
)
|
)
|
||||||
|
|
||||||
header = find_logo(logoname="header", dept_id=g.scodoc_dept_id)
|
header = find_logo(logoname="header", dept_id=g.scodoc_dept_id)
|
||||||
if header is not None:
|
if header is not None:
|
||||||
self.logo_header = Image(
|
self.logo_header = Image(
|
||||||
header.filepath,
|
header.filepath,
|
||||||
height=LOGO_HEADER_HEIGHT,
|
height=LOGO_HEADER_HEIGHT,
|
||||||
width=LOGO_HEADER_WIDTH,
|
width=LOGO_HEADER_WIDTH,
|
||||||
)
|
)
|
||||||
|
|
||||||
def beforeDrawPage(self, canvas, doc):
|
def beforeDrawPage(self, canvas, doc):
|
||||||
"""Draws a logo and an contribution message on each page."""
|
"""Draws a logo and an contribution message on each page."""
|
||||||
|
|
|
@ -36,12 +36,12 @@
|
||||||
<div class="configuration_logo">
|
<div class="configuration_logo">
|
||||||
<h3>Logo en-tête</h3>
|
<h3>Logo en-tête</h3>
|
||||||
<p class="help">image placée en haut de certains documents documents PDF. Image actuelle:</p>
|
<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.logo_header', scodoc_dept=scodoc_dept) }}"
|
<div class="img-container"><img src="{{ url_for('scodoc.get_logo_global', name="header") }}"
|
||||||
alt="pas de logo chargé" /></div>
|
alt="pas de logo chargé" /></div>
|
||||||
{{ render_field(form.logo_header) }}
|
{{ render_field(form.logo_header) }}
|
||||||
<h3>Logo pied de page</h3>
|
<h3>Logo pied de page</h3>
|
||||||
<p class="help">image placée en pied de page de certains documents documents PDF. Image actuelle:</p>
|
<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.logo_footer', scodoc_dept=g.scodoc_dept) }}"
|
<div class="img-container"><img src="{{ url_for('scodoc.get_logo_global', name="footer") }}"
|
||||||
alt="pas de logo chargé" /></div>
|
alt="pas de logo chargé" /></div>
|
||||||
{{ render_field(form.logo_footer) }}
|
{{ render_field(form.logo_footer) }}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -30,6 +30,8 @@ Module main: page d'accueil, avec liste des départements
|
||||||
|
|
||||||
Emmanuel Viennet, 2021
|
Emmanuel Viennet, 2021
|
||||||
"""
|
"""
|
||||||
|
import io
|
||||||
|
|
||||||
from app.auth.models import User
|
from app.auth.models import User
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
@ -38,7 +40,7 @@ from flask import abort, flash, url_for, redirect, render_template, send_file
|
||||||
from flask import request
|
from flask import request
|
||||||
from flask.app import Flask
|
from flask.app import Flask
|
||||||
import flask_login
|
import flask_login
|
||||||
from flask_login.utils import login_required
|
from flask_login.utils import login_required, current_user
|
||||||
from flask_wtf import FlaskForm
|
from flask_wtf import FlaskForm
|
||||||
from flask_wtf.file import FileField, FileAllowed
|
from flask_wtf.file import FileField, FileAllowed
|
||||||
from werkzeug.exceptions import BadRequest, NotFound
|
from werkzeug.exceptions import BadRequest, NotFound
|
||||||
|
@ -61,10 +63,14 @@ from app.decorators import (
|
||||||
scodoc,
|
scodoc,
|
||||||
permission_required_compat_scodoc7,
|
permission_required_compat_scodoc7,
|
||||||
)
|
)
|
||||||
|
from app.scodoc.imageresize import ImageScale
|
||||||
from app.scodoc.sco_exceptions import AccessDenied
|
from app.scodoc.sco_exceptions import AccessDenied
|
||||||
|
from app.scodoc.sco_logos import Logo
|
||||||
from app.scodoc.sco_permissions import Permission
|
from app.scodoc.sco_permissions import Permission
|
||||||
from app.views import scodoc_bp as bp
|
from app.views import scodoc_bp as bp
|
||||||
|
|
||||||
|
from PIL import Image as PILImage
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/")
|
@bp.route("/")
|
||||||
@bp.route("/ScoDoc")
|
@bp.route("/ScoDoc")
|
||||||
|
@ -240,13 +246,9 @@ def configuration():
|
||||||
if form.validate_on_submit():
|
if form.validate_on_submit():
|
||||||
ScoDocSiteConfig.set_bonus_sport_func(form.bonus_sport_func_name.data)
|
ScoDocSiteConfig.set_bonus_sport_func(form.bonus_sport_func_name.data)
|
||||||
if form.logo_header.data:
|
if form.logo_header.data:
|
||||||
sco_logos.store_image(
|
sco_logos.write_logo(stream=form.logo_header.data, name="header")
|
||||||
form.logo_header.data, os.path.join(scu.SCODOC_LOGOS_DIR, "logo_header")
|
|
||||||
)
|
|
||||||
if form.logo_footer.data:
|
if form.logo_footer.data:
|
||||||
sco_logos.store_image(
|
sco_logos.write_logo(stream=form.logo_footer.data, name="footer")
|
||||||
form.logo_footer.data, os.path.join(scu.SCODOC_LOGOS_DIR, "logo_footer")
|
|
||||||
)
|
|
||||||
app.clear_scodoc_cache()
|
app.clear_scodoc_cache()
|
||||||
flash(f"Configuration enregistrée")
|
flash(f"Configuration enregistrée")
|
||||||
return redirect(url_for("scodoc.index"))
|
return redirect(url_for("scodoc.index"))
|
||||||
|
@ -259,29 +261,83 @@ def configuration():
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def _return_logo(logo_type="header", scodoc_dept=""):
|
SMALL_SIZE = (300, 300)
|
||||||
|
|
||||||
|
|
||||||
|
def _return_logo(
|
||||||
|
name="header", dept_id="", small=False, global_if_not_found: bool = True
|
||||||
|
):
|
||||||
# stockée dans /opt/scodoc-data/config/logos donc servie manuellement ici
|
# stockée dans /opt/scodoc-data/config/logos donc servie manuellement ici
|
||||||
filename = sco_logos.get_logo_filename(logo_type, scodoc_dept)
|
# génération d'une url
|
||||||
if filename:
|
# url = url_for(
|
||||||
extension = os.path.splitext(filename)[1]
|
# "scodoc.get_logo_small",
|
||||||
return send_file(filename, mimetype=f"image/{extension}")
|
# name=name,
|
||||||
|
# dept_id=dept_id,
|
||||||
|
# global_if_not_found=global_if_not_found,
|
||||||
|
# )
|
||||||
|
logo = sco_logos.find_logo(name, dept_id, global_if_not_found)
|
||||||
|
if logo is not None:
|
||||||
|
suffix = logo.suffix
|
||||||
|
if small:
|
||||||
|
with PILImage.open(logo.filepath) as im:
|
||||||
|
im.thumbnail(SMALL_SIZE)
|
||||||
|
stream = io.BytesIO()
|
||||||
|
# on garde le même format (on pourrait plus simplement générer systématiquement du JPEG)
|
||||||
|
fmt = { # adapt suffix to be compliant with PIL save format
|
||||||
|
"PNG": "PNG",
|
||||||
|
"JPG": "JPEG",
|
||||||
|
"JPEG": "JPEG",
|
||||||
|
}[suffix.upper()]
|
||||||
|
im.save(stream, fmt)
|
||||||
|
stream.seek(0)
|
||||||
|
return send_file(stream, mimetype=f"image/{fmt}")
|
||||||
|
else:
|
||||||
|
return send_file(logo.filepath, mimetype=f"image/{suffix}")
|
||||||
else:
|
else:
|
||||||
return ""
|
abort(404)
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/ScoDoc/logo_header")
|
# small version (copy/paste from get_logo
|
||||||
@bp.route("/ScoDoc/<scodoc_dept>/logo_header")
|
@bp.route("/ScoDoc/logos/<name>/small", defaults={"dept_id": None})
|
||||||
def logo_header(scodoc_dept=""):
|
@bp.route("/ScoDoc/<int:dept_id>/logos/<name>/small")
|
||||||
"Image logo header"
|
@admin_required
|
||||||
# "/opt/scodoc-data/config/logos/logo_header")
|
def get_logo_small(name: str, dept_id: int):
|
||||||
return _return_logo(logo_type="header", scodoc_dept=scodoc_dept)
|
global_if_not_found = request.args.get("global_if_not_found", "True")
|
||||||
|
return _return_logo(
|
||||||
|
name,
|
||||||
|
dept_id=dept_id,
|
||||||
|
small=True,
|
||||||
|
global_if_not_found=global_if_not_found.upper() not in ["0", "FALSE"],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/ScoDoc/logo_footer")
|
@bp.route(
|
||||||
@bp.route("/ScoDoc/<scodoc_dept>/logo_footer")
|
"/ScoDoc/logos/<name>", defaults={"dept_id": None}
|
||||||
def logo_footer(scodoc_dept=""):
|
) # if dept not specified, take global logo
|
||||||
"Image logo footer"
|
@bp.route("/ScoDoc/<int:dept_id>/logos/<name>")
|
||||||
return _return_logo(logo_type="footer", scodoc_dept=scodoc_dept)
|
@admin_required
|
||||||
|
def get_logo(name: str, dept_id: int):
|
||||||
|
global_if_not_found = request.args.get("global_if_not_found", "True")
|
||||||
|
return _return_logo(
|
||||||
|
name,
|
||||||
|
dept_id=dept_id,
|
||||||
|
small=False,
|
||||||
|
global_if_not_found=global_if_not_found.upper() not in ["0", "FALSE"],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# @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
|
# essais
|
||||||
|
|
Loading…
Reference in New Issue