<commit_before>/*
 * Copyright (c) $year, Den Norske Turistforening (DNT)
 *
 * https://github.com/Turistforeningen/turadmin
 */

var sentry = require('../lib/sentry');

module.exports = function (app, options) {
    "use strict";

    var underscore = require('underscore');
    var userGroupsFetcher = options.userGroupsFetcher;
    var restProxy = options.restProxy;
    var NodeCache = require('node-cache');
    var cache = new NodeCache();
    var TurbasenAuth = require('turbasen-auth');

    var turbasenAuthClient = new TurbasenAuth('Turadmin', process.env.NTB_API_KEY, {env: process.env.NTB_API_ENV || 'dev'});

    /*
     * All GET requests to /grupper
     */
    var getGroupsAll = function (req, res, next) {

        if (req.session.user.er_admin) {
            req.renderOptions = req.renderOptions || {};
            req.renderOptions.userData = JSON.stringify(req.session.user);
            req.renderOptions.userGroups = JSON.stringify(req.userGroups || []);
            req.renderOptions.routeApiUri = options.routeApiUri;
            req.renderOptions.authType = req.session.authType;
            req.renderOptions.isAdmin = req.session.user.er_admin;
            next();

        } else {
            res.redirect(401, '/turer');
        }

    };

    /**
     * GET list of groups (index page)
     */
    var getGroupsIndex = function (req, res, next) {

        var userGroups = req.userGroups || [];
        var userDefaultGroupFetchQuery = (!!req.signedCookies && req.signedCookies['userDefaultGroupFetchQuery_' + req.session.userId]) ? req.signedCookies['userDefaultGroupFetchQuery_' + req.session.userId] : {};

        var groups;
        var onCompleteGrupperRequest = function (data) {
            // cache.set('/grupper/?tags=!&limit=200&fields=navn&sort=navn', data, 86400);
            groups = data.documents;
            onCompleteNtbRequest();
        };

        var onCompleteNtbRequest = underscore.after(1, function () {
            var renderOptions = {
                title: 'Mine grupper',
                userData: JSON.stringify(req.session.user),
                userGroups: JSON.stringify(userGroups),
                externalGroups: JSON.stringify(groups),
                authType: req.session.authType,
                itemType: 'grupper',
                isAdmin: req.session.user.er_admin
            };

            res.render('groups/index', renderOptions);
        });

        restProxy.makeApiRequest('/grupper/?tags=!DNT&limit=200&fields=navn&sort=navn', req, undefined, onCompleteGrupperRequest);

    };

    var getGroupsNew = function (req, res, next) {
        req.renderOptions = req.renderOptions || {};
        req.renderOptions.title = 'Ny gruppe';
        res.render('groups/editor', req.renderOptions);
    };

    var getGroupsEdit = function (req, res, next) {
        // Id of group being edited
        var groupId = req.params.id;

        // Callback for when group data is fetched from NTB
        var onCompleteGroupRequest = function (data) {

            var groupData = data;

            if ((typeof groupData.tags === 'undefined') || (groupData.tags.indexOf('DNT') === -1)) {

                req.renderOptions = req.renderOptions || {};
                req.renderOptions.title = groupData.navn;
                req.renderOptions.groupName = groupData.navn;
                req.renderOptions.groupData = JSON.stringify(groupData);

                res.render('groups/editor', req.renderOptions);

            } else {
                res.redirect(403, '/grupper');
            }

        };

        restProxy.makeApiRequest('/grupper/' + groupId, req, undefined, onCompleteGroupRequest);
    };

    var deleteGroups = function (req, res, next) {
        restProxy.makeApiRequest('/grupper/' + req.params.id, req, res, undefined);
    };

    var postPutGroups = function (req, res, next) {
        var group = req.body;
        var users = group && group.privat && group.privat.brukere || [];
        var uri = '/grupper';
        uri += (!!req.params.id) ? '/' + req.params.id : '';

        var saveGroup = function () {
            restProxy.makeApiRequest(uri, req, res, undefined);
        };

        var passwordIsPbkdf2 = underscore.after(users.length, function () {
            saveGroup();
        });

        var userAuthCreated = function (err, user) {
            if (err) {
                sentry.captureError(err, {extra: {query: req.query}});

            } else {
                var userIndex = users.indexOf(underscore.findWhere(users, {epost: user.epost}));
                users[userIndex] = user;
                passwordIsPbkdf2();
            }
        };

        if (users && users.length > 0) {

            for (var i = 0, user; i < users.length; i++) {
                user = users[i];

                // If new password is set for any of the users, generate pbkdf2
                if (user.passord) {
                    turbasenAuthClient.createUserAuth(user.navn, user.epost, user.passord, userAuthCreated);

                } else {
                    passwordIsPbkdf2();
                }
            }

        } else {
            saveGroup();
        }

    };

    app.get('/grupper*', userGroupsFetcher);
    app.get('/grupper*', getGroupsAll);
    app.get('/grupper', getGroupsIndex);
    app.get('/grupper/ny', getGroupsNew);
    app.get('/grupper/:id', getGroupsEdit);

    app.post('/ntb-api/grupper', postPutGroups);
    app.put('/ntb-api/grupper/:id', postPutGroups);
    app.delete('/ntb-api/grupper/:id', deleteGroups);
};
<commit_msg>Allow editing groups with tag Hytte<commit_after>/*
 * Copyright (c) $year, Den Norske Turistforening (DNT)
 *
 * https://github.com/Turistforeningen/turadmin
 */

var sentry = require('../lib/sentry');

module.exports = function (app, options) {
    "use strict";

    var underscore = require('underscore');
    var userGroupsFetcher = options.userGroupsFetcher;
    var restProxy = options.restProxy;
    var NodeCache = require('node-cache');
    var cache = new NodeCache();
    var TurbasenAuth = require('turbasen-auth');

    var turbasenAuthClient = new TurbasenAuth('Turadmin', process.env.NTB_API_KEY, {env: process.env.NTB_API_ENV || 'dev'});

    /*
     * All GET requests to /grupper
     */
    var getGroupsAll = function (req, res, next) {

        if (req.session.user.er_admin) {
            req.renderOptions = req.renderOptions || {};
            req.renderOptions.userData = JSON.stringify(req.session.user);
            req.renderOptions.userGroups = JSON.stringify(req.userGroups || []);
            req.renderOptions.routeApiUri = options.routeApiUri;
            req.renderOptions.authType = req.session.authType;
            req.renderOptions.isAdmin = req.session.user.er_admin;
            next();

        } else {
            res.redirect(401, '/turer');
        }

    };

    /**
     * GET list of groups (index page)
     */
    var getGroupsIndex = function (req, res, next) {

        var userGroups = req.userGroups || [];
        var userDefaultGroupFetchQuery = (!!req.signedCookies && req.signedCookies['userDefaultGroupFetchQuery_' + req.session.userId]) ? req.signedCookies['userDefaultGroupFetchQuery_' + req.session.userId] : {};

        var groups;
        var onCompleteGrupperRequest = function (data) {
            // cache.set('/grupper/?tags=!&limit=200&fields=navn&sort=navn', data, 86400);
            groups = data.documents;
            onCompleteNtbRequest();
        };

        var onCompleteNtbRequest = underscore.after(1, function () {
            var renderOptions = {
                title: 'Mine grupper',
                userData: JSON.stringify(req.session.user),
                userGroups: JSON.stringify(userGroups),
                externalGroups: JSON.stringify(groups),
                authType: req.session.authType,
                itemType: 'grupper',
                isAdmin: req.session.user.er_admin
            };

            res.render('groups/index', renderOptions);
        });

        restProxy.makeApiRequest('/grupper/?tags=!DNT&limit=200&fields=navn&sort=navn', req, undefined, onCompleteGrupperRequest);

    };

    var getGroupsNew = function (req, res, next) {
        req.renderOptions = req.renderOptions || {};
        req.renderOptions.title = 'Ny gruppe';
        res.render('groups/editor', req.renderOptions);
    };

    var getGroupsEdit = function (req, res, next) {
        // Id of group being edited
        var groupId = req.params.id;

        // Callback for when group data is fetched from NTB
        var onCompleteGroupRequest = function (data) {

            var groupData = data;

            if ((typeof groupData.tags === 'undefined') || (groupData.tags.indexOf('Hytte') > -1) || (groupData.tags.indexOf('DNT') === -1)) {

                req.renderOptions = req.renderOptions || {};
                req.renderOptions.title = groupData.navn;
                req.renderOptions.groupName = groupData.navn;
                req.renderOptions.groupData = JSON.stringify(groupData);

                res.render('groups/editor', req.renderOptions);

            } else {
                res.redirect(403, '/grupper');
            }

        };

        restProxy.makeApiRequest('/grupper/' + groupId, req, undefined, onCompleteGroupRequest);
    };

    var deleteGroups = function (req, res, next) {
        restProxy.makeApiRequest('/grupper/' + req.params.id, req, res, undefined);
    };

    var postPutGroups = function (req, res, next) {
        var group = req.body;
        var users = group && group.privat && group.privat.brukere || [];
        var uri = '/grupper';
        uri += (!!req.params.id) ? '/' + req.params.id : '';

        var saveGroup = function () {
            restProxy.makeApiRequest(uri, req, res, undefined);
        };

        var passwordIsPbkdf2 = underscore.after(users.length, function () {
            saveGroup();
        });

        var userAuthCreated = function (err, user) {
            if (err) {
                sentry.captureError(err, {extra: {query: req.query}});

            } else {
                var userIndex = users.indexOf(underscore.findWhere(users, {epost: user.epost}));
                users[userIndex] = user;
                passwordIsPbkdf2();
            }
        };

        if (users && users.length > 0) {

            for (var i = 0, user; i < users.length; i++) {
                user = users[i];

                // If new password is set for any of the users, generate pbkdf2
                if (user.passord) {
                    turbasenAuthClient.createUserAuth(user.navn, user.epost, user.passord, userAuthCreated);

                } else {
                    passwordIsPbkdf2();
                }
            }

        } else {
            saveGroup();
        }

    };

    app.get('/grupper*', userGroupsFetcher);
    app.get('/grupper*', getGroupsAll);
    app.get('/grupper', getGroupsIndex);
    app.get('/grupper/ny', getGroupsNew);
    app.get('/grupper/:id', getGroupsEdit);

    app.post('/ntb-api/grupper', postPutGroups);
    app.put('/ntb-api/grupper/:id', postPutGroups);
    app.delete('/ntb-api/grupper/:id', deleteGroups);
};
<|endoftext|>


