<commit_before>(function(angular, undefined) {
'use strict';

// module: django.shop, TODO: move this into a summary JS file
var djangoShopModule = angular.module('django.shop.dialogs', ['ng.django.urls', 'ng.django.forms']);

// Shared controller for all forms, links and buttons using shop-dialog elements. It just adds
// an `upload` function to the scope, so that all forms can send their gathered data to the
// server. Since this controller does not make any presumption on how and where to proceed to,
// the caller has to set the controllers `deferred` to a `$q.deferred()` object.
djangoShopModule.controller('DialogCtrl', ['$scope', '$rootScope', '$http', '$q', 'djangoUrl', 'djangoForm',
                                   function($scope, $rootScope, $http, $q, djangoUrl, djangoForm) {
	var uploadURL = djangoUrl.reverse('shop:checkout-upload');

	function getProperty(obj, prop) {
		var parts = prop.split('.'), part;
		for (part = parts.shift(); obj && part; part = parts.shift()) {
			obj = obj[part];
		}
		return obj;
	}

	this.uploadScope = function(scope, deferred) {
		$http.post(uploadURL, scope.data).success(function(response) {
			var hasErrors = false;
			if (deferred) {
				// only report errors, when the customer clicked onto a button using the
				// directive `shop-dialog-proceed`, but not on ordinary upload events.
				angular.forEach(response.errors, function(errors, key) {
					var errProp = getProperty(scope, key);
					hasErrors = djangoForm.setErrors(errProp, errors) || hasErrors;
				});
				if (hasErrors) {
					deferred.reject(response);
				} else {
					deferred.resolve(response);
				}
			}
			$rootScope.cart = response;
		}).error(function(errors) {
			console.error("Unable to upload checkout forms:");
			console.log(errors);
		});
	};

}]);

// Directive <form shop-dialog-form> (must be added as attribute to the <form> element)
// It is used to add an `upload()` method to the scope, so that `ng-change="upload()"`
// can be added to any input element. Use it to upload the models on the server.
djangoShopModule.directive('shopDialogForm', function() {
	return {
		restrict: 'A',
		controller: 'DialogCtrl',
		link: function(scope, element, attrs, DialogCtrl) {
			scope.upload = function() {
				DialogCtrl.uploadScope(scope);
			};
		}
	};
});

// Directive to be added to button elements.
djangoShopModule.directive('shopDialogProceed', ['$window', '$http', '$q', 'djangoUrl',
                         function($window, $http, $q, djangoUrl) {
	var purchaseURL = djangoUrl.reverse('shop:checkout-purchase');
	return {
		restrict: 'EA',
		controller: 'DialogCtrl',
		link: function(scope, element, attrs, DialogCtrl) {
			// add ng-click="proceed()" to button elements wishing to post the content of the
			// current scope. Returns a promise for further processing.
			scope.proceed = function() {
				var deferred = $q.defer();
				DialogCtrl.uploadScope(scope, deferred);
				return deferred.promise;
			};

			// add ng-click="proceedWith(action)" to button elements wishing to
			// proceed after having posted the content of the current scope.
			scope.proceedWith = function(action) {
				var deferred = $q.defer();
				DialogCtrl.uploadScope(scope, deferred);
				performAction(deferred.promise, action);
			};

			// Some actions, such as purchasing require a lot of time. This function
			// deactivates the button and replaces existing Glyphicons against a spinning wheel.
			function deactivateButton() {
				element.attr('disabled', 'disabled');
				angular.forEach(element.find('span'), function(span) {
					span = angular.element(span);
					if (span.hasClass('glyphicon')) {
						span.attr('class', 'glyphicon glyphicon-refresh glyphicon-refresh-animate');
					}
				});
			}

			function performAction(promise, action) {
				$q.when(promise).then(function() {
					console.log("Proceed to: " + action);
					if (action === 'RELOAD_PAGE') {
						$window.location.reload();
					} else if (action === 'PURCHASE_NOW') {
						deactivateButton();
						// Convert the cart into an order object.
						return $http.post(purchaseURL, scope.data);
					} else {
						// Proceed as usual and load another page
						$window.location.href = action;
					}
				}).then(function(response) {
					if (response) {
						console.log(response);
						// evaluate expression to proceed on the PSP's server
						eval(response.data.expression);
					}
				}, function(errs) {
					if (errs) {
						console.error(errs);
					}
				});
			}
		}
	};
}]);

// Directive <TAG shop-form-validate="model-to-watch">
// It is used to override the validation of hidden form fragments.
// If model-to-watch is false, then input elements inside this DOM tree are not validated.
// This is useful, if a form fragment shall be validated only under certain conditions.
djangoShopModule.directive('shopFormValidate', function() {
	return {
		restrict: 'A',
		require: '^form',
		link: function(scope, element, attrs, formCtrl) {
			if (!attrs.shopFormValidate)
				return;
			scope.$watch(attrs.shopFormValidate, function() {
				var validateExpr = scope.$eval(attrs.shopFormValidate);
				angular.forEach(formCtrl, function(instance) {
					// iterate over form controller and move active parsers to inactive
					if (angular.isObject(instance) && instance.hasOwnProperty('$parsers')) {
						if (validateExpr) {
							if (angular.isArray(instance.$inactiveParsers)) {
								instance.$parsers = instance.$inactiveParsers;
							}
							instance.$inactiveParsers = [];
						} else {
							instance.$inactiveParsers = instance.$parsers;
							instance.$parsers = [];
							// reset all possible errors for this input element
							angular.forEach(instance.$error, function(val, key) {
								instance.$setValidity(key, true);
							});
						}
					}
				});
			});
		}
	};
});

})(window.angular);
<commit_msg>fixed: reactivae Button if PURCHASE_NOW fails<commit_after>(function(angular, undefined) {
'use strict';

// module: django.shop, TODO: move this into a summary JS file
var djangoShopModule = angular.module('django.shop.dialogs', ['ng.django.urls', 'ng.django.forms']);

// Shared controller for all forms, links and buttons using shop-dialog elements. It just adds
// an `upload` function to the scope, so that all forms can send their gathered data to the
// server. Since this controller does not make any presumption on how and where to proceed to,
// the caller has to set the controllers `deferred` to a `$q.deferred()` object.
djangoShopModule.controller('DialogCtrl', ['$scope', '$rootScope', '$http', '$q', 'djangoUrl', 'djangoForm',
                                   function($scope, $rootScope, $http, $q, djangoUrl, djangoForm) {
	var uploadURL = djangoUrl.reverse('shop:checkout-upload');

	function getProperty(obj, prop) {
		var parts = prop.split('.'), part;
		for (part = parts.shift(); obj && part; part = parts.shift()) {
			obj = obj[part];
		}
		return obj;
	}

	this.uploadScope = function(scope, deferred) {
		$http.post(uploadURL, scope.data).success(function(response) {
			var hasErrors = false;
			if (deferred) {
				// only report errors, when the customer clicked onto a button using the
				// directive `shop-dialog-proceed`, but not on ordinary upload events.
				angular.forEach(response.errors, function(errors, key) {
					var errProp = getProperty(scope, key);
					hasErrors = djangoForm.setErrors(errProp, errors) || hasErrors;
				});
				if (hasErrors) {
					deferred.reject(response);
				} else {
					deferred.resolve(response);
				}
			}
			$rootScope.cart = response;
		}).error(function(errors) {
			console.error("Unable to upload checkout forms:");
			console.log(errors);
		});
	};

}]);

// Directive <form shop-dialog-form> (must be added as attribute to the <form> element)
// It is used to add an `upload()` method to the scope, so that `ng-change="upload()"`
// can be added to any input element. Use it to upload the models on the server.
djangoShopModule.directive('shopDialogForm', function() {
	return {
		restrict: 'A',
		controller: 'DialogCtrl',
		link: function(scope, element, attrs, DialogCtrl) {
			scope.upload = function() {
				DialogCtrl.uploadScope(scope);
			};
		}
	};
});

// Directive to be added to button elements.
djangoShopModule.directive('shopDialogProceed', ['$window', '$http', '$q', 'djangoUrl',
                         function($window, $http, $q, djangoUrl) {
	var purchaseURL = djangoUrl.reverse('shop:checkout-purchase');
	return {
		restrict: 'EA',
		controller: 'DialogCtrl',
		link: function(scope, element, attrs, DialogCtrl) {
			// add ng-click="proceed()" to button elements wishing to post the content of the
			// current scope. Returns a promise for further processing.
			scope.proceed = function() {
				var deferred = $q.defer();
				DialogCtrl.uploadScope(scope, deferred);
				return deferred.promise;
			};

			// add ng-click="proceedWith(action)" to button elements wishing to
			// proceed after having posted the content of the current scope.
			scope.proceedWith = function(action) {
				var deferred = $q.defer();
				DialogCtrl.uploadScope(scope, deferred);
				performAction(deferred.promise, action);
			};

			// Some actions, such as purchasing require a lot of time. This function
			// deactivates the button and replaces existing Glyphicons against a spinning wheel.
			function deactivateButton() {
				element.attr('disabled', 'disabled');
				angular.forEach(element.find('span'), function(span) {
					span = angular.element(span);
					if (span.hasClass('glyphicon')) {
						span.attr('deactivated-class', span.attr('class'));
						span.attr('class', 'glyphicon glyphicon-refresh glyphicon-refresh-animate');
					}
				});
			}

			function reactivateButton(message) {
				element.removeAttr('disabled');
				angular.forEach(element.find('span'), function(span) {
					span = angular.element(span);
					if (span.hasClass('glyphicon')) {
						span.attr('class', span.attr('deactivated-class'));
						span.removeAttr('deactivated-class');
					}
				});
				if (message) {
					console.error(message);
				}
			}

			function performAction(promise, action) {
				$q.when(promise).then(function() {
					console.log("Proceed to: " + action);
					if (action === 'RELOAD_PAGE') {
						$window.location.reload();
					} else if (action === 'PURCHASE_NOW') {
						deactivateButton();
						// Convert the cart into an order object.
						return $http.post(purchaseURL, scope.data);
					} else {
						// Proceed as usual and load another page
						$window.location.href = action;
					}
				}).then(function(response) {
					var result;
					if (response) {
						console.log(response);
						// evaluate expression to proceed on the PSP's server ...
						result = eval(response.data.expression);
						// ... which itself may be a promise
						$q.when(result).then(function() {
							reactivateButton("Successfully purchased");
						}, function() {
							reactivateButton("Error during purchase");
						});
					}
				}, function(errs) {
					reactivateButton(errs);
				});
			}
		}
	};
}]);

// Directive <TAG shop-form-validate="model-to-watch">
// It is used to override the validation of hidden form fragments.
// If model-to-watch is false, then input elements inside this DOM tree are not validated.
// This is useful, if a form fragment shall be validated only under certain conditions.
djangoShopModule.directive('shopFormValidate', function() {
	return {
		restrict: 'A',
		require: '^form',
		link: function(scope, element, attrs, formCtrl) {
			if (!attrs.shopFormValidate)
				return;
			scope.$watch(attrs.shopFormValidate, function() {
				var validateExpr = scope.$eval(attrs.shopFormValidate);
				angular.forEach(formCtrl, function(instance) {
					// iterate over form controller and move active parsers to inactive
					if (angular.isObject(instance) && instance.hasOwnProperty('$parsers')) {
						if (validateExpr) {
							if (angular.isArray(instance.$inactiveParsers)) {
								instance.$parsers = instance.$inactiveParsers;
							}
							instance.$inactiveParsers = [];
						} else {
							instance.$inactiveParsers = instance.$parsers;
							instance.$parsers = [];
							// reset all possible errors for this input element
							angular.forEach(instance.$error, function(val, key) {
								instance.$setValidity(key, true);
							});
						}
					}
				});
			});
		}
	};
});

})(window.angular);
<|endoftext|>


