<commit_before>/*
* Copyright 2010-2011 Research In Motion Limited.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
 * @toc {System} System
 * @featureID blackberry.system
 * @namespace The System object allows you to get access to system level functions and attributes of the BlackBerry PlayBook.

 *
 The System object is static; all of its functions and properties are used directly from the object.
 * @example
 * <script type="text/javascript">
 * // See if we are in coverage
 *    if (!blackberry.system.hasDataCoverage()) {
 *        alert("You are not in coverage, we will attempt to send later");
 *    }
 *
 *    // Check if we have GPS capability
 *    if (blackberry.system.hasCapability("location.gps")) {
 *        alert("This PlayBook has a GPS.");
 *    }
 * </script>
 */
blackberry.system ={

    /**
     * @param {String} capability The capability being checked for.
     * @description This method will determine if the BlackBerry PlayBook or the BlackBerry Smartphone device is capable of the given service.

     *
 hasCapability() returns true if the BlackBerry device is capable of the service; false otherwise.

     *
 The supported string values for 'capability' are:
     *
input.keyboard.issuretype (returns if the user is currently using SureType),
     *
input.touch,
     *
media.audio.capture,
     *
media.video.capture,
     *
media.recording,
     *
location.gps,
     *
location.maps,
     *
storage.memorycard (checks for an EXTERNAL SD card only),
     *
network.bluetooth,
     *
network.wlan (WLAN wireless family includes 802.11, 802.11a, 802.11b, 802.11g),
     *
network.3gpp (3GPP wireless family includes GPRS, EDGE, UMTS, GERAN, UTRAN, and GAN),
     *
network.cdma (CDMA wireless family includes CDMA1x and EVDO),
     *
and network.iden.
     * @returns {Boolean} Returns true if the device is capable of the given service.
     * @BB50+
     * @PB10+
     * @RIPPLE
     */
    hasCapability : function(capability){},

    /**
     * @function
     * @description This method returns true so long as the device is connected to any network. This can be used in conjunction with the {@link blackberry.network} property to find out what kind of coverage it is in. On the smartphone this can be used in conjunction with {@link blackberry.system.event.onCoverageChange} to track changes.
     * @returns {Boolean} Returns true if the BlackBerry PlayBook or the BlackBerry Smartphone device has any network interface active, otherwise returns false. Always returns true on the PlayBook simulator. Please note, that on the PlayBook device, there might be a small delay of 2-3 seconds between the time the device connects until the method returns true.
     * @BB50+
     * @PB10+
     * @RIPPLE
     */
    hasDataCoverage : function(){},

    /**
     * @function
     * @description  Set the image that appears as the background of the Home screen on a BlackBerry device.
     * @param {String} uri URI path to an image file that resides in flash memory or a microSD Card.
     * @BB50+
     * @RIPPLE
     */
    setHomeScreenBackground : function(uri){},

    /**
     * @param {String} module The BlackBerry WebWorks namespace or class to check for access. For example blackberry.system, blackberry.app.
     * @description Determines the level of access to the requested module.
     * @returns {Number} The possible return values: 0 - ALLOW 1 - DENY
     * @BB50+
     * @PB10+
     * @RIPPLE
     */
    hasPermission : function(module){},

    /**
     * @description Returns whether USB MassStorage mode is active.
     * @returns {Boolean} Always returns false on the BlackBerry PlayBook since Mass Storage Mode is not supported. All memory is presented as a network share when connected by USB and is not blocked.
     * @BB50+
     * @PB10+
     * @RIPPLE
     */
    isMassStorageActive : function(){},

    /**
     * @uri
     * @BB50+
     * @PB10+
     * @description The objects in hasPermission will always be ALLOW (0). They will correspond to all the entries in the whitelist. If they are not whitelisted, they are omitted from the list. Similarly, all of the objects in hasCapability will be true, otherwise they will be omitted.
     * @returns {JSON of all the properties}
     * {
     *     "data":{
     *         "hasCapability":[
     *             "location.gps",
     *             "media.audio.capture",
     *             "media.video.capture",
     *             "media.recording",
     *             "network.bluetooth",
     *             "network.wlan"
     *         ],
     *         "softwareVersion":"QNX",
     *         "hasPermission":[
     *             "blackberry.invoke",
     *             "blackberry.system",
     *             "blackberry.app",
     *             "blackberry.app.event",
     *             "blackberry.system.event",
     *             "blackberry.ui.dialog",
     *             "blackberry.utils"
     *         ],
     *         "model":100669958,
     *         "hasDataCoverage":true,
     *         "scriptApiVersion":"1.0.0.0",
     *         "isMassStorageActive":false
     *     }
     * }
     * @example
     * <html>
     * <head>
     *     <script type="text/javascript" src="js/jquery-1.4.2.js" ></script>
     *     <script type="text/javascript" src="js/jquery.form.js" ></script>
     *     <script type="text/javascript" src="js/jquery.populate.js" ></script>
     *
     *     <script type="text/javascript">
     *          function getSystemData(){
     *              $.ajax({
     *                  type: "get",
     *                  url: "http://localhost:8472/blackberry/system/get",
     *                  success: function(msg){
     *                      $('#mySystemDiv').populate(JSON.parse(msg).data);
     *                  }
     *               });
     *           }
     *      </script>
     *
     *</head>
     *<body>
     *
     *    <input type="button" onclick="getSystemData();" value="Populate - System"/>
     *    <div id="mySystemDiv">
     *        Software Version: <span id="softwareVersion"></span><br/>
     *        Mass Storage Active: <span id="isMassStorageActive"></span>
     *    </div>
     *
     *</body>
     *</html>
     */
    get: function(){},

    /**
     * @type String
     * @description Returns the model number of the BlackBerry PlayBook or the BlackBerry Smartphone device.
     * @readOnly
     * @BB50+
     * @PB10+
     * @RIPPLE
     */
    model: null,

    /**
     * @type String
     * @description Returns the current version of the WebWorks library being used.
     * @readOnly
     * @BB50+
     * @PB10+
     * @RIPPLE
     */
    scriptApiVersion:null,

    /**
     * @type String
     * @description Returns the current version of the operating system, for example, 1.0.0.0.
     * @readOnly
     * @BB50+
     * @PB10+
     * @RIPPLE
     */
    softwareVersion:null,

    /**
     * @constant
     * @type Number
     * @description Returned by hasPermission() indicating that the module requested is accessible.
     * @default 0
     * @BB50+
     * @PB10+
     * @RIPPLE
     */
    ALLOW : 0,
    /**
     * @constant
     * @type Number
     * @description Returned by hasPermission() indicating that the module is not accessible.
     * @default 1
     * @BB50+
     * @PB10+
     * @RIPPLE
     */
    DENY:1
};
<commit_msg>Update correct return value for scriptApiVersion<commit_after>/*
* Copyright 2010-2011 Research In Motion Limited.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
 * @toc {System} System
 * @featureID blackberry.system
 * @namespace The System object allows you to get access to system level functions and attributes of the BlackBerry PlayBook.

 *
 The System object is static; all of its functions and properties are used directly from the object.
 * @example
 * <script type="text/javascript">
 * // See if we are in coverage
 *    if (!blackberry.system.hasDataCoverage()) {
 *        alert("You are not in coverage, we will attempt to send later");
 *    }
 *
 *    // Check if we have GPS capability
 *    if (blackberry.system.hasCapability("location.gps")) {
 *        alert("This PlayBook has a GPS.");
 *    }
 * </script>
 */
blackberry.system ={

    /**
     * @param {String} capability The capability being checked for.
     * @description This method will determine if the BlackBerry PlayBook or the BlackBerry Smartphone device is capable of the given service.

     *
 hasCapability() returns true if the BlackBerry device is capable of the service; false otherwise.

     *
 The supported string values for 'capability' are:
     *
input.keyboard.issuretype (returns if the user is currently using SureType),
     *
input.touch,
     *
media.audio.capture,
     *
media.video.capture,
     *
media.recording,
     *
location.gps,
     *
location.maps,
     *
storage.memorycard (checks for an EXTERNAL SD card only),
     *
network.bluetooth,
     *
network.wlan (WLAN wireless family includes 802.11, 802.11a, 802.11b, 802.11g),
     *
network.3gpp (3GPP wireless family includes GPRS, EDGE, UMTS, GERAN, UTRAN, and GAN),
     *
network.cdma (CDMA wireless family includes CDMA1x and EVDO),
     *
and network.iden.
     * @returns {Boolean} Returns true if the device is capable of the given service.
     * @BB50+
     * @PB10+
     * @RIPPLE
     */
    hasCapability : function(capability){},

    /**
     * @function
     * @description This method returns true so long as the device is connected to any network. This can be used in conjunction with the {@link blackberry.network} property to find out what kind of coverage it is in. On the smartphone this can be used in conjunction with {@link blackberry.system.event.onCoverageChange} to track changes.
     * @returns {Boolean} Returns true if the BlackBerry PlayBook or the BlackBerry Smartphone device has any network interface active, otherwise returns false. Always returns true on the PlayBook simulator. Please note, that on the PlayBook device, there might be a small delay of 2-3 seconds between the time the device connects until the method returns true.
     * @BB50+
     * @PB10+
     * @RIPPLE
     */
    hasDataCoverage : function(){},

    /**
     * @function
     * @description  Set the image that appears as the background of the Home screen on a BlackBerry device.
     * @param {String} uri URI path to an image file that resides in flash memory or a microSD Card.
     * @BB50+
     * @RIPPLE
     */
    setHomeScreenBackground : function(uri){},

    /**
     * @param {String} module The BlackBerry WebWorks namespace or class to check for access. For example blackberry.system, blackberry.app.
     * @description Determines the level of access to the requested module.
     * @returns {Number} The possible return values: 0 - ALLOW 1 - DENY
     * @BB50+
     * @PB10+
     * @RIPPLE
     */
    hasPermission : function(module){},

    /**
     * @description Returns whether USB MassStorage mode is active.
     * @returns {Boolean} Always returns false on the BlackBerry PlayBook since Mass Storage Mode is not supported. All memory is presented as a network share when connected by USB and is not blocked.
     * @BB50+
     * @PB10+
     * @RIPPLE
     */
    isMassStorageActive : function(){},

    /**
     * @uri
     * @BB50+
     * @PB10+
     * @description The objects in hasPermission will always be ALLOW (0). They will correspond to all the entries in the whitelist. If they are not whitelisted, they are omitted from the list. Similarly, all of the objects in hasCapability will be true, otherwise they will be omitted.
     * @returns {JSON of all the properties}
     * {
     *     "data":{
     *         "hasCapability":[
     *             "location.gps",
     *             "media.audio.capture",
     *             "media.video.capture",
     *             "media.recording",
     *             "network.bluetooth",
     *             "network.wlan"
     *         ],
     *         "softwareVersion":"QNX",
     *         "hasPermission":[
     *             "blackberry.invoke",
     *             "blackberry.system",
     *             "blackberry.app",
     *             "blackberry.app.event",
     *             "blackberry.system.event",
     *             "blackberry.ui.dialog",
     *             "blackberry.utils"
     *         ],
     *         "model":100669958,
     *         "hasDataCoverage":true,
     *         "scriptApiVersion":"1.0.0.0",
     *         "isMassStorageActive":false
     *     }
     * }
     * @example
     * <html>
     * <head>
     *     <script type="text/javascript" src="js/jquery-1.4.2.js" ></script>
     *     <script type="text/javascript" src="js/jquery.form.js" ></script>
     *     <script type="text/javascript" src="js/jquery.populate.js" ></script>
     *
     *     <script type="text/javascript">
     *          function getSystemData(){
     *              $.ajax({
     *                  type: "get",
     *                  url: "http://localhost:8472/blackberry/system/get",
     *                  success: function(msg){
     *                      $('#mySystemDiv').populate(JSON.parse(msg).data);
     *                  }
     *               });
     *           }
     *      </script>
     *
     *</head>
     *<body>
     *
     *    <input type="button" onclick="getSystemData();" value="Populate - System"/>
     *    <div id="mySystemDiv">
     *        Software Version: <span id="softwareVersion"></span><br/>
     *        Mass Storage Active: <span id="isMassStorageActive"></span>
     *    </div>
     *
     *</body>
     *</html>
     */
    get: function(){},

    /**
     * @type String
     * @description Returns the model number of the BlackBerry PlayBook or the BlackBerry Smartphone device.
     * @readOnly
     * @BB50+
     * @PB10+
     * @RIPPLE
     */
    model: null,

    /**
     * @type String
     * @description Returns the current version of the operating system, for example, 1.0.0.0.
     * @readOnly
     * @BB50+
     * @PB10+
     * @RIPPLE
     */
    scriptApiVersion:null,

    /**
     * @type String
     * @description Returns the current version of the operating system, for example, 1.0.0.0.
     * @readOnly
     * @BB50+
     * @PB10+
     * @RIPPLE
     */
    softwareVersion:null,

    /**
     * @constant
     * @type Number
     * @description Returned by hasPermission() indicating that the module requested is accessible.
     * @default 0
     * @BB50+
     * @PB10+
     * @RIPPLE
     */
    ALLOW : 0,
    /**
     * @constant
     * @type Number
     * @description Returned by hasPermission() indicating that the module is not accessible.
     * @default 1
     * @BB50+
     * @PB10+
     * @RIPPLE
     */
    DENY:1
};
<|endoftext|>


