<commit_before>/*
 * slush-backbone
 * https://github.com/jonkemp/slush-backbone
 *
 * Copyright (c) 2014, Jonathan Kemp
 * Licensed under the MIT license.
 */

'use strict';

var gulp = require('gulp'),
    gutil = require('gulp-util'),
    install = require('gulp-install'),
    conflict = require('gulp-conflict'),
    template = require('gulp-template'),
    rename = require('gulp-rename'),
    _s = require('underscore.string'),
    inquirer = require('inquirer'),
    fs = require('fs'),
    path = require('path'),
    wiredep = require('wiredep');

gulp.task('default', function (done) {
    gutil.log('Out of the box you get HTML5 Boilerplate, jQuery and Backbone.js to build your app.');

    inquirer.prompt([
        {
            type: 'checkbox',
            name: 'features',
            message: 'Which other options would you like to include?',
            choices: [{
                name: 'Sass',
                value: 'includeSass',
                checked: true
            }, {
                name: 'Bootstrap',
                value: 'includeBootstrap',
                checked: true
            }, {
                name: 'Modernizr',
                value: 'includeModernizr',
                checked: true
            }]
        }, {
            type: 'confirm',
            name: 'moveon',
            message: 'Continue?'
        }
    ],
    function (answers) {
        var appname,
            features = answers.features,
            hasFeature = function (feat) {
                return features.indexOf(feat) !== -1;
            };

        if (!answers.moveon) {
            return done();
        }

        try {
            appname = require(path.join(process.cwd(), 'bower.json')).name;
        } catch (e) {
            try {
                appname = require(path.join(process.cwd(), 'package.json')).name;
            } catch (e) {}
        }

        if (!appname) {
            appname = path.basename(process.cwd());
        }

        answers.appname = appname.replace(/[^\w\s]+?/g, ' ');
        answers.appNameSlug = _s.slugify(answers.appname);
        answers.classifyAppName = _s.classify(answers.appname);

        answers.includeSass = hasFeature('includeSass');
        answers.includeBootstrap = hasFeature('includeBootstrap');
        answers.includeModernizr = hasFeature('includeModernizr');

        gulp.src(__dirname + '/templates/**')
            .pipe(template(answers))
            .pipe(rename(function (file) {
                if (file.basename[0] === '_') {
                    file.basename = '.' + file.basename.slice(1);
                }
                if (answers.includeSass && file.extname === '.css') {
                    file.extname = '.scss';
                }
            }))
            .pipe(conflict('./'))
            .pipe(gulp.dest('./'))
            .pipe(install());

        process.on('exit', function () {
            var bowerJson = JSON.parse(fs.readFileSync('./bower.json'));
            var skipInstall = process.argv.slice(2).indexOf('--skip-install') >= 0;

            if (!skipInstall) {
                // wire Bower packages to .html
                wiredep({
                    bowerJson: bowerJson,
                    directory: 'app/bower_components',
                    src: 'app/index.html'
                });

                if (answers.includeSass) {
                    // wire Bower packages to .scss
                    wiredep({
                        bowerJson: bowerJson,
                        directory: 'app/bower_components',
                        src: 'app/styles/*.scss'
                    });
                }
            } else {
                gutil.log('After running `npm install & bower install`, inject your front end dependencies into');
                gutil.log('your HTML by running:');
                gutil.log('  gulp wiredep');
            }

            done();
        });
    });
});
<commit_msg>Add tasks for 'model', 'collection', 'router', 'view' and 'all'.<commit_after>/*
 * slush-backbone
 * https://github.com/jonkemp/slush-backbone
 *
 * Copyright (c) 2014, Jonathan Kemp
 * Licensed under the MIT license.
 */

'use strict';

var gulp = require('gulp'),
    gutil = require('gulp-util'),
    install = require('gulp-install'),
    conflict = require('gulp-conflict'),
    template = require('gulp-template'),
    rename = require('gulp-rename'),
    _s = require('underscore.string'),
    inquirer = require('inquirer'),
    fs = require('fs'),
    path = require('path'),
    wiredep = require('wiredep');

function getAppName() {
    var appname;

    try {
        appname = require(path.join(process.cwd(), 'bower.json')).name;
    } catch (e) {
        try {
            appname = require(path.join(process.cwd(), 'package.json')).name;
        } catch (e) {}
    }

    if (!appname) {
        appname = path.basename(process.cwd());
    }

    return appname.replace(/[^\w\s]+?/g, ' ');
}

gulp.task('default', function (done) {
    gutil.log('Out of the box you get HTML5 Boilerplate, jQuery and Backbone.js to build your app.');

    inquirer.prompt([
        {
            type: 'checkbox',
            name: 'features',
            message: 'Which other options would you like to include?',
            choices: [{
                name: 'Sass',
                value: 'includeSass',
                checked: true
            }, {
                name: 'Bootstrap',
                value: 'includeBootstrap',
                checked: true
            }, {
                name: 'Modernizr',
                value: 'includeModernizr',
                checked: true
            }]
        }, {
            type: 'confirm',
            name: 'moveon',
            message: 'Continue?'
        }
    ],
    function (answers) {
        var features = answers.features,
            hasFeature = function (feat) {
                return features.indexOf(feat) !== -1;
            };

        if (!answers.moveon) {
            return done();
        }

        answers.appname = getAppName();
        answers.appNameSlug = _s.slugify(answers.appname);
        answers.classifyAppName = _s.classify(answers.appname);

        answers.includeSass = hasFeature('includeSass');
        answers.includeBootstrap = hasFeature('includeBootstrap');
        answers.includeModernizr = hasFeature('includeModernizr');

        gulp.src(__dirname + '/templates/**')
            .pipe(template(answers))
            .pipe(rename(function (file) {
                if (file.basename[0] === '_') {
                    file.basename = '.' + file.basename.slice(1);
                }
                if (answers.includeSass && file.extname === '.css') {
                    file.extname = '.scss';
                }
            }))
            .pipe(conflict('./'))
            .pipe(gulp.dest('./'))
            .pipe(install());

        process.on('exit', function () {
            var bowerJson = JSON.parse(fs.readFileSync('./bower.json'));
            var skipInstall = process.argv.slice(2).indexOf('--skip-install') >= 0;

            if (!skipInstall) {
                // wire Bower packages to .html
                wiredep({
                    bowerJson: bowerJson,
                    directory: 'app/bower_components',
                    src: 'app/index.html'
                });

                if (answers.includeSass) {
                    // wire Bower packages to .scss
                    wiredep({
                        bowerJson: bowerJson,
                        directory: 'app/bower_components',
                        src: 'app/styles/*.scss'
                    });
                }
            } else {
                gutil.log('After running `npm install & bower install`, inject your front end dependencies into');
                gutil.log('your HTML by running:');
                gutil.log('  gulp wiredep');
            }

            done();
        });
    });
});

gulp.task('model', function (done) {
    var appData = {};
    var modelName = gulp.args[0];

    appData.appname = getAppName();
    appData.appNameSlug = _s.slugify(appData.appname);
    appData.classifyAppName = _s.classify(appData.appname);
    appData.classifyModelName = _s.classify(modelName);

    gulp.src(__dirname + '/models/index.js')
        .pipe(template(appData))
        .pipe(rename('/models/' + modelName + '.js'))
        .pipe(conflict('./'))
        .pipe(gulp.dest('./app/scripts'));

    process.on('exit', function () {
        done();
    });
});

gulp.task('view', function (done) {
    var appData = {};
    var viewName = gulp.args[0];

    appData.appname = getAppName();
    appData.appNameSlug = _s.slugify(appData.appname);
    appData.classifyAppName = _s.classify(appData.appname);
    appData.classifyViewName = _s.classify(viewName);

    gulp.src(__dirname + '/views/index.js')
        .pipe(template(appData))
        .pipe(rename('/views/' + viewName + '.js'))
        .pipe(conflict('./'))
        .pipe(gulp.dest('./app/scripts'));

    process.on('exit', function () {
        done();
    });
});

gulp.task('collection', function (done) {
    var appData = {};
    var collectionName = gulp.args[0];

    appData.appname = getAppName();
    appData.appNameSlug = _s.slugify(appData.appname);
    appData.classifyAppName = _s.classify(appData.appname);
    appData.classifyCollectionName = _s.classify(collectionName);

    gulp.src(__dirname + '/collections/index.js')
        .pipe(template(appData))
        .pipe(rename('/collections/' + collectionName + '.js'))
        .pipe(conflict('./'))
        .pipe(gulp.dest('./app/scripts'));

    process.on('exit', function () {
        done();
    });
});

gulp.task('router', function (done) {
    var appData = {};
    var routerName = gulp.args[0];

    appData.appname = getAppName();
    appData.appNameSlug = _s.slugify(appData.appname);
    appData.classifyAppName = _s.classify(appData.appname);
    appData.classifyRouterName = _s.classify(routerName);

    gulp.src(__dirname + '/routes/index.js')
        .pipe(template(appData))
        .pipe(rename('/routes/' + routerName + '.js'))
        .pipe(conflict('./'))
        .pipe(gulp.dest('./app/scripts'));

    process.on('exit', function () {
        done();
    });
});

gulp.task('all', ['model', 'collection', 'router', 'view']);
<|endoftext|>


<commit_before>const common = require("./common");

let CSRF_TOKEN = null;

/**
* @param {Object} opts
*  - `headers` (Object): The headers information.
*  - `url` (String): The access URL.
*  - `action` (Object): The main source of information.
*  - `method` (Function): Used to access the code.
*  - `data` (String): Used to show the process status.
*/

module.exports = {
    request (opts, cb) {
        const CSRF_META = document.head && document.head.querySelector("[name='csrf-token']");
        CSRF_TOKEN = CSRF_TOKEN || (CSRF_META && CSRF_META.content);
        if (!CSRF_TOKEN) {
            console.warn("Cannot get the CSRF token in the <head> element. Please consider adding it.");
        }

        opts.headers = opts.headers || {};

        const headers = Object.assign({
            "Content-Type": "application/json",
            "Accept": "application/json",
            "X-Csrf-Token": CSRF_TOKEN
        }, opts.headers);
        const url = opts.url || common.url(opts.action, opts);

        return new Promise((resolve, reject) => {
            const xhr = typeof XMLHttpRequest !== "undefined"
                    ? new XMLHttpRequest()
                    : new ActiveXObject("Microsoft.XMLHTTP")
                    ;

            xhr.open(opts.method, url, true);

            Object.keys(headers).forEach(header => {
                xhr.setRequestHeader(header, headers[header]);
            });

            xhr.onreadystatechange = function() {
                if (xhr.readyState === 4) {
                    let status = xhr.status;
                    if (status >= 500) {
                        const err = new Error("Server error.");
                        cb && cb(err);
                        reject(err);
                    } else {
                        let data = {};
                        try {
                            data = JSON.parse(xhr.responseText);
                        } catch (e) {
                            console.warn(e);
                        }
                        if (status === 200) {
                            cb && cb(null, data);
                            resolve(data);
                        } else {
                            const err = new Error(data.error || data.message || "Something went wrong.");
                            cb && cb(err, data);
                            reject(err);
                        }
                    }
                }
            };

            if (opts.data) {
                xhr.send(JSON.stringify(opts.data));
            } else {
                xhr.send();
            }
        });
    }
  , post (name, data, opts, cb) {
        if (typeof opts === "function") {
            cb = opts;
            opts = {};
        }
        return this.request(Object.assign({
            method: "POST"
          , action: name
          , data
        }, opts), cb);
    }
  , get (name, opts, cb) {
        if (typeof opts === "function") {
            cb = opts;
            opts = {};
        }
        return this.request(Object.assign({
            method: "GET"
          , action: name
        }, opts), cb);
    }
};
<commit_msg>Update<commit_after>const common = require("./common");

