<commit_before>/*
==================================================================================================
  Jasy - JavaScript Tooling Framework
  Copyright 2010-2011 Sebastian Werner
--------------------------------------------------------------------------------------------------
  Based on the work of ES5 Shim
  MIT License, Copyright (c) 2009, 280 North Inc. http://280north.com/
==================================================================================================
*/

// ES5
// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/isArray
if (!Array.isArray)
{
	Array.isArray = function(value) {
		return value != null && Object.prototype.toString.call(value) == "[object Array]";
	};
}

// ES5 15.4.4.18
// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/foreach
if (!Array.prototype.forEach)
{
	Array.prototype.forEach = function forEach(block, thisObject)
	{
		var len = +this.length;
		for (var i = 0; i < len; i++)
		{
			if (i in this) {
				block.call(thisObject, this[i], i, this);
			}
		}
	};
}

// ES5 15.4.4.19
// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/map
if (!Array.prototype.map)
{
	Array.prototype.map = function map(fun /*, thisp*/)
	{
		if (typeof fun !== "function") {
			throw new TypeError();
		}

		var len = this.length;
		var res = new Array(len);
		var thisp = arguments[1];

		for (var i = 0; i < len; i++)
		{
			if (i in this) {
				res[i] = fun.call(thisp, this[i], i, this);
			}
		}

		return res;
	};
}

// ES5 15.4.4.20
// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/filter
if (!Array.prototype.filter)
{
	Array.prototype.filter = function filter(block /*, thisp */)
	{
		var values = [];
		var thisp = arguments[1];

		for (var i = 0; i < this.length; i++)
		{
			if (block.call(thisp, this[i])) {
				values.push(this[i]);
			}
		}

		return values;
	};
}

// ES5 15.4.4.16
// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/every
if (!Array.prototype.every)
{
	Array.prototype.every = function every(block /*, thisp */)
	{
		var thisp = arguments[1];

		for (var i = 0; i < this.length; i++)
		{
			if (!block.call(thisp, this[i])) {
				return false;
			}
		}

		return true;
	};
}

// ES5 15.4.4.17
// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/some
if (!Array.prototype.some)
{
	Array.prototype.some = function some(block /*, thisp */)
	{
		var thisp = arguments[1];

		for (var i = 0; i < this.length; i++)
		{
			if (block.call(thisp, this[i])) {
				return true;
			}
		}

		return false;
	};
}

// ES5 15.4.4.21
// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduce
if (!Array.prototype.reduce)
{
	Array.prototype.reduce = function reduce(fun /*, initial*/)
	{
		var len = +this.length;

		// Whether to include (... || fun instanceof RegExp)
		// in the following expression to trap cases where
		// the provided function was actually a regular
		// expression literal, which in V8 and
		// JavaScriptCore is a typeof "function".  Only in
		// V8 are regular expression literals permitted as
		// reduce parameters, so it is desirable in the
		// general case for the shim to match the more
		// strict and common behavior of rejecting regular
		// expressions. However, the only case where the
		// shim is applied is IE's Trident (and perhaps very
		// old revisions of other engines).	 In Trident,
		// regular expressions are a typeof "object", so the
		// following guard alone is sufficient.

		if (typeof fun !== "function") {
			throw new TypeError();
		}

		// no value to return if no initial value and an empty array
		if (len === 0 && arguments.length === 1) {
			throw new TypeError();
		}

		var i = 0;
		if (arguments.length >= 2)
		{
			var rv = arguments[1];
		}
		else
		{
			do
			{
				if (i in this)
				{
					rv = this[i++];
					break;
				}

				// if array contains no values, no initial value to return
				if (++i >= len) {
					throw new TypeError();
				}
			}
			while (true);
		}

		for (; i < len; i++)
		{
			if (i in this) {
				rv = fun.call(null, rv, this[i], i, this);
			}
		}

		return rv;
	};
}

// ES5 15.4.4.22
// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduceRight
if (!Array.prototype.reduceRight)
{
	Array.prototype.reduceRight = function reduceRight(fun /*, initial*/)
	{
		if (typeof fun !== "function") {
			throw new TypeError();
		}

		// no value to return if no initial value, empty array
		var len = this.length;
		if (len === 0 && arguments.length === 1) {
			throw new TypeError();
		}

		var rv, i = len - 1;
		if (arguments.length >= 2)
		{
			rv = arguments[1];
		}
		else
		{
			do
			{
				if (i in this)
				{
					rv = this[i--];
					break;
				}

				// if array contains no values, no initial value to return
				if (--i < 0) {
					throw new TypeError();
				}
			}
			while (true);
		}

		for (; i >= 0; i--)
		{
			if (i in this) {
				rv = fun.call(null, rv, this[i], i, this);
			}
		}

		return rv;
	};
}

// ES5 15.4.4.14
// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf
if (!Array.prototype.indexOf)
{
	Array.prototype.indexOf = function indexOf(value /*, fromIndex */ )
	{
		var length = this.length;
		if (!length) {
			return -1;
		}

		var i = arguments[1] || 0;
		if (i >= length) {
			return -1;
		}

		if (i < 0) {
			i += length;
		}

		for (; i < length; i++)
		{
			if (!(i in this)) {
				continue;
			}

			if (value === this[i]) {
				return i;
			}
		}

		return -1;
	};
}

// ES5 15.4.4.15
// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/lastIndexOf
if (!Array.prototype.lastIndexOf)
{
	Array.prototype.lastIndexOf = function lastIndexOf(value /*, fromIndex */)
	{
		var length = this.length;
		if (!length) {
			return -1;
		}

		var i = arguments[1] || length;
		if (i < 0) {
			i += length;
		}

		i = Math.min(i, length - 1);

		for (; i >= 0; i--)
		{
			if (!(i in this)) {
				continue;
			}

			if (value === this[i]) {
				return i;
			}
		}

		return -1;
	};
}
<commit_msg>Removed array.indexOf from ES5 polyfill. Already fixed by fix.ArrayIndexOf.<commit_after>/*
==================================================================================================
  Jasy - JavaScript Tooling Framework
  Copyright 2010-2011 Sebastian Werner
--------------------------------------------------------------------------------------------------
  Based on the work of ES5 Shim
  MIT License, Copyright (c) 2009, 280 North Inc. http://280north.com/
==================================================================================================
*/

// ES5
// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/isArray
if (!Array.isArray)
{
	Array.isArray = function(value) {
		return value != null && Object.prototype.toString.call(value) == "[object Array]";
	};
}

// ES5 15.4.4.18
// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/foreach
if (!Array.prototype.forEach)
{
	Array.prototype.forEach = function forEach(block, thisObject)
	{
		var len = +this.length;
		for (var i = 0; i < len; i++)
		{
			if (i in this) {
				block.call(thisObject, this[i], i, this);
			}
		}
	};
}

// ES5 15.4.4.19
// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/map
if (!Array.prototype.map)
{
	Array.prototype.map = function map(fun /*, thisp*/)
	{
		if (typeof fun !== "function") {
			throw new TypeError();
		}

		var len = this.length;
		var res = new Array(len);
		var thisp = arguments[1];

		for (var i = 0; i < len; i++)
		{
			if (i in this) {
				res[i] = fun.call(thisp, this[i], i, this);
			}
		}

		return res;
	};
}

// ES5 15.4.4.20
// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/filter
if (!Array.prototype.filter)
{
	Array.prototype.filter = function filter(block /*, thisp */)
	{
		var values = [];
		var thisp = arguments[1];

		for (var i = 0; i < this.length; i++)
		{
			if (block.call(thisp, this[i])) {
				values.push(this[i]);
			}
		}

		return values;
	};
}

// ES5 15.4.4.16
// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/every
if (!Array.prototype.every)
{
	Array.prototype.every = function every(block /*, thisp */)
	{
		var thisp = arguments[1];

		for (var i = 0; i < this.length; i++)
		{
			if (!block.call(thisp, this[i])) {
				return false;
			}
		}

		return true;
	};
}

// ES5 15.4.4.17
// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/some
if (!Array.prototype.some)
{
	Array.prototype.some = function some(block /*, thisp */)
	{
		var thisp = arguments[1];

		for (var i = 0; i < this.length; i++)
		{
			if (block.call(thisp, this[i])) {
				return true;
			}
		}

		return false;
	};
}

// ES5 15.4.4.21
// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduce
if (!Array.prototype.reduce)
{
	Array.prototype.reduce = function reduce(fun /*, initial*/)
	{
		var len = +this.length;

		// Whether to include (... || fun instanceof RegExp)
		// in the following expression to trap cases where
		// the provided function was actually a regular
		// expression literal, which in V8 and
		// JavaScriptCore is a typeof "function".  Only in
		// V8 are regular expression literals permitted as
		// reduce parameters, so it is desirable in the
		// general case for the shim to match the more
		// strict and common behavior of rejecting regular
		// expressions. However, the only case where the
		// shim is applied is IE's Trident (and perhaps very
		// old revisions of other engines).	 In Trident,
		// regular expressions are a typeof "object", so the
		// following guard alone is sufficient.

		if (typeof fun !== "function") {
			throw new TypeError();
		}

		// no value to return if no initial value and an empty array
		if (len === 0 && arguments.length === 1) {
			throw new TypeError();
		}

		var i = 0;
		if (arguments.length >= 2)
		{
			var rv = arguments[1];
		}
		else
		{
			do
			{
				if (i in this)
				{
					rv = this[i++];
					break;
				}

				// if array contains no values, no initial value to return
				if (++i >= len) {
					throw new TypeError();
				}
			}
			while (true);
		}

		for (; i < len; i++)
		{
			if (i in this) {
				rv = fun.call(null, rv, this[i], i, this);
			}
		}

		return rv;
	};
}

// ES5 15.4.4.22
// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduceRight
if (!Array.prototype.reduceRight)
{
	Array.prototype.reduceRight = function reduceRight(fun /*, initial*/)
	{
		if (typeof fun !== "function") {
			throw new TypeError();
		}

		// no value to return if no initial value, empty array
		var len = this.length;
		if (len === 0 && arguments.length === 1) {
			throw new TypeError();
		}

		var rv, i = len - 1;
		if (arguments.length >= 2)
		{
			rv = arguments[1];
		}
		else
		{
			do
			{
				if (i in this)
				{
					rv = this[i--];
					break;
				}

				// if array contains no values, no initial value to return
				if (--i < 0) {
					throw new TypeError();
				}
			}
			while (true);
		}

		for (; i >= 0; i--)
		{
			if (i in this) {
				rv = fun.call(null, rv, this[i], i, this);
			}
		}

		return rv;
	};
}

// ES5 15.4.4.15
// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/lastIndexOf
if (!Array.prototype.lastIndexOf)
{
	Array.prototype.lastIndexOf = function lastIndexOf(value /*, fromIndex */)
	{
		var length = this.length;
		if (!length) {
			return -1;
		}

		var i = arguments[1] || length;
		if (i < 0) {
			i += length;
		}

		i = Math.min(i, length - 1);

		for (; i >= 0; i--)
		{
			if (!(i in this)) {
				continue;
			}

			if (value === this[i]) {
				return i;
			}
		}

		return -1;
	};
}
<|endoftext|>


<commit_before>/**
 * Created by vytautassugintas on 06/04/16.
 */
'use strict';

