<commit_before>// jscs:disable

app.controller('PrinterCtrl', PrinterCtrl);

PrinterCtrl.$inject = ['$scope', '$state', '$stateParams', '$controller', 'printer'];

function PrinterCtrl($scope, $state, $stateParams, $controller, printer) {
	$scope.recentJobs = [];
	$scope.commands = [];
	$scope.printer = [];
	$scope.command = {name: ''};
	$scope.currentJobAlert = [];

	$scope.printerModal = {};
	$scope.printerModal.form = {};
	$scope.printerModal.printer = {};
	$scope.printerModalVisible = false;

	$scope.cancelJobModal = {};
	$scope.cancelJobModalVisible = false;

	$scope.issuedCommandsConfig = {
		itemsPerPage: 6,
		maxPages: 5,
		fillLastPage: "no"
	};

	/**
	 * Update printer profile
	 */
	$scope.updatePrinter = function(attributes) {
		printer.update($stateParams.printerId, attributes)
			.success(function(response) {
				$scope.printerModal.addAlert('success', 'The printer has been updated successfully.');
				$scope.getPrinter();
				$scope.printerModal.form.$setPristine();
				$scope.printerModal.printer = {};
			})
			.error(function(response) {
				$scope.printerModal.addAlert('danger', 'Unable to update printer. Please double check that the specified name is not already in use by another printer.');
				console.log(response);
			});
	};

	/**
	 * Modal visibility toggling
	 */
	$scope.showPrinterModal = function() {
		$scope.printerModalVisible = true;
	};

	$scope.hidePrinterModal = function() {
		$scope.printerModalVisible = false;
		$scope.printerModal.alerts = [];
	};

	$scope.showCancelJobModal = function() {
		$scope.cancelJobModalVisible = true;
	};

	$scope.hideCancelJobModal = function() {
		$scope.cancelJobModalVisible = false;
	};

	/**
	 * Retrieve the current job associated with this printer
	 */
	$scope.getCurrentJob = function() {
		printer.getCurrentJob($stateParams.printerId)
			.success(function(response) {
				$scope.currentJob = response;
			})
			.error(function(response) {
				console.log('Unable to retrieve current job.');
				console.log(response);
			});
	};

	/**
	 * Retrieve the commands issued to this printer
	 */
	$scope.getCommands = function() {
		printer.getCommands($stateParams.printerId)
			.success(function(response) {
				$scope.commands = response;
			})
			.error(function(response) {
				console.log('Unable to retrieve list of commands.');
				console.log(response);
			});
	};

	/**
	 * Retrieve list of recent jobs associated with this printer
	 */
	$scope.getRecentJobs = function() {
		printer.getRecentJobs($stateParams.printerId)
			.success(function(response) {
				$scope.recentJobs = response;
			})
			.error(function(response) {
				console.log('Unable to retrieve list of recent jobs.');
				console.log(response);
			});
	};

	/**
	 * Retrieve list of all completed jobs associated with this printer
	 */
	$scope.getPrinter = function() {
		printer.getPrinter($stateParams.printerId)
			.success(function(response) {
				$scope.printer = response;
			})
			.error(function(response) {
				console.log('Unable to retrieve printer.');
				console.log(response);
			});
	};

	/**
	 * Issue a printer command.
	 */
	$scope.issueCommand = function() {
		if($scope.command.name === '') { return; }

		printer.issueCommand($stateParams.printerId, $scope.command.name)
			.success(function(response) {
				$scope.addAlert('info', 'The ' + $scope.command.name + ' command has been sent to the printer. Please wait a minute for the command be executed and the current job status updated.');
			})
			.error(function(response) {
				$scope.addAlert('danger', 'Unable to issue command. Please try again.');
				console.log(response);
			});
	};

	/**
	 * Refresh data.
	 */
	$scope.refresh = function() {
		$scope.getCurrentJob();
		$scope.getCommands();
		$scope.getPrinter();
		$scope.getRecentJobs();
	};

	$controller('AlertCtrl', { $scope: $scope });
	$controller('AlertCtrl', { $scope: $scope.printerModal});

	$scope.refresh();

	this.interval = setInterval(function(){
		$scope.refresh();
	}, 2000);

	$scope.$watch('command.name', $scope.issueCommand);
}
<commit_msg>Cancel timer after page change<commit_after>// jscs:disable

app.controller('PrinterCtrl', PrinterCtrl);

PrinterCtrl.$inject = ['$scope', '$state', '$stateParams', '$controller', '$interval', 'printer'];

function PrinterCtrl($scope, $state, $stateParams, $controller, $interval, printer) {
	$scope.recentJobs = [];
	$scope.commands = [];
	$scope.printer = [];
	$scope.command = {name: ''};
	$scope.currentJobAlert = [];

	$scope.printerModal = {};
	$scope.printerModal.form = {};
	$scope.printerModal.printer = {};
	$scope.printerModalVisible = false;

	$scope.cancelJobModal = {};
	$scope.cancelJobModalVisible = false;

	$scope.issuedCommandsConfig = {
		itemsPerPage: 6,
		maxPages: 5,
		fillLastPage: "no"
	};

	/**
	 * Update printer profile
	 */
	$scope.updatePrinter = function(attributes) {
		printer.update($stateParams.printerId, attributes)
			.success(function(response) {
				$scope.printerModal.addAlert('success', 'The printer has been updated successfully.');
				$scope.getPrinter();
				$scope.printerModal.form.$setPristine();
				$scope.printerModal.printer = {};
			})
			.error(function(response) {
				$scope.printerModal.addAlert('danger', 'Unable to update printer. Please double check that the specified name is not already in use by another printer.');
				console.log(response);
			});
	};

	/**
	 * Modal visibility toggling
	 */
	$scope.showPrinterModal = function() {
		$scope.printerModalVisible = true;
	};

	$scope.hidePrinterModal = function() {
		$scope.printerModalVisible = false;
		$scope.printerModal.alerts = [];
	};

	$scope.showCancelJobModal = function() {
		$scope.cancelJobModalVisible = true;
	};

	$scope.hideCancelJobModal = function() {
		$scope.cancelJobModalVisible = false;
	};

	/**
	 * Retrieve the current job associated with this printer
	 */
	$scope.getCurrentJob = function() {
		printer.getCurrentJob($stateParams.printerId)
			.success(function(response) {
				$scope.currentJob = response;
			})
			.error(function(response) {
				console.log('Unable to retrieve current job.');
				console.log(response);
			});
	};

	/**
	 * Retrieve the commands issued to this printer
	 */
	$scope.getCommands = function() {
		printer.getCommands($stateParams.printerId)
			.success(function(response) {
				$scope.commands = response;
			})
			.error(function(response) {
				console.log('Unable to retrieve list of commands.');
				console.log(response);
			});
	};

	/**
	 * Retrieve list of recent jobs associated with this printer
	 */
	$scope.getRecentJobs = function() {
		printer.getRecentJobs($stateParams.printerId)
			.success(function(response) {
				$scope.recentJobs = response;
			})
			.error(function(response) {
				console.log('Unable to retrieve list of recent jobs.');
				console.log(response);
			});
	};

	/**
	 * Retrieve list of all completed jobs associated with this printer
	 */
	$scope.getPrinter = function() {
		printer.getPrinter($stateParams.printerId)
			.success(function(response) {
				$scope.printer = response;
			})
			.error(function(response) {
				console.log('Unable to retrieve printer.');
				console.log(response);
			});
	};

	/**
	 * Issue a printer command.
	 */
	$scope.issueCommand = function() {
		if($scope.command.name === '') { return; }

		printer.issueCommand($stateParams.printerId, $scope.command.name)
			.success(function(response) {
				$scope.addAlert('info', 'The ' + $scope.command.name + ' command has been sent to the printer. Please wait a minute for the command be executed and the current job status updated.');
			})
			.error(function(response) {
				$scope.addAlert('danger', 'Unable to issue command. Please try again.');
				console.log(response);
			});
	};

	/**
	 * Refresh data.
	 */
	$scope.refresh = function() {
		$scope.getCurrentJob();
		$scope.getCommands();
		//$scope.getPrinter();
		$scope.getRecentJobs();
	};

	$controller('AlertCtrl', { $scope: $scope });
	$controller('AlertCtrl', { $scope: $scope.printerModal});

	var timerPromise;
	$scope.timer = function() {
		timerPromise = $interval($scope.refresh, 2000);
	};

	$scope.timer();

	$scope.$watch('command.name', $scope.issueCommand);

	$scope.$on('$destroy',function(){
	    if(timerPromise) {
	        $interval.cancel(timerPromise);
	    }
	});
}
<|endoftext|>


<commit_before>// jscs:disable

app.controller('ViewHubCtrl', ViewHubCtrl);
ViewHubCtrl.$inject = ['$scope', '$state', '$stateParams', '$timeout', '$q', '$controller', 'hub', 'printer', 'sensor'];

