<commit_before>/*
 * The "kaltura player" embedPlayer interface for fallback h.264 and flv video format support
 */
( function( mw, $ ) { "use strict";

	mw.EmbedPlayerChromecastReceiver = {
		// Instance name:
		instanceOf : 'ChromecastReceiver',
		bindPostfix: '.ccPlayer',
		// List of supported features:
		supports : {
			'playHead' : true,
			'pause' : true,
			'stop' : true,
			'volumeControl' : true,
			'overlays': true
		},
		seeking: false,
		startOffset: 0,
		currentTime: 0,
		duration: 0,
		userSlide: false,
		volume: 1,
		vid: null,
		monitorInterval: null,
		receiverName: '',
		nativeEvents: [
			'loadstart',
			'progress',
			'suspend',
			'abort',
			'error',
			'emptied',
			'stalled',
			'play',
			'pause',
			'loadedmetadata',
			'loadeddata',
			'waiting',
			'playing',
			'canplay',
			'canplaythrough',
			'seeking',
			'seeked',
			'timeupdate',
			'ended',
			'ratechange',
			'durationchange',
			'volumechange'
		],

		setup: function( readyCallback ) {
			this.vid = this.getPlayerElement();
			this.applyMediaElementBindings();
			mw.log('EmbedPlayerChromecastReceiver:: Setup. Video element: '+this.getPlayerElement().toString());
			$(this).trigger("chromecastReceiverLoaded",[this.getPlayerElement()]);
			var _this = this;
			this._propagateEvents = true;
			$(this.getPlayerElement()).css('position', 'absolute');
			if (this.inline) {
				$(this.getPlayerElement()).attr('webkit-playsinline', '');
			}
			if (this.monitorInterval !== null){
				clearInterval(this.monitorInterval);
			}
			this.monitorInterval = setInterval(function(){_this.monitor();},1000);
			readyCallback();
		},

		/**
		 * Apply media element bindings
		 */
		applyMediaElementBindings: function () {
			var _this = this;
			this.log("MediaElementBindings");
			var vid = this.getPlayerElement();
			if (!vid) {
				this.log(" Error: applyMediaElementBindings without player elemnet");
				return;
			}
			$.each(_this.nativeEvents, function (inx, eventName) {
				if (mw.isIOS8_9() && mw.isIphone() && eventName === "seeking") {
					return;
				}
				$(vid).unbind(eventName + '.embedPlayerChromecastReceiver').bind(eventName + '.embedPlayerChromecastReceiver', function () {
					// make sure we propagating events, and the current instance is in the correct closure.
					if (_this._propagateEvents && _this.instanceOf == 'ChromecastReceiver') {
						var argArray = $.makeArray(arguments);
						// Check if there is local handler:
						if (_this[ '_on' + eventName ]) {
							_this[ '_on' + eventName ].apply(_this, argArray);
						} else {
							// No local handler directly propagate the event to the abstract object:
							$(_this).trigger(eventName, argArray);
						}
					}
				});
			});
		},

		/**
		 * Handle the native paused event
		 */
		_onpause: function () {
			this.paused = true;
			this.layoutBuilder.showPlayerControls();
			this.parent_pause();
		},

		/**
		 * Handle the native play event
		 */
		_onplay: function () {
			this.paused = false;
			this.stopped = false;
			this.layoutBuilder.hidePlayerControls();
			this.parent_play();
		},
		// override these functions so embedPlayer won't try to sync time
		syncCurrentTime: function(){},

		isInSequence: function(){return false;},

		monitor: function(){
			if ( this.vid && this.vid.currentTime !== null && this.vid.duration !== null) {
				$(this).trigger("updatePlayHeadPercent",[ this.vid.currentTime / this.vid.duration ]);
				$( this ).trigger( 'externalTimeUpdate', [this.vid.currentTime]);
			}
			$(this).trigger( 'monitorEvent' );
		},

//		updatePlayhead: function (currentTime, duration) {
//			this.currentTime = currentTime;
//			this.vid.currentTime = currentTime;
//			if ( !this.seeking && !this.userSlide) {
//				$(this).trigger("updatePlayHeadPercent",[ currentTime / duration ]);
//				$( this ).trigger( 'timeupdate' );
//			}
//			$(this).trigger( 'monitorEvent' );
//		},
//
		getPlayerElementTime: function(){
			return this.getPlayerElement().currentTime;
		},
//
//		clipDone: function() {
//			mw.log("Chromecast::clip done");
//			if (this.vid.mediaFinishedCallback){
//				this.vid.mediaFinishedCallback();
//			}
//			$(this.vid).trigger("ended");
//			this.onClipDone();
//		},
//
//		play: function() {
//			$(this).trigger("chromecastPlay");
//			$(this.vid).trigger("onplay");
//			this.parent_play();
//			$(this).trigger("playing");
//			this.hideSpinner();
//		},
//
//		pause: function() {
//			$(this).trigger("chromecastPause");
//			$(this.vid).trigger("onpause");
//			this.parent_pause();
//		},
//
//		switchPlaySource: function( source, switchCallback, doneCallback ){
//			$(this).trigger("chromecastSwitchMedia", [source.src, source.mimeType]);
//			if (switchCallback){
//				this.vid.mediaLoadedCallback = switchCallback;
//			}
//			if (doneCallback){
//				this.vid.mediaFinishedCallback = doneCallback;
//			}
//		},
//
//		mediaLoaded: function(mediaSession){
//			var _this = this;
//			this.vid.currentTime = mediaSession.currentTime;
//			this.updateDuration(mediaSession.media.duration);
//			if (this.vid.mediaLoadedCallback){
//				this.vid.mediaLoadedCallback(this.vid);
//			}
//		},
//
//		updateDuration: function(duration){
//			this.vid.duration = duration;
//			this.duration = duration;
//			$( this ).trigger( 'durationChange',[duration] );
//		},
//
		getPlayerElement: function () {
			this.playerElement = $('#' + this.pid).get(0);
			return this.playerElement;
		},
//
//		seek: function(position) {
//			mw.log("seek to "+position);
//			this.seeking = true;
//			$(this).trigger("chromecastSeek", [position / this.vid.duration * 100]);
//			$(this.vid).trigger("seek");
//		},
//
//		setPlayerElementVolume: function(percentage) {
//			$(this).trigger("chromecastSetVolume",[percentage]);
//		},
//
//		onPlayerSeekEnd: function () {
//			$( this ).trigger( 'seeked' );
//			this.seeking = false;
//		},

		isVideoSiblingEnabled: function() {
			return false;
		}
	};
	} )( mediaWiki, jQuery );
<commit_msg>updated playing event<commit_after>/*
 * The "kaltura player" embedPlayer interface for fallback h.264 and flv video format support
 */
( function( mw, $ ) { "use strict";

	mw.EmbedPlayerChromecastReceiver = {
		// Instance name:
		instanceOf : 'ChromecastReceiver',
		bindPostfix: '.ccPlayer',
		// List of supported features:
		supports : {
			'playHead' : true,
			'pause' : true,
			'stop' : true,
			'volumeControl' : true,
			'overlays': true
		},
		seeking: false,
		startOffset: 0,
		currentTime: 0,
		duration: 0,
		userSlide: false,
		volume: 1,
		vid: null,
		monitorInterval: null,
		receiverName: '',
		nativeEvents: [
			'loadstart',
			'progress',
			'suspend',
			'abort',
			'error',
			'emptied',
			'stalled',
			'play',
			'pause',
			'loadedmetadata',
			'loadeddata',
			'waiting',
			'playing',
			'canplay',
			'canplaythrough',
			'seeking',
			'seeked',
			'timeupdate',
			'ended',
			'ratechange',
			'durationchange',
			'volumechange'
		],

		setup: function( readyCallback ) {
			this.vid = this.getPlayerElement();
			this.applyMediaElementBindings();
			mw.log('EmbedPlayerChromecastReceiver:: Setup. Video element: '+this.getPlayerElement().toString());
			$(this).trigger("chromecastReceiverLoaded",[this.getPlayerElement()]);
			var _this = this;
			this._propagateEvents = true;
			$(this.getPlayerElement()).css('position', 'absolute');
			if (this.inline) {
				$(this.getPlayerElement()).attr('webkit-playsinline', '');
			}
			if (this.monitorInterval !== null){
				clearInterval(this.monitorInterval);
			}
			this.monitorInterval = setInterval(function(){_this.monitor();},1000);
			readyCallback();
		},

		/**
		 * Apply media element bindings
		 */
		applyMediaElementBindings: function () {
			var _this = this;
			this.log("MediaElementBindings");
			var vid = this.getPlayerElement();
			if (!vid) {
				this.log(" Error: applyMediaElementBindings without player elemnet");
				return;
			}
			$.each(_this.nativeEvents, function (inx, eventName) {
				if (mw.isIOS8_9() && mw.isIphone() && eventName === "seeking") {
					return;
				}
				$(vid).unbind(eventName + '.embedPlayerChromecastReceiver').bind(eventName + '.embedPlayerChromecastReceiver', function () {
					// make sure we propagating events, and the current instance is in the correct closure.
					if (_this._propagateEvents && _this.instanceOf == 'ChromecastReceiver') {
						var argArray = $.makeArray(arguments);
						// Check if there is local handler:
						if (_this[ '_on' + eventName ]) {
							_this[ '_on' + eventName ].apply(_this, argArray);
						} else {
							// No local handler directly propagate the event to the abstract object:
							$(_this).trigger(eventName, argArray);
						}
					}
				});
			});
		},

		/**
		 * Handle the native paused event
		 */
		_onpause: function () {
			this.paused = true;
			this.layoutBuilder.showPlayerControls();
			$(this).trigger('onPlayerStateChange', [ "pause", "play" ]);
			this.parent_pause();
		},

		/**
		 * Handle the native play event
		 */
		_onplay: function () {
			this.paused = false;
			this.stopped = false;
			this.layoutBuilder.hidePlayerControls();
			$(this).trigger('onPlayerStateChange', [ "play", "pause" ]);
			this.parent_play();
		},
		// override these functions so embedPlayer won't try to sync time
		syncCurrentTime: function(){},

		isInSequence: function(){return false;},

		monitor: function(){
			if ( this.vid && this.vid.currentTime !== null && this.vid.duration !== null) {
				$(this).trigger("updatePlayHeadPercent",[ this.vid.currentTime / this.vid.duration ]);
				$( this ).trigger( 'externalTimeUpdate', [this.vid.currentTime]);
			}
			$(this).trigger( 'monitorEvent' );
		},

//		updatePlayhead: function (currentTime, duration) {
//			this.currentTime = currentTime;
//			this.vid.currentTime = currentTime;
//			if ( !this.seeking && !this.userSlide) {
//				$(this).trigger("updatePlayHeadPercent",[ currentTime / duration ]);
//				$( this ).trigger( 'timeupdate' );
//			}
//			$(this).trigger( 'monitorEvent' );
//		},
//
		getPlayerElementTime: function(){
			return this.getPlayerElement().currentTime;
		},
//
//		clipDone: function() {
//			mw.log("Chromecast::clip done");
//			if (this.vid.mediaFinishedCallback){
//				this.vid.mediaFinishedCallback();
//			}
//			$(this.vid).trigger("ended");
//			this.onClipDone();
//		},
//
//		play: function() {
//			$(this).trigger("chromecastPlay");
//			$(this.vid).trigger("onplay");
//			this.parent_play();
//			$(this).trigger("playing");
//			this.hideSpinner();
//		},
//
//		pause: function() {
//			$(this).trigger("chromecastPause");
//			$(this.vid).trigger("onpause");
//			this.parent_pause();
//		},
//
//		switchPlaySource: function( source, switchCallback, doneCallback ){
//			$(this).trigger("chromecastSwitchMedia", [source.src, source.mimeType]);
//			if (switchCallback){
//				this.vid.mediaLoadedCallback = switchCallback;
//			}
//			if (doneCallback){
//				this.vid.mediaFinishedCallback = doneCallback;
//			}
//		},
//
//		mediaLoaded: function(mediaSession){
//			var _this = this;
//			this.vid.currentTime = mediaSession.currentTime;
//			this.updateDuration(mediaSession.media.duration);
//			if (this.vid.mediaLoadedCallback){
//				this.vid.mediaLoadedCallback(this.vid);
//			}
//		},
//
//		updateDuration: function(duration){
//			this.vid.duration = duration;
//			this.duration = duration;
//			$( this ).trigger( 'durationChange',[duration] );
//		},
//
		getPlayerElement: function () {
			this.playerElement = $('#' + this.pid).get(0);
			return this.playerElement;
		},
//
//		seek: function(position) {
//			mw.log("seek to "+position);
//			this.seeking = true;
//			$(this).trigger("chromecastSeek", [position / this.vid.duration * 100]);
//			$(this.vid).trigger("seek");
//		},
//
//		setPlayerElementVolume: function(percentage) {
//			$(this).trigger("chromecastSetVolume",[percentage]);
//		},
//
//		onPlayerSeekEnd: function () {
//			$( this ).trigger( 'seeked' );
//			this.seeking = false;
//		},

		isVideoSiblingEnabled: function() {
			return false;
		}
	};
	} )( mediaWiki, jQuery );
