<commit_before>define(["Ti/_/declare", "Ti/_/UI/FontWidget", "Ti/_/dom", "Ti/_/css", "Ti/_/style", "Ti/_/lang", "Ti/Locale", "Ti/UI"],
	function(declare, FontWidget, dom, css, style, lang, Locale, UI) {

	var setStyle = style.set,
		unitize = dom.unitize,
		tabStop = 2,
		textPost = {
			post: "_setText"
		};

	return declare("Ti.UI.Label", FontWidget, {

		constructor: function() {
			this._add(this._textContainer = UI.createView({
				width: UI.INHERIT,
				height: UI.SIZE,
				center: {y: "50%"}
			}));

			var self = this,
				textContainerDomNode = this._textContainerDomNode = this._textContainer.domNode;
			self._textContainer._getContentSize = function(width, height) {
				var text = self._textContainerDomNode.innerHTML;
				return {
					width: self._measureText(text, textContainerDomNode, width).width,
					height: self._measureText(text, textContainerDomNode, width).height
				};
			};

			this._addStyleableDomNode(textContainerDomNode);
			this.wordWrap = true;
		},

		_defaultWidth: UI.SIZE,

		_defaultHeight: UI.SIZE,

		_getText: function() {
			var i,
				lineStartIndex = 0,
				currentIndex = 0,
				currentTabIndex,
				text = Locale._getString(this.textid, this.text);

			// Convert \t and \n to  's and
's
			while (currentIndex < text.length) {
				if (text[currentIndex] === '\t') {
					var tabSpaces = "",
						numSpacesToInsert = tabStop - (currentTabIndex) % tabStop;
					for (i = 0; i < numSpacesToInsert; i++) {
						tabSpaces += " ";
					}
					text = text.substring(0, currentIndex) + tabSpaces + text.substring(currentIndex + 1);
					currentIndex += tabSpaces.length;
					currentTabIndex += numSpacesToInsert;
				} else if (text[currentIndex] === '\n') {
					text = text.substring(0, currentIndex) + "
" + text.substring(currentIndex + 1);
					currentIndex += 5;
					lineStartIndex = currentIndex;
					currentTabIndex = 0;
				} else {
					currentIndex++;
					currentTabIndex++;
				}
			}

			text.match(/
$/) && (text += " ");
			return text;
		},

		_setText: function() {
			this._textContainerDomNode.innerHTML = this._getText();
			this._hasSizeDimensions() && this._triggerLayout();
		},

		_setTextShadow: function() {
			var shadowColor = this.shadowColor && this.shadowColor !== "" ? this.shadowColor : void 0;
			setStyle(
				this._textContainerDomNode,
				"textShadow",
				this.shadowOffset || shadowColor
					? (this.shadowOffset ? unitize(this.shadowOffset.x) + " " + unitize(this.shadowOffset.y) : "0px 0px") + " 0.1em " + lang.val(shadowColor,"black")
					: ""
			);
		},

		properties: {
			ellipsize: {
				set: function(value) {
					setStyle(this._textContainerDomNode,"textOverflow", !!value ? "ellipsis" : "clip");
					return value;
				},
				value: true
			},
			html: {
				set: function(value) {
					this._textContainerDomNode.innerHTML = value;
					this._hasSizeDimensions() && this._triggerLayout();
					return value;
				}
			},
			shadowColor: {
				post: function() {
					this._setTextShadow();
				}
			},
			shadowOffset: {
				post: function() {
					this._setTextShadow();
				}
			},
			text: textPost,
			textAlign: {
				set: function(value) {
					setStyle(this._textContainerDomNode, "textAlign", /(center|right)/.test(value) ? value : "left");
					return value;
				}
			},
			textid: textPost,
			wordWrap: {
				set: function(value) {
					setStyle(this._textContainerDomNode, "whiteSpace", !!value ? "normal" : "nowrap");
					return value;
				}
			},
			verticalAlign: {
				set: function(value) {
					var top,
						bottom,
						center = this.center || {},
						textContainer = this._textContainer;
					switch(value) {
						case UI.TEXT_VERTICAL_ALIGNMENT_TOP: top = 0; break;
						case UI.TEXT_VERTICAL_ALIGNMENT_CENTER: center.y = "50%"; break;
						case UI.TEXT_VERTICAL_ALIGNMENT_BOTTOM: bottom = 0; break;
					}
					textContainer.top = top;
					textContainer.center = center;
					textContainer.bottom = bottom;
					return value;
				},
				value: UI.TEXT_VERTICAL_ALIGNMENT_CENTER
			}
		}

	});

});<commit_msg>[TIMOB-8275] Bug fix in Label.<commit_after>define(["Ti/_/declare", "Ti/_/UI/FontWidget", "Ti/_/dom", "Ti/_/css", "Ti/_/style", "Ti/_/lang", "Ti/Locale", "Ti/UI"],
	function(declare, FontWidget, dom, css, style, lang, Locale, UI) {

	var setStyle = style.set,
		unitize = dom.unitize,
		tabStop = 2,
		textPost = {
			post: "_setText"
		};

	return declare("Ti.UI.Label", FontWidget, {

		constructor: function() {
			this._add(this._textContainer = UI.createView({
				width: UI.INHERIT,
				height: UI.SIZE,
				center: {y: "50%"}
			}));

			var self = this,
				textContainerDomNode = this._textContainerDomNode = this._textContainer.domNode;
			self._textContainer._getContentSize = function(width, height) {
				var text = self._textContainerDomNode.innerHTML;
				return {
					width: self._measureText(text, textContainerDomNode, width).width,
					height: self._measureText(text, textContainerDomNode, width).height
				};
			};

			this._addStyleableDomNode(textContainerDomNode);
			this.wordWrap = true;
		},

		_defaultWidth: UI.SIZE,

		_defaultHeight: UI.SIZE,

		_getText: function() {
			var i,
				lineStartIndex = 0,
				currentIndex = 0,
				currentTabIndex,
				text = Locale._getString(this.textid, this.text);

			// Handle null, undefined, etc edge case
			if (!text) {
				return "";
			}

			// Convert \t and \n to  's and
's
			while (currentIndex < text.length) {
				if (text[currentIndex] === '\t') {
					var tabSpaces = "",
						numSpacesToInsert = tabStop - (currentTabIndex) % tabStop;
					for (i = 0; i < numSpacesToInsert; i++) {
						tabSpaces += " ";
					}
					text = text.substring(0, currentIndex) + tabSpaces + text.substring(currentIndex + 1);
					currentIndex += tabSpaces.length;
					currentTabIndex += numSpacesToInsert;
				} else if (text[currentIndex] === '\n') {
					text = text.substring(0, currentIndex) + "
" + text.substring(currentIndex + 1);
					currentIndex += 5;
					lineStartIndex = currentIndex;
					currentTabIndex = 0;
				} else {
					currentIndex++;
					currentTabIndex++;
				}
			}

			text.match(/
$/) && (text += " ");
			return text;
		},

		_setText: function() {
			this._textContainerDomNode.innerHTML = this._getText();
			this._hasSizeDimensions() && this._triggerLayout();
		},

		_setTextShadow: function() {
			var shadowColor = this.shadowColor && this.shadowColor !== "" ? this.shadowColor : void 0;
			setStyle(
				this._textContainerDomNode,
				"textShadow",
				this.shadowOffset || shadowColor
					? (this.shadowOffset ? unitize(this.shadowOffset.x) + " " + unitize(this.shadowOffset.y) : "0px 0px") + " 0.1em " + lang.val(shadowColor,"black")
					: ""
			);
		},

		properties: {
			ellipsize: {
				set: function(value) {
					setStyle(this._textContainerDomNode,"textOverflow", !!value ? "ellipsis" : "clip");
					return value;
				},
				value: true
			},
			html: {
				set: function(value) {
					this._textContainerDomNode.innerHTML = value;
					this._hasSizeDimensions() && this._triggerLayout();
					return value;
				}
			},
			shadowColor: {
				post: function() {
					this._setTextShadow();
				}
			},
			shadowOffset: {
				post: function() {
					this._setTextShadow();
				}
			},
			text: textPost,
			textAlign: {
				set: function(value) {
					setStyle(this._textContainerDomNode, "textAlign", /(center|right)/.test(value) ? value : "left");
					return value;
				}
			},
			textid: textPost,
			wordWrap: {
				set: function(value) {
					setStyle(this._textContainerDomNode, "whiteSpace", !!value ? "normal" : "nowrap");
					return value;
				}
			},
			verticalAlign: {
				set: function(value) {
					var top,
						bottom,
						center = this.center || {},
						textContainer = this._textContainer;
					switch(value) {
						case UI.TEXT_VERTICAL_ALIGNMENT_TOP: top = 0; break;
						case UI.TEXT_VERTICAL_ALIGNMENT_CENTER: center.y = "50%"; break;
						case UI.TEXT_VERTICAL_ALIGNMENT_BOTTOM: bottom = 0; break;
					}
					textContainer.top = top;
					textContainer.center = center;
					textContainer.bottom = bottom;
					return value;
				},
				value: UI.TEXT_VERTICAL_ALIGNMENT_CENTER
			}
		}

	});

});<|endoftext|>


