<commit_before>/**
 * Angucomplete
 * Autocomplete directive for AngularJS
 * By Daryl Rowland
 */

angular.module('angucomplete', [] )
    .directive('angucomplete', function ($parse, $http, $sce) {
    return {
        restrict: 'EA',
        scope: {
            "id": "@id",
            "placeholder": "@placeholder",
            "selectedObject": "=selectedobject",
            "url": "@url",
            "dataField": "@datafield",
            "titleField": "@titlefield",
            "descriptionField": "@descriptionfield",
            "imageField": "@imagefield",
            "inputClass": "@inputclass",
            "userPause": "@pause",
            "localData": "=localdata",
            "searchFields": "@searchfields",
            "minLengthUser": "@minlength",
            "matchClass": "@matchclass"
        },
        template: '
<input id="{{id}}_value" ng-model="searchStr" type="text" placeholder="{{placeholder}}" class="{{inputClass}}" ng-keyup="keyPressed($event)"/>

Searching...

No results found

{{ result.title }}

{{result.description}}

',
        controller: function ( $scope ) {
            $scope.lastFoundWord = null;
            $scope.currentIndex = null;
            $scope.justChanged = false;
            $scope.searchTimer = null;
            $scope.searching = false;
            $scope.pause = 500;
            $scope.minLength = 3;

            if ($scope.minLengthUser && $scope.minLengthUser != "") {
                $scope.minLength = $scope.minLengthUser;
            }

            if ($scope.userPause) {
                $scope.pause = $scope.userPause;
            }

            $scope.processResults = function(responseData, str) {
                if (responseData && responseData.length > 0) {
                    $scope.results = [];

                    var titleFields = [];
                    if ($scope.titleField && $scope.titleField != "") {
                        titleFields = $scope.titleField.split(",");
                    }

                    for (var i = 0; i < responseData.length; i++) {
                        // Get title variables
                        var titleCode = "";

                        for (var t = 0; t < titleFields.length; t++) {
                            if (t > 0) {
                                titleCode = titleCode +  " + ' ' + ";
                            }
                            titleCode = titleCode + "responseData[i]." + titleFields[t];
                        }

                        var description = "";
                        if ($scope.descriptionField) {
                            description = $scope.extractValue(responseData[i], $scope.descriptionField);
                        }

                        var image = "";
                        if ($scope.imageField) {
                            image = $scope.extractValue(responseData[i], $scope.imageField);
                        }

                        var text = eval(titleCode);
                        if ($scope.matchClass) {
                            var re = new RegExp(str, 'i');
                            var strPart = text.match(re)[0];
                            text = $sce.trustAsHtml(text.replace(re, ''+ strPart +''));
                        }

                        var resultRow = {
                            title: text,
                            description: description,
                            image: image,
                            originalObject: responseData[i]
                        }

                        $scope.results[$scope.results.length] = resultRow;
                    }

                } else {
                    $scope.results = [];
                }
            }

            $scope.searchTimerComplete = function(str) {
                // Begin the search

                if (str.length >= $scope.minLength) {
                    if ($scope.localData) {
                        var searchFields = $scope.searchFields.split(",");

                        var matches = [];

                        for (var i = 0; i < $scope.localData.length; i++) {
                            var match = false;

                            for (var s = 0; s < searchFields.length; s++) {
                                var evalStr = 'match = match || ($scope.localData[i].' + searchFields[s] + '.toLowerCase().indexOf("' + str.toLowerCase() + '") >= 0)';
                                eval(evalStr);
                            }

                            if (match) {
                                matches[matches.length] = $scope.localData[i];
                            }
                        }

                        $scope.searching = false;
                        $scope.processResults(matches, str);
                        $scope.$apply();

                    } else {
                        $http.get($scope.url + str, {}).
                            success(function(responseData, status, headers, config) {
                                $scope.searching = false;
                                data = $scope.extractValue(responseData, $scope.dataField)
                                $scope.processResults(data, str);
                            }).
                            error(function(data, status, headers, config) {
                                console.log("error");
                            });
                    }
                }

            }

            $scope.extractValue = function(obj, key) {
                if (key) {
                    value = eval("obj." + key);
                } else {
                    value = obj;
                }
                return value;
            }

            $scope.hoverRow = function(index) {
                $scope.currentIndex = index;
            }

            $scope.keyPressed = function(event) {
                if (!(event.which == 38 || event.which == 40 || event.which == 13)) {
                    if (!$scope.searchStr || $scope.searchStr == "") {
                        $scope.showDropdown = false;
                    } else {

                        if ($scope.searchStr.length >= $scope.minLength) {
                            $scope.showDropdown = true;
                            $scope.currentIndex = -1;
                            $scope.results = [];

                            if ($scope.searchTimer) {
                                clearTimeout($scope.searchTimer);
                            }

                            $scope.searching = true;

                            $scope.searchTimer = setTimeout(function() {
                                $scope.searchTimerComplete($scope.searchStr);
                            }, $scope.pause);
                        }

                    }

                } else {
                    event.preventDefault();
                }
            }

            $scope.selectResult = function(result) {
                if ($scope.matchClass) {
                    result.title = result.title.toString().replace(/(<([^>]+)>)/ig, '');
                }
                $scope.searchStr = result.title;
                $scope.selectedObject = result;
                $scope.showDropdown = false;
                $scope.results = [];
                //$scope.$apply();
            }
        },

        link: function($scope, elem, attrs, ctrl) {

            elem.bind("keyup", function (event) {
                if(event.which === 40) {
                    if (($scope.currentIndex + 1) < $scope.results.length) {
                        $scope.currentIndex ++;
                        $scope.$apply();
                        event.preventDefault;
                        event.stopPropagation();
                    }

                    $scope.$apply();
                } else if(event.which == 38) {
                    if ($scope.currentIndex >= 1) {
                        $scope.currentIndex --;
                        $scope.$apply();
                        event.preventDefault;
                        event.stopPropagation();
                    }

                } else if (event.which == 13) {
                    if ($scope.currentIndex >= 0 && $scope.currentIndex < $scope.results.length) {
                        $scope.selectResult($scope.results[$scope.currentIndex]);
                        $scope.$apply();
                        event.preventDefault;
                        event.stopPropagation();
                    } else {
                        $scope.results = [];
                        $scope.$apply();
                        event.preventDefault;
                        event.stopPropagation();
                    }

                } else if (event.which == 27) {
                    $scope.results = [];
                    $scope.showDropdown = false;
                    $scope.$apply();
                } else if (event.which == 8) {
                    $scope.selectedObject = null;
                    $scope.$apply();
                }
            });

        }
    };
});

<commit_msg>Make extractValue a private function<commit_after>/**
 * Angucomplete
 * Autocomplete directive for AngularJS
 * By Daryl Rowland
 */

