diff --git a/app/app/urls.py b/app/app/urls.py index d174fca6bc6..f7eb7357f77 100644 --- a/app/app/urls.py +++ b/app/app/urls.py @@ -81,6 +81,11 @@ path('issue/accept', dashboard.views.accept_bounty, name='process_funding'), path('issue/increase', dashboard.views.increase_bounty, name='increase_bounty'), path('issue/cancel', dashboard.views.cancel_bounty, name='kill_bounty'), + path( + 'issue/increase/changepayout/', + dashboard.views.request_change_payout_amount, + name='request_change_payout' + ), # Avatars path('avatar/', include('avatar.urls', namespace='avatar')), diff --git a/app/assets/v2/js/pages/bounty_details.js b/app/assets/v2/js/pages/bounty_details.js index c02baa28d61..8413959f476 100644 --- a/app/assets/v2/js/pages/bounty_details.js +++ b/app/assets/v2/js/pages/bounty_details.js @@ -586,7 +586,6 @@ var do_actions = function(result) { var kill_bounty_enabled = isBountyOwner(result); var submit_work_enabled = !isBountyOwner(result); var start_stop_work_enabled = !isBountyOwner(result); - var increase_bounty_enabled = isBountyOwner(result); var show_accept_submission = isBountyOwner(result) && !is_status_expired && !is_status_done; var show_suspend_auto_approval = document.isStaff && result['permission_type'] == 'approval'; var show_admin_methods = document.isStaff; @@ -662,9 +661,8 @@ var do_actions = function(result) { } if (show_increase_bounty) { - var enabled = increase_bounty_enabled; var _entry = { - enabled: enabled, + enabled: true, href: result['action_urls']['increase'], text: gettext('Add Contribution'), parent: 'right_actions', diff --git a/app/assets/v2/js/pages/increase_bounty.js b/app/assets/v2/js/pages/increase_bounty.js index 9c54b181cf1..e0b65e8f743 100644 --- a/app/assets/v2/js/pages/increase_bounty.js +++ b/app/assets/v2/js/pages/increase_bounty.js @@ -111,6 +111,10 @@ $(document).ready(function() { mixpanel.track('Submit New Bounty Success', {}); document.location.href = '/funding/details/?url=' + issueURL; }, 1000); + + if (!document.isFunder) { + $.get('/issue/increase/changepayout/' + amount + '/?pk=' + bountyId + '&network=' + document.web3network); + } } var bountyAmount = parseInt($('input[name=valueInToken]').val(), 10); @@ -123,9 +127,6 @@ $(document).ready(function() { if (bountyAmount == 0 || open == false) { errormsg = gettext('No active funded issue found at this address on ' + document.web3network + '. Are you sure this is an active funded issue?'); } - if (fromAddress != web3.eth.coinbase) { - errormsg = gettext('Only the address that submitted this funded issue may increase the payout.'); - } if (errormsg) { _alert({ message: errormsg }); @@ -133,7 +134,20 @@ $(document).ready(function() { return; } - function do_bounty() { + function do_bounty_as_funder_changingFulfillment() { + bounty.changeBountyFulfillmentAmount( + bountyId, + bountyAmount + amount, + { + from: account, + value: 0, + gasPrice: web3.toHex($('#gasPrice').val() + Math.pow(10, 9)) + }, + web3Callback + ); + } + + function do_bounty_as_funder_increasingPayout() { bounty.increasePayout( bountyId, bountyAmount + amount, @@ -147,7 +161,28 @@ $(document).ready(function() { ); } - do_bounty(); + function do_bounty_as_contributor() { + bounty.contribute( + bountyId, + amount, + { + from: account, + value: ethAmount, + gasPrice: web3.toHex($('#gasPrice').val() + Math.pow(10, 9)) + }, + web3Callback + ); + } + + if (document.isFunder) { + if (document.changePayoutAmount) { + do_bounty_as_funder_changingFulfillment(); + } else { + do_bounty_as_funder_increasingPayout(); + } + } else { + do_bounty_as_contributor(); + } }); }); diff --git a/app/dashboard/templates/increase_bounty.html b/app/dashboard/templates/increase_bounty.html index a24ee3ede8d..3f93a17873c 100644 --- a/app/dashboard/templates/increase_bounty.html +++ b/app/dashboard/templates/increase_bounty.html @@ -110,6 +110,11 @@

Increase Funding