<commit_before>var http = require('http'),
    https = require('https'),
    querystring = require('querystring'),
    xml2js = require('xml2js');

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

    var directoryOptions = {
        host: 'directory.ucsf.edu',
        port: 80
    };

    var dataNeedsCleaning = true;

    var protocol = http;

    //TODO: document id option at developer.ucsf.edu
    if ('id' in req.query) {
        directoryOptions.path = '/mobile_people_detail.jsp?' + querystring.stringify({'FNO': req.query.id});
    } else if (req.query.first_name || req.query.last_name || req.query.dep_name) {
        directoryOptions.path = '/mobile_people_result_set.jsp?' + querystring.stringify(req.query);
    } else if (req.query.q) {
        directoryOptions.host = 'myaccess2.ucsf.edu';
        directoryOptions.port = 443;
        directoryOptions.path = '/directory/?json&' + querystring.stringify({q: req.query.q});
        protocol = https;
        dataNeedsCleaning = false;
    } else {
        res.send({data: []});
        return;
    }

    protocol.get(directoryOptions, function (resp) {
        var rawData = '';

        function callback(result) {
            function deGoober(name, data, stringify) {
                var arrayInstance = [].constructor,
                    value = data.hasOwnProperty(name) ? data[name] : '';
                // Sometimes, the string is inexplicably buried in an array.
                if ((stringify) && (value instanceof arrayInstance)) {
                    return value[0];
                }
                return value;
            }

            function amassPhones(data) {
                var rv = {},
                    thisPhone,
                    phones = [
                        ['telephoneNumber', 'main'],
                        ['telephoneNumber2', 'alternate'],
                        ['privatePracticePhone', 'privatePractice'],
                        ['mobile', 'mobile'],
                        ['pager', 'pager']
                    ];
                for (var i = 0; i < phones.length; i++) {
                    thisPhone = deGoober(phones[i][0], data, true);
                    // *sigh* Don't send back empty objects and strings inside the array
                    if ((typeof thisPhone === 'object') || (thisPhone === '')) {
                        rv[phones[i][1]] = [];
                    } else {
                        // *sigh* part 2: Arrays should be able to have multiple values.
                        rv[phones[i][1]] = [thisPhone];
                    }
                }
                return rv;
            }

            // <facepalm>
            var results = [];
            if (result.hasOwnProperty('results') && result.results.hasOwnProperty('result')) {
                results = result.results.result;
            }
            // </facepalm>

            // *Sigh*. As much as I'd love to just send everything as is,
            // too much crap XML means too much badly formatted stuff sent back. Let's
            // declare a bunch of variables, loop through, and try to clean up some of it.

            var rv = [];
            var degreeFilterCallback = function (el) { return typeof el === 'string'; };
            for (var i = 0; i < results.length; i++) {
                rv[i] = {};
                rv[i].name = deGoober('displayName', results[i], true);
                if (Array.isArray(results[i].degrees) && results[i].degrees[0] && Array.isArray(results[i].degrees[0].degree)) {
                    rv[i].degrees = results[i].degrees[0].degree.filter(degreeFilterCallback);
                }
                rv[i].department = deGoober('department', results[i], false);
                rv[i].email = deGoober('mail', results[i], false);
                rv[i].title = deGoober('workingTitle', results[i], false);
                rv[i].campusBox = deGoober('campusBox', results[i], false);
                rv[i].address = deGoober('postalAddress', results[i], false);
                for (var j = 0; j < rv[i].address.length; j++) {
                    rv[i].address[j] = rv[i].address[j].replace(/\$/g, '\n');
                }
                rv[i].id = deGoober('key', results[i], true);
                if ((rv[i].id === '') && (req.query.hasOwnProperty('id'))) {
                    rv[i].id = req.query.id;
                }

                rv[i].phones = amassPhones(results[i]);

                // Failing to capitalize the Chancellor's name correctly is embarrassing. Sad hack to fix it.
                rv[i].name.replace('Desmond-hellman', 'Desmond-Hellman');
            }

            res.send({data: rv});
        }

        resp.on('data', function (chunk) {
            rawData += chunk;
        });
        resp.on('end', function () {
            if (dataNeedsCleaning) {
                var parser = new xml2js.Parser();
                parser.on('end', callback);
                parser.on('error', function (err) {
                    console.dir(err);
                });
                parser.parseString(rawData);
            } else {
                // Harumph, still needs some minor cleaning.
                // Hopefully Elliot fixes this soon and I can remove it.
                var cookedData = JSON.parse(rawData);

                var convertToString = function (input) {
                    if (input instanceof Array) {
                        return input[0];
                    }
                    return input;
                };

                if (cookedData.data && cookedData.data instanceof Array) {
                    for (var i = 0, l = cookedData.len; i < l; i++) {
                        cookedData.data[i].displayname = convertToString(cookedData.data[i].displayname);
                        cookedData.data[i].ucsfeduprimarydepartmentname = convertToString(cookedData.data[i].ucsfeduprimarydepartmentname);
                    }
                }

                // In an ideal world, this is all we'd need.
                res.send(cookedData);
            }
        });
    }).on('error', function (e) {
        console.log('Directory error: ' + e.message);
        res.send({error: e.message});
    });
};<commit_msg>fix condition<commit_after>var http = require('http'),
    https = require('https'),
    querystring = require('querystring'),
    xml2js = require('xml2js');

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

    var directoryOptions = {
        host: 'directory.ucsf.edu',
        port: 80
    };

    var dataNeedsCleaning = true;

    var protocol = http;

    //TODO: document id option at developer.ucsf.edu
    if ('id' in req.query) {
        directoryOptions.path = '/mobile_people_detail.jsp?' + querystring.stringify({'FNO': req.query.id});
    } else if (req.query.first_name || req.query.last_name || req.query.dep_name) {
        directoryOptions.path = '/mobile_people_result_set.jsp?' + querystring.stringify(req.query);
    } else if (req.query.q) {
        directoryOptions.host = 'myaccess2.ucsf.edu';
        directoryOptions.port = 443;
        directoryOptions.path = '/directory/?json&' + querystring.stringify({q: req.query.q});
        protocol = https;
        dataNeedsCleaning = false;
    } else {
        res.send({data: []});
        return;
    }

    protocol.get(directoryOptions, function (resp) {
        var rawData = '';

        function callback(result) {
            function deGoober(name, data, stringify) {
                var arrayInstance = [].constructor,
                    value = data.hasOwnProperty(name) ? data[name] : '';
                // Sometimes, the string is inexplicably buried in an array.
                if ((stringify) && (value instanceof arrayInstance)) {
                    return value[0];
                }
                return value;
            }

            function amassPhones(data) {
                var rv = {},
                    thisPhone,
                    phones = [
                        ['telephoneNumber', 'main'],
                        ['telephoneNumber2', 'alternate'],
                        ['privatePracticePhone', 'privatePractice'],
                        ['mobile', 'mobile'],
                        ['pager', 'pager']
                    ];
                for (var i = 0; i < phones.length; i++) {
                    thisPhone = deGoober(phones[i][0], data, true);
                    // *sigh* Don't send back empty objects and strings inside the array
                    if ((typeof thisPhone === 'object') || (thisPhone === '')) {
                        rv[phones[i][1]] = [];
                    } else {
                        // *sigh* part 2: Arrays should be able to have multiple values.
                        rv[phones[i][1]] = [thisPhone];
                    }
                }
                return rv;
            }

            // <facepalm>
            var results = [];
            if (result.hasOwnProperty('results') && result.results.hasOwnProperty('result')) {
                results = result.results.result;
            }
            // </facepalm>

            // *Sigh*. As much as I'd love to just send everything as is,
            // too much crap XML means too much badly formatted stuff sent back. Let's
            // declare a bunch of variables, loop through, and try to clean up some of it.

            var rv = [];
            var degreeFilterCallback = function (el) { return typeof el === 'string'; };
            for (var i = 0; i < results.length; i++) {
                rv[i] = {};
                rv[i].name = deGoober('displayName', results[i], true);
                if (Array.isArray(results[i].degrees) && results[i].degrees[0] && Array.isArray(results[i].degrees[0].degree)) {
                    rv[i].degrees = results[i].degrees[0].degree.filter(degreeFilterCallback);
                }
                rv[i].department = deGoober('department', results[i], false);
                rv[i].email = deGoober('mail', results[i], false);
                rv[i].title = deGoober('workingTitle', results[i], false);
                rv[i].campusBox = deGoober('campusBox', results[i], false);
                rv[i].address = deGoober('postalAddress', results[i], false);
                for (var j = 0; j < rv[i].address.length; j++) {
                    rv[i].address[j] = rv[i].address[j].replace(/\$/g, '\n');
                }
                rv[i].id = deGoober('key', results[i], true);
                if ((rv[i].id === '') && (req.query.hasOwnProperty('id'))) {
                    rv[i].id = req.query.id;
                }

                rv[i].phones = amassPhones(results[i]);

                // Failing to capitalize the Chancellor's name correctly is embarrassing. Sad hack to fix it.
                rv[i].name.replace('Desmond-hellman', 'Desmond-Hellman');
            }

            res.send({data: rv});
        }

        resp.on('data', function (chunk) {
            rawData += chunk;
        });
        resp.on('end', function () {
            if (dataNeedsCleaning) {
                var parser = new xml2js.Parser();
                parser.on('end', callback);
                parser.on('error', function (err) {
                    console.dir(err);
                });
                parser.parseString(rawData);
            } else {
                // Harumph, still needs some minor cleaning.
                // Hopefully Elliot fixes this soon and I can remove it.
                var cookedData = JSON.parse(rawData);

                var convertToString = function (input) {
                    if (input instanceof Array) {
                        return input[0];
                    }
                    return input;
                };

                if (cookedData.data && cookedData.data instanceof Array) {
                    for (var i = 0, l = cookedData.data.len; i < l; i++) {
                        cookedData.data[i].displayname = convertToString(cookedData.data[i].displayname);
                        cookedData.data[i].ucsfeduprimarydepartmentname = convertToString(cookedData.data[i].ucsfeduprimarydepartmentname);
                    }
                }

                // In an ideal world, this is all we'd need.
                res.send(cookedData);
            }
        });
    }).on('error', function (e) {
        console.log('Directory error: ' + e.message);
        res.send({error: e.message});
    });
};<|endoftext|>


