diff --git a/_data/eoc_dashboard.yml b/_data/eoc_dashboard.yml new file mode 100644 index 0000000..4817a00 --- /dev/null +++ b/_data/eoc_dashboard.yml @@ -0,0 +1,78 @@ +# Equal Opportunity Dashboard data. +# +# The `meta`, `members` and `mc` keys below are AUTO-GENERATED from +# CA24136-WG-members.csv by scripts/extract-eoc-stats.rb — do not edit +# them by hand; re-run the script to refresh. Aggregate counts only; +# no personal data is stored here. + +meta: + generated: "2026-06-29" + source: "CA24136-WG-members.csv" + +members: + title: "Action Members" + subtitle: "Composition of the Action" + headline: "191" + headline_label: "members across 38 countries" + stats: + - label: "Women" + value: "24.6%" + fraction: [47, 191] + - label: "ITC" + value: "54.5%" + fraction: [104, 191] + - label: "Young Researchers" + value: "55.0%" + fraction: [105, 191] + note: "Men: 142 (74.3%) · Other / prefer not to say: 2 (1.0%)" + +mc: + title: "Management Committee" + subtitle: "Governance representation" + headline: "56" + headline_label: "MC members across 33 countries" + stats: + - label: "Women" + value: "30.4%" + fraction: [17, 56] + - label: "ITC" + value: "64.3%" + fraction: [36, 56] + - label: "Young Researchers" + value: "28.6%" + fraction: [16, 56] + note: "Men: 39 (69.6%)" + +# === MANUAL SECTION (edited by hand — preserved when this script re-runs) === + +# Each entry below renders as its own summary box on the dashboard. +# Add as many entries as you like; provide `fraction: [count, total]` on a stat +# to draw a bar. These figures are gathered by hand (not available in the CSV). + +conference: + - title: "Inaugural Conference: NextGen Synergy" + subtitle: "Inclusiveness in scientific visibility" + headline: "90+" + headline_label: "participants across 21 countries" + stats: + - label: "ITC" + value: "17/21" + fraction: [17, 21] + - label: "Women keynote speakers" + value: "1/8" + fraction: [1, 8] + note: "Hosted in Prague · local chair: Tatiana Valentine Guy · ~50% women as session chairs" + +stsm: + - title: "STSM Participation" + subtitle: "Mobility and career development" + headline: "5" + headline_label: "STSM applications (1 call)" + stats: + - label: "ITC involved" + value: "4/6" + fraction: [4, 6] + - label: "Women applicants" + value: "2/5" + fraction: [2, 5] + note: "2 ITC ↔ ITC missions" diff --git a/_includes/desktop-menu.html b/_includes/desktop-menu.html index 4e3cae3..288c00b 100644 --- a/_includes/desktop-menu.html +++ b/_includes/desktop-menu.html @@ -27,6 +27,7 @@ Action Leaders Core Group Management Committee + Equal Opportunity @@ -68,12 +69,13 @@ - diff --git a/_includes/eoc-box.html b/_includes/eoc-box.html new file mode 100644 index 0000000..da01ed9 --- /dev/null +++ b/_includes/eoc-box.html @@ -0,0 +1,37 @@ +{% comment %} + Renders one Equal Opportunity summary box. + Parameter: box - a hash with title, subtitle, headline, headline_label, + stats (list of {label, value, fraction:[count,total]}), note. +{% endcomment %} +{% assign box = include.box %} +
+

{{ box.title }}

+ {% if box.subtitle %}

{{ box.subtitle }}

{% endif %} + {% if box.headline %} +

+ {{ box.headline }} + {% if box.headline_label %}{{ box.headline_label }}{% endif %} +

+ {% endif %} + {% if box.stats %} + + {% endif %} + {% if box.note %}

{{ box.note }}