<commit_before>(function () {
    'use strict';

    angular
        .module('dpShared')
        .factory('user', userFactory);

    userFactory.$inject = ['$window', 'userSettings'];

    function userFactory ($window, userSettings) {
        const USER_TYPE = { // the possible types of a user
            NONE: 'NONE',
            ANONYMOUS: 'ANONYMOUS',
            AUTHENTICATED: 'AUTHENTICATED'
        };

        const AUTHORIZATION_LEVEL = {   // The possible user authorization levels
            NONE: 'NONE',       // unkown authorization level or authorization level not set
            DEFAULT: 'DEFAULT',
            EMPLOYEE: 'EMPLOYEE',
            EMPLOYEE_PLUS: 'EMPLOYEE_PLUS'
        };

        const AUTHORIZATION_LEVEL_MAPPING = {   // maps the backend level codes upon a valid authorization level
            0: AUTHORIZATION_LEVEL.DEFAULT,
            1: AUTHORIZATION_LEVEL.EMPLOYEE,
            3: AUTHORIZATION_LEVEL.EMPLOYEE_PLUS
        };

        class User {
            constructor () {
                this.init = function () {   // initialize private properties
                    this._accessToken = null;
                    this._authorizationLevel = AUTHORIZATION_LEVEL.NONE;
                    this.name = '';
                };

                this.decodeToken = function (token) {
                    try {
                        return angular.fromJson(
                            $window.atob(token
                                .split('.')[1]
                                .replace('-', '+')
                                .replace('_', '/')
                            ));
                    } catch (e) {
                        return {};
                    }
                };

                this.parseToken = function (token) {   // private method to parse a refresh or access token
                    const content = this.decodeToken(token);

                    if (angular.isDefined(content.sub)) {   // contained in refresh token
                        this.name = content.sub || '';
                    }

                    if (angular.isDefined(content.authz)) { // contained in access token
                        this.authorizationLevel = content.authz;
                    }
                };

                this.init();

                if (this.refreshToken) {                // get any existing refresh token
                    this.parseToken(this.refreshToken); // and parse its contents
                }
            }

            clear () {
                userSettings.refreshToken.remove();
                userSettings.userType.remove();

                this.init();
            }

            get refreshToken () {
                return userSettings.refreshToken.value; // the refresh token in stored in the session
            }

            set refreshToken (value) {
                userSettings.refreshToken.value = value;
                this.parseToken(value);
            }

            get accessToken () {
                return this._accessToken;
            }

            set accessToken (value) {
                this._accessToken = value;
                this.parseToken(value);
            }

            get type () {
                return USER_TYPE[userSettings.userType.value] || USER_TYPE.NONE;
            }

            set type (value) {
                userSettings.userType.value = USER_TYPE[value];
            }

            get name () {
                return this._name;
            }

            set name (value) {
                this._name = value;
            }

            get authorizationLevel () {
                return AUTHORIZATION_LEVEL[this._authorizationLevel];
            }

            set authorizationLevel (value) {
                this._authorizationLevel = AUTHORIZATION_LEVEL_MAPPING[value] || AUTHORIZATION_LEVEL.NONE;
            }
        }

        const user = new User();

        return {
            getRefreshToken,
            setRefreshToken,
            getAccessToken,
            setAccessToken,
            getName,
            getAuthorizationLevel,
            getUserType,
            clearToken,
            meetsRequiredLevel,
            USER_TYPE,
            AUTHORIZATION_LEVEL
        };

        function getRefreshToken () {
            return user.refreshToken;
        }

        function setRefreshToken (token, userType) {
            user.type = userType;
            user.refreshToken = token;
        }

        function getAccessToken () {
            return user.accessToken;
        }

        function setAccessToken (token) {
            const currentAuthorizationLevel = user.authorizationLevel;

            user.accessToken = token;

            if (!meetsRequiredLevel(currentAuthorizationLevel)) {
                onLowerAuthorizationLevel();
            }
        }

        function getUserType () {
            return user.type;
        }

        function getName () {
            return user.name;
        }

        function getAuthorizationLevel () {
            return user.authorizationLevel;
        }

        function meetsRequiredLevel (requiredLevel) {
            if (angular.isDefined(AUTHORIZATION_LEVEL[requiredLevel])) {
                const access = Object.keys(AUTHORIZATION_LEVEL_MAPPING).reduce((result, value) => ({
                    user: user.authorizationLevel === AUTHORIZATION_LEVEL_MAPPING[value] ? value : result.user,
                    required: requiredLevel === AUTHORIZATION_LEVEL_MAPPING[value] ? value : result.required
                }), {
                    user: Number.NEGATIVE_INFINITY,
                    required: Number.NEGATIVE_INFINITY
                });
                return access.user >= access.required;
            } else {
                return angular.isUndefined(requiredLevel);
            }
        }

        function onLowerAuthorizationLevel () {
            // Brute fix to reload the application when the user authorization decreases
            $window.location.reload();
        }

        function clearToken () {
            user.clear();
            onLowerAuthorizationLevel();
        }
    }
})();
<commit_msg>Force reload from the server instead of the cache<commit_after>(function () {
    'use strict';

    angular
        .module('dpShared')
        .factory('user', userFactory);

    userFactory.$inject = ['$window', 'userSettings'];

    function userFactory ($window, userSettings) {
        const USER_TYPE = { // the possible types of a user
            NONE: 'NONE',
            ANONYMOUS: 'ANONYMOUS',
            AUTHENTICATED: 'AUTHENTICATED'
        };

        const AUTHORIZATION_LEVEL = {   // The possible user authorization levels
            NONE: 'NONE',       // unkown authorization level or authorization level not set
            DEFAULT: 'DEFAULT',
            EMPLOYEE: 'EMPLOYEE',
            EMPLOYEE_PLUS: 'EMPLOYEE_PLUS'
        };

        const AUTHORIZATION_LEVEL_MAPPING = {   // maps the backend level codes upon a valid authorization level
            0: AUTHORIZATION_LEVEL.DEFAULT,
            1: AUTHORIZATION_LEVEL.EMPLOYEE,
            3: AUTHORIZATION_LEVEL.EMPLOYEE_PLUS
        };

        class User {
            constructor () {
                this.init = function () {   // initialize private properties
                    this._accessToken = null;
                    this._authorizationLevel = AUTHORIZATION_LEVEL.NONE;
                    this.name = '';
                };

                this.decodeToken = function (token) {
                    try {
                        return angular.fromJson(
                            $window.atob(token
                                .split('.')[1]
                                .replace('-', '+')
                                .replace('_', '/')
                            ));
                    } catch (e) {
                        return {};
                    }
                };

                this.parseToken = function (token) {   // private method to parse a refresh or access token
                    const content = this.decodeToken(token);

                    if (angular.isDefined(content.sub)) {   // contained in refresh token
                        this.name = content.sub || '';
                    }

                    if (angular.isDefined(content.authz)) { // contained in access token
                        this.authorizationLevel = content.authz;
                    }
                };

                this.init();

                if (this.refreshToken) {                // get any existing refresh token
                    this.parseToken(this.refreshToken); // and parse its contents
                }
            }

            clear () {
                userSettings.refreshToken.remove();
                userSettings.userType.remove();

                this.init();
            }

            get refreshToken () {
                return userSettings.refreshToken.value; // the refresh token in stored in the session
            }

            set refreshToken (value) {
                userSettings.refreshToken.value = value;
                this.parseToken(value);
            }

            get accessToken () {
                return this._accessToken;
            }

            set accessToken (value) {
                this._accessToken = value;
                this.parseToken(value);
            }

            get type () {
                return USER_TYPE[userSettings.userType.value] || USER_TYPE.NONE;
            }

            set type (value) {
                userSettings.userType.value = USER_TYPE[value];
            }

            get name () {
                return this._name;
            }

            set name (value) {
                this._name = value;
            }

            get authorizationLevel () {
                return AUTHORIZATION_LEVEL[this._authorizationLevel];
            }

            set authorizationLevel (value) {
                this._authorizationLevel = AUTHORIZATION_LEVEL_MAPPING[value] || AUTHORIZATION_LEVEL.NONE;
            }
        }

        const user = new User();

        return {
            getRefreshToken,
            setRefreshToken,
            getAccessToken,
            setAccessToken,
            getName,
            getAuthorizationLevel,
            getUserType,
            clearToken,
            meetsRequiredLevel,
            USER_TYPE,
            AUTHORIZATION_LEVEL
        };

        function getRefreshToken () {
            return user.refreshToken;
        }

        function setRefreshToken (token, userType) {
            user.type = userType;
            user.refreshToken = token;
        }

        function getAccessToken () {
            return user.accessToken;
        }

        function setAccessToken (token) {
            const currentAuthorizationLevel = user.authorizationLevel;

            user.accessToken = token;

            if (!meetsRequiredLevel(currentAuthorizationLevel)) {
                onLowerAuthorizationLevel();
            }
        }

        function getUserType () {
            return user.type;
        }

        function getName () {
            return user.name;
        }

        function getAuthorizationLevel () {
            return user.authorizationLevel;
        }

        function meetsRequiredLevel (requiredLevel) {
            if (angular.isDefined(AUTHORIZATION_LEVEL[requiredLevel])) {
                const access = Object.keys(AUTHORIZATION_LEVEL_MAPPING).reduce((result, value) => ({
                    user: user.authorizationLevel === AUTHORIZATION_LEVEL_MAPPING[value] ? value : result.user,
                    required: requiredLevel === AUTHORIZATION_LEVEL_MAPPING[value] ? value : result.required
                }), {
                    user: Number.NEGATIVE_INFINITY,
                    required: Number.NEGATIVE_INFINITY
                });
                return access.user >= access.required;
            } else {
                return angular.isUndefined(requiredLevel);
            }
        }

        function onLowerAuthorizationLevel () {
            // Brute fix to reload the application when the user authorization decreases
            $window.location.reload(true);
        }

        function clearToken () {
            user.clear();
            onLowerAuthorizationLevel();
        }
    }
})();
<|endoftext|>


<commit_before>itemTweetFactory = {
  build: function (item, type = 'regular') {
    var trim = 0,
        status = getStatus(item, type, trim);

    while (status.length > 140) {
      trim++;
      status = getStatus(item, type, trim);
    }

    return status;
  }
};

var getStatus = function (item, type = 'regular', trim = 0) {
  if (type === 'regular') {
    return _.sample([
      `${getOpening(item)} ${getTitle(item, trim)} ${getFlightNumber(item)} ${getUrl(item)}`,
      `${getTitle(item, trim)} ${getDescription(item)} ${getUrl(item)}`
    ]);
  } else if (type === 'trending') {
    var Indicator = _.sample(["🔥", "🌟", "💫", "🌠"]);
    return `${Indicator} Trending ${Indicator} ${getTitle(item, trim)} ${getTrendingDescription(item)} ${getUrl(item)}`;
  }
};

var getTitle = function (item, trim = 0) {
  var title = item.title;
  var trimmedTitle = title.slice(0, title.length - trim);

  return `"${trimmedTitle}"`;
};

var getOpening = function (item) {
  var possibleOpening = [
    "Check out:",
    "Have you read this?",
    "Recent item:",
    "New:",
    "Dear paseengers:"
  ];

  if (item.sourceName === 'Reddit') {
    possibleOpening.push(
      "Recently on Reddit:",
      "New on Reddit:",
      "Reddit:",
      "New item on /r/digitalnomad",
      "On Reddit:"
    );
  }

  if (item.sourceName === 'NomadForum') {
    possibleOpening.push(
      "Recently on nomadforum:",
      "Check out this thread on nomadforum.",
      "On nomadforum:",
      "New post on nomadforum",
      "New on nomadforum"
    );
  }

  if (item.sourceType === 'blog') {
    possibleOpening.push(
      "New blog post:",
      "Meanwhile in a nomad blog:",
      "Blog post:",
      "Check out this post:"
    );
  }

  return _.sample(possibleOpening);
};

