diff --git a/esbuild.config.js b/esbuild.config.js index 7b295479..a06a59d7 100644 --- a/esbuild.config.js +++ b/esbuild.config.js @@ -45,6 +45,7 @@ await Promise.all([ "snyk.png", "sonatype.png", "avatar-default.png", + "scorecard.png", "ext-link.svg" ].map((name) => fs.copyFile(path.join(kImagesDir, name), path.join(kOutDir, name))), fs.copyFile(path.join(kPublicDir, "favicon.ico"), path.join(kOutDir, "favicon.ico")) diff --git a/public/css/views/home.css b/public/css/views/home.css index 7353dfe8..a10ba381 100644 --- a/public/css/views/home.css +++ b/public/css/views/home.css @@ -9,10 +9,65 @@ #home--view .home--header { display: flex; +} + +.home--header--scorecard { + display: none; + flex-shrink: 0; + margin-left: 40px; + overflow: hidden; + border-radius: 4px; + font-family: 'mononoki'; + letter-spacing: 1px; + cursor: pointer; +} + +.home--header--scorecard .description { + width: 190px; + background: linear-gradient(to bottom, #37474f 0%,#263238 100%); + display: flex; + align-items: center; +} + +.home--header--scorecard .description > img { + height: 73px; +} + +.home--header--scorecard .description > p { + margin-left: 10px; +} + +.home--header--scorecard .score { + width: 73px; + color: #FFF; + display: flex; + font-size: 20px; flex-direction: column; + justify-content: center; + align-items: center; + text-shadow: 1px 1px 5px #0000007a; + box-shadow: 2px 2px 10px #1e1e1e69 inset; +} +.home--header--scorecard .score.green { + background-color: rgb(113 203 45); +} +.home--header--scorecard .score.red { + background-color: rgb(219 80 58); +} +.home--header--scorecard .score.orange { + background-color: rgb(252 196 39); +} +.home--header--scorecard .score.blue { + background-color: rgb(39 144 252); +} + +.home--header--title { + display: flex; + flex-direction: column; + flex-grow: 1; } -#home--view .home--header>.top { +.home--header--title .top { display: flex; height: 40px; align-items: center; @@ -21,37 +76,37 @@ border-bottom: 2px solid #cecec9; } -#home--view .home--header>.top #project-name { +.home--header--title .top #project-name { color: var(--primary-lighter); } -#home--view .home--header>.top #project-version { +.home--header--title .top #project-version { color: var(--secondary-darker); margin-left: 15px; font-size: 20px; margin-top: 5px; } -#home--view .home--header>.bottom { +.home--header--title .bottom { display: flex; height: 26px; align-items: center; margin-top: 5px; } -#home--view .home--header>.bottom #project-description { +.home--header--title .bottom #project-description { color: var(--primary); letter-spacing: 1px; font-family: system-ui; } -#home--view .home--header>.bottom>ul { +.home--header--title .bottom>ul { margin-left: auto; height: inherit; display: flex; } -#home--view .home--header>.bottom>ul li { +.home--header--title .bottom>ul li { display: flex; align-items: center; color: #425964; @@ -59,18 +114,18 @@ letter-spacing: 0.5px; } -#home--view .home--header>.bottom>ul li:hover { +.home--header--title .bottom>ul li:hover { text-decoration: underline; cursor: pointer; } -#home--view .home--header>.bottom>ul li img { +.home--header--title .bottom>ul li img { width: 20px; height: 20px; margin-right: 5px; } -#home--view .home--header>.bottom>ul li+li { +.home--header--title .bottom>ul li+li { margin-left: 40px; } diff --git a/public/img/scorecard.png b/public/img/scorecard.png new file mode 100644 index 00000000..9a9b8d54 Binary files /dev/null and b/public/img/scorecard.png differ diff --git a/public/js/components/home.js b/public/js/components/home.js index 85910370..a00f7e84 100644 --- a/public/js/components/home.js +++ b/public/js/components/home.js @@ -4,6 +4,7 @@ import { NodeSecureDataSet, getJSON } from "@nodesecure/vis-network"; // Import Internal Dependencies import * as utils from "../utils.js"; import { Gauge } from "./gauge.js"; +import { fetchScorecardData, getScoreColor, getScorecardLink } from "../scorecard.js"; export class HomeView { /** @@ -12,6 +13,7 @@ export class HomeView { constructor(secureDataSet) { this.secureDataSet = secureDataSet; + this.generateScorecard(); this.generateHeader(); this.generateOverview(); this.generateWarnings(); @@ -20,6 +22,27 @@ export class HomeView { this.generateMaintainers(); } + generateScorecard() { + const { repository } = this.secureDataSet.linker.get(0); + const repoName = utils.getGithubRepositoryPath( + utils.parseRepositoryUrl(repository) + ) + + fetchScorecardData(repoName).then((data) => { + if (data !== null) { + document + .querySelector(".home--header--scorecard .score") + .classList.add(getScoreColor(data.score)); + document.getElementById("home-scorecard-score").innerHTML = data.score; + const scorescardElement = document.querySelector(".home--header--scorecard"); + scorescardElement.addEventListener("click", () => { + window.open(getScorecardLink(repoName), "_blank"); + }); + scorescardElement.style.display = "flex"; + } + }); + } + generateHeader() { const { name, version, description, repository } = this.secureDataSet.linker.get(0); diff --git a/public/js/components/package/pannels/scorecard.js b/public/js/components/package/pannels/scorecard.js index ed1cdd59..a0f26c83 100644 --- a/public/js/components/package/pannels/scorecard.js +++ b/public/js/components/package/pannels/scorecard.js @@ -1,34 +1,12 @@ -// Import Third-party Dependencies -import { getJSON } from "@nodesecure/vis-network"; - // Import Internal Dependencies import * as utils from "../../../utils.js"; +import { fetchScorecardData, getScoreColor, getScorecardLink } from "../../../scorecard.js"; export class Scorecard { - static ExternalLinks = { - visualizer: "https://kooltheba.github.io/openssf-scorecard-api-visualizer/#/projects/github.com/" - } - constructor(pkg) { this.package = pkg; } - async fetchScorecardData(repoName) { - try { - const { data } = (await getJSON(`/scorecard/${repoName}`)); - if (!data) { - return null; - } - - return data; - } - catch (error) { - console.error(error); - - return null; - } - } - hide() { const scorecardMenu = document.getElementById('scorecard-menu'); if (scorecardMenu) { @@ -45,14 +23,9 @@ export class Scorecard { return this.hide(); } - const github = new URL(githubURL.href); - const repoName = github.pathname.slice( - 1, - github.pathname.includes(".git") ? -4 : github.pathname.length - ); - + const repoName = utils.getGithubRepositoryPath(githubURL.href); const pannel = clone.getElementById("pan-scorecard"); - this.fetchScorecardData(repoName).then((data) => { + fetchScorecardData(repoName).then((data) => { if (!data) { return this.hide(); } @@ -62,20 +35,6 @@ export class Scorecard { }); } - getScoreColor(score) { - if (score < 4) { - return "red"; - } - if (score < 6.5) { - return "orange"; - } - if (score < 8.5) { - return "blue"; - } - - return "green"; - } - renderScorecard(data, repoName) { const { score, checks } = data; @@ -89,12 +48,12 @@ export class Scorecard { document.getElementById('ossf-score').innerText = score; document.getElementById('scorecard-menu').classList.add( - this.getScoreColor(score) + getScoreColor(score) ); document.getElementById('head-score').innerText = score; document .querySelector(".score-header .visualizer a") - .setAttribute('href', Scorecard.ExternalLinks.visualizer + repoName); + .setAttribute('href', getScorecardLink(repoName)); container.childNodes.forEach((check, checkKey) => { check.addEventListener('click', () => { diff --git a/public/js/scorecard.js b/public/js/scorecard.js new file mode 100644 index 00000000..6ebf0dcf --- /dev/null +++ b/public/js/scorecard.js @@ -0,0 +1,45 @@ +// Import Third-party Dependencies +import { getJSON } from "@nodesecure/vis-network"; + +/** + * @param {!string} repoName + */ +export async function fetchScorecardData(repoName) { + try { + const { data } = (await getJSON(`/scorecard/${repoName}`)); + if (!data) { + return null; + } + + return data; + } + catch (error) { + console.error(error); + + return null; + } +} + +/** + * @param {!number} score + * @returns {string} + */ +export function getScoreColor(score) { + if (score < 4) { + return "red"; + } + if (score < 6.5) { + return "orange"; + } + if (score < 8.5) { + return "blue"; + } + + return "green"; +} + +export function getScorecardLink( + repoName +) { + return `https://kooltheba.github.io/openssf-scorecard-api-visualizer/#/projects/github.com/` + repoName; +} diff --git a/public/js/utils.js b/public/js/utils.js index 6624af6a..d867ca13 100644 --- a/public/js/utils.js +++ b/public/js/utils.js @@ -3,6 +3,15 @@ import avatarURL from "../img/avatar-default.png"; window.activeLegendElement = null; +export function getGithubRepositoryPath(url) { + const github = new URL(url); + + return github.pathname.slice( + 1, + github.pathname.includes(".git") ? -4 : github.pathname.length + ); +} + /** * @param {keyof HTMLElementTagNameMap} kind * @param {object} [options] diff --git a/views/index.html b/views/index.html index 8faf64ec..f5379fbc 100644 --- a/views/index.html +++ b/views/index.html @@ -59,13 +59,24 @@