<commit_before>#!/usr/bin/env node
/*
 * jQuery Core Release Management
 */

// Debugging variables
var	debug = false,
	skipRemote = false;

var fs = require("fs"),
	child = require("child_process"),
	path = require("path"),
	zlib = require("zlib");

var archiver = require("archiver");
var gzipOptions = {
  level: 9
};

var releaseVersion,
	nextVersion,
	isBeta,
	pkg,
	branch,

	scpURL = "jqadmin@code.origin.jquery.com:/var/www/html/code.jquery.com/",
	cdnURL = "http://code.origin.jquery.com/",
	repoURL = "git@github.com:jquery/jquery.git",

	// Windows needs the .cmd version but will find the non-.cmd
	// On Windows, ensure the HOME environment variable is set
	gruntCmd = process.platform === "win32" ? "grunt.cmd" : "grunt",

	devFile = "dist/jquery.js",
	minFile = "dist/jquery.min.js",
	mapFile = "dist/jquery.min.map",

	releaseFiles = {
		"jquery-VER.js": devFile,
		"jquery-VER.min.js": minFile,
		"jquery-VER.min.map": mapFile,
		"jquery.js": devFile,
		"jquery.min.js": minFile,
		"jquery.min.map": mapFile,
		"jquery-latest.js": devFile,
		"jquery-latest.min.js": minFile,
		"jquery-latest.min.map": mapFile
	},

	jQueryFilesCDN = [],

	googleFilesCDN = [
		"jquery.js", "jquery.min.js", "jquery.min.map"
	],

	msFilesCDN = [
		"jquery-VER.js", "jquery-VER.min.js", "jquery-VER.min.map"
	];

steps(
	initialize,
	checkGitStatus,
	tagReleaseVersion,
	gruntBuild,
	makeReleaseCopies,
	setNextVersion,
	copyTojQueryCDN,
	buildGoogleCDN,
	buildMicrosoftCDN,
	pushToGithub,
	exit
);

function initialize( next ) {

	if ( process.argv[2] === "-d" ) {
		process.argv.shift();
		debug = true;
		console.warn("=== DEBUG MODE ===" );
	}

	// First arg should be the version number being released
	var newver, oldver,
		rsemver = /^(\d+)\.(\d+)\.(\d+)(?:-([\dA-Za-z\-]+(?:\.[\dA-Za-z\-]+)*))?$/,
		version = ( process.argv[3] || "" ).toLowerCase().match( rsemver ) || {},
		major = version[1],
		minor = version[2],
		patch = version[3],
		xbeta = version[4];

	branch = process.argv[2];
	releaseVersion = process.argv[3];
	isBeta = !!xbeta;

	if ( !branch || !major || !minor || !patch ) {
		die( "Usage: " + process.argv[1] + " branch releaseVersion" );
	}
	if ( xbeta === "pre" ) {
		die( "Cannot release a 'pre' version!" );
	}
	if ( !(fs.existsSync || path.existsSync)( "package.json" ) ) {
		die( "No package.json in this directory" );
	}
	pkg = JSON.parse( fs.readFileSync( "package.json" ) );

	console.log( "Current version is " + pkg.version + "; generating release " + releaseVersion );
	version = pkg.version.match( rsemver );
	oldver = ( +version[1] ) * 10000 + ( +version[2] * 100 ) + ( +version[3] )
	newver = ( +major ) * 10000 + ( +minor * 100 ) + ( +patch );
	if ( newver < oldver ) {
		die( "Next version is older than current version!" );
	}

	nextVersion = major + "." + minor + "." + ( isBeta ? patch : +patch + 1 ) + "-pre";
	next();
}

function checkGitStatus( next ) {
	git( [ "status" ], function( error, stdout, stderr ) {
		var onBranch = ((stdout||"").match( /On branch (\S+)/ ) || [])[1];
		if ( onBranch !== branch ) {
			die( "Branches don't match: Wanted " + branch + ", got " + onBranch );
		}
		if ( /Changes to be committed/i.test( stdout ) ) {
			dieIfReal( "Please commit changed files before attemping to push a release." );
		}
		if ( /Changes not staged for commit/i.test( stdout ) ) {
			dieIfReal( "Please stash files before attempting to push a release." );
		}
		next();
	});
}

function tagReleaseVersion( next ) {
	updatePackageVersion( releaseVersion );
	git( [ "commit", "-a", "-m", "Tagging the " + releaseVersion + " release." ], function(){
		git( [ "tag", releaseVersion ], next, debug);
	}, debug);
}

function gruntBuild( next ) {
	exec( gruntCmd, [], function( error, stdout ) {
		if ( error ) {
			die( error + stderr );
		}
		console.log( stdout );
		next();
	}, debug);
}

function makeReleaseCopies( next ) {
	Object.keys( releaseFiles ).forEach(function( key ) {
		var text,
			builtFile = releaseFiles[ key ],
			releaseFile = key.replace( /VER/g, releaseVersion );

		// Beta releases don't update the jquery-latest etc. copies
		if ( !isBeta || key !== releaseFile ) {

			if ( /\.map$/.test( releaseFile ) ) {
				// Map files need to reference the new uncompressed name;
				// assume that all files reside in the same directory.
				// "file":"jquery.min.js","sources":["jquery.js"]
				text = fs.readFileSync( builtFile, "utf8" )
					.replace( /"file":"([^"]+)","sources":\["([^"]+)"\]/,
						"\"file\":\"" + releaseFile.replace( /\.min\.map/, ".min.js" ) +
						"\",\"sources\":[\"" + releaseFile.replace( /\.min\.map/, ".js" ) + "\"]" );
				console.log( "Modifying map " + builtFile + " to " + releaseFile );
				if ( !debug ) {
					fs.writeFileSync( "dist/" + releaseFile, text );
				}
			} else {
				copy( builtFile, "dist/" + releaseFile );
			}

			jQueryFilesCDN.push( releaseFile );
		}
	});
	next();
}

function setNextVersion( next ) {
	updatePackageVersion( nextVersion );
	git( [ "commit", "-a", "-m", "Updating the source version to " + nextVersion ], next, debug );
}

function copyTojQueryCDN( next ) {
	var cmds = [];

	jQueryFilesCDN.forEach(function( name ) {
		cmds.push(function( nxt ){
			exec( "scp", [ name, scpURL ], nxt, debug || skipRemote );
		});
		cmds.push(function( nxt ){
			exec( "curl", [ cdnURL + name + "?reload" ], nxt, debug || skipRemote );
		});
	});
	cmds.push( next );

	steps.apply( this, cmds );
}

function buildGoogleCDN( next ) {
	makeArchive( "googlecdn", googleFilesCDN, next );
}

function buildMicrosoftCDN( next ) {
	makeArchive( "mscdn", msFilesCDN, next );
}

function pushToGithub( next ) {
	git( [ "push", "--tags", repoURL, branch ], next, debug || skipRemote );
}

//==============================

function steps() {
	var cur = 0,
		steps = arguments;
	(function next(){
		process.nextTick(function(){
			steps[ cur++ ]( next );
		});
	})();
}

function updatePackageVersion( ver ) {
	console.log( "Updating package.json version to " + ver );
	pkg.version = ver;
	if ( !debug ) {
		fs.writeFileSync( "package.json", JSON.stringify( pkg, null, "\t" ) + "\n" );
	}
}

function makeArchive( cdn, files, fn ) {
	if ( isBeta ) {
		console.log( "Skipping archive creation for " + cdn + "; " + releaseVersion + " is beta" );
		process.nextTick( fn );
		return;
	}

	console.log( "Creating production archive for " + cdn );

	var gzipper = zlib.createGzip( gzipOptions );
	var output = fs.createWriteStream( "dist/" + cdn + "-jquery-" + releaseVersion + ".tar.gz" );

	var archive = archiver( "tar" );

	archive.on( "error", function( err ) {
		throw err;
	});

	output.on( "close", fn );

	archive.pipe( gzipper ).pipe( output );

	files = files.map(function( item ) {
		return "dist/" + item.replace( /VER/g, releaseVersion );
	});

	var md5file = "dist/" + cdn + "-md5.txt";
	exec( "md5sum", files, function( err, stdout, stderr ) {
		fs.writeFileSync( md5file, stdout );
		files.push( md5file );

		files.forEach(function( file ) {
			archive.append( fs.createReadStream( file ), { name: file } );
		});

		archive.finalize();
	}, false );
}

function copy( oldFile, newFile ) {
	console.log( "Copying " + oldFile + " to " + newFile );
	if ( !debug ) {
		fs.writeFileSync( newFile, fs.readFileSync( oldFile, "utf8" ) );
	}
}

function git( args, fn, skip ) {
	exec( "git", args, fn, skip );
}

function exec( cmd, args, fn, skip ) {
	if ( skip ) {
		console.log( "# " + cmd + " " + args.join(" ") );
		fn( "", "", "" );
	} else {
		console.log( cmd + " " + args.join(" ") );
		child.execFile( cmd, args, { env: process.env },
			function( err, stdout, stderr ) {
				if ( err ) {
					die( stderr || stdout || err );
				}
				fn.apply( this, arguments );
			}
		);
	}
}

function dieIfReal( msg ) {
	if ( debug ) {
		console.log ( "DIE: " + msg );
	} else {
		die( msg );
	}
}

function die( msg ) {
	console.error( "ERROR: " + msg );
	process.exit( 1 );
}

function exit() {
	process.exit( 0 );
}
<commit_msg>build: switch from .min.gz to .zip format. (cherry picked from commit 5e8a5f4adcbaf07a8306f8a6a14a9fbcda81afb8)<commit_after>#!/usr/bin/env node
/*
 * jQuery Core Release Management
 */

// Debugging variables
var	debug = false,
	skipRemote = false;

var fs = require("fs"),
	child = require("child_process"),
	path = require("path"),
	archiver = require("archiver");

var releaseVersion,
	nextVersion,
	isBeta,
	pkg,
	branch,

	scpURL = "jqadmin@code.origin.jquery.com:/var/www/html/code.jquery.com/",
	cdnURL = "http://code.origin.jquery.com/",
	repoURL = "git@github.com:jquery/jquery.git",

	// Windows needs the .cmd version but will find the non-.cmd
	// On Windows, ensure the HOME environment variable is set
	gruntCmd = process.platform === "win32" ? "grunt.cmd" : "grunt",

	devFile = "dist/jquery.js",
	minFile = "dist/jquery.min.js",
	mapFile = "dist/jquery.min.map",

	releaseFiles = {
		"jquery-VER.js": devFile,
		"jquery-VER.min.js": minFile,
		"jquery-VER.min.map": mapFile,
		"jquery.js": devFile,
		"jquery.min.js": minFile,
		"jquery.min.map": mapFile,
		"jquery-latest.js": devFile,
		"jquery-latest.min.js": minFile,
		"jquery-latest.min.map": mapFile
	},

	jQueryFilesCDN = [],

	googleFilesCDN = [
		"jquery.js", "jquery.min.js", "jquery.min.map"
	],

	msFilesCDN = [
		"jquery-VER.js", "jquery-VER.min.js", "jquery-VER.min.map"
	];

steps(
	initialize,
	checkGitStatus,
	tagReleaseVersion,
	gruntBuild,
	makeReleaseCopies,
	setNextVersion,
	copyTojQueryCDN,
	buildGoogleCDN,
	buildMicrosoftCDN,
	pushToGithub,
	exit
);

