<commit_before>'use strict'

const t = require('../lib/translator')
const Logger = require('../lib/logger')
const languages = require('../lib/lang')
const mixpanel = require('../lib/mixpanel')
const db = require('../db/redis')
const _ = require('lodash')

const responseType = {
  getStarted: '!getstarted',
  change: '!change'
};

class MessageHandler {

  static handleMessage(bot, payload, reply) {

    const { sender, message, postback } = payload
    bot.setTyping(sender.id, true)
    bot.getProfile(sender.id, (err, profile) => {

      if (err) return Logger.log(err)

      db.getAsync(sender.id).then((context) => {
        if (postback && postback.payload === responseType.getStarted) {
          return MessageHandler.handleGetStarted(sender, profile, reply)
        }
        if (_.includes(message.text, responseType.change)) {
          return MessageHandler.handleChange(sender, reply)
        }
        if (context === null) {
          return MessageHandler.handleNoContext(sender, message, reply)
        }
        // we made it! translate the message
        MessageHandler.handleTranslation(context, sender, message, reply)
      })
    })
  }

  static handleGetStarted(sender, profile, reply) {
    reply({
      text: `Hola ${profile.first_name}, let's get started!\n\nI speak lots of different languages, so go ahead and tell me what to translate for you.\n\nFor example, type "english to spanish" or "greek to japanese"`
    }, () => {
      mixpanel.setPerson(sender, profile)
      mixpanel.track('I click to get started', sender)
    })
  }

  static handleChange(sender, reply) {
    db.delAsync(sender.id).then((err, resp) => {
      return reply({
        text: `Sure thing. What language you would like me to translate for you now?`
      }, () => {
        mixpanel.track('I change context', sender)
      })
    })
  }

  static handleNoContext(sender, message, reply) {
    const context = MessageHandler.getContext(message.text)
    if (!context.hasTwo) {
      const text = `Hmmm... I didn't quite catch that. \n\nType, for example: "english to spanish" or "korean to portugese"`
      if (context.hasOne) text = `I only caught ${_.capitalize(context.matches[0])} in there. Type, for example: "english to spanish" or "korean to portugese"`
      return reply({
        text: text
      }, () => {
        mixpanel.track('I incorrectly set context', sender, message)
      })
    }
    return MessageHandler.handleIncomingContext(context, sender, message, reply)
  }

  static handleIncomingContext(context, sender, message, reply) {
    // we have context, store it and reply
    const contextValue = `${context.matches[0].code}:${context.matches[1].code}`
    db.setAsync(sender.id, contextValue).then((err, resp) => {
      return reply({
        text: `${_.capitalize(context.matches[0].name)} to ${_.capitalize(context.matches[1].name)}. Got it! Now go ahead and tell me what to say.\n\nType "${responseType.change}" at anytime to switch languages`
      }, () => {
        mixpanel.track('I set context', sender, message)
      })
    })
  }

  static handleTranslation(context, sender, message, reply) {
    t.translate(message.text, context).
      then((result) => {
        reply({ text: result }, (err) => {
          if (err) Logger.log(err)
          mixpanel.track('I send a message to be translated', sender, message)
        })
      }).
      catch((err) => {
        reply({ text: `Oh no, something has gone wrong. Please try that again` })
      })
  }

  static getContext(message) {
    let matches = []
    const words = message.split(' ')
    words.forEach((word) => {
      languages.filter(item => item.name === _.lowerCase(word)).map((lang) => {
        if (matches.length === 2) return
        matches.push(lang)
      })
    })
    return {
      hasTwo: matches.length === 2,
      hasOne: matches.length === 1,
      hasNone: matches.length === 0,
      matches: matches
    }
  }
}

module.exports = MessageHandler<commit_msg>const to let<commit_after>'use strict'

const t = require('../lib/translator')
const Logger = require('../lib/logger')
const languages = require('../lib/lang')
const mixpanel = require('../lib/mixpanel')
const db = require('../db/redis')
const _ = require('lodash')

const responseType = {
  getStarted: '!getstarted',
  change: '!change'
};

class MessageHandler {

  static handleMessage(bot, payload, reply) {

    const { sender, message, postback } = payload
    bot.setTyping(sender.id, true)
    bot.getProfile(sender.id, (err, profile) => {

      if (err) return Logger.log(err)

      db.getAsync(sender.id).then((context) => {
        if (postback && postback.payload === responseType.getStarted) {
          return MessageHandler.handleGetStarted(sender, profile, reply)
        }
        if (_.includes(message.text, responseType.change)) {
          return MessageHandler.handleChange(sender, reply)
        }
        if (context === null) {
          return MessageHandler.handleNoContext(sender, message, reply)
        }
        // we made it! translate the message
        MessageHandler.handleTranslation(context, sender, message, reply)
      })
    })
  }

  static handleGetStarted(sender, profile, reply) {
    reply({
      text: `Hola ${profile.first_name}, let's get started!\n\nI speak lots of different languages, so go ahead and tell me what to translate for you.\n\nFor example, type "english to spanish" or "greek to japanese"`
    }, () => {
      mixpanel.setPerson(sender, profile)
      mixpanel.track('I click to get started', sender)
    })
  }

  static handleChange(sender, reply) {
    db.delAsync(sender.id).then((err, resp) => {
      return reply({
        text: `Sure thing. What language you would like me to translate for you now?`
      }, () => {
        mixpanel.track('I change context', sender)
      })
    })
  }

  static handleNoContext(sender, message, reply) {
    const context = MessageHandler.getContext(message.text)
    if (!context.hasTwo) {
      let text = `Hmmm... I didn't quite catch that. \n\nType, for example: "english to spanish" or "korean to portugese"`
      if (context.hasOne) text = `I only caught ${_.capitalize(context.matches[0])} in there. Type, for example: "english to spanish" or "korean to portugese"`
      return reply({
        text: text
      }, () => {
        mixpanel.track('I incorrectly set context', sender, message)
      })
    }
    return MessageHandler.handleIncomingContext(context, sender, message, reply)
  }

  static handleIncomingContext(context, sender, message, reply) {
    // we have context, store it and reply
    const contextValue = `${context.matches[0].code}:${context.matches[1].code}`
    db.setAsync(sender.id, contextValue).then((err, resp) => {
      return reply({
        text: `${_.capitalize(context.matches[0].name)} to ${_.capitalize(context.matches[1].name)}. Got it! Now go ahead and tell me what to say.\n\nType "${responseType.change}" at anytime to switch languages`
      }, () => {
        mixpanel.track('I set context', sender, message)
      })
    })
  }

  static handleTranslation(context, sender, message, reply) {
    t.translate(message.text, context).
      then((result) => {
        reply({ text: result }, (err) => {
          if (err) Logger.log(err)
          mixpanel.track('I send a message to be translated', sender, message)
        })
      }).
      catch((err) => {
        reply({ text: `Oh no, something has gone wrong. Please try that again` })
      })
  }

  static getContext(message) {
    let matches = []
    const words = message.split(' ')
    words.forEach((word) => {
      languages.filter(item => item.name === _.lowerCase(word)).map((lang) => {
        if (matches.length === 2) return
        matches.push(lang)
      })
    })
    return {
      hasTwo: matches.length === 2,
      hasOne: matches.length === 1,
      hasNone: matches.length === 0,
      matches: matches
    }
  }
}

module.exports = MessageHandler<|endoftext|>


<commit_before>import Component from '@ember/component';
const resourceTypeGeneralList = [
  'Audiovisual',
  'Collection',
  'DataPaper',
  'Dataset',
  'Event',
  'Image',
  'InteractiveResource',
  'Model',
  'PhysicalObject',
  'Service',
  'Software',
  'Sound',
  'Text',
  'Workflow',
  'Other'
]

export default Component.extend({
  resourceTypeGeneralList,
  resourceTypesGeneral: resourceTypeGeneralList,

  searchResourceTypeGeneral(query) {
    resourceTypesGeneral = resourceTypeGeneralList.filter(function(resourceTypeGeneral) {
      return resourceTypeGeneral.startsWith(query.toLowerCase());
    })
  },
  selectResourceTypeGeneral(resourceTypeGeneral) {
    this.get('model').set('types', { 'resourceTypeGeneral': resourceTypeGeneral });
    this.set('resourceTypesGeneral', resourceTypeGeneralList);
  },

  actions: {
    selectResourceTypeGeneral(resourceTypeGeneral) {
      this.selectResourceTypeGeneral(resourceTypeGeneral);
    },
    searchResourceTypeGeneral(query) {
      this.searchResourceTypeGeneral(query);
    }
  }
});<commit_msg>properly define variable. #117<commit_after>import Component from '@ember/component';
const resourceTypeGeneralList = [
  'Audiovisual',
  'Collection',
  'DataPaper',
  'Dataset',
  'Event',
  'Image',
  'InteractiveResource',
  'Model',
  'PhysicalObject',
  'Service',
  'Software',
  'Sound',
  'Text',
  'Workflow',
  'Other'
]

export default Component.extend({
  resourceTypeGeneralList,
  resourceTypesGeneral: resourceTypeGeneralList,

  searchResourceTypeGeneral(query) {
    this.resourceTypesGeneral = resourceTypeGeneralList.filter(function(resourceTypeGeneral) {
      return resourceTypeGeneral.startsWith(query.toLowerCase());
    })
  },
  selectResourceTypeGeneral(resourceTypeGeneral) {
    this.get('model').set('types', { 'resourceTypeGeneral': resourceTypeGeneral });
    this.set('resourceTypesGeneral', resourceTypeGeneralList);
  },

  actions: {
    selectResourceTypeGeneral(resourceTypeGeneral) {
      this.selectResourceTypeGeneral(resourceTypeGeneral);
    },
    searchResourceTypeGeneral(query) {
      this.searchResourceTypeGeneral(query);
    }
  }
});<|endoftext|>


<commit_before>/**
 * @author Gilles Coomans <gilles.coomans@gmail.com>
 * Unit test class and statics.
 * Manage natively promise pattern.
 */
if (typeof define !== 'function') {
	var define = require('amdefine')(module);
}

