Skip to content

Commit 2a1b641

Browse files
saadmk11agjohnson
authored andcommitted
Refactor Gold Views (#6272)
* Refactor Gold Views * Update gold projects template and CSS
1 parent 48d6a6b commit 2a1b641

File tree

5 files changed

+91
-53
lines changed

5 files changed

+91
-53
lines changed

media/css/core.css

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,9 @@ div.module.search-dashboard input {
478478
/* Admin project Translation */
479479
.module-translation { padding-bottom: 25px; }
480480

481+
/* Accounts Gold Projects */
482+
.module-gold-projects { padding-bottom: 25px; }
483+
481484
/* project bar */
482485

483486
#project_bar { background: #E8ECEF url(../images/project-bar-bg.png) top left repeat; border-bottom: 1px solid #DAE1E5; overflow:hidden; position:relative; }

readthedocs/gold/forms.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,11 @@ def generate_choices(self, active_user):
109109
def clean_project(self):
110110
project_slug = self.cleaned_data.get('project', '')
111111
project_instance = Project.objects.filter(slug=project_slug)
112+
112113
if not project_instance.exists():
113114
raise forms.ValidationError(_('No project found.'))
115+
elif project_instance.first() in self.projects:
116+
raise forms.ValidationError(_('This project is already Ad-Free.'))
114117
else:
115118
return project_slug
116119

readthedocs/gold/templates/gold/projects.html

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,36 @@ <h3>{% trans "Gold Projects" %}</h3>
2222
</ul>
2323

2424
<h3>{% trans 'Ad-free projects' %}</h3>
25-
<ul class="donate-about">
26-
{% for project in projects %}
27-
<li>
28-
<a href="{{ project.get_absolute_url }}">{{ project }}</a>
29-
<span>(<a href="{% url "gold_projects_remove" project.slug %}">{% trans "Remove Ad-Free Status" %}</a>)</span>
30-
</li>
31-
{% empty %}
32-
<p>{% trans 'No projects are currently ad-free.' %}</p>
33-
{% endfor %}
34-
</ul>
25+
26+
<div class="module-gold-projects">
27+
<div class="module-list">
28+
<div class="module-list-wrapper">
29+
<ul>
30+
{% for project in projects %}
31+
<li class="module-item">
32+
<a class="module-item-title" href="{{ project.get_absolute_url }}">
33+
{{ project.name }}
34+
</a>
35+
<ul class="module-item-menu">
36+
<li>
37+
<form method="post" action="{% url "gold_projects_remove" project.slug %}">
38+
{% csrf_token %}
39+
<input type="submit" title="{% trans 'Remove Ad-Free Status' %}" value="{% trans 'Remove' %}">
40+
</form>
41+
</li>
42+
</ul>
43+
</li>
44+
{% empty %}
45+
<li class="module-item">
46+
<p class="quiet">
47+
{% trans 'No projects are currently ad-free.' %}
48+
</p>
49+
</li>
50+
{% endfor %}
51+
</ul>
52+
</div>
53+
</div>
54+
</div>
3555

3656
<h3>{% trans "Make a project ad-free" %}</h3>
3757
{% if gold_user.num_supported_projects > projects|length %}

readthedocs/gold/urls.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,14 @@
2020
views.DeleteGoldSubscription.as_view(),
2121
name='gold_cancel',
2222
),
23-
url(r'^projects/$', views.projects, name='gold_projects'),
23+
url(r'^projects/$', views.GoldProjectsListCreate.as_view(), name='gold_projects'),
2424
url(
2525
(
2626
r'^projects/remove/(?P<project_slug>{project_slug})/$'.format(
2727
project_slug=PROJECT_SLUG_REGEX,
2828
)
2929
),
30-
views.projects_remove,
30+
views.GoldProjectRemove.as_view(),
3131
name='gold_projects_remove',
3232
),
3333
]

readthedocs/gold/views.py

