UNPKG

gaf-mobile

Version:

GAF mobile Web site

1,022 lines (879 loc) 34.6 kB
'use strict'; angular.module('gafMobileApp') .factory('ViewProjectCtrlFactory', function(Projects) { return { getProject: function(projectId) { return Projects.getByIdWithUserDetails(projectId, { full_description: true, job_details: true, upgrade_details: true, location_details: true, selected_bids: true, nda_signature_details: true }, { reputation: true, employer_reputation: true, status: true, avatar: true }); } }; }) .controller('ViewProjectCtrl', function($scope, $q, $route, $location, $window, $anchorScroll, $filter, $document, Projects, Users, Bids, Auth, Preload, Budgets, Analytics, Pager, Milestones, MilestoneRequests, loggedInUser, Experiments) { var _this = this; _this.userInfo = loggedInUser; // Select the template based on the user's logged in state _this.isLoggedIn = Auth.isAuthenticated(); _this.milestones = {}; //Set default view state to list bids _this.viewState = 'bidsList'; _this.disableCreateMilestoneButton = false; _this.shouldShowCreateMilestoneModal = false; var milestoneStatuses = { cleared: 'released', frozen: 'in progress', requested_release: 'release requested', pending: 'requested' }; var params = $location.search(); // If a "loggedin" param is supplied, redirect people to the login page so // that they view the loggedin version if (angular.isDefined(params.sms) && !_this.isLoggedIn) { $location.url('/login?return=' + encodeURIComponent($location.url())); $location.replace(); } // Preloading of the next view var p = []; // Export project info & employer profile var project = $route.current.locals.projectBundle; var employer = project.getUser(); var isLoadingBids = false; _this.project = project.get(); _this.projectObj = project; _this.projectTimeLeft = project.getTimeLeft(); _this.employer = employer.get(); _this.isOwner = (employer.get().id === Auth.getUserId()); _this.user = Auth.getUserId(); // Cleanup when RearrangePVPBtns A/B test is done _this.rearrangePVPBtns = Experiments.activateTest('RearrangePVPBtns'); // List of AB tests made for the bid item directive // Clean up once NewFreelancerBidding A/B Test is done // Clean up once OnlineOfflineStatus A/B Test is done _this.bidItemAbTests = { 'showNewFreelancer': Experiments.activateTest('NewFreelancerBidding', true), 'showOnlineOfflineStatus': Experiments.activateTest('OnlineOfflineStatus', true) }; // Bids list _this.bids = []; _this.awardedBids = []; _this.pendingBids = []; _this.rejectedBids = []; angular.forEach(_this.project.nda_signatures, function(sign) { _this.ndaSigned = sign.user_id === _this.user; }); // Map marker (need a copy to prevent issues with binding) _this.marker = { location: { latitude: project.get().location.latitude, longitude: project.get().location.longitude } }; _this.isProjectOwner = function() { return Auth.isAuthenticated() && _this.project.owner_id === _this.user; }; _this.getUserBid = function(bids) { return $filter('filter')(bids, function(bid) { return _this.user === bid.get().bidder_id; })[0]; }; _this.canAwardProject = function() { return _this.bids.length > 0 && _this.project.status === 'active' || (_this.project.status === 'frozen' && _this.project.sub_status !== 'frozen_awarded'); }; _this.isProjectAwarded = function() { return _this.project.sub_status === 'closed_awarded'; }; _this.setDefaultTab = function() { if (_this.isProjectOwner()) { if (_this.isProjectAwarded()) { _this.defaultTab = 'management'; } else if (_this.canAwardProject()) { _this.defaultTab = 'bids'; } else { _this.defaultTab = 'info'; } } else { _this.defaultTab = 'info'; } var selectTab = $location.hash() === 'placebid' ? _this.defaultTab : $location.hash(); $scope.tab = { name: selectTab ? selectTab : _this.defaultTab }; }; _this.setDefaultTab(); // Disable all interactivity and UI elements for interactivity on local map _this.mapOptions = { disableDefaultUI: true, draggable: false, zoomControl: false, scrollwheel: false, disableDoubleClickZoom: true, keyboardShortcuts: false }; _this.modal = {}; _this.processing = { award: {} }; // Shows the request milestone modal when true, hides it otherwise _this.modal.requestMilestone = _this.isLoggedIn && $location.search().showRequestMilestone; _this.awardError = {}; _this.acceptError = {}; var isBidListed = function(checkBid) { return _this.bids.filter(function(bid) { return bid.get().bidder_id === checkBid.get().bidder_id; }).length !== 0; }; $scope.$on('bidList.update', function() { $scope.$apply(function() { var projectBids = project.get().bidList.getUnselectedBidArray(); if ( projectBids.length > 0 && !isBidListed(projectBids[projectBids.length - 1])) { _this.bids.push(projectBids[projectBids.length - 1]); _this.project.bid_stats.bid_count += 1; } }); }); // Pager instance that loads 20 bids - just to bump var loadMoreBids = Pager(Bids.getListForProjectWithUserDetails.bind(Bids), 20, 1); // Load the specified number of bids _this.loadBids = function(reset) { if (!isLoadingBids) { isLoadingBids = true; // Get bid details loadMoreBids.nextPage(project.get().id, { recommended_bid: _this.isOwner ? true : undefined, tag: 'websocketReloadMobileWeb' }, { avatar: true, reputation: true }) // Get avatar URLs .then(function(bids) { _this.bids = reset ? [] : _this.bids; project.set({ bidList: bids }); _this.bidListLoaded = true; _this.bids = _this.bids.concat(bids.getUnselectedBidArray()); _this.bids = _this.bids.filter(function(value) { return !value.get().retracted; }); _this.hasMoreBids = loadMoreBids.hasNext(); _this.setDefaultTab(); // Load recommended bid if (_this.isOwner && _this.awardedBids.length === 0 && _this.pendingBids.length === 0) { var recommended = _this.project.bidList.getRecommendedBid(); if (angular.isDefined(recommended)) { recommended.isRecommended = true; _this.bids.unshift(recommended); // Remove duplicate recommended bid var recommendedId = recommended.get().id; angular.forEach(_this.bids.slice(1), function(bid, i) { if (recommendedId === bid.get().id) { _this.bids.splice(i + 1, 1); } }); } } isLoadingBids = false; }); } else { return $q.when(); } }; $document.on('libnotify.connected', function() { loadMoreBids.reset(); _this.loadBids(true); Analytics.trackEvent('ViewProject', 'ReloadingBids', 'UserId', _this.user); }); // When awarding through chat, get bid details // first from API if (params.awardBid) { var awardBid = parseInt(params.awardBid); _this.viewState = 'loadingBids'; Bids.getListWithUserDetails( { 'bids[]': awardBid }, { avatar: true, reputation: true } ) .then(function(bid) { var bidToAward = bid.getById(awardBid); if (bidToAward) { _this.award(bidToAward); } else { _this.viewState = 'bidsList'; } }); } // Change tab and update the location. _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(); } else { // To go the top of the current view $anchorScroll(); } }; // Check skill requirements and direct user to skill selector if not met _this.checkSkillReqs = function() { var userJobIds = []; var projectJobIds = []; var noMatchingSkills = true; angular.forEach(loggedInUser.get().jobs, function(userJob) { userJobIds.push(userJob.id); }); angular.forEach(_this.project.jobs, function(job) { projectJobIds.push(job.id); if (userJobIds.indexOf(job.id) !== -1) { _this.modal.showBidForm = true; noMatchingSkills = false; } }); if (noMatchingSkills) { $location.url('/skill-select?jobs=' + projectJobIds.join(',') + '&return=/projects/' + _this.project.seo_url); } }; // On click on "Award Project", get the buyer fee and show the award modal _this.showAwardModal = function(bid) { _this.processing.award[bid.get().id] = true; _this.awardError = {}; return Bids.getBuyerFeeById(bid.get().id) .then(function(buyerFee) { Analytics.trackAction('bid', 'buyerFee', 'SUCCESS'); // If buyer fee > 0, show buyer fee if (buyerFee.get().buyer_project_fee.amount > 0) { _this.buyerFee = buyerFee; } // Show the confirm modal _this.processing.award[bid.get().id] = false; _this.selectedBid = bid; _this.viewState = 'confirmAward'; }).catch(function(error) { Analytics.trackAction('bid', 'buyerFee', error.code); _this.processing.award[bid.get().id] = false; _this.awardError.error = error; _this.awardError.errorCode = {}; _this.awardError.errorCode[error.code] = true; if (['BID_ALREADY_RETRACTED', 'BID_RETRACTED', 'NOT_FOUND', 'MAXIMUM_AWARDED_BIDDERS_REACHED', 'FREELANCER_ACCOUNT_UNDER_REVIEW' ].indexOf(error.code) === -1) { _this.awardError.unknownError = true; } }); }; // post similar project button is hidden when user: // + is logged in, // + is a freelancer and // + has no verified payment // and is otherwise shown. _this.hidePostSimilar = function() { return _this.isLoggedIn && !loggedInUser.get().status.payment_verified && loggedInUser.get().role === 'freelancer'; }; // Get Initial milestone request _this.getInitMilestoneReq = function(bidderId, amount) { return { id: 'initial', selected: true, fakeRequest: true, bidder_id: bidderId, description: 'Initial milestone request', amount: amount, reason: 'full_payment' }; }; // Award a specified bid _this.award = function(bid) { _this.processing.award[bid.get().id] = true; _this.awardError = {}; if ($location.search().awardBid) { // Let's remove the awardBid param after // processing so that if ever the user refreshes // the page we won't get an error $location.search('awardBid', null); } return Bids.award(bid.get().id) .then(function() { Analytics.trackAction('bid', 'award', 'SUCCESS'); _this.processing.award[bid.get().id] = false; // Add the award bid to the pendingBids list _this.pendingBids.push(bid); // Remove the awarded bid from the active bids list _this.bids = _this.bids.filter(function(value) { return value.get().bidder_id !== bid.get().bidder_id; }); _this.focusBid = bid; _this.getBuyerFee(); return MilestoneRequests.getMilestoneRequestsForBid(bid.get().id); }).then(function(requests) { _this.showPostAwardMilestoneModal = true; _this.newAwardedBid = bid; _this.milestoneRequests = requests.getPending(); // Return to the bid list _this.viewState = 'bidsList'; // If no requested milestones, add one for the full payment if (_this.milestoneRequests.length === 0) { _this.milestoneRequests = [_this.getInitMilestoneReq(bid.get().bidder_id, bid.get().amount)]; } // Add numbers for displaying the milestones angular.forEach(_this.milestoneRequests, function(milestone, i) { milestone.number = i + 1; milestone.selected = true; }); angular.forEach(_this.pendingBids, function(bid) { _this.milestones[bid.get().bidder_id] = { user: bid.getBidderDetails().get(), bid: bid.get(), milestones: [] }; }); }).catch(function(error) { _this.viewState = 'bidsList'; Analytics.trackAction('bid', 'award', error.code); _this.processing.award[bid.get().id] = false; _this.awardError.error = error; _this.awardError.errorCode = {}; _this.awardError.errorCode[error.code] = true; if (['BID_ALREADY_RETRACTED', 'BID_RETRACTED', 'NOT_FOUND', 'MAXIMUM_AWARDED_BIDDERS_REACHED', 'FREELANCER_ACCOUNT_UNDER_REVIEW' ].indexOf(error.code) === -1) { _this.awardError.unknownError = true; } }); }; // Cleanup the url parameters to avoid milestone being // created again when the page refreshes _this.cleanupURL = function() { $location.search({}); params = {}; }; _this.createMilestonesPostAward = function() { var createMilestones = []; var selectedMilestones = []; _this.selectedRequests = _this.milestoneRequests.filter(function(m) { return m.selected === true; }); _this.processingCreateMilestone = true; angular.forEach(_this.selectedRequests, function(request) { selectedMilestones.push(request.id); createMilestones.push(Milestones.create( _this.project.id, request.bidder_id, request.description, request.amount, request.reason || 'partial_payment', request.fakeRequest ? {} : { request_id: request.id } )); }); _this.cleanupURL(); return $q.all(createMilestones) .then(function(milestone) { _this.processingCreateMilestone = false; _this.showPostAwardMilestoneModal = false; _this.getMilestones(_this.project); _this.changeTab('management'); }).catch(function(err) { _this.processingCreateMilestone = false; _this.error = { milestoneCreateError: true }; if (err.code === 'INVALID_MILESTONE') { _this.error.invalidMilestone = true; } else if (err.code === 'UNAUTHORIZED_MILESTONE') { _this.error.unauthorizedMilestone = true; } else if (err.code === 'ACCOUNT_DETAILS_UPDATE_REQUIRED') { _this.error.accountDetailsUpdateRequired = true; } else if (err.code === 'PROJECT_NOT_ACCEPTED') { _this.error.projectNotAccepted = true; } else if (err.code === 'INVALID_MILESTONE_AMOUNT_FORMAT') { _this.error.invalidMilestoneFormat = true; } else if (err.code === 'INSUFFICIENT_MILESTONE_FUNDS') { $location.url('/deposit?type=milestones&subtype=create' + '&amount=' + _this.getTotalAmount() + '&action=create_milestone' + '&milestones=' + selectedMilestones.join() + '&project=' + _this.project.id + '&bidder=' + _this.selectedRequests[0].bidder_id + '&currency=' + _this.project.currency.id); } else { _this.error.internalError = true; } }); }; _this.getBuyerFee = function() { if (angular.isDefined(_this.focusBid)) { return Bids.getBuyerFeeById(_this.focusBid.get().id) .then(function(res) { _this.focusBid.buyerFee = res.get().buyer_project_fee.amount; }); } else { _this.focusBid = { buyerFee: 0 }; } }; _this.getTotalAmount = function() { var total = 0; angular.forEach(_this.milestoneRequests, function(milestone) { if (milestone.selected === true) { total += milestone.amount; } }); return total; }; // Repost project _this.repost = function(project) { _this.processing.repost = true; Projects.getCurrent().reset(); Projects.getCurrent().set(project); if (!Auth.isAuthenticated()) { // Clean up when RedirectToPPPTiles A/B Test is done var redirectToTiles = Experiments.activateTest('RedirectToPPPTiles'); if (redirectToTiles) { $location.url('/post-project'); } else { $location.url('/post-project/custom'); } } else { $location.url('/post-project/custom'); } }; // Accept project _this.acceptProject = function(bid) { _this.acceptError = {}; return bid.accept().then(function() { $window.location.reload(); }).catch(function(error) { _this.viewState = 'bidsList'; Analytics.trackAction('bid', 'accept', error.code); if (error.code === 'NDA_NOT_SIGNED') { _this.acceptError.ndaNotSigned = true; } else { _this.acceptError.unknownError = error.code; } }); }; // Reject project _this.rejectProject = function(bid) { return bid.reject().then(function() { $window.location.reload(); }).catch(function(error) { Analytics.trackAction('bid', 'reject', error.code); _this.acceptError.error = error; _this.acceptError.unknownError = true; }); }; _this.loadingManagement = true; _this.upgrade = function() { $location.path('/upgrade-project/' + _this.project.id); $location.hash('oldproject'); }; _this.totalMilestones = function() { var total = 0; angular.forEach(_this.milestones, function(freelancer) { total += freelancer.milestones.length; }); return total; }; // Get milestones _this.getMilestones = function(project) { var totalBids = _this.awardedBids.concat(_this.pendingBids); var freelancerBid = _this.getUserBid(totalBids); _this.disableCreateMilestoneButton = true; if (angular.isUndefined(freelancerBid) && !_this.isOwner) { _this.loadingManagement = false; _this.milestoneDenied = true; return $q.reject(); } var getMilestoneRequests = _this.isOwner ? MilestoneRequests.getMilestoneRequestsForProject(project.id) : MilestoneRequests.getMilestoneRequestsForBid(freelancerBid.get().id); var getMilestones = _this.isOwner ? Milestones.getForProject(project.id) : Milestones.getForBid(freelancerBid.get().id); return getMilestoneRequests .then(function(requests) { requests = requests.getPending(); return getMilestones .then(function(milestones) { _this.milestones = {}; milestones = milestones.get(); angular.forEach(totalBids, function(bid) { if (_this.isOwner || _this.user === bid.get().bidder_id) { _this.milestones[bid.get().bidder_id] = { user: bid.getBidderDetails().get(), bid: bid.get(), milestones: [] }; } }); angular.forEach(milestones, function(milestone) { if (angular.isDefined(milestoneStatuses[milestone.status])) { milestone.status = milestoneStatuses[milestone.status]; } if (_this.milestones[milestone.bidder_id]) { _this.milestones[milestone.bidder_id] .milestones.push(milestone); } }); angular.forEach(requests, function(request) { if (angular.isDefined(milestoneStatuses[request.status])) { request.status = milestoneStatuses[request.status]; request.other_reason = request.description; if (_this.milestones[request.bidder_id]) { _this.milestones[request.bidder_id] .milestones.push(request); } } }); }) .catch(function(err) { if (err.code === 'PERMISSION_DENIED') { _this.milestoneDenied = true; } }); }) .catch(function(err) { if (err.code === 'PERMISSION_DENIED') { _this.milestoneDenied = true; } }).finally(function() { _this.loadingManagement = false; _this.disableCreateMilestoneButton = false; }); }; _this.showCreateMilestoneModal = function(milestone) { _this.focusMilestone = milestone; _this.shouldShowCreateMilestoneModal = true; }; _this.showCreateRequestedMilestoneModal = function(milestone) { _this.focusMilestone = milestone; _this.modal.createRequestedMilestone = true; }; _this.showReleaseMilestoneModal = function(milestone) { _this.focusMilestone = milestone; _this.modal.releaseMilestone = true; }; _this.closeRequestMilestoneModal = function() { _this.error = {}; delete _this.requestMilestoneNewAmount; delete _this.requestMilestoneNewDescription; _this.modal.requestMilestone = false; }; // Only show bid button if authenticated if (Auth.isAuthenticated()) { // Show bid button _this.showBidButton = true; // Hide bid button if status is frozen or in progress if (_this.project.sub_status === 'frozen_awarded' || _this.project.frontend_project_status === 'work_in_progress') { _this.showBidButton = false; } // If authenticated user has placed a bid on the project, // do not display bid button angular.forEach($route.current.locals.userBids.get().bids, function(bid) { if (bid.project_id === _this.project.id && !bid.retracted) { _this.showBidButton = false; } }); } _this.showRevokeModal = function(bid) { _this.openRevokeModal = true; _this.focusBid = bid; }; _this.revokeAward = function() { return Bids.revoke(_this.focusBid.id) .then(function() { _this.openRevokeModal = false; angular.forEach(_this.pendingBids, function(bid, index) { if (bid.get().id === _this.focusBid.id) { _this.pendingBids.splice(index, 1); } }); loadMoreBids.reset(); _this.bids = []; _this.loadBids(); _this.getMilestones(_this.project); }); }; _this.milestoneCreation = {}; _this.closeReleaseMilestoneModal = function() { _this.error = {}; delete _this.milestoneNewAmount; delete _this.milestoneNewDescription; _this.modal.releaseMilestone = false; }; _this.closeCreateRequestedMilestoneModal = function() { _this.error = {}; delete _this.milestoneNewAmount; delete _this.milestoneNewDescription; _this.modal.createRequestedMilestone = false; }; _this.skipCreateMilestonePostAward = function() { _this.getMilestones(_this.project); _this.showPostAwardMilestoneModal = false; _this.changeTab('management'); }; _this.createRequestedMilestone = function() { _this.milestoneNewDescription = _this.focusMilestone.description; _this.milestoneNewAmount = _this.focusMilestone.amount; _this.focusMilestone.bid = { project_id: _this.focusMilestone.project_id, bidder_id: _this.focusMilestone.bidder_id }; var reason = 3; // milestone reason enumeration for 'OTHER' return Milestones.create( _this.focusMilestone.bid.project_id, _this.focusMilestone.bid.bidder_id, _this.milestoneNewDescription, _this.milestoneNewAmount, reason, { request_id: _this.focusMilestone.id }) .then(function() { _this.closeCreateRequestedMilestoneModal(); _this.getMilestones(_this.project); }) .catch(function(err) { _this.error = { milestoneCreateError: true }; if (err.code === 'INVALID_MILESTONE') { _this.error.invalidMilestone = true; } else if (err.code === 'UNAUTHORIZED_MILESTONE') { _this.error.unauthorizedMilestone = true; } else if (err.code === 'ACCOUNT_DETAILS_UPDATE_REQUIRED') { _this.error.accountDetailsUpdateRequired = true; } else if (err.code === 'PROJECT_NOT_ACCEPTED') { _this.error.projectNotAccepted = true; } else if (err.code === 'INVALID_MILESTONE_AMOUNT_FORMAT') { _this.error.invalidMilestoneFormat = true; } else if (err.code === 'INSUFFICIENT_MILESTONE_FUNDS') { // Redirect to deposits page var depositUrl = '/deposit?type=milestones&subtype=create' + '&amount=' + _this.milestoneNewAmount + '&action=create_milestone' + '&milestones=' + _this.focusMilestone.id + '&project=' + _this.focusMilestone.bid.project_id + '&bidder=' + _this.focusMilestone.bid.bidder_id + '&currency=' + _this.project.currency.id; $location.url(depositUrl); } else { _this.error.internalError = true; } }); }; _this.requestMilestone = function() { var bid = _this.milestones[_this.user].bid; return MilestoneRequests.createMilestoneRequest( bid.project_id,bid.id, _this.requestMilestoneNewAmount, _this.requestMilestoneNewDescription).then(function() { _this.getMilestones(_this.project); _this.closeRequestMilestoneModal(); }).catch(function(err) { _this.error = {}; _this.error.errorCode = {}; _this.error.errorCode[err.code] = true; if ([ 'INVALID_MILESTONE_REQUEST', 'UNAUTHORIZED_MILESTONE_REQUEST', 'UNAUTHORIZED_MILESTONE_VIEW', 'BID_DOES_NOT_BELONG_TO_PROJECT', 'EMPTY_MILESTONE_REQUEST_DESCRIPTION', 'MILESTONE_REQUEST_PENDING', 'NEGATIVE_MILESTONE_REQUEST_AMOUNT', 'MILESTONE_REQUEST_DESCRIPTION_INVALID_LENGTH' ].indexOf(err.code) === -1) { _this.error.requestMilestoneError = err.code; } }); }; _this.releaseMilestone = function() { return Milestones.release(_this.focusMilestone.transaction_id, _this.focusMilestone.amount) .then(function() { _this.closeReleaseMilestoneModal(); _this.getMilestones(_this.project); }).catch(function(err) { _this.error = { milestoneReleaseError: true }; if (err.code === 'INVALID_MILESTONE') { _this.error.invalidMilestone = true; } else if (err.code === 'UNAUTHORIZED_MILESTONE') { _this.error.unauthorizedMilestone = true; } else if (err.code === 'ACCOUNT_DETAILS_UPDATE_REQUIRED') { _this.error.accountDetailsUpdateRequired = true; } else if (err.code === 'PROJECT_NOT_ACCEPTED') { _this.error.projectNotAccepted = true; } else if (err.code === 'INVALID_MILESTONE_AMOUNT_FORMAT') { _this.error.invalidMilestoneFormat = true; } else if (err.code === 'INSUFFICIENT_MILESTONE_FUNDS') { _this.error.insufficientFund = true; } else { _this.error.internalError = true; } }); }; _this.shouldShowCreateMilestone = function() { return _this.isProjectOwner() && (_this.awardedBids.length > 0 || _this.pendingBids.length > 0) && _this.totalMilestones() === 0 && $scope.tab.name !== 'management'; }; _this.showPadding = function() { var freelancerBid = _this.getUserBid(_this.pendingBids); if (angular.isDefined(freelancerBid)) { _this.isPendingAwarded = true; _this.pendingBid = freelancerBid; } return ((!_this.isProjectOwner() && _this.showBidButton) || (_this.isProjectOwner() && _this.canAwardProject() && $scope.tab.name !== 'bids') || (_this.isPendingAwarded) || _this.shouldShowCreateMilestone() && _this.viewState !== 'loadingBids'); }; _this.isUserAwarded = function(userId, bids) { var isAwarded = false; angular.forEach(bids, function(bid) { if (bid.get().bidder_id === userId && bid.get().award_status === 'awarded') { isAwarded = true; } }); return isAwarded; }; _this.getAverageBidAmount = function() { if (_this.project.bid_stats.bid_count > 0) { return _this.project.bid_stats.bid_avg; } if (!angular.isDefined(_this.project.budget.minimum)) { return _this.project.budget.maximum; } if (!angular.isDefined(_this.project.budget.maximum)) { return _this.project.budget.minimum; } return (_this.project.budget.minimum + _this.project.budget.maximum) / 2; }; // Success callback for create milestone modal _this.successCallback = function() { _this.getMilestones(_this.project); }; // Close create milestone modal _this.closeCallback = function() { _this.shouldShowCreateMilestoneModal = false; }; // Only load the bid list in "logged in" view if (Auth.isAuthenticated()) { if ($location.hash() === 'placebid') { _this.checkSkillReqs(); if (_this.isNDA && !_this.ndaSigned) { $location.url('/nda/' + _this.project.id + '?return=/projects/' + 'project-' + _this.project.id + '#placebid'); } else { _this.modal.showBidForm = true; } } // Get the awarded freelancers. We don't do that using the bid query // because it will be far to big to load at once (200k for 200 bids) p.push(Bids.getListWithUserDetails({ 'projects[]': [project.get().id], 'award_statuses[]': ['awarded', 'pending', 'rejected'], user_reputation: true }, { avatar: true }).then(function(bids) { //// Check if there are awarded/pending bids and push to list _this.awardedBids = bids.getBidsByAwardStatus('awarded'); _this.pendingBids = bids.getBidsByAwardStatus('pending'); //// Rejected bids are pushed back into the active bids _this.rejectedBids = bids.getBidsByAwardStatus('rejected'); _this.isAwarded = _this.isUserAwarded(_this.user, bids.getBids()); // If url params contain `create_milestone` action and milestones, // create initial/defined ID milestones if (params.action === 'create_milestone' && params.milestones) { var milestones = params.milestones.split(','); _this.pendingBids.map(function(bid) { if (bid.get().bidder_id === parseInt(params.bidder)) { _this.newAwardedBid = bid; } }); if (milestones[0] === 'initial') { _this.milestoneRequests = [_this.getInitMilestoneReq(_this.newAwardedBid.get().bidder_id, _this.newAwardedBid.get().amount)]; _this.createMilestonesPostAward(); } else if (milestones[0] === '0') { _this.milestoneRequests = [{ id: 0, selected: true, fakeRequest: true, bidder_id: parseInt(params.bidder), description: params.descr, amount: parseInt(params.milestone_amount), reason: params.reason}]; _this.createMilestonesPostAward(); } else { p.push(MilestoneRequests .getMilestoneRequestsForProject(_this.project.id) .then(function(milestoneRequests) { var milestoneReqs = milestoneRequests.getList(); angular.forEach(milestoneReqs, function(request) { if (milestones.indexOf(request.id.toString()) !== -1) { request.selected = true; } }); _this.milestoneRequests = milestoneReqs; return _this.createMilestonesPostAward(); })); } } if (params.accept) { _this.viewState = 'loadingBids'; var acceptedBid = _this.pendingBids.filter(function(bid) { return bid.get().bidder_id === Auth.getUserId(); }); if (acceptedBid.length > 0) { _this.acceptProject(acceptedBid[0]); } else { _this.viewState = 'bidsList'; } } })); p.push(_this.loadBids()); } $q.all(p) .then(function() { // Preload the Post Project page as we'll likely need it soon Preload.routes('/post-project'); Budgets.getWithCurrencies({ project_type: 'fixed' }); if (_this.isLoggedIn) { return _this.getMilestones(_this.project) .then(function() { var freelancerInfo = _this.milestones[params.createMilestoneFor]; var shouldShowModal = params.createMilestoneFor && !params.showRequestMilestone && _this.isOwner; if (shouldShowModal && freelancerInfo) { _this.showCreateMilestoneModal(freelancerInfo); } }); } }); });