define(["require", "../deep"], function(require, deep) {

	function Unit(unit) {
		if (unit)
			deep.aup(unit, this);
		//console.log("Unit created : ", this);
		this.tests = this.tests || {};
	}

	Unit.prototype = {
		_deep_unit_: true,
		title: "Generic tests",
		stopOnError: false,
		options: null,
		setup: function(options) {},
		clean: function(options) {
			delete this.context;
		},
		run: function(tests, options) {
			options = options || {};
			tests = tests || [];
			if (!tests.forEach)
				tests = [tests];

			var toTest = this.tests;
			if (toTest._deep_ocm_)
				toTest = toTest();
			//console.log("unit context : ", context);
			var functions = deep.query(toTest, "./[" + tests.join(",") + "]", {
				fullOutput: true
			});
			var numberOfTests = functions.length;
			var stopOnError = this.stopOnError;
			if (typeof options.stopOnError !== 'undefined')
				stopOnError = options.stopOnError;
			if (options.verbose !== false) {
				if (console.group)
					console.group("unit : " + this.title);

				console.log("\n\n**********************************************************");
				console.log("*****  lib/unit : will run : ", this.title, " *****");
				console.log("\tStop on error ? ", stopOnError);
				console.log("\tNumber of tests : ", functions.length, "\n");
			}
			//console.log("\tContext : ",context,"\n\n" );
			var errors = [];
			var self = this,
				totalTime = 0;

			if (functions.length === 0) {
				if (options.verbose !== false) {
					console.log("**********************************************************");
					console.log("************* Nothing to do : aborting unit **************");
					console.log("**********************************************************");
					if (console.groupEnd)
						console.groupEnd();
				}
				return {
					title: self.title,
					numberOfTests: 0,
					success: 0,
					failure: 0,
					ommited: 0,
					errors: errors,
					valid: true,
					time: 0
				};
			}
			var results = [];
			var d = deep.contextualise({ protocols:{}, session:null }).done(function(){ return self.setup(options); });
			var closure = {};
			var applyTest = function(fn) {
				if (fn._deep_ocm_)
					fn = fn();
				if (options.verbose !== false)
					console.log("\n- unit test runned : ", fn.key);
				closure.fn = fn;
				var time = new Date().getTime();
				return deep.when(fn.value.call(self.context))
					.always(function(s, e) {
						time = new Date().getTime() - time;
						totalTime += time;
						if (options.verbose !== false)
							if (e)
								console.error("****** test failed ! ******* : ", fn.key, " error : ", e, e.report);
							else
								console.log("\tok !         (" + time + " ms)");
					});
			};
			var done = function(r) {
				results.push(r);
				if (functions.length > 0)
					d.when(applyTest(functions.shift())).done(done).fail(fail);
			};
			var fail = function(error) {
				results.push(error);
				errors.push({
					unit: self.title,
					test: closure.fn.key,
					error: error
				});
				//deep.utils.dumpError(error);
				if (!stopOnError && functions.length > 0)
					d.when(applyTest(functions.shift())).done(done).fail(fail);
				return true;
			};
			d.always(function() {
				if (options.verbose !== false)
					console.log("\tsetup done.");
			})
			.done(function(context) {
				self.context = context || { debug:true };
				this.when(applyTest(functions.shift()))
					.done(done)
					.fail(fail);
			})
			.always(function(s, e) {
				//console.log("_______________________________________________ unit test result : ",s,e);
				if (options.verbose !== false) {
					console.log("\n*************", self.title, " : time ****************");

					if (e || results.length < numberOfTests || errors.length > 0)
						console.warn("*************", self.title, " : FAILED **************");
					else
						console.log("*************", self.title, " : PASSED **************");

					if (errors.length > 0) {
						console.log("\n\tErrors : ");
						console.log("\t", e || errors);
					}

					console.log("\n\tNumber of tests : ", numberOfTests);
					console.log("\tsuccess : ", results.length - errors.length, "/", numberOfTests);
					console.log("\tfailure : ", errors.length, "/", numberOfTests);
					console.log("\tommited : ", numberOfTests - results.length, "/", numberOfTests);
					console.log("\ttime : ", totalTime);
				}
				return self.clean();
			})
			.always(function(s, e) {
				if (options.verbose !== false) {
					if (e)
						console.log("error while cleanin test : ", self.title, " : ", e);
					console.log("\n**************", self.title, " cleaned **************");
					console.log("***********************************************************");
					if (console.groupEnd)
						console.groupEnd();
				}
				return {
					title: self.title,
					numberOfTests: numberOfTests,
					success: results.length - errors.length,
					failure: errors.length,
					ommited: numberOfTests - results.length,
					//results:results,
					errors: errors,
					valid: ((errors.length === 0) && (results.length == numberOfTests)),
					time: totalTime
				};
			});
			return d;
		}
	};

	function reportToString(){
		var report = this, e = this.finalError;
		var output = "";
		output += "\n\n\n___________________________________________________________________";
		output += "\n*******************************************************************";
		output += "\n************************** Bunch time : ***************************";

		if (e)
			output += "\nerror while executings tests bunch : ";
			output +=  e;
		output += "\n*******************************************************************";
		output += "\n********** tests bunch arrived to end : final report : ************";
		//console.log("\n",report,"\n");
		if(report.errors)
		{
			output += "\n\tErrors: ";
			report.errors.forEach(function(e) {
				output += e.unit + ":" + e.test + " " + String(e.error);
				if (e.error && e.error.report)
					output += "\nreport : " + report.toString();

			});
		}
		else
			output += "\n\tNo errors.\n";
		output += "\n\tNumber of units : " + report.numberOfUnits;
		output += "\n\tNumber of tests : " + report.numberOfTests;
		output += "\n\tsuccess : " + report.success + "/" + report.numberOfTests;
		output += "\n\tfailure : " + report.failure + "/" + report.numberOfTests;
		output += "\n\tommited : " + report.ommited + "/" + report.numberOfTests;
		output += "\n\tommiteds : " + report.ommiteds;

		output += "\n\ttime : " + report.time;
		output += "\n\ttotalTime : " + report.totalTime;
		output += "\n\tcounters : " + JSON.stringify(deep.counter, null, ' ');
		//output += JSON.stringify(report, null, ' '));
		output += "\n*******************************************************************";
		output += "\n*******************************************************************";
		output += "\n___________________________________________________________________\n\n";
		return output;
	}

	Unit.run = deep.test = function(units, options) {
		if (!options && units === false)
			options = units;
		if (options === false)
			options = {
				verbose: false
			};
		else
			options = options || {};
		//if(options.verbose !== false)
		//{
		console.log("\n*******************************************************************");
		console.log("*************************** Units Bunch ****************************");
		//}
		units = units || deep.coreUnits;
		var alls = [];
		if (!units.forEach)
			units = [units];
		units.forEach(function(unit) {
			if (typeof unit === 'string')
				alls.push(deep.get(unit));
			else
				alls.push(unit);
		});
		var report = {
			reports: [],
			errors: [],
			numberOfUnits: units.length,
			numberOfTests: 0,
			success: 0,
			failure: 0,
			ommited: 0,
			ommiteds: [],
			time: 0
		};
		deep.counter = {
			delayCount: 0
		};
		if (alls.length === 0)
			return deep.when(report);
		return deep.all(alls)
			.done(function(units) {
				deep.Promise.context = this._context = { $:deep.Promise.context.$, debug:true };
				//console.log("units loaded : ", units);
				if (options.profile)
					console.profile("bunch");
				var results = [];
				var errors = [];
				var doTest = function(unit) {
					unit = new deep.Unit(unit);
					if (options.verbose !== false)
						console.log("\n\n\n*************** Executing unit : ", unit.title);
					return deep.when(unit.run("*", options));
				};
				var startTime = new Date().getTime();

				//if(options.verbose !== false)
				if (console.time)
					console.time("bunch");
				var d = deep.when(doTest(units.shift()));
				var always = function(s, e) {
					if (e)
						report.errors.push(e);
					report.reports.push(s);
					report.success += s.success;
					report.failure += s.failure;
					report.ommited += s.ommited;
					if(s.ommited)
						report.ommiteds.push(s.title);
					report.numberOfTests += s.numberOfTests;
					report.errors = report.errors.concat(s.errors);
					report.time += s.time;
					results.push(s);
					if (units.length > 0)
						d.when(doTest(units.shift())).always(always);
					return true;
				};
				return d.always(always)
					.always(function(s, e) {
						if (options.profile)
							console.profileEnd("bunch");
						report.totalTime = new Date().getTime() - startTime;
						report.counters = deep.counter;
						//if(options.verbose !== false)
						//{
						console.log("\n\n\n___________________________________________________________________");
						console.log("\n*******************************************************************");
						console.log("************************** Bunch time : ***************************");
						if (console.time)
							console.timeEnd("bunch");
						if (e)
							console.log("error while executings tests bunch : ", e);
						console.log("*******************************************************************");
						console.log("********** tests bunch arrived to end : final report : ************");
						//console.log("\n",report,"\n");
						if(report.errors)
						{
							console.log("\n\tErrors: ");
							report.errors.forEach(function(e) {
								console.log(e.unit + ":" + e.test, String(e.error));
								if (e.error && e.error.report)
									console.log("report : ", report.toString());

							});
						}
						else
							console.log("\n\tNo errors.\n")
						console.log("\tNumber of units : ", report.numberOfUnits);
						console.log("\tNumber of tests : ", report.numberOfTests);
						console.log("\tsuccess : ", report.success, "/", report.numberOfTests);
						console.log("\tfailure : ", report.failure, "/", report.numberOfTests);
						console.log("\tommited : ", report.ommited, "/", report.numberOfTests);
						console.log("\tommiteds : ", report.ommiteds);

						console.log("\ttime : ", report.time);
						console.log("\ttotalTime : ", report.totalTime);
						console.log("\tcounters : ", JSON.stringify(deep.counter, null, ' '));
						//console.log(JSON.stringify(report, null, ' '));
						console.log("\n*******************************************************************");
						console.log("*******************************************************************");
						console.log("___________________________________________________________________\n\n");
						//}
						report.toString = reportToString;
						report.finalError = e;
						return report;
					});
			})
			.fail(function(error) {
				console.error("deep : Unit bunch failed to load : ", error);
			});
	};

	deep.Unit = Unit;

	return Unit;
});<commit_msg>update unit output<commit_after>/**
 * @author Gilles Coomans <gilles.coomans@gmail.com>
 * Unit test class and statics.
 * Manage natively promise pattern.
 */
if (typeof define !== 'function') {
	var define = require('amdefine')(module);
}

