How to display a notification in all properties view

Vote:
 

Does anyone know if I can display a notification like the one pictured?

I'm making a custom archiving job, and I'd like for the user to see that the page is set to be archived at a glance when editing.

My first thought was to use the built-in PageData.StopPublish date. That would have been great, but I haven't been able to come up with a good solution that fits the project constraints. I'd be happy to expound on that, but I'll just make a different topic about archiving if the notification is a no-go.

Edit: Fixed wrong property name for StopPublish

#221876
Edited, Apr 27, 2020 15:03
Vote:
 

Hi Leo,

Are you able to expound on those requirements briefly? I agree that using the out-of-the-box expiration funcionality would be your best option, if at all possible.

#221886
Apr 27, 2020 16:24
Vote:
 

Hi, Jake!

Thanks for taking the time to look at my question.

The the new job I'm making is for moving content to a new "archive" location where it will remain published. Or at the very least the job could set the archive links and let the standard job do the moving.

The problem with that is that using the StopPoblish property would clobber the "just unpublish this page" functionality that exists by default.

Let's say my job traverses the page tree looking for content that has a StopPublish date, but no archive link. Then it wants to add the archive link so that the page can be moved to the archive location. But when such a page is encountered, there's no way to tell whether the page should be moved or whether it's supposed to stay where it is, but be temporarily invisible to the public.

I could add another property to all the pages, like "MoveOnArchiving", but I think there's no sensible default for this and it will confuse the editors if they have to set the StopPublish date, then hunt around elsewhere for that other flag. So the best course of action seems to be separating the archiving functionality from the unpublishing functionality.

Edit: Clarified why editors might be confused.

#221912
Edited, Apr 28, 2020 7:44
Vote:
 

Ok, makes sensein that context you probably shouldn't use StopPublish.

I've never worked with those notifications before, so I thought it'd be interesting to take a look.

First, you just need to add a property to the page:

[Display(
    Name = "Archive",
    Order = 200,
    GroupName = SystemTabNames.PageHeader)]
[ClientEditor(ClientEditingClass = "epi-cms/contentediting/editors/PreviewableDateTimeEditor")]
public virtual DateTime? Archive { get; set; }

Nothing unusual about that part, I just stuck it in the page header/settings panel for convenience.

Next, we need to add a Dojo notification widget, this watches that property and displays a relevant message based on the selected property:

define("scripts/ArchiveNotification", [
// 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 archive 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: 60 * 24 * 60 * 60,

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

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

            this._updateNotification(archive);

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

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

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

            var serverTime = epiDatetime.serverTime();

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

Based this heavily on the existing epi-cms/contentediting/ExpirationNotification and epi-cms/contentediting/ShortcutNotification and it seems to work!

Next we need a module initializer to add our ArchiveNotification to the edit notifications plugin area:

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

Finally, you need to add the following to your module.config (or create it):

<?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>

By default, the JavaScript examples above should be placed at ClientResources/Scripts/Initializer.js and ClientResources/Scripts/ArchiveNotification.js based on this configuration.

Hopefully that's useful for you, there's also another example in the documentation here: https://world.episerver.com/documentation/developer-guides/CMS/user-interface/plug-in-areas/

#221996
Edited, Apr 29, 2020 4:52
Vote:
 

Thanks so much for going into such detail. You're a legend!

I got it working right away.

#222017
Apr 29, 2020 7:53
Jake Jones - Apr 29, 2020 14:10
Glad it worked so seamlessly! 👌
Vote:
 

Excellent work Jake, if you haven't considered it already you may wish to think about blogging this. I have seen requirements to interact with the notifications come up before and this seems an elegant and simple solution. 

#222062
Apr 29, 2020 12:37
Jake Jones - Apr 29, 2020 14:35
Thanks! I did notice a dearth of information on edit notifications, so I think I will spin off a blog post soon.
This topic was created over six months ago and has been resolved. If you have a similar question, please create a new topic and refer to this one.
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.