Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tracking cart functionality #6902

Merged
merged 7 commits into from
Jun 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 28 additions & 3 deletions app/assets/v2/js/cart-data.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ class CartData {
accptedTokenName = 'DAI';
}

grantData.uuid = get_UUID();

if (acceptsAllTokens || 'DAI' == accptedTokenName) {
grantData.grant_donation_amount = 5;
grantData.grant_donation_currency = 'DAI';
Expand All @@ -71,14 +73,22 @@ class CartData {

cartList.push(grantData);
this.setCart(cartList);

fetchData(`/grants/${grantData.grant_id}/activity`, 'POST', {
action: 'ADD_ITEM',
metadata: JSON.stringify(cartList)
}, {'X-CSRFToken': $("input[name='csrfmiddlewaretoken']").val()});
}

static removeIdFromCart(grantId) {
let cartList = this.loadCart();

const newList = cartList.filter(grant => {
return (grant.grant_id !== grantId);
});
const newList = cartList.filter(grant => grant.grant_id !== grantId);

fetchData(`/grants/${grantId}/activity`, 'POST', {
action: 'REMOVE_ITEM',
metadata: JSON.stringify(newList)
}, {'X-CSRFToken': $("input[name='csrfmiddlewaretoken']").val()});

this.setCart(newList);
}
Expand Down Expand Up @@ -106,6 +116,21 @@ class CartData {
this.setCart(cartList);
}

static clearCart() {
let cartList = this.loadCart();

cartList.map(grant => {
fetchData('/grants/activity', 'POST', {
action: 'REMOVE_ITEM',
metadata: JSON.stringify(cartList),
bulk: true
}, {'X-CSRFToken': $("input[name='csrfmiddlewaretoken']").val()});
});

localStorage.setItem('grants_cart', JSON.stringify([]));
applyCartMenuStyles();
}

static loadCart() {
const cartList = localStorage.getItem('grants_cart');

Expand Down
2 changes: 1 addition & 1 deletion app/assets/v2/js/cart.js
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ Vue.component('grants-cart', {
},

clearCart() {
CartData.setCart([]);
CartData.clearCart();
this.grantData = [];
update_cart_title();
},
Expand Down
12 changes: 12 additions & 0 deletions app/assets/v2/js/shared.js
Original file line number Diff line number Diff line change
Expand Up @@ -1244,3 +1244,15 @@ const fetchIssueDetailsFromGithub = issue_url => {
});
});
};

const get_UUID = () => {
var dt = new Date().getTime();
const uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
const r = (dt + Math.random() * 16) % 16 | 0;

dt = Math.floor(dt / 16);
return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
});

return uuid;
};
11 changes: 9 additions & 2 deletions app/grants/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from django.utils.html import format_html
from django.utils.safestring import mark_safe

from grants.models import CLRMatch, Contribution, Flag, Grant, MatchPledge, PhantomFunding, Subscription
from grants.models import CLRMatch, Contribution, Flag, Grant, MatchPledge, PhantomFunding, Subscription, CartActivity


class GeneralAdmin(admin.ModelAdmin):
Expand Down Expand Up @@ -147,7 +147,7 @@ def subscriptions_links(self, instance):

def contributions_links(self, instance):
"""Define the logo image tag to be displayed in the admin."""
eles = []
eles = []

for i in [True, False]:
html = f"<h3>Success {i}</h3>"
Expand Down Expand Up @@ -308,10 +308,17 @@ def from_ip_address(self, instance):
return " , ".join(visits)


class CartActivityAdmin(admin.ModelAdmin):
list_display = ['id', 'grant', 'profile', 'action', 'bulk', 'created_on']
raw_id_fields = ['grant', 'profile']
search_fields = ['bulk', 'action', 'grant']


admin.site.register(PhantomFunding, PhantomFundingAdmin)
admin.site.register(MatchPledge, MatchPledgeAdmin)
admin.site.register(Grant, GrantAdmin)
admin.site.register(Flag, FlagAdmin)
admin.site.register(CLRMatch, CLRMatchAdmin)
admin.site.register(Subscription, SubscriptionAdmin)
admin.site.register(Contribution, ContributionAdmin)
admin.site.register(CartActivity, CartActivityAdmin)
48 changes: 48 additions & 0 deletions app/grants/migrations/0059_auto_20200617_1508.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Generated by Django 2.2.4 on 2020-06-17 15:08

import django.contrib.postgres.fields.jsonb
from django.db import migrations, models
import django.db.models.deletion
import economy.models


class Migration(migrations.Migration):

dependencies = [
('dashboard', '0122_auto_20200615_1510'),
('grants', '0058_auto_20200615_1226'),
]

operations = [
migrations.AlterField(
model_name='contribution',
name='tx_id',
field=models.CharField(blank=True, default='0x0', help_text='The transaction ID of the Contribution.', max_length=255),
),
migrations.AlterField(
model_name='grant',
name='grant_type',
field=models.CharField(choices=[('tech', 'tech'), ('health', 'health'), ('Community', 'media'), ('change', 'change'), ('matic', 'matic')], default='tech', help_text='Grant CLR category', max_length=15),
),
migrations.AlterField(
model_name='matchpledge',
name='pledge_type',
field=models.CharField(choices=[('tech', 'tech'), ('media', 'media'), ('health', 'health'), ('change', 'change')], default='tech', help_text='CLR pledge type', max_length=15),
),
migrations.CreateModel(
name='CartActivity',
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)),
('action', models.CharField(choices=[('ADD_ITEM', 'Add item to cart'), ('REMOVE_ITEM', 'Remove item to cart')], help_text='Type of activity', max_length=20)),
('metadata', django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=dict, help_text='Related data to the action')),
('bulk', models.BooleanField(default=False)),
('grant', models.ForeignKey(help_text='Related Grant Activity ', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='cart_actions', to='grants.Grant')),
('profile', models.ForeignKey(help_text='User Cart Activity', on_delete=django.db.models.deletion.CASCADE, related_name='cart_activity', to='dashboard.Profile')),
],
options={
'abstract': False,
},
),
]
17 changes: 17 additions & 0 deletions app/grants/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1401,3 +1401,20 @@ def to_mock_contribution(self):
context['tx_cleared'] = True
context['success'] = True
return context


