Skip to content

Commit

Permalink
Profile component (#1825)
Browse files Browse the repository at this point in the history
* adds a "profiles by id" streamfield component
* adds a "latest X profiles" streamfield component
  • Loading branch information
Pomax committed Sep 21, 2018
1 parent 5b32703 commit 6440c46
Show file tree
Hide file tree
Showing 8 changed files with 386 additions and 0 deletions.
Binary file added network-api/db.sqlite3.backup
Binary file not shown.
135 changes: 135 additions & 0 deletions network-api/networkapi/wagtailpages/customblocks.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import json

from urllib import request, parse
from django.conf import settings
from wagtail.core import blocks
from wagtail.images.blocks import ImageChooserBlock

Expand Down Expand Up @@ -339,3 +343,134 @@ class Meta:
template = 'wagtailpages/blocks/pulse_project_list.html'
icon = 'site'
value_class = PulseProjectQueryValue


class ProfileById(blocks.StructBlock):

ids = blocks.CharBlock(
label='Profile by ID',
help_text='Show profiles for pulse users with specific profile ids'
' (mozillapulse.org/profile/[##]). For multiple profiles'
', specify a comma separated list (e.g. 85,105,332).'
)

def get_context(self, value, parent_context=None):
context = super().get_context(value, parent_context=parent_context)
ids = context['block'].value['ids']
data = list()

# FIXME: the protocol should be part of the pulse api variable.
# see: https://github.com/mozilla/foundation.mozilla.org/issues/1824

url = "https://{pulse_api}/api/pulse/v2/profiles/?format=json&ids={ids}".format(
pulse_api=settings.FRONTEND['PULSE_API_DOMAIN'],
ids=ids
)

try:
response = request.urlopen(url)
response_data = response.read()
data = json.loads(response_data)

except (IOError, ValueError) as exception:
print(str(exception))
pass

context['profiles'] = data
return context

class Meta:
template = 'wagtailpages/blocks/profile_blocks.html'
icon = 'user'


class LatestProfileQueryValue(blocks.StructValue):
@property
def size(self):
max_number_of_results = self['max_number_of_results']
return '' if max_number_of_results <= 0 else max_number_of_results

@property
def rev(self):
# The default API behaviour is newest-first, so the "rev" attribute
# should only have an attribute value when oldest-first is needed.
newest_first = self['newest_first']
return True if newest_first else ''


class LatestProfileList(blocks.StructBlock):
max_number_of_results = blocks.IntegerBlock(
min_value=1,
max_value=48,
default=12,
required=True,
help_text='Pick up to 48 profiles.',
)

advanced_filter_header = blocks.StaticBlock(
label=' ',
admin_text='-------- ADVANCED FILTERS: OPTIONS TO DISPLAY FEWER, MORE TARGETED RESULTS. --------',
)

profile_type = blocks.CharBlock(
required=False,
default='',
help_text='Example: Fellow.'
)

program_type = blocks.CharBlock(
required=False,
default='',
help_text='Example: Tech Policy.'
)

year = blocks.CharBlock(
required=False,
default=''
)

def get_context(self, value, parent_context=None):
context = super().get_context(value, parent_context=parent_context)
query_args = {
'limit': context['block'].value['max_number_of_results'],
'profile_type': context['block'].value['profile_type'],
'program_type': context['block'].value['program_type'],
'program_year': context['block'].value['year'],
'ordering': '-id',
'is_active': 'true',
'format': 'json',
}

# filter out emptish values
query_args = {k: v for k, v in query_args.items() if v}

# FIXME: the protocol should be part of the pulse api variable.
# see: https://github.com/mozilla/foundation.mozilla.org/issues/1824

url = "https://{pulse_api}/api/pulse/v2/profiles/?{query}".format(
pulse_api=settings.FRONTEND['PULSE_API_DOMAIN'],
query=parse.urlencode(query_args)
)

try:
response = request.urlopen(url)
response_data = response.read()
data = json.loads(response_data)

for profile in data:
profile['created_entries'] = False
profile['published_entries'] = False
profile['entry_count'] = False
profile['user_bio_long'] = False

except (IOError, ValueError) as exception:
print(str(exception))
pass

context['profiles'] = data
return context

class Meta:
template = 'wagtailpages/blocks/profile_blocks.html'
icon = 'group'
value_class = LatestProfileQueryValue

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions network-api/networkapi/wagtailpages/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@
('spacer', customblocks.BootstrapSpacerBlock()),
('quote', customblocks.QuoteBlock()),
('pulse_listing', customblocks.PulseProjectList()),
('profile_listing', customblocks.LatestProfileList()),
('profile_by_id', customblocks.ProfileById()),
]


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<div class="profiles">
<div class="row">
{% for profile in profiles %}
<div class="col-md-6 col-12 mb-5">
<div class="person-card row no-gutters">
<div class="col-4 mr-3">
<div class="row">
<div class="col">
<img
src="{% if profile.thumbnail %}{{ profile.thumbnail }}{% else %}/_images/fellowships/headshot/placeholder.jpg{% endif %}"
class="headshot"
alt="Headshot"
>
</div>
</div>
</div>
<div class="col bio-content pt-3">

