Commit 2d8da571 authored by Vladimir Baranov's avatar Vladimir Baranov

Merge branch 'feature/messaging-improvements' into develop

parents 45019b81 03773d10
...@@ -2480,6 +2480,7 @@ table.dataTable thead .sorting:after { ...@@ -2480,6 +2480,7 @@ table.dataTable thead .sorting:after {
.chat-app .conversation-section .user-message .message-content { .chat-app .conversation-section .user-message .message-content {
font-family: 'robotomedium'; font-family: 'robotomedium';
position: relative;
} }
.chat-app .conversation-section .message-content-url { .chat-app .conversation-section .message-content-url {
...@@ -2576,14 +2577,14 @@ table.dataTable thead .sorting:after { ...@@ -2576,14 +2577,14 @@ table.dataTable thead .sorting:after {
opacity:1; opacity:1;
} }
.chat-app .conversation-section .user-message .edit-text-message input {
.chat-app .conversation-section .user-message .edit-text-message .editor {
width: 100%; width: 100%;
margin-bottom: 7px; margin-bottom: 7px;
margin-top: 7px; margin-top: 7px;
height: 30px;
border-radius: 3px; border-radius: 3px;
border: 1px solid #ccc; border: 1px solid #ccc;
padding-left: 7px; padding: 5px 10px;
outline: none; outline: none;
} }
......
angular.module("ulakbus.messaging") angular.module("ulakbus.messaging")
.directive('messaging', function (Generator, MessagingService, $log, $rootScope, MessagingPopup, Utils, $q) { .directive('messaging', function (Generator, MessagingService, $log, $rootScope, MessagingPopup, Utils, $q, $timeout) {
// get channel key // get channel key
function getKey (channel) { function getKey (channel) {
...@@ -45,6 +45,7 @@ angular.module("ulakbus.messaging") ...@@ -45,6 +45,7 @@ angular.module("ulakbus.messaging")
function reset(){ function reset(){
iScope.selectedChannel = null; iScope.selectedChannel = null;
iScope.allMessagesLoaded = false;
iScope.publicChannels = []; iScope.publicChannels = [];
iScope.notificationsChannel = []; iScope.notificationsChannel = [];
iScope.directChannels = []; iScope.directChannels = [];
...@@ -66,6 +67,10 @@ angular.module("ulakbus.messaging") ...@@ -66,6 +67,10 @@ angular.module("ulakbus.messaging")
}) })
} }
function getMessageElementByKey(key){
return $("#msg-"+key);
}
function updateLastMessage(message){ function updateLastMessage(message){
if (!message && iScope.selectedChannel && iScope.selectedChannel.messages.length > 0){ if (!message && iScope.selectedChannel && iScope.selectedChannel.messages.length > 0){
var last = iScope.selectedChannel.messages.length - 1; var last = iScope.selectedChannel.messages.length - 1;
...@@ -79,11 +84,26 @@ angular.module("ulakbus.messaging") ...@@ -79,11 +84,26 @@ angular.module("ulakbus.messaging")
if (channel.messages){ if (channel.messages){
channel.messages.push(message); channel.messages.push(message);
} }
}; }
updateLastMessage(message); updateLastMessage(message);
reportLastSeenMessage(); reportLastSeenMessage();
} }
function updateMessage(message){
// update current channel messages only
if (message.channel_key != getKey(iScope.selectedChannel)) return;
// update only visible messages
var storedMessage = Utils.findWhere(iScope.selectedChannel.messages, {key: message.key})
if (storedMessage){
angular.extend(storedMessage, message)
var msgElement = getMessageElementByKey(message.key);
// use manual update because of 'bind-once' for messages list
if (msgElement) {
msgElement.text(message.content);
}
}
}
function updateAndSelect(channelKey){ function updateAndSelect(channelKey){
channelKey = getKey(channelKey); channelKey = getKey(channelKey);
return iScope.updateChannelsList().then(function(){ return iScope.updateChannelsList().then(function(){
...@@ -186,7 +206,9 @@ angular.module("ulakbus.messaging") ...@@ -186,7 +206,9 @@ angular.module("ulakbus.messaging")
case '_zops_delete_channel': case '_zops_delete_channel':
iScope.deleteConfirmation('Kanalı silmek istediğinize emin misiniz?') iScope.deleteConfirmation('Kanalı silmek istediğinize emin misiniz?')
.then(function(){ .then(function(){
MessagingService.delete_channel(getKey(channel)); MessagingService.delete_channel(getKey(channel)).then(function(){
iScope.selectedChannel = null;
});
}); });
break; break;
...@@ -249,11 +271,16 @@ angular.module("ulakbus.messaging") ...@@ -249,11 +271,16 @@ angular.module("ulakbus.messaging")
} }
iScope.selectChannel = function(channel, silent){ iScope.selectChannel = function(channel, silent){
// enable channel history loading
iScope.allMessagesLoaded = false;
var channelKey = getKey(channel); var channelKey = getKey(channel);
selectChannel(channelKey, silent).then(function(result){ selectChannel(channelKey, silent).then(function(result){
iScope.selectedChannel = result; iScope.selectedChannel = result;
iScope.selectedChannel.read_only = channel.read_only; iScope.selectedChannel.read_only = channel.read_only;
iScope.selectedChannel.messages = result.last_messages; iScope.selectedChannel.messages = result.last_messages;
if (iScope.selectedChannel.messages.length < 15){
iScope.allMessagesLoaded = true;
}
updateLastMessage(channel.messages); updateLastMessage(channel.messages);
reportLastSeenMessage(); reportLastSeenMessage();
}); });
...@@ -276,6 +303,7 @@ angular.module("ulakbus.messaging") ...@@ -276,6 +303,7 @@ angular.module("ulakbus.messaging")
iScope.applyMessageAction = function(message, action){ iScope.applyMessageAction = function(message, action){
var actionView = action[1]; var actionView = action[1];
switch (actionView) { switch (actionView) {
case "_zops_favorite_message": case "_zops_favorite_message":
MessagingService.add_to_favorites(message.key) MessagingService.add_to_favorites(message.key)
.then(function(){ .then(function(){
...@@ -283,6 +311,7 @@ angular.module("ulakbus.messaging") ...@@ -283,6 +311,7 @@ angular.module("ulakbus.messaging")
message.actions = null; message.actions = null;
}); });
break; break;
case "_zops_flag_message": case "_zops_flag_message":
MessagingService.flag_message(message.key, true) MessagingService.flag_message(message.key, true)
.then(function(){ .then(function(){
...@@ -290,6 +319,7 @@ angular.module("ulakbus.messaging") ...@@ -290,6 +319,7 @@ angular.module("ulakbus.messaging")
message.actions = null; message.actions = null;
}); });
break; break;
case "_zops_unflag_message": case "_zops_unflag_message":
MessagingService.flag_message(message.key, false) MessagingService.flag_message(message.key, false)
.then(function(){ .then(function(){
...@@ -297,6 +327,7 @@ angular.module("ulakbus.messaging") ...@@ -297,6 +327,7 @@ angular.module("ulakbus.messaging")
message.actions = null; message.actions = null;
}); });
break; break;
case "_zops_delete_message": case "_zops_delete_message":
iScope.deleteConfirmation("Mesajı silmek istediğinize emin misiniz?") iScope.deleteConfirmation("Mesajı silmek istediğinize emin misiniz?")
.then(function(){ .then(function(){
...@@ -305,7 +336,31 @@ angular.module("ulakbus.messaging") ...@@ -305,7 +336,31 @@ angular.module("ulakbus.messaging")
}) })
}); });
break; break;
case "_zops_edit_message": case "_zops_edit_message":
// find message content container
var messageContainer = getMessageElementByKey(message.key);
MessagingPopup.show({
templateUrl: "components/messaging/templates/edit_message.html",
rootElement: messageContainer,
// activate inplace editor logic
inplaceEditor: true,
link: function (scope) {
scope.internalContent = scope.content;
scope.save = function(){
// delete message if new content is empty
if (!scope.internalContent){
return iScope.applyMessageAction(message, ['_', '_zops_delete_message']);
}
MessagingService.edit_message(message.key, scope.internalContent)
.then(function(){
// apply changes to element
scope.content = scope.internalContent;
scope.done();
});
};
}
});
break; break;
} }
}; };
...@@ -317,9 +372,31 @@ angular.module("ulakbus.messaging") ...@@ -317,9 +372,31 @@ angular.module("ulakbus.messaging")
}) })
}; };
iScope.loadMore = function(){
if (iScope.allMessagesLoaded) return;
if (iScope.selectedChannel.messages.length > 0){
var first = iScope.selectedChannel.messages[0];
return MessagingService.channel_history(getKey(iScope.selectedChannel), first.timestamp)
.then(function(result){
var messages = iScope.selectedChannel.messages;
if (result.messages.length == 0){
iScope.allMessagesLoaded = true;
return;
}
// prepend loaded messages to current channel messages list
messages.unshift.apply(messages, result.messages);
return true;
});
}
};
// listen to new messages and add them to selected channel if any // listen to new messages and add them to selected channel if any
$rootScope.$on("message", function(e, message){ $rootScope.$on("message", function(e, message){
appendMessage(iScope.selectedChannel, MessagingService.prepareMessage(message)); if (message.is_update){
updateMessage(message);
} else {
appendMessage(iScope.selectedChannel, MessagingService.prepareMessage(message));
}
}); });
// notifications in messaging window are processed as ordinary messages // notifications in messaging window are processed as ordinary messages
$rootScope.$on("notifications", function(e, notification){ $rootScope.$on("notifications", function(e, notification){
...@@ -355,12 +432,9 @@ angular.module("ulakbus.messaging") ...@@ -355,12 +432,9 @@ angular.module("ulakbus.messaging")
.directive("scrollDownWhenUpdate", function($timeout){ .directive("scrollDownWhenUpdate", function($timeout){
return { return {
scope: {
changesWatcher: "&scrollDownWhenUpdate"
},
link: function(iScope, iElem, iAttrs){ link: function(iScope, iElem, iAttrs){
var elem = $(iElem); var elem = $(iElem);
iScope.$watch(iScope.changesWatcher, function(value){ iAttrs.$observe("scrollDownWhenUpdate", function(value){
if (value){ if (value){
// update on next digest // update on next digest
$timeout(function(){ $timeout(function(){
...@@ -371,3 +445,101 @@ angular.module("ulakbus.messaging") ...@@ -371,3 +445,101 @@ angular.module("ulakbus.messaging")
} }
} }
}) })
.directive("loadMoreTop", function($compile, $timeout, $q) {
// centered loader
var loaderTpl = $compile('<div class="loader" style="float: none; margin: auto; margin-top: 10px;" ng-show="loading"></div>');
return {
scope: {
loadMoreCallback: "&loadMoreTop"
},
link: function(iScope, iElem, iAttrs){
var elem = $(iElem);
iElem.prepend(angular.element(loaderTpl(iScope)));
iScope.loading = false;
function onScroll(){
var scrollTop = elem.scrollTop();
if (scrollTop <= 0 && !iScope.loading){
if (iScope.loadMoreCallback){
// save last top element with id position
var id = elem.find("[id]").first().attr('id');
$timeout(function(){iScope.loading = true});
$q.when(iScope.loadMoreCallback())
.finally(function(loaded){
$timeout(function(){
iScope.loading = false;
// if new elements loaded
if (loaded){
// try to restore last scroll position;
var lastTopElem = elem.find("#"+id);
if (lastTopElem){
var top = lastTopElem.offset().top - elem.offset().top - 100;
elem.scrollTop(top);
}
}
});
})
}
}
}
elem.scroll(onScroll);
}
}
})
.directive("contenteditable", function(){
return {
require: "?ngModel",
scope: {},
link: function(iScope, iElem, iAttrs, ngModel) {
if(!ngModel) return;
ngModel.$render = function() {
iElem.text(ngModel.$viewValue || '');
};
// Listen for change events to enable binding
iElem.on('blur keyup change', function() {
iScope.$evalAsync(read);
});
function read() {
var html = iElem.text();
ngModel.$setViewValue(html);
}
iScope.$on('$destroy', function(){
iElem.off('blur keyup change');
})
}
}
})
.directive('autoFocus', function($timeout){
function placeCaretAtEnd(el) {
el.focus();
if (typeof window.getSelection != "undefined"
&& typeof document.createRange != "undefined") {
var range = document.createRange();
range.selectNodeContents(el);
range.collapse(false);
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
} else if (typeof document.body.createTextRange != "undefined") {
var textRange = document.body.createTextRange();
textRange.moveToElementText(el);
textRange.collapse(false);
textRange.select();
}
}
return {
link: function(iScope, iElem){
$timeout(function(){
placeCaretAtEnd(iElem[0]);
}, 500);
}
}
});
...@@ -19,6 +19,7 @@ angular.module('ulakbus.messaging', ['ui.bootstrap']) ...@@ -19,6 +19,7 @@ angular.module('ulakbus.messaging', ['ui.bootstrap'])
var msg = {}; var msg = {};
var notificationsChannelKey; var notificationsChannelKey;
var channelsMap = {}; var channelsMap = {};
var groupedChannels = {};
// channels loader promise // channels loader promise
var channelsLoader; var channelsLoader;
...@@ -70,6 +71,10 @@ angular.module('ulakbus.messaging', ['ui.bootstrap']) ...@@ -70,6 +71,10 @@ angular.module('ulakbus.messaging', ['ui.bootstrap'])
if (!messagingAppIsHidden && message.channel_key == currentChannelKey){ if (!messagingAppIsHidden && message.channel_key == currentChannelKey){
return; return;
} }
// skip message updates
if (message.is_update) return;
checkIfInitialized().then(function(){ checkIfInitialized().then(function(){
var channel = channelsMap[message.channel_key]; var channel = channelsMap[message.channel_key];
if (channel){ if (channel){
...@@ -128,6 +133,7 @@ angular.module('ulakbus.messaging', ['ui.bootstrap']) ...@@ -128,6 +133,7 @@ angular.module('ulakbus.messaging', ['ui.bootstrap'])
currentChannelKey = null; currentChannelKey = null;
notificationsChannelKey = null; notificationsChannelKey = null;
channelsMap = {}; channelsMap = {};
groupedChannels = {};
unread.messages.count = 0; unread.messages.count = 0;
unread.notifications.count = 0; unread.notifications.count = 0;
channelsLoader = false; channelsLoader = false;
...@@ -179,16 +185,22 @@ angular.module('ulakbus.messaging', ['ui.bootstrap']) ...@@ -179,16 +185,22 @@ angular.module('ulakbus.messaging', ['ui.bootstrap'])
}; };
channelsLoader = wsRequest(outgoing).then(function (data) { channelsLoader = wsRequest(outgoing).then(function (data) {
var grouped = Utils.groupBy(data.channels||[], "type"); var initialGroups = {};
initialGroups[msg.CHANNEL_TYPE.PUBLIC] = [];
initialGroups[msg.CHANNEL_TYPE.DIRECT] = [];
initialGroups[msg.CHANNEL_TYPE.NOTIFICATION] = [];
groupedChannels = Utils.groupBy(data.channels||[], "type", initialGroups);
// add all channels to channels map // add all channels to channels map
for (var i = 0; i < data.channels.length; i++){ for (var i = 0; i < data.channels.length; i++){
var channel = data.channels[i]; var channel = data.channels[i];
channelsMap[channel.key] = channel; channelsMap[channel.key] = channel;
} }
// save notifications channel key // save notifications channel key
notificationsChannelKey = grouped[msg.CHANNEL_TYPE.NOTIFICATION][0].key; notificationsChannelKey = groupedChannels[msg.CHANNEL_TYPE.NOTIFICATION][0].key;
return {grouped: grouped, channelsMap: channelsMap}; return {grouped: groupedChannels, channelsMap: channelsMap};
}); });
return channelsLoader; return channelsLoader;
...@@ -275,6 +287,9 @@ angular.module('ulakbus.messaging', ['ui.bootstrap']) ...@@ -275,6 +287,9 @@ angular.module('ulakbus.messaging', ['ui.bootstrap'])
}; };
return wsRequest(outgoing).then(function(result){ return wsRequest(outgoing).then(function(result){
$log.info("Channel ", channelKey, " deleted: ", result); $log.info("Channel ", channelKey, " deleted: ", result);
if (channelsMap[channelKey]){
channelsMap[channelKey].deleted = true;
}
return result; return result;
}) })
}; };
...@@ -328,6 +343,7 @@ angular.module('ulakbus.messaging', ['ui.bootstrap']) ...@@ -328,6 +343,7 @@ angular.module('ulakbus.messaging', ['ui.bootstrap'])
}; };
return wsRequest(outgoing).then(function(result){ return wsRequest(outgoing).then(function(result){
$log.info("Load channel ", channelKey, "history: ", result); $log.info("Load channel ", channelKey, "history: ", result);
prepareMessages(result.messages);
return result; return result;
}) })
}; };
...@@ -483,6 +499,25 @@ angular.module('ulakbus.messaging', ['ui.bootstrap']) ...@@ -483,6 +499,25 @@ angular.module('ulakbus.messaging', ['ui.bootstrap'])
increaseUnread(message, 'notifications'); increaseUnread(message, 'notifications');
}); });
$rootScope.$on("channel_change", function(e, action, channel){
checkIfInitialized().then(function(){
if (action == 'add'){
var group = groupedChannels[channel.type];
if (!channelsMap[channel.key]){
channelsMap[channel.key] = channel;
}
return group.push(channel);
}
if (action == 'status'){
var localChannel = channelsMap[channel.channel_key];
if (localChannel){
localChannel.is_online = channel.is_online;
}
}
})
});
// reset state on logout // reset state on logout
$rootScope.$watch("loggedInUser", function(value){ $rootScope.$watch("loggedInUser", function(value){
if (!value){ if (!value){
...@@ -490,6 +525,11 @@ angular.module('ulakbus.messaging', ['ui.bootstrap']) ...@@ -490,6 +525,11 @@ angular.module('ulakbus.messaging', ['ui.bootstrap'])
}; };
}); });
// initialize unread messages counter when user logged in
$rootScope.$on("user_ready", function(){
msg.get_unread_messages_count();
});
return msg; return msg;
}) })
...@@ -499,11 +539,12 @@ angular.module('ulakbus.messaging', ['ui.bootstrap']) ...@@ -499,11 +539,12 @@ angular.module('ulakbus.messaging', ['ui.bootstrap'])
var resultDeferred = $q.defer(); var resultDeferred = $q.defer();
var scope = config.scope || $rootScope.$new(true); var scope = config.scope || $rootScope.$new(true);
var rootElement = config.rootElement; var rootElement = config.rootElement;
var element = $compile(template)(scope); var originalContent, element;
if (config.link){
config.link(scope);
}
if (config.inplaceEditor){
originalContent = rootElement.text();
scope.content = originalContent;
}
scope.done = function(result){ scope.done = function(result){
resultDeferred.resolve.apply(this, arguments); resultDeferred.resolve.apply(this, arguments);
}; };
...@@ -511,14 +552,26 @@ angular.module('ulakbus.messaging', ['ui.bootstrap']) ...@@ -511,14 +552,26 @@ angular.module('ulakbus.messaging', ['ui.bootstrap'])
resultDeferred.reject.apply(this, arguments); resultDeferred.reject.apply(this, arguments);
}; };
if (config.link){
config.link(scope);
}
element = $compile(template)(scope);
rootElement.empty(); rootElement.empty();
rootElement.append(element); rootElement.append(element);
resultDeferred.promise._done = scope.done; resultDeferred.promise._done = scope.done;
resultDeferred.promise._cancel = scope.cancel; resultDeferred.promise._cancel = scope.cancel;
return resultDeferred.promise.finally(function(){ return resultDeferred.promise
rootElement.empty(); .finally(function(){
scope.$destroy(); // inplace editor can change scope.content and it will be applied to original rootElement
if (config.inplaceEditor){
rootElement.text(scope.content);
} else {
rootElement.empty();
}
scope.$destroy();
}); });
} }
...@@ -531,4 +584,4 @@ angular.module('ulakbus.messaging', ['ui.bootstrap']) ...@@ -531,4 +584,4 @@ angular.module('ulakbus.messaging', ['ui.bootstrap'])
return compile(config.template, config); return compile(config.template, config);
}; };
}); })
...@@ -31,10 +31,10 @@ ...@@ -31,10 +31,10 @@
</div> </div>
</div> </div>
<div class="conversation-body" ng-class="{readonly: selectedChannel.read_only}" scroll-down-when-update="lastMessage"> <div class="conversation-body" ng-class="{readonly: selectedChannel.read_only}" scroll-down-when-update="{{lastMessage}}" load-more-top="loadMore()">
<div class="conversation-body-inner"> <div class="conversation-body-inner">
<div class="beginning-of-conversation"> <div class="beginning-of-conversation" ng-show="allMessagesLoaded">
Burası yazışmanın başı! Burası yazışmanın başı!
</div> </div>
...@@ -49,7 +49,7 @@ ...@@ -49,7 +49,7 @@
</div> </div>
<div class="user-photo"> <div class="user-photo">
<img ng-src="{{msg.avatar_url}}" ng-show="msg.avatar_url"> <img ng-src="{{::msg.avatar_url}}" ng-if="msg.avatar_url">
</div> </div>
<div class="user-message"> <div class="user-message">
<div class="message-header clearfix"> <div class="message-header clearfix">
...@@ -57,8 +57,8 @@ ...@@ -57,8 +57,8 @@
<div class="message-time">{{::msg.moment|fromNow}}</div> <div class="message-time">{{::msg.moment|fromNow}}</div>
</div> </div>
<div class="message-content"> <div class="message-content">
{{::msg.content}} <div class="editable-message-content" id="msg-{{::msg.key}}">{{::msg.content}}</div>
<a class="message-content-url" href="{{::msg.url}}" ng-if="msg.url">{{msg.url}}</a> <a class="message-content-url" href="{{::msg.url}}" ng-click="hideApp()" ng-if="msg.url">{{::msg.url}}</a>
</div> </div>
</div> </div>
</div> </div>
......
<div class="edit-text-message">
<div class="editor" contenteditable="" auto-focus on-enter-pressed="save()" on-esc-pressed="cancel()" ng-model="internalContent"></div>
<button class="btn btn-default" ng-click="cancel()">Cancel</button>
<button class="btn btn-success" ng-click="save()">Save Changes</button>
</div>
...@@ -11,12 +11,12 @@ ...@@ -11,12 +11,12 @@
<ul class="channels"> <ul class="channels">
<li class="title">KANALLAR <span class="add-action glyphicon glyphicon-plus-sign" ng-click="createChannel()"></span></li> <li class="title">KANALLAR <span class="add-action glyphicon glyphicon-plus-sign" ng-click="createChannel()"></span></li>
<li ng-class="{'unread': ch.unread, 'public-ro-channel': ch.read_only, 'active': isChannelSelected(ch)}" title="{{ch.description}}" ng-repeat="ch in publicChannels" ng-click="selectChannel(ch)">{{ch.name}}</li> <li ng-class="{'unread': ch.unread, 'public-ro-channel': ch.read_only, 'active': isChannelSelected(ch)}" title="{{ch.description}}" ng-repeat="ch in publicChannels" ng-click="selectChannel(ch)" ng-hide="ch.deleted">{{ch.name}}</li>
</ul> </ul>
<ul class="direct-messages"> <ul class="direct-messages">
<li class="title">MESAJLAR <span class="add-action glyphicon glyphicon-plus-sign" ng-click="searchUser()"></span></li> <li class="title">MESAJLAR <span class="add-action glyphicon glyphicon-plus-sign" ng-click="searchUser()"></span></li>
<li ng-class="{'unread': userChannel.unread, 'active': isChannelSelected(userChannel), 'online': userChannel.is_online}" ng-repeat="userChannel in directChannels" ng-click="selectChannel(userChannel)">{{userChannel.name}}</li> <li ng-class="{'unread': userChannel.unread, 'active': isChannelSelected(userChannel), 'online': userChannel.is_online}" ng-repeat="userChannel in directChannels" ng-click="selectChannel(userChannel)" ng-hide="userChannel.deleted">{{userChannel.name}}</li>
</ul> </ul>
</div> </div>
......
...@@ -43,8 +43,6 @@ angular.module('ulakbus') ...@@ -43,8 +43,6 @@ angular.module('ulakbus')
scope: {}, scope: {},
controller: function ($scope, $log) { controller: function ($scope, $log) {
$scope.count = MessagingService.get_unread_counters(); $scope.count = MessagingService.get_unread_counters();
// initialize counters
MessagingService.get_unread_messages_count();
$scope.showMessagesWindow = function(type){ $scope.showMessagesWindow = function(type){
if (type == 'notifications'){ if (type == 'notifications'){
...@@ -686,6 +684,35 @@ angular.module('ulakbus') ...@@ -686,6 +684,35 @@ angular.module('ulakbus')
}); });
event.preventDefault(); event.preventDefault();
} }
});
scope.$on('$destroy', function(){
element.unbind('keydown keypress');
})
}
}
})
/**
* @memberof ulakbus
* @ngdoc directive
* @name onEscPressed
* @description Fire action when ESC pressed on element
*/
.directive("onEscPressed", function () {
return {
link: function (scope, element, attrs) {
element.bind("keydown keypress", function (event) {
if(event.which === 27 ) {
scope.$apply(function (){
scope.$eval(attrs.onEscPressed);
});
event.preventDefault();
}
});
scope.$on('$destroy', function(){
element.unbind('keydown keypress');
}) })
} }
} }
......
...@@ -102,6 +102,7 @@ angular.module('ulakbus') ...@@ -102,6 +102,7 @@ angular.module('ulakbus')
if ($location.path() === "/login") { if ($location.path() === "/login") {
$log.debug("show errors on login form"); $log.debug("show errors on login form");
} else { } else {
alert("Want relogin!");
return window.location.reload(); return window.location.reload();
} }
}, },
...@@ -129,4 +130,4 @@ angular.module('ulakbus') ...@@ -129,4 +130,4 @@ angular.module('ulakbus')
}; };
return error_service; return error_service;
}); });
\ No newline at end of file
...@@ -162,6 +162,16 @@ angular.module('ulakbus') ...@@ -162,6 +162,16 @@ angular.module('ulakbus')
task_list: function () { task_list: function () {
// broadcast task list to task_list directive in dashboard_widget_directives.js // broadcast task list to task_list directive in dashboard_widget_directives.js
$rootScope.$broadcast('task_list', msg_data["task_list"]); $rootScope.$broadcast('task_list', msg_data["task_list"]);
},
channel_subscription: function(){
$timeout(function(){
$rootScope.$broadcast('channel_change', 'add', msg_data);
})
},
user_status: function(){
$timeout(function(){
$rootScope.$broadcast('channel_change', 'status', msg_data);
})
} }
}; };
// do_action is the dispatcher function for incoming events // do_action is the dispatcher function for incoming events
......
...@@ -14,7 +14,7 @@ angular.module("ulakbus") ...@@ -14,7 +14,7 @@ angular.module("ulakbus")
// check if obj1 has properties values equal to corresponding properties in obj2 // check if obj1 has properties values equal to corresponding properties in obj2
function hasEqualProperties(obj1, obj2){ function hasEqualProperties(obj1, obj2){
var result = true var result = true;
for (var prop in obj2){ for (var prop in obj2){
if(obj2.hasOwnProperty(prop)){ if(obj2.hasOwnProperty(prop)){
result = result && obj2[prop] == obj1[prop]; result = result && obj2[prop] == obj1[prop];
...@@ -26,14 +26,16 @@ angular.module("ulakbus") ...@@ -26,14 +26,16 @@ angular.module("ulakbus")
/** /**
* @param list {Array} Array of objects to group * @param list {Array} Array of objects to group
* @param propName {String} property name to group array by * @param propName {String} property name to group array by
* @param initialObject {Object} initial object for groups setup
* @returns {Object} * @returns {Object}
*/ */
this.groupBy = function (list, propName) { this.groupBy = function (list, propName, initialObject) {
if (!initialObject) initialObject = {};
return list.reduce(function(acc, item) { return list.reduce(function(acc, item) {
(acc[item[propName]] = acc[item[propName]] || []).push(item); (acc[item[propName]] = acc[item[propName]] || []).push(item);
return acc; return acc;
}, {}); }, initialObject);
}; };
/** /**
...@@ -48,5 +50,18 @@ angular.module("ulakbus") ...@@ -48,5 +50,18 @@ angular.module("ulakbus")
return list[i]; return list[i];
} }
} }
};
/**
* @param list {Array} Array of objects to group
* @param condition {Object} conditions object. If object in collection has same values as in conditions object found object will be returned
* @returns {Object}|undefined
*/
this.findWhere = function(list, condition){
for (var i = 0; i < list.length; i++){
if (hasEqualProperties(list[i], condition)){
return list[i];
}
}
} }
}); });
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment