Skip to content

Commit cd41a39

Browse files
authored
Merge pull request #2213
Add a separate page for each Rust team member
2 parents 9b68df4 + 03913b9 commit cd41a39

File tree

11 files changed

+333
-23
lines changed

11 files changed

+333
-23
lines changed

Cargo.lock

Lines changed: 52 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ toml = "0.9"
1515
serde_json = "1.0"
1616
rust_team_data = { git = "https://github.com/rust-lang/team" }
1717
percent-encoding = "2.3.2"
18+
rayon = "1"
1819

1920
[dev-dependencies]
2021
time = { version = "0.3.44", features = ["parsing"] }

locales/en-US/governance.ftl

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,12 @@ governance-members-header = Members
3434
governance-alumni-header = Alumni
3535
governance-alumni-thanks = We also want to thank all past members for their invaluable contributions!
3636
37-
## governance/all-team-members.mbs
37+
## governance/all-team-members.hbs
3838
governance-all-team-members-title = All Rust team members
3939
governance-all-team-members-intro = This section lists the members of currently active Rust teams.
4040
governance-all-team-members-alumni-intro = This section lists our team alumni.
41+
42+
## govenance/person.hbs
43+
governance-person-title = Rust Project team member
44+
governance-person-team-member = Team member
45+
governance-person-team-alumni = Alumni

