Source: new_reservation.js

(
/**
* Contains the functionalities related to the new reservations page.
*
* @module new_reservation
* @author Joonas Konki
* @author Anu Koskela
* @author Mikko Kuhno
* @author Henrik Paananen
* @author Atte Räty
* @license BSD 3-clause, see LICENSE for more details.
* @copyright 2015 Kepler project authors
*/
function(){
var currentGroupSelection = -1;
var currentTimeSlot = null;
var unitList = null;
var units = null;
var unit = null;
var cal = null;
var groups = null;
var eventTimeSlot = null;
var savedTSColor = null;

/**
* Selects the clicked calendar timeslot event.
* @memberof module:new_reservation
* @param {object} timeslot - The selected timeslot.
*/
function selectCalendarTimeslot(timeslot) {
    if (eventTimeSlot !== null) {
        eventTimeSlot.k.selected = false;
    }

    eventTimeSlot = timeslot;
    currentTimeSlot = eventTimeSlot.eventTimeSlot.id;

    timeslot.k.selected = true;
    cal.fullCalendar('rerenderEvents');
}

/**
* Gets the selected calendar timeslot event.
* @memberof module:new_reservation
* @param event - Contains the event information.
* @param element - Contains information what kind of
* element the clicked event is.
* @param view - Contains the view in which the element is shown.
*/
function calendarClick (event, element, view) {
    if (event.eventTimeSlot !== undefined) {
        selectCalendarTimeslot(event);
        $("#makeReservationBtn").attr("disabled", false);
    }
}

/**
* Shows information related to the FullCalendar event. The selection is
* highlighted if the event selection is active in the calendar view.
* @memberof module:new_reservation
* @param event - Contains the event information.
* @param element - Contains information what kind of
* element the clicked event is.
* @param view - Contains the view in which the element is shown.
* @param eventData - Contains the data that the event has.
*/
function calendarEventRender(event, element, view, eventData) {
    if( event.eventTimeSlot !== undefined &&
        event.eventTimeSlot.id == currentTimeSlot){

        event.selected = true;
        eventTimeSlot = event;
    }

    calUtil.defaultEventRender(event, element, view);
}

/**
* Initialises the calendar with the given custom attributes.
* @memberof module:new_reservation
*/
function initCalendar(){
    function eventFilter(event) {
        if (event.reservation === undefined) return true;
        return (event.reservation.status === 'active_id');
    }
    cal = calUtil.initDefaultCal(calendarClick,
                                 calendarEventRender,
                                 eventFilter);

    cal.fullCalendar('addEventSource',{
        events: function(start, end, timezone, callback){
             var params = {
                'start_time': start.toISOString(),
                'end_time': end.toISOString(),
                'unit_type_id': unit.unit_type_id,
                'unit_id': unit.id,
            };

            kepler.getTimeSlotEvents(params, function(data){
                 var events = [];

                 var content =
                    kepler.translate('calendar.time_slot.reservable');
//                 title += ': ' + unit.name;

                 for (var i = 0; i < data.time_slots.length; i++) {
                    var ts = data.time_slots[i];

                    event = calUtil.makeCalendarEvent(ts);


                    event.eventTimeSlot = ts;
                    event.k.pointer = true;

                    events.push(event);
                }
                eventTimeSlot = null;
                callback(events);
            });
        },
    });
}

/**
* Shows the calendar to pick a suitable time for the reservation
* after the work selection has been made.
* Initialises the calendar if it is null.
* @memberof module:new_reservation
*/
function showPickTimeArea(){
    $("#pickTimeArea").show();
    if (cal === null){
        initCalendar();
    }

}

/**
* Clears the calendar and refetches the events.
* @memberof module:new_reservation
*/
function updateCalendar(){
    if (cal !== null) {
        cal.fullCalendar('refetchEvents');
    }
}


/**
* Shows a notification if the selected user group is bigger than the defined
* maximum number of participants for the unit group.
* @memberof module:new_reservation
* @param {object} groups - A list of all user groups.
*/
function checkGroupSize(groups){
    if(unit !== null){
        var maxSize = unit.max_user_group_size;

        for (var i = 0; i < groups.length; i++){
            if( (groups[i].id === currentGroupSelection) &&
                (groups[i].members.length > maxSize) ){

                var parag = $("<p>").addClass("bg-danger");
                parag.text(kepler.translate(
                  'content.new_reservations_group_too_big') + ".");

                $("#groupMembersWarning").empty();
                $("#groupMembersWarning").append(parag);
            }
            else {
                $("#groupMembersWarning").empty();
            }
        }
    }
}


/**
* Creates a table row element for each available time slot.
* @memberof module:new_reservation
*/
function initList(){
    $("#list").empty();

    if (unit !== null) {
        var listDiv = $('<table>').addClass('table table-striped');
        listDiv.attr('id','shiftTable');

        $("#list").append(listDiv);

        var headerTh = $("<th>").addClass('header');
        headerTh.text(kepler.translate(
          'content.supervision_shifts_header') + ":");
        var headerDiv = $("<tr>");
        headerDiv.append(headerTh);
        var tHead = $("<thead>").append(headerDiv);

        $("#shiftTable").append(tHead);
        $("#shiftTable").append($("<tbody>"));

        var listDisplayArea = $("#shiftTable").find("tbody");

        var params = {
            'unit_type_id': unit.unit_type_id,
            'unit_id': unit.id
        };
        kepler.getTimeSlotEvents(params, function(data){
            for (var i = 0; i < data.time_slots.length; i++){
                var ts = data.time_slots[i];
                listDiv = $('<tr>').addClass('reservableShift');

                var listRadioButton = $("<input>").attr('type', 'radio');
                listRadioButton.attr('name', 'shiftSelector').val(ts.id);
                listRadioButton.css('cursor', 'pointer');

                var shiftInfo = " "+kepler.datetimeIntervalString(ts.start_time,
                                    ts.end_time);
                shiftInfo += ", " +ts.unit_type_name;

                var label = $("<label>");
                label.append(listRadioButton);
                label.append(shiftInfo);

                var td = $('<td>').append(label);
                listDiv.append(td);

                listDisplayArea.append(listDiv);
            }
            //Should check if some selection is defined to filter things
            if (currentTimeSlot !== null){
                $('input:radio[name=shiftSelector]').filter(
                  '[value=' + currentTimeSlot +']').attr('checked', true);
            }
        });


    }
    else {
        var heading = $("<h4>").addClass("bg-info");
        heading.text(kepler.translate(
          'content.new_reservations_pick_experiment') + "!");
        $("#list").append(heading);
    }
}

/**
* Pastes the unit group, identified and name of the unit together into one
* string for better readability.
* @param {object} unit - The selected unit.
* @returns {string} - The names of the unit group, qualifier and unit.
* @memberof module:new_reservation
*/
function unitDisplayName(unit) {
    return unit.unit_group + "/" + unit.qualifier + ", " + unit.name;
}

/**
* Sets the unit's name and other information to the corresponding areas.
* @memberof module:new_reservation
*/
function displayUnitDescription() {
    var unitNameDiv = $("#selectedUnitName");
    var unitDescDiv = $("#selectedUnitDesc");
    var maxGroupSizeDiv = $("#selectedUnitGroupMaxSize");

    var divNameLabel = $("<div>").addClass("selected-unit-label");
    divNameLabel.text(kepler.translate('content.unit_name'));

    var divNameValue = $("<div>").addClass("selected-unit-value");
    divNameValue.text(unitDisplayName(unit));

    unitNameDiv.empty();
    unitNameDiv.append(divNameLabel);
    unitNameDiv.append(divNameValue);

    var divDescLabel = $("<div>").addClass("selected-unit-label");
    divDescLabel.text(kepler.translate('content.unit_desc'));

    var divDescValue = $("<div>").addClass("selected-unit-value");
    divDescValue.text(unit.description ? unit.description : "-");

    unitDescDiv.empty();
    unitDescDiv.append(divDescLabel);
    unitDescDiv.append(divDescValue);

    var divGroup = $("<div>").addClass("selected-unit-label");
    divGroup.text(kepler.translate('content.unit_user_group_max_size'));
    maxGroupSizeDiv.empty();
    maxGroupSizeDiv.append(divGroup);

    var maxGroupSize = unit.max_user_group_size + " ";
    if (unit.max_user_group_size == 1) {
        maxGroupSize += kepler.translate('content.unit_user_group_member_1');
    }
    else {
        maxGroupSize += kepler.translate('content.unit_user_group_member_N');
    }

    var maxUsers = $("<div>").addClass("selected-unit-value");
    maxUsers.text(maxGroupSize);

    maxGroupSizeDiv.append(maxUsers);
}


/**
* Fills the unitList with the units that match the given string.
* @memberof module:new_reservation
* @param {string} inputText - The string that has to be found in the name of
* each displayed unit.
*/
function updateUnitList(inputText){
    $("#unitList").empty();
    var filter = inputText.toLowerCase();
    for (var i = 0; i < units.length; i++) {
        var unit = units[i];
        var displayName = unitDisplayName(unit);
        var displayLower = displayName.toLowerCase();
        if(displayLower.indexOf(filter) != -1) {
            var option = $("<option>");
            option.val(i);
            // option.val(unit.id);
            option.text(displayName);
            $("#unitList").append(option);
        }
    }
}


/**
* Changes between the list and calendar views when the button is clicked.
* @function
* @name toggleViewButton click
* @memberof module:new_reservation
*/
$("#toggleViewButton").click(function(data){
    if($("#viewList").is(":visible")){
        $("#viewList").hide();
        $("#viewCalendar").show();
        updateCalendar();
        if(currentTimeSlot !== null){
            console.log(currentTimeSlot);
        }
        $("#toggleViewButton").text( kepler.translate(
          'content.reservation_frame_button_list') );

    } else {
        initList();
        $("#viewList").show();
        $("#viewCalendar").hide();
        $("#toggleViewButton").text( kepler.translate(
          'content.reservation_frame_button_calendar') );
    }
});


/**
* This is executed after the HTML page has been loaded.
* This is a common procedure of all of the client-side modules to
* initialise the page content.
* @memberof module:new_reservation
*/
function doc_ready() {
    $("#navNewReservation").addClass("active");

    $("#viewList").change(function() {
        currentTimeSlot = $('#viewList').find(':checked').val();
        $("#makeReservationBtn").attr("disabled",false);
    });

    kepler.getUserGroups(function (data) {

        groups = data.groups;
        currentGroupSelection = groups[0].id;
        for (var i = 0; i < groups.length; i++){
            var group = groups[i];
            if (group.is_personal === false){
                $("#newReservationSelectGroup").append("<option value='" +
                group.id + "'> " + kepler.translate('label.group') + ": " +
                group.name + "</option>");
            }
            else {
                $("#newReservationSelectGroup").
                    append("<option value='" + group.id + "'>" +
                    group.members[0].first_names + " " +
                    group.members[0].last_name + "</option>");
            }
        }

    });

    /**
    * Displays the members of the selected user group and calls the function
    * checkGroupSize.
    *
    * @function
    * @name newReservationSelectGroup change
    * @inner
    * @memberof module:new_reservation
    */
    $("#newReservationSelectGroup").change(function(v){
        $("#groupMembersArea").empty();
        currentGroupSelection = parseInt(v.target.value);

        for (var i = 0; i < groups.length; i++){
            var group = groups[i];
            if ((group.id === currentGroupSelection) &&
                (group.is_personal === false)) {
                $("#groupMembersArea").empty();
                var memberslist = "";

                for (var k = 0; k < groups[i].members.length; k++){
                    if(k > 0) memberslist += ",";
                    if (groups[i].members[k].call_name !== null)
                        memberslist += " " + groups[i].members[k].call_name +
                                       " " + groups[i].members[k].last_name;
                    else
                        memberslist += " " + groups[i].members[k].first_names +
                                       " " + groups[i].members[k].last_name;
                }

                var mTitle = $("<b>").text(kepler.translate(
                  'content.new_reservations_group_members') + ":");
                var pMembers = $("<p>").append(mTitle);
                pMembers.append(memberslist);
                $("#groupMembersArea").append(pMembers);
            }
        }

        checkGroupSize(groups);
    });

    $("#searchField").on("input", function(v){
        var inputText = v.target.value;
        updateUnitList(inputText);
    });

    unitList = kepler.createLoadElement("#unitList", function (element) {
        call = kepler.getUnits(function (data) {
            units = data.units;
            updateUnitList("");
        });
        return call;
    });
    unitList.load();

    var selectedUnit = null;

    /**
    * Displays the unit's description, check the size of the selected user
    * group and updates the available time slots shown in the calendar or the
    * list view.
    *
    * @function
    * @name unitList change
    * @inner
    * @memberof module:new_reservation
    */
    $('#unitList').change(function(v) {
        if (selectedUnit !== v.target.value && v.target.value !== "") {
            selectedUnit = v.target.value;

            var index = parseInt(selectedUnit);
            unit = units[index];

            displayUnitDescription();
            checkGroupSize(groups);
            showPickTimeArea();

            // Check which view is open and update that
            if(cal.is(":visible")) {
                updateCalendar();
            } else {
                initList();
            }
       }
    });

    $("#pickTimeArea").hide();

    //Functions to disable and enable makeReservationButton
    if (eventTimeSlot !== null){
        $("#makeReservationBtn").attr("disabled",false);
    }else {
        $("#makeReservationBtn").attr("disabled",true);
    }

    /**
    * Gets the additional information from the extraInfo field and calls the
    * function addReservation at kepler.js to save the reservation with the
    * provided parameters.
    *
    * @function
    * @name makeReservationBtn click
    * @inner
    * @memberof module:new_reservation
    */
    $("#makeReservationBtn").click(function(){
        var addInfo = $("#extraInfo").val();

         if ( cal !== null && cal.is(":visible") ) {
            if(eventTimeSlot !== null) {
                console.log(eventTimeSlot.eventTimeSlot.id);
                var params = {
                    'time_slot_id': eventTimeSlot.eventTimeSlot.id,
                    'unit_id': unit.id,
                    'unit_group_id': unit.unit_group_id,
                    'user_group_id': currentGroupSelection,
                    'note': addInfo,
                };

                console.log (params);
                kepler.addReservation(params, function (data) {
                    if (data.result.success === true) {
                        $('#extraInfo').val("");
                    }
                    kepler.showResult(data.result, "#notification");
                    updateCalendar();
                });
            } else {
                // TODO(henrik): This should be cleaned-up: no alert
                alert(kepler.translate('content.new_reservations_picktime')+
                                       '!');
            }
        } else {
            var params = {
                'time_slot_id': currentTimeSlot,
                'unit_id': unit.id,
                'unit_group_id': unit.unit_group_id,
                'user_group_id': currentGroupSelection,
                'note': addInfo,
            };

            console.log (params);
            kepler.addReservation(params, function (data) {
                if (data.result.success === true) {
                    $('#extraInfo').val("");
                }
                kepler.showResult(data.result, "#notification");
                currentTimeSlot = null;

                if(cal.is(":visible")){
                    updateCalendar();
                } else {
                    initList();
                }
            });
        }
    });

}

$(document).ready(doc_ready);
}());