gaf-mobile
Version:
GAF mobile Web site
325 lines (292 loc) • 10.7 kB
JavaScript
module('gafMobileApp')
/**
* @ngdoc controller
* @name gafMobileApp.FreelancersDirectoryCtrl
* @description
* Controller for the freelancer directory
*/
.controller('FreelancersDirectoryCtrl', function($q, $scope, $location,
Users, Auth, Projects, Analytics, Pager, Experiments, loggedInUser,
categories) {
var _this = this;
var params = $location.search();
// Clean this up when ShowFreelancerDirTabs A/B test is done
_this.showDirectoryTabs = Experiments.activateTest('ShowFreelancerDirTabs');
// Clean this up when ReskinDirectory A/B test is done
this.reskinDirectory = Experiments.activateTest('ReskinDirectory');
// Clean up once OnlineOfflineStatus A/B Test is done
this.showOnlineOfflineStatus =
Experiments.activateTest('OnlineOfflineStatus', true);
/**
* @ngdoc property
* @name gafMobileApp.FreelancersDirectoryCtrl#queryString
* @propertyOf gafMobileApp.FreelancersDirectoryCtrl
* @description
* Stores the query string for the input search box
*/
_this.queryString = '';
/**
* @ngdoc property
* @name gafMobileApp.FreelancersDirectoryCtrl#freelancers
* @propertyOf gafMobileApp.FreelancersDirectoryCtrl
* @description
* Stores the current freelancer objects loaded on the page
*/
_this.freelancers = [];
/**
* @ngdoc property
* @name gafMobileApp.FreelancersDirectoryCtrl#isSearching
* @propertyOf gafMobileApp.FreelancersDirectoryCtrl
* @description
* Stores the current loading state of the search methods
*/
_this.isSearching = true;
/**
* @ngdoc property
* @name gafMobileApp.FreelancersDirectoryCtrl#tab
* @propertyOf gafMobileApp.FreelancersDirectoryCtrl
* @description
* Stores the current state of the page tabs
*/
$scope.tab = {
name: this.showDirectoryTabs ? ($location.hash() || 'categories') :
'recommended'
};
/**
* @ngdoc method
* @name gafMobileApp.FreelancersDirectoryCtrl#changeTab
* @param {String} tab Tab name to change hash into
* @methodOf gafMobileApp.FreelancersDirectoryCtrl
* @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);
// We use replace() here to update the current history record
// instead of creating a new one.
$location.replace();
}
};
// Default limit size of freelancers
var pageSize = 10;
var loadFreelancers = Pager(Users.search.bind(Users), pageSize, 1, 0);
/**
* @ngdoc method
* @name gafMobileApp.FreelancersDirectoryCtrl#hasMoreFreelancers
* @methodOf gafMobileApp.DepositCtrl
* @description
* Check whether more freelancers can be loaded from pager method
*/
_this.hasMoreFreelancers = function () {
return loadFreelancers.hasNext();
};
/**
* @ngdoc method
* @name gafMobileApp.FreelancersDirectoryCtrl#filterUserJobs
* @param {Array} users Array of user objects to filter jobs on
* depending on the contents of searchedJobs
* @param {Array} searchedJobs Array job ids used as basis of the filter
* @methodOf gafMobileApp.DepositCtrl
* @description
* Filter out the user jobs depending on the search params
* and remove all users without any skills after the filter
*/
_this.filterUserJobs = function(users, searchedJobs) {
return users.map(function(user) {
if (searchedJobs && searchedJobs.length > 0 && user.jobs.length > 0) {
user.jobs = user.jobs.filter(function(job) {
return searchedJobs.indexOf(job.id) !== -1;
});
}
// Leave only 5 jobs on the user as we only use jobs for view anyway
user.jobs = user.jobs.slice(0, 5);
return user;
}).filter(function(user) {
// TODO: Remove after https://phabricator.freelancer.com/T33374 is pushed
// for filtering users properly
return user.jobs.length > 0;
});
};
/**
* @ngdoc method
* @name gafMobileApp.FreelancersDirectoryCtrl#loadMoreFreelancers
* @param {Boolean} Determine if the loaded results should be reset or not
* @methodOf gafMobileApp.FreelancersDirectoryCtrl
* @description
* Load freelancers according to saved search parameters
*/
_this.loadMoreFreelancers = function(reset) {
this.isSearching = true;
if (reset) {
loadFreelancers.reset();
this.freelancers = [];
}
var params = this.savedSearch || {};
params = angular.extend(params, {
user_details: true,
user_avatar: true,
user_reputation: true,
user_jobs: true
});
if (!params.query ||
params.query && params.query.trim() === '') {
delete params.query;
this.queryString = '';
$location.search('q', null);
} else {
// Update query string so we can go back to this search
$location.search('q', params.query);
}
return loadFreelancers.nextPage(params.query, params)
.then(function(response) {
var newList = _this.filterUserJobs(response.getList(),
params['jobs[]']);
// TODO: Remove after https://phabricator.freelancer.com/T33374
// is pushed for filtering users properly. Setting to 5 is arbitrary
// and based on the current users we have on each category.
if (_this.freelancers.length < 5 && response.getSearchTotal() >= 5) {
_this.loadMoreFreelancers();
}
var searchedFreelancers = _this.freelancers.concat(newList);
_this.freelancers = searchedFreelancers.filter(function(freelancer) {
return freelancer.id !== Auth.getUserId();
});
}).catch(function() {
return _this.loadMoreFreelancers();
}).finally(function() {
_this.isSearching = false;
});
};
/**
* @ngdoc method
* @name gafMobileApp.FreelancersDirectoryCtrl#searchWithJobs
* @param {Object} category Category factory that contains the jobs
* @methodOf gafMobileApp.FreelancersDirectoryCtrl
* @description
* Setup load freelancers with search parameters according to Job IDs
*
* @return {Object} Promise to resolve to loading freelancers
*/
_this.searchWithJobs = function(category) {
var categoryId = parseInt(category);
var jobIds = categories.getJobsByCategoryId(categoryId).getList()
.map(function(job) {
return job.id;
// Reduce the number of parameters to at least 30 as loading
// all skills for some categories throttle the API endpoint
}).slice(0, 30);
if (jobIds.length) {
this.changeTab('recommended');
_this.savedSearch = { 'jobs[]': jobIds };
return _this.loadMoreFreelancers(true);
}
};
/**
* @ngdoc method
* @name gafMobileApp.FreelancersDirectoryCtrl#searchWithQuery
* @param {String} query Query string to search freelancers with
* @methodOf gafMobileApp.FreelancersDirectoryCtrl
* @description
* Setup load freelancers with search parameters according to query
* string
*
* @return {Object} Promise to resolve to loading freelancers
*/
_this.searchWithQuery = function(query) {
var queryString = query ? query.toString() : '';
if (queryString.length) {
_this.changeTab('recommended');
_this.savedSearch = { query: queryString };
return this.loadMoreFreelancers(true);
}
};
/**
* @ngdoc method
* @name gafMobileApp.FreelancersDirectoryCtrl#clearSearchField
* @methodOf gafMobileApp.FreelancersDirectoryCtrl
* @description
* Clear up the query string on the search input box and the saved query
* then load according to cleared query
*/
_this.clearSearchField = function () {
delete _this.queryString;
delete _this.savedSearch.query;
_this.loadMoreFreelancers(true);
};
// If we have '?q=something' in the querystring on page load, do the search
// This is to handle situations like the user clicks on a search result and
// then hits the BACK button.
var paramQueryString = params.q;
if (angular.isDefined(paramQueryString) && paramQueryString.length > 0) {
_this.queryString = paramQueryString;
_this.searchWithQuery(this.queryString);
} else {
_this.loadMoreFreelancers(true);
}
/**
* @ngdoc method
* @name gafMobileApp.FreelancersDirectoryCtrl#showHiremeModal
* @param {Object} user User object to input in hire me modal
* @methodOf gafMobileApp.FreelancersDirectoryCtrl
* @description
* Show hire me modal
*/
_this.showHiremeModal = function(user, currency, resetCurrentProject) {
if (!Auth.isAuthenticated()) {
$location.url('/signup?role=employer&return=' +
encodeURIComponent($location.url()));
return $q.reject();
} else {
// clear the info on the saved current project
if (resetCurrentProject) {
Projects.setCurrent();
}
_this.shouldShowHiremeModal = true;
_this.focusUser = user;
_this.userCurrency = currency || _this.userCurrency;
}
};
/**
* @ngdoc method
* @name gafMobileApp.FreelancersDirectoryCtrl#closeHiremeModalCallback
* @methodOf gafMobileApp.FreelancersDirectoryCtrl
* @description
* Callback for closing Hireme modal
*/
_this.closeHiremeModalCallback = function() {
_this.shouldShowHiremeModal = false;
_this.project = Projects.getCurrent();
if (_this.project.get().id) {
_this.shouldShowCreateMilestoneModal = true;
}
};
/**
* @ngdoc method
* @name gafMobileApp.FreelancersDirectoryCtrl#closeCreateMilestoneModal
* @methodOf gafMobileApp.FreelancersDirectoryCtrl
* @description
* Redirects the user to PVP when create milestone modal was closed
*/
_this.closeCreateMilestoneModalCallback = function() {
_this.shouldShowCreateMilestoneModal = false;
$location.url('/projects/project-' + _this.project.get().id);
};
// User currency for hireme projects
if (angular.isDefined(loggedInUser)) {
_this.userCurrency = loggedInUser.get().primary_currency;
}
// continue creating Hireme project after deposit success
// Unfortunately we currently cannot show the Hireme modal without a
// focusUser, so we'll just have to let the employer reopen and resubmit
// the Hireme modal form -- this happens after a successful Paypal deposit
if (params.showhireme && params.deposit === 'success') {
var currentProject = Projects.getCurrent().get();
if (currentProject.hireme && currentProject.user &&
currentProject.currency) {
_this.showHiremeModal(currentProject.user, currentProject.currency);
}
}
});
;
angular.