<commit_before>var path						= require('path'),
		hound						= require('hound'),
		exif						= require('exif2'),
		http						= require('http'),
		MediaController	= require('./media');

/**
	* MediaTasks tasks watch the media directory for new, changed, or deleted images
	* and videos. It reads exif data from new media, converts the data into
	* something usable, adds it to the database, and passes the passes it to the
	* media controller for processing. Deleted media is removed from the database.
	*
	* @namespace MediaTasks
	*/

(function () {
	var MediaTasks;

	MediaTasks = (function (MediaTasks) {
		'use strict';

		/**
			* Watches specified directory for new, changed, or deleted media and
			* calls the appropriate funtions to handle them.
			*
			* @param {string} directory The directory to watch for changes.
			* @param {object} watcher The object returned from a call to hound.watch().
			* @param {function} createCallback The function to run when a new file is created.
			* @param {function} changeCallback The function to run when a file is modified.
			* @param {function} deleteCallback The function to run when a file is deleted.
			*
			* @memberof MediaTasks
			* @public
			*/
		MediaTasks.watchDirectory = function (directory, watcher, createCallback, changeCallback, deleteCallback) {
			createCallback = createCallback || _readExif;
			deleteCallback = deleteCallback || _deleteMedia;
			watcher = watcher || hound.watch(directory);

			watcher.on('create', function(file, stats) {
				createCallback(file);
			});

			watcher.on('change', function(file, stats) {
				if (changeCallback !== undefined) {
					changeCallback(file);
				}
			});

			watcher.on('delete', function(file) {
				if (deleteCallback !== undefined) {
					deleteCallback(file);
				}
			});
		};

		/**
			* Reads exif data from new media and passes it to the _prepareData()
			* function.
			*
			* @param {string} file The file to read exif data from.
			*
			* @memberof MediaTasks
			*/
		function _readExif (file) {
			exif(file, function (err, obj) {
				if (err) throw err;

				_prepareData(obj);
			});
		}

		/**
			* Parses exif data from readExit() and prepares it so it is ready to be
			* submitted to the database with _submitMedia().
			*
			* @param {object} data The data from the new media.
			*
			* @memberof MediaTasks
			*/
		function _prepareData (data) {
			var preparedData = {},
					createDate,
					file,
					lastindex,
					sizearray;

			// Convert date into a string usable by JavaScript's new Date()
			if (data['create date']) {
				createDate = data['create date'].split(' ');
				createDate[0] = createDate[0].replace(/[:]/g, '-');
				createDate = createDate.join('T');
			}

			// Set up file name to be split into filename and extension
			file = data['file name'];
			lastindex = file.lastIndexOf('.');

			// Creates an array for width and height
			sizearray = (data['image size']) ? data['image size'].split('x') : [];

			preparedData.extension = file.substr(lastindex + 1);
			preparedData.filename = file.substr(0, file.length - preparedData.extension.length - 1);
			preparedData.title = preparedData.filename;
			preparedData.tags = [];
			preparedData.date = new Date(createDate);
			preparedData.description = '';
			preparedData.dimensions = data['image size'];
			preparedData.width = Number(sizearray[0]);
			preparedData.height = Number(sizearray[1]);
			preparedData.layout = (preparedData.width > preparedData.height) ? 'landscape' : 'portrait';

			if (preparedData.extension.match(/^(jpg|jpeg|png|gif)$/)) {
				preparedData.type = 'photo';
			}
			else if (preparedData.extension.match(/^(mp4|m4v|mov|wmv|avi|mpg|ogv|3gp|3g2|webm)$/)) {
				preparedData.type = 'video';
			}
			else {
				preparedData.type = 'not allowed';
			}

			_submitMedia(preparedData);
		}

		/**
			* Passes the data from _prepareData() to the API that submits it to the
			* database via an HTTP request. Then passes the data to _optimizeImage()
			* or _optimizeVideo() to prepare the media for the web.
			*
			* @param {object} preparedData The data passed from perpareData().
			* @param {string} host The hostname for the HTTP call.
			* @param {string} path The path for the HTTP call.
			* @param {number} port The port number for the HTTP call.
			*
			* @memberof MediaTasks
			*/
		function _submitMedia (preparedData, host, path, port) {
			var options,
					req,
					data = JSON.stringify(preparedData),
					callback;

			callback = (preparedData.type === 'video') ? _optimizeVideo : _optimizeImage;

			host = host || 'localhost';
			path = (preparedData.type === 'video') ? '/api/v1/videos/' + encodeURIComponent(preparedData.filename) : '/api/v1/photos/' + encodeURIComponent(preparedData.filename);
			port = port || 8080;

			options = {
				host: host,
				path: path,
				port: port,
				method: 'POST',
				headers: {
					'Content-Type': 'application/json'
				}
			};

			req = http.request(options, function (response) {
				response.on('data', function (chunk) {
					// A piece of data has been recieved
				});

				response.on('end', function () {
					// Response has been recieved
					if (callback) {
						callback(preparedData);
					}
				});
			});

			req.write(data);
			req.end();
		}

		/**
			* Converts full resolution image to web optimized versions to be used on
			* on the website and other applications.
			*
			* @param {object} data The data passed from _submitMedia().
			* @param {string} imagePath The path of the full resolution image.
			* @param {string} destPath The path where new images will be placed.
			*
			* @memberof MediaTasks
			*/
		function _optimizeImage (data, imagePath, destPath) {
			imagePath = imagePath || __dirname + '/../../public/media/photos/';
			destPath = destPath || __dirname + '/../../public/images/';

			var orig = imagePath + data.filename + '.' + data.extension;

			MediaController.makeImages(orig, destPath, data.filename, data.extension);
		}

		/**
			* On delete of media from the media directory, this function will delete
			* the optimized media files and send a call to the API to delete the item
			* from the database.
			*
			* @param {string} file The file to be deleted.
			* @param {string} host The hostname for the HTTP call.
			* @param {string} path The path for the HTTP call.
			* @param {number} port The port number for the HTTP call.
			*
			* @memberof MediaTasks
			*/
		function _deleteMedia (file, host, path, port) {
			var options,
					req,
					filename = '',
					extension = '';

			filename = file.substring(file.lastIndexOf('/') + 1);
			filename = filename.substring(0, filename.length - 4);
			extension = file.slice(-3);

			if (file.indexOf('/photos/') !== -1) {
				var imagePath = __dirname + '/../../public/images/';

				MediaController.removeMedia(imagePath + filename + '.thumb.' + extension);
				MediaController.removeMedia(imagePath + filename + '.mob.' + extension);
				MediaController.removeMedia(imagePath + filename + '.desk.' + extension);
				MediaController.removeMedia(imagePath + filename + '.large.' + extension);
				MediaController.removeMedia(imagePath + filename + '.bg.' + extension);
			}

			host = host || 'localhost';
			path = (file.indexOf('/photos/') === -1) ? '/api/v1/videos/' + encodeURIComponent(filename) : '/api/v1/photos/' + encodeURIComponent(filename);
			port = port || 8080;

			options = {
				host: host,
				path: path,
				port: port,
				method: 'DELETE',
				headers: {
					'Content-Type': 'application/json'
				}
			};

			http.request(options, function (response) {
				response.on('data', function (chunk) {
					// A piece of data has been recieved
				});

				response.on('end', function () {
					// Response has been recieved
					console.log(filename + ' deleted.');
				});
			}).end();
		}

		return MediaTasks;
	})({});

	module.exports = MediaTasks;
})();<commit_msg>Adding console.log to check directory that is being watched by tasks.js<commit_after>var path						= require('path'),
		hound						= require('hound'),
		exif						= require('exif2'),
		http						= require('http'),
		MediaController	= require('./media');

/**
	* MediaTasks tasks watch the media directory for new, changed, or deleted images
	* and videos. It reads exif data from new media, converts the data into
	* something usable, adds it to the database, and passes the passes it to the
	* media controller for processing. Deleted media is removed from the database.
	*
	* @namespace MediaTasks
	*/