class CartActivity(SuperModel):
ACTIONS = (
('ADD_ITEM', 'Add item to cart'),
('REMOVE_ITEM', 'Remove item to cart')
)
grant = models.ForeignKey(Grant, null=True, on_delete=models.CASCADE, related_name='cart_actions',
help_text=_('Related Grant Activity '))
profile = models.ForeignKey('dashboard.Profile', on_delete=models.CASCADE, related_name='cart_activity',
help_text=_('User Cart Activity'))
action = models.CharField(max_length=20, choices=ACTIONS, help_text=_('Type of activity'))
metadata = JSONField(default=dict, blank=True, help_text=_('Related data to the action'))
bulk = models.BooleanField(default=False)

def __str__(self):
return f'{self.action} {self.grant.id if self.grant else "bulk"} from the cart {self.profile.handle}'
5 changes: 3 additions & 2 deletions app/grants/templates/grants/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
<a class="btn btn-gc-blue cart-btn font-smaller-3 font-weight-semibold float-right mt-1 mr-1" href="/grants/cart/bulk-add/{% for prev_grant in prev_grants %}{{prev_grant.pk}},{% endfor %}">+
Add to Cart</a>
<p class="mb-2">Want to contribute to <a href="https://vitalik.ca/general/2020/04/30/round5.html" target="_blank">stability of ecosystem funding</a>? You funded {{prev_grants.count}} grant{{ prev_grants.count|pluralize }} last time. Fund
them again?</p>
them again?</p>
<span class="font-smaller-3">{% for prev_grant in prev_grants %}
<a href="{{prev_grant.url}}">{{prev_grant.title}}</a>
{% if not forloop.last %}{% ifequal forloop.revcounter 2 %} and {% else %}, {% endifequal %}{% else %}{% endif %}
Expand Down Expand Up @@ -89,6 +89,7 @@
</div>
</div>
</div>
{% csrf_token %}
</div>
<div id="side-cart" class="grant-side-cart px-5 px-md-4 pb-5 pb-md-0 pt-md-0" style="display: none;">
{% include 'grants/detail/side-cart.html' %}
Expand Down Expand Up @@ -126,4 +127,4 @@
{% endif %}


</html>
</html>
6 changes: 4 additions & 2 deletions app/grants/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@

from grants.views import (
flag, grant_categories, grant_details, grant_fund, grant_new, grant_new_whitelabel, grants, grants_addr_as_json,
grants_bulk_add, grants_by_grant_type, grants_cart_view, grants_stats_view, invoice, leaderboard,
new_matching_partner, profile, quickstart, subscription_cancel,
grants_bulk_add, grants_by_grant_type, grants_cart_view, grants_stats_view, grant_activity, invoice, leaderboard,
new_matching_partner, profile, quickstart, subscription_cancel
)

app_name = 'grants'
Expand All @@ -31,6 +31,8 @@
path('getstats/', grants_stats_view, name='grants_stats'),
path('grants.json', grants_addr_as_json, name='grants_json'),
path('flag/<int:grant_id>', flag, name='grantflag'),
path('<int:grant_id>/activity', grant_activity, name='log_activity'),
path('activity', grant_activity, name='log_activity'),
path('<int:grant_id>/<slug:grant_slug>', grant_details, name='details'),
path('<int:grant_id>/<slug:grant_slug>/', grant_details, name='details2'),
re_path(r'^matic/new', grant_new_whitelabel, name='new_whitelabel'),
Expand Down
24 changes: 22 additions & 2 deletions app/grants/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@
from dashboard.utils import get_web3, has_tx_mined
from economy.utils import convert_amount
from gas.utils import conf_time_spread, eth_usd_conv_rate, gas_advisories, recommend_min_gas_price_to_confirm_in_time
from grants.models import Contribution, Flag, Grant, GrantCategory, MatchPledge, PhantomFunding, Subscription
from grants.models import Contribution, Flag, Grant, GrantCategory, MatchPledge, PhantomFunding, Subscription, \
CartActivity
from grants.utils import get_leaderboard, is_grant_team_member
from inbox.utils import send_notification_to_user_from_gitcoinbot
from kudos.models import BulkTransferCoupon, Token
Expand Down Expand Up @@ -407,7 +408,7 @@ def grants_by_grant_type(request, grant_type):
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,
Expand Down Expand Up @@ -1128,3 +1129,22 @@ def grant_categories(request):
return JsonResponse({
'categories': categories
})


@login_required
def grant_activity(request, grant_id=None):
action = request.POST.get('action')
metadata = request.POST.get('metadata')
bulk = request.POST.get('bulk') == 'true'

if grant_id == None:
grant = None
else:
grant = get_object_or_404(Grant, pk=grant_id)

CartActivity.objects.create(grant=grant, profile=request.user.profile, action=action,
metadata=json.loads(metadata), bulk=bulk)

return JsonResponse({
'error': False
})