diff --git a/docs/_data/navigation.yml b/docs/_data/navigation.yml
index b84ddc05..e8bde151 100644
--- a/docs/_data/navigation.yml
+++ b/docs/_data/navigation.yml
@@ -9,6 +9,8 @@
url: "/users-activity"
- title: "Git Versions"
url: "/users-git-versions"
+ - title: "Organization Owners"
+ url: "/org-owners"
- title: "Pull Requests"
url: "/pr-usage"
subnavigation:
diff --git a/docs/assets/js/charts.js b/docs/assets/js/charts.js
index c21b8327..dfd7715e 100644
--- a/docs/assets/js/charts.js
+++ b/docs/assets/js/charts.js
@@ -362,20 +362,28 @@ function createTable(table)
.enter()
.append("td")
.each(function(d, i) {
- var cell = d3.select(this);
+ const cell = d3.select(this);
switch (data.columns[i].toLowerCase()) {
case "user":
case "organization":
case "repository":
case "resource":
case "fork":
- cell = cell
- .append("a")
- .attr("target", "_blank")
- .attr("href", gheUrl() + "/" + d);
- break;
+ case "owners": {
+ const entries = d.split(",");
+ console.log(entries);
+ for (let i = 0; i < entries.length; i++) {
+ if (i > 0)
+ cell.innerHTML += ", ";
+ cell = cell
+ .append("a")
+ .attr("target", "_blank")
+ .attr("href", gheUrl() + "/" + entries[i]);
+ break;
+ }
+ }
}
- cell.text(function(d) { return d; })
+ cell.text(function(d) { return d; });
});
});
}
diff --git a/docs/demo-data/org-owners.tsv b/docs/demo-data/org-owners.tsv
new file mode 100644
index 00000000..8d9480a9
--- /dev/null
+++ b/docs/demo-data/org-owners.tsv
@@ -0,0 +1,10 @@
+organization owners
+Alpha user39, user72, user81, user20
+Bravo user50, user39
+Charlie user80
+Delta user78, user59, user86
+Echo user70
+Foxtrot user24, user87
+Golf user36, user90, user27, user40, user67
+Hotel user67, user90
+India user65
diff --git a/docs/org-owners.html b/docs/org-owners.html
new file mode 100644
index 00000000..1fd3537b
--- /dev/null
+++ b/docs/org-owners.html
@@ -0,0 +1,21 @@
+---
+layout: default
+title: Organization Owners
+permalink: /org-owners
+---
+
+Organization Owners
+
+
+
+
+
+
+
Owners for each GitHub organization.
+
+
+
diff --git a/updater/reports/ReportOrgOwners.py b/updater/reports/ReportOrgOwners.py
new file mode 100644
index 00000000..c5855d50
--- /dev/null
+++ b/updater/reports/ReportOrgOwners.py
@@ -0,0 +1,15 @@
+from .Report import *
+
+# Lists all orgs and their owners without site admins or suspended users
+class ReportOrgOwners(Report):
+ def name(self):
+ return "org-owners"
+
+ # The data is overwritten every day, so skip reading the old data
+ def readData(self):
+ pass
+
+ def updateData(self):
+ self.header, self.data = self.parseData(
+ self.executeScript(self.scriptPath("org-owners.sh"))
+ )
diff --git a/updater/scripts/org-owners.sh b/updater/scripts/org-owners.sh
new file mode 100644
index 00000000..9372eff8
--- /dev/null
+++ b/updater/scripts/org-owners.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+#
+# Get the owners for each org. Exclude site admins and suspended users.
+#
+echo -e "organization\towners"
+
+github-env bin/runner -e production "'
+ User.where(:type => \"Organization\").each do |o|
+ owners = o.admins.where(:disabled => false, :gh_role => nil).join(\",\")
+ puts \"#{o.login}\\t#{owners}\\n\"
+ end
+'"
diff --git a/updater/update-stats.py b/updater/update-stats.py
index 76cc4156..5a7e51d0 100755
--- a/updater/update-stats.py
+++ b/updater/update-stats.py
@@ -14,6 +14,7 @@
from reports.ReportGitRequests import *
from reports.ReportGitVersions import *
from reports.ReportOrgCollaboration import *
+from reports.ReportOrgOwners import *
from reports.ReportPRByOrg import *
from reports.ReportPRByRepo import *
from reports.ReportPRHistory import *
@@ -75,6 +76,7 @@ def main():
ReportGitRequests(configuration, dataDirectory, metaStats).update()
ReportGitVersions(configuration, dataDirectory, metaStats).update()
ReportOrgCollaboration(configuration, dataDirectory, metaStats).update()
+ ReportOrgOwners(configuration, dataDirectory, metaStats).update()
ReportPRByOrg(configuration, dataDirectory, metaStats).update()
ReportPRByRepo(configuration, dataDirectory, metaStats).update()
ReportPRHistory(configuration, dataDirectory, metaStats).update()