Aller au contenu principal

Définition de vue Model-Driven

Identifiant du schéma : model-driven-view@2 Schéma lisible par machine : model-driven-view.schema.json

Version remplacée : model-driven-view@1 (model-driven-view-v1.schema.json) reste publiée et enregistrée, afin qu’une solution déjà déployée avec elle soit toujours validée selon le schéma pour lequel elle a été conçue. La version 2 ne fait jamais qu’ajouter des propriétés facultatives — le tableau Structure ci-dessous en donne la liste actuelle — : toute définition v1 est donc aussi une définition v2 valide, et rien n’est à réécrire.

La représentation canonique d’une vue Model-Driven Apps (section 6.7) — une liste tabulaire d’enregistrements avec ses colonnes, ses filtres et ses tris.

Structure​

ChampTypeObligatoireRemarques
logicalNamestringouiPréfixé par l’éditeur, en snake-case minuscule.
displayNamestringouiNom lisible de la vue.
entitystringouiLe nom logique de la table propriétaire.
descriptionstringnonLa ligne affichée sous le titre dans la barre de titre de la vue.
iconstringnonL’icône affichée dans la barre de titre de la vue.
viewTypestringnonCe à quoi sert la vue : Public (par défaut), Lookup, QuickFind, Associated, QuickView, Card, SeedData.
seedDataKindstringsur une vue SeedDataObligatoire sur une vue SeedData et refusé sur toute autre : Configuration (des lignes dont la solution a besoin pour fonctionner ; une importation les apporte toujours, Production comprise) ou Demonstration (des lignes d’exemple ; importées uniquement lorsque Inclure les données de démonstration est coché, jamais en Production). Reporté dans le package comme kind du document de données initiales.
columnsarrayouiNoms logiques des champs affichés en colonnes.
filtersarraynonClauses de filtre à plat (combinées par ET) : field, operator et (pour les opérateurs à valeur) value.
filterGroupobjectnonUne arborescence de filtres ET/OU hiérarchique (à la manière de la recherche avancée), combinée par ET avec filters.
sortsarraynonClauses de tri : field, descending.
actionsarraynonActions de barre de commandes configurables.
hierarchyobjectnonPrésent lorsque la vue s’affiche sous forme d’arbre plutôt que de grille.
calendarobjectnonPrésent lorsque la vue s’affiche sous forme de calendrier plutôt que de grille. Jamais en même temps que hierarchy.
columnPropertiesarraynonLa manière dont chaque colonne est présentée — en-tête, largeur, format, alignement, contrôle. Clairsemé.
commandOverridesarraynonCe que cette vue modifie dans les commandes détenues par la plateforme.
commandOrderarraynonUne barre, un ordre : commandes intégrées et commandes du créateur entremêlées, par id.
rowSelectionbooleannonIndique si les lignes portent une case à cocher de sélection. true par défaut.

Opérateurs : Equals, NotEquals, Contains, GreaterThan, LessThan, IsNull, IsNotNull. Chaque champ référencé (colonnes, filtres, conditions de groupe de filtres, tris) doit exister sur la table.

viewType​

Le type d’une vue indique quelle surface la lit. Une même table peut porter simultanément une vue par défaut de chaque type, car elles répondent à des questions différentes :

ValeurÀ quoi elle sert
PublicLa page de liste normale de la table. C’est la valeur par défaut, et ce qu’est une définition sans viewType.
LookupLes colonnes affichées dans le panneau de résultats d’un contrôle de recherche — généralement deux à quatre.
QuickFindLes colonnes de recherche : les colonnes sur lesquelles porte une recherche saisie. Ses columns forment l’ensemble interrogé ; ses filtres et tris ne sont pas lus.
SeedDataLes lignes et colonnes qui voyagent avec la solution (PF22). Jamais affichée : une exportation de solution l’exécute — ses filters déterminent les lignes, ses columns les champs — et empaquette le résultat sous forme de document seed-data@1, qu’une importation insère ou met à jour par id. Une table qui en a plusieurs utilise celle par défaut, sinon la première par nom logique.
AssociatedLa sous-grille des enregistrements associés. Réservée — rien ne l’affiche encore.

Un contrôle de recherche qui ne nomme aucune vue en résout une automatiquement : la vue Lookup par défaut de la table cible, sinon sa vue Public par défaut réduite à ses trois premières colonnes, sinon le seul champ principal de la table. Une recherche sans vue QuickFind ne porte que sur le champ principal. Les colonnes de recherche doivent être des champs texte, car la correspondance est un « contient » insensible à la casse.

calendar (une vue qui s’affiche sous forme de calendrier)​

