Aller au contenu principal

Définition d’application Model-Driven

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

La représentation canonique d’une application pilotée par modèle (section 6.7) — une application nommée qui regroupe un sous-ensemble choisi des tables, tableaux de bord et rapports de l’environnement dans une navigation (plan de site) dotée d’une page d’accueil, comme le fait une application pilotée par modèle Power Apps. Validée de manière identique, qu’elle provienne du concepteur, d’un appel d’API, d’un assistant IA ou d’une importation de solution.

Structure​

ChampTypeObligatoireRemarques
logicalNamestringouiPréfixé par l’éditeur, en snake-case minuscule (par exemple par_sales_app).
displayNamestringouiNom lisible de l’application, affiché sur sa vignette de lancement.
publisherPrefixstringouiLe préfixe de l’éditeur propriétaire ; le nom logique doit commencer par lui.
descriptionstringnonBrève description affichée sur la vignette de lancement.
iconstringnonClé d’icône pour la vignette de lancement et l’en-tête du rail de l’application.
supportsTasksbooleannonIndique si l’application participe à des processus métier. Activé, le Shell propose la liste des tâches et le bouton Décider lorsque l’application est ouverte ; désactivé, il n’affiche ni l’un ni l’autre. La valeur par défaut est désactivé, car la plupart des applications ne font partie d’aucun processus, et une boîte de réception sur l’une d’elles ne serait qu’un habillage toujours vide.
homedestinationouiCe qui s’ouvre à /apps/{id} ; doit figurer dans navigation. Voir ci-dessous.
navigationarrayouiUn ou plusieurs groupes de navigation (le plan de site ; voir ci-dessous).
includesarraynonLes composants de l’application : ce qu’elle peut ouvrir et qui ne figure pas sur son plan de site. Voir ci-dessous.

Destination​

Un endroit où l’application peut aller — une seule forme, utilisée pour un élément de navigation et pour home. C’est délibéré et non fortuit : « la page d’accueil doit être un endroit où mène la navigation » devient alors la comparaison de deux valeurs du même type, au lieu de trois vérifications presque identiques qui pourraient diverger une sorte après l’autre.

ChampTypeObligatoireRemarques
typeEntity | Dashboard | ReportouiLes trois choses que le Player peut afficher à l’écran : une grille, un hôte de tableau de bord, une visionneuse de rapport.
targetstringouiLe nom logique de la destination. Le magasin dans lequel elle doit exister est déterminé par type.

Groupe de navigation​

ChampTypeObligatoireRemarques
titlestringouiTitre du groupe, affiché dans la navigation de gauche de l’application.
itemsarrayouiUn ou plusieurs éléments de navigation (voir ci-dessous).

Élément de navigation​

Une destination, plus la manière dont l’application veut la libeller. Les remplacements de libellé et d’icône s’appliquent à toutes les sortes — une application qui appelle la table Accounts « Clients » a la même raison d’appeler un tableau de bord « Aujourd’hui ».

ChampTypeObligatoireRemarques
typeEntity | Dashboard | ReportouiCe qu’ouvre cet élément.
targetstringouiSon nom logique (doit exister dans l’environnement, en tant que chose de cette sorte).
displayNamestringnonRemplacement du libellé pour le rail de cette application ; à défaut, le nom d’affichage propre au composant est utilisé.
iconstringnonClé d’icône de l’élément du rail.
formsarray of stringnonÉléments de table uniquement. Les formulaires de cette table que propose cette application, par nom logique. Voir ci-dessous.
viewsarray of stringnonÉléments de table uniquement. Les vues de cette table que propose cette application, par nom logique.

Chaque destination référencée — dans un élément de navigation et dans home — doit exister dans l’environnement dans le magasin que désigne sa propre sorte, et home doit correspondre à l’un des éléments de navigation à la fois par type et par target. Ces deux règles sont appliquées à l’enregistrement, en plus de la validation du schéma (modelapps.app.unknown_entity, modelapps.app.unknown_dashboard, modelapps.app.unknown_report, modelapps.app.home_not_in_navigation).

forms et views sur un élément Dashboard ou Report sont refusés, et non ignorés (modelapps.app.component_selection_not_allowed) : aucun des deux n’a de formulaires ni de vues, une sélection à cet endroit est donc une erreur de conception qui, sinon, disparaîtrait en silence et laisserait son auteur croire qu’il a restreint quelque chose.

Qui peut en ouvrir un​

