<commit_before>var fs = require('fs');
var http = require('http');
var http2 = require('http2');
var httpProxy = require('http-proxy');

var sslkeyPath = '/etc/letsencrypt/live/goita.beta.or.jp/'
var options = {
    key: fs.readFileSync(sslkeyPath + 'privkey.pem', 'utf8'),
    cert: fs.readFileSync(sslkeyPath + 'cert.pem', 'utf8')
  }
var proxy = httpProxy.createProxyServer({
    target: "http://goita.beta.or.jp:8880",
    ws: true
});

var server = http.createServer(function(req, res){
    proxy.web(req, res);
});
server.on('upgrade', function (req, socket, head) {
    proxy.ws(req, socket, head);
});

var server2 = http2.createServer(options,function(req, res){
    proxy.web(req, res);
});

server2.on('upgrade', function (req, socket, head) {
    proxy.ws(req, socket, head);
});

server.listen(80); //root is required to run service on port 80.
server2.listen(443); //root is required to run service on port 443.
console.log("proxy server started");<commit_msg>test2<commit_after>var fs = require('fs');
var http = require('http');
var https = require('https');
var http2 = require('http2');
var httpProxy = require('http-proxy');

var sslkeyPath = '/etc/letsencrypt/live/goita.beta.or.jp/'
var options = {
    key: fs.readFileSync(sslkeyPath + 'privkey.pem', 'utf8'),
    cert: fs.readFileSync(sslkeyPath + 'cert.pem', 'utf8')
  }
var proxy = httpProxy.createProxyServer({
    target: "http://goita.beta.or.jp:8880",
    ws: true
});

var server = http.createServer(function(req, res){
    proxy.web(req, res);
});
server.on('upgrade', function (req, socket, head) {
    proxy.ws(req, socket, head);
});

var sslproxy = httpProxy.createServer({
    target: "http://goita.beta.or.jp:8880",
    ws: true,
    secure: true,
    ssl:{
        key: fs.readFileSync(sslkeyPath + 'privkey.pem', 'utf8'),
        cert: fs.readFileSync(sslkeyPath + 'cert.pem', 'utf8')
    }
});

server.listen(80); //root is required to run service on port 80.
sslproxy.listen(443); //root is required to run service on port 443.
console.log("proxy server started");<|endoftext|>


<commit_before>var request = require('request');
var http = require('http');
var metaserve = require('metaserve')('.');

http.createServer(function(req, res) {
  if (req.url.match(/^\/proxy/)) {
    // Handle the custom route
    return proxy(req, res);
  } else {
    // Fall back to metaserve
    metaserve(req, res);
  }
}).listen(8080);

function notFound (res) {
  res.statusCode = 404;
  res.end('404 Error');
}

