Wednesday, July 30, 2014

How to create Custom Ribbon Button to Move Documents in Library with Metadata/versions

This article is follow up from my last article "OneNote Custom Actions to support Create/Move Pages and Sections and conversion to Folder in SharePointwith a new feature "Move document in Library" Ribbon Action.

This Feature gives to users the ability to manage documents in a very easy way using a tree Dialog of folders from the Document Library and maintain the Metadata/versions associated.

Here the final output of the solution,


One thing i didn't like in my last article was the ability to manage documents. The "Drag and Drop" feature from SharePoint 2013 is a GREAT feature, but users aren't that skillful about managing documents in folders and they get confused very easily.  
Like i show in my last video you can count a loot of steps to move documents from one folder to another even using the drag and drop option and this is what i am trying to avoid.

There is another Out of Box tool call "Site Content and Structure Feature" that does this and a lot more but i don't want to use a cannon to kill a fly.... 

Site Content and Structure Feature

This great Out of the Box feature from SharePoint already exist for some years and gives users the ability to manage items or Document across the Site Collection, but this option just exist when Web Content Management is activated and with SharePoint Standard license, no to SharePoint Foundation and this is the reason why i created this feature, is more limited (Only move documents in current Document Library folders to preserve the Metadata) but responds my needs without to much clicks. 

Pre-Conditions:
You need to have SharePoint Standard license then you should activate the following feature:

  • Site collection features
    • Activate "SharePoint Server Publishing Infrastructure"
  • Manage site features
    • Activate "SharePoint Server Publishing"

After activated you can access in the foloowing path

Site Settings > Site Administration > Content and structure



To support this option, was used the SharePoint Out of the Box Method "LaunchPickerTreeDialogSelectUrl" already discuss in early articles.

Here are some links that support me in this article:
OneNote Custom Actions to support Create/Move Pages and Sections and conversion to Folder in SharePoint
http://aaclage.blogspot.ch/2014/07/onenote-custom-actions-to-support.html
SharePoint 2013: Manage Site/Web/Lists/Folder Filter using Picker Tree Dialog (LaunchPickerTreeDialogSelectUrl )

http://aaclage.blogspot.ch/2014/02/sharepoint-2013-manage-siteweb-lists.html
SharePoint 2013 App - Manage List Threshold (Moving Multiple Documents in Folders) Office365/ On-premise
http://aaclage.blogspot.ch/2014/02/sharepoint-2013-app-manage-list.html
SharePoint App Processlynx Custom Action and Ribbon Manager Launch
http://aaclage.blogspot.ch/2014/06/sharepoint-app-processlynx-custom.html

How solution "Move document in Library" Works

This solution creates a new Ribbon call "Move document in Library" in all templates of Document Libraries and is enabled when a document is selected.


When the Ribbon "Move document in Library" is enabled you are able to select the option.
This option opens a dialog box of the Library and his folders and sub folder "same behavior when users uploads documents to a specific folder".
This dialog box give the ability to select the folder where the document will be moved.


After select OK in the dialog box the document will be moved to the selected Subfolder as shown in the image without losing Metadata or versions.

How was configured(Implementation)

To configured this funcionalities i used the Processlynx Custom Action & Ribbon Manager for the customizations of the Ribbon and Actions associated and everything was made using Javascript and JSOM.
But you can also use Visual Studio declarative XML, JSOM or REST Custom Actions from SharePoint.

This code was tested in Office 365 Enviroment and Internet Explorer Browser 11.

With Processlynx Custom Action & Ribbon Manager

This SharePoint App Manage the CustomActions in the HostWeb in a very eficient and user friendly way.
For more info about the tool here a link


This options was configured in my last article OneNote Custom Actions to support Create/Move Pages and Sections and conversion to Folder in SharePoint and was given a new option in the Custom Action "OneNote Ribbon Support".


Configure "Move document in Library" Ribbon

LocationRibbon.Documents.Manage

Enable Script Code:

javascript: var EnableDisableItem = function() {
 this.clientContext = SP.ClientContext.get_current();
 this.selectedItems = SP.ListOperation.Selection.getSelectedItems(this.clientContext);
 if (selectedItems.length==1)
 {
if (selectedItems[0].fsObjType == 0)
{return true;}
else 
{return false;}
 }
 if (selectedItems.length!=1)
 {return false;}
 };
 EnableDisableItem();

Action Script Code:

