<commit_before>import Checkbox from './Checkbox'
import render from './render'
import { isString, warn } from '../../helpers/util'

export default {
  name: 'VkTable',
  render,
  props: {
    fields: {
      type: Array,
      required: true
    },
    rows: {
      type: Array,
      required: true
    },
    rowsClass: {
      type: String,
      default: ''
    },
    trackBy: {
      type: String,
      default: 'id'
    },
    selectable: {
      type: Boolean,
      default: false
    },
    condensed: {
      type: Boolean,
      default: false
    },
    striped: {
      type: Boolean,
      default: false
    },
    hover: {
      type: Boolean,
      default: false
    },
    sortOrder: {
      type: Object,
      default: () => ({}) // field: asc|desc
    }
  },
  data: () => ({
    selectedRows: []
  }),
  created () {
    // check for rows id if selectable enabled
    if (warn && this.selectable) {
      this.rows.forEach(row => {
        if (row[this.trackBy] === undefined) {
          warn(`Some of the Table rows have no 'id' set.`)
        }
      })
    }
    // watch and trigger un/selectAll event
    this.$watch('selectedRows', rows => {
      if (this.allSelected) {
        this.$emit('selectAll')
      } else if (this.selectedRows.length === 0) {
        this.$emit('unselectAll')
      }
    })
  },
  computed: {
    allSelected () {
      return this.rows.every(row =>
        this.selectedRows.find(id => id === this.getRowId(row))
      )
    },
    fieldsDef () {
      const fields = processFields(this.fields)
      // add selectable field if
      // required and no provided
      if (this.selectable) {
        fields.unshift(selectFieldDef)
      }
      return fields
    }
  },
  methods: {
    isSelected (row) {
      return this.selectedRows.find(id => id === this.getRowId(row))
    },
    getRowId (row) {
      return `row_${row[this.trackBy]}`
    },
    toggleSelection (row) {
      const rowId = this.getRowId(row)
      if (this.isSelected(row)) {
        const index = this.selectedRows.indexOf(rowId)
        this.selectedRows.splice(index, 1) // remove
        this.$emit('unselect', row)
      } else {
        this.selectedRows.push(rowId)
        this.$emit('select', row)
      }
    },
    emitSort (field) {
      const sortBy = field.sortBy === true
        ? field.name
        : field.sortBy
      const sortOrder = {}
      // prepare the final order object state
      if (this.sortOrder[sortBy]) {
        sortOrder[sortBy] = this.sortOrder[sortBy] === 'asc'
          ? 'desc'
          : 'asc'
      } else {
        sortOrder[sortBy] = 'asc'
      }
      this.$emit('sort', sortOrder)
    }
  }
}

const processFields = fields => fields.map(f => {
  let field = {
    name: '',
    header: '',
    headerClass: '',
    cellClass: '',
    sortBy: ''
  }
  // set field data
  if (isString(f)) {
    field.name = f
  } else {
    // merge both
    field = {...field, ...f}
  }
  // set default Header
  if (field.header === '') {
    field.header = titleCase(field.name)
  }
  return field
})

const selectFieldDef = {
  headerClass: 'vk-table-width-minimum',
  cellClass: 'vk-table-width-minimum',
  cell (h, { parent, props }) {
    const { row } = props
    return h(Checkbox, {
      props: {
        checked: parent.isSelected(row),
        onClick: e => {
          parent.toggleSelection(row)
        }
      }
    })
  },
  header (h, { parent, props }) {
    return h(Checkbox, {
      props: {
        checked: parent.allSelected,
        onClick: e => {
          if (parent.allSelected) {
            parent.selectedRows = []
          } else {
            parent.selectedRows = parent.rows.map(row => parent.getRowId(row))
          }
        }
      }
    })
  }
}

function titleCase (str) {
  return str.replace(/\w+/g, txt =>
    txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase()
  )
}
<commit_msg>minor Table updates<commit_after>import Checkbox from './Checkbox'
import render from './render'
import { isString, warn } from '../../helpers/util'

export default {
  name: 'VkTable',
  render,
  props: {
    fields: {
      type: Array,
      required: true
    },
    rows: {
      type: Array,
      required: true
    },
    rowsClass: {
      type: String,
      default: ''
    },
    trackBy: {
      type: String,
      default: 'id'
    },
    selectable: {
      type: Boolean,
      default: false
    },
    condensed: {
      type: Boolean,
      default: false
    },
    striped: {
      type: Boolean,
      default: false
    },
    hover: {
      type: Boolean,
      default: false
    },
    sortOrder: {
      type: Object,
      default: () => ({}) // field: asc|desc
    }
  },
  data: () => ({
    selected: []
  }),
  created () {
    // check for rows id if selectable enabled
    if (warn && this.selectable) {
      this.rows.forEach(row => {
        if (row[this.trackBy] === undefined) {
          warn(`Some of the Table rows have no 'id' set.`)
        }
      })
    }
    // watch and trigger un/selectAll event
    this.$watch('selected', rows => {
      if (this.isAllSelected) {
        this.$emit('selectAll')
      } else if (this.selected.length === 0) {
        this.$emit('unselectAll')
      }
    })
  },
  computed: {
    isAllSelected () {
      return this.rows.every(row =>
        this.selected.find(id => id === this.getRowId(row))
      )
    },
    selectedRows () {
      return this.selected.map(rowId =>
        this.rows.find(row => this.getRowId(row) === rowId)
      )
    },
    fieldsDef () {
      const fields = processFields(this.fields)
      // add selectable field if
      // required and no provided
      if (this.selectable) {
        fields.unshift(selectFieldDef)
      }
      return fields
    }
  },
  methods: {
    isSelected (row) {
      return this.selected.find(id => id === this.getRowId(row))
    },
    getRowId (row) {
      return `row_${row[this.trackBy]}`
    },
    toggleSelection (row) {
      const rowId = this.getRowId(row)
      if (this.isSelected(row)) {
        const index = this.selected.indexOf(rowId)
        this.selected.splice(index, 1) // remove
        this.$emit('unselect', row)
      } else {
        this.selected.push(rowId)
        this.$emit('select', row)
      }
    },
    emitSort (field) {
      const sortBy = field.sortBy === true
        ? field.name
        : field.sortBy
      const sortOrder = {}
      // prepare the final order object state
      if (this.sortOrder[sortBy]) {
        sortOrder[sortBy] = this.sortOrder[sortBy] === 'asc'
          ? 'desc'
          : 'asc'
      } else {
        sortOrder[sortBy] = 'asc'
      }
      this.$emit('sort', sortOrder)
    }
  }
}

const processFields = fields => fields.map(f => {
  let field = {
    name: '',
    header: '',
    headerClass: '',
    cellClass: '',
    sortBy: ''
  }
  // set field data
  if (isString(f)) {
    field.name = f
  } else {
    // merge both
    field = {...field, ...f}
  }
  // set default Header
  if (field.header === '') {
    field.header = titleCase(field.name)
  }
  return field
})

const selectFieldDef = {
  headerClass: 'vk-table-width-minimum',
  cellClass: 'vk-table-width-minimum',
  cell (h, { parent, props }) {
    const { row } = props
    return h(Checkbox, {
      props: {
        checked: parent.isSelected(row),
        onClick: e => {
          parent.toggleSelection(row)
        }
      }
    })
  },
  header (h, { parent, props }) {
    return h(Checkbox, {
      props: {
        checked: parent.isAllSelected,
        onClick: e => {
          if (parent.isAllSelected) {
            parent.selected = []
          } else {
            parent.selected = parent.rows.map(row => parent.getRowId(row))
          }
        }
      }
    })
  }
}

function titleCase (str) {
  return str.replace(/\w+/g, txt =>
    txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase()
  )
}
<|endoftext|>


<commit_before>// utility methods

