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

Feature/new person page #660

Merged
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
1 change: 1 addition & 0 deletions requirements/base.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ newspaper3k==0.2.8

git+git://github.com/DemocracyClub/dc_base_theme.git@0.3.11
git+https://github.com/DemocracyClub/dc_signup_form.git@2.1.0
git+https://github.com/DemocracyClub/design-system.git
djangorestframework-jsonp==1.0.2
feedparser==6.0.2

Expand Down
17 changes: 17 additions & 0 deletions wcivf/apps/core/migrations/0003_auto_20210225_1103.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Generated by Django 2.2.18 on 2021-02-25 11:03

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
("core", "0002_auto_20170526_1448"),
]

operations = [
migrations.AlterModelOptions(
name="loggedpostcode",
options={"get_latest_by": "modified"},
),
]
17 changes: 17 additions & 0 deletions wcivf/apps/feedback/migrations/0003_auto_20210225_1103.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Generated by Django 2.2.18 on 2021-02-25 11:03

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
("feedback", "0002_feedback_token"),
]

operations = [
migrations.AlterModelOptions(
name="feedback",
options={"get_latest_by": "modified"},
),
]
17 changes: 17 additions & 0 deletions wcivf/apps/news_mentions/migrations/0003_auto_20210225_1103.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Generated by Django 2.2.18 on 2021-02-25 11:03

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
("news_mentions", "0002_ballotnewsarticle_publisher"),
]

operations = [
migrations.AlterModelOptions(
name="ballotnewsarticle",
options={"get_latest_by": "modified"},
),
]
4 changes: 4 additions & 0 deletions wcivf/apps/parties/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ def is_independent(self):
"""
return self.party_id == "ynmp-party:2"

@property
def is_joint_party(self):
return self.party_id.startswith("joint-party:")


class LocalParty(models.Model):
parent = models.ForeignKey(
Expand Down
68 changes: 68 additions & 0 deletions wcivf/apps/people/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,74 @@ def get_max_facebook_ad_spend(self):
)
)

@property
def facebook_personal_username(self):
facebook_personal_url = self.facebook_personal_url
facebook_split = list(filter(None, facebook_personal_url.split("/")))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With all these properties:

First, I wonder if there's a way to DRY up the methods a little - like pulling the main logic in to one place?

Second, parsing URLs is (or can be) hard - for example, we don't know that someone hadn't added a querystring to the end of a given URL that might look odd.

Here's an example from the actual data:

https://www.facebook.com/sarahmurraylibdem?notif_id=1523864067803194&notif_t=page_invite_accept&ref=notif.

I think this code would reduce this down to:

sarahmurraylibdem?notif_id=1523864067803194&notif_t=page_invite_accept&ref=notif.

A better option might be to use Python's build in URL parsing:

from urllib.parse import urlparse
parsed_url = urlparse('https://www.facebook.com/sarahmurraylibdem?notif_id=1523864067803194&notif_t=page_invite_accept&ref=notif')

Now parsed_url.path would be sarahmurraylibdem but might also contain more path elements, so we'd want to then do `url = parsed_url.path.split("/")[0].

Of course the real solution here is to get the screen name from the 3rd party site itself, but that's a problem for another day!

Copy link
Contributor Author

@VirginiaDooley VirginiaDooley Feb 24, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Absolutely. I'll put this on my 'things to refactor' list. 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Punting this to an issue as suggested so we can get this reviewed and rolled out faster.

facebook_personal_username = facebook_split[-1]

return facebook_personal_username

@property
def facebook_username(self):
facebook_page_url = self.facebook_page_url
facebook_split = list(filter(None, facebook_page_url.split("/")))
return facebook_split[-1]

@property
def instagram_username(self):
instagram_url = self.instagram_url
instagram_split = list(filter(None, instagram_url.split("/")))
instagram_username = instagram_split[-1]

return instagram_username

@property
def linkedin_username(self):
linkedin_url = self.linkedin_url
linkedin_split = list(filter(None, linkedin_url.split("/")))
linkedin_username = linkedin_split[-1]

return linkedin_username

@property
def youtube_username(self):
youtube_url = self.youtube_profile
if "channel" in youtube_url:
return self.name + "'s Channel"
youtube_split = list(filter(None, youtube_url.split("/")))
youtube_username = youtube_split[-1]
return youtube_username

@property
def long_statement(self):
return self.statement_count > 100

@property
def statement_count(self):
statement = self.statement_to_voters
statement_count = len(statement.split())
return statement_count

@property
def statement_intro(self):
statement_intro = self.statement_to_voters.split(".")[0] + "."
return statement_intro

@property
def statement_remainder(self):
statement_split = self.statement_to_voters.split(".")
statement_remainder = ".".join(statement_split[1:])

return statement_remainder

@property
def display_deceased(self):
if self.death_date and self.current_or_future_candidacies:
VirginiaDooley marked this conversation as resolved.
Show resolved Hide resolved
return True
else:
return False

@cached_property
def current_or_future_candidacies(self):
"""
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{% if object.wikipedia_bio or object.associatedcompany_set.exists or object.cv %}
<section class="ds-card">
<div class="ds-card-body">
<h2 class="ds-candidate-name ds-h3">
About {{ object.name }}
</h2>
{% if object.cv %}
<p>
<h3>CV</h3>
<p>{{ object.cv }}</p>
{% endif %}
</p>

