Thursday, January 24, 2019

Highlighting list items with .NET and CSR (Employee Vacation Project) on SharePoint server 2013, 2016

Hello everyone, in this article I will talk about the project in which I needed to highlight the elements of the list that matched by dates and categories. All of us go on vacation from time to time and someone may substitute us for the time of our absence, however, we need to see whether the period of time for vacation for employees in one category (for example, SharePoint developers) or not, for this task, I need a list of Calendar, columns Title, Category (lookup another list column), Start Time, End Time and Flag (hidden). I create several elements of the list (employees) with a start and end date, some leave vacation days.
The main advantage of this code is the use of C#, which means such features are available as Visual Web Part and JSLink (CSR).




Lets get started!

1. Open the visual studio 2012 or 2015 as run as administrator on SharePoint server (my example on SharePoint server 2013 OnPremise). 
2. Create an SharePoint server 2013 - Visual Web Part (name Project: "CalendarDatePeriods").



3. Set URL and Select a Farm Solution.



4. Add reference in the Project Microsoft.CSharp.

5. Open file "VisualWebPart1UserControl.ascx.cs".



6. Remove code "protected void Page_Load(object sender, EventArgs e){ }".

7. Add this code (Do not forget that the URL of the server and the name of the list may differ from yours!):
public class Item
 {
   public Int32 ID { get; set; }
   public string Title { get; set; }
   public string Category { get; set; }
   public DateTime StartTime { get; set; }
   public DateTime EndTime { get; set; }
 }
    //Class declaration array
    public class RootObject
    {
        public RootObject()
         {
            items = new List<Item>();
         }
            public List<Item> items { get; set; }
     }
         //Load page
         protected void Page_Load(object sender, EventArgs e)
          {
            //create int array
            List<int> ID_array = new List<int>();
            //GetListAllItems
            using (SPSite site = new SPSite("http://sp-test/sites/eng"))
            {
                using (SPWeb web = site.OpenWeb())
                {
                    web.AllowUnsafeUpdates = true;
                    string listUrl = web.ServerRelativeUrl + "/lists/Calendar";
                    SPList list = web.GetList(listUrl);
                    SPView view = list.Views["All Events"];
                    SPListItemCollection items = list.GetItems(view);
                    //Run class RootObject
                    RootObject objs = new RootObject();
                    foreach (SPListItem item in items)
                    {
                        //Add items to array
                        objs.items.Add(new Item
                        {
                            ID = Int32.Parse(item["ID"].ToString()),
                            Title = item["Title"].ToString(),
                            Category = item["Category"].ToString(),
                            StartTime = DateTime.Parse(item["Start Time"].ToString()),
                            EndTime = DateTime.Parse(item["End Time"].ToString()),
                        });
                    }
                    //Filter array DateTime periods
                    var array = objs.items;
                    for (int i = 0; i < array.Count - 1; i++)
                    {
                        for (int j = i + 1; j < array.Count; j++)
                        {
                            var p1 = array[i];
                            var p2 = array[j];
                            if (p1.Category != "1;#-" && p2.Category != "1;#-")
                            {
                                if (p1.Category != p2.Category)
                                    continue;
                                if (!(p1.StartTime > p2.EndTime || p2.StartTime > p1.EndTime))
                                {
                                    ID_array.Add(p1.ID);
                                    ID_array.Add(p2.ID);
                                    ID_array.Distinct().ToArray();
                                }
                            }
                        }
                    }
                    //Update List Item to DateTime period
                    for (int x = 0; x < ID_array.Count; x++)
                    {
                        using (SPSite osite = new SPSite("http://sp-test/sites/eng"))
                        {
                            using (SPWeb oweb = site.OpenWeb())
                            {
                                SPList olist = oweb.Lists["Calendar"];
                                SPListItemCollection oitems = list.GetItems(new SPQuery()
                                {
                                    Query = @"<Where><Eq><FieldRef Name='ID' /><Value Type='Int'>" + ID_array[x] + "</Value></Eq></Where>"
                                });

                                foreach (SPListItem item in oitems)
                                {
                                    item["Flag"] = "Yes";
                                    item.Update();
                                }
                            }
                        }
                    }
                }
            }
        }