<|endoftext|>


<commit_before>/* Line stopping example */
var lineExample =
        "<xml>" +
                "<block type='controls_if' x='25' y='25'>" +
                        "<mutation else='1'></mutation>" +
                        "<value name='IF0'>" +
                                "<block type='sumorobot_line'>" +
                                        "<field name='LINE'>LINE_MIDDLE</field>" +
                                "</block>" +
                        "</value>" +
                        "<statement name='DO0'>" +
                                "<block type='sumorobot_move'>" +
                                        "<field name='MOVE'>stop</field>" +
                                "</block>" +
                        "</statement>" +
                        "<statement name='ELSE'>" +
                                "<block type='sumorobot_move'>" +
                                        "<field name='MOVE'>forward</field>" +
                                "</block>" +
                        "</statement>" +
                "</block>" +
        "</xml>";

/* Enemy attacking example */
var enemyExample =
        "<xml>" +
                "<block type='controls_if' x='25' y='25'>" +
                        "<mutation else='1'></mutation>" +
                        "<value name='IF0'>" +
                                "<block type='sumorobot_enemy'>" +
                                        "<field name='ENEMY'>ENEMY_FRONT</field>" +
                                "</block>" +
                        "</value>" +
                        "<statement name='DO0'>" +
                                "<block type='sumorobot_move'>" +
                                        "<field name='MOVE'>forward</field>" +
                                "</block>" +
                        "</statement>" +
                        "<statement name='ELSE'>" +
                                "<block type='sumorobot_spin'>" +
                                        "<field name='SPIN'>spinLeft</field>" +
                                "</block>" +
                        "</statement>" +
                "</block>" +
        "</xml>";

/* The socket object */
var socket = null;

var code = "";

/* When code has changed */
var onCodeChanged = function onCodeChanged() {
	if (code != Blockly.Arduino.workspaceToCode())
		sendCode();
	code = Blockly.Arduino.workspaceToCode();
	//$('#arduino-code').val(Blockly.Arduino.workspaceToCode());
};

/* Example code snippets */
var showExample = function showExample(exampleXML) {
	Blockly.mainWorkspace.clear();
	var xml = Blockly.Xml.textToDom(exampleXML);
	Blockly.Xml.domToWorkspace(Blockly.mainWorkspace, xml);
};

/* Send the code */
var sendCode = function sendCode() {
	$('#upload').attr('disabled', 'disabled');
	socket.emit('send-sumorobot-code', Blockly.Arduino.workspaceToCode());
};

/* Get a users code */
var getCode = function getCode(user) {
	socket.emit('get-sumorobot-code', user);
};

/* Show the code */
var showCode = function showCode() {
	alert(Blockly.Arduino.workspaceToCode());
};

/* When DOM has been loaded */
window.onload = function() {
	/* Initialize blockly */
	Blockly.inject(document.getElementById('blockly-div'), {
		trashcan: true,
		path: '/js/blockly/',
		toolbox: document.getElementById('toolbox')
	});
	Blockly.addChangeListener(onCodeChanged);

	/* Initialize sockets */
	socket = io.connect();

	/* Receive messages */
	socket.on('sumorobot-message', function(message) {
		$('#upload').removeAttr('disabled');
	});
}

/* When keydown on document */
$(document).keydown(function(e) {
	var tag = e.target.tagName.toLowerCase();
	/* Check the key code */
	switch(e.which) {
		case 38:
			if (tag != 'input' && tag != 'textarea') /* UP */;
			break;
		case 40:
			if (tag != 'input' && tag != 'textarea') /* DOWN */;
			break;
		case 37:
			if (tag != 'input' && tag != 'textarea') /* LEFT */;
			break;
		case 39:
			if (tag != 'input' && tag != 'textarea') /* RIGHT */;
			break;
		case 69:
			if (tag != 'input' && tag != 'textarea') showExample(enemyExample);
			break;
		case 76:
			if (tag != 'input' && tag != 'textarea') showExample(lineExample);
			break;
		case 85:
			if (tag != 'input' && tag != 'textarea') sendCode();
			break;
	}
});
<commit_msg>updated petricity programming<commit_after>var code = "";
var socket = null;

/* When code has changed */
var onCodeChanged = function onCodeChanged() {
	if (code != Blockly.Arduino.workspaceToCode())
		sendCode();
	code = Blockly.Arduino.workspaceToCode();
	//$('#arduino-code').val(Blockly.Arduino.workspaceToCode());
};

/* Example code snippets */
var showExample = function showExample(exampleXML) {
	Blockly.mainWorkspace.clear();
	var xml = Blockly.Xml.textToDom(exampleXML);
	Blockly.Xml.domToWorkspace(Blockly.mainWorkspace, xml);
};

/* Send the code */
var sendCode = function sendCode() {
	$('#upload').attr('disabled', 'disabled');
	socket.emit('send-petricity-code', Blockly.Arduino.workspaceToCode());
};

/* Get a users code */
var getCode = function getCode(user) {
	socket.emit('get-petricity-code', user);
};

/* Show the code */
var showCode = function showCode() {
	alert(Blockly.Arduino.workspaceToCode());
};

/* When DOM has been loaded */
window.onload = function() {
	/* Initialize blockly */
	Blockly.inject(document.getElementById('blockly-div'), {
		trashcan: true,
		path: '/js/blockly/',
		toolbox: document.getElementById('toolbox')
	});
	Blockly.addChangeListener(onCodeChanged);

	/* Initialize sockets */
	socket = io.connect();

	/* Receive messages */
	socket.on('petricity-message', function(message) {
		$('#upload').removeAttr('disabled');
	});
}

/* When keydown on document */
$(document).keydown(function(e) {
	var tag = e.target.tagName.toLowerCase();
	/* Check the key code */
	switch(e.which) {
		case 38:
			if (tag != 'input' && tag != 'textarea') /* UP */;
			break;
		case 40:
			if (tag != 'input' && tag != 'textarea') /* DOWN */;
			break;
		case 37:
			if (tag != 'input' && tag != 'textarea') /* LEFT */;
			break;
		case 39:
			if (tag != 'input' && tag != 'textarea') /* RIGHT */;
			break;
		case 69:
			if (tag != 'input' && tag != 'textarea') showExample(enemyExample);
			break;
		case 76:
			if (tag != 'input' && tag != 'textarea') showExample(lineExample);
			break;
		case 85:
			if (tag != 'input' && tag != 'textarea') sendCode();
			break;
	}
});
<|endoftext|>


<commit_before>var app = angular.module("browseApp.workslist", []);

app.controller("workslistCtrl", function($scope, $http) {

    var query = '';

    if ($scope.querystring != null) {
        query += '?' + encodeURI($scope.querystring);
    }
    console.log('Query: ' + query);

    $http.get("reqs/list/" + $scope.catID + query)
      .success(function(response)
        {

            $scope.works = response;

        });

});
<commit_msg>Parse JSON strings<commit_after>var app = angular.module("browseApp.workslist", []);

app.controller("workslistCtrl", function($scope, $http) {

    var query = '';

    if ($scope.querystring != null) {
        query += '?' + encodeURI($scope.querystring);
    }
    console.log('Query: ' + query);

    $http.get("reqs/list/" + $scope.catID + query)
      .success(function(response)
        {

            $scope.works = response;

            for (i in $scope.works)
            {
              $scope.works[i].tags = $scope.works[i].tags.slice(1,-1);
              $scope.works[i].tags = $scope.works[i].tags.split(",");

              $scope.works[i].info = JSON.parse($scope.works[i].info);
            }

        });

});
<|endoftext|>