function ViewHubCtrl($scope, $state, $stateParams, $timeout, $q, $controller, hub, printer, sensor) {
  var hubId = Number($stateParams.hubId);

  var hubPromise = hub.getHub(hubId);
  var printersPromise = hub.getPrinters(hubId);

  $scope.sensors = {};
  $scope.updateSensorModal = {};
  $scope.updateSensorModal.form = {};
  $scope.updateSensorModal.attributes = {};
  $scope.updateSensorModalVisible = false;
  $scope.showDeleteModal = false; // Set to true to show the delete confirmation modal
  $scope.printersCurrentPage = 1;
  $scope.printersItemsPerPage = 2;

  $controller('AlertCtrl', { $scope: $scope });
  $controller('AlertCtrl', { $scope: $scope.updateSensorModal});

  /*********************************************************
   *
   * FUNCTIONS
   *
   * /

  /**
   * Modal visibility toggling
   */
  $scope.showSensorModal = function() {
    $scope.updateSensorModalVisible = true;
  };

  $scope.hideSensorModal = function() {
    $scope.updateSensorModalVisible = false;
    $scope.updateSensorModal.alerts = [];
  };

  /**
   * Update a sensor
   */
  $scope.updateSensor = function(sensorId, attributes) {
    hub.updateSensor(sensorId, attributes)
      .success(function(response) {
        $scope.updateSensorModal.addAlert('success', 'The sensor has been updated successfully.');
        angular.forEach(attributes, function(attribute, key){
            if(attribute) {
              $scope.updateSensorModal.sensor[key] = attribute;
            }
        });
        $scope.updateSensorModal.attributes = {};
        $scope.updateSensorModal.form.$setPristine();
        $scope.getSensors();
      })
      .error(function(response) {
          $scope.updateSensorModal.addAlert('danger', 'Unable to update sensor. Please double check that the specified name is not already in use by another sensor.');
          console.log(response);
      });
  };

  /**
   * ToHubsPage
   * Waits 500 milliseconds for the animation to fade
   * Sets the state to the main hubs page
   * @param {boolean} reload
   *  if reload = true the ListHubs controller will refresh
   * @returns {undefined}
   */
  $scope.toHubsPage = function(reload) {
    $timeout(function() {
      $state.go('dashboard.listHubs',{},{reload: reload});
    },500);
  };

  /**
   * UpdateHub
   * Updates a hub in the DB with the hub object gathered from the form
   * Performs multiple checks on the form, check if there are no warnings
   *  checks if the form is empty or not
   *  Checks if the user is an admin, incase they edit some htlm and get the form to show
   * If all checks clear, then it updates the hub, if the entity is invalid it will add the alert to tell the user
   *
   * @param _hubId
   * @param _hub
   * @returns {undefined}
   */
  $scope.updateHub = function(_hubId, _hub) {
    if (!$scope.updateHubForm.$valid) {
      $scope.addAlert('danger', 'Please correct the errors below and try submitting the form again.');
      return;
    }

    // Check whether form has not been filled out
    if ($scope.updateHubForm.$pristine) {
      $scope.addAlert('warning', 'Please fill out the form below before saving.');
      return;
    }

    // Remove empty fields from profile to prevent errors
    Object.keys($scope.hub).forEach(function(key) {
      if ($scope.hub[key] === '') {
        delete $scope.hub[key];
      }
    });

    if ($scope.user.isAdmin()) {
      updateHubPromise = hub.updateHub(_hubId, _hub);

      updateHubPromise.then(function(data) {
        if (typeof (data) === 'object') {
          $scope.resetForm();
          $scope.addAlert('success', 'Hub updated successfully!');
          $scope.hub = data;
        } else {
          $scope.addAlert('danger', 'Sorry but this hub could not be modified.  Some values are unprocessable.');
        }
      });
      return;
    }
  };

  /**
   * ResetForm
   * clears the $scope.hub and sets the form to pristine(cleared)
   *
   * @returns {undefined}
   */
  $scope.resetForm = function() {
    $scope.hubDetails = {};
    $scope.updateHubForm.$setPristine();
  };

  /**
   * DeleteHub
   * calls deleteHub from the service
   * deleteHub in the service removes the hub by id
   * @param _id
   * @returns {}
   */
  $scope.deleteHub = function(_id) {
    console.log('Firing?');
    $scope.showDeleteModal = false;
    if ($scope.user._user.admin === true) {
      // Hub.deleteHub(_id);
      this.toHubsPage(true);
      console.log($scope.showDeleteModal);
    } else {
      console.log('Permission Denied');
    }
  };

  /**
   * DeleteModal
   * Called by the delete button
   * makes the deleteModal visible
   *
   * @returns {undefined}
   */
  $scope.deleteModal = function() {
    console.log('DeleteModal firing');
    $scope.showDeleteModal = !$scope.showDeleteModal;
  };

  /**
   * GenerateApiKey
   * calls generateApiKey from the service
   * generateApiKey in the service generates a new hub API key
   * @param _id
   * @returns a new hub api key
   */
  $scope.generateApiKey = function(_id) {
    if ($scope.user._user.admin === true) {
      hub.generateApiKey(_id).then(function(resp) {
        console.log(resp);
        $scope.apiKey = resp.api_key;
      });
    } else {
      console.log('Permission Denied');
    }
  };

  /**
   * ViewPrinter
   * Sets the state to that of the printer with the associated _id
   *
   * @param _id
   * @returns {undefined}
   */
  $scope.viewPrinter = function(_id) {
    $state.go('dashboard.printer', {hubId: hubId, printerId: _id });
  };

  $scope.getSensors = function() {
    hub.getSensors(hubId)
      .success(function(response) {
        $scope.sensors = response;
        console.log(response);
      })
      .error(function(response) {
        console.log('Unable to retrieve a list of sensors.');
        console.log(response);
      });
  };

  /*********************************************************
   *
   * Promise handling
   * Setting scope variables
   *
   * /

  /*
   * Handling the promise and
   * Retrieving the proper hub
   *  $scope.hub
   */
  hubPromise.then(function(_hub) {
    $scope.hub = _hub;
  });

  /*
   * Retrieving all sensors that are connected to the hub
   *  $scope.sensors {object}[]
   * Handling the promise for retrieving the sensor data and assigning that data to the associated sensor
   *  $scope.sensors.data {object}
   *  $scope.sensors.newestDatum
   */
  /*sensorsPromise.then(function(_sensors) {
    var sensorDataPromises = [];
    $scope.sensors = _sensors;

    for (var i = 0; i < $scope.sensors.length; i++) {
      sensorDataPromises.push(sensor.getData($scope.sensors[i].id));
    }

    $q.all(sensorDataPromises).then(function(_data) {
      var sensorData = _data;
      console.log('Sensor Data Size: ' + sensorData.length);

      for (var j = 0; j < sensorData.length; j++) {
        $scope.sensors[j].data = sensorData[j];
        var dataLength = $scope.sensors[j].data.length;
        $scope.sensors[j].newestDatum = $scope.sensors[j].data[dataLength - 1];
        if ($scope.sensors[j].data[dataLength - 1].value === '1' || $scope.sensors[j].data[dataLength - 1].value === '0') {
          if ($scope.sensors[j].data[dataLength - 1].value === '1') {
            $scope.sensors[j].newestDatum.value = 'True';
          } else {
            $scope.sensors[j].newestDatum.value = 'False';
          }
        }else {
          $scope.sensors[j].newestDatum.value = parseFloat($scope.sensors[j].data[dataLength - 1].value).toFixed(2);
        }
      }

    });
  });*/

  /*
   * Retrieving all printers connected to the hub
   *  $scope.printers {object}[]
   */
  printersPromise.then(function(_printers) {
    $scope.printers = _printers;
    $scope.printersTotalItems = _printers.length;
  });

  /**
   * Retrieve list of sensors
   */
  $scope.getSensors();
}
<commit_msg>Poll backend to retrieve updated sensor readings<commit_after>// jscs:disable

app.controller('ViewHubCtrl', ViewHubCtrl);
ViewHubCtrl.$inject = ['$scope', '$state', '$stateParams', '$timeout', '$q', '$controller', 'hub', 'printer', 'sensor'];

function ViewHubCtrl($scope, $state, $stateParams, $timeout, $q, $controller, hub, printer, sensor) {
  var hubId = Number($stateParams.hubId);

  var hubPromise = hub.getHub(hubId);
  var printersPromise = hub.getPrinters(hubId);

  $scope.sensors = {};
  $scope.updateSensorModal = {};
  $scope.updateSensorModal.form = {};
  $scope.updateSensorModal.attributes = {};
  $scope.updateSensorModalVisible = false;
  $scope.showDeleteModal = false; // Set to true to show the delete confirmation modal
  $scope.printersCurrentPage = 1;
  $scope.printersItemsPerPage = 2;

  $controller('AlertCtrl', { $scope: $scope });
  $controller('AlertCtrl', { $scope: $scope.updateSensorModal});

  /*********************************************************
   *
   * FUNCTIONS
   *
   * /

  /**
   * Modal visibility toggling
   */
  $scope.showSensorModal = function() {
    $scope.updateSensorModalVisible = true;
  };

  $scope.hideSensorModal = function() {
    $scope.updateSensorModalVisible = false;
    $scope.updateSensorModal.alerts = [];
  };

  /**
   * Update a sensor
   */
  $scope.updateSensor = function(sensorId, attributes) {
    hub.updateSensor(sensorId, attributes)
      .success(function(response) {
        $scope.updateSensorModal.addAlert('success', 'The sensor has been updated successfully.');
        angular.forEach(attributes, function(attribute, key){
            if(attribute) {
              $scope.updateSensorModal.sensor[key] = attribute;
            }
        });
        $scope.updateSensorModal.attributes = {};
        $scope.updateSensorModal.form.$setPristine();
        $scope.getSensors();
      })
      .error(function(response) {
          $scope.updateSensorModal.addAlert('danger', 'Unable to update sensor. Please double check that the specified name is not already in use by another sensor.');
          console.log(response);
      });
  };

  /**
   * ToHubsPage
   * Waits 500 milliseconds for the animation to fade
   * Sets the state to the main hubs page
   * @param {boolean} reload
   *  if reload = true the ListHubs controller will refresh
   * @returns {undefined}
   */
  $scope.toHubsPage = function(reload) {
    $timeout(function() {
      $state.go('dashboard.listHubs',{},{reload: reload});
    },500);
  };

  /**
   * UpdateHub
   * Updates a hub in the DB with the hub object gathered from the form
   * Performs multiple checks on the form, check if there are no warnings
   *  checks if the form is empty or not
   *  Checks if the user is an admin, incase they edit some htlm and get the form to show
   * If all checks clear, then it updates the hub, if the entity is invalid it will add the alert to tell the user
   *
   * @param _hubId
   * @param _hub
   * @returns {undefined}
   */
  $scope.updateHub = function(_hubId, _hub) {
    if (!$scope.updateHubForm.$valid) {
      $scope.addAlert('danger', 'Please correct the errors below and try submitting the form again.');
      return;
    }

    // Check whether form has not been filled out
    if ($scope.updateHubForm.$pristine) {
      $scope.addAlert('warning', 'Please fill out the form below before saving.');
      return;
    }

    // Remove empty fields from profile to prevent errors
    Object.keys($scope.hub).forEach(function(key) {
      if ($scope.hub[key] === '') {
        delete $scope.hub[key];
      }
    });

    if ($scope.user.isAdmin()) {
      updateHubPromise = hub.updateHub(_hubId, _hub);

      updateHubPromise.then(function(data) {
        if (typeof (data) === 'object') {
          $scope.resetForm();
          $scope.addAlert('success', 'Hub updated successfully!');
          $scope.hub = data;
        } else {
          $scope.addAlert('danger', 'Sorry but this hub could not be modified.  Some values are unprocessable.');
        }
      });
      return;
    }
  };

  /**
   * ResetForm
   * clears the $scope.hub and sets the form to pristine(cleared)
   *
   * @returns {undefined}
   */
  $scope.resetForm = function() {
    $scope.hubDetails = {};
    $scope.updateHubForm.$setPristine();
  };

  /**
   * DeleteHub
   * calls deleteHub from the service
   * deleteHub in the service removes the hub by id
   * @param _id
   * @returns {}
   */
  $scope.deleteHub = function(_id) {
    console.log('Firing?');
    $scope.showDeleteModal = false;
    if ($scope.user._user.admin === true) {
      // Hub.deleteHub(_id);
      this.toHubsPage(true);
      console.log($scope.showDeleteModal);
    } else {
      console.log('Permission Denied');
    }
  };

  /**
   * DeleteModal
   * Called by the delete button
   * makes the deleteModal visible
   *
   * @returns {undefined}
   */
  $scope.deleteModal = function() {
    console.log('DeleteModal firing');
    $scope.showDeleteModal = !$scope.showDeleteModal;
  };

  /**
   * GenerateApiKey
   * calls generateApiKey from the service
   * generateApiKey in the service generates a new hub API key
   * @param _id
   * @returns a new hub api key
   */
  $scope.generateApiKey = function(_id) {
    if ($scope.user._user.admin === true) {
      hub.generateApiKey(_id).then(function(resp) {
        console.log(resp);
        $scope.apiKey = resp.api_key;
      });
    } else {
      console.log('Permission Denied');
    }
  };

  /**
   * ViewPrinter
   * Sets the state to that of the printer with the associated _id
   *
   * @param _id
   * @returns {undefined}
   */
  $scope.viewPrinter = function(_id) {
    $state.go('dashboard.printer', {hubId: hubId, printerId: _id });
  };

  $scope.getSensors = function() {
    hub.getSensors(hubId)
      .success(function(response) {
        $scope.sensors = response;
      })
      .error(function(response) {
        console.log('Unable to retrieve a list of sensors.');
        console.log(response);
      });
  };

  /*********************************************************
   *
   * Promise handling
   * Setting scope variables
   *
   * /

  /*
   * Handling the promise and
   * Retrieving the proper hub
   *  $scope.hub
   */
  hubPromise.then(function(_hub) {
    $scope.hub = _hub;
  });

  /*
   * Retrieving all sensors that are connected to the hub
   *  $scope.sensors {object}[]
   * Handling the promise for retrieving the sensor data and assigning that data to the associated sensor
   *  $scope.sensors.data {object}
   *  $scope.sensors.newestDatum
   */
  /*sensorsPromise.then(function(_sensors) {
    var sensorDataPromises = [];
    $scope.sensors = _sensors;

    for (var i = 0; i < $scope.sensors.length; i++) {
      sensorDataPromises.push(sensor.getData($scope.sensors[i].id));
    }

    $q.all(sensorDataPromises).then(function(_data) {
      var sensorData = _data;
      console.log('Sensor Data Size: ' + sensorData.length);

      for (var j = 0; j < sensorData.length; j++) {
        $scope.sensors[j].data = sensorData[j];
        var dataLength = $scope.sensors[j].data.length;
        $scope.sensors[j].newestDatum = $scope.sensors[j].data[dataLength - 1];
        if ($scope.sensors[j].data[dataLength - 1].value === '1' || $scope.sensors[j].data[dataLength - 1].value === '0') {
          if ($scope.sensors[j].data[dataLength - 1].value === '1') {
            $scope.sensors[j].newestDatum.value = 'True';
          } else {
            $scope.sensors[j].newestDatum.value = 'False';
          }
        }else {
          $scope.sensors[j].newestDatum.value = parseFloat($scope.sensors[j].data[dataLength - 1].value).toFixed(2);
        }
      }

    });
  });*/

  /*
   * Retrieving all printers connected to the hub
   *  $scope.printers {object}[]
   */
  printersPromise.then(function(_printers) {
    $scope.printers = _printers;
    $scope.printersTotalItems = _printers.length;
  });

  /**
   * Retrieve list of sensors
   */
  $scope.getSensors();

  this.interval = setInterval(function(){
    $scope.getSensors();
  }, 2000);
}
<|endoftext|>


