<commit_before>define
([
    'jquery', 'jquery/superdesk', 'dust/core', 'utils/sha512', 'jquery/tmpl', 'jquery/rest', 'bootstrap',
    'tmpl!auth',
],
function($, superdesk, dust, jsSHA)
{
<<<<<<< HEAD
    var AuthLogin = function(username, password, logintoken){
=======
    var AuthDetails = function(username){
		var authDetails = new $.rest('Superdesk/User');
		authDetails.resetData().xfilter('Name,Id,EMail').select({ name: username }).done(function(users){
			var user = users.UserList[0];
			localStorage.setItem('superdesk.login.id', user.Id);
			localStorage.setItem('superdesk.login.name', user.Name);
			localStorage.setItem('superdesk.login.email', user.EMail);
		});
		return $(authDetails);
	},
	AuthLogin = function(username, password, logintoken){
>>>>>>> 718d8c014dc7f1c47606de731769286a6bcebb81
		var shaObj = new jsSHA(logintoken, "ASCII"),shaPassword = new jsSHA(password, "ASCII"),
			authLogin = new $.rest('Authentication');
			authLogin.resetData().insert({
			UserName: username,
			LoginToken: logintoken,
			HashedLoginToken: shaObj.getHMAC(username+shaPassword.getHash("SHA-512", "HEX"), "ASCII", "SHA-512", "HEX")
		}).done(function(user){
			localStorage.setItem('superdesk.login.session', user.Session);
			localStorage.setItem('superdesk.login.id', user.Id);
			localStorage.setItem('superdesk.login.name', user.UserName);
			localStorage.setItem('superdesk.login.email', user.EMail);
			$(authLogin).trigger('success');
		});
		return $(authLogin);
	},
	AuthToken = function(username, password) {
		var authToken = new $.rest('Authentication');
		authToken.resetData().select({ userName: username }).done(
			function(data){
				authLogin = AuthLogin(username, password, data.Token);
				authLogin.on('failed', function(){
					$(authToken).trigger('failed', 'authToken');
				}).on('success', function(){
					$(authToken).trigger('success');
				});
			}
		);
		return $(authToken);
	},
	AuthApp =
    {
        success: $.noop,
        require: function()
        {
			if(this.showed) return;
            var self = this; // rest
			self.showed = true;
            $.tmpl('auth', null, function(e, o)
            {
                var dialog = $(o).eq(0).dialog
                ({
                    draggable: false,
                    resizable: false,
                    modal: true,
                    width: "40.1709%",
                    buttons:
                    [
                         { text: "Login", click: function(){ $(form).trigger('submit'); }, class: "btn btn-primary"},
                         { text: "Close", click: function(){ $(this).dialog('close'); }, class: "btn"}
                    ]
                }),
                    form = dialog.find('form');
                form.off('submit.superdesk')//
                .on('submit.superdesk', function(event)
                {
                    var username = $(this).find('#username'), password=$(this).find('#password');
					AuthToken(username.val(), password.val()).on('failed',function(evt, type){
						username.val('');
						password.val('')
					}).on('success', function(){
                        AuthApp.success && AuthApp.success.apply();
						$(dialog).dialog('close');
						self.showed = false;
					});
                    event.preventDefault();

                });
            });
        }
    };
    return AuthApp;
});<commit_msg>NR-226: Create login functionality in Ally framework<commit_after>define
([
    'jquery', 'jquery/superdesk', 'dust/core', 'utils/sha512', 'jquery/tmpl', 'jquery/rest', 'bootstrap',
    'tmpl!auth',
],
function($, superdesk, dust, jsSHA)
{
    var AuthLogin = function(username, password, logintoken){
		var shaObj = new jsSHA(logintoken, "ASCII"),shaPassword = new jsSHA(password, "ASCII"),
			authLogin = new $.rest('Authentication');
			authLogin.resetData().insert({
			UserName: username,
			LoginToken: logintoken,
			HashedLoginToken: shaObj.getHMAC(username+shaPassword.getHash("SHA-512", "HEX"), "ASCII", "SHA-512", "HEX")
		}).done(function(user){
			localStorage.setItem('superdesk.login.session', user.Session);
			localStorage.setItem('superdesk.login.id', user.Id);
			localStorage.setItem('superdesk.login.name', user.UserName);
			localStorage.setItem('superdesk.login.email', user.EMail);
			$(authLogin).trigger('success');
		});
		return $(authLogin);
	},
	AuthToken = function(username, password) {
		var authToken = new $.rest('Authentication');
		authToken.resetData().select({ userName: username }).done(
			function(data){
				authLogin = AuthLogin(username, password, data.Token);
				authLogin.on('failed', function(){
					$(authToken).trigger('failed', 'authToken');
				}).on('success', function(){
					$(authToken).trigger('success');
				});
			}
		);
		return $(authToken);
	},
	AuthApp =
    {
        success: $.noop,
        require: function()
        {
			if(this.showed) return;
            var self = this; // rest
			self.showed = true;
            $.tmpl('auth', null, function(e, o)
            {
                var dialog = $(o).eq(0).dialog
                ({
                    draggable: false,
                    resizable: false,
                    modal: true,
                    width: "40.1709%",
                    buttons:
                    [
                         { text: "Login", click: function(){ $(form).trigger('submit'); }, class: "btn btn-primary"},
                         { text: "Close", click: function(){ $(this).dialog('close'); }, class: "btn"}
                    ]
                }),
                    form = dialog.find('form');
                form.off('submit.superdesk')//
                .on('submit.superdesk', function(event)
                {
                    var username = $(this).find('#username'), password=$(this).find('#password');
					AuthToken(username.val(), password.val()).on('failed',function(evt, type){
						username.val('');
						password.val('')
					}).on('success', function(){
                        AuthApp.success && AuthApp.success.apply();
						$(dialog).dialog('close');
						self.showed = false;
					});
                    event.preventDefault();

                });
            });
        }
    };
    return AuthApp;
});<|endoftext|>


<commit_before>import Ember from 'ember';
import layout from './template';
import RSVP from 'rsvp';
import EventStream from 'npm:sse.js';

import config from '../../config/environment';

export default Ember.Component.extend({
    layout,
    authRequest: Ember.inject.service(),
    internalState: Ember.inject.service(),
    tokenHandler: Ember.inject.service(),
    notificationHandler: Ember.inject.service(),

    datasources: Ember.A(),

    num_results: -1,
    error: false,
    errorMessage: '',
    searching: false,
    searchDataId: '',
    dataId: '',
    doi: '',
    name: '',
    repository: '',
    size: '',

    disableRegister() {
        Ember.$('.icon.register').removeClass('checkmark');
        Ember.$('.ui.positive.register.button').addClass('disabled');
    },

    enableRegister(dataId) {
        let ds = this.datasources.find(ds => {
            return (dataId == ds.dataId || dataId == ds.doi);
        });

        this.set('dataId', ds.dataId);
        this.set('doi', ds.doi);
        this.set('name', ds.name);
        this.set('repository', ds.repository);
        this.set('size', ds.size);

        Ember.$('.icon.register').addClass('checkmark');
        Ember.$('.ui.positive.register.button').removeClass('disabled');
    },

    clearModal() {
        Ember.$('#harvester-dropdown').dropdown('clear');
        Ember.$('#results').addClass('hidden');
        Ember.$('#searchbox').val('');

        this.set('datasources', Ember.A());
        this.set('error', false);
        this.set('errorMessage', '');
        this.set('num_results', -1);
        this.set('dataId', '');
        this.set('doi', '');
        this.set('name', '');
        this.set('repository', '');
        this.set('size', '');
    },

    didRender() {
        let self = this;
        Ember.$('#harvester-dropdown').dropdown({
            onChange: function(dataId) {
                if(!dataId || dataId === "") {
                    self.disableRegister();
                    return;
                }
                self.enableRegister(dataId);
            }
        });
    },

    getEventStream() {
        let token = this.get('tokenHandler').getWholeTaleAuthToken();
        let source = new EventStream.SSE(config.apiUrl+"/notification/stream?timeout=15000", {headers: {'Girder-Token': token}});

        let self = this;
        source.addEventListener('message', function(evt) {
            let payload = JSON.parse(evt.data);
            let notifier = self.get('notificationHandler');
            notifier.pushNotification({
                message: payload.data.message,
                header: payload.data.title
            });
        });

        source.stream();

        return source;
    },

    actions: {
        register() {
            this.set('error', false);

            let state = this.get('internalState');

            let parentId = state.getCurrentParentId();
            let parentType = state.getCurrentParentType();

            let queryParams = "?"+[
                "parentType="+parentType,
                "parentId="+parentId,
                "public=false"
            ].join('&');

            let dataMap = JSON.stringify([{
                name: this.name,
                dataId: this.dataId,
                repository: this.repository
            }]);

            let url = config.apiUrl + '/folder/register' + queryParams;
            let options = {
                method: 'POST',
                data: {
                    dataMap: dataMap
                }
            };

            let source = this.getEventStream();
            let self = this;

            this.get('authRequest').send(url, options)
                .then(rep => {
                })
                .catch(e => {
                    let notifier = self.get('notificationHandler');
                    notifier.pushNotification({
                        header: "Error Registering Dataset",
                        message: "To see a stack trace of what went wrong click (WIP)"
                    });
                })
                .finally(_ => {
                    source.close();
                });

            this.clearModal();
            this.disableRegister();
        },

        cancel() {
            this.clearModal();
            this.disableRegister();
        },

        search() {
            this.clearModal();
            this.set('searching', true);
            Ember.$('#results').removeClass('hidden');

            let url = config.apiUrl + '/repository/lookup';
            let options = {
                method: 'GET',
                data: {
                    dataId: JSON.stringify(this.searchDataId.split())
                }
            };

            let self = this;
            return self.get('authRequest').send(url, options)
                .then(rep => {
                    self.set('error', false);
                    self.set('num_results', rep.length);
                    self.datasources.pushObjects(rep);

                    if(rep.length === 1) {
                        let name = self.datasources[0].name;
                        let dataId = self.datasources[0].dataId;
                        Ember.run.later(self, function() {
                            Ember.$('#harvester-dropdown').dropdown('set text', name);
                            Ember.$('#harvester-dropdown').dropdown('set value', dataId);
                        }, 250);
                    }
                    else {
                        Ember.$('#harvester-dropdown').dropdown('set visible');
                        Ember.$('#harvester-dropdown').dropdown('set active');
                        let menu = Ember.$('#harvester-dropdown .menu');
                        menu.removeClass('hidden');
                        menu.addClass('transition visible');
                    }
                })
                .catch(e => {
                    console.log("Error: " + e);
                    self.set('error', true);
                    self.set('errorMessage', 'No matching results found.');
                    self.disableRegister();
                })
                .finally((_) => {
                    self.set('searching', false);
                });
        }
    }
});
<commit_msg>Fix issue #56<commit_after>import Ember from 'ember';
import layout from './template';
import RSVP from 'rsvp';
import EventStream from 'npm:sse.js';

import config from '../../config/environment';

export default Ember.Component.extend({
    layout,
    authRequest: Ember.inject.service(),
    userAuth: Ember.inject.service(),
    internalState: Ember.inject.service(),
    tokenHandler: Ember.inject.service(),
    notificationHandler: Ember.inject.service(),

    datasources: Ember.A(),

    num_results: -1,
    error: false,
    errorMessage: '',
    searching: false,
    searchDataId: '',
    dataId: '',
    doi: '',
    name: '',
    repository: '',
    size: '',

    disableRegister() {
        Ember.$('.icon.register').removeClass('checkmark');
        Ember.$('.ui.positive.register.button').addClass('disabled');
    },

    enableRegister(dataId) {
        let ds = this.datasources.find(ds => {
            return (dataId == ds.dataId || dataId == ds.doi);
        });

        this.set('dataId', ds.dataId);
        this.set('doi', ds.doi);
        this.set('name', ds.name);
        this.set('repository', ds.repository);
        this.set('size', ds.size);

        Ember.$('.icon.register').addClass('checkmark');
        Ember.$('.ui.positive.register.button').removeClass('disabled');
    },

    clearModal() {
        Ember.$('#harvester-dropdown').dropdown('clear');
        Ember.$('#results').addClass('hidden');
        Ember.$('#searchbox').val('');

        this.set('datasources', Ember.A());
        this.set('error', false);
        this.set('errorMessage', '');
        this.set('num_results', -1);
        this.set('dataId', '');
        this.set('doi', '');
        this.set('name', '');
        this.set('repository', '');
        this.set('size', '');
    },

    didRender() {
        let self = this;
        Ember.$('#harvester-dropdown').dropdown({
            onChange: function(dataId) {
                if(!dataId || dataId === "") {
                    self.disableRegister();
                    return;
                }
                self.enableRegister(dataId);
            }
        });
    },

    getEventStream() {
        let token = this.get('tokenHandler').getWholeTaleAuthToken();
        let source = new EventStream.SSE(config.apiUrl+"/notification/stream?timeout=15000", {headers: {'Girder-Token': token}});

        let self = this;
        source.addEventListener('message', function(evt) {
            let payload = JSON.parse(evt.data);
            let notifier = self.get('notificationHandler');
            notifier.pushNotification({
                message: payload.data.message,
                header: payload.data.title
            });
        });

        source.stream();

        return source;
    },

    actions: {
        register() {
            this.set('error', false);

            let state = this.get('internalState');
            let userAuth = this.get('userAuth');

            let parentId = state.getCurrentParentId();
            let parentType = state.getCurrentParentType();

            if(!!parentId || parentId === "undefined" || parentId === undefined) {
                parentId = userAuth.getCurrentUserID();
                parentType = "user";
            }

            let queryParams = "?"+[
                "parentType="+parentType,
                "parentId="+parentId,
                "public=false"
            ].join('&');

            let dataMap = JSON.stringify([{
                name: this.name,
                dataId: this.dataId,
                repository: this.repository
            }]);

            let url = config.apiUrl + '/folder/register' + queryParams;
            let options = {
                method: 'POST',
                data: {
                    dataMap: dataMap
                }
            };

            let source = this.getEventStream();
            let self = this;

            this.get('authRequest').send(url, options)
                .then(rep => {
                })
                .catch(e => {
                    let notifier = self.get('notificationHandler');
                    notifier.pushNotification({
                        header: "Error Registering Dataset",
                        message: "To see a stack trace of what went wrong click <button onclick=\"alert(1);\">here</button>"
                    });
                })
                .finally(_ => {
                    source.close();
                });

            this.clearModal();
            this.disableRegister();
        },

        cancel() {
            this.clearModal();
            this.disableRegister();
        },

        search() {
            this.clearModal();
            this.set('searching', true);
            Ember.$('#results').removeClass('hidden');

            let url = config.apiUrl + '/repository/lookup';
            let options = {
                method: 'GET',
                data: {
                    dataId: JSON.stringify(this.searchDataId.split())
                }
            };

            let self = this;
            return self.get('authRequest').send(url, options)
                .then(rep => {
                    self.set('error', false);
                    self.set('num_results', rep.length);
                    self.datasources.pushObjects(rep);

                    if(rep.length === 1) {
                        let name = self.datasources[0].name;
                        let dataId = self.datasources[0].dataId;
                        Ember.run.later(self, function() {
                            Ember.$('#harvester-dropdown').dropdown('set text', name);
                            Ember.$('#harvester-dropdown').dropdown('set value', dataId);
                        }, 250);
                    }
                    else {
                        Ember.$('#harvester-dropdown').dropdown('set visible');
                        Ember.$('#harvester-dropdown').dropdown('set active');
                        let menu = Ember.$('#harvester-dropdown .menu');
                        menu.removeClass('hidden');
                        menu.addClass('transition visible');
                    }
                })
                .catch(e => {
                    console.log("Error: " + e);
                    self.set('error', true);
                    self.set('errorMessage', 'No matching results found.');
                    self.disableRegister();
                })
                .finally((_) => {
                    self.set('searching', false);
                });
        }
    }
});
<|endoftext|>


<commit_before>'use strict';

angular.module('cfsn', [
        'ngRoute',
        'ngSanitize',
        'cfsn.data',
        'cfsn.filters',
        'cfsn.main.controller',
        'cfsn.term.controller'
    ])

    .value('version', '0.0.1')

    .directive('appVersion', ['version', function(version) {
        return function(scope, elm, attrs) {
            elm.text(version);
        };
     }])

    .config(['$routeProvider', function ($routeProvider) {
        $routeProvider
            .when('/', {
                templateUrl: 'views/main.html',
                controller: 'MainCtrl'})

            .when('/:term', {
                templateUrl: 'views/term.html',
                controller: 'TermCtrl'})

            .when('/search/:search', {
                templateUrl: 'views/main.html',
                controller: 'MainCtrl'})

            .otherwise({redirectTo: '/'});
    }])

    .factory('Works', ['$rootScope', function($rootScope) {
        var nextWorkId = 0;
        var worksById = {};

        var works = {
            add: function(w) {
                var id = ++nextWorkId;
                worksById[id] = w;
                return id;
            },
            has:  function(id) {
                return worksById[id] !== undefined;
            },
            remove:  function(id) {
                var w = worksById[id];
                delete worksById[id];
                return w;
            },
            update:  function(id, w) {
                worksById[id] = w;
            },
            removeAll: function() {
                worksById = {};
            },
            any:  function() {
                if (_.size(worksById) > 0) {
                    for (var id in worksById) {
                        if (worksById.hasOwnProperty(id)) {
                            return worksById[id];
                        }
                    }
                }
                return undefined;
            }
        };

        $rootScope.works = works;

        return {
            works: works
        };
    }])
;
<commit_msg>0.0.2: cache, and better hyperlinking in descriptions<commit_after>'use strict';

angular.module('cfsn', [
        'ngRoute',
        'ngSanitize',
        'cfsn.data',
        'cfsn.filters',
        'cfsn.main.controller',
        'cfsn.term.controller'
    ])

    .value('version', '0.0.2')

    .directive('appVersion', ['version', function(version) {
        return function(scope, elm, attrs) {
            elm.text(version);
        };
     }])

    .config(['$routeProvider', function ($routeProvider) {
        $routeProvider
            .when('/', {
                templateUrl: 'views/main.html',
                controller: 'MainCtrl'})

            .when('/:term', {
                templateUrl: 'views/term.html',
                controller: 'TermCtrl'})

            .when('/search/:search', {
                templateUrl: 'views/main.html',
                controller: 'MainCtrl'})

            .otherwise({redirectTo: '/'});
    }])

    .factory('Works', ['$rootScope', function($rootScope) {
        var nextWorkId = 0;
        var worksById = {};

        var works = {
            add: function(w) {
                var id = ++nextWorkId;
                worksById[id] = w;
                return id;
            },
            has:  function(id) {
                return worksById[id] !== undefined;
            },
            remove:  function(id) {
                var w = worksById[id];
                delete worksById[id];
                return w;
            },
            update:  function(id, w) {
                worksById[id] = w;
            },
            removeAll: function() {
                worksById = {};
            },
            any:  function() {
                if (_.size(worksById) > 0) {
                    for (var id in worksById) {
                        if (worksById.hasOwnProperty(id)) {
                            return worksById[id];
                        }
                    }
                }
                return undefined;
            }
        };

        $rootScope.works = works;

        return {
            works: works
        };
    }])
;
<|endoftext|>


<commit_before>let Promise = require('bluebird');
let express = require('express');
let parser = require('body-parser');
let app = express();
let Config = require('../config');
let botanService = require('./services/botan-service');
let buildService = require('./services/build-service');
let logger = require('./logger');

app.use(parser.json());
app.get('/', (req, res) => {
	res.send('OK');
});

app.post('/codeship/:chatId', (req, res) => {
	res.send();
	let build = req.body ? req.body.build : null;
	let chatId = req.params.chatId;
	let mode = req.query.mode;
	let format = req.query.format;

	if (!build) {
		return;
	}

	logger.log('Build:', build.project_id, build.status);

	botanService.trackBuildNotification(build);
	buildService.onBuild(build, chatId, mode, format);
});

class Server {

	constructor() {
	}

	start() {
		return new Promise((resolve) => {
			this.instance = app.listen(Config.app.port, resolve);
		}).return(this.instance);
	}

}

module.exports = Server;

<commit_msg>Log if build data not present<commit_after>let Promise = require('bluebird');
let express = require('express');
let parser = require('body-parser');
let app = express();
let Config = require('../config');
let botanService = require('./services/botan-service');
let buildService = require('./services/build-service');
let logger = require('./logger');

app.use(parser.json());
app.get('/', (req, res) => {
	res.send('OK');
});

app.post('/codeship/:chatId', (req, res) => {
	res.send();
	let build = req.body ? req.body.build : null;
	let chatId = req.params.chatId;
	let mode = req.query.mode;
	let format = req.query.format;

	if (!build) {
		logger.error('No build in body present');
		return;
	}

	logger.log('Build:', build.project_id, build.status);

	botanService.trackBuildNotification(build);
	buildService.onBuild(build, chatId, mode, format);
});

class Server {

	constructor() {
	}

	start() {
		return new Promise((resolve) => {
			this.instance = app.listen(Config.app.port, resolve);
		}).return(this.instance);
	}

}

module.exports = Server;

<|endoftext|>


<commit_before>'use strict';

angular.module('memexLinkerApp')
.controller('SavedentitiesCtrl', function ($scope, $http, $q, lodash) {
    var _ = lodash;

    // fetch saved entities
    var _ = lodash;
    var source_map = {
    	1 : 'Backpage',
    	2 : 'Craigslist',
    	3 : 'Classivox',
    	4 : 'MyProviderGuide',
    	5 : 'NaughtyReviews',
    	6 : 'RedBook',
    	7 : 'CityVibe',
    	8 :  'MassageTroll',
    	9 : 'RedBookForum',
    	10 : 'CityXGuide',
    	11 : 'CityXGuideForum',
    	12 : 'RubAds',
    	13 : 'Anunico',
    	14 : 'SipSap',
    	15 : 'EscortsInCollege',
    	16 : 'EscortPhoneList',
    	17 : 'EroticMugshots',
    	18 :  'EscortsAdsXXX',
    	19 : 'EscortsinCA',
    	20 : 'EscortsintheUS',
    	21 : 'LiveEscortReviws',
    	22 : 'MyProviderGuideForum',
    	23 : 'USASexGuide',
    	24 : 'EroticReview',
    	25 : 'AdultSearch',
    	26 : 'HappyMassage',
    	27: 'UtopiaGuide',
    	28 : 'MissingKids'
    };

     /*
    * Returns the set of unique, flattened items, and removes undefined values.
    */

    function uniqueFlatAndDefined(items) {
      return _.filter(_.uniq(_.flattenDeep(items)), function(item) {
        return ! _.isUndefined(item);
    });
  }

  function collectAdProperty(ads, propertyName) {
      return _.map(ads, function(ad) {
        return ad.properties[propertyName];
    });
  }

  // Temporary hashmap for computing search result aggregate statistics.
  $scope.logo = 'http://icons.iconarchive.com/icons/icons8/ios7/256/Very-Basic-Paper-Clip-icon.png';
  $scope.blur = true;
  $scope.entities = [];

  function summarizeEntity(entity) {
      var deferred = $q.defer();

      $http.get('api/entities/' + entity.id + '/byphone').success(function(res){
        var ads = _.map(res, function(element){
          var ad = {
            'id':element.ad._id,
            'labels':element.ad.labels,
            'properties':element.ad.properties
        };
        return ad;
    });

        var postTimes = _.map(ads, function(ad){
          return new Date(ad.properties.posttime);
      });
        var lastPostTime = _.max(postTimes);
        var firstPostTime = _.min(postTimes);

        var age = uniqueFlatAndDefined(collectAdProperty(ads, 'age')).sort();
        var minAges = _.min(age);
        var maxAges = _.max(age);
        var rate60 = uniqueFlatAndDefined(collectAdProperty(ads, 'rate60'));
        var priceRange = 'Missing' ;
        if (rate60.length === 1 && rate60[0] != null) {
          priceRange = rate60[0] ;
      }
      else if (rate60.length > 1) {
          priceRange = _.min(rate60) + ' to ' +  _.max(rate60);
      }
      var website=[];
      var sourcesid = uniqueFlatAndDefined(collectAdProperty(ads, 'sources_id'));
      for (var i = 0; i < sourcesid.length; i++) {
          website=website.concat(source_map[sourcesid[i]]);
          //  console.log(website);
      }
      website = _.filter(_.uniq(website), function(element){
          return ! _.isUndefined(element);
      });

      var title = collectAdProperty(ads, 'title');
      var text = collectAdProperty(ads, 'text');
      var name = uniqueFlatAndDefined(collectAdProperty(ads, 'name'));
      var city = uniqueFlatAndDefined(collectAdProperty(ads, 'city'));

      var instagram = uniqueFlatAndDefined(collectAdProperty(ads, 'instagram'));
      var twitter = uniqueFlatAndDefined(collectAdProperty(ads, 'twitter'));
      var ethnicity = uniqueFlatAndDefined(collectAdProperty(ads, 'ethnicity'));

      var imageUrls = _.uniq(lodash.flatten(
          _.map(ads, function(ad) {
            return ad.properties.image_locations;
        }),
          true
          ));

      imageUrls = _.filter(imageUrls, function(element){
          return ! _.isUndefined(element);
      });

      var face = uniqueFlatAndDefined(lodash.flatten(
          _.map(ads, function(ad) {
            return ad.properties.face_image_url;
        }),
          true
          ));

      var nFaces = face.length;

        // TODO: refactor server to provide all suggested ads, with reason(s) why each was suggested.
        $http.get('api/entities/' + entity.id + '/byimage').success(function(res){
          var nSuggestedByImage = res.length;

          var entitySummary = {
            id: entity.id,
            phone: entity.phone,
            nPosts: ads.length,
            nPics: imageUrls.length,
            nSuggestedByImage: nSuggestedByImage,
            nSuggestedByText: 0,
            nSuggestedByPhone: 0,
            postTimes : postTimes,
            lastPostTime: lastPostTime,
            firstPostTime: firstPostTime,
            age: age,
            minAges: minAges,
            maxAges: maxAges,
            imageUrls: imageUrls,
            priceRange: priceRange,
            rate60: rate60,
            sourcesid: sourcesid,
            title: title,
            text:text,
            name: name,
            city: city,
            nFaces: nFaces,
            website: website,
            twitter: twitter,
            instagram: instagram,
            ethnicity: ethnicity
        };
        deferred.resolve(entitySummary);
    });
    });

    return deferred.promise;
    }

    // Get saved entities
    var data = {
        userName : 'username'
    };
    $http.post('/api/interaction/saved', data).
    success(function(res) {
        console.log(res);
        var savedEntities = _.map(res, function(e){
          return {
            'id': e._node._id,
            'phone' : e._node.properties.identifier
          };
        });
                //Aggregate details from ads belonging to each entity.
        _.forEach(savedEntities, function(entity) {
          summarizeEntity(entity).then(function(entitySummary) {
            // success
            $scope.entities.push(entitySummary);
          }, function(reason) {
            console.log('Failed for ' + reason);
          });

        });
    }).
    error(function(data, status, headers, config) {
        console.error(status);
    });

});
<commit_msg>removes inaccurate comments<commit_after>'use strict';

angular.module('memexLinkerApp')
.controller('SavedentitiesCtrl', function ($scope, $http, $q, lodash) {
    var _ = lodash;

    // fetch saved entities
    var _ = lodash;
    var source_map = {
    	1 : 'Backpage',
    	2 : 'Craigslist',
    	3 : 'Classivox',
    	4 : 'MyProviderGuide',
    	5 : 'NaughtyReviews',
    	6 : 'RedBook',
    	7 : 'CityVibe',
    	8 :  'MassageTroll',
    	9 : 'RedBookForum',
    	10 : 'CityXGuide',
    	11 : 'CityXGuideForum',
    	12 : 'RubAds',
    	13 : 'Anunico',
    	14 : 'SipSap',
    	15 : 'EscortsInCollege',
    	16 : 'EscortPhoneList',
    	17 : 'EroticMugshots',
    	18 :  'EscortsAdsXXX',
    	19 : 'EscortsinCA',
    	20 : 'EscortsintheUS',
    	21 : 'LiveEscortReviws',
    	22 : 'MyProviderGuideForum',
    	23 : 'USASexGuide',
    	24 : 'EroticReview',
    	25 : 'AdultSearch',
    	26 : 'HappyMassage',
    	27: 'UtopiaGuide',
    	28 : 'MissingKids'
    };

     /*
    * Returns the set of unique, flattened items, and removes undefined values.
    */

    function uniqueFlatAndDefined(items) {
      return _.filter(_.uniq(_.flattenDeep(items)), function(item) {
        return ! _.isUndefined(item);
    });
  }

  function collectAdProperty(ads, propertyName) {
      return _.map(ads, function(ad) {
        return ad.properties[propertyName];
    });
  }

  $scope.logo = 'http://icons.iconarchive.com/icons/icons8/ios7/256/Very-Basic-Paper-Clip-icon.png';
  $scope.blur = true;
  $scope.entities = [];

  function summarizeEntity(entity) {
      var deferred = $q.defer();

      $http.get('api/entities/' + entity.id + '/byphone').success(function(res){
        var ads = _.map(res, function(element){
          var ad = {
            'id':element.ad._id,
            'labels':element.ad.labels,
            'properties':element.ad.properties
        };
        return ad;
    });

        var postTimes = _.map(ads, function(ad){
          return new Date(ad.properties.posttime);
      });
        var lastPostTime = _.max(postTimes);
        var firstPostTime = _.min(postTimes);

        var age = uniqueFlatAndDefined(collectAdProperty(ads, 'age')).sort();
        var minAges = _.min(age);
        var maxAges = _.max(age);
        var rate60 = uniqueFlatAndDefined(collectAdProperty(ads, 'rate60'));
        var priceRange = 'Missing' ;
        if (rate60.length === 1 && rate60[0] != null) {
          priceRange = rate60[0] ;
      }
      else if (rate60.length > 1) {
          priceRange = _.min(rate60) + ' to ' +  _.max(rate60);
      }
      var website=[];
      var sourcesid = uniqueFlatAndDefined(collectAdProperty(ads, 'sources_id'));
      for (var i = 0; i < sourcesid.length; i++) {
          website=website.concat(source_map[sourcesid[i]]);
          //  console.log(website);
      }
      website = _.filter(_.uniq(website), function(element){
          return ! _.isUndefined(element);
      });

      var title = collectAdProperty(ads, 'title');
      var text = collectAdProperty(ads, 'text');
      var name = uniqueFlatAndDefined(collectAdProperty(ads, 'name'));
      var city = uniqueFlatAndDefined(collectAdProperty(ads, 'city'));

      var instagram = uniqueFlatAndDefined(collectAdProperty(ads, 'instagram'));
      var twitter = uniqueFlatAndDefined(collectAdProperty(ads, 'twitter'));
      var ethnicity = uniqueFlatAndDefined(collectAdProperty(ads, 'ethnicity'));

      var imageUrls = _.uniq(lodash.flatten(
          _.map(ads, function(ad) {
            return ad.properties.image_locations;
        }),
          true
          ));

      imageUrls = _.filter(imageUrls, function(element){
          return ! _.isUndefined(element);
      });

      var face = uniqueFlatAndDefined(lodash.flatten(
          _.map(ads, function(ad) {
            return ad.properties.face_image_url;
        }),
          true
          ));

      var nFaces = face.length;

        // TODO: refactor server to provide all suggested ads, with reason(s) why each was suggested.
        $http.get('api/entities/' + entity.id + '/byimage').success(function(res){
          var nSuggestedByImage = res.length;

          var entitySummary = {
            id: entity.id,
            phone: entity.phone,
            nPosts: ads.length,
            nPics: imageUrls.length,
            nSuggestedByImage: nSuggestedByImage,
            nSuggestedByText: 0,
            nSuggestedByPhone: 0,
            postTimes : postTimes,
            lastPostTime: lastPostTime,
            firstPostTime: firstPostTime,
            age: age,
            minAges: minAges,
            maxAges: maxAges,
            imageUrls: imageUrls,
            priceRange: priceRange,
            rate60: rate60,
            sourcesid: sourcesid,
            title: title,
            text:text,
            name: name,
            city: city,
            nFaces: nFaces,
            website: website,
            twitter: twitter,
            instagram: instagram,
            ethnicity: ethnicity
        };
        deferred.resolve(entitySummary);
    });
    });

    return deferred.promise;
    }

    // Get saved entities
    var data = {
        userName : 'username'
    };
    $http.post('/api/interaction/saved', data).
    success(function(res) {
        console.log(res);
        var savedEntities = _.map(res, function(e){
          return {
            'id': e._node._id,
            'phone' : e._node.properties.identifier
          };
        });
                //Aggregate details from ads belonging to each entity.
        _.forEach(savedEntities, function(entity) {
          summarizeEntity(entity).then(function(entitySummary) {
            // success
            $scope.entities.push(entitySummary);
          }, function(reason) {
            console.log('Failed for ' + reason);
          });

        });
    }).
    error(function(data, status, headers, config) {
        console.error(status);
    });

});
<|endoftext|>


<commit_before>/**
 * Dreamscapes\ledctl
 *
 * Licensed under the BSD-3-Clause license
 * For full copyright and license information, please see the LICENSE file
 *
 * @author     Robert Rossmann <rr.rossmann@me.com>
 * @copyright  2014 Robert Rossmann
 * @link       https://github.com/Dreamscapes/ledctl
 * @license    http://choosealicense.com/licenses/BSD-3-Clause  BSD-3-Clause License
 */

// Make jshint play nicely with should.js
/* jshint expr: true */

'use strict';

var fs = require('fs')
  , path = require('path')
  , domain = require('domain')
  , LEDController = require('../lib/ledcontroller')
// List of some triggers usually found on LEDs
  , knownTriggers =
    [ 'none'
    , 'timer'
    , 'heartbeat'
    , 'default-on'
    ]
  , led // Used for ad-hoc object construction
  , ledGreen
  , ledRed

// Get the path to given file belonging, optionally, to the specified LED (otherwise the green
// one is used)
function pathTo(file, led) {

  led = led || 'green:led0'

  return path.join(__dirname, 'fakeleds', led, file)
}

// Helper function that restores the /triggers file to a known state
function restoreTriggers () {

  var triggers = knownTriggers.slice() // Shallow copy, that's all we need
  triggers[0] = '[' + triggers[0] + ']' // Mark the first trigger as being active
  fs.writeFileSync(pathTo('trigger'), triggers.join(' ') + '\n', 'utf8')
}

// Helper function that restores the /brightness file to a known state
function restoreBrightness () {

  fs.writeFileSync(pathTo('brightness'), '0\n', 'utf8')
}

describe('LEDController', function () {

  beforeEach(function () {
    // Override the default root path for LEDs so we can predictably test this thing...
    LEDController.ROOT = path.join(__dirname, 'fakeleds')
    ledGreen = new LEDController('green:led0')
    ledRed = new LEDController('red:led1')
  })

  it('should throw when no identifier given', function () {
    (function () {
      led = new LEDController()
    }).should.throw()
  })

  it('should throw when trying to control non-existent LED', function () {
    (function () {
      led = new LEDController('ifeellucky')
    }).should.throw()
  })

  it('should not throw when only one LED is available and no identifier given', function () {
    // Monkey-patching
    var discoverFunc = LEDController.discover
    LEDController.discover = function () {
      return ['green:led0']   // Only one LED available on this system...
    }

    try {
      led = new LEDController()
    } catch (e) {
      LEDController.discover = discoverFunc
      throw e
    }

    LEDController.discover = discoverFunc
    led.id.should.equal('green:led0')
  })

  it('should have property RATE equal to 1', function () {
    LEDController.RATE.should.equal(1)
  })

  describe('property:id', function () {

    it('should be what is passed to the constructor (the LED\'s actual ID)', function () {
      ledGreen.id.should.equal('green:led0')
    })
  })

  describe('property:location', function () {

    it('should be combination of LEDController.ROOT and LED\'s identifier', function () {
      ledGreen.location
        .should.be.String
        .and.equal(path.join(LEDController.ROOT, 'green:led0'))
    })
  })

  describe('property:brightness', function () {

    beforeEach(restoreBrightness)
    after(restoreBrightness)

    it('should have property min and equal 0', function () {

      ledGreen.brightness.min
        .should.be.Number
        .and.equal(0)
    })

    it('should have property max and equal to /max_brightness', function () {
      var contents = fs.readFileSync(
        pathTo('max_brightness')
      , 'utf8'
      ).trim()

      ledGreen.brightness.max
        .should.be.Number
        .and.equal(parseInt(contents))
    })

    it('should have property cur and equal to /brightness', function () {
      var contents = fs.readFileSync(
        pathTo('brightness')
      , 'utf8'
      ).trim()

      ledGreen.brightness.cur
        .should.be.Number
        .and.equal(parseInt(contents))
    })

    it('should reflect runtime changes in brightness.cur', function () {
      var original = parseInt(fs.readFileSync(
        pathTo('brightness')
      , 'utf8'
      ).trim())
      , modified = 100

      // Just making sure we are REALLY changing the value... Ya ne'er know
      original.should.not.equal(modified)

      // Modify the brightness and check if the property updated the value, too
      fs.writeFileSync(
        pathTo('brightness')
      , modified.toString(), 'utf8'
      )

      ledGreen.brightness.cur.should.equal(100)
    })
  })

  describe('property:triggers', function () {

    afterEach(restoreTriggers)
    after(restoreTriggers)

    it('should have property all and equal to /trigger', function () {
      ledGreen.triggers.all.should.containDeep(knownTriggers)
    })

    it('should have property cur and equal to currently selected trigger in /trigger', function () {
      var current = '[' + ledGreen.triggers.cur + ']'
        , contents = fs.readFileSync(pathTo('trigger'), 'utf8')

      contents.indexOf(current).should.not.equal(-1)
    })

    it('should reflect runtime changes in triggers.cur', function () {
      var modified = knownTriggers.slice() // shallow copy

      ledGreen.triggers.cur.should.not.equal(3) // Are we actually changing stuff?

      modified[3] = '[' + modified[3] + ']' // I just randomly chose 3.
      fs.writeFileSync(pathTo('trigger'), modified.join(' ') + '\n', 'utf8')

      ledGreen.triggers.cur.should.equal(knownTriggers[3])
    })
  })

  describe(':discover()', function () {

    it('should list the LEDs available in LEDController.ROOT', function () {
      var contents = fs.readdirSync(LEDController.ROOT)

      LEDController.discover()
        .should.be.Array
        .and.containDeep(contents)
    })

    it('should recognise valid LEDs and ignore random folders', function () {
      LEDController.ROOT = __dirname    // Set the root to the test dir

      // There are no real LEDs in the test folder!
      LEDController.discover()
        .should.be.Array
        .and.have.lengthOf(0)
    })

    it('should not throw when no LEDs are available and return empty array', function () {
      var retVal

      (function () {
        LEDController.ROOT = '/some/random/junk'
        retVal = LEDController.discover()
      }).should.not.throw()

      retVal.should.be.empty
    })
  })

  describe(':register()', function () {

    afterEach(function () {
      // Cleanup
      delete LEDController.prototype.dummymethod
    })

    it('should accept functions as handlers', function () {
      (function () {
        LEDController.register('dummymethod', function () {})
      }).should.not.throw()
    })

    it('should throw on handlers not being functions', function () {
      (function () {
        LEDController.register('dummymethod', 'ladida')
      }).should.throw();    // Semicolon necessary... wow

      (function () {
        LEDController.register('dummymethod', 42)
      }).should.throw();

      (function () {
        LEDController.register('dummymethod', undefined)
      }).should.throw()
    })

    it('should put the handler onto the prototype', function () {
      var handler = function () {}

      LEDController.register('dummymethod', handler)

      LEDController.prototype.dummymethod
        .should.be.a.Function
        .and.should.not.equal(handler)    // Because we wrap it in our own function
    })

    it('should throw when attempting to register the same handler more than once', function () {
      // This should pass - registering it for the first time...
      (function () {
        LEDController.register('dummymethod', function () {})
      }).should.not.throw();
      // And here it should throw
      (function () {
        LEDController.register('dummymethod', function () {})
      }).should.throw()
    })

    it('should call the handler when calling the attached method', function (done) {
      var handler = function (input) {
        input.should.equal('test')

        process.nextTick(done)
      }

      LEDController.register('dummymethod', handler)
      ledGreen.dummymethod('test')
    })

    it('should pass all errors thrown from handlers to the method callback', function (done) {
      LEDController.register('dummymethod', function () {
        // Imagine an error in my custom serialiser happened...
        throw new Error('test')
      })

      ledGreen.dummymethod('input', function (err) {
        err.message.should.equal('test')

        done()
      })
    })

    it('should call the callback only once, even if more blinks are in queue', function (done) {
      LEDController.register('dummymethod', function () {
        // Just two superfast blink events...
        return [{ rate: 10000 }, { rate: 10000 }]
      })

      // Mocha will surely complain about calling done multiple times
      ledGreen.dummymethod('test', done)
    })

    it('should make the attached function to return this', function () {
      LEDController.register('dummymethod', function () {})

      ledGreen.dummymethod().should.be.exactly(ledGreen)
    })
  })

  describe('.trigger()', function () {

    beforeEach(restoreTriggers)
    after(restoreTriggers)

    it('should write the desired trigger to /trigger', function (done) {
      ledGreen.trigger('default-on', function () {
        fs.readFileSync(pathTo('trigger'), 'utf8').trim().should.equal('default-on')

        done()
      })
    })

    it('should return this', function (done) {
      ledGreen.trigger('default-on', done).should.be.exactly(ledGreen)
    })

    it('should error out on invalid trigger name', function (done) {
      ledGreen.trigger('something', function (err) {

        err.should.be.Error
        err.message.should.containEql('something')

        done()
      })
    })

    it('should throw on error when no callback given', function (done) {
      // Warning - fragile test! If it fails, it crashes the whole test suite. Not sure what
      // exactly is going on or how to fix it... Just FYI.
      var d = domain.create()

      d.on('error', function (err) {
        err.should.be.an.Error
        err.message.should.containEql('Unsupported trigger')

        d.dispose()
        done()
      })

      d.run(function () {
        ledGreen.trigger('something')
      })
    })
  })

  describe('.turnOn() / .turnOff()', function () {

    beforeEach(restoreBrightness)
    after(restoreBrightness)

    it('.turnOn() should write to /brightness its maximum brightness', function (done) {
      ledGreen.turnOn(function () {
        var contents = fs.readFileSync(pathTo('brightness'), 'utf8').trim()
          , maxBrightness = fs.readFileSync(pathTo('max_brightness'), 'utf8').trim()

        contents.should.equal(maxBrightness)
        done()
      })
    })

    it('.turnOn() should return this', function (done) {
      ledGreen.turnOn(done).should.be.exactly(ledGreen)
    })

    it('.turnOff() should write to /brightness 0', function (done) {
      ledGreen.turnOff(function () {
        var contents = parseInt(fs.readFileSync(pathTo('brightness'), 'utf8').trim())

        contents.should.equal(0)
        done()
      })
    })

    it('.turnOff() should return this', function (done) {
      ledGreen.turnOff(done).should.be.exactly(ledGreen)
    })
  })

  describe('.blink()', function () {

    // TODO
  })

  describe('.toString()', function () {

    it('should return proper object class name', function () {
      ledGreen.toString().should.equal('[object LEDController]')
    })
  })

  describe('.valueOf()', function () {

    it('should return the LED\'s current brightness', function () {

      ledGreen.valueOf().should.equal(ledGreen.brightness.cur)
    })
  })
})
<commit_msg>Move the semicolons to reflect what npm does<commit_after>/**
 * Dreamscapes\ledctl
 *
 * Licensed under the BSD-3-Clause license
 * For full copyright and license information, please see the LICENSE file
 *
 * @author     Robert Rossmann <rr.rossmann@me.com>
 * @copyright  2014 Robert Rossmann
 * @link       https://github.com/Dreamscapes/ledctl
 * @license    http://choosealicense.com/licenses/BSD-3-Clause  BSD-3-Clause License
 */

// Make jshint play nicely with should.js
/* jshint expr: true */

'use strict';

var fs = require('fs')
  , path = require('path')
  , domain = require('domain')
  , LEDController = require('../lib/ledcontroller')
// List of some triggers usually found on LEDs
  , knownTriggers =
    [ 'none'
    , 'timer'
    , 'heartbeat'
    , 'default-on'
    ]
  , led // Used for ad-hoc object construction
  , ledGreen
  , ledRed

// Get the path to given file belonging, optionally, to the specified LED (otherwise the green
// one is used)
function pathTo(file, led) {

  led = led || 'green:led0'

  return path.join(__dirname, 'fakeleds', led, file)
}

// Helper function that restores the /triggers file to a known state
function restoreTriggers () {

  var triggers = knownTriggers.slice() // Shallow copy, that's all we need
  triggers[0] = '[' + triggers[0] + ']' // Mark the first trigger as being active
  fs.writeFileSync(pathTo('trigger'), triggers.join(' ') + '\n', 'utf8')
}

// Helper function that restores the /brightness file to a known state
function restoreBrightness () {

  fs.writeFileSync(pathTo('brightness'), '0\n', 'utf8')
}

describe('LEDController', function () {

  beforeEach(function () {
    // Override the default root path for LEDs so we can predictably test this thing...
    LEDController.ROOT = path.join(__dirname, 'fakeleds')
    ledGreen = new LEDController('green:led0')
    ledRed = new LEDController('red:led1')
  })

  it('should throw when no identifier given', function () {
    (function () {
      led = new LEDController()
    }).should.throw()
  })

  it('should throw when trying to control non-existent LED', function () {
    (function () {
      led = new LEDController('ifeellucky')
    }).should.throw()
  })

  it('should not throw when only one LED is available and no identifier given', function () {
    // Monkey-patching
    var discoverFunc = LEDController.discover
    LEDController.discover = function () {
      return ['green:led0']   // Only one LED available on this system...
    }

    try {
      led = new LEDController()
    } catch (e) {
      LEDController.discover = discoverFunc
      throw e
    }

    LEDController.discover = discoverFunc
    led.id.should.equal('green:led0')
  })

  it('should have property RATE equal to 1', function () {
    LEDController.RATE.should.equal(1)
  })

  describe('property:id', function () {

    it('should be what is passed to the constructor (the LED\'s actual ID)', function () {
      ledGreen.id.should.equal('green:led0')
    })
  })

  describe('property:location', function () {

    it('should be combination of LEDController.ROOT and LED\'s identifier', function () {
      ledGreen.location
        .should.be.String
        .and.equal(path.join(LEDController.ROOT, 'green:led0'))
    })
  })

  describe('property:brightness', function () {

    beforeEach(restoreBrightness)
    after(restoreBrightness)

    it('should have property min and equal 0', function () {

      ledGreen.brightness.min
        .should.be.Number
        .and.equal(0)
    })

    it('should have property max and equal to /max_brightness', function () {
      var contents = fs.readFileSync(
        pathTo('max_brightness')
      , 'utf8'
      ).trim()

      ledGreen.brightness.max
        .should.be.Number
        .and.equal(parseInt(contents))
    })

    it('should have property cur and equal to /brightness', function () {
      var contents = fs.readFileSync(
        pathTo('brightness')
      , 'utf8'
      ).trim()

      ledGreen.brightness.cur
        .should.be.Number
        .and.equal(parseInt(contents))
    })

    it('should reflect runtime changes in brightness.cur', function () {
      var original = parseInt(fs.readFileSync(
        pathTo('brightness')
      , 'utf8'
      ).trim())
      , modified = 100

      // Just making sure we are REALLY changing the value... Ya ne'er know
      original.should.not.equal(modified)

      // Modify the brightness and check if the property updated the value, too
      fs.writeFileSync(
        pathTo('brightness')
      , modified.toString(), 'utf8'
      )

      ledGreen.brightness.cur.should.equal(100)
    })
  })

  describe('property:triggers', function () {

    afterEach(restoreTriggers)
    after(restoreTriggers)

    it('should have property all and equal to /trigger', function () {
      ledGreen.triggers.all.should.containDeep(knownTriggers)
    })

    it('should have property cur and equal to currently selected trigger in /trigger', function () {
      var current = '[' + ledGreen.triggers.cur + ']'
        , contents = fs.readFileSync(pathTo('trigger'), 'utf8')

      contents.indexOf(current).should.not.equal(-1)
    })

    it('should reflect runtime changes in triggers.cur', function () {
      var modified = knownTriggers.slice() // shallow copy

      ledGreen.triggers.cur.should.not.equal(3) // Are we actually changing stuff?

      modified[3] = '[' + modified[3] + ']' // I just randomly chose 3.
      fs.writeFileSync(pathTo('trigger'), modified.join(' ') + '\n', 'utf8')

      ledGreen.triggers.cur.should.equal(knownTriggers[3])
    })
  })

  describe(':discover()', function () {

    it('should list the LEDs available in LEDController.ROOT', function () {
      var contents = fs.readdirSync(LEDController.ROOT)

      LEDController.discover()
        .should.be.Array
        .and.containDeep(contents)
    })

    it('should recognise valid LEDs and ignore random folders', function () {
      LEDController.ROOT = __dirname    // Set the root to the test dir

      // There are no real LEDs in the test folder!
      LEDController.discover()
        .should.be.Array
        .and.have.lengthOf(0)
    })

    it('should not throw when no LEDs are available and return empty array', function () {
      var retVal

      (function () {
        LEDController.ROOT = '/some/random/junk'
        retVal = LEDController.discover()
      }).should.not.throw()

      retVal.should.be.empty
    })
  })

  describe(':register()', function () {

    afterEach(function () {
      // Cleanup
      delete LEDController.prototype.dummymethod
    })

    it('should accept functions as handlers', function () {
      (function () {
        LEDController.register('dummymethod', function () {})
      }).should.not.throw()
    })

    it('should throw on handlers not being functions', function () {
      (function () {
        LEDController.register('dummymethod', 'ladida')
      }).should.throw()

      ;(function () {
        LEDController.register('dummymethod', 42)
      }).should.throw()

      ;(function () {
        LEDController.register('dummymethod', undefined)
      }).should.throw()
    })

    it('should put the handler onto the prototype', function () {
      var handler = function () {}

      LEDController.register('dummymethod', handler)

      LEDController.prototype.dummymethod
        .should.be.a.Function
        .and.should.not.equal(handler)    // Because we wrap it in our own function
    })

    it('should throw when attempting to register the same handler more than once', function () {
      // This should pass - registering it for the first time...
      (function () {
        LEDController.register('dummymethod', function () {})
      }).should.not.throw()
      // And here it should throw
      ;(function () {
        LEDController.register('dummymethod', function () {})
      }).should.throw()
    })

    it('should call the handler when calling the attached method', function (done) {
      var handler = function (input) {
        input.should.equal('test')

        process.nextTick(done)
      }

      LEDController.register('dummymethod', handler)
      ledGreen.dummymethod('test')
    })

    it('should pass all errors thrown from handlers to the method callback', function (done) {
      LEDController.register('dummymethod', function () {
        // Imagine an error in my custom serialiser happened...
        throw new Error('test')
      })

      ledGreen.dummymethod('input', function (err) {
        err.message.should.equal('test')

        done()
      })
    })

    it('should call the callback only once, even if more blinks are in queue', function (done) {
      LEDController.register('dummymethod', function () {
        // Just two superfast blink events...
        return [{ rate: 10000 }, { rate: 10000 }]
      })

      // Mocha will surely complain about calling done multiple times
      ledGreen.dummymethod('test', done)
    })

    it('should make the attached function to return this', function () {
      LEDController.register('dummymethod', function () {})

      ledGreen.dummymethod().should.be.exactly(ledGreen)
    })
  })

  describe('.trigger()', function () {

    beforeEach(restoreTriggers)
    after(restoreTriggers)

    it('should write the desired trigger to /trigger', function (done) {
      ledGreen.trigger('default-on', function () {
        fs.readFileSync(pathTo('trigger'), 'utf8').trim().should.equal('default-on')

        done()
      })
    })

    it('should return this', function (done) {
      ledGreen.trigger('default-on', done).should.be.exactly(ledGreen)
    })

    it('should error out on invalid trigger name', function (done) {
      ledGreen.trigger('something', function (err) {

        err.should.be.Error
        err.message.should.containEql('something')

        done()
      })
    })

    it('should throw on error when no callback given', function (done) {
      // Warning - fragile test! If it fails, it crashes the whole test suite. Not sure what
      // exactly is going on or how to fix it... Just FYI.
      var d = domain.create()

      d.on('error', function (err) {
        err.should.be.an.Error
        err.message.should.containEql('Unsupported trigger')

        d.dispose()
        done()
      })

      d.run(function () {
        ledGreen.trigger('something')
      })
    })
  })

  describe('.turnOn() / .turnOff()', function () {

    beforeEach(restoreBrightness)
    after(restoreBrightness)

    it('.turnOn() should write to /brightness its maximum brightness', function (done) {
      ledGreen.turnOn(function () {
        var contents = fs.readFileSync(pathTo('brightness'), 'utf8').trim()
          , maxBrightness = fs.readFileSync(pathTo('max_brightness'), 'utf8').trim()

        contents.should.equal(maxBrightness)
        done()
      })
    })

    it('.turnOn() should return this', function (done) {
      ledGreen.turnOn(done).should.be.exactly(ledGreen)
    })

    it('.turnOff() should write to /brightness 0', function (done) {
      ledGreen.turnOff(function () {
        var contents = parseInt(fs.readFileSync(pathTo('brightness'), 'utf8').trim())

        contents.should.equal(0)
        done()
      })
    })

    it('.turnOff() should return this', function (done) {
      ledGreen.turnOff(done).should.be.exactly(ledGreen)
    })
  })

  describe('.blink()', function () {

    // TODO
  })

  describe('.toString()', function () {

    it('should return proper object class name', function () {
      ledGreen.toString().should.equal('[object LEDController]')
    })
  })

  describe('.valueOf()', function () {

    it('should return the LED\'s current brightness', function () {

      ledGreen.valueOf().should.equal(ledGreen.brightness.cur)
    })
  })
})
<|endoftext|>


<commit_before>describe("Shader", function() {
    var sandbox = null;
    var material = null;
    var obj;
    var geo;
    var director;

    var gl;
    var state;

    beforeEach(function () {
        sandbox = sinon.sandbox.create();

        testTool.clearAndOpenContractCheck(sandbox);

        var data = sceneTool.prepareGameObjectAndAddToScene(false, null, lightMaterialTool.create());
        obj = data.gameObject;
        geo = data.geometry;
        material = data.material;

        state = stateTool.createAndSetFakeGLState(sandbox);

        gl = stateTool.getGLFromFakeGLState(state);
    });
    afterEach(function () {
        testTool.clear(sandbox);
        sandbox.restore();
    });

    describe("init", function() {
        beforeEach(function(){
        });

        describe("init shader", function() {
            function initShader() {
                // directorTool.init(state);
                directorTool.loopBody(state);
            }

            beforeEach(function(){
                directorTool.init(state);
            });

            it("if program already exist, return", function () {
                initShader();
                initShader();

                expect(gl.createProgram).toCalledOnce();
            });

            it("create vs and fs shader", function () {
                initShader();

                expect(gl.createShader.withArgs(gl.VERTEX_SHADER)).toCalledOnce();
                expect(gl.createShader.withArgs(gl.FRAGMENT_SHADER)).toCalledOnce();
            });

            describe("compile vs and fs shader", function(){
                it("compile", function () {
                    initShader();

                    expect(gl.shaderSource).toCalledTwice();
                    expect(gl.compileShader).toCalledTwice();
                });

                describe("check COMPILE_STATUS", function () {
                    it("invoke gl.getShaderParameter", function () {
                        initShader();

                        expect(gl.getShaderParameter).toCalledTwice();
                    });
                    it("if gl.getShaderParameter return false, log shader info", function () {
                        sandbox.stub(wd.Log, "log");
                        gl.getShaderParameter.withArgs(sinon.match.any, gl.COMPILE_STATUS).returns(false);

                        initShader();

                        // expect(gl.getShaderParameter).toCalledTwice();
                        expect(gl.getShaderInfoLog).toCalledTwice();
                        expect(wd.Log.log).toCalled();
                    });
                });
            });

            it("attach vs and fs shader", function () {
                initShader();

                expect(gl.attachShader).toCalledTwice();
            });
            it("to avoid \"Attribute 0 is disabled.\". This has significant performance penalty", function () {
                initShader();

                expect(gl.bindAttribLocation.withArgs(sinon.match.any, 0, "a_position")).toCalledOnce();
            });

            describe("link program", function () {
                it("test", function () {
                    initShader();

                    expect(gl.linkProgram).toCalledOnce();
                });
                it("check error", function () {
                    gl.getProgramParameter.withArgs(sinon.match.any, gl.LINK_STATUS).returns(false);
                    gl.getProgramInfoLog.returns("err");

                    expect(function(){
                        initShader();
                    }).toThrow("link program error:err");
                });
            });

            it("delete vs and fs shader after link", function () {
                initShader();

                expect(gl.deleteShader).toCalledTwice();
                expect(gl.deleteShader).toCalledAfter(gl.linkProgram);
            });
        });
    });

    describe("getUniformLocation", function(){
        var pos;

        beforeEach(function(){
            pos = 1;
        });

        describe("test cache", function(){
            beforeEach(function(){
                // device.gl.getUniformLocation.returns(pos);
            });

            it("if cached, return cached data", function () {
                gl.getUniformLocation.withArgs(sinon.match.any, "u_mMatrix").returns(pos);

                directorTool.init(state);
                directorTool.loopBody(state);
                directorTool.loopBody(state);

                expect(gl.getUniformLocation.withArgs(sinon.match.any, "u_mMatrix")).toCalledOnce();
            });
        });
    });

    describe("getAttributeLocation", function(){
        var pos;

        beforeEach(function(){
            pos = 1;
        });

        describe("test cache", function() {
            beforeEach(function () {
            });

            it("if cached, return cached data", function () {
                gl.getAttribLocation.withArgs(sinon.match.any, "a_position").returns(pos);

                directorTool.init(state);
                directorTool.loopBody(state);
                directorTool.loopBody(state);

                expect(gl.getAttribLocation.withArgs(sinon.match.any, "a_position")).toCalledOnce();
            });
        });
    });

    // describe("dispose", function() {
    //     beforeEach(function(){
    //
    //     });
    //
    //     it("", function(){
    //     });
    // });

    describe("one type material map to multi shader index", function() {
        beforeEach(function(){

        });

        it("basic material with map send a_texCoords, but the material with no map not send a_texCoords", function(){
            sceneTool.removeGameObject(obj);

            var data = sceneTool.prepareGameObjectAndAddToScene();
            obj = data.gameObject;
            geo = data.geometry;
            material = data.material;

            bufferTool.makeCreateDifferentBuffer(gl);

            var texture = textureTool.create();
            textureTool.setSource(texture, {});

            basicMaterialTool.addMap(material, texture);

            var material2;

            material2 = basicMaterialTool.create();

            var obj2 = sceneTool.createGameObject(null, material2);
            sceneTool.addGameObject(obj2);

            var name = "a_texCoord",
            size = 2;

            var pos1 = 10;
            var pos2 = 11;

            gl.getAttribLocation.withArgs(sinon.match.any, name).onCall(0).returns(pos1);

            gl.getAttribLocation.withArgs(sinon.match.any, name).onCall(1).returns(pos2);

            directorTool.init(state);

            var data = geometryTool.getTexCoords(geo);

            directorTool.loopBody(state);

            expect(gl.createBuffer.callCount).toEqual(5);
            expect(gl.vertexAttribPointer).toCalledWith(pos1,size,"FLOAT",false,0,0);
            expect(gl.vertexAttribPointer).not.toCalledWith(pos2,size,"FLOAT",false,0,0);

        });
    });

    it("glsl shouldn't be changed after first init shader", function () {
        directorTool.init(state);
        directorTool.loopBody(state);

        var shaderSourceCallCount = gl.shaderSource.callCount;

        var texture = textureTool.create();
        textureTool.setSource(texture, {});

        lightMaterialTool.setSpecularMap(material, texture);

        directorTool.loopBody(state);

        expect(gl.shaderSource.callCount).toEqual(shaderSourceCallCount)
    });

    describe("shader", function() {
        var sandbox = null;
        var gl;
        var state;
        var material;

        var MaterialData = wd.MaterialData;
        var material_config = wd.webgl1_material_config;

        beforeEach(function () {
            sandbox = sinon.sandbox.create();

            testTool.clearAndOpenContractCheck(sandbox);

            state = stateTool.createAndSetFakeGLState(sandbox);

            gl = stateTool.getGLFromFakeGLState(state);

            var data = sceneTool.prepareGameObjectAndAddToScene(false, null, lightMaterialTool.create());

            material = data.material;
        });
        afterEach(function () {
            testTool.clear(sandbox);
            sandbox.restore();
        });

        describe("use shader for material", function(){
            function isInitShader(expect, gl) {
                expect(gl.createProgram.callCount).toEqual(1);
            }

            function getUsedShaderShaderIndex() {
                return 0;
            }

            it("init material shader", function () {
                directorTool.init(state);
                directorTool.loopBody(state);

                isInitShader(expect, gl);
            });
            it("set shader index", function () {
                directorTool.init(state);
                directorTool.loopBody(state);

                expect(MaterialData.shaderIndices[material.index]).toEqual(getUsedShaderShaderIndex());
            });
        });

        describe("optimize", function() {
            beforeEach(function(){
            });

            it("only init the shader of the same shader name once", function () {
                sceneTool.addGameObject(sceneTool.createGameObject(null, lightMaterialTool.create()));

                directorTool.init(state);
                directorTool.loopBody(state);

                directorTool.loopBody(state);

                expect(gl.createProgram.callCount).toEqual(1);
            });

            it("only exec branch func to get material shader lib name array of the same shader once", function () {
                function getFirstBranchShaderLibItem(material_config) {
                    return material_config.shaders.materialShaders.FrontRenderLight.filter(function (data) {
                        return data.branch !== undefined;
                    })[0];
                }

                function stubBranchFunc(sandbox, material_config) {
                    sandbox.stub(getFirstBranchShaderLibItem(material_config), "branch");
                }

                stubBranchFunc(sandbox, material_config);

                directorTool.init(state);
                directorTool.loopBody(state);

                directorTool.loopBody(state);

                expect(getFirstBranchShaderLibItem(material_config).branch).toCalledOnce();
            });
        });
    });
});
<commit_msg>refactor: rename test->webgl1->ShaderSpec to shaderSpec<commit_after><|endoftext|>


<commit_before>//index.js
//获取应用实例
var app = getApp()

Page({
  data: {
    mallName:wx.getStorageSync('mallName'),
    goodsList:[],
    isNeedLogistics:0, // 是否需要物流信息
    allGoodsPrice:0,
    yunPrice:0,

    goodsJsonStr:""
  },
  onShow : function () {
    this.initShippingAddress();
  },
  onLoad: function (e) {
    var that = this;
    var shopList = [];
    var shopCarInfoMem = wx.getStorageSync('shopCarInfo');
    if (shopCarInfoMem && shopCarInfoMem.shopList) {
      shopList = shopCarInfoMem.shopList
    }
    var isNeedLogistics = 0;
    var allGoodsPrice = 0;

    var goodsJsonStr = "[";
    for (var i =0; i < shopList.length; i++) {
      var carShopBean = shopList[i];
      console.log(carShopBean);
      if (carShopBean.logisticsType > 0) {
        isNeedLogistics = 1;
      }
      allGoodsPrice += carShopBean.price * carShopBean.number

      var goodsJsonStrTmp = '';
      if (i > 0){
        goodsJsonStrTmp = ",";
      }
      goodsJsonStrTmp += '{"goodsId":'+ carShopBean.goodsId +',"number":'+ carShopBean.number +',"propertyChildIds":"'+ carShopBean.propertyChildIds +'","logisticsType":'+ carShopBean.logisticsType +'}';
      goodsJsonStr += goodsJsonStrTmp;
    }
    goodsJsonStr += "]";
    that.setData({
      goodsList:shopList,
      isNeedLogistics:isNeedLogistics,
      allGoodsPrice:allGoodsPrice,
      goodsJsonStr:goodsJsonStr
    });

  },
  createOrder:function (e) {
    wx.showLoading();
    var that = this;
    var loginToken = app.globalData.token // 用户登录 token
    var remark = e.detail.value.remark; // 备注信息

    var postData = {
      token: loginToken,
      goodsJsonStr: that.data.goodsJsonStr,
      remark: remark
    };
    postData.aaaa = 1234;
    if (that.data.isNeedLogistics > 0) {
      postData.provinceId = that.data.curAddressData.provinceId;
      postData.cityId = that.data.curAddressData.cityId;
      postData.districtId = that.data.curAddressData.districtId;
      postData.address = that.data.curAddressData.address;
      postData.linkMan = that.data.curAddressData.linkMan;
      postData.mobile = that.data.curAddressData.mobile;
      postData.code = that.data.curAddressData.code;
    }

    wx.request({
      url: 'https://api.it120.cc/'+ app.globalData.subDomain +'/order/create',
      method:'POST',
      header: {
        'content-type': 'application/x-www-form-urlencoded'
      },
      data: postData, // 设置请求的 参数
      success: (res) =>{
        wx.hideLoading();
        console.log(res.data);
        if (res.data.code != 0) {
          wx.showModal({
            title: '错误',
            content: res.data.msg,
            showCancel: false
          })
          return;
        }
        // 清空购物车数据
        wx.removeStorageSync('shopCarInfo');
        // 下单成功，跳转到订单管理界面
        wx.reLaunch({
          url: "/pages/order-list/index"
        });
      }
    })
  },
  initShippingAddress: function () {
    var that = this;
    wx.request({
      url: 'https://api.it120.cc/'+ app.globalData.subDomain +'/user/shipping-address/default',
      data: {
        token:app.globalData.token
      },
      success: (res) =>{
        console.log(res.data)
        if (res.data.code == 0) {
          that.setData({
            curAddressData:res.data.data
          });
        }
      }
    })
  },
  addAddress: function () {
    wx.navigateTo({
      url:"/pages/address-add/index"
    })
  },
  selectAddress: function () {
    wx.navigateTo({
      url:"/pages/select-address/index"
    })
  }
})
<commit_msg>下单的时候没设置收货地址增加提示<commit_after>//index.js
//获取应用实例
var app = getApp()

Page({
  data: {
    mallName:wx.getStorageSync('mallName'),
    goodsList:[],
    isNeedLogistics:0, // 是否需要物流信息
    allGoodsPrice:0,
    yunPrice:0,

    goodsJsonStr:""
  },
  onShow : function () {
    this.initShippingAddress();
  },
  onLoad: function (e) {
    var that = this;
    var shopList = [];
    var shopCarInfoMem = wx.getStorageSync('shopCarInfo');
    if (shopCarInfoMem && shopCarInfoMem.shopList) {
      shopList = shopCarInfoMem.shopList
    }
    var isNeedLogistics = 0;
    var allGoodsPrice = 0;

    var goodsJsonStr = "[";
    for (var i =0; i < shopList.length; i++) {
      var carShopBean = shopList[i];
      console.log(carShopBean);
      if (carShopBean.logisticsType > 0) {
        isNeedLogistics = 1;
      }
      allGoodsPrice += carShopBean.price * carShopBean.number

      var goodsJsonStrTmp = '';
      if (i > 0){
        goodsJsonStrTmp = ",";
      }
      goodsJsonStrTmp += '{"goodsId":'+ carShopBean.goodsId +',"number":'+ carShopBean.number +',"propertyChildIds":"'+ carShopBean.propertyChildIds +'","logisticsType":'+ carShopBean.logisticsType +'}';
      goodsJsonStr += goodsJsonStrTmp;
    }
    goodsJsonStr += "]";
    that.setData({
      goodsList:shopList,
      isNeedLogistics:isNeedLogistics,
      allGoodsPrice:allGoodsPrice,
      goodsJsonStr:goodsJsonStr
    });

  },
  createOrder:function (e) {
    wx.showLoading();
    var that = this;
    var loginToken = app.globalData.token // 用户登录 token
    var remark = e.detail.value.remark; // 备注信息

    var postData = {
      token: loginToken,
      goodsJsonStr: that.data.goodsJsonStr,
      remark: remark
    };
    postData.aaaa = 1234;
    if (that.data.isNeedLogistics > 0) {
      if (!that.data.curAddressData) {
        wx.hideLoading();
        wx.showModal({
          title: '错误',
          content: '请选择您的收货地址',
          showCancel: false
        })
        return;
      }
      postData.provinceId = that.data.curAddressData.provinceId;
      postData.cityId = that.data.curAddressData.cityId;
      postData.districtId = that.data.curAddressData.districtId;
      postData.address = that.data.curAddressData.address;
      postData.linkMan = that.data.curAddressData.linkMan;
      postData.mobile = that.data.curAddressData.mobile;
      postData.code = that.data.curAddressData.code;
    }

    wx.request({
      url: 'https://api.it120.cc/'+ app.globalData.subDomain +'/order/create',
      method:'POST',
      header: {
        'content-type': 'application/x-www-form-urlencoded'
      },
      data: postData, // 设置请求的 参数
      success: (res) =>{
        wx.hideLoading();
        console.log(res.data);
        if (res.data.code != 0) {
          wx.showModal({
            title: '错误',
            content: res.data.msg,
            showCancel: false
          })
          return;
        }
        // 清空购物车数据
        wx.removeStorageSync('shopCarInfo');
        // 下单成功，跳转到订单管理界面
        wx.reLaunch({
          url: "/pages/order-list/index"
        });
      }
    })
  },
  initShippingAddress: function () {
    var that = this;
    wx.request({
      url: 'https://api.it120.cc/'+ app.globalData.subDomain +'/user/shipping-address/default',
      data: {
        token:app.globalData.token
      },
      success: (res) =>{
        console.log(res.data)
        if (res.data.code == 0) {
          that.setData({
            curAddressData:res.data.data
          });
        }
      }
    })
  },
  addAddress: function () {
    wx.navigateTo({
      url:"/pages/address-add/index"
    })
  },
  selectAddress: function () {
    wx.navigateTo({
      url:"/pages/select-address/index"
    })
  }
})
<|endoftext|>


<commit_before>import React, { PropTypes } from 'react'

/**
 * The public higher-order component API for re-rendering as the
 * location changes. Also, passes ...context.router as props.
 */
const withRouter = (component) => {
  return class extends React.Component {
    static displayName = `withRouter(${component.displayName || component.name})`

    static contextTypes = {
      router: PropTypes.shape({
        listen: PropTypes.func.isRequired
      }).isRequired
    }

    componentWillMount() {
      // Start listening here so we can <Redirect> on the initial render.
      this.unlisten = this.context.router.listen(() => this.forceUpdate())
    }

    componentWillUnmount() {
      this.unlisten()
    }

    render() {
      return React.createElement(component, {
        ...this.props,
        ...this.context.router
      })
    }
  }
}

export default withRouter
<commit_msg>Doc tweak<commit_after>import React, { PropTypes } from 'react'

/**
 * A public higher-order component for re-rendering as the
 * location changes. Also, passes ...context.router as props.
 */
const withRouter = (component) => {
  return class extends React.Component {
    static displayName = `withRouter(${component.displayName || component.name})`

    static contextTypes = {
      router: PropTypes.shape({
        listen: PropTypes.func.isRequired
      }).isRequired
    }

    componentWillMount() {
      // Start listening here so we can <Redirect> on the initial render.
      this.unlisten = this.context.router.listen(() => this.forceUpdate())
    }

    componentWillUnmount() {
      this.unlisten()
    }

    render() {
      return React.createElement(component, {
        ...this.props,
        ...this.context.router
      })
    }
  }
}

export default withRouter
<|endoftext|>


<commit_before>import { clearSelection } from '../utils/selection.js'
import { prevent } from '../utils/event.js'
import { addEvt, cleanEvt } from '../utils/touch.js'

export default {
  props: {
    target: {
      type: [Boolean, String],
      default: true
    },
    noParentEvent: Boolean,
    contextMenu: Boolean
  },

  watch: {
    contextMenu (val) {
      if (this.anchorEl !== void 0) {
        this.__unconfigureAnchorEl()
        this.__configureAnchorEl(val)
      }
    },

    target () {
      if (this.anchorEl !== void 0) {
        this.__unconfigureAnchorEl()
      }

      this.__pickAnchorEl()
    },

    noParentEvent (val) {
      if (this.anchorEl !== void 0) {
        if (val === true) {
          this.__unconfigureAnchorEl()
        }
        else {
          this.__configureAnchorEl()
        }
      }
    }
  },

  methods: {
    __showCondition (evt) {
      // abort with no parent configured or on multi-touch
      if (this.anchorEl === void 0) {
        return false
      }
      if (evt === void 0) {
        return true
      }
      return evt.touches === void 0 || evt.touches.length <= 1
    },

    __contextClick (evt) {
      this.hide(evt)
      this.$nextTick(() => {
        this.show(evt)
      })
      prevent(evt)
    },

    __toggleKey (evt) {
      if (evt !== void 0 && evt.keyCode === 13 && evt.qKeyEvent !== true) {
        this.toggle(evt)
      }
    },

    __mobileTouch (evt) {
      clearTimeout(this.touchTimer)

      if (this.showing === true && evt !== void 0) {
        clearSelection()
      }

      if (this.__showCondition(evt) !== true) {
        return
      }

      this.hide(evt)
      this.anchorEl.classList.add('non-selectable')

      this.touchTimer = setTimeout(() => {
        this.show(evt)
        this.anchorEl.classList.remove('non-selectable')
      }, 300)
    },

    __unconfigureAnchorEl () {
      cleanEvt(this, 'anchor')
    },

    __configureAnchorEl (context = this.contextMenu) {
      if (this.noParentEvent === true || this.anchorEl === void 0) { return }

      let evts

      if (context === true) {
        if (this.$q.platform.is.mobile === true) {
          evts = [
            [ this.anchorEl, 'touchstart', '__mobileTouch', 'passive' ]
          ]
        }
        else {
          evts = [
            [ this.anchorEl, 'click', 'hide', 'passive' ],
            [ this.anchorEl, 'contextmenu', '__contextClick', 'notPassive' ]
          ]
        }
      }
      else {
        evts = [
          [ this.anchorEl, 'click', 'toggle', 'passive' ],
          [ this.anchorEl, 'keyup', '__toggleKey', 'passive' ]
        ]
      }

      addEvt(this, 'anchor', evts)
    },

    __setAnchorEl (el) {
      this.anchorEl = el
      while (this.anchorEl.classList.contains('q-anchor--skip')) {
        this.anchorEl = this.anchorEl.parentNode
      }
      this.__configureAnchorEl()
    },

    __pickAnchorEl () {
      if (this.target && typeof this.target === 'string') {
        const el = document.querySelector(this.target)
        if (el !== null) {
          this.anchorEl = el
          this.__configureAnchorEl()
        }
        else {
          this.anchorEl = void 0
          console.error(`Anchor: target "${this.target}" not found`, this)
        }
      }
      else if (this.target !== false) {
        this.__setAnchorEl(this.parentEl)
      }
      else {
        this.anchorEl = void 0
      }
    }
  },

  created () {
    if (
      typeof this.__configureScrollTarget === 'function' &&
      typeof this.__unconfigureScrollTarget === 'function'
    ) {
      this.noParentEventWatcher = this.$watch('noParentEvent', () => {
        if (this.scrollTarget !== void 0) {
          this.__unconfigureScrollTarget()
          this.__configureScrollTarget()
        }
      })
    }
  },

  mounted () {
    this.parentEl = this.$el.parentNode
    this.__pickAnchorEl()

    if (this.value === true && this.anchorEl === void 0) {
      this.$emit('input', false)
    }
  },

  beforeDestroy () {
    clearTimeout(this.touchTimer)
    this.noParentEventWatcher !== void 0 && this.noParentEventWatcher()
    this.__anchorCleanup !== void 0 && this.__anchorCleanup()
    this.__unconfigureAnchorEl()
  }
}
<commit_msg>fix(anchor-mixin): Add cleanup events for context menu #5638 (#5640)<commit_after>import { clearSelection } from '../utils/selection.js'
import { prevent } from '../utils/event.js'
import { addEvt, cleanEvt, getTouchTarget } from '../utils/touch.js'

export default {
  props: {
    target: {
      type: [Boolean, String],
      default: true
    },
    noParentEvent: Boolean,
    contextMenu: Boolean
  },

  watch: {
    contextMenu (val) {
      if (this.anchorEl !== void 0) {
        this.__unconfigureAnchorEl()
        this.__configureAnchorEl(val)
      }
    },

    target () {
      if (this.anchorEl !== void 0) {
        this.__unconfigureAnchorEl()
      }

      this.__pickAnchorEl()
    },

    noParentEvent (val) {
      if (this.anchorEl !== void 0) {
        if (val === true) {
          this.__unconfigureAnchorEl()
        }
        else {
          this.__configureAnchorEl()
        }
      }
    }
  },

  methods: {
    __showCondition (evt) {
      // abort with no parent configured or on multi-touch
      if (this.anchorEl === void 0) {
        return false
      }
      if (evt === void 0) {
        return true
      }
      return evt.touches === void 0 || evt.touches.length <= 1
    },

    __contextClick (evt) {
      this.hide(evt)
      this.$nextTick(() => {
        this.show(evt)
      })
      prevent(evt)
    },

    __toggleKey (evt) {
      if (evt !== void 0 && evt.keyCode === 13 && evt.qKeyEvent !== true) {
        this.toggle(evt)
      }
    },

    __mobileCleanup (evt) {
      this.anchorEl.classList.remove('non-selectable')
      clearTimeout(this.touchTimer)

      if (this.showing === true && evt !== void 0) {
        clearSelection()
      }
    },

    __mobilePrevent: prevent,

    __mobileTouch (evt) {
      this.__mobileCleanup(evt)

      if (this.__showCondition(evt) !== true) {
        return
      }

      this.hide(evt)
      this.anchorEl.classList.add('non-selectable')

      const target = getTouchTarget(evt.target)
      addEvt(this, 'anchor', [
        [ target, 'touchmove', '__mobileCleanup', 'passive' ],
        [ target, 'touchend', '__mobileCleanup', 'passive' ],
        [ target, 'touchcancel', '__mobileCleanup', 'passive' ],
        [ this.anchorEl, 'contextmenu', '__mobilePrevent', 'notPassive' ]
      ])

      this.touchTimer = setTimeout(() => {
        this.show(evt)
      }, 300)
    },

    __unconfigureAnchorEl () {
      cleanEvt(this, 'anchor')
    },

    __configureAnchorEl (context = this.contextMenu) {
      if (this.noParentEvent === true || this.anchorEl === void 0) { return }

      let evts

      if (context === true) {
        if (this.$q.platform.is.mobile === true) {
          evts = [
            [ this.anchorEl, 'touchstart', '__mobileTouch', 'passive' ]
          ]
        }
        else {
          evts = [
            [ this.anchorEl, 'click', 'hide', 'passive' ],
            [ this.anchorEl, 'contextmenu', '__contextClick', 'notPassive' ]
          ]
        }
      }
      else {
        evts = [
          [ this.anchorEl, 'click', 'toggle', 'passive' ],
          [ this.anchorEl, 'keyup', '__toggleKey', 'passive' ]
        ]
      }

      addEvt(this, 'anchor', evts)
    },

    __setAnchorEl (el) {
      this.anchorEl = el
      while (this.anchorEl.classList.contains('q-anchor--skip')) {
        this.anchorEl = this.anchorEl.parentNode
      }
      this.__configureAnchorEl()
    },

    __pickAnchorEl () {
      if (this.target && typeof this.target === 'string') {
        const el = document.querySelector(this.target)
        if (el !== null) {
          this.anchorEl = el
          this.__configureAnchorEl()
        }
        else {
          this.anchorEl = void 0
          console.error(`Anchor: target "${this.target}" not found`, this)
        }
      }
      else if (this.target !== false) {
        this.__setAnchorEl(this.parentEl)
      }
      else {
        this.anchorEl = void 0
      }
    }
  },

  created () {
    if (
      typeof this.__configureScrollTarget === 'function' &&
      typeof this.__unconfigureScrollTarget === 'function'
    ) {
      this.noParentEventWatcher = this.$watch('noParentEvent', () => {
        if (this.scrollTarget !== void 0) {
          this.__unconfigureScrollTarget()
          this.__configureScrollTarget()
        }
      })
    }
  },

  mounted () {
    this.parentEl = this.$el.parentNode
    this.__pickAnchorEl()

    if (this.value === true && this.anchorEl === void 0) {
      this.$emit('input', false)
    }
  },

  beforeDestroy () {
    clearTimeout(this.touchTimer)
    this.noParentEventWatcher !== void 0 && this.noParentEventWatcher()
    this.__anchorCleanup !== void 0 && this.__anchorCleanup()
    this.__unconfigureAnchorEl()
  }
}
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import styles from './Input.scss';

const InputTypeNumber = 'number';
const InputTypeText = 'text';

export default class Input extends Component {
  static propTypes = {
    value: PropTypes.any,
    player: PropTypes.number,
    type: React.PropTypes.oneOf([InputTypeText, InputTypeNumber]),
    onChange: PropTypes.func
  };

  static defaultProps = {
    type: InputTypeNumber
  };

  handleFocus(event) {
    event.target.select();
  }

  handleChange(event) {
    this.props.onChange(this.props.player, event.target.value);
  }

  render() {
    return <input className={(this.props.type === InputTypeNumber) ? styles.number : styles.normal} type={this.props.type} defaultValue={this.props.value} {...this.state} onFocus={this.handleFocus.bind(this)} onChange={this.handleChange.bind(this)}/>;
  }

}
<commit_msg>fix select on ios<commit_after>import React, { Component, PropTypes } from 'react';
import styles from './Input.scss';

const InputTypeNumber = 'number';
const InputTypeText = 'text';

export default class Input extends Component {
  static propTypes = {
    value: PropTypes.any,
    defaultValue: PropTypes.any,
    player: PropTypes.number,
    type: React.PropTypes.oneOf([InputTypeText, InputTypeNumber]),
    onChange: PropTypes.func
  };

  static defaultProps = {
    type: InputTypeNumber
  };

  handleFocus(event) {
    const t = event.target;
    event.target.select();
    setTimeout(() => {
      t.setSelectionRange(0, 9999);
    }, 1);
  }

  handleChange(event) {
    this.props.onChange(this.props.player, event.target.value);
  }

  render() {
    return <input className={(this.props.type === InputTypeNumber) ? styles.number : styles.normal} type={this.props.type} {...this.props} {...this.state} onFocus={this.handleFocus.bind(this)} onChange={this.handleChange.bind(this)}/>;
  }

}
<|endoftext|>


<commit_before>#!/usr/bin/env node

const yargs = require('yargs');
const path = require('path');

const FtpSrv = require('../src');
const errors = require('../src/errors');

const args = setupYargs();
const state = setupState(args);
startFtpServer(state);

function setupYargs() {
  return yargs
    .option('credentials', {
      alias: 'c',
      describe: 'Load user & pass from json file',
      normalize: true
    })
    .option('username', {
      describe: 'Blank for anonymous',
      type: 'string',
      default: ''
    })
    .option('password', {
      describe: 'Password for given username',
      type: 'string'
    })
    .option('root', {
      alias: 'r',
      describe: 'Default root directory for users',
      type: 'string',
      normalize: true
    })
    .option('read-only', {
      describe: 'Disable write actions such as upload, delete, etc',
      boolean: true,
      default: false
    })
    .option('pasv_url', {
      describe: 'URL to provide for passive connections',
      type: 'string'
    })
    .option('pasv_min', {
      describe: 'Starting point to use when creating passive connections',
      type: 'number',
      default: 1024
    })
    .option('pasv_max', {
      describe: 'Ending port to use when creating passive connections',
      type: 'number',
      default: 65535
    })
    .parse();
}

function setupState(_args) {
  const _state = {};

  function setupOptions() {
    if (_args._ && _args._.length > 0) {
      _state.url = _args._[0];
    }
    _state.pasv_url = _args.pasv_url;
    _state.pasv_min = _args.pasv_min;
    _state.pasv_max = _args.pasv_max;
    _state.anonymous = _args.username === '';
  }

  function setupRoot() {
    const dirPath = _args.root;
    if (dirPath) {
      _state.root = dirPath;
    } else {
      _state.root = process.cwd();
    }
  }

  function setupCredentials() {
    _state.credentials = {};

    const setCredentials = (username, password, root = null) => {
      _state.credentials[username] = {
        password,
        root
      };
    };

    if (_args.credentials) {
      const credentialsFile = path.resolve(_args.credentials);
      const credentials = require(credentialsFile);

      for (const cred of credentials) {
        setCredentials(cred.username, cred.password, cred.root);
      }
    } else if (_args.username) {
      setCredentials(_args.username, _args.password);
    }
  }

  function setupCommandBlacklist() {
    if (_args.readOnly) {
      _state.blacklist = ['ALLO', 'APPE', 'DELE', 'MKD', 'RMD', 'RNRF', 'RNTO', 'STOR', 'STRU'];
    }
  }

  setupOptions();
  setupRoot();
  setupCredentials();
  setupCommandBlacklist();

  return _state;
}

function startFtpServer(_state) {
  // Remove null/undefined options so they get set to defaults, below
  for (const key in _state) {
    if (_state[key] === undefined) delete _state[key];
  }

  function checkLogin(data, resolve, reject) {
    const user = _state.credentials[data.username];
    if (_state.anonymous || user && user.password === data.password) {
      return resolve({root: user && user.root || _state.root});
    }

    return reject(new errors.GeneralError('Invalid username or password', 401));
  }

  const ftpServer = new FtpSrv({
    url: _state.url,
    pasv_url: _state.pasv_url,
    pasv_min: _state.pasv_min,
    pasv_max: _state.pasv_max,
    anonymous: _state.anonymous,
    blacklist: _state.blacklist
  });

  ftpServer.on('login', checkLogin);
  ftpServer.listen();
}
<commit_msg>fix: cli arg consistency<commit_after>#!/usr/bin/env node

const yargs = require('yargs');
const path = require('path');

const FtpSrv = require('../src');
const errors = require('../src/errors');

const args = setupYargs();
const state = setupState(args);
startFtpServer(state);

function setupYargs() {
  return yargs
    .option('credentials', {
      alias: 'c',
      describe: 'Load user & pass from json file',
      normalize: true
    })
    .option('username', {
      describe: 'Blank for anonymous',
      type: 'string',
      default: ''
    })
    .option('password', {
      describe: 'Password for given username',
      type: 'string'
    })
    .option('root', {
      alias: 'r',
      describe: 'Default root directory for users',
      type: 'string',
      normalize: true
    })
    .option('read-only', {
      describe: 'Disable write actions such as upload, delete, etc',
      boolean: true,
      default: false
    })
    .option('pasv-url', {
      describe: 'URL to provide for passive connections',
      type: 'string',
      alias: 'pasv_url'
    })
    .option('pasv-min', {
      describe: 'Starting point to use when creating passive connections',
      type: 'number',
      default: 1024,
      alias: 'pasv_min'
    })
    .option('pasv-max', {
      describe: 'Ending port to use when creating passive connections',
      type: 'number',
      default: 65535,
      alias: 'pasv_max'
    })
    .parse();
}

function setupState(_args) {
  const _state = {};

  function setupOptions() {
    if (_args._ && _args._.length > 0) {
      _state.url = _args._[0];
    }
    _state.pasv_url = _args.pasv_url;
    _state.pasv_min = _args.pasv_min;
    _state.pasv_max = _args.pasv_max;
    _state.anonymous = _args.username === '';
  }

  function setupRoot() {
    const dirPath = _args.root;
    if (dirPath) {
      _state.root = dirPath;
    } else {
      _state.root = process.cwd();
    }
  }

  function setupCredentials() {
    _state.credentials = {};

    const setCredentials = (username, password, root = null) => {
      _state.credentials[username] = {
        password,
        root
      };
    };

    if (_args.credentials) {
      const credentialsFile = path.resolve(_args.credentials);
      const credentials = require(credentialsFile);

      for (const cred of credentials) {
        setCredentials(cred.username, cred.password, cred.root);
      }
    } else if (_args.username) {
      setCredentials(_args.username, _args.password);
    }
  }

  function setupCommandBlacklist() {
    if (_args.readOnly) {
      _state.blacklist = ['ALLO', 'APPE', 'DELE', 'MKD', 'RMD', 'RNRF', 'RNTO', 'STOR', 'STRU'];
    }
  }

  setupOptions();
  setupRoot();
  setupCredentials();
  setupCommandBlacklist();

  return _state;
}

function startFtpServer(_state) {
  // Remove null/undefined options so they get set to defaults, below
  for (const key in _state) {
    if (_state[key] === undefined) delete _state[key];
  }

  function checkLogin(data, resolve, reject) {
    const user = _state.credentials[data.username];
    if (_state.anonymous || user && user.password === data.password) {
      return resolve({root: user && user.root || _state.root});
    }

    return reject(new errors.GeneralError('Invalid username or password', 401));
  }

  const ftpServer = new FtpSrv({
    url: _state.url,
    pasv_url: _state.pasv_url,
    pasv_min: _state.pasv_min,
    pasv_max: _state.pasv_max,
    anonymous: _state.anonymous,
    blacklist: _state.blacklist
  });

  ftpServer.on('login', checkLogin);
  ftpServer.listen();
}
<|endoftext|>