<commit_before>define([
    '/bower_components/chainpad-crypto/crypto.js',
    '/bower_components/jquery/dist/jquery.min.js',
], function (Crypto) {
/*  This file exposes functionality which is specific to Cryptpad, but not to
    any particular pad type. This includes functions for committing metadata
    about pads to your local storage for future use and improved usability.

    Additionally, there is some basic functionality for import/export.
*/
    var $ = window.jQuery;
    var common = {};

    var isArray = function (o) { return Object.prototype.toString.call(o) === '[object Array]'; };

    var getSecrets = common.getSecrets = function () {
        var secret = {};
        if (!/#/.test(window.location.href)) {
            secret.key = Crypto.genKey();
        } else {
            var hash = window.location.hash.slice(1);
            secret.channel = hash.slice(0, 32);
            secret.key = hash.slice(32);
        }
        return secret;
    };

    var storageKey = common.storageKey = 'CryptPad_RECENTPADS';
    //var timeframe = common.timeframe = 1000 * 60 * 60 * 24 * 30;

    /*
        the first time this gets called, your local storage will migrate to a
        new format. No more indices for values, everything is named now.

        * href
        * atime (access time)
        * title
        * ??? // what else can we put in here?
    */
    var migrateRecentPads = common.migrateRecentPads = function (pads) {
        return pads.map(function (pad) {
            if (isArray(pad)) {
                var href = pad[0];
                var hash;
                href.replace(/\#(.*)$/, function (a, h) {
                    hash = h;
                });

                return {
                    href: pad[0],
                    atime: pad[1],
                    title: pad[2] || hash && hash.slice(0,8),
                    ctime: pad[1],
                };
            } else if (typeof(pad) === 'object') {
                if (!pad.ctime) { pad.ctime = pad.atime; }
                if (!pad.title) {
                    pad.href.replace(/#(.*)$/, function (x, hash) {
                        pad.title = hash.slice(0,8);
                    });
                }
                return pad;
            } else {
                console.error("[Cryptpad.migrateRecentPads] pad had unexpected value");
                console.log(pad);
                return {};
            }
        });
    };

    /* fetch and migrate your pad history from localStorage */
    var getRecentPads = common.getRecentPads = function () {
        var recentPadsStr = localStorage[storageKey];

        var recentPads = [];
        if (recentPadsStr) {
            try {
                recentPads = JSON.parse(recentPadsStr);
            } catch (err) {
                // couldn't parse the localStorage?
                // just overwrite it.
            }
        }
        return migrateRecentPads(recentPads);
    };

    /* commit a list of pads to localStorage */
    var setRecentPads = common.setRecentPads = function (pads) {
        localStorage.setItem(storageKey, JSON.stringify(pads));
    };

    /* Sort pads according to how recently they were accessed */
    var mostRecent = common.mostRecent = function (a, b) {
        return new Date(b.atime).getTime() - new Date(a.atime).getTime();
    };

    var forgetPad = common.forgetPad = function (href) {
        var recentPads = getRecentPads().filter(function (pad) {
            return pad.href !== href;
        });
        setRecentPads(recentPads);
    };

    var rememberPad = common.rememberPad = window.rememberPad = function (title) {
        // bail out early
        if (!/#/.test(window.location.hash)) { return; }

        var pads = getRecentPads();

        var now = new Date();
        var href = window.location.href;

        var isUpdate = false;

        var out = pads.map(function (pad) {
            if (pad && pad.href === href) {
                isUpdate = true;
                // bump the atime
                pad.atime = now;

                pad.title = title;
            }
            return pad;
        });

        if (!isUpdate) {
            // href, atime, name
            out.push({
                href: href,
                atime: now,
                ctime: now,
                title: title || window.location.hash.slice(1,9),
            });
        }
        setRecentPads(out);
    };

    var setPadTitle = common.setPadTitle = function (name) {
        var href = window.location.href;
        var recent = getRecentPads();

        var renamed = recent.map(function (pad) {
            if (pad.href === href) {
                // update the atime
                pad.atime = new Date().toISOString();

                // set the name
                pad.title = name;
            }
            return pad;
        });

        setRecentPads(renamed);
    };

    var getPadTitle = common.getPadTitle = function () {
        var href = window.location.href;
        var hashSlice = window.location.hash.slice(1,9);
        var title = '';
        getRecentPads().some(function (pad) {
            if (pad.href === href) {
                title = pad.title || hashSlice;
                return true;
            }
        });
        return title;
    };

    var causesNamingConflict = common.causesNamingConflict = function (title) {
        var href = window.location.href;
        return getRecentPads().some(function (pad) {
            return pad.title === title &&
                pad.href !== href;
        });
    };

    var importContent = common.importContent = function (type, f) {
        return function () {
            var $files = $('<input type="file">').click();
            $files.on('change', function (e) {
                var file = e.target.files[0];
                var reader = new FileReader();
                reader.onload = function (e) { f(e.target.result, file); };
                reader.readAsText(file, type);
            });
        };
    };

    return common;
});
<commit_msg>add wrappers for alertifyjs<commit_after>define([
    '/bower_components/chainpad-crypto/crypto.js',
    '/bower_components/alertifyjs/dist/js/alertify.js',
    '/bower_components/jquery/dist/jquery.min.js',
], function (Crypto, Alertify) {
/*  This file exposes functionality which is specific to Cryptpad, but not to
    any particular pad type. This includes functions for committing metadata
    about pads to your local storage for future use and improved usability.

    Additionally, there is some basic functionality for import/export.
*/
    var $ = window.jQuery;

    var common = {};

    var isArray = function (o) { return Object.prototype.toString.call(o) === '[object Array]'; };

    var getSecrets = common.getSecrets = function () {
        var secret = {};
        if (!/#/.test(window.location.href)) {
            secret.key = Crypto.genKey();
        } else {
            var hash = window.location.hash.slice(1);
            secret.channel = hash.slice(0, 32);
            secret.key = hash.slice(32);
        }
        return secret;
    };

    var storageKey = common.storageKey = 'CryptPad_RECENTPADS';
    //var timeframe = common.timeframe = 1000 * 60 * 60 * 24 * 30;

    /*
        the first time this gets called, your local storage will migrate to a
        new format. No more indices for values, everything is named now.

        * href
        * atime (access time)
        * title
        * ??? // what else can we put in here?
    */
    var migrateRecentPads = common.migrateRecentPads = function (pads) {
        return pads.map(function (pad) {
            if (isArray(pad)) {
                var href = pad[0];
                var hash;
                href.replace(/\#(.*)$/, function (a, h) {
                    hash = h;
                });

                return {
                    href: pad[0],
                    atime: pad[1],
                    title: pad[2] || hash && hash.slice(0,8),
                    ctime: pad[1],
                };
            } else if (typeof(pad) === 'object') {
                if (!pad.ctime) { pad.ctime = pad.atime; }
                if (!pad.title) {
                    pad.href.replace(/#(.*)$/, function (x, hash) {
                        pad.title = hash.slice(0,8);
                    });
                }
                return pad;
            } else {
                console.error("[Cryptpad.migrateRecentPads] pad had unexpected value");
                console.log(pad);
                return {};
            }
        });
    };

    /* fetch and migrate your pad history from localStorage */
    var getRecentPads = common.getRecentPads = function () {
        var recentPadsStr = localStorage[storageKey];

        var recentPads = [];
        if (recentPadsStr) {
            try {
                recentPads = JSON.parse(recentPadsStr);
            } catch (err) {
                // couldn't parse the localStorage?
                // just overwrite it.
            }
        }
        return migrateRecentPads(recentPads);
    };

    /* commit a list of pads to localStorage */
    var setRecentPads = common.setRecentPads = function (pads) {
        localStorage.setItem(storageKey, JSON.stringify(pads));
    };

    /* Sort pads according to how recently they were accessed */
    var mostRecent = common.mostRecent = function (a, b) {
        return new Date(b.atime).getTime() - new Date(a.atime).getTime();
    };

    var forgetPad = common.forgetPad = function (href) {
        var recentPads = getRecentPads().filter(function (pad) {
            return pad.href !== href;
        });
        setRecentPads(recentPads);
    };

    var rememberPad = common.rememberPad = window.rememberPad = function (title) {
        // bail out early
        if (!/#/.test(window.location.hash)) { return; }

        var pads = getRecentPads();

        var now = new Date();
        var href = window.location.href;

        var isUpdate = false;

        var out = pads.map(function (pad) {
            if (pad && pad.href === href) {
                isUpdate = true;
                // bump the atime
                pad.atime = now;

                pad.title = title;
            }
            return pad;
        });

        if (!isUpdate) {
            // href, atime, name
            out.push({
                href: href,
                atime: now,
                ctime: now,
                title: title || window.location.hash.slice(1,9),
            });
        }
        setRecentPads(out);
    };

    var setPadTitle = common.setPadTitle = function (name) {
        var href = window.location.href;
        var recent = getRecentPads();

        var renamed = recent.map(function (pad) {
            if (pad.href === href) {
                // update the atime
                pad.atime = new Date().toISOString();

                // set the name
                pad.title = name;
            }
            return pad;
        });

        setRecentPads(renamed);
    };

    var getPadTitle = common.getPadTitle = function () {
        var href = window.location.href;
        var hashSlice = window.location.hash.slice(1,9);
        var title = '';
        getRecentPads().some(function (pad) {
            if (pad.href === href) {
                title = pad.title || hashSlice;
                return true;
            }
        });
        return title;
    };

    var causesNamingConflict = common.causesNamingConflict = function (title) {
        var href = window.location.href;
        return getRecentPads().some(function (pad) {
            return pad.title === title &&
                pad.href !== href;
        });
    };

    var importContent = common.importContent = function (type, f) {
        return function () {
            var $files = $('<input type="file">').click();
            $files.on('change', function (e) {
                var file = e.target.files[0];
                var reader = new FileReader();
                reader.onload = function (e) { f(e.target.result, file); };
                reader.readAsText(file, type);
            });
        };
    };

    var styleAlerts = common.styleAlerts = function (href) {
        href = href || '/customize/alertify.css';
        $('head').append($('<link>', {
            rel: 'stylesheet',
            id: 'alertifyCSS',
            href: href,
        }));
    };

    common.alert = function (msg, cb) {
        Alertify.alert(msg, cb);
    };

    common.prompt = function (msg, def, cb, opt) {
        opt = opt || {};
        Alertify
            .defaultValue(def || '')
            .okBtn(opt.ok || 'OK')
            .cancelBtn(opt.cancel || 'Cancel')
            .prompt(msg, function (val, ev) {
                cb(val, ev);
            }, function (ev) {
                cb(null, ev);
            });
    };

    common.confirm = function (msg, cb, opt) {
        opt = opt || {};
        Alertify
            .okBtn(opt.ok || 'OK')
            .cancelBtn(opt.cancel || 'Cancel')
            .confirm(msg, function () {
                cb(true);
            }, function () {
                cb(false);
            });
    };

    return common;
});
<|endoftext|>