var getFlightNumber = function (item) {
  var flightNumber = Flights.findOne(item.flightId).number;

  return _.sample([
    `on flight #${flightNumber}`,
    `is on flight #${flightNumber}`,
    `✈✈${flightNumber}`
  ]);
};

var getUrl = function (item) {
  return Utils.buildShortUrl(item);
};

var getDescription = function (item) {
  var possibleDescriptions = [
    "is new.",
    "Read it at:"
  ];

  if (item.sourceName === 'Reddit') {
    possibleDescriptions.push(
      "is on Reddit.",
      "is new on Reddit",
      "was posted on Reddit"
    );
  }

  if (item.sourceName === 'NomadForum') {
    possibleDescriptions.push(
      "is on nomadforum.",
      "was posted on nomadforum.",
      "on nomadforum:",
      "Read at nomadforum:"
    );
  }

  if (item.sourceType === 'blog') {
    possibleDescriptions.push(
      "is a new blog post.",
      "New blog post.",
      "Maybe worth reading?",
      "Check out the blog post:",
      "Blog post:"
    );
  }

  return _.sample(possibleDescriptions);
};

var getTrendingDescription = function (item) {
  var possibleDescriptions = [
    "Most viewed (last 24 hrs)."
  ];

  return _.sample(possibleDescriptions);
};
<commit_msg>Display author twitter in tweets<commit_after>itemTweetFactory = {
  build: function (item, type = 'regular') {
    var trim = 0,
        status = getStatus(item, type, trim);

    while (status.length > 140) {
      trim++;
      status = getStatus(item, type, trim);
    }

    return status;
  }
};

var getStatus = function (item, type = 'regular', trim = 0) {
  if (type === 'regular') {
    return _.sample([
      `${getOpening(item)} ${getTitle(item, trim)}${getAuthorTwitter(item)} ${getFlightNumber(item)} ${getUrl(item)}`,
      `${getTitle(item, trim)}${getAuthorTwitter(item)} ${getDescription(item)} ${getUrl(item)}`
    ]);
  } else if (type === 'trending') {
    var Indicator = _.sample(["🔥", "🌟", "💫", "🌠"]);
    return `${Indicator} Trending ${Indicator} ${getTitle(item, trim)}${getAuthorTwitter(item)} ${getTrendingDescription(item)} ${getUrl(item)}`;
  }
};

var getAuthorTwitter = function (item) {
  if (!!item.authorTwitter) {
    return ` by @${item.authorTwitter}`;
  }
};

var getTitle = function (item, trim = 0) {
  var title = item.title;
  var trimmedTitle = title.slice(0, title.length - trim);

  return `"${trimmedTitle}"`;
};

var getOpening = function (item) {
  var possibleOpening = [
    "Check out:",
    "Recent:",
    "New:",
  ];

  if (item.sourceName === 'Reddit') {
    possibleOpening.push(
      "Recently on Reddit:",
      "New on Reddit:",
      "Reddit:",
      "New item on /r/digitalnomad",
      "On Reddit:"
    );
  }

  if (item.sourceName === 'NomadForum') {
    possibleOpening.push(
      "Recently on nomadforum:",
      "Check out this thread on nomadforum.",
      "On nomadforum:",
      "New post on nomadforum",
      "New on nomadforum"
    );
  }

  if (item.sourceType === 'blog') {
    possibleOpening.push(
      "New blog post:",
      "Meanwhile in a nomad blog:",
      "Blog post:",
      "Check out this post:"
    );
  }

  return _.sample(possibleOpening);
};

var getFlightNumber = function (item) {
  var flightNumber = Flights.findOne(item.flightId).number;

  return _.sample([
    `on flight #${flightNumber}`,
    `is on flight #${flightNumber}`,
    `✈✈${flightNumber}`
  ]);
};

var getUrl = function (item) {
  return Utils.buildShortUrl(item);
};

var getDescription = function (item) {
  var possibleDescriptions = [
    "is new.",
    "Read it at:"
  ];

  if (item.sourceName === 'Reddit') {
    possibleDescriptions.push(
      "is on Reddit.",
      "is new on Reddit",
      "was posted on Reddit"
    );
  }

  if (item.sourceName === 'NomadForum') {
    possibleDescriptions.push(
      "is on nomadforum.",
      "was posted on nomadforum.",
      "on nomadforum:",
      "Read at nomadforum:"
    );
  }

  if (item.sourceType === 'blog') {
    possibleDescriptions.push(
      "is a new blog post.",
      "New blog post.",
      "Maybe worth reading?",
      "Check out the blog post:",
      "Blog post:"
    );
  }

  return _.sample(possibleDescriptions);
};

var getTrendingDescription = function (item) {
  var possibleDescriptions = [
    "Most viewed (last 24 hrs)."
  ];

  return _.sample(possibleDescriptions);
};
<|endoftext|>


<commit_before>/**
 * This file is part of Superdesk.
 *
 * Copyright 2013, 2014 Sourcefabric z.u. and contributors.
 *
 * For the full copyright and license information, please see the
 * AUTHORS and LICENSE files distributed with this source code, or
 * at https://www.sourcefabric.org/superdesk/license
 */