define(["require", "../deep"], function(require, deep) {

	function Unit(unit) {
		if (unit)
			deep.aup(unit, this);
		//console.log("Unit created : ", this);
		this.tests = this.tests || {};
	}

	Unit.prototype = {
		_deep_unit_: true,
		title: "Generic tests",
		stopOnError: false,
		options: null,
		setup: function(options) {},
		clean: function(options) {
			delete this.context;
		},
		run: function(tests, options) {
			options = options || {};
			tests = tests || [];
			if (!tests.forEach)
				tests = [tests];

			var toTest = this.tests;
			if (toTest._deep_ocm_)
				toTest = toTest();
			//console.log("unit context : ", context);
			var functions = deep.query(toTest, "./[" + tests.join(",") + "]", {
				fullOutput: true
			});
			var numberOfTests = functions.length;
			var stopOnError = this.stopOnError;
			if (typeof options.stopOnError !== 'undefined')
				stopOnError = options.stopOnError;
			if (options.verbose !== false) {
				if (console.group)
					console.group("unit : " + this.title);

				console.log("\n\n**********************************************************");
				console.log("*****  lib/unit : will run : ", this.title, " *****");
				console.log("\tStop on error ? ", stopOnError);
				console.log("\tNumber of tests : ", functions.length, "\n");
			}
			//console.log("\tContext : ",context,"\n\n" );
			var errors = [];
			var self = this,
				totalTime = 0;

			if (functions.length === 0) {
				if (options.verbose !== false) {
					console.log("**********************************************************");
					console.log("************* Nothing to do : aborting unit **************");
					console.log("**********************************************************");
					if (console.groupEnd)
						console.groupEnd();
				}
				return {
					title: self.title,
					numberOfTests: 0,
					success: 0,
					failure: 0,
					ommited: 0,
					errors: errors,
					valid: true,
					time: 0
				};
			}
			var results = [];
			var d = deep.contextualise({ protocols:{}, session:null, rethrow:false, debug:true }).done(function(){ return self.setup(options); });
			var closure = {};
			var applyTest = function(fn) {
				if (fn._deep_ocm_)
					fn = fn();
				if (options.verbose !== false)
					console.log("\n- unit test runned : ", fn.key);
				closure.fn = fn;
				var time = new Date().getTime();
				return deep.when(fn.value.call(self.context))
					.always(function(s, e) {
						time = new Date().getTime() - time;
						totalTime += time;
						if (options.verbose !== false)
							if (e)
								console.error("****** test failed ! ******* : ", fn.key, " error : ", e, e.report);
							else
								console.log("\tok !         (" + time + " ms)");
					});
			};
			var done = function(r) {
				results.push(r);
				if (functions.length > 0)
					d.when(applyTest(functions.shift())).done(done).fail(fail);
			};
			var fail = function(error) {
				results.push(error);
				errors.push({
					unit: self.title,
					test: closure.fn.key,
					error: error
				});
				//deep.utils.dumpError(error);
				if (!stopOnError && functions.length > 0)
					d.when(applyTest(functions.shift())).done(done).fail(fail);
				return true;
			};
			d.always(function() {
				if (options.verbose !== false)
					console.log("\tsetup done.");
			})
			.done(function(context) {
				self.context = context || { debug:true };
				this.when(applyTest(functions.shift()))
					.done(done)
					.fail(fail);
			})
			.always(function(s, e) {
				//console.log("_______________________________________________ unit test result : ",s,e);
				if (options.verbose !== false) {
					console.log("\n*************", self.title, " : time ****************");

					if (e || results.length < numberOfTests || errors.length > 0)
						console.warn("*************", self.title, " : FAILED **************");
					else
						console.log("*************", self.title, " : PASSED **************");

					if (errors.length > 0) {
						console.log("\n\tErrors : ");
						console.log("\t", e || errors);
					}

					console.log("\n\tNumber of tests : ", numberOfTests);
					console.log("\tsuccess : ", results.length - errors.length, "/", numberOfTests);
					console.log("\tfailure : ", errors.length, "/", numberOfTests);
					console.log("\tommited : ", numberOfTests - results.length, "/", numberOfTests);
					console.log("\ttime : ", totalTime);
				}
				return self.clean();
			})
			.always(function(s, e) {
				if (options.verbose !== false) {
					if (e)
						console.log("error while cleanin test : ", self.title, " : ", e);
					console.log("\n**************", self.title, " cleaned **************");
					console.log("***********************************************************");
					if (console.groupEnd)
						console.groupEnd();
				}
				return {
					title: self.title,
					numberOfTests: numberOfTests,
					success: results.length - errors.length,
					failure: errors.length,
					ommited: numberOfTests - results.length,
					//results:results,
					errors: errors,
					valid: ((errors.length === 0) && (results.length == numberOfTests)),
					time: totalTime
				};
			});
			return d;
		}
	};

	function reportToString(){
		var report = this, e = this.finalError;
		var output = "";
		output += "\n\n\n___________________________________________________________________";
		output += "\n*******************************************************************";
		output += "\n************************** Bunch time : ***************************";

		if (e)
			output += "\nerror while executings tests bunch : ";
			output +=  e;
		output += "\n*******************************************************************";
		output += "\n********** tests bunch arrived to end : final report : ************";
		//console.log("\n",report,"\n");
		if(report.errors)
		{
			output += "\n\tErrors: ";
			report.errors.forEach(function(e) {
				output += e.unit + ":" + e.test + " " + String(e.error);
				if (e.error && e.error.report)
					output += "\nreport : " + report.toString();

			});
		}
		else
			output += "\n\tNo errors.\n";
		output += "\n\tNumber of units : " + report.numberOfUnits;
		output += "\n\tNumber of tests : " + report.numberOfTests;
		output += "\n\tsuccess : " + report.success + "/" + report.numberOfTests;
		output += "\n\tfailure : " + report.failure + "/" + report.numberOfTests;
		output += "\n\tommited : " + report.ommited + "/" + report.numberOfTests;
		output += "\n\tommiteds : " + report.ommiteds;

		output += "\n\ttime : " + report.time;
		output += "\n\ttotalTime : " + report.totalTime;
		output += "\n\tcounters : " + JSON.stringify(deep.counter, null, ' ');
		//output += JSON.stringify(report, null, ' '));
		output += "\n*******************************************************************";
		output += "\n*******************************************************************";
		output += "\n___________________________________________________________________\n\n";
		return output;
	}

	Unit.run = deep.test = function(units, options) {
		if (!options && units === false)
			options = units;
		if (options === false)
			options = {
				verbose: false
			};
		else
			options = options || {};
		//if(options.verbose !== false)
		//{
		console.log("\n*******************************************************************");
		console.log("*************************** Units Bunch ****************************");
		//}
		units = units || deep.coreUnits;
		var alls = [];
		if (!units.forEach)
			units = [units];
		units.forEach(function(unit) {
			if (typeof unit === 'string')
				alls.push(deep.get(unit));
			else
				alls.push(unit);
		});
		var report = {
			reports: [],
			errors: [],
			numberOfUnits: units.length,
			numberOfTests: 0,
			success: 0,
			failure: 0,
			ommited: 0,
			ommiteds: [],
			time: 0
		};
		deep.counter = {
			delayCount: 0
		};
		if (alls.length === 0)
			return deep.when(report);
		return deep.all(alls)
			.done(function(units) {
				deep.Promise.context = this._context = { $:deep.Promise.context.$, debug:true };
				//console.log("units loaded : ", units);
				if (options.profile)
					console.profile("bunch");
				var results = [];
				var errors = [];
				var doTest = function(unit) {
					unit = new deep.Unit(unit);
					if (options.verbose !== false)
						console.log("\n\n\n*************** Executing unit : ", unit.title);
					return deep.when(unit.run("*", options));
				};
				var startTime = new Date().getTime();

				//if(options.verbose !== false)
				if (console.time)
					console.time("bunch");
				var d = deep.when(doTest(units.shift()));
				var always = function(s, e) {
					if (e)
						report.errors.push(e);
					report.reports.push(s);
					report.success += s.success;
					report.failure += s.failure;
					report.ommited += s.ommited;
					if(s.ommited)
						report.ommiteds.push(s.title);
					report.numberOfTests += s.numberOfTests;
					report.errors = report.errors.concat(s.errors);
					report.time += s.time;
					results.push(s);
					if (units.length > 0)
						d.when(doTest(units.shift())).always(always);
					return true;
				};
				return d.always(always)
					.always(function(s, e) {
						if (options.profile)
							console.profileEnd("bunch");
						report.totalTime = new Date().getTime() - startTime;
						report.counters = deep.counter;
						//if(options.verbose !== false)
						//{
						console.log("\n\n\n___________________________________________________________________");
						console.log("\n*******************************************************************");
						console.log("************************** Bunch time : ***************************");
						if (console.time)
							console.timeEnd("bunch");
						if (e)
							console.log("error while executings tests bunch : ", e);
						console.log("*******************************************************************");
						console.log("********** tests bunch arrived to end : final report : ************");
						//console.log("\n",report,"\n");
						if(report.errors)
						{
							console.log("\n\tErrors: ");
							report.errors.forEach(function(e) {
								console.log(e.unit + ":" + e.test, String(e.error));
								if (e.error && e.error.report)
									console.log("report : ", report.toString());

							});
						}
						else
							console.log("\n\tNo errors.\n")
						console.log("\tNumber of units : ", report.numberOfUnits);
						console.log("\tNumber of tests : ", report.numberOfTests);
						console.log("\tsuccess : ", report.success, "/", report.numberOfTests);
						console.log("\tfailure : ", report.failure, "/", report.numberOfTests);
						console.log("\tommited : ", report.ommited, "/", report.numberOfTests);
						console.log("\tommiteds : ", report.ommiteds);

						console.log("\ttime : ", report.time);
						console.log("\ttotalTime : ", report.totalTime);
						console.log("\tcounters : ", JSON.stringify(deep.counter, null, ' '));
						//console.log(JSON.stringify(report, null, ' '));
						console.log("\n*******************************************************************");
						console.log("*******************************************************************");
						console.log("___________________________________________________________________\n\n");
						//}
						report.toString = reportToString;
						report.finalError = e;
						return report;
					});
			})
			.fail(function(error) {
				console.error("deep : Unit bunch failed to load : ", error);
			});
	};

	deep.Unit = Unit;

	return Unit;
});<|endoftext|>


<commit_before>const shell = require('shelljs')

const cmdArguments = process.argv.slice(2)
const semverType = cmdArguments[0]

if (!semverType || !semverType.match(/^(major|minor|patch)$/)) {
   console.log(`Usage: major|minor|patch`)
   process.exit(1)
}

execCommand(`npm version ${semverType}`)
execCommand(`npm run build`)
execCommand(`npm run test:rules`)
execCommand(`git push`)
execCommand(`git push --tags`)
execCommand(`npm publish`)

function execCommand(command) {
   const result = shell.exec(command)
   if (!!result.code) {
      console.log(result.stdout)
      process.exit(1)
   }
}
<commit_msg>Fix publish script<commit_after>const shell = require('shelljs')

const cmdArguments = process.argv.slice(2)
const semverType = cmdArguments[0]

if (!semverType || !semverType.match(/^(major|minor|patch)$/)) {
   console.log(`Usage: major|minor|patch`)
   process.exit(1)
}

execCommand(`npm version ${semverType}`)
execCommand(`npm run build`)
execCommand(`npm run test`)
execCommand(`git push`)
execCommand(`git push --tags`)
execCommand(`npm publish`)

function execCommand(command) {
   const result = shell.exec(command)
   if (!!result.code) {
      console.log(result.stdout)
      process.exit(1)
   }
}
<|endoftext|>


<commit_before>const Home = ({ children }) => {
  return React.createElement(
    'section',
    null,
    children
  );
};
<commit_msg>add child components to home<commit_after>const Home = (props) => {
  return React.createElement(
    'section',
    null,
    [
      React.createElement(Search, { onSearchUpdate: props.onSearchUpdate }),
      React.createElement(
        UserListContainer,
        {
          query: props.query,
          onUserListUpdate: props.onUserListUpdate,
          onCurrentUserUpdate: props.onCurrentUserUpdate
        }
      )
    ]
  );
};
<|endoftext|>


<commit_before>var VirtualDOMNode = require("./virtual-dom-node")
var VirtualTextNode = require("./virtual-text-node")

var isVDOMNode = require("./lib/is-virtual-dom")
var isVTextNode = require("./lib/is-virtual-text")
var isWidget = require("./lib/is-widget")

module.exports = diff

function diff(a, b) {
    var patch = { a: a }
    // index a so we can implicitly reference
    indexTree(a)
    walk(a, b, patch)
    return patch
}

