From 4f6c3e504e5bb57831b3ca6d59992789e727442a Mon Sep 17 00:00:00 2001 From: cgombauld Date: Mon, 15 Sep 2025 15:02:28 +0200 Subject: [PATCH] refactor(maintainers): migrate popup to lit --- public/components/icon/icon.js | 19 +- public/components/popup/popup.js | 4 - public/components/views/home/home.js | 4 +- .../views/home/maintainers/maintainers.css | 187 -------- .../views/home/maintainers/maintainers.html | 19 - .../views/home/maintainers/maintainers.js | 416 ++++++++++++++---- 6 files changed, 344 insertions(+), 305 deletions(-) delete mode 100644 public/components/views/home/maintainers/maintainers.html diff --git a/public/components/icon/icon.js b/public/components/icon/icon.js index ca48e145..fcd29d87 100644 --- a/public/components/icon/icon.js +++ b/public/components/icon/icon.js @@ -91,7 +91,24 @@ const kIcons = { 118.784q47.104 47.104 47.104 115.712 0 70.656-50.176 119.808l50.176 50.176q49.152-50.176 118.784-50.176 68.608 0 116.736 48.128l118.784 118.784q48.128 48.128 48.128 116.736z"/> -` +`, + "right-open-big": html``, + globe: html`` }; export class Icon extends LitElement { diff --git a/public/components/popup/popup.js b/public/components/popup/popup.js index 8a92cef7..558c7238 100644 --- a/public/components/popup/popup.js +++ b/public/components/popup/popup.js @@ -70,10 +70,6 @@ section#popup--background>.popup { if (this.isOpen) { return; } - // FIXME: temporary fix until all the popups content are migrated - if (this.theme === "dark" && content.firstElementChild) { - content.firstElementChild.classList.add("popup-dark"); - } this.appendChild(content); this.isOpen = true; }; diff --git a/public/components/views/home/home.js b/public/components/views/home/home.js index 5f160d6b..d40ee3a6 100644 --- a/public/components/views/home/home.js +++ b/public/components/views/home/home.js @@ -393,11 +393,9 @@ export class HomeView { const popupReport = document.createElement("popup-report"); popupReport.rootDependencyName = this.secureDataSet.data.rootDependencyName; popupReport.theme = this.secureDataSet.theme; - const fragment = document.createDocumentFragment(); - fragment.appendChild(popupReport); window.dispatchEvent(new CustomEvent(EVENTS.MODAL_OPENED, { detail: { - content: fragment + content: popupReport } })); }); diff --git a/public/components/views/home/maintainers/maintainers.css b/public/components/views/home/maintainers/maintainers.css index 6f7fe9c5..99448906 100644 --- a/public/components/views/home/maintainers/maintainers.css +++ b/public/components/views/home/maintainers/maintainers.css @@ -83,190 +83,3 @@ body.dark .home--maintainers > .highlighted { .home--maintainers>.person>div.packagescount>i { margin-right: 4px; } - -/** - * POPUP - * FIXME: remove the !important when the popup is migrated to lit - **/ -.maintainers--popup { - display: flex; - flex-direction: column; - width: 500px; - margin: 5px; -} - -.maintainers--popup>.header { - height: 80px; - display: flex; - flex-shrink: 0; - margin-bottom: 10px; - border-radius: 4px; - overflow: hidden; - margin-right: 25px; -} - -.maintainers--popup>.header>.avatar { - width: 80px; - overflow: hidden; - flex-shrink: 0; - border-radius: 8px; - box-sizing: border-box; - box-shadow: 2px 2px 6px 0 #00000012; -} - -.maintainers--popup>.header>.avatar>img { - width: 80px; -} - -.maintainers--popup>.header>.informations { - display: flex; - flex-direction: column; - flex-grow: 1; - justify-content: center; - font-family: mononoki; - margin: 0 10px; -} - -.maintainers--popup>.header>.informations>p.name { - color: #546884; -} - -.popup-dark >.header>.informations>p.name { - color: white !important; -} - -.maintainers--popup>.header>.informations>p.email { - color: var(--secondary-darker); - margin-top: 10px; - font-family: monospace; -} - -.popup-dark >.header>.informations>p.email { - color: var(--dark-theme-secondary-color) !important; - opacity: 0.9 !important; -} - -.maintainers--popup>.header>.icons { - display: flex; - align-items: center; -} - -.maintainers--popup>.header>.icons>i { - height: 40px; - width: 40px; - font-size: 20px; - display: flex; - align-items: center; - justify-content: center; - background-color: var(--secondary-darker); - border-radius: 100%; - color: #FFF; - box-shadow: 2px 2px 6px 0 #00000012; -} - -.maintainers--popup>.header>.icons>i:hover { - cursor: pointer; - background-color: var(--primary); -} - -.maintainers--popup>.header>.icons>i+i { - margin-left: 10px; -} - -.maintainers--popup>.separator { - height: 2px; - background: #d3d3d387; - margin: 0 10px; - display: flex; - align-items: center; - justify-content: center; - flex-shrink: 0; -} - -.popup-dark >.separator { - background: var(--dark-theme-secondary-color) !important; -} - -.maintainers--popup>.separator>p { - background: #f5f4f4; - padding: 0 10px; - font-family: roboto; - font-weight: bold; - letter-spacing: 1.2px; - color: #255471; -} - -.popup-dark>.separator>p { - background: #303263 !important; - color: #3cbde5 !important; -} - -.maintainers--popup>ul { - display: flex; - flex-direction: column; - flex-grow: 1; - overflow: hidden auto; - max-height: 240px; - margin-top: 20px; - margin-bottom: 10px; -} - -.maintainers--popup>ul li { - height: 36px; - padding: 0 10px; - display: flex; - align-items: center; - background: linear-gradient(to right, rgb(221 229 251) 0%, rgb(255 255 255 / 0%) 100%); - border-left: 2px solid #4480da; - color: #234c99; - border-radius: 4px; - font-family: mononoki; - flex-shrink: 0; - font-size: 15px; -} - -.popup-dark>ul li { - background: linear-gradient(to right, var(--dark-theme-primary-color) 0%, rgb(28 29 58 / 18.5%) 100%) !important; - border: none !important; - color: white !important; -} - -.maintainers--popup>ul li>p{ - color: #234c99; -} - -.popup-dark>ul li>p{ - color: #9ca6b7 !important; -} - -.maintainers--popup>ul li>span{ - color: #2470b3; - margin-left: 10px; -} - -.popup-dark>ul li>span{ - color: var(--dark-theme-secondary-color) !important; -} - -.maintainers--popup>ul li>i{ - margin-left: auto; - margin-right: 13px; - background: #4ab968; - color: #FFF; - border-radius: 100%; - width: 26px; - height: 26px; - display: flex; - justify-content: center; - align-items: center; - box-shadow: 2px 2px 6px 0 #00000012; -} - -.maintainers--popup>ul li>i:hover { - background: #4ab8b9; - cursor: pointer; -} - -.maintainers--popup>ul li+li { - margin-top: 5px; -} diff --git a/public/components/views/home/maintainers/maintainers.html b/public/components/views/home/maintainers/maintainers.html deleted file mode 100644 index 78b2a6f5..00000000 --- a/public/components/views/home/maintainers/maintainers.html +++ /dev/null @@ -1,19 +0,0 @@ - diff --git a/public/components/views/home/maintainers/maintainers.js b/public/components/views/home/maintainers/maintainers.js index 67c99985..4d6f1dd3 100644 --- a/public/components/views/home/maintainers/maintainers.js +++ b/public/components/views/home/maintainers/maintainers.js @@ -1,7 +1,14 @@ +// Import Third-party Dependencies +import { LitElement, html, css, nothing } from "lit"; +import { when } from "lit/directives/when.js"; +import { repeat } from "lit/directives/repeat.js"; + // Import Internal Dependencies import * as utils from "../../../../common/utils.js"; import "../../../expandable/expandable.js"; import { EVENTS } from "../../../../core/events.js"; +import "../../../icon/icon.js"; +import avatarURL from "../../../../img/avatar-default.png"; export class Maintainers { static whois(name, email) { @@ -78,9 +85,14 @@ export class Maintainers { } person.addEventListener("click", () => { // TODO: close package info? + const popupMaintainer = document.createElement("popup-maintainer"); + popupMaintainer.data = data; + popupMaintainer.theme = this.secureDataSet.theme; + popupMaintainer.nsn = this.nsn; + popupMaintainer.name = name; window.dispatchEvent(new CustomEvent(EVENTS.MODAL_OPENED, { detail: { - content: new PopupMaintainer(name, data, this.nsn).render() + content: popupMaintainer } })); }); @@ -98,112 +110,334 @@ export class Maintainers { } } -export class PopupMaintainer { - constructor(name, data, nsn) { - this.name = name; - this.data = data; - this.nsn = nsn; - } +export class PopupMaintainer extends LitElement { + static styles = css` +.maintainers--popup { + display: flex; + flex-direction: column; + width: 500px; + margin: 5px; +} - render() { - const { email, url = null } = this.data; +.maintainers--popup>.header { + height: 80px; + display: flex; + flex-shrink: 0; + margin-bottom: 10px; + border-radius: 4px; + overflow: hidden; + margin-right: 25px; +} - const templateElement = document.getElementById("maintainers-popup-template"); - /** @type {HTMLElement} */ - const clone = templateElement.content.cloneNode(true); +.maintainers--popup>.header>.avatar { + width: 80px; + overflow: hidden; + flex-shrink: 0; + border-radius: 8px; + box-sizing: border-box; + box-shadow: 2px 2px 6px 0 #00000012; +} - clone.querySelector(".avatar").appendChild( - utils.createAvatarImageElementForAuthor(this.data) - ); - clone.querySelector(".name").textContent = this.name; - const emailElement = clone.querySelector(".email"); +.maintainers--popup>.header>.avatar>img { + width: 80px; +} - if (typeof email === "string") { - emailElement.textContent = email; - } - else { - emailElement.style.display = "none"; - } +.maintainers--popup>.header>.informations { + display: flex; + flex-direction: column; + flex-grow: 1; + justify-content: center; + font-family: mononoki; + margin: 0 10px; +} - const linkElement = clone.querySelector(".icon-link"); - if (typeof url === "string") { - linkElement.addEventListener("click", () => window.open(url, "_blank")); - } - else { - linkElement.style.display = "none"; - } +.maintainers--popup>.header>.informations>p.name { + color: #546884; +} - const globeElement = clone.querySelector(".icon-globe-alt-outline"); - const packagesList = [...this.data.packages] - .map((spec) => { - const { name, version } = utils.parseNpmSpec(spec); +.dark >.header>.informations>p.name { + color: white !important; +} - return `${name}@${version}`; - }); +.maintainers--popup>.header>.informations>p.email { + color: var(--secondary-darker); + margin-top: 10px; + font-family: monospace; +} - globeElement.addEventListener("click", () => { - const nodeIds = [...this.nsn.findNodeIds(new Set(packagesList))]; - - this.nsn.highlightMultipleNodes(nodeIds); - window.locker.lock(); - window.dispatchEvent(new CustomEvent(EVENTS.MODAL_CLOSED)); - window.navigation.setNavByName("network--view"); - - const currentSelectedNode = window.networkNav.currentNodeParams; - const moveTo = currentSelectedNode === null || !nodeIds.includes(currentSelectedNode.nodes[0]); - if (moveTo) { - const origin = this.nsn.network.getViewPosition(); - const closestNode = nodeIds - .map((id) => { - return { id, pos: this.nsn.network.getPosition(id) }; - }) - .reduce( - (a, b) => (utils.vec2Distance(origin, a.pos) < utils.vec2Distance(origin, b.pos) ? a : b) - ); - - const scale = nodeIds.length > 3 ? 0.25 : 0.35; - this.nsn.network.focus(closestNode.id, { - animation: true, - scale - }); - } - }); +.dark >.header>.informations>p.email { + color: var(--dark-theme-secondary-color) !important; + opacity: 0.9 !important; +} + +.maintainers--popup>.header>.icons { + display: flex; + align-items: center; +} + +.maintainers--popup>.header>.icons>a,.maintainers--popup>.header>.icons>button { + border:none; + height: 40px; + width: 40px; + font-size: 20px; + display: flex; + align-items: center; + justify-content: center; + background-color: var(--secondary-darker); + border-radius: 100%; + color: #FFF; + box-shadow: 2px 2px 6px 0 #00000012; + margin-left: 10px; +} - this.generatePackagesList(clone); +.maintainers--popup>.header>.icons>a:hover,.maintainers--popup>.header>.icons>button:hover { + cursor: pointer; + background-color: var(--primary); +} + +.maintainers--popup>.header>.icons>a > nsecure-icon,.maintainers--popup>.header>.icons>button > nsecure-icon{ + margin: 0; + transform: translateX(1px); +} + +.maintainers--popup>.separator { + height: 2px; + background: #d3d3d387; + margin: 0 10px; + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; +} + +.dark >.separator { + background: var(--dark-theme-secondary-color) !important; +} + +.maintainers--popup>.separator>p { + background: #f5f4f4; + padding: 0 10px; + font-family: roboto; + font-weight: bold; + letter-spacing: 1.2px; + color: #255471; +} - return clone; +.dark>.separator>p { + background: #303263 !important; + color: #3cbde5 !important; +} + +.maintainers--popup>ul { + display: flex; + flex-direction: column; + flex-grow: 1; + overflow: hidden auto; + max-height: 240px; + margin-top: 20px; + margin-bottom: 10px; + padding: 0; +} + +.maintainers--popup>ul li { + height: 36px; + padding: 0 10px; + display: flex; + align-items: center; + background: linear-gradient(to right, rgb(221 229 251) 0%, rgb(255 255 255 / 0%) 100%); + border-left: 2px solid #4480da; + color: #234c99; + border-radius: 4px; + font-family: mononoki; + flex-shrink: 0; + font-size: 15px; +} + +.dark>ul li { + background: linear-gradient(to right, var(--dark-theme-primary-color) 0%, rgb(28 29 58 / 18.5%) 100%) !important; + border: none !important; + color: white !important; +} + +.maintainers--popup>ul li>p{ + color: #234c99; +} + +.dark>ul li>p{ + color: #9ca6b7 !important; +} + +.maintainers--popup>ul li>span{ + color: #2470b3; + margin-left: 10px; +} + +.dark>ul li>span{ + color: var(--dark-theme-secondary-color) !important; +} + +.maintainers--popup>ul li> button{ + border: none; + margin-left: auto; + margin-right: 13px; + background: #4ab968; + color: #FFF; + border-radius: 100%; + width: 26px; + height: 26px; + display: flex; + justify-content: center; + align-items: center; + box-shadow: 2px 2px 6px 0 #00000012; +} + +.maintainers--popup>ul li> button nsecure-icon{ + margin: 0; + transform: translateX(4px); +} + +.maintainers--popup>ul li>button:hover { + background: #4ab8b9; + cursor: pointer; +} + +.maintainers--popup>ul li+li { + margin-top: 5px; +} +`; + static properties = { + name: { type: String }, + data: { type: Object }, + nsn: { type: Object }, + theme: { type: String } + }; + + constructor() { + super(); + this.isLoading = false; + this.settingsChanged = ({ detail: { theme } }) => { + if (theme !== this.theme) { + this.theme = theme; + } + }; } - /** - * @param {!HTMLElement} clone - */ - generatePackagesList(clone) { - const fragment = document.createDocumentFragment(); + connectedCallback() { + super.connectedCallback(); + window.addEventListener(EVENTS.SETTINGS_SAVED, this.settingsChanged); + } - for (const spec of this.data.packages) { - const { name, version } = utils.parseNpmSpec(spec); + disconnectedCallback() { + window.removeEventListener(EVENTS.SETTINGS_SAVED, this.settingsChanged); + super.disconnectedCallback(); + } - const iconNetwork = utils.createDOMElement("i", { - className: "icon-right-open-big" - }); - iconNetwork.addEventListener("click", () => { - window.dispatchEvent(new CustomEvent(EVENTS.MODAL_CLOSED)); - window.navigation.setNavByName("network--view"); - setTimeout(() => this.nsn.focusNodeByNameAndVersion(name, version), 25); + render() { + const { url = null } = this.data; + const { popup: { maintainer } } = window.i18n[utils.currentLang()]; + const packagesList = [...this.data.packages] + .map((spec) => { + const { name, version } = utils.parseNpmSpec(spec); + + return `${name} @${version} `; }); - fragment.appendChild( - utils.createDOMElement("li", { - childs: [ - utils.createDOMElement("p", { text: name }), - utils.createDOMElement("span", { text: `v${version}` }), - iconNetwork - ] - }) - ); + return html` +
+
+
+ ${when( + this.data.npmAvatar, + () => html` { + e.currentTarget.src = avatarURL; + }}>`, + () => html` { + e.currentTarget.src = avatarURL; + }}>` + ) + } +
+
+

+ ${this.name} +

+ ${when( + typeof this.data.email === "string", + () => html``, + () => nothing + )} +
+
+ ${when( + typeof url === "string", + () => html` + + `, + () => nothing + )} + +
+
+
+

${maintainer.intree}

+
+ +
+ `; } } + +customElements.define("popup-maintainer", PopupMaintainer);