<commit_before>/*****Testing dependencies ***********************/
//This block is only executed when testing inside node.js
if (typeof require !== "undefined") {
 var fs = require("fs");
 var DaterProfile = require("./daterprofile");
 var DogProfile = require("./dogprofile");
 var DateRequest = require("./daterequest");
 var Address = require("./address");
}
/************************************************/

/**
 * shelter object represents a shelter session for the front
 * end webapp. This object is composed of a set of date requests
 * and methods to query and update server data.
 *
 */
var Shelter = function(_token, _testingMockData) {

  if (arguments < 1 || _token === undefined) {
    throw new Error("User token is required when constructing Shelter object.");
  }

  /** Te array where all date requests for this shelter are stored*/
  var dateRequests = undefined;
  /** The shelter id - determinded by petfinder.com */
  var token = _token;
  /** Enumerator used to filter requests according to status */
  var filter = { pending: "pending", history: "history"};
  /**object to which all functinality is attached */
  var shelter = {};

  /** Determines if we are testing - defaults to false if no second arg given */
  var testingMockData = _testingMockData || false;

  // This function makes XMLHttpRequest to back end API
  // server for date requests associated with the shelter token
  // This funtion is asynchronous, and takes a callback function
  // as the second parameter to be executed after successful
  // HttpRequest. Any calls made to this shelter object must be made
  // from within the passed callback funtion, as all shelter
  // funtionality is dependent on the availability of dateRequests
  // for this shelter object.
  //
  // param:
  //   token - the string token associated with shelter account
  //           for which dateRequests are to be returned if any.
  //   callback - The funtion to be executed upon successful data
  //           retrieval.
  shelter.updateDateRequests = function(callback) {
    if (!testingMockData) {
      // Request data from server through asynchronous call
      var httpRequest = new XMLHttpRequest();
      httpRequest.onreadystatechange = function() {
        if (httpRequest.readyState === 4 && httpRequest.status === 200) {
          var data = JSON.parse(httpRequest.responseText);
          if (callback) {
            // pass filtered array to callback
            console.log(data);
            dateRequests = extractDateRequestProperties(data);
            callback();
          }
        }
      };
      // prepare and send http request
      httpRequest.open('POST', '/api/getShelterRequests');
      httpRequest.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
      httpRequest.setRequestHeader("access_token", token);
      httpRequest.send(JSON.stringify());

    } else {  // this is a test run
      // Are we testing data from a specified testFile?
      if (shelter.testFile == undefined) {
        // set default mock data test file if one is not provided
        shelter.testFile = "./test/mockData/testData.json";
      }
      // read from mock data throgh synchronous call
      var content = fs.readFileSync(shelter.testFile);
      var jsonContent = JSON.parse(content);
      dateRequests = extractDateRequestProperties(jsonContent);
    }
  };

  // Getter function wich provides access to pending date
  // requests objects for this shelter.
  //
  // return:
  //   An unordered array of dateRequest objects with status
  //   equal to 'P'. Logs error, and returns null
  //   if called before shelter data is fetched.
  //
  shelter.getPendingRequests = function() {
    if (dateRequests === undefined){
      throw new Error("Calling getPendingRequests() before fetching shelter data.");
    }
    // return fileterd date requests
    return filterDateRequests(filter.pending);
  };

  // Getter function wich provides access to history date
  // requests objects for this shelter.
  //
  // return:
  //   An unorderedd array of dateRequest objects with staus
  //   equal to 'A' or 'D'. Logs error, and returns
  //   null if called before shelter data is fetched.
  //
  shelter.getHistoryRequests = function() {
    if (dateRequests === undefined){
      throw new Error("Calling getHistoryRequests() before fetching shelter data.");
    }
    // return fileterd date requests
    return filterDateRequests(filter.history);
  };

  // Makes appropiate call to database/API to update
  // status for the specified requestId - careful to update
  // the current screen to reflect changes
  shelter.updateRequestStatus = function(requestId, newStatus, feedback) {
    if (typeof(feedback) === "undefined") {
      // we reset feedback if none provided
      feedback = "";
    }
    console.log("Your feedback: " + feedback);
    var httpRequest = new XMLHttpRequest();
    httpRequest.onreadystatechange = function() {
      if (httpRequest.readyState === 4 && httpRequest.status === 200) {
        console.log("updateStatus response: " +  httpRequest.responseText);
      }
    };

    httpRequest.open('POST', '/api/updateRequestStatus');
    httpRequest.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
    httpRequest.setRequestHeader("access_token", token);
    httpRequest.send(JSON.stringify({"id": requestId, "status": newStatus, "feedback": feedback}));
  };

  // Private helper function which filters daterequests
  // based on its status determined by the passed parameter 'filterBy'.
  //
  // param:
  //   filterBy - a string which determines which set of
  //              date requests to return.
  // returns:
  //   An array of dateRequest objects with status == 'P' if
  //   parameter 'filterBy' == "pendign", or an
  //   objects with status == 'A' | 'D' if  parameter 'filetrBy' == "history".
  function filterDateRequests(filterBy) {
    var resultArray = [];
    // iterate through each request available and filter
    for (var i = 0; i < dateRequests.length; i++) {
      var status = dateRequests[i].status;

      if (filterBy == filter.pending && status == 'P') {
        // want pending requests, so status of 'P'
        resultArray.push(dateRequests[i]);
      } else if (filterBy == filter.history && status != 'P') {
        // any other status not equal to 'P' is history
        resultArray.push(dateRequests[i]);
      }
    }
    return resultArray;
  };

  // Iterates the given array of dateRequests extracts properties
  // and generates a new object array. Each dateRequest object
  // in the retuned array has the following tree properties;
  //
  //  {
  //     "id": 187326,
  //     "dateTime": "tomorrow",
  //     "status": "P",
  //     "daterProfile": {
  //       "fName": "Mike",
  //       "lName": "Jones",
  //       "email": "Mike.Jones@gmial.com",
  //       "phone": "281-330-8004",
  //       "address": {
  //         "street": "652 N 16th St",
  //         "city": "Seattle",
  //         "state": "WA",
  //         "zipcode": "92104"
  //       }
  //     },
  //     "dogProfile": {
  //       "id": 14553,
  //       "name": "Chewbacca",
  //       "sex": "M",
  //       "age:": "Adult",
  //       "photoURL": "somephotourl.com"
  //     }
  //  }
  //
  // param:
  //   data - is the unfiltered data which usually contains more fileds
  //          than we need for shelter dateRequests.
  // return:
  //   An unordered array containing date requests with limited properties
  //
  function extractDateRequestProperties(data) {
    var filteredArray = [];
    // parse data into array of dateRequests objects. Here we
    // extract the desired fields to build each dateRequest
    for (var i = 0; i < data.length; i++) {
      var r = data[i];   // current result

      // parse user's address
      var address = Address(r.user.street,
                            r.user.city,
                            r.user.state,
                            r.user.zip);
      // parse daterProfile into object
      var dater = DaterProfile (r.user.fname,
                                r.user.lname,
                                r.user.email,
                                r.user.phone,
                                address);
      // parse dogProfile inot object
      var dog = DogProfile(r.dog.id,
                           r.dog.name,
                           r.dog.sex,
                           r.dog.age,
                           r.dog.media.photos[1].pn);
      // build dateRequest from parsed data
      var parsedRequest = DateRequest(r.request.id,
                                      dog, dater,
                                      epochToString(r.request.epoch),
                                      r.request.status,
                                      r.request.reason,
                                      r.request.feedback);

      // add new request
      filteredArray.push(parsedRequest);
    }

    return filteredArray;
  };

  // Formats epoch and returns a human readable date:time
  // Private helper function which formats the given epoch
  // into a human readable date string in the following format;
  //
  //   "mm/dd/year at hr:mi"
  //
  // param:
  //   epoch - the epoch value to be convertedinto
  function epochToString(epoch) {
    var d = new Date(epoch);
    var month  = d.getMonth() + 1; // account for month offset [0,11]
    var day    = d.getDate();
    var year   = d.getFullYear();
    var hr     =  "" + d.getHours();
    var min    = "" + d.getMinutes();
    // maintain two digit time format
    hr = (hr.length < 2) ? "0" + hr: hr;
    min = (min.length < 2) ? "0" + min: min;

    return month + "/" + day + "/" + year + " at " + hr + ":" + min;
  }

  return shelter;
};

if (typeof module !== "undefined" && typeof module.exports !== "undefined") {
 module.exports = Shelter;
} else {
  window.Shelter = Shelter;
}
<commit_msg>added date request date validation for request object from backend API<commit_after>/*****Testing dependencies ***********************/
//This block is only executed when testing inside node.js
if (typeof require !== "undefined") {
 var fs = require("fs");
 var DaterProfile = require("./daterprofile");
 var DogProfile = require("./dogprofile");
 var DateRequest = require("./daterequest");
 var Address = require("./address");
}
/************************************************/

/**
 * shelter object represents a shelter session for the front
 * end webapp. This object is composed of a set of date requests
 * and methods to query and update server data.
 *
 */
