Timeline

The Timeline component shows rows of several tables as one list, newest first: by default a record's notes, portal communications and other activities. Put it inside a RecordContext and it lists the rows about that record: who wrote each and when, its rich-text body cut to a few lines until Show more, and its attachment to download. It reads a page at a time, with Load more for the rest and Refresh to read it again. The search works as a grid's: text matches from the start of a subject or text, or anywhere after a leading *, and a day or a year, with >, <, >= or <= before it, finds the rows of those days. With more than one table, a menu beside the search chooses which to show.

React Blazor

A record's timeline

The notes, messages and appointments about Schmeler and Sons, the account the account detail page demo shows. One of its notes is internal — its text does not start with *WEB* — so it is not listed. Choose the tables it shows, or narrow them with Edit filters (AllowFiltering), in the Filter menu, and sign in to save them there as a view of your own (AllowSavedViews).

React example Blazor example React TypeScript Razor
  1. Carmen Stamm
    Updated billing contact
  2. Customer Support
    Q4 business review summary
    Show more
  3. Customer Support
    Delivery schedule
    November delivery schedule.csv
  4. Customer Support
    Re: Question about the November order
    Revised November shipments.pdf
  5. Timothy Blick
    Question about the November order
  6. Timothy Blick
  7. Customer Support
    Renewal kickoff

Which notes and activities are shown

A note reaches the portal only when its text starts with *WEB*, so staff can keep internal notes on records customers see. Phone calls, tasks and other activities follow the same rule through their description, except the unfiltered types — portal communications, by default. The server applies this to every query, grids and joins included, so no table access rule can widen it. The portal never shows the prefix, and adds it to a note or activity created through the portal. A note whose title names its writer as Note created on … by Name [contact:id] is shown as written by that contact. Set SecurityOptions.PortalVisibility.Prefix to use another prefix, or to null to show every note and activity, and add a table to UnfilteredActivities to show its every activity. Staff signed in to the portal as themselves are the exception: they see every note and activity their security roles let them read, as they would in Dynamics, with its text as stored, so they add the prefix themselves to a note meant for the portal.

Emails can't be marked with the prefix. An email's body is written by the mail client that sent it, as a whole HTML document, so the prefix is never its first text, and no email reaches the portal by its prefix. Adding email to UnfilteredActivities is the only way to show emails, and it shows every email the user can read on a record — internal ones included.

Portal communications

A portal communication (ppp_portalcommunication) is an activity in the Power Portals Pro solution for messages between a portal user and staff. It is meant for the portal, so it needs no prefix. Its From says who wrote it: the portal user's contact, or the staff member who replied, with the contact in To. The message is rich text and can carry one attachment.

Access

The timeline lists only what the user may read: each kind of item needs read on its table, and a user who can read neither sees no timeline at all. A note points at its record through objectid and a portal communication through regardingobjectid, so the usual rule lets a user read the items about the records they can reach, with RowsViaParent. Keep that lookup among the columns they may read: the timeline asks for the items about its record through it, and a condition on a column a user may not read is dropped, which would list the items of every record they reach.

The portal's application user needs read on both tables in Dataverse as well. Notes need read on the Note table. Dataverse grants every activity type through one set of privileges, so portal communications are covered by the read on activities the Power Portals Pro Application User role already holds. For users to change or delete notes and messages, it needs Write and Delete on the Note table and Delete on activities as well, which that role does not hold.

Writing messages

A user who may create portal communications gets New message: a subject, a rich-text message and one attachment, about the record the timeline is on, and one who may create notes gets New note. CreatableTables names the tables a new row can be written of, notes and portal communications by default; a note or message is written in place, another table's row in a side panel. It is a form of its own, saved apart from the page around it. The server sends the message from the user, whatever the request says, so one user cannot write as another. Grant it with table access: OwnedBy("from") sends a new message from its writer, and RowsForWriting with RowsOwnedByContact("from") lets users change and delete only what they sent. Leave out Write and Delete, and a message stays as it was sent. The timeline offers Edit and Delete on each row the user's access lets them change or delete, and the server judges each change again when it arrives. FormLocation (React: formLocation) says where another table's form opens: a side panel on the right, as by default, or the left, a dialog in the center, or Inline — in place in the timeline, as notes and messages are written.