(function (__,window,jQuery){

	// intentionally global
	var $fn = {

		// return if an object is an object but not an array
		isObject	: 	function ($$,strict){
							if(strict){
								return ( (typeof $$ === 'object') && ($$ !== null));
							}
							return (typeof $$ === 'object') && ($$ !== null) && !($$ instanceof Array);
						},

		isArray	:	function ($$){
							return ( (typeof $$ === 'object') && ($$ instanceof Array) && $$.length >= 0 );
						},

		//  [undefined, null, false, 'false', 0, '0', '', empty string]
		isFalsey	:	function ($$){

							var case_ = 'case_'+$$,
								cases = {
									case_false		: function() { return true; },
									case_0 			: function() { return true; },
									case_null		: function() { return true; },
									case_undefined 	: function() { return true; },
									case_			: function() { return true; }
								};
							case_ = case_.trim();
							return cases[case_] ? cases[case_]() : false;

						},

		// checks undefined using strict equality (===)
		// [undefined]
		isUndefined	:	function ($$){
									return ( typeof $$ === 'undefined');
							},
		// checks null using strict equality (===)
		// [null]
		isNull		:	function ($$){
								return ($$ === null);
							},
		// checks for a sting with no value
		// [undefined, null, '', empty string]
		isBlank	:		function ($$){

							var case_ = 'case_'+$$,
								cases = {
									case_undefined 	: function(){ return true; },
									case_null		: function(){ return true; },
									case_			: function(){ return true; }
								};
							case_ = case_.trim();
							return cases[case_] ? cases[case_]() : false;
						},

		is$		:		function ($$){
								return ($$ instanceof jQuery);
							},

		// create events
		createEvent	:	function  (type) {

                                var event;
                                try {
                                    event = new Event(type);
                                }catch(e){
                                    event = document.createEvent('event');
                                    event.initEvent(type,true,false);
                                }
                                return event;
							},

		// create custom events
		customEvent : 	function (type,params) {

								var event;
								if (window.CustomEvent) {

                                    try{
                                        params = params || { bubbles: false, cancelable: false, detail: {} };
                                        event = new CustomEvent(type, params);
                                    }catch (e){
                                        event = document.createEvent('CustomEvent');
								  	     event.initCustomEvent(type, params.bubbles || false, params.cancelable || false, params.detail || {});
                                    }

								} else {
									event = document.createEvent('CustomEvent');
								  	event.initCustomEvent(type, params.bubbles || false, params.cancelable || false, params.detail || {});
								}
								return event;
						},

		 Switch : function (caseObject){

                    // preserve this in function scope
					var $this = this,
                        cases = {};

					if(_.isObject(caseObject)){
                        for(var $case in caseObject){

                            if( ({}).hasOwnProperty.call(caseObject,$case) ){
                                addCase($case,caseObject[$case]);
                            }
                        }
                    }

					// private methods
					function addCase(key,func,strict){

						// STRICT: only add case if it's not already defined
						if(strict){
							($fn.typeOf(cases[key]) == 'undefined') && (cases[key] = [func]);
							return;
						}

                        // ensure array
                        cases[key] = !_.isArray(cases[key]) ? [] : cases[key];
                        // ensure function
                        _.isFunction(func) && cases[key].push(func);

						return $this;
					}

					// @param $case[str]: the value you're trying to match
					// @param args[array]: arguments to pass to a matched function or functions
					function run($case,args){

                        if(!cases['default']){
                            cases['default'] = [function(){ return false; }];
                        }

						var $this = this;

                        // make sure the arguments are an array
						args = _.isArray(args) ? args : (_.isString(args) ? args.split(',') : []);

                        return cases[$case] ? callAll(cases[$case],args) : cases['default'][0](args);

                        // helper
                        function callAll(funcArray,args){

                            var n = funcArray.length;

                            if(n == 1){
                                return _.isFunction(funcArray[0]) && funcArray[0].apply(null,args);
                            }else{
                                for(var i=0; i<n; i++){
                                   // closure to preserve func reference
                                   callOne(funcArray[i],args);
                                }
                            }
						}

                        // helper's helper
                        function callOne(func,args){
                            // set timeout for async
                            setTimeout(function(){
                                _.isFunction(func) && func.apply(null,args);
                           },0);
                        }
					}

					// public

					this.addCase = function(key,func){
						return addCase(key,func);
					};
					this.run = function($case,argsArray){
						return run($case,argsArray);
					};
					this.getCases = function(){
						return cases;
					};
				},

		// a better typeof operation, although slower, it has the benefit of being predicatble
		// credit: Angus Croll
		// http://javascriptweblog.wordpress.com/2011/08/08/fixing-the-javascript-typeof-operator/
		typeOf : function(obj) {
  					return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase();
				},

		// create objects from query string in URL
		// credit Cory LaViska, http://www.abeautifulsite.net/parsing-urls-in-javascript/
		/* --------------------------------------------------------------------- */

		location : function (){

				 var parser = document.createElement('a'),
					  searchObject = {},
					  queries, param;
				 // Let the browser do the work
				 parser.href = window.location;
				 // Convert query string to object
				 queries = parser.search.replace(/^\?/, '').split('&');

				 for( var i = 0,n = queries.length; i < n; i++ ) {
					  param = queries[i].split('=');

					  if( !$fn.isBlank(param) ){
					  	var key = param[0],val = param[1];
					  	searchObject[key] = val;
					  }
				 }
				return {
					  protocol		: parser.protocol,
					  host			: parser.host,
					  hostname		: parser.hostname,
					  port			: parser.port,
					  pathname		: parser.pathname,
					  searchString	: parser.search,
					  searchObject	: searchObject,
					  hash			: parser.hash
				 };
			},

        titleize : function(string){

                        if($fn.typeOf(string) == 'string'){
                            return string
                                    .replace(/\-+|[_]+/,' ')
                                    .replace(/^.|\s+?[a-z]/g,
                                        function(chr){
                                            return chr.toUpperCase();
                                    });
                        }
                    },

        camelize : function(string){

                         if($fn.typeOf(string) == 'string'){
                            return string
                            .replace(/\W+?[a-z]|\_+?[a-z]/g,
                                function(chr){
                                    return chr.toUpperCase();
                            })
                            .replace(/\W+|\_+/g,'');
                         }
                    },

        dashify : function(string){

                         if($fn.typeOf(string) == 'string'){
                            return string
                                    .replace(/\s+|[_]+/g,'-')
                                    .replace(/[A-Z]/g,
                                        function(chr){
                                            return '-'+chr.toLowerCase();
                                    })
                                    .replace(/-{2}/g,'-');
                         }
                    },

        inArray : function(array,value){

                        return array.indexOf(value) !== -1;
                    }

	};

	!String.prototype.__titleize  && Object.defineProperty(String.prototype,'__titleize',{
		value : function (){
			return this
					.replace(/\-+|[_]+/,' ')
					.replace(/^.|\s+?[a-z]/g,
						function(chr){
							return chr.toUpperCase();
					});
		},
		configurable	: false,
		writable 		: false,
		enumerable 		: false

	});

	!String.prototype.__camelize && Object.defineProperty(String.prototype,'__camelize',{
		value : function (){
			return this
					.replace(/\W+?[a-z]|\_+?[a-z]/g,
						function(chr){
							return chr.toUpperCase();
					})
					.replace(/\W+|\_+/g,'');
		},
		configurable	: false,
		writable 		: false,
		enumerable 		: false
	});

	!String.prototype.__dashify && Object.defineProperty(String.prototype,'__dashify',{
		value : function (){
			return this
					.replace(/\s+|[_]+/g,'-')
					.replace(/[A-Z]/g,
						function(chr){
							return '-'+chr.toLowerCase();
					})
					.replace(/-{2}/g,'-');
		},
		configurable	: false,
		writable 		: false,
		enumerable 		: false
	});

	!Function.prototype.__construct && Object.defineProperty(Function.prototype,'__construct',{
		value:  function (args){
					var proto = this.prototype;
					var instance = Object.create(proto);
					this.apply(instance,args);
					return instance;
				},
		configurable	: false,
		writable 		: false,
		enumerable 		: false
	});

	!Array.prototype.__contains && Object.defineProperty(Array.prototype,'__contains',{
		value 			: function (value){ return this.indexOf(value) !== -1; },
		configurable	: false,
		writable 		: false,
		enumerable 		: false
	});

	!Array.prototype.__isEmpty && Object.defineProperty(Array.prototype,'__isEmpty',{
		value 			: function (){ return this.length === 0; },
		configurable 	: false,
		writable 		: false,
		enumerable 		: false
	});

	// augmenting Object.prototype? Insanity! At least it's non-enumberable...
	!Object.prototype.__isEmpty && Object.defineProperty(Object.prototype, '__isEmpty',{
		value : function (){
					var prop;
					for(prop in this){
						if( ({}).hasOwnProperty.call(this,prop)){
							return false;
						}
					}
					return true;
		},
		configurable 	: false,
		writable 		: false,
		enumerable 		: false
	});

	window[__] = $fn;

})('__',window,jQuery);

	<commit_msg>added __forEach and __map methods to Array.prototype in doubleUnder<commit_after>// utility methods

