gaf-mobile
Version:
GAF mobile Web site
1,022 lines (879 loc) • 34.6 kB
JavaScript
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 +
'¤cy=' + _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 +
'¤cy=' + _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);
}
});
}
});
});
;
angular.