(
/**
* Contains the functionalities related to the supervision shifts page.
*
* @module supervision_shifts
* @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 timeslots = null;
var ownTimeSlots = null;
var allTimeSlots = null;
var currentTime = null;
var showOwnTimeSlots = true;
var cal = null;
/**
* Creates a table which displays all the supervision shifts, and a toggleable
* area for each shift, which includes the information of the reserved unit
* groups and of the participants. Adds a "cancel shift" button (and a listener
* for it) for each upcoming shift.
* @memberof module:supervision_shifts
*/
function initTable(data) {
//TODO (Anu) Editing the time slot
timeslots = data.time_slots;
var tsList = $('#timeSlotList');
for (var i = 0; i < timeslots.length; i++) {
var ts = timeslots[i];
var tsDiv = $('<li>').addClass('timeSlot').attr('id',"li" + i);
var hasReservations = ts.reservations.length !== 0;
var listRow = $('<div>').addClass("list-group-item");
listRow.attr("id", "header" + i);
var noOfExperiments = getNumberOfReservations(ts);
if(ts.status == 'canceled_id'){
listRow.append($("<span>").addClass("badge").text(
noOfExperiments).css("background", "#a94442").css(
"display", "inline-block"));
listRow.addClass("list-group-item-danger");
listRow.attr("data-toggle", "collapse").attr("data-target",
"#row" + i).css("cursor","pointer");
listRow.append($("<span>").addClass(
"glyphicon glyphicon-chevron-down").css("float","left").css(
"cursor","pointer"));
}
else if(hasReservations){
listRow.append($("<span>").addClass("badge").text(
noOfExperiments).css("display", "inline-block"));
listRow.addClass("list-group-item-info");
listRow.attr("data-toggle","collapse").attr(
"data-target","#row"+i).css("cursor","pointer");
listRow.append($("<span>").addClass(
"glyphicon glyphicon-chevron-down").css("float","left").css(
"cursor","pointer"));
}
else {
listRow.append($("<span>").addClass("badge").text(
noOfExperiments).css("background",
"lightgray").css("display", "inline-block"));
listRow.addClass("list-group-item-default").attr("disabled", true);
listRow.append($("<span>").addClass(
"glyphicon glyphicon-chevron-down").css("color", "lightgray").css(
"float","left"));
}
var tsTime = kepler.datetimeIntervalString(ts.start_time, ts.end_time);
var tm_span = $("<div>").text(tsTime);
tm_span.css("display", "inline-block").css("min-width", "12em");
tm_span.css("margin-left", "1em");
listRow.append(tm_span);
var tsName = ts.unit_type_name;
var instructors = "";
for (var k = 0; k < ts.supervisors.length; k++){
if (k > 0) instructors += ",";
if(ts.supervisors[k].call_name !== null) {
instructors += " " + ts.supervisors[k].call_name;
}
else {
instructors += " " + ts.supervisors[k].first_names;
}
instructors += " " + ts.supervisors[k].last_name;
}
tsName += ", " + instructors;
listRow.append($("<div>").text(tsName).css("display", "inline-block"));
if (ts.status == 'canceled_id'){
var cancelledSpan = $("<div>").text(
kepler.translate('content.reservations_cancelled_time_slot'));
cancelledSpan.css("display","inline-block").css("min-width","12em");
cancelledSpan.css("margin-left", "1em");
listRow.append(cancelledSpan);
}
tsDiv.append(listRow);
var collapseRow = $('<div>').addClass('collapse').attr('id',"row" + i);
for (var j = 0; j < ts.reservations.length; j++){
var colUnitGroup = "";
var listItem = $("<li>").addClass("list-group-item");
var helpDiv = $("<div>").addClass("row");
var listDivInfo = $("<div>").addClass("col-sm-6");
addExperimentsInfo(ts, j, listDivInfo);
helpDiv.append(listDivInfo);
if(ts.reservations[j].notes.length !== 0){
var infoDiv = $("<div>").append($("<b>").text(kepler.translate(
'content.reservations_extra_info') + ":"));
for (var l = 0; l < ts.reservations[j].notes.length; l++) {
infoDiv.append($("<br>")).append($("<i>").text(
ts.reservations[j].notes[l].note));
}
helpDiv.append(infoDiv);
}
listItem.append(helpDiv);
collapseRow.append(listItem);
}
var buttonClass = '';
buttonClass = "class='btn btn-default'";
var editButton = $("<button id=" + ts.id + " " + buttonClass +
">" + kepler.translate('button.edit') +"</button>");
if (ts.start_time > currentTime) editButton.hide();
if (noOfExperiments === 0) editButton.attr("disabled", true);
editButton.click(function(){
notImplementedMsg();
});
var buttonDiv = $("<div>").attr("align", "right");
buttonDiv.append(editButton);
collapseRow.append(buttonDiv);
tsDiv.append(collapseRow);
tsList.append(tsDiv);
}
}
/**
* Initialises and updates the calendar.
* @memberof module:supervision_shifts
*/
function updateCalendar() {
if (cal === null) {
initCalendar();
}
cal.fullCalendar('refetchEvents');
}
/**
* Selects the event clicked on the calendar.
* @memberof module:supervision_shifts
* @param event - Contains the event information.
* @param element - Contains information what kind of
* element the clicked event is.
* @param view - Contains the viewmode in which the element is shown.
*/
function calendarClick (event, element, view) {
if (event.eventTimeslot !== undefined) {
selectCalendarTimeslot(event);
}
}
/**
* Renders the events to the calendar using a default renderer.
* @memberof module:supervision_shifts
* @param event - Contains the event information.
* @param element - Contains information what kind of
* element the clicked event is.
* @param view - Contains the viewmode in which the element is shown.
*/
function calendarEventRender(event, element, view) {
calUtil.defaultEventRender(event, element, view);
}
/**
* Initialises the calendar.
* @memberof module:supervision_shifts
* @param calendarClick - The click function to be added to the calendar events.
* @param calendarEventRender - The render options to be added to
* the calendar events.
*/
function initCalendar() {
cal = calUtil.initCal(calendarClick, calendarEventRender);
cal.fullCalendar('addEventSource', {
events: function(start, end, timezone, callback) {
var params = {
'start_time': start.toISOString(),
'end_time': end.toISOString()
};
if(showOwnTimeSlots) {
params.current_user = true;
}
kepler.getCalendarEvents(params, function(data) {
var events = [];
for (var i = 0; i < data.events.length; i++) {
var event = data.events[i];
var color = calUtil.colorPalette.reservedGrey;
var pointer = false;
var res_id = null;
if(event.type === 'reservation'){
color = calUtil.colorPalette.lightBlue;
res_id = event.reservation.id;
pointer = true;
}
calEvent = calUtil.makeCalendarEvent(event);
calEvent.color = color;
calEvent.borderColor = calUtil.colorPalette.borderBlue;
calEvent.textColor = 'black';
calEvent.reservation_id = res_id;
calEvent.pointer = pointer;
events.push(calEvent);
}
callback(events);
});
}
});
}
/**
* Gets the number of reservations for the specific time slot.
*
* @memberof module:supervision_shifts
* @param timeslot - The time slot for which the information is fetched for.
*/
function getNumberOfReservations(timeslot){
return timeslot.reservations.length;
}
/**
* Creates a list element that includes the information of the reserved
* unit, the extra information it may have and its participants.
* @memberof module:supervision_shifts
* @param {object} timeslot - The selected time slot.
* @param {number} index - The index of the wanted unit.
* @param {object} parent - The element where the information is added.
*/
function addExperimentsInfo(timeslot, index, parent){
var studentList = $("<ul>").css("list-style","none");
var experiment = timeslot.reservations[index];
parent.append($("<div>").text(experiment.unit_group_name + "/" +
experiment.unit_qualifier + ", " + experiment.unit_name));
for (var k = 0; k < experiment.user_group.members.length; k++){
var listItem = $("<li>");
var button = $("<button>");
button.addClass("btn btn-xs btn-default").attr("type", "button");
button.attr("data-placement", "bottom");
button.attr("data-toggle", "popover").attr("title",
kepler.translate('label.contactInfo'));
var emailText = "";
if (experiment.user_group.members[k].email === ""){
emailText = kepler.translate('label.noContactInfo');
}
else {
emailText = experiment.user_group.members[k].email;
}
button.attr("data-content",emailText);
button.append($("<span>").addClass("glyphicon glyphicon-info-sign"));
button.popover();
listItem.append(button);
listItem.append($("<span>").text(
" " + experiment.user_group.members[k].name + " "));
studentList.append(listItem);
}
parent.append(studentList);
}
/**
* Shows the wanted time slots based on which options (past, present, future)
* are checked and hides the rest. If no time slots match the selected time
* frame, shows a notification.
* @memberof module:supervision_shifts
*/
function updateTable(){
var tsList = $('#timeSlotList');
var howManyDisplayed = 0;
var showPast = $('#selectionPast').is(':checked');
var showCurrent = $('#selectionCurrent').is(':checked');
var showFuture =$('#selectionFuture').is(':checked');
function timeSlotVisible(timeSlot) {
return (showPast && timeSlot.end_time < currentTime) ||
(showCurrent && (timeSlot.start_time < currentTime &&
timeSlot.end_time > currentTime) ) ||
(showFuture && timeSlot.start_time > currentTime);
}
for (var i = 0; i < timeslots.length; i++) {
if (timeSlotVisible(timeslots[i])) {
$("#li" + i).show();
howManyDisplayed++;
}
else $("#li" + i).hide();
}
if(howManyDisplayed === 0) {
$("#noMatches").show();
$("#timeSlotList").hide();
}
else {
$("#noMatches").hide();
$("#timeSlotList").show();
}
}
/**
* Reloads the information of the time slots from the database, empties and
* updates the list of the time slots.
* @memberof module:supervision_shifts
*/
function reloadTimeSlots(){
var tsTable = $("#timeSlotList");
tsTable.empty();
var params = null;
if (showOwnTimeSlots){
if(ownTimeSlots === null){
params = {
"current_user": true,
"only_active": true,
};
kepler.getTimeSlots(params, function (data) {
ownTimeSlots = data;
currentTime = data.timestamp;
initTable(ownTimeSlots);
updateTable();
$('#displayedSelection').change(function () {
updateTable();
});
});
}
else {
initTable(ownTimeSlots);
updateTable();
}
}
else if (!showOwnTimeSlots){
if(allTimeSlots === null){
params = {
"only_active": true,
};
kepler.getTimeSlots(params, function (data) {
allTimeSlots = data;
currentTime = data.timestamp;
initTable(allTimeSlots);
updateTable();
});
}
else{
initTable(allTimeSlots);
updateTable();
}
}
}
/**
* 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:supervision_shifts
*/
function doc_ready() {
$("#navSupervisionShifts").addClass("active");
reloadTimeSlots();
$("#timeframeSelection").change(function(v){
notImplementedMsg();
//TODO (Anu)
});
/**
* Updates the view to shows the supervision time slots of the selected
* user.
*
* @function
* @name supervisorSelection change
* @inner
* @memberof module:supervision_shifts
*/
$("#supervisorSelection").change(function(v){
if ($("#showOwn").is(':checked')) {
showOwnTimeSlots = true;
if($("#calendar").is(":visible")){
updateCalendar();
}else{
reloadTimeSlots();
}
}
else if ($("#showAll").is(':checked')){
showOwnTimeSlots = false;
if($("#calendar").is(":visible")){
updateCalendar();
}else{
reloadTimeSlots();
}
}
});
/**
* Toggles between the calendar and list views when the button is clicked.
*
* @function
* @name toggleCalendarBtn click
* @inner
* @memberof module:supervision_shifts
*/
$("#toggleCalendarBtn").click(function(v) {
if($("#calendar").is(":visible")) {
$("#timeSlotList").show();
$("#calendar").hide();
$("#toggleCalendarBtn").text(
kepler.translate('content.reservation_frame_button_calendar'));
reloadTimeSlots();
} else {
$("#timeSlotList").hide();
$("#calendar").show();
updateCalendar();
$("#toggleCalendarBtn").text(
kepler.translate('content.reservation_frame_button_list'));
}
});
}
$(document).ready(doc_ready);
}());