<commit_before>"use strict";

// External dependencies.
var $ = require("jquery"),
    Backbone = require("backbone"),
    _ = require("underscore"),
    Twister = require("../Twister"),
    app = require("../app"),
    twemoji = require('twemoji'),
    moment = require("moment");

Backbone.$ = $;

var TYPES = {
    RETWIST: 'retwist',
    REPLY: 'reply',
    POST: 'post',
    COMPOSE: 'compose',
    COMPOSE_REPLY: 'compose_reply',
};

// Defining the application router.
var PostModel = module.exports = Backbone.Model.extend({
    defaults: {
        twister_id: null,
        message: null,
        time: null,
        last_time: null,
        user: null,
        retwist: null,
        retwisters: [],
        replies: [],
        lovers: []
    },

    initialize: function () {
        this.set('retwisters', new Array());
        this.set('replies', new Array());
        this.set('lovers', new Array());
    },

    /**
     * data = Twister post data
     * users = user collection to retrieve users from
     */
    parse: function (data, users) {
        var item = data.userpost,
            user;

        if (!users.findWhere) {
            user = users;
        } else {
            user = users.findWhere({username: item.n});
        }

        // Maybe the user doens't excist yet when we are parsing a
        // parent post of a reply for example
        if (!user) {
            user = users.newUser({username: item.n, isFollowing: false});
        }

        if(item.rt) {
            var retwistUser = users.findWhere({username: item.rt.n});

            // Update the lowest_id and last_twister_id of the retwisting user,
            // since there is further no trace of this 'post' of the retwisting user
            user.processTwisterIdsOfPost(item.k, item.lastk);

            // If this is a retwist we might not know the user
            // in that case add it to the list of users
            if (!retwistUser) {
                retwistUser = users.newUser({username: item.rt.n, isFollowing: false});
            } else {
                // Check if post is already known
                var post = retwistUser.get('posts').findWhere({id: retwistUser.get('username') + '_' + item.rt.k});
                if (post) {
                    user.addRetwist(post);
                    post.setLastTime(item.time);
                    post.addRetwister(user);
                    return post;
                }
            }

            // Build the retwist post model
            var retwist = new PostModel({
                id: retwistUser.get('username') + '_' + item.rt.k,
                signature: item.sig_rt,
                height: item.rt.height,
                user: retwistUser,
                message: item.rt.msg,
                time: item.rt.time,
                last_time: item.time,
                last_rt_time: item.time,
                twister_id: item.rt.k,
                last_twister_id: item.rt.lastk,
                retwisters: [user]
            });

            // The the post as an post of the original poster
            retwistUser.addPost(retwist);

            user.addRetwist(retwist);

            // Return the retwist as if it is an original twist
            return retwist;
        }

        this.set({
            id: user.get('username') + '_' + item.k,
            signature: data.sig_userpost,
            height: item.height,
            user: user,
            message: item.msg,
            time: item.time,
            last_time: item.time,
            retwist: retwist,
            reply: item.reply ? {username: item.reply.n, twister_id: item.reply.k} : undefined,
            twister_id: item.k,
            last_twister_id: item.lastk
        });

        user.addPost(this);

        return this;
    },

    reply: function (user, msg, callback) {
        var self = this;
        Twister.reply(user.get('username'), msg, this.get('user').get('username'), this.get('twister_id'), function (err, data) {
            if (err) return callback (err);
            var reply = new PostModel().parse(data, user);
            var replies = self.get('replies');
            replies.push(reply);
            self.set('replies', replies);
            callback(null, reply);
        });
    },

    addRetwister: function (user) {
        var retwisters = this.get('retwisters');
        if (retwisters.indexOf(user) != -1) {
            return;
        }
        user.fetchAvatarFromDisk();
        retwisters.push(user);
        this.set('retwisters', retwisters);
    },

    setLastTime: function (time) {
        if (time > this.get('last_time')) {
            this.set('last_time', time);
        }
    },

    getMessageRegexed: function () {
        if (!this.get('message')) return "";
        // Urls
        var msg = this.get('message').replace( /(https?:\/\/[^\s]+)/g, function(url) { return ''+url+'' });
        // Hashtags
        msg = msg.replace( /(^|[^#\w])#(\w{1,30})\b/g, '$1#$2' );
        // Mentions
        msg = msg.replace( /(^|[^@\w])@(\w{1,30})\b/g, '$1$2' );
        // Emojis
        msg = twemoji.parse(msg, {
            base: '',
            folder: 'node_modules/twemoji/svg',
            ext: '.svg'
        });
        // Breaks / enters
        msg = msg.replace(/(?:\r\n|\r|\n)/g, '
');
        return msg;
    },

    getTimeAgo: function ()
    {
        return moment(this.get('time') * 1000).fromNow();
    },

    getDaysAgo: function ()
    {
        var now = moment(new Date());
        var date = moment(this.get('last_time') * 1000);
        console.log('days ago', now.diff(date, 'days'));
        return now.diff(date, 'days');
    },

    getAsUserpost: function ()
    {
        var data = {
            height: this.get('height'),
            k: this.get('twister_id'),
            lastk: this.get('last_twister_id'),
            msg: this.get('message'),
            n: this.get('user').get('username'),
            time: this.get('time')
        };
        if (this.get('reply')) {
            data.reply = {
                k: this.get('reply').twister_id,
                n: this.get('reply').username
            };
        }
        return data;
    },

    toRetwist: function ()
    {
        var sig_userpost = this.get('signature');
        var userpost = this.getAsUserpost();
        return {
            sig_userpost: sig_userpost,
            userpost: userpost
        }
    },

    getTopParent: function ()
    {
        var t = this;
        // This is the top parent
        if (!t.get('parent')) return t;
        // Treverse to top
        while(t.get('parent')) {
            t = t.get('parent');
        }
        return t;
    },

    getLastChild: function ()
    {
        var t = this;

        if (t.get('replies').length == 0) return t;

        while(t.get('replies').length > 0) {
            t = t.get('replies')[t.get('replies').length - 1];
        }
        return t;
    },

    getType: function ()
    {
        if (this.get('twister_id') == null && this.get('reply')) {
            return TYPES.COMPOSE_REPLY;
        } else if (this.get('twister_id') == null) {
            return TYPES.COMPOSE;
        } else if (this.get('last_time') != this.get('time')) {
            return TYPES.RETWIST;
        } else if (this.get('reply')) {
            return TYPES.REPLY;
        }
        return TYPES.POST;
    },

    /**
     * Returns the usernames of the users mentioned in this post
     * without the '@'
     */
    getMentionedUsernames: function ()
    {
        var text = this.get('message');
        var usernames = text.match( /(^|[^@\w])@(\w{1,30})\b/g);
        for (var i = 0; i < usernames.length; i++) {
            usernames[i] = usernames[i].trim().substr(1);
        }
        return usernames;
    }
});
<commit_msg>Make sure inline html gets converted to text<commit_after>"use strict";

// External dependencies.
var $ = require("jquery"),
    Backbone = require("backbone"),
    _ = require("underscore"),
    Twister = require("../Twister"),
    app = require("../app"),
    twemoji = require('twemoji'),
    moment = require("moment");

Backbone.$ = $;

var TYPES = {
    RETWIST: 'retwist',
    REPLY: 'reply',
    POST: 'post',
    COMPOSE: 'compose',
    COMPOSE_REPLY: 'compose_reply',
};

// Defining the application router.
var PostModel = module.exports = Backbone.Model.extend({
    defaults: {
        twister_id: null,
        message: null,
        time: null,
        last_time: null,
        user: null,
        retwist: null,
        retwisters: [],
        replies: [],
        lovers: []
    },

    initialize: function () {
        this.set('retwisters', new Array());
        this.set('replies', new Array());
        this.set('lovers', new Array());
    },

    /**
     * data = Twister post data
     * users = user collection to retrieve users from
     */
    parse: function (data, users) {
        var item = data.userpost,
            user;

        if (!users.findWhere) {
            user = users;
        } else {
            user = users.findWhere({username: item.n});
        }

        // Maybe the user doens't excist yet when we are parsing a
        // parent post of a reply for example
        if (!user) {
            user = users.newUser({username: item.n, isFollowing: false});
        }

        if(item.rt) {
            var retwistUser = users.findWhere({username: item.rt.n});

            // Update the lowest_id and last_twister_id of the retwisting user,
            // since there is further no trace of this 'post' of the retwisting user
            user.processTwisterIdsOfPost(item.k, item.lastk);

            // If this is a retwist we might not know the user
            // in that case add it to the list of users
            if (!retwistUser) {
                retwistUser = users.newUser({username: item.rt.n, isFollowing: false});
            } else {
                // Check if post is already known
                var post = retwistUser.get('posts').findWhere({id: retwistUser.get('username') + '_' + item.rt.k});
                if (post) {
                    user.addRetwist(post);
                    post.setLastTime(item.time);
                    post.addRetwister(user);
                    return post;
                }
            }

            // Build the retwist post model
            var retwist = new PostModel({
                id: retwistUser.get('username') + '_' + item.rt.k,
                signature: item.sig_rt,
                height: item.rt.height,
                user: retwistUser,
                message: item.rt.msg,
                time: item.rt.time,
                last_time: item.time,
                last_rt_time: item.time,
                twister_id: item.rt.k,
                last_twister_id: item.rt.lastk,
                retwisters: [user]
            });

            // The the post as an post of the original poster
            retwistUser.addPost(retwist);

            user.addRetwist(retwist);

            // Return the retwist as if it is an original twist
            return retwist;
        }

        this.set({
            id: user.get('username') + '_' + item.k,
            signature: data.sig_userpost,
            height: item.height,
            user: user,
            message: item.msg,
            time: item.time,
            last_time: item.time,
            retwist: retwist,
            reply: item.reply ? {username: item.reply.n, twister_id: item.reply.k} : undefined,
            twister_id: item.k,
            last_twister_id: item.lastk
        });

        user.addPost(this);

        return this;
    },

    reply: function (user, msg, callback) {
        var self = this;
        Twister.reply(user.get('username'), msg, this.get('user').get('username'), this.get('twister_id'), function (err, data) {
            if (err) return callback (err);
            var reply = new PostModel().parse(data, user);
            var replies = self.get('replies');
            replies.push(reply);
            self.set('replies', replies);
            callback(null, reply);
        });
    },

    addRetwister: function (user) {
        var retwisters = this.get('retwisters');
        if (retwisters.indexOf(user) != -1) {
            return;
        }
        user.fetchAvatarFromDisk();
        retwisters.push(user);
        this.set('retwisters', retwisters);
    },

    setLastTime: function (time) {
        if (time > this.get('last_time')) {
            this.set('last_time', time);
        }
    },

    getMessageRegexed: function () {
        if (!this.get('message')) return "";
        var msg = this.get('message');
        // Html
        msg = msg.replace(/</g, "<").replace(/>/g, ">");
        // Urls
        msg = msg.replace( /(https?:\/\/[^\s]+)/g, function(url) { return ''+url+'' });
        // Hashtags
        msg = msg.replace( /(^|[^#\w])#(\w{1,30})\b/g, '$1#$2' );
        // Mentions
        msg = msg.replace( /(^|[^@\w])@(\w{1,30})\b/g, '$1$2' );
        // Emojis
        msg = twemoji.parse(msg, {
            base: '',
            folder: 'node_modules/twemoji/svg',
            ext: '.svg'
        });
        // Breaks / enters
        msg = msg.replace(/(?:\r\n|\r|\n)/g, '
');
        return msg;
    },

    getTimeAgo: function ()
    {
        return moment(this.get('time') * 1000).fromNow();
    },

    getDaysAgo: function ()
    {
        var now = moment(new Date());
        var date = moment(this.get('last_time') * 1000);
        console.log('days ago', now.diff(date, 'days'));
        return now.diff(date, 'days');
    },

    getAsUserpost: function ()
    {
        var data = {
            height: this.get('height'),
            k: this.get('twister_id'),
            lastk: this.get('last_twister_id'),
            msg: this.get('message'),
            n: this.get('user').get('username'),
            time: this.get('time')
        };
        if (this.get('reply')) {
            data.reply = {
                k: this.get('reply').twister_id,
                n: this.get('reply').username
            };
        }
        return data;
    },

    toRetwist: function ()
    {
        var sig_userpost = this.get('signature');
        var userpost = this.getAsUserpost();
        return {
            sig_userpost: sig_userpost,
            userpost: userpost
        }
    },

    getTopParent: function ()
    {
        var t = this;
        // This is the top parent
        if (!t.get('parent')) return t;
        // Treverse to top
        while(t.get('parent')) {
            t = t.get('parent');
        }
        return t;
    },

    getLastChild: function ()
    {
        var t = this;

        if (t.get('replies').length == 0) return t;

        while(t.get('replies').length > 0) {
            t = t.get('replies')[t.get('replies').length - 1];
        }
        return t;
    },

    getType: function ()
    {
        if (this.get('twister_id') == null && this.get('reply')) {
            return TYPES.COMPOSE_REPLY;
        } else if (this.get('twister_id') == null) {
            return TYPES.COMPOSE;
        } else if (this.get('last_time') != this.get('time')) {
            return TYPES.RETWIST;
        } else if (this.get('reply')) {
            return TYPES.REPLY;
        }
        return TYPES.POST;
    },

    /**
     * Returns the usernames of the users mentioned in this post
     * without the '@'
     */
    getMentionedUsernames: function ()
    {
        var text = this.get('message');
        var usernames = text.match( /(^|[^@\w])@(\w{1,30})\b/g);
        for (var i = 0; i < usernames.length; i++) {
            usernames[i] = usernames[i].trim().substr(1);
        }
        return usernames;
    }
});
<|endoftext|>


<commit_before>import { randomNumber } from '../utils/random';

export function number(digits=10) {
  let num = '';
  if (digits > 1) {
    num = `${nonZeroDigit()}`;
    digits -= 1;
  }
  return parseInt(num + leadingZeroNumber(digits));
}

export function decimal(leftDigits=5, rightDigits=2) {
  return `${number(leftDigits)}.${decimalPart(rightDigits)}`;
}

export function normal(mean=1, standardDeviation=1) {
  let theta = 2 * Math.PI * Math.random();
  let rho = Math.sqrt(-2 * Math.log(1 - Math.random()));
  let scale = standardDeviation * rho;
  return mean + scale * Math.cos(theta);
}

export function hexadecimal(digits=6) {
  return [...Array(digits).keys()]
    .map(_ => randomNumber(0, 15).toString(16))
    .join('');
}

export function between(from=1.00, to=5000.00) {
  let min = Math.min(from, to);
  let max = Math.max(from, to);
  return randomNumber(min, max);
}

export function positive(from=1.00, to=5000.00) {
  let value = between(from, to);
  return value < 0 ? (value *= -1) : value;
}

export function negative(from=-1.00, to=-5000.00) {
  let value = between(from, to);
  return value < 0 ? value : (value *= -1);
}

export function digit() {
  return randomNumber(0, 9);
}

function nonZeroDigit() {
  return randomNumber(1, 9);
}

function decimalPart(digits) {
  let num = '';
  if (digits > 1) {
    num = `${nonZeroDigit()}`;
    digits -= 1;
  }
  return leadingZeroNumber(digits) + num;
}

function leadingZeroNumber(digits) {
  return [...Array(digits).keys()]
    .map(_ => digit())
    .join('');
}
<commit_msg>Checking if input is decimal or integer for between call.<commit_after>import { randomNumber, randomFloat } from '../utils/random';

function isDecimal(n) {
  return !!(''+n).match(/\./);
}

export function number(digits=10) {
  let num = '';
  if (digits > 1) {
    num = `${nonZeroDigit()}`;
    digits -= 1;
  }
  return parseInt(num + leadingZeroNumber(digits));
}

export function decimal(leftDigits=5, rightDigits=2) {
  return `${number(leftDigits)}.${decimalPart(rightDigits)}`;
}

export function normal(mean=1, standardDeviation=1) {
  let theta = 2 * Math.PI * Math.random();
  let rho = Math.sqrt(-2 * Math.log(1 - Math.random()));
  let scale = standardDeviation * rho;
  return mean + scale * Math.cos(theta);
}

export function hexadecimal(digits=6) {
  return [...Array(digits).keys()]
    .map(_ => randomNumber(0, 15).toString(16))
    .join('');
}

export function between(from=1.00, to=5000.00) {
  let min = Math.min(from, to);
  let max = Math.max(from, to);
  return isDecimal(min) || isDecimal(max)
    ? randomFloat(min, max)
    : randomNumber(min, max);
}

export function positive(from=1.00, to=5000.00) {
  let value = between(from, to);
  return value < 0 ? (value *= -1) : value;
}

export function negative(from=-1.00, to=-5000.00) {
  let value = between(from, to);
  return value < 0 ? value : (value *= -1);
}

export function digit() {
  return randomNumber(0, 9);
}

function nonZeroDigit() {
  return randomNumber(1, 9);
}

function decimalPart(digits) {
  let num = '';
  if (digits > 1) {
    num = `${nonZeroDigit()}`;
    digits -= 1;
  }
  return leadingZeroNumber(digits) + num;
}

function leadingZeroNumber(digits) {
  return [...Array(digits).keys()]
    .map(_ => digit())
    .join('');
}
<|endoftext|>


<commit_before>/* jshint ignore:start */
require(["neue/validation", "validation/auth", "validation/reportback"], function(Validation, auth, reportback) {
  module("Validation");

  test("Name", function() {
    Validation.Validations.name.fn("John", function(result) {
      ok(result.message == "Hey, John!", "should greet");
    });

    Validation.Validations.name.fn("", function(result) {
      ok(result.success == false, "should require name");
    });

  });

  test("Birthdays", function() {
    var now = new Date();
    var birthday_date = (now.getMonth() + 1) + "/" + now.getDate() + "/1990";
    var user_9_years_old = Math.min(now.getMonth() + 2, 12) + "/" + now.getDate() + "/" + (now.getFullYear() - 10);
    var user_19_years_old = Math.min(now.getMonth() + 2, 12) + "/" + now.getDate() + "/" + (now.getFullYear() - 20);

    Validation.Validations.birthday.fn(birthday_date, function(result) {
      ok(result.message == "Wow, happy birthday!", "should wish me a happy birthday");
    });

    Validation.Validations.birthday.fn(user_9_years_old, function(result) {
      ok(result.message == "Wow, you're 9!", "should tell young users their age");
    });

    Validation.Validations.birthday.fn(user_19_years_old, function(result) {
      ok(result.message == "Cool, 19!", "should tell me my age");
    });

    Validation.Validations.birthday.fn("yesterday", function(result) {
      ok(result.success == false, "should reject non-formatted dates");
    });

    Validation.Validations.birthday.fn("1/15/1960", function(result) {
      ok(result.message == "Got it!", "should be cordial to old people");
    });

    Validation.Validations.birthday.fn("1/15/1860", function(result) {
      ok(result.message == "That doesn't seem right.", "should reject users with birthdates too far in the past");
    });

    Validation.Validations.birthday.fn("1/15/2095", function(result) {
      ok(result.message == "Are you a time traveller?", "should reject users with future birthdates");
    });

    Validation.Validations.birthday.fn("61/12/1990", function(result) {
      ok(result.success == false, "should reject users with invalid month values");
    });

    Validation.Validations.birthday.fn("12/42/1990", function(result) {
      ok(result.success == false, "should reject users with day value greater than 31");
    });

    Validation.Validations.birthday.fn("10/25/90", function(result) {
      ok(result.success == false, "should reject dates with two-digit years");
    });

  });

  test("Emails", function() {
    Validation.Validations.email.fn("my.name@gmail.com", function(result) {
      ok(result.success == true, "should accept a valid email");
    });

    Validation.Validations.email.fn("my.name.com", function(result) {
      ok(result.success == false, "should reject an invalid email");
    });

    Validation.Validations.email.fn("myname@com", function(result) {
      ok(result.success == false, "should reject an invalid email");
    });

    Validation.Validations.email.fn("myname@gmail.123", function(result) {
      ok(result.success == false, "should reject an invalid email");
    });
  });

  test("Passwords", function() {
    Validation.Validations.password.fn("12345", function(result) {
      ok(result.success == false, "should reject if too short");
    });

    Validation.Validations.password.fn("super$ecure19", function(result) {
      ok(result.success == true, "should be totally chill with a good password");
    });
  });

  test("Match", function() {
    Validation.Validations.match.fn("dog", "cat", function(result) {
      ok(result.success == false, "should reject if different strings");
    });

    Validation.Validations.match.fn("dog", "Dog", function(result) {
      ok(result.success == false, "should reject if different capitalization");
    });

    Validation.Validations.match.fn("dog", "dog ", function(result) {
      ok(result.success == false, "should reject if different spacing");
    });

    Validation.Validations.match.fn("super$ecure19", "super$ecure19", function(result) {
      ok(result.success == true, "should accept if the same");
    });
  });

  test("Phone numbers", function() {
    Validation.Validations.phone.fn("123-456-7890", function(result) {
      ok(result.success == true, "should accept 10-digit number with dashes");
    });

    Validation.Validations.phone.fn("123.456 7890", function(result) {
      ok(result.success == true, "should accept 10-digit number with dot and space");
    });

    Validation.Validations.phone.fn("1 (123) 456-7890", function(result) {
      ok(result.success == true, "should accept 11-digit US number");
    });

    Validation.Validations.phone.fn("123-555-9942", function(result) {
      ok(result.success == false, "should reject number with repeating digits");
    });

    Validation.Validations.phone.fn("1 902 #@@ 1234", function(result) {
      ok(result.success == false, "should reject number with invalid symbols");
    });

    Validation.Validations.phone.fn("999 999 9999", function(result) {
      ok(result.success == false, "should reject number with all repeating digits");
    });
  });

  test("Reportback numbers", function() {
    Validation.Validations.positiveInteger.fn("19", function(result) {
      ok(result.success == true, "should accept a valid integer");
    });

    Validation.Validations.positiveInteger.fn(" 5", function(result) {
      ok(result.success == true, "should accept a number with space in front");
    });

    Validation.Validations.positiveInteger.fn("5 ", function(result) {
      ok(result.success == true, "should accept a number with space at the end");
    });

    Validation.Validations.positiveInteger.fn("two", function(result) {
      ok(result.success == false, "should reject a number spelled out as a string");
    });

    Validation.Validations.positiveInteger.fn("4.5", function(result) {
      ok(result.success == false, "should reject a decimal number");
    });

    Validation.Validations.positiveInteger.fn("0", function(result) {
      ok(result.success == false, "should reject zero");
    });
  });

});
<commit_msg>Updates unit test for #2999.<commit_after>/* jshint ignore:start */
require(["neue/validation", "validation/auth", "validation/reportback"], function(Validation, auth, reportback) {
  module("Validation");

  test("Name", function() {
    Validation.Validations.name.fn("John", function(result) {
      ok(result.message == "Hey, John!", "should greet");
    });

    Validation.Validations.name.fn("", function(result) {
      ok(result.success == false, "should require name");
    });

  });

  test("Birthdays", function() {
    var now = new Date();
    var birthday_date = (now.getMonth() + 1) + "/" + now.getDate() + "/1990";
    var user_9_years_old = Math.min(now.getMonth() + 2, 12) + "/" + now.getDate() + "/" + (now.getFullYear() - 10);
    var user_19_years_old = Math.min(now.getMonth() + 2, 12) + "/" + now.getDate() + "/" + (now.getFullYear() - 20);

    Validation.Validations.birthday.fn(birthday_date, function(result) {
      ok(result.message == "Wow, happy birthday!", "should wish me a happy birthday");
    });

    Validation.Validations.birthday.fn(user_9_years_old, function(result) {
      ok(result.message == "Wow, you're 9!", "should tell young users their age");
    });

    Validation.Validations.birthday.fn(user_19_years_old, function(result) {
      ok(result.message == "Cool, 19!", "should tell me my age");
    });

    Validation.Validations.birthday.fn("yesterday", function(result) {
      ok(result.success == false, "should reject non-formatted dates");
    });

    Validation.Validations.birthday.fn("1/15/1960", function(result) {
      ok(result.message == "Got it!", "should be cordial to old people");
    });

    Validation.Validations.birthday.fn("1/15/1860", function(result) {
      ok(result.message == "That doesn't seem right.", "should reject users with birthdates too far in the past");
    });

    Validation.Validations.birthday.fn("1/15/2095", function(result) {
      ok(result.message == "Are you a time traveller?", "should reject users with future birthdates");
    });

    Validation.Validations.birthday.fn("61/12/1990", function(result) {
      ok(result.success == false, "should reject users with invalid month values");
    });

    Validation.Validations.birthday.fn("12/42/1990", function(result) {
      ok(result.success == false, "should reject users with day value greater than 31");
    });

    Validation.Validations.birthday.fn("10/25/90", function(result) {
      ok(result.success == false, "should reject dates with two-digit years");
    });

  });

  test("Emails", function() {
    Validation.Validations.email.fn("my.name@gmail.com", function(result) {
      ok(result.success == true, "should accept a valid email");
    });

    Validation.Validations.email.fn("my.name.com", function(result) {
      ok(result.success == false, "should reject an invalid email");
    });

    Validation.Validations.email.fn("myname@com", function(result) {
      ok(result.success == false, "should reject an invalid email");
    });

    Validation.Validations.email.fn("myname@gmail.123", function(result) {
      ok(result.success == false, "should reject an invalid email");
    });
  });

  test("Passwords", function() {
    Validation.Validations.password.fn("12345", function(result) {
      ok(result.success == false, "should reject if too short");
    });

    Validation.Validations.password.fn("super$ecure19", function(result) {
      ok(result.success == true, "should be totally chill with a good password");
    });
  });

  test("Match", function() {
    Validation.Validations.match.fn("dog", "cat", function(result) {
      ok(result.success == false, "should reject if different strings");
    });

    Validation.Validations.match.fn("dog", "Dog", function(result) {
      ok(result.success == false, "should reject if different capitalization");
    });

    Validation.Validations.match.fn("dog", "dog ", function(result) {
      ok(result.success == false, "should reject if different spacing");
    });

    Validation.Validations.match.fn("super$ecure19", "super$ecure19", function(result) {
      ok(result.success == true, "should accept if the same");
    });
  });

  test("Phone numbers", function() {
    Validation.Validations.phone.fn("123-456-7890", function(result) {
      ok(result.success == true, "should accept 10-digit number with dashes");
    });

    Validation.Validations.phone.fn("123.456 7890", function(result) {
      ok(result.success == true, "should accept 10-digit number with dot and space");
    });

    Validation.Validations.phone.fn("1 (123) 456-7890", function(result) {
      ok(result.success == true, "should accept 11-digit US number");
    });

    Validation.Validations.phone.fn("123-555-9942", function(result) {
      ok(result.success == true, "should accept number with some repeating digits");
    });

    Validation.Validations.phone.fn("1 902 #@@ 1234", function(result) {
      ok(result.success == false, "should reject number with invalid symbols");
    });

    Validation.Validations.phone.fn("999 999 9999", function(result) {
      ok(result.success == false, "should reject number with all repeating digits");
    });
  });

  test("Reportback numbers", function() {
    Validation.Validations.positiveInteger.fn("19", function(result) {
      ok(result.success == true, "should accept a valid integer");
    });

    Validation.Validations.positiveInteger.fn(" 5", function(result) {
      ok(result.success == true, "should accept a number with space in front");
    });

    Validation.Validations.positiveInteger.fn("5 ", function(result) {
      ok(result.success == true, "should accept a number with space at the end");
    });

    Validation.Validations.positiveInteger.fn("two", function(result) {
      ok(result.success == false, "should reject a number spelled out as a string");
    });

    Validation.Validations.positiveInteger.fn("4.5", function(result) {
      ok(result.success == false, "should reject a decimal number");
    });

    Validation.Validations.positiveInteger.fn("0", function(result) {
      ok(result.success == false, "should reject zero");
    });
  });

});
<|endoftext|>


<commit_before>var fw = require('knockout/build/output/knockout-latest');
var _ = require('footwork-lodash');

var util = require('../../misc/util');
var hasPathStart = util.hasPathStart;
var hasHashStart = util.hasHashStart;
var resultBound  = util.resultBound;
var startingHashRegex = util.startingHashRegex;
var removeClass = util.removeClass;
var addClass = util.addClass;
var hasClass = util.hasClass;
var privateDataSymbol = util.getSymbol('footwork');

var routerTools = require('./router-tools');
var nearestParentRouter = routerTools.nearestParentRouter;
var isNullRouter = routerTools.isNullRouter;

function findParentNode (element, selector) {
  if (selector === true) {
    return element.parentNode;
  }

  if (element.parentNode && _.isFunction(element.parentNode.querySelectorAll)) {
    var parentNode = element.parentNode;
    var matches = parentNode.querySelectorAll(selector);
    if (matches.length && _.includes(matches, element)) {
      return element;
    }
    return findParentNode(parentNode, selector);
  }

  return undefined;
}

var isFullURLRegex = /(^[a-z]+:\/\/|^\/\/)/i;
var isFullURL = fw.utils.isFullURL = function (thing) {
  return _.isString(thing) && isFullURLRegex.test(thing);
};

fw.bindingHandlers.$route = {
  init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
    var router = nearestParentRouter(bindingContext);
    var routeParams = valueAccessor();
    var elementIsSetup = false;
    var stateTracker = null;
    var hashOnly = null;

    var routeHandlerDescription = {
      on: 'click',
      url: function defaultURLForRoute () { return element.getAttribute('href'); },
      activeClass: fw.router.activeClass,
      history: 'push',
      handler: function defaultHandlerForRouteBinding (event, url) {
        /* istanbul ignore else */
        if (!hashOnly && !isFullURL(url) && event.which !== 2) {
          event.preventDefault();
          return true;
        } else {
          return false;
        }
      }
    };

    if (_.isFunction(routeParams) || _.isString(routeParams)) {
      routeHandlerDescription.url = routeParams;
    } else if (_.isObject(routeParams)) {
      _.extend(routeHandlerDescription, routeParams);
    }

    var routeHandlerDescriptionURL = routeHandlerDescription.url;
    if (!_.isFunction(routeHandlerDescriptionURL)) {
      routeHandlerDescription.url = function () { return routeHandlerDescriptionURL; };
    }

    function getRouteURL () {
      var routeURL = routeHandlerDescription.url();

      if (!isFullURL(routeURL) && hasHashStart(routeURL)) {
        var currentRoute = router[privateDataSymbol].currentRoute();
        if (currentRoute) {
          routeURL = currentRoute.segment + routeURL;
        }
      }

      return routeURL;
    };

    function checkForMatchingSegment (mySegment, newRoute) {
      if (_.isString(mySegment)) {
        var currentRoute = router[privateDataSymbol].currentRoute();
        var activeRouteClassName = resultBound(routeHandlerDescription, 'activeClass', router);

        if (_.isObject(currentRoute)) {
          if (_.isString(activeRouteClassName) && activeRouteClassName.length) {
            if (mySegment === '/') {
              mySegment = '';
            }

            if (!_.isNull(newRoute) && newRoute.segment === mySegment) {
              // newRoute.segment is the same as this routers segment...add the activeRouteClassName to the element to indicate it is active
              addClass(element, activeRouteClassName);
            } else if (hasClass(element, activeRouteClassName)) {
              removeClass(element, activeRouteClassName);
            }
          }
        }
      }

      if (_.isNull(newRoute)) {
        // No route currently selected, remove the activeRouteClassName from the element
        removeClass(element, activeRouteClassName);
      }
    };

    function setUpElement () {
      if (!isNullRouter(router)) {
        var myCurrentSegment = getRouteURL();
        var configParams = router[privateDataSymbol].configParams;
        if (element.tagName.toLowerCase() === 'a') {
          element.href = configParams.baseRoute + getRouteURL();
        }

        if (_.isObject(stateTracker) && _.isFunction(stateTracker.dispose)) {
          stateTracker.dispose();
        }
        stateTracker = router[privateDataSymbol].currentRoute.subscribe(_.partial(checkForMatchingSegment, myCurrentSegment));

        if (elementIsSetup === false) {
          elementIsSetup = true;
          checkForMatchingSegment(myCurrentSegment, router[privateDataSymbol].currentRoute());

          fw.utils.registerEventHandler(element, resultBound(routeHandlerDescription, 'on', router), function (event) {
            var currentRouteURL = getRouteURL();
            var handlerResult = routeHandlerDescription.handler.call(viewModel, event, currentRouteURL);
            if (handlerResult) {
              if (_.isString(handlerResult)) {
                currentRouteURL = handlerResult;
              }
              if (_.isString(currentRouteURL) && !isFullURL(currentRouteURL)) {
                router[resultBound(routeHandlerDescription, 'history', router) + 'State'](currentRouteURL);
              }
            }
            return true;
          });
        }
      }
    }

    if (fw.isObservable(routeHandlerDescription.url)) {
      router.disposeWithInstance(routeHandlerDescription.url.subscribe(setUpElement));
    }
    setUpElement();

    /* istanbul ignore next */
    fw.utils.domNodeDisposal.addDisposeCallback(element, function () {
      if (_.isObject(stateTracker)) {
        stateTracker.dispose();
      }
    });
  }
};
<commit_msg>removed dead code<commit_after>var fw = require('knockout/build/output/knockout-latest');
var _ = require('footwork-lodash');

var util = require('../../misc/util');
var hasPathStart = util.hasPathStart;
var hasHashStart = util.hasHashStart;
var resultBound  = util.resultBound;
var startingHashRegex = util.startingHashRegex;
var removeClass = util.removeClass;
var addClass = util.addClass;
var hasClass = util.hasClass;
var privateDataSymbol = util.getSymbol('footwork');

var routerTools = require('./router-tools');
var nearestParentRouter = routerTools.nearestParentRouter;
var isNullRouter = routerTools.isNullRouter;

var isFullURLRegex = /(^[a-z]+:\/\/|^\/\/)/i;
var isFullURL = fw.utils.isFullURL = function (thing) {
  return _.isString(thing) && isFullURLRegex.test(thing);
};

fw.bindingHandlers.$route = {
  init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
    var router = nearestParentRouter(bindingContext);
    var routeParams = valueAccessor();
    var elementIsSetup = false;
    var stateTracker = null;
    var hashOnly = null;

    var routeHandlerDescription = {
      on: 'click',
      url: function defaultURLForRoute () { return element.getAttribute('href'); },
      activeClass: fw.router.activeClass,
      history: 'push',
      handler: function defaultHandlerForRouteBinding (event, url) {
        /* istanbul ignore else */
        if (!hashOnly && !isFullURL(url) && event.which !== 2) {
          event.preventDefault();
          return true;
        } else {
          return false;
        }
      }
    };

    if (_.isFunction(routeParams) || _.isString(routeParams)) {
      routeHandlerDescription.url = routeParams;
    } else if (_.isObject(routeParams)) {
      _.extend(routeHandlerDescription, routeParams);
    }

    var routeHandlerDescriptionURL = routeHandlerDescription.url;
    if (!_.isFunction(routeHandlerDescriptionURL)) {
      routeHandlerDescription.url = function () { return routeHandlerDescriptionURL; };
    }

    function getRouteURL () {
      var routeURL = routeHandlerDescription.url();

      if (!isFullURL(routeURL) && hasHashStart(routeURL)) {
        var currentRoute = router[privateDataSymbol].currentRoute();
        if (currentRoute) {
          routeURL = currentRoute.segment + routeURL;
        }
      }

      return routeURL;
    };

    function checkForMatchingSegment (mySegment, newRoute) {
      if (_.isString(mySegment)) {
        var currentRoute = router[privateDataSymbol].currentRoute();
        var activeRouteClassName = resultBound(routeHandlerDescription, 'activeClass', router);

        if (_.isObject(currentRoute)) {
          if (_.isString(activeRouteClassName) && activeRouteClassName.length) {
            if (mySegment === '/') {
              mySegment = '';
            }

            if (!_.isNull(newRoute) && newRoute.segment === mySegment) {
              // newRoute.segment is the same as this routers segment...add the activeRouteClassName to the element to indicate it is active
              addClass(element, activeRouteClassName);
            } else if (hasClass(element, activeRouteClassName)) {
              removeClass(element, activeRouteClassName);
            }
          }
        }
      }

      if (_.isNull(newRoute)) {
        // No route currently selected, remove the activeRouteClassName from the element
        removeClass(element, activeRouteClassName);
      }
    };

    function setUpElement () {
      if (!isNullRouter(router)) {
        var myCurrentSegment = getRouteURL();
        var configParams = router[privateDataSymbol].configParams;
        if (element.tagName.toLowerCase() === 'a') {
          element.href = configParams.baseRoute + getRouteURL();
        }

        if (_.isObject(stateTracker) && _.isFunction(stateTracker.dispose)) {
          stateTracker.dispose();
        }
        stateTracker = router[privateDataSymbol].currentRoute.subscribe(_.partial(checkForMatchingSegment, myCurrentSegment));

        if (elementIsSetup === false) {
          elementIsSetup = true;
          checkForMatchingSegment(myCurrentSegment, router[privateDataSymbol].currentRoute());

          fw.utils.registerEventHandler(element, resultBound(routeHandlerDescription, 'on', router), function (event) {
            var currentRouteURL = getRouteURL();
            var handlerResult = routeHandlerDescription.handler.call(viewModel, event, currentRouteURL);
            if (handlerResult) {
              if (_.isString(handlerResult)) {
                currentRouteURL = handlerResult;
              }
              if (_.isString(currentRouteURL) && !isFullURL(currentRouteURL)) {
                router[resultBound(routeHandlerDescription, 'history', router) + 'State'](currentRouteURL);
              }
            }
            return true;
          });
        }
      }
    }

    if (fw.isObservable(routeHandlerDescription.url)) {
      router.disposeWithInstance(routeHandlerDescription.url.subscribe(setUpElement));
    }
    setUpElement();

    /* istanbul ignore next */
    fw.utils.domNodeDisposal.addDisposeCallback(element, function () {
      if (_.isObject(stateTracker)) {
        stateTracker.dispose();
      }
    });
  }
};
<|endoftext|>


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

'use strict';

var fs             = require('fs'),
    program        = require('commander'),
    chalk          = require('chalk'),
    logSymbols     = require('log-symbols'),
    inquirer       = require('inquirer'),
    filesystem     = require('../lib/util/filesystem');

var projectVersion = require('../package.json').version,
    defaultDir     = process.env.HOME + '/.knick-knack';

program
  .version(projectVersion)
  .option('-d, --directory [directory]', 'Specify the directory where knick-knack should look for templates [' + defaultDir + ']', defaultDir);

program.on('--help', function () {
  console.log('  ' + chalk.cyan.underline('Commands:'));
  console.log();
  console.log('    $ knick-knack [list]             List all available knick-knack templates');
  console.log('    $ knick-knack [template-name]    Generate a new project based on a template');
  console.log('    $ knick-knack add general-readme Add a readme partial to the project in the current directory');
  console.log('    $ knick-knack init               Initialize a knick-knack templates directory');
  console.log();
});

program.parse(process.argv);

var additionalArgs = program.args,
    directory      = program.directory;

var list     = require('../lib/list'),
    init     = require('../lib/init'),
    generate = require('../lib/generate');

function folderInvalid(name) {
  if (! filesystem.folderExists(name) && name !== defaultDir && additionalArgs[0] !== 'init') {
    //the user passed in an invalid folder with -d but did not want to create one with "init"
    return true;
  }
  return false;
}

if (folderInvalid(directory)) {
  console.error(chalk.yellow('"' + directory + '" is not a valid directory.'));
  return;
}

switch (additionalArgs[0]) {
  case 'init':
    init.createTemplateFolder(directory);
    break;

  case undefined:
    if (! filesystem.folderExists(directory)) {
      console.log('This seems to be the first time you\'re using knick-knack.\n');

      var continueQuestion = {
        name: 'continue',
        type: 'confirm',
        message: 'May I suggest that you start the setup assistant for you?',
        default: true
      };
      inquirer.prompt(continueQuestion, function(answer) {
        if (answer.continue) {
          init.createTemplateFolder(directory);
        }
      });
      return;
    }

    var templates = list.listTemplates(directory);

    if (templates.length > 0) {
      console.log(chalk.cyan.underline('\nAvailable templates:'));
      console.log(templates.join('\n') + '\n');
      console.log('You can generate a new project with ' + chalk.blue.bold('knick-knack TEMPLATE') + '\n');
      console.log('For more information see https://github.com/haimich/knick-knack\n');
    } else {
      console.log(logSymbols.warning + chalk.magenta(' No templates found in "' + directory + '".'));
      console.log();
    }

    break;

  case 'check':
    console.log('check');
    break;
  case 'add':
    console.log('add ' + additionalArgs[1]);
    break;
  case 'create':
    console.log('create ' + additionalArgs[1]);
    break;

  default: // not a command, maybe a template name?
    generate.createProject(additionalArgs[0]);
}
<commit_msg>renamed filesystem variable<commit_after>#!/usr/bin/env node

'use strict';

var fs             = require('fs'),
    program        = require('commander'),
    chalk          = require('chalk'),
    logSymbols     = require('log-symbols'),
    inquirer       = require('inquirer'),
    fsutil         = require('../lib/util/filesystem');

var projectVersion = require('../package.json').version,
    defaultDir     = process.env.HOME + '/.knick-knack';

program
  .version(projectVersion)
  .option('-d, --directory [directory]', 'Specify the directory where knick-knack should look for templates [' + defaultDir + ']', defaultDir);

program.on('--help', function () {
  console.log('  ' + chalk.cyan.underline('Commands:'));
  console.log();
  console.log('    $ knick-knack [list]             List all available knick-knack templates');
  console.log('    $ knick-knack [template-name]    Generate a new project based on a template');
  console.log('    $ knick-knack add general-readme Add a readme partial to the project in the current directory');
  console.log('    $ knick-knack init               Initialize a knick-knack templates directory');
  console.log();
});

program.parse(process.argv);

var additionalArgs = program.args,
    directory      = program.directory;

var list     = require('../lib/list'),
    init     = require('../lib/init'),
    generate = require('../lib/generate');

function folderInvalid(name) {
  if (! fsutil.folderExists(name) && name !== defaultDir && additionalArgs[0] !== 'init') {
    //the user passed in an invalid folder with -d but did not want to create one with "init"
    return true;
  }
  return false;
}

if (folderInvalid(directory)) {
  console.error(chalk.yellow('"' + directory + '" is not a valid directory.'));
  return;
}

switch (additionalArgs[0]) {
  case 'init':
    init.createTemplateFolder(directory);
    break;

  case undefined:
    if (! fsutil.folderExists(directory)) {
      console.log('This seems to be the first time you\'re using knick-knack.\n');

      var continueQuestion = {
        name: 'continue',
        type: 'confirm',
        message: 'May I suggest that you start the setup assistant for you?',
        default: true
      };
      inquirer.prompt(continueQuestion, function(answer) {
        if (answer.continue) {
          init.createTemplateFolder(directory);
        }
      });
      return;
    }

    var templates = list.listTemplates(directory);

    if (templates.length > 0) {
      console.log(chalk.cyan.underline('\nAvailable templates:'));
      console.log(templates.join('\n') + '\n');
      console.log('You can generate a new project with ' + chalk.blue.bold('knick-knack TEMPLATE') + '\n');
      console.log('For more information see https://github.com/haimich/knick-knack\n');
    } else {
      console.log(logSymbols.warning + chalk.magenta(' No templates found in "' + directory + '".'));
      console.log();
    }

    break;

  case 'check':
    console.log('check');
    break;
  case 'add':
    console.log('add ' + additionalArgs[1]);
    break;
  case 'create':
    console.log('create ' + additionalArgs[1]);
    break;

  default: // not a command, maybe a template name?
    generate.createProject(additionalArgs[0]);
}
<|endoftext|>


<commit_before>/**
 * Produce a form for making NVCL Analytical jobs
 */
Ext.define('NVCLAnalyticsTsgForm', {
    extend : 'Ext.window.Window',

    statics: {
        NVCL_ANALYTIC_SERVICE : 'http://localhost:8080/NVCLAnalyticalServices',
        NON_STANDARD_ALGORITHM_ID : -9999
    },

    layer : null,
    map : null,
    bboxButton : null,
    serviceUrl : null,

    constructor : function(cfg) {
        this.layer=cfg.layer;
        this.map=cfg.map;

        var fieldWidth = 335;
        var defaults = {
            labelWidth: 150,
            padding: 0
        };

        var tsgAlgNameStore = Ext.create('Ext.data.Store', {
            fields: [{name: 'tsgAlgName', type: 'string'}],
            data : [
                    {tsgAlgName: 'Hematite-goethite_distr'},
                    {tsgAlgName: 'Kaolinite Crystallinity'},
                    {tsgAlgName: 'None Template Algorithm'}
                ],
            autoLoad: true,
            sorters: ["tsgAlgName"],
            listeners: {
                load: function(algorithmOutputStore, records, success) {
                }
            }
        });

        var operatorStore = Ext.create('Ext.data.Store', {
            fields: ['name', 'value'],
            data: [{name: '<', value: 'lt'},{name: '>', value: 'gt'}, {name: '=', value: 'eq'}]
        });

        var uomStore = Ext.create('Ext.data.Store', {
            fields: ['name', 'value'],
            data: [{name: 'count', value: 'count'},{name: '%', value: 'pct'}]
        });

        Ext.apply(cfg, {
            title: 'National Virtual Core Library Analytics',
            height: 750,
            width: 700,
            layout: 'fit',
            padding: '10',
            border: false,
            modal: true,
            items: [{
                xtype: 'form',
                border: false,
                autoScroll: true,
                items: [{
                    xtype: 'container',
                    html: '
National Virtual Core Library analytics are run remotely and may take some time to complete. By entering an email and a job name you can come back to this form later to collect your results.
'
                },{
                    xtype: 'textfield',
                    name: 'email',
                    itemId: 'email',
                    fieldLabel: 'Email',
                    allowBlank: false,
                    value: this._recoverUserEmail(),
                    anchor: '100%'
                },{
                    xtype: 'textfield',
                    name: 'jobname',
                    fieldLabel: 'Job Name',
                    allowBlank: false,
                    anchor: '100%'
                },{
                    xtype: 'container',
                    html: '
Please select a classification algorithm to filter boreholes against.
'
                },{
                    xtype: 'fieldset',
                    title: 'TSG Algorithm',
                    defaults: defaults,
                    items: [{
                        xtype: 'fieldset',
                        layout: 'vbox',
                        border: false,
                        defaults: defaults,
                        items: [{
                            xtype: 'combo',
                            name: 'tsgalgname',
                            itemId: 'tsgalgname',
                            fieldLabel: 'Name',
                            store: tsgAlgNameStore,
                            displayField: 'tsgAlgName',
                            valueField: 'tsgAlgName',
                            forceSelection: true,
                            queryMode: 'local',
                            typeAhead: true,
                            allowBlank: false,
                            width: fieldWidth,
                            listeners: {
                                select: Ext.bind(this._onAlgorithmSelect, this)
                            }
                        },{
                            xtype: 'combo',
                            name: 'tsgwvrange',
                            itemId: 'tsgwvrange',
                            fieldLabel: 'Wavelength',
                            store:['Thermal','VisSWIR'],
                            displayField: 'tsgWvRange',
                            valueField: 'tsgWvRange',
                            forceSelection: true,
                            queryMode: 'local',
                            typeAhead: true,
                            allowBlank: false,
                            width: fieldWidth,

                        },{
                            xtype     : 'textareafield',
                            itemId    : 'tsgscript',
                            grow      : true,
                            width     : 700,
                            height    : 300,
                            name      : 'tsgscript',
                            fieldLabel: 'Algorithm',
                            anchor    : '100%'
                        }]
                    }]
                },{
                    xtype: 'container',
                    html: '
Please select a borehole depth range and value (compared against the above algorithm) to filter NVCL boreholes.
'
                },{
                    xtype: 'fieldset',
                    title: 'Filter Parameters',
                    defaults: defaults,
                    items: [{
                        xtype: 'fieldset',
                        layout: 'hbox',
                        border: false,
                        defaults: defaults,
                        items: [{
                            xtype: 'numberfield',
                            name: 'startdepth',
                            fieldLabel: 'Region of interest',
                            decimalPrecision: 0,
                            allowBlank: false,
                            value: 0,
                            width: fieldWidth
                        },{
                            xtype: 'label',
                            text: ' metres to ',
                            margin: '3 5 0 5'
                        },{
                            xtype: 'numberfield',
                            name: 'enddepth',
                            decimalPrecision: 0,
                            allowBlank: false,
                            value: 9999
                        },{
                            xtype: 'label',
                            text: ' metres',
                            margin: '3 0 0 5'
                        }]
                    },{
                        xtype: 'combo',
                        name: 'logicalop',
                        fieldLabel: 'Operator',
                        store: operatorStore,
                        displayField: 'name',
                        valueField: 'value',
                        forceSelection: true,
                        allowBlank: false,
                        queryMode: 'local',
                        width: fieldWidth
                    },{
                        xtype: 'fieldset',
                        layout: 'hbox',
                        border: false,
                        defaults: defaults,
                        items: [{
                            xtype: 'numberfield',
                            name: 'value',
                            fieldLabel: 'Value',
                            allowBlank: false,
                            decimalPrecision: 5,
                            width: fieldWidth
                        },{
                            xtype: 'label',
                            text: ' ',
                            margin: '3 5 0 5'
                        },{
                            xtype: 'combo',
                            name: 'units',
                            store: uomStore,
                            displayField: 'name',
                            valueField: 'value',
                            forceSelection: true,
                            queryMode: 'local',
                            allowBlank: false,
                            value: 'count'
                        }]
                    },{
                        xtype: 'fieldset',
                        layout: 'hbox',
                        border: false,
                        defaults: defaults,
                        items: [{
                            xtype: 'numberfield',
                            name: 'span',
                            fieldLabel: 'Evaluated over a span of',
                            decimalPrecision: 0,
                            allowBlank: false,
                            value: 1,
                            width: fieldWidth
                        },{
                            xtype: 'label',
                            text: 'metres',
                            margin: '3 5 0 5'
                        }]
                    }]
                }]
            }],
            dockedItems: [{
                xtype: 'toolbar',
                dock: 'bottom',
                items: [{
                    xtype: 'tbfill'
                },{
                    xtype: 'button',
                    text: 'Check Status',
                    iconCls : 'info',
                    handler: Ext.bind(this._onStatus, this, [null, null], false)
                },{
                    xtype: 'button',
                    text: 'Begin Processing',
                    iconCls : 'download',
                    handler: Ext.bind(this._onSubmit, this)
                }]
            }]
        });

        this.callParent(arguments);
    },

    _onAlgorithmSelect: function(combo, record) {
        var tsgAlgName = combo.getValue();
        Ext.Ajax.request({
            url: 'http://localhost:8080/NVCLAnalyticalServices/getTsgAlgorithms.do',
            params: {tsgAlgName: tsgAlgName},
            scope: this,
            success: function(response) {
                console.log(response.responseText);
                this.down('#tsgscript').setValue(response.responseText);
             },
             failure : function(fp,action){
                 Ext.Msg.alert('Status', 'Unable to get Algorithm.');
             }
        });
    },

    _saveUserEmail: function(email) {
        if (window.localStorage) {
            localStorage.setItem('auscope-nvcl-analytics-email', email);
        }
    },

    _recoverUserEmail: function() {
        if (window.localStorage) {
            return localStorage.getItem('auscope-nvcl-analytics-email');
        } else {
            return '';
        }
    },

    /**
     * Shows the status popup for the given user email (ignores any entered email).
     *
     * If jobId is set, that particular jobID will be highlighted in the status popup.
     */
    showStatusPopup: function(jobEmail, jobId) {
        this._onStatus(jobEmail, jobId);
    },

    _onStatus: function(jobEmail, jobId) {
        var params = {};
        if (Ext.isEmpty(jobEmail)) {
            var formPanel = this.down('form');
            var emailField = formPanel.down('#email');

            if (!emailField.isValid()) {
                return;
            }

            var email = emailField.getValue();
            this._saveUserEmail(email);
            params.email = email;
        } else {
            params.email = jobEmail;
        }

        var mask = new Ext.LoadMask({
            msg: 'Checking status...',
            target: this
        });
        mask.show();
        portal.util.Ajax.request({
            url: 'checkNVCLProcessingJob.do',
            params: params,
            scope: this,
            callback: function(success, data, message) {
                mask.hide();

                if (!success) {
                    Ext.Msg.alert('Error', 'Unable to check your processing jobs at this time. Please try again later.');
                    return;
                }

                if (Ext.isEmpty(data)) {
                    Ext.Msg.alert('No Jobs', 'There are currently no jobs submitted for ' + email);
                    return;
                }

                var popup = Ext.create('Ext.window.Window', {
                    modal: true,
                    layout: 'fit',
                    title: 'Previously submitted jobs',
                    width: 500,
                    height: 200,
                    items: [{
                        xtype: 'analyticaljobstatuspanel',
                        statuses: data,
                        listeners: {
                            statusselect: Ext.bind(function(panel, rec) {
                                this._loadFilterForJob(rec.get('jobId'), rec.get('jobDescription'));
                                popup.close();
                                this.close();
                            }, this),

                            statusdownload: Ext.bind(function(panel, rec) {
                                this._downloadJobResults(rec.get('jobId'));
                            }, this),

                            afterrender: function(panel) {
                                if (jobId) {
                                    var recIdx = panel.getStore().find('jobId', jobId);
                                    if (recIdx >= 0) {
                                        var record = panel.getStore().getAt(recIdx);
                                        panel.getSelectionModel().select(record);
                                    }
                                }
                            }
                        }
                    }]
                });
                popup.show();
            }
        });
    },

    _downloadJobResults: function(jobId) {
        portal.util.FileDownloader.downloadFile('downloadNVCLProcessingResults.do', {
            jobId: jobId
        });
    },

    _loadFilterForJob: function(jobId, jobName) {
        this.layer.get('filterer').setParameters({
            analyticsJobId: jobId,
            nvclJobName: jobName
        }, false);
        this.layer.get('filterForm').readFromFilterer(this.layer.get('filterer'));
        portal.map.openlayers.ActiveLayerManager.addLayer(this.layer);
    },

    _onSubmit: function() {
        var formPanel = this.down('form');
        if (!formPanel.isValid()) {
            return;
        }

        //Build up our parameters for job submission
        var params = {};
        if (this.layer) {
            params = this.layer.get('filterer').getParameters();

            var wfsUrls = [];
            if (Ext.isEmpty(params.serviceFilter)) {
                var wfsResources = portal.csw.OnlineResource.getFilteredFromArray(this.layer.getAllOnlineResources(), portal.csw.OnlineResource.WFS);
                wfsUrls = wfsResources.map(function(or) {
                    return or.get('url');
                });
            } else {
                wfsUrls = [params.serviceFilter];
            }

            params.wfsUrl = wfsUrls;
        }
        Ext.apply(params, formPanel.getValues());

        this._saveUserEmail(params.email);

        //Submit the job
        var mask = new Ext.LoadMask({
            msg: 'Submitting job...',
            target: this
        });
        mask.show();
        Ext.Ajax.request({
            url: 'submitNVCLTSGModJob.do?serviceurls=http://geology.data.nt.gov.au/geoserver/wfs&filter =<ogc:Filter><PropertyIsEqualTo><PropertyName>gsmlp:nvclCollection</PropertyName><Literal>true</Literal></PropertyIsEqualTo></ogc:Filter>',
            params: params,
            timeout: 60000,
            method: 'GET',
            scope: this,
            callback: function(success) {
                mask.hide();
                if (!success) {
                    Ext.Msg.alert('Error', 'Unable to submit your processing job at this time. Please try again later.');
                    return;
                }

                Ext.Msg.alert('Success', 'Your job has successfully submitted. You can check the status with the "Check Status" button below');
            }
        });
    }
});<commit_msg>*Fixed Access-Control-Allow-Origin JavaScript issue.<commit_after>/**
 * Produce a form for making NVCL Analytical jobs
 */
Ext.define('NVCLAnalyticsTsgForm', {
    extend : 'Ext.window.Window',

    statics: {
        NVCL_ANALYTIC_SERVICE : 'http://localhost:8080/NVCLAnalyticalServices',
        NON_STANDARD_ALGORITHM_ID : -9999
    },

    layer : null,
    map : null,
    bboxButton : null,
    serviceUrl : null,

    constructor : function(cfg) {
        this.layer=cfg.layer;
        this.map=cfg.map;

        var fieldWidth = 335;
        var defaults = {
            labelWidth: 150,
            padding: 0
        };

        var tsgAlgNameStore = Ext.create('Ext.data.Store', {
            fields: [{name: 'tsgAlgName', type: 'string'}],
            data : [
                    {tsgAlgName: 'Hematite-goethite_distr'},
                    {tsgAlgName: 'Kaolinite Crystallinity'},
                    {tsgAlgName: 'None Template Algorithm'}
                ],
            autoLoad: true,
            sorters: ["tsgAlgName"],
            listeners: {
                load: function(algorithmOutputStore, records, success) {
                }
            }
        });

        var operatorStore = Ext.create('Ext.data.Store', {
            fields: ['name', 'value'],
            data: [{name: '<', value: 'lt'},{name: '>', value: 'gt'}, {name: '=', value: 'eq'}]
        });

        var uomStore = Ext.create('Ext.data.Store', {
            fields: ['name', 'value'],
            data: [{name: 'count', value: 'count'},{name: '%', value: 'pct'}]
        });

        Ext.apply(cfg, {
            title: 'National Virtual Core Library Analytics',
            height: 750,
            width: 700,
            layout: 'fit',
            padding: '10',
            border: false,
            modal: true,
            items: [{
                xtype: 'form',
                border: false,
                autoScroll: true,
                items: [{
                    xtype: 'container',
                    html: '
National Virtual Core Library analytics are run remotely and may take some time to complete. By entering an email and a job name you can come back to this form later to collect your results.
'
                },{
                    xtype: 'textfield',
                    name: 'email',
                    itemId: 'email',
                    fieldLabel: 'Email',
                    allowBlank: false,
                    value: this._recoverUserEmail(),
                    anchor: '100%'
                },{
                    xtype: 'textfield',
                    name: 'jobname',
                    fieldLabel: 'Job Name',
                    allowBlank: false,
                    anchor: '100%'
                },{
                    xtype: 'container',
                    html: '
Please select a classification algorithm to filter boreholes against.
'
                },{
                    xtype: 'fieldset',
                    title: 'TSG Algorithm',
                    defaults: defaults,
                    items: [{
                        xtype: 'fieldset',
                        layout: 'vbox',
                        border: false,
                        defaults: defaults,
                        items: [{
                            xtype: 'combo',
                            name: 'tsgalgname',
                            itemId: 'tsgalgname',
                            fieldLabel: 'Name',
                            store: tsgAlgNameStore,
                            displayField: 'tsgAlgName',
                            valueField: 'tsgAlgName',
                            forceSelection: true,
                            queryMode: 'local',
                            typeAhead: true,
                            allowBlank: false,
                            width: fieldWidth,
                            listeners: {
                                select: Ext.bind(this._onAlgorithmSelect, this)
                            }
                        },{
                            xtype: 'combo',
                            name: 'tsgwvrange',
                            itemId: 'tsgwvrange',
                            fieldLabel: 'Wavelength',
                            store:['Thermal','VisSWIR'],
                            displayField: 'tsgWvRange',
                            valueField: 'tsgWvRange',
                            forceSelection: true,
                            queryMode: 'local',
                            typeAhead: true,
                            allowBlank: false,
                            width: fieldWidth,

                        },{
                            xtype     : 'textareafield',
                            itemId    : 'tsgscript',
                            grow      : true,
                            width     : 700,
                            height    : 300,
                            name      : 'tsgscript',
                            fieldLabel: 'Algorithm',
                            anchor    : '100%'
                        }]
                    }]
                },{
                    xtype: 'container',
                    html: '
Please select a borehole depth range and value (compared against the above algorithm) to filter NVCL boreholes.
'
                },{
                    xtype: 'fieldset',
                    title: 'Filter Parameters',
                    defaults: defaults,
                    items: [{
                        xtype: 'fieldset',
                        layout: 'hbox',
                        border: false,
                        defaults: defaults,
                        items: [{
                            xtype: 'numberfield',
                            name: 'startdepth',
                            fieldLabel: 'Region of interest',
                            decimalPrecision: 0,
                            allowBlank: false,
                            value: 0,
                            width: fieldWidth
                        },{
                            xtype: 'label',
                            text: ' metres to ',
                            margin: '3 5 0 5'
                        },{
                            xtype: 'numberfield',
                            name: 'enddepth',
                            decimalPrecision: 0,
                            allowBlank: false,
                            value: 9999
                        },{
                            xtype: 'label',
                            text: ' metres',
                            margin: '3 0 0 5'
                        }]
                    },{
                        xtype: 'combo',
                        name: 'logicalop',
                        fieldLabel: 'Operator',
                        store: operatorStore,
                        displayField: 'name',
                        valueField: 'value',
                        forceSelection: true,
                        allowBlank: false,
                        queryMode: 'local',
                        width: fieldWidth
                    },{
                        xtype: 'fieldset',
                        layout: 'hbox',
                        border: false,
                        defaults: defaults,
                        items: [{
                            xtype: 'numberfield',
                            name: 'value',
                            fieldLabel: 'Value',
                            allowBlank: false,
                            decimalPrecision: 5,
                            width: fieldWidth
                        },{
                            xtype: 'label',
                            text: ' ',
                            margin: '3 5 0 5'
                        },{
                            xtype: 'combo',
                            name: 'units',
                            store: uomStore,
                            displayField: 'name',
                            valueField: 'value',
                            forceSelection: true,
                            queryMode: 'local',
                            allowBlank: false,
                            value: 'count'
                        }]
                    },{
                        xtype: 'fieldset',
                        layout: 'hbox',
                        border: false,
                        defaults: defaults,
                        items: [{
                            xtype: 'numberfield',
                            name: 'span',
                            fieldLabel: 'Evaluated over a span of',
                            decimalPrecision: 0,
                            allowBlank: false,
                            value: 1,
                            width: fieldWidth
                        },{
                            xtype: 'label',
                            text: 'metres',
                            margin: '3 5 0 5'
                        }]
                    }]
                }]
            }],
            dockedItems: [{
                xtype: 'toolbar',
                dock: 'bottom',
                items: [{
                    xtype: 'tbfill'
                },{
                    xtype: 'button',
                    text: 'Check Status',
                    iconCls : 'info',
                    handler: Ext.bind(this._onStatus, this, [null, null], false)
                },{
                    xtype: 'button',
                    text: 'Begin Processing',
                    iconCls : 'download',
                    handler: Ext.bind(this._onSubmit, this)
                }]
            }]
        });

        this.callParent(arguments);
    },

    _onAlgorithmSelect: function(combo, record) {
        var tsgAlgName = combo.getValue();
        Ext.Ajax.request({
            url: 'getTsgAlgorithms.do',
            params: {tsgAlgName: tsgAlgName},
            scope: this,
            success: function(response) {
                console.log(response.responseText);
                this.down('#tsgscript').setValue(response.responseText);
             },
             failure : function(fp,action){
                 Ext.Msg.alert('Status', 'Unable to get Algorithm.');
             }
        });
    },

    _saveUserEmail: function(email) {
        if (window.localStorage) {
            localStorage.setItem('auscope-nvcl-analytics-email', email);
        }
    },

    _recoverUserEmail: function() {
        if (window.localStorage) {
            return localStorage.getItem('auscope-nvcl-analytics-email');
        } else {
            return '';
        }
    },

    /**
     * Shows the status popup for the given user email (ignores any entered email).
     *
     * If jobId is set, that particular jobID will be highlighted in the status popup.
     */
    showStatusPopup: function(jobEmail, jobId) {
        this._onStatus(jobEmail, jobId);
    },

    _onStatus: function(jobEmail, jobId) {
        var params = {};
        if (Ext.isEmpty(jobEmail)) {
            var formPanel = this.down('form');
            var emailField = formPanel.down('#email');

            if (!emailField.isValid()) {
                return;
            }

            var email = emailField.getValue();
            this._saveUserEmail(email);
            params.email = email;
        } else {
            params.email = jobEmail;
        }

        var mask = new Ext.LoadMask({
            msg: 'Checking status...',
            target: this
        });
        mask.show();
        portal.util.Ajax.request({
            url: 'checkNVCLProcessingJob.do',
            params: params,
            scope: this,
            callback: function(success, data, message) {
                mask.hide();

                if (!success) {
                    Ext.Msg.alert('Error', 'Unable to check your processing jobs at this time. Please try again later.');
                    return;
                }

                if (Ext.isEmpty(data)) {
                    Ext.Msg.alert('No Jobs', 'There are currently no jobs submitted for ' + email);
                    return;
                }

                var popup = Ext.create('Ext.window.Window', {
                    modal: true,
                    layout: 'fit',
                    title: 'Previously submitted jobs',
                    width: 500,
                    height: 200,
                    items: [{
                        xtype: 'analyticaljobstatuspanel',
                        statuses: data,
                        listeners: {
                            statusselect: Ext.bind(function(panel, rec) {
                                this._loadFilterForJob(rec.get('jobId'), rec.get('jobDescription'));
                                popup.close();
                                this.close();
                            }, this),

                            statusdownload: Ext.bind(function(panel, rec) {
                                this._downloadJobResults(rec.get('jobId'));
                            }, this),

                            afterrender: function(panel) {
                                if (jobId) {
                                    var recIdx = panel.getStore().find('jobId', jobId);
                                    if (recIdx >= 0) {
                                        var record = panel.getStore().getAt(recIdx);
                                        panel.getSelectionModel().select(record);
                                    }
                                }
                            }
                        }
                    }]
                });
                popup.show();
            }
        });
    },

    _downloadJobResults: function(jobId) {
        portal.util.FileDownloader.downloadFile('downloadNVCLProcessingResults.do', {
            jobId: jobId
        });
    },

    _loadFilterForJob: function(jobId, jobName) {
        this.layer.get('filterer').setParameters({
            analyticsJobId: jobId,
            nvclJobName: jobName
        }, false);
        this.layer.get('filterForm').readFromFilterer(this.layer.get('filterer'));
        portal.map.openlayers.ActiveLayerManager.addLayer(this.layer);
    },

    _onSubmit: function() {
        var formPanel = this.down('form');
        if (!formPanel.isValid()) {
            return;
        }

        //Build up our parameters for job submission
        var params = {};
        if (this.layer) {
            params = this.layer.get('filterer').getParameters();

            var wfsUrls = [];
            if (Ext.isEmpty(params.serviceFilter)) {
                var wfsResources = portal.csw.OnlineResource.getFilteredFromArray(this.layer.getAllOnlineResources(), portal.csw.OnlineResource.WFS);
                wfsUrls = wfsResources.map(function(or) {
                    return or.get('url');
                });
            } else {
                wfsUrls = [params.serviceFilter];
            }

            params.wfsUrl = wfsUrls;
        }
        Ext.apply(params, formPanel.getValues());

        this._saveUserEmail(params.email);

        //Submit the job
        var mask = new Ext.LoadMask({
            msg: 'Submitting job...',
            target: this
        });
        mask.show();
        Ext.Ajax.request({
            url: 'submitNVCLTSGModJob.do?serviceurls=http://geology.data.nt.gov.au/geoserver/wfs&filter =<ogc:Filter><PropertyIsEqualTo><PropertyName>gsmlp:nvclCollection</PropertyName><Literal>true</Literal></PropertyIsEqualTo></ogc:Filter>',
            params: params,
            timeout: 60000,
            method: 'GET',
            scope: this,
            callback: function(success) {
                mask.hide();
                if (!success) {
                    Ext.Msg.alert('Error', 'Unable to submit your processing job at this time. Please try again later.');
                    return;
                }

                Ext.Msg.alert('Success', 'Your job has successfully submitted. You can check the status with the "Check Status" button below');
            }
        });
    }
});<|endoftext|>


<commit_before>// @flow

import { type ThreadInfo, threadInfoPropType } from 'lib/types/thread-types';
import type { AppState } from '../../redux/redux-setup';
import type { DispatchActionPromise } from 'lib/utils/action-utils';
import type {
  SubscriptionUpdateRequest,
  SubscriptionUpdateResult,
} from 'lib/types/subscription-types';

import * as React from 'react';
import { Text, View, Switch } from 'react-native';
import PropTypes from 'prop-types';

import { connect } from 'lib/utils/redux-utils';
import {
  updateSubscriptionActionTypes,
  updateSubscription,
} from 'lib/actions/user-actions';

import { styleSelector } from '../../themes/colors';

type Props = {|
  threadInfo: ThreadInfo,
  // Redux state
  styles: typeof styles,
  // Redux dispatch functions
  dispatchActionPromise: DispatchActionPromise,
  // async functions that hit server APIs
  updateSubscription: (
    subscriptionUpdate: SubscriptionUpdateRequest,
  ) => Promise<SubscriptionUpdateResult>,
|};
type State = {|
  currentValue: boolean,
|};
class ThreadSettingsHomeNotifs extends React.PureComponent<Props, State> {
  static propTypes = {
    threadInfo: threadInfoPropType.isRequired,
    styles: PropTypes.objectOf(PropTypes.object).isRequired,
    dispatchActionPromise: PropTypes.func.isRequired,
    updateSubscription: PropTypes.func.isRequired,
  };

  constructor(props: Props) {
    super(props);
    this.state = {
      currentValue: !props.threadInfo.currentUser.subscription.home,
    };
  }

  render() {
    return (
      <View style={this.props.styles.row}>
        <Text style={this.props.styles.label}>Background</Text>
        <View style={this.props.styles.currentValue}>
          <Switch
            value={this.state.currentValue}
            onValueChange={this.onValueChange}
          />
        </View>
      </View>
    );
  }

  onValueChange = (value: boolean) => {
    this.setState({ currentValue: value });
    this.props.dispatchActionPromise(
      updateSubscriptionActionTypes,
      this.props.updateSubscription({
        threadID: this.props.threadInfo.id,
        updatedFields: {
          home: !value,
        },
      }),
    );
  };
}

const styles = {
  currentValue: {
    alignItems: 'flex-end',
    flex: 1,
    margin: 0,
    paddingLeft: 4,
    paddingRight: 0,
    paddingVertical: 0,
  },
  label: {
    color: 'panelForegroundTertiaryLabel',
    fontSize: 16,
    width: 96,
  },
  row: {
    alignItems: 'center',
    backgroundColor: 'panelForeground',
    flexDirection: 'row',
    paddingHorizontal: 24,
    paddingVertical: 3,
  },
};
const stylesSelector = styleSelector(styles);

export default connect(
  (state: AppState) => ({
    styles: stylesSelector(state),
  }),
  { updateSubscription },
)(ThreadSettingsHomeNotifs);
<commit_msg>[native] Use hooks for data-binding in ThreadSettingsHomeNotifs<commit_after>// @flow

import { type ThreadInfo, threadInfoPropType } from 'lib/types/thread-types';
import type { DispatchActionPromise } from 'lib/utils/action-utils';
import type {
  SubscriptionUpdateRequest,
  SubscriptionUpdateResult,
} from 'lib/types/subscription-types';

import * as React from 'react';
import { Text, View, Switch } from 'react-native';
import PropTypes from 'prop-types';

import {
  updateSubscriptionActionTypes,
  updateSubscription,
} from 'lib/actions/user-actions';
import {
  useServerCall,
  useDispatchActionPromise,
} from 'lib/utils/action-utils';

import { useStyles } from '../../themes/colors';

type BaseProps = {|
  +threadInfo: ThreadInfo,
|};
type Props = {|
  ...BaseProps,
  // Redux state
  +styles: typeof unboundStyles,
  // Redux dispatch functions
  +dispatchActionPromise: DispatchActionPromise,
  // async functions that hit server APIs
  +updateSubscription: (
    subscriptionUpdate: SubscriptionUpdateRequest,
  ) => Promise<SubscriptionUpdateResult>,
|};
type State = {|
  +currentValue: boolean,
|};
class ThreadSettingsHomeNotifs extends React.PureComponent<Props, State> {
  static propTypes = {
    threadInfo: threadInfoPropType.isRequired,
    styles: PropTypes.objectOf(PropTypes.object).isRequired,
    dispatchActionPromise: PropTypes.func.isRequired,
    updateSubscription: PropTypes.func.isRequired,
  };

  constructor(props: Props) {
    super(props);
    this.state = {
      currentValue: !props.threadInfo.currentUser.subscription.home,
    };
  }

  render() {
    return (
      <View style={this.props.styles.row}>
        <Text style={this.props.styles.label}>Background</Text>
        <View style={this.props.styles.currentValue}>
          <Switch
            value={this.state.currentValue}
            onValueChange={this.onValueChange}
          />
        </View>
      </View>
    );
  }

  onValueChange = (value: boolean) => {
    this.setState({ currentValue: value });
    this.props.dispatchActionPromise(
      updateSubscriptionActionTypes,
      this.props.updateSubscription({
        threadID: this.props.threadInfo.id,
        updatedFields: {
          home: !value,
        },
      }),
    );
  };
}

const unboundStyles = {
  currentValue: {
    alignItems: 'flex-end',
    flex: 1,
    margin: 0,
    paddingLeft: 4,
    paddingRight: 0,
    paddingVertical: 0,
  },
  label: {
    color: 'panelForegroundTertiaryLabel',
    fontSize: 16,
    width: 96,
  },
  row: {
    alignItems: 'center',
    backgroundColor: 'panelForeground',
    flexDirection: 'row',
    paddingHorizontal: 24,
    paddingVertical: 3,
  },
};

export default React.memo<BaseProps>(function ConnectedThreadSettingsHomeNotifs(
  props: BaseProps,
) {
  const styles = useStyles(unboundStyles);
  const dispatchActionPromise = useDispatchActionPromise();
  const callUpdateSubscription = useServerCall(updateSubscription);
  return (
    <ThreadSettingsHomeNotifs
      {...props}
      styles={styles}
      dispatchActionPromise={dispatchActionPromise}
      updateSubscription={callUpdateSubscription}
    />
  );
});
<|endoftext|>


<commit_before>// Don't let the remote end spew us with unrecognized commands
// Defaults to 10 max unrecognized commands

exports.hook_connect = function (next, connection) {
    const plugin = this;
    connection.results.add(plugin, {
        max: plugin.config.get('max_unrecognized_commands') || 10,
        count: 0,
    });
    return next();
}

exports.hook_unrecognized_command = function (next, connection, params) {
    const plugin = this;

    connection.results.add(plugin, {fail: `Unrecognized command: ${params}`, emit: true});
    connection.results.incr(plugin, {count: 1});

    const uc = connection.results.get('max_unrecognized_commands');
    if (uc.count >= uc.max) {
        connection.loginfo(plugin, "Closing connection. Too many bad commands.");
        return next(DENYDISCONNECT, "Too many bad commands");
    }
    return next();
}
<commit_msg>deprecate plugins/max_unrecognized_commands in favor of limit (#2402)<commit_after>
exports.register = function () {
    this.lognotice("the plugin max_unrecognized_commands has been replaced by 'limit'. Please update config/plugins");
}
<|endoftext|>


<commit_before>var directionsDisplay;
var directionsService = new google.maps.DirectionsService();
var map;

/**
 * Called when the page is loaded and performs all needed initialization.
 */
initialize = function() {
  directionsDisplay = new google.maps.DirectionsRenderer();
  var mapOptions = {
    center: new google.maps.LatLng(40.006756,-105.263618),
    zoom: 13
  };
  var map = new google.maps.Map(document.getElementById("map-canvas"),
      mapOptions);
  directionsDisplay.setMap(map);
}

calcRoute = function() {
  var start = document.getElementById('startaddr').value;
  var end = document.getElementById('destaddr').value;
  var request = {
      origin:start,
      destination:end,
      travelMode: google.maps.TravelMode.DRIVING
  };
  directionsService.route(request, function(response, status) {
    if (status == google.maps.DirectionsStatus.OK) {
      directionsDisplay.setDirections(response);
    }
  });
}
<commit_msg>Example with DistanceMatrixService, computing the NxN matrix of time between all waypoints<commit_after>var directionsDisplay;
var directionsService = new google.maps.DirectionsService();
var distanceMatrixService = new google.maps.DistanceMatrixService();
var map;

/**
 * Called when the page is loaded and performs all needed initialization.
 */
initialize = function() {
  directionsDisplay = new google.maps.DirectionsRenderer();
  var mapOptions = {
    center: new google.maps.LatLng(40.006756,-105.263618),
    zoom: 13
  };
  var map = new google.maps.Map(document.getElementById("map-canvas"),
      mapOptions);
  directionsDisplay.setMap(map);
}

calcRoute = function() {
  var start = document.getElementById('startaddr').value;
  var waypoints = document.getElementById('destaddr').value.split('\n');
  // Strip off leading and trailing whitespace.
  waypoints = waypoints.map(function(value) {
    return value.replace(/^\s+/, '').replace(/\s+$/, '');
  });
  var addresses = [start].concat(waypoints);
  // Remove empty addresses.
  waypoints = waypoints.filter(function(value) { return value; });
  var dmRequest = {
    origins: addresses,
    destinations: addresses,
    travelMode: google.maps.TravelMode.DRIVING
  };

  distanceMatrixService.getDistanceMatrix(dmRequest,
      function(dmResponse, dmStatus) {
        console.log(dmResponse);
        console.log(dmStatus);
      });
  /*
  var request = {
    origin:start,
    destination:end,
    travelMode: google.maps.TravelMode.DRIVING
  };
  directionsService.route(request, function(response, status) {
    if (status == google.maps.DirectionsStatus.OK) {
      directionsDisplay.setDirections(response);
    }
  });
  */
}
<|endoftext|>