UNPKG

gaf-mobile

Version:

GAF mobile Web site

325 lines (292 loc) 10.7 kB
'use strict'; angular.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); } } });