angular
    .module('myApp.profile', [
        'ngRoute',
        'ngCookies',
        'angucomplete'
    ])

    .controller('profileController', function ($http, $scope, $window, $cookies, $timeout, $httpParamSerializer, ProfileService) {
        checkUser();

        var inputChangedPromise;

        $scope.userAvailableKudos = 0;
        $scope.userReceivedKudos = 0;
        $scope.sendKudosErrorMessage = "Please enter receiver and amount";
        $scope.incomingKudosShowLimit = 3;
        $scope.outgoingKudosShowLimit = 3;
        $scope.maxSendKudosLength = $scope.userAvailableKudos;
        $scope.incomingKudosCollection = [];
        $scope.outgoingKudosCollection = [];
        $scope.usersCollection = [];
        $scope.buttonDisabled = true;

        $scope.updateProfile = updateProfile;
        $scope.logout = logout;
        $scope.sendKudos = sendKudos;
        $scope.inputChanged = inputChanged;
        $scope.kudosValidation = kudosValidation;
        $scope.isValid = isValid;
        $scope.clearSendKudosFormValues = clearSendKudosFormValues;
        $scope.showMoreIncomingKudos = showMoreIncomingKudos;
        $scope.showMoreOutgoingKudos = showMoreOutgoingKudos;
        $scope.showLessIncomingKudos = showLessIncomingKudos;
        $scope.showLessOutgoingKudos = showLessOutgoingKudos;
        $scope.resetModal = resetModal;

        ProfileService.userHome().then(function (val) {
            $scope.userEmail = val.email;
            $scope.userName = val.firstName;
            $scope.userSurname = val.lastName;
            $scope.userPhone = val.phone;
            $scope.userPosition = val.position;
            $scope.userLocation = val.location;
            $scope.userTeam = val.team;
            $scope.userStartedToWork = val.startedToWorkDate;
            $scope.userBirthday = val.birthday;
        });

        ProfileService.remainingKudos().then(function (val) {
            $scope.userAvailableKudos = val;
        });

        ProfileService.receivedKudos().then(function (val) {
            $scope.userReceivedKudos = val;
        });

        ProfileService.incomingKudos().then(function (val) {
            $scope.incomingKudosCollection = val;
        });

        ProfileService.outgoingKudos().then(function (val) {
            $scope.outgoingKudosCollection = val;
        });

        ProfileService.listUsers().then(function (val) {
            $scope.usersCollection = val.userList;
        });

        function showMoreIncomingKudos() {
            if ($scope.incomingKudosShowLimit <= $scope.incomingKudosCollection.length) {
                $scope.incomingKudosShowLimit += 5;
            }
        }

        function showMoreOutgoingKudos() {
            if ($scope.outgoingKudosShowLimit <= $scope.outgoingKudosCollection.length) {
                $scope.outgoingKudosShowLimit += 5;
            }
        }

        function showLessOutgoingKudos() {
            $scope.outgoingKudosShowLimit = 3;
        }

        function showLessIncomingKudos() {
            $scope.incomingKudosShowLimit = 3;
        }

        function updateProfile() {
            var updateInfo = $.param({
                birthday: this.birthday,
                department: this.department,
                location: this.location,
                phone: "",              // <-- TODO FIX PHONE
                position: this.position,
                startToWork: this.startToWork,
                team: this.team
            });
            ProfileService.update(updateInfo).then(function (val) {
                $('#userDetailsModal').modal('hide');
                checkUser();
            })
        }

        function sendKudos() {
            var sendTo = $httpParamSerializer({
                receiverEmail: $scope.sendKudosTo,
                amount: $scope.sendKudosAmount,
                message: $scope.sendKudosMessage
            });

            ProfileService.send(sendTo).then(function (val) {
                $scope.showSendKudosModal = false;
                $scope.showSuccess = true;
                $scope.userAvailableKudos = $scope.userAvailableKudos - val.data.amount;
                $('#sendKudosModal').modal('hide');
                toastr.success('You successfully sent ' + acornPlural(val.data.amount) + ' to ' + val.data.receiver);
                pushOutgoingTransferIntoCollection(val.data);
                clearSendKudosFormValues();
            }).catch(function () {
                showSendKudosErrorMessage("Receiver does not exist");
            });
        }

        function inputChanged() {
            if (inputChangedPromise) {
                $timeout.cancel(inputChangedPromise);
            }
            inputChangedPromise = $timeout(kudosValidation, 100);
        }

        function kudosValidation() {
            $scope.errorClass = "error-message";
            if ($scope.sendKudosAmount > $scope.userAvailableKudos
            ) {
                showSendKudosErrorMessage("You don't have enough Acorns");
                $scope.sendKudosForm.sendKudosAmount.$invalid = true;
            } else if ($scope.sendKudosAmount == null) {
                showSendKudosErrorMessage("Please enter amount");
                $scope.sendKudosForm.sendKudosAmount.$invalid = true;
            } else if ($scope.sendKudosAmount <= 0) {
                showSendKudosErrorMessage("Please enter more than zero");
                $scope.sendKudosForm.sendKudosAmount.$invalid = true;
            } else if ($scope.sendKudosTo == null) {
                showSendKudosErrorMessage("Please enter receiver");
                $scope.sendKudosForm.sendKudosTo.$invalid = true;
            } else if (!validateEmail($scope.sendKudosTo)) {
                showSendKudosErrorMessage("Please enter valid receiver email");
                $scope.sendKudosForm.sendKudosTo.$invalid = true;
            } else if ($scope.sendKudosTo === $scope.userEmail) {
                showSendKudosErrorMessage("Can't send kudos to yourself");
                $scope.sendKudosForm.sendKudosTo.$invalid = true;
            } else {
                showSendKudosSuccessMessage("Ok, you'r good to go!");
            }
        }

        function inputChanged() {
            if (inputChangedPromise) {
                $timeout.cancel(inputChangedPromise);
            }
            inputChangedPromise = $timeout(kudosValidation, 100);
        }

        function checkUser() {
            ProfileService.checkUser().then(function (val) {
                val.logged ? $window.location.href = "#/profile" : $window.location.href = "#/login";
            });
        }

        function logout() {
            clearCookies();
            ProfileService.logout().catch(function () {
                $window.location.href = "#/login";
            });
        }

        function clearCookies() {
            $cookies.put('remember_user', 'false');
            $cookies.put('user_credentials', '');
        }

        function isValid(value) {
            return typeof value === "undefined";
        }

        function enableSendKudosButton() {
            $scope.buttonDisabled = false;
        }

        function disableSendKudosButton() {
            $scope.buttonDisabled = true;
        }

        function isValid(value) {
            return typeof value === "undefined";
        }

        function validateEmail(email) {
            var re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
            return re.test(email);
        }

        function showSendKudosErrorMessage(message) {
            $scope.sendKudosErrorMessage = message;
            disableSendKudosButton();
        }

        function showSendKudosSuccessMessage(message) {
            $scope.errorClass = "success-message";
            $scope.sendKudosErrorMessage = message;
            enableSendKudosButton();
        }

        function clearSendKudosFormValues() {
            $scope.sendKudosTo = "";
            $scope.sendKudosAmount = "";
            $scope.sendKudosMessage = "";
            $scope.errorClass = "error-message";
            $scope.sendKudosErrorMessage = "Please enter receiver and amount";
            disableSendKudosButton();
        }

        function pushOutgoingTransferIntoCollection(val) {
            var itemToAdd = {
                receiver: val.receiver,
                message: val.message,
                amount: val.amount,
                timestamp: val.timestamp
            };
            $scope.outgoingKudosCollection.push(itemToAdd);
        }

        function acornPlural(amount) {
            return amount > 1 ? amount + " Acorns" : amount + " Acorn"
        }

    });<commit_msg>Profile controller fix<commit_after>/**
 * Created by vytautassugintas on 06/04/16.
 */
'use strict';

angular
    .module('myApp.profile', [
        'ngRoute',
        'ngCookies',
        'angucomplete'
    ])

    .controller('profileController', function ($http, $scope, $window, $cookies, $timeout, $httpParamSerializer, ProfileService) {
        checkUser();

        var inputChangedPromise;

        $scope.userAvailableKudos = 0;
        $scope.userReceivedKudos = 0;
        $scope.sendKudosErrorMessage = "Please enter receiver and amount";
        $scope.incomingKudosShowLimit = 3;
        $scope.outgoingKudosShowLimit = 3;
        $scope.maxSendKudosLength = $scope.userAvailableKudos;
        $scope.incomingKudosCollection = [];
        $scope.outgoingKudosCollection = [];
        $scope.usersCollection = [];
        $scope.buttonDisabled = true;

        $scope.updateProfile = updateProfile;
        $scope.logout = logout;
        $scope.sendKudos = sendKudos;
        $scope.inputChanged = inputChanged;
        $scope.kudosValidation = kudosValidation;
        $scope.isValid = isValid;
        $scope.clearSendKudosFormValues = clearSendKudosFormValues;
        $scope.showMoreIncomingKudos = showMoreIncomingKudos;
        $scope.showMoreOutgoingKudos = showMoreOutgoingKudos;
        $scope.showLessIncomingKudos = showLessIncomingKudos;
        $scope.showLessOutgoingKudos = showLessOutgoingKudos;

        ProfileService.userHome().then(function (val) {
            $scope.userEmail = val.email;
            $scope.userName = val.firstName;
            $scope.userSurname = val.lastName;
            $scope.userPhone = val.phone;
            $scope.userPosition = val.position;
            $scope.userLocation = val.location;
            $scope.userTeam = val.team;
            $scope.userStartedToWork = val.startedToWorkDate;
            $scope.userBirthday = val.birthday;
        });

        ProfileService.remainingKudos().then(function (val) {
            $scope.userAvailableKudos = val;
        });

        ProfileService.receivedKudos().then(function (val) {
            $scope.userReceivedKudos = val;
        });

        ProfileService.incomingKudos().then(function (val) {
            $scope.incomingKudosCollection = val;
        });

        ProfileService.outgoingKudos().then(function (val) {
            $scope.outgoingKudosCollection = val;
        });

        ProfileService.listUsers().then(function (val) {
            $scope.usersCollection = val.userList;
        });

        function showMoreIncomingKudos() {
            if ($scope.incomingKudosShowLimit <= $scope.incomingKudosCollection.length) {
                $scope.incomingKudosShowLimit += 5;
            }
        }

        function showMoreOutgoingKudos() {
            if ($scope.outgoingKudosShowLimit <= $scope.outgoingKudosCollection.length) {
                $scope.outgoingKudosShowLimit += 5;
            }
        }

        function showLessOutgoingKudos() {
            $scope.outgoingKudosShowLimit = 3;
        }

        function showLessIncomingKudos() {
            $scope.incomingKudosShowLimit = 3;
        }

        function updateProfile() {
            var updateInfo = $.param({
                birthday: this.birthday,
                department: this.department,
                location: this.location,
                phone: "",              // <-- TODO FIX PHONE
                position: this.position,
                startToWork: this.startToWork,
                team: this.team
            });
            ProfileService.update(updateInfo).then(function (val) {
                $('#userDetailsModal').modal('hide');
                checkUser();
            })
        }

        function sendKudos() {
            var sendTo = $httpParamSerializer({
                receiverEmail: $scope.sendKudosTo,
                amount: $scope.sendKudosAmount,
                message: $scope.sendKudosMessage
            });

            ProfileService.send(sendTo).then(function (val) {
                $scope.showSendKudosModal = false;
                $scope.showSuccess = true;
                $scope.userAvailableKudos = $scope.userAvailableKudos - val.data.amount;
                $('#sendKudosModal').modal('hide');
                toastr.success('You successfully sent ' + acornPlural(val.data.amount) + ' to ' + val.data.receiver);
                pushOutgoingTransferIntoCollection(val.data);
                clearSendKudosFormValues();
            }).catch(function () {
                showSendKudosErrorMessage("Receiver does not exist");
            });
        }

        function inputChanged() {
            if (inputChangedPromise) {
                $timeout.cancel(inputChangedPromise);
            }
            inputChangedPromise = $timeout(kudosValidation, 100);
        }

        function kudosValidation() {
            $scope.errorClass = "error-message";
            if ($scope.sendKudosAmount > $scope.userAvailableKudos
            ) {
                showSendKudosErrorMessage("You don't have enough Acorns");
                $scope.sendKudosForm.sendKudosAmount.$invalid = true;
            } else if ($scope.sendKudosAmount == null) {
                showSendKudosErrorMessage("Please enter amount");
                $scope.sendKudosForm.sendKudosAmount.$invalid = true;
            } else if ($scope.sendKudosAmount <= 0) {
                showSendKudosErrorMessage("Please enter more than zero");
                $scope.sendKudosForm.sendKudosAmount.$invalid = true;
            } else if ($scope.sendKudosTo == null) {
                showSendKudosErrorMessage("Please enter receiver");
                $scope.sendKudosForm.sendKudosTo.$invalid = true;
            } else if (!validateEmail($scope.sendKudosTo)) {
                showSendKudosErrorMessage("Please enter valid receiver email");
                $scope.sendKudosForm.sendKudosTo.$invalid = true;
            } else if ($scope.sendKudosTo === $scope.userEmail) {
                showSendKudosErrorMessage("Can't send kudos to yourself");
                $scope.sendKudosForm.sendKudosTo.$invalid = true;
            } else {
                showSendKudosSuccessMessage("Ok, you'r good to go!");
            }
        }

        function inputChanged() {
            if (inputChangedPromise) {
                $timeout.cancel(inputChangedPromise);
            }
            inputChangedPromise = $timeout(kudosValidation, 100);
        }

        function checkUser() {
            ProfileService.checkUser().then(function (val) {
                val.logged ? $window.location.href = "#/profile" : $window.location.href = "#/login";
            });
        }

        function logout() {
            clearCookies();
            ProfileService.logout().catch(function () {
                $window.location.href = "#/login";
            });
        }

        function clearCookies() {
            $cookies.put('remember_user', 'false');
            $cookies.put('user_credentials', '');
        }

        function isValid(value) {
            return typeof value === "undefined";
        }

        function enableSendKudosButton() {
            $scope.buttonDisabled = false;
        }

        function disableSendKudosButton() {
            $scope.buttonDisabled = true;
        }

        function isValid(value) {
            return typeof value === "undefined";
        }

        function validateEmail(email) {
            var re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
            return re.test(email);
        }

        function showSendKudosErrorMessage(message) {
            $scope.sendKudosErrorMessage = message;
            disableSendKudosButton();
        }

        function showSendKudosSuccessMessage(message) {
            $scope.errorClass = "success-message";
            $scope.sendKudosErrorMessage = message;
            enableSendKudosButton();
        }

        function clearSendKudosFormValues() {
            $scope.sendKudosTo = "";
            $scope.sendKudosAmount = "";
            $scope.sendKudosMessage = "";
            $scope.errorClass = "error-message";
            $scope.sendKudosErrorMessage = "Please enter receiver and amount";
            disableSendKudosButton();
        }

        function pushOutgoingTransferIntoCollection(val) {
            var itemToAdd = {
                receiver: val.receiver,
                message: val.message,
                amount: val.amount,
                timestamp: val.timestamp
            };
            $scope.outgoingKudosCollection.push(itemToAdd);
        }

        function acornPlural(amount) {
            return amount > 1 ? amount + " Acorns" : amount + " Acorn"
        }

    });<|endoftext|>


