def marketplace(request): """Render the Kudos 'marketplace' page.""" q = request.GET.get('q', '') order_by = request.GET.get('order_by', '-created_on') title = str(_('Kudos Marketplace')) network = request.GET.get('network', 'xdai') if not network: network = 'xdai' # Only show the latest contract Kudos for the current network. query_kwargs = { 'num_clones_allowed__gt': 0, 'contract__is_latest': True, 'contract__network': network, } token_list = Token.objects.select_related('contract').visible().filter( **query_kwargs) if q: title = f'{q.title()} Kudos' token_list = token_list.keyword(q) # log this search, it might be useful for matching purposes down the line try: SearchHistory.objects.update_or_create(search_type='kudos', user=request.user, data=request.GET, ip_address=get_ip(request)) except Exception as e: logger.debug(e) pass # increment view counts pks = list(token_list.values_list('pk', flat=True)) if len(pks): increment_view_count.delay(pks, token_list.first().content_type, request.user.id, 'index') listings = token_list.order_by(order_by).cache() context = { 'is_outside': True, 'active': 'marketplace', 'title': title, 'q': q, 'card_title': _('Each Kudos is a unique work of art.'), 'card_desc': _('It can be sent to highlight, recognize, and show appreciation.'), 'avatar_url': request.build_absolute_uri( static('v2/images/twitter_cards/tw_cards-06.png')), 'listings': listings, 'network': network } return TemplateResponse(request, 'kudos_marketplace.html', context)
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) num_kudos_limit = 100 if kudos.hidden_token_details_page: raise Http404 what = f'kudos:{kudos.pk}' try: pinned = PinnedPost.objects.get(what=what) except PinnedPost.DoesNotExist: pinned = None context = { 'send_enabled': kudos.send_enabled_for(request.user), 'is_outside': True, 'reward_for': kudos.quests_reward.filter(visible=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': request.build_absolute_uri(static('v2/images/kudos/assets/kudos-image.png')), 'kudos': kudos, 'pinned': pinned, 'related_handles': list(set(kudos.owners_handles))[:num_kudos_limit], 'target': f'/activity?what=kudos:{kudos.pk}', } if kudos: token = Token.objects.select_related('contract').get( token_id=kudos.cloned_from_id, contract__address=kudos.contract.address, ) # increment view counts increment_view_count.delay([token.pk], token.content_type, request.user.id, 'individual') # 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.ui_name context['card_title'] = kudos.humanized_name context['card_desc'] = kudos.description context['avatar_url'] = kudos.img_url context['kudos'] = kudos if not kudos.send_enabled_for_non_gitcoin_admins: context['send_enabled_for'] = TransferEnabledFor.objects.filter(token=kudos) return TemplateResponse(request, 'kudos_details.html', context)
def grant_details(request, grant_id, grant_slug): """Display the Grant details page.""" tab = request.GET.get('tab', 'description') profile = get_profile(request) add_cancel_params = False try: grant = None try: grant = Grant.objects.prefetch_related( 'subscriptions', 'team_members').get(pk=grant_id, slug=grant_slug) except Grant.DoesNotExist: grant = Grant.objects.prefetch_related( 'subscriptions', 'team_members').get(pk=grant_id) increment_view_count.delay([grant.pk], grant.content_type, request.user.id, 'individual') subscriptions = grant.subscriptions.filter( active=True, error=False, is_postive_vote=True).order_by('-created_on') cancelled_subscriptions = grant.subscriptions.filter( active=False, error=False, is_postive_vote=True).order_by('-created_on') activity_count = grant.contribution_count contributors = [] contributions = [] negative_contributions = [] voucher_fundings = [] if tab in ['transactions', 'contributors']: _contributions = Contribution.objects.filter( subscription__in=grant.subscriptions.all().cache( timeout=60)).cache(timeout=60) negative_contributions = _contributions.filter( subscription__is_postive_vote=False) _contributions = _contributions.filter( subscription__is_postive_vote=True) phantom_funds = grant.phantom_funding.all().cache(timeout=60) contributions = list(_contributions.order_by('-created_on')) voucher_fundings = [ ele.to_mock_contribution() for ele in phantom_funds.order_by('-created_on') ] contributors = list( _contributions.distinct('subscription__contributor_profile') ) + list(phantom_funds.distinct('profile')) activity_count = len(cancelled_subscriptions) + len(contributions) user_subscription = grant.subscriptions.filter( contributor_profile=profile, active=True).first() user_non_errored_subscription = grant.subscriptions.filter( contributor_profile=profile, active=True, error=False).first() add_cancel_params = user_subscription except Grant.DoesNotExist: raise Http404 is_admin = (grant.admin_profile.id == profile.id) if profile and grant.admin_profile else False if is_admin: add_cancel_params = True is_team_member = is_grant_team_member(grant, profile) if request.method == 'POST' and (is_team_member or request.user.is_staff): grant.last_update = timezone.now() if request.FILES.get('input_image'): logo = request.FILES.get('input_image', None) grant.logo = logo grant.save() record_grant_activity_helper('update_grant', grant, profile) return redirect( reverse('grants:details', args=(grant.pk, grant.slug))) if 'contract_address' in request.POST: grant.cancel_tx_id = request.POST.get('grant_cancel_tx_id', '') grant.active = False grant.save() grant_cancellation(grant, user_subscription) for sub in subscriptions: subscription_terminated(grant, sub) record_grant_activity_helper('killed_grant', grant, profile) elif 'edit-title' in request.POST: grant.title = request.POST.get('edit-title') grant.reference_url = request.POST.get('edit-reference_url') team_members = request.POST.getlist('edit-grant_members[]') team_members.append(str(grant.admin_profile.id)) grant.team_members.set(team_members) if 'edit-description' in request.POST: grant.description = request.POST.get('edit-description') grant.description_rich = request.POST.get( 'edit-description_rich') grant.save() form_category_ids = request.POST.getlist('edit-categories[]') '''Overwrite the existing categories and then add the new ones''' grant.categories.clear() add_form_categories_to_grant(form_category_ids, grant, grant.grant_type) record_grant_activity_helper('update_grant', grant, profile) return redirect( reverse('grants:details', args=(grant.pk, grant.slug))) # handle grant updates unsubscribe key = 'unsubscribed_profiles' is_unsubscribed_from_updates_from_this_grant = request.user.is_authenticated and request.user.profile.pk in grant.metadata.get( key, []) if request.GET.get('unsubscribe') and request.user.is_authenticated: ups = grant.metadata.get(key, []) ups.append(request.user.profile.pk) grant.metadata[key] = ups grant.save() messages.info( request, _('You have been unsubscribed from the updates from this grant.')) is_unsubscribed_from_updates_from_this_grant = True try: what = f'grant:{grant.pk}' pinned = PinnedPost.objects.get(what=what) except PinnedPost.DoesNotExist: pinned = None params = { 'active': 'grant_details', 'clr_matching_banners_style': clr_matching_banners_style, 'grant': grant, 'tab': tab, 'title': matching_live_tiny + grant.title + " | Grants", 'card_desc': grant.description, 'avatar_url': grant.logo.url if grant.logo else None, 'subscriptions': subscriptions, 'cancelled_subscriptions': cancelled_subscriptions, 'contributions': contributions, 'negative_contributions': negative_contributions, 'user_subscription': user_subscription, 'user_non_errored_subscription': user_non_errored_subscription, 'is_admin': is_admin, 'grant_is_inactive': not grant.active, 'keywords': get_keywords(), 'target': f'/activity?what={what}', 'pinned': pinned, 'what': what, 'activity_count': activity_count, 'contributors': contributors, 'clr_active': clr_active, 'is_team_member': is_team_member, 'voucher_fundings': voucher_fundings, 'is_unsubscribed_from_updates_from_this_grant': is_unsubscribed_from_updates_from_this_grant, 'is_round_5_5': False, 'options': [(f'Email Grant Funders ({grant.contributor_count})', 'bullhorn', 'Select this option to email your status update to all your funders.' )] if is_team_member else [], } if tab == 'stats': params['max_graph'] = grant.history_by_month_max params['history'] = json.dumps(grant.history_by_month) if add_cancel_params: add_in_params = { 'recommend_gas_price': recommend_min_gas_price_to_confirm_in_time(4), 'recommend_gas_price_slow': recommend_min_gas_price_to_confirm_in_time(120), 'recommend_gas_price_avg': recommend_min_gas_price_to_confirm_in_time(15), 'recommend_gas_price_fast': recommend_min_gas_price_to_confirm_in_time(1), 'eth_usd_conv_rate': eth_usd_conv_rate(), 'conf_time_spread': conf_time_spread(), 'gas_advisories': gas_advisories(), } for key, value in add_in_params.items(): params[key] = value return TemplateResponse(request, 'grants/detail/index.html', params)
def grants_by_grant_type(request, grant_type): """Handle grants explorer.""" # hack for vivek if grant_type == 'change': new_url = request.get_full_path().replace('/change', '/crypto-for-black-lives') return redirect(new_url) if grant_type == 'crypto-for-black-lives': grant_type = 'change' limit = request.GET.get('limit', 6) page = request.GET.get('page', 1) sort = request.GET.get('sort_option', 'weighted_shuffle') network = request.GET.get('network', 'mainnet') keyword = request.GET.get('keyword', '') state = request.GET.get('state', 'active') category = request.GET.get('category', '') profile = get_profile(request) _grants = None bg = 4 bg = f"{bg}.jpg" mid_back = 'bg14.png' bottom_back = 'bg13.gif' if grant_type == 'tech': bottom_back = '0.png' bg = '0.jpg' if grant_type == 'tech': bottom_back = 'bg20-2.png' bg = '1.jpg' if grant_type == 'media': bottom_back = 'bg16.gif' bg = '2.jpg' if grant_type == 'health': bottom_back = 'health.jpg' bg = 'health2.jpg' if grant_type in ['about', 'activity']: bg = '3.jpg' show_past_clr = False sort_by_index = None sort_by_clr_pledge_matching_amount = None if 'match_pledge_amount_' in sort: sort_by_clr_pledge_matching_amount = int(sort.split('amount_')[1]) _grants = Grant.objects.filter(network=network, hidden=False).keyword(keyword) try: _grants = _grants.order_by(sort, 'pk') ____ = _grants.first() except Exception as e: print(e) return redirect('/grants') if state == 'active': _grants = _grants.active() if keyword: grant_type = '' else: # dotn do search by cateogry if grant_type != 'all': _grants = _grants.filter(grant_type=grant_type) clr_prediction_curve_schema_map = {10**x: x + 1 for x in range(0, 5)} if sort_by_clr_pledge_matching_amount in clr_prediction_curve_schema_map.keys( ): sort_by_index = clr_prediction_curve_schema_map.get( sort_by_clr_pledge_matching_amount, 0) field_name = f'clr_prediction_curve__{sort_by_index}__2' _grants = _grants.order_by(f"-{field_name}") if category: _grants = _grants.filter(Q(categories__category__icontains=category)) _grants = _grants.prefetch_related('categories') paginator = Paginator(_grants, limit) grants = paginator.get_page(page) partners = MatchPledge.objects.filter( active=True, pledge_type=grant_type) if grant_type else MatchPledge.objects.filter( active=True) now = datetime.datetime.now() # record view pks = list([grant.pk for grant in grants]) if len(pks): increment_view_count.delay(pks, grants[0].content_type, request.user.id, 'index') current_partners = partners.filter(end_date__gte=now).order_by('-amount') past_partners = partners.filter(end_date__lt=now).order_by('-amount') current_partners_fund = 0 for partner in current_partners: current_partners_fund += partner.amount grant_amount = 0 grant_stats = Stat.objects.filter(key='grants', ).order_by('-pk') if grant_stats.exists(): grant_amount = lazy_round_number(grant_stats.first().val) tech_grants_count = Grant.objects.filter(network=network, hidden=False, grant_type='tech').count() media_grants_count = Grant.objects.filter(network=network, hidden=False, grant_type='media').count() health_grants_count = Grant.objects.filter(network=network, hidden=False, grant_type='health').count() matic_grants_count = Grant.objects.filter(network=network, hidden=False, grant_type='matic').count() change_count = Grant.objects.filter(network=network, hidden=False, grant_type='change').count() all_grants_count = Grant.objects.filter(network=network, hidden=False).count() categories = [ _category[0] for _category in basic_grant_categories(grant_type) ] grant_types = [ { 'label': 'Tech', 'keyword': 'tech', 'count': tech_grants_count }, { 'label': 'Community', 'keyword': 'media', 'count': media_grants_count }, # {'label': 'Health', 'keyword': 'health', 'count': health_grants_count}, # {'label': 'Matic', 'keyword': 'matic', 'count': matic_grants_count}, { 'label': 'Crypto for Black Lives', 'keyword': 'change', 'count': change_count }, ] sub_categories = [] for _keyword in [grant_type['keyword'] for grant_type in grant_types]: sub_category = {} sub_category[_keyword] = [ tuple[0] for tuple in basic_grant_categories(_keyword) ] sub_categories.append(sub_category) title = matching_live + str(_('Grants')) has_real_grant_type = grant_type and grant_type != 'activity' grant_type_title_if_any = grant_type.title() if has_real_grant_type else '' if grant_type_title_if_any == "Media": grant_type_title_if_any = "Community" if grant_type_title_if_any == "Change": grant_type_title_if_any = "Crypto for Black Lives" grant_type_gfx_if_any = grant_type if has_real_grant_type else 'total' if has_real_grant_type: title = f"{matching_live} {grant_type_title_if_any.title()} {category.title()} Grants" if grant_type == 'stats': title = f"Round {clr_round} Stats" cht = [] chart_list = '' try: what = 'all_grants' pinned = PinnedPost.objects.get(what=what) except PinnedPost.DoesNotExist: pinned = None prev_grants = Grant.objects.none() if request.user.is_authenticated: prev_grants = request.user.profile.grant_contributor.filter( created_on__gt=last_round_start, created_on__lt=last_round_end).values_list('grant', flat=True) prev_grants = Grant.objects.filter(pk__in=prev_grants) params = { 'active': 'grants_landing', 'title': title, 'sort': sort, 'network': network, 'keyword': keyword, 'type': grant_type, 'round_end': round_end, 'next_round_start': next_round_start, 'after_that_next_round_begin': after_that_next_round_begin, 'all_grants_count': all_grants_count, 'now': timezone.now(), 'mid_back': mid_back, 'cht': cht, 'chart_list': chart_list, 'bottom_back': bottom_back, 'clr_matching_banners_style': clr_matching_banners_style, 'categories': categories, 'sub_categories': sub_categories, 'prev_grants': prev_grants, 'grant_types': grant_types, 'current_partners_fund': current_partners_fund, 'current_partners': current_partners, 'past_partners': past_partners, 'card_desc': f'{live_now}', 'avatar_url': request.build_absolute_uri( static('v2/images/twitter_cards/tw_cards-03.png')), 'card_type': 'summary_large_image', 'avatar_height': 1097, 'avatar_width': 1953, 'grants': grants, 'what': what, 'can_pin': can_pin(request, what), 'pinned': pinned, 'target': f'/activity?what=all_grants', 'bg': bg, 'keywords': get_keywords(), 'grant_amount': grant_amount, 'total_clr_pot': total_clr_pot, 'clr_active': clr_active, 'sort_by_index': sort_by_index, 'clr_round': clr_round, 'show_past_clr': show_past_clr, 'is_staff': request.user.is_staff, 'selected_category': category, 'profile': profile } # log this search, it might be useful for matching purposes down the line if keyword: try: SearchHistory.objects.update_or_create(search_type='grants', user=request.user, data=request.GET, ip_address=get_ip(request)) except Exception as e: logger.debug(e) pass response = TemplateResponse(request, 'grants/index.html', params) response['X-Frame-Options'] = 'SAMEORIGIN' return response