diff --git a/dashboard.njk b/dashboard.njk new file mode 100644 index 0000000..308f887 --- /dev/null +++ b/dashboard.njk @@ -0,0 +1,200 @@ +{% extends "base.njk" %} + +{% block content %} +
+

{{ org }}

+

+ {% if totalRepos === 1 %} + There is 1 repository + {% else %} + There are {{ totalRepos }} repositories + {% endif %} + that Towtruck is tracking for {{ org }}. +

+
+ + + + + {{macros.sortableTableHeader("Open issues count", "openIssues", sortDirection, sortBy)}} + {{macros.sortableTableHeader("Open bot PR count", "openBotPrCount", sortDirection, sortBy)}} + {{macros.sortableTableHeader("Open PR count", "openPrCount", sortDirection, sortBy)}} + {{macros.sortableTableHeader("Updated at", "updatedAt", sortDirection, sortBy)}} + {{macros.sortableTableHeader("Most recent PR opened", "mostRecentPrOpenedAt", sortDirection, sortBy)}} + {{macros.sortableTableHeader("Oldest open PR opened", "oldestOpenPrOpenedAt", sortDirection, sortBy)}} + {{macros.sortableTableHeader("Most recent issue opened", "mostRecentIssueOpenedAt", sortDirection, sortBy)}} + {{macros.sortableTableHeader("Oldest open issue opened", "oldestOpenIssueOpenedAt", sortDirection, sortBy)}} + + + + {% for repo in repos %} + + + + + + + + + + + + + + {% else %} + + + + {% endfor %} + +
Repository
+
+ {{ repo.name }} + {% if repo.language %} + {{ repo.language }} + {% endif %} + {% if repo.totalOpenAlerts !== undefined %} +
+ {% set id = [repo.name, "alerts", "critical"] | join("-") %} + {% set mainText = ["", repo.criticalSeverityAlerts, ""] | join('') | safe %} +
{{macros.tooltip(id, mainText, "Critical severity alerts")}}
+ {% set id = [repo.name, "alerts", "high"] | join("-") %} + {% set mainText = ["", repo.highSeverityAlerts, ""] | join('') | safe %} +
{{macros.tooltip(id, mainText, "High severity alerts")}}
+ {% set id = [repo.name, "alerts", "medium"] | join("-") %} + {% set mainText = ["", repo.mediumSeverityAlerts, ""] | join('') | safe %} +
{{macros.tooltip(id, mainText, "Medium severity alerts")}}
+ {% set id = [repo.name, "alerts", "low"] | join("-") %} + {% set mainText = ["", repo.lowSeverityAlerts, ""] | join('') | safe %} +
{{macros.tooltip(id, mainText, "Low severity alerts")}}
+
+ {% else %} + Dependabot alerts have been disabled for this repository. + {% endif %} +
+

{{ repo.description }}

+ + {% if repo.topics.length %} +
+ {% for topic in repo.topics %} + {{ topic }} + {% endfor %} +
+ {% endif %} + +
+ +
+ {% if repo.dependencies.length %} +
+

+ {% if repo.dependencies.length === 1 %} + There is 1 dependency: + {% else %} + There are {{ repo.dependencies.length }} dependencies: + {% endif %} + +

+ +
+ {% else %} + + No dependencies have been discovered. +
+ Please make sure that Renovate has been configured on the repository to produce a dependency dashboard. +
+ {% endif %} +
+
+ + + {{ repo.openIssues }} + + + + + + {{ repo.openBotPrCount }} + + + + + + {{ repo.openPrCount }} + + + + + + {{ repo.updatedAt }} + + + + + + {{ repo.mostRecentPrOpenedAt }} + + + + + + {{ repo.oldestOpenPrOpenedAt }} + + + + + + {{ repo.mostRecentIssueOpenedAt }} + + + + + + {{ repo.oldestOpenIssueOpenedAt }} + + +
No repositories found.
+
+
+{% endblock %} diff --git a/index.njk b/index.njk index 308f887..dcc0937 100644 --- a/index.njk +++ b/index.njk @@ -2,199 +2,25 @@ {% block content %}
-

{{ org }}

+

Organisations

+ {% if orgs.length %}

- {% if totalRepos === 1 %} - There is 1 repository + {% if orgs.length === 1 %} + There is 1 organisation {% else %} - There are {{ totalRepos }} repositories + There are {{ orgs.length }} organisations {% endif %} - that Towtruck is tracking for {{ org }}. + using Towtruck that you are a member of.

