-
-
Notifications
You must be signed in to change notification settings - Fork 58
Sharepoint Discussion Board
Since SharepointPlus v5, you can deal with Discussion Board.
You can either use $SP().webService()
with AddDiscussionBoard following the format explained here or here or here, or you can use $SP().list().add()
, but, in that case, your whole board will need to use this method (you cannot mix normal board update with programmatic update)
I'll explain here how to use the second method.
First, a board discussion item returns the below fields:
<?xml version="1.0" encoding="utf-8" ?>
<z:row xmlns:z='#RowsetSchema'
ows_ContentTypeId='0x010700135BC7419F95B04C8EA15325163C1444'
ows_Body='<div class=ExternalClassAAF51B42E3834F8D90CA3A8DA7739064><div>second sample item<br><br><hr><b>From: </b>System Account<br><b>Posted: </b>Wednesday, June 04, 2008 5:14 PM<br><b>Subject: </b>sample item one<br><br><div class=ExternalClassF19C451E2C284124AB09D103E8A70A18><div>first sample item</div></div></div></div>'
ows_TrimmedBody='<div class=ExternalClass4D66DF23C3C649C4985CFE81A1E2E0E2><div>second sample item<br></div></div>'
ows_ParentFolderId='1'
ows_ID='2'
ows_ContentType='Message'
ows_Modified='2008-06-04 17:14:33'
ows_Created='2008-06-04 17:14:33'
ows_Author='1073741823;#System Account'
ows_Editor='1073741823;#System Account'
ows_owshiddenversion='1'
ows_WorkflowVersion='1'
ows__UIVersion='512'
ows__UIVersionString='1.0'
ows_Attachments='0'
ows__ModerationStatus='0'
ows_SelectTitle='2'
ows_Order='200.000000000000'
ows_GUID='{8FAC9A20-6343-48A3-8BE3-CD7E17E45894}'
ows_FileRef='2;#SiteDirectory/mktg/Lists/TeamDiscussion/sample item one/2_.000'
ows_FileDirRef='2;#SiteDirectory/mktg/Lists/Team Discussion/sample item one'
ows_Last_x0020_Modified='2;#2008-06-04 17:14:33'
ows_Created_x0020_Date='2;#2008-06-04 17:14:33'
ows_FSObjType='2;#0'
ows_PermMask='0x7fffffffffffffff'
ows_FileLeafRef='2;#2_.000'
ows_UniqueId='2;#{87C5CD04-7D68-4B26-B00C-DD76AE7B96D8}'
ows_ProgId='2;#'
ows_ScopeId='2;#{6ED2F3B8-3D0A-4B4F-B092-C9A6D1942AE2}'
ows__EditMenuTableStart='2_.000'
ows__EditMenuTableEnd='2'
ows_LinkFilenameNoMenu='2_.000'
ows_LinkFilename='2_.000'
ows_ServerUrl='/SiteDirectory/mktg/Lists/Team Discussion/sample item one/2_.000'
ows_EncodedAbsUrl='http://moss.litwareinc.com/SiteDirectory/mktg/Lists/Team%20Discussion/sample%20item%20one/2_.000'
ows_BaseName='2_'
ows_MetaInfo='2;#'
ows__Level='1'
ows__IsCurrentVersion='1'
ows_ThreadIndex='0x01CA94B8313E972C16929A454ACFA141B2588F7291DB000004B927'
ows_ShortestThreadIndexIdLookup='1;#'
ows_DiscussionTitleLookup='1;#sample item one'
ows_DiscussionTitle='sample item one'
ows_ReplyNoGif='SiteDirectory/mktg/Lists/Team Discussion/sample item one'
ows_ThreadingControls='0x01CA94B8313E972C16929A454ACFA141B2588F7291DB000004B927'
ows_IndentLevel='0x01CA94B8313E972C16929A454ACFA141B2588F7291DB000004B927'
ows_Indentation='0x01CA94B8313E972C16929A454ACFA141B2588F7291DB000004B927'
ows_StatusBar='2008-06-05T00:14:33Z'
ows_BodyAndMore='<div class=ExternalClassAAF51B42E3834F8D90CA3A8DA7739064><div>second sample item<br><br><hr><b>From: </b>System Account<br><b>Posted: </b>Wednesday, June 04, 2008 5:14 PM<br><b>Subject: </b>sample item one<br><br><div class=ExternalClassF19C451E2C284124AB09D103E8A70A18><div>first sample item</div></div></div></div>'
ows_MessageBody='<div class=ExternalClassAAF51B42E3834F8D90CA3A8DA7739064><div>second sample item<br><br><hr><b>From: </b>System Account<br><b>Posted: </b>Wednesday, June 04, 2008 5:14 PM<br><b>Subject: </b>sample item one<br><br><div class=ExternalClassF19C451E2C284124AB09D103E8A70A18><div>first sample item</div></div></div></div>'
ows_BodyWasExpanded='{8FAC9A20-6343-48A3-8BE3-CD7E17E45894}'
ows_QuotedTextWasExpanded='{8FAC9A20-6343-48A3-8BE3-CD7E17E45894}'
ows_CorrectBodyToShow='<div class=ExternalClass4D66DF23C3C649C4985CFE81A1E2E0E2><div>second sample item<br></div></div>' ows_FullBody='<div class=ExternalClassAAF51B42E3834F8D90CA3A8DA7739064><div>second sample item<br><br><hr><b>From: </b>System Account<br><b>Posted: </b>Wednesday, June 04, 2008 5:14 PM<br><b>Subject: </b>sample item one<br><br><div class=ExternalClassF19C451E2C284124AB09D103E8A70A18><div>first sample item</div></div></div></div>'
ows_LimitedBody='<div class=ExternalClassAAF51B42E3834F8D90CA3A8DA7739064><div>second sample item<br><br><hr><b>From: </b>System Account<br><b>Posted: </b>Wednesday, June 04, 2008 5:14 PM<br><b>Subject: </b>sample item one<br><br><div class=ExternalClassF19C451E2C284124AB09D103E8A70A18><div>first sample item</div></div></div></div>'
ows_MoreLink='2'
ows_LessLink='2'
ows_ToggleQuotedText='2'
ows_Threading='0x01CA94B8313E972C16929A454ACFA141B2588F7291DB000004B927'
ows_PersonImage='System Account'
ows_PersonViewMinimal='System Account'
ows_IsRootPost='0'
ows_ItemChildCount='2;#0'
ows_ServerRedirected='0'/>
Some explanations:
-
DiscussionTitle
returns the Subject/Title for the discussion thread (only for replies) -
ItemChildCount
returns the number of replies for the discussion thread -
Title
is null for replies, but represents the subject for topics -
Body
is the body content for both topic and replies -
ParentFolderId
the item ID of the parent topic -
ContentType
is Discussion for topic, and Message for replies -
ThreadIndex
permits to connect messages together and to order them into the discussion -
ServerUrl
will be used for theRootFolder
parameter for direct replies to topics -
FileDirRef
will be used for theRootFolder
parameter for replies of replies
Let's speak a bit about ThreadIndex
. There is a very technical documentation about it, and it's difficult to duplicate.
However, it's possible to define our own index! We just need to respect the number of bits.
Examples of ThreadIndex
from a Sharepoint Discussion Board:
Topic: "0x01D51560C1C20E7086D03C904FC9941D033E62126633"
Reply1: "0x01D51560C1C20E7086D03C904FC9941D033E621266330000073AC4"
SubReply1: "0x01D51560C1C20E7086D03C904FC9941D033E621266330000073AC40000034446"
SubSubReply1: "0x01D51560C1C20E7086D03C904FC9941D033E621266330000073AC400000344460004848064"
Reply2: "0x01D51560C1C20E7086D03C904FC9941D033E62126633000008DC95"
(Disclaimer: I'll use the term characters instead of speaking about bits or bytes, to simplify the explanation)
The idea is to have a first index of 44 characters (e.g. 01D51560C1C20E7086D03C904FC9941D033E62126633), and all direct replies will have the same first 44 characters, followed by 10 other characters. Each time we have a sub-reply, we need to add 10 more characters.
To handle our index we'll use the current timestamp.
So let's do some code:
// Define a Thread Index for the topic
var threadIndex = Array(35).join('0') + Math.round(Date.now()/10).toString(16);
// Create a new topic
$SP().list("MyBoard").add({
Title:"Topic 1",
Body:"Discussion about first topic",
ContentType:"Discussion",
ThreadIndex:threadIndex
})
The ThreadIndex
just created has 44 characters: 34 zero (Array(35).join('0')
) and the current timestamp represented as an hexadecimal of 10 characters (Math.round(Date.now()/10).toString(16)
).
To add a reply for this thread:
// We first get the details from the topic
$SP().list("MyBoard").get({
fields:"ID,ThreadIndex,ServerUrl",
where:"ID = 1", // ID of the topic, or where:"Title = 'Topic 1'"
folderOptions:{show:"FilesAndFolders_Recursive"} // we need this option to get all
}).then(function(data) {
if (data.length===0) throw "ERROR: topic not found";
else {
// we can now create the reply
var parentID = data[0].getAttribute("ID");
// threadIndex = original ThreadIndex + 10 characters that represent the current time in hexadecimal
var threadIndex = data[0].getAttribute("ThreadIndex") + Math.round(Date.now()/10).toString(16);
var rootFolder = $SP().cleanResult(data[0].getAttribute("ServerUrl"));
return $SP().list("MyBoard").add({
Body:"Reply for the first topic",
ContentType:"Message",
ParentFolderId:parentID,
ThreadIndex:threadIndex
}, {rootFolder:rootFolder}); // don't forget the "rootFolder" option!
}
}).then(function(res) {
if (res.passed.length===1) alert("Done!");
else alert("Failed :(");
})
if you want to add a reply to a reply:
// We first get the details for the reply we want to comment
$SP().list("MyBoard").get({
fields:"ID,ThreadIndex,FileDirRef,ParentFolderId",
where:"ID = 2", // ID of the reply
folderOptions:{show:"FilesAndFolders_Recursive"}
}).then(function(data) {
if (data.length===0) throw "ERROR: message not found";
else {
// we can now create the reply of the reply
var parentID = data[0].getAttribute("ParentFolderId");
// threadIndex = original ThreadIndex + 10 characters that represent the current time in hexadecimal
var threadIndex = data[0].getAttribute("ThreadIndex") + Math.round(Date.now()/10).toString(16);
// here we need to use FileDirRef
var rootFolder = '/' + $SP().cleanResult(data[0].getAttribute("FileDirRef"));
return $SP().list("MyBoard").add({
Body:"Reply of the Reply for the first topic",
ContentType:"Message",
ParentFolderId:parentID,
ThreadIndex:threadIndex
}, {rootFolder:rootFolder});
}
}).then(function(res) {
if (res.passed.length===1) alert("Done!");
else alert("Failed :(");
})
And get all messages from the board:
$SP().list("MyBoard").get({
fields:"ID,DiscussionTitle,Title,Body,ItemChildCount,ContentType,ThreadIndex",
where:"ID > 0",
orderby:"ThreadIndex",
folderOptions:{show:"FilesAndFolders_Recursive"} // we need this option to get all topics and replies
}).then(function(data) {
data.forEach(function(d) {
var blank = d.getAttribute("ThreadIndex").slice(46).length/5;
console.log(Array(blank).join(" ")
+ (d.getAttribute("ContentType")==="Discussion"?"[TOPIC] "+d.getAttribute("Title"):"[REPLY in "+d.getAttribute("DiscussionTitle")+"] "+d.getAttribute("Body")))
})
})
In our example the above code will return into the console:
[TOPIC] Topic 1
[REPLY in Topic 1] Reply for the first topic
[REPLY in Topic 1] Reply of the Reply for the first topic
And finally, to edit or delete, just use the regular functions:
$SP().list("MyBoard").update({ID:2, Body:"Updated Body"});
$SP().list("MyBoard").remove({ID:2});