(function () {
	var MediaTasks;

	MediaTasks = (function (MediaTasks) {
		'use strict';

		/**
			* Watches specified directory for new, changed, or deleted media and
			* calls the appropriate funtions to handle them.
			*
			* @param {string} directory The directory to watch for changes.
			* @param {object} watcher The object returned from a call to hound.watch().
			* @param {function} createCallback The function to run when a new file is created.
			* @param {function} changeCallback The function to run when a file is modified.
			* @param {function} deleteCallback The function to run when a file is deleted.
			*
			* @memberof MediaTasks
			* @public
			*/
		MediaTasks.watchDirectory = function (directory, watcher, createCallback, changeCallback, deleteCallback) {
			console.log(directory);
			createCallback = createCallback || _readExif;
			deleteCallback = deleteCallback || _deleteMedia;
			watcher = watcher || hound.watch(directory);

			watcher.on('create', function(file, stats) {
				createCallback(file);
			});

			watcher.on('change', function(file, stats) {
				if (changeCallback !== undefined) {
					changeCallback(file);
				}
			});

			watcher.on('delete', function(file) {
				if (deleteCallback !== undefined) {
					deleteCallback(file);
				}
			});
		};

		/**
			* Reads exif data from new media and passes it to the _prepareData()
			* function.
			*
			* @param {string} file The file to read exif data from.
			*
			* @memberof MediaTasks
			*/
		function _readExif (file) {
			exif(file, function (err, obj) {
				if (err) throw err;

				_prepareData(obj);
			});
		}

		/**
			* Parses exif data from readExit() and prepares it so it is ready to be
			* submitted to the database with _submitMedia().
			*
			* @param {object} data The data from the new media.
			*
			* @memberof MediaTasks
			*/
		function _prepareData (data) {
			var preparedData = {},
					createDate,
					file,
					lastindex,
					sizearray;

			// Convert date into a string usable by JavaScript's new Date()
			if (data['create date']) {
				createDate = data['create date'].split(' ');
				createDate[0] = createDate[0].replace(/[:]/g, '-');
				createDate = createDate.join('T');
			}

			// Set up file name to be split into filename and extension
			file = data['file name'];
			lastindex = file.lastIndexOf('.');

			// Creates an array for width and height
			sizearray = (data['image size']) ? data['image size'].split('x') : [];

			preparedData.extension = file.substr(lastindex + 1);
			preparedData.filename = file.substr(0, file.length - preparedData.extension.length - 1);
			preparedData.title = preparedData.filename;
			preparedData.tags = [];
			preparedData.date = new Date(createDate);
			preparedData.description = '';
			preparedData.dimensions = data['image size'];
			preparedData.width = Number(sizearray[0]);
			preparedData.height = Number(sizearray[1]);
			preparedData.layout = (preparedData.width > preparedData.height) ? 'landscape' : 'portrait';

			if (preparedData.extension.match(/^(jpg|jpeg|png|gif)$/)) {
				preparedData.type = 'photo';
			}
			else if (preparedData.extension.match(/^(mp4|m4v|mov|wmv|avi|mpg|ogv|3gp|3g2|webm)$/)) {
				preparedData.type = 'video';
			}
			else {
				preparedData.type = 'not allowed';
			}

			_submitMedia(preparedData);
		}

		/**
			* Passes the data from _prepareData() to the API that submits it to the
			* database via an HTTP request. Then passes the data to _optimizeImage()
			* or _optimizeVideo() to prepare the media for the web.
			*
			* @param {object} preparedData The data passed from perpareData().
			* @param {string} host The hostname for the HTTP call.
			* @param {string} path The path for the HTTP call.
			* @param {number} port The port number for the HTTP call.
			*
			* @memberof MediaTasks
			*/
		function _submitMedia (preparedData, host, path, port) {
			var options,
					req,
					data = JSON.stringify(preparedData),
					callback;

			callback = (preparedData.type === 'video') ? _optimizeVideo : _optimizeImage;

			host = host || 'localhost';
			path = (preparedData.type === 'video') ? '/api/v1/videos/' + encodeURIComponent(preparedData.filename) : '/api/v1/photos/' + encodeURIComponent(preparedData.filename);
			port = port || 8080;

			options = {
				host: host,
				path: path,
				port: port,
				method: 'POST',
				headers: {
					'Content-Type': 'application/json'
				}
			};

			req = http.request(options, function (response) {
				response.on('data', function (chunk) {
					// A piece of data has been recieved
				});

				response.on('end', function () {
					// Response has been recieved
					if (callback) {
						callback(preparedData);
					}
				});
			});

			req.write(data);
			req.end();
		}

		/**
			* Converts full resolution image to web optimized versions to be used on
			* on the website and other applications.
			*
			* @param {object} data The data passed from _submitMedia().
			* @param {string} imagePath The path of the full resolution image.
			* @param {string} destPath The path where new images will be placed.
			*
			* @memberof MediaTasks
			*/
		function _optimizeImage (data, imagePath, destPath) {
			imagePath = imagePath || __dirname + '/../../public/media/photos/';
			destPath = destPath || __dirname + '/../../public/images/';

			var orig = imagePath + data.filename + '.' + data.extension;

			MediaController.makeImages(orig, destPath, data.filename, data.extension);
		}

		/**
			* On delete of media from the media directory, this function will delete
			* the optimized media files and send a call to the API to delete the item
			* from the database.
			*
			* @param {string} file The file to be deleted.
			* @param {string} host The hostname for the HTTP call.
			* @param {string} path The path for the HTTP call.
			* @param {number} port The port number for the HTTP call.
			*
			* @memberof MediaTasks
			*/
		function _deleteMedia (file, host, path, port) {
			var options,
					req,
					filename = '',
					extension = '';

			filename = file.substring(file.lastIndexOf('/') + 1);
			filename = filename.substring(0, filename.length - 4);
			extension = file.slice(-3);

			if (file.indexOf('/photos/') !== -1) {
				var imagePath = __dirname + '/../../public/images/';

				MediaController.removeMedia(imagePath + filename + '.thumb.' + extension);
				MediaController.removeMedia(imagePath + filename + '.mob.' + extension);
				MediaController.removeMedia(imagePath + filename + '.desk.' + extension);
				MediaController.removeMedia(imagePath + filename + '.large.' + extension);
				MediaController.removeMedia(imagePath + filename + '.bg.' + extension);
			}

			host = host || 'localhost';
			path = (file.indexOf('/photos/') === -1) ? '/api/v1/videos/' + encodeURIComponent(filename) : '/api/v1/photos/' + encodeURIComponent(filename);
			port = port || 8080;

			options = {
				host: host,
				path: path,
				port: port,
				method: 'DELETE',
				headers: {
					'Content-Type': 'application/json'
				}
			};

			http.request(options, function (response) {
				response.on('data', function (chunk) {
					// A piece of data has been recieved
				});

				response.on('end', function () {
					// Response has been recieved
					console.log(filename + ' deleted.');
				});
			}).end();
		}

		return MediaTasks;
	})({});

	module.exports = MediaTasks;
})();<|endoftext|>


<commit_before>define(function() {

  'use strict';

  var rx_escape = '\\\\(?:u(?:\\{[^\\}]+\\}|....)?|x..|c.|[^cux])';
  var rx_set = '\\[(?:[^\\\\\\]]+|' + rx_escape + ')+\\]';
  var rx_singleton = rx_escape + '|' + rx_set + '|[^\\\\\\[\\]\\(\\)\\{\\}\\*\\?\\+\\$\\^\\|]';
  var rx_special = '\\((?:\\?[=!:])?|\\)|[\\*\\+\\?]\\??|\\{[^\\}]*\\}|\\$|\\^|\\|';

  var rx = new RegExp('(' + rx_singleton + ')|(' + rx_special + ')', 'g');

  function BytePattern(source) {
    if (source instanceof RegExp) source = source.source;
    else if (typeof source !== 'string') {
      throw new TypeError('source must be string or RegExp');
    }
    rx.lastIndex = 0;
    var nextIndex = 0;
    var context = [':'];
    var contextStack = [];
    for (var match = rx.exec(source); match; match = rx.exec(source)) {
      if (match.index > nextIndex) {
        throw new Error('invalid pattern: ' + source);
      }
      nextIndex = rx.lastIndex;
      if (typeof match[1] === 'string') {
        // character set or block of literal character
        var ch = match[1];
        context.push(ch);
      }
      else {
        // special character (grouping, repeat, etc.)
        var special = match[2];
        switch (special[0]) {
          case '(':
            contextStack.push(context);
            var newContext = [special[2] || special];
            context.push(newContext);
            context = newContext;
            break;
          case ')':
            context = contextStack.pop();
            break;
          case '*':
          case '?':
          case '+':
            context.push([special, context.pop()]);
            break;
          case '{':
            var range = special.match(/^\{\s*(\d+)\s*(,\s*(\d+))?\s*\}$/);
            if (!range) throw new Error('invalid pattern: ' + source);
            var min = +range[1];
            var max = (typeof range[2] === 'string') ? +(range[3] || Infinity) : min;
            context.push(['{', min, max, context.pop()]);
            break;
          case '|':
            if (contextStack.length > 0 && contextStack[contextStack.length-1][0] === '|') {
              contextStack[contextStack.length-1].push(context = [':']);
            }
            else {
              var newContext = context.splice(0, context.length, '|');
              context[1] = newContext;
              contextStack.push(context);
              context = newContext;
            }
            break;
        }
      }
    }
    if (nextIndex < source.length) {
      throw new Error('invalid pattern: ' + source);
    }
    if (context.length === 2 && context[0] === ':') context = context[1];
    this.tree = context;
  }

  return BytePattern;

});
<commit_msg>Recursively remove redundant contexts<commit_after>define(function() {

  'use strict';

  var rx_escape = '\\\\(?:u(?:\\{[^\\}]+\\}|....)?|x..|c.|[^cux])';
  var rx_set = '\\[(?:[^\\\\\\]]+|' + rx_escape + ')+\\]';
  var rx_singleton = rx_escape + '|' + rx_set + '|[^\\\\\\[\\]\\(\\)\\{\\}\\*\\?\\+\\$\\^\\|]';
  var rx_special = '\\((?:\\?[=!:])?|\\)|[\\*\\+\\?]\\??|\\{[^\\}]*\\}|\\$|\\^|\\|';

  var rx = new RegExp('(' + rx_singleton + ')|(' + rx_special + ')', 'g');

  function BytePattern(source) {
    if (source instanceof RegExp) source = source.source;
    else if (typeof source !== 'string') {
      throw new TypeError('source must be string or RegExp');
    }
    rx.lastIndex = 0;
    var nextIndex = 0;
    var context = [':'];
    var contextStack = [];
    for (var match = rx.exec(source); match; match = rx.exec(source)) {
      if (match.index > nextIndex) {
        throw new Error('invalid pattern: ' + source);
      }
      nextIndex = rx.lastIndex;
      if (typeof match[1] === 'string') {
        // character set or block of literal character
        var ch = match[1];
        context.push(ch);
      }
      else {
        // special character (grouping, repeat, etc.)
        var special = match[2];
        switch (special[0]) {
          case '(':
            contextStack.push(context);
            var newContext = [special[2] || special];
            context.push(newContext);
            context = newContext;
            break;
          case ')':
            context = contextStack.pop();
            break;
          case '*':
          case '?':
          case '+':
            context.push([special, context.pop()]);
            break;
          case '{':
            var range = special.match(/^\{\s*(\d+)\s*(,\s*(\d+))?\s*\}$/);
            if (!range) throw new Error('invalid pattern: ' + source);
            var min = +range[1];
            var max = (typeof range[2] === 'string') ? +(range[3] || Infinity) : min;
            context.push(['{', min, max, context.pop()]);
            break;
          case '|':
            if (contextStack.length > 0 && contextStack[contextStack.length-1][0] === '|') {
              contextStack[contextStack.length-1].push(context = [':']);
            }
            else {
              var newContext = context.splice(0, context.length, '|');
              context[1] = newContext;
              contextStack.push(context);
              context = newContext;
            }
            break;
        }
      }
    }
    if (nextIndex < source.length) {
      throw new Error('invalid pattern: ' + source);
    }
    while (context.length === 2 && context[0] === ':') context = context[1];
    this.tree = context;
  }

  return BytePattern;

});
<|endoftext|>