<commit_before>'use strict';

const helpers = require('../../test/server/rest/mockServer');
const webshot = require('webshot');
const getOptions = require('./options');
const sharp = require('sharp');

function addWebshotMethod(server, languageCode)
{
    server.webshot = function(angularPath, filename, done) {
        let o = server.getUrlOptions();
        let url = 'http://'+o.hostname+':'+o.port+'/#'+angularPath;
        let options = getOptions();
        options.customHeaders = o.headers;

        return new Promise((resolve, reject) => {
            webshot(url, './doc/screenshots/'+languageCode+'/'+filename+'.png', options, function(err) {
                if (err) {
                    return reject(err);
                }

                resolve(true);
            });

        });

    };

}

exports = module.exports = {

    /**
     * Function loaded in a beforeEach to ensure the server is started for every test
     * This start only one instance
     *
     * @param {String} [dbname]     optionnal database name
     * @param {String} countryCode  Database will be initialized with this country UK|FR|...
     * @param {String} languageCode en|fr|...
     * @param {function} ready      callback
     */
    screenServer: function(dbname, countryCode, languageCode, ready) {

        helpers.mockServer(dbname, function(_mockServer) {
            addWebshotMethod(_mockServer, languageCode);
            ready(_mockServer).catch(err => {
                console.error(err);
                console.log(err.stack);
            });
        }, countryCode, languageCode);
    }
};
<commit_msg>sharp integration<commit_after>'use strict';

const helpers = require('../../test/server/rest/mockServer');
const webshot = require('webshot');
const getOptions = require('./options');
const sharp = require('sharp');
const fs = require('fs');

function addWebshotMethod(server, languageCode)
{
    server.webshot = function(angularPath, filename, done) {
        let o = server.getUrlOptions();
        let url = 'http://'+o.hostname+':'+o.port+'/#'+angularPath;
        let options = getOptions();
        options.customHeaders = o.headers;

        return new Promise((resolve, reject) => {
            let filepathFull = './doc/screenshots/'+languageCode+'/'+filename+'.full.png';
            let filepath = './doc/screenshots/'+languageCode+'/'+filename+'.png';

            webshot(url, filepathFull, options, function(err) {
                if (err) {
                    return reject(err);
                }

                sharp(filepathFull)
                .resize(600)
                .toFile(filepath, (err, info) => {
                    if (err) {
                        return reject(err);
                    }

                    fs.unlink(filepathFull);
                    resolve(true);
                });

            });

        });

    };

}

exports = module.exports = {

    /**
     * Function loaded in a beforeEach to ensure the server is started for every test
     * This start only one instance
     *
     * @param {String} [dbname]     optionnal database name
     * @param {String} countryCode  Database will be initialized with this country UK|FR|...
     * @param {String} languageCode en|fr|...
     * @param {function} ready      callback
     */
    screenServer: function(dbname, countryCode, languageCode, ready) {

        helpers.mockServer(dbname, function(_mockServer) {
            addWebshotMethod(_mockServer, languageCode);
            ready(_mockServer).catch(err => {
                console.error(err);
                console.log(err.stack);
            });
        }, countryCode, languageCode);
    }
};
<|endoftext|>