angular.module('angucomplete', [] )
    .directive('angucomplete', function ($parse, $http, $sce) {
    return {
        restrict: 'EA',
        scope: {
            "id": "@id",
            "placeholder": "@placeholder",
            "selectedObject": "=selectedobject",
            "url": "@url",
            "dataField": "@datafield",
            "titleField": "@titlefield",
            "descriptionField": "@descriptionfield",
            "imageField": "@imagefield",
            "inputClass": "@inputclass",
            "userPause": "@pause",
            "localData": "=localdata",
            "searchFields": "@searchfields",
            "minLengthUser": "@minlength",
            "matchClass": "@matchclass"
        },
        template: '
<input id="{{id}}_value" ng-model="searchStr" type="text" placeholder="{{placeholder}}" class="{{inputClass}}" ng-keyup="keyPressed($event)"/>

Searching...

No results found

{{ result.title }}

{{result.description}}

',
        controller: function ( $scope ) {
            $scope.lastFoundWord = null;
            $scope.currentIndex = null;
            $scope.justChanged = false;
            $scope.searchTimer = null;
            $scope.searching = false;
            $scope.pause = 500;
            $scope.minLength = 3;

            if ($scope.minLengthUser && $scope.minLengthUser != "") {
                $scope.minLength = $scope.minLengthUser;
            }

            if ($scope.userPause) {
                $scope.pause = $scope.userPause;
            }

            extractValue = function(obj, key) {
                if (key) {
                    value = eval("obj." + key);
                } else {
                    value = obj;
                }
                return value;
            }

            $scope.processResults = function(responseData, str) {
                if (responseData && responseData.length > 0) {
                    $scope.results = [];

                    var titleFields = [];
                    if ($scope.titleField && $scope.titleField != "") {
                        titleFields = $scope.titleField.split(",");
                    }

                    for (var i = 0; i < responseData.length; i++) {
                        // Get title variables
                        var titleCode = "";

                        for (var t = 0; t < titleFields.length; t++) {
                            if (t > 0) {
                                titleCode = titleCode +  " + ' ' + ";
                            }
                            titleCode = titleCode + "responseData[i]." + titleFields[t];
                        }

                        var description = "";
                        if ($scope.descriptionField) {
                            description = extractValue(responseData[i], $scope.descriptionField);
                        }

                        var image = "";
                        if ($scope.imageField) {
                            image = extractValue(responseData[i], $scope.imageField);
                        }

                        var text = eval(titleCode);
                        if ($scope.matchClass) {
                            var re = new RegExp(str, 'i');
                            var strPart = text.match(re)[0];
                            text = $sce.trustAsHtml(text.replace(re, ''+ strPart +''));
                        }

                        var resultRow = {
                            title: text,
                            description: description,
                            image: image,
                            originalObject: responseData[i]
                        }

                        $scope.results[$scope.results.length] = resultRow;
                    }

                } else {
                    $scope.results = [];
                }
            }

            $scope.searchTimerComplete = function(str) {
                // Begin the search

                if (str.length >= $scope.minLength) {
                    if ($scope.localData) {
                        var searchFields = $scope.searchFields.split(",");

                        var matches = [];

                        for (var i = 0; i < $scope.localData.length; i++) {
                            var match = false;

                            for (var s = 0; s < searchFields.length; s++) {
                                var evalStr = 'match = match || ($scope.localData[i].' + searchFields[s] + '.toLowerCase().indexOf("' + str.toLowerCase() + '") >= 0)';
                                eval(evalStr);
                            }

                            if (match) {
                                matches[matches.length] = $scope.localData[i];
                            }
                        }

                        $scope.searching = false;
                        $scope.processResults(matches, str);
                        $scope.$apply();

                    } else {
                        $http.get($scope.url + str, {}).
                            success(function(responseData, status, headers, config) {
                                $scope.searching = false;
                                data = extractValue(responseData, $scope.dataField)
                                $scope.processResults(data, str);
                            }).
                            error(function(data, status, headers, config) {
                                console.log("error");
                            });
                    }
                }

            }

            $scope.hoverRow = function(index) {
                $scope.currentIndex = index;
            }

            $scope.keyPressed = function(event) {
                if (!(event.which == 38 || event.which == 40 || event.which == 13)) {
                    if (!$scope.searchStr || $scope.searchStr == "") {
                        $scope.showDropdown = false;
                    } else {

                        if ($scope.searchStr.length >= $scope.minLength) {
                            $scope.showDropdown = true;
                            $scope.currentIndex = -1;
                            $scope.results = [];

                            if ($scope.searchTimer) {
                                clearTimeout($scope.searchTimer);
                            }

                            $scope.searching = true;

                            $scope.searchTimer = setTimeout(function() {
                                $scope.searchTimerComplete($scope.searchStr);
                            }, $scope.pause);
                        }

                    }

                } else {
                    event.preventDefault();
                }
            }

            $scope.selectResult = function(result) {
                if ($scope.matchClass) {
                    result.title = result.title.toString().replace(/(<([^>]+)>)/ig, '');
                }
                $scope.searchStr = result.title;
                $scope.selectedObject = result;
                $scope.showDropdown = false;
                $scope.results = [];
                //$scope.$apply();
            }
        },

        link: function($scope, elem, attrs, ctrl) {

            elem.bind("keyup", function (event) {
                if(event.which === 40) {
                    if (($scope.currentIndex + 1) < $scope.results.length) {
                        $scope.currentIndex ++;
                        $scope.$apply();
                        event.preventDefault;
                        event.stopPropagation();
                    }

                    $scope.$apply();
                } else if(event.which == 38) {
                    if ($scope.currentIndex >= 1) {
                        $scope.currentIndex --;
                        $scope.$apply();
                        event.preventDefault;
                        event.stopPropagation();
                    }

                } else if (event.which == 13) {
                    if ($scope.currentIndex >= 0 && $scope.currentIndex < $scope.results.length) {
                        $scope.selectResult($scope.results[$scope.currentIndex]);
                        $scope.$apply();
                        event.preventDefault;
                        event.stopPropagation();
                    } else {
                        $scope.results = [];
                        $scope.$apply();
                        event.preventDefault;
                        event.stopPropagation();
                    }

                } else if (event.which == 27) {
                    $scope.results = [];
                    $scope.showDropdown = false;
                    $scope.$apply();
                } else if (event.which == 8) {
                    $scope.selectedObject = null;
                    $scope.$apply();
                }
            });

        }
    };
});

<|endoftext|>


<commit_before>'use strict';

/* Controllers */

var analyticsControllers = angular.module('analyticsControllers', []);

/**
 * Dashboard Controller
 */
analyticsControllers.controller('DashboardCtrl', ['$scope', '$interval', '$timeout', 'DashboardSvc',
    function($scope, $interval, $timeout, DashboardSvc) {

		/**
		 * entries currently on display
		 */
		var entries = [];

		/**
		 * number of entries in page
		 */
		var pageSize = 5;

		/**
		 * total number of pages
		 */
		var totalPages = 1;

		var updatePagingControlRequired = true;

		/**
		 * get data for the aggregates line
		 */
		var getAggregates = function getAggregates(liveOnly) {
			DashboardSvc.getAggregates(liveOnly).then (function(data) {
				var o = data.objects[0];
				var results = [
				           	{"title" : liveOnly ? "audience" : "plays",
				           		"value" : liveOnly ? o.audience : o.plays,
				           		"tooltip" : liveOnly ? "agg_audience_tt" : "agg_plays_tt"},
				        	{"title": "seconds_viewed", "value": o.secondsViewed, "tooltip":"agg_secs_tt"},
				        	{"title": "buffertime", "value": o.bufferTime, "tooltip":"agg_buffer_tt"},
				        	{"title": "bitrate", "value": o.avgBitrate, "tooltip":"agg_bitrate_tt"}
				        ];

				$scope.aggregates = results;
				// reactivate tooltips
				$timeout(function() {$('.tooltip-wrap').tooltip();}, 0);
			});
		};

		/**
		 * @param liveOnly	fetch KalturaLive currently live (true) or all live entries (false)
		 * @param pageNumber index of page to fetch
		 */
		var getEntries = function getEntries(liveOnly, pageNumber) {
			var result;
			if (liveOnly) {
				result = DashboardSvc.getLiveEntries(pageNumber);
			}
			else {
				result = DashboardSvc.getAllEntries(pageNumber);
			}

			result.then(function(data) {
				$scope.entries = data.objects;
				totalPages = Math.ceil(data.totalCount/pageSize);
				if (updatePagingControlRequired) {
					updatePagingControl(pageNumber, totalPages);
					updatePagingControlRequired = false;
				}
			});
		};

		/**
		 * get entries data by page
		 * @param e
		 * @param oldPage
		 * @param newPage
		 */
		var doPaging = function doPaging(e,oldPage,newPage) {
			getEntries($scope.boardType == "liveOnly", newPage);
		};

		/**
		 * update paging control
		 * @param current	index of current page
		 * @param total		total number of pages
		 */
		var updatePagingControl = function updatePagingControl(current, total) {
			if (total < 1) total = 1; // it's only for display..
			var options = {
	                currentPage: current,
	                totalPages: total
	            };
	        $('#pagination').bootstrapPaginator(options);
		};

		/**
		 * initial screen set up
		 */
		var screenSetup = function screenSetup() {
			// set report dates:
			var d = new Date();
			$scope.nowTime = d;
			d = new Date();
			d.setHours(d.getHours() - 36);
			$scope.reportStartTime = d;

			var options = {
					bootstrapMajorVersion: 3,
					onPageChanged: doPaging,
					shouldShowPage:function(type, page, current){
		                switch(type) {
		                    case "first":
		                    case "last":
		                        return false;
		                    default:
		                        return true;
		                }
		            },
		            alignment: 'center',
		            currentPage: 1,
		            totalPages: totalPages
		    };

		    $('#pagination').bootstrapPaginator(options);

		    $scope.boardType = "all";
			$scope.$watch("boardType", function(newValue, oldValue) {
				getAggregates(newValue == "liveOnly");
	    		getEntries(newValue == "liveOnly", 1);
				updatePagingControlRequired = true;
			 });
		};

		screenSetup();

    }]);

/**
 * General controller for the entry drill-down page
 */