(function (__,window,jQuery){

	// intentionally global
	var $fn = {

		// return if an object is an object but not an array
		isObject	: 	function ($$,strict){
							if(strict){
								return ( (typeof $$ === 'object') && ($$ !== null));
							}
							return (typeof $$ === 'object') && ($$ !== null) && !($$ instanceof Array);
						},

		isArray	:	function ($$){
							return ( (typeof $$ === 'object') && ($$ instanceof Array) && $$.length >= 0 );
						},

		//  [undefined, null, false, 'false', 0, '0', '', empty string]
		isFalsey	:	function ($$){

							var case_ = 'case_'+$$,
								cases = {
									case_false		: function() { return true; },
									case_0 			: function() { return true; },
									case_null		: function() { return true; },
									case_undefined 	: function() { return true; },
									case_			: function() { return true; }
								};
							case_ = case_.trim();
							return cases[case_] ? cases[case_]() : false;

						},

		// checks undefined using strict equality (===)
		// [undefined]
		isUndefined	:	function ($$){
									return ( typeof $$ === 'undefined');
							},
		// checks null using strict equality (===)
		// [null]
		isNull		:	function ($$){
								return ($$ === null);
							},
		// checks for a sting with no value
		// [undefined, null, '', empty string]
		isBlank	:		function ($$){

							var case_ = 'case_'+$$,
								cases = {
									case_undefined 	: function(){ return true; },
									case_null		: function(){ return true; },
									case_			: function(){ return true; }
								};
							case_ = case_.trim();
							return cases[case_] ? cases[case_]() : false;
						},

		is$		:		function ($$){
								return ($$ instanceof jQuery);
							},

        isEmail :       function(email){

            return /^[-0-9a-zA-Z]+[-0-9a-zA-Z.+_]+@(?:[A-Za-z0-9-]+\.)+[a-zA-Z]{2,4}$/.test(email);
        },
		// create events
		createEvent	:	function  (type) {

                                var event;
                                try {
                                    event = new Event(type);
                                }catch(e){
                                    event = document.createEvent('event');
                                    event.initEvent(type,true,false);
                                }
                                return event;
							},

		// create custom events
		customEvent : 	function (type,params) {

								var event;
								if (window.CustomEvent) {

                                    try{
                                        params = params || { bubbles: false, cancelable: false, detail: {} };
                                        event = new CustomEvent(type, params);
                                    }catch (e){
                                        event = document.createEvent('CustomEvent');
								  	     event.initCustomEvent(type, params.bubbles || false, params.cancelable || false, params.detail || {});
                                    }

								} else {
									event = document.createEvent('CustomEvent');
								  	event.initCustomEvent(type, params.bubbles || false, params.cancelable || false, params.detail || {});
								}
								return event;
						},

		 Switch : function (caseObject){

                    // preserve this in function scope
					var $this = this,
                        cases = {};

					if(_.isObject(caseObject)){
                        for(var $case in caseObject){

                            if( ({}).hasOwnProperty.call(caseObject,$case) ){
                                addCase($case,caseObject[$case]);
                            }
                        }
                    }

					// private methods
					function addCase(key,func,strict){

						// STRICT: only add case if it's not already defined
						if(strict){
							($fn.typeOf(cases[key]) == 'undefined') && (cases[key] = [func]);
							return;
						}

                        // ensure array
                        cases[key] = !_.isArray(cases[key]) ? [] : cases[key];
                        // ensure function
                        _.isFunction(func) && cases[key].push(func);

						return $this;
					}

					// @param $case[str]: the value you're trying to match
					// @param args[array]: arguments to pass to a matched function or functions
					function run($case,args){

                        if(!cases['default']){
                            cases['default'] = [function(){ return false; }];
                        }

						var $this = this;

                        // make sure the arguments are an array
						args = _.isArray(args) ? args : [args];

                        return cases[$case] ? callAll(cases[$case],args) : cases['default'][0].apply(cases['default'][0],args);

                        // helper
                        function callAll(funcArray,args){

                            var n = funcArray.length;

                            if(n == 1){
                                return _.isFunction(funcArray[0]) && funcArray[0].apply(null,args);
                            }else{
                                for(var i=0; i<n; i++){
                                   // closure to preserve func reference
                                   callOne(funcArray[i],args);
                                }
                            }
						}

                        // helper's helper
                        function callOne(func,args){
                            // set timeout for async
                            setTimeout(function(){
                                _.isFunction(func) && func.apply(null,args);
                           },0);
                        }
					}

					// public

					this.addCase = function(key,func){
						return addCase(key,func);
					};
					this.run = function($case,argsArray){
						return run($case,argsArray);
					};
					this.getCases = function(){
						return cases;
					};
				},

		// a better typeof operation, although slower, it has the benefit of being predicatble
		// credit: Angus Croll
		// http://javascriptweblog.wordpress.com/2011/08/08/fixing-the-javascript-typeof-operator/
		typeOf : function(obj) {
  					return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase();
				},

		// create objects from query string in URL
		// credit Cory LaViska, http://www.abeautifulsite.net/parsing-urls-in-javascript/
		/* --------------------------------------------------------------------- */

		location : function (){

				 var parser = document.createElement('a'),
					  searchObject = {},
					  queries, param;
				 // Let the browser do the work
				 parser.href = window.location;
				 // Convert query string to object
				 queries = parser.search.replace(/^\?/, '').split('&');

				 for( var i = 0,n = queries.length; i < n; i++ ) {
					  param = queries[i].split('=');

					  if( !$fn.isBlank(param) ){
					  	var key = param[0],val = param[1];
					  	searchObject[key] = val;
					  }
				 }
				return {
					  protocol		: parser.protocol,
					  host			: parser.host,
					  hostname		: parser.hostname,
					  port			: parser.port,
					  pathname		: parser.pathname,
					  searchString	: parser.search,
					  searchObject	: searchObject,
					  hash			: parser.hash
				 };
			},

        titleize : function(string){

                        if($fn.typeOf(string) == 'string'){
                            return string
                                    .replace(/\-+|[_]+/,' ')
                                    .replace(/^.|\s+?[a-z]/g,
                                        function(chr){
                                            return chr.toUpperCase();
                                    });
                        }
                    },

        camelize : function(string){

                         if($fn.typeOf(string) == 'string'){
                            return string
                            .replace(/\W+?[a-z]|\_+?[a-z]/g,
                                function(chr){
                                    return chr.toUpperCase();
                            })
                            .replace(/\W+|\_+/g,'');
                         }
                    },

        dashify : function(string){

                         if($fn.typeOf(string) == 'string'){
                            return string
                                    .replace(/\s+|[_]+/g,'-')
                                    .replace(/[A-Z]/g,
                                        function(chr){
                                            return '-'+chr.toLowerCase();
                                    })
                                    .replace(/-{2}/g,'-');
                         }
                    },

        inArray : function(array,value){

                        return array.indexOf(value) !== -1;
                    }

	};

	!String.prototype.__titleize  && Object.defineProperty(String.prototype,'__titleize',{
		value : function (){
			return this
					.replace(/\-+|[_]+/,' ')
					.replace(/^.|\s+?[a-z]/g,
						function(chr){
							return chr.toUpperCase();
					});
		},
		configurable	: false,
		writable 		: false,
		enumerable 		: false

	});

	!String.prototype.__camelize && Object.defineProperty(String.prototype,'__camelize',{
		value : function (){
			return this
					.replace(/\W+?[a-z]|\_+?[a-z]/g,
						function(chr){
							return chr.toUpperCase();
					})
					.replace(/\W+|\_+/g,'');
		},
		configurable	: false,
		writable 		: false,
		enumerable 		: false
	});

	!String.prototype.__dashify && Object.defineProperty(String.prototype,'__dashify',{
		value : function (){
			return this
					.replace(/\s+|[_]+/g,'-')
					.replace(/[A-Z]/g,
						function(chr){
							return '-'+chr.toLowerCase();
					})
					.replace(/-{2}/g,'-');
		},
		configurable	: false,
		writable 		: false,
		enumerable 		: false
	});

	!Function.prototype.__construct && Object.defineProperty(Function.prototype,'__construct',{
		value:  function (args){
					var proto = this.prototype;
					var instance = Object.create(proto);
					this.apply(instance,args);
					return instance;
				},
		configurable	: false,
		writable 		: false,
		enumerable 		: false
	});

	!Array.prototype.__contains && Object.defineProperty(Array.prototype,'__contains',{
		value 			: function (value){ return this.indexOf(value) !== -1; },
		configurable	: false,
		writable 		: false,
		enumerable 		: false
	});

	!Array.prototype.__isEmpty && Object.defineProperty(Array.prototype,'__isEmpty',{
		value 			: function (){ return this.length === 0; },
		configurable 	: false,
		writable 		: false,
		enumerable 		: false
	});

	// augmenting Object.prototype? Insanity! At least it's non-enumberable...
	!Object.prototype.__isEmpty && Object.defineProperty(Object.prototype, '__isEmpty',{
		value : function (){
					var prop;
					for(prop in this){
						if( ({}).hasOwnProperty.call(this,prop)){
							return false;
						}
					}
					return true;
		},
		configurable 	: false,
		writable 		: false,
		enumerable 		: false
	});

    Object.defineProperty(Array.prototype, '__forEach',{
        value :function(closure){
                    var
                    n=this.length,
                    i=0;
                  for(i;i<n;i++){
                      closure(this[i],i);
                  }
        },
        configurable : false,
        writable : false,
        enumerable : false
    });

     Object.defineProperty(Array.prototype,'__map',{
         value : function(closure){
                    var
                    n = this.length,
                    mapped = [],
                    i=0;
                    for(;i<n;i++){
                        mapped[i]=closure(this[i],i);
                    }
                return mapped;
                },
         configurable : false,
         writable : false,
         enumerable : false
     });

	window[__] = $fn;

})('__',window,jQuery);

	<|endoftext|>


<commit_before>'use strict';

import uuid from '../utils/uuid';
import VueResource from 'vue-resource';
import Vuex from 'vuex';
import Vue from 'vue';

import {
  fetchTasks,
  saveTasks
} from './Actions';

import {
  ADD_TASK,
  DELETE_TASK,
  TOGGLE_COMPLETED,
  REPLACE_TASKS,
  CLEAR_TASKS
} from './MutationTypes';

Vue.use(VueResource);
Vue.use(Vuex);

export default new Vuex.Store({
  state: {
    tasks: [
      // { id: uuid(), title: 'Task 1', completed: false },
      // { id: uuid(), title: 'Task 2', completed: false },
      // { id: uuid(), title: 'Task 3', completed: true }
    ]
  },

  getters: {
    totalCompleted (state) {
      return state.tasks.filter(item => {
        return ! item.completed;
      }).length;
    }
  },

  mutations: {
    /**
     * Add a new task to the local store
     */
    [ADD_TASK] (state, payload) {
      state.tasks.push({
        id: uuid(),
        title: payload.title,
        completed: payload.completed
      });
    },

    /**
     * Delete a task from the local store by index
     */
    [DELETE_TASK] (state, payload) {
      state.tasks.splice(payload.index, 1);
    },

    /**
     * Toggle the completed state of a specific task
     */
    [TOGGLE_COMPLETED] (state, payload) {
      const task = state.tasks.find(item => item.id === payload.id);
      task.completed = ! task.completed;
    },

    /**
     * Replace all tasks within the local store
     */
    [REPLACE_TASKS] (state, payload) {
      state.tasks = payload.tasks;
    },

    /**
     * Remove all tasks from the local store
     */
    [CLEAR_TASKS] (state) {
      state.tasks = [];
    }
  },

  actions: {
    fetchTasks,
    saveTasks
  }
});
<commit_msg>Remove redundant import for vue-resource<commit_after>'use strict';

import uuid from '../utils/uuid';
import Vuex from 'vuex';
import Vue from 'vue';

import {
  fetchTasks,
  saveTasks
} from './Actions';

import {
  ADD_TASK,
  DELETE_TASK,
  TOGGLE_COMPLETED,
  REPLACE_TASKS,
  CLEAR_TASKS
} from './MutationTypes';

Vue.use(VueResource);
Vue.use(Vuex);

export default new Vuex.Store({
  state: {
    tasks: [
      // { id: uuid(), title: 'Task 1', completed: false },
      // { id: uuid(), title: 'Task 2', completed: false },
      // { id: uuid(), title: 'Task 3', completed: true }
    ]
  },

  getters: {
    totalCompleted (state) {
      return state.tasks.filter(item => {
        return ! item.completed;
      }).length;
    }
  },

  mutations: {
    /**
     * Add a new task to the local store
     */
    [ADD_TASK] (state, payload) {
      state.tasks.push({
        id: uuid(),
        title: payload.title,
        completed: payload.completed
      });
    },

    /**
     * Delete a task from the local store by index
     */
    [DELETE_TASK] (state, payload) {
      state.tasks.splice(payload.index, 1);
    },

    /**
     * Toggle the completed state of a specific task
     */
    [TOGGLE_COMPLETED] (state, payload) {
      const task = state.tasks.find(item => item.id === payload.id);
      task.completed = ! task.completed;
    },

    /**
     * Replace all tasks within the local store
     */
    [REPLACE_TASKS] (state, payload) {
      state.tasks = payload.tasks;
    },

    /**
     * Remove all tasks from the local store
     */
    [CLEAR_TASKS] (state) {
      state.tasks = [];
    }
  },

  actions: {
    fetchTasks,
    saveTasks
  }
});
<|endoftext|>


<commit_before>import { difference, isEmpty, pickBy } from 'lodash'
import { flow, filter, map, includes } from 'lodash/fp'
import {
  handleMissingTagDescriptions, throwErrorIfMissingTags
} from '../../lib/util/controllers'
import { normalizeComment } from '../../lib/util/normalize'
import { sanitize, markdown } from 'hylo-utils/text'

const userColumns = q => q.column('id', 'name', 'avatar_url')

const updateRecentComments = postId =>
  Queue.classMethod('Post', 'setRecentComments', {postId})

const presentComment = (comment) =>
  comment.load({user: userColumns})
  .then(c => CommentPresenter.present(c, c.get('user_id')))
  .then(c => {
    const buckets = {people: []}
    normalizeComment(c, buckets, true)
    return Object.assign(buckets, c)
  })

const createAndPresentComment = function (commenterId, text, post, opts = {}) {
  text = sanitize(text)
  var attrs = {
    text: text,
    created_at: new Date(),
    post_id: post.id,
    user_id: commenterId,
    active: true,
    created_from: opts.created_from || null
  }

  return post.load('followers')
  .then(() => {
    const mentioned = RichText.getUserMentions(text)
    const existingFollowers = post.relations.followers.pluck('id')
    const newFollowers = _.difference(_.uniq(mentioned.concat(commenterId)), existingFollowers)
    const isThread = post.get('type') === Post.Type.THREAD

    return bookshelf.transaction(trx =>
      new Comment(attrs).save(null, {transacting: trx})
      .tap(comment => Tag.updateForComment(comment, opts.tagDescriptions, trx))
      .tap(() => post.updateCommentCount(trx)))
    .then(comment => Promise.all([
      presentComment(comment)
      .tap(c => isThread
        ? post.pushMessageToSockets(c, existingFollowers)
        : post.pushCommentToSockets(c)),

      (isThread
        ? Queue.classMethod('Comment', 'notifyAboutMessage', {commentId: comment.id})
        : comment.createActivities()),

      post.addFollowers(newFollowers, commenterId),
      updateRecentComments(post.id)
    ]))
    .then(promises => promises[0])
  })
}