<commit_before>(function(){
	var Communist = function(){};
	var makeWorker = function(strings){
		var URL = window.URL || window.webkitURL || self.URL;
		return new Worker(URL.createObjectURL(new Blob([strings.join("")],{type: "text/javascript"})));
	};
	var oneOff = function(fun,data){
		var promise = new RSVP.Promise();
		var worker = makeWorker(['var fun = ',fun,';\
		function _clb(data,transfer){\
				self.postMessage(data,transfer);\
				self.close();\
			}\
			var _rst = fun(',JSON.stringify(data),',_clb);\
			if(typeof _rst !== "undefined"){\
				_clb(_rst);\
			}']);
		worker.onmessage=function(e){
			promise.resolve(e.data);
		};
		worker.onerror=function(e){
			promise.reject(e);
		};
		return promise;
	};
	var mapWorker=function(fun,callback,onerr){
		var w = new Communist();
		var worker = makeWorker(['var _db={};var fun = ',fun,';\
			function _clb(data,transfer){\
				self.postMessage(data,transfer);\
			}\
			self.onmessage=function(e){\
			var _rst = fun(e.data,_clb);\
				if(typeof _rst !== "undefined"){\
					_clb(_rst);\
				}\
			}']);
		worker.onmessage = function(e){
			callback(e.data);
		};
		worker.onerror=onerr||function(){callback();};
		w.data=function(d,t){
			worker.postMessage(d,t);
		};
		w.close=function(){
			return worker.terminate();
		};
		return w;
	};
	var sticksAround = function(fun){
		var w = new Communist();
		var promises = [];
		var rejectPromises = function(msg){
			promises.forEach(function(p){
				if(p){
					p.reject(msg);
				}
			});
		};
		var func = 'function(data,cb){var _fun = '+fun+';\
			var _nCB = function(num,d,tran){\
			cb([num,d],tran);\
			};\
			var _bCB = _nCB.bind(self,data[0]);\
			var _nR = _fun(data[1],_bCB);\
			if(typeof _nR !== "undefined"){\
				_bCB(_nR);\
			}\
		}';
		var callback = function(data){
				promises[data[0]].resolve(data[1]);
				promises[data[0]]=0;
		};
		var worker = mapWorker(func, callback,rejectPromises);
		w.close = function(){
			worker.close();
			rejectPromises("closed");
			return;
		};
		w.data=function(data, transfer){
			var i = promises.length;
			promises[i] = new RSVP.Promise();
			worker.data([i,data],transfer);
			return promises[i];
		};
		return w;
	};
	var rWorker = function(fun,callback){
		var w = new Communist();
		var func = 'function(dat,cb){ var fun = '+fun+';\
			switch(dat[0]){\
				case "data":\
					if(!_db._r){\
						_db._r = dat[1];\
					}else{\
						_db._r = fun(_db._r,dat[1]);\
					}\
					break;\
				case "get":\
					return cb(_db._r);\
				case "close":\
					cb(_db._r);\
					self.close();\
					break;\
			}\
		};'
		var cb =function(data){
			callback(data);
		};
		var worker = mapWorker(func,cb);
		w.data=function(data,transfer){
			worker.data(["data",data],transfer);
		};
		w.fetch=function(){
			worker.data(["get"]);
		};
		w.close=function(silent){
			if(silent){
				callback=function(){};
			}
			worker.data(["close"]);
		};
		return w;
	};
	var nonIncrementalMapReduce = function(threads){
		var data=[];
		var len = 0;
		var reducer;
		var w = new RSVP.Promise();
		var workers = [];
		var terminated = threads;
		var status = {
			map:false,
			reduce:false,
			data:false
		};
		var checkStatus = function(){
			if(status.map && status.reduce && status.data){
				return go();
			}else{
				return w;
			}
		};
		w.map=function(fun,t){
			if(status.map){
				return w;
			}
			var i = 0;
			while(i<threads){
				var dd;
				(function(){
					var mw = mapWorker(fun, function(d){
						if(typeof d !== undefined){
							reducer.data(d);
						}
						if(len>0){
							len--;
							dd = data.pop();
							if(t){
								mw.data(dd,[dd]);
							}else{
							mw.data(dd);
							}
						}else{
							terminated++;
							mw.close();
							if(terminated===threads){
								reducer.close();
							}
						}
					});
				workers.push(mw);
				})();
				i++;
			}
			status.map=true;
			return checkStatus();
		};
		w.reduce=function(fun){
			if(status.reduce){
				return w;
			}
			reducer = rWorker(fun,function(d){
				w.resolve(d);
			});
			status.reduce=true;
			return checkStatus();
		};
		w.data = function(d){
			len = len + d.length;
			data = data.concat(d);
			status.data=true;
			return checkStatus();
		};
		function go(){
			var i = 0;
			var wlen = workers.length;
			while(i<wlen && len>0){
				len--;
				workers[i].data(data.pop());
				i++;
				terminated--;
			}
			w.data=function(){
				w.reject("can't add data, already called.");
				return w;
			};
			return w;
		}
		return w;
	};
	var incrementalMapReduce = function(threads){
		var w = new Communist();
		var len = 0;
		var promise;
		var workers = [];
		var data=[];
		var idle = threads;
		var reducer;
		var waiting=false;
		var closing=false;
		var status = {
			map:false,
			reduce:false,
			data:false
		};
		var checkStatus = function(){
			if(status.map && status.reduce && status.data){
				return go();
			}else{
				return w;
			}
		};
		w.map=function(fun, t){
			window._temp=[];
			if(status.map){
				return w;
			}
			var i = 0;
			while(i<threads){
				(function(){
					var dd;
					var mw = mapWorker(fun, function(d){
						if(typeof d !== undefined){
							reducer.data(d);
							window._temp.push(d);
						}
						if(len>0){
							len--;
							dd = data.pop();
							if(t){
								mw.data(dd,[dd]);
							}else{
							mw.data(dd);
							}
						}else{
							idle++;
							if(idle===threads){
								status.data=false;
								if(closing){
								closeUp();
								}else if(waiting){
									waiting = false;
									reducer.fetch();
								}
							}
						}
					});
				workers.push(mw);
				})();
				i++;
			}
			status.map=true;
			return checkStatus();
		};
		w.reduce=function(fun){
			if(status.reduce){
				return w;
			}
			reducer = rWorker(fun,function(d){
				if(promise){
					promise.resolve(d);
					promise = false;
				}
			});
			status.reduce=true;
			return checkStatus();
		};
		w.data = function(d){
			if(closing){
				return;
			}
			len = len + d.length;
			data = data.concat(d);
			status.data=true;
			return checkStatus();
		};
		function go(){
			var i = 0;
			var wlen = workers.length;
			while(i<wlen && len>0 && idle>0){
				len--;
				workers[i].data(data.pop());
				i++;
				idle--;
			}
			return w;
		}
		w.fetch=function(now){
			if(!promise){
				promise = new RSVP.Promise();
			}
			if(idle<threads && !now){
				waiting=true;
			}else{
				reducer.fetch();
			}
			return promise;
		};
		w.close=function(){
			if(!promise){
				promise = new RSVP.Promise();
			}
			if(idle<threads){
				closing=true;
			}else{
				closeUp();
			}
			return promise;
		};
		function closeUp(){
			reducer.close();
			workers.forEach(function(v){
				v.close();
			});
		}
		return w;
	};
	var p=function(a,b){
		if(typeof a === "function" && typeof b === "function"){
			return mapWorker(a,b);
		}else if(typeof a === "function" || typeof a === "string"){
			return b ? oneOff(a,b):sticksAround(a);
		}else if(typeof a === "number"){
			return b ? incrementalMapReduce(a):nonIncrementalMapReduce(a);
		}
	};
	p.makeUrl = function (fileName) {
		var link = document.createElement("link");
		link.href = fileName;
		return link.href;
	};
	p.ajax = function(url,after,notjson){
		var txt=!notjson?'JSON.parse(request.responseText)':"request.responseText";
		var resp = after?"("+after.toString()+")("+txt+",cb)":txt;
		var func = 'function (url, cb) {\
			var request = new XMLHttpRequest();\
			request.open("GET", url);\
				request.onreadystatechange = function() {\
					var _resp;\
					if (request.readyState === 4 && request.status === 200) {'+
						'_resp = '+resp+';\
						if(typeof _resp!=="undefined"){cb(_resp);}\
						}\
				};\
			request.send();\
		}';
		return p(func,p.makeUrl(url));
	};
	p.reducer = rWorker;
	p.worker = makeWorker;
	window.communist=p;
})();<commit_msg>fixed chain bug which #13 pointed out<commit_after>(function(){
	var Communist = function(){};
	var makeWorker = function(strings){
		var URL = window.URL || window.webkitURL || self.URL;
		return new Worker(URL.createObjectURL(new Blob([strings.join("")],{type: "text/javascript"})));
	};
	var oneOff = function(fun,data){
		var promise = new RSVP.Promise();
		var worker = makeWorker(['var fun = ',fun,';\
		function _clb(data,transfer){\
				self.postMessage(data,transfer);\
				self.close();\
			}\
			var _rst = fun(',JSON.stringify(data),',_clb);\
			if(typeof _rst !== "undefined"){\
				_clb(_rst);\
			}']);
		worker.onmessage=function(e){
			promise.resolve(e.data);
		};
		worker.onerror=function(e){
			promise.reject(e);
		};
		return promise;
	};
	var mapWorker=function(fun,callback,onerr){
		var w = new Communist();
		var worker = makeWorker(['var _db={};var fun = ',fun,';\
			function _clb(data,transfer){\
				self.postMessage(data,transfer);\
			}\
			self.onmessage=function(e){\
			var _rst = fun(e.data,_clb);\
				if(typeof _rst !== "undefined"){\
					_clb(_rst);\
				}\
			}']);
		worker.onmessage = function(e){
			callback(e.data);
		};
		worker.onerror=onerr||function(){callback();};
		w.data=function(d,t){
			worker.postMessage(d,t);
			return w;
		};
		w.close=function(){
			return worker.terminate();
		};
		return w;
	};
	var sticksAround = function(fun){
		var w = new Communist();
		var promises = [];
		var rejectPromises = function(msg){
			promises.forEach(function(p){
				if(p){
					p.reject(msg);
				}
			});
		};
		var func = 'function(data,cb){var _fun = '+fun+';\
			var _nCB = function(num,d,tran){\
			cb([num,d],tran);\
			};\
			var _bCB = _nCB.bind(self,data[0]);\
			var _nR = _fun(data[1],_bCB);\
			if(typeof _nR !== "undefined"){\
				_bCB(_nR);\
			}\
		}';
		var callback = function(data){
				promises[data[0]].resolve(data[1]);
				promises[data[0]]=0;
		};
		var worker = mapWorker(func, callback,rejectPromises);
		w.close = function(){
			worker.close();
			rejectPromises("closed");
			return;
		};
		w.data=function(data, transfer){
			var i = promises.length;
			promises[i] = new RSVP.Promise();
			worker.data([i,data],transfer);
			return promises[i];
		};
		return w;
	};
	var rWorker = function(fun,callback){
		var w = new Communist();
		var func = 'function(dat,cb){ var fun = '+fun+';\
			switch(dat[0]){\
				case "data":\
					if(!_db._r){\
						_db._r = dat[1];\
					}else{\
						_db._r = fun(_db._r,dat[1]);\
					}\
					break;\
				case "get":\
					return cb(_db._r);\
				case "close":\
					cb(_db._r);\
					self.close();\
					break;\
			}\
		};'
		var cb =function(data){
			callback(data);
		};
		var worker = mapWorker(func,cb);
		w.data=function(data,transfer){
			worker.data(["data",data],transfer);
			return w;
		};
		w.fetch=function(){
			worker.data(["get"]);
			return w;
		};
		w.close=function(silent){
			if(silent){
				callback=function(){};
			}
			worker.data(["close"]);
			return;
		};
		return w;
	};
	var nonIncrementalMapReduce = function(threads){
		var data=[];
		var len = 0;
		var reducer;
		var w = new RSVP.Promise();
		var workers = [];
		var terminated = threads;
		var status = {
			map:false,
			reduce:false,
			data:false
		};
		var checkStatus = function(){
			if(status.map && status.reduce && status.data){
				return go();
			}else{
				return w;
			}
		};
		w.map=function(fun,t){
			if(status.map){
				return w;
			}
			var i = 0;
			while(i<threads){
				var dd;
				(function(){
					var mw = mapWorker(fun, function(d){
						if(typeof d !== undefined){
							reducer.data(d);
						}
						if(len>0){
							len--;
							dd = data.pop();
							if(t){
								mw.data(dd,[dd]);
							}else{
							mw.data(dd);
							}
						}else{
							terminated++;
							mw.close();
							if(terminated===threads){
								reducer.close();
							}
						}
					});
				workers.push(mw);
				})();
				i++;
			}
			status.map=true;
			return checkStatus();
		};
		w.reduce=function(fun){
			if(status.reduce){
				return w;
			}
			reducer = rWorker(fun,function(d){
				w.resolve(d);
			});
			status.reduce=true;
			return checkStatus();
		};
		w.data = function(d){
			len = len + d.length;
			data = data.concat(d);
			status.data=true;
			return checkStatus();
		};
		function go(){
			var i = 0;
			var wlen = workers.length;
			while(i<wlen && len>0){
				len--;
				workers[i].data(data.pop());
				i++;
				terminated--;
			}
			w.data=function(){
				w.reject("can't add data, already called.");
				return w;
			};
			return w;
		}
		return w;
	};
	var incrementalMapReduce = function(threads){
		var w = new Communist();
		var len = 0;
		var promise;
		var workers = [];
		var data=[];
		var idle = threads;
		var reducer;
		var waiting=false;
		var closing=false;
		var status = {
			map:false,
			reduce:false,
			data:false
		};
		var checkStatus = function(){
			if(status.map && status.reduce && status.data){
				return go();
			}else{
				return w;
			}
		};
		w.map=function(fun, t){
			window._temp=[];
			if(status.map){
				return w;
			}
			var i = 0;
			while(i<threads){
				(function(){
					var dd;
					var mw = mapWorker(fun, function(d){
						if(typeof d !== undefined){
							reducer.data(d);
							window._temp.push(d);
						}
						if(len>0){
							len--;
							dd = data.pop();
							if(t){
								mw.data(dd,[dd]);
							}else{
							mw.data(dd);
							}
						}else{
							idle++;
							if(idle===threads){
								status.data=false;
								if(closing){
								closeUp();
								}else if(waiting){
									waiting = false;
									reducer.fetch();
								}
							}
						}
					});
				workers.push(mw);
				})();
				i++;
			}
			status.map=true;
			return checkStatus();
		};
		w.reduce=function(fun){
			if(status.reduce){
				return w;
			}
			reducer = rWorker(fun,function(d){
				if(promise){
					promise.resolve(d);
					promise = false;
				}
			});
			status.reduce=true;
			return checkStatus();
		};
		w.data = function(d){
			if(closing){
				return;
			}
			len = len + d.length;
			data = data.concat(d);
			status.data=true;
			return checkStatus();
		};
		function go(){
			var i = 0;
			var wlen = workers.length;
			while(i<wlen && len>0 && idle>0){
				len--;
				workers[i].data(data.pop());
				i++;
				idle--;
			}
			return w;
		}
		w.fetch=function(now){
			if(!promise){
				promise = new RSVP.Promise();
			}
			if(idle<threads && !now){
				waiting=true;
			}else{
				reducer.fetch();
			}
			return promise;
		};
		w.close=function(){
			if(!promise){
				promise = new RSVP.Promise();
			}
			if(idle<threads){
				closing=true;
			}else{
				closeUp();
			}
			return promise;
		};
		function closeUp(){
			reducer.close();
			workers.forEach(function(v){
				v.close();
			});
		}
		return w;
	};
	var p=function(a,b){
		if(typeof a === "function" && typeof b === "function"){
			return mapWorker(a,b);
		}else if(typeof a === "function" || typeof a === "string"){
			return b ? oneOff(a,b):sticksAround(a);
		}else if(typeof a === "number"){
			return b ? incrementalMapReduce(a):nonIncrementalMapReduce(a);
		}
	};
	p.makeUrl = function (fileName) {
		var link = document.createElement("link");
		link.href = fileName;
		return link.href;
	};
	p.ajax = function(url,after,notjson){
		var txt=!notjson?'JSON.parse(request.responseText)':"request.responseText";
		var resp = after?"("+after.toString()+")("+txt+",cb)":txt;
		var func = 'function (url, cb) {\
			var request = new XMLHttpRequest();\
			request.open("GET", url);\
				request.onreadystatechange = function() {\
					var _resp;\
					if (request.readyState === 4 && request.status === 200) {'+
						'_resp = '+resp+';\
						if(typeof _resp!=="undefined"){cb(_resp);}\
						}\
				};\
			request.send();\
		}';
		return p(func,p.makeUrl(url));
	};
	p.reducer = rWorker;
	p.worker = makeWorker;
	window.communist=p;
})();<|endoftext|>


