Christmas Bonus - Workflow with comments in Sitefinity 3.x

December 25, 2009 Digital Experience

In this blog post I will show you how to create a workflow with comments. This is very useful when the workflow for your website is enabled and you want to leave a message to your content editors why a give content has been approved, declined, published. Generally the idea is only to leave a message when you decline a content item, so your editor will be able to fix the problem with this content and send it back for approval. Here is what I did to get workflow comments working.

1. I created a new metakey called WorkflowDeclineComment1

<add key="News.WorkflowDeclineComment1" valueType="ShortText" visible="True" searchable="True" sortable="True"></add> 

As you can see I added the metakey for news provider, but you can do it for each other Generic Content based provider( Events, Blogs, Generic_Conent.

2. Then I mapped the NewsItemPreview external template through ControlsConfig file.

    <viewSettings hostType="Telerik.News.WebControls.Admin.NewsItemPreview" 
                  layoutTemplatePath="~/Sitefinity/Admin/ControlTemplates/News/NewsItemPreview.ascx" /> 

3. I modified the template by adding one TextBox and one Label. The texbox will be used by the approver to set text when a content item is declined. I used jQuery to toggle the TexBox on click. The Literal will be visible to all.

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="NewsItemPreview.ascx.cs" Inherits="Sitefinity_Admin_ControlTemplates_News_NewsItemPreview" %> 
 
<%@ Register TagPrefix="telerik" Namespace="Telerik.Workflow.WebControls" Assembly="Telerik.Workflow" %> 
<%@ Register TagPrefix="telerik" Namespace="Telerik.Cms.Engine.WebControls" Assembly="Telerik.Cms.Engine" %> 
<%@ Register TagPrefix="telerik" Namespace="Telerik.Localization.WebControls" Assembly="Telerik.Localization" %> 
<telerik:JsFileLink id="jsLink" runat="server" ScriptType="jQuery" /> 
 
<script type="text/javascript"
 
    $(document).ready(function() { 
        $("#" + "<%= postCommentsPlh.ClientID %>").hide(); 
    }); 
    function ToggleDiv() { 
          $("#" + "<%= postCommentsPlh.ClientID %>").toggle("slow"); 
   } 
 
</script> 
 
<div class="ToolsAll"
    <asp:Label ID="lockedWarning" runat="server"
        <class="locked"
            <strong>{0}</strong>  
            <asp:Literal ID="Literal1" runat="server" Text="<%$Resources:IsEditingContent %>"></asp:Literal> 
        </p> 
    </asp:Label> 
    <div class="backWrapp"
        <asp:HyperLink ID="BackButton1" CssClass="actions back" runat="server"
            <asp:Literal ID="Literal2" Text="<%$Resources:BackToAllNewsItems %>" runat="server" /> 
        </asp:HyperLink> 
    </div> 
    <telerik:RadTabStrip  
                    id="tabStrip"  
                    Align="Right"  
                    runat="server" 
                    selectedindex="0"  
                    causesvalidation="false" 
                    EnableEmbeddedSkins="false" 
                    Skin="SitefinityPages" 
                    > 
                        <Tabs> 
                            <telerik:RadTab Text="<%$Resources:View %>" ></telerik:RadTab> 
                            <telerik:RadTab Text="<%$Resources:Edit %>" ></telerik:RadTab> 
                            <telerik:RadTab Text="<%$Resources:History %>" ></telerik:RadTab> 
                        </Tabs> 
                    </telerik:RadTabStrip> 
    <div class="clear"><!-- --></div
</div> 
<div id="divWorkArea" runat="server" class="workArea"
    <telerik:MessageControl runat="server" ID="message1"
        <ItemTemplate> 
            <asp:Label runat="server" ID="messageText"></asp:Label> 
        </ItemTemplate> 
    </telerik:MessageControl> 
    <div class="view"
        <class="button_area"
            <telerik:WorkflowMenu ID="workflowMenu" runat="server" /> 
        <asp:HyperLink ID="editCommand1" runat="server" CssClass="CmsButLeft editdark"
                <strong class="CmsButRight dark"
                    <asp:Literal ID="editLiteral" runat="server" Text="<%$Resources:EditThisNews %>"></asp:Literal> 
                </strong> 
            </asp:HyperLink> 
<href="javascript:void(0)" id="test1" onclick="ToggleDiv();">Leave Workflow comment</a> 
       <div runat="server" id="postCommentsPlh"
        <asp:TextBox runat="server" ID="WorkflowDeclineComment1" /> 
 </div> 
 <asp:Label ID="WorkflowMessageLabel1" runat="server" /> 
 
 
                ..... 
                    ..... 
                         ..... 

 

4. I created a code behind of the template

  • OnPreRender - get the item and set the text of the label
  • Page_Load - get the itemand hide the texbox depending on the current user permissions using. You can do the same for the link that is used to show the TextBox
  • Inside Command event of WorkflowMenu I added the logic used to get the EventActivity CommandName and set the metadata using SetMetaData method.
  •  

    The important this here is that we have to work with StagedContent.

 

public partial class Sitefinity_Admin_ControlTemplates_News_NewsItemPreview : System.Web.UI.UserControl 
    protected override void OnPreRender(EventArgs e) 
    { 
            base.OnPreRender(e); 
            NewsItemPreview itemPreview = (NewsItemPreview)this.Parent.Parent; 
            Guid contentID = new Guid(CmsHttpRequest.Current.QueryStirng[itemPreview.ParameterKey]); 
            IContent content = itemPreview.Manager.GetContent(contentID); 
            WorkflowMessageLabel1.Text = (string)content.GetMetaData("WorkflowDeclineComment1"); 
    } 
 
    protected void Page_Load(object sender, EventArgs e) 
    { 
          workflowMenu.Command += new CommandEventHandler(workflowMenu_Command); 
          NewsItemPreview itemPreview = (NewsItemPreview)this.Parent.Parent; 
          Guid contentID = new Guid(CmsHttpRequest.Current.QueryStirng[itemPreview.ParameterKey]); 
          StagedContent content = itemPreview.Manager.GetCurrentState(contentID); 
          GlobalPermission perm; 
          perm = itemPreview.Manager.GetPermission(content); 
          WorkflowDeclineComment1.Visible = perm.CheckDemand(WorkflowRights.Approve); 
    } 
 
    void workflowMenu_Command(object sender, CommandEventArgs e) 
    { 
        WorkflowInstance instance = ((WorkflowMenu)sender).GetWorkflow(); 
        if (instance != null
        { 
            List<EventActivity> commands = new List<EventActivity>(); 
            this.LoadCommands(commands, instance.Activity.Activities); 
            int idx = int.Parse((string)e.CommandArgument); 
            if ((commands.Count > idx) && !(commands[idx].CommandName.Equals("Publish"))) 
            { 
                NewsItemPreview itemPreview = (NewsItemPreview)this.Parent.Parent; 
                Guid contentID = new Guid(CmsHttpRequest.Current.QueryStirng[itemPreview.ParameterKey]); 
                StagedContent content = itemPreview.Manager.GetCurrentState(contentID); 
 
                switch (commands[idx].CommandName) 
                { 
                    case "SendForApproval"
                        content.SetMetaData("WorkflowDeclineComment1", WorkflowDeclineComment1.Text); 
                        newsManager.Content.SavedStagedContent(content, ContentStatus.Published);                                         
                        break
                    case "Approve"
                        content.SetMetaData("WorkflowDeclineComment1", WorkflowDeclineComment1.Text); 
                        newsManager.Content.SavedStagedContent(content, ContentStatus.Published); 
                        break
                    case "Decline"
                        content.SetMetaData("WorkflowDeclineComment1", WorkflowDeclineComment1.Text); 
                        newsManager.Content.SavedStagedContent(content, ContentStatus.Published); 
                        break
         
                    case "Publish"
                        content.SetMetaData("WorkflowDeclineComment1", WorkflowDeclineComment1.Text); 
                        newsManager.Content.SavedStagedContent(content, ContentStatus.Published); 
ContentStatus.Published); 
                        break
                } 
 
            } 
        } 
    } 
 
    private void LoadCommands(List<EventActivity> commands, IList<Activity> activities) 
    { 
        foreach (Activity act in activities) 
        { 
            if (act is EventActivity) 
                commands.Add((EventActivity)act); 
            this.LoadCommands(commands, act.Activities); 
        } 
    } 
  
 
 
 

The Progress Team