diff --git a/.eslintignore b/.eslintignore index f7b71292d16..9c3e5d9d179 100644 --- a/.eslintignore +++ b/.eslintignore @@ -5,6 +5,8 @@ app/assets/v2/js/jquery*.js app/assets/v2/js/jsrender.js app/assets/v2/js/showdown.js app/assets/v2/js/tooltip.js +app/assets/v2/js/tweenlite.js +app/assets/v2/js/abi.js app/assets/onepager/js/confetti.js diff --git a/.gitignore b/.gitignore index a6026806d7b..75d447c3553 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,7 @@ node_modules/ gcoin/ .cache/ webpack-stats.json +.sass-cache # Sensitive environment files .env diff --git a/.stylelintignore b/.stylelintignore index 09a572c74c2..c9d057feb60 100644 --- a/.stylelintignore +++ b/.stylelintignore @@ -1,2 +1,4 @@ app/assets/v2/css/jquery.select2.min.css app/assets/v2/css/bootstrap.min.css +app/assets/v2/js/tweenlite.js +app/assets/v2/js/abi.js diff --git a/app/app/context.py b/app/app/context.py index 5e375d2cb54..abbb964a883 100644 --- a/app/app/context.py +++ b/app/app/context.py @@ -23,6 +23,7 @@ from django.utils import timezone from dashboard.models import Tip +from kudos.models import KudosTransfer def insert_settings(request): @@ -75,7 +76,12 @@ def insert_settings(request): username__iexact=context['github_handle'], web3_type='v3', ).exclude(txid='') + context['unclaimed_kudos'] = KudosTransfer.objects.filter( + receive_txid='', username__iexact="@" + context['github_handle'], web3_type='v3', + ).exclude(txid='') + if not settings.DEBUG: context['unclaimed_tips'] = context['unclaimed_tips'].filter(network='mainnet') + context['unclaimed_kudos'] = context['unclaimed_kudos'].filter(network='mainnet') return context diff --git a/app/app/settings.py b/app/app/settings.py index 3a7a1c92511..80fd9de230a 100644 --- a/app/app/settings.py +++ b/app/app/settings.py @@ -27,6 +27,9 @@ import raven from easy_thumbnails.conf import Settings as easy_thumbnails_defaults +import warnings +warnings.filterwarnings("ignore", category=UserWarning, module='psycopg2') + root = environ.Path(__file__) - 2 # Set the base directory to two levels. env = environ.Env(DEBUG=(bool, False), ) # set default values and casting env.read_env(str(root.path('app/.env'))) # reading .env file @@ -101,6 +104,8 @@ 'external_bounties', 'dataviz', 'impersonate', + 'kudos', + 'django.contrib.postgres', 'bounty_requests' ] @@ -130,7 +135,7 @@ TEMPLATES = [{ 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'DIRS': ['retail/templates/', 'external_bounties/templates/', 'dataviz/templates', ], + 'DIRS': ['retail/templates/', 'external_bounties/templates/', 'dataviz/templates', 'kudos/templates'], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ @@ -489,6 +494,18 @@ SLACK_TOKEN = env('SLACK_TOKEN', default='') # TODO SLACK_WELCOMEBOT_TOKEN = env('SLACK_WELCOMEBOT_TOKEN', default='') # TODO +# OpenSea API +OPENSEA_API_KEY = env('OPENSEA_API_KEY', default='') + +# Kudos +KUDOS_OWNER_ACCOUNT = env('KUDOS_OWNER_ACCOUNT', default='0xD386793F1DB5F21609571C0164841E5eA2D33aD8') +KUDOS_PRIVATE_KEY = env('KUDOS_PRIVATE_KEY', default='') +KUDOS_CONTRACT_MAINNET = env('KUDOS_CONTRACT_MAINNET', default='0x2aea4add166ebf38b63d09a75de1a7b94aa24163') +KUDOS_CONTRACT_RINKEBY = env('KUDOS_CONTRACT_RINKEBY', default='0x4077ae95eec529d924571d00e81ecde104601ae8') +KUDOS_CONTRACT_ROPSTEN = env('KUDOS_CONTRACT_ROPSTEN', default='0xcd520707fc68d153283d518b29ada466f9091ea8') +KUDOS_CONTRACT_TESTRPC = env('KUDOS_CONTRACT_TESTRPC', default='0xe7bed272ee374e8116049d0a49737bdda86325b6') +KUDOS_NETWORK = env('KUDOS_NETWORK', default='localhost') + # Reporting Integrations MIXPANEL_TOKEN = env('MIXPANEL_TOKEN', default='') diff --git a/app/app/urls.py b/app/app/urls.py index c00ab594c29..1931a2c0edc 100644 --- a/app/app/urls.py +++ b/app/app/urls.py @@ -40,6 +40,7 @@ import faucet.views import gitcoinbot.views import healthcheck.views +import kudos.views import linkshortener.views import marketing.views import marketing.webhookviews @@ -48,21 +49,43 @@ import tdi.views from dashboard.router import router as dbrouter from external_bounties.router import router as ebrouter +from kudos.router import router as kdrouter from .sitemaps import sitemaps urlpatterns = [ path('jsi18n/', JavaScriptCatalog.as_view(), name='javascript-catalog'), + # kudos + path('kudos/', kudos.views.about, name='kudos_main'), + path('kudos/about/', kudos.views.about, name='kudos_about'), + path('kudos/marketplace/', kudos.views.marketplace, name='kudos_marketplace'), + path('kudos/mint/', kudos.views.mint, name='kudos_mint'), + path('kudos/send/', kudos.views.send_2, name='kudos_send'), + path('kudos/send/3/', kudos.views.send_3, name='kudos_send_3'), + path('kudos/send/4/', kudos.views.send_4, name='kudos_send_4'), + re_path(r'^lazy_load_kudos/$', dashboard.views.lazy_load_kudos, name='lazy_load_kudos'), + re_path(r'^kudos/receive/v3/(?P.*)/(?P.*)/(?P.*)?', kudos.views.receive, name='kudos_receive'), + re_path(r'^kudos/search/$', kudos.views.search, name='kudos_search'), + re_path( + r'^kudos/(?P
\w*)/(?P\d+)/(?P\w*)', + kudos.views.details_by_address_and_token_id, + name='kudos_details_by_address_and_token_id' + ), + re_path(r'^kudos/(?P\d+)/(?P\w*)', kudos.views.details, name='kudos_details'), + re_path(r'^kudos/address/(?P.*)', kudos.views.kudos_preferred_wallet, name='kudos_preferred_wallet'), + re_path(r'^dynamic/kudos/(?P\d+)/(?P\w*)', kudos.views.image, name='kudos_details'), + # api views url(r'^api/v0.1/profile/(.*)?/keywords', dashboard.views.profile_keywords, name='profile_keywords'), url(r'^api/v0.1/funding/save/?', dashboard.ios.save, name='save'), url(r'^api/v0.1/faucet/save/?', faucet.views.save_faucet, name='save_faucet'), url(r'^api/v0.1/', include(dbrouter.urls)), url(r'^api/v0.1/', include(ebrouter.urls)), - url(r'^actions/api/v0.1/', include(dbrouter.urls)), # same as active, but not cached in cloudfront + url(r'^api/v0.1/', include(kdrouter.urls)), + url(r'^actions/api/v0.1/', include(dbrouter.urls)), # same as active, but not cached in cluodfront url(r'^api/v0.1/users_search/', dashboard.views.get_users, name='users_search'), - + url(r'^api/v0.1/kudos_search/', dashboard.views.get_kudos, name='kudos_search'), # Health check endpoint re_path(r'^health/', include('health_check.urls')), re_path(r'^lbcheck/?', healthcheck.views.lbcheck, name='lbcheck'), @@ -252,6 +275,9 @@ # admin views re_path(r'^_administration/?', admin.site.urls, name='admin'), + path('_administration/email/new_kudos', retail.emails.new_kudos, name='new_kudos'), + path('_administration/email/kudos_mint', retail.emails.kudos_mint, name='kudos_mint'), + path('_administration/email/kudos_mkt', retail.emails.kudos_mkt, name='kudos_mkt'), path('_administration/email/new_bounty', retail.emails.new_bounty, name='admin_new_bounty'), path('_administration/email/roundup', retail.emails.roundup, name='roundup'), path('_administration/email/faucet_rejected', retail.emails.faucet_rejected, name='email_faucet_rejected'), diff --git a/app/assets/onepager/css/main.css b/app/assets/onepager/css/main.css index 027ab812193..b1a508455e7 100644 --- a/app/assets/onepager/css/main.css +++ b/app/assets/onepager/css/main.css @@ -20,30 +20,6 @@ body { background-attachment: fixed; } -body::after { - content: ''; - display: block; - position: fixed; - top: 0; - left: 0; - width: 100%; - height: inherit; - opacity: 0; - z-index: 1; - background-color: #ffffff; - background-image: url('/static/onepager/images/overlay.png'), -moz-linear-gradient(60deg, rgba(255, 165, 150, 0.5) 5%, rgba(0, 228, 255, 0.35)); - background-image: url('/static/onepager/images/overlay.png'), -webkit-linear-gradient(60deg, rgba(255, 165, 150, 0.5) 5%, rgba(0, 228, 255, 0.35)); - background-image: url('/static/onepager/images/overlay.png'), -ms-linear-gradient(60deg, rgba(255, 165, 150, 0.5) 5%, rgba(0, 228, 255, 0.35)); - background-image: url('/static/onepager/images/overlay.png'), linear-gradient(60deg, rgba(255, 165, 150, 0.5) 5%, rgba(0, 228, 255, 0.35)); - background-repeat: repeat, no-repeat; - background-size: 100px 100px, cover; - background-position: top left, center center; - -moz-transition: opacity 1.75s ease-out; - -webkit-transition: opacity 1.75s ease-out; - -ms-transition: opacity 1.75s ease-out; - transition: opacity 1.75s ease-out; -} - body.is-loading:after { opacity: 1; } diff --git a/app/assets/onepager/js/receive.js b/app/assets/onepager/js/receive.js index aa1a4ad21b2..f5b28e79065 100644 --- a/app/assets/onepager/js/receive.js +++ b/app/assets/onepager/js/receive.js @@ -25,7 +25,7 @@ window.onload = function() { } ipfs.catText(document.ipfs_key_to_secret, function(err, key2) { if (err) { - _alert('could not reach IPFS. please try again later.', 'error'); + _alert('Could not reach IPFS. please try again later.', 'error'); return; } document.priv_key = combine_secrets(key2, document.gitcoin_secret); diff --git a/app/assets/v2/css/base.css b/app/assets/v2/css/base.css index 78859cdb40e..7e83b948ff6 100644 --- a/app/assets/v2/css/base.css +++ b/app/assets/v2/css/base.css @@ -453,10 +453,6 @@ p a { color: #25e899; } -.btn:focus { - box-shadow: none; -} - .cta-green { background-color: var(--gc-green); text-align: center; diff --git a/app/assets/v2/css/buttons.css b/app/assets/v2/css/buttons.css index a135aa7bfb6..07b0e5ce9c5 100644 --- a/app/assets/v2/css/buttons.css +++ b/app/assets/v2/css/buttons.css @@ -60,16 +60,6 @@ box-shadow: inset 0 -3.25em 0 0 var(--hover); } -.slide { - --color: #8fc866; - --hover: #66c887; -} - -.slide:hover, -.slide:focus { - box-shadow: inset 6.5em 0 0 0 var(--hover); -} - .offset { --color: #19bc8b; --hover: #1973bc; diff --git a/app/assets/v2/css/gitcoin.css b/app/assets/v2/css/gitcoin.css index 84e62f2077f..e422355b866 100644 --- a/app/assets/v2/css/gitcoin.css +++ b/app/assets/v2/css/gitcoin.css @@ -399,6 +399,14 @@ div.button-pink { cursor: pointer; } +.gc-round-text-input { + height: 32px; + border: 1px solid #eee; + outline: none; + padding-left: 10px; + font-weight: 300; +} + .gc-border-black { border: 1px solid black !important; } @@ -407,16 +415,12 @@ div.button-pink { border: 1px solid #37ea9c !important; } -.gc-selected { - border: 1px solid #4ef6ad !important; +.gc-border-blue { + border-color: #0D0764; } -.gc-round-text-input { - height: 32px; - border: 1px solid #eee; - outline: none; - padding-left: 10px; - font-weight: 300; +.gc-selected { + border: 1px solid #4ef6ad !important; } .gc-round-text-form { @@ -467,10 +471,11 @@ div.button-pink { /* stylelint-disable-next-line */ font-family: 'Font Awesome 5 Free'; content: '\f107'; - font-size: 16px; + font-size: 1.2em; margin-right: auto; margin-top: auto; float: right; + font-weight: 600; } .accordion.active:after { @@ -554,17 +559,29 @@ div.button-pink { } } -/* AutoComplete */ -.select2-container .select2-selection--single { - height: 2.5rem !important +.nav-tabs .nav-line { + color: #4A4A4A; + border-width: 0px 0px 3px 0; +} +.nav-tabs .nav-line.active { + color: #0D0764; + border-color: #0D0764; + background-color: transparent; +} + +.border-transparent { + border-color: transparent; } +/* AutoComplete */ + .select2-results__option, .select2-search--dropdown .select2-search__field { font-size: 0.8rem } .select2-container--default .select2-selection--single { + height: 2.5rem !important; border-radius: 2px !important; border-color: black !important; } @@ -656,3 +673,32 @@ div.button-pink { } } /* TODO: End */ + +/* fallback for send tip navbar */ +.d-none { + display: none!important; +} + +@media (min-width: 768px) { + + .d-md-block { + display: block!important; + } + .d-md-flex { + display: -ms-flexbox!important; + display: flex!important; + } + .d-md-none { + display: none!important; + } +} + +.notification-dot { + background-color: #ef3427; + width: 0.5rem; + height: 0.5rem; + position: absolute; + top: 6px; + border-radius: 30px; + left: 6px; +} diff --git a/app/assets/v2/css/kudos/range-slider.scss b/app/assets/v2/css/kudos/range-slider.scss new file mode 100644 index 00000000000..edcf8f3fb7f --- /dev/null +++ b/app/assets/v2/css/kudos/range-slider.scss @@ -0,0 +1,37 @@ +$blue: #0D0764; + +[data-rangeslider] { + -webkit-appearance: none; + width: 100%; + height: 2px; + background: $blue; + outline: none; + margin: 1rem 0; + + &::-webkit-slider-thumb { + -webkit-appearance: none; + appearance: none; + width: 18px; + height: 18px; + border-radius: 50px; + background: $blue; + cursor: pointer; + transition: .1s all linear; + } + + &:hover::-webkit-slider-thumb { + width: 22px; + height: 22px; + } + &:focus::-webkit-slider-thumb { + width: 26px; + height: 26px; + border-radius: 50px 50px 4px; + transform: rotate(45deg); + margin-bottom: 50px; + } + + &::-webkit-slider-runnable-track {} +} + + diff --git a/app/assets/v2/css/kudos/select2.bootstrap4.scss b/app/assets/v2/css/kudos/select2.bootstrap4.scss new file mode 100644 index 00000000000..cf676c426ae --- /dev/null +++ b/app/assets/v2/css/kudos/select2.bootstrap4.scss @@ -0,0 +1,68 @@ +$arrow-color: #6c757d; +$border-grey: #ced4da; + +.select2 { + width: 100%; +} + +.select2-container--bootstrap4 { + border: 1px solid #ced4da; + padding: 0.25em; + border-radius: .25rem; +} + +.select2-container--bootstrap4.select2-container--disabled { + background-color: #e9ecef; + opacity: 1; +} + +.select2-container--bootstrap4.select2-container--open .select2-selection .select2-selection__arrow b { + border-color: transparent transparent $arrow-color transparent; + border-width: 0 0.45rem 0.45rem 0.45rem; +} + +.select2-container--bootstrap4 .select2-selection--single .select2-selection__arrow { + position: absolute; + bottom: 0; + right: 0.375rem; + top: 0; + width: 0.85rem; +} + +.select2-container--bootstrap4 .select2-selection--single .select2-selection__arrow b { + border-color: $arrow-color transparent transparent transparent; + border-style: solid; + border-width: 0.45rem 0.45rem 0 0.45rem; + height: 0; + left: 0; + position: absolute; + top: 0; + bottom: 0; + width: 0; + border-radius: 4px; + margin: auto; + } + + .select2-container--bootstrap4 .select2-search--dropdown .select2-search__field { + border-radius: 4px; + border: 1px solid #7777; + } + +.select2-container--open .select2-dropdown.select2-dropdown--below { + top: -3px; + left: -1px; + } + +.select2-container--open .select2-dropdown.select2-dropdown--above { + top: 1px; + left: -1px; + } + + .select2-container--bootstrap4 .select2-dropdown { + border-color: $border-grey; + } + + .select2-container--bootstrap4 .select2-results__option--highlighted[aria-selected] { + background-color: #5897fb; + color: white; +} diff --git a/app/assets/v2/css/kudos/styles.css b/app/assets/v2/css/kudos/styles.css new file mode 100644 index 00000000000..0f3b368ce45 --- /dev/null +++ b/app/assets/v2/css/kudos/styles.css @@ -0,0 +1,578 @@ +.box-transaction { + max-width: 35rem; + margin: auto; + background: #fff; + z-index: 2; + position: relative; + padding: 1em 3em 3em 3em; } + +.transaction { + background-color: #0d023b; + background-image: -moz-linear-gradient(60deg, rgba(255, 165, 150, 0.5) 5%, rgba(0, 228, 255, 0.35)), url("/static/v2/images/header-bg.png"); + background-image: -webkit-linear-gradient(60deg, rgba(255, 165, 150, 0.5) 5%, rgba(0, 228, 255, 0.35)), url("/static/v2/images/header-bg.png"); + background-image: -ms-linear-gradient(60deg, rgba(255, 165, 150, 0.5) 5%, rgba(0, 228, 255, 0.35)), url("/static/v2/images/header-bg.png"); + background-image: linear-gradient(60deg, rgba(255, 165, 150, 0.5) 5%, rgba(0, 228, 255, 0.35)), url("/static/v2/images/header-bg.png"); + background-repeat: no-repeat; + background-size: cover; + background-position: center center; + background-attachment: fixed; } + +.alert_msg { + top: 0px; + width: 100%; + z-index: 99999; + background-color: #f44336; + color: white; + position: fixed; + text-align: center; } + +.alert_msg.info { + background-color: #2196F3; } + +.line-back { + position: relative; + display: block; } + .line-back:before { + content: ''; + display: block; + position: absolute; + top: 50%; + left: -3em; + width: calc(100% + 6em); + height: 1px; + z-index: -1; + background: #c8cccf; } + +.copyright a { + color: white; } + +[data-rangeslider] { + -webkit-appearance: none; + width: 100%; + height: 2px; + background: #0D0764; + outline: none; + margin: 1rem 0; } + [data-rangeslider]::-webkit-slider-thumb { + -webkit-appearance: none; + appearance: none; + width: 18px; + height: 18px; + border-radius: 50px; + background: #0D0764; + cursor: pointer; + transition: .1s all linear; } + [data-rangeslider]:hover::-webkit-slider-thumb { + width: 22px; + height: 22px; } + [data-rangeslider]:focus::-webkit-slider-thumb { + width: 26px; + height: 26px; + border-radius: 50px 50px 4px; + transform: rotate(45deg); + margin-bottom: 50px; } + +.select2 { + width: 100%; } + +.select2-container--bootstrap4 { + border: 1px solid #ced4da; + padding: 0.25em; + border-radius: .25rem; } + +.select2-container--bootstrap4.select2-container--disabled { + background-color: #e9ecef; + opacity: 1; } + +.select2-container--bootstrap4.select2-container--open .select2-selection .select2-selection__arrow b { + border-color: transparent transparent #6c757d transparent; + border-width: 0 0.45rem 0.45rem 0.45rem; } + +.select2-container--bootstrap4 .select2-selection--single .select2-selection__arrow { + position: absolute; + bottom: 0; + right: 0.375rem; + top: 0; + width: 0.85rem; } + +.select2-container--bootstrap4 .select2-selection--single .select2-selection__arrow b { + border-color: #6c757d transparent transparent transparent; + border-style: solid; + border-width: 0.45rem 0.45rem 0 0.45rem; + height: 0; + left: 0; + position: absolute; + top: 0; + bottom: 0; + width: 0; + border-radius: 4px; + margin: auto; } + +.select2-container--bootstrap4 .select2-search--dropdown .select2-search__field { + border-radius: 4px; + border: 1px solid #7777; } + +.select2-container--open .select2-dropdown.select2-dropdown--below { + top: -3px; + left: -1px; } + +.select2-container--open .select2-dropdown.select2-dropdown--above { + top: 1px; + left: -1px; } + +.select2-container--bootstrap4 .select2-dropdown { + border-color: #ced4da; } + +.select2-container--bootstrap4 .select2-results__option--highlighted[aria-selected] { + background-color: #5897fb; + color: white; } + +.kd-card { + position: relative; } + .kd-card.ghost { + -webkit-filter: grayscale(1); + filter: grayscale(1); + opacity: 0.4; } + .kd-card.gold .img-thumbnail { + border-image: linear-gradient(to bottom, rgba(255, 193, 7, 0.5), rgba(169, 116, 21, 0.5)); + border-image-slice: 1; } + .kd-card .img-thumbnail { + width: 100%; + padding: 1.25rem 2.14rem; + transition: all linear .15s; } + .kd-card a:hover .img-thumbnail { + border-color: #3e00ff; + box-shadow: inset 0 0 0px 2px #3e00ff; } + .kd-card .kd-name { + font-weight: 300; + padding: 0.5em; } + header .kd-card .kd-name { + color: white; } + .kd-card .kd-price { + position: absolute; + top: 0; + right: 0; + padding: 0.5em; } + +.kd-date { + font-size: 1.1rem; + color: #43484d; } + +.kd-shadow { + box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.1); } + +.kd-extended { + background: #fff; + border-radius: .25rem; + height: 100%; + overflow: hidden; } + .kd-extended:hover .content-hover, .kd-extended:active .content-hover, .kd-extended:focus .content-hover, .kd-extended:focus-within .content-hover { + display: flex; } + .kd-extended .img-thumbnail { + padding: 1.25rem 3.05rem; } + .kd-extended .kd-title { + font-size: 1.25rem; + padding: 0; } + +.kd-content { + font-size: 0.9rem; + padding: 1.3rem 2rem; } + .kd-content a { + color: #3e00ff; } + +.content-hover { + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + background: rgba(62, 0, 255, 0.8); + color: white; + padding: 1rem; + display: none; + overflow-y: auto; + flex-direction: column; } + .content-hover a { + color: white; + font-weight: 700; } + +.listing-kudo a { + color: #43484d; } + +.full-height { + min-height: 100vh; } + +.bg-dark-blue { + background-color: #0d023b; + color: white; } + +.bg-light-blue { + background-color: #3e00ff; + color: white; } + +.bg-cellarius { + background-color: #4D5858; } + +.lh-3 { + line-height: 3rem; } + +.cta-square { + display: flex; + width: 100%; + justify-content: center; + align-items: center; + border-radius: .25rem; + color: #fff; + background-color: #3e00ff; + font-size: 2em; } + .cta-square:after { + content: ' '; + padding-top: 100%; + display: table; } + .cta-square > div { + display: flex; + flex-direction: column; + padding: 0 0.6em 0; + line-height: 1.1; + align-self: stretch; + justify-content: space-evenly; } + .cta-square:hover { + color: rgba(255, 255, 255, 0.8); } + +#carouselkudos .carousel-inner { + width: 90%; + margin: auto; } + +.carousel-control-kudos .carousel-control-next, +.carousel-control-kudos .carousel-control-prev { + width: 3.3rem; + height: 3.3rem; + background: #0d023b; + top: 0; + bottom: 0; + margin: auto; + border-radius: 40px; } +.carousel-control-kudos .carousel-control-next-icon, +.carousel-control-kudos .carousel-control-prev-icon { + height: 34px; } +.carousel-control-kudos .carousel-control-prev-icon { + background-image: url("data:image/svg+xml,%0A%3Csvg width='19px' height='34px' viewBox='0 0 19 34' version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3E%3C!-- Generator: Sketch 50.2 %2855047%29 - http://www.bohemiancoding.com/sketch --%3E%3Cdesc%3ECreated with Sketch.%3C/desc%3E%3Cdefs%3E%3C/defs%3E%3Cg id='Symbols' stroke='none' stroke-width='1' fill='none' fill-rule='evenodd'%3E%3Cg id='Headers/Header-%239' transform='translate%28-101.000000, -638.000000%29' fill='%23C1C1C1'%3E%3Cpath d='M116.89675,671.709 L101.58275,656.405 C100.80575,655.629 100.80575,654.371 101.58275,653.595 L116.89675,638.291 C117.28475,637.903 117.91475,637.903 118.30275,638.291 L119.70875,639.696 C120.09675,640.084 120.09675,640.713 119.70875,641.101 L106.50275,654.297 C106.11475,654.685 106.11475,655.315 106.50275,655.702 L119.70875,668.899 C120.09675,669.287 120.09675,669.916 119.70875,670.304 L118.30275,671.709 C117.91475,672.097 117.28475,672.097 116.89675,671.709' id='Icon'%3E%3C/path%3E%3C/g%3E%3C/g%3E%3C/svg%3E"); } +.carousel-control-kudos .carousel-control-next-icon { + background-image: url("data:image/svg+xml,%0A%3Csvg width='19px' height='34px' viewBox='0 0 19 34' version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3E%3C!-- Generator: Sketch 50.2 %2855047%29 - http://www.bohemiancoding.com/sketch --%3E%3Cdesc%3ECreated with Sketch.%3C/desc%3E%3Cdefs%3E%3C/defs%3E%3Cg id='Symbols' stroke='none' stroke-width='1' fill='none' fill-rule='evenodd'%3E%3Cg id='Headers/Header-%239' transform='translate%28-1320.000000, -638.000000%29' fill='%23C1C1C1'%3E%3Cpath d='M1335.89675,671.709 L1320.58275,656.405 C1319.80575,655.629 1319.80575,654.371 1320.58275,653.595 L1335.89675,638.291 C1336.28475,637.903 1336.91475,637.903 1337.30275,638.291 L1338.70875,639.696 C1339.09675,640.084 1339.09675,640.713 1338.70875,641.101 L1325.50275,654.297 C1325.11475,654.685 1325.11475,655.315 1325.50275,655.702 L1338.70875,668.899 C1339.09675,669.287 1339.09675,669.916 1338.70875,670.304 L1337.30275,671.709 C1336.91475,672.097 1336.28475,672.097 1335.89675,671.709' id='Icon' transform='translate%281329.499875, 655.000000%29 scale%28-1, 1%29 translate%28-1329.499875, -655.000000%29 '%3E%3C/path%3E%3C/g%3E%3C/g%3E%3C/svg%3E"); } + +.wallet-popover { + max-width: 490px; } + +.wallets-list { + max-height: 140px; + overflow-y: auto; + background-color: #f3f3f3; } + +.wallets-list:empty { + display: none; } + +.btn-lightblue { + color: white; + background-color: var(--gc-blue); } + +.btn-orange { + background-color: #d38971; + color: white; + padding: .75rem 1.5rem; } + .btn-orange:hover { + color: white; + background-color: rgba(211, 137, 113, 0.9); } + +.hexagon { + background: red; + width: 10rem; + display: block; + margin: auto; + height: 11.56rem; + display: flex; + align-content: center; + justify-content: center; + align-items: center; + -webkit-clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%); + clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%); } + +a:hover #shape-hexagon { + animation-play-state: paused; } + +#shape-hexagon { + animation: rotation 5s linear infinite; + animation-fill-mode: none; + animation-direction: alternate; + animation-iteration-count: infinite; } + +@keyframes rotation { + 0% { + stroke: #0cc67f; + fill: rgba(12, 198, 127, 0.6); } + 15% { + stroke: #1e6ee2; + fill: rgba(30, 110, 226, 0.6); } + 30% { + stroke: #662d91; + fill: rgba(102, 45, 145, 0.6); } + 50% { + stroke: #018cb2; + fill: rgba(1, 140, 178, 0.6); } + 65% { + stroke: #e57418; + fill: rgba(229, 116, 24, 0.6); } + 85% { + stroke: #4d4d4d; + fill: rgba(77, 77, 77, 0.6); } + 100% { + stroke: #0044e0; + fill: rgba(0, 68, 224, 0.6); } } +.hexagon-group { + width: 100%; + display: flex; + flex-wrap: wrap; + justify-content: center; + margin: auto; + font-size: 16px; + padding-bottom: 3em; + display: grid; + grid-template-columns: repeat(4, 1fr); } + .hexagon-group svg { + height: 16.8em; + width: 14.4em; } + .hexagon-group svg text { + font-size: 1.1em; } + .hexagon-group .paging-animation { + font-size: 14px; + margin: 0.8em; + margin-bottom: -3em; + perspective: 1000px; + position: relative; + height: 208px; } + .hexagon-group .paging-animation .faces { + transform-style: preserve-3d; + transition: all 0.5s linear; + width: 100%; + height: 100%; } + .hexagon-group .paging-animation .face { + position: absolute; + width: 100%; + height: 100%; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; } + .hexagon-group .paging-animation .back { + display: block; + transform: rotateY(0.5turn); + box-sizing: border-box; } + .hexagon-group .paging-animation:hover .faces { + transform: rotateY(0.5turn); } + .hexagon-group .paging-animation:nth-child(1) { + color: #FF7200; + grid-column: 1/4; } + .hexagon-group .paging-animation:nth-child(2) { + color: #F9006C; + grid-column: 2/5; } + .hexagon-group .paging-animation:nth-child(3) { + color: #3E00FF; + grid-column: 1/4; } + .hexagon-group .paging-animation:nth-child(4) { + color: #0ECF7C; + grid-column: 2/5; } + .hexagon-group .paging-animation:nth-child(5) { + color: #7ED321; + grid-column: 1/4; } + .hexagon-group .paging-animation:nth-child(6) { + color: #8E2ABE; + grid-column: 2/5; } + .hexagon-group .paging-animation:nth-child(7) { + color: #43D0B0; + grid-column: 1/4; } + @media (min-width: 400px) { + .hexagon-group svg text { + font-size: 1.3em; } + .hexagon-group .paging-animation { + height: 260px; + font-size: 16px; } + .hexagon-group .paging-animation:nth-child(1) { + grid-column: 1/3; } + .hexagon-group .paging-animation:nth-child(2) { + grid-column: 2/4; } + .hexagon-group .paging-animation:nth-child(3) { + grid-column: 1/3; } + .hexagon-group .paging-animation:nth-child(4) { + grid-column: 3/5; } + .hexagon-group .paging-animation:nth-child(5) { + grid-column: 2/4; } + .hexagon-group .paging-animation:nth-child(6) { + grid-column: 1/3; } + .hexagon-group .paging-animation:nth-child(7) { + grid-column: 3/5; } } + @media (min-width: 800px) { + .hexagon-group { + grid-template-columns: repeat(8, 1fr); } + .hexagon-group .paging-animation:nth-child(1) { + grid-column: 1/3; } + .hexagon-group .paging-animation:nth-child(2) { + grid-column: 3/5; } + .hexagon-group .paging-animation:nth-child(3) { + grid-column: 5/7; } + .hexagon-group .paging-animation:nth-child(4) { + grid-column: 7/9; } + .hexagon-group .paging-animation:nth-child(5) { + grid-column: 2/4; } + .hexagon-group .paging-animation:nth-child(6) { + grid-column: 4/6; } + .hexagon-group .paging-animation:nth-child(7) { + grid-column: 6/8; } } + +.star-pulse { + animation: pulse-shadow .5s ease-out infinite; + animation-direction: alternate; + margin-left: -60px; + margin-top: 4rem; + top: 0; } + @media (max-width: 768px) { + .star-pulse { + right: -10px; + margin-top: 0; + width: 5rem; } } + +@keyframes pulse-shadow { + 0% { + transform: scale(0.98); + filter: drop-shadow(0px 0px 0px rgba(0, 0, 0, 0.9)); } + 100% { + transform: scale(1); + filter: drop-shadow(0px 5px 5px rgba(0, 0, 0, 0.5)); } } +.bg-hexa { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Cg stroke='none' stroke-width='1' fill='none' fill-rule='evenodd' opacity='0.187946429'%3E%3Cg transform='translate(-227.000000, -1170.000000)' stroke='%233E00FF' stroke-width='10'%3E%3Cg id='Group-5-Copy-7' transform='translate(294.737804, 1248.626588) rotate(-330.000000) translate(-294.737804, -1248.626588) translate(223.737804, 1186.126588)'%3E%3Cpolygon opacity='0.334877232' points='105.943991 0 35.3139974 0 9.09494702e-13 62.3980694 35.3139974 124.7941 105.943991 124.7941 141.259988 62.3980694'%3E%3C/polygon%3E%3C/g%3E%3C/g%3E%3C/g%3E%3C/svg%3E"); + background-position: 2rem 2rem; + background-repeat: no-repeat; } + +.text-featured { + font-size: 1.7rem; } + +.badge-kudos { + background-color: #D8EAFF; + color: #4A4A4A; + border-radius: 2px; + text-decoration: none; } + +#world { + z-index: -1; } + +a.cellarius-partner:before { + content: ''; + position: absolute; + right: 1rem; + bottom: 3rem; + width: 16%; + height: 16%; + background-size: cover; + background: url("/static/v2/images/kudos/assets/cellarius-logo.svg"); + background-repeat: no-repeat; } + +.cellarius-badge { + right: 1rem; + bottom: 3rem; + width: 16%; + height: 16%; + background-size: cover; + background: url("/static/v2/images/kudos/assets/cellarius-logo.svg"); + background-repeat: no-repeat; + background-color: #fff; + border-radius: 50px; } + +.kudos-details__title { + font-weight: 200; + font-size: 3.2rem; + margin-bottom: 0; } + +.kudos-details__subtitle { + font-size: 1rem; + font-weight: 700; + color: #0D0764; + border-bottom: 1px solid #C8C8C8; + padding-bottom: 0.8rem; + margin-bottom: 1rem; } + +.kudos-details__price { + font-size: 1.5rem; + font-weight: 700; } + .kudos-details__price small { + font-size: 1.25rem; + font-weight: 600; + color: #4A4A4A; } + +.kudos-details__address { + color: #3E00FF; } + +.text-color_blue { + color: #0D0764; } + +.text-weight_semibold { + font-weight: 600; } + +.tooltip-kudos .title-tooltip { + text-align: left; + display: block; + font-size: 14px; + color: #0ECF7C; + font-weight: 600; + line-height: 1.5; } +.tooltip-kudos .tooltip-inner { + width: 300px; + background-color: #0D0764; + font-size: 12px; + padding: 1rem; + max-width: 240px; } + .tooltip-kudos .tooltip-inner table { + width: 100%; } + +.author-shape { + -webkit-clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%); + clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%); } + +#kudos-image, .kudos_levitate_container { + cursor: pointer; } + +#kudos-image.shake { + animation: shake 0.82s cubic-bezier(0.36, 0.07, 0.19, 0.97) both; + transform: translate3d(0, 0, 0); + backface-visibility: hidden; + perspective: 1000px; } + +@keyframes shake { + 10%, 90% { + transform: translate3d(-1px, 0, 0); } + 20%, 80% { + transform: translate3d(2px, 0, 0); } + 30%, 50%, 70% { + transform: translate3d(-4px, 0, 0); } + 40%, 60% { + transform: translate3d(4px, 0, 0); } } +.kudos_msg { + margin-top: -90px; + display: none; + position: relative; + background-color: #3e00ff; + border-radius: 10px; + color: white; + padding: 3px 10px; + margin-bottom: 20px; } + +.kudos_msg:after { + content: ''; + position: absolute; + bottom: 0; + left: 50%; + width: 0; + height: 0; + border: 20px solid transparent; + border-top-color: #3e00ff; + border-bottom: 0; + border-left: 0; + margin-left: -10px; + margin-bottom: -20px; } + +/*# sourceMappingURL=styles.css.map */ diff --git a/app/assets/v2/css/kudos/styles.css.map b/app/assets/v2/css/kudos/styles.css.map new file mode 100644 index 00000000000..68ff31d95ba --- /dev/null +++ b/app/assets/v2/css/kudos/styles.css.map @@ -0,0 +1,7 @@ +{ +"version": 3, +"mappings": "AAAA,gBAAiB;EACf,SAAS,EAAE,KAAK;EAChB,MAAM,EAAE,IAAI;EACZ,UAAU,EAAE,IAAI;EAChB,OAAO,EAAE,CAAC;EACV,QAAQ,EAAE,QAAQ;EAClB,OAAO,EAAE,eAAe;;AAG1B,YAAa;EACX,gBAAgB,EAAE,OAAO;EACzB,gBAAgB,EAAG,yHAAyH;EAC5I,gBAAgB,EAAG,4HAA4H;EAC/I,gBAAgB,EAAG,wHAAwH;EAC3I,gBAAgB,EAAG,oHAAoH;EACvI,iBAAiB,EAAE,SAAS;EAC5B,eAAe,EAAE,KAAK;EACtB,mBAAmB,EAAE,aAAa;EAClC,qBAAqB,EAAE,KAAK;;AAG9B,UAAW;EACT,GAAG,EAAE,GAAG;EACR,KAAK,EAAE,IAAI;EACX,OAAO,EAAE,KAAK;EACd,gBAAgB,EAAE,OAAO;EACzB,KAAK,EAAE,KAAK;EACZ,QAAQ,EAAE,KAAK;EACf,UAAU,EAAE,MAAM;;AAGpB,eAAgB;EACd,gBAAgB,EAAE,OAAO;;AAG3B,UAAW;EACT,QAAQ,EAAE,QAAQ;EAClB,OAAO,EAAE,KAAK;EAEd,iBAAS;IACP,OAAO,EAAE,EAAE;IACX,OAAO,EAAE,KAAK;IACd,QAAQ,EAAE,QAAQ;IAClB,GAAG,EAAE,GAAG;IACR,IAAI,EAAE,IAAI;IACV,KAAK,EAAE,gBAAgB;IACvB,MAAM,EAAE,GAAG;IACX,OAAO,EAAE,EAAE;IACX,UAAU,EAAE,OAAO;;AAKrB,YAAE;EACA,KAAK,EAAE,KAAK;;ACpDhB,kBAAmB;EACf,kBAAkB,EAAE,IAAI;EACxB,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,GAAG;EACX,UAAU,EANP,OAAO;EAOV,OAAO,EAAE,IAAI;EACb,MAAM,EAAE,MAAM;EAEhB,wCAAwB;IACtB,kBAAkB,EAAE,IAAI;IACxB,UAAU,EAAE,IAAI;IAChB,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,IAAI;IACZ,aAAa,EAAE,IAAI;IACnB,UAAU,EAhBP,OAAO;IAiBV,MAAM,EAAE,OAAO;IACf,UAAU,EAAE,cAAc;EAG5B,8CAA8B;IAC5B,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,IAAI;EAEd,8CAA8B;IAC5B,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,IAAI;IACZ,aAAa,EAAE,aAAa;IAC5B,SAAS,EAAE,aAAa;IACxB,aAAa,EAAE,IAAI;;AC3BvB,QAAS;EACL,KAAK,EAAE,IAAI;;AAGf,8BAA+B;EAC3B,MAAM,EAAE,iBAAiB;EACzB,OAAO,EAAE,MAAM;EACf,aAAa,EAAE,MAAM;;AAGzB,0DAA2D;EACvD,gBAAgB,EAAE,OAAO;EACzB,OAAO,EAAE,CAAC;;AAGd,qGAAsG;EAClG,YAAY,EAAE,2CAAgD;EAC9D,YAAY,EAAE,yBAAyB;;AAG3C,mFAAoF;EAChF,QAAQ,EAAE,QAAQ;EAClB,MAAM,EAAE,CAAC;EACT,KAAK,EAAE,QAAQ;EACf,GAAG,EAAE,CAAC;EACN,KAAK,EAAE,OAAO;;AAGlB,qFAAsF;EAClF,YAAY,EAAE,2CAAgD;EAC9D,YAAY,EAAE,KAAK;EACnB,YAAY,EAAE,yBAAyB;EACvC,MAAM,EAAE,CAAC;EACT,IAAI,EAAE,CAAC;EACP,QAAQ,EAAE,QAAQ;EAClB,GAAG,EAAE,CAAC;EACN,MAAM,EAAE,CAAC;EACT,KAAK,EAAE,CAAC;EACR,aAAa,EAAE,GAAG;EAClB,MAAM,EAAE,IAAI;;AAGd,+EAAgF;EAC9E,aAAa,EAAE,GAAG;EAClB,MAAM,EAAE,eAAe;;AAG3B,kEAAmE;EAC9D,GAAG,EAAE,IAAI;EACT,IAAI,EAAE,IAAI;;AAGf,kEAAmE;EAC/D,GAAG,EAAE,GAAG;EACR,IAAI,EAAE,IAAI;;AAGb,gDAAiD;EAC7C,YAAY,EA5DH,OAAO;;AA+DpB,mFAAoF;EACnF,gBAAgB,EAAE,OAAO;EACzB,KAAK,EAAE,KAAK;;AC3Cd,QAAS;EACP,QAAQ,EAAE,QAAQ;EAElB,cAAQ;IACN,cAAc,EAAE,YAAY;IAC5B,MAAM,EAAE,YAAY;IACpB,OAAO,EAAE,GAAG;EAGd,4BAAsB;IACpB,YAAY,EAAE,2EAA2E;IACzF,kBAAkB,EAAE,CAAC;EAGvB,uBAAe;IACb,KAAK,EAAE,IAAI;IACX,OAAO,EAAE,eAAe;IACxB,UAAU,EAAE,eAAe;EAK3B,+BAAe;IACb,YAAY,EA5CR,OAAO;IA6CX,UAAU,EAAE,yBAA0B;EAI1C,iBAAS;IACP,WAAW,EAAE,GAAG;IAChB,OAAO,EAAE,KAAK;IAEd,wBAAS;MACP,KAAK,EAAE,KAAK;EAIhB,kBAAU;IACR,QAAQ,EAAE,QAAQ;IAClB,GAAG,EAAE,CAAC;IACN,KAAK,EAAE,CAAC;IACR,OAAO,EAAE,KAAK;;AAIlB,QAAS;EACP,SAAS,EAAE,MAAM;EACjB,KAAK,EAAE,OAAO;;AAGhB,UAAW;EACT,UAAU,EAAE,8BAA4B;;AAG1C,YAAa;EACX,UAAU,EAAE,IAAI;EAChB,aAAa,EAAE,MAAM;EACrB,MAAM,EAAE,IAAI;EACZ,QAAQ,EAAE,MAAM;EAMd,kJAAe;IACb,OAAO,EAAE,IAAI;EAIjB,2BAAe;IACb,OAAO,EAAE,eAAe;EAG1B,sBAAU;IACR,SAAS,EAAE,OAAO;IAClB,OAAO,EAAE,CAAC;;AAId,WAAY;EACV,SAAS,EAAE,MAAM;EACjB,OAAO,EAAE,WAAW;EAEpB,aAAE;IACA,KAAK,EAAE,OAAO;;AAIlB,cAAe;EACb,QAAQ,EAAE,QAAQ;EAClB,GAAG,EAAE,CAAC;EACN,MAAM,EAAE,CAAC;EACT,IAAI,EAAE,CAAC;EACP,KAAK,EAAE,CAAC;EACR,UAAU,EAAE,qBAAiB;EAC7B,KAAK,EAAE,KAAK;EACZ,OAAO,EAAE,IAAI;EACb,OAAO,EAAE,IAAI;EACb,UAAU,EAAC,IAAI;EACf,cAAc,EAAE,MAAM;EAGtB,gBAAE;IACA,KAAK,EAAE,KAAK;IACZ,WAAW,EAAE,GAAG;;AAMlB,eAAE;EACA,KAAK,EAAE,OAAO;;AAKlB,YAAa;EACX,UAAU,EAAE,KAAK;;AAGnB,aAAc;EACZ,gBAAgB,EA/IN,OAAO;EAgJjB,KAAK,EAAE,KAAK;;AAEd,cAAe;EACb,gBAAgB,EAlJR,OAAO;EAmJf,KAAK,EAAE,KAAK;;AAGd,aAAc;EACZ,gBAAgB,EAtJH,OAAO;;AAyJtB,KAAM;EACJ,WAAW,EAAE,IAAI;;AAGnB,WAAY;EArJV,OAAO,EAAE,IAAI;EACb,KAAK,EAAE,IAAI;EACX,eAAe,EAAE,MAAM;EACvB,WAAW,EAAE,MAAM;EAoJnB,aAAa,EAAE,MAAM;EACrB,KAAK,EAAE,IAAI;EACX,gBAAgB,EAlKR,OAAO;EAmKf,SAAS,EAAE,GAAG;EAtJd,iBAAQ;IACN,OAAO,EAAE,GAAG;IACZ,WAAW,EAAE,IAAI;IACjB,OAAO,EAAE,KAAK;EAqJhB,iBAAM;IACJ,OAAO,EAAE,IAAI;IACb,cAAc,EAAE,MAAM;IACtB,OAAO,EAAE,SAAS;IAClB,WAAW,EAAE,GAAG;IAChB,UAAU,EAAE,OAAO;IACnB,eAAe,EAAE,YAAY;EAG/B,iBAAQ;IACN,KAAK,EAAC,wBACR;;AAGF,8BAA+B;EAC7B,KAAK,EAAE,GAAG;EACV,MAAM,EAAE,IAAI;;AAGZ;8CACuB;EACrB,KAAK,EAAE,MAAM;EACb,MAAM,EAAE,MAAM;EACd,UAAU,EAAE,OAAO;EACnB,GAAG,EAAE,CAAC;EACN,MAAM,EAAE,CAAC;EACT,MAAM,EAAE,IAAI;EACZ,aAAa,EAAE,IAAI;AAGrB;mDAC4B;EAC1B,MAAM,EAAE,IAAI;AAEd,mDAA4B;EAC1B,gBAAgB,EAAE,ygCAAygC;AAE7hC,mDAA4B;EAC1B,gBAAgB,EAAE,ipCAAipC;;AAIvqC,eAAgB;EACd,SAAS,EAAE,KAAK;;AAGlB,aAAc;EACZ,UAAU,EAAE,KAAK;EACjB,UAAU,EAAE,IAAI;EAEhB,gBAAgB,EAAE,OAAO;;AAG3B,mBAAoB;EAClB,OAAO,EAAE,IAAI;;AAGf,cAAe;EACb,KAAK,EAAE,KAAK;EACZ,gBAAgB,EAAE,cAAc;;AAGlC,WAAY;EACV,gBAAgB,EAAE,OAAO;EACzB,KAAK,EAAE,KAAK;EACZ,OAAO,EAAE,aAAa;EAEtB,iBAAQ;IACN,KAAK,EAAE,KAAK;IACZ,gBAAgB,EAAE,wBAAiB;;AAIvC,QAAS;EACP,UAAU,EAAE,GAAG;EACf,KAAK,EAAE,KAAK;EACZ,OAAO,EAAE,KAAK;EACd,MAAM,EAAE,IAAI;EACZ,MAAM,EAAE,QAAQ;EAChB,OAAO,EAAE,IAAI;EACb,aAAa,EAAE,MAAM;EACrB,eAAe,EAAE,MAAM;EACvB,WAAW,EAAE,MAAM;EACnB,iBAAiB,EAAE,0DAElB;EAED,SAAS,EAAE,0DAEV;;AAQD,sBAAe;EACb,oBAAoB,EAAE,MAAM;;AAG9B,cAAe;EAEb,SAAS,EAAE,2BAA2B;EACtC,mBAAmB,EAAE,IAAI;EACzB,mBAAmB,EAAE,SAAS;EAC9B,yBAAyB,EAAE,QAAQ;;AAOvC,mBAuCC;EArCC,EAAG;IACD,MAAM,EAAC,OAAO;IACd,IAAI,EAAC,uBAAiB;EAExB,GAAI;IACF,MAAM,EAAC,OAAO;IACd,IAAI,EAAC,uBAAiB;EAExB,GAAI;IACF,MAAM,EAAC,OAAO;IACd,IAAI,EAAC,uBAAiB;EAExB,GAAI;IACF,MAAM,EAAC,OAAO;IACd,IAAI,EAAC,sBAAiB;EAExB,GAAI;IACF,MAAM,EAAC,OAAO;IACd,IAAI,EAAC,uBAAiB;EAExB,GAAI;IACF,MAAM,EAAC,OAAO;IACd,IAAI,EAAC,qBAAiB;EAExB,IAAK;IACH,MAAM,EAAC,OAAO;IACd,IAAI,EAAC,qBAAiB;AAe1B,cAAe;EACb,KAAK,EAAE,IAAI;EACX,OAAO,EAAE,IAAI;EACb,SAAS,EAAE,IAAI;EACf,eAAe,EAAE,MAAM;EACvB,MAAM,EAAE,IAAI;EACZ,SAAS,EAAE,IAAI;EACf,cAAc,EAAE,GAAG;EAEnB,OAAO,EAAE,IAAI;EACb,qBAAqB,EAAE,cAAc;EAIrC,kBAAI;IACF,MAAM,EAAE,MAAM;IACd,KAAK,EAAE,MAAM;IAEb,uBAAK;MACH,SAAS,EAAE,KAAK;EAKpB,gCAAkB;IAChB,SAAS,EAAE,IAAI;IACf,MAAM,EAAE,KAAK;IACb,aAAa,EAAE,IAAI;IAEnB,WAAW,EAAE,MAAM;IACnB,QAAQ,EAAE,QAAQ;IAClB,MAAM,EAAE,KAAK;IAEb,uCAAO;MACL,eAAe,EAAE,WAAW;MAC5B,UAAU,EAAE,eAAe;MAC3B,KAAK,EAAE,IAAI;MACX,MAAM,EAAE,IAAI;IAId,sCAAM;MACJ,QAAQ,EAAE,QAAQ;MAClB,KAAK,EAAE,IAAI;MACX,MAAM,EAAE,IAAI;MACZ,2BAA2B,EAAE,MAAM;MACnC,mBAAmB,EAAE,MAAM;IAG7B,sCAAM;MACJ,OAAO,EAAE,KAAK;MACd,SAAS,EAAE,gBAAgB;MAC3B,UAAU,EAAE,UAAU;IAIxB,6CAAc;MACZ,SAAS,EAAE,gBAAgB;IAG7B,6CAAe;MACb,KAAK,EAAE,OAAO;MACd,WAAW,EAAE,GAAG;IAGlB,6CAAe;MACb,KAAK,EAAE,OAAO;MACd,WAAW,EAAE,GAAG;IAGlB,6CAAe;MACb,KAAK,EAAE,OAAO;MACd,WAAW,EAAE,GAAG;IAGlB,6CAAe;MACb,KAAK,EAAE,OAAO;MACd,WAAW,EAAE,GAAG;IAGlB,6CAAe;MACb,KAAK,EAAE,OAAO;MACd,WAAW,EAAE,GAAG;IAGlB,6CAAe;MACb,KAAK,EAAE,OAAO;MACd,WAAW,EAAE,GAAG;IAGlB,6CAAe;MACb,KAAK,EAAE,OAAO;MACd,WAAW,EAAE,GAAG;EAIpB,yBAAyB;IAEvB,uBAAS;MACP,SAAS,EAAE,KAAK;IAElB,gCAAkB;MAChB,MAAM,EAAE,KAAK;MACb,SAAS,EAAE,IAAI;MAEf,6CAAe;QACb,WAAW,EAAE,GAAG;MAGlB,6CAAe;QACb,WAAW,EAAE,GAAG;MAGlB,6CAAe;QACb,WAAW,EAAE,GAAG;MAGlB,6CAAe;QACb,WAAW,EAAE,GAAG;MAGlB,6CAAe;QACb,WAAW,EAAE,GAAG;MAGlB,6CAAe;QACb,WAAW,EAAE,GAAG;MAGlB,6CAAe;QACb,WAAW,EAAE,GAAG;EAKtB,yBAAyB;IAvI3B,cAAe;MAwIX,qBAAqB,EAAE,cAAc;MAGnC,6CAAe;QACb,WAAW,EAAE,GAAG;MAGlB,6CAAe;QACb,WAAW,EAAE,GAAG;MAGlB,6CAAe;QACb,WAAW,EAAE,GAAG;MAGlB,6CAAe;QACb,WAAW,EAAE,GAAG;MAGlB,6CAAe;QACb,WAAW,EAAE,GAAG;MAGlB,6CAAe;QACb,WAAW,EAAE,GAAG;MAGlB,6CAAe;QACb,WAAW,EAAE,GAAG;;AAQxB,WAAY;EACV,SAAS,EAAE,kCAAkC;EAC7C,mBAAmB,EAAE,SAAS;EAC9B,WAAW,EAAE,KAAK;EAClB,UAAU,EAAE,IAAI;EAChB,GAAG,EAAE,CAAC;EAEN,yBAA0B;IAP5B,WAAY;MAQR,KAAK,EAAE,KAAK;MACZ,UAAU,EAAE,CAAC;MACb,KAAK,EAAE,IAAI;;AAGf,uBAUC;EATC,EAAG;IACD,SAAS,EAAE,WAAW;IACtB,MAAM,EAAE,2CAAwC;EAGlD,IAAK;IACH,SAAS,EAAE,QAAQ;IACnB,MAAM,EAAE,2CAAwC;AAIpD,QAAS;EACP,gBAAgB,EAAE,mnBAAmnB;EACroB,mBAAmB,EAAE,SAAS;EAC9B,iBAAiB,EAAE,SAAS;;AAG9B,cAAe;EACb,SAAS,EAAE,MAAM;;AAGnB,YAAa;EACX,gBAAgB,EAAE,OAAO;EACzB,KAAK,EAAE,OAAO;EACd,aAAa,EAAE,GAAG;EAClB,eAAe,EAAE,IAAI;;AAGvB,MAAO;EACL,OAAO,EAAE,EAAE;;AAGb,0BAA2B;EACzB,OAAO,EAAE,EAAE;EACX,QAAQ,EAAE,QAAQ;EAClB,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,IAAI;EACZ,KAAK,EAAE,GAAG;EACV,MAAM,EAAE,GAAG;EACX,eAAe,EAAE,KAAK;EACtB,UAAU,EAAE,wDAAwD;EACpE,iBAAiB,EAAE,SAAS;;AAG9B,gBAAiB;EACf,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,IAAI;EACZ,KAAK,EAAE,GAAG;EACV,MAAM,EAAE,GAAG;EACX,eAAe,EAAE,KAAK;EACtB,UAAU,EAAE,wDAAwD;EACpE,iBAAiB,EAAE,SAAS;EAC5B,gBAAgB,EAAE,IAAI;EACtB,aAAa,EAAC,IAAI;;AAIpB,qBAAsB;EACpB,WAAW,EAAE,GAAG;EAChB,SAAS,EAAE,MAAM;EACjB,aAAa,EAAE,CAAC;;AAGlB,wBAAyB;EACvB,SAAS,EAAE,IAAI;EACf,WAAW,EAAE,GAAG;EAChB,KAAK,EAAE,OAAO;EACd,aAAa,EAAE,iBAAiB;EAChC,cAAc,EAAE,MAAM;EACtB,aAAa,EAAE,IAAI;;AAGrB,qBAAsB;EACpB,SAAS,EAAE,MAAM;EACjB,WAAW,EAAE,GAAG;EAEhB,2BAAM;IACJ,SAAS,EAAE,OAAO;IAClB,WAAW,EAAE,GAAG;IAChB,KAAK,EAAE,OAAO;;AAIlB,uBAAwB;EACtB,KAAK,EAAE,OAAO;;AAGhB,gBAAiB;EACf,KAAK,EAAE,OAAO;;AAGhB,qBAAsB;EACpB,WAAW,EAAE,GAAG;;AAIhB,6BAAe;EACb,UAAU,EAAE,IAAI;EAChB,OAAO,EAAE,KAAK;EACd,SAAS,EAAE,IAAI;EACf,KAAK,EAAE,OAAO;EACd,WAAW,EAAE,GAAG;EAChB,WAAW,EAAE,GAAG;AAGlB,6BAAe;EACb,KAAK,EAAE,KAAK;EACZ,gBAAgB,EAAE,OAAO;EACzB,SAAS,EAAE,IAAI;EACf,OAAO,EAAE,IAAI;EACb,SAAS,EAAE,KAAK;EAEhB,mCAAM;IACJ,KAAK,EAAE,IAAI;;AAMjB,aAAc;EACZ,iBAAiB,EAAE,4DAA4D;EACjF,SAAS,EAAE,4DAA4D;;AAIvE,uCAAuC;EACrC,MAAM,EAAE,OAAO;;AAGjB,kBAAkB;EAChB,SAAS,EAAE,qDAA8C;EACzD,SAAS,EAAE,oBAAoB;EAC/B,mBAAmB,EAAE,MAAM;EAC3B,WAAW,EAAE,MAAM;;AAGrB,gBAgBC;EAfC,QAAS;IACP,SAAS,EAAE,uBAAuB;EAGpC,QAAS;IACP,SAAS,EAAE,sBAAsB;EAGnC,aAAc;IACZ,SAAS,EAAE,uBAAuB;EAGpC,QAAS;IACP,SAAS,EAAE,sBAAsB;AAIrC,UAAU;EACR,UAAU,EAAE,KAAK;EACjB,OAAO,EAAE,IAAI;EACb,QAAQ,EAAE,QAAQ;EAClB,gBAAgB,EAAE,OAAO;EACzB,aAAa,EAAE,IAAI;EACnB,KAAK,EAAE,KAAK;EACZ,OAAO,EAAE,QAAQ;EACjB,aAAa,EAAE,IAAI;;AAIrB,gBAAiB;EACf,OAAO,EAAE,EAAE;EACX,QAAQ,EAAE,QAAQ;EAClB,MAAM,EAAE,CAAC;EACT,IAAI,EAAE,GAAG;EACT,KAAK,EAAE,CAAC;EACR,MAAM,EAAE,CAAC;EACT,MAAM,EAAE,sBAAsB;EAC9B,gBAAgB,EAAE,OAAO;EACzB,aAAa,EAAE,CAAC;EAChB,WAAW,EAAE,CAAC;EACd,WAAW,EAAE,KAAK;EAClB,aAAa,EAAE,KAAK", +"sources": ["transaction.scss","range-slider.scss","select2.bootstrap4.scss","styles.scss"], +"names": [], +"file": "styles.css" +} \ No newline at end of file diff --git a/app/assets/v2/css/kudos/styles.scss b/app/assets/v2/css/kudos/styles.scss new file mode 100644 index 00000000000..d386992672a --- /dev/null +++ b/app/assets/v2/css/kudos/styles.scss @@ -0,0 +1,689 @@ +// VARS +$dark-blue: #0d023b; +$gc-blue: #3e00ff; +$bg-cellarius: #4D5858; + +@import 'transaction'; +@import 'range-slider'; +@import 'select2.bootstrap4'; + +// MIXINS +@mixin square() { + display: flex; + width: 100%; + justify-content: center; + align-items: center; + &:after { + content: ' '; + padding-top: 100%; + display: table; + } +} + +// CODE +.kd-card { + position: relative; + + &.ghost { + -webkit-filter: grayscale(1); + filter: grayscale(1); + opacity: 0.4; + } + + &.gold .img-thumbnail { + border-image: linear-gradient(to bottom, rgba(255, 193, 7, 0.5) , rgba(169, 116, 21, .5)); + border-image-slice: 1; + } + + .img-thumbnail { + width: 100%; + padding: 1.25rem 2.14rem; + transition: all linear .15s; + + } + + a:hover { + .img-thumbnail { + border-color: $gc-blue; + box-shadow: inset 0 0 0px 2px $gc-blue; + } + } + + .kd-name { + font-weight: 300; + padding: 0.5em; + + header & { + color: white; + } + } + + .kd-price { + position: absolute; + top: 0; + right: 0; + padding: 0.5em; + } +} + +.kd-date { + font-size: 1.1rem; + color: #43484d; +} + +.kd-shadow { + box-shadow: 1px 1px 2px rgba(0,0,0, 0.1); +} + +.kd-extended { + background: #fff; + border-radius: .25rem; + height: 100%; + overflow: hidden; + + &:hover, + &:active, + &:focus, + &:focus-within { + .content-hover { + display: flex; + } + } + + .img-thumbnail { + padding: 1.25rem 3.05rem; + } + + .kd-title { + font-size: 1.25rem; + padding: 0; + } +} + +.kd-content { + font-size: 0.9rem; + padding: 1.3rem 2rem; + + a { + color: #3e00ff; + } +} + +.content-hover { + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + background: rgba($gc-blue,.8); + color: white; + padding: 1rem; + display: none; + overflow-y:auto; + flex-direction: column; + // justify-content: space-between; + + a { + color: white; + font-weight: 700; + } +} + +.listing-kudo { + + a { + color: #43484d; + } +} + +// GENERAL +.full-height { + min-height: 100vh; +} + +.bg-dark-blue { + background-color: $dark-blue; + color: white; +} +.bg-light-blue { + background-color: $gc-blue; + color: white; +} + +.bg-cellarius { + background-color: $bg-cellarius; +} + +.lh-3 { + line-height: 3rem; +} + +.cta-square { + @include square; + border-radius: .25rem; + color: #fff; + background-color: $gc-blue; + font-size: 2em; + + > div { + display: flex; + flex-direction: column; + padding: 0 0.6em 0; + line-height: 1.1; + align-self: stretch; + justify-content: space-evenly; + } + + &:hover { + color:rgba(255,255,255, 0.8) + } +} + +#carouselkudos .carousel-inner { + width: 90%; + margin: auto; +} +.carousel-control-kudos { + .carousel-control-next, + .carousel-control-prev { + width: 3.3rem; + height: 3.3rem; + background: #0d023b; + top: 0; + bottom: 0; + margin: auto; + border-radius: 40px; + } + + .carousel-control-next-icon, + .carousel-control-prev-icon { + height: 34px; + } + .carousel-control-prev-icon { + background-image: url("data:image/svg+xml,%0A%3Csvg width='19px' height='34px' viewBox='0 0 19 34' version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3E%3C!-- Generator: Sketch 50.2 %2855047%29 - http://www.bohemiancoding.com/sketch --%3E%3Cdesc%3ECreated with Sketch.%3C/desc%3E%3Cdefs%3E%3C/defs%3E%3Cg id='Symbols' stroke='none' stroke-width='1' fill='none' fill-rule='evenodd'%3E%3Cg id='Headers/Header-%239' transform='translate%28-101.000000, -638.000000%29' fill='%23C1C1C1'%3E%3Cpath d='M116.89675,671.709 L101.58275,656.405 C100.80575,655.629 100.80575,654.371 101.58275,653.595 L116.89675,638.291 C117.28475,637.903 117.91475,637.903 118.30275,638.291 L119.70875,639.696 C120.09675,640.084 120.09675,640.713 119.70875,641.101 L106.50275,654.297 C106.11475,654.685 106.11475,655.315 106.50275,655.702 L119.70875,668.899 C120.09675,669.287 120.09675,669.916 119.70875,670.304 L118.30275,671.709 C117.91475,672.097 117.28475,672.097 116.89675,671.709' id='Icon'%3E%3C/path%3E%3C/g%3E%3C/g%3E%3C/svg%3E"); + } + .carousel-control-next-icon { + background-image: url("data:image/svg+xml,%0A%3Csvg width='19px' height='34px' viewBox='0 0 19 34' version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3E%3C!-- Generator: Sketch 50.2 %2855047%29 - http://www.bohemiancoding.com/sketch --%3E%3Cdesc%3ECreated with Sketch.%3C/desc%3E%3Cdefs%3E%3C/defs%3E%3Cg id='Symbols' stroke='none' stroke-width='1' fill='none' fill-rule='evenodd'%3E%3Cg id='Headers/Header-%239' transform='translate%28-1320.000000, -638.000000%29' fill='%23C1C1C1'%3E%3Cpath d='M1335.89675,671.709 L1320.58275,656.405 C1319.80575,655.629 1319.80575,654.371 1320.58275,653.595 L1335.89675,638.291 C1336.28475,637.903 1336.91475,637.903 1337.30275,638.291 L1338.70875,639.696 C1339.09675,640.084 1339.09675,640.713 1338.70875,641.101 L1325.50275,654.297 C1325.11475,654.685 1325.11475,655.315 1325.50275,655.702 L1338.70875,668.899 C1339.09675,669.287 1339.09675,669.916 1338.70875,670.304 L1337.30275,671.709 C1336.91475,672.097 1336.28475,672.097 1335.89675,671.709' id='Icon' transform='translate%281329.499875, 655.000000%29 scale%28-1, 1%29 translate%28-1329.499875, -655.000000%29 '%3E%3C/path%3E%3C/g%3E%3C/g%3E%3C/svg%3E"); + } +} + +.wallet-popover { + max-width: 490px; +} + +.wallets-list { + max-height: 140px; + overflow-y: auto; + // margin-top: 1rem; + background-color: #f3f3f3; +} + +.wallets-list:empty { + display: none; +} + +.btn-lightblue { + color: white; + background-color: var(--gc-blue); +} + +.btn-orange { + background-color: #d38971; + color: white; + padding: .75rem 1.5rem; + + &:hover { + color: white; + background-color: rgba(#d38971,0.9); + } +} + +.hexagon { + background: red; + width: 10rem; + display: block; + margin: auto; + height: 11.56rem; + display: flex; + align-content: center; + justify-content: center; + align-items: center; + -webkit-clip-path: polygon( + 50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25% + ); + + clip-path: polygon( + 50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25% + ); +} + + +#shape-hexagon { + // transition: all linear 1s; +} +a:hover { + #shape-hexagon { + animation-play-state: paused; + } +} + #shape-hexagon { + // stroke:red; + animation: rotation 5s linear infinite; + animation-fill-mode: none; + animation-direction: alternate; + animation-iteration-count: infinite; + + } + #svg-text { + + } + +@keyframes rotation { + // stroke-dasharray: 300 + 0% { + stroke:#0cc67f; + fill:rgba(#0cc67f,0.6); + } + 15% { + stroke:#1e6ee2; + fill:rgba(#1e6ee2,0.6); + } + 30% { + stroke:#662d91; + fill:rgba(#662d91,0.6); + } + 50% { + stroke:#018cb2; + fill:rgba(#018cb2,0.6); + } + 65% { + stroke:#e57418; + fill:rgba(#e57418,0.6); + } + 85% { + stroke:#4d4d4d; + fill:rgba(#4d4d4d,0.6); + } + 100% { + stroke:#0044e0; + fill:rgba(#0044e0,0.6); + } + // stroke:#1e6ee2; + // stroke:#662d91; + // stroke:#018cb2; + // stroke:#e57418; + // stroke:#4d4d4d; + // stroke:#0044e0; + // stroke-dasharray: 30 + // -webkit-transform: rotate(360deg); + // transform: rotate(360deg); +} + + + +.hexagon-group { + width: 100%; + display: flex; + flex-wrap: wrap; + justify-content: center; + margin: auto; + font-size: 16px; + padding-bottom: 3em; + + display: grid; + grid-template-columns: repeat(4, 1fr); + + + + svg { + height: 16.8em; + width: 14.4em; + + text { + font-size: 1.1em; + } + } + + + .paging-animation { + font-size: 14px; + margin: 0.8em; + margin-bottom: -3em; + // width: 22%; + perspective: 1000px; + position: relative; + height: 208px; + + .faces { + transform-style: preserve-3d; + transition: all 0.5s linear; + width: 100%; + height: 100%; + + } + + .face { + position: absolute; + width: 100%; + height: 100%; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + } + + .back { + display: block; + transform: rotateY(0.5turn); + box-sizing: border-box; + + } + + &:hover .faces{ + transform: rotateY(0.5turn); + } + + &:nth-child(1) { + color: #FF7200; + grid-column: 1/4; + } + + &:nth-child(2) { + color: #F9006C; + grid-column: 2/5; + } + + &:nth-child(3) { + color: #3E00FF; + grid-column: 1/4; + } + + &:nth-child(4) { + color: #0ECF7C; + grid-column: 2/5; + } + + &:nth-child(5) { + color: #7ED321; + grid-column: 1/4; + } + + &:nth-child(6) { + color: #8E2ABE; + grid-column: 2/5; + } + + &:nth-child(7) { + color: #43D0B0; + grid-column: 1/4; + } + } + + @media(min-width: 400px) { + + svg text { + font-size: 1.3em; + } + .paging-animation { + height: 260px; + font-size: 16px; + + &:nth-child(1) { + grid-column: 1/3; + } + + &:nth-child(2) { + grid-column: 2/4; + } + + &:nth-child(3) { + grid-column: 1/3; + } + + &:nth-child(4) { + grid-column: 3/5; + } + + &:nth-child(5) { + grid-column: 2/4; + } + + &:nth-child(6) { + grid-column: 1/3; + } + + &:nth-child(7) { + grid-column: 3/5; + } + } + } + + @media(min-width: 800px) { + grid-template-columns: repeat(8, 1fr); + .paging-animation { + // font-size: 16px; + &:nth-child(1) { + grid-column: 1/3; + } + + &:nth-child(2) { + grid-column: 3/5; + } + + &:nth-child(3) { + grid-column: 5/7; + } + + &:nth-child(4) { + grid-column: 7/9; + } + + &:nth-child(5) { + grid-column: 2/4; + } + + &:nth-child(6) { + grid-column: 4/6; + } + + &:nth-child(7) { + grid-column: 6/8; + } + } + } + +} + + +.star-pulse { + animation: pulse-shadow .5s ease-out infinite; + animation-direction: alternate; + margin-left: -60px; + margin-top: 4rem; + top: 0; + + @media (max-width: 768px) { + right: -10px; + margin-top: 0; + width: 5rem; + } +} +@keyframes pulse-shadow { + 0% { + transform: scale(0.98); + filter: drop-shadow(0px 0px 0px rgba(0,0,0,0.9)); + } + + 100% { + transform: scale(1); + filter: drop-shadow(0px 5px 5px rgba(0,0,0,0.5)); + } +} + +.bg-hexa { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Cg stroke='none' stroke-width='1' fill='none' fill-rule='evenodd' opacity='0.187946429'%3E%3Cg transform='translate(-227.000000, -1170.000000)' stroke='%233E00FF' stroke-width='10'%3E%3Cg id='Group-5-Copy-7' transform='translate(294.737804, 1248.626588) rotate(-330.000000) translate(-294.737804, -1248.626588) translate(223.737804, 1186.126588)'%3E%3Cpolygon opacity='0.334877232' points='105.943991 0 35.3139974 0 9.09494702e-13 62.3980694 35.3139974 124.7941 105.943991 124.7941 141.259988 62.3980694'%3E%3C/polygon%3E%3C/g%3E%3C/g%3E%3C/g%3E%3C/svg%3E"); + background-position: 2rem 2rem; + background-repeat: no-repeat; +} + +.text-featured { + font-size: 1.7rem; +} + +.badge-kudos { + background-color: #D8EAFF; + color: #4A4A4A; + border-radius: 2px; + text-decoration: none; +} + +#world { + z-index: -1; +} + +a.cellarius-partner:before { + content: ''; + position: absolute; + right: 1rem; + bottom: 3rem; + width: 16%; + height: 16%; + background-size: cover; + background: url('/static/v2/images/kudos/assets/cellarius-logo.svg'); + background-repeat: no-repeat; +} + +.cellarius-badge { + right: 1rem; + bottom: 3rem; + width: 16%; + height: 16%; + background-size: cover; + background: url('/static/v2/images/kudos/assets/cellarius-logo.svg'); + background-repeat: no-repeat; + background-color: #fff; + border-radius:50px; +} + +// Kudos details +.kudos-details__title { + font-weight: 200; + font-size: 3.2rem; + margin-bottom: 0; +} + +.kudos-details__subtitle { + font-size: 1rem; + font-weight: 700; + color: #0D0764; + border-bottom: 1px solid #C8C8C8; + padding-bottom: 0.8rem; + margin-bottom: 1rem; +} + +.kudos-details__price { + font-size: 1.5rem; + font-weight: 700; + + small { + font-size: 1.25rem; + font-weight: 600; + color: #4A4A4A; + } +} + +.kudos-details__address { + color: #3E00FF; +} + +.text-color_blue { + color: #0D0764; +} + +.text-weight_semibold { + font-weight: 600; +} + +.tooltip-kudos { + .title-tooltip { + text-align: left; + display: block; + font-size: 14px; + color: #0ECF7C; + font-weight: 600; + line-height: 1.5; + + } + .tooltip-inner { + width: 300px; + background-color: #0D0764; + font-size: 12px; + padding: 1rem; + max-width: 240px; + + table { + width: 100%; + } + + } +} + +.author-shape { + -webkit-clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%); +clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%); +} + +// kudos detail animations +#kudos-image, .kudos_levitate_container{ + cursor: pointer; +} + +#kudos-image.shake{ + animation: shake 0.82s cubic-bezier(.36,.07,.19,.97) both; + transform: translate3d(0, 0, 0); + backface-visibility: hidden; + perspective: 1000px; +} + +@keyframes shake { + 10%, 90% { + transform: translate3d(-1px, 0, 0); + } + + 20%, 80% { + transform: translate3d(2px, 0, 0); + } + + 30%, 50%, 70% { + transform: translate3d(-4px, 0, 0); + } + + 40%, 60% { + transform: translate3d(4px, 0, 0); + } +} + +.kudos_msg{ + margin-top: -90px; + display: none; + position: relative; + background-color: #3e00ff; + border-radius: 10px; + color: white; + padding: 3px 10px; + margin-bottom: 20px + +} + +.kudos_msg:after { + content: ''; + position: absolute; + bottom: 0; + left: 50%; + width: 0; + height: 0; + border: 20px solid transparent; + border-top-color: #3e00ff; + border-bottom: 0; + border-left: 0; + margin-left: -10px; + margin-bottom: -20px; +} diff --git a/app/assets/v2/css/kudos/transaction.scss b/app/assets/v2/css/kudos/transaction.scss new file mode 100644 index 00000000000..821b81f86bb --- /dev/null +++ b/app/assets/v2/css/kudos/transaction.scss @@ -0,0 +1,57 @@ +.box-transaction { + max-width: 35rem; + margin: auto; + background: #fff; + z-index: 2; + position: relative; + padding: 1em 3em 3em 3em; +} + +.transaction { + background-color: #0d023b; + background-image: -moz-linear-gradient(60deg, rgba(255, 165, 150, 0.5) 5%, rgba(0, 228, 255, 0.35)), url('/static/v2/images/header-bg.png'); + background-image: -webkit-linear-gradient(60deg, rgba(255, 165, 150, 0.5) 5%, rgba(0, 228, 255, 0.35)), url('/static/v2/images/header-bg.png'); + background-image: -ms-linear-gradient(60deg, rgba(255, 165, 150, 0.5) 5%, rgba(0, 228, 255, 0.35)), url('/static/v2/images/header-bg.png'); + background-image: linear-gradient(60deg, rgba(255, 165, 150, 0.5) 5%, rgba(0, 228, 255, 0.35)), url('/static/v2/images/header-bg.png'); + background-repeat: no-repeat; + background-size: cover; + background-position: center center; + background-attachment: fixed; +} + +.alert_msg { + top: 0px; + width: 100%; + z-index: 99999; + background-color: #f44336; + color: white; + position: fixed; + text-align: center; +} + +.alert_msg.info { + background-color: #2196F3; +} + +.line-back { + position: relative; + display: block; + + &:before { + content: ''; + display: block; + position: absolute; + top: 50%; + left: -3em; + width: calc(100% + 6em); + height: 1px; + z-index: -1; + background: #c8cccf; + } +} + +.copyright { + a { + color: white; + } +} \ No newline at end of file diff --git a/app/assets/v2/css/lib/typography.css b/app/assets/v2/css/lib/typography.css index 5d40aa7721e..87064aa0520 100644 --- a/app/assets/v2/css/lib/typography.css +++ b/app/assets/v2/css/lib/typography.css @@ -3,9 +3,45 @@ src: url('/static/v2/fonts/futura/font4.ttf')/* TTF file for CSS3 browsers */ } +/* muli-200 - latin */ @font-face { font-family: 'Muli'; - src: url('/static/v2/fonts/Muli/Regular.ttf'); + font-style: normal; + font-weight: 200; + src: local('Muli ExtraLight'), local('Muli-ExtraLight'), + url('/static/v2/fonts/muli/muli-v12-latin-200.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ + url('/static/v2/fonts/muli/muli-v12-latin-200.woff') format('woff'), /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ + url('/static/v2/fonts/muli/muli-v12-latin-200.ttf') format('truetype'); +} +/* muli-regular - latin */ +@font-face { + font-family: 'Muli'; + font-style: normal; + font-weight: 400; + src: local('Muli Regular'), local('Muli-Regular'), + url('/static/v2/fonts/muli/muli-v12-latin-regular.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ + url('/static/v2/fonts/muli/muli-v12-latin-regular.woff') format('woff'), /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ + url('/static/v2/fonts/muli/muli-v12-latin-regular.ttf') format('truetype'); +} +/* muli-600 - latin */ +@font-face { + font-family: 'Muli'; + font-style: normal; + font-weight: 600; + src: local('Muli SemiBold'), local('Muli-SemiBold'), + url('/static/v2/fonts/muli/muli-v12-latin-600.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ + url('/static/v2/fonts/muli/muli-v12-latin-600.woff') format('woff'), /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ + url('/static/v2/fonts/muli/muli-v12-latin-600.ttf') format('truetype'); +} +/* muli-700 - latin */ +@font-face { + font-family: 'Muli'; + font-style: normal; + font-weight: 700; + src: local('Muli Bold'), local('Muli-Bold'), + url('/static/v2/fonts/muli/muli-v12-latin-700.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ + url('/static/v2/fonts/muli/muli-v12-latin-700.woff') format('woff'), /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ + url('/static/v2/fonts/muli/muli-v12-latin-700.ttf') format('truetype'); } .g-font-futura { diff --git a/app/assets/v2/css/rain.css b/app/assets/v2/css/rain.css index b1760be2b88..a30350b2269 100644 --- a/app/assets/v2/css/rain.css +++ b/app/assets/v2/css/rain.css @@ -25,10 +25,14 @@ display: none; } +.transaction .rain { + position: fixed; +} + @media (min-width: 768px) { .rain { display: block; - } + } } .rain:nth-of-type(3n+0) { @@ -45,10 +49,10 @@ .rain.grey { background: rgba(241,225,255,0.2); -} +} -.rain.purple { - background-color: rgba(13,7,100, 0.2); +.rain.purple { + background-color: rgba(13,7,100, 0.2); } @-webkit-keyframes rains-fall { diff --git a/app/assets/v2/css/select2-kudos.css b/app/assets/v2/css/select2-kudos.css new file mode 100644 index 00000000000..4340a144bdd --- /dev/null +++ b/app/assets/v2/css/select2-kudos.css @@ -0,0 +1,140 @@ +:root { + --arrow-color: #6c757d; + --border-grey: #ced4da; + --border-blue: #0D0764; +} + +.select2 { + width: 100%; +} + +.select2-container--kudos { + border: 1px solid #ced4da; + padding: 0.25em; + border-radius: .25rem; +} + +.select2-container--kudos.select2-container--disabled { + background-color: #e9ecef; + opacity: 1; +} + +.select2-container--kudos .select2-selection--single .select2-selection__arrow b { + border-color: var(--arrow-color) transparent transparent transparent; + border-style: solid; + border-width: 0.45rem 0.45rem 0 0.45rem; + height: 0; + left: 0; + /* margin-top: -0.125rem; */ + position: absolute; + top: 0; + bottom: 0; + width: 0; + border-radius: 4px; + margin: auto; +} + +.select2-container--kudos.select2-container--open .select2-selection .select2-selection__arrow b { + border-color: transparent transparent var(--arrow-color) transparent; + border-width: 0 0.45rem 0.45rem 0.45rem; +} + +.select2-container--kudos .select2-selection--single { + min-height: 28px; + height: auto; + display: flex; +} + +.select2-container--kudos .select2-selection__placeholder { + vertical-align: middle; +} + +.select2-container--kudos .select2-selection--single .select2-selection__arrow { + position: absolute; + bottom: 0; + right: 0.375rem; + top: 0; + width: 0.85rem; +} + +.select2-container--kudos .select2-search--dropdown .select2-search__field { + border-radius: 4px; + border: 1px solid #7777; +} + +.select2-container--open .select2-dropdown.select2-dropdown--below { + top: -3px; + left: -1px; +} + +.select2-container--open .select2-dropdown.select2-dropdown--above { + top: 1px; + left: -1px; +} + +.select2-container--kudos .select2-dropdown { + /* border-color: var(--border-grey); */ +} + +.select2-container--kudos .select2-results__options { + max-height: 300px; + overflow-y: auto; +} + +.select2-container--kudos .select2-results__option { + font-size: 12px; + padding: 9px 6px; +} + +.select2-container--kudos .select2-results__option--highlighted[aria-selected] { + background-color: #F2F6F9; +} + +.select2-container--kudos .select2-selection--single .select2-selection__rendered { + /* display: flex; + justify-content: space-between; + align-items: center; + flex-basis: 100%; */ +} + +.select2-container--kudos .select2-selection--single .select2-selection__clear { + /* order: 1; + font-size: 20px; + line-height: 1; */ + + position: absolute; + bottom: 0; + right: 0.375rem; + top: 0; + width: 0.85rem; + font-size: 20px; + z-index: 100; +} + +.gc-border-blue + .select2-container--kudos, +.select2-container--kudos > .select2-dropdown { + border-color: var(--border-blue); +} + + +.kudos-name { + font-weight: 600; + font-size: 14px; +} + +.kudos-description { + color: #9B9B9B; +} + +.kudos-search-result a.more{ + float: right; +} +.kudos-search-result img{ + /* width: 50px; */ + height: 50px; +} +.kudos-search-result.kudos-search-result-large img{ + /* width: 100px; */ + height: 100px; +} + diff --git a/app/assets/v2/css/top-nav.css b/app/assets/v2/css/top-nav.css new file mode 100644 index 00000000000..125d12cafa3 --- /dev/null +++ b/app/assets/v2/css/top-nav.css @@ -0,0 +1,69 @@ +.top-nav { + color: #9E9E9E; + display: flex; + flex-wrap: wrap; + flex-shrink: 0; + background: #0D023B; + justify-content: space-around; + border-bottom: 1px solid rgba(255,255,255,0.3); + padding: 0.5rem 0; + font-size: 1rem; + line-height: 1.5; +} + + +.top-nav a { + padding: 0.6rem 1rem; +} + +.top-nav .link { + text-decoration: none; + color: #9E9E9E; +} + + +.top-nav a img { + filter: grayscale(1); + opacity: 0.6; + transition: all 0.2s linear; + height: 60px; +} + +@media (min-width: 768px) { + .top-nav { + flex: 1 0 45px; + background: black; + flex-direction: row; + align-items: center; + justify-content: center; + border: none; + padding: 0; + } + + .top-nav a img { + height: auto; + } +} +.top-nav a:hover img, +.top-nav a.selected img { + /* opacity: 1; */ +} + +.top-nav a:hover img { + filter: grayscale(0); + opacity: 1; +} +.navbar-toggler[aria-expanded="true"] .navbar-toggler-icon { + background-image: url("data:image/svg+xml,%0A%3Csvg width='30px' height='30px' viewBox='0 0 30 30' version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3E%3C!-- Generator: Sketch 51.2 (57519) - http://www.bohemiancoding.com/sketch --%3E%3Cdesc%3ECreated with Sketch.%3C/desc%3E%3Cdefs%3E%3C/defs%3E%3Cg id='Page-1' stroke='none' stroke-width='1' fill='none' fill-rule='evenodd'%3E%3Cg id='Artboard' transform='translate(-146.000000, -156.000000)' fill-rule='nonzero'%3E%3Cg id='download' transform='translate(77.000000, 45.000000)'%3E%3Cpath d='M73,118 L95,134 M73,134 L95,118' id='Shape-Copy-2' stroke-opacity='0.5' stroke='%23FFFFFF' stroke-width='2' stroke-linecap='round'%3E%3C/path%3E%3Crect id='Path' x='69' y='111' width='30' height='30'%3E%3C/rect%3E%3C/g%3E%3C/g%3E%3C/g%3E%3C/svg%3E"); +} + +.brand-hover .logo-animated { + display: none; +} +.brand-hover:hover .logo-animated { + display: block; +} +.brand-hover:hover .logo-static { + display: none; +} + diff --git a/app/assets/v2/fonts/Muli/Bold.ttf b/app/assets/v2/fonts/Muli/Bold.ttf deleted file mode 100755 index a1d70c4e962..00000000000 Binary files a/app/assets/v2/fonts/Muli/Bold.ttf and /dev/null differ diff --git a/app/assets/v2/fonts/Muli/BoldItalic.ttf b/app/assets/v2/fonts/Muli/BoldItalic.ttf deleted file mode 100755 index 4c50ab08b46..00000000000 Binary files a/app/assets/v2/fonts/Muli/BoldItalic.ttf and /dev/null differ diff --git a/app/assets/v2/fonts/Muli/ExtraLight.ttf b/app/assets/v2/fonts/Muli/ExtraLight.ttf deleted file mode 100755 index ad12000b257..00000000000 Binary files a/app/assets/v2/fonts/Muli/ExtraLight.ttf and /dev/null differ diff --git a/app/assets/v2/fonts/Muli/ExtraLightItalic.ttf b/app/assets/v2/fonts/Muli/ExtraLightItalic.ttf deleted file mode 100755 index dde2cd10bf8..00000000000 Binary files a/app/assets/v2/fonts/Muli/ExtraLightItalic.ttf and /dev/null differ diff --git a/app/assets/v2/fonts/Muli/Light.ttf b/app/assets/v2/fonts/Muli/Light.ttf deleted file mode 100755 index 0ffcfba2e8b..00000000000 Binary files a/app/assets/v2/fonts/Muli/Light.ttf and /dev/null differ diff --git a/app/assets/v2/fonts/Muli/LightItalic.ttf b/app/assets/v2/fonts/Muli/LightItalic.ttf deleted file mode 100755 index e8b3c3acf35..00000000000 Binary files a/app/assets/v2/fonts/Muli/LightItalic.ttf and /dev/null differ diff --git a/app/assets/v2/fonts/Muli/Regular.ttf b/app/assets/v2/fonts/Muli/Regular.ttf deleted file mode 100755 index 01313e90532..00000000000 Binary files a/app/assets/v2/fonts/Muli/Regular.ttf and /dev/null differ diff --git a/app/assets/v2/fonts/Muli/RegularItalic.ttf b/app/assets/v2/fonts/Muli/RegularItalic.ttf deleted file mode 100755 index 824ee71282b..00000000000 Binary files a/app/assets/v2/fonts/Muli/RegularItalic.ttf and /dev/null differ diff --git a/app/assets/v2/fonts/Muli/SemiBold.ttf b/app/assets/v2/fonts/Muli/SemiBold.ttf deleted file mode 100755 index dc27bcbe0d8..00000000000 Binary files a/app/assets/v2/fonts/Muli/SemiBold.ttf and /dev/null differ diff --git a/app/assets/v2/fonts/Muli/SemiBoldItalic.ttf b/app/assets/v2/fonts/Muli/SemiBoldItalic.ttf deleted file mode 100755 index 3ea891d55f8..00000000000 Binary files a/app/assets/v2/fonts/Muli/SemiBoldItalic.ttf and /dev/null differ diff --git a/app/assets/v2/fonts/muli/muli-v12-latin-200.eot b/app/assets/v2/fonts/muli/muli-v12-latin-200.eot new file mode 100644 index 00000000000..8c1335c5833 Binary files /dev/null and b/app/assets/v2/fonts/muli/muli-v12-latin-200.eot differ diff --git a/app/assets/v2/fonts/muli/muli-v12-latin-200.svg b/app/assets/v2/fonts/muli/muli-v12-latin-200.svg new file mode 100644 index 00000000000..de110a3d8ee --- /dev/null +++ b/app/assets/v2/fonts/muli/muli-v12-latin-200.svg @@ -0,0 +1,310 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/assets/v2/fonts/muli/muli-v12-latin-200.ttf b/app/assets/v2/fonts/muli/muli-v12-latin-200.ttf new file mode 100644 index 00000000000..baf81f3f9f9 Binary files /dev/null and b/app/assets/v2/fonts/muli/muli-v12-latin-200.ttf differ diff --git a/app/assets/v2/fonts/muli/muli-v12-latin-200.woff b/app/assets/v2/fonts/muli/muli-v12-latin-200.woff new file mode 100644 index 00000000000..b1abdda87d5 Binary files /dev/null and b/app/assets/v2/fonts/muli/muli-v12-latin-200.woff differ diff --git a/app/assets/v2/fonts/muli/muli-v12-latin-200.woff2 b/app/assets/v2/fonts/muli/muli-v12-latin-200.woff2 new file mode 100644 index 00000000000..12c58e9647e Binary files /dev/null and b/app/assets/v2/fonts/muli/muli-v12-latin-200.woff2 differ diff --git a/app/assets/v2/fonts/muli/muli-v12-latin-600.eot b/app/assets/v2/fonts/muli/muli-v12-latin-600.eot new file mode 100644 index 00000000000..5ce0d8f04d4 Binary files /dev/null and b/app/assets/v2/fonts/muli/muli-v12-latin-600.eot differ diff --git a/app/assets/v2/fonts/muli/muli-v12-latin-600.svg b/app/assets/v2/fonts/muli/muli-v12-latin-600.svg new file mode 100644 index 00000000000..77d31a12e46 --- /dev/null +++ b/app/assets/v2/fonts/muli/muli-v12-latin-600.svg @@ -0,0 +1,309 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/assets/v2/fonts/muli/muli-v12-latin-600.ttf b/app/assets/v2/fonts/muli/muli-v12-latin-600.ttf new file mode 100644 index 00000000000..e3fa78d637b Binary files /dev/null and b/app/assets/v2/fonts/muli/muli-v12-latin-600.ttf differ diff --git a/app/assets/v2/fonts/muli/muli-v12-latin-600.woff b/app/assets/v2/fonts/muli/muli-v12-latin-600.woff new file mode 100644 index 00000000000..82534d6795d Binary files /dev/null and b/app/assets/v2/fonts/muli/muli-v12-latin-600.woff differ diff --git a/app/assets/v2/fonts/muli/muli-v12-latin-600.woff2 b/app/assets/v2/fonts/muli/muli-v12-latin-600.woff2 new file mode 100644 index 00000000000..797ce473d9d Binary files /dev/null and b/app/assets/v2/fonts/muli/muli-v12-latin-600.woff2 differ diff --git a/app/assets/v2/fonts/muli/muli-v12-latin-700.eot b/app/assets/v2/fonts/muli/muli-v12-latin-700.eot new file mode 100644 index 00000000000..d49849317c9 Binary files /dev/null and b/app/assets/v2/fonts/muli/muli-v12-latin-700.eot differ diff --git a/app/assets/v2/fonts/muli/muli-v12-latin-700.svg b/app/assets/v2/fonts/muli/muli-v12-latin-700.svg new file mode 100644 index 00000000000..32bac76a2a4 --- /dev/null +++ b/app/assets/v2/fonts/muli/muli-v12-latin-700.svg @@ -0,0 +1,308 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/assets/v2/fonts/muli/muli-v12-latin-700.ttf b/app/assets/v2/fonts/muli/muli-v12-latin-700.ttf new file mode 100644 index 00000000000..b3ec4d97760 Binary files /dev/null and b/app/assets/v2/fonts/muli/muli-v12-latin-700.ttf differ diff --git a/app/assets/v2/fonts/muli/muli-v12-latin-700.woff b/app/assets/v2/fonts/muli/muli-v12-latin-700.woff new file mode 100644 index 00000000000..46bf34a8e1e Binary files /dev/null and b/app/assets/v2/fonts/muli/muli-v12-latin-700.woff differ diff --git a/app/assets/v2/fonts/muli/muli-v12-latin-700.woff2 b/app/assets/v2/fonts/muli/muli-v12-latin-700.woff2 new file mode 100644 index 00000000000..feba72d965a Binary files /dev/null and b/app/assets/v2/fonts/muli/muli-v12-latin-700.woff2 differ diff --git a/app/assets/v2/fonts/muli/muli-v12-latin-regular.eot b/app/assets/v2/fonts/muli/muli-v12-latin-regular.eot new file mode 100644 index 00000000000..fe3eb74c3c2 Binary files /dev/null and b/app/assets/v2/fonts/muli/muli-v12-latin-regular.eot differ diff --git a/app/assets/v2/fonts/muli/muli-v12-latin-regular.svg b/app/assets/v2/fonts/muli/muli-v12-latin-regular.svg new file mode 100644 index 00000000000..384c0cc0ea3 --- /dev/null +++ b/app/assets/v2/fonts/muli/muli-v12-latin-regular.svg @@ -0,0 +1,310 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/assets/v2/fonts/muli/muli-v12-latin-regular.ttf b/app/assets/v2/fonts/muli/muli-v12-latin-regular.ttf new file mode 100644 index 00000000000..0753befd327 Binary files /dev/null and b/app/assets/v2/fonts/muli/muli-v12-latin-regular.ttf differ diff --git a/app/assets/v2/fonts/muli/muli-v12-latin-regular.woff b/app/assets/v2/fonts/muli/muli-v12-latin-regular.woff new file mode 100644 index 00000000000..798ef0cb2a0 Binary files /dev/null and b/app/assets/v2/fonts/muli/muli-v12-latin-regular.woff differ diff --git a/app/assets/v2/fonts/muli/muli-v12-latin-regular.woff2 b/app/assets/v2/fonts/muli/muli-v12-latin-regular.woff2 new file mode 100644 index 00000000000..f81ba6ba827 Binary files /dev/null and b/app/assets/v2/fonts/muli/muli-v12-latin-regular.woff2 differ diff --git a/app/assets/v2/images/avatar/Accessories/HatShort-cowboy.svg b/app/assets/v2/images/avatar/Accessories/HatShort-cowboy.svg index 8dbf4476c64..b9cff125b46 100644 --- a/app/assets/v2/images/avatar/Accessories/HatShort-cowboy.svg +++ b/app/assets/v2/images/avatar/Accessories/HatShort-cowboy.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/assets/v2/images/avatar/Accessories/Masks-gitcoinbot.svg b/app/assets/v2/images/avatar/Accessories/Masks-gitcoinbot.svg index 8a5ed7ea6e0..aaa7632ff84 100644 --- a/app/assets/v2/images/avatar/Accessories/Masks-gitcoinbot.svg +++ b/app/assets/v2/images/avatar/Accessories/Masks-gitcoinbot.svg @@ -1 +1,34 @@ - \ No newline at end of file + + + + Artboard + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/assets/v2/images/avatar/Accessories/Masks-guy-fawkes.svg b/app/assets/v2/images/avatar/Accessories/Masks-guy-fawkes.svg index 2737b09e69d..9b54a98a668 100644 --- a/app/assets/v2/images/avatar/Accessories/Masks-guy-fawkes.svg +++ b/app/assets/v2/images/avatar/Accessories/Masks-guy-fawkes.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/assets/v2/images/avatar/Accessories/Masks-jack-o-lantern-lighted.svg b/app/assets/v2/images/avatar/Accessories/Masks-jack-o-lantern-lighted.svg index 1c8e7e451e8..e66565a7b29 100644 --- a/app/assets/v2/images/avatar/Accessories/Masks-jack-o-lantern-lighted.svg +++ b/app/assets/v2/images/avatar/Accessories/Masks-jack-o-lantern-lighted.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/assets/v2/images/avatar/Clothing/spacecadet-4242F4.svg b/app/assets/v2/images/avatar/Clothing/spacecadet-4242F4.svg index 8b2c8d4b680..ca6f4621d72 100644 --- a/app/assets/v2/images/avatar/Clothing/spacecadet-4242F4.svg +++ b/app/assets/v2/images/avatar/Clothing/spacecadet-4242F4.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/assets/v2/images/avatar/Clothing/spacecadet-F48914.svg b/app/assets/v2/images/avatar/Clothing/spacecadet-F48914.svg index db320b7880c..fc23d534a7a 100644 --- a/app/assets/v2/images/avatar/Clothing/spacecadet-F48914.svg +++ b/app/assets/v2/images/avatar/Clothing/spacecadet-F48914.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/assets/v2/images/avatar/Clothing/suit-4242F4.svg b/app/assets/v2/images/avatar/Clothing/suit-4242F4.svg index 5ac21b1c2ba..b3ff3b44020 100644 --- a/app/assets/v2/images/avatar/Clothing/suit-4242F4.svg +++ b/app/assets/v2/images/avatar/Clothing/suit-4242F4.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/assets/v2/images/avatar/Clothing/suit-43B9F9.svg b/app/assets/v2/images/avatar/Clothing/suit-43B9F9.svg index 77c5ad69fa1..c966fbadb37 100644 --- a/app/assets/v2/images/avatar/Clothing/suit-43B9F9.svg +++ b/app/assets/v2/images/avatar/Clothing/suit-43B9F9.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/assets/v2/images/avatar/Clothing/suit-684A23.svg b/app/assets/v2/images/avatar/Clothing/suit-684A23.svg index ac7d11a7f15..26df2c2d84e 100644 --- a/app/assets/v2/images/avatar/Clothing/suit-684A23.svg +++ b/app/assets/v2/images/avatar/Clothing/suit-684A23.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/assets/v2/images/avatar/Clothing/suit-CCCCCC.svg b/app/assets/v2/images/avatar/Clothing/suit-CCCCCC.svg index 0f7157f6c3c..c35386e9edd 100644 --- a/app/assets/v2/images/avatar/Clothing/suit-CCCCCC.svg +++ b/app/assets/v2/images/avatar/Clothing/suit-CCCCCC.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/assets/v2/images/avatar/Clothing/suit-F48914.svg b/app/assets/v2/images/avatar/Clothing/suit-F48914.svg index bc05e5128ba..288a88250f5 100644 --- a/app/assets/v2/images/avatar/Clothing/suit-F48914.svg +++ b/app/assets/v2/images/avatar/Clothing/suit-F48914.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/assets/v2/images/avatar/Clothing/suit-FFCC3B.svg b/app/assets/v2/images/avatar/Clothing/suit-FFCC3B.svg index ecf3275becd..843054332e1 100644 --- a/app/assets/v2/images/avatar/Clothing/suit-FFCC3B.svg +++ b/app/assets/v2/images/avatar/Clothing/suit-FFCC3B.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/assets/v2/images/emails/email-kudos.png b/app/assets/v2/images/emails/email-kudos.png new file mode 100644 index 00000000000..3ff33b7ffe3 Binary files /dev/null and b/app/assets/v2/images/emails/email-kudos.png differ diff --git a/app/assets/v2/images/emails/generic-kudos.png b/app/assets/v2/images/emails/generic-kudos.png new file mode 100644 index 00000000000..0c2da00420f Binary files /dev/null and b/app/assets/v2/images/emails/generic-kudos.png differ diff --git a/app/assets/v2/images/emails/kudos-group.png b/app/assets/v2/images/emails/kudos-group.png new file mode 100644 index 00000000000..fbc7b284817 Binary files /dev/null and b/app/assets/v2/images/emails/kudos-group.png differ diff --git a/app/assets/v2/images/emails/kudos-logo.png b/app/assets/v2/images/emails/kudos-logo.png new file mode 100644 index 00000000000..046588cf43d Binary files /dev/null and b/app/assets/v2/images/emails/kudos-logo.png differ diff --git a/app/assets/v2/images/emails/kudos-transfer.jpg b/app/assets/v2/images/emails/kudos-transfer.jpg new file mode 100644 index 00000000000..d5a06dc1dd6 Binary files /dev/null and b/app/assets/v2/images/emails/kudos-transfer.jpg differ diff --git a/app/assets/v2/images/grow_open_source_new.png b/app/assets/v2/images/grow_open_source_new.png index 10f1444b2ff..b484eccf514 100644 Binary files a/app/assets/v2/images/grow_open_source_new.png and b/app/assets/v2/images/grow_open_source_new.png differ diff --git a/app/assets/v2/images/kudos-flower.gif b/app/assets/v2/images/kudos-flower.gif new file mode 100644 index 00000000000..6f8f2194cdf Binary files /dev/null and b/app/assets/v2/images/kudos-flower.gif differ diff --git a/app/assets/v2/images/kudos/a_genius.svg b/app/assets/v2/images/kudos/a_genius.svg new file mode 100644 index 00000000000..1d76f35ff36 --- /dev/null +++ b/app/assets/v2/images/kudos/a_genius.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/above_and_beyond.svg b/app/assets/v2/images/kudos/above_and_beyond.svg new file mode 100644 index 00000000000..4e44ee452af --- /dev/null +++ b/app/assets/v2/images/kudos/above_and_beyond.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/always_shipping.svg b/app/assets/v2/images/kudos/always_shipping.svg new file mode 100644 index 00000000000..7e56d2b1184 --- /dev/null +++ b/app/assets/v2/images/kudos/always_shipping.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/angular_royalty.svg b/app/assets/v2/images/kudos/angular_royalty.svg new file mode 100644 index 00000000000..ce2caf2ff1e --- /dev/null +++ b/app/assets/v2/images/kudos/angular_royalty.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/app_dev_all_star.svg b/app/assets/v2/images/kudos/app_dev_all_star.svg new file mode 100644 index 00000000000..cb2c00be4e9 --- /dev/null +++ b/app/assets/v2/images/kudos/app_dev_all_star.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/arts_and_farts.svg b/app/assets/v2/images/kudos/arts_and_farts.svg new file mode 100644 index 00000000000..f14b432b455 --- /dev/null +++ b/app/assets/v2/images/kudos/arts_and_farts.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/assets/cellarius-logo.png b/app/assets/v2/images/kudos/assets/cellarius-logo.png new file mode 100644 index 00000000000..1f8e955871f Binary files /dev/null and b/app/assets/v2/images/kudos/assets/cellarius-logo.png differ diff --git a/app/assets/v2/images/kudos/assets/cellarius-logo.svg b/app/assets/v2/images/kudos/assets/cellarius-logo.svg new file mode 100644 index 00000000000..0102b37e7ae --- /dev/null +++ b/app/assets/v2/images/kudos/assets/cellarius-logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/assets/cellarius_logo_horizontal.svg b/app/assets/v2/images/kudos/assets/cellarius_logo_horizontal.svg new file mode 100644 index 00000000000..1ebef279bb0 --- /dev/null +++ b/app/assets/v2/images/kudos/assets/cellarius_logo_horizontal.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/assets/empty-kudos-desktop.svg b/app/assets/v2/images/kudos/assets/empty-kudos-desktop.svg new file mode 100644 index 00000000000..02754ba9f84 --- /dev/null +++ b/app/assets/v2/images/kudos/assets/empty-kudos-desktop.svg @@ -0,0 +1 @@ +Unique collectible artworkShowcase special skills & talentsBought & sold on the Kudos MarketplaceShow appreciation/ collaborationGifted by another Gitcoin memberminted on the blockchainERC-721 \ No newline at end of file diff --git a/app/assets/v2/images/kudos/assets/empty-kudos.svg b/app/assets/v2/images/kudos/assets/empty-kudos.svg new file mode 100644 index 00000000000..64abaf661bd --- /dev/null +++ b/app/assets/v2/images/kudos/assets/empty-kudos.svg @@ -0,0 +1 @@ +Unique collectible artworkGifted by another Gitcoin memberERC-721 \ No newline at end of file diff --git a/app/assets/v2/images/kudos/assets/erc-721.svg b/app/assets/v2/images/kudos/assets/erc-721.svg new file mode 100644 index 00000000000..e61a5dc477d --- /dev/null +++ b/app/assets/v2/images/kudos/assets/erc-721.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/assets/how-get.svg b/app/assets/v2/images/kudos/assets/how-get.svg new file mode 100644 index 00000000000..db307516278 --- /dev/null +++ b/app/assets/v2/images/kudos/assets/how-get.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/assets/kudos-diamond.svg b/app/assets/v2/images/kudos/assets/kudos-diamond.svg new file mode 100644 index 00000000000..901244190c4 --- /dev/null +++ b/app/assets/v2/images/kudos/assets/kudos-diamond.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/assets/kudos-image.png b/app/assets/v2/images/kudos/assets/kudos-image.png new file mode 100644 index 00000000000..601c32d91cf Binary files /dev/null and b/app/assets/v2/images/kudos/assets/kudos-image.png differ diff --git a/app/assets/v2/images/kudos/assets/no-kudos.gif b/app/assets/v2/images/kudos/assets/no-kudos.gif new file mode 100644 index 00000000000..865b7d6a99a Binary files /dev/null and b/app/assets/v2/images/kudos/assets/no-kudos.gif differ diff --git a/app/assets/v2/images/kudos/assets/octavian.jpg b/app/assets/v2/images/kudos/assets/octavian.jpg new file mode 100644 index 00000000000..f3864188ee8 Binary files /dev/null and b/app/assets/v2/images/kudos/assets/octavian.jpg differ diff --git a/app/assets/v2/images/kudos/assets/send-kudos.png b/app/assets/v2/images/kudos/assets/send-kudos.png new file mode 100644 index 00000000000..cecb4bbea8e Binary files /dev/null and b/app/assets/v2/images/kudos/assets/send-kudos.png differ diff --git a/app/assets/v2/images/kudos/assets/star.png b/app/assets/v2/images/kudos/assets/star.png new file mode 100644 index 00000000000..c9c86263773 Binary files /dev/null and b/app/assets/v2/images/kudos/assets/star.png differ diff --git a/app/assets/v2/images/kudos/backend_star.svg b/app/assets/v2/images/kudos/backend_star.svg new file mode 100644 index 00000000000..e81ed7de0c5 --- /dev/null +++ b/app/assets/v2/images/kudos/backend_star.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/bee_of_all_trades.svg b/app/assets/v2/images/kudos/bee_of_all_trades.svg new file mode 100644 index 00000000000..19469b04cf5 --- /dev/null +++ b/app/assets/v2/images/kudos/bee_of_all_trades.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/birds.svg b/app/assets/v2/images/kudos/birds.svg new file mode 100644 index 00000000000..0b35ef3ff58 --- /dev/null +++ b/app/assets/v2/images/kudos/birds.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/blockchain_star.svg b/app/assets/v2/images/kudos/blockchain_star.svg new file mode 100644 index 00000000000..23f7511fe24 --- /dev/null +++ b/app/assets/v2/images/kudos/blockchain_star.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/blockchain_the_world.svg b/app/assets/v2/images/kudos/blockchain_the_world.svg new file mode 100644 index 00000000000..c4c0613d4da --- /dev/null +++ b/app/assets/v2/images/kudos/blockchain_the_world.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/blockchain_utopia.svg b/app/assets/v2/images/kudos/blockchain_utopia.svg new file mode 100644 index 00000000000..37b39b12759 --- /dev/null +++ b/app/assets/v2/images/kudos/blockchain_utopia.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/blockchain_world.svg b/app/assets/v2/images/kudos/blockchain_world.svg new file mode 100644 index 00000000000..f1ccf84a611 --- /dev/null +++ b/app/assets/v2/images/kudos/blockchain_world.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/bug_squasher.svg b/app/assets/v2/images/kudos/bug_squasher.svg new file mode 100644 index 00000000000..2e953cd5929 --- /dev/null +++ b/app/assets/v2/images/kudos/bug_squasher.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/bug_squasher_new.svg b/app/assets/v2/images/kudos/bug_squasher_new.svg new file mode 100644 index 00000000000..bccea64b953 --- /dev/null +++ b/app/assets/v2/images/kudos/bug_squasher_new.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/builder_of_a_better_world.svg b/app/assets/v2/images/kudos/builder_of_a_better_world.svg new file mode 100644 index 00000000000..adfcb9324aa --- /dev/null +++ b/app/assets/v2/images/kudos/builder_of_a_better_world.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/business_minded.svg b/app/assets/v2/images/kudos/business_minded.svg new file mode 100644 index 00000000000..c6720525b3c --- /dev/null +++ b/app/assets/v2/images/kudos/business_minded.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/c++_scientist.svg b/app/assets/v2/images/kudos/c++_scientist.svg new file mode 100644 index 00000000000..bd424ebc997 --- /dev/null +++ b/app/assets/v2/images/kudos/c++_scientist.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/c_debugger.svg b/app/assets/v2/images/kudos/c_debugger.svg new file mode 100644 index 00000000000..dc3478de894 --- /dev/null +++ b/app/assets/v2/images/kudos/c_debugger.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/c_sharp_programmer.svg b/app/assets/v2/images/kudos/c_sharp_programmer.svg new file mode 100644 index 00000000000..50d851c0763 --- /dev/null +++ b/app/assets/v2/images/kudos/c_sharp_programmer.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/cellarius/Burst.svg b/app/assets/v2/images/kudos/cellarius/Burst.svg new file mode 100755 index 00000000000..fa120d07ac0 --- /dev/null +++ b/app/assets/v2/images/kudos/cellarius/Burst.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/cellarius/Circle.svg b/app/assets/v2/images/kudos/cellarius/Circle.svg new file mode 100755 index 00000000000..588d9a650c0 --- /dev/null +++ b/app/assets/v2/images/kudos/cellarius/Circle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/cellarius/Diamond.svg b/app/assets/v2/images/kudos/cellarius/Diamond.svg new file mode 100755 index 00000000000..c7f6d72aa10 --- /dev/null +++ b/app/assets/v2/images/kudos/cellarius/Diamond.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/cellarius/Infinite.svg b/app/assets/v2/images/kudos/cellarius/Infinite.svg new file mode 100755 index 00000000000..8391df6ce8e --- /dev/null +++ b/app/assets/v2/images/kudos/cellarius/Infinite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/cellarius/Spaghetti.svg b/app/assets/v2/images/kudos/cellarius/Spaghetti.svg new file mode 100755 index 00000000000..e97b624e95a --- /dev/null +++ b/app/assets/v2/images/kudos/cellarius/Spaghetti.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/cellarius/Triangle.svg b/app/assets/v2/images/kudos/cellarius/Triangle.svg new file mode 100755 index 00000000000..65f4d19a3b1 --- /dev/null +++ b/app/assets/v2/images/kudos/cellarius/Triangle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/cellarius/backend_architect.svg b/app/assets/v2/images/kudos/cellarius/backend_architect.svg new file mode 100755 index 00000000000..82fd5df1e6d --- /dev/null +++ b/app/assets/v2/images/kudos/cellarius/backend_architect.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/cellarius/bug_eliminator.svg b/app/assets/v2/images/kudos/cellarius/bug_eliminator.svg new file mode 100755 index 00000000000..0651ce09f9a --- /dev/null +++ b/app/assets/v2/images/kudos/cellarius/bug_eliminator.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/cellarius/bug_finder.svg b/app/assets/v2/images/kudos/cellarius/bug_finder.svg new file mode 100755 index 00000000000..98acb5e96ca --- /dev/null +++ b/app/assets/v2/images/kudos/cellarius/bug_finder.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/cellarius/cellarius/Burst.svg b/app/assets/v2/images/kudos/cellarius/cellarius/Burst.svg new file mode 100755 index 00000000000..fa120d07ac0 --- /dev/null +++ b/app/assets/v2/images/kudos/cellarius/cellarius/Burst.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/cellarius/cellarius/Circle.svg b/app/assets/v2/images/kudos/cellarius/cellarius/Circle.svg new file mode 100755 index 00000000000..588d9a650c0 --- /dev/null +++ b/app/assets/v2/images/kudos/cellarius/cellarius/Circle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/cellarius/cellarius/Diamond.svg b/app/assets/v2/images/kudos/cellarius/cellarius/Diamond.svg new file mode 100755 index 00000000000..c7f6d72aa10 --- /dev/null +++ b/app/assets/v2/images/kudos/cellarius/cellarius/Diamond.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/cellarius/cellarius/Infinite.svg b/app/assets/v2/images/kudos/cellarius/cellarius/Infinite.svg new file mode 100755 index 00000000000..8391df6ce8e --- /dev/null +++ b/app/assets/v2/images/kudos/cellarius/cellarius/Infinite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/cellarius/cellarius/Spaghetti.svg b/app/assets/v2/images/kudos/cellarius/cellarius/Spaghetti.svg new file mode 100755 index 00000000000..e97b624e95a --- /dev/null +++ b/app/assets/v2/images/kudos/cellarius/cellarius/Spaghetti.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/cellarius/cellarius/Triangle.svg b/app/assets/v2/images/kudos/cellarius/cellarius/Triangle.svg new file mode 100755 index 00000000000..65f4d19a3b1 --- /dev/null +++ b/app/assets/v2/images/kudos/cellarius/cellarius/Triangle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/cellarius/cellarius/backend_architect.svg b/app/assets/v2/images/kudos/cellarius/cellarius/backend_architect.svg new file mode 100755 index 00000000000..82fd5df1e6d --- /dev/null +++ b/app/assets/v2/images/kudos/cellarius/cellarius/backend_architect.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/cellarius/cellarius/bug_eliminator.svg b/app/assets/v2/images/kudos/cellarius/cellarius/bug_eliminator.svg new file mode 100755 index 00000000000..0651ce09f9a --- /dev/null +++ b/app/assets/v2/images/kudos/cellarius/cellarius/bug_eliminator.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/cellarius/cellarius/bug_finder.svg b/app/assets/v2/images/kudos/cellarius/cellarius/bug_finder.svg new file mode 100755 index 00000000000..98acb5e96ca --- /dev/null +++ b/app/assets/v2/images/kudos/cellarius/cellarius/bug_finder.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/cellarius/cellarius/heart.svg b/app/assets/v2/images/kudos/cellarius/cellarius/heart.svg new file mode 100755 index 00000000000..627dca4fa43 --- /dev/null +++ b/app/assets/v2/images/kudos/cellarius/cellarius/heart.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/cellarius/cellarius/lightning_fast.svg b/app/assets/v2/images/kudos/cellarius/cellarius/lightning_fast.svg new file mode 100755 index 00000000000..51a58dfb6a2 --- /dev/null +++ b/app/assets/v2/images/kudos/cellarius/cellarius/lightning_fast.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/cellarius/cellarius/oddjobs.svg b/app/assets/v2/images/kudos/cellarius/cellarius/oddjobs.svg new file mode 100755 index 00000000000..291aa213b09 --- /dev/null +++ b/app/assets/v2/images/kudos/cellarius/cellarius/oddjobs.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/cellarius/cellarius/trusted_contributor.svg b/app/assets/v2/images/kudos/cellarius/cellarius/trusted_contributor.svg new file mode 100755 index 00000000000..d91a0af3a52 --- /dev/null +++ b/app/assets/v2/images/kudos/cellarius/cellarius/trusted_contributor.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/cellarius/heart.svg b/app/assets/v2/images/kudos/cellarius/heart.svg new file mode 100755 index 00000000000..627dca4fa43 --- /dev/null +++ b/app/assets/v2/images/kudos/cellarius/heart.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/cellarius/lightning_fast.svg b/app/assets/v2/images/kudos/cellarius/lightning_fast.svg new file mode 100755 index 00000000000..51a58dfb6a2 --- /dev/null +++ b/app/assets/v2/images/kudos/cellarius/lightning_fast.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/cellarius/oddjobs.svg b/app/assets/v2/images/kudos/cellarius/oddjobs.svg new file mode 100755 index 00000000000..291aa213b09 --- /dev/null +++ b/app/assets/v2/images/kudos/cellarius/oddjobs.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/cellarius/trusted_contributor.svg b/app/assets/v2/images/kudos/cellarius/trusted_contributor.svg new file mode 100755 index 00000000000..d91a0af3a52 --- /dev/null +++ b/app/assets/v2/images/kudos/cellarius/trusted_contributor.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/cleanest_code.svg b/app/assets/v2/images/kudos/cleanest_code.svg new file mode 100644 index 00000000000..74e851f36f7 --- /dev/null +++ b/app/assets/v2/images/kudos/cleanest_code.svg @@ -0,0 +1 @@ +</> \ No newline at end of file diff --git a/app/assets/v2/images/kudos/climb_the_ladder.svg b/app/assets/v2/images/kudos/climb_the_ladder.svg new file mode 100644 index 00000000000..01bb6491004 --- /dev/null +++ b/app/assets/v2/images/kudos/climb_the_ladder.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/code_shipper.svg b/app/assets/v2/images/kudos/code_shipper.svg new file mode 100644 index 00000000000..bdd7328e94f --- /dev/null +++ b/app/assets/v2/images/kudos/code_shipper.svg @@ -0,0 +1 @@ +HTMLXMLJavascriptPHPC++GoJavaPython \ No newline at end of file diff --git a/app/assets/v2/images/kudos/coding_ducky.svg b/app/assets/v2/images/kudos/coding_ducky.svg new file mode 100644 index 00000000000..412430c43ee --- /dev/null +++ b/app/assets/v2/images/kudos/coding_ducky.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/collab_robot.svg b/app/assets/v2/images/kudos/collab_robot.svg new file mode 100644 index 00000000000..b82ba771058 --- /dev/null +++ b/app/assets/v2/images/kudos/collab_robot.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/collaboration_machine.svg b/app/assets/v2/images/kudos/collaboration_machine.svg new file mode 100644 index 00000000000..fd7a45e6394 --- /dev/null +++ b/app/assets/v2/images/kudos/collaboration_machine.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/collaboration_robot.svg b/app/assets/v2/images/kudos/collaboration_robot.svg new file mode 100644 index 00000000000..b82ba771058 --- /dev/null +++ b/app/assets/v2/images/kudos/collaboration_robot.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/corporate_ladder.svg b/app/assets/v2/images/kudos/corporate_ladder.svg new file mode 100644 index 00000000000..c66048370be --- /dev/null +++ b/app/assets/v2/images/kudos/corporate_ladder.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/craftsman.svg b/app/assets/v2/images/kudos/craftsman.svg new file mode 100644 index 00000000000..bce0f7e9fb6 --- /dev/null +++ b/app/assets/v2/images/kudos/craftsman.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/css_gentle(wo)man.svg b/app/assets/v2/images/kudos/css_gentle(wo)man.svg new file mode 100644 index 00000000000..7dede095cc6 --- /dev/null +++ b/app/assets/v2/images/kudos/css_gentle(wo)man.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/data_savvy.svg b/app/assets/v2/images/kudos/data_savvy.svg new file mode 100644 index 00000000000..acfcece5a7b --- /dev/null +++ b/app/assets/v2/images/kudos/data_savvy.svg @@ -0,0 +1 @@ +00111101 0011010 0 1100 10 000111101 0011010 0 1100001 0011 010 0 110 00001 0011 010 0 110 000 101 00 11010 0 1100 100000 01 00 11 010 0 1100 1000000 101 00 1 00 100 000 101 00 110 10 0 11000111 00 110 10 0 110 0 10 011 00 11 0 10 0 11001 010 0 110 0 1 010 0 110 0 10000111101 0011010 0 1100 10 11101 0011010 0 1100001 0011 010 0 110 00001 0011 010 0 110 000 101 00 1 00 100000 01 00 11 010 0 1100 1000000 101 00 11010 0 1100 100 000 101 00 110 10 0 11000111 0 110 0 10 011 00 11 0 10 0 11001 010 0 110 0 100 01 010 0 110 0 10000111101 0011010 0 11101 0011010 0 1100001 0 0 0 110 00001 0011 010 0 110 000 101 00 11 100 100000 01 00 11 010 0 1100 1000000 101 00 11010 0 1100 100 000 101 00 110 10 0 11000111 00 110 10 0 110 0 10 011 00 11 0 10 0 11001 010 0 110 0 100 01 010 0 110 0 1000 101 00 11010 0 1100 100 000 101 00 110 10 0 11000111 0 110 0 10 011 00 11 0 10 0 11001 010 0 110 0 100 01 010 0 110 0 10000111101 0011010 0 11101 0011010 0 1100001 0 0 0 110 00001 0011 010 0 110 000 101 00 11 100 100000 01 00 11 010 0 1100 1000000 101 00 11010 0 1100 100 000 101 00 110 10 0 11000111 00 110 10 0 110 0 10 011 00 11 0 10 0 11001 010 0 110 0 100 01 010 0 110 0 100 \ No newline at end of file diff --git a/app/assets/v2/images/kudos/delegation_machine.svg b/app/assets/v2/images/kudos/delegation_machine.svg new file mode 100644 index 00000000000..612ba84e6af --- /dev/null +++ b/app/assets/v2/images/kudos/delegation_machine.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/design_star.svg b/app/assets/v2/images/kudos/design_star.svg new file mode 100644 index 00000000000..36fba8e605e --- /dev/null +++ b/app/assets/v2/images/kudos/design_star.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/devcon_4.svg b/app/assets/v2/images/kudos/devcon_4.svg new file mode 100644 index 00000000000..fabd2a04590 --- /dev/null +++ b/app/assets/v2/images/kudos/devcon_4.svg @@ -0,0 +1 @@ +ETHERIUMETHERIUMエーテル \ No newline at end of file diff --git a/app/assets/v2/images/kudos/direct.svg b/app/assets/v2/images/kudos/direct.svg new file mode 100644 index 00000000000..f88c11cd7d8 --- /dev/null +++ b/app/assets/v2/images/kudos/direct.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/django_cowboy.svg b/app/assets/v2/images/kudos/django_cowboy.svg new file mode 100644 index 00000000000..ecbf19f9702 --- /dev/null +++ b/app/assets/v2/images/kudos/django_cowboy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/django_dev.svg b/app/assets/v2/images/kudos/django_dev.svg new file mode 100644 index 00000000000..ecbf19f9702 --- /dev/null +++ b/app/assets/v2/images/kudos/django_dev.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/django_pony.svg b/app/assets/v2/images/kudos/django_pony.svg new file mode 100644 index 00000000000..c9d5842bc68 --- /dev/null +++ b/app/assets/v2/images/kudos/django_pony.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/do_more_faster.svg b/app/assets/v2/images/kudos/do_more_faster.svg new file mode 100644 index 00000000000..53df8e14cc4 --- /dev/null +++ b/app/assets/v2/images/kudos/do_more_faster.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/dont_just_hodl_buidl.svg b/app/assets/v2/images/kudos/dont_just_hodl_buidl.svg new file mode 100644 index 00000000000..1aa0755dadd --- /dev/null +++ b/app/assets/v2/images/kudos/dont_just_hodl_buidl.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/drupal_brainiac.svg b/app/assets/v2/images/kudos/drupal_brainiac.svg new file mode 100644 index 00000000000..e1cfa9822e2 --- /dev/null +++ b/app/assets/v2/images/kudos/drupal_brainiac.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/elixer_mixer.svg b/app/assets/v2/images/kudos/elixer_mixer.svg new file mode 100644 index 00000000000..7a9d60b344d --- /dev/null +++ b/app/assets/v2/images/kudos/elixer_mixer.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/ember_master.svg b/app/assets/v2/images/kudos/ember_master.svg new file mode 100644 index 00000000000..b61cce7a8a8 --- /dev/null +++ b/app/assets/v2/images/kudos/ember_master.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/eth_hacker2.svg b/app/assets/v2/images/kudos/eth_hacker2.svg new file mode 100644 index 00000000000..2f33cafd36d --- /dev/null +++ b/app/assets/v2/images/kudos/eth_hacker2.svg @@ -0,0 +1 @@ +01 010 101 11 01 0101 010 101 11 01 0101 010 101 11 01 0101 010 101 \ No newline at end of file diff --git a/app/assets/v2/images/kudos/ethereum_constellation.svg b/app/assets/v2/images/kudos/ethereum_constellation.svg new file mode 100644 index 00000000000..109871067c0 --- /dev/null +++ b/app/assets/v2/images/kudos/ethereum_constellation.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/eye_for_detail.svg b/app/assets/v2/images/kudos/eye_for_detail.svg new file mode 100644 index 00000000000..68348c080c1 --- /dev/null +++ b/app/assets/v2/images/kudos/eye_for_detail.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/fast_response.svg b/app/assets/v2/images/kudos/fast_response.svg new file mode 100644 index 00000000000..6bef729e91c --- /dev/null +++ b/app/assets/v2/images/kudos/fast_response.svg @@ -0,0 +1 @@ +hey whats up?John14:4514:4509:2109:21not much just chilling.Wed 27.wanna join us for basketball today?sure why not. \ No newline at end of file diff --git a/app/assets/v2/images/kudos/fast_turn_around.svg b/app/assets/v2/images/kudos/fast_turn_around.svg new file mode 100644 index 00000000000..ad2fedecc03 --- /dev/null +++ b/app/assets/v2/images/kudos/fast_turn_around.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/firefighter.svg b/app/assets/v2/images/kudos/firefighter.svg new file mode 100644 index 00000000000..cfe350cc45d --- /dev/null +++ b/app/assets/v2/images/kudos/firefighter.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/fission_color.svg b/app/assets/v2/images/kudos/fission_color.svg new file mode 100644 index 00000000000..b304f2037c7 --- /dev/null +++ b/app/assets/v2/images/kudos/fission_color.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/flying_pony.svg b/app/assets/v2/images/kudos/flying_pony.svg new file mode 100644 index 00000000000..c9d5842bc68 --- /dev/null +++ b/app/assets/v2/images/kudos/flying_pony.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/focus.svg b/app/assets/v2/images/kudos/focus.svg new file mode 100644 index 00000000000..a59916d09a6 --- /dev/null +++ b/app/assets/v2/images/kudos/focus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/freedom.svg b/app/assets/v2/images/kudos/freedom.svg new file mode 100644 index 00000000000..d5b7c91e60e --- /dev/null +++ b/app/assets/v2/images/kudos/freedom.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/frontend_alchemist.svg b/app/assets/v2/images/kudos/frontend_alchemist.svg new file mode 100644 index 00000000000..2f96a355372 --- /dev/null +++ b/app/assets/v2/images/kudos/frontend_alchemist.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/g1.svg b/app/assets/v2/images/kudos/g1.svg new file mode 100644 index 00000000000..64ffc18835a --- /dev/null +++ b/app/assets/v2/images/kudos/g1.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/games_first.svg b/app/assets/v2/images/kudos/games_first.svg new file mode 100644 index 00000000000..593a63e3f6f --- /dev/null +++ b/app/assets/v2/images/kudos/games_first.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/games_runner up.svg b/app/assets/v2/images/kudos/games_runner up.svg new file mode 100644 index 00000000000..448dfc4c5b2 --- /dev/null +++ b/app/assets/v2/images/kudos/games_runner up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/games_runner_up.svg b/app/assets/v2/images/kudos/games_runner_up.svg new file mode 100644 index 00000000000..448dfc4c5b2 --- /dev/null +++ b/app/assets/v2/images/kudos/games_runner_up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/gitcoin_genesis.svg b/app/assets/v2/images/kudos/gitcoin_genesis.svg new file mode 100644 index 00000000000..51d787d195b --- /dev/null +++ b/app/assets/v2/images/kudos/gitcoin_genesis.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/gitcoin_rasta.svg b/app/assets/v2/images/kudos/gitcoin_rasta.svg new file mode 100644 index 00000000000..44eba5070fc --- /dev/null +++ b/app/assets/v2/images/kudos/gitcoin_rasta.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/gitcoin_sustainer.svg b/app/assets/v2/images/kudos/gitcoin_sustainer.svg new file mode 100644 index 00000000000..bec90994caf --- /dev/null +++ b/app/assets/v2/images/kudos/gitcoin_sustainer.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/gitcoin_tree.svg b/app/assets/v2/images/kudos/gitcoin_tree.svg new file mode 100644 index 00000000000..e2327a6c631 --- /dev/null +++ b/app/assets/v2/images/kudos/gitcoin_tree.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/gitter_of_coins.svg b/app/assets/v2/images/kudos/gitter_of_coins.svg new file mode 100644 index 00000000000..b5d5a80d633 --- /dev/null +++ b/app/assets/v2/images/kudos/gitter_of_coins.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/go_developer.svg b/app/assets/v2/images/kudos/go_developer.svg new file mode 100644 index 00000000000..fb9c8b70db6 --- /dev/null +++ b/app/assets/v2/images/kudos/go_developer.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/good_communicator.svg b/app/assets/v2/images/kudos/good_communicator.svg new file mode 100644 index 00000000000..690f07e1248 --- /dev/null +++ b/app/assets/v2/images/kudos/good_communicator.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/grow_open_source.svg b/app/assets/v2/images/kudos/grow_open_source.svg new file mode 100644 index 00000000000..8f2e69e7e60 --- /dev/null +++ b/app/assets/v2/images/kudos/grow_open_source.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/growopen_source.svg b/app/assets/v2/images/kudos/growopen_source.svg new file mode 100644 index 00000000000..5f81bbb41e0 --- /dev/null +++ b/app/assets/v2/images/kudos/growopen_source.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/growoss_crystalball.svg b/app/assets/v2/images/kudos/growoss_crystalball.svg new file mode 100644 index 00000000000..f96ab07f30e --- /dev/null +++ b/app/assets/v2/images/kudos/growoss_crystalball.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/hadoop_admiral.svg b/app/assets/v2/images/kudos/hadoop_admiral.svg new file mode 100644 index 00000000000..a9a5d3db9e2 --- /dev/null +++ b/app/assets/v2/images/kudos/hadoop_admiral.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/handy_woman.svg b/app/assets/v2/images/kudos/handy_woman.svg new file mode 100644 index 00000000000..30e47b2d2b7 --- /dev/null +++ b/app/assets/v2/images/kudos/handy_woman.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/handyman.svg b/app/assets/v2/images/kudos/handyman.svg new file mode 100644 index 00000000000..348cf005678 --- /dev/null +++ b/app/assets/v2/images/kudos/handyman.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/hard_worker.svg b/app/assets/v2/images/kudos/hard_worker.svg new file mode 100644 index 00000000000..7457374afe7 --- /dev/null +++ b/app/assets/v2/images/kudos/hard_worker.svg @@ -0,0 +1 @@ +#include <iostream> // std::cin, std::coutint main () {char name[256], title[256];std::cout << "Please, enter your name: ";std::cin.getline (name,256,'$'); //Line 3std::cout << "Please, enter your favourite movie: ";std::cin.getline (title,256); // Line std::cout << name << "'s favourite movie is " return 0; \ No newline at end of file diff --git a/app/assets/v2/images/kudos/helping_hand.svg b/app/assets/v2/images/kudos/helping_hand.svg new file mode 100644 index 00000000000..9f14bd67887 --- /dev/null +++ b/app/assets/v2/images/kudos/helping_hand.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/heros_honour.svg b/app/assets/v2/images/kudos/heros_honour.svg new file mode 100644 index 00000000000..176e1d4005e --- /dev/null +++ b/app/assets/v2/images/kudos/heros_honour.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/html_celebrity.svg b/app/assets/v2/images/kudos/html_celebrity.svg new file mode 100644 index 00000000000..1d94bc32943 --- /dev/null +++ b/app/assets/v2/images/kudos/html_celebrity.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/idea_person.svg b/app/assets/v2/images/kudos/idea_person.svg new file mode 100644 index 00000000000..23c7e2e6aee --- /dev/null +++ b/app/assets/v2/images/kudos/idea_person.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/infrastructure_ninja.svg b/app/assets/v2/images/kudos/infrastructure_ninja.svg new file mode 100644 index 00000000000..bf6a13c9856 --- /dev/null +++ b/app/assets/v2/images/kudos/infrastructure_ninja.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/java_doctor.svg b/app/assets/v2/images/kudos/java_doctor.svg new file mode 100644 index 00000000000..6655b508107 --- /dev/null +++ b/app/assets/v2/images/kudos/java_doctor.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/javascript_master_scriber.svg b/app/assets/v2/images/kudos/javascript_master_scriber.svg new file mode 100644 index 00000000000..355dece08d0 --- /dev/null +++ b/app/assets/v2/images/kudos/javascript_master_scriber.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/jquery_fixer.svg b/app/assets/v2/images/kudos/jquery_fixer.svg new file mode 100644 index 00000000000..6c2812d16b9 --- /dev/null +++ b/app/assets/v2/images/kudos/jquery_fixer.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/kauri_1.svg b/app/assets/v2/images/kudos/kauri_1.svg new file mode 100644 index 00000000000..7fb9f2ed101 --- /dev/null +++ b/app/assets/v2/images/kudos/kauri_1.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/kauri_2.svg b/app/assets/v2/images/kudos/kauri_2.svg new file mode 100644 index 00000000000..f75a699510d --- /dev/null +++ b/app/assets/v2/images/kudos/kauri_2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/kudos_faster_repeat-bkp.gif b/app/assets/v2/images/kudos/kudos_faster_repeat-bkp.gif new file mode 100644 index 00000000000..ebedf550620 Binary files /dev/null and b/app/assets/v2/images/kudos/kudos_faster_repeat-bkp.gif differ diff --git a/app/assets/v2/images/kudos/kudos_faster_repeat-bkp2.gif b/app/assets/v2/images/kudos/kudos_faster_repeat-bkp2.gif new file mode 100644 index 00000000000..26179b80e27 Binary files /dev/null and b/app/assets/v2/images/kudos/kudos_faster_repeat-bkp2.gif differ diff --git a/app/assets/v2/images/kudos/kudos_faster_repeat.gif b/app/assets/v2/images/kudos/kudos_faster_repeat.gif new file mode 100644 index 00000000000..62c7055421b Binary files /dev/null and b/app/assets/v2/images/kudos/kudos_faster_repeat.gif differ diff --git a/app/assets/v2/images/kudos/level_up.svg b/app/assets/v2/images/kudos/level_up.svg new file mode 100644 index 00000000000..3c9366eb4c9 --- /dev/null +++ b/app/assets/v2/images/kudos/level_up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/link_legend_of_zelda.svg b/app/assets/v2/images/kudos/link_legend_of_zelda.svg new file mode 100644 index 00000000000..61605c03a92 --- /dev/null +++ b/app/assets/v2/images/kudos/link_legend_of_zelda.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/linux_wizard.svg b/app/assets/v2/images/kudos/linux_wizard.svg new file mode 100644 index 00000000000..20a5daaefc0 --- /dev/null +++ b/app/assets/v2/images/kudos/linux_wizard.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/logins_color.svg b/app/assets/v2/images/kudos/logins_color.svg new file mode 100644 index 00000000000..d0c22340569 --- /dev/null +++ b/app/assets/v2/images/kudos/logins_color.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/logo.svg b/app/assets/v2/images/kudos/logo.svg new file mode 100644 index 00000000000..beb693e77d9 --- /dev/null +++ b/app/assets/v2/images/kudos/logo.svg @@ -0,0 +1 @@ +K U DO S \ No newline at end of file diff --git a/app/assets/v2/images/kudos/magic_unicorn.svg b/app/assets/v2/images/kudos/magic_unicorn.svg new file mode 100644 index 00000000000..c0e9fc0dd15 --- /dev/null +++ b/app/assets/v2/images/kudos/magic_unicorn.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/mana_from_heavens.svg b/app/assets/v2/images/kudos/mana_from_heavens.svg new file mode 100644 index 00000000000..206f2f77b8d --- /dev/null +++ b/app/assets/v2/images/kudos/mana_from_heavens.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/market_first.svg b/app/assets/v2/images/kudos/market_first.svg new file mode 100644 index 00000000000..78e661ec76b --- /dev/null +++ b/app/assets/v2/images/kudos/market_first.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/marketplaces_runner up.svg b/app/assets/v2/images/kudos/marketplaces_runner up.svg new file mode 100644 index 00000000000..576f3ffc64d --- /dev/null +++ b/app/assets/v2/images/kudos/marketplaces_runner up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/marketplaces_runner_up.svg b/app/assets/v2/images/kudos/marketplaces_runner_up.svg new file mode 100644 index 00000000000..576f3ffc64d --- /dev/null +++ b/app/assets/v2/images/kudos/marketplaces_runner_up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/mega_open_collaborator.svg b/app/assets/v2/images/kudos/mega_open_collaborator.svg new file mode 100644 index 00000000000..78c4c6e6fa5 --- /dev/null +++ b/app/assets/v2/images/kudos/mega_open_collaborator.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/mongo_db_programmer.svg b/app/assets/v2/images/kudos/mongo_db_programmer.svg new file mode 100644 index 00000000000..16228d2c736 --- /dev/null +++ b/app/assets/v2/images/kudos/mongo_db_programmer.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/mysql_hero.svg b/app/assets/v2/images/kudos/mysql_hero.svg new file mode 100644 index 00000000000..bb45e8913b1 --- /dev/null +++ b/app/assets/v2/images/kudos/mysql_hero.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/new_dawn.svg b/app/assets/v2/images/kudos/new_dawn.svg new file mode 100644 index 00000000000..372b259f0b3 --- /dev/null +++ b/app/assets/v2/images/kudos/new_dawn.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/night_owl.svg b/app/assets/v2/images/kudos/night_owl.svg new file mode 100644 index 00000000000..cff86ba6ff8 --- /dev/null +++ b/app/assets/v2/images/kudos/night_owl.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/node_js_wizard.svg b/app/assets/v2/images/kudos/node_js_wizard.svg new file mode 100644 index 00000000000..4718747404a --- /dev/null +++ b/app/assets/v2/images/kudos/node_js_wizard.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/open_source_freedom_fighter.svg b/app/assets/v2/images/kudos/open_source_freedom_fighter.svg new file mode 100644 index 00000000000..e8184ce2bd3 --- /dev/null +++ b/app/assets/v2/images/kudos/open_source_freedom_fighter.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/out_of_this_world_programmer.svg b/app/assets/v2/images/kudos/out_of_this_world_programmer.svg new file mode 100644 index 00000000000..417c68ae214 --- /dev/null +++ b/app/assets/v2/images/kudos/out_of_this_world_programmer.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/participant_color.svg b/app/assets/v2/images/kudos/participant_color.svg new file mode 100644 index 00000000000..e68b29f16ff --- /dev/null +++ b/app/assets/v2/images/kudos/participant_color.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/party_robot.svg b/app/assets/v2/images/kudos/party_robot.svg new file mode 100644 index 00000000000..493b863ecfc --- /dev/null +++ b/app/assets/v2/images/kudos/party_robot.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/path.svg b/app/assets/v2/images/kudos/path.svg new file mode 100644 index 00000000000..f359d3f5c80 --- /dev/null +++ b/app/assets/v2/images/kudos/path.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/path_finder.svg b/app/assets/v2/images/kudos/path_finder.svg new file mode 100644 index 00000000000..e1968f2315f --- /dev/null +++ b/app/assets/v2/images/kudos/path_finder.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/philosophers.svg b/app/assets/v2/images/kudos/philosophers.svg new file mode 100644 index 00000000000..acf9a059792 --- /dev/null +++ b/app/assets/v2/images/kudos/philosophers.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/php_superstar.svg b/app/assets/v2/images/kudos/php_superstar.svg new file mode 100644 index 00000000000..4889295de08 --- /dev/null +++ b/app/assets/v2/images/kudos/php_superstar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/powertool_user.svg b/app/assets/v2/images/kudos/powertool_user.svg new file mode 100644 index 00000000000..7124cee3b2a --- /dev/null +++ b/app/assets/v2/images/kudos/powertool_user.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/powertools.svg b/app/assets/v2/images/kudos/powertools.svg new file mode 100644 index 00000000000..eec4bb27cbf --- /dev/null +++ b/app/assets/v2/images/kudos/powertools.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/praying.svg b/app/assets/v2/images/kudos/praying.svg new file mode 100644 index 00000000000..0ab4adb1fbd --- /dev/null +++ b/app/assets/v2/images/kudos/praying.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/problem_solver.svg b/app/assets/v2/images/kudos/problem_solver.svg new file mode 100644 index 00000000000..9942266c3df --- /dev/null +++ b/app/assets/v2/images/kudos/problem_solver.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/product_wizard.svg b/app/assets/v2/images/kudos/product_wizard.svg new file mode 100644 index 00000000000..08d5d3a0688 --- /dev/null +++ b/app/assets/v2/images/kudos/product_wizard.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/pythonista.svg b/app/assets/v2/images/kudos/pythonista.svg new file mode 100644 index 00000000000..ce8ae407fed --- /dev/null +++ b/app/assets/v2/images/kudos/pythonista.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/qa_ninja.svg b/app/assets/v2/images/kudos/qa_ninja.svg new file mode 100644 index 00000000000..1c759dd5ac4 --- /dev/null +++ b/app/assets/v2/images/kudos/qa_ninja.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/react_reactor.svg b/app/assets/v2/images/kudos/react_reactor.svg new file mode 100644 index 00000000000..1819638507c --- /dev/null +++ b/app/assets/v2/images/kudos/react_reactor.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/red_stapler.svg b/app/assets/v2/images/kudos/red_stapler.svg new file mode 100644 index 00000000000..ed6e3e3bb8c --- /dev/null +++ b/app/assets/v2/images/kudos/red_stapler.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/redux_programmer.svg b/app/assets/v2/images/kudos/redux_programmer.svg new file mode 100644 index 00000000000..9e85ca4bfe0 --- /dev/null +++ b/app/assets/v2/images/kudos/redux_programmer.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/release_early_and_often.svg b/app/assets/v2/images/kudos/release_early_and_often.svg new file mode 100644 index 00000000000..eca07f49b51 --- /dev/null +++ b/app/assets/v2/images/kudos/release_early_and_often.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/robot_large.svg b/app/assets/v2/images/kudos/robot_large.svg new file mode 100644 index 00000000000..5b4103753fd --- /dev/null +++ b/app/assets/v2/images/kudos/robot_large.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/robot_medium.svg b/app/assets/v2/images/kudos/robot_medium.svg new file mode 100644 index 00000000000..0f695599cdd --- /dev/null +++ b/app/assets/v2/images/kudos/robot_medium.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/robot_small.svg b/app/assets/v2/images/kudos/robot_small.svg new file mode 100644 index 00000000000..cf397d3e5b6 --- /dev/null +++ b/app/assets/v2/images/kudos/robot_small.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/ruby_gem.svg b/app/assets/v2/images/kudos/ruby_gem.svg new file mode 100644 index 00000000000..13d9781d1e8 --- /dev/null +++ b/app/assets/v2/images/kudos/ruby_gem.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/ruby_on_rails_machine.svg b/app/assets/v2/images/kudos/ruby_on_rails_machine.svg new file mode 100644 index 00000000000..8291e989ac5 --- /dev/null +++ b/app/assets/v2/images/kudos/ruby_on_rails_machine.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/ruby_on_rails_master.svg b/app/assets/v2/images/kudos/ruby_on_rails_master.svg new file mode 100644 index 00000000000..b5404f4643b --- /dev/null +++ b/app/assets/v2/images/kudos/ruby_on_rails_master.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/scirbe_color.svg b/app/assets/v2/images/kudos/scirbe_color.svg new file mode 100644 index 00000000000..8df643c3557 --- /dev/null +++ b/app/assets/v2/images/kudos/scirbe_color.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/shill_colorado.svg b/app/assets/v2/images/kudos/shill_colorado.svg new file mode 100644 index 00000000000..7701df8920e --- /dev/null +++ b/app/assets/v2/images/kudos/shill_colorado.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/shill_ethereum.svg b/app/assets/v2/images/kudos/shill_ethereum.svg new file mode 100644 index 00000000000..95e9b3d4ba6 --- /dev/null +++ b/app/assets/v2/images/kudos/shill_ethereum.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/shillin_like_a_villian.svg b/app/assets/v2/images/kudos/shillin_like_a_villian.svg new file mode 100644 index 00000000000..c4993d0b038 --- /dev/null +++ b/app/assets/v2/images/kudos/shillin_like_a_villian.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/shillville.svg b/app/assets/v2/images/kudos/shillville.svg new file mode 100644 index 00000000000..78cac686986 --- /dev/null +++ b/app/assets/v2/images/kudos/shillville.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/social_first.svg b/app/assets/v2/images/kudos/social_first.svg new file mode 100644 index 00000000000..ca829388704 --- /dev/null +++ b/app/assets/v2/images/kudos/social_first.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/social_runner up.svg b/app/assets/v2/images/kudos/social_runner up.svg new file mode 100644 index 00000000000..3de2251db41 --- /dev/null +++ b/app/assets/v2/images/kudos/social_runner up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/social_runner_up.svg b/app/assets/v2/images/kudos/social_runner_up.svg new file mode 100644 index 00000000000..3de2251db41 --- /dev/null +++ b/app/assets/v2/images/kudos/social_runner_up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/sociall_first.svg b/app/assets/v2/images/kudos/sociall_first.svg new file mode 100644 index 00000000000..ca829388704 --- /dev/null +++ b/app/assets/v2/images/kudos/sociall_first.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/struck_oil.svg b/app/assets/v2/images/kudos/struck_oil.svg new file mode 100644 index 00000000000..f6e3115185d --- /dev/null +++ b/app/assets/v2/images/kudos/struck_oil.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/subscription_color.svg b/app/assets/v2/images/kudos/subscription_color.svg new file mode 100644 index 00000000000..1f515e45ecf --- /dev/null +++ b/app/assets/v2/images/kudos/subscription_color.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/sunburst.svg b/app/assets/v2/images/kudos/sunburst.svg new file mode 100644 index 00000000000..44eba5070fc --- /dev/null +++ b/app/assets/v2/images/kudos/sunburst.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/super_juggler.svg b/app/assets/v2/images/kudos/super_juggler.svg new file mode 100644 index 00000000000..2a8fa3e8260 --- /dev/null +++ b/app/assets/v2/images/kudos/super_juggler.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/sustainer.svg b/app/assets/v2/images/kudos/sustainer.svg new file mode 100644 index 00000000000..842e1624890 --- /dev/null +++ b/app/assets/v2/images/kudos/sustainer.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/tools.svg b/app/assets/v2/images/kudos/tools.svg new file mode 100644 index 00000000000..dde93b5f5d9 --- /dev/null +++ b/app/assets/v2/images/kudos/tools.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/travel_first.svg b/app/assets/v2/images/kudos/travel_first.svg new file mode 100644 index 00000000000..987b03b918d --- /dev/null +++ b/app/assets/v2/images/kudos/travel_first.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/travel_runner up.svg b/app/assets/v2/images/kudos/travel_runner up.svg new file mode 100644 index 00000000000..8ba49e42a9c --- /dev/null +++ b/app/assets/v2/images/kudos/travel_runner up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/travel_runner_up.svg b/app/assets/v2/images/kudos/travel_runner_up.svg new file mode 100644 index 00000000000..8ba49e42a9c --- /dev/null +++ b/app/assets/v2/images/kudos/travel_runner_up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/unix_philosophy.svg b/app/assets/v2/images/kudos/unix_philosophy.svg new file mode 100644 index 00000000000..233b144e1c0 --- /dev/null +++ b/app/assets/v2/images/kudos/unix_philosophy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/vitalik.svg b/app/assets/v2/images/kudos/vitalik.svg new file mode 100644 index 00000000000..609ecfc67d4 --- /dev/null +++ b/app/assets/v2/images/kudos/vitalik.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/vitalik_genesis.svg b/app/assets/v2/images/kudos/vitalik_genesis.svg new file mode 100644 index 00000000000..dab79b3c1b4 --- /dev/null +++ b/app/assets/v2/images/kudos/vitalik_genesis.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/volunteer_color.svg b/app/assets/v2/images/kudos/volunteer_color.svg new file mode 100644 index 00000000000..ebe28bbb529 --- /dev/null +++ b/app/assets/v2/images/kudos/volunteer_color.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/wallet_color.svg b/app/assets/v2/images/kudos/wallet_color.svg new file mode 100644 index 00000000000..ea233ec8de1 --- /dev/null +++ b/app/assets/v2/images/kudos/wallet_color.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/west.svg b/app/assets/v2/images/kudos/west.svg new file mode 100644 index 00000000000..ecb8e348c8f --- /dev/null +++ b/app/assets/v2/images/kudos/west.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/kudos/wildcard.svg b/app/assets/v2/images/kudos/wildcard.svg new file mode 100644 index 00000000000..92de274ef20 --- /dev/null +++ b/app/assets/v2/images/kudos/wildcard.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/v2/images/top-bar/codefund-logo.svg b/app/assets/v2/images/top-bar/codefund-logo.svg new file mode 100644 index 00000000000..e549e8ebb1d --- /dev/null +++ b/app/assets/v2/images/top-bar/codefund-logo.svg @@ -0,0 +1,31 @@ + + + + codefund-logo + Created with Sketch. + + + + + + + + + \ No newline at end of file diff --git a/app/assets/v2/images/top-bar/codefund-symbol.svg b/app/assets/v2/images/top-bar/codefund-symbol.svg new file mode 100644 index 00000000000..5655022a249 --- /dev/null +++ b/app/assets/v2/images/top-bar/codefund-symbol.svg @@ -0,0 +1,17 @@ + + + + Created with Sketch. + + + + + + + + + Codefund + + + + diff --git a/app/assets/v2/images/top-bar/gitcoin-logo.svg b/app/assets/v2/images/top-bar/gitcoin-logo.svg new file mode 100644 index 00000000000..9aaabccbe7e --- /dev/null +++ b/app/assets/v2/images/top-bar/gitcoin-logo.svg @@ -0,0 +1,28 @@ + + + + gitcoin-logo + Created with Sketch. + + + + + diff --git a/app/assets/v2/images/top-bar/gitcoin-symbol.svg b/app/assets/v2/images/top-bar/gitcoin-symbol.svg new file mode 100644 index 00000000000..fd0f2fff451 --- /dev/null +++ b/app/assets/v2/images/top-bar/gitcoin-symbol.svg @@ -0,0 +1,23 @@ + + + + Created with Sketch. + + + + + + + + + + + + + + + Gitcoin + + + + diff --git a/app/assets/v2/images/top-bar/grants-logo.svg b/app/assets/v2/images/top-bar/grants-logo.svg new file mode 100644 index 00000000000..4aa7120cfb1 --- /dev/null +++ b/app/assets/v2/images/top-bar/grants-logo.svg @@ -0,0 +1,39 @@ + + + + grants-logo + Created with Sketch. + + + + + \ No newline at end of file diff --git a/app/assets/v2/images/top-bar/grants-symbol.svg b/app/assets/v2/images/top-bar/grants-symbol.svg new file mode 100644 index 00000000000..dbd393660a4 --- /dev/null +++ b/app/assets/v2/images/top-bar/grants-symbol.svg @@ -0,0 +1,25 @@ + + + + Created with Sketch. + + + + + Grants + + + + + + + + + + + + + + + + diff --git a/app/assets/v2/images/top-bar/kudos-logo.svg b/app/assets/v2/images/top-bar/kudos-logo.svg new file mode 100644 index 00000000000..85a5462f8a1 --- /dev/null +++ b/app/assets/v2/images/top-bar/kudos-logo.svg @@ -0,0 +1,20 @@ + + + + kudos-logo + Created with Sketch. + + + + + + + diff --git a/app/assets/v2/images/top-bar/kudos-symbol.svg b/app/assets/v2/images/top-bar/kudos-symbol.svg new file mode 100644 index 00000000000..3cb4b56f36f --- /dev/null +++ b/app/assets/v2/images/top-bar/kudos-symbol.svg @@ -0,0 +1,15 @@ + + + + Kudos + + + + + + + Kudos + + + + diff --git a/app/assets/v2/js/abi.js b/app/assets/v2/js/abi.js index a564d7bed4a..bad69bb41d9 100644 --- a/app/assets/v2/js/abi.js +++ b/app/assets/v2/js/abi.js @@ -1,6 +1,6 @@ var token_abi = [{'inputs': [], 'constant': true, 'name': 'mintingFinished', 'outputs': [{'type': 'bool', 'name': ''}], 'payable': false, 'type': 'function'}, {'inputs': [], 'constant': true, 'name': 'name', 'outputs': [{'type': 'string', 'name': ''}], 'payable': false, 'type': 'function'}, {'inputs': [{'type': 'address', 'name': '_spender'}, {'type': 'uint256', 'name': '_value'}], 'constant': false, 'name': 'approve', 'outputs': [{'type': 'bool', 'name': ''}], 'payable': false, 'type': 'function'}, {'inputs': [], 'constant': true, 'name': 'totalSupply', 'outputs': [{'type': 'uint256', 'name': ''}], 'payable': false, 'type': 'function'}, {'inputs': [{'type': 'address', 'name': '_from'}, {'type': 'address', 'name': '_to'}, {'type': 'uint256', 'name': '_value'}], 'constant': false, 'name': 'transferFrom', 'outputs': [{'type': 'bool', 'name': ''}], 'payable': false, 'type': 'function'}, {'inputs': [], 'constant': true, 'name': 'decimals', 'outputs': [{'type': 'uint8', 'name': ''}], 'payable': false, 'type': 'function'}, {'inputs': [{'type': 'address', 'name': '_to'}, {'type': 'uint256', 'name': '_amount'}], 'constant': false, 'name': 'mint', 'outputs': [{'type': 'bool', 'name': ''}], 'payable': false, 'type': 'function'}, {'inputs': [], 'constant': true, 'name': 'version', 'outputs': [{'type': 'string', 'name': ''}], 'payable': false, 'type': 'function'}, {'inputs': [{'type': 'address', 'name': '_owner'}], 'constant': true, 'name': 'balanceOf', 'outputs': [{'type': 'uint256', 'name': 'balance'}], 'payable': false, 'type': 'function'}, {'inputs': [], 'constant': false, 'name': 'finishMinting', 'outputs': [{'type': 'bool', 'name': ''}], 'payable': false, 'type': 'function'}, {'inputs': [], 'constant': true, 'name': 'owner', 'outputs': [{'type': 'address', 'name': ''}], 'payable': false, 'type': 'function'}, {'inputs': [], 'constant': true, 'name': 'symbol', 'outputs': [{'type': 'string', 'name': ''}], 'payable': false, 'type': 'function'}, {'inputs': [{'type': 'address', 'name': '_to'}, {'type': 'uint256', 'name': '_value'}], 'constant': false, 'name': 'transfer', 'outputs': [{'type': 'bool', 'name': ''}], 'payable': false, 'type': 'function'}, {'inputs': [{'type': 'address', 'name': '_owner'}, {'type': 'address', 'name': '_spender'}], 'constant': true, 'name': 'allowance', 'outputs': [{'type': 'uint256', 'name': 'remaining'}], 'payable': false, 'type': 'function'}, {'inputs': [{'type': 'address', 'name': 'newOwner'}], 'constant': false, 'name': 'transferOwnership', 'outputs': [], 'payable': false, 'type': 'function'}, {'payable': false, 'type': 'fallback'}, {'inputs': [{'indexed': true, 'type': 'address', 'name': 'to'}, {'indexed': false, 'type': 'uint256', 'name': 'amount'}], 'type': 'event', 'name': 'Mint', 'anonymous': false}, {'inputs': [], 'type': 'event', 'name': 'MintFinished', 'anonymous': false}, {'inputs': [{'indexed': true, 'type': 'address', 'name': 'owner'}, {'indexed': true, 'type': 'address', 'name': 'spender'}, {'indexed': false, 'type': 'uint256', 'name': 'value'}], 'type': 'event', 'name': 'Approval', 'anonymous': false}, {'inputs': [{'indexed': true, 'type': 'address', 'name': 'from'}, {'indexed': true, 'type': 'address', 'name': 'to'}, {'indexed': false, 'type': 'uint256', 'name': 'value'}], 'type': 'event', 'name': 'Transfer', 'anonymous': false}]; var bounty_abi = [{'constant': false, 'inputs': [{'name': '_bountyId', 'type': 'uint256'}], 'name': 'killBounty', 'outputs': [], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'function'}, {'constant': true, 'inputs': [{'name': '_bountyId', 'type': 'uint256'}], 'name': 'getBountyToken', 'outputs': [{'name': '', 'type': 'address'}], 'payable': false, 'stateMutability': 'view', 'type': 'function'}, {'constant': false, 'inputs': [{'name': '_bountyId', 'type': 'uint256'}, {'name': '_data', 'type': 'string'}], 'name': 'fulfillBounty', 'outputs': [], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'function'}, {'constant': false, 'inputs': [{'name': '_bountyId', 'type': 'uint256'}, {'name': '_newDeadline', 'type': 'uint256'}], 'name': 'extendDeadline', 'outputs': [], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'function'}, {'constant': true, 'inputs': [], 'name': 'getNumBounties', 'outputs': [{'name': '', 'type': 'uint256'}], 'payable': false, 'stateMutability': 'view', 'type': 'function'}, {'constant': false, 'inputs': [{'name': '_bountyId', 'type': 'uint256'}, {'name': '_fulfillmentId', 'type': 'uint256'}, {'name': '_data', 'type': 'string'}], 'name': 'updateFulfillment', 'outputs': [], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'function'}, {'constant': false, 'inputs': [{'name': '_bountyId', 'type': 'uint256'}, {'name': '_newFulfillmentAmount', 'type': 'uint256'}, {'name': '_value', 'type': 'uint256'}], 'name': 'increasePayout', 'outputs': [], 'payable': true, 'stateMutability': 'payable', 'type': 'function'}, {'constant': false, 'inputs': [{'name': '_bountyId', 'type': 'uint256'}, {'name': '_newFulfillmentAmount', 'type': 'uint256'}], 'name': 'changeBountyFulfillmentAmount', 'outputs': [], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'function'}, {'constant': false, 'inputs': [{'name': '_bountyId', 'type': 'uint256'}, {'name': '_newIssuer', 'type': 'address'}], 'name': 'transferIssuer', 'outputs': [], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'function'}, {'constant': false, 'inputs': [{'name': '_bountyId', 'type': 'uint256'}, {'name': '_value', 'type': 'uint256'}], 'name': 'activateBounty', 'outputs': [], 'payable': true, 'stateMutability': 'payable', 'type': 'function'}, {'constant': false, 'inputs': [{'name': '_issuer', 'type': 'address'}, {'name': '_deadline', 'type': 'uint256'}, {'name': '_data', 'type': 'string'}, {'name': '_fulfillmentAmount', 'type': 'uint256'}, {'name': '_arbiter', 'type': 'address'}, {'name': '_paysTokens', 'type': 'bool'}, {'name': '_tokenContract', 'type': 'address'}], 'name': 'issueBounty', 'outputs': [{'name': '', 'type': 'uint256'}], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'function'}, {'constant': false, 'inputs': [{'name': '_issuer', 'type': 'address'}, {'name': '_deadline', 'type': 'uint256'}, {'name': '_data', 'type': 'string'}, {'name': '_fulfillmentAmount', 'type': 'uint256'}, {'name': '_arbiter', 'type': 'address'}, {'name': '_paysTokens', 'type': 'bool'}, {'name': '_tokenContract', 'type': 'address'}, {'name': '_value', 'type': 'uint256'}], 'name': 'issueAndActivateBounty', 'outputs': [{'name': '', 'type': 'uint256'}], 'payable': true, 'stateMutability': 'payable', 'type': 'function'}, {'constant': true, 'inputs': [{'name': '_bountyId', 'type': 'uint256'}], 'name': 'getBountyArbiter', 'outputs': [{'name': '', 'type': 'address'}], 'payable': false, 'stateMutability': 'view', 'type': 'function'}, {'constant': false, 'inputs': [{'name': '_bountyId', 'type': 'uint256'}, {'name': '_value', 'type': 'uint256'}], 'name': 'contribute', 'outputs': [], 'payable': true, 'stateMutability': 'payable', 'type': 'function'}, {'constant': true, 'inputs': [], 'name': 'owner', 'outputs': [{'name': '', 'type': 'address'}], 'payable': false, 'stateMutability': 'view', 'type': 'function'}, {'constant': false, 'inputs': [{'name': '_bountyId', 'type': 'uint256'}, {'name': '_newPaysTokens', 'type': 'bool'}, {'name': '_newTokenContract', 'type': 'address'}], 'name': 'changeBountyPaysTokens', 'outputs': [], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'function'}, {'constant': true, 'inputs': [{'name': '_bountyId', 'type': 'uint256'}], 'name': 'getBountyData', 'outputs': [{'name': '', 'type': 'string'}], 'payable': false, 'stateMutability': 'view', 'type': 'function'}, {'constant': true, 'inputs': [{'name': '_bountyId', 'type': 'uint256'}, {'name': '_fulfillmentId', 'type': 'uint256'}], 'name': 'getFulfillment', 'outputs': [{'name': '', 'type': 'bool'}, {'name': '', 'type': 'address'}, {'name': '', 'type': 'string'}], 'payable': false, 'stateMutability': 'view', 'type': 'function'}, {'constant': false, 'inputs': [{'name': '_bountyId', 'type': 'uint256'}, {'name': '_newArbiter', 'type': 'address'}], 'name': 'changeBountyArbiter', 'outputs': [], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'function'}, {'constant': false, 'inputs': [{'name': '_bountyId', 'type': 'uint256'}, {'name': '_newDeadline', 'type': 'uint256'}], 'name': 'changeBountyDeadline', 'outputs': [], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'function'}, {'constant': false, 'inputs': [{'name': '_bountyId', 'type': 'uint256'}, {'name': '_fulfillmentId', 'type': 'uint256'}], 'name': 'acceptFulfillment', 'outputs': [], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'function'}, {'constant': true, 'inputs': [{'name': '', 'type': 'uint256'}], 'name': 'bounties', 'outputs': [{'name': 'issuer', 'type': 'address'}, {'name': 'deadline', 'type': 'uint256'}, {'name': 'data', 'type': 'string'}, {'name': 'fulfillmentAmount', 'type': 'uint256'}, {'name': 'arbiter', 'type': 'address'}, {'name': 'paysTokens', 'type': 'bool'}, {'name': 'bountyStage', 'type': 'uint8'}, {'name': 'balance', 'type': 'uint256'}], 'payable': false, 'stateMutability': 'view', 'type': 'function'}, {'constant': true, 'inputs': [{'name': '_bountyId', 'type': 'uint256'}], 'name': 'getBounty', 'outputs': [{'name': '', 'type': 'address'}, {'name': '', 'type': 'uint256'}, {'name': '', 'type': 'uint256'}, {'name': '', 'type': 'bool'}, {'name': '', 'type': 'uint256'}, {'name': '', 'type': 'uint256'}], 'payable': false, 'stateMutability': 'view', 'type': 'function'}, {'constant': false, 'inputs': [{'name': '_bountyId', 'type': 'uint256'}, {'name': '_newData', 'type': 'string'}], 'name': 'changeBountyData', 'outputs': [], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'function'}, {'constant': true, 'inputs': [{'name': '_bountyId', 'type': 'uint256'}], 'name': 'getNumFulfillments', 'outputs': [{'name': '', 'type': 'uint256'}], 'payable': false, 'stateMutability': 'view', 'type': 'function'}, {'inputs': [{'name': '_owner', 'type': 'address'}], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'constructor'}, {'anonymous': false, 'inputs': [{'indexed': false, 'name': 'bountyId', 'type': 'uint256'}], 'name': 'BountyIssued', 'type': 'event'}, {'anonymous': false, 'inputs': [{'indexed': false, 'name': 'bountyId', 'type': 'uint256'}, {'indexed': false, 'name': 'issuer', 'type': 'address'}], 'name': 'BountyActivated', 'type': 'event'}, {'anonymous': false, 'inputs': [{'indexed': false, 'name': 'bountyId', 'type': 'uint256'}, {'indexed': true, 'name': 'fulfiller', 'type': 'address'}, {'indexed': true, 'name': '_fulfillmentId', 'type': 'uint256'}], 'name': 'BountyFulfilled', 'type': 'event'}, {'anonymous': false, 'inputs': [{'indexed': false, 'name': '_bountyId', 'type': 'uint256'}, {'indexed': false, 'name': '_fulfillmentId', 'type': 'uint256'}], 'name': 'FulfillmentUpdated', 'type': 'event'}, {'anonymous': false, 'inputs': [{'indexed': false, 'name': 'bountyId', 'type': 'uint256'}, {'indexed': true, 'name': 'fulfiller', 'type': 'address'}, {'indexed': true, 'name': '_fulfillmentId', 'type': 'uint256'}], 'name': 'FulfillmentAccepted', 'type': 'event'}, {'anonymous': false, 'inputs': [{'indexed': false, 'name': 'bountyId', 'type': 'uint256'}, {'indexed': true, 'name': 'issuer', 'type': 'address'}], 'name': 'BountyKilled', 'type': 'event'}, {'anonymous': false, 'inputs': [{'indexed': false, 'name': 'bountyId', 'type': 'uint256'}, {'indexed': true, 'name': 'contributor', 'type': 'address'}, {'indexed': false, 'name': 'value', 'type': 'uint256'}], 'name': 'ContributionAdded', 'type': 'event'}, {'anonymous': false, 'inputs': [{'indexed': false, 'name': 'bountyId', 'type': 'uint256'}, {'indexed': false, 'name': 'newDeadline', 'type': 'uint256'}], 'name': 'DeadlineExtended', 'type': 'event'}, {'anonymous': false, 'inputs': [{'indexed': false, 'name': 'bountyId', 'type': 'uint256'}], 'name': 'BountyChanged', 'type': 'event'}, {'anonymous': false, 'inputs': [{'indexed': false, 'name': '_bountyId', 'type': 'uint256'}, {'indexed': true, 'name': '_newIssuer', 'type': 'address'}], 'name': 'IssuerTransferred', 'type': 'event'}, {'anonymous': false, 'inputs': [{'indexed': false, 'name': '_bountyId', 'type': 'uint256'}, {'indexed': false, 'name': '_newFulfillmentAmount', 'type': 'uint256'}], 'name': 'PayoutIncreased', 'type': 'event'}]; - +var kudos_abi = [{"constant":true,"inputs":[{"name":"_interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_tokenId","type":"uint256"}],"name":"approve","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"cloneFeePercentage","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"InterfaceId_ERC165","outputs":[{"name":"","type":"bytes4"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"isMintable","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"exists","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"kudos","outputs":[{"name":"priceFinney","type":"uint256"},{"name":"numClonesAllowed","type":"uint256"},{"name":"numClonesInWild","type":"uint256"},{"name":"clonedFromId","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_tokenId","type":"uint256"},{"name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"}],"name":"OwnershipRenounced","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"},{"indexed":true,"name":"_tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_owner","type":"address"},{"indexed":true,"name":"_approved","type":"address"},{"indexed":true,"name":"_tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_owner","type":"address"},{"indexed":true,"name":"_operator","type":"address"},{"indexed":false,"name":"_approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_priceFinney","type":"uint256"},{"name":"_numClonesAllowed","type":"uint256"},{"name":"_tokenURI","type":"string"}],"name":"mint","outputs":[{"name":"tokenId","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_tokenId","type":"uint256"},{"name":"_numClonesRequested","type":"uint256"}],"name":"clone","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"_owner","type":"address"},{"name":"_tokenId","type":"uint256"}],"name":"burn","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_cloneFeePercentage","type":"uint256"}],"name":"setCloneFeePercentage","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_isMintable","type":"bool"}],"name":"setMintable","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_tokenId","type":"uint256"},{"name":"_newPriceFinney","type":"uint256"}],"name":"setPrice","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"getKudosById","outputs":[{"name":"priceFinney","type":"uint256"},{"name":"numClonesAllowed","type":"uint256"},{"name":"numClonesInWild","type":"uint256"},{"name":"clonedFromId","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"getNumClonesInWild","outputs":[{"name":"numClonesInWild","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getLatestId","outputs":[{"name":"tokenId","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}]; var bounty_address = function() { if (document.web3network === null) { @@ -24,6 +24,28 @@ var bounty_address = function() { } }; +var kudos_address = function() { + if (document.web3network === null) { + // default to mainnet if web3network isn't found in time + document.web3network = 'mainnet'; + } + switch (document.web3network) { + case 'mainnet': + return '0x2aea4add166ebf38b63d09a75de1a7b94aa24163'; + case 'ropsten': + return '0xcd520707fc68d153283d518b29ada466f9091ea8'; + case 'kovan': + throw 'this network is not supported for kudos'; + case 'rinkeby': + return '0x4077ae95eec529d924571d00e81ecde104601ae8'; + case 'custom network': + // This only works if you deploy the Standard Bounties contract locally + // Set the testrpc address to the address below in in the truffle.js file. + // In the Standard Bounties repo, `truffle deploy --network testrpc` + return '0xe7bed272ee374e8116049d0a49737bdda86325b6'; + } +}; + var etherscan_tx_url = function(txid) { switch (document.web3network) { case 'mainnet': diff --git a/app/assets/v2/js/ajax-helper.js b/app/assets/v2/js/ajax-helper.js new file mode 100644 index 00000000000..13d6d296f48 --- /dev/null +++ b/app/assets/v2/js/ajax-helper.js @@ -0,0 +1,24 @@ +/** + * Generic function to make an AJAX call avoid DRY + * + * ex: + * var getdata = fetchData ('/api/v0.1/data/','GET') + * $.when( getdata ).then( function ( response ){ return response }) + * + * var sendForm = fetchData ( e.currentTarget.action, + * e.currentTarget.method, + * $("#form-wallets").serialize() + * ) + * $.when( sendForm ).then( function ( payback ){ return payback }) + * +*/ + +var fetchData = function(urlRequest, methodType, data) { + // Return the $.ajax promise + return $.ajax({ + url: urlRequest, + type: methodType, + dataType: 'json', + data: data + }); +}; diff --git a/app/assets/v2/js/base.js b/app/assets/v2/js/base.js index 5e2bfdb462a..e64baaefbca 100644 --- a/app/assets/v2/js/base.js +++ b/app/assets/v2/js/base.js @@ -68,10 +68,20 @@ $(document).ready(function() { $('#logo').mouseleave(function(e) { $(this).attr('src', $(this).attr('old-src')); }); - - $('.navbar-toggler').click(function() { - $('.navbar-collapse').toggleClass('show'); - }); + if (!$.fn.collapse) { + $('.navbar-toggler').click(function() { + var toggle = $(this).attr('aria-expanded'); + + console.log(toggle); + $('.navbar-collapse').toggleClass('show'); + if (toggle === 'false') { + $(this).attr('aria-expanded', 'true'); + } else { + $(this).attr('aria-expanded', 'false'); + } + + }); + } // get started modal $('body').delegate('.iama', 'click', function() { @@ -175,10 +185,6 @@ $(document).ready(function() { }); }); -$(window).scroll(function() { - var scrollPos = jQuery(document).scrollTop(); -}); - /* TODO : Remove after GDPR */ if ($('#is-authenticated').val() === 'True' && !localStorage['notify_policy_update']) { localStorage['notify_policy_update'] = true; diff --git a/app/assets/v2/js/bootstrap.min.js b/app/assets/v2/js/bootstrap.min.js new file mode 100644 index 00000000000..63ad32fbf6b --- /dev/null +++ b/app/assets/v2/js/bootstrap.min.js @@ -0,0 +1,7 @@ +/*! + * Bootstrap v4.1.2 (https://getbootstrap.com/) + * Copyright 2011-2018 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("jquery"),require("popper.js")):"function"==typeof define&&define.amd?define(["exports","jquery","popper.js"],e):e(t.bootstrap={},t.jQuery,t.Popper)}(this,function(t,e,h){"use strict";function i(t,e){for(var n=0;nthis._items.length-1||t<0))if(this._isSliding)P(this._element).one(Q.SLID,function(){return e.to(t)});else{if(n===t)return this.pause(),void this.cycle();var i=ndocument.documentElement.clientHeight;!this._isBodyOverflowing&&t&&(this._element.style.paddingLeft=this._scrollbarWidth+"px"),this._isBodyOverflowing&&!t&&(this._element.style.paddingRight=this._scrollbarWidth+"px")},t._resetAdjustments=function(){this._element.style.paddingLeft="",this._element.style.paddingRight=""},t._checkScrollbar=function(){var t=document.body.getBoundingClientRect();this._isBodyOverflowing=t.left+t.right
',trigger:"hover focus",title:"",delay:0,html:!(Ie={AUTO:"auto",TOP:"top",RIGHT:"right",BOTTOM:"bottom",LEFT:"left"}),selector:!(Se={animation:"boolean",template:"string",title:"(string|element|function)",trigger:"string",delay:"(number|object)",html:"boolean",selector:"(string|boolean)",placement:"(string|function)",offset:"(number|string)",container:"(string|element|boolean)",fallbackPlacement:"(string|array)",boundary:"(string|element)"}),placement:"top",offset:0,container:!1,fallbackPlacement:"flip",boundary:"scrollParent"},we="out",Ne={HIDE:"hide"+Ee,HIDDEN:"hidden"+Ee,SHOW:(De="show")+Ee,SHOWN:"shown"+Ee,INSERTED:"inserted"+Ee,CLICK:"click"+Ee,FOCUSIN:"focusin"+Ee,FOCUSOUT:"focusout"+Ee,MOUSEENTER:"mouseenter"+Ee,MOUSELEAVE:"mouseleave"+Ee},Oe="fade",ke="show",Pe=".tooltip-inner",je=".arrow",He="hover",Le="focus",Re="click",xe="manual",We=function(){function i(t,e){if("undefined"==typeof h)throw new TypeError("Bootstrap tooltips require Popper.js (https://popper.js.org)");this._isEnabled=!0,this._timeout=0,this._hoverState="",this._activeTrigger={},this._popper=null,this.element=t,this.config=this._getConfig(e),this.tip=null,this._setListeners()}var t=i.prototype;return t.enable=function(){this._isEnabled=!0},t.disable=function(){this._isEnabled=!1},t.toggleEnabled=function(){this._isEnabled=!this._isEnabled},t.toggle=function(t){if(this._isEnabled)if(t){var e=this.constructor.DATA_KEY,n=pe(t.currentTarget).data(e);n||(n=new this.constructor(t.currentTarget,this._getDelegateConfig()),pe(t.currentTarget).data(e,n)),n._activeTrigger.click=!n._activeTrigger.click,n._isWithActiveTrigger()?n._enter(null,n):n._leave(null,n)}else{if(pe(this.getTipElement()).hasClass(ke))return void this._leave(null,this);this._enter(null,this)}},t.dispose=function(){clearTimeout(this._timeout),pe.removeData(this.element,this.constructor.DATA_KEY),pe(this.element).off(this.constructor.EVENT_KEY),pe(this.element).closest(".modal").off("hide.bs.modal"),this.tip&&pe(this.tip).remove(),this._isEnabled=null,this._timeout=null,this._hoverState=null,(this._activeTrigger=null)!==this._popper&&this._popper.destroy(),this._popper=null,this.element=null,this.config=null,this.tip=null},t.show=function(){var e=this;if("none"===pe(this.element).css("display"))throw new Error("Please use show on visible elements");var t=pe.Event(this.constructor.Event.SHOW);if(this.isWithContent()&&this._isEnabled){pe(this.element).trigger(t);var n=pe.contains(this.element.ownerDocument.documentElement,this.element);if(t.isDefaultPrevented()||!n)return;var i=this.getTipElement(),r=Fn.getUID(this.constructor.NAME);i.setAttribute("id",r),this.element.setAttribute("aria-describedby",r),this.setContent(),this.config.animation&&pe(i).addClass(Oe);var o="function"==typeof this.config.placement?this.config.placement.call(this,i,this.element):this.config.placement,s=this._getAttachment(o);this.addAttachmentClass(s);var a=!1===this.config.container?document.body:pe(document).find(this.config.container);pe(i).data(this.constructor.DATA_KEY,this),pe.contains(this.element.ownerDocument.documentElement,this.tip)||pe(i).appendTo(a),pe(this.element).trigger(this.constructor.Event.INSERTED),this._popper=new h(this.element,i,{placement:s,modifiers:{offset:{offset:this.config.offset},flip:{behavior:this.config.fallbackPlacement},arrow:{element:je},preventOverflow:{boundariesElement:this.config.boundary}},onCreate:function(t){t.originalPlacement!==t.placement&&e._handlePopperPlacementChange(t)},onUpdate:function(t){e._handlePopperPlacementChange(t)}}),pe(i).addClass(ke),"ontouchstart"in document.documentElement&&pe(document.body).children().on("mouseover",null,pe.noop);var l=function(){e.config.animation&&e._fixTransition();var t=e._hoverState;e._hoverState=null,pe(e.element).trigger(e.constructor.Event.SHOWN),t===we&&e._leave(null,e)};if(pe(this.tip).hasClass(Oe)){var c=Fn.getTransitionDurationFromElement(this.tip);pe(this.tip).one(Fn.TRANSITION_END,l).emulateTransitionEnd(c)}else l()}},t.hide=function(t){var e=this,n=this.getTipElement(),i=pe.Event(this.constructor.Event.HIDE),r=function(){e._hoverState!==De&&n.parentNode&&n.parentNode.removeChild(n),e._cleanTipClass(),e.element.removeAttribute("aria-describedby"),pe(e.element).trigger(e.constructor.Event.HIDDEN),null!==e._popper&&e._popper.destroy(),t&&t()};if(pe(this.element).trigger(i),!i.isDefaultPrevented()){if(pe(n).removeClass(ke),"ontouchstart"in document.documentElement&&pe(document.body).children().off("mouseover",null,pe.noop),this._activeTrigger[Re]=!1,this._activeTrigger[Le]=!1,this._activeTrigger[He]=!1,pe(this.tip).hasClass(Oe)){var o=Fn.getTransitionDurationFromElement(n);pe(n).one(Fn.TRANSITION_END,r).emulateTransitionEnd(o)}else r();this._hoverState=""}},t.update=function(){null!==this._popper&&this._popper.scheduleUpdate()},t.isWithContent=function(){return Boolean(this.getTitle())},t.addAttachmentClass=function(t){pe(this.getTipElement()).addClass(Te+"-"+t)},t.getTipElement=function(){return this.tip=this.tip||pe(this.config.template)[0],this.tip},t.setContent=function(){var t=this.getTipElement();this.setElementContent(pe(t.querySelectorAll(Pe)),this.getTitle()),pe(t).removeClass(Oe+" "+ke)},t.setElementContent=function(t,e){var n=this.config.html;"object"==typeof e&&(e.nodeType||e.jquery)?n?pe(e).parent().is(t)||t.empty().append(e):t.text(pe(e).text()):t[n?"html":"text"](e)},t.getTitle=function(){var t=this.element.getAttribute("data-original-title");return t||(t="function"==typeof this.config.title?this.config.title.call(this.element):this.config.title),t},t._getAttachment=function(t){return Ie[t.toUpperCase()]},t._setListeners=function(){var i=this;this.config.trigger.split(" ").forEach(function(t){if("click"===t)pe(i.element).on(i.constructor.Event.CLICK,i.config.selector,function(t){return i.toggle(t)});else if(t!==xe){var e=t===He?i.constructor.Event.MOUSEENTER:i.constructor.Event.FOCUSIN,n=t===He?i.constructor.Event.MOUSELEAVE:i.constructor.Event.FOCUSOUT;pe(i.element).on(e,i.config.selector,function(t){return i._enter(t)}).on(n,i.config.selector,function(t){return i._leave(t)})}pe(i.element).closest(".modal").on("hide.bs.modal",function(){return i.hide()})}),this.config.selector?this.config=l({},this.config,{trigger:"manual",selector:""}):this._fixTitle()},t._fixTitle=function(){var t=typeof this.element.getAttribute("data-original-title");(this.element.getAttribute("title")||"string"!==t)&&(this.element.setAttribute("data-original-title",this.element.getAttribute("title")||""),this.element.setAttribute("title",""))},t._enter=function(t,e){var n=this.constructor.DATA_KEY;(e=e||pe(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),pe(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusin"===t.type?Le:He]=!0),pe(e.getTipElement()).hasClass(ke)||e._hoverState===De?e._hoverState=De:(clearTimeout(e._timeout),e._hoverState=De,e.config.delay&&e.config.delay.show?e._timeout=setTimeout(function(){e._hoverState===De&&e.show()},e.config.delay.show):e.show())},t._leave=function(t,e){var n=this.constructor.DATA_KEY;(e=e||pe(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),pe(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusout"===t.type?Le:He]=!1),e._isWithActiveTrigger()||(clearTimeout(e._timeout),e._hoverState=we,e.config.delay&&e.config.delay.hide?e._timeout=setTimeout(function(){e._hoverState===we&&e.hide()},e.config.delay.hide):e.hide())},t._isWithActiveTrigger=function(){for(var t in this._activeTrigger)if(this._activeTrigger[t])return!0;return!1},t._getConfig=function(t){return"number"==typeof(t=l({},this.constructor.Default,pe(this.element).data(),"object"==typeof t&&t?t:{})).delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),Fn.typeCheckConfig(ve,t,this.constructor.DefaultType),t},t._getDelegateConfig=function(){var t={};if(this.config)for(var e in this.config)this.constructor.Default[e]!==this.config[e]&&(t[e]=this.config[e]);return t},t._cleanTipClass=function(){var t=pe(this.getTipElement()),e=t.attr("class").match(be);null!==e&&e.length&&t.removeClass(e.join(""))},t._handlePopperPlacementChange=function(t){var e=t.instance;this.tip=e.popper,this._cleanTipClass(),this.addAttachmentClass(this._getAttachment(t.placement))},t._fixTransition=function(){var t=this.getTipElement(),e=this.config.animation;null===t.getAttribute("x-placement")&&(pe(t).removeClass(Oe),this.config.animation=!1,this.hide(),this.show(),this.config.animation=e)},i._jQueryInterface=function(n){return this.each(function(){var t=pe(this).data(ye),e="object"==typeof n&&n;if((t||!/dispose|hide/.test(n))&&(t||(t=new i(this,e),pe(this).data(ye,t)),"string"==typeof n)){if("undefined"==typeof t[n])throw new TypeError('No method named "'+n+'"');t[n]()}})},s(i,null,[{key:"VERSION",get:function(){return"4.1.2"}},{key:"Default",get:function(){return Ae}},{key:"NAME",get:function(){return ve}},{key:"DATA_KEY",get:function(){return ye}},{key:"Event",get:function(){return Ne}},{key:"EVENT_KEY",get:function(){return Ee}},{key:"DefaultType",get:function(){return Se}}]),i}(),pe.fn[ve]=We._jQueryInterface,pe.fn[ve].Constructor=We,pe.fn[ve].noConflict=function(){return pe.fn[ve]=Ce,We._jQueryInterface},We),Jn=(qe="popover",Ke="."+(Fe="bs.popover"),Me=(Ue=e).fn[qe],Qe="bs-popover",Be=new RegExp("(^|\\s)"+Qe+"\\S+","g"),Ve=l({},zn.Default,{placement:"right",trigger:"click",content:"",template:''}),Ye=l({},zn.DefaultType,{content:"(string|element|function)"}),ze="fade",Ze=".popover-header",Ge=".popover-body",$e={HIDE:"hide"+Ke,HIDDEN:"hidden"+Ke,SHOW:(Je="show")+Ke,SHOWN:"shown"+Ke,INSERTED:"inserted"+Ke,CLICK:"click"+Ke,FOCUSIN:"focusin"+Ke,FOCUSOUT:"focusout"+Ke,MOUSEENTER:"mouseenter"+Ke,MOUSELEAVE:"mouseleave"+Ke},Xe=function(t){var e,n;function i(){return t.apply(this,arguments)||this}n=t,(e=i).prototype=Object.create(n.prototype),(e.prototype.constructor=e).__proto__=n;var r=i.prototype;return r.isWithContent=function(){return this.getTitle()||this._getContent()},r.addAttachmentClass=function(t){Ue(this.getTipElement()).addClass(Qe+"-"+t)},r.getTipElement=function(){return this.tip=this.tip||Ue(this.config.template)[0],this.tip},r.setContent=function(){var t=Ue(this.getTipElement());this.setElementContent(t.find(Ze),this.getTitle());var e=this._getContent();"function"==typeof e&&(e=e.call(this.element)),this.setElementContent(t.find(Ge),e),t.removeClass(ze+" "+Je)},r._getContent=function(){return this.element.getAttribute("data-content")||this.config.content},r._cleanTipClass=function(){var t=Ue(this.getTipElement()),e=t.attr("class").match(Be);null!==e&&0=this._offsets[r]&&("undefined"==typeof this._offsets[r+1]||t0.006 ETH + * The eth value inside data attr will be converted and added to the tag + * NOTE: needs amount.js to be loaded + * +*/ + +(function() { + this.ethprice = function() { + var elems = document.querySelectorAll('[data-ethprice]'); + + elems.forEach(function(elem) { + new Promise(function(resolve, reject) { + getUSDEstimate(elem.dataset.ethprice, 'ETH', function(usdAmount) { + resolve(usdAmount); + }); + }).then(function(result) { + addValue(elem, result); + }, function(reject) { + console.log(reject); + }); + }); + + function addValue(elem, result) { + elem.children[0].textContent = `(${result.value} USD)`; + } + }; +}()); + +var ethprice = new ethprice(); diff --git a/app/assets/v2/js/jquery.select2.min.js b/app/assets/v2/js/jquery.select2.min.js index e5316a7ffa6..f2b2ecba0a9 100644 --- a/app/assets/v2/js/jquery.select2.min.js +++ b/app/assets/v2/js/jquery.select2.min.js @@ -1 +1 @@ -/*! Select2 4.0.4 | https://github.com/select2/select2/blob/master/LICENSE.md */!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof module&&module.exports?module.exports=function(b,c){return void 0===c&&(c="undefined"!=typeof window?require("jquery"):require("jquery")(b)),a(c),c}:a(jQuery)}(function(a){var b=function(){if(a&&a.fn&&a.fn.select2&&a.fn.select2.amd)var b=a.fn.select2.amd;var b;return function(){if(!b||!b.requirejs){b?c=b:b={};var a,c,d;!function(b){function e(a,b){return v.call(a,b)}function f(a,b){var c,d,e,f,g,h,i,j,k,l,m,n,o=b&&b.split("/"),p=t.map,q=p&&p["*"]||{};if(a){for(a=a.split("/"),g=a.length-1,t.nodeIdCompat&&x.test(a[g])&&(a[g]=a[g].replace(x,"")),"."===a[0].charAt(0)&&o&&(n=o.slice(0,o.length-1),a=n.concat(a)),k=0;k0&&(a.splice(k-1,2),k-=2)}a=a.join("/")}if((o||q)&&p){for(c=a.split("/"),k=c.length;k>0;k-=1){if(d=c.slice(0,k).join("/"),o)for(l=o.length;l>0;l-=1)if((e=p[o.slice(0,l).join("/")])&&(e=e[d])){f=e,h=k;break}if(f)break;!i&&q&&q[d]&&(i=q[d],j=k)}!f&&i&&(f=i,h=j),f&&(c.splice(0,h,f),a=c.join("/"))}return a}function g(a,c){return function(){var d=w.call(arguments,0);return"string"!=typeof d[0]&&1===d.length&&d.push(null),o.apply(b,d.concat([a,c]))}}function h(a){return function(b){return f(b,a)}}function i(a){return function(b){r[a]=b}}function j(a){if(e(s,a)){var c=s[a];delete s[a],u[a]=!0,n.apply(b,c)}if(!e(r,a)&&!e(u,a))throw new Error("No "+a);return r[a]}function k(a){var b,c=a?a.indexOf("!"):-1;return c>-1&&(b=a.substring(0,c),a=a.substring(c+1,a.length)),[b,a]}function l(a){return a?k(a):[]}function m(a){return function(){return t&&t.config&&t.config[a]||{}}}var n,o,p,q,r={},s={},t={},u={},v=Object.prototype.hasOwnProperty,w=[].slice,x=/\.js$/;p=function(a,b){var c,d=k(a),e=d[0],g=b[1];return a=d[1],e&&(e=f(e,g),c=j(e)),e?a=c&&c.normalize?c.normalize(a,h(g)):f(a,g):(a=f(a,g),d=k(a),e=d[0],a=d[1],e&&(c=j(e))),{f:e?e+"!"+a:a,n:a,pr:e,p:c}},q={require:function(a){return g(a)},exports:function(a){var b=r[a];return void 0!==b?b:r[a]={}},module:function(a){return{id:a,uri:"",exports:r[a],config:m(a)}}},n=function(a,c,d,f){var h,k,m,n,o,t,v,w=[],x=typeof d;if(f=f||a,t=l(f),"undefined"===x||"function"===x){for(c=!c.length&&d.length?["require","exports","module"]:c,o=0;o0&&(b.call(arguments,a.prototype.constructor),e=c.prototype.constructor),e.apply(this,arguments)}function e(){this.constructor=d}var f=b(c),g=b(a);c.displayName=a.displayName,d.prototype=new e;for(var h=0;h":">",'"':""","'":"'","/":"/"};return"string"!=typeof a?a:String(a).replace(/[&<>"'\/\\]/g,function(a){return b[a]})},c.appendMany=function(b,c){if("1.7"===a.fn.jquery.substr(0,3)){var d=a();a.map(c,function(a){d=d.add(a)}),c=d}b.append(c)},c}),b.define("select2/results",["jquery","./utils"],function(a,b){function c(a,b,d){this.$element=a,this.data=d,this.options=b,c.__super__.constructor.call(this)}return b.Extend(c,b.Observable),c.prototype.render=function(){var b=a('
    ');return this.options.get("multiple")&&b.attr("aria-multiselectable","true"),this.$results=b,b},c.prototype.clear=function(){this.$results.empty()},c.prototype.displayMessage=function(b){var c=this.options.get("escapeMarkup");this.clear(),this.hideLoading();var d=a('
  • '),e=this.options.get("translations").get(b.message);d.append(c(e(b.args))),d[0].className+=" select2-results__message",this.$results.append(d)},c.prototype.hideMessages=function(){this.$results.find(".select2-results__message").remove()},c.prototype.append=function(a){this.hideLoading();var b=[];if(null==a.results||0===a.results.length)return void(0===this.$results.children().length&&this.trigger("results:message",{message:"noResults"}));a.results=this.sort(a.results);for(var c=0;c0?b.first().trigger("mouseenter"):a.first().trigger("mouseenter"),this.ensureHighlightVisible()},c.prototype.setClasses=function(){var b=this;this.data.current(function(c){var d=a.map(c,function(a){return a.id.toString()});b.$results.find(".select2-results__option[aria-selected]").each(function(){var b=a(this),c=a.data(this,"data"),e=""+c.id;null!=c.element&&c.element.selected||null==c.element&&a.inArray(e,d)>-1?b.attr("aria-selected","true"):b.attr("aria-selected","false")})})},c.prototype.showLoading=function(a){this.hideLoading();var b=this.options.get("translations").get("searching"),c={disabled:!0,loading:!0,text:b(a)},d=this.option(c);d.className+=" loading-results",this.$results.prepend(d)},c.prototype.hideLoading=function(){this.$results.find(".loading-results").remove()},c.prototype.option=function(b){var c=document.createElement("li");c.className="select2-results__option";var d={role:"treeitem","aria-selected":"false"};b.disabled&&(delete d["aria-selected"],d["aria-disabled"]="true"),null==b.id&&delete d["aria-selected"],null!=b._resultId&&(c.id=b._resultId),b.title&&(c.title=b.title),b.children&&(d.role="group",d["aria-label"]=b.text,delete d["aria-selected"]);for(var e in d){var f=d[e];c.setAttribute(e,f)}if(b.children){var g=a(c),h=document.createElement("strong");h.className="select2-results__group";a(h);this.template(b,h);for(var i=[],j=0;j",{class:"select2-results__options select2-results__options--nested"});m.append(i),g.append(h),g.append(m)}else this.template(b,c);return a.data(c,"data",b),c},c.prototype.bind=function(b,c){var d=this,e=b.id+"-results";this.$results.attr("id",e),b.on("results:all",function(a){d.clear(),d.append(a.data),b.isOpen()&&(d.setClasses(),d.highlightFirstItem())}),b.on("results:append",function(a){d.append(a.data),b.isOpen()&&d.setClasses()}),b.on("query",function(a){d.hideMessages(),d.showLoading(a)}),b.on("select",function(){b.isOpen()&&(d.setClasses(),d.highlightFirstItem())}),b.on("unselect",function(){b.isOpen()&&(d.setClasses(),d.highlightFirstItem())}),b.on("open",function(){d.$results.attr("aria-expanded","true"),d.$results.attr("aria-hidden","false"),d.setClasses(),d.ensureHighlightVisible()}),b.on("close",function(){d.$results.attr("aria-expanded","false"),d.$results.attr("aria-hidden","true"),d.$results.removeAttr("aria-activedescendant")}),b.on("results:toggle",function(){var a=d.getHighlightedResults();0!==a.length&&a.trigger("mouseup")}),b.on("results:select",function(){var a=d.getHighlightedResults();if(0!==a.length){var b=a.data("data");"true"==a.attr("aria-selected")?d.trigger("close",{}):d.trigger("select",{data:b})}}),b.on("results:previous",function(){var a=d.getHighlightedResults(),b=d.$results.find("[aria-selected]"),c=b.index(a);if(0!==c){var e=c-1;0===a.length&&(e=0);var f=b.eq(e);f.trigger("mouseenter");var g=d.$results.offset().top,h=f.offset().top,i=d.$results.scrollTop()+(h-g);0===e?d.$results.scrollTop(0):h-g<0&&d.$results.scrollTop(i)}}),b.on("results:next",function(){var a=d.getHighlightedResults(),b=d.$results.find("[aria-selected]"),c=b.index(a),e=c+1;if(!(e>=b.length)){var f=b.eq(e);f.trigger("mouseenter");var g=d.$results.offset().top+d.$results.outerHeight(!1),h=f.offset().top+f.outerHeight(!1),i=d.$results.scrollTop()+h-g;0===e?d.$results.scrollTop(0):h>g&&d.$results.scrollTop(i)}}),b.on("results:focus",function(a){a.element.addClass("select2-results__option--highlighted")}),b.on("results:message",function(a){d.displayMessage(a)}),a.fn.mousewheel&&this.$results.on("mousewheel",function(a){var b=d.$results.scrollTop(),c=d.$results.get(0).scrollHeight-b+a.deltaY,e=a.deltaY>0&&b-a.deltaY<=0,f=a.deltaY<0&&c<=d.$results.height();e?(d.$results.scrollTop(0),a.preventDefault(),a.stopPropagation()):f&&(d.$results.scrollTop(d.$results.get(0).scrollHeight-d.$results.height()),a.preventDefault(),a.stopPropagation())}),this.$results.on("mouseup",".select2-results__option[aria-selected]",function(b){var c=a(this),e=c.data("data");if("true"===c.attr("aria-selected"))return void(d.options.get("multiple")?d.trigger("unselect",{originalEvent:b,data:e}):d.trigger("close",{}));d.trigger("select",{originalEvent:b,data:e})}),this.$results.on("mouseenter",".select2-results__option[aria-selected]",function(b){var c=a(this).data("data");d.getHighlightedResults().removeClass("select2-results__option--highlighted"),d.trigger("results:focus",{data:c,element:a(this)})})},c.prototype.getHighlightedResults=function(){return this.$results.find(".select2-results__option--highlighted")},c.prototype.destroy=function(){this.$results.remove()},c.prototype.ensureHighlightVisible=function(){var a=this.getHighlightedResults();if(0!==a.length){var b=this.$results.find("[aria-selected]"),c=b.index(a),d=this.$results.offset().top,e=a.offset().top,f=this.$results.scrollTop()+(e-d),g=e-d;f-=2*a.outerHeight(!1),c<=2?this.$results.scrollTop(0):(g>this.$results.outerHeight()||g<0)&&this.$results.scrollTop(f)}},c.prototype.template=function(b,c){var d=this.options.get("templateResult"),e=this.options.get("escapeMarkup"),f=d(b,c);null==f?c.style.display="none":"string"==typeof f?c.innerHTML=e(f):a(c).append(f)},c}),b.define("select2/keys",[],function(){return{BACKSPACE:8,TAB:9,ENTER:13,SHIFT:16,CTRL:17,ALT:18,ESC:27,SPACE:32,PAGE_UP:33,PAGE_DOWN:34,END:35,HOME:36,LEFT:37,UP:38,RIGHT:39,DOWN:40,DELETE:46}}),b.define("select2/selection/base",["jquery","../utils","../keys"],function(a,b,c){function d(a,b){this.$element=a,this.options=b,d.__super__.constructor.call(this)}return b.Extend(d,b.Observable),d.prototype.render=function(){var b=a('');return this._tabindex=0,null!=this.$element.data("old-tabindex")?this._tabindex=this.$element.data("old-tabindex"):null!=this.$element.attr("tabindex")&&(this._tabindex=this.$element.attr("tabindex")),b.attr("title",this.$element.attr("title")),b.attr("tabindex",this._tabindex),this.$selection=b,b},d.prototype.bind=function(a,b){var d=this,e=(a.id,a.id+"-results");this.container=a,this.$selection.on("focus",function(a){d.trigger("focus",a)}),this.$selection.on("blur",function(a){d._handleBlur(a)}),this.$selection.on("keydown",function(a){d.trigger("keypress",a),a.which===c.SPACE&&a.preventDefault()}),a.on("results:focus",function(a){d.$selection.attr("aria-activedescendant",a.data._resultId)}),a.on("selection:update",function(a){d.update(a.data)}),a.on("open",function(){d.$selection.attr("aria-expanded","true"),d.$selection.attr("aria-owns",e),d._attachCloseHandler(a)}),a.on("close",function(){d.$selection.attr("aria-expanded","false"),d.$selection.removeAttr("aria-activedescendant"),d.$selection.removeAttr("aria-owns"),d.$selection.focus(),d._detachCloseHandler(a)}),a.on("enable",function(){d.$selection.attr("tabindex",d._tabindex)}),a.on("disable",function(){d.$selection.attr("tabindex","-1")})},d.prototype._handleBlur=function(b){var c=this;window.setTimeout(function(){document.activeElement==c.$selection[0]||a.contains(c.$selection[0],document.activeElement)||c.trigger("blur",b)},1)},d.prototype._attachCloseHandler=function(b){a(document.body).on("mousedown.select2."+b.id,function(b){var c=a(b.target),d=c.closest(".select2");a(".select2.select2-container--open").each(function(){var b=a(this);this!=d[0]&&b.data("element").select2("close")})})},d.prototype._detachCloseHandler=function(b){a(document.body).off("mousedown.select2."+b.id)},d.prototype.position=function(a,b){b.find(".selection").append(a)},d.prototype.destroy=function(){this._detachCloseHandler(this.container)},d.prototype.update=function(a){throw new Error("The `update` method must be defined in child classes.")},d}),b.define("select2/selection/single",["jquery","./base","../utils","../keys"],function(a,b,c,d){function e(){e.__super__.constructor.apply(this,arguments)}return c.Extend(e,b),e.prototype.render=function(){var a=e.__super__.render.call(this);return a.addClass("select2-selection--single"),a.html(''),a},e.prototype.bind=function(a,b){var c=this;e.__super__.bind.apply(this,arguments);var d=a.id+"-container";this.$selection.find(".select2-selection__rendered").attr("id",d),this.$selection.attr("aria-labelledby",d),this.$selection.on("mousedown",function(a){1===a.which&&c.trigger("toggle",{originalEvent:a})}),this.$selection.on("focus",function(a){}),this.$selection.on("blur",function(a){}),a.on("focus",function(b){a.isOpen()||c.$selection.focus()}),a.on("selection:update",function(a){c.update(a.data)})},e.prototype.clear=function(){this.$selection.find(".select2-selection__rendered").empty()},e.prototype.display=function(a,b){var c=this.options.get("templateSelection");return this.options.get("escapeMarkup")(c(a,b))},e.prototype.selectionContainer=function(){return a("")},e.prototype.update=function(a){if(0===a.length)return void this.clear();var b=a[0],c=this.$selection.find(".select2-selection__rendered"),d=this.display(b,c);c.empty().append(d),c.prop("title",b.title||b.text)},e}),b.define("select2/selection/multiple",["jquery","./base","../utils"],function(a,b,c){function d(a,b){d.__super__.constructor.apply(this,arguments)}return c.Extend(d,b),d.prototype.render=function(){var a=d.__super__.render.call(this);return a.addClass("select2-selection--multiple"),a.html('
      '),a},d.prototype.bind=function(b,c){var e=this;d.__super__.bind.apply(this,arguments),this.$selection.on("click",function(a){e.trigger("toggle",{originalEvent:a})}),this.$selection.on("click",".select2-selection__choice__remove",function(b){if(!e.options.get("disabled")){var c=a(this),d=c.parent(),f=d.data("data");e.trigger("unselect",{originalEvent:b,data:f})}})},d.prototype.clear=function(){this.$selection.find(".select2-selection__rendered").empty()},d.prototype.display=function(a,b){var c=this.options.get("templateSelection");return this.options.get("escapeMarkup")(c(a,b))},d.prototype.selectionContainer=function(){return a('
    • ×
    • ')},d.prototype.update=function(a){if(this.clear(),0!==a.length){for(var b=[],d=0;d1||c)return a.call(this,b);this.clear();var d=this.createPlaceholder(this.placeholder);this.$selection.find(".select2-selection__rendered").append(d)},b}),b.define("select2/selection/allowClear",["jquery","../keys"],function(a,b){function c(){}return c.prototype.bind=function(a,b,c){var d=this;a.call(this,b,c),null==this.placeholder&&this.options.get("debug")&&window.console&&console.error&&console.error("Select2: The `allowClear` option should be used in combination with the `placeholder` option."),this.$selection.on("mousedown",".select2-selection__clear",function(a){d._handleClear(a)}),b.on("keypress",function(a){d._handleKeyboardClear(a,b)})},c.prototype._handleClear=function(a,b){if(!this.options.get("disabled")){var c=this.$selection.find(".select2-selection__clear");if(0!==c.length){b.stopPropagation();for(var d=c.data("data"),e=0;e0||0===c.length)){var d=a('×');d.data("data",c),this.$selection.find(".select2-selection__rendered").prepend(d)}},c}),b.define("select2/selection/search",["jquery","../utils","../keys"],function(a,b,c){function d(a,b,c){a.call(this,b,c)}return d.prototype.render=function(b){var c=a('');this.$searchContainer=c,this.$search=c.find("input");var d=b.call(this);return this._transferTabIndex(),d},d.prototype.bind=function(a,b,d){var e=this;a.call(this,b,d),b.on("open",function(){e.$search.trigger("focus")}),b.on("close",function(){e.$search.val(""),e.$search.removeAttr("aria-activedescendant"),e.$search.trigger("focus")}),b.on("enable",function(){e.$search.prop("disabled",!1),e._transferTabIndex()}),b.on("disable",function(){e.$search.prop("disabled",!0)}),b.on("focus",function(a){e.$search.trigger("focus")}),b.on("results:focus",function(a){e.$search.attr("aria-activedescendant",a.id)}),this.$selection.on("focusin",".select2-search--inline",function(a){e.trigger("focus",a)}),this.$selection.on("focusout",".select2-search--inline",function(a){e._handleBlur(a)}),this.$selection.on("keydown",".select2-search--inline",function(a){if(a.stopPropagation(),e.trigger("keypress",a),e._keyUpPrevented=a.isDefaultPrevented(),a.which===c.BACKSPACE&&""===e.$search.val()){var b=e.$searchContainer.prev(".select2-selection__choice");if(b.length>0){var d=b.data("data");e.searchRemoveChoice(d),a.preventDefault()}}});var f=document.documentMode,g=f&&f<=11;this.$selection.on("input.searchcheck",".select2-search--inline",function(a){if(g)return void e.$selection.off("input.search input.searchcheck");e.$selection.off("keyup.search")}),this.$selection.on("keyup.search input.search",".select2-search--inline",function(a){if(g&&"input"===a.type)return void e.$selection.off("input.search input.searchcheck");var b=a.which;b!=c.SHIFT&&b!=c.CTRL&&b!=c.ALT&&b!=c.TAB&&e.handleSearch(a)})},d.prototype._transferTabIndex=function(a){this.$search.attr("tabindex",this.$selection.attr("tabindex")),this.$selection.attr("tabindex","-1")},d.prototype.createPlaceholder=function(a,b){this.$search.attr("placeholder",b.text)},d.prototype.update=function(a,b){var c=this.$search[0]==document.activeElement;this.$search.attr("placeholder",""),a.call(this,b),this.$selection.find(".select2-selection__rendered").append(this.$searchContainer),this.resizeSearch(),c&&this.$search.focus()},d.prototype.handleSearch=function(){if(this.resizeSearch(),!this._keyUpPrevented){var a=this.$search.val();this.trigger("query",{term:a})}this._keyUpPrevented=!1},d.prototype.searchRemoveChoice=function(a,b){this.trigger("unselect",{data:b}),this.$search.val(b.text),this.handleSearch()},d.prototype.resizeSearch=function(){this.$search.css("width","25px");var a="";if(""!==this.$search.attr("placeholder"))a=this.$selection.find(".select2-selection__rendered").innerWidth();else{a=.75*(this.$search.val().length+1)+"em"}this.$search.css("width",a)},d}),b.define("select2/selection/eventRelay",["jquery"],function(a){function b(){}return b.prototype.bind=function(b,c,d){var e=this,f=["open","opening","close","closing","select","selecting","unselect","unselecting"],g=["opening","closing","selecting","unselecting"];b.call(this,c,d),c.on("*",function(b,c){if(-1!==a.inArray(b,f)){c=c||{};var d=a.Event("select2:"+b,{params:c});e.$element.trigger(d),-1!==a.inArray(b,g)&&(c.prevented=d.isDefaultPrevented())}})},b}),b.define("select2/translation",["jquery","require"],function(a,b){function c(a){this.dict=a||{}}return c.prototype.all=function(){return this.dict},c.prototype.get=function(a){return this.dict[a]},c.prototype.extend=function(b){this.dict=a.extend({},b.all(),this.dict)},c._cache={},c.loadPath=function(a){if(!(a in c._cache)){var d=b(a);c._cache[a]=d}return new c(c._cache[a])},c}),b.define("select2/diacritics",[],function(){return{"Ⓐ":"A","A":"A","À":"A","Á":"A","Â":"A","Ầ":"A","Ấ":"A","Ẫ":"A","Ẩ":"A","Ã":"A","Ā":"A","Ă":"A","Ằ":"A","Ắ":"A","Ẵ":"A","Ẳ":"A","Ȧ":"A","Ǡ":"A","Ä":"A","Ǟ":"A","Ả":"A","Å":"A","Ǻ":"A","Ǎ":"A","Ȁ":"A","Ȃ":"A","Ạ":"A","Ậ":"A","Ặ":"A","Ḁ":"A","Ą":"A","Ⱥ":"A","Ɐ":"A","Ꜳ":"AA","Æ":"AE","Ǽ":"AE","Ǣ":"AE","Ꜵ":"AO","Ꜷ":"AU","Ꜹ":"AV","Ꜻ":"AV","Ꜽ":"AY","Ⓑ":"B","B":"B","Ḃ":"B","Ḅ":"B","Ḇ":"B","Ƀ":"B","Ƃ":"B","Ɓ":"B","Ⓒ":"C","C":"C","Ć":"C","Ĉ":"C","Ċ":"C","Č":"C","Ç":"C","Ḉ":"C","Ƈ":"C","Ȼ":"C","Ꜿ":"C","Ⓓ":"D","D":"D","Ḋ":"D","Ď":"D","Ḍ":"D","Ḑ":"D","Ḓ":"D","Ḏ":"D","Đ":"D","Ƌ":"D","Ɗ":"D","Ɖ":"D","Ꝺ":"D","DZ":"DZ","DŽ":"DZ","Dz":"Dz","Dž":"Dz","Ⓔ":"E","E":"E","È":"E","É":"E","Ê":"E","Ề":"E","Ế":"E","Ễ":"E","Ể":"E","Ẽ":"E","Ē":"E","Ḕ":"E","Ḗ":"E","Ĕ":"E","Ė":"E","Ë":"E","Ẻ":"E","Ě":"E","Ȅ":"E","Ȇ":"E","Ẹ":"E","Ệ":"E","Ȩ":"E","Ḝ":"E","Ę":"E","Ḙ":"E","Ḛ":"E","Ɛ":"E","Ǝ":"E","Ⓕ":"F","F":"F","Ḟ":"F","Ƒ":"F","Ꝼ":"F","Ⓖ":"G","G":"G","Ǵ":"G","Ĝ":"G","Ḡ":"G","Ğ":"G","Ġ":"G","Ǧ":"G","Ģ":"G","Ǥ":"G","Ɠ":"G","Ꞡ":"G","Ᵹ":"G","Ꝿ":"G","Ⓗ":"H","H":"H","Ĥ":"H","Ḣ":"H","Ḧ":"H","Ȟ":"H","Ḥ":"H","Ḩ":"H","Ḫ":"H","Ħ":"H","Ⱨ":"H","Ⱶ":"H","Ɥ":"H","Ⓘ":"I","I":"I","Ì":"I","Í":"I","Î":"I","Ĩ":"I","Ī":"I","Ĭ":"I","İ":"I","Ï":"I","Ḯ":"I","Ỉ":"I","Ǐ":"I","Ȉ":"I","Ȋ":"I","Ị":"I","Į":"I","Ḭ":"I","Ɨ":"I","Ⓙ":"J","J":"J","Ĵ":"J","Ɉ":"J","Ⓚ":"K","K":"K","Ḱ":"K","Ǩ":"K","Ḳ":"K","Ķ":"K","Ḵ":"K","Ƙ":"K","Ⱪ":"K","Ꝁ":"K","Ꝃ":"K","Ꝅ":"K","Ꞣ":"K","Ⓛ":"L","L":"L","Ŀ":"L","Ĺ":"L","Ľ":"L","Ḷ":"L","Ḹ":"L","Ļ":"L","Ḽ":"L","Ḻ":"L","Ł":"L","Ƚ":"L","Ɫ":"L","Ⱡ":"L","Ꝉ":"L","Ꝇ":"L","Ꞁ":"L","LJ":"LJ","Lj":"Lj","Ⓜ":"M","M":"M","Ḿ":"M","Ṁ":"M","Ṃ":"M","Ɱ":"M","Ɯ":"M","Ⓝ":"N","N":"N","Ǹ":"N","Ń":"N","Ñ":"N","Ṅ":"N","Ň":"N","Ṇ":"N","Ņ":"N","Ṋ":"N","Ṉ":"N","Ƞ":"N","Ɲ":"N","Ꞑ":"N","Ꞥ":"N","NJ":"NJ","Nj":"Nj","Ⓞ":"O","O":"O","Ò":"O","Ó":"O","Ô":"O","Ồ":"O","Ố":"O","Ỗ":"O","Ổ":"O","Õ":"O","Ṍ":"O","Ȭ":"O","Ṏ":"O","Ō":"O","Ṑ":"O","Ṓ":"O","Ŏ":"O","Ȯ":"O","Ȱ":"O","Ö":"O","Ȫ":"O","Ỏ":"O","Ő":"O","Ǒ":"O","Ȍ":"O","Ȏ":"O","Ơ":"O","Ờ":"O","Ớ":"O","Ỡ":"O","Ở":"O","Ợ":"O","Ọ":"O","Ộ":"O","Ǫ":"O","Ǭ":"O","Ø":"O","Ǿ":"O","Ɔ":"O","Ɵ":"O","Ꝋ":"O","Ꝍ":"O","Ƣ":"OI","Ꝏ":"OO","Ȣ":"OU","Ⓟ":"P","P":"P","Ṕ":"P","Ṗ":"P","Ƥ":"P","Ᵽ":"P","Ꝑ":"P","Ꝓ":"P","Ꝕ":"P","Ⓠ":"Q","Q":"Q","Ꝗ":"Q","Ꝙ":"Q","Ɋ":"Q","Ⓡ":"R","R":"R","Ŕ":"R","Ṙ":"R","Ř":"R","Ȑ":"R","Ȓ":"R","Ṛ":"R","Ṝ":"R","Ŗ":"R","Ṟ":"R","Ɍ":"R","Ɽ":"R","Ꝛ":"R","Ꞧ":"R","Ꞃ":"R","Ⓢ":"S","S":"S","ẞ":"S","Ś":"S","Ṥ":"S","Ŝ":"S","Ṡ":"S","Š":"S","Ṧ":"S","Ṣ":"S","Ṩ":"S","Ș":"S","Ş":"S","Ȿ":"S","Ꞩ":"S","Ꞅ":"S","Ⓣ":"T","T":"T","Ṫ":"T","Ť":"T","Ṭ":"T","Ț":"T","Ţ":"T","Ṱ":"T","Ṯ":"T","Ŧ":"T","Ƭ":"T","Ʈ":"T","Ⱦ":"T","Ꞇ":"T","Ꜩ":"TZ","Ⓤ":"U","U":"U","Ù":"U","Ú":"U","Û":"U","Ũ":"U","Ṹ":"U","Ū":"U","Ṻ":"U","Ŭ":"U","Ü":"U","Ǜ":"U","Ǘ":"U","Ǖ":"U","Ǚ":"U","Ủ":"U","Ů":"U","Ű":"U","Ǔ":"U","Ȕ":"U","Ȗ":"U","Ư":"U","Ừ":"U","Ứ":"U","Ữ":"U","Ử":"U","Ự":"U","Ụ":"U","Ṳ":"U","Ų":"U","Ṷ":"U","Ṵ":"U","Ʉ":"U","Ⓥ":"V","V":"V","Ṽ":"V","Ṿ":"V","Ʋ":"V","Ꝟ":"V","Ʌ":"V","Ꝡ":"VY","Ⓦ":"W","W":"W","Ẁ":"W","Ẃ":"W","Ŵ":"W","Ẇ":"W","Ẅ":"W","Ẉ":"W","Ⱳ":"W","Ⓧ":"X","X":"X","Ẋ":"X","Ẍ":"X","Ⓨ":"Y","Y":"Y","Ỳ":"Y","Ý":"Y","Ŷ":"Y","Ỹ":"Y","Ȳ":"Y","Ẏ":"Y","Ÿ":"Y","Ỷ":"Y","Ỵ":"Y","Ƴ":"Y","Ɏ":"Y","Ỿ":"Y","Ⓩ":"Z","Z":"Z","Ź":"Z","Ẑ":"Z","Ż":"Z","Ž":"Z","Ẓ":"Z","Ẕ":"Z","Ƶ":"Z","Ȥ":"Z","Ɀ":"Z","Ⱬ":"Z","Ꝣ":"Z","ⓐ":"a","a":"a","ẚ":"a","à":"a","á":"a","â":"a","ầ":"a","ấ":"a","ẫ":"a","ẩ":"a","ã":"a","ā":"a","ă":"a","ằ":"a","ắ":"a","ẵ":"a","ẳ":"a","ȧ":"a","ǡ":"a","ä":"a","ǟ":"a","ả":"a","å":"a","ǻ":"a","ǎ":"a","ȁ":"a","ȃ":"a","ạ":"a","ậ":"a","ặ":"a","ḁ":"a","ą":"a","ⱥ":"a","ɐ":"a","ꜳ":"aa","æ":"ae","ǽ":"ae","ǣ":"ae","ꜵ":"ao","ꜷ":"au","ꜹ":"av","ꜻ":"av","ꜽ":"ay","ⓑ":"b","b":"b","ḃ":"b","ḅ":"b","ḇ":"b","ƀ":"b","ƃ":"b","ɓ":"b","ⓒ":"c","c":"c","ć":"c","ĉ":"c","ċ":"c","č":"c","ç":"c","ḉ":"c","ƈ":"c","ȼ":"c","ꜿ":"c","ↄ":"c","ⓓ":"d","d":"d","ḋ":"d","ď":"d","ḍ":"d","ḑ":"d","ḓ":"d","ḏ":"d","đ":"d","ƌ":"d","ɖ":"d","ɗ":"d","ꝺ":"d","dz":"dz","dž":"dz","ⓔ":"e","e":"e","è":"e","é":"e","ê":"e","ề":"e","ế":"e","ễ":"e","ể":"e","ẽ":"e","ē":"e","ḕ":"e","ḗ":"e","ĕ":"e","ė":"e","ë":"e","ẻ":"e","ě":"e","ȅ":"e","ȇ":"e","ẹ":"e","ệ":"e","ȩ":"e","ḝ":"e","ę":"e","ḙ":"e","ḛ":"e","ɇ":"e","ɛ":"e","ǝ":"e","ⓕ":"f","f":"f","ḟ":"f","ƒ":"f","ꝼ":"f","ⓖ":"g","g":"g","ǵ":"g","ĝ":"g","ḡ":"g","ğ":"g","ġ":"g","ǧ":"g","ģ":"g","ǥ":"g","ɠ":"g","ꞡ":"g","ᵹ":"g","ꝿ":"g","ⓗ":"h","h":"h","ĥ":"h","ḣ":"h","ḧ":"h","ȟ":"h","ḥ":"h","ḩ":"h","ḫ":"h","ẖ":"h","ħ":"h","ⱨ":"h","ⱶ":"h","ɥ":"h","ƕ":"hv","ⓘ":"i","i":"i","ì":"i","í":"i","î":"i","ĩ":"i","ī":"i","ĭ":"i","ï":"i","ḯ":"i","ỉ":"i","ǐ":"i","ȉ":"i","ȋ":"i","ị":"i","į":"i","ḭ":"i","ɨ":"i","ı":"i","ⓙ":"j","j":"j","ĵ":"j","ǰ":"j","ɉ":"j","ⓚ":"k","k":"k","ḱ":"k","ǩ":"k","ḳ":"k","ķ":"k","ḵ":"k","ƙ":"k","ⱪ":"k","ꝁ":"k","ꝃ":"k","ꝅ":"k","ꞣ":"k","ⓛ":"l","l":"l","ŀ":"l","ĺ":"l","ľ":"l","ḷ":"l","ḹ":"l","ļ":"l","ḽ":"l","ḻ":"l","ſ":"l","ł":"l","ƚ":"l","ɫ":"l","ⱡ":"l","ꝉ":"l","ꞁ":"l","ꝇ":"l","lj":"lj","ⓜ":"m","m":"m","ḿ":"m","ṁ":"m","ṃ":"m","ɱ":"m","ɯ":"m","ⓝ":"n","n":"n","ǹ":"n","ń":"n","ñ":"n","ṅ":"n","ň":"n","ṇ":"n","ņ":"n","ṋ":"n","ṉ":"n","ƞ":"n","ɲ":"n","ʼn":"n","ꞑ":"n","ꞥ":"n","nj":"nj","ⓞ":"o","o":"o","ò":"o","ó":"o","ô":"o","ồ":"o","ố":"o","ỗ":"o","ổ":"o","õ":"o","ṍ":"o","ȭ":"o","ṏ":"o","ō":"o","ṑ":"o","ṓ":"o","ŏ":"o","ȯ":"o","ȱ":"o","ö":"o","ȫ":"o","ỏ":"o","ő":"o","ǒ":"o","ȍ":"o","ȏ":"o","ơ":"o","ờ":"o","ớ":"o","ỡ":"o","ở":"o","ợ":"o","ọ":"o","ộ":"o","ǫ":"o","ǭ":"o","ø":"o","ǿ":"o","ɔ":"o","ꝋ":"o","ꝍ":"o","ɵ":"o","ƣ":"oi","ȣ":"ou","ꝏ":"oo","ⓟ":"p","p":"p","ṕ":"p","ṗ":"p","ƥ":"p","ᵽ":"p","ꝑ":"p","ꝓ":"p","ꝕ":"p","ⓠ":"q","q":"q","ɋ":"q","ꝗ":"q","ꝙ":"q","ⓡ":"r","r":"r","ŕ":"r","ṙ":"r","ř":"r","ȑ":"r","ȓ":"r","ṛ":"r","ṝ":"r","ŗ":"r","ṟ":"r","ɍ":"r","ɽ":"r","ꝛ":"r","ꞧ":"r","ꞃ":"r","ⓢ":"s","s":"s","ß":"s","ś":"s","ṥ":"s","ŝ":"s","ṡ":"s","š":"s","ṧ":"s","ṣ":"s","ṩ":"s","ș":"s","ş":"s","ȿ":"s","ꞩ":"s","ꞅ":"s","ẛ":"s","ⓣ":"t","t":"t","ṫ":"t","ẗ":"t","ť":"t","ṭ":"t","ț":"t","ţ":"t","ṱ":"t","ṯ":"t","ŧ":"t","ƭ":"t","ʈ":"t","ⱦ":"t","ꞇ":"t","ꜩ":"tz","ⓤ":"u","u":"u","ù":"u","ú":"u","û":"u","ũ":"u","ṹ":"u","ū":"u","ṻ":"u","ŭ":"u","ü":"u","ǜ":"u","ǘ":"u","ǖ":"u","ǚ":"u","ủ":"u","ů":"u","ű":"u","ǔ":"u","ȕ":"u","ȗ":"u","ư":"u","ừ":"u","ứ":"u","ữ":"u","ử":"u","ự":"u","ụ":"u","ṳ":"u","ų":"u","ṷ":"u","ṵ":"u","ʉ":"u","ⓥ":"v","v":"v","ṽ":"v","ṿ":"v","ʋ":"v","ꝟ":"v","ʌ":"v","ꝡ":"vy","ⓦ":"w","w":"w","ẁ":"w","ẃ":"w","ŵ":"w","ẇ":"w","ẅ":"w","ẘ":"w","ẉ":"w","ⱳ":"w","ⓧ":"x","x":"x","ẋ":"x","ẍ":"x","ⓨ":"y","y":"y","ỳ":"y","ý":"y","ŷ":"y","ỹ":"y","ȳ":"y","ẏ":"y","ÿ":"y","ỷ":"y","ẙ":"y","ỵ":"y","ƴ":"y","ɏ":"y","ỿ":"y","ⓩ":"z","z":"z","ź":"z","ẑ":"z","ż":"z","ž":"z","ẓ":"z","ẕ":"z","ƶ":"z","ȥ":"z","ɀ":"z","ⱬ":"z","ꝣ":"z","Ά":"Α","Έ":"Ε","Ή":"Η","Ί":"Ι","Ϊ":"Ι","Ό":"Ο","Ύ":"Υ","Ϋ":"Υ","Ώ":"Ω","ά":"α","έ":"ε","ή":"η","ί":"ι","ϊ":"ι","ΐ":"ι","ό":"ο","ύ":"υ","ϋ":"υ","ΰ":"υ","ω":"ω","ς":"σ"}}),b.define("select2/data/base",["../utils"],function(a){function b(a,c){b.__super__.constructor.call(this)}return a.Extend(b,a.Observable),b.prototype.current=function(a){throw new Error("The `current` method must be defined in child classes.")},b.prototype.query=function(a,b){throw new Error("The `query` method must be defined in child classes.")},b.prototype.bind=function(a,b){},b.prototype.destroy=function(){},b.prototype.generateResultId=function(b,c){var d=b.id+"-result-";return d+=a.generateChars(4),null!=c.id?d+="-"+c.id.toString():d+="-"+a.generateChars(4),d},b}),b.define("select2/data/select",["./base","../utils","jquery"],function(a,b,c){function d(a,b){this.$element=a,this.options=b,d.__super__.constructor.call(this)}return b.Extend(d,a),d.prototype.current=function(a){var b=[],d=this;this.$element.find(":selected").each(function(){var a=c(this),e=d.item(a);b.push(e)}),a(b)},d.prototype.select=function(a){var b=this;if(a.selected=!0,c(a.element).is("option"))return a.element.selected=!0,void this.$element.trigger("change");if(this.$element.prop("multiple"))this.current(function(d){var e=[];a=[a],a.push.apply(a,d);for(var f=0;f=0){var k=f.filter(d(j)),l=this.item(k),m=c.extend(!0,{},j,l),n=this.option(m);k.replaceWith(n)}else{var o=this.option(j);if(j.children){var p=this.convertToOptions(j.children);b.appendMany(o,p)}h.push(o)}}return h},d}),b.define("select2/data/ajax",["./array","../utils","jquery"],function(a,b,c){function d(a,b){this.ajaxOptions=this._applyDefaults(b.get("ajax")),null!=this.ajaxOptions.processResults&&(this.processResults=this.ajaxOptions.processResults),d.__super__.constructor.call(this,a,b)}return b.Extend(d,a),d.prototype._applyDefaults=function(a){var b={data:function(a){return c.extend({},a,{q:a.term})},transport:function(a,b,d){var e=c.ajax(a);return e.then(b),e.fail(d),e}};return c.extend({},b,a,!0)},d.prototype.processResults=function(a){return a},d.prototype.query=function(a,b){function d(){var d=f.transport(f,function(d){var f=e.processResults(d,a);e.options.get("debug")&&window.console&&console.error&&(f&&f.results&&c.isArray(f.results)||console.error("Select2: The AJAX results did not return an array in the `results` key of the response.")),b(f)},function(){d.status&&"0"===d.status||e.trigger("results:message",{message:"errorLoading"})});e._request=d}var e=this;null!=this._request&&(c.isFunction(this._request.abort)&&this._request.abort(),this._request=null);var f=c.extend({type:"GET"},this.ajaxOptions);"function"==typeof f.url&&(f.url=f.url.call(this.$element,a)),"function"==typeof f.data&&(f.data=f.data.call(this.$element,a)),this.ajaxOptions.delay&&null!=a.term?(this._queryTimeout&&window.clearTimeout(this._queryTimeout),this._queryTimeout=window.setTimeout(d,this.ajaxOptions.delay)):d()},d}),b.define("select2/data/tags",["jquery"],function(a){function b(b,c,d){var e=d.get("tags"),f=d.get("createTag");void 0!==f&&(this.createTag=f);var g=d.get("insertTag");if(void 0!==g&&(this.insertTag=g),b.call(this,c,d),a.isArray(e))for(var h=0;h0&&b.term.length>this.maximumInputLength)return void this.trigger("results:message",{message:"inputTooLong",args:{maximum:this.maximumInputLength,input:b.term,params:b}});a.call(this,b,c)},a}),b.define("select2/data/maximumSelectionLength",[],function(){function a(a,b,c){this.maximumSelectionLength=c.get("maximumSelectionLength"),a.call(this,b,c)}return a.prototype.query=function(a,b,c){var d=this;this.current(function(e){var f=null!=e?e.length:0;if(d.maximumSelectionLength>0&&f>=d.maximumSelectionLength)return void d.trigger("results:message",{message:"maximumSelected",args:{maximum:d.maximumSelectionLength}});a.call(d,b,c)})},a}),b.define("select2/dropdown",["jquery","./utils"],function(a,b){function c(a,b){this.$element=a,this.options=b,c.__super__.constructor.call(this)}return b.Extend(c,b.Observable),c.prototype.render=function(){var b=a('');return b.attr("dir",this.options.get("dir")),this.$dropdown=b,b},c.prototype.bind=function(){},c.prototype.position=function(a,b){},c.prototype.destroy=function(){this.$dropdown.remove()},c}),b.define("select2/dropdown/search",["jquery","../utils"],function(a,b){function c(){}return c.prototype.render=function(b){var c=b.call(this),d=a('');return this.$searchContainer=d,this.$search=d.find("input"),c.prepend(d),c},c.prototype.bind=function(b,c,d){var e=this;b.call(this,c,d),this.$search.on("keydown",function(a){e.trigger("keypress",a),e._keyUpPrevented=a.isDefaultPrevented()}),this.$search.on("input",function(b){a(this).off("keyup")}),this.$search.on("keyup input",function(a){e.handleSearch(a)}),c.on("open",function(){e.$search.attr("tabindex",0),e.$search.focus(),window.setTimeout(function(){e.$search.focus()},0)}),c.on("close",function(){e.$search.attr("tabindex",-1),e.$search.val("")}),c.on("focus",function(){c.isOpen()||e.$search.focus()}),c.on("results:all",function(a){if(null==a.query.term||""===a.query.term){e.showSearch(a)?e.$searchContainer.removeClass("select2-search--hide"):e.$searchContainer.addClass("select2-search--hide")}})},c.prototype.handleSearch=function(a){if(!this._keyUpPrevented){var b=this.$search.val();this.trigger("query",{term:b})}this._keyUpPrevented=!1},c.prototype.showSearch=function(a,b){return!0},c}),b.define("select2/dropdown/hidePlaceholder",[],function(){function a(a,b,c,d){this.placeholder=this.normalizePlaceholder(c.get("placeholder")),a.call(this,b,c,d)}return a.prototype.append=function(a,b){b.results=this.removePlaceholder(b.results),a.call(this,b)},a.prototype.normalizePlaceholder=function(a,b){return"string"==typeof b&&(b={id:"",text:b}),b},a.prototype.removePlaceholder=function(a,b){for(var c=b.slice(0),d=b.length-1;d>=0;d--){var e=b[d];this.placeholder.id===e.id&&c.splice(d,1)}return c},a}),b.define("select2/dropdown/infiniteScroll",["jquery"],function(a){function b(a,b,c,d){this.lastParams={},a.call(this,b,c,d),this.$loadingMore=this.createLoadingMore(),this.loading=!1}return b.prototype.append=function(a,b){this.$loadingMore.remove(),this.loading=!1,a.call(this,b),this.showLoadingMore(b)&&this.$results.append(this.$loadingMore)},b.prototype.bind=function(b,c,d){var e=this;b.call(this,c,d),c.on("query",function(a){e.lastParams=a,e.loading=!0}),c.on("query:append",function(a){e.lastParams=a,e.loading=!0}),this.$results.on("scroll",function(){var b=a.contains(document.documentElement,e.$loadingMore[0]);if(!e.loading&&b){e.$results.offset().top+e.$results.outerHeight(!1)+50>=e.$loadingMore.offset().top+e.$loadingMore.outerHeight(!1)&&e.loadMore()}})},b.prototype.loadMore=function(){this.loading=!0;var b=a.extend({},{page:1},this.lastParams);b.page++,this.trigger("query:append",b)},b.prototype.showLoadingMore=function(a,b){return b.pagination&&b.pagination.more},b.prototype.createLoadingMore=function(){var b=a('
    • '),c=this.options.get("translations").get("loadingMore");return b.html(c(this.lastParams)),b},b}),b.define("select2/dropdown/attachBody",["jquery","../utils"],function(a,b){function c(b,c,d){this.$dropdownParent=d.get("dropdownParent")||a(document.body),b.call(this,c,d)}return c.prototype.bind=function(a,b,c){var d=this,e=!1;a.call(this,b,c),b.on("open",function(){d._showDropdown(),d._attachPositioningHandler(b),e||(e=!0,b.on("results:all",function(){d._positionDropdown(),d._resizeDropdown()}),b.on("results:append",function(){d._positionDropdown(),d._resizeDropdown()}))}),b.on("close",function(){d._hideDropdown(),d._detachPositioningHandler(b)}),this.$dropdownContainer.on("mousedown",function(a){a.stopPropagation()})},c.prototype.destroy=function(a){a.call(this),this.$dropdownContainer.remove()},c.prototype.position=function(a,b,c){b.attr("class",c.attr("class")),b.removeClass("select2"),b.addClass("select2-container--open"),b.css({position:"absolute",top:-999999}),this.$container=c},c.prototype.render=function(b){var c=a(""),d=b.call(this);return c.append(d),this.$dropdownContainer=c,c},c.prototype._hideDropdown=function(a){this.$dropdownContainer.detach()},c.prototype._attachPositioningHandler=function(c,d){var e=this,f="scroll.select2."+d.id,g="resize.select2."+d.id,h="orientationchange.select2."+d.id,i=this.$container.parents().filter(b.hasScroll);i.each(function(){a(this).data("select2-scroll-position",{x:a(this).scrollLeft(),y:a(this).scrollTop()})}),i.on(f,function(b){var c=a(this).data("select2-scroll-position");a(this).scrollTop(c.y)}),a(window).on(f+" "+g+" "+h,function(a){e._positionDropdown(),e._resizeDropdown()})},c.prototype._detachPositioningHandler=function(c,d){var e="scroll.select2."+d.id,f="resize.select2."+d.id,g="orientationchange.select2."+d.id;this.$container.parents().filter(b.hasScroll).off(e),a(window).off(e+" "+f+" "+g)},c.prototype._positionDropdown=function(){var b=a(window),c=this.$dropdown.hasClass("select2-dropdown--above"),d=this.$dropdown.hasClass("select2-dropdown--below"),e=null,f=this.$container.offset();f.bottom=f.top+this.$container.outerHeight(!1);var g={height:this.$container.outerHeight(!1)};g.top=f.top,g.bottom=f.top+g.height;var h={height:this.$dropdown.outerHeight(!1)},i={top:b.scrollTop(),bottom:b.scrollTop()+b.height()},j=i.topf.bottom+h.height,l={left:f.left,top:g.bottom},m=this.$dropdownParent;"static"===m.css("position")&&(m=m.offsetParent());var n=m.offset();l.top-=n.top,l.left-=n.left,c||d||(e="below"),k||!j||c?!j&&k&&c&&(e="below"):e="above",("above"==e||c&&"below"!==e)&&(l.top=g.top-n.top-h.height),null!=e&&(this.$dropdown.removeClass("select2-dropdown--below select2-dropdown--above").addClass("select2-dropdown--"+e),this.$container.removeClass("select2-container--below select2-container--above").addClass("select2-container--"+e)),this.$dropdownContainer.css(l)},c.prototype._resizeDropdown=function(){var a={width:this.$container.outerWidth(!1)+"px"};this.options.get("dropdownAutoWidth")&&(a.minWidth=a.width,a.position="relative",a.width="auto"),this.$dropdown.css(a)},c.prototype._showDropdown=function(a){this.$dropdownContainer.appendTo(this.$dropdownParent),this._positionDropdown(),this._resizeDropdown()},c}),b.define("select2/dropdown/minimumResultsForSearch",[],function(){function a(b){for(var c=0,d=0;d0&&(l.dataAdapter=j.Decorate(l.dataAdapter,r)),l.maximumInputLength>0&&(l.dataAdapter=j.Decorate(l.dataAdapter,s)),l.maximumSelectionLength>0&&(l.dataAdapter=j.Decorate(l.dataAdapter,t)),l.tags&&(l.dataAdapter=j.Decorate(l.dataAdapter,p)),null==l.tokenSeparators&&null==l.tokenizer||(l.dataAdapter=j.Decorate(l.dataAdapter,q)),null!=l.query){var C=b(l.amdBase+"compat/query");l.dataAdapter=j.Decorate(l.dataAdapter,C)}if(null!=l.initSelection){var D=b(l.amdBase+"compat/initSelection");l.dataAdapter=j.Decorate(l.dataAdapter,D)}}if(null==l.resultsAdapter&&(l.resultsAdapter=c,null!=l.ajax&&(l.resultsAdapter=j.Decorate(l.resultsAdapter,x)),null!=l.placeholder&&(l.resultsAdapter=j.Decorate(l.resultsAdapter,w)),l.selectOnClose&&(l.resultsAdapter=j.Decorate(l.resultsAdapter,A))),null==l.dropdownAdapter){if(l.multiple)l.dropdownAdapter=u;else{var E=j.Decorate(u,v);l.dropdownAdapter=E}if(0!==l.minimumResultsForSearch&&(l.dropdownAdapter=j.Decorate(l.dropdownAdapter,z)),l.closeOnSelect&&(l.dropdownAdapter=j.Decorate(l.dropdownAdapter,B)),null!=l.dropdownCssClass||null!=l.dropdownCss||null!=l.adaptDropdownCssClass){var F=b(l.amdBase+"compat/dropdownCss");l.dropdownAdapter=j.Decorate(l.dropdownAdapter,F)}l.dropdownAdapter=j.Decorate(l.dropdownAdapter,y)}if(null==l.selectionAdapter){if(l.multiple?l.selectionAdapter=e:l.selectionAdapter=d,null!=l.placeholder&&(l.selectionAdapter=j.Decorate(l.selectionAdapter,f)),l.allowClear&&(l.selectionAdapter=j.Decorate(l.selectionAdapter,g)),l.multiple&&(l.selectionAdapter=j.Decorate(l.selectionAdapter,h)),null!=l.containerCssClass||null!=l.containerCss||null!=l.adaptContainerCssClass){var G=b(l.amdBase+"compat/containerCss");l.selectionAdapter=j.Decorate(l.selectionAdapter,G)}l.selectionAdapter=j.Decorate(l.selectionAdapter,i)}if("string"==typeof l.language)if(l.language.indexOf("-")>0){var H=l.language.split("-"),I=H[0];l.language=[l.language,I]}else l.language=[l.language];if(a.isArray(l.language)){var J=new k;l.language.push("en");for(var K=l.language,L=0;L0){for(var f=a.extend(!0,{},e),g=e.children.length-1;g>=0;g--){null==c(d,e.children[g])&&f.children.splice(g,1)}return f.children.length>0?f:c(d,f)}var h=b(e.text).toUpperCase(),i=b(d.term).toUpperCase();return h.indexOf(i)>-1?e:null}this.defaults={amdBase:"./",amdLanguageBase:"./i18n/",closeOnSelect:!0,debug:!1,dropdownAutoWidth:!1,escapeMarkup:j.escapeMarkup,language:C,matcher:c,minimumInputLength:0,maximumInputLength:0,maximumSelectionLength:0,minimumResultsForSearch:0,selectOnClose:!1,sorter:function(a){return a},templateResult:function(a){return a.text},templateSelection:function(a){return a.text},theme:"default",width:"resolve"}},D.prototype.set=function(b,c){var d=a.camelCase(b),e={};e[d]=c;var f=j._convertData(e);a.extend(this.defaults,f)},new D}),b.define("select2/options",["require","jquery","./defaults","./utils"],function(a,b,c,d){function e(b,e){if(this.options=b,null!=e&&this.fromElement(e),this.options=c.apply(this.options),e&&e.is("input")){var f=a(this.get("amdBase")+"compat/inputData");this.options.dataAdapter=d.Decorate(this.options.dataAdapter,f)}}return e.prototype.fromElement=function(a){var c=["select2"];null==this.options.multiple&&(this.options.multiple=a.prop("multiple")),null==this.options.disabled&&(this.options.disabled=a.prop("disabled")),null==this.options.language&&(a.prop("lang")?this.options.language=a.prop("lang").toLowerCase():a.closest("[lang]").prop("lang")&&(this.options.language=a.closest("[lang]").prop("lang"))),null==this.options.dir&&(a.prop("dir")?this.options.dir=a.prop("dir"):a.closest("[dir]").prop("dir")?this.options.dir=a.closest("[dir]").prop("dir"):this.options.dir="ltr"),a.prop("disabled",this.options.disabled),a.prop("multiple",this.options.multiple),a.data("select2Tags")&&(this.options.debug&&window.console&&console.warn&&console.warn('Select2: The `data-select2-tags` attribute has been changed to use the `data-data` and `data-tags="true"` attributes and will be removed in future versions of Select2.'),a.data("data",a.data("select2Tags")),a.data("tags",!0)),a.data("ajaxUrl")&&(this.options.debug&&window.console&&console.warn&&console.warn("Select2: The `data-ajax-url` attribute has been changed to `data-ajax--url` and support for the old attribute will be removed in future versions of Select2."),a.attr("ajax--url",a.data("ajaxUrl")),a.data("ajax--url",a.data("ajaxUrl")));var e={};e=b.fn.jquery&&"1."==b.fn.jquery.substr(0,2)&&a[0].dataset?b.extend(!0,{},a[0].dataset,a.data()):a.data();var f=b.extend(!0,{},e);f=d._convertData(f);for(var g in f)b.inArray(g,c)>-1||(b.isPlainObject(this.options[g])?b.extend(this.options[g],f[g]):this.options[g]=f[g]);return this},e.prototype.get=function(a){return this.options[a]},e.prototype.set=function(a,b){this.options[a]=b},e}),b.define("select2/core",["jquery","./options","./utils","./keys"],function(a,b,c,d){var e=function(a,c){null!=a.data("select2")&&a.data("select2").destroy(),this.$element=a,this.id=this._generateId(a),c=c||{},this.options=new b(c,a),e.__super__.constructor.call(this);var d=a.attr("tabindex")||0;a.data("old-tabindex",d),a.attr("tabindex","-1");var f=this.options.get("dataAdapter");this.dataAdapter=new f(a,this.options);var g=this.render();this._placeContainer(g);var h=this.options.get("selectionAdapter");this.selection=new h(a,this.options),this.$selection=this.selection.render(),this.selection.position(this.$selection,g);var i=this.options.get("dropdownAdapter");this.dropdown=new i(a,this.options),this.$dropdown=this.dropdown.render(),this.dropdown.position(this.$dropdown,g);var j=this.options.get("resultsAdapter");this.results=new j(a,this.options,this.dataAdapter),this.$results=this.results.render(),this.results.position(this.$results,this.$dropdown);var k=this;this._bindAdapters(),this._registerDomEvents(),this._registerDataEvents(),this._registerSelectionEvents(),this._registerDropdownEvents(),this._registerResultsEvents(),this._registerEvents(),this.dataAdapter.current(function(a){k.trigger("selection:update",{data:a})}),a.addClass("select2-hidden-accessible"),a.attr("aria-hidden","true"),this._syncAttributes(),a.data("select2",this)};return c.Extend(e,c.Observable),e.prototype._generateId=function(a){var b="";return b=null!=a.attr("id")?a.attr("id"):null!=a.attr("name")?a.attr("name")+"-"+c.generateChars(2):c.generateChars(4),b=b.replace(/(:|\.|\[|\]|,)/g,""),b="select2-"+b},e.prototype._placeContainer=function(a){a.insertAfter(this.$element);var b=this._resolveWidth(this.$element,this.options.get("width"));null!=b&&a.css("width",b)},e.prototype._resolveWidth=function(a,b){var c=/^width:(([-+]?([0-9]*\.)?[0-9]+)(px|em|ex|%|in|cm|mm|pt|pc))/i;if("resolve"==b){var d=this._resolveWidth(a,"style");return null!=d?d:this._resolveWidth(a,"element")}if("element"==b){var e=a.outerWidth(!1);return e<=0?"auto":e+"px"}if("style"==b){var f=a.attr("style");if("string"!=typeof f)return null;for(var g=f.split(";"),h=0,i=g.length;h=1)return k[1]}return null}return b},e.prototype._bindAdapters=function(){this.dataAdapter.bind(this,this.$container),this.selection.bind(this,this.$container),this.dropdown.bind(this,this.$container),this.results.bind(this,this.$container)},e.prototype._registerDomEvents=function(){var b=this;this.$element.on("change.select2",function(){b.dataAdapter.current(function(a){b.trigger("selection:update",{data:a})})}),this.$element.on("focus.select2",function(a){b.trigger("focus",a)}),this._syncA=c.bind(this._syncAttributes,this),this._syncS=c.bind(this._syncSubtree,this),this.$element[0].attachEvent&&this.$element[0].attachEvent("onpropertychange",this._syncA);var d=window.MutationObserver||window.WebKitMutationObserver||window.MozMutationObserver;null!=d?(this._observer=new d(function(c){a.each(c,b._syncA),a.each(c,b._syncS)}),this._observer.observe(this.$element[0],{attributes:!0,childList:!0,subtree:!1})):this.$element[0].addEventListener&&(this.$element[0].addEventListener("DOMAttrModified",b._syncA,!1),this.$element[0].addEventListener("DOMNodeInserted",b._syncS,!1),this.$element[0].addEventListener("DOMNodeRemoved",b._syncS,!1))},e.prototype._registerDataEvents=function(){var a=this;this.dataAdapter.on("*",function(b,c){a.trigger(b,c)})},e.prototype._registerSelectionEvents=function(){var b=this,c=["toggle","focus"];this.selection.on("toggle",function(){b.toggleDropdown()}),this.selection.on("focus",function(a){b.focus(a)}),this.selection.on("*",function(d,e){-1===a.inArray(d,c)&&b.trigger(d,e)})},e.prototype._registerDropdownEvents=function(){var a=this;this.dropdown.on("*",function(b,c){a.trigger(b,c)})},e.prototype._registerResultsEvents=function(){var a=this;this.results.on("*",function(b,c){a.trigger(b,c)})},e.prototype._registerEvents=function(){var a=this;this.on("open",function(){a.$container.addClass("select2-container--open")}),this.on("close",function(){a.$container.removeClass("select2-container--open")}),this.on("enable",function(){a.$container.removeClass("select2-container--disabled")}),this.on("disable",function(){a.$container.addClass("select2-container--disabled")}),this.on("blur",function(){a.$container.removeClass("select2-container--focus")}),this.on("query",function(b){a.isOpen()||a.trigger("open",{}),this.dataAdapter.query(b,function(c){a.trigger("results:all",{data:c,query:b})})}),this.on("query:append",function(b){this.dataAdapter.query(b,function(c){a.trigger("results:append",{data:c,query:b})})}),this.on("keypress",function(b){var c=b.which;a.isOpen()?c===d.ESC||c===d.TAB||c===d.UP&&b.altKey?(a.close(),b.preventDefault()):c===d.ENTER?(a.trigger("results:select",{}),b.preventDefault()):c===d.SPACE&&b.ctrlKey?(a.trigger("results:toggle",{}),b.preventDefault()):c===d.UP?(a.trigger("results:previous",{}),b.preventDefault()):c===d.DOWN&&(a.trigger("results:next",{}),b.preventDefault()):(c===d.ENTER||c===d.SPACE||c===d.DOWN&&b.altKey)&&(a.open(),b.preventDefault())})},e.prototype._syncAttributes=function(){this.options.set("disabled",this.$element.prop("disabled")),this.options.get("disabled")?(this.isOpen()&&this.close(),this.trigger("disable",{})):this.trigger("enable",{})},e.prototype._syncSubtree=function(a,b){var c=!1,d=this;if(!a||!a.target||"OPTION"===a.target.nodeName||"OPTGROUP"===a.target.nodeName){if(b)if(b.addedNodes&&b.addedNodes.length>0)for(var e=0;e0&&(c=!0);else c=!0;c&&this.dataAdapter.current(function(a){d.trigger("selection:update",{data:a})})}},e.prototype.trigger=function(a,b){var c=e.__super__.trigger,d={open:"opening",close:"closing",select:"selecting",unselect:"unselecting"};if(void 0===b&&(b={}),a in d){var f=d[a],g={prevented:!1,name:a,args:b};if(c.call(this,f,g),g.prevented)return void(b.prevented=!0)}c.call(this,a,b)},e.prototype.toggleDropdown=function(){this.options.get("disabled")||(this.isOpen()?this.close():this.open())},e.prototype.open=function(){this.isOpen()||this.trigger("query",{})},e.prototype.close=function(){this.isOpen()&&this.trigger("close",{})},e.prototype.isOpen=function(){return this.$container.hasClass("select2-container--open")},e.prototype.hasFocus=function(){return this.$container.hasClass("select2-container--focus")},e.prototype.focus=function(a){this.hasFocus()||(this.$container.addClass("select2-container--focus"),this.trigger("focus",{}))},e.prototype.enable=function(a){this.options.get("debug")&&window.console&&console.warn&&console.warn('Select2: The `select2("enable")` method has been deprecated and will be removed in later Select2 versions. Use $element.prop("disabled") instead.'),null!=a&&0!==a.length||(a=[!0]);var b=!a[0];this.$element.prop("disabled",b)},e.prototype.data=function(){this.options.get("debug")&&arguments.length>0&&window.console&&console.warn&&console.warn('Select2: Data can no longer be set using `select2("data")`. You should consider setting the value instead using `$element.val()`.');var a=[];return this.dataAdapter.current(function(b){a=b}),a},e.prototype.val=function(b){if(this.options.get("debug")&&window.console&&console.warn&&console.warn('Select2: The `select2("val")` method has been deprecated and will be removed in later Select2 versions. Use $element.val() instead.'),null==b||0===b.length)return this.$element.val();var c=b[0];a.isArray(c)&&(c=a.map(c,function(a){return a.toString()})),this.$element.val(c).trigger("change")},e.prototype.destroy=function(){this.$container.remove(),this.$element[0].detachEvent&&this.$element[0].detachEvent("onpropertychange",this._syncA),null!=this._observer?(this._observer.disconnect(),this._observer=null):this.$element[0].removeEventListener&&(this.$element[0].removeEventListener("DOMAttrModified",this._syncA,!1),this.$element[0].removeEventListener("DOMNodeInserted",this._syncS,!1),this.$element[0].removeEventListener("DOMNodeRemoved",this._syncS,!1)),this._syncA=null,this._syncS=null,this.$element.off(".select2"),this.$element.attr("tabindex",this.$element.data("old-tabindex")),this.$element.removeClass("select2-hidden-accessible"),this.$element.attr("aria-hidden","false"),this.$element.removeData("select2"),this.dataAdapter.destroy(),this.selection.destroy(),this.dropdown.destroy(),this.results.destroy(),this.dataAdapter=null,this.selection=null,this.dropdown=null,this.results=null},e.prototype.render=function(){var b=a('');return b.attr("dir",this.options.get("dir")),this.$container=b,this.$container.addClass("select2-container--"+this.options.get("theme")),b.data("element",this.$element),b},e}),b.define("jquery-mousewheel",["jquery"],function(a){return a}),b.define("jquery.select2",["jquery","jquery-mousewheel","./select2/core","./select2/defaults"],function(a,b,c,d){if(null==a.fn.select2){var e=["open","close","destroy"];a.fn.select2=function(b){if("object"==typeof(b=b||{}))return this.each(function(){var d=a.extend(!0,{},b);new c(a(this),d)}),this;if("string"==typeof b){var d,f=Array.prototype.slice.call(arguments,1);return this.each(function(){var c=a(this).data("select2");null==c&&window.console&&console.error&&console.error("The select2('"+b+"') method was called on an element that is not using Select2."),d=c[b].apply(c,f)}),a.inArray(b,e)>-1?this:d}throw new Error("Invalid arguments for Select2: "+b)}}return null==a.fn.select2.defaults&&(a.fn.select2.defaults=d),c}),{define:b.define,require:b.require}}(),c=b.require("jquery.select2");return a.fn.select2.amd=b,c}); +/*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof module&&module.exports?module.exports=function(b,c){return void 0===c&&(c="undefined"!=typeof window?require("jquery"):require("jquery")(b)),a(c),c}:a(jQuery)}(function(a){var b=function(){if(a&&a.fn&&a.fn.select2&&a.fn.select2.amd)var b=a.fn.select2.amd;var b;return function(){if(!b||!b.requirejs){b?c=b:b={};var a,c,d;!function(b){function e(a,b){return v.call(a,b)}function f(a,b){var c,d,e,f,g,h,i,j,k,l,m,n,o=b&&b.split("/"),p=t.map,q=p&&p["*"]||{};if(a){for(a=a.split("/"),g=a.length-1,t.nodeIdCompat&&x.test(a[g])&&(a[g]=a[g].replace(x,"")),"."===a[0].charAt(0)&&o&&(n=o.slice(0,o.length-1),a=n.concat(a)),k=0;k0&&(a.splice(k-1,2),k-=2)}a=a.join("/")}if((o||q)&&p){for(c=a.split("/"),k=c.length;k>0;k-=1){if(d=c.slice(0,k).join("/"),o)for(l=o.length;l>0;l-=1)if((e=p[o.slice(0,l).join("/")])&&(e=e[d])){f=e,h=k;break}if(f)break;!i&&q&&q[d]&&(i=q[d],j=k)}!f&&i&&(f=i,h=j),f&&(c.splice(0,h,f),a=c.join("/"))}return a}function g(a,c){return function(){var d=w.call(arguments,0);return"string"!=typeof d[0]&&1===d.length&&d.push(null),o.apply(b,d.concat([a,c]))}}function h(a){return function(b){return f(b,a)}}function i(a){return function(b){r[a]=b}}function j(a){if(e(s,a)){var c=s[a];delete s[a],u[a]=!0,n.apply(b,c)}if(!e(r,a)&&!e(u,a))throw new Error("No "+a);return r[a]}function k(a){var b,c=a?a.indexOf("!"):-1;return c>-1&&(b=a.substring(0,c),a=a.substring(c+1,a.length)),[b,a]}function l(a){return a?k(a):[]}function m(a){return function(){return t&&t.config&&t.config[a]||{}}}var n,o,p,q,r={},s={},t={},u={},v=Object.prototype.hasOwnProperty,w=[].slice,x=/\.js$/;p=function(a,b){var c,d=k(a),e=d[0],g=b[1];return a=d[1],e&&(e=f(e,g),c=j(e)),e?a=c&&c.normalize?c.normalize(a,h(g)):f(a,g):(a=f(a,g),d=k(a),e=d[0],a=d[1],e&&(c=j(e))),{f:e?e+"!"+a:a,n:a,pr:e,p:c}},q={require:function(a){return g(a)},exports:function(a){var b=r[a];return void 0!==b?b:r[a]={}},module:function(a){return{id:a,uri:"",exports:r[a],config:m(a)}}},n=function(a,c,d,f){var h,k,m,n,o,t,v,w=[],x=typeof d;if(f=f||a,t=l(f),"undefined"===x||"function"===x){for(c=!c.length&&d.length?["require","exports","module"]:c,o=0;o0&&(b.call(arguments,a.prototype.constructor),e=c.prototype.constructor),e.apply(this,arguments)}function e(){this.constructor=d}var f=b(c),g=b(a);c.displayName=a.displayName,d.prototype=new e;for(var h=0;h":">",'"':""","'":"'","/":"/"};return"string"!=typeof a?a:String(a).replace(/[&<>"'\/\\]/g,function(a){return b[a]})},c.appendMany=function(b,c){if("1.7"===a.fn.jquery.substr(0,3)){var d=a();a.map(c,function(a){d=d.add(a)}),c=d}b.append(c)},c}),b.define("select2/results",["jquery","./utils"],function(a,b){function c(a,b,d){this.$element=a,this.data=d,this.options=b,c.__super__.constructor.call(this)}return b.Extend(c,b.Observable),c.prototype.render=function(){var b=a('
        ');return this.options.get("multiple")&&b.attr("aria-multiselectable","true"),this.$results=b,b},c.prototype.clear=function(){this.$results.empty()},c.prototype.displayMessage=function(b){var c=this.options.get("escapeMarkup");this.clear(),this.hideLoading();var d=a('
      • '),e=this.options.get("translations").get(b.message);d.append(c(e(b.args))),d[0].className+=" select2-results__message",this.$results.append(d)},c.prototype.hideMessages=function(){this.$results.find(".select2-results__message").remove()},c.prototype.append=function(a){this.hideLoading();var b=[];if(null==a.results||0===a.results.length)return void(0===this.$results.children().length&&this.trigger("results:message",{message:"noResults"}));a.results=this.sort(a.results);for(var c=0;c0?b.first().trigger("mouseenter"):a.first().trigger("mouseenter"),this.ensureHighlightVisible()},c.prototype.setClasses=function(){var b=this;this.data.current(function(c){var d=a.map(c,function(a){return a.id.toString()});b.$results.find(".select2-results__option[aria-selected]").each(function(){var b=a(this),c=a.data(this,"data"),e=""+c.id;null!=c.element&&c.element.selected||null==c.element&&a.inArray(e,d)>-1?b.attr("aria-selected","true"):b.attr("aria-selected","false")})})},c.prototype.showLoading=function(a){this.hideLoading();var b=this.options.get("translations").get("searching"),c={disabled:!0,loading:!0,text:b(a)},d=this.option(c);d.className+=" loading-results",this.$results.prepend(d)},c.prototype.hideLoading=function(){this.$results.find(".loading-results").remove()},c.prototype.option=function(b){var c=document.createElement("li");c.className="select2-results__option";var d={role:"treeitem","aria-selected":"false"};b.disabled&&(delete d["aria-selected"],d["aria-disabled"]="true"),null==b.id&&delete d["aria-selected"],null!=b._resultId&&(c.id=b._resultId),b.title&&(c.title=b.title),b.children&&(d.role="group",d["aria-label"]=b.text,delete d["aria-selected"]);for(var e in d){var f=d[e];c.setAttribute(e,f)}if(b.children){var g=a(c),h=document.createElement("strong");h.className="select2-results__group";a(h);this.template(b,h);for(var i=[],j=0;j",{class:"select2-results__options select2-results__options--nested"});m.append(i),g.append(h),g.append(m)}else this.template(b,c);return a.data(c,"data",b),c},c.prototype.bind=function(b,c){var d=this,e=b.id+"-results";this.$results.attr("id",e),b.on("results:all",function(a){d.clear(),d.append(a.data),b.isOpen()&&(d.setClasses(),d.highlightFirstItem())}),b.on("results:append",function(a){d.append(a.data),b.isOpen()&&d.setClasses()}),b.on("query",function(a){d.hideMessages(),d.showLoading(a)}),b.on("select",function(){b.isOpen()&&(d.setClasses(),d.highlightFirstItem())}),b.on("unselect",function(){b.isOpen()&&(d.setClasses(),d.highlightFirstItem())}),b.on("open",function(){d.$results.attr("aria-expanded","true"),d.$results.attr("aria-hidden","false"),d.setClasses(),d.ensureHighlightVisible()}),b.on("close",function(){d.$results.attr("aria-expanded","false"),d.$results.attr("aria-hidden","true"),d.$results.removeAttr("aria-activedescendant")}),b.on("results:toggle",function(){var a=d.getHighlightedResults();0!==a.length&&a.trigger("mouseup")}),b.on("results:select",function(){var a=d.getHighlightedResults();if(0!==a.length){var b=a.data("data");"true"==a.attr("aria-selected")?d.trigger("close",{}):d.trigger("select",{data:b})}}),b.on("results:previous",function(){var a=d.getHighlightedResults(),b=d.$results.find("[aria-selected]"),c=b.index(a);if(0!==c){var e=c-1;0===a.length&&(e=0);var f=b.eq(e);f.trigger("mouseenter");var g=d.$results.offset().top,h=f.offset().top,i=d.$results.scrollTop()+(h-g);0===e?d.$results.scrollTop(0):h-g<0&&d.$results.scrollTop(i)}}),b.on("results:next",function(){var a=d.getHighlightedResults(),b=d.$results.find("[aria-selected]"),c=b.index(a),e=c+1;if(!(e>=b.length)){var f=b.eq(e);f.trigger("mouseenter");var g=d.$results.offset().top+d.$results.outerHeight(!1),h=f.offset().top+f.outerHeight(!1),i=d.$results.scrollTop()+h-g;0===e?d.$results.scrollTop(0):h>g&&d.$results.scrollTop(i)}}),b.on("results:focus",function(a){a.element.addClass("select2-results__option--highlighted")}),b.on("results:message",function(a){d.displayMessage(a)}),a.fn.mousewheel&&this.$results.on("mousewheel",function(a){var b=d.$results.scrollTop(),c=d.$results.get(0).scrollHeight-b+a.deltaY,e=a.deltaY>0&&b-a.deltaY<=0,f=a.deltaY<0&&c<=d.$results.height();e?(d.$results.scrollTop(0),a.preventDefault(),a.stopPropagation()):f&&(d.$results.scrollTop(d.$results.get(0).scrollHeight-d.$results.height()),a.preventDefault(),a.stopPropagation())}),this.$results.on("mouseup",".select2-results__option[aria-selected]",function(b){var c=a(this),e=c.data("data");if("true"===c.attr("aria-selected"))return void(d.options.get("multiple")?d.trigger("unselect",{originalEvent:b,data:e}):d.trigger("close",{}));d.trigger("select",{originalEvent:b,data:e})}),this.$results.on("mouseenter",".select2-results__option[aria-selected]",function(b){var c=a(this).data("data");d.getHighlightedResults().removeClass("select2-results__option--highlighted"),d.trigger("results:focus",{data:c,element:a(this)})})},c.prototype.getHighlightedResults=function(){return this.$results.find(".select2-results__option--highlighted")},c.prototype.destroy=function(){this.$results.remove()},c.prototype.ensureHighlightVisible=function(){var a=this.getHighlightedResults();if(0!==a.length){var b=this.$results.find("[aria-selected]"),c=b.index(a),d=this.$results.offset().top,e=a.offset().top,f=this.$results.scrollTop()+(e-d),g=e-d;f-=2*a.outerHeight(!1),c<=2?this.$results.scrollTop(0):(g>this.$results.outerHeight()||g<0)&&this.$results.scrollTop(f)}},c.prototype.template=function(b,c){var d=this.options.get("templateResult"),e=this.options.get("escapeMarkup"),f=d(b,c);null==f?c.style.display="none":"string"==typeof f?c.innerHTML=e(f):a(c).append(f)},c}),b.define("select2/keys",[],function(){return{BACKSPACE:8,TAB:9,ENTER:13,SHIFT:16,CTRL:17,ALT:18,ESC:27,SPACE:32,PAGE_UP:33,PAGE_DOWN:34,END:35,HOME:36,LEFT:37,UP:38,RIGHT:39,DOWN:40,DELETE:46}}),b.define("select2/selection/base",["jquery","../utils","../keys"],function(a,b,c){function d(a,b){this.$element=a,this.options=b,d.__super__.constructor.call(this)}return b.Extend(d,b.Observable),d.prototype.render=function(){var b=a('');return this._tabindex=0,null!=this.$element.data("old-tabindex")?this._tabindex=this.$element.data("old-tabindex"):null!=this.$element.attr("tabindex")&&(this._tabindex=this.$element.attr("tabindex")),b.attr("title",this.$element.attr("title")),b.attr("tabindex",this._tabindex),this.$selection=b,b},d.prototype.bind=function(a,b){var d=this,e=(a.id,a.id+"-results");this.container=a,this.$selection.on("focus",function(a){d.trigger("focus",a)}),this.$selection.on("blur",function(a){d._handleBlur(a)}),this.$selection.on("keydown",function(a){d.trigger("keypress",a),a.which===c.SPACE&&a.preventDefault()}),a.on("results:focus",function(a){d.$selection.attr("aria-activedescendant",a.data._resultId)}),a.on("selection:update",function(a){d.update(a.data)}),a.on("open",function(){d.$selection.attr("aria-expanded","true"),d.$selection.attr("aria-owns",e),d._attachCloseHandler(a)}),a.on("close",function(){d.$selection.attr("aria-expanded","false"),d.$selection.removeAttr("aria-activedescendant"),d.$selection.removeAttr("aria-owns"),d.$selection.focus(),d._detachCloseHandler(a)}),a.on("enable",function(){d.$selection.attr("tabindex",d._tabindex)}),a.on("disable",function(){d.$selection.attr("tabindex","-1")})},d.prototype._handleBlur=function(b){var c=this;window.setTimeout(function(){document.activeElement==c.$selection[0]||a.contains(c.$selection[0],document.activeElement)||c.trigger("blur",b)},1)},d.prototype._attachCloseHandler=function(b){a(document.body).on("mousedown.select2."+b.id,function(b){var c=a(b.target),d=c.closest(".select2");a(".select2.select2-container--open").each(function(){var b=a(this);this!=d[0]&&b.data("element").select2("close")})})},d.prototype._detachCloseHandler=function(b){a(document.body).off("mousedown.select2."+b.id)},d.prototype.position=function(a,b){b.find(".selection").append(a)},d.prototype.destroy=function(){this._detachCloseHandler(this.container)},d.prototype.update=function(a){throw new Error("The `update` method must be defined in child classes.")},d}),b.define("select2/selection/single",["jquery","./base","../utils","../keys"],function(a,b,c,d){function e(){e.__super__.constructor.apply(this,arguments)}return c.Extend(e,b),e.prototype.render=function(){var a=e.__super__.render.call(this);return a.addClass("select2-selection--single"),a.html(''),a},e.prototype.bind=function(a,b){var c=this;e.__super__.bind.apply(this,arguments);var d=a.id+"-container";this.$selection.find(".select2-selection__rendered").attr("id",d),this.$selection.attr("aria-labelledby",d),this.$selection.on("mousedown",function(a){1===a.which&&c.trigger("toggle",{originalEvent:a})}),this.$selection.on("focus",function(a){}),this.$selection.on("blur",function(a){}),a.on("focus",function(b){a.isOpen()||c.$selection.focus()}),a.on("selection:update",function(a){c.update(a.data)})},e.prototype.clear=function(){this.$selection.find(".select2-selection__rendered").empty()},e.prototype.display=function(a,b){var c=this.options.get("templateSelection");return this.options.get("escapeMarkup")(c(a,b))},e.prototype.selectionContainer=function(){return a("")},e.prototype.update=function(a){if(0===a.length)return void this.clear();var b=a[0],c=this.$selection.find(".select2-selection__rendered"),d=this.display(b,c);c.empty().append(d),c.prop("title",b.title||b.text)},e}),b.define("select2/selection/multiple",["jquery","./base","../utils"],function(a,b,c){function d(a,b){d.__super__.constructor.apply(this,arguments)}return c.Extend(d,b),d.prototype.render=function(){var a=d.__super__.render.call(this);return a.addClass("select2-selection--multiple"),a.html('
          '),a},d.prototype.bind=function(b,c){var e=this;d.__super__.bind.apply(this,arguments),this.$selection.on("click",function(a){e.trigger("toggle",{originalEvent:a})}),this.$selection.on("click",".select2-selection__choice__remove",function(b){if(!e.options.get("disabled")){var c=a(this),d=c.parent(),f=d.data("data");e.trigger("unselect",{originalEvent:b,data:f})}})},d.prototype.clear=function(){this.$selection.find(".select2-selection__rendered").empty()},d.prototype.display=function(a,b){var c=this.options.get("templateSelection");return this.options.get("escapeMarkup")(c(a,b))},d.prototype.selectionContainer=function(){return a('
        • ×
        • ')},d.prototype.update=function(a){if(this.clear(),0!==a.length){for(var b=[],d=0;d1||c)return a.call(this,b);this.clear();var d=this.createPlaceholder(this.placeholder);this.$selection.find(".select2-selection__rendered").append(d)},b}),b.define("select2/selection/allowClear",["jquery","../keys"],function(a,b){function c(){}return c.prototype.bind=function(a,b,c){var d=this;a.call(this,b,c),null==this.placeholder&&this.options.get("debug")&&window.console&&console.error&&console.error("Select2: The `allowClear` option should be used in combination with the `placeholder` option."),this.$selection.on("mousedown",".select2-selection__clear",function(a){d._handleClear(a)}),b.on("keypress",function(a){d._handleKeyboardClear(a,b)})},c.prototype._handleClear=function(a,b){if(!this.options.get("disabled")){var c=this.$selection.find(".select2-selection__clear");if(0!==c.length){b.stopPropagation();for(var d=c.data("data"),e=0;e0||0===c.length)){var d=a('×');d.data("data",c),this.$selection.find(".select2-selection__rendered").prepend(d)}},c}),b.define("select2/selection/search",["jquery","../utils","../keys"],function(a,b,c){function d(a,b,c){a.call(this,b,c)}return d.prototype.render=function(b){var c=a('');this.$searchContainer=c,this.$search=c.find("input");var d=b.call(this);return this._transferTabIndex(),d},d.prototype.bind=function(a,b,d){var e=this;a.call(this,b,d),b.on("open",function(){e.$search.trigger("focus")}),b.on("close",function(){e.$search.val(""),e.$search.removeAttr("aria-activedescendant"),e.$search.trigger("focus")}),b.on("enable",function(){e.$search.prop("disabled",!1),e._transferTabIndex()}),b.on("disable",function(){e.$search.prop("disabled",!0)}),b.on("focus",function(a){e.$search.trigger("focus")}),b.on("results:focus",function(a){e.$search.attr("aria-activedescendant",a.id)}),this.$selection.on("focusin",".select2-search--inline",function(a){e.trigger("focus",a)}),this.$selection.on("focusout",".select2-search--inline",function(a){e._handleBlur(a)}),this.$selection.on("keydown",".select2-search--inline",function(a){if(a.stopPropagation(),e.trigger("keypress",a),e._keyUpPrevented=a.isDefaultPrevented(),a.which===c.BACKSPACE&&""===e.$search.val()){var b=e.$searchContainer.prev(".select2-selection__choice");if(b.length>0){var d=b.data("data");e.searchRemoveChoice(d),a.preventDefault()}}});var f=document.documentMode,g=f&&f<=11;this.$selection.on("input.searchcheck",".select2-search--inline",function(a){if(g)return void e.$selection.off("input.search input.searchcheck");e.$selection.off("keyup.search")}),this.$selection.on("keyup.search input.search",".select2-search--inline",function(a){if(g&&"input"===a.type)return void e.$selection.off("input.search input.searchcheck");var b=a.which;b!=c.SHIFT&&b!=c.CTRL&&b!=c.ALT&&b!=c.TAB&&e.handleSearch(a)})},d.prototype._transferTabIndex=function(a){this.$search.attr("tabindex",this.$selection.attr("tabindex")),this.$selection.attr("tabindex","-1")},d.prototype.createPlaceholder=function(a,b){this.$search.attr("placeholder",b.text)},d.prototype.update=function(a,b){var c=this.$search[0]==document.activeElement;this.$search.attr("placeholder",""),a.call(this,b),this.$selection.find(".select2-selection__rendered").append(this.$searchContainer),this.resizeSearch(),c&&this.$search.focus()},d.prototype.handleSearch=function(){if(this.resizeSearch(),!this._keyUpPrevented){var a=this.$search.val();this.trigger("query",{term:a})}this._keyUpPrevented=!1},d.prototype.searchRemoveChoice=function(a,b){this.trigger("unselect",{data:b}),this.$search.val(b.text),this.handleSearch()},d.prototype.resizeSearch=function(){this.$search.css("width","25px");var a="";if(""!==this.$search.attr("placeholder"))a=this.$selection.find(".select2-selection__rendered").innerWidth();else{a=.75*(this.$search.val().length+1)+"em"}this.$search.css("width",a)},d}),b.define("select2/selection/eventRelay",["jquery"],function(a){function b(){}return b.prototype.bind=function(b,c,d){var e=this,f=["open","opening","close","closing","select","selecting","unselect","unselecting"],g=["opening","closing","selecting","unselecting"];b.call(this,c,d),c.on("*",function(b,c){if(-1!==a.inArray(b,f)){c=c||{};var d=a.Event("select2:"+b,{params:c});e.$element.trigger(d),-1!==a.inArray(b,g)&&(c.prevented=d.isDefaultPrevented())}})},b}),b.define("select2/translation",["jquery","require"],function(a,b){function c(a){this.dict=a||{}}return c.prototype.all=function(){return this.dict},c.prototype.get=function(a){return this.dict[a]},c.prototype.extend=function(b){this.dict=a.extend({},b.all(),this.dict)},c._cache={},c.loadPath=function(a){if(!(a in c._cache)){var d=b(a);c._cache[a]=d}return new c(c._cache[a])},c}),b.define("select2/diacritics",[],function(){return{"Ⓐ":"A","A":"A","À":"A","Á":"A","Â":"A","Ầ":"A","Ấ":"A","Ẫ":"A","Ẩ":"A","Ã":"A","Ā":"A","Ă":"A","Ằ":"A","Ắ":"A","Ẵ":"A","Ẳ":"A","Ȧ":"A","Ǡ":"A","Ä":"A","Ǟ":"A","Ả":"A","Å":"A","Ǻ":"A","Ǎ":"A","Ȁ":"A","Ȃ":"A","Ạ":"A","Ậ":"A","Ặ":"A","Ḁ":"A","Ą":"A","Ⱥ":"A","Ɐ":"A","Ꜳ":"AA","Æ":"AE","Ǽ":"AE","Ǣ":"AE","Ꜵ":"AO","Ꜷ":"AU","Ꜹ":"AV","Ꜻ":"AV","Ꜽ":"AY","Ⓑ":"B","B":"B","Ḃ":"B","Ḅ":"B","Ḇ":"B","Ƀ":"B","Ƃ":"B","Ɓ":"B","Ⓒ":"C","C":"C","Ć":"C","Ĉ":"C","Ċ":"C","Č":"C","Ç":"C","Ḉ":"C","Ƈ":"C","Ȼ":"C","Ꜿ":"C","Ⓓ":"D","D":"D","Ḋ":"D","Ď":"D","Ḍ":"D","Ḑ":"D","Ḓ":"D","Ḏ":"D","Đ":"D","Ƌ":"D","Ɗ":"D","Ɖ":"D","Ꝺ":"D","DZ":"DZ","DŽ":"DZ","Dz":"Dz","Dž":"Dz","Ⓔ":"E","E":"E","È":"E","É":"E","Ê":"E","Ề":"E","Ế":"E","Ễ":"E","Ể":"E","Ẽ":"E","Ē":"E","Ḕ":"E","Ḗ":"E","Ĕ":"E","Ė":"E","Ë":"E","Ẻ":"E","Ě":"E","Ȅ":"E","Ȇ":"E","Ẹ":"E","Ệ":"E","Ȩ":"E","Ḝ":"E","Ę":"E","Ḙ":"E","Ḛ":"E","Ɛ":"E","Ǝ":"E","Ⓕ":"F","F":"F","Ḟ":"F","Ƒ":"F","Ꝼ":"F","Ⓖ":"G","G":"G","Ǵ":"G","Ĝ":"G","Ḡ":"G","Ğ":"G","Ġ":"G","Ǧ":"G","Ģ":"G","Ǥ":"G","Ɠ":"G","Ꞡ":"G","Ᵹ":"G","Ꝿ":"G","Ⓗ":"H","H":"H","Ĥ":"H","Ḣ":"H","Ḧ":"H","Ȟ":"H","Ḥ":"H","Ḩ":"H","Ḫ":"H","Ħ":"H","Ⱨ":"H","Ⱶ":"H","Ɥ":"H","Ⓘ":"I","I":"I","Ì":"I","Í":"I","Î":"I","Ĩ":"I","Ī":"I","Ĭ":"I","İ":"I","Ï":"I","Ḯ":"I","Ỉ":"I","Ǐ":"I","Ȉ":"I","Ȋ":"I","Ị":"I","Į":"I","Ḭ":"I","Ɨ":"I","Ⓙ":"J","J":"J","Ĵ":"J","Ɉ":"J","Ⓚ":"K","K":"K","Ḱ":"K","Ǩ":"K","Ḳ":"K","Ķ":"K","Ḵ":"K","Ƙ":"K","Ⱪ":"K","Ꝁ":"K","Ꝃ":"K","Ꝅ":"K","Ꞣ":"K","Ⓛ":"L","L":"L","Ŀ":"L","Ĺ":"L","Ľ":"L","Ḷ":"L","Ḹ":"L","Ļ":"L","Ḽ":"L","Ḻ":"L","Ł":"L","Ƚ":"L","Ɫ":"L","Ⱡ":"L","Ꝉ":"L","Ꝇ":"L","Ꞁ":"L","LJ":"LJ","Lj":"Lj","Ⓜ":"M","M":"M","Ḿ":"M","Ṁ":"M","Ṃ":"M","Ɱ":"M","Ɯ":"M","Ⓝ":"N","N":"N","Ǹ":"N","Ń":"N","Ñ":"N","Ṅ":"N","Ň":"N","Ṇ":"N","Ņ":"N","Ṋ":"N","Ṉ":"N","Ƞ":"N","Ɲ":"N","Ꞑ":"N","Ꞥ":"N","NJ":"NJ","Nj":"Nj","Ⓞ":"O","O":"O","Ò":"O","Ó":"O","Ô":"O","Ồ":"O","Ố":"O","Ỗ":"O","Ổ":"O","Õ":"O","Ṍ":"O","Ȭ":"O","Ṏ":"O","Ō":"O","Ṑ":"O","Ṓ":"O","Ŏ":"O","Ȯ":"O","Ȱ":"O","Ö":"O","Ȫ":"O","Ỏ":"O","Ő":"O","Ǒ":"O","Ȍ":"O","Ȏ":"O","Ơ":"O","Ờ":"O","Ớ":"O","Ỡ":"O","Ở":"O","Ợ":"O","Ọ":"O","Ộ":"O","Ǫ":"O","Ǭ":"O","Ø":"O","Ǿ":"O","Ɔ":"O","Ɵ":"O","Ꝋ":"O","Ꝍ":"O","Ƣ":"OI","Ꝏ":"OO","Ȣ":"OU","Ⓟ":"P","P":"P","Ṕ":"P","Ṗ":"P","Ƥ":"P","Ᵽ":"P","Ꝑ":"P","Ꝓ":"P","Ꝕ":"P","Ⓠ":"Q","Q":"Q","Ꝗ":"Q","Ꝙ":"Q","Ɋ":"Q","Ⓡ":"R","R":"R","Ŕ":"R","Ṙ":"R","Ř":"R","Ȑ":"R","Ȓ":"R","Ṛ":"R","Ṝ":"R","Ŗ":"R","Ṟ":"R","Ɍ":"R","Ɽ":"R","Ꝛ":"R","Ꞧ":"R","Ꞃ":"R","Ⓢ":"S","S":"S","ẞ":"S","Ś":"S","Ṥ":"S","Ŝ":"S","Ṡ":"S","Š":"S","Ṧ":"S","Ṣ":"S","Ṩ":"S","Ș":"S","Ş":"S","Ȿ":"S","Ꞩ":"S","Ꞅ":"S","Ⓣ":"T","T":"T","Ṫ":"T","Ť":"T","Ṭ":"T","Ț":"T","Ţ":"T","Ṱ":"T","Ṯ":"T","Ŧ":"T","Ƭ":"T","Ʈ":"T","Ⱦ":"T","Ꞇ":"T","Ꜩ":"TZ","Ⓤ":"U","U":"U","Ù":"U","Ú":"U","Û":"U","Ũ":"U","Ṹ":"U","Ū":"U","Ṻ":"U","Ŭ":"U","Ü":"U","Ǜ":"U","Ǘ":"U","Ǖ":"U","Ǚ":"U","Ủ":"U","Ů":"U","Ű":"U","Ǔ":"U","Ȕ":"U","Ȗ":"U","Ư":"U","Ừ":"U","Ứ":"U","Ữ":"U","Ử":"U","Ự":"U","Ụ":"U","Ṳ":"U","Ų":"U","Ṷ":"U","Ṵ":"U","Ʉ":"U","Ⓥ":"V","V":"V","Ṽ":"V","Ṿ":"V","Ʋ":"V","Ꝟ":"V","Ʌ":"V","Ꝡ":"VY","Ⓦ":"W","W":"W","Ẁ":"W","Ẃ":"W","Ŵ":"W","Ẇ":"W","Ẅ":"W","Ẉ":"W","Ⱳ":"W","Ⓧ":"X","X":"X","Ẋ":"X","Ẍ":"X","Ⓨ":"Y","Y":"Y","Ỳ":"Y","Ý":"Y","Ŷ":"Y","Ỹ":"Y","Ȳ":"Y","Ẏ":"Y","Ÿ":"Y","Ỷ":"Y","Ỵ":"Y","Ƴ":"Y","Ɏ":"Y","Ỿ":"Y","Ⓩ":"Z","Z":"Z","Ź":"Z","Ẑ":"Z","Ż":"Z","Ž":"Z","Ẓ":"Z","Ẕ":"Z","Ƶ":"Z","Ȥ":"Z","Ɀ":"Z","Ⱬ":"Z","Ꝣ":"Z","ⓐ":"a","a":"a","ẚ":"a","à":"a","á":"a","â":"a","ầ":"a","ấ":"a","ẫ":"a","ẩ":"a","ã":"a","ā":"a","ă":"a","ằ":"a","ắ":"a","ẵ":"a","ẳ":"a","ȧ":"a","ǡ":"a","ä":"a","ǟ":"a","ả":"a","å":"a","ǻ":"a","ǎ":"a","ȁ":"a","ȃ":"a","ạ":"a","ậ":"a","ặ":"a","ḁ":"a","ą":"a","ⱥ":"a","ɐ":"a","ꜳ":"aa","æ":"ae","ǽ":"ae","ǣ":"ae","ꜵ":"ao","ꜷ":"au","ꜹ":"av","ꜻ":"av","ꜽ":"ay","ⓑ":"b","b":"b","ḃ":"b","ḅ":"b","ḇ":"b","ƀ":"b","ƃ":"b","ɓ":"b","ⓒ":"c","c":"c","ć":"c","ĉ":"c","ċ":"c","č":"c","ç":"c","ḉ":"c","ƈ":"c","ȼ":"c","ꜿ":"c","ↄ":"c","ⓓ":"d","d":"d","ḋ":"d","ď":"d","ḍ":"d","ḑ":"d","ḓ":"d","ḏ":"d","đ":"d","ƌ":"d","ɖ":"d","ɗ":"d","ꝺ":"d","dz":"dz","dž":"dz","ⓔ":"e","e":"e","è":"e","é":"e","ê":"e","ề":"e","ế":"e","ễ":"e","ể":"e","ẽ":"e","ē":"e","ḕ":"e","ḗ":"e","ĕ":"e","ė":"e","ë":"e","ẻ":"e","ě":"e","ȅ":"e","ȇ":"e","ẹ":"e","ệ":"e","ȩ":"e","ḝ":"e","ę":"e","ḙ":"e","ḛ":"e","ɇ":"e","ɛ":"e","ǝ":"e","ⓕ":"f","f":"f","ḟ":"f","ƒ":"f","ꝼ":"f","ⓖ":"g","g":"g","ǵ":"g","ĝ":"g","ḡ":"g","ğ":"g","ġ":"g","ǧ":"g","ģ":"g","ǥ":"g","ɠ":"g","ꞡ":"g","ᵹ":"g","ꝿ":"g","ⓗ":"h","h":"h","ĥ":"h","ḣ":"h","ḧ":"h","ȟ":"h","ḥ":"h","ḩ":"h","ḫ":"h","ẖ":"h","ħ":"h","ⱨ":"h","ⱶ":"h","ɥ":"h","ƕ":"hv","ⓘ":"i","i":"i","ì":"i","í":"i","î":"i","ĩ":"i","ī":"i","ĭ":"i","ï":"i","ḯ":"i","ỉ":"i","ǐ":"i","ȉ":"i","ȋ":"i","ị":"i","į":"i","ḭ":"i","ɨ":"i","ı":"i","ⓙ":"j","j":"j","ĵ":"j","ǰ":"j","ɉ":"j","ⓚ":"k","k":"k","ḱ":"k","ǩ":"k","ḳ":"k","ķ":"k","ḵ":"k","ƙ":"k","ⱪ":"k","ꝁ":"k","ꝃ":"k","ꝅ":"k","ꞣ":"k","ⓛ":"l","l":"l","ŀ":"l","ĺ":"l","ľ":"l","ḷ":"l","ḹ":"l","ļ":"l","ḽ":"l","ḻ":"l","ſ":"l","ł":"l","ƚ":"l","ɫ":"l","ⱡ":"l","ꝉ":"l","ꞁ":"l","ꝇ":"l","lj":"lj","ⓜ":"m","m":"m","ḿ":"m","ṁ":"m","ṃ":"m","ɱ":"m","ɯ":"m","ⓝ":"n","n":"n","ǹ":"n","ń":"n","ñ":"n","ṅ":"n","ň":"n","ṇ":"n","ņ":"n","ṋ":"n","ṉ":"n","ƞ":"n","ɲ":"n","ʼn":"n","ꞑ":"n","ꞥ":"n","nj":"nj","ⓞ":"o","o":"o","ò":"o","ó":"o","ô":"o","ồ":"o","ố":"o","ỗ":"o","ổ":"o","õ":"o","ṍ":"o","ȭ":"o","ṏ":"o","ō":"o","ṑ":"o","ṓ":"o","ŏ":"o","ȯ":"o","ȱ":"o","ö":"o","ȫ":"o","ỏ":"o","ő":"o","ǒ":"o","ȍ":"o","ȏ":"o","ơ":"o","ờ":"o","ớ":"o","ỡ":"o","ở":"o","ợ":"o","ọ":"o","ộ":"o","ǫ":"o","ǭ":"o","ø":"o","ǿ":"o","ɔ":"o","ꝋ":"o","ꝍ":"o","ɵ":"o","ƣ":"oi","ȣ":"ou","ꝏ":"oo","ⓟ":"p","p":"p","ṕ":"p","ṗ":"p","ƥ":"p","ᵽ":"p","ꝑ":"p","ꝓ":"p","ꝕ":"p","ⓠ":"q","q":"q","ɋ":"q","ꝗ":"q","ꝙ":"q","ⓡ":"r","r":"r","ŕ":"r","ṙ":"r","ř":"r","ȑ":"r","ȓ":"r","ṛ":"r","ṝ":"r","ŗ":"r","ṟ":"r","ɍ":"r","ɽ":"r","ꝛ":"r","ꞧ":"r","ꞃ":"r","ⓢ":"s","s":"s","ß":"s","ś":"s","ṥ":"s","ŝ":"s","ṡ":"s","š":"s","ṧ":"s","ṣ":"s","ṩ":"s","ș":"s","ş":"s","ȿ":"s","ꞩ":"s","ꞅ":"s","ẛ":"s","ⓣ":"t","t":"t","ṫ":"t","ẗ":"t","ť":"t","ṭ":"t","ț":"t","ţ":"t","ṱ":"t","ṯ":"t","ŧ":"t","ƭ":"t","ʈ":"t","ⱦ":"t","ꞇ":"t","ꜩ":"tz","ⓤ":"u","u":"u","ù":"u","ú":"u","û":"u","ũ":"u","ṹ":"u","ū":"u","ṻ":"u","ŭ":"u","ü":"u","ǜ":"u","ǘ":"u","ǖ":"u","ǚ":"u","ủ":"u","ů":"u","ű":"u","ǔ":"u","ȕ":"u","ȗ":"u","ư":"u","ừ":"u","ứ":"u","ữ":"u","ử":"u","ự":"u","ụ":"u","ṳ":"u","ų":"u","ṷ":"u","ṵ":"u","ʉ":"u","ⓥ":"v","v":"v","ṽ":"v","ṿ":"v","ʋ":"v","ꝟ":"v","ʌ":"v","ꝡ":"vy","ⓦ":"w","w":"w","ẁ":"w","ẃ":"w","ŵ":"w","ẇ":"w","ẅ":"w","ẘ":"w","ẉ":"w","ⱳ":"w","ⓧ":"x","x":"x","ẋ":"x","ẍ":"x","ⓨ":"y","y":"y","ỳ":"y","ý":"y","ŷ":"y","ỹ":"y","ȳ":"y","ẏ":"y","ÿ":"y","ỷ":"y","ẙ":"y","ỵ":"y","ƴ":"y","ɏ":"y","ỿ":"y","ⓩ":"z","z":"z","ź":"z","ẑ":"z","ż":"z","ž":"z","ẓ":"z","ẕ":"z","ƶ":"z","ȥ":"z","ɀ":"z","ⱬ":"z","ꝣ":"z","Ά":"Α","Έ":"Ε","Ή":"Η","Ί":"Ι","Ϊ":"Ι","Ό":"Ο","Ύ":"Υ","Ϋ":"Υ","Ώ":"Ω","ά":"α","έ":"ε","ή":"η","ί":"ι","ϊ":"ι","ΐ":"ι","ό":"ο","ύ":"υ","ϋ":"υ","ΰ":"υ","ω":"ω","ς":"σ"}}),b.define("select2/data/base",["../utils"],function(a){function b(a,c){b.__super__.constructor.call(this)}return a.Extend(b,a.Observable),b.prototype.current=function(a){throw new Error("The `current` method must be defined in child classes.")},b.prototype.query=function(a,b){throw new Error("The `query` method must be defined in child classes.")},b.prototype.bind=function(a,b){},b.prototype.destroy=function(){},b.prototype.generateResultId=function(b,c){var d=b.id+"-result-";return d+=a.generateChars(4),null!=c.id?d+="-"+c.id.toString():d+="-"+a.generateChars(4),d},b}),b.define("select2/data/select",["./base","../utils","jquery"],function(a,b,c){function d(a,b){this.$element=a,this.options=b,d.__super__.constructor.call(this)}return b.Extend(d,a),d.prototype.current=function(a){var b=[],d=this;this.$element.find(":selected").each(function(){var a=c(this),e=d.item(a);b.push(e)}),a(b)},d.prototype.select=function(a){var b=this;if(a.selected=!0,c(a.element).is("option"))return a.element.selected=!0,void this.$element.trigger("change");if(this.$element.prop("multiple"))this.current(function(d){var e=[];a=[a],a.push.apply(a,d);for(var f=0;f=0){var k=f.filter(d(j)),l=this.item(k),m=c.extend(!0,{},j,l),n=this.option(m);k.replaceWith(n)}else{var o=this.option(j);if(j.children){var p=this.convertToOptions(j.children);b.appendMany(o,p)}h.push(o)}}return h},d}),b.define("select2/data/ajax",["./array","../utils","jquery"],function(a,b,c){function d(a,b){this.ajaxOptions=this._applyDefaults(b.get("ajax")),null!=this.ajaxOptions.processResults&&(this.processResults=this.ajaxOptions.processResults),d.__super__.constructor.call(this,a,b)}return b.Extend(d,a),d.prototype._applyDefaults=function(a){var b={data:function(a){return c.extend({},a,{q:a.term})},transport:function(a,b,d){var e=c.ajax(a);return e.then(b),e.fail(d),e}};return c.extend({},b,a,!0)},d.prototype.processResults=function(a){return a},d.prototype.query=function(a,b){function d(){var d=f.transport(f,function(d){var f=e.processResults(d,a);e.options.get("debug")&&window.console&&console.error&&(f&&f.results&&c.isArray(f.results)||console.error("Select2: The AJAX results did not return an array in the `results` key of the response.")),b(f)},function(){d.status&&"0"===d.status||e.trigger("results:message",{message:"errorLoading"})});e._request=d}var e=this;null!=this._request&&(c.isFunction(this._request.abort)&&this._request.abort(),this._request=null);var f=c.extend({type:"GET"},this.ajaxOptions);"function"==typeof f.url&&(f.url=f.url.call(this.$element,a)),"function"==typeof f.data&&(f.data=f.data.call(this.$element,a)),this.ajaxOptions.delay&&null!=a.term?(this._queryTimeout&&window.clearTimeout(this._queryTimeout),this._queryTimeout=window.setTimeout(d,this.ajaxOptions.delay)):d()},d}),b.define("select2/data/tags",["jquery"],function(a){function b(b,c,d){var e=d.get("tags"),f=d.get("createTag");void 0!==f&&(this.createTag=f);var g=d.get("insertTag");if(void 0!==g&&(this.insertTag=g),b.call(this,c,d),a.isArray(e))for(var h=0;h0&&b.term.length>this.maximumInputLength)return void this.trigger("results:message",{message:"inputTooLong",args:{maximum:this.maximumInputLength,input:b.term,params:b}});a.call(this,b,c)},a}),b.define("select2/data/maximumSelectionLength",[],function(){function a(a,b,c){this.maximumSelectionLength=c.get("maximumSelectionLength"),a.call(this,b,c)}return a.prototype.query=function(a,b,c){var d=this;this.current(function(e){var f=null!=e?e.length:0;if(d.maximumSelectionLength>0&&f>=d.maximumSelectionLength)return void d.trigger("results:message",{message:"maximumSelected",args:{maximum:d.maximumSelectionLength}});a.call(d,b,c)})},a}),b.define("select2/dropdown",["jquery","./utils"],function(a,b){function c(a,b){this.$element=a,this.options=b,c.__super__.constructor.call(this)}return b.Extend(c,b.Observable),c.prototype.render=function(){var b=a('');return b.attr("dir",this.options.get("dir")),this.$dropdown=b,b},c.prototype.bind=function(){},c.prototype.position=function(a,b){},c.prototype.destroy=function(){this.$dropdown.remove()},c}),b.define("select2/dropdown/search",["jquery","../utils"],function(a,b){function c(){}return c.prototype.render=function(b){var c=b.call(this),d=a('');return this.$searchContainer=d,this.$search=d.find("input"),c.prepend(d),c},c.prototype.bind=function(b,c,d){var e=this;b.call(this,c,d),this.$search.on("keydown",function(a){e.trigger("keypress",a),e._keyUpPrevented=a.isDefaultPrevented()}),this.$search.on("input",function(b){a(this).off("keyup")}),this.$search.on("keyup input",function(a){e.handleSearch(a)}),c.on("open",function(){e.$search.attr("tabindex",0),e.$search.focus(),window.setTimeout(function(){e.$search.focus()},0)}),c.on("close",function(){e.$search.attr("tabindex",-1),e.$search.val("")}),c.on("focus",function(){c.isOpen()||e.$search.focus()}),c.on("results:all",function(a){if(null==a.query.term||""===a.query.term){e.showSearch(a)?e.$searchContainer.removeClass("select2-search--hide"):e.$searchContainer.addClass("select2-search--hide")}})},c.prototype.handleSearch=function(a){if(!this._keyUpPrevented){var b=this.$search.val();this.trigger("query",{term:b})}this._keyUpPrevented=!1},c.prototype.showSearch=function(a,b){return!0},c}),b.define("select2/dropdown/hidePlaceholder",[],function(){function a(a,b,c,d){this.placeholder=this.normalizePlaceholder(c.get("placeholder")),a.call(this,b,c,d)}return a.prototype.append=function(a,b){b.results=this.removePlaceholder(b.results),a.call(this,b)},a.prototype.normalizePlaceholder=function(a,b){return"string"==typeof b&&(b={id:"",text:b}),b},a.prototype.removePlaceholder=function(a,b){for(var c=b.slice(0),d=b.length-1;d>=0;d--){var e=b[d];this.placeholder.id===e.id&&c.splice(d,1)}return c},a}),b.define("select2/dropdown/infiniteScroll",["jquery"],function(a){function b(a,b,c,d){this.lastParams={},a.call(this,b,c,d),this.$loadingMore=this.createLoadingMore(),this.loading=!1}return b.prototype.append=function(a,b){this.$loadingMore.remove(),this.loading=!1,a.call(this,b),this.showLoadingMore(b)&&this.$results.append(this.$loadingMore)},b.prototype.bind=function(b,c,d){var e=this;b.call(this,c,d),c.on("query",function(a){e.lastParams=a,e.loading=!0}),c.on("query:append",function(a){e.lastParams=a,e.loading=!0}),this.$results.on("scroll",function(){var b=a.contains(document.documentElement,e.$loadingMore[0]);if(!e.loading&&b){e.$results.offset().top+e.$results.outerHeight(!1)+50>=e.$loadingMore.offset().top+e.$loadingMore.outerHeight(!1)&&e.loadMore()}})},b.prototype.loadMore=function(){this.loading=!0;var b=a.extend({},{page:1},this.lastParams);b.page++,this.trigger("query:append",b)},b.prototype.showLoadingMore=function(a,b){return b.pagination&&b.pagination.more},b.prototype.createLoadingMore=function(){var b=a('
        • '),c=this.options.get("translations").get("loadingMore");return b.html(c(this.lastParams)),b},b}),b.define("select2/dropdown/attachBody",["jquery","../utils"],function(a,b){function c(b,c,d){this.$dropdownParent=d.get("dropdownParent")||a(document.body),b.call(this,c,d)}return c.prototype.bind=function(a,b,c){var d=this,e=!1;a.call(this,b,c),b.on("open",function(){d._showDropdown(),d._attachPositioningHandler(b),e||(e=!0,b.on("results:all",function(){d._positionDropdown(),d._resizeDropdown()}),b.on("results:append",function(){d._positionDropdown(),d._resizeDropdown()}))}),b.on("close",function(){d._hideDropdown(),d._detachPositioningHandler(b)}),this.$dropdownContainer.on("mousedown",function(a){a.stopPropagation()})},c.prototype.destroy=function(a){a.call(this),this.$dropdownContainer.remove()},c.prototype.position=function(a,b,c){b.attr("class",c.attr("class")),b.removeClass("select2"),b.addClass("select2-container--open"),b.css({position:"absolute",top:-999999}),this.$container=c},c.prototype.render=function(b){var c=a(""),d=b.call(this);return c.append(d),this.$dropdownContainer=c,c},c.prototype._hideDropdown=function(a){this.$dropdownContainer.detach()},c.prototype._attachPositioningHandler=function(c,d){var e=this,f="scroll.select2."+d.id,g="resize.select2."+d.id,h="orientationchange.select2."+d.id,i=this.$container.parents().filter(b.hasScroll);i.each(function(){a(this).data("select2-scroll-position",{x:a(this).scrollLeft(),y:a(this).scrollTop()})}),i.on(f,function(b){var c=a(this).data("select2-scroll-position");a(this).scrollTop(c.y)}),a(window).on(f+" "+g+" "+h,function(a){e._positionDropdown(),e._resizeDropdown()})},c.prototype._detachPositioningHandler=function(c,d){var e="scroll.select2."+d.id,f="resize.select2."+d.id,g="orientationchange.select2."+d.id;this.$container.parents().filter(b.hasScroll).off(e),a(window).off(e+" "+f+" "+g)},c.prototype._positionDropdown=function(){var b=a(window),c=this.$dropdown.hasClass("select2-dropdown--above"),d=this.$dropdown.hasClass("select2-dropdown--below"),e=null,f=this.$container.offset();f.bottom=f.top+this.$container.outerHeight(!1);var g={height:this.$container.outerHeight(!1)};g.top=f.top,g.bottom=f.top+g.height;var h={height:this.$dropdown.outerHeight(!1)},i={top:b.scrollTop(),bottom:b.scrollTop()+b.height()},j=i.topf.bottom+h.height,l={left:f.left,top:g.bottom},m=this.$dropdownParent;"static"===m.css("position")&&(m=m.offsetParent());var n=m.offset();l.top-=n.top,l.left-=n.left,c||d||(e="below"),k||!j||c?!j&&k&&c&&(e="below"):e="above",("above"==e||c&&"below"!==e)&&(l.top=g.top-n.top-h.height),null!=e&&(this.$dropdown.removeClass("select2-dropdown--below select2-dropdown--above").addClass("select2-dropdown--"+e),this.$container.removeClass("select2-container--below select2-container--above").addClass("select2-container--"+e)),this.$dropdownContainer.css(l)},c.prototype._resizeDropdown=function(){var a={width:this.$container.outerWidth(!1)+"px"};this.options.get("dropdownAutoWidth")&&(a.minWidth=a.width,a.position="relative",a.width="auto"),this.$dropdown.css(a)},c.prototype._showDropdown=function(a){this.$dropdownContainer.appendTo(this.$dropdownParent),this._positionDropdown(),this._resizeDropdown()},c}),b.define("select2/dropdown/minimumResultsForSearch",[],function(){function a(b){for(var c=0,d=0;d0&&(l.dataAdapter=j.Decorate(l.dataAdapter,r)),l.maximumInputLength>0&&(l.dataAdapter=j.Decorate(l.dataAdapter,s)),l.maximumSelectionLength>0&&(l.dataAdapter=j.Decorate(l.dataAdapter,t)),l.tags&&(l.dataAdapter=j.Decorate(l.dataAdapter,p)),null==l.tokenSeparators&&null==l.tokenizer||(l.dataAdapter=j.Decorate(l.dataAdapter,q)),null!=l.query){var C=b(l.amdBase+"compat/query");l.dataAdapter=j.Decorate(l.dataAdapter,C)}if(null!=l.initSelection){var D=b(l.amdBase+"compat/initSelection");l.dataAdapter=j.Decorate(l.dataAdapter,D)}}if(null==l.resultsAdapter&&(l.resultsAdapter=c,null!=l.ajax&&(l.resultsAdapter=j.Decorate(l.resultsAdapter,x)),null!=l.placeholder&&(l.resultsAdapter=j.Decorate(l.resultsAdapter,w)),l.selectOnClose&&(l.resultsAdapter=j.Decorate(l.resultsAdapter,A))),null==l.dropdownAdapter){if(l.multiple)l.dropdownAdapter=u;else{var E=j.Decorate(u,v);l.dropdownAdapter=E}if(0!==l.minimumResultsForSearch&&(l.dropdownAdapter=j.Decorate(l.dropdownAdapter,z)),l.closeOnSelect&&(l.dropdownAdapter=j.Decorate(l.dropdownAdapter,B)),null!=l.dropdownCssClass||null!=l.dropdownCss||null!=l.adaptDropdownCssClass){var F=b(l.amdBase+"compat/dropdownCss");l.dropdownAdapter=j.Decorate(l.dropdownAdapter,F)}l.dropdownAdapter=j.Decorate(l.dropdownAdapter,y)}if(null==l.selectionAdapter){if(l.multiple?l.selectionAdapter=e:l.selectionAdapter=d,null!=l.placeholder&&(l.selectionAdapter=j.Decorate(l.selectionAdapter,f)),l.allowClear&&(l.selectionAdapter=j.Decorate(l.selectionAdapter,g)),l.multiple&&(l.selectionAdapter=j.Decorate(l.selectionAdapter,h)),null!=l.containerCssClass||null!=l.containerCss||null!=l.adaptContainerCssClass){var G=b(l.amdBase+"compat/containerCss");l.selectionAdapter=j.Decorate(l.selectionAdapter,G)}l.selectionAdapter=j.Decorate(l.selectionAdapter,i)}if("string"==typeof l.language)if(l.language.indexOf("-")>0){var H=l.language.split("-"),I=H[0];l.language=[l.language,I]}else l.language=[l.language];if(a.isArray(l.language)){var J=new k;l.language.push("en");for(var K=l.language,L=0;L0){for(var f=a.extend(!0,{},e),g=e.children.length-1;g>=0;g--){null==c(d,e.children[g])&&f.children.splice(g,1)}return f.children.length>0?f:c(d,f)}var h=b(e.text).toUpperCase(),i=b(d.term).toUpperCase();return h.indexOf(i)>-1?e:null}this.defaults={amdBase:"./",amdLanguageBase:"./i18n/",closeOnSelect:!0,debug:!1,dropdownAutoWidth:!1,escapeMarkup:j.escapeMarkup,language:C,matcher:c,minimumInputLength:0,maximumInputLength:0,maximumSelectionLength:0,minimumResultsForSearch:0,selectOnClose:!1,sorter:function(a){return a},templateResult:function(a){return a.text},templateSelection:function(a){return a.text},theme:"default",width:"resolve"}},D.prototype.set=function(b,c){var d=a.camelCase(b),e={};e[d]=c;var f=j._convertData(e);a.extend(this.defaults,f)},new D}),b.define("select2/options",["require","jquery","./defaults","./utils"],function(a,b,c,d){function e(b,e){if(this.options=b,null!=e&&this.fromElement(e),this.options=c.apply(this.options),e&&e.is("input")){var f=a(this.get("amdBase")+"compat/inputData");this.options.dataAdapter=d.Decorate(this.options.dataAdapter,f)}}return e.prototype.fromElement=function(a){var c=["select2"];null==this.options.multiple&&(this.options.multiple=a.prop("multiple")),null==this.options.disabled&&(this.options.disabled=a.prop("disabled")),null==this.options.language&&(a.prop("lang")?this.options.language=a.prop("lang").toLowerCase():a.closest("[lang]").prop("lang")&&(this.options.language=a.closest("[lang]").prop("lang"))),null==this.options.dir&&(a.prop("dir")?this.options.dir=a.prop("dir"):a.closest("[dir]").prop("dir")?this.options.dir=a.closest("[dir]").prop("dir"):this.options.dir="ltr"),a.prop("disabled",this.options.disabled),a.prop("multiple",this.options.multiple),a.data("select2Tags")&&(this.options.debug&&window.console&&console.warn&&console.warn('Select2: The `data-select2-tags` attribute has been changed to use the `data-data` and `data-tags="true"` attributes and will be removed in future versions of Select2.'),a.data("data",a.data("select2Tags")),a.data("tags",!0)),a.data("ajaxUrl")&&(this.options.debug&&window.console&&console.warn&&console.warn("Select2: The `data-ajax-url` attribute has been changed to `data-ajax--url` and support for the old attribute will be removed in future versions of Select2."),a.attr("ajax--url",a.data("ajaxUrl")),a.data("ajax--url",a.data("ajaxUrl")));var e={};e=b.fn.jquery&&"1."==b.fn.jquery.substr(0,2)&&a[0].dataset?b.extend(!0,{},a[0].dataset,a.data()):a.data();var f=b.extend(!0,{},e);f=d._convertData(f);for(var g in f)b.inArray(g,c)>-1||(b.isPlainObject(this.options[g])?b.extend(this.options[g],f[g]):this.options[g]=f[g]);return this},e.prototype.get=function(a){return this.options[a]},e.prototype.set=function(a,b){this.options[a]=b},e}),b.define("select2/core",["jquery","./options","./utils","./keys"],function(a,b,c,d){var e=function(a,c){null!=a.data("select2")&&a.data("select2").destroy(),this.$element=a,this.id=this._generateId(a),c=c||{},this.options=new b(c,a),e.__super__.constructor.call(this);var d=a.attr("tabindex")||0;a.data("old-tabindex",d),a.attr("tabindex","-1");var f=this.options.get("dataAdapter");this.dataAdapter=new f(a,this.options);var g=this.render();this._placeContainer(g);var h=this.options.get("selectionAdapter");this.selection=new h(a,this.options),this.$selection=this.selection.render(),this.selection.position(this.$selection,g);var i=this.options.get("dropdownAdapter");this.dropdown=new i(a,this.options),this.$dropdown=this.dropdown.render(),this.dropdown.position(this.$dropdown,g);var j=this.options.get("resultsAdapter");this.results=new j(a,this.options,this.dataAdapter),this.$results=this.results.render(),this.results.position(this.$results,this.$dropdown);var k=this;this._bindAdapters(),this._registerDomEvents(),this._registerDataEvents(),this._registerSelectionEvents(),this._registerDropdownEvents(),this._registerResultsEvents(),this._registerEvents(),this.dataAdapter.current(function(a){k.trigger("selection:update",{data:a})}),a.addClass("select2-hidden-accessible"),a.attr("aria-hidden","true"),this._syncAttributes(),a.data("select2",this)};return c.Extend(e,c.Observable),e.prototype._generateId=function(a){var b="";return b=null!=a.attr("id")?a.attr("id"):null!=a.attr("name")?a.attr("name")+"-"+c.generateChars(2):c.generateChars(4),b=b.replace(/(:|\.|\[|\]|,)/g,""),b="select2-"+b},e.prototype._placeContainer=function(a){a.insertAfter(this.$element);var b=this._resolveWidth(this.$element,this.options.get("width"));null!=b&&a.css("width",b)},e.prototype._resolveWidth=function(a,b){var c=/^width:(([-+]?([0-9]*\.)?[0-9]+)(px|em|ex|%|in|cm|mm|pt|pc))/i;if("resolve"==b){var d=this._resolveWidth(a,"style");return null!=d?d:this._resolveWidth(a,"element")}if("element"==b){var e=a.outerWidth(!1);return e<=0?"auto":e+"px"}if("style"==b){var f=a.attr("style");if("string"!=typeof f)return null;for(var g=f.split(";"),h=0,i=g.length;h=1)return k[1]}return null}return b},e.prototype._bindAdapters=function(){this.dataAdapter.bind(this,this.$container),this.selection.bind(this,this.$container),this.dropdown.bind(this,this.$container),this.results.bind(this,this.$container)},e.prototype._registerDomEvents=function(){var b=this;this.$element.on("change.select2",function(){b.dataAdapter.current(function(a){b.trigger("selection:update",{data:a})})}),this.$element.on("focus.select2",function(a){b.trigger("focus",a)}),this._syncA=c.bind(this._syncAttributes,this),this._syncS=c.bind(this._syncSubtree,this),this.$element[0].attachEvent&&this.$element[0].attachEvent("onpropertychange",this._syncA);var d=window.MutationObserver||window.WebKitMutationObserver||window.MozMutationObserver;null!=d?(this._observer=new d(function(c){a.each(c,b._syncA),a.each(c,b._syncS)}),this._observer.observe(this.$element[0],{attributes:!0,childList:!0,subtree:!1})):this.$element[0].addEventListener&&(this.$element[0].addEventListener("DOMAttrModified",b._syncA,!1),this.$element[0].addEventListener("DOMNodeInserted",b._syncS,!1),this.$element[0].addEventListener("DOMNodeRemoved",b._syncS,!1))},e.prototype._registerDataEvents=function(){var a=this;this.dataAdapter.on("*",function(b,c){a.trigger(b,c)})},e.prototype._registerSelectionEvents=function(){var b=this,c=["toggle","focus"];this.selection.on("toggle",function(){b.toggleDropdown()}),this.selection.on("focus",function(a){b.focus(a)}),this.selection.on("*",function(d,e){-1===a.inArray(d,c)&&b.trigger(d,e)})},e.prototype._registerDropdownEvents=function(){var a=this;this.dropdown.on("*",function(b,c){a.trigger(b,c)})},e.prototype._registerResultsEvents=function(){var a=this;this.results.on("*",function(b,c){a.trigger(b,c)})},e.prototype._registerEvents=function(){var a=this;this.on("open",function(){a.$container.addClass("select2-container--open")}),this.on("close",function(){a.$container.removeClass("select2-container--open")}),this.on("enable",function(){a.$container.removeClass("select2-container--disabled")}),this.on("disable",function(){a.$container.addClass("select2-container--disabled")}),this.on("blur",function(){a.$container.removeClass("select2-container--focus")}),this.on("query",function(b){a.isOpen()||a.trigger("open",{}),this.dataAdapter.query(b,function(c){a.trigger("results:all",{data:c,query:b})})}),this.on("query:append",function(b){this.dataAdapter.query(b,function(c){a.trigger("results:append",{data:c,query:b})})}),this.on("keypress",function(b){var c=b.which;a.isOpen()?c===d.ESC||c===d.TAB||c===d.UP&&b.altKey?(a.close(),b.preventDefault()):c===d.ENTER?(a.trigger("results:select",{}),b.preventDefault()):c===d.SPACE&&b.ctrlKey?(a.trigger("results:toggle",{}),b.preventDefault()):c===d.UP?(a.trigger("results:previous",{}),b.preventDefault()):c===d.DOWN&&(a.trigger("results:next",{}),b.preventDefault()):(c===d.ENTER||c===d.SPACE||c===d.DOWN&&b.altKey)&&(a.open(),b.preventDefault())})},e.prototype._syncAttributes=function(){this.options.set("disabled",this.$element.prop("disabled")),this.options.get("disabled")?(this.isOpen()&&this.close(),this.trigger("disable",{})):this.trigger("enable",{})},e.prototype._syncSubtree=function(a,b){var c=!1,d=this;if(!a||!a.target||"OPTION"===a.target.nodeName||"OPTGROUP"===a.target.nodeName){if(b)if(b.addedNodes&&b.addedNodes.length>0)for(var e=0;e0&&(c=!0);else c=!0;c&&this.dataAdapter.current(function(a){d.trigger("selection:update",{data:a})})}},e.prototype.trigger=function(a,b){var c=e.__super__.trigger,d={open:"opening",close:"closing",select:"selecting",unselect:"unselecting"};if(void 0===b&&(b={}),a in d){var f=d[a],g={prevented:!1,name:a,args:b};if(c.call(this,f,g),g.prevented)return void(b.prevented=!0)}c.call(this,a,b)},e.prototype.toggleDropdown=function(){this.options.get("disabled")||(this.isOpen()?this.close():this.open())},e.prototype.open=function(){this.isOpen()||this.trigger("query",{})},e.prototype.close=function(){this.isOpen()&&this.trigger("close",{})},e.prototype.isOpen=function(){return this.$container.hasClass("select2-container--open")},e.prototype.hasFocus=function(){return this.$container.hasClass("select2-container--focus")},e.prototype.focus=function(a){this.hasFocus()||(this.$container.addClass("select2-container--focus"),this.trigger("focus",{}))},e.prototype.enable=function(a){this.options.get("debug")&&window.console&&console.warn&&console.warn('Select2: The `select2("enable")` method has been deprecated and will be removed in later Select2 versions. Use $element.prop("disabled") instead.'),null!=a&&0!==a.length||(a=[!0]);var b=!a[0];this.$element.prop("disabled",b)},e.prototype.data=function(){this.options.get("debug")&&arguments.length>0&&window.console&&console.warn&&console.warn('Select2: Data can no longer be set using `select2("data")`. You should consider setting the value instead using `$element.val()`.');var a=[];return this.dataAdapter.current(function(b){a=b}),a},e.prototype.val=function(b){if(this.options.get("debug")&&window.console&&console.warn&&console.warn('Select2: The `select2("val")` method has been deprecated and will be removed in later Select2 versions. Use $element.val() instead.'),null==b||0===b.length)return this.$element.val();var c=b[0];a.isArray(c)&&(c=a.map(c,function(a){return a.toString()})),this.$element.val(c).trigger("change")},e.prototype.destroy=function(){this.$container.remove(),this.$element[0].detachEvent&&this.$element[0].detachEvent("onpropertychange",this._syncA),null!=this._observer?(this._observer.disconnect(),this._observer=null):this.$element[0].removeEventListener&&(this.$element[0].removeEventListener("DOMAttrModified",this._syncA,!1),this.$element[0].removeEventListener("DOMNodeInserted",this._syncS,!1),this.$element[0].removeEventListener("DOMNodeRemoved",this._syncS,!1)),this._syncA=null,this._syncS=null,this.$element.off(".select2"),this.$element.attr("tabindex",this.$element.data("old-tabindex")),this.$element.removeClass("select2-hidden-accessible"),this.$element.attr("aria-hidden","false"),this.$element.removeData("select2"),this.dataAdapter.destroy(),this.selection.destroy(),this.dropdown.destroy(),this.results.destroy(),this.dataAdapter=null,this.selection=null,this.dropdown=null,this.results=null},e.prototype.render=function(){var b=a('');return b.attr("dir",this.options.get("dir")),this.$container=b,this.$container.addClass("select2-container--"+this.options.get("theme")),b.data("element",this.$element),b},e}),b.define("jquery-mousewheel",["jquery"],function(a){return a}),b.define("jquery.select2",["jquery","jquery-mousewheel","./select2/core","./select2/defaults"],function(a,b,c,d){if(null==a.fn.select2){var e=["open","close","destroy"];a.fn.select2=function(b){if("object"==typeof(b=b||{}))return this.each(function(){var d=a.extend(!0,{},b);new c(a(this),d)}),this;if("string"==typeof b){var d,f=Array.prototype.slice.call(arguments,1);return this.each(function(){var c=a(this).data("select2");null==c&&window.console&&console.error&&console.error("The select2('"+b+"') method was called on an element that is not using Select2."),d=c[b].apply(c,f)}),a.inArray(b,e)>-1?this:d}throw new Error("Invalid arguments for Select2: "+b)}}return null==a.fn.select2.defaults&&(a.fn.select2.defaults=d),c}),{define:b.define,require:b.require}}(),c=b.require("jquery.select2");return a.fn.select2.amd=b,c}); diff --git a/app/assets/v2/js/kudos-search.js b/app/assets/v2/js/kudos-search.js new file mode 100644 index 00000000000..1bf11156841 --- /dev/null +++ b/app/assets/v2/js/kudos-search.js @@ -0,0 +1,179 @@ +function kudosSearch(elem) { + var selectItem = elem || '.kudos-search'; + + $(selectItem).each(function() { + if (!$(this).length) { + return; + } + var auto_terms = [ 'rare', 'common', 'ninja', 'soft skills', 'programming' ]; + var autocomplete_html = ''; + + for (var i = 0; i < auto_terms.length; i++) { + var delimiter = i == auto_terms.length - 1 ? '' : '|'; + + autocomplete_html += " " + auto_terms[i] + ' ' + delimiter; + } + + $(this).select2({ + ajax: { + url: '/api/v0.1/kudos_search/', + dataType: 'json', + delay: 250, + data: function(params) { + + let query = { + term: params.term[0] === '@' ? params.term.slice(1) : params.term + }; + + return query; + }, + processResults: function(data) { + return { + results: data + }; + }, + cache: true + }, + theme: 'kudos', + placeholder: 'Search kudos (or try: ' + autocomplete_html + ' )', + allowClear: true, + minimumInputLength: 3, + escapeMarkup: function(markup) { + + return markup; + }, + templateResult: formatKudos, + templateSelection: formatKudosSelection + }); + + // fix for wrong position on select open + var select2Instance = $(this).data('select2'); + + select2Instance.on('results:message', function(params) { + this.dropdown._resizeDropdown(); + this.dropdown._positionDropdown(); + }); + + function formatKudos(kudos) { + + if (kudos.loading) { + return kudos.text; + } + var markup; + + if (kudos.copy) { + var autocomplete_html = '
            '; + + for (var i = 0; i < kudos.autocomplete.length; i++) { + autocomplete_html += "
          • " + kudos.autocomplete[i] + '
          • '; + } + autocomplete_html += '
          '; + + markup = `
          +
          + ${kudos.copy} ${autocomplete_html} +
          +
          `; + } else { + markup = `
          +
          + +
          +
          +
          +
          ${kudos.name_human}
          +
          ${kudos.price_finney} ETH (${kudos.price_usd_humanized})
          +
          + expand > +
          ${kudos.description}
          +
          +
          `; + } + + return markup; + } + + function formatKudosSelection(kudos) { + + let selected; + + if (kudos.id === '') { + kudosIsSelected(); + return kudos.text; + } else if (kudos.id) { + kudosIsSelected(true); + selected = `
          +
          + +
          +
          +
          +
          ${kudos.name_human} ${kudos.price_finney} ETH
          +
          +
          ${kudos.description}
          +
          +
          `; + + document.selected_kudos = $('.kudos-search').select2('data')[0]; + // document.selected_kudos = { + // name: kudos.name, + // id: kudos.id, + // price_finney: kudos.price_finney + // }; + } else { + selected = kudos.name_human; + } + return selected; + } + + function kudosIsSelected(state) { + let comments = $('.kudos-comment'); + let alert = $('.msg-alert'); + + if (state) { + comments.show(); + alert.show(); + } else { + comments.hide(); + alert.hide(); + } + + } + + $(selectItem).on('select2:unselecting', function(e) { + $(this).val(null).trigger('change'); + document.selected_kudos = null; + e.preventDefault(); + }); + + }); +} + +$('document').ready(function() { + kudosSearch(); + + $('body').on('click', '#kudos_autocomplete li, .kudos_autocomplete', function(e) { + var search_term = $(this).text(); + + $('.select2-search__field').val(search_term); + $('.select2-search__field').trigger('keyup'); + e.preventDefault(); + }); + var expandFunc = function(e) { + $(this).parents('.kudos-search-result').addClass('kudos-search-result-large'); + $(this).parents('.kudos-search-result').find('.text-truncate').removeClass('text-truncate'); + $(this).addClass('hidden'); + e.preventDefault(); + }; + + $('body').on('mouseover', 'a.more', expandFunc); + $('body').on('click', 'a.more', expandFunc); + + $('body').on('mouseleave', '.kudos-search-result', function(e) { + $(this).removeClass('kudos-search-result-large'); + $(this).find('.kudos-description').addClass('text-truncate'); + $(this).find('.more').removeClass('hidden'); + e.preventDefault(); + }); + +}); diff --git a/app/assets/v2/js/pages/kudos-search.js b/app/assets/v2/js/pages/kudos-search.js new file mode 100644 index 00000000000..aeb2851af3d --- /dev/null +++ b/app/assets/v2/js/pages/kudos-search.js @@ -0,0 +1,34 @@ +/* eslint-disable no-div-regex */ + +$(document).ready(function() { + var queryParam = getQueryParams(document.location.search); + var clearBtn = $('.clear-search'); + + if (queryParam && queryParam.q) { + $('#kudos-search').val(queryParam.q); + clearBtn.removeClass('hidden'); + } + + if (queryParam && queryParam.order_by) { + $('#sort_order').val(queryParam.order_by); + } + + $('#sort_order').change(function() { + if (queryParam && queryParam.q) { + window.location.search = '?q=' + queryParam.q + '&order_by=' + $(this).val(); + } else { + window.location.search = '?order_by=' + $(this).val(); + } + + }); +}); + +function getQueryParams(query) { + if (!query.length) { + return; + } + + var search = query.substring(1); + + return JSON.parse('{"' + decodeURI(search).replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g, '":"') + '"}'); +} diff --git a/app/assets/v2/js/pages/kudos_details.js b/app/assets/v2/js/pages/kudos_details.js new file mode 100644 index 00000000000..a89e15afbcb --- /dev/null +++ b/app/assets/v2/js/pages/kudos_details.js @@ -0,0 +1,155 @@ +var cloneKudos = function(name, numClones) { + console.log('name: ' + name); + console.log('numClones: ' + numClones); + + var account = web3.eth.coinbase; + var kudosContractInstance = web3.eth.contract(kudos_abi).at(kudos_address()); + + kudosContractInstance.clone(name, numClones, {from: account, value: new web3.BigNumber(1000000000000000)}, function(error, txid) { + console.log('txid:' + txid); + return true; + }); +}; + +var getKudosById = function(kudosId) { + $.get('/api/v0.1/kudos/' + kudosId, function(results, status) { + return results; + }); +}; + + +$(document).ready(function() { + // stop_kudos_levitate(); + // let kudosId = window.location.pathname.split('/')[2]; + // let kudosId = $('#kudosId').text() + // let kudosName = $('#kudosName').text() + let kudosNumClonesAvailable = parseInt($('#kudosNumClonesAvailable').text()); + let kudosNumClonesAllowed = parseInt($('#kudosNumClonesAllowed').text()); + let numClones = kudosNumClonesAvailable - kudosNumClonesAllowed; + + $('#kudos-image').hover(function() { + start_kudos_levitate(); + }, function() { + stop_kudos_levitate(); + }); + + + $('.kudos_levitate_container, #kudos-image').click(function() { + + pct_msg_should_be_shown = 0; // Disabled, *for now*. I will convince people that + // the Kudos should say something at some point :) - KO + if (Math.random() < pct_msg_should_be_shown) { + rotate_kudos_msg(); + $('.kudos_msg').css('display', 'block'); + setTimeout(function() { + $('.kudos_msg').css('display', 'none'); + }, 1000); + } else { + $('#kudos-image').addClass('shake'); + setTimeout(function() { + $('#kudos-image').removeClass('shake'); + }, 1000); + } + + }); + + if (kudosNumClonesAvailable == 0) { + $('#getKudos').attr('class', 'btn btn-gc-blue disabled').attr('aria-disabled', 'true'); + return; + } + + $('#getKudos').click(function() { + if (numClones > kudosNumClonesAvailable) { + alert('Cannot make ' + numClones + ' clone(s). ' + kudosNumClonesAvailable + ' clones available!'); + return; + } + + $.get('/api/v0.1/kudos/' + kudosId, function(results, status) { + let kudosName = results.name; + + cloneKudos(kudosName, numClones); + }); + }); + +}); + +var rotate_kudos_msg = function() { + var messages = [ + [ 'Buy Me!', 'I\'m looking for a good home.' ], + [ 'Please.. Choose me!', 'All I want is a good home.' ], + [ 'Please.. Choose me!', "You don't know what it's like to live in the blockchain..." ], + [ "It's ...", '... so lonely in here..' ], + [ 'Am I the one?', '' ], + [ 'Am I the one?', '(sad puppy dog eyes)' ], + [ 'Who are you sending a kudos to?', "I bet I'll make them really happy!" ], + [ 'Who are you sending a kudos to?', "I'm the one to make them happy!" ], + [ 'I play nice with others.', '' ], + [ "I'd look really good on a profile!", '' ], + [ 'Who are you sending a kudos to?', "I'd look good on their profile.." ] + ]; + var item = messages[Math.floor(Math.random() * messages.length)]; + var h1 = item[0]; + var p = item[1]; + + $('.kudos_msg strong').text(h1); + $('.kudos_msg p').text(p); +}; + + +var start_kudos_levitate = function() { + $('.kudos_levitate_container').css('display', 'block'); + var sapphire = document.getElementById('kudos-image'); + var shadow = document.getElementById('shadow'); + var sparkle1 = document.getElementById('sparkle1'); + var sparkle2 = document.getElementById('sparkle2'); + var sparkle3 = document.getElementById('sparkle3'); + var sparkle4 = document.getElementById('sparkle4'); + var twinkle1 = document.querySelectorAll('#sparkle1 > .st6, #sparkle1 > .st7'); + var twinkle2 = document.querySelectorAll('#sparkle2 > .st6, #sparkle2 > .st7'); + var twinkle3 = document.querySelectorAll('#sparkle3 > .st6, #sparkle3 > .st7'); + var twinkle4 = document.querySelectorAll('#sparkle4 > .st6, #sparkle4 > .st7'); + var sapphireTl = new TimelineLite(); + var sparkleTl = new TimelineLite({ + repeat: -1, + yoyo: true, + onComplete: function() { + this.restart(); + } + }); + + sapphireTl.from(sapphire, 1, { y: '10px', ease: Power1.easeInOut, repeat: -1, yoyo: true }, 'sapph') + .fromTo(shadow, 1, { scale: 1, transformOrigin: 'center center', ease: Power1.easeInOut, yoyo: true, repeat: -1 }, { scale: 0.5, transformOrigin: 'center center', ease: Power1.easeInOut, yoyo: true, repeat: -1 }, 'sapph'); + + + sparkleTl.to(twinkle1, 1, { scale: 0, transformOrigin: 'center center', ease: Power1.easeOut }, 'sparkle') + .to(twinkle2, 1, { scale: 0, transformOrigin: 'center center', ease: Power1.easeOut }, 'sparkle+=0.3') + .to(twinkle3, 1, { scale: 0, transformOrigin: 'center center', ease: Power1.easeOut }, 'sparkle+=0.6') + .to(twinkle4, 1, { scale: 0, transformOrigin: 'center center', ease: Power1.easeOut }, 'sparkle+=0.9') + .to(twinkle1, 1, { scale: 1, transformOrigin: 'center center', ease: Elastic.easeOut }, 'sparkleshow') + .to(twinkle2, 1, { scale: 1, transformOrigin: 'center center', ease: Elastic.easeOut }, 'sparkleshow+=0.3') + .to(twinkle3, 1, { scale: 1, transformOrigin: 'center center', ease: Elastic.easeOut }, 'sparkleshow+=0.6') + .to(twinkle4, 1, { scale: 1, transformOrigin: 'center center', ease: Elastic.easeOut }, 'sparkleshow+=0.9'); + + sparkleTl.timeScale(2); +}; + +var stop_kudos_levitate = function() { + $('.kudos_levitate_container').css('display', 'none'); + TweenMax.killAll(false, true, false); + +}; + +// $('#getKudos').click(function() { + + +// $(document).ready(function() { +// let address = web3.eth.coinbase; +// console.log(address); +// $.get('/api/v0.1/kudos?lister=' + address, function(results, status) { +// console.log(status) +// console.log(results) +// let numKudos = results.length; +// results.forEach(renderKudos) +// // renderKudos(results) +// }) +// }) diff --git a/app/assets/v2/js/pages/kudos_receive.js b/app/assets/v2/js/pages/kudos_receive.js new file mode 100644 index 00000000000..856fc5c118b --- /dev/null +++ b/app/assets/v2/js/pages/kudos_receive.js @@ -0,0 +1,185 @@ +/* eslint-disable no-console */ +var combine_secrets = function(secret1, secret2) { + var shares = [ secret1, secret2 ]; + + return secrets.combine(shares); +}; + +var sign_and_send = function(rawTx, success_callback, private_key) { + // sign & serialize raw transaction + console.log('rawTx: ' + JSON.stringify(rawTx)); + console.log('private_key: ' + private_key); + var tx = new EthJS.Tx(rawTx); + + var private_key_buffer = new EthJS.Buffer.Buffer.from(private_key, 'hex'); + // console.log(private_key_buffer) + + tx.sign(private_key_buffer); + var serializedTx = tx.serialize(); + + console.log('0x' + serializedTx.toString('hex')); + + // send raw transaction + web3.eth.sendRawTransaction('0x' + serializedTx.toString('hex'), success_callback); + +}; + +window.onload = function() { + waitforWeb3(function() { + console.log(document.kudos_transfer); + console.log(document.ipfs_key_to_secret); + ipfs.ipfsApi = IpfsApi(ipfsConfig); + ipfs.setProvider(ipfsConfig); + if (typeof document.ipfs_key_to_secret == 'undefined') { + return; + } + ipfs.catText(document.ipfs_key_to_secret, function(err, key2) { + if (err) { + _alert('Could not reach IPFS. please try again later.', 'error'); + return; + } + document.priv_key = combine_secrets(key2, document.gitcoin_secret); + }); + }); + waitforWeb3(function() { + if (document.web3network != document.network) { + _alert({ message: gettext('You are not on the right web3 network. Please switch to ') + document.network }, 'error'); + } else { + $('#forwarding_address').val(web3.eth.coinbase); + } + $('#network').val(document.web3network); + }); +}; + +$(document).ready(function() { + $(document).on('click', '#receive', function(e) { + e.preventDefault(); + + var forwarding_address = $('#forwarding_address').val(); + + if (!$('#tos').is(':checked')) { + _alert('Please accept TOS.', 'error'); + unloading_button($(this)); + return; + } + if (forwarding_address == '0x0' || forwarding_address == '') { + _alert('Invalid forwarding address.', 'error'); + unloading_button($(this)); + return; + } + if (typeof web3 == 'undefined') { + _alert({ message: gettext('You are not on a web3 browser. Please switch to a web3 browser.') }, 'error'); + unloading_button($(this)); + return; + } + if (typeof document.kudos_transfer == 'undefined') { + _alert({ message: gettext('You do not have permission to do that.') }, 'error'); + return; + } + + if (document.web3network != document.network) { + _alert({ message: gettext('You are not on the right web3 network. Please switch to ') + document.network }, 'error'); + unloading_button($(this)); + return; + } + + loading_button($(this)); + + var success_callback = function(err, txid) { + unloading_button($(this)); + if (err) { + _alert(err.message.split('\n')[0], 'error'); + } else { + document.location.href = window.location.href.split('?')[0] + + '?receive_txid=' + txid + + '&forwarding_address=' + $('#forwarding_address').val() + + '&save_addr=' + ($('#save_addr').is(':checked') ? '1' : '0'); + } + }; + + // redeem kudos + + var gas_price_wei = new web3.BigNumber(document.gas_price * 10 ** 9); + // Not used + var token_address = document.kudos_transfer['token_address']; + var kudos_contract = web3.eth.contract(kudos_abi).at(kudos_address()); + var holding_address = document.kudos_transfer['holding_address']; + + + web3.eth.getTransactionCount(holding_address, function(error, result) { + var nonce = result; + + if (!nonce) { + nonce = 0; + } + // find existing balance + web3.eth.getBalance(holding_address, function(error, result) { + var balance = new web3.BigNumber(result.toString()); + + if (balance == 0) { + _alert('You must wait until the senders transaction confirm before claiming this Kudos.'); + return; + } + var rawTx; + + // Build the raw transaction data for the kudos clone & transfer + var kudosId = $('#kudosid').data('kudosid'); + var tokenId = $('#tokenid').data('tokenid'); + var numClones = 1; + var data = kudos_contract.clone.getData(forwarding_address, tokenId, numClones); + + // create the raw transaction + rawTx = { + nonce: web3.toHex(nonce), + to: kudos_address(), + from: holding_address, + data: data + }; + // console.log(rawTx) + + var kudosPriceInEth = parseFloat($('#kudosPrice').attr('data-ethprice')); + + console.log(kudosPriceInEth); + var kudosPriceInWei = new web3.BigNumber(kudosPriceInEth * 1.0 * Math.pow(10, 18)); + + var params = { + forwarding_address: forwarding_address, + tokenid: tokenId, + numClones: numClones, + holding_address: holding_address, + kudosPriceInWei: kudosPriceInWei.toString(10) + } + console.log('params for kudos clone:'); + console.log(params); + + kudos_contract.clone.estimateGas(forwarding_address, tokenId, numClones, {from: holding_address, value: kudosPriceInWei}, function(error, gasLimit) { + console.log(gasLimit); + var buffer = new web3.BigNumber(0); + + gasLimit = new web3.BigNumber(gasLimit); + var send_amount = balance.minus(gasLimit.times(gas_price_wei)).minus(buffer); + // rawTx['value'] = web3.toHex(send_amount.toString()); // deduct gas costs from amount to send + + rawTx['value'] = send_amount.toNumber(); + rawTx['gasPrice'] = web3.toHex(gas_price_wei.toString()); + // rawTx['gas'] = web3.toHex(gasLimit.toString()); + rawTx['gasLimit'] = web3.toHex(gasLimit.toString()); + show_console = true; + if (show_console) { + console.log('from_addr ', holding_address); + console.log('balance ', balance.toString()); + console.log('sending ', send_amount.toString()); + console.log('gas ', (gasLimit.times(gas_price_wei)).toString()); + console.log('gas price ', (gas_price_wei.toString())); + console.log('buffer ', (buffer.toString())); + console.log('balance > value ', balance > send_amount); + console.log(rawTx); + } + sign_and_send(rawTx, success_callback, document.priv_key); + // console.log('txid:' + txid) + // }) + }); + }); + }); + }); +}); \ No newline at end of file diff --git a/app/assets/v2/js/pages/kudos_send.js b/app/assets/v2/js/pages/kudos_send.js new file mode 100644 index 00000000000..bf4dcfef1ea --- /dev/null +++ b/app/assets/v2/js/pages/kudos_send.js @@ -0,0 +1,557 @@ +/* eslint-disable no-console */ + +var get_gas_price = function() { + if ($('#gasPrice').length) { + return $('#gasPrice').val() * Math.pow(10, 9); + } + if (typeof defaultGasPrice != 'undefined') { + return defaultGasPrice; + } + // 5 gwei + return 5 * 10 ** 9; +}; + +var generate_or_get_private_key = function() { + if (typeof document.account != 'undefined') { + return document.account; + } + document.account = new Accounts().new(); + document.account['shares'] = secrets.share(document.account['private'], 3, 2); + return document.account; +}; + +var clear_metadata = function() { + document.account = undefined; + document.hash1 = undefined; +}; + +var set_metadata = function(callback) { + var account = generate_or_get_private_key(); + var shares = account['shares']; + + console.log(ipfsConfig); + ipfs.ipfsApi = IpfsApi(ipfsConfig); + ipfs.setProvider(ipfsConfig); + ipfs.add(shares[1], function(err, hash1) { + if (err) + throw err; + document.hash1 = hash1; + }); +}; + +// Step 6 +var wait_for_metadata = function(callback) { + setTimeout(function() { + if ((typeof document.hash1 != 'undefined') && (document.hash1 != null)) { + console.log('document.hash1 = ' + document.hash1); + var account = generate_or_get_private_key(); + + // This is the metadata that gets passed into got_metadata_callback() + callback({ + 'pub_key': account['public'], + 'address': account['address'], + 'reference_hash_for_receipient': document.hash1, + 'gitcoin_secret': account['shares'][0], + 'is_direct': false + }); + } else { + console.log('still waiting...'); + // Step 7 + // Once the new account and key are generated, move onto got_metadata_callback() + wait_for_metadata(callback); + } + }, 500); + +}; + + +var wait_for_metadata_test = function(callback) { + // only for local testing purposes + console.log('document.hash1 = ' + document.hash1); + var account = generate_or_get_private_key(); + + // This is the metadata that gets passed into got_metadata_callback() + callback({ + 'pub_key': account['public'], + 'address': account['address'], + 'reference_hash_for_receipient': document.hash1, + 'gitcoin_secret': account['shares'][0], + 'is_direct': false + }); +}; + + +function advancedToggle() { + $('#advanced_toggle').css('display', 'none'); + $('#advanced').css('display', 'block'); + return false; +} + +function validateEmail(email) { + var re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; + + return re.test(email); +} + +function isNumeric(n) { + return !isNaN(parseFloat(n)) && isFinite(n); +} + +var updateEstimate = function(e) { + var denomination = $('#token option:selected').text(); + var amount = $('#amount').val(); + + getUSDEstimate(amount, denomination, function(usdAmount) { + if (usdAmount && usdAmount['full_text']) { + $('#usd_amount').html(usdAmount['full_text']); + } else { + $('#usd_amount').html('
          '); + } + }); +}; + +var etherscanDomain = function() { + var etherscanDomain = 'etherscan.io'; + + if (document.web3network == 'custom network') { + // testrpc + etherscanDomain = 'localhost'; + } else if (document.web3network == 'rinkeby') { + // rinkeby + etherscanDomain = 'rinkeby.etherscan.io'; + } else if (document.web3network == 'ropsten') { + // ropsten + etherscanDomain = 'ropsten.etherscan.io'; + } else { + // mainnet + } + return etherscanDomain; +}; + +var renderWallets = function(profileId) { + // $('.form-check').remove() + console.log('profileId: ' + profileId); + let url = '/api/v0.1/wallet?profile_id=' + profileId; + + $.get(url, function(results, status) { + console.log(status); + results.forEach(function(r) { + console.log(r); + let walletAddress = r.address; + + let walletItem = document.createElement('div'); + + $(walletItem).attr('class', 'form-check'); + + let walletInput = document.createElement('input'); + + $(walletInput).attr('class', 'form-check-input').attr('type', 'radio'). + attr('name', 'address').attr('value', walletAddress).attr('checked', 'true'); + + let walletLabel = document.createElement('label'); + + $(walletLabel).attr('class', 'form-check-label').attr('for', 'address').text(walletAddress); + + $(walletItem).append(walletInput, walletLabel); + $('#username-fg').after(walletItem); + }); + }); +}; + +// START HERE +// Step 0 +// DOM is ready +$(document).ready(function() { + set_metadata(); + // jquery bindings + $('#advanced_toggle').click(function(e) { + e.preventDefault(); + advancedToggle(); + }); + $('#amount').on('keyup blur change', updateEstimate); + $('#token').on('change', updateEstimate); + $('#username').select2(); + + // Step 1 + // Kudos send button is clicked + $('#send').click(function(e) { + e.preventDefault(); + $('#send_eth')[0].checkValidity(); + + if (!$('#username')[0].checkValidity()) { + $('#username')[0].reportValidity(); + } + var inputsValidate = document.querySelectorAll('input'); + + inputsValidate.forEach(function(elem) { + elem.reportValidity(); + }); + if ($(this).hasClass('disabled') || !$('#send_eth')[0].checkValidity()) + return; + + + loading_button($(this)); + + var username; + + if ($('#username').select2('data')[0] && $('#username').select2('data')[0].text) { + username = $('#username').select2('data')[0].text; + } else { + username = undefined; + } + + // Step 2 + // get form data + var email = $('#email').val(); + var github_url = $('#issueURL').val(); + var from_name = $('#fromName').val(); + // should username be to_username for clarity? + // var username = $('#username').select2('data')[0].text || $('#username').select2('data')[0]; + var receiverAddress = $('#receiverAddress').val(); + var amountInEth = parseFloat($('#amount').val()); + var comments_priv = $('#comments_priv').val(); + var comments_public = $('#comments_public').val(); + var from_email = $('#fromEmail').val(); + var accept_tos = $('#tos').is(':checked'); + var tokenAddress = $('#token').val(); + var expires = parseInt($('#expires').val()); + // kudosId is the kudos database id that is being cloned + var kudosId = $('#kudosid').data('kudosid'); + // tokenId is the kudos blockchain id that is being cloned + var tokenId = $('#tokenid').data('tokenid'); + + // get kudosPrice from the HTML + kudosPriceInEth = parseFloat($('#kudosPrice').attr('data-ethprice')); + kudosPriceInWei = new web3.BigNumber(kudosPriceInEth * 1.0 * Math.pow(10, 18)); + + var formData = { + email: email, + github_url: github_url, + from_name: from_name, + username: username, + receiverAddress: receiverAddress, + // amountInEth is the kudos price in eth + amountInEth: amountInEth, + comments_priv: comments_priv, + comments_public: comments_public, + from_email: from_email, + accept_tos: accept_tos, + tokenAddress: tokenAddress, + expires: expires, + kudosId: kudosId, + tokenId: tokenId + }; + + // derived info + // var isSendingETH = (tokenAddress == '0x0' || tokenAddress == '0x0000000000000000000000000000000000000000'); + var tokenDetails = tokenAddressToDetails(tokenAddress); + var tokenName = 'ETH'; + + var weiConvert = Math.pow(10, 18); + + // if (!isSendingETH) { + // tokenName = tokenDetails.name; + // } + + // Step 11 (LAST STEP) + // Show the congragulation screen + var success_callback = function(txid) { + + startConfetti(); + var url = 'https://' + etherscanDomain() + '/tx/' + txid; + + $('#loading_trans').html('This transaction has been sent 👌'); + $('#loading_trans').hide(); + $('#send_eth').css('display', 'none'); + $('#send_eth_done').css('display', 'block'); + $('#tokenName').html(tokenName); + $('#new_username').html(username); + $('#trans_link').attr('href', url); + $('#trans_link2').attr('href', url); + unloading_button($(this)); + }; + var failure_callback = function() { + unloading_button($('#send')); + }; + + kudosId = $('#kudosid').data('kudosid'); + tokenId = $('#tokenid').data('tokenid'); + // cloneAndTransferKudos(kudosId, 1, receiverAddress); + // cloneKudos(kudosId, 1); + + console.log(formData); + // Step 3 + // Run sendKudos function + return sendKudos(email, github_url, from_name, username, amountInEth, comments_public, comments_priv, from_email, accept_tos, tokenAddress, expires, kudosId, tokenId, success_callback, failure_callback, false); + + }); + + waitforWeb3(function() { + tokens(document.web3network).forEach(function(ele) { + if (ele && ele.addr) { + var html = ''; + + $('#token').append(html); + } + }); + // jQuery('#token').select2(); + }); + +}); + +// Step 3 +function sendKudos(email, github_url, from_name, username, amountInEth, comments_public, comments_priv, from_email, accept_tos, tokenAddress, expires, kudosId, tokenId, success_callback, failure_callback, is_for_bounty_fulfiller) { + mixpanel.track('Tip Step 2 Click', {}); + if (typeof web3 == 'undefined') { + _alert({ message: gettext('You must have a web3 enabled browser to do this. Please download Metamask.') }, 'warning'); + failure_callback(); + return; + } + // setup + + if (username.indexOf('@') == -1) { + username = '@' + username; + } + var _disableDeveloperTip = true; + var gas_money = parseInt(Math.pow(10, (9 + 5)) * ((defaultGasPrice * 1.001) / Math.pow(10, 9))); + // var isSendingETH = (tokenAddress == '0x0' || tokenAddress == '0x0000000000000000000000000000000000000000'); + var tokenDetails = tokenAddressToDetails(tokenAddress); + var tokenName = 'ETH'; + // var tokenName = window.location.href.split('\=')[1]; + var weiConvert = Math.pow(10, 18); + var creation_time = Math.round((new Date()).getTime() / 1000); + var salt = parseInt((Math.random() * 1000000)); + + var amountInWei = amountInEth * 1.0 * weiConvert; + // validation + // console.log(amountInEth) + // console.log(amountInWei) + var hasEmail = email != ''; + var hasUsername = username != ''; + + // Step 4 + // validation + if (hasEmail && !validateEmail(email)) { + _alert({ message: gettext('To Email is optional, but if you enter an email, you must enter a valid email!') }, 'warning'); + failure_callback(); + return; + } + if (from_email != '' && !validateEmail(from_email)) { + _alert({ message: gettext('From Email is optional, but if you enter an email, you must enter a valid email!') }, 'warning'); + failure_callback(); + return; + } + if (!isNumeric(amountInWei) || amountInWei == 0) { + _alert({ message: gettext('You must enter a number for the amount!') }, 'warning'); + failure_callback(); + return; + } + if (username == '' || username === undefined) { + _alert({ message: gettext('You must enter a username.') }, 'warning'); + failure_callback(); + return; + } + if (!accept_tos) { + _alert({ message: gettext('You must accept the terms.') }, 'warning'); + failure_callback(); + return; + } + // console.log('got to metadata_callback') + + // Step 7 + // Do a POST request to the kudos/send/3 + // This adds the information to the kudos_transfer table + // Then the metamask transaction gets kicked off + // Once the transaction is mined, the txid is added to the database in kudos/send/4 + // function inside of getKudos() + var got_metadata_callback = function(metadata) { + const url = '/kudos/send/3/'; + + metadata['creation_time'] = creation_time; + metadata['salt'] = salt; + metadata['source_url'] = document.location.href; + + fetch(url, { + method: 'POST', + credentials: 'include', + body: JSON.stringify({ + username: username, + email: email, + tokenName: tokenName, + amount: amountInEth, + comments_priv: comments_priv, + comments_public: comments_public, + expires_date: expires, + github_url: github_url, + from_email: from_email, + from_name: from_name, + tokenAddress: tokenAddress, + kudosId: kudosId, + tokenId: tokenId, + network: document.web3network, + from_address: web3.eth.coinbase, + is_for_bounty_fulfiller: is_for_bounty_fulfiller, + metadata: metadata + }) + }).then(function(response) { + // console.log(response) + return response.json(); + }).then(function(json) { + var is_success = json['status'] == 'OK'; + var _class = is_success ? 'info' : 'error'; + + if (!is_success) { + _alert(json['message'], _class); + failure_callback(); + } else { + // Step 8 + // A json object with SUCCESS is received from the back-end + var is_direct_to_recipient = metadata['is_direct']; + var destinationAccount = metadata['address']; + + var post_send_callback = function(errors, txid, kudos_id) { + if (errors) { + _alert({ message: gettext('There was an error.') }, 'warning'); + failure_callback(); + } else { + const url = '/kudos/send/4/'; + + fetch(url, { + method: 'POST', + credentials: 'include', + body: JSON.stringify({ + destinationAccount: destinationAccount, + txid: txid, + kudos_id: kudos_id, + is_direct_to_recipient: is_direct_to_recipient, + creation_time: creation_time, + salt: salt + }) + }).then(function(response) { + return response.json(); + }).then(function(json) { + var is_success = json['status'] == 'OK'; + + if (!is_success) { + _alert(json, _class); + } else { + clear_metadata(); + set_metadata(); + // Step 11 + // LAST STEP + success_callback(txid); + } + }); + } + }; + // end post_send_callback + + // Pull up Kudos contract instance + var kudos_contract = web3.eth.contract(kudos_abi).at(kudos_address()); + + var numClones = 1; + var account = web3.eth.coinbase; + + console.log('destinationAccount:' + destinationAccount); + + var kudosPriceInEth = parseFloat($('#kudosPrice').attr('data-ethprice')) || $('.kudos-search').select2('data')[0].price_finney; + var kudosPriceInWei = new web3.BigNumber(kudosPriceInEth * 1.0 * Math.pow(10, 18)); + + if (is_direct_to_recipient) { + // Step 9 + // Kudos Direct Send (KDS) + console.log('Using Kudos Direct Send (KDS)'); + + + kudos_contract.clone(destinationAccount, tokenId, numClones, {from: account, value: kudosPriceInWei}, function(cloneError, cloneTxid) { + // getLatestId yields the last kudos_id + kudos_contract.getLatestId(function(error, kudos_id) { + post_send_callback(cloneError, cloneTxid, kudos_id); + }); + }); + + // Send Indirectly + } else { + // Step 9 + // Kudos Indirect Send (KIS) + // estimate gas for cloning the kudos + console.log('Using Kudos Indirect Send (KIS)'); + + params = { + tokenId: tokenId, + numClones: numClones, + from: account, + value: kudosPriceInWei.toString() + }; + + kudos_contract.clone.estimateGas(destinationAccount, tokenId, numClones, {from: account, value: kudosPriceInWei}, function(err, kudosGasEstimate) { + if (err) + throw (err); + console.log('kudosGasEstimate: ' + kudosGasEstimate); + // Multiply gas * gas_price_gwei to get gas cost in wei. + kudosGasEstimateInWei = kudosGasEstimate * get_gas_price(); + _alert({ message: gettext('You will now be asked to confirm a transaction to cover the cost of the Kudos and the gas money.') }, 'info'); + money = { + gas_money: gas_money, + kudosGasEstimateInWei: kudosGasEstimateInWei, + kudosPriceInWei: kudosPriceInWei.toNumber() + }; + console.log(money); + web3.eth.sendTransaction({ + to: destinationAccount, + // Add gas_money + gas cost for kudos contract transaction + cost of kudos token (Gitcoin keeps this amount?) + value: gas_money + kudosGasEstimateInWei + kudosPriceInWei.toNumber(), + gasPrice: web3.toHex(get_gas_price()) + }, post_send_callback); + }); + } + } + }); + }; + + // send direct, or not? + const url = '/kudos/address/' + username; + + // Step 5 + // Check if we are sending direct or not + // In the case of no kudos wallets, this will fail, move onto Step 6 + fetch(url, {method: 'GET', credentials: 'include'}).then(function(response) { + return response.json(); + }).then(function(json) { + if (json.addresses.length > 0) { + // pay out directly + got_metadata_callback({ + 'is_direct': true, + 'address': json.addresses[0], + 'creation_time': creation_time, + 'salt': salt + }); + } else { + console.log('waiting for metadata'); + // pay out via secret sharing algo + // Step 6 + wait_for_metadata(got_metadata_callback); + } + }); +} + +// web3.currentProvider.publicConfigStore.on('update', function(e) { +var error; + +window.ethereum.publicConfigStore.on('update', checkNetwork); +function checkNetwork(e) { + if (error) { + return; + } + + var network = e ? e.networkVersion : web3.version.network; + + console.log(web3.currentProvider); + if (network === '4' || network === '1') { + console.log(network); + } else { + error = true; + _alert({ message: gettext('You are not on the right web3 network. Please switch to ') + document.network }, 'error'); + } +} +checkNetwork(); diff --git a/app/assets/v2/js/pages/process_bounty.js b/app/assets/v2/js/pages/process_bounty.js index e1a5e76a781..5be19635bc8 100644 --- a/app/assets/v2/js/pages/process_bounty.js +++ b/app/assets/v2/js/pages/process_bounty.js @@ -109,6 +109,40 @@ window.onload = function() { }; + var attach_and_send_kudos = function(selected_kudos, callback) { + // get form data + + var email = ''; + var github_url = $('#issueURL').val(); + var from_name = document.contxt['github_handle']; + var username = $('#bountyFulfillment option:selected').data('username'); + var amountInEth = selected_kudos.price_finney / 1000.0; + var comments_public = $('.kudos-comment textarea').val(); + var comments_priv = ''; + var from_email = ''; + var accept_tos = true; + var tokenAddress = document.token_address; + var expires = 9999999999; + var kudosId = selected_kudos.id; + var tokenId = selected_kudos.token_id; + var success_callback = function(txid) { + var url = 'https://' + etherscanDomain() + '/tx/' + txid; + var msg = 'The Kudos has been sent 👌 [Etherscan Link]'; + + // send msg to frontend + _alert(msg, 'info'); + callback(); + + }; + var failure_callback = function() { + // do nothing + $.noop(); + }; + + return sendKudos(email, github_url, from_name, username, amountInEth, comments_public, comments_priv, from_email, accept_tos, tokenAddress, expires, kudosId, tokenId, success_callback, failure_callback, true); + + }; + $('#acceptBounty').click(function(e) { try { @@ -214,16 +248,26 @@ window.onload = function() { next(); } }; - var send = function() { + // just sent payout + var send_payout = function() { bounty.acceptFulfillment(bountyId, fulfillmentId, {gasPrice: web3.toHex($('#gasPrice').val() * Math.pow(10, 9))}, final_callback); }; - if ($('#tipPercent').val() > 0) { - attach_and_send_tip(send); + // send both tip and payout + var send_tip_and_payout_callback = function() { + if ($('#tipPercent').val() > 0) { + attach_and_send_tip(send_payout); + } else { + send_payout(); + } + }; + + if ($('.kudos-search').select2('data')[0]) { + attach_and_send_kudos($('.kudos-search').select2('data')[0], send_tip_and_payout_callback); } else { - send(); + send_tip_and_payout_callback(); } - + }; // Get bountyId from the database diff --git a/app/assets/v2/js/popper.min.js b/app/assets/v2/js/popper.min.js new file mode 100644 index 00000000000..79ccbf58b02 --- /dev/null +++ b/app/assets/v2/js/popper.min.js @@ -0,0 +1,5 @@ +/* + Copyright (C) Federico Zivolo 2018 + Distributed under the MIT License (license terms are at http://opensource.org/licenses/MIT). + */(function(e,t){'object'==typeof exports&&'undefined'!=typeof module?module.exports=t():'function'==typeof define&&define.amd?define(t):e.Popper=t()})(this,function(){'use strict';function e(e){return e&&'[object Function]'==={}.toString.call(e)}function t(e,t){if(1!==e.nodeType)return[];var o=getComputedStyle(e,null);return t?o[t]:o}function o(e){return'HTML'===e.nodeName?e:e.parentNode||e.host}function n(e){if(!e)return document.body;switch(e.nodeName){case'HTML':case'BODY':return e.ownerDocument.body;case'#document':return e.body;}var i=t(e),r=i.overflow,p=i.overflowX,s=i.overflowY;return /(auto|scroll|overlay)/.test(r+s+p)?e:n(o(e))}function r(e){return 11===e?re:10===e?pe:re||pe}function p(e){if(!e)return document.documentElement;for(var o=r(10)?document.body:null,n=e.offsetParent;n===o&&e.nextElementSibling;)n=(e=e.nextElementSibling).offsetParent;var i=n&&n.nodeName;return i&&'BODY'!==i&&'HTML'!==i?-1!==['TD','TABLE'].indexOf(n.nodeName)&&'static'===t(n,'position')?p(n):n:e?e.ownerDocument.documentElement:document.documentElement}function s(e){var t=e.nodeName;return'BODY'!==t&&('HTML'===t||p(e.firstElementChild)===e)}function d(e){return null===e.parentNode?e:d(e.parentNode)}function a(e,t){if(!e||!e.nodeType||!t||!t.nodeType)return document.documentElement;var o=e.compareDocumentPosition(t)&Node.DOCUMENT_POSITION_FOLLOWING,n=o?e:t,i=o?t:e,r=document.createRange();r.setStart(n,0),r.setEnd(i,0);var l=r.commonAncestorContainer;if(e!==l&&t!==l||n.contains(i))return s(l)?l:p(l);var f=d(e);return f.host?a(f.host,t):a(e,d(t).host)}function l(e){var t=1=o.clientWidth&&n>=o.clientHeight}),l=0a[e]&&!t.escapeWithReference&&(n=J(f[o],a[e]-('right'===e?f.width:f.height))),ae({},o,n)}};return l.forEach(function(e){var t=-1===['left','top'].indexOf(e)?'secondary':'primary';f=le({},f,m[t](e))}),e.offsets.popper=f,e},priority:['left','right','top','bottom'],padding:5,boundariesElement:'scrollParent'},keepTogether:{order:400,enabled:!0,fn:function(e){var t=e.offsets,o=t.popper,n=t.reference,i=e.placement.split('-')[0],r=Z,p=-1!==['top','bottom'].indexOf(i),s=p?'right':'bottom',d=p?'left':'top',a=p?'width':'height';return o[s]r(n[s])&&(e.offsets.popper[d]=r(n[s])),e}},arrow:{order:500,enabled:!0,fn:function(e,o){var n;if(!q(e.instance.modifiers,'arrow','keepTogether'))return e;var i=o.element;if('string'==typeof i){if(i=e.instance.popper.querySelector(i),!i)return e;}else if(!e.instance.popper.contains(i))return console.warn('WARNING: `arrow.element` must be child of its popper element!'),e;var r=e.placement.split('-')[0],p=e.offsets,s=p.popper,d=p.reference,a=-1!==['left','right'].indexOf(r),l=a?'height':'width',f=a?'Top':'Left',m=f.toLowerCase(),h=a?'left':'top',c=a?'bottom':'right',u=S(i)[l];d[c]-us[c]&&(e.offsets.popper[m]+=d[m]+u-s[c]),e.offsets.popper=g(e.offsets.popper);var b=d[m]+d[l]/2-u/2,y=t(e.instance.popper),w=parseFloat(y['margin'+f],10),E=parseFloat(y['border'+f+'Width'],10),v=b-e.offsets.popper[m]-w-E;return v=$(J(s[l]-u,v),0),e.arrowElement=i,e.offsets.arrow=(n={},ae(n,m,Q(v)),ae(n,h,''),n),e},element:'[x-arrow]'},flip:{order:600,enabled:!0,fn:function(e,t){if(W(e.instance.modifiers,'inner'))return e;if(e.flipped&&e.placement===e.originalPlacement)return e;var o=v(e.instance.popper,e.instance.reference,t.padding,t.boundariesElement,e.positionFixed),n=e.placement.split('-')[0],i=T(n),r=e.placement.split('-')[1]||'',p=[];switch(t.behavior){case he.FLIP:p=[n,i];break;case he.CLOCKWISE:p=z(n);break;case he.COUNTERCLOCKWISE:p=z(n,!0);break;default:p=t.behavior;}return p.forEach(function(s,d){if(n!==s||p.length===d+1)return e;n=e.placement.split('-')[0],i=T(n);var a=e.offsets.popper,l=e.offsets.reference,f=Z,m='left'===n&&f(a.right)>f(l.left)||'right'===n&&f(a.left)f(l.top)||'bottom'===n&&f(a.top)f(o.right),g=f(a.top)f(o.bottom),b='left'===n&&h||'right'===n&&c||'top'===n&&g||'bottom'===n&&u,y=-1!==['top','bottom'].indexOf(n),w=!!t.flipVariations&&(y&&'start'===r&&h||y&&'end'===r&&c||!y&&'start'===r&&g||!y&&'end'===r&&u);(m||b||w)&&(e.flipped=!0,(m||b)&&(n=p[d+1]),w&&(r=G(r)),e.placement=n+(r?'-'+r:''),e.offsets.popper=le({},e.offsets.popper,C(e.instance.popper,e.offsets.reference,e.placement)),e=P(e.instance.modifiers,e,'flip'))}),e},behavior:'flip',padding:5,boundariesElement:'viewport'},inner:{order:700,enabled:!1,fn:function(e){var t=e.placement,o=t.split('-')[0],n=e.offsets,i=n.popper,r=n.reference,p=-1!==['left','right'].indexOf(o),s=-1===['top','left'].indexOf(o);return i[p?'left':'top']=r[o]-(s?i[p?'width':'height']:0),e.placement=T(t),e.offsets.popper=g(i),e}},hide:{order:800,enabled:!0,fn:function(e){if(!q(e.instance.modifiers,'hide','preventOverflow'))return e;var t=e.offsets.reference,o=D(e.instance.modifiers,function(e){return'preventOverflow'===e.name}).boundaries;if(t.bottomo.right||t.top>o.bottom||t.right + * Value: + * +*/ + +(function() { + this.createRanger = function(slider, id) { + var output = document.getElementById(id); + + output.innerHTML = slider.value; + slider.oninput = function() { + output.innerHTML = this.value; + }; + + }; + + this.rangeslider = function() { + var elem = document.querySelectorAll('[data-rangeslider]'); + + for (var i = 0; i < elem.length; ++i) { + if (elem[i].dataset.rangeslider) { + createRanger (elem[i], elem[i].dataset.rangeslider); + } + } + }; +}()); + +var rangeslider = new rangeslider(); diff --git a/app/assets/v2/js/truncate-hash.js b/app/assets/v2/js/truncate-hash.js index ca16952827e..9d5d8adeb0c 100644 --- a/app/assets/v2/js/truncate-hash.js +++ b/app/assets/v2/js/truncate-hash.js @@ -71,4 +71,4 @@ new metamaskAddress(); web3.currentProvider.publicConfigStore.on('update', function(e) { new metamaskAddress(); -}); \ No newline at end of file +}); diff --git a/app/assets/v2/js/tweenlite.js b/app/assets/v2/js/tweenlite.js new file mode 100644 index 00000000000..e6afe041d0d --- /dev/null +++ b/app/assets/v2/js/tweenlite.js @@ -0,0 +1,2600 @@ +/* ! + * VERSION: 2.0.2 + * DATE: 2018-08-27 + * UPDATES AND DOCS AT: http://greensock.com + * + * Includes all of the following: TweenLite, TweenMax, TimelineLite, TimelineMax, EasePack, CSSPlugin, RoundPropsPlugin, BezierPlugin, AttrPlugin, DirectionalRotationPlugin + * + * @license Copyright (c) 2008-2018, GreenSock. All rights reserved. + * This work is subject to the terms at http://greensock.com/standard-license or for + * Club GreenSock members, the software agreement that was issued with your membership. + * + * @author: Jack Doyle, jack@greensock.com + * */ +var _gsScope = 'undefined' != typeof module && module.exports && 'undefined' != typeof global ? global : this || window; + +(_gsScope._gsQueue || (_gsScope._gsQueue = [])).push(function() { + 'use strict'; _gsScope._gsDefine('TweenMax', [ 'core.Animation', 'core.SimpleTimeline', 'TweenLite' ], function(a, b, c) { + var d = function(a) { + var b, + c = [], + d = a.length; + + for (b = 0; b !== d; c.push(a[b++])) + ;return c; + }, + e = function(a, b, c) { + var d, + e, + f = a.cycle; + + for (d in f) + e = f[d], a[d] = 'function' == typeof e ? e(c, b[c]) : e[c % e.length]; delete a.cycle; + }, + f = function(a, b, d) { + c.call(this, a, b, d), this._cycle = 0, this._yoyo = this.vars.yoyo === !0 || !!this.vars.yoyoEase, this._repeat = this.vars.repeat || 0, this._repeatDelay = this.vars.repeatDelay || 0, this._repeat && this._uncache(!0), this.render = f.prototype.render; + }, + g = 1e-10, + h = c._internals, + i = h.isSelector, + j = h.isArray, + k = f.prototype = c.to({}, .1, {}), + l = []; + + f.version = '2.0.2', k.constructor = f, k.kill()._gc = !1, f.killTweensOf = f.killDelayedCallsTo = c.killTweensOf, f.getTweensOf = c.getTweensOf, f.lagSmoothing = c.lagSmoothing, f.ticker = c.ticker, f.render = c.render, k.invalidate = function() { + return this._yoyo = this.vars.yoyo === !0 || !!this.vars.yoyoEase, this._repeat = this.vars.repeat || 0, this._repeatDelay = this.vars.repeatDelay || 0, this._yoyoEase = null, this._uncache(!0), c.prototype.invalidate.call(this); + }, k.updateTo = function(a, b) { + var d, + e = this.ratio, + f = this.vars.immediateRender || a.immediateRender; + + b && this._startTime < this._timeline._time && (this._startTime = this._timeline._time, this._uncache(!1), this._gc ? this._enabled(!0, !1) : this._timeline.insert(this, this._startTime - this._delay)); for (d in a) + this.vars[d] = a[d]; if (this._initted || f) + if (b) + this._initted = !1, f && this.render(0, !0, !0); else if (this._gc && this._enabled(!0, !1), this._notifyPluginsOfEnabled && this._firstPT && c._onPluginEvent('_onDisable', this), this._time / this._duration > .998) { + var g = this._totalTime; + + this.render(0, !0, !1), this._initted = !1, this.render(g, !0, !1); + } else if (this._initted = !1, this._init(), this._time > 0 || f) + for (var h, i = 1 / (1 - e), j = this._firstPT; j;) + h = j.s + j.c, j.c *= i, j.s = h - j.c, j = j._next; return this; + }, k.render = function(a, b, d) { + this._initted || 0 === this._duration && this.vars.repeat && this.invalidate(); var e, + f, + i, + j, + k, + l, + m, + n, + o, + p = this._dirty ? this.totalDuration() : this._totalDuration, + q = this._time, + r = this._totalTime, + s = this._cycle, + t = this._duration, + u = this._rawPrevTime; + + if (a >= p - 1e-7 && a >= 0 ? (this._totalTime = p, this._cycle = this._repeat, this._yoyo && 0 !== (1 & this._cycle) ? (this._time = 0, this.ratio = this._ease._calcEnd ? this._ease.getRatio(0) : 0) : (this._time = t, this.ratio = this._ease._calcEnd ? this._ease.getRatio(1) : 1), this._reversed || (e = !0, f = 'onComplete', d = d || this._timeline.autoRemoveChildren), 0 === t && (this._initted || !this.vars.lazy || d) && (this._startTime === this._timeline._duration && (a = 0), (0 > u || 0 >= a && a >= -1e-7 || u === g && 'isPause' !== this.data) && u !== a && (d = !0, u > g && (f = 'onReverseComplete')), this._rawPrevTime = n = !b || a || u === a ? a : g)) : 1e-7 > a ? (this._totalTime = this._time = this._cycle = 0, this.ratio = this._ease._calcEnd ? this._ease.getRatio(0) : 0, (0 !== r || 0 === t && u > 0) && (f = 'onReverseComplete', e = this._reversed), 0 > a && (this._active = !1, 0 === t && (this._initted || !this.vars.lazy || d) && (u >= 0 && (d = !0), this._rawPrevTime = n = !b || a || u === a ? a : g)), this._initted || (d = !0)) : (this._totalTime = this._time = a, 0 !== this._repeat && (j = t + this._repeatDelay, this._cycle = this._totalTime / j >> 0, 0 !== this._cycle && this._cycle === this._totalTime / j && a >= r && this._cycle--, this._time = this._totalTime - this._cycle * j, this._yoyo && 0 !== (1 & this._cycle) && (this._time = t - this._time, o = this._yoyoEase || this.vars.yoyoEase, o && (this._yoyoEase || (o !== !0 || this._initted ? this._yoyoEase = o = o === !0 ? this._ease : o instanceof Ease ? o : Ease.map[o] : (o = this.vars.ease, this._yoyoEase = o = o ? o instanceof Ease ? o : 'function' == typeof o ? new Ease(o, this.vars.easeParams) : Ease.map[o] || c.defaultEase : c.defaultEase)), this.ratio = o ? 1 - o.getRatio((t - this._time) / t) : 0)), this._time > t ? this._time = t : this._time < 0 && (this._time = 0)), this._easeType && !o ? (k = this._time / t, l = this._easeType, m = this._easePower, (1 === l || 3 === l && k >= .5) && (k = 1 - k), 3 === l && (k *= 2), 1 === m ? k *= k : 2 === m ? k *= k * k : 3 === m ? k *= k * k * k : 4 === m && (k *= k * k * k * k), 1 === l ? this.ratio = 1 - k : 2 === l ? this.ratio = k : this._time / t < .5 ? this.ratio = k / 2 : this.ratio = 1 - k / 2) : o || (this.ratio = this._ease.getRatio(this._time / t))), q === this._time && !d && s === this._cycle) + return void (r !== this._totalTime && this._onUpdate && (b || this._callback('onUpdate'))); if (!this._initted) { + if (this._init(), !this._initted || this._gc) + return; if (!d && this._firstPT && (this.vars.lazy !== !1 && this._duration || this.vars.lazy && !this._duration)) + return this._time = q, this._totalTime = r, this._rawPrevTime = u, this._cycle = s, h.lazyTweens.push(this), void (this._lazy = [ a, b ]); !this._time || e || o ? e && this._ease._calcEnd && !o && (this.ratio = this._ease.getRatio(0 === this._time ? 0 : 1)) : this.ratio = this._ease.getRatio(this._time / t); + } for (this._lazy !== !1 && (this._lazy = !1), this._active || !this._paused && this._time !== q && a >= 0 && (this._active = !0), 0 === r && (2 === this._initted && a > 0 && this._init(), this._startAt && (a >= 0 ? this._startAt.render(a, !0, d) : f || (f = '_dummyGS')), this.vars.onStart && (0 !== this._totalTime || 0 === t) && (b || this._callback('onStart'))), i = this._firstPT; i;) + i.f ? i.t[i.p](i.c * this.ratio + i.s) : i.t[i.p] = i.c * this.ratio + i.s, i = i._next; this._onUpdate && (0 > a && this._startAt && this._startTime && this._startAt.render(a, !0, d), b || (this._totalTime !== r || f) && this._callback('onUpdate')), this._cycle !== s && (b || this._gc || this.vars.onRepeat && this._callback('onRepeat')), f && (!this._gc || d) && (0 > a && this._startAt && !this._onUpdate && this._startTime && this._startAt.render(a, !0, d), e && (this._timeline.autoRemoveChildren && this._enabled(!1, !1), this._active = !1), !b && this.vars[f] && this._callback(f), 0 === t && this._rawPrevTime === g && n !== g && (this._rawPrevTime = 0)); + }, f.to = function(a, b, c) { + return new f(a, b, c); + }, f.from = function(a, b, c) { + return c.runBackwards = !0, c.immediateRender = 0 != c.immediateRender, new f(a, b, c); + }, f.fromTo = function(a, b, c, d) { + return d.startAt = c, d.immediateRender = 0 != d.immediateRender && 0 != c.immediateRender, new f(a, b, d); + }, f.staggerTo = f.allTo = function(a, b, g, h, k, m, n) { + h = h || 0; var o, + p, + q, + r, + s = 0, + t = [], + u = function() { + g.onComplete && g.onComplete.apply(g.onCompleteScope || this, arguments), k.apply(n || g.callbackScope || this, m || l); + }, + v = g.cycle, + w = g.startAt && g.startAt.cycle; + + for (j(a) || ('string' == typeof a && (a = c.selector(a) || a), i(a) && (a = d(a))), a = a || [], 0 > h && (a = d(a), a.reverse(), h *= -1), o = a.length - 1, q = 0; o >= q; q++) { + p = {}; for (r in g) + p[r] = g[r]; if (v && (e(p, a, q), null != p.duration && (b = p.duration, delete p.duration)), w) { + w = p.startAt = {}; for (r in g.startAt) + w[r] = g.startAt[r]; e(p.startAt, a, q); + }p.delay = s + (p.delay || 0), q === o && k && (p.onComplete = u), t[q] = new f(a[q], b, p), s += h; + } return t; + }, f.staggerFrom = f.allFrom = function(a, b, c, d, e, g, h) { + return c.runBackwards = !0, c.immediateRender = 0 != c.immediateRender, f.staggerTo(a, b, c, d, e, g, h); + }, f.staggerFromTo = f.allFromTo = function(a, b, c, d, e, g, h, i) { + return d.startAt = c, d.immediateRender = 0 != d.immediateRender && 0 != c.immediateRender, f.staggerTo(a, b, d, e, g, h, i); + }, f.delayedCall = function(a, b, c, d, e) { + return new f(b, 0, {delay: a, onComplete: b, onCompleteParams: c, callbackScope: d, onReverseComplete: b, onReverseCompleteParams: c, immediateRender: !1, useFrames: e, overwrite: 0}); + }, f.set = function(a, b) { + return new f(a, 0, b); + }, f.isTweening = function(a) { + return c.getTweensOf(a, !0).length > 0; + }; var m = function(a, b) { + for (var d = [], e = 0, f = a._first; f;) + f instanceof c ? d[e++] = f : (b && (d[e++] = f), d = d.concat(m(f, b)), e = d.length), f = f._next; return d; + }, + n = f.getAllTweens = function(b) { + return m(a._rootTimeline, b).concat(m(a._rootFramesTimeline, b)); + }; + + f.killAll = function(a, c, d, e) { + null == c && (c = !0), null == d && (d = !0); var f, + g, + h, + i = n(0 != e), + j = i.length, + k = c && d && e; + + for (h = 0; j > h; h++) + g = i[h], (k || g instanceof b || (f = g.target === g.vars.onComplete) && d || c && !f) && (a ? g.totalTime(g._reversed ? 0 : g.totalDuration()) : g._enabled(!1, !1)); + }, f.killChildTweensOf = function(a, b) { + if (null != a) { + var e, + g, + k, + l, + m, + n = h.tweenLookup; + + if ('string' == typeof a && (a = c.selector(a) || a), i(a) && (a = d(a)), j(a)) + for (l = a.length; --l > -1;) + f.killChildTweensOf(a[l], b); else { + e = []; for (k in n) + for (g = n[k].target.parentNode; g;) + g === a && (e = e.concat(n[k].tweens)), g = g.parentNode; for (m = e.length, l = 0; m > l; l++) + b && e[l].totalTime(e[l].totalDuration()), e[l]._enabled(!1, !1); + } + } + }; var o = function(a, c, d, e) { + c = c !== !1, d = d !== !1, e = e !== !1; for (var f, g, h = n(e), i = c && d && e, j = h.length; --j > -1;) + g = h[j], (i || g instanceof b || (f = g.target === g.vars.onComplete) && d || c && !f) && g.paused(a); + }; + + return f.pauseAll = function(a, b, c) { + o(!0, a, b, c); + }, f.resumeAll = function(a, b, c) { + o(!1, a, b, c); + }, f.globalTimeScale = function(b) { + var d = a._rootTimeline, + e = c.ticker.time; + + return arguments.length ? (b = b || g, d._startTime = e - (e - d._startTime) * d._timeScale / b, d = a._rootFramesTimeline, e = c.ticker.frame, d._startTime = e - (e - d._startTime) * d._timeScale / b, d._timeScale = a._rootTimeline._timeScale = b, b) : d._timeScale; + }, k.progress = function(a, b) { + return arguments.length ? this.totalTime(this.duration() * (this._yoyo && 0 !== (1 & this._cycle) ? 1 - a : a) + this._cycle * (this._duration + this._repeatDelay), b) : this._time / this.duration(); + }, k.totalProgress = function(a, b) { + return arguments.length ? this.totalTime(this.totalDuration() * a, b) : this._totalTime / this.totalDuration(); + }, k.time = function(a, b) { + return arguments.length ? (this._dirty && this.totalDuration(), a > this._duration && (a = this._duration), this._yoyo && 0 !== (1 & this._cycle) ? a = this._duration - a + this._cycle * (this._duration + this._repeatDelay) : 0 !== this._repeat && (a += this._cycle * (this._duration + this._repeatDelay)), this.totalTime(a, b)) : this._time; + }, k.duration = function(b) { + return arguments.length ? a.prototype.duration.call(this, b) : this._duration; + }, k.totalDuration = function(a) { + return arguments.length ? -1 === this._repeat ? this : this.duration((a - this._repeat * this._repeatDelay) / (this._repeat + 1)) : (this._dirty && (this._totalDuration = -1 === this._repeat ? 999999999999 : this._duration * (this._repeat + 1) + this._repeatDelay * this._repeat, this._dirty = !1), this._totalDuration); + }, k.repeat = function(a) { + return arguments.length ? (this._repeat = a, this._uncache(!0)) : this._repeat; + }, k.repeatDelay = function(a) { + return arguments.length ? (this._repeatDelay = a, this._uncache(!0)) : this._repeatDelay; + }, k.yoyo = function(a) { + return arguments.length ? (this._yoyo = a, this) : this._yoyo; + }, f; + }, !0), _gsScope._gsDefine('TimelineLite', [ 'core.Animation', 'core.SimpleTimeline', 'TweenLite' ], function(a, b, c) { + var d = function(a) { + b.call(this, a), this._labels = {}, this.autoRemoveChildren = this.vars.autoRemoveChildren === !0, this.smoothChildTiming = this.vars.smoothChildTiming === !0, this._sortChildren = !0, this._onUpdate = this.vars.onUpdate; var c, + d, + e = this.vars; + + for (d in e) + c = e[d], i(c) && -1 !== c.join('').indexOf('{self}') && (e[d] = this._swapSelfInParams(c)); i(e.tweens) && this.add(e.tweens, 0, e.align, e.stagger); + }, + e = 1e-10, + f = c._internals, + g = d._internals = {}, + h = f.isSelector, + i = f.isArray, + j = f.lazyTweens, + k = f.lazyRender, + l = _gsScope._gsDefine.globals, + m = function(a) { + var b, + c = {}; + + for (b in a) + c[b] = a[b]; return c; + }, + n = function(a, b, c) { + var d, + e, + f = a.cycle; + + for (d in f) + e = f[d], a[d] = 'function' == typeof e ? e(c, b[c]) : e[c % e.length]; delete a.cycle; + }, + o = g.pauseCallback = function() {}, + p = function(a) { + var b, + c = [], + d = a.length; + + for (b = 0; b !== d; c.push(a[b++])) + ;return c; + }, + q = d.prototype = new b; + + return d.version = '2.0.2', q.constructor = d, q.kill()._gc = q._forcingPlayhead = q._hasPause = !1, q.to = function(a, b, d, e) { + var f = d.repeat && l.TweenMax || c; + + return b ? this.add(new f(a, b, d), e) : this.set(a, d, e); + }, q.from = function(a, b, d, e) { + return this.add((d.repeat && l.TweenMax || c).from(a, b, d), e); + }, q.fromTo = function(a, b, d, e, f) { + var g = e.repeat && l.TweenMax || c; + + return b ? this.add(g.fromTo(a, b, d, e), f) : this.set(a, e, f); + }, q.staggerTo = function(a, b, e, f, g, i, j, k) { + var l, + o, + q = new d({onComplete: i, onCompleteParams: j, callbackScope: k, smoothChildTiming: this.smoothChildTiming}), + r = e.cycle; + + for ('string' == typeof a && (a = c.selector(a) || a), a = a || [], h(a) && (a = p(a)), f = f || 0, 0 > f && (a = p(a), a.reverse(), f *= -1), o = 0; o < a.length; o++) + l = m(e), l.startAt && (l.startAt = m(l.startAt), l.startAt.cycle && n(l.startAt, a, o)), r && (n(l, a, o), null != l.duration && (b = l.duration, delete l.duration)), q.to(a[o], b, l, o * f); return this.add(q, g); + }, q.staggerFrom = function(a, b, c, d, e, f, g, h) { + return c.immediateRender = 0 != c.immediateRender, c.runBackwards = !0, this.staggerTo(a, b, c, d, e, f, g, h); + }, q.staggerFromTo = function(a, b, c, d, e, f, g, h, i) { + return d.startAt = c, d.immediateRender = 0 != d.immediateRender && 0 != c.immediateRender, this.staggerTo(a, b, d, e, f, g, h, i); + }, q.call = function(a, b, d, e) { + return this.add(c.delayedCall(0, a, b, d), e); + }, q.set = function(a, b, d) { + return d = this._parseTimeOrLabel(d, 0, !0), null == b.immediateRender && (b.immediateRender = d === this._time && !this._paused), this.add(new c(a, 0, b), d); + }, d.exportRoot = function(a, b) { + a = a || {}, null == a.smoothChildTiming && (a.smoothChildTiming = !0); var e, + f, + g, + h, + i = new d(a), + j = i._timeline; + + for (null == b && (b = !0), j._remove(i, !0), i._startTime = 0, i._rawPrevTime = i._time = i._totalTime = j._time, g = j._first; g;) + h = g._next, b && g instanceof c && g.target === g.vars.onComplete || (f = g._startTime - g._delay, 0 > f && (e = 1), i.add(g, f)), g = h; return j.add(i, 0), e && i.totalDuration(), i; + }, q.add = function(e, f, g, h) { + var j, + k, + l, + m, + n, + o; + + if ('number' != typeof f && (f = this._parseTimeOrLabel(f, 0, !0, e)), !(e instanceof a)) { + if (e instanceof Array || e && e.push && i(e)) { + for (g = g || 'normal', h = h || 0, j = f, k = e.length, l = 0; k > l; l++) + i(m = e[l]) && (m = new d({tweens: m})), this.add(m, j), 'string' != typeof m && 'function' != typeof m && ('sequence' === g ? j = m._startTime + m.totalDuration() / m._timeScale : 'start' === g && (m._startTime -= m.delay())), j += h; return this._uncache(!0); + } if ('string' == typeof e) + return this.addLabel(e, f); if ('function' != typeof e) + throw 'Cannot add ' + e + ' into the timeline; it is not a tween, timeline, function, or string.'; e = c.delayedCall(0, e); + } if (b.prototype.add.call(this, e, f), e._time && (j = Math.max(0, Math.min(e.totalDuration(), (this.rawTime() - e._startTime) * e._timeScale)), Math.abs(j - e._totalTime) > 1e-5 && e.render(j, !1, !1)), (this._gc || this._time === this._duration) && !this._paused && this._duration < this.duration()) + for (n = this, o = n.rawTime() > e._startTime; n._timeline;) + o && n._timeline.smoothChildTiming ? n.totalTime(n._totalTime, !0) : n._gc && n._enabled(!0, !1), n = n._timeline; return this; + }, q.remove = function(b) { + if (b instanceof a) { + this._remove(b, !1); var c = b._timeline = b.vars.useFrames ? a._rootFramesTimeline : a._rootTimeline; + + return b._startTime = (b._paused ? b._pauseTime : c._time) - (b._reversed ? b.totalDuration() - b._totalTime : b._totalTime) / b._timeScale, this; + } if (b instanceof Array || b && b.push && i(b)) { + for (var d = b.length; --d > -1;) + this.remove(b[d]); return this; + } return 'string' == typeof b ? this.removeLabel(b) : this.kill(null, b); + }, q._remove = function(a, c) { + b.prototype._remove.call(this, a, c); var d = this._last; + + return d ? this._time > this.duration() && (this._time = this._duration, this._totalTime = this._totalDuration) : this._time = this._totalTime = this._duration = this._totalDuration = 0, this; + }, q.append = function(a, b) { + return this.add(a, this._parseTimeOrLabel(null, b, !0, a)); + }, q.insert = q.insertMultiple = function(a, b, c, d) { + return this.add(a, b || 0, c, d); + }, q.appendMultiple = function(a, b, c, d) { + return this.add(a, this._parseTimeOrLabel(null, b, !0, a), c, d); + }, q.addLabel = function(a, b) { + return this._labels[a] = this._parseTimeOrLabel(b), this; + }, q.addPause = function(a, b, d, e) { + var f = c.delayedCall(0, o, d, e || this); + + return f.vars.onComplete = f.vars.onReverseComplete = b, f.data = 'isPause', this._hasPause = !0, this.add(f, a); + }, q.removeLabel = function(a) { + return delete this._labels[a], this; + }, q.getLabelTime = function(a) { + return null != this._labels[a] ? this._labels[a] : -1; + }, q._parseTimeOrLabel = function(b, c, d, e) { + var f, + g; + + if (e instanceof a && e.timeline === this) + this.remove(e); else if (e && (e instanceof Array || e.push && i(e))) + for (g = e.length; --g > -1;) + e[g] instanceof a && e[g].timeline === this && this.remove(e[g]); if (f = 'number' != typeof b || c ? this.duration() > 99999999999 ? this.recent().endTime(!1) : this._duration : 0, 'string' == typeof c) + return this._parseTimeOrLabel(c, d && 'number' == typeof b && null == this._labels[c] ? b - f : 0, d); if (c = c || 0, 'string' != typeof b || !isNaN(b) && null == this._labels[b]) + null == b && (b = f); else { + if (g = b.indexOf('='), -1 === g) + return null == this._labels[b] ? d ? this._labels[b] = f + c : c : this._labels[b] + c; c = parseInt(b.charAt(g - 1) + '1', 10) * Number(b.substr(g + 1)), b = g > 1 ? this._parseTimeOrLabel(b.substr(0, g - 1), 0, d) : f; + } return Number(b) + c; + }, q.seek = function(a, b) { + return this.totalTime('number' == typeof a ? a : this._parseTimeOrLabel(a), b !== !1); + }, q.stop = function() { + return this.paused(!0); + }, q.gotoAndPlay = function(a, b) { + return this.play(a, b); + }, q.gotoAndStop = function(a, b) { + return this.pause(a, b); + }, q.render = function(a, b, c) { + this._gc && this._enabled(!0, !1); var d, + f, + g, + h, + i, + l, + m, + n = this._time, + o = this._dirty ? this.totalDuration() : this._totalDuration, + p = this._startTime, + q = this._timeScale, + r = this._paused; + + if (n !== this._time && (a += this._time - n), a >= o - 1e-7 && a >= 0) + this._totalTime = this._time = o, this._reversed || this._hasPausedChild() || (f = !0, h = 'onComplete', i = !!this._timeline.autoRemoveChildren, 0 === this._duration && (0 >= a && a >= -1e-7 || this._rawPrevTime < 0 || this._rawPrevTime === e) && this._rawPrevTime !== a && this._first && (i = !0, this._rawPrevTime > e && (h = 'onReverseComplete'))), this._rawPrevTime = this._duration || !b || a || this._rawPrevTime === a ? a : e, a = o + 1e-4; else if (1e-7 > a) + if (this._totalTime = this._time = 0, (0 !== n || 0 === this._duration && this._rawPrevTime !== e && (this._rawPrevTime > 0 || 0 > a && this._rawPrevTime >= 0)) && (h = 'onReverseComplete', f = this._reversed), 0 > a) + this._active = !1, this._timeline.autoRemoveChildren && this._reversed ? (i = f = !0, h = 'onReverseComplete') : this._rawPrevTime >= 0 && this._first && (i = !0), this._rawPrevTime = a; else { + if (this._rawPrevTime = this._duration || !b || a || this._rawPrevTime === a ? a : e, 0 === a && f) + for (d = this._first; d && 0 === d._startTime;) + d._duration || (f = !1), d = d._next; a = 0, this._initted || (i = !0); + } else { + if (this._hasPause && !this._forcingPlayhead && !b) { + if (a >= n) + for (d = this._first; d && d._startTime <= a && !l;) + d._duration || 'isPause' !== d.data || d.ratio || 0 === d._startTime && 0 === this._rawPrevTime || (l = d), d = d._next; else + for (d = this._last; d && d._startTime >= a && !l;) + d._duration || 'isPause' === d.data && d._rawPrevTime > 0 && (l = d), d = d._prev; l && (this._time = a = l._startTime, this._totalTime = a + this._cycle * (this._totalDuration + this._repeatDelay)); + } this._totalTime = this._time = this._rawPrevTime = a; + } if (this._time !== n && this._first || c || i || l) { + if (this._initted || (this._initted = !0), this._active || !this._paused && this._time !== n && a > 0 && (this._active = !0), 0 === n && this.vars.onStart && (0 === this._time && this._duration || b || this._callback('onStart')), m = this._time, m >= n) + for (d = this._first; d && (g = d._next, m === this._time && (!this._paused || r));) + (d._active || d._startTime <= m && !d._paused && !d._gc) && (l === d && this.pause(), d._reversed ? d.render((d._dirty ? d.totalDuration() : d._totalDuration) - (a - d._startTime) * d._timeScale, b, c) : d.render((a - d._startTime) * d._timeScale, b, c)), d = g; else + for (d = this._last; d && (g = d._prev, m === this._time && (!this._paused || r));) { + if (d._active || d._startTime <= n && !d._paused && !d._gc) { + if (l === d) { + for (l = d._prev; l && l.endTime() > this._time;) + l.render(l._reversed ? l.totalDuration() - (a - l._startTime) * l._timeScale : (a - l._startTime) * l._timeScale, b, c), l = l._prev; l = null, this.pause(); + }d._reversed ? d.render((d._dirty ? d.totalDuration() : d._totalDuration) - (a - d._startTime) * d._timeScale, b, c) : d.render((a - d._startTime) * d._timeScale, b, c); + }d = g; + } this._onUpdate && (b || (j.length && k(), this._callback('onUpdate'))), h && (this._gc || (p === this._startTime || q !== this._timeScale) && (0 === this._time || o >= this.totalDuration()) && (f && (j.length && k(), this._timeline.autoRemoveChildren && this._enabled(!1, !1), this._active = !1), !b && this.vars[h] && this._callback(h))); + } + }, q._hasPausedChild = function() { + for (var a = this._first; a;) { + if (a._paused || a instanceof d && a._hasPausedChild()) + return !0; a = a._next; + } return !1; + }, q.getChildren = function(a, b, d, e) { + e = e || -9999999999; for (var f = [], g = this._first, h = 0; g;) + g._startTime < e || (g instanceof c ? b !== !1 && (f[h++] = g) : (d !== !1 && (f[h++] = g), a !== !1 && (f = f.concat(g.getChildren(!0, b, d)), h = f.length))), g = g._next; return f; + }, q.getTweensOf = function(a, b) { + var d, + e, + f = this._gc, + g = [], + h = 0; + + for (f && this._enabled(!0, !0), d = c.getTweensOf(a), e = d.length; --e > -1;) + (d[e].timeline === this || b && this._contains(d[e])) && (g[h++] = d[e]); return f && this._enabled(!1, !0), g; + }, q.recent = function() { + return this._recent; + }, q._contains = function(a) { + for (var b = a.timeline; b;) { + if (b === this) + return !0; b = b.timeline; + } return !1; + }, q.shiftChildren = function(a, b, c) { + c = c || 0; for (var d, e = this._first, f = this._labels; e;) + e._startTime >= c && (e._startTime += a), e = e._next; if (b) + for (d in f) + f[d] >= c && (f[d] += a); return this._uncache(!0); + }, q._kill = function(a, b) { + if (!a && !b) + return this._enabled(!1, !1); for (var c = b ? this.getTweensOf(b) : this.getChildren(!0, !0, !1), d = c.length, e = !1; --d > -1;) + c[d]._kill(a, b) && (e = !0); return e; + }, q.clear = function(a) { + var b = this.getChildren(!1, !0, !0), + c = b.length; + + for (this._time = this._totalTime = 0; --c > -1;) + b[c]._enabled(!1, !1); return a !== !1 && (this._labels = {}), this._uncache(!0); + }, q.invalidate = function() { + for (var b = this._first; b;) + b.invalidate(), b = b._next; return a.prototype.invalidate.call(this); + }, q._enabled = function(a, c) { + if (a === this._gc) + for (var d = this._first; d;) + d._enabled(a, !0), d = d._next; return b.prototype._enabled.call(this, a, c); + }, q.totalTime = function(b, c, d) { + this._forcingPlayhead = !0; var e = a.prototype.totalTime.apply(this, arguments); + + return this._forcingPlayhead = !1, e; + }, q.duration = function(a) { + return arguments.length ? (0 !== this.duration() && 0 !== a && this.timeScale(this._duration / a), this) : (this._dirty && this.totalDuration(), this._duration); + }, q.totalDuration = function(a) { + if (!arguments.length) { + if (this._dirty) { + for (var b, c, d = 0, e = this._last, f = 999999999999; e;) + b = e._prev, e._dirty && e.totalDuration(), e._startTime > f && this._sortChildren && !e._paused && !this._calculatingDuration ? (this._calculatingDuration = 1, this.add(e, e._startTime - e._delay), this._calculatingDuration = 0) : f = e._startTime, e._startTime < 0 && !e._paused && (d -= e._startTime, this._timeline.smoothChildTiming && (this._startTime += e._startTime / this._timeScale, this._time -= e._startTime, this._totalTime -= e._startTime, this._rawPrevTime -= e._startTime), this.shiftChildren(-e._startTime, !1, -9999999999), f = 0), c = e._startTime + e._totalDuration / e._timeScale, c > d && (d = c), e = b; this._duration = this._totalDuration = d, this._dirty = !1; + } return this._totalDuration; + } return a && this.totalDuration() ? this.timeScale(this._totalDuration / a) : this; + }, q.paused = function(b) { + if (!b) + for (var c = this._first, d = this._time; c;) + c._startTime === d && 'isPause' === c.data && (c._rawPrevTime = 0), c = c._next; return a.prototype.paused.apply(this, arguments); + }, q.usesFrames = function() { + for (var b = this._timeline; b._timeline;) + b = b._timeline; return b === a._rootFramesTimeline; + }, q.rawTime = function(a) { + return a && (this._paused || this._repeat && this.time() > 0 && this.totalProgress() < 1) ? this._totalTime % (this._duration + this._repeatDelay) : this._paused ? this._totalTime : (this._timeline.rawTime(a) - this._startTime) * this._timeScale; + }, d; + }, !0), _gsScope._gsDefine('TimelineMax', [ 'TimelineLite', 'TweenLite', 'easing.Ease' ], function(a, b, c) { + var d = function(b) { + a.call(this, b), this._repeat = this.vars.repeat || 0, this._repeatDelay = this.vars.repeatDelay || 0, this._cycle = 0, this._yoyo = this.vars.yoyo === !0, this._dirty = !0; + }, + e = 1e-10, + f = b._internals, + g = f.lazyTweens, + h = f.lazyRender, + i = _gsScope._gsDefine.globals, + j = new c(null, null, 1, 0), + k = d.prototype = new a; + + return k.constructor = d, k.kill()._gc = !1, d.version = '2.0.2', k.invalidate = function() { + return this._yoyo = this.vars.yoyo === !0, this._repeat = this.vars.repeat || 0, this._repeatDelay = this.vars.repeatDelay || 0, this._uncache(!0), a.prototype.invalidate.call(this); + }, k.addCallback = function(a, c, d, e) { + return this.add(b.delayedCall(0, a, d, e), c); + }, k.removeCallback = function(a, b) { + if (a) + if (null == b) + this._kill(null, a); else + for (var c = this.getTweensOf(a, !1), d = c.length, e = this._parseTimeOrLabel(b); --d > -1;) + c[d]._startTime === e && c[d]._enabled(!1, !1); return this; + }, k.removePause = function(b) { + return this.removeCallback(a._internals.pauseCallback, b); + }, k.tweenTo = function(a, c) { + c = c || {}; var d, + e, + f, + g = {ease: j, useFrames: this.usesFrames(), immediateRender: !1, lazy: !1}, + h = c.repeat && i.TweenMax || b; + + for (e in c) + g[e] = c[e]; return g.time = this._parseTimeOrLabel(a), d = Math.abs(Number(g.time) - this._time) / this._timeScale || .001, f = new h(this, d, g), g.onStart = function() { + f.target.paused(!0), f.vars.time === f.target.time() || d !== f.duration() || f.isFromTo || f.duration(Math.abs(f.vars.time - f.target.time()) / f.target._timeScale).render(f.time(), !0, !0), c.onStart && c.onStart.apply(c.onStartScope || c.callbackScope || f, c.onStartParams || []); + }, f; + }, k.tweenFromTo = function(a, b, c) { + c = c || {}, a = this._parseTimeOrLabel(a), c.startAt = {onComplete: this.seek, onCompleteParams: [a], callbackScope: this}, c.immediateRender = c.immediateRender !== !1; var d = this.tweenTo(b, c); + + return d.isFromTo = 1, d.duration(Math.abs(d.vars.time - a) / this._timeScale || .001); + }, k.render = function(a, b, c) { + this._gc && this._enabled(!0, !1); var d, + f, + i, + j, + k, + l, + m, + n, + o = this._time, + p = this._dirty ? this.totalDuration() : this._totalDuration, + q = this._duration, + r = this._totalTime, + s = this._startTime, + t = this._timeScale, + u = this._rawPrevTime, + v = this._paused, + w = this._cycle; + + if (o !== this._time && (a += this._time - o), a >= p - 1e-7 && a >= 0) + this._locked || (this._totalTime = p, this._cycle = this._repeat), this._reversed || this._hasPausedChild() || (f = !0, j = 'onComplete', k = !!this._timeline.autoRemoveChildren, 0 === this._duration && (0 >= a && a >= -1e-7 || 0 > u || u === e) && u !== a && this._first && (k = !0, u > e && (j = 'onReverseComplete'))), this._rawPrevTime = this._duration || !b || a || this._rawPrevTime === a ? a : e, this._yoyo && 0 !== (1 & this._cycle) ? this._time = a = 0 : (this._time = q, a = q + 1e-4); else if (1e-7 > a) + if (this._locked || (this._totalTime = this._cycle = 0), this._time = 0, (0 !== o || 0 === q && u !== e && (u > 0 || 0 > a && u >= 0) && !this._locked) && (j = 'onReverseComplete', f = this._reversed), 0 > a) + this._active = !1, this._timeline.autoRemoveChildren && this._reversed ? (k = f = !0, j = 'onReverseComplete') : u >= 0 && this._first && (k = !0), this._rawPrevTime = a; else { + if (this._rawPrevTime = q || !b || a || this._rawPrevTime === a ? a : e, 0 === a && f) + for (d = this._first; d && 0 === d._startTime;) + d._duration || (f = !1), d = d._next; a = 0, this._initted || (k = !0); + } else if (0 === q && 0 > u && (k = !0), this._time = this._rawPrevTime = a, this._locked || (this._totalTime = a, 0 !== this._repeat && (l = q + this._repeatDelay, this._cycle = this._totalTime / l >> 0, 0 !== this._cycle && this._cycle === this._totalTime / l && a >= r && this._cycle--, this._time = this._totalTime - this._cycle * l, this._yoyo && 0 !== (1 & this._cycle) && (this._time = q - this._time), this._time > q ? (this._time = q, a = q + 1e-4) : this._time < 0 ? this._time = a = 0 : a = this._time)), this._hasPause && !this._forcingPlayhead && !b) { + if (a = this._time, a >= o || this._repeat && w !== this._cycle) + for (d = this._first; d && d._startTime <= a && !m;) + d._duration || 'isPause' !== d.data || d.ratio || 0 === d._startTime && 0 === this._rawPrevTime || (m = d), d = d._next; else + for (d = this._last; d && d._startTime >= a && !m;) + d._duration || 'isPause' === d.data && d._rawPrevTime > 0 && (m = d), d = d._prev; m && m._startTime < q && (this._time = a = m._startTime, this._totalTime = a + this._cycle * (this._totalDuration + this._repeatDelay)); + } if (this._cycle !== w && !this._locked) { + var x = this._yoyo && 0 !== (1 & w), + y = x === (this._yoyo && 0 !== (1 & this._cycle)), + z = this._totalTime, + A = this._cycle, + B = this._rawPrevTime, + C = this._time; + + if (this._totalTime = w * q, this._cycle < w ? x = !x : this._totalTime += q, this._time = o, this._rawPrevTime = 0 === q ? u - 1e-4 : u, this._cycle = w, this._locked = !0, o = x ? 0 : q, this.render(o, b, 0 === q), b || this._gc || this.vars.onRepeat && (this._cycle = A, this._locked = !1, this._callback('onRepeat')), o !== this._time) + return; if (y && (this._cycle = w, this._locked = !0, o = x ? q + 1e-4 : -1e-4, this.render(o, !0, !1)), this._locked = !1, this._paused && !v) + return; this._time = C, this._totalTime = z, this._cycle = A, this._rawPrevTime = B; + } if (!(this._time !== o && this._first || c || k || m)) + return void (r !== this._totalTime && this._onUpdate && (b || this._callback('onUpdate'))); if (this._initted || (this._initted = !0), this._active || !this._paused && this._totalTime !== r && a > 0 && (this._active = !0), 0 === r && this.vars.onStart && (0 === this._totalTime && this._totalDuration || b || this._callback('onStart')), n = this._time, n >= o) + for (d = this._first; d && (i = d._next, n === this._time && (!this._paused || v));) + (d._active || d._startTime <= this._time && !d._paused && !d._gc) && (m === d && this.pause(), d._reversed ? d.render((d._dirty ? d.totalDuration() : d._totalDuration) - (a - d._startTime) * d._timeScale, b, c) : d.render((a - d._startTime) * d._timeScale, b, c)), d = i; else + for (d = this._last; d && (i = d._prev, n === this._time && (!this._paused || v));) { + if (d._active || d._startTime <= o && !d._paused && !d._gc) { + if (m === d) { + for (m = d._prev; m && m.endTime() > this._time;) + m.render(m._reversed ? m.totalDuration() - (a - m._startTime) * m._timeScale : (a - m._startTime) * m._timeScale, b, c), m = m._prev; m = null, this.pause(); + }d._reversed ? d.render((d._dirty ? d.totalDuration() : d._totalDuration) - (a - d._startTime) * d._timeScale, b, c) : d.render((a - d._startTime) * d._timeScale, b, c); + }d = i; + } this._onUpdate && (b || (g.length && h(), this._callback('onUpdate'))), j && (this._locked || this._gc || (s === this._startTime || t !== this._timeScale) && (0 === this._time || p >= this.totalDuration()) && (f && (g.length && h(), this._timeline.autoRemoveChildren && this._enabled(!1, !1), this._active = !1), !b && this.vars[j] && this._callback(j))); + }, k.getActive = function(a, b, c) { + null == a && (a = !0), null == b && (b = !0), null == c && (c = !1); var d, + e, + f = [], + g = this.getChildren(a, b, c), + h = 0, + i = g.length; + + for (d = 0; i > d; d++) + e = g[d], e.isActive() && (f[h++] = e); return f; + }, k.getLabelAfter = function(a) { + a || 0 !== a && (a = this._time); var b, + c = this.getLabelsArray(), + d = c.length; + + for (b = 0; d > b; b++) + if (c[b].time > a) + return c[b].name; return null; + }, k.getLabelBefore = function(a) { + null == a && (a = this._time); for (var b = this.getLabelsArray(), c = b.length; --c > -1;) + if (b[c].time < a) + return b[c].name; return null; + }, k.getLabelsArray = function() { + var a, + b = [], + c = 0; + + for (a in this._labels) + b[c++] = {time: this._labels[a], name: a}; return b.sort(function(a, b) { + return a.time - b.time; + }), b; + }, k.invalidate = function() { + return this._locked = !1, a.prototype.invalidate.call(this); + }, k.progress = function(a, b) { + return arguments.length ? this.totalTime(this.duration() * (this._yoyo && 0 !== (1 & this._cycle) ? 1 - a : a) + this._cycle * (this._duration + this._repeatDelay), b) : this._time / this.duration() || 0; + }, k.totalProgress = function(a, b) { + return arguments.length ? this.totalTime(this.totalDuration() * a, b) : this._totalTime / this.totalDuration() || 0; + }, k.totalDuration = function(b) { + return arguments.length ? -1 !== this._repeat && b ? this.timeScale(this.totalDuration() / b) : this : (this._dirty && (a.prototype.totalDuration.call(this), this._totalDuration = -1 === this._repeat ? 999999999999 : this._duration * (this._repeat + 1) + this._repeatDelay * this._repeat), this._totalDuration); + }, k.time = function(a, b) { + return arguments.length ? (this._dirty && this.totalDuration(), a > this._duration && (a = this._duration), this._yoyo && 0 !== (1 & this._cycle) ? a = this._duration - a + this._cycle * (this._duration + this._repeatDelay) : 0 !== this._repeat && (a += this._cycle * (this._duration + this._repeatDelay)), this.totalTime(a, b)) : this._time; + }, k.repeat = function(a) { + return arguments.length ? (this._repeat = a, this._uncache(!0)) : this._repeat; + }, k.repeatDelay = function(a) { + return arguments.length ? (this._repeatDelay = a, this._uncache(!0)) : this._repeatDelay; + }, k.yoyo = function(a) { + return arguments.length ? (this._yoyo = a, this) : this._yoyo; + }, k.currentLabel = function(a) { + return arguments.length ? this.seek(a, !0) : this.getLabelBefore(this._time + 1e-8); + }, d; + }, !0), function() { + var a = 180 / Math.PI, + b = [], + c = [], + d = [], + e = {}, + f = _gsScope._gsDefine.globals, + g = function(a, b, c, d) { + c === d && (c = d - (d - b) / 1e6), a === b && (b = a + (c - a) / 1e6), this.a = a, this.b = b, this.c = c, this.d = d, this.da = d - a, this.ca = c - a, this.ba = b - a; + }, + h = ',x,y,z,left,top,right,bottom,marginTop,marginLeft,marginRight,marginBottom,paddingLeft,paddingTop,paddingRight,paddingBottom,backgroundPosition,backgroundPosition_y,', + i = function(a, b, c, d) { + var e = {a: a}, + f = {}, + g = {}, + h = {c: d}, + i = (a + b) / 2, + j = (b + c) / 2, + k = (c + d) / 2, + l = (i + j) / 2, + m = (j + k) / 2, + n = (m - l) / 8; + + return e.b = i + (a - i) / 4, f.b = l + n, e.c = f.a = (e.b + f.b) / 2, f.c = g.a = (l + m) / 2, g.b = m - n, h.b = k + (d - k) / 4, g.c = h.a = (g.b + h.b) / 2, [ e, f, g, h ]; + }, + j = function(a, e, f, g, h) { + var j, + k, + l, + m, + n, + o, + p, + q, + r, + s, + t, + u, + v, + w = a.length - 1, + x = 0, + y = a[0].a; + + for (j = 0; w > j; j++) + n = a[x], k = n.a, l = n.d, m = a[x + 1].d, h ? (t = b[j], u = c[j], v = (u + t) * e * .25 / (g ? .5 : d[j] || .5), o = l - (l - k) * (g ? .5 * e : 0 !== t ? v / t : 0), p = l + (m - l) * (g ? .5 * e : 0 !== u ? v / u : 0), q = l - (o + ((p - o) * (3 * t / (t + u) + .5) / 4 || 0))) : (o = l - (l - k) * e * .5, p = l + (m - l) * e * .5, q = l - (o + p) / 2), o += q, p += q, n.c = r = o, 0 !== j ? n.b = y : n.b = y = n.a + .6 * (n.c - n.a), n.da = l - k, n.ca = r - k, n.ba = y - k, f ? (s = i(k, y, r, l), a.splice(x, 1, s[0], s[1], s[2], s[3]), x += 4) : x++, y = p; n = a[x], n.b = y, n.c = y + .4 * (n.d - y), n.da = n.d - n.a, n.ca = n.c - n.a, n.ba = y - n.a, f && (s = i(n.a, y, n.c, n.d), a.splice(x, 1, s[0], s[1], s[2], s[3])); + }, + k = function(a, d, e, f) { + var h, + i, + j, + k, + l, + m, + n = []; + + if (f) + for (a = [f].concat(a), i = a.length; --i > -1;) + 'string' == typeof (m = a[i][d]) && '=' === m.charAt(1) && (a[i][d] = f[d] + Number(m.charAt(0) + m.substr(2))); if (h = a.length - 2, 0 > h) + return n[0] = new g(a[0][d], 0, 0, a[0][d]), n; for (i = 0; h > i; i++) + j = a[i][d], k = a[i + 1][d], n[i] = new g(j, 0, 0, k), e && (l = a[i + 2][d], b[i] = (b[i] || 0) + (k - j) * (k - j), c[i] = (c[i] || 0) + (l - k) * (l - k)); return n[i] = new g(a[i][d], 0, 0, a[i + 1][d]), n; + }, + l = function(a, f, g, i, l, m) { + var n, + o, + p, + q, + r, + s, + t, + u, + v = {}, + w = [], + x = m || a[0]; + + l = 'string' == typeof l ? ',' + l + ',' : h, null == f && (f = 1); for (o in a[0]) + w.push(o); if (a.length > 1) { + for (u = a[a.length - 1], t = !0, n = w.length; --n > -1;) + if (o = w[n], Math.abs(x[o] - u[o]) > .05) { + t = !1; break; + }t && (a = a.concat(), m && a.unshift(m), a.push(a[1]), m = a[a.length - 3]); + } for (b.length = c.length = d.length = 0, n = w.length; --n > -1;) + o = w[n], e[o] = -1 !== l.indexOf(',' + o + ','), v[o] = k(a, o, e[o], m); for (n = b.length; --n > -1;) + b[n] = Math.sqrt(b[n]), + c[n] = Math.sqrt(c[n]); if (!i) { + for (n = w.length; --n > -1;) + if (e[o]) + for (p = v[w[n]], s = p.length - 1, q = 0; s > q; q++) + r = p[q + 1].da / c[q] + p[q].da / b[q] || 0, d[q] = (d[q] || 0) + r * r; for (n = d.length; --n > -1;) + d[n] = Math.sqrt(d[n]); + } for (n = w.length, q = g ? 4 : 1; --n > -1;) + o = w[n], p = v[o], j(p, f, g, i, e[o]), t && (p.splice(0, q), p.splice(p.length - q, q)); return v; + }, + m = function(a, b, c) { + b = b || 'soft'; var d, + e, + f, + h, + i, + j, + k, + l, + m, + n, + o, + p = {}, + q = 'cubic' === b ? 3 : 2, + r = 'soft' === b, + s = []; + + if (r && c && (a = [c].concat(a)), null == a || a.length < q + 1) + throw 'invalid Bezier data'; for (m in a[0]) + s.push(m); for (j = s.length; --j > -1;) { + for (m = s[j], p[m] = i = [], n = 0, l = a.length, k = 0; l > k; k++) + d = null == c ? a[k][m] : 'string' == typeof (o = a[k][m]) && '=' === o.charAt(1) ? c[m] + Number(o.charAt(0) + o.substr(2)) : Number(o), r && k > 1 && l - 1 > k && (i[n++] = (d + i[n - 2]) / 2), i[n++] = d; for (l = n - q + 1, n = 0, k = 0; l > k; k += q) + d = i[k], e = i[k + 1], f = i[k + 2], h = 2 === q ? 0 : i[k + 3], i[n++] = o = 3 === q ? new g(d, e, f, h) : new g(d, (2 * e + d) / 3, (2 * e + f) / 3, f); i.length = n; + } return p; + }, + n = function(a, b, c) { + for (var d, e, f, g, h, i, j, k, l, m, n, o = 1 / c, p = a.length; --p > -1;) + for (m = a[p], f = m.a, g = m.d - f, h = m.c - f, i = m.b - f, d = e = 0, k = 1; c >= k; k++) + j = o * k, l = 1 - j, d = e - (e = (j * j * g + 3 * l * (j * h + l * i)) * j), n = p * c + k - 1, b[n] = (b[n] || 0) + d * d; + }, + o = function(a, b) { + b = b >> 0 || 6; var c, + d, + e, + f, + g = [], + h = [], + i = 0, + j = 0, + k = b - 1, + l = [], + m = []; + + for (c in a) + n(a[c], g, b); for (e = g.length, d = 0; e > d; d++) + i += Math.sqrt(g[d]), f = d % b, m[f] = i, f === k && (j += i, f = d / b >> 0, l[f] = m, h[f] = j, i = 0, m = []); return {length: j, lengths: h, segments: l}; + }, + p = _gsScope._gsDefine.plugin({propName: 'bezier', priority: -1, version: '1.3.8', API: 2, global: !0, init: function(a, b, c) { + this._target = a, b instanceof Array && (b = {values: b}), this._func = {}, this._mod = {}, this._props = [], this._timeRes = null == b.timeResolution ? 6 : parseInt(b.timeResolution, 10); var d, + e, + f, + g, + h, + i = b.values || [], + j = {}, + k = i[0], + n = b.autoRotate || c.vars.orientToBezier; + + this._autoRotate = n ? n instanceof Array ? n : [[ 'x', 'y', 'rotation', n === !0 ? 0 : Number(n) || 0 ]] : null; for (d in k) + this._props.push(d); for (f = this._props.length; --f > -1;) + d = this._props[f], this._overwriteProps.push(d), e = this._func[d] = 'function' == typeof a[d], j[d] = e ? a[d.indexOf('set') || 'function' != typeof a['get' + d.substr(3)] ? d : 'get' + d.substr(3)]() : parseFloat(a[d]), h || j[d] !== i[0][d] && (h = j); if (this._beziers = 'cubic' !== b.type && 'quadratic' !== b.type && 'soft' !== b.type ? l(i, isNaN(b.curviness) ? 1 : b.curviness, !1, 'thruBasic' === b.type, b.correlate, h) : m(i, b.type, j), this._segCount = this._beziers[d].length, this._timeRes) { + var p = o(this._beziers, this._timeRes); + + this._length = p.length, this._lengths = p.lengths, this._segments = p.segments, this._l1 = this._li = this._s1 = this._si = 0, this._l2 = this._lengths[0], this._curSeg = this._segments[0], this._s2 = this._curSeg[0], this._prec = 1 / this._curSeg.length; + } if (n = this._autoRotate) + for (this._initialRotations = [], n[0] instanceof Array || (this._autoRotate = n = [n]), f = n.length; --f > -1;) { + for (g = 0; 3 > g; g++) + d = n[f][g], this._func[d] = 'function' == typeof a[d] ? a[d.indexOf('set') || 'function' != typeof a['get' + d.substr(3)] ? d : 'get' + d.substr(3)] : !1; d = n[f][2], this._initialRotations[f] = (this._func[d] ? this._func[d].call(this._target) : this._target[d]) || 0, this._overwriteProps.push(d); + } return this._startRatio = c.vars.runBackwards ? 1 : 0, !0; + }, set: function(b) { + var c, + d, + e, + f, + g, + h, + i, + j, + k, + l, + m = this._segCount, + n = this._func, + o = this._target, + p = b !== this._startRatio; + + if (this._timeRes) { + if (k = this._lengths, l = this._curSeg, b *= this._length, e = this._li, b > this._l2 && m - 1 > e) { + for (j = m - 1; j > e && (this._l2 = k[++e]) <= b;) + ;this._l1 = k[e - 1], this._li = e, this._curSeg = l = this._segments[e], this._s2 = l[this._s1 = this._si = 0]; + } else if (b < this._l1 && e > 0) { + for (;e > 0 && (this._l1 = k[--e]) >= b;) + ;0 === e && b < this._l1 ? this._l1 = 0 : e++, this._l2 = k[e], this._li = e, this._curSeg = l = this._segments[e], this._s1 = l[(this._si = l.length - 1) - 1] || 0, this._s2 = l[this._si]; + } if (c = e, b -= this._l1, e = this._si, b > this._s2 && e < l.length - 1) { + for (j = l.length - 1; j > e && (this._s2 = l[++e]) <= b;) + ;this._s1 = l[e - 1], this._si = e; + } else if (b < this._s1 && e > 0) { + for (;e > 0 && (this._s1 = l[--e]) >= b;) + ;0 === e && b < this._s1 ? this._s1 = 0 : e++, this._s2 = l[e], this._si = e; + }h = (e + (b - this._s1) / (this._s2 - this._s1)) * this._prec || 0; + } else + c = 0 > b ? 0 : b >= 1 ? m - 1 : m * b >> 0, h = (b - c * (1 / m)) * m; for (d = 1 - h, e = this._props.length; --e > -1;) + f = this._props[e], g = this._beziers[f][c], i = (h * h * g.da + 3 * d * (h * g.ca + d * g.ba)) * h + g.a, this._mod[f] && (i = this._mod[f](i, o)), n[f] ? o[f](i) : o[f] = i; if (this._autoRotate) { + var q, + r, + s, + t, + u, + v, + w, + x = this._autoRotate; + + for (e = x.length; --e > -1;) + f = x[e][2], v = x[e][3] || 0, w = x[e][4] === !0 ? 1 : a, g = this._beziers[x[e][0]], q = this._beziers[x[e][1]], g && q && (g = g[c], q = q[c], r = g.a + (g.b - g.a) * h, t = g.b + (g.c - g.b) * h, r += (t - r) * h, t += (g.c + (g.d - g.c) * h - t) * h, s = q.a + (q.b - q.a) * h, u = q.b + (q.c - q.b) * h, s += (u - s) * h, u += (q.c + (q.d - q.c) * h - u) * h, i = p ? Math.atan2(u - s, t - r) * w + v : this._initialRotations[e], this._mod[f] && (i = this._mod[f](i, o)), n[f] ? o[f](i) : o[f] = i); + } + }}), + q = p.prototype; + + p.bezierThrough = l, p.cubicToQuadratic = i, p._autoCSS = !0, p.quadraticToCubic = function(a, b, c) { + return new g(a, (2 * b + a) / 3, (2 * b + c) / 3, c); + }, p._cssRegister = function() { + var a = f.CSSPlugin; + + if (a) { + var b = a._internals, + c = b._parseToProxy, + d = b._setPluginRatio, + e = b.CSSPropTween; + + b._registerComplexSpecialProp('bezier', {parser: function(a, b, f, g, h, i) { + b instanceof Array && (b = {values: b}), i = new p; var j, + k, + l, + m = b.values, + n = m.length - 1, + o = [], + q = {}; + + if (0 > n) + return h; for (j = 0; n >= j; j++) + l = c(a, m[j], g, h, i, n !== j), o[j] = l.end; for (k in b) + q[k] = b[k]; return q.values = o, h = new e(a, 'bezier', 0, 0, l.pt, 2), h.data = l, h.plugin = i, h.setRatio = d, 0 === q.autoRotate && (q.autoRotate = !0), !q.autoRotate || q.autoRotate instanceof Array || (j = q.autoRotate === !0 ? 0 : Number(q.autoRotate), q.autoRotate = null != l.end.left ? [[ 'left', 'top', 'rotation', j, !1 ]] : null != l.end.x ? [[ 'x', 'y', 'rotation', j, !1 ]] : !1), q.autoRotate && (g._transform || g._enableTransforms(!1), l.autoRotate = g._target._gsTransform, l.proxy.rotation = l.autoRotate.rotation || 0, g._overwriteProps.push('rotation')), i._onInitTween(l.proxy, q, g._tween), h; + }}); + } + }, q._mod = function(a) { + for (var b, c = this._overwriteProps, d = c.length; --d > -1;) + b = a[c[d]], b && 'function' == typeof b && (this._mod[c[d]] = b); + }, q._kill = function(a) { + var b, + c, + d = this._props; + + for (b in this._beziers) + if (b in a) + for (delete this._beziers[b], delete this._func[b], c = d.length; --c > -1;) + d[c] === b && d.splice(c, 1); if (d = this._autoRotate) + for (c = d.length; --c > -1;) + a[d[c][2]] && d.splice(c, 1); return this._super._kill.call(this, a); + }; + }(), _gsScope._gsDefine('plugins.CSSPlugin', [ 'plugins.TweenPlugin', 'TweenLite' ], function(a, b) { + var c, + d, + e, + f, + g = function() { + a.call(this, 'css'), this._overwriteProps.length = 0, this.setRatio = g.prototype.setRatio; + }, + h = _gsScope._gsDefine.globals, + i = {}, + j = g.prototype = new a('css'); + + j.constructor = g, g.version = '2.0.2', g.API = 2, g.defaultTransformPerspective = 0, g.defaultSkewType = 'compensated', g.defaultSmoothOrigin = !0, j = 'px', g.suffixMap = {top: j, right: j, bottom: j, left: j, width: j, height: j, fontSize: j, padding: j, margin: j, perspective: j, lineHeight: ''}; var k, + l, + m, + n, + o, + p, + q, + r, + s = /(?:\-|\.|\b)(\d|\.|e\-)+/g, + t = /(?:\d|\-\d|\.\d|\-\.\d|\+=\d|\-=\d|\+=.\d|\-=\.\d)+/g, + u = /(?:\+=|\-=|\-|\b)[\d\-\.]+[a-zA-Z0-9]*(?:%|\b)/gi, + v = /(?![+-]?\d*\.?\d+|[+-]|e[+-]\d+)[^0-9]/g, + w = /(?:\d|\-|\+|=|#|\.)*/g, + x = /opacity *= *([^)]*)/i, + y = /opacity:([^;]*)/i, + z = /alpha\(opacity *=.+?\)/i, + A = /^(rgb|hsl)/, + B = /([A-Z])/g, + C = /-([a-z])/gi, + D = /(^(?:url\(\"|url\())|(?:(\"\))$|\)$)/gi, + E = function(a, b) { + return b.toUpperCase(); + }, + F = /(?:Left|Right|Width)/i, + G = /(M11|M12|M21|M22)=[\d\-\.e]+/gi, + H = /progid\:DXImageTransform\.Microsoft\.Matrix\(.+?\)/i, + I = /,(?=[^\)]*(?:\(|$))/gi, + J = /[\s,\(]/i, + K = Math.PI / 180, + L = 180 / Math.PI, + M = {}, + N = {style: {}}, + O = _gsScope.document || {createElement: function() { + return N; + }}, + P = function(a, b) { + return O.createElementNS ? O.createElementNS(b || 'http://www.w3.org/1999/xhtml', a) : O.createElement(a); + }, + Q = P('div'), + R = P('img'), + S = g._internals = {_specialProps: i}, + T = (_gsScope.navigator || {}).userAgent || '', + U = function() { + var a = T.indexOf('Android'), + b = P('a'); + + return m = -1 !== T.indexOf('Safari') && -1 === T.indexOf('Chrome') && (-1 === a || parseFloat(T.substr(a + 8, 2)) > 3), o = m && parseFloat(T.substr(T.indexOf('Version/') + 8, 2)) < 6, n = -1 !== T.indexOf('Firefox'), (/MSIE ([0-9]{1,}[\.0-9]{0,})/.exec(T) || (/Trident\/.*rv:([0-9]{1,}[\.0-9]{0,})/).exec(T)) && (p = parseFloat(RegExp.$1)), b ? (b.style.cssText = 'top:1px;opacity:.55;', (/^0.55/).test(b.style.opacity)) : !1; + }(), + V = function(a) { + return x.test('string' == typeof a ? a : (a.currentStyle ? a.currentStyle.filter : a.style.filter) || '') ? parseFloat(RegExp.$1) / 100 : 1; + }, + W = function(a) { + _gsScope.console && console.log(a); + }, + X = '', + Y = '', + Z = function(a, b) { + b = b || Q; var c, + d, + e = b.style; + + if (void 0 !== e[a]) + return a; for (a = a.charAt(0).toUpperCase() + a.substr(1), c = [ 'O', 'Moz', 'ms', 'Ms', 'Webkit' ], d = 5; --d > -1 && void 0 === e[c[d] + a];) + ;return d >= 0 ? (Y = 3 === d ? 'ms' : c[d], X = '-' + Y.toLowerCase() + '-', Y + a) : null; + }, + $ = ('undefined' != typeof window ? window : O.defaultView || {getComputedStyle: function() {}}).getComputedStyle, + _ = g.getStyle = function(a, b, c, d, e) { + var f; + + return U || 'opacity' !== b ? (!d && a.style[b] ? f = a.style[b] : (c = c || $(a)) ? f = c[b] || c.getPropertyValue(b) || c.getPropertyValue(b.replace(B, '-$1').toLowerCase()) : a.currentStyle && (f = a.currentStyle[b]), null == e || f && 'none' !== f && 'auto' !== f && 'auto auto' !== f ? f : e) : V(a); + }, + aa = S.convertToPixels = function(a, c, d, e, f) { + if ('px' === e || !e && 'lineHeight' !== c) + return d; if ('auto' === e || !d) + return 0; var h, + i, + j, + k = F.test(c), + l = a, + m = Q.style, + n = 0 > d, + o = 1 === d; + + if (n && (d = -d), o && (d *= 100), 'lineHeight' !== c || e) + if ('%' === e && -1 !== c.indexOf('border')) + h = d / 100 * (k ? a.clientWidth : a.clientHeight); else { + if (m.cssText = 'border:0 solid red;position:' + _(a, 'position') + ';line-height:0;', '%' !== e && l.appendChild && 'v' !== e.charAt(0) && 'rem' !== e) + m[k ? 'borderLeftWidth' : 'borderTopWidth'] = d + e; else { + if (l = a.parentNode || O.body, -1 !== _(l, 'display').indexOf('flex') && (m.position = 'absolute'), i = l._gsCache, j = b.ticker.frame, i && k && i.time === j) + return i.width * d / 100; m[k ? 'width' : 'height'] = d + e; + }l.appendChild(Q), h = parseFloat(Q[k ? 'offsetWidth' : 'offsetHeight']), l.removeChild(Q), k && '%' === e && g.cacheWidths !== !1 && (i = l._gsCache = l._gsCache || {}, i.time = j, i.width = h / d * 100), 0 !== h || f || (h = aa(a, c, d, e, !0)); + } else + i = $(a).lineHeight, a.style.lineHeight = d, h = parseFloat($(a).lineHeight), a.style.lineHeight = i; return o && (h /= 100), n ? -h : h; + }, + ba = S.calculateOffset = function(a, b, c) { + if ('absolute' !== _(a, 'position', c)) + return 0; var d = 'left' === b ? 'Left' : 'Top', + e = _(a, 'margin' + d, c); + + return a['offset' + d] - (aa(a, b, parseFloat(e), e.replace(w, '')) || 0); + }, + ca = function(a, b) { + var c, + d, + e, + f = {}; + + if (b = b || $(a, null)) + if (c = b.length) + for (;--c > -1;) + e = b[c], (-1 === e.indexOf('-transform') || Da === e) && (f[e.replace(C, E)] = b.getPropertyValue(e)); else + for (c in b) + (-1 === c.indexOf('Transform') || Ca === c) && (f[c] = b[c]); else if (b = a.currentStyle || a.style) + for (c in b) + 'string' == typeof c && void 0 === f[c] && (f[c.replace(C, E)] = b[c]); return U || (f.opacity = V(a)), d = Ra(a, b, !1), f.rotation = d.rotation, f.skewX = d.skewX, f.scaleX = d.scaleX, f.scaleY = d.scaleY, f.x = d.x, f.y = d.y, Fa && (f.z = d.z, f.rotationX = d.rotationX, f.rotationY = d.rotationY, f.scaleZ = d.scaleZ), f.filters && delete f.filters, f; + }, + da = function(a, b, c, d, e) { + var f, + g, + h, + i = {}, + j = a.style; + + for (g in c) + 'cssText' !== g && 'length' !== g && isNaN(g) && (b[g] !== (f = c[g]) || e && e[g]) && -1 === g.indexOf('Origin') && ('number' == typeof f || 'string' == typeof f) && (i[g] = 'auto' !== f || 'left' !== g && 'top' !== g ? '' !== f && 'auto' !== f && 'none' !== f || 'string' != typeof b[g] || '' === b[g].replace(v, '') ? f : 0 : ba(a, g), void 0 !== j[g] && (h = new sa(j, g, j[g], h))); if (d) + for (g in d) + 'className' !== g && (i[g] = d[g]); return {difs: i, firstMPT: h}; + }, + ea = {width: [ 'Left', 'Right' ], height: [ 'Top', 'Bottom' ]}, + fa = [ 'marginLeft', 'marginRight', 'marginTop', 'marginBottom' ], + ga = function(a, b, c) { + if ('svg' === (a.nodeName + '').toLowerCase()) + return (c || $(a))[b] || 0; if (a.getCTM && Oa(a)) + return a.getBBox()[b] || 0; var d = parseFloat('width' === b ? a.offsetWidth : a.offsetHeight), + e = ea[b], + f = e.length; + + for (c = c || $(a, null); --f > -1;) + d -= parseFloat(_(a, 'padding' + e[f], c, !0)) || 0, d -= parseFloat(_(a, 'border' + e[f] + 'Width', c, !0)) || 0; return d; + }, + ha = function(a, b) { + if ('contain' === a || 'auto' === a || 'auto auto' === a) + return a + ' '; (null == a || '' === a) && (a = '0 0'); var c, + d = a.split(' '), + e = -1 !== a.indexOf('left') ? '0%' : -1 !== a.indexOf('right') ? '100%' : d[0], + f = -1 !== a.indexOf('top') ? '0%' : -1 !== a.indexOf('bottom') ? '100%' : d[1]; + + if (d.length > 3 && !b) { + for (d = a.split(', ').join(',').split(','), a = [], c = 0; c < d.length; c++) + a.push(ha(d[c])); return a.join(','); + } return null == f ? f = 'center' === e ? '50%' : '0' : 'center' === f && (f = '50%'), ('center' === e || isNaN(parseFloat(e)) && -1 === (e + '').indexOf('=')) && (e = '50%'), a = e + ' ' + f + (d.length > 2 ? ' ' + d[2] : ''), b && (b.oxp = -1 !== e.indexOf('%'), b.oyp = -1 !== f.indexOf('%'), b.oxr = '=' === e.charAt(1), b.oyr = '=' === f.charAt(1), b.ox = parseFloat(e.replace(v, '')), b.oy = parseFloat(f.replace(v, '')), b.v = a), b || a; + }, + ia = function(a, b) { + return 'function' == typeof a && (a = a(r, q)), 'string' == typeof a && '=' === a.charAt(1) ? parseInt(a.charAt(0) + '1', 10) * parseFloat(a.substr(2)) : parseFloat(a) - parseFloat(b) || 0; + }, + ja = function(a, b) { + 'function' == typeof a && (a = a(r, q)); var c = 'string' == typeof a && '=' === a.charAt(1); + + return 'string' == typeof a && 'v' === a.charAt(a.length - 2) && (a = (c ? a.substr(0, 2) : 0) + window['inner' + ('vh' === a.substr(-2) ? 'Height' : 'Width')] * (parseFloat(c ? a.substr(2) : a) / 100)), null == a ? b : c ? parseInt(a.charAt(0) + '1', 10) * parseFloat(a.substr(2)) + b : parseFloat(a) || 0; + }, + ka = function(a, b, c, d) { + var e, + f, + g, + h, + i, + j = 1e-6; + + return 'function' == typeof a && (a = a(r, q)), null == a ? h = b : 'number' == typeof a ? h = a : (e = 360, f = a.split('_'), i = '=' === a.charAt(1), g = (i ? parseInt(a.charAt(0) + '1', 10) * parseFloat(f[0].substr(2)) : parseFloat(f[0])) * (-1 === a.indexOf('rad') ? 1 : L) - (i ? 0 : b), f.length && (d && (d[c] = b + g), -1 !== a.indexOf('short') && (g %= e, g !== g % (e / 2) && (g = 0 > g ? g + e : g - e)), -1 !== a.indexOf('_cw') && 0 > g ? g = (g + 9999999999 * e) % e - (g / e | 0) * e : -1 !== a.indexOf('ccw') && g > 0 && (g = (g - 9999999999 * e) % e - (g / e | 0) * e)), h = b + g), j > h && h > -j && (h = 0), h; + }, + la = {aqua: [ 0, 255, 255 ], lime: [ 0, 255, 0 ], silver: [ 192, 192, 192 ], black: [ 0, 0, 0 ], maroon: [ 128, 0, 0 ], teal: [ 0, 128, 128 ], blue: [ 0, 0, 255 ], navy: [ 0, 0, 128 ], white: [ 255, 255, 255 ], fuchsia: [ 255, 0, 255 ], olive: [ 128, 128, 0 ], yellow: [ 255, 255, 0 ], orange: [ 255, 165, 0 ], gray: [ 128, 128, 128 ], purple: [ 128, 0, 128 ], green: [ 0, 128, 0 ], red: [ 255, 0, 0 ], pink: [ 255, 192, 203 ], cyan: [ 0, 255, 255 ], transparent: [ 255, 255, 255, 0 ]}, + ma = function(a, b, c) { + return a = 0 > a ? a + 1 : a > 1 ? a - 1 : a, 255 * (1 > 6 * a ? b + (c - b) * a * 6 : .5 > a ? c : 2 > 3 * a ? b + (c - b) * (2 / 3 - a) * 6 : b) + .5 | 0; + }, + na = g.parseColor = function(a, b) { + var c, + d, + e, + f, + g, + h, + i, + j, + k, + l, + m; + + if (a) + if ('number' == typeof a) + c = [ a >> 16, a >> 8 & 255, 255 & a ]; else { + if (',' === a.charAt(a.length - 1) && (a = a.substr(0, a.length - 1)), la[a]) + c = la[a]; else if ('#' === a.charAt(0)) + 4 === a.length && (d = a.charAt(1), e = a.charAt(2), f = a.charAt(3), a = '#' + d + d + e + e + f + f), a = parseInt(a.substr(1), 16), c = [ a >> 16, a >> 8 & 255, 255 & a ]; else if ('hsl' === a.substr(0, 3)) + if (c = m = a.match(s), b) { + if (-1 !== a.indexOf('=')) + return a.match(t); + } else + g = Number(c[0]) % 360 / 360, h = Number(c[1]) / 100, i = Number(c[2]) / 100, e = .5 >= i ? i * (h + 1) : i + h - i * h, d = 2 * i - e, c.length > 3 && (c[3] = Number(c[3])), c[0] = ma(g + 1 / 3, d, e), c[1] = ma(g, d, e), c[2] = ma(g - 1 / 3, d, e); else + c = a.match(s) || la.transparent; c[0] = Number(c[0]), c[1] = Number(c[1]), c[2] = Number(c[2]), c.length > 3 && (c[3] = Number(c[3])); + } else + c = la.black; return b && !m && (d = c[0] / 255, e = c[1] / 255, f = c[2] / 255, j = Math.max(d, e, f), k = Math.min(d, e, f), i = (j + k) / 2, j === k ? g = h = 0 : (l = j - k, h = i > .5 ? l / (2 - j - k) : l / (j + k), g = j === d ? (e - f) / l + (f > e ? 6 : 0) : j === e ? (f - d) / l + 2 : (d - e) / l + 4, g *= 60), c[0] = g + .5 | 0, c[1] = 100 * h + .5 | 0, c[2] = 100 * i + .5 | 0), c; + }, + oa = function(a, b) { + var c, + d, + e, + f = a.match(pa) || [], + g = 0, + h = ''; + + if (!f.length) + return a; for (c = 0; c < f.length; c++) + d = f[c], e = a.substr(g, a.indexOf(d, g) - g), g += e.length + d.length, d = na(d, b), 3 === d.length && d.push(1), h += e + (b ? 'hsla(' + d[0] + ',' + d[1] + '%,' + d[2] + '%,' + d[3] : 'rgba(' + d.join(',')) + ')'; return h + a.substr(g); + }, + pa = '(?:\\b(?:(?:rgb|rgba|hsl|hsla)\\(.+?\\))|\\B#(?:[0-9a-f]{3}){1,2}\\b'; + + for (j in la) + pa += '|' + j + '\\b'; pa = new RegExp(pa + ')', 'gi'), g.colorStringFilter = function(a) { + var b, + c = a[0] + ' ' + a[1]; + + pa.test(c) && (b = -1 !== c.indexOf('hsl(') || -1 !== c.indexOf('hsla('), a[0] = oa(a[0], b), a[1] = oa(a[1], b)), pa.lastIndex = 0; + }, b.defaultStringFilter || (b.defaultStringFilter = g.colorStringFilter); var qa = function(a, b, c, d) { + if (null == a) + return function(a) { + return a; + }; var e, + f = b ? (a.match(pa) || [''])[0] : '', + g = a.split(f).join('').match(u) || [], + h = a.substr(0, a.indexOf(g[0])), + i = ')' === a.charAt(a.length - 1) ? ')' : '', + j = -1 !== a.indexOf(' ') ? ' ' : ',', + k = g.length, + l = k > 0 ? g[0].replace(s, '') : ''; + + return k ? e = b ? function(a) { + var b, + m, + n, + o; + + if ('number' == typeof a) + a += l; else if (d && I.test(a)) { + for (o = a.replace(I, '|').split('|'), n = 0; n < o.length; n++) + o[n] = e(o[n]); return o.join(','); + } if (b = (a.match(pa) || [f])[0], m = a.split(b).join('').match(u) || [], n = m.length, k > n--) + for (;++n < k;) + m[n] = c ? m[(n - 1) / 2 | 0] : g[n]; return h + m.join(j) + j + b + i + (-1 !== a.indexOf('inset') ? ' inset' : ''); + } : function(a) { + var b, + f, + m; + + if ('number' == typeof a) + a += l; else if (d && I.test(a)) { + for (f = a.replace(I, '|').split('|'), m = 0; m < f.length; m++) + f[m] = e(f[m]); return f.join(','); + } if (b = a.match(u) || [], m = b.length, k > m--) + for (;++m < k;) + b[m] = c ? b[(m - 1) / 2 | 0] : g[m]; return h + b.join(j) + i; + } : function(a) { + return a; + }; + }, + ra = function(a) { + return a = a.split(','), function(b, c, d, e, f, g, h) { + var i, + j = (c + '').split(' '); + + for (h = {}, i = 0; 4 > i; i++) + h[a[i]] = j[i] = j[i] || j[(i - 1) / 2 >> 0]; return e.parse(b, h, f, g); + }; + }, + sa = (S._setPluginRatio = function(a) { + this.plugin.setRatio(a); for (var b, c, d, e, f, g = this.data, h = g.proxy, i = g.firstMPT, j = 1e-6; i;) + b = h[i.v], i.r ? b = i.r(b) : j > b && b > -j && (b = 0), i.t[i.p] = b, i = i._next; if (g.autoRotate && (g.autoRotate.rotation = g.mod ? g.mod.call(this._tween, h.rotation, this.t, this._tween) : h.rotation), 1 === a || 0 === a) + for (i = g.firstMPT, f = 1 === a ? 'e' : 'b'; i;) { + if (c = i.t, c.type) { + if (1 === c.type) { + for (e = c.xs0 + c.s + c.xs1, d = 1; d < c.l; d++) + e += c['xn' + d] + c['xs' + (d + 1)]; c[f] = e; + } + } else + c[f] = c.s + c.xs0; i = i._next; + } + }, function(a, b, c, d, e) { + this.t = a, this.p = b, this.v = c, this.r = e, d && (d._prev = this, this._next = d); + }), + ta = (S._parseToProxy = function(a, b, c, d, e, f) { + var g, + h, + i, + j, + k, + l = d, + m = {}, + n = {}, + o = c._transform, + p = M; + + for (c._transform = null, M = b, d = k = c.parse(a, b, d, e), M = p, f && (c._transform = o, l && (l._prev = null, l._prev && (l._prev._next = null))); d && d !== l;) { + if (d.type <= 1 && (h = d.p, n[h] = d.s + d.c, m[h] = d.s, f || (j = new sa(d, 's', h, j, d.r), d.c = 0), 1 === d.type)) + for (g = d.l; --g > 0;) + i = 'xn' + g, h = d.p + '_' + i, n[h] = d.data[i], m[h] = d[i], f || (j = new sa(d, i, h, j, d.rxp[i])); d = d._next; + } return {proxy: m, end: n, firstMPT: j, pt: k}; + }, S.CSSPropTween = function(a, b, d, e, g, h, i, j, k, l, m) { + this.t = a, this.p = b, this.s = d, this.c = e, this.n = i || b, a instanceof ta || f.push(this.n), this.r = j ? 'function' == typeof j ? j : Math.round : j, this.type = h || 0, k && (this.pr = k, c = !0), this.b = void 0 === l ? d : l, this.e = void 0 === m ? d + e : m, g && (this._next = g, g._prev = this); + }), + ua = function(a, b, c, d, e, f) { + var g = new ta(a, b, c, d - c, e, -1, f); + + return g.b = c, g.e = g.xs0 = d, g; + }, + va = g.parseComplex = function(a, b, c, d, e, f, h, i, j, l) { + c = c || f || '', 'function' == typeof d && (d = d(r, q)), h = new ta(a, b, 0, 0, h, l ? 2 : 1, null, !1, i, c, d), d += '', e && pa.test(d + c) && (d = [ c, d ], g.colorStringFilter(d), c = d[0], d = d[1]); var m, + n, + o, + p, + u, + v, + w, + x, + y, + z, + A, + B, + C, + D = c.split(', ').join(',').split(' '), + E = d.split(', ').join(',').split(' '), + F = D.length, + G = k !== !1; + + for ((-1 !== d.indexOf(',') || -1 !== c.indexOf(',')) && (-1 !== (d + c).indexOf('rgb') || -1 !== (d + c).indexOf('hsl') ? (D = D.join(' ').replace(I, ', ').split(' '), E = E.join(' ').replace(I, ', ').split(' ')) : (D = D.join(' ').split(',').join(', ').split(' '), E = E.join(' ').split(',').join(', ').split(' ')), F = D.length), F !== E.length && (D = (f || '').split(' '), F = D.length), h.plugin = j, h.setRatio = l, pa.lastIndex = 0, m = 0; F > m; m++) + if (p = D[m], u = E[m] + '', x = parseFloat(p), x || 0 === x) + h.appendXtra('', x, ia(u, x), u.replace(t, ''), G && -1 !== u.indexOf('px') ? Math.round : !1, !0); else if (e && pa.test(p)) + B = u.indexOf(')') + 1, B = ')' + (B ? u.substr(B) : ''), C = -1 !== u.indexOf('hsl') && U, z = u, p = na(p, C), u = na(u, C), y = p.length + u.length > 6, y && !U && 0 === u[3] ? (h['xs' + h.l] += h.l ? ' transparent' : 'transparent', h.e = h.e.split(E[m]).join('transparent')) : (U || (y = !1), C ? h.appendXtra(z.substr(0, z.indexOf('hsl')) + (y ? 'hsla(' : 'hsl('), p[0], ia(u[0], p[0]), ',', !1, !0).appendXtra('', p[1], ia(u[1], p[1]), '%,', !1).appendXtra('', p[2], ia(u[2], p[2]), y ? '%,' : '%' + B, !1) : h.appendXtra(z.substr(0, z.indexOf('rgb')) + (y ? 'rgba(' : 'rgb('), p[0], u[0] - p[0], ',', Math.round, !0).appendXtra('', p[1], u[1] - p[1], ',', Math.round).appendXtra('', p[2], u[2] - p[2], y ? ',' : B, Math.round), y && (p = p.length < 4 ? 1 : p[3], h.appendXtra('', p, (u.length < 4 ? 1 : u[3]) - p, B, !1))), pa.lastIndex = 0; else if (v = p.match(s)) { + if (w = u.match(t), !w || w.length !== v.length) + return h; for (o = 0, n = 0; n < v.length; n++) + A = v[n], z = p.indexOf(A, o), h.appendXtra(p.substr(o, z - o), Number(A), ia(w[n], A), '', G && 'px' === p.substr(z + A.length, 2) ? Math.round : !1, 0 === n), o = z + A.length; h['xs' + h.l] += p.substr(o); + } else + h['xs' + h.l] += h.l || h['xs' + h.l] ? ' ' + u : u; if (-1 !== d.indexOf('=') && h.data) { + for (B = h.xs0 + h.data.s, m = 1; m < h.l; m++) + B += h['xs' + m] + h.data['xn' + m]; h.e = B + h['xs' + m]; + } return h.l || (h.type = -1, h.xs0 = h.e), h.xfirst || h; + }, + wa = 9; + + for (j = ta.prototype, j.l = j.pr = 0; --wa > 0;) + j['xn' + wa] = 0, j['xs' + wa] = ''; j.xs0 = '', j._next = j._prev = j.xfirst = j.data = j.plugin = j.setRatio = j.rxp = null, j.appendXtra = function(a, b, c, d, e, f) { + var g = this, + h = g.l; + + return g['xs' + h] += f && (h || g['xs' + h]) ? ' ' + a : a || '', c || 0 === h || g.plugin ? (g.l++, g.type = g.setRatio ? 2 : 1, g['xs' + g.l] = d || '', h > 0 ? (g.data['xn' + h] = b + c, g.rxp['xn' + h] = e, g['xn' + h] = b, g.plugin || (g.xfirst = new ta(g, 'xn' + h, b, c, g.xfirst || g, 0, g.n, e, g.pr), g.xfirst.xs0 = 0), g) : (g.data = {s: b + c}, g.rxp = {}, g.s = b, g.c = c, g.r = e, g)) : (g['xs' + h] += b + (d || ''), g); + }; var xa = function(a, b) { + b = b || {}, this.p = b.prefix ? Z(a) || a : a, i[a] = i[this.p] = this, this.format = b.formatter || qa(b.defaultValue, b.color, b.collapsible, b.multi), b.parser && (this.parse = b.parser), this.clrs = b.color, this.multi = b.multi, this.keyword = b.keyword, this.dflt = b.defaultValue, this.pr = b.priority || 0; + }, + ya = S._registerComplexSpecialProp = function(a, b, c) { + 'object' != typeof b && (b = {parser: c}); var d, + e, + f = a.split(','), + g = b.defaultValue; + + for (c = c || [g], d = 0; d < f.length; d++) + b.prefix = 0 === d && b.prefix, b.defaultValue = c[d] || g, e = new xa(f[d], b); + }, + za = S._registerPluginProp = function(a) { + if (!i[a]) { + var b = a.charAt(0).toUpperCase() + a.substr(1) + 'Plugin'; + + ya(a, {parser: function(a, c, d, e, f, g, j) { + var k = h.com.greensock.plugins[b]; + + return k ? (k._cssRegister(), i[d].parse(a, c, d, e, f, g, j)) : (W('Error: ' + b + ' js file not loaded.'), f); + }}); + } + }; + + j = xa.prototype, j.parseComplex = function(a, b, c, d, e, f) { + var g, + h, + i, + j, + k, + l, + m = this.keyword; + + if (this.multi && (I.test(c) || I.test(b) ? (h = b.replace(I, '|').split('|'), i = c.replace(I, '|').split('|')) : m && (h = [b], i = [c])), i) { + for (j = i.length > h.length ? i.length : h.length, g = 0; j > g; g++) + b = h[g] = h[g] || this.dflt, c = i[g] = i[g] || this.dflt, m && (k = b.indexOf(m), l = c.indexOf(m), k !== l && (-1 === l ? h[g] = h[g].split(m).join('') : -1 === k && (h[g] += ' ' + m))); b = h.join(', '), c = i.join(', '); + } return va(a, this.p, b, c, this.clrs, this.dflt, d, this.pr, e, f); + }, j.parse = function(a, b, c, d, f, g, h) { + return this.parseComplex(a.style, this.format(_(a, this.p, e, !1, this.dflt)), this.format(b), f, g); + }, g.registerSpecialProp = function(a, b, c) { + ya(a, {parser: function(a, d, e, f, g, h, i) { + var j = new ta(a, e, 0, 0, g, 2, e, !1, c); + + return j.plugin = h, j.setRatio = b(a, d, f._tween, e), j; + }, priority: c}); + }, g.useSVGTransformAttr = !0; var Aa, + Ba = 'scaleX,scaleY,scaleZ,x,y,z,skewX,skewY,rotation,rotationX,rotationY,perspective,xPercent,yPercent'.split(','), + Ca = Z('transform'), + Da = X + 'transform', + Ea = Z('transformOrigin'), + Fa = null !== Z('perspective'), + Ga = S.Transform = function() { + this.perspective = parseFloat(g.defaultTransformPerspective) || 0, this.force3D = g.defaultForce3D !== !1 && Fa ? g.defaultForce3D || 'auto' : !1; + }, + Ha = _gsScope.SVGElement, + Ia = function(a, b, c) { + var d, + e = O.createElementNS('http://www.w3.org/2000/svg', a), + f = /([a-z])([A-Z])/g; + + for (d in c) + e.setAttributeNS(null, d.replace(f, '$1-$2').toLowerCase(), c[d]); return b.appendChild(e), e; + }, + Ja = O.documentElement || {}, + Ka = function() { + var a, + b, + c, + d = p || (/Android/i).test(T) && !_gsScope.chrome; + + return O.createElementNS && !d && (a = Ia('svg', Ja), b = Ia('rect', a, {width: 100, height: 50, x: 100}), c = b.getBoundingClientRect().width, b.style[Ea] = '50% 50%', b.style[Ca] = 'scaleX(0.5)', d = c === b.getBoundingClientRect().width && !(n && Fa), Ja.removeChild(a)), d; + }(), + La = function(a, b, c, d, e, f) { + var h, + i, + j, + k, + l, + m, + n, + o, + p, + q, + r, + s, + t, + u, + v = a._gsTransform, + w = Qa(a, !0); + + v && (t = v.xOrigin, u = v.yOrigin), (!d || (h = d.split(' ')).length < 2) && (n = a.getBBox(), 0 === n.x && 0 === n.y && n.width + n.height === 0 && (n = {x: parseFloat(a.hasAttribute('x') ? a.getAttribute('x') : a.hasAttribute('cx') ? a.getAttribute('cx') : 0) || 0, y: parseFloat(a.hasAttribute('y') ? a.getAttribute('y') : a.hasAttribute('cy') ? a.getAttribute('cy') : 0) || 0, width: 0, height: 0}), b = ha(b).split(' '), h = [ (-1 !== b[0].indexOf('%') ? parseFloat(b[0]) / 100 * n.width : parseFloat(b[0])) + n.x, (-1 !== b[1].indexOf('%') ? parseFloat(b[1]) / 100 * n.height : parseFloat(b[1])) + n.y ]), c.xOrigin = k = parseFloat(h[0]), c.yOrigin = l = parseFloat(h[1]), d && w !== Pa && (m = w[0], n = w[1], o = w[2], p = w[3], q = w[4], r = w[5], s = m * p - n * o, s && (i = k * (p / s) + l * (-o / s) + (o * r - p * q) / s, j = k * (-n / s) + l * (m / s) - (m * r - n * q) / s, k = c.xOrigin = h[0] = i, l = c.yOrigin = h[1] = j)), v && (f && (c.xOffset = v.xOffset, c.yOffset = v.yOffset, v = c), e || e !== !1 && g.defaultSmoothOrigin !== !1 ? (i = k - t, j = l - u, v.xOffset += i * w[0] + j * w[2] - i, v.yOffset += i * w[1] + j * w[3] - j) : v.xOffset = v.yOffset = 0), f || a.setAttribute('data-svg-origin', h.join(' ')); + }, + Ma = function(a) { + var b, + c = P('svg', this.ownerSVGElement && this.ownerSVGElement.getAttribute('xmlns') || 'http://www.w3.org/2000/svg'), + d = this.parentNode, + e = this.nextSibling, + f = this.style.cssText; + + if (Ja.appendChild(c), c.appendChild(this), this.style.display = 'block', a) + try { + b = this.getBBox(), this._originalGetBBox = this.getBBox, this.getBBox = Ma; + } catch (g) {} else + this._originalGetBBox && (b = this._originalGetBBox()); return e ? d.insertBefore(this, e) : d.appendChild(this), Ja.removeChild(c), this.style.cssText = f, b; + }, + Na = function(a) { + try { + return a.getBBox(); + } catch (b) { + return Ma.call(a, !0); + } + }, + Oa = function(a) { + return !(!Ha || !a.getCTM || a.parentNode && !a.ownerSVGElement || !Na(a)); + }, + Pa = [ 1, 0, 0, 1, 0, 0 ], + Qa = function(a, b) { + var c, + d, + e, + f, + g, + h, + i = a._gsTransform || new Ga, + j = 1e5, + k = a.style; + + if (Ca ? d = _(a, Da, null, !0) : a.currentStyle && (d = a.currentStyle.filter.match(G), d = d && 4 === d.length ? [ d[0].substr(4), Number(d[2].substr(4)), Number(d[1].substr(4)), d[3].substr(4), i.x || 0, i.y || 0 ].join(',') : ''), c = !d || 'none' === d || 'matrix(1, 0, 0, 1, 0, 0)' === d, !Ca || !(h = !$(a) || 'none' === $(a).display) && a.parentNode || (h && (f = k.display, k.display = 'block'), a.parentNode || (g = 1, Ja.appendChild(a)), d = _(a, Da, null, !0), c = !d || 'none' === d || 'matrix(1, 0, 0, 1, 0, 0)' === d, f ? k.display = f : h && Va(k, 'display'), g && Ja.removeChild(a)), (i.svg || a.getCTM && Oa(a)) && (c && -1 !== (k[Ca] + '').indexOf('matrix') && (d = k[Ca], c = 0), e = a.getAttribute('transform'), c && e && (e = a.transform.baseVal.consolidate().matrix, d = 'matrix(' + e.a + ',' + e.b + ',' + e.c + ',' + e.d + ',' + e.e + ',' + e.f + ')', c = 0)), c) + return Pa; for (e = (d || '').match(s) || [], wa = e.length; --wa > -1;) + f = Number(e[wa]), e[wa] = (g = f - (f |= 0)) ? (g * j + (0 > g ? -.5 : .5) | 0) / j + f : f; return b && e.length > 6 ? [ e[0], e[1], e[4], e[5], e[12], e[13] ] : e; + }, + Ra = S.getTransform = function(a, c, d, e) { + if (a._gsTransform && d && !e) + return a._gsTransform; var f, + h, + i, + j, + k, + l, + m = d ? a._gsTransform || new Ga : new Ga, + n = m.scaleX < 0, + o = 2e-5, + p = 1e5, + q = Fa ? parseFloat(_(a, Ea, c, !1, '0 0 0').split(' ')[2]) || m.zOrigin || 0 : 0, + r = parseFloat(g.defaultTransformPerspective) || 0; + + if (m.svg = !(!a.getCTM || !Oa(a)), m.svg && (La(a, _(a, Ea, c, !1, '50% 50%') + '', m, a.getAttribute('data-svg-origin')), Aa = g.useSVGTransformAttr || Ka), f = Qa(a), f !== Pa) { + if (16 === f.length) { + var s, + t, + u, + v, + w, + x = f[0], + y = f[1], + z = f[2], + A = f[3], + B = f[4], + C = f[5], + D = f[6], + E = f[7], + F = f[8], + G = f[9], + H = f[10], + I = f[12], + J = f[13], + K = f[14], + M = f[11], + N = Math.atan2(D, H); + + m.zOrigin && (K = -m.zOrigin, I = F * K - f[12], J = G * K - f[13], K = H * K + m.zOrigin - f[14]), m.rotationX = N * L, N && (v = Math.cos(-N), w = Math.sin(-N), s = B * v + F * w, t = C * v + G * w, u = D * v + H * w, F = B * -w + F * v, G = C * -w + G * v, H = D * -w + H * v, M = E * -w + M * v, B = s, C = t, D = u), N = Math.atan2(-z, H), m.rotationY = N * L, N && (v = Math.cos(-N), w = Math.sin(-N), s = x * v - F * w, t = y * v - G * w, u = z * v - H * w, G = y * w + G * v, H = z * w + H * v, M = A * w + M * v, x = s, y = t, z = u), N = Math.atan2(y, x), m.rotation = N * L, N && (v = Math.cos(N), w = Math.sin(N), s = x * v + y * w, t = B * v + C * w, u = F * v + G * w, y = y * v - x * w, C = C * v - B * w, G = G * v - F * w, x = s, B = t, F = u), m.rotationX && Math.abs(m.rotationX) + Math.abs(m.rotation) > 359.9 && (m.rotationX = m.rotation = 0, m.rotationY = 180 - m.rotationY), N = Math.atan2(B, C), m.scaleX = (Math.sqrt(x * x + y * y + z * z) * p + .5 | 0) / p, m.scaleY = (Math.sqrt(C * C + D * D) * p + .5 | 0) / p, m.scaleZ = (Math.sqrt(F * F + G * G + H * H) * p + .5 | 0) / p, x /= m.scaleX, B /= m.scaleY, y /= m.scaleX, C /= m.scaleY, Math.abs(N) > o ? (m.skewX = N * L, B = 0, 'simple' !== m.skewType && (m.scaleY *= 1 / Math.cos(N))) : m.skewX = 0, m.perspective = M ? 1 / (0 > M ? -M : M) : 0, m.x = I, m.y = J, m.z = K, m.svg && (m.x -= m.xOrigin - (m.xOrigin * x - m.yOrigin * B), m.y -= m.yOrigin - (m.yOrigin * y - m.xOrigin * C)); + } else if (!Fa || e || !f.length || m.x !== f[4] || m.y !== f[5] || !m.rotationX && !m.rotationY) { + var O = f.length >= 6, + P = O ? f[0] : 1, + Q = f[1] || 0, + R = f[2] || 0, + S = O ? f[3] : 1; + + m.x = f[4] || 0, m.y = f[5] || 0, i = Math.sqrt(P * P + Q * Q), j = Math.sqrt(S * S + R * R), k = P || Q ? Math.atan2(Q, P) * L : m.rotation || 0, l = R || S ? Math.atan2(R, S) * L + k : m.skewX || 0, m.scaleX = i, m.scaleY = j, m.rotation = k, m.skewX = l, Fa && (m.rotationX = m.rotationY = m.z = 0, m.perspective = r, m.scaleZ = 1), m.svg && (m.x -= m.xOrigin - (m.xOrigin * P + m.yOrigin * R), m.y -= m.yOrigin - (m.xOrigin * Q + m.yOrigin * S)); + }Math.abs(m.skewX) > 90 && Math.abs(m.skewX) < 270 && (n ? (m.scaleX *= -1, m.skewX += m.rotation <= 0 ? 180 : -180, m.rotation += m.rotation <= 0 ? 180 : -180) : (m.scaleY *= -1, m.skewX += m.skewX <= 0 ? 180 : -180)), m.zOrigin = q; for (h in m) + m[h] < o && m[h] > -o && (m[h] = 0); + } return d && (a._gsTransform = m, m.svg && (Aa && a.style[Ca] ? b.delayedCall(.001, function() { + Va(a.style, Ca); + }) : !Aa && a.getAttribute('transform') && b.delayedCall(.001, function() { + a.removeAttribute('transform'); + }))), m; + }, + Sa = function(a) { + var b, + c, + d = this.data, + e = -d.rotation * K, + f = e + d.skewX * K, + g = 1e5, + h = (Math.cos(e) * d.scaleX * g | 0) / g, + i = (Math.sin(e) * d.scaleX * g | 0) / g, + j = (Math.sin(f) * -d.scaleY * g | 0) / g, + k = (Math.cos(f) * d.scaleY * g | 0) / g, + l = this.t.style, + m = this.t.currentStyle; + + if (m) { + c = i, i = -j, j = -c, b = m.filter, l.filter = ''; var n, + o, + q = this.t.offsetWidth, + r = this.t.offsetHeight, + s = 'absolute' !== m.position, + t = 'progid:DXImageTransform.Microsoft.Matrix(M11=' + h + ', M12=' + i + ', M21=' + j + ', M22=' + k, + u = d.x + q * d.xPercent / 100, + v = d.y + r * d.yPercent / 100; + + if (null != d.ox && (n = (d.oxp ? q * d.ox * .01 : d.ox) - q / 2, o = (d.oyp ? r * d.oy * .01 : d.oy) - r / 2, u += n - (n * h + o * i), v += o - (n * j + o * k)), s ? (n = q / 2, o = r / 2, t += ', Dx=' + (n - (n * h + o * i) + u) + ', Dy=' + (o - (n * j + o * k) + v) + ')') : t += ", sizingMethod='auto expand')", -1 !== b.indexOf('DXImageTransform.Microsoft.Matrix(') ? l.filter = b.replace(H, t) : l.filter = t + ' ' + b, (0 === a || 1 === a) && 1 === h && 0 === i && 0 === j && 1 === k && (s && -1 === t.indexOf('Dx=0, Dy=0') || x.test(b) && 100 !== parseFloat(RegExp.$1) || -1 === b.indexOf(b.indexOf('Alpha')) && l.removeAttribute('filter')), !s) { + var y, + z, + A, + B = 8 > p ? 1 : -1; + + for (n = d.ieOffsetX || 0, o = d.ieOffsetY || 0, d.ieOffsetX = Math.round((q - ((0 > h ? -h : h) * q + (0 > i ? -i : i) * r)) / 2 + u), d.ieOffsetY = Math.round((r - ((0 > k ? -k : k) * r + (0 > j ? -j : j) * q)) / 2 + v), wa = 0; 4 > wa; wa++) + z = fa[wa], y = m[z], c = -1 !== y.indexOf('px') ? parseFloat(y) : aa(this.t, z, parseFloat(y), y.replace(w, '')) || 0, A = c !== d[z] ? 2 > wa ? -d.ieOffsetX : -d.ieOffsetY : 2 > wa ? n - d.ieOffsetX : o - d.ieOffsetY, l[z] = (d[z] = Math.round(c - A * (0 === wa || 2 === wa ? 1 : B))) + 'px'; + } + } + }, + Ta = S.set3DTransformRatio = S.setTransformRatio = function(a) { + var b, + c, + d, + e, + f, + g, + h, + i, + j, + k, + l, + m, + o, + p, + q, + r, + s, + t, + u, + v, + w, + x, + y, + z = this.data, + A = this.t.style, + B = z.rotation, + C = z.rotationX, + D = z.rotationY, + E = z.scaleX, + F = z.scaleY, + G = z.scaleZ, + H = z.x, + I = z.y, + J = z.z, + L = z.svg, + M = z.perspective, + N = z.force3D, + O = z.skewY, + P = z.skewX; + + if (O && (P += O, B += O), ((1 === a || 0 === a) && 'auto' === N && (this.tween._totalTime === this.tween._totalDuration || !this.tween._totalTime) || !N) && !J && !M && !D && !C && 1 === G || Aa && L || !Fa) + return void (B || P || L ? (B *= K, x = P * K, y = 1e5, c = Math.cos(B) * E, f = Math.sin(B) * E, d = Math.sin(B - x) * -F, g = Math.cos(B - x) * F, x && 'simple' === z.skewType && (b = Math.tan(x - O * K), b = Math.sqrt(1 + b * b), d *= b, g *= b, O && (b = Math.tan(O * K), b = Math.sqrt(1 + b * b), c *= b, f *= b)), L && (H += z.xOrigin - (z.xOrigin * c + z.yOrigin * d) + z.xOffset, I += z.yOrigin - (z.xOrigin * f + z.yOrigin * g) + z.yOffset, Aa && (z.xPercent || z.yPercent) && (q = this.t.getBBox(), H += .01 * z.xPercent * q.width, I += .01 * z.yPercent * q.height), q = 1e-6, q > H && H > -q && (H = 0), q > I && I > -q && (I = 0)), u = (c * y | 0) / y + ',' + (f * y | 0) / y + ',' + (d * y | 0) / y + ',' + (g * y | 0) / y + ',' + H + ',' + I + ')', L && Aa ? this.t.setAttribute('transform', 'matrix(' + u) : A[Ca] = (z.xPercent || z.yPercent ? 'translate(' + z.xPercent + '%,' + z.yPercent + '%) matrix(' : 'matrix(') + u) : A[Ca] = (z.xPercent || z.yPercent ? 'translate(' + z.xPercent + '%,' + z.yPercent + '%) matrix(' : 'matrix(') + E + ',0,0,' + F + ',' + H + ',' + I + ')'); if (n && (q = 1e-4, q > E && E > -q && (E = G = 2e-5), q > F && F > -q && (F = G = 2e-5), !M || z.z || z.rotationX || z.rotationY || (M = 0)), B || P) + B *= K, r = c = Math.cos(B), s = f = Math.sin(B), P && (B -= P * K, r = Math.cos(B), s = Math.sin(B), 'simple' === z.skewType && (b = Math.tan((P - O) * K), b = Math.sqrt(1 + b * b), r *= b, s *= b, z.skewY && (b = Math.tan(O * K), b = Math.sqrt(1 + b * b), c *= b, f *= b))), d = -s, g = r; else { + if (!(D || C || 1 !== G || M || L)) + return void (A[Ca] = (z.xPercent || z.yPercent ? 'translate(' + z.xPercent + '%,' + z.yPercent + '%) translate3d(' : 'translate3d(') + H + 'px,' + I + 'px,' + J + 'px)' + (1 !== E || 1 !== F ? ' scale(' + E + ',' + F + ')' : '')); c = g = 1, d = f = 0; + }k = 1, e = h = i = j = l = m = 0, o = M ? -1 / M : 0, p = z.zOrigin, q = 1e-6, v = ',', w = '0', B = D * K, B && (r = Math.cos(B), s = Math.sin(B), i = -s, l = o * -s, e = c * s, h = f * s, k = r, o *= r, c *= r, f *= r), B = C * K, B && (r = Math.cos(B), s = Math.sin(B), b = d * r + e * s, t = g * r + h * s, j = k * s, m = o * s, e = d * -s + e * r, h = g * -s + h * r, k *= r, o *= r, d = b, g = t), 1 !== G && (e *= G, h *= G, k *= G, o *= G), 1 !== F && (d *= F, g *= F, j *= F, m *= F), 1 !== E && (c *= E, f *= E, i *= E, l *= E), (p || L) && (p && (H += e * -p, I += h * -p, J += k * -p + p), L && (H += z.xOrigin - (z.xOrigin * c + z.yOrigin * d) + z.xOffset, I += z.yOrigin - (z.xOrigin * f + z.yOrigin * g) + z.yOffset), q > H && H > -q && (H = w), q > I && I > -q && (I = w), q > J && J > -q && (J = 0)), u = z.xPercent || z.yPercent ? 'translate(' + z.xPercent + '%,' + z.yPercent + '%) matrix3d(' : 'matrix3d(', u += (q > c && c > -q ? w : c) + v + (q > f && f > -q ? w : f) + v + (q > i && i > -q ? w : i), u += v + (q > l && l > -q ? w : l) + v + (q > d && d > -q ? w : d) + v + (q > g && g > -q ? w : g), C || D || 1 !== G ? (u += v + (q > j && j > -q ? w : j) + v + (q > m && m > -q ? w : m) + v + (q > e && e > -q ? w : e), u += v + (q > h && h > -q ? w : h) + v + (q > k && k > -q ? w : k) + v + (q > o && o > -q ? w : o) + v) : u += ',0,0,0,0,1,0,', u += H + v + I + v + J + v + (M ? 1 + -J / M : 1) + ')', A[Ca] = u; + }; + + j = Ga.prototype, j.x = j.y = j.z = j.skewX = j.skewY = j.rotation = j.rotationX = j.rotationY = j.zOrigin = j.xPercent = j.yPercent = j.xOffset = j.yOffset = 0, j.scaleX = j.scaleY = j.scaleZ = 1, ya('transform,scale,scaleX,scaleY,scaleZ,x,y,z,rotation,rotationX,rotationY,rotationZ,skewX,skewY,shortRotation,shortRotationX,shortRotationY,shortRotationZ,transformOrigin,svgOrigin,transformPerspective,directionalRotation,parseTransform,force3D,skewType,xPercent,yPercent,smoothOrigin', {parser: function(a, b, c, d, f, h, i) { + if (d._lastParsedTransform === i) + return f; d._lastParsedTransform = i; var j, + k = i.scale && 'function' == typeof i.scale ? i.scale : 0; + + 'function' == typeof i[c] && (j = i[c], i[c] = b), k && (i.scale = k(r, a)); var l, + m, + n, + o, + p, + s, + t, + u, + v, + w = a._gsTransform, + x = a.style, + y = 1e-6, + z = Ba.length, + A = i, + B = {}, + C = 'transformOrigin', + D = Ra(a, e, !0, A.parseTransform), + E = A.transform && ('function' == typeof A.transform ? A.transform(r, q) : A.transform); + + if (D.skewType = A.skewType || D.skewType || g.defaultSkewType, d._transform = D, 'rotationZ' in A && (A.rotation = A.rotationZ), E && 'string' == typeof E && Ca) + m = Q.style, m[Ca] = E, m.display = 'block', m.position = 'absolute', -1 !== E.indexOf('%') && (m.width = _(a, 'width'), m.height = _(a, 'height')), O.body.appendChild(Q), l = Ra(Q, null, !1), 'simple' === D.skewType && (l.scaleY *= Math.cos(l.skewX * K)), D.svg && (s = D.xOrigin, t = D.yOrigin, l.x -= D.xOffset, l.y -= D.yOffset, (A.transformOrigin || A.svgOrigin) && (E = {}, La(a, ha(A.transformOrigin), E, A.svgOrigin, A.smoothOrigin, !0), s = E.xOrigin, t = E.yOrigin, l.x -= E.xOffset - D.xOffset, l.y -= E.yOffset - D.yOffset), (s || t) && (u = Qa(Q, !0), l.x -= s - (s * u[0] + t * u[2]), l.y -= t - (s * u[1] + t * u[3]))), O.body.removeChild(Q), l.perspective || (l.perspective = D.perspective), null != A.xPercent && (l.xPercent = ja(A.xPercent, D.xPercent)), null != A.yPercent && (l.yPercent = ja(A.yPercent, D.yPercent)); else if ('object' == typeof A) { + if (l = {scaleX: ja(null != A.scaleX ? A.scaleX : A.scale, D.scaleX), scaleY: ja(null != A.scaleY ? A.scaleY : A.scale, D.scaleY), scaleZ: ja(A.scaleZ, D.scaleZ), x: ja(A.x, D.x), y: ja(A.y, D.y), z: ja(A.z, D.z), xPercent: ja(A.xPercent, D.xPercent), yPercent: ja(A.yPercent, D.yPercent), perspective: ja(A.transformPerspective, D.perspective)}, p = A.directionalRotation, null != p) + if ('object' == typeof p) + for (m in p) + A[m] = p[m]; else + A.rotation = p; 'string' == typeof A.x && -1 !== A.x.indexOf('%') && (l.x = 0, l.xPercent = ja(A.x, D.xPercent)), 'string' == typeof A.y && -1 !== A.y.indexOf('%') && (l.y = 0, l.yPercent = ja(A.y, D.yPercent)), l.rotation = ka('rotation' in A ? A.rotation : 'shortRotation' in A ? A.shortRotation + '_short' : D.rotation, D.rotation, 'rotation', B), Fa && (l.rotationX = ka('rotationX' in A ? A.rotationX : 'shortRotationX' in A ? A.shortRotationX + '_short' : D.rotationX || 0, D.rotationX, 'rotationX', B), l.rotationY = ka('rotationY' in A ? A.rotationY : 'shortRotationY' in A ? A.shortRotationY + '_short' : D.rotationY || 0, D.rotationY, 'rotationY', B)), l.skewX = ka(A.skewX, D.skewX), l.skewY = ka(A.skewY, D.skewY); + } for (Fa && null != A.force3D && (D.force3D = A.force3D, o = !0), n = D.force3D || D.z || D.rotationX || D.rotationY || l.z || l.rotationX || l.rotationY || l.perspective, n || null == A.scale || (l.scaleZ = 1); --z > -1;) + v = Ba[z], E = l[v] - D[v], (E > y || -y > E || null != A[v] || null != M[v]) && (o = !0, f = new ta(D, v, D[v], E, f), v in B && (f.e = B[v]), f.xs0 = 0, f.plugin = h, d._overwriteProps.push(f.n)); return E = A.transformOrigin, D.svg && (E || A.svgOrigin) && (s = D.xOffset, t = D.yOffset, La(a, ha(E), l, A.svgOrigin, A.smoothOrigin), f = ua(D, 'xOrigin', (w ? D : l).xOrigin, l.xOrigin, f, C), f = ua(D, 'yOrigin', (w ? D : l).yOrigin, l.yOrigin, f, C), (s !== D.xOffset || t !== D.yOffset) && (f = ua(D, 'xOffset', w ? s : D.xOffset, D.xOffset, f, C), f = ua(D, 'yOffset', w ? t : D.yOffset, D.yOffset, f, C)), E = '0px 0px'), (E || Fa && n && D.zOrigin) && (Ca ? (o = !0, v = Ea, E = (E || _(a, v, e, !1, '50% 50%')) + '', f = new ta(x, v, 0, 0, f, -1, C), f.b = x[v], f.plugin = h, Fa ? (m = D.zOrigin, E = E.split(' '), D.zOrigin = (E.length > 2 && (0 === m || '0px' !== E[2]) ? parseFloat(E[2]) : m) || 0, f.xs0 = f.e = E[0] + ' ' + (E[1] || '50%') + ' 0px', f = new ta(D, 'zOrigin', 0, 0, f, -1, f.n), f.b = m, f.xs0 = f.e = D.zOrigin) : f.xs0 = f.e = E) : ha(E + '', D)), o && (d._transformType = D.svg && Aa || !n && 3 !== this._transformType ? 2 : 3), j && (i[c] = j), k && (i.scale = k), f; + }, prefix: !0}), ya('boxShadow', {defaultValue: '0px 0px 0px 0px #999', prefix: !0, color: !0, multi: !0, keyword: 'inset'}), ya('borderRadius', {defaultValue: '0px', parser: function(a, b, c, f, g, h) { + b = this.format(b); var i, + j, + k, + l, + m, + n, + o, + p, + q, + r, + s, + t, + u, + v, + w, + x, + y = [ 'borderTopLeftRadius', 'borderTopRightRadius', 'borderBottomRightRadius', 'borderBottomLeftRadius' ], + z = a.style; + + for (q = parseFloat(a.offsetWidth), r = parseFloat(a.offsetHeight), i = b.split(' '), j = 0; j < y.length; j++) + this.p.indexOf('border') && (y[j] = Z(y[j])), m = l = _(a, y[j], e, !1, '0px'), -1 !== m.indexOf(' ') && (l = m.split(' '), m = l[0], l = l[1]), n = k = i[j], o = parseFloat(m), t = m.substr((o + '').length), u = '=' === n.charAt(1), u ? (p = parseInt(n.charAt(0) + '1', 10), n = n.substr(2), p *= parseFloat(n), s = n.substr((p + '').length - (0 > p ? 1 : 0)) || '') : (p = parseFloat(n), s = n.substr((p + '').length)), '' === s && (s = d[c] || t), s !== t && (v = aa(a, 'borderLeft', o, t), w = aa(a, 'borderTop', o, t), '%' === s ? (m = v / q * 100 + '%', l = w / r * 100 + '%') : 'em' === s ? (x = aa(a, 'borderLeft', 1, 'em'), m = v / x + 'em', l = w / x + 'em') : (m = v + 'px', l = w + 'px'), u && (n = parseFloat(m) + p + s, k = parseFloat(l) + p + s)), g = va(z, y[j], m + ' ' + l, n + ' ' + k, !1, '0px', g); return g; + }, prefix: !0, formatter: qa('0px 0px 0px 0px', !1, !0)}), ya('borderBottomLeftRadius,borderBottomRightRadius,borderTopLeftRadius,borderTopRightRadius', {defaultValue: '0px', parser: function(a, b, c, d, f, g) { + return va(a.style, c, this.format(_(a, c, e, !1, '0px 0px')), this.format(b), !1, '0px', f); + }, prefix: !0, formatter: qa('0px 0px', !1, !0)}), ya('backgroundPosition', {defaultValue: '0 0', parser: function(a, b, c, d, f, g) { + var h, + i, + j, + k, + l, + m, + n = 'background-position', + o = e || $(a, null), + q = this.format((o ? p ? o.getPropertyValue(n + '-x') + ' ' + o.getPropertyValue(n + '-y') : o.getPropertyValue(n) : a.currentStyle.backgroundPositionX + ' ' + a.currentStyle.backgroundPositionY) || '0 0'), + r = this.format(b); + + if (-1 !== q.indexOf('%') != (-1 !== r.indexOf('%')) && r.split(',').length < 2 && (m = _(a, 'backgroundImage').replace(D, ''), m && 'none' !== m)) { + for (h = q.split(' '), i = r.split(' '), R.setAttribute('src', m), j = 2; --j > -1;) + q = h[j], k = -1 !== q.indexOf('%'), k !== (-1 !== i[j].indexOf('%')) && (l = 0 === j ? a.offsetWidth - R.width : a.offsetHeight - R.height, h[j] = k ? parseFloat(q) / 100 * l + 'px' : parseFloat(q) / l * 100 + '%'); q = h.join(' '); + } return this.parseComplex(a.style, q, r, f, g); + }, formatter: ha}), ya('backgroundSize', {defaultValue: '0 0', formatter: function(a) { + return a += '', 'co' === a.substr(0, 2) ? a : ha(-1 === a.indexOf(' ') ? a + ' ' + a : a); + }}), ya('perspective', {defaultValue: '0px', prefix: !0}), ya('perspectiveOrigin', {defaultValue: '50% 50%', prefix: !0}), ya('transformStyle', {prefix: !0}), ya('backfaceVisibility', {prefix: !0}), ya('userSelect', {prefix: !0}), ya('margin', {parser: ra('marginTop,marginRight,marginBottom,marginLeft')}), ya('padding', {parser: ra('paddingTop,paddingRight,paddingBottom,paddingLeft')}), ya('clip', {defaultValue: 'rect(0px,0px,0px,0px)', parser: function(a, b, c, d, f, g) { + var h, + i, + j; + + return 9 > p ? (i = a.currentStyle, j = 8 > p ? ' ' : ',', h = 'rect(' + i.clipTop + j + i.clipRight + j + i.clipBottom + j + i.clipLeft + ')', b = this.format(b).split(',').join(j)) : (h = this.format(_(a, this.p, e, !1, this.dflt)), b = this.format(b)), this.parseComplex(a.style, h, b, f, g); + }}), ya('textShadow', {defaultValue: '0px 0px 0px #999', color: !0, multi: !0}), ya('autoRound,strictUnits', {parser: function(a, b, c, d, e) { + return e; + }}), ya('border', {defaultValue: '0px solid #000', parser: function(a, b, c, d, f, g) { + var h = _(a, 'borderTopWidth', e, !1, '0px'), + i = this.format(b).split(' '), + j = i[0].replace(w, ''); + + return 'px' !== j && (h = parseFloat(h) / aa(a, 'borderTopWidth', 1, j) + j), this.parseComplex(a.style, this.format(h + ' ' + _(a, 'borderTopStyle', e, !1, 'solid') + ' ' + _(a, 'borderTopColor', e, !1, '#000')), i.join(' '), f, g); + }, color: !0, formatter: function(a) { + var b = a.split(' '); + + return b[0] + ' ' + (b[1] || 'solid') + ' ' + (a.match(pa) || ['#000'])[0]; + }}), ya('borderWidth', {parser: ra('borderTopWidth,borderRightWidth,borderBottomWidth,borderLeftWidth')}), ya('float,cssFloat,styleFloat', {parser: function(a, b, c, d, e, f) { + var g = a.style, + h = 'cssFloat' in g ? 'cssFloat' : 'styleFloat'; + + return new ta(g, h, 0, 0, e, -1, c, !1, 0, g[h], b); + }}); var Ua = function(a) { + var b, + c = this.t, + d = c.filter || _(this.data, 'filter') || '', + e = this.s + this.c * a | 0; + + 100 === e && (-1 === d.indexOf('atrix(') && -1 === d.indexOf('radient(') && -1 === d.indexOf('oader(') ? (c.removeAttribute('filter'), b = !_(this.data, 'filter')) : (c.filter = d.replace(z, ''), b = !0)), b || (this.xn1 && (c.filter = d = d || 'alpha(opacity=' + e + ')'), -1 === d.indexOf('pacity') ? 0 === e && this.xn1 || (c.filter = d + ' alpha(opacity=' + e + ')') : c.filter = d.replace(x, 'opacity=' + e)); + }; + + ya('opacity,alpha,autoAlpha', {defaultValue: '1', parser: function(a, b, c, d, f, g) { + var h = parseFloat(_(a, 'opacity', e, !1, '1')), + i = a.style, + j = 'autoAlpha' === c; + + return 'string' == typeof b && '=' === b.charAt(1) && (b = ('-' === b.charAt(0) ? -1 : 1) * parseFloat(b.substr(2)) + h), j && 1 === h && 'hidden' === _(a, 'visibility', e) && 0 !== b && (h = 0), U ? f = new ta(i, 'opacity', h, b - h, f) : (f = new ta(i, 'opacity', 100 * h, 100 * (b - h), f), f.xn1 = j ? 1 : 0, i.zoom = 1, f.type = 2, f.b = 'alpha(opacity=' + f.s + ')', f.e = 'alpha(opacity=' + (f.s + f.c) + ')', f.data = a, f.plugin = g, f.setRatio = Ua), j && (f = new ta(i, 'visibility', 0, 0, f, -1, null, !1, 0, 0 !== h ? 'inherit' : 'hidden', 0 === b ? 'hidden' : 'inherit'), f.xs0 = 'inherit', d._overwriteProps.push(f.n), d._overwriteProps.push(c)), f; + }}); var Va = function(a, b) { + b && (a.removeProperty ? (('ms' === b.substr(0, 2) || 'webkit' === b.substr(0, 6)) && (b = '-' + b), a.removeProperty(b.replace(B, '-$1').toLowerCase())) : a.removeAttribute(b)); + }, + Wa = function(a) { + if (this.t._gsClassPT = this, 1 === a || 0 === a) { + this.t.setAttribute('class', 0 === a ? this.b : this.e); for (var b = this.data, c = this.t.style; b;) + b.v ? c[b.p] = b.v : Va(c, b.p), b = b._next; 1 === a && this.t._gsClassPT === this && (this.t._gsClassPT = null); + } else + this.t.getAttribute('class') !== this.e && this.t.setAttribute('class', this.e); + }; + + ya('className', {parser: function(a, b, d, f, g, h, i) { + var j, + k, + l, + m, + n, + o = a.getAttribute('class') || '', + p = a.style.cssText; + + if (g = f._classNamePT = new ta(a, d, 0, 0, g, 2), g.setRatio = Wa, g.pr = -11, c = !0, g.b = o, k = ca(a, e), l = a._gsClassPT) { + for (m = {}, n = l.data; n;) + m[n.p] = 1, n = n._next; l.setRatio(1); + } return a._gsClassPT = g, g.e = '=' !== b.charAt(1) ? b : o.replace(new RegExp('(?:\\s|^)' + b.substr(2) + '(?![\\w-])'), '') + ('+' === b.charAt(0) ? ' ' + b.substr(2) : ''), a.setAttribute('class', g.e), j = da(a, k, ca(a), i, m), a.setAttribute('class', o), g.data = j.firstMPT, a.style.cssText = p, g = g.xfirst = f.parse(a, j.difs, g, h); + }}); var Xa = function(a) { + if ((1 === a || 0 === a) && this.data._totalTime === this.data._totalDuration && 'isFromStart' !== this.data.data) { + var b, + c, + d, + e, + f, + g = this.t.style, + h = i.transform.parse; + + if ('all' === this.e) + g.cssText = '', e = !0; else + for (b = this.e.split(' ').join('').split(','), d = b.length; --d > -1;) + c = b[d], i[c] && (i[c].parse === h ? e = !0 : c = 'transformOrigin' === c ? Ea : i[c].p), Va(g, c); e && (Va(g, Ca), f = this.t._gsTransform, f && (f.svg && (this.t.removeAttribute('data-svg-origin'), this.t.removeAttribute('transform')), delete this.t._gsTransform)); + } + }; + + for (ya('clearProps', {parser: function(a, b, d, e, f) { + return f = new ta(a, d, 0, 0, f, 2), f.setRatio = Xa, f.e = b, f.pr = -10, f.data = e._tween, c = !0, f; + }}), j = 'bezier,throwProps,physicsProps,physics2D'.split(','), wa = j.length; wa--;) + za(j[wa]); j = g.prototype, j._firstPT = j._lastParsedTransform = j._transform = null, j._onInitTween = function(a, b, h, j) { + if (!a.nodeType) + return !1; this._target = q = a, this._tween = h, this._vars = b, r = j, k = b.autoRound, c = !1, d = b.suffixMap || g.suffixMap, e = $(a, ''), f = this._overwriteProps; var n, + p, + s, + t, + u, + v, + w, + x, + z, + A = a.style; + + if (l && '' === A.zIndex && (n = _(a, 'zIndex', e), ('auto' === n || '' === n) && this._addLazySet(A, 'zIndex', 0)), 'string' == typeof b && (t = A.cssText, n = ca(a, e), A.cssText = t + ';' + b, n = da(a, n, ca(a)).difs, !U && y.test(b) && (n.opacity = parseFloat(RegExp.$1)), b = n, A.cssText = t), b.className ? this._firstPT = p = i.className.parse(a, b.className, 'className', this, null, null, b) : this._firstPT = p = this.parse(a, b, null), this._transformType) { + for (z = 3 === this._transformType, Ca ? m && (l = !0, '' === A.zIndex && (w = _(a, 'zIndex', e), ('auto' === w || '' === w) && this._addLazySet(A, 'zIndex', 0)), o && this._addLazySet(A, 'WebkitBackfaceVisibility', this._vars.WebkitBackfaceVisibility || (z ? 'visible' : 'hidden'))) : A.zoom = 1, s = p; s && s._next;) + s = s._next; x = new ta(a, 'transform', 0, 0, null, 2), this._linkCSSP(x, null, s), x.setRatio = Ca ? Ta : Sa, x.data = this._transform || Ra(a, e, !0), x.tween = h, x.pr = -1, f.pop(); + } if (c) { + for (;p;) { + for (v = p._next, s = t; s && s.pr > p.pr;) + s = s._next; (p._prev = s ? s._prev : u) ? p._prev._next = p : t = p, (p._next = s) ? s._prev = p : u = p, p = v; + } this._firstPT = t; + } return !0; + }, j.parse = function(a, b, c, f) { + var g, + h, + j, + l, + m, + n, + o, + p, + s, + t, + u = a.style; + + for (g in b) { + if (n = b[g], 'function' == typeof n && (n = n(r, q)), h = i[g]) + c = h.parse(a, n, g, this, c, f, b); else { + if ('--' === g.substr(0, 2)) { + this._tween._propLookup[g] = this._addTween.call(this._tween, a.style, 'setProperty', $(a).getPropertyValue(g) + '', n + '', g, !1, g); continue; + }m = _(a, g, e) + '', s = 'string' == typeof n, 'color' === g || 'fill' === g || 'stroke' === g || -1 !== g.indexOf('Color') || s && A.test(n) ? (s || (n = na(n), n = (n.length > 3 ? 'rgba(' : 'rgb(') + n.join(',') + ')'), c = va(u, g, m, n, !0, 'transparent', c, 0, f)) : s && J.test(n) ? c = va(u, g, m, n, !0, null, c, 0, f) : (j = parseFloat(m), o = j || 0 === j ? m.substr((j + '').length) : '', ('' === m || 'auto' === m) && ('width' === g || 'height' === g ? (j = ga(a, g, e), o = 'px') : 'left' === g || 'top' === g ? (j = ba(a, g, e), o = 'px') : (j = 'opacity' !== g ? 0 : 1, o = '')), t = s && '=' === n.charAt(1), t ? (l = parseInt(n.charAt(0) + '1', 10), n = n.substr(2), l *= parseFloat(n), p = n.replace(w, '')) : (l = parseFloat(n), p = s ? n.replace(w, '') : ''), '' === p && (p = g in d ? d[g] : o), n = l || 0 === l ? (t ? l + j : l) + p : b[g], o !== p && ('' !== p || 'lineHeight' === g) && (l || 0 === l) && j && (j = aa(a, g, j, o), '%' === p ? (j /= aa(a, g, 100, '%') / 100, b.strictUnits !== !0 && (m = j + '%')) : 'em' === p || 'rem' === p || 'vw' === p || 'vh' === p ? j /= aa(a, g, 1, p) : 'px' !== p && (l = aa(a, g, l, p), p = 'px'), t && (l || 0 === l) && (n = l + j + p)), t && (l += j), !j && 0 !== j || !l && 0 !== l ? void 0 !== u[g] && (n || n + '' != 'NaN' && null != n) ? (c = new ta(u, g, l || j || 0, 0, c, -1, g, !1, 0, m, n), c.xs0 = 'none' !== n || 'display' !== g && -1 === g.indexOf('Style') ? n : m) : W('invalid ' + g + ' tween value: ' + b[g]) : (c = new ta(u, g, j, l - j, c, 0, g, k !== !1 && ('px' === p || 'zIndex' === g), 0, m, n), c.xs0 = p)); + }f && c && !c.plugin && (c.plugin = f); + } return c; + }, j.setRatio = function(a) { + var b, + c, + d, + e = this._firstPT, + f = 1e-6; + + if (1 !== a || this._tween._time !== this._tween._duration && 0 !== this._tween._time) + if (a || this._tween._time !== this._tween._duration && 0 !== this._tween._time || this._tween._rawPrevTime === -1e-6) + for (;e;) { + if (b = e.c * a + e.s, e.r ? b = e.r(b) : f > b && b > -f && (b = 0), e.type) + if (1 === e.type) + if (d = e.l, 2 === d) + e.t[e.p] = e.xs0 + b + e.xs1 + e.xn1 + e.xs2; else if (3 === d) + e.t[e.p] = e.xs0 + b + e.xs1 + e.xn1 + e.xs2 + e.xn2 + e.xs3; else if (4 === d) + e.t[e.p] = e.xs0 + b + e.xs1 + e.xn1 + e.xs2 + e.xn2 + e.xs3 + e.xn3 + e.xs4; else if (5 === d) + e.t[e.p] = e.xs0 + b + e.xs1 + e.xn1 + e.xs2 + e.xn2 + e.xs3 + e.xn3 + e.xs4 + e.xn4 + e.xs5; else { + for (c = e.xs0 + b + e.xs1, d = 1; d < e.l; d++) + c += e['xn' + d] + e['xs' + (d + 1)]; e.t[e.p] = c; + } else + -1 === e.type ? e.t[e.p] = e.xs0 : e.setRatio && e.setRatio(a); else + e.t[e.p] = b + e.xs0; e = e._next; + } else + for (;e;) + 2 !== e.type ? e.t[e.p] = e.b : e.setRatio(a), e = e._next; else + for (;e;) { + if (2 !== e.type) + if (e.r && -1 !== e.type) + if (b = e.r(e.s + e.c), e.type) { + if (1 === e.type) { + for (d = e.l, c = e.xs0 + b + e.xs1, d = 1; d < e.l; d++) + c += e['xn' + d] + e['xs' + (d + 1)]; e.t[e.p] = c; + } + } else + e.t[e.p] = b + e.xs0; else + e.t[e.p] = e.e; else + e.setRatio(a); e = e._next; + } + }, j._enableTransforms = function(a) { + this._transform = this._transform || Ra(this._target, e, !0), this._transformType = this._transform.svg && Aa || !a && 3 !== this._transformType ? 2 : 3; + }; var Ya = function(a) { + this.t[this.p] = this.e, this.data._linkCSSP(this, this._next, null, !0); + }; + + j._addLazySet = function(a, b, c) { + var d = this._firstPT = new ta(a, b, 0, 0, this._firstPT, 2); + + d.e = c, d.setRatio = Ya, d.data = this; + }, j._linkCSSP = function(a, b, c, d) { + return a && (b && (b._prev = a), a._next && (a._next._prev = a._prev), a._prev ? a._prev._next = a._next : this._firstPT === a && (this._firstPT = a._next, d = !0), c ? c._next = a : d || null !== this._firstPT || (this._firstPT = a), a._next = b, a._prev = c), a; + }, j._mod = function(a) { + for (var b = this._firstPT; b;) + 'function' == typeof a[b.p] && (b.r = a[b.p]), b = b._next; + }, j._kill = function(b) { + var c, + d, + e, + f = b; + + if (b.autoAlpha || b.alpha) { + f = {}; for (d in b) + f[d] = b[d]; f.opacity = 1, f.autoAlpha && (f.visibility = 1); + } for (b.className && (c = this._classNamePT) && (e = c.xfirst, e && e._prev ? this._linkCSSP(e._prev, c._next, e._prev._prev) : e === this._firstPT && (this._firstPT = c._next), c._next && this._linkCSSP(c._next, c._next._next, e._prev), this._classNamePT = null), c = this._firstPT; c;) + c.plugin && c.plugin !== d && c.plugin._kill && (c.plugin._kill(b), d = c.plugin), c = c._next; return a.prototype._kill.call(this, f); + }; var Za = function(a, b, c) { + var d, + e, + f, + g; + + if (a.slice) + for (e = a.length; --e > -1;) + Za(a[e], b, c); else + for (d = a.childNodes, e = d.length; --e > -1;) + f = d[e], g = f.type, f.style && (b.push(ca(f)), c && c.push(f)), 1 !== g && 9 !== g && 11 !== g || !f.childNodes.length || Za(f, b, c); + }; + + return g.cascadeTo = function(a, c, d) { + var e, + f, + g, + h, + i = b.to(a, c, d), + j = [i], + k = [], + l = [], + m = [], + n = b._internals.reservedProps; + + for (a = i._targets || i.target, Za(a, k, m), i.render(c, !0, !0), Za(a, l), i.render(0, !0, !0), i._enabled(!0), e = m.length; --e > -1;) + if (f = da(m[e], k[e], l[e]), f.firstMPT) { + f = f.difs; for (g in d) + n[g] && (f[g] = d[g]); h = {}; for (g in f) + h[g] = k[e][g]; j.push(b.fromTo(m[e], c, h, f)); + } return j; + }, a.activate([g]), g; + }, !0), function() { + var a = _gsScope._gsDefine.plugin({propName: 'roundProps', version: '1.7.0', priority: -1, API: 2, init: function(a, b, c) { + return this._tween = c, !0; + }}), + b = function(a) { + var b = 1 > a ? Math.pow(10, (a + '').length - 2) : 1; + + return function(c) { + return (Math.round(c / a) * a * b | 0) / b; + }; + }, + c = function(a, b) { + for (;a;) + a.f || a.blob || (a.m = b || Math.round), a = a._next; + }, + d = a.prototype; + + d._onInitAllProps = function() { + var a, + d, + e, + f, + g = this._tween, + h = g.vars.roundProps, + i = {}, + j = g._propLookup.roundProps; + + if ('object' != typeof h || h.push) + for ('string' == typeof h && (h = h.split(',')), e = h.length; --e > -1;) + i[h[e]] = Math.round; else + for (f in h) + i[f] = b(h[f]); for (f in i) + for (a = g._firstPT; a;) + d = a._next, a.pg ? a.t._mod(i) : a.n === f && (2 === a.f && a.t ? c(a.t._firstPT, i[f]) : (this._add(a.t, f, a.s, a.c, i[f]), d && (d._prev = a._prev), a._prev ? a._prev._next = d : g._firstPT === a && (g._firstPT = d), a._next = a._prev = null, g._propLookup[f] = j)), a = d; return !1; + }, d._add = function(a, b, c, d, e) { + this._addTween(a, b, c, c + d, b, e || Math.round), this._overwriteProps.push(b); + }; + }(), function() { + _gsScope._gsDefine.plugin({propName: 'attr', API: 2, version: '0.6.1', init: function(a, b, c, d) { + var e, + f; + + if ('function' != typeof a.setAttribute) + return !1; for (e in b) + f = b[e], 'function' == typeof f && (f = f(d, a)), this._addTween(a, 'setAttribute', a.getAttribute(e) + '', f + '', e, !1, e), this._overwriteProps.push(e); return !0; + }}); + }(), _gsScope._gsDefine.plugin({propName: 'directionalRotation', version: '0.3.1', API: 2, init: function(a, b, c, d) { + 'object' != typeof b && (b = {rotation: b}), this.finals = {}; var e, + f, + g, + h, + i, + j, + k = b.useRadians === !0 ? 2 * Math.PI : 360, + l = 1e-6; + + for (e in b) + 'useRadians' !== e && (h = b[e], 'function' == typeof h && (h = h(d, a)), j = (h + '').split('_'), f = j[0], g = parseFloat('function' != typeof a[e] ? a[e] : a[e.indexOf('set') || 'function' != typeof a['get' + e.substr(3)] ? e : 'get' + e.substr(3)]()), h = this.finals[e] = 'string' == typeof f && '=' === f.charAt(1) ? g + parseInt(f.charAt(0) + '1', 10) * Number(f.substr(2)) : Number(f) || 0, i = h - g, j.length && (f = j.join('_'), -1 !== f.indexOf('short') && (i %= k, i !== i % (k / 2) && (i = 0 > i ? i + k : i - k)), -1 !== f.indexOf('_cw') && 0 > i ? i = (i + 9999999999 * k) % k - (i / k | 0) * k : -1 !== f.indexOf('ccw') && i > 0 && (i = (i - 9999999999 * k) % k - (i / k | 0) * k)), (i > l || -l > i) && (this._addTween(a, e, g, g + i, e), this._overwriteProps.push(e))); return !0; + }, set: function(a) { + var b; + + if (1 !== a) + this._super.setRatio.call(this, a); else + for (b = this._firstPT; b;) + b.f ? b.t[b.p](this.finals[b.p]) : b.t[b.p] = this.finals[b.p], b = b._next; + }})._autoCSS = !0, _gsScope._gsDefine('easing.Back', ['easing.Ease'], function(a) { + var b, + c, + d, + e, + f = _gsScope.GreenSockGlobals || _gsScope, + g = f.com.greensock, + h = 2 * Math.PI, + i = Math.PI / 2, + j = g._class, + k = function(b, c) { + var d = j('easing.' + b, function() {}, !0), + e = d.prototype = new a; + + return e.constructor = d, e.getRatio = c, d; + }, + l = a.register || function() {}, + m = function(a, b, c, d, e) { + var f = j('easing.' + a, {easeOut: new b, easeIn: new c, easeInOut: new d}, !0); + + return l(f, a), f; + }, + n = function(a, b, c) { + this.t = a, this.v = b, c && (this.next = c, c.prev = this, this.c = c.v - b, this.gap = c.t - a); + }, + o = function(b, c) { + var d = j('easing.' + b, function(a) { + this._p1 = a || 0 === a ? a : 1.70158, this._p2 = 1.525 * this._p1; + }, !0), + e = d.prototype = new a; + + return e.constructor = d, e.getRatio = c, e.config = function(a) { + return new d(a); + }, d; + }, + p = m('Back', o('BackOut', function(a) { + return (a -= 1) * a * ((this._p1 + 1) * a + this._p1) + 1; + }), o('BackIn', function(a) { + return a * a * ((this._p1 + 1) * a - this._p1); + }), o('BackInOut', function(a) { + return (a *= 2) < 1 ? .5 * a * a * ((this._p2 + 1) * a - this._p2) : .5 * ((a -= 2) * a * ((this._p2 + 1) * a + this._p2) + 2); + })), + q = j('easing.SlowMo', function(a, b, c) { + b = b || 0 === b ? b : .7, null == a ? a = .7 : a > 1 && (a = 1), this._p = 1 !== a ? b : 0, this._p1 = (1 - a) / 2, this._p2 = a, this._p3 = this._p1 + this._p2, this._calcEnd = c === !0; + }, !0), + r = q.prototype = new a; + + return r.constructor = q, r.getRatio = function(a) { + var b = a + (.5 - a) * this._p; + + return a < this._p1 ? this._calcEnd ? 1 - (a = 1 - a / this._p1) * a : b - (a = 1 - a / this._p1) * a * a * a * b : a > this._p3 ? this._calcEnd ? 1 === a ? 0 : 1 - (a = (a - this._p3) / this._p1) * a : b + (a - b) * (a = (a - this._p3) / this._p1) * a * a * a : this._calcEnd ? 1 : b; + }, q.ease = new q(.7, .7), r.config = q.config = function(a, b, c) { + return new q(a, b, c); + }, b = j('easing.SteppedEase', function(a, b) { + a = a || 1, this._p1 = 1 / a, this._p2 = a + (b ? 0 : 1), this._p3 = b ? 1 : 0; + }, !0), r = b.prototype = new a, r.constructor = b, r.getRatio = function(a) { + return 0 > a ? a = 0 : a >= 1 && (a = .999999999), ((this._p2 * a | 0) + this._p3) * this._p1; + }, r.config = b.config = function(a, c) { + return new b(a, c); + }, c = j('easing.ExpoScaleEase', function(a, b, c) { + this._p1 = Math.log(b / a), this._p2 = b - a, this._p3 = a, this._ease = c; + }, !0), r = c.prototype = new a, r.constructor = c, r.getRatio = function(a) { + return this._ease && (a = this._ease.getRatio(a)), (this._p3 * Math.exp(this._p1 * a) - this._p3) / this._p2; + }, r.config = c.config = function(a, b, d) { + return new c(a, b, d); + }, d = j('easing.RoughEase', function(b) { + b = b || {}; for (var c, d, e, f, g, h, i = b.taper || 'none', j = [], k = 0, l = 0 | (b.points || 20), m = l, o = b.randomize !== !1, p = b.clamp === !0, q = b.template instanceof a ? b.template : null, r = 'number' == typeof b.strength ? .4 * b.strength : .4; --m > -1;) + c = o ? Math.random() : 1 / l * m, d = q ? q.getRatio(c) : c, 'none' === i ? e = r : 'out' === i ? (f = 1 - c, e = f * f * r) : 'in' === i ? e = c * c * r : .5 > c ? (f = 2 * c, e = f * f * .5 * r) : (f = 2 * (1 - c), e = f * f * .5 * r), o ? d += Math.random() * e - .5 * e : m % 2 ? d += .5 * e : d -= .5 * e, p && (d > 1 ? d = 1 : 0 > d && (d = 0)), j[k++] = {x: c, y: d}; for (j.sort(function(a, b) { + return a.x - b.x; + }), h = new n(1, 1, null), m = l; --m > -1;) + g = j[m], h = new n(g.x, g.y, h); this._prev = new n(0, 0, 0 !== h.t ? h : h.next); + }, !0), r = d.prototype = new a, r.constructor = d, r.getRatio = function(a) { + var b = this._prev; + + if (a > b.t) { + for (;b.next && a >= b.t;) + b = b.next; b = b.prev; + } else + for (;b.prev && a <= b.t;) + b = b.prev; return this._prev = b, b.v + (a - b.t) / b.gap * b.c; + }, r.config = function(a) { + return new d(a); + }, d.ease = new d, m('Bounce', k('BounceOut', function(a) { + return 1 / 2.75 > a ? 7.5625 * a * a : 2 / 2.75 > a ? 7.5625 * (a -= 1.5 / 2.75) * a + .75 : 2.5 / 2.75 > a ? 7.5625 * (a -= 2.25 / 2.75) * a + .9375 : 7.5625 * (a -= 2.625 / 2.75) * a + .984375; + }), k('BounceIn', function(a) { + return (a = 1 - a) < 1 / 2.75 ? 1 - 7.5625 * a * a : 2 / 2.75 > a ? 1 - (7.5625 * (a -= 1.5 / 2.75) * a + .75) : 2.5 / 2.75 > a ? 1 - (7.5625 * (a -= 2.25 / 2.75) * a + .9375) : 1 - (7.5625 * (a -= 2.625 / 2.75) * a + .984375); + }), k('BounceInOut', function(a) { + var b = .5 > a; + + return a = b ? 1 - 2 * a : 2 * a - 1, a = 1 / 2.75 > a ? 7.5625 * a * a : 2 / 2.75 > a ? 7.5625 * (a -= 1.5 / 2.75) * a + .75 : 2.5 / 2.75 > a ? 7.5625 * (a -= 2.25 / 2.75) * a + .9375 : 7.5625 * (a -= 2.625 / 2.75) * a + .984375, b ? .5 * (1 - a) : .5 * a + .5; + })), m('Circ', k('CircOut', function(a) { + return Math.sqrt(1 - (a -= 1) * a); + }), k('CircIn', function(a) { + return -(Math.sqrt(1 - a * a) - 1); + }), k('CircInOut', function(a) { + return (a *= 2) < 1 ? -.5 * (Math.sqrt(1 - a * a) - 1) : .5 * (Math.sqrt(1 - (a -= 2) * a) + 1); + })), e = function(b, c, d) { + var e = j('easing.' + b, function(a, b) { + this._p1 = a >= 1 ? a : 1, this._p2 = (b || d) / (1 > a ? a : 1), this._p3 = this._p2 / h * (Math.asin(1 / this._p1) || 0), this._p2 = h / this._p2; + }, !0), + f = e.prototype = new a; + + return f.constructor = e, f.getRatio = c, f.config = function(a, b) { + return new e(a, b); + }, e; + }, m('Elastic', e('ElasticOut', function(a) { + return this._p1 * Math.pow(2, -10 * a) * Math.sin((a - this._p3) * this._p2) + 1; + }, .3), e('ElasticIn', function(a) { + return -(this._p1 * Math.pow(2, 10 * (a -= 1)) * Math.sin((a - this._p3) * this._p2)); + }, .3), e('ElasticInOut', function(a) { + return (a *= 2) < 1 ? -.5 * (this._p1 * Math.pow(2, 10 * (a -= 1)) * Math.sin((a - this._p3) * this._p2)) : this._p1 * Math.pow(2, -10 * (a -= 1)) * Math.sin((a - this._p3) * this._p2) * .5 + 1; + }, .45)), m('Expo', k('ExpoOut', function(a) { + return 1 - Math.pow(2, -10 * a); + }), k('ExpoIn', function(a) { + return Math.pow(2, 10 * (a - 1)) - .001; + }), k('ExpoInOut', function(a) { + return (a *= 2) < 1 ? .5 * Math.pow(2, 10 * (a - 1)) : .5 * (2 - Math.pow(2, -10 * (a - 1))); + })), m('Sine', k('SineOut', function(a) { + return Math.sin(a * i); + }), k('SineIn', function(a) { + return -Math.cos(a * i) + 1; + }), k('SineInOut', function(a) { + return -.5 * (Math.cos(Math.PI * a) - 1); + })), j('easing.EaseLookup', {find: function(b) { + return a.map[b]; + }}, !0), l(f.SlowMo, 'SlowMo', 'ease,'), l(d, 'RoughEase', 'ease,'), l(b, 'SteppedEase', 'ease,'), p; + }, !0); +}), _gsScope._gsDefine && _gsScope._gsQueue.pop()(), function(a, b) { + 'use strict'; var c = {}, + d = a.document, + e = a.GreenSockGlobals = a.GreenSockGlobals || a, + f = e[b]; + + if (f) + return 'undefined' != typeof module && module.exports && (module.exports = f), f; var g, + h, + i, + j, + k, + l = function(a) { + var b, + c = a.split('.'), + d = e; + + for (b = 0; b < c.length; b++) + d[c[b]] = d = d[c[b]] || {}; return d; + }, + m = l('com.greensock'), + n = 1e-10, + o = function(a) { + var b, + c = [], + d = a.length; + + for (b = 0; b !== d; c.push(a[b++])) + ;return c; + }, + p = function() {}, + q = function() { + var a = Object.prototype.toString, + b = a.call([]); + + return function(c) { + return null != c && (c instanceof Array || 'object' == typeof c && !!c.push && a.call(c) === b); + }; + }(), + r = {}, + s = function(d, f, g, h) { + this.sc = r[d] ? r[d].sc : [], r[d] = this, this.gsClass = null, this.func = g; var i = []; + + this.check = function(j) { + for (var k, m, n, o, p = f.length, q = p; --p > -1;) + (k = r[f[p]] || new s(f[p], [])).gsClass ? (i[p] = k.gsClass, q--) : j && k.sc.push(this); if (0 === q && g) { + if (m = ('com.greensock.' + d).split('.'), n = m.pop(), o = l(m.join('.'))[n] = this.gsClass = g.apply(g, i), h) + if (e[n] = c[n] = o, 'undefined' != typeof module && module.exports) + if (d === b) { + module.exports = c[b] = o; for (p in c) + o[p] = c[p]; + } else + c[b] && (c[b][n] = o); else + 'function' == typeof define && define.amd && define((a.GreenSockAMDPath ? a.GreenSockAMDPath + '/' : '') + d.split('.').pop(), [], function() { + return o; + }); for (p = 0; p < this.sc.length; p++) + this.sc[p].check(); + } + }, this.check(!0); + }, + t = a._gsDefine = function(a, b, c, d) { + return new s(a, b, c, d); + }, + u = m._class = function(a, b, c) { + return b = b || function() {}, t(a, [], function() { + return b; + }, c), b; + }; + + t.globals = e; var v = [ 0, 0, 1, 1 ], + w = u('easing.Ease', function(a, b, c, d) { + this._func = a, this._type = c || 0, this._power = d || 0, this._params = b ? v.concat(b) : v; + }, !0), + x = w.map = {}, + y = w.register = function(a, b, c, d) { + for (var e, f, g, h, i = b.split(','), j = i.length, k = (c || 'easeIn,easeOut,easeInOut').split(','); --j > -1;) + for (f = i[j], e = d ? u('easing.' + f, null, !0) : m.easing[f] || {}, g = k.length; --g > -1;) + h = k[g], x[f + '.' + h] = x[h + f] = e[h] = a.getRatio ? a : a[h] || new a; + }; + + for (i = w.prototype, i._calcEnd = !1, i.getRatio = function(a) { + if (this._func) + return this._params[0] = a, this._func.apply(null, this._params); var b = this._type, + c = this._power, + d = 1 === b ? 1 - a : 2 === b ? a : .5 > a ? 2 * a : 2 * (1 - a); + + return 1 === c ? d *= d : 2 === c ? d *= d * d : 3 === c ? d *= d * d * d : 4 === c && (d *= d * d * d * d), 1 === b ? 1 - d : 2 === b ? d : .5 > a ? d / 2 : 1 - d / 2; + }, g = [ 'Linear', 'Quad', 'Cubic', 'Quart', 'Quint,Strong' ], h = g.length; --h > -1;) + i = g[h] + ',Power' + h, y(new w(null, null, 1, h), i, 'easeOut', !0), y(new w(null, null, 2, h), i, 'easeIn' + (0 === h ? ',easeNone' : '')), y(new w(null, null, 3, h), i, 'easeInOut'); x.linear = m.easing.Linear.easeIn, x.swing = m.easing.Quad.easeInOut; var z = u('events.EventDispatcher', function(a) { + this._listeners = {}, this._eventTarget = a || this; + }); + + i = z.prototype, i.addEventListener = function(a, b, c, d, e) { + e = e || 0; var f, + g, + h = this._listeners[a], + i = 0; + + for (this !== j || k || j.wake(), null == h && (this._listeners[a] = h = []), g = h.length; --g > -1;) + f = h[g], f.c === b && f.s === c ? h.splice(g, 1) : 0 === i && f.pr < e && (i = g + 1); h.splice(i, 0, {c: b, s: c, up: d, pr: e}); + }, i.removeEventListener = function(a, b) { + var c, + d = this._listeners[a]; + + if (d) + for (c = d.length; --c > -1;) + if (d[c].c === b) + return void d.splice(c, 1); + }, i.dispatchEvent = function(a) { + var b, + c, + d, + e = this._listeners[a]; + + if (e) + for (b = e.length, b > 1 && (e = e.slice(0)), c = this._eventTarget; --b > -1;) + d = e[b], d && (d.up ? d.c.call(d.s || c, {type: a, target: c}) : d.c.call(d.s || c)); + }; var A = a.requestAnimationFrame, + B = a.cancelAnimationFrame, + C = Date.now || function() { + return (new Date).getTime(); + }, + D = C(); + + for (g = [ 'ms', 'moz', 'webkit', 'o' ], h = g.length; --h > -1 && !A;) + A = a[g[h] + 'RequestAnimationFrame'], B = a[g[h] + 'CancelAnimationFrame'] || a[g[h] + 'CancelRequestAnimationFrame']; u('Ticker', function(a, b) { + var c, + e, + f, + g, + h, + i = this, + l = C(), + m = b !== !1 && A ? 'auto' : !1, + o = 500, + q = 33, + r = 'tick', + s = function(a) { + var b, + d, + j = C() - D; + + j > o && (l += j - q), D += j, i.time = (D - l) / 1e3, b = i.time - h, (!c || b > 0 || a === !0) && (i.frame++, h += b + (b >= g ? .004 : g - b), d = !0), a !== !0 && (f = e(s)), d && i.dispatchEvent(r); + }; + + z.call(i), i.time = i.frame = 0, i.tick = function() { + s(!0); + }, i.lagSmoothing = function(a, b) { + return arguments.length ? (o = a || 1 / n, void (q = Math.min(b, o, 0))) : 1 / n > o; + }, i.sleep = function() { + null != f && (m && B ? B(f) : clearTimeout(f), e = p, f = null, i === j && (k = !1)); + }, i.wake = function(a) { + null !== f ? i.sleep() : a ? l += -D + (D = C()) : i.frame > 10 && (D = C() - o + 5), e = 0 === c ? p : m && A ? A : function(a) { + return setTimeout(a, 1e3 * (h - i.time) + 1 | 0); + }, i === j && (k = !0), s(2); + }, i.fps = function(a) { + return arguments.length ? (c = a, g = 1 / (c || 60), h = this.time + g, void i.wake()) : c; + }, i.useRAF = function(a) { + return arguments.length ? (i.sleep(), m = a, void i.fps(c)) : m; + }, i.fps(a), setTimeout(function() { + 'auto' === m && i.frame < 5 && 'hidden' !== (d || {}).visibilityState && i.useRAF(!1); + }, 1500); + }), i = m.Ticker.prototype = new m.events.EventDispatcher, i.constructor = m.Ticker; var E = u('core.Animation', function(a, b) { + if (this.vars = b = b || {}, this._duration = this._totalDuration = a || 0, this._delay = Number(b.delay) || 0, this._timeScale = 1, this._active = b.immediateRender === !0, this.data = b.data, this._reversed = b.reversed === !0, Y) { + k || j.wake(); var c = this.vars.useFrames ? X : Y; + + c.add(this, c._time), this.vars.paused && this.paused(!0); + } + }); + + j = E.ticker = new m.Ticker, i = E.prototype, i._dirty = i._gc = i._initted = i._paused = !1, i._totalTime = i._time = 0, i._rawPrevTime = -1, i._next = i._last = i._onUpdate = i._timeline = i.timeline = null, i._paused = !1; var F = function() { + k && C() - D > 2e3 && ('hidden' !== (d || {}).visibilityState || !j.lagSmoothing()) && j.wake(); var a = setTimeout(F, 2e3); + + a.unref && a.unref(); + }; + + F(), i.play = function(a, b) { + return null != a && this.seek(a, b), this.reversed(!1).paused(!1); + }, i.pause = function(a, b) { + return null != a && this.seek(a, b), this.paused(!0); + }, i.resume = function(a, b) { + return null != a && this.seek(a, b), this.paused(!1); + }, i.seek = function(a, b) { + return this.totalTime(Number(a), b !== !1); + }, i.restart = function(a, b) { + return this.reversed(!1).paused(!1).totalTime(a ? -this._delay : 0, b !== !1, !0); + }, i.reverse = function(a, b) { + return null != a && this.seek(a || this.totalDuration(), b), this.reversed(!0).paused(!1); + }, i.render = function(a, b, c) {}, i.invalidate = function() { + return this._time = this._totalTime = 0, this._initted = this._gc = !1, this._rawPrevTime = -1, (this._gc || !this.timeline) && this._enabled(!0), this; + }, i.isActive = function() { + var a, + b = this._timeline, + c = this._startTime; + + return !b || !this._gc && !this._paused && b.isActive() && (a = b.rawTime(!0)) >= c && a < c + this.totalDuration() / this._timeScale - 1e-7; + }, i._enabled = function(a, b) { + return k || j.wake(), this._gc = !a, this._active = this.isActive(), b !== !0 && (a && !this.timeline ? this._timeline.add(this, this._startTime - this._delay) : !a && this.timeline && this._timeline._remove(this, !0)), !1; + }, i._kill = function(a, b) { + return this._enabled(!1, !1); + }, i.kill = function(a, b) { + return this._kill(a, b), this; + }, i._uncache = function(a) { + for (var b = a ? this : this.timeline; b;) + b._dirty = !0, b = b.timeline; return this; + }, i._swapSelfInParams = function(a) { + for (var b = a.length, c = a.concat(); --b > -1;) + '{self}' === a[b] && (c[b] = this); return c; + }, i._callback = function(a) { + var b = this.vars, + c = b[a], + d = b[a + 'Params'], + e = b[a + 'Scope'] || b.callbackScope || this, + f = d ? d.length : 0; + + switch (f) { + case 0:c.call(e); break; case 1:c.call(e, d[0]); break; case 2:c.call(e, d[0], d[1]); break; default:c.apply(e, d); + } + }, i.eventCallback = function(a, b, c, d) { + if ('on' === (a || '').substr(0, 2)) { + var e = this.vars; + + if (1 === arguments.length) + return e[a]; null == b ? delete e[a] : (e[a] = b, e[a + 'Params'] = q(c) && -1 !== c.join('').indexOf('{self}') ? this._swapSelfInParams(c) : c, e[a + 'Scope'] = d), 'onUpdate' === a && (this._onUpdate = b); + } return this; + }, i.delay = function(a) { + return arguments.length ? (this._timeline.smoothChildTiming && this.startTime(this._startTime + a - this._delay), this._delay = a, this) : this._delay; + }, i.duration = function(a) { + return arguments.length ? (this._duration = this._totalDuration = a, this._uncache(!0), this._timeline.smoothChildTiming && this._time > 0 && this._time < this._duration && 0 !== a && this.totalTime(this._totalTime * (a / this._duration), !0), this) : (this._dirty = !1, this._duration); + }, i.totalDuration = function(a) { + return this._dirty = !1, arguments.length ? this.duration(a) : this._totalDuration; + }, i.time = function(a, b) { + return arguments.length ? (this._dirty && this.totalDuration(), this.totalTime(a > this._duration ? this._duration : a, b)) : this._time; + }, i.totalTime = function(a, b, c) { + if (k || j.wake(), !arguments.length) + return this._totalTime; if (this._timeline) { + if (0 > a && !c && (a += this.totalDuration()), this._timeline.smoothChildTiming) { + this._dirty && this.totalDuration(); var d = this._totalDuration, + e = this._timeline; + + if (a > d && !c && (a = d), this._startTime = (this._paused ? this._pauseTime : e._time) - (this._reversed ? d - a : a) / this._timeScale, e._dirty || this._uncache(!1), e._timeline) + for (;e._timeline;) + e._timeline._time !== (e._startTime + e._totalTime) / e._timeScale && e.totalTime(e._totalTime, !0), e = e._timeline; + } this._gc && this._enabled(!0, !1), (this._totalTime !== a || 0 === this._duration) && (K.length && $(), this.render(a, b, !1), K.length && $()); + } return this; + }, i.progress = i.totalProgress = function(a, b) { + var c = this.duration(); + + return arguments.length ? this.totalTime(c * a, b) : c ? this._time / c : this.ratio; + }, i.startTime = function(a) { + return arguments.length ? (a !== this._startTime && (this._startTime = a, this.timeline && this.timeline._sortChildren && this.timeline.add(this, a - this._delay)), this) : this._startTime; + }, i.endTime = function(a) { + return this._startTime + (0 != a ? this.totalDuration() : this.duration()) / this._timeScale; + }, i.timeScale = function(a) { + if (!arguments.length) + return this._timeScale; var b, + c; + + for (a = a || n, this._timeline && this._timeline.smoothChildTiming && (b = this._pauseTime, c = b || 0 === b ? b : this._timeline.totalTime(), this._startTime = c - (c - this._startTime) * this._timeScale / a), this._timeScale = a, c = this.timeline; c && c.timeline;) + c._dirty = !0, c.totalDuration(), c = c.timeline; return this; + }, i.reversed = function(a) { + return arguments.length ? (a != this._reversed && (this._reversed = a, this.totalTime(this._timeline && !this._timeline.smoothChildTiming ? this.totalDuration() - this._totalTime : this._totalTime, !0)), this) : this._reversed; + }, i.paused = function(a) { + if (!arguments.length) + return this._paused; var b, + c, + d = this._timeline; + + return a != this._paused && d && (k || a || j.wake(), b = d.rawTime(), c = b - this._pauseTime, !a && d.smoothChildTiming && (this._startTime += c, this._uncache(!1)), this._pauseTime = a ? b : null, this._paused = a, this._active = this.isActive(), !a && 0 !== c && this._initted && this.duration() && (b = d.smoothChildTiming ? this._totalTime : (b - this._startTime) / this._timeScale, this.render(b, b === this._totalTime, !0))), this._gc && !a && this._enabled(!0, !1), this; + }; var G = u('core.SimpleTimeline', function(a) { + E.call(this, 0, a), this.autoRemoveChildren = this.smoothChildTiming = !0; + }); + + i = G.prototype = new E, i.constructor = G, i.kill()._gc = !1, i._first = i._last = i._recent = null, i._sortChildren = !1, i.add = i.insert = function(a, b, c, d) { + var e, + f; + + if (a._startTime = Number(b || 0) + a._delay, a._paused && this !== a._timeline && (a._pauseTime = this.rawTime() - (a._timeline.rawTime() - a._pauseTime)), a.timeline && a.timeline._remove(a, !0), a.timeline = a._timeline = this, a._gc && a._enabled(!0, !0), e = this._last, this._sortChildren) + for (f = a._startTime; e && e._startTime > f;) + e = e._prev; return e ? (a._next = e._next, e._next = a) : (a._next = this._first, this._first = a), a._next ? a._next._prev = a : this._last = a, a._prev = e, this._recent = a, this._timeline && this._uncache(!0), this; + }, i._remove = function(a, b) { + return a.timeline === this && (b || a._enabled(!1, !0), a._prev ? a._prev._next = a._next : this._first === a && (this._first = a._next), a._next ? a._next._prev = a._prev : this._last === a && (this._last = a._prev), a._next = a._prev = a.timeline = null, a === this._recent && (this._recent = this._last), this._timeline && this._uncache(!0)), this; + }, i.render = function(a, b, c) { + var d, + e = this._first; + + for (this._totalTime = this._time = this._rawPrevTime = a; e;) + d = e._next, (e._active || a >= e._startTime && !e._paused && !e._gc) && (e._reversed ? e.render((e._dirty ? e.totalDuration() : e._totalDuration) - (a - e._startTime) * e._timeScale, b, c) : e.render((a - e._startTime) * e._timeScale, b, c)), e = d; + }, i.rawTime = function() { + return k || j.wake(), this._totalTime; + }; var H = u('TweenLite', function(b, c, d) { + if (E.call(this, c, d), this.render = H.prototype.render, null == b) + throw 'Cannot tween a null target.'; this.target = b = 'string' != typeof b ? b : H.selector(b) || b; var e, + f, + g, + h = b.jquery || b.length && b !== a && b[0] && (b[0] === a || b[0].nodeType && b[0].style && !b.nodeType), + i = this.vars.overwrite; + + if (this._overwrite = i = null == i ? W[H.defaultOverwrite] : 'number' == typeof i ? i >> 0 : W[i], (h || b instanceof Array || b.push && q(b)) && 'number' != typeof b[0]) + for (this._targets = g = o(b), this._propLookup = [], this._siblings = [], e = 0; e < g.length; e++) + f = g[e], f ? 'string' != typeof f ? f.length && f !== a && f[0] && (f[0] === a || f[0].nodeType && f[0].style && !f.nodeType) ? (g.splice(e--, 1), this._targets = g = g.concat(o(f))) : (this._siblings[e] = _(f, this, !1), 1 === i && this._siblings[e].length > 1 && ba(f, this, null, 1, this._siblings[e])) : (f = g[e--] = H.selector(f), 'string' == typeof f && g.splice(e + 1, 1)) : g.splice(e--, 1); else + this._propLookup = {}, this._siblings = _(b, this, !1), 1 === i && this._siblings.length > 1 && ba(b, this, null, 1, this._siblings); (this.vars.immediateRender || 0 === c && 0 === this._delay && this.vars.immediateRender !== !1) && (this._time = -n, this.render(Math.min(0, -this._delay))); + }, !0), + I = function(b) { + return b && b.length && b !== a && b[0] && (b[0] === a || b[0].nodeType && b[0].style && !b.nodeType); + }, + J = function(a, b) { + var c, + d = {}; + + for (c in a) + V[c] || c in b && 'transform' !== c && 'x' !== c && 'y' !== c && 'width' !== c && 'height' !== c && 'className' !== c && 'border' !== c || !(!S[c] || S[c] && S[c]._autoCSS) || (d[c] = a[c], delete a[c]); a.css = d; + }; + + i = H.prototype = new E, i.constructor = H, i.kill()._gc = !1, i.ratio = 0, i._firstPT = i._targets = i._overwrittenProps = i._startAt = null, i._notifyPluginsOfEnabled = i._lazy = !1, H.version = '2.0.2', H.defaultEase = i._ease = new w(null, null, 1, 1), H.defaultOverwrite = 'auto', H.ticker = j, H.autoSleep = 120, H.lagSmoothing = function(a, b) { + j.lagSmoothing(a, b); + }, H.selector = a.$ || a.jQuery || function(b) { + var c = a.$ || a.jQuery; + + return c ? (H.selector = c, c(b)) : (d || (d = a.document), d ? d.querySelectorAll ? d.querySelectorAll(b) : d.getElementById('#' === b.charAt(0) ? b.substr(1) : b) : b); + }; var K = [], + L = {}, + M = /(?:(-|-=|\+=)?\d*\.?\d*(?:e[\-+]?\d+)?)[0-9]/gi, + N = /[\+-]=-?[\.\d]/, + O = function(a) { + for (var b, c = this._firstPT, d = 1e-6; c;) + b = c.blob ? 1 === a && null != this.end ? this.end : a ? this.join('') : this.start : c.c * a + c.s, c.m ? b = c.m.call(this._tween, b, this._target || c.t, this._tween) : d > b && b > -d && !c.blob && (b = 0), c.f ? c.fp ? c.t[c.p](c.fp, b) : c.t[c.p](b) : c.t[c.p] = b, c = c._next; + }, + P = function(a, b, c, d) { + var e, + f, + g, + h, + i, + j, + k, + l = [], + m = 0, + n = '', + o = 0; + + for (l.start = a, l.end = b, a = l[0] = a + '', b = l[1] = b + '', c && (c(l), a = l[0], b = l[1]), l.length = 0, e = a.match(M) || [], f = b.match(M) || [], d && (d._next = null, d.blob = 1, l._firstPT = l._applyPT = d), i = f.length, h = 0; i > h; h++) + k = f[h], j = b.substr(m, b.indexOf(k, m) - m), n += j || !h ? j : ',', m += j.length, o ? o = (o + 1) % 5 : 'rgba(' === j.substr(-5) && (o = 1), k === e[h] || e.length <= h ? n += k : (n && (l.push(n), n = ''), g = parseFloat(e[h]), l.push(g), l._firstPT = {_next: l._firstPT, t: l, p: l.length - 1, s: g, c: ('=' === k.charAt(1) ? parseInt(k.charAt(0) + '1', 10) * parseFloat(k.substr(2)) : parseFloat(k) - g) || 0, f: 0, m: o && 4 > o ? Math.round : 0}), m += k.length; return n += b.substr(m), n && l.push(n), l.setRatio = O, N.test(b) && (l.end = null), l; + }, + Q = function(a, b, c, d, e, f, g, h, i) { + 'function' == typeof d && (d = d(i || 0, a)); var j, + k = typeof a[b], + l = 'function' !== k ? '' : b.indexOf('set') || 'function' != typeof a['get' + b.substr(3)] ? b : 'get' + b.substr(3), + m = 'get' !== c ? c : l ? g ? a[l](g) : a[l]() : a[b], + n = 'string' == typeof d && '=' === d.charAt(1), + o = {t: a, p: b, s: m, f: 'function' === k, pg: 0, n: e || b, m: f ? 'function' == typeof f ? f : Math.round : 0, pr: 0, c: n ? parseInt(d.charAt(0) + '1', 10) * parseFloat(d.substr(2)) : parseFloat(d) - m || 0}; + + return ('number' != typeof m || 'number' != typeof d && !n) && (g || isNaN(m) || !n && isNaN(d) || 'boolean' == typeof m || 'boolean' == typeof d ? (o.fp = g, j = P(m, n ? parseFloat(o.s) + o.c + (o.s + '').replace(/[0-9\-\.]/g, '') : d, h || H.defaultStringFilter, o), o = {t: j, p: 'setRatio', s: 0, c: 1, f: 2, pg: 0, n: e || b, pr: 0, m: 0}) : (o.s = parseFloat(m), n || (o.c = parseFloat(d) - o.s || 0))), o.c ? ((o._next = this._firstPT) && (o._next._prev = o), this._firstPT = o, o) : void 0; + }, + R = H._internals = {isArray: q, isSelector: I, lazyTweens: K, blobDif: P}, + S = H._plugins = {}, + T = R.tweenLookup = {}, + U = 0, + V = R.reservedProps = {ease: 1, delay: 1, overwrite: 1, onComplete: 1, onCompleteParams: 1, onCompleteScope: 1, useFrames: 1, runBackwards: 1, startAt: 1, onUpdate: 1, onUpdateParams: 1, onUpdateScope: 1, onStart: 1, onStartParams: 1, onStartScope: 1, onReverseComplete: 1, onReverseCompleteParams: 1, onReverseCompleteScope: 1, onRepeat: 1, onRepeatParams: 1, onRepeatScope: 1, easeParams: 1, yoyo: 1, immediateRender: 1, repeat: 1, repeatDelay: 1, data: 1, paused: 1, reversed: 1, autoCSS: 1, lazy: 1, onOverwrite: 1, callbackScope: 1, stringFilter: 1, id: 1, yoyoEase: 1}, + W = {none: 0, all: 1, auto: 2, concurrent: 3, allOnStart: 4, preexisting: 5, 'true': 1, 'false': 0}, + X = E._rootFramesTimeline = new G, + Y = E._rootTimeline = new G, + Z = 30, + $ = R.lazyRender = function() { + var a, + b = K.length; + + for (L = {}; --b > -1;) + a = K[b], a && a._lazy !== !1 && (a.render(a._lazy[0], a._lazy[1], !0), a._lazy = !1); K.length = 0; + }; + + Y._startTime = j.time, X._startTime = j.frame, Y._active = X._active = !0, setTimeout($, 1), E._updateRoot = H.render = function() { + var a, + b, + c; + + if (K.length && $(), Y.render((j.time - Y._startTime) * Y._timeScale, !1, !1), X.render((j.frame - X._startTime) * X._timeScale, !1, !1), K.length && $(), j.frame >= Z) { + Z = j.frame + (parseInt(H.autoSleep, 10) || 120); for (c in T) { + for (b = T[c].tweens, a = b.length; --a > -1;) + b[a]._gc && b.splice(a, 1); 0 === b.length && delete T[c]; + } if (c = Y._first, (!c || c._paused) && H.autoSleep && !X._first && 1 === j._listeners.tick.length) { + for (;c && c._paused;) + c = c._next; c || j.sleep(); + } + } + }, j.addEventListener('tick', E._updateRoot); var _ = function(a, b, c) { + var d, + e, + f = a._gsTweenID; + + if (T[f || (a._gsTweenID = f = 't' + U++)] || (T[f] = {target: a, tweens: []}), b && (d = T[f].tweens, d[e = d.length] = b, c)) + for (;--e > -1;) + d[e] === b && d.splice(e, 1); return T[f].tweens; + }, + aa = function(a, b, c, d) { + var e, + f, + g = a.vars.onOverwrite; + + return g && (e = g(a, b, c, d)), g = H.onOverwrite, g && (f = g(a, b, c, d)), e !== !1 && f !== !1; + }, + ba = function(a, b, c, d, e) { + var f, + g, + h, + i; + + if (1 === d || d >= 4) { + for (i = e.length, f = 0; i > f; f++) + if ((h = e[f]) !== b) + h._gc || h._kill(null, a, b) && (g = !0); else if (5 === d) + break; return g; + } var j, + k = b._startTime + n, + l = [], + m = 0, + o = 0 === b._duration; + + for (f = e.length; --f > -1;) + (h = e[f]) === b || h._gc || h._paused || (h._timeline !== b._timeline ? (j = j || ca(b, 0, o), 0 === ca(h, j, o) && (l[m++] = h)) : h._startTime <= k && h._startTime + h.totalDuration() / h._timeScale > k && ((o || !h._initted) && k - h._startTime <= 2e-10 || (l[m++] = h))); for (f = m; --f > -1;) + if (h = l[f], i = h._firstPT, 2 === d && h._kill(c, a, b) && (g = !0), 2 !== d || !h._firstPT && h._initted && i) { + if (2 !== d && !aa(h, b)) + continue; h._enabled(!1, !1) && (g = !0); + } return g; + }, + ca = function(a, b, c) { + for (var d = a._timeline, e = d._timeScale, f = a._startTime; d._timeline;) { + if (f += d._startTime, e *= d._timeScale, d._paused) + return -100; d = d._timeline; + } return f /= e, f > b ? f - b : c && f === b || !a._initted && 2 * n > f - b ? n : (f += a.totalDuration() / a._timeScale / e) > b + n ? 0 : f - b - n; + }; + + i._init = function() { + var a, + b, + c, + d, + e, + f, + g = this.vars, + h = this._overwrittenProps, + i = this._duration, + j = !!g.immediateRender, + k = g.ease; + + if (g.startAt) { + this._startAt && (this._startAt.render(-1, !0), this._startAt.kill()), e = {}; for (d in g.startAt) + e[d] = g.startAt[d]; if (e.data = 'isStart', e.overwrite = !1, e.immediateRender = !0, e.lazy = j && g.lazy !== !1, e.startAt = e.delay = null, e.onUpdate = g.onUpdate, e.onUpdateParams = g.onUpdateParams, e.onUpdateScope = g.onUpdateScope || g.callbackScope || this, this._startAt = H.to(this.target || {}, 0, e), j) + if (this._time > 0) + this._startAt = null; else if (0 !== i) + return; + } else if (g.runBackwards && 0 !== i) + if (this._startAt) + this._startAt.render(-1, !0), this._startAt.kill(), this._startAt = null; else { + 0 !== this._time && (j = !1), c = {}; for (d in g) + V[d] && 'autoCSS' !== d || (c[d] = g[d]); if (c.overwrite = 0, c.data = 'isFromStart', c.lazy = j && g.lazy !== !1, c.immediateRender = j, this._startAt = H.to(this.target, 0, c), j) { + if (0 === this._time) + return; + } else + this._startAt._init(), this._startAt._enabled(!1), this.vars.immediateRender && (this._startAt = null); + } if (this._ease = k = k ? k instanceof w ? k : 'function' == typeof k ? new w(k, g.easeParams) : x[k] || H.defaultEase : H.defaultEase, g.easeParams instanceof Array && k.config && (this._ease = k.config.apply(k, g.easeParams)), this._easeType = this._ease._type, this._easePower = this._ease._power, this._firstPT = null, this._targets) + for (f = this._targets.length, a = 0; f > a; a++) + this._initProps(this._targets[a], this._propLookup[a] = {}, this._siblings[a], h ? h[a] : null, a) && (b = !0); else + b = this._initProps(this.target, this._propLookup, this._siblings, h, 0); if (b && H._onPluginEvent('_onInitAllProps', this), h && (this._firstPT || 'function' != typeof this.target && this._enabled(!1, !1)), g.runBackwards) + for (c = this._firstPT; c;) + c.s += c.c, c.c = -c.c, c = c._next; this._onUpdate = g.onUpdate, this._initted = !0; + }, i._initProps = function(b, c, d, e, f) { + var g, + h, + i, + j, + k, + l; + + if (null == b) + return !1; L[b._gsTweenID] && $(), this.vars.css || b.style && b !== a && b.nodeType && S.css && this.vars.autoCSS !== !1 && J(this.vars, b); for (g in this.vars) + if (l = this.vars[g], V[g]) + l && (l instanceof Array || l.push && q(l)) && -1 !== l.join('').indexOf('{self}') && (this.vars[g] = l = this._swapSelfInParams(l, this)); else if (S[g] && (j = new S[g])._onInitTween(b, this.vars[g], this, f)) { + for (this._firstPT = k = {_next: this._firstPT, t: j, p: 'setRatio', s: 0, c: 1, f: 1, n: g, pg: 1, pr: j._priority, m: 0}, h = j._overwriteProps.length; --h > -1;) + c[j._overwriteProps[h]] = this._firstPT; (j._priority || j._onInitAllProps) && (i = !0), (j._onDisable || j._onEnable) && (this._notifyPluginsOfEnabled = !0), k._next && (k._next._prev = k); + } else + c[g] = Q.call(this, b, g, 'get', l, g, 0, null, this.vars.stringFilter, f); return e && this._kill(e, b) ? this._initProps(b, c, d, e, f) : this._overwrite > 1 && this._firstPT && d.length > 1 && ba(b, this, c, this._overwrite, d) ? (this._kill(c, b), this._initProps(b, c, d, e, f)) : (this._firstPT && (this.vars.lazy !== !1 && this._duration || this.vars.lazy && !this._duration) && (L[b._gsTweenID] = !0), i); + }, i.render = function(a, b, c) { + var d, + e, + f, + g, + h = this._time, + i = this._duration, + j = this._rawPrevTime; + + if (a >= i - 1e-7 && a >= 0) + this._totalTime = this._time = i, this.ratio = this._ease._calcEnd ? this._ease.getRatio(1) : 1, this._reversed || (d = !0, e = 'onComplete', c = c || this._timeline.autoRemoveChildren), 0 === i && (this._initted || !this.vars.lazy || c) && (this._startTime === this._timeline._duration && (a = 0), (0 > j || 0 >= a && a >= -1e-7 || j === n && 'isPause' !== this.data) && j !== a && (c = !0, j > n && (e = 'onReverseComplete')), this._rawPrevTime = g = !b || a || j === a ? a : n); else if (1e-7 > a) + this._totalTime = this._time = 0, this.ratio = this._ease._calcEnd ? this._ease.getRatio(0) : 0, (0 !== h || 0 === i && j > 0) && (e = 'onReverseComplete', d = this._reversed), 0 > a && (this._active = !1, 0 === i && (this._initted || !this.vars.lazy || c) && (j >= 0 && (j !== n || 'isPause' !== this.data) && (c = !0), this._rawPrevTime = g = !b || a || j === a ? a : n)), (!this._initted || this._startAt && this._startAt.progress()) && (c = !0); else if (this._totalTime = this._time = a, this._easeType) { + var k = a / i, + l = this._easeType, + m = this._easePower; + + (1 === l || 3 === l && k >= .5) && (k = 1 - k), 3 === l && (k *= 2), 1 === m ? k *= k : 2 === m ? k *= k * k : 3 === m ? k *= k * k * k : 4 === m && (k *= k * k * k * k), 1 === l ? this.ratio = 1 - k : 2 === l ? this.ratio = k : .5 > a / i ? this.ratio = k / 2 : this.ratio = 1 - k / 2; + } else + this.ratio = this._ease.getRatio(a / i); if (this._time !== h || c) { + if (!this._initted) { + if (this._init(), !this._initted || this._gc) + return; if (!c && this._firstPT && (this.vars.lazy !== !1 && this._duration || this.vars.lazy && !this._duration)) + return this._time = this._totalTime = h, this._rawPrevTime = j, K.push(this), void (this._lazy = [ a, b ]); this._time && !d ? this.ratio = this._ease.getRatio(this._time / i) : d && this._ease._calcEnd && (this.ratio = this._ease.getRatio(0 === this._time ? 0 : 1)); + } for (this._lazy !== !1 && (this._lazy = !1), this._active || !this._paused && this._time !== h && a >= 0 && (this._active = !0), 0 === h && (this._startAt && (a >= 0 ? this._startAt.render(a, !0, c) : e || (e = '_dummyGS')), this.vars.onStart && (0 !== this._time || 0 === i) && (b || this._callback('onStart'))), f = this._firstPT; f;) + f.f ? f.t[f.p](f.c * this.ratio + f.s) : f.t[f.p] = f.c * this.ratio + f.s, f = f._next; this._onUpdate && (0 > a && this._startAt && a !== -1e-4 && this._startAt.render(a, !0, c), b || (this._time !== h || d || c) && this._callback('onUpdate')), e && (!this._gc || c) && (0 > a && this._startAt && !this._onUpdate && a !== -1e-4 && this._startAt.render(a, !0, c), d && (this._timeline.autoRemoveChildren && this._enabled(!1, !1), this._active = !1), !b && this.vars[e] && this._callback(e), 0 === i && this._rawPrevTime === n && g !== n && (this._rawPrevTime = 0)); + } + }, i._kill = function(a, b, c) { + if ('all' === a && (a = null), null == a && (null == b || b === this.target)) + return this._lazy = !1, this._enabled(!1, !1); b = 'string' != typeof b ? b || this._targets || this.target : H.selector(b) || b; var d, + e, + f, + g, + h, + i, + j, + k, + l, + m = c && this._time && c._startTime === this._startTime && this._timeline === c._timeline, + n = this._firstPT; + + if ((q(b) || I(b)) && 'number' != typeof b[0]) + for (d = b.length; --d > -1;) + this._kill(a, b[d], c) && (i = !0); else { + if (this._targets) { + for (d = this._targets.length; --d > -1;) + if (b === this._targets[d]) { + h = this._propLookup[d] || {}, this._overwrittenProps = this._overwrittenProps || [], e = this._overwrittenProps[d] = a ? this._overwrittenProps[d] || {} : 'all'; break; + } + } else { + if (b !== this.target) + return !1; h = this._propLookup, e = this._overwrittenProps = a ? this._overwrittenProps || {} : 'all'; + } if (h) { + if (j = a || h, k = a !== e && 'all' !== e && a !== h && ('object' != typeof a || !a._tempKill), c && (H.onOverwrite || this.vars.onOverwrite)) { + for (f in j) + h[f] && (l || (l = []), l.push(f)); if ((l || !a) && !aa(this, c, b, l)) + return !1; + } for (f in j) + (g = h[f]) && (m && (g.f ? g.t[g.p](g.s) : g.t[g.p] = g.s, i = !0), g.pg && g.t._kill(j) && (i = !0), g.pg && 0 !== g.t._overwriteProps.length || (g._prev ? g._prev._next = g._next : g === this._firstPT && (this._firstPT = g._next), g._next && (g._next._prev = g._prev), g._next = g._prev = null), delete h[f]), k && (e[f] = 1); !this._firstPT && this._initted && n && this._enabled(!1, !1); + } + } return i; + }, i.invalidate = function() { + return this._notifyPluginsOfEnabled && H._onPluginEvent('_onDisable', this), this._firstPT = this._overwrittenProps = this._startAt = this._onUpdate = null, this._notifyPluginsOfEnabled = this._active = this._lazy = !1, this._propLookup = this._targets ? {} : [], E.prototype.invalidate.call(this), this.vars.immediateRender && (this._time = -n, this.render(Math.min(0, -this._delay))), this; + }, i._enabled = function(a, b) { + if (k || j.wake(), a && this._gc) { + var c, + d = this._targets; + + if (d) + for (c = d.length; --c > -1;) + this._siblings[c] = _(d[c], this, !0); else + this._siblings = _(this.target, this, !0); + } return E.prototype._enabled.call(this, a, b), this._notifyPluginsOfEnabled && this._firstPT ? H._onPluginEvent(a ? '_onEnable' : '_onDisable', this) : !1; + }, H.to = function(a, b, c) { + return new H(a, b, c); + }, H.from = function(a, b, c) { + return c.runBackwards = !0, c.immediateRender = 0 != c.immediateRender, new H(a, b, c); + }, H.fromTo = function(a, b, c, d) { + return d.startAt = c, d.immediateRender = 0 != d.immediateRender && 0 != c.immediateRender, new H(a, b, d); + }, H.delayedCall = function(a, b, c, d, e) { + return new H(b, 0, {delay: a, onComplete: b, onCompleteParams: c, callbackScope: d, onReverseComplete: b, onReverseCompleteParams: c, immediateRender: !1, lazy: !1, useFrames: e, overwrite: 0}); + }, H.set = function(a, b) { + return new H(a, 0, b); + }, H.getTweensOf = function(a, b) { + if (null == a) + return []; a = 'string' != typeof a ? a : H.selector(a) || a; var c, + d, + e, + f; + + if ((q(a) || I(a)) && 'number' != typeof a[0]) { + for (c = a.length, d = []; --c > -1;) + d = d.concat(H.getTweensOf(a[c], b)); for (c = d.length; --c > -1;) + for (f = d[c], e = c; --e > -1;) + f === d[e] && d.splice(c, 1); + } else if (a._gsTweenID) + for (d = _(a).concat(), c = d.length; --c > -1;) + (d[c]._gc || b && !d[c].isActive()) && d.splice(c, 1); return d || []; + }, H.killTweensOf = H.killDelayedCallsTo = function(a, b, c) { + 'object' == typeof b && (c = b, b = !1); for (var d = H.getTweensOf(a, b), e = d.length; --e > -1;) + d[e]._kill(c, a); + }; var da = u('plugins.TweenPlugin', function(a, b) { + this._overwriteProps = (a || '').split(','), this._propName = this._overwriteProps[0], this._priority = b || 0, this._super = da.prototype; + }, !0); + + if (i = da.prototype, da.version = '1.19.0', da.API = 2, i._firstPT = null, i._addTween = Q, i.setRatio = O, i._kill = function(a) { + var b, + c = this._overwriteProps, + d = this._firstPT; + + if (null != a[this._propName]) + this._overwriteProps = []; else + for (b = c.length; --b > -1;) + null != a[c[b]] && c.splice(b, 1); for (;d;) + null != a[d.n] && (d._next && (d._next._prev = d._prev), d._prev ? (d._prev._next = d._next, d._prev = null) : this._firstPT === d && (this._firstPT = d._next)), d = d._next; return !1; + }, i._mod = i._roundProps = function(a) { + for (var b, c = this._firstPT; c;) + b = a[this._propName] || null != c.n && a[c.n.split(this._propName + '_').join('')], b && 'function' == typeof b && (2 === c.f ? c.t._applyPT.m = b : c.m = b), c = c._next; + }, H._onPluginEvent = function(a, b) { + var c, + d, + e, + f, + g, + h = b._firstPT; + + if ('_onInitAllProps' === a) { + for (;h;) { + for (g = h._next, d = e; d && d.pr > h.pr;) + d = d._next; (h._prev = d ? d._prev : f) ? h._prev._next = h : e = h, (h._next = d) ? d._prev = h : f = h, h = g; + }h = b._firstPT = e; + } for (;h;) + h.pg && 'function' == typeof h.t[a] && h.t[a]() && (c = !0), h = h._next; return c; + }, da.activate = function(a) { + for (var b = a.length; --b > -1;) + a[b].API === da.API && (S[(new a[b])._propName] = a[b]); return !0; + }, t.plugin = function(a) { + if (!(a && a.propName && a.init && a.API)) + throw 'illegal plugin definition.'; var b, + c = a.propName, + d = a.priority || 0, + e = a.overwriteProps, + f = {init: '_onInitTween', set: 'setRatio', kill: '_kill', round: '_mod', mod: '_mod', initAll: '_onInitAllProps'}, + g = u('plugins.' + c.charAt(0).toUpperCase() + c.substr(1) + 'Plugin', function() { + da.call(this, c, d), this._overwriteProps = e || []; + }, a.global === !0), + h = g.prototype = new da(c); + + h.constructor = g, g.API = a.API; for (b in f) + 'function' == typeof a[b] && (h[f[b]] = a[b]); return g.version = a.version, da.activate([g]), g; + }, g = a._gsQueue) { + for (h = 0; h < g.length; h++) + g[h](); for (i in r) + r[i].func || a.console.log('GSAP encountered missing dependency: ' + i); + }k = !1; +}('undefined' != typeof module && module.exports && 'undefined' != typeof global ? global : this || window, 'TweenMax'); \ No newline at end of file diff --git a/app/assets/v2/js/user-search.js b/app/assets/v2/js/user-search.js index 4057c3f6999..d58051060d5 100644 --- a/app/assets/v2/js/user-search.js +++ b/app/assets/v2/js/user-search.js @@ -1,4 +1,5 @@ -function userSearch(elem, showAddress) { +function userSearch(elem, showAddress, theme) { + var themeChoice = theme || undefined; var selectItem = elem || '.username-search'; $(selectItem).each(function() { @@ -26,6 +27,7 @@ function userSearch(elem, showAddress) { }, cache: true }, + theme: themeChoice, placeholder: 'Search by username', minimumInputLength: 3, escapeMarkup: function(markup) { @@ -89,4 +91,4 @@ function userSearch(elem, showAddress) { return selected; } }); -} \ No newline at end of file +} diff --git a/app/bounty_requests/templates/bounty_request_form.html b/app/bounty_requests/templates/bounty_request_form.html index e43e1ec7b32..56d71e36262 100644 --- a/app/bounty_requests/templates/bounty_request_form.html +++ b/app/bounty_requests/templates/bounty_request_form.html @@ -23,6 +23,7 @@
          + {% include 'shared/top_nav.html' with class='d-md-flex' %} {% include 'shared/nav.html' %}
          diff --git a/app/dashboard/migrations/0110_auto_20181027_1727.py b/app/dashboard/migrations/0110_auto_20181027_1727.py new file mode 100644 index 00000000000..28f3a5befaf --- /dev/null +++ b/app/dashboard/migrations/0110_auto_20181027_1727.py @@ -0,0 +1,30 @@ +# Generated by Django 2.1.2 on 2018-10-27 17:27 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('kudos', '0001_initial'), + ('dashboard', '0109_bounty_funding_organisation'), + ] + + operations = [ + migrations.AddField( + model_name='profile', + name='preferred_kudos_wallet', + field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='preferred_kudos_wallet', to='kudos.Wallet'), + ), + migrations.AlterField( + model_name='tip', + name='expires_date', + field=models.DateTimeField(blank=True, null=True), + ), + migrations.AlterField( + model_name='tip', + name='tokenName', + field=models.CharField(default='ETH', max_length=255), + ), + ] diff --git a/app/dashboard/models.py b/app/dashboard/models.py index 5fba69557af..79c4c669200 100644 --- a/app/dashboard/models.py +++ b/app/dashboard/models.py @@ -1054,22 +1054,17 @@ def __str__(self): return f"{self.email} {self.created_on}" -class TipPayoutException(Exception): - pass - - -class Tip(SuperModel): +class SendCryptoAsset(SuperModel): + """Abstract Base Class to handle the model for both Tips and Kudos.""" web3_type = models.CharField(max_length=50, default='v3') emails = JSONField(blank=True) url = models.CharField(max_length=255, default='', blank=True) - tokenName = models.CharField(max_length=255) + tokenName = models.CharField(max_length=255, default='ETH') tokenAddress = models.CharField(max_length=255) amount = models.DecimalField(default=1, decimal_places=4, max_digits=50) - comments_priv = models.TextField(default='', blank=True) comments_public = models.TextField(default='', blank=True) ip = models.CharField(max_length=50) - expires_date = models.DateTimeField() github_url = models.URLField(null=True, blank=True) from_name = models.CharField(max_length=255, default='', blank=True) from_email = models.CharField(max_length=255, default='', blank=True) @@ -1081,12 +1076,6 @@ class Tip(SuperModel): received_on = models.DateTimeField(null=True, blank=True) from_address = models.CharField(max_length=255, default='', blank=True) receive_address = models.CharField(max_length=255, default='', blank=True) - recipient_profile = models.ForeignKey( - 'dashboard.Profile', related_name='received_tips', on_delete=models.SET_NULL, null=True, blank=True - ) - sender_profile = models.ForeignKey( - 'dashboard.Profile', related_name='sent_tips', on_delete=models.SET_NULL, null=True, blank=True - ) metadata = JSONField(default=dict, blank=True) is_for_bounty_fulfiller = models.BooleanField( default=False, @@ -1094,6 +1083,9 @@ class Tip(SuperModel): ' fulfiller, not self.usernameusername.', ) + class Meta: + abstract = True + def __str__(self): """Return the string representation for a tip.""" if self.web3_type == 'yge': @@ -1131,28 +1123,6 @@ def org_name(self): except Exception: return None - @property - def receive_url(self): - if self.web3_type == 'yge': - return self.url - elif self.web3_type == 'v3': - return self.receive_url_for_recipient - elif self.web3_type != 'v2': - raise Exception - - return self.receive_url_for_recipient - - @property - def receive_url_for_recipient(self): - if self.web3_type != 'v3': - raise Exception - - try: - key = self.metadata['reference_hash_for_receipient'] - return f"{settings.BASE_URL}tip/receive/v3/{key}/{self.txid}/{self.network}" - except: - return None - # TODO: DRY @property def value_in_eth(self): @@ -1240,6 +1210,46 @@ def bounty(self): return None +class Tip(SendCryptoAsset): + """ Inherit from SendCryptoAsset base class, and extra fields that are needed for Tips. """ + expires_date = models.DateTimeField(null=True, blank=True) + comments_priv = models.TextField(default='', blank=True) + recipient_profile = models.ForeignKey( + 'dashboard.Profile', related_name='received_tips', on_delete=models.SET_NULL, null=True, blank=True + ) + sender_profile = models.ForeignKey( + 'dashboard.Profile', related_name='sent_tips', on_delete=models.SET_NULL, null=True, blank=True + ) + + @property + def receive_url(self): + if self.web3_type == 'yge': + return self.url + elif self.web3_type == 'v3': + return self.receive_url_for_recipient + elif self.web3_type != 'v2': + raise Exception + + return self.receive_url_for_recipient + + @property + def receive_url_for_recipient(self): + if self.web3_type != 'v3': + logger.error('Web3 type is not "v3"') + return '' + + try: + key = self.metadata['reference_hash_for_receipient'] + return f"{settings.BASE_URL}tip/receive/v3/{key}/{self.txid}/{self.network}" + except Exception as e: + logger.warning('Receive url for Tip recipient not found') + return '' + + +class TipPayoutException(Exception): + pass + + @receiver(pre_save, sender=Tip, dispatch_uid="psave_tip") def psave_tip(sender, instance, **kwargs): # when a new tip is saved, make sure it doesnt have whitespace in it @@ -1549,6 +1559,7 @@ class Profile(SuperModel): form_submission_records = JSONField(default=list, blank=True) max_num_issues_start_work = models.IntegerField(default=3) preferred_payout_address = models.CharField(max_length=255, default='', blank=True) + preferred_kudos_wallet = models.OneToOneField('kudos.Wallet', related_name='preferred_kudos_wallet', on_delete=models.SET_NULL, null=True, blank=True) max_tip_amount_usdt_per_tx = models.DecimalField(default=500, decimal_places=2, max_digits=50) max_tip_amount_usdt_per_week = models.DecimalField(default=1500, decimal_places=2, max_digits=50) diff --git a/app/dashboard/notifications.py b/app/dashboard/notifications.py index fb9dda6caf8..b992a22fc53 100644 --- a/app/dashboard/notifications.py +++ b/app/dashboard/notifications.py @@ -25,14 +25,18 @@ from django.conf import settings from django.contrib.humanize.templatetags.humanize import naturaltime from django.templatetags.static import static +from django.utils import timezone, translation +from django.utils.translation import gettext import requests import twitter from economy.utils import convert_token_to_usdt from git.utils import delete_issue_comment, org_name, patch_issue_comment, post_issue_comment, repo_name -from marketing.mails import tip_email +from marketing.mails import send_mail, setup_lang, tip_email from marketing.models import GithubOrgToTwitterHandleMapping +from marketing.utils import should_suppress_notification_email from pyshorteners import Shortener +from retail.emails import render_new_kudos_email from slackclient import SlackClient logger = logging.getLogger(__name__) @@ -362,6 +366,65 @@ def maybe_market_tip_to_slack(tip, event_name): return True +def maybe_market_kudos_to_email(kudos_transfer): + """Send an email for the specified Kudos. The general flow of this function: + + - 1. Decide if we are sending it + - 2. Generate subject + - 3. Render email + - 4. Send email + - 5. Do translation + + Args: + kudos_transfer (kudos.models.KudosTransfer): The Kudos Email object to be marketed. + + Returns: + bool: Whether or not the email notification was sent successfully. + + """ + is_new = True + + # 1. Decide if we are sending it + if kudos_transfer.network != settings.ENABLE_NOTIFICATIONS_ON_NETWORK: + logger.warning('Notifications are disabled. Skipping email.') + logger.debug(kudos_transfer.network) + logger.debug(settings.ENABLE_NOTIFICATIONS_ON_NETWORK) + return False + + if not kudos_transfer or not kudos_transfer.txid or not kudos_transfer.amount or not kudos_transfer.kudos_token_cloned_from: + logger.warning('Some kudos information not found. Skipping email.') + return False + + # 2. Generate subject + on_network = '' if kudos_transfer.network == 'mainnet' else f'({kudos_transfer.network})' + if is_new: + subject = gettext(f"⚡️ New {kudos_transfer.kudos_token_cloned_from.humanized_name} Kudos Available {on_network}") + else: + subject = gettext(f"🕐 Your {kudos_transfer.kudos_token_cloned_from.humanized_name} Kudos Is Expiring Soon {on_network}") + + logger.info(f'Emails to send to: {kudos_transfer.emails}') + + for to_email in kudos_transfer.emails: + cur_language = translation.get_language() + try: + setup_lang(to_email) + # TODO: Does the from_email field in the database mean nothing? We just override it here. + from_email = settings.CONTACT_EMAIL + # 3. Render email + html, text = render_new_kudos_email(to_email, kudos_transfer, is_new) + + # 4. Send email unless the email address has notifications disabled + if not should_suppress_notification_email(to_email, 'kudos'): + # TODO: Should we be doing something with the response from SendGrid? + # Maybe we should store it somewhere. + send_mail(from_email, to_email, subject, text, html) + finally: + # 5. Do translation + translation.activate(cur_language) + + return True + + def get_status_header(bounty): statuses = ['Open'] status = bounty.status diff --git a/app/dashboard/templates/bounty/change.html b/app/dashboard/templates/bounty/change.html index 3fc52eb7b0e..dc44d3dfd41 100644 --- a/app/dashboard/templates/bounty/change.html +++ b/app/dashboard/templates/bounty/change.html @@ -25,6 +25,7 @@ {% include 'shared/tag_manager_2.html' %}
          + {% include 'shared/top_nav.html' with class='d-md-flex' %} {% include 'shared/nav.html' %}
          diff --git a/app/dashboard/templates/bounty/details.html b/app/dashboard/templates/bounty/details.html index 2a11bc93efe..f8ad30a0205 100644 --- a/app/dashboard/templates/bounty/details.html +++ b/app/dashboard/templates/bounty/details.html @@ -14,6 +14,7 @@ {% include 'shared/tag_manager_2.html' %}
          + {% include 'shared/top_nav.html' with class='d-md-flex' %} {% include 'shared/nav.html' %}
          diff --git a/app/dashboard/templates/bounty/fulfill.html b/app/dashboard/templates/bounty/fulfill.html index 072ee774432..7948802b0ba 100644 --- a/app/dashboard/templates/bounty/fulfill.html +++ b/app/dashboard/templates/bounty/fulfill.html @@ -25,6 +25,7 @@ {% include 'shared/tag_manager_2.html' %}
          + {% include 'shared/top_nav.html' with class='d-md-flex' %} {% include 'shared/nav.html' %}
          diff --git a/app/dashboard/templates/bounty/increase.html b/app/dashboard/templates/bounty/increase.html index 912a47ccaf2..545e9b68352 100644 --- a/app/dashboard/templates/bounty/increase.html +++ b/app/dashboard/templates/bounty/increase.html @@ -27,6 +27,7 @@ {% include 'shared/tag_manager_2.html' %}
          + {% include 'shared/top_nav.html' with class='d-md-flex' %} {% include 'shared/nav.html' %}
          diff --git a/app/dashboard/templates/bounty/kill.html b/app/dashboard/templates/bounty/kill.html index 65129606557..ae12ab5e482 100644 --- a/app/dashboard/templates/bounty/kill.html +++ b/app/dashboard/templates/bounty/kill.html @@ -25,6 +25,7 @@ {% include 'shared/tag_manager_2.html' %}
          + {% include 'shared/top_nav.html' with class='d-md-flex' %} {% include 'shared/nav.html' %}
          diff --git a/app/dashboard/templates/bounty/new.html b/app/dashboard/templates/bounty/new.html index b4421402fce..d7049929a3d 100644 --- a/app/dashboard/templates/bounty/new.html +++ b/app/dashboard/templates/bounty/new.html @@ -29,6 +29,7 @@ {% include 'shared/tag_manager_2.html' %}
          + {% include 'shared/top_nav.html' with class='d-md-flex' %} {% include 'shared/nav.html' %}
          diff --git a/app/dashboard/templates/bulk_payout_bounty.html b/app/dashboard/templates/bulk_payout_bounty.html index 605499ad10b..02ed11a138f 100644 --- a/app/dashboard/templates/bulk_payout_bounty.html +++ b/app/dashboard/templates/bulk_payout_bounty.html @@ -28,6 +28,7 @@ {% include 'shared/tag_manager_2.html' %}
          + {% include 'shared/top_nav.html' with class='d-md-flex' %} {% include 'shared/nav.html' %}
          diff --git a/app/dashboard/templates/contribute_bounty.html b/app/dashboard/templates/contribute_bounty.html index a3acc9e24af..bd913b392ba 100644 --- a/app/dashboard/templates/contribute_bounty.html +++ b/app/dashboard/templates/contribute_bounty.html @@ -26,6 +26,7 @@ {% include 'shared/tag_manager_2.html' %}
          + {% include 'shared/top_nav.html' with class='d-md-flex' %} {% include 'shared/nav.html' %}
          diff --git a/app/dashboard/templates/dashboard/index.html b/app/dashboard/templates/dashboard/index.html index 643644bf8d6..74f535a5378 100644 --- a/app/dashboard/templates/dashboard/index.html +++ b/app/dashboard/templates/dashboard/index.html @@ -31,6 +31,7 @@ {% include 'shared/tag_manager_2.html' %}
          + {% include 'shared/top_nav.html' with class='d-md-flex' %} {% include 'shared/nav.html' %}
          {% include 'dashboard/ftux.html' %} diff --git a/app/dashboard/templates/ftux/onboard.html b/app/dashboard/templates/ftux/onboard.html index ddf5b1c7abe..d17a1f07ae4 100644 --- a/app/dashboard/templates/ftux/onboard.html +++ b/app/dashboard/templates/ftux/onboard.html @@ -30,6 +30,7 @@ {% include 'shared/tag_manager_2.html' %}
          + {% include 'shared/top_nav.html' with class='d-md-flex' %} {% include 'shared/nav.html' %}
          diff --git a/app/dashboard/templates/legal/terms.html b/app/dashboard/templates/legal/terms.html index 244ec883937..4b1f1b4089d 100644 --- a/app/dashboard/templates/legal/terms.html +++ b/app/dashboard/templates/legal/terms.html @@ -30,6 +30,7 @@ {% include 'shared/tag_manager_2.html' %}
          + {% include 'shared/top_nav.html' with class='d-md-flex' %} {% include 'shared/nav.html' %} {% include 'shared/minihero.html' with h1='Terms of Use' position_h1_below_logo=1 %}
          diff --git a/app/dashboard/templates/onepager/base.html b/app/dashboard/templates/onepager/base.html index 119ea958370..9237a213244 100644 --- a/app/dashboard/templates/onepager/base.html +++ b/app/dashboard/templates/onepager/base.html @@ -28,6 +28,7 @@ + @@ -83,6 +84,7 @@ {% include 'shared/tag_manager_2.html' %} {% include 'shared/analytics.html' with suppress_sumo=1 %} + {% include 'shared/top_nav.html' with class='d-md-flex' %} {% block 'world' %} {% endblock %} {% include 'shared/rain.html' with class="color" %} @@ -129,8 +131,9 @@ {% include 'shared/messages.html' %} + {% include 'shared/tag_manager_2.html' %}
          + {% include 'shared/top_nav.html' with class='d-md-flex' %} {% include 'shared/nav.html' %}
          @@ -54,7 +67,7 @@

          {% trans "Basic Payout" %}

          {% include 'shared/network_status.html' %}
          - +
          @@ -65,8 +78,9 @@

          {% trans "Basic Payout" %}

          - % worth 0 {{bounty.token_name}} + % worth 0 {{bounty.token_name}}
          + {% include 'shared/add_kudos.html' %}
          {% include 'shared/bounty_actions_hidden_vars.html' %} {% include 'shared/wallet_estimate.html' %} @@ -122,5 +136,7 @@

          {% trans "Basic Payout" %}

          + + diff --git a/app/dashboard/templates/profiles/profile.html b/app/dashboard/templates/profiles/profile.html index 8ba905ab3a7..2aadeb01cda 100644 --- a/app/dashboard/templates/profiles/profile.html +++ b/app/dashboard/templates/profiles/profile.html @@ -7,17 +7,19 @@ + {% include 'shared/tag_manager_2.html' %}
          + {% include 'shared/top_nav.html' with class='d-md-flex' %} {% include 'shared/nav.html' %}
          - +

          {% if profile.data.name %} {{ profile.data.name }} @@ -40,6 +42,11 @@ {% endif %}

          + {% if preferred_payout_address %} +
          {{ preferred_payout_address }}
          + {% else %} +
          No preferred address
          + {% endif %} {% if profile.data.bio %}
          {{ profile.data.bio }} @@ -116,6 +123,50 @@
          + {% if not hidden %} +
          +
          + {% if user.is_authenticated and request.path == '/profile/' %} +
          + + +
          + + {% endif %} + +
          + {% include "shared/profile_kudos.html" %} +
          +
          +
          + {% endif %}
          {% if hidden %} {% include 'profiles/hidden.html' %} @@ -256,7 +307,11 @@ - + + + @@ -270,10 +325,89 @@ $('.profile-bounties--tips .bounty_row').removeClass('bounty_row--hidden'); }); } - setupTabs('#activity-tabs'); + setupTabs('#activity-tabs'); + + + + $("[data-toggle=popover]").popover({ + html : true, + trigger: 'focus', + template: '', + content: function() { + var content = $(this).attr("data-popover-content"); + return $(content).children(".popover-body").html(); + }, + title: function() { + var title = $(this).attr("data-popover-content"); + return $(title).children(".popover-heading").html(); + } + }); + + {% if not preferred_payout_address%} + $("[data-toggle=popover]").popover('show') + {% endif %} + + $("body").on('submit', '#form-wallets', function(e) { + e.preventDefault() + var data = $("#form-wallets").serializeArray(); + data.push({'page': 2}); + var postWallets = fetchData ( e.currentTarget.action, + e.currentTarget.method, + data + ) + $.when( postWallets ).then( function ( response ){ + var walletAddress = response.wallets[0] + var newAddress = new truncate(walletAddress) + $('#preferred-address').text(newAddress.elem); + $('#preferred-address').prop('title', walletAddress) + $('#kudos-section').html(response.kudos_html) + + }) + }); }); + + + (function($) { + $(document).on('click','.load-more' ,function() { + var address = $('#preferred-address').prop('title') + if (!address) { + return + } + var link = $(this); + var page = link.data('page'); + var request = link.data('request') + $.ajax({ + type: 'POST', + url: '/lazy_load_kudos/', + data: { + 'page': page, + 'request': request, + 'address': address, + 'csrfmiddlewaretoken': '{{csrf_token}}' // from index.html + }, + success: function(data) { + // if there are still more pages to load, + // add 1 to the "Load More Posts" link's page data attribute + // else hide the link + if (data.has_next) { + link.data('page', page+1); + } else { + link.hide(); + } + // append html to the posts div + var elem = '#' + request + $(elem + ' div').first().append(data.kudos_html); + }, + error: function(xhr, status, error) { + // shit happens friends! + } + }); + }); + }(jQuery)); + + diff --git a/app/dashboard/templates/quickstart.html b/app/dashboard/templates/quickstart.html index a1e981239a6..e2d8f02b492 100644 --- a/app/dashboard/templates/quickstart.html +++ b/app/dashboard/templates/quickstart.html @@ -28,6 +28,7 @@ {% include 'shared/tag_manager_2.html' %}
          + {% include 'shared/top_nav.html' with class='d-md-flex' %} {% include 'shared/nav.html' %}
          diff --git a/app/dashboard/templates/shared/add_kudos.html b/app/dashboard/templates/shared/add_kudos.html new file mode 100644 index 00000000000..bb88ff51f1b --- /dev/null +++ b/app/dashboard/templates/shared/add_kudos.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 i18n static %} +
          + + +
          + + What is kudos? + +
          + + +
          diff --git a/app/dashboard/templates/shared/nav_auth.html b/app/dashboard/templates/shared/nav_auth.html index 9a41d13e8be..6b4397bfa51 100644 --- a/app/dashboard/templates/shared/nav_auth.html +++ b/app/dashboard/templates/shared/nav_auth.html @@ -15,11 +15,15 @@ along with this program. If not, see . {% endcomment %} {% load i18n static %} +{% load kudos_extras %} {% if user.is_authenticated %} - {% else %} + +
          + +
          +
          + {% include 'shared/kudos_card_profile.html' with kudos_data='kudos' %} +
          +
          + {% if kudos.count > 8 %} + + {% endif %} +
          + {% if not kudos %} +
          +

          What is Kudos?

          +
          + {% trans + {% trans +
          + More About Kudos +
          + {% endif %} +
          + +
          +
          + {% include 'shared/kudos_card_profile.html' with kudos_data='sent_kudos' %} +
          +
          + {% if sent_kudos.count > 8 %} + + {% endif %} +
          + {% if not sent_kudos %} +
          +

          What is Kudos?

          +
          + {% trans + {% trans +
          + More About Kudos +
          + {% endif %} +
          + +
          + diff --git a/app/dashboard/templates/social_contribution.html b/app/dashboard/templates/social_contribution.html index 00d98048c03..98c9dded434 100644 --- a/app/dashboard/templates/social_contribution.html +++ b/app/dashboard/templates/social_contribution.html @@ -26,6 +26,7 @@ {% include 'shared/tag_manager_2.html' %}
          + {% include 'shared/top_nav.html' with class='d-md-flex' %} {% include 'shared/nav.html' %}
          diff --git a/app/dashboard/templates/toolbox.html b/app/dashboard/templates/toolbox.html index e85c5094162..d5676d4c1ac 100644 --- a/app/dashboard/templates/toolbox.html +++ b/app/dashboard/templates/toolbox.html @@ -29,6 +29,7 @@ {% include 'shared/tag_manager_2.html' %}
          + {% include 'shared/top_nav.html' with class='d-md-flex' %} {% include 'shared/nav.html' %}
          diff --git a/app/dashboard/utils.py b/app/dashboard/utils.py index e9a6789b84c..7b968bc3d00 100644 --- a/app/dashboard/utils.py +++ b/app/dashboard/utils.py @@ -31,8 +31,9 @@ from gas.utils import conf_time_spread, eth_usd_conv_rate, gas_advisories, recommend_min_gas_price_to_confirm_in_time from hexbytes import HexBytes from ipfsapi.exceptions import CommunicationError -from web3 import HTTPProvider, Web3 +from web3 import HTTPProvider, Web3, WebsocketProvider from web3.exceptions import BadFunctionCallOutput +from web3.middleware import geth_poa_middleware logger = logging.getLogger(__name__) @@ -188,7 +189,7 @@ def ipfs_cat_requests(key): return None, 500 -def get_web3(network): +def get_web3(network, sockets=False): """Get a Web3 session for the provided network. Attributes: @@ -203,7 +204,17 @@ def get_web3(network): """ if network in ['mainnet', 'rinkeby', 'ropsten']: - return Web3(HTTPProvider(f'https://{network}.infura.io')) + if sockets: + provider = WebsocketProvider(f'wss://{network}.infura.io/ws') + else: + provider = HTTPProvider(f'https://{network}.infura.io') + w3 = Web3(provider) + if network == 'rinkeby': + w3.middleware_stack.inject(geth_poa_middleware, layer=0) + return w3 + elif network == 'localhost' or 'custom network': + return Web3(Web3.HTTPProvider("http://testrpc:8545", request_kwargs={'timeout': 60})) + raise UnsupportedNetworkException(network) @@ -438,7 +449,6 @@ def get_ordinal_repr(num): return f'{num}{suffix}' - def record_user_action_on_interest(interest, event_name, last_heard_from_user_days): """Record User actions and activity for the associated Interest.""" payload = { diff --git a/app/dashboard/views.py b/app/dashboard/views.py index 95d8e404890..3ee92112531 100644 --- a/app/dashboard/views.py +++ b/app/dashboard/views.py @@ -25,42 +25,52 @@ from django.conf import settings from django.contrib import messages from django.contrib.auth.models import User +from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator +from django.db.models import Q from django.http import Http404, HttpResponse, JsonResponse from django.shortcuts import redirect +from django.template import loader from django.template.response import TemplateResponse from django.templatetags.static import static from django.utils import timezone from django.utils.text import slugify from django.utils.translation import gettext_lazy as _ +from django.views.decorators.clickjacking import xframe_options_exempt from django.views.decorators.csrf import csrf_exempt from django.views.decorators.http import require_GET, require_POST +from eth_utils import to_checksum_address, to_normalized_address +from pytz import UTC +from web3 import HTTPProvider, Web3 from app.utils import clean_str, ellipses, sync_profile from avatar.utils import get_avatar_context +from economy.utils import convert_token_to_usdt from gas.utils import recommend_min_gas_price_to_confirm_in_time -from git.utils import get_auth_url, get_github_user_data, is_github_token_valid, search_users -from marketing.mails import ( - admin_contact_funder, bounty_uninterested, start_work_approved, start_work_new_applicant, start_work_rejected, -) +from git.utils import (get_auth_url, get_github_user_data, + is_github_token_valid, search_users) +from kudos.models import KudosTransfer, Token, Wallet +from kudos.utils import humanize_name +from marketing.mails import (admin_contact_funder, bounty_uninterested, + start_work_approved, start_work_new_applicant, + start_work_rejected) from marketing.models import Keyword -from pytz import UTC from ratelimit.decorators import ratelimit from retail.helpers import get_ip -from web3 import HTTPProvider, Web3 from .helpers import get_bounty_data_for_activity, handle_bounty_views -from .models import ( - Activity, Bounty, CoinRedemption, CoinRedemptionRequest, Interest, Profile, ProfileSerializer, Subscription, Tool, - ToolVote, UserAction, -) -from .notifications import ( - maybe_market_tip_to_email, maybe_market_tip_to_github, maybe_market_tip_to_slack, maybe_market_to_email, - maybe_market_to_github, maybe_market_to_slack, maybe_market_to_twitter, maybe_market_to_user_discord, - maybe_market_to_user_slack, -) -from .utils import ( - get_bounty, get_bounty_id, get_context, has_tx_mined, record_user_action_on_interest, web3_process_bounty, -) +from .models import (Activity, Bounty, CoinRedemption, CoinRedemptionRequest, + Interest, Profile, ProfileSerializer, Subscription, Tool, + ToolVote, UserAction) +from .notifications import (maybe_market_tip_to_email, + maybe_market_tip_to_github, + maybe_market_tip_to_slack, maybe_market_to_email, + maybe_market_to_github, maybe_market_to_slack, + maybe_market_to_twitter, + maybe_market_to_user_discord, + maybe_market_to_user_slack) +from .utils import (get_bounty, get_bounty_id, get_context, get_web3, + has_tx_mined, record_user_action_on_interest, + web3_process_bounty) logger = logging.getLogger(__name__) @@ -139,7 +149,6 @@ def record_bounty_activity(bounty, user, event_name, interest=None): logger.error(f"error in record_bounty_activity: {e} - {event_name} - {bounty} - {user}") - def helper_handle_access_token(request, access_token): # https://gist.github.com/owocki/614a18fbfec7a5ed87c97d37de70b110 # interest API via token @@ -1105,6 +1114,10 @@ def profile(request, handle): """ status = 200 + order_by = request.GET.get('order_by', '-modified_on') + owned_kudos = None + sent_kudos = None + owned_kudos_comments_public = None try: if not handle and not request.user.is_authenticated: @@ -1133,10 +1146,94 @@ def profile(request, handle): }, }, } + return TemplateResponse(request, 'profiles/profile.html', context, status=status) + + context['preferred_payout_address'] = profile.preferred_payout_address + + if context['preferred_payout_address']: + owned_kudos = Token.objects.select_related('kudos_transfer', 'contract').filter( + Q(owner_address__iexact=context['preferred_payout_address']) | + Q(kudos_transfer__recipient_profile=profile), + contract__network=settings.KUDOS_NETWORK + ).distinct('id').order_by('id', order_by) + sent_kudos = Token.objects.select_related('kudos_transfer', 'contract').filter( + Q(kudos_transfer__from_address__iexact=context['preferred_payout_address']) | + Q(kudos_transfer__sender_profile=profile), + contract__network=settings.KUDOS_NETWORK, + ).distinct('id').order_by('id', order_by) + + if owned_kudos: + owned_kudos_comments_public = [] + for kudos_token in owned_kudos: + try: + owned_kudos_comments_public.append(kudos_token.kudos_transfer.comments_public) + except Exception as e: + logger.error(e) + + context['kudos_comments_public'] = owned_kudos_comments_public + context['kudos'] = owned_kudos + context['sent_kudos'] = sent_kudos + + if request.method == 'POST' and request.is_ajax(): + # Send kudos data when new preferred address + address = request.POST.get('address') + context['kudos'] = Token.objects.select_related('kudos_transfer', 'contract').filter( + Q(owner_address__iexact=address) | + Q(kudos_transfer__recipient_profile=profile), + contract__network=settings.KUDOS_NETWORK, + ).distinct('id').order_by('id', order_by) + context['sent_kudos'] = Token.objects.select_related('contract', 'kudos_transfer').filter( + Q(kudos_transfer__from_address__iexact=address) | + Q(kudos_transfer__sender_profile=profile), + contract__network=settings.KUDOS_NETWORK, + ).distinct('id').order_by('id', order_by) + profile.preferred_payout_address = address + kudos_html = loader.render_to_string('shared/profile_kudos.html', context) + try: + profile.save() + except Exception as e: + logger.error(e) + msg = { + 'status': 500, + 'msg': _('Internal server error'), + } + else: + msg = { + 'status': 200, + 'msg': _('Success!'), + 'wallets': [profile.preferred_payout_address, ], + 'kudos_html': kudos_html, + } + + return JsonResponse(msg, status=msg.get('status', 200)) return TemplateResponse(request, 'profiles/profile.html', context, status=status) +def lazy_load_kudos(request): + page = request.POST.get('page', 1) + address = request.POST.get('address') + context = {} + datarequest = request.POST.get('request') + order_by = request.GET.get('order_by', '-modified_on') + limit = int(request.GET.get('limit', 8)) + query_kwargs = {'contract__network': settings.KUDOS_NETWORK} + + if datarequest == 'mykudos': + key = 'kudos' + query_kwargs['owner_address__iexact'] = address + else: + key = 'sent_kudos' + query_kwargs['sent_from_address__iexact'] = address + + context[key] = Token.objects.filter(owner_address__iexact=address, **query_kwargs).order_by(order_by) + paginator = Paginator(context[key], limit) + + kudos = paginator.get_page(page) + kudos_html = loader.render_to_string('shared/kudos_card_profile.html', {'kudos': kudos}) + return JsonResponse({'kudos_html': kudos_html, 'has_next': kudos.has_next()}) + + @csrf_exempt @ratelimit(key='ip', rate='5/m', method=ratelimit.UNSAFE, block=True) def get_quickstart_video(request): @@ -1235,7 +1332,7 @@ def sync_web3(request): # LEGAL - +@xframe_options_exempt def terms(request): context = { 'title': _('Terms of Use'), @@ -1607,3 +1704,40 @@ def get_users(request): raise Http404 mimetype = 'application/json' return HttpResponse(data, mimetype) + + +def get_kudos(request): + autocomplete_kudos = { + 'copy': "No results found. Try these categories: ", + 'autocomplete': ['rare','common','ninja','soft skills','programming'] + } + if request.is_ajax(): + q = request.GET.get('term') + eth_to_usd = convert_token_to_usdt('ETH') + kudos_by_name = Token.objects.filter(name__icontains=q) + kudos_by_desc = Token.objects.filter(description__icontains=q) + kudos_by_tags = Token.objects.filter(tags__icontains=q) + kudos_pks = (kudos_by_desc | kudos_by_name | kudos_by_tags).values_list('pk', flat=True) + kudos = Token.objects.filter(pk__in=kudos_pks).order_by('name') + results = [] + for token in kudos: + kudos_json = {} + kudos_json['id'] = token.id + kudos_json['token_id'] = token.token_id + kudos_json['name'] = token.name + kudos_json['name_human'] = humanize_name(token.name) + kudos_json['description'] = token.description + kudos_json['image'] = token.image + + kudos_json['price_finney'] = token.price_finney / 1000 + kudos_json['price_usd'] = eth_to_usd * kudos_json['price_finney'] + kudos_json['price_usd_humanized'] = f"${round(kudos_json['price_usd'], 2)}" + + results.append(kudos_json) + if not results: + results = [autocomplete_kudos] + data = json.dumps(results) + else: + raise Http404 + mimetype = 'application/json' + return HttpResponse(data, mimetype) diff --git a/app/external_bounties/templates/external_bounties.html b/app/external_bounties/templates/external_bounties.html index 924b13d4ac8..fd8771d6eb0 100644 --- a/app/external_bounties/templates/external_bounties.html +++ b/app/external_bounties/templates/external_bounties.html @@ -11,6 +11,7 @@ {% include 'shared/tag_manager_2.html' %}
          + {% include 'shared/top_nav.html' with class='d-md-flex' %} {% include 'shared/nav.html' %}
          diff --git a/app/external_bounties/templates/external_bounties_new.html b/app/external_bounties/templates/external_bounties_new.html index 5e4c3b36482..613bdc36e7b 100644 --- a/app/external_bounties/templates/external_bounties_new.html +++ b/app/external_bounties/templates/external_bounties_new.html @@ -10,6 +10,7 @@ {% include 'shared/tag_manager_2.html' %}
          + {% include 'shared/top_nav.html' with class='d-md-flex' %} {% include 'shared/nav.html' %}
          {% if msg %} diff --git a/app/external_bounties/templates/external_bounties_show.html b/app/external_bounties/templates/external_bounties_show.html index aba5e8a7f41..c5782fac1b2 100644 --- a/app/external_bounties/templates/external_bounties_show.html +++ b/app/external_bounties/templates/external_bounties_show.html @@ -17,6 +17,7 @@ {% include 'shared/tag_manager_2.html' %}
          + {% include 'shared/top_nav.html' with class='d-md-flex' %} {% include 'shared/nav.html' %}
          diff --git a/app/faucet/templates/faucet_form.html b/app/faucet/templates/faucet_form.html index 7cc329bad9d..a477701e021 100644 --- a/app/faucet/templates/faucet_form.html +++ b/app/faucet/templates/faucet_form.html @@ -25,6 +25,7 @@
          + {% include 'shared/top_nav.html' with class='d-md-flex' %} {% include 'shared/nav.html' %}
          diff --git a/app/kudos/Kudos.json b/app/kudos/Kudos.json new file mode 100644 index 00000000000..c0b1c85dae6 --- /dev/null +++ b/app/kudos/Kudos.json @@ -0,0 +1 @@ +[{"constant":true,"inputs":[{"name":"_interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_tokenId","type":"uint256"}],"name":"approve","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"cloneFeePercentage","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"InterfaceId_ERC165","outputs":[{"name":"","type":"bytes4"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"isMintable","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"exists","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"kudos","outputs":[{"name":"priceFinney","type":"uint256"},{"name":"numClonesAllowed","type":"uint256"},{"name":"numClonesInWild","type":"uint256"},{"name":"clonedFromId","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_tokenId","type":"uint256"},{"name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"}],"name":"OwnershipRenounced","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"},{"indexed":true,"name":"_tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_owner","type":"address"},{"indexed":true,"name":"_approved","type":"address"},{"indexed":true,"name":"_tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_owner","type":"address"},{"indexed":true,"name":"_operator","type":"address"},{"indexed":false,"name":"_approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_priceFinney","type":"uint256"},{"name":"_numClonesAllowed","type":"uint256"},{"name":"_tokenURI","type":"string"}],"name":"mint","outputs":[{"name":"tokenId","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_tokenId","type":"uint256"},{"name":"_numClonesRequested","type":"uint256"}],"name":"clone","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"_owner","type":"address"},{"name":"_tokenId","type":"uint256"}],"name":"burn","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_cloneFeePercentage","type":"uint256"}],"name":"setCloneFeePercentage","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_isMintable","type":"bool"}],"name":"setMintable","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_tokenId","type":"uint256"},{"name":"_newPriceFinney","type":"uint256"}],"name":"setPrice","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"getKudosById","outputs":[{"name":"priceFinney","type":"uint256"},{"name":"numClonesAllowed","type":"uint256"},{"name":"numClonesInWild","type":"uint256"},{"name":"clonedFromId","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"getNumClonesInWild","outputs":[{"name":"numClonesInWild","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getLatestId","outputs":[{"name":"tokenId","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}] \ No newline at end of file diff --git a/app/assets/v2/js/pages/profile_details.js b/app/kudos/__init__.py similarity index 100% rename from app/assets/v2/js/pages/profile_details.js rename to app/kudos/__init__.py diff --git a/app/kudos/admin.py b/app/kudos/admin.py new file mode 100644 index 00000000000..5284b07baba --- /dev/null +++ b/app/kudos/admin.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +"""Define Admin views. + +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 . + +""" + +from django.contrib import admin +from django.utils.html import format_html + +from .models import KudosTransfer, Token, Wallet + + +class GeneralAdmin(admin.ModelAdmin): + ordering = ['-id'] + + +class TransferAdmin(admin.ModelAdmin): + raw_id_fields = ['recipient_profile', 'sender_profile', 'kudos_token'] + ordering = ['-id'] + readonly_fields = ['claim'] + search_fields = ['tokenName', 'comments_public', 'comments_priv', 'from_name', 'username', 'network', 'github_url', 'url', 'emails', 'from_address', 'receive_address'] + + def claim(self, instance): + if instance.web3_type == 'yge': + return 'n/a' + if not instance.txid: + return 'n/a' + if instance.receive_txid: + return 'n/a' + try: + if instance.web3_type == 'v2': + html = format_html('claim', instance.receive_url) + if instance.web3_type == 'v3': + html = format_html(f'claim as recipient') + except Exception: + html = 'n/a' + return html + + +admin.site.register(Token, GeneralAdmin) +admin.site.register(KudosTransfer, TransferAdmin) +admin.site.register(Wallet, GeneralAdmin) diff --git a/app/kudos/forms.py b/app/kudos/forms.py new file mode 100644 index 00000000000..a49f8d1daef --- /dev/null +++ b/app/kudos/forms.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +"""Define Forms. + +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 . + +""" +from django import forms +from django.utils.translation import gettext as _ + + +class KudosSearchForm(forms.Form): + """Form template for kudos search. + + Attributes: + kudos_search (form): Use for kudos search GET request. + """ + kudos_search = forms.CharField(label=_('Kudos Search'), max_length=100) diff --git a/app/kudos/helpers.py b/app/kudos/helpers.py new file mode 100644 index 00000000000..c09e5feaaf9 --- /dev/null +++ b/app/kudos/helpers.py @@ -0,0 +1,101 @@ +# -*- coding: utf-8 -*- +"""Define helper functions. + +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 . + +""" +import logging + +from django.conf import settings +from django.shortcuts import get_object_or_404 + +from eth_utils import is_address, to_checksum_address + +from .models import Contract, Token, Wallet + +logger = logging.getLogger(__name__) + + +def get_token(token_id, network, address): + """Helper to find the kudos.Token primary key, given the contract address and token_id fields. + This function was created so that we can find the kudos token pk, only know the contract and + token_id from the blockchain. This is useful when linking to gitcoin from outside sites such + as Open Sea. + + Args: + token_id (int): The token_id field in the database (from blockchain) + network (str): The ethereum network + address (str): Contract address for this token (from blockchain) + + Returns: + obj or None: Return Django object if found, else None. + + """ + try: + contract = Contract.objects.get( + address=address, + network=network + ) + except Exception as e: + logger.warning(e) + contract = Contract.objects.get( + is_latest=True, + network=network + ) + + return get_object_or_404(Token, contract=contract, token_id=token_id) + + +def reconcile_kudos_preferred_wallet(profile): + """DEPRECATED. + Helper function to set the kudos_preferred_wallet if it doesn't already exist + + Args: + profile (TYPE): Description + + Returns: + str: Profile wallet address. + + """ + # If the preferred_kudos_wallet is not set, figure out how to set it. + if not profile.preferred_kudos_wallet: + # If the preferred_payout_address exists, use it for the preferred_kudos_Wallet + if profile.preferred_payout_address and profile.preferred_payout_address != '0x0': + # Check if the preferred_payout_addess exists as a kudos wallet address + kudos_wallet = profile.wallets.filter(address=profile.preferred_payout_address).first() + if kudos_wallet: + # If yes, set that wallet to be the profile.preferred_kudos_wallet + profile.preferred_kudos_wallet = kudos_wallet + # profile.preferred_kudos_wallet = profile.wallets.filter(address=profile.preferred_payout_address) + else: + # Create the kudos_wallet and set it as the preferred_kudos_wallet in the profile + new_kudos_wallet = Wallet(address=profile.preferred_payout_address) + new_kudos_wallet.save() + profile.preferred_kudos_wallet = new_kudos_wallet + else: + # Check if there are any kudos_wallets available. If so, set the first one to preferred. + kudos_wallet = profile.kudos_wallets.all() + if kudos_wallet: + profile.preferred_kudos_wallet = kudos_wallet.first() + else: + # Not enough information available to set the preferred_kudos_wallet + # Use kudos indrect send. + logger.warning('No kudos wallets or preferred_payout_address address found. Use Kudos Indirect Send.') + return None + + profile.save() + + return profile.preferred_kudos_wallet diff --git a/app/kudos/kudos.yaml b/app/kudos/kudos.yaml new file mode 100644 index 00000000000..3fe075fa1f1 --- /dev/null +++ b/app/kudos/kudos.yaml @@ -0,0 +1,1801 @@ +- name: hadoop_admiral + description: You are a Master of MapReduce, a sultan of reliable, distributed, and + scalable computing. Owners of this badge are infamous for their command of distributing + processing of large data sets! + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 500 + tags: + - hadoop + - distributed + - scalable + - data + - common + image: hadoop_admiral.svg +- name: linux_wizard + description: All hail the Linux Penguin! Linux is a force in open source, powering + millions of websites and businesses. Owners of this badge are known for their + mastery of the Linux family of Operating Systems! + priceFinney: 3 + artist: mladen + platform: gitcoin + numClonesAllowed: 500 + tags: + - linux + - open source + - penguin + - OS + - common + image: linux_wizard.svg +- name: gitcoin_genesis + description: The Gitcoin Genesis Badge is the rarest of the Gitcoin team badges. Owners + of this badge contributed to Gitcoin in a meaningful way in the way-back-when. + priceFinney: 1000 + artist: mladen + platform: gitcoin + numClonesAllowed: 4 + tags: + - gitcoin + - genesis + - rare + image: gitcoin_genesis.svg +- name: javascript_master_scriber + description: Remember the web in the days before javascript? No? Neither can we! Javascript + powers the modern web, top to bottom and we <3 the usage of javascript here at + Gitcoin. Owners of this badge are masters of the asyncronous, event driven, programming + language and specifically, of client side scripting! + priceFinney: 3 + artist: mladen + platform: gitcoin + numClonesAllowed: 500 + tags: + - javascript + - node + - web + - common + image: javascript_master_scriber.svg +- name: infrastructure_ninja + description: Just like every building needs a solid foundation, every website needs + a great infrastructure. Infrastructure Ninjas are rarely seen or heard, but they + are omnipresent -- Quickly tackling the gnarly infrastructure issues that crop + up in the modern web, and ensuring stability, peace, performance, and prosperity + for inhabinants the modern web. + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 300 + tags: + - OS + - infrastructure + - linux + - common + image: infrastructure_ninja.svg +- name: java_doctor + description: Is there anything better than a cup 'o' Joe in the morning? Java can + be written once and run everywhere; so what better tool to BUIDL on in the modern, + blockchain-enabled, web? Owners of the Java Doctor badge are famous for their + mastery of the Java programming language! + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 500 + tags: + - java + - web + - sun + - common + image: java_doctor.svg +- name: do_more_faster + description: Is there anything better than working with someone who can rapidly + iterate? The modern web is built by Agile, and favors experimentation and iteration. Owners + of the Do More Faster badge, well, they DO MORE FASTER! + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 500 + tags: + - do more faster + - iteration + - hypothesis testing + - soft skills + - common + image: do_more_faster.svg +- name: jquery_fixer + description: jQuery is a force in the modern web. By solving compatibilty issues + across browsers, and providing a friendly interface for developing AJAX websites, + jQuery won our <3s. To owners of this badge, thank you for using jQuery to provide + Fixes to all! + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 800 + tags: + - jquery + - javascript + - web + - MVC + - common + image: jquery_fixer.svg +- name: elixer_mixer + description: Elixer Mixers are known for their alchemy. Just as a chemist combines + fundamental chemical primitives to create potions that are near-magic, an Elixer + Mixer combines functional programming with the Erlang VM to to produce low-latency, + fault tolerant, systems! + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 250 + tags: + - elixer + - erlang + - functional + - common + image: elixer_mixer.svg +- name: collaboration_machine + description: Is there anything better than working with a collaboration machine? Known + for their communication skills, rapid value delivery, and great attitudes, Collaboration + Machines are a huge asset to the modern programming ecosystem! + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 300 + tags: + - collaboration + - soft skills + image: collaboration_machine.svg +- name: unix_philosophy + description: Owners of this badge 'Write programs that do one thing and do it well'; + just like the UNIX OS! + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 500 + tags: + - unix + - build once + - common + - OS + image: unix_philosophy.svg +- name: ruby_gem + description: Is there anyone who knows more about 'gem's than someone who's good + enough at Ruby, to be a 'Gem' themselves? Owners of this badge are known for their + mastery of the Ruby programming language. + priceFinney: 5 + artist: mladen + platform: gitcoin + numClonesAllowed: 550 + tags: + - rails + - ruby + - common + - web + - MVC + - DRY + image: ruby_gem.svg +- name: angular_royalty + description: AngularJS is a great extension of javsacript, and we love how it lets + us declare dynamic views for our dApps! Owners of this badge are royalty of + the AngularJS programming framework! + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 500 + tags: + - angular + - javascript + - common + - mvc + - web + image: angular_royalty.svg +- name: qa_ninja + description: Rarely heard or seen, the modern QA Ninja is a hyper-efficient finder + and reporter of bugs. Got a number input on an HTML form? They'll find a way + to type 'LIZARD' into it? Buffer overflow somewhere in your dApp? They'll find + it. QA Ninjas make the web bug free, and we salute them! + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 700 + tags: + - qa + - ninja + - bugs + - common + - bug squasher + image: qa_ninja.svg +- name: code_shipper + description: Know who we LOVE working with? Programmers who are always shipping + code! Always. Be. Shipping. + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 500 + tags: + - shipping + - soft skills + - common + image: code_shipper.svg +- name: drupal_brainiac + description: Want to ship content on the modern web? Drupal is where it's at. The + leading Open Source CMS has provided tons of value to the modern web, and adding + a Drupal Brainiac to your project is a sure fire way to make your CMS fly! + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 500 + tags: + - drupal + - CMS + - web + - common + image: drupal_brainiac.svg +- name: ruby_on_rails_master + description: Can anyone spin up websites faster than a Ruby on Rails Master? Owners + of this badge are legitimately famous for their mastery of MVC website development, + DRY, and use of Active Record. + priceFinney: 4 + artist: mladen + platform: gitcoin + numClonesAllowed: 200 + tags: + - rails + - ruby + - web + - MVC + - common + - DRY + image: ruby_on_rails_master.svg +- name: open_source_freedom_fighter + description: Hey, look -- In the sky, it's a bird. No it's a plane. No it's an + Open Source Freedom Fighter! OSS Freedom Fighters fight for liberty, justice, + and open source code for all! + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 500 + tags: + - oss + - common + - soft skills + image: open_source_freedom_fighter.svg +- name: mega_open_collaborator + description: '"Be open to the point of promiscuity" is one of our favorite points + from the famous essay from Eric Raymond entitled "The Cathedral and the Bazaar". Owners + of this badge embody the principle of Openness from the Cathedral and the Bazaar.' + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 500 + tags: + - common + - soft skills + - open + image: mega_open_collaborator.svg +- name: problem_solver + description: Is there anything better than working with someone who can rapidly + solve problems? The modern web is built by Agile, and favors experimentation + and iteration. Owners of this badge, well, they SOLVE PROBLEMS! + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 500 + tags: + - common + - soft skills + image: problem_solver.svg +- name: sustainer + description: Open Source Software is fraught with problems with sustainability. Owners + of this badge are fighting to change to tide and to make Open Source Software + sustainable for generations to come! + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 500 + tags: + - soft skills + - common + - sustainer + - open source + image: sustainer.svg +- name: super_juggler + description: Jugglers are known for their joyous attitude and their ability to manage + multiple balls in the air at once. Owners of this badge can contribute meaningfully + to several projects at once and not let a single one drop! + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 500 + tags: + - soft skills + - common + - project management + image: super_juggler.svg +- name: above_and_beyond + description: Owners of this badge are always under-promising and over-delivering. They + go 'above and beyond' for their clients! + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 500 + tags: + - soft skills + - common + - project management + image: above_and_beyond.svg +- name: new_dawn + description: Owners of this badge have completely changed the course of a project + their on, with their skills, organization, tenacity and sheer ability to deliver. + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 50 + tags: + - common + - soft skills + - momentum + image: new_dawn.svg +- name: design_star + description: Know that feeling early in a project when you're just putting pencil + to paper, figuring out what things are going to look like? Owners of this badge + at Design Stars, delivering tons of value on aesthetics, UX, and otherwise shaping + the very projects they work on! + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 350 + tags: + - design + - common + - star + - aesthetics + - ux + image: design_star.svg +- name: handyman + description: Its great to have a handy man around your house when your sink, plumbing, + electricity, breaks. Owners of this badge are digital handymen and handywomen. They + fix stuff, and do it with a smile on their face! + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 210 + tags: + - soft skills + - programmer + - technical + - handyman + image: handyman.svg +- name: handy_woman + description: Its great to have a someone handy around your house when your sink, + plumbing, electricity, breaks. Owners of this badge are digital handymen and + handywomen. They fix stuff, and do it with a smile on their face! + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 210 + tags: + - soft skills + - programmer + - technical + - handywoman + image: handy_woman.svg +- name: data_savvy + description: Being Data-Driven is an asset in today's world. Owners of this badge + have mastered the abiltiy to gather, cultivate, clean, gain insight, and deliver + value from a dataset + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 500 + tags: + - data + - graphs + - charts + - common + image: data_savvy.svg +- name: idea_person + description: Idea people create value and warmth with the sheer radiance of their + ideas. They think outside the box, they combine left-brain and right brain. They + deliver value by thinking about things in a new way. + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 500 + tags: + - soft skills + - ideas + - project manager + - product manager + - common + image: idea_person.svg +- name: always_shipping + description: Know who we LOVE working with? Programmers who are always shipping + code! Always. Be. Shipping. + priceFinney: 5 + artist: mladen + platform: gitcoin + numClonesAllowed: 500 + tags: + - shipping + - SHIPL + - soft skils + - common + image: always_shipping.svg +- name: c_sharp_programmer + description: Need someone who uses strong typing, declarative, functional, code? Look + no further than the owners of the C# Blacksmith Kudos! + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 500 + tags: + - c# + - programmer + - common + image: c_sharp_programmer.svg +- name: cleanest_code + description: Want to work with someone who is famous for having squeaky clean code? Look + no further than owners of the 'Cleanest Code' Kudos. + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 500 + tags: + - clean code + - programmer + - soft skills + - common + image: cleanest_code.svg +- name: relase_early_and_often + description: Want to work with someone who RERO (Relase Early and Often)? RERO is + a software development philosophy that emphasizes the importance of early and + frequent releases. This creates a tight feedback looop between devs and testers. Want + someone who releases frequently? Owners of this badge are who you'll want to + talk to! + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 300 + tags: + - iteration + - release early + - RERO + - soft skills + - common + image: release_early_and_often.svg +- name: grow_open_source + description: Owners of this Kudos embody Gitcoin's mission of 'Grow Open Source' + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 200 + tags: + - mission + - open source + - sustainer + - common + image: grow_open_source.svg +- name: mongo_db_programmer + description: Want someone who can work efficiently with MongoDB? Look no further + than owners of this badge. + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 500 + tags: + - mongodb + - db + - common + image: mongo_db_programmer.svg +- name: navigator + description: Want to work with someone who can navigate through complexity and deliver + on-time, on-scope, and on-budget? Look no further than owneres of this kudos! + priceFinney: 4 + artist: mladen + platform: gitcoin + numClonesAllowed: 300 + tags: + - navigator + - project management + - common + - soft skills + image: direct.svg +- name: fast_turn_around + description: Want someone who ships deliverables quick? Owners of this 'fast turnaround' + kudos are the first place to look! + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 500 + tags: + - soft skills + - fast + - common + - quick + image: fast_turn_around.svg +- name: css_gentle(wo)man + description: CSS is one of the foundations of the modern web. Owners of this badge + are masters of building beautiful, mobile-friendly, products. + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 500 + tags: + - css + - frontend + - common + - html + image: css_gentle(wo)man.svg +- name: night_owl + description: Owners of this badge always seem to be up at night, SHIPling product + to customers. + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 200 + tags: + - night owl + - quirks + image: night_owl.svg +- name: php_superstar + description: PHP -- The og web developers programming language! Know whats cool + about PHP? It's a recursive acronym, "PHP Hypertext Processor". Want a PHP programmer + for your project? Look no further than to owners of this badge! + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 200 + tags: + - php + - programmer + - php6 + - php7 + image: php_superstar.svg +- name: builder_of_a_better_world + description: Owners of this badge are obsessed with BUIDLing a better world than + what came before them. We salute them for their dedication to making things better. + priceFinney: 10 + artist: mladen + platform: gitcoin + numClonesAllowed: 500 + tags: + - soft skills + - common + - inspiration + image: builder_of_a_better_world.svg +- name: c_debugger + description: Need a programmer for your performant, object oriented, project that + can manage their own memory and manage on-scope and on-budget!? Look no further; + Owners of this badge are renown for their work in the C programming language. + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 300 + tags: + - c + - memory management + - programming + image: c_debugger.svg +- name: redux_programmer + description: Need someone who can deliver value in Redux? Owners of this badge + are renown for their ability to work effciently in Redux. + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 200 + tags: + - redux + - react + image: redux_programmer.svg +- name: ruby_on_rails_machine + description: Can anyone spin up websites faster than a Ruby on Rails hacker? Owners + of this badge are famous for their mastery of MVC website development, DRY, and + use of Active Record. + priceFinney: 5 + artist: mladen + platform: gitcoin + numClonesAllowed: 550 + tags: + - rails + - common + - ruby + - web + - MVC + - DRY + image: ruby_on_rails_machine.svg +- name: helping_hand + description: Need a helping hand for your project. Start with an owner of this + 'Helping Hand' badge! + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 50 + tags: + - helping hand + - soft skills + - helpful + image: helping_hand.svg +- name: node_js_wizard + description: Remember the bad old days in the web before javascript? Javascript + powers the modern web, top to bottom and we <3 the usage of javascript here at + Gitcoin. Owners of this badge are masters of the asyncronous, event driven, programming + language and specifically, of server side scripting! + priceFinney: 4 + artist: mladen + platform: gitcoin + numClonesAllowed: 300 + tags: + - javascript + - nodeJS + - common + - node + - asyncronous + image: node_js_wizard.svg +- name: c++_scientist + description: Need a programmer for your performant, object oriented, project that + can manage their own memory and manage on-scope and on-budget!? Look no further; + Owners of this badge are renown for their work in the C++ programming language. + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 300 + tags: + - c++ + - c + - memory management + - common + - programming + image: c++_scientist.svg +- name: pythonista + description: Pythonistas are loyal users of the Python programming language. + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 300 + tags: + - python + - pythonista + image: pythonista.svg +- name: level_up + description: Owners of this badge are known for their ability to Level Up the teams + and projects they work on + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 500 + tags: + - soft skills + - common + - programmer + image: level_up.svg +- name: delegation_machine + description: Owners of this badge are known for their ability to clearly articulate + requirements, to work with collaborators of all types, and to product value in + a team atmosphere! + priceFinney: 5 + artist: mladen + platform: gitcoin + numClonesAllowed: 300 + tags: + - delegate + - team + - common + - soft skills + image: delegation_machine.svg +- name: arts_and_farts + description: Need someone who is going to create beautiful designs of any kind? Check + out the owners of the 'Arts and Farts' Kudos. + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 100 + tags: + - arts + - design + - frontend + - aesthetics + image: arts_and_farts.svg +- name: react_reactor + description: React is a force in the modern web, and so are those who can yield + it. Owners of this badge have demonstrated proficiency in React on a past project. + priceFinney: 3 + artist: mladen + platform: gitcoin + numClonesAllowed: 400 + tags: + - react + - javascript + - common + - programming + image: react_reactor.svg +- name: html_celebrity + description: Looking for someone who writes clean, standards-compliant, HTML? Look + no further than this HTML Celebrity kudos. + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 500 + tags: + - html + - frontend + - standards-compliant + image: html_celebrity.svg +- name: eye_for_detail + description: Looking for someone who has a great eye for detail? Look no further + than this eye for detail kudos badge. + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 50 + tags: + - design + - details + - soft skills + image: eye_for_detail.svg +- name: ember_master + description: Ember is a great extension of javsacript, and we love how it lets use + declare dynamic views for our dApps! Owners of this badge are masters of the + Ember programming framework! + priceFinney: 6 + artist: mladen + platform: gitcoin + numClonesAllowed: 300 + tags: + - ember + - javascript + image: ember_master.svg +- name: flying_pony + description: Flying Ponies take risks, inspire other ponies to think big to achieve + big ideas. We turn lofty ideas into something tangible. We are fearless about + the outcome, sometimes to our own detriment. + priceFinney: 3 + artist: mladen + platform: gitcoin + numClonesAllowed: 342 + tags: + - pony + - risks + - common + - ideas + - dreamer + image: flying_pony.svg +- name: bee_of_all_trades + description: Are you a cross-pollinator? Do you deliver value in a lot of places + at once? This 'Bee of all trades' badge is for you! + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 200 + tags: + - soft skills + - cross-pollinator + image: bee_of_all_trades.svg +- name: mysql_hero + description: MySQL is a great asset to modern web developers. Looking for someone + who knows MySQL? This badge is for you. + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 100 + tags: + - mysql + - database + - db + image: mysql_hero.svg +- name: app_dev_all_star + description: Looking for an all star app developer? This badge is for you. + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 340 + tags: + - app + - common + - web + - programmer + image: app_dev_all_star.svg +- name: go_developer + description: Looking for someone who can Go Go Go and BUIDL in Go? This kudos is + for you. + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 200 + tags: + - go + - programmer + image: go_developer.svg +- name: product_wizard + description: Looking for someone to put on their product wizard's cap and deliver + massive value to your project? This kudos is for you! + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 500 + tags: + - product + - common + - soft skills + image: product_wizard.svg +- name: business_minded + description: Looking for someone who can deliver the goods from a business side + of things? Look no further than owners of this 'business minded' kudos. + priceFinney: 3 + artist: mladen + platform: gitcoin + numClonesAllowed: 340 + tags: + - business + - common + - soft skills + image: business_minded.svg +- name: bug_squasher + description: Splat goes the bug! Owners of this badge are proficient at squashing + bugs. + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 500 + tags: + - bugs + - common + - soft skills + image: bug_squasher.svg +- name: shill_ethereum + description: For your friends & family who just love to shill Ethereum + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 500 + tags: + - ethereum + - shills + image: shill_ethereum.svg +- name: shill_colorado + description: For your friends & family who just love to shill Colorado + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 500 + tags: + - colorado + - common + - shills + image: shill_colorado.svg +- name: devcon_4 + description: For your friends & family who came to Devcon 4 with you. + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 500 + tags: + - devcon + - ethereum + - common + - shills + image: devcon_4.svg +- name: django_pony + description: Flying Ponies take risks, inspire other ponies to think big to achieve + big ideas. We turn lofty ideas into something tangible. We are fearless about + the outcome, sometimes to our own detriment. + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 77 + tags: + - django + - programmer + image: django_pony.svg +- name: blockchain_utopia + description: Got a Utopian vision for a blockchain-ized world? This badge is for + you. + priceFinney: 5 + artist: mladen + platform: gitcoin + numClonesAllowed: 55 + tags: + - soft skills + - vision + - inspiration + image: blockchain_utopia.svg +- name: collaboration_robot + description: Collab Robots push the envelope. They make connections and find ways + to build new ideas. With our powers, we can develop collabs with the smallest + or largest machines. + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 400 + tags: + - collboration + - common + - soft skills + image: collaboration_robot.svg +- name: path_finder + description: "Pathfinders are masters of navigation, able to pave ways forward without\ + \ hesitation. The amount of trees or woods are no concern - we won\u2019t rest\ + \ until the right path has been uncovered." + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 60 + tags: + - soft skills + - path + - finder + image: path_finder.svg +- name: to_the_moon + description: This kudos is for users who are taking the ecosystem to the moon! + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 400 + tags: + - soft skills + - common + image: climb_the_ladder.svg +- name: gitcoin_sustainer + description: A very special, limited edition, Kudos, for sustainers of Gitcoin. + priceFinney: 10 + artist: mladen + platform: gitcoin + numClonesAllowed: 50 + tags: + - gitcoin + - mission + - grow open source + image: gitcoin_sustainer.svg +- name: craftsman + description: Know a crafts-man? A craftsperson kudos is a great way to celebrate + the tools we use and the people that use them! + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 100 + tags: + - soft skills + - programmer + image: craftsman.svg +- name: struck_oil + description: Know someone who just unlocks value all the time? Send them the 'struck + oil' Kudos! + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 100 + tags: + - soft skills + - oil + - value + image: struck_oil.svg +- name: freedom + description: Is there someone out there who is creating a better world? A more free + world? Send them the 'freedom' kudos! + priceFinney: 3 + artist: mladen + platform: gitcoin + numClonesAllowed: 70 + tags: + - freedom + - soft skills + - inspiration + image: freedom.svg +- name: focus + description: Know someone who has extremely good focus? Send them a 'kudos' kudos. + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 20 + tags: + - focus + - soft skills + image: focus.svg +- name: powertool_user + description: Know someone who's great at setting up and using power tools!? Send + them a powertool user kudos. + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 400 + tags: + - powertools + - tools + - first_mint + image: powertool_user.svg +- name: party_robot + description: Is one of your teammates just a lot of fun to be around? Send them + a Party Robot Kudos. + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 500 + tags: + - party + - common + - fun + - soft skills + image: party_robot.svg +- name: release_early_and_often + description: With the goal of releasing in mind, we help sustain the ecosystem by + shipping quickly to learn quickly. + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 100 + tags: + - soft skills + - agile + image: release_early_and_often.svg +- name: direct + description: Holders of this badge seek the most straightforward ways to solve problem. + Our great challenge is finding the shortest path to the truth + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 55 + tags: + - direct + - path + - navigator + image: direct.svg +- name: crystal_ball + description: "A crystal ball is just a way to predict the future, but hidden inside\ + \ is a compelling story. Crystal Ball holders are visionaries that transform what\u2019\ + s happening into an understandable future." + priceFinney: 15 + artist: mladen + platform: gitcoin + numClonesAllowed: 70 + tags: + - soft skills + - vision + - inspiration + image: growoss_crystalball.svg +- name: gitter_of_coins + description: For the contributors on the platform that, well... , GIT coins. + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 500 + tags: + - git + - common + - coins + - money + image: gitter_of_coins.svg +- name: mana_from_heavens + description: Open Source Software is mana from the heavens. Celebrate someone who's + provided value to your lift with this Kudos badge. + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 200 + tags: + - mana + - fun + image: mana_from_heavens.svg +- name: gitcoin_bot + description: Just for fun, this Gitcoin Robot is a way of celebrating the contributors + in your life. + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 400 + tags: + - robot + - gitcoin + - just for fun + image: robot_medium.svg +- name: heros_honour + description: Know someone who's a hero? Send them this video-game-inspired, badge. + priceFinney: 4 + artist: mladen + platform: gitcoin + numClonesAllowed: 77 + tags: + - hero + - honour + - honor + - soft skills + image: heros_honour.svg +- name: blockchain_the_world + description: Know someone who's blockchain-izing the world? Send them this badge. + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 500 + tags: + - blockchain + - common + - soft skills + image: blockchain_the_world.svg +- name: gitcoin_minibot + description: Just for fun, this Gitcoin Robot is a way of celebrating the contributors + in your life. + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 100 + tags: + - robot + - just for fun + image: robot_small.svg +- name: firefighter + description: Know someone who's great at putting out fires? This firefighter badge + is for them! + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 200 + tags: + - firefigheter + - bugs + image: firefighter.svg +- name: gitcoin_sun + description: A very special, limited edition, Kudos, only for sustainers of Gitcoin. + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 300 + tags: + - sustainers + - gitcoin + - common + - just for fun + image: gitcoin_rasta.svg +- name: big_bot + description: Just for fun, this Gitcoin Robot is a way of celebrating the contributors + in your life. + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 100 + tags: + - robot + - just for fun + - gitcoin + image: robot_large.svg +- name: genius + description: A Genius bring ideas to life. We activate creative thinking and push + problem solving with our words and stories. The world is our experiment lab, and + we are players in it. + priceFinney: 25 + artist: mladen + platform: gitcoin + numClonesAllowed: 100 + tags: + - genius + - albert einstein + - smart + image: a_genius.svg +- name: vitalik_genesis + description: A kudos that celebrates Vitalik's leadership in the Ethereum world. One + day, Gitcoin founder @owocki hopes to work up the courage to give this Kudos to + Vitalik. Perhaps Vitalik will tweet about Gitcoin one day, and @owocki will send + it to him then.... + priceFinney: 100 + artist: mladen + platform: gitcoin + numClonesAllowed: 55 + tags: + - vitalik + - just for fun + image: vitalik_genesis.svg +- name: sunburst + description: This person bring Gitcoin sunshine to OSS projects. We energize the + project with what we do. + priceFinney: 3 + artist: mladen + platform: gitcoin + numClonesAllowed: 55 + tags: + - sunshine + - oss + - energy + image: sunburst.svg +- name: simplifier + description: This badge is for anyone who creates simplicity from complexity. + priceFinney: 5 + artist: mladen + platform: gitcoin + numClonesAllowed: 45 + tags: + - ethereum + - simple + image: ethereum_constellation.svg +- name: tools + description: This kudos is for the person creates the best tools! + priceFinney: 1 + artist: mladen + platform: gitcoin + numClonesAllowed: 1000 + tags: + - tools + - common + - oss + image: tools.svg +- name: hard_worker + description: Hard workers are diligent and vigilent at doing the best they can on + everything they do. + priceFinney: 5 + artist: mladen + platform: gitcoin + numClonesAllowed: 100 + tags: + - hard worker + - achievement + - buidl + image: hard_worker.svg +- name: blockchain_engineer + description: This kudos is for contributors to your project that make the blockchain + work! + priceFinney: 5 + artist: mladen + platform: gitcoin + numClonesAllowed: 25 + tags: + - star + - rise + image: blockchain_star.svg +- name: gitcoin_og + description: You are an OG. You are a pioneer of Gitcoin open source! + priceFinney: 10 + artist: mladen + platform: gitcoin + numClonesAllowed: 100 + tags: + - og + - gitcoin + - early + image: west.svg +- name: rubber_ducky + description: A ducky that helps solve your problems! Always ask your ducky first + when you can't figure something out :) + priceFinney: 5 + artist: mladen + platform: gitcoin + numClonesAllowed: 110 + tags: + - duck + - coding + - problem solver + image: coding_ducky.svg +- name: django_cowboy + description: Faster than fast on django. Better than the best. HODLers of this + badge are great at creating beautiful apps in django! + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 100 + tags: + - django + - fast + - developer + image: django_cowboy.svg +- name: fontend_wizard + description: A frontend wizard mixes things up to create a beautiful UX. + priceFinney: 3 + artist: mladen + platform: gitcoin + numClonesAllowed: 100 + tags: + - frontend + - creative + image: frontend_alchemist.svg +- name: backend_star + description: A shining star of all things hidden in the backend of applications. + priceFinney: 3 + artist: mladen + platform: gitcoin + numClonesAllowed: 110 + tags: + - star + - backend + image: backend_star.svg +- name: squahser_of_bugs + description: A bug squasher makes bugs dissapear like magic. + priceFinney: 4 + artist: mladen + platform: gitcoin + numClonesAllowed: 80 + tags: + - bugs + - clean code + - magic + image: bug_squasher_new.svg +- name: freedom + description: This bird is free to work on what it wants, when it wants. Making impact + where they feel necessary, and always having leverage over your life? Then this + kudos is for you! + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 55 + tags: + - birds + - freedom + - impact + - oss + image: birds.svg +- name: out_of_this_world_programmer + description: A programmer that moves the ecosystem forward and out of this world. + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 55 + tags: + - programmer + - development + image: out_of_this_world_programmer.svg +- name: good_communicator + description: Holders of this badge are great communicators that help to clarify + any situation. + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 55 + tags: + - communication + - clear + image: good_communicator.svg +- name: gitcoin_tree + description: A tree that sustains open source. Just for fun + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 55 + tags: + - oss + - grow open source + - fun + image: gitcoin_tree.svg +- name: status_hackathon_2018_games_track_first_prize + description: For the winner of the Status Hackathon Games Track + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 2 + tags: + - status hackathon + - special event + image: games_first.svg +- name: status_hackathon_2018_marketplace_track_second_prize + description: For the runner up of the Status Hackathon Marketplace Track + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 2 + tags: + - status hackathon + - special event + image: marketplaces_runner_up.svg +- name: status_hackathon_2018_traveltrack_second_prize + description: For the runner up of the Status Hackathon Travel Track + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 2 + tags: + - status hackathon + - special event + image: travel_runner_up.svg +- name: status_hackathon_2018_travel_track_first_prize + description: For the winner of the Status Hackathon Travel Track + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 2 + tags: + - status hackathon + - special event + image: travel_first.svg +- name: status_hackathon_2018__games_second_prize + description: For the runner up of the Status Hackathon Games Track + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 2 + tags: + - status hackathon + - special event + image: games_runner_up.svg +- name: philosophers_stone + description: For whomever makes the greatest contribution to the Status Hackathon + Philospher Circle at the Status Hackathon 2018 + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 2 + tags: + - status hackathon + - special event + image: philosophers.svg +- name: status_hackathon_2018_travel_social_first_prize + description: For the winner of the Status Hackathon Social Track + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 2 + tags: + - status hackathon + - special event + image: social_first.svg +- name: status_hackathon_2018_marketplace_first_prize + description: For the winner of the Status Hackathon Marketplace Track + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 2 + tags: + - special event + - status hackathon + image: market_first.svg +- name: status_hackathon_2018_social_second_prize + description: For the runner up of the Status Hackathon Social Track + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 2 + tags: + - status hackathon + - special event + image: social_runner_up.svg +- name: gitcoin_love + description: This kudos is for showing appreciation for someone who did some work + that you love + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 55 + tags: + - gitcoin + - results + image: gitcoin_rasta.svg +- name: status_hackathon_2018_wildcard + description: Winner of the wildcard prize at the Status Hackahton 2018 + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 2 + tags: + - status hackathon + image: wildcard.svg +- name: fast_response + description: For those communicators who are reliable and always quickly responding + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 55 + tags: + - soft skills + - fast response + image: fast_response.svg +- name: eth_hacker + description: You create value out of bits as an ETH Hacker! + priceFinney: 5 + artist: mladen + platform: gitcoin + numClonesAllowed: 23 + tags: + - eth + - blockchain + - hacker + image: eth_hacker2.svg +- name: backend_architect + description: Limited Edition Cellarius Kudos! A backend architect is not only the + keeper of the ins and outs but also the holder of information and the intricacies + of a system. + priceFinney: 100 + artist: Octavian + platform: gitcoin + numClonesAllowed: 25 + tags: + - rare + - architect + - plan + - backend + image: cellarius/backend_architect.svg +- name: bug_eliminator + description: Limited Edition Cellarius Kudos! A bug eliminator skill is core to + an efficient system or service. They effortlessly remove and resolve any bug with + speed. + priceFinney: 150 + artist: Octavian + platform: gitcoin + numClonesAllowed: 25 + tags: + - rare + - bug + - squasher + - eliminator + - problem solver + - cellarius + image: cellarius/bug_eliminator.svg +- name: bug_finder + description: Limited Edition Cellarius Kudos! These holders are insightful, and + easily spot and solve the very hidden problems unseen to the naked eye. + priceFinney: 150 + artist: Octavian + platform: gitcoin + numClonesAllowed: 25 + tags: + - rare + - bug + - problem solver + - cellarius + - troubleshoot + image: cellarius/bug_finder.svg +- name: lightning_fast + description: Limited Edition Cellarius Kudos! The holder of this badge needs no + introduction. Work is completed quickly as is a flash of lightning. + priceFinney: 100 + artist: Octavian + platform: gitcoin + numClonesAllowed: 25 + tags: + - rare + - fast + - quick + - turnaround + - speed + - cellarius + image: cellarius/lightning_fast.svg +- name: oddjobs + description: Limited Edition Cellarius Kudos! Holders of these badges are highly + skilled at many things. Their talents are unlimited and sometimes at odds on the + spectrum of skills. + priceFinney: 100 + artist: Octavian + platform: gitcoin + numClonesAllowed: 25 + tags: + - rare + - cellarius + - skilled + - multi-task + - well-rounded + image: cellarius/oddjobs.svg +- name: trusted_contributor + description: Limited Edition Cellarius Kudos!A trusted contributor checks all the + boxes of being not only an expert in their domain but reliable and dependable. + They thrive on being called upon and fulfilling any tasked mission. + priceFinney: 100 + artist: Octavian + platform: gitcoin + numClonesAllowed: 35 + tags: + - rare + - trusted + - developer + - contributor + - reliable + - cellarius + image: cellarius/trusted_contributor.svg +- name: burst_of_energy + description: Limited Edition Cellarius Kudos! This kudos is for the contributors + to your repo that are a burst of energy! + priceFinney: 150 + artist: Octavian + platform: gitcoin + numClonesAllowed: 35 + tags: + - rare + - cellarius + - energy + image: cellarius/Burst.svg +- name: impossible_object + description: Limited Edition Cellarius Kudos! This kudos is just for fun. If anyone + in your repo is impossibly great contributor, send them this kudos! + priceFinney: 100 + artist: Octavian + platform: gitcoin + numClonesAllowed: 35 + tags: + - rare + - cellarius + - just for fun + image: cellarius/Circle.svg +- name: diamond + description: Limited Edition Cellarius Kudos! This kudos is for any contributor + who is a diamond! + priceFinney: 200 + artist: Octavian + platform: gitcoin + numClonesAllowed: 35 + tags: + - rare + - cellarius + - diamond + image: cellarius/Diamond.svg +- name: heart + description: Limited Edition Cellarius Kudos! This one is for contributors who + show a lot of heart! + priceFinney: 200 + artist: Octavian + platform: gitcoin + numClonesAllowed: 35 + tags: + - rare + - cellarius + - heart + - soft skills + image: cellarius/heart.svg +- name: infinite_energy + description: Limited Edition Cellarius Kudos! This kudos is for contributors who + are infinite sources of energy to your project! + priceFinney: 150 + artist: Octavian + platform: gitcoin + numClonesAllowed: 35 + tags: + - cellarius + - rare + - energy + - gumption + image: cellarius/Infinite.svg +- name: creative + description: Limited Edition Cellarius Kudos! This kudos is for the squiggles, + not the lines. If your contributor is very creative, send them this kudos! + priceFinney: 150 + artist: Octavian + platform: gitcoin + numClonesAllowed: 35 + tags: + - cellarius + - rare + - creative + - skills + image: cellarius/Spaghetti.svg +- name: foundation + description: Limited Edition Cellarius Kudos! This kudos is for those who lay a + solid foundation. + priceFinney: 100 + artist: Octavian + platform: gitcoin + numClonesAllowed: 35 + tags: + - cellarius + - rare + - foundation + image: cellarius/Triangle.svg +- name: Best use of Fission -- ETHMagicians Prague 2018 + description: This kudos is for the Best use of Fission -- ETHMagicians Prague 2018 + artist: mladen + priceFinney: 1 + artist: mladen + platform: gitcoin + numClonesAllowed: 2 + tags: + - ethmagicians + - prague + - special event + image: fission_color.svg +- name: Best use of Universal Logins -- ETHMagicians Prague 2018 + description: This kudos is for the Best use of Universal Logins -- ETHMagicians Prague 2018 + priceFinney: 1 + artist: mladen + platform: gitcoin + numClonesAllowed: 2 + tags: + - ethmagicians + - prague + - special event + image: logins_color.svg +- name: Awesome Participant -- ETHMagicians Prague 2018 + description: This kudos is for the Awesome Participant -- ETHMagicians Prague 2018 + priceFinney: 1 + artist: mladen + platform: gitcoin + numClonesAllowed: 2 + tags: + - ethmagicians + - prague + - special event + image: participant_color.svg +- name: Scribe -- ETHMagicians Prague 2018 + description: This kudos is for the Scribe kudos award -- ETHMagicians Prague 2018 + priceFinney: 1 + artist: mladen + platform: gitcoin + numClonesAllowed: 2 + tags: + - ethmagicians + - prague + - special event + image: scirbe_color.svg +- name: Best use of 1337 Subscriptions -- ETHMagicians Prague 2018 + description: This kudos is for the Best use of 1337 Subscriptions -- ETHMagicians Prague 2018 + priceFinney: 1 + artist: mladen + platform: gitcoin + numClonesAllowed: 2 + tags: + - ethmagicians + - prague + - special event + image: subscription_color.svg +- name: Volunteer Organizer Award -- ETHMagicians Prague 2018 + description: This kudos is for the Volunteer Organizer Award -- ETHMagicians Prague 2018 + priceFinney: 1 + artist: mladen + platform: gitcoin + numClonesAllowed: 2 + tags: + - ethmagicians + - prague + - special event + image: volunteer_color.svg +- name: Best Use Of Wallet Standards -- ETHMagicians Prague 2018 + description: This kudos is for the Best Use Of Wallet Standards -- ETHMagicians Prague 2018 + priceFinney: 1 + artist: mladen + platform: gitcoin + numClonesAllowed: 2 + tags: + - ethmagicians + - prague + - special event + image: wallet_color.svg +- name: magical_unicorn + description: Know someone who's contributions are magical? Send them this kudos to celebrate their contributions :) + priceFinney: 2 + numClonesAllowed: 100 + tags: + - unicorn + - magic + image: magic_unicorn.svg + platform: gitcoin +- name: red_stapler + description: "Has anyone seen my stapler?" + priceFinney: 1 + numClonesAllowed: 200 + tags: + - stapler + - just for fun + image: red_stapler.svg + platform: gitcoin +- name: shillin_like_a_villian + description: Know someone who so good at shillin' that they're shillin like a Villian? This Kudos is for them! + priceFinney: 1 + numClonesAllowed: 100 + tags: + - shillin + - shill + - funny + image: shillin_like_a_villian.svg +- name: shillville + description: Every Shill down in Shillville likes Open Source a lot. This Shillville badge is for the Shills in your life~! + priceFinney: 1 + numClonesAllowed: 100 + tags: + - shill + - shillville + - open source + platform: gitcoin + image: shillville.svg +- name: Kauri Pioneer + description: Cheers to you, one of the first Kauri contributors! + priceFinney: 3 + numClonesAllowed: 100 + tags: + - web3 + - kauri + - ethereum + - documentation + - knowledge + image: kauri_1.svg + to_address: 0xF8aE578d5d4e570De6c31F26D42eF369C320aE0b +- name: Web3 Advocate + description: Out with the old and in with the new! Kudos to knowledge sharers, crossing the void from web2 to web3. + priceFinney: 3 + numClonesAllowed: 100 + tags: + - web3 + - kauri + - ethereum + - documentation + - knowledge + image: kauri_2.svg + to_address: 0xF8aE578d5d4e570De6c31F26D42eF369C320aE0b + + diff --git a/app/kudos/kudos_mainnet.yaml b/app/kudos/kudos_mainnet.yaml new file mode 100644 index 00000000000..aa56482aacb --- /dev/null +++ b/app/kudos/kudos_mainnet.yaml @@ -0,0 +1,180 @@ +- name: powertool_user + description: Know someone who's great at setting up and using power tools!? Send + them a powertool user kudos. + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 400 + tags: + - powertools + - tools + - first_mint + image: powertool_user.svg +- name: status_hackathon_2018_games_track_first_prize + description: For the winner of the Status Hackathon Games Track + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 1 + tags: + - status hackathon + image: games_first.svg +- name: status_hackathon_2018_marketplace_track_second_prize + description: For the runner up of the Status Hackathon Marketplace Track + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 1 + tags: + - status hackathon + image: marketplaces_runner_up.svg +- name: status_hackathon_2018_traveltrack_second_prize + description: lorum + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 1 + tags: + - status hackathon + image: travel_runner_up.svg +- name: status_hackathon_2018_travel_track_first_prize + description: For the winner of the Status Hackathon Travel Track + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 1 + tags: + - status hackathon + image: travel_first.svg +- name: status_hackathon_2018__games_second_prize + description: lorum + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 1 + tags: + - status hackathon + image: games_runner_up.svg +- name: philosophers_stone + description: For whomever makes the greatest contribution to the Status Hackathon + Philospher Circle at the Status Hackathon 2018 + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 1 + tags: + - status hackathon + image: philosophers.svg +- name: status_hackathon_2018_travel_social_first_prize + description: For the winner of the Status Hackathon Social Track + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 1 + tags: + - status hackathon + image: social_first.svg +- name: status_hackathon_2018_social_first_prize + description: lorum + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 1 + tags: + - status hackathon + image: market_first.svg +- name: status_hackathon_2018_social_second_prize + description: For the runner up of the Status Hackathon Social Track + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 1 + tags: + - status hackathon + image: social_runner_up.svg +- name: status_hackathon_2018_wildcard + description: Winner of the wildcard prize at the Status Hackahton 2018 + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 1 + tags: + - status hackathon + image: wildcard.svg +- name: Best use of Fission -- ETHMagicians Prague 2018 + description: This kudos is for the Best use of Fission -- ETHMagicians Prague 2018 + rarity: 20 + priceFinney: 1 + artist: mladen + platform: gitcoin + numClonesAllowed: 1 + tags: + - ethmagicians + - prague + image: fission_color.svg +- name: Best use of Universal Logins -- ETHMagicians Prague 2018 + description: This kudos is for the Best use of Universal Logins -- ETHMagicians Prague 2018 + rarity: 20 + priceFinney: 1 + artist: mladen + platform: gitcoin + numClonesAllowed: 1 + tags: + - ethmagicians + - prague + image: logins_color.svg +- name: Awesome Participant -- ETHMagicians Prague 2018 + description: This kudos is for the Awesome Participant -- ETHMagicians Prague 2018 + rarity: 20 + priceFinney: 1 + artist: mladen + platform: gitcoin + numClonesAllowed: 1 + tags: + - ethmagicians + - prague + image: participant_color.svg +- name: Scribe -- ETHMagicians Prague 2018 + description: This kudos is for the Scribe kudos award -- ETHMagicians Prague 2018 + rarity: 20 + priceFinney: 1 + artist: mladen + platform: gitcoin + numClonesAllowed: 1 + tags: + - ethmagicians + - prague + image: scirbe_color.svg +- name: Best use of 1337 Subscriptions -- ETHMagicians Prague 2018 + description: This kudos is for the Best use of 1337 Subscriptions -- ETHMagicians Prague 2018 + rarity: 20 + priceFinney: 1 + artist: mladen + platform: gitcoin + numClonesAllowed: 1 + tags: + - ethmagicians + - prague + image: subscription_color.svg +- name: Volunteer Organizer Award -- ETHMagicians Prague 2018 + description: This kudos is for the Volunteer Organizer Award -- ETHMagicians Prague 2018 + rarity: 20 + priceFinney: 1 + artist: mladen + platform: gitcoin + numClonesAllowed: 1 + tags: + - ethmagicians + - prague + image: volunteer_color.svg +- name: Best Use Of Wallet Standards -- ETHMagicians Prague 2018 + description: This kudos is for the Best Use Of Wallet Standards -- ETHMagicians Prague 2018 + rarity: 20 + priceFinney: 1 + artist: mladen + platform: gitcoin + numClonesAllowed: 1 + tags: + - ethmagicians + - prague + image: wallet_color.svg diff --git a/app/kudos/kudos_test.yaml b/app/kudos/kudos_test.yaml new file mode 100644 index 00000000000..c57f7626be7 --- /dev/null +++ b/app/kudos/kudos_test.yaml @@ -0,0 +1,120 @@ +- name: hadoop_admiral + description: You are a Master of MapReduce, a sultan of reliable, distributed, and + scalable computing. Owners of this badge are infamous for their command of distributing + processing of large data sets! + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 500 + tags: + - hadoop + - distributed + - scalable + - data + - common + image: hadoop_admiral.svg +- name: linux_wizard + description: All hail the Linux Penguin! Linux is a force in open source, powering + millions of websites and businesses. Owners of this badge are known for their + mastery of the Linux family of Operating Systems! + priceFinney: 3 + artist: mladen + platform: gitcoin + numClonesAllowed: 500 + tags: + - linux + - open source + - penguin + - OS + - common + image: linux_wizard.svg +- name: gitcoin_genesis + description: The Gitcoin Genesis Badge is the rarest of the Gitcoin team badges. Owners + of this badge contributed to Gitcoin in a meaningful way in the way-back-when. + priceFinney: 1000 + artist: mladen + platform: gitcoin + numClonesAllowed: 4 + tags: + - gitcoin + - genesis + - rare + image: gitcoin_genesis.svg +- name: javascript_master_scriber + description: Remember the web in the days before javascript? No? Neither can we! Javascript + powers the modern web, top to bottom and we <3 the usage of javascript here at + Gitcoin. Owners of this badge are masters of the asyncronous, event driven, programming + language and specifically, of client side scripting! + priceFinney: 3 + artist: mladen + platform: gitcoin + numClonesAllowed: 500 + tags: + - javascript + - node + - web + - common + image: javascript_master_scriber.svg +- name: infrastructure_ninja + description: Just like every building needs a solid foundation, every website needs + a great infrastructure. Infrastructure Ninjas are rarely seen or heard, but they + are omnipresent -- Quickly tackling the gnarly infrastructure issues that crop + up in the modern web, and ensuring stability, peace, performance, and prosperity + for inhabinants the modern web. + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 300 + tags: + - OS + - infrastructure + - linux + - common + image: infrastructure_ninja.svg +- name: java_doctor + description: Is there anything better than a cup 'o' Joe in the morning? Java can + be written once and run everywhere; so what better tool to BUIDL on in the modern, + blockchain-enabled, web? Owners of the Java Doctor badge are famous for their + mastery of the Java programming language! + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 500 + tags: + - java + - web + - sun + - common + image: java_doctor.svg +- name: do_more_faster + description: Is there anything better than working with someone who can rapidly + iterate? The modern web is built by Agile, and favors experimentation and iteration. Owners + of the Do More Faster badge, well, they DO MORE FASTER! + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 500 + tags: + - do more faster + - iteration + - hypothesis testing + - soft skills + - common + image: do_more_faster.svg +- name: jquery_fixer + description: jQuery is a force in the modern web. By solving compatibilty issues + across browsers, and providing a friendly interface for developing AJAX websites, + jQuery won our <3s. To owners of this badge, thank you for using jQuery to provide + Fixes to all! + priceFinney: 2 + artist: mladen + platform: gitcoin + numClonesAllowed: 800 + tags: + - jquery + - javascript + - web + - MVC + - common + image: jquery_fixer.svg + diff --git a/app/kudos/management/commands/burn_kudos.py b/app/kudos/management/commands/burn_kudos.py new file mode 100644 index 00000000000..cb62c871d37 --- /dev/null +++ b/app/kudos/management/commands/burn_kudos.py @@ -0,0 +1,68 @@ +"""Define the burn kudos management command. + +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 . + +""" +import logging +import warnings + +from django.conf import settings +from django.core.management.base import BaseCommand + +from kudos.utils import KudosContract + +warnings.filterwarnings("ignore", category=DeprecationWarning) +logging.getLogger("requests").setLevel(logging.WARNING) +logging.getLogger("urllib3").setLevel(logging.WARNING) +logging.getLogger("web3").setLevel(logging.WARNING) + +logger = logging.getLogger(__name__) +formatter = '%(levelname)s:%(name)s.%(funcName)s:%(message)s' +logging.basicConfig(level=logging.DEBUG) + + +class Command(BaseCommand): + + help = 'clone a kudos to an address' + + def add_arguments(self, parser): + parser.add_argument('network', default='localhost', type=str) + parser.add_argument('owner', type=str, help='The ETH address of the kudos.') + parser.add_argument('token_id', type=int, help='The Kudos ID to burn.') + parser.add_argument('--skip_sync', action='store_true') + parser.add_argument('--gitcoin_account', action='store_true', help='use account stored in .env file') + parser.add_argument('--account', help='public account address to use for transaction', type=str) + parser.add_argument('--private_key', help='private key for signing transactions', type=str) + + def handle(self, *args, **options): + # config + network = options['network'] + token_id = options['token_id'] + + skip_sync = options['skip_sync'] + gitcoin_account = options['gitcoin_account'] + if gitcoin_account: + account = settings.KUDOS_OWNER_ACCOUNT + private_key = settings.KUDOS_PRIVATE_KEY + else: + account = options['account'] + private_key = options['private_key'] + + kudos_contract = KudosContract(network=network) + owner = kudos_contract._w3.toChecksumAddress(options['owner']) + + args = (owner, token_id) + kudos_contract.burn(*args, account=account, private_key=private_key, skip_sync=skip_sync) diff --git a/app/kudos/management/commands/clone_kudos.py b/app/kudos/management/commands/clone_kudos.py new file mode 100644 index 00000000000..d9f0e220fa7 --- /dev/null +++ b/app/kudos/management/commands/clone_kudos.py @@ -0,0 +1,69 @@ +"""Define the clone kudos management command. + +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 . + +""" +import logging +import warnings + +from django.conf import settings +from django.core.management.base import BaseCommand + +from kudos.utils import KudosContract + +warnings.filterwarnings("ignore", category=DeprecationWarning) +logging.getLogger("requests").setLevel(logging.WARNING) +logging.getLogger("urllib3").setLevel(logging.WARNING) +logging.getLogger("web3").setLevel(logging.WARNING) + +logger = logging.getLogger(__name__) +logging.basicConfig(level=logging.INFO) + + +class Command(BaseCommand): + + help = 'clone a kudos to an address' + + def add_arguments(self, parser): + parser.add_argument('network', default='localhost', type=str) + parser.add_argument('clone_to', type=str, help='The ETH address to clone to.') + parser.add_argument('token_id', type=int, help='The Kudos ID to clone.') + parser.add_argument('--numClonesRequested', default=1, type=str) + parser.add_argument('--skip_sync', action='store_true') + parser.add_argument('--gitcoin_account', action='store_true', help='use account stored in .env file') + parser.add_argument('--account', help='public account address to use for transaction', type=str) + parser.add_argument('--private_key', help='private key for signing transactions', type=str) + + def handle(self, *args, **options): + # config + network = options['network'] + token_id = options['token_id'] + # to = options['to'] + numClonesRequested = options['numClonesRequested'] + skip_sync = options['skip_sync'] + gitcoin_account = options['gitcoin_account'] + if gitcoin_account: + account = settings.KUDOS_OWNER_ACCOUNT + private_key = settings.KUDOS_PRIVATE_KEY + else: + account = options['account'] + private_key = options['private_key'] + + kudos_contract = KudosContract(network=network) + clone_to = kudos_contract._w3.toChecksumAddress(options['clone_to']) + + args = (clone_to, token_id, numClonesRequested) + kudos_contract.clone(*args, account=account, private_key=private_key, skip_sync=skip_sync) diff --git a/app/kudos/management/commands/mint_all_kudos.py b/app/kudos/management/commands/mint_all_kudos.py new file mode 100644 index 00000000000..91187a4047a --- /dev/null +++ b/app/kudos/management/commands/mint_all_kudos.py @@ -0,0 +1,171 @@ +"""Define the mint all kudos management command. + +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 . + +""" +import logging +import time +import urllib +import warnings + +from django.conf import settings +from django.core.management.base import BaseCommand + +import oyaml as yaml +from kudos.utils import KudosContract, get_rarity_score, humanize_name + +warnings.filterwarnings("ignore", category=DeprecationWarning) +logging.getLogger("requests").setLevel(logging.WARNING) +logging.getLogger("urllib3").setLevel(logging.WARNING) +logging.getLogger("web3").setLevel(logging.WARNING) + +logger = logging.getLogger(__name__) +formatter = '%(levelname)s:%(name)s.%(funcName)s:%(message)s' + + +class Command(BaseCommand): + + help = 'mints the initial kudos gen0 set' + + def add_arguments(self, parser): + parser.add_argument('network', default='localhost', type=str) + parser.add_argument('yaml_file', help='absolute path to kudos.yaml file', type=str) + parser.add_argument('--mint_to', help='address to mint the kudos to', type=str) + parser.add_argument('--gas_price_gwei', help='the gas price for mining', type=int) + parser.add_argument('--skip_sync', action='store_true') + parser.add_argument('--gitcoin_account', action='store_true', help='use account stored in .env file') + parser.add_argument('--account', help='public account address to use for transaction', type=str) + parser.add_argument('--private_key', help='private key for signing transactions', type=str) + parser.add_argument('--debug', help='turn on debug statements', action='store_true') + + def handle(self, *args, **options): + # config + if options['debug']: + logging.basicConfig(level=logging.DEBUG) + else: + logging.basicConfig(level=logging.INFO) + network = options['network'] + gitcoin_account = options['gitcoin_account'] + gas_price_gwei = options['gas_price_gwei'] + + if gitcoin_account: + account = settings.KUDOS_OWNER_ACCOUNT + private_key = settings.KUDOS_PRIVATE_KEY + else: + account = options['account'] + private_key = options['private_key'] + skip_sync = options['skip_sync'] + + kudos_contract = KudosContract(network=network) + + yaml_file = options['yaml_file'] + + with open(yaml_file) as f: + all_kudos = yaml.load(f) + + for __, kudos in enumerate(all_kudos): + image_name = urllib.parse.quote(kudos.get('image')) + if image_name: + # Support Open Sea + if kudos_contract.network == 'rinkeby': + image_path = 'https://ss.gitcoin.co/static/v2/images/kudos/' + image_name + external_url = f'https://stage.gitcoin.co/kudos/{kudos_contract.address}/{kudos_contract.getLatestId() + 1}' + elif kudos_contract.network == 'mainnet': + image_path = 'https://s.gitcoin.co/static/v2/images/kudos/' + image_name + external_url = f'https://gitcoin.co/kudos/{kudos_contract.address}/{kudos_contract.getLatestId() + 1}' + elif kudos_contract.network == 'localhost': + image_path = 'v2/images/kudos/' + image_name + external_url = f'http://localhost:8000/kudos/{kudos_contract.address}/{kudos_contract.getLatestId() + 1}' + else: + raise RuntimeError('Need to set the image path for that network') + else: + image_path = '' + + attributes = [] + # "trait_type": "investor_experience", + # "value": 20, + # "display_type": "boost_number", + # "max_value": 100 + rarity = { + "trait_type": "rarity", + "value": get_rarity_score(kudos['numClonesAllowed']), + } + attributes.append(rarity) + + artist = { + "trait_type": "artist", + "value": kudos.get('artist') + } + attributes.append(artist) + + platform = { + "trait_type": "platform", + "value": kudos.get('platform') + } + attributes.append(platform) + + tags = kudos['tags'] + price_finney = kudos['priceFinney'] + + # append tags + if price_finney < 2: + tags.append('budget') + if price_finney < 5: + tags.append('affordable') + if price_finney > 20: + tags.append('premium') + if price_finney > 200: + tags.append('expensive') + + for tag in tags: + if tag: + tag = { + "trait_type": "tag", + "value": tag + } + attributes.append(tag) + + metadata = { + 'name': humanize_name(kudos['name']), + 'image': image_path, + 'description': kudos['description'], + 'external_url': external_url, + 'background_color': 'fbfbfb', + 'attributes': attributes + } + + if not options['mint_to']: + mint_to = kudos_contract._w3.toChecksumAddress(settings.KUDOS_OWNER_ACCOUNT) + else: + mint_to = kudos_contract._w3.toChecksumAddress(options['mint_to']) + + for x in range(1, 4): + try: + tokenURI_url = kudos_contract.create_tokenURI_url(**metadata) + args = (mint_to, kudos['priceFinney'], kudos['numClonesAllowed'], tokenURI_url) + kudos_contract.mint( + *args, + account=account, + private_key=private_key, + skip_sync=skip_sync, + gas_price_gwei=gas_price_gwei, + ) + except Exception as e: + logger.error('Error: %s - Trying to mint again' % e) + time.sleep(2) + continue + else: + break diff --git a/app/kudos/management/commands/mint_kudos.py b/app/kudos/management/commands/mint_kudos.py new file mode 100644 index 00000000000..2a874c1311b --- /dev/null +++ b/app/kudos/management/commands/mint_kudos.py @@ -0,0 +1,67 @@ +''' + Copyright (C) 2017 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 . + +''' + +import datetime +import logging +import warnings + +from django.conf import settings +from django.core.management.base import BaseCommand + +from kudos.utils import mint_kudos_on_web3_and_db + +warnings.filterwarnings("ignore", category=DeprecationWarning) +logging.getLogger("requests").setLevel(logging.WARNING) +logging.getLogger("urllib3").setLevel(logging.WARNING) +# logging.getLogger("web3").setLevel(logging.WARNING) + +logger = logging.getLogger(__name__) +default_start_id = 0 if not settings.DEBUG else 402 + + +class Command(BaseCommand): + + help = 'syncs database with kudos on the blockchain' + + def add_arguments(self, parser): + parser.add_argument('network', default='ropsten', type=str) + parser.add_argument('name', type=str) + parser.add_argument('--description', default='', type=str) + parser.add_argument('--rarity', default=50, type=int) + parser.add_argument('--price', default=1, type=int) + parser.add_argument('--numClonesAllowed', default=10, type=int) + parser.add_argument('--tags', default='', type=str) + parser.add_argument('--image', default='', type=str, help='absolute path to Kudos image') + parser.add_argument('--private_key', help='private key for signing transactions', type=str) + + def handle(self, *args, **options): + # config + network = options['network'] + private_key = options['private_key'] + logging.info(options) + + image = options.get('image') + if image: + image_path = image + else: + image_path = '' + + args = (options['name'], options['description'], options['rarity'], options['price'], + options['numClonesAllowed'], options['tags'], image_path) + + mint_kudos_on_web3_and_db(network, private_key, *args) diff --git a/app/kudos/management/commands/remove_kudos_orphans.py b/app/kudos/management/commands/remove_kudos_orphans.py new file mode 100644 index 00000000000..bee30d720c2 --- /dev/null +++ b/app/kudos/management/commands/remove_kudos_orphans.py @@ -0,0 +1,48 @@ +''' + Copyright (C) 2017 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 . + +''' + +import logging +import warnings + +from django.core.management.base import BaseCommand + +from kudos.utils import KudosContract + +warnings.filterwarnings("ignore", category=DeprecationWarning) +logging.getLogger("requests").setLevel(logging.WARNING) +logging.getLogger("urllib3").setLevel(logging.WARNING) +logging.getLogger("web3").setLevel(logging.WARNING) + +logger = logging.getLogger(__name__) +logging.basicConfig(level=logging.INFO) + + +class Command(BaseCommand): + + help = 'remove kudos orphans from the database' + + def add_arguments(self, parser): + parser.add_argument('--network', default='localhost', type=str, + help='Network such as "localhost", "ropsten", "mainnet"') + + def handle(self, *args, **options): + # config + network = options['network'] + + kudos_contract = KudosContract(network) + kudos_contract.remove_kudos_orphans_db() diff --git a/app/kudos/management/commands/sync_kudos.py b/app/kudos/management/commands/sync_kudos.py new file mode 100644 index 00000000000..2a37fc17550 --- /dev/null +++ b/app/kudos/management/commands/sync_kudos.py @@ -0,0 +1,223 @@ +''' + Copyright (C) 2017 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 . + +''' + +import logging +import time +import warnings + +from django.conf import settings +from django.core.management.base import BaseCommand +from django.db.models import Max + +import requests +import web3 +from kudos.models import Token +from kudos.utils import KudosContract + +# from web3.middleware import local_filter_middleware + +warnings.filterwarnings("ignore", category=DeprecationWarning) +logging.getLogger("requests").setLevel(logging.WARNING) +logging.getLogger("urllib3").setLevel(logging.WARNING) +logging.getLogger("web3").setLevel(logging.WARNING) + +logger = logging.getLogger(__name__) +logging.basicConfig(level=logging.INFO) + + +class Command(BaseCommand): + + help = 'syncs database with kudos on the blockchain' + + def add_arguments(self, parser): + parser.add_argument('network', type=str, choices=['localhost', 'rinkeby', 'mainnet'], + help='ethereum network to use') + parser.add_argument('syncmethod', type=str, choices=['filter', 'id', 'block', 'opensea'], + help='sync method to use') + group = parser.add_mutually_exclusive_group(required=True) + group.add_argument('-s', '--start', type=str, + help='kudos_id to or kudos block to start syncing at. Lowest kudos_id is 1.\ + Options for block are: block number (int), "earliest", or "latest"') + group.add_argument('-r', '--rewind', type=int, + help='Sync the lastest Kudos Ids or block transactions.') + group.add_argument('--catchup', action='store_true', + help='Attempt to sync up the newest kudos to the database') + + def opensea_sync(self, kudos_contract, start_id): + if kudos_contract.network == 'rinkeby': + url = 'https://rinkeby-api.opensea.io/api/v1/events' + elif kudos_contract.network == 'mainnet': + url = 'https://api.opensea.io/api/v1/events' + else: + raise RuntimeError('The Open Sea API is only supported for contracts on rinkeby and mainnet.') + + end_id = kudos_contract._contract.functions.getLatestId().call() + token_ids = range(start_id, end_id + 1) + + headers = {'X-API-KEY': settings.OPENSEA_API_KEY} + + # Event API + for token_id in token_ids: + payload = dict( + asset_contract_address=kudos_contract.address, + token_id=token_id, + ) + r = requests.get(url, params=payload, headers=headers) + r.raise_for_status() + asset_token_id = r.json()['asset_events'][0]['asset']['token_id'] + transaction_hash = r.json()['asset_events'][0]['transaction']['transaction_hash'] + logger.info(f'token_id: {asset_token_id}, txid: {transaction_hash}') + kudos_contract.sync_db(kudos_id=int(asset_token_id), txid=transaction_hash) + + def filter_sync(self, kudos_contract, fromBlock): + event_filter = kudos_contract._contract.events.Transfer.createFilter(fromBlock=fromBlock) + logger.info(event_filter) + for event in event_filter.get_all_entries(): + msg = dict( + blockNumber=event.blockNumber, + _tokenId=event.args._tokenId, + transactionHash=event.transactionHash.hex() + ) + logger.info(f'Transfer event: {msg}') + if logger.isEnabledFor(logging.DEBUG): + logger.debug(f'Raw Transfer event: {event}') + kudos_contract.sync_db(kudos_id=event.args._tokenId, txid=event.transactionHash.hex()) + + def id_sync(self, kudos_contract, start_id): + # iterate through all the kudos + # kudos_contract.reconcile_db(start_id=start_id) + end_id = kudos_contract._contract.functions.getLatestId().call() + kudos_enum = start_id + more_kudos = True + + while more_kudos: + kudos_contract.sync_db_without_txid(kudos_id=kudos_enum) + kudos_enum += 1 + + if kudos_enum > end_id: + more_kudos = False + + def block_sync(self, kudos_contract, fromBlock): + raise NotImplementedError('block_sync does not work properly') + block = fromBlock + last_block_number = kudos_contract._w3.eth.getBlock('latest')['number'] + # for block_num in range(block, last_block_number + 1) + while True: + # wait for a new block + block = kudos_contract._w3.eth.getBlock(block) + if not block: + break + block_hash = block['hash'] + block_number = block['number'] + + logger.info('got new block %s' % kudos_contract._w3.toHex(block_hash)) + logger.info(f'block id: {block_number}') + + # get txs + transactions = block['transactions'] + for tx in transactions: + tx = kudos_contract._w3.eth.getTransaction(tx) + if not tx or tx['to'] != kudos_contract.address: + continue + + logger.info('found a kudos tx') + data = tx['input'] + method_id = data[:10] + logger.info(f'method_id: {method_id}') + + # Check if its a Clone or cloneAndTransfer function call + valid_method_ids = ['0xed74de9d'] + if method_id in valid_method_ids: + kudos_contract._w3.eth.waitForTransactionReceipt(tx['hash']) + kudos_id = kudos_contract._contract.functions.getLatestId().call() + if kudos_contract.network == 'localhost': + # On localhost, the tx syncs faster than the website loads + time.sleep(3) + kudos_contract.sync_db(kudos_id=kudos_id, txid=tx['hash'].hex()) + + block = block_number + 1 + if block == last_block_number: + break + + def handle(self, *args, **options): + # config + network = options['network'] + syncmethod = options['syncmethod'] + + start = options['start'] + rewind = options['rewind'] + catchup = options['catchup'] + + kudos_contract = KudosContract(network, sockets=True) + # kudos_contract._w3.middleware_stack.add(local_filter_middleware()) + + # Handle the filter sync + if syncmethod == 'filter': + if start: + if start.isdigit(): + raise RuntimeError('This option is unstable if not on web3py 4.7.2. May crash testrpc.') + if start in ['earliest', 'latest']: + fromBlock = start + else: + raise ValueError('--fromBlock must be "earliest", or "latest"') + elif rewind: + if web3.__version__ != '4.7.2': + raise RuntimeError('This option is unstable if not on web3py 4.7.2. May crash testrpc.') + fromBlock = kudos_contract._w3.eth.getBlock('latest')['number'] - rewind + elif catchup: + raise ValueError('--catchup option is not valid for filter syncing') + + logger.info(fromBlock) + self.filter_sync(kudos_contract, fromBlock) + return + + # Handle the block sync + if syncmethod == 'block': + if start: + if start.isdigit(): + fromBlock = start + elif start in ['earliest', 'latest']: + fromBlock = start + else: + raise ValueError('--fromBlock must be "earliest", or "latest"') + elif rewind: + fromBlock = kudos_contract._w3.eth.getBlock('latest')['number'] - rewind + elif catchup: + raise ValueError('--catchup option is not valid for block syncing') + + logger.info(fromBlock) + self.block_sync(kudos_contract, fromBlock) + return + + # Handle the other sync methods + if start: + start_id = start + elif rewind: + start_id = kudos_contract._contract.functions.getLatestId().call() - rewind + elif catchup: + start_id = Token.objects.filter(contract__address=kudos_contract.address).aggregate( + Max('token_id'))['token_id__max'] + + if start_id is None or start_id < 0: + start_id = 1 + + if syncmethod == 'id': + self.id_sync(kudos_contract, int(start_id)) + elif syncmethod == 'opensea': + self.opensea_sync(kudos_contract, int(start_id)) + return diff --git a/app/kudos/management/commands/sync_kudos_listener.py b/app/kudos/management/commands/sync_kudos_listener.py new file mode 100644 index 00000000000..3fb164d3467 --- /dev/null +++ b/app/kudos/management/commands/sync_kudos_listener.py @@ -0,0 +1,158 @@ +''' + 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 . + +''' + +import logging +import time +import warnings + +from django.conf import settings +from django.core.management.base import BaseCommand + +import requests +from kudos.utils import KudosContract + +warnings.simplefilter("ignore", category=DeprecationWarning) +warnings.simplefilter("ignore", category=UserWarning) + +logging.getLogger("requests").setLevel(logging.WARNING) +logging.getLogger("urllib3").setLevel(logging.WARNING) +logging.getLogger("web3").setLevel(logging.WARNING) +logging.getLogger("websockets").setLevel(logging.WARNING) + +logger = logging.getLogger(__name__) +logging.basicConfig(level=logging.INFO) + + +class Command(BaseCommand): + help = 'listens for kudos token changes ' + + def add_arguments(self, parser): + parser.add_argument('network', type=str, choices=['localhost', 'rinkeby', 'mainnet'], + help='ethereum network to use') + parser.add_argument('syncmethod', type=str, choices=['filter', 'block', 'opensea'], + help='sync method to use') + parser.add_argument('-i', '--interval', default=1, type=int, + help='how often to poll for updates') + + def opensea_listener(self, kudos_contract, interval): + if kudos_contract.network == 'rinkeby': + url = 'https://rinkeby-api.opensea.io/api/v1/events' + elif kudos_contract.network == 'mainnet': + url = 'https://api.opensea.io/api/v1/events' + else: + raise RuntimeError('The Open Sea API is only supported for contracts on rinkeby and mainnet.') + + # Event API + payload = dict( + asset_contract_address=kudos_contract.address, + event_type='transfer', + ) + headers = {'X-API-KEY': settings.OPENSEA_API_KEY} + asset_token_id = 0 + transaction_hash = 0 + while True: + cache = (asset_token_id, transaction_hash) + r = requests.get(url, params=payload, headers=headers) + r.raise_for_status() + + asset_token_id = r.json()['asset_events'][0]['asset']['token_id'] + transaction_hash = r.json()['asset_events'][0]['transaction']['transaction_hash'] + # If the result is the same as last time, don't re-sync the database + if cache == (asset_token_id, transaction_hash): + continue + logger.info(f'token_id: {asset_token_id}, txid: {transaction_hash}') + kudos_contract.sync_db(kudos_id=int(asset_token_id), txid=transaction_hash) + time.sleep(interval) + + def filter_listener(self, kudos_contract, interval): + + event_filter = kudos_contract._contract.events.Transfer.createFilter(fromBlock='latest') + + while True: + for event in event_filter.get_new_entries(): + msg = dict( + blockNumber=event.blockNumber, + _tokenId=event.args._tokenId, + transactionHash=event.transactionHash.hex() + ) + logger.info(f'Transfer event: {msg}') + if logger.isEnabledFor(logging.DEBUG): + logger.debug(f'Raw Transfer event: {event}') + kudos_contract._w3.eth.waitForTransactionReceipt(msg['transactionHash']) + logger.debug(f"Tx hash: {msg['transactionHash']}") + if kudos_contract.network == 'localhost': + time.sleep(5) + kudos_contract.sync_db(kudos_id=msg['_tokenId'], txid=msg['transactionHash']) + time.sleep(interval) + + def block_listener(self, kudos_contract, interval): + block = 'latest' + last_block_hash = None + while True: + # wait for a new block + block = kudos_contract._w3.eth.getBlock('latest') + block_hash = block['hash'] + block_number = block['number'] + + if last_block_hash == block_hash: + time.sleep(interval) + continue + + logger.info('got new block %s' % kudos_contract._w3.toHex(block_hash)) + logger.info(f'block id: {block_number}') + + # get txs + transactions = block['transactions'] + for tx in transactions: + tx = kudos_contract._w3.eth.getTransaction(tx) + if not tx or tx['to'] != kudos_contract.address: + continue + + logger.info('found a kudos tx') + data = tx['input'] + method_id = data[:10] + logger.info(f'method_id: {method_id}') + + # Check if its a Clone or a Mint method. + # NOTE: These method_id's will change if a new contract is deployed. + # You will have to watch the logs to figure out the new method_id's. + if method_id == '0xed74de9d' or method_id == '0xbb7fde71': + kudos_contract._w3.eth.waitForTransactionReceipt(tx['hash']) + kudos_id = kudos_contract._contract.functions.getLatestId().call() + if kudos_contract.network == 'localhost': + # On localhost, the tx syncs faster than the website loads + time.sleep(3) + kudos_contract.sync_db(kudos_id=kudos_id, txid=tx['hash'].hex()) + + last_block_hash = block_hash + + def handle(self, *args, **options): + network = options['network'] + syncmethod = options['syncmethod'] + interval = options['interval'] + + kudos_contract = KudosContract(network) + + logger.info('Listening for new Kudos events...') + if syncmethod == 'filter': + kudos_contract = KudosContract(network, sockets=True) + self.filter_listener(kudos_contract, interval) + elif syncmethod == 'block': + self.block_listener(kudos_contract, interval) + elif syncmethod == 'opensea': + self.opensea_listener(kudos_contract, interval) diff --git a/app/kudos/management/commands/update_kudos_metadata.py b/app/kudos/management/commands/update_kudos_metadata.py new file mode 100644 index 00000000000..f14448b87bb --- /dev/null +++ b/app/kudos/management/commands/update_kudos_metadata.py @@ -0,0 +1,131 @@ +''' + Copyright (C) 2017 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 . + +''' + +import logging +import time +import warnings + +from django.core.management.base import BaseCommand + +from kudos.utils import KudosContract, get_rarity_score, humanize_name + +warnings.filterwarnings("ignore", category=DeprecationWarning) +logging.getLogger("requests").setLevel(logging.WARNING) +logging.getLogger("urllib3").setLevel(logging.WARNING) +logging.getLogger("web3").setLevel(logging.WARNING) + +logger = logging.getLogger(__name__) +logging.basicConfig(level=logging.INFO) + + +class Command(BaseCommand): + + help = 'syncs database with kudos on the blockchain' + + def add_arguments(self, parser): + parser.add_argument('network', type=str, choices=['localhost', 'rinkeby', 'ropsten', 'mainnet'], + help='ethereum network to use') + parser.add_argument('--start_id', default=1, type=int, + help='kudos_id to or kudos block to start syncing at. Lowest kudos_id is 1.') + parser.add_argument('--end_id', type=int, + help='kudos_id to stop syncing at. By default it will sync to the latest token.') + + def handle(self, *args, **options): + # config + network = options['network'] + start_id = options['start_id'] + + kudos_contract = KudosContract(network) + + if options['end_id']: + end_id = options['end_id'] + else: + end_id = kudos_contract._w3.functions.getLatestId().call() + + for kudos_id in range(start_id, end_id + 1): + kudos = kudos_contract.getKudosById(kudos_id, to_dict=True) + + # Copied from mint_all_kudos + image_name = kudos.get('image') + if image_name: + # Support Open Sea + if kudos_contract.network == 'mainnet': + image_path = 'http://kudosdemo.gitcoin.co/static/v2/images/kudos/' + image_name + else: + image_path = 'v2/images/kudos/' + image_name + else: + image_path = '' + + attributes = [] + rarity = { + "trait_type": "rarity", + "value": get_rarity_score(kudos['numClonesAllowed']), + } + attributes.append(rarity) + + artist = { + "trait_type": "artist", + "value": kudos.get('artist') + } + attributes.append(artist) + + platform = { + "trait_type": "platform", + "value": kudos.get('platform') + } + attributes.append(platform) + + tags = kudos['tags'] + # append tags + if kudos['priceFinney'] < 2: + tags.append('budget') + if kudos['priceFinney'] < 5: + tags.append('affordable') + if kudos['priceFinney'] > 20: + tags.append('premium') + if kudos['priceFinney'] > 200: + tags.append('expensive') + + for tag in tags: + if tag: + tag = { + "trait_type": "tag", + "value": tag + } + attributes.append(tag) + + metadata = { + 'name': humanize_name(kudos['name']), + 'image': image_path, + 'description': kudos['description'], + 'external_url': f'http://kudosdemo.gitcoin.co/kudos', + 'background_color': '#fbfbfb', + 'attributes': attributes + } + + for x in range(1, 4): + try: + tokenURI_url = kudos_contract.create_tokenURI_url(**metadata) + args = () + except Exception as e: + logger.error(e) + logger.info("Trying the mint again...") + time.sleep(2) + continue + else: + break diff --git a/app/kudos/migrations/0001_initial.py b/app/kudos/migrations/0001_initial.py new file mode 100644 index 00000000000..8a7d206c327 --- /dev/null +++ b/app/kudos/migrations/0001_initial.py @@ -0,0 +1,125 @@ +# Generated by Django 2.1.2 on 2018-10-27 17:27 + +import django.contrib.postgres.fields.jsonb +from django.db import migrations, models +import django.db.models.deletion +import economy.models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('dashboard', '0109_bounty_funding_organisation'), + ] + + operations = [ + migrations.CreateModel( + name='Contract', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_on', models.DateTimeField(db_index=True, default=economy.models.get_time)), + ('modified_on', models.DateTimeField(default=economy.models.get_time)), + ('address', models.CharField(max_length=255, unique=True)), + ('is_latest', models.BooleanField(default=False)), + ('network', models.CharField(max_length=255)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='KudosTransfer', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_on', models.DateTimeField(db_index=True, default=economy.models.get_time)), + ('modified_on', models.DateTimeField(default=economy.models.get_time)), + ('web3_type', models.CharField(default='v3', max_length=50)), + ('emails', django.contrib.postgres.fields.jsonb.JSONField(blank=True)), + ('url', models.CharField(blank=True, default='', max_length=255)), + ('tokenName', models.CharField(default='ETH', max_length=255)), + ('tokenAddress', models.CharField(max_length=255)), + ('amount', models.DecimalField(decimal_places=4, default=1, max_digits=50)), + ('comments_public', models.TextField(blank=True, default='')), + ('ip', models.CharField(max_length=50)), + ('github_url', models.URLField(blank=True, null=True)), + ('from_name', models.CharField(blank=True, default='', max_length=255)), + ('from_email', models.CharField(blank=True, default='', max_length=255)), + ('from_username', models.CharField(blank=True, default='', max_length=255)), + ('username', models.CharField(blank=True, default='', max_length=255)), + ('network', models.CharField(default='', max_length=255)), + ('txid', models.CharField(default='', max_length=255)), + ('receive_txid', models.CharField(blank=True, default='', max_length=255)), + ('received_on', models.DateTimeField(blank=True, null=True)), + ('from_address', models.CharField(blank=True, default='', max_length=255)), + ('receive_address', models.CharField(blank=True, default='', max_length=255)), + ('metadata', django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=dict)), + ('is_for_bounty_fulfiller', models.BooleanField(default=False, help_text='If this option is chosen, this tip will be automatically paid to the bounty fulfiller, not self.usernameusername.')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='Token', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_on', models.DateTimeField(db_index=True, default=economy.models.get_time)), + ('modified_on', models.DateTimeField(default=economy.models.get_time)), + ('price_finney', models.IntegerField()), + ('num_clones_allowed', models.IntegerField(blank=True, null=True)), + ('num_clones_in_wild', models.IntegerField(blank=True, null=True)), + ('cloned_from_id', models.IntegerField()), + ('name', models.CharField(max_length=255)), + ('description', models.CharField(max_length=510)), + ('image', models.CharField(max_length=255, null=True)), + ('rarity', models.CharField(max_length=255, null=True)), + ('tags', models.CharField(max_length=255, null=True)), + ('artist', models.CharField(blank=True, max_length=255, null=True)), + ('platform', models.CharField(blank=True, max_length=255, null=True)), + ('external_url', models.CharField(max_length=255, null=True)), + ('background_color', models.CharField(max_length=255, null=True)), + ('owner_address', models.CharField(max_length=255)), + ('txid', models.CharField(blank=True, max_length=255, null=True)), + ('token_id', models.IntegerField()), + ('contract', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='kudos_contract', to='kudos.Contract')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='Wallet', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_on', models.DateTimeField(db_index=True, default=economy.models.get_time)), + ('modified_on', models.DateTimeField(default=economy.models.get_time)), + ('address', models.CharField(max_length=255, unique=True)), + ('profile', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='kudos_wallets', to='dashboard.Profile')), + ], + options={ + 'abstract': False, + }, + ), + migrations.AddField( + model_name='kudostransfer', + name='kudos_token', + field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='kudos_transfer', to='kudos.Token'), + ), + migrations.AddField( + model_name='kudostransfer', + name='kudos_token_cloned_from', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='kudos_token_cloned_from', to='kudos.Token'), + ), + migrations.AddField( + model_name='kudostransfer', + name='recipient_profile', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='received_kudos', to='dashboard.Profile'), + ), + migrations.AddField( + model_name='kudostransfer', + name='sender_profile', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='sent_kudos', to='dashboard.Profile'), + ), + ] diff --git a/app/kudos/migrations/__init__.py b/app/kudos/migrations/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/app/kudos/models.py b/app/kudos/models.py new file mode 100644 index 00000000000..6a4769cdac4 --- /dev/null +++ b/app/kudos/models.py @@ -0,0 +1,299 @@ +# -*- coding: utf-8 -*- +"""Define models. + +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 . + +""" +import logging +from io import BytesIO + +from django.conf import settings +from django.core.files import File +from django.db import models +from django.utils.text import slugify + +import environ +import pyvips +from dashboard.models import SendCryptoAsset +from economy.models import SuperModel +from eth_utils import to_checksum_address +from pyvips.error import Error as VipsError + +logger = logging.getLogger(__name__) + + +class Token(SuperModel): + """Model representing a Kudos ERC721 token on the blockchain. + + The model attempts to match the actual blockchain data as much as possible, without being duplicative. + + Attributes: + artist (str): The artist that created the kudos image. + background_color (str): 6 digit hex code background color. See Open Sea docs for details. + cloned_from_id (int): Orignal Kudos that this one was cloned from. + contract (FK): Foreing key to the Contract model. + description (str): Description of the kudos. + external_url (str): External URL pointer to image asset. See Open Sea docs for details. + image (str): Image file name. + name (str): Kudos name. + num_clones_allowed (int): How many clones are allowed to be made. + num_clones_available (int): How many clones the Kudos has left. + num_clones_in_wild (int): How many clones there are in the wild. + owner_address (str): ETH address of the owner. Pulled from the `ownerOf` contract function. + platform (str): Where the Kudos originated from. + price_finney (int): Price to clone the Kudos in finney. + rarity (str): Rarity metric, defined in kudos.utils.py + tags (str): Comma delimited tags. TODO: change to array + token_id (int): the token_id on the blockchain. + txid (str): The ethereum transaction id that generated this kudos. + + """ + + # Kudos Struct (also in contract) + price_finney = models.IntegerField() + num_clones_allowed = models.IntegerField(null=True, blank=True) + num_clones_in_wild = models.IntegerField(null=True, blank=True) + cloned_from_id = models.IntegerField() + + # Kudos metadata from tokenURI (also in contract) + name = models.CharField(max_length=255) + description = models.CharField(max_length=510) + image = models.CharField(max_length=255, null=True) + rarity = models.CharField(max_length=255, null=True) + tags = models.CharField(max_length=255, null=True) + artist = models.CharField(max_length=255, null=True, blank=True) + platform = models.CharField(max_length=255, null=True, blank=True) + external_url = models.CharField(max_length=255, null=True) + background_color = models.CharField(max_length=255, null=True) + + # Extra fields added to database (not on blockchain) + owner_address = models.CharField(max_length=255) + txid = models.CharField(max_length=255, null=True, blank=True) + token_id = models.IntegerField() + contract = models.ForeignKey( + 'kudos.Contract', related_name='kudos_contract', on_delete=models.SET_NULL, null=True + ) + + def save(self, *args, **kwargs): + if self.owner_address: + self.owner_address = to_checksum_address(self.owner_address) + + super().save(*args, **kwargs) + + @property + def price_in_eth(self): + """Convert price from finney to eth. + + Returns: + float or int: price in eth. + + """ + return self.price_finney / 1000 + + @property + def shortened_address(self): + """Shorten ethereum address to only the first and last 4 digits. + + Returns: + str: shortened address. + + """ + return self.owner_address[:6] + '...' + self.owner_address[38:] + + @property + def capitalized_name(self): + """Capitalize name + + Returns: + str: Capitalized name. + + """ + return ' '.join([x.capitalize() for x in self.name.split('_')]) + + @property + def num_clones_available(self): + """Calculate the number of clones available for a kudos. + + Returns: + int: Number of clones available. + + """ + r = self.num_clones_allowed - self.num_clones_in_wild + if r < 0: + r = 0 + return r + + @property + def humanized_name(self): + """Turn snake_case into Snake Case. + + Returns: + str: The humanized name. + + """ + return ' '.join([x.capitalize() for x in self.name.split('_')]) + + @property + def tags_as_array(self): + return [tag.strip() for tag in self.tags.split(',')] + + def humanize(self): + self.owner_address = self.shortened_address + self.name = self.capitalized_name + self.num_clones_available = self.get_num_clones_available() + return self + + def __str__(self): + """Return the string representation of a model.""" + return f"Kudos Token: {self.humanized_name}" + + @property + def as_img(self): + """Convert the provided buffer to another format. + + Args: + obj (File): The File/ContentFile object. + + Exceptions: + Exception: Cowardly catch blanket exceptions here, log it, and return None. + + Returns: + BytesIO: The BytesIO stream containing the converted File data. + None: If there is an exception, the method returns None. + + """ + root = environ.Path(__file__) - 2 # Set the base directory to two levels. + file_path = root('assets') + '/' + self.image + with open(file_path, 'rb') as f: + obj = File(f) + try: + obj_data = obj.read() + if obj_data: + image = pyvips.Image.new_from_file(obj.name) + return BytesIO(image.write_to_buffer(f'.png')) + except VipsError: + pass + except Exception as e: + logger.error(e) + return None + + @property + def img_url(self): + return f'{settings.BASE_URL}dynamic/kudos/{self.pk}/{slugify(self.name)}' + + +class KudosTransfer(SendCryptoAsset): + """Model that represents a request to clone a Kudos. + + Typically this gets created when using the "kudos send" functionality. + The model is inherited from the SendCryptoAsset model, which is also used by Tips. + + Attributes: + from_address (str): Eth address of the person that is sending the kudos. + kudos_token (kudos.Token): Foreign key to the kudos_token that was cloned. + This is filled in after the kudos has been cloned. + kudos_token_cloned_from (kudos.Token): Foreign key to the kudos_token that will be cloned and sent. + recipient_profile (dashboard.Profile): Foreign key to the profile of the person that is being sent the kudos. + sender_profile (dashboard.Profile): Foreign key to the profile of the person that is sending the kudos. + + """ + + # kudos_token_cloned_from is a reference to the original Kudos Token that is being cloned. + kudos_token_cloned_from = models.ForeignKey( + 'kudos.Token', related_name='kudos_token_cloned_from', on_delete=models.SET_NULL, null=True + ) + # kudos_token is a reference to the new Kudos Token that is soon to be minted + kudos_token = models.OneToOneField( + 'kudos.Token', related_name='kudos_transfer', on_delete=models.SET_NULL, null=True + ) + + recipient_profile = models.ForeignKey( + 'dashboard.Profile', related_name='received_kudos', on_delete=models.SET_NULL, null=True, blank=True + ) + sender_profile = models.ForeignKey( + 'dashboard.Profile', related_name='sent_kudos', on_delete=models.SET_NULL, null=True, blank=True + ) + + def save(self, *args, **kwargs): + if self.from_address: + self.from_address = to_checksum_address(self.from_address) + if self.receive_address: + self.receive_address = to_checksum_address(self.receive_address) + + super().save(*args, **kwargs) + + @property + def receive_url(self): + """URL used for indirect send. Deprecated in favor of receive_url_for_recipient + + Returns: + str: URL for recipient. + + """ + return self.receive_url_for_recipient + + @property + def receive_url_for_recipient(self): + """URL used for indirect send. Deprecated in favor of receive_url_for_recipient + + Returns: + str: URL for recipient. + + """ + try: + key = self.metadata['reference_hash_for_receipient'] + return f"{settings.BASE_URL}kudos/receive/v3/{key}/{self.txid}/{self.network}" + except KeyError as e: + logger.error(e) + return '' + + def __str__(self): + """Return the string representation of a model.""" + status = 'funded' if self.txid else 'not funded' + return f"({status}) transfer of {self.kudos_token_cloned_from} from {self.sender_profile} to {self.recipient_profile} on {self.network}" + + +class Contract(SuperModel): + + address = models.CharField(max_length=255, unique=True) + is_latest = models.BooleanField(default=False) + network = models.CharField(max_length=255) + + def save(self, *args, **kwargs): + if self.address: + self.address = to_checksum_address(self.address) + super().save(*args, **kwargs) + + +class Wallet(SuperModel): + """DEPRECATED. Kudos Address where the tokens are stored. + + Currently not used. Instead we are using preferred_payout_address for now. + + Attributes: + address (TYPE): Description + profile (TYPE): Description + + """ + + address = models.CharField(max_length=255, unique=True) + profile = models.ForeignKey( + 'dashboard.Profile', related_name='kudos_wallets', on_delete=models.SET_NULL, null=True + ) + + def __str__(self): + """Return the string representation of a model.""" + return f"Wallet: {self.address} Profile: {self.profile}" diff --git a/app/kudos/router.py b/app/kudos/router.py new file mode 100644 index 00000000000..43952f25f2f --- /dev/null +++ b/app/kudos/router.py @@ -0,0 +1,109 @@ +# -*- coding: utf-8 -*- +"""Define dashboard specific DRF API routes. + +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 . + +""" + +import django_filters.rest_framework +from rest_framework import routers, serializers, viewsets + +from .models import Token, Wallet + + +class TokenSerializer(serializers.HyperlinkedModelSerializer): + class Meta: + model = Token + fields = ('id', 'created_on', 'modified_on', 'name', 'description', 'image', 'rarity', + 'price', 'num_clones_allowed', 'num_clones_in_wild', 'owner_address', 'tags') + + +class WalletSerializer(serializers.HyperlinkedModelSerializer): + class Meta: + model = Wallet + fields = ('address', 'profile_id') + + +class WalletViewSet(viewsets.ModelViewSet): + queryset = Wallet.objects.all().order_by('-id') + serializer_class = WalletSerializer + filter_backends = (django_filters.rest_framework.DjangoFilterBackend,) + + def get_queryset(self): + param_keys = self.request.query_params.keys() + queryset = Wallet.objects.all().order_by('-id') + + # Filter by address + if 'address' in param_keys: + queryset = queryset.filter(address=self.request.query_params.get('address')) + + # Filter by profile_id + if 'profile_id' in param_keys: + queryset = queryset.filter(profile__id=self.request.query_params.get('profile_id')) + + # Filter by profile_id + if 'profile_handle' in param_keys: + queryset = queryset.filter(profile__handle=self.request.query_params.get('profile_handle')) + + return queryset + + +class TokenViewSet(viewsets.ModelViewSet): + queryset = Token.objects.all().order_by('-id') + serializer_class = TokenSerializer + filter_backends = (django_filters.rest_framework.DjangoFilterBackend,) + # filter_fields = ('name', 'description', 'image', 'rarity', 'price', 'num_clones_allowed', + # 'num_clones_in_wild', 'owner_address', 'tags') + + def get_queryset(self): + param_keys = self.request.query_params.keys() + queryset = Token.objects.all().order_by('-id') + + # Filter by owner_address + if 'owner_address' in param_keys: + queryset = queryset.filter(owner_address__iexact=self.request.query_params.get('owner_address')) + + # Filter by name + if 'name' in param_keys: + queryset = queryset.filter(name__iexact=self.request.query_params.get('name')) + + # Filter by rarity + if 'rarity' in param_keys: + queryset = queryset.filter(rarity__iexact=self.request.query_params.get('rarity')) + + # Filter by price + if 'price' in param_keys: + queryset = queryset.filter(price__iexact=self.request.query_params.get('price')) + + # Filter by num_clones_allowed + if 'num_clones_allowed' in param_keys: + queryset = queryset.filter(num_clones_allowed__iexact=self.request.query_params.get('num_clones_allowed')) + + # Filter by num_clones_in_wild + if 'num_clones_in_wild' in param_keys: + queryset = queryset.filter(num_clones_in_wild__iexact=self.request.query_params.get('num_clones_in_wild')) + + # Filter by tags + if 'tags' in param_keys: + queryset = queryset.filter(tags__in=self.request.query_params.get('tags')) + + return queryset + + +# Routers provide an easy way of automatically determining the URL conf. +router = routers.DefaultRouter() +router.register(r'kudos', TokenViewSet) +router.register(r'wallet', WalletViewSet) diff --git a/app/kudos/templates/__init__.py b/app/kudos/templates/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/app/kudos/templates/kudos_about.html b/app/kudos/templates/kudos_about.html new file mode 100644 index 00000000000..07a02c744f2 --- /dev/null +++ b/app/kudos/templates/kudos_about.html @@ -0,0 +1,347 @@ +{% comment %} + Copyright (C) 2017 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 i18n static %} + + + + + {% include 'shared/head.html' %} + {% include 'shared/cards_pic.html' %} + + + + {% include 'shared/top_nav.html' with class='d-md-flex' %} +
          + {% include 'shared/kudos_nav.html' %} + +
          +

          + Kudos is a new way to show
          appreciation and build relationships. +

          +
          +
          + + + +
          +
          + +
          +
          + +
          + +
          +
          +
          + +
          +
          +

          {% trans "What is Kudos?" %}

          +
          +
          +
          +
          +
          + +
          +
          +
          +
          + +
          +
          +
          +
          +
          + kudos +
          +
          +
          +
          + Cellarius +
          +
          +

          {% trans "Gitcoin has partnered with Cellarius Universe to create original collectible badges that feature Cellarius Art style. " %}

          +

          {% trans "Cellarius is an original transmedia cyberpunk franchise that leverages blockchain technology and user-generated assets to createa a collaborative, fan-curated story." %}

          +
          +
          +
          +
          +

          {% trans "In essence, the Cellarius Universe is a future-oriented mythology. It is also a collective storytelling project whose content and contours will be shaped by its community." %}

          +

          {% trans "Cellarius straddles the familiar cyberpunk themes of a dystopian and troubled future while maintaining a more optimistic outlook on humanity’s destiny and place in the cosmos." %}

          +
          +
          + Cellarius +
          +
          +
          +
          + Cellarius +
          +
          +

          {% trans "Octavian Todiruț" %}

          +

          {% blocktrans %} I am a long time graphic designer, art director and product designer. A fancy way of saying "I am moving the mouse or pencil around, playing with shapes and colors." I like getting lost in everything art, photography, design and architecture and their history. When I don't do any of the above, I walk, travel or sometimes play a game.{% endblocktrans %}

          +
          +
          + +
          +
          + + kudos hexagon + + + + + + + + + + + + + + + +
          +

          Why Use Kudos?

          +
          +
          +
          + + + {% trans "Recognize" %} + {% trans "People You’ve" %} + {% trans "Worked With" %} + + +
          +
          + +
          +
          + + + {% trans "Build Long" %} + {% trans "Lasting" %} + {% trans "Relationships" %} + + +
          +
          +
          +
          + + + {% trans "Understand" %} + {% trans "Other Gitcoiners" %} + {% trans "Skillsets" %} + + +
          +
          +
          +
          + + + {% trans "See Who" %} + {% trans "Gitcoiners have" %} + {% trans "Collaborated" %} + {% trans "With" %} + + +
          +
          +
          +
          + + + {% trans "Send Kudos" %} + {% trans "as a Tip" %} + + +
          +
          +
          +
          + + + {% trans "Become vetted " %} + {% trans "in Web3 & OSS" %} + + +
          +
          +
          +
          + + + {% trans "Grow Open" %} + {% trans "Source" %} + + +
          +
          +
          + +
          +
          +
          + +
          +
          +

          {% trans "How Do I Get One?" %}

          +

          {% trans "Kudos can be gifted to you by any other Gitcoin member. You can also purchase Kudos through the marketplace and send it to any other Gitcoin user. When you send a Kudos, they receive an email notication. After they accept the Kudos, it will be minted on the blockchain and delivered to its recipient." %}

          +
          +
          + + {% trans + +
          +
          +
          +
          + + {% trans + +
          +
          +

          {% trans "ERC-721" %}

          +

          {% trans "ERC-721 is a standard developed by the Ethereum Foundation that can be used to create Non-Fungible Tokens (NFT's). The most well known example of this is Cryptokitties, but there are many other examples. Here at Gitcoin we believe in the potential of NFT's, so we created our own - Kudos. Want to integrate this ERC 721 into your Dapp?" %} {% trans "click here" %}

          +
          +
          + +
          + +
          + +
          +
          +

          FAQ

          + +
          +
          +
          Kudos is a new usage of Non-Fungible tokens... Why did you make it?
          +
          +

          It's a common practice for on-site teams to be able to celebrate the work they've done together after shipping. We wanted to create a similar experience for distributed, open-source, teams to celebrate their wins and to celebrate each other.

          +

          Kudos is a way to celebrate the relationships that have been built. Kudos is meant to bootstrap reputation in web3.

          +
          +
          + +
          +
          How are Kudos minted?
          +
          +

          We currently take these steps but hope to explore uploaded svgs for minting in the future.

          +
            +
          1. Post an idea to https://github.com/gitcoinco/kudosbadges/issues/new
          2. +
          3. Get it prioritized with Mladen, our designer
          4. +
          5. Run it through a management command on the gitcoin site.. which will create the ERC721
          6. +
          +
          +
          + +
          +
          Who earns money when a new Kudos is created?
          +
          +

          When a new Kudos is created, the ETH sent during that minting process is sent to the illustrator who created the artwork for the Kudos. In some cases, Gitcoin may also take a 10% percentage of the minting.

          +
          +
          + +
          +
          How is Kudos' privacy managed?
          +
          +

          When you send a kudos, you are sending the non-fungible token (NFT) to a proxy address. The recipient can decide to accept it or reject it.

          +

          A recipient may elect to automatically accept Kudos in the future if they wish to forego the acceptance process.

          +
          +
          + +
          +
          I want to add Kudos to my site. How can I do that?
          +
          +

          We plan to make Kudos into an open network that any dapp can leverage. For more information, checkout get in touch over at https://github.com/OpenKudos/

          +
          +
          +
          +
          + +
          + {% include 'shared/footer.html' %} + {% include 'shared/analytics.html' %} + {% include 'shared/footer_scripts.html' with slim=1 %} + + + + {% include 'shared/messages.html' %} + diff --git a/app/kudos/templates/kudos_details.html b/app/kudos/templates/kudos_details.html new file mode 100644 index 00000000000..586295aa2e7 --- /dev/null +++ b/app/kudos/templates/kudos_details.html @@ -0,0 +1,138 @@ +{% load i18n static %} +{% load kudos_extras %} + + + + {% include 'shared/head.html' %} + {% include 'shared/cards_pic.html' %} + + + + + + + + {% include 'shared/top_nav.html' with class='d-md-flex' %} +
          + {% include 'shared/kudos_nav.html' %} + +
          + {% include 'shared/kudos_searchbar.html' %} +
          +
          + + + +
          +
          +
          + +
          + +

          + +

          +
          + +
          + {% include 'shared/kudos_levitate.html' %} + {{ kudos.name }} +
          +
          +
          + {% if 'cellarius' in kudos.tags %} + Cellarius + {% endif %} +

          {{ kudos.name|humanize_name }} {% if kudos.generation %}Gen {{ kudos.generation }}{% endif %}

          + +
          +

          {{ kudos.description }}

          +
          +
          + MARKETPLACE STATS +
          + +

          {{ kudos.rarity }} ({{ kudos.num_clones_in_wild }} out of {{ kudos.num_gen0_clones_allowed }})

          + +
          + {{ kudos.num_clones_available }} Total Available + {{ kudos.num_clones_in_wild }} Total minted +
          +

          {{ kudos.price_in_eth }} ETH

          +
          +
          + {% if kudos.num_clones_allowed != 0 and kudos.num_clones_available != 0 %} + {% trans "Send Kudos" %} + {% elif kudos.num_clones_allowed != 0 and kudos.num_clones_available == 0 %} + + There are no clones available due to popularity but you can still look at this awesome badge! + {% endif %} +
          +
          +
          +

          + {% for tag in kudos.tags_as_array %} + {{ tag }} + {% endfor %} +

          + {% if related_profiles %} +
          +
          +

          {% trans "These people own this Kudos" %}

          +
          +
          +
          +
          + {% for profile in related_profiles %} + + {{profile.username}} + + {% if forloop.counter|divisibleby:5 %} +
          +
          +
          + {% endif %} + {% endfor %} +
          + {% endif %} +
          +
          +
          +
          + + + {% include 'shared/disqus.html' with page_url=request.build_absolute_uri %} +
          + + + {% include 'shared/footer.html' %} + {% include 'shared/analytics.html' %} + {% include 'shared/footer_scripts.html' with slim=1 %} + + + + + + + + + {% include 'shared/messages.html' %} + + diff --git a/app/kudos/templates/kudos_marketplace.html b/app/kudos/templates/kudos_marketplace.html new file mode 100644 index 00000000000..909f4665219 --- /dev/null +++ b/app/kudos/templates/kudos_marketplace.html @@ -0,0 +1,96 @@ +{% load i18n static %} + + + + {% include 'shared/head.html' %} + {% include 'shared/cards_pic.html' %} + + + + {% include 'shared/top_nav.html' with class='d-md-flex' %} +
          + {% include 'shared/kudos_nav.html' %} + +
          + {% include 'shared/kudos_searchbar.html' %} +
          +
          + +
          +
          +
          {{listings.count}} Kudos available on {{ network }}
          + {% if listings %} +
          + + +
          + {% endif %} +
          + {% if not listings %} +
          +

          UH-OH!

          + The kudos you were looking for isn't here, but here's a surprise! + +
          + {% trans "Feeling creative?" %} {% trans "Mint Your Own!" %} +
          +
          + + {% endif %} +
          + {% for listing in listings %} +
          + {% include 'shared/kudos_card.html' %} +
          + {% if forloop.counter|divisibleby:4 %} +
          +
          + {% endif %} + {% endfor %} + + {% if listings %} + + {% endif %} +
          +
          + + {% include 'shared/footer.html' %} + {% include 'shared/analytics.html' %} + {% include 'shared/footer_scripts.html' with slim=1 %} + + + + + {% include 'shared/messages.html' %} + + diff --git a/app/kudos/templates/kudos_mint.html b/app/kudos/templates/kudos_mint.html new file mode 100644 index 00000000000..e897abcfaa8 --- /dev/null +++ b/app/kudos/templates/kudos_mint.html @@ -0,0 +1,71 @@ +{% extends 'transaction/base.html' %} +{% 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 i18n static %} +{% block 'scripts' %} + + + +{% endblock %} + +{% block 'main' %} +
          +
          + + + + + +

          {% trans "Mint" %} {% trans "Kudos" %}

          +
          +
          +
          + + +
          +
          + + +
          +
          + + + 0 to 100 +
          +
          + + +
          +
          + + +
          + +
          +
          +{% endblock %} diff --git a/app/kudos/templates/shared/kudos_banner.html b/app/kudos/templates/shared/kudos_banner.html new file mode 100644 index 00000000000..5efc054ad3a --- /dev/null +++ b/app/kudos/templates/shared/kudos_banner.html @@ -0,0 +1,21 @@ +{% comment %} + Copyright (C) 2017 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 i18n %} +{% load staticfiles %} +
          + kudos +
          diff --git a/app/kudos/templates/shared/kudos_card.html b/app/kudos/templates/shared/kudos_card.html new file mode 100644 index 00000000000..fa41b65008e --- /dev/null +++ b/app/kudos/templates/shared/kudos_card.html @@ -0,0 +1,25 @@ +{% comment %} + Copyright (C) 2017 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 i18n staticfiles %} +{% load kudos_extras matches %} +
          + + {{ listing.name }} + + {{ listing.price_in_eth }} ETH +
          {{ listing.name|humanize_name }}
          +
          diff --git a/app/kudos/templates/shared/kudos_card_profile.html b/app/kudos/templates/shared/kudos_card_profile.html new file mode 100644 index 00000000000..d9fa90d07e0 --- /dev/null +++ b/app/kudos/templates/shared/kudos_card_profile.html @@ -0,0 +1,76 @@ +{% comment %} + Copyright (C) 2017 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 i18n staticfiles %} +{% load kudos_extras %} +{% if kudos_data == 'sent_kudos' %} + {% for kudo in sent_kudos|slice:":8" %} +
          +
          + + {{ kudo.name|humanize_name }} + +
          +
          {{ kudo.name|humanize_name }}
          + {{ kudo.description|truncatechars:60 }} +
          +
          + {{ kudo.name|humanize_name }} + {% if kudo.kudos_transfer %} +

          Sent to {{kudo.kudos_transfer.username|slice:"1:"}}

          +

          + {{ kudo.kudos_transfer.txid|humanize_address }} +

          + + {% if kudo.kudos_transfer.comments_public %} + Comment: +

          {{kudo.kudos_transfer.comments_public}}

          + {% endif %} + {% endif %} +
          +
          +
          + {% endfor %} +{% else %} + {% for kudo in kudos|slice:":8" %} +
          +
          + + {{ kudo.name|humanize_name }} + +
          +
          {{ kudo.name|humanize_name }}
          + {{ kudo.description|truncatechars:60 }} +
          +
          + {{ kudo.name|humanize_name }} + {% if kudo.kudos_transfer %} +

          Sent from {{kudo.kudos_transfer.from_name}}

          +

          + {{ kudo.kudos_transfer.txid|humanize_address }} +

          + + {% if kudo.kudos_transfer.comments_public %} + Comment: +

          {{kudo.kudos_transfer.comments_public}}

          + {% endif %} + {% endif %} +
          +
          +
          + {% endfor %} + +{% endif %} diff --git a/app/kudos/templates/shared/kudos_levitate.html b/app/kudos/templates/shared/kudos_levitate.html new file mode 100644 index 00000000000..aef66aa1fd4 --- /dev/null +++ b/app/kudos/templates/shared/kudos_levitate.html @@ -0,0 +1,48 @@ +
          +
          + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          +
          diff --git a/app/kudos/templates/shared/kudos_nav.html b/app/kudos/templates/shared/kudos_nav.html new file mode 100644 index 00000000000..b7e576c8520 --- /dev/null +++ b/app/kudos/templates/shared/kudos_nav.html @@ -0,0 +1,61 @@ +{% comment %} + Copyright (C) 2017 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 i18n static matches %} + +{% if request.path|matches:"^\/((explorer)|(issue.*)|(.*new.*))$" %} + +{% endif %} diff --git a/app/kudos/templates/shared/kudos_searchbar.html b/app/kudos/templates/shared/kudos_searchbar.html new file mode 100644 index 00000000000..ac6de1a5d58 --- /dev/null +++ b/app/kudos/templates/shared/kudos_searchbar.html @@ -0,0 +1,59 @@ +{% comment %} + Copyright (C) 2017 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 i18n kudos_extras %} +
          +
          +
          +
          + + + + + + + + + + + + + + + + + +
          + + + +
          +
          +
          + Search suggestions: + rare - + common - + ninja - + soft skills - + programming +
          +
          +
          +
          diff --git a/app/kudos/templates/transaction/base.html b/app/kudos/templates/transaction/base.html new file mode 100644 index 00000000000..9b13d012a35 --- /dev/null +++ b/app/kudos/templates/transaction/base.html @@ -0,0 +1,65 @@ +{% 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 i18n static cookielaw_tags %} + + + + + {% include 'shared/head.html' %} + {% include 'shared/cards_pic.html' %} + + + + + {% include 'shared/tag_manager_2.html' %} + {% include 'shared/analytics.html' with suppress_sumo=1 %} + {% include 'shared/top_nav.html' with class='d-md-flex' %} + {% block 'world' %} {% endblock %} + + +
          + {% include 'transaction/kudos_auth.html' with source='authed' %} + {% cookielaw_banner %} + + {% block 'main' %} {% endblock %} + + +
          + {% include 'shared/rain.html' with class="color" %} + + + {% include 'shared/footer_scripts.html' with slim=1 %} + {% block 'scripts' %}{% endblock %} + + + + + diff --git a/app/kudos/templates/transaction/kudos_auth.html b/app/kudos/templates/transaction/kudos_auth.html new file mode 100644 index 00000000000..89fb3d753fc --- /dev/null +++ b/app/kudos/templates/transaction/kudos_auth.html @@ -0,0 +1,99 @@ +{% 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 i18n static %} +{% load is_in_list %} + + + + + + + diff --git a/app/kudos/templates/transaction/receive.html b/app/kudos/templates/transaction/receive.html new file mode 100644 index 00000000000..cda5bea8923 --- /dev/null +++ b/app/kudos/templates/transaction/receive.html @@ -0,0 +1,111 @@ +{% extends 'transaction/base.html' %} +{% 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 i18n static %} +{% load kudos_extras %} +{% block 'scripts' %} + + + + + + + + + + +{% endblock %} + +{% block 'world' %} +
          + +
          +{% endblock %} +{% block 'main' %} +
          +
          + + +

          {% trans "You've got a Kudos" %}

          + +
          + + + + {{ kudos_transfer.kudos_token_cloned_from.humanized_name }} + {{ kudos_transfer.kudos_token_cloned_from.price_in_eth }} ETH +
          + +
          + + + {% if not kudos_transfer.receive_txid and is_authed %} + + {% endif %} +{% if kudos_transfer.receive_txid %} + +{% endif %} +
          + +{% endblock %} diff --git a/app/kudos/templates/transaction/receive_legacy.html b/app/kudos/templates/transaction/receive_legacy.html new file mode 100644 index 00000000000..3c34734955d --- /dev/null +++ b/app/kudos/templates/transaction/receive_legacy.html @@ -0,0 +1,84 @@ +{% extends 'transaction/base.html' %} +{% 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 i18n static %} +{% block 'scripts' %} + + + + + + + + + + + + +{% endblock %} + +{% block 'world' %} + +{% endblock %} +{% block 'main' %} +
          +
          + + + + + +
          +
          +

          {% trans "Loading" %}

          + +

          {% trans "waiting for web3..." %}

          +
          + + + +
          +{% endblock %} diff --git a/app/kudos/templates/transaction/receive_v2.html b/app/kudos/templates/transaction/receive_v2.html new file mode 100644 index 00000000000..974db388db1 --- /dev/null +++ b/app/kudos/templates/transaction/receive_v2.html @@ -0,0 +1,71 @@ +{% extends 'transaction/base.html' %} +{% 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 i18n static %} +{% block 'scripts' %} + + + + +{% endblock %} + +{% block 'world' %} +
          + +
          +{% endblock %} +{% block 'main' %} +
          +
          + + + + + +
          + + +{% if tip.receive_txid %} + +{% endif %} +
          + +{% endblock %} diff --git a/app/kudos/templates/transaction/send.html b/app/kudos/templates/transaction/send.html new file mode 100644 index 00000000000..71ecf5cf7e9 --- /dev/null +++ b/app/kudos/templates/transaction/send.html @@ -0,0 +1,180 @@ +{% extends 'transaction/base.html' %} +{% 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 i18n static %} +{% load kudos_extras %} +{% block 'scripts' %} + {% include 'shared/current_profile.html' %} + + + + + + + + + + + + + + + +{% endblock %} + +{% block 'main' %} +
          + +
          +
          +
          + + +

          {% trans "Send Kudos" %}

          + +
          + {% if kudos.name %} + {{ kudos.name }} + {{ kudos.name|humanize_name }} + + + {{ kudos.price_in_eth }} ETH USD + {% else %} + + + Select kudos. + + + Pick a kudos + + + + Pick a Kudos + {% endif %} +
          + +
          + + +
          + + + + + +
          + +
          + + +
          + + +
          +
          + + +
          + + + +
          + + +
          +
          + + +
          +
          + + +
          + +{% endblock %} diff --git a/app/kudos/templates/transaction/send1.html b/app/kudos/templates/transaction/send1.html new file mode 100644 index 00000000000..dfad8397baa --- /dev/null +++ b/app/kudos/templates/transaction/send1.html @@ -0,0 +1,46 @@ +{% extends 'transaction/base.html' %} +{% 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 i18n static %} +{% block 'scripts' %} + + +{% endblock %} + +{% block 'main' %} +
          +
          + + + + + +

          {% trans "Send Tip" %}

          +

          {% trans "It's Fast. It's Easy. It's Free.️" %}

          +

          ({% trans "Supports any github username or email address" %})

          +
          + +
          + {% trans "Send Ether" %} 💰 +
          +{% endblock %} diff --git a/app/kudos/templatetags/kudos_extras.py b/app/kudos/templatetags/kudos_extras.py new file mode 100644 index 00000000000..1e8dc793581 --- /dev/null +++ b/app/kudos/templatetags/kudos_extras.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +"""Define the add_url_schema template tag to allow cleaning up url in templates. + +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 . + +""" + +from django import template + +from kudos.utils import humanize_name as humanize_method + +register = template.Library() + + +@register.filter +def humanize_name(name): + """Convert the lowercase and underscores to uppercase and spaces. + + Args: + name (str): The name to convert. + + Usage: + {{ name|humanize_name }} + + Returns: + str: The new name. + + """ + return humanize_method(name) + + +@register.filter +def humanize_address(address): + """Shorten the Ethereum address to be more readable. + + Args: + address (str): The address to shorten. + + Usage: + {{ address|humanize_address }} + + Returns: + str: The new address. + + """ + return address[:6] + '...' + address[-4:] + + +@register.filter +def replace_commas(string): + return ' '.join([x.capitalize() for x in string.split(',')]) diff --git a/app/kudos/test_models.py b/app/kudos/test_models.py new file mode 100644 index 00000000000..51e161e2159 --- /dev/null +++ b/app/kudos/test_models.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +"""Test the Kudos models. + +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 . +""" +import logging +import unittest + +from django.test import Client, TestCase diff --git a/app/kudos/test_utils.py b/app/kudos/test_utils.py new file mode 100644 index 00000000000..cb05de5dfa1 --- /dev/null +++ b/app/kudos/test_utils.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +"""Test the Kudos utils. + +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 . +""" +import logging +import unittest + +from django.test import Client, TestCase + +from .utils import KudosContract + +logging.getLogger("requests").setLevel(logging.WARNING) +logging.getLogger("urllib3").setLevel(logging.WARNING) +logging.getLogger("web3").setLevel(logging.WARNING) + + +@unittest.skip(reason='Not creating fresh database and blockchain instances') +class KudosContractTestCase(TestCase): + def setUp(self): + self.contract = KudosContract(network='localhost') + self.metadata = { + 'name': 'pythonista', + 'image': '', + 'description': 'something', + 'external_url': 'http://localhost:8000/kudos', + 'background_color': 'fbfbfb', + 'attributes': [] + } + + def test_mint(self): + tokenURI_url = self.contract.create_tokenURI_url(**self.metadata) + args = ( + '0xD386793F1DB5F21609571C0164841E5eA2D33aD8', + 5, + 1, + tokenURI_url + ) + + self.contract.mint(*args) diff --git a/app/kudos/test_views.py b/app/kudos/test_views.py new file mode 100644 index 00000000000..4ee3430f72b --- /dev/null +++ b/app/kudos/test_views.py @@ -0,0 +1,97 @@ +# -*- coding: utf-8 -*- +"""Test the Kudos Views. + +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 . +""" +import logging +from unittest import skip + +from django.test import Client, TestCase + +# from .utils import KudosContract + +logging.getLogger("requests").setLevel(logging.WARNING) +logging.getLogger("urllib3").setLevel(logging.WARNING) +logging.getLogger("web3").setLevel(logging.WARNING) + + +class KudosViewsTestCase(TestCase): + def setUp(self): + self.client = Client() + + def test_about(self): + r = self.client.get('/kudos/') + self.assertEqual(r.status_code, 200) + r = self.client.get('/kudos/about/') + self.assertEqual(r.status_code, 200) + + def test_marketplace(self): + r = self.client.get('/kudos/marketplace/') + self.assertEqual(r.status_code, 200) + + r = self.client.get('/kudos/marketplace/?q=python') + self.assertEqual(r.status_code, 200) + + # @skip(reason='stub for future testing') + # def test_image(self): + # self.client.get('/kudos/1') + + # @skip(reason='stub for future testing') + # def test_details_by_address_and_token_id(self): + # c = Client() + # c.get('/kudos/1') + + # @skip(reason='stub for future testing') + # def test_details(self): + # self.client.get('/kudos/1') + + def test_mint(self): + r = self.client.get('/kudos/mint/') + self.assertEqual(r.status_code, 200) + + # @skip(reason='stub for future testing') + # def test_get_to_emails(self): + # self.client.get('/kudos/1') + + # @skip(reason='stub for future testing') + # def test_kudos_preferred_wallet(self): + # self.client.get('/kudos/1') + + # @skip(reason='stub for future testing') + # def test_tipee_address(self): + # self.client.get('/kudos/1') + + def test_send_2(self): + r = self.client.get('/kudos/send/') + self.assertEqual(r.status_code, 200) + # r = self.client.get('/kudos/send/?id=1') + # self.assertEqual(r.status_code, 200) + + # @skip(reason='stub for future testing') + # def test_send_3(self): + # self.client.get('/kudos/1') + + # @skip(reason='stub for future testing') + # def test_send_4(self): + # self.client.get('/kudos/1') + + # @skip(reason='stub for future testing') + # def test_record_kudos_email_activity(self): + # pass + + # @skip(reason='stub for future testing') + # def test_receive(self): + # pass diff --git a/app/kudos/utils.py b/app/kudos/utils.py new file mode 100644 index 00000000000..e8854a8f582 --- /dev/null +++ b/app/kudos/utils.py @@ -0,0 +1,640 @@ +# -*- coding: utf-8 -*- +"""Define utility functions. + +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 . + +""" +import json +import logging +import re +import time +from functools import wraps + +from django.conf import settings + +import ipfsapi +from dashboard.utils import get_web3 +from eth_utils import to_checksum_address +from kudos.models import Contract, KudosTransfer, Token +from web3.exceptions import BadFunctionCallOutput + +logger = logging.getLogger(__name__) + + +def humanize_name(name): + """Turn snake_case into Snake Case. + + Returns: + str: The humanized name. + + """ + return ' '.join([x.capitalize() for x in name.split('_')]) + + +def computerize_name(name): + """Turn Humanized Name into humanized_name. + + Returns: + str: computerized_name + """ + return name.lower().replace(' ', '_') + + +def get_rarity_score(num_clones_allowed): + """Calculate rarity metrics based on the num_clones_allowed. + + Args: + num_clones_allowed (int): Number of kudos clones allowed. + + Returns: + str: Rarity description. + + Raises: + ValueError: Raises an error if the number of clones allowed in less than one. + """ + if not isinstance(num_clones_allowed, int): + raise ValueError('num_clones_allowed must be an integer') + + if num_clones_allowed == 1: + return 'One of a Kind' + elif 2 <= num_clones_allowed <= 5: + return 'Legendary' + elif 6 <= num_clones_allowed <= 15: + return 'Ultra' + elif 16 <= num_clones_allowed <= 35: + return 'Very Rare' + elif 36 <= num_clones_allowed <= 100: + return 'Rare' + elif 101 <= num_clones_allowed <= 200: + return 'Special' + elif num_clones_allowed >= 201: + return 'Common' + else: + raise ValueError('num_clones_allowed must be greater than or equal to 1') + + +class KudosError(Exception): + """Base class for exceptions in this module.""" + pass + + +class KudosTransferNotFound(KudosError): + """ Exception is raised when web3 and the database are out of sync. + + + Attributes: + kudos_id -- the kudos id that has mismatched data + message -- explanation of the error + + """ + def __init__(self, kudos_id, message): + self.kudos_id = kudos_id + self.message = message + + +class KudosMismatch(KudosError): + """ Exception is raised when web3 and the database are out of sync. + + Attributes: + kudos_id -- the kudos id that has mismatched data + kudos_web3 -- kudos attributes on web3 + kudos_db -- kudos attritubes in the database + message -- explanation of the error + + """ + def __init__(self, kudos_id, kudos_web3, kudos_db, message): + self.kudos_id = kudos_id + self.kudos_web3 = kudos_web3 + self.kudos_db = kudos_db + self.message = message + + +class KudosContract: + """A class represending the Kudos.sol contract. + + Note: There are two types of interactions that can be done on the Solidity contract, + - call() + - transact() + + A call() is just a getter, and does not require gas, or an account to transact with. + A transact() or transaction requires gas and typically changes state on the contract. + + A transaction requires an account, because it needs somewhere to pull the gas from. + When working in Javascript and web3js, Metamask is used to handle this interaction. + When working in Python and web3py, there is no interaction with MetaMask so this + needs to be handled behind the scenes, by providing the account and private_key to + web3py to create the raw transaction. + + Attributes: + address (str): Eth address of the kudos contract + network (str): The blockchain network (localhost, rinkeby, ropsten, mainnet) + """ + + def __init__(self, network='localhost', sockets=False): + """Initialize the KudosContract. + + Args: + network (str, optional): The blockchain network (localhost, rinkeby, ropsten, mainnet) + sockets (bool, optional): Use web socket provider if set to True, otherwise use Http provider. + + """ + network = 'localhost' if network == 'custom network' else network + self.network = network + + self._w3 = get_web3(self.network, sockets=sockets) + + host = f'{settings.IPFS_API_SCHEME}://{settings.IPFS_HOST}' + self._ipfs = ipfsapi.connect(host=host, port=settings.IPFS_API_PORT) + self._contract = self._get_contract() + + self.address = self._get_contract_address() + + @staticmethod + def get_kudos_map(kudos, metadata): + """Pass in a kudos array that is returned from web3, convert to dictionary. + + Use this to operate on the database. + + Args: + kudos (list): A kudos object returned from the Kudos.sol contract. Soldidity returns + the Kudos strcut as an array. + metadata (dict): The metadata return from the tokenURI. + + Returns: + dict: Kudos dictionary with key/values to be used to interact with the database. + + """ + mapping = dict( + price_finney=kudos[0], + num_clones_allowed=kudos[1], + num_clones_in_wild=kudos[2], + cloned_from_id=kudos[3], + ) + + attributes = metadata.pop('attributes') + tags = [] + for attrib in attributes: + if attrib['trait_type'] == 'rarity': + mapping['rarity'] = attrib['value'] + elif attrib['trait_type'] == 'tag': + tags.append(attrib['value']) + elif attrib['trait_type'] == 'artist': + mapping['artist'] = attrib['value'] + elif attrib['trait_type'] == 'platform': + mapping['platform'] = attrib['value'] + + mapping['tags'] = ', '.join(tags) + + # Add the rest of the fields + kudos_map = {**mapping, **metadata} + + kudos_map['name'] = computerize_name(kudos_map['name']) + kudos_map['image'] = re.sub(r'http.*?static\/', '', kudos_map['image']) + + return kudos_map + + def may_require_key(f): + """Decorator to check if the operation needs a private key.""" + @wraps(f) + def wrapper(self, *args, **kwargs): + if self.network != 'localhost' and (kwargs['account'] is None or kwargs['private_key'] is None): + raise ValueError(f'Since you are on the {self.network} network, you must provide and account and private_key') + else: + return f(self, *args, **kwargs) + return wrapper + + def log_args(f): + """Decorator to log out the contract args.""" + @wraps(f) + def wrapper(self, *args, **kwargs): + logger.debug(f'args: {args}') + return f(self, *args, **kwargs) + return wrapper + + def retry(f): + """Decorator to retry a function if it failed.""" + @wraps(f) + def wrapper(self, *args, **kwargs): + for i in range(1, 4): + try: + f(self, *args, **kwargs) + except BadFunctionCallOutput as e: + logger.warning(f'A network error occurred when trying to mint the Kudos.') + logger.warning('Retrying...') + time.sleep(1) + continue + except KudosTransfer.DoesNotExist as e: + logger.warning('Retrying...') + time.sleep(1) + continue + break + return f(self, *args, **kwargs) + return wrapper + + @retry + def remove_kudos_orphans_db(self): + """DEPRECATED. This funciton must be updated to use. + Sync up existing kudos from the blockchain to the database. + + Then remove all "orphaned Kudos" from the database. + """ + + latest_id = self._contract.functions.getLatestId().call() + + # Remove orphaned Kudos in the database + orphans = Token.objects.filter(token_id__gt=latest_id) + for orphan in orphans: + logger.info('Removing Kudos orphan with ID: {orphan.id}') + orphans.delete() + + def sync_db_without_txid(self, kudos_id): + """DEPRECATED. + The regular sync_db method should be preferred over this. + + This method is only to be used if you are syncing kudos directly from the blockchain + and don't know the txid. + + The problem with not having a txid that is there is no good way to related it back + to the kudos_transfer object. Which means we don't know who the original sender is. + + Args: + kudos_id (int): Kudos id. + """ + kudos = self.getKudosById(kudos_id, to_dict=True) + kudos['owner_address'] = self._contract.functions.ownerOf(kudos_id).call() + kudos['contract_address'] = self._contract.address + kudos['network'] = self.network + if Token.objects.filter(token_id=kudos_id).exists(): + kudos_token = Token.objects.get(token_id=kudos_id) + kudos['txid'] = kudos_token.txid + updated_kudos_token = Token(token_id=kudos_id, **kudos) + updated_kudos_token.save() + else: + kudos_token = Token(token_id=kudos_id, **kudos) + kudos_token.save() + logger.info(f'Synced id #{kudos_token.token_id}, "{kudos_token.name}" kudos to the database.') + + def sync_db(self, kudos_id, txid): + """Sync up the Kudos contract on the blockchain with the database. + + Args: + kudos_id (int): Kudos Id + txid (str): The transaction hash. + """ + + # Handle the dummy Kudos + if kudos_id == 0: + return False + + # Grab the Kudos from the blockchain, augment with owner_address + kudos = self.getKudosById(kudos_id, to_dict=True) + kudos['owner_address'] = self._contract.functions.ownerOf(kudos_id).call() + + contract, created = Contract.objects.get_or_create( + address=self._contract.address, + network=self.network, + defaults=dict(is_latest=True) + ) + if created: + old_contracts = Contract.objects.filter(network=self.network).exclude(id=contract.id) + old_contracts.update(is_latest=False) + + # Update an existing Kudos in the database or create a new one + kudos['txid'] = txid + kudos_token, created = Token.objects.update_or_create(token_id=kudos_id, contract=contract, defaults=kudos) + # Update the cloned_from_id kudos. Namely the num_clones_in_wild field should be updated. + if created: + self.sync_db(kudos_id=kudos_token.cloned_from_id, txid=txid) + # Find the object which matches the kudos that was just cloned + try: + kudos_transfer = KudosTransfer.objects.get(receive_txid=txid) + except KudosTransfer.DoesNotExist: + # Only warn for a Kudos that is cloned/transfered, not a Gen0 Kudos. + if kudos_token.num_clones_allowed == 0: + logger.warning(f'No KudosTransfer object found for Kudos ID {kudos_id}') + # raise KudosTransferNotFound(kudos_id, 'No KudosTransfer object found') + # raise + else: + # Store the foreign key reference if the kudos_transfer object exists + kudos_transfer.kudos_token = kudos_token + kudos_transfer.save() + + logger.info(f'Synced id #{kudos_token.token_id}, "{kudos_token.name}" kudos to the database.') + + def _get_contract_address(self): + """Get the Kudos contract address, depending on the network. + + Returns: + str: Kudos contract address. + """ + if self.network == 'mainnet': + return to_checksum_address(settings.KUDOS_CONTRACT_MAINNET) + elif self.network == 'ropsten': + return to_checksum_address(settings.KUDOS_CONTRACT_ROPSTEN) + elif self.network == 'rinkeby': + return to_checksum_address(settings.KUDOS_CONTRACT_RINKEBY) + elif self.network == 'localhost' or self.network == 'custom network': + # local testrpc + return to_checksum_address(settings.KUDOS_CONTRACT_TESTRPC) + else: + raise ValueError('Unsupported network') + + def _get_contract(self): + """Load up the Kudos ABI from a .json file. + + Returns: + obj: Web3py contract object. + """ + with open('kudos/Kudos.json') as f: + abi = json.load(f) + address = self._get_contract_address() + return self._w3.eth.contract(address=address, abi=abi) + + def _resolve_account(self, account): + """ + This method will return one of the following: + - the checksummed account address if the account is given + - the local account if it can find it + - raise an error if it can't resolve the account + + Args: + account (str): The ethereum public account address. + + Returns: + str: The eth address of the account. + + TODO: Should be consistent if we are returning a check summed address or not. + + Raises: + RuntimeError: Return an error if it can't resolve the account. + + """ + if account: + return to_checksum_address(account) + else: + try: + return self._w3.eth.accounts[0] + except IndexError: + raise RuntimeError('Please specify an account to use for transacting with the Kudos Contract.') + + @log_args + @may_require_key + def mint(self, *args, account=None, private_key=None, skip_sync=False, gas_price_gwei=None): + """Contract transaction method. + + Mint a new Gen0 Kudos on the blockchain. Not to be confused with clone. + A clone() operation is only valid for an already existing Gen0 Kudos. + + From Kudos.sol: + + Args: + *args: From Kudos.sol: + mint( + address _to, + uint256 _priceFinney, + uint256 _numClonesAllowed, + string _tokenURI, + ) + account (str, optional): Public account address. Not needed for localhost testing. + private_key (str, optional): Private key for account. Not needed for localhost testing. + skip_sync (bool, optional): If True, don't sync the database after the mint. + + Returns: + int: If a sync did occur, returns the kudos_id + """ + account = self._resolve_account(account) + + if private_key: + logger.debug('Private key found, creating raw transaction for Kudos mint...') + nonce = self._w3.eth.getTransactionCount(account) + gas_estimate = self._contract.functions.mint(*args).estimateGas({'nonce': nonce, 'from': account}) + logger.debug(f'Gas estimate for raw tx: {gas_estimate}') + if gas_price_gwei: + gasPrice = self._w3.toWei(gas_price_gwei, 'gwei') + txn = self._contract.functions.mint(*args).buildTransaction( + {'gasPrice': gasPrice, 'gas': gas_estimate, 'nonce': nonce, 'from': account} + ) + else: + txn = self._contract.functions.mint(*args).buildTransaction( + {'gas': gas_estimate, 'nonce': nonce, 'from': account} + ) + signed_txn = self._w3.eth.account.signTransaction(txn, private_key=private_key) + tx_hash = self._w3.eth.sendRawTransaction(signed_txn.rawTransaction) + else: + logger.debug('No private key provided, using local signing...') + tx_hash = self._contract.functions.mint(*args).transact({"from": account}) + + tx_receipt = self._w3.eth.waitForTransactionReceipt(tx_hash) + logger.debug(f'Tx hash: {tx_hash.hex()}') + + kudos_id = self._contract.functions.getLatestId().call() + logger.info(f'Minted id #{kudos_id} on the blockchain.') + logger.info(f'Gas usage for id #{kudos_id}: {tx_receipt["gasUsed"]}') + + if not skip_sync: + self.sync_db(kudos_id=kudos_id, txid=tx_hash.hex()) + + return kudos_id + + @may_require_key + def clone(self, *args, account=None, private_key=None, skip_sync=False): + """Contract transaction method. + + Args: + *args: From Kudos.sol + clone( + address _to, + uint256 _tokenId, + uint256 numClonesRequested + ) + account (str, optional): Public account address. Not needed for localhost testing. + private_key (str, optional): Private key for account. Not needed for localhost testing. + skip_sync (bool, optional): If True, don't sync the database after the mint. + + Returns: + int: The kudos_id + """ + account = self._resolve_account(account) + price_finney = self.getKudosById(args[1], to_dict=True)['price_finney'] + price_wei = self._w3.toWei(price_finney, 'finney') + + if private_key: + logger.debug('Private key found, creating raw transaction...') + nonce = self._w3.eth.getTransactionCount(account) + gas_estimate = self._contract.functions.clone(*args).estimateGas({'nonce': nonce, 'from': account, 'value': price_wei}) + txn = self._contract.functions.clone(*args).buildTransaction({'gas': gas_estimate, 'nonce': nonce, 'from': account, 'value': price_wei}) + signed_txn = self._w3.eth.account.signTransaction(txn, private_key=private_key) + tx_hash = self._w3.eth.sendRawTransaction(signed_txn.rawTransaction) + else: + logger.debug('No private key provided, using local signing...') + tx_hash = self._contract.functions.clone(*args).transact({"from": account, "value": price_wei}) + + tx_receipt = self._w3.eth.waitForTransactionReceipt(tx_hash) + logger.debug(f'Tx hash: {tx_hash.hex()}') + + kudos_id = self._contract.functions.getLatestId().call() + logger.info(f'Cloned a new Kudos. id #{kudos_id} on the blockchain.') + logger.info(f'Gas usage for id #{kudos_id}: {tx_receipt["gasUsed"]}') + + if not skip_sync: + self.sync_db(kudos_id=kudos_id, txid=tx_hash.hex()) + + return kudos_id + + @may_require_key + def burn(self, *args, account=None, private_key=None, skip_sync=False): + """Contract transaction method. + + Args: + *args: From Kudos.sol + burn( + address _owner, + uint256 _tokenId, + ) + account (str, optional): Public account address. Not needed for localhost testing. + private_key (str, optional): Private key for account. Not needed for localhost testing. + skip_sync (bool, optional): If True, don't sync the database after the mint. + + Returns: + int: The kudos_id + """ + account = self._resolve_account(account) + kudos_id = args[1] + + if private_key: + logger.debug('Private key found, creating raw transaction...') + nonce = self._w3.eth.getTransactionCount(account) + gas_estimate = self._contract.functions.burn(*args).estimateGas({'nonce': nonce, 'from': account}) + txn = self._contract.functions.burn(*args).buildTransaction({'gas': gas_estimate, 'nonce': nonce, 'from': account}) + signed_txn = self._w3.eth.account.signTransaction(txn, private_key=private_key) + tx_hash = self._w3.eth.sendRawTransaction(signed_txn.rawTransaction) + else: + logger.debug('No private key provided, using local signing...') + tx_hash = self._contract.functions.burn(*args).transact({"from": account}) + + tx_receipt = self._w3.eth.waitForTransactionReceipt(tx_hash) + logger.debug(f'Tx hash: {tx_hash.hex()}') + + logger.info(f'Burned Kudos with id #{kudos_id} on the blockchain.') + logger.info(f'Gas usage to burn id #{kudos_id}: {tx_receipt["gasUsed"]}') + + if not skip_sync: + self.sync_db(kudos_id=kudos_id, txid=tx_hash.hex()) + + return kudos_id + + def getKudosById(self, *args, to_dict=False): + """Contract call method. + + Args: + *args: From Kudos.sol: + getKudosById(uint256 tokenId) + to_dict (bool, optional): Return a dictionary mapping instead of an array. + + Returns: + list or dict: From Kudos.sol: + returns (uint256 priceFinney, uint256 numClonesAllowed, + uint256 numClonesInWild, uint256 clonedFromId + ) + """ + kudos = self._contract.functions.getKudosById(args[0]).call() + tokenURI = self._contract.functions.tokenURI(args[0]).call() + ipfs_hash = tokenURI.split('/')[-1] + + metadata = self._ipfs.get_json(ipfs_hash) + + if to_dict: + return self.get_kudos_map(kudos, metadata) + else: + return kudos + + def getLatestId(self): + """Contract call method. + + From Kudos.sol: + getLatestId() view public returns (uint256 tokenId) + + Returns: + int: The latest token id. + """ + return self._contract.functions.getLatestId().call() + + def gen0_exists_db(self, kudos_name): + """Helper method. + + Args: + kudos_name (TYPE): Description + + Returns: + TYPE: Description + """ + kudos_name = Token.objects.filter(name__iexact=kudos_name).first() + if not kudos_name: + return False + else: + return True + + def create_tokenURI_url(self, **kwargs): + """Create a tokenURI object, upload it to IPFS, and return the URL. + + Keyword Args: + name (str): Name of the kudos. + image (str): Image location of the kudos. Should be a link to an image on the web. + description (str): Word description of the kudos. + attributes (dict): Dictionary containing attirbutes of the kudos. + tags (str): comma delimited tags. + number_of_clones_allowed (int): self explanatory. + rarity (int): integer from 0 to 100 (0 is most common). + external_url (str): External link to where the Kudos lives on the Gitcoin site. + background_color (str): Hex code. + + Returns: + str: URL location on IPFS where the URI data is stored. + """ + tokenURI = kwargs + logger.debug(f'tokenURI: {tokenURI}') + ipfs_hash = self._ipfs.add_json(tokenURI) + ipfs_url = f'{settings.IPFS_API_SCHEME}://{settings.IPFS_HOST}:{settings.IPFS_API_PORT}/api/v0/cat/{ipfs_hash}' + name = kwargs['name'] + logger.info(f'Posted metadata for "{name}" to IPFS.') + logger.debug(f'ipfs_url for {kwargs["name"]}: {ipfs_url.replace("ipfs:", "localhost:")}') + + return ipfs_url + + +def get_to_emails(params): + """Get a list of email address to send the alert to, in this priority: + + 1. get_emails_master() pulls email addresses from the user's public Github account. + 2. If an email address is included in the Tips/Kudos form, append that to the email list. + + + Args: + params (dict): A dictionary parsed form the POST request. Typically this is a POST + request coming in from a Tips/Kudos send. + + Returns: + list: An array of email addresses to send the email to. + """ + to_emails = [] + + to_username = params['username'].lstrip('@') + to_emails = get_emails_master(to_username) + + if params.get('email'): + to_emails.append(params['email']) + + return list(set(to_emails)) diff --git a/app/kudos/views.py b/app/kudos/views.py new file mode 100644 index 00000000000..30aecde99a1 --- /dev/null +++ b/app/kudos/views.py @@ -0,0 +1,523 @@ +# -*- coding: utf-8 -*- +"""Define view for the Kudos app. + +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 . + +""" + +import json +import logging +import re + +from django.conf import settings +from django.contrib import messages +from django.contrib.postgres.search import SearchVector +from django.contrib.staticfiles.templatetags.staticfiles import static +from django.http import Http404, HttpResponse, JsonResponse +from django.shortcuts import get_object_or_404, redirect +from django.template.response import TemplateResponse +from django.utils import timezone +from django.utils.translation import gettext_lazy as _ +from django.views.decorators.csrf import csrf_exempt + +from dashboard.models import Activity, Profile +from dashboard.notifications import maybe_market_kudos_to_email +from dashboard.utils import get_web3 +from dashboard.views import record_user_action +from eth_utils import is_address, to_checksum_address, to_normalized_address +from gas.utils import recommend_min_gas_price_to_confirm_in_time +from git.utils import get_emails_master, get_github_primary_email +from ratelimit.decorators import ratelimit +from retail.helpers import get_ip +from web3 import Web3 + +from .forms import KudosSearchForm +from .helpers import get_token +from .models import KudosTransfer, Token + +logger = logging.getLogger(__name__) + +confirm_time_minutes_target = 4 + + +def get_profile(handle): + """Get the gitcoin profile. + TODO: This might be depreacted in favor of the sync_profile function in the future. + + Args: + handle (str): The github handle. + + Returns: + obj: The profile model object. + """ + try: + to_profile = Profile.objects.get(handle__iexact=handle) + except Profile.MultipleObjectsReturned: + to_profile = Profile.objects.filter(handle__iexact=handle).order_by('-created_on').first() + except Profile.DoesNotExist: + to_profile = None + return to_profile + + +def about(request): + """Render the Kudos 'about' page.""" + listings = Token.objects.filter( + num_clones_allowed__gt=0, + contract__is_latest=True, + contract__network=settings.KUDOS_NETWORK, + ).order_by('-created_on') + context = { + 'is_outside': True, + 'active': 'about', + 'title': 'About Kudos', + 'card_title': _('Each Kudos is a unique work of art.'), + 'card_desc': _('It can be sent to highlight, recognize, and show appreciation.'), + 'avatar_url': static('v2/images/kudos/assets/kudos-image.png'), + "listings": listings + } + return TemplateResponse(request, 'kudos_about.html', context) + + +def marketplace(request): + """Render the Kudos 'marketplace' page.""" + q = request.GET.get('q') + order_by = request.GET.get('order_by', '-created_on') + logger.info(order_by) + logger.info(q) + title = q.title() + str(_(" Kudos ")) if q else str(_('Kudos Marketplace')) + + if q: + listings = Token.objects.annotate( + search=SearchVector('name', 'description', 'tags') + ).filter( + # Only show the latest contract Kudos for the current network + num_clones_allowed__gt=0, + contract__is_latest=True, + contract__network=settings.KUDOS_NETWORK, + search=q + ).order_by(order_by) + else: + listings = Token.objects.filter( + num_clones_allowed__gt=0, + contract__is_latest=True, + contract__network=settings.KUDOS_NETWORK, + ).order_by(order_by) + context = { + 'is_outside': True, + 'active': 'marketplace', + 'title': title, + 'card_title': _('Each Kudos is a unique work of art.'), + 'card_desc': _('It can be sent to highlight, recognize, and show appreciation.'), + 'avatar_url': static('v2/images/kudos/assets/kudos-image.png'), + 'listings': listings, + 'network': settings.KUDOS_NETWORK + } + + return TemplateResponse(request, 'kudos_marketplace.html', context) + + +def search(request): + """Render the search page. + TODO: This might no longer be used. + """ + context = {} + + if request.method == 'GET': + form = KudosSearchForm(request.GET) + context = {'form': form} + + return TemplateResponse(request, 'kudos_marketplace.html', context) + + +def image(request, kudos_id, name): + + kudos = Token.objects.get(pk=kudos_id) + img = kudos.as_img + if not img: + raise Http404 + + response = HttpResponse(img.getvalue(), content_type='image/png') + response['Content-Disposition'] = 'attachment; filename=kudos.png' + return response + + +def details_by_address_and_token_id(request, address, token_id, name): + kudos = get_token(token_id=token_id, network=settings.KUDOS_NETWORK, address=address) + return redirect(f'/kudos/{kudos.id}/{kudos.name}') + + +def details(request, kudos_id, name): + """Render the Kudos 'detail' page.""" + if not re.match(r'\d+', kudos_id): + raise ValueError(f'Invalid Kudos ID found. ID is not a number: {kudos_id}') + + # Find other profiles that have the same kudos name + kudos = get_object_or_404(Token, pk=kudos_id) + # Find other Kudos rows that are the same kudos.name, but of a different owner + related_kudos = Token.objects.select_related('contract').filter( + name=kudos.name, + num_clones_allowed=0, + contract__network=settings.KUDOS_NETWORK, + ) + # Find the Wallet rows that match the Kudos.owner_addresses + # related_wallets = Wallet.objects.filter(address__in=[rk.owner_address for rk in related_kudos]).distinct()[:20] + + # Find the related Profiles assuming the preferred_payout_address is the kudos owner address. + # Note that preferred_payout_address is most likely in normalized form. + # https://eth-utils.readthedocs.io/en/latest/utilities.html#to-normalized-address-value-text + owner_addresses = [ + to_normalized_address(rk.owner_address) if is_address(rk.owner_address) is not False else None + for rk in related_kudos + ] + related_profiles = Profile.objects.filter(preferred_payout_address__in=owner_addresses).distinct()[:20] + # profile_ids = [rw.profile_id for rw in related_wallets] + + # Avatar can be accessed via Profile.avatar + # related_profiles = Profile.objects.filter(pk__in=profile_ids).distinct() + + context = { + 'is_outside': True, + 'active': 'details', + 'title': 'Details', + 'card_title': _('Each Kudos is a unique work of art.'), + 'card_desc': _('It can be sent to highlight, recognize, and show appreciation.'), + 'avatar_url': static('v2/images/kudos/assets/kudos-image.png'), + 'kudos': kudos, + 'related_profiles': related_profiles, + } + if kudos: + token = Token.objects.select_related('contract').get( + token_id=kudos.cloned_from_id, + contract__address=kudos.contract.address, + ) + # The real num_cloned_in_wild is only stored in the Gen0 Kudos token + kudos.num_clones_in_wild = token.num_clones_in_wild + # Create a new attribute to reference number of gen0 clones allowed + kudos.num_gen0_clones_allowed = token.num_clones_allowed + + context['title'] = kudos.humanized_name + context['card_title'] = kudos.humanized_name + context['card_desc'] = kudos.description + context['avatar_url'] = kudos.img_url + context['kudos'] = kudos + + return TemplateResponse(request, 'kudos_details.html', context) + + +def mint(request): + """Render the Kudos 'mint' page. This is mostly a placeholder for future functionality.""" + return TemplateResponse(request, 'kudos_mint.html', {}) + + +def get_primary_from_email(params, request): + """Find the primary_from_email address. This function finds the address using this priority: + + 1. If the email field is filed out in the Send POST request, use the `fromEmail` field. + 2. If the user is logged in, they should have an email address associated with their account. + Use this as the second option. `request_user_email`. + 3. If all else fails, attempt to pull the email from the user's github account. + + Args: + params (dict): A dictionary parsed form the POST request. Typically this is a POST + request coming in from a Tips/Kudos send. + + Returns: + str: The primary_from_email string. + """ + + request_user_email = request.user.email if request.user.is_authenticated else '' + logger.info(request.user.profile) + access_token = request.user.profile.get_access_token() if request.user.is_authenticated else '' + + if params.get('fromEmail'): + primary_from_email = params['fromEmail'] + elif request_user_email: + primary_from_email = request_user_email + elif access_token: + primary_from_email = get_github_primary_email(access_token) + else: + primary_from_email = 'unknown@gitcoin.co' + + return primary_from_email + + +def kudos_preferred_wallet(request, handle): + """Returns the address, if any, that someone would like to be send kudos directly to.""" + response = { + 'addresses': [] + } + + profile = get_profile(str(handle).replace('@', '')) + + if profile: + # reconcile_kudos_preferred_wallet(profile) + if profile.preferred_payout_address: + response['addresses'].append(profile.preferred_payout_address) + + return JsonResponse(response) + + +@ratelimit(key='ip', rate='5/m', method=ratelimit.UNSAFE, block=True) +def send_2(request): + """Handle the first start of the Kudos email send. + + This form is filled out before the 'send' button is clicked. + + """ + id = request.GET.get('id') + kudos = Token.objects.filter(pk=id).first() + params = { + 'active': 'send', + 'issueURL': request.GET.get('source'), + 'class': 'send2', + 'recommend_gas_price': recommend_min_gas_price_to_confirm_in_time(confirm_time_minutes_target), + 'from_email': getattr(request.user, 'email', ''), + 'from_handle': request.user.username, + 'title': _('Send Kudos | Gitcoin'), + 'card_desc': _('Send a Kudos to any github user at the click of a button.'), + 'kudos': kudos, + } + return TemplateResponse(request, 'transaction/send.html', params) + + +@csrf_exempt +@ratelimit(key='ip', rate='5/m', method=ratelimit.UNSAFE, block=True) +def send_3(request): + """Handle the third stage of sending a kudos (the POST). + + This function is derived from send_tip_3. + The request to send the kudos is added to the database, but the transaction + has not happened yet. The txid is added in `send_kudos_4`. + + Returns: + JsonResponse: The response with success state. + + """ + response = { + 'status': 'OK', + 'message': _('Kudos Created'), + } + + is_user_authenticated = request.user.is_authenticated + from_username = request.user.username if is_user_authenticated else '' + primary_from_email = request.user.email if is_user_authenticated else '' + access_token = request.user.profile.get_access_token() if is_user_authenticated else '' + to_emails = [] + + params = json.loads(request.body) + + to_username = params.get('username', '').lstrip('@') + to_emails = get_emails_master(to_username) + + email = params.get('email') + if email: + to_emails.append(email) + + # If no primary email in session, try the POST data. If none, fetch from GH. + primary_from_email = params.get('fromEmail') + + if access_token and not primary_from_email: + primary_from_email = get_github_primary_email(access_token) + + to_emails = list(set(to_emails)) + + # Validate that the token exists on the back-end + kudos_id = params.get('kudosId') + if not kudos_id: + raise Http404 + + try: + kudos_token_cloned_from = Token.objects.get(pk=kudos_id) + except Token.DoesNotExist: + raise Http404 + + # db mutations + KudosTransfer.objects.create( + emails=to_emails, + # For kudos, `token` is a kudos.models.Token instance. + kudos_token_cloned_from=kudos_token_cloned_from, + amount=params['amount'], + comments_public=params['comments_public'], + ip=get_ip(request), + github_url=params['github_url'], + from_name=params['from_name'], + from_email=params['from_email'], + from_username=from_username, + username=params['username'], + network=params['network'], + tokenAddress=params['tokenAddress'], + from_address=params['from_address'], + is_for_bounty_fulfiller=params['is_for_bounty_fulfiller'], + metadata=params['metadata'], + recipient_profile=get_profile(to_username), + sender_profile=get_profile(from_username), + ) + + return JsonResponse(response) + + +@csrf_exempt +@ratelimit(key='ip', rate='5/m', method=ratelimit.UNSAFE, block=True) +def send_4(request): + """Handle the fourth stage of sending a tip (the POST). Once the metamask transaction is complete, + add it to the database. + + Returns: + JsonResponse: response with success state. + + """ + response = { + 'status': 'OK', + 'message': _('Kudos Sent'), + } + params = json.loads(request.body) + from_username = request.user.username + txid = params['txid'] + destination_account = params['destinationAccount'] + is_direct_to_recipient = params.get('is_direct_to_recipient', False) + kudos_transfer = KudosTransfer.objects.get( + metadata__address=destination_account, + metadata__creation_time=params['creation_time'], + metadata__salt=params['salt'], + ) + + # Return Permission Denied if not authenticated + is_authenticated_via_login = (kudos_transfer.from_username and kudos_transfer.from_username == from_username) + is_authenticated_for_this_via_ip = kudos_transfer.ip == get_ip(request) + is_authed = is_authenticated_for_this_via_ip or is_authenticated_via_login + + if not is_authed: + return JsonResponse({'status': 'error', 'message': _('Permission Denied')}, status=401) + + # Save the txid to the database once it has been confirmed in MetaMask. If there is no txid, + # it means that the user never went through with the transaction. + kudos_transfer.txid = txid + if is_direct_to_recipient: + kudos_transfer.receive_txid = txid + kudos_transfer.save() + + # notifications + maybe_market_kudos_to_email(kudos_transfer) + # record_user_action(kudos_transfer.from_username, 'send_kudos', kudos_transfer) + # record_kudos_activity(kudos_transfer, kudos_transfer.from_username, 'new_kudos' if kudos_transfer.username else 'new_crowdfund') + return JsonResponse(response) + + +def record_kudos_email_activity(kudos_transfer, github_handle, event_name): + kwargs = { + 'activity_type': event_name, + 'kudos_transfer': kudos_transfer, + 'metadata': { + 'amount': str(kudos_transfer.amount), + 'token_name': kudos_transfer.tokenName, + 'value_in_eth': str(kudos_transfer.value_in_eth), + 'value_in_usdt_now': str(kudos_transfer.value_in_usdt_now), + 'github_url': kudos_transfer.github_url, + 'to_username': kudos_transfer.username, + 'from_name': kudos_transfer.from_name, + 'received_on': str(kudos_transfer.received_on) if kudos_transfer.received_on else None + } + } + try: + kwargs['profile'] = Profile.objects.get(handle=github_handle) + except Profile.MultipleObjectsReturned: + kwargs['profile'] = Profile.objects.filter(handle__iexact=github_handle).first() + except Profile.DoesNotExist: + logging.error(f"error in record_kudos_email_activity: profile with github name {github_handle} not found") + return + try: + kwargs['bounty'] = kudos_transfer.bounty + except KudosTransfer.DoesNotExist: + logger.info('No bounty is associated with this kudos transfer.') + + try: + Activity.objects.create(**kwargs) + except Exception as e: + logging.error(f"error in record_kudos_email_activity: {e} - {event_name} - {kudos_transfer} - {github_handle}") + + +def receive(request, key, txid, network): + """Handle the receiving of a kudos (the POST). + + Returns: + TemplateResponse: the UI with the kudos confirmed + + """ + + if request.method == 'POST': + logger.info('method is post') + + these_kudos_emails = KudosTransfer.objects.filter(web3_type='v3', txid=txid, network=network) + kudos_emails = these_kudos_emails.filter(metadata__reference_hash_for_receipient=key) | these_kudos_emails.filter( + metadata__reference_hash_for_funder=key) + kudos_transfer = kudos_emails.first() + is_authed = request.user.username.replace('@', '') in [ + kudos_transfer.username.replace('@', ''), + kudos_transfer.from_username.replace('@', '') + ] + not_mined_yet = get_web3(kudos_transfer.network).eth.getBalance( + Web3.toChecksumAddress(kudos_transfer.metadata['address'])) == 0 + + if not request.user.is_authenticated or request.user.is_authenticated and not getattr( + request.user, 'profile', None + ): + login_redirect = redirect('/login/github?next=' + request.get_full_path()) + return login_redirect + + if kudos_transfer.receive_txid: + messages.info(request, _('This kudos has been received')) + elif not is_authed: + messages.error( + request, f'This kudos is for {kudos_transfer.username} but you are logged in as {request.user.username}. Please logout and log back in as {kudos_transfer.username}.') + elif not_mined_yet and not request.GET.get('receive_txid'): + messages.info( + request, f'This tx {kudos_transfer.txid}, is still mining. Please wait a moment before submitting the receive form.') + elif request.GET.get('receive_txid') and not kudos_transfer.receive_txid: + params = request.GET + + # db mutations + try: + if params['save_addr']: + profile = get_profile(kudos_transfer.username) + if profile: + # TODO: Does this mean that the address the user enters in the receive form + # Will overwrite an already existing preferred_payout_address? Should we + # ask the user to confirm this? + profile.preferred_payout_address = params['forwarding_address'] + profile.save() + kudos_transfer.receive_txid = params['receive_txid'] + kudos_transfer.receive_address = params['forwarding_address'] + kudos_transfer.received_on = timezone.now() + kudos_transfer.save() + record_user_action(kudos_transfer.from_username, 'receive_kudos', kudos_transfer) + record_kudos_email_activity(kudos_transfer, kudos_transfer.username, 'receive_kudos') + messages.success(request, _('This kudos has been received')) + except Exception as e: + messages.error(request, str(e)) + logger.exception(e) + + params = { + 'issueURL': request.GET.get('source'), + 'class': 'receive', + 'title': _('Receive Kudos'), + 'gas_price': round(recommend_min_gas_price_to_confirm_in_time(120), 1), + 'kudos_transfer': kudos_transfer, + 'key': key, + 'is_authed': is_authed, + 'disable_inputs': kudos_transfer.receive_txid or not_mined_yet or not is_authed, + } + + return TemplateResponse(request, 'transaction/receive.html', params) diff --git a/app/marketing/mails.py b/app/marketing/mails.py index 9651f93ffbb..219855cee14 100644 --- a/app/marketing/mails.py +++ b/app/marketing/mails.py @@ -17,6 +17,8 @@ along with this program. If not, see . """ +import logging + from django.conf import settings from django.utils import timezone, translation from django.utils.translation import gettext @@ -28,21 +30,24 @@ from retail.emails import ( render_admin_contact_funder, render_bounty_changed, render_bounty_expire_warning, render_bounty_feedback, render_bounty_startwork_expire_warning, render_bounty_unintersted, render_faucet_rejected, render_faucet_request, - render_funder_stale, 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_funder_stale, render_gdpr_reconsent, render_gdpr_update, render_kudos_email, 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, ) from sendgrid.helpers.mail import Content, Email, Mail, Personalization from sendgrid.helpers.stats import Category +logger = logging.getLogger(__name__) + def send_mail(from_email, _to_email, subject, body, html=False, - from_name="Gitcoin.co", cc_emails=None, categories=None): + from_name="Gitcoin.co", cc_emails=None, categories=None, debug_mode=False): """Send email via SendGrid.""" # make sure this subscriber is saved if not settings.SENDGRID_API_KEY: - print('No SendGrid API Key set. Not attempting to send email.') + logger.warning('No SendGrid API Key set. Not attempting to send email.') return if categories is None: @@ -61,9 +66,13 @@ def send_mail(from_email, _to_email, subject, body, html=False, # build content content = Content(contenttype, html) if html else Content(contenttype, body) - if settings.IS_DEBUG_ENV: + + # TODO: A bit of a hidden state change here. Really confusing when doing development. + # Maybe this should be a variable passed into the function the value is set upstream? + if settings.IS_DEBUG_ENV or debug_mode: to_email = Email(settings.CONTACT_EMAIL) # just to be double secret sure of what were doing in dev subject = _("[DEBUG] ") + subject + mail = Mail(from_email, subject, to_email, content) response = None @@ -84,15 +93,14 @@ def send_mail(from_email, _to_email, subject, body, html=False, mail.add_category(Category(category)) # debug logs - print(f"-- Sending Mail '{subject}' to {_to_email}") - - # send mails + logger.info(f"-- Sending Mail '{subject}' to {to_email}") try: response = sg.client.mail.send.post(request_body=mail.get()) - except UnauthorizedError: - print(f'-- Sendgrid Mail failure - Unauthorized - Check sendgrid credentials') + except UnauthorizedError as e: + logger.error(f'-- Sendgrid Mail failure - Unauthorized - Check sendgrid credentials') + logger.error(e) except HTTPError as e: - print(f'-- Sendgrid Mail failure - {e}') + logger.error(f'-- Sendgrid Mail failure - {e}') return response diff --git a/app/marketing/utils.py b/app/marketing/utils.py index 2a4a2daee6e..70997425f64 100644 --- a/app/marketing/utils.py +++ b/app/marketing/utils.py @@ -153,6 +153,7 @@ def validate_discord_integration(webhook_url, message=None, icon_url=''): result['output'] = _('An error has occurred.') return result + def should_suppress_notification_email(email, email_type): from marketing.models import EmailSubscriber queryset = EmailSubscriber.objects.filter(email__iexact=email) diff --git a/app/retail/emails.py b/app/retail/emails.py index d266064b8ec..4c37ebf00fc 100644 --- a/app/retail/emails.py +++ b/app/retail/emails.py @@ -17,6 +17,7 @@ ''' import logging +from functools import partial from django.conf import settings from django.contrib import messages @@ -34,6 +35,8 @@ from marketing.utils import get_or_save_email_subscriber from retail.utils import strip_double_chars, strip_html +logger = logging.getLogger(__name__) + # RENDERERS # key, name, frequency @@ -94,6 +97,48 @@ def render_tip_email(to_email, tip, is_new): return response_html, response_txt +def render_kudos_email(to_email, kudos_transfer, is_new, html_template, text_template=None): + """Summary + + Args: + to_emails (list): An array of email addresses to send the email to. + kudos_transfer (model): An instance of the `kudos.model.KudosTransfer` object. This contains the information about the kudos that will be cloned. + is_new (TYPE): Description + + Returns: + tup: response_html, response_txt + """ + warning = kudos_transfer.network if kudos_transfer.network != 'mainnet' else "" + already_redeemed = bool(kudos_transfer.receive_txid) + link = kudos_transfer.receive_url_for_recipient + params = { + 'link': link, + 'amount': round(kudos_transfer.amount, 5), + 'token_elem': kudos_transfer.kudos_token, + 'kudos_token:': kudos_transfer.kudos_token, + 'comments_public': kudos_transfer.comments_public, + 'kudos_transfer': kudos_transfer, + 'already_redeemed': already_redeemed, + 'is_new': is_new, + 'warning': warning, + 'subscriber': get_or_save_email_subscriber(to_email, 'internal'), + 'is_sender': to_email not in kudos_transfer.emails, + 'is_receiver': to_email in kudos_transfer.emails, + } + + response_html = premailer_transform(render_to_string(html_template, params)) + response_txt = render_to_string(text_template, params) if text_template else None + + return response_html, response_txt + + +render_new_kudos_email = partial(render_kudos_email, html_template='emails/new_kudos.html', text_template='emails/new_kudos.txt') +render_sent_kudos_email = partial(render_kudos_email, html_template='emails/new_kudos.html', text_template='emails/new_kudos.txt') +render_kudos_accepted_email = partial(render_kudos_email, html_template='emails/new_kudos.html', text_template='emails/new_kudos.txt') +render_kudos_mint_email = partial(render_kudos_email, html_template='emails/kudos_mint.html', text_template=None) +render_kudos_mkt_email = partial(render_kudos_email, html_template='emails/kudos_mkt.html', text_template=None) + + def render_match_email(bounty, github_username): params = { 'bounty': bounty, @@ -655,6 +700,33 @@ def new_tip(request): return HttpResponse(response_html) +@staff_member_required +def new_kudos(request): + from kudos.models import KudosTransfer + kudos_transfer = KudosTransfer.objects.last() + response_html, _ = render_new_kudos_email(settings.CONTACT_EMAIL, kudos_transfer, True) + + return HttpResponse(response_html) + + +@staff_member_required +def kudos_mint(request): + from kudos.models import KudosTransfer + kudos_transfer = KudosTransfer.objects.last() + response_html, _ = render_kudos_mint_email(settings.CONTACT_EMAIL, kudos_transfer, True) + + return HttpResponse(response_html) + + +@staff_member_required +def kudos_mkt(request): + from kudos.models import KudosTransfer + kudos_transfer = KudosTransfer.objects.last() + response_html, _ = render_kudos_mkt_email(settings.CONTACT_EMAIL, kudos_transfer, True) + + return HttpResponse(response_html) + + @staff_member_required def new_match(request): from dashboard.models import Bounty diff --git a/app/retail/templates/about.html b/app/retail/templates/about.html index 7da62043e6d..44bdbf242bc 100644 --- a/app/retail/templates/about.html +++ b/app/retail/templates/about.html @@ -27,6 +27,7 @@ {% include 'shared/tag_manager_2.html' %}
          + {% include 'shared/top_nav.html' with class='d-md-flex' %} {% include 'shared/nav.html' %} {% include 'shared/minihero.html' with h1='About' %}
          diff --git a/app/retail/templates/activity.html b/app/retail/templates/activity.html index cf1bc7c25d8..876049307a8 100644 --- a/app/retail/templates/activity.html +++ b/app/retail/templates/activity.html @@ -29,6 +29,7 @@ {% include 'shared/tag_manager_2.html' %}
          + {% include 'shared/top_nav.html' with class='d-md-flex' %} {% include 'shared/nav.html' %} {% include 'shared/minihero.html' with h1='Activity Feed' position_h1_below_logo=1 %}
          diff --git a/app/retail/templates/base.html b/app/retail/templates/base.html index e5fa7f502e4..9b551555593 100644 --- a/app/retail/templates/base.html +++ b/app/retail/templates/base.html @@ -24,6 +24,7 @@ {% include 'shared/tag_manager_2.html' %}
          + {% include 'shared/top_nav.html' with class='d-md-flex' %} {% include 'shared/nav.html' %} {% if minihero %} {% include 'shared/minihero.html' with h1=minihero %} diff --git a/app/retail/templates/emails/kudos_mint.html b/app/retail/templates/emails/kudos_mint.html new file mode 100644 index 00000000000..d228f00ca1d --- /dev/null +++ b/app/retail/templates/emails/kudos_mint.html @@ -0,0 +1,96 @@ +{% extends 'emails/template.html' %} +{% 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 i18n humanize static kudos_extras %} + +{% block content %} + + + +
          +

          {% trans "A New Kudos Is Being Minted" %}

          + +

          + {% trans 'Hello!' %} {{kudos_transfer.from_name}}
          + {% trans 'Your minted Kudos is now ready' %} +

          +
          + +
          +
          + +
          +
          +
          + + {% if comments_public %} +

          + {% trans "Description:" %} +

          {{comments_public}}
          +

          + {% endif %} +
          +
          + +
          + +{% endblock %} diff --git a/app/retail/templates/emails/kudos_mkt.html b/app/retail/templates/emails/kudos_mkt.html new file mode 100644 index 00000000000..a0cc24bef3a --- /dev/null +++ b/app/retail/templates/emails/kudos_mkt.html @@ -0,0 +1,100 @@ +{% extends 'emails/template.html' %} +{% 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 i18n humanize static kudos_extras %} + +{% block content %} + + + +
          +

          {% trans "Show Appreciation with Kudos!" %}

          +
          + + + +
          +
          +

          + {% trans "What is Kudos?" %} +

          + + +

          {% blocktrans %} Kudos is a way of showing your appreciation for another Gitcoin member. It's also a way to showcase special skills that a member might have, such as Pythonista, or Design Star. Kudos tokens can also be bought and sold on the Kudos Marketplace.{% endblocktrans %}

          + +

          {% trans "Kudos can be used to" %}

          +

          + {% blocktrans %} + Recognize Gitcoiners you’ve worked with
          + Understand other Gitcoiner skillsets
          + See who Gitcoiners have worked iwth
          + Send as a tip
          + Send with a tip
          + Grow Open Source!
          + {% endblocktrans %} +

          + + {% trans "Kudos is a Non-Fungible Token and collectible similar to crypto kitties." %} + + + + + + +{% endblock %} diff --git a/app/retail/templates/emails/new_kudos.html b/app/retail/templates/emails/new_kudos.html new file mode 100644 index 00000000000..8ae1c834e0d --- /dev/null +++ b/app/retail/templates/emails/new_kudos.html @@ -0,0 +1,139 @@ +{% extends 'emails/template.html' %} +{% 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 i18n humanize static kudos_extras %} + +{% block content %} + + + +
          + {% if is_new %} +

          {% trans "You've Received a Kudos" %}

          + {% else %} +

          🕑 {% trans "Reminder: Kudos Expires Soon" %} 🕝

          + {% endif %} +

          + {% if kudos_transfer.from_name %} + {{kudos_transfer.from_name}} {% blocktrans %} sent you a {% endblocktrans %}{{ token_elem.name|humanize_name }} kudos! + {% else %} + Someone sent you a {{ token_elem.name|humanize_name }} kudos. + {% endif %}{% if not is_new %} {{kudos_transfer.created_on | naturaltime}}{%endif%} +

          +
          + {{token_elem.name|humanize_name  }} +
          +
          + +
          +
          +
          + {% if kudos_transfer.github_url %} +

          + {% if kudos_transfer.from_name %}{{kudos_transfer.from_name}}{% else %}The sender{% endif %} said it was for your work on {{kudos_transfer.github_url}}. + {% if comments %} + {% trans "They had the following comments:" %} +

          {{comments}}
          + {% endif %} +

          + {% endif %} + + {% if comments_priv %} +

          + {% trans "They had the following private comments:" %} +

          {{comments_priv}}
          +

          + {% endif %} + + {% if comments_public %} +

          + {% trans "Comment:" %} +

          {{comments_public}}
          +

          + {% endif %} + {% if already_redeemed %} +

          + {% trans "This kudos has been remitted automatically to the Ethereum address on file for your account via txid " %}{{kudos_transfer.txid}} +

          + {% elif show_expires %} +

          + {% trans "The kudos expires on" %} {{kudos_transfer.expires_date}}, {% trans "in just" %} {{kudos_transfer.expires_date | naturaltime}}. {% trans "No pressure, but if you wanted to redeem your kudos sooner rather than later that'd be 👌:" %} +

          + {% endif %} +
          +
          + {% if not already_redeemed %} + + {% endif %} +
          + +
          + +
          + {{token_elem.name|humanize_name  }} +

          Kudos is a way of showing your appreciation for another Gitcoin member. It's also a way to showcase special skills that a member might have, such as Pythonista, or Design Star. Kudos are non-fungible tokens that can also be bought and sold on the Kudos Marketplace.

          +
          + + +{% endblock %} diff --git a/app/retail/templates/emails/new_kudos.txt b/app/retail/templates/emails/new_kudos.txt new file mode 100644 index 00000000000..23a4f0d542f --- /dev/null +++ b/app/retail/templates/emails/new_kudos.txt @@ -0,0 +1,30 @@ +{% load humanize i18n kudos_extras %} +{% trans "You've Received a Kudos" %} +{% if kudos_transfer.from_name %} +{{kudos_transfer.from_name}} {% blocktrans %} sent you a {% endblocktrans %}{{ token_elem.name|humanize_name }} kudos! +{% else %} +Someone sent you a {{ token_elem.name|humanize_name }} kudos. +{% endif %}{% if not is_new %} {{kudos_transfer.created_on | naturaltime}}{%endif%} + + + +{% if kudos_transfer.url %} +{% if kudos_transfer.from_name %}{{kudos_transfer.from_name}}{% else %}The sender{% endif %} said it was for your work on {{kudos_transfer.github_url}}: +{% endif %} + +{% if comments %} +{% if kudos_transfer.from_name %}{{kudos_transfer.from_name}}{% else %}The sender{% endif %} had the following comments: +{{comments}} +{% endif %} + +{% if already_redeemed %} + {% trans "This kudos has been remitted automatically to the Ethereum address on file for your account via txid " %}{{kudos_transfer.txid}} +{% elif show_expires %} +The kudos expires on *{{kudos_transfer.expires_date}}, in just {{kudos_transfer.expires_date | naturaltime}}*. No pressure, but if you wanted to redeem your kudos sooner rather than later that'd be 👌: +{% else %} +No pressure, but if you wanted to redeem your kudos sooner rather than later that'd be 👌: +{% endif %} + +{% if not already_redeemed %} +Click here to redeem it: {{link}} +{% endif %} diff --git a/app/retail/templates/emails/template.html b/app/retail/templates/emails/template.html index ffe8b54724e..6364b5ed49f 100644 --- a/app/retail/templates/emails/template.html +++ b/app/retail/templates/emails/template.html @@ -118,7 +118,6 @@ p, a, - span, ul, ol, li { @@ -177,11 +176,11 @@
          {% endif %} -
          - {% block content %} - {% endblock %} - Gitcoin Open Source -
          +
          + {% block content %} + {% endblock %} + Gitcoin Open Source +