<commit_before>/*global $: false, console: false */
/*jslint browser: true, sloppy: true, forin: true, plusplus: true, maxerr: 50, indent: 4 */

/*

	Component Name
	VERSION 0.0.1
	AUTHOR X.X.

	DEPENDENCIES:

	- jQuery

	TODO:

	-

*/

window.Component = function (target, options) {
	var self = this,
		defaults;

	// Event subscription setup

	self.events.parent = self;
	self.callbacks = {};

	// Options

	defaults = {};
	$.extend(defaults, options);
	self.options = defaults;

	// Element references

	self.$target = $(target);

	// Properties

	// Setup

	// Event Delegation

};

window.Component.prototype = {
	events: {
		actionHappened: function (event) {
			var self = this.parent;

			self.runCallbacks('actionHappened', event);
		}
	},
	action: function () {
		var self = this;

		self.events.actionHappened({metadata: 'More event info...'});
	},
	bind: function (eventType, callback, scope) {
		var self = this;

		if (typeof self.callbacks[eventType] === 'undefined') {
			self.callbacks[eventType] = [];
		}

		self.callbacks[eventType].push({
			callback: callback,
			scope: scope
		});
	},
	unbind: function (eventType) {
		var self = this;

		self.callbacks[eventType] = [];
	},
	runCallbacks: function (eventType, eventData) {
		var self = this,
			i,
			ii;

		if (typeof self.callbacks[eventType] !== 'undefined') {
			for (i = 0, ii = self.callbacks[eventType].length; i < ii; i++) {
				self.callbacks[eventType][i].callback.call(self.callbacks[eventType][i].scope || self, eventData);
			}
		}
	}
};<commit_msg>tabs to spaces; versioning dependency<commit_after>/*global $: false, console: false */
/*jslint browser: true, sloppy: true, forin: true, plusplus: true, maxerr: 50, indent: 4 */

/*

    Component Name
    VERSION 0.0.1
    AUTHOR X.X.

    DEPENDENCIES:

    - jQuery 1.7.2

    TODO:

    -

*/

window.Component = function (target, options) {
    var self = this,
        defaults;

    // Event subscription setup

    self.events.parent = self;
    self.callbacks = {};

    // Options

    defaults = {};
    $.extend(defaults, options);
    self.options = defaults;

    // Element references

    self.$target = $(target);

    // Properties

    // Setup

    // Event Delegation

};