var Shelter = function(_token, _testingMockData) {

  if (arguments < 1 || _token === undefined) {
    throw new Error("User token is required when constructing Shelter object.");
  }

  /** Te array where all date requests for this shelter are stored*/
  var dateRequests = undefined;
  /** The shelter id - determinded by petfinder.com */
  var token = _token;
  /** Enumerator used to filter requests according to status */
  var filter = { pending: "pending", history: "history"};
  /**object to which all functinality is attached */
  var shelter = {};

  /** Determines if we are testing - defaults to false if no second arg given */
  var testingMockData = _testingMockData || false;

  // This function makes XMLHttpRequest to back end API
  // server for date requests associated with the shelter token
  // This funtion is asynchronous, and takes a callback function
  // as the second parameter to be executed after successful
  // HttpRequest. Any calls made to this shelter object must be made
  // from within the passed callback funtion, as all shelter
  // funtionality is dependent on the availability of dateRequests
  // for this shelter object.
  //
  // param:
  //   token - the string token associated with shelter account
  //           for which dateRequests are to be returned if any.
  //   callback - The funtion to be executed upon successful data
  //           retrieval.
  shelter.updateDateRequests = function(callback) {
    if (!testingMockData) {
      // Request data from server through asynchronous call
      var httpRequest = new XMLHttpRequest();
      httpRequest.onreadystatechange = function() {
        if (httpRequest.readyState === 4 && httpRequest.status === 200) {
          var data = JSON.parse(httpRequest.responseText);
          if (callback) {
            // pass filtered array to callback
            console.log(data);
            dateRequests = extractDateRequestProperties(data);
            callback();
          }
        }
      };
      // prepare and send http request
      httpRequest.open('POST', '/api/getShelterRequests');
      httpRequest.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
      httpRequest.setRequestHeader("access_token", token);
      httpRequest.send(JSON.stringify());

    } else {  // this is a test run
      // Are we testing data from a specified testFile?
      if (shelter.testFile == undefined) {
        // set default mock data test file if one is not provided
        shelter.testFile = "./test/mockData/testData.json";
      }
      // read from mock data throgh synchronous call
      var content = fs.readFileSync(shelter.testFile);
      var jsonContent = JSON.parse(content);
      dateRequests = extractDateRequestProperties(jsonContent);
    }
  };

  // Getter function wich provides access to pending date
  // requests objects for this shelter.
  //
  // return:
  //   An unordered array of dateRequest objects with status
  //   equal to 'P'. Logs error, and returns null
  //   if called before shelter data is fetched.
  //
  shelter.getPendingRequests = function() {
    if (dateRequests === undefined){
      throw new Error("Calling getPendingRequests() before fetching shelter data.");
    }
    // return fileterd date requests
    return filterDateRequests(filter.pending);
  };

  // Getter function wich provides access to history date
  // requests objects for this shelter.
  //
  // return:
  //   An unorderedd array of dateRequest objects with staus
  //   equal to 'A' or 'D'. Logs error, and returns
  //   null if called before shelter data is fetched.
  //
  shelter.getHistoryRequests = function() {
    if (dateRequests === undefined){
      throw new Error("Calling getHistoryRequests() before fetching shelter data.");
    }
    // return fileterd date requests
    return filterDateRequests(filter.history);
  };

  // Makes appropiate call to database/API to update
  // status for the specified requestId - careful to update
  // the current screen to reflect changes
  shelter.updateRequestStatus = function(requestId, newStatus, feedback) {
    if (typeof(feedback) === "undefined") {
      // we reset feedback if none provided
      feedback = "";
    }
    console.log("Your feedback: " + feedback);
    var httpRequest = new XMLHttpRequest();
    httpRequest.onreadystatechange = function() {
      if (httpRequest.readyState === 4 && httpRequest.status === 200) {
        console.log("updateStatus response: " +  httpRequest.responseText);
      }
    };

    httpRequest.open('POST', '/api/updateRequestStatus');
    httpRequest.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
    httpRequest.setRequestHeader("access_token", token);
    httpRequest.send(JSON.stringify({"id": requestId, "status": newStatus, "feedback": feedback}));
  };

  // Private helper function which filters daterequests
  // based on its status determined by the passed parameter 'filterBy'.
  //
  // param:
  //   filterBy - a string which determines which set of
  //              date requests to return.
  // returns:
  //   An array of dateRequest objects with status == 'P' if
  //   parameter 'filterBy' == "pendign", or an
  //   objects with status == 'A' | 'D' if  parameter 'filetrBy' == "history".
  function filterDateRequests(filterBy) {
    var resultArray = [];
    // iterate through each request available and filter
    for (var i = 0; i < dateRequests.length; i++) {
      var status = dateRequests[i].status;

      if (filterBy == filter.pending && status == 'P') {
        // want pending requests, so status of 'P'
        resultArray.push(dateRequests[i]);
      } else if (filterBy == filter.history && status != 'P') {
        // any other status not equal to 'P' is history
        resultArray.push(dateRequests[i]);
      }
    }
    return resultArray;
  };

  // Iterates the given array of dateRequests extracts properties
  // and generates a new object array. Each dateRequest object
  // in the retuned array has the following tree properties;
  //
  //  {
  //     "id": 187326,
  //     "dateTime": "tomorrow",
  //     "status": "P",
  //     "daterProfile": {
  //       "fName": "Mike",
  //       "lName": "Jones",
  //       "email": "Mike.Jones@gmial.com",
  //       "phone": "281-330-8004",
  //       "address": {
  //         "street": "652 N 16th St",
  //         "city": "Seattle",
  //         "state": "WA",
  //         "zipcode": "92104"
  //       }
  //     },
  //     "dogProfile": {
  //       "id": 14553,
  //       "name": "Chewbacca",
  //       "sex": "M",
  //       "age:": "Adult",
  //       "photoURL": "somephotourl.com"
  //     }
  //  }
  //
  // param:
  //   data - is the unfiltered data which usually contains more fileds
  //          than we need for shelter dateRequests.
  // return:
  //   An unordered array containing date requests with limited properties
  //
  function extractDateRequestProperties(data) {
    var filteredArray = [];
    // parse data into array of dateRequests objects. Here we
    // extract the desired fields to build each dateRequest
    for (var i = 0; i < data.length; i++) {
      var r =  validateRequestProperties(data[i]);   // current result

      // parse user's address
      var address = Address(r.user.street,
                            r.user.city,
                            r.user.state,
                            r.user.zip);
      // parse daterProfile into object
      var dater = DaterProfile (r.user.fname,
                                r.user.lname,
                                r.user.email,
                                r.user.phone,
                                address);
      // parse dogProfile inot object
      var dog = DogProfile(r.dog.id,
                           r.dog.name,
                           r.dog.sex,
                           r.dog.age,
                           r.dog.media.photos[1].pn);
      // build dateRequest from parsed data
      var parsedRequest = DateRequest(r.request.id,
                                      dog, dater,
                                      epochToString(r.request.epoch),
                                      r.request.status,
                                      r.request.reason,
                                      r.request.feedback);

      // add new request
      filteredArray.push(parsedRequest);
    }

    return filteredArray;
  };

  // Validates request properties for undefined, null, or empty strings
  // param: r - the request object to verify
  //
  // return:
  //  A request object with invalid fields replaced with "Non provided"
  //
  function validateRequestProperties (r) {
    // Verify user profile properties
    if (typeof(r.user.street) === "undefined" || r.user.street === null || r.user.street === "") { r.user.street = "None provided";}
    if (typeof(r.user.city) === "undefined" || r.user.city === null || r.user.city === "") { r.user.city = "None provided";}
    if (typeof(r.user.state) === "undefined" || r.user.state === null || r.user.state === "") { r.user.state = "None provided";}
    if (typeof(r.user.zip) === "undefined" || r.user.zip === null || r.user.zip === "") { r.user.zip = "None provided";}
    if (typeof(r.user.fname) === "undefined" || r.user.fname === null || r.user.fname === "") { r.user.fname = "None provided";}
    if (typeof(r.user.lname) === "undefined" || r.user.lname === null || r.user.lname === "") { r.user.lname = "None provided";}
    if (typeof(r.user.email) === "undefined" || r.user.email === null || r.user.email === "") { r.user.email = "None provided";}
    if (typeof(r.user.phone) === "undefined" || r.user.phone=== null || r.user.phone === "") { r.user.phone = "None provided";}

    // Verify dog profile properties
    if (typeof(r.dog.id) === "undefined" || r.dog.id === null || r.dog.id === "" ) { r.dog.id = "None provided";}
    if (typeof(r.dog.name) === "undefined" || r.dog.name === null || r.dog.name === "") { r.dog.name = "None provided";}
    if (typeof(r.dog.sex) === "undefined" || r.dog.sex === null || r.dog.sex === "") { r.dog.sex = "None provided";}
    if (typeof(r.dog.age) === "undefined" || r.dog.age === null || r.dog.age === "") { r.dog.age = "None provided";}
    if (typeof(r.dog.media.photos[1]) === "undefined") { r.dog.media.photos[1] = "Non provided";}

    // Verify request properties
    if (typeof(r.request.id) === "undefined" || r.request.id === null || r.request.id === "") { r.request.id = "None provided";}
    if (typeof(r.request.status) === "undefined" || r.request.status === null || r.request.status === "") { r.request.status = "P";}
    if (typeof(r.request.epoch) === "undefined" || r.request.epoch === null || r.request.epoch) { r.request.epoch = "None provided";}
    if (typeof(r.request.reason) === "undefined" || r.request.reason === null || r.request.reason === "") { r.request.reason = "None provided";}
    if (typeof(r.request.feedback) === "undefined" || r.request.feedback === "") { r.request.feedback = "None provided";}
    return r;
  }

  // Formats epoch and returns a human readable date:time
  // Private helper function which formats the given epoch
  // into a human readable date string in the following format;
  //
  //   "mm/dd/year at hr:mi"
  //
  // param:
  //   epoch - the epoch value to be convertedinto
  function epochToString(epoch) {
    var d = new Date(epoch);
    var month  = d.getMonth() + 1; // account for month offset [0,11]
    var day    = d.getDate();
    var year   = d.getFullYear();
    var hr     =  "" + d.getHours();
    var min    = "" + d.getMinutes();
    // maintain two digit time format
    hr = (hr.length < 2) ? "0" + hr: hr;
    min = (min.length < 2) ? "0" + min: min;

    return month + "/" + day + "/" + year + " at " + hr + ":" + min;
  }

  return shelter;
};

if (typeof module !== "undefined" && typeof module.exports !== "undefined") {
 module.exports = Shelter;
} else {
  window.Shelter = Shelter;
}
<|endoftext|>


<commit_before>// delete-resource.js
/*
   Copyright (c) 2011 3 Round Stones Inc., Some Rights Reserved
   Licensed under the Apache License, Version 2.0, http://www.apache.org/licenses/LICENSE-2.0
*/

