diff --git a/app/forms/main/config_logos.py b/app/forms/main/config_logos.py index daea5de1b..0d0ac0d5a 100644 --- a/app/forms/main/config_logos.py +++ b/app/forms/main/config_logos.py @@ -41,11 +41,8 @@ from wtforms.fields.simple import StringField, HiddenField from app.models import Departement from app.scodoc import sco_logos, html_sco_header from app.scodoc import sco_utils as scu -from app.scodoc.sco_config_actions import ( - LogoDelete, - LogoUpdate, - LogoInsert, -) + +from app.scodoc.sco_config_actions import LogoInsert from app.scodoc.sco_logos import find_logo @@ -120,6 +117,8 @@ def logo_name_validator(message=None): class AddLogoForm(FlaskForm): """Formulaire permettant l'ajout d'un logo (dans un département)""" + from app.scodoc.sco_config_actions import LogoInsert + dept_key = HiddenField() name = StringField( label="Nom", @@ -160,13 +159,13 @@ class AddLogoForm(FlaskForm): return LogoInsert.build_action(self.data) return None - def errors(self): + def opened(self): if self.do_insert.data: if self.name.errors: - return True + return "open" if self.upload.errors: - return True - return False + return "open" + return "" class LogoForm(FlaskForm): @@ -184,7 +183,18 @@ class LogoForm(FlaskForm): ) ], ) - do_delete = SubmitField("Supprimer l'image") + do_delete = SubmitField("Supprimer") + do_rename = SubmitField("Renommer") + new_name = StringField( + label="Nom", + validators=[ + logo_name_validator("Nom de logo invalide (alphanumérique, _)"), + validators.Length( + max=20, message="Un nom ne doit pas dépasser 20 caractères" + ), + validators.DataRequired("Nom de logo requis (alphanumériques ou '-')"), + ], + ) def __init__(self, *args, **kwargs): kwargs["meta"] = {"csrf": False} @@ -213,16 +223,24 @@ class LogoForm(FlaskForm): self.titre = "Logo pied de page" def select_action(self): + from app.scodoc.sco_config_actions import LogoRename + from app.scodoc.sco_config_actions import LogoUpdate + from app.scodoc.sco_config_actions import LogoDelete + if self.do_delete.data and self.can_delete: return LogoDelete.build_action(self.data) if self.upload.data and self.validate(): return LogoUpdate.build_action(self.data) + if self.do_rename.data and self.validate(): + return LogoRename.build_action(self.data) return None - def errors(self): + def opened(self): if self.upload.data and self.upload.errors: - return True - return False + return "open" + if self.new_name.data and self.new_name.errors: + return "open" + return "" class DeptForm(FlaskForm): @@ -257,13 +275,22 @@ class DeptForm(FlaskForm): return self return self.index.get(logoname, None) - def errors(self): - if self.add_logo.errors(): - return True + def opened(self): + if self.add_logo.opened(): + return "open" for logo_form in self.logos: - if logo_form.errors(): - return True - return False + if logo_form.opened(): + return "open" + return "" + + def count(self): + compte = len(self.logos.entries) + if compte == 0: + return "vide" + elif compte == 1: + return "1 élément" + else: + return f"{compte} éléments" def _make_dept_id_name(): diff --git a/app/scodoc/sco_config_actions.py b/app/scodoc/sco_config_actions.py index e0e9133ec..887b66084 100644 --- a/app/scodoc/sco_config_actions.py +++ b/app/scodoc/sco_config_actions.py @@ -28,11 +28,10 @@ """ """ -from app.models import ScoDocSiteConfig -from app.scodoc.sco_logos import write_logo, find_logo, delete_logo -import app from flask import current_app +from app.scodoc.sco_logos import find_logo + class Action: """Base class for all classes describing an action from from config form.""" @@ -42,9 +41,9 @@ class Action: self.parameters = parameters @staticmethod - def build_action(parameters, stream=None): + def build_action(parameters): """Check (from parameters) if some action has to be done and - then return list of action (or else return empty list).""" + then return list of action (or else return None).""" raise NotImplementedError def display(self): @@ -59,6 +58,45 @@ class Action: GLOBAL = "_" +class LogoRename(Action): + """Action: rename a logo + dept_id: dept_id or '-' + logo_id: logo_id (old name) + new_name: new_name + """ + + def __init__(self, parameters): + super().__init__( + f"Renommage du logo {parameters['logo_id']} en {parameters['new_name']}", + parameters, + ) + + @staticmethod + def build_action(parameters): + dept_id = parameters["dept_key"] + if dept_id == GLOBAL: + dept_id = None + parameters["dept_id"] = dept_id + if parameters["new_name"]: + logo = find_logo( + logoname=parameters["new_name"], + dept_id=parameters["dept_key"], + strict=True, + ) + if logo is None: + return LogoRename(parameters) + + def execute(self): + from app.scodoc.sco_logos import rename_logo + + current_app.logger.info(self.message) + rename_logo( + old_name=self.parameters["logo_id"], + new_name=self.parameters["new_name"], + dept_id=self.parameters["dept_id"], + ) + + class LogoUpdate(Action): """Action: change a logo dept_id: dept_id or '_', @@ -83,6 +121,8 @@ class LogoUpdate(Action): return None def execute(self): + from app.scodoc.sco_logos import write_logo + current_app.logger.info(self.message) write_logo( stream=self.parameters["upload"], @@ -113,6 +153,8 @@ class LogoDelete(Action): return None def execute(self): + from app.scodoc.sco_logos import delete_logo + current_app.logger.info(self.message) delete_logo(name=self.parameters["logo_id"], dept_id=self.parameters["dept_id"]) @@ -143,6 +185,8 @@ class LogoInsert(Action): return None def execute(self): + from app.scodoc.sco_logos import write_logo + dept_id = self.parameters["dept_key"] if dept_id == GLOBAL: dept_id = None diff --git a/app/scodoc/sco_logos.py b/app/scodoc/sco_logos.py index 02272ce87..27ce7573d 100644 --- a/app/scodoc/sco_logos.py +++ b/app/scodoc/sco_logos.py @@ -89,6 +89,11 @@ def write_logo(stream, name, dept_id=None): Logo(logoname=name, dept_id=dept_id).create(stream) +def rename_logo(old_name, new_name, dept_id): + logo = find_logo(old_name, dept_id, True) + logo.rename(new_name) + + def list_logos(): """Crée l'inventaire de tous les logos existants. L'inventaire se présente comme un dictionnaire de dictionnaire de Logo: @@ -285,6 +290,20 @@ class Logo: dt = path.stat().st_mtime return path.stat().st_mtime + def rename(self, new_name): + """Change le nom (pas le département) + Les éléments non utiles ne sont pas recalculés (car rechargés lors des accès ultérieurs) + """ + old_path = Path(self.filepath) + self.logoname = secure_filename(new_name) + if not self.logoname: + self.logoname = "*** *** nom de logo invalide *** à changer ! *** ***" + else: + new_path = os.path.sep.join( + [self.dirpath, self.prefix + self.logoname + "." + self.suffix] + ) + old_path.rename(new_path) + def guess_image_type(stream) -> str: "guess image type from header in stream" diff --git a/app/static/css/scodoc.css b/app/static/css/scodoc.css index 1b1e33a02..24548b28c 100644 --- a/app/static/css/scodoc.css +++ b/app/static/css/scodoc.css @@ -1055,6 +1055,14 @@ span.wtf-field ul.errors li { display: list-item !important; } +.configuration_logo entete_dept { + display: inline-block; +} + +.configuration_logo .effectifs { + float: right; +} + .configuration_logo h1 { display: inline-block; } diff --git a/app/templates/config_logos.html b/app/templates/config_logos.html index 04d4d2663..69d18f7bd 100644 --- a/app/templates/config_logos.html +++ b/app/templates/config_logos.html @@ -20,28 +20,20 @@ {% endmacro %} {% macro render_add_logo(add_logo_form) %} - {% if add_logo_form.errors() %} -
- {% else %} -
- {% endif %} - -

Ajouter un logo

-
-
- {{ render_field(add_logo_form.name) }} - {{ render_field(add_logo_form.upload) }} - {{ render_field(add_logo_form.do_insert, False, onSubmit="submit_form") }} -
-
+
+ +

Ajouter un logo

+
+
+ {{ render_field(add_logo_form.name) }} + {{ render_field(add_logo_form.upload) }} + {{ render_field(add_logo_form.do_insert, False, onSubmit="submit_form") }} +
+
{% endmacro %} {% macro render_logo(dept_form, logo_form) %} - {% if logo_form.errors() %} -
- {% else %} -
- {% endif %} +
{{ logo_form.hidden_tag() }} {% if logo_form.titre %} @@ -73,6 +65,11 @@ {{ render_field(logo_form.upload, False, onchange="submit_form()") }} {% if logo_form.can_delete %} +
Renommer
+
+ {{ render_field(logo_form.new_name, False) }} + {{ render_field(logo_form.do_rename, False, onSubmit="submit_form()") }} +
Supprimer l'image
{{ render_field(logo_form.do_delete, False, onSubmit="submit_form()") }} @@ -107,22 +104,22 @@ {% for dept_entry in form.depts.entries %} {% set dept_form = dept_entry.form %} {{ dept_entry.form.hidden_tag() }} - {% if dept_form.errors() %} -
- {% else %} -
- {% endif %} +
- {% if dept_entry.form.is_local() %} -

Département {{ dept_form.dept_name.data }}

-
Les paramètres donnés sont spécifiques à ce département.
- Les logos du département se substituent aux logos de même nom définis globalement:
- {% else %} -

Logos généraux

-
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)
- {% endif %} + + {% if dept_entry.form.is_local() %} +

Département {{ dept_form.dept_name.data }}

+

{{ dept_form.count() }}

+
Les paramètres donnés sont spécifiques à ce département.
+ Les logos du département se substituent aux logos de même nom définis globalement:
+ {% else %} +

Logos généraux

+

{{ dept_form.count() }}

+
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)
+ {% endif %} +
{{ render_logos(dept_form) }}