Wednesday, August 8, 2018

Using CSR in List Items (SharePoint server 2013, 2016)

All of us have become very advanced users and of course we use various messengers for calls, such as Skype and many others, so users need to make a call. In my case, the contact information was in the SharePoint list, i.e. there was all the information including the email and of course the phones. In the list view, I see all users and their phones, but how do I call the phone number with a simple click, the more Skype is active? To help me came "CSR".

How is create of this solution, lets get started!

In my list 2 columns "Title" and "CellPhone", I was add 5 items (Users):


We need to add 2 items in library "Site Assets" "jquery-2.1.3.min.js" and picture size 16*16 (Metro-Phone-Blue-16.png), then create JavaScript-file CellPhone.js, open it and add code, where we using "Clien-Side rendering" and save it
<script type="text/javascript" src="/sites/test/SiteAssets/jquery-2.1.3.min.js"></script>
<script type="text/javascript">
(function () { 
    var linkFilenameFiledContext = {}; 
    linkFilenameFiledContext.Templates = {}; 
    linkFilenameFiledContext.Templates.Fields = { 
        "CellPhone": { "View": linkFilenameFiledTemplate } 
    };
    SPClientTemplates.TemplateManager.RegisterTemplateOverrides(linkFilenameFiledContext); 
})(); 

function linkFilenameFiledTemplate(ctx) {
    var title = ctx.CurrentItem["CellPhone"];
    var phone = ctx.CurrentItem["CellPhone"];
    title = title.replace(/\.[^/.]+$/, "") 
    if (phone != '') {
        return title + " <a href=" + "'callto: +7 " + phone + "'><img src='/sites/test/SiteAssets/Metro-Phone-Blue-16.png'/ title='Call number'></a>"; 
    } 
}
</script>
and save it:


"Add a Web Part" -> Category "Media and content" -> Add "Content Editor":



Content Editor "Edit Web Part"



Add script "Content link" url, your JavaScript-file('/sites/test/SiteAssets/CellPhone.js') and "Apply"



Refresh Page your list and we will see:



Click the button phone, call to Skype:



Happy Coding!

Tuesday, August 7, 2018

SharePoint migration (2010, 2013, 2016) errors correction

Many of us have faced migration to the new version SharePoint server and, of course, not without exception, experienced difficulties with errors, today I will describe the mistakes I personally encountered and try to show one or more solutions.

We have already attached the database to MS SQL Server and open Windows PowerShell ISE (run as Administrator). Make sure that the account under which we work has system account rights on the current farm SharePoint server and db_owner for a migrated database.
Now add script "Add-PSSnappin":

Add-pssnapin Microsoft.sharepoint.powershell

Now add script "Test-SPContentDatabase", if you need comfortable view use "Out-GridView"

Test-SPContentDatabase -Name WSS_ContentSPS -WebApplication http://sp-test | Out-GridView
OR export data to file "Export-Csv"
Test-SPContentDatabase -Name WSS_ContentSPS -WebApplication http://sp-test | Export-Csv -path 'C:\TestMigration_WSSContentSPS_07.08.2018.csv' -Encoding unicode -Delimiter "`t"
Run script and will see error:

Category : MissingAssembly
Error : True
UpgradeBlocking : False
Message : Assembly
[Microsoft.ReportingServices.SharePoint.UI.ServerPages,
Version=14.0.0.0, Culture=neutral,
PublicKeyToken=89845dcd8080cc91] is referenced in the
database [WSS_ContentSPS], but is not installed on the
current farm. Please install any feature/solution which
contains this assembly.
Remedy : One or more assemblies are referenced in the database
[WSS_ContentSPS], but are not installed on the current
farm. Please install any feature or solution which contains
these assemblies.


How is the fix? You can install the solution or if you are sure that you do not need this solution on the current farm, then you can delete it via T-SQL, first open MS SQL Management studio, click create query and select the database you need, then add script (you need table "EventReceivers" -> column "Assembly")
Select * from EventReceivers where Assembly like '%Microsoft.ReportingServices.SharePoint.UI.ServerPages,Version=14.0.0.0,Culture=neutral,PublicKeyToken=89845dcd8080cc91%'
We are convinced that this solution is really present and then delete:
Delete from EventReceivers where Assembly like '%Microsoft.ReportingServices.SharePoint.UI.ServerPages,Version=14.0.0.0,Culture=neutral,PublicKeyToken=89845dcd8080cc91%'


Category : MissingFeature
Error : True
UpgradeBlocking : False
Message : Database
[WSS_Content] has reference(s) to a missing feature: Id = [bf8b58f5-ebae-4a70-9848-622beaaf2043],
Name = [Power View Integration Feature], Description = [Enables interactive data exploration and visual presentation against PowerPivot workbooks and Analysis Services tabular databases.],
Install Location = [PowerView]."
","The feature with Id bf8b58f5-ebae-4a70-9848-622beaaf2043 is referenced in the database [WSS_Content]
but is not installed on the current farm.
The missing feature may cause upgrade to fail. Please install any solution which contains the feature and restart upgrade if necessary."