window.Component.prototype = {
    events: {
        actionHappened: function (event) {
            var self = this.parent;

            self.runCallbacks('actionHappened', event);
        }
    },
    action: function () {
        var self = this;

        self.events.actionHappened({metadata: 'More event info...'});
    },
    bind: function (eventType, callback, scope) {
        var self = this;

        if (typeof self.callbacks[eventType] === 'undefined') {
            self.callbacks[eventType] = [];
        }

        self.callbacks[eventType].push({
            callback: callback,
            scope: scope
        });
    },
    unbind: function (eventType) {
        var self = this;

        self.callbacks[eventType] = [];
    },
    runCallbacks: function (eventType, eventData) {
        var self = this,
            i,
            ii;

        if (typeof self.callbacks[eventType] !== 'undefined') {
            for (i = 0, ii = self.callbacks[eventType].length; i < ii; i++) {
                self.callbacks[eventType][i].callback.call(self.callbacks[eventType][i].scope || self, eventData);
            }
        }
    }
};<|endoftext|>


<commit_before>/**
    Framework for building object relational database apps
    Copyright (C) 2018  John Rogelstad

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
**/
/*jslint node, es6, eval */
(function () {
    "strict";

    require("./common/extend-string.js");

    const {
        Client
    } = require("pg");
    const {
        Config
    } = require("./server/config");
    const {
        API
    } = require("./scripts/api");
    const fs = require("fs");
    const path = require("path");
    const datasource = require("./server/datasource");
    const format = require("pg-format");
    const MANIFEST = "manifest.json";
    const api = new API();

    var manifest, file, content, execute, name, defineSettings,
            saveModule, saveService, saveRoute, saveFeathers, saveWorkbooks,
            rollback, connect, commit, begin, processFile, client, user,
            runBatch, configure,
            config = new Config(),
            dir = path.resolve(__dirname, process.argv[2] || "."),
            filename = path.format({
        root: "/",
        dir: dir,
        base: MANIFEST
    }),
            exit = process.exit,
            i = 0;

    connect = function (callback) {
        config.read().then(function (config) {
            user = config.postgres.user;
            client = new Client(config.postgres);

            client.connect(function (err) {
                if (err) {
                    return console.error(err);
                }

                callback();
            });
        });
    };

    begin = function () {
        //console.log("BEGIN");
        client.query("BEGIN;", processFile);
    };

    commit = function () {
        return new Promise(function (resolve) {
            client.query("COMMIT;", function () {
                //console.log("COMMIT");
                client.end();
                resolve();
            });
        });
    };

    rollback = function (err) {
        client.query("ROLLBACK;", function () {
            console.error(err);
            //console.log("ROLLBACK");
            console.error("Configuration failed.");
            client.end();
            process.exit();
        });
    };

    execute = function (filename) {
        var dep = path.resolve(filename),
            exp = require(dep);

        exp.execute({
            user: user,
            client: client
        })
            .then(processFile)
            .catch(rollback);
    };

    processFile = function () {
        var filepath, module, version, dependencies;

        function done() {
            console.log("Configuration completed!");
            process.exit();
        }

        file = manifest.files[i];
        i += 1;

        // If we've processed all the files, wrap this up
        if (!file) {
            Promise.resolve()
                .then(commit)
                .then(api.build)
                .then(done)
                .catch(function (err) {
                    console.error(err);
                    process.exit();
                });
            return;
        }

        filename = file.path;
        name = path.parse(filename).name;
        filepath = path.format({
            root: "/",
            dir: dir,
            base: filename
        });

        module = file.module || manifest.module;
        version = file.version || manifest.version;
        dependencies = file.dependencies || manifest.dependencies;

        fs.readFile(filepath, "utf8", function (err, data) {
            if (err) {
                console.error(err);
                return;
            }

            content = data;

            console.log("Configuring " + filename);

            switch (file.type) {
            case "configure":
                configure(filename);
                break;
            case "execute":
                execute(filename);
                break;
            case "module":
                saveModule(module, content, version, dependencies);
                break;
            case "service":
                saveService(file.name || name, module, content, version);
                break;
            case "route":
                saveRoute(file.name || name, module, content, version);
                break;
            case "feather":
                saveFeathers(JSON.parse(content), file.isSystem);
                break;
            case "batch":
                runBatch(JSON.parse(content));
                break;
            case "workbook":
                saveWorkbooks(JSON.parse(content));
                break;
            case "settings":
                defineSettings(JSON.parse(content));
                break;
            default:
                rollback("Unknown type.");
                return;
            }
        });
    };

    configure = function (filename) {
        var submanifest,
            subfilepath = path.format({
                root: "/",
                dir: dir,
                base: filename
            }),
            subdir = path.parse(filename).dir,
            n = i;

        fs.readFile(subfilepath, "utf8", function (err, data) {
            if (err) {
                console.error(err);
                return;
            }

            submanifest = JSON.parse(data);
            submanifest.files.forEach(function (file) {
                file.path = subdir + "/" + file.path;
                file.module = file.module || submanifest.module || manifest.module;
                file.version = file.version || submanifest.version || manifest.version;
                file.dependencies = file.dependencies || submanifest.dependencies || manifest.dependencies;
                manifest.files.splice(n, 0, file);
                n += 1;
            });
            processFile();
        });
    };

    defineSettings = function (settings) {
        var sql = "SELECT * FROM \"$settings\" WHERE name='" + settings.name + "';",
            params = [settings.name, settings];

        client.query(sql, function (err, result) {
            if (err) {
                rollback(err);
                return;
            }
            if (result.rows.length) {
                sql = "UPDATE \"$settings\" SET " +
                        "definition=$2 WHERE name=$1;";
            } else {
                params.push(user);
                sql = "INSERT INTO \"$settings\" (name, definition, id, " +
                        " created, created_by, updated, updated_by, is_deleted) " +
                        "VALUES ($1, $2, $1, now(), $3, now(), $3, false);";
            }

            client.query(sql, params, processFile);
        });
    };

    saveModule = function (name, script, version, dependencies) {
        var sql = "SELECT * FROM \"$module\" WHERE name='" + name + "';";

        client.query(sql, function (err, result) {
            var params = [
                name,
                version,
                {value: dependencies}
            ];

            if (err) {
                rollback(err);
                return;
            }
            if (result.rows.length) {
                sql = "UPDATE \"$module\" SET " +
                        "script=$$" + script + "$$," +
                        "version=$2," +
                        "dependencies=$3 " +
                        "WHERE name=$1;";
            } else {
                sql = "INSERT INTO \"$module\" VALUES ($1, $$" + script + "$$, $2, $3);";
            }

            client.query(sql, params, processFile);
        });
    };

    saveService = function (name, module, script, version) {
        var sql = "SELECT * FROM \"$service\" WHERE name='" + name + "';";

        client.query(sql, function (err, result) {
            if (err) {
                rollback(err);
                return;
            }
            if (result.rows.length) {
                sql = "UPDATE \"$service\" SET " +
                        "script=$$" + script + "$$," +
                        "version='" + version + "' " +
                        "WHERE name='" + name + "';";
            } else {
                sql = "INSERT INTO \"$service\" VALUES ('" + name +
                        "','" + module + "',$$" + script + "$$, '" + version + "');";
            }

            client.query(sql, processFile);
        });
    };

    saveRoute = function (name, module, script, version) {
        var sql = "SELECT * FROM \"$route\" WHERE name='" + name + "';";

        client.query(sql, function (err, result) {
            if (err) {
                rollback(err);
                return;
            }
            if (result.rows.length) {
                sql = "UPDATE \"$route\" SET " +
                        "script=$$" + script + "$$," +
                        "version='" + version + "' " +
                        "WHERE name='" + name + "';";
            } else {
                sql = "INSERT INTO \"$route\" VALUES ('" + name +
                        "','" + module + "',$$" + script + "$$, '" + version + "');";
            }

            client.query(sql, processFile);
        });
    };

    saveFeathers = function (feathers, isSystem) {
        var payload,
            data = [];

        // System feathers don't get to be tables
        if (isSystem) {
            payload = {
                method: "PUT",
                name: "saveFeather",
                user: user,
                client: client,
                data: {
                    specs: feathers
                }
            };

            datasource.request(payload)
                .then(processFile)
                .catch(rollback);
            return;
        }

        // Map feather structure to table structure
        feathers.forEach(function (feather) {
            var keys = Object.keys(feather.properties || {}),
                props = feather.properties;

            feather.properties = keys.map(function (key) {
                var prop = props[key];
                prop.name = key;
                return prop;
            });

            data.push({
                name: "TableSpec",
                method: "POST",
                id: feather.name,
                data: feather
            });
        });

        runBatch(data);
    };

    saveWorkbooks = function (workbooks) {
        var payload = {
            method: "PUT",
            name: "saveWorkbook",
            user: user,
            client: client,
            data: {
                specs: workbooks
            }
        };

        datasource.request(payload)
            .then(processFile)
            .catch(rollback);
    };

    runBatch = function (data) {
        var getServices, nextItem,
                len = data.length,
                b = 0;

        getServices = function () {
            var payload, after;

            after = function (resp) {
                resp.forEach(function (service) {
                    eval(service.script);
                });
                nextItem();
            };

            payload = {
                method: "GET",
                name: "getServices",
                user: "postgres",
                client: client
            };

            datasource.request(payload).then(after).catch(exit);
        };

        // Iterate recursively
        nextItem = function () {
            var payload;

            if (b < len) {
                payload = data[b];
                payload.user = user;
                payload.client = client;
                b += 1;
                datasource.request(payload)
                    .then(nextItem)
                    .catch(rollback);
                return;
            }

            // We're done here
            processFile();
        };

        // Start processing
        getServices();
    };

    /* Real work starts here */
    fs.readFile(filename, "utf8", function (err, data) {
        if (err) {
            console.error(err);
            return;
        }

        var exec = function () {
            manifest = JSON.parse(data);
            connect(begin);
        };

        config.read().then(function (config) {
            var pgclient,
                conn = "postgres://" +
                        config.postgres.user + ":" +
                        config.postgres.password + "@" +
                        config.postgres.host + ":" +
                        config.postgres.port + "/" + "postgres";

            pgclient = new Client({
                connectionString: conn
            });

            pgclient.connect(function (err) {
                if (err) {
                    return console.error(err);
                }

                var sql = "SELECT datname FROM pg_database " +
                        "WHERE datistemplate = false AND datname = $1";

                pgclient.query(sql, [config.postgres.database], function (err, resp) {
                    if (err) {
                        return console.error(err);
                    }

                    // If database exists, get started
                    if (resp.rows.length === 1) {
                        datasource.getCatalog().then(exec).catch(exit);
                        // Otherwise create database first
                    } else {
                        console.log('Creating database "' + config.postgres.database + '"');
                        sql = "CREATE DATABASE %I;";
                        sql = format(sql, config.postgres.database, config.postgres.user);
                        pgclient.query(sql, function () {
                            if (err) {
                                return console.error(err);
                            }
                            exec();
                        });
                    }
                });
            });
        });
    });
}());<commit_msg>Update configure.js<commit_after>/**
    Framework for building object relational database apps
    Copyright (C) 2018  John Rogelstad

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
**/
/*jslint node, eval */
(function () {
    "use strict";

    require("./common/extend-string.js");

    const {
        Client
    } = require("pg");
    const {
        Config
    } = require("./server/config");
    const {
        API
    } = require("./scripts/api");
    const fs = require("fs");
    const path = require("path");
    const datasource = require("./server/datasource");
    const format = require("pg-format");
    const MANIFEST = "manifest.json";
    const api = new API();

    let manifest;
    let file;
    let content;
    let execute;
    let name;
    let defineSettings;
    let saveModule;
    let saveService;
    let saveRoute;
    let saveFeathers;
    let saveWorkbooks;
    let rollback;
    let connect;
    let commit;
    let begin;
    let processFile;
    let client;
    let user;
    let runBatch;
    let configure;
    let config = new Config();
    let dir = path.resolve(__dirname, process.argv[2] || ".");
    let filename = path.format({
        root: "/",
        dir: dir,
        base: MANIFEST
    });
    let exit = process.exit;
    let i = 0;

    connect = function (callback) {
        config.read().then(function (config) {
            user = config.postgres.user;
            client = new Client(config.postgres);

            client.connect(function (err) {
                if (err) {
                    return console.error(err);
                }

                callback();
            });
        });
    };

    begin = function () {
        //console.log("BEGIN");
        client.query("BEGIN;", processFile);
    };

    commit = function () {
        return new Promise(function (resolve) {
            client.query("COMMIT;", function () {
                //console.log("COMMIT");
                client.end();
                resolve();
            });
        });
    };

    rollback = function (err) {
        client.query("ROLLBACK;", function () {
            console.error(err);
            //console.log("ROLLBACK");
            console.error("Configuration failed.");
            client.end();
            process.exit();
        });
    };

    execute = function (filename) {
        let dep = path.resolve(filename);
        let exp = require(dep);

        exp.execute({
            user: user,
            client: client
        }).then(processFile).catch(rollback);
    };

    processFile = function () {
        let filepath;
        let module;
        let version;
        let dependencies;

        function done() {
            console.log("Configuration completed!");
            process.exit();
        }

        file = manifest.files[i];
        i += 1;

        // If we've processed all the files, wrap this up
        if (!file) {
            Promise.resolve().then(commit).then(api.build).then(done).catch(
                function (err) {
                    console.error(err);
                    process.exit();
                }
            );
            return;
        }

        filename = file.path;
        name = path.parse(filename).name;
        filepath = path.format({
            root: "/",
            dir: dir,
            base: filename
        });

        module = file.module || manifest.module;
        version = file.version || manifest.version;
        dependencies = file.dependencies || manifest.dependencies;

        fs.readFile(filepath, "utf8", function (err, data) {
            if (err) {
                console.error(err);
                return;
            }

            content = data;

            console.log("Configuring " + filename);

            switch (file.type) {
            case "configure":
                configure(filename);
                break;
            case "execute":
                execute(filename);
                break;
            case "module":
                saveModule(module, content, version, dependencies);
                break;
            case "service":
                saveService(file.name || name, module, content, version);
                break;
            case "route":
                saveRoute(file.name || name, module, content, version);
                break;
            case "feather":
                saveFeathers(JSON.parse(content), file.isSystem);
                break;
            case "batch":
                runBatch(JSON.parse(content));
                break;
            case "workbook":
                saveWorkbooks(JSON.parse(content));
                break;
            case "settings":
                defineSettings(JSON.parse(content));
                break;
            default:
                rollback("Unknown type.");
                return;
            }
        });
    };

    configure = function (filename) {
        let subman;
        let subfilepath = path.format({
            root: "/",
            dir: dir,
            base: filename
        });
        let subdir = path.parse(filename).dir;
        let n = i;

        fs.readFile(subfilepath, "utf8", function (err, data) {
            if (err) {
                console.error(err);
                return;
            }

            subman = JSON.parse(data);
            subman.files.forEach(function (file) {
                file.path = subdir + "/" + file.path;
                file.module = file.module || subman.module;
                file.module = file.module || manifest.module;
                file.version = file.version || subman.version;
                file.version = file.version || manifest.version;
                file.dependencies = file.dependencies || subman.dependencies;
                file.dependencies = file.dependencies || manifest.dependencies;
                manifest.files.splice(n, 0, file);
                n += 1;
            });
            processFile();
        });
    };

    defineSettings = function (settings) {
        let sql;
        let params = [settings.name, settings];

        sql = "SELECT * FROM \"$settings\" WHERE name='";
        sql += settings.name + "';";

        client.query(sql, function (err, result) {
            if (err) {
                rollback(err);
                return;
            }
            if (result.rows.length) {
                sql = "UPDATE \"$settings\" SET ";
                sql += "definition=$2 WHERE name=$1;";
            } else {
                params.push(user);
                sql = "INSERT INTO \"$settings\" (name, definition, id, ";
                sql += "created, created_by, updated, updated_by,";
                sql += " is_deleted) ";
                sql += "VALUES ($1, $2, $1, now(), $3, now(), $3, false);";
            }

            client.query(sql, params, processFile);
        });
    };

    saveModule = function (name, script, version, dependencies) {
        let sql = "SELECT * FROM \"$module\" WHERE name='" + name + "';";

        client.query(sql, function (err, result) {
            let params = [
                name,
                version,
                {value: dependencies}
            ];

            if (err) {
                rollback(err);
                return;
            }
            if (result.rows.length) {
                sql = "UPDATE \"$module\" SET ";
                sql += "script=$$" + script + "$$,";
                sql += "version=$2,";
                sql += "dependencies=$3 ";
                sql += "WHERE name=$1;";
            } else {
                sql = "INSERT INTO \"$module\" ";
                sql += "VALUES ($1, $$" + script + "$$, $2, $3);";
            }

            client.query(sql, params, processFile);
        });
    };

    saveService = function (name, module, script, version) {
        let sql = "SELECT * FROM \"$service\" WHERE name='" + name + "';";

        client.query(sql, function (err, result) {
            if (err) {
                rollback(err);
                return;
            }
            if (result.rows.length) {
                sql = "UPDATE \"$service\" SET ";
                sql += "script=$$" + script + "$$,";
                sql += "version='" + version + "' ";
                sql += "WHERE name='" + name + "';";
            } else {
                sql = "INSERT INTO \"$service\" VALUES ('" + name;
                sql += "','" + module + "',$$" + script + "$$, '";
                sql += version + "');";
            }

            client.query(sql, processFile);
        });
    };

    saveRoute = function (name, module, script, version) {
        let sql = "SELECT * FROM \"$route\" WHERE name='" + name + "';";

        client.query(sql, function (err, result) {
            if (err) {
                rollback(err);
                return;
            }
            if (result.rows.length) {
                sql = "UPDATE \"$route\" SET ";
                sql += "script=$$" + script + "$$,";
                sql += "version='" + version + "' ";
                sql += "WHERE name='" + name + "';";
            } else {
                sql = "INSERT INTO \"$route\" VALUES ('" + name;
                sql += "','" + module + "',$$" + script + "$$, '";
                sql += version + "');";
            }

            client.query(sql, processFile);
        });
    };

    saveFeathers = function (feathers, isSystem) {
        let payload;
        let data = [];

        // System feathers don't get to be tables
        if (isSystem) {
            payload = {
                method: "PUT",
                name: "saveFeather",
                user: user,
                client: client,
                data: {
                    specs: feathers
                }
            };

            datasource.request(payload).then(processFile).catch(rollback);
            return;
        }

        // Map feather structure to table structure
        feathers.forEach(function (feather) {
            let keys = Object.keys(feather.properties || {});
            let props = feather.properties;

            feather.properties = keys.map(function (key) {
                let prop = props[key];
                prop.name = key;
                return prop;
            });

            data.push({
                name: "TableSpec",
                method: "POST",
                id: feather.name,
                data: feather
            });
        });

        runBatch(data);
    };

    saveWorkbooks = function (workbooks) {
        let payload = {
            method: "PUT",
            name: "saveWorkbook",
            user: user,
            client: client,
            data: {
                specs: workbooks
            }
        };

        datasource.request(payload).then(processFile).catch(rollback);
    };

    runBatch = function (data) {
        let getServices;
        let nextItem;
        let len = data.length;
        let b = 0;

        getServices = function () {
            let payload;
            let after;

            after = function (resp) {
                resp.forEach(function (service) {
                    eval(service.script);
                });
                nextItem();
            };

            payload = {
                method: "GET",
                name: "getServices",
                user: "postgres",
                client: client
            };

            datasource.request(payload).then(after).catch(exit);
        };

        // Iterate recursively
        nextItem = function () {
            let payload;

            if (b < len) {
                payload = data[b];
                payload.user = user;
                payload.client = client;
                b += 1;
                datasource.request(payload).then(nextItem).catch(rollback);
                return;
            }

            // We're done here
            processFile();
        };

        // Start processing
        getServices();
    };

    /* Real work starts here */
    fs.readFile(filename, "utf8", function (err, data) {
        if (err) {
            console.error(err);
            return;
        }

        let exec = function () {
            manifest = JSON.parse(data);
            connect(begin);
        };

        config.read().then(function (config) {
            let pgclient;
            let conn;

            conn = "postgres://";
            conn += config.postgres.user + ":";
            conn += config.postgres.password + "@";
            conn += config.postgres.host + ":";
            conn += config.postgres.port + "/" + "postgres";

            pgclient = new Client({
                connectionString: conn
            });

            pgclient.connect(function (err) {
                if (err) {
                    return console.error(err);
                }

                let sql;

                sql = "SELECT datname FROM pg_database ";
                sql += "WHERE datistemplate = false AND datname = $1";

                pgclient.query(sql, [config.postgres.database], function (
                    err,
                    resp
                ) {
                    let msg;

                    if (err) {
                        return console.error(err);
                    }

                    // If database exists, get started
                    if (resp.rows.length === 1) {
                        datasource.getCatalog().then(exec).catch(exit);
                        // Otherwise create database first
                    } else {
                        msg = "Creating database \"";
                        msg += config.postgres.database + "\"";
                        console.log(msg);

                        sql = "CREATE DATABASE %I;";
                        sql = format(
                            sql,
                            config.postgres.database,
                            config.postgres.user
                        );
                        pgclient.query(sql, function () {
                            if (err) {
                                return console.error(err);
                            }
                            exec();
                        });
                    }
                });
            });
        });
    });
}());<|endoftext|>