analyticsControllers.controller('EntryCtrl', ['$scope', '$rootScope', '$routeParams', '$interval', '$timeout', 'SessionInfo', 'EntrySvc',
    function($scope, $rootScope, $routeParams, $interval, $timeout, SessionInfo, EntrySvc) {
		$scope.intervalPromise = null; 			// use this to hold update interval
		$scope.entryId = $routeParams.entryid;	// current entry
		$scope.pid = SessionInfo.pid;
		$scope.uiconfId = SessionInfo.uiconfid;
		$scope.playerEntryId = '';				// entry that should be shown in player (live / vod)
		$rootScope.nonav = $routeParams.nonav == 'nonav';

		/**
		 * get data for the aggregates line
		 * @param isLive is the entry currently broadcasting
		 */
		var getAggregates = function getAggregates(isLive) {
			EntrySvc.getAggregates($scope.entryId, isLive).then (function(data) {
				var o;
				if (data.objects && data.objects.length > 0) {
					o = data.objects[0];
				}
				else {
					// create empty dummy object
					o = {'audience' : 0,
						'plays' : 0,
						'secondsViewed' : 0,
						'bufferTime' : 0,
						'avgBitrate' : 0
					};
				}
				var results = [
				           	{"title" : isLive ? "audience" : "plays",
				           		"value" : isLive ? o.audience : o.plays,
				           		"tooltip" : isLive ? "agg_audience_tt" : "agg_plays_tt"},
				        	{"title": "seconds_viewed", "value": o.secondsViewed, "tooltip":"agg_secs_tt"},
				        	{"title": "buffertime", "value": o.bufferTime, "tooltip":"agg_buffer_tt"},
				        	{"title": "bitrate", "value": o.avgBitrate, "tooltip":"agg_bitrate_tt"}
				        ];

				$scope.aggregates = results;
				// reactivate tooltips
				$timeout(function() {$('.tooltip-wrap').tooltip();}, 0);

				getReferrers(isLive, o.plays);

			});
		};

		/**
		 * get data for the top referrals table
		 * @param totalPlays
		 */
		var getReferrers = function getReferrers(isLive, totalPlays) {
			if (isLive) {
				// need to get the non-live entry stats and use the totalplays from there
				EntrySvc.getAggregates($scope.entryId, false).then (function(data) {
					var o;
					if (data.objects && data.objects.length > 0) {
						o = data.objects[0];
					}
					else {
						// create empty dummy object
						o = {'audience' : 0,
							'plays' : 0,
							'secondsViewed' : 0,
							'bufferTime' : 0,
							'avgBitrate' : 0
						};
					}
					getReferrers(false, o.plays);
				});
			}
			else {
				EntrySvc.getReferrers($scope.entryId).then (function(data) {
					var objects;
					if (data.objects && data.objects.length > 0) {
						objects = data.objects;
					}
					else {
						objects = new Array();
					}
					var results = new Array();
					var o;
					for (var i = 0; i<objects.length; i++) {
						o = {
								'domain': objects[i].referrer,
								'visits': objects[i].plays,
								'percents' : objects[i].plays / totalPlays
							};
						results.push(o);
					}
					$scope.referals = results;
				});
			}
		};

		/**
		 * get the entry in question
		 */
		var getEntry = function getEntry() {
			return EntrySvc.getEntry($scope.entryId).then(function(entry){
				$scope.entry = entry;
				if (entry.isLive) {
					// live session - show live entry in player
					$scope.playerEntryId = entry.id;
					// set 30 secs update interval
					$scope.intervalPromise = $interval(function() {screenUpdate();}, 30000);
				}
				else if (entry.recordedEntryId && entry.recordedEntryId != '') {
					// session ended, got recording - show recorded entry in player
					$scope.playerEntryId = entry.recordedEntryId;
				}
				else {
					// show "no recording" in player
					$scope.playerEntryId = -1;
				}
				// set report dates:
				var d = new Date();
				$scope.nowTime = d;
				$rootScope.$broadcast('setupScreen', Math.floor(d.getTime()/1000));
				d = new Date();
				d.setHours(d.getHours() - 36);
				$scope.reportStartTime = d;
				getAggregates(entry.isLive);

			});
		};

		var screenSetup = function screenSetup() {
			// report data:
			getEntry();
		};

		var screenUpdate = function screenUpdate() {
			var d = new Date();
			var t = d.getTime()/1000;

			$scope.nowTime = d;
			var d = new Date();
			d.setHours(d.getHours() - 36);
			$scope.reportStartTime = d;
			getAggregates($scope.entry.isLive);
			$rootScope.$broadcast('updateScreen', t);
		};

		$scope.$on('$destroy', function() {
			// Make sure that the interval is destroyed too
			if (angular.isDefined($scope.intervalPromise)) {
				$interval.cancel($scope.intervalPromise);
				$scope.intervalPromise = undefined;
			}
		});

		screenSetup();
}]);
<commit_msg>PLAT-1825 dashboard auto refresh <commit_after>'use strict';

/* Controllers */

var analyticsControllers = angular.module('analyticsControllers', []);

/**
 * Dashboard Controller
 */
analyticsControllers.controller('DashboardCtrl', ['$scope', '$interval', '$timeout', 'DashboardSvc',
    function($scope, $interval, $timeout, DashboardSvc) {

		/**
		 * entries currently on display
		 */
		var entries = [];

		/**
		 * number of entries in page
		 */
		var pageSize = 6;

		/**
		 * total number of pages
		 */
		var totalPages = 1;

		var updatePagingControlRequired = true;

		/**
		 * get data for the aggregates line
		 */
		var getAggregates = function getAggregates(liveOnly) {
			DashboardSvc.getAggregates(liveOnly).then (function(data) {
				var o = data.objects[0];
				var results = [
				           	{"title" : liveOnly ? "audience" : "plays",
				           		"value" : liveOnly ? o.audience : o.plays,
				           		"tooltip" : liveOnly ? "agg_audience_tt" : "agg_plays_tt"},
				        	{"title": "seconds_viewed", "value": o.secondsViewed, "tooltip":"agg_secs_tt"},
				        	{"title": "buffertime", "value": o.bufferTime, "tooltip":"agg_buffer_tt"},
				        	{"title": "bitrate", "value": o.avgBitrate, "tooltip":"agg_bitrate_tt"}
				        ];

				$scope.aggregates = results;
				// reactivate tooltips
				$timeout(function() {$('.tooltip-wrap').tooltip();}, 0);
			});
		};

		/**
		 * @param liveOnly	fetch KalturaLive currently live (true) or all live entries (false)
		 * @param pageNumber index of page to fetch
		 */
		var getEntries = function getEntries(liveOnly, pageNumber) {
			var result;
			if (liveOnly) {
				result = DashboardSvc.getLiveEntries(pageNumber);
			}
			else {
				result = DashboardSvc.getAllEntries(pageNumber);
			}

			result.then(function(data) {
				$scope.entries = data.objects;
				totalPages = Math.ceil(data.totalCount/pageSize);
				if (updatePagingControlRequired) {
					updatePagingControl(pageNumber, totalPages);
					updatePagingControlRequired = false;
				}
			});
		};

		/**
		 * get entries data by page
		 * @param e
		 * @param oldPage
		 * @param newPage
		 */
		var doPaging = function doPaging(e,oldPage,newPage) {
			getEntries($scope.boardType == "liveOnly", newPage);
		};

		/**
		 * update paging control
		 * @param current	index of current page
		 * @param total		total number of pages
		 */
		var updatePagingControl = function updatePagingControl(current, total) {
			if (total < 1) total = 1; // it's only for display..
			var options = {
	                currentPage: current,
	                totalPages: total
	            };
	        $('#pagination').bootstrapPaginator(options);
		};

		/**
		 * initial screen set up
		 */
		var screenSetup = function screenSetup() {
			// set report dates:
			var d = new Date();
			$scope.nowTime = d;
			d = new Date();
			d.setHours(d.getHours() - 36);
			$scope.reportStartTime = d;

			var options = {
					bootstrapMajorVersion: 3,
					onPageChanged: doPaging,
					shouldShowPage:function(type, page, current){
		                switch(type) {
		                    case "first":
		                    case "last":
		                        return false;
		                    default:
		                        return true;
		                }
		            },
		            alignment: 'center',
		            currentPage: 1,
		            totalPages: totalPages
		    };

		    $('#pagination').bootstrapPaginator(options);

		    $scope.boardType = "all";
			$scope.$watch("boardType", function(newValue, oldValue) {
				getAggregates(newValue == "liveOnly");
	    		getEntries(newValue == "liveOnly", 1);
				updatePagingControlRequired = true;
			 });
			// set 30 secs update interval
			$scope.intervalPromise = $interval(function() {screenUpdate();}, 30000);
		};

		var screenUpdate = function screenUpdate() {
			var d = new Date();
			var t = d.getTime()/1000;

			$scope.nowTime = d;
			var d = new Date();
			d.setHours(d.getHours() - 36);
			$scope.reportStartTime = d;
			getAggregates($scope.boardType == "liveOnly");
			var pages = $('#pagination').bootstrapPaginator('getPages');
			getEntries($scope.boardType == "liveOnly", pages.current);
		};

		$scope.$on('$destroy', function() {
			// Make sure that the interval is destroyed too
			if (angular.isDefined($scope.intervalPromise)) {
				$interval.cancel($scope.intervalPromise);
				$scope.intervalPromise = undefined;
			}
		});

		screenSetup();

    }]);

/**
 * General controller for the entry drill-down page
 */