const checkCommentTags = (text, post, descriptions) => {
  const tags = Tag.tagsInText(text)
  const describedTags = Object.keys(pickBy(descriptions, (v, k) => !!v))
  return isEmpty(difference(tags, describedTags))
    ? Promise.resolve()
    : post.load('communities').then(() =>
        throwErrorIfMissingTags(tags, post.relations.communities.pluck('id')))
}

module.exports = {
  findForPost: function (req, res) {
    const { beforeId, limit, newest } = req.allParams()
    Comment.query(q => {
      q.where({post_id: res.locals.post.id, active: true})
      if (beforeId) q.where('id', '<', beforeId)
      if (limit) q.limit(limit)
      q.orderBy('id', newest ? 'desc' : 'asc')
    }).fetchAll({withRelated: [
      {user: userColumns},
      'thanks',
      {'thanks.thankedBy': userColumns}
    ]})
    .then(cs => cs.map(c => CommentPresenter.present(c, req.session.userId)))
    .then(comments => {
      const buckets = {people: []}
      comments.forEach((c, i) => normalizeComment(c, buckets, i === comments.length - 1))
      return Object.assign(buckets, {comments})
    })
    .then(res.ok, res.serverError)
  },

  create: function (req, res) {
    const text = req.param('text')
    const post = res.locals.post
    const tagDescriptions = req.param('tagDescriptions')

    return checkCommentTags(text, post, tagDescriptions)
    .then(() => createAndPresentComment(req.session.userId, text, post, {tagDescriptions}))
    .then(res.ok)
    .catch(err => {
      if (handleMissingTagDescriptions(err, res)) return
      res.serverError(err)
    })
  },

  createFromEmail: function (req, res) {
    try {
      var replyData = Email.decodePostReplyAddress(req.param('To'))
    } catch (e) {
      return res.serverError(new Error('Invalid reply address: ' + req.param('To')))
    }

    return Post.find(replyData.postId, {withRelated: 'communities'})
    .then(post => {
      if (!post) return
      const community = post.relations.communities.first()
      Analytics.track({
        userId: replyData.userId,
        event: 'Post: Comment: Add by Email',
        properties: {
          post_id: post.id,
          community: community && community.get('name')
        }
      })
      return User.find(replyData.userId).then(user => {
        const text = Comment.cleanEmailText(user, req.param('stripped-text'))
        return createAndPresentComment(replyData.userId, text, post, {created_from: 'email'})
      })
    })
    .then(() => res.ok({}), res.serverError)
  },

  thank: function (req, res) {
    Comment.find(req.param('commentId'), {withRelated: [
      {thanks: q => q.where('thanked_by_id', req.session.userId)}
    ]})
    .then(comment => {
      const thank = comment.relations.thanks.first()
      return thank
        ? thank.destroy()
        : Thank.create(comment, req.session.userId)
    })
    .then(() => res.ok({}), res.serverError)
  },

  destroy: function (req, res) {
    Comment.find(req.param('commentId'))
    .then(comment =>
      bookshelf.transaction(trx => Promise.join(
        Activity.removeForComment(comment.id, trx),

        Post.query().where('id', comment.get('post_id'))
        .decrement('num_comments', 1).transacting(trx),

        comment.save({
          deactivated_by_id: req.session.userId,
          deactivated_at: new Date(),
          active: false,
          recent: false
        }, {patch: true}).tap(c => updateRecentComments(c.get('post_id')))
    )))
    .then(() => res.ok({}), res.serverError)
  },

  update: function (req, res) {
    return Comment.find(req.param('commentId'))
    .then(comment => {
      if (!comment) return res.notFound()
      return bookshelf.transaction(function (trx) {
        return comment.save({text: req.param('text')}, {transacting: trx})
        .tap(comment => Tag.updateForComment(comment, req.param('tagDescriptions'), trx))
      })
      .then(res.ok, res.serverError)
    })
  },

  createBatchFromEmailForm: function (req, res) {
    const { communityId, userId } = res.locals.tokenData

    const replyText = postId => markdown(req.param(`post-${postId}`))

    const postIds = flow(
      Object.keys,
      filter(k => k.match(/^post-(\d)+$/)),
      map(k => k.replace(/^post-/, ''))
    )(req.allParams())

    var failures = false

    return Community.find(communityId)
    .then(community => Promise.map(postIds, id => {
      if (isEmpty(replyText(id))) return
      return Post.find(id, {withRelated: ['communities']})
      .then(post => {
        if (!post || !includes(communityId, post.relations.communities.pluck('id'))) {
          failures = true
          return Promise.resolve()
        }
        Analytics.track({
          userId,
          event: 'Post: Comment: Add by Email Form',
          properties: {
            post_id: post.id,
            community: community && community.get('name')
          }
        })
        return createAndPresentComment(userId, replyText(post.id), post, {created_from: 'email batch form'})
        .then(() => Post.setRecentComments({postId: post.id}))
      })
    })
    .then(() => {
      var notification
      if (failures) {
        notification = 'Some of your comments could not be added.'
      } else {
        notification = 'Your comments have been added.'
      }
      return res.redirect(Frontend.Route.community(community) + `?notification=${notification}&error=${failures}`)
    }, res.serverError))
  }
}
<commit_msg>change query string for batch comment notification<commit_after>import { difference, isEmpty, pickBy } from 'lodash'
import { flow, filter, map, includes } from 'lodash/fp'
import {
  handleMissingTagDescriptions, throwErrorIfMissingTags
} from '../../lib/util/controllers'
import { normalizeComment } from '../../lib/util/normalize'
import { sanitize, markdown } from 'hylo-utils/text'

const userColumns = q => q.column('id', 'name', 'avatar_url')

const updateRecentComments = postId =>
  Queue.classMethod('Post', 'setRecentComments', {postId})

const presentComment = (comment) =>
  comment.load({user: userColumns})
  .then(c => CommentPresenter.present(c, c.get('user_id')))
  .then(c => {
    const buckets = {people: []}
    normalizeComment(c, buckets, true)
    return Object.assign(buckets, c)
  })

const createAndPresentComment = function (commenterId, text, post, opts = {}) {
  text = sanitize(text)
  var attrs = {
    text: text,
    created_at: new Date(),
    post_id: post.id,
    user_id: commenterId,
    active: true,
    created_from: opts.created_from || null
  }

  return post.load('followers')
  .then(() => {
    const mentioned = RichText.getUserMentions(text)
    const existingFollowers = post.relations.followers.pluck('id')
    const newFollowers = _.difference(_.uniq(mentioned.concat(commenterId)), existingFollowers)
    const isThread = post.get('type') === Post.Type.THREAD

    return bookshelf.transaction(trx =>
      new Comment(attrs).save(null, {transacting: trx})
      .tap(comment => Tag.updateForComment(comment, opts.tagDescriptions, trx))
      .tap(() => post.updateCommentCount(trx)))
    .then(comment => Promise.all([
      presentComment(comment)
      .tap(c => isThread
        ? post.pushMessageToSockets(c, existingFollowers)
        : post.pushCommentToSockets(c)),

      (isThread
        ? Queue.classMethod('Comment', 'notifyAboutMessage', {commentId: comment.id})
        : comment.createActivities()),

      post.addFollowers(newFollowers, commenterId),
      updateRecentComments(post.id)
    ]))
    .then(promises => promises[0])
  })
}

const checkCommentTags = (text, post, descriptions) => {
  const tags = Tag.tagsInText(text)
  const describedTags = Object.keys(pickBy(descriptions, (v, k) => !!v))
  return isEmpty(difference(tags, describedTags))
    ? Promise.resolve()
    : post.load('communities').then(() =>
        throwErrorIfMissingTags(tags, post.relations.communities.pluck('id')))
}

module.exports = {
  findForPost: function (req, res) {
    const { beforeId, limit, newest } = req.allParams()
    Comment.query(q => {
      q.where({post_id: res.locals.post.id, active: true})
      if (beforeId) q.where('id', '<', beforeId)
      if (limit) q.limit(limit)
      q.orderBy('id', newest ? 'desc' : 'asc')
    }).fetchAll({withRelated: [
      {user: userColumns},
      'thanks',
      {'thanks.thankedBy': userColumns}
    ]})
    .then(cs => cs.map(c => CommentPresenter.present(c, req.session.userId)))
    .then(comments => {
      const buckets = {people: []}
      comments.forEach((c, i) => normalizeComment(c, buckets, i === comments.length - 1))
      return Object.assign(buckets, {comments})
    })
    .then(res.ok, res.serverError)
  },

  create: function (req, res) {
    const text = req.param('text')
    const post = res.locals.post
    const tagDescriptions = req.param('tagDescriptions')

    return checkCommentTags(text, post, tagDescriptions)
    .then(() => createAndPresentComment(req.session.userId, text, post, {tagDescriptions}))
    .then(res.ok)
    .catch(err => {
      if (handleMissingTagDescriptions(err, res)) return
      res.serverError(err)
    })
  },

  createFromEmail: function (req, res) {
    try {
      var replyData = Email.decodePostReplyAddress(req.param('To'))
    } catch (e) {
      return res.serverError(new Error('Invalid reply address: ' + req.param('To')))
    }

    return Post.find(replyData.postId, {withRelated: 'communities'})
    .then(post => {
      if (!post) return
      const community = post.relations.communities.first()
      Analytics.track({
        userId: replyData.userId,
        event: 'Post: Comment: Add by Email',
        properties: {
          post_id: post.id,
          community: community && community.get('name')
        }
      })
      return User.find(replyData.userId).then(user => {
        const text = Comment.cleanEmailText(user, req.param('stripped-text'))
        return createAndPresentComment(replyData.userId, text, post, {created_from: 'email'})
      })
    })
    .then(() => res.ok({}), res.serverError)
  },

  thank: function (req, res) {
    Comment.find(req.param('commentId'), {withRelated: [
      {thanks: q => q.where('thanked_by_id', req.session.userId)}
    ]})
    .then(comment => {
      const thank = comment.relations.thanks.first()
      return thank
        ? thank.destroy()
        : Thank.create(comment, req.session.userId)
    })
    .then(() => res.ok({}), res.serverError)
  },

  destroy: function (req, res) {
    Comment.find(req.param('commentId'))
    .then(comment =>
      bookshelf.transaction(trx => Promise.join(
        Activity.removeForComment(comment.id, trx),

        Post.query().where('id', comment.get('post_id'))
        .decrement('num_comments', 1).transacting(trx),

        comment.save({
          deactivated_by_id: req.session.userId,
          deactivated_at: new Date(),
          active: false,
          recent: false
        }, {patch: true}).tap(c => updateRecentComments(c.get('post_id')))
    )))
    .then(() => res.ok({}), res.serverError)
  },

  update: function (req, res) {
    return Comment.find(req.param('commentId'))
    .then(comment => {
      if (!comment) return res.notFound()
      return bookshelf.transaction(function (trx) {
        return comment.save({text: req.param('text')}, {transacting: trx})
        .tap(comment => Tag.updateForComment(comment, req.param('tagDescriptions'), trx))
      })
      .then(res.ok, res.serverError)
    })
  },

  createBatchFromEmailForm: function (req, res) {
    const { communityId, userId } = res.locals.tokenData

    const replyText = postId => markdown(req.param(`post-${postId}`))

    const postIds = flow(
      Object.keys,
      filter(k => k.match(/^post-(\d)+$/)),
      map(k => k.replace(/^post-/, ''))
    )(req.allParams())

    var failures = false

    return Community.find(communityId)
    .then(community => Promise.map(postIds, id => {
      if (isEmpty(replyText(id))) return
      return Post.find(id, {withRelated: ['communities']})
      .then(post => {
        if (!post || !includes(communityId, post.relations.communities.pluck('id'))) {
          failures = true
          return Promise.resolve()
        }
        Analytics.track({
          userId,
          event: 'Post: Comment: Add by Email Form',
          properties: {
            post_id: post.id,
            community: community && community.get('name')
          }
        })
        return createAndPresentComment(userId, replyText(post.id), post, {created_from: 'email batch form'})
        .then(() => Post.setRecentComments({postId: post.id}))
      })
    })
    .then(() => {
      var notification
      if (failures) {
        notification = 'Some of your comments could not be added.'
      } else {
        notification = 'Your comments have been added.'
      }
      return res.redirect(Frontend.Route.community(community) +
        `?notification=${notification}${failures ? '&error=true' : ''}`)
    }, res.serverError))
  }
}
<|endoftext|>


