cancel
Showing results for 
Search instead for 
Did you mean: 

Get name of forum thread and of all site users?

icrew
Champ in-the-making
Champ in-the-making
Hi all:

I'm writing a script that's triggered by a rule anytime a discussion post is created or updated in a share site.  The idea is to send out an email with the contents of any new or updated posts to the users of the Share site.

I've made pretty decent progress (I can now send an email with the title and contents of a Discussions post, and can get to the node of the site that the Discussions are in.)  However, I'm stuck on two parts of this:

1) If the Discussions post is a reply to a topic, its "title" property is an empty string.  If I walk back up the tree with document.getParent(), I can't figure out how to check for a "title" property on the parent node.  Even when I know that the parent node does have a "title" property, that property (or other discussion-post-specific properties  like "content") don't show up.  I've tried running a for loop to show all of the properties of the parent (i.e. "for (var myProperty in parent.properties)"), and those discussion-post-specific properties just aren't there.  How do I get at those properties?

2) What's the easiest way to get a list of all the members of the site, so that I can send them email?  (I'm assuming that that'll be starting from the node representing the site, no?)

Thanks,

Ian
4 REPLIES 4

icrew
Champ in-the-making
Champ in-the-making
To answer the first part of my own question:

You can get the name of a discussion thread as follows:

A discussion thread is a node of type "fm:topic".

Each of the posts in that thread are of type "fmSmiley Tongueost", and  are children of the "fm:topic" node.

When a new discussion thread is created, Alfresco creates both an "fm:topic" object, as well as a first "fmSmiley Tongueost" object in that thread as a child of the "fm:topic" object.

The title of the thread is stored in the "title" property of that first "fmSmiley Tongueost" object.

So, if you have an arbitrary node in a thread, you can get the title of the thread by doing the following:

1) Get the parent of the node you have:
var parent = document.getParent();
(That parent will be the "fm:topic" object.)

2) Get the title of the first child of the "fm:topic" object:
var threadTitle = parent.children[0].properties["title"] 

I don't know how Alfresco maintains the hierarchy of posts within a given discussion thread, but that doesn't matter for my current purposes.

Hope this is useful to someone else!

Now to go off and work on figuring out how to get a list of all the email addresses of the people who are members of the site…..

icrew
Champ in-the-making
Champ in-the-making
Finally figured out the second bit of this, too:

while ((document.getParent() != null)) {
   var parent = document.getParent();
   
   if (parent.typeShort == "st:site") {
      //get the ID of the site for use in the reply location URL
      siteID = parent.properties["name"];
      
      //get the short name of the site so we can get the group with the members of the site
      var siteShortName = parent.getSiteShortName();
      
      //use the site short name to assemble the group name
      var siteGroup = people.getGroup("GROUP_site_"+siteShortName);
      
      //get the members of that group
      var siteGroupUsers = people.getMembers(siteGroup, true);
      
      //put the emails of the members of the site into a new array for use in sending the notices
      var siteUsers = new Array;
      for (var i in siteGroupUsers)
      {
         var name1=siteGroupUsers[i];
         siteUsers.push(name1.properties["email"]);   
      }
      break;
   }

   document = parent;
}

So now I've got a rule that can be applied to the "discussions" section of a Share site that sends email to all users of that site whenever a new post is made to the discussions section of that site. It's not quite as good as letting users choose which threads they want to subscribe to, but it works for my purposes.  If there's interest, I'll try to find time to clean it up and post it to the http://wiki.alfresco.com/wiki/JavaScript_API_Cookbook page–let me know.

efestione
Champ in-the-making
Champ in-the-making
Hi,
I am really interested in this.
I think there would be a page on the wiki with the istructions to setup mail actions for all pages in Share!

For example, I need a notification for every new comment in document library and I need the title of the document which has been commented in the notification mail…

Regards
Alex

icrew
Champ in-the-making
Champ in-the-making
Hi Alex:

Sorry to be slow about responding.  Here's the script I wrote.  Here's how you use it:

1) Put it in Repository > Data Dictionary > Scripts
2) Find the site for which you wish to have the forum send out notifications in Repository > Sites
3) Click Manage Rules for the discussions folder within your site (e.g. Repository > Sites > Foo > discussions)
4) Create a new rule, which runs when Items are created or enter this folder, for All Items, performing action Execute Script (selecting this script), with it set to Rule applies to subfolders and Run rule in background

You should be good to go–all users of the site will get notified in email whenever someone posts in the forum.

Please do feel free to let me know if you find any bugs/make any improvements, but I can't promise to provide any support (or take any responsibility) if it doesn't work right.

Hope this is useful!

Ian

/*
send-forum-notify.js
version of 22/5/2011
by Ian Crew

A script for Alfresco Community Edition that takes the ownership of anything uploaded to a
directory. It can be used for site quotas or drop box functionality.

This script has only been tested on Alfresco CE 3.4c.

Legalese
This script is copyright 2011 by Ian Crew.  No warranties are expressed or implied. 
Use at your own risk.  This script may be freely distributed and modified
so long as this copyright notice is included in all derivative versions.
*/