analyticsControllers.controller('EntryCtrl', ['$scope', '$rootScope', '$routeParams', '$interval', '$timeout', 'SessionInfo', 'EntrySvc',
    function($scope, $rootScope, $routeParams, $interval, $timeout, SessionInfo, EntrySvc) {
		$scope.intervalPromise = null; 			// use this to hold update interval
		$scope.entryId = $routeParams.entryid;	// current entry
		$scope.pid = SessionInfo.pid;
		$scope.uiconfId = SessionInfo.uiconfid;
		$scope.playerEntryId = '';				// entry that should be shown in player (live / vod)
		$rootScope.nonav = $routeParams.nonav == 'nonav';

		/**
		 * get data for the aggregates line
		 * @param isLive is the entry currently broadcasting
		 */
		var getAggregates = function getAggregates(isLive) {
			EntrySvc.getAggregates($scope.entryId, isLive).then (function(data) {
				var o;
				if (data.objects && data.objects.length > 0) {
					o = data.objects[0];
				}
				else {
					// create empty dummy object
					o = {'audience' : 0,
						'plays' : 0,
						'secondsViewed' : 0,
						'bufferTime' : 0,
						'avgBitrate' : 0
					};
				}
				var results = [
				           	{"title" : isLive ? "audience" : "plays",
				           		"value" : isLive ? o.audience : o.plays,
				           		"tooltip" : isLive ? "agg_audience_tt" : "agg_plays_tt"},
				        	{"title": "seconds_viewed", "value": o.secondsViewed, "tooltip":"agg_secs_tt"},
				        	{"title": "buffertime", "value": o.bufferTime, "tooltip":"agg_buffer_tt"},
				        	{"title": "bitrate", "value": o.avgBitrate, "tooltip":"agg_bitrate_tt"}
				        ];

				$scope.aggregates = results;
				// reactivate tooltips
				$timeout(function() {$('.tooltip-wrap').tooltip();}, 0);

				getReferrers(isLive, o.plays);

			});
		};

		/**
		 * get data for the top referrals table
		 * @param totalPlays
		 */
		var getReferrers = function getReferrers(isLive, totalPlays) {
			if (isLive) {
				// need to get the non-live entry stats and use the totalplays from there
				EntrySvc.getAggregates($scope.entryId, false).then (function(data) {
					var o;
					if (data.objects && data.objects.length > 0) {
						o = data.objects[0];
					}
					else {
						// create empty dummy object
						o = {'audience' : 0,
							'plays' : 0,
							'secondsViewed' : 0,
							'bufferTime' : 0,
							'avgBitrate' : 0
						};
					}
					getReferrers(false, o.plays);
				});
			}
			else {
				EntrySvc.getReferrers($scope.entryId).then (function(data) {
					var objects;
					if (data.objects && data.objects.length > 0) {
						objects = data.objects;
					}
					else {
						objects = new Array();
					}
					var results = new Array();
					var o;
					for (var i = 0; i<objects.length; i++) {
						o = {
								'domain': objects[i].referrer,
								'visits': objects[i].plays,
								'percents' : objects[i].plays / totalPlays
							};
						results.push(o);
					}
					$scope.referals = results;
				});
			}
		};

		/**
		 * get the entry in question
		 */
		var getEntry = function getEntry() {
			return EntrySvc.getEntry($scope.entryId).then(function(entry){
				$scope.entry = entry;
				if (entry.isLive) {
					// live session - show live entry in player
					$scope.playerEntryId = entry.id;
					// set 30 secs update interval
					$scope.intervalPromise = $interval(function() {screenUpdate();}, 30000);
				}
				else if (entry.recordedEntryId && entry.recordedEntryId != '') {
					// session ended, got recording - show recorded entry in player
					$scope.playerEntryId = entry.recordedEntryId;
				}
				else {
					// show "no recording" in player
					$scope.playerEntryId = -1;
				}
				// set report dates:
				var d = new Date();
				$scope.nowTime = d;
				$rootScope.$broadcast('setupScreen', Math.floor(d.getTime()/1000));
				d = new Date();
				d.setHours(d.getHours() - 36);
				$scope.reportStartTime = d;
				getAggregates(entry.isLive);

			});
		};

		var screenSetup = function screenSetup() {
			// report data:
			getEntry();
		};

		var screenUpdate = function screenUpdate() {
			var d = new Date();
			var t = d.getTime()/1000;

			$scope.nowTime = d;
			var d = new Date();
			d.setHours(d.getHours() - 36);
			$scope.reportStartTime = d;
			getAggregates($scope.entry.isLive);
			$rootScope.$broadcast('updateScreen', t);
		};

		$scope.$on('$destroy', function() {
			// Make sure that the interval is destroyed too
			if (angular.isDefined($scope.intervalPromise)) {
				$interval.cancel($scope.intervalPromise);
				$scope.intervalPromise = undefined;
			}
		});

		screenSetup();
}]);
<|endoftext|>


<commit_before>/**
 * ngAuth 0.0.1
 * (c) 2014 Sahat Yalkabov <sahat@me.com>
 * License: MIT
 */

angular.module('ngAuth', [])
  .provider('ngAuth', function() {
//    var config = {
//      apiUrl: '/api',
//      signOutUrl: '/auth/sign_out',
//      emailSignInPath: '/auth/sign_in',
//      emailRegistrationPath: '/auth',
//      confirmationSuccessUrl: window.location.href,
//      tokenValidationPath: '/auth/validate_token',
//      proxyIf: function() {
//        return false;
//      },
//      proxyUrl: '/proxy',
//      authProviderPaths: {
//        github: '/auth/github',
//        facebook: '/auth/facebook',
//        google: '/auth/google_oauth2'
//      }
//    };
    this.$get = ['$http', function($http) {
      return {
        hello: function() {
          console.log('Hello world');
        }
      };
    }];
  })
  .factory('Local', ['$http', '$location', '$rootScope', '$alert', '$window',
    function($http, $location, $rootScope, $alert, $window) {
      var token = $window.localStorage.token;

      if (token) {
        var payload = JSON.parse($window.atob(token.split('.')[1]));
        if (Date.now() > payload.exp) {
          $window.alert('Token has expired');
          delete $window.localStorage.token;
        } else {
          $rootScope.currentUser = payload.prn;
        }
      }

      return {
        login: function(user) {
          return $http.post('/api/login', user).success(function(data) {
            $window.localStorage.token = data.token;
            var token = $window.localStorage.token;
            var payload = JSON.parse($window.atob(token.split('.')[1]));
            $rootScope.currentUser = payload.prn;
            $location.path('/');
          });
        },
        signup: function(user) {
          return $http.post('/api/signup', user).success(function() {
            $location.path('/login');
          });
        },
        logout: function() {
          delete $window.localStorage.token;
          $rootScope.currentUser = null;
          $location.path('/');
        }
      };
    }])
  .factory('authInterceptor', function($q, $window, $location) {
    return {
      request: function(config) {
        if ($window.localStorage.token) {
          config.headers.Authorization = 'Bearer ' + $window.localStorage.token;
        }
        return config;
      },
      responseError: function(response) {
        if (response.status === 401) {
          $location.path('/login');
        }
        return $q.reject(response);
      }
    }
  })
  .config(['$httpProvider', function($httpProvider) {
    $httpProvider.interceptors.push('authInterceptor');
  }]);
<commit_msg>Redirect to /login on 403 response status<commit_after>/**
 * ngAuth 0.0.1
 * (c) 2014 Sahat Yalkabov <sahat@me.com>
 * License: MIT
 */

angular.module('ngAuth', [])
  .provider('ngAuth', function() {
//    var config = {
//      apiUrl: '/api',
//      signOutUrl: '/auth/sign_out',
//      emailSignInPath: '/auth/sign_in',
//      emailRegistrationPath: '/auth',
//      confirmationSuccessUrl: window.location.href,
//      tokenValidationPath: '/auth/validate_token',
//      proxyIf: function() {
//        return false;
//      },
//      proxyUrl: '/proxy',
//      authProviderPaths: {
//        github: '/auth/github',
//        facebook: '/auth/facebook',
//        google: '/auth/google_oauth2'
//      }
//    };
    this.$get = ['$http', function($http) {
      return {
        hello: function() {
          console.log('Hello world');
        }
      };
    }];
  })
  .factory('Local', ['$http', '$location', '$rootScope', '$alert', '$window',
    function($http, $location, $rootScope, $alert, $window) {
      var token = $window.localStorage.token;

      if (token) {
        var payload = JSON.parse($window.atob(token.split('.')[1]));
        if (Date.now() > payload.exp) {
          $window.alert('Token has expired');
          delete $window.localStorage.token;
        } else {
          $rootScope.currentUser = payload.prn;
        }
      }

      return {
        login: function(user) {
          return $http.post('/api/login', user).success(function(data) {
            $window.localStorage.token = data.token;
            var token = $window.localStorage.token;
            var payload = JSON.parse($window.atob(token.split('.')[1]));
            $rootScope.currentUser = payload.prn;
            $location.path('/');
          });
        },
        signup: function(user) {
          return $http.post('/api/signup', user).success(function() {
            $location.path('/login');
          });
        },
        logout: function() {
          delete $window.localStorage.token;
          $rootScope.currentUser = null;
          $location.path('/');
        }
      };
    }])
  .factory('authInterceptor', function($q, $window, $location) {
    return {
      request: function(config) {
        if ($window.localStorage.token) {
          config.headers.Authorization = 'Bearer ' + $window.localStorage.token;
        }
        return config;
      },
      responseError: function(response) {
        if (response.status === 401 || response.status === 403) {
          $location.path('/login');
        }
        return $q.reject(response);
      }
    }
  })
  .config(['$httpProvider', function($httpProvider) {
    $httpProvider.interceptors.push('authInterceptor');
  }]);
<|endoftext|>


<commit_before>import NodeGit from "nodegit"
import _ from "underscore"

// Public: Clones a public git repository to the specified destination directory,
// and notifies the caller of clone progress via callback.
//
// repoURL          - String containing the URL of the public Git repository. It
//                    should be possible to clone the repository with `git clone`
// destination      - String containing Absolute path where the repository files will
//                    be cloned.
// progressCallback - Callback Function used for notifying the caller of clone
//                    progress. The function is called with the percentage of object
//                    fetched.
//
// Examples
//
//    clone(
//      "https://github.com/education/classroom-desktop",
//      "/tmp/desktop-classroom",
//      (percentage) => {
//        console.log("Percentage complete: " + percentage + "%")
//      }
//    ).then(() => {
//      console.log("Finished cloning")
//    })
//
// Returns a Promise
export const clone = (repoURL, destination, progressCallback, token) => {
  return new Promise((resolve, reject) => {
    let progressOnCompletion = false

    const options = {
      fetchOpts: {
        callbacks: {

        }
      }
    }

    if (progressCallback) {
      options.fetchOpts.callbacks.transferProgress = _.throttle((progressInfo) => {
        const percentage = 100 * progressInfo.receivedObjects() / progressInfo.totalObjects()
        if (percentage === 100) progressOnCompletion = true
        progressCallback(percentage)
      }, 300, { trailing: false })
    }

    if (token) {
      options.fetchOpts.callbacks.credentials = function () {
        return NodeGit.Cred.userpassPlaintextNew(token, "x-oauth-basic")
      }
    }

    progressCallback(0)

    NodeGit.Clone(
      repoURL,
      destination,
      options
    ).then((repo) => {
      if (!progressOnCompletion && progressCallback) {
        progressCallback(100)
      }
      resolve()
    }).catch((err) => {
      reject(err)
    })
  })
}
<commit_msg>add clone utils changes from main branch<commit_after>import NodeGit from "nodegit"
import _ from "underscore"