<commit_before>
// Copyright (C) 2016 Louis de Charsonville
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License version 3 as
// published by the Free Software Foundation.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

var assert = require('assert'),
    concat = require('concat-stream'),
    request = require('request'),
    cheerio = require('cheerio'),
    iconv = require('iconv-lite'),
    ical = require('ical-generator'),
    moment = require('moment-timezone'),
    forms = require('forms'),
    http = require('http'),
    https = require('https');

function buildHMTL(arr,name) {

    var header = '<title>SDMX API for EViews / '+ name +'</title>';
    var body = '';
    var table ='';
    var theader1 = 'Dates	'+name+'	';
    var tbody = '';

    arr.forEach(function(it,ind) {
        tbody += '
'+it[0]+'	'+it[1]+'
';
    });

    var myHtml = '<!DOCTYPE html>' + '' + header + '' + '
' + '
'  + '
' + theader1 + '

' + '
' + tbody + '
'  +'
' + '';
    return myHtml;

}

exports.getSeries = function(req,res) {

    var arrSeries = req.params.series.split('+');
    var series = req.params.series;
    var dataset = req.params.dataset;
    var apiKey = req.params.apiKey;

    if (dataset === "ICE") {

        arrSeries.forEach(function(it,ind) {
            var myPath = '/api/v3/datasets/'+ dataset + '/' + it + '.json?api_key'+apiKey;
            var options = {
                hostname: 'www.quandl.com',
                port: 443,
                path: myPath,
                headers: {
                    'connection': 'keep-alive'
                }
            };

            https.get(options, function(result) {
                if (result.statusCode >=200 && result.statusCode < 400) {
                    var xml = '';
                    result.on('data', function(chunk) {
                        xml += chunk;
                    });
                    result.on('end',function() {
                        var json = JSON.parse(xml);
                        var nameSeries = json.dataset.column_names[4];
                        var mySeries = [];
                        json.dataset.data.forEach(function(item,indice) {
                            mySeries.push([item[0],item[4]]);
                        });
                        res.send(buildHMTL(mySeries.reverse(),nameSeries));
                    });
                } else {
                    var e = "Error: "+result.statusCode;
                    res.send(e);
                };
            });
        });
     } else {
        res.send('Not yet supported');
     }
};

<commit_msg>send headers if error<commit_after>
// Copyright (C) 2016 Louis de Charsonville
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License version 3 as
// published by the Free Software Foundation.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

var assert = require('assert'),
    concat = require('concat-stream'),
    request = require('request'),
    cheerio = require('cheerio'),
    iconv = require('iconv-lite'),
    ical = require('ical-generator'),
    moment = require('moment-timezone'),
    forms = require('forms'),
    http = require('http'),
    https = require('https');

function buildHMTL(arr,name) {

    var header = '<title>SDMX API for EViews / '+ name +'</title>';
    var body = '';
    var table ='';
    var theader1 = 'Dates	'+name+'	';
    var tbody = '';

    arr.forEach(function(it,ind) {
        tbody += '
'+it[0]+'	'+it[1]+'
';
    });

    var myHtml = '<!DOCTYPE html>' + '' + header + '' + '
' + '
'  + '
' + theader1 + '

' + '
' + tbody + '
'  +'
' + '';
    return myHtml;

}

exports.getSeries = function(req,res) {

    var arrSeries = req.params.series.split('+');
    var series = req.params.series;
    var dataset = req.params.dataset;
    var apiKey = req.params.apiKey;

    if (dataset === "ICE") {

        arrSeries.forEach(function(it,ind) {
            var myPath = '/api/v3/datasets/'+ dataset + '/' + it + '.json?api_key'+apiKey;
            var options = {
                hostname: 'www.quandl.com',
                port: 443,
                path: myPath,
                headers: {
                    'connection': 'keep-alive'
                }
            };

            https.get(options, function(result) {
                if (result.statusCode >=200 && result.statusCode < 400) {
                    var xml = '';
                    result.on('data', function(chunk) {
                        xml += chunk;
                    });
                    result.on('end',function() {
                        var json = JSON.parse(xml);
                        var nameSeries = json.dataset.column_names[4];
                        var mySeries = [];
                        json.dataset.data.forEach(function(item,indice) {
                            mySeries.push([item[0],item[4]]);
                        });
                        res.send(buildHMTL(mySeries.reverse(),nameSeries));
                    });
                } else {
                    var e = "Error: "+result.statusCode + ' | Headers :'+req.headers;
                    res.send(e);
                };
            });
        });
     } else {
        res.send('Not yet supported');
     }
};

<|endoftext|>


<commit_before>import { Router } from 'express';
import Quote from '../models/quote';
import Tag from '../models/tag';
import scopify from '../helpers/scopify';
import { needs, needsApprovedIndex, needsApprovedOne } from '../middleware/permissions';
import verifyUser from '../middleware/verify-user';
import paginate from '../middleware/paginate';
import Promise from 'bluebird';

const router = Router(); // eslint-disable-line new-cap

router
  .route('/')
    .get(verifyUser, paginate, needsApprovedIndex('quotes'), (req, res, next) => {
      const scopes = scopify(req.query, 'body', 'tag', 'search', 'approved');
      Quote
        .scope(scopes)
        .findAndCountAll({
          order: [['id', 'DESC']],
        })
        .then(result => {
          const count = typeof result.count !== 'number' ? result.count.length : result.count;
          return [count, Promise.map(result.rows, quote => quote.reload({ include: [{ model: Tag, attributes: ['name'] }] }))];
        })
        .spread((count, quotes) => {
          res.send({
            total: count,
            perPage: req.query.perPage,
            currentPage: req.query.page,
            data: quotes,
          });
        })
        .catch(err => next(err));
    })
    .post((req, res, next) => {
      req.body.tags = req.body.tags || [];
      Quote.create(req.body, { fields: ['body', 'description'] })
        .then(quote => {
          const arr = [quote];
          for (const tag of req.body.tags) {
            arr.push(Tag.findOrCreate({ where: { name: tag } }));
          }
          return arr;
        })
        .spread((quote, ...tags) => [quote, quote.setTags(tags.map(tag => tag[0]))])
        .spread(quote => quote.reload({ include: [Tag] }))
        .then(quote => res.status(201).send(quote))
        .catch(err => {
          err.status = 422;
          next(err);
        });
    });

router
  .route('/:id')
    .get(verifyUser, needsApprovedOne('quotes'), (req, res, next) => {
      Quote
        .findById(req.params.id, {
          include: [Tag],
        })
        .then(quote => {
          if (quote) {
            if (!quote.approved && !req.auth.allowed) {
              return next({
                message: 'User does not have permission: unapproved quotes',
                status: 403,
              });
            }
            return res.send(quote);
          }
          return Promise.reject({ message: 'Quote not found', status: 404 });
        })
        .catch(err => next(err));
    })
    .put(needs('quotes', 'update'), (req, res, next) => {
      req.body.tags = req.body.tags || [];
      Quote
        .findById(req.params.id, {
          include: [Tag],
        })
        .then(quote => {
          if (quote) {
            return quote.updateAttributes(req.body, {
              fields: ['body', 'description', 'approved'],
            });
          }
          return Promise.reject({ message: 'Quote not found', status: 404 });

        })
        .then(quote => {
          const arr = [quote];
          for (const tag of req.body.tags) {
            arr.push(Tag.findOrCreate({ where: { name: tag } }));
          }
          return arr;
        })
        .spread((quote, ...tags) => [quote, quote.setTags(tags.map(tag => tag[0]))])
        .spread(quote => quote.reload({ include: [Tag] }))
        .then(quote => res.send(quote))
        .catch(err => next(err));
    })
    .delete(needs('quotes', 'destroy'), (req, res, next) => {
      Quote
        .findById(req.params.id)
        .then(quote => {
          if (quote) {
            return quote.destroy();
          }
          return Promise.reject({ message: 'Quote not found', status: 404 });
        })
        .then(quote => res.send(quote))
        .catch(err => next(err));
    });

export default router;
<commit_msg>Make sure tags stay when quotes are approved<commit_after>import { Router } from 'express';
import Quote from '../models/quote';
import Tag from '../models/tag';
import scopify from '../helpers/scopify';
import { needs, needsApprovedIndex, needsApprovedOne } from '../middleware/permissions';
import verifyUser from '../middleware/verify-user';
import paginate from '../middleware/paginate';
import Promise from 'bluebird';

const router = Router(); // eslint-disable-line new-cap

router
  .route('/')
    .get(verifyUser, paginate, needsApprovedIndex('quotes'), (req, res, next) => {
      const scopes = scopify(req.query, 'body', 'tag', 'search', 'approved');
      Quote
        .scope(scopes)
        .findAndCountAll({
          order: [['id', 'DESC']],
        })
        .then(result => {
          const count = typeof result.count !== 'number' ? result.count.length : result.count;
          return [count, Promise.map(result.rows, quote => quote.reload({ include: [{ model: Tag, attributes: ['name'] }] }))];
        })
        .spread((count, quotes) => {
          res.send({
            total: count,
            perPage: req.query.perPage,
            currentPage: req.query.page,
            data: quotes,
          });
        })
        .catch(err => next(err));
    })
    .post((req, res, next) => {
      req.body.tags = req.body.tags || [];
      Quote.create(req.body, { fields: ['body', 'description'] })
        .then(quote => {
          const arr = [quote];
          for (const tag of req.body.tags) {
            arr.push(Tag.findOrCreate({ where: { name: tag } }));
          }
          return arr;
        })
        .spread((quote, ...tags) => [quote, quote.setTags(tags.map(tag => tag[0]))])
        .spread(quote => quote.reload({ include: [Tag] }))
        .then(quote => res.status(201).send(quote))
        .catch(err => {
          err.status = 422;
          next(err);
        });
    });