var postContentNode = document.properties["content"];  //get the node containing the content of this post
var postContent= postContentNode.getContent();  //get the actual content of the post
var postTitle = document.properties["title"];   //get the title of the post.  Unless this is the first post in a new thread, this will be blank, and we'll fill it in below.
var   threadID = document.properties["name"];  //get the id of this post, so we can link to the thread in the email that goes out.  If this is a reply, this will get overwritten below with the id of the first post in the thread, below.

//Get the human-readable name of the creator of this post for the notification email.
var postCreator = document.properties["creator"];   //get the creator of the post.
var postCreatorPerson=people.getPerson(postCreator);
var postCreatorName=postCreatorPerson.properties["firstName"] + " " + postCreatorPerson.properties["lastName"];

//variables to be filled in below.
var siteTitle = "";
//var threadID = "";
var siteID = "";


//debugging info
//var postProperties = "\n\n\n______________________________________________________________________\nDEBUGGING\n______________________________________________________________________\n";
//postProperties += dumpEntireNode(document);


while ((document.getParent() != null)) {
   var parent = document.getParent();
   
   //postProperties += "\nPARENT " + dumpEntireNode(parent);
   
   if ((parent.typeShort == "fm:topic")  && (postTitle == "") && (parent.children[0].properties["title"] != null)) {
      //get the name of the thread for use in the subject line
      postTitle = "Re: " + parent.children[0].properties["title"] ;
      
      //get the ID of the thread for use in the reply location URL
      threadID = parent.properties["name"];
   }
   else if (parent.typeShort == "st:site") {
      //Get the name of the site for use in the message subject line
      siteTitle = parent.properties["title"];
      
      //get the ID of the site for use in the reply location URL
      siteID = parent.properties["name"];
      
      //get the short name of the site so we can get the group with the members of the site
      var siteShortName = parent.getSiteShortName();
      //postProperties += "Site Short Name:\n\t–\n" + siteShortName +"\n\t–\n";
      
      //use the site short name to assemble the group name
      var siteGroup = people.getGroup("GROUP_site_"+siteShortName);
      
      //get the members of that group
      var siteGroupUsers = people.getMembers(siteGroup, true);
      
      //put the emails of the members of the site into a new array for use in sending the notices
      var siteUsers = new Array;
      for (var i in siteGroupUsers)
      {
         var name1=siteGroupUsers[i];
         //siteUsers += dumpEntireNode(name1);
         siteUsers.push(name1.properties["email"]);   
      }
      
      //postProperties += "\nSITE USERS:\n\t–\n" + dump(siteUsers) +"\n\t–\n";
      break;
   }

   document = parent;

}

var replyLocation = "Reply to this post at\n<https://foo.bar.com/share/page/site/'+siteID+'/discussions-topicview?topicId='+threadID+">\n";


if (postContent != "") { //check for null, because some updates seem to generate two messages, one blank.

   //error checking
   if (postTitle == "") { postTitle = "Unknown post!"; }
   if (postContent == "") { postContent = "Unknown content!"; }  //this shouldn't ever happen
   if (siteTitle == "") { siteTitle = "Unknown site!"; }

   //Strip the HTML and clean up the resulting text.
   postContent = new String(postContent);  //wrap java string in javascript string so we can work with it…..
   postContent = postContent.replace(/<br \/>/g, "\n"); //turn BRs into newlines
   postContent = postContent.replace(/<.*?>/g, "");  //strip all tags
   postContent = postContent.replace(/ /g, " "); //strip nonbreaking spaces
   postContent = postContent.replace(/\n+/g, "\n\n"); //clean up consecutive newlines

   //assemble the final message, with the reply location listed before and after
   //postContent = replyLocation + "———————————————————————-\n" + postContent + "\n———————————————————————-\n" + replyLocation;
   postContent = postCreatorName + " writes:\n\n" + postContent + "\n———————————————————————-\n" + replyLocation;

   //send email, individually, to each user of the site.
   for (var i in siteUsers)
   {
      var emailAddr=siteUsers[i];
      sendMail (emailAddr, "[" + siteTitle + "] " + postTitle, postContent, document); //+postProperties
   }
}


//do the change of ownership
//changeOwner();

//logger.log("Done changing owner.");
//logger.log("———————");