function initialize( next ) {

	if ( process.argv[2] === "-d" ) {
		process.argv.shift();
		debug = true;
		console.warn("=== DEBUG MODE ===" );
	}

	// First arg should be the version number being released
	var newver, oldver,
		rsemver = /^(\d+)\.(\d+)\.(\d+)(?:-([\dA-Za-z\-]+(?:\.[\dA-Za-z\-]+)*))?$/,
		version = ( process.argv[3] || "" ).toLowerCase().match( rsemver ) || {},
		major = version[1],
		minor = version[2],
		patch = version[3],
		xbeta = version[4];

	branch = process.argv[2];
	releaseVersion = process.argv[3];
	isBeta = !!xbeta;

	if ( !branch || !major || !minor || !patch ) {
		die( "Usage: " + process.argv[1] + " branch releaseVersion" );
	}
	if ( xbeta === "pre" ) {
		die( "Cannot release a 'pre' version!" );
	}
	if ( !(fs.existsSync || path.existsSync)( "package.json" ) ) {
		die( "No package.json in this directory" );
	}
	pkg = JSON.parse( fs.readFileSync( "package.json" ) );

	console.log( "Current version is " + pkg.version + "; generating release " + releaseVersion );
	version = pkg.version.match( rsemver );
	oldver = ( +version[1] ) * 10000 + ( +version[2] * 100 ) + ( +version[3] )
	newver = ( +major ) * 10000 + ( +minor * 100 ) + ( +patch );
	if ( newver < oldver ) {
		die( "Next version is older than current version!" );
	}

	nextVersion = major + "." + minor + "." + ( isBeta ? patch : +patch + 1 ) + "-pre";
	next();
}

function checkGitStatus( next ) {
	git( [ "status" ], function( error, stdout, stderr ) {
		var onBranch = ((stdout||"").match( /On branch (\S+)/ ) || [])[1];
		if ( onBranch !== branch ) {
			dieIfReal( "Branches don't match: Wanted " + branch + ", got " + onBranch );
		}
		if ( /Changes to be committed/i.test( stdout ) ) {
			dieIfReal( "Please commit changed files before attemping to push a release." );
		}
		if ( /Changes not staged for commit/i.test( stdout ) ) {
			dieIfReal( "Please stash files before attempting to push a release." );
		}
		next();
	});
}

function tagReleaseVersion( next ) {
	updatePackageVersion( releaseVersion );
	git( [ "commit", "-a", "-m", "Tagging the " + releaseVersion + " release." ], function(){
		git( [ "tag", releaseVersion ], next, debug);
	}, debug);
}

function gruntBuild( next ) {
	exec( gruntCmd, [], function( error, stdout ) {
		if ( error ) {
			die( error + stderr );
		}
		console.log( stdout );
		next();
	}, false );
}

function makeReleaseCopies( next ) {
	Object.keys( releaseFiles ).forEach(function( key ) {
		var text,
			builtFile = releaseFiles[ key ],
			releaseFile = key.replace( /VER/g, releaseVersion );

		// Beta releases don't update the jquery-latest etc. copies
		if ( !isBeta || key !== releaseFile ) {

			if ( /\.map$/.test( releaseFile ) ) {
				// Map files need to reference the new uncompressed name;
				// assume that all files reside in the same directory.
				// "file":"jquery.min.js","sources":["jquery.js"]
				text = fs.readFileSync( builtFile, "utf8" )
					.replace( /"file":"([^"]+)","sources":\["([^"]+)"\]/,
						"\"file\":\"" + releaseFile.replace( /\.min\.map/, ".min.js" ) +
						"\",\"sources\":[\"" + releaseFile.replace( /\.min\.map/, ".js" ) + "\"]" );
				console.log( "Modifying map " + builtFile + " to " + releaseFile );
				fs.writeFileSync( "dist/" + releaseFile, text );
			} else {
				copy( builtFile, "dist/" + releaseFile );
			}

			jQueryFilesCDN.push( releaseFile );
		}
	});
	next();
}

function setNextVersion( next ) {
	updatePackageVersion( nextVersion );
	git( [ "commit", "-a", "-m", "Updating the source version to " + nextVersion ], next, debug );
}

function copyTojQueryCDN( next ) {
	var cmds = [];

	jQueryFilesCDN.forEach(function( name ) {
		cmds.push(function( nxt ){
			exec( "scp", [ name, scpURL ], nxt, debug || skipRemote );
		});
		cmds.push(function( nxt ){
			exec( "curl", [ cdnURL + name + "?reload" ], nxt, debug || skipRemote );
		});
	});
	cmds.push( next );

	steps.apply( this, cmds );
}

function buildGoogleCDN( next ) {
	makeArchive( "googlecdn", googleFilesCDN, next );
}

function buildMicrosoftCDN( next ) {
	makeArchive( "mscdn", msFilesCDN, next );
}

function pushToGithub( next ) {
	git( [ "push", "--tags", repoURL, branch ], next, debug || skipRemote );
}

//==============================

function steps() {
	var cur = 0,
		steps = arguments;
	(function next(){
		process.nextTick(function(){
			steps[ cur++ ]( next );
		});
	})();
}

function updatePackageVersion( ver ) {
	console.log( "Updating package.json version to " + ver );
	pkg.version = ver;
	if ( !debug ) {
		fs.writeFileSync( "package.json", JSON.stringify( pkg, null, "\t" ) + "\n" );
	}
}

function makeArchive( cdn, files, fn ) {
	if ( isBeta ) {
		console.log( "Skipping archive creation for " + cdn + "; " + releaseVersion + " is beta" );
		process.nextTick( fn );
		return;
	}

	console.log( "Creating production archive for " + cdn );

	var archive = archiver( "zip" ),
		md5file = "dist/" + cdn + "-md5.txt",
		output = fs.createWriteStream( "dist/" + cdn + "-jquery-" + releaseVersion + ".zip" );

	archive.on( "error", function( err ) {
		throw err;
	});

	output.on( "close", fn );
	archive.pipe( output );

	files = files.map(function( item ) {
		return "dist/" + item.replace( /VER/g, releaseVersion );
	});

	exec( "md5sum", files, function( err, stdout, stderr ) {
		fs.writeFileSync( md5file, stdout );
		files.push( md5file );

		files.forEach(function( file ) {
			archive.append( fs.createReadStream( file ), { name: file } );
		});

		archive.finalize();
	}, false );
}

function copy( oldFile, newFile, skip ) {
	console.log( "Copying " + oldFile + " to " + newFile );
	if ( !skip ) {
		fs.writeFileSync( newFile, fs.readFileSync( oldFile, "utf8" ) );
	}
}

function git( args, fn, skip ) {
	exec( "git", args, fn, skip );
}

function exec( cmd, args, fn, skip ) {
	if ( skip ) {
		console.log( "# " + cmd + " " + args.join(" ") );
		fn( "", "", "" );
	} else {
		console.log( cmd + " " + args.join(" ") );
		child.execFile( cmd, args, { env: process.env },
			function( err, stdout, stderr ) {
				if ( err ) {
					die( stderr || stdout || err );
				}
				fn.apply( this, arguments );
			}
		);
	}
}

function dieIfReal( msg ) {
	if ( debug ) {
		console.log ( "DIE: " + msg );
	} else {
		die( msg );
	}
}

function die( msg ) {
	console.error( "ERROR: " + msg );
	process.exit( 1 );
}

function exit() {
	process.exit( 0 );
}
<|endoftext|>


<commit_before>
var app = {
  // Application Constructor
  initialize: function() {
    this.frobulateManager = null;
    this.bindEvents();
  },
  // Bind Event Listeners
  //
  // Bind any events that are required on startup.
  bindEvents: function() {
    window.addEventListener('load', this.onLoad, false);
  },
  // load Event Handler
  //
  // The scope of 'this' is the event. In order to call the 'receivedEvent'
  // function, we must explicitly call 'app.receivedEvent(...);'
  onLoad: function() {
  	clobberlog();

    if (!('getFrobulate' in navigator)) {
      console.log('navigator.getFrobulate is not defined');
      return;
    }

    console.log('Hooray, we have navigator.getFrobulate');

    navigator.getFrobulate()
      .then(function(frobulate) {
        app.frobulateManager = frobulate;

        app.updateStateValue();
        app.updateLevelValue();

        app.frobulateManager.addEventListener('statechange', app.stateChangedEvent);
        app.frobulateManager.addEventListener('levelchange', app.levelChangedEvent);

        document.getElementById("DoButton").onclick = function () {
          doSomething();
        };

	    });
	},

  updateStateValue: function() {
    document.getElementById('RunningInput').value = app.frobulateManager.running;
  },

  updateLevelValue: function() {
    document.getElementById('LevelInput').value = app.frobulateManager.level;
  },

  stateChangedEvent: function(evt) {
    console.log('Received Event: ' + evt.type);
    app.updateStateValue();
  },

  levelChangedEvent: function(evt) {
    console.log('Received Event: ' + evt.type);
    app.updateLevelValue();
  }
};

function doSomething () {
  navigator.getFrobulate()
    .then(function(frobulate) {
      frobulate.doSomethingNow();
    });
}

function newLog (arg) {
    var textArea = document.getElementById("console");
    textArea.value = timestamp() + ": " + arg + '\n' + textArea.value;
}

function clobberlog (arg) {
    var oldLog = Function.prototype.bind.call(console.log, console);
    console.log = function (arg) {
	oldLog(arg);
	newLog(arg);
    };
}

function timestamp () {
    var date = new Date();
    var ms = date.getMilliseconds();
    var s = date.getSeconds();
    var mi = date.getMinutes();
    var h = date.getHours();
    var d = date.getDate();
    var mo = date.getMonth() + 1;
    var y = date.getFullYear();
    function z (num) {
	return "" + (num < 10 ? "0" : "") + num;
    }
    return "" + y + ":" + z(mo) + ":" + z(d) + ":" + z(h) + ":" + z(mi) + ":" + z(s) + ":" + (ms < 100 ? "0" : "") + (ms < 10 ? "0" : "") + ms;
}

function objectToString (object) {
    var toPrint = "";
    for (var propertyName in object) {
	if (typeof object[propertyName] === 'function') {
	    continue;
	}
	if (propertyName[0] === '_') {
	    continue;
	}
	toPrint = toPrint + '\n\t' + propertyName + ": " + object[propertyName];
    }
    return toPrint;
}

app.initialize();
<commit_msg>Add existence checks for attributes on sample API<commit_after>
var app = {
  // Application Constructor
  initialize: function() {
    this.frobulateManager = null;
    this.bindEvents();
  },
  // Bind Event Listeners
  //
  // Bind any events that are required on startup.
  bindEvents: function() {
    window.addEventListener('load', this.onLoad, false);
  },
  // load Event Handler
  //
  // The scope of 'this' is the event. In order to call the 'receivedEvent'
  // function, we must explicitly call 'app.receivedEvent(...);'
  onLoad: function() {
  	clobberlog();

    if (!('getFrobulate' in navigator)) {
      console.log('navigator.getFrobulate is not defined');
      return;
    }

    console.log('Hooray, we have navigator.getFrobulate');

    navigator.getFrobulate()
      .then(function(frobulate) {
        app.frobulateManager = frobulate;

        app.updateStateValue();
        app.updateLevelValue();

        app.frobulateManager.addEventListener('statechange', app.stateChangedEvent);
        app.frobulateManager.addEventListener('levelchange', app.levelChangedEvent);

        document.getElementById("DoButton").onclick = function () {
          doSomething();
        };

	    });
	},

  updateStateValue: function() {
    if (app.frobulateManager.running) {
      document.getElementById('RunningInput').value = app.frobulateManager.running;
      return;
    }
    document.getElementById('RunningInput').value = "[not supported]";
  },

  updateLevelValue: function() {
    if (app.frobulateManager.level) {
      document.getElementById('LevelInput').value = app.frobulateManager.level;
      return;
    }
    document.getElementById('LevelInput').value = "[not supported]";
  },

  stateChangedEvent: function(evt) {
    console.log('Received Event: ' + evt.type);
    app.updateStateValue();
  },

  levelChangedEvent: function(evt) {
    console.log('Received Event: ' + evt.type);
    app.updateLevelValue();
  }
};

function doSomething () {
  navigator.getFrobulate()
    .then(function(frobulate) {
      frobulate.doSomethingNow();
    });
}

function newLog (arg) {
    var textArea = document.getElementById("console");
    textArea.value = timestamp() + ": " + arg + '\n' + textArea.value;
}

function clobberlog (arg) {
    var oldLog = Function.prototype.bind.call(console.log, console);
    console.log = function (arg) {
	oldLog(arg);
	newLog(arg);
    };
}