<commit_before>var $graphic;
var bar_gap = 10;
var bar_height = 25;
var graphic_aspect_width = 16;
var graphic_aspect_height = 9;
var mobile_threshold = 625;
var pymChild = null;

var colors = {
    'red1': '#6C2315', 'red2': '#A23520', 'red3': '#D8472B', 'red4': '#E27560', 'red5': '#ECA395', 'red6': '#F5D1CA',
    'orange1': '#714616', 'orange2': '#AA6A21', 'orange3': '#E38D2C', 'orange4': '#EAAA61', 'orange5': '#F1C696', 'orange6': '#F8E2CA',
    'yellow1': '#77631B', 'yellow2': '#B39429', 'yellow3': '#EFC637', 'yellow4': '#F3D469', 'yellow5': '#F7E39B', 'yellow6': '#FBF1CD',
    'teal1': '#0B403F', 'teal2': '#11605E', 'teal3': '#17807E', 'teal4': '#51A09E', 'teal5': '#8BC0BF', 'teal6': '#C5DFDF',
    'blue1': '#28556F', 'blue2': '#3D7FA6', 'blue3': '#51AADE', 'blue4': '#7DBFE6', 'blue5': '#A8D5EF', 'blue6': '#D3EAF7'
};

var graphic_data_race = [
    { "label": "Black", "deaths": 91.1 },
    { "label": "Hispanic", "deaths": 4.3 },
    { "label": "White", "deaths": 3.2 },
    { "label": "Other", "deaths": 1.4 }
];

var graphic_data_age = [
    { "label": "0-9", "deaths": 2.6 },
    { "label": "10-19", "deaths": 14.2 },
    { "label": "20-29", "deaths": 39.3 },
    { "label": "30-39", "deaths": 24.6 },
    { "label": "40-49", "deaths": 11.3 },
    { "label": "50-59", "deaths": 5.8 },
    { "label": "60-69", "deaths": 1.4 },
    { "label": "70+", "deaths": 0.9 }
];

var labels = {
    "race": "Murders by race, 2012-13",
    "age": "Murders by age, 2012-13"
};

/*
 * Render the graphic
 */
function draw_graphic(width) {
    if (Modernizr.svg) {
        // clear out existing graphics
        $graphic.empty();

        // load in new graphics
        render_chart(graphic_data_race, 'race', width)
        render_chart(graphic_data_age, 'age', width)
    }
}
function render_chart(data, id, container_width) {
    var graphic_data = data;
    var is_mobile = false;
    var last_data_point = graphic_data.length - 1;
    var margin = { top: 10, right: 10, bottom: 35, left: 30 };
    var num_bars = graphic_data.length;
    var num_ticks = 4;
    var width = container_width;

    if (width <= mobile_threshold) {
        is_mobile = true;
        width = container_width - margin.left - margin.right;
    } else {
        width = Math.floor(((container_width - 44) / 2) - margin.left - margin.right);
    }

    var height = Math.ceil((width * graphic_aspect_height) / graphic_aspect_width) - margin.top - margin.bottom;

    var x = d3.scale.ordinal()
        .rangeRoundBands([0, width], .1)
        .domain(graphic_data.map(function(d) { return d.label; }));

    var y = d3.scale.linear()
        .range([height, 0])
        .domain([0, 100]);

    var xAxis = d3.svg.axis()
        .scale(x)
        .orient('bottom');

    var yAxis = d3.svg.axis()
        .scale(y)
        .orient('left')
        .ticks(num_ticks);

    var y_axis_grid = function() { return yAxis; }

    var container = d3.select('#graphic').append('div')
        .attr('id', 'graph-' + id)
        .attr('class', 'graph')
        .attr('style', function(d) {
            if (!is_mobile) {
                return 'width: ' + (width + margin.left + margin.right) + 'px';
            }
        });

    var headline = container.append('h3')
            .text(labels[id]);

    var svg = container.append('svg')
        .attr('width', width + margin.left + margin.right)
        .attr('height', height + margin.top + margin.bottom)
        .append('g')
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    svg.append('g')
        .attr('class', 'x axis')
        .attr('transform', 'translate(0,' + height + ')')
        .call(xAxis);

    svg.append('g')
        .attr('class', 'y axis')
        .call(yAxis);

    svg.append('g')
        .attr('class', 'y grid')
        .call(y_axis_grid()
            .tickSize(-width, 0)
            .tickFormat('')
        );

    svg.append('g')
        .attr('class', 'bars')
        .selectAll('rect')
            .data(graphic_data)
        .enter().append('rect')
            .attr("x", function(d) { return x(d.label); })
            .attr("y", function(d) { return y(d.deaths); })
            .attr("width", x.rangeBand())
            .attr("height", function(d){ return height - y(d.deaths); })
            .attr('class', function(d, i) {
                return 'bar bar-' + i;
            });

    svg.append('g')
        .attr('class', 'value')
        .selectAll('text')
            .data(graphic_data)
        .enter().append('text')
            .attr('x', function(d, i) {
                return x(d.label) + (x.rangeBand() / 2);
            })
            .attr('y', function(d) {
                return y(d.deaths) - 6;
            })
            .attr('text-anchor', 'middle')
            .text(function(d) { return d.deaths + '%' });

    if (pymChild) {
        pymChild.sendHeightToParent();
    }
}

/*
 * NB: Use window.load instead of document.ready
 * to ensure all images have loaded
 */
$(window).load(function() {
    $graphic = $('#graphic');

    if (Modernizr.svg) {
        // setup pym
        pymChild = new pym.Child({
            renderCallback: draw_graphic
        });
    } else {
        pymChild = new pym.Child();
    }
})
<commit_msg>labelling adjustments<commit_after>var $graphic;
var bar_gap = 10;
var bar_height = 25;
var graphic_aspect_width = 16;
var graphic_aspect_height = 9;
var mobile_threshold = 625;
var pymChild = null;

var colors = {
    'red1': '#6C2315', 'red2': '#A23520', 'red3': '#D8472B', 'red4': '#E27560', 'red5': '#ECA395', 'red6': '#F5D1CA',
    'orange1': '#714616', 'orange2': '#AA6A21', 'orange3': '#E38D2C', 'orange4': '#EAAA61', 'orange5': '#F1C696', 'orange6': '#F8E2CA',
    'yellow1': '#77631B', 'yellow2': '#B39429', 'yellow3': '#EFC637', 'yellow4': '#F3D469', 'yellow5': '#F7E39B', 'yellow6': '#FBF1CD',
    'teal1': '#0B403F', 'teal2': '#11605E', 'teal3': '#17807E', 'teal4': '#51A09E', 'teal5': '#8BC0BF', 'teal6': '#C5DFDF',
    'blue1': '#28556F', 'blue2': '#3D7FA6', 'blue3': '#51AADE', 'blue4': '#7DBFE6', 'blue5': '#A8D5EF', 'blue6': '#D3EAF7'
};

var graphic_data_race = [
    { "label": "Black", "deaths": 91.1 },
    { "label": "Hispanic", "deaths": 4.3 },
    { "label": "White", "deaths": 3.2 },
    { "label": "Other", "deaths": 1.4 }
];

var graphic_data_age = [
    { "label": "0-9", "deaths": 2.6 },
    { "label": "10-19", "deaths": 14.2 },
    { "label": "20-29", "deaths": 39.3 },
    { "label": "30-39", "deaths": 24.6 },
    { "label": "40-49", "deaths": 11.3 },
    { "label": "50-59", "deaths": 5.8 },
    { "label": "60-69", "deaths": 1.4 },
    { "label": "70+", "deaths": 0.9 }
];

var labels = {
    "race": "Share Of Murders By Race, 2012-13",
    "age": "Share Of Murders By Age Group, 2012-13"
};

/*
 * Render the graphic
 */
