www.trr379.de/layouts/contributors/list.html
Jennifer Krzemien 870014bd46
Restore "Retired" section on the contributors page
The contributor generator (person.py in q02/pool-publication-page) already
writes `active: false` into a person's front matter once the defined end
date of their project association in the knowledge pool has passed. The
redesigned contributors page had stopped evaluating that flag, so former
members were listed among the current ones.

Contributors are now split into a current grid and a "Retired" section
below it, plus a "Retired" filter button that is only rendered when
somebody actually is retired. Both grids hide themselves when a filter
leaves them empty. Card markup moved into a partial so the two grids
cannot drift apart.

Contributors carrying no `active` flag at all (those without any project
association) count as current — a missing flag means "never evaluated",
not "ended".

Also fixes the German page, which rendered bare taxonomy terms (slug
names, no portraits, no metadata) because the person records only exist as
English content files: it now uses the same layout and page set. And the
section illustration is resolved through the page bundle, since a bare
"people.png" resolves to /de/contributors/people.png and 404s.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-21 05:58:26 +02:00

167 lines
7.4 KiB
HTML

{{ define "main" }}
<style>body { height: auto !important; min-height: 100vh !important; }</style>
<link rel="stylesheet" href="/css/projects.css">
<link rel="stylesheet" href="/css/contributors.css">
<div class="contributors-page">
{{/* ── Where the people come from ──
`contributors` is a taxonomy, and the person records exist only as
English content files (content/contributors/<slug>/_index.md — there
is no *.de.md variant). In any other language Hugo therefore only has
the bare taxonomy terms: humanised slug as the title, no portrait, no
params. Contributors are language-independent entities anyway (see the
IRI note in config/_default/config.toml), so every language renders the
English page set. Links then point at the English person pages, which
are the only ones that carry content. */}}
{{ $source := . }}
{{ if ne site.Language.Lang "en" }}
{{ range site.Sites }}
{{ if eq .Language.Lang "en" }}
{{ with .GetPage "/contributors" }}{{ $source = . }}{{ end }}
{{ end }}
{{ end }}
{{ end }}
{{/* ── Header ── */}}
<h1 class="projects-title">Contributors</h1>
<p class="projects-subtitle">Neuropsychobiology of Aggression</p>
<div class="area-bar" style="margin-bottom:2rem">
<div class="area-bar-a" style="flex:8"></div>
<div class="area-bar-b" style="flex:5"></div>
<div class="area-bar-c" style="flex:7"></div>
<div class="area-bar-q" style="flex:3"></div>
</div>
{{/* ── Intro + figure ── */}}
<div class="projects-intro-row" style="margin-bottom:2.5rem">
<div class="projects-intro-text">
<h2 class="projects-areas-title">Contributors</h2>
<p>TRR379 is a large collaborative research initiative. Many individuals contribute their expertise in various roles, such as:</p>
<ul>
<li><a href="/roles/spokesperson/">Spokesperson</a></li>
<li><a href="/roles/deputy-spokesperson/">Deputy spokesperson</a></li>
<li><a href="/roles/pi/">Principal investigator / project lead</a></li>
<li><a href="/roles/postdoc/">Postdoctoral researchers</a></li>
<li><a href="/roles/doctoral-researcher/">Doctoral researchers</a></li>
<li><a href="/roles/research-assistant/">Research assistants</a></li>
<li><a href="/roles/sab-member/">Scientific Advisory Board</a></li>
<li><a href="/roles/eoc-member/">Equal Opportunity Committee</a></li>
<li><a href="/roles/cab-member/">Citizen Advisory Board</a></li>
</ul>
<p>The following individuals are contributing to this effort.</p>
</div>
<div class="projects-intro-figure">
{{/* Via the page bundle — a bare "people.png" would 404 on
/de/contributors/. See layouts/topics/list.html. */}}
{{ with .Resources.GetMatch "people.png" }}
<img src="{{ .RelPermalink }}" alt="">
{{ end }}
</div>
</div>
{{/* ── Role filter buttons ── */}}
<div class="role-filters">
<button class="role-btn active" data-role="all">All</button>
<button class="role-btn" data-role="spokesperson">Spokesperson</button>
<button class="role-btn" data-role="deputy-spokesperson">Deputy spokesperson</button>
<button class="role-btn" data-role="pi">Principal investigator</button>
<button class="role-btn" data-role="postdoc">Postdoc</button>
<button class="role-btn" data-role="doctoral-researcher">Doctoral researcher</button>
{{/* Not a role but a status — the button is only rendered when there is
actually somebody retired, so it never leads to an empty result. */}}
{{ if where $source.Pages "Params.active" false }}
<button class="role-btn role-btn-retired" data-role="retired">Retired</button>
{{ end }}
</div>
{{/* ── Current vs. retired ──
`active` comes from the knowledge pool, not from this repository: the
generator (person.py in q02/pool-publication-page, run by
.forgejo/workflows/contributors-projects.yml) writes `active: false`
into a contributor's front matter once the defined end date of their
project association has passed. Nothing here needs maintaining by
hand — a person moves into the retired grid on the next scheduled run
after their end date.
Contributors with no project association at all carry no `active` flag
(currently 11 of them). Those count as current: a missing flag means
"never evaluated", not "ended". */}}
{{ $current := slice }}
{{ $retired := slice }}
{{ range sort $source.Pages ".Params.sortkey" }}
{{ if eq .Params.active false }}
{{ $retired = $retired | append . }}
{{ else }}
{{ $current = $current | append . }}
{{ end }}
{{ end }}
{{/* ── Portrait grid ── */}}
<div class="contributors-grid" id="contributorsGrid">
{{ range $current }}
{{ partial "contributor-card.html" . }}
{{ end }}
</div>
{{/* ── Retired ── */}}
{{ with $retired }}
<section class="contributors-retired" id="retiredSection">
<h2 class="retired-title">Retired</h2>
<p class="retired-note">
Former members whose contribution to TRR379 has ended. Their pages
remain available.
</p>
<div class="contributors-grid">
{{ range . }}
{{ partial "contributor-card.html" . }}
{{ end }}
</div>
</section>
{{ end }}
</div>
<script>
// The filter spans both grids, so a retired member still shows up when
// filtering by e.g. "Postdoc". "Retired" is a status rather than a role:
// it selects by which grid a card sits in, not by data-roles.
//
// Either grid hides itself once a filter leaves it without a visible card,
// so no empty heading and no gap remains — under "Retired" that means only
// the retired block is left standing.
const mainGrid = document.getElementById('contributorsGrid');
const retiredSection = document.getElementById('retiredSection');
const isRetired = card => retiredSection !== null && retiredSection.contains(card);
function matches(card, role) {
if (role === 'all') return true;
if (role === 'retired') return isRetired(card);
return card.dataset.roles.includes(role);
}
function hideIfEmpty(container) {
if (!container) return;
const anyVisible = [...container.querySelectorAll('.contributor-card')]
.some(card => card.style.display !== 'none');
container.style.display = anyVisible ? '' : 'none';
}
document.querySelectorAll('.role-btn').forEach(btn => {
btn.addEventListener('click', () => {
document.querySelectorAll('.role-btn').forEach(b => b.classList.remove('active'));
btn.classList.add('active');
const role = btn.dataset.role;
document.querySelectorAll('.contributor-card').forEach(card => {
card.style.display = matches(card, role) ? '' : 'none';
});
hideIfEmpty(mainGrid);
hideIfEmpty(retiredSection);
});
});
</script>
{{ end }}