<commit_before>CircleBlvd.Services.stories = function ($http) {

	var s = {};
	var isFacade = false;

	var getStory = function (storyId) {
		return s[storyId];
	};

	var getLastStoryId = function (projectId) {
		return "last-" + projectId;
	};

	var saveStory = function (story, callback) {
		if (isFacade) {
			if (callback) {
				callback(story);
			}
			return;
		}

		$http.put('/data/story/', story)
		.success(function (savedStory) {
			if (callback) {
				callback(savedStory);
			}
		})
		.error(function (data, status) {
			console.log(status);
			console.log(data);
		});
	};

	var saveStoryComment = function (story, comment, callback) {
		if (isFacade) {
			if (callback) {
				callback(story);
			}
			return;
		}

		var data = {};
		data.circleId = story.projectId;
		data.storyId = story.id;
		data.comment = comment;
		$http.put('/data/story/comment', data)
		.success(function (savedStory) {
			if (callback) {
				callback(savedStory);
			}
		})
		.error(function (data, status) {
			console.log(status);
			console.log(data);
		});
	};

	var usefulStories = function() {
		var s = {};
		s.first = undefined;

		return {
			setFirst: function (story) {
				if (s.first) {
					s.first.isFirstStory = false;
				}
				s.first = story;
				if (s.first) {
					s.first.isFirstStory = true;
				}
			},
			getFirst: function () {
				return s.first;
			},
			hasFirst: function() {
				if (s.first) {
					return true;
				}
				else {
					return false;
				}
			}
		};
	}(); // closure

	var addStory = function (story, callback) {
		var onSuccess = function (newStory) {
			s[newStory.id] = newStory;
			callback(newStory);
		};

		if (isFacade) {
			// TODO: Need a faux id
			onSuccess(story);
			return;
		}

		$http.post('/data/story/', story)
		.success(onSuccess)
		.error(function (data, status) {
			// TODO: Show that something went wrong.
			// Most likely there was a data conflict
			// that could not be resolved.
			console.log(status);
			console.log(data);
			callback(null);
		});
	};

	var insertFirstStory = function (story, projectId, callback) {
		var hadFirstStoryPreviously = usefulStories.hasFirst();
		if (hadFirstStoryPreviously) {
			story.nextId = usefulStories.getFirst().id;
		}

		story.projectId = projectId;
		story.type = "story";

		addStory(story, function (newStory) {
			if (newStory) {
				var serverStory = getStory(newStory.id);
				if (newStory.isFirstStory) {
					usefulStories.setFirst(serverStory);
				}
				else {
					// TODO: Probably want to refresh the whole list
					// from the server, because some crazy things are
					// happening!
				}
				if (callback) {
					callback(serverStory);
				}
			}
			else if (callback) {
				callback();
			}
		});
	};

	var isBacklogBroken = function () {
		var nextIdCounts = {};
		var isBroken = false;
		var currentStory = usefulStories.getFirst();
		while (currentStory && !isBroken) {
			if (!nextIdCounts[currentStory.id]) {
				nextIdCounts[currentStory.id] = 1;
			}
			else {
				nextIdCounts[currentStory.id]++;
				isBroken = true;
			}
			currentStory = getStory(currentStory.nextId);
		}

		return isBroken;
	};

	var getPreviousStory = function (story, serverStory) {
		var previousStory = story;
		if (usefulStories.getFirst().id === story.id) {
			return undefined;
		}

		if (isBacklogBroken()) {
			return null;
		}

		var currentStory = usefulStories.getFirst();
		while (currentStory) {
			if (currentStory.nextId === serverStory.id) {
				previousStory = currentStory;
				return previousStory;
			}
			currentStory = getStory(currentStory.nextId);
		}

		// TODO: If we get here, the story doesn't exist.
		return previousStory;
	};

	// wrap around getting and setting the server-side stories,
	// so we can push to the server when we set things. there's
	// probably a better way / pattern for doing this. feel free
	// to implement it, future self.
	var stories = function() {

		return {
			setFacade: function (val) {
				isFacade = val;
			},
			setFirst: usefulStories.setFirst,
			getFirst: usefulStories.getFirst,
			hasFirst: usefulStories.hasFirst,

			init: function (data) {
				s = data;
			},
			add: addStory,
			insertFirst: insertFirstStory,
			move: function (story, newNextStory, callback) {
				var body = {};
				body.story = story;

				if (newNextStory) {
					body.newNextId = newNextStory.id;
				}
				else {
					body.newNextId = getLastStoryId(story.projectId);
				}

				if (isFacade) {
					callback();
					return;
				}

				$http.put('/data/story/move', body)
				.success(function (response) {
					// TODO: Move stuff around or something
					callback(null, response);
				})
				.error(function (data, status) {
					callback({
						status: status,
						data: data
					});
				});
			},
			save: saveStory,
			saveComment: saveStoryComment,
			get: getStory,
			getPrevious: getPreviousStory,
			set: function (storyId, story, callback) {
				if (s[storyId]) {
					s[storyId] = story;
					// update story
					stories.save(story, function (savedStory) {
						if (callback) {
							callback(savedStory);
						}
					});
				}
			},
			all: function() {
				return s;
			},
			remove: function (storyId) {
				// TODO: Right now the server-side is handled outside of
				// this class. Should probably make things be consistent.
				if (s[storyId]) {
					delete s[storyId];
				}
			},
			isListBroken: isBacklogBroken
		};
	}(); // closure;

	return stories;
};
CircleBlvd.Services.stories.$inject = ['$http'];<commit_msg>StoryList: Show error as story when limit is hit<commit_after>CircleBlvd.Services.stories = function ($http) {

	var s = {};
	var isFacade = false;

	var getStory = function (storyId) {
		return s[storyId];
	};

	var getLastStoryId = function (projectId) {
		return "last-" + projectId;
	};

	var saveStory = function (story, callback) {
		if (isFacade) {
			if (callback) {
				callback(story);
			}
			return;
		}

		$http.put('/data/story/', story)
		.success(function (savedStory) {
			if (callback) {
				callback(savedStory);
			}
		})
		.error(function (data, status) {
			console.log(status);
			console.log(data);
		});
	};

	var saveStoryComment = function (story, comment, callback) {
		if (isFacade) {
			if (callback) {
				callback(story);
			}
			return;
		}

		var data = {};
		data.circleId = story.projectId;
		data.storyId = story.id;
		data.comment = comment;
		$http.put('/data/story/comment', data)
		.success(function (savedStory) {
			if (callback) {
				callback(savedStory);
			}
		})
		.error(function (data, status) {
			console.log(status);
			console.log(data);
		});
	};

	var usefulStories = function() {
		var s = {};
		s.first = undefined;

		return {
			setFirst: function (story) {
				if (s.first) {
					s.first.isFirstStory = false;
				}
				s.first = story;
				if (s.first) {
					s.first.isFirstStory = true;
				}
			},
			getFirst: function () {
				return s.first;
			},
			hasFirst: function() {
				if (s.first) {
					return true;
				}
				else {
					return false;
				}
			}
		};
	}(); // closure

	var addStory = function (story, callback) {
		var onSuccess = function (newStory) {
			s[newStory.id] = newStory;
			callback(newStory);
		};

		if (isFacade) {
			// TODO: Need a faux id
			onSuccess(story);
			return;
		}

		$http.post('/data/story/', story)
		.success(onSuccess)
		.error(function (data, status) {
			// TODO: Show that something went wrong.
			// Most likely there was a data conflict
			// that could not be resolved.
			console.log(status);
			console.log(data);
			var id = "error-" + Date.now();
			var facade = null;
			if (status === 403) {
				var description = "Hi! Thanks for using Circle Blvd so much!\n\n" +
				"Please tell Phil this is happening, and he'll fix this problem right away.";
				facade = {
					id: id,
					summary: data,
					description: description,
					type: "story"
				};
				s[id] = facade;
			}
			callback(facade);
		});
	};

	var insertFirstStory = function (story, projectId, callback) {
		var hadFirstStoryPreviously = usefulStories.hasFirst();
		if (hadFirstStoryPreviously) {
			story.nextId = usefulStories.getFirst().id;
		}

		story.projectId = projectId;
		story.type = "story";

		addStory(story, function (newStory) {
			if (newStory) {
				var serverStory = getStory(newStory.id);
				if (newStory.isFirstStory) {
					usefulStories.setFirst(serverStory);
				}
				else {
					// TODO: Probably want to refresh the whole list
					// from the server, because some crazy things are
					// happening!
				}
				if (callback) {
					callback(serverStory);
				}
			}
			else if (callback) {
				callback();
			}
		});
	};

	var isBacklogBroken = function () {
		var nextIdCounts = {};
		var isBroken = false;
		var currentStory = usefulStories.getFirst();
		while (currentStory && !isBroken) {
			if (!nextIdCounts[currentStory.id]) {
				nextIdCounts[currentStory.id] = 1;
			}
			else {
				nextIdCounts[currentStory.id]++;
				isBroken = true;
			}
			currentStory = getStory(currentStory.nextId);
		}

		return isBroken;
	};

	var getPreviousStory = function (story, serverStory) {
		var previousStory = story;
		if (usefulStories.getFirst().id === story.id) {
			return undefined;
		}

		if (isBacklogBroken()) {
			return null;
		}

		var currentStory = usefulStories.getFirst();
		while (currentStory) {
			if (currentStory.nextId === serverStory.id) {
				previousStory = currentStory;
				return previousStory;
			}
			currentStory = getStory(currentStory.nextId);
		}

		// TODO: If we get here, the story doesn't exist.
		return previousStory;
	};

	// wrap around getting and setting the server-side stories,
	// so we can push to the server when we set things. there's
	// probably a better way / pattern for doing this. feel free
	// to implement it, future self.
	var stories = function() {

		return {
			setFacade: function (val) {
				isFacade = val;
			},
			setFirst: usefulStories.setFirst,
			getFirst: usefulStories.getFirst,
			hasFirst: usefulStories.hasFirst,

			init: function (data) {
				s = data;
			},
			add: addStory,
			insertFirst: insertFirstStory,
			move: function (story, newNextStory, callback) {
				var body = {};
				body.story = story;

				if (newNextStory) {
					body.newNextId = newNextStory.id;
				}
				else {
					body.newNextId = getLastStoryId(story.projectId);
				}

				if (isFacade) {
					callback();
					return;
				}

				$http.put('/data/story/move', body)
				.success(function (response) {
					// TODO: Move stuff around or something
					callback(null, response);
				})
				.error(function (data, status) {
					callback({
						status: status,
						data: data
					});
				});
			},
			save: saveStory,
			saveComment: saveStoryComment,
			get: getStory,
			getPrevious: getPreviousStory,
			set: function (storyId, story, callback) {
				if (s[storyId]) {
					s[storyId] = story;
					// update story
					stories.save(story, function (savedStory) {
						if (callback) {
							callback(savedStory);
						}
					});
				}
			},
			all: function() {
				return s;
			},
			remove: function (storyId) {
				// TODO: Right now the server-side is handled outside of
				// this class. Should probably make things be consistent.
				if (s[storyId]) {
					delete s[storyId];
				}
			},
			isListBroken: isBacklogBroken
		};
	}(); // closure;

	return stories;
};
CircleBlvd.Services.stories.$inject = ['$http'];<|endoftext|>