router
  .route('/:id')
    .get(verifyUser, needsApprovedOne('quotes'), (req, res, next) => {
      Quote
        .findById(req.params.id, {
          include: [Tag],
        })
        .then(quote => {
          if (quote) {
            if (!quote.approved && !req.auth.allowed) {
              return next({
                message: 'User does not have permission: unapproved quotes',
                status: 403,
              });
            }
            return res.send(quote);
          }
          return Promise.reject({ message: 'Quote not found', status: 404 });
        })
        .catch(err => next(err));
    })
    .put(needs('quotes', 'update'), (req, res, next) => {
      req.body.tags = req.body.tags || [];
      Quote
        .findById(req.params.id, {
          include: [Tag],
        })
        .then(quote => {
          if (quote) {
            return quote.updateAttributes(req.body, {
              fields: ['body', 'description', 'approved'],
            });
          }
          return Promise.reject({ message: 'Quote not found', status: 404 });

        })
        .then(quote => {
          const arr = [quote];
          for (const tag of req.body.tags) {
            arr.push(Tag.findOrCreate({ where: { name: tag } }));
          }
          return arr;
        })
        .spread((quote, ...tags) => {
          if (tags.length !== 0) {
            return [quote, quote.setTags(tags.map(tag => tag[0]))];
          }
          return [quote];
        })
        .spread(quote => quote.reload({ include: [Tag] }))
        .then(quote => res.send(quote))
        .catch(err => next(err));
    })
    .delete(needs('quotes', 'destroy'), (req, res, next) => {
      Quote
        .findById(req.params.id)
        .then(quote => {
          if (quote) {
            return quote.destroy();
          }
          return Promise.reject({ message: 'Quote not found', status: 404 });
        })
        .then(quote => res.send(quote))
        .catch(err => next(err));
    });

export default router;
<|endoftext|>


<commit_before>/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
'use strict';

const child_process = require('child_process');
const fs = require('fs');
const path = require('path');
const findXcodeProject = require('./findXcodeProject');
const findReactNativeScripts = require('../util/findReactNativeScripts');
const parseIOSDevicesList = require('./parseIOSDevicesList');
const findMatchingSimulator = require('./findMatchingSimulator');
const getBuildPath = function (configuration = 'Debug', appName, isDevice) {
  let device;

  if (isDevice) {
    device = 'iphoneos';
  } else if (appName.toLowerCase().includes('tvos')) {
    device = 'appletvsimulator';
  } else {
    device = 'iphonesimulator';
  }

  return `build/Build/Products/${configuration}-${device}/${appName}.app`;
};
const xcprettyAvailable = function() {
  try {
    child_process.execSync('xcpretty --version', {
      stdio: [ 0, 'pipe', 'ignore', ]
    });
  } catch (error) {
    return false;
  }
  return true;
};

function runIOS(argv, config, args) {
  if (!fs.existsSync(args.projectPath)) {
    const reactNativeScriptsPath = findReactNativeScripts();
    if (reactNativeScriptsPath) {
      child_process.spawnSync(
        reactNativeScriptsPath,
        ['ios'].concat(process.argv.slice(1)),
        {stdio: 'inherit'}
      );
      return;
    } else {
      throw new Error('iOS project folder not found. Are you sure this is a React Native project?');
    }
  }
  process.chdir(args.projectPath);
  const xcodeProject = findXcodeProject(fs.readdirSync('.'));
  if (!xcodeProject) {
    throw new Error('Could not find Xcode project files in ios folder');
  }

  const inferredSchemeName = path.basename(xcodeProject.name, path.extname(xcodeProject.name));
  const scheme = args.scheme || inferredSchemeName;
  console.log(`Found Xcode ${xcodeProject.isWorkspace ? 'workspace' : 'project'} ${xcodeProject.name}`);
  const devices = parseIOSDevicesList(
    child_process.execFileSync('xcrun', ['instruments', '-s'], {encoding: 'utf8'})
  );
  if (args.device) {
    const selectedDevice = matchingDevice(devices, args.device);
    if (selectedDevice) {
      return runOnDevice(selectedDevice, scheme, xcodeProject, args.configuration, args.packager, args.verbose);
    } else {
      if (devices && devices.length > 0) {
        console.log('Could not find device with the name: "' + args.device + '".');
        console.log('Choose one of the following:');
        printFoundDevices(devices);
      } else {
        console.log('No iOS devices connected.');
      }
    }
  } else if (args.udid) {
    return runOnDeviceByUdid(args, scheme, xcodeProject, devices);
  } else {
    return runOnSimulator(xcodeProject, args, scheme);
  }
}

function runOnDeviceByUdid(args, scheme, xcodeProject, devices) {
  const selectedDevice = matchingDeviceByUdid(devices, args.udid);
  if (selectedDevice) {
    return runOnDevice(selectedDevice, scheme, xcodeProject, args.configuration, args.packager, args.verbose, args.port);
  } else {
    if (devices && devices.length > 0) {
      console.log('Could not find device with the udid: "' + args.udid + '".');
      console.log('Choose one of the following:');
      printFoundDevices(devices);
    } else {
      console.log('No iOS devices connected.');
    }
  }
}

function runOnSimulator(xcodeProject, args, scheme) {
  return new Promise((resolve) => {
    try {
      var simulators = JSON.parse(
      child_process.execFileSync('xcrun', ['simctl', 'list', '--json', 'devices'], {encoding: 'utf8'})
      );
    } catch (e) {
      throw new Error('Could not parse the simulator list output');
    }

    const selectedSimulator = findMatchingSimulator(simulators, args.simulator);
    if (!selectedSimulator) {
      throw new Error(`Could not find ${args.simulator} simulator`);
    }

    const simulatorFullName = formattedDeviceName(selectedSimulator);
    console.log(`Launching ${simulatorFullName}...`);
    try {
      child_process.spawnSync('xcrun', ['instruments', '-w', selectedSimulator.udid]);
    } catch (e) {
      // instruments always fail with 255 because it expects more arguments,
      // but we want it to only launch the simulator
    }
    resolve(selectedSimulator.udid);
  })
  .then((udid) => buildProject(xcodeProject, udid, scheme, args.configuration, args.packager, args.verbose, args.port))
  .then((appName) => {
    if (!appName) {
      appName = scheme;
    }
    let appPath = getBuildPath(args.configuration, appName);
    console.log(`Installing ${appPath}`);
    child_process.spawnSync('xcrun', ['simctl', 'install', 'booted', appPath], {stdio: 'inherit'});

    const bundleID = child_process.execFileSync(
      '/usr/libexec/PlistBuddy',
      ['-c', 'Print:CFBundleIdentifier', path.join(appPath, 'Info.plist')],
      {encoding: 'utf8'}
    ).trim();

    console.log(`Launching ${bundleID}`);
    child_process.spawnSync('xcrun', ['simctl', 'launch', 'booted', bundleID], {stdio: 'inherit'});
  });
}

function runOnDevice(selectedDevice, scheme, xcodeProject, configuration, launchPackager, verbose, port) {
  return buildProject(xcodeProject, selectedDevice.udid, scheme, configuration, launchPackager, verbose, port)
  .then((appName) => {
    if (!appName) {
      appName = scheme;
    }
    const iosDeployInstallArgs = [
      '--bundle', getBuildPath(configuration, appName, true),
      '--id' , selectedDevice.udid,
      '--justlaunch'
    ];
    console.log(`installing and launching your app on ${selectedDevice.name}...`);
    const iosDeployOutput = child_process.spawnSync('ios-deploy', iosDeployInstallArgs, {encoding: 'utf8'});
    if (iosDeployOutput.error) {
      console.log('');
      console.log('** INSTALLATION FAILED **');
      console.log('Make sure you have ios-deploy installed globally.');
      console.log('(e.g "npm install -g ios-deploy")');
    } else {
      console.log('** INSTALLATION SUCCEEDED **');
    }
  });
}

function buildProject(xcodeProject, udid, scheme, configuration = 'Debug', launchPackager = false, verbose, port) {
  return new Promise((resolve,reject) =>
  {
     var xcodebuildArgs = [
      xcodeProject.isWorkspace ? '-workspace' : '-project', xcodeProject.name,
      '-configuration', configuration,
      '-scheme', scheme,
      '-destination', `id=${udid}`,
      '-derivedDataPath', 'build',
    ];
    console.log(`Building using "xcodebuild ${xcodebuildArgs.join(' ')}"`);
    let xcpretty;
    if (!verbose) {
      xcpretty = xcprettyAvailable() && child_process.spawn('xcpretty', [], { stdio: ['pipe', process.stdout, process.stderr] });
    }
    const buildProcess = child_process.spawn('xcodebuild', xcodebuildArgs, getProcessOptions(launchPackager, port));
    let buildOutput = '';
    buildProcess.stdout.on('data', function(data) {
      buildOutput += data.toString();
      if (xcpretty) {
        xcpretty.stdin.write(data);
      } else {
        console.log(data.toString());
      }
    });
    buildProcess.stderr.on('data', function(data) {
      console.error(data.toString());
    });
    buildProcess.on('close', function(code) {
      if (xcpretty) {
        xcpretty.stdin.end();
      }
      //FULL_PRODUCT_NAME is the actual file name of the app, which actually comes from the Product Name in the build config, which does not necessary match a scheme name,  example output line: export FULL_PRODUCT_NAME="Super App Dev.app"
      let productNameMatch = /export FULL_PRODUCT_NAME="?(.+).app"?$/m.exec(buildOutput);
      if (productNameMatch && productNameMatch.length && productNameMatch.length > 1) {
        return resolve(productNameMatch[1]);//0 is the full match, 1 is the app name
      }
      return buildProcess.error ? reject(buildProcess.error) : resolve();
    });
  });
}

function matchingDevice(devices, deviceName) {
  if (deviceName === true && devices.length === 1)
  {
    console.log(`Using first available device ${devices[0].name} due to lack of name supplied.`);
    return devices[0];
  }
  for (let i = devices.length - 1; i >= 0; i--) {
    if (devices[i].name === deviceName || formattedDeviceName(devices[i]) === deviceName) {
      return devices[i];
    }
  }
}

function matchingDeviceByUdid(devices, udid) {
  for (let i = devices.length - 1; i >= 0; i--) {
    if (devices[i].udid === udid) {
      return devices[i];
    }
  }
}

function formattedDeviceName(simulator) {
  return `${simulator.name} (${simulator.version})`;
}

function printFoundDevices(devices) {
  for (let i = devices.length - 1; i >= 0; i--) {
    console.log(devices[i].name + ' Udid: ' + devices[i].udid);
  }
}

function getProcessOptions(launchPackager, port) {
  if (launchPackager) {
    return {
      env: { ...process.env, RCT_METRO_PORT: port }
    };
  }

  return {
    env: { ...process.env, RCT_NO_LAUNCH_PACKAGER: true },
  };
}