<commit_before>angular.module('ui.bootstrap-slider', [])
    .directive('slider', ['$parse', '$timeout', function ($parse, $timeout) {
        return {
            restrict: 'AE',
            replace: true,
            template: '
<input class="slider-input" type="text" />
',
            require: 'ngModel',
            scope: {
                max: "=",
                min: "=",
                step: "=",
                value: "=",
                ngModel: '=',
                range:'=',
                sliderid:'=',
                formater:'&',
                onStartSlide: '&',
                onStopSlide: '&',
                onSlide: '&'
            },
            link: function ($scope, element, attrs, ngModelCtrl, $compile) {
                initSlider();

                function initSlider() {

                    if (attrs.ngChange) {
                        ngModelCtrl.$viewChangeListeners.push(function () {
                            $scope.$apply(attrs.ngChange);
                        });
                    }

                    $.fn.slider.Constructor.prototype.disable = function () {
                        this.picker.off();
                    };

                    $.fn.slider.Constructor.prototype.enable = function () {
                        this.picker.on();
                    };

                    if (attrs.ngChange) {
                        ngModelCtrl.$viewChangeListeners.push(function () {
                            $scope.$apply(attrs.ngChange);
                        });
                    }

                    var options = {};
                    if ($scope.sliderid) options.id = $scope.sliderid;
                    if ($scope.min) options.min = parseFloat($scope.min);
                    if ($scope.max) {
                        options.max = parseFloat($scope.max);
                    }

                    if (attrs.step) options.step = parseFloat($scope.step);
                    if (attrs.precision) options.precision = parseFloat(attrs.precision);
                    if (attrs.orientation) options.orientation = attrs.orientation;
                    if ($scope.value) {
                        if (angular.isNumber($scope.value) || angular.isArray($scope.value)) {
                            options.value = $scope.value;
                        } else if (angular.isString($scope.value)) {
                            if (attrs.value.indexOf("[") === 0) {
                                options.value = angular.fromJson($scope.value);
                            } else {
                                options.value = parseFloat($scope.value);
                            }
                        }
                    }
                    if ($scope.range) {
                        options.range = $scope.range === true;
                    }

                    if (attrs.selection) options.selection = attrs.selection;
                    if (attrs.tooltip) options.tooltip = attrs.tooltip;
                    if (attrs.tooltipseparator) options.tooltip_separator = attrs.tooltipseparator;
                    if (attrs.tooltipsplit) options.tooltip_split = attrs.tooltipsplit === 'true';
                    if (attrs.handle) options.handle = attrs.handle;
                    if (attrs.reversed) options.reversed = attrs.reversed === 'true';
                    if (attrs.enabled) options.enabled = attrs.enabled === 'true';
                    if (attrs.naturalarrowkeys) options.natural_arrow_keys = attrs.naturalarrowkeys === 'true';
                    if (attrs.formater) options.formater = $scope.$eval($scope.formater);

                    if (options.range && !options.value) {
                        options.value = [0, 0]; // This is needed, because of value defined at $.fn.slider.defaults - default value 5 prevents creating range slider
                    }

                    var slider = $(element.find(".slider-input")[0]).slider(options);
                    slider.slider('destroy');
                    slider = $(element.find(".slider-input")[0]).slider(options);

                    var updateEvent;
                    if (angular.isString(attrs.updateevent)) {
                        // check if array of event names
                        if (attrs.updateevent.indexOf("[") === 0) {
                            updateEvent = angular.fromJson(attrs.updateevent);
                        }
                        else {
                            // if only single event name in string
                            updateEvent = [attrs.updateevent];
                        }
                    }
                    else {
                        // default to slide event
                        updateEvent = ['slide'];
                    }

                    angular.forEach(updateEvent, function(sliderEvent) {
                        slider.on(sliderEvent, function(ev) {
                            ngModelCtrl.$setViewValue(ev.value);
                            $timeout(function() {
                                $scope.$apply();
                            });
                        });
                    });

                    // Event listeners
                    var sliderEvents = {
                        slideStart: 'onStartSlide',
                        slide: 'onSlide',
                        slideStop: 'onStopSlide'
                    };

                    angular.forEach(sliderEvents, function(sliderEventAttr, sliderEvent) {
                        slider.on(sliderEvent, function(ev) {

                            if ($scope[sliderEventAttr]) {
                                var invoker = $parse(attrs[sliderEventAttr]);
                                invoker($scope.$parent, { $event: ev, value: ev.value });

                                $timeout(function() {
                                    $scope.$apply();
                                });
                            }
                        });
                    });

                    if (angular.isDefined(attrs.ngDisabled)) {
                        $scope.$watch(attrs.ngDisabled, function (value) {
                            if (value) {
                                slider.slider('disable');
                            } else {
                                slider.slider('enable');
                            }
                        });
                    }

                    $scope.$watch('ngModel', function(value) {
                        slider.slider('setValue', value);
                    });
                };

                $scope.$watch('max', function(value){
                     initSlider();
                });

                $scope.$watch('min', function(value){
                    initSlider();
                });

                $scope.$watch('step', function(value){
                    initSlider();
                });

                $scope.$watch('range', function(value) {
                    initSlider();
                });
            }
        };
    }])
;
<commit_msg>Follow bootstrap-slider 4.0 change<commit_after>angular.module('ui.bootstrap-slider', [])
    .directive('slider', ['$parse', '$timeout', function ($parse, $timeout) {
        return {
            restrict: 'AE',
            replace: true,
            template: '
<input class="slider-input" type="text" />
',
            require: 'ngModel',
            scope: {
                max: "=",
                min: "=",
                step: "=",
                value: "=",
                ngModel: '=',
                range:'=',
                sliderid:'=',
                formater:'&',
                onStartSlide: '&',
                onStopSlide: '&',
                onSlide: '&'
            },
            link: function ($scope, element, attrs, ngModelCtrl, $compile) {
                initSlider();

                function initSlider() {

                    if (attrs.ngChange) {
                        ngModelCtrl.$viewChangeListeners.push(function () {
                            $scope.$apply(attrs.ngChange);
                        });
                    }

                    $.fn.slider.constructor.prototype.disable = function () {
                        this.picker.off();
                    };

                    $.fn.slider.constructor.prototype.enable = function () {
                        this.picker.on();
                    };

                    if (attrs.ngChange) {
                        ngModelCtrl.$viewChangeListeners.push(function () {
                            $scope.$apply(attrs.ngChange);
                        });
                    }

                    var options = {};
                    if ($scope.sliderid) options.id = $scope.sliderid;
                    if ($scope.min) options.min = parseFloat($scope.min);
                    if ($scope.max) {
                        options.max = parseFloat($scope.max);
                    }

                    if (attrs.step) options.step = parseFloat($scope.step);
                    if (attrs.precision) options.precision = parseFloat(attrs.precision);
                    if (attrs.orientation) options.orientation = attrs.orientation;
                    if ($scope.value) {
                        if (angular.isNumber($scope.value) || angular.isArray($scope.value)) {
                            options.value = $scope.value;
                        } else if (angular.isString($scope.value)) {
                            if (attrs.value.indexOf("[") === 0) {
                                options.value = angular.fromJson($scope.value);
                            } else {
                                options.value = parseFloat($scope.value);
                            }
                        }
                    }
                    if ($scope.range) {
                        options.range = $scope.range === true;
                    }

                    if (attrs.selection) options.selection = attrs.selection;
                    if (attrs.tooltip) options.tooltip = attrs.tooltip;
                    if (attrs.tooltipseparator) options.tooltip_separator = attrs.tooltipseparator;
                    if (attrs.tooltipsplit) options.tooltip_split = attrs.tooltipsplit === 'true';
                    if (attrs.handle) options.handle = attrs.handle;
                    if (attrs.reversed) options.reversed = attrs.reversed === 'true';
                    if (attrs.enabled) options.enabled = attrs.enabled === 'true';
                    if (attrs.naturalarrowkeys) options.natural_arrow_keys = attrs.naturalarrowkeys === 'true';
                    if (attrs.formater) options.formater = $scope.$eval($scope.formater);

                    if (options.range && !options.value) {
                        options.value = [0, 0]; // This is needed, because of value defined at $.fn.slider.defaults - default value 5 prevents creating range slider
                    }

                    var slider = $(element.find(".slider-input")[0]).slider(options);
                    slider.slider('destroy');
                    slider = $(element.find(".slider-input")[0]).slider(options);

                    var updateEvent;
                    if (angular.isString(attrs.updateevent)) {
                        // check if array of event names
                        if (attrs.updateevent.indexOf("[") === 0) {
                            updateEvent = angular.fromJson(attrs.updateevent);
                        }
                        else {
                            // if only single event name in string
                            updateEvent = [attrs.updateevent];
                        }
                    }
                    else {
                        // default to slide event
                        updateEvent = ['slide'];
                    }

                    angular.forEach(updateEvent, function(sliderEvent) {
                        slider.on(sliderEvent, function(ev) {
                            ngModelCtrl.$setViewValue(ev.value);
                            $timeout(function() {
                                $scope.$apply();
                            });
                        });
                    });

                    // Event listeners
                    var sliderEvents = {
                        slideStart: 'onStartSlide',
                        slide: 'onSlide',
                        slideStop: 'onStopSlide'
                    };

                    angular.forEach(sliderEvents, function(sliderEventAttr, sliderEvent) {
                        slider.on(sliderEvent, function(ev) {

                            if ($scope[sliderEventAttr]) {
                                var invoker = $parse(attrs[sliderEventAttr]);
                                invoker($scope.$parent, { $event: ev, value: ev.value });

                                $timeout(function() {
                                    $scope.$apply();
                                });
                            }
                        });
                    });

                    if (angular.isDefined(attrs.ngDisabled)) {
                        $scope.$watch(attrs.ngDisabled, function (value) {
                            if (value) {
                                slider.slider('disable');
                            } else {
                                slider.slider('enable');
                            }
                        });
                    }

                    $scope.$watch('ngModel', function(value) {
                        slider.slider('setValue', value);
                    });
                };

                $scope.$watch('max', function(value){
                     initSlider();
                });

                $scope.$watch('min', function(value){
                    initSlider();
                });

                $scope.$watch('step', function(value){
                    initSlider();
                });

                $scope.$watch('range', function(value) {
                    initSlider();
                });
            }
        };
    }])
