TreeNodesRenderingNotification in Umbraco 9

Last week I blogged about using the Azure Computer Vision Image Analysis service to generate friendly captions for images in Umbraco Media Library. I used the MediaSavedNotification for this and while going through the Umbraco Docs for Notifications, the Tree Notifications caught my eye. 

Generating friendly captions for images is great but it can be made more editor friendly, if its obvious to the editors what images are missing the caption. The TreeRenderingNotification can help here. This notification is published whenever a list of child nodes is created in the backoffice. In my example I am using this Notification to change the icon colour of the media node to red if the image caption is missing.

Every Notification in Umbraco needs to be handled, so I start off with a NotificationHandler. My code checks whether the TreeAlias of the notification is Media. If true, then it gets the media item using _umbracoContextFactory.EnsureUmbracoContext() and then adds a css class to the node.

public class MediaTreeNodeRenderingNotificationHandler : INotificationHandler<TreeNodesRenderingNotification>
    {
        private readonly IUmbracoContextFactory _umbracoContextFactory;

        public MediaTreeNodeRenderingNotificationHandler(IUmbracoContextFactory umbracoContextFactory)
        {
            _umbracoContextFactory = umbracoContextFactory;
        }

        public void Handle(TreeNodesRenderingNotification notification)
        {
            if (notification.TreeAlias == Constants.Trees.Media)
            {
                var umbracoContextReference = _umbracoContextFactory.EnsureUmbracoContext();

                using (umbracoContextReference)
                {

                    foreach (var node in notification.Nodes)
                    {
                        if (int.TryParse(node.Id.ToString(), out var nodeId) && nodeId > 0)
                        {
                            var mediaItem = umbracoContextReference.UmbracoContext.Media.GetById(nodeId);
                            if (mediaItem != null)
                            {
                                if (mediaItem.ContentType.Alias == Image.ModelTypeAlias && (!mediaItem.HasValue("caption")
                                    || mediaItem.Value<string>("caption").IsNullOrWhiteSpace()))
                                {
                                    node.CssClasses.Add("caption-missing");
                                }
                            }

                        }
                    }
                }
            }            
        }
    }

Now I need to add some styling in App_Plugins. The caption-missing class gets added to an li element. My css rule looks as shown below.

li.caption-missing span.umb-tree-icon {
    color: red;
}

I also need to register this css using a package.manifest.

{
    "css": [
        "~/App_Plugins/customstyles/customstyles.css"
    ]
}

Finally, I need to register my notification handler in Startup.cs. You can do it using a Composer or an extension method but I have kept it simple for now.

AddNotificationHandler<TreeNodesRenderingNotification, MediaTreeNodeRenderingNotificationHandler>()

And the result? For the media items where the caption is missing the node icon is in red :-)