function draw_graphic(width) {
    if (Modernizr.svg) {
        // clear out existing graphics
        $graphic.empty();

        // load in new graphics
        render_chart(graphic_data_race, 'race', width)
        render_chart(graphic_data_age, 'age', width)
    }
}
function render_chart(data, id, container_width) {
    var graphic_data = data;
    var is_mobile = false;
    var last_data_point = graphic_data.length - 1;
    var margin = { top: 10, right: 10, bottom: 35, left: 40 };
    var num_bars = graphic_data.length;
    var num_ticks = 4;
    var width = container_width;

    if (width <= mobile_threshold) {
        is_mobile = true;
        width = container_width - margin.left - margin.right;
    } else {
        width = Math.floor(((container_width - 44) / 2) - margin.left - margin.right);
    }

    var height = Math.ceil((width * graphic_aspect_height) / graphic_aspect_width) - margin.top - margin.bottom;

    var x = d3.scale.ordinal()
        .rangeRoundBands([0, width], .1)
        .domain(graphic_data.map(function(d) { return d.label; }));

    var y = d3.scale.linear()
        .range([height, 0])
        .domain([0, 100]);

    var xAxis = d3.svg.axis()
        .scale(x)
        .orient('bottom');

    var yAxis = d3.svg.axis()
        .scale(y)
        .orient('left')
        .ticks(num_ticks)
        .tickFormat(function(d) {
            return d + '%';
        });

    var y_axis_grid = function() { return yAxis; }

    var container = d3.select('#graphic').append('div')
        .attr('id', 'graph-' + id)
        .attr('class', 'graph')
        .attr('style', function(d) {
            if (!is_mobile) {
                return 'width: ' + (width + margin.left + margin.right) + 'px';
            }
        });

    var headline = container.append('h3')
            .text(labels[id]);

    var svg = container.append('svg')
        .attr('width', width + margin.left + margin.right)
        .attr('height', height + margin.top + margin.bottom)
        .append('g')
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    svg.append('g')
        .attr('class', 'x axis')
        .attr('transform', 'translate(0,' + height + ')')
        .call(xAxis);

    svg.append('g')
        .attr('class', 'y axis')
        .call(yAxis);

    svg.append('g')
        .attr('class', 'y grid')
        .call(y_axis_grid()
            .tickSize(-width, 0)
            .tickFormat('')
        );

    svg.append('g')
        .attr('class', 'bars')
        .selectAll('rect')
            .data(graphic_data)
        .enter().append('rect')
            .attr("x", function(d) { return x(d.label); })
            .attr("y", function(d) { return y(d.deaths); })
            .attr("width", x.rangeBand())
            .attr("height", function(d){ return height - y(d.deaths); })
            .attr('class', function(d, i) {
                return 'bar bar-' + i;
            });

    svg.append('g')
        .attr('class', 'value')
        .selectAll('text')
            .data(graphic_data)
        .enter().append('text')
            .attr('x', function(d, i) {
                return x(d.label) + (x.rangeBand() / 2);
            })
            .attr('y', function(d) {
                return y(d.deaths) - 6;
            })
            .attr('text-anchor', 'middle')
            .text(function(d) { return d.deaths + '%' });

    if (pymChild) {
        pymChild.sendHeightToParent();
    }
}

/*
 * NB: Use window.load instead of document.ready
 * to ensure all images have loaded
 */
$(window).load(function() {
    $graphic = $('#graphic');

    if (Modernizr.svg) {
        // setup pym
        pymChild = new pym.Child({
            renderCallback: draw_graphic
        });
    } else {
        pymChild = new pym.Child();
    }
})
<|endoftext|>