8. Add reference in the lines where the code is highlighted in red, he will suggest.

using System;

using Microsoft.SharePoint;

using System.Collections.Generic;

using System.Linq;

using System.Web.UI;

9. If no errors are detected in the project, then do "Deploy Solution".
10. After the project is published on the server, IIS is restarted and you need to wait a couple of minutes if you need to make sure that the project has been published successfully, follow the link: http://your_sharepoint_server:port/_admin/Solutions.aspx and see your solution "calendardateperiods.wsp" status "Deployed". Then restart our list and click to "Property" -> "Edit Page":



"Add a Web Part" -> Categories "Custom" -> Add "CalendarDatePeriods - VisualWebPart1":



We added a web part and immediately saw that in the "Flag" column, for elements that match in categories and dates, the value is "Yes". This means our code is working successfully.



To highlight the color of elements whose values match, we use CSR (JSlink) and add it via the Content Editor Web Part. We need to add item in library "Site Assets" "jquery-2.1.3.min.js", then create JavaScript-file DateCSR.js in which you need to add the code allocated by our elements and "Flag" hiding column:

<script type="text/javascript" src="/sites/eng/SiteAssets/jquery-2.1.3.min.js"></script>
<script type="text/javascript">
(function () { 
    var priorityFiledContext = {}; 
    priorityFiledContext.Templates = {}; 
    priorityFiledContext.Templates.Fields = {  
        "EventDate": { 
            "View": EventDateFiledTemplate 
        },
        "EndDate": { 
            "View": EndDateFiledTemplate 
        }
    }; 
    SPClientTemplates.TemplateManager.RegisterTemplateOverrides(priorityFiledContext);
})();
(function () { 
    var linkFiledContext = {}; 
    linkFiledContext.Templates = {}; 
    linkFiledContext.OnPostRender = linkOnPostRender;
    SPClientTemplates.TemplateManager.RegisterTemplateOverrides(linkFiledContext);
})();
function linkOnPostRender(ctx) 
{ 
    var linkCloumnIsEmpty = 1;
    for (i = 0; i < ctx.ListData.Row.length; i++) { 
        if (ctx.ListData.Row[i]["Flag"]) 
        { 
            linkCloumnIsEmpty = 1; 
            break; 
        } 
    } 
    if (linkCloumnIsEmpty) {
        var cell = $("div [name='Flag']").closest('th'); 
        var cellIndex = cell[0].cellIndex + 1;
        $('td:nth-child(' + cellIndex + ')').hide(); 
        $('th:nth-child(' + cellIndex + ')').hide(); 
    }
}
function EventDateFiledTemplate(ctx) {
    var Flag = ctx.CurrentItem.Flag;
    var EventDate = ctx.CurrentItem.EventDate;
    if (Flag == "Yes"){
       return "<span style='color :red'>" + EventDate + "</span>";
    } else {
          return "<span style='color :green'>" + EventDate + "</span>";
    }        
}
  function EndDateFiledTemplate(ctx) {
    var Flag = ctx.CurrentItem.Flag;
    var EndDate = ctx.CurrentItem.EndDate; 
    if (Flag == "Yes"){
         return "<span style='color :red'>" + EndDate + "</span>";
    } else {
        return "<span style='color :green'>" + EndDate + "</span>";
    }
}
</script>
"Add a Web Part" -> Category "Media and content" -> Add "Content Editor":



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



And we see our result, the most important thing is that this solution allows you to work with a large number of list items (I used more than 1000), without delays and timeouts. Additionally, you can modify this solution to suit your requirements; you can add an Event Reciever to create, modify, or delete list items with similar logic.


Happy Coding!

No comments:

Post a Comment