;
<|endoftext|>


<commit_before>// chicken.routes.js

// Require appropriate modules
var express = require('express');
var mongoose = require('mongoose');
var bodyParser = require('body-parser');

var ChickenSchema = require('../schemas/chicken.schema').ChickenSchema;

// Get the configuration object
var config = require('../config');

// Create the mongodb connection
var db = mongoose.connect(config.mongoUri, config.mongoOptions).connection;

// Create a connection error callback
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', () => {
  console.log(`Mongoose connected to mongodb @ ${config.mongoUri}`);
});

// Create the mongoose model and instance of the model
var Chicken = mongoose.model('chicken', ChickenSchema);
// Also create a mongoose model for latest chickens
var LatestChicken = mongoose.model('latestchicken', ChickenSchema);

// Get an instance of an express router
var routes = express.Router();

// Configure the express router to use body-parser as middleware to handle post requests
routes.use(bodyParser.urlencoded({ extended: true }));
routes.use(bodyParser.json());

routes.get('/chickens', (req, res) => {
  try {
    // Get the number of elements to retrieve - null should be 0 to get all
    var num = req.query.num == null ? 0 : req.query.num;

    console.log(`This is the number of results to retrieve: ${num}`);
    // Perform a find all with mongoose
    Chicken.find((err, ckns) => {
      // Check for an error case
      if (err != null) {
        console.log(`An error was detected when getting the chickens: ${err}`);
        // Return an error
        res.status(400).json(err);
      } else {
        // Change status to 200 "OK" and chicken the json response
        res.status(200).json(ckns);
      }
    }).limit(Number(num));
  } catch (ex) {
    // Set and send status 500 "Internal Server Error"
    res.status(500).json(JSON.stringify(ex));
  }
});

/**
 * Chicken endpoint for getting the latest cknes
 * @type {Boolean}
 */
routes.get('/chickens/latest', (req, res) => {
  try {
    // Get the number of elements to retrieve - null should be 0 to get all
    var num = req.query.num == null ? 0 : req.query.num;

    LatestChicken.find((err, chickens) => {
      // Check for an error case
      if (err != null) {
        console.log(`An error was detected when getting the latest chickens: ${err}`);
        // Return an error
        res.status(400).json(err);
      } else {
        // Change status to 200 "OK" and chicken the json response
        res.status(200).json(chickens);
      }
    })
  } catch (err) {
      // Set and send status 500 "Internal Server Error"
      res.status(500).json(JSON.stringify(err));
  }
});

/**
 * Chickens endpoint for getting all Chickens of a particular id
 * @type {Boolean}
 */
routes.get('/chickens/:name', (req, res) => {
  try {
    var name = req.params.name;
    console.log(`This is the id we got! name: ${name}`);
    // Get the number of elements to retrieve - null should be 0 to get all
    var num = req.query.num == null ? 0 : req.query.num;
    console.log(`This is the number of results to retrieve: ${num}`);
    // Make sure we were given a name to query
    if (name) {
      // Perform a find on the name
      Chicken.find({ name: name }, (err, ckns) => {
        // Check for an error case
        if (err != null) {
          console.log(`An error was detected when getting the chickens: ${err}`);
          // Return an error
          res.status(400).json(err);
        } else {
          // Change status to 200 "OK" and chicken the json response
          res.status(200).json(ckns);
        }
      }).sort({ time: 'descending' }).limit(Number(num));
    } else {
      // Set and send status 400 "Bad Request"
      res.status(400).send('A name parameter must be provided.');
    }
  } catch (ex) {
    console.log(ex);
    // Set and send status 400 "Bad Request"
    res.status(400).json(JSON.stringify(ex));
  }
});

// Register post request
routes.post('/chickens', (req, res) => {
  // The request should be able to be cast to type Chicken
  try {
    // Instantiate a new Chicken with given json
    var ckn = new Chicken(req.body);
    console.log('Finalized chicken: ' + JSON.stringify(ckn));
    // Insert the Chicken into the store
    //TODO: Add type checking to ensure we are putting in our base Chicken prototype (at least)
    ckn.save((err, ckn) => {
      if (err != null) {
        console.log(`An error was detected when saving the chicken: ${err}`)
        // Return an error
        res.status(400).json(JSON.stringify(err));
      } else {
        // Change status to 201 "Created"
        res.status(201).send();
      }
    });

  } catch (e) {
    console.log('Houston - We have a problemo...');
    // The user's request was bad - send 400 "Bad Request"
    res.status(400).json(JSON.stringify(e));
  }
});

/**
 * Performs a map-reduce on the chicken collection and stores the result
 * in the latestchicken collection
 */
function reduceChickens() {
  // Set reducing to true
  this.reducing = true;
  // Instantiate the map reduce function in an object
  var mapReduce = {};
  // Create the map function (name -> ckn)
  mapReduce.map = function() {
    emit(this.name, this);
  }
  // Create the reduce function (Only return the latest ckn objects)
  mapReduce.reduce = function(name, chickens) {
    // Iterate through the chickens, searching for the latest chicken
    // We're assuming it was a min heap (implemented as array it would be at the last index)
    var latest = chickens[chickens.length - 1];
    // We can skip the first box
    // for (var i = 1; i < ckns.length; i++) {
    //   if (ckns[i].time > latest.time) {
    //     latest = ckns[i];
    //   }
    // }

    // Return the latest ckn
    return latest;
  }

  // Perform a find all with mongoose
  Chicken.mapReduce(mapReduce, (err, reduction) => {
    try {
      console.log(`Map reduce reduction: ${JSON.stringify(reduction)}`);
      // Check for an error case
      if (err) {
        // Set reducing to false
        this.reducing = false;
        console.log(`An error was detected when performing a map-reduce
          ${err}`);
      } else {
        // Collect each value from the id-value tuples in the reduction array
        var latest = [];
        for (r of reduction) {
          latest.push(new LatestChicken(r.value));
        }
        // Delete everything in the latestchicken collection
        LatestChicken.remove({}, (err) => {
          if(err) {
            console.log(`An error occured while attempting to remove all elements
              from the latestchicken collection\n${err}`);
          }
          // Attempt to add the new latest to the collection
          for (chicken of latest) {
            chicken.save();
          }
          // Set reducing to false
          this.reducing = false;
          console.log('Map-reduce completed!');
        });
      }
    } catch (err) {
      // Set reducing to false
      this.reducing = false;
      console.log(`An error was detected when updating the latestchicken collection
        ${err}`);
    }

  });
}

// Define the requested and reducing flags on the reduceChickens function
reduceChickens.requested = false;
reduceChickens.reducing = false

// Create an interval for the chickens to be reduced on
var reductionInterval = interval(config.reductionDT, () => {
  // Check if a reduce has been requested and one is not currently running
  if (reduceChickens.requested && !reduceChickens.reducing) {
    // Set requested to false
    reduceChickens.requested = false;
    // Reduce the chickens
    reduceChickens();
  }
});

// Export the routes as an unnamed object
module.exports = routes;
<commit_msg>Corrected interval syntax<commit_after>// chicken.routes.js

// Require appropriate modules
var express = require('express');
var mongoose = require('mongoose');
var bodyParser = require('body-parser');

var ChickenSchema = require('../schemas/chicken.schema').ChickenSchema;

// Get the configuration object
var config = require('../config');

// Create the mongodb connection
var db = mongoose.connect(config.mongoUri, config.mongoOptions).connection;

// Create a connection error callback
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', () => {
  console.log(`Mongoose connected to mongodb @ ${config.mongoUri}`);
});

// Create the mongoose model and instance of the model
var Chicken = mongoose.model('chicken', ChickenSchema);
// Also create a mongoose model for latest chickens
var LatestChicken = mongoose.model('latestchicken', ChickenSchema);

// Get an instance of an express router
var routes = express.Router();

// Configure the express router to use body-parser as middleware to handle post requests
routes.use(bodyParser.urlencoded({ extended: true }));
routes.use(bodyParser.json());

routes.get('/chickens', (req, res) => {
  try {
    // Get the number of elements to retrieve - null should be 0 to get all
    var num = req.query.num == null ? 0 : req.query.num;

    console.log(`This is the number of results to retrieve: ${num}`);
    // Perform a find all with mongoose
    Chicken.find((err, ckns) => {
      // Check for an error case
      if (err != null) {
        console.log(`An error was detected when getting the chickens: ${err}`);
        // Return an error
        res.status(400).json(err);
      } else {
        // Change status to 200 "OK" and chicken the json response
        res.status(200).json(ckns);
      }
    }).limit(Number(num));
  } catch (ex) {
    // Set and send status 500 "Internal Server Error"
    res.status(500).json(JSON.stringify(ex));
  }
});

