<commit_before>var optionAmount = 0;

$(function() {
    $('.vacant').prop('disabled', true);
    $('#vakant1').prop('disabled', false);

    var maxVotes = $("#maximumnrOfVotes").val();

    $('.optionsform').on('change', '.voteoption', function(event) {

        if ($(this).prop('checked')) {
            optionAmount++;
            if (optionAmount == maxVotes) {
                $('.voteoption:not(:checked)').prop('disabled', true);
            }
        } else {
            optionAmount--;
            $('.voteoption:not(.vacant):not(:checked)').prop('disabled', false);
            $('#vakant1').prop('disabled', false);
        }
        $("#votesleft").html(maxVotes - optionAmount);
    });
    $('.optionsform').on('change', '.vacant', function(event) {
        var id = $(this).prop('id');
        id = parseInt(id.replace('vakant', ''));
        var newId = '#vakant' + (id + 1);

        if ($(this).prop('checked')) {
            if (optionAmount)
                $(newId).prop('disabled', false);
        } else {
            if ($(newId).prop('checked')) {
                optionAmount--;
                $(newId).prop('checked', false);
                $(newId).prop('disabled', true);
            }

        }
        $("#votesleft").html(maxVotes - optionAmount);
    })

    window.setInterval(countDown, 1000);
    $("#votesleft").html(maxVotes);
    //$('.voteoption:class(:vakant)').prop('disabled', true);
    function countDown() {
        //  console.log($("#timeleft").html());
        $("#timeleft").html($("#timeleft").html() - 1);
        if ($("#timeleft").html() == 0) {
            location.reload();
        }
    }
});
<commit_msg>Updated name of variable<commit_after>var optionAmount = 0;

$(function() {
    $('.vacant').prop('disabled', true);
    $('#vakant1').prop('disabled', false);

    var maxVotes = $("#maximumNbrOfVotes").val();

    $('.optionsform').on('change', '.voteoption', function(event) {

        if ($(this).prop('checked')) {
            optionAmount++;
            if (optionAmount == maxVotes) {
                $('.voteoption:not(:checked)').prop('disabled', true);
            }
        } else {
            optionAmount--;
            $('.voteoption:not(.vacant):not(:checked)').prop('disabled', false);
            $('#vakant1').prop('disabled', false);
        }
        $("#votesleft").html(maxVotes - optionAmount);
    });
    $('.optionsform').on('change', '.vacant', function(event) {
        var id = $(this).prop('id');
        id = parseInt(id.replace('vakant', ''));
        var newId = '#vakant' + (id + 1);

        if ($(this).prop('checked')) {
            if (optionAmount)
                $(newId).prop('disabled', false);
        } else {
            if ($(newId).prop('checked')) {
                optionAmount--;
                $(newId).prop('checked', false);
                $(newId).prop('disabled', true);
            }

        }
        $("#votesleft").html(maxVotes - optionAmount);
    })

    window.setInterval(countDown, 1000);
    $("#votesleft").html(maxVotes);
    //$('.voteoption:class(:vakant)').prop('disabled', true);
    function countDown() {
        //  console.log($("#timeleft").html());
        $("#timeleft").html($("#timeleft").html() - 1);
        if ($("#timeleft").html() == 0) {
            location.reload();
        }
    }
});
<|endoftext|>


<commit_before>/*global MAPJS, Color, _, jQuery, Kinetic*/
/*jslint nomen: true, newcap: true*/
(function () {
	'use strict';
	/*shamelessly copied from http://james.padolsey.com/javascript/wordwrap-for-javascript */
	var COLUMN_WORD_WRAP_LIMIT = 25;
	function wordWrap(str, width, brk, cut) {
		brk = brk || '\n';
		width = width || 75;
		cut = cut || false;
		if (!str) {
			return str;
		}
		var regex = '.{1,' + width + '}(\\s|$)' + (cut ? '|.{' + width + '}|.+$' : '|\\S+?(\\s|$)');
		return str.match(new RegExp(regex, 'g')).join(brk);
	}
	function joinLines(string) {
		return string.replace(/\n/g, ' ');
	}
	function breakWords(string) {
		return wordWrap(joinLines(string), COLUMN_WORD_WRAP_LIMIT, '\n', false);
	}
	Kinetic.Idea = function (config) {
		var ENTER_KEY_CODE = 13,
			ESC_KEY_CODE = 27,
			self = this,
			unformattedText = joinLines(config.text),
			bgRect = function (offset) {
				return new Kinetic.Rect({
					strokeWidth: 1,
					cornerRadius: 10,
					x: offset,
					y: offset,
					visible: false
				});
			};
		config.text = breakWords(config.text);
		this.level = config.level;
		this.mmStyle = config.mmStyle;
		this.isSelected = false;
		config.draggable = config.level > 1;
		config.name = 'Idea';
		Kinetic.Group.call(this, config);
		this.rect = new Kinetic.Rect({
			strokeWidth: 1,
			cornerRadius: 10
		});
		this.rectbg1 = bgRect(8);
		this.rectbg2 = bgRect(4);
		this.text = new Kinetic.Text({
			text: config.text,
			fontSize: 14,
			fontFamily: 'Helvetica',
			lineHeight: 1.5,
			fontStyle: 'bold',
			align: 'center'
		});
		this.add(this.rectbg1);
		this.add(this.rectbg2);
		this.add(this.rect);
		this.add(this.text);
		this.setText = function (text) {
			unformattedText = text;
			self.text.setText(breakWords(text));
			self.setStyle();
		};
		this.setStyle();
		this.classType = 'Idea';
		this.getNodeAttrs = function () {
			return self.attrs;
		};
		this.isVisible = function (offset) {
			var stage = self.getStage();
			return stage && stage.isRectVisible(new MAPJS.Rectangle(self.attrs.x, self.attrs.y, self.getWidth(), self.getHeight()), offset);
		};
		this.editNode = function (shouldSelectAll) {
			self.fire(':editing');
			self.getLayer().draw();
			var canvasPosition = jQuery(self.getLayer().getCanvas().getElement()).offset(),
				ideaInput,
				onStageMoved = _.throttle(function () {
					ideaInput.css({
						top: canvasPosition.top + self.getAbsolutePosition().y,
						left: canvasPosition.left + self.getAbsolutePosition().x
					});
				}, 10),
				updateText = function (newText) {
					self.setStyle();
					self.getStage().draw();
					self.fire(':textChanged', {
						text: newText || unformattedText
					});
					ideaInput.remove();
					self.stopEditing = undefined;
					self.getStage().off('xChange yChange', onStageMoved);
				},
				onCommit = function () {
					updateText(ideaInput.val());
				},
				onCancelEdit = function () {
					updateText(unformattedText);
				},
				scale = self.getStage().getScale().x || 1;
			ideaInput = jQuery('<textarea type="text" wrap="soft" class="ideaInput"></textarea>')
				.css({
					top: canvasPosition.top + self.getAbsolutePosition().y,
					left: canvasPosition.left + self.getAbsolutePosition().x,
					width: (6 + self.getWidth()) * scale,
					height: (6 + self.getHeight()) * scale,
					'padding': 3 * scale + 'px',
					'font-size': self.text.attrs.fontSize * scale + 'px',
					'line-height': 1.2,
					'background-color': self.getBackground(),
					'margin': -3 * scale,
					'border-radius': self.rect.attrs.cornerRadius * scale + 'px',
					'border': self.rect.attrs.strokeWidth * (2 * scale) + 'px dashed ' + self.rect.attrs.stroke,
					'color': self.text.attrs.fill
				})
				.val(unformattedText)
				.appendTo('body')
				.keydown(function (e) {
					if (e.which === ENTER_KEY_CODE) {
						onCommit();
					} else if (e.which === ESC_KEY_CODE) {
						onCancelEdit();
					} else if (e.which === 9) {
						e.preventDefault();
					} else if (e.which === 83 && (e.metaKey || e.ctrlKey)) {
						e.preventDefault();
						onCommit();
						return; /* propagate to let the environment handle ctrl+s */
					} else if (!e.shiftKey && e.which === 90 && (e.metaKey || e.ctrlKey)) {
						if (ideaInput.val() === unformattedText) {
							onCancelEdit();
						}
					}
					e.stopPropagation();
				})
				.blur(onCommit)
				.focus(function () {
					if (shouldSelectAll) {
						if (ideaInput[0].setSelectionRange) {
							ideaInput[0].setSelectionRange(0, unformattedText.length);
						} else {
							ideaInput.select();
						}
					} else if (ideaInput[0].setSelectionRange) {
						ideaInput[0].setSelectionRange(unformattedText.length, unformattedText.length);
					}
				})
				.on('input', function () {
					var text = new Kinetic.Idea({
						text: ideaInput.val()
					});
					ideaInput.width(Math.max(ideaInput.width(), text.getWidth() * scale));
					ideaInput.height(Math.max(ideaInput.height(), text.getHeight() * scale));
				});

			self.stopEditing = onCancelEdit;
			ideaInput.focus();

			self.getStage().on('xChange yChange', onStageMoved);
		};
	};
}());

Kinetic.Idea.prototype.setShadowOffset = function (offset) {
	'use strict';
	offset = this.getMMScale().x * offset;
	_.each([this.rect, this.rectbg1, this.rectbg2], function (r) {
		r.setShadowOffset([offset, offset]);
	});
};

Kinetic.Idea.prototype.getMMScale = function () {
	'use strict';
	var stage = this.getStage(),
		scale = (stage && stage.attrs && stage.attrs.scale && stage.attrs.scale.x) || (this.attrs && this.attrs.scale && this.attrs.scale.x) || 1;
	return {x: scale, y: scale};
};

Kinetic.Idea.prototype.setupShadows = function () {
	'use strict';
	var scale = this.getMMScale().x,
		isSelected = this.isSelected,
		offset =  (this.mmStyle && this.mmStyle.collapsed) ? 3 * scale : 4 * scale,
		normalShadow = {
			color: 'black',
			blur: 10 * scale,
			offset: [offset, offset],
			opacity: 0.4 * scale
		},
		selectedShadow = {
			color: 'black',
			blur: 0,
			offset: [offset, offset],
			opacity: 1
		},
		shadow = isSelected ? selectedShadow : normalShadow;
	_.each([this.rect, this.rectbg1, this.rectbg2], function (r) {
		r.setShadowColor(shadow.color);
		r.setShadowBlur(shadow.blur);
		r.setShadowOpacity(shadow.opacity);
		r.setShadowOffset(shadow.offset);
	});
};
Kinetic.Idea.prototype.getBackground = function () {
	'use strict';
	/*jslint newcap: true*/
	var isRoot = this.level === 1,
		defaultBg = MAPJS.defaultStyles[isRoot ? 'root' : 'nonRoot'].background,
		validColor = function (color, defaultColor) {
			if (!color) {
				return defaultColor;
			}
			var parsed = Color(color).hexString();
			return color.toUpperCase() === parsed.toUpperCase() ? color : defaultColor;
		};
	return validColor(this.mmStyle && this.mmStyle.background, defaultBg);
};
Kinetic.Idea.prototype.setStyle = function () {
	'use strict';
	/*jslint newcap: true*/
	var self = this,
		isDroppable = this.isDroppable,
		isSelected = this.isSelected,
		background = this.getBackground(),
		tintedBackground = Color(background).mix(Color('#EEEEEE')).hexString(),
		padding = 8;
	this.attrs.width = this.text.getWidth() + 2 * padding;
	this.attrs.height = this.text.getHeight() + 2 * padding;
	this.text.attrs.x = padding;
	this.text.attrs.y = padding;

	_.each([this.rect, this.rectbg1, this.rectbg2], function (r) {
		r.attrs.width = self.text.getWidth() + 2 * padding;
		r.attrs.height = self.text.getHeight() + 2 * padding;
		if (isDroppable) {
			r.attrs.stroke = '#9F4F4F';
			r.attrs.fillLinearGradientStartPoint = {x: 0, y: 0};
			r.attrs.fillLinearGradientEndPoint = {x: 100, y: 100};
			r.attrs.fillLinearGradientColorStops = [0, '#EF6F6F', 1, '#CF4F4F'];
			background = '#EF6F6F';
		} else if (isSelected) {
			r.attrs.fill = background;
		} else {
			r.attrs.stroke = '#888';
			r.attrs.fillLinearGradientStartPoint = {x: 0, y: 0};
			r.attrs.fillLinearGradientEndPoint = {x: 100, y: 100};
			r.attrs.fillLinearGradientColorStops = [0, tintedBackground, 1, background];
		}
	});
	this.setupShadows();
	this.text.attrs.fill = MAPJS.contrastForeground(tintedBackground);
};
Kinetic.Idea.prototype.setMMStyle = function (newMMStyle) {
	'use strict';
	this.mmStyle = newMMStyle;
	this.setStyle();
	this.rectbg1.setVisible(this.mmStyle.collapsed || false);
	this.rectbg2.setVisible(this.mmStyle.collapsed || false);
	this.getLayer().draw();
};
Kinetic.Idea.prototype.getIsSelected = function () {
	'use strict';
	return this.isSelected;
};