// Index the tree in-order
function indexTree(tree, index, parent, c) {

    if (tree.index === 0 && !parent) {
        // The tree has already been indexed once
        return
    } else if (tree.index >= 0 && parent) {
        // This node has been indexed somewhere else in the tree, so clone
        if (isVDOMNode(tree)) {
            tree = parent[c] = new VirtualDOMNode(
                tree.tagName,
                tree.properties,
                tree.children)
        } else if (isVTextNode(tree)) {
            tree = parent[c] = new VirtualTextNode(tree.text)
        } else if (isWidget(tree)) {
            tree = tree.init(tree)  // calling init with self should clone
        }
    }

    index = index || 0
    tree.index = index

    if (tree.children) {
        for (var i = 0; i < tree.children.length; i++) {
            index = indexTree(tree.children[i], index + 1, tree, i)
        }
    }

    return tree.index
}

var remove = [{ type: "remove" }]

function walk(a, b, patch) {
    var apply

    if (a === b) {
        return b
    }

    if (updateWidget(a, b)) {
        apply = [{ "type": "update", widget: a, patch: b }]
        b = a
    } else if (isVDOMNode(a) && isVDOMNode(b) && a.tagName === b.tagName) {
        var propsPatch = diffProps(a.properties, b.properties)
        if (diffProps) {
            apply = [{
                type: "update",
                patch: propsPatch
            }]
        }

        var aChildren = a.children
        var bChildren = b.children
        var aLen = aChildren.length
        var bLen = bChildren.length
        var len = aLen < bLen ? aLen : bLen

        for (var i = 0; i < len; i++) {
            var rightNode = bChildren[i]
            var newRight = walk(aChildren[i], rightNode, patch)

            if (rightNode !== newRight) {
                b[i] = newRight
            }
        }

        // Excess nodes in a need to be removed
        for (; i < aLen; i++) {
            var excess = aChildren[i]
            if (isWidget(excess)) {
                patch[excess.index] = [{
                    type: "remove",
                    widget: excess
                }]
            } else {
                patch[aChildren[i].index] = remove
            }
        }

        // Excess nodes in b need to be added
        for (; i < bLen; i++) {
            apply = apply || []
            var addition = bChildren[i]
            if (isWidget(addition)) {
                apply.push({
                    type: "insert",
                    widget: addition
                })
            } else {
                apply.push({
                    type: "insert",
                    b: addition
                })
            }
        }
    } else if (isVTextNode(a) && isVTextNode(b) && a.text !== b.text) {
        apply = [{ type: "update", patch: b.text }]
    } else if (a !== b) {
        if (isWidget(b)) {
            apply = [{ type: "replace", widget: b }]
        } else {
            apply = [{ type: "replace", b: b }]
        }
    }

    if (apply) {
        patch[a.index] = apply
    }

    return b
}

var nullProps = {}

function diffProps(a, b) {
    var diff

    for (var aKey in a) {
        if (aKey === "style") {
            var styleDiff = diffProps(a.style, b.style || nullProps)
            if (styleDiff) {
                diff = diff || {}
                diff.style = styleDiff
            }
        } else {
            var aValue = a[aKey]
            var bValue = b[aKey]

            if (typeof aValue === "function" || aValue !== bValue) {
                diff = diff || {}
                diff[aKey] = bValue
            }
        }
    }

    for (var bKey in b) {
        if (!(bKey in a)) {
            diff = diff || {}
            diff[bKey] = b[bKey]
        }
    }

    return diff
}

function updateWidget(a, b) {
    if (isWidget(a) && isWidget(b)) {
        if ("type" in a && "type" in b) {
            return a.type === b.type
        } else {
            return a.init === b.init
        }
    }

    return false
}
<commit_msg>fix typo propsPatch<commit_after>var VirtualDOMNode = require("./virtual-dom-node")
var VirtualTextNode = require("./virtual-text-node")

var isVDOMNode = require("./lib/is-virtual-dom")
var isVTextNode = require("./lib/is-virtual-text")
var isWidget = require("./lib/is-widget")

module.exports = diff

function diff(a, b) {
    var patch = { a: a }
    // index a so we can implicitly reference
    indexTree(a)
    walk(a, b, patch)
    return patch
}

// Index the tree in-order
function indexTree(tree, index, parent, c) {

    if (tree.index === 0 && !parent) {
        // The tree has already been indexed once
        return
    } else if (tree.index >= 0 && parent) {
        // This node has been indexed somewhere else in the tree, so clone
        if (isVDOMNode(tree)) {
            tree = parent[c] = new VirtualDOMNode(
                tree.tagName,
                tree.properties,
                tree.children)
        } else if (isVTextNode(tree)) {
            tree = parent[c] = new VirtualTextNode(tree.text)
        } else if (isWidget(tree)) {
            tree = tree.init(tree)  // calling init with self should clone
        }
    }

    index = index || 0
    tree.index = index

    if (tree.children) {
        for (var i = 0; i < tree.children.length; i++) {
            index = indexTree(tree.children[i], index + 1, tree, i)
        }
    }

    return tree.index
}

var remove = [{ type: "remove" }]

function walk(a, b, patch) {
    var apply

    if (a === b) {
        return b
    }

    if (updateWidget(a, b)) {
        apply = [{ "type": "update", widget: a, patch: b }]
        b = a
    } else if (isVDOMNode(a) && isVDOMNode(b) && a.tagName === b.tagName) {
        var propsPatch = diffProps(a.properties, b.properties)
        if (propsPatch) {
            apply = [{
                type: "update",
                patch: propsPatch
            }]
        }

        var aChildren = a.children
        var bChildren = b.children
        var aLen = aChildren.length
        var bLen = bChildren.length
        var len = aLen < bLen ? aLen : bLen

        for (var i = 0; i < len; i++) {
            var rightNode = bChildren[i]
            var newRight = walk(aChildren[i], rightNode, patch)

            if (rightNode !== newRight) {
                b[i] = newRight
            }
        }

        // Excess nodes in a need to be removed
        for (; i < aLen; i++) {
            var excess = aChildren[i]
            if (isWidget(excess)) {
                patch[excess.index] = [{
                    type: "remove",
                    widget: excess
                }]
            } else {
                patch[aChildren[i].index] = remove
            }
        }

        // Excess nodes in b need to be added
        for (; i < bLen; i++) {
            apply = apply || []
            var addition = bChildren[i]
            if (isWidget(addition)) {
                apply.push({
                    type: "insert",
                    widget: addition
                })
            } else {
                apply.push({
                    type: "insert",
                    b: addition
                })
            }
        }
    } else if (isVTextNode(a) && isVTextNode(b) && a.text !== b.text) {
        apply = [{ type: "update", patch: b.text }]
    } else if (a !== b) {
        if (isWidget(b)) {
            apply = [{ type: "replace", widget: b }]
        } else {
            apply = [{ type: "replace", b: b }]
        }
    }

    if (apply) {
        patch[a.index] = apply
    }

    return b
}

var nullProps = {}

function diffProps(a, b) {
    var diff

    for (var aKey in a) {
        if (aKey === "style") {
            var styleDiff = diffProps(a.style, b.style || nullProps)
            if (styleDiff) {
                diff = diff || {}
                diff.style = styleDiff
            }
        } else {
            var aValue = a[aKey]
            var bValue = b[aKey]

            if (typeof aValue === "function" || aValue !== bValue) {
                diff = diff || {}
                diff[aKey] = bValue
            }
        }
    }

    for (var bKey in b) {
        if (!(bKey in a)) {
            diff = diff || {}
            diff[bKey] = b[bKey]
        }
    }

    return diff
}

function updateWidget(a, b) {
    if (isWidget(a) && isWidget(b)) {
        if ("type" in a && "type" in b) {
            return a.type === b.type
        } else {
            return a.init === b.init
        }
    }

    return false
}
<|endoftext|>


<commit_before>/* eslint-disable react/prefer-stateless-function, max-len */
import React, { Component, PropTypes } from 'react';
import find from 'lodash/find';
import groupBy from 'lodash/groupBy';
import startsWith from 'lodash/startsWith';
import size from 'lodash/size';
import { Link } from 'react-router';

import Icon from '../../widgets/Icon';

import './SidebarUsers.scss';

function UnreadCount({ unread }) {
  if (!unread) return null;
  return (

        {unread}

  );
}

export default class SidebarUsers extends Component {
  static propTypes = {
    contacts: PropTypes.array,
    messages: PropTypes.object,
  };

  constructor(props) {
    super(props);
    this.state = {
      search: '',
    };
  }

  search = (e) => {
    this.setState({ search: e.target.value });
  };

  render() {
    const unreadByChannel = groupBy(this.props.messages.unreadMessages, 'channelName');
    const unreadMessages = unreadByChannel.length > 0 && unreadByChannel.map((messages, channelName) => {
      let channelNamePrime = channelName;

      if (channelName.indexOf(',') !== -1 &&
          this.props.auth &&
          this.props.auth.user) {
        channelNamePrime = find(
          channelName.split(','),
          (c) => c !== `@${this.props.auth.user.name}`
        );
      }

      return (

          <Link
            to={`/messages/${channelNamePrime}`}
            activeClassName="active"
          >
            {channelNamePrime}{' '}
            <UnreadCount unread={messages.length} />
          </Link>

      );
    });

    const search = this.state.search;
    let users = this.props.contacts.filter((user) => {
      return startsWith(user, search);
    });
    users = users.slice(0, 20);
    users = users.filter((contact) => {
      const channelName = [
        `@${contact}`,
        `@${this.props.auth.user && this.props.auth.user.name}`,
      ].sort().toString();
      return !unreadByChannel[channelName] || !unreadByChannel[channelName].length;
    });
    users = users.map((follow, key) => (

        <Link
          to={`/@${follow}`}
          activeClassName="active"
        >
          @{follow}{' '}
          <UnreadCount unread={size(unreadByChannel[`@${follow}`])} />
        </Link>

    ));

    return (

              <Icon name="search" sm />
              <input
                type="text"
                className="form-control"
                placeholder="Search"
                value={search}
                onChange={this.search}
              />

          {unreadMessages.length ? (
            unreadMessages
          ) : null}
          {users.length ? (
            users
          ) : null}

    );
  }
}
<commit_msg>Improve syntax<commit_after>/* eslint-disable react/prefer-stateless-function, max-len */
import React, { Component, PropTypes } from 'react';
import find from 'lodash/find';
import groupBy from 'lodash/groupBy';
import startsWith from 'lodash/startsWith';
import size from 'lodash/size';
import { Link } from 'react-router';

import Icon from '../../widgets/Icon';

import './SidebarUsers.scss';

function UnreadCount({ unread }) {
  if (!unread) return null;
  return (

        {unread}

  );
}

export default class SidebarUsers extends Component {
  static propTypes = {
    contacts: PropTypes.array,
    messages: PropTypes.object,
  };

  constructor(props) {
    super(props);
    this.state = {
      search: '',
    };
  }

  search = (e) => {
    this.setState({ search: e.target.value });
  };