/**
 * Chicken endpoint for getting the latest cknes
 * @type {Boolean}
 */
routes.get('/chickens/latest', (req, res) => {
  try {
    // Get the number of elements to retrieve - null should be 0 to get all
    var num = req.query.num == null ? 0 : req.query.num;

    LatestChicken.find((err, chickens) => {
      // Check for an error case
      if (err != null) {
        console.log(`An error was detected when getting the latest chickens: ${err}`);
        // Return an error
        res.status(400).json(err);
      } else {
        // Change status to 200 "OK" and chicken the json response
        res.status(200).json(chickens);
      }
    })
  } catch (err) {
      // Set and send status 500 "Internal Server Error"
      res.status(500).json(JSON.stringify(err));
  }
});

/**
 * Chickens endpoint for getting all Chickens of a particular id
 * @type {Boolean}
 */
routes.get('/chickens/:name', (req, res) => {
  try {
    var name = req.params.name;
    console.log(`This is the id we got! name: ${name}`);
    // Get the number of elements to retrieve - null should be 0 to get all
    var num = req.query.num == null ? 0 : req.query.num;
    console.log(`This is the number of results to retrieve: ${num}`);
    // Make sure we were given a name to query
    if (name) {
      // Perform a find on the name
      Chicken.find({ name: name }, (err, ckns) => {
        // Check for an error case
        if (err != null) {
          console.log(`An error was detected when getting the chickens: ${err}`);
          // Return an error
          res.status(400).json(err);
        } else {
          // Change status to 200 "OK" and chicken the json response
          res.status(200).json(ckns);
        }
      }).sort({ time: 'descending' }).limit(Number(num));
    } else {
      // Set and send status 400 "Bad Request"
      res.status(400).send('A name parameter must be provided.');
    }
  } catch (ex) {
    console.log(ex);
    // Set and send status 400 "Bad Request"
    res.status(400).json(JSON.stringify(ex));
  }
});

// Register post request
routes.post('/chickens', (req, res) => {
  // The request should be able to be cast to type Chicken
  try {
    // Instantiate a new Chicken with given json
    var ckn = new Chicken(req.body);
    console.log('Finalized chicken: ' + JSON.stringify(ckn));
    // Insert the Chicken into the store
    //TODO: Add type checking to ensure we are putting in our base Chicken prototype (at least)
    ckn.save((err, ckn) => {
      if (err != null) {
        console.log(`An error was detected when saving the chicken: ${err}`)
        // Return an error
        res.status(400).json(JSON.stringify(err));
      } else {
        // Change status to 201 "Created"
        res.status(201).send();
      }
    });

  } catch (e) {
    console.log('Houston - We have a problemo...');
    // The user's request was bad - send 400 "Bad Request"
    res.status(400).json(JSON.stringify(e));
  }
});

/**
 * Performs a map-reduce on the chicken collection and stores the result
 * in the latestchicken collection
 */
function reduceChickens() {
  // Set reducing to true
  this.reducing = true;
  // Instantiate the map reduce function in an object
  var mapReduce = {};
  // Create the map function (name -> ckn)
  mapReduce.map = function() {
    emit(this.name, this);
  }
  // Create the reduce function (Only return the latest ckn objects)
  mapReduce.reduce = function(name, chickens) {
    // Iterate through the chickens, searching for the latest chicken
    // We're assuming it was a min heap (implemented as array it would be at the last index)
    var latest = chickens[chickens.length - 1];
    // We can skip the first box
    // for (var i = 1; i < ckns.length; i++) {
    //   if (ckns[i].time > latest.time) {
    //     latest = ckns[i];
    //   }
    // }

    // Return the latest ckn
    return latest;
  }

  // Perform a find all with mongoose
  Chicken.mapReduce(mapReduce, (err, reduction) => {
    try {
      console.log(`Map reduce reduction: ${JSON.stringify(reduction)}`);
      // Check for an error case
      if (err) {
        // Set reducing to false
        this.reducing = false;
        console.log(`An error was detected when performing a map-reduce
          ${err}`);
      } else {
        // Collect each value from the id-value tuples in the reduction array
        var latest = [];
        for (r of reduction) {
          latest.push(new LatestChicken(r.value));
        }
        // Delete everything in the latestchicken collection
        LatestChicken.remove({}, (err) => {
          if(err) {
            console.log(`An error occured while attempting to remove all elements
              from the latestchicken collection\n${err}`);
          }
          // Attempt to add the new latest to the collection
          for (chicken of latest) {
            chicken.save();
          }
          // Set reducing to false
          this.reducing = false;
          console.log('Map-reduce completed!');
        });
      }
    } catch (err) {
      // Set reducing to false
      this.reducing = false;
      console.log(`An error was detected when updating the latestchicken collection
        ${err}`);
    }

  });
}

// Define the requested and reducing flags on the reduceChickens function
reduceChickens.requested = false;
reduceChickens.reducing = false

// Create an interval for the chickens to be reduced on
var reductionInterval = setInterval(() => {
  // Check if a reduce has been requested and one is not currently running
  if (reduceChickens.requested && !reduceChickens.reducing) {
    // Set requested to false
    reduceChickens.requested = false;
    // Reduce the chickens
    reduceChickens();
  }
}, config.reductionDT);

// Export the routes as an unnamed object
module.exports = routes;
<|endoftext|>


<commit_before>const path = require('path');

// Initial map location for new users and visitors.
exports.defaultMapState = {
  lat: 57.5727427,
  lng: 21.8783527,
  zoom: 13,
  mapTypeId: 'hybrid', // 'roadmap', 'satellite', 'hybrid', or 'terrain'
};

// Login screen mode
exports.loginPageSize = 'full'; // or 'medium' to show the map.
// Login screen background image. The first thing the user experiences.
// The image will be copied to a public location on start up.
// Use only an absolute path.
exports.loginBackground = path.join(__dirname, 'images/login-background.jpg');
// A color scheme for buttons and progress bars on the login page.
// The possible values are the contextual color from Bootstrap 3:
// 'muted', 'primary', 'success', 'info', 'warning', 'danger'
exports.loginColor = 'primary';
<commit_msg>improve config landing docs<commit_after>const path = require('path');

// Initial map location for new users and visitors.
exports.defaultMapState = {
  lat: 57.5727427,
  lng: 21.8783527,
  zoom: 13,
  mapTypeId: 'hybrid', // 'roadmap', 'satellite', 'hybrid', or 'terrain'
};

// Login screen mode
exports.loginPageSize = 'full'; // 'full', 'medium', or 'small'
// Login screen background image. The first thing the user experiences.
// The image will be copied to a public location on start up.
// Use only an absolute path.
exports.loginBackground = path.join(__dirname, 'images/login-background.jpg');
// A color scheme for buttons and progress bars on the login page.
// The possible values are the contextual color from Bootstrap 3:
// 'muted', 'primary', 'success', 'info', 'warning', 'danger'
exports.loginColor = 'primary';
<|endoftext|>