Une vue dotée d’un bloc calendar dessine ses enregistrements placés sur une feuille de jour, de semaine ou de mois — selon deux de ses propres champs de date — au lieu d’une grille. Son absence signifie la grille, exactement comme pour hierarchy, de sorte que toute vue stockée reste valide. Une vue qui porte les deux blocs est refusée : une vue se dessine d’une seule manière.

C’est une correspondance, pas un modèle de données. Il n’y a ni table de réservation ni type de rendez-vous : toute table comportant une date peut être disposée sur un calendrier, et c’est au créateur de dire laquelle de ses dates signifie « commence ».

ChampTypeObligatoireRemarques
startstringouiLe champ Date et heure auquel un bloc est placé. Le seul rôle obligatoire : un enregistrement sans début ne peut pas être placé sur une feuille, il n’y a donc aucune solution de repli. Un champ système est autorisé — created_at_utc dispose les enregistrements selon leur date d’arrivée.
endstringnonLe champ Date et heure auquel un bloc se termine. Son absence convient à une table qui enregistre un instant plutôt qu’une durée, et donne à chaque bloc une longueur de defaultDurationMinutes — et non zéro, car un bloc sans hauteur ne peut pas être cliqué.
titlestringnonLe champ d’où provient la première ligne du bloc. Son absence signifie le champ principal de la table, ce qu’affichent déjà une grille, un panneau de recherche et un fil d’Ariane.
categorystringnonUn champ Choix, État ou Raison dont les options colorent les blocs et remplissent la légende.
bookedForstringnonLe champ qui indique pour qui est le créneau, affiché discrètement sous le titre. N’importe quel type : une recherche se résout en nom de l’enregistrement cible.
notestringnonLe champ affiché sur un bloc assez haut pour une troisième ligne, et sinon dans son info-bulle.
defaultScalestringnonLa feuille sur laquelle la vue s’ouvre : Day, Week (par défaut) ou Month.
startHourintegernonLa première heure affichée par les feuilles de jour et de semaine, 0–23. 0 par défaut.
endHourintegernonL’heure à laquelle ces feuilles se terminent, 1–24, et supérieure à startHour. 24 par défaut.
defaultDurationMinutesintegernonLa durée d’un créneau lorsque le lecteur clique sur un créneau vide — celle avec laquelle arrive le nouvel enregistrement — et la hauteur de chaque bloc sur une vue qui n’associe aucun end. Au moins 1 ; 60 par défaut.

🔴 start et end doivent être des champs Date et heure, et category doit porter des couleurs. Les deux sont refusés à l’enregistrement, car tous deux échouent en silence à l’écran : un start qui est une colonne texte dessine une feuille vide, qui se lit comme « rien n’est réservé cette semaine » — la seule conclusion sur laquelle un lecteur agira et qu’il ne peut pas vérifier. La couleur réside sur les options mêmes du choix, ce qui permet de dire une seule fois « Examen est ambre » et que le calendrier, une cellule de grille et un graphique le lisent tous de la même façon.

startHour et endHour font la différence entre une feuille de réservation utilisable et une feuille qui s’ouvre aux deux tiers vide : une clinique ouverte de 8 h à 19 h ne veut pas seize lignes de nuit. Ils indiquent où la feuille s’ouvre — le lecteur peut toujours changer d’échelle et restreindre les heures depuis l’en-tête de la feuille, car la fenêtre lui appartient plutôt qu’au créateur.

Il n’y a volontairement pas de rôle resource. Les feuilles disposent les jours en colonnes : un champ désignant la colonne à laquelle appartient un bloc serait une correspondance qu’un créateur pourrait établir pour ensuite la voir ne rien faire. Il arrivera avec l’axe qui le dessine.

hierarchy (une vue qui s’affiche sous forme d’arbre)​

Une vue dotée d’un bloc hierarchy dessine ses enregistrements imbriqués selon une recherche — un organigramme avec les personnes de chaque unité, une arborescence de catégories, une nomenclature — au lieu d’une grille. Son absence signifie la grille qu’ont toujours été les vues, et c’est pourquoi toute vue stockée reste valide.

Un arbre sert à la navigation : les lignes sont récupérées par fenêtre, de sorte qu’un organigramme de cinquante mille personnes s’ouvre sans en charger aucune.

ChampTypeObligatoireRemarques
nodeTypesarrayouiChaque sorte de nœud que l’arbre peut dessiner. Au moins une.
orderarraynonL’ordre dans lequel les segments sous un nœud sont dessinés, par id de type de nœud. Son absence signifie l’ordre de déclaration.
rootPickerbooleannonIndique si un lecteur peut centrer l’arbre sur un nœud — l’ouvrir sur une ville plutôt que sur toute l’organisation.
expandRootsbooleannonIndique si le premier niveau se déplie au chargement. true par défaut.