let CSRF_TOKEN = null;

module.exports = {
    request (opts, cb) {

        /**
        * @param opts  {Object}    Contains a set of parameters.
        *  - `headers` (Object)    The headers information.
        *  - `url`     (String)    The access URL.
        *  - `action`  (Object)    The main source of information.
        *  - `method`  (Function)  Used to access the code.
        *  - `data`    (String)    Used to show the process status.
        * @param cb    {Function}  The callback function.
        */

        const CSRF_META = document.head && document.head.querySelector("[name='csrf-token']");
        CSRF_TOKEN = CSRF_TOKEN || (CSRF_META && CSRF_META.content);
        if (!CSRF_TOKEN) {
            console.warn("Cannot get the CSRF token in the <head> element. Please consider adding it.");
        }

        opts.headers = opts.headers || {};

        const headers = Object.assign({
            "Content-Type": "application/json",
            "Accept": "application/json",
            "X-Csrf-Token": CSRF_TOKEN
        }, opts.headers);
        const url = opts.url || common.url(opts.action, opts);

        return new Promise((resolve, reject) => {
            const xhr = typeof XMLHttpRequest !== "undefined"
                    ? new XMLHttpRequest()
                    : new ActiveXObject("Microsoft.XMLHTTP")
                    ;

            xhr.open(opts.method, url, true);

            Object.keys(headers).forEach(header => {
                xhr.setRequestHeader(header, headers[header]);
            });

            xhr.onreadystatechange = function() {
                if (xhr.readyState === 4) {
                    let status = xhr.status;
                    if (status >= 500) {
                        const err = new Error("Server error.");
                        cb && cb(err);
                        reject(err);
                    } else {
                        let data = {};
                        try {
                            data = JSON.parse(xhr.responseText);
                        } catch (e) {
                            console.warn(e);
                        }
                        if (status === 200) {
                            cb && cb(null, data);
                            resolve(data);
                        } else {
                            const err = new Error(data.error || data.message || "Something went wrong.");
                            cb && cb(err, data);
                            reject(err);
                        }
                    }
                }
            };

            if (opts.data) {
                xhr.send(JSON.stringify(opts.data));
            } else {
                xhr.send();
            }
        });
    }
  , post (name, data, opts, cb) {

        /**
        * @param name {String}   The action name.
        * @param data {String}   Contains the assigned object's process info.
        * @param opts {Object}   Contains a set of parameters.
        * @param cb   {Function} The callback function.
        */

        if (typeof opts === "function") {
            cb = opts;
            opts = {};
        }
        return this.request(Object.assign({
            method: "POST"
          , action: name
          , data
        }, opts), cb);
    }
  , get (name, opts, cb) {

        /*
        * @param name {String}   The action name.
        * @param opts {Object}   Contains a set of parameters.
        * @param cb   {Function} The callback function.
        */

        if (typeof opts === "function") {
            cb = opts;
            opts = {};
        }
        return this.request(Object.assign({
            method: "GET"
          , action: name
        }, opts), cb);
    }
};
<|endoftext|>


<commit_before>/*This is doitest.js */

/* == Define global variables == */

/* doiRegExp is a regular expression to determine if a string is a valid DOI (Digital Object Identifier) */
var doiRegExp = new RegExp('(10[.][0-9]{4,}(?:[.][0-9]+)*/(?:(?![%"#? ])\\S)+)');

/* Change this value if you are using this script in an ILLiad ArticleRequest Form or not -- set to true or false */
var isILLiad = true;

/* OpenURLbase is the URL for your institution's OpenURL resolver, stopping just before the "?" before the OpenURL fields */
var OpenURLbase = 'http://resolver.ebscohost.com/openurl';

/* OpenURLsuffix is only required if your resolver requires institutional authentication in a GET variable (EBSCO), as opposed to having the code in the host name (like 360Link).

Change this value to '' if you're in the latter category. */
var OpenURLsuffix = '&site=ftf-live&authtype=guest&custid=s9000206&groupid=main';

/* OpenURLbase is the label displayed for OpenURL links */
var OpenURLbranding = 'Get It @ Fisher';

