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"> |
| <p 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"> |
| <p 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> |
| <a 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
| 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); |
| } |
| } |
| } |
| |
| |
| |