Skip to content
Open
Show file tree
Hide file tree
Changes from 2 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
39 changes: 39 additions & 0 deletions data/team.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
Name,Role,Role,Bio,Image,Email,GitHub,Twitter,LinkedIn
Comment thread
davehorsfall marked this conversation as resolved.
Outdated
Dave Horsfall,Team,Project Co-lead,Leads the DIRECT framework and community strategy.,assets/img/team/dave-horsfall.webp,,https://github.com/davehorsfall,,
Aleks Nenadic,Team,Project Co-lead,Leads the DIRECT framework and framework strategy.,assets/img/team/aleksandra-nenadic.webp,,https://github.com/anenadic,,
Adrian D'Alessandro,Team,WebApp Lead,Oversees WebApp architecture and implementation.,assets/img/team/adrian-dallesandro.webp,,https://github.com/AdrianDAlessandro,,
Comment thread
davehorsfall marked this conversation as resolved.
Outdated
Ryan Smith,Contributor,,,,,,,
Andrew Gait,Contributor,,,,,,,
Bryn Ubald,Contributor,,,,,,,
Jason Klebes,Contributor,,,,,,,
Sam Bland,Team,,,,,,,
Barney Dobson,Contributor,,,,,,,
Saranjeet Kaur,Team,,,,,,,
Aman Goel,Team,,,,,,,
Phil Reed,Team,,,,,,,
Toby Hodges,Contributor,,,,,,,
GeoDaoyu,Contributor,,,,,,,
Christopher Cave-Ayland,Contributor,,,,,,,
Sahil Raja,Contributor,,,,,,,
Connor Aird,Contributor,,,,,,,
Emma Hogan,Team,,,,,,,
Matt Craddock,Contributor,,,,,,,
Tamora James,Team,,,,,,,
Becky Osselton,Contributor,,,,,,,
Eli Chadwick,Contributor,,,,,,,
Gabriel Hanganu,Contributor,,,,,,,
Hannah Williams,Contributor,,,,,,,
Matthew Bluteau,Contributor,,,,,,,
Patricia Loto,Contributor,,,,,,,
Camille Santistevan,Contributor,,,,,,,
Ella Kaye,Contributor,,,,,,,
Jonathan Cooper,Team,,,,,,,
Samantha Wittke,Contributor,,,,,,,
Sarah Gibson,Contributor,,,,,,,
Iain Barrass,Contributor,,,,,,,
Lieke de Boer,Contributor,,,,,,,
Martin O'Reilly,Contributor,,,,,,,
Nadine Spychala,Contributor,,,,,,,
Paul K Korir,Contributor,,,,,,,
Sean Marshallsay,Contributor,,,,,,,
Diego Alonso Alvarez,Contributor,,,,,,,
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added main/static/assets/img/team/dave-horsfall.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
77 changes: 77 additions & 0 deletions main/templates/main/pages/team.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
{% extends "main/base.page.html" %}
{% load static %}
{% block title %}
Digital Research Competencies Framework
{% endblock title %}
{% block breadcrumb_items %}
<li class="breadcrumb-item active" aria-current="page">Events</li>
Comment thread
davehorsfall marked this conversation as resolved.
Outdated
{% endblock breadcrumb_items %}
{% block content %}
<section id="about">
<div class="row">
<h2 class="mb-4">Team Members</h2>
Comment thread
davehorsfall marked this conversation as resolved.
Outdated
Comment thread
davehorsfall marked this conversation as resolved.
Outdated
<div class="row mb-5">
{% for member in team_members %}
<div class="col-lg-3 col-md-6 mb-4">
<div class="text-center">
<img src="{{ member.image }}"
alt="{{ member.name }}"
class="img-fluid rounded-circle mb-3"
style="width: 160px;
height: 160px;
object-fit: cover" />
<h5 class="fw-semibold mb-1">{{ member.name }}</h5>
<p class="text-muted mb-2">{{ member.role }}</p>
<p class="small">{{ member.bio }}</p>
<ul class="list-inline mt-3">
{% if member.email %}
<li class="list-inline-item">
<a href="mailto:{{ member.email }}" class="text-decoration-none px-1">
<i class="fa-solid fa-envelope"></i>
</a>
</li>
{% endif %}
{% if member.github %}
<li class="list-inline-item">
<a href="{{ member.github }}"
target="_blank"
class="text-decoration-none px-1">
<i class="fa-brands fa-github"></i>
</a>
Comment thread
davehorsfall marked this conversation as resolved.
</li>
{% endif %}
{% if member.twitter %}
<li class="list-inline-item">
<a href="{{ member.twitter }}"
target="_blank"
class="text-decoration-none px-1">
<i class="fa-brands fa-twitter"></i>
</a>
</li>
{% endif %}
{% if member.linkedin %}
<li class="list-inline-item">
<a href="{{ member.linkedin }}"
target="_blank"
class="text-decoration-none px-1">
<i class="fa-brands fa-linkedin"></i>
Comment on lines +44 to +69
</a>
</li>
{% endif %}
</ul>
</div>
</div>
{% endfor %}
</div>
<h2 class="mb-3">Contributors</h2>
<p class="mb-0">
{% for contributor in contributors %}
{{ contributor }}
{% if not forloop.last %},{% endif %}
Comment thread
davehorsfall marked this conversation as resolved.
Outdated
{% empty %}
No contributors listed.
{% endfor %}
</p>
</div>
</section>
{% endblock content %}
1 change: 1 addition & 0 deletions main/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,5 @@
path("framework-json/", views.FrameworkView.as_view(), name="framework_json"),
path("governance/", views.GovernancePageView.as_view(), name="governance"),
path("licensing/", views.LicensingPageView.as_view(), name="licensing"),
path("team/", views.TeamPageView.as_view(), name="team"),
]
79 changes: 79 additions & 0 deletions main/views/page_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,85 @@ def get_context_data(self, **kwargs: Mapping[str, object]) -> dict[str, object]:
return context