module.exports = {
  name: 'run-ios',
  description: 'builds your app and starts it on iOS simulator',
  func: runIOS,
  examples: [
  {
    desc: 'Run on a different simulator, e.g. iPhone 5',
    cmd: 'react-native run-ios --simulator "iPhone 5"',
  },
  {
    desc: 'Pass a non-standard location of iOS directory',
    cmd: 'react-native run-ios --project-path "./app/ios"',
  },
  {
    desc: "Run on a connected device, e.g. Max's iPhone",
    cmd: 'react-native run-ios --device "Max\'s iPhone"',
  },
  {
    desc: 'Run on the AppleTV simulator',
    cmd: 'react-native run-ios --simulator "Apple TV"  --scheme "helloworld-tvOS"',
  }
  ],
  options: [{
    command: '--simulator [string]',
    description: 'Explicitly set simulator to use',
    default: 'iPhone 6',
  } , {
    command: '--configuration [string]',
    description: 'Explicitly set the scheme configuration to use',
  } , {
    command: '--scheme [string]',
    description: 'Explicitly set Xcode scheme to use',
  }, {
    command: '--project-path [string]',
    description: 'Path relative to project root where the Xcode project '
      + '(.xcodeproj) lives. The default is \'ios\'.',
    default: 'ios',
  }, {
    command: '--device [string]',
    description: 'Explicitly set device to use by name.  The value is not required if you have a single device connected.',
  }, {
    command: '--udid [string]',
    description: 'Explicitly set device to use by udid',
  }, {
    command: '--no-packager',
    description: 'Do not launch packager while building',
  }, {
    command: '--verbose',
    description: 'Do not use xcpretty even if installed',
  },{
    command: '--port [number]',
    default: process.env.RCT_METRO_PORT || 8081,
    parse: (val: string) => Number(val),
  }],
};
<commit_msg>Pass port when running on device (fix #17973)<commit_after>/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
'use strict';

const child_process = require('child_process');
const fs = require('fs');
const path = require('path');
const findXcodeProject = require('./findXcodeProject');
const findReactNativeScripts = require('../util/findReactNativeScripts');
const parseIOSDevicesList = require('./parseIOSDevicesList');
const findMatchingSimulator = require('./findMatchingSimulator');
const getBuildPath = function (configuration = 'Debug', appName, isDevice) {
  let device;

  if (isDevice) {
    device = 'iphoneos';
  } else if (appName.toLowerCase().includes('tvos')) {
    device = 'appletvsimulator';
  } else {
    device = 'iphonesimulator';
  }

  return `build/Build/Products/${configuration}-${device}/${appName}.app`;
};
const xcprettyAvailable = function() {
  try {
    child_process.execSync('xcpretty --version', {
      stdio: [ 0, 'pipe', 'ignore', ]
    });
  } catch (error) {
    return false;
  }
  return true;
};

function runIOS(argv, config, args) {
  if (!fs.existsSync(args.projectPath)) {
    const reactNativeScriptsPath = findReactNativeScripts();
    if (reactNativeScriptsPath) {
      child_process.spawnSync(
        reactNativeScriptsPath,
        ['ios'].concat(process.argv.slice(1)),
        {stdio: 'inherit'}
      );
      return;
    } else {
      throw new Error('iOS project folder not found. Are you sure this is a React Native project?');
    }
  }
  process.chdir(args.projectPath);
  const xcodeProject = findXcodeProject(fs.readdirSync('.'));
  if (!xcodeProject) {
    throw new Error('Could not find Xcode project files in ios folder');
  }

  const inferredSchemeName = path.basename(xcodeProject.name, path.extname(xcodeProject.name));
  const scheme = args.scheme || inferredSchemeName;
  console.log(`Found Xcode ${xcodeProject.isWorkspace ? 'workspace' : 'project'} ${xcodeProject.name}`);
  const devices = parseIOSDevicesList(
    child_process.execFileSync('xcrun', ['instruments', '-s'], {encoding: 'utf8'})
  );
  if (args.device) {
    const selectedDevice = matchingDevice(devices, args.device);
    if (selectedDevice) {
      return runOnDevice(selectedDevice, scheme, xcodeProject, args.configuration, args.packager, args.verbose, args.port);
    } else {
      if (devices && devices.length > 0) {
        console.log('Could not find device with the name: "' + args.device + '".');
        console.log('Choose one of the following:');
        printFoundDevices(devices);
      } else {
        console.log('No iOS devices connected.');
      }
    }
  } else if (args.udid) {
    return runOnDeviceByUdid(args, scheme, xcodeProject, devices);
  } else {
    return runOnSimulator(xcodeProject, args, scheme);
  }
}

function runOnDeviceByUdid(args, scheme, xcodeProject, devices) {
  const selectedDevice = matchingDeviceByUdid(devices, args.udid);
  if (selectedDevice) {
    return runOnDevice(selectedDevice, scheme, xcodeProject, args.configuration, args.packager, args.verbose, args.port);
  } else {
    if (devices && devices.length > 0) {
      console.log('Could not find device with the udid: "' + args.udid + '".');
      console.log('Choose one of the following:');
      printFoundDevices(devices);
    } else {
      console.log('No iOS devices connected.');
    }
  }
}

function runOnSimulator(xcodeProject, args, scheme) {
  return new Promise((resolve) => {
    try {
      var simulators = JSON.parse(
      child_process.execFileSync('xcrun', ['simctl', 'list', '--json', 'devices'], {encoding: 'utf8'})
      );
    } catch (e) {
      throw new Error('Could not parse the simulator list output');
    }

    const selectedSimulator = findMatchingSimulator(simulators, args.simulator);
    if (!selectedSimulator) {
      throw new Error(`Could not find ${args.simulator} simulator`);
    }

    const simulatorFullName = formattedDeviceName(selectedSimulator);
    console.log(`Launching ${simulatorFullName}...`);
    try {
      child_process.spawnSync('xcrun', ['instruments', '-w', selectedSimulator.udid]);
    } catch (e) {
      // instruments always fail with 255 because it expects more arguments,
      // but we want it to only launch the simulator
    }
    resolve(selectedSimulator.udid);
  })
  .then((udid) => buildProject(xcodeProject, udid, scheme, args.configuration, args.packager, args.verbose, args.port))
  .then((appName) => {
    if (!appName) {
      appName = scheme;
    }
    let appPath = getBuildPath(args.configuration, appName);
    console.log(`Installing ${appPath}`);
    child_process.spawnSync('xcrun', ['simctl', 'install', 'booted', appPath], {stdio: 'inherit'});

    const bundleID = child_process.execFileSync(
      '/usr/libexec/PlistBuddy',
      ['-c', 'Print:CFBundleIdentifier', path.join(appPath, 'Info.plist')],
      {encoding: 'utf8'}
    ).trim();

    console.log(`Launching ${bundleID}`);
    child_process.spawnSync('xcrun', ['simctl', 'launch', 'booted', bundleID], {stdio: 'inherit'});
  });
}

function runOnDevice(selectedDevice, scheme, xcodeProject, configuration, launchPackager, verbose, port) {
  return buildProject(xcodeProject, selectedDevice.udid, scheme, configuration, launchPackager, verbose, port)
  .then((appName) => {
    if (!appName) {
      appName = scheme;
    }
    const iosDeployInstallArgs = [
      '--bundle', getBuildPath(configuration, appName, true),
      '--id' , selectedDevice.udid,
      '--justlaunch'
    ];
    console.log(`installing and launching your app on ${selectedDevice.name}...`);
    const iosDeployOutput = child_process.spawnSync('ios-deploy', iosDeployInstallArgs, {encoding: 'utf8'});
    if (iosDeployOutput.error) {
      console.log('');
      console.log('** INSTALLATION FAILED **');
      console.log('Make sure you have ios-deploy installed globally.');
      console.log('(e.g "npm install -g ios-deploy")');
    } else {
      console.log('** INSTALLATION SUCCEEDED **');
    }
  });
}

function buildProject(xcodeProject, udid, scheme, configuration = 'Debug', launchPackager = false, verbose, port) {
  return new Promise((resolve,reject) =>
  {
     var xcodebuildArgs = [
      xcodeProject.isWorkspace ? '-workspace' : '-project', xcodeProject.name,
      '-configuration', configuration,
      '-scheme', scheme,
      '-destination', `id=${udid}`,
      '-derivedDataPath', 'build',
    ];
    console.log(`Building using "xcodebuild ${xcodebuildArgs.join(' ')}"`);
    let xcpretty;
    if (!verbose) {
      xcpretty = xcprettyAvailable() && child_process.spawn('xcpretty', [], { stdio: ['pipe', process.stdout, process.stderr] });
    }
    const buildProcess = child_process.spawn('xcodebuild', xcodebuildArgs, getProcessOptions(launchPackager, port));
    let buildOutput = '';
    buildProcess.stdout.on('data', function(data) {
      buildOutput += data.toString();
      if (xcpretty) {
        xcpretty.stdin.write(data);
      } else {
        console.log(data.toString());
      }
    });
    buildProcess.stderr.on('data', function(data) {
      console.error(data.toString());
    });
    buildProcess.on('close', function(code) {
      if (xcpretty) {
        xcpretty.stdin.end();
      }
      //FULL_PRODUCT_NAME is the actual file name of the app, which actually comes from the Product Name in the build config, which does not necessary match a scheme name,  example output line: export FULL_PRODUCT_NAME="Super App Dev.app"
      let productNameMatch = /export FULL_PRODUCT_NAME="?(.+).app"?$/m.exec(buildOutput);
      if (productNameMatch && productNameMatch.length && productNameMatch.length > 1) {
        return resolve(productNameMatch[1]);//0 is the full match, 1 is the app name
      }
      return buildProcess.error ? reject(buildProcess.error) : resolve();
    });
  });
}

function matchingDevice(devices, deviceName) {
  if (deviceName === true && devices.length === 1)
  {
    console.log(`Using first available device ${devices[0].name} due to lack of name supplied.`);
    return devices[0];
  }
  for (let i = devices.length - 1; i >= 0; i--) {
    if (devices[i].name === deviceName || formattedDeviceName(devices[i]) === deviceName) {
      return devices[i];
    }
  }
}

function matchingDeviceByUdid(devices, udid) {
  for (let i = devices.length - 1; i >= 0; i--) {
    if (devices[i].udid === udid) {
      return devices[i];
    }
  }
}

function formattedDeviceName(simulator) {
  return `${simulator.name} (${simulator.version})`;
}

function printFoundDevices(devices) {
  for (let i = devices.length - 1; i >= 0; i--) {
    console.log(devices[i].name + ' Udid: ' + devices[i].udid);
  }
}

function getProcessOptions(launchPackager, port) {
  if (launchPackager) {
    return {
      env: { ...process.env, RCT_METRO_PORT: port }
    };
  }

  return {
    env: { ...process.env, RCT_NO_LAUNCH_PACKAGER: true },
  };
}

module.exports = {
  name: 'run-ios',
  description: 'builds your app and starts it on iOS simulator',
  func: runIOS,
  examples: [
  {
    desc: 'Run on a different simulator, e.g. iPhone 5',
    cmd: 'react-native run-ios --simulator "iPhone 5"',
  },
  {
    desc: 'Pass a non-standard location of iOS directory',
    cmd: 'react-native run-ios --project-path "./app/ios"',
  },
  {
    desc: "Run on a connected device, e.g. Max's iPhone",
    cmd: 'react-native run-ios --device "Max\'s iPhone"',
  },
  {
    desc: 'Run on the AppleTV simulator',
    cmd: 'react-native run-ios --simulator "Apple TV"  --scheme "helloworld-tvOS"',
  }
  ],
  options: [{
    command: '--simulator [string]',
    description: 'Explicitly set simulator to use',
    default: 'iPhone 6',
  } , {
    command: '--configuration [string]',
    description: 'Explicitly set the scheme configuration to use',
  } , {
    command: '--scheme [string]',
    description: 'Explicitly set Xcode scheme to use',
  }, {
    command: '--project-path [string]',
    description: 'Path relative to project root where the Xcode project '
      + '(.xcodeproj) lives. The default is \'ios\'.',
    default: 'ios',
  }, {
    command: '--device [string]',
    description: 'Explicitly set device to use by name.  The value is not required if you have a single device connected.',
  }, {
    command: '--udid [string]',
    description: 'Explicitly set device to use by udid',
  }, {
    command: '--no-packager',
    description: 'Do not launch packager while building',
  }, {
    command: '--verbose',
    description: 'Do not use xcpretty even if installed',
  },{
    command: '--port [number]',
    default: process.env.RCT_METRO_PORT || 8081,
    parse: (val: string) => Number(val),
  }],
};
<|endoftext|>


<commit_before>/**
 * @file
 * Define the API
 */

import ElasticClass from '../components/ElasticSearch/ElasticSearchClass';

// Libraries
const Router = require('koa-router');

// Init router
const APIRouter = new Router();

const ElasticClient = new ElasticClass();

// Small helper function for generating relative urls.
function generateHierarchyUrl(dk5) {
  return `/hierarchy/${dk5}`;
}

// Small helper function for generating search urls
function generateSearchUrl(q) {
  return `#!/search/${encodeURIComponent(q)}/10/0/relevance/dictionary`;
}

// Define handler functions
async function suggestHandler(ctx) {
  let {q} = ctx.query; // eslint-disable-line no-unused-vars
  const response = {
    status: 200,
    query: {endpoint: 'suggest', query: q},
    response: (await ElasticClient.elasticSuggest(q)).prefix.map(match => {
      const res = {
        label: match.match || '',
        href: generateSearchUrl(match.match || '')
      };

      return res;
    })
  };

  ctx.set('Content-Type', 'application/json');
  ctx.body = JSON.stringify(response);
}

async function hierarchyHandler(ctx) {
  let {q} = ctx.query;
  const response = {
    status: 200,
    parameters: {endpoint: 'hierarchy', query: q},
    response: {},
    result: await ElasticClient.elasticHierarchy(q)
  };

  ctx.set('Content-Type', 'application/json');
  ctx.body = JSON.stringify(response);
}

async function searchHandler(ctx) {
  ctx.set('Content-Type', 'application/json');
  let {q, limit, offset, sort, spell} = ctx.query; // eslint-disable-line no-unused-vars
  const validSorts = ['relevance', 'dk5'];
  let errors = 0;
  if (!q) {
    ctx.body = JSON.stringify({status: 400, error: 'No query provided'});
    ctx.status = 400;
    errors += 1;
  }

  if (q && q === '') {
    ctx.body = JSON.stringify({status: 400, error: 'No query provided'});
    ctx.status = 400;
    errors += 1;
  }

  if (limit && limit !== '') {
    limit = parseInt(limit, 10) || 10;
  }
  else {
    limit = 10;
  }

  if (offset && offset !== '') {
    offset = parseInt(offset, 10) || 0;
  }
  else {
    offset = 0;
  }

  if (!sort || sort === '') {
    sort = validSorts[0];
  }

  if (validSorts.indexOf(sort) < 0) {
    ctx.body = JSON.stringify({status: 400, error: 'Invalid sort selected!'});
    ctx.status = 400;
    errors += 1;
  }

  if (errors === 0) {
    const response = {
      status: 200,
      parameters: {endpoint: 'search', query: q, limit: limit, offset: offset},
      correction: {},
      elasticStatus: await ElasticClient.elasticPing(),
      result: await ElasticClient.elasticSearch({query: q, limit: limit, offset: offset})
    };

    if (spell && spell !== 'none') {
      // Get the closest spelling
      q = 'Japan';
      response.correction.q = q;
    }

    response.response = [{
      title: '65.2 Regnskabsføring i alm.',
      dk5: {index: '65.2', title: 'Regnskabsføring i alm.'},
      items: []
    }, {
      title: '65.126 Forbrugerbekyttelse i alm.',
      dk5: {index: '65.126', title: 'Forbrugerbekyttelse i alm.'},
      items: []
    }];

    ctx.body = JSON.stringify(response);
  }
}

// Connect endpoints to the functions.
APIRouter.get('/api/suggest', suggestHandler);
APIRouter.get('/api/hierarchy', hierarchyHandler);
APIRouter.get('/api/search', searchHandler);

module.exports = {
  APIRouter
};
<commit_msg>adjustments to suggestions.<commit_after>/**
 * @file
 * Define the API
 */

import ElasticClass from '../components/ElasticSearch/ElasticSearchClass';

// Libraries
const Router = require('koa-router');

// Init router
const APIRouter = new Router();

const ElasticClient = new ElasticClass();

// Small helper function for generating search urls
function generateSearchUrl(q) {
  return `#!/search/${encodeURIComponent(q)}/10/0/relevance/dictionary`;
}

// Define handler functions
async function suggestHandler(ctx) {
  let {q} = ctx.query; // eslint-disable-line no-unused-vars
  const response = {
    status: 200,
    query: {endpoint: 'suggest', query: q},
    response: (await ElasticClient.elasticSuggest(q)).prefix.map(match => {
      const res = {
        label: match.match || '',
        href: generateSearchUrl(match.match || '')
      };

      return res;
    })
  };

  ctx.set('Content-Type', 'application/json');
  ctx.body = JSON.stringify(response);
}

async function hierarchyHandler(ctx) {
  let {q} = ctx.query;
  const response = {
    status: 200,
    parameters: {endpoint: 'hierarchy', query: q},
    response: {},
    result: await ElasticClient.elasticHierarchy(q)
  };

  ctx.set('Content-Type', 'application/json');
  ctx.body = JSON.stringify(response);
}

async function searchHandler(ctx) {
  ctx.set('Content-Type', 'application/json');
  let {q, limit, offset, sort, spell} = ctx.query; // eslint-disable-line no-unused-vars
  const validSorts = ['relevance', 'dk5'];
  let errors = 0;
  if (!q) {
    ctx.body = JSON.stringify({status: 400, error: 'No query provided'});
    ctx.status = 400;
    errors += 1;
  }

  if (q && q === '') {
    ctx.body = JSON.stringify({status: 400, error: 'No query provided'});
    ctx.status = 400;
    errors += 1;
  }

  if (limit && limit !== '') {
    limit = parseInt(limit, 10) || 10;
  }
  else {
    limit = 10;
  }

  if (offset && offset !== '') {
    offset = parseInt(offset, 10) || 0;
  }
  else {
    offset = 0;
  }

  if (!sort || sort === '') {
    sort = validSorts[0];
  }

  if (validSorts.indexOf(sort) < 0) {
    ctx.body = JSON.stringify({status: 400, error: 'Invalid sort selected!'});
    ctx.status = 400;
    errors += 1;
  }

  if (errors === 0) {
    const response = {
      status: 200,
      parameters: {endpoint: 'search', query: q, limit: limit, offset: offset},
      correction: {},
      elasticStatus: await ElasticClient.elasticPing(),
      result: await ElasticClient.elasticSearch({query: q, limit: limit, offset: offset})
    };

    if (spell && spell !== 'none') {
      // Get the closest spelling
      q = 'Japan';
      response.correction.q = q;
    }

    response.response = [{
      title: '65.2 Regnskabsføring i alm.',
      dk5: {index: '65.2', title: 'Regnskabsføring i alm.'},
      items: []
    }, {
      title: '65.126 Forbrugerbekyttelse i alm.',
      dk5: {index: '65.126', title: 'Forbrugerbekyttelse i alm.'},
      items: []
    }];

    ctx.body = JSON.stringify(response);
  }
}

// Connect endpoints to the functions.
APIRouter.get('/api/suggest', suggestHandler);
APIRouter.get('/api/hierarchy', hierarchyHandler);
APIRouter.get('/api/search', searchHandler);

module.exports = {
  APIRouter
};
<|endoftext|>


<commit_before>import { h, Component } from 'preact';
import style from './style';
import { Day } from '../../components/day';
import { Intro } from '../../components/intro';

const DAY_OF_ADVENT = 25;

let windowProxy;
if (typeof window === "undefined") {
	windowProxy = {innerWidth: 1200};
} else {
	windowProxy = window;
}

export default class Home extends Component {

	state = { isMouseDown: false, x: 0, offsetX: 0 };

	render(props, state) {
		return (
			<div
				class="fullscreen container"
				onTouchStart={this.startDrag}
				onTouchEnd={this.endDrag}
				onTouchMove={this.drag}
				onMouseDown={this.startDrag}
				onMouseUp={this.endDrag}
				onMouseMove={this.drag}
				onMouseWheel={this.scroll}
				onMouseLeave={this.endDrag}
			>
				<div
					class={`fullscreen ${style.days} ${this.grabbingClass}`}
					style={this.getTransform(state)}
				>
					<Intro offsetX={state.offsetX}/>
					{this.renderDays(state.offsetX)}
				</div>
			</div>
		);
	}

	startDrag = e => {
		const x = getXFromTouchOrPointer(e);
		this.setState({ isMouseDown: true, x });
	}

	endDrag = e => {
		this.setState({ isMouseDown: false });
	}

	drag = e => {
		if (this.state.isMouseDown) {
			const x = getXFromTouchOrPointer(e);
			const delta = this.state.x - x;
			this.setState({ x });
			this.updateOffset(delta);
		}
	}

	scroll = e => {
		e.preventDefault();
		const delta = e.deltaX + e.deltaY;
		this.updateOffset(delta);
	}

	updateOffset(delta) {
		const offsetX = constrainNumber(this.state.offsetX + delta, 0, windowProxy.innerWidth * DAY_OF_ADVENT);
		this.setState({ offsetX });
	}

	getTransform({ offsetX }) {
		return { transform: `translate3d(${-1 * offsetX}px, 0, 0)` };
	}

	renderDays(offsetX) {
		const days = [];
		const windowWidth = windowProxy.innerWidth;
		for (let i = 0; i < DAY_OF_ADVENT; i++) {
			const dayOffsetX = offsetX - windowWidth * (i + 1);
			days.push(<Day day={i} offsetX={dayOffsetX} />);
		}
		return days;
	}

	get grabbingClass() {
		return this.state.isMouseDown ? style.grabbing : '';
	}

}

function getXFromTouchOrPointer(event) {
	let x;
	if ('touches' in event) {
		x = event.touches[0].clientX;
	} else {
		x = event.clientX;
	}
	return x;
}

function constrainNumber(number, min, max) {
	return Math.min(Math.max(number, min), max);
}<commit_msg>Added deceleration on true drag<commit_after>import { h, Component } from 'preact';
import style from './style';
import { Day } from '../../components/day';
import { Intro } from '../../components/intro';

const DAY_OF_ADVENT = 25;

const FRICTION = 0.95;
const STOP_THRESHOLD = 0.3;

let windowProxy;
if (typeof window === "undefined") {
	windowProxy = { innerWidth: 1200 };
} else {
	windowProxy = window;
}

export default class Home extends Component {

	state = { isMouseDown: false, x: 0, offsetX: 0, trackingPoints: [], decVelX: 0 };

	render(props, state) {
		return (
			<div
				class="fullscreen container"
				onTouchStart={this.startDrag}
				onTouchEnd={this.endDrag}
				onTouchMove={this.drag}
				onMouseDown={this.startDrag}
				onMouseUp={this.endDrag}
				onMouseMove={this.drag}
				onMouseWheel={this.scroll}
				onMouseLeave={this.endDrag}
			>
				<div
					class={`fullscreen ${style.days} ${this.grabbingClass}`}
					style={this.getTransform(state)}
				>
					<Intro offsetX={state.offsetX} />
					{this.renderDays(state.offsetX)}
				</div>
			</div>
		);
	}

	startDrag = e => {
		const x = getXFromTouchOrPointer(e);
		this.setState({ isMouseDown: true, x, trackingPoints: [] });
	}

	endDrag = e => {
		const x = getXFromTouchOrPointer(e);
		this.addTrackingPoint(x);
		this.setState({ isMouseDown: false });
		this.startDeceleration();
	}

	drag = e => {
		if (this.state.isMouseDown) {
			const x = getXFromTouchOrPointer(e);
			this.addTrackingPoint(x);
			const delta = this.state.x - x;
			this.setState({ x });
			this.updateOffset(delta);
		}
	}

	scroll = e => {
		e.preventDefault();
		const delta = e.deltaX + e.deltaY;
		this.updateOffset(delta);
	}

	addTrackingPoint(x) {
		const time = Date.now();
		const trackingPoints = [...this.state.trackingPoints];
		while (trackingPoints.length > 0) {
			if (time - trackingPoints[0].time <= 100) {
				break;
			}
			trackingPoints.shift();
		}
		trackingPoints.push({ x, time })
		this.setState({trackingPoints});
	}

	updateOffset(delta) {
		const offsetX = constrainNumber(this.state.offsetX + delta, 0, windowProxy.innerWidth * DAY_OF_ADVENT);
		this.setState({ offsetX });
	}

	getTransform({ offsetX }) {
		return { transform: `translate3d(${-1 * offsetX}px, 0, 0)` };
	}

	renderDays(offsetX) {
		const days = [];
		const windowWidth = windowProxy.innerWidth;
		for (let i = 0; i < DAY_OF_ADVENT; i++) {
			const dayOffsetX = offsetX - windowWidth * (i + 1);
			days.push(<Day day={i} offsetX={dayOffsetX} />);
		}
		return days;
	}

	get grabbingClass() {
		return this.state.isMouseDown ? style.grabbing : '';
	}

	// Deceleration
	startDeceleration() {
		const { trackingPoints } = this.state;
		const firstPoint = trackingPoints[0];
		const lastPoint = trackingPoints[trackingPoints.length - 1];

		var xOffset = lastPoint.x - firstPoint.x;
		var timeOffset = lastPoint.time - firstPoint.time;

		const D = (timeOffset / 15);

		const decVelX = (xOffset / D) || 0; // prevent NaN

		let decelerating = false;
		if (Math.abs(decVelX) > 1) {
			decelerating = true;
			requestAnimationFrame(this.stepDeceleration.bind(this));
		}
		this.setState({ decelerating, decVelX });
	}

	stepDeceleration() {
		if (!this.state.decelerating) {
			return;
		}

		const decVelX = this.state.decVelX * FRICTION;
		if (Math.abs(decVelX) > STOP_THRESHOLD) {
			this.updateOffset(-1 * decVelX);

			requestAnimationFrame(this.stepDeceleration.bind(this));
			this.setState({decVelX});
		} else {
			this.setState({decelerating: false});
		}
	}

}

function getXFromTouchOrPointer(event) {
	let x;
	if ('touches' in event) {
		try {
			x = event.changedTouches[0].clientX;
		} catch (e) {
			console.log(event);
		}

	} else {
		x = event.clientX;
	}
	return x;
}

function constrainNumber(number, min, max) {
	return Math.min(Math.max(number, min), max);
}<|endoftext|>


<commit_before>/**
 * React Starter Kit (https://www.reactstarterkit.com/)
 *
 * Copyright © 2014-2016 Kriasoft, LLC. All rights reserved.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE.txt file in the root directory of this source tree.
 */

import React from 'react';
import Home from './Home';
import fetch from '../../core/fetch';
import Layout from '../../components/Layout';

export default {

  path: '/',

  async action() {
    const resp = await fetch('/graphql', {
      method: 'post',
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        query: '{news{title,link,publishedDate,contentSnippet}}',
      }),
      credentials: 'include',
    });
    const { data } = await resp.json();
    if (!data || !data.news) throw new Error('Failed to load the news feed.');
    return {
      title: 'React Starter Kit',
      component: <Layout><Home news={data.news} /></Layout>,
    };
  },

};
<commit_msg>fixed news feed query (#1045)<commit_after>/**
 * React Starter Kit (https://www.reactstarterkit.com/)
 *
 * Copyright © 2014-2016 Kriasoft, LLC. All rights reserved.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE.txt file in the root directory of this source tree.
 */

import React from 'react';
import Home from './Home';
import fetch from '../../core/fetch';
import Layout from '../../components/Layout';

export default {

  path: '/',

  async action() {
    const resp = await fetch('/graphql', {
      method: 'post',
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        query: '{news{title,link,pubDate,content}}',
      }),
      credentials: 'include',
    });
    const { data } = await resp.json();
    if (!data || !data.news) throw new Error('Failed to load the news feed.');
    return {
      title: 'React Starter Kit',
      component: <Layout><Home news={data.news} /></Layout>,
    };
  },

};
<|endoftext|>