-
- - - - - {{macros.sortableTableHeader("Open issues count", "openIssues", sortDirection, sortBy)}} - {{macros.sortableTableHeader("Open bot PR count", "openBotPrCount", sortDirection, sortBy)}} - {{macros.sortableTableHeader("Open PR count", "openPrCount", sortDirection, sortBy)}} - {{macros.sortableTableHeader("Updated at", "updatedAt", sortDirection, sortBy)}} - {{macros.sortableTableHeader("Most recent PR opened", "mostRecentPrOpenedAt", sortDirection, sortBy)}} - {{macros.sortableTableHeader("Oldest open PR opened", "oldestOpenPrOpenedAt", sortDirection, sortBy)}} - {{macros.sortableTableHeader("Most recent issue opened", "mostRecentIssueOpenedAt", sortDirection, sortBy)}} - {{macros.sortableTableHeader("Oldest open issue opened", "oldestOpenIssueOpenedAt", sortDirection, sortBy)}} - - - - {% for repo in repos %} - - - - - - - - - - - - - - {% else %} - - - - {% endfor %} - -
Repository
-
- {{ repo.name }} - {% if repo.language %} - {{ repo.language }} - {% endif %} - {% if repo.totalOpenAlerts !== undefined %} -
- {% set id = [repo.name, "alerts", "critical"] | join("-") %} - {% set mainText = ["", repo.criticalSeverityAlerts, ""] | join('') | safe %} -
{{macros.tooltip(id, mainText, "Critical severity alerts")}}
- {% set id = [repo.name, "alerts", "high"] | join("-") %} - {% set mainText = ["", repo.highSeverityAlerts, ""] | join('') | safe %} -
{{macros.tooltip(id, mainText, "High severity alerts")}}
- {% set id = [repo.name, "alerts", "medium"] | join("-") %} - {% set mainText = ["", repo.mediumSeverityAlerts, ""] | join('') | safe %} -
{{macros.tooltip(id, mainText, "Medium severity alerts")}}
- {% set id = [repo.name, "alerts", "low"] | join("-") %} - {% set mainText = ["", repo.lowSeverityAlerts, ""] | join('') | safe %} -
{{macros.tooltip(id, mainText, "Low severity alerts")}}
-
- {% else %} - Dependabot alerts have been disabled for this repository. - {% endif %} -
-

{{ repo.description }}

- - {% if repo.topics.length %} -
- {% for topic in repo.topics %} - {{ topic }} - {% endfor %} -
- {% endif %} - -
- -
- {% if repo.dependencies.length %} -
-

- {% if repo.dependencies.length === 1 %} - There is 1 dependency: - {% else %} - There are {{ repo.dependencies.length }} dependencies: - {% endif %} - -

- -
- {% else %} - - No dependencies have been discovered. -
- Please make sure that Renovate has been configured on the repository to produce a dependency dashboard. -
- {% endif %} -
-
- - - {{ repo.openIssues }} - - - - - - {{ repo.openBotPrCount }} - - - - - - {{ repo.openPrCount }} - - - - - - {{ repo.updatedAt }} - - - - - - {{ repo.mostRecentPrOpenedAt }} - - - - - - {{ repo.oldestOpenPrOpenedAt }} - - - - - - {{ repo.mostRecentIssueOpenedAt }} - - - - - - {{ repo.oldestOpenIssueOpenedAt }} - - -
No repositories found.
-
+ + {% else %} +

+ You are not a member of any organisations that are using Towtruck. +

+ {% endif %}
{% endblock %} diff --git a/routes/handlers.js b/routes/handlers.js index a156677..59a7366 100644 --- a/routes/handlers.js +++ b/routes/handlers.js @@ -3,24 +3,55 @@ import { mapRepoFromStorageToUi } from "../utils/index.js"; import { getQueryParams } from "../utils/queryParams.js"; import { sortByType } from "../utils/sorting.js"; import { TowtruckDatabase } from "../db/index.js"; +import { OctokitApp } from "../octokitApp.js"; -export const index = async (_, request, response) => { +const getOrgsForUser = async (token) => { + const octokit = await OctokitApp.app.oauth.getUserOctokit({ token }); + + const { data } = await octokit.request("GET /user/memberships/orgs"); + + return data + .filter(membership => membership.state === "active") + .map(membership => membership.organization.login); +} + +export const index = async (token, request, response) => { + const orgs = await getOrgsForUser(token); + + const template = nunjucks.render("index.njk", { + orgs, + }); + + return response.end(template); +}; + +export const org = async (token, request, response, {org}) => { const url = new URL(request.url, `http://${request.headers.host}`); + const orgs = await getOrgsForUser(token); + + if (!orgs.includes(org)) { + response.writeHead(302, { + "Location": "/", + }); + return response.end(); + } + const db = new TowtruckDatabase(); - const persistedRepoData = db.getAllRepositories(); + const persistedRepoData = db.getAllRepositoriesForOrg(org); const persistedLifetimeData = db.getAllDependencies(); const reposForUi = mapRepoFromStorageToUi(persistedRepoData, persistedLifetimeData); const { sortDirection, sortBy } = getQueryParams(url); - const template = nunjucks.render("index.njk", { + const template = nunjucks.render("dashboard.njk", { sortBy, sortDirection, + org, ...reposForUi, repos: sortByType(reposForUi.repos, sortDirection, sortBy), }); return response.end(template); -}; +} diff --git a/routes/index.js b/routes/index.js index c9da685..a1e2c99 100644 --- a/routes/index.js +++ b/routes/index.js @@ -1,9 +1,9 @@ -import { index } from "./handlers.js"; +import { index, org } from "./handlers.js"; import { match } from "./match.js"; const pathHandlers = { "/": index, - "/{org}": index, + "/{org}": org, }; export const handleRoutes = async (token, request, response) => { diff --git a/utils/index.js b/utils/index.js index f772d1e..976725e 100644 --- a/utils/index.js +++ b/utils/index.js @@ -171,7 +171,7 @@ export const mapRepoFromStorageToUi = (persistedData, persistedLifetimes) => { const totalRepos = mappedRepos.length; - return { org: Object.entries(persistedData)[0][1].owner, repos: mappedRepos, totalRepos }; + return { repos: mappedRepos, totalRepos }; }; /**