{% endif %} +
diff --git a/_sass/eoc.scss b/_sass/eoc.scss new file mode 100644 index 0000000..771b07b --- /dev/null +++ b/_sass/eoc.scss @@ -0,0 +1,85 @@ +@use "variables" as *; + +.eoc-box { + text-align: left; + + &__subtitle { + margin: -0.25rem 0 0.75rem; + color: $altBlue; + font-size: 0.9rem; + } + + &__headline { + margin: 0 0 1rem; + } + + &__number { + font-size: 2.4rem; + font-weight: bold; + color: $mainBlue; + line-height: 1; + } + + &__headline-label { + color: $mainBlue; + font-size: 0.9rem; + margin-left: 0.4rem; + } + + &__stats { + list-style: none; + margin: 0; + padding: 0; + } + + &__stat { + margin-bottom: 0.75rem; + } + + &__stat-head { + display: flex; + justify-content: space-between; + align-items: baseline; + margin-bottom: 0.2rem; + } + + &__stat-label { + color: $mainBlue; + font-size: 0.9rem; + } + + &__stat-value { + color: $altBlue; + font-weight: bold; + font-size: 0.9rem; + } + + &__bar { + display: block; + width: 100%; + height: 0.5rem; + background: $altGray; + border-radius: 999px; + overflow: hidden; + } + + &__bar-fill { + display: block; + height: 100%; + background: $mainGreen; + border-radius: 999px; + } + + &__note { + margin: 1rem 0 0; + color: $mainGray; + font-size: 0.8rem; + } +} + +.eoc-source { + text-align: center; + color: $mainGray; + font-size: 0.85rem; + margin-top: 2rem; +} diff --git a/assets/css/main.scss b/assets/css/main.scss index abb96f7..6b51964 100644 --- a/assets/css/main.scss +++ b/assets/css/main.scss @@ -11,4 +11,5 @@ @use "news" as *; @use "responsive" as *; @use "dissemination" as *; -@use "jobs" as *; \ No newline at end of file +@use "jobs" as *; +@use "eoc" as *; \ No newline at end of file diff --git a/extract-eoc-stats.sh b/extract-eoc-stats.sh new file mode 100755 index 0000000..f8427b1 --- /dev/null +++ b/extract-eoc-stats.sh @@ -0,0 +1,15 @@ +#!/bin/bash +# Extracts aggregate Equal Opportunity statistics from the WG members CSV into +# _data/eoc_dashboard.yml, via the Docker container (so no local Ruby is needed). +# +# Usage: ./extract-eoc-stats.sh [path/to/members.csv] + +CSV="${1:-CA24136-WG-members.csv}" + +if [ ! -f "$CSV" ]; then + echo "Error: CSV file '$CSV' not found" + echo "Usage: ./extract-eoc-stats.sh [path/to/members.csv]" + exit 1 +fi + +docker compose run --rm intercoml-homepage ruby scripts/extract-eoc-stats.rb "$CSV" diff --git a/pages/equal-opportunity.html b/pages/equal-opportunity.html new file mode 100644 index 0000000..1ec51e9 --- /dev/null +++ b/pages/equal-opportunity.html @@ -0,0 +1,36 @@ +--- +title: Equal Opportunity +permalink: /:basename/ +--- + +{% assign d = site.data.eoc_dashboard %} + +
+

Equal Opportunity Dashboard

+ +

+ {{ site.actionAbbreviation }} is committed to inclusiveness and balanced participation across all + Action activities. This dashboard summarises the involvement of women, Young Researchers (YR) and + researchers from Inclusiveness Target Countries (ITC) in the Action. +

+ +

Composition of the Action

+
+ {% if d.members %}{% include eoc-box.html box=d.members %}{% endif %} + {% if d.mc %}{% include eoc-box.html box=d.mc %}{% endif %} +
+ + {% if d.conference or d.stsm %} +

Activities

+
+ {% for c in d.conference %}{% include eoc-box.html box=c %}{% endfor %} + {% for s in d.stsm %}{% include eoc-box.html box=s %}{% endfor %} +
+ {% endif %} + + {% if d.meta.generated %} +

+ Figures generated from membership records on {{ d.meta.generated }}. +