<commit_before>(function () {
  'use strict';
  // Polls controller
  angular
    .module('polls')
    .controller('PollInputController', PollInputController)
    .controller('BottomSheetController', BottomSheetController);

  PollInputController.$inject = [
    '$rootScope',
    '$scope',
    '$state',
    '$window',
    'Authentication',
    'pollResolve',
    'notifResolve',
    'OptsService',
    'Socket',
    'CategorysService',
    'toastr',
    'Action',
    'ngDialog',
    '$mdBottomSheet'
  ];

  function PollInputController(
    $rootScope,
    $scope,
    $state,
    $window,
    Authentication,
    poll,
    notif,
    Opts,
    Socket,
    Categorys,
    toast,
    Action,
    dialog,
    $mdBottomSheet
  ) {
    var ctrl = this;

    ctrl.authentication = Authentication;
    ctrl.user = Authentication.user;
    ctrl.isLogged = (ctrl.user);
    ctrl.poll = poll;
    ctrl.poll.close = ctrl.poll.close ? moment(ctrl.poll.close) : ctrl.poll.close;
    ctrl.isClosed = moment(ctrl.poll.close).isAfter(new moment());
    Categorys.query().$promise.then(_ctgrs => {
      ctrl.categorys = _ctgrs;
      console.log();
    })

    ctrl.bk_poll = _.clone(poll);
    ctrl.form = {};
    ctrl.opts = ctrl.poll.opts || [];

    function init() {
      if (ctrl.poll._id) {
        initSocket();
      }
      analysic_nofif();
    }

    init();
    // Init Socket
    function initSocket() {
      if (!Socket.socket) {
        Socket.connect();
      }
      Socket.emit('subscribe_poll', {
        pollId: ctrl.poll._id,
        userId: ctrl.user._id
      });
      Socket.on('poll_delete', res => {
        toast.error('This poll has been deleted.', 'Error!');
        $state.go('polls.list');
      });
      Socket.on('opts_request', res => {
        console.log('Has option request');
        Action.get_poll(ctrl.poll._id)
          .then(_poll => {
            ctrl.poll = _poll;
            ctrl.opts = ctrl.poll.opts;
            $scope.$apply();
          }, err => {
            toast.error(err.message, 'Error!');
          });
      });
      $scope.$on('$destroy', function () {
        Socket.emit('unsubscribe', {
          pollId: ctrl.poll._id,
          userId: ctrl.user._id
        });
        Socket.removeListener('poll_delete');
        Socket.removeListener('opts_request');
      });
    }

    function analysic_nofif() {
      if (notif) {
        if (notif.status === 0) {
          notif.status = 1;
          notif.$update(() => {
            $rootScope.$emit('changeNotif');
          });
        }
      }
    }

    function isCanUpdate() {
      return true;
      // const update = moment(ctrl.poll.updated);
      // const now = moment(new Date());
      // var duration = moment.duration(now.diff(update)).asHours();
      // return duration >= 1;
    }
    // Function
    ctrl.remove = () => {
      $scope.message_title = 'Delete poll!';
      $scope.message_content = 'Are you sure you want to delete?';
      $scope.dialog_type = 3;
      $scope.buton_label = 'Delete';
      dialog.openConfirm({
        scope: $scope,
        templateUrl: 'modules/core/client/views/templates/confirm.dialog.template.html'
      }).then(confirm => {
        handle_delete();
      }, reject => {
      });
      function handle_delete() {
        ctrl.poll.$remove(() => {
          Socket.emit('poll_delete', { pollId: ctrl.poll._id });
          $state.go('polls.list');
        });
      }
    };

    ctrl.save = isValid => {
      if (!isValid) {
        $scope.$broadcast('show-errors-check-validity', 'pollForm');
        return false;
      }

      if (!ctrl.validateBody() || !ctrl.validateCategory() || !ctrl.validateTitle() || !ctrl.validateCloseDate()) {
        toast.error('You have not entered enough information.', 'Error!');
        return;
      }
      if (!ctrl.poll.isPublic) {
        $scope.message_title = 'Save poll!';
        $scope.message_content = 'You want to save a private poll?';
        $scope.dialog_type = 1;
        $scope.buton_label = 'Save';
        dialog.openConfirm({
          scope: $scope,
          templateUrl: 'modules/core/client/views/templates/confirm.dialog.template.html'
        }).then(confirm => {
          handle_save();
        }, reject => {
        });
      } else {
        handle_save();
      }
      function handle_save() {
        ctrl.poll.opts = ctrl.opts;
        Action.save_poll(ctrl.poll)
          .then(res => {
            $state.go('polls.view', { pollId: res._id });
          })
          .catch(err => {
            toast.error(err.message, 'Error!');
          });
      }
    };

    ctrl.validateCategory = () => {
      return (ctrl.poll.category) ? true : false;
    };
    ctrl.validateTitle = () => {
      return (ctrl.poll.title) ? true : false;
    };
    ctrl.validateBody = () => {
      return (ctrl.poll.body) ? true : false;
    };
    ctrl.validateCloseDate = () => {
      if (!ctrl.poll.close) {
        return true;
      }
      return moment(ctrl.poll.close).isAfter(new moment());
    };
    ctrl.discard = () => {
      if (angular.equals(ctrl.poll, ctrl.bk_poll)) {
        handle_discard();
      } else {
        $scope.message_title = 'Discard poll!';
        $scope.message_content = 'Are you sure you want to discard?';
        $scope.dialog_type = 2;
        $scope.buton_label = 'Discard';
        dialog.openConfirm({
          scope: $scope,
          templateUrl: 'modules/core/client/views/templates/confirm.dialog.template.html'
        }).then(confirm => {
          handle_discard();
        }, reject => {
        });
      }
    };
    function handle_discard() {
      if (ctrl.poll._id) {
        $state.go('polls.view', { pollId: ctrl.poll._id });
      } else {
        $state.go('polls.list');
      }
    }

    // OPTIONS
    ctrl.tmp_opt = {};
    ctrl.show_colorpicker = false;
    ctrl.opt_class = opt => {
      var classStr = 'custom-panel ';
      classStr += opt.status === 1 ? 'public' : '';
      classStr += opt.status === 2 ? 'waiting' : '';
      return classStr;
    };
    ctrl.input_opt = opt => {
      ctrl.tmp_opt = (!opt) ? { poll: ctrl.poll._id, title: '', body: '', status: 1 } : opt;
      $mdBottomSheet.show({
        templateUrl: 'modules/polls/client/views/new-opt.client.view.html',
        controller: 'BottomSheetController',
        clickOutsideToClose: true
      }).then(function (clickedItem) {
        console.log(clickedItem);
      }).catch(function (error) {
        // User clicked outside or hit escape
      });
    };
    ctrl.remove_opt = opt => {
      $scope.message_title = 'Delete option!';
      $scope.message_content = 'Are you sure you want to delete this option?';
      $scope.dialog_type = 3;
      $scope.buton_label = 'Delete';
      dialog.openConfirm({
        scope: $scope,
        templateUrl: 'modules/core/client/views/templates/confirm.dialog.template.html'
      }).then(confirm => {
        handle_delete();
      }, reject => {
      });
      function handle_delete() {
        ctrl.opts = _.without(ctrl.opts, opt);
        if (opt._id) {
          var _opt = new Opts(opt);
          _opt.$remove(() => {
            Socket.emit('opts_update', { pollId: ctrl.poll._id });
          });
        }
      }
    };
    ctrl.approve_opt = opt => {
      $scope.message_title = 'Approve option!';
      $scope.message_content = 'Are you sure you want to approve this option?';
      $scope.dialog_type = 1;
      $scope.buton_label = 'Approve';
      dialog.openConfirm({
        scope: $scope,
        templateUrl: 'modules/core/client/views/templates/confirm.dialog.template.html'
      }).then(confirm => {
        handle_approve();
      }, reject => {
      });
      function handle_approve() {
        opt.status = 1;
        var _opt = new Opts(opt);
        _opt.$update(() => {
          Socket.emit('opts_update', { pollId: ctrl.poll._id });
        });
      }
    };
    ctrl.reject_opt = opt => {
      $scope.message_title = 'Reject option!';
      $scope.message_content = 'Are you sure you want to reject this option?';
      $scope.dialog_type = 2;
      $scope.buton_label = 'Reject';
      dialog.openConfirm({
        scope: $scope,
        templateUrl: 'modules/core/client/views/templates/confirm.dialog.template.html'
      }).then(confirm => {
        handle_reject();
      }, reject => {
      });
      function handle_reject() {
        opt.status = 3;
        var _opt = new Opts(opt);
        _opt.$update(() => {
        });
      }
    };
    ctrl.save_opt = isValid => {
      if (!isValid) {
        $scope.$broadcast('show-errors-check-validity', 'ctrl.form.optForm');
        return false;
      }
      if (!ctrl.tmp_opt._id && !_.contains(ctrl.opts, ctrl.tmp_opt)) {
        ctrl.opts.push(ctrl.tmp_opt);
      }
    };

    ctrl.showOptionSheet = opt => {
    };
    $scope.clear_close_date = () => {
      delete ctrl.poll.close;
    };

  }
  BottomSheetController.$inject = ['$scope', '$mdBottomSheet'];
  function BottomSheetController($scope, $mdBottomSheet) {
    console.log(ctrl.tmp_opt);
    $scope.dismiss = () => {
      $mdBottomSheet.hide();
    };
    $scope.save = () => {
      $mdBottomSheet.hide();
    };
    $scope.listItemClick = function ($index) {
      var clickedItem = $scope.items[$index];
      $mdBottomSheet.hide(clickedItem);
    };
  }
})();
<commit_msg>Commited from lenh at Fri, Aug 18, 2017  3:12:26 PM<commit_after>(function () {
  'use strict';
  // Polls controller
  angular
    .module('polls')
    .controller('PollInputController', PollInputController)
    .controller('BottomSheetController', BottomSheetController);

  PollInputController.$inject = [
    '$rootScope',
    '$scope',
    '$state',
    '$window',
    'Authentication',
    'pollResolve',
    'notifResolve',
    'OptsService',
    'Socket',
    'CategorysService',
    'toastr',
    'Action',
    'ngDialog',
    '$mdBottomSheet'
  ];

  function PollInputController(
    $rootScope,
    $scope,
    $state,
    $window,
    Authentication,
    poll,
    notif,
    Opts,
    Socket,
    Categorys,
    toast,
    Action,
    dialog,
    $mdBottomSheet
  ) {
    var ctrl = this;

    ctrl.authentication = Authentication;
    ctrl.user = Authentication.user;
    ctrl.isLogged = (ctrl.user);
    ctrl.poll = poll;
    ctrl.poll.close = ctrl.poll.close ? moment(ctrl.poll.close) : ctrl.poll.close;
    ctrl.isClosed = moment(ctrl.poll.close).isAfter(new moment());
    Categorys.query().$promise.then(_ctgrs => {
      ctrl.categorys = _ctgrs;
      console.log();
    })

    ctrl.bk_poll = _.clone(poll);
    ctrl.form = {};
    ctrl.opts = ctrl.poll.opts || [];

    function init() {
      if (ctrl.poll._id) {
        initSocket();
      }
      analysic_nofif();
    }

    init();
    // Init Socket
    function initSocket() {
      if (!Socket.socket) {
        Socket.connect();
      }
      Socket.emit('subscribe_poll', {
        pollId: ctrl.poll._id,
        userId: ctrl.user._id
      });
      Socket.on('poll_delete', res => {
        toast.error('This poll has been deleted.', 'Error!');
        $state.go('polls.list');
      });
      Socket.on('opts_request', res => {
        console.log('Has option request');
        Action.get_poll(ctrl.poll._id)
          .then(_poll => {
            ctrl.poll = _poll;
            ctrl.opts = ctrl.poll.opts;
            $scope.$apply();
          }, err => {
            toast.error(err.message, 'Error!');
          });
      });
      $scope.$on('$destroy', function () {
        Socket.emit('unsubscribe', {
          pollId: ctrl.poll._id,
          userId: ctrl.user._id
        });
        Socket.removeListener('poll_delete');
        Socket.removeListener('opts_request');
      });
    }

    function analysic_nofif() {
      if (notif) {
        if (notif.status === 0) {
          notif.status = 1;
          notif.$update(() => {
            $rootScope.$emit('changeNotif');
          });
        }
      }
    }

    function isCanUpdate() {
      return true;
      // const update = moment(ctrl.poll.updated);
      // const now = moment(new Date());
      // var duration = moment.duration(now.diff(update)).asHours();
      // return duration >= 1;
    }
    // Function
    ctrl.remove = () => {
      $scope.message_title = 'Delete poll!';
      $scope.message_content = 'Are you sure you want to delete?';
      $scope.dialog_type = 3;
      $scope.buton_label = 'Delete';
      dialog.openConfirm({
        scope: $scope,
        templateUrl: 'modules/core/client/views/templates/confirm.dialog.template.html'
      }).then(confirm => {
        handle_delete();
      }, reject => {
      });
      function handle_delete() {
        ctrl.poll.$remove(() => {
          Socket.emit('poll_delete', { pollId: ctrl.poll._id });
          $state.go('polls.list');
        });
      }
    };

    ctrl.save = isValid => {
      if (!isValid) {
        $scope.$broadcast('show-errors-check-validity', 'pollForm');
        return false;
      }

      if (!ctrl.validateBody() || !ctrl.validateCategory() || !ctrl.validateTitle() || !ctrl.validateCloseDate()) {
        toast.error('You have not entered enough information.', 'Error!');
        return;
      }
      if (!ctrl.poll.isPublic) {
        $scope.message_title = 'Save poll!';
        $scope.message_content = 'You want to save a private poll?';
        $scope.dialog_type = 1;
        $scope.buton_label = 'Save';
        dialog.openConfirm({
          scope: $scope,
          templateUrl: 'modules/core/client/views/templates/confirm.dialog.template.html'
        }).then(confirm => {
          handle_save();
        }, reject => {
        });
      } else {
        handle_save();
      }
      function handle_save() {
        ctrl.poll.opts = ctrl.opts;
        Action.save_poll(ctrl.poll)
          .then(res => {
            $state.go('polls.view', { pollId: res._id });
          })
          .catch(err => {
            toast.error(err.message, 'Error!');
          });
      }
    };

    ctrl.validateCategory = () => {
      return (ctrl.poll.category) ? true : false;
    };
    ctrl.validateTitle = () => {
      return (ctrl.poll.title) ? true : false;
    };
    ctrl.validateBody = () => {
      return (ctrl.poll.body) ? true : false;
    };
    ctrl.validateCloseDate = () => {
      if (!ctrl.poll.close) {
        return true;
      }
      return moment(ctrl.poll.close).isAfter(new moment());
    };
    ctrl.discard = () => {
      if (angular.equals(ctrl.poll, ctrl.bk_poll)) {
        handle_discard();
      } else {
        $scope.message_title = 'Discard poll!';
        $scope.message_content = 'Are you sure you want to discard?';
        $scope.dialog_type = 2;
        $scope.buton_label = 'Discard';
        dialog.openConfirm({
          scope: $scope,
          templateUrl: 'modules/core/client/views/templates/confirm.dialog.template.html'
        }).then(confirm => {
          handle_discard();
        }, reject => {
        });
      }
    };
    function handle_discard() {
      if (ctrl.poll._id) {
        $state.go('polls.view', { pollId: ctrl.poll._id });
      } else {
        $state.go('polls.list');
      }
    }

    // OPTIONS
    ctrl.tmp_opt = {};
    ctrl.show_colorpicker = false;
    ctrl.opt_class = opt => {
      var classStr = 'custom-panel ';
      classStr += opt.status === 1 ? 'public' : '';
      classStr += opt.status === 2 ? 'waiting' : '';
      return classStr;
    };
    ctrl.input_opt = opt => {
      ctrl.tmp_opt = (!opt) ? { poll: ctrl.poll._id, title: '', body: '', status: 1 } : opt;
      $mdBottomSheet.show({
        templateUrl: 'modules/polls/client/views/new-opt.client.view.html',
        controller: 'BottomSheetController',
        locals: {
          option: ctrl.tmp_opt
        }
      }).then(function (clickedItem) {
        console.log(clickedItem);
      }).catch(function (error) {
        // User clicked outside or hit escape
      });
    };
    ctrl.remove_opt = opt => {
      $scope.message_title = 'Delete option!';
      $scope.message_content = 'Are you sure you want to delete this option?';
      $scope.dialog_type = 3;
      $scope.buton_label = 'Delete';
      dialog.openConfirm({
        scope: $scope,
        templateUrl: 'modules/core/client/views/templates/confirm.dialog.template.html'
      }).then(confirm => {
        handle_delete();
      }, reject => {
      });
      function handle_delete() {
        ctrl.opts = _.without(ctrl.opts, opt);
        if (opt._id) {
          var _opt = new Opts(opt);
          _opt.$remove(() => {
            Socket.emit('opts_update', { pollId: ctrl.poll._id });
          });
        }
      }
    };
    ctrl.approve_opt = opt => {
      $scope.message_title = 'Approve option!';
      $scope.message_content = 'Are you sure you want to approve this option?';
      $scope.dialog_type = 1;
      $scope.buton_label = 'Approve';
      dialog.openConfirm({
        scope: $scope,
        templateUrl: 'modules/core/client/views/templates/confirm.dialog.template.html'
      }).then(confirm => {
        handle_approve();
      }, reject => {
      });
      function handle_approve() {
        opt.status = 1;
        var _opt = new Opts(opt);
        _opt.$update(() => {
          Socket.emit('opts_update', { pollId: ctrl.poll._id });
        });
      }
    };
    ctrl.reject_opt = opt => {
      $scope.message_title = 'Reject option!';
      $scope.message_content = 'Are you sure you want to reject this option?';
      $scope.dialog_type = 2;
      $scope.buton_label = 'Reject';
      dialog.openConfirm({
        scope: $scope,
        templateUrl: 'modules/core/client/views/templates/confirm.dialog.template.html'
      }).then(confirm => {
        handle_reject();
      }, reject => {
      });
      function handle_reject() {
        opt.status = 3;
        var _opt = new Opts(opt);
        _opt.$update(() => {
        });
      }
    };
    ctrl.save_opt = isValid => {
      if (!isValid) {
        $scope.$broadcast('show-errors-check-validity', 'ctrl.form.optForm');
        return false;
      }
      if (!ctrl.tmp_opt._id && !_.contains(ctrl.opts, ctrl.tmp_opt)) {
        ctrl.opts.push(ctrl.tmp_opt);
      }
    };

    ctrl.showOptionSheet = opt => {
    };
    $scope.clear_close_date = () => {
      delete ctrl.poll.close;
    };

  }
  BottomSheetController.$inject = ['$scope', '$mdBottomSheet'];
  function BottomSheetController($scope, $mdBottomSheet, option) {
    console.log(option);
    $scope.dismiss = () => {
      $mdBottomSheet.hide();
    };
    $scope.save = () => {
      $mdBottomSheet.hide();
    };
    $scope.listItemClick = function ($index) {
      var clickedItem = $scope.items[$index];
      $mdBottomSheet.hide(clickedItem);
    };
  }
})();
<|endoftext|>