Staff hear of a new message through PortalCommunicationOptions. By default it is addressed to the owner of the record it is about, when that owner is a user. It can go to a queue instead, which the portal's application user needs access to add items to, or to no one, leaving it on the record's timeline alone.

Tables

Notes and every activity table are registered on the server for timelines and calendars, each dated by what its forms ask for: an appointment by its start, a task or phone call by its due date, an email or message by when it was written. A timeline lists every registered table the user may read; name the ones it shows in Tables. On a record it lists the rows about it, and the activities the record takes part in as a sender, recipient or attendee. The server shows only the notes and activities meant for the portal: those whose text starts with *WEB*, or every one of a type in UnfilteredActivities. Emails can't carry the prefix, so they appear only when email is in that list.

React Blazor

Register a table of your own with AddMultiTableSource: a title, and what else is shown, such as the text, its owner and recipients, and the lookup to the record a row is about. Then name each control it is for, with the columns that control needs: ForTimelines the date its rows are ordered by, ForCalendars its start and, if it has them, its end and all-day column, ForSearch, and ForMaps its latitude and longitude. Those columns are always read, whatever a view's query names. A registration that names a column the table doesn't have, or one of the wrong type, stops the portal at startup and says what is wrong. Registering a notes or activity table again changes only what the registration names. A registration grants no access: each table still needs read access like any table.

Upcoming rows

A timeline lists its rows newest first, from now back. Upcoming (React: upcoming) starts it that far ahead, so what is coming up shows first under its own heading, and Ascending (React: ascending) lists the rows from now on, soonest first: see Upcoming Items. To draw a table's rows your own way, or write them in forms of your own, see Custom Rendering.

React Blazor

Views

Give the timeline views to choose from, as a grid has: Dataverse's own in ViewIds, such as My Phone Calls or All Activities, views of several tables in MultiTableViewIds, and views of your own in CustomViewDefinitions, with DefaultViewId naming the one shown first. With two or more, a view selector takes the heading's place. A Dataverse view of activitypointer lists each registered activity table, and on a record a view lists the rows about the record that it lets through. With AllowSavedViews (React: allowSavedViews), a signed-in user can save the tables the timeline shows as a view of their own, offered beside yours, and choose their default view and hide the ones they don't use, from the Filter menu: see Saved Views.

A view of your own lists rows of one or more tables. Give a table a FetchXML query, and its filters and joins decide which rows show, so a view can reach rows filed against other records, such as the phone calls with an account's contacts; set FilterByRecord to false for the view's queries to decide on their own. The timeline reads its own columns in its own order, so a query's columns and orders don't matter. The user must be able to read each column a filter tests: a condition on a column the user may not read is dropped.

React Blazor

Notes only, two at a time

Choose which tables are listed, how many items each page adds, whether the search box is shown, and how tall the list grows before it scrolls.

React example Blazor example React TypeScript Razor
  1. Customer Support
    Q4 business review summary
    Show more
  2. Customer Support
    Delivery schedule
    November delivery schedule.csv
React Blazor

Timeline Class

Parameters