function timestamp () {
    var date = new Date();
    var ms = date.getMilliseconds();
    var s = date.getSeconds();
    var mi = date.getMinutes();
    var h = date.getHours();
    var d = date.getDate();
    var mo = date.getMonth() + 1;
    var y = date.getFullYear();
    function z (num) {
	return "" + (num < 10 ? "0" : "") + num;
    }
    return "" + y + ":" + z(mo) + ":" + z(d) + ":" + z(h) + ":" + z(mi) + ":" + z(s) + ":" + (ms < 100 ? "0" : "") + (ms < 10 ? "0" : "") + ms;
}

function objectToString (object) {
    var toPrint = "";
    for (var propertyName in object) {
	if (typeof object[propertyName] === 'function') {
	    continue;
	}
	if (propertyName[0] === '_') {
	    continue;
	}
	toPrint = toPrint + '\n\t' + propertyName + ": " + object[propertyName];
    }
    return toPrint;
}

app.initialize();
<|endoftext|>


<commit_before>"use strict";
var Joi = require('joi');
/**
 * Pickup schema.
 *
 * @description Pickup definition schema.
 *
 * @author Leonardo Cabral <leomcabral@gmail.com>
 * @since 02/28/2016
 */
function PickupSchema() {
    this.schema = {
        requester: Joi.string().description('User id that requested the pickup'),
        address: {
            street: Joi.string(),
            city: Joi.string(),
            state: Joi.string(),
            zip: Joi.string(),
            location: Joi.object({
                type: Joi.string(),
                coordinates: Joi.array().items(Joi.number())
            })
        },
        time: Joi.date().description('Date/time to the pickup'),
        instructions: Joi.string().description('Instructions to the binner'),
        items: Joi.array().items(Joi.object({
            type: Joi.string().valid('can', 'bottle').description('Type of item'),
            packageSize: Joi.string().valid('small', 'medium', 'large').description('Size classification of the units'),
            quantity: Joi.string().description('Number of packages of this type and size. May be a string.')
        })),
        authorization: Joi.object({
            'Authorization': Joi.string().description('Authorization Token')
        }).unknown()
    };
}
module.exports = PickupSchema;<commit_msg>POST /api/v1.0/pickup #46<commit_after>"use strict";
var Joi = require('joi');
/**
 * Pickup schema.
 *
 * @description Pickup definition schema.
 *
 * @author Leonardo Cabral <leomcabral@gmail.com>
 * @since 02/28/2016
 */
function PickupSchema() {
    this.schema = {
        requester: Joi.string().description('User id that requested the pickup'),
        address: {
            street: Joi.string(),
            //TODO: this field is candidate to return
            // city: Joi.string(),
            //TODO: this field is candidate to return
            // state: Joi.string(),
            //TODO: this field is candidate to return
            // zip: Joi.string(),
            location: Joi.object({
                //TODO: this field is candidate to return
                // type: Joi.string(),
                coordinates: Joi.array().items(Joi.number())
            })
        },
        time: Joi.date().description('Date/time to the pickup'),
        instructions: Joi.string().description('Instructions to the binner'),
        items: Joi.array().items(Joi.object({
            //TODO: this field is candidate to return
            // type: Joi.string().valid('can', 'bottle').description('Type of item'),
            //TODO: this field is candidate to return
            // packageSize: Joi.string().valid('small', 'medium', 'large').description('Size classification of the units'),
            quantity: Joi.string().description('Number of packages of this type and size. May be a string.')
        })),
        authorization: Joi.object({
            'Authorization': Joi.string().description('Authorization Token')
        }).unknown()
    };
}
module.exports = PickupSchema;<|endoftext|>


<commit_before>//SET ROUTER DISINI
var windingQualitySamplingRouter = require('../src/routers/v1/spinning/winding/winding-quality-sampling-router');
var windingMachingByUnitRouter = require('../src/routers/v1/spinning/winding/machine-by-unit-router');
var windingQualitySamplingReportRouter = require('../src/routers/v1/spinning/winding/reports/winding-quality-sampling-report-router');

//WINDING PRODUCTION OUTPUT
var windingProductionOutputByUserRouter = require('../src/routers/v1/spinning/winding/winding-production-output/winding-production-output-by-user-router');
var lotMachineByProductMachineRouter = require('../src/routers/v1/spinning/winding/winding-production-output/lot-machine-by-product-machine-router');
var dailySpinningProductionReportRouter = require('../src/routers/v1/spinning/winding/reports/daily-spinning-production-report-router');

//PRODUCTION ORDER
var productionOrderRouter = require('../src/routers/v1/sales/production-order-router');
var productionOrderReportRouter = require('../src/routers/v1/sales/reports/production-order-report-router');
var materialRouter = require('../src/routers/v1/sales/material-router');

//DAILY OPERATION
var DailyOperationRouter = require('../src/routers/v1/finishing-printing/daily-operation-router');
var DailyOperationReportRouter = require('../src/routers/v1/finishing-printing/reports/daily-operation-report-router');

//MONITORING EVENT
var monitoringEventRouter = require('../src/routers/v1/finishing-printing/monitoring-event-router');
var monitoringEventReportRouter = require('../src/routers/v1/finishing-printing/reports/monitoring-event-report-router');

//MONITORING SPECIFICATION MACHINE
var monitoringSpecificationMachineRouter= require('../src/routers/v1/finishing-printing/monitoring-specification-machine-router');
var monitoringSpecificationMachineReportByEventRouter = require('../src/routers/v1/finishing-printing/reports/monitoring-specification-machine-by-event-router');
var monitoringSpecificationMachineReportRouter= require('../src/routers/v1/finishing-printing/reports/monitoring-specification-machine-report-router');

// KANBAN
var kanbanRouter = require('../src/routers/v1/finishing-printing/kanban-router');
var monitoringKanbanRouter= require('../src/routers/v1/finishing-printing/monitoring-kanban-router');

// QUALITY-CONTROL/FABRIC
var fabricQualityControlRouter= require('../src/routers/v1/finishing-printing/fabric-quality-control-router');
var packingRouter= require('../src/routers/v1/finishing-printing/packing-router');

//SALES CONTRACT
var finishingPrintingSalesContractRouter = require('../src/routers/v1/sales/finishing-printing-sales-contract-router');
var spinningSalesContractRouter = require('../src/routers/v1/sales/spinning-sales-contract-router');
var weavingSalesContractRouter = require('../src/routers/v1/sales/weaving-sales-contract-router');

var weavingSalesContractReportRouter = require('../src/routers/v1/sales/reports/weaving-sales-contract-report-router');

var finishingPrintingSalesContractReportRouter = require('../src/routers/v1/sales/reports/finishing-printing-sales-contract-report-router');
var spinningSalesContractReportRouter = require('../src/routers/v1/sales/reports/spinning-sales-contract-report-router');

module.exports = function(server) {
    windingQualitySamplingRouter().applyRoutes(server,                        "/spinning/winding/winding-quality-samplings");
    windingMachingByUnitRouter().applyRoutes(server,                          "/spinning/winding/machine-by-units");
    windingQualitySamplingReportRouter().applyRoutes(server,                  "/spinning/winding/reports/winding-quality-samplings");

    windingProductionOutputByUserRouter().applyRoutes(server,                 "/spinning/winding/production-outputs/by-user");
    lotMachineByProductMachineRouter().applyRoutes(server,                    "/spinning/winding/search-lots");
    dailySpinningProductionReportRouter().applyRoutes(server,                 "/spinning/winding/reports/daily-production");
    productionOrderRouter().applyRoutes(server,                               "/sales/production-orders");
    productionOrderReportRouter().applyRoutes(server,                         "/sales/reports/production-order-report");
    materialRouter().applyRoutes(server,                                      "/sales/materials");
    finishingPrintingSalesContractRouter().applyRoutes(server,                "/sales/finishing-printing-sales-contracts");
    spinningSalesContractRouter().applyRoutes(server,                         "/sales/spinning-sales-contracts");
    spinningSalesContractReportRouter().applyRoutes(server,                   "/sales/reports/spinning-sales-contract-reports");
    weavingSalesContractRouter().applyRoutes(server,                          "/sales/weaving-sales-contracts");
    weavingSalesContractReportRouter().applyRoutes(server,                    "/sales/reports/weaving-sales-contract-report");
    DailyOperationRouter().applyRoutes(server,                                "/finishing-printing/daily-operations");
    DailyOperationReportRouter().applyRoutes(server,                          "/finishing-printing/reports/daily-operation-report");
    monitoringEventRouter().applyRoutes(server,                               "/finishing-printing/monitoring-events");
    monitoringEventReportRouter().applyRoutes(server,                         "/finishing-printing/reports/monitoring-events");
    monitoringSpecificationMachineRouter().applyRoutes(server,                "/finishing-printing/monitoring-specification-machine");
    monitoringSpecificationMachineReportByEventRouter().applyRoutes(server,   "/finishing-printing/reports/monitoring-specification-machine/by-event");
    monitoringSpecificationMachineReportRouter().applyRoutes(server,          "/finishing-printing/reports/monitoring-specification-machine")
    monitoringKanbanRouter().applyRoutes(server,                              "/finishing-printing/monitoring-kanbans");
    kanbanRouter().applyRoutes(server,                                        "/finishing-printing/kanbans");

    fabricQualityControlRouter().applyRoutes(server,                          "/finishing-printing/quality-control/fabrics");
    packingRouter().applyRoutes(server,                                       "/finishing-printing/quality-control/packings");
    finishingPrintingSalesContractReportRouter().applyRoutes(server,          "/finishing-printing/reports/finishing-printing-sales-contract-reports");
};<commit_msg>add router default finishing printing sc by number<commit_after>//SET ROUTER DISINI
var windingQualitySamplingRouter = require('../src/routers/v1/spinning/winding/winding-quality-sampling-router');
var windingMachingByUnitRouter = require('../src/routers/v1/spinning/winding/machine-by-unit-router');
var windingQualitySamplingReportRouter = require('../src/routers/v1/spinning/winding/reports/winding-quality-sampling-report-router');

//WINDING PRODUCTION OUTPUT
var windingProductionOutputByUserRouter = require('../src/routers/v1/spinning/winding/winding-production-output/winding-production-output-by-user-router');
var lotMachineByProductMachineRouter = require('../src/routers/v1/spinning/winding/winding-production-output/lot-machine-by-product-machine-router');
var dailySpinningProductionReportRouter = require('../src/routers/v1/spinning/winding/reports/daily-spinning-production-report-router');

//PRODUCTION ORDER
var productionOrderRouter = require('../src/routers/v1/sales/production-order-router');
var productionOrderReportRouter = require('../src/routers/v1/sales/reports/production-order-report-router');
var materialRouter = require('../src/routers/v1/sales/material-router');

//DAILY OPERATION
var DailyOperationRouter = require('../src/routers/v1/finishing-printing/daily-operation-router');
var DailyOperationReportRouter = require('../src/routers/v1/finishing-printing/reports/daily-operation-report-router');

//MONITORING EVENT
var monitoringEventRouter = require('../src/routers/v1/finishing-printing/monitoring-event-router');
var monitoringEventReportRouter = require('../src/routers/v1/finishing-printing/reports/monitoring-event-report-router');

//MONITORING SPECIFICATION MACHINE
var monitoringSpecificationMachineRouter= require('../src/routers/v1/finishing-printing/monitoring-specification-machine-router');
var monitoringSpecificationMachineReportByEventRouter = require('../src/routers/v1/finishing-printing/reports/monitoring-specification-machine-by-event-router');
var monitoringSpecificationMachineReportRouter= require('../src/routers/v1/finishing-printing/reports/monitoring-specification-machine-report-router');

// KANBAN
var kanbanRouter = require('../src/routers/v1/finishing-printing/kanban-router');
var monitoringKanbanRouter= require('../src/routers/v1/finishing-printing/monitoring-kanban-router');

// QUALITY-CONTROL/FABRIC
var fabricQualityControlRouter= require('../src/routers/v1/finishing-printing/fabric-quality-control-router');
var packingRouter= require('../src/routers/v1/finishing-printing/packing-router');