<commit_before>'use strict';

function HomeCtrl(session, hacks, $scope, $timeout, $http, $routeParams, $route) {

	var circleId = session.activeCircle;

	$scope.$on('storyListBroken', function () {
		$scope.isBacklogBroken = true;
	});

	var entryPanel = function () {
		$scope.isAdding = [];
		$scope.isAdding['story'] = false;
		$scope.isAdding['deadline'] = false;

		$scope.showEntry = function (panelName) {
			if (!panelName) {
				$scope.isAddingNew = true;
				$scope.showEntry('story');
				// TODO: Focus for all the story types
				hacks.focus('storyEntry');
			}
			else {
				for (var pName in $scope.isAdding) {
					$scope.isAdding[pName] = false;
				}
				$scope.isAdding[panelName] = true;
				hacks.focus(panelName + 'Entry');
			}
		};

		$scope.hideEntry = function () {
			$scope.isAddingNew = undefined;
		};

		$scope.toggleAltMode = function () {
			if ($scope.isManualAltMode) {
				$scope.isManualAltMode = false;
			}
			else {
				$scope.isManualAltMode = true;
			}
		}
	}();

	var insertNewStory = function (newStory, callback) {
		$scope.$broadcast('insertNewStory', newStory, callback);
	};

	var isCreatingStory = false;
	$scope.create = function (newStory) {
		if (!isCreatingStory && newStory) {
			isCreatingStory = true;
			insertNewStory(newStory, function () {
				$scope.newStory = undefined;
				isCreatingStory = false;
				$timeout(makeStoriesDraggable, 0);
			});
		}
	};

	$scope.createDeadline = function (newDeadline) {
		if (!isCreatingStory && newDeadline) {
			isCreatingStory = true;
			newDeadline.isDeadline = true;
			insertNewStory(newDeadline, function () {
				$scope.newDeadline = undefined;
				isCreatingStory = false;
				$timeout(makeStoriesDraggable, 0);
			});
		}
	};

	$scope.createMany = function (newMany) {
		var input = newMany.txt;
		var lines = input.split('\n');

		if (!lines || lines.length === 0 || isCreatingStory) {
			return;
		}

		isCreatingStory = true;

		var lineIndex = lines.length-1;
		var lastLine = lines[lineIndex];

		var done = function () {
			$scope.newMany = undefined;
			isCreatingStory = false;
			$timeout(makeStoriesDraggable, 0);
		};

		var parseStory = function (line) {
			var story = {};

			line = line.trim();
			if (line.indexOf('--') === 0) {
				story.isDeadline = true;
				// Remove all preceding hyphens,
				// so mileposts denoted with '----'
				// are also possible.
				while (line.indexOf('-') === 0) {
					line = line.substring(1);
				}
				line = line.trim();
			}

			story.summary = line;
			return story;
		};

		var createStory = function (line) {
			if (!line) {
				return done();
			}

			var story = parseStory(line);
			insertNewStory(story, function () {
				lineIndex--;
				if (lineIndex >= 0) {
					createStory(lines[lineIndex]);
				}
				else {
					done();
				}
			});
		};

		createStory(lastLine);
	};

	var scrollToStorySpecifiedByUrl = function () {
		var storyId = $routeParams.storyId;
		if (!storyId) {
			return;
		}

		$scope.$broadcast('scrollToStory', storyId);
	};

	var makeStoriesDraggable = function () {
		$scope.$broadcast('makeStoriesDraggable');
	};

	var addKeyListener = function () {
		$scope.$watch('keyboard.isShiftDown', function (newValue, oldValue) {
			$scope.isAltMode = newValue;
			// UX: Maybe once something is marked as 'isMoving' it
			// should stay that way until the page is revisited. This
			// way people can change their minds on which milestone
			// things go to and it's no big deal.
			//
			// if (!newValue) {
			// 	stories.forEach(function (story) {
			// 		story.isMoving = false;
			// 	});
			// }
		});
	};

	var init = function() {
		$scope.owners = [];

		if (circleId === undefined) {
			// What is happening? Nothing.
			$scope.signOut();
			return;
		}

		var handleInitError = function (data, status) {
			console.log('failure');
			console.log(status);
			console.log(data);

			if (status === 401 && $scope.isSignedIn()) {
				// We're not actually signed in.
				$scope.signOut();
			}
		};

		$http.get('/data/' + circleId + '/first-story')
		.success(function (firstStory) {

			$http.get('/data/' + circleId + '/stories')
			.success(function (serverStories) {
				if ($scope.getAccountName) {
					$scope.accountName = $scope.getAccountName();
				}
				$scope.data = {
					firstStory: firstStory,
					allStories: serverStories,
					circleId: circleId
				};
				$timeout(makeStoriesDraggable, 0);
				scrollToStorySpecifiedByUrl();

				// UX: Hide story-entry panel at first.
				// $timeout(function() {
				// 	$scope.showEntry('many');
				// }, 300);
			})
			.error(handleInitError);

			$http.get("/data/" + circleId + "/members/names")
			.success(function (names) {
				$scope.owners = names;
			})
			.error(handleInitError);

		}).error(handleInitError);

		// $scope.$on('$viewContentLoaded', function (e) {
		// 	activateDragAndDrop();
		// });

		addKeyListener();
	};

	init();
}
HomeCtrl.$inject = ['session', 'hacks',
'$scope', '$timeout', '$http', '$routeParams', '$route'];
<commit_msg>Many entry: Use @ sign for assignment<commit_after>'use strict';

function HomeCtrl(session, hacks, $scope, $timeout, $http, $routeParams, $route) {

	var circleId = session.activeCircle;

	$scope.$on('storyListBroken', function () {
		$scope.isBacklogBroken = true;
	});

	var entryPanel = function () {
		$scope.isAdding = [];
		$scope.isAdding['story'] = false;
		$scope.isAdding['deadline'] = false;

		$scope.showEntry = function (panelName) {
			if (!panelName) {
				$scope.isAddingNew = true;
				$scope.showEntry('story');
				// TODO: Focus for all the story types
				hacks.focus('storyEntry');
			}
			else {
				for (var pName in $scope.isAdding) {
					$scope.isAdding[pName] = false;
				}
				$scope.isAdding[panelName] = true;
				hacks.focus(panelName + 'Entry');
			}
		};

		$scope.hideEntry = function () {
			$scope.isAddingNew = undefined;
		};

		$scope.toggleAltMode = function () {
			if ($scope.isManualAltMode) {
				$scope.isManualAltMode = false;
			}
			else {
				$scope.isManualAltMode = true;
			}
		}
	}();

	var insertNewStory = function (newStory, callback) {
		$scope.$broadcast('insertNewStory', newStory, callback);
	};

	var isCreatingStory = false;
	$scope.create = function (newStory) {
		if (!isCreatingStory && newStory) {
			isCreatingStory = true;
			insertNewStory(newStory, function () {
				$scope.newStory = undefined;
				isCreatingStory = false;
				$timeout(makeStoriesDraggable, 0);
			});
		}
	};

	$scope.createDeadline = function (newDeadline) {
		if (!isCreatingStory && newDeadline) {
			isCreatingStory = true;
			newDeadline.isDeadline = true;
			insertNewStory(newDeadline, function () {
				$scope.newDeadline = undefined;
				isCreatingStory = false;
				$timeout(makeStoriesDraggable, 0);
			});
		}
	};

	$scope.createMany = function (newMany) {
		var input = newMany.txt;
		var lines = input.split('\n');

		if (!lines || lines.length === 0 || isCreatingStory) {
			return;
		}

		isCreatingStory = true;

		var lineIndex = lines.length-1;
		var lastLine = lines[lineIndex];

		var done = function () {
			$scope.newMany = undefined;
			isCreatingStory = false;
			$timeout(makeStoriesDraggable, 0);
		};

		var parseStory = function (line) {
			var story = {};

			line = line.trim();
			// Parse mileposts
			if (line.indexOf('--') === 0) {
				story.isDeadline = true;
				// Remove all preceding hyphens,
				// so mileposts denoted with '----'
				// are also possible.
				while (line.indexOf('-') === 0) {
					line = line.substring(1);
				}
				line = line.trim();
			}

			// Parse owners
			var owners = $scope.owners;
			var ownerFound = false;
			var lowerCaseLine = line.toLowerCase();
			owners.forEach(function (owner) {
				if (ownerFound) {
					return;
				}
				var lowerCaseOwner = owner.toLowerCase();
				// owners start with the @ sign and
				// are at the end of the line
				var ownerIndex = lowerCaseLine.indexOf(lowerCaseOwner);
				if (ownerIndex > 0
					&& line[ownerIndex-1] === '@'
					&& line.length === ownerIndex + owner.length) {
					ownerFound = true;
					story.owner = owner;
					line = line.substring(0, ownerIndex-1).trim();
				}
			});

			story.summary = line;
			return story;
		};

		var createStory = function (line) {
			if (!line) {
				return done();
			}

			var story = parseStory(line);
			insertNewStory(story, function () {
				lineIndex--;
				if (lineIndex >= 0) {
					createStory(lines[lineIndex]);
				}
				else {
					done();
				}
			});
		};

		createStory(lastLine);
	};

	var scrollToStorySpecifiedByUrl = function () {
		var storyId = $routeParams.storyId;
		if (!storyId) {
			return;
		}

		$scope.$broadcast('scrollToStory', storyId);
	};

	var makeStoriesDraggable = function () {
		$scope.$broadcast('makeStoriesDraggable');
	};

	var addKeyListener = function () {
		$scope.$watch('keyboard.isShiftDown', function (newValue, oldValue) {
			$scope.isAltMode = newValue;
			// UX: Maybe once something is marked as 'isMoving' it
			// should stay that way until the page is revisited. This
			// way people can change their minds on which milestone
			// things go to and it's no big deal.
			//
			// if (!newValue) {
			// 	stories.forEach(function (story) {
			// 		story.isMoving = false;
			// 	});
			// }
		});
	};

	var init = function() {
		$scope.owners = [];

		if (circleId === undefined) {
			// What is happening? Nothing.
			$scope.signOut();
			return;
		}

		var handleInitError = function (data, status) {
			console.log('failure');
			console.log(status);
			console.log(data);

			if (status === 401 && $scope.isSignedIn()) {
				// We're not actually signed in.
				$scope.signOut();
			}
		};

		$http.get('/data/' + circleId + '/first-story')
		.success(function (firstStory) {

			$http.get('/data/' + circleId + '/stories')
			.success(function (serverStories) {
				if ($scope.getAccountName) {
					$scope.accountName = $scope.getAccountName();
				}
				$scope.data = {
					firstStory: firstStory,
					allStories: serverStories,
					circleId: circleId
				};
				$timeout(makeStoriesDraggable, 0);
				scrollToStorySpecifiedByUrl();

				// UX: Hide story-entry panel at first.
				// $timeout(function() {
				// 	$scope.showEntry('many');
				// }, 300);
			})
			.error(handleInitError);

			$http.get("/data/" + circleId + "/members/names")
			.success(function (names) {
				$scope.owners = names;
			})
			.error(handleInitError);

		}).error(handleInitError);

		// $scope.$on('$viewContentLoaded', function (e) {
		// 	activateDragAndDrop();
		// });

		addKeyListener();
	};

	init();
}
HomeCtrl.$inject = ['session', 'hacks',
'$scope', '$timeout', '$http', '$routeParams', '$route'];
<|endoftext|>