{% if object.wikipedia_bio %}
<h3>Wikipedia</h3>
<p>{{ object.wikipedia_bio }}</p>
<a href="{{ object.wikipedia_url }}" class="link-button">Read more on Wikipedia</a>
{% endif %}

{% if object.associatedcompany_set.exists %}
<h3>Associated companies</h3>
<p>{{object.name}} is associated with the following companies:</p>
<ul>
{% for company in object.associatedcompany_set.all %}
<li>
<strong>{{ company.company_name }}</strong>

{{ company.role }}{% if company.role_status %}({{ company.role_status }}){% endif %}
{{ company.role_appointed_date | date:"Y" }} &ndash; {{ company.role_resigned_date | date:"Y"}}

<a href="https://beta.companieshouse.gov.uk/company/{{ company.company_number }}/">
More details from Companies House}
</a>
</li>
{% endfor %}
</ul>
{% endif %}
</div>
</section>
{% endif %}
108 changes: 108 additions & 0 deletions wcivf/apps/people/templates/people/includes/_person_contact_card.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
<section class="ds-card">
<div class="ds-card-body ds-stack-smaller">
<h2 class="ds-candidate-name ds-h3">
{{ object.name }} online
</h2>
<dl class="ds-descriptions">
{% if object.facebook_page_url or object.facebook_personal_url %}
<div>
<dt>Facebook</dt>
<div>
{% if object.facebook_personal_url %}
<dd>
<a href="{{ object.facebook_personal_url }}" title="{{ object.name }}'s Facebook personal page">
{{ object.facebook_personal_username }}
</a><br />
</dd>
{% endif %}
{% if object.facebook_page_url %}
<dd>
<a href="{{ object.facebook_page_url }}" title="{{ object.name }}'s Facebook page">
{{ object.facebook_username}}
</a>
</dd>
{% endif %}
</div>
</div>
{% endif %}

{% if object.linkedin_url %}
<div>
<dt>LinkedIn</dt>
<dd>
<a href="{{ object.linkedin_url }}" title="{{ object.name }}'s LinkedIn profile">
{{ object.linkedin_username}}
</a>
</dd>
</div>
{% endif %}

{% if object.homepage_url %}
<div>
<dt>Home page</dt>
<dd>
<a href="{{ object.homepage_url }}" title="{{ object.name }}'s home page">
{{ object.homepage_url }}
</a>
</dd>
</div>
{% endif %}

{% if object.instagram_url %}
<div>
<dt>Instagram</dt>
<dd>
<a href="{{ object.instagram_url }}" title="{{ object.name }}'s instagram">
{{ object.instagram_username }}
</a>
</dd>
</div>
{% endif %}

{% if object.youtube_profile %}
<div>
<dt>YouTube</dt>
<dd>
<a href="{{ object.youtube_profile }}" title="{{ object.name }}'s YouTube">
{{ object.youtube_username }}
</a>
</dd>
</div>
{% endif %}

