Skip to content

Commit 28c6d8c

Browse files
aboydnwcursoragent
andauthored
Fix scroll (#44)
@gadomski all these weird issues were because testing locally used `index.html` but production pointed to `python/templates/index.html.jinja` and I wasn't syncing that properly or able to really test it. So this PR looks big because it's collapsing that to a single source of truth, index.html. --------- Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent c5095e8 commit 28c6d8c

File tree

16 files changed

+198
-728
lines changed

16 files changed

+198
-728
lines changed

assets/data/config.json

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
{
2+
"title": "The Development Seed Contributor Network",
3+
"author": "Pete Gadomski",
4+
"description": "An interactive visualization of contributors to Development Seed code and their connections to other repositories",
5+
"central_repository": "developmentseed/DevSeed Team",
6+
"contributor_padding": 20,
7+
"contributors": {
8+
"AMSCamacho": "Angela Camacho",
9+
"AliceR": "Alice Rühl",
10+
"LanesGood": "Lane Goodman",
11+
"abarciauskas-bgse": "Aimee Barciauskas",
12+
"aboydnw": "Anthony Boyd",
13+
"aliziel": "Ali Z",
14+
"alukach": "Anthony Lukach",
15+
"anayeaye": "Alexandra Kirk",
16+
"batpad": "Sanjay Bhangar",
17+
"beatrizbsperes": "Beatriz Peres",
18+
"benbovy": "Benoît Bovy",
19+
"bitner": "David Bitner",
20+
"botanical": "Jennifer Tran",
21+
"brianna-corremonte": "Brianna Corremonte",
22+
"camillecroft": "Camille Croft",
23+
"ceholden": "Chris Holden",
24+
"chuckwondo": "Chuck Daniels",
25+
"ciaransweet": "Ciaran Sweet",
26+
"danielfdsilva": "Daniel da Silva",
27+
"dannybauman": "Danny Bauman",
28+
"dzole0311": "Gjore Milevski",
29+
"emmalu": "Emma Paz",
30+
"emmanuelmathot": "Emmanuel Mathot",
31+
"faustoperez": "Fausto Pérez",
32+
"gadomski": "Pete Gadomski",
33+
"geohacker": "Sajjad Anwar",
34+
"hanbyul-here": "Hanbyul Jo",
35+
"hrodmn": "Henry Rodman",
36+
"ianschuler": "Ian Schuler",
37+
"indraneel": "Indraneel Purohit",
38+
"ividito": "Isayah Vidito",
39+
"j08lue": "Jonas Sølvsteen",
40+
"jjfrench": "Jamison French",
41+
"kamicut": "Marc Farra",
42+
"kcarini": "Kiri Carini",
43+
"kevinbullock": "Kevin Bullock",
44+
"kimmurph": "Kim Murphy",
45+
"kylebarron": "Kyle Barron",
46+
"leothomas": "Leo Thomas",
47+
"lillythomas": "Lilly Thomas",
48+
"maxrjones": "Max Jones",
49+
"martham93": "Martha Morrissey",
50+
"olafveerman": "Olaf Veerman",
51+
"omniajoe": "Omnia Joehar",
52+
"pantierra": "xıʃǝɟ",
53+
"ricardoduplos": "Ricardo Duplos",
54+
"sandrahoang686": "Sandra Hoang",
55+
"sharkinsspatial": "Sean Harkins",
56+
"sharonwanlu": "SharonLu",
57+
"smohiudd": "Saadiq Mohiuddin",
58+
"srmsoumya": "Soumya Ranjan Mohanty",
59+
"sunu": "Tarashish Mishra",
60+
"vgeorge": "Vitor George",
61+
"vincentsarago": "Vincent Sarago",
62+
"weiji14": "Wei Ji",
63+
"wildintellect": "Alex I. Mandel",
64+
"willemarcel": "Wille Marcel",
65+
"wrynearson": "Will Rynearson",
66+
"yellowcap": "Daniel Wiesmann",
67+
"zacdezgeo": "Zac Deziel"
68+
}
69+
}

index.html

Lines changed: 75 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,28 @@
22
<html>
33
<head>
44
<meta charset="utf-8">
5-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
5+
<meta name="viewport" content="width=device-width, shrink-to-fit=0, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
6+
67
<title>Contributor Network</title>
8+
9+
<meta name="author" content="Development Seed">
10+
<meta name="description" content="An interactive visualization of contributors and their connections to repositories">
11+
<meta name="theme-color" content="#cf3f02">
12+
<meta property="og:title" content="The Development Seed Contributor Network">
13+
<meta property="og:url" content="https://developmentseed.org/contributor-network/">
14+
<meta property="og:type" content="article">
15+
<meta property="og:locale" content="en_US">
16+
<meta property="og:image" content="https://developmentseed.org/contributor-network/site-image.jpg">
17+
<meta property="og:image:type" content="image/jpeg">
18+
<meta property="og:image:width" content="1200">
19+
<meta property="og:image:height" content="800">
20+
721
<link rel="shortcut icon" type="image/png" href="assets/img/favicon.png" />
822
<link rel="stylesheet" href="assets/css/style.css">
23+
<link rel="preconnect" href="https://fonts.googleapis.com">
24+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
25+
<link href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,400;0,700;1,400;1,700&family=Roboto+Condensed:wght@400;700&family=Fira+Code:wght@300..700&display=swap" rel="stylesheet">
26+
927
<script src="assets/lib/d3.v7.js"></script>
1028
<script src="assets/lib/d3-delaunay.js"></script>
1129
<script src="assets/lib/d3-bboxCollide.min.js"></script>
@@ -15,11 +33,11 @@
1533
<div id="chart-introduction">
1634
<div id="chart-title">
1735
<h1>The Contributor Network of</h1>
18-
<h1><span id="title-repo-name" class="central-repo">Development Seed</span></h1>
36+
<h1><span id="title-repo-name" class="central-repo">...</span></h1>
1937
<p id="last-commit-date"></p>
2038
</div>
2139
<div id="chart-intro-text">
22-
<p>Explore the network of contributors and repositories.</p>
40+
<p id="chart-description">Explore the network of contributors and repositories.</p>
2341
<p>This visualization is based off of the excellent <a href="https://nbremer.github.io/ORCA/top-contributor-network/">Top Contributor Network</a> from <a href="https://github.com/nbremer">Nadieh Bremer</a>, and is licensed the same (MPL).</p>
2442
</div>
2543
</div>
@@ -51,84 +69,74 @@ <h1><span id="title-repo-name" class="central-repo">Development Seed</span></h1>
5169
</div>
5270

5371
<script type="module">
54-
// Load the main visualization module and handle all initialization
5572
import { createContributorNetworkVisual } from './js/chart.js';
5673

57-
const REPOSITORY = "NASA-IMPACT/veda-config";
58-
const contributor_padding = 20;
74+
// ─── Load configuration ───────────────────────────────────
75+
// In production, config.json is generated by the build command from config.toml.
76+
// For local development, place a config.json in assets/data/ with at minimum:
77+
// { "central_repository": "owner/repo", "contributor_padding": 20, "contributors": {} }
78+
const configResponse = await fetch('assets/data/config.json');
79+
if (!configResponse.ok) {
80+
document.getElementById("chart-container").innerHTML =
81+
'<p style="color: red; padding: 20px;">Error: Could not load config.json. Run the build command or create assets/data/config.json for local development.</p>';
82+
throw new Error('Failed to load config.json');
83+
}
84+
const config = await configResponse.json();
5985

60-
// Master contributor list - simplified for testing
61-
const mainContributors = new Set([
62-
"Angela Camacho",
63-
"Alice Rühl",
64-
"Lane Goodman",
65-
"Aimee Barciauskas",
66-
"Anthony Boyd"
67-
]);
86+
const REPOSITORY = config.central_repository;
87+
const contributor_padding = config.contributor_padding || 20;
6888

69-
// For compatibility with isValidContributor function
70-
const masterContributors = {};
89+
// Build contributor lookup maps from config
90+
const masterContributors = config.contributors || {};
7191
const displayNameToUsername = {};
72-
mainContributors.forEach(name => {
73-
masterContributors[name] = true;
74-
displayNameToUsername[name] = name;
92+
Object.entries(masterContributors).forEach(([username, displayName]) => {
93+
displayNameToUsername[displayName] = username;
7594
});
7695

77-
// Load data
78-
const promises = [
79-
d3.csv('assets/data/top_contributors.csv'),
80-
d3.csv('assets/data/repositories.csv'),
81-
d3.csv('assets/data/links.csv')
82-
];
96+
// ─── Populate page from config ────────────────────────────
97+
const repoDisplayName = REPOSITORY.includes('/') ? REPOSITORY.split('/').pop() : REPOSITORY;
98+
document.getElementById("title-repo-name").textContent = repoDisplayName;
99+
if (config.title) document.title = config.title;
100+
if (config.description) document.getElementById("chart-description").textContent = config.description;
83101

84-
let container = document.getElementById("chart-container");
85-
let wrapper = document.getElementById("chart-wrapper");
86-
let contributorNetworkVisual;
102+
// ─── Set up sizing ────────────────────────────────────────
103+
const container = document.getElementById("chart-container");
104+
const wrapper = document.getElementById("chart-wrapper");
87105

88-
// Get chart dimensions based on available container space
89106
function getChartDimensions() {
90107
let wrapperRect = wrapper.getBoundingClientRect();
91108
let availableWidth = wrapperRect.width - 40;
92-
93109
if (availableWidth < 400) {
94110
availableWidth = Math.min(window.innerWidth - 40, 1400 - 40);
95111
}
96-
97112
return Math.max(availableWidth, 600);
98113
}
99114

100-
// Initialize visualization
101-
function initVisualization() {
102-
let size = getChartDimensions();
103-
container.style.height = size + 'px';
104-
105-
contributorNetworkVisual = createContributorNetworkVisual(
106-
container,
107-
REPOSITORY,
108-
contributor_padding,
109-
masterContributors,
110-
displayNameToUsername
111-
)
112-
.width(size)
113-
.height(size)
114-
.repository(REPOSITORY);
115-
116-
return size;
117-
}
118-
119-
let size = initVisualization();
115+
// ─── Initialize visualization ─────────────────────────────
116+
let size = getChartDimensions();
117+
container.style.height = size + 'px';
118+
119+
const contributorNetworkVisual = createContributorNetworkVisual(
120+
container,
121+
REPOSITORY,
122+
contributor_padding,
123+
masterContributors,
124+
displayNameToUsername
125+
)
126+
.width(size)
127+
.height(size)
128+
.repository(REPOSITORY);
129+
130+
// ─── Load CSV data and render ─────────────────────────────
131+
const promises = [
132+
d3.csv('assets/data/top_contributors.csv'),
133+
d3.csv('assets/data/repositories.csv'),
134+
d3.csv('assets/data/links.csv')
135+
];
120136

121137
document.fonts.ready.then(() => {
122138
Promise.all(promises).then(values => {
123-
let formatDigit = d3.format(",.2r");
124-
125-
// Deep copy data
126-
let data_raw = [];
127-
data_raw.push(JSON.parse(JSON.stringify(values[0])));
128-
data_raw.push(JSON.parse(JSON.stringify(values[1])));
129-
data_raw.push(JSON.parse(JSON.stringify(values[2])));
130-
131-
// Generate organization options
139+
// Generate organization filter options
132140
const uniqueOrgs = new Set();
133141
values[1].forEach(repo => {
134142
const owner = repo.repo.substring(0, repo.repo.indexOf("/"));
@@ -145,7 +153,7 @@ <h1><span id="title-repo-name" class="central-repo">Development Seed</span></h1>
145153
});
146154

147155
let currentSelectedOrg = null;
148-
orgSelect.addEventListener("change", function() {
156+
orgSelect.addEventListener("change", function () {
149157
const selectedOrg = this.value;
150158
if (selectedOrg === "") {
151159
if (currentSelectedOrg) {
@@ -170,14 +178,12 @@ <h1><span id="title-repo-name" class="central-repo">Development Seed</span></h1>
170178
statsElement.textContent = `Filtered to: ${currentSelectedOrg}`;
171179
}
172180
}
173-
174181
updateFilterStats();
175182

176183
// Render the visualization
177184
contributorNetworkVisual(values);
178185

179-
// Get dates
180-
let central_repo = values[1].find(d => d.repo === REPOSITORY);
186+
// Display most recent commit date
181187
let formatDateLong = d3.utcFormat("%B %-e, %Y");
182188
let links_to_central = values[2].filter(d => {
183189
if (typeof d.target === 'object' && d.target && d.target.data) {
@@ -187,17 +193,18 @@ <h1><span id="title-repo-name" class="central-repo">Development Seed</span></h1>
187193
});
188194
let most_recent_commit = d3.max(links_to_central, d => +d.commit_sec_max);
189195
if (most_recent_commit) {
190-
// Convert Unix timestamp (seconds) to Date object (milliseconds)
191196
let commitDate = new Date(most_recent_commit * 1000);
192-
document.getElementById("last-commit-date").innerHTML = `Including commits up to ${formatDateLong(commitDate)}`;
197+
document.getElementById("last-commit-date").innerHTML =
198+
`Including commits up to ${formatDateLong(commitDate)}`;
193199
}
194200
}).catch(err => {
195201
console.error('Error loading data:', err);
196-
document.getElementById("chart-container").innerHTML = '<p style="color: red; padding: 20px;">Error loading data files. Make sure CSV files exist.</p>';
202+
document.getElementById("chart-container").innerHTML =
203+
'<p style="color: red; padding: 20px;">Error loading data files. Make sure CSV files exist in assets/data/.</p>';
197204
});
198205
});
199206

200-
// Handle resize
207+
// ─── Handle resize ────────────────────────────────────────
201208
let resizeTimer = null;
202209
window.addEventListener("resize", function () {
203210
clearTimeout(resizeTimer);

0 commit comments

Comments
 (0)