<commit_before>import Vue from 'vue'
import * as types from './mutation-types'
import OpenTrons from '../rest_api_wrapper'
import {addHrefs} from '../util'

const actions = {
  connect_robot ({ commit }, port) {
    const payload = {is_connected: true, 'port': port}
    OpenTrons.connect(port).then((was_successful) => {
      if (was_successful) commit(types.UPDATE_ROBOT_CONNECTION, payload)
    })
  },
  disconnect_robot ({ commit }) {
    OpenTrons.disconnect().then((was_successful) => {
      if (was_successful) {
        commit(types.UPDATE_ROBOT_CONNECTION, {'is_connected': false, 'port': null})
      }
    })
  },
  updateFilename ({commit}, fileName) {
    commit(types.UPDATE_FILE_NAME, {'fileName': fileName})
  },
  uploadProtocol ({commit}, formData) {
    commit(types.UPDATE_ROBOT_STATE, {'busy': true})
    OpenTrons.uploadProtocol(formData).then((result) =>{
      if (result.success) {
        let tasks = result.calibrations
        addHrefs(tasks)
        commit(types.UPDATE_TASK_LIST, {'tasks': tasks})
      } else {
        commit(types.UPDATE_TASK_LIST, {tasks: []})
      }
      commit(types.UPDATE_WARNINGS, {warning: result.warnings})
      commit(types.UPDATE_ERROR, {errors: result.errors})
      commit(types.UPDATE_ROBOT_STATE, {'busy': false})
    }),
    OpenTrons.getRunPlan().then((plan) => {
      commit(types.UPDATE_RUN_PLAN, {run_plan: plan})
    })
  },
  selectIncrement ({commit}, data) {
    let {inc, type} = data
    commit(types.UPDATE_INCREMENT, { 'current_increment': inc, 'type': type })
  },
  jog ({commit}, coords) {
    commit(types.UPDATE_ROBOT_STATE, {'busy': true})
    OpenTrons.jog(coords).then((result) => {
      commit(types.UPDATE_ROBOT_STATE, {'busy': false})
    })
  },
  jogToSlot ({commit}, data) {
    commit(types.UPDATE_ROBOT_STATE, {'busy': true})
    OpenTrons.jogToSlot(data).then(() => {
      commit(types.UPDATE_ROBOT_STATE, {'busy': false})
    })
  },
  calibrate ({commit}, data) {
    let type = "plunger"
    if (data.slot) { type = "placeable"}
    OpenTrons.calibrate(data, type).then((tasks) => {
      if (tasks) {
        commit('UPDATE_TASK_LIST', {'tasks': tasks})
      }
    })
  },
  moveToPlaceable({commit}, data) {
    commit(types.UPDATE_ROBOT_STATE, {'busy': true})
    Vue.http
    .post('http://localhost:5000/move_to_container', JSON.stringify(data), {emulateJSON: true})
    .then((response) => {
       commit(types.UPDATE_ROBOT_STATE, {'busy': false})
       console.log('success',response)
    }, (response) => {
       commit(types.UPDATE_ROBOT_STATE, {'busy': true})
       console.log('failed', response)
    })
  },
  getRunPlan({ commit }) {
    OpenTrons.getRunPlan().then((results) => {
      commit(types.UPDATE_RUN_PLAN, results)
    })
  },
  runProtocol({ commit }) {
    commit(types.RESET_RUN_LOG)
    commit(types.UPDATE_ROBOT_STATE, {'busy': true})
    OpenTrons.runProtocol().then((results) => {
      commit(types.UPDATE_ROBOT_STATE, {'busy': false})
      // commit(types.UPDATE_RUN_STATE, results)
    })
  },
  pauseProtocol({ commit }) {
    OpenTrons.pauseProtocol().then((results) => {
      console.log(results)
      // commit(types.UPDATE_RUN_STATE, results)
    })
  },
  resumeProtocol({ commit }) {
    OpenTrons.resumeProtocol().then((results) => {
      console.log(results)
      // commit(types.UPDATE_RUN_STATE, results)
    })
  },
  moveToPosition ({commit}, data) {
    let type = "plunger"
    if (data.slot) { type = "placeable" }
    commit(types.UPDATE_ROBOT_STATE, {'busy': true})
    OpenTrons.moveToPosition(data, type).then(() => {
      commit(types.UPDATE_ROBOT_STATE, {'busy': false})
    })
  },
  pickUpTip ({commit}, data) {
    commit(types.UPDATE_ROBOT_STATE, {'busy': true})
    OpenTrons.pickUpTip(data).then(() => {
      commit(types.UPDATE_ROBOT_STATE, {'busy': false})
    })
  },
  dropTip ({commit}, data) {
    OpenTrons.dropTip(data)
  },
  home ({commit}, data) {
    commit(types.UPDATE_ROBOT_STATE, {'busy': true})
    OpenTrons.home(data.axis).then(() => {
      commit(types.UPDATE_ROBOT_STATE, {'busy': false})
    })
  }
}

export default {
  actions
}
<commit_msg>remove comma, function spacing<commit_after>import Vue from 'vue'
import * as types from './mutation-types'
import OpenTrons from '../rest_api_wrapper'
import {addHrefs} from '../util'

const actions = {
  connect_robot ({ commit }, port) {
    const payload = {is_connected: true, 'port': port}
    OpenTrons.connect(port).then((was_successful) => {
      if (was_successful) commit(types.UPDATE_ROBOT_CONNECTION, payload)
    })
  },
  disconnect_robot ({ commit }) {
    OpenTrons.disconnect().then((was_successful) => {
      if (was_successful) {
        commit(types.UPDATE_ROBOT_CONNECTION, {'is_connected': false, 'port': null})
      }
    })
  },
  updateFilename ({commit}, fileName) {
    commit(types.UPDATE_FILE_NAME, {'fileName': fileName})
  },
  uploadProtocol ({commit}, formData) {
    commit(types.UPDATE_ROBOT_STATE, {'busy': true})
    OpenTrons.uploadProtocol(formData).then((result) => {
      if (result.success) {
        let tasks = result.calibrations
        addHrefs(tasks)
        commit(types.UPDATE_TASK_LIST, {'tasks': tasks})
      } else {
        commit(types.UPDATE_TASK_LIST, {tasks: []})
      }
      commit(types.UPDATE_WARNINGS, {warning: result.warnings})
      commit(types.UPDATE_ERROR, {errors: result.errors})
      commit(types.UPDATE_ROBOT_STATE, {'busy': false})
    })
    OpenTrons.getRunPlan().then((plan) => {
      commit(types.UPDATE_RUN_PLAN, {run_plan: plan})
    })
  },
  selectIncrement ({commit}, data) {
    let {inc, type} = data
    commit(types.UPDATE_INCREMENT, { 'current_increment': inc, 'type': type })
  },
  jog ({commit}, coords) {
    commit(types.UPDATE_ROBOT_STATE, {'busy': true})
    OpenTrons.jog(coords).then((result) => {
      commit(types.UPDATE_ROBOT_STATE, {'busy': false})
    })
  },
  jogToSlot ({commit}, data) {
    commit(types.UPDATE_ROBOT_STATE, {'busy': true})
    OpenTrons.jogToSlot(data).then(() => {
      commit(types.UPDATE_ROBOT_STATE, {'busy': false})
    })
  },
  calibrate ({commit}, data) {
    let type = "plunger"
    if (data.slot) { type = "placeable"}
    OpenTrons.calibrate(data, type).then((tasks) => {
      if (tasks) {
        commit('UPDATE_TASK_LIST', {'tasks': tasks})
      }
    })
  },
  moveToPlaceable({commit}, data) {
    commit(types.UPDATE_ROBOT_STATE, {'busy': true})
    Vue.http
    .post('http://localhost:5000/move_to_container', JSON.stringify(data), {emulateJSON: true})
    .then((response) => {
       commit(types.UPDATE_ROBOT_STATE, {'busy': false})
       console.log('success',response)
    }, (response) => {
       commit(types.UPDATE_ROBOT_STATE, {'busy': true})
       console.log('failed', response)
    })
  },
  getRunPlan({ commit }) {
    OpenTrons.getRunPlan().then((results) => {
      commit(types.UPDATE_RUN_PLAN, results)
    })
  },
  runProtocol({ commit }) {
    commit(types.RESET_RUN_LOG)
    commit(types.UPDATE_ROBOT_STATE, {'busy': true})
    OpenTrons.runProtocol().then((results) => {
      commit(types.UPDATE_ROBOT_STATE, {'busy': false})
      // commit(types.UPDATE_RUN_STATE, results)
    })
  },
  pauseProtocol({ commit }) {
    OpenTrons.pauseProtocol().then((results) => {
      console.log(results)
      // commit(types.UPDATE_RUN_STATE, results)
    })
  },
  resumeProtocol({ commit }) {
    OpenTrons.resumeProtocol().then((results) => {
      console.log(results)
      // commit(types.UPDATE_RUN_STATE, results)
    })
  },
  moveToPosition ({commit}, data) {
    let type = "plunger"
    if (data.slot) { type = "placeable" }
    commit(types.UPDATE_ROBOT_STATE, {'busy': true})
    OpenTrons.moveToPosition(data, type).then(() => {
      commit(types.UPDATE_ROBOT_STATE, {'busy': false})
    })
  },
  pickUpTip ({commit}, data) {
    commit(types.UPDATE_ROBOT_STATE, {'busy': true})
    OpenTrons.pickUpTip(data).then(() => {
      commit(types.UPDATE_ROBOT_STATE, {'busy': false})
    })
  },
  dropTip ({commit}, data) {
    OpenTrons.dropTip(data)
  },
  home ({commit}, data) {
    commit(types.UPDATE_ROBOT_STATE, {'busy': true})
    OpenTrons.home(data.axis).then(() => {
      commit(types.UPDATE_ROBOT_STATE, {'busy': false})
    })
  }
}