  render() {
    const unreadByChannel = groupBy(this.props.messages.unreadMessages, 'channelName');
    const unreadMessages = unreadByChannel.length > 0 && unreadByChannel.map((messages, channelName) => {
      let channelNamePrime = channelName;

      if (channelName.indexOf(',') !== -1 &&
          this.props.auth &&
          this.props.auth.user) {
        channelNamePrime = find(
          channelName.split(','),
          (c) => c !== `@${this.props.auth.user.name}`
        );
      }

      return (

          <Link
            to={`/messages/${channelNamePrime}`}
            activeClassName="active"
          >
            {channelNamePrime}{' '}
            <UnreadCount unread={messages.length} />
          </Link>

      );
    });

    const search = this.state.search;
    let users = this.props.contacts.filter((user) => {
      return startsWith(user, search);
    });
    users = users.slice(0, 20);
    users = users.filter((contact) => {
      const channelName = [
        `@${contact}`,
        `@${this.props.auth.user && this.props.auth.user.name}`,
      ].sort().toString();
      return !unreadByChannel[channelName] || !unreadByChannel[channelName].length;
    });
    users = users.map((follow, key) => (

        <Link
          to={`/@${follow}`}
          activeClassName="active"
        >
          @{follow}{' '}
          <UnreadCount unread={size(unreadByChannel[`@${follow}`])} />
        </Link>

    ));

    return (

              <Icon name="search" sm />
              <input
                type="text"
                className="form-control"
                placeholder="Search"
                value={search}
                onChange={this.search}
              />

          {unreadMessages.length
            ? (unreadMessages)
            : null
          }
          {users.length
            ? (users)
            : null
          }

    );
  }
}
<|endoftext|>


<commit_before>'use strict';
const _ = require('lodash');
const BaseApp = require('./app');

/**
 * User Class
 */
class User {

    /**
     * Constructor
     * @param {*} platform
     * @param {*=} config
     */
    constructor(platform, config) {
        this.platform = platform;
        this.config = {};
        this.config.intentMap = config.intentMap;
        this.config.userMetaData = config.userMetaData;
        this.config.userContext = config.userContext;
        // metaData && context are initialized at setData() | prevents saving an empty object
        this.metaData;
        this.context;
        this.data = {};
        this.isNew = false;
        this.isDeleted = false;
    }

    /**
     * Loads user data from database
     * @return {Promise<any>}
     */
    loadDataFromDb() {
        return new Promise((resolve, reject) => {
            this.platform.jovo.db().loadObject((error, data) => {
                if (error && (error.code === 'ERR_MAIN_KEY_NOT_FOUND' ||
                    error.code === 'ERR_DATA_KEY_NOT_FOUND')) {
                    this.setIsNewUser(true);
                    this.setData(this.createUserData());
                } else if (!data[this.platform.jovo.app.config.userDataCol]) {
                    this.setData(this.createUserData());
                } else {
                    this.setData(data[this.platform.jovo.app.config.userDataCol]);
                }
                resolve();
            });
        });
    }

    /**
     * Saves user data to database
     * @return {Promise<any>}
     */
    saveDataToDb() {
        return new Promise((resolve, reject) => {
            if (this.isDeleted) {
                resolve();
                return;
            }

            this.updateMetaData();
            this.updateContext();
            this.platform.jovo.db().saveFullObject(
                this.platform.jovo.app.config.userDataCol,
                this.getData(), function(error, data) {
                    if (error) {
                        reject(error);
                        return;
                    }
                    resolve();
                });
        });
    }

    /**
     * Deletes current user from db
     * @return {Promise<any>}
     */
    delete() {
        return new Promise((resolve, reject) => {
            this.isDeleted = true;
            this.platform.jovo.db().deleteUser((err) => {
                if (err) {
                    reject(err);
                    return;
                }
                resolve();
            });
        });
    }

    /**
     * Sets isNew flag for user
     * @param {boolean} isNew
     */
    setIsNewUser(isNew) {
        this.isNew = isNew;
    }

    /**
     * Returns isNew flag
     * @return {boolean|*}
     */
    isNewUser() {
        return this.isNew;
    }

    /**
     * Sets data
     * @param {*} data
     */
    setData(data) {
        if (!data) {
            data = {};
        }
        this.data = data.data;
        // Prevents saving an empty object
        _.values(this.config.userMetaData).forEach((element) => {
            if (element || element > 0) {
                this.metaData = data.metaData || {};
            }
        });
        // Prevents saving an empty object
        if (_.get(this, 'config.userContext.prev.size') > 0) {
            this.context = data.context || {};

            if (_.isEmpty(this.context)) {
                this.context.prev = [];
            }
        }
    }

    /**
     * Returns full user data object
     * @return {{data: *, metaData: *}}
     */
    getData() {
        return {
            data: this.data,
            metaData: this.metaData,
            context: this.context,
        };
    }

    /**
     * Updates dynamic meta data
     */
    updateMetaData() {
        if (_.get(this, 'config.userMetaData.lastUsedAt')) {
            this.metaData.lastUsedAt = new Date().toISOString();
        }

        if (_.get(this, 'config.userMetaData.sessionsCount')) {
            if (this.platform.isNewSession()) {
                if (!this.metaData.sessionsCount) {
                    this.metaData.sessionsCount = 0;
                }
                this.metaData.sessionsCount += 1;
            }
        }

        if (_.get(this, 'config.userMetaData.requestHistorySize') > 0) {
            if (!this.metaData.requests) {
                this.metaData.requests = {};
            }
            if (!this.metaData.requests[this.platform.jovo.getHandlerPath()]) {

                let requests = {
                    count: 0,
                    log: [],
                };
                this.metaData.requests[this.platform.jovo.getHandlerPath()] = requests;
            }
            let requestItem = this.metaData.requests[this.platform.jovo.getHandlerPath()];
            requestItem.count += 1;
            requestItem.log.push(new Date().toISOString());

            if (requestItem.log.length > this.config.requestHistorySize) {
                requestItem.log = requestItem.log.slice(1, requestItem.log.length);
            }
        }

        if (_.get(this, 'config.userMetaData.devices')) {
            if (!_.get(this.metaData, 'devices["'+this.platform.getDeviceId()+'"]')) {
                let device = {
                    hasAudioInterface: this.platform.hasAudioInterface(),
                    hasScreenInterface: this.platform.hasScreenInterface(),
                };
                _.set(this.metaData,
                    'devices["'+this.platform.getDeviceId()+'"]',
                    device);
            }
        }
    }

    /**
     * Updats the user context
     */
    updateContext() {
        if (_.get(this, 'config.userContext.prev.size') > 0) {
            this.updateContextPrev();
        }
    }

    /**
     * Updates context's prev array
     */
    updateContextPrev() {
        let prevObject = {
            request: {},
            response: {},
        };
        if (_.get(this, 'config.userContext.prev.response.speech')) {
            try { // sometimes there is no output
                prevObject.response.speech = this.platform.getSpeechText();
            } catch (error) {

            }
        }
        if (_.get(this, 'config.userContext.prev.response.reprompt')) {
            if (this.platform.getType() === BaseApp.PLATFORM_ENUM.ALEXA_SKILL) {
                try { // sometimes there is no reprompt
                    prevObject.response.reprompt = this.platform.getRepromptText();
                } catch (error) {

                }
            } else {
                try { // sometimes there is no reprompt
                    let response = this.platform.getResponse();
                    // Array length = amount of reprompts
                    let repromptCount = _.get(response, 'responseObj.data.google.noInputPrompts').length;
                    let repromptArray = new Array(repromptCount);
                    for (let i = 0; i < repromptArray.length; i++) {
                        let repromptStr = _.get(response, 'responseObj.data.google.noInputPrompts')[i].ssml;
                        repromptArray[i] = removeSpeakTags(repromptStr);
                    }
                    prevObject.response.reprompt = repromptArray;
                } catch (error) {

                }
            }
        }
        if (_.get(this, 'config.userContext.prev.response.state')) {
            if (this.platform.getType() === BaseApp.PLATFORM_ENUM.GOOGLE_ACTION) {
                prevObject.response.state = this.platform.getState();
            } else if (this.platform.getType() === BaseApp.PLATFORM_ENUM.ALEXA_SKILL) {
                prevObject.response.state = this.platform.getState();
            }
        }
        if (_.get(this, 'config.userContext.prev.request.intent')) {
            // Not platform specific
            if (this.platform.getRequestType() === BaseApp.REQUEST_TYPE_ENUM.INTENT) {
                /**
                 * Saves platform specific intent name first,
                 * but switches to intentMap value if defined
                 */
                let intentName = this.platform.getIntentName();
                prevObject.request.intent = intentName;
                _.keys(_.get(this, 'config.intentMap')).forEach((key) => {
                    if (intentName === key) {
                        prevObject.request.intent = this.config.intentMap[key];
                    }
                });
            } else if (this.platform.getType() === BaseApp.PLATFORM_ENUM.ALEXA_SKILL) {
                let request = this.platform.getRequest();
                let requestType = this.platform.getRequestType();
                switch (requestType) {
                    // Special cases: save specific request type, e.g.'AudioPlayer.PlaybackStarted'
                    case BaseApp.REQUEST_TYPE_ENUM.ON_EVENT:
                        prevObject.request.intent = _.get(request, 'request.type');
                        break;
                    case BaseApp.REQUEST_TYPE_ENUM.AUDIOPLAYER:
                        prevObject.request.intent = _.get(request, 'request.type');
                        break;
                    default:
                        // Save enum
                        prevObject.request.intent = requestType;
                }
            } else if (this.platform.getType() === BaseApp.PLATFORM_ENUM.GOOGLE_ACTION) {
                prevObject.request.intent = this.platform.getRequestType();
            }
        }
        if (_.get(this, 'config.userContext.prev.request.timestamp')) {
            prevObject.request.timestamp = this.platform.getTimestamp();
        }
        if (_.get(this, 'config.userContext.prev.request.state')) {
            if (this.platform.getType() === BaseApp.PLATFORM_ENUM.GOOGLE_ACTION) {
                let request = this.platform.getRequest();
                let contextSession = request.getContext('session');
                prevObject.request.state = _.get(contextSession, 'parameters.STATE');
            } else if (this.platform.getType() === BaseApp.PLATFORM_ENUM.ALEXA_SKILL) {
                try {
                    if (this.platform.request.getSessionAttribute('STATE')) {
                        prevObject.request.state = this.platform.request.getSessionAttribute('STATE');
                    }
                } catch (err) {
                    // Some requests don't have a state
                }
            }
        }
        if (_.get(this, 'config.userContext.prev.request.inputs')) {
            if (this.platform.getType() === BaseApp.PLATFORM_ENUM.ALEXA_SKILL) {
                if (this.platform.getRequestType() === BaseApp.REQUEST_TYPE_ENUM.INTENT) {
                    let inputsObject = this.platform.getInputsObj();
                    if (!_.isEmpty(inputsObject)) {
                        prevObject.request.inputs = inputsObject;
                    }
                }
            } else {
                let inputsObject = this.platform.getInputs();
                if (!_.isEmpty(inputsObject)) {
                    prevObject.request.inputs = inputsObject;
                }
            }
        }

        // Deletes request/response, if nothing was saved there
        if (Object.keys(prevObject.request).length === 0) {
            delete prevObject.request;
        }
        if (Object.keys(prevObject.response).length === 0) {
            delete prevObject.response;
        }
        if (this.context.prev.length === _.get(this, 'config.userContext.prev.size')) {
            this.context.prev.pop(); // remove last element
        }
        if (_.get(prevObject, 'request') || _.get(prevObject, 'response')) {
            // Prevents storing empty object
            this.context.prev.unshift(prevObject); // add new prevObject to the beginning
        }
    }

