Second Life of a Hungarian SharePoint Geek

April 17, 2013

How to use LINQ expressions in your JavaScript code when accessing the REST API (and other useful JavaScript libraries)

Filed under: JavaScript, jQuery, LINQ, Project Server, REST, SP 2010, SP 2013 — Tags: , , , , , , — Peter Holpar @ 04:24

Working with both C# and JavaScript to process and display information stored on Project Server, I had to realize the power of LINQ in C#, and the lack of this language feature in JavaScript. Fortunately, after a quick search I found the LINQ for JavaScript library, that enables a very similar syntax. Below I show a few examples to give you a highlight of its features.

The other handy library I use these days frequently is Datejs, that enables effective handling of the Date objects in JavaScript.

Although the code samples in this post are related to Project Server, you can apply the same technique to SharePoint as well. For the sake of simplicity I post only code snippets, and not the full code of the application. Hopefully it will be enough to demonstrate the power of these libraries.

LINQ for JavaScript

Note, that I’m using version 3.0.3-Beta4 in the samples below, and not the stable 2.2.0.2 version. There are considerable syntax differences between these versions, like lower case vs. upper case function names, so be sure the check the reference.htm coming with the actual version of your choice.

See my former post about using and limitations of the $expand query option.

In the first step I send a few REST request to the server and store the results in JavaScript object trees.

The sample below sends a REST request to the Project Server to query information, like Name, Id and ResourceCalendarExceptions properties of the enterprise resources as well as the Name of their BaseCalendar property. We need the response as a JSON stream, so we set the Accept header to ‘application/json; odata=verbose‘. If the call was successful, the result is stored in the resources variable.

var siteFullUrl = ‘http://yourProjectSite’;

var resources;
var calendars;
var assignments;

$.ajax({
                type: ‘GET’, 
                contentType: ‘application/json;odata=verbose’,
                url: siteFullUrl + "/sites/pwa/_api/ProjectServer/EnterpriseResources?$select=Name,Id,ResourceCalendarExceptions,BaseCalendar/Name&$expand=ResourceCalendarExceptions,BaseCalendar/Name",
                headers: {
                    ‘X-RequestDigest’: $(‘#__REQUESTDIGEST’).val(),
                    ‘Accept’: ‘application/json; odata=verbose’
                },
                dataType: ‘json’,
                complete: function (result) {
                    var response = JSON.parse(result.responseText);
                    if (response.error) {
                        alert("Error: " + response.error.code + "\n" + response.error.message.value);
                    }
                   else {
                       resources = response.d.results;
                   }
});

We can request the enterprise calendar data (name and exceptions) using a similar call of jQuery AJAX method, but in this case the URL of the REST query looks like this one below:

"/sites/pwa/_api/ProjectServer/Calendars?$select=Name,BaseCalendarExceptions&$expand=BaseCalendarExceptions"

and we store the response in the calendars variable.

calendars = response.d.results;

To to get the assignments for March I submitted a REST request with the following URL:

"/sites/pwa/_api/ProjectData/Assignments?$select=ResourceId,ProjectName,AssignmentStartDate,AssignmentFinishDate,AssignmentBookingId&$filter=AssignmentStartDate+le+datetime’2013-03-31′ and AssignmentFinishDate+ge+datetime’2013-03-01’"

and stored the results in the assignments variable:

assignments = response.d.results;

Having all of the responses on the client side, we can process them using a code like this one:

// default enterprise base calendar
var wdExcs = calendars[0].BaseCalendarExceptions.results;

$.each(resources, function (index) {
        // get the calendar exceptions of the current resource
        var wdExcsPriv = this.ResourceCalendarExceptions.results;
        var resId = this.Id;

        // get all assignments of the current resource
        var assignmentsPriv = Enumerable.from(assignments).where(function(x) { return (x.ResourceId == resId); }).toArray();

        // get the first day of the current month, that was 1st of March at the time of test
        var day = Date.today();
        var day = day.moveToFirstDayOfMonth();
        var dayOfWeek = day.getDay();

        var assignmentsForThisDay = Enumerable.from(assignmentsPriv).where(function(x) { return (new Date(parseInt(x.AssignmentStartDate.substr(6))) <= day) && (new Date(parseInt(x.AssignmentFinishDate.substr(6))) >= day) }).toArray();

        // is it a weekend, a base calendar exception (like state holidays) or a resource exception (private holiday)?
        var isHoliday = ((dayOfWeek == 0) || (dayOfWeek == 6)
          || (Enumerable.from(wdExcs).any(function(x) { return (Date.parse(x.Start) <= day) && (Date.parse(x.Finish) >= day) }))
          || (Enumerable.from(wdExcsPriv).any(function(x) { return (Date.parse(x.Start) <= day) && (Date.parse(x.Finish) >= day) })));

        // is there at least a single committed assignment or only proposed ones?
        var isBooked = (Enumerable.from(assignmentsForThisDay).any(function(x) { return (x.AssignmentBookingId==0); }));

        // aggregate (join) the assignment names
        var projects = (Enumerable.from(assignmentsForThisDay).select("$.ProjectName")).join();

});

Datejs

You can see Datejs in action in the previous code snippet, like the call of the moveToFirstDayOfMonth function above.

It has a lot of other useful features, for example, to get the number of days in the current month:

var month = today.getMonth();
var year = today.getFullYear();
var dayCount = Date.getDaysInMonth(year, month);

The getDayDiff function (requires time.js) returns the number of days between two dates:

function getDayDiff(time1, time2) {
  var timeSpan = new TimeSpan(time1 – time2);
  var dayCount = timeSpan.getDays() ;
  return dayCount;
}

The next snippet sets the variable firstDay to the first day of the current month, and lastDay to the last day of the following month:

var firstDay = Date.today();
firstDay.moveToFirstDayOfMonth();

var lastDay = Date.today().add(1).month();
lastDay.moveToLastDayOfMonth();

I’ve been working with these libraries for a few weeks now, and I can say they made my coding more efficient, so I think they worth a try if you have to work with complex REST responses and Date objects from JavaScript, that is very likely if you would like to implement some exciting SharePoint applications based on the new app model.

Advertisements

Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Blog at WordPress.com.

%d bloggers like this: