diff --git a/app/assets/v2/css/bounty.css b/app/assets/v2/css/bounty.css index 0b0a4243b21..ddc329feb07 100644 --- a/app/assets/v2/css/bounty.css +++ b/app/assets/v2/css/bounty.css @@ -58,6 +58,33 @@ body { padding-top: 3em; } +.invite-user .avatar { + width: 5.5rem; + height: 5.5rem; +} + +.quote-container { + width: 55%; + z-index: 2; +} + +.quote-container img { + top: 3rem; + left: -2rem; + position: relative; +} + +.quote-container .quote_text { + font-size: 1.1rem; + color: #4A4A4A; +} + +.quote-container .quote_author { + color: #4A4A4A; + font-size: 1rem; + font-style: italic; +} + .bounty_details .avatar { width: 50px; height: 50px; @@ -65,6 +92,7 @@ body { border-radius: 50px; margin-top: 0px; } + .bounty_details .avatar.Azure-Samples { border-radius: 0px; } @@ -478,7 +506,10 @@ a.btn { font-weight: 600; } -.username, .contributor-position, .in-progress, .current_status { +.contributor-position, +.username, +.current_status, +.in-progress { color: #0D0764; } @@ -487,11 +518,13 @@ a.btn { font-size: 10px; line-height: 11px; } + .completed-bounties { color: #05B66A; } -.abandoned-bounties, .removed-bounties { +.abandoned-bounties, +.removed-bounties { color: #F5A623; } @@ -682,7 +715,6 @@ a.btn { width: auto; } - .btn-interested, .btn-extend, .btn-cancel { @@ -727,28 +759,6 @@ a.btn { text-align: center; } -.bounty_details .quote-container, -.grant_waiting .quote-container { - width: 55%; - margin: 4rem auto; - font-weight: 700; - z-index: 2; -} - -.bounty_details .quote_text, -.grant_waiting .quote_text { - margin-top: 50px; - font-size: 1.1rem; - color: #4A4A4A; -} - -.bounty_details .quote_author, -.grant_waiting .quote_author { - color: #4A4A4A; - margin: 1rem auto; - font-size: 1rem; -} - .ethereum-issue { width:100%; color: #ffffff; diff --git a/app/assets/v2/js/pages/bounty_details.js b/app/assets/v2/js/pages/bounty_details.js index 29fd9881746..c0cfddcd0dd 100644 --- a/app/assets/v2/js/pages/bounty_details.js +++ b/app/assets/v2/js/pages/bounty_details.js @@ -501,9 +501,9 @@ var showWarningMessage = function(txid) { $('.left-rails').hide(); $('#bounty_details').hide(); - $('#bounty_detail').hide(); waitingStateActive(); + show_invite_users(); }; // refresh page if metamask changes @@ -1564,6 +1564,67 @@ const is_bounty_expired = function(bounty) { return now.getTime() >= expires_date.getTime(); }; +/** + * Checks sessionStorage to toggle to show the quote + * container vs showing the list of fulfilled users to be + * invite. + */ +const show_invite_users = () => { + + if (sessionStorage['fulfillers']) { + const users = sessionStorage['fulfillers'].split(','); + + if (users.length == 1) { + + let user = users[0]; + const title = `Work with ${user} again on your next bounty ?`; + const invite = ` +
+ +

+ + Yes, invite to one of my bounties + +

+
`; + + $('#invite-header').html(title); + $('#invite-users').html(invite); + } else { + + let invites = []; + const title = 'Work with these contributors again on your next bounty?'; + + users.forEach(user => { + const invite = ` +
+ +

+ + ${user} + +

+ + Invite + +
`; + + invites.push(invite); + }); + + $('#invite-users').addClass('d-flex justify-content-center'); + $('#invite-header').html(title); + $('#invite-users').html(invites); + } + delete sessionStorage['fulfillers']; + $('.invite-user-container').removeClass('hidden'); + $('.quote-container').addClass('hidden'); + } else { + $('.invite-user-container').addClass('hidden'); + $('.quote-container').removeClass('hidden'); + } +}; + var main = function() { const moderatorAndAdminActions = $('#moderator-admin-actions'); const scrollHeight = 150; diff --git a/app/assets/v2/js/pages/bulk_payout.js b/app/assets/v2/js/pages/bulk_payout.js index d751c06b55c..5178a5611e1 100644 --- a/app/assets/v2/js/pages/bulk_payout.js +++ b/app/assets/v2/js/pages/bulk_payout.js @@ -134,6 +134,7 @@ $(document).ready(function($) { $('#acceptBounty').on('click', function(e) { e.preventDefault(); + getFulfillers(); update_registry(); if (!$('#terms').is(':checked')) { @@ -346,6 +347,19 @@ var update_registry = function(coinbase) { document.transactions = transactions; }; +/** + * stores fulfillers in sessionStorage on + * triggering advanced payout + */ +const getFulfillers = () => { + let fulfillers = []; + const users = $('.new-user option'); + + for (let i = 0; i < users.length; i++) { + fulfillers.push($('.new-user option')[i].innerHTML); + } + sessionStorage['fulfillers'] = fulfillers; +}; $(document).on('click', '.user-fulfiller', function(event) { let elem = $('.username-search'); diff --git a/app/assets/v2/js/shared.js b/app/assets/v2/js/shared.js index 6a860d36fee..feb76c316b4 100644 --- a/app/assets/v2/js/shared.js +++ b/app/assets/v2/js/shared.js @@ -281,20 +281,18 @@ var waitingStateActive = function() { }; const notify_funder = (network, std_bounties_id, data) => { - var request_url = '/actions/bounty/' + network + '/' + std_bounties_id + '/notify/funder_payout_reminder/'; + var request_url = '/actions/bounty/' + network + '/' + std_bounties_id + '/notify/funder_payout_reminder/'; - showBusyOverlay(); - $.post(request_url, data).then(result => { - hideBusyOverlay(); - - _alert({message: gettext('Sent payout reminder')}, 'success'); - $('#notifyFunder a').addClass('disabled'); - return true; - }).fail(result => { - hideBusyOverlay(); - - _alert({ message: gettext('got an error. please try again, or contact support@gitcoin.co') }, 'error'); - }); + showBusyOverlay(); + $.post(request_url, data).then(() => { + hideBusyOverlay(); + _alert({message: gettext('Sent payout reminder')}, 'success'); + $('#notifyFunder a').addClass('disabled'); + return true; + }).fail(() => { + hideBusyOverlay(); + _alert({ message: gettext('got an error. please try again, or contact support@gitcoin.co') }, 'error'); + }); }; /** Add the current profile to the interested profiles list. */ diff --git a/app/assets/v2/js/users.js b/app/assets/v2/js/users.js index 3d307178217..e8564e272c2 100644 --- a/app/assets/v2/js/users.js +++ b/app/assets/v2/js/users.js @@ -101,7 +101,6 @@ Vue.mixin({ console.log(user); vm.userSelected = user; vm.showModal = true; - }, sendInvite: function(bounty, user) { let vm = this; @@ -129,6 +128,21 @@ Vue.mixin({ }, closeModal() { this.$refs['user-modal'].closeModal(); + }, + inviteOnMount: function() { + let vm = this; + let contributor = getURLParams('invite'); + + if (contributor) { + let api = `/api/v0.1/users_fetch/?search=${contributor}`; + let getUsers = fetchData (api, 'GET'); + + $.when(getUsers).then(function(response) { + if (response && response.data) { + vm.reinviteUser = response.data[0]; + } + }); + } } } @@ -156,10 +170,12 @@ if (document.getElementById('gc-users-directory')) { skills: document.keywords, selectedSkills: [], noResults: false, - isLoading: true + isLoading: true, + reinviteUser: '' }, mounted() { this.fetchUsers(); + this.inviteOnMount(); this.$watch('params', function(newVal, oldVal) { this.searchUsers(); }, { @@ -182,3 +198,14 @@ if (document.getElementById('gc-users-directory')) { }); } +if (getURLParams('invite')) { + let timer = setInterval(function() { + if ($('#reinvite-user').length) { + $('#reinvite-user').trigger('click'); + setTimeout(function() { + $('#reinvite-user').trigger('click'); + }, 200); + clearInterval(timer); + } + }, 500); +} \ No newline at end of file diff --git a/app/dashboard/templates/bounty/details.html b/app/dashboard/templates/bounty/details.html index 92fe509a6d4..701015566c8 100644 --- a/app/dashboard/templates/bounty/details.html +++ b/app/dashboard/templates/bounty/details.html @@ -30,7 +30,8 @@
- {% include 'shared/bounty_waiting_state.html' with can_close=True %} + {% include 'shared/waiting_state.html' %} + - -
diff --git a/app/dashboard/templates/dashboard/users.html b/app/dashboard/templates/dashboard/users.html index 2502397a115..c1d870bd787 100644 --- a/app/dashboard/templates/dashboard/users.html +++ b/app/dashboard/templates/dashboard/users.html @@ -48,6 +48,11 @@
+ + +
@@ -111,6 +116,12 @@ +
+ +
+ +
+
@@ -178,7 +189,7 @@
[[ user.work_done ]] bounties completed
- +
@@ -192,32 +203,41 @@
Invite User to Bounty
- [[ userSelected.data.name || userSelected.handle ]] + [[ userSelected.data.name ]] [[ userSelected.handle ]]
- Select a bounty -
-
- -

- [[ bounty.title ]] -

-
- [[ bounty.value_true ]] [[ bounty.token_name ]] - [[ bounty.value_in_usdt_now ]] USD +
+ Select a bounty +
+
+ +

+ [[ bounty.title ]] +

+
+ [[ bounty.value_true ]] [[ bounty.token_name ]] + [[ bounty.value_in_usdt_now ]] USD +
+
+

You've got NO open bounties

+

+ Create a bounty + to invite [[ userSelected.handle ]] +

+
view bounty
- +
diff --git a/app/dashboard/templates/process_bounty.html b/app/dashboard/templates/process_bounty.html index 038c188e869..f87cb761043 100644 --- a/app/dashboard/templates/process_bounty.html +++ b/app/dashboard/templates/process_bounty.html @@ -143,6 +143,15 @@

Suggested Kudos

document.bounty_amount_whole = {{bounty.get_value_true}}; document.bounty_amount_wei = {{bounty.value_in_token}}; document.token_address = '{{bounty.token_address}}'; + {% if open_fulfillments %} + let fulfillers= []; + + {% for fulfillment in open_fulfillments %} + fulfillers.push('{{ fulfillment.fulfiller_github_username }}'); + + {% endfor %} + sessionStorage['fulfillers'] = fulfillers; + {% endif %} diff --git a/app/dashboard/templates/shared/waiting_state.html b/app/dashboard/templates/shared/waiting_state.html new file mode 100644 index 00000000000..238eacc356b --- /dev/null +++ b/app/dashboard/templates/shared/waiting_state.html @@ -0,0 +1,36 @@ +{% comment %} + Copyright (C) 2018 Gitcoin Core + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +{% endcomment %} +{% load static i18n %} + +{% include 'shared/bounty_waiting_state.html' with can_close=True %} + \ No newline at end of file diff --git a/app/dashboard/views.py b/app/dashboard/views.py index cb02dbc24f0..4f37ffb0913 100644 --- a/app/dashboard/views.py +++ b/app/dashboard/views.py @@ -732,13 +732,11 @@ def onboard(request, flow): return TemplateResponse(request, 'ftux/onboard.html', params) +@login_required def users_directory(request): """Handle displaying users directory page.""" from retail.utils import programming_languages, programming_languages_full - if not request.user.is_authenticated: - return redirect('/login/github?next=' + request.get_full_path()) - keywords = programming_languages + programming_languages_full params = { diff --git a/app/grants/templates/grants/shared/waiting_state.html b/app/grants/templates/grants/shared/waiting_state.html index e9aa34799c0..b7fd7969373 100644 --- a/app/grants/templates/grants/shared/waiting_state.html +++ b/app/grants/templates/grants/shared/waiting_state.html @@ -20,11 +20,11 @@ {% include 'shared/bounty_waiting_state.html' with can_close=False %} diff --git a/app/retail/templates/shared/bulk_payout_form.html b/app/retail/templates/shared/bulk_payout_form.html index 041c2206f86..0ab87579cb2 100644 --- a/app/retail/templates/shared/bulk_payout_form.html +++ b/app/retail/templates/shared/bulk_payout_form.html @@ -54,10 +54,4 @@
-
- - - - - - + \ No newline at end of file