<commit_before>/*
  This file is part of the Jasmine JSReporter project from Ivan De Marino.

  Copyright (C) 2011 Ivan De Marino (aka detro, aka detronizator), http://blog.ivandemarino.me, ivan.de.marino@gmail.com

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the name of the <organization> nor the
      names of its contributors may be used to endorse or promote products
      derived from this software without specific prior written permission.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  ARE DISCLAIMED. IN NO EVENT SHALL IVAN DE MARINO BE LIABLE FOR ANY
  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

(function () {
    // Ensure that Jasmine library is loaded first
    if (!jasmine) {
        throw new Exception("[Jasmine JSReporter] 'Jasmine' library not found");
    }

    /**
     * Calculate elapsed time, in Seconds.
     * @param startMs Start time in Milliseconds
     * @param finishMs Finish time in Milliseconds
     * @return Elapsed time in Seconds */
    function elapsedSec (startMs, finishMs) {
        return (finishMs - startMs) / 1000;
    }

    /**
     * Round an amount to the given number of Digits.
     * If no number of digits is given, than '2' is assumed.
     * @param amount Amount to round
     * @param numOfDecDigits Number of Digits to round to. Default value is '2'.
     * @return Rounded amount */
    function round (amount, numOfDecDigits) {
        numOfDecDigits = numOfDecDigits || 2;
        return Math.round(amount * Math.pow(10, numOfDecDigits)) / Math.pow(10, numOfDecDigits);
    }

    /**
     * Collect information about a Suite, recursively, and return a JSON result.
     * @param suite The Jasmine Suite to get data from
     */
    function getSuiteData (suite) {
        var suiteData = {
                description : suite.description,
                durationSec : 0,
                specs: [],
                suites: [],
                passed: true,
                total: 0,
                failed: 0
            },
            specs = suite.specs(),
            suites = suite.suites(),
            i, ilen;

        // Loop over all the Suite's Specs
        for (i = 0, ilen = specs.length; i < ilen; ++i) {
            var spec = specs[i];
            var r = spec.results();
            suiteData.specs[i] = {
                description : spec.description,
                durationSec : spec.durationSec,
                passed : r.passedCount === r.totalCount,
                skipped : r.skipped,
                passedCount : r.passedCount,
                failedCount : r.failedCount,
                totalCount : r.totalCount
            };
            if (r.passedCount != r.totalCount) {
                var msgs = [];
                r.getItems().forEach(function(item) {
                    if (!item.passed_) msgs.push(spec.getFullName() + ': ' + item.message);
                });
                suiteData.specs[i].failures = msgs;
            }
            suiteData.total += r.totalCount;
            suiteData.failed += r.failedCount;
            suiteData.passed = !suiteData.specs[i].passed ? false : suiteData.passed;
            suiteData.durationSec += suiteData.specs[i].durationSec;
        }

        // Loop over all the Suite's sub-Suites
        for (i = 0, ilen = suites.length; i < ilen; ++i) {
            suiteData.suites[i] = getSuiteData(suites[i]); //< recursive population
            suiteData.passed = !suiteData.suites[i].passed ? false : suiteData.passed;
            suiteData.durationSec += suiteData.suites[i].durationSec;
            suiteData.total += suiteData.suites[i].total;
            suiteData.failed += suiteData.suites[i].failed;
        }

        // Rounding duration numbers to 3 decimal digits
        suiteData.durationSec = round(suiteData.durationSec, 4);

        return suiteData;
    }

    var platformMap = {
        'ipod touch':'ios'
    };

    var JSReporter =  function (server) {
        this.server = server;
    };

    JSReporter.prototype = {
        reportRunnerStarting: function (runner) {
            // Nothing to do
        },

        reportSpecStarting: function (spec) {
            // Start timing this spec
            spec.startedAt = new Date();
        },

        reportSpecResults: function (spec) {
            // Finish timing this spec and calculate duration/delta (in sec)
            spec.finishedAt = new Date();
            spec.durationSec = elapsedSec(spec.startedAt.getTime(), spec.finishedAt.getTime());
        },

        reportSuiteResults: function (suite) {
            // Nothing to do
        },

        reportRunnerResults: function (runner) {
            var suites = runner.suites(),
                i, ilen;

            // Attach results to the "jasmine" object to make those results easy to scrap/find
            jasmine.runnerResults = {
                suites: [],
                durationSec : 0,
                passed : true,
                total: 0,
                failed: 0
            };

            // Loop over all the Suites
            for (i = 0, ilen = suites.length; i < ilen; ++i) {
                if (suites[i].parentSuite === null) {
                    jasmine.runnerResults.suites.push(getSuiteData(suites[i]));
                    var l = jasmine.runnerResults.suites.length;
                    // If 1 suite fails, the whole runner fails
                    var last = jasmine.runnerResults.suites[l-1];
                    jasmine.runnerResults.passed = !last.passed ? false : jasmine.runnerResults.passed;
                    // Add up all the durations
                    jasmine.runnerResults.durationSec += last.durationSec;
                    jasmine.runnerResults.total += last.total;
                    jasmine.runnerResults.failed += last.failed;
                }
            }

            var p = device.platform.toLowerCase();

            this.postTests({
                mobilespec:jasmine.runnerResults,
                sha:library_sha,
                platform:(platformMap.hasOwnProperty(p) ? platformMap[p] : p),
                version:device.version.toLowerCase(),
                timestamp:Math.floor((new Date()).getTime() / 1000),
                model:device.model || device.name
            });
        },
        postTests: function(json) {
            console.log('posting tests');
            var xhr = new XMLHttpRequest();
            var doc_id = [json.platform, library_sha, json.version, json.model].map(encodeURIComponent).join('__');
            var doc_url = this.server + '/mobilespec_results/' + doc_id;
            xhr.open("PUT", doc_url, true);
            xhr.onreadystatechange=function() {
                console.log('onreadystatechange');
                if (xhr.readyState==4) {
                    console.log('readystate==4, status: ' + xhr.status);
                    if (xhr.status==201) {
                        // HTTP 201 Created
                        // we added the doc, hooray
                        console.log('>>> DONE <<<');
                    } else if (xhr.status == 409) {
                        console.log('conflict on couch');
                        // HTTP 409 Conflict
                        // doc already exists. now let's GET it, grab the rev, delete it, and try again.
                        var exehar = new XMLHttpRequest();
                        exehar.open('GET', doc_url, true);
                        exehar.onreadystatechange=function() {
                            if (exehar.readyState==4) {
                                if (exehar.status==200) {
                                    var existing_doc = JSON.parse(exehar.responseText);
                                    var rev = existing_doc._rev;
                                    var eksatschargh = new XMLHttpRequest();
                                    eksatschargh.open('DELETE', doc_url + '?rev=' + rev, true);
                                    eksatschargh.onreadystatechange=function() {
                                        if (eksatschargh.readyState==4) {
                                            if (eksatschargh.status==200) {
                                                var x_h_r = new XMLHttpRequest();
                                                x_h_r.open('PUT', doc_url, true);
                                                x_h_r.onreadystatechange=function() {
                                                    if (x_h_r.readyState==4) {
                                                        if (x_h_r.status==201) {
                                                            console.log('>>> DONE <<<');
                                                        } else {
                                                            console.log('the round trip delete+create failed. i give up. status was: ' + x_h_r.status);
                                                            console.log(x_h_r.responseText);
                                                        }
                                                    }
                                                };
                                                x_h_r.send(JSON.stringify(json));
                                            } else {
                                                console.log('look, we tried to add the results to couch. it said it alrady exists. now im trying to DELETE it. it fucked up. wtf. status on the DELETE: ' + eksatschargh.status);
                                            }
                                        }
                                    };
                                    eksatschargh.send(null);
                                } else {
                                    console.log('look, we tried to add the results to couch. it said it alrady exists. now im trying to GET it so i can DELETE it. it fucked up. wtf. status on the GET: ' + exehar.status);
                                }
                            }
                        };
                        exehar.send(null);
                    } else {
                        console.log('some crazy shit happened. couch returned some balltastic info. status code: ' + xhr.status);
                        console.log(xhr.responseText);
                    }
                }
            };
            xhr.send(JSON.stringify(json));
        },
    };

    // export public
    jasmine.JSReporter = JSReporter;
})();

<commit_msg>better rolling up of jasmine data<commit_after>/*
  This file is part of the Jasmine JSReporter project from Ivan De Marino.

  Copyright (C) 2011 Ivan De Marino (aka detro, aka detronizator), http://blog.ivandemarino.me, ivan.de.marino@gmail.com

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the name of the <organization> nor the
      names of its contributors may be used to endorse or promote products
      derived from this software without specific prior written permission.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  ARE DISCLAIMED. IN NO EVENT SHALL IVAN DE MARINO BE LIABLE FOR ANY
  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

(function () {
    // Ensure that Jasmine library is loaded first
    if (!jasmine) {
        throw new Exception("[Jasmine JSReporter] 'Jasmine' library not found");
    }

    /**
     * Calculate elapsed time, in Seconds.
     * @param startMs Start time in Milliseconds
     * @param finishMs Finish time in Milliseconds
     * @return Elapsed time in Seconds */
    function elapsedSec (startMs, finishMs) {
        return (finishMs - startMs) / 1000;
    }

    var platformMap = {
        'ipod touch':'ios'
    };

    var JSReporter =  function (server) {
        this.server = server;
    };

    JSReporter.prototype = {
        reportRunnerStarting: function (runner) {
            // Attach results to the "jasmine" object to make those results easy to scrap/find
            jasmine.runnerResults = {
                failures: [],
                durationSec : 0,
                passed : true,
                total: 0,
                failed: 0
            };
        },

        reportSpecStarting: function (spec) {
            // Start timing this spec
            spec.startedAt = new Date();
        },

        reportSpecResults: function (spec) {
            // Finish timing this spec and calculate duration/delta (in sec)
            spec.finishedAt = new Date();
            spec.durationSec = elapsedSec(spec.startedAt.getTime(), spec.finishedAt.getTime());
            jasmine.runnerResults.durationSec += spec.durationSec;
            jasmine.runnerResults.total++;
            var results = jasmine.runnerResults.results();
            var failed = results.passed();
            if (failed) {
                var failure = {spec:spec.getFullName(),assertions:[]};
                jasmine.runnerResults.failed++;
                failed.getItems().forEach(function(item) {
                    if (!item.passed) {
                        failure.assertions.push({exception:item.message,trace:item.trace.stack});
                    }
                });
                jasmine.runnerResults.failures.push(failure);
            }
        },

        reportSuiteResults: function (suite) {
            // Nothing to do
        },

        reportRunnerResults: function (runner) {
            var p = device.platform.toLowerCase();

            this.postTests({
                mobilespec:jasmine.runnerResults,
                sha:library_sha,
                platform:(platformMap.hasOwnProperty(p) ? platformMap[p] : p),
                version:device.version.toLowerCase(),
                timestamp:Math.round(Math.floor((new Date()).getTime() / 1000)),
                model:device.model || device.name
            });
        },
        postTests: function(json) {
            console.log('posting tests');
            var xhr = new XMLHttpRequest();
            var doc_id = [json.platform, library_sha, json.version, json.model].map(encodeURIComponent).join('__');
            var doc_url = this.server + '/mobilespec_results/' + doc_id;
            xhr.open("PUT", doc_url, true);
            xhr.onreadystatechange=function() {
                console.log('onreadystatechange');
                if (xhr.readyState==4) {
                    console.log('readystate==4, status: ' + xhr.status);
                    if (xhr.status==201) {
                        // HTTP 201 Created
                        // we added the doc, hooray
                        console.log('>>> DONE <<<');
                    } else if (xhr.status == 409) {
                        console.log('conflict on couch');
                        // HTTP 409 Conflict
                        // doc already exists. now let's GET it, grab the rev, delete it, and try again.
                        var exehar = new XMLHttpRequest();
                        exehar.open('GET', doc_url, true);
                        exehar.onreadystatechange=function() {
                            if (exehar.readyState==4) {
                                if (exehar.status==200) {
                                    var existing_doc = JSON.parse(exehar.responseText);
                                    var rev = existing_doc._rev;
                                    var eksatschargh = new XMLHttpRequest();
                                    eksatschargh.open('DELETE', doc_url + '?rev=' + rev, true);
                                    eksatschargh.onreadystatechange=function() {
                                        if (eksatschargh.readyState==4) {
                                            if (eksatschargh.status==200) {
                                                var x_h_r = new XMLHttpRequest();
                                                x_h_r.open('PUT', doc_url, true);
                                                x_h_r.onreadystatechange=function() {
                                                    if (x_h_r.readyState==4) {
                                                        if (x_h_r.status==201) {
                                                            console.log('>>> DONE <<<');
                                                        } else {
                                                            console.log('the round trip delete+create failed. i give up. status was: ' + x_h_r.status);
                                                            console.log(x_h_r.responseText);
                                                        }
                                                    }
                                                };
                                                x_h_r.send(JSON.stringify(json));
                                            } else {
                                                console.log('look, we tried to add the results to couch. it said it alrady exists. now im trying to DELETE it. it fucked up. wtf. status on the DELETE: ' + eksatschargh.status);
                                            }
                                        }
                                    };
                                    eksatschargh.send(null);
                                } else {
                                    console.log('look, we tried to add the results to couch. it said it alrady exists. now im trying to GET it so i can DELETE it. it fucked up. wtf. status on the GET: ' + exehar.status);
                                }
                            }
                        };
                        exehar.send(null);
                    } else {
                        console.log('some crazy shit happened. couch returned some balltastic info. status code: ' + xhr.status);
                        console.log(xhr.responseText);
                    }
                }
            };
            xhr.send(JSON.stringify(json));
        },
    };

    // export public
    jasmine.JSReporter = JSReporter;
})();