<commit_before>'use strict';

var errorHandler = require('./errors'),
	mongoose = require('mongoose'),
	User = mongoose.model('User'),
	config = require('../../config/config'),
	async = require('async'),
	path = require('path'),
	fs = require('fs'),
	_ = require('lodash');

exports.getPreviewTemplate = function(req, res) {
	if(!req.isAuthenticated()) {
		return res.status(401).send({'message' : 'User is not logged in.'});
	} else {
		if(!req.hasAuthorization(req.user, ["recruiter", "admin"])) {
			return res.status(401).send({'message' : 'User does not have permission.'});
		} else {
			if(!req.query.event_name || !req.query.event_id) {
				return res.status(400).send({'message' : 'Event name or id not specified.'});
			}

			async.parallel([
				function(callback) {
					var fileName = req.query.event_name.replace(/[\.,-\/#!$%\^&\*;:{}=\-_`~()\[\]'\\@+"|<>?]/g,"");
					fileName = fileName.replace(/\s{2,}/g," ");
					fileName = fileName.replace(/ /g, "_");

					var filepath = path.normalize(__dirname + "/../views/templates/preview/" + fileName.toLowerCase() + '.server.view.html');
					//return res.status(400).send({message:filepath});

					fs.readFile(filepath, {encoding: 'utf8'}, function(err, data) {
						if(err) {
							callback(err, null);
						} else {
							callback(null, data);
						}
					});
				},
				function(callback) {
					var query = User.findOne({_id : req.user._id});
					query.populate('status.event_id');
					query.exec(function(err, result) {
						if(_.intersection(result.roles, ["admin"]).length) {
							callback(null, true);
						} else {
							if(err)
								callback(err, null);
							else {
								var i=0;
								for(; i<result.status.length; i++) {
									if((result.status[i].event_id._id.toString() === req.query.event_id.toString()) && (result.status[i].event_id.name === req.query.event_name)) {
										if(result.status[i].recruiter) {
											callback(null, true);
										} else {
											callback(null, false);
										}
										break;
									}
								}

								if(i===result.status.length) {
									callback(null, false);
								}
							}
						}
					});
				}
			],
				function(err, results) {
					if(err) {
						return res.status(400).send({message : err});
					} else {
						if(results[1])
							return res.status(200).send({'preview' : results[0]});
						else
							return res.status(401).send({message : 'You do not have permission to view this template.'});
					}
				}
			);
		}
	}
};<commit_msg>Removed logic from preview template and the email_id variable so bad data is not sent to the server.<commit_after>'use strict';

var errorHandler = require('./errors'),
	mongoose = require('mongoose'),
	User = mongoose.model('User'),
	config = require('../../config/config'),
	async = require('async'),
	path = require('path'),
	fs = require('fs'),
	_ = require('lodash');

exports.getPreviewTemplate = function(req, res) {
	if(!req.isAuthenticated()) {
		return res.status(401).send({'message' : 'User is not logged in.'});
	} else {
		if(!req.hasAuthorization(req.user, ["recruiter", "admin"])) {
			return res.status(401).send({'message' : 'User does not have permission.'});
		} else {
			if(!req.query.event_name || !req.query.event_id) {
				return res.status(400).send({'message' : 'Event name or id not specified.'});
			}

			async.parallel([
				function(callback) {
					var fileName = req.query.event_name.replace(/[\.,-\/#!$%\^&\*;:{}=\-_`~()\[\]'\\@+"|<>?]/g,"");
					fileName = fileName.replace(/\s{2,}/g," ");
					fileName = fileName.replace(/ /g, "_");

					var filepath = path.normalize(__dirname + "/../views/templates/preview/" + fileName.toLowerCase() + '.server.view.html');
					//return res.status(400).send({message:filepath});

					fs.readFile(filepath, {encoding: 'utf8'}, function(err, data) {
						if(err) {
							callback(err, null);
						} else {
							callback(null, data);
						}
					});
				},
				function(callback) {
					var query = User.findOne({_id : req.user._id});
					query.populate('status.event_id');
					query.exec(function(err, result) {
						if(_.intersection(result.roles, ["admin"]).length) {
							callback(null, true);
						} else {
							if(err)
								callback(err, null);
							else {
								var i=0;
								for(; i<result.status.length; i++) {
									if((result.status[i].event_id._id.toString() === req.query.event_id.toString()) && (result.status[i].event_id.name === req.query.event_name)) {
										if(result.status[i].recruiter) {
											callback(null, true);
										} else {
											callback(null, false);
										}
										break;
									}
								}

								if(i===result.status.length) {
									callback(null, false);
								}
							}
						}
					});
				}
			],
				function(err, results) {
					if(err) {
						return res.status(400).send({message : err});
					} else {
						if(results[1]) {
							//For now, remove items we do not want.  Eventually we may translate a conditional section in swig to a conditional element in Angular (this would be done by replacing {% if testvar %}{% endif %} =>

)
							var conditonals = /{%.*?%}/g;
							var email_id = /{{email_id}}/g;

							results[0] = results[0].replace(email_id, "");
							results[0] = results[0].replace(conditonals, "");

							return res.status(200).send({'preview' : results[0]});
						}
						else
							return res.status(401).send({message : 'You do not have permission to view this template.'});
					}
				}
			);
		}
	}
};<|endoftext|>


<commit_before>var DockerEvents = require('docker-events')
var SPM = require('spm-metrics-js')
var SpmAgent = require('spm-agent')
var os = require('os')

function DockerEventForwarder (docker) {
  var Docker = require('dockerode')
  try {
    this.docker = docker || new Docker()
    this.dockerEvents = new DockerEvents({docker: this.docker})
  } catch (dockerError) {
    SpmAgent.Logger.log('error', 'Error in sendEvent(): ' + err)
  }

  this.spm = new SPM(SpmAgent.Config.tokens.spm, 0)
  this.spm.on('error', function (err) {
    try {
      SpmAgent.Logger.log('error', 'Error in DockerEventForwarder: ' + err)
    } catch (err2) {
      console.log(err2)
      console.log(err)
    }
  })
  var self = this
  this.sendEvent = function (type, msg) {
    msg.creator = process.env.HOSTNAME || os.hostname()
    self.spm.sendEvent(type, msg, function (err, res) {
      if (err) {
        console.log('Error sending event to SPM ' + err)
      } else {
        if (res && res.statusCode > 299) {
          console.log('Error sending event to SPM ' + res.body)
        }
      }
    })
  }
  this.forwardEvent = function (dockerEvent) {
    try {
      if (dockerEvent.Type) {
        if (!dockerEvent.status) {
          dockerEvent.status = dockerEvent.Type + ' ' + (dockerEvent.Action || '')
        }
        if (dockerEvent.Actor && dockerEvent.Actor.Attributes) {
          dockerEvent.id = dockerEvent.Actor.Attributes.container
          dockerEvent.message = ''
          Object.keys(dockerEvent.Actor.Attributes).forEach(function (key, i) {
            if (i > 0) {
              dockerEvent.message += ', '
            }
            dockerEvent.message += key + ':' + dockerEvent.Actor.Attributes[key]
          })
        }
      }
      var msgStr = dockerEvent.status + ' ' + (dockerEvent.from || '') + ' ' + (dockerEvent.id || '') + ' ' + (dockerEvent.message || '')
      console.log('Docker Event: ' + msgStr)
      var msg = {
        name: dockerEvent.from,
        message: msgStr,
        tags: ['docker', process.env.HOSTNAME || os.hostname(), dockerEvent.status, dockerEvent.id ]
      }
      var type = (dockerEvent.status || 'docker')
      type = type.replace(/[\W]/gi, '_')
      if (/exec_.*/.test(type)) {
        type = 'exec'
      }
      self.sendEvent(type, msg)
    } catch (err) {
      console.error(err)
    }
  }
  setTimeout(function () {
    self.docker.version(function (err, data) {
      if (!err) {
        self.sendEvent('docker-info', { message: 'Docker: ' + data.Version + ' API: ' + data.ApiVersion + ' Kernel: ' + data.KernelVersion }, function (err, res) {
          if (err) {
            SpmAgent.Logger.log('error', 'Error in sendEvent(): ' + err)
          }
        })
      }
    })
  }, 500)
  this.dockerEvents.on('connect', function () {
    self.dockerEvents.on('_message', self.forwardEvent)
  })
  this.dockerEvents.on('disconnect', function () {
    self.dockerEvents.removeListener('_message', self.forwardEvent)
  })
  this.dockerEvents.on('error', function (err) {
    SpmAgent.Logger.log('error', 'Error in DockerEventsForwarder: ' + err)
  })
  this.dockerEvents.start()
  return this
}

module.exports = DockerEventForwarder
<commit_msg>print events only in debig mode to console<commit_after>var DockerEvents = require('docker-events')
var SPM = require('spm-metrics-js')
var SpmAgent = require('spm-agent')
var os = require('os')

function DockerEventForwarder (docker) {
  var Docker = require('dockerode')
  try {
    this.docker = docker || new Docker()
    this.dockerEvents = new DockerEvents({docker: this.docker})
  } catch (dockerError) {
    SpmAgent.Logger.log('error', 'Error in sendEvent(): ' + err)
  }

  this.spm = new SPM(SpmAgent.Config.tokens.spm, 0)
  this.spm.on('error', function (err) {
    try {
      SpmAgent.Logger.log('error', 'Error in DockerEventForwarder: ' + err)
    } catch (err2) {
      console.log(err2)
      console.log(err)
    }
  })
  var self = this
  this.sendEvent = function (type, msg) {
    msg.creator = process.env.HOSTNAME || os.hostname()
    self.spm.sendEvent(type, msg, function (err, res) {
      if (err) {
        console.log('Error sending event to SPM ' + err)
      } else {
        if (res && res.statusCode > 299) {
          console.log('Error sending event to SPM ' + res.body)
        }
      }
    })
  }
  this.forwardEvent = function (dockerEvent) {
    try {
      if (dockerEvent.Type) {
        if (!dockerEvent.status) {
          dockerEvent.status = dockerEvent.Type + ' ' + (dockerEvent.Action || '')
        }
        if (dockerEvent.Actor && dockerEvent.Actor.Attributes) {
          dockerEvent.id = dockerEvent.Actor.Attributes.container
          dockerEvent.message = ''
          Object.keys(dockerEvent.Actor.Attributes).forEach(function (key, i) {
            if (i > 0) {
              dockerEvent.message += ', '
            }
            dockerEvent.message += key + ':' + dockerEvent.Actor.Attributes[key]
          })
        }
      }
      var msgStr = dockerEvent.status + ' ' + (dockerEvent.from || '') + ' ' + (dockerEvent.id || '') + ' ' + (dockerEvent.message || '')
      if (process.env.SPM_LOG_LEVEL==='debug') {
        console.log('Docker Event: ' + msgStr)
      }
      var msg = {
        name: dockerEvent.from,
        message: msgStr,
        tags: ['docker', process.env.HOSTNAME || os.hostname(), dockerEvent.status, dockerEvent.id ]
      }
      var type = (dockerEvent.status || 'docker')
      type = type.replace(/[\W]/gi, '_')
      if (/exec_.*/.test(type)) {
        type = 'exec'
      }
      self.sendEvent(type, msg)
    } catch (err) {
      console.error(err)
    }
  }
  setTimeout(function () {
    self.docker.version(function (err, data) {
      if (!err) {
        self.sendEvent('docker-info', { message: 'Docker: ' + data.Version + ' API: ' + data.ApiVersion + ' Kernel: ' + data.KernelVersion }, function (err, res) {
          if (err) {
            SpmAgent.Logger.log('error', 'Error in sendEvent(): ' + err)
          }
        })
      }
    })
  }, 500)
  this.dockerEvents.on('connect', function () {
    self.dockerEvents.on('_message', self.forwardEvent)
  })
  this.dockerEvents.on('disconnect', function () {
    self.dockerEvents.removeListener('_message', self.forwardEvent)
  })
  this.dockerEvents.on('error', function (err) {
    SpmAgent.Logger.log('error', 'Error in DockerEventsForwarder: ' + err)
  })
  this.dockerEvents.start()
  return this
}

module.exports = DockerEventForwarder
<|endoftext|>


<commit_before>'use strict';

var inherits = require('inherits');

var BaseRenderer = require('./BaseRenderer');

var renderUtil = require('../util/RenderUtil');

var componentsToPath = renderUtil.componentsToPath,
    createLine = renderUtil.createLine;

/**
 * The default renderer used for shapes and connections.
 *
 * @param {EventBus} eventBus
 * @param {Styles} styles
 */
function DefaultRenderer(eventBus, styles) {
  BaseRenderer.call(this, eventBus);

  this.CONNECTION_STYLE = styles.style([ 'no-fill' ], { strokeWidth: 5, stroke: 'fuchsia' });
  this.SHAPE_STYLE = styles.style({ fill: 'white', stroke: 'fuchsia', strokeWidth: 2 });
}

inherits(DefaultRenderer, BaseRenderer);

DefaultRenderer.prototype.canRender = function() {
  return true;
};

DefaultRenderer.prototype.drawShape = function drawShape(visuals, element) {
  return visuals.rect(0, 0, element.width || 0, element.height || 0).attr(this.SHAPE_STYLE);
};

DefaultRenderer.prototype.drawConnection = function drawConnection(visuals, connection) {
  return createLine(connection.waypoints, this.CONNECTION_STYLE).appendTo(visuals);
};

DefaultRenderer.prototype.getShapePath = function getShapePath(shape) {

  var x = shape.x,
      y = shape.y,
      width = shape.width,
      height = shape.height;

  var shapePath = [
    ['M', x, y],
    ['l', width, 0],
    ['l', 0, height],
    ['l', -width, 0],
    ['z']
  ];

  return componentsToPath(shapePath);
};

DefaultRenderer.prototype.getConnectionPath = function getConnectionPath(connection) {
  var waypoints = connection.waypoints;

  var idx, point, connectionPath = [];

  for (idx = 0; !!(point = waypoints[idx]); idx++) {

    // take invisible docking into account
    // when creating the path
    point = point.original || point;

    connectionPath.push([ idx === 0 ? 'M' : 'L', point.x, point.y ]);
  }

  return componentsToPath(connectionPath);
};

DefaultRenderer.$inject = [ 'eventBus', 'styles' ];

module.exports = DefaultRenderer;
<commit_msg>fix(draw): apply default renderer with minimum priority<commit_after>'use strict';

var inherits = require('inherits');

var BaseRenderer = require('./BaseRenderer');

var renderUtil = require('../util/RenderUtil');

var componentsToPath = renderUtil.componentsToPath,
    createLine = renderUtil.createLine;

// apply default renderer with lowest possible priority
// so that it only kicks in if noone else could render
var DEFAULT_RENDER_PRIORITY = 1;

/**
 * The default renderer used for shapes and connections.
 *
 * @param {EventBus} eventBus
 * @param {Styles} styles
 */
function DefaultRenderer(eventBus, styles) {
  //
  BaseRenderer.call(this, eventBus, DEFAULT_RENDER_PRIORITY);

  this.CONNECTION_STYLE = styles.style([ 'no-fill' ], { strokeWidth: 5, stroke: 'fuchsia' });
  this.SHAPE_STYLE = styles.style({ fill: 'white', stroke: 'fuchsia', strokeWidth: 2 });
}

inherits(DefaultRenderer, BaseRenderer);

DefaultRenderer.prototype.canRender = function() {
  return true;
};

DefaultRenderer.prototype.drawShape = function drawShape(visuals, element) {
  return visuals.rect(0, 0, element.width || 0, element.height || 0).attr(this.SHAPE_STYLE);
};

DefaultRenderer.prototype.drawConnection = function drawConnection(visuals, connection) {
  return createLine(connection.waypoints, this.CONNECTION_STYLE).appendTo(visuals);
};

DefaultRenderer.prototype.getShapePath = function getShapePath(shape) {

  var x = shape.x,
      y = shape.y,
      width = shape.width,
      height = shape.height;

  var shapePath = [
    ['M', x, y],
    ['l', width, 0],
    ['l', 0, height],
    ['l', -width, 0],
    ['z']
  ];

  return componentsToPath(shapePath);
};

DefaultRenderer.prototype.getConnectionPath = function getConnectionPath(connection) {
  var waypoints = connection.waypoints;

  var idx, point, connectionPath = [];

  for (idx = 0; !!(point = waypoints[idx]); idx++) {

    // take invisible docking into account
    // when creating the path
    point = point.original || point;

    connectionPath.push([ idx === 0 ? 'M' : 'L', point.x, point.y ]);
  }

  return componentsToPath(connectionPath);
};

DefaultRenderer.$inject = [ 'eventBus', 'styles' ];

module.exports = DefaultRenderer;
<|endoftext|>


<commit_before>/*
 * == BSD2 LICENSE ==
 * Copyright (c) 2015, Tidepool Project
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the associated License, which is identical to the BSD 2-Clause
 * License as published by the Open Source Initiative at opensource.org.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the License for more details.
 *
 * You should have received a copy of the License along with this program; if
 * not, you can obtain one from Tidepool Project at tidepool.org.
 * == BSD2 LICENSE ==
 */

var _ = require('lodash');
var async = require('async');
var sundial = require('sundial');
var annotate = require('../eventAnnotations');
var util = require('util');

var crcCalculator = require('../crc.js');
var struct = require('../struct.js')();

var TZOUtil = require('../TimezoneOffsetUtil');

var debug = require('../bows')('AnimasDriver');

module.exports = function (config) {
  var cfg = _.clone(config);
  debug('animas config: ', cfg);
  var serialDevice = config.deviceComms;
  var animasDeviceId;

  if (config.silent) {
    // debug = _.noop;
  }

  var BOM_BYTE = 0xC0;
  var EOM_BYTE = 0xC1;
  var ADDRESS_CONNECT = 0xFF; //used to establish 7-bit conenction address

  var CMDS = {
    NULL: { value: 0, name: 'NULL' },
    ACK: { value: 1, name: 'ACK' },
    NAK: { value: 2, name: 'NAK' },
    INVALID_COMMAND: { value: 3, name: 'Invalid Command' },
    CONNECT: { value: 0x93, name: 'CONNECT'},
    HANDSHAKE: {value: 0xBF, name: 'HANDSHAKE'}
  };

  var getCmdName = function (idx) {
    for (var i in CMDS) {
      if (CMDS[i].value == idx) {
        return CMDS[i].name;
      }
    }
    return 'UNKNOWN COMMAND!';
  };

  var firmwareHeader = null;

  // builds a command in an ArrayBuffer
  // Byte 1: always 0xC0 (BOM - Beginning of Message),
  // Byte 2: address field; bit 0 is command/response bit (primary device sets this bit, secondary clears it)
  // Byte 3: control field; if bit 4 is clear sender retains transmit rights, if set receiver has transmit rights
  // Payload: 0-128 bytes
  // CRC bytes: 2 check bytes over bytes 2-3 and payload
  // EOM byte: always 0xC1 (signals end of message)

  var buildPacket = function (address, command, payloadLength, payload) {
    var datalen = payloadLength + 6;
    var buf = new ArrayBuffer(datalen);
    var bytes = new Uint8Array(buf);
    var ctr = struct.pack(bytes, 0, 'bbb', BOM_BYTE, address,command);
    ctr += struct.copyBytes(bytes, ctr, payload, payloadLength);
    // checksum only over address field, control field and payload
    var crc = crcCalculator.calcCheckBytes(bytes.subarray(1,payloadLength+3), ctr);
    struct.pack(bytes, ctr, 'sb', crc, EOM_BYTE);
    debug("bytes sent:", bytes);
    return buf;
  };

  var setupConnection = function() {
    return {
      packet: buildPacket(
        ADDRESS_CONNECT, CMDS.CONNECT.value, 9, [0x01,0x00,0x00,0x00,0x5F,0x00,0x00,0x00,0x02]
      ),
      parser: function (packet) {
        var data = parsePayload(packet);
        address = data;
        return data;
      }
    };
  };

  var handshake = function(iter) {
    return {
      packet: buildPacket(
        ADDRESS_CONNECT, CMDS.HANDSHAKE.value, 10, [0x01,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x02,iter]
      ),
      parser: function (packet) {
        var data = parsePayload(packet);
        return data;
      }
    };
  };

  var readFirmwareHeader = function () {
    return {
      packet: buildPacket(
        CMDS.READ_FIRMWARE_HEADER.value, 0, null
      ),
      parser: function (packet) {
        var data = parseXMLPayload(packet);
        firmwareHeader = data;
        return data;
      }
    };
  };

  var ping = function () {
    return {
      packet: buildPacket(
        CMDS.PING.value, 0, null
      ),
      parser: function (packet) {
        debug('pong!');
        debug(packet);
      }
    };
  };

  // accepts a stream of bytes and tries to find a packet
  // at the beginning of it.
  // returns a packet object; if valid == true it's a valid packet
  // if packet_len is nonzero, that much should be deleted from the stream
  // if valid is false and packet_len is nonzero, the previous packet
  // should be NAKed.
  var extractPacket = function (bytes) {
    var packet = {
      bytes: bytes,
      valid: false,
      packet_len: 0,
      command: 0,
      payload: null,
      crc: 0
    };

    if (bytes[0] != BOM_BYTE) {
      return packet;
    }

    var plen = bytes.length;
    var packet_len = struct.extractShort(bytes, 1);
    // minimum packet len is 6
    if (packet_len > plen) {
      return packet;  // we're not done yet
    }

    // we now have enough length for a complete packet, so calc the CRC
    packet.packet_len = packet_len;
    packet.crc = struct.extractShort(bytes, packet_len - 2);
    var crc = crcCalculator.calcCRC_D(bytes, packet_len - 2);
    if (crc != packet.crc) {
      // if the crc is bad, we should discard the whole packet
      // (packet_len is nonzero)
      return packet;
    }

    // command is the fourth byte, packet is remainder of data
    packet.command = bytes[3];
    packet.payload = new Uint8Array(packet_len - 6);
    for (var i = 0; i < packet_len - 6; ++i) {
      packet.payload[i] = bytes[i + 4];
    }

    packet.valid = true;
    return packet;
  };

  var parsePayload = function (packet) {
    console.log("Packet:", packet);

    if (!packet.valid) {
      return {};
    }
    if (packet.command !== 1) {
      return {};
    }

    var len = packet.packet_len - 6;
    var data = null;
    if (len) {
      console.log(struct.extractString(packet.payload, 0, len));
    }
    return data;
  };

  var animasPacketHandler = function (buffer) {
    // for efficiency reasons, we're not going to bother to ask the driver
    // to decode things that can't possibly be a packet
    // first, discard bytes that can't start a packet
    var discardCount = 0;
    while (buffer.len() > discardCount && buffer.get(0) != BOM_BYTE) {
      ++discardCount;
    }
    if (discardCount) {
      buffer.discard(discardCount);
    }

    if (buffer.len() < 6) { // all complete packets must be at least this long
      return false;       // not enough there yet
    }

    // there's enough there to try, anyway
    var packet = extractPacket(buffer.bytes());
    if (packet.packet_len !== 0) {
      // remove the now-processed packet
      buffer.discard(packet.packet_len);
    }

    if (packet.valid) {
      return packet;
    } else {
      return null;
    }
  };

  var listenForPacket = function (timeout, commandpacket, callback) {
    var abortTimer = setTimeout(function () {
      clearInterval(listenTimer);
      debug('TIMEOUT');
      callback('TIMEOUT', null);
    }, timeout);

    var listenTimer = setInterval(function () {
      if (serialDevice.hasAvailablePacket()) {
        var pkt = serialDevice.nextPacket();
        // we always call the callback if we get a packet back,
        // so just cancel the timers if we do
        clearTimeout(abortTimer);
        clearInterval(listenTimer);
        if (pkt.command != CMDS.ACK.value) {
          callback('Bad result ' + pkt.command + ' (' +
                   getCmdName(pkt.command) + ') from data packet', pkt);
        } else {
          // only attempt to parse the payload if it worked
          if (pkt.payload) {
            pkt.parsed_payload = commandpacket.parser(pkt);
          }
          callback(null, pkt);
        }
      }
    }, 250);
  };

  var animasCommandResponse = function (commandpacket, callback) {
    serialDevice.writeSerial(commandpacket.packet, function () {
      // once we've sent the command, start listening for a response
      // but if we don't get one in 1 second give up
      listenForPacket(5000, commandpacket, callback);
    });
  };

  var getConnection = function(obj, cb) {
    debug('connecting to animas');
    var cmd = setupConnection();
    animasCommandResponse(cmd, function (err, result) {
      if (err) {
        debug('Failure trying to talk to animas.');
        debug(err);
        debug(result);
        cb(null, null);
      } else {
        cb(null, obj);
      }
    });
  };

  var getFirmwareHeader = function (obj, cb) {
    debug('looking for animas');
    var cmd = readFirmwareHeader();
    animasCommandResponse(cmd, function (err, result) {
      if (err) {
        debug('Failure trying to talk to animas.');
        debug(err);
        debug(result);
        cb(null, null);
      } else {
        cb(null, obj);
      }
    });
  };

  function do_ping(cb) {
    var cmd = ping();
    animasCommandResponse(cmd, function (err, result) {
      if (err) {
        debug('Failure trying to talk to animas.');
        debug(err);
        debug(result);
        cb(null, null);
      } else {
        cb(null, null);
      }
    });
  }

  // this is the probe function passed to connect
  function probe(cb) {
    debug('handshaking with animas');

    for(var i=0; i<16;i++) {
      var cmd = handshake(i);
      animasCommandResponse(cmd, function (err, result) {
        if (err) {
          debug('Failure trying to talk to animas.');
          debug(err);
          debug(result);
          cb(null, null);
        } else {
          cb(null, obj);
        }
      });
    }
  };

  return {
    // using the default detect for this driver
    // detect: function(cb) {
    // },

    // this function starts the chain, so it has to create but not accept
    // the result (data) object; it's then passed down the rest of the chain
    setup: function (deviceInfo, progress, cb) {
      debug('STEP: setup');
      progress(100);
      cb(null, {deviceInfo: deviceInfo});
    },

    connect: function (progress, data, cb) {
      debug('STEP: connect');
      cfg.deviceComms.connect(data.deviceInfo, animasPacketHandler, probe, function(err) {
        if (err) {
          return cb(err);
        }

        getConnection(true, function(connectErr, obj) {
          if(connectErr) {
            cb(connectErr, obj);
          }else{

            getFirmwareHeader(true, function(firmwareErr, obj) {
              if (firmwareErr) {
                cb(firmwareErr, obj);
              } else {

                    do_ping(function (err, result) {
                      // we're talking so tell the serial device to record this port
                      cfg.deviceComms.recordPort(data.deviceInfo.driverId);
                      progress(100);
                      data.connect = true;
                      data.firmwareHeader = firmwareHeader;
                      data.partitionInfo = partitionInfo;
                      data.model = firmwareHeader.attrs.ProductId;
                      cb(null, data);
                    });

              }
            });
          }
        });
      });
    },

    getConfigInfo: function (progress, data, cb) {
      debug('STEP: getConfigInfo');

      //TODO: fetch manufacturing data
      progress(100);
      data.getConfigInfo = true;
      cb(null, data);

    },

    fetchData: function (progress, data, cb) {
      // a little helper to split up our progress bar segment
      var makeProgress = function (progfunc, start, end) {
        return function(x) {
          progfunc(start + (x/100.0)*(end-start));
        };
      };

      debug('STEP: fetchData');
      progress(0);

      //TODO: fetchData

      progress(100);
      cb(err, data);

    },

    processData: function (progress, data, cb) {
      debug('STEP: processData');
      progress(0);

      //TODO: processData

      progress(100);
      data.processData = true;
      cb(null, data);
    },

    uploadData: function (progress, data, cb) {
      debug('STEP: uploadData');
      progress(0);

      //TODO: uploadData

      progress(100);
      return cb(null, data);

    },

    disconnect: function (progress, data, cb) {
      debug('STEP: disconnect');
      progress(100);
      data.disconnect = true;
      cb(null, data);
  },

    cleanup: function (progress, data, cb) {
      debug('STEP: cleanup');
      cfg.deviceComms.clearPacketHandler();
      cfg.deviceComms.disconnect(function() {
        progress(100);
        data.cleanup = true;
        cb(null, data);
      });
    }
  };
};
<commit_msg>Checks for special characters in payload<commit_after>/*
 * == BSD2 LICENSE ==
 * Copyright (c) 2015, Tidepool Project
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the associated License, which is identical to the BSD 2-Clause
 * License as published by the Open Source Initiative at opensource.org.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the License for more details.
 *
 * You should have received a copy of the License along with this program; if
 * not, you can obtain one from Tidepool Project at tidepool.org.
 * == BSD2 LICENSE ==
 */

var _ = require('lodash');
var async = require('async');
var sundial = require('sundial');
var annotate = require('../eventAnnotations');
var util = require('util');

var crcCalculator = require('../crc.js');
var struct = require('../struct.js')();

var TZOUtil = require('../TimezoneOffsetUtil');

var debug = require('../bows')('AnimasDriver');

module.exports = function (config) {
  var cfg = _.clone(config);
  debug('animas config: ', cfg);
  var serialDevice = config.deviceComms;
  var animasDeviceId;

  if (config.silent) {
    // debug = _.noop;
  }

  var BOM_BYTE = 0xC0;
  var EOM_BYTE = 0xC1;
  var ADDRESS_CONNECT = 0xFF; //used to establish 7-bit conenction address

  var CMDS = {
    NULL: { value: 0, name: 'NULL' },
    ACK: { value: 1, name: 'ACK' },
    NAK: { value: 2, name: 'NAK' },
    INVALID_COMMAND: { value: 3, name: 'Invalid Command' },
    CONNECT: { value: 0x93, name: 'CONNECT'},
    HANDSHAKE: {value: 0xBF, name: 'HANDSHAKE'}
  };

  var getCmdName = function (idx) {
    for (var i in CMDS) {
      if (CMDS[i].value == idx) {
        return CMDS[i].name;
      }
    }
    return 'UNKNOWN COMMAND!';
  };

  var firmwareHeader = null;

  // builds a command in an ArrayBuffer
  // Byte 1: always 0xC0 (BOM - Beginning of Message),
  // Byte 2: address field; bit 0 is command/response bit (primary device sets this bit, secondary clears it)
  // Byte 3: control field; if bit 4 is clear sender retains transmit rights, if set receiver has transmit rights
  // Payload: 0-128 bytes
  // CRC bytes: 2 check bytes over bytes 2-3 and payload
  // EOM byte: always 0xC1 (signals end of message)

  var buildPacket = function (address, command, payloadLength, payload) {
    var datalen = payloadLength + 6;
    var buf = new ArrayBuffer(datalen);
    var bytes = new Uint8Array(buf);
    var ctr = struct.pack(bytes, 0, 'bbb', BOM_BYTE, address,command);

    ctr += struct.copyBytes(bytes, ctr, checkExceptions(payload), payloadLength);
    // checksum only over address field, control field and payload
    var crc = checkExceptions(crcCalculator.calcCheckBytes(bytes.subarray(1,payloadLength+3), ctr));

    struct.pack(bytes, ctr, 'sb', crc, EOM_BYTE);
    debug("bytes sent:", bytes);
    return buf;
  };

  var checkExceptions = function(buf) {
    for(var i in buf) {
      var byte = buf[i];
      if(byte == BOM_BYTE || byte == EOM_BYTE || byte == 0x7D) {
        debug("Replacing special character");
        buf[i] = 0x7D;
        buf.splice(i, 0, byte ^ 0x20);
      }
    }
    return buf;
  }

  var setupConnection = function() {
    return {
      packet: buildPacket(
        ADDRESS_CONNECT, CMDS.CONNECT.value, 9, [0x01,0x00,0x00,0x00,0x5F,0x00,0x00,0x00,0x02]
      ),
      parser: function (packet) {
        var data = parsePayload(packet);
        address = data;
        return data;
      }
    };
  };

  var handshake = function(iter) {
    return {
      packet: buildPacket(
        ADDRESS_CONNECT, CMDS.HANDSHAKE.value, 10, [0x01,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x02,iter]
      ),
      parser: function (packet) {
        var data = parsePayload(packet);
        return data;
      }
    };
  };

  var readFirmwareHeader = function () {
    return {
      packet: buildPacket(
        //TODO: CMDS.READ_FIRMWARE_HEADER.value, 0, null

      ),
      parser: function (packet) {
        var data = parseXMLPayload(packet);
        firmwareHeader = data;
        return data;
      }
    };
  };

  var ping = function () {
    return {
      packet: buildPacket(
        //TODO: CMDS.PING.value, 0, null
      ),
      parser: function (packet) {
        debug('pong!');
        debug(packet);
      }
    };
  };

  // accepts a stream of bytes and tries to find a packet
  // at the beginning of it.
  // returns a packet object; if valid == true it's a valid packet
  // if packet_len is nonzero, that much should be deleted from the stream
  // if valid is false and packet_len is nonzero, the previous packet
  // should be NAKed.
  var extractPacket = function (bytes) {
    var packet = {
      bytes: bytes,
      valid: false,
      packet_len: 0,
      command: 0,
      payload: null,
      crc: 0
    };

    if (bytes[0] != BOM_BYTE) {
      return packet;
    }

    var plen = bytes.length;
    var packet_len = struct.extractShort(bytes, 1);
    // minimum packet len is 6
    if (packet_len > plen) {
      return packet;  // we're not done yet
    }

    // we now have enough length for a complete packet, so calc the CRC
    packet.packet_len = packet_len;
    packet.crc = struct.extractShort(bytes, packet_len - 2);
    var crc = crcCalculator.calcCRC_D(bytes, packet_len - 2);
    if (crc != packet.crc) {
      // if the crc is bad, we should discard the whole packet
      // (packet_len is nonzero)
      return packet;
    }

    // command is the fourth byte, packet is remainder of data
    packet.command = bytes[3];
    packet.payload = new Uint8Array(packet_len - 6);
    for (var i = 0; i < packet_len - 6; ++i) {
      packet.payload[i] = bytes[i + 4];
    }

    packet.valid = true;
    return packet;
  };

  var parsePayload = function (packet) {
    console.log("Packet:", packet);

    if (!packet.valid) {
      return {};
    }
    if (packet.command !== 1) {
      return {};
    }

    var len = packet.packet_len - 6;
    var data = null;
    if (len) {
      console.log(struct.extractString(packet.payload, 0, len));
    }
    return data;
  };

  var animasPacketHandler = function (buffer) {
    // for efficiency reasons, we're not going to bother to ask the driver
    // to decode things that can't possibly be a packet
    // first, discard bytes that can't start a packet
    var discardCount = 0;
    while (buffer.len() > discardCount && buffer.get(0) != BOM_BYTE) {
      ++discardCount;
    }
    if (discardCount) {
      buffer.discard(discardCount);
    }

    if (buffer.len() < 6) { // all complete packets must be at least this long
      return false;       // not enough there yet
    }

    // there's enough there to try, anyway
    var packet = extractPacket(buffer.bytes());
    if (packet.packet_len !== 0) {
      // remove the now-processed packet
      buffer.discard(packet.packet_len);
    }

    if (packet.valid) {
      return packet;
    } else {
      return null;
    }
  };

  var listenForPacket = function (timeout, commandpacket, callback) {
    var abortTimer = setTimeout(function () {
      clearInterval(listenTimer);
      debug('TIMEOUT');
      callback('TIMEOUT', null);
    }, timeout);

    var listenTimer = setInterval(function () {
      if (serialDevice.hasAvailablePacket()) {
        var pkt = serialDevice.nextPacket();
        // we always call the callback if we get a packet back,
        // so just cancel the timers if we do
        clearTimeout(abortTimer);
        clearInterval(listenTimer);
        if (pkt.command != CMDS.ACK.value) {
          callback('Bad result ' + pkt.command + ' (' +
                   getCmdName(pkt.command) + ') from data packet', pkt);
        } else {
          // only attempt to parse the payload if it worked
          if (pkt.payload) {
            pkt.parsed_payload = commandpacket.parser(pkt);
          }
          callback(null, pkt);
        }
      }
    }, 250);
  };

  var animasCommandResponse = function (commandpacket, callback) {
    serialDevice.writeSerial(commandpacket.packet, function () {
      // once we've sent the command, start listening for a response
      // but if we don't get one in 1 second give up
      listenForPacket(5000, commandpacket, callback);
    });
  };

  var getConnection = function(obj, cb) {
    debug('connecting to animas');
    var cmd = setupConnection();
    animasCommandResponse(cmd, function (err, result) {
      if (err) {
        debug('Failure trying to talk to animas.');
        debug(err);
        debug(result);
        cb(null, null);
      } else {
        cb(null, obj);
      }
    });
  };

  var getFirmwareHeader = function (obj, cb) {
    debug('looking for animas');
    var cmd = readFirmwareHeader();
    animasCommandResponse(cmd, function (err, result) {
      if (err) {
        debug('Failure trying to talk to animas.');
        debug(err);
        debug(result);
        cb(null, null);
      } else {
        cb(null, obj);
      }
    });
  };

  function do_ping(cb) {
    var cmd = ping();
    animasCommandResponse(cmd, function (err, result) {
      if (err) {
        debug('Failure trying to talk to animas.');
        debug(err);
        debug(result);
        cb(null, null);
      } else {
        cb(null, null);
      }
    });
  }

  // this is the probe function passed to connect
  function probe(cb) {
    debug('handshaking with animas');

    for (var i = 0; i < 256; i++)
    {
      var forcedDisconnect = buildPacket(i, 0x53, 0, null);
      serialDevice.writeSerial(forcedDisconnect, function () {});
    }

    var waitTimer = setTimeout(function () {

      var i = 0;
      var handshakeInterval = setInterval(function() {
        console.log('Handshake ',i);
        var cmd = handshake(i);
        animasCommandResponse(cmd, function (err, result) {
          if (err) {
            debug('Failure trying to talk to animas.');
            debug(err);
            debug(result);
            cb(null, null);
          } else {
            console.log(result);
            clearInterval(handshakeInterval);
            cb(null, result);
          }
        });

        i++;
        if(i == 16) {
          clearInterval(handshakeInterval);
        }
      }, 500);

    }, 1000);

  };

  return {
    // using the default detect for this driver
    // detect: function(cb) {
    // },

    // this function starts the chain, so it has to create but not accept
    // the result (data) object; it's then passed down the rest of the chain
    setup: function (deviceInfo, progress, cb) {
      debug('STEP: setup');
      progress(100);
      cb(null, {deviceInfo: deviceInfo});
    },

    connect: function (progress, data, cb) {
      debug('STEP: connect');
      cfg.deviceComms.connect(data.deviceInfo, animasPacketHandler, probe, function(err) {
        if (err) {
          return cb(err);
        }

        getConnection(true, function(connectErr, obj) {
          if(connectErr) {
            cb(connectErr, obj);
          }else{

            getFirmwareHeader(true, function(firmwareErr, obj) {
              if (firmwareErr) {
                cb(firmwareErr, obj);
              } else {

                    do_ping(function (err, result) {
                      // we're talking so tell the serial device to record this port
                      cfg.deviceComms.recordPort(data.deviceInfo.driverId);
                      progress(100);
                      data.connect = true;
                      // TODO:
                      //data.firmwareHeader = firmwareHeader;
                      //data.partitionInfo = partitionInfo;
                      //data.model = firmwareHeader.attrs.ProductId;
                      cb(null, data);
                    });

              }
            });
          }
        });
      });
    },

    getConfigInfo: function (progress, data, cb) {
      debug('STEP: getConfigInfo');

      //TODO: fetch manufacturing data
      progress(100);
      data.getConfigInfo = true;
      cb(null, data);

    },

    fetchData: function (progress, data, cb) {
      // a little helper to split up our progress bar segment
      var makeProgress = function (progfunc, start, end) {
        return function(x) {
          progfunc(start + (x/100.0)*(end-start));
        };
      };

      debug('STEP: fetchData');
      progress(0);

      //TODO: fetchData

      progress(100);
      cb(err, data);

    },

    processData: function (progress, data, cb) {
      debug('STEP: processData');
      progress(0);

      //TODO: processData

      progress(100);
      data.processData = true;
      cb(null, data);
    },

    uploadData: function (progress, data, cb) {
      debug('STEP: uploadData');
      progress(0);

      //TODO: uploadData

      progress(100);
      return cb(null, data);

    },

    disconnect: function (progress, data, cb) {
      debug('STEP: disconnect');
      progress(100);
      data.disconnect = true;
      cb(null, data);
  },

    cleanup: function (progress, data, cb) {
      debug('STEP: cleanup');
      cfg.deviceComms.clearPacketHandler();
      cfg.deviceComms.disconnect(function() {
        progress(100);
        data.cleanup = true;
        cb(null, data);
      });
    }
  };
};
<|endoftext|>


<commit_before>/*!
 * Copyright (C) Linaro Limited 2015,2016,2017,2019
 * Author: Matt Hart <matthew.hart@linaro.org>
 * Author: Milo Casagrande <milo.casagrande@linaro.org>
 *
 * kernelci dashboard.
 *
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */
define([
    'utils/html'
], function(html) {
    'use strict';
    var gCache,
        gTablesUtils;

    gCache = {};
    gTablesUtils = {};

    /**
     * Function to render the date.
     *
     * @private
     * @param {object} date: The date object.
     * @return {Element} A DOM element.
    **/
    function _dateNode(date) {
        var timeNode;

        if (date) {
            timeNode = html.time(date);
        } else {
            timeNode = html.nonavail();
        }

        return timeNode;
    }

    function _toStatusCacheKey(status, defaults) {
        var objKey;

        objKey = status;
        Object.keys(defaults).forEach(function(key) {
            objKey = objKey + key + defaults[key];
        });

        return objKey;
    }

    /**
     * Create the actual count badge.
     *
     * @return {Element} A DOM element.
    **/
    function _countBadge(data, type, extraClasses, idStart) {
        var classes;
        var iNode;
        var nodeId;
        var spanNode;

        if (idStart && idStart.length > 0) {
            nodeId = idStart;
        } else {
            nodeId = '';
        }

        switch (type) {
            case 'success':
                nodeId = nodeId + 'success-count-' + data;
                classes = ['badge', 'alert-success', 'count-badge'];
                break;
            case 'fail':
                nodeId = nodeId + 'fail-count-' + data;
                classes = ['badge', 'alert-danger', 'count-badge'];
                break;
            case 'unknown':
                nodeId = nodeId + 'unknown-count-' + data;
                classes = ['badge', 'alert-warning', 'count-badge'];
                break;
            case 'total':
                nodeId = nodeId + 'total-count-' + data;
                classes = ['badge', 'count-badge'];
                break;
            default:
                nodeId = nodeId + 'count-' + data;
                classes = ['badge', 'count-badge'];
                break;
        }

        if (extraClasses && extraClasses.length > 0) {
            classes = classes.concat(extraClasses);
        }

        spanNode = document.createElement('span');
        spanNode.id = nodeId;
        spanNode.className = classes.join(' ');

        iNode = document.createElement('i');
        iNode.className = 'fa fa-circle-o-notch fa-spin fa-fw count-content';

        spanNode.appendChild(iNode);

        return spanNode;
    }

    function _statusNode(status, defaults) {
        var tooltipNode;
        tooltipNode = html.tooltip();

        switch (status) {
            case 'BUILD':
                tooltipNode.setAttribute('title', defaults.build);
                tooltipNode.appendChild(html.building());
                break;
            case 'PASS':
                tooltipNode.setAttribute('title', defaults.pass);
                tooltipNode.appendChild(html.success());
                break;
            case 'FAIL':
                tooltipNode.setAttribute('title', defaults.fail);
                tooltipNode.appendChild(html.fail());
                break;
            case 'OFFLINE':
                tooltipNode.setAttribute('title', defaults.offline);
                tooltipNode.appendChild(html.offline());
                break;
            default:
                tooltipNode.setAttribute('title', defaults.default);
                tooltipNode.appendChild(html.unknown());
                break;
        }

        return tooltipNode;
    }

    /**
     * Create the actual count badge.
     *
     * @private
     * @param {String} data: The data value.
     * @param {String} type: The type of the badge: 'success' or 'fail'.
     * @param {Array} extraClasses: Array of classes to add to the badges.
     * @param {String} idStart: Head string for the id of the badge.
     * @return {Element} The badge node as an HTMLElement.
    **/
    gTablesUtils.countBadge = function(data, type, extraClasses, idStart) {
        return _countBadge(data, type, extraClasses, idStart);
    };

    /**
     * Create the total/success/fail/other count badges.
     *
     * @param {Object} settings: An object with the necessary data. Its
     * properties include:
     * - data: The actual data.
     * - href: The href attribute for the link.
     * - extraClasses: Extra CSS classes to add to the badge.
     * - idStart: Head element for the id of the badge.
    **/
    gTablesUtils.countAll = function(settings) {
        var aNode;
        var divNode;
        var failNode;
        var rendered;
        var successNode;
        var totalNode;
        var unknownNode;

        if (settings.type === 'display') {
            divNode = document.createElement('div');

            totalNode = _countBadge(
                settings.data,
                'total', settings.extraClasses, settings.idStart);
            successNode = _countBadge(
                settings.data,
                'success', settings.extraClasses, settings.idStart);
            failNode = _countBadge(
                settings.data,
                'fail', settings.extraClasses, settings.idStart);
            unknownNode = _countBadge(
                settings.data,
                'unknown', settings.extraClasses, settings.idStart);

            if (settings.href) {
                aNode = document.createElement('a');
                aNode.className = 'clean-link';
                aNode.setAttribute('href', settings.href);

                aNode.appendChild(totalNode);
                aNode.appendChild(successNode);
                aNode.appendChild(failNode);
                aNode.appendChild(unknownNode);

                divNode.appendChild(aNode);
            } else {
                divNode.appendChild(totalNode);
                divNode.appendChild(successNode);
                divNode.appendChild(failNode);
                divNode.appendChild(unknownNode);
            }

            rendered = divNode.outerHTML;

            // Remove the nodes.
            totalNode.remove();
            successNode.remove();
            failNode.remove();
            unknownNode.remove();
            if (aNode) {
                aNode.remove();
            }
            divNode.remove();
        } else {
            rendered = null;
        }

        return rendered;
    };

    gTablesUtils.renderTree = function(tree, type, href) {
        var aNode;
        var rendered;

        rendered = tree;
        if (type === 'display') {
            if (href && href.length > 0) {
                aNode = document.createElement('a');
                aNode.className = 'table-link';
                aNode.setAttribute('href', href);
                aNode.appendChild(document.createTextNode(tree));
                rendered = aNode.outerHTML;
                // Remove the node.
                aNode.remove();
            }
        }

        return rendered;
    };

    /**
     * Function to render the date.
     *
     * @param {object} date: The date object.
     * @return {Element} The DOM element.
    **/
    gTablesUtils.dateNode = function(date) {
        return _dateNode(date);
    };

    /**
     * Function to render the date column on a table.
     *
     * @param {object} date: The date object.
     * @param {string} type: The type of the display option.
     * @return {string} The rendered element as a string.
    **/
    gTablesUtils.renderDate = function(date, type) {
        var created;
        var node;
        var rendered;

        if (date) {
            if (type === 'display') {
                node = _dateNode(date).firstElementChild;
                rendered = node.outerHTML;
            } else {
                created = new Date(date.$date);
                rendered = created.toCustomISODate();
            }
        } else {
            rendered = date;
            if (type === 'display') {
                node = html.nonavail().firstElementChild;
                rendered = node.outerHTML;
            }
        }

        return rendered;
    };

    gTablesUtils.statusNode = function(status, defaults) {
        return _statusNode(status, defaults);
    };

    /**
     * Render the status column on a table.
     *
     * @param {string} status: The status value.
     * @param {object} defaults: The default values for the status string.
     * @return {Element} The DOM element.
    **/
    gTablesUtils.renderStatus = function(status, type, defaults) {
        var cacheKey;
        var node;
        var rendered;

        if (type === 'display') {
            cacheKey = _toStatusCacheKey(status, defaults);
            if (gCache.hasOwnProperty(cacheKey)) {
                rendered = gCache[cacheKey];
            } else {
                node = _statusNode(status, defaults);
                rendered = node.outerHTML;
                gCache[cacheKey] = rendered;
                // Remove the node.
                node.remove();
            }
        } else {
            rendered = status;
        }

        return rendered;
    };

    /**
     * Render the details column on a table.
     *
     * @param {String} href: The link location.
     * @param {String} type: The type of the display option.
     * @param {String} title: The title for the tooltip.
    **/
    gTablesUtils.renderDetails = function(href, type, title) {
        var aNode;
        var rendered;
        var tooltipNode;

        rendered = null;
        if (type === 'display') {
            tooltipNode = html.tooltip();

            if (title && title.length > 0) {
                tooltipNode.setAttribute('title', title);
            } else {
                tooltipNode.setAttribute('title', 'More info');
            }

            aNode = document.createElement('a');
            aNode.setAttribute('href', href);

            aNode.appendChild(html.search());
            tooltipNode.appendChild(aNode);

            rendered = tooltipNode.outerHTML;
            // Remove the nodes.
            aNode.remove();
            tooltipNode.remove();
        }

        return rendered;
    };

    /**
     * Render the kernel column on a table.
     *
     * @param {String} href: The link location.
     * @param {String} type: The type of the display option.
     * @param {String} href: The href to associate with the node.
     * @return {String} The HTML string to be rendered by dataTables.
    **/
    gTablesUtils.renderKernel = function(data, type, href) {
        var aNode;
        var rendered;
        var tooltipNode;

        rendered = data;
        if (type === 'display') {
            tooltipNode = html.tooltip();
            tooltipNode.setAttribute('title', data);

            if (href) {
                aNode = document.createElement('a');
                aNode.className = 'table-link';
                aNode.setAttribute('href', href);

                aNode.appendChild(document.createTextNode(data));
                tooltipNode.appendChild(aNode);
            } else {
                tooltipNode.appendChild(document.createTextNode(data));
            }

            rendered = tooltipNode.outerHTML;
            // Remove the nodes.
            if (aNode) {
                aNode.remove();
            }
            tooltipNode.remove();
        }

        return rendered;
    };

    return gTablesUtils;
});
<commit_msg>Fix link error when href is null<commit_after>/*!
 * Copyright (C) Linaro Limited 2015,2016,2017,2019
 * Author: Matt Hart <matthew.hart@linaro.org>
 * Author: Milo Casagrande <milo.casagrande@linaro.org>
 *
 * kernelci dashboard.
 *
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */
define([
    'utils/html'
], function(html) {
    'use strict';
    var gCache,
        gTablesUtils;

    gCache = {};
    gTablesUtils = {};

    /**
     * Function to render the date.
     *
     * @private
     * @param {object} date: The date object.
     * @return {Element} A DOM element.
    **/
    function _dateNode(date) {
        var timeNode;

        if (date) {
            timeNode = html.time(date);
        } else {
            timeNode = html.nonavail();
        }

        return timeNode;
    }

    function _toStatusCacheKey(status, defaults) {
        var objKey;

        objKey = status;
        Object.keys(defaults).forEach(function(key) {
            objKey = objKey + key + defaults[key];
        });

        return objKey;
    }

    /**
     * Create the actual count badge.
     *
     * @return {Element} A DOM element.
    **/
    function _countBadge(data, type, extraClasses, idStart) {
        var classes;
        var iNode;
        var nodeId;
        var spanNode;

        if (idStart && idStart.length > 0) {
            nodeId = idStart;
        } else {
            nodeId = '';
        }

        switch (type) {
            case 'success':
                nodeId = nodeId + 'success-count-' + data;
                classes = ['badge', 'alert-success', 'count-badge'];
                break;
            case 'fail':
                nodeId = nodeId + 'fail-count-' + data;
                classes = ['badge', 'alert-danger', 'count-badge'];
                break;
            case 'unknown':
                nodeId = nodeId + 'unknown-count-' + data;
                classes = ['badge', 'alert-warning', 'count-badge'];
                break;
            case 'total':
                nodeId = nodeId + 'total-count-' + data;
                classes = ['badge', 'count-badge'];
                break;
            default:
                nodeId = nodeId + 'count-' + data;
                classes = ['badge', 'count-badge'];
                break;
        }

        if (extraClasses && extraClasses.length > 0) {
            classes = classes.concat(extraClasses);
        }

        spanNode = document.createElement('span');
        spanNode.id = nodeId;
        spanNode.className = classes.join(' ');

        iNode = document.createElement('i');
        iNode.className = 'fa fa-circle-o-notch fa-spin fa-fw count-content';

        spanNode.appendChild(iNode);

        return spanNode;
    }

    function _statusNode(status, defaults) {
        var tooltipNode;
        tooltipNode = html.tooltip();

        switch (status) {
            case 'BUILD':
                tooltipNode.setAttribute('title', defaults.build);
                tooltipNode.appendChild(html.building());
                break;
            case 'PASS':
                tooltipNode.setAttribute('title', defaults.pass);
                tooltipNode.appendChild(html.success());
                break;
            case 'FAIL':
                tooltipNode.setAttribute('title', defaults.fail);
                tooltipNode.appendChild(html.fail());
                break;
            case 'OFFLINE':
                tooltipNode.setAttribute('title', defaults.offline);
                tooltipNode.appendChild(html.offline());
                break;
            default:
                tooltipNode.setAttribute('title', defaults.default);
                tooltipNode.appendChild(html.unknown());
                break;
        }

        return tooltipNode;
    }

    /**
     * Create the actual count badge.
     *
     * @private
     * @param {String} data: The data value.
     * @param {String} type: The type of the badge: 'success' or 'fail'.
     * @param {Array} extraClasses: Array of classes to add to the badges.
     * @param {String} idStart: Head string for the id of the badge.
     * @return {Element} The badge node as an HTMLElement.
    **/
    gTablesUtils.countBadge = function(data, type, extraClasses, idStart) {
        return _countBadge(data, type, extraClasses, idStart);
    };

    /**
     * Create the total/success/fail/other count badges.
     *
     * @param {Object} settings: An object with the necessary data. Its
     * properties include:
     * - data: The actual data.
     * - href: The href attribute for the link.
     * - extraClasses: Extra CSS classes to add to the badge.
     * - idStart: Head element for the id of the badge.
    **/
    gTablesUtils.countAll = function(settings) {
        var aNode;
        var divNode;
        var failNode;
        var rendered;
        var successNode;
        var totalNode;
        var unknownNode;

        if (settings.type === 'display') {
            divNode = document.createElement('div');

            totalNode = _countBadge(
                settings.data,
                'total', settings.extraClasses, settings.idStart);
            successNode = _countBadge(
                settings.data,
                'success', settings.extraClasses, settings.idStart);
            failNode = _countBadge(
                settings.data,
                'fail', settings.extraClasses, settings.idStart);
            unknownNode = _countBadge(
                settings.data,
                'unknown', settings.extraClasses, settings.idStart);

            if (settings.href) {
                aNode = document.createElement('a');
                aNode.className = 'clean-link';
                aNode.setAttribute('href', settings.href);

                aNode.appendChild(totalNode);
                aNode.appendChild(successNode);
                aNode.appendChild(failNode);
                aNode.appendChild(unknownNode);

                divNode.appendChild(aNode);
            } else {
                divNode.appendChild(totalNode);
                divNode.appendChild(successNode);
                divNode.appendChild(failNode);
                divNode.appendChild(unknownNode);
            }

            rendered = divNode.outerHTML;

            // Remove the nodes.
            totalNode.remove();
            successNode.remove();
            failNode.remove();
            unknownNode.remove();
            if (aNode) {
                aNode.remove();
            }
            divNode.remove();
        } else {
            rendered = null;
        }

        return rendered;
    };

    gTablesUtils.renderTree = function(tree, type, href) {
        var aNode;
        var rendered;

        rendered = tree;
        if (type === 'display') {
            if (href && href.length > 0) {
                aNode = document.createElement('a');
                aNode.className = 'table-link';
                aNode.setAttribute('href', href);
                aNode.appendChild(document.createTextNode(tree));
                rendered = aNode.outerHTML;
                // Remove the node.
                aNode.remove();
            }
        }

        return rendered;
    };

    /**
     * Function to render the date.
     *
     * @param {object} date: The date object.
     * @return {Element} The DOM element.
    **/
    gTablesUtils.dateNode = function(date) {
        return _dateNode(date);
    };

    /**
     * Function to render the date column on a table.
     *
     * @param {object} date: The date object.
     * @param {string} type: The type of the display option.
     * @return {string} The rendered element as a string.
    **/
    gTablesUtils.renderDate = function(date, type) {
        var created;
        var node;
        var rendered;

        if (date) {
            if (type === 'display') {
                node = _dateNode(date).firstElementChild;
                rendered = node.outerHTML;
            } else {
                created = new Date(date.$date);
                rendered = created.toCustomISODate();
            }
        } else {
            rendered = date;
            if (type === 'display') {
                node = html.nonavail().firstElementChild;
                rendered = node.outerHTML;
            }
        }

        return rendered;
    };

    gTablesUtils.statusNode = function(status, defaults) {
        return _statusNode(status, defaults);
    };

    /**
     * Render the status column on a table.
     *
     * @param {string} status: The status value.
     * @param {object} defaults: The default values for the status string.
     * @return {Element} The DOM element.
    **/
    gTablesUtils.renderStatus = function(status, type, defaults) {
        var cacheKey;
        var node;
        var rendered;

        if (type === 'display') {
            cacheKey = _toStatusCacheKey(status, defaults);
            if (gCache.hasOwnProperty(cacheKey)) {
                rendered = gCache[cacheKey];
            } else {
                node = _statusNode(status, defaults);
                rendered = node.outerHTML;
                gCache[cacheKey] = rendered;
                // Remove the node.
                node.remove();
            }
        } else {
            rendered = status;
        }

        return rendered;
    };

    /**
     * Render the details column on a table.
     *
     * @param {String} href: The link location.
     * @param {String} type: The type of the display option.
     * @param {String} title: The title for the tooltip.
    **/
    gTablesUtils.renderDetails = function(href, type, title) {
        var aNode;
        var rendered;
        var tooltipNode;

        rendered = null;
        if (type === 'display') {
            tooltipNode = html.tooltip();

            if (title && title.length > 0) {
                tooltipNode.setAttribute('title', title);
            } else {
                tooltipNode.setAttribute('title', 'More info');
            }

            if (href) {
                aNode = document.createElement('a');
                aNode.setAttribute('href', href);
            } else {
                aNode = document.createElement('span');
            }

            aNode.appendChild(html.search());
            tooltipNode.appendChild(aNode);

            rendered = tooltipNode.outerHTML;
            // Remove the nodes.
            aNode.remove();
            tooltipNode.remove();
        }

        return rendered;
    };

    /**
     * Render the kernel column on a table.
     *
     * @param {String} href: The link location.
     * @param {String} type: The type of the display option.
     * @param {String} href: The href to associate with the node.
     * @return {String} The HTML string to be rendered by dataTables.
    **/
    gTablesUtils.renderKernel = function(data, type, href) {
        var aNode;
        var rendered;
        var tooltipNode;

        rendered = data;
        if (type === 'display') {
            tooltipNode = html.tooltip();
            tooltipNode.setAttribute('title', data);

            if (href) {
                aNode = document.createElement('a');
                aNode.className = 'table-link';
                aNode.setAttribute('href', href);

                aNode.appendChild(document.createTextNode(data));
                tooltipNode.appendChild(aNode);
            } else {
                tooltipNode.appendChild(document.createTextNode(data));
            }

            rendered = tooltipNode.outerHTML;
            // Remove the nodes.
            if (aNode) {
                aNode.remove();
            }
            tooltipNode.remove();
        }

        return rendered;
    };

    return gTablesUtils;
});
<|endoftext|>


<commit_before>/**
 * Created by gaowhen on 15/2/8.
 */
const PI = 3.14

$(document).ready(function () {
  console.log('Hello world ' + PI)
})
<commit_msg>test: jscs fail<commit_after>/**
 * Created by gaowhen on 15/2/8.
 */
const PI = 3.14

$(document).ready(function() {
  console.log('Hello world ' + PI)
})
<|endoftext|>


<commit_before><commit_msg>Added Warning to not to initialize b dependent variables outside setup() or draw()<commit_after><|endoftext|>


<commit_before><commit_msg>Documentation for performance Options cleaned up<commit_after><|endoftext|>