<commit_before>/**
 * UpdatesController
 *
 * @description :: Server-side logic for managing Telegram's BOT Updates
 * @author      :: Alejandro González - algope@github
 * @licence     :: The MIT License (MIT)
 * @help        :: See http://sailsjs.org/#!/documentation/concepts/Controllers
 *
 */

var Mixpanel = require('mixpanel');
var mixpanel = Mixpanel.init('2ac0d6d54c481e7dea88d065874c806f');

module.exports = {

    update: function (req, res) {
        var update = req.body;
        var userId = update.message.from.id;
        var userName = update.message.from.first_name;
        var userLast = update.message.from.last_name;
        var userAlias = update.message.from.username;
        if (update.message.text) {
            var text = update.message.text;
            var command = commands.processIt(text);
        } else command = false;

        /**
         * Creates a new entry into Updates table
         */
        update.message.chat.chat_id = update.message.chat.id;
        delete update.message.chat.id;
        res.ok(update);
        sails.log.debug("I'M HERE 1");
        Updates.create(req.body, function (ko, ok) {
            if (ko) {
                sails.log.error("[DB] - Updates.create error: ", ko);
            }
            if (ok) {
                mixpanel.track("Update", {
                    distinct_id: update.update_id,
                    from: userId,
                    user_id: userAlias,
                    text: update.message.text,
                    photo: update.message.photo
                });
            }
        });
        sails.log.debug("I'M HERE 2--");

        /**
         * Let's look for a previous user, otherwise we create a new one
         */
        stages.findOrCreateEntry({user_id: userId}, {user_id: userId, stage: 1}).then(
            function (user) {
                mixpanel.people.set(userId, {
                    "$first_name": userName,
                    "$last_name": userLast,
                    "user_name": userAlias,
                    "$created": user.createdAt,
                    "stage": user.stage,
                    "contributions": 0
                });
                /**
                 * STAGE 1 > First stage, no commands executed.
                 */
                if (user.stage == 1) { //Initial stage

                    if (update.message.photo || command.commandId == 0 || !command) {
                        answers.answeringError(userId, update, userAlias, user);
                    } else if (command.commandType == 1) {
                        answers.answeringCommandsS1(command, userId, userName)
                    } else {
                        answers.answeringError(userId, update, userAlias, user);
                    }

                    /**
                     * STAGE 2 > Second stage, command /enviar_info executed
                     */
                } else if (user.stage == 2) { //Command /enviar_info

                    if (update.message.photo || command.commandId == 0 || !command) {
                        answers.answeringError(userId, update, userAlias, user);
                    } else if (command.commandType == 1) {
                        answers.answeringCommandsS2(command, userId, userName);
                    } else if (command.commandType == 3) {
                        answers.answeringTextOrImage(command, userId);
                    } else {
                        answers.answeringError(userId, update, userAlias, user);
                    }

                    /**
                     * STAGE 3 > Third stage, the user had selected datatype
                     */
                } else if (user.stage == 3) { //Data type selected

                    if (command && command.commandType == 1) {
                        answers.answeringCommandsS3(command, userId, userName);
                    } else if (update.message.photo && user.data_type_selected == 2) {
                        answers.answeringLabelingS3(1, update, userId);
                    } else if (update.message.text && user.data_type_selected == 1) {
                        answers.answeringLabelingS3(2, update, userId);
                    } else {
                        answers.answeringError(userId, update, userAlias, user);
                    }

                    /**
                     * STAGE 4 > Fourth stage, the bot had recieved the media
                     */
                } else if (user.stage == 4) { //Data recieved, not labeled

                    sails.log.debug("commandID: ", command.commandId);
                    if (update.message.photo || command.commandId == 0 || !command) {
                        answers.answeringError(userId, update, userAlias, user);
                    } else if (command.commandType == 1) {
                        answers.answeringCommandsS4(command, userId, userName);
                    } else if (command.commandType == 2) {
                        answers.answeringThanksS4(userId, command, update);
                    } else {
                        answers.answeringError(userId, update, userAlias, user);
                    }

                    /**
                     * STAGE 10 > Tenth stage (no regular), FeedBack Stage
                     */
                } else if (user.stage == 10) { //FeedBack

                    if (update.message.photo || command.commandId == 0) {
                        answers.answeringError(userId, update, userAlias, user);
                    } else if (command && command.commandType == 1) {
                        answers.answeringCommandsS10(command, userId ,userName);
                    } else if (update.message.text) {
                        answers.answeringThanksS10(userId, update, userAlias);
                    } else {
                        answers.answeringError(userId, update, userAlias, user);
                    }
                }
            }
        );
        res.ok();
    }
};

<commit_msg>testing models<commit_after>/**
 * UpdatesController
 *
 * @description :: Server-side logic for managing Telegram's BOT Updates
 * @author      :: Alejandro González - algope@github
 * @licence     :: The MIT License (MIT)
 * @help        :: See http://sailsjs.org/#!/documentation/concepts/Controllers
 *
 */

var Mixpanel = require('mixpanel');
var mixpanel = Mixpanel.init('2ac0d6d54c481e7dea88d065874c806f');

module.exports = {

    update: function (req, res) {
        var update = req.body;
        var userId = update.message.from.id;
        var userName = update.message.from.first_name;
        var userLast = update.message.from.last_name;
        var userAlias = update.message.from.username;
        if (update.message.text) {
            var text = update.message.text;
            var command = commands.processIt(text);
        } else command = false;

        /**
         * Creates a new entry into Updates table
         */
        update.message.chat.chat_id = update.message.chat.id;
        update.message.from.user_id = update.message.from.id;
        delete update.message.chat.id;
        delete update.message.from.id;
        res.ok(update);
        sails.log.debug("I'M HERE 1");
        Updates.create(req.body, function (ko, ok) {
            if (ko) {
                sails.log.error("[DB] - Updates.create error: ", ko);
            }
            if (ok) {
                mixpanel.track("Update", {
                    distinct_id: update.update_id,
                    from: userId,
                    user_id: userAlias,
                    text: update.message.text,
                    photo: update.message.photo
                });
            }
        });
        sails.log.debug("I'M HERE 2--");

        /**
         * Let's look for a previous user, otherwise we create a new one
         */
        stages.findOrCreateEntry({user_id: userId}, {user_id: userId, stage: 1}).then(
            function (user) {
                mixpanel.people.set(userId, {
                    "$first_name": userName,
                    "$last_name": userLast,
                    "user_name": userAlias,
                    "$created": user.createdAt,
                    "stage": user.stage,
                    "contributions": 0
                });
                /**
                 * STAGE 1 > First stage, no commands executed.
                 */
                if (user.stage == 1) { //Initial stage

                    if (update.message.photo || command.commandId == 0 || !command) {
                        answers.answeringError(userId, update, userAlias, user);
                    } else if (command.commandType == 1) {
                        answers.answeringCommandsS1(command, userId, userName)
                    } else {
                        answers.answeringError(userId, update, userAlias, user);
                    }

                    /**
                     * STAGE 2 > Second stage, command /enviar_info executed
                     */
                } else if (user.stage == 2) { //Command /enviar_info

                    if (update.message.photo || command.commandId == 0 || !command) {
                        answers.answeringError(userId, update, userAlias, user);
                    } else if (command.commandType == 1) {
                        answers.answeringCommandsS2(command, userId, userName);
                    } else if (command.commandType == 3) {
                        answers.answeringTextOrImage(command, userId);
                    } else {
                        answers.answeringError(userId, update, userAlias, user);
                    }

                    /**
                     * STAGE 3 > Third stage, the user had selected datatype
                     */
                } else if (user.stage == 3) { //Data type selected

                    if (command && command.commandType == 1) {
                        answers.answeringCommandsS3(command, userId, userName);
                    } else if (update.message.photo && user.data_type_selected == 2) {
                        answers.answeringLabelingS3(1, update, userId);
                    } else if (update.message.text && user.data_type_selected == 1) {
                        answers.answeringLabelingS3(2, update, userId);
                    } else {
                        answers.answeringError(userId, update, userAlias, user);
                    }

                    /**
                     * STAGE 4 > Fourth stage, the bot had recieved the media
                     */
                } else if (user.stage == 4) { //Data recieved, not labeled

                    sails.log.debug("commandID: ", command.commandId);
                    if (update.message.photo || command.commandId == 0 || !command) {
                        answers.answeringError(userId, update, userAlias, user);
                    } else if (command.commandType == 1) {
                        answers.answeringCommandsS4(command, userId, userName);
                    } else if (command.commandType == 2) {
                        answers.answeringThanksS4(userId, command, update);
                    } else {
                        answers.answeringError(userId, update, userAlias, user);
                    }

                    /**
                     * STAGE 10 > Tenth stage (no regular), FeedBack Stage
                     */
                } else if (user.stage == 10) { //FeedBack

                    if (update.message.photo || command.commandId == 0) {
                        answers.answeringError(userId, update, userAlias, user);
                    } else if (command && command.commandType == 1) {
                        answers.answeringCommandsS10(command, userId ,userName);
                    } else if (update.message.text) {
                        answers.answeringThanksS10(userId, update, userAlias);
                    } else {
                        answers.answeringError(userId, update, userAlias, user);
                    }
                }
            }
        );
        res.ok();
    }
};