(function($, jQuery){

if (!window.calli) {
    window.calli = {};
}
window.calli.deleteResource = function(event, redirect) {
    event = calli.fixEvent(event);
    var form = $(event.target);
    if(!form.is('form')) form = form.closest('form');

    if (event && !confirm("Are you sure you want to delete " + document.title + "?"))
        return;

    if (!form || !form.length) {
        form = $("form[about],form[resource]");
    }
    if (!form.length) {
        form = $(document);
    }
    try {
        var de = jQuery.Event("calliDelete");
        form.trigger(de);
        if (!de.isDefaultPrevented()) {
            var url = calli.getPageUrl();
            if (url.indexOf('?') > 0) {
                url = url.substring(0, url.indexOf('?'));
            }
            var xhr = $.ajax({ type: "DELETE", url: url, beforeSend: function(xhr){
                var lastmod = getLastModified();
                if (lastmod) {
                    xhr.setRequestHeader("If-Unmodified-Since", lastmod);
                }
                withCredentials(xhr);
            }, success: function(data, textStatus) {
                try {
                    var event = jQuery.Event("calliRedirect");
                    event.location = redirect ? redirect : form.attr("data-redirect");
                    if (!event.location) {
                        if (!event.location) {
                            event.location = document.referrer;
                        }
                        if (event.location) {
                            var href = calli.getPageUrl();
                            if (href.indexOf('?') > 0) {
                                href = href.substring(0, href.indexOf('?'));
                            }
                            var referrer = event.location;
                            if (referrer.indexOf('?') > 0) {
                                referrer = referrer.substring(0, referrer.indexOf('?'));
                            }
                            if (href == referrer) {
                                event.location = null; // don't redirect back to self
                            }
                        }
                    }
                    if (event.location) {
                        // TODO verify this location is not going to 404 on us w/o causing an calliError
                    }
                    if (!event.location && location.pathname.match(/\//)) {
                        event.location = '../';
                    }
                    if (!event.location) {
                        event.location = './';
                    }
                    form.trigger(event)
                    if (!event.isDefaultPrevented()) {
                        if (event.location) {
                            location.replace(event.location);
                        } else {
                            location.replace('/');
                        }
                    }
                } catch(e) {
                    throw calli.error(e);
                }
            }})
        }
    } catch(e) {
        calli.error(e);
    }
}

function getLastModified() {
    try {
        var committedOn = $('#resource-lastmod').find('[property=audit:committedOn]').attr('content');
        return new Date(committedOn).toGMTString();
    } catch (e) {
        return null;
    }
}

function withCredentials(req) {
    try {
        req.withCredentials = true;
    } catch (e) {}
}

})(jQuery, jQuery);

<commit_msg>Fix ondelete redirect location<commit_after>// delete-resource.js
/*
   Copyright (c) 2011 3 Round Stones Inc., Some Rights Reserved
   Licensed under the Apache License, Version 2.0, http://www.apache.org/licenses/LICENSE-2.0
*/

(function($, jQuery){

if (!window.calli) {
    window.calli = {};
}
window.calli.deleteResource = function(event, redirect) {
    event = calli.fixEvent(event);
    var form = $(event.target);
    if(!form.is('form')) form = form.closest('form');

    if (event && !confirm("Are you sure you want to delete " + document.title + "?"))
        return;

    if (!form || !form.length) {
        form = $("form[about],form[resource]");
    }
    if (!form.length) {
        form = $(document);
    }
    try {
        var de = jQuery.Event("calliDelete");
        form.trigger(de);
        if (!de.isDefaultPrevented()) {
            var url = calli.getPageUrl();
            if (url.indexOf('?') > 0) {
                url = url.substring(0, url.indexOf('?'));
            }
            var xhr = $.ajax({ type: "DELETE", url: url, beforeSend: function(xhr){
                var lastmod = getLastModified();
                if (lastmod) {
                    xhr.setRequestHeader("If-Unmodified-Since", lastmod);
                }
                withCredentials(xhr);
            }, success: function(data, textStatus) {
                try {
                    var event = jQuery.Event("calliRedirect");
                    event.location = redirect ? redirect : form.attr("data-redirect");
                    if (!event.location) {
                        if (!event.location) {
                            event.location = document.referrer;
                        }
                        if (event.location) {
                            var href = calli.getPageUrl();
                            if (href.indexOf('?') > 0) {
                                href = href.substring(0, href.indexOf('?'));
                            }
                            var referrer = event.location;
                            if (referrer.indexOf('?') > 0) {
                                referrer = referrer.substring(0, referrer.indexOf('?'));
                            }
                            if (href == referrer) {
                                event.location = null; // don't redirect back to self
                            }
                        }
                    }
                    if (event.location) {
                        // TODO verify this location is not going to 404 on us w/o causing an calliError
                    }
                    if (!event.location && location.pathname.match(/\/$/)) {
                        event.location = '../';
                    }
                    if (!event.location) {
                        event.location = './';
                    }
                    form.trigger(event)
                    if (!event.isDefaultPrevented()) {
                        if (event.location) {
                            location.replace(event.location);
                        } else {
                            location.replace('/');
                        }
                    }
                } catch(e) {
                    throw calli.error(e);
                }
            }})
        }
    } catch(e) {
        calli.error(e);
    }
}

function getLastModified() {
    try {
        var committedOn = $('#resource-lastmod').find('[property=audit:committedOn]').attr('content');
        return new Date(committedOn).toGMTString();
    } catch (e) {
        return null;
    }
}

function withCredentials(req) {
    try {
        req.withCredentials = true;
    } catch (e) {}
}

})(jQuery, jQuery);

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved.
 */

define([
    'underscore',
    'backbone',
    'setting/sm/ui/js/models/ClusterModel',
    'setting/sm/ui/js/views/ClusterEditView'
], function (_, Backbone, ClusterModel, ClusterEditView) {
    var prefixId = smConstants.CLUSTER_PREFIX_ID,
        clusterEditView = new ClusterEditView(),
        gridElId = '#' + prefixId + '-results';

    var ClusterView = Backbone.View.extend({
        el: $(contentContainer),

        render: function (viewConfig) {
            var hashParams = viewConfig['hashParams']
            if (hashParams['cluster_id'] != null) {
                this.renderCluster(hashParams['cluster_id']);
            } else {
                this.renderClustersList();
            }
        },

        renderClustersList: function () {
            var directoryTemplate = contrail.getTemplate4Id(smConstants.SM_PREFIX_ID + "-template");

            this.$el.html(directoryTemplate({name: prefixId}));

            var gridConfig = {
                header: {
                    title: {
                        text: smLabels.TITLE_CLUSTERS
                    },
                    advanceControls: headerActionConfig
                },
                columnHeader: {
                    columns: smGridConfig.CLUSTER_COLUMNS
                },
                body: {
                    options: {
                        actionCell: rowActionConfig,
                        checkboxSelectable: {
                            onNothingChecked: function(e){
                                $('#btnDeleteClusters').addClass('disabled-link');
                            },
                            onSomethingChecked: function(e){
                                $('#btnDeleteClusters').removeClass('disabled-link');
                            }
                        },
                        detail: {
                            template: $('#sm-grid-2-row-group-detail-template').html(),
                            templateConfig: detailTemplateConfig
                        }
                    },
                    dataSource: {
                        remote: {
                            ajaxConfig: {
                                url: smUtils.getObjectDetailUrl(prefixId, smConstants.SERVERS_STATE_PROCESSOR)
                            }
                        }
                    }
                }
            };

            smUtils.renderGrid(gridElId, gridConfig);
        },

        renderCluster: function (clusterId) {
            var detailTemplate = contrail.getTemplate4Id("sm-grid-2-row-group-detail-template"),
                clusterTemplate = contrail.getTemplate4Id("sm-cluster-template"),
                clusterActionTemplate = contrail.getTemplate4Id("sm-cluster-action-template"),
                ajaxConfig = {}, that = this;
            ajaxConfig.type = "GET";
            ajaxConfig.cache = "true";
            ajaxConfig.url = smUtils.getObjectDetailUrl(smConstants.CLUSTER_PREFIX_ID, smConstants.SERVERS_STATE_PROCESSOR) + "&id=" + clusterId;

            that.$el.html(clusterTemplate({cluster_id: clusterId}));
            contrail.ajaxHandler(ajaxConfig, function () {}, function (response) {
                var actionConfigItem = null, i = 0;
                $.each(clusterActionCallbackConfig, function(rowActionCallbackConfigKey, rowActionCallbackConfigValue) {
                    actionConfigItem = $(clusterActionTemplate(rowActionConfig[i]));
                    that.$el.find("#cluster-actions").append(actionConfigItem);

                    actionConfigItem.on('click', function() {
                        rowActionCallbackConfigValue(response[0]);
                    });
                    i++;
                });

                that.$el.find("#cluster-details").html(detailTemplate({dc: response[0], templateConfig: detailTemplateConfig}));
                requirejs(["/setting/sm/ui/js/views/ServersView.js"], function (ServersView) {
                    var serversView = new ServersView({
                        el: that.$el.find("#cluster-server-list")
                    });
                    serversView.render({serverColumnsType: smConstants.CLUSTER_PREFIX_ID, showAssignRoles: true, hashParams: {"cluster_id": clusterId}});
                });
            }, function () {});
        }
    });

    var clusterActionCallbackConfig = {
        renderAddServers: function(dataItem) {
            var clusterModel = new ClusterModel(dataItem);

            clusterEditView.model = clusterModel;
            clusterEditView.renderAddServers({"title": smLabels.TITLE_ADD_SERVERS, callback: function () {
                loadFeature({p: smConstants.URL_HASH_SM_CLUSTERS, q: {cluster_id: dataItem['id']}});
            }});
        },
        renderRemoveServers: function(dataItem) {
            var clusterModel = new ClusterModel(dataItem);

            clusterEditView.model = clusterModel;
            clusterEditView.renderRemoveServers({"title": smLabels.TITLE_REMOVE_SERVERS, callback: function () {
                loadFeature({p: smConstants.URL_HASH_SM_CLUSTERS, q: {cluster_id: dataItem['id']}});
            }});
        },
        renderAssignRoles: function(dataItem) {
            var clusterModel = new ClusterModel(dataItem),
                checkedRow = [dataItem];

            clusterEditView.model = clusterModel;
            clusterEditView.renderAssignRoles({"title": smLabels.TITLE_ASSIGN_ROLES, checkedRows: checkedRow, callback: function () {
                loadFeature({p: smConstants.URL_HASH_SM_CLUSTERS, q: {cluster_id: dataItem['id']}});
            }});
        },
        renderConfigure: function(dataItem) {
            var clusterModel = new ClusterModel(dataItem),
                checkedRow = [dataItem];

            clusterEditView.model = clusterModel;
            clusterEditView.renderConfigure({"title": smLabels.TITLE_EDIT_CONFIG, checkedRows: checkedRow, callback: function () {
                loadFeature({p: smConstants.URL_HASH_SM_CLUSTERS, q: {cluster_id: dataItem['id']}});
            }});
        },
        renderReimage: function(dataItem) {
            var clusterModel = new ClusterModel(dataItem),
                checkedRow = [dataItem];

            clusterEditView.model = clusterModel;
            clusterEditView.renderReimage({"title": smLabels.TITLE_REIMAGE, checkedRows: checkedRow, callback: function () {
                loadFeature({p: smConstants.URL_HASH_SM_CLUSTERS, q: {cluster_id: dataItem['id']}});
            }});
        },
        renderProvision: function(dataItem) {
            var clusterModel = new ClusterModel(dataItem),
                checkedRow = [dataItem];

            clusterEditView.model = clusterModel;
            clusterEditView.renderProvision({"title": smLabels.TITLE_PROVISION_CLUSTER, checkedRows: checkedRow, callback: function () {
                loadFeature({p: smConstants.URL_HASH_SM_CLUSTERS, q: {cluster_id: dataItem['id']}});
            }});
        },
        renderDelete: function (dataItem) {
            var clusterModel = new ClusterModel(dataItem),
                checkedRow = dataItem;

            clusterEditView.model = clusterModel;
            clusterEditView.renderDeleteCluster({"title": smLabels.TITLE_DEL_CLUSTER, checkedRows: checkedRow, callback: function () {
                loadFeature({p: smConstants.URL_HASH_SM_CLUSTERS, q: {}});
            }});
        }
    };

    var rowActionCallbackConfig = {
        renderAddServers: function(dataItem) {
            var clusterModel = new ClusterModel(dataItem),
                _title = smLabels.TITLE_ADD_SERVERS + ' ('+ dataItem['id'] +')';

            clusterEditView.model = clusterModel;
            clusterEditView.renderAddServers({"title": _title, callback: function () {
                var dataView = $(gridElId).data("contrailGrid")._dataView;
                dataView.refreshData();
            }});
        },
        renderRemoveServers: function(dataItem) {
            var clusterModel = new ClusterModel(dataItem),
                _title = smLabels.TITLE_REMOVE_SERVERS + ' ('+ dataItem['id'] +')';

            clusterEditView.model = clusterModel;
            clusterEditView.renderRemoveServers({"title": _title, callback: function () {
                var dataView = $(gridElId).data("contrailGrid")._dataView;
                dataView.refreshData();
            }});
        },
        renderAssignRoles: function(dataItem) {
            var clusterModel = new ClusterModel(dataItem),
                checkedRow = [dataItem],
                _title = smLabels.TITLE_ASSIGN_ROLES + ' ('+ dataItem['id'] +')';

            clusterEditView.model = clusterModel;
            clusterEditView.renderAssignRoles({"title": _title, checkedRows: checkedRow, callback: function () {
                var dataView = $(gridElId).data("contrailGrid")._dataView;
                dataView.refreshData();
            }});
        },
        renderConfigure: function(dataItem) {
            var clusterModel = new ClusterModel(dataItem),
                checkedRow = [dataItem],
                _title = smLabels.TITLE_EDIT_CONFIG + ' ('+ dataItem['id'] +')';

            clusterEditView.model = clusterModel;
            clusterEditView.renderConfigure({"title": _title, checkedRows: checkedRow, callback: function () {
                var dataView = $(gridElId).data("contrailGrid")._dataView;
                dataView.refreshData();
            }});
        },
        renderReimage: function(dataItem) {
            var clusterModel = new ClusterModel(dataItem),
                checkedRow = [dataItem],
                _title = smLabels.TITLE_REIMAGE + ' ('+ dataItem['id'] +')';

            clusterEditView.model = clusterModel;
            clusterEditView.renderReimage({"title": _title, checkedRows: checkedRow, callback: function () {
                var dataView = $(gridElId).data("contrailGrid")._dataView;
                dataView.refreshData();
            }});
        },
        renderProvision: function(dataItem) {
            var clusterModel = new ClusterModel(dataItem),
                checkedRow = [dataItem],
                _title = smLabels.TITLE_PROVISION_CLUSTER + ' ('+ dataItem['id'] +')';

            clusterEditView.model = clusterModel;
            clusterEditView.renderProvision({"title": _title, checkedRows: checkedRow, callback: function () {
                var dataView = $(gridElId).data("contrailGrid")._dataView;
                dataView.refreshData();
            }});
        },
        renderDelete: function (dataItem) {
            var clusterModel = new ClusterModel(dataItem),
                checkedRow = dataItem,
                _title = smLabels.TITLE_ADD_SERVERS + ' ('+ dataItem['id'] +')';

            clusterEditView.model = clusterModel;
            clusterEditView.renderDeleteCluster({"title": _title, checkedRows: checkedRow, callback: function () {
                var dataView = $(gridElId).data("contrailGrid")._dataView;
                dataView.refreshData();
            }});
        }
    };

    var rowActionConfig = [
        smGridConfig.getAddServersAction(function (rowIndex) {
            var dataItem = $('#' + prefixId + '-results').data('contrailGrid')._dataView.getItem(rowIndex);
            rowActionCallbackConfig.renderAddServers(dataItem);
        }),
        smGridConfig.getRemoveServersAction(function (rowIndex) {
            var dataItem = $('#' + prefixId + '-results').data('contrailGrid')._dataView.getItem(rowIndex);
            rowActionCallbackConfig.renderRemoveServers(dataItem);
        }),
        smGridConfig.getAssignRoleAction(function (rowIndex) {
            var dataItem = $('#' + prefixId + '-results').data('contrailGrid')._dataView.getItem(rowIndex);
            rowActionCallbackConfig.renderAssignRoles(dataItem)
        }),
        smGridConfig.getConfigureAction(function (rowIndex) {
            var dataItem = $('#' + prefixId + '-results').data('contrailGrid')._dataView.getItem(rowIndex);
            rowActionCallbackConfig.renderConfigure(dataItem);
        }),
        smGridConfig.getReimageAction(function (rowIndex) {
            var dataItem = $('#' + prefixId + '-results').data('contrailGrid')._dataView.getItem(rowIndex);
            rowActionCallbackConfig.renderReimage(dataItem);
        }, true),
        smGridConfig.getProvisionAction(function (rowIndex) {
            var dataItem = $('#' + prefixId + '-results').data('contrailGrid')._dataView.getItem(rowIndex);
            rowActionCallbackConfig.renderProvision(dataItem);
        }),
        smGridConfig.getDeleteAction(function (rowIndex) {
            var dataItem = $('#' + prefixId + '-results').data('contrailGrid')._dataView.getItem(rowIndex);
            rowActionCallbackConfig.renderDelete(dataItem);
        }, true)
    ];

    var detailTemplateConfig = [
        [
            {
                title: smLabels.TITLE_DETAILS,
                keys: ['id', 'email']
            },
            {
                title: smLabels.TITLE_OPENSTACK,
                keys: ['parameters.openstack_mgmt_ip', 'parameters.keystone_tenant', 'parameters.keystone_username']
            },
            {
                title: smLabels.TITLE_CONTRAIL,
                keys: ['parameters.analytics_data_ttl', 'parameters.haproxy', 'parameters.multi_tenancy', 'parameters.use_certificates', 'parameters.external_bgp', 'parameters.encapsulation_priority', 'parameters.router_asn', 'parameters.database_dir']
            }
        ],
        [
            {
                title: smLabels.TITLE_STATUS,
                keys: ['ui_added_parameters.servers_status.total_servers', 'ui_added_parameters.servers_status.new_servers', 'ui_added_parameters.servers_status.configured_servers', 'ui_added_parameters.servers_status.inprovision_servers', 'ui_added_parameters.servers_status.provisioned_servers']
            },
            {
                title: smLabels.TITLE_SERVERS_CONFIG,
                keys: ['parameters.domain', 'parameters.gateway', 'parameters.subnet_mask', 'base_image_id', 'package_image_id']
            },
            {
                title: smLabels.TITLE_STORAGE,
                keys: ['parameters.uuid', 'parameters.storage_virsh_uuid', 'parameters.storage_fsid']
            },
        ]
    ];

    var headerActionConfig = [
        /*
        {
            "type": "link",
            linkElementId: 'btnDeleteClusters',
            disabledLink: true,
            "title": smLabels.TITLE_DEL_CLUSTERS,
            "iconClass": "icon-trash",
            "onClick": function () {
            }
        },
        */
        {
            "type": "link",
            "title": smLabels.TITLE_ADD_CLUSTER,
            "iconClass": "icon-plus",
            "onClick": function () {
                var clusterModel = new ClusterModel();

                clusterEditView.model = clusterModel;
                clusterEditView.renderAddCluster({"title": smLabels.TITLE_ADD_CLUSTER, callback: function () {
                    var dataView = $(gridElId).data("contrailGrid")._dataView;
                    dataView.refreshData();
                }});
            }
        }
    ];
    return ClusterView;
});<commit_msg>Bug: Modal title name for Delete Cluster updated to 'Delete Cluster' was 'Add Server' earlier.<commit_after>/*
 * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved.
 */

define([
    'underscore',
    'backbone',
    'setting/sm/ui/js/models/ClusterModel',
    'setting/sm/ui/js/views/ClusterEditView'
], function (_, Backbone, ClusterModel, ClusterEditView) {
    var prefixId = smConstants.CLUSTER_PREFIX_ID,
        clusterEditView = new ClusterEditView(),
        gridElId = '#' + prefixId + '-results';

    var ClusterView = Backbone.View.extend({
        el: $(contentContainer),

        render: function (viewConfig) {
            var hashParams = viewConfig['hashParams']
            if (hashParams['cluster_id'] != null) {
                this.renderCluster(hashParams['cluster_id']);
            } else {
                this.renderClustersList();
            }
        },

        renderClustersList: function () {
            var directoryTemplate = contrail.getTemplate4Id(smConstants.SM_PREFIX_ID + "-template");

            this.$el.html(directoryTemplate({name: prefixId}));

            var gridConfig = {
                header: {
                    title: {
                        text: smLabels.TITLE_CLUSTERS
                    },
                    advanceControls: headerActionConfig
                },
                columnHeader: {
                    columns: smGridConfig.CLUSTER_COLUMNS
                },
                body: {
                    options: {
                        actionCell: rowActionConfig,
                        checkboxSelectable: {
                            onNothingChecked: function(e){
                                $('#btnDeleteClusters').addClass('disabled-link');
                            },
                            onSomethingChecked: function(e){
                                $('#btnDeleteClusters').removeClass('disabled-link');
                            }
                        },
                        detail: {
                            template: $('#sm-grid-2-row-group-detail-template').html(),
                            templateConfig: detailTemplateConfig
                        }
                    },
                    dataSource: {
                        remote: {
                            ajaxConfig: {
                                url: smUtils.getObjectDetailUrl(prefixId, smConstants.SERVERS_STATE_PROCESSOR)
                            }
                        }
                    }
                }
            };

            smUtils.renderGrid(gridElId, gridConfig);
        },

        renderCluster: function (clusterId) {
            var detailTemplate = contrail.getTemplate4Id("sm-grid-2-row-group-detail-template"),
                clusterTemplate = contrail.getTemplate4Id("sm-cluster-template"),
                clusterActionTemplate = contrail.getTemplate4Id("sm-cluster-action-template"),
                ajaxConfig = {}, that = this;
            ajaxConfig.type = "GET";
            ajaxConfig.cache = "true";
            ajaxConfig.url = smUtils.getObjectDetailUrl(smConstants.CLUSTER_PREFIX_ID, smConstants.SERVERS_STATE_PROCESSOR) + "&id=" + clusterId;

            that.$el.html(clusterTemplate({cluster_id: clusterId}));
            contrail.ajaxHandler(ajaxConfig, function () {}, function (response) {
                var actionConfigItem = null, i = 0;
                $.each(clusterActionCallbackConfig, function(rowActionCallbackConfigKey, rowActionCallbackConfigValue) {
                    actionConfigItem = $(clusterActionTemplate(rowActionConfig[i]));
                    that.$el.find("#cluster-actions").append(actionConfigItem);

                    actionConfigItem.on('click', function() {
                        rowActionCallbackConfigValue(response[0]);
                    });
                    i++;
                });

                that.$el.find("#cluster-details").html(detailTemplate({dc: response[0], templateConfig: detailTemplateConfig}));
                requirejs(["/setting/sm/ui/js/views/ServersView.js"], function (ServersView) {
                    var serversView = new ServersView({
                        el: that.$el.find("#cluster-server-list")
                    });
                    serversView.render({serverColumnsType: smConstants.CLUSTER_PREFIX_ID, showAssignRoles: true, hashParams: {"cluster_id": clusterId}});
                });
            }, function () {});
        }
    });

    var clusterActionCallbackConfig = {
        renderAddServers: function(dataItem) {
            var clusterModel = new ClusterModel(dataItem);

            clusterEditView.model = clusterModel;
            clusterEditView.renderAddServers({"title": smLabels.TITLE_ADD_SERVERS, callback: function () {
                loadFeature({p: smConstants.URL_HASH_SM_CLUSTERS, q: {cluster_id: dataItem['id']}});
            }});
        },
        renderRemoveServers: function(dataItem) {
            var clusterModel = new ClusterModel(dataItem);

            clusterEditView.model = clusterModel;
            clusterEditView.renderRemoveServers({"title": smLabels.TITLE_REMOVE_SERVERS, callback: function () {
                loadFeature({p: smConstants.URL_HASH_SM_CLUSTERS, q: {cluster_id: dataItem['id']}});
            }});
        },
        renderAssignRoles: function(dataItem) {
            var clusterModel = new ClusterModel(dataItem),
                checkedRow = [dataItem];

            clusterEditView.model = clusterModel;
            clusterEditView.renderAssignRoles({"title": smLabels.TITLE_ASSIGN_ROLES, checkedRows: checkedRow, callback: function () {
                loadFeature({p: smConstants.URL_HASH_SM_CLUSTERS, q: {cluster_id: dataItem['id']}});
            }});
        },
        renderConfigure: function(dataItem) {
            var clusterModel = new ClusterModel(dataItem),
                checkedRow = [dataItem];

            clusterEditView.model = clusterModel;
            clusterEditView.renderConfigure({"title": smLabels.TITLE_EDIT_CONFIG, checkedRows: checkedRow, callback: function () {
                loadFeature({p: smConstants.URL_HASH_SM_CLUSTERS, q: {cluster_id: dataItem['id']}});
            }});
        },
        renderReimage: function(dataItem) {
            var clusterModel = new ClusterModel(dataItem),
                checkedRow = [dataItem];

            clusterEditView.model = clusterModel;
            clusterEditView.renderReimage({"title": smLabels.TITLE_REIMAGE, checkedRows: checkedRow, callback: function () {
                loadFeature({p: smConstants.URL_HASH_SM_CLUSTERS, q: {cluster_id: dataItem['id']}});
            }});
        },
        renderProvision: function(dataItem) {
            var clusterModel = new ClusterModel(dataItem),
                checkedRow = [dataItem];

            clusterEditView.model = clusterModel;
            clusterEditView.renderProvision({"title": smLabels.TITLE_PROVISION_CLUSTER, checkedRows: checkedRow, callback: function () {
                loadFeature({p: smConstants.URL_HASH_SM_CLUSTERS, q: {cluster_id: dataItem['id']}});
            }});
        },
        renderDelete: function (dataItem) {
            var clusterModel = new ClusterModel(dataItem),
                checkedRow = dataItem;

            clusterEditView.model = clusterModel;
            clusterEditView.renderDeleteCluster({"title": smLabels.TITLE_DEL_CLUSTER, checkedRows: checkedRow, callback: function () {
                loadFeature({p: smConstants.URL_HASH_SM_CLUSTERS, q: {}});
            }});
        }
    };

    var rowActionCallbackConfig = {
        renderAddServers: function(dataItem) {
            var clusterModel = new ClusterModel(dataItem),
                _title = smLabels.TITLE_ADD_SERVERS + ' ('+ dataItem['id'] +')';

            clusterEditView.model = clusterModel;
            clusterEditView.renderAddServers({"title": _title, callback: function () {
                var dataView = $(gridElId).data("contrailGrid")._dataView;
                dataView.refreshData();
            }});
        },
        renderRemoveServers: function(dataItem) {
            var clusterModel = new ClusterModel(dataItem),
                _title = smLabels.TITLE_REMOVE_SERVERS + ' ('+ dataItem['id'] +')';

            clusterEditView.model = clusterModel;
            clusterEditView.renderRemoveServers({"title": _title, callback: function () {
                var dataView = $(gridElId).data("contrailGrid")._dataView;
                dataView.refreshData();
            }});
        },
        renderAssignRoles: function(dataItem) {
            var clusterModel = new ClusterModel(dataItem),
                checkedRow = [dataItem],
                _title = smLabels.TITLE_ASSIGN_ROLES + ' ('+ dataItem['id'] +')';

            clusterEditView.model = clusterModel;
            clusterEditView.renderAssignRoles({"title": _title, checkedRows: checkedRow, callback: function () {
                var dataView = $(gridElId).data("contrailGrid")._dataView;
                dataView.refreshData();
            }});
        },
        renderConfigure: function(dataItem) {
            var clusterModel = new ClusterModel(dataItem),
                checkedRow = [dataItem],
                _title = smLabels.TITLE_EDIT_CONFIG + ' ('+ dataItem['id'] +')';

            clusterEditView.model = clusterModel;
            clusterEditView.renderConfigure({"title": _title, checkedRows: checkedRow, callback: function () {
                var dataView = $(gridElId).data("contrailGrid")._dataView;
                dataView.refreshData();
            }});
        },
        renderReimage: function(dataItem) {
            var clusterModel = new ClusterModel(dataItem),
                checkedRow = [dataItem],
                _title = smLabels.TITLE_REIMAGE + ' ('+ dataItem['id'] +')';

            clusterEditView.model = clusterModel;
            clusterEditView.renderReimage({"title": _title, checkedRows: checkedRow, callback: function () {
                var dataView = $(gridElId).data("contrailGrid")._dataView;
                dataView.refreshData();
            }});
        },
        renderProvision: function(dataItem) {
            var clusterModel = new ClusterModel(dataItem),
                checkedRow = [dataItem],
                _title = smLabels.TITLE_PROVISION_CLUSTER + ' ('+ dataItem['id'] +')';

            clusterEditView.model = clusterModel;
            clusterEditView.renderProvision({"title": _title, checkedRows: checkedRow, callback: function () {
                var dataView = $(gridElId).data("contrailGrid")._dataView;
                dataView.refreshData();
            }});
        },
        renderDelete: function (dataItem) {
            var clusterModel = new ClusterModel(dataItem),
                checkedRow = dataItem,
                _title = smLabels.TITLE_DEL_CLUSTER + ' ('+ dataItem['id'] +')';

            clusterEditView.model = clusterModel;
            clusterEditView.renderDeleteCluster({"title": _title, checkedRows: checkedRow, callback: function () {
                var dataView = $(gridElId).data("contrailGrid")._dataView;
                dataView.refreshData();
            }});
        }
    };

    var rowActionConfig = [
        smGridConfig.getAddServersAction(function (rowIndex) {
            var dataItem = $('#' + prefixId + '-results').data('contrailGrid')._dataView.getItem(rowIndex);
            rowActionCallbackConfig.renderAddServers(dataItem);
        }),
        smGridConfig.getRemoveServersAction(function (rowIndex) {
            var dataItem = $('#' + prefixId + '-results').data('contrailGrid')._dataView.getItem(rowIndex);
            rowActionCallbackConfig.renderRemoveServers(dataItem);
        }),
        smGridConfig.getAssignRoleAction(function (rowIndex) {
            var dataItem = $('#' + prefixId + '-results').data('contrailGrid')._dataView.getItem(rowIndex);
            rowActionCallbackConfig.renderAssignRoles(dataItem)
        }),
        smGridConfig.getConfigureAction(function (rowIndex) {
            var dataItem = $('#' + prefixId + '-results').data('contrailGrid')._dataView.getItem(rowIndex);
            rowActionCallbackConfig.renderConfigure(dataItem);
        }),
        smGridConfig.getReimageAction(function (rowIndex) {
            var dataItem = $('#' + prefixId + '-results').data('contrailGrid')._dataView.getItem(rowIndex);
            rowActionCallbackConfig.renderReimage(dataItem);
        }, true),
        smGridConfig.getProvisionAction(function (rowIndex) {
            var dataItem = $('#' + prefixId + '-results').data('contrailGrid')._dataView.getItem(rowIndex);
            rowActionCallbackConfig.renderProvision(dataItem);
        }),
        smGridConfig.getDeleteAction(function (rowIndex) {
            var dataItem = $('#' + prefixId + '-results').data('contrailGrid')._dataView.getItem(rowIndex);
            rowActionCallbackConfig.renderDelete(dataItem);
        }, true)
    ];

    var detailTemplateConfig = [
        [
            {
                title: smLabels.TITLE_DETAILS,
                keys: ['id', 'email']
            },
            {
                title: smLabels.TITLE_OPENSTACK,
                keys: ['parameters.openstack_mgmt_ip', 'parameters.keystone_tenant', 'parameters.keystone_username']
            },
            {
                title: smLabels.TITLE_CONTRAIL,
                keys: ['parameters.analytics_data_ttl', 'parameters.haproxy', 'parameters.multi_tenancy', 'parameters.use_certificates', 'parameters.external_bgp', 'parameters.encapsulation_priority', 'parameters.router_asn', 'parameters.database_dir']
            }
        ],
        [
            {
                title: smLabels.TITLE_STATUS,
                keys: ['ui_added_parameters.servers_status.total_servers', 'ui_added_parameters.servers_status.new_servers', 'ui_added_parameters.servers_status.configured_servers', 'ui_added_parameters.servers_status.inprovision_servers', 'ui_added_parameters.servers_status.provisioned_servers']
            },
            {
                title: smLabels.TITLE_SERVERS_CONFIG,
                keys: ['parameters.domain', 'parameters.gateway', 'parameters.subnet_mask', 'base_image_id', 'package_image_id']
            },
            {
                title: smLabels.TITLE_STORAGE,
                keys: ['parameters.uuid', 'parameters.storage_virsh_uuid', 'parameters.storage_fsid']
            },
        ]
    ];

    var headerActionConfig = [
        /*
        {
            "type": "link",
            linkElementId: 'btnDeleteClusters',
            disabledLink: true,
            "title": smLabels.TITLE_DEL_CLUSTERS,
            "iconClass": "icon-trash",
            "onClick": function () {
            }
        },
        */
        {
            "type": "link",
            "title": smLabels.TITLE_ADD_CLUSTER,
            "iconClass": "icon-plus",
            "onClick": function () {
                var clusterModel = new ClusterModel();

                clusterEditView.model = clusterModel;
                clusterEditView.renderAddCluster({"title": smLabels.TITLE_ADD_CLUSTER, callback: function () {
                    var dataView = $(gridElId).data("contrailGrid")._dataView;
                    dataView.refreshData();
                }});
            }
        }
    ];
    return ClusterView;
});
<|endoftext|>


<commit_before>'use strict';

module.exports = (XIBLE, EXPRESS_APP) => {
  const XibleRegistryWrapper = require('xible-registry-wrapper');
  const fsExtra = require('fs-extra');

  const registryUrl = XIBLE.Config.getValue('registry.url');
  if (!registryUrl) {
    throw new Error('"registry.url" not found in config');
  }

  const xibleRegistry = new XibleRegistryWrapper(registryUrl);

  // the tmp path for downloading this node
  const TMP_REGISTRY_DIR = '/tmp/xibleRegistryTmp';

  function cleanUp() {
    return new Promise((resolve, reject) => {
      // remove the tmp dir
      fsExtra.remove(TMP_REGISTRY_DIR, (err) => {
        if (err) {
          reject(err);
          return;
        }

        resolve();
      });
    });
  }

  /**
  * Installs a flow from a registry.
  * @param {String} altName The name to publish the flow with. Defaults to the flow name.
  * @returns {Promise}
  */
  xibleRegistry.Flow.prototype.install = function flowInstall(altName) {
    if (!XIBLE.Config.getValue('registry.flows.allowinstall')) {
      return Promise.reject('Your config does not allow to install flows from the registry');
    }

    let flowPath = XIBLE.Config.getValue('flows.path');
    if (!flowPath) {
      return Promise.reject('no "flows.path" configured');
    }
    flowPath = XIBLE.resolvePath(flowPath);

    if (altName) {
      if (!XIBLE.Flow.validateId(altName)) {
        return Promise.reject('flow _id/name cannot contain reserved/unsave characters');
      }
      this._id = altName;
      this.name = altName;
    }

    // remove fields specifically for the registry
    delete this.publishUserName;
    delete this.publishDate;

    return new Promise((resolve, reject) => {
      // write
      const flowDestPath = `${flowPath}/${this._id}.json`;
      fsExtra.writeFile(flowDestPath, JSON.stringify(this, null, '\t'), (err) => {
        if (err) {
          reject(err);
          return;
        }
        resolve();
      });
    });
  };

  /**
  * Installs a nodepack from a registry.
  * @returns {Promise}
  */
  xibleRegistry.NodePack.prototype.install = function nodePackInstall() {
    if (!XIBLE.Config.getValue('registry.nodepacks.allowinstall')) {
      return Promise.reject('Your config does not allow to install nodepacks from the registry');
    }

    let nodePath = XIBLE.Config.getValue('nodes.path');
    if (!nodePath) {
      return Promise.reject('no "nodes.path" configured');
    }
    nodePath = XIBLE.resolvePath(nodePath);

    // get the registrydata
    return this.getRegistryData().then((registryData) => {
      if (!registryData.name) {
        return Promise.reject(`No "name" field found in the registry data for node "${this.name}"`);
      }

      return this.getTarballUrl().then(tarballUrl => new Promise((resolve, reject) => {
        // check if the tarbalUrl is safe
        if (encodeURI(tarballUrl) !== tarballUrl) {
          reject(new Error('Package URL contains potentially unsafe characters'));
          return;
        }

        // clean the tmp dir where we will download the npm package
        fsExtra.emptyDir(TMP_REGISTRY_DIR, (err) => {
          if (err) {
            reject(err);
            return;
          }

          // create a package.json so npm knows where the root lies
          // remove the dependencies from the package so npm doesn't get confused
          const packageJson = require(`${__dirname}/../../package.json`);
          delete packageJson.dependencies;
          delete packageJson.devDependencies;

          // write off package.json
          fsExtra.writeFile(`${TMP_REGISTRY_DIR}/package.json`, JSON.stringify(packageJson), (createPackageJsonErr) => {
            if (createPackageJsonErr) {
              reject(createPackageJsonErr);
              return;
            }

            // fork npm to install the registry url
            const fork = require('child_process').spawn;
            const npm = fork('npm', ['install', tarballUrl], {
              cwd: TMP_REGISTRY_DIR,
              shell: true
            });

            npm.on('error', npmErr => reject(npmErr));

            npm.on('exit', (exitCode) => {
              if (exitCode) {
                reject(`exited with code: ${exitCode}`);
                return;
              }

              // specify the dir where this node will be installed
              const nodeDestDir = `${nodePath}/${this.name}`;

              // when success, resolve
              const onSuccess = () => XIBLE.Node
              .initFromPath(nodeDestDir)
              .then(cleanUp)
              .then(() => {
                // see if we can/need to reinit flows that are not runnable
                const flows = XIBLE.getFlows();
                for (const flowId in flows) {
                  if (!flows[flowId].runnable) {
                    flows[flowId].initJson(flows[flowId].json);
                  }
                }
              })
              .then(resolve)
              .catch((onSuccessErr) => {
                reject(onSuccessErr);
              });

              // remove existing node directory
              fsExtra.emptyDir(nodeDestDir, (removeExistingNodeErr) => {
                if (removeExistingNodeErr) {
                  reject(removeExistingNodeErr);
                  return;
                }

                // first move the node itself
                fsExtra.move(`${TMP_REGISTRY_DIR}/node_modules/${registryData.name}`, nodeDestDir, {
                  overwrite: true
                }, (moveNodeErr) => {
                  if (moveNodeErr) {
                    reject(moveNodeErr);
                    return;
                  }

                  // check if there's anything left in node_modules
                  fsExtra.readdir(`${TMP_REGISTRY_DIR}/node_modules`, (remainingNodeModulesErr, files) => {
                    if (remainingNodeModulesErr) {
                      reject(remainingNodeModulesErr);
                      return;
                    }

                    if (!files.length) {
                      onSuccess();
                      return;
                    }

                    // move the rest of the node_modules
                    fsExtra.move(`${TMP_REGISTRY_DIR}/node_modules`, `${nodeDestDir}/node_modules`, {
                      overwrite: true
                    }, (moveNodeModulesErr) => {
                      if (moveNodeModulesErr) {
                        reject(moveNodeModulesErr);
                        return;
                      }

                      onSuccess();
                    });
                  });
                });
              });
            });

            npm.stdout.on('data', (data) => {
              console.log(data.toString());
            });

            npm.stderr.on('data', (data) => {
              console.log(data.toString());
            });
          });
        });
      }));
    }).catch(err => cleanUp().then(() => Promise.reject(err)).catch(() => Promise.reject(err)));
  };

  if (EXPRESS_APP) {
    require('./routes.js')(xibleRegistry, XIBLE, EXPRESS_APP);
  }

  return {
    Registry: xibleRegistry
  };
};
<commit_msg>fixes #33<commit_after>'use strict';

module.exports = (XIBLE, EXPRESS_APP) => {
  const XibleRegistryWrapper = require('xible-registry-wrapper');
  const fsExtra = require('fs-extra');
  const os = require('os');

  const registryUrl = XIBLE.Config.getValue('registry.url');
  if (!registryUrl) {
    throw new Error('"registry.url" not found in config');
  }

  const xibleRegistry = new XibleRegistryWrapper(registryUrl);

  // the tmp path for downloading this node
  const TMP_REGISTRY_DIR = `${os.tmpdir() || '/tmp'}/xibleRegistryTmp`;

  function cleanUp() {
    return new Promise((resolve, reject) => {
      // remove the tmp dir
      fsExtra.remove(TMP_REGISTRY_DIR, (err) => {
        if (err) {
          reject(err);
          return;
        }

        resolve();
      });
    });
  }

  /**
  * Installs a flow from a registry.
  * @param {String} altName The name to publish the flow with. Defaults to the flow name.
  * @returns {Promise}
  */
  xibleRegistry.Flow.prototype.install = function flowInstall(altName) {
    if (!XIBLE.Config.getValue('registry.flows.allowinstall')) {
      return Promise.reject('Your config does not allow to install flows from the registry');
    }

    let flowPath = XIBLE.Config.getValue('flows.path');
    if (!flowPath) {
      return Promise.reject('no "flows.path" configured');
    }
    flowPath = XIBLE.resolvePath(flowPath);

    if (altName) {
      if (!XIBLE.Flow.validateId(altName)) {
        return Promise.reject('flow _id/name cannot contain reserved/unsave characters');
      }
      this._id = altName;
      this.name = altName;
    }

    // remove fields specifically for the registry
    delete this.publishUserName;
    delete this.publishDate;

    return new Promise((resolve, reject) => {
      // write
      const flowDestPath = `${flowPath}/${this._id}.json`;
      fsExtra.writeFile(flowDestPath, JSON.stringify(this, null, '\t'), (err) => {
        if (err) {
          reject(err);
          return;
        }
        resolve();
      });
    });
  };

  /**
  * Installs a nodepack from a registry.
  * @returns {Promise}
  */
  xibleRegistry.NodePack.prototype.install = function nodePackInstall() {
    if (!XIBLE.Config.getValue('registry.nodepacks.allowinstall')) {
      return Promise.reject('Your config does not allow to install nodepacks from the registry');
    }

    let nodePath = XIBLE.Config.getValue('nodes.path');
    if (!nodePath) {
      return Promise.reject('no "nodes.path" configured');
    }
    nodePath = XIBLE.resolvePath(nodePath);

    // get the registrydata
    return this.getRegistryData().then((registryData) => {
      if (!registryData.name) {
        return Promise.reject(`No "name" field found in the registry data for node "${this.name}"`);
      }

      return this.getTarballUrl().then(tarballUrl => new Promise((resolve, reject) => {
        // check if the tarbalUrl is safe
        if (encodeURI(tarballUrl) !== tarballUrl) {
          reject(new Error('Package URL contains potentially unsafe characters'));
          return;
        }

        // clean the tmp dir where we will download the npm package
        fsExtra.emptyDir(TMP_REGISTRY_DIR, (err) => {
          if (err) {
            reject(err);
            return;
          }

          // create a package.json so npm knows where the root lies
          // remove the dependencies from the package so npm doesn't get confused
          const packageJson = require(`${__dirname}/../../package.json`);
          delete packageJson.dependencies;
          delete packageJson.devDependencies;

          // write off package.json
          fsExtra.writeFile(`${TMP_REGISTRY_DIR}/package.json`, JSON.stringify(packageJson), (createPackageJsonErr) => {
            if (createPackageJsonErr) {
              reject(createPackageJsonErr);
              return;
            }

            // fork npm to install the registry url
            const fork = require('child_process').spawn;
            const npm = fork('npm', ['install', tarballUrl], {
              cwd: TMP_REGISTRY_DIR,
              shell: true
            });

            npm.on('error', npmErr => reject(npmErr));

            npm.on('exit', (exitCode) => {
              if (exitCode) {
                reject(`exited with code: ${exitCode}`);
                return;
              }

              // specify the dir where this node will be installed
              const nodeDestDir = `${nodePath}/${this.name}`;

              // when success, resolve
              const onSuccess = () => XIBLE.Node
              .initFromPath(nodeDestDir)
              .then(cleanUp)
              .then(() => {
                // see if we can/need to reinit flows that are not runnable
                const flows = XIBLE.getFlows();
                for (const flowId in flows) {
                  if (!flows[flowId].runnable) {
                    flows[flowId].initJson(flows[flowId].json);
                  }
                }
              })
              .then(resolve)
              .catch((onSuccessErr) => {
                reject(onSuccessErr);
              });

              // remove existing node directory
              fsExtra.emptyDir(nodeDestDir, (removeExistingNodeErr) => {
                if (removeExistingNodeErr) {
                  reject(removeExistingNodeErr);
                  return;
                }

                // first move the node itself
                fsExtra.move(`${TMP_REGISTRY_DIR}/node_modules/${registryData.name}`, nodeDestDir, {
                  overwrite: true
                }, (moveNodeErr) => {
                  if (moveNodeErr) {
                    reject(moveNodeErr);
                    return;
                  }

                  // check if there's anything left in node_modules
                  fsExtra.readdir(`${TMP_REGISTRY_DIR}/node_modules`, (remainingNodeModulesErr, files) => {
                    if (remainingNodeModulesErr) {
                      reject(remainingNodeModulesErr);
                      return;
                    }

                    if (!files.length) {
                      onSuccess();
                      return;
                    }

                    // move the rest of the node_modules
                    fsExtra.move(`${TMP_REGISTRY_DIR}/node_modules`, `${nodeDestDir}/node_modules`, {
                      overwrite: true
                    }, (moveNodeModulesErr) => {
                      if (moveNodeModulesErr) {
                        reject(moveNodeModulesErr);
                        return;
                      }

                      onSuccess();
                    });
                  });
                });
              });
            });

            npm.stdout.on('data', (data) => {
              console.log(data.toString());
            });

            npm.stderr.on('data', (data) => {
              console.log(data.toString());
            });
          });
        });
      }));
    }).catch(err => cleanUp().then(() => Promise.reject(err)).catch(() => Promise.reject(err)));
  };

  if (EXPRESS_APP) {
    require('./routes.js')(xibleRegistry, XIBLE, EXPRESS_APP);
  }

  return {
    Registry: xibleRegistry
  };
};
<|endoftext|>


<commit_before>var generators = require('./answer-generators'),
	utils = require('./utils');

// even?
// if rightAnswer.length >=2
// .. then Inverted number
// .. else random number
// Multiple -1
// Right answer
// Multiple +1
function answerSelector(problem) {
	var currentAnswersArray = [problem.result];

	if (problem.result.toString().length > 1) {
		generators.invertRightAnswer(problem, currentAnswersArray);
	} else {
		generators.findRandomNumber1(problem, currentAnswersArray);
	}

	generators.add1ToYFactor(problem, currentAnswersArray);
	generators.substract1ToYFactor(problem, currentAnswersArray);

	// Last phase
	while(currentAnswersArray.length < 4) {
		generators.findRandomNumber2(problem, currentAnswersArray);
	}

	return utils.shuffle(currentAnswersArray);
}

module.exports = answerSelector;<commit_msg>Added a conditional into the 'answerSelector' to decide if choose add1ToFactor or substract1ToFactor<commit_after>var generators = require('./answer-generators'),
	utils = require('./utils');

// even?
// if rightAnswer.length >=2
// .. then Inverted number
// .. else random number
// Multiple -1
// Right answer
// Multiple +1
function answerSelector(problem) {
	var currentAnswersArray = [problem.result];

	if (problem.result.toString().length > 1) {
		generators.invertRightAnswer(problem, currentAnswersArray);
	} else {
		generators.findRandomNumber1(problem, currentAnswersArray);
	}

	if (Math.random() > 0.5) {
		generators.add1ToYFactor(problem, currentAnswersArray);
	} else {
		generators.substract1ToYFactor(problem, currentAnswersArray);
	}

	// Last phase
	while(currentAnswersArray.length < 4) {
		generators.findRandomNumber2(problem, currentAnswersArray);
	}

	return utils.shuffle(currentAnswersArray);
}

module.exports = answerSelector;
<|endoftext|>


<commit_before>/*jslint browser: true, nomen: true, unparam: true */

(function (flow, $, _, ace, Backbone, Blob, d3, FileReader, girder, tangelo, URL) {
    "use strict";

   // The view for selecting, running, and editing analyses
    flow.AnalysisManagementView = Backbone.View.extend({
        formats: [
            'table:rows',
            'table:r.dataframe',
            'table:csv',
            'table:tsv',
            'table:vtktable.serialized',
            'tree:nested',
            'tree:newick',
            'tree:r.apetree',
            'tree:vtktree.serialized',
            'string:text',
            'number:number',
            'image:png.base64',
            'r:object'
        ],

        events: {
            'click #show-script': function () {
                var hide = d3.select("#show-script").classed("active");
                flow.setDisplay(hide ? "vis" : "editor");
                this.editor.resize();
                d3.select("#show-script-icon").classed("glyphicon-eye-open", hide);
                d3.select("#show-script-icon").classed("glyphicon-eye-close", !hide);
                d3.select("#show-script-text").text(hide ? "Show script" : "Hide script");
            },

            'click #edit': function () {
                var edit = d3.select("#edit").classed("active");
                this.editor.setReadOnly(edit);
                this.editor.renderer.$cursorLayer.element.style.opacity = edit ? 0 : 1;
                d3.selectAll(".edit-controls").classed("hidden", edit);
            },

            'change #mode': function () {
                if (this.analysis) {
                    this.analysis.get('meta').analysis.mode = $("#mode").val();
                    this.editor.getSession().setMode("ace/mode/" + this.analysis.get('meta').analysis.mode);
                }
            },

            'click #save': function () {
                var info;
                if (this.analysis) {
                    info = this.analysis.get('meta').analysis;
                    info.name = this.$(".analysis-edit-name").val();
                    info.script = this.editor.getValue();
                    info.inputs = this.inputVariables.toJSON();
                    info.outputs = this.outputVariables.toJSON();
                    d3.json(girder.apiRoot + '/item/' + this.analysis.id + '?name=' + encodeURIComponent(info.name)).send('put', _.bind(function (error, result) {
                        d3.json(girder.apiRoot + '/item/' + this.analysis.id + '/metadata').send('put', JSON.stringify(this.analysis.get('meta')), _.bind(function () {
                            // Trigger recreating the analysis UI
                            $("#analysis").change();
                            // Trigger updating this analysis views
                            this.analysis.set('name', info.name);
                        }, this));
                    }, this));
                }
            },

            'click .delete-analysis': function () {
                $('#confirm-delete').modal('show');
            },

            'change #analysis': function () {
                this.changeAnalysis(this.analyses.get($("#analysis").val()));
            },

            'click #setup': function () {
                if (this.analysis) {
                    this.analysisSetupView.model = this.analysis;
                    this.analysisSetupView.render();
                }
            },

            'click .add-input-variable': function () {
                var model = new Backbone.Model();
                this.inputVariableEditView.model = model;
                this.inputVariables.add(model);
                this.inputVariableEditView.render();
            },

            'click .add-output-variable': function () {
                var model = new Backbone.Model();
                this.outputVariableEditView.model = model;
                this.outputVariables.add(model);
                this.outputVariableEditView.render();
            },

            'click #analysis-new': function () {
                var analysis = {
                    name: $("#analysis-name").val(),
                    inputs: [],
                    outputs: [],
                    mode: "python",
                    script: ""
                };
                this.createAnalysis(analysis);
            },

            'click #analysis-download': function () {
                var blob = new Blob([JSON.stringify(this.analysis.get('meta').analysis, null, "    ")]),
                    filename = this.analysis.get('meta').analysis.name + '.json',
                    anchor = $('');
                anchor[0].click();
            },

            'change #analysis-files': function () {
                var files = $('#analysis-files')[0].files;
                _.each(files, function (file) {
                    this.upload(file);
                }, this);
            },

            'click #analysis-upload': function () {
                $('#analysis-files').click();
            }

        },

        initialize: function (settings) {
            this.analysis = null;
            this.datasets = settings.datasets;
            this.analysisSetupView = new flow.AnalysisSetupView({
                el: $('#analysis-setup-dialog'),
                model: this.analysis,
                datasets: this.datasets
            });

            this.editor = ace.edit("editor");
            this.editor.setTheme("ace/theme/chrome");
            this.editor.setHighlightActiveLine(false);
            this.editor.setHighlightGutterLine(false);
            this.editor.setShowPrintMargin(false);
            this.editor.setReadOnly(true);
            this.editor.setFontSize(14);
            this.editor.renderer.$cursorLayer.element.style.opacity = 0;

            this.analyses = settings.analyses;
            this.analysesView = new flow.ItemsView({el: this.$('#analysis'), itemView: flow.ItemOptionView, collection: this.analyses});
            this.analysesView.render();

            this.inputVariables = new Backbone.Collection();
            this.outputVariables = new Backbone.Collection();
            this.inputVariableEditView = new flow.VariableEditView({el: $('#input-variable-edit-dialog'), input: true});
            this.inputVariablesView = new flow.VariablesView({
                el: this.$('.input-variables'),
                itemView: flow.VariableView,
                itemOptions: {editView: this.inputVariableEditView, collection: this.inputVariables},
                collection: this.inputVariables
            });
            this.outputVariableEditView = new flow.VariableEditView({el: $('#output-variable-edit-dialog'), input: false});
            this.outputVariablesView = new flow.VariablesView({
                el: this.$('.output-variables'),
                itemView: flow.VariableView,
                itemOptions: {editView: this.outputVariableEditView, collection: this.outputVariables},
                collection: this.outputVariables
            });

            // Once the first analysis is added, make it the active analysis
            this.analyses.on('add', _.bind(function (item) {
                if (!this.analysis) {
                    this.changeAnalysis(item);
                }
            }, this));

            flow.events.on('flow:change-save-location', this.saveLocationChange, this);

            $('.really-delete-analysis').click(_.bind(function () {
                if (this.analysis) {
                    d3.json(girder.apiRoot + '/item/' + this.analysis.id).send('delete', _.bind(function (error, result) {
                        this.analyses.remove(this.analysis);
                        // Trigger recreating the analysis UI
                        $("#analysis").change();
                        $('#confirm-delete').modal('hide');
                    }, this));
                }
            }, this));
        },

        changeAnalysis: function (analysis) {
            var checkCanEdit = function () {
                if (!this.analysis.get('collection') || this.analysis.get('collection').get('_accessLevel') > 0) {
                    d3.select("#edit").classed("hidden", false);
                    d3.selectAll(".edit-controls").classed("hidden", !d3.select("#edit").classed("active"));
                }
            };

            if (this.analysis) {
                this.analysis.off('change:collection', null, this);
            }

            this.analysis = analysis;
            if (this.analysis) {
                this.editor.setValue(this.analysis.get('meta').analysis.script);
                this.editor.clearSelection();
                this.editor.getSession().setMode("ace/mode/" + this.analysis.get('meta').analysis.mode);
                this.inputVariables.set(this.analysis.get('meta').analysis.inputs);
                this.outputVariables.set(this.analysis.get('meta').analysis.outputs);
                this.$('.analysis-edit-name').val(this.analysis.get('meta').analysis.name);
                this.$('#mode').val(this.analysis.get('meta').analysis.mode);

                this.analysis.on('change:collection', checkCanEdit, this);
                _.bind(checkCanEdit, this)();
            } else {
                this.editor.setValue('');
                this.inputVariables.set([]);
                this.outputVariables.set([]);
            }
        },

        upload: function (file) {
            var reader = new FileReader();

            reader.onload = _.bind(function (e) {
                this.createAnalysis(JSON.parse(e.target.result));
            }, this);

            reader.readAsText(file);
        },

        createAnalysis: function (analysis) {
            d3.json(girder.apiRoot + '/item/?name=' + encodeURIComponent(analysis.name) + '&folderId=' + flow.saveLocation.get('analysisFolder')).post(_.bind(function (error, result) {
                var analysisUri = girder.apiRoot + '/item/' + result._id;
                d3.json(analysisUri + '/metadata').send('put', JSON.stringify({analysis: analysis}), _.bind(function (error, result) {
                    var model = new Backbone.Model(result);
                    model.id = model.get('_id');
                    this.analyses.add(model);
                    $("#analysis").val(model.cid);
                    $("#analysis").change();
                    $("#analysis-name").val("");
                }, this));
            }, this));
        },

        saveLocationChange: function () {
            this.$('#new-analysis-form').toggleClass('hidden', flow.saveLocation === null);
        }

    });

}(window.flow, window.$, window._, window.ace, window.Backbone, window.Blob, window.d3, window.FileReader, window.girder, window.tangelo, window.URL));
<commit_msg>Download analysis working in Firefox - fixes #66<commit_after>/*jslint browser: true, nomen: true, unparam: true */

(function (flow, $, _, ace, Backbone, Blob, d3, FileReader, girder, tangelo, URL) {
    "use strict";

   // The view for selecting, running, and editing analyses
    flow.AnalysisManagementView = Backbone.View.extend({
        formats: [
            'table:rows',
            'table:r.dataframe',
            'table:csv',
            'table:tsv',
            'table:vtktable.serialized',
            'tree:nested',
            'tree:newick',
            'tree:r.apetree',
            'tree:vtktree.serialized',
            'string:text',
            'number:number',
            'image:png.base64',
            'r:object'
        ],

        events: {
            'click #show-script': function () {
                var hide = d3.select("#show-script").classed("active");
                flow.setDisplay(hide ? "vis" : "editor");
                this.editor.resize();
                d3.select("#show-script-icon").classed("glyphicon-eye-open", hide);
                d3.select("#show-script-icon").classed("glyphicon-eye-close", !hide);
                d3.select("#show-script-text").text(hide ? "Show script" : "Hide script");
            },

            'click #edit': function () {
                var edit = d3.select("#edit").classed("active");
                this.editor.setReadOnly(edit);
                this.editor.renderer.$cursorLayer.element.style.opacity = edit ? 0 : 1;
                d3.selectAll(".edit-controls").classed("hidden", edit);
            },

            'change #mode': function () {
                if (this.analysis) {
                    this.analysis.get('meta').analysis.mode = $("#mode").val();
                    this.editor.getSession().setMode("ace/mode/" + this.analysis.get('meta').analysis.mode);
                }
            },

            'click #save': function () {
                var info;
                if (this.analysis) {
                    info = this.analysis.get('meta').analysis;
                    info.name = this.$(".analysis-edit-name").val();
                    info.script = this.editor.getValue();
                    info.inputs = this.inputVariables.toJSON();
                    info.outputs = this.outputVariables.toJSON();
                    d3.json(girder.apiRoot + '/item/' + this.analysis.id + '?name=' + encodeURIComponent(info.name)).send('put', _.bind(function (error, result) {
                        d3.json(girder.apiRoot + '/item/' + this.analysis.id + '/metadata').send('put', JSON.stringify(this.analysis.get('meta')), _.bind(function () {
                            // Trigger recreating the analysis UI
                            $("#analysis").change();
                            // Trigger updating this analysis views
                            this.analysis.set('name', info.name);
                        }, this));
                    }, this));
                }
            },

            'click .delete-analysis': function () {
                $('#confirm-delete').modal('show');
            },

            'change #analysis': function () {
                this.changeAnalysis(this.analyses.get($("#analysis").val()));
            },

            'click #setup': function () {
                if (this.analysis) {
                    this.analysisSetupView.model = this.analysis;
                    this.analysisSetupView.render();
                }
            },

            'click .add-input-variable': function () {
                var model = new Backbone.Model();
                this.inputVariableEditView.model = model;
                this.inputVariables.add(model);
                this.inputVariableEditView.render();
            },

            'click .add-output-variable': function () {
                var model = new Backbone.Model();
                this.outputVariableEditView.model = model;
                this.outputVariables.add(model);
                this.outputVariableEditView.render();
            },

            'click #analysis-new': function () {
                var analysis = {
                    name: $("#analysis-name").val(),
                    inputs: [],
                    outputs: [],
                    mode: "python",
                    script: ""
                };
                this.createAnalysis(analysis);
            },

            'click #analysis-download': function () {
                var blob = new Blob([JSON.stringify(this.analysis.get('meta').analysis, null, "    ")]),
                    filename = this.analysis.get('meta').analysis.name + '.json',
                    anchor = $('');
                $("body").append(anchor);
                anchor[0].click();
            },

            'change #analysis-files': function () {
                var files = $('#analysis-files')[0].files;
                _.each(files, function (file) {
                    this.upload(file);
                }, this);
            },

            'click #analysis-upload': function () {
                $('#analysis-files').click();
            }

        },

        initialize: function (settings) {
            this.analysis = null;
            this.datasets = settings.datasets;
            this.analysisSetupView = new flow.AnalysisSetupView({
                el: $('#analysis-setup-dialog'),
                model: this.analysis,
                datasets: this.datasets
            });

            this.editor = ace.edit("editor");
            this.editor.setTheme("ace/theme/chrome");
            this.editor.setHighlightActiveLine(false);
            this.editor.setHighlightGutterLine(false);
            this.editor.setShowPrintMargin(false);
            this.editor.setReadOnly(true);
            this.editor.setFontSize(14);
            this.editor.renderer.$cursorLayer.element.style.opacity = 0;

            this.analyses = settings.analyses;
            this.analysesView = new flow.ItemsView({el: this.$('#analysis'), itemView: flow.ItemOptionView, collection: this.analyses});
            this.analysesView.render();

            this.inputVariables = new Backbone.Collection();
            this.outputVariables = new Backbone.Collection();
            this.inputVariableEditView = new flow.VariableEditView({el: $('#input-variable-edit-dialog'), input: true});
            this.inputVariablesView = new flow.VariablesView({
                el: this.$('.input-variables'),
                itemView: flow.VariableView,
                itemOptions: {editView: this.inputVariableEditView, collection: this.inputVariables},
                collection: this.inputVariables
            });
            this.outputVariableEditView = new flow.VariableEditView({el: $('#output-variable-edit-dialog'), input: false});
            this.outputVariablesView = new flow.VariablesView({
                el: this.$('.output-variables'),
                itemView: flow.VariableView,
                itemOptions: {editView: this.outputVariableEditView, collection: this.outputVariables},
                collection: this.outputVariables
            });

            // Once the first analysis is added, make it the active analysis
            this.analyses.on('add', _.bind(function (item) {
                if (!this.analysis) {
                    this.changeAnalysis(item);
                }
            }, this));

            flow.events.on('flow:change-save-location', this.saveLocationChange, this);

            $('.really-delete-analysis').click(_.bind(function () {
                if (this.analysis) {
                    d3.json(girder.apiRoot + '/item/' + this.analysis.id).send('delete', _.bind(function (error, result) {
                        this.analyses.remove(this.analysis);
                        // Trigger recreating the analysis UI
                        $("#analysis").change();
                        $('#confirm-delete').modal('hide');
                    }, this));
                }
            }, this));
        },

        changeAnalysis: function (analysis) {
            var checkCanEdit = function () {
                if (!this.analysis.get('collection') || this.analysis.get('collection').get('_accessLevel') > 0) {
                    d3.select("#edit").classed("hidden", false);
                    d3.selectAll(".edit-controls").classed("hidden", !d3.select("#edit").classed("active"));
                }
            };

            if (this.analysis) {
                this.analysis.off('change:collection', null, this);
            }

            this.analysis = analysis;
            if (this.analysis) {
                this.editor.setValue(this.analysis.get('meta').analysis.script);
                this.editor.clearSelection();
                this.editor.getSession().setMode("ace/mode/" + this.analysis.get('meta').analysis.mode);
                this.inputVariables.set(this.analysis.get('meta').analysis.inputs);
                this.outputVariables.set(this.analysis.get('meta').analysis.outputs);
                this.$('.analysis-edit-name').val(this.analysis.get('meta').analysis.name);
                this.$('#mode').val(this.analysis.get('meta').analysis.mode);

                this.analysis.on('change:collection', checkCanEdit, this);
                _.bind(checkCanEdit, this)();
            } else {
                this.editor.setValue('');
                this.inputVariables.set([]);
                this.outputVariables.set([]);
            }
        },

        upload: function (file) {
            var reader = new FileReader();

            reader.onload = _.bind(function (e) {
                this.createAnalysis(JSON.parse(e.target.result));
            }, this);

            reader.readAsText(file);
        },

        createAnalysis: function (analysis) {
            d3.json(girder.apiRoot + '/item/?name=' + encodeURIComponent(analysis.name) + '&folderId=' + flow.saveLocation.get('analysisFolder')).post(_.bind(function (error, result) {
                var analysisUri = girder.apiRoot + '/item/' + result._id;
                d3.json(analysisUri + '/metadata').send('put', JSON.stringify({analysis: analysis}), _.bind(function (error, result) {
                    var model = new Backbone.Model(result);
                    model.id = model.get('_id');
                    this.analyses.add(model);
                    $("#analysis").val(model.cid);
                    $("#analysis").change();
                    $("#analysis-name").val("");
                }, this));
            }, this));
        },

        saveLocationChange: function () {
            this.$('#new-analysis-form').toggleClass('hidden', flow.saveLocation === null);
        }

    });

}(window.flow, window.$, window._, window.ace, window.Backbone, window.Blob, window.d3, window.FileReader, window.girder, window.tangelo, window.URL));
<|endoftext|>


<commit_before>//Setup module to run Behave tests
require('behave').andSetup(this);

describe('Index screen', function() {

	var index = null;
	it('creates a index controller', function() {
		index = Alloy.createController('index');
		expect(index).notToBe(null);
	});

	it('creates a scrollableview for you and me and the rest of the world', function() {
		expect(index.getView("scrollableViewID")).notToBe(undefined);
	});

	// go nuts! :-)

}); <commit_msg>check<commit_after>//Setup module to run Behave tests
require('behave').andSetup(this);

describe('Index screen', function() {

	var index = null;
	it('creates a index controller', function() {
		index = Alloy.createController('index');
		expect(index).notToBe(null);
	});

	it('creates a scrollableview for you and me and the rest of the world', function() {
		expect(index.getView("scrollableViewID")).notToBe(null);
	});

	// go nuts! :-)

}); <|endoftext|>