<commit_before>/*
 * jQuery UI Button @VERSION
 *
 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Button
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.widget.js
 */
(function( $, undefined ) {

var lastActive,
	baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
	stateClasses = "ui-state-hover ui-state-active ",
	typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",
	formResetHandler = function( event ) {
		$( ":ui-button", event.target.form ).each(function() {
			var inst = $( this ).data( "button" );
			setTimeout(function() {
				inst.refresh();
			}, 1 );
		});
	},
	radioGroup = function( radio ) {
		var name = radio.name,
			form = radio.form,
			radios = $( [] );
		if ( name ) {
			if ( form ) {
				radios = $( form ).find( "[name='" + name + "']" );
			} else {
				radios = $( "[name='" + name + "']", radio.ownerDocument )
					.filter(function() {
						return !this.form;
					});
			}
		}
		return radios;
	};

$.widget( "ui.button", {
	defaultElement: "<button>",
	options: {
		disabled: null,
		text: true,
		label: null,
		icons: {
			primary: null,
			secondary: null
		}
	},
	_create: function() {
		this.element.closest( "form" )
			.unbind( "reset.button" )
			.bind( "reset.button", formResetHandler );

		if ( typeof this.options.disabled !== "boolean" ) {
			this.options.disabled = this.element.attr( "disabled" );
		}

		this._determineButtonType();
		this.hasTitle = !!this.buttonElement.attr( "title" );

		var self = this,
			options = this.options,
			toggleButton = this.type === "checkbox" || this.type === "radio",
			hoverClass = "ui-state-hover" + ( !toggleButton ? " ui-state-active" : "" ),
			focusClass = "ui-state-focus";

		if ( options.label === null ) {
			options.label = this.buttonElement.html();
		}

		if ( this.element.is( ":disabled" ) ) {
			options.disabled = true;
		}

		this.buttonElement
			.addClass( baseClasses )
			.attr( "role", "button" )
			.bind( "mouseenter.button", function() {
				if ( options.disabled ) {
					return;
				}
				$( this ).addClass( "ui-state-hover" );
				if ( this === lastActive ) {
					$( this ).addClass( "ui-state-active" );
				}
			})
			.bind( "mouseleave.button", function() {
				if ( options.disabled ) {
					return;
				}
				$( this ).removeClass( hoverClass );
			})
			.bind( "focus.button", function() {
				// no need to check disabled, focus won't be triggered anyway
				$( this ).addClass( focusClass );
			})
			.bind( "blur.button", function() {
				$( this ).removeClass( focusClass );
			})
			.bind( "click.button", function( event ) {
				if ( options.disabled ) {
					event.stopImmediatePropagation();
				}
			});

		if ( toggleButton ) {
			this.element.bind( "change.button", function() {
				self.refresh();
			});
		}

		if ( this.type === "checkbox" ) {
			this.buttonElement.bind( "click.button", function() {
				if ( options.disabled ) {
					return false;
				}
				$( this ).toggleClass( "ui-state-active" );
				self.buttonElement.attr( "aria-pressed", self.element[0].checked );
			});
		} else if ( this.type === "radio" ) {
			this.buttonElement.bind( "click.button", function() {
				if ( options.disabled ) {
					return false;
				}
				$( this ).addClass( "ui-state-active" );
				self.buttonElement.attr( "aria-pressed", true );

				var radio = self.element[ 0 ];
				radioGroup( radio )
					.not( radio )
					.map(function() {
						return $( this ).button( "widget" )[ 0 ];
					})
					.removeClass( "ui-state-active" )
					.attr( "aria-pressed", false );
			});
		} else {
			this.buttonElement
				.bind( "mousedown.button", function() {
					if ( options.disabled ) {
						return false;
					}
					$( this ).addClass( "ui-state-active" );
					lastActive = this;
					$( document ).one( "mouseup", function() {
						lastActive = null;
					});
				})
				.bind( "mouseup.button", function() {
					if ( options.disabled ) {
						return false;
					}
					$( this ).removeClass( "ui-state-active" );
				})
				.bind( "keydown.button", function(event) {
					if ( options.disabled ) {
						return false;
					}
					if ( event.keyCode == $.ui.keyCode.SPACE || event.keyCode == $.ui.keyCode.ENTER ) {
						$( this ).addClass( "ui-state-active" );
					}
				})
				.bind( "keyup.button", function() {
					$( this ).removeClass( "ui-state-active" );
				});

			if ( this.buttonElement.is("a") ) {
				this.buttonElement.keyup(function(event) {
					if ( event.keyCode === $.ui.keyCode.SPACE ) {
						// TODO pass through original event correctly (just as 2nd argument doesn't work)
						$( this ).click();
					}
				});
			}
		}

		// TODO: pull out $.Widget's handling for the disabled option into
		// $.Widget.prototype._setOptionDisabled so it's easy to proxy and can
		// be overridden by individual plugins
		this._setOption( "disabled", options.disabled );
		this._resetButton();
	},

	_determineButtonType: function() {

		if ( this.element.is(":checkbox") ) {
			this.type = "checkbox";
		} else if ( this.element.is(":radio") ) {
			this.type = "radio";
		} else if ( this.element.is("input") ) {
			this.type = "input";
		} else {
			this.type = "button";
		}

		if ( this.type === "checkbox" || this.type === "radio" ) {
			// we don't search against the document in case the element
			// is disconnected from the DOM
			var ancestor = this.element.parents().last(),
				labelSelector = "label[for=" + this.element.attr("id") + "]";
			this.buttonElement = ancestor.find( labelSelector );
			if ( !this.buttonElement.length ) {
				ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings();
				this.buttonElement = ancestor.filter( labelSelector );
				if ( !this.buttonElement.length ) {
					this.buttonElement = ancestor.find( labelSelector );
				}
			}
			this.element.addClass( "ui-helper-hidden-accessible" );

			var checked = this.element.is( ":checked" );
			if ( checked ) {
				this.buttonElement.addClass( "ui-state-active" );
			}
			this.buttonElement.attr( "aria-pressed", checked );
		} else {
			this.buttonElement = this.element;
		}
	},

	widget: function() {
		return this.buttonElement;
	},

	_destroy: function() {
		this.element
			.removeClass( "ui-helper-hidden-accessible" );
		this.buttonElement
			.removeClass( baseClasses + " " + stateClasses + " " + typeClasses )
			.removeAttr( "role" )
			.removeAttr( "aria-pressed" )
			.html( this.buttonElement.find(".ui-button-text").html() );

		if ( !this.hasTitle ) {
			this.buttonElement.removeAttr( "title" );
		}
	},

	_setOption: function( key, value ) {
		this._super( "_setOption", key, value );
		if ( key === "disabled" ) {
			if ( value ) {
				this.element.attr( "disabled", true );
			} else {
				this.element.removeAttr( "disabled" );
			}
			return;
		}
		this._resetButton();
	},

	refresh: function() {
		var isDisabled = this.element.is( ":disabled" );
		if ( isDisabled !== this.options.disabled ) {
			this._setOption( "disabled", isDisabled );
		}
		if ( this.type === "radio" ) {
			radioGroup( this.element[0] ).each(function() {
				if ( $( this ).is( ":checked" ) ) {
					$( this ).button( "widget" )
						.addClass( "ui-state-active" )
						.attr( "aria-pressed", true );
				} else {
					$( this ).button( "widget" )
						.removeClass( "ui-state-active" )
						.attr( "aria-pressed", false );
				}
			});
		} else if ( this.type === "checkbox" ) {
			if ( this.element.is( ":checked" ) ) {
				this.buttonElement
					.addClass( "ui-state-active" )
					.attr( "aria-pressed", true );
			} else {
				this.buttonElement
					.removeClass( "ui-state-active" )
					.attr( "aria-pressed", false );
			}
		}
	},

	_resetButton: function() {
		if ( this.type === "input" ) {
			if ( this.options.label ) {
				this.element.val( this.options.label );
			}
			return;
		}
		var buttonElement = this.buttonElement.removeClass( typeClasses ),
			buttonText = $( "" )
				.addClass( "ui-button-text" )
				.html( this.options.label )
				.appendTo( buttonElement.empty() )
				.text(),
			icons = this.options.icons,
			multipleIcons = icons.primary && icons.secondary,
			buttonClasses = [];

		if ( icons.primary || icons.secondary ) {
			if ( this.options.text ) {
				buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
			}

			if ( icons.primary ) {
				buttonElement.prepend( "" );
			}

			if ( icons.secondary ) {
				buttonElement.append( "" );
			}

			if ( !this.options.text ) {
				buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" );

				if ( !this.hasTitle ) {
					buttonElement.attr( "title", buttonText );
				}
			}
		} else {
			buttonClasses.push( "ui-button-text-only" );
		}
		buttonElement.addClass( buttonClasses.join( " " ) );
	}
});

$.ui.button.version = "@VERSION";

$.widget( "ui.buttonset", {
	options: {
		items: ":button, :submit, :reset, :checkbox, :radio, a, :data(button)"
	},

	_create: function() {
		this.element.addClass( "ui-buttonset" );
	},

	_init: function() {
		this.refresh();
	},

	_setOption: function( key, value ) {
		if ( key === "disabled" ) {
			this.buttons.button( "option", key, value );
		}

		this._super( "_setOption", key, value );
	},

	refresh: function() {
		var ltr = this.element.css( "direction" ) === "ltr";

		this.buttons = this.element.find( this.options.items )
			.filter( ":ui-button" )
				.button( "refresh" )
			.end()
			.not( ":ui-button" )
				.button()
			.end()
			.map(function() {
				return $( this ).button( "widget" )[ 0 ];
			})
				.removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
				.filter( ":first" )
					.addClass( ltr ? "ui-corner-left" : "ui-corner-right" )
				.end()
				.filter( ":last" )
					.addClass( ltr ? "ui-corner-right" : "ui-corner-left" )
				.end()
			.end();
	},

	_destroy: function() {
		this.element.removeClass( "ui-buttonset" );
		this.buttons
			.map(function() {
				return $( this ).button( "widget" )[ 0 ];
			})
				.removeClass( "ui-corner-left ui-corner-right" )
			.end()
			.button( "destroy" );
	}
});

$.ui.buttonset.version = "@VERSION";

}( jQuery ) );
<commit_msg>Button: Don't fire click/change events if mouse was dragged during click of toggle (checkbox/radio) button. Fixed #6970 - Button state inconsistencies after (accidental) drag-clicking the button.<commit_after>/*
 * jQuery UI Button @VERSION
 *
 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Button
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.widget.js
 */