<commit_before>import Historian from 'historian';

describe('historian', () => {
    let lastVisitTime, historian;

    beforeEach(() => {
        jasmine.clock().mockDate(new Date(1993, 9, 26, 3, 25, 0));

        Historian.__set__({
            browser: {
                setToStorage: ({key, value}) => {
                    if (key === 'lastVisitTime')
                        lastVisitTime = value;
                },
                getFromStorage: (key) => {
                    if (key === 'lastVisitTime')
                        return lastVisitTime;
                },
                searchFromHistory: (query, lastVisitTime, callback) => {
                    if (query === 'http://southpark.cc.com/full-episodes/') {
                        callback([{
                            lastVisitTime: 743859800000,
                            url: 'http://southpark.cc.com/full-episodes/s01e01'
                        }, {
                            lastVisitTime: 743829100000,
                            url: 'http://southpark.cc.com/full-episodes/s01e02'
                        }]);
                    } else if (query === 'http://kisscartoon.me/Cartoon/South-Park-Season') {
                        callback([{
                            lastVisitTime: 703806800000,
                            url: 'http://kisscartoon.me/Cartoon/South-Park-Season-03/Episode-004'
                        }, {
                            lastVisitTime: 783806800000,
                            url: 'http://kisscartoon.me/Cartoon/South-Park-Season-04/Episode-005'
                        }]);
                    }
                }
            }
        });
        historian = new Historian();
    });

    it('sets last visit time to storage', () => {
        expect(lastVisitTime).toEqual(743819100000);
    });

    describe('getSeenEpisodes()', () => {
        it('collects all seen episodes', (done) => {
            historian.getSeenEpisodes().then((seenEpisodes) => {
                expect(seenEpisodes).toEqual([
                    {season: 1, episode: 1},
                    {season: 1, episode: 2},
                    {season: 4, episode: 5}
                ]);
                done();
            });
        });
    });
});
<commit_msg>#FIX Mock time in historian tests to make sure that timezones don't fck it up<commit_after>import Historian from 'historian';