<|endoftext|>


<commit_before>import React from 'react';
import {
  StyleSheet,
  View,
  KeyboardAvoidingView,
  Text,
  TextInput,
  Platform,
  StatusBar,
  Image,
  TouchableOpacity,
  ScrollView,
} from 'react-native';

import { Actions } from 'react-native-router-flux';
import PropTypes from 'prop-types';
import AppUtil from '../lib/util';

import { Alerts, Spacer, Button } from '../components/ui/';
import Network from '../network';
import t from '../i18n';
import { AppColors, AppStyles } from '../theme/';
import Application from '../constants/config';

const styles = StyleSheet.create({
  messageContainer: {
    flex: 1,
    flexDirection: 'column',
    justifyContent: 'center',
    alignItems: 'center',
    marginBottom: (Platform.OS === 'ios') ? 16 : 0,
  },
  textInput: {
    backgroundColor: '#F5F5F5',
    borderRadius: 5,
    padding: 10,
    height: 40,
    flex: 1,
    fontSize: 16,
  },
  viewContainer: {
    flex: 1,
    flexDirection: 'row',
    justifyContent: 'center',
    alignItems: 'center',
    padding: 15,
  },
  logo: { opacity: 1 },
  loadText: {
    fontSize: 14,
    color: 'rgba(255,255,255,0.7)',
  },
  centerAll: {
    flexDirection: 'column',
    justifyContent: 'center',
    alignItems: 'center',
  },
  workspace: { color: '#FFF', fontSize: 16 },
});

export default class SelectServer extends React.Component {
  constructor(props) {
    super(props);
    this._service = new Network();
    this._mounted = false;
    const switchServer = props.switchServer;
    this.state = {
      isLoading: true,
      loadText: t('loading'),
      switchServer,
      serverUrl: '',
      resultMsg: {
        status: '',
        success: '',
        error: '',
      },
    };
  }

  componentDidMount() {
    this._service.onLogin(() => {
      if (this._mounted && this._service.service.loggedInUser) {
//        this._service.switchToLoggedInUser();
        Actions.app({ type: 'reset' });
      }
    });
    // Get server name
    setTimeout(() => {
      if (this._mounted) {
        const serverUrl = this._service.getServer();
        if (serverUrl && !this.state.switchServer) {
          Application.resetInstance(serverUrl);
          this.connectToServer(serverUrl);
        } else {
          this.setState({ isLoading: false });
        }
      }
    }, 100);
    this._mounted = true;
  }

  componentWillUnmount() {
    this._mounted = false;
  }

  settingsCallback = (err/* , data */) => {
    if (this._mounted) {
      if (err) {
        // error, no settings could be fetched
        this.setState({ isLoading: false });
      } else {
        Actions.login({ type: 'reset' });
      }
    }
  }

  connectToServer(serverUrl) {
    AppUtil.debug(new Date().toLocaleString(), '[Performance] SelectServer');
    this._service.setServer(serverUrl, this.settingsCallback);
    if (this._service.db.realm) {
      // data base loaded, lets go straight to home
      Actions.app({ type: 'reset' });
      return;
    }
    // if login happens before timeout, switch gears to logged in screen
    const loadStrings = [
      t('loading_text_init_screens'),
      t('loading_text_conn_to_server'),
      t('loading_text_still_reaching'),
      t('dots'),
    ];
    // don't increase this timeout as this would impact the experience of folks
    // who are logging in for the first time
    for (let i = 0; i < loadStrings.length; i += 1) {
      setTimeout(() => {
        if (this._mounted) {
          if (i === loadStrings.length - 1) {
            if (!this._service.isConnected) {
              // we should throw exception to user and ask to selectserver
              this.setState({ isLoading: false });
            }
          }
          this.setState({
            loadText: loadStrings[i],
          });
        }
      }, (2000 * (i + 1)));
    }
  }

  sendServerUrl = () => {
    const inputServerVal = this.state.serverUrl ? this.state.serverUrl.trim() : undefined;
    // inputServerVal = inputServerVal.trim();
    // Validation for alphanumeric, dash and dots
    if (inputServerVal) {
//      inputServerVal = inputServerVal.replace(`.${Application.brandName}`, '');
      const regexp = /^[a-zA-Z0-9-.]+$/;
      if (regexp.test(inputServerVal)) {
        Application.resetInstance(inputServerVal);
        this.setState({
          isLoading: true,
          resultMsg: {
            status: '',
            success: '',
            error: '',
          },
        });
        this.connectToServer(Application.instance);
      } else {
        this.setState({ resultMsg: { error: t('err_enter_valid_workspace') } });
      }
    } else {
      this.setState({ resultMsg: { error: t('err_workspace_name_empty') } });
    }
  };

  render() {
    return (
      <View
        style={[styles.viewContainer, { backgroundColor: AppColors.brand().secondary }]}
        testID={'welcome'}
      >
        <StatusBar barStyle="light-content" />
        {this.state.isLoading === true &&
        <View style={[AppStyles.windowSize, AppStyles.containerCentered]}>
          <Image
            source={Application.logo}
            style={[AppStyles.loginLogoSplash, styles.logo]}
          />
          <Text
            style={[styles.loadText, AppStyles.baseFont]}
          >{this.state.loadText}</Text>
        </View>
        }
        {this.state.isLoading === false &&
        <ScrollView
          keyboardShouldPersistTaps={'handled'}
        >
          <KeyboardAvoidingView
            behavior={'position'}
            style={styles.messageContainer}
          >
            <View style={[AppStyles.row]}>
              <View style={[styles.centerAll]}>
                <Image
                  source={Application.logo}
                  style={[AppStyles.loginLogoSplash]}
                />
                <Alerts
                  error={this.state.resultMsg.error}
                />
                <Text style={
                [AppStyles.ListItemTitle, styles.workspace]
                }
                >{t('lbl_enter_your_workspace')}</Text>
              </View>
            </View>
            <View style={[AppStyles.row]}>
              <View style={[AppStyles.flex1, { height: 40 }]}>
                <TextInput
                  placeholder={`[workspace].${Application.brandName}`}
                  autoCapitalize={'none'}
                  style={[styles.textInput, AppStyles.baseFont]}
                  onChangeText={(text) => { this.setState({ serverUrl: text }); }}
                  value={this.state.serverUrl}
                  underlineColorAndroid={'transparent'}
                  autoCorrect={false}
                />
              </View>
            </View>
            <Spacer size={20} />
            <View style={[AppStyles.row]}>
              <View style={[AppStyles.flex1]}>
                <Button
                  title={t('confirm')}
                  onPress={this.sendServerUrl}
                  backgroundColor="transparent"
                  testID={'select-server'}
                />
              </View>
            </View>
            <View style={[AppStyles.row, { alignItems: 'center', justifyContent: 'center' }]}>
              <TouchableOpacity
                style={{
                  borderWidth: 1,
                  paddingHorizontal: 15,
                  paddingVertical: 2,
                  marginTop: 20,
                  borderColor: '#fff',
                  borderRadius: 3,
                  alignItems: 'center',
                  justifyContent: 'center',
                }}
                onPress={() => Actions.pop({ type: 'reset' })}
              >
                <Text
                  style={[AppStyles.ListItemTitle, styles.workspace]}
                >{t('txt_back')}</Text>
              </TouchableOpacity>
            </View>
          </KeyboardAvoidingView>
          </ScrollView>
        }
      </View>
    );
  }
}

SelectServer.defaultProps = {
  switchServer: false,
};

SelectServer.propTypes = {
  switchServer: PropTypes.bool,
};
<commit_msg>testId params for back button<commit_after>import React from 'react';
import {
  StyleSheet,
  View,
  KeyboardAvoidingView,
  Text,
  TextInput,
  Platform,
  StatusBar,
  Image,
  TouchableOpacity,
  ScrollView,
} from 'react-native';

import { Actions } from 'react-native-router-flux';
import PropTypes from 'prop-types';
import AppUtil from '../lib/util';

import { Alerts, Spacer, Button } from '../components/ui/';
import Network from '../network';
import t from '../i18n';
import { AppColors, AppStyles } from '../theme/';
import Application from '../constants/config';

const styles = StyleSheet.create({
  messageContainer: {
    flex: 1,
    flexDirection: 'column',
    justifyContent: 'center',
    alignItems: 'center',
    marginBottom: (Platform.OS === 'ios') ? 16 : 0,
  },
  textInput: {
    backgroundColor: '#F5F5F5',
    borderRadius: 5,
    padding: 10,
    height: 40,
    flex: 1,
    fontSize: 16,
  },
  viewContainer: {
    flex: 1,
    flexDirection: 'row',
    justifyContent: 'center',
    alignItems: 'center',
    padding: 15,
  },
  logo: { opacity: 1 },
  loadText: {
    fontSize: 14,
    color: 'rgba(255,255,255,0.7)',
  },
  centerAll: {
    flexDirection: 'column',
    justifyContent: 'center',
    alignItems: 'center',
  },
  workspace: { color: '#FFF', fontSize: 16 },
});