<|endoftext|>


<commit_before>import moment from 'moment';
import TextFieldComponent from '../textfield/TextField';

const defaultDataFormat = 'HH:mm:ss';

export default class TimeComponent extends TextFieldComponent {
  static schema(...extend) {
    return TextFieldComponent.schema({
      type: 'time',
      label: 'Time',
      key: 'time',
      inputType: 'time',
      format: 'HH:mm',
      dataFormat: defaultDataFormat,
    }, ...extend);
  }

  constructor(component, options, data) {
    super(component, options, data);
    //check if <input type="time" /> is supported to fallback to input with mask (for Safari and IE)
    const input = this.ce('time');
    this.timeInputSupported = (input.type === 'time');
    if (!this.timeInputSupported) {
      this.component.inputMask = '99:99';
    }
  }

  static get builderInfo() {
    return {
      title: 'Time',
      icon: 'clock-o',
      group: 'advanced',
      documentation: 'http://help.form.io/userguide/#time',
      weight: 55,
      schema: TimeComponent.schema(),
    };
  }

  get dataFormat() {
    return this.component.dataFormat || defaultDataFormat;
  }

  get defaultSchema() {
    return TimeComponent.schema();
  }

  get defaultValue() {
    let value = super.defaultValue;
    if (this.component.multiple && Array.isArray(value)) {
      value = value.map(item => item ? moment(item).format(this.component.format) : item);
    }
    else {
      if (value) {
        value = moment(value).format(this.component.format);
      }
    }
    return value;
  }

  get inputInfo() {
    const info = super.inputInfo;
    info.attr.type = 'time';
    return info;
  }

  get skipMaskValidation() {
    return true;
  }

  getValueAt(index) {
    if (!this.refs.input.length || !this.refs.input[index]) {
      return this.emptyValue;
    }
    const val = this.refs.input[index].value;
    if (!val) {
      return this.emptyValue;
    }

    return moment(val, this.component.format).format(this.dataFormat);
  }

  setValueAt(index, value) {
    this.refs.input[index].value = value ? this.getView(value) : value;
  }

  getView(value) {
    return moment(value, this.dataFormat).format(this.component.format);
  }
}
<commit_msg>Time component improvements.<commit_after>import moment from 'moment';
import TextFieldComponent from '../textfield/TextField';

const defaultDataFormat = 'HH:mm:ss';

export default class TimeComponent extends TextFieldComponent {
  static schema(...extend) {
    return TextFieldComponent.schema({
      type: 'time',
      label: 'Time',
      key: 'time',
      inputType: 'time',
      format: 'HH:mm',
      dataFormat: defaultDataFormat,
    }, ...extend);
  }

  constructor(component, options, data) {
    super(component, options, data);
    //check if <input type="time" /> is supported to fallback to input with mask (for Safari and IE)
    const input = this.ce('time');
    this.timeInputSupported = (input.type === 'time');
    if (!this.timeInputSupported) {
      this.component.inputMask = '99:99';
    }
  }

  static get builderInfo() {
    return {
      title: 'Time',
      icon: 'clock-o',
      group: 'advanced',
      documentation: 'http://help.form.io/userguide/#time',
      weight: 55,
      schema: TimeComponent.schema(),
    };
  }

  get dataFormat() {
    return this.component.dataFormat || defaultDataFormat;
  }

  get defaultSchema() {
    return TimeComponent.schema();
  }

  get defaultValue() {
    let value = super.defaultValue;
    if (this.component.multiple && Array.isArray(value)) {
      value = value.map(item => item ? this.getValueFromView(item) : item);
    }
    else {
      if (value) {
        value = this.getValueFromView(value);
      }
    }
    return value;
  }

  get inputInfo() {
    const info = super.inputInfo;
    info.attr.type = 'time';
    return info;
  }

  get skipMaskValidation() {
    return true;
  }

  getValueAt(index) {
    if (!this.refs.input.length || !this.refs.input[index]) {
      return this.emptyValue;
    }
    const { value } = this.refs.input[index];
    if (!value) {
      return this.emptyValue;
    }

    return this.getValueFromView(value);
  }

  setValueAt(index, value) {
    this.refs.input[index].value = value ? this.getView(value) : value;
  }

  getValueFromView(view) {
    return moment(view, this.component.format).format(this.dataFormat);
  }

  getView(value) {
    return moment(value, this.dataFormat).format(this.component.format);
  }
}
<|endoftext|>


<commit_before>/**
 * Created by irelance on 2017/2/3.
 */
ExcelTable.table.Action = function (parent) {
    this.private = {
        getText: function (sRow, sCol, eRow, eCol) {
            var txt = '';
            for (var j = sRow; j <= eRow; j++) {
                for (var i = sCol; i <= eCol; i++) {
                    txt += parent.result[j][i].value;
                    if (i == eCol && j != eRow) {
                        txt += "\n";
                    } else if (i != eCol) {
                        txt += "\t";
                    }
                }
            }
            return txt;
        },
        deleteText: function (sRow, sCol, eRow, eCol) {
            for (var j = sRow; j <= eRow; j++) {
                for (var i = sCol; i <= eCol; i++) {
                    ExcelTable.unit.setValue(parent.result[j][i], '');
                }
            }
        },
        getCRLF: function (txt) {
            var CRLFs = ["\r\n", "\n\r", "\n", "\r"];
            var CRLF = false;
            for (var i in CRLFs) {
                if (txt.indexOf(CRLFs[i]) != -1) {
                    CRLF = CRLFs[i];
                    break;
                }
            }
            return CRLF;
        },
        pasteText: function (sRow, sCol, txt) {
            var CRLF = this.getCRLF(txt);
            var rows = txt.split(CRLF),
                cols = [];
            rows.forEach(function (v, i) {
                cols = v.split("\t");
                cols.forEach(function (v, j) {
                    if (parent.result[sRow + i] && parent.result[sRow + i][sCol + j]) {
                        ExcelTable.unit.setValue(parent.result[sRow + i][sCol + j], v);
                    }
                });
            });
        },
        csv2json: function (txt) {
            var CRLF = this.getCRLF(txt),
                rows = txt.split(CRLF),
                match = /^"(.*)"$/,
                data = {
                    rows: 0,
                    columns: 0,
                    units: []
                };
            rows.forEach(function (cols, i) {
                cols = cols.split(',');
                cols.forEach(function (unit, j) {
                    unit = unit.replace(match, '$1');
                    data.units.push({row: i, column: j, value: unit});
                    data.columns = j + 1;
                    data.rows = i + 1;
                })
            });
            return data;
        }
    };
    this.copy = function () {
        var txt = this.private.getText(
            parent.selectLines.range.sRow,
            parent.selectLines.range.sCol,
            parent.selectLines.range.eRow,
            parent.selectLines.range.eCol
        );
        var clipboard = parent.target.find('.clipboard');
        clipboard.val(txt).show().trigger('select');
        document.execCommand('Copy');
        clipboard.hide();
        return parent;
    };
    this.delete = function () {
        this.private.deleteText(
            parent.selectLines.range.sRow,
            parent.selectLines.range.sCol,
            parent.selectLines.range.eRow,
            parent.selectLines.range.eCol
        );
        return parent;
    };
    this.paste = function (txt) {
        this.private.pasteText(parent.selectLines.active.row, parent.selectLines.active.col, txt);
        return parent;
    };
    this.import = function (mixed) {
        switch (typeof mixed) {
            case 'string':
                break;
            case 'object':
                parent.rows = mixed.rows ? mixed.rows : 0;
                parent.columns = mixed.columns ? mixed.columns : 0;
                parent.units = [];
                for (var i = 0; i < parent.rows; i++) {
                    for (var j = 0; j < parent.columns; j++) {
                        parent.createUnit(i, j);
                    }
                }
                parent.dimOne2Two();
                if (mixed.units) {
                    mixed.units.forEach(function (v) {
                        ExcelTable.unit.setValue(parent.result[v.row][v.column], v.value);
                    });
                }
                break;
        }
        return parent;
    };
    this.export = function () {
        var data = {
            rows: parent.rows,
            columns: parent.columns,
            units: []
        };
        parent.result.forEach(function (row, i) {
            row.forEach(function (unit, j) {
                if (unit.value == 0 || unit.value) {
                    data.units.push({row: unit.row, column: unit.column, value: unit.value});
                }
            });
        });
        return data;
    };
    this.move = function (row, col) {
        var txt = this.private.getText(
            parent.selectLines.range.sRow,
            parent.selectLines.range.sCol,
            parent.selectLines.range.eRow,
            parent.selectLines.range.eCol
        );
        this.private.deleteText(
            parent.selectLines.range.sRow,
            parent.selectLines.range.sCol,
            parent.selectLines.range.eRow,
            parent.selectLines.range.eCol
        );
        this.private.pasteText(row, col, txt);
        return parent;
    };
    this.sort = function (type) {
        switch (type) {
            case 'asc':
                type = 1;
                break;
            case 'desc':
                type = -1;
                break;
            default:
                return false;
        }
        var sCol = parent.selectLines.range.sCol,
            eCol = parent.selectLines.range.eCol;
        if (parent.selectLines.range.sCol == parent.selectLines.active.col && parent.selectLines.range.eCol == parent.selectLines.active.col) {
            sCol = 0;
            eCol = parent.columns - 1;
        }
        var list = [];
        for (var i = parent.selectLines.range.sRow; i <= parent.selectLines.range.eRow; i++) {
            list.push(parent.result[i][parent.selectLines.active.col]);
        }
        list.sort(function (a, b) {
            if (typeof a.result != 'number' && typeof b.result == 'number') {
                return type;
            }
            return a.result == b.result ? 0 : a.result > b.result ? type : -type;
        });
        list.forEach(function (v, i) {
            parent.result[v.row].forEach(function (unit) {
                if (unit.column >= sCol && unit.column <= eCol) {
                    unit.row = i;
                }
            });
        });
        return parent;
    };
    this.insertRow = function (active, number) {
        var i, j;
        if (active < 0 && active >= -parent.rows) {
            active += parent.rows;
        } else if (active >= 0 && active <= parent.rows) {
        } else if (active == 'append') {
            active = parent.rows;
        } else {
            return false;
        }
        if (!number) {
            number = 1;
        }
        for (i = active; i < parent.rows; i++) {
            for (j = 0; j < parent.rows; j++) {
                parent.result[j][i].row += number;
            }
        }
        for (i = 0; i < parent.columns; i++) {
            for (j = active; j < active + number; j++) {
                parent.createUnit(j, i);
            }
        }
        parent.rows += number;
        return parent;
    };
    this.insertColumn = function (active, number) {
        var i, j;
        if (active < 0 && active >= -parent.columns) {
            active += parent.columns;
        } else if (active >= 0 && active <= parent.columns) {
        } else if (active == 'append') {
            active = parent.columns;
        } else {
            return false;
        }
        if (!number) {
            number = 1;
        }
        for (i = active; i < parent.columns; i++) {
            for (j = 0; j < parent.rows; j++) {
                parent.result[j][i].column += number;
            }
        }
        for (i = 0; i < parent.rows; i++) {
            for (j = active; j < active + number; j++) {
                parent.createUnit(i, j);
            }
        }
        parent.columns += number;
        return parent;
    };
    this.increaseHorizontal = function () {
        var iHorizontal = function (row, sRange, eRange) {
            var length = 0,
                number = 0,
                first = 0,
                last = 0,
                i, err;
            for (i = sRange.sCol; i <= sRange.eCol; i++) {
                if (parent.result[row][i].type == 'number') {
                    last = parent.result[row][i].result;
                    if (!number) {
                        first = last;
                    }
                    number++;
                }
                length++;
            }
            err = (last - first) / (number - 1) * number;
            err = err ? err : 0;
            for (i = sRange.eCol + 1; i <= eRange.eCol; i++) {
                switch (parent.result[row][i - length].type) {
                    case 'function':
                        ExcelTable.unit.setValue(parent.result[row][i], parent.result[row][i - length].value);
                        break;
                    case 'number':
                        ExcelTable.unit.setValue(parent.result[row][i], parent.result[row][i - length].value + err);
                        break;
                    default:
                        ExcelTable.unit.setValue(parent.result[row][i], parent.result[row][i - length].value);
                        break;
                }
            }
        };
        for (var j = parent.changeLines.eRange.sRow; j <= parent.changeLines.eRange.eRow; j++) {
            iHorizontal(j, parent.changeLines.sRange, parent.changeLines.eRange);
        }
    };
    this.increaseVertical = function () {
        var iVertical = function (col, sRange, eRange) {
            var length = 0,
                number = 0,
                first = 0,
                last = 0,
                i, err;
            for (i = sRange.sRow; i <= sRange.eRow; i++) {
                if (parent.result[i][col].type == 'number') {
                    last = parent.result[i][col].result;
                    if (!number) {
                        first = last;
                    }
                    number++;
                }
                length++;
            }
            err = (last - first) / (number - 1) * number;
            err = err ? err : 0;
            for (i = sRange.eRow + 1; i <= eRange.eRow; i++) {
                switch (parent.result[i - length][col].type) {
                    case 'function':
                        ExcelTable.unit.setValue(parent.result[i][col], parent.result[i - length][col].value);
                        break;
                    case 'number':
                        ExcelTable.unit.setValue(parent.result[i][col], parent.result[i - length][col].value + err);
                        break;
                    default:
                        ExcelTable.unit.setValue(parent.result[i][col], parent.result[i - length][col].value);
                        break;
                }
            }
        };
        for (var j = parent.changeLines.eRange.sCol; j <= parent.changeLines.eRange.eCol; j++) {
            iVertical(j, parent.changeLines.sRange, parent.changeLines.eRange);
        }
    };
    this.decreaseHorizontal = function () {
        var dHorizontal = function (row, sRange, eRange) {
            var length = 0,
                number = 0,
                first = 0,
                last = 0,
                i, err;
            for (i = sRange.sCol; i <= sRange.eCol; i++) {
                if (parent.result[row][i].type == 'number') {
                    last = parent.result[row][i].result;
                    if (!number) {
                        first = last;
                    }
                    number++;
                }
                length++;
            }
            err = (last - first) / (number - 1) * number;
            err = err ? err : 0;
            for (i = eRange.sCol; i < sRange.sCol; i++) {
                switch (parent.result[row][i + length].type) {
                    case 'function':
                        ExcelTable.unit.setValue(parent.result[row][i], parent.result[row][i + length].value);
                        break;
                    case 'number':
                        ExcelTable.unit.setValue(parent.result[row][i], parent.result[row][i + length].value - err);
                        break;
                    default:
                        ExcelTable.unit.setValue(parent.result[row][i], parent.result[row][i + length].value);
                        break;
                }
            }
        };
        for (var j = parent.changeLines.eRange.sRow; j <= parent.changeLines.eRange.eRow; j++) {
            dHorizontal(j, parent.changeLines.sRange, parent.changeLines.eRange);
        }
    };
    this.decreaseVertical = function () {
        var dVertical = function (col, sRange, eRange) {
            var length = 0,
                number = 0,
                first = 0,
                last = 0,
                i, err;
            for (i = sRange.sRow; i <= sRange.eRow; i++) {
                if (parent.result[i][col].type == 'number') {
                    last = parent.result[i][col].result;
                    if (!number) {
                        first = last;
                    }
                    number++;
                }
                length++;
            }
            err = (last - first) / (number - 1) * number;
            err = err ? err : 0;
            for (i = eRange.sRow; i < sRange.sRow; i++) {
                switch (parent.result[i + length][col].type) {
                    case 'function':
                        ExcelTable.unit.setValue(parent.result[i][col], parent.result[i + length][col].value);
                        break;
                    case 'number':
                        ExcelTable.unit.setValue(parent.result[i][col], parent.result[i + length][col].value - err);
                        break;
                    default:
                        ExcelTable.unit.setValue(parent.result[i][col], parent.result[i + length][col].value);
                        break;
                }
            }
        };
        for (var j = parent.changeLines.eRange.sCol; j <= parent.changeLines.eRange.eCol; j++) {
            dVertical(j, parent.changeLines.sRange, parent.changeLines.eRange);
        }
    };
};<commit_msg>fix: autofill decrease bug<commit_after>/**
 * Created by irelance on 2017/2/3.
 */
