Tag Archives: Sitecore client

Sitecore Workflow commands not being shown in the ribbon or gutter.

Requirement

The customer required that when an item is in a a specific workflow state, the item cannot be edited.

Sitecore has a special security permission to achieve this Workflow State Write, if you set this to deny on the relevant workflow item, the item will become readonly whilst in that state. Perfect I thought, of course you have to ensured that the user has the Workflow Command Execute permission.

Problem

Unfortunately in Sitecore 8.1.0.151207, if you do not have write access to the item, the workflow commands are not shown in the ribbon and the workflow gutter icon is not visible either.

Therefore, the user cannot approve or reject the item, unless they are an administrator!

Solution

However, if you want to display workflow commands in the ribbon even if workflow write access is denied you can follow the following steps:

  • Use dotpeak, resharper, etc and decompile Sitecore.Shell.Applications.ContentManager.Panels.WorkflowPanel class.
  • Change the namespace and or the class name.
  • Modify the CanShowCommands method, in my case I checked to see if the current user has the workflow execute permissions.
public static bool CanShowCommands(Item item, WorkflowCommand[] commands)
{
Assert.ArgumentNotNull(item, "item");
if ((item.Appearance.ReadOnly || (commands == null)) || (commands.Length <= 0))
{
return false;
}
if (Context.IsAdministrator ||(item.Access.CanWriteLanguage() && (item.Locking.CanLock() || item.Locking.HasLock())))
return true;

// get command item from 'master' database
Item curItem = item.Database.GetItem(ID.Parse(commands[0].CommandID));
// check if user can execute workflow commands
if (AuthorizationManager.IsAllowed(curItem, AccessRight.WorkflowCommandExecute, Context.User))
return true;
return false;
}
  • Build the assembly and deploy it to the website.
  • Modify the following item in the Core database /sitecore/content/Applications/Content Editor/Ribbons/Chunks/Workflow/WorkflowPanel change the Type field, so it matches your WorkflowPanel class.

I hope this helps, and yes I know it is not nice, but until this bug is fixed it was the best that I could do.

Sitecore SheerResponse.Download Error with XML

I had  a solution where we need to generate an XML file and download it from the Sitecore client. But when using SheerResponse.Download to download an XML file, it would add 2 elements to the end of the XML document (see the image below). The issue was found in sitecore 8.1 rev. 151207 (Update-1).

extra-elements

Sitecore have registered this a bug and provided a solution where I had to modify the main layout for the Sitecore client and use several support DLL’s, I decided not to do this.

Solution

I therefore did what I consider to be a nasty hack, but better than the alternative of modifying the Sitecore client, so please do not judge me for this!

SheerUI has a Eval function, which allows you to execute JavaScript within the Sitecore client. So I added an A tag, with a link to the file and then called click on the link.

internal void DownloadFile([NotNull] FileInfo file)
  {
    Assert.ArgumentNotNull(file, "file");
    var virtualPath = file.FullName;
    var rootPath = HostingEnvironment.MapPath("/");
    if (rootPath == null)
       return;

    virtualPath = virtualPath.Replace(rootPath, string.Empty);
    virtualPath = $"/{virtualPath.Replace("\\", "/")}";
    string js = $"var link=document.createElement('a');document.body.appendChild(link);link.href = '{virtualPath}';link.download='{file.Name}';link.click();";
    SheerResponse.Eval(js);
  }

How to add a button to the sitecore content editor to download data as a CSV file

In this blog I will explain how to add a button to the content editor and download data as an CSV file. For this example I will assume that we want to download the data for a given web form for marketers form as a CSV file.

Adding the button
the button

Contextual Ribbons

You may not have noticed but this is a contextual ribbon that is it is only shown when the item is based on the forms template, as it gives no meaning to have the download data as CSV added to all items.

First you need to swap to the core database, and navigate to the Contextual Ribbons item for the content editor i.e. /sitecore/content/Applications/Content Editor/Ribbons/Contextual Ribbons.

This is where all the ribbons that are only shown for specific item types are placed; within this folder there is a forms toolbar, which contains a form strip, which contains a forms chunk, which in turn contains the “Export Data as CSV” button item.

button item
The most important part of the button item is the click field, which defines the command name that will be raised when the button is clicked (I will explain how to hook this up in more detail later).

But how is a contextual ribbon associated with a given template – well that part is easy on the template item under the appearance section there is a ribbon field which can define a contextual ribbon or toolbar to be shown.

co0ntextual form

How to hook the button click up to the code that is to executed? 

We have to add a command item to the /app_config/commands.config file to bind the command name to the class that is going to provide the functionality.

<command name="forms:exportformdata" type="WFFM.SQLServer.SaveToDatabase.Infrastructure.Commands.ExportFormDataCommand, WFFM.SQLServer.SaveToDatabase" />

The class must inherit from the Sitecore Command class, and override the Execute function.

    internal class ExportFormDataCommand : Command
    {
        public override void Execute(CommandContext context)
        {
            Assert.ArgumentNotNull(context, "context");
            Assert.IsNotNull(context.Items, "context items are null");
            Assert.IsTrue(context.Items.Length > 0, "context items length is 0");

            Item contextItem = context.Items[0];
            Assert.IsNotNull(contextItem, "First context item is null");
            OpenNewWindow(contextItem.ID, contextItem.Name);
        }

        private void OpenNewWindow(ID id, string name)
        {
            Assert.ArgumentNotNull(id, "id");
            UrlString url = new UrlString(Constants.Url.ExportFromDataPage);
            url.Append(Constants.QueryString.Name.ItemId, HttpContext.Current.Server.UrlEncode(id.ToString()));
            url.Append(Constants.QueryString.Name.ItemName, HttpContext.Current.Server.UrlEncode(name));
            SheerResponse.Eval(string.Format("window.open('{0}');", url));
        }
    }

Its not very elegant, but the code generates a URL which points to a aspx page that will stream the data. The Eval method of the sheer response, allows me to execute JavaScript on the client which in this case opens a tab/window.

The aspx page doesn’t do that much it just sets the ContentType to “text/csv” and streams the data. If you want to see the complete implementation, you can download it from github

Hope this was helpful, Alan