export default class SelectServer extends React.Component {
  constructor(props) {
    super(props);
    this._service = new Network();
    this._mounted = false;
    const switchServer = props.switchServer;
    this.state = {
      isLoading: true,
      loadText: t('loading'),
      switchServer,
      serverUrl: '',
      resultMsg: {
        status: '',
        success: '',
        error: '',
      },
    };
  }

  componentDidMount() {
    this._service.onLogin(() => {
      if (this._mounted && this._service.service.loggedInUser) {
//        this._service.switchToLoggedInUser();
        Actions.app({ type: 'reset' });
      }
    });
    // Get server name
    setTimeout(() => {
      if (this._mounted) {
        const serverUrl = this._service.getServer();
        if (serverUrl && !this.state.switchServer) {
          Application.resetInstance(serverUrl);
          this.connectToServer(serverUrl);
        } else {
          this.setState({ isLoading: false });
        }
      }
    }, 100);
    this._mounted = true;
  }

  componentWillUnmount() {
    this._mounted = false;
  }

  settingsCallback = (err/* , data */) => {
    if (this._mounted) {
      if (err) {
        // error, no settings could be fetched
        this.setState({ isLoading: false });
      } else {
        Actions.login({ type: 'reset' });
      }
    }
  }

  connectToServer(serverUrl) {
    AppUtil.debug(new Date().toLocaleString(), '[Performance] SelectServer');
    this._service.setServer(serverUrl, this.settingsCallback);
    if (this._service.db.realm) {
      // data base loaded, lets go straight to home
      Actions.app({ type: 'reset' });
      return;
    }
    // if login happens before timeout, switch gears to logged in screen
    const loadStrings = [
      t('loading_text_init_screens'),
      t('loading_text_conn_to_server'),
      t('loading_text_still_reaching'),
      t('dots'),
    ];
    // don't increase this timeout as this would impact the experience of folks
    // who are logging in for the first time
    for (let i = 0; i < loadStrings.length; i += 1) {
      setTimeout(() => {
        if (this._mounted) {
          if (i === loadStrings.length - 1) {
            if (!this._service.isConnected) {
              // we should throw exception to user and ask to selectserver
              this.setState({ isLoading: false });
            }
          }
          this.setState({
            loadText: loadStrings[i],
          });
        }
      }, (2000 * (i + 1)));
    }
  }

  sendServerUrl = () => {
    const inputServerVal = this.state.serverUrl ? this.state.serverUrl.trim() : undefined;
    // inputServerVal = inputServerVal.trim();
    // Validation for alphanumeric, dash and dots
    if (inputServerVal) {
//      inputServerVal = inputServerVal.replace(`.${Application.brandName}`, '');
      const regexp = /^[a-zA-Z0-9-.]+$/;
      if (regexp.test(inputServerVal)) {
        Application.resetInstance(inputServerVal);
        this.setState({
          isLoading: true,
          resultMsg: {
            status: '',
            success: '',
            error: '',
          },
        });
        this.connectToServer(Application.instance);
      } else {
        this.setState({ resultMsg: { error: t('err_enter_valid_workspace') } });
      }
    } else {
      this.setState({ resultMsg: { error: t('err_workspace_name_empty') } });
    }
  };

  render() {
    return (
      <View
        style={[styles.viewContainer, { backgroundColor: AppColors.brand().secondary }]}
        testID={'welcome'}
      >
        <StatusBar barStyle="light-content" />
        {this.state.isLoading === true &&
        <View style={[AppStyles.windowSize, AppStyles.containerCentered]}>
          <Image
            source={Application.logo}
            style={[AppStyles.loginLogoSplash, styles.logo]}
          />
          <Text
            style={[styles.loadText, AppStyles.baseFont]}
          >{this.state.loadText}</Text>
        </View>
        }
        {this.state.isLoading === false &&
        <ScrollView
          keyboardShouldPersistTaps={'handled'}
        >
          <KeyboardAvoidingView
            behavior={'position'}
            style={styles.messageContainer}
          >
            <View style={[AppStyles.row]}>
              <View style={[styles.centerAll]}>
                <Image
                  source={Application.logo}
                  style={[AppStyles.loginLogoSplash]}
                />
                <Alerts
                  error={this.state.resultMsg.error}
                />
                <Text style={
                [AppStyles.ListItemTitle, styles.workspace]
                }
                >{t('lbl_enter_your_workspace')}</Text>
              </View>
            </View>
            <View style={[AppStyles.row]}>
              <View style={[AppStyles.flex1, { height: 40 }]}>
                <TextInput
                  placeholder={`[workspace].${Application.brandName}`}
                  autoCapitalize={'none'}
                  style={[styles.textInput, AppStyles.baseFont]}
                  onChangeText={(text) => { this.setState({ serverUrl: text }); }}
                  value={this.state.serverUrl}
                  underlineColorAndroid={'transparent'}
                  autoCorrect={false}
                />
              </View>
            </View>
            <Spacer size={20} />
            <View style={[AppStyles.row]}>
              <View style={[AppStyles.flex1]}>
                <Button
                  title={t('confirm')}
                  onPress={this.sendServerUrl}
                  backgroundColor="transparent"
                  testID={'select-server'}
                />
              </View>
            </View>
            <View style={[AppStyles.row, { alignItems: 'center', justifyContent: 'center' }]}>
              <TouchableOpacity
                style={{
                  borderWidth: 1,
                  paddingHorizontal: 15,
                  paddingVertical: 2,
                  marginTop: 20,
                  borderColor: '#fff',
                  borderRadius: 3,
                  alignItems: 'center',
                  justifyContent: 'center',
                }}
                onPress={() => Actions.pop({ type: 'reset' })}
                testID={'back-login'}
              >
                <Text
                  style={[AppStyles.ListItemTitle, styles.workspace]}
                >{t('txt_back')}</Text>
              </TouchableOpacity>
            </View>
          </KeyboardAvoidingView>
          </ScrollView>
        }
      </View>
    );
  }
}

SelectServer.defaultProps = {
  switchServer: false,
};

SelectServer.propTypes = {
  switchServer: PropTypes.bool,
};
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  ListView,
  Navigator,
  Image,
  TouchableHighlight
} from 'react-native';

import UserDogs from './UserDogs';
import DogEdit from './DogEdit';
import Navbar from './Navbar';

var REQUEST_URL = 'http://localhost:3000/dogs/';

class DogProfile extends Component {
  constructor(props) {
    super(props);
    console.log("Constructing DogProfile");
    console.log("this.props.dog_id is " + this.props.dog_id);
    console.log("this.props.navigator is " + this.props.navigator);

    this.state = {
      dog: {},
      loaded: false,
    };
  }

  componentDidMount() {
    this.fetchData();
  }

  fetchData() {
    console.log("fetchData (DogProfile) called for dog_id " + this.props.dog_id);
    fetch(REQUEST_URL + this.props.dog_id)
      .then((response) => response.json())
      .then((responseData) => {
        console.log("fetchData for DogProfile: " + responseData);

        this.setState({
          dog: responseData,
          loaded: true,
        });
      })
      .done();
  }

  goBack() {
    this.props.navigator.pop();
  }

  onPressEdit() {
    console.log("onPressEdit");
    this.props.navigator.push({
      component: DogEdit,
      // Make sure to pass the playdate_id to the Edit component
      // Note the value has to be an object of key-value properties!
      passProps: { dog_id: this.props.dog_id }
    });
  }

  render() {
    var dog = this.state.dog;
    return (
      <View style={styles.container}>
        <TouchableHighlight style={styles.backButton} onPress={() => this.onPressEdit()}>
        <Text>Edit</Text>
        </TouchableHighlight>

        <View style={styles.container}>
          <Image style={styles.dogImage} source={{ uri: dog.avatar }} />
          <Text>Owner:  {dog.owner_username}</Text>
          <Text>Breed:  {dog.breed}</Text>
          <Text>Age:  {dog.age}</Text>
          <Text>Favorite Toy:  {dog.toy}</Text>
          <Text>PlayDates: N/A</Text>
          <Text>Gender:  {dog.gender}</Text>
          <Text>Description: </Text>
          <Text style={styles.dogDescription}>
             {dog.description}
          </Text>
        </View>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
  text: {
    fontSize: 14,
  },
  dogImage: {
    width: 128,
    height: 128,
    borderRadius: 128/2,
  },
  dogDescription: {
    height: 50,
  },
  backButton: {
    borderWidth: 1,
    padding: 10,
    alignSelf: 'flex-start'
  },
  editButton: {
    borderWidth: 1,
    padding: 10,
    alignSelf: 'flex-end',
  },
  backButtonText: {
    fontSize: 14,
    borderRadius: 12,
    fontWeight: 'bold',
  },
  navbar: {
    marginTop: 20,
    backgroundColor: 'skyblue',
    marginBottom: 6,
  },
});

module.exports = DogProfile;
<commit_msg>Add title to navigator push route for DogProfile component<commit_after>import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  ListView,
  Navigator,
  Image,
  TouchableHighlight
} from 'react-native';

import UserDogs from './UserDogs';
import DogEdit from './DogEdit';
import Navbar from './Navbar';

var REQUEST_URL = 'http://localhost:3000/dogs/';

class DogProfile extends Component {
  constructor(props) {
    super(props);
    console.log("Constructing DogProfile");
    console.log("this.props.dog_id is " + this.props.dog_id);
    console.log("this.props.navigator is " + this.props.navigator);

    this.state = {
      dog: {},
      loaded: false,
    };
  }

  componentDidMount() {
    this.fetchData();
  }

  fetchData() {
    console.log("fetchData (DogProfile) called for dog_id " + this.props.dog_id);
    fetch(REQUEST_URL + this.props.dog_id)
      .then((response) => response.json())
      .then((responseData) => {
        console.log("fetchData for DogProfile: " + responseData);

        this.setState({
          dog: responseData,
          loaded: true,
        });
      })
      .done();
  }

  goBack() {
    this.props.navigator.pop();
  }

  onPressEdit() {
    console.log("onPressEdit");
    this.props.navigator.push({
      title: 'Edit Dog Profile',
      component: DogEdit,
      // Make sure to pass the playdate_id to the Edit component
      // Note the value has to be an object of key-value properties!
      passProps: { dog_id: this.props.dog_id }
    });
  }