function proxy (req, res) {
  var url = req.url;

  console.log('url: ' + url);

  req.on('data', function(chunk){
    console.log(chunk.toString(),'\n\n\n');
  });

  var test = {
    proxy: /^\/proxy\/(.+)$/,
    hosts: /^https?:\/\/(geotrigger\.)?arcgis\.com\//
  };

  var matchProxy = url.match(test.proxy);

  if (!matchProxy) {
    return notFound(res);
  }

  var target = matchProxy[1];
  var matchHosts = target.match(test.hosts);

  if (!matchHosts) {
    return notFound(res);
  }

  var headers = req.headers;
  var method = req.method;

  console.log(headers, method,'\n\n\n');

  if (!headers['content-type']) {
    if (matchProxy[1].match(/geotrigger\.arcgis\.com\//)) {
      headers['content-type'] = 'application/json';
    } else {
      headers['content-type'] = 'application/x-www-form-urlencoded';
    }
  }

  delete headers.host;

  req.pipe(request({
    url: target,
    headers: headers,
    method: method
  })).pipe(res);

}

console.log('proxy server running on port 8080');<commit_msg>move proxy to example folder<commit_after><|endoftext|>


<commit_before>var Rx = require('rx');
var colors = require('colors');
var Observable = Rx.Observable;
var Benchmark = require('benchmark');
var suite = new Benchmark.Suite();
var glob = require('glob');
var path = require('path');
var fs = require('fs');

var oldRxPackage = JSON.parse(require('fs').readFileSync('node_modules/rx/package.json'));
var oldVersion = oldRxPackage.version;
var newRxPackage = JSON.parse(require('fs').readFileSync('package.json'));
var newVersion = newRxPackage.version;

function line() {
  return [].slice.call(arguments)
    .map(function (n) {
      return Array(n + 2).join('-');
    }).join('---');
}

function row() {
  var columnWidths = [].slice.call(arguments);

  return function () {
    var data = [].slice.call(arguments);
    return data.map(function (d, i) {
      var text = String(d);
      var w = columnWidths[i];

      if (w < text.length) {
        text = text.substring(0, w);
      }

      while (text.length < w) {
        text = ' ' + text;
      }

      return text;
    }).join(' | ');
  };
}

function formatNumber(n, fix) {
  var f = fix;
  var num = n;
  if (typeof fix !== 'number' || !isFinite(fix)) {
    f = (n < 100 ? 2 : 0);
  }
  num = n.toFixed(f);
  var text = String(n).split('.');
  return text[0].replace(/(?=(?:\d{3})+$)(?!\b)/g, ',') +
    (text[1] ? '.' + text[1] : '');
}

console.log();
console.log();
console.log();
console.log('Testing against RxJS v ' + oldVersion);
console.log('for csv output, use:  --csv filename.csv');
console.log();
console.log(row(40, 30, 30, 15, 15)('', 'RxJS ' + oldVersion, 'RxJS ' + newVersion, 'factor', '% improved'));
console.log(line(40, 30, 30, 15, 15));

var output = [];
output.push(['name', 'old ops/sec', 'old error margin', 'new ops/sec', 'new error margin', 'factor', 'percent improved']);

Observable.create(function (observer) {
  ['perf/micro/immediate-scheduler/**/*.js', 'perf/micro/current-thread-scheduler/**/*.js']
  .forEach(function (pattern) {
    try {
      glob.sync(pattern).forEach(function (file) {
        observer.onNext(file);
      });
    } catch (err) {
      observer.onError(err);
    }
  });
  observer.onCompleted();
})
.map(function (filename) {
  return './' + path.relative(__dirname, filename);
})
.filter(function (filePath) {
  var argv = process.argv;
  if (argv && argv.length > 2) {
    return argv.slice(2).some(function (val) {
      return path.parse(filePath).name === val;
    });
  }
  return true;
})
.map(function (filePath) {
  var info = path.parse(filePath);
  return {
    name: info.name + (info.dir.indexOf('immediate') !== -1 ? ' - immediate' : ''),
    test: require(filePath)
  };
})
.concatMap(function (x) {
  var test = x.test;
  var name = x.name;
  var tests = test(new Benchmark.Suite(name));

  return Observable.create(function (observer) {
    tests.on('complete', function () {
      var _old = this[0];
      var _new = this[1];

      observer.onNext({
        old: _old,
        new: _new,
        name: name
      });

      observer.onCompleted();
    }).run({ async: true });
  });
})
.do(function (d) {
  var r = d.new.hz / d.old.hz;
  var p = (d.new.hz - d.old.hz) / d.old.hz;
  output.push([d.name, d.old.hz, d.old.stats.rme, d.new.hz, d.new.stats.rme, r, p]);
})
.map(function (d) {
  var oldHz = d.old.hz;
  var newHz = d.new.hz;
  var r = newHz / oldHz;
  var p = 100 * ((newHz - oldHz) / oldHz);
  var oldRme = ' (\xb1' + d.old.stats.rme.toFixed(2) + '%)';
  var newRme = ' (\xb1' + d.new.stats.rme.toFixed(2) + '%)';
  return row(40, 30, 30, 15, 15)(d.name, formatNumber(oldHz) + oldRme,
    formatNumber(newHz) + newRme, formatNumber(r) + 'x', formatNumber(p, 1) + '%');
})
.subscribe(console.log.bind(console), function (err) {
  if (err.stack === undefined) {
    console.log(err);
  } else {
    console.log(err.stack);
  }
}, function () {
  var csv = process.argv.indexOf('--csv');
  if (csv !== -1) {
    var filename = process.argv[csv + 1];
    fs.writeFileSync(filename, output.map(function (o) {
      return o.map(function (v) {
        return JSON.stringify(v);
      }).join(',');
    }).join('\n'), { encoding: 'utf8' });
  }
});<commit_msg>chore(micro perf): fix number formatting regression introduced by lint fixes<commit_after>var Rx = require('rx');
var colors = require('colors');
var Observable = Rx.Observable;
var Benchmark = require('benchmark');
var suite = new Benchmark.Suite();
var glob = require('glob');
var path = require('path');
var fs = require('fs');

var oldRxPackage = JSON.parse(require('fs').readFileSync('node_modules/rx/package.json'));
var oldVersion = oldRxPackage.version;
var newRxPackage = JSON.parse(require('fs').readFileSync('package.json'));
var newVersion = newRxPackage.version;

function line() {
  return [].slice.call(arguments)
    .map(function (n) {
      return Array(n + 2).join('-');
    }).join('---');
}

function row() {
  var columnWidths = [].slice.call(arguments);

  return function () {
    var data = [].slice.call(arguments);
    return data.map(function (d, i) {
      var text = String(d);
      var w = columnWidths[i];

      if (w < text.length) {
        text = text.substring(0, w);
      }

      while (text.length < w) {
        text = ' ' + text;
      }

      return text;
    }).join(' | ');
  };
}

function formatNumber(n, fix) {
  var f = Number(fix);
  if (typeof fix !== 'number' || !isFinite(fix)) {
    f = n < 100 ? 2 : 0;
  }
  var num = n.toFixed(Number(f));
  var text = String(num).split('.');
  return text[0].replace(/(?=(?:\d{3})+$)(?!\b)/g, ',') +
    (text[1] ? '.' + text[1] : '');
}

console.log();
console.log();
console.log();
console.log('Testing against RxJS v ' + oldVersion);
console.log('for csv output, use:  --csv filename.csv');
console.log();
console.log(row(40, 30, 30, 15, 15)('', 'RxJS ' + oldVersion, 'RxJS ' + newVersion, 'factor', '% improved'));
console.log(line(40, 30, 30, 15, 15));

var output = [];
output.push(['name', 'old ops/sec', 'old error margin', 'new ops/sec', 'new error margin', 'factor', 'percent improved']);

Observable.create(function (observer) {
  ['perf/micro/immediate-scheduler/**/*.js', 'perf/micro/current-thread-scheduler/**/*.js']
  .forEach(function (pattern) {
    try {
      glob.sync(pattern).forEach(function (file) {
        observer.onNext(file);
      });
    } catch (err) {
      observer.onError(err);
    }
  });
  observer.onCompleted();
})
.map(function (filename) {
  return './' + path.relative(__dirname, filename);
})
.filter(function (filePath) {
  var argv = process.argv;
  if (argv && argv.length > 2) {
    return argv.slice(2).some(function (val) {
      return path.parse(filePath).name === val;
    });
  }
  return true;
})
.map(function (filePath) {
  var info = path.parse(filePath);
  return {
    name: info.name + (info.dir.indexOf('immediate') !== -1 ? ' - immediate' : ''),
    test: require(filePath)
  };
})
.concatMap(function (x) {
  var test = x.test;
  var name = x.name;
  var tests = test(new Benchmark.Suite(name));

  return Observable.create(function (observer) {
    tests.on('complete', function () {
      var _old = this[0];
      var _new = this[1];

      observer.onNext({
        old: _old,
        new: _new,
        name: name
      });

      observer.onCompleted();
    }).run({ async: true });
  });
})
.do(function (d) {
  var r = d.new.hz / d.old.hz;
  var p = (d.new.hz - d.old.hz) / d.old.hz;
  output.push([d.name, d.old.hz, d.old.stats.rme, d.new.hz, d.new.stats.rme, r, p]);
})
.map(function (d) {
  var oldHz = d.old.hz;
  var newHz = d.new.hz;
  var r = newHz / oldHz;
  var p = 100 * ((newHz - oldHz) / oldHz);
  var oldRme = ' (\xb1' + d.old.stats.rme.toFixed(2) + '%)';
  var newRme = ' (\xb1' + d.new.stats.rme.toFixed(2) + '%)';
  return row(40, 30, 30, 15, 15)(d.name, formatNumber(oldHz) + oldRme,
    formatNumber(newHz) + newRme, formatNumber(r) + 'x', formatNumber(p, 1) + '%');
})
.subscribe(console.log.bind(console), function (err) {
  if (err.stack === undefined) {
    console.log(err);
  } else {
    console.log(err.stack);
  }
}, function () {
  var csv = process.argv.indexOf('--csv');
  if (csv !== -1) {
    var filename = process.argv[csv + 1];
    fs.writeFileSync(filename, output.map(function (o) {
      return o.map(function (v) {
        return JSON.stringify(v);
      }).join(',');
    }).join('\n'), { encoding: 'utf8' });
  }
});<|endoftext|>


<commit_before>'use strict';

/**
 * Module dependencies.
 */

var mongoose = require('mongoose'),
	errorHandler = require('./errors.server.controller'),
	Product = mongoose.model('Product'),
	Collection = mongoose.model('Collection'),
	Tag = mongoose.model('Tag'),
	Article = mongoose.model('Article'),
	Inventory = mongoose.model('Inventory'),
	LocalStore = mongoose.model('LocalStore'),
	SiteContent = mongoose.model('SiteContent'),
	nodemailer = require('nodemailer'),
	async = require('async'),
	config = require('../../config/config'),
	_ = require('lodash');
var	orderController = require('../../app/controllers/order.server.controller');
var	DiscountCode = mongoose.model('DiscountCode');

exports.index = function(req, res) {
	SiteContent.findOne({'visible':true,'_id':'socialPage'}).exec(function(err,content){
		res.render('index', {
			user: req.user || null,
			content: content,
		});
	 });
};

var translateDiscountCode = function(discountObject){
	var description = 'Use o código: '+ discountObject._id + ' para o desconto de ';

	switch(discountObject.typeForPay){
		case 'value':
			description = description +'R$ '+discountObject.valueOf;
			break;
		case 'percent':
			description = description +discountObject.valueOf+'% ';
			break;
	}

	switch(discountObject.ordersValidation){
		case 'all':
			description = description +', válido para qualquer produto';
			break;
		case 'overValue':
			description = description +', válido nas compras acima de R$' + discountObject.overValueOf ;
			break;
		case 'collections':
			description = description +', válido nas coleções '+ discountObject.collectionsSlug.toString();
			break;
		case 'specificProduct':
			description = description + ', válido para os produtos '+ discountObject.productSlugs.toString();
			break;
	}
	switch(discountObject.whereApply){
		case 'oncePerOrder':
			description = description + ';  Desconto válido apenas para cada compra.';
			break;
		case 'toEveryProduct':
			description = description + ';  Desconto válido para cada itém comrado.';
			break;
	}
	return description;

};

exports.mainMenu = function(req,res){
	async.waterfall([
	function(done) {
		//products out of stock
		Inventory.aggregate([{$group:{_id:'$product',inventories:{$push:'$$ROOT'},count:{$sum:1}}}])
			 		.exec(function(err, result){
		 			if(err){
						return res.status(400).send({
							message: err
						});
					}
					var productsId = [];
					result.forEach(function(product){
						var isToAdd= true;
						product.inventories.forEach(function(inventory){
							if(!inventory.orderOutOfStock&&(inventory.sellInOutOfStock||inventory.quantity>0)){
								isToAdd = false;
							}
						});
						if(isToAdd)
							productsId.push(product._id.oid);
					});
					productsId = productsId.slice(0,5);
					Product.find({ '_id':{$in:productsId}})
						.where('onLineVisible').equals(true)
					   	.select('-_id title slug ')
					   	.exec(function(err,products){
					   		if(err){
								return res.status(400).send({
									message: err
								});
							}
							var outOFStock = [];
							if(products){
					            products.forEach(function(product) {
									outOFStock.push({'slug':product.slug,'title':product.title});
					            });
							}
							var response = {'loja':{collection:{}}};
							if(outOFStock.length>0){
								response.loja.collection['Fora de estoque'] = outOFStock;
							}
							done(err,response);
					   	});
   		});
	},
	function(response,done) {
		Collection.find({'onLineVisible':true}).or([{'gender':true},{'mainMenu':true}])
		.select('-_id slug gender otherProducts')
		.exec(function(err, collectionsSlugs){
			if(err){
				return res.status(400).send({
					message: err
				});
			}
			var collectionsSlugsMapped = [];
			var collectionSlugGender = [];
			var collectionsSlugsNotGender = [];
			var collectionsSlugsOtherProducts = [];

			collectionsSlugs.forEach(function(collection){
				if(collection.gender)
					collectionSlugGender.push(collection.slug);
				else if(collection.otherProducts)
					collectionsSlugsOtherProducts.push(collection.slug);
				else
					collectionsSlugsNotGender.push(collection.slug);
			});
			collectionsSlugsMapped = _.union(collectionSlugGender,collectionsSlugsOtherProducts,collectionsSlugsNotGender);
			//todo with inventory?
			Inventory.find({'orderOutOfStock':false}).or([{'quantity':{$gt:0}},{'sellInOutOfStock':true}])
					.distinct('product.$id')
			 		.exec(function(err, productsId){

				Product.find({ '_id':{$in:productsId}})
						.where('onLineVisible').equals(true)
					   	.where('collectionsSlugs').in(collectionsSlugsMapped)
					   	.select('-_id collectionsSlugs slug title types')
					   	.exec(function(err,products){
							var gender = {};
							var otherProducts = {};
							var collection = response.loja.collection;
							if(products){
					            products.forEach(function(product) {
						       		product.collectionsSlugs.forEach(function(collectionSlug){
							   			if(collectionSlugGender.indexOf(collectionSlug)>=0){
							   				if(!gender[collectionSlug])
							   					gender[collectionSlug] = [];
											gender[collectionSlug] = gender[collectionSlug].concat(product.types);

											gender[collectionSlug] = _.uniq(gender[collectionSlug], true);
							   			}else if(collectionsSlugsOtherProducts.indexOf(collectionSlug)>=0){
											if(!otherProducts[collectionSlug])
												otherProducts[collectionSlug] = [];
											otherProducts[collectionSlug].push({'slug':product.slug,'title':product.title});
											otherProducts[collectionSlug] = _.uniq(otherProducts[collectionSlug], true);
							   			}else if(collectionsSlugsNotGender.indexOf(collectionSlug)>=0){
							   				if(!collection[collectionSlug])
												collection[collectionSlug] = [];
											gender[collectionSlug] = gender[collectionSlug].concat(product.types);
											collection[collectionSlug] = _.uniq(collection[collectionSlug], true);
							   			}
							   		});
					            });
							}
							response.loja.gender = gender;
							response.loja.collection = collection;
							response.loja.otherProducts = otherProducts;
				            done(err, response);
	        				// res.json(mainMenu);

				});
			});

		});
	},
	function(response, done) {
		LocalStore.find({'onLineVisible':true}).exec(function(err,localStores){
			if (!err&&localStores) {
				response.localStores = {};
				var localStoresSlugs = [];
				localStores.forEach(function(store){
					localStoresSlugs.push(store.slug);
					response.localStores[store.slug] = {'title':store.title};
				});
				// Inventory.find({'orderOutOfStock':false}).or([{'quantity':{$gt:0}},{'sellInOutOfStock':true}])
				// 	.distinct('product.$id')
			 // 		.exec(function(err, productsId){
				Product.find({})
				// .find({ '_id':{$in:productsId}})
						.where('onLineVisible').equals(true)
					   	.where('localStoresSlugs').in(localStoresSlugs)
					   	.select('-_id localStoresSlugs type')
					   	.exec(function(err,products){
					   		products.forEach(function(product){
					   			product.localStoresSlugs.forEach(function(storeSlug){
					   				if(response.localStores[storeSlug].products)
										response.localStores[storeSlug].products.push(product.type);
									else{
										response.localStores[storeSlug].products = [];
										response.localStores[storeSlug].products.push(product.type);
									}
					   			});

					   		});
				   		  	done(err, response);
							// res.json(response);
				   	});
			   	// });
				// res.send({
				// 	message: 'An email has been sent to ' + user.email + ' with further instructions.'
				// });
			}else if(err){
				done(err);
			}else{
				done(err, response);
			}

		});
	},function(response, done) {
		DiscountCode.findOne({onLineVisible:true,active:true,
			$and:[{$or:[{noTimesLimits:true},{timesLeft:{$gt:0}}]},
					{$or:[{noDateLimits:true},{endDate:{$lte:new Date()}}]}
				 ]
			})
			.exec(function(err,discountObject){
				if (!err&&discountObject) {
					var description = translateDiscountCode(discountObject);
					response.discount = discountObject;
					response.discount.description = discountObject.description||description;
					res.json(response);
				}else if(err){
					done(err);
				}else{
					res.json(response);
				}
			});
	}], function(err) {
		if(err){
			return res.status(400).send({
				message: err
			});
		}
	});
};

exports.mainPage = function(req,res){
	async.waterfall([
	function(done) {
		 SiteContent.findOne({'visible':true,'_id':'frontPage'}).exec(function(err,content){
		 	if(err){
				done(err);
			}else{
				if(content)
			 		done(err,{'content':content});
			 	else
			 		done(err,{'content':new SiteContent()});
			}
		 });
	},function(response,done) {
		 Collection.find({'onLineVisible':true}).or([{'gender':true},{'front':true}])
		.select('-_id title description slug image front gender')
		.exec(function(err, collectionsSlugs){
		 	if(err){
				done(err);
			}else{
				if(collectionsSlugs){
					response.collections = collectionsSlugs;
			 		done(err,response);
				}
			}
		 });
	},function(response,done) {
		 LocalStore.find({'onLineVisible':true})
		 .select('-_id images title slug')
		 .exec(function(err,localStores){
		 	if(err){
				done(err);
			}else{
				if(localStores){
					response.localStores = localStores;
			 		done(err,response);
				}
			}
		 });
	},function(response, done) {
			Inventory.find({'orderOutOfStock':false}).or([{'quantity':{$gt:0}},{'sellInOutOfStock':true}])
						.distinct('product.$id')
				 		.exec(function(err, productsId){

					Product.find({ '_id':{$in:productsId}})
							.where('onLineVisible').equals(true)
						   	.where('collectionsSlugs').in(['destaque'])
						   	.select('-_id newProduct slug price title priceFormatted priceOldFormatted priceCompareWith images')
						   	// .limit(10)
						   	.exec(function(err,products){
						   		if(!err){
			   						products.forEach(function(product,indexProduct){
										var images = [];

										var frontImages = product.images.filter(function(image,indexImage){
											return image.frontImage;
										});
										var notFrontImage = product.images.filter(function(image,indexImage){
											return !image.frontImage;
										});

										if(frontImages.length>0){
											images = _.union(frontImages.slice(0,1),notFrontImage.slice(0,1));
										}else{
											images = notFrontImage.slice(0,2);
										}
										products[indexProduct].images = images;
										products[indexProduct].inventories = [];
									});
							   		response.destaque = products;
									res.json(response);
									//done(err,response);
								}else{
									done(err);
								}
				   	});
			   });

	}], function(err) {
		if(err){
			return res.status(400).send({
				message: err
			});
		}
	});
};

/**
 * Forgot for reset password (forgot POST)
 */
exports.sendContact = function(req, res, next) {
	async.waterfall([
		// Lookup user by email
		function(done) {
			if(req.body.userContact.email&&req.body.userContact.content&&req.body.userContact.subject){

				res.render('templates/contact-email', {
					name: req.body.userContact.name,
					email: req.body.userContact.email,
					phone: req.body.userContact.phone,
					content: req.body.userContact.content,
					appName: config.app.title
				}, function(err, emailHTML) {
					done(err, emailHTML, req.body.userContact);
				});
			}else{
				return res.status(400).send({
					message: 'Por favor preencha os dados corretamente.'
				});
			}

		},
		// If valid email, send reset email using service
		function(emailHTML, userContact, done) {
			var smtpTransport = nodemailer.createTransport(config.mailer.options);
			var mailOptions = {
				to: config.mailer.from,
				from: config.mailer.from,
				subject: 'Contato - '+userContact.subject,
				html: emailHTML
			};
			smtpTransport.sendMail(mailOptions, function(err) {
				if (!err) {
					res.send({
						message: 'Obrigado por entrar em contato a equipe '+config.app.title+' agradece!'
					});
				}

				done(err);
			});
		}
	], function(err) {
		if(err){
			return res.status(400).send({
				message: err
			});
		}
	});
};<commit_msg>rebuild menu<commit_after>'use strict';

/**
 * Module dependencies.
 */

var mongoose = require('mongoose'),
	errorHandler = require('./errors.server.controller'),
	Product = mongoose.model('Product'),
	Collection = mongoose.model('Collection'),
	Tag = mongoose.model('Tag'),
	Article = mongoose.model('Article'),
	Inventory = mongoose.model('Inventory'),
	LocalStore = mongoose.model('LocalStore'),
	SiteContent = mongoose.model('SiteContent'),
	nodemailer = require('nodemailer'),
	async = require('async'),
	config = require('../../config/config'),
	_ = require('lodash');
var	orderController = require('../../app/controllers/order.server.controller');
var	DiscountCode = mongoose.model('DiscountCode');

exports.index = function(req, res) {
	SiteContent.findOne({'visible':true,'_id':'socialPage'}).exec(function(err,content){
		res.render('index', {
			user: req.user || null,
			content: content,
		});
	 });
};

var translateDiscountCode = function(discountObject){
	var description = 'Use o código: '+ discountObject._id + ' para o desconto de ';

	switch(discountObject.typeForPay){
		case 'value':
			description = description +'R$ '+discountObject.valueOf;
			break;
		case 'percent':
			description = description +discountObject.valueOf+'% ';
			break;
	}

	switch(discountObject.ordersValidation){
		case 'all':
			description = description +', válido para qualquer produto';
			break;
		case 'overValue':
			description = description +', válido nas compras acima de R$' + discountObject.overValueOf ;
			break;
		case 'collections':
			description = description +', válido nas coleções '+ discountObject.collectionsSlug.toString();
			break;
		case 'specificProduct':
			description = description + ', válido para os produtos '+ discountObject.productSlugs.toString();
			break;
	}
	switch(discountObject.whereApply){
		case 'oncePerOrder':
			description = description + ';  Desconto válido apenas para cada compra.';
			break;
		case 'toEveryProduct':
			description = description + ';  Desconto válido para cada itém comrado.';
			break;
	}
	return description;

};

exports.mainMenu = function(req,res){
	async.waterfall([
	function(done) {
		//products out of stock
		Inventory.aggregate([{$group:{_id:'$product',inventories:{$push:'$$ROOT'},count:{$sum:1}}}])
			 		.exec(function(err, result){
		 			if(err){
						return res.status(400).send({
							message: err
						});
					}
					var productsId = [];
					result.forEach(function(product){
						var isToAdd= true;
						product.inventories.forEach(function(inventory){
							if(!inventory.orderOutOfStock&&(inventory.sellInOutOfStock||inventory.quantity>0)){
								isToAdd = false;
							}
						});
						if(isToAdd)
							productsId.push(product._id.oid);
					});
					productsId = productsId.slice(0,5);
					Product.find({ '_id':{$in:productsId}})
						.where('onLineVisible').equals(true)
					   	.select('-_id title slug ')
					   	.exec(function(err,products){
					   		if(err){
								return res.status(400).send({
									message: err
								});
							}
							var outOFStock = [];
							if(products){
					            products.forEach(function(product) {
									outOFStock.push({'slug':product.slug,'title':product.title});
					            });
							}
							var response = {'loja':{collection:{}}};
							// if(outOFStock.length>0){
							// 	response.loja.collection['Fora de estoque'] = outOFStock;
							// }
							done(err,response);
					   	});
   		});
	},
	function(response,done) {
		Collection.find({'onLineVisible':true}).or([{'gender':true},{'mainMenu':true}])
		.select('-_id slug gender otherProducts')
		.exec(function(err, collectionsSlugs){
			if(err){
				return res.status(400).send({
					message: err
				});
			}
			var collectionsSlugsMapped = [];
			var collectionSlugGender = [];
			var collectionsSlugsNotGender = [];
			var collectionsSlugsOtherProducts = [];

			collectionsSlugs.forEach(function(collection){
				if(collection.gender)
					collectionSlugGender.push(collection.slug);
				else if(collection.otherProducts)
					collectionsSlugsOtherProducts.push(collection.slug);
				else
					collectionsSlugsNotGender.push(collection.slug);
			});
			collectionsSlugsMapped = _.union(collectionSlugGender,collectionsSlugsOtherProducts,collectionsSlugsNotGender);
			//todo with inventory?
			Inventory.aggregate([
                     { $match: {'orderOutOfStock':false,$or:[{'quantity':{$gt:0}},{'sellInOutOfStock':true}]} },
                     { $group: { _id: '$genderSlug', models: { $push: '$type' } } },
                   ],function(err, reponses){
                   			var gender = {};
							var otherProducts = {};
							var collection = response.loja.collection;
							reponses.forEach(function(elem){
								if(collectionSlugGender.indexOf(elem._id)>=0){
									gender[elem._id] = elem.models;
								}
								if(collectionsSlugsOtherProducts.indexOf(elem._id)>=0){
									otherProducts[elem._id] = elem.models;
								}
								if(collectionsSlugsNotGender.indexOf(elem._id)>=0){
									collection[elem._id] = elem.models;
								}
							});

							response.loja.gender = gender;
							response.loja.collection = collection;
							response.loja.otherProducts = otherProducts;
				            done(err, response);
	        				// res.json(mainMenu);
			});

		});
	},
	function(response, done) {
		LocalStore.find({'onLineVisible':true}).exec(function(err,localStores){
			if (!err&&localStores) {
				response.localStores = {};
				var localStoresSlugs = [];
				localStores.forEach(function(store){
					localStoresSlugs.push(store.slug);
					response.localStores[store.slug] = {'title':store.title};
				});
				// Inventory.find({'orderOutOfStock':false}).or([{'quantity':{$gt:0}},{'sellInOutOfStock':true}])
				// 	.distinct('product.$id')
			 // 		.exec(function(err, productsId){
				Product.find({})
				// .find({ '_id':{$in:productsId}})
						.where('onLineVisible').equals(true)
					   	.where('localStoresSlugs').in(localStoresSlugs)
					   	.select('-_id localStoresSlugs type')
					   	.exec(function(err,products){
					   		products.forEach(function(product){
					   			product.localStoresSlugs.forEach(function(storeSlug){
					   				if(response.localStores[storeSlug].products)
										response.localStores[storeSlug].products.push(product.type);
									else{
										response.localStores[storeSlug].products = [];
										response.localStores[storeSlug].products.push(product.type);
									}
					   			});

					   		});
				   		  	done(err, response);
							// res.json(response);
				   	});
			   	// });
				// res.send({
				// 	message: 'An email has been sent to ' + user.email + ' with further instructions.'
				// });
			}else if(err){
				done(err);
			}else{
				done(err, response);
			}

		});
	},function(response, done) {
		DiscountCode.findOne({onLineVisible:true,active:true,
			$and:[{$or:[{noTimesLimits:true},{timesLeft:{$gt:0}}]},
					{$or:[{noDateLimits:true},{endDate:{$lte:new Date()}}]}
				 ]
			})
			.exec(function(err,discountObject){
				if (!err&&discountObject) {
					var description = translateDiscountCode(discountObject);
					response.discount = discountObject;
					response.discount.description = discountObject.description||description;
					res.json(response);
				}else if(err){
					done(err);
				}else{
					res.json(response);
				}
			});
	}], function(err) {
		if(err){
			return res.status(400).send({
				message: err
			});
		}
	});
};

exports.mainPage = function(req,res){
	async.waterfall([
	function(done) {
		 SiteContent.findOne({'visible':true,'_id':'frontPage'}).exec(function(err,content){
		 	if(err){
				done(err);
			}else{
				if(content)
			 		done(err,{'content':content});
			 	else
			 		done(err,{'content':new SiteContent()});
			}
		 });
	},function(response,done) {
		 Collection.find({'onLineVisible':true}).or([{'gender':true},{'front':true}])
		.select('-_id title description slug image front gender')
		.exec(function(err, collectionsSlugs){
		 	if(err){
				done(err);
			}else{
				if(collectionsSlugs){
					response.collections = collectionsSlugs;
			 		done(err,response);
				}
			}
		 });
	},function(response,done) {
		 LocalStore.find({'onLineVisible':true})
		 .select('-_id images title slug')
		 .exec(function(err,localStores){
		 	if(err){
				done(err);
			}else{
				if(localStores){
					response.localStores = localStores;
			 		done(err,response);
				}
			}
		 });
	},function(response, done) {
			Inventory.find({'orderOutOfStock':false}).or([{'quantity':{$gt:0}},{'sellInOutOfStock':true}])
						.distinct('product.$id')
				 		.exec(function(err, productsId){

					Product.find({ '_id':{$in:productsId}})
							.where('onLineVisible').equals(true)
						   	.where('collectionsSlugs').in(['destaque'])
						   	.select('-_id newProduct slug price title priceFormatted priceOldFormatted priceCompareWith images')
						   	// .limit(10)
						   	.exec(function(err,products){
						   		if(!err){
			   						products.forEach(function(product,indexProduct){
										var images = [];

										var frontImages = product.images.filter(function(image,indexImage){
											return image.frontImage;
										});
										var notFrontImage = product.images.filter(function(image,indexImage){
											return !image.frontImage;
										});

										if(frontImages.length>0){
											images = _.union(frontImages.slice(0,1),notFrontImage.slice(0,1));
										}else{
											images = notFrontImage.slice(0,2);
										}
										products[indexProduct].images = images;
										products[indexProduct].inventories = [];
									});
							   		response.destaque = products;
									res.json(response);
									//done(err,response);
								}else{
									done(err);
								}
				   	});
			   });

	}], function(err) {
		if(err){
			return res.status(400).send({
				message: err
			});
		}
	});
};

/**
 * Forgot for reset password (forgot POST)
 */
exports.sendContact = function(req, res, next) {
	async.waterfall([
		// Lookup user by email
		function(done) {
			if(req.body.userContact.email&&req.body.userContact.content&&req.body.userContact.subject){

				res.render('templates/contact-email', {
					name: req.body.userContact.name,
					email: req.body.userContact.email,
					phone: req.body.userContact.phone,
					content: req.body.userContact.content,
					appName: config.app.title
				}, function(err, emailHTML) {
					done(err, emailHTML, req.body.userContact);
				});
			}else{
				return res.status(400).send({
					message: 'Por favor preencha os dados corretamente.'
				});
			}

		},
		// If valid email, send reset email using service
		function(emailHTML, userContact, done) {
			var smtpTransport = nodemailer.createTransport(config.mailer.options);
			var mailOptions = {
				to: config.mailer.from,
				from: config.mailer.from,
				subject: 'Contato - '+userContact.subject,
				html: emailHTML
			};
			smtpTransport.sendMail(mailOptions, function(err) {
				if (!err) {
					res.send({
						message: 'Obrigado por entrar em contato a equipe '+config.app.title+' agradece!'
					});
				}

				done(err);
			});
		}
	], function(err) {
		if(err){
			return res.status(400).send({
				message: err
			});
		}
	});
};<|endoftext|>


<commit_before>'use strict';

const fse = require('fs-extra');
const path = require('path');
const ejs = require('ejs');
const utils = require('../cli/utils');
const pkg = require('../package.json');
const { Storage } = require('@google-cloud/storage');
const storage = new Storage();
const buildPath = 'build';
const cordova = utils.cordova(buildPath);

const BUILD_NUMBER = parseInt(process.env.GITHUB_RUN_NUMBER || '1') + 2530;
const BRANCH = process.env.GITHUB_REF && process.env.GITHUB_REF.replace('refs/heads/', '');

async function run() {
  const config = ejs.render(fse.readFileSync('config.xml.template', 'utf-8'), {
    widget: {
      id: 'com.coinspace.app',
      version: pkg.version,
      androidVersionCode: BUILD_NUMBER,
    },
  });
  fse.writeFileSync(path.resolve(buildPath, 'config.xml'), config);

  /* eslint-disable max-len */
  cordova('platform add android@8.1.0');
  cordova('plugin add cordova-custom-config@5.1.0');
  cordova('plugin add cordova-plugin-geolocation@4.0.2');
  cordova('plugin add phonegap-plugin-barcodescanner@8.1.0');
  cordova('plugin add cordova-plugin-dialogs@2.0.2');
  cordova('plugin add cordova-plugin-inappbrowser@4.0.0');
  cordova('plugin add cordova-plugin-x-socialsharing@5.6.8');
  cordova('plugin add cordova-plugin-fingerprint-aio@3.0.1');
  cordova('plugin add cordova-plugin-customurlscheme@5.0.1 --variable URL_SCHEME=coinspace');
  cordova('plugin add https://github.com/CoinSpace/cordova-plugin-zendesk#8fcf90c399568895ba8b6e3e858727d275b0f29f');
  cordova('plugin add cordova-plugin-splashscreen@5.0.4');
  cordova('plugin add cordova-plugin-whitelist@1.3.4');
  cordova('plugin add cordova-plugin-safariviewcontroller@1.6.0');
  cordova('plugin add cordova-plugin-inapp-review@1.1.0 --variable PLAY_CORE_VERSION=1.8.0');

  if (process.env.RELEASE) {
    cordova('build android --release');
    utils.shell(
      'jarsigner -sigalg SHA1withRSA -digestalg SHA1 -keystore ../release.keystore \
      -storepass coinspace platforms/android/app/build/outputs/apk/release/app-release-unsigned.apk coinspace',
      { cwd: buildPath }
    );
    utils.shell(
      'zipalign -f 4 platforms/android/app/build/outputs/apk/release/app-release-unsigned.apk \
      ../deploy/coinspace-release.apk',
      { cwd: buildPath }
    );
    const destination = `${pkg.version}-${BRANCH || 'local'}/${pkg.name}-${process.env.BUILD_PLATFORM}-${pkg.version}.apk`;
    await storage.bucket(process.env.GOOGLE_CLOUD_BUCKET).upload('deploy/coinspace-release.apk', { destination });
  } else {
    cordova('build android');
  }
}

process.on('unhandledRejection', (err) => {
  throw err;
});

run();
<commit_msg>chore(android): fix build<commit_after>'use strict';

const fse = require('fs-extra');
const path = require('path');
const ejs = require('ejs');
const utils = require('../cli/utils');
const pkg = require('../package.json');
const { Storage } = require('@google-cloud/storage');
const storage = new Storage();
const buildPath = 'build';
const cordova = utils.cordova(buildPath);

const BUILD_NUMBER = parseInt(process.env.GITHUB_RUN_NUMBER || '1') + 2530;
const BRANCH = process.env.GITHUB_REF && process.env.GITHUB_REF.replace('refs/heads/', '');

async function run() {
  const config = ejs.render(fse.readFileSync('config.xml.template', 'utf-8'), {
    widget: {
      id: 'com.coinspace.app',
      version: pkg.version,
      androidVersionCode: BUILD_NUMBER,
    },
  });
  fse.writeFileSync(path.resolve(buildPath, 'config.xml'), config);

  /* eslint-disable max-len */
  cordova('platform add android@8.1.0');
  cordova('plugin add cordova-plugin-androidx@3.0.0');
  cordova('plugin add cordova-plugin-androidx-adapter@1.1.3');
  cordova('plugin add cordova-custom-config@5.1.0');
  cordova('plugin add cordova-plugin-geolocation@4.0.2');
  cordova('plugin add phonegap-plugin-barcodescanner@8.1.0 --variable ANDROID_SUPPORT_V4_VERSION=28.0.0');
  cordova('plugin add cordova-plugin-dialogs@2.0.2');
  cordova('plugin add cordova-plugin-inappbrowser@4.0.0');
  cordova('plugin add cordova-plugin-x-socialsharing@5.6.8');
  cordova('plugin add cordova-plugin-fingerprint-aio@3.0.1');
  cordova('plugin add cordova-plugin-customurlscheme@5.0.1 --variable URL_SCHEME=coinspace');
  cordova('plugin add https://github.com/CoinSpace/cordova-plugin-zendesk#8fcf90c399568895ba8b6e3e858727d275b0f29f');
  cordova('plugin add cordova-plugin-splashscreen@5.0.4');
  cordova('plugin add cordova-plugin-whitelist@1.3.4');
  cordova('plugin add cordova-plugin-safariviewcontroller@1.6.0');
  cordova('plugin add cordova-plugin-inapp-review@1.1.0 --variable PLAY_CORE_VERSION=1.8.0');

  if (process.env.RELEASE) {
    cordova('build android --release');
    utils.shell(
      'jarsigner -sigalg SHA1withRSA -digestalg SHA1 -keystore ../release.keystore \
      -storepass coinspace platforms/android/app/build/outputs/apk/release/app-release-unsigned.apk coinspace',
      { cwd: buildPath }
    );
    utils.shell(
      'zipalign -f 4 platforms/android/app/build/outputs/apk/release/app-release-unsigned.apk \
      ../deploy/coinspace-release.apk',
      { cwd: buildPath }
    );
    const destination = `${pkg.version}-${BRANCH || 'local'}/${pkg.name}-${process.env.BUILD_PLATFORM}-${pkg.version}.apk`;
    await storage.bucket(process.env.GOOGLE_CLOUD_BUCKET).upload('deploy/coinspace-release.apk', { destination });
  } else {
    cordova('build android');
  }
}

process.on('unhandledRejection', (err) => {
  throw err;
});

run();
<|endoftext|>


<commit_before>'use strict';

angular
.module('app.controllers')
.controller('TinyMceCtrl', function($scope) {
	$scope.getTinyMceConfiguration = function(field) {
		console.log(field);
		return tinymceConfig(
			field.validation.allowedHtml,
			field.validation.maxlength || false,
			field.validation.readOnly
		);
	};

	/**
	 * Returns a tinymce.init() compatible configuration object based on the
	 * field's allowed tags and maxlength.
	 *
	 * @TODO: Use tinymce.Editor.addButton() to add buttons for <blockquote> and <q>
	 * that automatically trigger a popup asking for `cite` info, so users can add
	 * attributed notes in the notes field.
	 *
	 * Also add a button for the character counter, which means (probably)figuring
	 * out a property that angular can observe to make falsey when over maxlength.
	 */
	var tinymceConfig = function(allowedTags, charLimit, disabled) {
		var toolbarItems = [],
			formatsListItems = [],
			allowsBlockFormatting = false,
			allowsInlineFormatting = false;

		// Build the items in formatsListItems based on the allowedTags. We do want
		// to add the formats to formatsListItems in the order they're defined in
		// the object literal below, so it's reassuring to know that object member
		// enumeration is in fact deterministic in ES6.
		var tagsToFormats = {
			'h1': {title: 'Heading', format: 'h1'},
			'h2': {title: 'Subheading', format: 'h2'},
			'p': {title: 'Standard Paragraph', format: 'p'},
			'code': {title: 'Code', icon: 'code', format: 'code'},
			'sup': {title: 'Superscript', icon: 'superscript', format: 'superscript'},
			'sub': {title: 'Subscript', icon: 'subscript', format: 'subscript'},
		};

		var tagsToButtonNames = {
			'em': 'italic',
			'strong': 'bold',
			'ul': 'bullist',
			'ol': 'numlist',
			'blockquote': 'blockquote'
		};

		for(var tag in tagsToFormats) {
			if(allowedTags.indexOf(tag) !== -1) {
				formatsListItems.push(tagsToFormats[tag]);
			}
		}

		// Add format picker to the toolbar
		toolbarItems.push('styleselect');
		toolbarItems.push('spacer');

		// Add inline formatting buttons
		['strong','em'].forEach(function(tag) {
			if(allowedTags.indexOf(tag) !== -1) {
				toolbarItems.push(tagsToButtonNames[tag]);
				allowsInlineFormatting = true;
			}
		});

		if(allowsInlineFormatting) {
			toolbarItems.push('spacer');
		}

		// Add Link buttons
		if(allowedTags.indexOf('a') !== -1) {
			toolbarItems.push('link');
			toolbarItems.push('anchor');
			toolbarItems.push('spacer');
		}

		// Add block formatting buttons.
		['ul', 'ol', 'blockquote'].forEach(function(tag) {
			if(allowedTags.indexOf(tag) !== -1) {
				toolbarItems.push(tagsToButtonNames[tag]);
				allowsBlockFormatting = true;
			}
		});

		if(allowsBlockFormatting) {
			toolbarItems.push('spacer');
		}

		// HTML EDITING.
		toolbarItems.push('code');

		// Note: DO NOT include the importcss plugin below,
		// as a bug makes it incompatible with the styleselect button.
		return {
			selector: 'textarea',
			theme: 'modern',
			plugins: [
				'anchor autolink autoresize autosave charmap code contextmenu emoticons',
				'lists link noneditable paste save searchreplace tabfocus table',
				'template textpattern'
			],
			toolbar: toolbarItems.join(' '),
			browser_spellcheck : true,
			fix_list_elements : true,
			image_advtab: true,
			menubar: false,
			statusbar: false,
			object_resizing : false,
			templates: [],
			valid_elements: allowedTags.join(' '), // the array from the api
			relative_urls: false,
			style_formats: formatsListItems,
			style_formats_merge: false,
			autoresize_min_height: 175,
			readonly: disabled
		};
	};
});

<commit_msg>Fix bad valid_elements tinyMCE configuration<commit_after>'use strict';

angular
.module('app.controllers')
.controller('TinyMceCtrl', function($scope) {
	$scope.getTinyMceConfiguration = function(field) {
		return tinymceConfig(
			field.validation.allowedHtml,
			field.validation.maxlength || false,
			field.validation.readOnly
		);
	};

	/**
	 * Returns a tinymce.init() compatible configuration object based on the
	 * field's allowed tags and maxlength.
	 *
	 * @TODO: Use tinymce.Editor.addButton() to add buttons for <blockquote> and <q>
	 * that automatically trigger a popup asking for `cite` info, so users can add
	 * attributed notes in the notes field.
	 *
	 * Also add a button for the character counter, which means (probably)figuring
	 * out a property that angular can observe to make falsey when over maxlength.
	 */
	var tinymceConfig = function(allowedTags, charLimit, disabled) {
		var toolbarItems = [],
			formatsListItems = [],
			allowsBlockFormatting = false,
			allowsInlineFormatting = false;

		// Build the items in formatsListItems based on the allowedTags. We do want
		// to add the formats to formatsListItems in the order they're defined in
		// the object literal below, so it's reassuring to know that object member
		// enumeration is in fact deterministic in ES6.
		var tagsToFormats = {
			'h1': {title: 'Heading', format: 'h1'},
			'h2': {title: 'Subheading', format: 'h2'},
			'p': {title: 'Standard Paragraph', format: 'p'},
			'code': {title: 'Code', icon: 'code', format: 'code'},
			'sup': {title: 'Superscript', icon: 'superscript', format: 'superscript'},
			'sub': {title: 'Subscript', icon: 'subscript', format: 'subscript'},
		};

		var tagsToButtonNames = {
			'em': 'italic',
			'strong': 'bold',
			'ul': 'bullist',
			'ol': 'numlist',
			'blockquote': 'blockquote'
		};

		for(var tag in tagsToFormats) {
			if(allowedTags.indexOf(tag) !== -1) {
				formatsListItems.push(tagsToFormats[tag]);
			}
		}

		// Add format picker to the toolbar
		toolbarItems.push('styleselect');
		toolbarItems.push('spacer');

		// Add inline formatting buttons
		['strong','em'].forEach(function(tag) {
			if(allowedTags.indexOf(tag) !== -1) {
				toolbarItems.push(tagsToButtonNames[tag]);
				allowsInlineFormatting = true;
			}
		});

		if(allowsInlineFormatting) {
			toolbarItems.push('spacer');
		}

		// Add Link buttons
		if(allowedTags.indexOf('a') !== -1) {
			toolbarItems.push('link');
			toolbarItems.push('anchor');
			toolbarItems.push('spacer');
		}

		// Add block formatting buttons.
		['ul', 'ol', 'blockquote'].forEach(function(tag) {
			if(allowedTags.indexOf(tag) !== -1) {
				toolbarItems.push(tagsToButtonNames[tag]);
				allowsBlockFormatting = true;
			}
		});

		if(allowsBlockFormatting) {
			toolbarItems.push('spacer');
		}

		// HTML EDITING.
		toolbarItems.push('code');

		// Note: DO NOT include the importcss plugin below,
		// as a bug makes it incompatible with the styleselect button.
		return {
			selector: 'textarea',
			theme: 'modern',
			plugins: [
				'anchor autolink autoresize autosave charmap code contextmenu emoticons',
				'lists link noneditable paste save searchreplace tabfocus table',
				'template textpattern'
			],
			toolbar: toolbarItems.join(' '),
			browser_spellcheck : true,
			fix_list_elements : true,
			image_advtab: true,
			menubar: false,
			statusbar: false,
			object_resizing : false,
			templates: [],
			valid_elements: allowedTags.join(','), // the array from the api
			relative_urls: false,
			style_formats: formatsListItems,
			style_formats_merge: false,
			autoresize_min_height: 175,
			readonly: disabled
		};
	};
});

<|endoftext|>


<commit_before>// artists.controller.js
//==============================================

//====== Define depencies ======
const Artist = require('./artist.model'),
  moment = require('moment'),
  underscore = require('underscore'),
  multer = require('multer'),
  sharp = require('sharp'),
  nodemailer = require('nodemailer'),
  userMiddlewares = require('../users/user.middlewares');

//====== Export method ======
module.exports = {
  showArtists: showArtists,
  getArtistsIndex: getArtistsIndex,
  showSingle: showSingle,
  showCreate: showCreate,
  processCreate: processCreate,
  processSubmit: processSubmit,
  showEdit: showEdit,
  processEdit: processEdit,
  deleteArtist: deleteArtist,
  getArtistsGeojson: getArtistsGeojson,
  uploadThumbnail: uploadThumbnail
};

//====== Methods ======

/**
 * [showArtists Show a list of all artists]
 */
function showArtists (req, res) {
  Artist.find({}, (err, artists) => {

    var publishedArtists = artists.filter(function(item) {
      if(item.published === true) {
        return item;
      }
    });

    const locals = {
      artists: artists,
      moment: moment,
      success: req.flash('success'),
      layout: 'admin',
      title: 'All artists (' + publishedArtists.length + ' / ' + artists.length + ')',
      slug: 'page-admin'
    };

    if(err) {
      res.status(404);
      res.send('Artists not found!');
    }

    res.render('pages/artists/artists', locals);
  });
}

/**
 * [showSingle Show a single artist]
 */
function showSingle (req, res) {
  // get a single artist
  Artist.findOne({ slug: req.params.slug }, (err, artist) => {
    if(err) {
      res.status(404);
      res.send(`Artist ${req.params.slug} cannot be found!`);
    }

    res.json(artist);
  });
}

/**
 * [showCreate Show artist creation page]
 */
function showCreate(req, res) {
  const locals = {
    errors: req.flash('errors'),
    underscore: underscore,
    layout: 'admin',
    title: 'Create a new artist',
    slug: 'page-admin',
    form: req.flash('body')
  };

  res.render('pages/artists/create', locals);
}

/**
 * [processCreate Process artist creation]
 */
function processCreate(req, res) {

  // validate informations
  req.checkBody('name', 'Name is required.').notEmpty();
  req.checkBody('city', 'City name is required').notEmpty();

  if(req.body.coordinates) {
    req.checkBody('coordinates', 'Coordinate must be formated <lng, lat>').matches(/(\-?\d+(\.\d+)?),\s*(\-?\d+(\.\d+)?)\w+/);
  }

  // if there are errors, redirect and save errors to flash
  const errors = req.validationErrors();

  if (errors) {
    console.log('Errors: ', errors.map(err => err.msg));
    req.flash('errors', errors.map(err => err.msg));
    return res.status(400).redirect('/artists/create');
  }

  var thumbnail = req.file ? req.file.filename : req.body.thumbnailUrl;

  var published = (req.isAuthenticated() ? req.body.published : false);

  // create a new artist
  const artist = new Artist({
    name: req.body.name,
    location: {
      city: req.body.city,
      coordinates: req.body.coordinates,
      neighborhood: req.body.neighborhoodName
    },
    categories: req.body.categories,
    image: {
      thumbnailUrl: thumbnail
    },
    bio: {
      summary: req.body.summary,
      url: req.body.bioUrl,
      birthdate: req.body.birthdate,
      deathdate: req.body.deathdate,
      yearsActiveStart: req.body.yearsActiveStart,
      yearsActiveEnd: req.body.yearsActiveEnd
    },
    youtube: {
      clipExampleUrl: req.body.clipExampleUrl
    },
    published: published
  });

  artist.save((err) => {

    if (err) {
      console.log(err.msg);
      req.flash('errors', err.msg);
      return res.redirect('/artists/create');
    }

    // User is logged (creation from admin)
    // set a successful flash message
    console.log('Successfuly created ' + req.body.name);
    req.flash('success', 'Successfuly created artist!');

    // Redirect to the newly created artist
    res.redirect('/artists/create');
  });
}

/**
 * [processSubmit Process submit artist]
 * From atlas by non authenticated user
 */
function processSubmit(req, res) {

  // validate informations
  req.checkBody('name', 'Name is required.').notEmpty();
  req.checkBody('city', 'City name is required').notEmpty();

  // Check errors
  const errors = req.validationErrors();

  if (errors) {
    return res.status(400).json(errors);
  }

  // create a new artist
  const artist = new Artist({
    name: req.body.name,
    location: {
      city: req.body.city,
      coordinates: '',
      neighborhood: ''
    },
    categories: [],
    image: {
      thumbnailUrl: ''
    },
    bio: {
      summary: '',
      url: req.body.bioUrl,
      birthdate: '',
      deathdate: '',
      yearsActiveStart: '',
      yearsActiveEnd: ''
    },
    youtube: {
      clipExampleUrl: req.body.clipExampleUrl
    },
    published: false
  });

  artist.save((error) => {

    if (error) {
      return res.status(400).json([error]);
    }

    var smtpConfig = {
      host: process.env.SMTP_HOST,
      service: process.env.SMTP_SERVICE,
      port: process.env.SMTP_PORT,
      secure: false,
      auth: {
        user: process.env.SMTP_USER,
        pass: process.env.SMTP_PASS
      },
      tls: {
        rejectUnauthorized:false
      }
    };

    var transporter = nodemailer.createTransport(smtpConfig);

    var mailOptions = {
      from: process.env.MAIL_FROM,
      to: process.env.MAIL_TO,
      subject: 'Rap World Map - New entry submited: ' + req.body.name,
      html: `

A new entry was submited.

Name: ${req.body.name}

City: ${req.body.city}

Bio Url: ${req.body.bioUrl}

Clip Url: ${req.body.clipExampleUrl}

        Edit the entry on rapworldmap.com`
    };

    transporter.sendMail(mailOptions, function(error, info) {
      if (error) {
        res.json({
          error: error,
          response: info.response
        });
      } else {
        res.json({
          success: true,
          response: info.response
        });
      }
    });
  });
}

/**
 * [uploadThumbnail Upload thumbnail (using multer)]
 */
function uploadThumbnail(req, res, next) {
  var storage =   multer.diskStorage({
    destination: function (req, file, callback) {
      callback(null, './uploads');
    },
    filename: function (req, file, callback) {
      callback(null, Date.now() + '-' + file.originalname);
    }
  });
  var upload = multer({ storage : storage}).single('thumbnail');

  upload(req,res,function(err) {
    if(err) {
      return res.end('Error uploading file: ' + req.file);
    }

    if(req.file) {
      sharp(req.file.path).resize(300, 300).crop(sharp.strategy.entropy).toFile('uploads/medium-' + req.file.filename, function (err, info) {
        if (err) {
          return next(err);
        }

      });
    }

    next();

  });
}
/**
 * [showEdit Show artist edit page]
 */
function showEdit(req, res) {
  // Retrieve the artist to edit
  Artist.findOne({ slug: req.params.slug }, (err, artist) => {

    // Return 404 if artist cannot be found
    if(!artist) {
      res.status(404);
      res.send(`Artist ${req.params.slug} cannot be found!`);
    }

    console.log(artist);

    const locals = {
      artist: artist,
      moment: moment,
      underscore: underscore,
      errors: req.flash('errors'),
      layout: 'admin',
      title: 'Edit artist - ' + artist.name + '',
      slug: 'page-admin'
    };

    // Render the view
    res.render('pages/artists/edit', locals);
  });
}

/**
 * [processEdit Process artist edition]
 */
function processEdit(req, res) {

  // validate informations
  req.checkBody('name', 'Name is required.').notEmpty();
  req.checkBody('city', 'City name is required').notEmpty();

  // if there are errors, redirect to form and save errors to flash
  const errors = req.validationErrors();
  if (errors) {
    req.flash('errors', errors.map(err => err.msg));
    return res.redirect(`/artists/${req.params.slug}/edit`);
  }

  // Find current artist
  Artist.findOne({ slug: req.params.slug }, (err, artist) => {

    var tumbnail = req.file ? req.file.filename : req.body.originalThumbnail;

    var published = (userMiddlewares.isLoggedIn ? req.body.published : false);

    // updating the current artist
    artist.name = req.body.name;
    artist.location.city = req.body.city;
    artist.location.coordinates = req.body.coordinates;
    artist.location.neighborhood = req.body.neighborhoodName;
    artist.categories = req.body.categories;
    artist.image.thumbnailUrl = tumbnail;
    artist.bio.summary = req.body.summary;
    artist.bio.url = req.body.bioUrl;
    artist.bio.birthdate = req.body.birthdate;
    artist.bio.deathdate = req.body.deathdate;
    artist.bio.yearsActiveStart = req.body.yearsActiveStart;
    artist.bio.yearsActiveEnd = req.body.yearsActiveEnd;
    artist.youtube.pageUrl = req.body.youtugePageUrl;
    artist.youtube.clipExampleUrl = req.body.clipExampleUrl;
    artist.published = published;

    artist.save( (err) => {
      if (err) {
        req.flash('errors', err.msg);
        return res.redirect('back');
      }

      // Set flash success
      // Redirect to artists
      req.flash('success', `Successfuly update ${artist.name}!`);
      res.redirect('/artists');
    });

  });
}

/**
 * [deleteArtist Delete an artist from the database]
 */
function deleteArtist(req, res) {
  Artist.remove({ slug: req.params.slug }, (err) => {
    if(err) {
      console.log(err);
    } else {
      req.flash('success', `Artist ${req.params.slug} successfuly delete`);
      res.redirect('/artists');
    }
  });
}

/**
 * [getArtistsGeojson Return a list of all rappers formated into geojson for mapbox]
 */
function getArtistsGeojson (req, res) {

  Artist.find({
    'location.coordinates': {
      $gt: []
    },
    'published': true
  }, (err, artists) => {

    if(err) {
      res.status(404);
      res.send('Artists not found!');
    }

    var features = [];
    for (var i = artists.length - 1; i >= 0; i--) {
      var artist = artists[i];

      features.push({
        'type': 'Feature',
        'geometry': {
          'type': 'Point',
          'coordinates': JSON.parse( '[' + artist.location.coordinates + ']' )
        },
        'properties': {
          'name': artist.name,
          'icon': {
            'iconUrl': (artist.image.thumbnailUrl ? '/uploads/medium-' + artist.image.thumbnailUrl : '/images/placeholder-artists.svg'),
            'iconSize': [50, 50],
            'iconAnchor': [25, 25],
            'popupAnchor': [0, -25],
            'className': 'marker'
          },
          'location' : {
            'city': artist.location.city,
            'neighborhood': artist.location.neighborhood,
            'coordinates': artist.location.coordinates
          },
          image: {
            thumbnailUrl: artist.image.thumbnailUrl,
          },
          categories: artist.categories,
          bio: {
            summary: artist.bio.summary,
            url: artist.bio.url,
            birthdate: artist.bio.birthdate,
            deathdate: artist.bio.deathdate,
            yearsActiveStart: artist.bio.yearsActiveStart,
            yearsActiveEnd: artist.bio.yearsActiveEnd
          },
          youtube: {
            pageUrl: artist.youtube.pageUrl,
            clipExampleUrl: artist.youtube.clipExampleUrl
          }
        }
      });
    }

    var geojson = {
      'type': 'FeatureCollection',
      'features': features
    };

    res.status(200).json(geojson);
  });
}

/**
 * [showArtistsJson Return an index of all artists in json]
 */
function getArtistsIndex (req, res) {
  Artist.find({
    'published': true
  }, (err, artists) => {

    if(err) {
      res.status(404);
      res.send('Artists not found!');
    }

    var result = {
      'index': {},
      'data': []
    };

    for (var i = artists.length - 1; i >= 0; i--) {
      var artist = artists[i];

      result.index[artist.slug] = (artists.length - 1) - i;

      result.data.push({
        'index': (artists.length - 1) - i,
        'slug': artist.slug,
        'name': artist.name,
        'city': artist.location.city,
        'neighborhood': artist.location.neighborhood,
        'coordinates': artist.location.coordinates,
        'categories': artist.categories,
        'summary': artist.bio.summary,
        'thumbnail': artist.image.thumbnailUrl
      });
    }

    res.status(200).json(result);
  });
}<commit_msg>Error handling for too heavy picture (max 2mo) (closed #6)<commit_after>// artists.controller.js
//==============================================

//====== Define depencies ======
const Artist = require('./artist.model'),
  moment = require('moment'),
  underscore = require('underscore'),
  multer = require('multer'),
  sharp = require('sharp'),
  nodemailer = require('nodemailer'),
  userMiddlewares = require('../users/user.middlewares'),
  utils = require('../../utils/utils');

//====== Export method ======
module.exports = {
  showArtists: showArtists,
  getArtistsIndex: getArtistsIndex,
  showSingle: showSingle,
  showCreate: showCreate,
  processCreate: processCreate,
  processSubmit: processSubmit,
  showEdit: showEdit,
  processEdit: processEdit,
  deleteArtist: deleteArtist,
  getArtistsGeojson: getArtistsGeojson,
  uploadThumbnail: uploadThumbnail
};

//====== Methods ======

/**
 * [showArtists Show a list of all artists]
 */
function showArtists (req, res) {
  Artist.find({}, (err, artists) => {

    var publishedArtists = artists.filter(function(item) {
      if(item.published === true) {
        return item;
      }
    });

    const locals = {
      artists: artists,
      moment: moment,
      success: req.flash('success'),
      layout: 'admin',
      title: 'All artists (' + publishedArtists.length + ' / ' + artists.length + ')',
      slug: 'page-admin'
    };

    if(err) {
      res.status(404);
      res.send('Artists not found!');
    }

    res.render('pages/artists/artists', locals);
  });
}

/**
 * [showSingle Show a single artist]
 */
function showSingle (req, res) {
  // get a single artist
  Artist.findOne({ slug: req.params.slug }, (err, artist) => {
    if(err) {
      res.status(404);
      res.send(`Artist ${req.params.slug} cannot be found!`);
    }

    res.json(artist);
  });
}

/**
 * [showCreate Show artist creation page]
 */
function showCreate(req, res) {
  const locals = {
    errors: req.flash('errors'),
    underscore: underscore,
    layout: 'admin',
    title: 'Create a new artist',
    slug: 'page-admin',
    form: req.flash('body')
  };

  res.render('pages/artists/create', locals);
}

/**
 * [processCreate Process artist creation]
 */
function processCreate(req, res) {

  // validate informations
  req.checkBody('name', 'Name is required.').notEmpty();
  req.checkBody('city', 'City name is required').notEmpty();

  if(req.body.coordinates) {
    req.checkBody('coordinates', 'Coordinate must be formated <lng, lat>').matches(/(\-?\d+(\.\d+)?),\s*(\-?\d+(\.\d+)?)\w+/);
  }

  // if there are errors, redirect and save errors to flash
  const errors = req.validationErrors();

  if (errors) {
    console.log('Errors: ', errors.map(err => err.msg));
    req.flash('errors', errors.map(err => err.msg));
    return res.status(400).redirect('/artists/create');
  }

  var thumbnail = req.file ? req.file.filename : req.body.thumbnailUrl;

  var published = (req.isAuthenticated() ? req.body.published : false);

  // create a new artist
  const artist = new Artist({
    name: req.body.name,
    location: {
      city: req.body.city,
      coordinates: req.body.coordinates,
      neighborhood: req.body.neighborhoodName
    },
    categories: req.body.categories,
    image: {
      thumbnailUrl: thumbnail
    },
    bio: {
      summary: req.body.summary,
      url: req.body.bioUrl,
      birthdate: req.body.birthdate,
      deathdate: req.body.deathdate,
      yearsActiveStart: req.body.yearsActiveStart,
      yearsActiveEnd: req.body.yearsActiveEnd
    },
    youtube: {
      clipExampleUrl: req.body.clipExampleUrl
    },
    published: published
  });

  artist.save((err) => {

    if (err) {
      console.log(err.msg);
      req.flash('errors', err.msg);
      return res.redirect('/artists/create');
    }

    // User is logged (creation from admin)
    // set a successful flash message
    console.log('Successfuly created ' + req.body.name);
    req.flash('success', 'Successfuly created artist!');

    // Redirect to the newly created artist
    res.redirect('/artists/create');
  });
}

/**
 * [processSubmit Process submit artist]
 * From atlas by non authenticated user
 */
function processSubmit(req, res) {

  // validate informations
  req.checkBody('name', 'Name is required.').notEmpty();
  req.checkBody('city', 'City name is required').notEmpty();

  // Check errors
  const errors = req.validationErrors();

  if (errors) {
    return res.status(400).json(errors);
  }

  // create a new artist
  const artist = new Artist({
    name: req.body.name,
    location: {
      city: req.body.city,
      coordinates: '',
      neighborhood: ''
    },
    categories: [],
    image: {
      thumbnailUrl: ''
    },
    bio: {
      summary: '',
      url: req.body.bioUrl,
      birthdate: '',
      deathdate: '',
      yearsActiveStart: '',
      yearsActiveEnd: ''
    },
    youtube: {
      clipExampleUrl: req.body.clipExampleUrl
    },
    published: false
  });

  artist.save((error) => {

    if (error) {
      return res.status(400).json([error]);
    }

    var smtpConfig = {
      host: process.env.SMTP_HOST,
      service: process.env.SMTP_SERVICE,
      port: process.env.SMTP_PORT,
      secure: false,
      auth: {
        user: process.env.SMTP_USER,
        pass: process.env.SMTP_PASS
      },
      tls: {
        rejectUnauthorized:false
      }
    };

    var transporter = nodemailer.createTransport(smtpConfig);

    var mailOptions = {
      from: process.env.MAIL_FROM,
      to: process.env.MAIL_TO,
      subject: 'Rap World Map - New entry submited: ' + req.body.name,
      html: `

A new entry was submited.

Name: ${req.body.name}

City: ${req.body.city}

Bio Url: ${req.body.bioUrl}

Clip Url: ${req.body.clipExampleUrl}

        Edit the entry on rapworldmap.com`
    };

    transporter.sendMail(mailOptions, function(error, info) {
      if (error) {
        res.json({
          error: error,
          response: info.response
        });
      } else {
        res.json({
          success: true,
          response: info.response
        });
      }
    });
  });
}

/**
 * [uploadThumbnail Upload thumbnail (using multer)]
 */
function uploadThumbnail(req, res, next) {
  var maxSize = 2097152; // 2mo

  var storage =   multer.diskStorage({
    destination: function (req, file, callback) {
      callback(null, './uploads');
    },
    filename: function (req, file, callback) {
      callback(null, Date.now() + '-' + file.originalname);
    }
  });
  var upload = multer({
    storage : storage,
    limits: { fileSize: maxSize }
  }).single('thumbnail');

  upload(req, res, function(err) {

    if(err) {
      var errorMsg = 'An error occured during file upload';

      if(err.code === 'LIMIT_FILE_SIZE')
        errorMsg = `File size too heavy. Maximum file size is ${maxSize/1048576}mo.`;

      req.flash('errors', errorMsg);
      return res.redirect('back');
    }

    if(req.file) {
      sharp(req.file.path).resize(300, 300).crop(sharp.strategy.entropy).toFile('uploads/medium-' + req.file.filename, function (err) {
        if (err) {
          return next(err);
        }

      });
    }

    next();

  });
}
/**
 * [showEdit Show artist edit page]
 */
function showEdit(req, res) {
  // Retrieve the artist to edit
  Artist.findOne({ slug: req.params.slug }, (err, artist) => {

    // Return 404 if artist cannot be found
    if(!artist) {
      res.status(404);
      res.send(`Artist ${req.params.slug} cannot be found!`);
    }

    console.log(artist);

    const locals = {
      artist: artist,
      moment: moment,
      underscore: underscore,
      errors: req.flash('errors'),
      layout: 'admin',
      title: 'Edit artist - ' + artist.name + '',
      slug: 'page-admin'
    };

    // Render the view
    res.render('pages/artists/edit', locals);
  });
}

/**
 * [processEdit Process artist edition]
 */
function processEdit(req, res) {

  // validate informations
  req.checkBody('name', 'Name is required.').notEmpty();
  req.checkBody('city', 'City name is required').notEmpty();

  // if there are errors, redirect to form and save errors to flash
  const errors = req.validationErrors();
  if (errors) {
    req.flash('errors', errors.map(err => err.msg));
    return res.redirect(`/artists/${req.params.slug}/edit`);
  }

  // Find current artist
  Artist.findOne({ slug: req.params.slug }, (err, artist) => {

    var tumbnail = req.file ? req.file.filename : req.body.originalThumbnail;

    var published = (userMiddlewares.isLoggedIn ? req.body.published : false);

    // updating the current artist
    artist.name = req.body.name;
    artist.location.city = req.body.city;
    artist.location.coordinates = req.body.coordinates;
    artist.location.neighborhood = req.body.neighborhoodName;
    artist.categories = req.body.categories;
    artist.image.thumbnailUrl = tumbnail;
    artist.bio.summary = req.body.summary;
    artist.bio.url = req.body.bioUrl;
    artist.bio.birthdate = req.body.birthdate;
    artist.bio.deathdate = req.body.deathdate;
    artist.bio.yearsActiveStart = req.body.yearsActiveStart;
    artist.bio.yearsActiveEnd = req.body.yearsActiveEnd;
    artist.youtube.pageUrl = req.body.youtugePageUrl;
    artist.youtube.clipExampleUrl = req.body.clipExampleUrl;
    artist.published = published;

    artist.save( (err) => {
      if (err) {
        req.flash('errors', err.msg);
        return res.redirect('back');
      }

      // Set flash success
      // Redirect to artists
      req.flash('success', `Successfuly update ${artist.name}!`);
      res.redirect('/artists');
    });

  });
}

/**
 * [deleteArtist Delete an artist from the database]
 */
function deleteArtist(req, res) {
  Artist.remove({ slug: req.params.slug }, (err) => {
    if(err) {
      console.log(err);
    } else {
      req.flash('success', `Artist ${req.params.slug} successfuly delete`);
      res.redirect('/artists');
    }
  });
}

/**
 * [getArtistsGeojson Return a list of all rappers formated into geojson for mapbox]
 */
function getArtistsGeojson (req, res) {

  Artist.find({
    'location.coordinates': {
      $gt: []
    },
    'published': true
  }, (err, artists) => {

    if(err) {
      res.status(404);
      res.send('Artists not found!');
    }

    var features = [];
    for (var i = artists.length - 1; i >= 0; i--) {
      var artist = artists[i];

      features.push({
        'type': 'Feature',
        'geometry': {
          'type': 'Point',
          'coordinates': JSON.parse( '[' + artist.location.coordinates + ']' )
        },
        'properties': {
          'name': artist.name,
          'icon': {
            'iconUrl': (artist.image.thumbnailUrl ? '/uploads/medium-' + artist.image.thumbnailUrl : '/images/placeholder-artists.svg'),
            'iconSize': [50, 50],
            'iconAnchor': [25, 25],
            'popupAnchor': [0, -25],
            'className': 'marker'
          },
          'location' : {
            'city': artist.location.city,
            'neighborhood': artist.location.neighborhood,
            'coordinates': artist.location.coordinates
          },
          image: {
            thumbnailUrl: artist.image.thumbnailUrl,
          },
          categories: artist.categories,
          bio: {
            summary: artist.bio.summary,
            url: artist.bio.url,
            birthdate: artist.bio.birthdate,
            deathdate: artist.bio.deathdate,
            yearsActiveStart: artist.bio.yearsActiveStart,
            yearsActiveEnd: artist.bio.yearsActiveEnd
          },
          youtube: {
            pageUrl: artist.youtube.pageUrl,
            clipExampleUrl: artist.youtube.clipExampleUrl
          }
        }
      });
    }

    var geojson = {
      'type': 'FeatureCollection',
      'features': features
    };

    res.status(200).json(geojson);
  });
}

/**
 * [showArtistsJson Return an index of all artists in json]
 */
function getArtistsIndex (req, res) {
  Artist.find({
    'published': true
  }, (err, artists) => {

    if(err) {
      res.status(404);
      res.send('Artists not found!');
    }

    var result = {
      'index': {},
      'data': []
    };

    for (var i = artists.length - 1; i >= 0; i--) {
      var artist = artists[i];

      result.index[artist.slug] = (artists.length - 1) - i;

      result.data.push({
        'index': (artists.length - 1) - i,
        'slug': artist.slug,
        'name': artist.name,
        'city': artist.location.city,
        'neighborhood': artist.location.neighborhood,
        'coordinates': artist.location.coordinates,
        'categories': artist.categories,
        'summary': artist.bio.summary,
        'thumbnail': artist.image.thumbnailUrl
      });
    }

    res.status(200).json(result);
  });
}<|endoftext|>


<commit_before>'use strict';

angular.module('confRegistrationWebApp')
  .controller('eventDashboardCtrl', function ($rootScope, $scope, ConfCache, RegistrationCache, $modal, $location, $http, Model, uuid) {
    $rootScope.globalPage = {
      type: 'admin',
      mainClass: 'container dashboard',
      bodyClass: '',
      title: 'My Dashboard',
      confId: 0,
      footer: true
    };

    $scope.$on('conferences/', function (event, conferences) {
      $scope.conferences = conferences;
    });
    ConfCache.query();

    $scope.$watch('showArchivedEvents', function (v) {
      if (v) {
        $scope.showArchivedEventsFilter = '';
      } else {
        $scope.showArchivedEventsFilter = false;
      }
    });

    $scope.createEvent = function () {
      $modal.open({
        templateUrl: 'views/modals/createEvent.html',
        controller: 'createEventCtrl',
        resolve: {
          defaultValue: function () {
            return '';
          }
        }
      }).result.then(function (conferenceName) {
          if (conferenceName !== null && conferenceName !== '' && !angular.isUndefined(conferenceName)) {
            ConfCache.create(conferenceName).then(function (conference) {
              $location.path('/eventDetails/' + conference.id);
            });
          }
        });
    };

    $scope.goToEventPage = function (page, eventId) {
      var eventData = _.find($scope.conferences, {id: eventId});
      if (!eventData.archived) {
        $location.path('/' + page + '/' + eventId);
      }
    };

    $scope.restoreEvent = function (eventId) {
      var eventData = _.find($scope.conferences, {id: eventId});
      eventData.archived = false;

      $http({
        method: 'PUT',
        url: 'conferences/' + eventId,
        data: eventData
      }).success(function () {
        //Clear cache
        ConfCache.empty();
      }).error(function (data) {
        alert('Error: ' + data);
        eventData.archived = true;
      });
    };

    $scope.cloneEvent = function (conferenceToCloneId) {
      var conferenceToClone = _.find($scope.conferences, {id: conferenceToCloneId});

      $modal.open({
        templateUrl: 'views/modals/cloneEvent.html',
        controller: 'createEventCtrl',
        resolve: {
          defaultValue: function () {
            return conferenceToClone.name + ' (clone)';
          }
        }
      }).result.then(function (conferenceName) {
        if (conferenceName !== null && conferenceName !== '' && !angular.isUndefined(conferenceName)) {
          ConfCache.create(conferenceName).then(function (conference) {
            var conferenceOrig = conference;
            $http.get('conferences/' + conferenceToClone.id).success(function (result) {
              //clone conference details
              conference = angular.copy(result);
              //fixme: i don't think this is right
              conference.contactUser = conferenceOrig.contactUser;
              conference.id = conferenceOrig.id;
              conference.name = conferenceName;

              //clone registrant types
              conference.registrantTypes = result.registrantTypes;

              // map the old id to the new id so that question to registrant type assignments can be cloned.
              var registrantTypeIdMap = {};

              for (i = 0; i < conference.registrantTypes.length; i++) {
                var originalRegTypeId = conference.registrantTypes[i].id;
                var clonedRegTypeId = uuid();
                registrantTypeIdMap[originalRegTypeId] = clonedRegTypeId;
                conference.registrantTypes[i].id = clonedRegTypeId;
                conference.registrantTypes[i].conferenceId = conference.id;
              }

              //clone conference pages
              conference.registrationPages = result.registrationPages;
              for (var i = 0; i < conference.registrationPages.length; i++) {
                var pageUuid = uuid();
                conference.registrationPages[i].id = pageUuid;
                conference.registrationPages[i].conferenceId = conference.id;
                for (var j = 0; j < conference.registrationPages[i].blocks.length; j++) {
                  conference.registrationPages[i].blocks[j].id = uuid();
                  conference.registrationPages[i].blocks[j].pageId = pageUuid;

                  // take a copy of the registrantTypes for this block
                  var originalRegTypeIds = angular.copy(conference.registrationPages[i].blocks[j].registrantTypes);

                  // clear the registrantTypes on the block (a copy was just made)
                  conference.registrationPages[i].blocks[j].registrantTypes = [];

                  // loop through the registantTypes from the original block
                  for(var k = 0; k <  originalRegTypeIds.length; k++) {
                    // take the original block ID, and look up the new on that corresponds to it in the map.
                    // add that new Id to the registrant types on the block
                    var id = originalRegTypeIds[k];
                    conference.registrationPages[i].blocks[j].registrantTypes.push(registrantTypeIdMap[id]);
                  }
                }
              }

              Model.update('conferences/' + conference.id, conference, function () {
                $location.path('/eventDetails/' + conference.id);
              });
            });
          });
        }
      });
    };
  });
<commit_msg>update fixme<commit_after>'use strict';

angular.module('confRegistrationWebApp')
  .controller('eventDashboardCtrl', function ($rootScope, $scope, ConfCache, RegistrationCache, $modal, $location, $http, Model, uuid) {
    $rootScope.globalPage = {
      type: 'admin',
      mainClass: 'container dashboard',
      bodyClass: '',
      title: 'My Dashboard',
      confId: 0,
      footer: true
    };

    $scope.$on('conferences/', function (event, conferences) {
      $scope.conferences = conferences;
    });
    ConfCache.query();

    $scope.$watch('showArchivedEvents', function (v) {
      if (v) {
        $scope.showArchivedEventsFilter = '';
      } else {
        $scope.showArchivedEventsFilter = false;
      }
    });

    $scope.createEvent = function () {
      $modal.open({
        templateUrl: 'views/modals/createEvent.html',
        controller: 'createEventCtrl',
        resolve: {
          defaultValue: function () {
            return '';
          }
        }
      }).result.then(function (conferenceName) {
          if (conferenceName !== null && conferenceName !== '' && !angular.isUndefined(conferenceName)) {
            ConfCache.create(conferenceName).then(function (conference) {
              $location.path('/eventDetails/' + conference.id);
            });
          }
        });
    };

    $scope.goToEventPage = function (page, eventId) {
      var eventData = _.find($scope.conferences, {id: eventId});
      if (!eventData.archived) {
        $location.path('/' + page + '/' + eventId);
      }
    };

    $scope.restoreEvent = function (eventId) {
      var eventData = _.find($scope.conferences, {id: eventId});
      eventData.archived = false;

      $http({
        method: 'PUT',
        url: 'conferences/' + eventId,
        data: eventData
      }).success(function () {
        //Clear cache
        ConfCache.empty();
      }).error(function (data) {
        alert('Error: ' + data);
        eventData.archived = true;
      });
    };

    $scope.cloneEvent = function (conferenceToCloneId) {
      var conferenceToClone = _.find($scope.conferences, {id: conferenceToCloneId});

      $modal.open({
        templateUrl: 'views/modals/cloneEvent.html',
        controller: 'createEventCtrl',
        resolve: {
          defaultValue: function () {
            return conferenceToClone.name + ' (clone)';
          }
        }
      }).result.then(function (conferenceName) {
        if (conferenceName !== null && conferenceName !== '' && !angular.isUndefined(conferenceName)) {
          ConfCache.create(conferenceName).then(function (conference) {
            var conferenceOrig = conference;
            $http.get('conferences/' + conferenceToClone.id).success(function (result) {
              //clone conference details
              conference = angular.copy(result);
              //fixme: i don't think this does anything. contactUser is not an object on the conference object
              conference.contactUser = conferenceOrig.contactUser;
              conference.id = conferenceOrig.id;
              conference.name = conferenceName;

              //clone registrant types
              conference.registrantTypes = result.registrantTypes;

              // map the old id to the new id so that question to registrant type assignments can be cloned.
              var registrantTypeIdMap = {};

              for (i = 0; i < conference.registrantTypes.length; i++) {
                var originalRegTypeId = conference.registrantTypes[i].id;
                var clonedRegTypeId = uuid();
                registrantTypeIdMap[originalRegTypeId] = clonedRegTypeId;
                conference.registrantTypes[i].id = clonedRegTypeId;
                conference.registrantTypes[i].conferenceId = conference.id;
              }

              //clone conference pages
              conference.registrationPages = result.registrationPages;
              for (var i = 0; i < conference.registrationPages.length; i++) {
                var pageUuid = uuid();
                conference.registrationPages[i].id = pageUuid;
                conference.registrationPages[i].conferenceId = conference.id;
                for (var j = 0; j < conference.registrationPages[i].blocks.length; j++) {
                  conference.registrationPages[i].blocks[j].id = uuid();
                  conference.registrationPages[i].blocks[j].pageId = pageUuid;

                  // take a copy of the registrantTypes for this block
                  var originalRegTypeIds = angular.copy(conference.registrationPages[i].blocks[j].registrantTypes);

                  // clear the registrantTypes on the block (a copy was just made)
                  conference.registrationPages[i].blocks[j].registrantTypes = [];

                  // loop through the registantTypes from the original block
                  for(var k = 0; k <  originalRegTypeIds.length; k++) {
                    // take the original block ID, and look up the new on that corresponds to it in the map.
                    // add that new Id to the registrant types on the block
                    var id = originalRegTypeIds[k];
                    conference.registrationPages[i].blocks[j].registrantTypes.push(registrantTypeIdMap[id]);
                  }
                }
              }

              Model.update('conferences/' + conference.id, conference, function () {
                $location.path('/eventDetails/' + conference.id);
              });
            });
          });
        }
      });
    };
  });
<|endoftext|>


<commit_before>'use strict'

window.angular.module('scegratooApp')
  .service('TreeNodeAttribute', (React, R) => {
    const {
      contains,
      flatten,
      map,
      pipe,
      split
    } = R

    const deserializeVector = pipe(
      split(' '),
      map(split(',')),
      flatten,
      map(Number.parseFloat),
      map(n => n.toFixed(2))
    )

    return React.createClass({
      displayName: 'TreeNodeAttribute',
      propTypes: {
        owner: React.PropTypes.object.isRequired,
        attribute: React.PropTypes.object.isRequired
      },
      clicked: function (event) {
        if (event.currentTarget.checked) {
          this.props.owner.render = true
        } else {
          this.props.owner.render = false
        }
      },
      render: function () {
        const attribute = this.props.attribute

        if (attribute.name === 'render') {
          const checked = attribute.value === 'true'
          return (

              {attribute.name}: <input type='checkbox' checked={checked} onClick={this.clicked} />

          )
        } else if (contains(attribute.name, ['translation', 'rotation'])) {
          return (

              {attribute.name}: {deserializeVector(attribute.value).map(coordinate => <input type='text' value={coordinate} style={ {width: '50px'} }/>)}

          )
        } else {
          return (

              {attribute.name}: {attribute.value}

          )
        }
      }
    })
  })
<commit_msg>tree view attributes can be edited<commit_after>'use strict'

window.angular.module('scegratooApp')
  .service('TreeNodeAttribute', (React, R) => {
    const {
      contains,
      curry,
      flatten,
      map,
      pipe,
      split,
      take
    } = R

    const splitVector = pipe(
      split(' '),
      map(split(',')),
      flatten
    )

    const deserializeVector = pipe(
      splitVector,
      map(Number.parseFloat),
      map(n => n.toFixed(2))
    )

    return React.createClass({
      displayName: 'TreeNodeAttribute',
      propTypes: {
        owner: React.PropTypes.object.isRequired,
        attribute: React.PropTypes.object.isRequired
      },
      getInitialState: function () {
        return {
          renderAttribute: true
        }
      },
      mapAttributeToHandler: function (name, value, index) {
        if (name === 'translation') {
          return curry(this.translationChanged)(value, index)
        } else if (name === 'rotation') {
          return curry(this.rotationChanged)(value, index)
        } else {
          throw new Error('Unknown attribute')
        }
      },
      clicked: function (event) {
        if (event.currentTarget.checked) {
          this.props.owner.render = true
        } else {
          this.props.owner.render = false
        }
      },
      focus: function (translation, event) {
        this.setState({
          renderAttribute: false,
          translation: this.props.owner.translation,
          rotation: this.props.owner.rotation
        })
      },
      blur: function (oldValue, index, event) {
        this.setState({renderAttribute: true})
      },
      translationChanged: function (oldValue, index, event) {
        const oldVector = deserializeVector(oldValue)
        oldVector[index] = event.currentTarget.value
        const newVector = take(3, oldVector).join(' ')

        this.props.owner.translation = newVector
        this.setState({
          translation: newVector
        })
      },
      rotationChanged: function (oldValue, index, event) {
        const oldVector = deserializeVector(oldValue)
        oldVector[index] = event.currentTarget.value
        const newVector = take(4, oldVector).join(' ')

        this.props.owner.rotation = newVector
        this.setState({
          rotation: newVector
        })
      },
      render: function () {
        const attribute = this.props.attribute

        console.log('render: ', this.state)

        if (attribute.name === 'render') {
          const checked = attribute.value === 'true'
          return (

              {attribute.name}: <input type='checkbox' checked={checked} onClick={this.clicked} />

          )
        } else if (contains(attribute.name, ['translation', 'rotation'])) {
          return (

              {attribute.name}: {(this.state.renderAttribute ? deserializeVector(attribute.value) : this.state[attribute.name].split(' ')).map((coordinate, index) => <input
                type='text'
                value={coordinate}
                onFocus={this.focus}
                onBlur={this.blur}
                onChange={this.mapAttributeToHandler(attribute.name, attribute.value, index)}
                style={ {width: '50px'} }
              />)}

          )
        } else {
          return (

              {attribute.name}: {attribute.value}

          )
        }
      }
    })
  })
<|endoftext|>


<commit_before>import React, { PropTypes } from 'react';
import styles from './index.module.scss';
import cssModules from 'react-css-modules';
import Heading from 'grommet-udacity/components/Heading';
import Section from 'grommet-udacity/components/Section';
import Box from 'grommet-udacity/components/Box';
import Article from 'grommet-udacity/components/Article';
import Image from 'grommet-udacity/components/Image';
import Paragraph from 'grommet-udacity/components/Paragraph';
import { Author, ArticleMeta } from 'components';

const SingleArticle = ({
  article,
}) => (
  <Box>

        <Heading className={styles.heading} align="center" tag="h2">
          {article.title}
        </Heading>
        <Image src={article.feature_image} full="horizontal" />
        <Box align="center" justify="center" size="large" pad={{ horizontal: 'small' }}>
          <Paragraph>
            {article.content}
          </Paragraph>
        </Box>

      <Author author={article.user} />

      <ArticleMeta article={article} />

  </Box>
);

SingleArticle.propTypes = {
  article: PropTypes.object.isRequired,
};

export default cssModules(SingleArticle, styles);
<commit_msg>Fix: rc style in article meta<commit_after>import React, { PropTypes } from 'react';
import styles from './index.module.scss';
import cssModules from 'react-css-modules';
import Heading from 'grommet-udacity/components/Heading';
import Section from 'grommet-udacity/components/Section';
import Box from 'grommet-udacity/components/Box';
import Article from 'grommet-udacity/components/Article';
import Image from 'grommet-udacity/components/Image';
import Paragraph from 'grommet-udacity/components/Paragraph';
import { Author, ArticleMeta } from 'components';

const SingleArticle = ({
  article,
}) => (
  <Box>

        <Heading className={styles.heading} align="center" tag="h2">
          {article.title}
        </Heading>
        <Image src={article.feature_image} full="horizontal" />
        <Box
          align="center"
          justify="center"
          size="large"
          pad={{ horizontal: 'small' }}
        >
          <Paragraph>
            {article.content}
          </Paragraph>
        </Box>

      <Author author={article.user} />

      <ArticleMeta article={article} />

  </Box>
);

SingleArticle.propTypes = {
  article: PropTypes.object.isRequired,
};

export default cssModules(SingleArticle, styles);
<|endoftext|>