(function( $, undefined ) {

var lastActive, startXPos, startYPos, clickDragged,
	baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
	stateClasses = "ui-state-hover ui-state-active ",
	typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",
	formResetHandler = function( event ) {
		$( ":ui-button", event.target.form ).each(function() {
			var inst = $( this ).data( "button" );
			setTimeout(function() {
				inst.refresh();
			}, 1 );
		});
	},
	radioGroup = function( radio ) {
		var name = radio.name,
			form = radio.form,
			radios = $( [] );
		if ( name ) {
			if ( form ) {
				radios = $( form ).find( "[name='" + name + "']" );
			} else {
				radios = $( "[name='" + name + "']", radio.ownerDocument )
					.filter(function() {
						return !this.form;
					});
			}
		}
		return radios;
	};

$.widget( "ui.button", {
	defaultElement: "<button>",
	options: {
		disabled: null,
		text: true,
		label: null,
		icons: {
			primary: null,
			secondary: null
		}
	},
	_create: function() {
		this.element.closest( "form" )
			.unbind( "reset.button" )
			.bind( "reset.button", formResetHandler );

		if ( typeof this.options.disabled !== "boolean" ) {
			this.options.disabled = this.element.attr( "disabled" );
		}

		this._determineButtonType();
		this.hasTitle = !!this.buttonElement.attr( "title" );

		var self = this,
			options = this.options,
			toggleButton = this.type === "checkbox" || this.type === "radio",
			hoverClass = "ui-state-hover" + ( !toggleButton ? " ui-state-active" : "" ),
			focusClass = "ui-state-focus";

		if ( options.label === null ) {
			options.label = this.buttonElement.html();
		}

		if ( this.element.is( ":disabled" ) ) {
			options.disabled = true;
		}

		this.buttonElement
			.addClass( baseClasses )
			.attr( "role", "button" )
			.bind( "mouseenter.button", function() {
				if ( options.disabled ) {
					return;
				}
				$( this ).addClass( "ui-state-hover" );
				if ( this === lastActive ) {
					$( this ).addClass( "ui-state-active" );
				}
			})
			.bind( "mouseleave.button", function() {
				if ( options.disabled ) {
					return;
				}
				$( this ).removeClass( hoverClass );
			})
			.bind( "focus.button", function() {
				// no need to check disabled, focus won't be triggered anyway
				$( this ).addClass( focusClass );
			})
			.bind( "blur.button", function() {
				$( this ).removeClass( focusClass );
			})
			.bind( "click.button", function( event ) {
				if ( options.disabled ) {
					event.stopImmediatePropagation();
				}
			});

		if ( toggleButton ) {
			this.element.bind( "change.button", function() {
				if ( clickDragged ) {
					return;
				}
				self.refresh();
			});
			// if mouse moves between mousedown and mouseup (drag) set clickDragged flag
			// prevents issue where button state changes but checkbox/radio checked state
			// does not in Firefox (see ticket #6970)
			this.buttonElement
				.bind( "mousedown.button", function( event ) {
					if ( options.disabled ) {
						return;
					}
					clickDragged = false;
					startXPos = event.pageX;
					startYPos = event.pageY;
				})
				.bind( "mouseup.button", function( event ) {
					if ( options.disabled ) {
						return;
					}
					if ( startXPos !== event.pageX || startYPos !== event.pageY ) {
						clickDragged = true;
					}
			});
		}

		if ( this.type === "checkbox" ) {
			this.buttonElement.bind( "click.button", function() {
				if ( options.disabled || clickDragged ) {
					return false;
				}
				$( this ).toggleClass( "ui-state-active" );
				self.buttonElement.attr( "aria-pressed", self.element[0].checked );
			});
		} else if ( this.type === "radio" ) {
			this.buttonElement.bind( "click.button", function() {
				if ( options.disabled || clickDragged ) {
					return false;
				}
				$( this ).addClass( "ui-state-active" );
				self.buttonElement.attr( "aria-pressed", true );

				var radio = self.element[ 0 ];
				radioGroup( radio )
					.not( radio )
					.map(function() {
						return $( this ).button( "widget" )[ 0 ];
					})
					.removeClass( "ui-state-active" )
					.attr( "aria-pressed", false );
			});
		} else {
			this.buttonElement
				.bind( "mousedown.button", function() {
					if ( options.disabled ) {
						return false;
					}
					$( this ).addClass( "ui-state-active" );
					lastActive = this;
					$( document ).one( "mouseup", function() {
						lastActive = null;
					});
				})
				.bind( "mouseup.button", function() {
					if ( options.disabled ) {
						return false;
					}
					$( this ).removeClass( "ui-state-active" );
				})
				.bind( "keydown.button", function(event) {
					if ( options.disabled ) {
						return false;
					}
					if ( event.keyCode == $.ui.keyCode.SPACE || event.keyCode == $.ui.keyCode.ENTER ) {
						$( this ).addClass( "ui-state-active" );
					}
				})
				.bind( "keyup.button", function() {
					$( this ).removeClass( "ui-state-active" );
				});

			if ( this.buttonElement.is("a") ) {
				this.buttonElement.keyup(function(event) {
					if ( event.keyCode === $.ui.keyCode.SPACE ) {
						// TODO pass through original event correctly (just as 2nd argument doesn't work)
						$( this ).click();
					}
				});
			}
		}

		// TODO: pull out $.Widget's handling for the disabled option into
		// $.Widget.prototype._setOptionDisabled so it's easy to proxy and can
		// be overridden by individual plugins
		this._setOption( "disabled", options.disabled );
		this._resetButton();
	},

	_determineButtonType: function() {

		if ( this.element.is(":checkbox") ) {
			this.type = "checkbox";
		} else if ( this.element.is(":radio") ) {
			this.type = "radio";
		} else if ( this.element.is("input") ) {
			this.type = "input";
		} else {
			this.type = "button";
		}

		if ( this.type === "checkbox" || this.type === "radio" ) {
			// we don't search against the document in case the element
			// is disconnected from the DOM
			var ancestor = this.element.parents().last(),
				labelSelector = "label[for=" + this.element.attr("id") + "]";
			this.buttonElement = ancestor.find( labelSelector );
			if ( !this.buttonElement.length ) {
				ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings();
				this.buttonElement = ancestor.filter( labelSelector );
				if ( !this.buttonElement.length ) {
					this.buttonElement = ancestor.find( labelSelector );
				}
			}
			this.element.addClass( "ui-helper-hidden-accessible" );

			var checked = this.element.is( ":checked" );
			if ( checked ) {
				this.buttonElement.addClass( "ui-state-active" );
			}
			this.buttonElement.attr( "aria-pressed", checked );
		} else {
			this.buttonElement = this.element;
		}
	},

	widget: function() {
		return this.buttonElement;
	},

	_destroy: function() {
		this.element
			.removeClass( "ui-helper-hidden-accessible" );
		this.buttonElement
			.removeClass( baseClasses + " " + stateClasses + " " + typeClasses )
			.removeAttr( "role" )
			.removeAttr( "aria-pressed" )
			.html( this.buttonElement.find(".ui-button-text").html() );

		if ( !this.hasTitle ) {
			this.buttonElement.removeAttr( "title" );
		}
	},

	_setOption: function( key, value ) {
		this._super( "_setOption", key, value );
		if ( key === "disabled" ) {
			if ( value ) {
				this.element.attr( "disabled", true );
			} else {
				this.element.removeAttr( "disabled" );
			}
			return;
		}
		this._resetButton();
	},

	refresh: function() {
		var isDisabled = this.element.is( ":disabled" );
		if ( isDisabled !== this.options.disabled ) {
			this._setOption( "disabled", isDisabled );
		}
		if ( this.type === "radio" ) {
			radioGroup( this.element[0] ).each(function() {
				if ( $( this ).is( ":checked" ) ) {
					$( this ).button( "widget" )
						.addClass( "ui-state-active" )
						.attr( "aria-pressed", true );
				} else {
					$( this ).button( "widget" )
						.removeClass( "ui-state-active" )
						.attr( "aria-pressed", false );
				}
			});
		} else if ( this.type === "checkbox" ) {
			if ( this.element.is( ":checked" ) ) {
				this.buttonElement
					.addClass( "ui-state-active" )
					.attr( "aria-pressed", true );
			} else {
				this.buttonElement
					.removeClass( "ui-state-active" )
					.attr( "aria-pressed", false );
			}
		}
	},

	_resetButton: function() {
		if ( this.type === "input" ) {
			if ( this.options.label ) {
				this.element.val( this.options.label );
			}
			return;
		}
		var buttonElement = this.buttonElement.removeClass( typeClasses ),
			buttonText = $( "" )
				.addClass( "ui-button-text" )
				.html( this.options.label )
				.appendTo( buttonElement.empty() )
				.text(),
			icons = this.options.icons,
			multipleIcons = icons.primary && icons.secondary,
			buttonClasses = [];

		if ( icons.primary || icons.secondary ) {
			if ( this.options.text ) {
				buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
			}

			if ( icons.primary ) {
				buttonElement.prepend( "" );
			}

			if ( icons.secondary ) {
				buttonElement.append( "" );
			}

			if ( !this.options.text ) {
				buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" );

				if ( !this.hasTitle ) {
					buttonElement.attr( "title", buttonText );
				}
			}
		} else {
			buttonClasses.push( "ui-button-text-only" );
		}
		buttonElement.addClass( buttonClasses.join( " " ) );
	}
});

$.ui.button.version = "@VERSION";

$.widget( "ui.buttonset", {
	options: {
		items: ":button, :submit, :reset, :checkbox, :radio, a, :data(button)"
	},

	_create: function() {
		this.element.addClass( "ui-buttonset" );
	},

	_init: function() {
		this.refresh();
	},

	_setOption: function( key, value ) {
		if ( key === "disabled" ) {
			this.buttons.button( "option", key, value );
		}

		this._super( "_setOption", key, value );
	},

	refresh: function() {
		var ltr = this.element.css( "direction" ) === "ltr";

		this.buttons = this.element.find( this.options.items )
			.filter( ":ui-button" )
				.button( "refresh" )
			.end()
			.not( ":ui-button" )
				.button()
			.end()
			.map(function() {
				return $( this ).button( "widget" )[ 0 ];
			})
				.removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
				.filter( ":first" )
					.addClass( ltr ? "ui-corner-left" : "ui-corner-right" )
				.end()
				.filter( ":last" )
					.addClass( ltr ? "ui-corner-right" : "ui-corner-left" )
				.end()
			.end();
	},

	_destroy: function() {
		this.element.removeClass( "ui-buttonset" );
		this.buttons
			.map(function() {
				return $( this ).button( "widget" )[ 0 ];
			})
				.removeClass( "ui-corner-left ui-corner-right" )
			.end()
			.button( "destroy" );
	}
});

$.ui.buttonset.version = "@VERSION";

}( jQuery ) );
<|endoftext|>


<commit_before>'use strict';
var moment    = require('moment'),
    debug     = require('debug')('sabesp:seed'),
    yesterday = moment().subtract(1, 'day'),
    request   = require('request');

debug('Job: Seed yesterday');
var url = 'http://localhost:8080/' + yesterday.format('YYYY-MM-DD');
doRequest(url);

function doRequest(url) {
  request(url, function (error, response, body) {
    debug('Job: Seed yesterday');
    if (error) {
      debug(error);
    }
  });
}
<commit_msg>Update cron job<commit_after>'use strict';
var moment    = require('moment'),
    debug     = require('debug')('sabesp:seed'),
    yesterday = moment().subtract(1, 'day'),
    request   = require('request');

debug('Job: Seed yesterday');
var url = 'https://sabesp-api.herokuapp.com/' + yesterday.format('YYYY-MM-DD');
doRequest(url);

function doRequest(url) {
  request(url, function (error, response, body) {
    debug('Job: Seed yesterday');
    if (error) {
      debug(error);
    }
  });
}
<|endoftext|>


<commit_before>angular.module('starter.services', [])

.value('muscleGroups', [
    {label : 'Chest'},
    {label : 'Shoulders'},
    {label : 'Back'},
    {label : 'Biceps'},
    {label : 'Triceps'},
    {label : 'Legs'},
    {label : 'Abs'}
])