define([
    'angular',
    'lodash',
    'ng-sir-trevor',
    'ng-sir-trevor-blocks',
    'angular-embed'
], function(angular, _) {
    'use strict';

    BlogEditController.$inject = [
        'api', '$q', '$scope', 'blog', 'notify', 'gettext',
        'upload', 'config', 'embedService', 'postsService', 'modal',
        'blogService', '$route', '$routeParams'
    ];
    function BlogEditController(api, $q, $scope, blog, notify, gettext,
        upload, config, embedService, postsService, modal, blogService, $route, $routeParams) {

        // return the list of items from the editor
        function getItemsFromEditor() {
            return _.map($scope.editor.get(), function(block) {
                return {
                    text: block.text.replace(/(^
)|(<\/div>$)/g, '').replace(/(
$)/g, ''),
                    meta: block.meta,
                    item_type: block.type
                };
            });
        }

        // ask in a modalbox if the user is sure to want to overwrite editor.
        // call the callback if user say yes or if editor is empty
        function doOrAskBeforeIfEditorIsNotEmpty(callback, msg) {
            var are_all_blocks_empty = _.all($scope.editor.blocks, function(block) {return block.isEmpty();});
            if (are_all_blocks_empty || !$scope.isCurrentPostUnsaved()) {
                callback();
            } else {
                msg = msg || gettext('You have content in the editor. You will lose it if you continue without saving it before.');
                modal.confirm(msg).then(callback);
            }
        }

        // remove and clean every items from the editor
        function cleanEditor() {
            $scope.editor.reinitialize();
            $scope.currentPost = undefined;
        }
        var vm = this;

        // define the $scope
        angular.extend($scope, {
            blog: blog,
            currentPost: undefined,
            askAndResetEditor: function() {
                doOrAskBeforeIfEditorIsNotEmpty(cleanEditor);
            },
            openPostInEditor: function (post) {
                function fillEditor(post) {
                    cleanEditor();
                    $scope.currentPost = angular.copy(post);
                    var items = post.groups[1].refs;
                    items.forEach(function(item) {
                        item = item.item;
                        if (angular.isDefined(item)) {
                            var data = _.extend({text: item.text}, item.meta);
                            $scope.editor.createBlock(item.item_type, data);
                        }
                    });
                }
                doOrAskBeforeIfEditorIsNotEmpty(fillEditor.bind(null, post));
            },
            saveAsDraft: function() {
                notify.info(gettext('Saving draft'));
                postsService.saveDraft(blog._id, $scope.currentPost, getItemsFromEditor()).then(function(post) {
                    notify.pop();
                    notify.info(gettext('Draft saved'));
                    cleanEditor();
                }, function() {
                    notify.pop();
                    notify.error(gettext('Something went wrong. Please try again later'));
                });
            },
            publish: function() {
                notify.info(gettext('Saving post'));
                postsService.savePost(blog._id,
                    $scope.currentPost,
                    getItemsFromEditor(),
                    {post_status: 'open'}
                ).then(function(post) {
                    notify.pop();
                    notify.info(gettext('Post saved'));
                    cleanEditor();
                }, function() {
                    notify.pop();
                    notify.error(gettext('Something went wrong. Please try again later'));
                });
            },
            // retrieve draft panel status from url
            draftPanelState: $routeParams.drafts === 'open'? 'open' : 'closed',
            toggleDraftPanel: function() {
                // reverse status
                var newStateValue = $scope.draftPanelState === 'open' ? 'closed': 'open';
                // update new status
                $scope.draftPanelState = newStateValue;
                // update url for deeplinking
                $route.updateParams({drafts: newStateValue === 'open' ? 'open' : undefined});
            },
            stParams: {
                coverMaxWidth: 350,
                embedService: embedService,
                // provide an uploader to the editor for media (custom sir-trevor image block uses it)
                uploader: function(file, success_callback, error_callback) {
                    var handleError = function(response) {
                        // call the uploader callback with the error message as parameter
                        error_callback(response.data? response.data._message : undefined);
                    };
                    // return a promise of upload which will call the success/error callback
                    return api.upload.getUrl().then(function(url) {
                        upload.start({
                            method: 'POST',
                            url: url,
                            data: {media: file}
                        })
                        .then(function(response) {
                            if (response.data._issues) {
                                return handleError(response);
                            }
                            // used in `SirTrevor.Blocks.Image` to fill in the block content.
                            var media_meta = {
                                _info: config.server.url + response.data._links.self.href,
                                _id: response.data._id,
                                _url: response.data.renditions.viewImage.href
                            };
                            // media will be added latter in the `meta` if this item in this callback
                            success_callback({media: media_meta});
                        }, handleError, function(progress) {
                        });
                    });
                }
            },
            fetchNewTimelinePage: function() {
                vm.timelineInstance.fetchPage();
            },
            isBlogOpened: function() {
                return $scope.blog.blog_status === 'open';
            },
            isCurrentPostPublished: function() {
                return angular.isDefined($scope.currentPost) && $scope.currentPost.post_status === 'open';
            },
            isCurrentPostUnsaved: function() {
                if (angular.isDefined($scope.currentPost)) {
                    return _.any(getItemsFromEditor(), function (item, item_index) {
                        return _.any(_.keys(item), function (key) {
                            if (!angular.isDefined($scope.currentPost.items[item_index])) {
                                return true;
                            } else {
                                return !_.isEqual(item[key], $scope.currentPost.items[item_index].item[key]);
                            }
                        });
                    });
                } else {
                    return true;
                }
            }
        });
    }

    BlogSettingsController.$inject = ['$scope', 'blog', 'api', 'blogService', '$location', 'notify',
        'gettext', 'config', 'modal', '$q'];
    function BlogSettingsController($scope, blog, api, blogService, $location, notify,
        gettext, config, modal, $q) {
        // set view's model
        var vm = this;
        angular.extend(vm, {
            blog: blog,
            newBlog: _.create(blog),
            blogPreferences: angular.copy(blog.blog_preferences),
            availableLanguages: [],
            original_creator: {},
            availableThemes: [],
            isSaved: true,
            forms: {},
            tab: false,
            changeTab: function(tab) {
                if (vm.tab) {
                    vm.forms.dirty = vm.forms.dirty || vm.forms[vm.tab].$dirty;
                }
                vm.tab = tab;
            },
            // take the public url (from s3) or the local address
            // FIXME: The local address shouldn't be given on production mode
            iframe_url: blog.public_url || config.server.url.replace('/api', '/embed/' + blog._id),
            setFormsPristine: function() {
                if (vm.forms.dirty) {
                    vm.forms.dirty = false;
                }
                angular.forEach(vm.forms, function(value, key) {
                    if (vm.forms[key] && vm.forms[key].$dirty) {
                        vm.forms[key].$setPristine();
                    }
                });
            },
            saveAndClose: function() {
                vm.save().then(function() {
                    vm.close();
                });
            },
            save: function() {
                // save on backend
                var deferred = $q.defer();
                notify.info(gettext('saving blog settings'));
                var changedBlog = {
                    blog_preferences: vm.blogPreferences,
                    original_creator: vm.original_creator._id,
                    blog_status: vm.blog_switch === true? 'open': 'closed'
                };
                angular.extend(changedBlog, vm.newBlog);
                blogService.save(vm.blog._id, changedBlog).then(function(blog) {
                    vm.isSaved = true;
                    vm.blog = blog;
                    notify.pop();
                    notify.info(gettext('blog settings saved'));
                    vm.setFormsPristine();
                    deferred.resolve();
                });
                return deferred.promise;
            },
            reset: function() {
                // reset vm.blogPreferences's values with the ones from global_preferences (backend)
                api('global_preferences').query().then(function(global_preferences) {
                    global_preferences._items.forEach(function(item) {
                        vm.blogPreferences[item.key] = item.value;
                    });
                });
            },
            close: function() {
                // return to blog edit page
                $location.path('/liveblog/edit/' + vm.blog._id);
            },
            buildOwner: function(userID) {
                api('users').getById(userID).then(function(data) {
                    //temp_selected_owner is used handle the selection of users in the change owner autocomplete box
                    //without automatically changing the owner that is displayed
                    vm.temp_selected_owner = vm.original_creator = data;
                });
            },
            getMembers: function() {
                //contributors
                vm.members = [];
                _.each(blog.members, function(member) {
                    api('users').getById(member.user).then(function(data) {
                        vm.members.push(data);
                    });
                });
            }

        });
        // load available languages
        api('languages').query().then(function(data) {
            vm.availableLanguages = data._items;
        });
        // load available themes
        api('themes').query().then(function(data) {
            vm.availableThemes = data._items;
        });
        api('users').getById(blog.original_creator).then(function(data) {
            vm.original_creator = data;
        });
        api('users').query().then(function(data) {
            vm.avUsers = data._items;
        });
        vm.buildOwner(blog.original_creator);
        vm.getMembers();
        //check if form is dirty before leaving the page
        var deregisterPreventer = $scope.$on('$locationChangeStart', function (event, next, current) {
            event.preventDefault();
            //check if one of the forms is dirty
            var dirty = false;
            if (vm.forms.dirty) {
                dirty = true;
            } else {
                angular.forEach(vm.forms, function(value, key) {
                    if (vm.forms[key] && vm.forms[key].$dirty) {
                        dirty = true;
                        return;
                    }
                });
            }
            if (dirty) {
                modal.confirm(gettext('You have unsaved settings. Are you sure you want to leave the page?')).then(function() {
                    goToNextPage(next);
                });
            } else {
                goToNextPage(next);
            }
        });
        var goToNextPage = function(url) {
            $location.path($location.url(url).hash());
            deregisterPreventer();
        };
        vm.changeTab('general');
        vm.blog_switch = vm.newBlog.blog_status === 'open'? true: false;
    }

    /**
     * Resolve a blog by route id and redirect to /liveblog if such blog does not exist
     */
    BlogResolver.$inject = ['api', '$route', '$location', 'notify', 'gettext', 'blogService'];
    function BlogResolver(api, $route, $location, notify, gettext, blogService) {

        return blogService.update($route.current.params._id)
            .then(null, function(response) {
                if (response.status === 404) {
                    notify.error(gettext('Blog was not found, sorry.'), 5000);
                    $location.path('/liveblog');
                }
                return response;
            });
    }

    var app = angular.module('liveblog.edit', [
        'SirTrevor',
        'SirTrevorBlocks',
        'angular-embed',
        'angular-embed.handlers',
        'ngRoute',
        'superdesk.services.modal'
    ]);
    app.config(['superdeskProvider', function(superdesk) {
        superdesk.activity('/liveblog/edit/:_id', {
            label: gettext('Blog Edit'),
            auth: true,
            controller: BlogEditController,
            controllerAs: 'blogEdit',
            templateUrl: 'scripts/liveblog-edit/views/main.html',
            resolve: {blog: BlogResolver}
        }).activity('/liveblog/settings/:_id', {
            label: gettext('Blog Settings'),
            auth: true,
            controller: BlogSettingsController,
            controllerAs: 'settings',
            templateUrl: 'scripts/liveblog-edit/views/settings.html',
            resolve: {blog: BlogResolver}
        });
    }]).config(['apiProvider', function(apiProvider) {
        apiProvider.api('posts', {
            type: 'http',
            backend: {rel: 'posts'}
        });
        apiProvider.api('items', {
            type: 'http',
            backend: {rel: 'items'}
        });
        apiProvider.api('upload', {
            type: 'http',
            backend: {rel: 'upload'}
        });
    }]).config(['SirTrevorOptionsProvider', 'SirTrevorProvider', function(SirTrevorOptions, SirTrevor) {
        // here comes all the sir trevor customization (except custom blocks which are in the SirTrevorBlocks module)
        SirTrevor = SirTrevor.$get();
        // change the remove trash icon by a cross
        SirTrevor.BlockDeletion.prototype.attributes['data-icon'] = 'close';
        // extends the options given as parameter to the editor contructor
        SirTrevorOptions.$extend({
            onEditorRender: function() {
                var editor = this;
                // when a new block is added, remove empty blocks
                function removeEmptyBlockExceptTheBlock(new_block) {
                    _.each(editor.blocks, function(block) {
                        if (block !== new_block && block.isEmpty()) {
                            editor.removeBlock(block.blockID);
                        }
                    });
                }
                SirTrevor.EventBus.on('block:create:existing', removeEmptyBlockExceptTheBlock);
                SirTrevor.EventBus.on('block:create:new', removeEmptyBlockExceptTheBlock);
            },
            blockTypes: ['Text', 'Image', 'Embed', 'Quote'],
            // render a default block when the editor is loaded
            defaultType: 'Text',
            transform: {
                get: function(block) {
                    return {
                        type: block.blockStorage.type,
                        text: block.toHTML(),
                        meta: block.toMeta()
                    };
                },
                set: function(block) {
                    return {
                        type: block.type,
                        data: block.data
                    };
                }
            }
        });
    }]).config(['embedlyServiceProvider', 'embedServiceProvider', 'config', function(embedlyServiceProvider, embedServiceProvider, config) {
        embedlyServiceProvider.setKey(config.embedly);
        embedServiceProvider.setConfig('facebookAppId', config.facebookAppId);
    }]).run(['$q', 'embedService', 'ngEmbedTwitterHandler', 'ngEmbedFacebookHandler',
            'ngEmbedYoutubeHandler', 'ngEmbedInstagramHandler', 'ngEmbedPictureHandler',
        function($q, embedService, ngEmbedTwitterHandler, ngEmbedFacebookHandler,
                ngEmbedYoutubeHandler, ngEmbedInstagramHandler, ngEmbedPictureHandler) {
            // register all the special handlers we want to use for angular-embed
            embedService.registerHandler(ngEmbedFacebookHandler); // use embed.ly and update the embed code with a max_width
            embedService.registerHandler(ngEmbedYoutubeHandler); // use embed.ly
            embedService.registerHandler(ngEmbedInstagramHandler); // Use embed.ly
            embedService.registerHandler(ngEmbedTwitterHandler); // use embed.ly, load a script to render the card.
            embedService.registerHandler(ngEmbedPictureHandler); // use embed.ly, and provide a `thumbnail_url` field from the `url`
        }
    ]);
    return app;
});
<commit_msg>Settings: fix a bug with url after confirming we want to leave the page<commit_after>/**
 * This file is part of Superdesk.
 *
 * Copyright 2013, 2014 Sourcefabric z.u. and contributors.
 *
 * For the full copyright and license information, please see the
 * AUTHORS and LICENSE files distributed with this source code, or
 * at https://www.sourcefabric.org/superdesk/license
 */