describe('historian', () => {
    let lastVisitTime, historian;

    beforeEach(() => {
        jasmine.clock().mockDate(new Date(736043100000));

        Historian.__set__({
            browser: {
                setToStorage: ({key, value}) => {
                    if (key === 'lastVisitTime')
                        lastVisitTime = value;
                },
                getFromStorage: (key) => {
                    if (key === 'lastVisitTime')
                        return lastVisitTime;
                },
                searchFromHistory: (query, lastVisitTime, callback) => {
                    if (query === 'http://southpark.cc.com/full-episodes/') {
                        callback([{
                            lastVisitTime: 743859800000,
                            url: 'http://southpark.cc.com/full-episodes/s01e01'
                        }, {
                            lastVisitTime: 743829100000,
                            url: 'http://southpark.cc.com/full-episodes/s01e02'
                        }]);
                    } else if (query === 'http://kisscartoon.me/Cartoon/South-Park-Season') {
                        callback([{
                            lastVisitTime: 708270700000,
                            url: 'http://kisscartoon.me/Cartoon/South-Park-Season-03/Episode-004'
                        }, {
                            lastVisitTime: 783806800000,
                            url: 'http://kisscartoon.me/Cartoon/South-Park-Season-04/Episode-005'
                        }]);
                    }
                }
            }
        });
        historian = new Historian();
    });

    it('sets last visit time to storage', () => {
        expect(lastVisitTime).toEqual(728270700000);
    });

    describe('getSeenEpisodes()', () => {
        it('collects all seen episodes', (done) => {
            historian.getSeenEpisodes().then((seenEpisodes) => {
                expect(seenEpisodes).toEqual([
                    {season: 1, episode: 1},
                    {season: 1, episode: 2},
                    {season: 4, episode: 5}
                ]);
                done();
            });
        });
    });
});
<|endoftext|>