Chaque entrée de nodeTypes :

ChampTypeObligatoireRemarques
idstringouiLe nom de ce type au sein du bloc — unit, person. Unique ici, et c’est à lui que se réfèrent order et chaque childOf.of. Une même table peut apparaître deux fois dans un organigramme, c’est pourquoi il s’agit du mot propre au créateur plutôt que d’un nom de table.
entitystringouiLa table dont ces nœuds sont des enregistrements.
childOfobjectouiLa façon dont ce type se rattache à son parent — voir ci-dessous.
labelstringnonLe champ dont la valeur constitue la ligne du nœud. Son absence signifie le champ principal de la table.
secondarystringnonLe champ affiché discrètement après le libellé. Son absence signifie le champ secondaire propre à la table ; une chaîne vide signifie aucun — sur une unité, le nom du parent est la ligne juste au-dessus, un organigramme est donc un endroit où la seconde ligne par défaut d’une table est erronée.
iconstringnonLe glyphe de la ligne. Son absence signifie l’icône propre à la table.
imagebooleannonIndique si la ligne porte l’image de l’enregistrement.
detailobjectnonCe qui remplit le volet à côté de l’organigramme lorsqu’un nœud est sélectionné. Son absence signifie le formulaire principal de la table.

childOf prend un field — la recherche de la table de ce type qui contient l’enregistrement parent — et un of facultatif, le type de nœud auquel il se rattache, par id.

🔴 Exactement un type de nœud omet of. Celui-là est la table même de l’arbre imbriquée en elle-même, et ses enregistrements au parent vide forment le niveau supérieur de l’organigramme ; chaque autre type nomme ce à quoi il se rattache. Les nœuds hétérogènes sont le cas général et non un ajout : les unités, puis les personnes qu’elles contiennent relève du même mécanisme que province → ville → agence modélisé en trois tables.

La recherche nommée par childOf.field doit cibler la table du type parent — sa propre table, pour le type racine. Une recherche pointant ailleurs ne décrit pas une imbrication, et est refusée à l’enregistrement plutôt que d’afficher un niveau sans rien en dessous.

detail prend un kind valant Form (le formulaire propre à la table, enregistré via le chemin d’écriture du formulaire d’enregistrement), Card (une vue Carte disposée pour être lue plutôt que saisie, ce que l’on veut généralement pour une personne sous une unité) ou None (pour un type qui n’est jamais qu’une structure), plus un name facultatif indiquant quel formulaire ou quelle vue Carte.

columnProperties (comment une colonne est présentée)​

Une liste clairsemée : seules les colonnes configurées par un créateur y figurent, et une colonne sans entrée s’affiche à partir des seules métadonnées de son champ. Elle se place à côté de columns plutôt que de transformer celle-ci en liste d’objets, afin que toute définition v1 reste valide et que tout lecteur qui n’a besoin de savoir que quelles colonnes a une vue ne soit pas affecté.

ChampTypeObligatoireRemarques
fieldstringouiLa colonne que configure l’entrée. Doit faire partie des columns de la vue.
labelstring | nullnonRemplacement de l’en-tête. En son absence, le nom d’affichage du champ est utilisé.
widthinteger | nullnonLargeur en pixels, 40–1200. En son absence, la colonne se dimensionne elle-même.
formatstring | nullnonFormat de la valeur. Pour une colonne DateTime, le même jeu de jetons que celui qu’acceptent les contrôles de date du formulaire (yyyy, yy, MM, dd, HH, mm, ss) — un seul vocabulaire de mise en forme dans tout le produit.
alignstring | nullnonstart, center ou end. Logique, et non gauche/droite, afin de suivre le sens de lecture (§6.13.6).
controlTypestring | nullnonLe contrôle avec lequel la colonne s’affiche — un glyphe d’interrupteur pour un booléen, une date persane pour une date.

controlType prend Text, TextArea, Check, Toggle, Date, DateTime, Time, PersianDate, PersianDateTime, PersianTime, Lookup, PolymorphicLookup, Dropdown ou Label. En son absence, il hérite de la valeur par défaut du champ, puis de celle du type de données.

🔴 Il est toujours affiché en lecture seule. Une grille n’a pas de modification en ligne : un interrupteur y montre donc un état au lieu de réagir à un clic. C’est aussi le seul moyen d’afficher une colonne en calendrier jalali chez un locataire grégorien, puisque format est un motif sans calendrier associé.

commandOverrides (modifier une commande détenue par la plateforme)​

Ce que cette vue modifie dans les commandes intégrées — Nouveau, Modifier, Supprimer, Actualiser, Enregistrer, Enregistrer et fermer, Épingler. Son absence ne change rien, ce que signifie chaque vue conçue avant l’existence de cette fonction.