Ouvrir un tableau de bord et exécuter un rapport sont des autorisations accordées sur ce composant — des permissions nommées <logicalName>.Open et <logicalName>.Run, détenues par un rôle de sécurité comme n’importe quelle autre, avec *.Open / *.Run comme jokers couvrant tout ce qui sera construit ensuite. Placer l’un d’eux dans un plan de site ne l’accorde pas. Ce que lisent ensuite les widgets du tableau de bord et les jeux de données du rapport est de toute façon autorisé séparément : un utilisateur qui atteint un tableau de bord dont il n’a pas les données voit des widgets vides plutôt que les chiffres de quelqu’un d’autre.

Sélection des composants — forms et views​

Une table accumule des formulaires et des vues au fil de sa vie : un formulaire d’administration à côté de celui qu’utilise un commercial, une vue « Mes éléments ouverts » qui ne compte que pour une équipe. Que chaque application les affiche tous, c’est ainsi qu’une table propre devient une application encombrée ; un élément de navigation peut donc nommer ceux que propose son application.

L’absence et un tableau vide ne sont pas la même chose, et ni l’une ni l’autre ne signifie « tout coché ».

ValeurSignification
clé absenteTous les formulaires/vues de la table, y compris ceux ajoutés plus tard. La valeur par défaut pour une table qui vient d’être placée dans une application, et ce que signifie chaque application conçue avant l’existence de cette fonction.
une listeUn choix fermé. Un formulaire ajouté ensuite à la table n’apparaît pas dans cette application tant qu’il n’est pas listé.
[]Invalide. Il ne peut pas signifier « tout » (c’est le rôle de l’absence) et ne doit pas signifier « aucun » — une table sans formulaire ne peut pas être ouverte.

Chaque nom listé doit être un formulaire ou une vue de cette table, ce qui est vérifié à l’enregistrement (modelapps.app.unknown_component). Un nom mal saisi mérite un échec plutôt qu’être ignoré : sinon, il restreindrait silencieusement l’application à moins de formulaires que l’auteur n’en avait choisi, et l’application semblerait correcte jusqu’à ce qu’un utilisateur tombe sur une table impossible à ouvrir.

La liste ne décide que de l’appartenance, jamais de l’ordre — l’exécution conserve l’ordre propre à la table et sa propre valeur par défaut, lorsque celle-ci survit à la sélection. Ordonner les vues d’une table au sein d’une application est une fonctionnalité distincte, et ce n’est pas celle-ci.

Page incluse — includes​

La navigation dit ce qu’une application affiche ; includes dit ce qu’elle contient, et une application contient plus qu’elle n’affiche. Un processus ouvre un formulaire d’une table que personne ne parcourt ; une commande conçue ouvre un tableau de bord délibérément tenu à l’écart du rail ; un rapport s’atteint depuis un enregistrement et jamais depuis la navigation. Sans cette liste, chacune de ces destinations serait inaccessible, ou chaque application devrait afficher tout ce qu’elle pourrait jamais ouvrir.

ChampTypeObligatoireRemarques
typeEntity | Dashboard | Report | StudioAppouiLa sorte de chose dont il s’agit.
targetstringouiSon nom logique.
formsarray | nullnonTables uniquement. Les formulaires de cette table que l’application peut ouvrir, par nom logique — la même règle que pour un élément de navigation.
viewsarray | nullnonTables uniquement. Les vues de cette table que l’application peut ouvrir. Même règle que forms.

forms et views suivent exactement la règle de Sélection des composants : l’absence signifie tous, une liste est un choix fermé, et un tableau vide est invalide.

Exemple​

{
"logicalName": "par_sales_app",
"displayName": "Sales",
"publisherPrefix": "par",
"description": "Manage accounts and invoices",
"icon": "briefcase",
"home": { "type": "Dashboard", "target": "par_sales_overview" },
"navigation": [
{
"title": "Sales",
"items": [
{ "type": "Dashboard", "target": "par_sales_overview", "displayName": "Overview", "icon": "gauge" },
{ "type": "Entity", "target": "par_account", "displayName": "Accounts", "icon": "users" },
{
"type": "Entity",
"target": "par_invoice",
"forms": ["par_invoice_main"],
"views": ["par_invoice_active", "par_invoice_overdue"]
},
{ "type": "Entity", "target": "par_contact" },
{ "type": "Report", "target": "par_invoice_print", "displayName": "Print invoices" }
]
}
]
}

Cette application s’ouvre sur son tableau de bord plutôt que sur une grille de lignes, ce à quoi sert un home qui n’est pas une table. par_invoice est sélectionnée — l’application propose l’un de ses formulaires et deux de ses vues, et une vue ajoutée demain à la table n’apparaîtra pas ici. par_account et par_contact ne nomment aucune sélection : l’application propose donc tout ce que ces tables ont, maintenant comme plus tard.