ExcelTable.table.Action = function (parent) {
    this.private = {
        getText: function (sRow, sCol, eRow, eCol) {
            var txt = '';
            for (var j = sRow; j <= eRow; j++) {
                for (var i = sCol; i <= eCol; i++) {
                    txt += parent.result[j][i].value;
                    if (i == eCol && j != eRow) {
                        txt += "\n";
                    } else if (i != eCol) {
                        txt += "\t";
                    }
                }
            }
            return txt;
        },
        deleteText: function (sRow, sCol, eRow, eCol) {
            for (var j = sRow; j <= eRow; j++) {
                for (var i = sCol; i <= eCol; i++) {
                    ExcelTable.unit.setValue(parent.result[j][i], '');
                }
            }
        },
        getCRLF: function (txt) {
            var CRLFs = ["\r\n", "\n\r", "\n", "\r"];
            var CRLF = false;
            for (var i in CRLFs) {
                if (txt.indexOf(CRLFs[i]) != -1) {
                    CRLF = CRLFs[i];
                    break;
                }
            }
            return CRLF;
        },
        pasteText: function (sRow, sCol, txt) {
            var CRLF = this.getCRLF(txt);
            var rows = txt.split(CRLF),
                cols = [];
            rows.forEach(function (v, i) {
                cols = v.split("\t");
                cols.forEach(function (v, j) {
                    if (parent.result[sRow + i] && parent.result[sRow + i][sCol + j]) {
                        ExcelTable.unit.setValue(parent.result[sRow + i][sCol + j], v);
                    }
                });
            });
        },
        csv2json: function (txt) {
            var CRLF = this.getCRLF(txt),
                rows = txt.split(CRLF),
                match = /^"(.*)"$/,
                data = {
                    rows: 0,
                    columns: 0,
                    units: []
                };
            rows.forEach(function (cols, i) {
                cols = cols.split(',');
                cols.forEach(function (unit, j) {
                    unit = unit.replace(match, '$1');
                    data.units.push({row: i, column: j, value: unit});
                    data.columns = j + 1;
                    data.rows = i + 1;
                })
            });
            return data;
        }
    };
    this.copy = function () {
        var txt = this.private.getText(
            parent.selectLines.range.sRow,
            parent.selectLines.range.sCol,
            parent.selectLines.range.eRow,
            parent.selectLines.range.eCol
        );
        var clipboard = parent.target.find('.clipboard');
        clipboard.val(txt).show().trigger('select');
        document.execCommand('Copy');
        clipboard.hide();
        return parent;
    };
    this.delete = function () {
        this.private.deleteText(
            parent.selectLines.range.sRow,
            parent.selectLines.range.sCol,
            parent.selectLines.range.eRow,
            parent.selectLines.range.eCol
        );
        return parent;
    };
    this.paste = function (txt) {
        this.private.pasteText(parent.selectLines.active.row, parent.selectLines.active.col, txt);
        return parent;
    };
    this.import = function (mixed) {
        switch (typeof mixed) {
            case 'string':
                break;
            case 'object':
                parent.rows = mixed.rows ? mixed.rows : 0;
                parent.columns = mixed.columns ? mixed.columns : 0;
                parent.units = [];
                for (var i = 0; i < parent.rows; i++) {
                    for (var j = 0; j < parent.columns; j++) {
                        parent.createUnit(i, j);
                    }
                }
                parent.dimOne2Two();
                if (mixed.units) {
                    mixed.units.forEach(function (v) {
                        ExcelTable.unit.setValue(parent.result[v.row][v.column], v.value);
                    });
                }
                break;
        }
        return parent;
    };
    this.export = function () {
        var data = {
            rows: parent.rows,
            columns: parent.columns,
            units: []
        };
        parent.result.forEach(function (row, i) {
            row.forEach(function (unit, j) {
                if (unit.value == 0 || unit.value) {
                    data.units.push({row: unit.row, column: unit.column, value: unit.value});
                }
            });
        });
        return data;
    };
    this.move = function (row, col) {
        var txt = this.private.getText(
            parent.selectLines.range.sRow,
            parent.selectLines.range.sCol,
            parent.selectLines.range.eRow,
            parent.selectLines.range.eCol
        );
        this.private.deleteText(
            parent.selectLines.range.sRow,
            parent.selectLines.range.sCol,
            parent.selectLines.range.eRow,
            parent.selectLines.range.eCol
        );
        this.private.pasteText(row, col, txt);
        return parent;
    };
    this.sort = function (type) {
        switch (type) {
            case 'asc':
                type = 1;
                break;
            case 'desc':
                type = -1;
                break;
            default:
                return false;
        }
        var sCol = parent.selectLines.range.sCol,
            eCol = parent.selectLines.range.eCol;
        if (parent.selectLines.range.sCol == parent.selectLines.active.col && parent.selectLines.range.eCol == parent.selectLines.active.col) {
            sCol = 0;
            eCol = parent.columns - 1;
        }
        var list = [];
        for (var i = parent.selectLines.range.sRow; i <= parent.selectLines.range.eRow; i++) {
            list.push(parent.result[i][parent.selectLines.active.col]);
        }
        list.sort(function (a, b) {
            if (typeof a.result != 'number' && typeof b.result == 'number') {
                return type;
            }
            return a.result == b.result ? 0 : a.result > b.result ? type : -type;
        });
        list.forEach(function (v, i) {
            parent.result[v.row].forEach(function (unit) {
                if (unit.column >= sCol && unit.column <= eCol) {
                    unit.row = i;
                }
            });
        });
        return parent;
    };
    this.insertRow = function (active, number) {
        var i, j;
        if (active < 0 && active >= -parent.rows) {
            active += parent.rows;
        } else if (active >= 0 && active <= parent.rows) {
        } else if (active == 'append') {
            active = parent.rows;
        } else {
            return false;
        }
        if (!number) {
            number = 1;
        }
        for (i = active; i < parent.rows; i++) {
            for (j = 0; j < parent.rows; j++) {
                parent.result[j][i].row += number;
            }
        }
        for (i = 0; i < parent.columns; i++) {
            for (j = active; j < active + number; j++) {
                parent.createUnit(j, i);
            }
        }
        parent.rows += number;
        return parent;
    };
    this.insertColumn = function (active, number) {
        var i, j;
        if (active < 0 && active >= -parent.columns) {
            active += parent.columns;
        } else if (active >= 0 && active <= parent.columns) {
        } else if (active == 'append') {
            active = parent.columns;
        } else {
            return false;
        }
        if (!number) {
            number = 1;
        }
        for (i = active; i < parent.columns; i++) {
            for (j = 0; j < parent.rows; j++) {
                parent.result[j][i].column += number;
            }
        }
        for (i = 0; i < parent.rows; i++) {
            for (j = active; j < active + number; j++) {
                parent.createUnit(i, j);
            }
        }
        parent.columns += number;
        return parent;
    };
    this.increaseHorizontal = function () {
        var iHorizontal = function (row, sRange, eRange) {
            var length = 0,
                number = 0,
                first = 0,
                last = 0,
                i, err;
            for (i = sRange.sCol; i <= sRange.eCol; i++) {
                if (parent.result[row][i].type == 'number') {
                    last = parent.result[row][i].result;
                    if (!number) {
                        first = last;
                    }
                    number++;
                }
                length++;
            }
            err = (last - first) / (number - 1) * number;
            err = err ? err : 0;
            for (i = sRange.eCol + 1; i <= eRange.eCol; i++) {
                switch (parent.result[row][i - length].type) {
                    case 'function':
                        ExcelTable.unit.setValue(parent.result[row][i], parent.result[row][i - length].value);
                        break;
                    case 'number':
                        ExcelTable.unit.setValue(parent.result[row][i], parent.result[row][i - length].value + err);
                        break;
                    default:
                        ExcelTable.unit.setValue(parent.result[row][i], parent.result[row][i - length].value);
                        break;
                }
            }
        };
        for (var j = parent.changeLines.eRange.sRow; j <= parent.changeLines.eRange.eRow; j++) {
            iHorizontal(j, parent.changeLines.sRange, parent.changeLines.eRange);
        }
    };
    this.increaseVertical = function () {
        var iVertical = function (col, sRange, eRange) {
            var length = 0,
                number = 0,
                first = 0,
                last = 0,
                i, err;
            for (i = sRange.sRow; i <= sRange.eRow; i++) {
                if (parent.result[i][col].type == 'number') {
                    last = parent.result[i][col].result;
                    if (!number) {
                        first = last;
                    }
                    number++;
                }
                length++;
            }
            err = (last - first) / (number - 1) * number;
            err = err ? err : 0;
            for (i = sRange.eRow + 1; i <= eRange.eRow; i++) {
                switch (parent.result[i - length][col].type) {
                    case 'function':
                        ExcelTable.unit.setValue(parent.result[i][col], parent.result[i - length][col].value);
                        break;
                    case 'number':
                        ExcelTable.unit.setValue(parent.result[i][col], parent.result[i - length][col].value + err);
                        break;
                    default:
                        ExcelTable.unit.setValue(parent.result[i][col], parent.result[i - length][col].value);
                        break;
                }
            }
        };
        for (var j = parent.changeLines.eRange.sCol; j <= parent.changeLines.eRange.eCol; j++) {
            iVertical(j, parent.changeLines.sRange, parent.changeLines.eRange);
        }
    };
    this.decreaseHorizontal = function () {
        var dHorizontal = function (row, sRange, eRange) {
            var length = 0,
                number = 0,
                first = 0,
                last = 0,
                i, err;
            for (i = sRange.sCol; i <= sRange.eCol; i++) {
                if (parent.result[row][i].type == 'number') {
                    last = parent.result[row][i].result;
                    if (!number) {
                        first = last;
                    }
                    number++;
                }
                length++;
            }
            err = (last - first) / (number - 1) * number;
            err = err ? err : 0;
            for (i = sRange.sCol - 1; i >= eRange.sCol; i--) {
                switch (parent.result[row][i + length].type) {
                    case 'function':
                        ExcelTable.unit.setValue(parent.result[row][i], parent.result[row][i + length].value);
                        break;
                    case 'number':
                        ExcelTable.unit.setValue(parent.result[row][i], parent.result[row][i + length].value - err);
                        break;
                    default:
                        ExcelTable.unit.setValue(parent.result[row][i], parent.result[row][i + length].value);
                        break;
                }
            }
        };
        for (var j = parent.changeLines.eRange.sRow; j <= parent.changeLines.eRange.eRow; j++) {
            dHorizontal(j, parent.changeLines.sRange, parent.changeLines.eRange);
        }
    };
    this.decreaseVertical = function () {
        var dVertical = function (col, sRange, eRange) {
            var length = 0,
                number = 0,
                first = 0,
                last = 0,
                i, err;
            for (i = sRange.sRow; i <= sRange.eRow; i++) {
                if (parent.result[i][col].type == 'number') {
                    last = parent.result[i][col].result;
                    if (!number) {
                        first = last;
                    }
                    number++;
                }
                length++;
            }
            err = (last - first) / (number - 1) * number;
            err = err ? err : 0;
            for (i = sRange.sRow - 1; i >= eRange.sRow; i--) {
                switch (parent.result[i + length][col].type) {
                    case 'function':
                        ExcelTable.unit.setValue(parent.result[i][col], parent.result[i + length][col].value);
                        break;
                    case 'number':
                        ExcelTable.unit.setValue(parent.result[i][col], parent.result[i + length][col].value - err);
                        break;
                    default:
                        ExcelTable.unit.setValue(parent.result[i][col], parent.result[i + length][col].value);
                        break;
                }
            }
        };
        for (var j = parent.changeLines.eRange.sCol; j <= parent.changeLines.eRange.eCol; j++) {
            dVertical(j, parent.changeLines.sRange, parent.changeLines.eRange);
        }
    };
};<|endoftext|>


