diff --git a/.travis.yml b/.travis.yml index 9899a4cb97a..803a040586f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -32,11 +32,13 @@ jobs: - pip install codecov # Fetch and Install GeoIP database files. - sudo apt-get update && sudo apt-get install -y libmaxminddb-dev - - wget http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.mmdb.gz - - wget http://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.mmdb.gz - - gunzip GeoLite2-City.mmdb.gz && gunzip GeoLite2-Country.mmdb.gz + - wget --output-document GeoLite2-City.mmdb.tar.gz "https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-City&date=20191231&license_key=7PZQgKNxgqTRhkWy&suffix=tar.gz" + - wget --output-document GeoLite2-Country.mmdb.tar.gz "https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-Country&date=20191231&license_key=7PZQgKNxgqTRhkWy&suffix=tar.gz" + - gunzip GeoLite2-City.mmdb.tar.gz && gunzip GeoLite2-Country.mmdb.tar.gz + - tar -xvf GeoLite2-City.mmdb.tar && tar -xvf GeoLite2-Country.mmdb.tar - sudo mkdir -p /opt/GeoIP/ - - sudo mv *.mmdb /opt/GeoIP/ + - sudo mv GeoLite2-City_20191231/*.mmdb /opt/GeoIP/ + - sudo mv GeoLite2-Country_20191231/*.mmdb /opt/GeoIP/ # Install libvips dependencies. - sudo apt-get install -y libvips libvips-dev # Install Node and Python dependencies. diff --git a/Dockerfile b/Dockerfile index ed0ab581778..102ce3ffff5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -25,11 +25,14 @@ RUN apt-get install -y python3-pip # GeoIP2 Data Files RUN mkdir -p /usr/share/GeoIP/ && \ - wget http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.mmdb.gz && \ - wget http://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.mmdb.gz && \ - gunzip GeoLite2-City.mmdb.gz && \ - gunzip GeoLite2-Country.mmdb.gz && \ - mv *.mmdb /usr/share/GeoIP/ + wget --output-document GeoLite2-City.mmdb.tar.gz "https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-City&date=20191231&license_key=7PZQgKNxgqTRhkWy&suffix=tar.gz" && \ + wget --output-document GeoLite2-Country.mmdb.tar.gz "https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-Country&date=20191231&license_key=7PZQgKNxgqTRhkWy&suffix=tar.gz" && \ + gunzip GeoLite2-City.mmdb.tar.gz && \ + gunzip GeoLite2-Country.mmdb.tar.gz && \ + tar -xvf GeoLite2-City.mmdb.tar && \ + tar -xvf GeoLite2-Country.mmdb.tar && \ + mv GeoLite2-City_20191231/*.mmdb /usr/share/GeoIP/ && \ + mv GeoLite2-Country_20191231/*.mmdb /usr/share/GeoIP/ # Upgrade package essentials. RUN pip3 install --upgrade pip setuptools wheel dumb-init pipenv diff --git a/app/app/context.py b/app/app/context.py index fdc866a84a4..fdff2dc55ae 100644 --- a/app/app/context.py +++ b/app/app/context.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- """Define additional context data to be passed to any request. -Copyright (C) 2018 Gitcoin Core +Copyright (C) 2020 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 @@ -91,10 +91,30 @@ def preprocess(request): callback = request.GET.get('cb') handle_marketing_callback(callback, request) + chat_unread_messages = False + + if profile and profile.chat_id: + try: + from chat.tasks import get_driver + chat_driver = get_driver() + + chat_unreads_request = chat_driver.teams.get_team_unreads_for_user( + profile.chat_id + ) + + if 'message' not in chat_unreads_request: + for teams in chat_unreads_request: + if teams['msg_count'] > 0 or teams['mention_count'] > 0: + chat_unread_messages = True + break + except Exception as e: + logger.error(str(e)) + context = { 'STATIC_URL': settings.STATIC_URL, 'MEDIA_URL': settings.MEDIA_URL, 'num_slack': num_slack, + 'chat_unread_messages' : chat_unread_messages, 'github_handle': request.user.username if user_is_authenticated else False, 'email': request.user.email if user_is_authenticated else False, 'name': request.user.get_full_name() if user_is_authenticated else False, diff --git a/app/app/log_filters.py b/app/app/log_filters.py index 36c670d9237..aed9175f012 100644 --- a/app/app/log_filters.py +++ b/app/app/log_filters.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- """Define custom log filters for Gitcoin logging. -Copyright (C) 2018 Gitcoin Core +Copyright (C) 2020 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 diff --git a/app/app/pipeline.py b/app/app/pipeline.py index 83b8b408c42..1c2051ae33f 100644 --- a/app/app/pipeline.py +++ b/app/app/pipeline.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- """Define authentication pipeline functions and logic. -Copyright (C) 2018 Gitcoin Core +Copyright (C) 2020 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 diff --git a/app/app/settings.py b/app/app/settings.py index e783a0a5bb1..d38bcd3ed72 100644 --- a/app/app/settings.py +++ b/app/app/settings.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- """Define the Gitcoin project settings. -Copyright (C) 2018 Gitcoin Core +Copyright (C) 2020 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 @@ -91,6 +91,7 @@ 'health_check.contrib.s3boto3_storage', 'app', 'avatar', + 'chat', 'retail', 'rest_framework', 'marketing', @@ -120,7 +121,8 @@ 'event_ethdenver2019', 'inbox', 'feeswapper', - 'oauth2_provider' + 'oauth2_provider', + 'compliance' ] MIDDLEWARE = [ @@ -467,6 +469,8 @@ CELERY_TASK_SERIALIZER = 'json' # http://docs.celeryproject.org/en/latest/userguide/configuration.html#std:setting-result_serializer CELERY_RESULT_SERIALIZER = 'json' +# http://docs.celeryproject.org/en/latest/userguide/configuration.html#std:setting-result_backend +CELERY_RESULT_BACKEND = env('CELERY_RESULT_BACKEND', default=CACHEOPS_REDIS) DJANGO_REDIS_IGNORE_EXCEPTIONS = env.bool('REDIS_IGNORE_EXCEPTIONS', default=True) DJANGO_REDIS_LOG_IGNORED_EXCEPTIONS = env.bool('REDIS_LOG_IGNORED_EXCEPTIONS', default=True) @@ -541,8 +545,11 @@ GITHUB_APP_NAME = env('GITHUB_APP_NAME', default='gitcoin-local') # Chat -CHAT_URL = env('CHAT_DRIVER_USER', default='') # location of where mattermost is hosted - +CHAT_PORT = env('CHAT_PORT', default=8065) # port of where mattermost is hosted +CHAT_URL = env('CHAT_URL', default='http://localhost') # location of where mattermost is hosted +CHAT_DRIVER_TOKEN = env('CHAT_DRIVER_TOKEN', default='') # driver token +GITCOIN_HACK_CHAT_TEAM_ID = env('GITCOIN_HACK_CHAT_TEAM_ID', default='') +GITCOIN_CHAT_TEAM_ID = env('GITCOIN_CHAT_TEAM_ID', default='') # Social Auth LOGIN_URL = 'gh_login' LOGOUT_URL = 'logout' diff --git a/app/app/templates/shared/messages.html b/app/app/templates/shared/messages.html index f1cc256796b..a3e38f582a7 100644 --- a/app/app/templates/shared/messages.html +++ b/app/app/templates/shared/messages.html @@ -1,5 +1,5 @@ {% comment %} - Copyright (C) 2018 Gitcoin Core + Copyright (C) 2020 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 diff --git a/app/app/templates/shared/rain.html b/app/app/templates/shared/rain.html index 3acc8f66a44..2137aa52887 100644 --- a/app/app/templates/shared/rain.html +++ b/app/app/templates/shared/rain.html @@ -1,5 +1,5 @@ {% comment %} - Copyright (C) 2018 Gitcoin Core + Copyright (C) 2020 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 diff --git a/app/app/templates/shared/sentry.html b/app/app/templates/shared/sentry.html index 5d12c127c47..7efab7eee9c 100644 --- a/app/app/templates/shared/sentry.html +++ b/app/app/templates/shared/sentry.html @@ -1,5 +1,5 @@ {% comment %} - Copyright (C) 2018 Gitcoin Core + Copyright (C) 2020 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 diff --git a/app/app/tests/test_app_urls.py b/app/app/tests/test_app_urls.py index 319561786dd..d30d83a39d1 100644 --- a/app/app/tests/test_app_urls.py +++ b/app/app/tests/test_app_urls.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- """Handle app url related tests. -Copyright (C) 2018 Gitcoin Core +Copyright (C) 2020 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 diff --git a/app/app/thumbnail_processors.py b/app/app/thumbnail_processors.py index b4a209c64da..d12dfe3d6c8 100644 --- a/app/app/thumbnail_processors.py +++ b/app/app/thumbnail_processors.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- """Define the EthOS thumbnail processors. -Copyright (C) 2018 Gitcoin Core +Copyright (C) 2020 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 diff --git a/app/app/urls.py b/app/app/urls.py index 2da35268758..2d6470636a3 100644 --- a/app/app/urls.py +++ b/app/app/urls.py @@ -1,5 +1,5 @@ ''' - Copyright (C) 2018 Gitcoin Core + Copyright (C) 2020 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 @@ -146,8 +146,9 @@ url(r'^api/v0.1/choose_persona/', dashboard.views.choose_persona, name='choose_persona'), # chat - url(r'^chat/', chat.views.embed, name='chat'), - url(r'^chat', chat.views.embed, name='chat2'), + url(r'^chat/web', chat.views.embed, name='web_chat'), + url(r'^chat/web/', chat.views.embed, name='web_chat2'), + re_path(r'^chat/?', chat.views.chat, name='chat'), # Health check endpoint re_path(r'^health/', include('health_check.urls')), re_path(r'^lbcheck/?', healthcheck.views.lbcheck, name='lbcheck'), diff --git a/app/app/wsgi.py b/app/app/wsgi.py index d2aa67c3d09..ee1f18de131 100644 --- a/app/app/wsgi.py +++ b/app/app/wsgi.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 """Define the application WSGI. -Copyright (C) 2018 Gitcoin Core +Copyright (C) 2020 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 diff --git a/app/assets/v2/css/base.css b/app/assets/v2/css/base.css index 1c073469433..1c0ffbae303 100644 --- a/app/assets/v2/css/base.css +++ b/app/assets/v2/css/base.css @@ -20,6 +20,10 @@ a { color: #3E00FF; } +.cursor-pointer { + cursor: pointer !important; +} + .nav_avatar { width: 40px; height: 40px; diff --git a/app/assets/v2/css/chat.css b/app/assets/v2/css/chat.css new file mode 100644 index 00000000000..1606668e904 --- /dev/null +++ b/app/assets/v2/css/chat.css @@ -0,0 +1,43 @@ +.banner { + background-color: #0d023b; + background-size: cover; + background-position: 0px 0px; + background-repeat: no-repeat; + position: relative; + color: #fff; + padding-top: 5rem; + padding-bottom: 5rem; +} + +.sub-headline { + line-height: 48px; +} + +.online { + color: #25e899; +} + +.dot { + background-color: #25e899; + display: none; + width: 9px; + height: 9px; + border-radius: 50%; + position: absolute; + top: 0.5em; + right: 0.9em; +} + +.open-app { + background-color: #0D001A; +} + +img.feature { + border-radius: 80px; +} + +@media (max-width: 1024px) { + .chat-img { + display: none; + } +} \ No newline at end of file diff --git a/app/assets/v2/css/grants/detail.css b/app/assets/v2/css/grants/detail.css index 90823db786c..59a3166755e 100644 --- a/app/assets/v2/css/grants/detail.css +++ b/app/assets/v2/css/grants/detail.css @@ -1,3 +1,10 @@ +.grant_details .box { + width: 20px; + height: 20px; + margin-right: 10px; + padding: 0px; +} + @media (min-width: 1200px) { .grant-detail .container { max-width: 85vw diff --git a/app/assets/v2/css/grants/grant.css b/app/assets/v2/css/grants/grant.css index 0b5d5750da2..e7d0ae9ee78 100644 --- a/app/assets/v2/css/grants/grant.css +++ b/app/assets/v2/css/grants/grant.css @@ -331,6 +331,7 @@ cursor: pointer; } +.grant-partners .nav-link, .grant-partners .nav-link:hover { border: none; } diff --git a/app/assets/v2/css/grants/new.css b/app/assets/v2/css/grants/new.css index 59b23dd8b0f..859db228962 100644 --- a/app/assets/v2/css/grants/new.css +++ b/app/assets/v2/css/grants/new.css @@ -53,7 +53,7 @@ } .select2-container--default .select2-selection--multiple { - height: 2.75rem; + height: 2rem; } .select2-container--default .select2-selection--multiple .select2-selection__choice { diff --git a/app/assets/v2/css/profile.css b/app/assets/v2/css/profile.css index 4904cace64f..6a3361b0806 100644 --- a/app/assets/v2/css/profile.css +++ b/app/assets/v2/css/profile.css @@ -18,7 +18,7 @@ background: #E8F0FA; padding: 4px; border-radius: 2px; - font-size: 12px; + font-size: 11px; color: #6487AE; display: inline-block; margin-bottom: 2px; @@ -215,8 +215,11 @@ display: none; } -} + .transaction-history.bounty_row .avatar { + max-width: 100% !important; + } +} .profile-header__stats { border: none; @@ -239,6 +242,19 @@ padding: 0.7rem; } + +.bounty_row { + border-bottom: 1px solid #EFEFEF; +} + +.bounty_row:hover { + background: none; +} + +#earn_dataviz { + max-width: 100%; +} + @media (min-width: 992px) and (max-width: 1199.98px) { .profile-header__stats .card-header { diff --git a/app/assets/v2/images/chat/android.png b/app/assets/v2/images/chat/android.png new file mode 100644 index 00000000000..8cbad34ce0f Binary files /dev/null and b/app/assets/v2/images/chat/android.png differ diff --git a/app/assets/v2/images/chat/apple.png b/app/assets/v2/images/chat/apple.png new file mode 100644 index 00000000000..3c3f8ab777b Binary files /dev/null and b/app/assets/v2/images/chat/apple.png differ diff --git a/app/assets/v2/images/chat/chat.png b/app/assets/v2/images/chat/chat.png new file mode 100644 index 00000000000..9ad17074af8 Binary files /dev/null and b/app/assets/v2/images/chat/chat.png differ diff --git a/app/assets/v2/images/chat/desktop.png b/app/assets/v2/images/chat/desktop.png new file mode 100644 index 00000000000..93d00bae3b2 Binary files /dev/null and b/app/assets/v2/images/chat/desktop.png differ diff --git a/app/assets/v2/images/chat/feature_1.png b/app/assets/v2/images/chat/feature_1.png new file mode 100644 index 00000000000..f976069fdf6 Binary files /dev/null and b/app/assets/v2/images/chat/feature_1.png differ diff --git a/app/assets/v2/images/chat/feature_2.png b/app/assets/v2/images/chat/feature_2.png new file mode 100644 index 00000000000..205266f29a9 Binary files /dev/null and b/app/assets/v2/images/chat/feature_2.png differ diff --git a/app/assets/v2/images/chat/feature_3.png b/app/assets/v2/images/chat/feature_3.png new file mode 100644 index 00000000000..9117e4e6e3b Binary files /dev/null and b/app/assets/v2/images/chat/feature_3.png differ diff --git a/app/assets/v2/images/chat/mobile.png b/app/assets/v2/images/chat/mobile.png new file mode 100644 index 00000000000..8b40ba895e7 Binary files /dev/null and b/app/assets/v2/images/chat/mobile.png differ diff --git a/app/assets/v2/images/chat/web.png b/app/assets/v2/images/chat/web.png new file mode 100644 index 00000000000..439e8b854d0 Binary files /dev/null and b/app/assets/v2/images/chat/web.png differ diff --git a/app/assets/v2/images/chat/windows.png b/app/assets/v2/images/chat/windows.png new file mode 100644 index 00000000000..080e74cc0e8 Binary files /dev/null and b/app/assets/v2/images/chat/windows.png differ diff --git a/app/assets/v2/js/base.js b/app/assets/v2/js/base.js index b263485f809..18195602334 100644 --- a/app/assets/v2/js/base.js +++ b/app/assets/v2/js/base.js @@ -406,3 +406,7 @@ const gitcoinUpdates = (force) => { if (document.contxt.github_handle) { gitcoinUpdates(); } + +if (document.contxt.chat_unread_messages) { + $('#chat-notification-dot').addClass('notification__dot__active'); +} diff --git a/app/assets/v2/js/grants/detail.js b/app/assets/v2/js/grants/detail.js index 6beed21d4d3..935251a27b9 100644 --- a/app/assets/v2/js/grants/detail.js +++ b/app/assets/v2/js/grants/detail.js @@ -13,10 +13,10 @@ $(document).ready(function() { setInterval (() => { notifyOwnerAddressMismatch( $('#grant-admin').text(), - $('#grant_contract_owner_address').text(), + $('#contract_owner_address').text(), '#cancel_grant', 'Looks like your grant has been created with ' + - $('#grant_contract_owner_address').text() + '. Switch to take action on your grant.' + $('#contract_owner_address').text() + '. Switch to take action on your grant.' ); if ($('#cancel_grant').attr('disabled')) { diff --git a/app/assets/v2/js/grants/fund.js b/app/assets/v2/js/grants/fund.js index c12775a5f4a..3fad96ee4ee 100644 --- a/app/assets/v2/js/grants/fund.js +++ b/app/assets/v2/js/grants/fund.js @@ -210,34 +210,42 @@ $(document).ready(function() { approvalAddress = data.contract_address; } - deployedToken.methods.approve( - approvalAddress, - web3.utils.toTwosComplement(approvalSTR) - ).send({ - from: accounts[0], - gasPrice: web3.utils.toHex($('#gasPrice').val() * Math.pow(10, 9)), - gas: web3.utils.toHex(gas_amount(document.location.href)), - gasLimit: web3.utils.toHex(gas_amount(document.location.href)) - }).on('error', function(error) { - console.log('1', error); - _alert({ message: gettext('Your approval transaction failed. Please try again.')}, 'error'); - }).on('transactionHash', function(transactionHash) { - $('#sub_new_approve_tx_id').val(transactionHash); - if (data.num_periods == 1) { - // call splitter after approval - splitPayment(accounts[0], data.admin_address, gitcoinDonationAddress, Number(grant_amount * Math.pow(10, decimals)).toLocaleString('fullwide', {useGrouping: false}), Number(gitcoin_grant_amount * Math.pow(10, decimals)).toLocaleString('fullwide', {useGrouping: false})); + deployedToken.methods.balanceOf( + accounts[0] + ).call().then(function(result) { + if (result < realTokenAmount) { + _alert({ message: gettext('Your balance could not be verified')}, 'error'); } else { - if (data.contract_version == 0 && gitcoin_grant_amount > 0) { - donationPayment(deployedToken, accounts[0], Number(gitcoin_grant_amount * Math.pow(10, decimals)).toLocaleString('fullwide', {useGrouping: false})); - } - subscribeToGrant(transactionHash); - } - }).on('confirmation', function(confirmationNumber, receipt) { - waitforData(() => { - document.suppress_loading_leave_code = true; - window.location = redirectURL; - }); // waitforData - }); // approve on confirmation + deployedToken.methods.approve( + approvalAddress, + web3.utils.toTwosComplement(approvalSTR) + ).send({ + from: accounts[0], + gasPrice: web3.utils.toHex($('#gasPrice').val() * Math.pow(10, 9)), + gas: web3.utils.toHex(gas_amount(document.location.href)), + gasLimit: web3.utils.toHex(gas_amount(document.location.href)) + }).on('error', function(error) { + console.log('1', error); + _alert({ message: gettext('Your approval transaction failed. Please try again.')}, 'error'); + }).on('transactionHash', function(transactionHash) { + $('#sub_new_approve_tx_id').val(transactionHash); + if (data.num_periods == 1) { + // call splitter after approval + splitPayment(accounts[0], data.admin_address, gitcoinDonationAddress, Number(grant_amount * Math.pow(10, decimals)).toLocaleString('fullwide', {useGrouping: false}), Number(gitcoin_grant_amount * Math.pow(10, decimals)).toLocaleString('fullwide', {useGrouping: false})); + } else { + if (data.contract_version == 0 && gitcoin_grant_amount > 0) { + donationPayment(deployedToken, accounts[0], Number(gitcoin_grant_amount * Math.pow(10, decimals)).toLocaleString('fullwide', {useGrouping: false})); + } + subscribeToGrant(transactionHash); + } + }).on('confirmation', function(confirmationNumber, receipt) { + waitforData(() => { + document.suppress_loading_leave_code = true; + window.location = redirectURL; + }); // waitforData + }); // approve on confirmation + } // if (result < realTokenAmount) + }); // check token balance }); // getAccounts }); // decimals } // submitHandler diff --git a/app/assets/v2/js/grants/new.js b/app/assets/v2/js/grants/new.js index 93aa59bfdae..a5765217fcd 100644 --- a/app/assets/v2/js/grants/new.js +++ b/app/assets/v2/js/grants/new.js @@ -76,7 +76,27 @@ const init = () => { $(this).select2(); }); - $('#create-grant').validate({ + $('#input-admin_address').on('change', function() { + $('.alert').remove(); + const validator = $('#create-grant').validate(); + let address = $(this).val(); + + if (isNaN(parseInt(address))) { + web3.eth.ens.getAddress(address).then(function(result) { + $('#input-admin_address').val(result); + return result; + }).catch(function() { + validator.showErrors({ + 'admin_address': 'Please check your address!' + }); + return _alert({ message: gettext('Please check your address and try again.') }, 'error'); + }); + } + }); + + $('#create-grant').submit(function(e) { + e.preventDefault(); + }).validate({ submitHandler: function(form) { let data = {}; @@ -240,6 +260,7 @@ const init = () => { }); }); }); + return false; } }); @@ -259,7 +280,8 @@ const init = () => { $('#js-token').select2(); $("#js-token option[value='0x0000000000000000000000000000000000000000']").remove(); $('#js-token').append("