<commit_before>(function () {
    'use strict';

    angular
        .module('orange')
        .factory('BasePagingService', BasePagingService)
        .factory('PatientPagingService', PatientPagingService);

    BasePagingService.$inject = ['$rootScope', '$q', '$state', '$ionicLoading', 'OrangeApi', 'settings', 'GlobalService'];
    PatientPagingService.$inject = ['$rootScope', 'BasePagingService', 'PatientService'];

    /**
     * Base Paging service works through OrangeApi
     */
    function BasePagingService($rootScope, $q, $state, $ionicLoading, OrangeApi, settings, GlobalService) {
        var Service = function () {

            this.apiEndpoint = '';
            this.items = null;
            this.item = null;
            this.count = 0;
            this.offset = 0;
            this.limit = settings.defaultLimit;
            this.sortBy = 'id';
            this.sortOrder = 'asc';

            this.errorItemNotFound = '';
            this.errorItemNotFoundText = 'Item not found';
            this.afterErrorItemNotFoundState = '';

            $rootScope.$on('auth:user:logout', this.clear.bind(this));
        };

        Service.prototype.initItems = initItems;
        Service.prototype.getItems = getItems;
        Service.prototype.getAllItems = getAllItems;
        Service.prototype.sendListChanged = sendListChanged;
        Service.prototype.onListChanged = onListChanged;
        Service.prototype.hasMore = hasMore;
        Service.prototype.moreItems = moreItems;
        Service.prototype.setItem = setItem;
        Service.prototype.getItem = getItem;
        Service.prototype.getItemPromise = getItemPromise;
        Service.prototype.removeItem = removeItem;
        Service.prototype.excludeItemFromList = excludeItemFromList;
        Service.prototype.saveItem = saveItem;
        Service.prototype.clear = clear;

        Service.prototype.getNewItemPromise = getNewItemPromise;
        Service.prototype.newItemSuccess = newItemSuccess;
        Service.prototype.getFetchPromise = getFetchPromise;
        Service.prototype.fetchItemsSuccess = fetchItemsSuccess;

        return Service;

        function initItems(all, limit) {
            all = all || false;
            var self = this,
                options = {
                    limit: all ? limit || 0 : this.limit
                    //limit: all ? 0 : this.limit
                };
            this.offset = 0;
            this.count = 0;
            return fetchItems.call(this, options).then(function (items) {
                self.items = items;
                self.offset = all ? items.meta['count'] : self.limit;
                self.sendListChanged();
                return self.items;
            });
        }

        function clear() {
            this.items = null;
            this.item = null;
            this.count = 0;
            this.offset = 0;
        }

        function getItems(force) {
            force = force || false;
            if (this.items == null || force) {
                return this.initItems();
            } else {
                var deferred = $q.defer();
                deferred.resolve(this.items);
                return deferred.promise;
            }
        }

        function getAllItems(force) {
            // TODO: Uncommented this, when limit:0 will work for all services
            //if (force || this.count === 0 || this.count > this.offset) {
            //    return initItems.call(this, true);
            //} else {
            //    return this.getItems();
            //}
            var self = this;
            return fetchItems.call(this, {limit: 0}).then(function (response) {
                var count = response.meta['count'] || 0;
                if (count && (count > self.offset || force)) {
                    return self.initItems(true, count);
                } else {
                    return self.getItems();
                }
            });
        }

        function fetchItems(options) {
            options = options || {};
            var opts = {
                    limit: options['limit'] !== undefined ? options['limit'] : this.limit,
                    offset: options['offset'] !== undefined ? options['offset'] : this.offset,
                    sort_by: options['sortBy'] || this.sortBy,
                    sort_order: options['sortOrder'] || this.sortOrder
                };

            return this.getFetchPromise(opts);
        }

        function getFetchPromise(options) {
            return OrangeApi[this.apiEndpoint].getList(options).then(
                this.fetchItemsSuccess.bind(this)
            );
        }

        function fetchItemsSuccess(response) {
            this.count = response.meta['count'];
            return response;
        }

        function moreItems() {
            var self = this;
            if (this.hasMore()) {
                return fetchItems.call(this, {offset: this.offset}).then(
                    function (items) {
                        self.items = _.union(self.items, items);
                        self.offset += self.limit;
                        self.sendListChanged();
                        return self.items;
                    }
                )
            }
        }

        function hasMore() {
            return this.count === undefined || this.count > this.offset;
        }

        function setItem(item) {
            this.item = item;
            item && console.log('Set item ' + item['id']);
        }

        function getItem(itemId, isClone) {
            isClone = isClone || false;
            var deferred = $q.defer(),
                self = this;

            if (this.item && (this.item.id == itemId || itemId === undefined)) {
                deferred.resolve(isClone ? angular.copy(this.item) : this.item);
                return deferred.promise;
            } else if (!itemId) {
                deferred.resolve(null);
                return deferred.promise;
            } else {
                if (this.items !== null) {
                    var existItem = _.find(this.items, function (item) {
                        return item.id == itemId;
                    });
                    if (existItem) {
                        deferred.resolve(isClone ? angular.copy(existItem) : existItem);
                        return deferred.promise;
                    }
                }
                return this.getItemPromise(itemId).then(
                    undefined,
                    function (error) {
                        if (error.data.errors[0] === self.errorItemNotFound) {
                            return onErrorNotFound.call(self, error).then(function () {
                                return $q.reject(error);
                            });
                        }
                        return $q.reject(error);
                    }
                );
            }
        }

        function getItemPromise(itemId) {
            var self = this;
            return OrangeApi[this.apiEndpoint].get(itemId).then(function (item) {
                self.setItem(item);
                return item;
            })
        }

        function removeItem(removedItem) {
            var self = this;
            return removedItem.remove().then(
                function () {
                    self.excludeItemFromList(removedItem);
                    self.count -= 1;
                    self.offset -= 1;
                    self.sendListChanged();
                    return self.items;
                },
                function (error) {
                    if (error.data.errors[0] === self.errorItemNotFound) {
                        if (self.excludeItemFromList(removedItem)) {
                            self.count -= 1;
                            self.offset -= 1;
                        }
                        return onErrorNotFound.call(self, error).then(function () {
                            return $q.reject(error);
                        });
                    }
                    return $q.reject(error);
                }
            );
        }

        function excludeItemFromList(item) {
            var itemIndex = this.items ? this.items.indexOf(item) : -1;
            if (itemIndex > -1) {
                this.items.splice(itemIndex, 1);
                return true;
            }
            return false;
        }

        function saveItem(savedItem) {
            var self = this;
            if (savedItem.id) {
                var listItem = _.find(this.items, function (item) {
                    return item.id === savedItem.id;
                });
                var _savedItem = listItem || savedItem;
                if (listItem) {
                    _savedItem = _.extend(listItem, savedItem);
                }
                return _savedItem.save().then(
                    function (newItem) {
                        if (listItem && listItem.id === self.item.id) {
                            self.setItem(listItem);
                        }
                        self.sendListChanged();
                        return listItem || newItem;
                    },
                    function (error) {
                        if (error.data.errors[0] === self.errorItemNotFound) {
                            if (self.excludeItemFromList(savedItem)) {
                                self.count -= 1;
                                self.offset -= 1;
                            }
                            return onErrorNotFound.call(self, error).then(function () {
                                return $q.reject(error);
                            });
                        }
                        return $q.reject(error);
                    }
                );
            } else {
                return this.getNewItemPromise(savedItem);
            }
        }

        function getNewItemPromise(savedItem) {
            return OrangeApi[this.apiEndpoint].post(savedItem).then(
                this.newItemSuccess.bind(this)
            );
        }

        function newItemSuccess(newItem, addCondition) {
            if (addCondition === undefined) {
                addCondition = true;
            }
            if (!this.hasMore() && addCondition && this.items) {
                this.items[this.sortOrder !== 'desc' ? 'push' : 'unshift'](newItem);
                this.offset += 1;
            }
            this.count += 1;
            this.item = newItem;
            this.sendListChanged();
            return newItem;
        }

        function onErrorNotFound(error) {
            var self = this;
            $ionicLoading.hide();
            return GlobalService.showError(this.errorItemNotFoundText).then(function () {
                self.setItem(null);
                self.afterErrorItemNotFoundState && $state.go(self.afterErrorItemNotFoundState);
            });
        }

        function sendListChanged() {
            $rootScope.$broadcast(this.apiEndpoint + ':items:changed', this.items);
        }

        function onListChanged(callback) {
            $rootScope.$on(this.apiEndpoint + ':items:changed', callback);
        }
    }

    /**
     * Paging service for patient endpoints
     */
    function PatientPagingService($rootScope, BasePagingService, PatientService) {
        var Service = function () {
            BasePagingService.call(this);
            $rootScope.$on('changePatient', this.clear.bind(this));
        };

        Service.prototype = Object.create(BasePagingService.prototype);
        Service.prototype.getNewItemPromise = getNewItemPromise;
        Service.prototype.getFetchPromise = getFetchPromise;
        Service.prototype.getItemPromise = getItemPromise;

        return Service;

        function getNewItemPromise(savedItem) {
            var self = this;
            return PatientService.getPatient().then(function (patient) {
                return patient.all(self.apiEndpoint).post(savedItem).then(
                    self.newItemSuccess.bind(self)
                );
            });
        }

        function getFetchPromise(options) {
            var self = this;
            return PatientService.getPatient().then(function (patient) {
                return patient.all(self.apiEndpoint).getList(options).then(
                    self.fetchItemsSuccess.bind(self)
                );
            });
        }

        function getItemPromise(itemId) {
            var self = this;
            return PatientService.getPatient().then(function (patient) {
                return patient.all(self.apiEndpoint).get(itemId).then(function (item) {
                    self.setItem(item);
                    return item;
                });
            });
        }
    }
})();
<commit_msg>[artefact][ORANGE-262]Fix saving items<commit_after>(function () {
    'use strict';

    angular
        .module('orange')
        .factory('BasePagingService', BasePagingService)
        .factory('PatientPagingService', PatientPagingService);

    BasePagingService.$inject = ['$rootScope', '$q', '$state', '$ionicLoading', 'OrangeApi', 'settings', 'GlobalService'];
    PatientPagingService.$inject = ['$rootScope', 'BasePagingService', 'PatientService'];

    /**
     * Base Paging service works through OrangeApi
     */
    function BasePagingService($rootScope, $q, $state, $ionicLoading, OrangeApi, settings, GlobalService) {
        var Service = function () {

            this.apiEndpoint = '';
            this.items = null;
            this.item = null;
            this.count = 0;
            this.offset = 0;
            this.limit = settings.defaultLimit;
            this.sortBy = 'id';
            this.sortOrder = 'asc';

            this.errorItemNotFound = '';
            this.errorItemNotFoundText = 'Item not found';
            this.afterErrorItemNotFoundState = '';

            $rootScope.$on('auth:user:logout', this.clear.bind(this));
        };

        Service.prototype.initItems = initItems;
        Service.prototype.getItems = getItems;
        Service.prototype.getAllItems = getAllItems;
        Service.prototype.sendListChanged = sendListChanged;
        Service.prototype.onListChanged = onListChanged;
        Service.prototype.hasMore = hasMore;
        Service.prototype.moreItems = moreItems;
        Service.prototype.setItem = setItem;
        Service.prototype.getItem = getItem;
        Service.prototype.getItemPromise = getItemPromise;
        Service.prototype.removeItem = removeItem;
        Service.prototype.excludeItemFromList = excludeItemFromList;
        Service.prototype.saveItem = saveItem;
        Service.prototype.clear = clear;

        Service.prototype.getNewItemPromise = getNewItemPromise;
        Service.prototype.newItemSuccess = newItemSuccess;
        Service.prototype.getFetchPromise = getFetchPromise;
        Service.prototype.fetchItemsSuccess = fetchItemsSuccess;

        return Service;

        function initItems(all, limit) {
            all = all || false;
            var self = this,
                options = {
                    limit: all ? limit || 0 : this.limit
                    //limit: all ? 0 : this.limit
                };
            this.offset = 0;
            this.count = 0;
            return fetchItems.call(this, options).then(function (items) {
                self.items = items;
                self.offset = all ? items.meta['count'] : self.limit;
                self.sendListChanged();
                return self.items;
            });
        }

        function clear() {
            this.items = null;
            this.item = null;
            this.count = 0;
            this.offset = 0;
        }

        function getItems(force) {
            force = force || false;
            if (this.items == null || force) {
                return this.initItems();
            } else {
                var deferred = $q.defer();
                deferred.resolve(this.items);
                return deferred.promise;
            }
        }

        function getAllItems(force) {
            // TODO: Uncommented this, when limit:0 will work for all services
            //if (force || this.count === 0 || this.count > this.offset) {
            //    return initItems.call(this, true);
            //} else {
            //    return this.getItems();
            //}
            var self = this;
            return fetchItems.call(this, {limit: 0}).then(function (response) {
                var count = response.meta['count'] || 0;
                if (count && (count > self.offset || force)) {
                    return self.initItems(true, count);
                } else {
                    return self.getItems();
                }
            });
        }

        function fetchItems(options) {
            options = options || {};
            var opts = {
                    limit: options['limit'] !== undefined ? options['limit'] : this.limit,
                    offset: options['offset'] !== undefined ? options['offset'] : this.offset,
                    sort_by: options['sortBy'] || this.sortBy,
                    sort_order: options['sortOrder'] || this.sortOrder
                };

            return this.getFetchPromise(opts);
        }

        function getFetchPromise(options) {
            return OrangeApi[this.apiEndpoint].getList(options).then(
                this.fetchItemsSuccess.bind(this)
            );
        }

        function fetchItemsSuccess(response) {
            this.count = response.meta['count'];
            return response;
        }

        function moreItems() {
            var self = this;
            if (this.hasMore()) {
                return fetchItems.call(this, {offset: this.offset}).then(
                    function (items) {
                        self.items = _.union(self.items, items);
                        self.offset += self.limit;
                        self.sendListChanged();
                        return self.items;
                    }
                )
            }
        }

        function hasMore() {
            return this.count === undefined || this.count > this.offset;
        }

        function setItem(item) {
            this.item = item;
            item && console.log('Set item ' + item['id']);
        }

        function getItem(itemId, isClone) {
            isClone = isClone || false;
            var deferred = $q.defer(),
                self = this;

            if (this.item && (this.item.id == itemId || itemId === undefined)) {
                deferred.resolve(isClone ? angular.copy(this.item) : this.item);
                return deferred.promise;
            } else if (!itemId) {
                deferred.resolve(null);
                return deferred.promise;
            } else {
                if (this.items !== null) {
                    var existItem = _.find(this.items, function (item) {
                        return item.id == itemId;
                    });
                    if (existItem) {
                        deferred.resolve(isClone ? angular.copy(existItem) : existItem);
                        return deferred.promise;
                    }
                }
                return this.getItemPromise(itemId).then(
                    undefined,
                    function (error) {
                        if (error.data.errors[0] === self.errorItemNotFound) {
                            return onErrorNotFound.call(self, error).then(function () {
                                return $q.reject(error);
                            });
                        }
                        return $q.reject(error);
                    }
                );
            }
        }

        function getItemPromise(itemId) {
            var self = this;
            return OrangeApi[this.apiEndpoint].get(itemId).then(function (item) {
                self.setItem(item);
                return item;
            })
        }

        function removeItem(removedItem) {
            var self = this;
            return removedItem.remove().then(
                function () {
                    self.excludeItemFromList(removedItem);
                    self.count -= 1;
                    self.offset -= 1;
                    self.sendListChanged();
                    return self.items;
                },
                function (error) {
                    if (error.data.errors[0] === self.errorItemNotFound) {
                        if (self.excludeItemFromList(removedItem)) {
                            self.count -= 1;
                            self.offset -= 1;
                        }
                        return onErrorNotFound.call(self, error).then(function () {
                            return $q.reject(error);
                        });
                    }
                    return $q.reject(error);
                }
            );
        }

        function excludeItemFromList(item) {
            var itemIndex = this.items ? this.items.indexOf(item) : -1;
            if (itemIndex > -1) {
                this.items.splice(itemIndex, 1);
                return true;
            }
            return false;
        }

        function saveItem(savedItem) {
            var self = this;
            if (savedItem.id) {
                var listItem = _.find(this.items, function (item) {
                    return item.id === savedItem.id;
                });
                var _savedItem = listItem || savedItem;
                if (listItem) {
                    _savedItem = _.extend(listItem, savedItem);
                }
                return _savedItem.save().then(
                    function (newItem) {
                        if (listItem && listItem.id === self.item.id) {
                            listItem = _.extend(listItem, newItem);
                            self.setItem(listItem);
                        }
                        self.sendListChanged();
                        return listItem || newItem;
                    },
                    function (error) {
                        if (error.data.errors[0] === self.errorItemNotFound) {
                            if (self.excludeItemFromList(savedItem)) {
                                self.count -= 1;
                                self.offset -= 1;
                            }
                            return onErrorNotFound.call(self, error).then(function () {
                                return $q.reject(error);
                            });
                        }
                        return $q.reject(error);
                    }
                );
            } else {
                return this.getNewItemPromise(savedItem);
            }
        }

        function getNewItemPromise(savedItem) {
            return OrangeApi[this.apiEndpoint].post(savedItem).then(
                this.newItemSuccess.bind(this)
            );
        }

        function newItemSuccess(newItem, addCondition) {
            if (addCondition === undefined) {
                addCondition = true;
            }
            if (!this.hasMore() && addCondition && this.items) {
                this.items[this.sortOrder !== 'desc' ? 'push' : 'unshift'](newItem);
                this.offset += 1;
            }
            this.count += 1;
            this.item = newItem;
            this.sendListChanged();
            return newItem;
        }

        function onErrorNotFound(error) {
            var self = this;
            $ionicLoading.hide();
            return GlobalService.showError(this.errorItemNotFoundText).then(function () {
                self.setItem(null);
                self.afterErrorItemNotFoundState && $state.go(self.afterErrorItemNotFoundState);
            });
        }

        function sendListChanged() {
            $rootScope.$broadcast(this.apiEndpoint + ':items:changed', this.items);
        }

        function onListChanged(callback) {
            $rootScope.$on(this.apiEndpoint + ':items:changed', callback);
        }
    }

    /**
     * Paging service for patient endpoints
     */
    function PatientPagingService($rootScope, BasePagingService, PatientService) {
        var Service = function () {
            BasePagingService.call(this);
            $rootScope.$on('changePatient', this.clear.bind(this));
        };

        Service.prototype = Object.create(BasePagingService.prototype);
        Service.prototype.getNewItemPromise = getNewItemPromise;
        Service.prototype.getFetchPromise = getFetchPromise;
        Service.prototype.getItemPromise = getItemPromise;

        return Service;

        function getNewItemPromise(savedItem) {
            var self = this;
            return PatientService.getPatient().then(function (patient) {
                return patient.all(self.apiEndpoint).post(savedItem).then(
                    self.newItemSuccess.bind(self)
                );
            });
        }

        function getFetchPromise(options) {
            var self = this;
            return PatientService.getPatient().then(function (patient) {
                return patient.all(self.apiEndpoint).getList(options).then(
                    self.fetchItemsSuccess.bind(self)
                );
            });
        }

        function getItemPromise(itemId) {
            var self = this;
            return PatientService.getPatient().then(function (patient) {
                return patient.all(self.apiEndpoint).get(itemId).then(function (item) {
                    self.setItem(item);
                    return item;
                });
            });
        }
    }
})();
<|endoftext|>