export default {
  actions
}
<|endoftext|>


<commit_before>(function(){
  function seekBar($document){

    var calculatePercent = function(seekBar, event){
      var offsetX = event.pageX - seekBar.offset().left;
      var seekBarWidth = seekBar.width();
      var offsetXPercent = offsetX / seekBarWidth;
      offsetXPercent = Math.max(0, offsetXPercent);
      offsetXPercent = Math.min(1, offsetXPercent);
      return offsetXPercent;
    };

    return {
      templateUrl: '../templates/directives/seek_bar.html',
      replace: true,
      restrict: 'E',
      scope: {
        onChange: '&'
      },
      link: function(scope, element, attributes){
        scope.value = 0;
        scope.max = 100;

        var seekBar = $(element);

        attributes.$observe('value', function(newValue){
          scope.value = newValue;
        });

        attributes.$observe('max', function(newValue){
          scope.max = newValue;
        });

        var percentString = function(){
          var value = scope.value;
          var max = scope.max;
          var percent = value / max * 100;
          return percent + '%';
        };

        scope.fillStyle = function(){
          return {width: percentString()};
        };

        scope.thumbStyle = function(){
          return {left: percentString()};
        };

        var notifyOnChange = function(newValue){
          if(typeof scope.onChange === 'function'){
            scope.onChange({value: newValue});
          }
        };

        scope.onClickSeekBar = function(event){
          var percent = calculatePercent(seekBar, event);
          scope.value = percent * scope.max;
          notifyOnChange(scope.value);
        };

        scope.trackThumb = function(){
          $document.bind('mousemove.thumb', function(event){
            var percent = calculatePercent(seekBar, event);
            scope.$apply(function(){
              scope.value = percent * scope.max;
              notifyOnChange(scope.value);
            });
          });

          $document.bind('mouseup.thumb', function(){
            $document.unbind('mousemove.thumb');
            $document.unbind('mouseup.thumb');
          });
        };
      }
    };
  }

  angular
    .module('blocJams')
    .directive('seekBar', ['$document', seekBar]);
})();<commit_msg>placed notifyOnChange function in the correct spot<commit_after>(function(){
  function seekBar($document){

    var calculatePercent = function(seekBar, event){
      var offsetX = event.pageX - seekBar.offset().left;
      var seekBarWidth = seekBar.width();
      var offsetXPercent = offsetX / seekBarWidth;
      offsetXPercent = Math.max(0, offsetXPercent);
      offsetXPercent = Math.min(1, offsetXPercent);
      return offsetXPercent;
    };

    return {
      templateUrl: '../templates/directives/seek_bar.html',
      replace: true,
      restrict: 'E',
      scope: {
        onChange: '&'
      },
      link: function(scope, element, attributes){
        scope.value = 0;
        scope.max = 100;

        var seekBar = $(element);

        attributes.$observe('value', function(newValue){
          scope.value = newValue;
        });

        attributes.$observe('max', function(newValue){
          scope.max = newValue;
        });

        var percentString = function(){
          var value = scope.value;
          var max = scope.max;
          var percent = value / max * 100;
          return percent + '%';
        };

        scope.fillStyle = function(){
          return {width: percentString()};
        };

        scope.thumbStyle = function(){
          return {left: percentString()};
        };

        scope.onClickSeekBar = function(event){
          var percent = calculatePercent(seekBar, event);
          scope.value = percent * scope.max;
          notifyOnChange(scope.value);
        };

        scope.trackThumb = function(){
          $document.bind('mousemove.thumb', function(event){
            var percent = calculatePercent(seekBar, event);
            scope.$apply(function(){
              scope.value = percent * scope.max;
              notifyOnChange(scope.value);
            });
          });

          $document.bind('mouseup.thumb', function(){
            $document.unbind('mousemove.thumb');
            $document.unbind('mouseup.thumb');
          });
        };

        var notifyOnChange = function(newValue){
          if(typeof scope.onChange === 'function'){
            scope.onChange({value: newValue});
          }
        };

      }
    };
  }

  angular
    .module('blocJams')
    .directive('seekBar', ['$document', seekBar]);
})();<|endoftext|>


<commit_before>'use strict';

/**
 * @ngdoc function
 * @name learningApp.services:roll
 * @description
 * # services
 * services for learning app
 */
var services = angular.module('services', []);

function AddRoll(number, sizeOfDice, add, title) {
  var self = this;
  this.rolls = [];
  this.add = function(number, sizeOfDice, add, title) {
    self.rolls.push(new AddRoll(number, sizeOfDice, add, title));
  };
  this.title = title || 'Title';
  this.number = number || 1;
  this.sizeOfDice = sizeOfDice || 6;
  this.addValue = add || 0;
  this.rollDice = function() {
  this.__type__ = 'AddRoll';
    var result = 0;
    var results=[];
    for (var i = 0; i < this.number; i++) {
      var roll = Math.floor(Math.random() * this.sizeOfDice) + 1;
      result += roll;
      results.push(roll);
    }
    this.results = results;
    this.result = result + this.addValue;
    return this;
  };
  this.remove = function(index) {
    self.rolls.splice(index, 1);
  };
  this.get = function(index) {
    return self.rolls[index];
  };

}

function MakeRoll() {
  var self = this;
  this.print = function() {
    console.log(self.toJson());
  };
  this.toJson = function() {
    return JSON.stringify(self.rolls);
  };

  this.fromJson = function(value) {
    var revive = function (key, value) {
      if (value.hasOwnProperty('__type__') && value.__type__ === 'AddRoll' ) {
        return new AddRoll(value.number, value.sizeOfDice, value.addValue, value.title);
      }
      return value;
    };
    return JSON.parse(value, revive);
  };
  this.__type__ = 'MakeRoll';
}

MakeRoll.prototype = new AddRoll();

services.factory('Roll', [function() {
  return new MakeRoll();
}
]);
<commit_msg>move location of this.__type__<commit_after>'use strict';

/**
 * @ngdoc function
 * @name learningApp.services:roll
 * @description
 * # services
 * services for learning app
 */
var services = angular.module('services', []);

function AddRoll(number, sizeOfDice, add, title) {
  var self = this;
  this.rolls = [];
  this.add = function(number, sizeOfDice, add, title) {
    self.rolls.push(new AddRoll(number, sizeOfDice, add, title));
  };
  this.title = title || 'Title';
  this.number = number || 1;
  this.sizeOfDice = sizeOfDice || 6;
  this.addValue = add || 0;
  this.__type__ = 'AddRoll';
  this.rollDice = function() {
    var result = 0;
    var results=[];
    for (var i = 0; i < this.number; i++) {
      var roll = Math.floor(Math.random() * this.sizeOfDice) + 1;
      result += roll;
      results.push(roll);
    }
    this.results = results;
    this.result = result + this.addValue;
    return this;
  };
  this.remove = function(index) {
    self.rolls.splice(index, 1);
  };
  this.get = function(index) {
    return self.rolls[index];
  };

}

function MakeRoll() {
  var self = this;
  this.print = function() {
    console.log(self.serialize());
  };
  this.serialize = function() {
    return JSON.stringify(self.rolls);
  };

  this.deserialize = function(value) {
    var revive = function (key, value) {
      if (value.hasOwnProperty('__type__') && value.__type__ === 'AddRoll' ) {
        return new AddRoll(value.number, value.sizeOfDice, value.addValue, value.title);
      }
      return value;
    };
    self.rolls = JSON.parse(value, revive);
    return self.rolls;
  };
  this.__type__ = 'MakeRoll';
}

MakeRoll.prototype = new AddRoll();

services.factory('Roll', [function() {
  return new MakeRoll();
}
]);
<|endoftext|>


<commit_before>'use strict';

var Reflux = require('reflux');
var config = require('../config/config.js');
var filterTransforms = require('../config/filterTransforms.js');
var FilterStateActions = require('../actions/filterState.js');
var dataSourceStore = require('../stores/dataSource.js');
var eventsStore = require('../stores/events.js');
var placesStore = require('../stores/places.js');
var peopleStore = require('../stores/people.js');
var sourcesStore = require('../stores/source.js');