define([
    'angular',
    'lodash',
    'ng-sir-trevor',
    'ng-sir-trevor-blocks',
    'angular-embed'
], function(angular, _) {
    'use strict';

    BlogEditController.$inject = [
        'api', '$q', '$scope', 'blog', 'notify', 'gettext',
        'upload', 'config', 'embedService', 'postsService', 'modal',
        'blogService', '$route', '$routeParams'
    ];
    function BlogEditController(api, $q, $scope, blog, notify, gettext,
        upload, config, embedService, postsService, modal, blogService, $route, $routeParams) {

        // return the list of items from the editor
        function getItemsFromEditor() {
            return _.map($scope.editor.get(), function(block) {
                return {
                    text: block.text.replace(/(^
)|(<\/div>$)/g, '').replace(/(
$)/g, ''),
                    meta: block.meta,
                    item_type: block.type
                };
            });
        }

        // ask in a modalbox if the user is sure to want to overwrite editor.
        // call the callback if user say yes or if editor is empty
        function doOrAskBeforeIfEditorIsNotEmpty(callback, msg) {
            var are_all_blocks_empty = _.all($scope.editor.blocks, function(block) {return block.isEmpty();});
            if (are_all_blocks_empty || !$scope.isCurrentPostUnsaved()) {
                callback();
            } else {
                msg = msg || gettext('You have content in the editor. You will lose it if you continue without saving it before.');
                modal.confirm(msg).then(callback);
            }
        }

        // remove and clean every items from the editor
        function cleanEditor() {
            $scope.editor.reinitialize();
            $scope.currentPost = undefined;
        }
        var vm = this;

        // define the $scope
        angular.extend($scope, {
            blog: blog,
            currentPost: undefined,
            askAndResetEditor: function() {
                doOrAskBeforeIfEditorIsNotEmpty(cleanEditor);
            },
            openPostInEditor: function (post) {
                function fillEditor(post) {
                    cleanEditor();
                    $scope.currentPost = angular.copy(post);
                    var items = post.groups[1].refs;
                    items.forEach(function(item) {
                        item = item.item;
                        if (angular.isDefined(item)) {
                            var data = _.extend({text: item.text}, item.meta);
                            $scope.editor.createBlock(item.item_type, data);
                        }
                    });
                }
                doOrAskBeforeIfEditorIsNotEmpty(fillEditor.bind(null, post));
            },
            saveAsDraft: function() {
                notify.info(gettext('Saving draft'));
                postsService.saveDraft(blog._id, $scope.currentPost, getItemsFromEditor()).then(function(post) {
                    notify.pop();
                    notify.info(gettext('Draft saved'));
                    cleanEditor();
                }, function() {
                    notify.pop();
                    notify.error(gettext('Something went wrong. Please try again later'));
                });
            },
            publish: function() {
                notify.info(gettext('Saving post'));
                postsService.savePost(blog._id,
                    $scope.currentPost,
                    getItemsFromEditor(),
                    {post_status: 'open'}
                ).then(function(post) {
                    notify.pop();
                    notify.info(gettext('Post saved'));
                    cleanEditor();
                }, function() {
                    notify.pop();
                    notify.error(gettext('Something went wrong. Please try again later'));
                });
            },
            // retrieve draft panel status from url
            draftPanelState: $routeParams.drafts === 'open'? 'open' : 'closed',
            toggleDraftPanel: function() {
                // reverse status
                var newStateValue = $scope.draftPanelState === 'open' ? 'closed': 'open';
                // update new status
                $scope.draftPanelState = newStateValue;
                // update url for deeplinking
                $route.updateParams({drafts: newStateValue === 'open' ? 'open' : undefined});
            },
            stParams: {
                coverMaxWidth: 350,
                embedService: embedService,
                // provide an uploader to the editor for media (custom sir-trevor image block uses it)
                uploader: function(file, success_callback, error_callback) {
                    var handleError = function(response) {
                        // call the uploader callback with the error message as parameter
                        error_callback(response.data? response.data._message : undefined);
                    };
                    // return a promise of upload which will call the success/error callback
                    return api.upload.getUrl().then(function(url) {
                        upload.start({
                            method: 'POST',
                            url: url,
                            data: {media: file}
                        })
                        .then(function(response) {
                            if (response.data._issues) {
                                return handleError(response);
                            }
                            // used in `SirTrevor.Blocks.Image` to fill in the block content.
                            var media_meta = {
                                _info: config.server.url + response.data._links.self.href,
                                _id: response.data._id,
                                _url: response.data.renditions.viewImage.href
                            };
                            // media will be added latter in the `meta` if this item in this callback
                            success_callback({media: media_meta});
                        }, handleError, function(progress) {
                        });
                    });
                }
            },
            fetchNewTimelinePage: function() {
                vm.timelineInstance.fetchPage();
            },
            isBlogOpened: function() {
                return $scope.blog.blog_status === 'open';
            },
            isCurrentPostPublished: function() {
                return angular.isDefined($scope.currentPost) && $scope.currentPost.post_status === 'open';
            },
            isCurrentPostUnsaved: function() {
                if (angular.isDefined($scope.currentPost)) {
                    return _.any(getItemsFromEditor(), function (item, item_index) {
                        return _.any(_.keys(item), function (key) {
                            if (!angular.isDefined($scope.currentPost.items[item_index])) {
                                return true;
                            } else {
                                return !_.isEqual(item[key], $scope.currentPost.items[item_index].item[key]);
                            }
                        });
                    });
                } else {
                    return true;
                }
            }
        });
    }

    BlogSettingsController.$inject = ['$scope', 'blog', 'api', 'blogService', '$location', 'notify',
        'gettext', 'config', 'modal', '$q'];
    function BlogSettingsController($scope, blog, api, blogService, $location, notify,
        gettext, config, modal, $q) {
        // set view's model
        var vm = this;
        angular.extend(vm, {
            blog: blog,
            newBlog: _.create(blog),
            blogPreferences: angular.copy(blog.blog_preferences),
            availableLanguages: [],
            original_creator: {},
            availableThemes: [],
            isSaved: true,
            forms: {},
            tab: false,
            changeTab: function(tab) {
                if (vm.tab) {
                    vm.forms.dirty = vm.forms.dirty || vm.forms[vm.tab].$dirty;
                }
                vm.tab = tab;
            },
            // take the public url (from s3) or the local address
            // FIXME: The local address shouldn't be given on production mode
            iframe_url: blog.public_url || config.server.url.replace('/api', '/embed/' + blog._id),
            setFormsPristine: function() {
                if (vm.forms.dirty) {
                    vm.forms.dirty = false;
                }
                angular.forEach(vm.forms, function(value, key) {
                    if (vm.forms[key] && vm.forms[key].$dirty) {
                        vm.forms[key].$setPristine();
                    }
                });
            },
            saveAndClose: function() {
                vm.save().then(function() {
                    vm.close();
                });
            },
            save: function() {
                // save on backend
                var deferred = $q.defer();
                notify.info(gettext('saving blog settings'));
                var changedBlog = {
                    blog_preferences: vm.blogPreferences,
                    original_creator: vm.original_creator._id,
                    blog_status: vm.blog_switch === true? 'open': 'closed'
                };
                angular.extend(changedBlog, vm.newBlog);
                blogService.save(vm.blog._id, changedBlog).then(function(blog) {
                    vm.isSaved = true;
                    vm.blog = blog;
                    notify.pop();
                    notify.info(gettext('blog settings saved'));
                    vm.setFormsPristine();
                    deferred.resolve();
                });
                return deferred.promise;
            },
            reset: function() {
                // reset vm.blogPreferences's values with the ones from global_preferences (backend)
                api('global_preferences').query().then(function(global_preferences) {
                    global_preferences._items.forEach(function(item) {
                        vm.blogPreferences[item.key] = item.value;
                    });
                });
            },
            close: function() {
                // return to blog edit page
                $location.path('/liveblog/edit/' + vm.blog._id);
            },
            buildOwner: function(userID) {
                api('users').getById(userID).then(function(data) {
                    //temp_selected_owner is used handle the selection of users in the change owner autocomplete box
                    //without automatically changing the owner that is displayed
                    vm.temp_selected_owner = vm.original_creator = data;
                });
            },
            getMembers: function() {
                //contributors
                vm.members = [];
                _.each(blog.members, function(member) {
                    api('users').getById(member.user).then(function(data) {
                        vm.members.push(data);
                    });
                });
            }

        });
        // load available languages
        api('languages').query().then(function(data) {
            vm.availableLanguages = data._items;
        });
        // load available themes
        api('themes').query().then(function(data) {
            vm.availableThemes = data._items;
        });
        api('users').getById(blog.original_creator).then(function(data) {
            vm.original_creator = data;
        });
        api('users').query().then(function(data) {
            vm.avUsers = data._items;
        });
        vm.buildOwner(blog.original_creator);
        vm.getMembers();
        //check if form is dirty before leaving the page
        var deregisterPreventer = $scope.$on('$locationChangeStart', routeChange);
        function routeChange (event, next, current) {
            //check if one of the forms is dirty
            var dirty = false;
            if (vm.forms.dirty) {
                dirty = true;
            } else {
                angular.forEach(vm.forms, function(value, key) {
                    if (vm.forms[key] && vm.forms[key].$dirty) {
                        dirty = true;
                        return;
                    }
                });
            }
            if (dirty) {
                event.preventDefault();
                modal.confirm(gettext('You have unsaved settings. Are you sure you want to leave the page?')).then(function() {
                    deregisterPreventer();
                    $location.url($location.url(next).hash());
                });
            }
        }
        vm.changeTab('general');
        vm.blog_switch = vm.newBlog.blog_status === 'open'? true: false;
    }

    /**
     * Resolve a blog by route id and redirect to /liveblog if such blog does not exist
     */
    BlogResolver.$inject = ['api', '$route', '$location', 'notify', 'gettext', 'blogService'];
    function BlogResolver(api, $route, $location, notify, gettext, blogService) {

        return blogService.update($route.current.params._id)
            .then(null, function(response) {
                if (response.status === 404) {
                    notify.error(gettext('Blog was not found, sorry.'), 5000);
                    $location.path('/liveblog');
                }
                return response;
            });
    }

    var app = angular.module('liveblog.edit', [
        'SirTrevor',
        'SirTrevorBlocks',
        'angular-embed',
        'angular-embed.handlers',
        'ngRoute',
        'superdesk.services.modal'
    ]);
    app.config(['superdeskProvider', function(superdesk) {
        superdesk.activity('/liveblog/edit/:_id', {
            label: gettext('Blog Edit'),
            auth: true,
            controller: BlogEditController,
            controllerAs: 'blogEdit',
            templateUrl: 'scripts/liveblog-edit/views/main.html',
            resolve: {blog: BlogResolver}
        }).activity('/liveblog/settings/:_id', {
            label: gettext('Blog Settings'),
            auth: true,
            controller: BlogSettingsController,
            controllerAs: 'settings',
            templateUrl: 'scripts/liveblog-edit/views/settings.html',
            resolve: {blog: BlogResolver}
        });
    }]).config(['apiProvider', function(apiProvider) {
        apiProvider.api('posts', {
            type: 'http',
            backend: {rel: 'posts'}
        });
        apiProvider.api('items', {
            type: 'http',
            backend: {rel: 'items'}
        });
        apiProvider.api('upload', {
            type: 'http',
            backend: {rel: 'upload'}
        });
    }]).config(['SirTrevorOptionsProvider', 'SirTrevorProvider', function(SirTrevorOptions, SirTrevor) {
        // here comes all the sir trevor customization (except custom blocks which are in the SirTrevorBlocks module)
        SirTrevor = SirTrevor.$get();
        // change the remove trash icon by a cross
        SirTrevor.BlockDeletion.prototype.attributes['data-icon'] = 'close';
        // extends the options given as parameter to the editor contructor
        SirTrevorOptions.$extend({
            onEditorRender: function() {
                var editor = this;
                // when a new block is added, remove empty blocks
                function removeEmptyBlockExceptTheBlock(new_block) {
                    _.each(editor.blocks, function(block) {
                        if (block !== new_block && block.isEmpty()) {
                            editor.removeBlock(block.blockID);
                        }
                    });
                }
                SirTrevor.EventBus.on('block:create:existing', removeEmptyBlockExceptTheBlock);
                SirTrevor.EventBus.on('block:create:new', removeEmptyBlockExceptTheBlock);
            },
            blockTypes: ['Text', 'Image', 'Embed', 'Quote'],
            // render a default block when the editor is loaded
            defaultType: 'Text',
            transform: {
                get: function(block) {
                    return {
                        type: block.blockStorage.type,
                        text: block.toHTML(),
                        meta: block.toMeta()
                    };
                },
                set: function(block) {
                    return {
                        type: block.type,
                        data: block.data
                    };
                }
            }
        });
    }]).config(['embedlyServiceProvider', 'embedServiceProvider', 'config', function(embedlyServiceProvider, embedServiceProvider, config) {
        embedlyServiceProvider.setKey(config.embedly);
        embedServiceProvider.setConfig('facebookAppId', config.facebookAppId);
    }]).run(['$q', 'embedService', 'ngEmbedTwitterHandler', 'ngEmbedFacebookHandler',
            'ngEmbedYoutubeHandler', 'ngEmbedInstagramHandler', 'ngEmbedPictureHandler',
        function($q, embedService, ngEmbedTwitterHandler, ngEmbedFacebookHandler,
                ngEmbedYoutubeHandler, ngEmbedInstagramHandler, ngEmbedPictureHandler) {
            // register all the special handlers we want to use for angular-embed
            embedService.registerHandler(ngEmbedFacebookHandler); // use embed.ly and update the embed code with a max_width
            embedService.registerHandler(ngEmbedYoutubeHandler); // use embed.ly
            embedService.registerHandler(ngEmbedInstagramHandler); // Use embed.ly
            embedService.registerHandler(ngEmbedTwitterHandler); // use embed.ly, load a script to render the card.
            embedService.registerHandler(ngEmbedPictureHandler); // use embed.ly, and provide a `thumbnail_url` field from the `url`
        }
    ]);
    return app;
});
<|endoftext|>


