[reledit] do NOT propose to edit composite-related entities (unlinking would destroy the other side)
.. -*- coding: utf-8 -*-
Paramétrages et extensions spécifiques
--------------------------------------
Valeurs par défaut dynamiques
`````````````````````````````
Il est possible de définir dans le schéma des valeurs par défaut *statiques*.
Il est également possible de définir des valeurs par défaut *dynamiques* en
définissant sur la classe d'entité une méthode `default_<nom attribut>` pour
un attribut donnée.
Contrôle des attributs chargés et du tri par défaut
```````````````````````````````````````````````````
* l'attribut de classe `fetch_attrs` permet de définir sur une classe d'entité
la liste des noms des attributs ou relations devant être chargés
automatiquement lors de la récupération d'entité(s) de ce type. Dans le cas
des relations, on est limité aux relations *sujets de cardinalité `?` ou `1`*.
* la méthode de classe `fetch_order(attr, var)` prend en argument un nom
d'attribut (ou de relation) et un nom de variable et doit retourner une chaine
à utiliser dans la close "ORDERBY" d'une requête RQL pour trier
automatiquement les listes d'entités de ce type selon cet attribut, ou `None`
si l'on ne veut pas de tri sur l'attribut passé en argument. Par défaut les
entités sont triées selon leur date de création
* la méthode de classe `fetch_unrelated_order(attr, var)` est similaire à la
méthode `fetch_order` mais est utilisée essentiellement pour contrôler le tri
des listes déroulantes permettant de créer des relations dans la vue d'édition
d'une entité
La fonction `fetch_config(fetchattrs, mainattr=None)` permet de simplifier la
définition des attributs à précharger et du tri en retournant une liste des
attributs à précharger (en considérant ceux de la classe `AnyEntity`
automatiquement) et une fonction de tri sur l'attribut "principal" (le 2eme
argument si spécifié ou sinon le premier attribut de la liste `fetchattrs`).
Cette fonction est définie dans le package `ginco.entities`.
Par exemple : ::
class Transition(AnyEntity):
"""..."""
id = 'Transition'
fetch_attrs, fetch_order = fetch_config(['name'])
Indique que pour le type d'entité "Transition" il faut précharger l'attribut
"name" et trier par défaut selon cet attribut.
Contrôle des formulaires d'édition
``````````````````````````````````
Il est possible de contrôler les attributs/relations dans la vue d'édition
simple ou multiple à l'aide des *rtags* suivants :
* `primary`, indique qu'un attribut ou une relation doit être incorporé dans
les formulaires d'édition simple et multiple. Dans le cas d'une relation,
le formulaire d'édition de l'entité liée sera inclus dans le formulaire
* `secondary`, indique qu'un attribut ou une relation doit être incorporé dans
le formulaire d'édition simple uniquement. Dans le cas d'une relation,
le formulaire d'édition de l'entité liée sera inclus dans le formulaire
* `generic`, indique qu'une relation doit être incorporé dans le formulaire
d'édition simple dans la boite générique d'ajout de relation
* `generated`, indique qu'un attribut est caculé dynamiquement ou autre, et
qu'il ne doit donc pas être présent dans les formulaires d'édition
Au besoin il est possible de surcharger la méthode
`relation_category(rtype, x='subject')` pour calculer dynamiquement la catégorie
d'édition d'une relation.
Contrôle de la boîte "add_related"
``````````````````````````````````
La boite `add related` est une boite automatique proposant de créer une entité
qui sera automatiquement liée à l'entité de départ (le contexte dans lequel
s'affiche la boite). Par défaut, les liens présents dans cette boite sont
calculés en fonction des propriétés du schéma de l'entité visualisée, mais il
est possible de les spécifier explicitement à l'aide des *rtags* suivants :
* `link`, indique qu'une relation est généralement créée vers une entité
existante et qu'il ne faut donc pas faire apparaitre de lien pour cette
relation
* `create`, indique qu'une relation est généralement créée vers de nouvelles
entités et qu'il faut donc faire apparaitre un lien pour créer une nouvelle
entité et la lier automatiquement
Au besoin il est possible de surcharger la méthode
`relation_mode(rtype, targettype, x='subject')` pour caculer dynamiquement la
catégorie de création d'une relation.
A noter également que si au moins une action dans la catégorie "addrelated" est
trouvée pour le contexte courant, le fonctionnement automatique est désactivé
en faveur du fonctionnement explicite (i.e. affichage des actions de la
catégorie "addrelated" uniquement).
Contrôle des formulaires de filtrage de table
`````````````````````````````````````````````
La vue "table" par défaut gère dynamiquement un formulaire de filtrage du
contenu de celle-ci. L'algorithme est le suivant :
1. on considère que la première colonne contient les entités à restreindre
2. on recupère la première entité de la table (ligne 0) pour "représenter"
toutes les autres
3. pour toutes les autres variables définies dans la requête originale :
1. si la variable est liée à la variable principale par au moins une
n'importe quelle relation
2. on appelle la méthode `filterform_vocabulary(rtype, x)` sur l'entité
et si rien est retourné (ou plus exactement un tuple de valeur `None`,
voir ci-dessous) on passe à la variable suivante, sinon un élément de
formulaire de filtrage sera créé avec les valeurs de vocabulaire
retournées
4. il n'y a pas d'autres limitations sur le rql, il peut comporter des clauses
de tris, de groupes... Des fonctions javascripts sont utilisées pour
regénérer une requête à partir de la requête de départ et des valeurs
séléctionnées dans les filtres de formulaire.
La méthode `filterform_vocabulary(rtype, x, var, rqlst, args, cachekey)` prend
en argument le nom d'une relation et la "cible", qui indique si l'entité sur
laquelle la méthode est appellée est sujet ou objet de la relation. Elle doit
retourner :
* un 2-uple de None si elle ne sait pas gérer cette relation
* un type et une liste contenant le vocabulaire
* la liste doit contenir des couples (valeur, label)
* le type indique si la valeur désigne un nombre entier (`type == 'int'`), une
chaîne de caractères (`type == 'string'`) ou une entité non finale (`type
== 'eid'`)
Par exemple dans notre application de gestion de tickets, on veut pouvoir
filtrés ceux-ci par :
* type
* priorité
* état (in_state)
* étiquette (tags)
* version (done_in)
On définit donc la méthode suivante : ::
class Ticket(AnyEntity):
...
def filterform_vocabulary(self, rtype, x, var, rqlst, args, cachekey):
_ = self.req._
if rtype == 'type':
return 'string', [(x, _(x)) for x in ('bug', 'story')]
if rtype == 'priority':
return 'string', [(x, _(x)) for x in ('minor', 'normal', 'important')]
if rtype == 'done_in':
rql = insert_attr_select_relation(rqlst, var, rtype, 'num')
return 'eid', self.req.execute(rql, args, cachekey)
return super(Ticket, self).filterform_vocabulary(rtype, x, var, rqlst,
args, cachekey)
NOTE: Le support du filtrage sur les étiquettes et l'état est installé
automatiquement, pas besoin de le gérer ici.