<commit_before>/**
 Given a timestamp in the future, calculate the largest, closest unit to show.
 On the high end we stop at hours. e.g. 15 days is still counted in hours not days or weeks.
 On the low end we stop at minutes.
 This rounds duration to the nearest integer. e.g. 5.7 minutes => will return 6 as duration.
 @param {number} timeStamp A future time stamp in ms.
 @returns {object} containing the unit (min, hours) and how many. e.g. {unit: minutes, duration: 3}
 */
const getTimeUnitAndDuration = timeStamp => {
    const diff = timeStamp - Date.now();
    const oneHourInMs = 1000 * 60 * 60;
    const oneMinuteInMs = 1000 * 60;

    let unit = 'minute';
    let duration = diff / oneMinuteInMs;
    // We show minutes up to 2 hours, then switch to hours.
    if (diff >= 2 * oneHourInMs) {
        unit = 'hour';
        duration = diff / oneHourInMs;
    }
    // Round to nearest hour or minute, but always have at least 1
    // so we don't show something like "0 minutes". Hours isn't
    // affected by the math.max because we choose minutes up to 2 hours.
    duration = Math.max(1, Math.round(duration));
    return {
        unit: unit,
        duration: duration
    };
};

/**
* Given a future timestamp and a langauge, constructs a phrase to describe that time relative to now.
* e.g. in 2 days, in 3 minutes, en 2 horas.
* The largest time unit is days, the smallest is minutes.
* @param {number} futureTime a timestamp in ms to build a phrase for.
* @param {string} lang Langauge to build the phrase in.
* @returns {string} A phrase representing the relative time in the future. e.g. 3 days 5 hours.
*/
module.exports.formatRelativeTime = (futureTime, lang) => {
    const formatter = new Intl.RelativeTimeFormat([lang].concat(window.navigator.languages), {
        localeMatcher: 'best fit',
        numeric: 'always',
        style: 'long'
    });
    const timeInfo = getTimeUnitAndDuration(futureTime);
    return formatter.format(timeInfo.duration, timeInfo.unit);
};
<commit_msg>Add message at the top of file mentioning the version in scratchr2<commit_after>// IMPORTANT: any changes to the time algorithm also need to be made in the corresponding
// scratchr2 file 'lib/format-time.js'

/**
 Given a timestamp in the future, calculate the largest, closest unit to show.
 On the high end we stop at hours. e.g. 15 days is still counted in hours not days or weeks.
 On the low end we stop at minutes.
 This rounds duration to the nearest integer. e.g. 5.7 minutes => will return 6 as duration.
 @param {number} timeStamp A future time stamp in ms.
 @returns {object} containing the unit (min, hours) and how many. e.g. {unit: minutes, duration: 3}
 */
const getTimeUnitAndDuration = timeStamp => {
    const diff = timeStamp - Date.now();
    const oneHourInMs = 1000 * 60 * 60;
    const oneMinuteInMs = 1000 * 60;

    let unit = 'minute';
    let duration = diff / oneMinuteInMs;
    // We show minutes up to 2 hours, then switch to hours.
    if (diff >= 2 * oneHourInMs) {
        unit = 'hour';
        duration = diff / oneHourInMs;
    }
    // Round to nearest hour or minute, but always have at least 1
    // so we don't show something like "0 minutes". Hours isn't
    // affected by the math.max because we choose minutes up to 2 hours.
    duration = Math.max(1, Math.round(duration));
    return {
        unit: unit,
        duration: duration
    };
};

/**
* Given a future timestamp and a langauge, constructs a phrase to describe that time relative to now.
* e.g. in 2 days, in 3 minutes, en 2 horas.
* The largest time unit is days, the smallest is minutes.
* @param {number} futureTime a timestamp in ms to build a phrase for.
* @param {string} lang Langauge to build the phrase in.
* @returns {string} A phrase representing the relative time in the future. e.g. 3 days 5 hours.
*/
module.exports.formatRelativeTime = (futureTime, lang) => {
    const formatter = new Intl.RelativeTimeFormat([lang].concat(window.navigator.languages), {
        localeMatcher: 'best fit',
        numeric: 'always',
        style: 'long'
    });
    const timeInfo = getTimeUnitAndDuration(futureTime);
    return formatter.format(timeInfo.duration, timeInfo.unit);
};
<|endoftext|>