Is the addin for "SSRS installed" in your new farm.

Category : MissingWebPart
Error : True
UpgradeBlocking : False
Message : WebPart class
[6a1f4b36-329d-317b-802a-96130a9ae5e7] (class [Microsoft.SharePoint.Portal.WebControls.BusinessDataFilterWebPart] from assembly
[Microsoft.SharePoint.Portal, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c]) is referenced [1] times in the database [WSS_Content], but
is not installed on the current farm. Please install any feature/solution which contains this web
part.","One or more web parts are referenced in the database [WSS_Content], but are not installed
on the current farm. Please install any feature or solution which contains these web parts."


Category : MissingWebPart
Error : True
UpgradeBlocking : False
Message : WebPart class
MissingWebPart,"True","False","WebPart class [69a2a58c-9b8d-d5c5-a7f6-a0feeeaf3867] (class
[Microsoft.SharePoint.Portal.WebControls.SpListFilterWebPart] from assembly
[Microsoft.SharePoint.Portal, Version=15.0.0.0, Culture=neutral,
PublicKeyToken=71e9bce111e9429c]) is referenced [10] times in the database [WSS_Content],
but is not installed on the current farm. Please install any feature/solution which contains this web part."


After you migrate the sites on Microsoft SharePoint Server 2013 to SharePoint Server 2016, the following web part controls no longer work on the migrated sites:

SpListFilterWebPart;
ExcelWebRenderer;
ReportViewerWebpart;

"Web part controls don't work after sites are migrated to SharePoint 2016."

Solutions: add your file web.config 2 row:
<SafeControl Assembly="Microsoft.SharePoint.Portal, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" Namespace="Microsoft.SharePoint.Portal.WebControls" TypeName="SpListFilterWebPart" Safe="True" />
<SafeControl Assembly="Microsoft.SharePoint.Portal, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" Namespace="Microsoft.SharePoint.Portal.WebControls" TypeName="BusinessDataFilterWebPart" Safe="True" />

To be continued,
Happy Coding!

Monday, August 6, 2018

Ribbons Customization in SharePoint 2013 (List Items Approved or Rejected)

In my first article I'll demonstrate how to create a project in Visual Studio for MS SharePoint server 2013 and make the buttons for authorization (Approve and Reject) in Ribbon for updating of list/library items.

In one of the projects I was asked to make it possible to authorize the list/library items when selecting these elements with the mouse in the list itself without opening one of the forms. Such a decision seemed to me interesting and I studied the CSOM with the possibility of a method SP.ListOperation.Selection.getSelectedItems().
var context = SP.ClientContext.get_current();
var selectedItemIds = SP.ListOperation.Selection.getSelectedItems(context);
It allows you to work directly with the list items when you select a click.



Further in the screenshots you can see that when you select multiple items and when you click button "Approved Items" or "Rejected Items", depending on the authorization logic the selected list items are updated.

Select "Title2" (Rejected) and "Title3" (Approved), click button "Approved Items, then will see: "Title3 is Approved"" and "Title2 successfully Approved".





How is create of this solution, lets get started:

1. Open the visual studio 2012 or 2015 as run as administrator. 
2. Create an Empty SharePoint Project 2013.



3. Let the name be "RibbonCustomActionExample".
4. Select a Farm Solution.



5. Add New Item to the solution (Module).



6. Add 2 Module. Name it as ApprovedCA



and RejectedCA



7. Then Add New Item to the solution (SharePoint "Layouts" Mapped Folder).



8. Rename folder "Layouts" in "Scripts".



9. Add New Item to folder "Scripts".



10. JavaScript-file name "script.js".