<commit_before>
var React = require('react-native');
var HOST = require('../../../config.js');

var { Image, } = React;

class Thumbnail extends React.Component {

	render(){
		var window = require('Dimensions').get('window');
		var uri = HOST + 'images?image=' + this.props.uri;

		var height = 100;
		var resizeMode = Image.resizeMode.cover;

		if (this.props.fullResolution){
			//Square image. Minus a small amount to eliminate any white border.
			if (this.props.height>=500){
				height = this.props.height-10;
			}else{
				height = (this.props.height * (window.width/500))-5;
			}
			resizeMode = Image.resizeMode.contain;
		}

		return (
			<Image
        style={{height: height, resizeMode: resizeMode }}
        source={{uri: uri }}
      />
		);
	}
}

module.exports = Thumbnail;

// /thumb = '<thumbnails>'Thumbnails({ some: propertie });
<commit_msg>thumbnails/ default to square<commit_after>
var React = require('react-native');
var HOST = require('../../../config.js');

var { Image, } = React;

class Thumbnail extends React.Component {

	render(){
		var window = require('Dimensions').get('window');
		var uri = HOST + 'images?image=' + this.props.uri;

		var height = window.width;
		var resizeMode = Image.resizeMode.cover;

		if (this.props.fullResolution){
			//Square image. Minus a small amount to eliminate any white border.
			if (this.props.height>=500){
				height = this.props.height-10;
			}else{
				height = (this.props.height * (window.width/500))-5;
			}
			resizeMode = Image.resizeMode.contain;
		}

		return (
			<Image
        style={{height: height, resizeMode: resizeMode }}
        source={{uri: uri }}
      />
		);
	}
}

module.exports = Thumbnail;

// /thumb = '<thumbnails>'Thumbnails({ some: propertie });
<|endoftext|>


<commit_before>'use strict';

/*
 * Bilateral view controller : api call and data manipulation to serve three
 * visualisations (dualtimeline, brushing & comparison timeline). ******
 */

