Naar hoofdinhoud gaan

Definitie van een modelgestuurde app

Schema-id: model-driven-app@1 Machineleesbaar schema: model-driven-app.schema.json

De canonieke weergave van een modelgestuurde app (sectie 6.7) — een app met een naam die een zorgvuldig gekozen deel van de tabellen, dashboards en rapporten van de omgeving groepeert in een navigatie (siteoverzicht) met een startpagina, zoals een modelgestuurde app in Power Apps dat doet. Wordt op dezelfde manier gevalideerd, of hij nu uit de ontwerper komt, uit een API-aanroep, van een AI-assistent of uit een oplossingsimport.

Structuur​

VeldTypeVerplichtOpmerkingen
logicalNametekenreeksjaMet uitgeversvoorvoegsel, in kleine letters snake_case (bijvoorbeeld par_sales_app).
displayNametekenreeksjaLeesbare naam van de app, getoond op de tegel in het startscherm.
publisherPrefixtekenreeksjaHet voorvoegsel van de eigenaar-uitgever; de logische naam moet ermee beginnen.
descriptiontekenreeksneeKorte beschrijving, getoond op de tegel in het startscherm.
icontekenreeksneePictogramsleutel voor de tegel en de kop van de navigatiebalk van de app.
supportsTasksbooleaansneeOf deze app meedoet aan bedrijfsprocessen. Staat het aan, dan biedt de shell de takenlijst en de knop Beslissen aan zolang de app open is; staat het uit, dan tekent hij geen van beide. Uit is de standaard, omdat de meeste apps geen deel uitmaken van een proces en een inbox in zo'n app omlijsting is waar nooit iets in staat.
homebestemmingjaWat er opent op /apps/{id}; moet in navigation voorkomen. Zie hieronder.
navigationarrayjaEen of meer navigatiegroepen (het siteoverzicht; zie hieronder).
includesarrayneeDe componenten van de app: dingen die hij kan openen maar die niet in zijn siteoverzicht staan. Zie hieronder.

Bestemming​

Een plek waar de app naartoe kan — één vorm, gebruikt voor een navigatie-item en voor home. Dat is een bewuste keuze en geen toeval: "home moet een plek zijn waar de navigatie naartoe gaat" wordt dan een vergelijking van twee waarden van hetzelfde type, in plaats van drie bijna identieke controles die per soort uit elkaar kunnen groeien.

VeldTypeVerplichtOpmerkingen
typeEntity | Dashboard | ReportjaDe drie dingen die de Player op een scherm kan zetten: een raster, een dashboardhost, een rapportviewer.
targettekenreeksjaDe logische naam van de bestemming. In welke opslag die moet bestaan, bepaalt type.
VeldTypeVerplichtOpmerkingen
titletekenreeksjaGroepskop in de linkernavigatie van de app.
itemsarrayjaEen of meer navigatie-items (zie hieronder).

Een bestemming, plus hoe deze app die wil laten benoemen. Het overschrijven van label en pictogram geldt voor elke soort — een app die de tabel Accounts "Klanten" noemt, heeft dezelfde reden om een dashboard "Vandaag" te noemen.

VeldTypeVerplichtOpmerkingen
typeEntity | Dashboard | ReportjaWat dit item opent.
targettekenreeksjaDe logische naam ervan (moet in de omgeving bestaan, als dat soort ding).
displayNametekenreeksneeLabel dat het label in de navigatiebalk van deze app overschrijft; zonder dit wordt de eigen weergavenaam van de component gebruikt.
icontekenreeksneePictogramsleutel voor het item in de navigatiebalk.
formsarray van tekenreeksenneeAlleen voor Entity-items. De formulieren van deze tabel die deze app aanbiedt, op logische naam. Zie hieronder.
viewsarray van tekenreeksenneeAlleen voor Entity-items. De weergaven van deze tabel die deze app aanbiedt, op logische naam.

Elke bestemming waarnaar wordt verwezen — in een navigatie-item en in home — moet in de omgeving bestaan in de opslag die haar eigen soort noemt, en home moet met een van de navigatie-items overeenkomen op zowel type als target. Beide worden bij het opslaan afgedwongen, naast de schemavalidatie (modelapps.app.unknown_entity, modelapps.app.unknown_dashboard, modelapps.app.unknown_report, modelapps.app.home_not_in_navigation).