//SALES CONTRACT
var finishingPrintingSalesContractRouter = require('../src/routers/v1/sales/finishing-printing-sales-contract-router');
var spinningSalesContractRouter = require('../src/routers/v1/sales/spinning-sales-contract-router');
var weavingSalesContractRouter = require('../src/routers/v1/sales/weaving-sales-contract-router');

var weavingSalesContractReportRouter = require('../src/routers/v1/sales/reports/weaving-sales-contract-report-router');

var finishingPrintingSalesContractReportRouter = require('../src/routers/v1/sales/reports/finishing-printing-sales-contract-report-router');
var spinningSalesContractReportRouter = require('../src/routers/v1/sales/reports/spinning-sales-contract-report-router');
var finishingPrintingSalesContractByNumberRouter = require('../src/routers/v1/sales/finishing-printing-sales-contract-by-number-router');

module.exports = function(server) {
    windingQualitySamplingRouter().applyRoutes(server,                        "/spinning/winding/winding-quality-samplings");
    windingMachingByUnitRouter().applyRoutes(server,                          "/spinning/winding/machine-by-units");
    windingQualitySamplingReportRouter().applyRoutes(server,                  "/spinning/winding/reports/winding-quality-samplings");

    windingProductionOutputByUserRouter().applyRoutes(server,                 "/spinning/winding/production-outputs/by-user");
    lotMachineByProductMachineRouter().applyRoutes(server,                    "/spinning/winding/search-lots");
    dailySpinningProductionReportRouter().applyRoutes(server,                 "/spinning/winding/reports/daily-production");
    productionOrderRouter().applyRoutes(server,                               "/sales/production-orders");
    productionOrderReportRouter().applyRoutes(server,                         "/sales/reports/production-order-report");
    materialRouter().applyRoutes(server,                                      "/sales/materials");
    finishingPrintingSalesContractRouter().applyRoutes(server,                "/sales/finishing-printing-sales-contracts");
    spinningSalesContractRouter().applyRoutes(server,                         "/sales/spinning-sales-contracts");
    spinningSalesContractReportRouter().applyRoutes(server,                   "/sales/reports/spinning-sales-contract-reports");
    weavingSalesContractRouter().applyRoutes(server,                          "/sales/weaving-sales-contracts");
    weavingSalesContractReportRouter().applyRoutes(server,                    "/sales/reports/weaving-sales-contract-report");
    DailyOperationRouter().applyRoutes(server,                                "/finishing-printing/daily-operations");
    DailyOperationReportRouter().applyRoutes(server,                          "/finishing-printing/reports/daily-operation-report");
    monitoringEventRouter().applyRoutes(server,                               "/finishing-printing/monitoring-events");
    monitoringEventReportRouter().applyRoutes(server,                         "/finishing-printing/reports/monitoring-events");
    monitoringSpecificationMachineRouter().applyRoutes(server,                "/finishing-printing/monitoring-specification-machine");
    monitoringSpecificationMachineReportByEventRouter().applyRoutes(server,   "/finishing-printing/reports/monitoring-specification-machine/by-event");
    monitoringSpecificationMachineReportRouter().applyRoutes(server,          "/finishing-printing/reports/monitoring-specification-machine")
    monitoringKanbanRouter().applyRoutes(server,                              "/finishing-printing/monitoring-kanbans");
    kanbanRouter().applyRoutes(server,                                        "/finishing-printing/kanbans");

    fabricQualityControlRouter().applyRoutes(server,                          "/finishing-printing/quality-control/fabrics");
    packingRouter().applyRoutes(server,                                       "/finishing-printing/quality-control/packings");
    finishingPrintingSalesContractReportRouter().applyRoutes(server,          "/finishing-printing/reports/finishing-printing-sales-contract-reports");
    finishingPrintingSalesContractByNumberRouter().applyRoutes(server,        "/sales/finishing-printing-sales-contract-by-number");
};<|endoftext|>


<commit_before>var http = require('http');
var url = require('url');
var config = require('../config');
var request = require('request');
var csv = require('csv');

var schedule = {};

var formatDate = function (date) {
    var pad = function (n){return n<10 ? '0'+n : n;};
    return pad(date.getMonth()+1) +
        pad(date.getDate()) +
        pad(date.getFullYear());
};

var callbackHeck = function (callbackOptions) {

};

var updateScheduleAsync = function () {
    var date = new Date();
    var startDate = formatDate(date);
    date.setDate(date.getDate() + 2);
    var endDate = formatDate(date);

    var url = 'http://www.xpiron.com/schedule/Access?pAction=20&pBorgID=2867&pEmailAddr=' +
            config.fitness.username +
            '&pPassword=' +
            config.fitness.password +
            '&pFirstPage=Reports?pAction=60&pType=20002&pStartDate=' +
            startDate +
            '&pEndDate=' +
            endDate +
            '&pServiceID=12552';

    request.get(url, function (error, response, body) {
        if (!error && response.statusCode == 200) {
            var data = csv()
                .from(body)
                .to.array(function (data, count) {
                    var allHeaders = data[0];
                    var headers = {};
                    headers[allHeaders.indexOf('GroupEvent')] = 'name';
                    headers[allHeaders.indexOf('Date')] = 'date';
                    headers[allHeaders.indexOf('Start Time')] = 'startTime';
                    headers[allHeaders.indexOf('End Time')] = 'endTime';
                    headers[allHeaders.indexOf('Instructor First Name')] = 'instructorFirstName';
                    headers[allHeaders.indexOf('Instructor Last Name')] = 'instructorLastName';
                    headers[allHeaders.indexOf('Location')] = 'location';

                    var newData = [];
                    for (var i=1; i<count; i++) {
                        newData[i-1] = {};
                        for (var prop in headers) {
                            newData[i-1][headers[prop]] = data[i][prop];
                        }
                    }
                    newData.sort(function(x, y) {

                        function setTime(timeString, dateObject) {
                            var time = timeString.match(/(\d+)(?::(\d\d))?\s*(p?)/);
                            dateObject.setHours(parseInt(time[1], 10) + (time[3] ? 12 : 0));
                            dateObject.setMinutes(parseInt(time[2], 10) || 0);
                            return dateObject;
                        }

                        var xDate = new Date(x.date);
                        xDate = setTime(x.startTime, xDate);
                        var yDate = new Date(y.date);
                        yDate = setTime(y.startTime, yDate);

                        if (xDate < yDate) {
                            return -1;
                        }
                        if (xDate > yDate) {
                            return 1;
                        }
                        return 0;
                    });
                    schedule.classes = newData;
                    schedule.lastUpdated = Date.now();
                });
        } else {
            console.log('fitness/schedule error: ' + JSON.stringify(error));
            console.log('HTTP status code: ' + response.statusCode);
        }
    });
};

updateScheduleAsync();

exports.schedule = function (req, res) {
    'use strict';

    if (typeof schedule === "undefined" || ! schedule.lastUpdated) {
        schedule = {};
        updateScheduleAsync();
    } else if (Date.now() - schedule.lastUpdated > 1000 * 60 * 60) {
        // schedule is older than an hour, refresh it
        updateScheduleAsync();
    }

    res.send(schedule);
};<commit_msg>stricter linting<commit_after>var config = require('../config');
var request = require('request');
var csv = require('csv');

var schedule = {};

var formatDate = function (date) {
	'use strict';
    var pad = function (n) { return n < 10 ? '0' + n : n; };
    return pad(date.getMonth() + 1) +
        pad(date.getDate()) +
        pad(date.getFullYear());
};

var updateScheduleAsync = function () {
	'use strict';
    var date = new Date();
    var startDate = formatDate(date);
    date.setDate(date.getDate() + 2);
    var endDate = formatDate(date);

    var url = 'http://www.xpiron.com/schedule/Access?pAction=20&pBorgID=2867&pEmailAddr=' +
            config.fitness.username +
            '&pPassword=' +
            config.fitness.password +
            '&pFirstPage=Reports?pAction=60&pType=20002&pStartDate=' +
            startDate +
            '&pEndDate=' +
            endDate +
            '&pServiceID=12552';

    request.get(url, function (error, response, body) {
        if (!error && response.statusCode === 200) {
            csv()
                .from(body)
                .to.array(function (data, count) {
                    var allHeaders = data[0];
                    var headers = {};
                    headers[allHeaders.indexOf('GroupEvent')] = 'name';
                    headers[allHeaders.indexOf('Date')] = 'date';
                    headers[allHeaders.indexOf('Start Time')] = 'startTime';
                    headers[allHeaders.indexOf('End Time')] = 'endTime';
                    headers[allHeaders.indexOf('Instructor First Name')] = 'instructorFirstName';
                    headers[allHeaders.indexOf('Instructor Last Name')] = 'instructorLastName';
                    headers[allHeaders.indexOf('Location')] = 'location';

                    var newData = [];
                    for (var i = 1; i < count; i++) {
                        newData[i - 1] = {};
                        for (var prop in headers) {
                            newData[i - 1][headers[prop]] = data[i][prop];
                        }
                    }
                    newData.sort(function (x, y) {

                        function setTime(timeString, dateObject) {
                            var time = timeString.match(/(\d+)(?::(\d\d))?\s*(p?)/);
                            dateObject.setHours(parseInt(time[1], 10) + (time[3] ? 12 : 0));
                            dateObject.setMinutes(parseInt(time[2], 10) || 0);
                            return dateObject;
                        }

                        var xDate = new Date(x.date);
                        xDate = setTime(x.startTime, xDate);
                        var yDate = new Date(y.date);
                        yDate = setTime(y.startTime, yDate);

                        if (xDate < yDate) {
                            return -1;
                        }
                        if (xDate > yDate) {
                            return 1;
                        }
                        return 0;
                    });
                    schedule.classes = newData;
                    schedule.lastUpdated = Date.now();
                });
        } else {
            console.log('fitness/schedule error: ' + JSON.stringify(error));
            console.log('HTTP status code: ' + response.statusCode);
        }
    });
};

updateScheduleAsync();

exports.schedule = function (req, res) {
    'use strict';

    if (typeof schedule === 'undefined' || ! schedule.lastUpdated) {
        schedule = {};
        updateScheduleAsync();
    } else if (Date.now() - schedule.lastUpdated > 1000 * 60 * 60) {
        // schedule is older than an hour, refresh it
        updateScheduleAsync();
    }

    res.send(schedule);
};<|endoftext|>


<commit_before>'use strict';