.value('workouts', {
    'Chest' : [
        {label : 'Barbell Flat Bench Press'},
        {label : 'Barbell Incline Bench Press'},
        {label : 'Dumbbell Flat Bench Press'},
        {label : 'Dumbbell Incline Bench Press'},
        {label : 'Decline Dumbbell Bench Press'},
        {label : 'Flat Bench Dumbbell Fly'},
        {label : 'Incline Dumbbell Fly'},
        {label : 'Cable Crossovers'},
        {label : 'Dumbbell Pullover'},
        {label : 'Parallel Bar Dip'}
    ],
    'Shoulders' : [
        {label : 'Seated Dumbbell Press'},
        {label : 'Front Raises'},
        {label : 'Lateral Raises'},
        {label : 'Reverse Flyes'},
        {label : 'Single Arm Lateral Raise With Dumbbell'},
        {label : 'Upright Cable Rows'},
        {label : 'Upright Barbell Rows'},
        {label : 'Seated Military Press On Smith Machine'},
        {label : 'Military Shoulder Barbell Presses'},
        {label : 'Single Side Cable Lateral Raise'}
    ],
    'Back' : [
        {label : 'Pull-Ups'},
        {label : 'Wide-Grip Lat Pulldown'},
        {label : 'One-Arm Dumbbell Rows'},
        {label : 'Seated Cable Rows'},
        {label : 'Back Extensions'},
        {label : 'Straight-Arm Pulldowns'},
        {label : 'Smith Machine Shrugs'},
        {label : 'Standing Shrugs with Dumbbells'},
        {label : 'Bent-over Barbell Rows'},
        {label : 'Deadlifts'}
    ],
    'Biceps' : [
        {label : 'Seated Alternate Dumbbell Curl'},
        {label : 'Barbell Curls'},
        {label : 'Preacher Curls'},
        {label : 'Concentration Curls'},
        {label : 'Dumbbell Becips Curls'},
        {label : 'Cable Curls'},
        {label : 'Hammer Curls'},
        {label : 'Seated Inclined Biceps Curls'},
        {label : 'Lying Dumbbell Biceps Curls'},
        {label : 'Close Grip Chin Ups'}
    ],
    'Triceps' : [
        {label : 'Seated Triceps Presses'},
        {label : 'Lying Triceps Presses'},
        {label : 'Triceps Kickbacks'},
        {label : 'Triceps Pushdowns'},
        {label : 'Overhead Rope Extensions'},
        {label : 'Bench Dips'},
        {label : 'Dips on the Dip Machine'},
        {label : 'Close Grip Bench Press'},
        {label : 'One Arm Dumbbell Extension'},
        {label : 'Seated Triceps Dumbbell Extension'}
    ],
    'Legs' : [
        {label : 'Barbell Squats'},
        {label : 'Leg Presses'},
        {label : 'Leg Extensions'},
        {label : 'Dumbbell Lunges'},
        {label : 'Sissy Squat'},
        {label : 'Lying Leg Curls'},
        {label : 'Seated Calf Raises'},
        {label : 'Standing Heel Raises'},
        {label : 'Squats on Smith Machine'},
        {label : 'Stift-leg Deadlifts'},
        {label : 'Glute Machine'}
    ],
    'Abs' : [
        {label : 'Floor Crunches'},
        {label : 'Incline Knee Raises'},
        {label : 'Decline Crunches'},
        {label : 'Roman Chair Sit Ups'},
        {label : 'Hanging Knee Raises'},
        {label : 'Reverse Crunches'},
        {label : 'Cable Crunches'},
        {label : 'The Swiss ball crunch'},
        {label : 'Knee Raises'},
        {label : 'Lying Leg Raise'},
        {label : 'Vertical Leg Raises'}
    ]
})

;<commit_msg>added datamodel<commit_after>angular.module('starter.services', [])

.value('muscleGroups', [
    {label : 'Chest'},
    {label : 'Shoulders'},
    {label : 'Back'},
    {label : 'Biceps'},
    {label : 'Triceps'},
    {label : 'Legs'},
    {label : 'Abs'}
])

.value('workouts', {
    'Chest' : [
        {label : 'Barbell Flat Bench Press'},
        {label : 'Barbell Incline Bench Press'},
        {label : 'Dumbbell Flat Bench Press'},
        {label : 'Dumbbell Incline Bench Press'},
        {label : 'Decline Dumbbell Bench Press'},
        {label : 'Flat Bench Dumbbell Fly'},
        {label : 'Incline Dumbbell Fly'},
        {label : 'Cable Crossovers'},
        {label : 'Dumbbell Pullover'},
        {label : 'Parallel Bar Dip'}
    ],
    'Shoulders' : [
        {label : 'Seated Dumbbell Press'},
        {label : 'Front Raises'},
        {label : 'Lateral Raises'},
        {label : 'Reverse Flyes'},
        {label : 'Single Arm Lateral Raise With Dumbbell'},
        {label : 'Upright Cable Rows'},
        {label : 'Upright Barbell Rows'},
        {label : 'Seated Military Press On Smith Machine'},
        {label : 'Military Shoulder Barbell Presses'},
        {label : 'Single Side Cable Lateral Raise'}
    ],
    'Back' : [
        {label : 'Pull-Ups'},
        {label : 'Wide-Grip Lat Pulldown'},
        {label : 'One-Arm Dumbbell Rows'},
        {label : 'Seated Cable Rows'},
        {label : 'Back Extensions'},
        {label : 'Straight-Arm Pulldowns'},
        {label : 'Smith Machine Shrugs'},
        {label : 'Standing Shrugs with Dumbbells'},
        {label : 'Bent-over Barbell Rows'},
        {label : 'Deadlifts'}
    ],
    'Biceps' : [
        {label : 'Seated Alternate Dumbbell Curl'},
        {label : 'Barbell Curls'},
        {label : 'Preacher Curls'},
        {label : 'Concentration Curls'},
        {label : 'Dumbbell Becips Curls'},
        {label : 'Cable Curls'},
        {label : 'Hammer Curls'},
        {label : 'Seated Inclined Biceps Curls'},
        {label : 'Lying Dumbbell Biceps Curls'},
        {label : 'Close Grip Chin Ups'}
    ],
    'Triceps' : [
        {label : 'Seated Triceps Presses'},
        {label : 'Lying Triceps Presses'},
        {label : 'Triceps Kickbacks'},
        {label : 'Triceps Pushdowns'},
        {label : 'Overhead Rope Extensions'},
        {label : 'Bench Dips'},
        {label : 'Dips on the Dip Machine'},
        {label : 'Close Grip Bench Press'},
        {label : 'One Arm Dumbbell Extension'},
        {label : 'Seated Triceps Dumbbell Extension'}
    ],
    'Legs' : [
        {label : 'Barbell Squats'},
        {label : 'Leg Presses'},
        {label : 'Leg Extensions'},
        {label : 'Dumbbell Lunges'},
        {label : 'Sissy Squat'},
        {label : 'Lying Leg Curls'},
        {label : 'Seated Calf Raises'},
        {label : 'Standing Heel Raises'},
        {label : 'Squats on Smith Machine'},
        {label : 'Stift-leg Deadlifts'},
        {label : 'Glute Machine'}
    ],
    'Abs' : [
        {label : 'Floor Crunches'},
        {label : 'Incline Knee Raises'},
        {label : 'Decline Crunches'},
        {label : 'Roman Chair Sit Ups'},
        {label : 'Hanging Knee Raises'},
        {label : 'Reverse Crunches'},
        {label : 'Cable Crunches'},
        {label : 'The Swiss ball crunch'},
        {label : 'Knee Raises'},
        {label : 'Lying Leg Raise'},
        {label : 'Vertical Leg Raises'}
    ]
})

.factory('WorkoutSession', function() {
    return function() {
        var workouts = [];

        this.addWorkout = function (workout) {
            workouts[workouts.length] = workout;
        };

        this.getWorkouts = function () {
            return workouts;
        };
    };
})

.factory('Workout', function() {
    return function(name) {
        this.name = name;
        var workoutSets = [];

        this.addWorkoutSet = function (set) {
            workoutSets[workoutSets.length] = set;
        };

        this.getWorkoutSets = function () {
            return workoutSets;
        };
    };
})

.factory('WorkoutSet', function() {
    return function(weight, reps) {
        this.weight = weight;
        this.reps = reps;
        var workoutSets = [];

        this.addWorkoutSet = function (set) {
            workoutSets[workoutSets.length] = set;
        };

        this.getWorkoutSets = function () {
            return workoutSets;
        };
    };
})

.service('activeWorkoutSession', function() {
    var workoutSession = null;

    this.setWorkoutSession = function (ws) {
        workoutSession = ws;
    };

    this.getWorkoutSession = function () {
        return workoutSession;
    };
})

.service('activeWorkout', function() {
    var workout = null;

    this.setWorkout = function (w) {
        workout = w;
    };

    this.getWorkout = function () {
        return workout;
    };
})

;
<|endoftext|>


<commit_before>describe("some weird things", function() {
	it("should be obvious what the problem is", function() {
		expect(" bla").toEqual("   bla");
	});

	it("should say when fixtures don't exist", function(){
		expect(function(){
			loadFixtures("surely-this-doesnt-exist.html");
		}).toThrow();

	});
});
<commit_msg>documented problem with jasmine-jquery - you can't set more than one fixture at a time<commit_after>describe("some weird things", function() {
	it("should be obvious what the problem is", function() {
		expect(" bla").toEqual("   bla");
	});

	it("should say when fixtures don't exist", function(){
		expect(function(){
			loadFixtures("surely-this-doesnt-exist.html");
		}).toThrow();

	});

    it("should be able to set multiple html fixtures inline", function(){
        jasmine.getFixtures().set("

");
        jasmine.getFixtures().set("

");
        expect($("fixture_2")).toExist();
    });
});
<|endoftext|>


<commit_before>/*
 * grunt-gettext
 * https://github.com/arendjr/grunt-gettext
 *
 * Copyright (c) 2013 Arend van Beelen, Speakap BV
 * Licensed under the MIT license.
 */

"use strict";
var path = require('path');