module.exports = Reflux.createStore({

  // this will set up listeners to all publishers in FilterStateActions,
  // using onKeyname (or keyname) as callbacks
  listenables: [FilterStateActions],

  init: function() {
    this.transformName = 'ViewingFilter';

    // Arrays to keep track of selected related documents in each data store
    this.selectedEventDocuments = [];
    this.selectedPeopleDocuments = [];
    this.selectedPlaceDocuments = [];

    // Register dataSourceStores's changes
    this.listenTo(dataSourceStore, this.dataSourceChanged);
  },

  // Set the filteredData Object
  dataSourceChanged: function () {

    // When the userFilteredCollection has been created on each data store, we can call the autoFilterCollections
    // method
    this.autoFilterCollections(false);
  },

  // Set search filter on our collectionTransform
  searchFilterChanged: function(searchFilterObject) {

    this.updateFilteredData(searchFilterObject);

    // When the userFilteredCollection has been created on each data store, we can call the autoFilterCollections
    // method
    this.autoFilterCollections(true);
  },

  // Set simpleSort on our collectionTransform
  sortingChanged: function(sortingObject) {

    this.updateSortedData(sortingObject);

    // When the userFilteredCollection has been created on each data store, we can call the autoFilterCollections
    // method
    this.autoFilterCollections(false);
  },

  // Update filtered data based on the collection
  // ToDo: Need to make this dynamic based on passed in fields
  updateFilteredData: function(searchFilterObject) {

    switch (searchFilterObject.collectionName) {
      case config.EventsCollection:
        filterTransforms[config.EventsCollection].filters = this.createFilterObject(searchFilterObject);
        break;
      case config.PlacesCollection:
        filterTransforms[config.PlacesCollection].filters = this.createFilterObject(searchFilterObject);
        break;
      case config.PeopleCollection:
        filterTransforms[config.PeopleCollection].filters = this.createFilterObject(searchFilterObject);
        break;
      case config.SourcesCollection:
        filterTransforms[config.SourcesCollection].filters = this.createFilterObject(searchFilterObject);
        break;
      default:
        console.error('No collection Name');
    }
  },

  // Update sorted data based on the collection
  // ToDo: Need to make this dynamic based on passed in fields
  updateSortedData: function(sortingObject) {

    switch (sortingObject.collectionName) {
      case config.EventsCollection:
        filterTransforms[config.EventsCollection].sorting = this.createSortingObject(sortingObject);
        break;
      case config.PlacesCollection:
        filterTransforms[config.PlacesCollection].sorting = this.createSortingObject(sortingObject);
        break;
      case config.PeopleCollection:
        filterTransforms[config.PeopleCollection].sorting = this.createSortingObject(sortingObject);
        break;
      case config.SourcesCollection:
        filterTransforms[config.SourcesCollection].sorting = this.createSortingObject(sortingObject);
        break;
      default:
        console.error('No collection Name');
    }
  },

  // Create a filter transform object from a filter Object
  createFilterObject: function(searchFilterObject) {

    var transform = {
      type: 'find',
      value: {
        $and: []
      }
    };

    searchFilterObject.fields.forEach(function (field) {

      var fieldObject = {};
      var queryObject = {};

      if (field.queryType !== 'regex') {
        queryObject[field.queryType] = field.value;
      } else {
        queryObject.$regex = [field.value, 'i'];
      }

      fieldObject[field.name] = queryObject;

      transform.value.$and.push(fieldObject);
    });

    return transform;
  },

  // Create a sorting transform object from a sorting Object
  createSortingObject: function(sortingObject) {

    var transform = {
      type: 'simplesort',
      property: sortingObject.fieldName,
      desc: sortingObject.desc
    };

    return transform;
  },

  // Triggered when a package is chosen to be viewed or edited
  packageSelected: function(presentationName) {

    // Call filterStateChanged on each data store
    eventsStore.filterStateChanged(presentationName);
    placesStore.filterStateChanged(presentationName);
    peopleStore.filterStateChanged(presentationName);
    sourcesStore.filterStateChanged(presentationName);
  },

  // Filter on datastore userFilteredCollections based on linkage rules between tables
  // Event Place field links to Places Shortname field
  // Event Suspects, Victims and Witnesses fields link to People's Shortname field
  autoFilterCollections: function(autoSelectCheckBoxes) {

    var eventsCollection = dataSourceStore.dataSource.getCollection(app.config.EventsCollection);

    // Manage the filter transform name in this store and listening collection
    // stores can use it when broadcasted
    filterTransforms.transformName = this.transformName;

    // Call filterStateChanged on each data store to ensure each store's userFilteredCollection is up to date
    eventsStore.filterStateChanged(filterTransforms);
    placesStore.filterStateChanged(filterTransforms);
    peopleStore.filterStateChanged(filterTransforms);
    sourcesStore.filterStateChanged(filterTransforms);

    // Set all event record's 'showRecord' properties that have been filtered out, to false
    eventsStore.setFilteredOutItemsToNotSelected(eventsCollection.data, eventsStore.userFilteredCollection.data());

    // Update all data types checkboxes to only show records from filtered records
    this.eventsCheckBoxUpdated(eventsCollection.data);

    // Update all Event Checkboxes
    if (autoSelectCheckBoxes) {
      this.selectAllCheckboxes(eventsStore, true);
    }

    // Pass data onto views
    eventsStore.trigger(eventsStore.userFilteredCollection.data());
    placesStore.trigger(placesStore.userFilteredCollection.data());
    peopleStore.trigger(peopleStore.userFilteredCollection.data());
    sourcesStore.trigger(sourcesStore);

    this.message = {
      type: 'userFilteredCollectionsUpdated'
    };

    this.trigger(this);
  },

  // Select all checkboxes in a store
  selectAllCheckboxes: function(store, value) {
    store.showAllSelected = value;

    // Set all records showRecord property to true
    eventsStore.userFilteredCollection.update(function (sourceObject) {
      sourceObject.showRecord = true;
    });
  },

  // Update showRecord property of collections
  checkBoxUpdated: function(showRecordObject) {

    switch(showRecordObject.collectionName) {
      case config.EventsCollection:

        // Start process of updating related data tables
        this.eventsCheckBoxUpdated(showRecordObject.collectionData);

        // Set property on the events store so the show All checkbox state will be maintained
        eventsStore.showAllSelected = showRecordObject.showAllSelected;

        break;
      case config.PlacesCollection:

        // Set property on the events store so the show All checkbox state will be maintained
        placesStore.showAllSelected = showRecordObject.showAllSelected;

        break;
      case config.PeopleCollection:

        // Set property on the events store so the show All checkbox state will be maintained
        peopleStore.showAllSelected = showRecordObject.showAllSelected;

        break;
      case config.SourcesCollection:

        // Set property on the events store so the show All checkbox state will be maintained
        sourcesStore.showAllSelected = showRecordObject.showAllSelected;

        break;
      default:
    }
  },

  // Auto Update the Places, People and Sources selected records
  eventsCheckBoxUpdated: function(collectionData) {

    // Manage the Source Collection Selected Records that are related to Event Supporting Documents
    collectionData.forEach(function(eventObject) {
      this.autoUpdateSourceCheckboxes(eventObject, config.EventsCollection);
    }.bind(this));

    // Auto Update related Place checkboxes
    this.autoUpdatePlacesCheckboxes(collectionData);

    // Auto Update related People checkboxes
    this.autoUpdatePeopleCheckboxes(collectionData);
  },

  // Iterate through each record in Places collection and set showRecord to true and selectedByEvent to true
  autoUpdatePlacesCheckboxes: function(itemArray) {

    // Used to keep track of places in case the same place is is used by an event record that isn't set to show and
    // then removes it from being set by a previous event which was set to show.
    var placeArray = [];

    itemArray.forEach(function(eventObject) {

      placesStore.userFilteredCollection.copy().find({
        'Short Name': {
          '$eq' : eventObject.Place
        }
      }).update(function(placeObject) {

        // If the event record is selected
        if (eventObject.showRecord) {
          placeArray.push(placeObject);
          placeObject.showRecord = true;
          placeObject.selectedByEvent = true;
          placeObject.highlightAsRelatedToEvent = true;
        } else {
          if (placeArray.indexOf(placeObject) === -1) {
            placeObject.showRecord = false;
            placeObject.selectedByEvent = false;
            placeObject.highlightAsRelatedToEvent = false;
          }
        }

        // Manage the Source Collection Selected Records
        this.autoUpdateSourceCheckboxes(placeObject, config.PlacesCollection);

      }.bind(this));
    }.bind(this));
  },

  // Find each record in People collection where People matches a person in Events collection and set showRecord,
  // selectedByEvent and highlightAsRelatedToEvent properties
  autoUpdatePeopleCheckboxes: function(itemArray) {

    // Helper methods for parsing People fields
    var filterSelected = function (item) {
      return item.showRecord === true;
    };

    var filterNonSelected = function (item) {
      return item.showRecord === false;
    };

    var split = function (item) {
      return _.union(item.Suspects.split(','), item.Victims.split(','), item.Witnesses.split(','));
    };

    var trim = function (item) {
      return item.trim();
    };

    // Parse People fields into single array of unique related people
    var relatedPeopleArray = _.uniq(_.map(_.flatten(_.map(_.filter(itemArray, filterSelected), split)), trim));

    // Parse People fields into single array of unique non related people
    var nonRelatedPeopleArray = _.difference(_.uniq(_.map(_.flatten(_.map(_.filter(itemArray, filterNonSelected), split)), trim)), relatedPeopleArray);

    // Update all People from the relatedPeople array to show
    relatedPeopleArray.forEach(function (person) {
      peopleStore.userFilteredCollection.copy().find({
        'Short Name': {
          '$eq': person
        }
      }).update(function (personObject) {

        personObject.showRecord = true;
        personObject.selectedByEvent = true;
        personObject.highlightAsRelatedToEvent = true;

        // Manage the Source Collection Selected Records
        this.autoUpdateSourceCheckboxes(personObject, config.PeopleCollection);

      }.bind(this));
    }.bind(this));

    // Update all People from the nonRelatedPeople array to not show
    nonRelatedPeopleArray.forEach(function (person) {
      peopleStore.userFilteredCollection.copy().find({
        'Short Name': {
          '$eq': person
        }
      }).update(function (personObject) {

        personObject.showRecord = false;
        personObject.selectedByEvent = false;
        personObject.highlightAsRelatedToEvent = false;

        // Manage the Source Collection Selected Records
        this.autoUpdateSourceCheckboxes(personObject, config.PeopleCollection);

      }.bind(this));
    }.bind(this));
  },

  // Add or remove Supporting Documents to each data type's array to work out whether to show a Source Record or not
  autoUpdateSourceCheckboxes: function(item, dataType) {

    var mergedObjectArray;
    var relatedSourceArray = [];

    // Helper methods for parsing Source records
    var trim = function (item) {
      if (item) {
        return item.trim();
      }
    };

    // Manage each data type's array
    switch(dataType) {
      case config.EventsCollection:
        if (item.showRecord === true && item['Supporting Documents']) {
          item.selectedByEvent = true;
          //this.selectedEventDocuments = this.selectedEventDocuments.concat(_.flatten(_.map(item['Supporting Documents'].split(','), trim)));
          this.selectedEventDocuments.push(item);
        } else {
          item.selectedByEvent = false;
          _.remove(this.selectedEventDocuments, item);
        }
        break;
      case config.PlacesCollection:
        if (item.showRecord === true && item['Supporting Documents']) {
          item.selectedByPlace = true;
          //this.selectedPlaceDocuments = this.selectedPlaceDocuments.concat(_.flatten(_.map(item['Supporting Documents'].split(','), trim)));
          this.selectedPlaceDocuments.push(item);
        } else {
          item.selectedByPlace = false;
          _.remove(this.selectedPlaceDocuments, item);
        }
        break;
      case config.PeopleCollection:
        if (item.showRecord === true && item['Supporting Documents']) {
          item.selectedByPeople = true;
          //this.selectedPeopleDocuments = this.selectedPeopleDocuments.concat(_.flatten(_.map(item['Supporting Documents'].split(','), trim)));
          this.selectedPeopleDocuments.push(item);
        } else {
          item.selectedByPeople = false;
          _.remove(this.selectedPeopleDocuments, item);
        }
        break;
      default:
    }

    // Created array of related source shortnames to match
    mergedObjectArray = _.union(this.selectedEventDocuments, this.selectedPlaceDocuments, this.selectedPeopleDocuments);

    mergedObjectArray.forEach(function(item) {
      relatedSourceArray.push(_.map(item['Supporting Documents'].toString().split(','), trim));
    });

    relatedSourceArray = _.uniq(_.flatten(relatedSourceArray));

    // Update related source records to show
    sourcesStore.userFilteredCollection.copy().where(function(sourceObject) {
        return relatedSourceArray.indexOf(sourceObject['Short Name'].toString()) !== -1;
      })
      .update(function (sourceObject) {
        sourceObject.showRecord = true;
        sourceObject.selectedByEvent = true;
        sourceObject.highlightAsRelatedToEvent = true;
    });

    // Update non related source records to not show
    sourcesStore.userFilteredCollection.copy().data().forEach(function(item) {

      var itemArray = [];

      relatedSourceArray.forEach(function(sourceName) {
        if (item['Short Name'].toString() === sourceName) {
          itemArray.push(item);
        }
      });

      if (!itemArray.length) {
        item.showRecord = false;
        item.selectedByEvent = false;
        item.highlightAsRelatedToEvent = false;
      }
    });
  }
});
<commit_msg>Sources updating when Places and People manually selected<commit_after>'use strict';

var Reflux = require('reflux');
var config = require('../config/config.js');
var filterTransforms = require('../config/filterTransforms.js');
var FilterStateActions = require('../actions/filterState.js');
var dataSourceStore = require('../stores/dataSource.js');
var eventsStore = require('../stores/events.js');
var placesStore = require('../stores/places.js');
var peopleStore = require('../stores/people.js');
var sourcesStore = require('../stores/source.js');

