Skip to content

Commit 5727fc3

Browse files
committed
Move 'add new candiadte' button / form into the table
I think this is a nicer way to link 'candidate actions' with the candidate table, leaving other actions to be 'ballot actions' in a fucutre commit.
1 parent d066160 commit 5727fc3

File tree

7 files changed

+70
-45
lines changed

7 files changed

+70
-45
lines changed

ynr/apps/candidates/models/popolo_extra.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -615,7 +615,6 @@ def user_can_edit_membership(self, user, allow_if_trusted_to_lock=True):
615615
if (
616616
not self.candidates_locked
617617
and not self.cancelled
618-
and not hasattr(self, "sopn")
619618
):
620619
return True
621620

ynr/apps/candidates/static/candidates/_forms.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ form.signup {
7373
.form-item {
7474
margin-bottom: 1.5em;
7575

76+
.row {
77+
margin: 0;
78+
}
79+
7680
input,
7781
select,
7882
p {

ynr/apps/candidates/static/js/ballot.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,19 @@ $(function() {
1818
}
1919

2020
/* Set up the hide / reveal for the add new candidate form */
21-
$('.show-new-candidate-form').on('click', function(e){
21+
$(document).on('click', '.show-new-candidate-form', function(e){
2222
e.preventDefault();
23+
e.target.classList.add('hide-new-candidate-form')
24+
e.target.classList.remove('show-new-candidate-form')
2325
var newCandidate = getNewCandidateDiv(e.target);
2426
newCandidate.slideDown(function(){
2527
newCandidate.find('input:text').eq(0).focus();
2628
});
2729
});
28-
$('.hide-new-candidate-form').on('click', function(e){
30+
$(document).on('click', '.hide-new-candidate-form', function(e){
31+
e.preventDefault();
32+
e.target.classList.add('show-new-candidate-form')
33+
e.target.classList.remove('hide-new-candidate-form')
2934
var newCandidate = getNewCandidateDiv(e.target);
3035
newCandidate.slideUp();
3136
});

ynr/apps/candidates/tests/test_candidacy_add_and_remove.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import re
2+
13
from django_webtest import WebTest
24
from official_documents.models import BallotSOPN
35
from people.tests.factories import PersonFactory
@@ -63,9 +65,14 @@ def test_can_see_add_button_with_no_sopn(self):
6365
user=self.user,
6466
)
6567
self.assertContains(response, "Add a new candidate")
68+
69+
# We allow adding candidates when there is a SOPN
70+
# but we mark the button as 'secondary'
6671
BallotSOPN.objects.create(ballot=ballot)
6772
response = self.app.get(
6873
ballot.get_absolute_url(),
6974
user=self.user,
7075
)
71-
self.assertNotContains(response, "Add a new candidate")
76+
button = response.html.find("a", text=re.compile("Add a new candidate"))
77+
self.assertIsNotNone(button)
78+
self.assertIn("secondary", button["class"])

ynr/apps/elections/templates/elections/ballot_view.html

Lines changed: 21 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ <h1>{{ ballot.post.label }}</h1>
4242

4343

4444
{% block content %}
45-
4645
<div class="row">
4746
<div class="columns large-9">
4847
<div class="ballot_status">
@@ -76,6 +75,9 @@ <h2>Candidates unknown</h2>
7675
We don’t know of any candidates in {{ ballot.post.label }} for the {{ ballot.election.name }} yet.
7776
We expect the official list of candidates to be published on or after
7877
<strong>{{ ballot.expected_sopn_date }}</strong>.</p>
78+
<p class="clearfix">
79+
{% include "elections/includes/_ballot_add_candidate.html" with position='left' %}
80+
</p>
7981
{% endif %}
8082
</div>
8183

@@ -182,61 +184,46 @@ <h2>Candidates unknown</h2>
182184
{% endif %}
183185
</tr>
184186
{% endfor %}
187+
188+
{% if membership_edits_allowed or not user.is_authenticated and not ballot.has_sopn%}
189+
<tr>
190+
<td colspan="3">
191+
{% include "elections/includes/_ballot_add_candidate.html" %}
192+
</td>
193+
</tr>
194+
195+
{% endif %}
196+
197+
185198
</tbody>
186199
</table>
187200
{% endif %}
201+
202+
<div class="ballot-ctas">
188203
{% if user_can_record_results and has_any_winners %}
189204
<form action="{% url 'retract-winner' ballot_paper_id=ballot.ballot_paper_id %}" method="post">
190205
{% csrf_token %}
191206
<input type="submit" class="button alert small" value="Unset the current winners, if incorrect">
192207
</form>
193208
{% endif %}
194-
195-
<div class="ballot-ctas">
196-
197209
{% include "elections/includes/_ballot_suggest_locking.html" %}
198210
{% include "elections/includes/_ballot_lock_form.html" %}
199211

200212
{% if user_can_review_photos and ballot.get_absolute_queued_image_review_url %}
201213
<p>This ballot has candidate photos awaiting approval.<a href="{{ ballot.get_absolute_queued_image_review_url }}"> Do you have time to review them?</a></p>
202214
{% endif %}
203-
204-
{% if membership_edits_allowed %}
205-
<p class="right-align">
206-
<a class="show-new-candidate-form button {% if ballot.has_sopn %}secondary{% endif %}" href="{% url 'person-create' ballot_paper_id=ballot.ballot_paper_id %}">
207-
Add a new candidate
208-
</a>
209-
</p>
210-
{% elif not user.is_authenticated and not ballot.has_sopn %}
211-
<p>
212-
213-
<a href="{% url 'wombles:login' %}?next={{ request.path }}" class="button">
214-
Sign in to add a new candidate
215-
</a>
216-
</p>
217-
{% endif %}
218215
</div>
219216

220-
{% if membership_edits_allowed %}
221-
{% if add_candidate_form %}
222-
<div class="candidates__new" {% if add_candidate_form.errors %}style="display: block"{% endif %}>
223-
<h4>Add a new candidate</h4>
224-
<form id="new-candidate-form" name="new-candidate-form" action="{% url 'person-create' ballot_paper_id=ballot.ballot_paper_id %}" method="post">
225-
{% with form=add_candidate_form identifiers_formset=identifiers_formset %}
226-
{% include 'candidates/_person_form.html' %}
227-
{% endwith %}
228-
</form>
229-
</div>
230-
{% endif %}
231217

232-
{# Only include these if the user can alter memberships #}
233-
{% include "elections/includes/_ballot_candidates_might_stand.html" %}
234-
{% include "elections/includes/_ballot_candidates_not_standing.html" %}
235-
{% endif %}
236218
{% if ballot.has_results and ballot.resultset %}
237219
{% include "elections/includes/_ballot_results_table.html" with results=ballot.resultset %}
238220
{% endif %}
239221

222+
{# Only include these if the user can alter memberships #}
223+
{% include "elections/includes/_ballot_candidates_might_stand.html" %}
224+
{% include "elections/includes/_ballot_candidates_not_standing.html" %}
225+
226+
240227
{% if user.is_authenticated and logged_actions %}
241228
<h2 id="history">History for this ballot</h2>
242229
{% for action in logged_actions %}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{% if not user.is_authenticated and not ballot.has_sopn %}
2+
<a href="{% url 'wombles:login' %}?next={{ request.path }}" class="button small right" style="margin:0">
3+
Sign in to add a new candidate
4+
</a>
5+
{% endif %}
6+
7+
{% if membership_edits_allowed %}
8+
<a class="show-new-candidate-form button small {% if not position %}right{% endif %} {% if ballot.has_sopn %}secondary{% else %}success{% endif %}"
9+
style="margin:0" href="{% url 'person-create' ballot_paper_id=ballot.ballot_paper_id %}">
10+
Add a new candidate
11+
</a>
12+
13+
{% if add_candidate_form %}
14+
<div class="candidates__new" {% if add_candidate_form.errors %}style="display: block"{% endif %}>
15+
<h4>Add a new candidate</h4>
16+
<form id="new-candidate-form" name="new-candidate-form"
17+
action="{% url 'person-create' ballot_paper_id=ballot.ballot_paper_id %}" method="post">
18+
{% with form=add_candidate_form identifiers_formset=identifiers_formset %}
19+
{% include 'candidates/_person_form.html' %}
20+
{% endwith %}
21+
</form>
22+
</div>
23+
{% endif %}
24+
{% endif %}

ynr/apps/elections/tests/data_timeline_helper.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import re
2+
13
from django_webtest import WebTest
24

35

@@ -72,14 +74,11 @@ def assertDataTimelineNotLocked(self, response):
7274

7375
def assertDataTimelineShowAddCandidateCTA(self, response):
7476
if not response.context["user"].is_authenticated:
75-
self.assertInHTML(
76-
"""
77-
<a href="/accounts/login/?next=/elections/local.foo.bar.2019-08-03/" class="button">
78-
Sign in to add a new candidate
79-
</a>
80-
""",
81-
response.text,
77+
button = response.html.find(
78+
"a", text=re.compile("Sign in to add a new candidate")
8279
)
80+
self.assertIsNotNone(button)
81+
self.assertEqual(button["href"], "/accounts/login/?next=/elections/local.foo.bar.2019-08-03/")
8382

8483
def assertDataTimelineCandidateAddingInProgress(self, response):
8584
self.assertDataTimelineShown(response)

0 commit comments

Comments
 (0)