Oct 12, 2017

Note board comment notifications

It is common case to request notification for the comments someone makes in your pages through Note Board web part. Since this is not supported out-of-the-box, the goal could be fulfilled only through custom code or 3rd party solution.
Next objectives must be addressed for completing the task:
  • what will trigger the notification – time based timer job (implies WSP package on prem or Azure hosted .Net code in o365) or hitting the "Post" button in the Note Board web part (JavaScript somehow…)
  • what will notification include – I guess the bare minimum that would be required is what is the page and what the last posted comment was
  • what kind of notification is required – email or something else
The shortest path is going with JavaScript code that is triggered after the "Post" button has been hit by the end-user, which triggers email notification with the comment details to be sent out.
Here is how to achieve this:
  • subscribe to the "Post" button for the Note Board web part after the comment has been posted to the discussion history
$(".ms-socialCommentContents input[id$='_PostBtn']").click(function () {

       //todo: your custom code here

       return false;

   });
  • read with SocialDataService.asmx the last comment for this page
function GenerateDataXML (url) { 

 

       var d1 = new Date ();

       var d2 = new Date ( d1 );

       d2.setHours ( d1.getHours() - 1 );

       var d3 = d2.toISOString();;

       

       var soapXml = "<?xml version='1.0' encoding='utf-8'?><soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" +   

        "<soap:Body>" +   

        "<GetCommentsOnUrl xmlns=\"http://microsoft.com/webservices/SharePointPortalServer/SocialDataService\">" +   

            "<url>" + url + "</url>" +   

            "<maximumItemsToReturn>5</maximumItemsToReturn>" +

            "<startIndex>0</startIndex>" +

            "<excludeItemsTime>" + d3 + "</excludeItemsTime>" +

        "</GetCommentsOnUrl>" +   

        "</soap:Body>" +   

        "</soap:Envelope>" ;

        

        return soapXml;   

    }   
This example returns last 5 comments made within last hour.
Then, we can fetch the last comment made and retrieve the text and use who posted it:
$(content).find('SocialCommentDetail').each(function (index) {

            if (index == 0)

            {

                var comment = $(this);

                var owner = comment.find('Owner')[0].innerHTML;

                var text = unescape(comment.find('Comment')[0].textContent);

               

                callback(owner, text);


                return false;

            }


        });
  • then we use SP.Utilities.Utility.SendEmail to send email
Below is the source code of all actions:
function ReturnLastComment(url, callback) {   

    var dataXML = GenerateDataXML([url]); 

         


     var soapAction = "http://microsoft.com/webservices/SharePointPortalServer/SocialDataService/GetCommentsOnUrl";

     var svcUrl = window.location.protocol + "//" + window.location.host + _spPageContextInfo.webServerRelativeUrl + "/_vti_bin/SocialDataService.asmx";

     $.ajax({   

        url: svcUrl,   

        data: dataXML,  

        headers: {

            'SOAPAction': soapAction,

            'Content-Type': 'text/xml; charset=\"utf-8\"',

            'Accept': 'application/xml, text/xml, */*'

        },        

        dataType: "xml",        

        method: "POST",   

        transformRequest: null,

        success: processResult,   

        error: function (request, error) {


           console.log('error: ' + request.responseText);

        }    



     })   

   

     //Following function generates the require soap XML   

     function GenerateDataXML (url) { 

 

        var d1 = new Date ();

        var d2 = new Date ( d1 );

        d2.setHours ( d1.getHours() - 1 );

        var d3 = d2.toISOString();;

        

        var soapXml = "<?xml version='1.0' encoding='utf-8'?><soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" +   

         "<soap:Body>" +   

         "<GetCommentsOnUrl xmlns=\"http://microsoft.com/webservices/SharePointPortalServer/SocialDataService\">" +   

             "<url>" + url + "</url>" +   

             "<maximumItemsToReturn>5</maximumItemsToReturn>" +

             "<startIndex>0</startIndex>" +

             "<excludeItemsTime>" + d3 + "</excludeItemsTime>" +

         "</GetCommentsOnUrl>" +   

         "</soap:Body>" +   

         "</soap:Envelope>" ;

         

         return soapXml;   

     }   

   

     function processResult(content, txtFunc, xhr) {  

         

         $(content).find('SocialCommentDetail').each(function (index) {

             if (index == 0)

             {

                 var comment = $(this);

                 var owner = comment.find('Owner')[0].innerHTML;

                 var text = unescape(comment.find('Comment')[0].textContent);

                

                 callback(owner, text);

 

                 return false;

             }

          

         });

     }  

}

 

function bindCommentsEvents()

{

    $(".ms-socialCommentContents input[id$='_PostBtn']").click(function () {

 

        var currentPageUrl = window.location.protocol + "//" + window.location.host + _spPageContextInfo.serverRequestPath;

        ReturnLastComment(currentPageUrl, function (owner, text) {

            var result = "last comment: " + owner + "; " + text;

            //alert(result);

 

            var mailBody = "<br>commented by: " + owner + "<br>" + "page: " + currentPageUrl +  "<br>comment: " + text;

            processSendEmails(mailBody)

        });

 

        return false;

    });

}

function processSendEmails(body) {

 

    var from = 'no-reply@domain',

        to = 'xxxx@domain',

        body = 'A comment has just been added to one of your pages.\n' + body,

        subject = 'New Comment';

 

    // Call sendEmail function

    //

    sendEmail(from, to, body, subject);

}

 

 

function sendEmail(from, to, body, subject) {

    //Get the relative url of the site

    var siteurl = _spPageContextInfo.webServerRelativeUrl;

    var urlTemplate = siteurl + "/_api/SP.Utilities.Utility.SendEmail";

    $.ajax({

        contentType: 'application/json',

        url: urlTemplate,

        type: "POST",

        data: JSON.stringify({

            'properties': {

                '__metadata': {

                    'type': 'SP.Utilities.EmailProperties'

                },

                'From': from,

                'To': {

                    'results': [to]

                },

                'Body': body,

                'Subject': subject

            }

        }),

        headers: {

            "Accept": "application/json;odata=verbose",

            "content-type": "application/json;odata=verbose",

            "X-RequestDigest": jQuery("#__REQUESTDIGEST").val()

        },

        success: function(data) {


            console.log('Email Sent Successfully');

        },

        error: function(err) {


            console.log('Error in sending Email: ' + JSON.stringify(err));

        }

    });

}
Caveats:
  • Outgoing email settings must be configured if on-premises
  • make sure the function that subscribes to click button of the Post button (bindCommentsEvents) is invoked on your page load – it could be through Script Editor web part
  • if there is more than one web part on your page you may need to adjust your jquery selector

Read full article!