module.exports = function(grunt) {

  var _ = grunt.util._;

  function escapeString(string) {

    return '"' + string.replace(/"/g, '\\"') + '"';
  }

  function mergeTranslationNamespaces(destination, source) {
    _.each(source, function(aNamespace, namespaceName) {
      destination[namespaceName] = _.extend(destination[namespaceName] || {}, aNamespace);
    });
    return destination;
  }

  /**
   * Get all messages of a content
   * @param  {String} content     content on which extract gettext calls
   * @param  {Regex} regex        first level regex
   * @param  {Regex} subRE        second level regex
   * @param  {Regex} quoteRegex   regex for quotes
   * @param  {String} quote       quote: " or '
   * @param  {Object} options     task options
   * @return {Object}             messages in a JS pot alike
   *                                       {
     *                                           singularKey: {
     *                                               singular: singularKey,
     *                                               plural: pluralKey,     // present only if plural
     *                                               message: ""
     *
     *                                           },
     *                                           ...
     *                                       }
   */
  function getMessages(content, regex, subRE, quoteRegex, quote, options) {
    var messages = {}, result, currentNamespace;
    var allNamespaces = {
      messages: {}
    };
    while ((result = regex.exec(content)) !== null) {
      var strings = result[1],
        singularKey = void 0;

      while ((result = subRE.exec(strings)) !== null) {
        var keyIndex = 1;
        currentNamespace = allNamespaces.messages;

        if (result.length === 3) {
          if (result[1] === undefined) {
            currentNamespace = allNamespaces.messages;
          } else {
            if (allNamespaces[result[1]] === undefined) {
              allNamespaces[result[1]] = {};
            }
            currentNamespace = allNamespaces[result[1]];
          }
          keyIndex = 2;
        }
        var string = options.processMessage(result[keyIndex].replace(quoteRegex, quote));

        // if singular form already defined add message as plural
        if (typeof singularKey !== 'undefined') {
          currentNamespace[singularKey].plural = string;
          // if not defined init message object
        } else {
          singularKey = string;
          currentNamespace[singularKey] = {
            singular: string,
            message: ""
          };
        }
      }
    }
    return allNamespaces;
  }

  /**
   * This method based on:
   *
   * gettext.js ( http://code.google.com/p/gettext-js/ )
   *
   * @author     Maxime Haineault, 2007 (max@centdessin.com)
   * @version    0.1.0
   * @licence    M.I.T
   */
  function parseIntoArray(str) {
    var messageRE = /(^#[\:\.,~|\s]\s?|^msgid\s"|^msgstr\s"|^"|"$)?/g;
    function clean(str) {
      return str.replace(messageRE, "").replace(/\\"/g, '"');
    }

    var curMsgid = 0;
    var curSection = "";
    var output = {
      msgid: [],
      msgstr: []
    };

    var lines = str.split("\n");
    lines.forEach(function(line) {
      if (line.substr(0, 6) === "msgid ") {
        // untranslated-string
        curSection = "msgid";
        output.msgid[curMsgid] = clean(line);
      } else if (line.substr(0, 6) === "msgstr") {
        // translated-string
        curSection = "msgstr";
        output.msgstr[curMsgid] = clean(line);
      } else if (line.substr(0, 1) === '"') {
        // continuation
        output[curSection][curMsgid] += clean(line);
      } else if (line.trim() === "") {
        curMsgid++;
      }
    });
    return output;
  }

  function updatePoFromPot(potFolderPath, namespace) {

    var potFilename = path.resolve(potFolderPath, namespace + ".pot");
    var poFilename = path.resolve(potFolderPath, namespace + "-en.po");

    var potContents = grunt.file.read(potFilename);
    var pot = parseIntoArray(potContents);

    var poContents = grunt.file.read(poFilename);
    var po = parseIntoArray(poContents);

    var newMsgids = [];
    // add new resources into po first
    for (var i = 0; i < pot.msgid.length; i++) {
      if (_.indexOf(po.msgid, pot.msgid[i]) === -1) {
        newMsgids.push(pot.msgid[i]);
      }
    }

    var sortedIndex = po.msgid.length;
    for (i = 0; i < newMsgids.length; i++) {
      sortedIndex = _.sortedIndex(po.msgid, newMsgids[i]);
      po.msgid.splice(sortedIndex, 0, newMsgids[i]);
      po.msgstr.splice(sortedIndex, 0, newMsgids[i]);
    }

    // remove resources from po next
    var removedMsgids = [];
    // exclude the first id and str to preserve the po header
    for (i = 1; i < po.msgid.length; i++) {
      if (_.indexOf(pot.msgid, po.msgid[i]) === -1) {
        removedMsgids.push(po.msgid[i]);
      }
    }

    for (i = 0; i < removedMsgids.length; i++) {
      var index = _.indexOf(po.msgid, removedMsgids[i]);
      po.msgid.splice(index, 1);
      po.msgstr.splice(index, 1);
    }

    // fail the build if the number of items in po and pot files are not the same
    if (pot.msgid.length !== (po.msgid.length - 1) || po.msgid.length !== po.msgstr.length) {
      grunt.fail.fatal("Convert from pot file to po file failed for this namespace: " + namespace + ". Please find UI team for help.");
    }

    var buffer = '';

    for (var j = 0; j < po.msgid.length - 1; j++) {
      buffer += 'msgid ' + escapeString(po.msgid[j]) + '\n' + 'msgstr ' + escapeString(po.msgstr[j]) + '\n\n';
    }
    buffer += 'msgid ' + escapeString(po.msgid[po.msgid.length - 1]) + '\n' + 'msgstr ' + escapeString(po.msgstr[po.msgid.length - 1]);

    grunt.file.write(poFilename, buffer);
  }

  var extractors = {
    angular: function(file, options) {
      var contents = grunt.file.read(file).replace("\n", " "),
        fn = _.flatten([ options.functionName ]),
        messages = {},
        namespaceSeparator = options.namespaceSeparator || '.';

      // Extract text strings with use the filter form of the ng-i18next library.
      var extractStrings = function(quote, fn) {
        var namespaceRegex = "(?:([\\d\\w]*)" + namespaceSeparator + ")?";
        var variablesRegex = "(?::\\{.*\\})?";
        var regex = new RegExp("\\{\\{\\s*((?:\\:{0,2}\\(?" +
                               quote + "(?:[^" + quote + "\\\\]|\\\\.)+" + quote +
                               "\\s*)+)[^}]*\\s*\\|\\s*" + fn + variablesRegex + "\\)?\\s*\\}\\}", "g");
        var subRE = new RegExp(quote + namespaceRegex + "((?:[^" + quote + "\\\\]|\\\\.)+)" + quote, "g");
        var quoteRegex = new RegExp("\\\\" + quote, "g");

        mergeTranslationNamespaces(messages, getMessages(contents, regex, subRE, quoteRegex, quote, options));
      };

      // Text strings may also use the ng-i18next directive with a set of arguments - particularly to do compiled HTML
      // (<b> tags for example) in the key text.
      var extractDirectiveStrings = function(quote, fn) {
        var allNamespaces = { messages : {}};
        var regex = new RegExp('ng-i18next=' + quote + '\\[html:' + fn + '\\](?:\\({(?!}\\)).+}\\))?([^' + quote + ']+)' + quote, "g");
        var result;
        while ((result = regex.exec(contents)) !== null) {
          var string = result[1];
          allNamespaces.messages[string] = {
            singular: string,
            message: ""
          };
        }

        mergeTranslationNamespaces(messages, allNamespaces);
      };

      _.each(fn, function(func) {
        extractStrings("'", func);
        extractStrings('"', func);
        extractDirectiveStrings("'", func);
        extractDirectiveStrings('"', func);
      });

      return messages;
    },

    handlebars: function(file, options) {
      var contents = grunt.file.read(file).replace("\n", " "),
        fn = _.flatten([ options.functionName ]),
        messages = {},
        namespaceSeparator = options.namespaceSeparator || '.';

      var extractStrings = function(quote, fn) {
        var namespaceRegex = "(?:([\\d\\w]*)" + namespaceSeparator + ")?";
        var regex = new RegExp("\\{\\{\\s*" + fn + "\\s+((?:" +
                               quote + "(?:[^" + quote + "\\\\]|\\\\.)+" + quote +
                               "\\s*)+)[^}]*\\s*\\}\\}", "g");
        var subRE = new RegExp(quote + namespaceRegex + "((?:[^" + quote + "\\\\]|\\\\.)+)" + quote, "g");
        var quoteRegex = new RegExp("\\\\" + quote, "g");

        mergeTranslationNamespaces(messages, getMessages(contents, regex, subRE, quoteRegex, quote, options));
      };

      _.each(fn, function(func) {
        extractStrings("'", func);
        extractStrings('"', func);
      });

      return messages;
    },

    json: function(file, options) {
      var contents = grunt.file.read(file),
        messages = {},
        namespaceSeparator = options.namespaceSeparator || '.';

      var extractStrings = function(quote) {
        var namespaceRegex = "(?:([\\d\\w]*)" + namespaceSeparator + ")?";
        var regex = /"((?:[\d\w]+:::)[^"]+)"/g;
        var subRE = new RegExp(namespaceRegex + "([^" + quote + "]+)", "g");
        var quoteRegex = new RegExp("\\\\" + quote, "g");

        mergeTranslationNamespaces(messages, getMessages(contents, regex, subRE, quoteRegex, quote, options));
      };

      extractStrings('"');

      return messages;
    },

    javascript: function(file, options) {
      var contents = grunt.file.read(file).replace("\n", " ")
        .replace(/"\s*\+\s*"/g, "")
        .replace(/'\s*\+\s*'/g, "");

      var fn = _.flatten([ options.functionName ]),
        messages = {},
        namespaceSeparator = options.namespaceSeparator || '.';

      var extractStrings = function(quote, fn) {
        var namespaceRegex = "(?:([\\d\\w]*)" + namespaceSeparator + ")?";
        var regex = new RegExp("(?:[^\\w]|^)" + fn + "\\s*\\(\\s*((?:" +
                               quote + "(?:[^" + quote + "\\\\]|\\\\.)+" + quote +
                               "\\s*[,)]\\s*)+)", "g");
        var subRE = new RegExp(quote + namespaceRegex + "((?:[^" + quote + "\\\\]|\\\\.)+)" + quote, "g");
        var quoteRegex = new RegExp("\\\\" + quote, "g");

        mergeTranslationNamespaces(messages, getMessages(contents, regex, subRE, quoteRegex, quote, options));
      };

      _.each(fn, function(func) {
        extractStrings("'", func);
        extractStrings('"', func);
        extractStrings("'", func + "_");
        extractStrings('"', func + "_");
      });

      return messages;
    }
  };

  function handleTranslations(options, files, potFolderPath) {

    var translations = {};

    files.forEach(function(f) {

      if (!extractors.hasOwnProperty(f.dest)) {
        console.log("No gettext extractor for type: " + f.dest);
        return;
      }

      var messages = {};
      f.src.forEach(function(file) {
        var newExtractedStrings = extractors[f.dest](file, options);
        _.each(newExtractedStrings, function(aNamespace, namespaceName) {
          messages[namespaceName] = _.extend(messages[namespaceName] || {}, aNamespace);
        });
      });

      mergeTranslationNamespaces(translations, messages);

      _.each(messages, function(aNamespace, namespaceName) {
        var count = Object.keys(aNamespace).length;
      })
    });

    _.each(translations, function(aNamespace, namespaceName) {
      var contents = "";

      var sortedKeys = Object.keys(aNamespace).sort();

      contents += _.map(sortedKeys, function (aKey) {
        var definition = aNamespace[aKey];
        var buffer = "msgid " + escapeString(definition.singular) + "\n";
        if (definition.plural) {
          buffer += "msgid_plural " + escapeString(definition.plural) + "\n";
          buffer += "msgstr[0] " + escapeString(definition.message) + "\n";
        } else {
          buffer += "msgstr " + escapeString(definition.message) + "\n";
        }
        return buffer;
      }).join("\n");

      var filename = path.resolve(options.potPath, namespaceName + ".pot");

      if (!grunt.option('fix')) {
        var existingResources = grunt.file.read(filename);
        if (contents !== existingResources) {
          grunt.fail.fatal("It appears that you have js resource changes not yet updated in po and pot files. Please run 'grunt xgettext --fix'");
        }
      } else {
        grunt.file.write(filename, contents, {});
        updatePoFromPot(potFolderPath, namespaceName);
      }
    });
  }

  grunt.registerMultiTask("xgettext", "Extracts translatable messages", function() {
    var options = this.options({
      functionName: "tr",
      processMessage: _.identity,
      potPath: '.'
    });
    handleTranslations(options, this.files, './project/translations');
  });

  grunt.registerMultiTask("xgettextKingsschool", "Extracts translatable messages for kingsschool project", function() {
    var options = this.options({
      functionName: "tr",
      processMessage: _.identity,
      potPath: '.'
    });
    handleTranslations(options, this.files, './project/kingsschool/translations');
  });
};
<commit_msg>make xgettext errors contain filenames<commit_after>/*
 * grunt-gettext
 * https://github.com/arendjr/grunt-gettext
 *
 * Copyright (c) 2013 Arend van Beelen, Speakap BV
 * Licensed under the MIT license.
 */

"use strict";
var path = require('path');

module.exports = function(grunt) {

  var _ = grunt.util._;

  function escapeString(string) {

    return '"' + string.replace(/"/g, '\\"') + '"';
  }

  function mergeTranslationNamespaces(destination, source) {
    _.each(source, function(aNamespace, namespaceName) {
      destination[namespaceName] = _.extend(destination[namespaceName] || {}, aNamespace);
    });
    return destination;
  }

  /**
   * Get all messages of a content
   * @param  {String} content           content on which extract gettext calls
   * @param  {Regex} regex              first level regex
   * @param  {Regex} subRE              second level regex
   * @param  {Regex} quoteRegex         regex for quotes
   * @param  {String} quote             quote: " or '
   * @param  {Object} options           task options
   * @param  {String} fileName          the source file of these messages
   * @param  {Object} messageToFilesMap  the map to keep track of what messages come from where
   * @return {Object}                   messages in a JS pot alike
   *                                       {
     *                                           singularKey: {
     *                                               singular: singularKey,
     *                                               plural: pluralKey,     // present only if plural
     *                                               message: ""
     *
     *                                           },
     *                                           ...
     *                                       }
   */
  function getMessages(content, regex, subRE, quoteRegex, quote, options, fileName, messageToFilesMap) {
    var messages = {}, result, currentNamespace;
    var allNamespaces = {
      messages: {}
    };
    while ((result = regex.exec(content)) !== null) {
      var strings = result[1],
        singularKey = void 0;

      while ((result = subRE.exec(strings)) !== null) {
        var keyIndex = 1;
        currentNamespace = allNamespaces.messages;
        var currentNamespaceString = 'messages';

        if (result.length === 3) {
          if (result[1] === undefined) {
            currentNamespace = allNamespaces.messages;
          } else {
            if (allNamespaces[result[1]] === undefined) {
              allNamespaces[result[1]] = {};
            }
            currentNamespace = allNamespaces[result[1]];
            currentNamespaceString = result[1];
          }
          keyIndex = 2;
        }
        var string = options.processMessage(result[keyIndex].replace(quoteRegex, quote));

        // if singular form already defined add message as plural
        if (typeof singularKey !== 'undefined') {
          currentNamespace[singularKey].plural = string;
          // if not defined init message object
        } else {
          singularKey = string;
          currentNamespace[singularKey] = {
            singular: string,
            message: ""
          };
        }
        if (!messageToFilesMap[currentNamespaceString]) {
          messageToFilesMap[currentNamespaceString] = {};
        }
        if (messageToFilesMap[currentNamespaceString][singularKey] &&
            !_.contains(messageToFilesMap[currentNamespaceString][singularKey], fileName)) {
          messageToFilesMap[currentNamespaceString][singularKey].push(fileName);
        } else if (!messageToFilesMap[currentNamespaceString][singularKey]) {
          messageToFilesMap[currentNamespaceString][singularKey] = [fileName];
        }
      }
    }
    return allNamespaces;
  }

  /**
   * This method based on:
   *
   * gettext.js ( http://code.google.com/p/gettext-js/ )
   *
   * @author     Maxime Haineault, 2007 (max@centdessin.com)
   * @version    0.1.0
   * @licence    M.I.T
   */
  function parseIntoArray(str) {
    var messageRE = /(^#[\:\.,~|\s]\s?|^msgid\s"|^msgstr\s"|^"|"$)?/g;
    function clean(str) {
      return str.replace(messageRE, "").replace(/\\"/g, '"');
    }

    var curMsgid = 0;
    var curSection = "";
    var output = {
      msgid: [],
      msgstr: []
    };

    var lines = str.split("\n");
    lines.forEach(function(line) {
      if (line.substr(0, 6) === "msgid ") {
        // untranslated-string
        curSection = "msgid";
        output.msgid[curMsgid] = clean(line);
      } else if (line.substr(0, 6) === "msgstr") {
        // translated-string
        curSection = "msgstr";
        output.msgstr[curMsgid] = clean(line);
      } else if (line.substr(0, 1) === '"') {
        // continuation
        output[curSection][curMsgid] += clean(line);
      } else if (line.trim() === "") {
        curMsgid++;
      }
    });
    return output;
  }

  function updatePoFromPot(potFolderPath, namespace) {

    var potFilename = path.resolve(potFolderPath, namespace + ".pot");
    var poFilename = path.resolve(potFolderPath, namespace + "-en.po");

    var potContents = grunt.file.read(potFilename);
    var pot = parseIntoArray(potContents);

    var poContents = grunt.file.read(poFilename);
    var po = parseIntoArray(poContents);

    var newMsgids = [];
    // add new resources into po first
    for (var i = 0; i < pot.msgid.length; i++) {
      if (_.indexOf(po.msgid, pot.msgid[i]) === -1) {
        newMsgids.push(pot.msgid[i]);
      }
    }

    var sortedIndex = po.msgid.length;
    for (i = 0; i < newMsgids.length; i++) {
      sortedIndex = _.sortedIndex(po.msgid, newMsgids[i]);
      po.msgid.splice(sortedIndex, 0, newMsgids[i]);
      po.msgstr.splice(sortedIndex, 0, newMsgids[i]);
    }

    // remove resources from po next
    var removedMsgids = [];
    // exclude the first id and str to preserve the po header
    for (i = 1; i < po.msgid.length; i++) {
      if (_.indexOf(pot.msgid, po.msgid[i]) === -1) {
        removedMsgids.push(po.msgid[i]);
      }
    }

    for (i = 0; i < removedMsgids.length; i++) {
      var index = _.indexOf(po.msgid, removedMsgids[i]);
      po.msgid.splice(index, 1);
      po.msgstr.splice(index, 1);
    }

    // fail the build if the number of items in po and pot files are not the same
    if (pot.msgid.length !== (po.msgid.length - 1) || po.msgid.length !== po.msgstr.length) {
      grunt.fail.fatal("Convert from pot file to po file failed for this namespace: " + namespace + ". Please find UI team for help.");
    }

    var buffer = '';

    for (var j = 0; j < po.msgid.length - 1; j++) {
      buffer += 'msgid ' + escapeString(po.msgid[j]) + '\n' + 'msgstr ' + escapeString(po.msgstr[j]) + '\n\n';
    }
    buffer += 'msgid ' + escapeString(po.msgid[po.msgid.length - 1]) + '\n' + 'msgstr ' + escapeString(po.msgstr[po.msgid.length - 1]);

    grunt.file.write(poFilename, buffer);
  }

  var extractors = {
    angular: function(file, options) {
      var contents = grunt.file.read(file).replace("\n", " "),
        fn = _.flatten([ options.functionName ]),
        messages = {},
        namespaceSeparator = options.namespaceSeparator || '.',
        messageToFilesMap = {};

      // Extract text strings with use the filter form of the ng-i18next library.
      var extractStrings = function(quote, fn) {
        var namespaceRegex = "(?:([\\d\\w]*)" + namespaceSeparator + ")?";
        var variablesRegex = "(?::\\{.*\\})?";
        var regex = new RegExp("\\{\\{\\s*((?:\\:{0,2}\\(?" +
                               quote + "(?:[^" + quote + "\\\\]|\\\\.)+" + quote +
                               "\\s*)+)[^}]*\\s*\\|\\s*" + fn + variablesRegex + "\\)?\\s*\\}\\}", "g");
        var subRE = new RegExp(quote + namespaceRegex + "((?:[^" + quote + "\\\\]|\\\\.)+)" + quote, "g");
        var quoteRegex = new RegExp("\\\\" + quote, "g");

        mergeTranslationNamespaces(messages, getMessages(contents, regex, subRE, quoteRegex, quote, options, file, messageToFilesMap));
      };

      // Text strings may also use the ng-i18next directive with a set of arguments - particularly to do compiled HTML
      // (<b> tags for example) in the key text.
      var extractDirectiveStrings = function(quote, fn) {
        var allNamespaces = { messages : {}};
        var regex = new RegExp('ng-i18next=' + quote + '\\[html:' + fn + '\\](?:\\({(?!}\\)).+}\\))?([^' + quote + ']+)' + quote, "g");
        var result;
        while ((result = regex.exec(contents)) !== null) {
          var string = result[1];
          allNamespaces.messages[string] = {
            singular: string,
            message: ""
          };
        }

        mergeTranslationNamespaces(messages, allNamespaces);
      };

      _.each(fn, function(func) {
        extractStrings("'", func);
        extractStrings('"', func);
        extractDirectiveStrings("'", func);
        extractDirectiveStrings('"', func);
      });

      return [messages, messageToFilesMap];
    },

    handlebars: function(file, options) {
      var contents = grunt.file.read(file).replace("\n", " "),
        fn = _.flatten([ options.functionName ]),
        messages = {},
        namespaceSeparator = options.namespaceSeparator || '.',
        messageToFilesMap = {};

      var extractStrings = function(quote, fn) {
        var namespaceRegex = "(?:([\\d\\w]*)" + namespaceSeparator + ")?";
        var regex = new RegExp("\\{\\{\\s*" + fn + "\\s+((?:" +
                               quote + "(?:[^" + quote + "\\\\]|\\\\.)+" + quote +
                               "\\s*)+)[^}]*\\s*\\}\\}", "g");
        var subRE = new RegExp(quote + namespaceRegex + "((?:[^" + quote + "\\\\]|\\\\.)+)" + quote, "g");
        var quoteRegex = new RegExp("\\\\" + quote, "g");

        mergeTranslationNamespaces(messages, getMessages(contents, regex, subRE, quoteRegex, quote, options, file, messageToFilesMap));
      };

      _.each(fn, function(func) {
        extractStrings("'", func);
        extractStrings('"', func);
      });

      return [messages, messageToFilesMap];
    },

    json: function(file, options) {
      var contents = grunt.file.read(file),
        messages = {},
        namespaceSeparator = options.namespaceSeparator || '.',
        messageToFilesMap = {};

      var extractStrings = function(quote) {
        var namespaceRegex = "(?:([\\d\\w]*)" + namespaceSeparator + ")?";
        var regex = /"((?:[\d\w]+:::)[^"]+)"/g;
        var subRE = new RegExp(namespaceRegex + "([^" + quote + "]+)", "g");
        var quoteRegex = new RegExp("\\\\" + quote, "g");

        mergeTranslationNamespaces(messages, getMessages(contents, regex, subRE, quoteRegex, quote, options, file, messageToFilesMap));
      };

      extractStrings('"');

      return [messages, messageToFilesMap];
    },

    javascript: function(file, options) {
      var contents = grunt.file.read(file).replace("\n", " ")
        .replace(/"\s*\+\s*"/g, "")
        .replace(/'\s*\+\s*'/g, "");

      var fn = _.flatten([ options.functionName ]),
        messages = {},
        namespaceSeparator = options.namespaceSeparator || '.',
        messageToFilesMap = {};

      var extractStrings = function(quote, fn) {
        var namespaceRegex = "(?:([\\d\\w]*)" + namespaceSeparator + ")?";
        var regex = new RegExp("(?:[^\\w]|^)" + fn + "\\s*\\(\\s*((?:" +
                               quote + "(?:[^" + quote + "\\\\]|\\\\.)+" + quote +
                               "\\s*[,)]\\s*)+)", "g");
        var subRE = new RegExp(quote + namespaceRegex + "((?:[^" + quote + "\\\\]|\\\\.)+)" + quote, "g");
        var quoteRegex = new RegExp("\\\\" + quote, "g");

        mergeTranslationNamespaces(messages, getMessages(contents, regex, subRE, quoteRegex, quote, options, file, messageToFilesMap));
      };

      _.each(fn, function(func) {
        extractStrings("'", func);
        extractStrings('"', func);
        extractStrings("'", func + "_");
        extractStrings('"', func + "_");
      });

      return [messages, messageToFilesMap];
    }
  };

  function combineMessageToFilesMaps(mapToModify, newMap) {
    _.each(newMap, function (files, message) {
      if (mapToModify[message]) {
        Array.prototype.push.apply(mapToModify[message], files);
      } else {
        mapToModify[message] = files;
      }
    });
  }

  function calculateDiffBetweenOldAndNewMessageIds(oldMessageIdsArray, messageToFilesMap) {
    var diff = '';
    _.each(messageToFilesMap, function (files, messageId) {
      if (!_.contains(oldMessageIdsArray, escapeString(messageId))) {
        diff += escapeString(messageId) + ' -- ' + files + '\n';
      }
    });
    return diff;
  }

  function extractMessageIds(string) {
    var messageIds = [];
    var match = true;
    var regex = new RegExp('msgid "((.|[\\s])+?([^\\\\]))"', 'gm');
    do {
      match = regex.exec(string);
      if (match) {
        messageIds.push(match[0].slice(6));
      }
    } while (match);
    return messageIds;
  }

  function handleTranslations(options, files, potFolderPath) {

    var translations = {};
    var messageToFilesMap = {};

    files.forEach(function(f) {

      if (!extractors.hasOwnProperty(f.dest)) {
        console.log("No gettext extractor for type: " + f.dest);
        return;
      }

      var messages = {};
      f.src.forEach(function(file) {
        var newExtracted = extractors[f.dest](file, options);
        var newExtractedStrings = newExtracted[0];
        var newMessageToFilesMap = newExtracted[1];
        _.each(newExtractedStrings, function(aNamespace, namespaceName) {
          if (!messageToFilesMap[namespaceName]) {
            messageToFilesMap[namespaceName] = {};
          }
          combineMessageToFilesMaps(messageToFilesMap[namespaceName], newMessageToFilesMap[namespaceName]);
          messages[namespaceName] = _.extend(messages[namespaceName] || {}, aNamespace);
        });
      });

      mergeTranslationNamespaces(translations, messages);
    });
    var errors = [];
    _.each(translations, function(aNamespace, namespaceName) {

      var filename = path.resolve(options.potPath, namespaceName + ".pot");

      if (!grunt.option('fix')) {
        var existingString = grunt.file.read(filename);
        var existingMessageIds = extractMessageIds(existingString);
        var diff = calculateDiffBetweenOldAndNewMessageIds(existingMessageIds, messageToFilesMap[namespaceName]);
        if (diff) {
          errors.push(diff);
        }
      } else {
        var contents = "";

        var sortedKeys = Object.keys(aNamespace).sort();

        contents += _.map(sortedKeys, function (aKey) {
          var definition = aNamespace[aKey];
          var buffer = "msgid " + escapeString(definition.singular) + "\n";
          if (definition.plural) {
            buffer += "msgid_plural " + escapeString(definition.plural) + "\n";
            buffer += "msgstr[0] " + escapeString(definition.message) + "\n";
          } else {
            buffer += "msgstr " + escapeString(definition.message) + "\n";
          }
          return buffer;
        }).join("\n");
        grunt.file.write(filename, contents, {});
        updatePoFromPot(potFolderPath, namespaceName);
      }
    });
    if (errors.length) {
      grunt.fail.fatal("It appears that you have js resource changes not yet updated in po and pot files. Please run 'grunt xgettext --fix'. The diff is:\n" + errors.join('\n'));
    }
  }

  grunt.registerMultiTask("xgettext", "Extracts translatable messages", function() {
    var options = this.options({
      functionName: "tr",
      processMessage: _.identity,
      potPath: '.'
    });
    handleTranslations(options, this.files, './project/translations');
  });

  grunt.registerMultiTask("xgettextKingsschool", "Extracts translatable messages for kingsschool project", function() {
    var options = this.options({
      functionName: "tr",
      processMessage: _.identity,
      potPath: '.'
    });
    handleTranslations(options, this.files, './project/kingsschool/translations');
  });
};
<|endoftext|>


<commit_before>var path = require('path'),
    spawn = require('child_process').spawn,
    exec = require('child_process').exec;

var sfs = require('scopedfs'),
    temp = require('temp'),
    rimraf = require('rimraf'),
    mkdirp = require('mkdirp'),
    glob = require('glob'),
    minilog = require('minilog');

//
// Set up a "build env"
//
module.exports = function buildEnv(options, cb) {

  var env = {};

  //
  // TODO: Jailing
  // (this is not safe at all, it's just for convenience right now)
  //

  //
  // Create the "build folder"
  //
  temp.mkdir(options.root, function (err, dirPath) {
    if (err) {
      return cb(err);
    }

    var env = {};

    env.log = minilog(dirPath);
    env.dirPath = dirPath;

    env.log.info('build-env: setting up build environment...');

    //
    // "scoped" fs operations
    //
    env.fs = sfs.scoped(dirPath);

    //
    // "spawn" is always in that cwd
    //
    env.spawn = function () {
      var argv = [].slice.call(arguments),
          _env = JSON.parse(JSON.stringify(process.env));

      _env.path = path.resolve(__dirname + '/node_modules/.bin');

      if (!argv[1]) {
        argv[1] = [];
      }

      if (!argv[2]) {
        argv[2] = {};
      }

      argv[2].cwd = argv[2].cwd
        ? path.join(dirPath, argv[2].cwd)
        : dirPath
      ;

      argv[2].env = _env;

      return spawn.apply(spawn, argv);
    };

    //
    // same with exec
    //
    env.exec = function () {
      var argv = [].slice.call(arguments),
          _env = JSON.parse(JSON.stringify(process.env));

      if (argv.length === 2) {
        argv = [ argv[0] ].concat({ cwd: dirPath }).concat(argv[1]);
      }
      else {
        argv[1].cwd = argv[1].cwd
          ? path.join(dirPath, argv[1].cwd)
          : dirPath
        ;
      }

      argv[1].env = _env;

      return exec.apply(exec, argv);
    };

    //
    // remove the folder
    //
    env.teardown = function (cb) {

      cb = cb || function () {};

      env.log.info('build-env: removing `' + dirPath + '`...');

      return rimraf(dirPath, function (err) {
        if (err) {
          env.log.warn('build-env: no dice while trying to remove `' + dirPath + '`:');
          env.log.warn(err.stack);
        }

        env.log.info('build-env: successfully removed `' + dirPath + '`.');
        cb(err);
      });
    }

    env.mkdirp = function (p, cb) {
      return mkdirp(path.join(dirPath, p), cb);
    };

    env.glob = function (g, opts, cb) {
      opts.cwd = path.join(dirPath, opts.cwd);
      return glob.call(glob, g, opts, cb);
    };

    env.log.info('build-env: set up build environment.');
    cb(null, env);
  });
};
<commit_msg>Fix build env spawn path<commit_after>var path = require('path'),
    spawn = require('child_process').spawn,
    exec = require('child_process').exec;

var sfs = require('scopedfs'),
    temp = require('temp'),
    rimraf = require('rimraf'),
    mkdirp = require('mkdirp'),
    glob = require('glob'),
    minilog = require('minilog');

//
// Set up a "build env"
//
module.exports = function buildEnv(options, cb) {

  var env = {};

  //
  // TODO: Jailing
  // (this is not safe at all, it's just for convenience right now)
  //

  //
  // Create the "build folder"
  //
  temp.mkdir(options.root, function (err, dirPath) {
    if (err) {
      return cb(err);
    }

    var env = {};

    env.log = minilog(dirPath);
    env.dirPath = dirPath;

    env.log.info('build-env: setting up build environment...');

    //
    // "scoped" fs operations
    //
    env.fs = sfs.scoped(dirPath);

    //
    // "spawn" is always in that cwd
    //
    env.spawn = function () {
      var argv = [].slice.call(arguments),
          _env = JSON.parse(JSON.stringify(process.env));

      _env.path = path.resolve(__dirname + '../node_modules/.bin');

      if (!argv[1]) {
        argv[1] = [];
      }

      if (!argv[2]) {
        argv[2] = {};
      }

      argv[2].cwd = argv[2].cwd
        ? path.join(dirPath, argv[2].cwd)
        : dirPath
      ;

      argv[2].env = _env;

      return spawn.apply(spawn, argv);
    };

    //
    // same with exec
    //
    env.exec = function () {
      var argv = [].slice.call(arguments),
          _env = JSON.parse(JSON.stringify(process.env));

      if (argv.length === 2) {
        argv = [ argv[0] ].concat({ cwd: dirPath }).concat(argv[1]);
      }
      else {
        argv[1].cwd = argv[1].cwd
          ? path.join(dirPath, argv[1].cwd)
          : dirPath
        ;
      }

      argv[1].env = _env;

      return exec.apply(exec, argv);
    };

    //
    // remove the folder
    //
    env.teardown = function (cb) {

      cb = cb || function () {};

      env.log.info('build-env: removing `' + dirPath + '`...');

      return rimraf(dirPath, function (err) {
        if (err) {
          env.log.warn('build-env: no dice while trying to remove `' + dirPath + '`:');
          env.log.warn(err.stack);
        }

        env.log.info('build-env: successfully removed `' + dirPath + '`.');
        cb(err);
      });
    }

    env.mkdirp = function (p, cb) {
      return mkdirp(path.join(dirPath, p), cb);
    };

    env.glob = function (g, opts, cb) {
      opts.cwd = path.join(dirPath, opts.cwd);
      return glob.call(glob, g, opts, cb);
    };

    env.log.info('build-env: set up build environment.');
    cb(null, env);
  });
};
<|endoftext|>


<commit_before>$(function() {
    var articles = $("article");
    articles.append("Show Hide");
});
<commit_msg>showHide in progress<commit_after>$(function() {
    var articles = $("article");
    var toggleVisibility = $("Hide");

    // add to the

    articles.append(toggleVisibility);

    toggleVisibility.click(function() {
        alert("clicked");
    });

});
<|endoftext|>


<commit_before>angular.module('ptApp.services', ['ptConfig'])

.factory('Main', function($rootScope, $http, PT_CONFIG){
  localStorage['user'] = localStorage['user'] || '{}';

  var service = {
    user: JSON.parse(localStorage['user']),

    interceptResponse: function(data, status){
      if(status == 404){
        $rootScope.$broadcast('connectionError');
      }
    },

    setInstallationId: function(aggregatorUrl){
      $http.get(aggregatorUrl + 'getId')
      .success(function(response){
        localStorage['installationId'] = response['payload']['installation_id'];
      });
    },

    updateUserInfo: function(){
      localStorage['user'] = JSON.stringify(this.user);
    },

    confirmInternetConnection: function(successCallback){
      if(window.Connection && navigator.connection.type !== Connection.NONE) {
        successCallback();
      } else {
        $rootScope.$broadcast('connectionError');
      }
    }
  }

  if(!localStorage['installationId']){
    service.setInstallationId(PT_CONFIG.aggregatorUrl);
  }

  return service;
})

.factory('Survey', function($rootScope, $http, $ionicPopup, $state, $filter, $location, PT_CONFIG, Main){
  localStorage['surveys'] = localStorage['surveys'] || '{}';
  localStorage['unsynced'] = localStorage['unsynced'] || '[]';
  localStorage['unsyncedImages'] = localStorage['unsyncedImages'] || '[]';
  localStorage['synced'] = localStorage['synced'] || '[]';

  var service = {
    surveys: JSON.parse(localStorage['surveys']),
    unsynced: JSON.parse(localStorage['unsynced']),
    synced: JSON.parse(localStorage['synced']),
    unsyncedImages: JSON.parse(localStorage['unsyncedImages']),
    currentResponse: {},
    currentSyncItemTotal: 0,
    currentSyncPercentage: 0,
    syncing: false,

    isSyncing: function(){
      return this.syncing;
    },

    hasUnsyncedItems: function(){
      return this.unsynced.length + this.unsyncedImages.length > 0;
    },

    getCampaignId: function(surveyId){
      var survey = this.surveys[surveyId];
      return survey.campaign_id;
    },

    fetchSurvey: function(surveyCode, successCallback, errorCallback){
      var self = this;
      $http.get(PT_CONFIG.aggregatorUrl + 'surveys/' + surveyCode)
        .success(function(data){
          if(data.status == 'success'){
            successCallback(data);
          } else {
            errorCallback(data.error_code.toString());
          }
        })

        .error(function(data, status){
          Main.interceptResponse(data, status);
        });
    },

    queueNewResponse: function(surveyId, locationConsent){
      var self = this;
      self.currentResponse = {
        installation_id: localStorage['installationId'],
        survey_id: surveyId,
        status: self.surveys[surveyId].status,
        timestamp: Date.now(),
        locationstamp: {},
        inputs: JSON.parse(JSON.stringify(self.surveys[surveyId].inputs)),
        activeIndex: 0
      };

      if(locationConsent){
        navigator.geolocation.getCurrentPosition(function(position){
          self.currentResponse.locationstamp.lon = position.coords.longitude;
          self.currentResponse.locationstamp.lat = position.coords.latitude;
        });
      }
      console.log(self.currentResponse);
    },

    addResponseToUnsynced: function(response){
      var index = this.unsynced.indexOf(response);
      if(index == -1){
        this.unsynced.push(response);
        localStorage['unsynced'] = JSON.stringify(this.unsynced);
      }
    },

    removeResponseFromUnsynced: function(response){
      var index = this.unsynced.indexOf(response);
      if(index > -1){
        this.unsynced.splice(index, 1);
        localStorage['unsynced'] = JSON.stringify(this.unsynced);
      }
    },

    refreshSyncItemCount: function(){
      this.currentSyncItemTotal = this.unsyncedImages.length + this.unsynced.length;
    },

    getSyncMessage: function(){
      var itemsToGo = this.unsyncedImages.length + this.unsynced.length;
      var message = (this.currentSyncItemTotal-itemsToGo+1) + '/' + this.currentSyncItemTotal;
      if(this.currentSyncPercentage > 0 && this.currentSyncPercentage < 100){
        message += " " + this.currentSyncPercentage + "%";
      }
      return message;
    },

    addImageToUnsynced: function(response){
      var self = this;
      // Search for images in the survey response
      response.inputs.forEach(function(input){
        if(input.input_type == 'image' && input.answer){
          self.unsyncedImages.push({id: response.id, input_id: input.id, fileLocation: input.answer});
        }
      });
      self.syncImages();
    },

    removeImageFromUnsynced: function(image){
      var self = this;
      var index = this.unsyncedImages.indexOf(image);
      if(index > -1){
        this.unsyncedImages.splice(index, 1);
        localStorage['unsyncedImages'] = JSON.stringify(this.unsyncedImages);
      }
    },

    addResponseToSynced: function(response){
      var index = this.unsynced.indexOf(response);
      this.synced.push(response);
      localStorage['synced'] = JSON.stringify(this.synced)
      if(index > -1){
        this.unsynced.splice(index, 1);
        localStorage['unsynced'] = JSON.stringify(this.unsynced);
      }
    },

    formatResponse: function(response){
      var formattedResponse = {
        installation_id: localStorage.installationId,
        survey_id: response.survey_id,
        status: response.status,
        timestamp: response.timestamp,
        locationstamp: response.locationstamp,
        answers: []
      };

      response.inputs.forEach(function(input){
        var answer = { id: input.id, value: input.answer, input_type: input.input_type };

        if(input.input_type == 'select'){
          answer.value = input.answer.map(function(value, index){
            if(value){
              return input.options[index];
            }
          }).filter(function(n){ return n!= undefined; });
        }

        formattedResponse.answers.push(answer);
      })

      return formattedResponse;
    },

    syncResponse: function(response){
      var self = this;
      var formattedResponse = self.formatResponse(response);
      self.addResponseToUnsynced(response);
      self.syncing =  true;
      $rootScope.$broadcast('updateStatus');
      $http.post(
        PT_CONFIG.aggregatorUrl + 'responses',
        { response: JSON.stringify(formattedResponse) }
      )
        .success(function(data){
          if(data['status'] == 'success'){
            response.id = data.payload.id;
            self.removeResponseFromUnsynced(response);
            self.addResponseToSynced(formattedResponse);
            self.addImageToUnsynced(response);
          }
          if(self.unsynced.length + self.unsyncedImages.length == 0) {
            self.syncing = false;
            $rootScope.$broadcast('updateStatus');
            $rootScope.$broadcast('viewMap', response.survey_id);
          }
          self.refreshSyncItemCount();
          self.syncResponses();
        })

        .error(function(data, status){
          Main.interceptResponse(data, status);
          self.syncing = false;
          $rootScope.$broadcast('updateStatus');
        });
    },

    syncImage: function(image){
      var self = this;
      self.syncing = true;
      $rootScope.$broadcast('updateStatus');
      // TODO: need to find if the image really exists
      // upload the image with cordova file-transfer
      var options = new FileUploadOptions();
      options.fileKey = "file";
      options.fileName = image.fileLocation.substr(image.fileLocation.lastIndexOf('/') + 1);
      options.mimeType = "image/jpeg";
      options.params = image;
      options.headers = { 'Authorization': PT_CONFIG.accessKey };
      var fileTransfer = new FileTransfer();
      fileTransfer.onprogress = function(result){
           var percent =  result.loaded / result.total * 100;
           percent = Math.round(percent);
           self.currentSyncPercentage = percent;
           $rootScope.$broadcast('updateStatus');
      };
      fileTransfer.upload(image.fileLocation, encodeURI(PT_CONFIG.aggregatorUrl + 'upload_image'),

        function(result){   // upload succeed
          if(typeof result.response != 'undefined'){
            self.removeImageFromUnsynced(image);
          }
          self.syncing = false;
          $rootScope.$broadcast('updateStatus');
          self.syncImages();
          self.currentSyncPercentage = 0;
        },

        function(error){   // upload failed
          // TODO: notify user of image upload failure
          self.currentSyncPercentage = 0;
          self.syncing =false;
          $rootScope.$broadcast('updateStatus');
        }, options);
    },

    syncResponses: function(){
      var self = this;
      if(self.unsynced.length>0){
        self.syncResponse(self.unsynced[0]);
      }
    },

    syncImages: function(){
      var self = this;
      if(self.unsyncedImages.length>0){
        self.syncImage(self.unsyncedImages[0]);
      }
    },

    cancelResponse: function() {
      var confirmPopup = $ionicPopup.confirm({
        template: $filter('translate')('DELETE_RESPONSE'),
        buttons: [
          {
            text: $filter('translate')('CANCEL')
          },
          {
            text: $filter('translate')('DELETE'),
            type: 'button-pink',
            onTap: function(){ return true; }
          }
        ]
      });
      confirmPopup.then(function(res) {
        if(res) {
          self.currentResponse = {};
          $state.go('home');
        }
      });
    }
  };

  return service;
})
<commit_msg>Set app language based on navigator<commit_after>angular.module('ptApp.services', ['ptConfig', 'pascalprecht.translate'])

.factory('Main', function($rootScope, $http, PT_CONFIG, $translate){
  localStorage['user'] = localStorage['user'] || '{}';

  var service = {
    user: JSON.parse(localStorage['user']),

    interceptResponse: function(data, status){
      if(status == 404){
        $rootScope.$broadcast('connectionError');
      }
    },

    setInstallationId: function(aggregatorUrl){
      $http.get(aggregatorUrl + 'getId')
      .success(function(response){
        localStorage['installationId'] = response['payload']['installation_id'];
      });
    },

    updateUserInfo: function(){
      localStorage['user'] = JSON.stringify(this.user);
    },

    confirmInternetConnection: function(successCallback){
      if(window.Connection && navigator.connection.type !== Connection.NONE) {
        successCallback();
      } else {
        $rootScope.$broadcast('connectionError');
      }
    }
  }

  $translate.use(navigator.language.split("-")[0] == "en" ? "en" : "pt-BR");

  if(!localStorage['installationId']){
    service.setInstallationId(PT_CONFIG.aggregatorUrl);
  }

  return service;
})

.factory('Survey', function($rootScope, $http, $ionicPopup, $state, $filter, $location, PT_CONFIG, Main){
  localStorage['surveys'] = localStorage['surveys'] || '{}';
  localStorage['unsynced'] = localStorage['unsynced'] || '[]';
  localStorage['unsyncedImages'] = localStorage['unsyncedImages'] || '[]';
  localStorage['synced'] = localStorage['synced'] || '[]';

  var service = {
    surveys: JSON.parse(localStorage['surveys']),
    unsynced: JSON.parse(localStorage['unsynced']),
    synced: JSON.parse(localStorage['synced']),
    unsyncedImages: JSON.parse(localStorage['unsyncedImages']),
    currentResponse: {},
    currentSyncItemTotal: 0,
    currentSyncPercentage: 0,
    syncing: false,

    isSyncing: function(){
      return this.syncing;
    },

    hasUnsyncedItems: function(){
      return this.unsynced.length + this.unsyncedImages.length > 0;
    },

    getCampaignId: function(surveyId){
      var survey = this.surveys[surveyId];
      return survey.campaign_id;
    },

    fetchSurvey: function(surveyCode, successCallback, errorCallback){
      var self = this;
      $http.get(PT_CONFIG.aggregatorUrl + 'surveys/' + surveyCode)
        .success(function(data){
          if(data.status == 'success'){
            successCallback(data);
          } else {
            errorCallback(data.error_code.toString());
          }
        })

        .error(function(data, status){
          Main.interceptResponse(data, status);
        });
    },

    queueNewResponse: function(surveyId, locationConsent){
      var self = this;
      self.currentResponse = {
        installation_id: localStorage['installationId'],
        survey_id: surveyId,
        status: self.surveys[surveyId].status,
        timestamp: Date.now(),
        locationstamp: {},
        inputs: JSON.parse(JSON.stringify(self.surveys[surveyId].inputs)),
        activeIndex: 0
      };

      if(locationConsent){
        navigator.geolocation.getCurrentPosition(function(position){
          self.currentResponse.locationstamp.lon = position.coords.longitude;
          self.currentResponse.locationstamp.lat = position.coords.latitude;
        });
      }
      console.log(self.currentResponse);
    },

    addResponseToUnsynced: function(response){
      var index = this.unsynced.indexOf(response);
      if(index == -1){
        this.unsynced.push(response);
        localStorage['unsynced'] = JSON.stringify(this.unsynced);
      }
    },

    removeResponseFromUnsynced: function(response){
      var index = this.unsynced.indexOf(response);
      if(index > -1){
        this.unsynced.splice(index, 1);
        localStorage['unsynced'] = JSON.stringify(this.unsynced);
      }
    },

    refreshSyncItemCount: function(){
      this.currentSyncItemTotal = this.unsyncedImages.length + this.unsynced.length;
    },

    getSyncMessage: function(){
      var itemsToGo = this.unsyncedImages.length + this.unsynced.length;
      var message = (this.currentSyncItemTotal-itemsToGo+1) + '/' + this.currentSyncItemTotal;
      if(this.currentSyncPercentage > 0 && this.currentSyncPercentage < 100){
        message += " " + this.currentSyncPercentage + "%";
      }
      return message;
    },

    addImageToUnsynced: function(response){
      var self = this;
      // Search for images in the survey response
      response.inputs.forEach(function(input){
        if(input.input_type == 'image' && input.answer){
          self.unsyncedImages.push({id: response.id, input_id: input.id, fileLocation: input.answer});
        }
      });
      self.syncImages();
    },

    removeImageFromUnsynced: function(image){
      var self = this;
      var index = this.unsyncedImages.indexOf(image);
      if(index > -1){
        this.unsyncedImages.splice(index, 1);
        localStorage['unsyncedImages'] = JSON.stringify(this.unsyncedImages);
      }
    },

    addResponseToSynced: function(response){
      var index = this.unsynced.indexOf(response);
      this.synced.push(response);
      localStorage['synced'] = JSON.stringify(this.synced)
      if(index > -1){
        this.unsynced.splice(index, 1);
        localStorage['unsynced'] = JSON.stringify(this.unsynced);
      }
    },

    formatResponse: function(response){
      var formattedResponse = {
        installation_id: localStorage.installationId,
        survey_id: response.survey_id,
        status: response.status,
        timestamp: response.timestamp,
        locationstamp: response.locationstamp,
        answers: []
      };

      response.inputs.forEach(function(input){
        var answer = { id: input.id, value: input.answer, input_type: input.input_type };

        if(input.input_type == 'select'){
          answer.value = input.answer.map(function(value, index){
            if(value){
              return input.options[index];
            }
          }).filter(function(n){ return n!= undefined; });
        }

        formattedResponse.answers.push(answer);
      })

      return formattedResponse;
    },

    syncResponse: function(response){
      var self = this;
      var formattedResponse = self.formatResponse(response);
      self.addResponseToUnsynced(response);
      self.syncing =  true;
      $rootScope.$broadcast('updateStatus');
      $http.post(
        PT_CONFIG.aggregatorUrl + 'responses',
        { response: JSON.stringify(formattedResponse) }
      )
        .success(function(data){
          if(data['status'] == 'success'){
            response.id = data.payload.id;
            self.removeResponseFromUnsynced(response);
            self.addResponseToSynced(formattedResponse);
            self.addImageToUnsynced(response);
          }
          if(self.unsynced.length + self.unsyncedImages.length == 0) {
            self.syncing = false;
            $rootScope.$broadcast('updateStatus');
            $rootScope.$broadcast('viewMap', response.survey_id);
          }
          self.refreshSyncItemCount();
          self.syncResponses();
        })

        .error(function(data, status){
          Main.interceptResponse(data, status);
          self.syncing = false;
          $rootScope.$broadcast('updateStatus');
        });
    },

    syncImage: function(image){
      var self = this;
      self.syncing = true;
      $rootScope.$broadcast('updateStatus');
      // TODO: need to find if the image really exists
      // upload the image with cordova file-transfer
      var options = new FileUploadOptions();
      options.fileKey = "file";
      options.fileName = image.fileLocation.substr(image.fileLocation.lastIndexOf('/') + 1);
      options.mimeType = "image/jpeg";
      options.params = image;
      options.headers = { 'Authorization': PT_CONFIG.accessKey };
      var fileTransfer = new FileTransfer();
      fileTransfer.onprogress = function(result){
           var percent =  result.loaded / result.total * 100;
           percent = Math.round(percent);
           self.currentSyncPercentage = percent;
           $rootScope.$broadcast('updateStatus');
      };
      fileTransfer.upload(image.fileLocation, encodeURI(PT_CONFIG.aggregatorUrl + 'upload_image'),

        function(result){   // upload succeed
          if(typeof result.response != 'undefined'){
            self.removeImageFromUnsynced(image);
          }
          self.syncing = false;
          $rootScope.$broadcast('updateStatus');
          self.syncImages();
          self.currentSyncPercentage = 0;
        },

        function(error){   // upload failed
          // TODO: notify user of image upload failure
          self.currentSyncPercentage = 0;
          self.syncing =false;
          $rootScope.$broadcast('updateStatus');
        }, options);
    },

    syncResponses: function(){
      var self = this;
      if(self.unsynced.length>0){
        self.syncResponse(self.unsynced[0]);
      }
    },

    syncImages: function(){
      var self = this;
      if(self.unsyncedImages.length>0){
        self.syncImage(self.unsyncedImages[0]);
      }
    },

    cancelResponse: function() {
      var confirmPopup = $ionicPopup.confirm({
        template: $filter('translate')('DELETE_RESPONSE'),
        buttons: [
          {
            text: $filter('translate')('CANCEL')
          },
          {
            text: $filter('translate')('DELETE'),
            type: 'button-pink',
            onTap: function(){ return true; }
          }
        ]
      });
      confirmPopup.then(function(res) {
        if(res) {
          self.currentResponse = {};
          $state.go('home');
        }
      });
    }
  };

  return service;
})
<|endoftext|>


<commit_before>'use babel';

import TeamObject from '../lib/TeamObject'
import UserObject from '../lib/UserObject'

// Action
import {
  // Team
  addNewTeam,
  updateTeam,
  setCurrentTeam,
  // User
  setAllUsers,
  addChannels,
  addNewUser,
  updateUser,
  // Channel
  setAllChannels,
  setActiveChannel,
  addNewChannel,
  updateChannel,
  // Messages
  sendMessage,
} from '../lib/actions'

// Reducers
import {
  teams,
  currentTeam,
  users,
} from '../lib/reducers'

describe('Reducers', () => {
  const [t1, t2] = [
    new TeamObject({
      id: '1111',
      name: 'first',
    }),
    new TeamObject({
      id: '222',
      name: 'second',
    }),
  ]

  const [u1, u2] = [
    new UserObject({
      id: 'u1id',
      teamId: 111,
      username: 'firstUser',
    }),
    new UserObject({
      id: 'u2id',
      teamId: 111,
      username: 'secondUser',
    }),
  ]

  describe('teams', () => {
    it('returns empty array by default', () => {
      expect(teams(undefined, { type: 'wrongType' })).toEqual([])
    })

    it('add new team to state', () => {
      expect(teams([], addNewTeam(t1))).toEqual([t1])
      expect(teams([t1], addNewTeam(t2))).toEqual([t1, t2])
    })

    it('update team', () => {
      const changedTeam = new TeamObject({
        id: t1.id,
        name: 'chnaged',
      })
      expect(teams([t1], updateTeam(changedTeam))).toEqual([changedTeam])
    })
  })

  describe('currentTeam', () => {
    it('is null by default (not set)', () => {
      expect(currentTeam(undefined, { type: 'wrongType' })).toEqual(null)
    })

    it('set current tam if no team before and you add new', () => {
      expect(currentTeam(undefined, addNewTeam(t1))).toEqual(t1)
    })

    it('will not change existing team for addNewTeam action', () => {
      expect(currentTeam(t1, addNewTeam(t2))).toEqual(t1)
    })

    it('will not change currentTeam if an other team was updated', () => {
      expect(currentTeam(t1, updateTeam(t2))).toEqual(t1)
    })

    it('will update currentTeam if update team action fiered for currentTeam', () => {
      const changedTeam = new TeamObject({
        id: t1.id,
        name: 'chnaged',
      })
      expect(currentTeam(t1, updateTeam(changedTeam))).toEqual(changedTeam)
    })

    it('will set currentTeam', () => {
      expect(currentTeam(t1, setCurrentTeam(t2))).toEqual(t2)
      expect(currentTeam(t1, setCurrentTeam(t1))).toEqual(t1)
      expect(currentTeam(null, setCurrentTeam(t1))).toEqual(t1)
      expect(currentTeam(t1, setCurrentTeam(null))).toEqual(t1)
    });
  })

  describe('users', () => {
    it('sets all users', () => {
      expect(users({
        xxx: {
          u1id: u1,
          u2id: u2,
        },
      }, setAllUsers({
        teamId: 'xxx',
        users: [u1],
      }))).toEqual({
        xxx: {
          u1id: u1,
        },
      })

      expect(users({
        xxx: {
          u1id: u1,
          u2id: u2,
        },
      }, setAllUsers({
        teamId: 'xxx',
        users: [],
      }))).toEqual({
        xxx: {},
      })

      expect(users({}, setAllUsers({
        teamId: 'xxx',
        users: [u2],
      }))).toEqual({
        xxx: {
          u2id: u2,
        },
      })

      expect(users(undefined, setAllUsers({
        teamId: 'xxx',
        users: [u1, u2],
      }))).toEqual({
        xxx: {
          u1id: u1,
          u2id: u2,
        },
      })
    })

    it('Will not add new user if user already exists', () => {
      expect(users({
        [u1.teamId]: {
          u1id: u1,
        },
      }, addNewUser(u1))).toEqual({
        [u1.teamId]: {
          u1id: u1,
        },
      })
    })

    it('Will add new user', () => {
      expect(users(undefined, addNewUser(u1))).toEqual({
        [u1.teamId]: {
          u1id: u1,
        },
      })

      expect(users({}, addNewUser(u1))).toEqual({
        [u1.teamId]: {
          u1id: u1,
        },
      })

      expect(users({
        [u1.teamId]: {
          u1id: u1,
        },
      }, addNewUser(u2))).toEqual({
        [u1.teamId]: {
          u1id: u1,
          u2id: u2,
        },
      })
    })

    it('add new user when addNewUser action fiered', () => {
      expect(users({
        xxx: {
          u1id: u1,
          u2id: u2,
        },
      }, setAllUsers({
        teamId: 'xxx',
        users: [],
      }))).toEqual({
        xxx: {},
      })

      expect(users({}, setAllUsers({
        teamId: 'xxx',
        users: [u2],
      }))).toEqual({
        xxx: {
          u2id: u2,
        },
      })

      expect(users(undefined, setAllUsers({
        teamId: 'xxx',
        users: [u1, u2],
      }))).toEqual({
        xxx: {
          u1id: u1,
          u2id: u2,
        },
      })
    })
  })
})
<commit_msg>add test for channels<commit_after>'use babel';

import TeamObject from '../lib/TeamObject'
import UserObject from '../lib/UserObject'
import ChannelObject from '../lib/ChannelObject'

// Action
import {
  // Team
  addNewTeam,
  updateTeam,
  setCurrentTeam,
  // User
  setAllUsers,
  addChannels,
  addNewUser,
  updateUser,
  // Channel
  setAllChannels,
  setActiveChannel,
  addNewChannel,
  updateChannel,
  // Messages
  sendMessage,
} from '../lib/actions'

// Reducers
import {
  teams,
  currentTeam,
  users,
  channels,
} from '../lib/reducers'

describe('Reducers', () => {
  const [t1, t2] = [
    new TeamObject({
      id: '1111',
      name: 'first',
    }),
    new TeamObject({
      id: '222',
      name: 'second',
    }),
  ]

  const [u1, u2] = [
    new UserObject({
      id: 'u1id',
      teamId: 111,
      username: 'firstUser',
    }),
    new UserObject({
      id: 'u2id',
      teamId: 111,
      username: 'secondUser',
    }),
  ]

  const [ch1, ch2] = [
    new ChannelObject({
      id: 'ch1id',
      teamId: 'xxx',
      name: 'First Channel',
    }),

    new ChannelObject({
      id: 'ch2id',
      teamId: 'xxx',
      name: 'Second Channel',
    }),
  ]

  describe('teams', () => {
    it('returns empty array by default', () => {
      expect(teams(undefined, { type: 'wrongType' })).toEqual([])
    })

    it('add new team to state', () => {
      expect(teams([], addNewTeam(t1))).toEqual([t1])
      expect(teams([t1], addNewTeam(t2))).toEqual([t1, t2])
    })

    it('update team', () => {
      const changedTeam = new TeamObject({
        id: t1.id,
        name: 'chnaged',
      })
      expect(teams([t1], updateTeam(changedTeam))).toEqual([changedTeam])
    })
  })

  describe('currentTeam', () => {
    it('is null by default (not set)', () => {
      expect(currentTeam(undefined, { type: 'wrongType' })).toEqual(null)
    })

    it('set current tam if no team before and you add new', () => {
      expect(currentTeam(undefined, addNewTeam(t1))).toEqual(t1)
    })

    it('will not change existing team for addNewTeam action', () => {
      expect(currentTeam(t1, addNewTeam(t2))).toEqual(t1)
    })

    it('will not change currentTeam if an other team was updated', () => {
      expect(currentTeam(t1, updateTeam(t2))).toEqual(t1)
    })

    it('will update currentTeam if update team action fiered for currentTeam', () => {
      const changedTeam = new TeamObject({
        id: t1.id,
        name: 'chnaged',
      })
      expect(currentTeam(t1, updateTeam(changedTeam))).toEqual(changedTeam)
    })

    it('will set currentTeam', () => {
      expect(currentTeam(t1, setCurrentTeam(t2))).toEqual(t2)
      expect(currentTeam(t1, setCurrentTeam(t1))).toEqual(t1)
      expect(currentTeam(null, setCurrentTeam(t1))).toEqual(t1)
      expect(currentTeam(t1, setCurrentTeam(null))).toEqual(t1)
    });
  })

  describe('users', () => {
    it('sets all users', () => {
      expect(users({
        xxx: {
          u1id: u1,
          u2id: u2,
        },
      }, setAllUsers({
        teamId: 'xxx',
        users: [u1],
      }))).toEqual({
        xxx: {
          u1id: u1,
        },
      })

      expect(users({
        xxx: {
          u1id: u1,
          u2id: u2,
        },
      }, setAllUsers({
        teamId: 'xxx',
        users: [],
      }))).toEqual({
        xxx: {},
      })

      expect(users({}, setAllUsers({
        teamId: 'xxx',
        users: [u2],
      }))).toEqual({
        xxx: {
          u2id: u2,
        },
      })

      expect(users(undefined, setAllUsers({
        teamId: 'xxx',
        users: [u1, u2],
      }))).toEqual({
        xxx: {
          u1id: u1,
          u2id: u2,
        },
      })
    })

    it('Will not add new user if user already exists', () => {
      expect(users({
        [u1.teamId]: {
          u1id: u1,
        },
      }, addNewUser(u1))).toEqual({
        [u1.teamId]: {
          u1id: u1,
        },
      })
    })

    it('Will add new user', () => {
      expect(users(undefined, addNewUser(u1))).toEqual({
        [u1.teamId]: {
          u1id: u1,
        },
      })

      expect(users({}, addNewUser(u1))).toEqual({
        [u1.teamId]: {
          u1id: u1,
        },
      })

      expect(users({
        [u1.teamId]: {
          u1id: u1,
        },
      }, addNewUser(u2))).toEqual({
        [u1.teamId]: {
          u1id: u1,
          u2id: u2,
        },
      })
    })

    it('add new user when addNewUser action fiered', () => {
      expect(users({
        xxx: {
          u1id: u1,
          u2id: u2,
        },
      }, setAllUsers({
        teamId: 'xxx',
        users: [],
      }))).toEqual({
        xxx: {},
      })

      expect(users({}, setAllUsers({
        teamId: 'xxx',
        users: [u2],
      }))).toEqual({
        xxx: {
          u2id: u2,
        },
      })

      expect(users(undefined, setAllUsers({
        teamId: 'xxx',
        users: [u1, u2],
      }))).toEqual({
        xxx: {
          u1id: u1,
          u2id: u2,
        },
      })
    })
  })

  describe('channels', () => {
    it('sets channels', () => {
      expect(channels(undefined, setAllChannels({
        teamId: 'xxx',
        channels: [ch1, ch2],
      }))).toEqual({
        xxx: [ch1, ch2],
      })
    })

    it('replace existing channels when setAllChannels action fiered', () => {
      expect(channels({
        xxx: [ch1, ch2],
      }, setAllChannels({
        teamId: 'xxx',
        channels: [ch1],
      }))).toEqual({ xxx: [ch1] })
    })

    it('adds channels', () => {
      expect(channels({
        xxx: [ch1],
      }, addChannels({
        teamId: 'xxx',
        channels: [ch2],
      }))).toEqual({
        xxx: [ch1, ch2],
      })
    })

    it('will update channel', () => {
      const changedChannel = new ChannelObject({
        id: ch1.id,
        teamId: ch1.teamId,
        name: 'Changed Name',
      })

      expect(channels({
        xxx: [ch1],
      }, updateChannel(changedChannel))).toEqual({
        xxx: [changedChannel],
      })
    })

    it('adds new channel', () => {
      expect(channels({
        xxx: [ch1],
      }, addNewChannel(ch2))).toEqual({
        xxx: [ch1, ch2],
      })
    });
  })
})
<|endoftext|>