Kinetic.Idea.prototype.setIsSelected = function (isSelected) {
	'use strict';
	this.isSelected = isSelected;
	this.setStyle();
	this.getLayer().draw();
	if (!isSelected && this.stopEditing) {
		this.stopEditing();
	}
};
Kinetic.Idea.prototype.setIsDroppable = function (isDroppable) {
	'use strict';
	this.isDroppable = isDroppable;
	this.setStyle(this.attrs);
};
Kinetic.Global.extend(Kinetic.Idea, Kinetic.Group);
<commit_msg>fix for droppable color<commit_after>/*global MAPJS, Color, _, jQuery, Kinetic*/
/*jslint nomen: true, newcap: true*/
(function () {
	'use strict';
	/*shamelessly copied from http://james.padolsey.com/javascript/wordwrap-for-javascript */
	var COLUMN_WORD_WRAP_LIMIT = 25;
	function wordWrap(str, width, brk, cut) {
		brk = brk || '\n';
		width = width || 75;
		cut = cut || false;
		if (!str) {
			return str;
		}
		var regex = '.{1,' + width + '}(\\s|$)' + (cut ? '|.{' + width + '}|.+$' : '|\\S+?(\\s|$)');
		return str.match(new RegExp(regex, 'g')).join(brk);
	}
	function joinLines(string) {
		return string.replace(/\n/g, ' ');
	}
	function breakWords(string) {
		return wordWrap(joinLines(string), COLUMN_WORD_WRAP_LIMIT, '\n', false);
	}
	Kinetic.Idea = function (config) {
		var ENTER_KEY_CODE = 13,
			ESC_KEY_CODE = 27,
			self = this,
			unformattedText = joinLines(config.text),
			bgRect = function (offset) {
				return new Kinetic.Rect({
					strokeWidth: 1,
					cornerRadius: 10,
					x: offset,
					y: offset,
					visible: false
				});
			};
		config.text = breakWords(config.text);
		this.level = config.level;
		this.mmStyle = config.mmStyle;
		this.isSelected = false;
		config.draggable = config.level > 1;
		config.name = 'Idea';
		Kinetic.Group.call(this, config);
		this.rect = new Kinetic.Rect({
			strokeWidth: 1,
			cornerRadius: 10
		});
		this.rectbg1 = bgRect(8);
		this.rectbg2 = bgRect(4);
		this.text = new Kinetic.Text({
			text: config.text,
			fontSize: 14,
			fontFamily: 'Helvetica',
			lineHeight: 1.5,
			fontStyle: 'bold',
			align: 'center'
		});
		this.add(this.rectbg1);
		this.add(this.rectbg2);
		this.add(this.rect);
		this.add(this.text);
		this.setText = function (text) {
			unformattedText = text;
			self.text.setText(breakWords(text));
			self.setStyle();
		};
		this.setStyle();
		this.classType = 'Idea';
		this.getNodeAttrs = function () {
			return self.attrs;
		};
		this.isVisible = function (offset) {
			var stage = self.getStage();
			return stage && stage.isRectVisible(new MAPJS.Rectangle(self.attrs.x, self.attrs.y, self.getWidth(), self.getHeight()), offset);
		};
		this.editNode = function (shouldSelectAll) {
			self.fire(':editing');
			self.getLayer().draw();
			var canvasPosition = jQuery(self.getLayer().getCanvas().getElement()).offset(),
				ideaInput,
				onStageMoved = _.throttle(function () {
					ideaInput.css({
						top: canvasPosition.top + self.getAbsolutePosition().y,
						left: canvasPosition.left + self.getAbsolutePosition().x
					});
				}, 10),
				updateText = function (newText) {
					self.setStyle();
					self.getStage().draw();
					self.fire(':textChanged', {
						text: newText || unformattedText
					});
					ideaInput.remove();
					self.stopEditing = undefined;
					self.getStage().off('xChange yChange', onStageMoved);
				},
				onCommit = function () {
					updateText(ideaInput.val());
				},
				onCancelEdit = function () {
					updateText(unformattedText);
				},
				scale = self.getStage().getScale().x || 1;
			ideaInput = jQuery('<textarea type="text" wrap="soft" class="ideaInput"></textarea>')
				.css({
					top: canvasPosition.top + self.getAbsolutePosition().y,
					left: canvasPosition.left + self.getAbsolutePosition().x,
					width: (6 + self.getWidth()) * scale,
					height: (6 + self.getHeight()) * scale,
					'padding': 3 * scale + 'px',
					'font-size': self.text.attrs.fontSize * scale + 'px',
					'line-height': 1.2,
					'background-color': self.getBackground(),
					'margin': -3 * scale,
					'border-radius': self.rect.attrs.cornerRadius * scale + 'px',
					'border': self.rect.attrs.strokeWidth * (2 * scale) + 'px dashed ' + self.rect.attrs.stroke,
					'color': self.text.attrs.fill
				})
				.val(unformattedText)
				.appendTo('body')
				.keydown(function (e) {
					if (e.which === ENTER_KEY_CODE) {
						onCommit();
					} else if (e.which === ESC_KEY_CODE) {
						onCancelEdit();
					} else if (e.which === 9) {
						e.preventDefault();
					} else if (e.which === 83 && (e.metaKey || e.ctrlKey)) {
						e.preventDefault();
						onCommit();
						return; /* propagate to let the environment handle ctrl+s */
					} else if (!e.shiftKey && e.which === 90 && (e.metaKey || e.ctrlKey)) {
						if (ideaInput.val() === unformattedText) {
							onCancelEdit();
						}
					}
					e.stopPropagation();
				})
				.blur(onCommit)
				.focus(function () {
					if (shouldSelectAll) {
						if (ideaInput[0].setSelectionRange) {
							ideaInput[0].setSelectionRange(0, unformattedText.length);
						} else {
							ideaInput.select();
						}
					} else if (ideaInput[0].setSelectionRange) {
						ideaInput[0].setSelectionRange(unformattedText.length, unformattedText.length);
					}
				})
				.on('input', function () {
					var text = new Kinetic.Idea({
						text: ideaInput.val()
					});
					ideaInput.width(Math.max(ideaInput.width(), text.getWidth() * scale));
					ideaInput.height(Math.max(ideaInput.height(), text.getHeight() * scale));
				});

			self.stopEditing = onCancelEdit;
			ideaInput.focus();

			self.getStage().on('xChange yChange', onStageMoved);
		};
	};
}());

Kinetic.Idea.prototype.setShadowOffset = function (offset) {
	'use strict';
	offset = this.getMMScale().x * offset;
	_.each([this.rect, this.rectbg1, this.rectbg2], function (r) {
		r.setShadowOffset([offset, offset]);
	});
};

Kinetic.Idea.prototype.getMMScale = function () {
	'use strict';
	var stage = this.getStage(),
		scale = (stage && stage.attrs && stage.attrs.scale && stage.attrs.scale.x) || (this.attrs && this.attrs.scale && this.attrs.scale.x) || 1;
	return {x: scale, y: scale};
};

Kinetic.Idea.prototype.setupShadows = function () {
	'use strict';
	var scale = this.getMMScale().x,
		isSelected = this.isSelected,
		offset =  (this.mmStyle && this.mmStyle.collapsed) ? 3 * scale : 4 * scale,
		normalShadow = {
			color: 'black',
			blur: 10 * scale,
			offset: [offset, offset],
			opacity: 0.4 * scale
		},
		selectedShadow = {
			color: 'black',
			blur: 0,
			offset: [offset, offset],
			opacity: 1
		},
		shadow = isSelected ? selectedShadow : normalShadow;
	_.each([this.rect, this.rectbg1, this.rectbg2], function (r) {
		r.setShadowColor(shadow.color);
		r.setShadowBlur(shadow.blur);
		r.setShadowOpacity(shadow.opacity);
		r.setShadowOffset(shadow.offset);
	});
};
Kinetic.Idea.prototype.getBackground = function () {
	'use strict';
	/*jslint newcap: true*/
	var isRoot = this.level === 1,
		defaultBg = MAPJS.defaultStyles[isRoot ? 'root' : 'nonRoot'].background,
		validColor = function (color, defaultColor) {
			if (!color) {
				return defaultColor;
			}
			var parsed = Color(color).hexString();
			return color.toUpperCase() === parsed.toUpperCase() ? color : defaultColor;
		};
	return validColor(this.mmStyle && this.mmStyle.background, defaultBg);
};
Kinetic.Idea.prototype.setStyle = function () {
	'use strict';
	/*jslint newcap: true*/
	var self = this,
		isDroppable = this.isDroppable,
		isSelected = this.isSelected,
		background = this.getBackground(),
		tintedBackground = Color(background).mix(Color('#EEEEEE')).hexString(),
		padding = 8;
	this.attrs.width = this.text.getWidth() + 2 * padding;
	this.attrs.height = this.text.getHeight() + 2 * padding;
	this.text.attrs.x = padding;
	this.text.attrs.y = padding;

	_.each([this.rect, this.rectbg1, this.rectbg2], function (r) {
		r.attrs.width = self.text.getWidth() + 2 * padding;
		r.attrs.height = self.text.getHeight() + 2 * padding;
		if (isDroppable) {
			r.attrs.stroke = '#9F4F4F';
			r.attrs.fillLinearGradientStartPoint = {x: 0, y: 0};
			r.attrs.fillLinearGradientEndPoint = {x: 100, y: 100};
			background = '#EF6F6F';
			r.attrs.fillLinearGradientColorStops = [0, background, 1, '#CF4F4F'];
		} else if (isSelected) {
			r.attrs.fillLinearGradientColorStops = [0, background, 1, background];
		} else {
			r.attrs.stroke = '#888';
			r.attrs.fillLinearGradientStartPoint = {x: 0, y: 0};
			r.attrs.fillLinearGradientEndPoint = {x: 100, y: 100};
			r.attrs.fillLinearGradientColorStops = [0, tintedBackground, 1, background];
		}
	});
	this.setupShadows();
	this.text.attrs.fill = MAPJS.contrastForeground(tintedBackground);
};
Kinetic.Idea.prototype.setMMStyle = function (newMMStyle) {
	'use strict';
	this.mmStyle = newMMStyle;
	this.setStyle();
	this.rectbg1.setVisible(this.mmStyle.collapsed || false);
	this.rectbg2.setVisible(this.mmStyle.collapsed || false);
	this.getLayer().draw();
};
Kinetic.Idea.prototype.getIsSelected = function () {
	'use strict';
	return this.isSelected;
};

Kinetic.Idea.prototype.setIsSelected = function (isSelected) {
	'use strict';
	this.isSelected = isSelected;
	this.setStyle();
	this.getLayer().draw();
	if (!isSelected && this.stopEditing) {
		this.stopEditing();
	}
};
Kinetic.Idea.prototype.setIsDroppable = function (isDroppable) {
	'use strict';
	this.isDroppable = isDroppable;
	this.setStyle(this.attrs);
};
Kinetic.Global.extend(Kinetic.Idea, Kinetic.Group);
<|endoftext|>