// Public: Clones a public git repository to the specified destination directory,
// and notifies the caller of clone progress via callback.
//
// repoURL          - String containing the URL of the public Git repository. It
//                    should be possible to clone the repository with `git clone`
// destination      - String containing Absolute path where the repository files will
//                    be cloned.
// progressCallback - Callback Function used for notifying the caller of clone
//                    progress. The function is called with the percentage of object
//                    fetched.
//
// Examples
//
//    clone(
//      "https://github.com/education/classroom-desktop",
//      "/tmp/desktop-classroom",
//      (percentage) => {
//        console.log("Percentage complete: " + percentage + "%")
//      }
//    ).then(() => {
//      console.log("Finished cloning")
//    })
//
// Returns a Promise
export const clone = (repoURL, destination, progressCallback, token) => {
  return new Promise((resolve, reject) => {
    let progressOnCompletion = false

    const options = {
      fetchOpts: {
        callbacks: {

        }
      }
    }

    if (progressCallback) {
      options.fetchOpts.callbacks.transferProgress = _.throttle((progressInfo) => {
        const percentage = 100 * progressInfo.receivedObjects() / progressInfo.totalObjects()
        if (percentage === 100) progressOnCompletion = true
        progressCallback(percentage)
      }, 300, { trailing: false })
    }

    if (token) {
      options.fetchOpts.callbacks.certificate_check = () => { // for libgit2 problem
        return 1
      }
      options.fetchOpts.callbacks.credentials = () => {
        return NodeGit.Cred.userpassPlaintextNew(token, "x-oauth-basic")
      }
    }

    progressCallback(0)

    NodeGit.Clone(
      repoURL,
      destination,
      options
    ).then((repo) => {
      if (!progressOnCompletion && progressCallback) {
        progressCallback(100)
      }
      resolve()
    }).catch((err) => {
      reject(err)
    })
  })
}
<|endoftext|>


<commit_before>/**
 * ngAuth 0.0.1
 * (c) 2014 Sahat Yalkabov <sahat@me.com>
 * License: MIT
 */

// TODO: Enable CORS, separate server from client, Gulp server runner
// TODO: Provider return object, underscore private functions < 10loc
// TODO: Modular, enable/disable facebook or twitter or local auth
// TODO: directive for login buttons that interact with provider