{% if object.party_ppc_page_url %}
<div>
<dt>The party's candidate page for this person</dt>
<dd>
<a href="{{ object.party_ppc_page_url }}" title="Party page for {{ object.name }}">
{{ object.party_ppc_page_url }}
</a>
</dd>
</div>
{% endif %}

{% if object.email and object.current_or_future_candidacies %}
<div>
<dt>Email</dt>
<dd>
<a href="mailto:{{ object.email }}">{{ object.email }}</a>
</dd>
</div>
{% else %}
<div>
<dt>We don't know {{ object.name }}'s email address.</dt>
<dd>
<a href="{{ object.get_ynr_url }}">Can you add it?</a>
</dd>
</div>
{% endif %}
</dl>
<h3>Latest tweets</h3>
<div class="twitter_container">
<a data-width="100%" data-height="500" class="twitter-timeline" href="https://twitter.com/{{ object.twitter_username }}">
Tweets by @{{ object.twitter_username }}</a>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
</div>
</div>
</section>

Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{% load humanize %}

{% if object.current_or_future_candidacies %}
<section class="ds-card">
<div class="ds-card-body">
<h3>That's all we know! Will you help us find more about this candidate?</h3>
<p>Our volunteers have been working hard to add information on as many
candidates as possible, but they need help.
</p>

{% if object.should_show_email_cta %}
<p>Thousands of voters will rely on this site.
{% else %}
<p>
{% endif %}
If you can add information that should be on this page

{% if object.cta_example_details %}
- such as {{ object.name }}'s
{{ object.cta_example_details|join:", " }} -
{% endif %}
please use our crowdsourcing website to add it.</p>
<a href="{{ object.get_ynr_url }}update/" class="ds-cta ds-cta-blue">
Add or edit details &raquo;
</a>
{% if object.should_show_email_cta %}
<p>You can also email {{ object.name }} directly to ask them to add information to this page.
<p>
<a href="{% url 'email_person_view' pk=object.pk ignored_slug=person.name|slugify %}"
class="ds-cta ds-cta-blue">Ask the
candidate for more information &raquo;</a>
</p>
{% endif %}

<h4>Upload your leaflets</h4>
<p>If you've received election leaflets from {{ object.name }}, please take a photo
of them and upload them to ElectionLeaflets.org</p>
<p><a class="ds-button ds-cta ds-cta-blue" type="button" href="https://electionleaflets.org/">Add leaflets</a>
</p>
</div>
</section>
{% endif %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{% load humanize %}

{% if object.postelection.husting_set.exists and object.current_or_future_candidacies %}
<section class="ds-card ds-stack-smaller">
<div class="ds-card-body">
<h3>Local hustings</h3>
<p>You can meet candidates and question them at local hustings. Here are hustings where {{ object.name }} may
be
appearing.
</p>
{% include "elections/includes/_hustings_list.html" with hustings=object.postelection.husting_set.all %}
</div>
</section>
{% endif %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<section class="ds-candidate">
<div class="ds-candidate-body ds-stack-smaller">
<h2 class="ds-candidate-name ds-h3">
{{ object.name }}
</h2>
{% if person.display_deceased and person.personpost.party.is_independent %}
(Deceased)
{% endif %}

{% if object.current_or_future_candidacies.all.count > 1 %}
<h5>{{ object.name }} is {% if object.personpost.party.is_independent %}an{% else %}a{% endif %} {{object.personpost.party.party_name }} candidate in the following elections:</h5>

{% for candidacy in object.current_or_future_candidacies %}
<ul>
<li>
{{ candidacy.election.name }} for {{ candidacy.post_election.friendly_name }}
</li>
</ul>
{% endfor %}

{% else %}
<p>
{{ object.intro|safe }}.
</p>
{% endif %}
</div>

{% if object.photo_url %}
<div class="ds-candidate-image">
<img src="{{ object.photo_url }}" alt="profile photo of {{ object.name }}">
</div>
{% endif %}
</section>
Loading