<commit_before>(function () {
  'use strict';
  // Polls controller
  angular
    .module('polls')
    .controller('PollInputController', PollInputController);

  PollInputController.$inject = [
    '$scope',
    '$state',
    '$stateParams',
    'PollsService',
    'OptsService',
    'Socket',
    'Action',
    'Constants',
    'Storages',
    'Notifications'
  ];

  function PollInputController(
    $scope,
    $state,
    $stateParams,
    PollsService,
    Opts,
    Socket,
    Action,
    Constants,
    Storages,
    Notifications
  ) {
    var vm = this;
    vm.form = {};
    // Biến tạm lưu option
    vm.tmp_opt = {};

    onPrepare();

    // Lấy id của poll trong đường dẫn để request API
    function onPrepare() {
      if (!$stateParams.pollId) {
        vm.poll = new PollsService();
        onCreate();
      } else {
        Action.loadPollById($stateParams.pollId).then(_poll => {
          // TODO
          console.log(_poll);
          vm.poll = _poll;
          onCreate();
        });
      }
    }

    function onCreate() {
      if (vm.poll._id) {
        if (!vm.poll.isCurrentUserOwner && !$scope.isAdmin) {
          $state.go('home');
          $scope.handleShowMessage('MS_CM_AUTH_ERROR', true);
          return;
        }
        $scope.handleChangePageTitle(vm.poll.title);
        //vm.poll.close = vm.poll.close ? moment(vm.poll.close) : vm.poll.close;
        // vm.isClosed = moment(vm.poll.close).utc().isAfter(new moment().utc());
        // Lắng nghe các request từ server socket
        prepareSocketListener();
      } else {
        // Kiểm tra có poll lưu trong storage hay không
        var poll = JSON.parse(Storages.get_local(Constants.storages.draft_poll, JSON.stringify({})));
        vm.poll = _.extend(vm.poll, poll);
      }
      vm.opts = vm.poll.opts || [];
      vm.bk_poll = _.clone(vm.poll);
      // Kiểm tra thông báo
      prepareParamNotification();
    }

    /**
     * PREPARE
     */
    function prepareSocketListener() {
      if (!Socket.socket) {
        Socket.connect();
      }
      Socket.emit('subscribe_poll', {
        pollId: vm.poll._id,
        userId: $scope.user._id
      });
      Socket.on('poll_delete', res => {
        $scope.handleShowMessage('LB_POLLS_DELETED', true);
        $state.go('polls.list');
      });
      Socket.on('opts_request', res => {
        Opts.get({ optId: res }, _opt => {
          vm.opts.push(_opt);
        });
      });
      $scope.$on('$destroy', function () {
        Socket.emit('unsubscribe', {
          pollId: vm.poll._id,
          userId: $scope.user._id
        });
        Socket.removeListener('poll_delete');
        Socket.removeListener('opts_request');
      });
    }
    function prepareParamNotification() {
      if ($stateParams.notif) {
        Notifications.markReadNotif($stateParams.notif);
      }
    }

    /**
     * HANDLES
     */
    // Lưu poll
    vm.handleSavePoll = isValid => {
      if (!isValid) {
        $scope.$broadcast('show-errors-check-validity', 'vm.form.pollForm');
        $scope.handleShowMessage('LB_POLL_SAVE_ERROR', true);
        return false;
      }
      if (!handleValidateCloseDate()) {
        $scope.handleShowMessage('LB_POLLS_CLOSE_INVALID', true);
        return;
      }
      if (!vm.poll.isPublic) {
        // Gọi function show dialog từ scope cha
        $scope.handleShowConfirm({
          content: 'LB_POLLS_PRIVATE_SAVE',
          type: 1,
          button: 'LB_SAVE'
        }, confirm => {
          handleSave();
        });
      } else {
        handleSave();
      }
      // TODO
      console.log(vm.poll.close);
      function handleSave() {
        vm.poll.opts = vm.opts;
        Action.savePoll(vm.poll)
          .then(res => {
            Storages.remove_local(Constants.storages.draft_poll);
            $state.go('polls.view', { pollId: res.slug });
          })
          .catch(err => {
            $scope.handleShowMessage(err.message, true);
          });
      }
    };
    // Lưu nháp
    vm.handleSaveDraft = () => {
      vm.poll.opts = vm.opts;
      Storages.set_local(Constants.storages.draft_poll, JSON.stringify(vm.poll));
      $scope.handleShowMessage('LB_POLL_SAVE_DRAFT', false);
    };
    // Hủy nhập poll
    vm.handleDiscard = handleDiscard;
    function handleDiscard() {
      if (angular.equals(vm.poll, vm.bk_poll)) {
        handle_discard();
      } else {
        // Gọi function show dialog từ scope cha
        $scope.handleShowConfirm({
          content: 'LB_POLLS_CONFIRM_DISCARD',
          type: 2,
          button: 'LB_DISCARD'
        }, confirm => {
          handle_discard();
        });
      }
      function handle_discard() {
        Storages.remove_local(Constants.storages.draft_poll);
        if (vm.poll._id) {
          $state.go('polls.view', { pollId: vm.poll.slug });
        } else {
          $state.go('home');
        }
      }
    }
    // Gọi màn hình nhập thông tin options
    vm.handleStartInputOption = handleStartInputOption;
    vm.isFocusOptionInput = false;
    function handleStartInputOption(opt) {
      vm.tmp_opt = (opt) ? _.clone(opt) : { poll: vm.poll._id, title: '', body: '', status: 1 };
      angular.element('body').toggleClass('aside-panel-open');
      vm.isFocusOptionInput = true;
    }
    // Xóa option
    vm.handleRemoveOption = handleRemoveOption;
    function handleRemoveOption(opt) {
      // Gọi function show dialog từ scope cha
      $scope.handleShowConfirm({
        content: 'LB_POLLS_CONFIRM_DELETE_OPT',
        type: 3,
        button: 'LB_DELETE'
      }, confirm => {
        handle_delete();
      });

      function handle_delete() {
        vm.opts = _.without(vm.opts, opt);
        if (opt._id) {
          var _opt = new Opts(opt);
          _opt.$remove(() => {
            Socket.emit('opts_update', { pollId: vm.poll._id });
          });
        }
      }
    }
    // Đồng ý đề xuất của thành viên
    vm.handleApproveOption = handleApproveOption;
    function handleApproveOption(opt) {
      // Gọi function show dialog từ scope cha
      $scope.handleShowConfirm({
        content: 'LB_POLLS_CONFIRM_APPROVE',
        type: 1,
        button: 'LB_APPROVE'
      }, confirm => {
        handle_approve();
      });
      function handle_approve() {
        opt.status = 1;
        var _opt = new Opts({ _id: opt._id, status: opt.status });
        _opt.$update(() => {
          Socket.emit('opts_update', { pollId: vm.poll._id });
        });
      }
    }
    // Từ chối đề xuất
    vm.handleRejectOption = handleRejectOption;
    function handleRejectOption(opt) {
      // Gọi function show dialog từ scope cha
      $scope.handleShowConfirm({
        content: 'LB_POLLS_CONFIRM_REJECT',
        type: 2,
        button: 'LB_REJECT'
      }, confirm => {
        handle_reject();
      });
      function handle_reject() {
        opt.status = 3;
        var _opt = new Opts({ _id: opt._id, status: opt.status });
        _opt.$update(() => {
        });
      }
    }
    // Lưu option
    vm.handleSaveOption = handleSaveOption;
    function handleSaveOption(isValid) {
      if (!isValid) {
        $scope.$broadcast('show-errors-check-validity', 'vm.form.optForm');
        return false;
      }
      // Kiểm tra poll đã tồn tại
      if (vm.tmp_opt._id) {
        // Update vào option cũ
        var opt = _.findWhere(vm.opts, { _id: vm.tmp_opt._id });
        opt = _.extend(opt, vm.tmp_opt);
      } else {
        // Nếu chưa có option nào giống với option mới thì add vào list
        if (!_.contains(vm.opts, vm.tmp_opt)) {
          vm.opts.push(_.clone(vm.tmp_opt));
        } else {
          $scope.handleShowMessage('LB_OPTION_DUPLICATE', true);
        }
      }
      vm.tmp_opt = {};
      $scope.$broadcast('show-errors-reset', 'vm.form.optForm');
      angular.element('body').removeClass('aside-panel-open');
      vm.isFocusOptionInput = false;
    }
    // Hiển thị full màn hình
    vm.handleShowFullOption = handleShowFullOption;
    function handleShowFullOption() {
      let aside = angular.element('.aside-panel')[0];
      angular.element(aside).toggleClass('full');
      angular.element('#aside-panel-full-toggle').find('i').toggleClass('r180');
    }
    // Xóa thông tin cài đặt ngày close
    vm.handleClearCloseDate = handleClearCloseDate;
    function handleClearCloseDate() {
      delete vm.poll.close;
    }
    // Kiểm tra ngày đóng poll hợp lệ hay không
    function handleValidateCloseDate() {
      if (!vm.poll.close) return true;
      if (vm.poll._id && vm.isClosed) return true;
      return moment(vm.poll.close).utc().isAfter(new moment().utc());
    }
  }
})();
<commit_msg>Commited from lenh at Wed, Nov 01, 2017 10:10:32 AM<commit_after>(function () {
  'use strict';
  // Polls controller
  angular
    .module('polls')
    .controller('PollInputController', PollInputController);

  PollInputController.$inject = [
    '$scope',
    '$state',
    '$stateParams',
    'PollsService',
    'OptsService',
    'Socket',
    'Action',
    'Constants',
    'Storages',
    'Notifications'
  ];

  function PollInputController(
    $scope,
    $state,
    $stateParams,
    PollsService,
    Opts,
    Socket,
    Action,
    Constants,
    Storages,
    Notifications
  ) {
    var vm = this;
    vm.form = {};
    // Biến tạm lưu option
    vm.tmp_opt = {};

    onPrepare();

    // Lấy id của poll trong đường dẫn để request API
    function onPrepare() {
      if (!$stateParams.pollId) {
        vm.poll = new PollsService();
        onCreate();
      } else {
        Action.loadPollById($stateParams.pollId).then(_poll => {
          // TODO
          console.log(_poll);
          vm.poll = _poll;
          onCreate();
        });
      }
    }

    function onCreate() {
      if (vm.poll._id) {
        if (!vm.poll.isCurrentUserOwner && !$scope.isAdmin) {
          $state.go('home');
          $scope.handleShowMessage('MS_CM_AUTH_ERROR', true);
          return;
        }
        $scope.handleChangePageTitle(vm.poll.title);
        vm.closeDate = moment(vm.poll.close);
        console.log(vm.closeDate.format());
        console.log(vm.closeDate.local().format());
        console.log(vm.closeDate.utc().format());
        //vm.poll.close = vm.poll.close ? moment(vm.poll.close) : vm.poll.close;
        // vm.isClosed = moment(vm.poll.close).utc().isAfter(new moment().utc());
        // Lắng nghe các request từ server socket
        prepareSocketListener();
      } else {
        // Kiểm tra có poll lưu trong storage hay không
        var poll = JSON.parse(Storages.get_local(Constants.storages.draft_poll, JSON.stringify({})));
        vm.poll = _.extend(vm.poll, poll);
      }
      vm.opts = vm.poll.opts || [];
      vm.bk_poll = _.clone(vm.poll);
      // Kiểm tra thông báo
      prepareParamNotification();
    }

    /**
     * PREPARE
     */
    function prepareSocketListener() {
      if (!Socket.socket) {
        Socket.connect();
      }
      Socket.emit('subscribe_poll', {
        pollId: vm.poll._id,
        userId: $scope.user._id
      });
      Socket.on('poll_delete', res => {
        $scope.handleShowMessage('LB_POLLS_DELETED', true);
        $state.go('polls.list');
      });
      Socket.on('opts_request', res => {
        Opts.get({ optId: res }, _opt => {
          vm.opts.push(_opt);
        });
      });
      $scope.$on('$destroy', function () {
        Socket.emit('unsubscribe', {
          pollId: vm.poll._id,
          userId: $scope.user._id
        });
        Socket.removeListener('poll_delete');
        Socket.removeListener('opts_request');
      });
    }
    function prepareParamNotification() {
      if ($stateParams.notif) {
        Notifications.markReadNotif($stateParams.notif);
      }
    }

    /**
     * HANDLES
     */
    // Lưu poll
    vm.handleSavePoll = isValid => {
      if (!isValid) {
        $scope.$broadcast('show-errors-check-validity', 'vm.form.pollForm');
        $scope.handleShowMessage('LB_POLL_SAVE_ERROR', true);
        return false;
      }
      if (!handleValidateCloseDate()) {
        $scope.handleShowMessage('LB_POLLS_CLOSE_INVALID', true);
        return;
      }
      if (!vm.poll.isPublic) {
        // Gọi function show dialog từ scope cha
        $scope.handleShowConfirm({
          content: 'LB_POLLS_PRIVATE_SAVE',
          type: 1,
          button: 'LB_SAVE'
        }, confirm => {
          handleSave();
        });
      } else {
        handleSave();
      }
      // TODO
      console.log(vm.poll.close);
      function handleSave() {
        vm.poll.opts = vm.opts;
        Action.savePoll(vm.poll)
          .then(res => {
            Storages.remove_local(Constants.storages.draft_poll);
            $state.go('polls.view', { pollId: res.slug });
          })
          .catch(err => {
            $scope.handleShowMessage(err.message, true);
          });
      }
    };
    // Lưu nháp
    vm.handleSaveDraft = () => {
      vm.poll.opts = vm.opts;
      Storages.set_local(Constants.storages.draft_poll, JSON.stringify(vm.poll));
      $scope.handleShowMessage('LB_POLL_SAVE_DRAFT', false);
    };
    // Hủy nhập poll
    vm.handleDiscard = handleDiscard;
    function handleDiscard() {
      if (angular.equals(vm.poll, vm.bk_poll)) {
        handle_discard();
      } else {
        // Gọi function show dialog từ scope cha
        $scope.handleShowConfirm({
          content: 'LB_POLLS_CONFIRM_DISCARD',
          type: 2,
          button: 'LB_DISCARD'
        }, confirm => {
          handle_discard();
        });
      }
      function handle_discard() {
        Storages.remove_local(Constants.storages.draft_poll);
        if (vm.poll._id) {
          $state.go('polls.view', { pollId: vm.poll.slug });
        } else {
          $state.go('home');
        }
      }
    }
    // Gọi màn hình nhập thông tin options
    vm.handleStartInputOption = handleStartInputOption;
    vm.isFocusOptionInput = false;
    function handleStartInputOption(opt) {
      vm.tmp_opt = (opt) ? _.clone(opt) : { poll: vm.poll._id, title: '', body: '', status: 1 };
      angular.element('body').toggleClass('aside-panel-open');
      vm.isFocusOptionInput = true;
    }
    // Xóa option
    vm.handleRemoveOption = handleRemoveOption;
    function handleRemoveOption(opt) {
      // Gọi function show dialog từ scope cha
      $scope.handleShowConfirm({
        content: 'LB_POLLS_CONFIRM_DELETE_OPT',
        type: 3,
        button: 'LB_DELETE'
      }, confirm => {
        handle_delete();
      });

      function handle_delete() {
        vm.opts = _.without(vm.opts, opt);
        if (opt._id) {
          var _opt = new Opts(opt);
          _opt.$remove(() => {
            Socket.emit('opts_update', { pollId: vm.poll._id });
          });
        }
      }
    }
    // Đồng ý đề xuất của thành viên
    vm.handleApproveOption = handleApproveOption;
    function handleApproveOption(opt) {
      // Gọi function show dialog từ scope cha
      $scope.handleShowConfirm({
        content: 'LB_POLLS_CONFIRM_APPROVE',
        type: 1,
        button: 'LB_APPROVE'
      }, confirm => {
        handle_approve();
      });
      function handle_approve() {
        opt.status = 1;
        var _opt = new Opts({ _id: opt._id, status: opt.status });
        _opt.$update(() => {
          Socket.emit('opts_update', { pollId: vm.poll._id });
        });
      }
    }
    // Từ chối đề xuất
    vm.handleRejectOption = handleRejectOption;
    function handleRejectOption(opt) {
      // Gọi function show dialog từ scope cha
      $scope.handleShowConfirm({
        content: 'LB_POLLS_CONFIRM_REJECT',
        type: 2,
        button: 'LB_REJECT'
      }, confirm => {
        handle_reject();
      });
      function handle_reject() {
        opt.status = 3;
        var _opt = new Opts({ _id: opt._id, status: opt.status });
        _opt.$update(() => {
        });
      }
    }
    // Lưu option
    vm.handleSaveOption = handleSaveOption;
    function handleSaveOption(isValid) {
      if (!isValid) {
        $scope.$broadcast('show-errors-check-validity', 'vm.form.optForm');
        return false;
      }
      // Kiểm tra poll đã tồn tại
      if (vm.tmp_opt._id) {
        // Update vào option cũ
        var opt = _.findWhere(vm.opts, { _id: vm.tmp_opt._id });
        opt = _.extend(opt, vm.tmp_opt);
      } else {
        // Nếu chưa có option nào giống với option mới thì add vào list
        if (!_.contains(vm.opts, vm.tmp_opt)) {
          vm.opts.push(_.clone(vm.tmp_opt));
        } else {
          $scope.handleShowMessage('LB_OPTION_DUPLICATE', true);
        }
      }
      vm.tmp_opt = {};
      $scope.$broadcast('show-errors-reset', 'vm.form.optForm');
      angular.element('body').removeClass('aside-panel-open');
      vm.isFocusOptionInput = false;
    }
    // Hiển thị full màn hình
    vm.handleShowFullOption = handleShowFullOption;
    function handleShowFullOption() {
      let aside = angular.element('.aside-panel')[0];
      angular.element(aside).toggleClass('full');
      angular.element('#aside-panel-full-toggle').find('i').toggleClass('r180');
    }
    // Xóa thông tin cài đặt ngày close
    vm.handleClearCloseDate = handleClearCloseDate;
    function handleClearCloseDate() {
      delete vm.poll.close;
    }
    // Kiểm tra ngày đóng poll hợp lệ hay không
    function handleValidateCloseDate() {
      if (!vm.poll.close) return true;
      if (vm.poll._id && vm.isClosed) return true;
      return moment(vm.poll.close).utc().isAfter(new moment().utc());
    }
  }
})();
<|endoftext|>