angular.module('ricardo.controllers.bilateral', [])
  .controller('bilateral', [ "$scope", "$location", "reportingEntities",
    "cfSource", "cfTarget", "apiService", "dataTableService", "utils",
    "DEFAULT_REPORTING", "DEFAULT_PARTNER", "TABLE_HEADERS", function ($scope, $location, reportingEntities,
    cfSource, cfTarget, apiService, dataTableService, utils,
    DEFAULT_REPORTING, DEFAULT_PARTNER, TABLE_HEADERS) {

    /*
     * Display message if error in selection
     */
     $scope.ok = function () {
      $scope.missing = "0";
    };

    $scope.okTarget = function () {
      $scope.missingTarget = "0";

    };

    $scope.fieldsByDefault = function () {
      $scope.missingTarget = "0";
      localStorage.removeItem('selectedMinDate');
      localStorage.removeItem('selectedMaxDate');
      localStorage.removeItem('targetEntitySelected');
      window.location.reload();
    }

    $scope.closeAlert = function(index) {
      $scope.alerts.splice(index, 1);
      };

    /*
     * Var initialisation
     */
    var data
    $scope.reportingEntities = reportingEntities;
    $scope.actualCurrency = "sterling pound"
    $scope.tableData = [];
    $scope.totalServerItems = 0;
    $scope.alerts = []

    /*
     * Data table init
     */
    $scope.viewTable = 0;
    $scope.pagingOptions = {
        pageSizes: [50],
        pageSize: 50,
        currentPage: 1
    };

    // States
    $scope.timelineData
    $scope.entities = {sourceEntity : {}, targetEntity : {}}
    $scope.rawMinDate
    $scope.rawMaxDate
    // $scope.selectedMinDate = 1787;
    // $scope.selectedMaxDate = 1938;
    $scope.rawYearsRange
    $scope.rawYearsRange_forInf
    $scope.rawYearsRange_forSup

    /*
     * First init - check if data are in local storage
     */
    try {
      if (localStorage.sourceEntitySelected && localStorage.targetEntitySelected)
      {
        $scope.entities.sourceEntity.selected = JSON.parse(localStorage.getItem('sourceEntitySelected'));
        $scope.entities.targetEntity.selected = JSON.parse(localStorage.getItem('targetEntitySelected'));
        init($scope.entities.sourceEntity.selected.RICid, $scope.entities.targetEntity.selected.RICid);
      }
      else if (localStorage.sourceEntitySelected && !localStorage.targetEntitySelected)
      {
        $scope.entities.sourceEntity.selected = JSON.parse(localStorage.getItem('sourceEntitySelected'));
        apiService
          .getFlows({reporting_ids:$scope.entities.sourceEntity.selected.RICid})
          .then(function (result) {
            for (var i=0, len = result.flows.length; i < len; i++) {
              if (!/^World/.test(result.flows[i].partner_id)) {
                var target = {RICid:"", name:""};
                target.RICid = result.flows[i].partner_id;
                target.RICname = result.flows[i].partner_id;
                $scope.entities.targetEntity.selected = target;
                break;
              }
              i++;
            }
            localStorage.targetEntitySelected = $scope.entities.targetEntity.selected
            $scope.selectedMinDate = JSON.parse(localStorage.getItem('selectedMinDate'))
            $scope.selectedMaxDate = JSON.parse(localStorage.getItem('selectedMaxDate'))
            if ($scope.entities.targetEntity.selected !== undefined)
              init($scope.entities.sourceEntity.selected.RICid,
                $scope.entities.targetEntity.selected.RICid,
                $scope.selectedMinDate, $scope.selectedMaxDate);
          })
      }
      else
      {
        $scope.entities.sourceEntity.selected = $scope.reportingEntities.filter(function(e){
        return e.RICid===DEFAULT_REPORTING})[0]
        $scope.entities.targetEntity.selected = $scope.reportingEntities.filter(function(e){
        return e.RICid===DEFAULT_PARTNER})[0]
        init(DEFAULT_REPORTING, DEFAULT_PARTNER);
      }
    }
    catch (e) {
      console.log("e", e);
      // $scope.entities.sourceEntity.selected = $scope.reportingEntities.filter(function(e){
      //   return e.RICid===DEFAULT_REPORTING})[0]
      // $scope.entities.targetEntity.selected = $scope.reportingEntities.filter(function(e){
      //   return e.RICid===DEFAULT_PARTNER})[0]
      // init(DEFAULT_REPORTING, DEFAULT_PARTNER);
    }

    function init(sourceID, targetID, minDate, maxDate) {
      if (targetID !== undefined) {
        apiService
          .getFlows({reporting_ids: sourceID, partner_ids: targetID, with_sources: 1})
          .then(function (data){
            /*
             * Set min & max dates
             */
            $scope.rawMinDate = d3.min( data.flows, function(d) {
              return d.year;
            })
            $scope.rawMaxDate = d3.max( data.flows, function(d) {
              return d.year;
            })

            if (minDate && maxDate)
            {
              $scope.selectedMinDate = minDate;
              $scope.selectedMaxDate = maxDate;

            }
            else
            {
              // $scope.selectedMinDate = Math.max( $scope.selectedMinDate, $scope.rawMinDate )
              $scope.selectedMinDate = $scope.rawMinDate;

              // $scope.selectedMaxDate = Math.min( $scope.selectedMaxDate, $scope.rawMaxDate )
              $scope.selectedMaxDate = $scope.rawMaxDate;

            }

            /*
             * Consolidate data, add mirror's data to flows array
             */
            mergeMirrorInFlows(data)

            /*
             * Send data to timeline directive
             */
            $scope.timelineData = data.flows;

            /*
             * Save source & target in localStorage
             */
            localStorage.selectedMinDate = JSON.stringify($scope.selectedMinDate);
            localStorage.selectedMaxDate = JSON.stringify($scope.selectedMaxDate);
            localStorage.sourceEntitySelected = JSON.stringify($scope.entities.sourceEntity.selected);
            localStorage.targetEntitySelected = JSON.stringify($scope.entities.targetEntity.selected);

            // call function to send data to tableData
            updateDateRange(data)

          },function (res){
            if (res[1] === 500)
            {
              $scope.missingTarget = "1";
              if ($scope.entities.sourceEntity.selected.RICid == $scope.entities.targetEntity.selected.RICid) {
                $scope.message = "Same source and target " + $scope.entities.targetEntity.selected.RICname
              }
              else {
                $scope.message = "Missing Target " + $scope.entities.targetEntity.selected.RICname
              }
            }
          }
        )
      }
    }

    /*
     * Watch if entities and dates change
     */

    $scope.$watch("entities.sourceEntity.selected", function (newValue, oldValue){
      if(newValue !== oldValue && newValue){
        // set data in local storage
        localStorage.removeItem('sourceEntitySelected');
        localStorage.sourceEntitySelected = JSON.stringify(newValue);
        init(newValue.RICid, $scope.entities.targetEntity.selected.RICid, $scope.selectedMinDate, $scope.selectedMaxDate);
      }
    })

    $scope.$watch("entities.targetEntity.selected", function (newValue, oldValue){
      if(newValue !== oldValue && newValue){
        // set data in local storage
        localStorage.removeItem('targetEntitySelected');
        localStorage.targetEntitySelected = JSON.stringify(newValue);
        init($scope.entities.sourceEntity.selected.RICid, newValue.RICid, $scope.selectedMinDate, $scope.selectedMaxDate);
      }
    })

    $scope.$watchCollection('[selectedMinDate, selectedMaxDate]', function (newValue, oldValue) {
      if (newValue !== oldValue && newValue[0] !== newValue[1]) {
        // set data in local storage
        localStorage.removeItem('selectedMinDate');
        localStorage.removeItem('selectedMaxDate');
        localStorage.selectedMinDate = newValue[0];
        localStorage.selectedMaxDate = newValue[1];
        updateDateRange()
      }
    })

    /*
     * Update Range from date on flows array
     */
    function updateDateRange(data){
        $scope.rawYearsRange = d3.range( $scope.rawMinDate, $scope.rawMaxDate + 1 )
        $scope.rawYearsRange_forInf = d3.range( $scope.rawMinDate, $scope.selectedMaxDate )
        $scope.rawYearsRange_forSup = d3.range( $scope.selectedMinDate + 1, $scope.rawMaxDate + 1 )
      if (data !== undefined) {
        cfSource.clear()
        cfSource.add(data.flows.filter(function(d){
          return d.year >= $scope.selectedMinDate && d.year <= $scope.selectedMaxDate;
        }));

        cfTarget.clear()
        cfTarget.add(data.mirror_flows.filter(function(d){
          return d.year >= $scope.selectedMinDate && d.year <= $scope.selectedMaxDate;
        }));

        $scope.tableData = cfSource.year().top(Infinity).concat(cfTarget.year().top(Infinity));

        // Select data to check if there are and if not, display message no data
        var dataFilterBySource = d3.nest()
          .key(function (d) {return d.reporting_id})
          .entries($scope.tableData);

        if (dataFilterBySource[0] !== undefined) {
          var missing;
          var allExpNull = dataFilterBySource[0].values.every(function (d) {
            return d.exp === null ;})
          var allImpNull = dataFilterBySource[0].values.every(function (d) {
            return d.imp === null ;})

          if (allExpNull && allImpNull) {
            missing = "1";
          }
          else {
            missing = "0";
          }
          $scope.missing = missing;
        }
      }
    }

    /*
     * Merge mirror array in flows array
     */
    function mergeMirrorInFlows(data){
      // exchange between countries by year
      var mirrorFlows_byYear = {}

      /*
       * First step : clean mirror_flows and push data into mirrorFlos_byYear
       */
      data.mirror_flows.forEach(function(d){
        var obj = mirrorFlows_byYear[d.year] || {}
        obj.imp = d.imp || null
        obj.exp = d.exp || null
        mirrorFlows_byYear[d.year] = obj // useless ?
      })

      /*
       * Second step : add mirror_flow to flow
       */

      data.flows.forEach(function(d){
        var mirror = mirrorFlows_byYear[d.year]
        if (mirror) {
          d.imp_mirror = mirror.imp || null
          d.exp_mirror = mirror.exp || null
        } else {
          d.imp_mirror = null
          d.exp_mirror = null
        }
      })
    }

    /*
     * Datatable initalisation & functions
     */

    $scope.tablePagedData = []
    $scope.gridOptions = {
      data: 'tablePagedData',
      enablePaging: true,
      showFooter: true,
      totalServerItems:'totalServerItems',
      pagingOptions: $scope.pagingOptions,
      enableRowSelection: false,
      footerRowHeight: 45,
      //useExternalPagination: true,
      useExternalSorting: true,
      columnDefs: TABLE_HEADERS,
      sortInfo: {
        fields: ["year", "partner"],
        directions: ["asc"]
      }
    }

    function setPagingData(data, pageSize, page){
          var pagedData = data.slice((page - 1) * pageSize, page * pageSize);
          $scope.tablePagedData = pagedData;
          $scope.totalServerItems = data.length;
          $scope.loading = false;
          if (!$scope.$$phase) {
              $scope.$apply();
          }
      }

    $scope.$watch('tableData', function (newVal, oldVal) {
        if (newVal !== oldVal) {
          setPagingData($scope.tableData, $scope.pagingOptions.pageSize,
            $scope.pagingOptions.currentPage);
        }
    }, true);

    $scope.$watch('pagingOptions', function (newVal, oldVal) {
        if (newVal !== oldVal && newVal.currentPage !== oldVal.currentPage) {
          setPagingData($scope.tableData,$scope.pagingOptions.pageSize,
            $scope.pagingOptions.currentPage);
        }
    }, true);

    /*
     * Watch filter on colomn and changed data
     */
    $scope.$watch('gridOptions.sortInfo', function (newVal, oldVal) {
        if ($scope.tableData) {
          $scope.loading = true;
          dataTableService.sortData($scope.tableData, newVal.fields[0], newVal.directions[0]);
          setPagingData($scope.tableData,$scope.pagingOptions.pageSize,
            $scope.pagingOptions.currentPage);
          $scope.pagingOptions.currentPage = $scope.pagingOptions.currentPage;
        }
    }, true);

    /*
     * Download data selected
     */

    $scope.download = function() {
      var fileName = "RICardo - Bilateral - " + $scope.entities.sourceEntity.selected.RICid
      + ' - ' + $scope.entities.targetEntity.selected.RICid + ' - ' + $scope.selectedMinDate
      + ' - ' + $scope.selectedMaxDate;
      var headers = TABLE_HEADERS.map(function(h) {
        return h.displayName;
      });

      var order = TABLE_HEADERS.map(function(h) {
        return h.field;
      });

      var data = $scope.tableData;
      utils.downloadCSV(data, headers, order, fileName);
    };
  }])<commit_msg>fix date selection issue on tableData in 3 views<commit_after>'use strict';

/*
 * Bilateral view controller : api call and data manipulation to serve three
 * visualisations (dualtimeline, brushing & comparison timeline). ******
 */