Name
Type
Default
Description
AllowFilteringbool
False
When true, the Filter menu offers the view's filters to change, as a grid's does — a tab for each table shown: conditions on its columns, nested in groups, and related tables to filter by, over the columns and tables the user may read. The changes last while the timeline shows the view, and a user who saves views can keep them as a view of their own. Not offered for a view of several tables kept in Dataverse, which the server reads by its id. Defaults to false: the user can take away every filter the view has, which a view meant to narrow a page's rows may not want.
AllowSavedViewsbool
False
Lets signed-in users save the tables the timeline shows as views of their own, offered in the view picker beside the page's, and choose their default view and hide the views they don't use. A view saved on a timeline or a calendar with no Timeline.SavedViewsKey is offered on both. Off by default. Needs the Power Portals Pro Core solution's multi-table view tables; an internal user also needs the Power Portals Pro Saved Views security role.
AllowSearchbool
True
Shows a search box over the rows' search columns, which also takes a day or a year — with >, <, >= or <= before it, as in a grid — among the days rows start. Defaults to true.
Ascendingbool
False
Lists the oldest rows first, from now on. Defaults to false: newest first, from now back.
ChildContentRenderFragment?
The page's templates and forms for its tables: Components.MultiTableTemplate and Components.MultiTableForm.
CreatableTablesIEnumerable<string>?
The tables a user may write a new row of from the timeline, those they may create. Defaults to notes and portal communications, which need the timeline's record.
CustomViewDefinitionsList<MultiTableViewDefinition>?
Views defined in code, listed last: each shows rows of one or more tables.
DefaultTablesIEnumerable<string>?
The tables shown at first when the timeline shows every table — no view of its own: the others the user may read are offered in the table menu, switched off. Defaults to notes, emails and portal communications. With none of them to show, every table is.
DefaultViewIdGuid?
The view shown first. Unset, or not among the views, it is the first.
FilterByRecordbool
True
Shows only the rows about the record of the surrounding form, when Timeline.Regarding names none. Set it to false for a timeline whose views decide on their own which rows show, wherever it is placed. Defaults to true.
FormLocationTimelineFormLocation
Right
Where a row's form opens, to create or change it: a side panel on the right or the left, a dialog in the center, or in place in the timeline, as notes and messages are written. Notes and messages without a form of the page's are written in place wherever forms open. Defaults to TimelineFormLocation.Right.
MatchPartiesbool?
Whether activities the record takes part in — as a sender, recipient or attendee — show beside those about it. Unset, each table's setting, else the server's.
MaxHeightstring?
The tallest the list of items grows, as a CSS length (480px, 50vh). Past it the list scrolls, while the heading, search and new message stay in view. Unset, it grows with its items.
MultiTableViewIdsIEnumerable<Guid>?
Views of several tables to choose from, by id: registered with AddMultiTableView, or kept in Dataverse (ppp_multitableview). Listed after Timeline.ViewIds.
PageSizeint
10
How many items are shown at first, and added by each 'Load more'. Defaults to 10.
RecordTableRecord?
The record whose timeline this is, cascaded by the surrounding form.
RegardingTableRecordReference?
The record whose rows show — those about it, and the activities it takes part in. Unset, the record of the surrounding form (see Timeline.FilterByRecord); with neither, every row the view shows.
SavedViewsKeystring?
Names this timeline among the timelines, so the views saved on it and the user's default and hidden views are its own. Without one, it shares its views with every timeline and calendar that has none. Letters, digits, -, _ and ..
SeriesMultiTableSeries?
How recurring appointments show. Unset, each table's setting.
ShowRecordLinksbool
True
Whether an item's title links to its record's page, registered with AddRecordPage. Default true; a table with no page shows no link.
SignInUrlstring
Account/Login
Where a user who isn't signed in is sent to sign in, from the saved views' menu, which asks them to first; they come back to this page. Defaults to Account/Login.
TablesIEnumerable<string>?
The tables shown, by logical name: each needs registering with AddMultiTableSource, as notes and activity tables are by default. Unset, every registered table the view reads.
Titlestring?
The heading. Defaults to the view's name, or 'Timeline'; a view selector takes its place.
UpcomingTimeSpan?
How far ahead the timeline starts, so what is coming up shows above the rest under its own heading: two days shows the next two days' rows first. Unset, it starts now.
ViewIdsIEnumerable<Guid>?
Dataverse views to choose from, by id — 'My Emails', 'All Activities' — each a view of one registered table, or of activitypointer, read as each activity table. With views, the timeline shows them in place of every table, with a view selector when there are two or more.
ViewSortViewSort
NameAscending
The order of the views in the picker. Defaults to ViewSort.NameAscending, as a grid's and a calendar's.
Name: AllowFiltering
Type: bool
Default: False
Description: When true, the Filter menu offers the view's filters to change, as a grid's does — a tab for each table shown: conditions on its columns, nested in groups, and related tables to filter by, over the columns and tables the user may read. The changes last while the timeline shows the view, and a user who saves views can keep them as a view of their own. Not offered for a view of several tables kept in Dataverse, which the server reads by its id. Defaults to false: the user can take away every filter the view has, which a view meant to narrow a page's rows may not want.
Name: AllowSavedViews
Type: bool
Default: False
Description: Lets signed-in users save the tables the timeline shows as views of their own, offered in the view picker beside the page's, and choose their default view and hide the views they don't use. A view saved on a timeline or a calendar with no Timeline.SavedViewsKey is offered on both. Off by default. Needs the Power Portals Pro Core solution's multi-table view tables; an internal user also needs the Power Portals Pro Saved Views security role.
Name: AllowSearch
Type: bool
Default: True
Description: Shows a search box over the rows' search columns, which also takes a day or a year — with >, <, >= or <= before it, as in a grid — among the days rows start. Defaults to true.
Name: Ascending
Type: bool
Default: False
Description: Lists the oldest rows first, from now on. Defaults to false: newest first, from now back.
Name: ChildContent
Type: RenderFragment?
Description: The page's templates and forms for its tables: Components.MultiTableTemplate and Components.MultiTableForm.
Name: CreatableTables
Type: IEnumerable<string>?
Description: The tables a user may write a new row of from the timeline, those they may create. Defaults to notes and portal communications, which need the timeline's record.
Name: CustomViewDefinitions
Type: List<MultiTableViewDefinition>?
Description: Views defined in code, listed last: each shows rows of one or more tables.
Name: DefaultTables
Type: IEnumerable<string>?
Description: The tables shown at first when the timeline shows every table — no view of its own: the others the user may read are offered in the table menu, switched off. Defaults to notes, emails and portal communications. With none of them to show, every table is.
Name: DefaultViewId
Type: Guid?
Description: The view shown first. Unset, or not among the views, it is the first.
Name: FilterByRecord
Type: bool
Default: True
Description: Shows only the rows about the record of the surrounding form, when Timeline.Regarding names none. Set it to false for a timeline whose views decide on their own which rows show, wherever it is placed. Defaults to true.
Name: FormLocation
Type: TimelineFormLocation
Default: Right
Description: Where a row's form opens, to create or change it: a side panel on the right or the left, a dialog in the center, or in place in the timeline, as notes and messages are written. Notes and messages without a form of the page's are written in place wherever forms open. Defaults to TimelineFormLocation.Right.
Name: MatchParties
Type: bool?
Description: Whether activities the record takes part in — as a sender, recipient or attendee — show beside those about it. Unset, each table's setting, else the server's.
Name: MaxHeight
Type: string?
Description: The tallest the list of items grows, as a CSS length (480px, 50vh). Past it the list scrolls, while the heading, search and new message stay in view. Unset, it grows with its items.
Name: MultiTableViewIds
Type: IEnumerable<Guid>?
Description: Views of several tables to choose from, by id: registered with AddMultiTableView, or kept in Dataverse (ppp_multitableview). Listed after Timeline.ViewIds.
Name: PageSize
Type: int
Default: 10
Description: How many items are shown at first, and added by each 'Load more'. Defaults to 10.
Name: Record
Type: TableRecord?
Description: The record whose timeline this is, cascaded by the surrounding form.
Name: Regarding
Type: TableRecordReference?
Description: The record whose rows show — those about it, and the activities it takes part in. Unset, the record of the surrounding form (see Timeline.FilterByRecord); with neither, every row the view shows.
Name: SavedViewsKey
Type: string?
Description: Names this timeline among the timelines, so the views saved on it and the user's default and hidden views are its own. Without one, it shares its views with every timeline and calendar that has none. Letters, digits, -, _ and ..
Name: Series
Type: MultiTableSeries?
Description: How recurring appointments show. Unset, each table's setting.
Name: ShowRecordLinks
Type: bool
Default: True
Description: Whether an item's title links to its record's page, registered with AddRecordPage. Default true; a table with no page shows no link.
Name: SignInUrl
Type: string
Default: Account/Login
Description: Where a user who isn't signed in is sent to sign in, from the saved views' menu, which asks them to first; they come back to this page. Defaults to Account/Login.
Name: Tables
Type: IEnumerable<string>?
Description: The tables shown, by logical name: each needs registering with AddMultiTableSource, as notes and activity tables are by default. Unset, every registered table the view reads.
Name: Title
Type: string?
Description: The heading. Defaults to the view's name, or 'Timeline'; a view selector takes its place.
Name: Upcoming
Type: TimeSpan?
Description: How far ahead the timeline starts, so what is coming up shows above the rest under its own heading: two days shows the next two days' rows first. Unset, it starts now.
Name: ViewIds
Type: IEnumerable<Guid>?
Description: Dataverse views to choose from, by id — 'My Emails', 'All Activities' — each a view of one registered table, or of activitypointer, read as each activity table. With views, the timeline shows them in place of every table, with a view selector when there are two or more.
Name: ViewSort
Type: ViewSort
Default: NameAscending
Description: The order of the views in the picker. Defaults to ViewSort.NameAscending, as a grid's and a calendar's.