<commit_before>const { expect } = require('chai');
const { searchEventsAction } = require('../app/actions');
const TYPES = require('../app/actions/action_types');

// ----------------------------------------
// import { expect } from 'chai';
// import * as actions from '../../actions/TodoActions'
// import * as types from '../../constants/ActionTypes'
// ----------------------------------------

describe('Action Creators', () => {
  describe('searchEventsAction', () => {
    it('should create a search query action', () => {
      const query = 'T'
      const expectedAction = {
        type: TYPES.SEARCH_EVENTS,
        payload: { query }
      };

      expect(searchEventsAction(query)).to.deep.equal(expectedAction)
    });

    it(`should have a type of ${TYPES.SEARCH_EVENTS}`, () => {
      const query = 'T'
      const expectedAction = {
        type: TYPES.SEARCH_EVENTS,
        payload: { query }
      };

      expect(searchEventsAction(query).type).to.equal(TYPES.SEARCH_EVENTS)
    });
  });
})
<commit_msg>(test) More search action testing<commit_after>const { expect } = require('chai');
const { searchEventsAction } = require('../app/actions');
const TYPES = require('../app/actions/action_types');

// ----------------------------------------
// import { expect } from 'chai';
// import * as actions from '../../actions/TodoActions'
// import * as types from '../../constants/ActionTypes'
// ----------------------------------------

