forked from ScoDoc/ScoDoc
Merge branch 'dev93' of https://scodoc.org/git/viennet/ScoDoc
This commit is contained in:
commit
557c5eec4f
@ -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():
|
||||
|
@ -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
|
||||
|
@ -28,6 +28,7 @@
|
||||
"""Tableau de bord semestre
|
||||
"""
|
||||
|
||||
import datetime
|
||||
from flask import current_app
|
||||
from flask import g
|
||||
from flask import request
|
||||
@ -760,8 +761,7 @@ def _make_listes_sem(sem, with_absences=True):
|
||||
)
|
||||
|
||||
formsemestre_id = sem["formsemestre_id"]
|
||||
|
||||
# calcule dates 1er jour semaine pour absences
|
||||
weekday = datetime.datetime.today().weekday()
|
||||
try:
|
||||
if with_absences:
|
||||
first_monday = sco_abs.ddmmyyyy(sem["date_debut"]).prev_monday()
|
||||
@ -780,8 +780,8 @@ def _make_listes_sem(sem, with_absences=True):
|
||||
<select name="datedebut" class="noprint">
|
||||
"""
|
||||
date = first_monday
|
||||
for jour in sco_abs.day_names():
|
||||
form_abs_tmpl += f'<option value="{date}">{jour}s</option>'
|
||||
for idx, jour in enumerate(sco_abs.day_names()):
|
||||
form_abs_tmpl += f"""<option value="{date}" {'selected' if idx == weekday else ''}>{jour}s</option>"""
|
||||
date = date.next_day()
|
||||
form_abs_tmpl += f"""
|
||||
</select>
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -20,28 +20,20 @@
|
||||
{% endmacro %}
|
||||
|
||||
{% macro render_add_logo(add_logo_form) %}
|
||||
{% if add_logo_form.errors() %}
|
||||
<details open>
|
||||
{% else %}
|
||||
<details>
|
||||
{% endif %}
|
||||
<summary>
|
||||
<h3>Ajouter un logo</h3>
|
||||
</summary>
|
||||
<div>
|
||||
{{ render_field(add_logo_form.name) }}
|
||||
{{ render_field(add_logo_form.upload) }}
|
||||
{{ render_field(add_logo_form.do_insert, False, onSubmit="submit_form") }}
|
||||
</div>
|
||||
</details>
|
||||
<details {{ add_logo_form.opened() }}>
|
||||
<summary>
|
||||
<h3>Ajouter un logo</h3>
|
||||
</summary>
|
||||
<div>
|
||||
{{ render_field(add_logo_form.name) }}
|
||||
{{ render_field(add_logo_form.upload) }}
|
||||
{{ render_field(add_logo_form.do_insert, False, onSubmit="submit_form") }}
|
||||
</div>
|
||||
</details>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro render_logo(dept_form, logo_form) %}
|
||||
{% if logo_form.errors() %}
|
||||
<details open>
|
||||
{% else %}
|
||||
<details>
|
||||
{% endif %}
|
||||
<details {{ logo_form.opened() }}>
|
||||
{{ logo_form.hidden_tag() }}
|
||||
<summary>
|
||||
{% if logo_form.titre %}
|
||||
@ -73,6 +65,11 @@
|
||||
<span class="wtf-field">{{ render_field(logo_form.upload, False, onchange="submit_form()") }}</span>
|
||||
</div>
|
||||
{% if logo_form.can_delete %}
|
||||
<div class="action_label">Renommer</div>
|
||||
<div class="action_button">
|
||||
{{ render_field(logo_form.new_name, False) }}
|
||||
{{ render_field(logo_form.do_rename, False, onSubmit="submit_form()") }}
|
||||
</div>
|
||||
<div class="action_label">Supprimer l'image</div>
|
||||
<div class="action_button">
|
||||
{{ 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() %}
|
||||
<details open>
|
||||
{% else %}
|
||||
<details>
|
||||
{% endif %}
|
||||
<details {{ dept_form.opened() }}>
|
||||
<summary>
|
||||
{% if dept_entry.form.is_local() %}
|
||||
<h2>Département {{ dept_form.dept_name.data }}</h2>
|
||||
<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>
|
||||
{% else %}
|
||||
<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>
|
||||
{% endif %}
|
||||
<span class="entete_dept">
|
||||
{% if dept_entry.form.is_local() %}
|
||||
<h2>Département {{ dept_form.dept_name.data }}</h2>
|
||||
<h3 class="effectifs">{{ dept_form.count() }}</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>
|
||||
{% else %}
|
||||
<h2>Logos généraux</h2>
|
||||
<h3 class="effectifs">{{ dept_form.count() }}</h3>
|
||||
<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>
|
||||
{% endif %}
|
||||
</span>
|
||||
</summary>
|
||||
<div>
|
||||
{{ render_logos(dept_form) }}
|
||||
|
@ -1,7 +1,7 @@
|
||||
# -*- mode: python -*-
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
SCOVERSION = "9.2.4"
|
||||
SCOVERSION = "9.2.5"
|
||||
|
||||
SCONAME = "ScoDoc"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user