/* == Define function for testing whether the input field contains a properly formatted DOI == */
function DOItest(DOItoTest) {
	/* DOI RegExp from https://github.com/regexhq/doi-regex/blob/master/index.js */
	/* Remove alerts once it goes into production: convert these into meaningful HTML text */
	if (doiRegExp.test(DOItoTest)) {
		$('#doiResponse').html('');
		return true;
	} else {
		$('#doiResponse').html('
Not a valid DOI
');
		return false;
	}
}

/* == Get things done once the document is ready == */
$(document).ready(function() {
	if (isILLiad == true) {
		$('#doiSearchBox').hide();
	}
	$('#haveDOI').click(function() {
		$('#doiSearchBox').show();
		$('#doiSearchBox').dialog({ title: "DOI Search for Interlibrary Loan", modal: true, width: 350, position: 'middle', center: true, buttons: [
		{
		text: 'Close',
		click: function() { $(this).dialog("close");}
		}
		] });

	});
	$('#checkDOI').click(function() {
		$('#doiResponse').text('');
		if (!(isILLiad == true)) {
			$('#doiResponse').css({"border":"1px solid #bbb", "margin-top":"0.2em", "padding":"0.5em"});
		}
		DOIval = $('#inputDOI').val();
		if (DOItest(DOIval) == true){
			DOI = DOIval.match(doiRegExp)[0];
			DOIurl = 'http://api.crossref.org/works/' + DOI;
			$('#doiResponse').append('');
			/* need error handling for cases with no CrossRef DOI record found, i.e. http://api.crossref.org/works/10.1016/j.iree.2016.07.002 */
			$.getJSON( DOIurl, function( data ) {
			})
			.success(function(data) {
				/* Define Local OpenURL variable */
				var strAuthor = '';
				var strJournal = '';
				var strTitle = '';
				var strVolume = '';
				var strIssue = '';
				var strType = '';
				var strDate = '';
				var strPublishedPrint = '';
				var strPublishedOnline = '';
				var strCreated = '';
				var strPage = '';
				var strISBN = '';
				var strCitedIn = '';
				if (isILLiad == true) {
					strCitedIn = 'Library DOI Resolver in ILLiad';
				} else {
					strCitedIn = 'Library DOI Resolver outside of ILLiad';
				}
				$.each(data, function() {
				  $.each(this, function(k, v) {
					/* Display all read data in key value pairs; note that nested arrays will show as "object Object" */
					/* $('#doiResponse').append(k + ': ' + v + '
'); */
					switch(k){
						case 'container-title':
							strJournal = v;
							break;
						case 'title':
							strTitle = v;
							break;
						case 'volume':
							strVolume = v;
							break;
						case 'issue':
							strIssue = v;
							break;
						case 'page':
							strPage = v;
							break;
						case 'type':
							/* TBD: nest conditionals to convert types into ILLiad/OpenURL values. Perhaps apply that logic separately to make code usable for both resolution systems? */
							strType = v;
							break;
						case 'published-print':
							/* Need nested loop to process array; also run logic later to prioritize published-print over published-online over created date */
							$.each(this, function(k2,v2) {
								/* Display all read data in key value pairs; note that nested arrays will show as "object Object" */
								if (k2 == 'date-parts'){
									strPublishedPrint = v2.toString().split(',')[0];
								}
							});
							break;
						case 'published-online':
							/* Need nested loop to process array; also run logic later to prioritize published-print over published-online over created date */
							$.each(this, function(k2,v2) {
								/* Display all read data in key value pairs; note that nested arrays will show as "object Object" */
								if (k2 == 'date-parts'){
									strPublishedOnline = v2.toString().split(',')[0];
								}
							});
							break;
						case 'created':
							/* Need nested loop to process array; also run logic later to prioritize published-print over published-online over created date */
							$.each(this, function(k2,v2) {
								/* Display all read data in key value pairs; note that nested arrays will show as "object Object" */
								if (k2 == 'date-parts'){
									strCreated = v2.toString().split(',')[0];
								}
							});
							break;

						case 'ISSN':
							strISSN = v.toString().split(',')[0];
							break;
						case 'ISBN':
							strISBN = v;
							break;
						case 'author':
							/* exists in a nested array for articles with multiple authors. Check for functionality if not an array: checked 2016/8/5 16:54 EDT */
							if (strAuthor == ''){
								var strGiven = '';
								var strFamily = '';
								$.each(this, function() {
									$.each(this, function(k2,v2) {
										/* Display all read data in key value pairs; note that nested arrays will show as "object Object" */
										/*$('#doiResponse').append(k2 + ': ' + v2 + '
');*/
										if (strAuthor == ''){
											if (k2 == 'family'){
												strFamily = v2;
											}
											if (k2 == 'given') {
												strGiven = v2;
											}
										}
									});
									if (!(strFamily == '') && !(strGiven =='')){
										strAuthor = strFamily + ', ' + strGiven;
									}
								});
							}
							break;
					}
					//cited in field: "Library DOI Resolver"
					//volume
					//issue
											//						page: 24-34
					//ISSN[0]: 1536-7967,1536-7975
					//DOI
					//published-print.date-parts[0] PRIORITIZE over published-online.date-parts[0]
					/*if (k=='type'){
						str
					}*/

				  });
				});

				/* Calculate Best Approximation of Date of Publication */
				if (!(strPublishedPrint == '')) {
					strDate = strPublishedPrint;
				} else if (!(strPublishedOnline == '')) {
					strDate = strPublishedOnline;
				} else if (!(strCreated == '')) {
					strDate = strCreated;
				}

				if (!(isILLiad == true)) {
					/* Since this isn't for ILLiad, Generate Output to the screen and create an OpenURL link */
					var OpenURLLink = OpenURLbase + '?sid=' + encodeURIComponent(strCitedIn) + '&genre=' + encodeURIComponent(strType) + '&issn=' + strISSN + '&ISBN=' + strISBN + '&volume=' + strVolume + '&issue=' + strVolume + '&date=' + encodeURIComponent(strDate) + '&spage=' + strPage + '&pages=' + strPage + '&title=' + encodeURIComponent(strJournal) + '&atitle=' + encodeURIComponent(strTitle) + '&aulast=' + encodeURIComponent(strAuthor) + '&id=doi%3A%2F%2F' + encodeURIComponent(DOI) + OpenURLsuffix;
					$('#doiResponse').append('
Check for full text

 Get It @ Fisher

Information About this DOI

');
					$('#doiResponse').append('Journal: ' + strJournal + '
');
					$('#doiResponse').append('Title: ' + strTitle + '
');
					$('#doiResponse').append('Author: ' + strAuthor + '
');
					$('#doiResponse').append('Volume: ' + strVolume + '
');
					$('#doiResponse').append('Issue: '  + strIssue + '
');
					$('#doiResponse').append('Page: '  + strPage + '
');
					$('#doiResponse').append('Type: '  + strType + '
');
					$('#doiResponse').append('Published-Print: '  + strPublishedPrint + '
');
					$('#doiResponse').append('Published-Online: '  + strPublishedOnline + '
');
					$('#doiResponse').append('Created: '  + strCreated + '
');
					$('#doiResponse').append('Date: '  + strDate + '
');
					$('#doiResponse').append('ISSN: ' + strISSN + '
');
					$('#doiResponse').append('ISBN: ' + strISBN + '
');
					$('#doiResponse').append('CitedIn: ' + strCitedIn + '
');
					$('#doiResponse').append('DOI: ' + DOI + '
');
				}
				if (isILLiad == true) {
					/* Populate data into ILLiad form */
					$('#PhotoArticleAuthor').val(strAuthor);
					$('#PhotoArticleTitle').val(strTitle);
					$('#PhotoJournalTitle').val(strJournal);
					$('#PhotoJournalVolume').val(strVolume);
					$('#PhotoJournalIssue').val(strIssue);
					$('#PhotoJournalInclusivePages').val(strPage);
					$('#ISSN').val(strISSN);
					$('#PhotoJournalYear').val(strDate);
					$('#CitedIn').val(strCitedIn);
					/* Close popup */
					$('#doiResponse').closest('.ui-dialog-content').dialog('close');
				}
			})
			.error(function(event,jqxhr, exception){
				$('#doiResponse').append('That DOI was not found. ');
			});
		} else {
			$('#doiResponse').append('No DOI found; no response called.');
		}
	});
});
<commit_msg>Set isILLiad to false by default<commit_after>/*This is doitest.js */

/* == Define global variables == */

/* doiRegExp is a regular expression to determine if a string is a valid DOI (Digital Object Identifier) */
var doiRegExp = new RegExp('(10[.][0-9]{4,}(?:[.][0-9]+)*/(?:(?![%"#? ])\\S)+)');

/* Change this value if you are using this script in an ILLiad ArticleRequest Form or not -- set to true or false */
var isILLiad = false;

/* OpenURLbase is the URL for your institution's OpenURL resolver, stopping just before the "?" before the OpenURL fields */
var OpenURLbase = 'http://resolver.ebscohost.com/openurl';

/* OpenURLsuffix is only required if your resolver requires institutional authentication in a GET variable (EBSCO), as opposed to having the code in the host name (like 360Link).
Change this value to '' if you're in the latter category. */
var OpenURLsuffix = '&site=ftf-live&authtype=guest&custid=s9000206&groupid=main';

/* OpenURLbase is the label displayed for OpenURL links */
var OpenURLbranding = 'Get It @ Fisher';

/* == Define function for testing whether the input field contains a properly formatted DOI == */
function DOItest(DOItoTest) {
	/* DOI RegExp from https://github.com/regexhq/doi-regex/blob/master/index.js */
	/* Remove alerts once it goes into production: convert these into meaningful HTML text */
	if (doiRegExp.test(DOItoTest)) {
		$('#doiResponse').html('');
		return true;
	} else {
		$('#doiResponse').html('
Not a valid DOI
');
		return false;
	}
}

/* == Get things done once the document is ready == */
$(document).ready(function() {
	if (isILLiad == true) {
		$('#doiSearchBox').hide();
	}
	$('#haveDOI').click(function() {
		$('#doiSearchBox').show();
		$('#doiSearchBox').dialog({ title: "DOI Search for Interlibrary Loan", modal: true, width: 350, position: 'middle', center: true, buttons: [
		{
		text: 'Close',
		click: function() { $(this).dialog("close");}
		}
		] });

	});
	$('#checkDOI').click(function() {
		$('#doiResponse').text('');
		if (!(isILLiad == true)) {
			$('#doiResponse').css({"border":"1px solid #bbb", "margin-top":"0.2em", "padding":"0.5em"});
		}
		DOIval = $('#inputDOI').val();
		if (DOItest(DOIval) == true){
			DOI = DOIval.match(doiRegExp)[0];
			DOIurl = 'http://api.crossref.org/works/' + DOI;
			$('#doiResponse').append('');
			/* need error handling for cases with no CrossRef DOI record found, i.e. http://api.crossref.org/works/10.1016/j.iree.2016.07.002 */
			$.getJSON( DOIurl, function( data ) {
			})
			.success(function(data) {
				/* Define Local OpenURL variable */
				var strAuthor = '';
				var strJournal = '';
				var strTitle = '';
				var strVolume = '';
				var strIssue = '';
				var strType = '';
				var strDate = '';
				var strPublishedPrint = '';
				var strPublishedOnline = '';
				var strCreated = '';
				var strPage = '';
				var strISBN = '';
				var strCitedIn = '';
				if (isILLiad == true) {
					strCitedIn = 'Library DOI Resolver in ILLiad';
				} else {
					strCitedIn = 'Library DOI Resolver outside of ILLiad';
				}
				$.each(data, function() {
				  $.each(this, function(k, v) {
					/* Display all read data in key value pairs; note that nested arrays will show as "object Object" */
					/* $('#doiResponse').append(k + ': ' + v + '
'); */
					switch(k){
						case 'container-title':
							strJournal = v;
							break;
						case 'title':
							strTitle = v;
							break;
						case 'volume':
							strVolume = v;
							break;
						case 'issue':
							strIssue = v;
							break;
						case 'page':
							strPage = v;
							break;
						case 'type':
							/* TBD: nest conditionals to convert types into ILLiad/OpenURL values. Perhaps apply that logic separately to make code usable for both resolution systems? */
							strType = v;
							break;
						case 'published-print':
							/* Need nested loop to process array; also run logic later to prioritize published-print over published-online over created date */
							$.each(this, function(k2,v2) {
								/* Display all read data in key value pairs; note that nested arrays will show as "object Object" */
								if (k2 == 'date-parts'){
									strPublishedPrint = v2.toString().split(',')[0];
								}
							});
							break;
						case 'published-online':
							/* Need nested loop to process array; also run logic later to prioritize published-print over published-online over created date */
							$.each(this, function(k2,v2) {
								/* Display all read data in key value pairs; note that nested arrays will show as "object Object" */
								if (k2 == 'date-parts'){
									strPublishedOnline = v2.toString().split(',')[0];
								}
							});
							break;
						case 'created':
							/* Need nested loop to process array; also run logic later to prioritize published-print over published-online over created date */
							$.each(this, function(k2,v2) {
								/* Display all read data in key value pairs; note that nested arrays will show as "object Object" */
								if (k2 == 'date-parts'){
									strCreated = v2.toString().split(',')[0];
								}
							});
							break;

						case 'ISSN':
							strISSN = v.toString().split(',')[0];
							break;
						case 'ISBN':
							strISBN = v;
							break;
						case 'author':
							/* exists in a nested array for articles with multiple authors. Check for functionality if not an array: checked 2016/8/5 16:54 EDT */
							if (strAuthor == ''){
								var strGiven = '';
								var strFamily = '';
								$.each(this, function() {
									$.each(this, function(k2,v2) {
										/* Display all read data in key value pairs; note that nested arrays will show as "object Object" */
										/*$('#doiResponse').append(k2 + ': ' + v2 + '
');*/
										if (strAuthor == ''){
											if (k2 == 'family'){
												strFamily = v2;
											}
											if (k2 == 'given') {
												strGiven = v2;
											}
										}
									});
									if (!(strFamily == '') && !(strGiven =='')){
										strAuthor = strFamily + ', ' + strGiven;
									}
								});
							}
							break;
					}
					//cited in field: "Library DOI Resolver"
					//volume
					//issue
											//						page: 24-34
					//ISSN[0]: 1536-7967,1536-7975
					//DOI
					//published-print.date-parts[0] PRIORITIZE over published-online.date-parts[0]
					/*if (k=='type'){
						str
					}*/

				  });
				});

				/* Calculate Best Approximation of Date of Publication */
				if (!(strPublishedPrint == '')) {
					strDate = strPublishedPrint;
				} else if (!(strPublishedOnline == '')) {
					strDate = strPublishedOnline;
				} else if (!(strCreated == '')) {
					strDate = strCreated;
				}

				if (!(isILLiad == true)) {
					/* Since this isn't for ILLiad, Generate Output to the screen and create an OpenURL link */
					var OpenURLLink = OpenURLbase + '?sid=' + encodeURIComponent(strCitedIn) + '&genre=' + encodeURIComponent(strType) + '&issn=' + strISSN + '&ISBN=' + strISBN + '&volume=' + strVolume + '&issue=' + strVolume + '&date=' + encodeURIComponent(strDate) + '&spage=' + strPage + '&pages=' + strPage + '&title=' + encodeURIComponent(strJournal) + '&atitle=' + encodeURIComponent(strTitle) + '&aulast=' + encodeURIComponent(strAuthor) + '&id=doi%3A%2F%2F' + encodeURIComponent(DOI) + OpenURLsuffix;
					$('#doiResponse').append('
Check for full text

 Get It @ Fisher

Information About this DOI

');
					$('#doiResponse').append('Journal: ' + strJournal + '
');
					$('#doiResponse').append('Title: ' + strTitle + '
');
					$('#doiResponse').append('Author: ' + strAuthor + '
');
					$('#doiResponse').append('Volume: ' + strVolume + '
');
					$('#doiResponse').append('Issue: '  + strIssue + '
');
					$('#doiResponse').append('Page: '  + strPage + '
');
					$('#doiResponse').append('Type: '  + strType + '
');
					$('#doiResponse').append('Published-Print: '  + strPublishedPrint + '
');
					$('#doiResponse').append('Published-Online: '  + strPublishedOnline + '
');
					$('#doiResponse').append('Created: '  + strCreated + '
');
					$('#doiResponse').append('Date: '  + strDate + '
');
					$('#doiResponse').append('ISSN: ' + strISSN + '
');
					$('#doiResponse').append('ISBN: ' + strISBN + '
');
					$('#doiResponse').append('CitedIn: ' + strCitedIn + '
');
					$('#doiResponse').append('DOI: ' + DOI + '
');
				}
				if (isILLiad == true) {
					/* Populate data into ILLiad form */
					$('#PhotoArticleAuthor').val(strAuthor);
					$('#PhotoArticleTitle').val(strTitle);
					$('#PhotoJournalTitle').val(strJournal);
					$('#PhotoJournalVolume').val(strVolume);
					$('#PhotoJournalIssue').val(strIssue);
					$('#PhotoJournalInclusivePages').val(strPage);
					$('#ISSN').val(strISSN);
					$('#PhotoJournalYear').val(strDate);
					$('#CitedIn').val(strCitedIn);
					/* Close popup */
					$('#doiResponse').closest('.ui-dialog-content').dialog('close');
				}
			})
			.error(function(event,jqxhr, exception){
				$('#doiResponse').append('That DOI was not found. ');
			});
		} else {
			$('#doiResponse').append('No DOI found; no response called.');
		}
	});
});
<|endoftext|>


<commit_before>"use strict";

/*  ---------------------------------------------------------------------------

    A tests launcher. Runs tests for all languages and all exchanges, in
    parallel, with a humanized error reporting.

    Usage: node run-tests [--php] [--js] [--python] [--python-async] [exchange] [symbol]

    --------------------------------------------------------------------------- */

const fs = require ('fs')
const log = require ('ololog')//.configure ({ indent: { pattern: '  ' }})
const ansi = require ('ansicolor').nice

/*  --------------------------------------------------------------------------- */

process.on ('uncaughtException',  e => { log.bright.red.error (e); process.exit (1) })
process.on ('unhandledRejection', e => { log.bright.red.error (e); process.exit (1) })

/*  --------------------------------------------------------------------------- */

const [,, ...args] = process.argv

const keys = {

    '--js': false,      // run JavaScript tests only
    '--php': false,     // run PHP tests only
    '--python': false,  // run Python 3 tests only
    '--python-async': false, // run Python 3 async tests only
    '--php-async': false,    // run php async tests only
}

let exchanges = []
let symbol = 'all'
let maxConcurrency = 5 // Number.MAX_VALUE // no limit

for (const arg of args) {
    if (arg.startsWith ('--'))               { keys[arg] = true }
    else if (arg.includes ('/'))             { symbol = arg }
    else if (Number.isFinite (Number (arg))) { maxConcurrency = Number (arg) }
    else                                     { exchanges.push (arg) }
}

/*  --------------------------------------------------------------------------- */

if (!exchanges.length) {

    if (!fs.existsSync ('./exchanges.json')) {

        log.bright.red ('\n\tNo', 'exchanges.json'.white, 'found, please run', 'npm run build'.white, 'to generate it!\n')
        process.exit (1)
    }

    exchanges = require ('./exchanges.json').ids
}

/*  --------------------------------------------------------------------------- */

const sleep = s => new Promise (resolve => setTimeout (resolve, s*1000))
const timeout = (s, promise) => Promise.race ([ promise, sleep (s).then (() => { throw new Error ('timed out') }) ])

/*  --------------------------------------------------------------------------- */

const exec = (bin, ...args) =>

/*  A custom version of child_process.exec that captures both stdout and
    stderr,  not separating them into distinct buffers — so that we can show
    the same output as if it were running in a terminal.                        */

    timeout (120, new Promise (return_ => {

        const ps = require ('child_process').spawn (bin, args)

        let output = ''
        let stderr = ''
        let hasWarnings = false

        ps.stdout.on ('data', data => { output += data.toString () })
        ps.stderr.on ('data', data => { output += data.toString (); stderr += data.toString (); hasWarnings = true })

        ps.on ('exit', code => {

            output = ansi.strip (output.trim ())
            stderr = ansi.strip (stderr)

            const regex = /\[[a-z]+?\]/gmi

            let match = undefined
            const warnings = []

            match = regex.exec (output)

            if (match) {
                warnings.push (match[0])
                do {
                    if (match = regex.exec (output)) {
                        warnings.push (match[0])
                    }
                } while (match);
            }

            return_ ({
                failed: code !== 0,
                output,
                hasOutput: output.length > 0,
                hasWarnings: hasWarnings || warnings.length > 0,
                warnings: warnings,
            })
        })

    })).catch (e => ({

        failed: true,
        output: e.message

    })).then (x => Object.assign (x, { hasOutput: x.output.length > 0 }))

/*  ------------------------------------------------------------------------ */

// const execWithRetry = () => {

//     // Sometimes execution (on a remote CI server) is just fails with no
//     // apparent reason, leaving an empty stdout/stderr behind. I suspect
//     // it's related to out-of-memory errors. So in that case we will re-try
//     // until it eventually finalizes.
// }

/*  ------------------------------------------------------------------------ */

let numExchangesTested = 0

/*  Tests of different languages for the same exchange should be run
    sequentially to prevent the interleaving nonces problem.
    ------------------------------------------------------------------------ */

const sequentialMap = async (input, fn) => {

    const result = []
    for (const item of input) { result.push (await fn (item)) }
    return result
}

/*  ------------------------------------------------------------------------ */

const testExchange = async (exchange) => {

/*  Run tests for all/selected languages (in parallel)     */

    const args = [exchange, ...symbol === 'all' ? [] : symbol]
        , allTests = [

            { language: 'JavaScript',     key: '--js',           exec: ['node',      'js/test/test.js',           ...args] },
            { language: 'Python 3',       key: '--python',       exec: ['python3',   'python/ccxt/test/test_sync.py',  ...args] },
            { language: 'Python 3 Async', key: '--python-async', exec: ['python3',   'python/ccxt/test/test_async.py', ...args] },
            { language: 'PHP',            key: '--php',          exec: ['php', '-f', 'php/test/test_sync.php',         ...args] },
            { language: 'PHP Async',      key: '--php-async',    exec: ['php', '-f', 'php/test/test_async.php',   ...args] },
        ]
        , selectedTests  = allTests.filter (t => keys[t.key])
        , scheduledTests = selectedTests.length ? selectedTests : allTests
        , completeTests  = await sequentialMap (scheduledTests, async test => Object.assign (test, await exec (...test.exec)))
        , failed         = completeTests.find (test => test.failed)
        , hasWarnings    = completeTests.find (test => test.hasWarnings)
        , warnings       = completeTests.reduce ((total, { warnings }) => total.concat (warnings), [])

/*  Print interactive log output    */

    numExchangesTested++

    const percentsDone = ((numExchangesTested / exchanges.length) * 100).toFixed (0) + '%'

    log.bright (('[' + percentsDone + ']').dim, 'Testing', exchange.cyan, (failed      ? 'FAIL'.red :
                                                                          (hasWarnings ? (warnings.length ? warnings.join (' ') : 'WARN').yellow
                                                                                : 'OK'.green)))

/*  Return collected data to main loop     */

    return {

        exchange,
        failed,
        hasWarnings,
        explain () {
            for (const { language, failed, output, hasWarnings } of completeTests) {
                if (failed || hasWarnings) {

                    if (!failed && output.indexOf('[Skipped]') >= 0)
                        continue;

                    if (failed) { log.bright ('\nFAILED'.bgBrightRed.white, exchange.red,    '(' + language + '):\n') }
                    else        { log.bright ('\nWARN'.yellow.inverse,      exchange.yellow, '(' + language + '):\n') }

                    log.indent (1) (output)
                }
            }
        }
    }
}

/*  ------------------------------------------------------------------------ */

function TaskPool (maxConcurrency) {

    const pending = []
        , queue   = []

    let numActive = 0

    return {

        pending,

        run (task) {

            if (numActive >= maxConcurrency) { // queue task

                return new Promise (resolve => queue.push (() => this.run (task).then (resolve)))

            } else { // execute task

                let p = task ().then (x => {
                    numActive--
                    return (queue.length && (numActive < maxConcurrency))
                                ? queue.shift () ().then (() => x)
                                : x
                })
                numActive++
                pending.push (p)
                return p
            }
        }
    }
}

/*  ------------------------------------------------------------------------ */

async function testAllExchanges () {

    const taskPool = TaskPool (maxConcurrency)
    const results = []

    for (const exchange of exchanges) {
        taskPool.run (() => testExchange (exchange).then (x => results.push (x)))
    }

    await Promise.all (taskPool.pending)

    return results
}

/*  ------------------------------------------------------------------------ */

(async function () {

    log.bright.magenta.noPretty ('Testing'.white, Object.assign (
                                                            { exchanges, symbol, keys },
                                                            maxConcurrency >= Number.MAX_VALUE ? {} : { maxConcurrency }))

    const tested    = await testAllExchanges ()
        , warnings  = tested.filter (t => !t.failed && t.hasWarnings)
        , failed    = tested.filter (t =>  t.failed)
        , succeeded = tested.filter (t => !t.failed && !t.hasWarnings)

    log.newline ()

    warnings.forEach (t => t.explain ())
    failed.forEach (t => t.explain ())

    log.newline ()

    if (failed.length)   { log.noPretty.bright.red    ('FAIL'.bgBrightRed.white, failed.map (t => t.exchange)) }
    if (warnings.length) { log.noPretty.bright.yellow ('WARN'.inverse,           warnings.map (t => t.exchange)) }

    log.newline ()

    log.bright ('All done,', [failed.length    && (failed.length    + ' failed')   .red,
                              succeeded.length && (succeeded.length + ' succeeded').green,
                              warnings.length  && (warnings.length  + ' warnings') .yellow].filter (s => s).join (', '))

    if (failed.length) {

        await sleep (10) // to fight TravisCI log truncation issue, see https://github.com/travis-ci/travis-ci/issues/8189
        process.exit (1)

    } else {
        process.exit (0)
    }

}) ();

/*  ------------------------------------------------------------------------ */
<commit_msg>update paths run-test<commit_after>"use strict";

/*  ---------------------------------------------------------------------------

    A tests launcher. Runs tests for all languages and all exchanges, in
    parallel, with a humanized error reporting.

    Usage: node run-tests [--php] [--js] [--python] [--python-async] [exchange] [symbol]

    --------------------------------------------------------------------------- */

const fs = require ('fs')
const log = require ('ololog')//.configure ({ indent: { pattern: '  ' }})
const ansi = require ('ansicolor').nice

/*  --------------------------------------------------------------------------- */

process.on ('uncaughtException',  e => { log.bright.red.error (e); process.exit (1) })
process.on ('unhandledRejection', e => { log.bright.red.error (e); process.exit (1) })

/*  --------------------------------------------------------------------------- */

const [,, ...args] = process.argv

const keys = {

    '--js': false,      // run JavaScript tests only
    '--php': false,     // run PHP tests only
    '--python': false,  // run Python 3 tests only
    '--python-async': false, // run Python 3 async tests only
    '--php-async': false,    // run php async tests only
}

let exchanges = []
let symbol = 'all'
let maxConcurrency = 5 // Number.MAX_VALUE // no limit

for (const arg of args) {
    if (arg.startsWith ('--'))               { keys[arg] = true }
    else if (arg.includes ('/'))             { symbol = arg }
    else if (Number.isFinite (Number (arg))) { maxConcurrency = Number (arg) }
    else                                     { exchanges.push (arg) }
}

/*  --------------------------------------------------------------------------- */

if (!exchanges.length) {

    if (!fs.existsSync ('./exchanges.json')) {

        log.bright.red ('\n\tNo', 'exchanges.json'.white, 'found, please run', 'npm run build'.white, 'to generate it!\n')
        process.exit (1)
    }

    exchanges = require ('./exchanges.json').ids
}

/*  --------------------------------------------------------------------------- */

const sleep = s => new Promise (resolve => setTimeout (resolve, s*1000))
const timeout = (s, promise) => Promise.race ([ promise, sleep (s).then (() => { throw new Error ('timed out') }) ])

/*  --------------------------------------------------------------------------- */

const exec = (bin, ...args) =>

/*  A custom version of child_process.exec that captures both stdout and
    stderr,  not separating them into distinct buffers — so that we can show
    the same output as if it were running in a terminal.                        */

    timeout (120, new Promise (return_ => {

        const ps = require ('child_process').spawn (bin, args)

        let output = ''
        let stderr = ''
        let hasWarnings = false

        ps.stdout.on ('data', data => { output += data.toString () })
        ps.stderr.on ('data', data => { output += data.toString (); stderr += data.toString (); hasWarnings = true })

        ps.on ('exit', code => {

            output = ansi.strip (output.trim ())
            stderr = ansi.strip (stderr)

            const regex = /\[[a-z]+?\]/gmi

            let match = undefined
            const warnings = []

            match = regex.exec (output)

            if (match) {
                warnings.push (match[0])
                do {
                    if (match = regex.exec (output)) {
                        warnings.push (match[0])
                    }
                } while (match);
            }

            return_ ({
                failed: code !== 0,
                output,
                hasOutput: output.length > 0,
                hasWarnings: hasWarnings || warnings.length > 0,
                warnings: warnings,
            })
        })

    })).catch (e => ({

        failed: true,
        output: e.message

    })).then (x => Object.assign (x, { hasOutput: x.output.length > 0 }))

/*  ------------------------------------------------------------------------ */

// const execWithRetry = () => {

//     // Sometimes execution (on a remote CI server) is just fails with no
//     // apparent reason, leaving an empty stdout/stderr behind. I suspect
//     // it's related to out-of-memory errors. So in that case we will re-try
//     // until it eventually finalizes.
// }

/*  ------------------------------------------------------------------------ */

let numExchangesTested = 0

/*  Tests of different languages for the same exchange should be run
    sequentially to prevent the interleaving nonces problem.
    ------------------------------------------------------------------------ */

const sequentialMap = async (input, fn) => {

    const result = []
    for (const item of input) { result.push (await fn (item)) }
    return result
}

/*  ------------------------------------------------------------------------ */

const testExchange = async (exchange) => {

/*  Run tests for all/selected languages (in parallel)     */

    const args = [exchange, ...symbol === 'all' ? [] : symbol]
        , allTests = [

            { language: 'JavaScript',     key: '--js',           exec: ['node',      'js/rest/test/test.js',           ...args] },
            { language: 'Python 3',       key: '--python',       exec: ['python3',   'python/ccxt/rest/test/test_sync.py',  ...args] },
            { language: 'Python 3 Async', key: '--python-async', exec: ['python3',   'python/ccxt/rest/test/test_async.py', ...args] },
            { language: 'PHP',            key: '--php',          exec: ['php', '-f', 'php/rest/test/test_sync.php',         ...args] },
            { language: 'PHP Async',      key: '--php-async',    exec: ['php', '-f', 'php/rest/test/test_async.php',   ...args] },
        ]
        , selectedTests  = allTests.filter (t => keys[t.key])
        , scheduledTests = selectedTests.length ? selectedTests : allTests
        , completeTests  = await sequentialMap (scheduledTests, async test => Object.assign (test, await exec (...test.exec)))
        , failed         = completeTests.find (test => test.failed)
        , hasWarnings    = completeTests.find (test => test.hasWarnings)
        , warnings       = completeTests.reduce ((total, { warnings }) => total.concat (warnings), [])

/*  Print interactive log output    */

    numExchangesTested++

    const percentsDone = ((numExchangesTested / exchanges.length) * 100).toFixed (0) + '%'

    log.bright (('[' + percentsDone + ']').dim, 'Testing', exchange.cyan, (failed      ? 'FAIL'.red :
                                                                          (hasWarnings ? (warnings.length ? warnings.join (' ') : 'WARN').yellow
                                                                                : 'OK'.green)))

/*  Return collected data to main loop     */

    return {

        exchange,
        failed,
        hasWarnings,
        explain () {
            for (const { language, failed, output, hasWarnings } of completeTests) {
                if (failed || hasWarnings) {

                    if (!failed && output.indexOf('[Skipped]') >= 0)
                        continue;

                    if (failed) { log.bright ('\nFAILED'.bgBrightRed.white, exchange.red,    '(' + language + '):\n') }
                    else        { log.bright ('\nWARN'.yellow.inverse,      exchange.yellow, '(' + language + '):\n') }

                    log.indent (1) (output)
                }
            }
        }
    }
}

/*  ------------------------------------------------------------------------ */

function TaskPool (maxConcurrency) {

    const pending = []
        , queue   = []

    let numActive = 0

    return {

        pending,

        run (task) {

            if (numActive >= maxConcurrency) { // queue task

                return new Promise (resolve => queue.push (() => this.run (task).then (resolve)))

            } else { // execute task

                let p = task ().then (x => {
                    numActive--
                    return (queue.length && (numActive < maxConcurrency))
                                ? queue.shift () ().then (() => x)
                                : x
                })
                numActive++
                pending.push (p)
                return p
            }
        }
    }
}

/*  ------------------------------------------------------------------------ */

async function testAllExchanges () {

    const taskPool = TaskPool (maxConcurrency)
    const results = []

    for (const exchange of exchanges) {
        taskPool.run (() => testExchange (exchange).then (x => results.push (x)))
    }

    await Promise.all (taskPool.pending)

    return results
}

/*  ------------------------------------------------------------------------ */

(async function () {

    log.bright.magenta.noPretty ('Testing'.white, Object.assign (
                                                            { exchanges, symbol, keys },
                                                            maxConcurrency >= Number.MAX_VALUE ? {} : { maxConcurrency }))

    const tested    = await testAllExchanges ()
        , warnings  = tested.filter (t => !t.failed && t.hasWarnings)
        , failed    = tested.filter (t =>  t.failed)
        , succeeded = tested.filter (t => !t.failed && !t.hasWarnings)

    log.newline ()

    warnings.forEach (t => t.explain ())
    failed.forEach (t => t.explain ())

    log.newline ()

    if (failed.length)   { log.noPretty.bright.red    ('FAIL'.bgBrightRed.white, failed.map (t => t.exchange)) }
    if (warnings.length) { log.noPretty.bright.yellow ('WARN'.inverse,           warnings.map (t => t.exchange)) }

    log.newline ()

    log.bright ('All done,', [failed.length    && (failed.length    + ' failed')   .red,
                              succeeded.length && (succeeded.length + ' succeeded').green,
                              warnings.length  && (warnings.length  + ' warnings') .yellow].filter (s => s).join (', '))

    if (failed.length) {

        await sleep (10) // to fight TravisCI log truncation issue, see https://github.com/travis-ci/travis-ci/issues/8189
        process.exit (1)

    } else {
        process.exit (0)
    }

}) ();

/*  ------------------------------------------------------------------------ */
<|endoftext|>


<commit_before>import * as _ from 'lodash'

import hasDepartment from 'helpers/hasDepartment'
import {partialNameOrTitle} from 'helpers/partialTitle'
import {checkCoursesFor} from 'helpers/courses'

import {isRequiredCourse} from './commonMajorUtilities.es6'

const csDeptRequiredCourses = [
	{deptnum: 'CSCI 121'}, {deptnum: 'CSCI 125'}, {deptnum: 'CSCI 241'}, {deptnum: 'CSCI 251'},
	{deptnum: 'CSCI 252'}, {deptnum: 'CSCI 231'}, {deptnum: 'CSCI 253'}, {deptnum: 'CSCI 263'},
	{deptnum: 'CSCI 276'}, {deptnum: 'CSCI 333'}, {deptnum: 'CSCI 273'}, {deptnum: 'CSCI 284'},
	{deptnum: 'CSCI 390'},

	// IR/IS
	{deptnum: 'CSCI 298'}, {deptnum: 'CSCI 398'},

	{deptnum: 'CSCI 300', name: 'Parallel'},

	{deptnum: 'MATH 232'}, {deptnum: 'MATH 252'},
]

let isRequiredCompSciCourse = _.curry(isRequiredCourse(csDeptRequiredCourses))

function foundationCourses(courses) {
	/* Foundation courses:
		- one of Computer Science 121 or 125;
		- Computer Science 241, 251, and 252;
		- one of Computer Science 231 or Math 232 or Math 252.
	*/

	var cs1 = _.any([
		checkCoursesFor(courses, {deptnum:'CSCI 121'}),
		checkCoursesFor(courses, {deptnum:'CSCI 125'}),
	])

	var design = _.all([
		checkCoursesFor(courses, {deptnum:'CSCI 241'}),
		checkCoursesFor(courses, {deptnum:'CSCI 251'}),
		checkCoursesFor(courses, {deptnum:'CSCI 252'}),
	])

	var proofWriting = _.any([
		checkCoursesFor(courses, {deptnum:'MATH 282', term:20141}),
		checkCoursesFor(courses, {deptnum:'MATH 244'}),
		checkCoursesFor(courses, {deptnum:'MATH 252'}),
	])

	let requirements = [
		{
			title: 'CS1',
			result: cs1,
		},
		{
			title: 'Design',
			result: design,
		},
		{
			title: 'Proof Writing',
			result: proofWriting,
		},
	]

	return {
		title: 'Foundation',
		description: '- one of Computer Science 121 or 125;\n- Computer Science 241, 251, and 252;\n- one of Computer Science 231 or Math 232 or Math 252.',
		result: _.all(requirements, 'result'),
		type: 'array/boolean',
		details: requirements,
	}
}

function coreCourses(courses) {
	/* Core courses:
		- Computer Science 253;
		- Computer Science 263;
		- either of Computer Science 276 or 333;
		- and either Computer Science 273, 284, or 300 with parallel and distributed computing.
	*/

	var algorithms = checkCoursesFor(courses, {deptnum:'CSCI 253'})

	var ethics = checkCoursesFor(courses, {deptnum:'CSCI 263'})

	var theory = _.any([
		checkCoursesFor(courses, {deptnum:'CSCI 276'}),
		checkCoursesFor(courses, {deptnum:'CSCI 333'})
	])

	var parallelDistributedComputing = _.chain(courses)
		.filter({deptnum:'CSCI 300'})
		.filter(partialNameOrTitle('Parallel'))
		.size().value() >= 1

	var options = _.any([
		checkCoursesFor(courses, {deptnum:'CSCI 273'}),
		checkCoursesFor(courses, {deptnum:'CSCI 284'}),
		parallelDistributedComputing
	])

	let requirements = [
		{
			title: 'Algorithms',
			result: algorithms,
		},
		{
			title: 'Ethics',
			result: ethics,
		},
		{
			title: 'Theory',
			result: theory,
		},
		{
			title: 'Options',
			result: options
		},
	]

	return {
		title: 'Core',
		type: 'array/boolean',
		description: '- Computer Science 253;\n- Computer Science 263;\n- either Computer Science 276 or 333;\n- and either Computer Science 273, 284, or 300 with parallel and distributed computing.',
		result: _.all(requirements, 'result'),
		details: requirements,
	}
}

function electiveCourses(courses) {
	// Electives: Two approved electives.

	var validCourses = _.chain(courses)
		.filter(hasDepartment('CSCI'))
		.reject(isRequiredCompSciCourse)
		.value()

	var numberTaken = _.size(validCourses)
	var numberNeeded = 2

	return {
		title: 'Electives',
		type: 'object/number',
		description: 'Two approved electives.',
		result: numberTaken >= numberNeeded,
		details: {
			has: numberTaken,
			needs: numberNeeded,
			matches: validCourses,
		}
	}
}

function capstoneCourse(courses) {
	// Capstone: Computer Science 390
	var hasTakenCapstone = checkCoursesFor(courses, {dept:'CSCI', num:390})

	return {
		title: 'Capstone',
		type: 'boolean',
		description: 'The Computer Science Capstone Course',
		result: hasTakenCapstone
	}
}

function checkComputerScienceMajor(student) {
	return student.data().then((studentPieces) => {
		let {courses} = studentPieces

		var computerScienceMajorRequirements = [
			foundationCourses(courses),
			coreCourses(courses),
			electiveCourses(courses),
			capstoneCourse(courses),
		]

		return {
			result: _.all(computerScienceMajorRequirements, 'result'),
			details: computerScienceMajorRequirements,
		}
	})
}

export default checkComputerScienceMajor
<commit_msg>Update the CSCI-Core description markdown<commit_after>import * as _ from 'lodash'

import hasDepartment from 'helpers/hasDepartment'
import {partialNameOrTitle} from 'helpers/partialTitle'
import {checkCoursesFor} from 'helpers/courses'

import {isRequiredCourse} from './commonMajorUtilities.es6'

const csDeptRequiredCourses = [
	{deptnum: 'CSCI 121'}, {deptnum: 'CSCI 125'}, {deptnum: 'CSCI 241'}, {deptnum: 'CSCI 251'},
	{deptnum: 'CSCI 252'}, {deptnum: 'CSCI 231'}, {deptnum: 'CSCI 253'}, {deptnum: 'CSCI 263'},
	{deptnum: 'CSCI 276'}, {deptnum: 'CSCI 333'}, {deptnum: 'CSCI 273'}, {deptnum: 'CSCI 284'},
	{deptnum: 'CSCI 390'},

	// IR/IS
	{deptnum: 'CSCI 298'}, {deptnum: 'CSCI 398'},

	{deptnum: 'CSCI 300', name: 'Parallel'},

	{deptnum: 'MATH 232'}, {deptnum: 'MATH 252'},
]

let isRequiredCompSciCourse = _.curry(isRequiredCourse(csDeptRequiredCourses))

function foundationCourses(courses) {
	/* Foundation courses:
		- one of Computer Science 121 or 125;
		- Computer Science 241, 251, and 252;
		- one of Computer Science 231 or Math 232 or Math 252.
	*/

	var cs1 = _.any([
		checkCoursesFor(courses, {deptnum:'CSCI 121'}),
		checkCoursesFor(courses, {deptnum:'CSCI 125'}),
	])

	var design = _.all([
		checkCoursesFor(courses, {deptnum:'CSCI 241'}),
		checkCoursesFor(courses, {deptnum:'CSCI 251'}),
		checkCoursesFor(courses, {deptnum:'CSCI 252'}),
	])

	var proofWriting = _.any([
		checkCoursesFor(courses, {deptnum:'MATH 282', term:20141}),
		checkCoursesFor(courses, {deptnum:'MATH 244'}),
		checkCoursesFor(courses, {deptnum:'MATH 252'}),
	])

	let requirements = [
		{
			title: 'CS1',
			result: cs1,
		},
		{
			title: 'Design',
			result: design,
		},
		{
			title: 'Proof Writing',
			result: proofWriting,
		},
	]

	return {
		title: 'Foundation',
		description: '- one of Computer Science 121 or 125;\n- Computer Science 241, 251, and 252;\n- one of Computer Science 231 or Math 232 or Math 252.',
		result: _.all(requirements, 'result'),
		type: 'array/boolean',
		details: requirements,
	}
}

function coreCourses(courses) {
	/* Core courses:
		- Computer Science 253;
		- Computer Science 263;
		- either of Computer Science 276 or 333;
		- and either Computer Science 273, 284, or 300 with parallel and distributed computing.
	*/

	var algorithms = checkCoursesFor(courses, {deptnum:'CSCI 253'})

	var ethics = checkCoursesFor(courses, {deptnum:'CSCI 263'})

	var theory = _.any([
		checkCoursesFor(courses, {deptnum:'CSCI 276'}),
		checkCoursesFor(courses, {deptnum:'CSCI 333'})
	])

	var parallelDistributedComputing = _.chain(courses)
		.filter({deptnum:'CSCI 300'})
		.filter(partialNameOrTitle('Parallel'))
		.size().value() >= 1

	var options = _.any([
		checkCoursesFor(courses, {deptnum:'CSCI 273'}),
		checkCoursesFor(courses, {deptnum:'CSCI 284'}),
		parallelDistributedComputing
	])

	let requirements = [
		{
			title: 'Algorithms',
			result: algorithms,
		},
		{
			title: 'Ethics',
			result: ethics,
		},
		{
			title: 'Theory',
			result: theory,
		},
		{
			title: 'Options',
			result: options
		},
	]

	return {
		title: 'Core',
		type: 'array/boolean',
		description: '- **Algorithms:** Computer Science 253 *(Algorithms and Data Structures)*;\n- **Ethics:** Computer Science 263 *(Ethical Issues in Software Design)*;\n- **Theory:** either Computer Science 276 *(Programming Languages)* or 333 *(Theory of Computation)*;\n- **Options:** and either Computer Science 273 *(Operating Systems)*, 284 *(Mobile Computing Applications)*, or 300 *(Topics)* with parallel and distributed computing.',
		result: _.all(requirements, 'result'),
		details: requirements,
	}
}

function electiveCourses(courses) {
	// Electives: Two approved electives.

	var validCourses = _.chain(courses)
		.filter(hasDepartment('CSCI'))
		.reject(isRequiredCompSciCourse)
		.value()

	var numberTaken = _.size(validCourses)
	var numberNeeded = 2

	return {
		title: 'Electives',
		type: 'object/number',
		description: 'Two approved electives.',
		result: numberTaken >= numberNeeded,
		details: {
			has: numberTaken,
			needs: numberNeeded,
			matches: validCourses,
		}
	}
}

function capstoneCourse(courses) {
	// Capstone: Computer Science 390
	var hasTakenCapstone = checkCoursesFor(courses, {dept:'CSCI', num:390})

	return {
		title: 'Capstone',
		type: 'boolean',
		description: 'The Computer Science Capstone Course',
		result: hasTakenCapstone
	}
}

function checkComputerScienceMajor(student) {
	return student.data().then((studentPieces) => {
		let {courses} = studentPieces

		var computerScienceMajorRequirements = [
			foundationCourses(courses),
			coreCourses(courses),
			electiveCourses(courses),
			capstoneCourse(courses),
		]

		return {
			result: _.all(computerScienceMajorRequirements, 'result'),
			details: computerScienceMajorRequirements,
		}
	})
}

export default checkComputerScienceMajor
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import { localeUtils } from './utils';

const keys = {
  LEFT: 37,
  RIGHT: 39,
  ENTER: 13,
  SPACE: 32
};

class WeekdayPicker extends Component {
  static propTypes = {
    className: PropTypes.string,
    style: PropTypes.object,
    tabIndex: PropTypes.number,

    ariaModifier: PropTypes.string,
    modifiers: PropTypes.object,

    locale: PropTypes.string,
    localeUtils: PropTypes.shape({
      formatWeekdayShort: PropTypes.func.isRequired,
      formatWeekdayLong: PropTypes.func.isRequired
    }),

    onWeekdayClick: PropTypes.func,
    onWeekdayMouseEnter: PropTypes.func,
    onWeekdayMouseLeave: PropTypes.func,
    onWeekdayTouchTap: PropTypes.func,
  }

  static defaultProps = {
    ariaModifier: 'selected',
    locale: 'en',
    localeUtils: localeUtils,
    tabIndex: 0,
  }

  getModifiersForDay(weekday, modifierFunctions) {
    const modifiers = [];
    if (modifierFunctions) {
      for (const modifier in modifierFunctions) {
        const func = modifierFunctions[modifier];
        if (func(weekday)) {
          modifiers.push(modifier);
        }
      }
    }
    return modifiers;
  }

  render() {
    const { locale, style, tabIndex } = this.props;
    let className = `WeekdayPicker DayPicker DayPicker--${locale}`;

    if (!this.props.onWeekdayClick && !this.props.onWeekdayTouchTap) {
      className = `${className} WeekdayPicker--InteractionDisabled`;
    }
    if (this.props.className) {
      className = `${className} ${this.props.className}`;
    }

    return (

        {this.renderWeekDays()}

    );
  }

  renderWeekDays() {
    let weekdays = [];
    for (let i = 0; i < 7; i++) {
      weekdays.push(this.renderWeekday(i));
    }
    return (

            {weekdays}

    );
  }

  renderWeekday(weekday) {
    const { locale, localeUtils, modifiers: modifierFunctions } = this.props;

    let className = 'DayPicker-Weekday';
    let modifiers = [];

    if (modifierFunctions) {
      const customModifiers = this.getModifiersForDay(weekday, modifierFunctions);
      modifiers = [...modifiers, ...customModifiers];
    }

    className += modifiers.map(modifier => ` ${className}--${modifier}`).join('');

    const ariaSelected = modifiers.indexOf(this.props.ariaModifier) > -1;

    const {
      onWeekdayClick,
      onWeekdayMouseEnter,
      onWeekdayMouseLeave,
      onWeekdayTouchTap,
    } = this.props;

    let tabIndex = null;
    if (onWeekdayTouchTap || onWeekdayClick) {
      tabIndex = -1;
      // Focus on the first day of the week
      if (weekday === 0) {
        tabIndex = this.props.tabIndex;
      }
    }

    let onClick = null;
    if (onWeekdayClick) {
      onClick = (e) => this.handleWeekdayClick(e, weekday, modifiers);
    }
    let onMouseEnter = null;
    if (onWeekdayMouseEnter) {
      onMouseEnter = (e) => this.handleWeekdayMouseEnter(e, weekday, modifiers);
    }
    let onMouseLeave = null;
    if (onWeekdayMouseLeave) {
      onMouseLeave = (e) => this.handleWeekdayMouseLeave(e, weekday, modifiers);
    }
    let onTouchTap = null;
    if (onWeekdayTouchTap) {
      onTouchTap = (e) => this.handleWeekdayTouchTap(e, weekday, modifiers)
    }

    return (
      <button key={weekday} className={className} tabIndex={tabIndex}
        aria-pressed={ariaSelected}
        onClick= {onClick}
        onKeyDown={(e) => this.handleDayKeyDown(e, weekday, modifiers)}
        onMouseEnter={onMouseEnter}
        onMouseLeave= {onMouseLeave}
        onTouchTap= {onTouchTap}
      >
        <attr title={localeUtils.formatWeekdayLong(weekday, locale)}>
          {localeUtils.formatWeekdayShort(weekday, locale)}
        </attr>
      </button>
    );
  }

  focusPreviousDay(dayNode) {
    const body = dayNode.parentNode.parentNode.parentNode.parentNode;
    let dayNodes = body.querySelectorAll('.DayPicker-Weekday:not(.DayPicker-Weekday--outside)');
    let nodeIndex;
    for (let i = 0; i < dayNodes.length; i++) {
      if (dayNodes[i] === dayNode) {
        nodeIndex = i;
        break;
      }
    }
    if (nodeIndex !== 0) {
      dayNodes[nodeIndex - 1].focus();
    }
  }

  focusNextDay(dayNode) {
    const body = dayNode.parentNode.parentNode.parentNode.parentNode;
    let dayNodes = body.querySelectorAll('.DayPicker-Weekday:not(.DayPicker-Weekday--outside)');
    let nodeIndex;
    for (let i = 0; i < dayNodes.length; i++) {
      if (dayNodes[i] === dayNode) {
        nodeIndex = i;
        break;
      }
    }

    if (nodeIndex !== dayNodes.length - 1) {
      dayNodes[nodeIndex + 1].focus();
    }
  }

  // Event handlers
  handleDayKeyDown(e, day, modifiers) {
    e.persist();
    switch (e.keyCode) {
      case keys.LEFT:
        e.preventDefault();
        e.stopPropagation();
        this.focusPreviousDay(e.target);
      break;
      case keys.RIGHT:
        e.preventDefault();
        e.stopPropagation();
        this.focusNextDay(e.target);
      break;
      case keys.ENTER:
      case keys.SPACE:
        e.preventDefault();
        e.stopPropagation();
        if (this.props.onWeekdayClick) {
          this.handleWeekdayClick(e, day, modifiers);
        }
        if (this.props.onWeekdayTouchTap) {
          this.handleWeekdayTouchTap(e, day, modifiers);
        }
      break;
    }
  }

  handleWeekdayTouchTap(e, weekday, modifiers) {
    e.persist();
    this.props.onWeekdayTouchTap(e, weekday, modifiers);
  }

  handleWeekdayClick(e, weekday, modifiers) {
    e.persist();
    this.props.onWeekdayClick(e, weekday, modifiers);
  }

  handleWeekdayMouseEnter(e, weekday, modifiers) {
    e.persist();
    this.props.onWeekdayMouseEnter(e, weekday, modifiers);
  }

  handleWeekdayMouseLeave(e, weekday, modifiers) {
    e.persist();
    this.props.onWeekdayMouseLeave(e, weekday, modifiers);
  }
}

export default WeekdayPicker;
<commit_msg>Require PropTypes from prop-types<commit_after>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { localeUtils } from './utils';

const keys = {
  LEFT: 37,
  RIGHT: 39,
  ENTER: 13,
  SPACE: 32
};

class WeekdayPicker extends Component {
  static propTypes = {
    className: PropTypes.string,
    style: PropTypes.object,
    tabIndex: PropTypes.number,

    ariaModifier: PropTypes.string,
    modifiers: PropTypes.object,

    locale: PropTypes.string,
    localeUtils: PropTypes.shape({
      formatWeekdayShort: PropTypes.func.isRequired,
      formatWeekdayLong: PropTypes.func.isRequired
    }),

    onWeekdayClick: PropTypes.func,
    onWeekdayMouseEnter: PropTypes.func,
    onWeekdayMouseLeave: PropTypes.func,
    onWeekdayTouchTap: PropTypes.func,
  }

  static defaultProps = {
    ariaModifier: 'selected',
    locale: 'en',
    localeUtils: localeUtils,
    tabIndex: 0,
  }

  getModifiersForDay(weekday, modifierFunctions) {
    const modifiers = [];
    if (modifierFunctions) {
      for (const modifier in modifierFunctions) {
        const func = modifierFunctions[modifier];
        if (func(weekday)) {
          modifiers.push(modifier);
        }
      }
    }
    return modifiers;
  }

  render() {
    const { locale, style, tabIndex } = this.props;
    let className = `WeekdayPicker DayPicker DayPicker--${locale}`;

    if (!this.props.onWeekdayClick && !this.props.onWeekdayTouchTap) {
      className = `${className} WeekdayPicker--InteractionDisabled`;
    }
    if (this.props.className) {
      className = `${className} ${this.props.className}`;
    }

    return (

        {this.renderWeekDays()}

    );
  }

  renderWeekDays() {
    let weekdays = [];
    for (let i = 0; i < 7; i++) {
      weekdays.push(this.renderWeekday(i));
    }
    return (

            {weekdays}

    );
  }

  renderWeekday(weekday) {
    const { locale, localeUtils, modifiers: modifierFunctions } = this.props;

    let className = 'DayPicker-Weekday';
    let modifiers = [];

    if (modifierFunctions) {
      const customModifiers = this.getModifiersForDay(weekday, modifierFunctions);
      modifiers = [...modifiers, ...customModifiers];
    }

    className += modifiers.map(modifier => ` ${className}--${modifier}`).join('');

    const ariaSelected = modifiers.indexOf(this.props.ariaModifier) > -1;

    const {
      onWeekdayClick,
      onWeekdayMouseEnter,
      onWeekdayMouseLeave,
      onWeekdayTouchTap,
    } = this.props;

    let tabIndex = null;
    if (onWeekdayTouchTap || onWeekdayClick) {
      tabIndex = -1;
      // Focus on the first day of the week
      if (weekday === 0) {
        tabIndex = this.props.tabIndex;
      }
    }

    let onClick = null;
    if (onWeekdayClick) {
      onClick = (e) => this.handleWeekdayClick(e, weekday, modifiers);
    }
    let onMouseEnter = null;
    if (onWeekdayMouseEnter) {
      onMouseEnter = (e) => this.handleWeekdayMouseEnter(e, weekday, modifiers);
    }
    let onMouseLeave = null;
    if (onWeekdayMouseLeave) {
      onMouseLeave = (e) => this.handleWeekdayMouseLeave(e, weekday, modifiers);
    }
    let onTouchTap = null;
    if (onWeekdayTouchTap) {
      onTouchTap = (e) => this.handleWeekdayTouchTap(e, weekday, modifiers)
    }

    return (
      <button key={weekday} className={className} tabIndex={tabIndex}
        aria-pressed={ariaSelected}
        onClick= {onClick}
        onKeyDown={(e) => this.handleDayKeyDown(e, weekday, modifiers)}
        onMouseEnter={onMouseEnter}
        onMouseLeave= {onMouseLeave}
        onTouchTap= {onTouchTap}
      >
        <attr title={localeUtils.formatWeekdayLong(weekday, locale)}>
          {localeUtils.formatWeekdayShort(weekday, locale)}
        </attr>
      </button>
    );
  }

  focusPreviousDay(dayNode) {
    const body = dayNode.parentNode.parentNode.parentNode.parentNode;
    let dayNodes = body.querySelectorAll('.DayPicker-Weekday:not(.DayPicker-Weekday--outside)');
    let nodeIndex;
    for (let i = 0; i < dayNodes.length; i++) {
      if (dayNodes[i] === dayNode) {
        nodeIndex = i;
        break;
      }
    }
    if (nodeIndex !== 0) {
      dayNodes[nodeIndex - 1].focus();
    }
  }

  focusNextDay(dayNode) {
    const body = dayNode.parentNode.parentNode.parentNode.parentNode;
    let dayNodes = body.querySelectorAll('.DayPicker-Weekday:not(.DayPicker-Weekday--outside)');
    let nodeIndex;
    for (let i = 0; i < dayNodes.length; i++) {
      if (dayNodes[i] === dayNode) {
        nodeIndex = i;
        break;
      }
    }

    if (nodeIndex !== dayNodes.length - 1) {
      dayNodes[nodeIndex + 1].focus();
    }
  }

  // Event handlers
  handleDayKeyDown(e, day, modifiers) {
    e.persist();
    switch (e.keyCode) {
      case keys.LEFT:
        e.preventDefault();
        e.stopPropagation();
        this.focusPreviousDay(e.target);
      break;
      case keys.RIGHT:
        e.preventDefault();
        e.stopPropagation();
        this.focusNextDay(e.target);
      break;
      case keys.ENTER:
      case keys.SPACE:
        e.preventDefault();
        e.stopPropagation();
        if (this.props.onWeekdayClick) {
          this.handleWeekdayClick(e, day, modifiers);
        }
        if (this.props.onWeekdayTouchTap) {
          this.handleWeekdayTouchTap(e, day, modifiers);
        }
      break;
    }
  }

  handleWeekdayTouchTap(e, weekday, modifiers) {
    e.persist();
    this.props.onWeekdayTouchTap(e, weekday, modifiers);
  }

  handleWeekdayClick(e, weekday, modifiers) {
    e.persist();
    this.props.onWeekdayClick(e, weekday, modifiers);
  }

  handleWeekdayMouseEnter(e, weekday, modifiers) {
    e.persist();
    this.props.onWeekdayMouseEnter(e, weekday, modifiers);
  }

  handleWeekdayMouseLeave(e, weekday, modifiers) {
    e.persist();
    this.props.onWeekdayMouseLeave(e, weekday, modifiers);
  }
}

export default WeekdayPicker;
<|endoftext|>


<commit_before>const Joi = require('joi');
const config = require('../config/config');
const Boom = require('boom');
const validations = require('../config/validations');
const crypto = require('crypto');
const mongoose = require('mongoose');
var ObjectId = require('mongoose').Types.ObjectId;

exports.register = function (server, options, next) {

    server.log(['info'], 'Loading user controller');

    const User = server.plugins['db'].models.User;
    const Interest = server.plugins['db'].models.Interest;
    const ParticipantRequest = server.plugins['db'].models.ParticipantRequest;

    const getUsers = function(request, reply) {
        server.log(['info'], 'getting all users');

        console.log(User);

        User.find(function (err, users) {
            if (!err) {
                reply(users);
            } else {
                reply(Boom.badImplementation(err)); // 500 error
            }
        });
    };

    server.route({
        method: ['GET'],
        path: '/user',
        config: {
            auth: false,
            handler: getUsers,
            description: 'Get all users',
            notes: 'Returns all users',
            tags: ['api', 'user']
        }
    });

    const getProfile = function(request, reply) {

        let userId =request.auth.credentials.id;

        User.findOne({
            _id : userId
        }, function(err, user) {
            if (!err) {
                reply(user);
            } else {
                reply(Boom.badImplementation(err)); // 500 error
            }
        });
    };

    server.route({
        method: ['GET'],
        path: '/user/profile',
        config: {
            handler: getProfile,
            description: 'get user profile',
            notes: 'get current user\'s profile info',
            tags: ['api', 'profile', 'user']
        }
    });

    const getUser = function(request, reply) {

        let userId = request.params.id;

        User.findOne({
            _id : userId
        }, function(err, user) {
            if (!err) {
                reply(user);
            } else {
                reply(Boom.badImplementation(err)); // 500 error
            }
        });
    };

    server.route({
        method: ['GET'],
        path: '/user/{id}',
        config: {
            auth: false,
            handler: getUser,
            description: 'Get user info by id',
            notes: 'Returns user by id.',
            tags: ['api', 'user'],
            validate: {
                params: {
                    id : validations.slug.description('user id')
                }
            }
        }
    });

    const getInterests = function(request, reply) {

        let userId = request.params.id;

        let query = {
            user : new ObjectId(userId),
            status: true
        };

        if(request.query.type==='past') {
            query.endDate = {
                $lte: new Date()
            };
        }
        else if(request.query.type==='future') {
            query.startDate = {
                $gt: new Date()
            };
        }

        Interest
            .find(query)
            .sort({'createdAt': -1})
            .limit(100)
            .populate('user')
            .populate('participants')
            .exec(function(err, result) {
                if (err)
                    return reply(Boom.badImplementation(err));

                // remove point from location data
                // delete not working on mongo response: http://stackoverflow.com/questions/32272937/javascript-delete-object-property-not-working
                const jsonResult = JSON.parse(JSON.stringify(result));

                jsonResult.forEach(function (item) {
                    item.location = item.location.coordinates;
                });

                reply({ results: jsonResult });
            });
    };

    server.route({
        method: ['GET'],
        path: '/user/{id}/interest',
        config: {
            auth: false,
            handler: getInterests,
            description: 'Get user interests',
            notes: 'Returns user interests',
            tags: ['api', 'user'],
            validate: {
                params: {
                    id : validations.slug.description('user id')
                },
                query: {
                    type: Joi.any().valid(['past', 'future']).optional().description('type')
                }
            }
        }
    });

    const pendingRequests = function(request, reply) {

        ParticipantRequest.find({
            owner: new ObjectId(request.params.id),
            status: 'pending'
        })
            .populate('user')
            .populate('interest')
            .exec(function(err, result) {
                if (err)
                    return reply(Boom.badImplementation(err));

                reply(result);
            })

    };

    server.route({
        method: ['GET'],
        path: '/user/{id}/requests',
        config: {
            auth: false,
            handler: pendingRequests,
            description: 'Returns pending requests',
            notes: 'Returns pending requests',
            tags: ['api', 'user'],
            validate: {
                params: {
                    id : validations.slug.description('user id')
                }
            }
        }
    });

    server.log(['info'], 'User controller loaded');
    next(); //IMPORTANT
};

exports.register.attributes = {
    name: 'UserController'
};
<commit_msg>pending requests sort & fix client obj<commit_after>const Joi = require('joi');
const config = require('../config/config');
const Boom = require('boom');
const validations = require('../config/validations');
const crypto = require('crypto');
const mongoose = require('mongoose');
var ObjectId = require('mongoose').Types.ObjectId;

exports.register = function (server, options, next) {

    server.log(['info'], 'Loading user controller');

    const User = server.plugins['db'].models.User;
    const Interest = server.plugins['db'].models.Interest;
    const ParticipantRequest = server.plugins['db'].models.ParticipantRequest;

    const getUsers = function(request, reply) {
        server.log(['info'], 'getting all users');

        console.log(User);

        User.find(function (err, users) {
            if (!err) {
                reply(users);
            } else {
                reply(Boom.badImplementation(err)); // 500 error
            }
        });
    };

    server.route({
        method: ['GET'],
        path: '/user',
        config: {
            auth: false,
            handler: getUsers,
            description: 'Get all users',
            notes: 'Returns all users',
            tags: ['api', 'user']
        }
    });

    const getProfile = function(request, reply) {

        let userId =request.auth.credentials.id;

        User.findOne({
            _id : userId
        }, function(err, user) {
            if (!err) {
                reply(user);
            } else {
                reply(Boom.badImplementation(err)); // 500 error
            }
        });
    };

    server.route({
        method: ['GET'],
        path: '/user/profile',
        config: {
            handler: getProfile,
            description: 'get user profile',
            notes: 'get current user\'s profile info',
            tags: ['api', 'profile', 'user']
        }
    });

    const getUser = function(request, reply) {

        let userId = request.params.id;

        User.findOne({
            _id : userId
        }, function(err, user) {
            if (!err) {
                reply(user);
            } else {
                reply(Boom.badImplementation(err)); // 500 error
            }
        });
    };

    server.route({
        method: ['GET'],
        path: '/user/{id}',
        config: {
            auth: false,
            handler: getUser,
            description: 'Get user info by id',
            notes: 'Returns user by id.',
            tags: ['api', 'user'],
            validate: {
                params: {
                    id : validations.slug.description('user id')
                }
            }
        }
    });

    const getInterests = function(request, reply) {

        let userId = request.params.id;

        let query = {
            user : new ObjectId(userId),
            status: true
        };

        if(request.query.type==='past') {
            query.endDate = {
                $lte: new Date()
            };
        }
        else if(request.query.type==='future') {
            query.startDate = {
                $gt: new Date()
            };
        }

        Interest
            .find(query)
            .sort({'createdAt': -1})
            .limit(100)
            .populate('user')
            .populate('participants')
            .exec(function(err, result) {
                if (err)
                    return reply(Boom.badImplementation(err));

                // remove point from location data
                // delete not working on mongo response: http://stackoverflow.com/questions/32272937/javascript-delete-object-property-not-working
                const jsonResult = JSON.parse(JSON.stringify(result));

                jsonResult.forEach(function (item) {
                    item.location = item.location.coordinates;
                });

                reply({ results: jsonResult });
            });
    };

    server.route({
        method: ['GET'],
        path: '/user/{id}/interest',
        config: {
            auth: false,
            handler: getInterests,
            description: 'Get user interests',
            notes: 'Returns user interests',
            tags: ['api', 'user'],
            validate: {
                params: {
                    id : validations.slug.description('user id')
                },
                query: {
                    type: Joi.any().valid(['past', 'future']).optional().description('type')
                }
            }
        }
    });

    const pendingRequests = function(request, reply) {

        ParticipantRequest.find({
            owner: new ObjectId(request.params.id),
            status: 'pending'
        })
            .sort({'createdAt': -1})
            .populate('user')
            .populate('interest')
            .exec(function(err, result) {
                if (err)
                    return reply(Boom.badImplementation(err));

                const jsonResult = JSON.parse(JSON.stringify(result));

                jsonResult.forEach(function (item) {
                    item.interest.location = item.interest.location.coordinates;
                });

                reply({ results: jsonResult });
            })

    };

    server.route({
        method: ['GET'],
        path: '/user/{id}/requests',
        config: {
            auth: false,
            handler: pendingRequests,
            description: 'Returns pending requests',
            notes: 'Returns pending requests',
            tags: ['api', 'user'],
            validate: {
                params: {
                    id : validations.slug.description('user id')
                }
            }
        }
    });

    server.log(['info'], 'User controller loaded');
    next(); //IMPORTANT
};

exports.register.attributes = {
    name: 'UserController'
};
<|endoftext|>


<commit_before>
/*!
 * Ext JS Connect
 * Copyright(c) 2010 Ext JS, Inc.
 * MIT Licensed
 */

/**
 * Module dependencies.
 */

var sys = require('sys'),
    utils = require('./../../utils'),
    Store = require('./store').Store;

// TODO: security

/**
 * Initialize CookieStore with the given options.
 *
 * @param {Object} options
 * @api public
 */

var CookieStore = exports.CookieStore = function CookieStore(options) {
    this.key = 'connect.session';
    this.httpOnly = true;
    this.path = '/';
    for (var key in options) {
        this[key] = options[key];
    }
};

sys.inherits(CookieStore, Store);

/**
 * Fetch session.
 *
 * @param {IncomingMessage} req
 * @param {Function} fn
 * @api public
 */

CookieStore.prototype.fetch = function(req, fn){
    var cookie = req.cookies[this.key];
    if (cookie) {
        try {
            var data = JSON.parse(utils.base64Decode(cookie).trim());
            fn(null, data);
        } catch (err) {
            fn(err);
        }
    } else {
        fn();
    }
};

/**
 * Commit session data to the given request.
 *
 * @param {Object} data
 * @param {ServerResponse} res
 * @param {Function} fn
 * @api public
 */

CookieStore.prototype.commit = function(data, res, fn){
    data = utils.base64Encode(JSON.stringify(data));
    res.headers['Set-Cookie'] = utils.serializeCookie(this.key, data);
    fn && fn();
};<commit_msg>Implemented CookieStore cookie options<commit_after>
/*!
 * Ext JS Connect
 * Copyright(c) 2010 Ext JS, Inc.
 * MIT Licensed
 */

/**
 * Module dependencies.
 */

var sys = require('sys'),
    utils = require('./../../utils'),
    Store = require('./store').Store;

// TODO: security

/**
 * Initialize CookieStore with the given options.
 *
 * @param {Object} options
 * @api public
 */

var CookieStore = exports.CookieStore = function CookieStore(options) {
    options = options || {};
    this.key = 'connect.session';
    this.cookie = { path: '/', httpOnly: true };
    for (var key in options.cookie) {
        this.cookie[key] = options.cookie[key];
    }
};

sys.inherits(CookieStore, Store);

/**
 * Fetch session.
 *
 * @param {IncomingMessage} req
 * @param {Function} fn
 * @api public
 */

CookieStore.prototype.fetch = function(req, fn){
    var cookie = req.cookies[this.key];
    if (cookie) {
        try {
            var data = JSON.parse(utils.base64Decode(cookie).trim());
            fn(null, data);
        } catch (err) {
            fn(err);
        }
    } else {
        fn();
    }
};

/**
 * Commit session data to the given request.
 *
 * @param {Object} data
 * @param {ServerResponse} res
 * @param {Function} fn
 * @api public
 */

CookieStore.prototype.commit = function(data, res, fn){
    data = utils.base64Encode(JSON.stringify(data));
    res.headers['Set-Cookie'] = utils.serializeCookie(this.key, data, this.cookie);
    fn && fn();
};<|endoftext|>


<commit_before>import { compose } from 'redux';
import { createSelector } from 'reselect';
import Polyglot from 'node-polyglot';
import { identity } from './private/utils';

const path = arrPath => obj => arrPath.reduce((cursor, key) => cursor && cursor[key], obj);
const toUpper = str => str.toUpperCase();
const titleize = str => str.toLowerCase().replace(/(?:^|\s|-)\S/g, c => c.toUpperCase());
const adjustString = (f, index) => str => (
    str.substr(0, index) + f(str[index]) + str.substr(index + 1)
);
const capitalize = adjustString(toUpper, 0);

const getLocale = path(['polyglot', 'locale']);
const getPhrases = path(['polyglot', 'phrases']);
const getPolyglotScope = (state, { polyglotScope = '' }) => (
    polyglotScope === '' ? '' : `${polyglotScope}.`
);

const getPolyglotOptions = (state, { polyglotOptions = {} }) => polyglotOptions;

const getPolyglot = createSelector(
    getLocale,
    getPhrases,
    getPolyglotOptions,
    (locale, phrases, polyglotOptions) => new Polyglot({
        locale,
        phrases,
        ...polyglotOptions,
    })
);

const getTranslation = createSelector(
    getPolyglot,
    getPolyglotScope,
    (p, scope) => (text, ...args) => p.t(scope + text, ...args)
);

const getTranslationMorphed = (...args) => f => compose(f, getTranslation(...args));
const getTranslationUpperCased = (...args) => getTranslationMorphed(...args)(toUpper);
const getTranslationCapitalized = (...args) => getTranslationMorphed(...args)(capitalize);
const getTranslationTitleized = (...args) => getTranslationMorphed(...args)(titleize);

const createGetP = (polyglotOptions) => (state, { polyglotScope } = {}) => {
    if (!getLocale(state) || !getPhrases(state)) {
        return {
            t: identity,
            tc: identity,
            tt: identity,
            tu: identity,
            tm: identity,
        };
    }
    const options = { polyglotScope, polyglotOptions };
    return {
        ...getPolyglot(state, options),
        t: getTranslation(state, options),
        tc: getTranslationCapitalized(state, options),
        tt: getTranslationTitleized(state, options),
        tu: getTranslationUpperCased(state, options),
        tm: getTranslationMorphed(state, options),
    };
};

const getP = createGetP();

export { getP, getLocale, createGetP };
<commit_msg>Fix useless re-renders (see #71)<commit_after>import { compose } from 'redux';
import { createSelector } from 'reselect';
import Polyglot from 'node-polyglot';
import { identity } from './private/utils';

const path = arrPath => obj => arrPath.reduce((cursor, key) => cursor && cursor[key], obj);
const toUpper = str => str.toUpperCase();
const titleize = str => str.toLowerCase().replace(/(?:^|\s|-)\S/g, c => c.toUpperCase());
const adjustString = (f, index) => str => (
    str.substr(0, index) + f(str[index]) + str.substr(index + 1)
);
const capitalize = adjustString(toUpper, 0);

const getLocale = path(['polyglot', 'locale']);
const getPhrases = path(['polyglot', 'phrases']);
const getPolyglotScope = (state, { polyglotScope = '' }) => (
    polyglotScope === '' ? '' : `${polyglotScope}.`
);

const getPolyglotOptions = (state, { polyglotOptions }) => polyglotOptions;

const getPolyglot = createSelector(
    getLocale,
    getPhrases,
    getPolyglotOptions,
    (locale, phrases, polyglotOptions) => new Polyglot({
        locale,
        phrases,
        ...polyglotOptions,
    })
);

const getTranslation = createSelector(
    getPolyglot,
    getPolyglotScope,
    (p, scope) => (text, ...args) => p.t(scope + text, ...args)
);

const getTranslationMorphed = createSelector(
    getTranslation,
    t => f => compose(f, t)
);

const getTranslationUpperCased = createSelector(
    getTranslationMorphed,
    m => m(toUpper)
);

const getTranslationCapitalized = createSelector(
    getTranslationMorphed,
    m => m(capitalize)
);

const getTranslationTitleized = createSelector(
    getTranslationMorphed,
    m => m(titleize)
);

const createGetP = (polyglotOptions) => {
    const options = { polyglotOptions };
    const getP = createSelector(
        getLocale,
        getPhrases,
        getPolyglot,
        getTranslation,
        getTranslationCapitalized,
        getTranslationTitleized,
        getTranslationUpperCased,
        getTranslationMorphed,
        (locale, phrases, p, t, tc, tt, tu, tm) => {
            if (!locale || !phrases) {
                return {
                    t: identity,
                    tc: identity,
                    tt: identity,
                    tu: identity,
                    tm: identity,
                };
            }
            return {
                ...p,
                t,
                tc,
                tt,
                tu,
                tm,
            };
        },
    );
    return (state, props) => getP(state, { ...props, ...options });
};

const getP = createGetP();

export { getP, getLocale, createGetP };
<|endoftext|>