describe('Action Creators', () => {
  describe('searchEventsAction', () => {
    it('should be a function', () => {
      expect(searchEventsAction).to.be.a('function');
    });

    it('should return an object', () => {
      const query = 'T'
      const expectedAction = {
        type: TYPES.SEARCH_EVENTS,
        payload: { query }
      };

      expect(searchEventsAction(query)).to.be.a('object');
    });

    it('should create a search query action', () => {
      const query = 'T'
      const expectedAction = {
        type: TYPES.SEARCH_EVENTS,
        payload: { query }
      };

      expect(searchEventsAction(query)).to.deep.equal(expectedAction);
    });

    it(`should have a type of ${TYPES.SEARCH_EVENTS}`, () => {
      const query = 'T'
      const expectedAction = {
        type: TYPES.SEARCH_EVENTS,
        payload: { query }
      };

      expect(searchEventsAction(query).type).to.equal(TYPES.SEARCH_EVENTS)
    });
  });
})
<|endoftext|>


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

  // Polls controller
  angular
    .module('polls')
    .controller('PollInputController', PollInputController);

  PollInputController.$inject = [
    '$scope',
    '$state',
    '$window',
    'Authentication',
    'pollResolve',
    'PollsApi',
    'TagsService',
    '$aside',
    'OptsService'
  ];

  function PollInputController($scope, $state, $window, Authentication, poll, PollsApi, Tags, $aside, Opts) {
    var vm = this;

    vm.authentication = Authentication;
    vm.poll = poll;
    vm.poll.close = (vm.poll.close) ? moment(vm.poll.close) : vm.poll.close;
    vm.poll.tags = [];
    vm.bk_poll = angular.copy(poll);
    vm.error = null;
    vm.form = {};

    vm.opts = [];

    if (vm.poll._id) {
      // Get all Opts
      PollsApi.findOpts(poll._id)
        .then(opts => {
          vm.opts = opts.data;
        })
        .catch(err => {
          alert('error' + err);
        });
      // Get all Tags
      PollsApi.findTags(poll._id)
        .then(polltags => {
          angular.forEach(polltags.data, (polltag, index) => {
            vm.poll.tags.push(polltag.tag);
          });
        })
        .catch(err => {
          alert('error' + err);
        });
    }

    // Function
    vm.remove = remove;
    vm.save = save;
    vm.discard = discard;

    // Remove existing Poll
    function remove() {
      if ($window.confirm('Are you sure you want to delete?')) {
        vm.poll.$remove($state.go('polls.list'));
      }
    }

    // Save Poll
    function save(isValid) {
      if (!isValid) {
        $scope.$broadcast('show-errors-check-validity', 'vm.form.pollForm');
        return false;
      }
      // TODO: move create/update logic to service
      if (vm.poll._id) {
        vm.poll.$update(successCallback, errorCallback);
      } else {
        vm.poll.$save(successCallback, errorCallback);
      }

      function successCallback(res) {
        $state.go('polls.view', {
          pollId: res._id
        });
      }

      function errorCallback(res) {
        vm.error = res.data.message;
      }
    }

    // Discard edit or add poll
    function discard() {
      if (angular.equals(vm.poll, vm.bk_poll)) {
        handle_discard();
      } else {
        if ($window.confirm('Are you sure you want to discard?')) {
          handle_discard();
        }
      }
    }

    // Back to before screen
    function handle_discard() {
      if (vm.poll._id) {
        $state.go('polls.view', { pollId: vm.poll._id });
      } else {
        $state.go('polls.list');
      }
    }

    // OPTIONS
    vm.opt_form = {
      scope: $scope,
      controllerAs: vm,
      templateUrl: 'modules/opts/client/views/new-opt-in-poll.client.view.html',
      title: vm.poll.title,
      placement: 'bottom',
      animation: 'am-fade-and-slide-bottom',
      show: false
    };
    var opt_aside = $aside(vm.opt_form);
    vm.input_opt = input_opt;
    vm.save_opt = save_opt;
    vm.aside_full_screen = aside_full_screen;
    // Click button add option
    function input_opt(opt) {
      vm.option = (!opt) ? {poll: vm.poll._id, title: '', body: '', image: 'modules/opts/client/img/option.png'} : opt;
      opt_aside.$promise.then(opt_aside.show);
    }
    // Click button save option
    function save_opt($form) {
      if (!$form.$valid) {
        $scope.$broadcast('show-errors-check-validity', 'vm.form.optForm');
        return false;
      }
      if (!vm.option._id) {
        vm.opts.push(vm.option);
        opt_aside.$promise.then(opt_aside.hide);
      }
      // if (vm.option._id) {
      //   vm.option.$update(successCallback, errorCallback);
      // } else {
      //   vm.option.poll = vm.poll._id;
      //   vm.comment.$save(successCallback, errorCallback);
      // }

      function successCallback(res) {
        opt_aside.$promise.then(opt_aside.hide);
        $state.reload();
      }

      function errorCallback(err) {
        console.log(err);
        //vm.error = res.data.message;
      }
    }
    function aside_full_screen() {
      alert(1);
    }
  }
}());
<commit_msg>Commited from lenh at 2017年 6月 20日 火曜日 19:36:46<commit_after>(function() {
  'use strict';

  // Polls controller
  angular
    .module('polls')
    .controller('PollInputController', PollInputController);

  PollInputController.$inject = [
    '$scope',
    '$state',
    '$window',
    'Authentication',
    'pollResolve',
    'PollsApi',
    'TagsService',
    '$aside',
    'OptsService'
  ];

  function PollInputController($scope, $state, $window, Authentication, poll, PollsApi, Tags, $aside, Opts) {
    var vm = this;

    vm.authentication = Authentication;
    vm.poll = poll;
    vm.poll.close = (vm.poll.close) ? moment(vm.poll.close) : vm.poll.close;
    vm.poll.tags = [];
    vm.bk_poll = angular.copy(poll);
    vm.error = null;
    vm.form = {};

    vm.opts = [];

    if (vm.poll._id) {
      // Get all Opts
      PollsApi.findOpts(poll._id)
        .then(opts => {
          vm.opts = opts.data;
        })
        .catch(err => {
          alert('error' + err);
        });
      // Get all Tags
      PollsApi.findTags(poll._id)
        .then(polltags => {
          angular.forEach(polltags.data, (polltag, index) => {
            vm.poll.tags.push(polltag.tag);
          });
        })
        .catch(err => {
          alert('error' + err);
        });
    }

    // Function
    vm.remove = remove;
    vm.save = save;
    vm.discard = discard;

    // Remove existing Poll
    function remove() {
      if ($window.confirm('Are you sure you want to delete?')) {
        vm.poll.$remove($state.go('polls.list'));
      }
    }

    // Save Poll
    function save(isValid) {
      if (!isValid) {
        $scope.$broadcast('show-errors-check-validity', 'vm.form.pollForm');
        return false;
      }
      // TODO: move create/update logic to service
      if (vm.poll._id) {
        vm.poll.$update(successCallback, errorCallback);
      } else {
        vm.poll.$save(successCallback, errorCallback);
      }

      function successCallback(res) {
        $state.go('polls.view', {
          pollId: res._id
        });
      }

      function errorCallback(res) {
        vm.error = res.data.message;
      }
    }

    // Discard edit or add poll
    function discard() {
      if (angular.equals(vm.poll, vm.bk_poll)) {
        handle_discard();
      } else {
        if ($window.confirm('Are you sure you want to discard?')) {
          handle_discard();
        }
      }
    }

    // Back to before screen
    function handle_discard() {
      if (vm.poll._id) {
        $state.go('polls.view', { pollId: vm.poll._id });
      } else {
        $state.go('polls.list');
      }
    }

    // OPTIONS
    vm.opt_form = {
      scope: $scope,
      controllerAs: vm,
      templateUrl: 'modules/opts/client/views/new-opt-in-poll.client.view.html',
      title: vm.poll.title,
      placement: 'bottom',
      animation: 'am-fade-and-slide-bottom',
      show: false
    };
    var opt_aside = $aside(vm.opt_form);
    vm.input_opt = input_opt;
    vm.save_opt = save_opt;
    vm.aside_full_screen = aside_full_screen;
    // Click button add option
    function input_opt(opt) {
      vm.option = (!opt) ? {poll: vm.poll._id, title: '', body: '', image: 'modules/opts/client/img/option.png'} : opt;
      opt_aside.$promise.then(opt_aside.show);
    }
    // Click button save option
    function save_opt($form) {
      if (!$form.$valid) {
        $scope.$broadcast('show-errors-check-validity', 'vm.form.optForm');
        return false;
      }
      if (!vm.option._id) {
        vm.opts.push(vm.option);
      }
      opt_aside.$promise.then(opt_aside.hide);
      // if (vm.option._id) {
      //   vm.option.$update(successCallback, errorCallback);
      // } else {
      //   vm.option.poll = vm.poll._id;
      //   vm.comment.$save(successCallback, errorCallback);
      // }

      function successCallback(res) {
        opt_aside.$promise.then(opt_aside.hide);
        $state.reload();
      }

      function errorCallback(err) {
        console.log(err);
        //vm.error = res.data.message;
      }
    }
    function aside_full_screen() {
      alert(1);
    }
  }
}());
<|endoftext|>


<commit_before>var $ = require('jquery');
var L = require('leaflet');
var Search = require('cdb/geo/ui/search');
var NOKIA  = require('cdb/geo/geocoder/nokia-geocoder');
var Map = require('cdb/geo/map');
var Template = require('cdb/core/template');
var LeafletMapView = require('cdb/geo/leaflet/leaflet-map-view');

