Updated billing contact Q4 business review summary Afficher plus Delivery schedule Re: Question about the November order Question about the November order Renewal kickoff
Le Timeline composant affiche des lignes de plusieurs tableaux en une seule liste, la plus récente en premier : par défaut les notes d’un enregistrement, les communications par portail et d’autres activités. Mettez-le dans un RecordContext et il liste les lignes concernant cet enregistrement : qui a écrit chaque enregistrement et quand, son corps en texte enrichi réduit à quelques lignes jusqu’à Afficher plus, et sa pièce jointe à télécharger. Il lit page par page, avec Charger plus pour le reste et Rafraîchir pour la relire. La recherche fonctionne comme une grille : le texte correspond au début d’un sujet ou d’un texte, ou n’importe où après un début *, et un jour ou une année, avec >, <, >= ou <= avant, trouve les lignes de ces jours. Avec plus d’un tableau, un menu à côté de la recherche choisit lequel afficher.
<RecordContext table="account" queryParameterName="id">
<Timeline />
</RecordContext><RecordContext TableName="account" QueryParameterName="id">
<Timeline />
</RecordContext>Les notes, messages et rendez-vous concernant Schmeler and Sons, le compte que montre la démo de la page de détail du compte. Une de ses notes est interne — son texte ne commence pas par *WEB* — donc elle n’est pas listée. Choisissez les tableaux qu’il affiche, ou affinez-les avec des filtres d’édition (AllowFiltering), dans le menu Filtre, et connectez-vous pour les enregistrer là-bas en tant que vue de votre propre profil (AllowSavedViews).
Une note n’arrive au portail que lorsque son texte commence par *WEB*, afin que le personnel puisse conserver des notes internes sur les dossiers que les clients voient. Les appels téléphoniques, tâches et autres activités suivent la même règle dans leur description, sauf les types non filtrés — communications par portail, par défaut. Le serveur applique cela à toutes les requêtes, grilles et jointures incluses, donc aucune règle d’accès à la table ne peut l’élargir. Le portail n’affiche jamais le préfixe, et l’ajoute à une note ou activité créée via le portail. Une note dont le titre nomme son auteur est Note created on … by Name [contact:id] affichée comme écrite par ce contact. Configuré SecurityOptions.PortalVisibility.Prefix pour utiliser un autre préfixe, ou pour null afficher chaque note et activité, et ajouter un tableau pour UnfilteredActivities afficher chaque activité. Le personnel connecté au portail en tant que lui-même fait exception : ils voient chaque note et activité que leurs rôles de sécurité leur permettent de lire, comme dans Dynamics, avec son texte tel que stocké, ils ajoutent donc eux-mêmes le préfixe à une note destinée au portail.
builder.Services.Configure<SecurityOptions>(options =>
{
// Les notes et activités arrivent au portail lorsque leur texte commence par *PORTAL*.
options.PortalVisibility.Prefix = "*PORTAL*";
// Chaque e-mail que l’utilisateur peut lire atteint le portail : les e-mails ne peuvent pas porter le préfixe.
options.PortalVisibility.UnfilteredActivities.Add("email");
});
Les emails ne peuvent pas être marqués avec le préfixe. Le corps d’un email est écrit par le client mail qui l’a envoyé, comme un document HTML complet, donc le préfixe n’est jamais son premier texte, et aucun email n’atteint le portail par son préfixe. Ajouter email à UnfilteredActivities est la seule façon d’afficher les emails, et il affiche chaque email que l’utilisateur peut lire sur un enregistrement — y compris les internes.
Une communication par portail (ppp_portalcommunication) est une activité dans la solution Power Portals Pro pour les messages entre un utilisateur du portail et son personnel. Elle est destinée au portail, elle n’a donc pas besoin de préfixe. Son message indique qui l’a écrite : le contact de l’utilisateur du portail, ou le membre du personnel qui a répondu, avec le contact dans To. Le message est en texte enrichi et peut contenir une pièce jointe.
La chronologie ne liste que ce que l’utilisateur peut lire : chaque type d’élément doit être lu sur sa table, et un utilisateur qui ne peut lire aucun ne voit aucune ligne du temps. Une note pointe vers son enregistrement via objectid et une communication par portail via regardingobjectid, donc la règle habituelle permet à un utilisateur de lire les éléments concernant les enregistrements qu’il peut atteindre, avec RowsViaParent. Garde cette recherche parmi les colonnes qu’il peut lire : la chronologie demande les éléments concernant son enregistrement via celle-ci, et une condition sur une colonne qu’un utilisateur ne peut pas lire est supprimée, ce qui listerait les éléments de chaque enregistrement atteint.
// Les utilisateurs lisent les notes et messages concernant le compte de leur propre entreprise.
builder.Services.AddTableAccess("annotation", t => t
.ForSignedInUsers()
.RowsViaParent("objectid", "account", parent => parent.RowsOfTheirAccount("accountid"))
.Allow(TableSecurityPermission.Read)
.ReadingAllColumns());
builder.Services.AddTableAccess("ppp_portalcommunication", t => t
.ForSignedInUsers()
.RowsViaParent("regardingobjectid", "account", parent => parent.RowsOfTheirAccount("accountid"))
.Allow(TableSecurityPermission.Read)
.ReadingAllColumns());
L’utilisateur de l’application du portail doit également lire les deux tables dans Dataverse. Les notes doivent être lues sur la table de notes. Dataverse accorde à chaque type d’activité un seul ensemble de privilèges, de sorte que les communications par portail sont couvertes par les activités de lecture que le rôle d’utilisateur d’application Power Portals Pro détient déjà. Pour que les utilisateurs modifient ou suppriment des notes et des messages, il faut aussi Écrire et supprimer sur la table de notes et Supprimer sur les activités, ce qui ne tient pas.
Un utilisateur qui peut créer des communications par portail reçoit Nouveau message : un sujet, un message enrichi et une pièce jointe, concernant l’enregistrement sur lequel se trouve la timeline, et celui qui peut créer des notes reçoit une nouvelle note. CreatableTables Nomme les tables sur lesquelles une nouvelle ligne peut être écrite, notes et communications par portail par défaut ; une note ou un message est écrit en place, la ligne d’une autre table dans un panneau latéral. C’est une forme à part, sauvegardée séparément de la page autour. Le serveur envoie le message de l’utilisateur, quoi que soit la demande, donc un utilisateur ne peut pas écrire comme un autre. Accordez-lui un accès à table : OwnedBy("from") envoie un nouveau message de son auteur, et RowsForWriting permet RowsOwnedByContact("from") aux utilisateurs de ne modifier ou supprimer que ce qu’ils ont envoyé. En omettant Écrire et Supprimer, un message reste tel qu’il a été envoyé. La timeline propose Modifier et Supprimer à chaque ligne où l’accès de l’utilisateur lui permet de modifier ou de supprimer, et le serveur juge chaque changement à nouveau lorsqu’il arrive. FormLocation (Réagir : formLocation) indique où s’ouvre la forme d’une autre table : un panneau latéral à droite, comme par défaut, ou à gauche, un dialogue au centre, ou Inline — en place dans la timeline, au fur et à mesure que les notes et messages sont écrits.
// Lisez chaque message concernant le compte de leur entreprise, écrivez-en de nouveaux, et modifiez ou supprimez le leur.
builder.Services.AddTableAccess("ppp_portalcommunication", t => t
.ForSignedInUsers()
.RowsViaParent("regardingobjectid", "account", parent => parent.RowsOfTheirAccount("accountid"))
.RowsForWriting(r => r.RowsOwnedByContact("from"))
.OwnedBy("from")
.Allow(TableSecurityPermission.Read | TableSecurityPermission.Create | TableSecurityPermission.Append
| TableSecurityPermission.Write | TableSecurityPermission.Delete)
.ReadingAllColumns()
.WritingOnCreate("regardingobjectid")
.Writing("subject", "description", "ppp_attachment"));
// Les messages des utilisateurs du portail vont dans une file d’attente plutôt qu’au propriétaire de l’enregistrement.
builder.Services.Configure<PortalCommunicationOptions>(options =>
{
options.Recipient = PortalCommunicationRecipient.Queue;
options.QueueId = new Guid("00000000-0000-0000-0000-000000000000");
});
Le personnel entend parler d’un nouveau message via PortalCommunicationOptions. Par défaut, il est adressé au propriétaire de l’enregistrement concerné, lorsque ce propriétaire est un utilisateur. Il peut aller dans une file d’attente, à laquelle l’utilisateur de l’application du portail doit accéder pour ajouter des éléments, ou à personne, ne laissant que le message sur la timeline de l’enregistrement.
Les notes et chaque table d’activités sont enregistrées sur le serveur pour les chronologies et calendriers, chacune datée selon ce que ses formulaires demandent : un rendez-vous au début, une tâche ou un appel téléphonique à la date d’échéance, un e-mail ou un message à la date de sa rédaction. Une chronologie liste toutes les tables enregistrées que l’utilisateur peut lire ; nommer celles qu’elle affiche dans Tables. Sur un enregistrement, elle liste les lignes à son sujet, ainsi que les activités auxquelles l’enregistrement participe en tant qu’expéditeur, destinataire ou participant. Le serveur affiche uniquement les notes et activités destinées au portail : celles dont le texte commence par *WEB*, ou chacune d’un type dans UnfilteredActivities. Les e-mails ne peuvent pas porter le préfixe, ils apparaissent donc uniquement lorsqu’ils email sont dans cette liste.
<Timeline tables={['annotation', 'ppp_portalcommunication', 'phonecall', 'email']} /><Timeline Tables="@(["annotation", "ppp_portalcommunication", "phonecall", "email"])" />Enregistrez votre propre tableau avec AddMultiTableSource: un titre, et ce qui est d’autre affiché, comme le texte, son propriétaire et ses destinataires, et la recherche vers l’enregistrement dont correspond une ligne. Ensuite, nommez chaque contrôle auquel il est destiné, avec les colonnes dont le contrôle a besoin : ForTimelines la date d’ordre de ses lignes, ForCalendars son début et, s’il les a, sa colonne de fin et de la journée entière, ForSearch, ainsi ForMaps que sa latitude et sa longitude. Ces colonnes sont toujours lues, quels que soient les noms de la requête d’une vue. Une inscription qui nomme une colonne que la table n’a pas, ou une de mauvais type, arrête le portail au démarrage et indique ce qui ne va pas. Enregistrer une table de notes ou d’activité ne change à nouveau que les noms de l’enregistrement. Une inscription n’accorde aucun accès : chaque table a toujours besoin d’un accès en lecture comme n’importe quelle table.
// Les dossiers sur les calendriers et les calendriers, datés selon leur ouverture.
builder.Services.AddMultiTableSource("incident", t => t
.Title("title")
.Body("description")
.Owner("ownerid")
.Regarding("customerid")
.ForTimelines(start: "createdon")
.ForCalendars(start: "createdon"));
// Les emails par moment d’envoi plutôt que par écrit.
builder.Services.AddMultiTableSource("email", t => t.ForTimelines(start: "senton"));
Une chronologie liste ses lignes les plus récentes en premier, puis à partir de maintenant. Upcoming (Réagir : upcoming) la commence aussi loin d’avance, donc ce qui apparaît apparaît d’abord sous son propre titre, et Ascending (Réagir : ascending) liste les lignes à partir de maintenant, le plus tôt : voir Éléments à venir. Pour dessiner les lignes d’une table à votre façon, ou les écrire sous vos propres formes, voir Rendu personnalisé.
<Timeline upcoming={{ days: 2 }} /><Timeline Upcoming="TimeSpan.FromDays(2)" />Donnez le choix aux vues de la timeline, car une grille possède : celles propres à Dataverse dans ViewIds, comme Mes appels téléphoniques ou Toutes les activités, des vues de plusieurs tables dans MultiTableViewIds, et des vues de vos propres vues dans CustomViewDefinitions, en DefaultViewId nommant celle affichée en premier. Avec deux vues ou plus, un sélecteur de vues remplace le titre. Une vue Dataverse liste activitypointer chaque table d’activité enregistrée, et sur un enregistrement, une vue liste les lignes concernant l’enregistrement qu’elle laisse passer. Avec (Réagir : allowSavedViews), un utilisateur connecté peut enregistrer les tables que la timeline affiche comme une vue propre, proposée à côté de AllowSavedViews la vôtre, et choisir sa vue par défaut et masquer celles qu’il n’utilise pas, depuis le menu Filtrage : voir Vues sauvegardées.
Une vue de vos propres liste les lignes d’une ou plusieurs tables. Donnez une requête FetchXML à une table, et ses filtres et jointures déterminent quelles lignes s’affichent, afin qu’une vue puisse accéder aux lignes déposées par rapport à d’autres enregistrements, comme les appels téléphoniques avec les contacts d’un compte ; réglée FilterByRecord sur false pour que les requêtes de la vue décident d’elles-mêmes. La timeline lit ses propres colonnes dans son propre ordre, donc les colonnes et ordres d’une requête n’ont pas d’importance. L’utilisateur doit pouvoir lire chaque colonne qu’un filtre teste : une condition sur une colonne que l’utilisateur ne peut pas lire est supprimée.
<Timeline
viewIds={[myPhoneCallsViewId, myTasksViewId]}
filterByRecord={false}
customViewDefinitions={[
{
// Les appels avec les contacts du compte, et les notes sur le compte.
id: '6f3c2a1e-0b7d-4c55-9a3e-2d8f1b6c4e90',
displayName: 'Calls with our people',
tables: [
{
table: 'phonecall',
fetchXml: `
<fetch>
<entity name="phonecall">
<link-entity name="contact" from="contactid" to="regardingobjectid">
<filter><condition attribute="parentcustomerid" operator="eq" value="${accountId}" /></filter>
</link-entity>
</entity>
</fetch>`,
},
{
table: 'annotation',
fetchXml: `
<fetch>
<entity name="annotation">
<filter><condition attribute="objectid" operator="eq" value="${accountId}" /></filter>
</entity>
</fetch>`,
},
],
},
]}
/><Timeline ViewIds="@([myPhoneCallsViewId, myTasksViewId])"
CustomViewDefinitions="@_views"
FilterByRecord="false" />
@code {
// Les appels avec les contacts du compte, et les notes sur le compte.
private List<MultiTableViewDefinition> _views =
[
new()
{
Id = new Guid("6f3c2a1e-0b7d-4c55-9a3e-2d8f1b6c4e90"),
DisplayName = "Calls with our people",
Tables =
[
new MultiTableViewTable
{
Table = "phonecall",
FetchXml = $"""
<fetch>
<entity name="phonecall">
<link-entity name="contact" from="contactid" to="regardingobjectid">
<filter><condition attribute="parentcustomerid" operator="eq" value="{accountId}" /></filter>
</link-entity>
</entity>
</fetch>
""",
},
new MultiTableViewTable
{
Table = "annotation",
FetchXml = $"""
<fetch>
<entity name="annotation">
<filter><condition attribute="objectid" operator="eq" value="{accountId}" /></filter>
</entity>
</fetch>
""",
},
],
},
];
}Choisissez quelles tables sont listées, combien d’éléments chaque page ajoute, si la barre de recherche est affichée, et jusqu’où la liste s’allonge avant de défiler.
Nom | Type | Par défaut | Description |
|---|---|---|---|
AllowFiltering | bool | False | Lorsque true, le menu Filtres propose de modifier les filtres de la vue, comme les filtres de la grille does — un onglet pour chaque tableau affiché : conditions sur ses colonnes, imbriquées en groupes, et associées les tables pour filtrer, sur les colonnes et les tables que l’utilisateur peut lire. Les changements durent tant que le La timeline affiche la vue, et un utilisateur qui sauvegarde les vues peut les conserver comme une vue à part entière. Non proposé pour une vue de plusieurs tables conservées dans Dataverse, que le serveur lit par son identifiant. Par défaut : falsel’utilisateur peut retirer tous les filtres de la vue, ce qui est un Une vue destinée à réduire les lignes d’une page ne conviendra peut-être pas. |
AllowSavedViews | bool | False | Permettez-nous aux utilisateurs connectés de sauvegarder les tables affichées dans la timeline comme des vues propres, proposées dans le Le sélecteur de vues à côté de celui de la page, et choisis leur vue par défaut et masque celles qu’ils n’utilisent pas. Une vue enregistrée sur une timeline ou un calendrier sans Timeline.SavedViewsKey indication est proposée sur les deux. Désactivé par défaut. Nécessite les tables multi-tableaux de la solution Power Portals Pro Core ; une version interne l’utilisateur a également besoin du rôle de sécurité Power |
AllowSearch | bool | True | Affiche une boîte de recherche au-dessus des colonnes de recherche des lignes, ce qui prend également un jour ou un an — avec true |
Ascending | bool | False | Liste d’abord les lignes les plus anciennes, à partir de maintenant. Par défaut : falsele plus récent en premier, à partir de maintenant. |
ChildContent | RenderFragment? | Les modèles et formulaires de la page pour ses tableaux : MultiTableTemplate et MultiTableForm. | |
CreatableTables | IEnumerable<string>? | Les tables dont un utilisateur peut écrire une nouvelle ligne à partir de la timeline, sont celles qu’il peut créer. Par défaut à des notes et des communications par portail, qui nécessitent le dossier de la chronologie. | |
CustomViewDefinitions | List<MultiTableViewDefinition>? | Vues définies dans le code, listées en dernier : chacune affiche des lignes d’une ou plusieurs tables. | |
DefaultTables | IEnumerable<string>? | Les tableaux montrés d’abord lorsque la chronologie montre chaque tableau — pas de vue propre : les autres que l’utilisateur peut lire est proposé dans le menu tableau, désactivé. Par défaut pour notes, emails et Communications par portail. Sans aucune d’elles à montrer, chaque table le fait. | |
DefaultViewId | Guid? | La vue montrée en premier. Non placée, ou pas parmi les vues, c’est la première. | |
FilterByRecord | bool | True | Montre uniquement les lignes autour de l’enregistrement de la forme environnante, lorsque Timeline.Regarding Ne nomme aucun. Fixe-le pour false une chronologie dont les opinions décident d’elles-mêmes quelles lignes s’affichent, où qu’elle soit placée. Par défaut, .true |
FormLocation | TimelineFormLocation | Right | Lorsque la forme d’une rangée s’ouvre, pour la créer ou la modifier : un panneau latéral à droite ou à gauche, un dialogues au centre, ou en place dans la timeline, au fur et à mesure que les notes et messages sont écrits. Notes et Les messages sans forme de page sont écrits en place partout où les formulaires s’ouvrent. Par défaut à TimelineFormLocation.Right. |
MatchParties | bool? | Que ce soit des activités auxquelles l’enregistrement participe — en tant qu’expéditeur, destinataire ou participant — affichez-vous à côté Ceux qui en parlent. Déposé, chaque réglage de table, sinon celui du serveur. | |
MaxHeight | string? | La liste des éléments est la plus haute, en longueur CSS ( | |
MultiTableViewIds | IEnumerable<Guid>? | Vues de plusieurs tables parmi lesquelles choisir, par id : enregistrées sur Timeline.ViewIds. | |
PageSize | int | 10 | Le nombre d’éléments affichés au début, et ajoutés par chaque « Charger plus ». Par défaut, c’est 10. |
Record | TableRecord? | Le registre dont cette chronologie appartient, cascadé par la forme environnante. | |
Regarding | TableRecordReference? | Le registre dont les rangées montrent — celles qui l’entourent, et les activités auxquelles il participe. Sans endroit, le enregistrement de la forme environnante (voir Timeline.FilterByRecord) ; avec ni l’un ni l’autre, chaque ligne Voir les émissions. | |
SavedViewsKey | string? | Nomme cette timeline parmi les timelines, donc les vues enregistrées dessus et les valeurs par défaut de l’utilisateur et les vues cachées sont les siennes. Sans celle-ci, elle partage ses vues avec chaque ligne temporelle et calendrier qui n’en a aucun. Lettres, chiffres, | |
Series | MultiTableSeries? | Comment les rendez-vous récurrents apparaissent. Déposé, la disposition de chaque table. | |
ShowRecordLinks | bool | True | Que le titre d’un élément renvoie à la page de son enregistrement, enregistré sur true; un tableau sans page ne montre aucun lien. |
SignInUrl | string | Account/Login | Lorsqu’un utilisateur non connecté est envoyé se connecter, depuis le menu des vues sauvegardées, qui demande ils passent en premier ; ils reviennent à cette page. Par défaut, compte |
Tables | IEnumerable<string>? | Les tables montrées, par nom logique : chacune doit être enregistrée auprès | |
Title | string? | L’en-tête. Par défaut est le nom de la vue, ou « Timeline » ; un sélecteur de vue prend sa place. | |
Upcoming | TimeSpan? | Jusqu’où la chronologie commence en avance, donc ce qui arrive apparaît au-dessus des autres sous son propre rang Heading : Two Days montre d’abord les rangées des deux jours suivants. Unset, ça commence maintenant. | |
ViewIds | IEnumerable<Guid>? | Des vues Dataverse à choisir, par id — « Mes Emails », « Toutes les activités » — chacune étant une vue d’un seul Une table enregistrée, ou de | |
ViewSort | ViewSort | NameAscending | L’ordre des vues dans le sélecteur. Par défaut est ViewSort.NameAscending, comme dans une grille et un calendrier. |
AllowFilteringtrue, le menu Filtres propose de modifier les filtres de la vue, comme les filtres de la grille does — un onglet pour chaque tableau affiché : conditions sur ses colonnes, imbriquées en groupes, et associées les tables pour filtrer, sur les colonnes et les tables que l’utilisateur peut lire. Les changements durent tant que le La timeline affiche la vue, et un utilisateur qui sauvegarde les vues peut les conserver comme une vue à part entière. Non proposé pour une vue de plusieurs tables conservées dans Dataverse, que le serveur lit par son identifiant. Par défaut : falsel’utilisateur peut retirer tous les filtres de la vue, ce qui est un Une vue destinée à réduire les lignes d’une page ne conviendra peut-être pas.AllowSavedViewsTimeline.SavedViewsKey indication est proposée sur les deux. Désactivé par défaut. Nécessite les tables multi-tableaux de la solution Power Portals Pro Core ; une version interne l’utilisateur a également besoin du rôle de sécurité Power AllowSearchtrueAscendingfalsele plus récent en premier, à partir de maintenant.ChildContentMultiTableTemplate et MultiTableForm.CreatableTablesCustomViewDefinitionsDefaultTablesDefaultViewIdFilterByRecordTimeline.Regarding Ne nomme aucun. Fixe-le pour false une chronologie dont les opinions décident d’elles-mêmes quelles lignes s’affichent, où qu’elle soit placée. Par défaut, .trueFormLocationTimelineFormLocation.Right.MatchPartiesMaxHeightMultiTableViewIdsTimeline.ViewIds.PageSizeRecordRegardingTimeline.FilterByRecord) ; avec ni l’un ni l’autre, chaque ligne Voir les émissions.SavedViewsKeySeriesShowRecordLinkstrue; un tableau sans page ne montre aucun lien.SignInUrlTablesTitleUpcomingViewIdsViewSortViewSort.NameAscending, comme dans une grille et un calendrier.