Lines changed: 53 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from django.shortcuts import get_object_or_404, render
1111
from django.urls import reverse, reverse_lazy
1212
from django.utils.translation import ugettext_lazy as _
13-
from vanilla import DeleteView, DetailView, UpdateView
13+
from vanilla import DeleteView, DetailView, FormView, GenericView, UpdateView
1414

1515
from readthedocs.core.mixins import PrivateViewMixin
1616
from readthedocs.payments.mixins import StripeMixin
@@ -98,45 +98,57 @@ def post(self, request, *args, **kwargs):
9898
return resp
9999

100100

101-
@login_required
102-
def projects(request):
103-
gold_user = get_object_or_404(GoldUser, user=request.user)
104-
gold_projects = gold_user.projects.all()
101+
class GoldProjectsMixin(PrivateViewMixin):
105102

106-
if request.method == 'POST':
107-
form = GoldProjectForm(
108-
active_user=request.user,
109-
data=request.POST,
110-
user=gold_user,
111-
projects=gold_projects,
103+
def get_gold_user(self):
104+
return get_object_or_404(GoldUser, user=self.request.user)
105+
106+
def get_gold_projects(self):
107+
return self.get_gold_user().projects.all()
108+
109+
def get_success_url(self):
110+
return reverse('gold_projects')
111+
112+
113+
class GoldProjectsListCreate(GoldProjectsMixin, FormView):
114+
115+
"""Gold Project list view and form view."""
116+
117+
form_class = GoldProjectForm
118+
template_name = 'gold/projects.html'
119+
120+
def form_valid(self, form):
121+
to_add = Project.objects.get(slug=form.cleaned_data['project'])
122+
gold_user = self.get_gold_user()
123+
gold_user.projects.add(to_add)
124+
return HttpResponseRedirect(self.get_success_url())
125+
126+
def get_form(self, data=None, files=None, **kwargs):
127+
kwargs['user'] = self.get_gold_user()
128+
kwargs['projects'] = self.get_gold_projects()
129+
return self.form_class(self.request.user, data, files, **kwargs)
130+
131+
def get_context_data(self, **kwargs):
132+
context = super().get_context_data(**kwargs)
133+
context['gold_user'] = self.get_gold_user()
134+
context['publishable'] = settings.STRIPE_PUBLISHABLE
135+
context['user'] = self.request.user
136+
context['projects'] = self.get_gold_projects()
137+
return context
138+
139+
140+
class GoldProjectRemove(GoldProjectsMixin, GenericView):
141+
142+
http_method_names = ['post']
143+
144+
def post(self, request, *args, **kwargs):
145+
# pylint: disable=unused-argument
146+
gold_user = self.get_gold_user()
147+
148+
project = get_object_or_404(
149+
Project.objects.all(),
150+
slug=self.kwargs.get('project_slug')
112151
)
113-
if form.is_valid():
114-
to_add = Project.objects.get(slug=form.cleaned_data['project'])
115-
gold_user.projects.add(to_add)
116-
return HttpResponseRedirect(reverse('gold_projects'))
117-
else:
118-
# HACK: active_user=request.user is passed
119-
# as argument to get the currently active
120-
# user in the GoldProjectForm which is used
121-
# to filter the choices based on the user.
122-
form = GoldProjectForm(active_user=request.user)
123-
124-
return render(
125-
request,
126-
'gold/projects.html',
127-
{
128-
'form': form,
129-
'gold_user': gold_user,
130-
'publishable': settings.STRIPE_PUBLISHABLE,
131-
'user': request.user,
132-
'projects': gold_projects,
133-
},
134-
)
135-
136-
137-
@login_required
138-
def projects_remove(request, project_slug):
139-
gold_user = get_object_or_404(GoldUser, user=request.user)
140-
project = get_object_or_404(Project.objects.all(), slug=project_slug)
141-
gold_user.projects.remove(project)
142-
return HttpResponseRedirect(reverse('gold_projects'))
152+
gold_user.projects.remove(project)
153+
154+
return HttpResponseRedirect(self.get_success_url())

0 commit comments

Comments
 (0)