describe('cdb/geo/ui/search', function() {

  beforeEach(function() {
    this.$el = $("
")
      .attr('id', 'map')
      .height(500)
      .width(500);
    $('body').append(this.$el);
    this.map = new Map();
    var template = Template.compile(
      '\
        <form>\
          \
          <input type="text" class="text" value="" />\
          <input type="submit" class="submit" value="" />\
        </form>\
      ',
      'mustache'
    );
    this.mapView = new LeafletMapView({
      el: this.$el,
      map: this.map
    });

    this.view = new Search({
      template: template,
      model: this.map,
      mapView: this.mapView
    });
    this.view.render();
  });

  it('should render properly', function() {
    expect(this.view.$('form').length).toBe(1);
    expect(this.view.$('input[type="text"]').length).toBe(1);
    expect(this.view.$('input[type="submit"]').length).toBe(1);
    expect(this.view.$('span.loader').length).toBe(1);
  });

  describe('onSubmit', function() {
    beforeEach(function(){
      var self = this;
      this.result = {
        lat: 43.0,
        lon: -3.0,
        boundingbox: {
          south: 6.0,
          north: 4.0,
          west: 6.0,
          east: 4.0
        },
        type: undefined
      };
      NOKIA.geocode = function(address, callback) {
        callback([ self.result ]);
      };

      this.view.$('input.text').val('Madrid, Spain');
    });

    it('should search with geocoder when form is submit', function() {
      spyOn(NOKIA, 'geocode');
      this.view.$('form').submit();
      expect(NOKIA.geocode).toHaveBeenCalled();
    });

    it('should change map center when geocoder returns any result', function() {
      var onBoundsChanged = jasmine.createSpy("onBoundsChange");
      this.map.bind('change:view_bounds_sw', onBoundsChanged, this.view);
      this.view.$('form').submit();
      expect(onBoundsChanged).toHaveBeenCalled();
      this.map.unbind('change:view_bounds_sw', onBoundsChanged, this.view);
    });

    it('should center map to lat,lon when bbox is not defined', function() {
      this.result = {
        lat: 43.0,
        lon: -3.0
      }
      this.view.$('form').submit();
      var center = this.map.get('center');
      expect(center[0]).toBe(43.0);
      expect(center[1]).toBe(-3.0);
    });

    it('should center map whith bbox when it is defined', function() {
      this.view.$('form').submit();
      var ne = this.map.get('view_bounds_ne');
      var sw = this.map.get('view_bounds_sw');
      expect(ne[0].toFixed(0)).toBe('6');
      expect(ne[1].toFixed(0)).toBe('6');
      expect(sw[0].toFixed(0)).toBe('4');
      expect(sw[1].toFixed(0)).toBe('4');
      var center = this.map.get('center');
      expect(center[0]).not.toBe(43.0);
      expect(center[1]).not.toBe(-3.0);
    });

    describe('result zoom', function() {

      it('should zoom to 18 when search result is building type', function() {
        this.result = {
          lat: 43.0,
          lon: -3.0,
          type: 'building'
        };
        this.view.$('form').submit();
        expect(this.map.get('zoom')).toBe(18);
      });

      it('should zoom to 15 when search result is building type', function() {
        this.result = {
          lat: 43.0,
          lon: -3.0,
          type: 'postal-area'
        };
        this.view.$('form').submit();
        expect(this.map.get('zoom')).toBe(15);
      });

      it('should zoom to 12 when search result is unknown type', function() {
        this.result = {
          lat: 43.0,
          lon: -3.0,
          type: 'whatever'
        };
        this.view.$('form').submit();
        expect(this.map.get('zoom')).toBe(12);
      });
    });

    describe('searchPin', function() {
      beforeEach(function() {
        this.view.options.searchPin = true;
        this.view.$('form').submit();
      });

      it('should add a pin and an infowindow when search is completed', function() {
        expect(this.view._searchPin).toBeDefined();
        expect(this.view._searchInfowindow).toBeDefined();
      });

      it('should place pin in the lat,lon if it is provided', function() {
        this.result = {
          lat: 43.0,
          lon: -3.0
        };
        var center = this.view._searchPin.model.get('geojson').coordinates;
        expect(center[0]).toBe(-3.0);
        expect(center[1]).toBe(43.0);
      });

      it('should place pin in the middle of the bbox if lat,lon is not provided', function() {
        this.result = {
          boundingbox: {
            south: 6.0,
            north: 4.0,
            west: 6.0,
            east: 4.0
          }
        };
        this.view.$('form').submit();
        var center = this.view._searchPin.model.get('geojson').coordinates;
        expect(center[0]).toBe(5.0);
        expect(center[1]).toBe(5.0);
      });

      it('should display address in the search infowindow', function() {
        expect(this.view._searchInfowindow.$('.cartodb-popup-content-wrapper p').text()).toBe('Madrid, Spain');
      });

      it('should destroy/hide search pin when map is clicked', function(done) {
        jasmine.clock().install();

        var view = this.view;
        expect(view._searchPin).toBeDefined();
        expect(view._searchInfowindow).toBeDefined();
        this.mapView.trigger('click');
        setTimeout(function() {
          expect(view._searchPin).toBeUndefined();
          expect(view._searchInfowindow).toBeUndefined();
          done();
        }, 1500);

        jasmine.clock().tick(2000);
      });
    });
  });

  afterEach(function() {
    this.$el.remove();
    jasmine.clock().uninstall();
  })

});
<commit_msg>Fix test<commit_after>var $ = require('jquery');
var L = require('leaflet');
var Search = require('cdb/geo/ui/search');
var NOKIA  = require('cdb/geo/geocoder/nokia-geocoder');
var Map = require('cdb/geo/map');
var Template = require('cdb/core/template');
var LeafletMapView = require('cdb/geo/leaflet/leaflet-map-view');

describe('cdb/geo/ui/search', function() {

  beforeEach(function() {
    this.$el = $("
")
      .attr('id', 'map')
      .height(500)
      .width(500);
    $('body').append(this.$el);
    this.map = new Map();
    var template = Template.compile(
      '\
        <form>\
          \
          <input type="text" class="text" value="" />\
          <input type="submit" class="submit" value="" />\
        </form>\
      ',
      'mustache'
    );
    this.mapView = new LeafletMapView({
      el: this.$el,
      map: this.map
    });

    this.view = new Search({
      template: template,
      model: this.map,
      mapView: this.mapView
    });
    this.view.render();
  });

  it('should render properly', function() {
    expect(this.view.$('form').length).toBe(1);
    expect(this.view.$('input[type="text"]').length).toBe(1);
    expect(this.view.$('input[type="submit"]').length).toBe(1);
    expect(this.view.$('span.loader').length).toBe(1);
  });

  describe('onSubmit', function() {
    beforeEach(function(){
      var self = this;
      this.result = {
        lat: 43.0,
        lon: -3.0,
        boundingbox: {
          south: 6.0,
          north: 4.0,
          west: 6.0,
          east: 4.0
        },
        type: undefined
      };
      NOKIA.geocode = function(address, callback) {
        callback([ self.result ]);
      };

      this.view.$('input.text').val('Madrid, Spain');
    });

    it('should search with geocoder when form is submit', function() {
      spyOn(NOKIA, 'geocode');
      this.view.$('form').submit();
      expect(NOKIA.geocode).toHaveBeenCalled();
    });

    it('should change map center when geocoder returns any result', function() {
      var onBoundsChanged = jasmine.createSpy("onBoundsChange");
      this.map.bind('change:view_bounds_sw', onBoundsChanged, this.view);
      this.view.$('form').submit();
      expect(onBoundsChanged).toHaveBeenCalled();
      this.map.unbind('change:view_bounds_sw', onBoundsChanged, this.view);
    });

    it('should center map to lat,lon when bbox is not defined', function() {
      this.result = {
        lat: 43.0,
        lon: -3.0
      }
      this.view.$('form').submit();
      var center = this.map.get('center');
      expect(center[0]).toBe(43.0);
      expect(center[1]).toBe(-3.0);
    });

    it('should center map whith bbox when it is defined', function() {
      this.view.$('form').submit();
      var ne = this.map.get('view_bounds_ne');
      var sw = this.map.get('view_bounds_sw');
      expect(ne[0].toFixed(0)).toBe('6');
      expect(ne[1].toFixed(0)).toBe('6');
      expect(sw[0].toFixed(0)).toBe('4');
      expect(sw[1].toFixed(0)).toBe('4');
      var center = this.map.get('center');
      expect(center[0]).not.toBe(43.0);
      expect(center[1]).not.toBe(-3.0);
    });

    describe('result zoom', function() {

      it('should zoom to 18 when search result is building type', function() {
        this.result = {
          lat: 43.0,
          lon: -3.0,
          type: 'building'
        };
        this.view.$('form').submit();
        expect(this.map.get('zoom')).toBe(18);
      });

      it('should zoom to 15 when search result is building type', function() {
        this.result = {
          lat: 43.0,
          lon: -3.0,
          type: 'postal-area'
        };
        this.view.$('form').submit();
        expect(this.map.get('zoom')).toBe(15);
      });

      it('should zoom to 12 when search result is unknown type', function() {
        this.result = {
          lat: 43.0,
          lon: -3.0,
          type: 'whatever'
        };
        this.view.$('form').submit();
        expect(this.map.get('zoom')).toBe(12);
      });
    });

    describe('searchPin', function() {
      beforeEach(function() {
        this.view.options.searchPin = true;
        this.view.$('form').submit();
      });

      it('should add a pin and an infowindow when search is completed', function() {
        expect(this.view._searchPin).toBeDefined();
        expect(this.view._searchInfowindow).toBeDefined();
      });

      it('should place pin in the lat,lon if it is provided', function() {
        this.result = {
          lat: 43.0,
          lon: -3.0
        };
        var center = this.view._searchPin.model.get('geojson').coordinates;
        expect(center[0]).toBe(-3.0);
        expect(center[1]).toBe(43.0);
      });

      it('should place pin in the middle of the bbox if lat,lon is not provided', function() {
        this.result = {
          boundingbox: {
            south: 6.0,
            north: 4.0,
            west: 6.0,
            east: 4.0
          }
        };
        this.view.$('form').submit();
        var center = this.view._searchPin.model.get('geojson').coordinates;
        expect(center[0]).toBe(5.0);
        expect(center[1]).toBe(5.0);
      });

      it('should display address in the search infowindow', function() {
        expect(this.view._searchInfowindow.$('.Cdb-infowindow-title').text()).toBe('Madrid, Spain');
      });

      it('should destroy/hide search pin when map is clicked', function(done) {
        jasmine.clock().install();

        var view = this.view;
        expect(view._searchPin).toBeDefined();
        expect(view._searchInfowindow).toBeDefined();
        this.mapView.trigger('click');
        setTimeout(function() {
          expect(view._searchPin).toBeUndefined();
          expect(view._searchInfowindow).toBeUndefined();
          done();
        }, 1500);

        jasmine.clock().tick(2000);
      });
    });
  });

  afterEach(function() {
    this.$el.remove();
    jasmine.clock().uninstall();
  })

});
<|endoftext|>


<commit_before>'use strict'

var gulp = require('gulp')
var rimraf = require('gulp-rimraf')
var tslint = require('gulp-tslint')
var ts = require('gulp-typescript')
var sourcemaps = require('gulp-sourcemaps')
var bowerfiles = require('main-bower-files')
var concat = require('gulp-concat')
var cssmin = require('gulp-cssmin')
var uglify = require('gulp-uglify')
var flatten = require('gulp-flatten')
var util = require('gulp-util')

var paths = {
  wwwroot: './wwwroot/',
  src: './src/',
  test: './test/'
}

paths.srcTs = paths.src + '**/*.ts'
paths.testTs = paths.test + '**/*.ts'
paths.srcCss = paths.src + '**/*.css'
paths.srcJs = paths.src + '**/*.js'
paths.testJs = paths.test + '**/*.js'
paths.srcJsMap = paths.src + '**/*.js.map'
paths.testJsMap = paths.test + '**/*.js.map'

paths.concatJsDest = paths.wwwroot + 'js/site.min.js'
paths.concatVendorJsDest = paths.wwwroot + 'js/vendor.min.js'
paths.concatCssDest = paths.wwwroot + 'css/site.min.css'
paths.concatVendorCssDest = paths.wwwroot + 'css/vendor.min.css'

var tsProject = ts.createProject('tsconfig.json')

gulp.task('clean', function (cb) {
  return gulp.src([
    paths.srcJs,
    paths.srcJsMap,
    paths.testJs,
    paths.testJsMap,
    paths.wwwroot], { read: false })
    .pipe(rimraf())
})

gulp.task('tslint', function (cb) {
  return gulp.src([paths.srcTs, paths.testTs])
    .pipe(tslint())
    .pipe(tslint.report('verbose'))
})

gulp.task('tscompile', ['tslint'], function (cb) {
  var tsResult = tsProject.src()
    .pipe(sourcemaps.init())
    .pipe(ts(tsProject))

  return tsResult.js
    .pipe(sourcemaps.write('.', {
      mapSources: function (sourcePath) {
        var truncatedSourcePath = sourcePath.substr(sourcePath.lastIndexOf('/') + 1)
        util.log('SourcePath within source map truncated to:', util.colors.cyan(truncatedSourcePath))
        return truncatedSourcePath
      }
    }))
    .pipe(gulp.dest('.'))
})

gulp.task('min:js', ['tscompile'], function () {
  gulp.src([paths.srcJs], { base: '.' })
    .pipe(sourcemaps.init({loadMaps: true}))
    .pipe(concat(paths.concatJsDest))
    .pipe(sourcemaps.write())
    .pipe(sourcemaps.init())
    // Note that compress: true and mangle: true gives you uglier code,
    // but makes debugging in the browser debugger more difficult.
    .pipe(uglify({compress: false, mangle: false}))
    .pipe(sourcemaps.write('.'))
    .pipe(gulp.dest('.'))
})

gulp.task('min:vendorjs', ['clean'], function () {
  gulp.src(bowerfiles('**/*.js'), { base: '.' })
    .pipe(sourcemaps.init())
    .pipe(concat(paths.concatVendorJsDest))
    .pipe(sourcemaps.write())
    .pipe(sourcemaps.init())
    // Note that compress: true and mangle: true gives you uglier code,
    // but makes debugging in the browser debugger more difficult.
    .pipe(uglify({compress: false, mangle: false}))
    .pipe(sourcemaps.write('.'))
    .pipe(gulp.dest('.'))
})

gulp.task('min:css', ['clean'], function () {
  gulp.src(paths.srcCss)
    .pipe(sourcemaps.init())
    .pipe(concat(paths.concatCssDest))
    .pipe(cssmin())
    .pipe(sourcemaps.write('.'))
    .pipe(gulp.dest('.'))
})

gulp.task('min:vendorcss', ['clean'], function () {
  gulp.src(bowerfiles('**/*.css',
    {overrides: {bootstrap: {main: ['./dist/css/bootstrap.css', './dist/fonts/*.*']}}}), { base: '.' })
    .pipe(sourcemaps.init())
    .pipe(concat(paths.concatVendorCssDest))
    .pipe(cssmin())
    .pipe(sourcemaps.write('.'))
    .pipe(gulp.dest('.'))
})

gulp.task('assets', ['clean'], function () {
  gulp.src([paths.src + '**/*', '!' + paths.srcTs, '!' + paths.srcJs, '!' + paths.srcJsMap])
    .pipe(gulp.dest(paths.wwwroot))
})

gulp.task('vendorassets', ['clean'], function () {
  gulp.src(bowerfiles(['**/*.eot', '**/*.svg', '**/*.ttf', '**/*.woff', '**/*.woff2'],
    {overrides: {bootstrap: {main: ['./dist/css/bootstrap.css', './dist/fonts/*.*']}}}), { base: '.' })
    .pipe(flatten({includeParents: -1}))
    .pipe(gulp.dest(paths.wwwroot))
})

gulp.task('min', ['min:js', 'min:vendorjs', 'min:css', 'min:vendorcss'])

gulp.task('build', ['min', 'assets', 'vendorassets'])

gulp.task('default', ['build'])
<commit_msg>Adjust stylesheet source map.<commit_after>'use strict'

var gulp = require('gulp')
var rimraf = require('gulp-rimraf')
var tslint = require('gulp-tslint')
var ts = require('gulp-typescript')
var sourcemaps = require('gulp-sourcemaps')
var bowerfiles = require('main-bower-files')
var concat = require('gulp-concat')
var cssmin = require('gulp-cssmin')
var uglify = require('gulp-uglify')
var flatten = require('gulp-flatten')
var util = require('gulp-util')

var paths = {
  wwwroot: './wwwroot/',
  src: './src/',
  test: './test/'
}

paths.srcTs = paths.src + '**/*.ts'
paths.testTs = paths.test + '**/*.ts'
paths.srcCss = paths.src + '**/*.css'
paths.srcJs = paths.src + '**/*.js'
paths.testJs = paths.test + '**/*.js'
paths.srcJsMap = paths.src + '**/*.js.map'
paths.testJsMap = paths.test + '**/*.js.map'

paths.concatJsDest = paths.wwwroot + 'js/site.min.js'
paths.concatVendorJsDest = paths.wwwroot + 'js/vendor.min.js'
paths.concatCssDest = paths.wwwroot + 'css/site.min.css'
paths.concatVendorCssDest = paths.wwwroot + 'css/vendor.min.css'

var tsProject = ts.createProject('tsconfig.json')
var bootstrapFiles = ['./dist/css/bootstrap.css', './dist/fonts/*.*']

gulp.task('clean', function (cb) {
  return gulp.src([
    paths.srcJs,
    paths.srcJsMap,
    paths.testJs,
    paths.testJsMap,
    paths.wwwroot], { read: false })
    .pipe(rimraf())
})

gulp.task('tslint', function (cb) {
  return gulp.src([paths.srcTs, paths.testTs])
    .pipe(tslint())
    .pipe(tslint.report('verbose'))
})

gulp.task('tscompile', ['tslint'], function (cb) {
  var tsResult = tsProject.src()
    .pipe(sourcemaps.init())
    .pipe(ts(tsProject))

  return tsResult.js
    .pipe(sourcemaps.write('.', {
      mapSources: function (sourcePath) {
        var truncatedSourcePath = sourcePath.substr(sourcePath.lastIndexOf('/') + 1)
        util.log('SourcePath within source map truncated to:', util.colors.cyan(truncatedSourcePath))
        return truncatedSourcePath
      }
    }))
    .pipe(gulp.dest('.'))
})

gulp.task('min:js', ['tscompile'], function () {
  gulp.src([paths.srcJs], { base: '.' })
    .pipe(sourcemaps.init({loadMaps: true}))
    .pipe(concat(paths.concatJsDest))
    .pipe(sourcemaps.write())
    .pipe(sourcemaps.init())
    // Note that compress: true and mangle: true gives you uglier code,
    // but makes debugging in the browser debugger more difficult.
    .pipe(uglify({compress: false, mangle: false}))
    .pipe(sourcemaps.write('.'))
    .pipe(gulp.dest('.'))
})

gulp.task('min:vendorjs', ['clean'], function () {
  gulp.src(bowerfiles('**/*.js'), { base: '.' })
    .pipe(sourcemaps.init())
    .pipe(concat(paths.concatVendorJsDest))
    .pipe(sourcemaps.write())
    .pipe(sourcemaps.init())
    // Note that compress: true and mangle: true gives you uglier code,
    // but makes debugging in the browser debugger more difficult.
    .pipe(uglify({compress: false, mangle: false}))
    .pipe(sourcemaps.write('.'))
    .pipe(gulp.dest('.'))
})

gulp.task('min:css', ['clean'], function () {
  gulp.src(paths.srcCss)
    .pipe(sourcemaps.init())
    .pipe(concat(paths.concatCssDest))
    .pipe(cssmin())
    .pipe(sourcemaps.write('.', {
      mapSources: function (sourcePath) {
        var extendedSourcePath = 'src/' + sourcePath
        util.log('SourcePath within source map extended to:', util.colors.cyan(extendedSourcePath))
        return extendedSourcePath
      }
    }))
    .pipe(gulp.dest('.'))
})

gulp.task('min:vendorcss', ['clean'], function () {
  gulp.src(bowerfiles('**/*.css',
    {overrides: {bootstrap: {main: bootstrapFiles}}}), { base: '.' })
    .pipe(sourcemaps.init())
    .pipe(concat(paths.concatVendorCssDest))
    .pipe(cssmin())
    .pipe(sourcemaps.write('.'))
    .pipe(gulp.dest('.'))
})

gulp.task('assets', ['clean'], function () {
  gulp.src([paths.src + '**/*', '!' + paths.srcTs, '!' + paths.srcJs, '!' + paths.srcJsMap])
    .pipe(gulp.dest(paths.wwwroot))
})

gulp.task('vendorassets', ['clean'], function () {
  gulp.src(bowerfiles(['**/*.eot', '**/*.svg', '**/*.ttf', '**/*.woff', '**/*.woff2'],
    {overrides: {bootstrap: {main: bootstrapFiles}}}), { base: '.' })
    .pipe(flatten({includeParents: -1}))
    .pipe(gulp.dest(paths.wwwroot))
})

gulp.task('min', ['min:js', 'min:vendorjs', 'min:css', 'min:vendorcss'])

gulp.task('build', ['min', 'assets', 'vendorassets'])

gulp.task('default', ['build'])
<|endoftext|>


<commit_before>

  /**
   *  Dialog to name the new visualization
   *  - It don't need any model or specific option
   */

  cdb.admin.NameVisualization = cdb.admin.BaseDialog.extend({

    _TEXTS: {
      _TITLE:       _t('Save your visualization'),
      _DESCRIPTION: _t('A visualization is a mix of layers, styles and sql. Your visualizations are now accesible from your dashboard.'),
      _BLANK_ERROR: _t('The visualization name can\'t be blank')
    },

    events: cdb.core.View.extendEvents({
      "keydown input":    "_checkEnter"
    }),

    initialize: function() {
      // Extend options
      _.extend(this.options, {
        title: this._TEXTS._TITLE,
        description: this._TEXTS._DESCRIPTION,
        template_name: 'common/views/dialog_base',
        clean_on_hide: true,
        ok_button_classes: "button green",
        ok_title: "Create visualization",
        modal_type: "creation",
        modal_class: "name_visualization",
        width: 450,
        error_messages: {
          blank: this._TEXTS._BLANK_ERROR
        }
      });
      this.constructor.__super__.initialize.apply(this);
    },

    render_content: function() {
      var $content = this.$content = $("<div>");
      this.template = cdb.templates.getTemplate('table/header/views/name_visualization_dialog');
      $content.append(this.template(this.options));

      // Focus in the input trick
      setTimeout(function() {
        $content.find("input").focus();
      },300);

      return $content;
    },

    _checkEnter: function(e) {
      var code = (e.keyCode ? e.keyCode : e.which);
      if(code == 13) {
        this.killEvent(e);
        this.ok();
      }
    },

    _isValidName: function() {
      var value = this.$content.find('input').val();
      return value.length > 0 && value != " ";
    },

    _showError: function() {
      this.$('div.info').addClass('active error');
    },

    _hideError: function() {
      this.$('div.info').removeClass('active');
    },

    ok: function(ev) {
      this.killEvent(ev);
      var value = this.$content.find('input').val();

      if (this._isValidName(value)) {
        this._hideError();
        this.options.onResponse && this.options.onResponse(value);
        this.hide();
      } else {
        this._showError();
      }
    }
  });
<commit_msg>name visualization dialog reviewed<commit_after>

  /**
   *  Dialog to name the new visualization
   *  - It don't need any model or specific option
   */

  cdb.admin.NameVisualization = cdb.admin.BaseDialog.extend({

    _TEXTS: {
      title:  _t('Save your visualization'),
      desc:   _t('A visualization is a mix of layers, styles and sql. Your \
              visualizations are now accesible from your dashboard.'),
      error:  _t('The visualization name can\'t be blank')
    },

    events: cdb.core.View.extendEvents({
      "keydown input":    "_checkEnter"
    }),

    initialize: function() {
      // Extend options
      _.extend(this.options, {
        title: this._TEXTS.title,
        description: this._TEXTS.desc,
        template_name: 'common/views/dialog_base',
        clean_on_hide: true,
        ok_button_classes: "button green",
        ok_title: "Create visualization",
        modal_type: "creation",
        modal_class: "name_visualization",
        width: 450,
        error_messages: {
          blank: this._TEXTS.error
        }
      });
      this.constructor.__super__.initialize.apply(this);
    },

    render_content: function() {
      var $content = this.$content = $("<div>");
      this.template = cdb.templates.getTemplate('table/header/views/name_visualization_dialog');
      $content.append(this.template(this.options));

      // Focus in the input trick
      setTimeout(function() {
        $content.find("input").focus();
      },300);

      return $content;
    },

    _checkEnter: function(e) {
      var code = (e.keyCode ? e.keyCode : e.which);
      if(code == 13) {
        this.killEvent(e);
        this.ok();
      }
    },

    _isValidName: function() {
      var value = this.$content.find('input').val();
      return value.length > 0 && value != " ";
    },

    _showError: function() {
      this.$('div.info').addClass('active error');
    },

    _hideError: function() {
      this.$('div.info').removeClass('active');
    },

    ok: function(ev) {
      this.killEvent(ev);
      var value = this.$content.find('input').val();

      if (this._isValidName(value)) {
        this._hideError();
        this.options.onResponse && this.options.onResponse(value);
        this.hide();
      } else {
        this._showError();
      }
    }
  });
<|endoftext|>