angular.module('ricardo.controllers.bilateral', [])
  .controller('bilateral', [ "$scope", "$location", "reportingEntities",
    "cfSource", "cfTarget", "apiService", "dataTableService", "utils",
    "DEFAULT_REPORTING", "DEFAULT_PARTNER", "TABLE_HEADERS", function ($scope, $location, reportingEntities,
    cfSource, cfTarget, apiService, dataTableService, utils,
    DEFAULT_REPORTING, DEFAULT_PARTNER, TABLE_HEADERS) {

    /*
     * Display message if error in selection
     */
     $scope.ok = function () {
      $scope.missing = "0";
    };

    $scope.okTarget = function () {
      $scope.missingTarget = "0";

    };

    $scope.fieldsByDefault = function () {
      $scope.missingTarget = "0";
      localStorage.removeItem('selectedMinDate');
      localStorage.removeItem('selectedMaxDate');
      localStorage.removeItem('targetEntitySelected');
      window.location.reload();
    }

    $scope.closeAlert = function(index) {
      $scope.alerts.splice(index, 1);
      };

    /*
     * Var initialisation
     */
    var data
    $scope.reportingEntities = reportingEntities;
    $scope.actualCurrency = "sterling pound"
    $scope.tableData = [];
    $scope.totalServerItems = 0;
    $scope.alerts = []

    /*
     * Data table init
     */
    $scope.viewTable = 0;
    $scope.pagingOptions = {
        pageSizes: [50],
        pageSize: 50,
        currentPage: 1
    };

    // States
    $scope.timelineData
    $scope.entities = {sourceEntity : {}, targetEntity : {}}
    $scope.rawMinDate
    $scope.rawMaxDate
    // $scope.selectedMinDate = 1787;
    // $scope.selectedMaxDate = 1938;
    $scope.rawYearsRange
    $scope.rawYearsRange_forInf
    $scope.rawYearsRange_forSup

    /*
     * First init - check if data are in local storage
     */
    try {
      if (localStorage.sourceEntitySelected && localStorage.targetEntitySelected)
      {
        $scope.entities.sourceEntity.selected = JSON.parse(localStorage.getItem('sourceEntitySelected'));
        $scope.entities.targetEntity.selected = JSON.parse(localStorage.getItem('targetEntitySelected'));
        init($scope.entities.sourceEntity.selected.RICid, $scope.entities.targetEntity.selected.RICid);
      }
      else if (localStorage.sourceEntitySelected && !localStorage.targetEntitySelected)
      {
        $scope.entities.sourceEntity.selected = JSON.parse(localStorage.getItem('sourceEntitySelected'));
        apiService
          .getFlows({reporting_ids:$scope.entities.sourceEntity.selected.RICid})
          .then(function (result) {
            for (var i=0, len = result.flows.length; i < len; i++) {
              if (!/^World/.test(result.flows[i].partner_id)) {
                var target = {RICid:"", name:""};
                target.RICid = result.flows[i].partner_id;
                target.RICname = result.flows[i].partner_id;
                $scope.entities.targetEntity.selected = target;
                break;
              }
              i++;
            }
            localStorage.targetEntitySelected = $scope.entities.targetEntity.selected
            $scope.selectedMinDate = JSON.parse(localStorage.getItem('selectedMinDate'))
            $scope.selectedMaxDate = JSON.parse(localStorage.getItem('selectedMaxDate'))
            if ($scope.entities.targetEntity.selected !== undefined)
              init($scope.entities.sourceEntity.selected.RICid,
                $scope.entities.targetEntity.selected.RICid,
                $scope.selectedMinDate, $scope.selectedMaxDate);
          })
      }
      else
      {
        $scope.entities.sourceEntity.selected = $scope.reportingEntities.filter(function(e){
        return e.RICid===DEFAULT_REPORTING})[0]
        $scope.entities.targetEntity.selected = $scope.reportingEntities.filter(function(e){
        return e.RICid===DEFAULT_PARTNER})[0]
        init(DEFAULT_REPORTING, DEFAULT_PARTNER);
      }
    }
    catch (e) {
      console.log("e", e);
      // $scope.entities.sourceEntity.selected = $scope.reportingEntities.filter(function(e){
      //   return e.RICid===DEFAULT_REPORTING})[0]
      // $scope.entities.targetEntity.selected = $scope.reportingEntities.filter(function(e){
      //   return e.RICid===DEFAULT_PARTNER})[0]
      // init(DEFAULT_REPORTING, DEFAULT_PARTNER);
    }

    function init(sourceID, targetID, minDate, maxDate) {
      if (targetID !== undefined) {
        apiService
          .getFlows({reporting_ids: sourceID, partner_ids: targetID, with_sources: 1})
          .then(function (data){
            /*
             * Set min & max dates
             */
            $scope.rawMinDate = d3.min( data.flows, function(d) {
              return d.year;
            })
            $scope.rawMaxDate = d3.max( data.flows, function(d) {
              return d.year;
            })

            if (minDate && maxDate)
            {
              $scope.selectedMinDate = minDate;
              $scope.selectedMaxDate = maxDate;

            }
            else
            {
              // $scope.selectedMinDate = Math.max( $scope.selectedMinDate, $scope.rawMinDate )
              $scope.selectedMinDate = $scope.rawMinDate;

              // $scope.selectedMaxDate = Math.min( $scope.selectedMaxDate, $scope.rawMaxDate )
              $scope.selectedMaxDate = $scope.rawMaxDate;

            }

            /*
             * Consolidate data, add mirror's data to flows array
             */
            mergeMirrorInFlows(data)

            /*
             * save data to scope
             */
            $scope.allData=data;
            /*
             * Send data to timeline directive
             */
            $scope.timelineData = data.flows;

            /*
             * Save source & target in localStorage
             */
            localStorage.selectedMinDate = JSON.stringify($scope.selectedMinDate);
            localStorage.selectedMaxDate = JSON.stringify($scope.selectedMaxDate);
            localStorage.sourceEntitySelected = JSON.stringify($scope.entities.sourceEntity.selected);
            localStorage.targetEntitySelected = JSON.stringify($scope.entities.targetEntity.selected);

            // call function to send data to tableData
            updateDateRange();

          },function (res){
            if (res[1] === 500)
            {
              $scope.missingTarget = "1";
              if ($scope.entities.sourceEntity.selected.RICid == $scope.entities.targetEntity.selected.RICid) {
                $scope.message = "Same source and target " + $scope.entities.targetEntity.selected.RICname
              }
              else {
                $scope.message = "Missing Target " + $scope.entities.targetEntity.selected.RICname
              }
            }
          }
        )
      }
    }

    /*
     * Watch if entities and dates change
     */

    $scope.$watch("entities.sourceEntity.selected", function (newValue, oldValue){
      if(newValue !== oldValue && newValue){
        // set data in local storage
        localStorage.removeItem('sourceEntitySelected');
        localStorage.sourceEntitySelected = JSON.stringify(newValue);
        init(newValue.RICid, $scope.entities.targetEntity.selected.RICid, $scope.selectedMinDate, $scope.selectedMaxDate);
      }
    })

    $scope.$watch("entities.targetEntity.selected", function (newValue, oldValue){
      if(newValue !== oldValue && newValue){
        // set data in local storage
        localStorage.removeItem('targetEntitySelected');
        localStorage.targetEntitySelected = JSON.stringify(newValue);
        init($scope.entities.sourceEntity.selected.RICid, newValue.RICid, $scope.selectedMinDate, $scope.selectedMaxDate);
      }
    })

    $scope.$watchCollection('[selectedMinDate, selectedMaxDate]', function (newValue, oldValue) {
      if (newValue !== oldValue && newValue[0] !== newValue[1]) {
        // set data in local storage
        localStorage.removeItem('selectedMinDate');
        localStorage.removeItem('selectedMaxDate');
        localStorage.selectedMinDate = newValue[0];
        localStorage.selectedMaxDate = newValue[1];
        updateDateRange()
      }
    })

    /*
     * Update Range from date on flows array
     */
    function updateDateRange(){
        $scope.rawYearsRange = d3.range( $scope.rawMinDate, $scope.rawMaxDate + 1 )
        $scope.rawYearsRange_forInf = d3.range( $scope.rawMinDate, $scope.selectedMaxDate )
        $scope.rawYearsRange_forSup = d3.range( $scope.selectedMinDate + 1, $scope.rawMaxDate + 1 )
      if ($scope.allData !== undefined) {
        console.log($scope.allData);
        cfSource.clear()
        cfSource.add($scope.allData.flows.filter(function(d){
          return d.year >= $scope.selectedMinDate && d.year <= $scope.selectedMaxDate;
        }));

        cfTarget.clear()
        cfTarget.add($scope.allData.mirror_flows.filter(function(d){
          return d.year >= $scope.selectedMinDate && d.year <= $scope.selectedMaxDate;
        }));

        $scope.tableData = cfSource.year().top(Infinity).concat(cfTarget.year().top(Infinity));
        console.log($scope.tableData);
        // Select data to check if there are and if not, display message no data
        var dataFilterBySource = d3.nest()
          .key(function (d) {return d.reporting_id})
          .entries($scope.tableData);

        if (dataFilterBySource[0] !== undefined) {
          var missing;
          var allExpNull = dataFilterBySource[0].values.every(function (d) {
            return d.exp === null ;})
          var allImpNull = dataFilterBySource[0].values.every(function (d) {
            return d.imp === null ;})

          if (allExpNull && allImpNull) {
            missing = "1";
          }
          else {
            missing = "0";
          }
          $scope.missing = missing;
        }
      }
    }

    /*
     * Merge mirror array in flows array
     */
    function mergeMirrorInFlows(data){
      // exchange between countries by year
      var mirrorFlows_byYear = {}

      /*
       * First step : clean mirror_flows and push data into mirrorFlos_byYear
       */
      data.mirror_flows.forEach(function(d){
        var obj = mirrorFlows_byYear[d.year] || {}
        obj.imp = d.imp || null
        obj.exp = d.exp || null
        mirrorFlows_byYear[d.year] = obj // useless ?
      })

      /*
       * Second step : add mirror_flow to flow
       */

      data.flows.forEach(function(d){
        var mirror = mirrorFlows_byYear[d.year]
        if (mirror) {
          d.imp_mirror = mirror.imp || null
          d.exp_mirror = mirror.exp || null
        } else {
          d.imp_mirror = null
          d.exp_mirror = null
        }
      })
    }

    /*
     * Datatable initalisation & functions
     */

    $scope.tablePagedData = []
    $scope.gridOptions = {
      data: 'tablePagedData',
      enablePaging: true,
      showFooter: true,
      totalServerItems:'totalServerItems',
      pagingOptions: $scope.pagingOptions,
      enableRowSelection: false,
      footerRowHeight: 45,
      //useExternalPagination: true,
      useExternalSorting: true,
      columnDefs: TABLE_HEADERS,
      sortInfo: {
        fields: ["year", "partner"],
        directions: ["asc"]
      }
    }

    function setPagingData(data, pageSize, page){
          var pagedData = data.slice((page - 1) * pageSize, page * pageSize);
          $scope.tablePagedData = pagedData;
          $scope.totalServerItems = data.length;
          $scope.loading = false;
          if (!$scope.$$phase) {
              $scope.$apply();
          }
      }

    $scope.$watch('tableData', function (newVal, oldVal) {
        if (newVal !== oldVal) {
          setPagingData($scope.tableData, $scope.pagingOptions.pageSize,
            $scope.pagingOptions.currentPage);
        }
    }, true);

    $scope.$watch('pagingOptions', function (newVal, oldVal) {
        if (newVal !== oldVal && newVal.currentPage !== oldVal.currentPage) {
          setPagingData($scope.tableData,$scope.pagingOptions.pageSize,
            $scope.pagingOptions.currentPage);
        }
    }, true);

    /*
     * Watch filter on colomn and changed data
     */
    $scope.$watch('gridOptions.sortInfo', function (newVal, oldVal) {
        if ($scope.tableData) {
          $scope.loading = true;
          dataTableService.sortData($scope.tableData, newVal.fields[0], newVal.directions[0]);
          setPagingData($scope.tableData,$scope.pagingOptions.pageSize,
            $scope.pagingOptions.currentPage);
          $scope.pagingOptions.currentPage = $scope.pagingOptions.currentPage;
        }
    }, true);

    /*
     * Download data selected
     */

    $scope.download = function() {
      var fileName = "RICardo - Bilateral - " + $scope.entities.sourceEntity.selected.RICid
      + ' - ' + $scope.entities.targetEntity.selected.RICid + ' - ' + $scope.selectedMinDate
      + ' - ' + $scope.selectedMaxDate;
      var headers = TABLE_HEADERS.map(function(h) {
        return h.displayName;
      });

      var order = TABLE_HEADERS.map(function(h) {
        return h.field;
      });

      var data = $scope.tableData;
      utils.downloadCSV(data, headers, order, fileName);
    };
  }])<|endoftext|>