Chill-Main issueshttps://framagit.org/Chill-project/Chill-Main/-/issues2017-04-19T00:09:34Zhttps://framagit.org/Chill-project/Chill-Main/-/issues/26Logs et données sensibles2017-04-19T00:09:34ZJulien FastréLogs et données sensiblesJ'ai créé un channel spécial pour pouvoir stocker des données sensibles dans les logs. Ca m'est apparu plus simple à réaliser pour faire implémenter la possibilité de supprimer des `membership` dans le bundle group.
J'ai documenté ça ...J'ai créé un channel spécial pour pouvoir stocker des données sensibles dans les logs. Ca m'est apparu plus simple à réaliser pour faire implémenter la possibilité de supprimer des `membership` dans le bundle group.
J'ai documenté ça ici : http://chill.readthedocs.io/en/latest/development/logging.html
Du coup, les logs peuvent contenir des données sensibles, et il est important de les encrypter. J'ai ajouté un avertissement dans la documentation d'installation (qui reste incomplète, je vais y jeter un oeil ces prochains jours) : http://chill.readthedocs.io/en/latest/installation/install_production_webserver.html1.1https://framagit.org/Chill-project/Chill-Main/-/issues/20Postal code may be null2017-04-19T00:09:34ZJulien FastréPostal code may be nullThe postal code may be null in address. This cause page "person view" to crash when rendering.
- [x] add a condition "if not empty" in macro rendering ;
- [x] add a validationThe postal code may be null in address. This cause page "person view" to crash when rendering.
- [x] add a condition "if not empty" in macro rendering ;
- [x] add a validation1.1Julien FastréJulien Fastréhttps://framagit.org/Chill-project/Chill-Main/-/issues/19Create a script which will insert postal code2017-04-19T00:09:34ZJulien FastréCreate a script which will insert postal codeA command line command should be able to load postal code from CSV files.A command line command should be able to load postal code from CSV files.1.1Julien FastréJulien Fastréhttps://framagit.org/Chill-project/Chill-Main/-/issues/18Add validation constraints to Addresses and postal code2017-04-19T00:09:34ZJulien FastréAdd validation constraints to Addresses and postal code1.1https://framagit.org/Chill-project/Chill-Main/-/issues/12Allow adding info on template at runtime2017-04-19T00:09:34ZJulien FastréAllow adding info on template at runtimeAs mentioned in #11, we should have a way to add information in a template defined by another bundle. For instance, as described in the mentioned issue : we have a bundle `Person` which define a template for showing persons, we would lik...As mentioned in #11, we should have a way to add information in a template defined by another bundle. For instance, as described in the mentioned issue : we have a bundle `Person` which define a template for showing persons, we would like a module `Group` to add information about groups membership in the defined bundle.
We are thinking about defining zone in the template `Person`. Those zones will trigger "something" (which must be discussed here) to add HTML code in those zone.
Some ideas I am thinking about :
Using events
=============
[Symfony has an event framework](http://symfony.com/doc/current/components/event_dispatcher/index.html). We might trigger an event during the template rendering, and other bundles will use the event to retrieve information (for instance : which person is concerned by the rendering template) and, if required, produce text about this person.
The event will be triggered from within the template, using a custom function :
```jinja2+html
{{ chill_rendering_event('person_template', { 'Person' : person } ) }}
```
**pros** (according to me) :
- a lot of documentation about those features.
- the event is well defined, and the service may expect which information may be gathered from the Event object passed as argument.
**problems** :
- with defining the custom function, we will have to gather data about which `Event` object we will have to build. This is not obvious and might be defined by services, tags, ...
- it is not foreseen that an event must "return" something and, in our case, the event should return HTML code. Actually, the aim of an event is to triggering something like sending an email, adding something in the database, modifying the request, ...
To change this, I am thinking about those two solutions :
1. the class which handle the event during rendering should add his text to another service
2. or the class should prepare the text, which will be gathered later by another service and included in the template.
3. asking for Listeners/Suscribers to add text to the Event object, with a convenient method (for instance `Event::addHtml($html)`)
## Sending html to another service
Example for 1:
```php
<?php
use Chill\PersonBundle\Event\PersonRenderingEvent;
use Chill\PersonBundle\something\CollectHTMLForEvent;
class GroupDisplayListener
{
/*
* @var Chill\PersonBundle\something\CollectHTMLForEvent
*/
private $collector;
public function __construct(CollectHTMLForEvent $collector)
{
$this->collector = $collector;
}
public function onRendering(PersonRenderingEvent $event)
{
$person = $event->getPerson();
$groups; // collect group from person
foreach ($groups as $group) {
$html .= " // create HTML code to render group. In real life, this should be done by templates.";
}
$this->collector->add($html);
}
}
```
## Collecting text from another service
Example for 2:
```php
<?php
use Chill\PersonBundle\Event\PersonRenderingEvent;
/*
* this class should be registered as a service and tagged with convenient
* tag. The tag will allow a collector (which must be written) to collect and inject
* those text into template.
*/
class GroupDisplayListener implements HTMLCollector
{
/*
* @var string
*/
private $html = "";
public function onRendering(PersonRenderingEvent $event)
{
$person = $event->getPerson();
$groups; // collect group from person
foreach ($groups as $group) {
$this->html .= " // create HTML code to render group. In real life this should be done by templates.";
}
}
public function getCollectedHTML()
{
return $this->text;
}
}
```
## using the event to send the html back
**problem for this idea:**
- we are not sure that the event dispatcher do not make a `clone` of the `Event` object.
- if the object `Event` is not passed by reference, some html might be loosed
But I think this is not a problem because some Event modifies the Request object => it might be something which is already used.
Example for 3:
```php
<?php
use Chill\PersonBundle\Event\PersonRenderingEvent;
class GroupDisplayListener implements HTMLCollector
{
public function onRendering(PersonRenderingEvent $event)
{
$person = $event->getPerson();
$groups; // collect group from person
foreach ($groups as $group) {
$html .= " // create HTML code to render group. In real life this should be done by templates.";
}
// we add the html back to event
$event->addHtml($html);
// the html will be collected back by the function which triggered the event
}
}
```
Using tagged service
====================
We might use tagged services, as described in #9 or for Voters, ...
- the classes which produces html are tagged in depency injection and implements a custom interface ;
- on class gather all the classes with this tag, and collect the HTML when some part of a template are rendered.
The html will be collected from within the template, using a custom function :
```jinja2+html
{{ chill_rendering_part('person_part_of_the_template', { 'Person' : person } ) }}
```
**pro** :
- we already use this in other part of our code.
- this is also well documented
**cons** :
- except if we create some class to transport data (by example, for specifiying which Person is currently being rendered), knowing which data will be passed as argument is not obvious.
1.1Julien FastréJulien Fastréhttps://framagit.org/Chill-project/Chill-Main/-/issues/11Création d'un module "groupe"2017-04-19T00:09:34ZJulien FastréCréation d'un module "groupe"Un module de groupe est demandé par des utilisateurs.
Cas d'utilisation
===================
L'idée: permettre d'associer des personnes entre elles, par exemple lorsque plusieurs personnes de la même famille sont accompagnées dans ...Un module de groupe est demandé par des utilisateurs.
Cas d'utilisation
===================
L'idée: permettre d'associer des personnes entre elles, par exemple lorsque plusieurs personnes de la même famille sont accompagnées dans la même association, ou lorsque l'association crée des groupes de parole, des activités de groupe, etc.
Le module serait néanmoins séparé du module `Person` pour permettre aux utilisateurs qui n'en ont pas besoin de ne pas utiliser les groupes.
Diagramme de classe
====================
Voici ce que l'on avait imaginé en diagramme de classe :
![diagramme de classe](/uploads/ef8da3b7ac26e184479ff6cb0785e501/classes.png)
Par rapport à une association classique entre un groupe et une personne, on propose d'intercaler une classe `Membership` qui permettrait d'indiquer un rôle qui caractériserait l'appartenance au groupe.
Intégration dans l'UI
======================
Affichage des appartenances et groupes
--------------------------------------
### Sur toutes les pages personnes
Proposition: que les groupes d'appartenances soient mentionnés
- soit dans le bandeau sur chaque page "personne",
- soit en bas ou en haut du menu.
Une manière de permettre de modifier les templates en fonction des autres modules installé est à étudier (en effet, le template des pages "personnes" est défini dans le module `PersonBundle`. Il faudrait donc trouver un moyen de le modifier dynamiquement).
### Page dédiée
Une autre page reprendrait la liste des appartenances.
## formulaire de saisie
Rien de défini pour le moment. Idées bienvenues.1.1https://framagit.org/Chill-project/Chill-Main/-/issues/24Create a pagination API2017-05-19T23:35:13ZJulien FastréCreate a pagination APIWe should think about an api for pagination. Currently, we do not have any limit on data appearing on page, but this might change.
We should be able to :
- limit the number of result par page ;
- create a link to the "next page" ...We should think about an api for pagination. Currently, we do not have any limit on data appearing on page, but this might change.
We should be able to :
- limit the number of result par page ;
- create a link to the "next page" with this `pagination class` ;
- rendering the class automatically with twig
1.1Julien FastréJulien Fastréhttps://framagit.org/Chill-project/Chill-Main/-/issues/10Layout of timeline2018-03-29T11:58:54ZJulien FastréLayout of timelineIt would be a good idea to improve the layout of timeline.
Here are some projects with re-usable code :
http://timelined.andriaus.lt/
http://nilswe.com/lab/css-timeline/ and http://codepen.io/NilsWe/pen/FemfK
http://codepen....It would be a good idea to improve the layout of timeline.
Here are some projects with re-usable code :
http://timelined.andriaus.lt/
http://nilswe.com/lab/css-timeline/ and http://codepen.io/NilsWe/pen/FemfK
http://codepen.io/betdream/details/Ifvbi
1.1Marc DucobuMarc Ducobu2016-05-13https://framagit.org/Chill-project/Chill-Main/-/issues/9Framework pour les exports2019-10-04T12:16:03ZJulien FastréFramework pour les exportsJ'ai un peu réfléchi à un framework pour les exports du logiciel. Mon objectif: essayez d'abstraire les exports en découpant chaque étape, de manière à pouvoir réutiliser le code au maximum.
**Comme le sujet est assez technique, j'uti...J'ai un peu réfléchi à un framework pour les exports du logiciel. Mon objectif: essayez d'abstraire les exports en découpant chaque étape, de manière à pouvoir réutiliser le code au maximum.
**Comme le sujet est assez technique, j'utilise le français.**
Fonctionnalités demandées
==========================
Résultat attendu
-----------------
Une des fonctionnalités les plus demandées est de pouvoir obtenir ce genre de tableau :
<table>
<thead>
<tr>
<th colspan="5">
Filtre par :
<ul>
<li> Nationalité: seulement "Belge", "Français"</li>
<li> Date: de janvier 2015 à mars 2015</li>
</ul>
</th>
<tr>
<th> Nationalité </th><th> Genre </th><th colspan="3"> Nombre d'activités effectuées</th>
</tr><tr>
<tr>
<th colspan="2"> </th><th> Janvier 2015 </th><th> Février 2015 </th><th> Mars 2015 </th>
</tr>
</thead>
<tbody>
<tr>
<td>Belge</td><td>Homme</td><td>15</td><td>12</td><td>9</td>
</tr>
<tr>
<td>Belge</td><td>Femme</td><td>25</td><td>22</td><td>19</td>
</tr>
<tr>
<td>Français</td><td>Homme</td><td>15</td><td>12</td><td>9</td>
</tr>
<tr>
<td>Français</td><td>Femme</td><td>25</td><td>22</td><td>19</td>
</tr>
</tbody>
</table>
Parcours utilisateur
---------------------
L'utilisateur clique sur le menu "export" en haut à droite.
Il arrive sur une page qui liste tous les types d'exports possibles, avec un petit mot d'explication sur chaque export. Pour l'export précédent, il choisit un export nommé "Nombre d'activités".
Il arrive sur une page qui contient trois parties :
- les filtres ;
- les agrégateurs ;
- le format d'export.
**Dans la première partie**, il voit une liste les filtres. Un filtre est un texte + éventuellement un formulaire. Certains concernent les activités, d'autres les personnes. Pour choisir les filtres, il remplit le formulaire qui y est associé, et coche une case pour l'activer (Alternative: faire un glisser-déposer vers une autre zone de la page). Exemples de filtre :
- filtrer par date d'activité, avec un (choisi ici)
- filtrer par catégories et sujets d'activité (on peut cliquer sur les catégories et les sujets)
- filtrer par nationalité (on peut cliquer sur les nationalités) (choisi ici) ;
- filtrer par sexe ;
- ...
**Dans la deuxième partie**, l'utilisateur choisit des agrégateurs.
Exemple d'agrégateur :
- grouper par Genre ;
- grouper par Nationalité ;
- grouper par date (avec un formulaire où on peut choisir "par mois", "par semaine", "par jour", "par trimestre", "par année")
- grouper par catégorie d'activités
- grouper par types d'activités
- ...
Cette partie de page est divisée en deux:
- partie de gauche, la liste des agrégateurs ;
- partie de droite, vers le haut les agrégateurs que l'utilisateur a sélectionné par drag and drop (ça serait top) et doivent figurer dans les en-têtes de colonne (ici, Nationalité et Genre)
- partie de droite, vers le bas, les agrégateurs que l'utilisateur a sélectionné par drag and drop (ça serait top) et doivent figurer dans les en-têtes de ligne (ici, par mois)
Il fait un glisser déposer et les mets dans la partie de droite. Il peut également les ordonner. Il peut également remplir un formulaire avec les éventuelles précisions.
**Dans la troisième partie**, l'utilisateur peut choisir entre les différents formats d'export :
- CSV
- xslx
- graphiques (à venir)
Le code derrière
================
Je propose de découper le code en quatre type d'objets :
- les exports ;
- les filtres ;
- les agrégateurs ;
- les formatteurs (pas trouvé de nom français plus joli, on s'en contentera)
Toutes ces classes sont déclarées comme des services, avec un tag qui permet à l'injecteur de dépendance de les identifier.
Les formatteurs
----------------
Ils reçoivent les données des exports et les mettent en forme. Il y en aura peu, à priori un pour le CSV, un pour le XLSX et un pour les graphiques.
Les exports
------------
Son boulot : rassembler tous les filtres, les agrégateurs et récupérer les données depuis la DB, puis les mettre sous une forme définie (un tableau associatif ?) qui précise quels sont les en-têtes de tableau, les en-têtes de ligne, etc. pour qu'elles puissent être mise en forme par le formatteur.
Le formatteur peut éventuellement être configuré par un formulaire (à voir si c'est nécessaire).
Techniquement, il s'agirait tout simple pour l'exporteur de préparer une requête "de base" avec [le QueryBuilder de doctrine](http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/query-builder.html). La requête serait passée aux filtres et aux agrégateurs qui y ajouteraient leurs paramètres. Puis elle serait exécutée et les résultats transmis au formatteur.
Les exports indiquent quel type de filtre et d'agrégateur ils supportent. Par exemple, dans l'exemple ci-dessus, ils supportent uniquement les filtres et les agrégateurs de type `person` et `activity`.
Les filtres
-----------
Les filtres fournissent :
- éventuellement un formulaire, qui est affichée dans l'UI, pour configurer le filtre. Par exemple, pour le choix des dates, il peut s'agir d'un formulaire qui présente la date de début et de fin de la période. Pour le filtre par nationalité, un select avec l'option multiple qui présente toutes les nationalités, etc.
- ajoutent leurs paramètres à la requête de l'export. Il s'agirait, pour eux, d'ajouter des paramètres à la clause `WHERE`. Ici, j'ai ajouté deux filtres qui ajouteraient les clauses suivantes : `WHERE person.nationality in (BELGIUM, FRANCE)` et `WHERE activity.date BETWEEN 2015-01-01 AND 2015-03-31`.
Chaque filtre indiquerait pour quel objet il peut être appelé. Donc un filtre qui peut être appelé pour l'objet `activity` sera ajouté au formulaire des exports qui concernent les activités, les filtres pour les personnes (filtre par nationalité, etc.) sera disponible pour les exports qui concernent les activités et les personnes, etc.
Les agrégateurs
----------------
Le boulot des agrégateur est de regrouper les données en fonction de certains paramètres.
- ils peuvent également fournir un formulaire, affiché dans l'UI, pour régler ces paramètres. Par exemple, un agrégateur par date pourrait demander aux utilisateurs de choisir entre une agrégation par mois, par semaine, par jour de la semaine, etc.
- ils ajouteraient des clauses `GROUP BY` aux requêtes SQL. Dans l'exemple ci-dessus, il pourrait s'agir d'un premier agrégateur `GROUP BY person.nationality` puis un autre : `GROUP BY person.gender` (+ le fait d'ajouter `person.nationality` et `person.gender` dans la clause `SELECT`).
**Note :** on aura peut-être un problème quand un utilisateur choisi un filtre qui concerne également les agrégations: dans ce cas là il faut utiliser HAVING plutôt que WHERE... (http://www.w3schools.com/sql/sql_having.asp).
Un contrôleur pour les exports
===============================
Pour orchestrer tout ce petit monde, un contrôleur, ou un autre service, serait informé de tous les agrégateurs, filtres et export possibles par l'injecteur de dépendance.
Il afficherait la liste des exports possibles, et, quand on sélectionnerait un export, il créerait un formulaire qui contiendrait tous les sous-formulaires des agrégateurs, filtres et exports.
Quand un utilisateur demanderait un export, il recevrait les données des formulaires, sélectionnairait les exports que l'utilisateur a demandé, en extrairait les données qu'il enverrait à l'export sélectionné (il créerait la requête DQL), puis aux filtres et agrégateur (ils modifieraient la requêtes DQL en ajoutant les paramètres WHERE et GROUP BY).
La ré-utilisation
-------------------
Evidemment, à chaque fois, le code des agrégateurs et filtres pourrait être ré-utilisés dans les autres bundles. Autrement dit, si on a un filtre par nationalité défini dans la bundle "person", ce filtre est réutilisable par le bundle "activity" pour les exports propres au bundle "activity".
Qu'en pensez-vous ?
Si ça vous semble ok, je peux avancer :
- définir les interfaces et les formats d'échange ;
- faire un premier POC1.1Julien FastréJulien Fastréhttps://framagit.org/Chill-project/Chill-Main/-/issues/21Fix OpenSans font-weight and font-style2021-03-11T13:28:17ZJulien FastréFix OpenSans font-weight and font-styleDans [le css qui charge la police](Resources/public/fonts/OpenSans/OpenSans.css), les attributs fonts-weight et font-style sont toujours "normal", tands que la font-familiy détermine le nom de la police.
Or, ce sont eux qui déterminen...Dans [le css qui charge la police](Resources/public/fonts/OpenSans/OpenSans.css), les attributs fonts-weight et font-style sont toujours "normal", tands que la font-familiy détermine le nom de la police.
Or, ce sont eux qui déterminent les variantes pour la même police. Dès lors, quand on a du bold qui s'affiche, ça n'est probablement pas la "bonne" police, mais une transformation du navigateur qui peut être de moins bonne qualité.
Il faudrait fixer les attributs font-family à "Open Sans" et modifier, le cas échéant, les attributs font-weight et font-style. Chez moi, l'apparence est parfois un peu diluée et peu agréable.
Je ne sais pas non plus si on a besoin de toutes les variantes de `weight`, depuis light jusqu'à extrabold. On pourrait se limiter à deux-trois (regular, bold, extrabold).1.1Julien FastréJulien Fastré