<commit_before>import m from 'mithril';
import _ from 'underscore';
import I18n from 'i18n-js';
import h from '../h';
import moment from 'moment';
import models from '../models';
import {catarse} from '../api';
import contributionVM from '../vms/contribution-vm';
import ownerMessageContent from '../c/owner-message-content';
import modalBox from '../c/modal-box';
import userVM from '../vms/user-vm';

const I18nScope = _.partial(h.i18nScope, 'payment.state');
const contributionScope = _.partial(h.i18nScope, 'users.contribution_row');

const userSubscriptionBox = {
    controller(args) {
        const subscription=args.subscription,
            displayModal = h.toggleProp(false, true),
            contactModalInfo = m.prop({});

        const filterProjVM = catarse.filtersVM({
                project_id: 'eq'
            }).project_id(subscription.project_external_id),
            lProj = catarse.loaderWithToken(models.project.getRowOptions(filterProjVM.parameters()));

        lProj.load().then(function(pr){
            subscription.project = pr[0];
            contactModalInfo({
                id: subscription.project.project_user_id,
                name: subscription.project.owner_name,
                project_id: subscription.project.project_id
            });
            console.log('subscription1:', JSON.stringify(subscription, null, 2));
        });

        if (subscription.reward_external_id) {
            const filterRewVM = catarse.filtersVM({
                    id: 'eq'
                }).id(subscription.reward_external_id),
                lRew = catarse.loaderWithToken(models.rewardDetail.getRowOptions(filterRewVM.parameters()));

            lRew.load().then(function(r) {
                subscription.reward = r[0];
                console.log('subscription2:', JSON.stringify(subscription, null, 2));
            });
        }

        return {
            toggleAnonymous: userVM.toggleAnonymous,
            displayModal,
            subscription,
            contactModalInfo
        };
    },
    view(ctrl) {
        const subscription = ctrl.subscription;

        return (!_.isEmpty(subscription) && !_.isEmpty(subscription.project) ? m('div',
            (ctrl.displayModal() && !_.isEmpty(ctrl.contactModalInfo())
                ? m.component(modalBox, {
                    displayModal: ctrl.displayModal,
                    content: [ownerMessageContent, ctrl.contactModalInfo]
                }) : ''
            ), [
                m('.card.w-row', [
                    m('.u-marginbottom-20.w-col.w-col-3', [
                        m('.u-marginbottom-10.w-row', [
                            m('.u-marginbottom-10.w-col.w-col-4',
                                m(`a.w-inline-block[href='/${subscription.project.permalink}']`,
                                    m(`img.thumb-project.u-radius[alt='${subscription.project.project_name}'][src='${subscription.project.project_img}'][width='50']`)
                                )
                            ),
                            m('.w-col.w-col-8',
                                m('.fontsize-small.fontweight-semibold.lineheight-tight',
                                    [
                                        m(`a.link-hidden[href='/${subscription.project.permalink}']`,
                                            subscription.project.project_name
                                        ),
                                        m('img[alt="Badge Assinatura"][src="/assets/catarse_bootstrap/badge-sub-h.png"]')
                                    ]
                                )
                            )
                        ]),
                        m("a.btn.btn-edit.btn-inline.btn-small.w-button[href='javascript:void(0);']", {
                            onclick: () => {
                                ctrl.displayModal.toggle();
                            }
                        },
                            I18n.t('contact_author', contributionScope())
                        )
                    ]),
                    m('.u-marginbottom-20.w-col.w-col-3', [
                        m('.fontsize-base.fontweight-semibold.lineheight-looser',
                            `R$ ${h.formatNumber(parseFloat(subscription.checkout_data.amount) / 100)} por mês`
                        ),
                        m('.fontcolor-secondary.fontsize-smaller.fontweight-semibold',
                            `Assinante há ${moment(subscription.created_at).locale('pt').fromNow(true)}`
                        ),
                        m('.w-embed',
                            m('div', [
                                m('.w-hidden-main.w-hidden-medium.fontsize-smallest.fontweight-semibold',
                                    I18n.t('status', contributionScope())
                                ),
                                m('.fontsize-smallest',
                                    (subscription.checkout_data.payment_method === 'BoletoBancario' ? 'Boleto Bancário' : 'Cartão de Crédito')
                                ),
                                (contributionVM.canShowReceipt(subscription) ?
                                    m(`a.alt-link.u-margintop-10[href='/projects/${subscription.project.id}/contributions/${subscription.contribution_id}/receipt'][target='__blank']`,
                                        I18n.t('show_receipt', contributionScope())
                                    ) : ''),

                                (subscription.gateway_data && contributionVM.canShowSlip(subscription) ?
                                    m(`a.alt-link.u-margintop-10[href='${subscription.gateway_data.boleto_url}'][target='__blank']`,
                                        I18n.t('print_slip', contributionScope())
                                    ) : ''),

                                (subscription.gateway_data && contributionVM.canGenerateSlip(subscription) ?
                                    m(`a.alt-link.u-margintop-10[href='/projects/${subscription.project.id}/contributions/${subscription.contribution_id}/second_slip'][target='__blank']`,
                                        I18n.t('slip_copy', contributionScope())
                                    ) : '')
                            ])
                        )
                    ]),
                    m('.u-marginbottom-20.w-col.w-col-3', [
                        (subscription.reward ? [m('.fontsize-smallest.fontweight-semibold',
                            subscription.reward.title
                        ), m('p.fontcolor-secondary.fontsize-smallest', m.trust(h.simpleFormat(
                            `${subscription.reward.description.substring(0, 90)} (...)`
                        )))] : (subscription.reward_external_id ? null : ` ${I18n.t('no_reward', contributionScope())} `))
                    ]),
                    m('.u-marginbottom-10.u-text-center.w-col.w-col-3',
                        (subscription.status === 'inactive' ? [
                            m('.card-alert.fontsize-smaller.fontweight-semibold.u-marginbottom-10.u-radius', [
                                m('span.fa.fa-exclamation-triangle'),
                                'Sua assinatura está suspensa por falta de pagamento'
                            ])
                        ] : subscription.status === 'canceled' ? [
                            m('.card-error.fontsize-smaller.fontweight-semibold.u-marginbottom-10.u-radius', [
                                m('span.fa.fa-exclamation-triangle'),
                                ' Você cancelou sua assinatura'
                            ])
                        ] : null)
                    )
                ])
            ]
        ) : m('div', '')
        );
    }
};