<commit_before>'use strict';

var self = getStatus;
module.exports = self;

var async = require('async');
var _ = require('underscore');

var configHandler = require('../../common/configHandler.js');
var VaultAdapter = require('../../common/VaultAdapter.js');

function getStatus(req, res) {
  var bag = {
    reqQuery: req.query,
    resBody: {
      isReachable: false,
      error: null
    },
    component: 'secrets'
  };

  bag.who = util.format('secrets|%s', self.name);
  logger.info(bag.who, 'Starting');

  async.series([
    _checkInputParams.bind(null, bag),
    _get.bind(null, bag),
    _createClient.bind(null, bag),
    _getStatus.bind(null, bag)
  ],
    function (err) {
      logger.info(bag.who, 'Completed');
      if (err)
        return respondWithError(res, err);

      sendJSONResponse(res, bag.resBody);
    }
  );
}

function _checkInputParams(bag, next) {
  var who = bag.who + '|' + _checkInputParams.name;
  logger.verbose(who, 'Inside');

  return next();
}

function _get(bag, next) {
  var who = bag.who + '|' + _get.name;
  logger.verbose(who, 'Inside');

  configHandler.get(bag.component,
    function (err, secrets) {
      if (err)
        return next(
          new ActErr(who, ActErr.DataNotFound,
            'Failed to get ' + bag.component, err)
        );

      if (_.isEmpty(secrets))
        return next(
          new ActErr(who, ActErr.DataNotFound,
            'No configuration in database for ' + bag.component)
        );

      bag.config = secrets;
      bag.vaultUrl = util.format('http://%s:%s',
        bag.config.address, bag.config.port);
      return next();
    }
  );
}

function _createClient(bag, next) {
  var who = bag.who + '|' + _createClient.name;
  logger.debug(who, 'Inside');

  bag.vaultAdapter = new VaultAdapter(
    bag.vaultUrl, bag.config.rootToken);

  return next();
}

function _getStatus(bag, next) {
  var who = bag.who + '|' + _getStatus.name;
  logger.verbose(who, 'Inside');

  bag.vaultAdapter.getHealth(
    function (err, response) {
      if (err)
        return next(
          new ActErr(who, ActErr.OperationFailed,
            'Failed to check status for ' + bag.component, err)
        );

      bag.resBody.isReachable = true;
      bag.resBody = _.extend(bag.resBody, response);
      return next();
    }
  );
}
<commit_msg>normalizing the error object<commit_after>'use strict';

var self = getStatus;
module.exports = self;

var async = require('async');
var _ = require('underscore');

var configHandler = require('../../common/configHandler.js');
var VaultAdapter = require('../../common/VaultAdapter.js');

function getStatus(req, res) {
  var bag = {
    reqQuery: req.query,
    resBody: {
      isReachable: false,
      error: null
    },
    component: 'secrets'
  };

  bag.who = util.format('secrets|%s', self.name);
  logger.info(bag.who, 'Starting');

  async.series([
    _checkInputParams.bind(null, bag),
    _get.bind(null, bag),
    _createClient.bind(null, bag),
    _getStatus.bind(null, bag)
  ],
    function (err) {
      logger.info(bag.who, 'Completed');
      if (err)
        return respondWithError(res, err);

      sendJSONResponse(res, bag.resBody);
    }
  );
}

function _checkInputParams(bag, next) {
  var who = bag.who + '|' + _checkInputParams.name;
  logger.verbose(who, 'Inside');

  return next();
}

function _get(bag, next) {
  var who = bag.who + '|' + _get.name;
  logger.verbose(who, 'Inside');

  configHandler.get(bag.component,
    function (err, secrets) {
      if (err)
        return next(
          new ActErr(who, ActErr.DataNotFound,
            'Failed to get ' + bag.component, err)
        );

      if (_.isEmpty(secrets))
        return next(
          new ActErr(who, ActErr.DataNotFound,
            'No configuration in database for ' + bag.component)
        );

      bag.config = secrets;
      bag.vaultUrl = util.format('http://%s:%s',
        bag.config.address, bag.config.port);
      return next();
    }
  );
}

function _createClient(bag, next) {
  var who = bag.who + '|' + _createClient.name;
  logger.debug(who, 'Inside');

  bag.vaultAdapter = new VaultAdapter(
    bag.vaultUrl, bag.config.rootToken);

  return next();
}

function _getStatus(bag, next) {
  var who = bag.who + '|' + _getStatus.name;
  logger.verbose(who, 'Inside');

  bag.vaultAdapter.getHealth(
    function (err, response) {
      if (err && err.code === 'ECONNREFUSED') {
        bag.resBody.isReachable = false;
        bag.resBody = _.extend(bag.resBody, err);
      } else if (err) {
        return next(
          new ActErr(who, ActErr.OperationFailed,
            'Failed to check status for ' + bag.component, err)
        );
      } else {
        bag.resBody.isReachable = true;
        bag.resBody = _.extend(bag.resBody, response);
      }

      return next();
    }
  );
}
<|endoftext|>


<commit_before>function createProject(e) {
    console.log("createProject handler");

    var projectName = global.jQuery("#projectName").val();
    var projectPath = global.jQuery("#projectPath").val();

    if(projectName.length > 0 && projectPath.length > 0) {
        localStorage.projDir = projectPath + "/" + projectName;
        create();
        global.jQuery("#newProjectOverlay").hide();
        global.jQuery("#overlay-bg").hide();
    } else {
        displayErrorMessage("new project requires a project name and a project path");
    }
}

function selectProjectPath(e) {
    global.createClicked = true;
    global.jQuery("#projectDirectory").trigger("click");
}

function openProject(e) {
    console.log("open project click handler");
    global.jQuery("#projectDirectory").trigger("click");
}

function selectDirectory(e) {
    console.log("change handler");
    console.log(global.jQuery("#projectDirectory").val());
    localStorage.projDir = global.jQuery("#projectDirectory").val();

    if(global.createClicked) {
        // new project creation workflow
        global.createClicked = false;
        global.jQuery("#projectPath").val(localStorage.projDir);
    } else {
        // open existing project workflow
        parseProjectConfig();
        //global.jQuery("#createOpenProjectOverlay").hide();
        global.jQuery("#overlay-bg").hide();
        hideAddCreateProjectOverlay();
        global.jQuery("#plus-icon").attr("src", "img/icons/normal/plus.svg");
    }
}

function create() {
    console.log("create();")
	var options = {};
       options.path = localStorage.projDir;
       options.version = global.pgVersion;

       global.pgServer.create(options)
          .on("progress", function(state) {
              if (state.percentage) {
                  console.log("downloaded: " + state.percentage + "%");
              }
          })
          .on("error", function(e) {
              console.log(e.message);
              displayErrorMessage(e.message);
          })
          .on("complete", function(data) {
              console.log("created project at:" + data.path);

              // parse config.xml of newly created project
              parseProjectConfig();

              global.jQuery("#overlay-bg").hide();
              hideAddNewProjectOverlay();
          });
}

function parseProjectConfig() {

    var filename = localStorage.projDir + "/www/config.xml";

    fs.readFile(filename, 'utf8', function(err, data) {
        if (err) throw err;

        var iconPath = localStorage.projDir + "/www/"

        global.jQuery.xmlDoc = global.jQuery.parseXML(data);
        global.jQuery.xml = global.jQuery(global.jQuery.xmlDoc);

        // get the project name
        var projectName = global.jQuery.xml.find("name").text();

        // get the project version
        var projectVersion = global.jQuery.xml.find("widget").attr("version");

        // get the app icon
        var projectIcon = global.jQuery.xml.find("icon").attr("src");
        iconPath += projectIcon;

        // check if the project exists in PG-GUI's localstorage before adding
        if(!projectExists(localStorage.projDir)) {
            addProject(projectName, projectVersion, iconPath, localStorage.projDir);
        } else {
            displayErrorMessage("project already exists");
        }
    });
}

function projectExists(projDir) {

    var projectFound = false;

    if (localStorage["projects"]) {
        var projects = JSON.parse(localStorage["projects"]);
        var index = projects.length;

        for (var i=0;i<index;i++) {
            if(projDir == projects[i].projDir) {
                projectFound = true;
                break;
            }
        }
    }

    return projectFound;
}
<commit_msg>[#137] display an error message instead of crashing the app when config.xml is not found<commit_after>function createProject(e) {
    console.log("createProject handler");

    var projectName = global.jQuery("#projectName").val();
    var projectPath = global.jQuery("#projectPath").val();

    if(projectName.length > 0 && projectPath.length > 0) {
        localStorage.projDir = projectPath + "/" + projectName;
        create();
        global.jQuery("#newProjectOverlay").hide();
        global.jQuery("#overlay-bg").hide();
    } else {
        displayErrorMessage("new project requires a project name and a project path");
    }
}

function selectProjectPath(e) {
    global.createClicked = true;
    global.jQuery("#projectDirectory").trigger("click");
}

function openProject(e) {
    console.log("open project click handler");
    global.jQuery("#projectDirectory").trigger("click");
}

function selectDirectory(e) {
    console.log("change handler");
    console.log(global.jQuery("#projectDirectory").val());
    localStorage.projDir = global.jQuery("#projectDirectory").val();

    if(global.createClicked) {
        // new project creation workflow
        global.createClicked = false;
        global.jQuery("#projectPath").val(localStorage.projDir);
    } else {
        // open existing project workflow
        parseProjectConfig();
        //global.jQuery("#createOpenProjectOverlay").hide();
        global.jQuery("#overlay-bg").hide();
        hideAddCreateProjectOverlay();
        global.jQuery("#plus-icon").attr("src", "img/icons/normal/plus.svg");
    }
}