src/render.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ use crate::{BaseUrl, ENGLISH, LAYOUT};
77
use anyhow::Context;
88
use handlebars::Handlebars;
99
use handlebars_fluent::{Loader, SimpleLoader};
10+
use rayon::iter::IntoParallelRefIterator;
11+
use rayon::iter::ParallelIterator;
1012
use serde::Serialize;
1113
use std::ffi::OsStr;
1214
use std::fs::File;
@@ -180,11 +182,14 @@ pub fn render_index(render_ctx: &RenderCtx) -> anyhow::Result<()> {
180182
pub fn render_governance(render_ctx: &RenderCtx) -> anyhow::Result<()> {
181183
let data = render_ctx.teams.index_data();
182184

185+
// Index page
183186
for_all_langs("governance/index.html", |dst_path, lang| {
184187
render_ctx
185188
.page("governance/index", "governance-page-title", &data, lang)
186189
.render(dst_path)
187190
})?;
191+
192+
// Individual teams
188193
for team in data.teams {
189194
let data: PageData = render_ctx
190195
.teams
@@ -207,6 +212,7 @@ pub fn render_governance(render_ctx: &RenderCtx) -> anyhow::Result<()> {
207212
)?;
208213
}
209214

215+
// Archived teams
210216
let archived_teams_data = render_ctx.teams.archived_teams();
211217
for_all_langs("governance/archived-teams.html", |dst_path, lang| {
212218
render_ctx
@@ -219,6 +225,7 @@ pub fn render_governance(render_ctx: &RenderCtx) -> anyhow::Result<()> {
219225
.render(dst_path)
220226
})?;
221227

228+
// Page with all team members
222229
let all_team_members_data = render_ctx.teams.all_team_members();
223230
for_all_langs("governance/all-team-members.html", |dst_path, lang| {
224231
render_ctx
@@ -231,6 +238,28 @@ pub fn render_governance(render_ctx: &RenderCtx) -> anyhow::Result<()> {
231238
.render(dst_path)
232239
})?;
233240

241+
// A specific page for each team member
242+
let all_person_data = render_ctx.teams.all_person_data();
243+
all_person_data
244+
.par_iter()
245+
.map(|person| {
246+
// Use <username>/index.html for a nicer URL (/people/foo vs /people/foo.html).
247+
for_all_langs(
248+
&format!("governance/people/{}/index.html", person.github),
249+
|dst_path, lang| {
250+
render_ctx
251+
.page(
252+
"governance/person",
253+
"governance-person-title",
254+
&person,
255+
lang,
256+
)
257+
.render(dst_path)
258+
},
259+
)
260+
})
261+
.collect::<anyhow::Result<Vec<_>>>()?;
262+
234263
Ok(())
235264
}
236265

src/teams.rs

Lines changed: 159 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,15 +71,11 @@ impl RustTeams {
7171
.filter(|team| team.website_data.is_some())
7272
// On the main page, show the leadership-council and all top-level
7373
// teams.
74-
.filter(|team| team.kind == TeamKind::Team && team.subteam_of.is_none())
74+
.filter(is_toplevel_team)
7575
.map(|team| IndexTeam {
7676
section: kind_to_str(team.kind),
7777
page_name: team.website_data.clone().unwrap().page,
78-
url: format!(
79-
"{}/{}",
80-
kind_to_str(team.kind),
81-
team.website_data.as_ref().unwrap().page
82-
),
78+
url: get_team_relative_url(&team),
8379
team,
8480
})
8581
.collect::<Vec<IndexTeam>>();
@@ -234,6 +230,111 @@ impl RustTeams {
234230

235231
AllTeamMembers { active, alumni }
236232
}
233+
234+
pub fn all_person_data(&self) -> Vec<PersonData> {
235+
let mut people: HashMap<String, PersonData> = HashMap::new();
236+
237+
enum TeamMode {
238+
Member,
239+
Alumni,
240+
MemberOfArchivedTeam,
241+
}
242+
243+
fn add_team(
244+
people: &mut HashMap<String, PersonData>,
245+
ctx: &RustTeams,
246+
member: &TeamMember,
247+
team: &Team,
248+
mode: TeamMode,
249+
) {
250+
let person = people
251+
.entry(member.github.clone())
252+
.or_insert_with(move || PersonData {
253+
name: member.name.clone(),
254+
github: member.github.clone(),
255+
active_teams: vec![],
256+
alumni_teams: vec![],
257+
});
258+
let teams = match mode {
259+
TeamMode::Member => &mut person.active_teams,
260+
TeamMode::Alumni | TeamMode::MemberOfArchivedTeam => &mut person.alumni_teams,
261+
};
262+
let url = match mode {
263+
TeamMode::Member | TeamMode::Alumni => ctx.get_toplevel_team_url(team),
264+
TeamMode::MemberOfArchivedTeam => Some("archived-teams.html".to_string()),
265+
};
266+
teams.push(PersonTeam::new(team, member, url));
267+
}
268+
269+
for team in &self.archived_teams {
270+
for member in team.members.iter().chain(&team.alumni) {
271+
add_team(
272+
&mut people,
273+
self,
274+
member,
275+
team,
276+
TeamMode::MemberOfArchivedTeam,
277+
);
278+
}
279+
}
280+
for team in &self.teams {
281+
if team.kind == TeamKind::MarkerTeam && team.website_data.is_none() {
282+
continue;
283+
}
284+
285+
for member in &team.members {
286+
add_team(&mut people, self, member, team, TeamMode::Member);
287+
}
288+
for member in &team.alumni {
289+
add_team(&mut people, self, member, team, TeamMode::Alumni);
290+
}
291+
}
292+
293+
let mut people: Vec<PersonData> = people.into_values().collect();
294+
people.sort_by(|a, b| a.github.cmp(&b.github));
295+
296+
for person in &mut people {
297+
person
298+
.active_teams
299+
.sort_by(|a, b| a.webpage_name.cmp(&b.webpage_name));
300+
person
301+
.alumni_teams
302+
.sort_by(|a, b| a.webpage_name.cmp(&b.webpage_name));
303+
}
304+
305+
people
306+
}
307+
308+
fn get_toplevel_team_url<'a>(&'a self, mut team: &'a Team) -> Option<String> {
309+
while !is_toplevel_team(team) {
310+
let Some(parent) = &team.subteam_of else {
311+
return None;
312+
};
313+
let parent = self.teams.iter().find(|t| t.name == *parent)?;
314+
team = parent;
315+
}
316+
317+
if team.website_data.is_some() {
318+
Some(get_team_relative_url(team))
319+
} else {
320+
None
321+
}
322+
}
323+
}
324+
325+
/// Get a relative URL of a team that should be appended to
326+
/// Should only be used for top-level teams.
327+
fn get_team_relative_url(team: &Team) -> String {
328+
assert!(is_toplevel_team(team));
329+
format!(
330+
"{}/{}",
331+
kind_to_str(team.kind),
332+
team.website_data.as_ref().unwrap().page
333+
)
334+
}
335+
336+
fn is_toplevel_team(team: &Team) -> bool {
337+
team.kind == TeamKind::Team && team.subteam_of.is_none()
237338
}
238339

239340
#[derive(Serialize)]
@@ -272,6 +373,58 @@ pub struct AllTeamMembers {
272373
alumni: Vec<TeamMember>,
273374
}
274375

376+
#[derive(Serialize)]
377+
pub struct PersonTeam {
378+
team: Team,
379+
toplevel_url: Option<String>,
380+
webpage_name: String,
381+
roles: Vec<String>,
382+
}
383+
384+
impl PersonTeam {
385+
fn new(team: &Team, member: &TeamMember, toplevel_url: Option<String>) -> Self {
386+
// Turn inside-rust-reviewers into Inside Rust Reviewers
387+
let normalize_name = |name: &str| {
388+
name.split("-")
389+
.map(|p| {
390+
p.chars()
391+
.take(1)
392+
.flat_map(|c| c.to_uppercase())
393+
.chain(p.chars().skip(1))
394+
.collect::<String>()
395+
})
396+
.collect::<Vec<String>>()
397+
.join(" ")
398+
};
399+
400+
let webpage_name = team
401+
.website_data
402+
.as_ref()
403+
.map(|w| w.name.clone())
404+
.unwrap_or_else(|| normalize_name(&team.name));
405+
406+
let mut roles = vec![];
407+
if member.is_lead {
408+
roles.push("Lead".to_string());
409+
}
410+
roles.extend(member.roles.iter().map(|r| normalize_name(r)));
411+
Self {
412+
team: team.clone(),
413+
toplevel_url,
414+
webpage_name,
415+
roles,
416+
}
417+
}
418+
}
419+
420+
#[derive(Serialize)]
421+
pub struct PersonData {
422+
name: String,
423+
pub github: String,
424+
active_teams: Vec<PersonTeam>,
425+
alumni_teams: Vec<PersonTeam>,
426+
}
427+
275428
pub fn load_rust_teams() -> anyhow::Result<RustTeams> {
276429
println!("Downloading Team API data");
277430

templates/governance/all-team-members.html.hbs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
{{#*inline "member"}}
22
<div class="w-100 w-25-l mb3 flex flex-row items-center">
3-
<a class="mr4 w3 h3 flex-shrink-0" href="https://github.com/{{member.github}}">
3+
<a class="mr4 w3 h3 flex-shrink-0" href="{{baseurl}}/governance/people/{{member.github}}">
44
<img class="w-100 h-100 bg-white br2"
55
src="https://avatars.githubusercontent.com/{{member.github}}"
66
alt="{{member.name}}">
77
</a>
88
<div>
9-
{{member.name}}
9+
<a href="{{baseurl}}/governance/people/{{member.github}}">{{member.name}}</a>
1010
<div class="f4">
1111
GitHub: <a href="https://github.com/{{member.github}}">{{member.github}}</a>
1212
</div>
@@ -24,7 +24,7 @@
2424
<section class="green" style="padding-bottom: 15px;">
2525
<div class="w-100 mw-none mw-8-m mw9-l flex flex-column flex-row-l flex-wrap-l center">
2626
{{#each data.active as |member|}}
27-
{{> member member=member }}
27+
{{> member member=member baseurl=../baseurl }}
2828
{{/each}}
2929
</div>
3030
</section>
@@ -38,7 +38,7 @@
3838
<section class="red" style="padding-bottom: 15px;">
3939
<div class="w-100 mw-none mw-8-m mw9-l flex flex-column flex-row-l flex-wrap-l center">
4040
{{#each data.alumni as |member|}}
41-
{{> member member=member }}
41+
{{> member member=member baseurl=../baseurl }}
4242
{{/each}}
4343
</div>
4444
</section>

0 commit comments

Comments
 (0)