class TeamPageView(TemplateView):
"""View that renders the team page from CSV."""

template_name = "main/pages/team.html"

def get_context_data(self, **kwargs: Mapping[str, Any]) -> dict[str, Any]:
"""Add grouped team and contributor data to the template context."""
context = super().get_context_data(**kwargs)
Comment on lines +152 to +159

csv_path = Path("data/team.csv")
team_members: list[dict[str, Any]] = []
Comment on lines +161 to +162
contributors: list[str] = []

def _safe_get(row: list[str], index: int | None) -> str:
if index is None or index >= len(row):
return ""
return row[index].strip()

def _safe_int(value: str, default: int = 999) -> int:
try:
return int(value)
except (TypeError, ValueError):
return default

if csv_path.exists():
Comment thread
davehorsfall marked this conversation as resolved.
Outdated
with open(csv_path, newline="", encoding="utf-8") as csvfile:
reader = csv.reader(csvfile)
Comment thread
davehorsfall marked this conversation as resolved.
Outdated
header = next(reader, None)

if header:
header_map = {
name.strip().lower(): idx for idx, name in enumerate(header)
}
role_indexes = [
idx
for idx, name in enumerate(header)
if name.strip().lower() == "role"
]

group_idx = role_indexes[0] if role_indexes else None
member_role_idx = (
role_indexes[1]
if len(role_indexes) > 1
else (role_indexes[0] if role_indexes else None)
)

for row in reader:
if not row:
continue

image_path = _safe_get(row, header_map.get("image"))
member = {
"name": _safe_get(row, header_map.get("name")),
"role": _safe_get(row, member_role_idx),
"bio": _safe_get(row, header_map.get("bio")),
"image": static(image_path) if image_path else None,
"email": _safe_get(row, header_map.get("email")),
"github": _safe_get(row, header_map.get("github")),
"twitter": _safe_get(row, header_map.get("twitter")),
"linkedin": _safe_get(row, header_map.get("linkedin")),
"order": _safe_int(_safe_get(row, header_map.get("order"))),
}

group = _safe_get(row, group_idx).lower()
if group in {"member", "contributor"}:
Comment thread
davehorsfall marked this conversation as resolved.
Outdated
if member["name"]:
contributors.append(cast(str, member["name"]))
else:
team_members.append(member)

team_members.sort(key=lambda m: cast(str, m["name"]).casefold())
contributors.sort(key=str.casefold)
Comment thread
davehorsfall marked this conversation as resolved.
Outdated

context["team_members"] = team_members
context["contributors"] = contributors

return context


class RolesPageView(TemplateView):
"""View that renders the role profiles page."""

Expand Down
Loading