Notifications

Weavy automatically creates notifications for reactions, mentions and other activities. Many of our components such as posts and comments come with a built-in notification UI, but there is also the standalone notifications component which can display an aggregated view of all notifications regardless of their origin. There is also a notification toasts component that may display on-page notifications, native browser notifications or handle custom notification toasts.

Notification toasts

To display realtime notification toasts on your page, simply add the <wy-notification-toasts> component anywhere on your page. Note that you need to add a wy-link event listener to handle navigation when the notifications are clicked. It the component the notification belongs to is currently visible, the notification will be suppressed.

Example: Display rich notification toasts on your page.

<wy-notification-toasts></wy-notification-toasts>

Example: Display native browser notification toasts.

<wy-notification-toasts appearance="native"></wy-notification-toasts>

Providing custom notification toasts

To provide custom notification toasts you can set the appearance of the wy-notification-toasts to none and listen to the wy-notification event on the component. The event is triggered whenever a notification toast should be displayed. It contains rich data about the notification. The title is translated if localization is provided.

The wy-notification event can also call event.preventDefault() to prevent page notifications or browser notifications from showing.

{
  "id": 4118,
  "type": "reaction",
  "action": "reaction_added",
  "actor": {
    "id": 1126,
    "uid": "marvin",
    "display_name": "Marvin Acme"
  },
  "template": "**{0}** reacted to your post: {1}",
  "args": ["Marvin Acme", "šŸ˜Ž"],
  "text": "**Marvin Acme** reacted to your post: šŸ˜Ž",
  "html": "<p><strong>Marvin Acme</strong> reacted to your post: šŸ˜Ž</p>",
  "plain": "Marvin Acme reacted to your post: šŸ˜Ž",
  "link": {
    "id": 2199,
    "type": "post",
    "app": {
      "id": 1971,
      "type": "5ebfa152-de85-48da-82dd-30a1b560c313",
      "uid": "demo-posts"
    }
  },
  "user": {
    "id": 2,
    "display_name": "Bugs Bunny"
  },
  "created_at": "2024-07-09T10:05:32.4269839Z",
  "is_unread": true,
  "title": "Marvin Acme reagerade pƄ din post",
  "detail": "šŸ˜Ž",
  "lang": "sv-SE"
}

Example: Custom notification toasts.

<wy-notification-toasts appearance="none" requestUserPermission></wy-notification-toasts>

<script>
  document
    .querySelector("wy-notification-toasts")
    .addEventListener("wy-notification", (e) => {
      const { title, detail, lang, actor } = e.detail;

      // Note that you need to request user permission to be able to create browser notifications, 
      // which can be handled automatically by adding the requestUserPermission attribute to the component.
      const customNotification = new Notification(title, {
        body: detail,
        icon: actor.avatar_url,
        lang: lang,
      });
    });
</script>

Handling navigation

When a notification in one of the notification components is clicked, Weavy dispatches a wy-link event. The event details (e.detail) for the event includes data about the linked entity in the notification. You can use this information to navigate to the corresponding page or view on your application.

Example: Event details for the wy-link event that links to a comment in a post.

{
  link: {
    id: 3616,
    type: "comment",
    app: {
      id: 1971,
      type: "5ebfa152-de85-48da-82dd-30a1b560c313",
      uid: "demo-posts",
    },
    parent: {
      id: 3554,
      type: "post",
    },
  },
  source_url: "https://example.com/my-page.html",
  source_name: "my_source_name"
  source_data: '{ "customer": 37: }'
};

To handle the wy-link event you should add an event listener on the the document (alternatively you can register event listeners on specific notification enabled components). After navigation, and once the corresponding Weavy component is loaded, the linked entity will automatically be highlighted.

document.addEventListener("wy-link", (e) => {
  const data = e.detail;

  // Evaluate the data and navigate to the correct page/view in your application
  // ...

  if (e.detail) window.location = "./some-page.html";
});

To simplify navigating between pages and different sites, you can keep track of navigation data in your system or you can store any additional custom data in the metadata property on the app using the Update App endpoint. This requires that the app for the component is unique for that page and not used in multiple places, otherwise you have to use your own custom logic to decide where to navigate. Weavy is using the source_url, source_name and source_data as standard in our examples and these are automatically provided in the wy-link event if defined.

  • source_url - The full url back to the page where the component is placed. This is useful for cross-site navigation.
  • source_name - The name of your site/single page app/system. Useful to quickly see where the link belongs.
  • source_data - Any data needed to navigate. For instance details needed to do in-app navigation in a single page app. The data needs to be encoded as a string, for instance using JSON.
curl -X PATCH {WEAVY-URL}/api/apps/demo-posts
-H "Authorization: Bearer {API-KEY}"
--json "{ 'metadata': { 'source_url': 'https://example.com/my-page.html', 'source_name': 'my_source_name', 'source_data': '{ "customer": 37: }' } }"

With details from the wy-link event you can make an educated decision on where to navigate or what to show. You can use any source metadata you have provided otherwise the most relevant data can be found in the link.app property.