+ + diff --git a/app/dashboard/views.py b/app/dashboard/views.py index b7a48797752..a8a62bb64e4 100644 --- a/app/dashboard/views.py +++ b/app/dashboard/views.py @@ -44,7 +44,9 @@ get_auth_url, get_github_emails, get_github_primary_email, get_github_user_data, is_github_token_valid, ) from marketing.mails import ( - admin_contact_funder, bounty_uninterested, start_work_approved, start_work_new_applicant, start_work_rejected, + admin_contact_funder, bounty_uninterested, change_payout_amount, start_work_approved, start_work_new_applicant, + start_work_rejected, + admin_contact_funder, bounty_uninterested, start_work_approved, start_work_new_applicant, start_work_rejected ) from marketing.models import Keyword from ratelimit.decorators import ratelimit @@ -665,13 +667,28 @@ def increase_bounty(request): """ bounty = handle_bounty_views(request) + user = request.user if request.user.is_authenticated else None + if user: + is_funder = bounty.is_funder(user.username.lower()) + else: + is_funder = False + params = get_context( ref_object=bounty, - user=request.user if request.user.is_authenticated else None, + user=user, confirm_time_minutes_target=confirm_time_minutes_target, active='increase_bounty', title=_('Increase Bounty'), ) + change_payout_amount = request.GET.get('change_payout_amount') + if change_payout_amount: + params['change_payout_amount'] = True if change_payout_amount == 'true' else False + else: + params['change_payout_amount'] = False + + params['is_funder'] = json.dumps(is_funder) + params['change_payout_amount'] = json.dumps(params['change_payout_amount']) + return TemplateResponse(request, 'increase_bounty.html', params) @@ -1123,6 +1140,16 @@ def sync_web3(request): return JsonResponse(result, status=result['status']) +def request_change_payout_amount(request, amount): + bounty = handle_bounty_views(request) + change_payout_amount(bounty, amount) + result = { + 'status': '200', + 'msg': 'email sent' + } + + return JsonResponse(result, status=result['status']) + # LEGAL def terms(request): diff --git a/app/marketing/mails.py b/app/marketing/mails.py index bce41e26d6d..b89119f670d 100644 --- a/app/marketing/mails.py +++ b/app/marketing/mails.py @@ -27,11 +27,17 @@ from python_http_client.exceptions import HTTPError, UnauthorizedError from retail.emails import ( render_admin_contact_funder, render_bounty_expire_warning, render_bounty_feedback, + render_bounty_startwork_expire_warning, render_bounty_unintersted, render_change_payout_amount, + render_faucet_rejected, render_faucet_request, render_gdpr_reconsent, render_gdpr_update, render_match_email, + render_new_bounty, render_new_bounty_acceptance, render_new_bounty_rejection, render_new_bounty_roundup, + render_new_work_submission, render_quarterly_stats, render_start_work_applicant_about_to_expire, + render_start_work_applicant_expired, render_start_work_approved, render_start_work_new_applicant, + render_start_work_rejected, render_tip_email, render_bounty_startwork_expire_warning, render_bounty_unintersted, render_faucet_rejected, render_faucet_request, render_gdpr_reconsent, render_gdpr_update, render_match_email, render_new_bounty, render_new_bounty_acceptance, render_new_bounty_rejection, render_new_bounty_roundup, render_new_work_submission, render_quarterly_stats, render_start_work_applicant_about_to_expire, render_start_work_applicant_expired, render_start_work_approved, - render_start_work_new_applicant, render_start_work_rejected, render_tip_email, + render_start_work_new_applicant, render_start_work_rejected, render_tip_email, render_change_payout_amount ) from sendgrid.helpers.mail import Content, Email, Mail, Personalization @@ -552,6 +558,18 @@ def start_work_applicant_expired(interest, bounty): translation.activate(cur_language) +def change_payout_amount(bounty, value): + from_email = settings.CONTACT_EMAIL + to_email = bounty.bounty_owner_email + cur_language = translation.get_language() + try: + setup_lang(to_email) + text, subject = render_change_payout_amount(bounty, value) + send_mail(from_email, to_email, subject, text) + finally: + translation.activate(cur_language) + + def setup_lang(to_email): """Activate the User's language preferences based on their email address. diff --git a/app/retail/emails.py b/app/retail/emails.py index 19ee672c6c9..996e3adae61 100644 --- a/app/retail/emails.py +++ b/app/retail/emails.py @@ -25,6 +25,7 @@ from django.shortcuts import redirect from django.template.loader import render_to_string from django.template.response import TemplateResponse +from django.urls import reverse from django.utils import timezone from django.utils.translation import gettext as _ @@ -588,6 +589,16 @@ def render_new_bounty_roundup(to_email): return response_html, response_txt, subject +def render_change_payout_amount(bounty, value): + subject = 'Change payout amount' + form_link = reverse('request_change_payout', kwargs={'value': value, 'pk': bounty.id, 'network': bounty.network}) + + response_text = """There is someone trying to increase the bounty on {value} on your issue, + can you change the payout amount of the bounty? The form to do it: {form_link}. You can + increase the payout amount in the value {value}.""" + + return response_text, subject + # DJANGO REQUESTS