<commit_before>/*global MAPJS, Color, _, jQuery, Kinetic*/
/*jslint nomen: true, newcap: true, browser: true*/
(function () {
	'use strict';
	/*shamelessly copied from http://james.padolsey.com/javascript/wordwrap-for-javascript */
	var COLUMN_WORD_WRAP_LIMIT = 25,
		urlPattern = /(https?:\/\/|www\.)[\w-]+(\.[\w-]+)+([\w.,@?^=%&:\/~+#-]*[\w@?^=%&\/~+#-])?/i;
	function wordWrap(str, width, brk, cut) {
		brk = brk || '\n';
		width = width || 75;
		cut = cut || false;
		if (!str) {
			return str;
		}
		var regex = '.{1,' + width + '}(\\s|$)' + (cut ? '|.{' + width + '}|.+$' : '|\\S+?(\\s|$)');
		return str.match(new RegExp(regex, 'g')).join(brk);
	}
	function joinLines(string) {
		return string.replace(/\n/g, ' ');
	}
	function breakWords(string) {
		return wordWrap(joinLines(string), COLUMN_WORD_WRAP_LIMIT, '\n', false);
	}
	function createLink() {
		var link = new Kinetic.Group(),
			rectProps = {
				width: 10,
				height: 20,
				rotation: 0.6,
				stroke: '#555555',
				strokeWidth: 3,
				cornerRadius: 6,
				shadowOffset: [2, 2],
				shadow: '#CCCCCC',
				shadowBlur: 0.4,
				shadowOpacity: 0.4,
			},
			rect = new Kinetic.Rect(rectProps),
			rect2 = new Kinetic.Rect(rectProps);
		rect2.attrs.x = 7;
		rect2.attrs.y = -7;
		link.add(rect);
		link.add(rect2);
		link.setActive = function (isActive) {
			rect.attrs.stroke = rect2.attrs.stroke = (isActive ? 'black' : '#555555');
			link.getLayer().draw();
		};
		return link;
	}
	Kinetic.Idea = function (config) {
		var ENTER_KEY_CODE = 13,
			ESC_KEY_CODE = 27,
			self = this,
			unformattedText = joinLines(config.text),
			bgRect = function (offset) {
				return new Kinetic.Rect({
					strokeWidth: 1,
					cornerRadius: 10,
					x: offset,
					y: offset,
					visible: false
				});
			};
		this.level = config.level;
		this.mmStyle = config.mmStyle;
		this.isSelected = false;
		config.draggable = config.level > 1;
		config.name = 'Idea';
		Kinetic.Group.call(this, config);
		this.rect = new Kinetic.Rect({
			strokeWidth: 1,
			cornerRadius: 10
		});
		this.rectbg1 = bgRect(8);
		this.rectbg2 = bgRect(4);
		this.link = createLink();
		this.link.on('click tap', function () {
			var url = unformattedText.match(urlPattern);
			if (url && url[0]) {
				url = url[0];
				if (!/https?:\/\//i.test(url)) {
					url = 'http://' + url;
				}
				window.open(url, '_blank');
			}
		});
		this.link.on('mouseover', function () {
			self.link.setActive(true);
		});
		this.link.on('mouseout', function () {
			self.link.setActive(false);
		});
		this.text = new Kinetic.Text({
			fontSize: 12,
			fontFamily: 'Helvetica',
			lineHeight: 1.5,
			fontStyle: 'bold',
			align: 'center'
		});
		this.add(this.rectbg1);
		this.add(this.rectbg2);
		this.add(this.rect);
		this.add(this.text);
		this.add(this.link);
		this.setText = function (text) {
			unformattedText = text;
			self.text.setText(breakWords(text.replace(urlPattern, '')));
			self.link.setVisible(urlPattern.test(text));
			self.setStyle();
		};
		this.setText(config.text);
		this.classType = 'Idea';
		this.getNodeAttrs = function () {
			return self.attrs;
		};
		this.isVisible = function (offset) {
			var stage = self.getStage();
			return stage && stage.isRectVisible(new MAPJS.Rectangle(self.attrs.x, self.attrs.y, self.getWidth(), self.getHeight()), offset);
		};
		this.editNode = function (shouldSelectAll) {
			self.fire(':editing');
			self.getLayer().draw();
			var canvasPosition = jQuery(self.getLayer().getCanvas().getElement()).offset(),
				ideaInput,
				onStageMoved = _.throttle(function () {
					ideaInput.css({
						top: canvasPosition.top + self.getAbsolutePosition().y,
						left: canvasPosition.left + self.getAbsolutePosition().x
					});
				}, 10),
				updateText = function (newText) {
					self.setStyle();
					self.getStage().draw();
					self.fire(':textChanged', {
						text: newText || unformattedText
					});
					ideaInput.remove();
					self.stopEditing = undefined;
					self.getStage().off('xChange yChange', onStageMoved);
				},
				onCommit = function () {
					updateText(ideaInput.val());
				},
				onCancelEdit = function () {
					updateText(unformattedText);
				},
				scale = self.getStage().getScale().x || 1;
			ideaInput = jQuery('<textarea type="text" wrap="soft" class="ideaInput"></textarea>')
				.css({
					top: canvasPosition.top + self.getAbsolutePosition().y,
					left: canvasPosition.left + self.getAbsolutePosition().x,
					width: (6 + self.getWidth()) * scale,
					height: (6 + self.getHeight()) * scale,
					'padding': 3 * scale + 'px',
					'font-size': self.text.attrs.fontSize * scale + 'px',
					'line-height': '150%',
					'background-color': self.getBackground(),
					'margin': -3 * scale,
					'border-radius': self.rect.attrs.cornerRadius * scale + 'px',
					'border': self.rect.attrs.strokeWidth * (2 * scale) + 'px dashed ' + self.rect.attrs.stroke,
					'color': self.text.attrs.fill
				})
				.val(unformattedText)
				.appendTo('body')
				.keydown(function (e) {
					if (e.which === ENTER_KEY_CODE) {
						onCommit();
					} else if (e.which === ESC_KEY_CODE) {
						onCancelEdit();
					} else if (e.which === 9) {
						e.preventDefault();
					} else if (e.which === 83 && (e.metaKey || e.ctrlKey)) {
						e.preventDefault();
						onCommit();
						return; /* propagate to let the environment handle ctrl+s */
					} else if (!e.shiftKey && e.which === 90 && (e.metaKey || e.ctrlKey)) {
						if (ideaInput.val() === unformattedText) {
							onCancelEdit();
						}
					}
					e.stopPropagation();
				})
				.blur(onCommit)
				.focus(function () {
					if (shouldSelectAll) {
						if (ideaInput[0].setSelectionRange) {
							ideaInput[0].setSelectionRange(0, unformattedText.length);
						} else {
							ideaInput.select();
						}
					} else if (ideaInput[0].setSelectionRange) {
						ideaInput[0].setSelectionRange(unformattedText.length, unformattedText.length);
					}
				})
				.on('input', function () {
					var text = new Kinetic.Idea({
						text: ideaInput.val()
					});
					ideaInput.width(Math.max(ideaInput.width(), text.getWidth() * scale));
					ideaInput.height(Math.max(ideaInput.height(), text.getHeight() * scale));
				});

			self.stopEditing = onCancelEdit;
			ideaInput.focus();

			self.getStage().on('xChange yChange', onStageMoved);
		};
	};
}());

Kinetic.Idea.prototype.setShadowOffset = function (offset) {
	'use strict';
	offset = this.getMMScale().x * offset;
	_.each([this.rect, this.rectbg1, this.rectbg2], function (r) {
		r.setShadowOffset([offset, offset]);
	});
};

Kinetic.Idea.prototype.getMMScale = function () {
	'use strict';
	var stage = this.getStage(),
		scale = (stage && stage.attrs && stage.attrs.scale && stage.attrs.scale.x) || (this.attrs && this.attrs.scale && this.attrs.scale.x) || 1;
	return {x: scale, y: scale};
};

Kinetic.Idea.prototype.setupShadows = function () {
	'use strict';
	var scale = this.getMMScale().x,
		isSelected = this.isSelected,
		offset =  (this.mmStyle && this.mmStyle.collapsed) ? 3 * scale : 4 * scale,
		normalShadow = {
			color: 'black',
			blur: 10 * scale,
			offset: [offset, offset],
			opacity: 0.4 * scale
		},
		selectedShadow = {
			color: 'black',
			blur: 0,
			offset: [offset, offset],
			opacity: 1
		},
		shadow = isSelected ? selectedShadow : normalShadow;
	_.each([this.rect, this.rectbg1, this.rectbg2], function (r) {
		r.setShadowColor(shadow.color);
		r.setShadowBlur(shadow.blur);
		r.setShadowOpacity(shadow.opacity);
		r.setShadowOffset(shadow.offset);
	});
};
Kinetic.Idea.prototype.getBackground = function () {
	'use strict';
	/*jslint newcap: true*/
	var isRoot = this.level === 1,
		defaultBg = MAPJS.defaultStyles[isRoot ? 'root' : 'nonRoot'].background,
		validColor = function (color, defaultColor) {
			if (!color) {
				return defaultColor;
			}
			var parsed = Color(color).hexString();
			return color.toUpperCase() === parsed.toUpperCase() ? color : defaultColor;
		};
	return validColor(this.mmStyle && this.mmStyle.background, defaultBg);
};
Kinetic.Idea.prototype.setStyle = function () {
	'use strict';
	/*jslint newcap: true*/
	var self = this,
		isDroppable = this.isDroppable,
		isSelected = this.isSelected,
		background = this.getBackground(),
		tintedBackground = Color(background).mix(Color('#EEEEEE')).hexString(),
		padding = 8;
	this.attrs.width = this.text.getWidth() + 2 * padding;
	this.attrs.height = this.text.getHeight() + 2 * padding;
	this.text.attrs.x = padding;
	this.text.attrs.y = padding;
	this.link.attrs.x = this.text.getWidth() + 10;
	this.link.attrs.y = this.text.getHeight() + 5;
	_.each([this.rect, this.rectbg1, this.rectbg2], function (r) {
		r.attrs.width = self.text.getWidth() + 2 * padding;
		r.attrs.height = self.text.getHeight() + 2 * padding;
		if (isDroppable) {
			r.attrs.stroke = '#9F4F4F';
			r.attrs.fillLinearGradientStartPoint = {x: 0, y: 0};
			r.attrs.fillLinearGradientEndPoint = {x: 100, y: 100};
			background = '#EF6F6F';
			r.attrs.fillLinearGradientColorStops = [0, background, 1, '#CF4F4F'];
		} else if (isSelected) {
			r.attrs.fillLinearGradientColorStops = [0, background, 1, background];
		} else {
			r.attrs.stroke = '#888';
			r.attrs.fillLinearGradientStartPoint = {x: 0, y: 0};
			r.attrs.fillLinearGradientEndPoint = {x: 100, y: 100};
			r.attrs.fillLinearGradientColorStops = [0, tintedBackground, 1, background];
		}
	});
	this.rectbg1.setVisible((this.mmStyle && this.mmStyle.collapsed) || false);
	this.rectbg2.setVisible((this.mmStyle && this.mmStyle.collapsed) || false);
	this.setupShadows();
	this.text.attrs.fill = MAPJS.contrastForeground(tintedBackground);
};
Kinetic.Idea.prototype.setMMStyle = function (newMMStyle) {
	'use strict';
	this.mmStyle = newMMStyle;
	this.setStyle();
	this.getLayer().draw();
};
Kinetic.Idea.prototype.getIsSelected = function () {
	'use strict';
	return this.isSelected;
};

Kinetic.Idea.prototype.setIsSelected = function (isSelected) {
	'use strict';
	this.isSelected = isSelected;
	this.setStyle();
	this.getLayer().draw();
	if (!isSelected && this.stopEditing) {
		this.stopEditing();
	}
};
Kinetic.Idea.prototype.setIsDroppable = function (isDroppable) {
	'use strict';
	this.isDroppable = isDroppable;
	this.setStyle(this.attrs);
};
Kinetic.Global.extend(Kinetic.Idea, Kinetic.Group);
<commit_msg>show part of URL when nothing else in node<commit_after>/*global MAPJS, Color, _, jQuery, Kinetic*/
/*jslint nomen: true, newcap: true, browser: true*/
(function () {
	'use strict';
	/*shamelessly copied from http://james.padolsey.com/javascript/wordwrap-for-javascript */
	var COLUMN_WORD_WRAP_LIMIT = 25,
		urlPattern = /(https?:\/\/|www\.)[\w-]+(\.[\w-]+)+([\w.,@?^=%&:\/~+#-]*[\w@?^=%&\/~+#-])?/i;
	function wordWrap(str, width, brk, cut) {
		brk = brk || '\n';
		width = width || 75;
		cut = cut || false;
		if (!str) {
			return str;
		}
		var regex = '.{1,' + width + '}(\\s|$)' + (cut ? '|.{' + width + '}|.+$' : '|\\S+?(\\s|$)');
		return str.match(new RegExp(regex, 'g')).join(brk);
	}
	function joinLines(string) {
		return string.replace(/\n/g, ' ');
	}
	function breakWords(string) {
		return wordWrap(joinLines(string), COLUMN_WORD_WRAP_LIMIT, '\n', false);
	}
	function createLink() {
		var link = new Kinetic.Group(),
			rectProps = {
				width: 10,
				height: 20,
				rotation: 0.6,
				stroke: '#555555',
				strokeWidth: 3,
				cornerRadius: 6,
				shadowOffset: [2, 2],
				shadow: '#CCCCCC',
				shadowBlur: 0.4,
				shadowOpacity: 0.4,
			},
			rect = new Kinetic.Rect(rectProps),
			rect2 = new Kinetic.Rect(rectProps);
		rect2.attrs.x = 7;
		rect2.attrs.y = -7;
		link.add(rect);
		link.add(rect2);
		link.setActive = function (isActive) {
			rect.attrs.stroke = rect2.attrs.stroke = (isActive ? 'black' : '#555555');
			link.getLayer().draw();
		};
		return link;
	}
	Kinetic.Idea = function (config) {
		var ENTER_KEY_CODE = 13,
			ESC_KEY_CODE = 27,
			self = this,
			unformattedText = joinLines(config.text),
			bgRect = function (offset) {
				return new Kinetic.Rect({
					strokeWidth: 1,
					cornerRadius: 10,
					x: offset,
					y: offset,
					visible: false
				});
			};
		this.level = config.level;
		this.mmStyle = config.mmStyle;
		this.isSelected = false;
		config.draggable = config.level > 1;
		config.name = 'Idea';
		Kinetic.Group.call(this, config);
		this.rect = new Kinetic.Rect({
			strokeWidth: 1,
			cornerRadius: 10
		});
		this.rectbg1 = bgRect(8);
		this.rectbg2 = bgRect(4);
		this.link = createLink();
		this.link.on('click tap', function () {
			var url = unformattedText.match(urlPattern);
			if (url && url[0]) {
				url = url[0];
				if (!/https?:\/\//i.test(url)) {
					url = 'http://' + url;
				}
				window.open(url, '_blank');
			}
		});
		this.link.on('mouseover', function () {
			self.link.setActive(true);
		});
		this.link.on('mouseout', function () {
			self.link.setActive(false);
		});
		this.text = new Kinetic.Text({
			fontSize: 12,
			fontFamily: 'Helvetica',
			lineHeight: 1.5,
			fontStyle: 'bold',
			align: 'center'
		});
		this.add(this.rectbg1);
		this.add(this.rectbg2);
		this.add(this.rect);
		this.add(this.text);
		this.add(this.link);
		this.setText = function (text) {
			var replacement = breakWords(text.replace(urlPattern, '')) || (text.substring(0, COLUMN_WORD_WRAP_LIMIT) + '...');
			unformattedText = text;
			self.text.setText(replacement);
			self.link.setVisible(urlPattern.test(text));
			self.setStyle();
		};
		this.setText(config.text);
		this.classType = 'Idea';
		this.getNodeAttrs = function () {
			return self.attrs;
		};
		this.isVisible = function (offset) {
			var stage = self.getStage();
			return stage && stage.isRectVisible(new MAPJS.Rectangle(self.attrs.x, self.attrs.y, self.getWidth(), self.getHeight()), offset);
		};
		this.editNode = function (shouldSelectAll) {
			self.fire(':editing');
			self.getLayer().draw();
			var canvasPosition = jQuery(self.getLayer().getCanvas().getElement()).offset(),
				ideaInput,
				onStageMoved = _.throttle(function () {
					ideaInput.css({
						top: canvasPosition.top + self.getAbsolutePosition().y,
						left: canvasPosition.left + self.getAbsolutePosition().x
					});
				}, 10),
				updateText = function (newText) {
					self.setStyle();
					self.getStage().draw();
					self.fire(':textChanged', {
						text: newText || unformattedText
					});
					ideaInput.remove();
					self.stopEditing = undefined;
					self.getStage().off('xChange yChange', onStageMoved);
				},
				onCommit = function () {
					updateText(ideaInput.val());
				},
				onCancelEdit = function () {
					updateText(unformattedText);
				},
				scale = self.getStage().getScale().x || 1;
			ideaInput = jQuery('<textarea type="text" wrap="soft" class="ideaInput"></textarea>')
				.css({
					top: canvasPosition.top + self.getAbsolutePosition().y,
					left: canvasPosition.left + self.getAbsolutePosition().x,
					width: (6 + self.getWidth()) * scale,
					height: (6 + self.getHeight()) * scale,
					'padding': 3 * scale + 'px',
					'font-size': self.text.attrs.fontSize * scale + 'px',
					'line-height': '150%',
					'background-color': self.getBackground(),
					'margin': -3 * scale,
					'border-radius': self.rect.attrs.cornerRadius * scale + 'px',
					'border': self.rect.attrs.strokeWidth * (2 * scale) + 'px dashed ' + self.rect.attrs.stroke,
					'color': self.text.attrs.fill
				})
				.val(unformattedText)
				.appendTo('body')
				.keydown(function (e) {
					if (e.which === ENTER_KEY_CODE) {
						onCommit();
					} else if (e.which === ESC_KEY_CODE) {
						onCancelEdit();
					} else if (e.which === 9) {
						e.preventDefault();
					} else if (e.which === 83 && (e.metaKey || e.ctrlKey)) {
						e.preventDefault();
						onCommit();
						return; /* propagate to let the environment handle ctrl+s */
					} else if (!e.shiftKey && e.which === 90 && (e.metaKey || e.ctrlKey)) {
						if (ideaInput.val() === unformattedText) {
							onCancelEdit();
						}
					}
					e.stopPropagation();
				})
				.blur(onCommit)
				.focus(function () {
					if (shouldSelectAll) {
						if (ideaInput[0].setSelectionRange) {
							ideaInput[0].setSelectionRange(0, unformattedText.length);
						} else {
							ideaInput.select();
						}
					} else if (ideaInput[0].setSelectionRange) {
						ideaInput[0].setSelectionRange(unformattedText.length, unformattedText.length);
					}
				})
				.on('input', function () {
					var text = new Kinetic.Idea({
						text: ideaInput.val()
					});
					ideaInput.width(Math.max(ideaInput.width(), text.getWidth() * scale));
					ideaInput.height(Math.max(ideaInput.height(), text.getHeight() * scale));
				});

			self.stopEditing = onCancelEdit;
			ideaInput.focus();

			self.getStage().on('xChange yChange', onStageMoved);
		};
	};
}());

Kinetic.Idea.prototype.setShadowOffset = function (offset) {
	'use strict';
	offset = this.getMMScale().x * offset;
	_.each([this.rect, this.rectbg1, this.rectbg2], function (r) {
		r.setShadowOffset([offset, offset]);
	});
};

Kinetic.Idea.prototype.getMMScale = function () {
	'use strict';
	var stage = this.getStage(),
		scale = (stage && stage.attrs && stage.attrs.scale && stage.attrs.scale.x) || (this.attrs && this.attrs.scale && this.attrs.scale.x) || 1;
	return {x: scale, y: scale};
};

Kinetic.Idea.prototype.setupShadows = function () {
	'use strict';
	var scale = this.getMMScale().x,
		isSelected = this.isSelected,
		offset =  (this.mmStyle && this.mmStyle.collapsed) ? 3 * scale : 4 * scale,
		normalShadow = {
			color: 'black',
			blur: 10 * scale,
			offset: [offset, offset],
			opacity: 0.4 * scale
		},
		selectedShadow = {
			color: 'black',
			blur: 0,
			offset: [offset, offset],
			opacity: 1
		},
		shadow = isSelected ? selectedShadow : normalShadow;
	_.each([this.rect, this.rectbg1, this.rectbg2], function (r) {
		r.setShadowColor(shadow.color);
		r.setShadowBlur(shadow.blur);
		r.setShadowOpacity(shadow.opacity);
		r.setShadowOffset(shadow.offset);
	});
};
Kinetic.Idea.prototype.getBackground = function () {
	'use strict';
	/*jslint newcap: true*/
	var isRoot = this.level === 1,
		defaultBg = MAPJS.defaultStyles[isRoot ? 'root' : 'nonRoot'].background,
		validColor = function (color, defaultColor) {
			if (!color) {
				return defaultColor;
			}
			var parsed = Color(color).hexString();
			return color.toUpperCase() === parsed.toUpperCase() ? color : defaultColor;
		};
	return validColor(this.mmStyle && this.mmStyle.background, defaultBg);
};
Kinetic.Idea.prototype.setStyle = function () {
	'use strict';
	/*jslint newcap: true*/
	var self = this,
		isDroppable = this.isDroppable,
		isSelected = this.isSelected,
		background = this.getBackground(),
		tintedBackground = Color(background).mix(Color('#EEEEEE')).hexString(),
		padding = 8;
	this.attrs.width = this.text.getWidth() + 2 * padding;
	this.attrs.height = this.text.getHeight() + 2 * padding;
	this.text.attrs.x = padding;
	this.text.attrs.y = padding;
	this.link.attrs.x = this.text.getWidth() + 10;
	this.link.attrs.y = this.text.getHeight() + 5;
	_.each([this.rect, this.rectbg1, this.rectbg2], function (r) {
		r.attrs.width = self.text.getWidth() + 2 * padding;
		r.attrs.height = self.text.getHeight() + 2 * padding;
		if (isDroppable) {
			r.attrs.stroke = '#9F4F4F';
			r.attrs.fillLinearGradientStartPoint = {x: 0, y: 0};
			r.attrs.fillLinearGradientEndPoint = {x: 100, y: 100};
			background = '#EF6F6F';
			r.attrs.fillLinearGradientColorStops = [0, background, 1, '#CF4F4F'];
		} else if (isSelected) {
			r.attrs.fillLinearGradientColorStops = [0, background, 1, background];
		} else {
			r.attrs.stroke = '#888';
			r.attrs.fillLinearGradientStartPoint = {x: 0, y: 0};
			r.attrs.fillLinearGradientEndPoint = {x: 100, y: 100};
			r.attrs.fillLinearGradientColorStops = [0, tintedBackground, 1, background];
		}
	});
	this.rectbg1.setVisible((this.mmStyle && this.mmStyle.collapsed) || false);
	this.rectbg2.setVisible((this.mmStyle && this.mmStyle.collapsed) || false);
	this.setupShadows();
	this.text.attrs.fill = MAPJS.contrastForeground(tintedBackground);
};
Kinetic.Idea.prototype.setMMStyle = function (newMMStyle) {
	'use strict';
	this.mmStyle = newMMStyle;
	this.setStyle();
	this.getLayer().draw();
};
Kinetic.Idea.prototype.getIsSelected = function () {
	'use strict';
	return this.isSelected;
};

Kinetic.Idea.prototype.setIsSelected = function (isSelected) {
	'use strict';
	this.isSelected = isSelected;
	this.setStyle();
	this.getLayer().draw();
	if (!isSelected && this.stopEditing) {
		this.stopEditing();
	}
};
Kinetic.Idea.prototype.setIsDroppable = function (isDroppable) {
	'use strict';
	this.isDroppable = isDroppable;
	this.setStyle(this.attrs);
};
Kinetic.Global.extend(Kinetic.Idea, Kinetic.Group);
<|endoftext|>


<commit_before>/**
 * Module for global and app configs.
 * @module kbox.core.config
 */

'use strict';

var path = require('path');
var os = require('os');
var fs = require('fs');
var env = require('./env.js');
var deps = require('./deps.js');
var log = require('./log.js');
var _ = require('lodash');

// Constants
var CONFIG_FILENAME = 'kalabox.json';
exports.CONFIG_FILENAME = CONFIG_FILENAME;

var DEFAULT_GLOBAL_CONFIG = {
  domain: 'kbox',
  engine: 'kalabox-engine-docker@https://github.com/kalabox/' +
    'kalabox-engine-docker/tarball/elton-rocketman',
  engineRepo: 'kalabox',
  codeDir: 'code',
  services: 'kalabox-services-kalabox@https://github.com/kalabox/' +
    'kalabox-services-kalabox/tarball/elton-rocketman',
  apps: [
    'kalabox-app-backdrop@https://github.com/kalabox/' +
      'kalabox-app-backdrop/tarball/elton-rocketman',
    'kalabox-app-drupal@https://github.com/kalabox/' +
      'kalabox-app-drupal/tarball/elton-rocketman',
    'kalabox-app-pantheon@https://github.com/kalabox/' +
      'kalabox-app-pantheon/tarball/elton-rocketman'
  ],
  profile: 'standard',
  sharing: true,
  stats: {
    report: true,
    url: 'http://stats.kalabox.biz'
  },
  kboxRoot: ':home:/kalabox',
  kalaboxRoot: ':kboxRoot:',
  logLevel: 'debug',
  logLevelConsole: 'info',
  logRoot: ':sysConfRoot:/logs',
  downloadsRoot: ':sysConfRoot:/downloads',
  appsRoot: ':kboxRoot:/apps',
  appRegistry: ':sysConfRoot:/appRegistry.json',
  globalPluginRoot: ':kboxRoot:/plugins',
  globalPlugins: [
    'kalabox-core',
    'kalabox-syncthing',
    'kalabox-app-drupal',
    'kalabox-app-backdrop',
    'kalabox-app-pantheon'
  ],
  configSources: [
    'DEFAULT_GLOBAL_CONFIG'
  ],
  shareIgnores: [
    '*.7z',
    '*.bz2',
    '*.dmg',
    '*.gz',
    '*.iso',
    '*.jar',
    '*.rar',
    '*.tar',
    '*.tgz',
    '*.un~',
    '*.zip',
    '.*.swp',
    '.*DS_Store',
    '.DS_Store*',
    '._*',
    '.sass-cache',
    'Icon',
    'Thumbs.db',
    'ehthumbs.db',
    'sites/default/files/*'
  ]
};

var logDebug = log.debug;
var logInfo = log.info;

/*
 * Pretty print an object.
 */
var pp = function(obj) {
  return JSON.stringify(obj, null, '  ');
};

/*
 * Looks up a key of the config object and returns it.
 */
var lookupKey = function(config, keyToFind) {

  // Recursive function.
  var rec = function(o, prefix) {

    // Loop through each of the objects properties to find value.
    return _.find(o, function(val, key) {

      // Build namespaced name.
      var name = _.filter([prefix, key]).join('.');

      if (typeof val === 'string') {

        // If name of string value matches, return it.
        return (':' + name + ':') === keyToFind;

      } else if (typeof val === 'object') {

        // Recursively check object.
        return rec(val, name);

      } else {

        // Not a string or an object so just return false.
        return false;

      }

    });

  };

  // Init recursive function and return.
  return rec(config);

};

/*
 * Translate a value.
 */
var normalizeValue = exports.normalizeValue = function(config, v) {

  // Search value for regex matches.
  //var params = v.match(/:[a-zA-Z0-9-_]*:/g);
  var params;
  try {
    params = v.match(/:[a-zA-Z0-9-_]*:/g);
  }
  catch (err) {
    throw new Error(typeof v);
  }

  if (!params) {

    // No params were found, so just return original value.
    return v;

  } else {

    // Reduce list of params to final value.
    return _.reduce(params, function(acc, param) {

      // Get replacement value from config object based on param name.
      var replacementValue = lookupKey(config, param);

      if (!replacementValue) {

        // Replacement value was not found so just return value.
        return acc;

      } else {

        // Replace and return.
        return acc.replace(param, replacementValue);

      }

    }, v);

  }

};

/*
 * Walk the properties of the top level object, replacing strings
 * with other properties values.
 */
var normalize = exports.normalize = function(config) {

  // Recursive funciton.
  var rec = function(o) {

    // Loop through each property of the object.
    _.each(o, function(val, key) {

      if (typeof val === 'string') {

        // For string values normalize.
        o[key] = normalizeValue(config, val);

      } else if (typeof val === 'object') {

        // For object values recursively normalize.
        rec(val);

      }

    });

  };

  // Init recursive function with config.
  rec(config);

  // Return config.
  return config;

};

function sort(config) {
  var keys = Object.keys(config).sort();
  var retVal = {};
  for (var i = 0; i < keys.length; ++i) {
    var key = keys[i];
    retVal[key] = config[key];
  }
  return retVal;
}

// @todo: implement
var KEYS_TO_CONCAT = [
  'configSources',
  'shareIgnores'
];

function mixIn(a, b) {
  for (var key in b) {
    var shouldConcat = _.contains(KEYS_TO_CONCAT, key);
    if (shouldConcat) {
      // Concat.
      if (_.isArray(a[key]) && _.isArray(b[key])) {
        a[key] = _.uniq(a[key].concat(b[key]));
        a[key].sort();
      } else {
        a[key] = b[key];
      }
    } else {
      // Override.
      a[key] = b[key];
    }
  }
  return sort(normalize(a));
}
exports.mixIn = mixIn;

var getPackageJson = function() {
  return require(path.join(env.getSourceRoot(), 'package.json'));
};

/**
 * Gets the kalabox environment config.
 * @returns {object} config - The kalabox enviroment config.
 * @example
 * var envConfig = kbox.core.config.getEnvConfig();
 * // Print home directory to stdout.
 * console.log(envConfig.home);
 */
exports.getEnvConfig = function() {
  var packageJson = getPackageJson();
  var provisioned = false;
  if (fs.existsSync(path.join(env.getSysConfRoot(), 'provisioned'))) {
    provisioned = true;
  }
  return {
    provisioned: provisioned,
    home: env.getHomeDir(),
    os: {
      type: os.type(),
      platform: os.platform(),
      release: os.release(),
      arch: os.arch()
    },
    sysConfRoot: env.getSysConfRoot(),
    sysProviderRoot: env.getSysProviderRoot(),
    srcRoot: env.getSourceRoot(),
    version: packageJson.version,
    configSources: [
      'ENV_CONFIG'
    ]
  };
};

/**
 * Gets the default config. The default config is a combination of the
 *   environment config and a set of default config values.
 * @returns {object} config - The kalabox default config.
 * @example
 * var defaultConfig = kbox.core.config.getDefaultConfig();
 * // Print global plugins
 * defaultConfig.globalPlugins.forEach(function(plugin) {
 *   console.log(plugin)  ;
 * });
 */
exports.getDefaultConfig = function() {
  return mixIn(this.getEnvConfig(), DEFAULT_GLOBAL_CONFIG);
};

var getReleaseConfigFilepath = exports.getReleaseConfigFilepath = function() {
  return path.join(env.getSourceRoot(), CONFIG_FILENAME);
};

var getGlobalConfigFilepath = function() {
  return path.join(env.getSysConfRoot(), CONFIG_FILENAME);
};

var loadConfigFile = function(configFilepath) {
  var loadedConfigFile = require(configFilepath);
  loadedConfigFile.configSources = [configFilepath];
  return loadedConfigFile;
};

/**
 * Gets the global config. The global config is a combination of the
 *   environment config, the default config, and any values overriden
 *   in the $HOME/.kalabox/kalabox.json config file.
 * @returns {object} config - The kalabox global config.
 * @example
 * var globalConfig = kbox.core.config.getGlobalConfig();
 * // Print the entire global config.
 * console.log(JSON.stringify(globalConfig, null, '\t'));
 */
exports.getGlobalConfig = function() {
  var defaultConfig = this.getDefaultConfig();
  var filesToLoad = [
    getReleaseConfigFilepath(),
    getGlobalConfigFilepath()
  ];
  var globalConfig = _.reduce(filesToLoad, function(config, fileToLoad) {
    if (fs.existsSync(fileToLoad)) {
      var loadedConfigFile = loadConfigFile(fileToLoad);
      config = mixIn(config, loadedConfigFile);
    }
    return config;
  }, defaultConfig);
  return globalConfig;
};

exports.getAppConfigFilepath = function(app, config) {
  return path.join(config.appsRoot, app.name, CONFIG_FILENAME);
};

/**
 * Gets the app config for an app. The app config is a combination of the
 *   environment config, the default config, any values overriden in the
 *   $HOME/.kalabox/kalabox.json config file, and the kalabox.json config
 *   file in the app's root directory.
 * @arg {string} app - The name of the app you'd like to get the config for.
 * @arg {string} appRoot [optional] - Directory to load the
 * app's config file from.
 * @returns {object} config - The app's kalabox app config.
 * @example
 * var appConfig = kbox.core.config.getAppConfig('myapp');
 * // Print the entire app config.
 * console.log(JSON.stringify(appConfig, null, '\t'));
 */
exports.getAppConfig = function(app, appRoot) {
  // @todo: this is jank
  if (typeof app === 'string') {
    var appName = app;
    app = {name: appName};
  }

  var globalConfig = this.getGlobalConfig();

  if (!appRoot) {
    appRoot = path.join(globalConfig.appsRoot, app.name);
  }

  var appConfigFilepath = path.join(appRoot, CONFIG_FILENAME);
  var appConfigFile = require(appConfigFilepath);
  appConfigFile.appRoot = appRoot;
  appConfigFile.appCidsRoot = ':appRoot:/.cids';
  var retVal = mixIn(globalConfig, appConfigFile);
  logDebug('CONFIG => App config loaded.', retVal);
  return retVal;
};
<commit_msg>we dont want to ignore platform specific drupalisms globally<commit_after>/**
 * Module for global and app configs.
 * @module kbox.core.config
 */

'use strict';

var path = require('path');
var os = require('os');
var fs = require('fs');
var env = require('./env.js');
var deps = require('./deps.js');
var log = require('./log.js');
var _ = require('lodash');

// Constants
var CONFIG_FILENAME = 'kalabox.json';
exports.CONFIG_FILENAME = CONFIG_FILENAME;

var DEFAULT_GLOBAL_CONFIG = {
  domain: 'kbox',
  engine: 'kalabox-engine-docker@https://github.com/kalabox/' +
    'kalabox-engine-docker/tarball/elton-rocketman',
  engineRepo: 'kalabox',
  codeDir: 'code',
  services: 'kalabox-services-kalabox@https://github.com/kalabox/' +
    'kalabox-services-kalabox/tarball/elton-rocketman',
  apps: [
    'kalabox-app-backdrop@https://github.com/kalabox/' +
      'kalabox-app-backdrop/tarball/elton-rocketman',
    'kalabox-app-drupal@https://github.com/kalabox/' +
      'kalabox-app-drupal/tarball/elton-rocketman',
    'kalabox-app-pantheon@https://github.com/kalabox/' +
      'kalabox-app-pantheon/tarball/elton-rocketman'
  ],
  profile: 'standard',
  sharing: true,
  stats: {
    report: true,
    url: 'http://stats.kalabox.biz'
  },
  kboxRoot: ':home:/kalabox',
  kalaboxRoot: ':kboxRoot:',
  logLevel: 'debug',
  logLevelConsole: 'info',
  logRoot: ':sysConfRoot:/logs',
  downloadsRoot: ':sysConfRoot:/downloads',
  appsRoot: ':kboxRoot:/apps',
  appRegistry: ':sysConfRoot:/appRegistry.json',
  globalPluginRoot: ':kboxRoot:/plugins',
  globalPlugins: [
    'kalabox-core',
    'kalabox-syncthing',
    'kalabox-app-drupal',
    'kalabox-app-backdrop',
    'kalabox-app-pantheon'
  ],
  configSources: [
    'DEFAULT_GLOBAL_CONFIG'
  ],
  shareIgnores: [
    '*.7z',
    '*.bz2',
    '*.dmg',
    '*.gz',
    '*.iso',
    '*.jar',
    '*.rar',
    '*.tar',
    '*.tgz',
    '*.un~',
    '*.zip',
    '.*.swp',
    '.*DS_Store',
    '.DS_Store*',
    '._*',
    '.sass-cache',
    'Icon',
    'Thumbs.db',
    'ehthumbs.db'
  ]
};

var logDebug = log.debug;
var logInfo = log.info;

/*
 * Pretty print an object.
 */
var pp = function(obj) {
  return JSON.stringify(obj, null, '  ');
};

/*
 * Looks up a key of the config object and returns it.
 */
var lookupKey = function(config, keyToFind) {

  // Recursive function.
  var rec = function(o, prefix) {

    // Loop through each of the objects properties to find value.
    return _.find(o, function(val, key) {

      // Build namespaced name.
      var name = _.filter([prefix, key]).join('.');

      if (typeof val === 'string') {

        // If name of string value matches, return it.
        return (':' + name + ':') === keyToFind;

      } else if (typeof val === 'object') {

        // Recursively check object.
        return rec(val, name);

      } else {

        // Not a string or an object so just return false.
        return false;

      }

    });

  };

  // Init recursive function and return.
  return rec(config);

};

/*
 * Translate a value.
 */
var normalizeValue = exports.normalizeValue = function(config, v) {

  // Search value for regex matches.
  //var params = v.match(/:[a-zA-Z0-9-_]*:/g);
  var params;
  try {
    params = v.match(/:[a-zA-Z0-9-_]*:/g);
  }
  catch (err) {
    throw new Error(typeof v);
  }

  if (!params) {

    // No params were found, so just return original value.
    return v;

  } else {

    // Reduce list of params to final value.
    return _.reduce(params, function(acc, param) {

      // Get replacement value from config object based on param name.
      var replacementValue = lookupKey(config, param);

      if (!replacementValue) {

        // Replacement value was not found so just return value.
        return acc;

      } else {

        // Replace and return.
        return acc.replace(param, replacementValue);

      }

    }, v);

  }

};

/*
 * Walk the properties of the top level object, replacing strings
 * with other properties values.
 */
var normalize = exports.normalize = function(config) {

  // Recursive funciton.
  var rec = function(o) {

    // Loop through each property of the object.
    _.each(o, function(val, key) {

      if (typeof val === 'string') {

        // For string values normalize.
        o[key] = normalizeValue(config, val);

      } else if (typeof val === 'object') {

        // For object values recursively normalize.
        rec(val);

      }

    });

  };

  // Init recursive function with config.
  rec(config);

  // Return config.
  return config;

};

function sort(config) {
  var keys = Object.keys(config).sort();
  var retVal = {};
  for (var i = 0; i < keys.length; ++i) {
    var key = keys[i];
    retVal[key] = config[key];
  }
  return retVal;
}

// @todo: implement
var KEYS_TO_CONCAT = [
  'configSources',
  'shareIgnores'
];

function mixIn(a, b) {
  for (var key in b) {
    var shouldConcat = _.contains(KEYS_TO_CONCAT, key);
    if (shouldConcat) {
      // Concat.
      if (_.isArray(a[key]) && _.isArray(b[key])) {
        a[key] = _.uniq(a[key].concat(b[key]));
        a[key].sort();
      } else {
        a[key] = b[key];
      }
    } else {
      // Override.
      a[key] = b[key];
    }
  }
  return sort(normalize(a));
}
exports.mixIn = mixIn;

var getPackageJson = function() {
  return require(path.join(env.getSourceRoot(), 'package.json'));
};

/**
 * Gets the kalabox environment config.
 * @returns {object} config - The kalabox enviroment config.
 * @example
 * var envConfig = kbox.core.config.getEnvConfig();
 * // Print home directory to stdout.
 * console.log(envConfig.home);
 */
exports.getEnvConfig = function() {
  var packageJson = getPackageJson();
  var provisioned = false;
  if (fs.existsSync(path.join(env.getSysConfRoot(), 'provisioned'))) {
    provisioned = true;
  }
  return {
    provisioned: provisioned,
    home: env.getHomeDir(),
    os: {
      type: os.type(),
      platform: os.platform(),
      release: os.release(),
      arch: os.arch()
    },
    sysConfRoot: env.getSysConfRoot(),
    sysProviderRoot: env.getSysProviderRoot(),
    srcRoot: env.getSourceRoot(),
    version: packageJson.version,
    configSources: [
      'ENV_CONFIG'
    ]
  };
};

/**
 * Gets the default config. The default config is a combination of the
 *   environment config and a set of default config values.
 * @returns {object} config - The kalabox default config.
 * @example
 * var defaultConfig = kbox.core.config.getDefaultConfig();
 * // Print global plugins
 * defaultConfig.globalPlugins.forEach(function(plugin) {
 *   console.log(plugin)  ;
 * });
 */
exports.getDefaultConfig = function() {
  return mixIn(this.getEnvConfig(), DEFAULT_GLOBAL_CONFIG);
};

var getReleaseConfigFilepath = exports.getReleaseConfigFilepath = function() {
  return path.join(env.getSourceRoot(), CONFIG_FILENAME);
};

var getGlobalConfigFilepath = function() {
  return path.join(env.getSysConfRoot(), CONFIG_FILENAME);
};

var loadConfigFile = function(configFilepath) {
  var loadedConfigFile = require(configFilepath);
  loadedConfigFile.configSources = [configFilepath];
  return loadedConfigFile;
};

/**
 * Gets the global config. The global config is a combination of the
 *   environment config, the default config, and any values overriden
 *   in the $HOME/.kalabox/kalabox.json config file.
 * @returns {object} config - The kalabox global config.
 * @example
 * var globalConfig = kbox.core.config.getGlobalConfig();
 * // Print the entire global config.
 * console.log(JSON.stringify(globalConfig, null, '\t'));
 */
exports.getGlobalConfig = function() {
  var defaultConfig = this.getDefaultConfig();
  var filesToLoad = [
    getReleaseConfigFilepath(),
    getGlobalConfigFilepath()
  ];
  var globalConfig = _.reduce(filesToLoad, function(config, fileToLoad) {
    if (fs.existsSync(fileToLoad)) {
      var loadedConfigFile = loadConfigFile(fileToLoad);
      config = mixIn(config, loadedConfigFile);
    }
    return config;
  }, defaultConfig);
  return globalConfig;
};

exports.getAppConfigFilepath = function(app, config) {
  return path.join(config.appsRoot, app.name, CONFIG_FILENAME);
};

/**
 * Gets the app config for an app. The app config is a combination of the
 *   environment config, the default config, any values overriden in the
 *   $HOME/.kalabox/kalabox.json config file, and the kalabox.json config
 *   file in the app's root directory.
 * @arg {string} app - The name of the app you'd like to get the config for.
 * @arg {string} appRoot [optional] - Directory to load the
 * app's config file from.
 * @returns {object} config - The app's kalabox app config.
 * @example
 * var appConfig = kbox.core.config.getAppConfig('myapp');
 * // Print the entire app config.
 * console.log(JSON.stringify(appConfig, null, '\t'));
 */
exports.getAppConfig = function(app, appRoot) {
  // @todo: this is jank
  if (typeof app === 'string') {
    var appName = app;
    app = {name: appName};
  }

  var globalConfig = this.getGlobalConfig();

  if (!appRoot) {
    appRoot = path.join(globalConfig.appsRoot, app.name);
  }

  var appConfigFilepath = path.join(appRoot, CONFIG_FILENAME);
  var appConfigFile = require(appConfigFilepath);
  appConfigFile.appRoot = appRoot;
  appConfigFile.appCidsRoot = ':appRoot:/.cids';
  var retVal = mixIn(globalConfig, appConfigFile);
  logDebug('CONFIG => App config loaded.', retVal);
  return retVal;
};
<|endoftext|>


<commit_before>define(["Ti/_/Evented", "Ti/_/lang"], function(Evented, lang) {

	lang.setObject("Ti.Filesystem", Evented, {

		constants: {
			MODE_APPEND: 1,
			MODE_READ: 2,
			MODE_WRITE: 3,
			applicationDataDirectory: "/",
			lineEnding: "\n",
			resourcesDirectory: "/",
			separator: "/",
			tempDirectory: "/tmp"
		},

		createFile: function(args){
			var m = require("Ti/Filesystem/File");
			return new m(args);
		},

		createTempDirectory: function(args) {
			//
		},

		createTempFile: function(args) {
			//
		},

		getFile: function(args) {
			//
		},

		isExternalStoragePresent: function(args) {
			return false;
		}

	});

});<commit_msg>[TIMOB-7111] Fixed bad character in Ti.Filesystem.<commit_after>define(["Ti/_/Evented", "Ti/_/lang"], function(Evented, lang) {

	lang.setObject("Ti.Filesystem", Evented, {

		constants: {
			MODE_APPEND: 1,
			MODE_READ: 2,
			MODE_WRITE: 3,
			applicationDataDirectory: "/",
			lineEnding: "\n",
			resourcesDirectory: "/",
			separator: "/",

			// on iphone, tempDirectory = "file://localhost/var/folders/14/_wzcmsd17pn76bzvb5lsmzr40000gn/T/"
			tempDirectory: "/tmp"
		},

		createFile: function(args){
			var m = require("Ti/Filesystem/File");
			return new m(args);
		},

		createTempDirectory: function(args) {
			//
		},

		createTempFile: function(args) {
			//
		},

		getFile: function(args) {
			//
		},

		isExternalStoragePresent: function(args) {
			return false;
		}

	});

});<|endoftext|>


<commit_before>module.exports = function(sequelize, DataTypes) {
  return sequelize.define('Comment',
    {
      texto:  {
        type:DataTypes.STRING,
        validate: {notEmpty: {msg: "-> Falta Comentario"}}
      },
      publicado{
        type:DataTypes.BOOLEAN,
        validate: false
      }
    }
  );
};
<commit_msg>login, sesion y comentarios<commit_after>module.exports = function(sequelize, DataTypes) {
  return sequelize.define('Comment',
    {
      texto:  {
        type:DataTypes.STRING,
        validate: {notEmpty: {msg: "-> Falta Comentario"}}
      },
      publicado: {
        type:DataTypes.BOOLEAN,
        validate: false
      }
    }
  );
};
<|endoftext|>


<commit_before>var mongoose = require('mongoose');
var bcrypt = require('bcrypt');

var PlayerSchema = new mongoose.Schema({
	name : {
		type: String,
		unique: true,
		required: true
	},
	height: {
		type: String,
		required: true
	},
	weight: {
		type: int,
		required: true
	},
	position: {
		type: String,
		required: true
	},
	hometown: {
		type: String,
		required: true
	},
	homestate: {
		type: String,
		required: true
	},
	year: {
		type: String,
		required: true
	}
});

module.exports = mongoose.model('Player', PlayerSchema);
<commit_msg>updated weight to string in player schema<commit_after>var mongoose = require('mongoose');
var bcrypt = require('bcrypt');

var PlayerSchema = new mongoose.Schema({
	name : {
		type: String,
		unique: true,
		required: true
	},
	height: {
		type: String,
		required: true
	},
	weight: {
		type: String,
		required: true
	},
	position: {
		type: String,
		required: true
	},
	hometown: {
		type: String,
		required: true
	},
	homestate: {
		type: String,
		required: true
	},
	year: {
		type: String,
		required: true
	}
});

module.exports = mongoose.model('Player', PlayerSchema);
<|endoftext|>


<commit_before>var _ = require('underscore'),
  async = require('async'),
  db = require('./db'),
  fs = require('fs'),
  fsx = require('fs.extra'),
  p = require('path');

/**
 * Get database names from config keys.
 *
 * @param {Object} dbConfig: database config
 * @return {Array} an array of database names
 */
function _databases(dbConfig) {
  return _.keys(dbConfig);
}

/**
 * Check each document:
 * - if it's an object, leave as-is
 * - if it's a json file then assign the content of the file as the document
 * - otherwise assume it's a module and require it
 * Location of file and module is based on the configured dir.
 *
 * @param {Object} dbConfig: database config
 * @return {Array} an array of database names
 */
function _docs(dbConfig, dir) {
  _.keys(dbConfig).forEach(function (dbName) {
    for (var i = 0, ln = dbConfig[dbName].length; i < ln; i += 1) {
      var item = dbConfig[dbName][i];
      if (_.isString(item)) {
        if (item.match(/\.json$/)) {
          dbConfig[dbName][i] = JSON.parse(fs.readFileSync(p.join(dir, item)));
        } else {
          dbConfig[dbName][i] = require(p.join(dir, item));
        }
      }
    }
  });
  return dbConfig;
}

/**
 * class Couchpenter
 *
 * @param {String} url: CouchDB URL in format http(s)://user:pass@host:port
 * @param {Object} dbConfig: database config
 * @param {String} dir: base directory of document paths in database config file, default is current working directory
 */
function Couchpenter(url, dbConfig, dir) {
  this.url = url || 'http://localhost:5984';
  this.dbConfig = dbConfig || {};
  this.dir = dir || process.cwd();
}

/**
 * Create a sample couchpenter.json configuration file in current directory.
 *
 * @param {Function} cb: standard cb(err, result) callback
 */
Couchpenter.prototype.config = function (cb) {
  console.log('Creating sample configuration file: couchpenter.json');
  fsx.copy(p.join(__dirname, '../examples/couchpenter.json'), 'couchpenter.json', cb);
};

/**
 * Execute database tasks in a series order.
 *
 * @param {Array} taskNames: the tasks to execute
 * @param {Function} cb: standard cb(err, result) callback
 */
Couchpenter.prototype.task = function (taskNames, cb) {
  var _db = new db(this.url, this.dbConfig, this.dir),
    self = this;
  async.forEachSeries(taskNames, function (taskName, cb) {
    var data = (taskName.match(/Databases$/)) ?
      _databases(self.dbConfig) :
      _docs(self.dbConfig, self.dir);
    _db[taskName](data, cb);
  }, cb);
};

/**
 * Set up databases and documents.
 * Convenient function for programmatical usage of Couchpenter.
 *
 * @param {Function} cb: standard cb(err, result) callback
 */
Couchpenter.prototype.setUp = function (cb) {
  this.task(['setUpDatabases', 'setUpDocuments'], cb);
};

/**
 * Delete databases and documents.
 * Convenient function for programmatical usage of Couchpenter.
 *
 * @param {Function} cb: standard cb(err, result) callback
 */
Couchpenter.prototype.tearDown = function (cb) {
  this.task(['tearDownDatabases'], cb);
};

module.exports = Couchpenter;<commit_msg>Modify task execution to use async.series instead of async.forEachSeries due to task results not being passed to main callback in async.forEachSeries.<commit_after>var _ = require('underscore'),
  async = require('async'),
  db = require('./db'),
  fs = require('fs'),
  fsx = require('fs.extra'),
  p = require('path');

/**
 * Get database names from config keys.
 *
 * @param {Object} dbConfig: database config
 * @return {Array} an array of database names
 */
function _databases(dbConfig) {
  return _.keys(dbConfig);
}

/**
 * Check each document:
 * - if it's an object, leave as-is
 * - if it's a json file then assign the content of the file as the document
 * - otherwise assume it's a module and require it
 * Location of file and module is based on the configured dir.
 *
 * @param {Object} dbConfig: database config
 * @return {Array} an array of database names
 */
function _docs(dbConfig, dir) {
  _.keys(dbConfig).forEach(function (dbName) {
    for (var i = 0, ln = dbConfig[dbName].length; i < ln; i += 1) {
      var item = dbConfig[dbName][i];
      if (_.isString(item)) {
        if (item.match(/\.json$/)) {
          dbConfig[dbName][i] = JSON.parse(fs.readFileSync(p.join(dir, item)));
        } else {
          dbConfig[dbName][i] = require(p.join(dir, item));
        }
      }
    }
  });
  return dbConfig;
}

/**
 * class Couchpenter
 *
 * @param {String} url: CouchDB URL in format http(s)://user:pass@host:port
 * @param {Object} dbConfig: database config
 * @param {String} dir: base directory of document paths in database config file, default is current working directory
 */
function Couchpenter(url, dbConfig, dir) {
  this.url = url || 'http://localhost:5984';
  this.dbConfig = dbConfig || {};
  this.dir = dir || process.cwd();
}

/**
 * Create a sample couchpenter.json configuration file in current directory.
 *
 * @param {Function} cb: standard cb(err, result) callback
 */
Couchpenter.prototype.config = function (cb) {
  console.log('Creating sample configuration file: couchpenter.json');
  fsx.copy(p.join(__dirname, '../examples/couchpenter.json'), 'couchpenter.json', cb);
};

/**
 * Execute database tasks in a series order.
 *
 * @param {Array} taskNames: the tasks to execute
 * @param {Function} cb: standard cb(err, result) callback
 */
Couchpenter.prototype.task = function (taskNames, cb) {
  var _db = new db(this.url, this.dbConfig, this.dir),
    tasks = [],
    self = this;
  taskNames.forEach(function (taskName) {
    tasks.push(function (cb) {
      var data = (taskName.match(/Databases$/)) ?
        _databases(self.dbConfig) :
        _docs(self.dbConfig, self.dir);
      _db[taskName](data, cb);
    });
  });
  async.series(tasks, cb);
};

/**
 * Set up databases and documents.
 * Convenient function for programmatical usage of Couchpenter.
 *
 * @param {Function} cb: standard cb(err, result) callback
 */
Couchpenter.prototype.setUp = function (cb) {
  this.task(['setUpDatabases', 'setUpDocuments'], cb);
};

/**
 * Delete databases and documents.
 * Convenient function for programmatical usage of Couchpenter.
 *
 * @param {Function} cb: standard cb(err, result) callback
 */
Couchpenter.prototype.tearDown = function (cb) {
  this.task(['tearDownDatabases'], cb);
};

module.exports = Couchpenter;<|endoftext|>


<commit_before>/* global _ */

'use strict';
angular.module('metadatamanagementApp').service(
  'ProjectUpdateAccessService',
  function(CurrentProjectService, Principal, SimpleMessageToastService) {

    var messagePrefix = 'data-acquisition-project-management.error.project' +
      '-update-access.';

    var errorList = {
      projectSelected: messagePrefix + 'project-selected',
      typeUpdateAllowed: messagePrefix + 'type-update-allowed',
      projectUnreleased: messagePrefix + 'project-released',
      memberOfAssignedGroup: messagePrefix + 'member-of-assigned-group',
      assignedToProject: messagePrefix + 'assigned-to-project',
      isNotRequired: messagePrefix + 'not-required'
    };

    var isProjectSelected = function(project) {
      return project !== undefined && project !== null;
    };

    var isProjectUnreleased = function(project) {
      return !project.release;
    };

    var isMemberOfAssignedGroup = function(project) {
      switch (project.assigneeGroup) {
        case 'PUBLISHER':
          return Principal.hasAuthority('ROLE_PUBLISHER');
        case 'DATA_PROVIDER':
          return Principal.hasAuthority('ROLE_DATA_PROVIDER');
        default:
          return false;
      }
    };

    var isTypeRequired = function(project, type) {
      if (type) {
        type = type === 'data_sets' ? 'dataSets' : type;
        return _.get(project, 'configuration.requirements.' + type +
          'Required');
      } else {
        return false;
      }
    };

    var isPublisherReady = function(project, type) {
      var isTypeReady = false;
      if (type) {
        var conf = project.configuration;
        switch (type) {
          case 'studies':
            isTypeReady = _.get(conf, 'studiesState.dataProviderReady') ||
              _.get(conf, 'studiesState.publisherReady');
            break;
          case 'surveys':
            isTypeReady = _.get(conf, 'surveysState.dataProviderReady') ||
              _.get(conf, 'surveysState.publisherReady');
            break;
          case 'instruments':
            isTypeReady = _.get(conf, 'instrumentsState.dataProviderReady') ||
              _.get(conf, 'instrumentsState.publisherReady');
            break;
          case 'data_sets':
            isTypeReady = _.get(conf, 'dataSetsState.dataProviderReady') ||
              _.get(conf, 'dataSetsState.publisherReady');
            break;
          case 'questions':
            isTypeReady = _.get(conf, 'questionsState.dataProviderReady') ||
              _.get(conf, 'questionsState.publisherReady');
            break;
          case 'variables':
            isTypeReady = _.get(conf, 'variablesState.dataProviderReady') ||
              _.get(conf, 'variablesState.publisherReady');
            break;
        }
      }
      return !isTypeReady;
    };

    var isAssignedToProject = function(project) {
      var userLogin = Principal.loginName();
      if (Principal.hasAuthority('ROLE_PUBLISHER')) {
        return project.configuration.publishers.indexOf(userLogin) !== -1;
      }

      if (Principal.hasAuthority('ROLE_DATA_PROVIDER')) {
        return project.configuration.dataProviders.indexOf(userLogin) !== -1;
      }

      return false;
    };

    var isUpdateAllowed = function(project, type, notify) {
      var test = project || CurrentProjectService.getCurrentProject();
      var isValid = true;

      var projectSelected = isProjectSelected.bind(null, test);
      projectSelected.canContinue = false;
      projectSelected.errorKey = errorList.projectSelected;

      var assignedToProject = isAssignedToProject.bind(null, test);
      assignedToProject.canContinue = false;
      assignedToProject.errorKey = errorList.assignedToProject;

      var typeRequired = isTypeRequired.bind(null, test, type);
      typeRequired.canContinue = true;
      typeRequired.errorKey = errorList.isNotRequired;

      var memberOfAssignedGroup = isMemberOfAssignedGroup.bind(null, test);
      memberOfAssignedGroup.canContinue = true;
      memberOfAssignedGroup.errorKey = errorList.memberOfAssignedGroup;

      var publisherReady = isPublisherReady.bind(null, test, type);
      publisherReady.canContinue = true;
      publisherReady.errorKey = errorList.typeUpdateAllowed;

      var projectUnreleased = isProjectUnreleased.bind(null, test);
      projectUnreleased.canContinue = true;
      projectUnreleased.errorKey = errorList.projectUnreleased;

      var validations = [projectSelected, assignedToProject, typeRequired,
        memberOfAssignedGroup, publisherReady, projectUnreleased];

      for (var i = 0; i < validations.length; i++) {
        try {
          validations[i].isValid = validations[i](project);
        } catch (e) {
          isValid = false;
          console.error('error during validation:', e);
          break;
        }
        isValid = isValid && validations[i].isValid;
        if (!validations[i].isValid && !validations[i].canContinue) {
          break;
        }
      }

      if (notify) {
        validations.forEach(function(validation) {
          if (validation.isValid === false) {
            SimpleMessageToastService
              .openAlertMessageToast(validation.errorKey);
          }
        });
      }

      return isValid;
    };

    return {
      isUpdateAllowed: isUpdateAllowed
    };

  });
<commit_msg>#1844 Fix jscs error<commit_after>/* global _ */

'use strict';
angular.module('metadatamanagementApp').service(
  'ProjectUpdateAccessService',
  function(CurrentProjectService, Principal, SimpleMessageToastService) {

    var messagePrefix = 'data-acquisition-project-management.error.project' +
      '-update-access.';

    var errorList = {
      projectSelected: messagePrefix + 'project-selected',
      typeUpdateAllowed: messagePrefix + 'type-update-allowed',
      projectUnreleased: messagePrefix + 'project-released',
      memberOfAssignedGroup: messagePrefix + 'member-of-assigned-group',
      assignedToProject: messagePrefix + 'assigned-to-project',
      isNotRequired: messagePrefix + 'not-required'
    };

    var isProjectSelected = function(project) {
      return project !== undefined && project !== null;
    };

    var isProjectUnreleased = function(project) {
      return !project.release;
    };

    var isMemberOfAssignedGroup = function(project) {
      switch (project.assigneeGroup) {
        case 'PUBLISHER':
          return Principal.hasAuthority('ROLE_PUBLISHER');
        case 'DATA_PROVIDER':
          return Principal.hasAuthority('ROLE_DATA_PROVIDER');
        default:
          return false;
      }
    };

    var isTypeRequired = function(project, type) {
      if (type) {
        type = type === 'data_sets' ? 'dataSets' : type;
        return _.get(project, 'configuration.requirements.' + type +
          'Required');
      } else {
        return false;
      }
    };

    var isPublisherReady = function(project, type) {
      var isTypeReady = false;
      if (type) {
        var conf = project.configuration;
        switch (type) {
          case 'studies':
            isTypeReady = _.get(conf, 'studiesState.dataProviderReady') ||
              _.get(conf, 'studiesState.publisherReady');
            break;
          case 'surveys':
            isTypeReady = _.get(conf, 'surveysState.dataProviderReady') ||
              _.get(conf, 'surveysState.publisherReady');
            break;
          case 'instruments':
            isTypeReady = _.get(conf, 'instrumentsState.dataProviderReady') ||
              _.get(conf, 'instrumentsState.publisherReady');
            break;
          case 'data_sets':
            isTypeReady = _.get(conf, 'dataSetsState.dataProviderReady') ||
              _.get(conf, 'dataSetsState.publisherReady');
            break;
          case 'questions':
            isTypeReady = _.get(conf, 'questionsState.dataProviderReady') ||
              _.get(conf, 'questionsState.publisherReady');
            break;
          case 'variables':
            isTypeReady = _.get(conf, 'variablesState.dataProviderReady') ||
              _.get(conf, 'variablesState.publisherReady');
            break;
        }
      }
      return !isTypeReady;
    };

    var isAssignedToProject = function(project) {
      var userLogin = Principal.loginName();
      if (Principal.hasAuthority('ROLE_PUBLISHER')) {
        return project.configuration.publishers.indexOf(userLogin) !== -1;
      }

      if (Principal.hasAuthority('ROLE_DATA_PROVIDER')) {
        return project.configuration.dataProviders.indexOf(userLogin) !== -1;
      }

      return false;
    };

    var isUpdateAllowed = function(project, type, notify) {
      var test = project || CurrentProjectService.getCurrentProject();
      var isValid = true;

      var projectSelected = isProjectSelected.bind(null, test);
      projectSelected.canContinue = false;
      projectSelected.errorKey = errorList.projectSelected;

      var assignedToProject = isAssignedToProject.bind(null, test);
      assignedToProject.canContinue = false;
      assignedToProject.errorKey = errorList.assignedToProject;

      var typeRequired = isTypeRequired.bind(null, test, type);
      typeRequired.canContinue = true;
      typeRequired.errorKey = errorList.isNotRequired;

      var memberOfAssignedGroup = isMemberOfAssignedGroup.bind(null, test);
      memberOfAssignedGroup.canContinue = true;
      memberOfAssignedGroup.errorKey = errorList.memberOfAssignedGroup;

      var publisherReady = isPublisherReady.bind(null, test, type);
      publisherReady.canContinue = true;
      publisherReady.errorKey = errorList.typeUpdateAllowed;

      var projectUnreleased = isProjectUnreleased.bind(null, test);
      projectUnreleased.canContinue = true;
      projectUnreleased.errorKey = errorList.projectUnreleased;

      var validations = [projectSelected, assignedToProject, typeRequired,
        memberOfAssignedGroup, publisherReady, projectUnreleased];

      for (var i = 0; i < validations.length; i++) {
        try {
          validations[i].isValid = validations[i](project);
        } catch (e) {
          isValid = false;
          console.error('error during validation:', e);
          break;
        }
        isValid = isValid && validations[i].isValid;
        if (!validations[i].isValid && !validations[i].canContinue) {
          break;
        }
      }

      if (notify) {
        validations.forEach(function(validation) {
          if (validation.isValid === false) {
            SimpleMessageToastService
              .openAlertMessageToast(validation.errorKey);
          }
        });
      }

      return isValid;
    };

    return {
      isUpdateAllowed: isUpdateAllowed
    };

  });
<|endoftext|>


<commit_before>(function( $, undefined ) {
    $.KBWidget({
        name: "KBaseLitWidget",
        parent: "kbaseWidget",
        version: "1.0.0",

        options: {
            genomeID: null,
            workspaceID: null,
			kbCache: null,
            loadingImage: "../../widgets/images/ajax-loader.gif",
            isInCard: false,
			width: 600,
			height: 700,
        },

		init: function(options) {
			this._super(options);

			if (this.options.row === null) {
				//throw an error
				return;
			}
            return this.render();
		},

		addInfoRow: function(a, b) {
            return "
" + a + "	" + b + "
";
        },

		xmlToJson: function(xml) {
				self = this;
				// Create the return object
				var obj = {};

				if (xml.nodeType == 1) { // element
					// do attributes
					if (xml.attributes.length > 0) {
					obj["@attributes"] = {};
						for (var j = 0; j < xml.attributes.length; j++) {
							var attribute = xml.attributes.item(j);
							obj["@attributes"][attribute.nodeName] = attribute.nodeValue;
						}
					}
				} else if (xml.nodeType == 3) { // text
					obj = xml.nodeValue;
				}

				// do children
				if (xml.hasChildNodes()) {
					for(var i = 0; i < xml.childNodes.length; i++) {
						var item = xml.childNodes.item(i);
						var nodeName = item.nodeName;
						if (typeof(obj[nodeName]) == "undefined") {
							obj[nodeName] = self.xmlToJson(item);
						} else {
							if (typeof(obj[nodeName].push) == "undefined") {
								var old = obj[nodeName];
								obj[nodeName] = [];
								obj[nodeName].push(old);
							}
							obj[nodeName].push(self.xmlToJson(item));
						}
					}
				}
				return obj;
		},

		render: function(options) {

			self = this;

			var lit = self.options.literature

			var resultsDiv = $("
").append('
')
			var searchBarDiv = $("
").append("<input type='text' id='lit-query-box'>")
			var searchBarButton = $("<input type='button' id='lit-search-button' value='Update Search'>")
									.on("click",function() {
										lit = $('#lit-query-box').val()
										tableInput = []
										litDataTable.fnDestroy()
										populateSearch(lit)
									})

			var tableInput = []
			var litDataTable;

			self.$elem.append(searchBarDiv.append(searchBarButton)).append(resultsDiv)

			$('#lit-query-box').val(lit)
			$('#lit-query-box').css({"width":"300px"})
			populateSearch(lit)

			function parseLitSearchDataTable(query) {
				var tableInputRow = {}

				$.get(query,
					function(data) {
						var htmlJson = self.xmlToJson(data)

						var litInfo = htmlJson.eSummaryResult[1].DocSum.Item
						// if (data[0].length == 0) {
								// self.$elem.append("
There are no other data objects (you can access) that reference this object.");
						// } else {
						for (i=0;i<litInfo.length;i++) {
							if ("#text" in litInfo[i]) {
								if (litInfo[i]["@attributes"].Name == "Source") tableInputRow["jo"] = litInfo[i]["#text"]
								if (litInfo[i]["@attributes"].Name == "AuthorList") {
									if ($.isArray(litInfo[i].Item)) {
										var authors = ""
										for (j=0;j<litInfo[i].Item.length;j++) {
											authors+=litInfo[i].Item[j]["#text"]
											if (j!=litInfo[i].Item.length-1) authors+=", "
										}
										tableInputRow["au"] = authors
									}
									else {tableInputRow["au"] = litInfo[i].Item["#text"]}
								}
								if (litInfo[i]["@attributes"].Name == "Title") {
									var pubmedLink = "http://www.ncbi.nlm.nih.gov/pubmed/"+htmlJson.eSummaryResult[1].DocSum.Id["#text"]
									tableInputRow["ti"] = "" + litInfo[i]["#text"] + ""
								}
							}
						}

					}
				)
				return tableInputRow
			}

			function populateSearch(lit) {
				$.get('http://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi?db=pubmed&term='+lit.replace(/\s+/g, "+"),
					function(data) {

						var htmlJson = self.xmlToJson(data)
						if ($.isArray(htmlJson.eSearchResult[1].IdList.Id)) {

							for (x=0;x<htmlJson.eSearchResult[1].IdList.Id.length;x++) {
								var query = 'http://eutils.ncbi.nlm.nih.gov/entrez/eutils/esummary.fcgi?db=pubmed&id='+htmlJson.eSearchResult[1].IdList.Id[x]['#text']
								tableInput.push(parseLitSearchDataTable(query))
							}
						}
						else {
							console.log(htmlJson)
							var query = 'http://eutils.ncbi.nlm.nih.gov/entrez/eutils/esummary.fcgi?db=pubmed&id='+htmlJson.eSearchResult[1].IdList.Id['#text']
							tableInput.push(parseLitSearchDataTable(query))
						}
						var sDom = 't<flip>'
						if (tableInput.length<=10) { sDom = 'tfi'; }

						setTimeout(function(){
							litDataTable = self.$elem.find('#literature-table').dataTable(
								{
									"sPaginationType": "full_numbers",
									"iDisplayLength": 10,
									"sDom": sDom,
									"aoColumns": [
										{sTitle: "Journal", mData: "jo"},
										{sTitle: "Authors", mData: "au"},
										{sTitle: "Title", mData: "ti"}
									],
									"aaData": tableInput
								}
							)
						},1000);
					}
				)
			}

			return this;
		},

	    getData: function() {
            return {
                type: "LitWidget",
                id: this.options.genomeID,
                workspace: this.options.workspaceID,
                title: "Literature"
            };
        },
	});
})(jQuery);<commit_msg>literature widget now displays more than 20 results<commit_after>(function( $, undefined ) {
    $.KBWidget({
        name: "KBaseLitWidget",
        parent: "kbaseWidget",
        version: "1.0.0",

        options: {
            genomeID: null,
            workspaceID: null,
			kbCache: null,
            loadingImage: "../../widgets/images/ajax-loader.gif",
            isInCard: false,
			width: 600,
			height: 700,
        },

		init: function(options) {
			this._super(options);

			if (this.options.row === null) {
				//throw an error
				return;
			}
            return this.render();
		},

		addInfoRow: function(a, b) {
            return "
" + a + "	" + b + "
";
        },

		xmlToJson: function(xml) {
				self = this;
				// Create the return object
				var obj = {};

				if (xml.nodeType == 1) { // element
					// do attributes
					if (xml.attributes.length > 0) {
					obj["@attributes"] = {};
						for (var j = 0; j < xml.attributes.length; j++) {
							var attribute = xml.attributes.item(j);
							obj["@attributes"][attribute.nodeName] = attribute.nodeValue;
						}
					}
				} else if (xml.nodeType == 3) { // text
					obj = xml.nodeValue;
				}

				// do children
				if (xml.hasChildNodes()) {
					for(var i = 0; i < xml.childNodes.length; i++) {
						var item = xml.childNodes.item(i);
						var nodeName = item.nodeName;
						if (typeof(obj[nodeName]) == "undefined") {
							obj[nodeName] = self.xmlToJson(item);
						} else {
							if (typeof(obj[nodeName].push) == "undefined") {
								var old = obj[nodeName];
								obj[nodeName] = [];
								obj[nodeName].push(old);
							}
							obj[nodeName].push(self.xmlToJson(item));
						}
					}
				}
				return obj;
		},

		render: function(options) {

			self = this;

			var lit = self.options.literature

			var resultsDiv = $("
").append('
')
			var searchBarDiv = $("
").append("<input type='text' id='lit-query-box'>")
			var searchBarButton = $("<input type='button' id='lit-search-button' value='Update Search'>")
									.on("click",function() {
										lit = $('#lit-query-box').val()
										tableInput = []
										litDataTable.fnDestroy()
										populateSearch(lit)
									})

			var tableInput = []
			var litDataTable;

			self.$elem.append(searchBarDiv.append(searchBarButton)).append(resultsDiv)

			$('#lit-query-box').val(lit)
			$('#lit-query-box').css({"width":"300px"})
			populateSearch(lit)

			function parseLitSearchDataTable(query) {
				var tableInputRow = {}

				$.ajax({
					async: false,
					url: query,
					type: 'GET',
					success:
					function(data) {
						var htmlJson = self.xmlToJson(data)
						var litInfo = htmlJson.eSummaryResult[1].DocSum.Item
						// if (data[0].length == 0) {
								// self.$elem.append("
There are no other data objects (you can access) that reference this object.");
						// } else {
						for (i=0;i<litInfo.length;i++) {
							if ("#text" in litInfo[i]) {
								if (litInfo[i]["@attributes"].Name == "Source") tableInputRow["jo"] = litInfo[i]["#text"]
								if (litInfo[i]["@attributes"].Name == "AuthorList") {
									if ($.isArray(litInfo[i].Item)) {
										var authors = ""
										for (j=0;j<litInfo[i].Item.length;j++) {
											authors+=litInfo[i].Item[j]["#text"]
											if (j!=litInfo[i].Item.length-1) authors+=", "
										}
										tableInputRow["au"] = authors
									}
									else {tableInputRow["au"] = litInfo[i].Item["#text"]}
								}
								if (litInfo[i]["@attributes"].Name == "Title") {
									var pubmedLink = "http://www.ncbi.nlm.nih.gov/pubmed/"+htmlJson.eSummaryResult[1].DocSum.Id["#text"]
									tableInputRow["ti"] = "" + litInfo[i]["#text"] + ""
								}
							}
						}
					}
				})
				return tableInputRow
			}

			function populateSearch(lit) {

				$.ajax({
					async: true,
					url: 'http://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi?db=pubmed&retmax=100000&term='+lit.replace(/\s+/g, "+"),
					type: 'GET',
					success:
					function(data) {

						var htmlJson = self.xmlToJson(data)
						console.log(htmlJson)
						if ($.isArray(htmlJson.eSearchResult[1].IdList.Id)) {

							for (x=0;x<htmlJson.eSearchResult[1].IdList.Id.length;x++) {
								var query = 'http://eutils.ncbi.nlm.nih.gov/entrez/eutils/esummary.fcgi?db=pubmed&id='+htmlJson.eSearchResult[1].IdList.Id[x]['#text']
								tableInput.push(parseLitSearchDataTable(query))
							}
						}
						else {
							console.log(htmlJson)
							var query = 'http://eutils.ncbi.nlm.nih.gov/entrez/eutils/esummary.fcgi?db=pubmed&id='+htmlJson.eSearchResult[1].IdList.Id['#text']
							tableInput.push(parseLitSearchDataTable(query))
						}
						var sDom = 't<flip>'
						if (tableInput.length<=10) { sDom = 'tfi'; }
						console.log(tableInput)
						var tableSettings = {
							"sPaginationType": "full_numbers",
							"iDisplayLength": 10,
							"sDom": sDom,
							"aoColumns": [
								{sTitle: "Journal", mData: "jo"},
								{sTitle: "Authors", mData: "au"},
								{sTitle: "Title", mData: "ti"}
							],
							"aaData": tableInput
						}
						litDataTable = self.$elem.find('#literature-table').dataTable(tableSettings)

					}
				})
			}

			return this;
		},

	    getData: function() {
            return {
                type: "LitWidget",
                id: this.options.genomeID,
                workspace: this.options.workspaceID,
                title: "Literature"
            };
        },
	});
})(jQuery);<|endoftext|>


<commit_before>import { isInteger, merge } from 'lodash'
import EventEmitter from 'eventemitter3'

import BackendInterface from './BackendInterface'
import GRPCInterface from './GRPCInterface'
import StoreInterface from './StoreInterface'
import { prefixString, timeoutCallback } from './utils'

function ServiceNode (_settings) {
  let settings = merge({}, defaultSettings, _settings)
  _validateSettings(settings)

  let node = new EventEmitter()

  let {
    host,
    port,
    credentials,
    backendSetupTimeout,
    backend,
    cluster
  } = settings

  // Private API
  let _connected = false
  let _connecting = false
  let _disconnecting = false
  let _backend = BackendInterface(backend)
  let _backendSetupTimeout = timeoutCallback(backendSetupTimeout, iMsg(`Backend setup timed out.`))
  let _store = StoreInterface({host, ...cluster})
  let _grpcServer = GRPCInterface({port, credentials, backend: _backend, store: _store})

  // Public api
  function connect () {
    if (_connected || _connecting || _disconnecting) return node
    _connecting = true

    _backend.setup(_backendSetupTimeout((err) => {
      if (err) {
        _connecting = false
        console.error(err)
        return
      }
      _store.once('connect', () => _grpcServer.connect())
      _grpcServer.once('connect', () => {
        _connected = true
        _connecting = false
        node.emit('connect')
      })
      _store.connect()
    }))
    return node
  }
  function disconnect () {
    if (!_connected || _connecting || _disconnecting) return node
    _disconnecting = true

    _grpcServer.once('disconnect', () => _store.disconnect())
    _store.once('disconnect', () => {
      _connected = false
      _disconnecting = true
      node.emit('disconnect')
    })
    _grpcServer.disconnect()
    return node
  }

  Object.defineProperty(node, 'connect', {value: connect})
  Object.defineProperty(node, 'disconnect', {value: disconnect})
  return node
}

const defaultSettings = {
  host: 'localhost',
  port: 1234,
  backendSetupTimeout: 1000,
  backend: {
    type: 'cockroachdb',
    host: 'localhost',
    port: 1234,
    database: 'eventstore',
    user: 'root'
  },
  cluster: {
    coordinationPort: 50061
  }
}

const iMsg = prefixString('[gRPC EventStore ServiceNode]: ')
function _validateSettings (settings) {
  let {
    backendSetupTimeout
  } = settings

  if (!isInteger(backendSetupTimeout) || backendSetupTimeout < 1) throw new TypeError(iMsg('settings.setupTimeout should be a positive integer'))
  if (backendSetupTimeout < 500) console.warn(iMsg('a value of less than 500 msec for settings.backendSetupTimeout could affect the right functioning of the EventStore backend'))
}

ServiceNode.customBackend = BackendInterface.customBackend

export default ServiceNode
<commit_msg>better defaults<commit_after>import { isInteger, assign } from 'lodash'
import EventEmitter from 'eventemitter3'

import BackendInterface from './BackendInterface'
import GRPCInterface from './GRPCInterface'
import StoreInterface from './StoreInterface'
import { prefixString, timeoutCallback } from './utils'

function ServiceNode (_settings) {
  let settings = assign({}, defaultSettings, _settings)
  _validateSettings(settings)

  let node = new EventEmitter()

  let {
    host,
    port,
    coordinationPort,
    backendSetupTimeout,
    credentials,
    backend
  } = settings

  // Private API
  let _connected = false
  let _connecting = false
  let _disconnecting = false
  let _backend = BackendInterface(backend || {})
  let _backendSetupTimeout = timeoutCallback(backendSetupTimeout, iMsg(`Backend setup timed out.`))
  let _store = StoreInterface({host, coordinationPort})
  let _grpcServer = GRPCInterface(assign(
    {},
    {backend: _backend, store: _store},
    port ? {port} : {},
    credentials ? {credentials} : {}
  ))

  // Public api
  function connect () {
    if (_connected || _connecting || _disconnecting) return node
    _connecting = true

    _backend.setup(_backendSetupTimeout((err) => {
      if (err) {
        _connecting = false
        console.error(err)
        return
      }
      _store.once('connect', () => _grpcServer.connect())
      _grpcServer.once('connect', () => {
        _connected = true
        _connecting = false
        node.emit('connect')
      })
      _store.connect()
    }))
    return node
  }
  function disconnect () {
    if (!_connected || _connecting || _disconnecting) return node
    _disconnecting = true

    _grpcServer.once('disconnect', () => _store.disconnect())
    _store.once('disconnect', () => {
      _connected = false
      _disconnecting = true
      node.emit('disconnect')
    })
    _grpcServer.disconnect()
    return node
  }

  Object.defineProperty(node, 'connect', {value: connect})
  Object.defineProperty(node, 'disconnect', {value: disconnect})
  return node
}

const defaultSettings = {
  host: 'localhost',
  coordinationPort: 50061,
  backendSetupTimeout: 1000
  /*
  port
  credentials
  backend
  */
}

const iMsg = prefixString('[gRPC EventStore ServiceNode]: ')
function _validateSettings (settings) {
  let {
    backendSetupTimeout
  } = settings

  if (!isInteger(backendSetupTimeout) || backendSetupTimeout < 1) throw new TypeError(iMsg('settings.setupTimeout should be a positive integer'))
  if (backendSetupTimeout < 500) console.warn(iMsg('a value of less than 500 msec for settings.backendSetupTimeout could affect the right functioning of the EventStore backend'))
}

ServiceNode.customBackend = BackendInterface.customBackend

export default ServiceNode
<|endoftext|>