-
#${json.profile.position}
-
Gitcoin Contributor
+
+
+
+
+ ${data.stats.position == 0 ? '-' : '#' + data.stats.position}
+
+
contributor
-
-
-
${json.statistics.work_completed}
-
Bounties Completed
-
-
-
${json.statistics.work_in_progress}
-
Bounties In Progress
-
-
-
${json.statistics.work_abandoned}
-
Bounties Abandoned
-
-
-
${json.statistics.work_removed}
-
Bounties Removed
-
+
+
+ ${data.stats.success_rate ? Math.round(data.stats.success_rate * 100) : 0} %
+
+
success rate
+
+
+
+ ${data.stats.earnings ? Number(data.stats.earnings).toFixed(4) : 0} ETH
+
+
+ collected from
+ ${data.stats.completed_bounties} bounties
+
-
-
`;
};
-const openContributorPopOver = (contributor, element) => {
- let contributorURL = `/api/v0.1/profile/${contributor}`;
+function openContributorPopOver(contributor, element) {
+ const keywords = document.result.keywords || '';
+ const contributorURL = `/api/v0.1/profile/${contributor}?keywords=${keywords}`;
if (popoverData.filter(index => index[contributor]).length === 0) {
fetch(contributorURL, { method: 'GET' })
@@ -65,8 +93,12 @@ const openContributorPopOver = (contributor, element) => {
element.popover({
placement: 'auto',
trigger: 'hover',
- template:
- '
',
+ template: `
+
`,
content: renderPopOverData(response),
html: true
});
@@ -80,8 +112,12 @@ const openContributorPopOver = (contributor, element) => {
element.popover({
placement: 'auto',
trigger: 'hover',
- template:
- '
',
+ template: `
+
`,
content: renderPopOverData(
popoverData.filter(item => item[contributor])[0][contributor]
),
@@ -89,35 +125,4 @@ const openContributorPopOver = (contributor, element) => {
});
$(element).popover('show');
}
-};
-
-const currentStatus = status => {
- const activity_names = {
- new_bounty: gettext('New Bounty'),
- start_work: gettext('Work Started'),
- stop_work: gettext('Work Stopped'),
- work_submitted: gettext('Work Submitted'),
- work_done: gettext('Work Done'),
- worker_approved: gettext('Worker Approved'),
- worker_rejected: gettext('Worker Rejected'),
- worker_applied: gettext('Worker Applied'),
- increased_bounty: gettext('Increased Funding'),
- killed_bounty: gettext('Canceled Bounty'),
- new_crowdfund: gettext('New Crowdfund Contribution'),
- new_tip: gettext('New Tip'),
- receive_tip: gettext('Tip Received'),
- bounty_abandonment_escalation_to_mods: gettext(
- 'Escalated for Abandonment of Bounty'
- ),
- bounty_abandonment_warning: gettext('Warned for Abandonment of Bounty'),
- bounty_removed_slashed_by_staff: gettext(
- 'Dinged and Removed from Bounty by Staff'
- ),
- bounty_removed_by_staff: gettext('Removed from Bounty by Staff'),
- bounty_removed_by_funder: gettext('Removed from Bounty by Funder'),
- bounty_changed: gettext('Bounty Details Changed'),
- extend_expiration: gettext('Extended Bounty Expiration')
- };
-
- return activity_names[status] || 'Unknown activity ';
-};
+}
diff --git a/app/dashboard/models.py b/app/dashboard/models.py
index 130d72b2834..d21ad5d019b 100644
--- a/app/dashboard/models.py
+++ b/app/dashboard/models.py
@@ -2364,8 +2364,28 @@ def is_staff(self):
"""
return self.user.is_staff if self.user else False
+
+ @property
+ def completed_bounties(self):
+ """Returns bounties completed by user
+
+ Returns:
+ number: number of bounties completed
+
+ """
+ network = self.get_network()
+ return self.bounties.filter(
+ idx_status__in=['done'], network=network).count()
+
+
@property
def success_rate(self):
+ """Returns success rate of user on the platform
+
+ Returns:
+ number: sucess rate of user
+
+ """
network = self.get_network()
num_completed_bounties = self.bounties.filter(
idx_status__in=['done'], network=network).count()
diff --git a/app/dashboard/templates/bounty/details.html b/app/dashboard/templates/bounty/details.html
index 297ffead966..a967ba008ca 100644
--- a/app/dashboard/templates/bounty/details.html
+++ b/app/dashboard/templates/bounty/details.html
@@ -15,6 +15,7 @@
+
@@ -488,6 +489,9 @@
{{ noscript.keywords }}
$("body").on("mouseover", "[data-username]", function(e) {
openContributorPopOver($(this).data("username"), $(this));
});
+ $("body").on("mouseout", "[data-username]", function(e) {
+ $(this).popover('dispose');
+ });
diff --git a/app/dashboard/views.py b/app/dashboard/views.py
index ba79f9d0090..e496c7a9483 100644
--- a/app/dashboard/views.py
+++ b/app/dashboard/views.py
@@ -34,7 +34,7 @@
from django.core import serializers
from django.core.exceptions import PermissionDenied
from django.core.paginator import Paginator
-from django.db.models import Avg, Count, Q
+from django.db.models import Avg, Count, Prefetch, Q
from django.http import Http404, HttpResponse, JsonResponse
from django.shortcuts import redirect
from django.template import loader
@@ -1804,29 +1804,67 @@ def profile_details(request, handle):
"""
try:
profile = profile_helper(handle, True)
- activity = Activity.objects.filter(profile=profile).order_by('-created_on').first()
- count_work_completed = Activity.objects.filter(profile=profile, activity_type='work_done').count()
- count_work_in_progress = Activity.objects.filter(profile=profile, activity_type='start_work').count()
- count_work_abandoned = Activity.objects.filter(profile=profile, activity_type='stop_work').count()
- count_work_removed = Activity.objects.filter(profile=profile, activity_type='bounty_removed_by_funder').count()
except (ProfileNotFoundException, ProfileHiddenException):
raise Http404
+ if not settings.DEBUG:
+ network = 'mainnet'
+ else:
+ network = 'rinkeby'
+
+ keywords = request.GET.get('keywords', '')
+
+ bounties = Bounty.objects.current().prefetch_related(
+ 'fulfillments',
+ 'interested',
+ 'interested__profile',
+ 'feedbacks'
+ ).filter(
+ interested__profile=profile,
+ network=network,
+ ).filter(
+ interested__status='okay'
+ ).filter(
+ interested__pending=False
+ ).filter(
+ idx_status='done'
+ ).filter(
+ feedbacks__receiver_profile=profile
+ ).filter(
+ Q(metadata__issueKeywords__icontains=keywords) |
+ Q(title__icontains=keywords) |
+ Q(issue_description__icontains=keywords)
+ ).distinct('pk')[:3]
+
+ _bounties = []
+ _orgs = []
+ if bounties :
+ for bounty in bounties:
+
+ _bounty = {
+ 'title': bounty.title,
+ 'id': bounty.id,
+ 'org': bounty.org_name,
+ 'rating': [feedback.rating for feedback in bounty.feedbacks.all().distinct('bounty_id')],
+ }
+ _org = bounty.org_name
+ _orgs.append(_org)
+ _bounties.append(_bounty)
+
response = {
- 'profile': ProfileSerializer(profile).data,
- 'success_rate': profile.success_rate,
- 'recent_activity': {
- 'activity_metadata': activity.metadata,
- 'activity_type': activity.activity_type,
- 'created': activity.created
- },
- 'statistics': {
- 'work_completed': count_work_completed,
- 'work_in_progress': count_work_in_progress,
- 'work_abandoned': count_work_abandoned,
- 'work_removed': count_work_removed
+ 'avatar': profile.avatar_url,
+ 'handle': profile.handle,
+ 'contributed_to': _orgs,
+ 'keywords': keywords,
+ 'related_bounties' : _bounties,
+ 'stats': {
+ 'position': profile.get_contributor_leaderboard_index(),
+ 'completed_bounties': profile.completed_bounties,
+ 'success_rate': profile.success_rate,
+ 'earnings': profile.get_eth_sum()
}
}
+
return JsonResponse(response, safe=False)