angular.module('ngAuth', [])
  .provider('Auth', function() {

    var config = this.config = {
      logoutRedirect: '/',
      loginRedirect: '/',
      loginUrl: '/auth/login',
      signupUrl: '/auth/signup',
      signupRedirect: '/login',
      providers: {
        facebook: {
          url: '/auth/facebook',
          appId: null,
          scope: null,
          responseType: 'token',
          locale: 'en_US',
          version: 'v2.0'
        },
        google: {
          clientId: null,
          scope: null,
          redirectUri: null,
          responseType: 'token'
        },
        linkedin: {
          clientId: null,
          scope: null,
          redirectUri: null,
          responseType: 'token'
        }
      }
    };

    function loadLinkedinSdk() {
      (function() {
        var e = document.createElement('script');
        e.type = 'text/javascript';
        e.src = 'http://platform.linkedin.com/in.js?async=true';
        e.onload = function() {
          IN.init({
            api_key: '75z17ew9n8c2pm',
            authorize: true
          });
        };
        var s = document.getElementsByTagName('script')[0];
        s.parentNode.insertBefore(e, s);
      })();
    }

    function loadFacebookSdk($document, $window) {
      if (!$document[0].getElementById('fb-root')) {
        $document.find('body').append('

');
      }

      $window.fbAsyncInit = function() {
        FB.init(config.providers.facebook);
      };

      (function(d, s, id) {
        var js, fjs = d.getElementsByTagName(s)[0];
        if (d.getElementById(id)) {
          return;
        }
        js = d.createElement(s);
        js.id = id;
        js.src = "//connect.facebook.net/" + config.providers.facebook.locale + "/sdk.js";
        fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    }

    function loadGooglePlusSdk() {
      (function() {
        var po = document.createElement('script');
        po.type = 'text/javascript';
        po.async = true;
        po.src = 'https://apis.google.com/js/client:plusone.js';
        var s = document.getElementsByTagName('script')[0];
        s.parentNode.insertBefore(po, s);
      })();
    }

    return {
      facebook: function(params) {
        angular.extend(config.providers.facebook, params);
      },

      google: function(params) {
        angular.extend(config.providers.google, params);
      },

      linkedin: function(params) {
        angular.extend(config.providers.linkedin, params);
      },

      oauth2: function(params) {
        var provider = params.name;
        config.providers[provider] = config.providers[provider] || {};
        angular.extend(config.providers[provider], params);
      },

      $get: function($http, $location, $rootScope, $alert, $q, $injector, $window, $document) {

        var token = $window.localStorage.token;
        if (token) {
          var payload = JSON.parse($window.atob(token.split('.')[1]));
          $rootScope.currentUser = payload.user;
        }

        if (config.providers.linkedin.clientId) {
          loadLinkedinSdk();
        }

        if (config.providers.facebook.appId) {
          loadFacebookSdk($document, $window);
        }

        if (config.providers.google.clientId) {
          loadGooglePlusSdk();
        }

        function logout() {
          delete $window.localStorage.token;
          $rootScope.currentUser = null;
          $location.path(config.logoutRedirect);
        }

        function login(user) {
          return $http.post(config.loginUrl, user).success(function(data) {
            $window.localStorage.token = data.token;
            var payload = JSON.parse($window.atob(data.token.split('.')[1]));
            $rootScope.currentUser = payload.user;
            $location.path(config.loginRedirect);
          });
        }

        function signup(user) {
          return $http.post(config.signupUrl, user).success(function() {
            $location.path(config.signupRedirect);
          });
        }

        function loggedIn() {
          // TODO: return login status
        }

        function user() {
          // TODO: move rootscope to here
          // TODO: make a property
        }

        function loginOauth(provider) {
          provider = provider.trim().toLowerCase();

          switch (provider) {
            case 'facebook':
              var scope = config.providers.facebook.scope.join(',');
              FB.login(function(response) {
                FB.api('/me', function(profile) {
                  var data = {
                    signedRequest: response.authResponse.signedRequest,
                    profile: profile
                  };
                  $http.post(config.providers.facebook.url, data).success(function(token) {
                    var payload = JSON.parse($window.atob(token.split('.')[1]));
                    $window.localStorage.token = token;
                    $rootScope.currentUser = payload.user;
                    $location.path(config.loginRedirect);
                  });
                });
              }, { scope: scope });
              break;
            case 'google':
              gapi.auth.authorize({
                client_id: config.providers.google.clientId,
                scope: config.providers.google.scope,
                immediate: false
              }, function(token) {
                gapi.client.load('plus', 'v1', function() {
                  var request = gapi.client.plus.people.get({
                    userId: 'me'
                  });
                  request.execute(function(response) {
                    var data = {
                      accessToken: token.access_token,
                      profile: response
                    };
                    $http.post(config.providers.google.url, data).success(function(token) {
                      var payload = JSON.parse($window.atob(token.split('.')[1]));
                      $window.localStorage.token = token;
                      $rootScope.currentUser = payload.user;
                      $location.path(config.loginRedirect);
                    });
                  });
                });
              });
              console.log('google signin');
              break;
            case 'linkedin':
              console.log('sign in with linkedin');
              IN.UI.Authorize().place();
              IN.Event.on(IN, 'auth', function() {
                console.log('Logged in...');
                var data = {
                  signedRequest: response.authResponse.signedRequest,
                  profile: profile
                };
                $http.post(config.providers.facebook.url, data).success(function(token) {
                  var payload = JSON.parse($window.atob(token.split('.')[1]));
                  $window.localStorage.token = token;
                  $rootScope.currentUser = payload.user;
                  $location.path(config.loginRedirect);
                });
              });
              break;
            default:
              break;
          }
        }

        return {
          loginOauth: loginOauth,
          login: login,
          signup: signup,
          logout: logout,
          loggedIn: loggedIn,
          user: user
        };
      }
    };
  })
  .factory('authInterceptor', function($q, $window, $location) {
    return {
      request: function(config) {
        if ($window.localStorage.token) {
          config.headers.Authorization = 'Bearer ' + $window.localStorage.token;
        }
        return config;
      },
      responseError: function(response) {
        if (response.status === 401 || response.status === 403) {
          $location.path('/login');
        }
        return $q.reject(response);
      }
    }
  })
  .config(function($httpProvider) {
    $httpProvider.interceptors.push('authInterceptor');
  })
  .run(function($rootScope, $location) {
    $rootScope.$on('$routeChangeStart', function(event, current, previous) {
      if ($rootScope.currentUser &&
        (current.originalPath === '/login' || current.originalPath === '/signup')) {
        $location.path('/');
      }
      if (current.authenticated && !$rootScope.currentUser) {
        $location.path('/login');
      }
    });
  });
<commit_msg>Fetch user's data when authorized with linkedin<commit_after>/**
 * ngAuth 0.0.1
 * (c) 2014 Sahat Yalkabov <sahat@me.com>
 * License: MIT
 */

// TODO: Enable CORS, separate server from client, Gulp server runner
// TODO: Provider return object, underscore private functions < 10loc
// TODO: Modular, enable/disable facebook or twitter or local auth
// TODO: directive for login buttons that interact with provider

angular.module('ngAuth', [])
  .provider('Auth', function() {

    var config = this.config = {
      logoutRedirect: '/',
      loginRedirect: '/',
      loginUrl: '/auth/login',
      signupUrl: '/auth/signup',
      signupRedirect: '/login',
      providers: {
        facebook: {
          url: '/auth/facebook',
          appId: null,
          scope: null,
          responseType: 'token',
          locale: 'en_US',
          version: 'v2.0'
        },
        google: {
          clientId: null,
          scope: null,
          redirectUri: null,
          responseType: 'token'
        },
        linkedin: {
          clientId: null,
          scope: null,
          redirectUri: null,
          responseType: 'token'
        }
      }
    };

    function loadLinkedinSdk() {
      (function() {
        var e = document.createElement('script');
        e.type = 'text/javascript';
        e.src = 'http://platform.linkedin.com/in.js?async=true';
        e.onload = function() {
          IN.init({
            api_key: '75z17ew9n8c2pm',
            authorize: true
          });
        };
        var s = document.getElementsByTagName('script')[0];
        s.parentNode.insertBefore(e, s);
      })();
    }

    function loadFacebookSdk($document, $window) {
      if (!$document[0].getElementById('fb-root')) {
        $document.find('body').append('

');
      }

      $window.fbAsyncInit = function() {
        FB.init(config.providers.facebook);
      };

      (function(d, s, id) {
        var js, fjs = d.getElementsByTagName(s)[0];
        if (d.getElementById(id)) {
          return;
        }
        js = d.createElement(s);
        js.id = id;
        js.src = "//connect.facebook.net/" + config.providers.facebook.locale + "/sdk.js";
        fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
    }

    function loadGooglePlusSdk() {
      (function() {
        var po = document.createElement('script');
        po.type = 'text/javascript';
        po.async = true;
        po.src = 'https://apis.google.com/js/client:plusone.js';
        var s = document.getElementsByTagName('script')[0];
        s.parentNode.insertBefore(po, s);
      })();
    }

    return {
      facebook: function(params) {
        angular.extend(config.providers.facebook, params);
      },

      google: function(params) {
        angular.extend(config.providers.google, params);
      },

      linkedin: function(params) {
        angular.extend(config.providers.linkedin, params);
      },

      oauth2: function(params) {
        var provider = params.name;
        config.providers[provider] = config.providers[provider] || {};
        angular.extend(config.providers[provider], params);
      },

      $get: function($http, $location, $rootScope, $alert, $q, $injector, $window, $document) {

        var token = $window.localStorage.token;
        if (token) {
          var payload = JSON.parse($window.atob(token.split('.')[1]));
          $rootScope.currentUser = payload.user;
        }

        if (config.providers.linkedin.clientId) {
          loadLinkedinSdk();
        }

        if (config.providers.facebook.appId) {
          loadFacebookSdk($document, $window);
        }

        if (config.providers.google.clientId) {
          loadGooglePlusSdk();
        }

        function logout() {
          delete $window.localStorage.token;
          $rootScope.currentUser = null;
          $location.path(config.logoutRedirect);
        }

        function login(user) {
          return $http.post(config.loginUrl, user).success(function(data) {
            $window.localStorage.token = data.token;
            var payload = JSON.parse($window.atob(data.token.split('.')[1]));
            $rootScope.currentUser = payload.user;
            $location.path(config.loginRedirect);
          });
        }

        function signup(user) {
          return $http.post(config.signupUrl, user).success(function() {
            $location.path(config.signupRedirect);
          });
        }

        function loggedIn() {
          // TODO: return login status
        }

        function user() {
          // TODO: move rootscope to here
          // TODO: make a property
        }

        function linkedinAuthorized() {
          IN.API.Profile('me').result(function(result) {
            var profile = result.values;
//            var data = {
//              signedRequest: response.authResponse.signedRequest,
//              profile: profile
//            };
            $http.post(config.providers.linkedink.url, profile).success(function(token) {
              var payload = JSON.parse($window.atob(token.split('.')[1]));
              $window.localStorage.token = token;
              $rootScope.currentUser = payload.user;
              $location.path(config.loginRedirect);
            });
          });
        }

        function loginOauth(provider) {
          provider = provider.trim().toLowerCase();

          switch (provider) {
            case 'facebook':
              var scope = config.providers.facebook.scope.join(',');
              FB.login(function(response) {
                FB.api('/me', function(profile) {
                  var data = {
                    signedRequest: response.authResponse.signedRequest,
                    profile: profile
                  };
                  $http.post(config.providers.facebook.url, data).success(function(token) {
                    var payload = JSON.parse($window.atob(token.split('.')[1]));
                    $window.localStorage.token = token;
                    $rootScope.currentUser = payload.user;
                    $location.path(config.loginRedirect);
                  });
                });
              }, { scope: scope });
              break;
            case 'google':
              gapi.auth.authorize({
                client_id: config.providers.google.clientId,
                scope: config.providers.google.scope,
                immediate: false
              }, function(token) {
                gapi.client.load('plus', 'v1', function() {
                  var request = gapi.client.plus.people.get({
                    userId: 'me'
                  });
                  request.execute(function(response) {
                    var data = {
                      accessToken: token.access_token,
                      profile: response
                    };
                    $http.post(config.providers.google.url, data).success(function(token) {
                      var payload = JSON.parse($window.atob(token.split('.')[1]));
                      $window.localStorage.token = token;
                      $rootScope.currentUser = payload.user;
                      $location.path(config.loginRedirect);
                    });
                  });
                });
              });
              console.log('google signin');
              break;
            case 'linkedin':
              IN.UI.Authorize().place();
              IN.Event.on(IN, 'auth', linkedinAuthorized);
              break;
            default:
              break;
          }
        }

        return {
          loginOauth: loginOauth,
          login: login,
          signup: signup,
          logout: logout,
          loggedIn: loggedIn,
          user: user
        };
      }
    };
  })
  .factory('authInterceptor', function($q, $window, $location) {
    return {
      request: function(config) {
        if ($window.localStorage.token) {
          config.headers.Authorization = 'Bearer ' + $window.localStorage.token;
        }
        return config;
      },
      responseError: function(response) {
        if (response.status === 401 || response.status === 403) {
          $location.path('/login');
        }
        return $q.reject(response);
      }
    }
  })
  .config(function($httpProvider) {
    $httpProvider.interceptors.push('authInterceptor');
  })
  .run(function($rootScope, $location) {
    $rootScope.$on('$routeChangeStart', function(event, current, previous) {
      if ($rootScope.currentUser &&
        (current.originalPath === '/login' || current.originalPath === '/signup')) {
        $location.path('/');
      }
      if (current.authenticated && !$rootScope.currentUser) {
        $location.path('/login');
      }
    });
  });
<|endoftext|>


<commit_before>/* global $ */
/* global angular */
/* global jQuery */

angular.module('angular-flot', []).directive('flot', function () {
  return {
    restrict: 'EA',
    template: '

',
    scope: {
      dataset: '=',
      options: '=',
      callback: '=',
      onPlotClick: '&',
      onPlotHover: '&',
      onPlotSelected: '&'
    },
    link: function (scope, element, attributes) {
      var plot = null;
      var width = attributes.width || '100%';
      var height = attributes.height || '100%';

      // Bug: Passing a jQuery object causes an infinite loop within Angular. Fail hard telling
      // users that they should pass us a jQuery expression as string instead.
      if ((((scope.options || {}).legend || {}).container) instanceof jQuery) {
        throw new Error('Please use a jQuery expression string with the "legend.container" option.');
      }

      if (!scope.dataset) {
        scope.dataset = [];
      }

      if (!scope.options) {
        scope.options = {
          legend: {
            show: false
          }
        };
      }

      var plotArea = $(element.children()[0]);

      plotArea.css({
        width: width,
        height: height
      });

      var init = function () {
        var plotObj = $.plot(plotArea, scope.dataset, scope.options);

        if (scope.callback) {
          scope.callback(plotObj);
        }

        return plotObj;
      };

      //
      // Events
      //

      plotArea.on('plotclick', function onPlotClick (event, pos, item) {
        scope.$apply(function onApplyPlotClick () {
          scope.onPlotClick({
            event: event,
            pos: pos,
            item: item
          });
        });
      });

      plotArea.on('plotselected', function onPlotSelected (event, ranges) {
        scope.$apply(function onApplyPlotSelected () {
          scope.onPlotSelected({
            event: event,
            ranges: ranges
          });
        });
      });

      plotArea.on('plothover', function onPlotHover (event, pos, item) {
        scope.$apply(function onApplyPlotHover () {
          scope.onPlotHover({
            event: event,
            pos: pos,
            item: item
          });
        });
      });

      //
      // Watches
      //

      var onOptionsChanged = function () {
        plot = init();
      };

      var unwatchOptions = scope.$watch('options', onOptionsChanged, true);

      var onDatasetChanged = function (dataset) {
        if (plot) {
          plot.setData(dataset);
          plot.setupGrid();

          return plot.draw();
        } else {
          plot = init();
        }
      };

      var unwatchDataset = scope.$watch('dataset', onDatasetChanged, true);

      attributes.$observe('width', function(value) {
        if (!value) return;
        width = value;
        plotArea.css('width', value);
      });

      attributes.$observe('height', function(value) {
        if (!value) return;
        height = value;
        plotArea.css('height', value);
      });

      //
      // Tear Down
      //

      element.on('$destroy', function onDestroy () {
        plotArea.off('plotclick');
        plotArea.off('plothover');
        plotArea.off('plotselected');

        plot.shutdown();
        unwatchDataset();
        unwatchOptions();
      });
    }
  };
});
<commit_msg>Cosmetic: add missing space after "function" keyword<commit_after>/* global $ */
/* global angular */
/* global jQuery */

angular.module('angular-flot', []).directive('flot', function () {
  return {
    restrict: 'EA',
    template: '

',
    scope: {
      dataset: '=',
      options: '=',
      callback: '=',
      onPlotClick: '&',
      onPlotHover: '&',
      onPlotSelected: '&'
    },
    link: function (scope, element, attributes) {
      var plot = null;
      var width = attributes.width || '100%';
      var height = attributes.height || '100%';

      // Bug: Passing a jQuery object causes an infinite loop within Angular. Fail hard telling
      // users that they should pass us a jQuery expression as string instead.
      if ((((scope.options || {}).legend || {}).container) instanceof jQuery) {
        throw new Error('Please use a jQuery expression string with the "legend.container" option.');
      }

      if (!scope.dataset) {
        scope.dataset = [];
      }

      if (!scope.options) {
        scope.options = {
          legend: {
            show: false
          }
        };
      }

      var plotArea = $(element.children()[0]);

      plotArea.css({
        width: width,
        height: height
      });

      var init = function () {
        var plotObj = $.plot(plotArea, scope.dataset, scope.options);

        if (scope.callback) {
          scope.callback(plotObj);
        }

        return plotObj;
      };

      //
      // Events
      //

      plotArea.on('plotclick', function onPlotClick (event, pos, item) {
        scope.$apply(function onApplyPlotClick () {
          scope.onPlotClick({
            event: event,
            pos: pos,
            item: item
          });
        });
      });

      plotArea.on('plotselected', function onPlotSelected (event, ranges) {
        scope.$apply(function onApplyPlotSelected () {
          scope.onPlotSelected({
            event: event,
            ranges: ranges
          });
        });
      });

      plotArea.on('plothover', function onPlotHover (event, pos, item) {
        scope.$apply(function onApplyPlotHover () {
          scope.onPlotHover({
            event: event,
            pos: pos,
            item: item
          });
        });
      });

      //
      // Watches
      //

      var onOptionsChanged = function () {
        plot = init();
      };

      var unwatchOptions = scope.$watch('options', onOptionsChanged, true);

      var onDatasetChanged = function (dataset) {
        if (plot) {
          plot.setData(dataset);
          plot.setupGrid();

          return plot.draw();
        } else {
          plot = init();
        }
      };

      var unwatchDataset = scope.$watch('dataset', onDatasetChanged, true);

      attributes.$observe('width', function (value) {
        if (!value) return;
        width = value;
        plotArea.css('width', value);
      });

      attributes.$observe('height', function (value) {
        if (!value) return;
        height = value;
        plotArea.css('height', value);
      });

      //
      // Tear Down
      //

      element.on('$destroy', function onDestroy () {
        plotArea.off('plotclick');
        plotArea.off('plothover');
        plotArea.off('plotselected');

        plot.shutdown();
        unwatchDataset();
        unwatchOptions();
      });
    }
  };
});
<|endoftext|>


<commit_before>const webpack = require('webpack')
const WebpackDevServer = require('webpack-dev-server')

const appPaths = require('./app-paths')
const openBrowser = require('./helpers/open-browser')
const { log } = require('./helpers/logger')

let alreadyNotified = false
module.exports = class DevServer {
  constructor (quasarConfFile) {
    this.quasarConfFile = quasarConfFile
  }

  async listen () {
    const cfg = this.quasarConfFile.quasarConf
    const webpackConf = this.quasarConfFile.webpackConf

    log(`Booting up...`)

    return new Promise(resolve => (
      cfg.ctx.mode.ssr
        ? this.listenSSR(webpackConf, cfg, resolve)
        : this.listenCSR(webpackConf, cfg, resolve)
    ))
  }

  listenCSR (webpackConf, cfg, resolve) {
    const compiler = webpack(webpackConf.renderer || webpackConf)

    compiler.hooks.done.tap('done-compiling', compiler => {
      if (this.__started) { return }

      // start dev server if there are no errors
      if (compiler.compilation.errors && compiler.compilation.errors.length > 0) {
        return
      }

      this.__started = true

      server.listen(cfg.devServer.port, cfg.devServer.host, () => {
        resolve()

        if (alreadyNotified) { return }
        alreadyNotified = true

        if (cfg.__devServer.open && ['spa', 'pwa'].includes(cfg.ctx.modeName)) {
          openBrowser({ url: cfg.build.APP_URL, opts: cfg.__devServer.openOptions })
        }
      })
    })

    // start building & launch server
    const server = new WebpackDevServer(compiler, cfg.devServer)

    this.__cleanup = () => {
      this.__cleanup = null
      return new Promise(resolve => {
        server.close(resolve)
      })
    }
  }

  listenSSR (webpackConf, cfg, resolve) {
    const fs = require('fs')
    const LRU = require('lru-cache')
    const express = require('express')
    const chokidar = require('chokidar')
    const { createBundleRenderer } = require('vue-server-renderer')
    const ouchInstance = require('./helpers/cli-error-handling').getOuchInstance()
    const SsrExtension = require('./ssr/ssr-extension')

    let renderer

    function createRenderer (bundle, options) {
      // https://github.com/vuejs/vue/blob/dev/packages/vue-server-renderer/README.md#why-use-bundlerenderer
      return createBundleRenderer(bundle, {
        ...options,
        shouldPreload: () => false,
        shouldPrefetch: () => false,

        // for component caching
        cache: new LRU({
          max: 1000,
          maxAge: 1000 * 60 * 15
        }),
        // recommended for performance
        runInNewContext: false
      })
    }

    function render (req, res) {
      const startTime = Date.now()

      res.setHeader('Content-Type', 'text/html')

      const handleError = err => {
        if (err.url) {
          res.redirect(err.url)
        }
        else if (err.code === 404) {
          res.status(404).send('404 | Page Not Found')
        }
        else {
          ouchInstance.handleException(err, req, res, () => {
            console.error(`${req.url} -> error during render`)
            console.error(err.stack)
          })
        }
      }

      const context = {
        url: req.url,
        req,
        res
      }

      renderer.renderToString(context, (err, html) => {
        if (err) {
          handleError(err)
          return
        }
        if (cfg.__meta) {
          html = context.$getMetaHTML(html, context)
        }
        console.log(`${req.url} -> request took: ${Date.now() - startTime}ms`)
        res.send(html)
      })
    }

    let bundle
    let template
    let clientManifest
    let pwa

    let ready
    const readyPromise = new Promise(r => { ready = r })
    function update () {
      if (bundle && clientManifest) {
        renderer = createRenderer(bundle, {
          template,
          clientManifest,
          basedir: appPaths.resolve.app('.')
        })
        ready()
      }
    }

    // read template from disk and watch
    const { getIndexHtml } = require('./ssr/html-template')
    const templatePath = appPaths.resolve.app(cfg.sourceFiles.indexHtmlTemplate)

    function getTemplate () {
      return getIndexHtml(fs.readFileSync(templatePath, 'utf-8'), cfg)
    }

    template = getTemplate()
    const htmlWatcher = chokidar.watch(templatePath).on('change', () => {
      template = getTemplate()
      console.log('index.template.html template updated.')
      update()
    })

    const serverCompiler = webpack(webpackConf.server)
    const clientCompiler = webpack(webpackConf.client)

    serverCompiler.hooks.done.tapAsync('done-compiling', ({ compilation: { errors, warnings, assets }}, cb) => {
      errors.forEach(err => console.error(err))
      warnings.forEach(err => console.warn(err))

      if (errors.length > 0) {
        cb()
        return
      }

      bundle = JSON.parse(assets['../quasar.server-manifest.json'].source())
      update()

      cb()
    })

    clientCompiler.hooks.done.tapAsync('done-compiling', ({ compilation: { errors, warnings, assets }}, cb) => {
      errors.forEach(err => console.error(err))
      warnings.forEach(err => console.warn(err))

      if (errors.length > 0) {
        cb()
        return
      }

      if (cfg.ctx.mode.pwa) {
        pwa = {
          manifest: assets['manifest.json'].source(),
          serviceWorker: assets['service-worker.js'].source()
        }
      }

      clientManifest = JSON.parse(assets['../quasar.client-manifest.json'].source())
      update()

      cb()
    })

    const serverCompilerWatcher = serverCompiler.watch({}, () => {})

    const originalAfter = cfg.devServer.after

    // start building & launch server
    const server = new WebpackDevServer(clientCompiler, {
      ...cfg.devServer,

      after: app => {
        if (cfg.ctx.mode.pwa) {
          app.use(cfg.build.publicPath + 'manifest.json', (_, res) => {
            res.setHeader('Content-Type', 'application/json')
            res.send(pwa.manifest)
          })
          app.use(cfg.build.publicPath + 'service-worker.js', (_, res) => {
            res.setHeader('Content-Type', 'text/javascript')
            res.send(pwa.serviceWorker)
          })
        }

        if (cfg.build.ignorePublicFolder !== true) {
          app.use(cfg.build.publicPath, express.static(appPaths.resolve.app('public'), {
            maxAge: 0
          }))
        }

        originalAfter && originalAfter(app)

        SsrExtension.getModule().extendApp({
          app,

          ssr: {
            renderToString ({ req, res }, fn) {
              const context = {
                url: req.url,
                req,
                res
              }

              renderer.renderToString(context, (err, html) => {
                if (err) {
                  handleError(err)
                  return
                }
                if (cfg.__meta) {
                  html = context.$getMetaHTML(html, context)
                }

                fn(err, html)
              })
            },

            settings: Object.assign(
              {},
              JSON.parse(cfg.ssr.__templateOpts),
              { debug: true }
            )
          }
        })

        app.get(cfg.build.publicPath + '*', render)
      }
    })

    readyPromise.then(() => {
      server.listen(cfg.devServer.port, cfg.devServer.host, () => {
        resolve()
        if (cfg.__devServer.open) {
          openBrowser({ url: cfg.build.APP_URL, opts: cfg.__devServer.openOptions })
        }
      })
    })

    this.__cleanup = () => {
      this.__cleanup = null
      htmlWatcher.close()
      return Promise.all([
        new Promise(resolve => { server.close(resolve) }),
        new Promise(resolve => { serverCompilerWatcher.close(resolve) })
      ])
    }
  }

  stop () {
    if (this.__cleanup) {
      log(`Shutting down`)
      return this.__cleanup()
    }
  }
}
<commit_msg>feat(app): Improve dev-server for SSR in dev mode #7958<commit_after>const webpack = require('webpack')
const WebpackDevServer = require('webpack-dev-server')

const appPaths = require('./app-paths')
const openBrowser = require('./helpers/open-browser')
const { log } = require('./helpers/logger')

let alreadyNotified = false
module.exports = class DevServer {
  constructor (quasarConfFile) {
    this.quasarConfFile = quasarConfFile
  }

  async listen () {
    const cfg = this.quasarConfFile.quasarConf
    const webpackConf = this.quasarConfFile.webpackConf

    log(`Booting up...`)

    return new Promise(resolve => (
      cfg.ctx.mode.ssr
        ? this.listenSSR(webpackConf, cfg, resolve)
        : this.listenCSR(webpackConf, cfg, resolve)
    ))
  }

  listenCSR (webpackConf, cfg, resolve) {
    const compiler = webpack(webpackConf.renderer || webpackConf)

    compiler.hooks.done.tap('done-compiling', compiler => {
      if (this.__started) { return }

      // start dev server if there are no errors
      if (compiler.compilation.errors && compiler.compilation.errors.length > 0) {
        return
      }

      this.__started = true

      server.listen(cfg.devServer.port, cfg.devServer.host, () => {
        resolve()

        if (alreadyNotified) { return }
        alreadyNotified = true

        if (cfg.__devServer.open && ['spa', 'pwa'].includes(cfg.ctx.modeName)) {
          openBrowser({ url: cfg.build.APP_URL, opts: cfg.__devServer.openOptions })
        }
      })
    })

    // start building & launch server
    const server = new WebpackDevServer(compiler, cfg.devServer)

    this.__cleanup = () => {
      this.__cleanup = null
      return new Promise(resolve => {
        server.close(resolve)
      })
    }
  }

  listenSSR (webpackConf, cfg, resolve) {
    const fs = require('fs')
    const LRU = require('lru-cache')
    const express = require('express')
    const chokidar = require('chokidar')
    const { createBundleRenderer } = require('vue-server-renderer')
    const ouchInstance = require('./helpers/cli-error-handling').getOuchInstance()
    const SsrExtension = require('./ssr/ssr-extension')

    let renderer

    function createRenderer (bundle, options) {
      // https://github.com/vuejs/vue/blob/dev/packages/vue-server-renderer/README.md#why-use-bundlerenderer
      return createBundleRenderer(bundle, {
        ...options,
        shouldPreload: () => false,
        shouldPrefetch: () => false,

        // for component caching
        cache: new LRU({
          max: 1000,
          maxAge: 1000 * 60 * 15
        }),
        // recommended for performance
        runInNewContext: false
      })
    }

    function render (req, res) {
      const startTime = Date.now()

      res.setHeader('Content-Type', 'text/html')

      const handleError = err => {
        if (err.url) {
          res.redirect(err.url)
        }
        else if (err.code === 404) {
          res.status(404).send('404 | Page Not Found')
        }
        else {
          ouchInstance.handleException(err, req, res, () => {
            console.error(`${req.url} -> error during render`)
            console.error(err.stack)
          })
        }
      }

      const context = {
        url: req.url,
        req,
        res
      }

      renderer.renderToString(context, (err, html) => {
        if (err) {
          handleError(err)
          return
        }
        if (cfg.__meta) {
          html = context.$getMetaHTML(html, context)
        }
        console.log(`${req.url} -> request took: ${Date.now() - startTime}ms`)
        res.send(html)
      })
    }

    let bundle
    let template
    let clientManifest
    let pwa

    let ready
    const readyPromise = new Promise(r => { ready = r })
    function update () {
      if (bundle && clientManifest) {
        renderer = createRenderer(bundle, {
          template,
          clientManifest,
          basedir: appPaths.resolve.app('.')
        })
        ready()
      }
    }

    // read template from disk and watch
    const { getIndexHtml } = require('./ssr/html-template')
    const templatePath = appPaths.resolve.app(cfg.sourceFiles.indexHtmlTemplate)

    function getTemplate () {
      return getIndexHtml(fs.readFileSync(templatePath, 'utf-8'), cfg)
    }

    template = getTemplate()
    const htmlWatcher = chokidar.watch(templatePath).on('change', () => {
      template = getTemplate()
      console.log('index.template.html template updated.')
      update()
    })

    const serverCompiler = webpack(webpackConf.server)
    const clientCompiler = webpack(webpackConf.client)

    serverCompiler.hooks.done.tapAsync('done-compiling', ({ compilation: { errors, warnings, assets }}, cb) => {
      errors.forEach(err => console.error(err))
      warnings.forEach(err => console.warn(err))

      if (errors.length > 0) {
        cb()
        return
      }

      bundle = JSON.parse(assets['../quasar.server-manifest.json'].source())
      update()

      cb()
    })

    clientCompiler.hooks.done.tapAsync('done-compiling', ({ compilation: { errors, warnings, assets }}, cb) => {
      errors.forEach(err => console.error(err))
      warnings.forEach(err => console.warn(err))

      if (errors.length > 0) {
        cb()
        return
      }

      if (cfg.ctx.mode.pwa) {
        pwa = {
          manifest: assets['manifest.json'].source(),
          serviceWorker: assets['service-worker.js'].source()
        }
      }

      clientManifest = JSON.parse(assets['../quasar.client-manifest.json'].source())
      update()

      cb()
    })

    const serverCompilerWatcher = serverCompiler.watch({}, () => {})

    const originalAfter = cfg.devServer.after

    // start building & launch server
    const server = new WebpackDevServer(clientCompiler, {
      ...cfg.devServer,

      after: app => {
        if (cfg.ctx.mode.pwa) {
          app.use(cfg.build.publicPath + 'manifest.json', (_, res) => {
            res.setHeader('Content-Type', 'application/json')
            res.send(pwa.manifest)
          })
          app.use(cfg.build.publicPath + 'service-worker.js', (_, res) => {
            res.setHeader('Content-Type', 'text/javascript')
            res.send(pwa.serviceWorker)
          })
        }

        if (cfg.build.ignorePublicFolder !== true) {
          app.use(cfg.build.publicPath, express.static(appPaths.resolve.app('public'), {
            maxAge: 0
          }))
        }

        originalAfter && originalAfter(app)

        SsrExtension.getModule().extendApp({
          app,

          ssr: {
            renderToString (opts, fn) {
              const context = {
                ...opts,
                url: opts.req.url
              }

              renderer.renderToString(context, (err, html) => {
                if (err) {
                  handleError(err)
                  return
                }
                if (cfg.__meta) {
                  html = context.$getMetaHTML(html, context)
                }

                fn(err, html)
              })
            },

            settings: Object.assign(
              {},
              JSON.parse(cfg.ssr.__templateOpts),
              { debug: true }
            )
          }
        })

        app.get(cfg.build.publicPath + '*', render)
      }
    })

    readyPromise.then(() => {
      server.listen(cfg.devServer.port, cfg.devServer.host, () => {
        resolve()
        if (cfg.__devServer.open) {
          openBrowser({ url: cfg.build.APP_URL, opts: cfg.__devServer.openOptions })
        }
      })
    })

    this.__cleanup = () => {
      this.__cleanup = null
      htmlWatcher.close()
      return Promise.all([
        new Promise(resolve => { server.close(resolve) }),
        new Promise(resolve => { serverCompilerWatcher.close(resolve) })
      ])
    }
  }

  stop () {
    if (this.__cleanup) {
      log(`Shutting down`)
      return this.__cleanup()
    }
  }
}
<|endoftext|>