export default userSubscriptionBox;
<commit_msg>Added subscribe again button<commit_after>import m from 'mithril';
import _ from 'underscore';
import I18n from 'i18n-js';
import h from '../h';
import moment from 'moment';
import models from '../models';
import {catarse} from '../api';
import contributionVM from '../vms/contribution-vm';
import ownerMessageContent from '../c/owner-message-content';
import modalBox from '../c/modal-box';
import userVM from '../vms/user-vm';

const I18nScope = _.partial(h.i18nScope, 'payment.state');
const contributionScope = _.partial(h.i18nScope, 'users.contribution_row');

const userSubscriptionBox = {
    controller(args) {
        const subscription=args.subscription,
            displayModal = h.toggleProp(false, true),
            contactModalInfo = m.prop({});

        const filterProjVM = catarse.filtersVM({
                project_id: 'eq'
            }).project_id(subscription.project_external_id),
            lProj = catarse.loaderWithToken(models.project.getRowOptions(filterProjVM.parameters()));

        lProj.load().then(function(arr){
            subscription.project = arr[0];
            contactModalInfo({
                id: subscription.project.project_user_id,
                name: subscription.project.owner_name,
                project_id: subscription.project.project_id
            });
            // console.log('subscription1:', JSON.stringify(subscription, null, 2));
        });

        if (subscription.reward_external_id) {
            const filterRewVM = catarse.filtersVM({
                    id: 'eq'
                }).id(subscription.reward_external_id),
                lRew = catarse.loaderWithToken(models.rewardDetail.getRowOptions(filterRewVM.parameters()));

            lRew.load().then(function(arr) {
                subscription.reward = arr[0];
                // console.log('subscription2:', JSON.stringify(subscription, null, 2));
            });
        }

        return {
            toggleAnonymous: userVM.toggleAnonymous,
            displayModal,
            subscription,
            contactModalInfo
        };
    },
    view(ctrl) {
        const subscription = ctrl.subscription;

        return (!_.isEmpty(subscription) /*&& !_.isEmpty(subscription.project)*/ ? m('div',
            (ctrl.displayModal() && !_.isEmpty(ctrl.contactModalInfo())
                ? m.component(modalBox, {
                    displayModal: ctrl.displayModal,
                    content: [ownerMessageContent, ctrl.contactModalInfo]
                }) : ''
            ), [
                m('.card.w-row', [
                    m('.u-marginbottom-20.w-col.w-col-3', [
                        m('.u-marginbottom-10.w-row', [
                            m('.u-marginbottom-10.w-col.w-col-4',
                                m(`a.w-inline-block[href='/${subscription.project.permalink}']`,
                                    m(`img.thumb-project.u-radius[alt='${subscription.project.project_name}'][src='${subscription.project.project_img}'][width='50']`)
                                )
                            ),
                            m('.w-col.w-col-8',
                                m('.fontsize-small.fontweight-semibold.lineheight-tight',
                                    [
                                        m(`a.link-hidden[href='/${subscription.project.permalink}']`,
                                            subscription.project.project_name
                                        ),
                                        m('img[alt="Badge Assinatura"][src="/assets/catarse_bootstrap/badge-sub-h.png"]')
                                    ]
                                )
                            )
                        ]),
                        m("a.btn.btn-edit.btn-inline.btn-small.w-button[href='javascript:void(0);']", {
                            onclick: () => {
                                ctrl.displayModal.toggle();
                            }
                        },
                            I18n.t('contact_author', contributionScope())
                        )
                    ]),
                    m('.u-marginbottom-20.w-col.w-col-3', [
                        m('.fontsize-base.fontweight-semibold.lineheight-looser',
                            `R$ ${h.formatNumber(parseFloat(subscription.checkout_data.amount) / 100)} por mês`
                        ),
                        m('.fontcolor-secondary.fontsize-smaller.fontweight-semibold',
                            `Assinante há ${moment(subscription.created_at).locale('pt').fromNow(true)}`
                        ),
                        m('.w-embed',
                            m('div', [
                                m('.w-hidden-main.w-hidden-medium.fontsize-smallest.fontweight-semibold',
                                    I18n.t('status', contributionScope())
                                ),
                                m('.fontsize-smallest',
                                    (subscription.checkout_data.payment_method === 'BoletoBancario' ? 'Boleto Bancário' : 'Cartão de Crédito')
                                ),
                                (contributionVM.canShowReceipt(subscription) ?
                                    m(`a.alt-link.u-margintop-10[href='/projects/${subscription.project.id}/contributions/${subscription.contribution_id}/receipt'][target='__blank']`,
                                        I18n.t('show_receipt', contributionScope())
                                    ) : ''),

                                (subscription.gateway_data && contributionVM.canShowSlip(subscription) ?
                                    m(`a.alt-link.u-margintop-10[href='${subscription.gateway_data.boleto_url}'][target='__blank']`,
                                        I18n.t('print_slip', contributionScope())
                                    ) : ''),

                                (subscription.gateway_data && contributionVM.canGenerateSlip(subscription) ?
                                    m(`a.alt-link.u-margintop-10[href='/projects/${subscription.project.id}/contributions/${subscription.contribution_id}/second_slip'][target='__blank']`,
                                        I18n.t('slip_copy', contributionScope())
                                    ) : '')
                            ])
                        )
                    ]),
                    m('.u-marginbottom-20.w-col.w-col-3', [
                        (subscription.reward ? [m('.fontsize-smallest.fontweight-semibold',
                            subscription.reward.title
                        ), m('p.fontcolor-secondary.fontsize-smallest', m.trust(h.simpleFormat(
                            `${subscription.reward.description.substring(0, 90)} (...)`
                        )))] : (subscription.reward_external_id ? null : ` ${I18n.t('no_reward', contributionScope())} `))
                    ]),
                    m('.u-marginbottom-10.u-text-center.w-col.w-col-3',
                        (subscription.status === 'inactive' ? [
                            m('.card-alert.fontsize-smaller.fontweight-semibold.u-marginbottom-10.u-radius', [
                                m('span.fa.fa-exclamation-triangle'),
                                'Sua assinatura está suspensa por falta de pagamento'
                            ]),
                            m(`a.btn.btn-inline.btn-small.w-button[target=_blank][href=/projects/${subscription.project_external_id}/subscriptions/start${subscription.reward_external_id?'?reward_id='+subscription.reward_external_id:''}]`, 'Assinar novamente')
                        ] : subscription.status === 'canceled' ? [
                            m('.card-error.fontsize-smaller.fontweight-semibold.u-marginbottom-10.u-radius', [
                                m('span.fa.fa-exclamation-triangle'),
                                ' Você cancelou sua assinatura'
                            ])
                        ] : null)
                    )
                ])
            ]
        ) : m('div', '')
        );
    }
};

export default userSubscriptionBox;
<|endoftext|>