forms en views op een item van het type Dashboard of Report worden geweigerd, niet genegeerd (modelapps.app.component_selection_not_allowed): geen van beide heeft formulieren of weergaven, dus een selectie daar is een fout van de auteur die anders ongemerkt zou verdwijnen en de auteur in de veronderstelling zou laten dat hij iets had ingeperkt.

Wie er een mag openen​

Een dashboard openen en een rapport uitvoeren zijn rechten op die component — rechten met de naam <logicalName>.Open en <logicalName>.Run, toegekend via een beveiligingsrol zoals elk ander recht, met *.Open / *.Run als jokers die alles blijven dekken wat hierna wordt gebouwd. Er een in een siteoverzicht plaatsen, kent het recht niet toe. Wat de widgets van het dashboard en de datasets van het rapport vervolgens lezen, wordt hoe dan ook zelfstandig geautoriseerd, dus een gebruiker die een dashboard bereikt waarvoor hij geen gegevens heeft, ziet lege widgets in plaats van de cijfers van iemand anders.

Componentselectie — forms en views​

Een tabel verzamelt in de loop van zijn leven formulieren en weergaven: een beheerdersformulier naast het formulier dat een verkoper gebruikt, een weergave "Mijn open items" die voor één team belangrijk is. Als elke app ze allemaal toont, wordt een nette tabel een rommelige app, dus een navigatie-item mag noemen welke zijn app aanbiedt.

Afwezigheid en een lege array zijn niet hetzelfde, en "alles aangevinkt" is ook iets anders.

WaardeBetekenis
sleutel afwezigElk formulier/elke weergave van de tabel, inclusief die later worden toegevoegd. De standaard voor een tabel die net in een app is geplaatst, en wat elke app betekent die is gemaakt voordat dit bestond.
een lijstEen gesloten keuze. Een formulier dat later aan de tabel wordt toegevoegd, verschijnt niet in deze app totdat het in de lijst staat.
[]Ongeldig. Het kan niet "alles" betekenen (dat doet afwezigheid) en mag niet "niets" betekenen — een tabel zonder formulier kan niet worden geopend.

Elke genoemde naam moet een formulier/weergave van die tabel zijn; dat wordt bij het opslaan gecontroleerd (modelapps.app.unknown_component). Een verkeerd getypte naam is het waard om op te falen in plaats van hem te negeren: anders zou hij de app ongemerkt beperken tot minder formulieren dan de auteur koos, en zou de app er correct uitzien totdat een gebruiker een tabel tegenkwam die hij niet kon openen.

De lijst bepaalt alleen het lidmaatschap, nooit de volgorde — de runtime behoudt de eigen volgorde van de tabel en haar eigen standaard, voor zover die standaard de selectie overleeft. De weergaven van een tabel binnen een app ordenen is een aparte mogelijkheid, en dit is die niet.

Opgenomen pagina — includes​

De navigatie zegt wat een app toont; includes zegt wat hij bevat, en een app bevat meer dan hij toont. Een proces opent een formulier van een tabel waar niemand doorheen bladert; een ontworpen opdracht opent een dashboard dat bewust uit de navigatiebalk is gehouden; een rapport wordt bereikt vanuit een record en nooit vanuit de navigatie. Zonder deze lijst zou elke zulke bestemming onbereikbaar zijn, of zou elke app alles moeten tonen wat hij ooit zou kunnen openen.

VeldTypeVerplichtOpmerkingen
typeEntity | Dashboard | Report | StudioAppjaWat voor soort ding dit is.
targettekenreeksjaDe logische naam ervan.
formsarray | nullneeAlleen voor tabellen. De formulieren van deze tabel die de app mag openen, op logische naam — dezelfde regel als bij een navigatie-item.
viewsarray | nullneeAlleen voor tabellen. De weergaven van deze tabel die de app mag openen. Dezelfde regel als bij forms.

forms en views volgen precies de regel in Componentselectie: afwezig betekent allemaal, een lijst is een gesloten keuze, en een lege array is ongeldig.

Voorbeeld​

{
"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" }
]
}
]
}

Deze app opent op zijn dashboard in plaats van op een raster met rijen, en daar is een home die geen tabel is voor bedoeld. par_invoice is een zorgvuldige selectie — de app biedt een van de formulieren en twee van de weergaven aan, en een weergave die morgen aan de tabel wordt toegevoegd, verschijnt hier niet. par_account en par_contact noemen geen selectie, dus de app biedt alles aan wat die tabellen hebben, nu en later.