javascript:
function loadScript(url, callback){
    var script = document.createElement("script");
    script.type = "text/javascript";
    if (script.readyState){
        script.onreadystatechange = function(){
            if (script.readyState == "loaded" || script.readyState == "complete"){
                script.onreadystatechange = null;callback();
            }};
    } else {
        script.onload = function(){callback();};
    }
    script.src = url;
    document.getElementsByTagName("head")[0].appendChild(script);
getWebProperties();
}
function LaunchTargetPicker(WebId,ListId,RootFolderList) {
var values = SP.ListOperation.Selection.getSelectedItems();
    var callback = function (dest) {
        if (dest != null && dest != undefined && dest[3] != null) {MoveItems(dest[3],values,ListId,RootFolderList);}
    };
ListId.replace("{", "");
ListId.replace("}", "");
    var iconUrl = "/_layouts/15/images/smt_icon.gif?rev=32";
SP.SOD.executeFunc('pickertreedialog.js', 'LaunchPickerTreeDialogSelectUrl', function () {
        LaunchPickerTreeDialogSelectUrl('CbqPickerSelectListTitle', 'CbqPickerSelectListText', 'websListsFolders', 'SPList:'+ListId+'?SPWeb:'+WebId+':', _spPageContextInfo.siteAbsoluteUrl, '', '', '', iconUrl, '', callback, 'true', '');
    });
}
function getWebProperties() {
        var ctx = new SP.ClientContext.get_current();
        var web = ctx.get_web();
        ctx.load(web,'Id');
        ctx.executeQueryAsync(function(){getListRootUrl(web.get_id(),'{ListId}')},Function.createDelegate(this, this.error));
    }
function getListRootUrl(WebID,ListId){
ListId.replace("{", "");
ListId.replace("}", "");
var ctx = new SP.ClientContext.get_current();
        var targetList = ctx.get_web().get_lists().getById(ListId);
var RootFolderList = targetList.get_rootFolder();
        ctx.load(RootFolderList, 'ServerRelativeUrl'); ctx.executeQueryAsync(function(){LaunchTargetPicker(WebID,ListId,RootFolderList)},Function.createDelegate(this, this.error));
}

function MoveItems(SelectedFolder,SelectedItem,ListId,RootFolderList) {
    Items = SelectedItem;
ListId.replace("{", "");
ListId.replace("}", "");
    var ctx = new SP.ClientContext.get_current();  
var targetList = ctx.get_web().get_lists().getById(ListId);    
    var currentItem = targetList.getItemById(Items[0].id);
    var file = currentItem.get_file();
    ctx.load(file, 'Name');
    ctx.executeQueryAsync(function(){
try {
if (file != null) {
var _destinationlibUrl;
if (SelectedFolder == "/")
{ _destinationlibUrl = RootFolderList.get_serverRelativeUrl()+ SelectedFolder + file.get_name(); }
else {
_destinationlibUrl = RootFolderList.get_serverRelativeUrl()+ SelectedFolder +"/"+ file.get_name();
}
file.moveTo(_destinationlibUrl, SP.MoveOperations.allowBrokenThickets);
ctx.executeQueryAsync(function(){SP.UI.Notify.addNotification('File moved', false);SP.UI.ModalDialog.RefreshPage(SP.UI.DialogResult.OK);}, Function.createDelegate(this, this.error));
}
} catch (e) {
alert(e.message);
}
}, Function.createDelegate(this, this.error));
}
function MoveFileHandler(SelectedFolder,file,RootFolderList) {
 }
 function error(sender,args){
alert('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
 }
loadScript(_spPageContextInfo.webAbsoluteUrl+"/_layouts/15/pickertreedialog.js", function(){}); 

Here a simple Form of the configuration:


or use the Code Source editor from the Tool



Configure with SharePoint REST/JSOM or Declarative XML

For the Custom Ribbon/Actions you can include the Custom Ribbon Action with the following XML Structure example:

<CommandUIExtension xmlns="http://schemas.microsoft.com/sharepoint/">
<CommandUIDefinitions>
<CommandUIDefinition Location="<Add Location>.Controls._children">
<Button Id="My Custom Button" LabelText="<Add LabelText>" Image32by32="/_layouts/15/1033/images/formatmap32x32.png?rev=33" Image32by32Left="-305" Image32by32Top="-169" ToolTipTitle="<Add TooltipTile>" Command="<Add ID>.Command" TemplateAlias="o1" />
</CommandUIDefinition>
</CommandUIDefinitions>
<CommandUIHandlers>
<CommandUIHandler Command="<Add ID>.Command" CommandAction="<Add action Code here>" EnabledScript="<Add validation Code here>" />
</CommandUIHandlers>
</CommandUIExtension>

For the REST call you can use the following link
For SharePoint JSOM call you can use the following link

Video


Support Links:
OneNote Custom Actions to support Create/Move Pages and Sections and conversion to Folder in SharePoint
http://aaclage.blogspot.ch/2014/07/onenote-custom-actions-to-support.html
SharePoint 2013: Manage Site/Web/Lists/Folder Filter using Picker Tree Dialog (LaunchPickerTreeDialogSelectUrl )

http://aaclage.blogspot.ch/2014/02/sharepoint-2013-manage-siteweb-lists.html
SharePoint 2013 App - Manage List Threshold (Moving Multiple Documents in Folders) Office365/ On-premise
http://aaclage.blogspot.ch/2014/02/sharepoint-2013-app-manage-list.html
SharePoint App Processlynx Custom Action and Ribbon Manager Launch
http://aaclage.blogspot.ch/2014/06/sharepoint-app-processlynx-custom.html

Hope you like this article,
Kind regards,
André Lage
Post a Comment