gaf-mobile
Version:
GAF mobile Web site
260 lines (233 loc) • 7.2 kB
JavaScript
'use strict';
angular.module('gafMobileApp')
/**
* @ngdoc directive
* @name gafMobileApp.inbox
* @restrict E
* @description
* Component for showing user's inbox (list of threads)
*
* @example
* <pre>
* <inbox></inbox>
* </pre>
*/
.directive('inbox', function() {
return {
restrict: 'E',
templateUrl: 'components/inbox/inbox.html',
scope: {},
controller: 'InboxCtrl',
controllerAs: 'ctrl',
bindToController: true
};
});
/**
* @ngdoc controller
* @name gafMobileApp.InboxCtrl
* @description
* Controller for Inbox
*/
angular.module('gafMobileApp')
.controller('InboxCtrl', function($q, Threads, Contacts, Pager, Auth, Bids,
$scope, $location, Experiments) {
var _this = this;
/**
* @ngdoc property
* @name gafMobileApp.InboxCtrl#threads
* @propertyOf gafMobileApp.InboxCtrl
* @description
* List of user threads displayed on view
*/
_this.threads = [];
/**
* @ngdoc property
* @name gafMobileApp.InboxCtrl#contacts
* @propertyOf gafMobileApp.InboxCtrl
* @description
* List of user contacts displayed on view
*/
_this.contacts = [];
/**
* @ngdoc property
* @name gafMobileApp.InboxCtrl#state
* @propertyOf gafMobileApp.InboxCtrl
* @description
* Stores the overall view states of the tabs, can be: 'loading', 'empty',
* 'error', 'threadList', 'contactList'. Upon init, states are `loading`.
*/
_this.state = {
messages: 'loading',
contacts: 'loading'
};
/**
* @ngdoc property
* @name gafMobileApp.InboxCtrl#chatLoading
* @propertyOf gafMobileApp.InboxCtrl
* @description
* Stores which contacts are currently in loading state while fetching
* the details needed to redirect to the correct chat thread
*/
_this.chatLoading = {};
/**
* @ngdoc property
* @name gafMobileApp.InboxCtrl#chatError
* @propertyOf gafMobileApp.InboxCtrl
* @description
* Stores which contacts are unable to be contacted by the user
*/
_this.chatError = {};
/**
* @ngdoc property
* @name gafMobileApp.InboxCtrl#isLoadingMessages
* @propertyOf gafMobileApp.InboxCtrl
* @description
* Stores the loading state of the promise loading the threads from API
*/
var isLoadingMessages = false;
/**
* @ngdoc property
* @name gafMobileApp.InboxCtrl#pageSize
* @propertyOf gafMobileApp.InboxCtrl
* @description
* Stores the size/length of threads to be loaded, default is 15
*/
var pageSize = 15;
/**
* @ngdoc property
* @name gafMobileApp.InboxCtrl#loadThreads
* @propertyOf gafMobileApp.InboxCtrl
* @description
* The pager instance that stores Threads.getList method
*/
var loadThreads = Pager(Threads.getList.bind(Threads), pageSize, 0);
/**
* @ngdoc property
* @name gafMobileApp.InboxCtrl#tab
* @propertyOf gafMobileApp.InboxCtrl
* @description
* Stores the current state of the page tabs
*/
$scope.tab = {
name: $location.hash() || 'messages'
};
/**
* @ngdoc method
* @name gafMobileApp.InboxCtrl#changeTab
* @param {String} tab Tab name to change hash into
* @methodOf gafMobileApp.InboxCtrl
* @description
* Changes the hash and the focused tab on view
*/
_this.changeTab = function(tab) {
if ($scope.tab.name !== tab) {
$scope.tab.name = tab;
$location.hash(tab);
$location.replace();
}
};
// TO DO: Clean up once OnlineOffline AB Test is done
_this.showOnlineOfflineStatus =
Experiments.activateTest('OnlineOfflineStatus', true);
/**
* @ngdoc method
* @name gafMobileApp.InboxCtrl#loadMoreMessages
* @methodOf gafMobileApp.InboxCtrl
* @description
* Lazy loads threads into view using the Pager service
*/
_this.loadMoreMessages = function() {
if (!isLoadingMessages) {
isLoadingMessages = true;
return loadThreads.nextPage({
'last_message': true,
'folders[]': 'inbox',
'context_details': true,
'user_details': true
}).then(function(res) {
_this.hasMoreMessages = loadThreads.hasNext();
angular.forEach(res.getList(), function(m) {
var message = m.get();
var users = m.getUsers();
message.project = m.getProject().get();
message.user = message.thread.members[0] !== Auth.getUserId() ?
users[message.thread.members[0]] :
users[message.thread.members[1]];
message.markRead = m.markRead;
_this.threads.push(message);
});
// Change state according the threads.length
_this.state.messages = _this.threads.length > 0 ?
'threadList' : 'empty';
isLoadingMessages = false;
}).catch(function() {
_this.state.messages = 'error';
});
} else {
return $q.when();
}
};
/**
* @ngdoc method
* @name gafMobileApp.InboxCtrl#loadContacts
* @methodOf gafMobileApp.InboxCtrl
* @description
* Loads the contacts list of the user
*/
_this.loadContacts = function() {
return Contacts.getList()
.then(function(response) {
_this.contacts = response;
_this.state.contacts = 'contactsList';
})
.catch(function() {
_this.state.contacts = 'error';
});
};
/**
* @ngdoc method
* @name gafMobileApp.InboxCtrl#loadContacts
* @methodOf gafMobileApp.InboxCtrl
* @description
* Redirects user to the appropriate thread to chat with a contact
*/
_this.chatContact = function(contact) {
var contexts = contact.contexts || [];
var latestContext = contexts.sort(function(a, b) {
return b.id - a.id;
})[0];
if (latestContext && latestContext.type === 'project') {
var projectId = latestContext.id;
var userId = contact.user.id;
_this.chatLoading[userId] = true;
_this.chatError = {};
var params = {
'bidders[]': [Auth.getUserId(), userId]
};
Bids.getListForProject(projectId, params).then(function(response) {
var bid = response.getList()[0];
if (bid && bid.id) {
$location.url('/messages/thread' +
'?pid=' + projectId +
'&uid=' + userId +
'&bid=' + bid.id);
} else {
return $q.reject({ code: 'NOT_FOUND' });
}
}).catch(function(error) {
if (error.code === 'NOT_FOUND') {
_this.chatError[userId] = { bidNotFound: true };
} else {
_this.chatError[userId] = { internalError: true };
}
}).finally(function() {
_this.chatLoading[userId] = false;
});
} else {
$location.url('/messages/thread/?uid=' + contact.user.id);
}
};
// Load threads and contacts upon init
_this.loadMoreMessages();
_this.loadContacts();
});