module.exports = Reflux.createStore({

  // this will set up listeners to all publishers in FilterStateActions,
  // using onKeyname (or keyname) as callbacks
  listenables: [FilterStateActions],

  init: function() {
    this.transformName = 'ViewingFilter';

    // Arrays to keep track of selected related documents in each data store
    this.selectedEventDocuments = [];
    this.selectedPeopleDocuments = [];
    this.selectedPlaceDocuments = [];

    // Register dataSourceStores's changes
    this.listenTo(dataSourceStore, this.dataSourceChanged);
  },

  // Set the filteredData Object
  dataSourceChanged: function () {

    // When the userFilteredCollection has been created on each data store, we can call the autoFilterCollections
    // method
    this.autoFilterCollections(false);
  },

  // Set search filter on our collectionTransform
  searchFilterChanged: function(searchFilterObject) {

    this.updateFilteredData(searchFilterObject);

    // When the userFilteredCollection has been created on each data store, we can call the autoFilterCollections
    // method
    this.autoFilterCollections(true);
  },

  // Set simpleSort on our collectionTransform
  sortingChanged: function(sortingObject) {

    this.updateSortedData(sortingObject);

    // When the userFilteredCollection has been created on each data store, we can call the autoFilterCollections
    // method
    this.autoFilterCollections(false);
  },

  // Update filtered data based on the collection
  // ToDo: Need to make this dynamic based on passed in fields
  updateFilteredData: function(searchFilterObject) {

    switch (searchFilterObject.collectionName) {
      case config.EventsCollection:
        filterTransforms[config.EventsCollection].filters = this.createFilterObject(searchFilterObject);
        break;
      case config.PlacesCollection:
        filterTransforms[config.PlacesCollection].filters = this.createFilterObject(searchFilterObject);
        break;
      case config.PeopleCollection:
        filterTransforms[config.PeopleCollection].filters = this.createFilterObject(searchFilterObject);
        break;
      case config.SourcesCollection:
        filterTransforms[config.SourcesCollection].filters = this.createFilterObject(searchFilterObject);
        break;
      default:
        console.error('No collection Name');
    }
  },

  // Update sorted data based on the collection
  // ToDo: Need to make this dynamic based on passed in fields
  updateSortedData: function(sortingObject) {

    switch (sortingObject.collectionName) {
      case config.EventsCollection:
        filterTransforms[config.EventsCollection].sorting = this.createSortingObject(sortingObject);
        break;
      case config.PlacesCollection:
        filterTransforms[config.PlacesCollection].sorting = this.createSortingObject(sortingObject);
        break;
      case config.PeopleCollection:
        filterTransforms[config.PeopleCollection].sorting = this.createSortingObject(sortingObject);
        break;
      case config.SourcesCollection:
        filterTransforms[config.SourcesCollection].sorting = this.createSortingObject(sortingObject);
        break;
      default:
        console.error('No collection Name');
    }
  },

  // Create a filter transform object from a filter Object
  createFilterObject: function(searchFilterObject) {

    var transform = {
      type: 'find',
      value: {
        $and: []
      }
    };

    searchFilterObject.fields.forEach(function (field) {

      var fieldObject = {};
      var queryObject = {};

      if (field.queryType !== 'regex') {
        queryObject[field.queryType] = field.value;
      } else {
        queryObject.$regex = [field.value, 'i'];
      }

      fieldObject[field.name] = queryObject;

      transform.value.$and.push(fieldObject);
    });

    return transform;
  },

  // Create a sorting transform object from a sorting Object
  createSortingObject: function(sortingObject) {

    var transform = {
      type: 'simplesort',
      property: sortingObject.fieldName,
      desc: sortingObject.desc
    };

    return transform;
  },

  // Triggered when a package is chosen to be viewed or edited
  packageSelected: function(presentationName) {

    // Call filterStateChanged on each data store
    eventsStore.filterStateChanged(presentationName);
    placesStore.filterStateChanged(presentationName);
    peopleStore.filterStateChanged(presentationName);
    sourcesStore.filterStateChanged(presentationName);
  },

  // Filter on datastore userFilteredCollections based on linkage rules between tables
  // Event Place field links to Places Shortname field
  // Event Suspects, Victims and Witnesses fields link to People's Shortname field
  autoFilterCollections: function(autoSelectCheckBoxes) {

    var eventsCollection = dataSourceStore.dataSource.getCollection(app.config.EventsCollection);

    // Manage the filter transform name in this store and listening collection
    // stores can use it when broadcasted
    filterTransforms.transformName = this.transformName;

    // Call filterStateChanged on each data store to ensure each store's userFilteredCollection is up to date
    eventsStore.filterStateChanged(filterTransforms);
    placesStore.filterStateChanged(filterTransforms);
    peopleStore.filterStateChanged(filterTransforms);
    sourcesStore.filterStateChanged(filterTransforms);

    // Set all event record's 'showRecord' properties that have been filtered out, to false
    eventsStore.setFilteredOutItemsToNotSelected(eventsCollection.data, eventsStore.userFilteredCollection.data());

    // Update all data types checkboxes to only show records from filtered records
    this.eventsCheckBoxUpdated(eventsCollection.data);

    // Update all Event Checkboxes
    if (autoSelectCheckBoxes) {
      this.selectAllCheckboxes(eventsStore, true);
    }

    // Pass data onto views
    eventsStore.trigger(eventsStore.userFilteredCollection.data());
    placesStore.trigger(placesStore.userFilteredCollection.data());
    peopleStore.trigger(peopleStore.userFilteredCollection.data());
    sourcesStore.trigger(sourcesStore);

    this.message = {
      type: 'userFilteredCollectionsUpdated'
    };

    this.trigger(this);
  },

  // Select all checkboxes in a store
  selectAllCheckboxes: function(store, value) {
    store.showAllSelected = value;

    // Set all records showRecord property to true
    eventsStore.userFilteredCollection.update(function (sourceObject) {
      sourceObject.showRecord = true;
    });
  },

  // Update showRecord property of collections
  checkBoxUpdated: function(showRecordObject) {

    switch(showRecordObject.collectionName) {
      case config.EventsCollection:

        // Start process of updating related data tables
        this.eventsCheckBoxUpdated(showRecordObject.collectionData);

        // Set property on the events store so the show All checkbox state will be maintained
        eventsStore.showAllSelected = showRecordObject.showAllSelected;

        break;
      case config.PlacesCollection:

        // Manage the Source Collection Selected Records
        if (showRecordObject.item) {
          this.autoUpdateSourceCheckboxes(showRecordObject.item, config.PlacesCollection);
        }

        // Set property on the events store so the show All checkbox state will be maintained
        placesStore.showAllSelected = showRecordObject.showAllSelected;

        break;
      case config.PeopleCollection:

        // Manage the Source Collection Selected Records
        if (showRecordObject.item) {
          this.autoUpdateSourceCheckboxes(showRecordObject.item, config.PeopleCollection);
        }

        // Set property on the events store so the show All checkbox state will be maintained
        peopleStore.showAllSelected = showRecordObject.showAllSelected;

        break;
      case config.SourcesCollection:

        // Set property on the events store so the show All checkbox state will be maintained
        sourcesStore.showAllSelected = showRecordObject.showAllSelected;

        break;
      default:
    }
  },

  // Auto Update the Places, People and Sources selected records
  eventsCheckBoxUpdated: function(collectionData) {

    // Manage the Source Collection Selected Records that are related to Event Supporting Documents
    collectionData.forEach(function(eventObject) {
      this.autoUpdateSourceCheckboxes(eventObject, config.EventsCollection);
    }.bind(this));

    // Auto Update related Place checkboxes
    this.autoUpdatePlacesCheckboxes(collectionData);

    // Auto Update related People checkboxes
    this.autoUpdatePeopleCheckboxes(collectionData);
  },

  // Iterate through each record in Places collection and set showRecord to true and selectedByEvent to true
  autoUpdatePlacesCheckboxes: function(itemArray) {

    // Used to keep track of places in case the same place is is used by an event record that isn't set to show and
    // then removes it from being set by a previous event which was set to show.
    var placeArray = [];

    itemArray.forEach(function(eventObject) {

      placesStore.userFilteredCollection.copy().find({
        'Short Name': {
          '$eq' : eventObject.Place
        }
      }).update(function(placeObject) {

        // If the event record is selected
        if (eventObject.showRecord) {
          placeArray.push(placeObject);
          placeObject.showRecord = true;
          placeObject.selectedByEvent = true;
          placeObject.highlightAsRelatedToEvent = true;
        } else {
          if (placeArray.indexOf(placeObject) === -1) {
            placeObject.showRecord = false;
            placeObject.selectedByEvent = false;
            placeObject.highlightAsRelatedToEvent = false;
          }
        }

        // Manage the Source Collection Selected Records
        this.autoUpdateSourceCheckboxes(placeObject, config.PlacesCollection);

      }.bind(this));
    }.bind(this));
  },

  // Find each record in People collection where People matches a person in Events collection and set showRecord,
  // selectedByEvent and highlightAsRelatedToEvent properties
  autoUpdatePeopleCheckboxes: function(itemArray) {

    // Helper methods for parsing People fields
    var filterSelected = function (item) {
      return item.showRecord === true;
    };

    var filterNonSelected = function (item) {
      return item.showRecord === false;
    };

    var split = function (item) {
      return _.union(item.Suspects.split(','), item.Victims.split(','), item.Witnesses.split(','));
    };

    var trim = function (item) {
      return item.trim();
    };

    // Parse People fields into single array of unique related people
    var relatedPeopleArray = _.uniq(_.map(_.flatten(_.map(_.filter(itemArray, filterSelected), split)), trim));

    // Parse People fields into single array of unique non related people
    var nonRelatedPeopleArray = _.difference(_.uniq(_.map(_.flatten(_.map(_.filter(itemArray, filterNonSelected), split)), trim)), relatedPeopleArray);

    // Update all People from the relatedPeople array to show
    relatedPeopleArray.forEach(function (person) {
      peopleStore.userFilteredCollection.copy().find({
        'Short Name': {
          '$eq': person
        }
      }).update(function (personObject) {

        personObject.showRecord = true;
        personObject.selectedByEvent = true;
        personObject.highlightAsRelatedToEvent = true;

        // Manage the Source Collection Selected Records
        this.autoUpdateSourceCheckboxes(personObject, config.PeopleCollection);

      }.bind(this));
    }.bind(this));

    // Update all People from the nonRelatedPeople array to not show
    nonRelatedPeopleArray.forEach(function (person) {
      peopleStore.userFilteredCollection.copy().find({
        'Short Name': {
          '$eq': person
        }
      }).update(function (personObject) {

        personObject.showRecord = false;
        personObject.selectedByEvent = false;
        personObject.highlightAsRelatedToEvent = false;

        // Manage the Source Collection Selected Records
        this.autoUpdateSourceCheckboxes(personObject, config.PeopleCollection);

      }.bind(this));
    }.bind(this));
  },

  // Add or remove Supporting Documents to each data type's array to work out whether to show a Source Record or not
  autoUpdateSourceCheckboxes: function(item, dataType) {

    var mergedObjectArray;
    var relatedSourceArray = [];

    // Helper methods for parsing Source records
    var trim = function (item) {
      if (item) {
        return item.trim();
      }
    };

    // Manage each data type's array
    switch(dataType) {
      case config.EventsCollection:
        if (item.showRecord === true && item['Supporting Documents']) {
          item.selectedByEvent = true;
          this.selectedEventDocuments.push(item);
        } else {
          item.selectedByEvent = false;
          _.remove(this.selectedEventDocuments, item);
        }
        break;
      case config.PlacesCollection:
        if (item.showRecord === true && item['Supporting Documents']) {
          item.selectedByPlace = true;
          this.selectedPlaceDocuments.push(item);
        } else {
          item.selectedByPlace = false;
          _.remove(this.selectedPlaceDocuments, item);
        }
        break;
      case config.PeopleCollection:
        if (item.showRecord === true && item['Supporting Documents']) {
          item.selectedByPeople = true;
          this.selectedPeopleDocuments.push(item);
        } else {
          item.selectedByPeople = false;
          _.remove(this.selectedPeopleDocuments, item);
        }
        break;
      default:
    }

    // Created array of related source shortnames to match
    mergedObjectArray = _.union(this.selectedEventDocuments, this.selectedPlaceDocuments, this.selectedPeopleDocuments);

    mergedObjectArray.forEach(function(item) {
      relatedSourceArray.push(_.map(item['Supporting Documents'].toString().split(','), trim));
    });

    relatedSourceArray = _.uniq(_.flatten(relatedSourceArray));

    // Update related source records to show
    sourcesStore.userFilteredCollection.copy().where(function(sourceObject) {
        return relatedSourceArray.indexOf(sourceObject['Short Name'].toString()) !== -1;
      })
      .update(function (sourceObject) {
        sourceObject.showRecord = true;
        sourceObject.selectedByEvent = true;
        sourceObject.highlightAsRelatedToEvent = true;
    });

    // Update non related source records to not show
    sourcesStore.userFilteredCollection.copy().data().forEach(function(item) {

      var itemArray = [];

      relatedSourceArray.forEach(function(sourceName) {
        if (item['Short Name'].toString() === sourceName) {
          itemArray.push(item);
        }
      });

      if (!itemArray.length) {
        item.showRecord = false;
        item.selectedByEvent = false;
        item.highlightAsRelatedToEvent = false;
      }
    });
  }
});
<|endoftext|>