To make a basic routing decision, follow this strategy.

  1. When the wy-link event is triggered, any visible component that the linked entity belongs to will automatically scroll and highlight the entity. No action is needed in these cases.
  2. To investigate if the linked entity belongs to the Messenger component, look at the e.detail.link.app.type and check if it is a Messenger conversation (private chat or chat room). The MessengerTypes map contains the guid:s for all Messenger conversation types and can be used to evaluate the app type.
  3. Check if the linked entity belongs to a bot chat by checking if the e.detail.link.app.type exists in MessengerBotTypes. The e.detail.link.bot may also provide the name of the bot.
  4. Otherwise, evaluate the e.detail.source_name and compare it to your current site/page or evaluate the e.detail.link.app.uid and compare it to the uid used in your components.
  5. If nothing is matched, check the e.detail.source_url to see if it provides any general navigation url.
  6. After checking the provided data, decide if and how navigation is required, e.g. by setting window.location or by toggling the visibility of hidden element etc.
  7. Once the correct app/component is visible it will consume the link and scroll to the linked entity and highlight it.

Example: Event listener for wy-link.

import { MessengerTypes, MessengerBotTypes } from "@weavy/uikit-web";

document.addEventListener("wy-link", (e) => {
  const appType = e.detail.link.app.type;
  const appUid = e.detail.link.app.uid;

  let navigationUrl;

  // Check if the appType is a Messenger conversation
  if (MessengerTypes.has(appType)) {
    // Toggle a panel to show the Messenger component
    document.querySelector("#messages").hidden = false;

    // Check if the appType is a Bot conversation
  } else if (MessengerBotTypes.has(appType)) {
    navigationUrl = new URL(
      `./botchat.html${`#${e.detail.link.bot}` || ""}`,
      window.location
    );

    // Check any source name and any source data
  } else if (
    e.detail.source_name === "my_source_name" &&
    e.detail.source_data
  ) {
    const parsedSourceData = JSON.parse(e.detail.source_data);

    // Do any custom navigation within your site/page
    navigationUrl = new URL(
      `./some-page.html?customer=${parsedSourceData.customer}#${appUid}`,
      window.location
    );

    // Check if a source url is provided
  } else if (e.detail.source_url) {
    // The link seems to belong in another site or other single page app.
    navigationUrl = new URL(e.detail.source_url);
  }

  // Navigate
  if (navigationUrl) {
    window.location = navigationUrl;
  }
});

It is a good idea to base the uid for components on something that identifies the location in your app where the Weavy component is being rendered to make navigation handling easier. Typically you would use something like a product id, page id, path or URL.

Custom notification handling

Normally you don't need to handle notifications as the notification components are automatically updated when needed. But, if required, you can configure Weavy to emit a wy-notifications event when notifications are created or updated, or when mark all as read is clicked.

// configure Weavy to emit the wy-notifications event
const weavy = new Weavy();
weavy.notificationEvents = true;

After enabling the event you can register a listener using the standard addEventListener() method on the document.

document.addEventListener("wy-notifications", (e) => {
  console.log(e.type, e.detail);
});

The event detail (e.detail) contains the following information.

  • id ā€“ Unique identifier for the event.
  • action ā€“ The type of activity that triggered the event (notification_created, notification_updated or notifications_marked).
  • actor ā€“ The user that triggered the event.
  • notification ā€“ Data about the notification.

Example: Event details for the notification_created action.

{
  "id": 11606,
  "action": "notification_created",
  "actor": {
    "id": 1126,
    "uid": "marvin",
    "display_name": "Marvin Acme"
  },
  "notification": {
    "id": 4118,
    "type": "reaction",
    "action": "reaction_added",
    "actor": {
      "id": 1126,
      "uid": "marvin",
      "display_name": "Marvin Acme"
    },
    "template": "**{0}** reacted to your post: {1}",
    "args": ["Marvin Acme", "šŸ˜Ž"],
    "text": "**Marvin Acme** reacted to your post: šŸ˜Ž",
    "html": "<p><strong>Marvin Acme</strong> reacted to your post: šŸ˜Ž</p>",
    "plain": "Marvin Acme reacted to your post: šŸ˜Ž",
    "link": {
      "id": 2199,
      "type": "post",
      "app": {
        "id": 1971,
        "type": "5ebfa152-de85-48da-82dd-30a1b560c313",
        "uid": "demo-posts"
      }
    },
    "user": {
      "id": 2,
      "display_name": "Bugs Bunny"
    },
    "created_at": "2024-07-09T10:05:32.4269839Z",
    "is_unread": true
  }
}

To prevent the default internal automatic link-handling that scrolls to, and highlights linked entities, you can call e.preventDefault() in your event listener. When preventing the default functionality, the link can be set for automatic handling manually by calling e.target.provideStorageLink(e.detail.link).

The .link property can also be set on a component to trigger the link handling, e.g. document.querySelector("wy-chat").link = e.detail.link.

Example: Custom wy-link event handling

document.addEventListener("wy-link", (e) => {
  // prevent the link from being automatically handled by components on the page
  e.preventDefault();

  // optionally save the link for internal auto handling later
  //e.target.provideStorageLink(e.detail.link);

  // do custom things to transfer the link somewhere...

  // ...or pass the link to a specific component
  document.querySelector("wy-chat").link = e.detail.link;
});
Support

To access live chat with our developer success team you need a Weavy account.

Sign in or create a Weavy account