    /**
     * Creates initial user data object
     * @return {{metaData: {createdAt: string, sessionsCount: number}, data: {}}}
     */
    createUserData() {
        let obj = {
            metaData: {},
            data: {},
            context: {},
        };

        if (_.get(this, 'config.userContext.prev.size') > 0) {
            obj.context.prev = [];
        }

        if (this.config.userMetaData.createdAt) {
            obj.metaData['createdAt'] = new Date().toISOString();
        }

        return obj;
    }
    /**
     * Returns user id
     * @return {string}
     */
    getId() {
        return this.platform.getUserId();
    }

    /**
     * Returns locale
     * @return {string}
     */
    getLocale() {
        return this.platform.getLocale();
    }

    /**
     * Returns device id
     * @return {string}
     */
    getDeviceId() {
        return this.platform.getDeviceId();
    }

    /** META DATA HELPER */

    /**
     * Seconds since last session
     * @return {number} time in seconds
     */
    getSecondsSinceLastSession() {
        let now = new Date();
        let lastUsedAt = new Date(this.metaData.lastUsedAt);
        return Math.ceil((now - lastUsedAt)/1000);
    }

    /**
     * Returns number of sessions
     * @return {number}
     */
    getSessionsCount() {
        return this.metaData.sessionsCount;
    }

    /**
     * Returns last used at iso timestamp
     * @return {string|*}
     */
    getLastUsedAt() {
        return this.metaData.lastUsedAt;
    }

    /**
     * Returns created at iso timestamp
     * @return {string|*}
     */
    getCreatedAt() {
        return this.metaData.lastUsedAt;
    }

    /**
     * Return the intent at the specified index
     * @param {number} index
     * @return {String}
     */
    getPrevIntent(index) {
        this.errorIfIndexNotInteger(index);
        this.errorIfIndexBiggerPrevSize(index);
        return this.context.prev[index].request.intent;
    }

    /**
     * Returns request.state at the specified index
     * @param {number} index
     * @return {String}
     */
    getPrevRequestState(index) {
        this.errorIfIndexNotInteger(index);
        this.errorIfIndexBiggerPrevSize(index);
        return this.context.prev[index].request.state;
    }

    /**
     * Returns response.state at the specified index
     * @param {number} index
     * @return {String}
     */
    getPrevResponseState(index) {
        this.errorIfIndexNotInteger(index);
        this.errorIfIndexBiggerPrevSize(index);
        return this.context.prev[index].response.state;
    }

    /**
     * Returns the inputs at the specified index
     * @param {number} index
     * @return {*}
     */
    getPrevInputs(index) {
        this.errorIfIndexNotInteger(index);
        this.errorIfIndexBiggerPrevSize(index);
        return this.context.prev[index].request.inputs;
    }

    /**
     * Returns the timestamp at the specified index
     * @param {number} index
     * @return {String|*}
     */
    getPrevTimestamp(index) {
        this.errorIfIndexNotInteger(index);
        this.errorIfIndexBiggerPrevSize(index);
        return this.context.prev[index].request.timestamp;
    }

    /**
     * Returns the speech at the specified index
     * @param {number} index
     * @return {String}
     */
    getPrevSpeech(index) {
        this.errorIfIndexNotInteger(index);
        this.errorIfIndexBiggerPrevSize(index);
        return this.context.prev[index].response.speech;
    }

    /**
     * Returns the reprompt at the specified index
     * @param {number} index
     * @return {String}
     */
    getPrevReprompt(index) {
        this.errorIfIndexNotInteger(index);
        this.errorIfIndexBiggerPrevSize(index);
        return this.context.prev[index].response.reprompt;
    }

    /**
     * Error if index is bigger than userContext.prev.size
     * @param {number} index Must be an integer
     */
    errorIfIndexBiggerPrevSize(index) {
        if (index >= _.get(this, 'config.userContext.prev.size')) {
            throw new Error('index has to be an integer smaller than prev.size (default value: 1)');
        }
    }

    /**
     * Error if index is not an integer
     * @param {number} index
     */
    errorIfIndexNotInteger(index) {
        if (!_.isInteger(index)) {
            throw new Error('index has to be an integer');
        }
    }
}

/**
 * Removes speak tags
 * @param {string} text
 * @return {XML|string}
 */
function removeSpeakTags(text) {
    return text.replace(/<speak>/g, '').replace(/<\/speak>/g, '');
}

module.exports.User = User;

<commit_msg>:rotating_light: Remove linter warnings<commit_after>'use strict';
const _ = require('lodash');
const BaseApp = require('./app');

/**
 * User Class
 */
class User {

    /**
     * Constructor
     * @param {*} platform
     * @param {*=} config
     */
    constructor(platform, config) {
        this.platform = platform;
        this.config = {};
        this.config.intentMap = config.intentMap;
        this.config.userMetaData = config.userMetaData;
        this.config.userContext = config.userContext;
        // metaData && context are initialized at setData() | prevents saving an empty object
        this.metaData;
        this.context;
        this.data = {};
        this.isNew = false;
        this.isDeleted = false;
    }

    /**
     * Loads user data from database
     * @return {Promise<any>}
     */
    loadDataFromDb() {
        return new Promise((resolve, reject) => {
            this.platform.jovo.db().loadObject((error, data) => {
                if (error && (error.code === 'ERR_MAIN_KEY_NOT_FOUND' ||
                    error.code === 'ERR_DATA_KEY_NOT_FOUND')) {
                    this.setIsNewUser(true);
                    this.setData(this.createUserData());
                } else if (!data[this.platform.jovo.app.config.userDataCol]) {
                    this.setData(this.createUserData());
                } else {
                    this.setData(data[this.platform.jovo.app.config.userDataCol]);
                }
                resolve();
            });
        });
    }

    /**
     * Saves user data to database
     * @return {Promise<any>}
     */
    saveDataToDb() {
        return new Promise((resolve, reject) => {
            if (this.isDeleted) {
                resolve();
                return;
            }

            this.updateMetaData();
            this.updateContext();
            this.platform.jovo.db().saveFullObject(
                this.platform.jovo.app.config.userDataCol,
                this.getData(), function(error, data) {
                    if (error) {
                        reject(error);
                        return;
                    }
                    resolve();
                });
        });
    }

    /**
     * Deletes current user from db
     * @return {Promise<any>}
     */
    delete() {
        return new Promise((resolve, reject) => {
            this.isDeleted = true;
            this.platform.jovo.db().deleteUser((err) => {
                if (err) {
                    reject(err);
                    return;
                }
                resolve();
            });
        });
    }

    /**
     * Sets isNew flag for user
     * @param {boolean} isNew
     */
    setIsNewUser(isNew) {
        this.isNew = isNew;
    }

    /**
     * Returns isNew flag
     * @return {boolean|*}
     */
    isNewUser() {
        return this.isNew;
    }

    /**
     * Sets data
     * @param {*} data
     */
    setData(data) {
        if (!data) {
            data = {};
        }
        this.data = data.data;
        // Prevents saving an empty object
        _.values(this.config.userMetaData).forEach((element) => {
            if (element || element > 0) {
                this.metaData = data.metaData || {};
            }
        });
        // Prevents saving an empty object
        if (_.get(this, 'config.userContext.prev.size') > 0) {
            this.context = data.context || {};

            if (_.isEmpty(this.context)) {
                this.context.prev = [];
            }
        }
    }

    /**
     * Returns full user data object
     * @return {{data: *, metaData: *}}
     */
    getData() {
        return {
            data: this.data,
            metaData: this.metaData,
            context: this.context,
        };
    }

    /**
     * Updates dynamic meta data
     */
    updateMetaData() {
        if (_.get(this, 'config.userMetaData.lastUsedAt')) {
            this.metaData.lastUsedAt = new Date().toISOString();
        }

        if (_.get(this, 'config.userMetaData.sessionsCount')) {
            if (this.platform.isNewSession()) {
                if (!this.metaData.sessionsCount) {
                    this.metaData.sessionsCount = 0;
                }
                this.metaData.sessionsCount += 1;
            }
        }

        if (_.get(this, 'config.userMetaData.requestHistorySize') > 0) {
            if (!this.metaData.requests) {
                this.metaData.requests = {};
            }
            if (!this.metaData.requests[this.platform.jovo.getHandlerPath()]) {
                let requests = {
                    count: 0,
                    log: [],
                };
                this.metaData.requests[this.platform.jovo.getHandlerPath()] = requests;
            }
            let requestItem = this.metaData.requests[this.platform.jovo.getHandlerPath()];
            requestItem.count += 1;
            requestItem.log.push(new Date().toISOString());

            if (requestItem.log.length > this.config.requestHistorySize) {
                requestItem.log = requestItem.log.slice(1, requestItem.log.length);
            }
        }

        if (_.get(this, 'config.userMetaData.devices')) {
            if (!_.get(this.metaData, 'devices["'+this.platform.getDeviceId()+'"]')) {
                let device = {
                    hasAudioInterface: this.platform.hasAudioInterface(),
                    hasScreenInterface: this.platform.hasScreenInterface(),
                };
                _.set(this.metaData,
                    'devices["'+this.platform.getDeviceId()+'"]',
                    device);
            }
        }
    }

    /**
     * Updats the user context
     */
    updateContext() {
        if (_.get(this, 'config.userContext.prev.size') > 0) {
            this.updateContextPrev();
        }
    }

