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.models import Departement
|
||||||
from app.scodoc import sco_logos, html_sco_header
|
from app.scodoc import sco_logos, html_sco_header
|
||||||
from app.scodoc import sco_utils as scu
|
from app.scodoc import sco_utils as scu
|
||||||
from app.scodoc.sco_config_actions import (
|
|
||||||
LogoDelete,
|
from app.scodoc.sco_config_actions import LogoInsert
|
||||||
LogoUpdate,
|
|
||||||
LogoInsert,
|
|
||||||
)
|
|
||||||
|
|
||||||
from app.scodoc.sco_logos import find_logo
|
from app.scodoc.sco_logos import find_logo
|
||||||
|
|
||||||
@ -120,6 +117,8 @@ def logo_name_validator(message=None):
|
|||||||
class AddLogoForm(FlaskForm):
|
class AddLogoForm(FlaskForm):
|
||||||
"""Formulaire permettant l'ajout d'un logo (dans un département)"""
|
"""Formulaire permettant l'ajout d'un logo (dans un département)"""
|
||||||
|
|
||||||
|
from app.scodoc.sco_config_actions import LogoInsert
|
||||||
|
|
||||||
dept_key = HiddenField()
|
dept_key = HiddenField()
|
||||||
name = StringField(
|
name = StringField(
|
||||||
label="Nom",
|
label="Nom",
|
||||||
@ -160,13 +159,13 @@ class AddLogoForm(FlaskForm):
|
|||||||
return LogoInsert.build_action(self.data)
|
return LogoInsert.build_action(self.data)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def errors(self):
|
def opened(self):
|
||||||
if self.do_insert.data:
|
if self.do_insert.data:
|
||||||
if self.name.errors:
|
if self.name.errors:
|
||||||
return True
|
return "open"
|
||||||
if self.upload.errors:
|
if self.upload.errors:
|
||||||
return True
|
return "open"
|
||||||
return False
|
return ""
|
||||||
|
|
||||||
|
|
||||||
class LogoForm(FlaskForm):
|
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):
|
def __init__(self, *args, **kwargs):
|
||||||
kwargs["meta"] = {"csrf": False}
|
kwargs["meta"] = {"csrf": False}
|
||||||
@ -213,16 +223,24 @@ class LogoForm(FlaskForm):
|
|||||||
self.titre = "Logo pied de page"
|
self.titre = "Logo pied de page"
|
||||||
|
|
||||||
def select_action(self):
|
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:
|
if self.do_delete.data and self.can_delete:
|
||||||
return LogoDelete.build_action(self.data)
|
return LogoDelete.build_action(self.data)
|
||||||
if self.upload.data and self.validate():
|
if self.upload.data and self.validate():
|
||||||
return LogoUpdate.build_action(self.data)
|
return LogoUpdate.build_action(self.data)
|
||||||
|
if self.do_rename.data and self.validate():
|
||||||
|
return LogoRename.build_action(self.data)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def errors(self):
|
def opened(self):
|
||||||
if self.upload.data and self.upload.errors:
|
if self.upload.data and self.upload.errors:
|
||||||
return True
|
return "open"
|
||||||
return False
|
if self.new_name.data and self.new_name.errors:
|
||||||
|
return "open"
|
||||||
|
return ""
|
||||||
|
|
||||||
|
|
||||||
class DeptForm(FlaskForm):
|
class DeptForm(FlaskForm):
|
||||||
@ -257,13 +275,22 @@ class DeptForm(FlaskForm):
|
|||||||
return self
|
return self
|
||||||
return self.index.get(logoname, None)
|
return self.index.get(logoname, None)
|
||||||
|
|
||||||
def errors(self):
|
def opened(self):
|
||||||
if self.add_logo.errors():
|
if self.add_logo.opened():
|
||||||
return True
|
return "open"
|
||||||
for logo_form in self.logos:
|
for logo_form in self.logos:
|
||||||
if logo_form.errors():
|
if logo_form.opened():
|
||||||
return True
|
return "open"
|
||||||
return False
|
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():
|
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 flask import current_app
|
||||||
|
|
||||||
|
from app.scodoc.sco_logos import find_logo
|
||||||
|
|
||||||
|
|
||||||
class Action:
|
class Action:
|
||||||
"""Base class for all classes describing an action from from config form."""
|
"""Base class for all classes describing an action from from config form."""
|
||||||
@ -42,9 +41,9 @@ class Action:
|
|||||||
self.parameters = parameters
|
self.parameters = parameters
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def build_action(parameters, stream=None):
|
def build_action(parameters):
|
||||||
"""Check (from parameters) if some action has to be done and
|
"""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
|
raise NotImplementedError
|
||||||
|
|
||||||
def display(self):
|
def display(self):
|
||||||
@ -59,6 +58,45 @@ class Action:
|
|||||||
GLOBAL = "_"
|
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):
|
class LogoUpdate(Action):
|
||||||
"""Action: change a logo
|
"""Action: change a logo
|
||||||
dept_id: dept_id or '_',
|
dept_id: dept_id or '_',
|
||||||
@ -83,6 +121,8 @@ class LogoUpdate(Action):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def execute(self):
|
def execute(self):
|
||||||
|
from app.scodoc.sco_logos import write_logo
|
||||||
|
|
||||||
current_app.logger.info(self.message)
|
current_app.logger.info(self.message)
|
||||||
write_logo(
|
write_logo(
|
||||||
stream=self.parameters["upload"],
|
stream=self.parameters["upload"],
|
||||||
@ -113,6 +153,8 @@ class LogoDelete(Action):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def execute(self):
|
def execute(self):
|
||||||
|
from app.scodoc.sco_logos import delete_logo
|
||||||
|
|
||||||
current_app.logger.info(self.message)
|
current_app.logger.info(self.message)
|
||||||
delete_logo(name=self.parameters["logo_id"], dept_id=self.parameters["dept_id"])
|
delete_logo(name=self.parameters["logo_id"], dept_id=self.parameters["dept_id"])
|
||||||
|
|
||||||
@ -143,6 +185,8 @@ class LogoInsert(Action):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def execute(self):
|
def execute(self):
|
||||||
|
from app.scodoc.sco_logos import write_logo
|
||||||
|
|
||||||
dept_id = self.parameters["dept_key"]
|
dept_id = self.parameters["dept_key"]
|
||||||
if dept_id == GLOBAL:
|
if dept_id == GLOBAL:
|
||||||
dept_id = None
|
dept_id = None
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
"""Tableau de bord semestre
|
"""Tableau de bord semestre
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import datetime
|
||||||
from flask import current_app
|
from flask import current_app
|
||||||
from flask import g
|
from flask import g
|
||||||
from flask import request
|
from flask import request
|
||||||
@ -760,8 +761,7 @@ def _make_listes_sem(sem, with_absences=True):
|
|||||||
)
|
)
|
||||||
|
|
||||||
formsemestre_id = sem["formsemestre_id"]
|
formsemestre_id = sem["formsemestre_id"]
|
||||||
|
weekday = datetime.datetime.today().weekday()
|
||||||
# calcule dates 1er jour semaine pour absences
|
|
||||||
try:
|
try:
|
||||||
if with_absences:
|
if with_absences:
|
||||||
first_monday = sco_abs.ddmmyyyy(sem["date_debut"]).prev_monday()
|
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">
|
<select name="datedebut" class="noprint">
|
||||||
"""
|
"""
|
||||||
date = first_monday
|
date = first_monday
|
||||||
for jour in sco_abs.day_names():
|
for idx, jour in enumerate(sco_abs.day_names()):
|
||||||
form_abs_tmpl += f'<option value="{date}">{jour}s</option>'
|
form_abs_tmpl += f"""<option value="{date}" {'selected' if idx == weekday else ''}>{jour}s</option>"""
|
||||||
date = date.next_day()
|
date = date.next_day()
|
||||||
form_abs_tmpl += f"""
|
form_abs_tmpl += f"""
|
||||||
</select>
|
</select>
|
||||||
|
@ -89,6 +89,11 @@ 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)
|
||||||
|
|
||||||
|
|
||||||
|
def rename_logo(old_name, new_name, dept_id):
|
||||||
|
logo = find_logo(old_name, dept_id, True)
|
||||||
|
logo.rename(new_name)
|
||||||
|
|
||||||
|
|
||||||
def list_logos():
|
def list_logos():
|
||||||
"""Crée l'inventaire de tous les logos existants.
|
"""Crée l'inventaire de tous les logos existants.
|
||||||
L'inventaire se présente comme un dictionnaire de dictionnaire de Logo:
|
L'inventaire se présente comme un dictionnaire de dictionnaire de Logo:
|
||||||
@ -285,6 +290,20 @@ class Logo:
|
|||||||
dt = path.stat().st_mtime
|
dt = path.stat().st_mtime
|
||||||
return 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:
|
def guess_image_type(stream) -> str:
|
||||||
"guess image type from header in stream"
|
"guess image type from header in stream"
|
||||||
|
@ -1055,6 +1055,14 @@ span.wtf-field ul.errors li {
|
|||||||
display: list-item !important;
|
display: list-item !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.configuration_logo entete_dept {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.configuration_logo .effectifs {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
.configuration_logo h1 {
|
.configuration_logo h1 {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
@ -20,28 +20,20 @@
|
|||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|
||||||
{% macro render_add_logo(add_logo_form) %}
|
{% macro render_add_logo(add_logo_form) %}
|
||||||
{% if add_logo_form.errors() %}
|
<details {{ add_logo_form.opened() }}>
|
||||||
<details open>
|
<summary>
|
||||||
{% else %}
|
<h3>Ajouter un logo</h3>
|
||||||
<details>
|
</summary>
|
||||||
{% endif %}
|
<div>
|
||||||
<summary>
|
{{ render_field(add_logo_form.name) }}
|
||||||
<h3>Ajouter un logo</h3>
|
{{ render_field(add_logo_form.upload) }}
|
||||||
</summary>
|
{{ render_field(add_logo_form.do_insert, False, onSubmit="submit_form") }}
|
||||||
<div>
|
</div>
|
||||||
{{ render_field(add_logo_form.name) }}
|
</details>
|
||||||
{{ render_field(add_logo_form.upload) }}
|
|
||||||
{{ render_field(add_logo_form.do_insert, False, onSubmit="submit_form") }}
|
|
||||||
</div>
|
|
||||||
</details>
|
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|
||||||
{% macro render_logo(dept_form, logo_form) %}
|
{% macro render_logo(dept_form, logo_form) %}
|
||||||
{% if logo_form.errors() %}
|
<details {{ logo_form.opened() }}>
|
||||||
<details open>
|
|
||||||
{% else %}
|
|
||||||
<details>
|
|
||||||
{% endif %}
|
|
||||||
{{ logo_form.hidden_tag() }}
|
{{ logo_form.hidden_tag() }}
|
||||||
<summary>
|
<summary>
|
||||||
{% if logo_form.titre %}
|
{% if logo_form.titre %}
|
||||||
@ -73,6 +65,11 @@
|
|||||||
<span class="wtf-field">{{ render_field(logo_form.upload, False, onchange="submit_form()") }}</span>
|
<span class="wtf-field">{{ render_field(logo_form.upload, False, onchange="submit_form()") }}</span>
|
||||||
</div>
|
</div>
|
||||||
{% if logo_form.can_delete %}
|
{% 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_label">Supprimer l'image</div>
|
||||||
<div class="action_button">
|
<div class="action_button">
|
||||||
{{ render_field(logo_form.do_delete, False, onSubmit="submit_form()") }}
|
{{ render_field(logo_form.do_delete, False, onSubmit="submit_form()") }}
|
||||||
@ -107,22 +104,22 @@
|
|||||||
{% for dept_entry in form.depts.entries %}
|
{% for dept_entry in form.depts.entries %}
|
||||||
{% set dept_form = dept_entry.form %}
|
{% set dept_form = dept_entry.form %}
|
||||||
{{ dept_entry.form.hidden_tag() }}
|
{{ dept_entry.form.hidden_tag() }}
|
||||||
{% if dept_form.errors() %}
|
<details {{ dept_form.opened() }}>
|
||||||
<details open>
|
|
||||||
{% else %}
|
|
||||||
<details>
|
|
||||||
{% endif %}
|
|
||||||
<summary>
|
<summary>
|
||||||
{% if dept_entry.form.is_local() %}
|
<span class="entete_dept">
|
||||||
<h2>Département {{ dept_form.dept_name.data }}</h2>
|
{% if dept_entry.form.is_local() %}
|
||||||
<div class="sco_help">Les paramètres donnés sont spécifiques à ce département.<br />
|
<h2>Département {{ dept_form.dept_name.data }}</h2>
|
||||||
Les logos du département se substituent aux logos de même nom définis globalement:</div>
|
<h3 class="effectifs">{{ dept_form.count() }}</h3>
|
||||||
{% else %}
|
<div class="sco_help">Les paramètres donnés sont spécifiques à ce département.<br />
|
||||||
<h2>Logos généraux</h2>
|
Les logos du département se substituent aux logos de même nom définis globalement:</div>
|
||||||
<div class="sco_help">Les images de cette section sont utilisé pour tous les départements,
|
{% else %}
|
||||||
mais peuvent être redéfinies localement au niveau de chaque département
|
<h2>Logos généraux</h2>
|
||||||
(il suffit de définir un logo local de même nom)</div>
|
<h3 class="effectifs">{{ dept_form.count() }}</h3>
|
||||||
{% endif %}
|
<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>
|
</summary>
|
||||||
<div>
|
<div>
|
||||||
{{ render_logos(dept_form) }}
|
{{ render_logos(dept_form) }}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# -*- mode: python -*-
|
# -*- mode: python -*-
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
SCOVERSION = "9.2.4"
|
SCOVERSION = "9.2.5"
|
||||||
|
|
||||||
SCONAME = "ScoDoc"
|
SCONAME = "ScoDoc"
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user