diff --git a/public/components/views/home/home.css b/public/components/views/home/home.css
index e110cc19..324dcc87 100644
--- a/public/components/views/home/home.css
+++ b/public/components/views/home/home.css
@@ -1,5 +1,4 @@
@import url("./maintainers/maintainers.css");
-@import url("./report/report.css");
#home--view {
z-index: 10;
diff --git a/public/components/views/home/home.js b/public/components/views/home/home.js
index 39268c62..5f160d6b 100644
--- a/public/components/views/home/home.js
+++ b/public/components/views/home/home.js
@@ -12,7 +12,7 @@ import { fetchScorecardData, getScorecardLink } from "../../../common/scorecard.
// Import Components
import { Maintainers } from "./maintainers/maintainers.js";
-import { PopupReport } from "./report/report.js";
+import "./report/report.js";
// CONSTANTS
const kFlagsToWatch = new Set([
@@ -390,9 +390,14 @@ export class HomeView {
handleReport() {
document.querySelector(".home--header--report").addEventListener("click", async() => {
+ 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: new PopupReport(this.secureDataSet.data.rootDependencyName).render()
+ content: fragment
}
}));
});
diff --git a/public/components/views/home/report/report.css b/public/components/views/home/report/report.css
deleted file mode 100644
index 4c41189a..00000000
--- a/public/components/views/home/report/report.css
+++ /dev/null
@@ -1,138 +0,0 @@
-/* FIXME: remove the !important when the popup is migrated to lit */
-
-.report--popup {
- min-width: 400px;
- padding: 40px;
- display: flex;
- flex-direction: column;
-}
-
-.report--popup>.title {
- height: 2px;
- background: #d3d3d387;
- margin: 0 10px;
- display: flex;
- align-items: center;
- justify-content: center;
- flex-shrink: 0;
-}
-
-.popup-dark>.title {
- background: var(--dark-theme-secondary-color) !important;
-}
-
-.report--popup>.title>p {
- background: #f5f4f4;
- padding: 0 10px;
- font-family: roboto;
- font-weight: bold;
- letter-spacing: 1.2px;
- color: #255471;
- font-size: 20px;
-}
-
-.popup-dark>.title>p {
- background: #303263 !important;
- color: #3cbde5 !important;
-}
-
-.report--popup>form {
- display: flex;
- flex-direction: column;
- padding: 20px;
- padding-bottom: 0;
-}
-
-.report--popup>form label {
- color: #546884;
- margin-bottom: 8px;
- font-weight: 500;
- font-size: 18px;
-}
-
-.popup-dark>form label {
- color: white !important;
-}
-
-.report--popup>form input {
- padding: 11px 6px;
- border: none;
- border-left: 4px solid #546884;
- margin-bottom: 10px;
- border-radius: 2px;
- box-shadow: 0 3px 7px 1px rgb(0 0 0 / 10%);
- font-size: 16px;
-}
-
-.report--popup>form>button {
- border: none;
- padding: 8px;
- color: white;
- background: #43a82f;
- font-weight: bold;
- cursor: pointer;
- width: 120px;
- margin: auto;
- margin-top: 20px;
- font-size: 16px;
- border-radius: 4px;
-}
-
-.report--popup .spinner {
- width: 7px;
- height: 7px;
- display: inline-block;
- border-radius: 50%;
- margin-right: 10px;
- border: 3px solid white;
- animation: spinner-from 0.8s infinite linear alternate, spinner-to 1.6s infinite linear;
-}
-
-
-@keyframes spinner-from {
- 0% {
- clip-path: polygon(50% 50%, 0 0, 50% 0%, 50% 0%, 50% 0%, 50% 0%, 50% 0%);
- }
-
- 12.5% {
- clip-path: polygon(50% 50%, 0 0, 50% 0%, 100% 0%, 100% 0%, 100% 0%, 100% 0%);
- }
-
- 25% {
- clip-path: polygon(50% 50%, 0 0, 50% 0%, 100% 0%, 100% 100%, 100% 100%, 100% 100%);
- }
-
- 50% {
- clip-path: polygon(50% 50%, 0 0, 50% 0%, 100% 0%, 100% 100%, 50% 100%, 0% 100%);
- }
-
- 62.5% {
- clip-path: polygon(50% 50%, 100% 0, 100% 0%, 100% 0%, 100% 100%, 50% 100%, 0% 100%);
- }
-
- 75% {
- clip-path: polygon(50% 50%, 100% 100%, 100% 100%, 100% 100%, 100% 100%, 50% 100%, 0% 100%);
- }
-
- 100% {
- clip-path: polygon(50% 50%, 50% 100%, 50% 100%, 50% 100%, 50% 100%, 50% 100%, 0% 100%);
- }
-}
-
-@keyframes spinner-to {
- 0% {
- transform: scaleY(1) rotate(0deg);
- }
-
- 49.99% {
- transform: scaleY(1) rotate(135deg);
- }
-
- 50% {
- transform: scaleY(-1) rotate(0deg);
- }
-
- 100% {
- transform: scaleY(-1) rotate(-135deg);
- }
-}
diff --git a/public/components/views/home/report/report.html b/public/components/views/home/report/report.html
deleted file mode 100644
index 005c288b..00000000
--- a/public/components/views/home/report/report.html
+++ /dev/null
@@ -1,26 +0,0 @@
-
diff --git a/public/components/views/home/report/report.js b/public/components/views/home/report/report.js
index 48571b9a..6f88a3a7 100644
--- a/public/components/views/home/report/report.js
+++ b/public/components/views/home/report/report.js
@@ -1,55 +1,272 @@
+// Import Third-party Dependencies
+import { LitElement, html, css, nothing } from "lit";
+import { when } from "lit/directives/when.js";
-export class PopupReport {
- constructor(rootDependencyName) {
- this.rootDependencyName = rootDependencyName;
+// Import Internal Dependencies
+import { EVENTS } from "../../../../core/events.js";
+import { currentLang } from "../../../../common/utils.js";
+
+class PopupReport extends LitElement {
+ static styles = css`
+.report--popup {
+ min-width: 400px;
+ padding: 40px;
+ display: flex;
+ flex-direction: column;
+}
+
+.report--popup>.title {
+ height: 2px;
+ margin: 0 10px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ flex-shrink: 0;
+}
+
+
+.light >.title {
+ background: #d3d3d387;
+}
+.dark >.title {
+ background: var(--dark-theme-secondary-color);
+}
+
+.report--popup>.title>p {
+ padding: 0 10px;
+ font-family: roboto;
+ font-weight: bold;
+ letter-spacing: 1.2px;
+ font-size: 20px;
+}
+
+.dark .title>p {
+ background: #303263;
+ color: #3cbde5;
+}
+
+.light .title>p {
+ background: #f5f4f4;
+ color: #255471;
+}
+
+.report--popup>form {
+ display: flex;
+ flex-direction: column;
+ padding: 20px;
+ padding-bottom: 0;
+}
+
+.report--popup>form label {
+ margin-bottom: 8px;
+ font-weight: 500;
+ font-size: 18px;
+}
+
+.dark >form label {
+ color: white;
+}
+
+.light >form label {
+ color: #546884;
+}
+
+.report--popup>form input {
+ padding: 11px 6px;
+ border: none;
+ border-left: 4px solid #546884;
+ margin-bottom: 10px;
+ border-radius: 2px;
+ box-shadow: 0 3px 7px 1px rgb(0 0 0 / 10%);
+ font-size: 16px;
+}
+
+.report--popup>form>button {
+ border: none;
+ padding: 8px;
+ color: white;
+ background: #43a82f;
+ font-weight: bold;
+ cursor: pointer;
+ width: 120px;
+ margin: auto;
+ margin-top: 20px;
+ font-size: 16px;
+ border-radius: 4px;
+}
+
+.report--popup .spinner {
+ width: 7px;
+ height: 7px;
+ display: inline-block;
+ border-radius: 50%;
+ margin-right: 10px;
+ border: 3px solid white;
+ animation: spinner-from 0.8s infinite linear alternate, spinner-to 1.6s infinite linear;
+}
+
+
+@keyframes spinner-from {
+ 0% {
+ clip-path: polygon(50% 50%, 0 0, 50% 0%, 50% 0%, 50% 0%, 50% 0%, 50% 0%);
}
- render() {
- const templateElement = document.getElementById("report-popup-template");
- /** @type {HTMLElement} */
- const clone = templateElement.content.cloneNode(true);
- const form = clone.querySelector("form");
+ 12.5% {
+ clip-path: polygon(50% 50%, 0 0, 50% 0%, 100% 0%, 100% 0%, 100% 0%, 100% 0%);
+ }
+
+ 25% {
+ clip-path: polygon(50% 50%, 0 0, 50% 0%, 100% 0%, 100% 100%, 100% 100%, 100% 100%);
+ }
+
+ 50% {
+ clip-path: polygon(50% 50%, 0 0, 50% 0%, 100% 0%, 100% 100%, 50% 100%, 0% 100%);
+ }
+
+ 62.5% {
+ clip-path: polygon(50% 50%, 100% 0, 100% 0%, 100% 0%, 100% 100%, 50% 100%, 0% 100%);
+ }
+
+ 75% {
+ clip-path: polygon(50% 50%, 100% 100%, 100% 100%, 100% 100%, 100% 100%, 50% 100%, 0% 100%);
+ }
+
+ 100% {
+ clip-path: polygon(50% 50%, 50% 100%, 50% 100%, 50% 100%, 50% 100%, 50% 100%, 0% 100%);
+ }
+}
+
+@keyframes spinner-to {
+ 0% {
+ transform: scaleY(1) rotate(0deg);
+ }
+
+ 49.99% {
+ transform: scaleY(1) rotate(135deg);
+ }
+
+ 50% {
+ transform: scaleY(-1) rotate(0deg);
+ }
+
+ 100% {
+ transform: scaleY(-1) rotate(-135deg);
+ }
+}
+`;
+
+ static properties = {
+ theme: { type: String },
+ rootDependencyName: { type: String },
+ isLoading: { type: Boolean }
+ };
+
+ constructor() {
+ super();
+ this.isLoading = false;
+ this.settingsChanged = ({ detail: { theme } }) => {
+ if (theme !== this.theme) {
+ this.theme = theme;
+ }
+ };
+ }
+
+ connectedCallback() {
+ super.connectedCallback();
+ window.addEventListener(EVENTS.SETTINGS_SAVED, this.settingsChanged);
+ }
+
+ disconnectedCallback() {
+ window.removeEventListener(EVENTS.SETTINGS_SAVED, this.settingsChanged);
+ super.disconnectedCallback();
+ }
+
+ firstUpdated() {
const isLightPreference = window.matchMedia && window.matchMedia("(prefers-color-scheme: light)").matches;
+ if (isLightPreference) {
+ this.renderRoot.querySelector("#lightTheme").checked = true;
+ }
+ else {
+ this.renderRoot.querySelector("#darkTheme").checked = true;
+ }
+ }
+
+ render() {
+ const { popup: { report } } = window.i18n[currentLang()];
const defaultTitle = `${this.rootDependencyName}'s report`;
- form.querySelector("#lightTheme").checked = isLightPreference;
- form.querySelector("#darkTheme").checked = !isLightPreference;
- clone.querySelector("#title").placeholder = defaultTitle;
- form.addEventListener("submit", (e) => {
- e.preventDefault();
-
- form.querySelector(".spinner").classList.remove("hidden");
- const title = form.querySelector("#title").value || defaultTitle;
- const theme = form.querySelector("#lightTheme").checked ? "light" : "dark";
- const includesAllDeps = form.querySelector("#includesAllDeps").checked;
-
- fetch("/report", {
- method: "POST",
- body: JSON.stringify({
- title,
- includesAllDeps,
- theme
- }),
- headers: {
- "Content-Type": "application/json"
+
+ return html`
+
+ `;
}
+
+ handleSubmit = (e) => {
+ e.preventDefault();
+ if (this.isLoading) {
+ return;
+ }
+ this.isLoading = true;
+ const formData = new FormData(e.target);
+ const title = formData.get("title") || `${this.rootDependencyName} 's report`;
+ const theme = formData.get("theme");
+ const includesAllDeps = formData.get("includesAllDeps") === "includesAllDeps";
+
+ fetch("/report", {
+ method: "POST",
+ body: JSON.stringify({
+ title,
+ includesAllDeps,
+ theme
+ }),
+ headers: {
+ "Content-Type": "application/json"
+ }
+ }).then(async(response) => {
+ const { data: json } = await response.json();
+ const url = window.URL.createObjectURL(
+ new Blob(
+ [new Uint8Array(json.data).buffer], { type: "application/pdf" }
+ )
+ );
+ const link = document.createElement("a");
+ link.href = url;
+ link.target = "_blank";
+ link.download = `${title}.pdf`;
+ document.body.appendChild(link);
+ link.click();
+ }).finally(() => {
+ this.isLoading = false;
+ });
+ };
}
+
+customElements.define("popup-report", PopupReport);