diff --git a/docs/components/people.md b/docs/components/people.md index d844f5b3..2d4d6a5a 100644 --- a/docs/components/people.md +++ b/docs/components/people.md @@ -39,7 +39,7 @@ The `groups` array determines which page sections a person appears in: |-------------|----------------------|----------------| | `steeringCommittee` | Steering Committee / Board | Subscriptions with committee roles linked to "Steering Committee" PWCI | | `administrativeTeam` | Our Team (staff) | GSF Team DB, Status = "Active" | -| `chairsAndLeads` | Chairs & Project Leads | Subscriptions with roles: WG Chair, Project Lead/Co-Lead, Committee Chair/Vice-Chair | +| `chairsAndLeads` | Chairs & Project Leads | Subscriptions with roles: WG Chair, Project Lead/Co-Lead, Chair/Vice Chair, Committee Chair/Vice-Chair | | `organisationalLeads` | Organisation Leads | Subscriptions with Role = "Organization Lead" | A person can belong to multiple groups and appears in each corresponding section. diff --git a/docs/notion.md b/docs/notion.md index c5d26c0a..13029c46 100644 --- a/docs/notion.md +++ b/docs/notion.md @@ -95,6 +95,26 @@ Person data for subscription-based people (name, title, LinkedIn, member org) is - `Subscription Status` (select) — must be "Active" - Roll-up fields: `First Name`, `Surname`, `Title`, `LinkedIn`, `Member`, `Volunteer Status` +#### Distinguishing leadership on a standards page (e.g. Chair vs Vice Chair) + +`fetchChairsAndLeads()` in `scripts/fetch-notion-data.cjs` maps `Role for Subscription` values to the `roleLabel` shown next to a project lead's name in `projects.json` (consumed by `TeamGrid` on standards pages): + +| Role for Subscription | roleLabel shown on site | +|---|---| +| `Working Group Chair` | Chair | +| `Project Lead` | Lead | +| `Project Co-Lead` | Co-Lead | +| `Chair` | Project Lead (Chair) | +| `Vice Chair` | Vice Chair | +| `Project Chair` | Project Lead (Chair) | +| `Project Vice Chair` | Vice Chair | +| `Committee Chair` | Chair | +| `Committee Vice-Chair` | Vice-Chair | + +When a project has multiple "Project Lead" subscriptions and needs to distinguish a Chair from a Vice Chair (as opposed to two equal leads), set one person's `Role for Subscription` to `Project Chair` and the other's to `Project Vice Chair` rather than leaving both as `Project Lead`. + +**Careful when picking a value in Notion's select field:** typing a value that isn't an exact match for an existing option silently creates a *new* option instead of reusing one — this is how `Chair`/`Vice Chair`/`Project Chair`/`Project Vice Chair` all ended up coexisting as separate, easily-confused options. Always pick from the existing dropdown list rather than retyping the text. `Project Chair` and `Project Vice Chair` are the canonical values to use going forward; `Chair` and `Vice Chair` are kept mapped for compatibility but are unused stray options that could be deleted from the Notion schema. + ### Volunteers DB - `First Name`, `Last Name` (rich text) diff --git a/docs/pages/standards.md b/docs/pages/standards.md index 8f5ae7a6..0772b046 100644 --- a/docs/pages/standards.md +++ b/docs/pages/standards.md @@ -15,7 +15,7 @@ Each standards page is a long-form landing page for a specific GSF standard/proj - **Project metadata** — imported from `src/data/projects.json`. Each page looks up its project by slug (e.g. `projects.find(p => p.slug === "sci")`) - **Lifecycle stage** — displayed as a badge in the hero, read from `projects.json` - **Parent working group** — resolved from `projects.json` to show "A [WG Name] Project" -- **Project leads** — the `leads` array from `projects.json` provides `fullName` and `roleLabel` +- **Project leads** — the `leads` array from `projects.json` provides `fullName` and `roleLabel`. Notion's query order isn't guaranteed, so pages that need a deterministic display order (e.g. Chair before Vice Chair) should sort the array by `roleLabel` in the page itself rather than relying on array order — see the `leadRoleRank()` helper in `src/pages/standards/swi/index.astro` See [Notion doc](../notion.md) for how `projects.json` is populated from the PWCIs database. diff --git a/scripts/fetch-notion-data.cjs b/scripts/fetch-notion-data.cjs index 31d03a0d..25ba365d 100644 --- a/scripts/fetch-notion-data.cjs +++ b/scripts/fetch-notion-data.cjs @@ -408,6 +408,10 @@ async function fetchChairsAndLeads(memberById) { "Working Group Chair", "Project Lead", "Project Co-Lead", + "Chair", + "Vice Chair", + "Project Chair", + "Project Vice Chair", "Committee Chair", "Committee Vice-Chair", "Committee Member", @@ -447,6 +451,10 @@ async function fetchChairsAndLeads(memberById) { "Working Group Chair": "Chair", "Project Lead": "Lead", "Project Co-Lead": "Co-Lead", + "Chair": "Project Lead (Chair)", + "Vice Chair": "Vice Chair", + "Project Chair": "Project Lead (Chair)", + "Project Vice Chair": "Vice Chair", "Committee Chair": "Chair", "Committee Vice-Chair": "Vice-Chair", }; diff --git a/src/pages/standards/index.astro b/src/pages/standards/index.astro index afb7000e..ca5e0cec 100644 --- a/src/pages/standards/index.astro +++ b/src/pages/standards/index.astro @@ -38,7 +38,7 @@ const standardDefs = [ { slug: "silo" }, { slug: "wdpc" }, { slug: "open19" }, - { slug: "see", urlSlug: "sei" }, + { slug: "sei" }, { slug: "swe" }, ]; const standardProjects = standardDefs diff --git a/src/pages/standards/sei/index.astro b/src/pages/standards/sei/index.astro index 56ccf42e..5c49c834 100644 --- a/src/pages/standards/sei/index.astro +++ b/src/pages/standards/sei/index.astro @@ -18,11 +18,11 @@ import ArticleCarousel from "@/components/article-carousel.astro"; import projects from "@/data/projects.json"; import { getCollection } from "astro:content"; import { articleUrl } from "@/lib/utils"; -const seeProject = projects.find(p => p.slug === "see"); -const parentWg = projects.find(p => p.name === seeProject?.parent); +const seiProject = projects.find(p => p.slug === "sei"); +const parentWg = projects.find(p => p.name === seiProject?.parent); const carouselArticles = (await getCollection("articles", (a) => a.data.published !== false)) - .filter(a => (a.data.tags || []).map((t: string) => t.toLowerCase()).includes("see")) + .filter(a => (a.data.tags || []).map((t: string) => t.toLowerCase()).includes("sei")) .sort((a, b) => new Date(b.data.date).getTime() - new Date(a.data.date).getTime()) .map(a => ({ title: a.data.title, @@ -56,7 +56,7 @@ const carouselArticles = (await getCollection("articles", (a) => a.data.publishe a.data.publishe ({ + members={(seiProject?.leads ?? []).map(lead => ({ fullName: lead.fullName, role: lead.roleLabel, }))} diff --git a/src/pages/standards/swi/index.astro b/src/pages/standards/swi/index.astro index d7b400df..5c7fffe4 100644 --- a/src/pages/standards/swi/index.astro +++ b/src/pages/standards/swi/index.astro @@ -21,6 +21,13 @@ import { articleUrl } from "@/lib/utils"; const sweProject = projects.find(p => p.slug === "swe"); const parentWg = projects.find(p => p.name === sweProject?.parent); +// Chair before Vice Chair before other lead roles, regardless of Notion query order +function leadRoleRank(roleLabel: string): number { + if (/chair/i.test(roleLabel) && !/vice/i.test(roleLabel)) return 0; + if (/vice.?chair/i.test(roleLabel)) return 1; + return 2; +} + const carouselArticles = (await getCollection("articles", (a) => a.data.published !== false)) .filter(a => (a.data.tags || []).map((t: string) => t.toLowerCase()).includes("swe")) .sort((a, b) => new Date(b.data.date).getTime() - new Date(a.data.date).getTime()) @@ -184,10 +191,12 @@ const carouselArticles = (await getCollection("articles", (a) => a.data.publishe body={parentWg ? `Part of the ${parentWg.name}` : ""} columns={sweProject.leads.length === 2 ? 2 : 3} highlighted={[]} - members={sweProject.leads.map(lead => ({ - fullName: lead.fullName, - role: lead.roleLabel, - }))} + members={[...sweProject.leads] + .sort((a, b) => leadRoleRank(a.roleLabel) - leadRoleRank(b.roleLabel)) + .map(lead => ({ + fullName: lead.fullName, + role: lead.roleLabel, + }))} bgClass="bg-white" /> )}