    /**
     * Updates context's prev array
     */
    updateContextPrev() {
        let prevObject = {
            request: {},
            response: {},
        };
        if (_.get(this, 'config.userContext.prev.response.speech')) {
            try { // sometimes there is no output
                prevObject.response.speech = this.platform.getSpeechText();
            } catch (error) {

            }
        }
        if (_.get(this, 'config.userContext.prev.response.reprompt')) {
            if (this.platform.getType() === BaseApp.PLATFORM_ENUM.ALEXA_SKILL) {
                try { // sometimes there is no reprompt
                    prevObject.response.reprompt = this.platform.getRepromptText();
                } catch (error) {

                }
            } else {
                try { // sometimes there is no reprompt
                    let response = this.platform.getResponse();
                    // Array length = amount of reprompts
                    let repromptCount = _.get(response, 'responseObj.data.google.noInputPrompts').length;
                    let repromptArray = new Array(repromptCount);
                    for (let i = 0; i < repromptArray.length; i++) {
                        let repromptStr = _.get(response, 'responseObj.data.google.noInputPrompts')[i].ssml;
                        repromptArray[i] = removeSpeakTags(repromptStr);
                    }
                    prevObject.response.reprompt = repromptArray;
                } catch (error) {

                }
            }
        }
        if (_.get(this, 'config.userContext.prev.response.state')) {
            if (this.platform.getType() === BaseApp.PLATFORM_ENUM.GOOGLE_ACTION) {
                prevObject.response.state = this.platform.getState();
            } else if (this.platform.getType() === BaseApp.PLATFORM_ENUM.ALEXA_SKILL) {
                prevObject.response.state = this.platform.getState();
            }
        }
        if (_.get(this, 'config.userContext.prev.request.intent')) {
            // Not platform specific
            if (this.platform.getRequestType() === BaseApp.REQUEST_TYPE_ENUM.INTENT) {
                /**
                 * Saves platform specific intent name first,
                 * but switches to intentMap value if defined
                 */
                let intentName = this.platform.getIntentName();
                prevObject.request.intent = intentName;
                _.keys(_.get(this, 'config.intentMap')).forEach((key) => {
                    if (intentName === key) {
                        prevObject.request.intent = this.config.intentMap[key];
                    }
                });
            } else if (this.platform.getType() === BaseApp.PLATFORM_ENUM.ALEXA_SKILL) {
                let request = this.platform.getRequest();
                let requestType = this.platform.getRequestType();
                switch (requestType) {
                    // Special cases: save specific request type, e.g.'AudioPlayer.PlaybackStarted'
                    case BaseApp.REQUEST_TYPE_ENUM.ON_EVENT:
                        prevObject.request.intent = _.get(request, 'request.type');
                        break;
                    case BaseApp.REQUEST_TYPE_ENUM.AUDIOPLAYER:
                        prevObject.request.intent = _.get(request, 'request.type');
                        break;
                    default:
                        // Save enum
                        prevObject.request.intent = requestType;
                }
            } else if (this.platform.getType() === BaseApp.PLATFORM_ENUM.GOOGLE_ACTION) {
                prevObject.request.intent = this.platform.getRequestType();
            }
        }
        if (_.get(this, 'config.userContext.prev.request.timestamp')) {
            prevObject.request.timestamp = this.platform.getTimestamp();
        }
        if (_.get(this, 'config.userContext.prev.request.state')) {
            if (this.platform.getType() === BaseApp.PLATFORM_ENUM.GOOGLE_ACTION) {
                let request = this.platform.getRequest();
                let contextSession = request.getContext('session');
                prevObject.request.state = _.get(contextSession, 'parameters.STATE');
            } else if (this.platform.getType() === BaseApp.PLATFORM_ENUM.ALEXA_SKILL) {
                try {
                    if (this.platform.request.getSessionAttribute('STATE')) {
                        prevObject.request.state = this.platform.request.getSessionAttribute('STATE');
                    }
                } catch (err) {
                    // Some requests don't have a state
                }
            }
        }
        if (_.get(this, 'config.userContext.prev.request.inputs')) {
            if (this.platform.getType() === BaseApp.PLATFORM_ENUM.ALEXA_SKILL) {
                if (this.platform.getRequestType() === BaseApp.REQUEST_TYPE_ENUM.INTENT) {
                    let inputsObject = this.platform.getInputsObj();
                    if (!_.isEmpty(inputsObject)) {
                        prevObject.request.inputs = inputsObject;
                    }
                }
            } else {
                let inputsObject = this.platform.getInputs();
                if (!_.isEmpty(inputsObject)) {
                    prevObject.request.inputs = inputsObject;
                }
            }
        }

        // Deletes request/response, if nothing was saved there
        if (Object.keys(prevObject.request).length === 0) {
            delete prevObject.request;
        }
        if (Object.keys(prevObject.response).length === 0) {
            delete prevObject.response;
        }
        if (this.context.prev.length === _.get(this, 'config.userContext.prev.size')) {
            this.context.prev.pop(); // remove last element
        }
        if (_.get(prevObject, 'request') || _.get(prevObject, 'response')) {
            // Prevents storing empty object
            this.context.prev.unshift(prevObject); // add new prevObject to the beginning
        }
    }

    /**
     * Creates initial user data object
     * @return {{metaData: {createdAt: string, sessionsCount: number}, data: {}}}
     */
    createUserData() {
        let obj = {
            metaData: {},
            data: {},
            context: {},
        };

        if (_.get(this, 'config.userContext.prev.size') > 0) {
            obj.context.prev = [];
        }

        if (this.config.userMetaData.createdAt) {
            obj.metaData['createdAt'] = new Date().toISOString();
        }

        return obj;
    }
    /**
     * Returns user id
     * @return {string}
     */
    getId() {
        return this.platform.getUserId();
    }

    /**
     * Returns locale
     * @return {string}
     */
    getLocale() {
        return this.platform.getLocale();
    }

    /**
     * Returns device id
     * @return {string}
     */
    getDeviceId() {
        return this.platform.getDeviceId();
    }

    /** META DATA HELPER */

    /**
     * Seconds since last session
     * @return {number} time in seconds
     */
    getSecondsSinceLastSession() {
        let now = new Date();
        let lastUsedAt = new Date(this.metaData.lastUsedAt);
        return Math.ceil((now - lastUsedAt)/1000);
    }

    /**
     * Returns number of sessions
     * @return {number}
     */
    getSessionsCount() {
        return this.metaData.sessionsCount;
    }

    /**
     * Returns last used at iso timestamp
     * @return {string|*}
     */
    getLastUsedAt() {
        return this.metaData.lastUsedAt;
    }

    /**
     * Returns created at iso timestamp
     * @return {string|*}
     */
    getCreatedAt() {
        return this.metaData.lastUsedAt;
    }

    /**
     * Return the intent at the specified index
     * @param {number} index
     * @return {String}
     */
    getPrevIntent(index) {
        this.errorIfIndexNotInteger(index);
        this.errorIfIndexBiggerPrevSize(index);
        return this.context.prev[index].request.intent;
    }

    /**
     * Returns request.state at the specified index
     * @param {number} index
     * @return {String}
     */
    getPrevRequestState(index) {
        this.errorIfIndexNotInteger(index);
        this.errorIfIndexBiggerPrevSize(index);
        return this.context.prev[index].request.state;
    }

    /**
     * Returns response.state at the specified index
     * @param {number} index
     * @return {String}
     */
    getPrevResponseState(index) {
        this.errorIfIndexNotInteger(index);
        this.errorIfIndexBiggerPrevSize(index);
        return this.context.prev[index].response.state;
    }

    /**
     * Returns the inputs at the specified index
     * @param {number} index
     * @return {*}
     */
    getPrevInputs(index) {
        this.errorIfIndexNotInteger(index);
        this.errorIfIndexBiggerPrevSize(index);
        return this.context.prev[index].request.inputs;
    }

    /**
     * Returns the timestamp at the specified index
     * @param {number} index
     * @return {String|*}
     */
    getPrevTimestamp(index) {
        this.errorIfIndexNotInteger(index);
        this.errorIfIndexBiggerPrevSize(index);
        return this.context.prev[index].request.timestamp;
    }

    /**
     * Returns the speech at the specified index
     * @param {number} index
     * @return {String}
     */
    getPrevSpeech(index) {
        this.errorIfIndexNotInteger(index);
        this.errorIfIndexBiggerPrevSize(index);
        return this.context.prev[index].response.speech;
    }

    /**
     * Returns the reprompt at the specified index
     * @param {number} index
     * @return {String}
     */
    getPrevReprompt(index) {
        this.errorIfIndexNotInteger(index);
        this.errorIfIndexBiggerPrevSize(index);
        return this.context.prev[index].response.reprompt;
    }

    /**
     * Error if index is bigger than userContext.prev.size
     * @param {number} index Must be an integer
     */
    errorIfIndexBiggerPrevSize(index) {
        if (index >= _.get(this, 'config.userContext.prev.size')) {
            throw new Error('index has to be an integer smaller than prev.size (default value: 1)');
        }
    }

    /**
     * Error if index is not an integer
     * @param {number} index
     */
    errorIfIndexNotInteger(index) {
        if (!_.isInteger(index)) {
            throw new Error('index has to be an integer');
        }
    }
}

/**
 * Removes speak tags
 * @param {string} text
 * @return {XML|string}
 */
function removeSpeakTags(text) {
    return text.replace(/<speak>/g, '').replace(/<\/speak>/g, '');
}

module.exports.User = User;

<|endoftext|>


<commit_before>const fs = require('fs');
const path = require('path');
const {
  exec, exit, cp, test,
} = require('shelljs');
const semver = require('semver');
const readline = require('readline-sync');
const replace = require('replace-in-file');
const pick = require('just-pick');
const ghpages = require('gh-pages');
const buildSite = require('./buildSite');

const {
  BASE_PACKAGE,
  PACKAGE_NAME,
  SOURCE_DIR,
  OUT_DIR,
  SITE_DIR,
  log,
  logSuccess,
  logError,
  execFail,
} = require('./util');

const PACKAGE_JSON = {
  keepFields: [
    'name',
    'version',
    'license',
    'homepage',
    'repository',
    'description',
    'keywords',
    'bugs',
  ],
  addFields: {
    'main': 'cjs/index.js',
    'react-native': 'cjs/index.js',
    'module': 'esm/index.js',
    'unpkg': 'wanakana.min.js',
    'engines': {
      node: '>=12',
    },
  },
};

const writePackage = (outDir, packageData) => fs.writeFileSync(
  path.resolve(outDir, 'package.json'),
  JSON.stringify(packageData, null, 2)
);