<div class="meta-block mb-2">
<div class="h5-heading mb-1">{{profile.name }}</div>
{% if profile.program_type %}
<div class="meta-block-item meta-block-item-role">{{ profile.program_type }}{% if profile.program_year %}, {{ profile.program_year }}{% endif %}</div>
{% endif %}
</div>

{% if profile.issues|length > 0 %}
<div class="person-issues">
{% for issue in profile.issues %}
<span class="issue-link small d-inline-block mr-1">{{ issue }}</span>
{% endfor %}
</div>
{% endif %}

<hr>

<div class="full-profile">
<a href="https://www.mozillapulse.org/profile/{{ profile.profile_id }}">SEE FULL PROFILE →</a>
</div>

</div>
</div>
</div>
{% endfor %}
</div>
</div>
2 changes: 2 additions & 0 deletions source/sass/wagtail.scss
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,5 @@ body div.wagtail-draft-warning {
font-weight: bold;
text-transform: uppercase;
}

@import './wagtail/blocks';
4 changes: 4 additions & 0 deletions source/sass/wagtail/blocks.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.cms {
@import './profiles';
}

109 changes: 109 additions & 0 deletions source/sass/wagtail/profiles.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
.profiles {
.headshot {
width: 100%;
}

.person-card {
border-top: 0.25rem solid black;
}

.person-card-featured {
.more-details {
background-color: $blue;
color: white;

&:hover {
background-color: $dark-blue;
}
}
}

.person-issues {
line-height: 1;
}

.meta-block {
.meta-block-item {
display: flex;
align-items: center;
font-size: 12px;
font-weight: 900;

&::before {
width: 12px;
height: 12px;
display: block;
content: '';
margin-right: 5px;
background-size: contain;
background-repeat: no-repeat;
}
}

.meta-block-item-role {
&::before {
background-image: url('/_images/glyphs/mozilla-icon.svg');
}
}

.meta-block-item-location {
&::before {
background-image: url('/_images/glyphs/map-marker-icon.svg');
}
}
}

.person-social-links {
position: relative;
z-index: 1;
border-top: 1px solid $gray-lightest;
padding-top: 0.75em;
}

.issue-link {
font-style: italic;
}

.issue-link:not(:last-child)::after {
content: ', ';
}

.person-quote {
z-index: 1;

&::before {
content: '\201C';
font-size: 15em;
color: $subtle-gray;
z-index: -1;
position: absolute;
font-weight: bold;
font-style: initial;
top: -0.3em;
}
}

.person-bio {
margin-top: 1em;

ul {
list-style-type: disc;
list-style-position: outside;
padding: 0 30px;
}
}

.partnership_logo {
max-width: 8rem;
max-height: 3rem;
filter: grayscale(100%) opacity(50%);
}

.full-profile {
text-align: left;

@media (min-width: $bp-md) {
text-align: right;
}
}
}

0 comments on commit 6440c46

Please sign in to comment.