  render() {
    var dog = this.state.dog;
    return (
      <View style={styles.container}>
        <TouchableHighlight style={styles.backButton} onPress={() => this.onPressEdit()}>
        <Text>Edit</Text>
        </TouchableHighlight>

        <View style={styles.container}>
          <Image style={styles.dogImage} source={{ uri: dog.avatar }} />
          <Text>Owner:  {dog.owner_username}</Text>
          <Text>Breed:  {dog.breed}</Text>
          <Text>Age:  {dog.age}</Text>
          <Text>Favorite Toy:  {dog.toy}</Text>
          <Text>PlayDates: N/A</Text>
          <Text>Gender:  {dog.gender}</Text>
          <Text>Description: </Text>
          <Text style={styles.dogDescription}>
             {dog.description}
          </Text>
        </View>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
  text: {
    fontSize: 14,
  },
  dogImage: {
    width: 128,
    height: 128,
    borderRadius: 128/2,
  },
  dogDescription: {
    height: 50,
  },
  backButton: {
    borderWidth: 1,
    padding: 10,
    alignSelf: 'flex-start'
  },
  editButton: {
    borderWidth: 1,
    padding: 10,
    alignSelf: 'flex-end',
  },
  backButtonText: {
    fontSize: 14,
    borderRadius: 12,
    fontWeight: 'bold',
  },
  navbar: {
    marginTop: 20,
    backgroundColor: 'skyblue',
    marginBottom: 6,
  },
});

module.exports = DogProfile;
<|endoftext|>


<commit_before>import Ember from 'ember';
import config from 'ember-get-config';
import layout from './template';
import hostAppName from '../../mixins/host-app-name';

/**
 * Adapted from Registries - displays total search results.  Currently can pull number of preprints, registries, or retractions
 * available for search, depending on consuming application. Otherwise, just returns number of all SHARE results.
 *
 * ```handlebars
 *  {{total-share-results
 * }}
 * ```
 * @class total-share-results
 */
const serviceMap = {
    Preprints: 'preprint',
    Registries: 'registration',
};

export default Ember.Component.extend(hostAppName, {
    layout,
    i18n: Ember.inject.service(),
    theme: Ember.inject.service(),
    shareTotal: null,
    shareTotalText: Ember.computed(function() {
        // Returns translation text name : searchablePreprints, for example.
        const hostAppName = this.get('hostAppName');
        const translation = 'eosf.components.totalShareResults.searchable';
        return hostAppName ? `${translation}${hostAppName}`: `${translation}Events`;
    }),
    resourceType: Ember.computed('hostAppName', function() {
        const hostAppName = this.get('hostAppName');
        if (hostAppName) {
            return serviceMap[hostAppName] || null;
        } else {
            return null;
        }
    }),
    init() {
        // Fetch total number of preprints. Allow elasticsearch failure to pass silently.
        // This is considered to be a one-time fetch, and therefore is run in controller init.
        this._super(...arguments);
        const filter = Ember.A();
        const resourceType = this.get('resourceType');
        if (resourceType) {
            filter.pushObject(
                {
                    term: {
                        types: resourceType
                    }
                }
        )}

        const getTotalPayload = {
            size: 0,
            from: 0,
            query: {
                bool: {
                    must: {
                        query_string: {
                            query: '*'
                        }
                    },
                    filter
                }
            }
        };

        if (this.get('theme.isProvider')) {
            filter.push({
                term: {
                    // TODO filter by name and use sources.raw (potential conflicts later), Needs API name to match SHARE source.
                    // Update: .raw has been removed from type and source queries.
                    sources: this.get('theme.id')
                }
            });
        }
        Ember.$.ajax({
            type: 'POST',
            url: config.OSF.shareSearchUrl,
            data: JSON.stringify(getTotalPayload),
            contentType: 'application/json',
            crossDomain: true,
        })
          .then(results => this.set('shareTotal', results.hits.total));

        this.set('currentDate', new Date());
    },
});
<commit_msg>If hostAppName not in serviceMap, use ‘searchable events’ by default.<commit_after>import Ember from 'ember';
import config from 'ember-get-config';
import layout from './template';
import hostAppName from '../../mixins/host-app-name';

/**
 * Adapted from Registries - displays total search results.  Currently can pull number of preprints, registries, or retractions
 * available for search, depending on consuming application. Otherwise, just returns number of all SHARE results.
 *
 * ```handlebars
 *  {{total-share-results
 * }}
 * ```
 * @class total-share-results
 */
const serviceMap = Ember.Object.create({
    Preprints: 'preprint',
    Registries: 'registration',
});

export default Ember.Component.extend(hostAppName, {
    layout,
    i18n: Ember.inject.service(),
    theme: Ember.inject.service(),
    shareTotal: null,
    shareTotalText: Ember.computed(function() {
        // Returns translation text name : searchablePreprints, for example.
        const hostAppName = this.get('hostAppName') || null;
        const translation = 'eosf.components.totalShareResults.searchable';
        return Object.keys(serviceMap).includes(hostAppName) ? `${translation}${hostAppName}`: `${translation}Events`;
    }),
    resourceType: Ember.computed('hostAppName', function() {
        const hostAppName = this.get('hostAppName');
        if (hostAppName) {
            return serviceMap[hostAppName] || null;
        } else {
            return null;
        }
    }),
    init() {
        // Fetch total number of preprints. Allow elasticsearch failure to pass silently.
        // This is considered to be a one-time fetch, and therefore is run in controller init.
        this._super(...arguments);
        const filter = Ember.A();
        const resourceType = this.get('resourceType');
        if (resourceType) {
            filter.pushObject(
                {
                    term: {
                        types: resourceType
                    }
                }
        )}

        const getTotalPayload = {
            size: 0,
            from: 0,
            query: {
                bool: {
                    must: {
                        query_string: {
                            query: '*'
                        }
                    },
                    filter
                }
            }
        };

        if (this.get('theme.isProvider')) {
            filter.push({
                term: {
                    // TODO filter by name and use sources.raw (potential conflicts later), Needs API name to match SHARE source.
                    // Update: .raw has been removed from type and source queries.
                    sources: this.get('theme.id')
                }
            });
        }
        Ember.$.ajax({
            type: 'POST',
            url: config.OSF.shareSearchUrl,
            data: JSON.stringify(getTotalPayload),
            contentType: 'application/json',
            crossDomain: true,
        })
          .then(results => this.set('shareTotal', results.hits.total));

        this.set('currentDate', new Date());
    },
});
<|endoftext|>


<commit_before>var spawn = require('child_process');
var MPR121 = require('node-picap');
var mpr121;

var p1Left = 4;
var p1Right = 5;
var p1Up = 6;
var p1Down = 7;

var p2Left = 8;
var p2Right = 9;
var p2Up = 10;
var p2Down = 11;

var p1Start = 12;
var p1Back = 13;
// correct address for the Pi Cap - other boards may vary
mpr121 = new MPR121('0x5C');
mpr121.setTouchThreshold(40);
mpr121.setReleaseThreshold(20);

mpr121.on('data', function(data) {
  var keys = [];
  data.forEach(function(electrode, i) {
    if (electrode.isNewTouch) {
      switch(i) {
        case 0:
          keys.push(p1Left);
          break;
        case 1:
          keys.push(p1Right);
          break;
        case 2:
          keys.push(p1Up);
          break;
        case 3:
          keys.push(p1Down);
          break;
        case 4:
          keys.push(p2Left);
          break;
        case 5:
          keys.push(p2Right);
          break;
        case 6:
          keys.push(p2Up);
          break;
        case 7:
          keys.push(p2Down);
          break;
        case 8:
          keys.push(p2Up);
          break;
        case 9:
          keys.push(p1Start);
          break;
        case 10:
          keys.push(p1Back);
          break;
      }
    }
  });
  keystroke = "\\0\\0";
  keys.forEach(function(key) {
    keystroke += "\\" + key;
  });
  while(keystroke.length != 16) {
    keystroke += "\\0";
  }
  console.log(spawn.execSync('echo -ne "' + keystroke + '" > /dev/hidg0').toString());
});

process.on('SIGINT', function () {
  process.exit(0);
});
<commit_msg>Fix potential inifite loop<commit_after>var spawn = require('child_process');
var MPR121 = require('node-picap');
var mpr121;

var p1Left = 4;
var p1Right = 5;
var p1Up = 6;
var p1Down = 7;

var p2Left = 8;
var p2Right = 9;
var p2Up = 10;
var p2Down = 11;

var p1Start = 12;
var p1Back = 13;
// correct address for the Pi Cap - other boards may vary
mpr121 = new MPR121('0x5C');
mpr121.setTouchThreshold(40);
mpr121.setReleaseThreshold(20);

mpr121.on('data', function(data) {
  var keys = [];
  data.forEach(function(electrode, i) {
    if (electrode.isNewTouch) {
      switch(i) {
        case 0:
          keys.push(p1Left);
          break;
        case 1:
          keys.push(p1Right);
          break;
        case 2:
          keys.push(p1Up);
          break;
        case 3:
          keys.push(p1Down);
          break;
        case 4:
          keys.push(p2Left);
          break;
        case 5:
          keys.push(p2Right);
          break;
        case 6:
          keys.push(p2Up);
          break;
        case 7:
          keys.push(p2Down);
          break;
        case 8:
          keys.push(p2Up);
          break;
        case 9:
          keys.push(p1Start);
          break;
        case 10:
          keys.push(p1Back);
          break;
      }
    }
  });
  keystroke = "\\0\\0";
  keys.forEach(function(key) {
    keystroke += "\\" + key;
  });
  while(keystroke.length < 16) {
    keystroke += "\\0";
  }
  console.log(spawn.execSync('echo -ne "' + keystroke + '" > /dev/hidg0').toString());
});

process.on('SIGINT', function () {
  process.exit(0);
});
<|endoftext|>