ChampTypeObligatoireRemarques
commandstringouiL’id stable de la commande remplacée.
labelstringnonRemplace le libellé de la plateforme. Son absence le conserve — y compris ses traductions, qu’un remplacement saisi perd nécessairement.
iconstringnonRemplace le glyphe de la plateforme.
initiallyHiddenbooleannonIndique si la commande est masquée au départ.
initiallyDisabledbooleannonIndique si la commande est désactivée au départ.

🔴 Indexé par un id de commande stable, jamais par libellé ni par position. L’id est le nom propre de la plateforme et ne change pas quand le libellé change : un remplacement ne peut donc pas se détacher de ce qu’il remplace dès que quelqu’un le modifie — et une commande intégrée peut être renommée ou retirée plus tard sans que chaque document stocké doive être réconcilié, puisqu’un remplacement nommant une commande qui n’existe plus est simplement ignoré.

🔴 Un créateur peut masquer et désactiver, jamais afficher ni activer. Le Player masque Nouveau pour qui ne peut pas créer et désactive Supprimer lorsque rien n’est sélectionné ; un remplacement capable d’annuler cela construirait une barre proposant ce que le serveur refusera.

« Au départ » dit tout. C’est l’état dans lequel la barre s’ouvre, et non une condition permanente — une règle métier ou le propre script de la commande peut l’afficher ensuite. Une commande qui ne doit jamais apparaître pour quelqu’un ne relève pas de ce mécanisme : c’est une autorisation, décidée sur le serveur, là où un navigateur ne peut pas la contester.

commandOrder (une barre, un ordre)​

Les commandes intégrées et celles du créateur, entremêlées comme le créateur les a disposées, par id.

Une liste explicite plutôt qu’un rang sur chaque commande, car un rang doit être réécrit sur chaque commande dès que l’une d’elles bouge, et deux commandes peuvent avoir le même — une égalité que le moteur de rendu départagerait alors autrement que le concepteur.

🔴 Tout ce que cette liste ne mentionne pas conserve sa place naturelle, à la fin. C’est ce qui permet à la règle de résister au temps : une commande intégrée ajoutée à la plateforme l’an prochain, ou une commande ajoutée par une mise à niveau, apparaît au lieu de disparaître parce qu’un ordre stocké lui est antérieur. Un id désignant quelque chose qui n’existe plus est ignoré.

rowSelection (si les lignes portent une case à cocher)​

true par défaut, et ce que signifie chaque vue conçue avant l’existence de cette fonction : la grille reçoit son en-tête « tout sélectionner » et une case par ligne, ce sur quoi agit la barre de commandes.

false convient à une vue qui n’est jamais que lue — une liste depuis laquelle personne ne supprime ni ne réaffecte — où une case à cocher offre une sélection multiple dont la surface n’a pas l’usage et coûte une colonne de largeur.

filterGroup (ET/OU hiérarchique)​

Un filterGroup est un nœud récursif qui combine ses membres avec un connector :

ChampTypeObligatoireRemarques
connectorstringouiAnd (tous les membres correspondent) ou Or (au moins un membre correspond).
conditionsarraynonConditions feuilles (field, operator, value) de ce groupe.
groupsarraynonSous-groupes imbriqués (même forme), pour une imbrication ET/OU arbitraire.

Exemple​

{
"logicalName": "par_invoice_active",
"displayName": "Active Invoices",
"entity": "par_invoice",
"viewType": "Public",
"columns": ["par_name", "par_total"],
"filters": [ { "field": "par_total", "operator": "GreaterThan", "value": 0 } ],
"filterGroup": {
"connector": "And",
"conditions": [ { "field": "par_name", "operator": "Contains", "value": "INV" } ],
"groups": [
{
"connector": "Or",
"conditions": [
{ "field": "par_total", "operator": "GreaterThan", "value": 1000 },
{ "field": "par_total", "operator": "IsNull" }
]
}
]
},
"sorts": [ { "field": "par_name", "descending": false } ]
}

Exemple — une vue de recherche​

{
"logicalName": "par_contact_pick",
"displayName": "Contact Lookup",
"entity": "par_contact",
"viewType": "Lookup",
"columns": ["par_name", "par_email", "par_city"],
"sorts": [ { "field": "par_name", "descending": false } ]
}

Exemple — une vue de recherche rapide​

Seul columns est lu : ce sont les colonnes sur lesquelles porte une recherche saisie.

{
"logicalName": "par_contact_find",
"displayName": "Contact Quick Find",
"entity": "par_contact",
"viewType": "QuickFind",
"columns": ["par_name", "par_email", "par_accountnumber"]
}