togglbutton.render('#channel_name:not(.toggl)', { observe: true }, function() {
  var link,
    placeholder = $('.channel_title_info'),
    project = $('#team_name').textContent,
    description = $('#channel_name')
      .textContent.trim()
      .replace(/^#/, '');

  link = togglbutton.createTimerLink({
    className: 'slack',
    description: description,
    projectName: project,
    buttonType: 'minimal'
  });

  placeholder.parentNode.insertBefore(link, placeholder);
});

togglbutton.render('.c-message--hover:not(.toggl)', { observe: true }, function(
  elem
) {
  var link,
    placeholder = $('.c-message_actions__button--last-child'),
    description = $('.c-message__body', elem).textContent,
    project = $('#team_name').textContent,
    button = document.createElement('button');

  link = togglbutton.createTimerLink({
    className: 'slack-message',
    projectName: project,
    description: description,
    buttonType: 'minimal'
  });

  button.className = 'c-button-unstyled c-message_actions__button';
  button.setAttribute('type', 'button');
  button.appendChild(link);

  placeholder.parentNode.insertBefore(button, placeholder);
});
<commit_msg>Fix individual message button in Slack<commit_after>'use strict';

togglbutton.render('#channel_name:not(.toggl)', { observe: true }, function() {
  var link,
    placeholder = $('.channel_title_info'),
    project = $('#team_name').textContent,
    description = $('#channel_name')
      .textContent.trim()
      .replace(/^#/, '');

  link = togglbutton.createTimerLink({
    className: 'slack',
    description: description,
    projectName: project,
    buttonType: 'minimal'
  });

  placeholder.parentNode.insertBefore(link, placeholder);
});

togglbutton.render('.c-message--hover:not(.toggl)', { observe: true }, function(
  elem
) {
  var link,
    placeholder = $('.c-message_actions__button:last-child'),
    description = $('.c-message__body', elem).textContent,
    project = $('#team_name').textContent,
    button = document.createElement('button');

  link = togglbutton.createTimerLink({
    className: 'slack-message',
    projectName: project,
    description: description,
    buttonType: 'minimal'
  });

  button.className = 'c-button-unstyled c-message_actions__button';
  button.setAttribute('type', 'button');
  button.appendChild(link);

  placeholder.parentNode.insertBefore(button, placeholder);
});
<|endoftext|>


<commit_before>/*
-----------------------------------------------------------------------------
Copyright (c) 2014-2015 Seth Anderson

This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the
use of this software.

Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:

1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software in a
product, an acknowledgment in the product documentation would be appreciated
but is not required.

2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.

3. This notice may not be removed or altered from any source distribution.
-----------------------------------------------------------------------------
*/

var passport = require("passport"),
	mongoose = require("mongoose"),
	q = require("q"),
	User = require("../model/user.js"),
	Token = require("../model/token.js"),
	authorize = require("../authorization.js").authorize,
	authorizeSessionUser = require("../authorization.js").authorizeSessionUser,
	register = require("../utils/common.js").register,
	login = require("../utils/common.js").login,
	authenticate = require("../utils/common.js").authenticate,
	verifyRecaptcha = require("../utils/common.js").verifyRecaptcha,
	removeDuplicates = require("../utils/common.js").removeDuplicates,
	sanitizeBodyForDB = require("../utils/common.js").sanitizeBodyForDB,
	smtp = require("../utils/smtp.js"),
	config = require("../utils/common.js").config;

module.exports = function(app, prefix){
	app.post(prefix + "/register",
		verifyRecaptcha,
		register,
	function(req, res){
		if(req.isAuthenticated()){
			// Send email for verification
			// Respond with "201 Created"
			res.status(201).send(req.user._id.toString());
		}else{
			res.status(403).end();
		}
	});

	app.post(prefix + "/login",
		login,
	function(req, res){
		if(req.isAuthenticated()){
			res.status(200).end();
		}else{
			res.status(403).end();
		}
	});

	app.post(prefix + "/logout", function(req, res){
		req.logout();
		res.status(200).end();
	});

	app.get(prefix + "/isloggedin", function(req, res){
		res.send({isLoggedIn: req.isAuthenticated()});
	});

	app.post(prefix + "/:user/verify",
		authenticate,
		authorizeSessionUser(),
	function(req, res){
		if(!mongoose.Types.ObjectId.isValid(req.params.user)){
			return res.status(404).end();
		}

		User.findById(req.params.user, function(err, doc){
			if(err){
				res.status(500).end();
			}else if(!doc){
				res.status(404).end();
			}else{
				smtp.sendEmailVerification(app, doc, req.protocol + '://' + config.domain)
				.then(function(){
					res.status(200).end();
				}).catch(function(err){
					res.status(400).end();
				});
			}
		});
	});

	app.post(prefix + "/:user/verify/:token", function(req, res){
		if(!mongoose.Types.ObjectId.isValid(req.params.user)){
			return res.status(404).end();
		}

		var deferredUser = q.defer(), deferredToken = q.defer(),
			verified = false;
		User.findById(req.params.user, function(err, doc){
			if(err){
				deferredUser.reject({reason: "db-error", message: err});
			}else if(!doc){
				deferredUser.reject({reason: "not-found", message: "User not found"});
			}else{
				verified = doc.verified;
				deferredUser.resolve(doc);
			}
		});
		Token.findOne({token: req.params.token}, function(err, doc){
			if(err){
				deferredToken.reject({reason: "db-error", message: err});
			}else if(!doc){
				deferredToken.reject({reason: "not-found", message: "Token not found"});
			}else{
				deferredToken.resolve(doc);
			}
		});
		q.all([deferredUser.promise, deferredToken.promise])
		.spread(function(user, token){
			if(verified){
				res.status(200).end();
				return;
			}
			if(token.validate(user.email)){
				user.verified = true;
				user.modified = Date.now();
				user.save(function(err){
					if(err){
						console.error("Error: Successfully verified token for user \"" + user.email + "\", but failed to update flag");
						res.status(500).end();
					}else{
						user.syncWithDirectory()
						.then(function(){
							res.status(200).end();
						}).catch(function(err){
							console.error("Error: Successfully verified token for user \"" + user.email + "\", but failed to sync with directory");
							res.status(500).end();
						});
					}
				});
			}else{
				res.status(400).end();
			}
		}).catch(function(err){
			if(verified){
				res.status(200).end();
				return;
			}
			if(err.reason === "db-error"){
				res.status(500).end();
			}else if(err.reason === "not-found"){
				res.status(404).end();
			}else{
				res.status(400).end();
			}
		});
	});

	app.get(prefix + "/:user/verified",
		authenticate,
		authorizeSessionUser(),
	function(req, res){
		if(!mongoose.Types.ObjectId.isValid(req.params.user)){
			return res.status(404).end();
		}
		// Retrieve and return the "verified" value
		User.findById(req.params.user, function(err, doc){
			if(doc){
				res.status(200).send({verified: doc.verified});
			}else{
				res.status(404).end();
			}
		});
	});

	app.get(prefix,
		authenticate,
		authorize({hasRoles: ["admin"]}),
	function(req, res){
		User.find({}, function(err, docs){
			if(err){
				res.status(500).end();
			}else{
				res.send(docs || []);
			}
		});
	});

	app.get(prefix + "/:user",
		authenticate,
		authorizeSessionUser(),
	function(req, res){
		if(!mongoose.Types.ObjectId.isValid(req.params.user)){
			return res.status(404).end();
		}
		User.findById(req.params.user, function(err, doc){
			if(err){
				res.status(500).end();
			}else if(!doc){
				res.status(404).end();
			}else{
				var responseData = {
					email: doc.email,
					verified: doc.verified,
					created: doc.created,
					modified: doc.modified,
					accessed: doc.accessed,
					vip: doc.vip,
					lanInviteDesired: doc.lanInviteDesired,
					firstName: doc.firstName,
					lastName: doc.lastName,
					primaryHandle: doc.primaryHandle,
					tertiaryHandles: doc.tertiaryHandles,
					roles: doc.roles,
					services: doc.services
				};

				if(req.user.hasRole("admin")){
					responseData.__v = doc.__v;
					responseData._id = doc._id;
					responseData.blacklisted = doc.blacklisted;
				}

				res.send(responseData);
			}
		});
	});

	app.post(prefix,
		authenticate,
		authorize({hasRoles: ["admin"]}),
		sanitizeBodyForDB,
	function(req, res){
		if(req.body.roles){
			req.body.roles = removeDuplicates(req.body.roles);
		}
		User.createNew(req.body)
		.then(function(newUser){
			res.status(201)
			.location(prefix + "/" + newUser._id)
			.send({_id: newUser._id});
		}).catch(function(err){
			res.status(400).end();
		});
	});

	app.put(prefix + "/:user",
		authenticate,
		authorizeSessionUser(),
		sanitizeBodyForDB,
	function(req, res){
		if(!mongoose.Types.ObjectId.isValid(req.params.user)){
			return res.status(404).end();
		}

		// Update the user
		User.findById(req.params.user, function(err, doc){
			if(err){
				res.status(400).end();
			}else if(!doc){
				res.status(404).end();
			}else{
				if(req.body.email !== doc.email){
					doc.verified = false;
				}
				doc.email = req.body.email;
				doc.firstName = req.body.firstName;
				doc.lastName = req.body.lastName;
				doc.lanInviteDesired = req.body.lanInviteDesired;
				doc.primaryHandle = req.body.primaryHandle;
				doc.tertiaryHandles = removeDuplicates(req.body.tertiaryHandles);
				doc.modified = Date.now();
				if(req.user.hasRole("admin")){
					doc.verified = req.body.verified;
					doc.vip = req.body.vip;
					doc.blacklisted = req.body.blacklisted;
					doc.roles = removeDuplicates(req.body.roles);
					doc.services = req.body.services;
				}
				doc.save(function(err){
					if(err){
						res.status(500).end();
					}else{
						doc.syncWithDirectory()
						.then(function(){
							res.status(200).end();
						}).catch(function(){
							res.status(500).end();
						});
					}
				});
			}
		});
	});

	app.put(prefix + "/:user/password",
		authenticate,
		authorizeSessionUser(),
	function(req, res){
		if(!mongoose.Types.ObjectId.isValid(req.params.user)){
			return res.status(404).end();
		}

		// Update the user
		User.findById(req.params.user, function(err, doc){
			if(err){
				res.status(400).end();
			}else if(!doc){
				res.status(404).end();
			}else{
				doc.changePassword(req.body.oldPassword, req.body.newPassword)
				.then(function(){
					res.status(200).end();
				}).catch(function(){
					res.status(400).end();
				});
			}
		});
	});
}
<commit_msg>Added a check to PUT /api/user/:user to fail early when attempting to change the email address to one that's already in use<commit_after>/*
-----------------------------------------------------------------------------
Copyright (c) 2014-2015 Seth Anderson

This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the
use of this software.

Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:

1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software in a
product, an acknowledgment in the product documentation would be appreciated
but is not required.

2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.

3. This notice may not be removed or altered from any source distribution.
-----------------------------------------------------------------------------
*/

var passport = require("passport"),
	mongoose = require("mongoose"),
	q = require("q"),
	User = require("../model/user.js"),
	Token = require("../model/token.js"),
	authorize = require("../authorization.js").authorize,
	authorizeSessionUser = require("../authorization.js").authorizeSessionUser,
	register = require("../utils/common.js").register,
	login = require("../utils/common.js").login,
	authenticate = require("../utils/common.js").authenticate,
	verifyRecaptcha = require("../utils/common.js").verifyRecaptcha,
	removeDuplicates = require("../utils/common.js").removeDuplicates,
	sanitizeBodyForDB = require("../utils/common.js").sanitizeBodyForDB,
	smtp = require("../utils/smtp.js"),
	config = require("../utils/common.js").config;

module.exports = function(app, prefix){
	app.post(prefix + "/register",
		verifyRecaptcha,
		register,
	function(req, res){
		if(req.isAuthenticated()){
			// Send email for verification
			// Respond with "201 Created"
			res.status(201).send(req.user._id.toString());
		}else{
			res.status(403).end();
		}
	});

	app.post(prefix + "/login",
		login,
	function(req, res){
		if(req.isAuthenticated()){
			res.status(200).end();
		}else{
			res.status(403).end();
		}
	});

	app.post(prefix + "/logout", function(req, res){
		req.logout();
		res.status(200).end();
	});

	app.get(prefix + "/isloggedin", function(req, res){
		res.send({isLoggedIn: req.isAuthenticated()});
	});

	app.post(prefix + "/:user/verify",
		authenticate,
		authorizeSessionUser(),
	function(req, res){
		if(!mongoose.Types.ObjectId.isValid(req.params.user)){
			return res.status(404).end();
		}

		User.findById(req.params.user, function(err, doc){
			if(err){
				res.status(500).end();
			}else if(!doc){
				res.status(404).end();
			}else{
				smtp.sendEmailVerification(app, doc, req.protocol + '://' + config.domain)
				.then(function(){
					res.status(200).end();
				}).catch(function(err){
					res.status(400).end();
				});
			}
		});
	});

	app.post(prefix + "/:user/verify/:token", function(req, res){
		if(!mongoose.Types.ObjectId.isValid(req.params.user)){
			return res.status(404).end();
		}

		var deferredUser = q.defer(), deferredToken = q.defer(),
			verified = false;
		User.findById(req.params.user, function(err, doc){
			if(err){
				deferredUser.reject({reason: "db-error", message: err});
			}else if(!doc){
				deferredUser.reject({reason: "not-found", message: "User not found"});
			}else{
				verified = doc.verified;
				deferredUser.resolve(doc);
			}
		});
		Token.findOne({token: req.params.token}, function(err, doc){
			if(err){
				deferredToken.reject({reason: "db-error", message: err});
			}else if(!doc){
				deferredToken.reject({reason: "not-found", message: "Token not found"});
			}else{
				deferredToken.resolve(doc);
			}
		});
		q.all([deferredUser.promise, deferredToken.promise])
		.spread(function(user, token){
			if(verified){
				res.status(200).end();
				return;
			}
			if(token.validate(user.email)){
				user.verified = true;
				user.modified = Date.now();
				user.save(function(err){
					if(err){
						console.error("Error: Successfully verified token for user \"" + user.email + "\", but failed to update flag");
						res.status(500).end();
					}else{
						user.syncWithDirectory()
						.then(function(){
							res.status(200).end();
						}).catch(function(err){
							console.error("Error: Successfully verified token for user \"" + user.email + "\", but failed to sync with directory");
							res.status(500).end();
						});
					}
				});
			}else{
				res.status(400).end();
			}
		}).catch(function(err){
			if(verified){
				res.status(200).end();
				return;
			}
			if(err.reason === "db-error"){
				res.status(500).end();
			}else if(err.reason === "not-found"){
				res.status(404).end();
			}else{
				res.status(400).end();
			}
		});
	});

	app.get(prefix + "/:user/verified",
		authenticate,
		authorizeSessionUser(),
	function(req, res){
		if(!mongoose.Types.ObjectId.isValid(req.params.user)){
			return res.status(404).end();
		}
		// Retrieve and return the "verified" value
		User.findById(req.params.user, function(err, doc){
			if(doc){
				res.status(200).send({verified: doc.verified});
			}else{
				res.status(404).end();
			}
		});
	});

	app.get(prefix,
		authenticate,
		authorize({hasRoles: ["admin"]}),
	function(req, res){
		User.find({}, function(err, docs){
			if(err){
				res.status(500).end();
			}else{
				res.send(docs || []);
			}
		});
	});

	app.get(prefix + "/:user",
		authenticate,
		authorizeSessionUser(),
	function(req, res){
		if(!mongoose.Types.ObjectId.isValid(req.params.user)){
			return res.status(404).end();
		}
		User.findById(req.params.user, function(err, doc){
			if(err){
				res.status(500).end();
			}else if(!doc){
				res.status(404).end();
			}else{
				var responseData = {
					email: doc.email,
					verified: doc.verified,
					created: doc.created,
					modified: doc.modified,
					accessed: doc.accessed,
					vip: doc.vip,
					lanInviteDesired: doc.lanInviteDesired,
					firstName: doc.firstName,
					lastName: doc.lastName,
					primaryHandle: doc.primaryHandle,
					tertiaryHandles: doc.tertiaryHandles,
					roles: doc.roles,
					services: doc.services
				};

				if(req.user.hasRole("admin")){
					responseData.__v = doc.__v;
					responseData._id = doc._id;
					responseData.blacklisted = doc.blacklisted;
				}

				res.send(responseData);
			}
		});
	});

	app.post(prefix,
		authenticate,
		authorize({hasRoles: ["admin"]}),
		sanitizeBodyForDB,
	function(req, res){
		if(req.body.roles){
			req.body.roles = removeDuplicates(req.body.roles);
		}
		User.createNew(req.body)
		.then(function(newUser){
			res.status(201)
			.location(prefix + "/" + newUser._id)
			.send({_id: newUser._id});
		}).catch(function(err){
			res.status(400).end();
		});
	});

	app.put(prefix + "/:user",
		authenticate,
		authorizeSessionUser(),
		sanitizeBodyForDB,
	function(req, res){
		if(!mongoose.Types.ObjectId.isValid(req.params.user)){
			return res.status(404).end();
		}

		var deferredExistingUser = q.defer(), deferredEditUser = q.defer();
		User.findOne({email: req.body.email}, function(err, doc){
			if(err){
				deferredExistingUser.reject({reason: "db-error", message: err});
			}else if(doc){
				deferredExistingUser.reject({reason: "address-in-use", message: "User already using that email address"});
			}else{
				deferredExistingUser.resolve(doc);
			}
		});
		User.findById(req.params.user, function(err, doc){
			if(err){
				deferredEditUser.reject({reason: "db-error", message: err});
			}else if(!doc){
				deferredEditUser.reject({reason: "not-found", message: "User not found"});
			}else{
				deferredEditUser.resolve(doc);
			}
		});
		q.all([deferredExistingUser.promise, deferredEditUser.promise])
		.spread(function(existingUser, editUser){
			if(req.body.email !== editUser.email){
				editUser.verified = false;
			}
			editUser.email = req.body.email;
			editUser.firstName = req.body.firstName;
			editUser.lastName = req.body.lastName;
			editUser.lanInviteDesired = req.body.lanInviteDesired;
			editUser.primaryHandle = req.body.primaryHandle;
			editUser.tertiaryHandles = removeDuplicates(req.body.tertiaryHandles);
			editUser.modified = Date.now();
			if(req.user.hasRole("admin")){
				editUser.verified = req.body.verified;
				editUser.vip = req.body.vip;
				editUser.blacklisted = req.body.blacklisted;
				editUser.roles = removeDuplicates(req.body.roles);
				editUser.services = req.body.services;
			}
			editUser.save(function(err){
				if(err){
					res.status(500).end();
				}else{
					editUser.syncWithDirectory()
					.then(function(){
						res.status(200).end();
					}).catch(function(){
						res.status(500).end();
					});
				}
			});
		}).catch(function(err){
			if(err.reason === "db-error"){
				res.status(500).end();
			}else if(err.reason === "address-in-use"){
				res.status(409).end();
			}else if(err.reason === "not-found"){
				res.status(404).end();
			}else{
				res.status(400).end();
			}
		});
	});

	app.put(prefix + "/:user/password",
		authenticate,
		authorizeSessionUser(),
	function(req, res){
		if(!mongoose.Types.ObjectId.isValid(req.params.user)){
			return res.status(404).end();
		}

		// Update the user
		User.findById(req.params.user, function(err, doc){
			if(err){
				res.status(400).end();
			}else if(!doc){
				res.status(404).end();
			}else{
				doc.changePassword(req.body.oldPassword, req.body.newPassword)
				.then(function(){
					res.status(200).end();
				}).catch(function(){
					res.status(400).end();
				});
			}
		});
	});
}
<|endoftext|>


<commit_before>/*global define */

define({
    ADD_ENDLINE_TO_THE_END_OF_FILE:     "Add endline at the end of file",
    ADD_TO_GITIGNORE:                   "Add to .gitignore",
    AMEND_COMMIT:                       "Amend last commit",
    AMEND_COMMIT_FORBIDDEN:             "Cannot amend commit when there are no unpushed commits",
    BASH_NOT_AVAILABLE:                 "Bash is not available or properly configured",
    BASIC_CONFIGURATION:                "Basic configuration",
    BRACKETS_GIT_ERROR:                 "Brackets Git encountered an error\u2026",
    BRANCH_NAME:                        "Branch name",
    TOOLTIP_BUG:                        "Report bug",
    BUTTON_CANCEL:                      "Cancel",
    BUTTON_CHANGELOG:                   "Show changelog",
    BUTTON_CLOSE:                       "Close",
    BUTTON_CLOSE_NOT_MODIFIED:          "Close not modified",
    BUTTON_COMMIT:                      "Commit",
    BUTTON_DEFAULTS:                    "Restore defaults",
    BUTTON_HIDE_UNTRACKED:              "Hide untracked",
    BUTTON_SHOW_UNTRACKED:              "Show untracked",
    BUTTON_INIT:                        "Init",
    BUTTON_OK:                          "OK",
    TOOLTIP_PULL:                       "Git Pull",
    TOOLTIP_PUSH:                       "Git Push",
    TOOLTIP_OPEN_BASH:                  "Open Bash console",
    BUTTON_REPORT:                      "Report",
    BUTTON_REFRESH_PANEL:               "Refresh panel",
    BUTTON_SAVE:                        "Save",
    CHANGELOG:                          "Changelog",
    CHECK_GIT_SETTINGS:                 "Check Git settings",
    COMMIT_CURRENT_SHORTCUT:            "Commit current file",
    COMMIT_ALL_SHORTCUT:                "Commit all files",
    COMMIT_MESSAGE_PLACEHOLDER:         "Enter commit message here\u2026",
    CREATE_NEW_BRANCH:                  "Create new branch\u2026",
    CUSTOM_TERMINAL_COMMAND:            "Custom terminal command (sample: gnome-terminal --window --working-directory=$1)",
    DELETE_FILE:                        "Delete file",
    DIFF:                               "Diff",
    ENTER_USERNAME:                     "Enter username",
    ENTER_PASSWORD:                     "Enter password",
    EXTENSION_WAS_UPDATED_TITLE:        "The extension was updated to {0}",
    ERROR_TERMINAL_NOT_FOUND:           "Terminal was not found for your OS, you can define a custom Terminal command in the settings",
    FEATURES:                           "Features",
    FILE_DELETED:                       "Deleted",
    FILE_MODIFIED:                      "Modified",
    FILE_NEWFILE:                       "New file",
    FILE_STAGED:                        "Staged",
    FILE_UNTRACKED:                     "Untracked",
    FILE_RENAMED:                       "Renamed",
    FOR_WINDOWS_USERS:                  "For Windows users",
    FOR_MAC_LINUX_USERS:                "For Mac/Linux users",
    GIT_COMMIT:                         "Git commit\u2026",
    GIT_DIFF:                           "Git diff —",
    GIT_IS_IN_PATH:                     "Git can be called from anywhere (is in system path, might not work on Mac)",
    GIT_PULL_RESPONSE:                  "Git Pull response",
    GIT_PUSH_RESPONSE:                  "Git Push response",
    GIT_SETTINGS:                       "Git Settings\u2026",
    LOADING:                            "Loading\u2026",
    MARK_MODIFIED_FILES_IN_TREE:        "Mark modified files in file tree",
    NOTHING_TO_COMMIT:                  "Nothing to commit, working directory clean.",
    PATH_TO_GIT_EXECUTABLE:             "Path to Git executable",
    PATH_TO_GIT_MSYSGIT:                "Path to msysgit folder",
    PANEL_COMMAND:                      "Git",
    PANEL_SHORTCUT:                     "Toggle panel",
    Q_DELETE_FILE:                      "Are you sure you wish to delete the file {0}?",
    Q_RESTART_BRACKETS:                 "Do you wish to restart Brackets to apply new settings?",
    Q_UNDO_CHANGES:                     "Reset changes to file {0}?",
    REMOVE_FROM_GITIGNORE:              "Remove from .gitignore",
    RESTART:                            "Restart",
    SAVE_PASSWORD_QUESTION:             "Save username/password?",
    SET_ORIGIN_URL:                     "Set origin URL",
    STRIP_WHITESPACE_FROM_COMMITS:      "Strip trailing whitespace from commits",
    UNDO_CHANGES:                       "Undo changes",
    URL:                                "URL",
    USE_GIT_GUTTER:                     "Use Git gutter marks",
    USING_GIT_VERSION:                  "Git version"
});
<commit_msg>Sort labels ...<commit_after>/*global define */

define({
    ADD_ENDLINE_TO_THE_END_OF_FILE:     "Add endline at the end of file",
    ADD_TO_GITIGNORE:                   "Add to .gitignore",
    AMEND_COMMIT:                       "Amend last commit",
    AMEND_COMMIT_FORBIDDEN:             "Cannot amend commit when there are no unpushed commits",
    BASH_NOT_AVAILABLE:                 "Bash is not available or properly configured",
    BASIC_CONFIGURATION:                "Basic configuration",
    BRACKETS_GIT_ERROR:                 "Brackets Git encountered an error\u2026",
    BRANCH_NAME:                        "Branch name",
    BUTTON_CANCEL:                      "Cancel",
    BUTTON_CHANGELOG:                   "Show changelog",
    BUTTON_CLOSE:                       "Close",
    BUTTON_CLOSE_NOT_MODIFIED:          "Close not modified",
    BUTTON_COMMIT:                      "Commit",
    BUTTON_DEFAULTS:                    "Restore defaults",
    BUTTON_HIDE_UNTRACKED:              "Hide untracked",
    BUTTON_INIT:                        "Init",
    BUTTON_OK:                          "OK",
    BUTTON_REFRESH_PANEL:               "Refresh panel",
    BUTTON_REPORT:                      "Report",
    BUTTON_SAVE:                        "Save",
    BUTTON_SHOW_UNTRACKED:              "Show untracked",
    CHANGELOG:                          "Changelog",
    CHECK_GIT_SETTINGS:                 "Check Git settings",
    COMMIT_ALL_SHORTCUT:                "Commit all files",
    COMMIT_CURRENT_SHORTCUT:            "Commit current file",
    COMMIT_MESSAGE_PLACEHOLDER:         "Enter commit message here\u2026",
    CREATE_NEW_BRANCH:                  "Create new branch\u2026",
    CUSTOM_TERMINAL_COMMAND:            "Custom terminal command (sample: gnome-terminal --window --working-directory=$1)",
    DELETE_FILE:                        "Delete file",
    DIFF:                               "Diff",
    ENTER_PASSWORD:                     "Enter password",
    ENTER_USERNAME:                     "Enter username",
    ERROR_TERMINAL_NOT_FOUND:           "Terminal was not found for your OS, you can define a custom Terminal command in the settings",
    EXTENSION_WAS_UPDATED_TITLE:        "The extension was updated to {0}",
    FEATURES:                           "Features",
    FILE_DELETED:                       "Deleted",
    FILE_MODIFIED:                      "Modified",
    FILE_NEWFILE:                       "New file",
    FILE_RENAMED:                       "Renamed",
    FILE_STAGED:                        "Staged",
    FILE_UNTRACKED:                     "Untracked",
    FOR_MAC_LINUX_USERS:                "For Mac/Linux users",
    FOR_WINDOWS_USERS:                  "For Windows users",
    GIT_COMMIT:                         "Git commit\u2026",
    GIT_DIFF:                           "Git diff —",
    GIT_IS_IN_PATH:                     "Git can be called from anywhere (is in system path, might not work on Mac)",
    GIT_PULL_RESPONSE:                  "Git Pull response",
    GIT_PUSH_RESPONSE:                  "Git Push response",
    GIT_SETTINGS:                       "Git Settings\u2026",
    LOADING:                            "Loading\u2026",
    MARK_MODIFIED_FILES_IN_TREE:        "Mark modified files in file tree",
    NOTHING_TO_COMMIT:                  "Nothing to commit, working directory clean.",
    PANEL_COMMAND:                      "Git",
    PANEL_SHORTCUT:                     "Toggle panel",
    PATH_TO_GIT_EXECUTABLE:             "Path to Git executable",
    PATH_TO_GIT_MSYSGIT:                "Path to msysgit folder",
    Q_DELETE_FILE:                      "Are you sure you wish to delete the file {0}?",
    Q_RESTART_BRACKETS:                 "Do you wish to restart Brackets to apply new settings?",
    Q_UNDO_CHANGES:                     "Reset changes to file {0}?",
    REMOVE_FROM_GITIGNORE:              "Remove from .gitignore",
    RESTART:                            "Restart",
    SAVE_PASSWORD_QUESTION:             "Save username/password?",
    SET_ORIGIN_URL:                     "Set origin URL",
    STRIP_WHITESPACE_FROM_COMMITS:      "Strip trailing whitespace from commits",
    TOOLTIP_BUG:                        "Report bug",
    TOOLTIP_OPEN_BASH:                  "Open Bash console",
    TOOLTIP_PULL:                       "Git Pull",
    TOOLTIP_PUSH:                       "Git Push",
    UNDO_CHANGES:                       "Undo changes",
    URL:                                "URL",
    USE_GIT_GUTTER:                     "Use Git gutter marks",
    USING_GIT_VERSION:                  "Git version"
});
<|endoftext|>


<commit_before>/**
 * Created by Anwender on 12.04.2017.
 */
'use strict';

angular.module('myApp.addSong', ['ngRoute', 'ngNotify', 'ngMaterial'])

    .config(['$routeProvider', function ($routeProvider) {
        $routeProvider.when('/addSong', {
            templateUrl: 'addSong/addSong.html',
            controller: 'addSongCtrl'
        });
    }])

    .controller('addSongCtrl', ['$scope', '$http', 'ngNotify', 'socketio', '$location', function (scope, http, ngNotify, socket, location) {

        var selectedSong = null;
        scope.songValid = false;
        scope.setSong = function (element) {
            selectedSong = element.files[0];
            console.log(selectedSong);
            if (selectedSong != null) {
                scope.$apply(function () {
                    scope.songValid = true;
                })

            } else {
                scope.$apply(function () {
                    scope.songValid = false;
                })
            }
        };

        var waitForImport = function () {

            socket.on('event:songImported', function (song) {
                ngNotify.set('Song "' + song.title + '" imported!', {
                    type: 'info',
                    duration: 3000
                });
                location.path('/editSong/' + song.id);
            });
        };

        scope.startUpload = function () {
            if (selectedSong != null) {
                scope.uploadFile(selectedSong);
            }
        };

        scope.songUpload = {
            "result": null,
            "progress": -1
        };

        scope.setProgress = function (value) {
            scope.songUpload.progress = value;
        };

        var client = null;

        scope.uploadFile = function uploadFile(file) {
            //Wieder unser File Objekt
            // var file = document.getElementById("fileA").files[0];
            //FormData Objekt erzeugen
            var formData = new FormData();
            //XMLHttpRequest Objekt erzeugen
            client = new XMLHttpRequest();

            //var prog = document.getElementById("progress");

            if (!file)
                return;

            // prog.value = 0;
            // prog.max = 100;

            //Fügt dem formData Objekt unser File Objekt hinzu
            formData.append("song", file);
            formData.append("clientID", socket.clientID);

            client.onerror = function (e) {
                ngNotify.set('Upload fehlgeschlagen.', {
                    type: 'error',
                    duration: 3000
                });
            };

            client.onload = function (e) {
                //document.getElementById("prozent").innerHTML = "100%";
                //prog.value = prog.max;
                console.log(this.responseText);
                scope.$apply(function () {
                    scope.songUpload.result = true;
                });
                ngNotify.set('Upload abgeschlossen.', {
                    type: 'success',
                    duration: 3000
                });
            };

            client.upload.onprogress = function (e) {
                var p = Math.round(100 / e.total * e.loaded);
                //document.getElementById("progress").value = p;
                //document.getElementById("prozent").innerHTML = p + "%";
                scope.setProgress(p);
            };

            client.onabort = function (e) {
                ngNotify.set('Upload abgebrochen.', {
                    type: 'warn',
                    duration: 3000
                });
            };

            client.open("POST", "songUpload");
            client.send(formData);

            waitForImport();
        };

    }]);<commit_msg>edit Song Seite erstellt<commit_after>/**
 * Created by Anwender on 12.04.2017.
 */
'use strict';

angular.module('myApp.addSong', ['ngRoute', 'ngNotify', 'ngMaterial'])

    .config(['$routeProvider', function ($routeProvider) {
        $routeProvider.when('/addSong', {
            templateUrl: 'addSong/addSong.html',
            controller: 'addSongCtrl'
        });
    }])

    .controller('addSongCtrl', ['$scope', '$http', 'ngNotify', 'socketio', '$location', function (scope, http, ngNotify, socket, location) {

        var selectedSong = null;
        scope.songValid = false;
        scope.setSong = function (element) {
            selectedSong = element.files[0];
            console.log(selectedSong);
            if (selectedSong != null) {
                scope.$apply(function () {
                    scope.songValid = true;
                })

            } else {
                scope.$apply(function () {
                    scope.songValid = false;
                })
            }
        };

        var waitForImport = function () {

            socket.on('event:songImported', function (song) {
                ngNotify.set('Song "' + song.title + '" imported!', {
                    type: 'info',
                    duration: 3000
                });
                scope.$apply(function () {
                    location.path('/editSong/' + song.id).replace();
                });

            });
        };

        scope.startUpload = function () {
            if (selectedSong != null) {
                scope.uploadFile(selectedSong);
            }
        };

        scope.songUpload = {
            "result": null,
            "progress": -1
        };

        scope.setProgress = function (value) {
            scope.songUpload.progress = value;
        };

        var client = null;

        scope.uploadFile = function uploadFile(file) {
            //Wieder unser File Objekt
            // var file = document.getElementById("fileA").files[0];
            //FormData Objekt erzeugen
            var formData = new FormData();
            //XMLHttpRequest Objekt erzeugen
            client = new XMLHttpRequest();

            //var prog = document.getElementById("progress");

            if (!file)
                return;

            // prog.value = 0;
            // prog.max = 100;

            //Fügt dem formData Objekt unser File Objekt hinzu
            formData.append("song", file);
            formData.append("clientID", socket.clientID);

            client.onerror = function (e) {
                ngNotify.set('Upload fehlgeschlagen.', {
                    type: 'error',
                    duration: 3000
                });
            };

            client.onload = function (e) {
                //document.getElementById("prozent").innerHTML = "100%";
                //prog.value = prog.max;
                console.log(this.responseText);
                scope.$apply(function () {
                    scope.songUpload.result = true;
                });
                ngNotify.set('Upload abgeschlossen.', {
                    type: 'success',
                    duration: 3000
                });
            };

            client.upload.onprogress = function (e) {
                var p = Math.round(100 / e.total * e.loaded);
                //document.getElementById("progress").value = p;
                //document.getElementById("prozent").innerHTML = p + "%";
                scope.setProgress(p);
            };

            client.onabort = function (e) {
                ngNotify.set('Upload abgebrochen.', {
                    type: 'warn',
                    duration: 3000
                });
            };

            client.open("POST", "songUpload");
            client.send(formData);

            waitForImport();
        };

    }]);<|endoftext|>


<commit_before>
carto_quotables = [
  'text-name',
  'text-face-name'
];

/**
 * some carto properties depends on others, this function
 * remove or add properties needed to carto works
 */
function manage_carto_properies(props) {
  if(/none/i.test(props['text-name'])) {
    // remove all text-* properties
    for(var p in props) {
      if(/^text-/.test(p)) {
        delete props[p];
      }
    }
  }
}

function simple_polygon_generator(table, props, callback) {

  manage_carto_properies(props);
  var carto_props = _(props).map(function(v, k) {
    if(_.include(carto_quotables, k)) {
      v = "'" + v + "'";
    }
    return "  " + k + ": " + v + ";";
  });
  callback("#" + table.get('name') + "{\n" + carto_props.join('\n') + "\n}");
}

function bubble_generator(table, props, callback) {
  var carto_props = {
   'marker-fill': props['marker-fill'],
   'marker-line-color': props['marker-line-color'],
   'marker-line-width': props['marker-line-width'],
   'marker-line-opacity': props['marker-line-opacity'],
   'marker-opacity': props['marker-opacity'],
   'marker-placement': 'point',
   'marker-type': 'ellipse',
   'marker-allow-overlap': true
  };
  var prop = props['property'];
  var min = props['radius_min'];
  var max = props['radius_max'];
  var values = [];
  var NPOINS = 10;
  //calculate the bubles sizes
  for(var i = 0; i < NPOINS; ++i) {
    var t = i/(NPOINS-1);
    values.push(min + t*(max - min));
  }

  var table_name = table.get('name');
  // generate carto
  simple_polygon_generator(table, carto_props, function(css) {
    table.data().quartiles(NPOINS, prop, function(quartiles)  {
      for(var i = NPOINS - 1; i >= 0; --i) {
        css += "\n#" + table_name +" [ " + prop + " <= " + quartiles[i] + "] {\n"
        css += "   marker-width: " + values[i].toFixed(1) + ";\n}"
      }
      callback(css);
    });
  });
}

function choropleth_generator(table, props, callback) {
  var carto_props = {
   'line-color': props['line-color'],
   'line-opacity': props['line-opacity'],
   'line-width': props['line-width'],
   'polygon-opacity': props['polygon-opacity'],
   'text-name': props['text-name'],
   'text-halo-fill': props['text-halo-fill'],
   'text-halo-radius': props['text-halo-radius'],
   'text-face-name': props['text-face-name'],
   'text-size': props['text-size'],
   'text-fill': props['text-fill']
  }

  var methodMap = {
    '3 Buckets': 3,
    '5 Buckets': 5,
    '7 Buckets': 7
  };

  var prop = props['property'];
  var nquartiles = methodMap[props['method']];
  var ramp = cdb.admin.color_ramps[props['color_ramp']][nquartiles];
  var table_name = table.get('name');

  if(!ramp) {
    cdb.log.error("no colo ramp defined for " + nquartiles + " quartiles");
  }

  simple_polygon_generator(table, carto_props, function(css) {
    table.data().quartiles(nquartiles, prop, function(quartiles)  {
      for(var i = nquartiles - 1; i >= 0; --i) {
        css += "\n#" + table_name +" [ " + prop + " <= " + quartiles[i] + "] {\n"
        css += "   polygon-fill: " + ramp[i] + ";\n}"
      }
      callback(css);
    });
  });
}

function density_generator(table, props, callback) {
  var carto_props = {
   'line-color': props['line-color'],
   'line-opacity': props['line-opacity'],
   'line-width': props['line-width'],
   'polygon-opacity': props['polygon-opacity'],
  }

  var methodMap = {
    '3 Buckets': 3,
    '5 Buckets': 5,
    '7 Buckets': 7
  };

  var nquartiles = methodMap[props['method']];
  var ramp = cdb.admin.color_ramps[props['color_ramp']][nquartiles];
  var table_name = table.get('name');

  if(!ramp) {
    cdb.log.error("no colo ramp defined for " + nquartiles + " quartiles");
  }

  var quartiles_buckets = {
    3: [0, 64, 512],
    5: [0, 8,  32,  128,  512],
    7: [0, 8, 16, 64, 128, 256, 512]
  };
  quartiles = quartiles_buckets[nquartiles];

  simple_polygon_generator(table, carto_props, function(css) {
    for(var i = nquartiles - 1; i >= 0; --i) {
      css += "\n#" + table_name +" [ points_count <= " + quartiles[i] + "] {\n"
      css += "   polygon-fill: " + ramp[i] + ";\n}"
    }
    callback(css);
  });
}

cdb.admin.CartoStyles = Backbone.Model.extend({

    defaults: {
      type: 'polygon',
      properties: {
        'polygon-fill': '#FF6600',
        'line-color': '#FFFFFF',
        'line-width': 1,
        'polygon-opacity': 0.7,
        'line-opacity':1
      }
    },

    initialize: function() {
      this.table = this.get('table');
      if(!this.table) {
        throw "table must be passed as param"
        return;
      }
      this.bind('change:properties', this._generateCarto, this);
      this.generators = {};
      this.registerGenerator('polygon', simple_polygon_generator);
      this.registerGenerator('bubble', bubble_generator);
      this.registerGenerator('choropleth', choropleth_generator);
      this.registerGenerator('density', density_generator); // the same generator than choroplet
    },

    // change a property attribute
    attr: function(name, val) {
      var old = this.attributes.properties[name];
      this.attributes.properties[name] = val;
      if(old != val) {
        this.trigger('change:properties', this, this.attributes.properties);
        this.trigger('changes', this);
      }
    },

    registerGenerator: function(name, gen) {
      this.generators[name] = gen;
    },

    /**
     * generate a header to show the user the params carto was
     * generated from
     */
    _generateHeader: function() {
      var c = _t("/**\n * this carto style was generated by cartodb. http://cartodb.com\n");
      c +=       " * genetor type: " + this.get('type') + "\n";
      c +=       " * params: " + JSON.stringify(this.get('properties')) + "\n";
      c +=       " */\n\n";
      return c;
    },

    _generateCarto: function(){
      var self = this;
      var gen = this.generators[this.get('type')];
      if(!gen) {
        cdb.log.error("can't get style generator for " + this.get('type'));
        return;
      }

      gen(this.table, this.get('properties'), function(style) {
        self.set({
          style: self._generateHeader() + style
        });
      })
    },

    /**
     * when cartocss is rendered the generator and properties are written in a comment.
     * This function try to load params from that comment.
     *
     * return true if it is able to load style
     */
    loadFromCartoCSS: function(carto) {
      var genType, params;
      if(!carto)  return false;
      var g = carto.match(/genetor type: (\w+)/);
      if(g) {
        genType = g[1];
      }
      g = carto.match(/params: \{(.*)\}/);
      if(g) {
        try {
          params = JSON.parse("{" + g[1] + "}");
        } catch(e) {
          cdb.log.info("can't parse css options");
        }
      }

      if(params && genType && this.generators[genType]) {
        this.set({
          type: genType,
          properties: params
        });
        return true;
      }
      return false;

    }

});
<commit_msg>fixed carto generation<commit_after>
carto_quotables = [
  'text-name',
  'text-face-name'
];

/**
 * some carto properties depends on others, this function
 * remove or add properties needed to carto works
 */
function manage_carto_properies(props) {
  if(/none/i.test(props['text-name'])) {
    // remove all text-* properties
    for(var p in props) {
      if(/^text-/.test(p)) {
        delete props[p];
      }
    }
  }
}

function simple_polygon_generator(table, props, callback) {

  manage_carto_properies(props);
  var carto_props = _(props).map(function(v, k) {
    if(_.include(carto_quotables, k)) {
      v = "'" + v + "'";
    }
    return "  " + k + ": " + v + ";";
  });
  callback("#" + table.get('name') + "{\n" + carto_props.join('\n') + "\n}");
}

function bubble_generator(table, props, callback) {
  var carto_props = {
   'marker-fill': props['marker-fill'],
   'marker-line-color': props['marker-line-color'],
   'marker-line-width': props['marker-line-width'],
   'marker-line-opacity': props['marker-line-opacity'],
   'marker-opacity': props['marker-opacity'],
   'marker-placement': 'point',
   'marker-type': 'ellipse',
   'marker-allow-overlap': true
  };
  var prop = props['property'];
  var min = props['radius_min'];
  var max = props['radius_max'];
  var values = [];
  var NPOINS = 10;
  //calculate the bubles sizes
  for(var i = 0; i < NPOINS; ++i) {
    var t = i/(NPOINS-1);
    values.push(min + t*(max - min));
  }

  var table_name = table.get('name');
  // generate carto
  simple_polygon_generator(table, carto_props, function(css) {
    table.data().quartiles(NPOINS, prop, function(quartiles)  {
      for(var i = NPOINS - 1; i >= 0; --i) {
        if(quartiles[i] !== undefined) {
          css += "\n#" + table_name +" [ " + prop + " <= " + quartiles[i] + "] {\n"
          css += "   marker-width: " + values[i].toFixed(1) + ";\n}"
        }
      }
      callback(css);
    });
  });
}

function choropleth_generator(table, props, callback) {
  var carto_props = {
   'line-color': props['line-color'],
   'line-opacity': props['line-opacity'],
   'line-width': props['line-width'],
   'polygon-opacity': props['polygon-opacity'],
   'text-name': props['text-name'],
   'text-halo-fill': props['text-halo-fill'],
   'text-halo-radius': props['text-halo-radius'],
   'text-face-name': props['text-face-name'],
   'text-size': props['text-size'],
   'text-fill': props['text-fill']
  }

  var methodMap = {
    '3 Buckets': 3,
    '5 Buckets': 5,
    '7 Buckets': 7
  };

  var prop = props['property'];
  var nquartiles = methodMap[props['method']];
  var ramp = cdb.admin.color_ramps[props['color_ramp']][nquartiles];
  var table_name = table.get('name');

  if(!ramp) {
    cdb.log.error("no colo ramp defined for " + nquartiles + " quartiles");
  }

  simple_polygon_generator(table, carto_props, function(css) {
    table.data().quartiles(nquartiles, prop, function(quartiles)  {
      for(var i = nquartiles - 1; i >= 0; --i) {
        css += "\n#" + table_name +" [ " + prop + " <= " + quartiles[i] + "] {\n"
        css += "   polygon-fill: " + ramp[i] + ";\n}"
      }
      callback(css);
    });
  });
}

function density_generator(table, props, callback) {
  var carto_props = {
   'line-color': props['line-color'],
   'line-opacity': props['line-opacity'],
   'line-width': props['line-width'],
   'polygon-opacity': props['polygon-opacity'],
  }

  var methodMap = {
    '3 Buckets': 3,
    '5 Buckets': 5,
    '7 Buckets': 7
  };

  var nquartiles = methodMap[props['method']];
  var ramp = cdb.admin.color_ramps[props['color_ramp']][nquartiles];
  var table_name = table.get('name');

  if(!ramp) {
    cdb.log.error("no colo ramp defined for " + nquartiles + " quartiles");
  }

  var quartiles_buckets = {
    3: [0, 64, 512],
    5: [0, 8,  32,  128,  512],
    7: [0, 8, 16, 64, 128, 256, 512]
  };
  quartiles = quartiles_buckets[nquartiles];

  simple_polygon_generator(table, carto_props, function(css) {
    for(var i = nquartiles - 1; i >= 0; --i) {
      css += "\n#" + table_name +" [ points_count <= " + quartiles[i] + "] {\n"
      css += "   polygon-fill: " + ramp[i] + ";\n}"
    }
    callback(css);
  });
}

cdb.admin.CartoStyles = Backbone.Model.extend({

    defaults: {
      type: 'polygon',
      properties: {
        'polygon-fill': '#FF6600',
        'line-color': '#FFFFFF',
        'line-width': 1,
        'polygon-opacity': 0.7,
        'line-opacity':1
      }
    },

    initialize: function() {
      this.table = this.get('table');
      if(!this.table) {
        throw "table must be passed as param"
        return;
      }
      this.bind('change:properties', this._generateCarto, this);
      this.generators = {};
      this.registerGenerator('polygon', simple_polygon_generator);
      this.registerGenerator('bubble', bubble_generator);
      this.registerGenerator('choropleth', choropleth_generator);
      this.registerGenerator('density', density_generator); // the same generator than choroplet
    },

    // change a property attribute
    attr: function(name, val) {
      var old = this.attributes.properties[name];
      this.attributes.properties[name] = val;
      if(old != val) {
        this.trigger('change:properties', this, this.attributes.properties);
        this.trigger('changes', this);
      }
    },

    registerGenerator: function(name, gen) {
      this.generators[name] = gen;
    },

    /**
     * generate a header to show the user the params carto was
     * generated from
     */
    _generateHeader: function() {
      var c = _t("/**\n * this carto style was generated by cartodb. http://cartodb.com\n");
      c +=       " * genetor type: " + this.get('type') + "\n";
      c +=       " * params: " + JSON.stringify(this.get('properties')) + "\n";
      c +=       " */\n\n";
      return c;
    },

    _generateCarto: function(){
      var self = this;
      var gen = this.generators[this.get('type')];
      if(!gen) {
        cdb.log.error("can't get style generator for " + this.get('type'));
        return;
      }

      gen(this.table, this.get('properties'), function(style) {
        self.set({
          style: self._generateHeader() + style
        });
      })
    },

    /**
     * when cartocss is rendered the generator and properties are written in a comment.
     * This function try to load params from that comment.
     *
     * return true if it is able to load style
     */
    loadFromCartoCSS: function(carto) {
      var genType, params;
      if(!carto)  return false;
      var g = carto.match(/genetor type: (\w+)/);
      if(g) {
        genType = g[1];
      }
      g = carto.match(/params: \{(.*)\}/);
      if(g) {
        try {
          params = JSON.parse("{" + g[1] + "}");
        } catch(e) {
          cdb.log.info("can't parse css options");
        }
      }

      if(params && genType && this.generators[genType]) {
        this.set({
          type: genType,
          properties: params
        });
        return true;
      }
      return false;

    }

});
<|endoftext|>