<commit_before>/*jslint nomen: true, undef: true, sloppy: true, white: true, stupid: true, passfail: false, node: true, plusplus: true, indent: 2 */

var should = require("should"),
    i18n = require('../i18n'),
    fs = require('fs');

i18n.configure({
  locales: ['en', 'de'],
  register: global,
  directory: './testlocales',
  extension: '.json',
  debug: false,
  verbose: false
});

describe('Configuration settings:', function () {

  after(function () {
    var stats = fs.lstatSync('./testlocales');
    should.exist(stats);
    if (stats) {
      fs.unlinkSync('./testlocales/de.json');
      fs.unlinkSync('./testlocales/en.json');
      fs.rmdirSync('./testlocales');
    }
  });

  describe('when using a custom directory with a custom extension', function () {

    it('the setLocale and getLocale should still be able to set current locale', function () {
      should.equal('en', i18n.getLocale(), 'should return default setting');
      should.equal('de', i18n.setLocale('de'), 'should return the new setting');
      should.equal('de', i18n.getLocale(), 'should return the new setting');
    });

    it('and some basic translations should still work', function () {
      i18n.setLocale('en');
      should.equal(__('Hello'), 'Hello');
      should.equal(__('Hello %s, how are you today?', 'Marcus'), 'Hello Marcus, how are you today?');
      should.equal(__('Hello %s, how are you today? How was your %s.', 'Marcus', __('weekend')), 'Hello Marcus, how are you today? How was your weekend.');
    });

  });
});
<commit_msg>finally travis shows concurrency issues in tests<commit_after>/*jslint nomen: true, undef: true, sloppy: true, white: true, stupid: true, passfail: false, node: true, plusplus: true, indent: 2 */

var should = require("should"),
    i18n = require('../i18n'),
    fs = require('fs');

i18n.configure({
  locales: ['en', 'de'],
  register: global,
  directory: './testlocales',
  extension: '.json',
  debug: false,
  verbose: false
});

describe('Configuration settings:', function () {

  after(function () {
    var stats = fs.lstatSync('./testlocales');
    should.exist(stats);
    if (stats) {
      fs.unlinkSync('./testlocales/de.json');
      fs.unlinkSync('./testlocales/en.json');
      fs.rmdirSync('./testlocales');
    }
  });

  describe('when using a custom directory with a custom extension', function () {

    it('getLocale should return configured default locale', function () {
      should.equal('en', i18n.getLocale(), 'should return default setting');
    });

    it('setting locales should return appropiate locale', function () {
      var my_setLocale = i18n.setLocale('de'),
          my_getLocale = i18n.getLocale();
      should.equal('de', my_setLocale);
      should.equal('de', my_getLocale);
    });

    it('and some basic translations should still work', function () {
      i18n.setLocale('en');
      should.equal(__('Hello'), 'Hello');
      should.equal(__('Hello %s, how are you today?', 'Marcus'), 'Hello Marcus, how are you today?');
      should.equal(__('Hello %s, how are you today? How was your %s.', 'Marcus', __('weekend')), 'Hello Marcus, how are you today? How was your weekend.');
    });

  });
});
<|endoftext|>


<commit_before>
var mime = require('mime'),
    uuid = require('node-uuid'),
    aws = require('aws-sdk'),
    express = require('express');

function checkTrailingSlash(path) {
    if (path && path[path.length-1] != '/') {
        path += '/';
    }
    return path;
}

function S3Router(options) {

    var S3_BUCKET = options.bucket,
        getFileKeyDir = options.getFileKeyDir || function() { return ""; };

    if (!S3_BUCKET) {
        throw new Error("S3_BUCKET is required.");
    }

    var router = express.Router();

    /**
     * Redirects image requests with a temporary signed URL, giving access
     * to GET an image.
     */
    router.get(/\/img\/(.*)/, function(req, res) {
        var params = {
            Bucket: S3_BUCKET,
            Key: checkTrailingSlash(getFileKeyDir(req)) + req.params[0]
        };
        var s3 = new aws.S3();
        s3.getSignedUrl('getObject', params, function(err, url) {
            res.redirect(url);
        });
    });

    /**
     * Returns an object with `signedUrl` and `publicUrl` properties that
     * give temporary access to PUT an object in an S3 bucket.
     */
    router.get('/sign', function(req, res) {
        var filename = uuid.v4() + "_" + req.query.objectName;
        var mimeType = mime.lookup(filename);
        var fileKey = checkTrailingSlash(getFileKeyDir(req)) + filename;

        var s3 = new aws.S3();
        var params = {
            Bucket: S3_BUCKET,
            Key: fileKey,
            Expires: 60,
            ContentType: mimeType,
            ACL: options.ACL || 'private'
        };
        s3.getSignedUrl('putObject', params, function(err, data) {
            if (err) {
                console.log(err);
                return res.send(500, "Cannot create S3 signed URL");
            }
            res.json({
                signedUrl: data,
                publicUrl: '/s3/img/' + filename,
                filename: filename
            });
        });
    });

    return router;
}

module.exports = S3Router;
<commit_msg>Change path to upload, to be more generic around file type<commit_after>
var mime = require('mime'),
    uuid = require('node-uuid'),
    aws = require('aws-sdk'),
    express = require('express');

function checkTrailingSlash(path) {
    if (path && path[path.length-1] != '/') {
        path += '/';
    }
    return path;
}

function S3Router(options) {

    var S3_BUCKET = options.bucket,
        getFileKeyDir = options.getFileKeyDir || function() { return ""; };

    if (!S3_BUCKET) {
        throw new Error("S3_BUCKET is required.");
    }

    var router = express.Router();

    /**
     * Redirects image requests with a temporary signed URL, giving access
     * to GET an upload.
     */
    router.get(/\/upload\/(.*)/, function(req, res) {
        var params = {
            Bucket: S3_BUCKET,
            Key: checkTrailingSlash(getFileKeyDir(req)) + req.params[0]
        };
        var s3 = new aws.S3();
        s3.getSignedUrl('getObject', params, function(err, url) {
            res.redirect(url);
        });
    });

    /**
     * Returns an object with `signedUrl` and `publicUrl` properties that
     * give temporary access to PUT an object in an S3 bucket.
     */
    router.get('/sign', function(req, res) {
        var filename = uuid.v4() + "_" + req.query.objectName;
        var mimeType = mime.lookup(filename);
        var fileKey = checkTrailingSlash(getFileKeyDir(req)) + filename;

        var s3 = new aws.S3();
        var params = {
            Bucket: S3_BUCKET,
            Key: fileKey,
            Expires: 60,
            ContentType: mimeType,
            ACL: options.ACL || 'private'
        };
        s3.getSignedUrl('putObject', params, function(err, data) {
            if (err) {
                console.log(err);
                return res.send(500, "Cannot create S3 signed URL");
            }
            res.json({
                signedUrl: data,
                publicUrl: '/s3/upload/' + filename,
                filename: filename
            });
        });
    });

    return router;
}

module.exports = S3Router;
<|endoftext|>


<commit_before>const {red, bold} = require('colorette');
const fs = require('fs');
const poster = require('poster');

// https://api.anonymousfiles.io/

class ImageReporter {
  constructor(globalConfig, options) {
    this._globalConfig = globalConfig;
    this._options = options;
  }

  onTestResult(test, testResult, aggregateResults) {
    if (process.env.CI !== 'true') {
      return;
    }

    if (
      testResult.numFailingTests &&
      testResult.failureMessage.match(/different from snapshot/)
    ) {
      const files = fs.readdirSync(
        './test/functional/__image_snapshots__/__diff_output__/',
      );
      files.forEach(async value => {
        const file = `./test/functional/__image_snapshots__/__diff_output__/${value}`;

        poster.post(
          file,
          {
            uploadUrl: 'https://api.anonymousfiles.io/',
            fileId: 'file',
            fileContentType: 'image/png',
          },
          (err, data) => {
            console.log(
              red(bold(`Uploaded image diff file to ${JSON.parse(data).url}`)),
            );
          },
        );
      });
    }
  }
}

module.exports = ImageReporter;
<commit_msg>test: throw err in image reporter<commit_after>const {red, bold} = require('colorette');
const fs = require('fs');
const poster = require('poster');

// https://api.anonymousfiles.io/

class ImageReporter {
  constructor(globalConfig, options) {
    this._globalConfig = globalConfig;
    this._options = options;
  }

  onTestResult(test, testResult, aggregateResults) {
    if (process.env.CI !== 'true') {
      return;
    }

    if (
      testResult.numFailingTests &&
      testResult.failureMessage.match(/different from snapshot/)
    ) {
      const files = fs.readdirSync(
        './test/functional/__image_snapshots__/__diff_output__/',
      );
      files.forEach(async value => {
        const file = `./test/functional/__image_snapshots__/__diff_output__/${value}`;

        poster.post(
          file,
          {
            uploadUrl: 'https://api.anonymousfiles.io/',
            fileId: 'file',
            fileContentType: 'image/png',
          },
          (err, data) => {
            if (err) {
              throw err;
            }

            console.log(
              red(bold(`Uploaded image diff file to ${JSON.parse(data).url}`)),
            );
          },
        );
      });
    }
  }
}

module.exports = ImageReporter;
<|endoftext|>