Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 90 additions & 14 deletions public/css/views/home.css
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,16 @@

.home--header--scorecard .description {
width: 190px;
background: linear-gradient(to bottom, #37474f 0%,#263238 100%);
background: linear-gradient(to bottom, #37474f 0%, #263238 100%);
display: flex;
align-items: center;
}

.home--header--scorecard .description > img {
.home--header--scorecard .description>img {
height: 73px;
}

.home--header--scorecard .description > p {
.home--header--scorecard .description>p {
margin-left: 10px;
}

Expand All @@ -48,20 +48,24 @@
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 {
.home--header--title {
display: flex;
flex-direction: column;
flex-grow: 1;
Expand Down Expand Up @@ -142,6 +146,7 @@
color: var(--secondary-darker);
flex-grow: 1;
flex-basis: 100%;
margin-top: 10px;
}

#home--view .home--body .pannel {
Expand Down Expand Up @@ -209,6 +214,22 @@
min-height: 20px;
}

#home--view .home--body .module>.content+.content {
margin-top: 10px;
}

#home--view .home--body .module>.content>p {
color: #7a7595;
display: flex;
align-items: center;
justify-content: center;
height: 40px;
font-family: "system-ui";
font-weight: 500;
letter-spacing: 1.1px;
padding: 10px;
}

/**
* WARNINGS BEGIN
*/
Expand All @@ -221,16 +242,13 @@

.home--warnings>p {
padding: 10px;
background: -moz-linear-gradient(left, rgba(140, 0, 0, 0.24) 0%, rgba(0, 0, 0, 0) 100%);
background: -webkit-linear-gradient(left, rgba(140, 0, 0, 0.24) 0%, rgba(0, 0, 0, 0) 100%);
background: linear-gradient(to right, rgba(140, 0, 0, 0.24) 0%, rgba(0, 0, 0, 0) 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#3d8c0000', endColorstr='#00000000', GradientType=1);

color: #4a0000;
border-left: 2px solid #da4e44;
background: linear-gradient(to right, rgb(231, 206, 195) 0%, rgba(255, 255, 255, 0) 100%);
color: #992323;
border-radius: 4px;
}

.home--warnings>p + p {
.home--warnings>p+p {
margin-top: 5px;
}

Expand Down Expand Up @@ -282,6 +300,63 @@
margin-top: 10px;
}

.home--packages--overview {
display: flex;
flex-direction: column;
margin-left: -10px;
margin-top: -10px;
}

.home--packages--overview>div {
background: linear-gradient(to right, rgb(231 216 195) 0%, rgba(255, 255, 255, 0) 100%);
display: flex;
align-items: center;
padding: 5px 10px;
position: relative;
box-sizing: border-box;
border-radius: 4px;
font-family: "mononoki";
margin-left: 10px;
margin-top: 10px;
border-left: 2px solid #da9744;
color: #992323;
font-size: 16px;
flex-wrap: wrap;
transition: 0.5s linear all;
}

.home--packages--overview>div:hover {
border-color: #da4e44;
cursor: pointer;
background: linear-gradient(to right, rgb(231, 206, 195) 0%, rgba(255, 255, 255, 0) 100%);
}

.home--packages--overview>div span {
color: #6d5703;
margin-left: 10px;
}

.home--packages--overview>div>div.chips {
margin-left: auto;
display: flex;
font-size: 15px;
font-family: 'Roboto';
font-weight: 500;
}

.home--packages--overview>div>div.chips>p {
padding: 5px;
background: linear-gradient(to bottom, rgba(252, 252, 252, 1) 0%, rgba(232, 232, 232, 1) 100%);
border-radius: 4px;
box-shadow: 2px 2px 6px 0px #71060633;
border: 1px solid #8f0e0e54;
color: #611717;
}

.home--packages--overview>div>div.chips>p+p {
margin-left: 10px;
}

/**
* OVERVIEW END
*/
Expand All @@ -299,7 +374,8 @@
.home--maintainers>.person {
height: 50px;
flex-basis: 300px;
display : flex;
background: linear-gradient(to bottom, rgba(252, 252, 252, 1) 0%, rgba(232, 232, 232, 1) 100%);
display: flex;
position: relative;
box-sizing: border-box;
border-radius: 4px;
Expand All @@ -317,15 +393,15 @@
}

.home--maintainers>.person.url:hover {
border-color: var(--primary);
border-color: var(--secondary-darker);
cursor: pointer;
}

.home--maintainers>.person>img {
width: 50px;
}

.home--maintainers>.person>i{
.home--maintainers>.person>i {
margin-right: 10px;
display: flex;
align-items: center;
Expand Down
94 changes: 92 additions & 2 deletions public/js/components/home.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,41 @@
// Import Third-party Dependencies
import { NodeSecureDataSet, getJSON } from "@nodesecure/vis-network";
import { NodeSecureDataSet, getFlagsEmojisInlined, getJSON } from "@nodesecure/vis-network";
import { licenseIdConformance } from "@nodesecure/licenses-conformance";

// Import Internal Dependencies
import * as utils from "../utils.js";
import { Gauge } from "./gauge.js";
import { fetchScorecardData, getScoreColor, getScorecardLink } from "../scorecard.js";

// CONSTANTS
const kFlagsToWatch = new Set([
"hasBannedFile",
"isDeprecated",
"hasVulnerabilities",
"hasScript"
]);

const kEmojiDescription = {
"📦": "scripts",
"⚔️": "sensitive files",
"🚨": "vulnerabilities"
};

export class HomeView {
/**
* @param {!NodeSecureDataSet} secureDataSet
*/
constructor(secureDataSet) {
constructor(
secureDataSet,
nsn
) {
this.secureDataSet = secureDataSet;
this.nsn = nsn;

this.generateScorecard();
this.generateHeader();
this.generateOverview();
this.generatePackagesToWatch();
this.generateWarnings();
this.generateExtensions();
this.generateLicenses();
Expand Down Expand Up @@ -137,6 +156,77 @@ export class HomeView {
}
}

generatePackagesToWatch() {
const maxPackages = 4;
const fragment = document.createDocumentFragment();

const deps = [];
for (const dependency of Object.values(this.secureDataSet.data.dependencies)) {
for (const dependencyVer of Object.values(dependency.versions)) {
const { flags } = dependencyVer;

const hasFlag = flags.some((name) => kFlagsToWatch.has(name));
if (hasFlag) {
deps.push(dependencyVer);
}
}
}

const hideItems = deps.length > maxPackages;
for (let id = 0; id < deps.length; id++) {
const dependency = deps[id];

const element = this.renderPackage(dependency);
element.addEventListener("click", () => {
window.navigation.setNavByName("network--view");
setTimeout(() => this.nsn.focusNodeByName(dependency.name), 25);
});
if (hideItems && id >= maxPackages) {
element.classList.add("hidden");
}

fragment.appendChild(element);
}

if (fragment.children.length === 0) {
document.querySelector(".home--to--watch").style.display = "none";
}
else {
if (hideItems) {
fragment.appendChild(utils.createExpandableSpan(maxPackages));
}

document.querySelector(".home--packages--overview")
.appendChild(fragment);
}
}

renderPackage(dependencyVer) {
const { name, version, flags } = dependencyVer;
const inlinedEmojis = getFlagsEmojisInlined(
flags.filter((name) => kFlagsToWatch.has(name)),
new Set(window.settings.config.ignore.flags)
);

const childs = utils.extractEmojis(inlinedEmojis)
.map((emoji) => utils.createDOMElement("p", { text: `${emoji} ${kEmojiDescription[emoji]}` }));

return utils.createDOMElement("div", {
childs: [
utils.createDOMElement("p", {
childs: [
document.createTextNode(name),
utils.createDOMElement("span", { text: `v${version}` })
]
}),
utils.createDOMElement("div", {
className: "chips",
childs
})
]
});
}

generateWarnings() {
const warningsModuleElement = document.getElementById("warnings-module");
if (this.secureDataSet.warnings.length === 0) {
Expand Down
2 changes: 1 addition & 1 deletion public/js/master.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ document.addEventListener("DOMContentLoaded", async () => {
});
await secureDataSet.init();

new HomeView(secureDataSet);
window.vulnerabilityStrategy = secureDataSet.data.vulnerabilityStrategy;

// Initialize vis Network
NodeSecureNetwork.networkElementId = "dependency-graph";
const nsn = new NodeSecureNetwork(secureDataSet);
new HomeView(secureDataSet, nsn);
const rootNodeParams = {
nodes: [0],
edges: nsn.network.getConnectedEdges(0)
Expand Down
9 changes: 9 additions & 0 deletions public/js/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,15 @@ export function isGitLabHost(host) {
}
}

export function extractEmojis(strWithEmojis) {
const segmenter = new Intl.Segmenter("en", {
granularity: "grapheme"
});
const segitr = segmenter.segment(strWithEmojis.replaceAll(" ", ""));

return Array.from(segitr, ({ segment }) => segment);
}

/**
* @param {keyof HTMLElementTagNameMap} kind
* @param {object} [options]
Expand Down
22 changes: 13 additions & 9 deletions views/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -90,15 +90,9 @@
<div class="content">
<div class="home--overview"></div>
</div>
</div>
<div class="module" id="warnings-module">
<div class="title warning">
<i class="icon-warning"></i>
<p>Warnings</p>
<span class="count">1</span>
</div>
<div class="content">
<div class="home--warnings"></div>
<div class="content" class="home--to--watch">
<p>Packages in the dependency tree requiring greater attention</p>
<div class="home--packages--overview"></div>
</div>
</div>
<div class="module">
Expand All @@ -113,6 +107,16 @@
</div>
</div>
<div class="pannel">
<div class="module" id="warnings-module">
<div class="title warning">
<i class="icon-warning"></i>
<p>Critical Warnings</p>
<span class="count">1</span>
</div>
<div class="content">
<div class="home--warnings"></div>
</div>
</div>
<div class="module">
<div class="title">
<i class="icon-doc"></i>
Expand Down