function create() {
    console.log("create();")
	var options = {};
       options.path = localStorage.projDir;
       options.version = global.pgVersion;

       global.pgServer.create(options)
          .on("progress", function(state) {
              if (state.percentage) {
                  console.log("downloaded: " + state.percentage + "%");
              }
          })
          .on("error", function(e) {
              console.log(e.message);
              displayErrorMessage(e.message);
          })
          .on("complete", function(data) {
              console.log("created project at:" + data.path);

              // parse config.xml of newly created project
              parseProjectConfig();

              global.jQuery("#overlay-bg").hide();
              hideAddNewProjectOverlay();
          });
}

function parseProjectConfig() {

    var filename = localStorage.projDir + "/www/config.xml";

    fs.readFile(filename, 'utf8', function(err, data) {
        if (err) {
            //throw err;
            displayErrorMessage("Selected folder doesn't contain a config.xml file");
        } else {
            var iconPath = localStorage.projDir + "/www/"

            global.jQuery.xmlDoc = global.jQuery.parseXML(data);
            global.jQuery.xml = global.jQuery(global.jQuery.xmlDoc);

            // get the project name
            var projectName = global.jQuery.xml.find("name").text();

            // get the project version
            var projectVersion = global.jQuery.xml.find("widget").attr("version");

            // get the app icon
            var projectIcon = global.jQuery.xml.find("icon").attr("src");
            iconPath += projectIcon;

            // check if the project exists in PG-GUI's localstorage before adding
            if(!projectExists(localStorage.projDir)) {
                addProject(projectName, projectVersion, iconPath, localStorage.projDir);
            } else {
                displayErrorMessage("project already exists");
            }
        }
    });
}

function projectExists(projDir) {

    var projectFound = false;

    if (localStorage["projects"]) {
        var projects = JSON.parse(localStorage["projects"]);
        var index = projects.length;

        for (var i=0;i<index;i++) {
            if(projDir == projects[i].projDir) {
                projectFound = true;
                break;
            }
        }
    }

    return projectFound;
}
<|endoftext|>


<commit_before>// @flow

import { ColorPalette } from '../../../styles';

const DEFAULT_SIZE = 65;

/**
 * The styles of the feature base/participants.
 */
export default {

    avatarContainer: (size: number = DEFAULT_SIZE) => {
        return {
            alignItems: 'center',
            borderRadius: size / 2,
            height: size,
            justifyContent: 'center',
            overflow: 'hidden',
            width: size
        };
    },

    avatarContent: (size: number = DEFAULT_SIZE) => {
        return {
            height: size,
            width: size
        };
    },

    initialsContainer: {
        alignItems: 'center',
        alignSelf: 'stretch',
        flex: 1,
        justifyContent: 'center'
    },

    initialsText: (size: number = DEFAULT_SIZE) => {
        return {
            color: 'rgba(255, 255, 255, 0.6)',
            fontSize: size * 0.5,
            fontWeight: '100'
        };
    },

    staticAvatar: {
        backgroundColor: ColorPalette.lightGrey,
        opacity: 0.4
    }
};
<commit_msg>fix: reduce avatar font size<commit_after>// @flow

import { ColorPalette } from '../../../styles';

const DEFAULT_SIZE = 65;

/**
 * The styles of the feature base/participants.
 */
export default {

    avatarContainer: (size: number = DEFAULT_SIZE) => {
        return {
            alignItems: 'center',
            borderRadius: size / 2,
            height: size,
            justifyContent: 'center',
            overflow: 'hidden',
            width: size
        };
    },

    avatarContent: (size: number = DEFAULT_SIZE) => {
        return {
            height: size,
            width: size
        };
    },

    initialsContainer: {
        alignItems: 'center',
        alignSelf: 'stretch',
        flex: 1,
        justifyContent: 'center'
    },

    initialsText: (size: number = DEFAULT_SIZE) => {
        return {
            color: 'rgba(255, 255, 255, 0.6)',
            fontSize: size * 0.45,
            fontWeight: '100'
        };
    },

    staticAvatar: {
        backgroundColor: ColorPalette.lightGrey,
        opacity: 0.4
    }
};
<|endoftext|>


<commit_before>// @flow

import React, { useCallback, useMemo, useState } from 'react';
import type { AbstractComponent } from 'react';
import { useTranslation } from 'react-i18next';
import { useDispatch, useSelector } from 'react-redux';

import { sendAnalytics, createPollEvent } from '../../analytics';
import { getParticipantById } from '../../base/participants/functions';
import { useBoundSelector } from '../../base/util/hooks';
import { setVoteChanging } from '../actions';
import { getPoll } from '../functions';

/**
 * The type of the React {@code Component} props of inheriting component.
 */
type InputProps = {

    /**
     * ID of the poll to display.
     */
    pollId: string,
};

export type AnswerInfo = {
    name: string,
    percentage: number,
    voters?: Array<{ id: number, name: string }>,
    voterCount: number
};

/**
 * The type of the React {@code Component} props of {@link AbstractPollResults}.
 */
export type AbstractProps = {
    answers: Array<AnswerInfo>,
    changeVote: Function,
    creatorName: string,
    showDetails: boolean,
    question: string,
    t: Function,
    toggleIsDetailed: Function,
    haveVoted: boolean,
};

/**
 * Higher Order Component taking in a concrete PollResult component and
 * augmenting it with state/behavior common to both web and native implementations.
 *
 * @param {React.AbstractComponent} Component - The concrete component.
 * @returns {React.AbstractComponent}
 */
const AbstractPollResults = (Component: AbstractComponent<AbstractProps>) => (props: InputProps) => {
    const { pollId } = props;

    const pollDetails = useSelector(getPoll(pollId));
    const participant = useBoundSelector(getParticipantById, pollDetails.senderId);

    const [ showDetails, setShowDetails ] = useState(false);
    const toggleIsDetailed = useCallback(() => {
        sendAnalytics(createPollEvent('vote.detailsViewed'));
        setShowDetails(!showDetails);
    });

    const answers: Array<AnswerInfo> = useMemo(() => {
        const voterSet = new Set();

        // Getting every voters ID that participates to the poll
        for (const answer of pollDetails.answers) {
            for (const [ voterId ] of answer.voters) {
                voterSet.add(voterId);
            }
        }

        const totalVotes = pollDetails.answers.reduce((sum, { voters: { size } }) => sum + size, 0);

        return pollDetails.answers.map(answer => {
            const percentage = totalVotes === 0 ? 0 : Math.round(answer.voters.size / totalVotes * 100);

            let voters = null;

            if (showDetails) {
                voters = [ ...answer.voters ].map(([ id, name ]) => {
                    return {
                        id,
                        name
                    };
                });
            }

            return {
                name: answer.name,
                percentage,
                voters,
                voterCount: answer.voters.size
            };
        });
    }, [ pollDetails.answers, showDetails ]);

    const dispatch = useDispatch();
    const changeVote = useCallback(() => {
        dispatch(setVoteChanging(pollId, true));
        sendAnalytics(createPollEvent('vote.changed'));
    }, [ dispatch, pollId ]);

    const { t } = useTranslation();

    return (
        <Component
            answers = { answers }
            changeVote = { changeVote }
            creatorName = { participant ? participant.name : '' }
            haveVoted = { pollDetails.lastVote !== null }
            question = { pollDetails.question }
            showDetails = { showDetails }
            t = { t }
            toggleIsDetailed = { toggleIsDetailed } />
    );
};

export default AbstractPollResults;
<commit_msg>Revert "fix(Polls): Calculate vote percentage based on total number of votes" (#10781)<commit_after>// @flow

import React, { useCallback, useMemo, useState } from 'react';
import type { AbstractComponent } from 'react';
import { useTranslation } from 'react-i18next';
import { useDispatch, useSelector } from 'react-redux';

import { sendAnalytics, createPollEvent } from '../../analytics';
import { getParticipantById } from '../../base/participants/functions';
import { useBoundSelector } from '../../base/util/hooks';
import { setVoteChanging } from '../actions';
import { getPoll } from '../functions';

/**
 * The type of the React {@code Component} props of inheriting component.
 */
type InputProps = {

    /**
     * ID of the poll to display.
     */
    pollId: string,
};

export type AnswerInfo = {
    name: string,
    percentage: number,
    voters?: Array<{ id: number, name: string }>,
    voterCount: number
};

/**
 * The type of the React {@code Component} props of {@link AbstractPollResults}.
 */
export type AbstractProps = {
    answers: Array<AnswerInfo>,
    changeVote: Function,
    creatorName: string,
    showDetails: boolean,
    question: string,
    t: Function,
    toggleIsDetailed: Function,
    haveVoted: boolean,
};

/**
 * Higher Order Component taking in a concrete PollResult component and
 * augmenting it with state/behavior common to both web and native implementations.
 *
 * @param {React.AbstractComponent} Component - The concrete component.
 * @returns {React.AbstractComponent}
 */
const AbstractPollResults = (Component: AbstractComponent<AbstractProps>) => (props: InputProps) => {
    const { pollId } = props;

    const pollDetails = useSelector(getPoll(pollId));
    const participant = useBoundSelector(getParticipantById, pollDetails.senderId);

    const [ showDetails, setShowDetails ] = useState(false);
    const toggleIsDetailed = useCallback(() => {
        sendAnalytics(createPollEvent('vote.detailsViewed'));
        setShowDetails(!showDetails);
    });

    const answers: Array<AnswerInfo> = useMemo(() => {
        const voterSet = new Set();

        // Getting every voters ID that participates to the poll
        for (const answer of pollDetails.answers) {
            for (const [ voterId ] of answer.voters) {
                voterSet.add(voterId);
            }
        }

        const totalVoters = voterSet.size;

        return pollDetails.answers.map(answer => {
            const percentage = totalVoters === 0 ? 0 : Math.round(answer.voters.size / totalVoters * 100);

            let voters = null;

            if (showDetails) {
                voters = [ ...answer.voters ].map(([ id, name ]) => {
                    return {
                        id,
                        name
                    };
                });
            }

            return {
                name: answer.name,
                percentage,
                voters,
                voterCount: answer.voters.size
            };
        });
    }, [ pollDetails.answers, showDetails ]);

    const dispatch = useDispatch();
    const changeVote = useCallback(() => {
        dispatch(setVoteChanging(pollId, true));
        sendAnalytics(createPollEvent('vote.changed'));
    }, [ dispatch, pollId ]);

    const { t } = useTranslation();

    return (
        <Component
            answers = { answers }
            changeVote = { changeVote }
            creatorName = { participant ? participant.name : '' }
            haveVoted = { pollDetails.lastVote !== null }
            question = { pollDetails.question }
            showDetails = { showDetails }
            t = { t }
            toggleIsDetailed = { toggleIsDetailed } />
    );
};

export default AbstractPollResults;
<|endoftext|>