-
Notifications
You must be signed in to change notification settings - Fork 1
Description
This issue is a proposal to resolve:
via Intents and contexts, rather than proliferating new API calls within the Desktop Agent scope. This approach has the advantage that it might be implemented by a desktop agent (with optional rules in its resolver to router the intents to its internal handling) or by another app in the desktop (e.g. a custom Notification center implementation) at the discretion of the DesktopAgent provider / assembler.
The proposal draws inspiration from the Notifications Web API (see MDN and the Notification API Spec), but deviates from it in a few key areas. The notifications Web API allows for actionable notifications but they are performed by the application that generated the notification, which will use the data element and the action name to determine what action to take.
Whereas in FDC3 we are focused on application interoperability and our primary use case is to allow actions to be performed by other apps, through intents and contexts. Hence, the actions array is specified via the fdc3.action type (currently proposed in PR finos#779) which encapsulates an FDC3 context and an optional intent - allowing a range of actions with associated data to be specified, which can then be performed by other applications when sent to them via raiseIntent or raiseIntentForContext. This obviates the need for a data element in the notification.
Enhancement Request
Allow notifications to be raised via a standardized intent and context.
Use Case:
Actionable notifications are a common part of a suite of desktop applications. They are tied to application interop by the fact that they may be generated by one application or system but could or should be actioned via one or more other applications.
For example:
For example, An order management system (or a service monitoring one) might raise notifications for new orders, and offer you actions to ViewChart, ViewRisk or ViewHoldings via other applications.
Intents
There are several possible Intents that could be associated with notifications. The primary need for one is to create a notification, but you might also want to dismiss it (if actioned independently in the source app), subscribe to updates
as it changes state or subscribe to a (filtered) stream of notifications.
CreateNotification
Create a new notification using the supplied notification context.
UpdateNotification
Update or dismiss a particular notification, by passing an updated notification context with the id set.
GetNotifications
Retrieve or subscribe to a stream of notifications or updates about a particular notification.
Would require a context type describing a filter for notifications.
Contexts
fdc3.notification
To define the content of a notification and any options relating to how it should be handled or displayed.
May include actions that would be performed via FDC3 APIs (primarily raiseIntent, but could also be used
to broadcast context on a channel.
Draws inspiration from the Notification web API:
- https://developer.mozilla.org/en-US/docs/Web/API/Notification/Notification
- https://notifications.spec.whatwg.org/#notifications
Details
| Property | Type | Required | Example Value |
|---|---|---|---|
type |
string | Yes | 'fdc3.notification' |
id.notificationId |
string | No | 'unique-value-123' |
title |
string | Yes | 'Notification title displayed at top' |
options |
object | No | see below |
options.body |
string | No | "Text content of the notification displayed in its body" |
options.icon |
string | No | https://www.example.com/example.png |
options.image |
string | No | https://www.example.com/example.png |
options.notificationType |
string | No | warning |
options.actions |
array | No | see below |
options.notificationAlertSound |
string | No | https://www.example.com/example.mp3 |
metadata |
object | No | see below |
metadata.issuedAt |
datetime | No | "2022-03-30T15:44:44Z" |
metadata.receivedAt |
datetime | No | "2022-03-30T15:44:44Z" |
metadata.source |
AppIdentifier | No | { appId: "ABC", instanceId: "ABC123" } |
metadata.timeout |
number | No | 600000 |
metadata.isRead |
boolean | No | false |
metadata.isMuted |
boolean | No | false |
metadata.isSnoozed |
boolean | No | false |
metadata.isDeleted |
boolean | No | false |
Examples
const notification = {
type: 'fdc3.notification',
/**
* @optional
* Identifiers for a notification. Might not be set when submitting a notification and applied by the
* receiving system. Multiple identifiers might be used to link the notification to other systems that
* generate or interact with it.
*/
id: {
notificationId: "uniqueIdentifier"
},
/**
* @required
* Defines a title for the notification, which is typically shown at the top of the notification window.
*/
title: "string",
/**
* An options object containing any custom settings that you want to apply to the notification.
* @see https://developer.mozilla.org/en-US/docs/Web/API/Notification/Notification
*/
options: {
/**
* A string representing the body text of the notification, which is displayed below the title.
*/
body: "Body content",
/**
* A string containing the URL of an icon to be displayed in the notification to attribute it.
* If not specified a desktop agent might harvest this from the submitting applications
* appD config.
*/
icon: "https://...",
/**
* A string containing the URL of an image to be displayed in the body of the notification.
* If not specified, this might be drawn from a templated notificationType (see below).
*/
image: "https://...",
/**
* @optional
* A classification for the notification that might be used to apply different templates and/or
* filters to notifications.
* Could use enumerated types: info | success | warning | error | debug
* or free text...
*/
notificationType: "warning",
/**
* A list of Actions that might be performed by a user interacting with the notification.
* This is a key part of the relevance of Notifications to FDC3 as the actions can be loosely
* coupled to applications that resolve them by defining them via intents and contexts. Hence,
* though inspired by the Notifications web API we *should* depart from its spec here.
* Encoded as an array of fdc3.action contexts as defined in PR #779
* https://github.com/finos/FDC3/pull/779/files
*/
actions: [
{
type:"fdc3.action",
title: "View Contact",
intent: "ViewContact",
context: {
type: 'fdc3.contact',
name: 'Jane Doe',
id: {
email: 'jane@mail.com'
}
}
},
{
type:"fdc3.action",
name: "Other actions", //No intent is specified, use findIntentByContext or raiseIntentForContext to handle
context: {
type: 'fdc3.contact',
name: 'Jane Doe',
id: {
email: 'jane@mail.com'
}
}
}
],
/**
* A string containing the URL of an alert sound to play when the notification is received.
*/
notificationAlertSound: "*.wav",
},
/**
* Additional details about the notification - intended to be populated or used by the Desktop Agent
* or the system receiving the notification, rather than the app raising the notification.
* Not necessary for submitting a notification - but may be useful for other use cases
* such as subscribing to a stream of filtered notifications or updates on a specific notification.
*/
metadata: {
/**
* ISO8601 date formatted string.
* When the notification was generated.
*/
issuedAt: "2022-03-30T15:44:44Z",
/**
* ISO8601 date formatted string.
* When the notification was received.
*/
receivedAt: "2022-03-30T15:44:44Z",
/**
* AppIdentifier representing the source application that generated the notification.
*/
source: { appId: "ABC", instanceId: "ABC123" },
/**
* How long should the notification appear in a toast UI in millisecs?
*/
timeout: 60000,
/* Properties relating to the state of the notification. */
isRead: false,
isMuted: false,
isSnoozed: false,
isDeleted: false,
}
}
//perform feature detection to determine if notifications are supported
const appIntent = await fdc3.findIntent("CreateNotification");
if (appIntent.apps.length > 0) {
//Submit a notification
const resolution = await fdc3.raiseIntent("CreateNotification", notification);
//receive it back updated with ids and metadata
const submittedNotification = await resolution.getResult();
//update the notification after an action or status change
submittedNotification.metadata.isSnoozed = true;
await fdc3.raiseIntent("UpdateNotification", submittedNotification);
//retrieve a stream of updates about a notification
const filter = { type: "fdc3.notification.filter", id: { notificationId: "ABC123" } };
const resolution2 = await fdc3.raiseIntent("GetNotifications", filter );
const channel = await resolution2.getResult();
channel.addContextListener("fdc3.notification", handlerFn);
//retrieve a stream of notifications according to a filter
const filter2 = { type: "fdc3.notification.filter", titleRegex: "(AAPL)/g", options: { type: "alert"} };
const resolution3 = await fdc3.raiseIntent("GetNotifications", filter2 );
const channel2 = await resolution3.getResult();
channel2.addContextListener("fdc3.notification", handlerFn);}