//send off the email
function sendMail (recipient, subject, contents, node) {
   //send email to the specified recipients


/*   

See http://savicprvoslav.blogspot.com/2010/10/send-html-email-from-alfresco-33-with.html to send html email someday

var htmlContents =
'Mime-Version: 1.0\
Content-Type: multipart/alternative; \
   boundary="—-=_Part_2665_1854048590.1224718126252"\
\
X-Content-Type-Outer-Envelope: multipart/alternative; boundary=Apple-Mail-1–549697194\
\
\
X-Content-Type-Message-Body: text/plain;\
   charset=US-ASCII;\
   format=flowed;\
   delsp=yes\
\
——=_Part_2665_1854048590.1224718126252\
Content-Type: text/html ; charset=ISO-8859-1\
Content-Transfer-Encoding: quoted-printable\
\
\
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"\
    "http://www.w3.org/TR/html4/loose.dtd">\
<html>\
<head>\
  <meta content="text/html;charset=utf-8"\
http-equiv="Content-Type">\
<title>MVP Disk Usage Report</title>\
</head>\
<body bgcolor="#ffffff" text="#000000">\
\
' + contents + '\
\
</body></html>\
\
——=_Part_2665_1854048590.1224718126252–\
\
';

*/

   
   // create mail action
   var mail = actions.create("mail");
   mail.parameters.to = recipient;
   mail.parameters.subject = subject;
   mail.parameters.from = "foo@bar.com";
   mail.parameters.template = null;
   mail.parameters.text = contents;
   // execute action against a document      
   mail.execute(node);
}

//dump the entire node, for debugging
function dumpEntireNode (node) {
   var nodeData = "=========================\nNODE DATA\n\n";
   nodeData += "node.properties:\n\t–\n"
   for (var childProperty in node.properties)
   {
      logger.log(childProperty +"\t"+node.properties[childProperty]);
      nodeData += childProperty +"\t"+node.properties[childProperty] + "\n";      
   }
   nodeData += "\t–\n";
   
   // ARRAY:
   nodeData += "node.children:\n\t–\n" + dump (node.children) + "\t–\n";
   nodeData += "node.assocs:\n\t–\n" + dump (node.assocs) + "\t–\n";
   nodeData += "node.sourceAssocs:\n\t–\n" + dump (node.sourceAssocs) + "\t–\n";
   nodeData += "node.childAssocs:\n\t–\n" + dump (node.childAssocs) + "\t–\n";
   nodeData += "node.parentAssocs:\n\t–\n" + dump (node.parentAssocs) + "\t–\n";
   nodeData += "node.aspects:\n\t–\n" + dump (node.aspects) + "\t–\n";
   nodeData += "node.parents:\n\t–\n" + dump (node.parents) + "\t–\n";
   nodeData += "node.activeWorkflows:\n\t–\n" + dump (node.activeWorkflows) + "\t–\n";
   
   // BOOLEAN:
   nodeData += "isContainer:\t" + node.isContainer + "\n";
   nodeData += "isDocument:\t" + node.isDocument + "\n";
   nodeData += "isCategory:\t" + node.isCategory + "\n";
   //nodeData += "boolean isScriptContent(object obj):\t" + node.boolean isScriptContent(object obj) + "\n";

   // STRING
   nodeData += "content:\n\t–\n" + node.content + "\n\t–\n";
   nodeData += "url:\t" + node.url + "\n";
   nodeData += "downloadUrl:\t" + node.downloadUrl + "\n";
   nodeData += "webdavUrl:\t" + node.webdavUrl + "\n";
   nodeData += "mimetype:\t" + node.mimetype + "\n";
   nodeData += "size:\t" + node.size + "\n";
   nodeData += "displayPath:\t" + node.displayPath + "\n";
   nodeData += "qnamePath:\t" + node.qnamePath + "\n";
   nodeData += "icon16:\t" + node.icon16 + "\n";
   nodeData += "icon32:\t" + node.icon32 + "\n";
   nodeData += "isLocked:\t" + node.isLocked + "\n";
   nodeData += "id:\t" + node.id + "\n";
   nodeData += "nodeRef:\t" + node.nodeRef + "\n";
   nodeData += "name:\t" + node.name + "\n";
   nodeData += "type:\t" + node.type + "\n";
   nodeData += "typeShort:\t" + node.typeShort + "\n";
   nodeData += "parent:\t" + node.parent + "\n";
   
   nodeData += node.getSiteShortName();
   nodeData += "=============================\n";
   
   return nodeData;
}

/**
* Function : dump()
* Arguments: The data - array,hash(associative array),object
*    The level - OPTIONAL
* Returns  : The textual representation of the array.
* This function was inspired by the print_r function of PHP.
* This will accept some data as the argument and return a
* text that will be a more readable version of the
* array/hash/object that is given.
* Docs: http://www.openjs.com/scripts/others/dump_function_php_print_r.php
*/
function dump(arr,level) {
   var dumped_text = "";
   if(!level) level = 0;
   
   //The padding given at the beginning of the line.
   var level_padding = "";
   for(var j=0;j<level+1;j++) level_padding += "    ";
   
   if(typeof(arr) == 'object') { //Array/Hashes/Objects
      for(var item in arr) {
         var value = arr[item];
         
         //if(typeof(value) == 'object') { //If it is an array,
         //   dumped_text += level_padding + "'" + item + "' …\n";
         //   dumped_text += dump(value,level+1);
         // } else {
            dumped_text += level_padding + "'" + item + "' => \"" + value + "\"\n";
         //}
      }
   } else { //Stings/Chars/Numbers etc.
      dumped_text = "===>"+arr+"<===("+typeof(arr)+")";
   }
   return dumped_text;
}