try {
  log('Preparing release...');
  if (execFail(exec('git diff-files --quiet'))) {
    logError(
      'You have unsaved changes in the working tree. Commit or stash changes before releasing.'
    );
    exit(1);
  }

  log('Have you updated the changelog?');
  if (!readline.keyInYN('Yes I have!')) {
    log('OK. Do that, then try again!');
    exit(0);
  }

  log('Running tests...');
  if (execFail(exec('npm-run-all lint:js test'))) {
    logError('The test command did not exit cleanly. Aborting release.');
    exit(1);
  }
  logSuccess('Tests were successful.');

  const versionLoc = path.resolve('VERSION');
  const version = fs.readFileSync(versionLoc, 'utf8').trim();
  let nextVersion = readline.question(
    `Current version of ${PACKAGE_NAME} is ${version}.\nNext version (exclude dist-tags like '-beta.1'): `
  );

  const distTag = readline.question(
    'Do you want to add an npm dist-tag other than latest (alpha.3, beta.0, rc.1)? Leave blank to skip: '
  );

  if (distTag) {
    nextVersion = `${nextVersion}-${distTag}`;
  }

  while (
    !(!nextVersion || (semver.valid(nextVersion) && semver.gt(nextVersion, version)))
  ) {
    nextVersion = readline.question(
      `Must provide a valid version that is greater than ${version}, or leave blank to skip: `
    );
  }

  try {
    replace.sync({
      files: `${path.resolve(SOURCE_DIR, 'constants.js')}`,
      from: /VERSION = '.*'/,
      to: `VERSION = '${nextVersion}'`,
    });
    log('Updated VERSION in Wanakana constants');
  } catch (error) {
    logError('Error occurred replacing version:', error);
    exit(1);
  }

  log('Building dist files...');
  if (execFail(exec('npm run build'))) {
    logError('The build command did not exit cleanly. Aborting release.');
    exit(1);
  } else {
    log('Compilation was successful.');
  }

  log('Copying additional project files...');

  const additionalProjectFiles = [
    'README.md',
    'CHANGELOG.md',
    'package.json',
    'LICENSE',
  ];

  additionalProjectFiles.forEach((filename) => {
    const file = path.resolve(process.cwd(), filename);
    if (!test('-e', file)) {
      logError(`Unable to resolve ${file}`);
      exit(1);
    }
    cp('-Rf', file, path.resolve(OUT_DIR));
  });

  log('Updating release package.json...');
  const updatedPackage = Object.assign(BASE_PACKAGE, { version: nextVersion });

  const releasePackage = Object.assign(
    pick(updatedPackage, PACKAGE_JSON.keepFields),
    PACKAGE_JSON.addFields
  );

  writePackage(OUT_DIR, releasePackage);

  log(`About to publish ${PACKAGE_NAME}@${nextVersion} to npm.`);
  if (!readline.keyInYN('Sound good? ')) {
    log('OK. Stopping release.');
    exit(0);
  }

  const otp = readline.question(
    'Enter NPM account Authenticator otp (blank to skip)'
  );

  log('Publishing...');
  if (
    execFail(
      exec(
        `cd ${OUT_DIR} && npm publish${otp && ` --otp=${otp}`}${distTag
          && ` --tag ${distTag}`}`
      )
    )
  ) {
    logError('Publish failed. Aborting release.');
    exit(1);
  }
  logSuccess(`${PACKAGE_NAME}@${nextVersion} was successfully published.`);

  log('Updating VERSION file...');
  fs.writeFileSync(versionLoc, `${nextVersion}\n`);

  log('Updating repo package.json');
  writePackage(process.cwd(), updatedPackage);

  log('Rebuilding docs');
  if (execFail(exec('npm run docs'))) {
    logError('Building docs failed.');
    exit(1);
  }

  log('Rebuilding demo site');
  buildSite(nextVersion);

  if (!distTag) {
    log('Publishing github-pages demo & docs');
    ghpages.publish(SITE_DIR, (err) => {
      if (err) {
        logError(err);
        logError('Publish github pages failed.');
        exit(1);
      } else {
        logSuccess('Published demo and docs to gh-pages branch');
        exit(0);
      }
    });
  }

  log('Committing version changes...');
  exec(`git add ${versionLoc} package.json src/constants.js`);
  exec(`git commit -m "Version ${nextVersion}"`);

  if (!distTag) {
    log(`Tagging release... (${nextVersion})`);
    exec(`git tag ${nextVersion}`);

    log('Pushing to GitHub...');
    exec('git push');
    exec('git push --tags');
  }

  logSuccess('New release pushed to github.');
  log('Finishing up...');
} catch (error) {
  logError('Release failed due to an error', error);
}
<commit_msg>build: ensure cypress tests run before release<commit_after>const fs = require('fs');
const path = require('path');
const {
  exec, exit, cp, test,
} = require('shelljs');
const semver = require('semver');
const readline = require('readline-sync');
const replace = require('replace-in-file');
const pick = require('just-pick');
const ghpages = require('gh-pages');
const buildSite = require('./buildSite');

const {
  BASE_PACKAGE,
  PACKAGE_NAME,
  SOURCE_DIR,
  OUT_DIR,
  SITE_DIR,
  log,
  logSuccess,
  logError,
  execFail,
} = require('./util');

const PACKAGE_JSON = {
  keepFields: [
    'name',
    'version',
    'license',
    'homepage',
    'repository',
    'description',
    'keywords',
    'bugs',
  ],
  addFields: {
    'main': 'cjs/index.js',
    'react-native': 'cjs/index.js',
    'module': 'esm/index.js',
    'unpkg': 'wanakana.min.js',
    'engines': {
      node: '>=12',
    },
  },
};

const writePackage = (outDir, packageData) => fs.writeFileSync(
  path.resolve(outDir, 'package.json'),
  JSON.stringify(packageData, null, 2)
);

try {
  log('Preparing release...');
  if (execFail(exec('git diff-files --quiet'))) {
    logError(
      'You have unsaved changes in the working tree. Commit or stash changes before releasing.'
    );
    exit(1);
  }

  log('Have you updated the changelog?');
  if (!readline.keyInYN('Yes I have!')) {
    log('OK. Do that, then try again!');
    exit(0);
  }

  log('Running tests...');
  if (execFail(exec('npm-run-all lint:js test cypress:test'))) {
    logError('The tests did not exit cleanly. Aborting release.');
    exit(1);
  }
  logSuccess('Tests were successful.');

  const versionLoc = path.resolve('VERSION');
  const version = fs.readFileSync(versionLoc, 'utf8').trim();
  let nextVersion = readline.question(
    `Current version of ${PACKAGE_NAME} is ${version}.\nNext version (exclude dist-tags like '-beta.1'): `
  );

  const distTag = readline.question(
    'Do you want to add an npm dist-tag other than latest (alpha.3, beta.0, rc.1)? Leave blank to skip: '
  );

  if (distTag) {
    nextVersion = `${nextVersion}-${distTag}`;
  }

  while (
    !(!nextVersion || (semver.valid(nextVersion) && semver.gt(nextVersion, version)))
  ) {
    nextVersion = readline.question(
      `Must provide a valid version that is greater than ${version}, or leave blank to skip: `
    );
  }

  try {
    replace.sync({
      files: `${path.resolve(SOURCE_DIR, 'constants.js')}`,
      from: /VERSION = '.*'/,
      to: `VERSION = '${nextVersion}'`,
    });
    log('Updated VERSION in Wanakana constants');
  } catch (error) {
    logError('Error occurred replacing version:', error);
    exit(1);
  }

  log('Building dist files...');
  if (execFail(exec('npm run build'))) {
    logError('The build command did not exit cleanly. Aborting release.');
    exit(1);
  } else {
    log('Compilation was successful.');
  }

  log('Copying additional project files...');

  const additionalProjectFiles = [
    'README.md',
    'CHANGELOG.md',
    'package.json',
    'LICENSE',
  ];

  additionalProjectFiles.forEach((filename) => {
    const file = path.resolve(process.cwd(), filename);
    if (!test('-e', file)) {
      logError(`Unable to resolve ${file}`);
      exit(1);
    }
    cp('-Rf', file, path.resolve(OUT_DIR));
  });

  log('Updating release package.json...');
  const updatedPackage = Object.assign(BASE_PACKAGE, { version: nextVersion });

  const releasePackage = Object.assign(
    pick(updatedPackage, PACKAGE_JSON.keepFields),
    PACKAGE_JSON.addFields
  );

  writePackage(OUT_DIR, releasePackage);

  log(`About to publish ${PACKAGE_NAME}@${nextVersion} to npm.`);
  if (!readline.keyInYN('Sound good? ')) {
    log('OK. Stopping release.');
    exit(0);
  }

  const otp = readline.question(
    'Enter NPM account Authenticator otp (blank to skip)'
  );

  log('Publishing...');
  if (
    execFail(
      exec(
        `cd ${OUT_DIR} && npm publish${otp && ` --otp=${otp}`}${distTag
          && ` --tag ${distTag}`}`
      )
    )
  ) {
    logError('Publish failed. Aborting release.');
    exit(1);
  }
  logSuccess(`${PACKAGE_NAME}@${nextVersion} was successfully published.`);

  log('Updating VERSION file...');
  fs.writeFileSync(versionLoc, `${nextVersion}\n`);

  log('Updating repo package.json');
  writePackage(process.cwd(), updatedPackage);

  log('Rebuilding docs');
  if (execFail(exec('npm run docs'))) {
    logError('Building docs failed.');
    exit(1);
  }

  log('Rebuilding demo site');
  buildSite(nextVersion);

  if (!distTag) {
    log('Publishing github-pages demo & docs');
    ghpages.publish(SITE_DIR, (err) => {
      if (err) {
        logError(err);
        logError('Publish github pages failed.');
        exit(1);
      } else {
        logSuccess('Published demo and docs to gh-pages branch');
        exit(0);
      }
    });
  }

  log('Committing version changes...');
  exec(`git add ${versionLoc} package.json src/constants.js`);
  exec(`git commit -m "Version ${nextVersion}"`);

  if (!distTag) {
    log(`Tagging release... (${nextVersion})`);
    exec(`git tag ${nextVersion}`);

    log('Pushing to GitHub...');
    exec('git push');
    exec('git push --tags');
  }

  logSuccess('New release pushed to github.');
  log('Finishing up...');
} catch (error) {
  logError('Release failed due to an error', error);
}
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import { Link } from 'react-router';
import LoginEmail from './LoginEmail';
import Message from './Message';

class LoginMenu extends Component {
  render() {
    const { loginTwitter, loginFacebook, loginSlack, state } = this.props;
    return (

        <Message message={state.app.message} />

Sign in

Welcome to Check. Invite your team and online community in a secure environment to work together to validate breaking news content. Then, quickly show the work to your audience on social media or your news site. Currently in Beta. Optimized for Chrome desktop.

            <button onClick={loginTwitter} id="twitter-login" className='login-menu__button login-menu__button--twitter'>Sign in with Twitter</button>

          {/*

            <button disabled id="google-login" className='login-menu__button login-menu__button--google'>Sign in with Google</button>

          */}

            <button onClick={loginFacebook} id="facebook-login" className='login-menu__button login-menu__button--facebook'>Sign in with Facebook</button>

            <button onClick={loginSlack} id="slack-login" className='login-menu__button login-menu__button--slack'>Sign in with Slack</button>

            <LoginEmail {...this.props} />

By signing in, you agree to the Check <Link to='/tos' className='login-menu__footer-link'>Terms of Service</Link> and <Link to='/privacy' className='login-menu__footer-link'>Privacy Policy</Link>.

    );
  }
}

export default LoginMenu;
<commit_msg>Update copywriting and layout with temporary inline CSS<commit_after>import React, { Component, PropTypes } from 'react';
import { Link } from 'react-router';
import LoginEmail from './LoginEmail';
import Message from './Message';

class LoginMenu extends Component {
  render() {
    const { loginTwitter, loginFacebook, loginSlack, state } = this.props;
    return (

        <Message message={state.app.message} />

Sign in

Welcome to Check. Invite your team and online community in a secure environment to work together to verify breaking news content. Then, quickly show the work to your audience on social media or your news site.

Currently in Beta. Optimized for Chrome desktop.

            <button onClick={loginTwitter} id="twitter-login" className='login-menu__button login-menu__button--twitter'>Sign in with Twitter</button>

          {/*

            <button disabled id="google-login" className='login-menu__button login-menu__button--google'>Sign in with Google</button>

          */}

            <button onClick={loginFacebook} id="facebook-login" className='login-menu__button login-menu__button--facebook'>Sign in with Facebook</button>

            <button onClick={loginSlack} id="slack-login" className='login-menu__button login-menu__button--slack'>Sign in with Slack</button>

            <LoginEmail {...this.props} />

By signing in, you agree to the Check <Link to='/tos' className='login-menu__footer-link'>Terms of Service</Link> and <Link to='/privacy' className='login-menu__footer-link'>Privacy Policy</Link>.

    );
  }
}

export default LoginMenu;
<|endoftext|>