11. Open JavaScript-file "script.js" and add to code:
function getSelectedItems(OnSuccess, OnError) {
    var context = SP.ClientContext.get_current();
    var listId = SP.ListOperation.Selection.getSelectedList();
    var selectedItemIds = SP.ListOperation.Selection.getSelectedItems(context);
    var list = context.get_web().get_lists().getById(listId);
    var listItems = [];
    for (idx in selectedItemIds) {
        var item = list.getItemById(parseInt(selectedItemIds[idx].id));
        listItems.push(item);
        context.load(item);
    }
    context.executeQueryAsync(
       function () {
           OnSuccess(listItems);
       },
       OnError
    );
}
function RejectedItems() {
    var context = SP.ClientContext.get_current();
    var selectedItems = SP.ListOperation.Selection.getSelectedItems(context);
    var ListGUID = SP.ListOperation.Selection.getSelectedList();
    var clientContext = new SP.ClientContext.get_current();
    var targetList = clientContext.get_web().get_lists().getById(ListGUID);
    var itemArray = [];
    var itemAllertNo = [];
    var itemAllertYes = [];
    getSelectedItems(function (items) {
        for (var i = 0 ; i < items.length; i++) {
            if ((items[i].get_item('Test') == "Rejected")) {
                itemAllertNo.push(items[i].get_item('Title'));
            } else {
                var oListItem = targetList.getItemById(selectedItems[i].id);
                oListItem.set_item('Test', 'Rejected');
                oListItem.update();
                itemArray[i] = oListItem;
                clientContext.load(itemArray[i]);
                itemAllertYes.push(items[i].get_item('Title'));
                clientContext.executeQueryAsync(onQueryFailed);
            }
        }
        if (itemAllertNo != '') {
            alert("List items " + itemAllertNo + " is rejected!");
        }
        if (itemAllertYes != '') {
            alert("List items " + itemAllertYes + " successfully rejected!");
            window.location.reload();
        }
    },
        function (sender, args) {
            alert('An error occured: ' + args.get_message());
        });
}
function ApprovedItems() {
    var context = SP.ClientContext.get_current();
    var selectedItems = SP.ListOperation.Selection.getSelectedItems(context);
    var ListGUID = SP.ListOperation.Selection.getSelectedList();
    var clientContext = new SP.ClientContext.get_current();
    var targetList = clientContext.get_web().get_lists().getById(ListGUID);
    var itemArray = [];
    var itemAllertNo = [];
    var itemAllertYes = [];
    getSelectedItems(function (items) {
        for (var i = 0 ; i < items.length; i++) {
            if ((items[i].get_item('Test') == "Aproved")) {
                itemAllertNo.push(items[i].get_item('Title'));
            } else {
                var oListItem = targetList.getItemById(selectedItems[i].id);
                oListItem.set_item('Test', 'Aproved');
                oListItem.update();
                itemArray[i] = oListItem;
                clientContext.load(itemArray[i]);
                itemAllertYes.push(items[i].get_item('Title'));
                clientContext.executeQueryAsync(onQueryFailed);
            }
        }
        if (itemAllertNo != '') {
            alert("List items " + itemAllertNo + " is approved!");
        }
        if (itemAllertYes != '') {
            alert("List items " + itemAllertYes + " successfully approved!");
            window.location.reload();
        }
    },
        function (sender, args) {
            alert('An error occured: ' + args.get_message());
        });
}
function onQueryFailed(sender, args) {
    alert('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
}
12. Open the Elements.xml in module ApprovedCA and remove default code



13. Add to code in this Elements.xml (ApprovedCA):
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<CustomAction Id="f110dac1-9797-4959-8596-2161fb5a3cb1.RibbonCustomAction"
RegistrationType="List"
RegistrationId="100"
Location="CommandUI.Ribbon"
Sequence="10001"
Title="New Action Command">
<CommandUIExtension>
<CommandUIDefinitions>
<CommandUIDefinition Location="Ribbon.ListItem.Actions.Controls._children">
<Button Id="Approved Items"
Alt="Request RibbonCustomAction"
Sequence="100"
Command="New Action Command"
LabelText="Approved Items"
TemplateAlias="o1"
Image32by32="/_layouts/15/1033/images/formatmap32x32.png?rev=23" Image32by32Left="-375" Image32by32Top="-511"
Image16by16="/_layouts/15/1033/images/formatmap32x32.png?rev=23" Image16by16Left="-375" Image16by16Top="-511" />
</CommandUIDefinition>
      </CommandUIDefinitions>
      <CommandUIHandlers>
        <CommandUIHandler Command="New Action Command"
CommandAction="javascript: ApprovedItems();"
EnabledScript="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();"/>
</CommandUIHandlers>
</CommandUIExtension >
</CustomAction>
<CustomAction
ScriptSrc="Scripts/script.js"
Location="ScriptLink"
Sequence="100">
</CustomAction>
</Elements>

14. Open the Elements.xml in module RejectedCA, remove default code and add to code in Elements.xml:
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<CustomAction Id="f110dac1-9797-4959-8596-2161fb5a3cb2.RibbonCustomAction"
RegistrationType="List"
RegistrationId="100"
Location="CommandUI.Ribbon"
Sequence="10001"
Title="Invoke 'RibbonCustomAction' action">
<CommandUIExtension>
<CommandUIDefinitions>
<CommandUIDefinition Location="Ribbon.ListItem.Actions.Controls._children">
<Button Id="New Action Command"
Alt="Request RibbonCustomAction"
Sequence="100"
Command="Invoke_RibbonCustomActionButtonRequest"
LabelText="Rejected Items"
TemplateAlias="o1"
Image32by32="/_layouts/15/1033/images/formatmap32x32.png?rev=23" Image32by32Left="-375" Image32by32Top="-511"
Image16by16="/_layouts/15/1033/images/formatmap32x32.png?rev=23" Image16by16Left="-375" Image16by16Top="-511" />
</CommandUIDefinition>
</CommandUIDefinitions>
<CommandUIHandlers>
<CommandUIHandler Command="Invoke_RibbonCustomActionButtonRequest"
CommandAction="javascript: RejectedItems();"
EnabledScript="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();  "/>
</CommandUIHandlers>
</CommandUIExtension>
</CustomAction>
<CustomAction
ScriptSrc="Scripts/script.js"
Location="ScriptLink"
Sequence="100">
</CustomAction>
</Elements>
15. Then Build -> "Deploy Solution" and check current solution.

Happy Coding!