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.
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.
Ok, makes sense—in 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/
Thanks so much for going into such detail. You're a legend!
I got it working right away.
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.
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