+ {% endif %} +
diff --git a/scripts/extract-eoc-stats.rb b/scripts/extract-eoc-stats.rb new file mode 100755 index 0000000..30ad4fd --- /dev/null +++ b/scripts/extract-eoc-stats.rb @@ -0,0 +1,151 @@ +#!/usr/bin/env ruby +# +# Extracts aggregate Equal Opportunity statistics from the WG members CSV and +# writes them to _data/eoc_dashboard.yml. +# +# Usage: ruby scripts/extract-eoc-stats.rb [path/to/members.csv] +# (defaults to CA24136-WG-members.csv in the project root) +# +# Only the `meta`, `members` and `mc` keys at the top of the output file are +# owned by this script. Everything below the MANUAL SECTION marker (the +# hand-maintained conference/STSM entries) is preserved verbatim on re-run. +# +# Privacy: only aggregate counts/percentages are written — no names, emails or +# any per-person data leave the CSV. The CSV itself is not committed (.gitignore). + +require 'csv' +require 'date' + +CSV_PATH = ARGV[0] || 'CA24136-WG-members.csv' +OUT_PATH = '_data/eoc_dashboard.yml' +MARKER = '# === MANUAL SECTION (edited by hand — preserved when this script re-runs) ===' + +unless File.exist?(CSV_PATH) + STDERR.puts "Error: CSV file '#{CSV_PATH}' not found" + STDERR.puts "Usage: ruby scripts/extract-eoc-stats.rb [path/to/members.csv]" + exit 1 +end + +def parse_country(country_str) + # "Serbia (RS)" -> "Serbia" + country_str.to_s.sub(/\s*\([^)]*\)\s*$/, '').strip +end + +def compute_box(rows, title, subtitle, members_word) + n = rows.size + women = rows.count { |r| r['Gender'].to_s.strip == 'Female' } + men = rows.count { |r| r['Gender'].to_s.strip == 'Male' } + other = n - women - men + itc = rows.count { |r| r['ITC'].to_s.strip == 'y' } + yr = rows.count { |r| r['Young Researcher'].to_s.strip == 'y' } + countries = rows.map { |r| parse_country(r['Country']) }.reject(&:empty?).uniq.size + + pct = ->(x) { n.zero? ? 0.0 : (100.0 * x / n).round(1) } + + note = "Men: #{men} (#{pct.call(men)}%)" + note += " · Other / prefer not to say: #{other} (#{pct.call(other)}%)" if other.positive? + + { + title: title, + subtitle: subtitle, + headline: n.to_s, + headline_label: "#{members_word} across #{countries} countries", + stats: [ + ['Women', "#{pct.call(women)}%", women, n], + ['ITC', "#{pct.call(itc)}%", itc, n], + ['Young Researchers', "#{pct.call(yr)}%", yr, n], + ], + note: note, + } +end + +def box_to_yaml(key, box) + lines = ["#{key}:"] + lines << %Q( title: "#{box[:title]}") + lines << %Q( subtitle: "#{box[:subtitle]}") + lines << %Q( headline: "#{box[:headline]}") + lines << %Q( headline_label: "#{box[:headline_label]}") + lines << ' stats:' + box[:stats].each do |label, value, num, den| + lines << %Q( - label: "#{label}") + lines << %Q( value: "#{value}") + lines << " fraction: [#{num}, #{den}]" + end + lines << %Q( note: "#{box[:note]}") + lines.join("\n") +end + +SEED_MANUAL = <<~'YAML' + + # Each entry below renders as its own summary box on the dashboard. + # Add as many entries as you like; provide `fraction: [count, total]` on a stat + # to draw a bar. These figures are gathered by hand (not available in the CSV). + + conference: + - title: "Inaugural Conference: NextGen Synergy" + subtitle: "Inclusiveness in scientific visibility" + headline: "90+" + headline_label: "participants across 21 countries" + stats: + - label: "ITC countries" + value: "17/21" + fraction: [17, 21] + - label: "Women keynote speakers" + value: "1/8" + fraction: [1, 8] + note: "Hosted in Prague · local chair: Tatiana Valentine Guy · ~5 women session chairs" + + stsm: + - title: "STSM Participation" + subtitle: "Mobility and career development" + headline: "5" + headline_label: "STSM applications (1 call)" + stats: + - label: "ITC countries involved" + value: "4/6" + fraction: [4, 6] + - label: "Women applicants" + value: "2/5" + fraction: [2, 5] + note: "2 ITC ↔ ITC missions · broader participation to encourage" +YAML + +rows = CSV.read(CSV_PATH, headers: true, col_sep: ';', encoding: 'bom|utf-8') + +members = rows.select { |r| r['Application Status'].to_s.strip.downcase == 'approved' } +mc = rows.select { |r| r['MC Membership Status'].to_s.strip == 'Member' } + +members_box = compute_box(members, 'Action Members', 'Composition of the Action', 'members') +mc_box = compute_box(mc, 'Management Committee', 'Governance representation', 'MC members') + +auto = [] +auto << '# Equal Opportunity Dashboard data.' +auto << '#' +auto << '# The `meta`, `members` and `mc` keys below are AUTO-GENERATED from' +auto << '# CA24136-WG-members.csv by scripts/extract-eoc-stats.rb — do not edit' +auto << '# them by hand; re-run the script to refresh. Aggregate counts only;' +auto << '# no personal data is stored here.' +auto << '' +auto << 'meta:' +auto << %Q( generated: "#{Date.today.iso8601}") +auto << ' source: "CA24136-WG-members.csv"' +auto << '' +auto << box_to_yaml('members', members_box) +auto << '' +auto << box_to_yaml('mc', mc_box) +auto << '' +auto_text = auto.join("\n") + "\n" + +# Preserve the manual section if the file already exists. +manual = + if File.exist?(OUT_PATH) && File.read(OUT_PATH).include?(MARKER) + File.read(OUT_PATH).split(MARKER, 2)[1] + else + "\n" + SEED_MANUAL + end + +File.write(OUT_PATH, auto_text + MARKER + manual) + +puts "Wrote #{OUT_PATH}" +puts " Action Members: #{members_box[:headline]} (#{members_box[:headline_label]})" +puts " Management Committee: #{mc_box[:headline]} (#{mc_box[:headline_label]})"