-
Notifications
You must be signed in to change notification settings - Fork 153
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鈥檒l occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fellowships directory pages #1046
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,15 @@ | ||
{% extends "fellowships-base.html" %} | ||
|
||
{% block template_id %}fellows-directory{% endblock %} | ||
|
||
{% block body %} | ||
fellows directory | ||
<div class="row"> | ||
<div class="col-md-12 col-lg-9"> | ||
<div class="mb-4"> | ||
<h1 class="h1-white">Fellows Directory</h1> | ||
</div> | ||
</div> | ||
</div> | ||
|
||
<div id="fellows-directory-featured-fellows"></div> | ||
{% endblock %} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
{% extends "fellowships-base.html" %} | ||
|
||
{% block template_id %}fellows-directory-{{type|slugify}}{% endblock %} | ||
|
||
{% block body %} | ||
<div id="fellowship-breadcrumb"> | ||
<ol class="breadcrumb"> | ||
<li class="breadcrumb-item small-gray"> | ||
<a href="{% url 'fellowships-directory' %}" class="small-gray">Directory</a> | ||
</li> | ||
<li class="breadcrumb-item small-gray active text-capitalize"> | ||
{{ type }} Fellows | ||
</li> | ||
</ol> | ||
</div> | ||
|
||
<div class="row"> | ||
<div class="col-12"> | ||
<div class="mb-4"> | ||
<h1 class="h1-white text-capitalize">{{ type }} Fellows</h1> | ||
</div> | ||
</div> | ||
</div> | ||
|
||
<div id="fellows-directory-fellows-by-type" data-type="{{type}}"> | ||
</div> | ||
{% endblock %} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -80,7 +80,7 @@ | |
<div class="col"> | ||
<div id="multipage-nav" class="d-flex flex-row align-items-center"> | ||
<div><a href="{% url 'fellowships-home' %}" class="{% fellowship_active_nav request 'fellowships-home fellowships-science fellowships-open-web' %}">Fellowships</a></div> | ||
<div><a href="{% url 'fellowships-directory' %}" class="{% fellowship_active_nav request 'fellowships-directory' %}">Directory</a></div> | ||
<div><a href="{% url 'fellowships-directory' %}" class="{% fellowship_active_nav request 'fellowships-directory fellowships-directory-senior' %}">Directory</a></div> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similar to above, I'm not clear on what the |
||
<div><a href="{% url 'fellowships-support' %}" class="{% fellowship_active_nav request 'fellowships-support' %}">Support the Program</a></div> | ||
<div><a href="{% url 'fellowships-apply' %}" class="{% fellowship_active_nav request 'fellowships-apply' %}">Apply to be a Fellow</a></div> | ||
</div> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
#multipage-nav-mobile { | ||
background: #f2f2f2; | ||
background: $off-white; | ||
|
||
.multipage-nav { | ||
div:first-child { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,8 +5,152 @@ import ReactDOM from 'react-dom'; | |
|
||
import Person from './components/people/person.jsx'; | ||
|
||
let pulseApiDomain = ``; | ||
const DIRECOTRY_PAGE_FILTER_OPTIONS = {'program_year': `2017`}; | ||
const DIRECTORY_PAGE_TYPE_ORDER = [ `senior`, `science`, `open web`, `tech policy`, `media`]; | ||
|
||
function getFellows(params, callback) { | ||
Object.assign(params, {'profile_type': `fellow`}); | ||
|
||
let queryString = Object.entries(params).map(pair => pair.map(encodeURIComponent).join(`=`)).join(`&`); | ||
let req = new XMLHttpRequest(); | ||
|
||
req.addEventListener(`load`, () => { | ||
callback.call(this, JSON.parse(req.response)); | ||
}); | ||
|
||
req.open(`GET`, `https://${pulseApiDomain}/api/pulse/profiles/?${queryString}`); | ||
req.send(); | ||
} | ||
|
||
function renderFellowCard(fellow) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you put a comment in describing what this is doing (vs, say, the existing |
||
// massage fellow's Pulse profile data and pass it to <Person> to render | ||
|
||
let links = {}; | ||
|
||
if ( fellow.twitter ) { | ||
links.twitter = fellow.twitter; | ||
} | ||
|
||
if ( fellow.linkedin ) { | ||
links.linkedIn = fellow.linkedin; | ||
} | ||
|
||
let metadata = { | ||
'internet_health_issues': fellow.issues, | ||
links: links, | ||
name: fellow.custom_name, | ||
role: `${fellow.program_type}${fellow.program_year ? `, ${fellow.program_year}` : ``}`, | ||
image: fellow.thumbnail, | ||
affiliations: [ fellow.affiliation ], | ||
'custom_link': { text: `See work`, link: `/fellowships/directory` } | ||
}; | ||
|
||
return <Person metadata={metadata} key={fellow.custom_name} />; | ||
} | ||
|
||
function groupFellowsByAttr(attribute, fellows) { | ||
if (!attribute) { | ||
return false; | ||
} | ||
|
||
let fellowsGroup = {}; | ||
|
||
fellows.forEach(fellow => { | ||
let attr = fellow[attribute]; | ||
|
||
if (!attr) { | ||
return; | ||
} | ||
|
||
if (!fellowsGroup[attr]) { | ||
fellowsGroup[attr] = [fellow]; | ||
} else { | ||
fellowsGroup[attr].push(fellow); | ||
} | ||
}); | ||
|
||
return fellowsGroup; | ||
} | ||
|
||
function renderFellowsOnDirectoryPage() { | ||
let getTypeSlug = function(type) { | ||
return type.toLowerCase().replace(`fellow`,``).trim().replace(/\s/g, `-`); | ||
}; | ||
|
||
let renderFilterOption = function(option) { | ||
return <button | ||
className="btn btn-link text-capitalize" | ||
key={option} | ||
onClick={(event) => { window.scrollTo(0, document.getElementById(event.target.dataset.targetId).offsetTop); }} | ||
data-target-id={`fellowships-directory-${getTypeSlug(option)}`} | ||
> | ||
{`${option}${option === `senior` ? ` Fellow` :``}`} | ||
</button>; | ||
}; | ||
|
||
getFellows(DIRECOTRY_PAGE_FILTER_OPTIONS, fellows => { | ||
let fellowsByType = groupFellowsByAttr(`program_type`, fellows); | ||
|
||
// render filter bar | ||
let filterBar = <div className="row"> | ||
<div className="col-12"> | ||
<div id="fellowships-directory-filter" className="d-flex flex-wrap p-2"> | ||
<div className="d-inline-block mr-2"><strong>Areas:</strong></div> | ||
{ DIRECTORY_PAGE_TYPE_ORDER.map(renderFilterOption) } | ||
</div> | ||
</div> | ||
</div>; | ||
|
||
// render program type sections | ||
let sections = Object.keys(fellowsByType).sort((a, b) => { | ||
let aIndex = DIRECTORY_PAGE_TYPE_ORDER.indexOf(a.replace(`fellow`,``).trim()); | ||
let bIndex = DIRECTORY_PAGE_TYPE_ORDER.indexOf(b.replace(`fellow`,``).trim()); | ||
|
||
return aIndex - bIndex; | ||
}).map(type => { | ||
return <div className="row my-4" key={type} id={`fellowships-directory-${getTypeSlug(type)}`}> | ||
<div className="col-12"> | ||
<h3 className="h3-black text-capitalize">{type}s</h3> | ||
<div className="row"> | ||
{fellowsByType[type].map(renderFellowCard)} | ||
</div> | ||
</div> | ||
<div className="col-12 text-center mt-3 mb-5"> | ||
<a href={`/fellowships/directory/${getTypeSlug(type)}`} className="btn btn-ghost">See all {type}s</a> | ||
</div> | ||
</div>; | ||
}); | ||
|
||
ReactDOM.render(<div>{filterBar}<div className="featured-fellow">{sections}</div></div>, document.getElementById(`fellows-directory-featured-fellows`)); | ||
}); | ||
} | ||
|
||
function renderFellowsOnDirectoryByTypePage() { | ||
let type = document.getElementById(`fellows-directory-fellows-by-type`).dataset.type; | ||
|
||
getFellows({'program_type': `${type} fellow`}, fellows => { | ||
let fellowsByYear = groupFellowsByAttr(`program_year`, fellows); | ||
|
||
let sections = Object.keys(fellowsByYear).sort().reverse().map(year => { | ||
return <div className="row mb-5" key={year}> | ||
<div className="col-12"> | ||
<div className="mb-4"> | ||
<h2 className="h2-typeaccents-gray">{year}</h2> | ||
</div> | ||
</div> | ||
{fellowsByYear[year].map(renderFellowCard)} | ||
</div>; | ||
}); | ||
|
||
ReactDOM.render(<div className="featured-fellow">{sections}</div>, document.getElementById(`fellows-directory-fellows-by-type`)); | ||
}); | ||
} | ||
|
||
// Embed various Fellowships pages related React components | ||
function injectReactComponents() { | ||
function injectReactComponents(pulseApiURL) { | ||
pulseApiDomain = pulseApiURL; | ||
|
||
// Science Fellowship | ||
if (document.getElementById(`featured-science-fellow`)) { | ||
let metadata = { | ||
|
@@ -19,7 +163,7 @@ function injectReactComponents() { | |
image: `https://images.pexels.com/photos/264206/pexels-photo-264206.jpeg?w=500`, | ||
quote: `Quote quote quote quote quote quote quote quote quote quote quote quote.`, | ||
affiliations: [`Stanford University Professor; YouthLAB founder`], | ||
'fellow_directory_link': { type: `science`, link: `/fellowships/directory` } | ||
'custom_link': { text: `See all science fellows`, link: `/fellowships/directory` } | ||
}; | ||
|
||
ReactDOM.render(<Person metadata={metadata} />, document.getElementById(`featured-science-fellow`)); | ||
|
@@ -37,7 +181,7 @@ function injectReactComponents() { | |
image: `https://images.pexels.com/photos/802112/pexels-photo-802112.jpeg?w=500`, | ||
quote: `Quote quote quote quote quote quote quote quote quote quote quote quote.`, | ||
affiliations: [`Stanford University Professor; YouthLAB founder`], | ||
'fellow_directory_link': { type: `science`, link: `/fellowships/directory` } | ||
'custom_link': { text: `See all science fellows`, link: `/fellowships/directory` } | ||
}; | ||
|
||
ReactDOM.render(<Person metadata={metadata} />, document.getElementById(`featured-open-web-fellow`)); | ||
|
@@ -55,11 +199,21 @@ function injectReactComponents() { | |
image: `https://static.pexels.com/photos/416138/pexels-photo-416138.jpeg?w=500`, | ||
quote: `Quote quote quote quote quote quote quote quote quote quote quote quote.`, | ||
affiliations: [ `Stanford University Professor; YouthLAB founder`], | ||
'fellow_directory_link': { type: `science`, link: `/fellowships/directory` } | ||
'custom_link': { text: `See all science fellows`, link: `/fellowships/directory` } | ||
}; | ||
|
||
ReactDOM.render(<Person metadata={metadata} />, document.getElementById(`featured-fellow-support-page`)); | ||
} | ||
|
||
// Fellows on Fellows Directory page | ||
if (document.querySelectorAll(`#fellows-directory-featured-fellows`)) { | ||
renderFellowsOnDirectoryPage(); | ||
} | ||
|
||
// Fellows on individual Directory page (e.g., science directory, open web directory) | ||
if (document.getElementById(`fellows-directory-fellows-by-type`)) { | ||
renderFellowsOnDirectoryByTypePage(); | ||
} | ||
} | ||
|
||
export default { injectReactComponents }; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,13 +23,14 @@ import fellowships from './fellowships'; | |
const SHOW_MEMBER_NOTICE = false; | ||
|
||
// To be populated via XHR... | ||
let env, networkSiteURL; | ||
let env, networkSiteURL, pulseApiURL; | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this going to cause problems when promoting heroku pipelines? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh or is it pulling this from the environment json view that the server exposes? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @alanmoo I think it should be fine. I'm following exactly how we are doing to get |
||
let main = { | ||
init () { | ||
this.fetchEnv((envData) => { | ||
env = envData; | ||
networkSiteURL = env.NETWORK_SITE_URL; | ||
pulseApiURL = env.PULSE_API_DOMAIN; | ||
|
||
// HEROKU_APP_DOMAIN is used by review apps | ||
if (!networkSiteURL && env.HEROKU_APP_NAME) { | ||
|
@@ -247,7 +248,7 @@ let main = { | |
} | ||
|
||
// Fellowships pages related components | ||
fellowships.injectReactComponents(); | ||
fellowships.injectReactComponents(pulseApiURL); | ||
} | ||
}; | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this called "senior"?