Displaying an edit notification in Episerver

This post will take you through displaying a custom edit notification in Episerver, including wiring it up to watch a particular property and displaying it conditionally based on that value. There is a bit of detail about edit notifications in the Episerver Plug-in areas documentation (see the last example). However, this blog post aims to give a much more in-depth example based on a question I encountered in the forums.

In this example we'll work with the concept of an event page which presents the editor with a notification depending on when the event is:

Displaying a custom edit notification in Episerver

This should be easily applicable to other use cases, especially if they revolve around a date—but you could just as easily watch a string property and display a notification based on it's value.

It should only take a few steps to get this working, starting with a:

Datetime property

Nothing fancy here, we just need a standard DateTime property (or a nullable one it you'd like to get fancy):

[Display(Name = "Date", Order = 10)]
public virtual DateTime? EventDate { get; set; } 

As I already mentioned, this could easily be adjusted to cover other scenarios.

Dojo notification component

This is the real meat and potatoes of our notification, it does nearly everything including watching the property, evaluating whether the notification conditions are met and triggering the showing or hiding of the notification.

All of that is maybe more compact than you'd imagine:

define("scripts/EventNotification", [
    // dojo
    "dojo/_base/declare",
    "dojo/_base/lang",
    "dojo/Stateful",
    "dojo/string",
    // epi
    "epi/datetime"
],
function (
    // dojo
    declare,
    lang,
    Stateful,
    string,
    // epi
    epiDatetime
) {
    return declare([Stateful], {
        // summary:
        //      Helper class to translate the event date
        //      into notifications for the notification bar.
        // tags:
        //      internal

        // order: [public] Number
        //      Sort order of notification
        order: 20,

        // notificationPeriod: [private] Number
        //      The max notification period in seconds
        _notificationPeriod: 10 * 24 * 60 * 60,

        _valueSetter: function (/*Object*/value) {
            // summary:
            //      Updates the notification when the eventDate property changes.
            // tags:
            //      private

            var eventDate = value.contentViewModel.contentModel.get("eventDate");

            this._updateNotification(eventDate);

            if (this._contentModelWatch) {
                this._contentModelWatch.unwatch();
            }

            this._contentModelWatch = value.contentViewModel.contentModel.watch("eventDate", lang.hitch(this, function (name, oldValue, newValue) {
                this._updateNotification(newValue);
            }));
        },

        _updateNotification: function (eventDate) {
            // summary:
            //      Gets a notification based based on the eventDate date
            // eventDate: Date
            //      The event date
            // tags:
            //      private

            var serverTime = epiDatetime.serverTime();

            var text = null;
            if (eventDate && epiDatetime.isDateValid(eventDate)) {
                if (new Date(serverTime.getTime() + this._notificationPeriod * 1000) > eventDate) {
                    text = eventDate < serverTime
                        ? "This event has already taken place"
                        : string.substitute("This event is taking place in ${0}", [epiDatetime.timeToGo(eventDate)]);
                }
            }
            if (!text) {
                this.set("notification", null); //clear notification
            } else {
                this.set("notification", { content: text });
            }
        }
    });
});

As per the forum post, I based this on the existing epi-cms/contentediting/ExpirationNotification and epi-cms/contentediting/ShortcutNotification.

There are a few bits in this worth mentioning:

  • You can play around with the _notificationPeriod to adjust when the notification should be displayed, it's currently set to show up to 10 days before the date.
  • We use the dojo/Stateful watch() function to watch the "eventDate" property, every time it changes the _updateNotification method is fired.
  • _updateNotification compares the date of the event with the server time and adjusts the messages and shows/hides the notification accordingly. It utilizes a few epi/datetime functions to get the server time and format the date.

I think that's enough of an overview, there's also plenty of comments above!

Initializer

This is just a very simple initializer that adds our event notification to the edit notifications plug-in area (plenty of detail is available in the documentation):

define([
    "dojo/_base/declare",
    "epi-cms/plugin-area/edit-notifications",
    // Parent class
    "epi/_Module",
    // Notifications
    "scripts/EventNotification"
],
function (
    declare,
    editNotifications,
    // Parent class
    _Module,
    // Notifications
    EventNotification
) {
    return declare([_Module], {
            initialize: function () {
                this.inherited(arguments);
                editNotifications.add(EventNotification);
            }
        });
    }
);

As you can see there's not too much to this, it simply adds the notification to the edit notifications area (epi-cms/plugin-area/edit-notifications).

Module.config

Finally, as always, you've got to add the following to your module.config:

<?xml version="1.0" encoding="utf-8"?>
<module>
  <dojo>
    <paths>
      <add name="scripts" path="Scripts" />
    </paths>
  </dojo>
  <clientModule initializer="scripts/Initializer">
    <moduleDependencies>
      <add dependency="CMS" type="RunAfter" />
    </moduleDependencies>
  </clientModule>
</module>

Feel like I've given a thousand examples of this now, the difference being with this one is that it also points at the initializer. The above example assumes that all your your JavaScript files are in the solution at: /ClientResources/Scripts, although this is easily configurable.

Done!

Your custom notification should now be working and displaying when the conditions are met—fire up edit mode and test it out!

Comments

There are zero comments 😢