diff --git a/src/home/rendering/render-github-issues.ts b/src/home/rendering/render-github-issues.ts
index c4073a92..fb175ca7 100644
--- a/src/home/rendering/render-github-issues.ts
+++ b/src/home/rendering/render-github-issues.ts
@@ -6,6 +6,8 @@ import { getLocalStore } from "../getters/get-local-store";
import { AvatarCache } from "../github-types";
import { issuesContainer, preview, previewBodyInner, titleAnchor, titleHeader } from "./render-preview-modal";
+const openNewLinkIcon = ``;
+
export function renderGitHubIssues(container: HTMLDivElement, issues: GitHubIssueWithNewFlag[]) {
if (container.classList.contains("ready")) {
container.classList.remove("ready");
@@ -20,129 +22,147 @@ export function renderGitHubIssues(container: HTMLDivElement, issues: GitHubIssu
for (const issue of issues) {
if (!existingIssueIds.has(issue.id.toString())) {
- const issueWrapper = document.createElement("div");
- const issueElement = document.createElement("div");
- issueElement.setAttribute("data-issue-id", issue.id.toString());
-
- if (issue.isNew) {
- issueWrapper.classList.add("new-issue");
- }
- issueElement.classList.add("issue-element-inner");
+ const issueWrapper = everyNewIssue({ issue, avatarCache, fetchInProgress, container });
setTimeout(() => issueWrapper.classList.add("active"), delay);
-
delay += baseDelay;
+ }
+ }
+ container.classList.add("ready");
+}
- const urlRegex = /(https?:\/\/[^\s]+)/g;
- const mirrorUrls = issue.body.match(urlRegex);
-
- const urlPattern = /https:\/\/github\.com\/([^/]+)\/([^/]+)\//;
- const match = mirrorUrls?.shift()?.match(urlPattern);
- const organizationName = match?.[1];
- const repositoryName = match?.[2];
-
- type LabelKey = "Pricing: " | "Time: " | "Priority: ";
-
- const labelOrder: Record = { "Pricing: ": 1, "Time: ": 2, "Priority: ": 3 };
-
- issue.labels.sort((a, b) => {
- const matchA = a.name.match(/^(Pricing|Time|Priority): /)?.[0] as LabelKey | undefined;
- const matchB = b.name.match(/^(Pricing|Time|Priority): /)?.[0] as LabelKey | undefined;
- const orderA = matchA ? labelOrder[matchA] : 0;
- const orderB = matchB ? labelOrder[matchB] : 0;
- return orderA - orderB;
- });
-
- // Filter labels that begin with specific prefixes
- const filteredLabels = issue.labels.filter((label) => {
- return label.name.startsWith("Time: ") || label.name.startsWith("Pricing: ") || label.name.startsWith("Priority: ");
- });
-
- // Map the filtered labels to HTML elements
- const labels = filteredLabels.map((label) => {
- // Remove the prefix from the label name
- const name = label.name.replace(/(Time|Pricing|Priority): /, "");
- if (label.name.startsWith("Pricing: ")) {
- return ``;
- } else {
- return ``;
- }
- });
+function everyNewIssue({
+ issue,
+ avatarCache,
+ fetchInProgress,
+ container,
+}: {
+ issue: GitHubIssueWithNewFlag;
+ avatarCache: AvatarCache;
+ fetchInProgress: Set;
+ container: HTMLDivElement;
+}) {
+ const issueWrapper = document.createElement("div");
+ const issueElement = document.createElement("div");
+ issueElement.setAttribute("data-issue-id", issue.id.toString());
+ issueElement.classList.add("issue-element-inner");
+
+ if (issue.isNew) {
+ issueWrapper.classList.add("new-issue");
+ }
- const openNewLinkIcon = ``;
+ const urlPattern = /https:\/\/github\.com\/([^/]+)\/([^/]+)\//;
+ const match = issue.body.match(urlPattern);
+ const organizationName = match?.[1];
+ const repositoryName = match?.[2];
+ const labels = parseAndGenerateLabels(issue);
+ setUpIssueElement(issueElement, issue, organizationName, repositoryName, labels, match);
+ issueWrapper.appendChild(issueElement);
+
+ // Set the issueWrapper background-image to the organization's avatar
+ if (organizationName) {
+ organizationAvatar(avatarCache, organizationName, issueElement, fetchInProgress);
+ }
+ container.appendChild(issueWrapper);
+ return issueWrapper;
+}
- issueElement.innerHTML = `
+function setUpIssueElement(
+ issueElement: HTMLDivElement,
+ issue: GitHubIssueWithNewFlag,
+ organizationName: string | undefined,
+ repositoryName: string | undefined,
+ labels: string[],
+ match: RegExpMatchArray | null
+) {
+ issueElement.innerHTML = `
${openNewLinkIcon}${
issue.title
}
${organizationName}
${repositoryName}
${labels.join(
""
)}
`;
- issueElement.addEventListener("click", function () {
- const previewId = Number(this.getAttribute("data-issue-id"));
- console.trace({ mapping, previewId });
- const full = mapping.get(previewId);
- if (!full) {
- window.open(match?.input, "_blank");
- } else {
- previewIssue(issue);
- }
- });
-
- issueWrapper.appendChild(issueElement);
+ issueElement.addEventListener("click", function () {
+ const previewId = Number(this.getAttribute("data-issue-id"));
+ console.trace({ mapping, previewId });
+ const full = mapping.get(previewId);
+ if (!full) {
+ window.open(match?.input, "_blank");
+ } else {
+ previewIssue(issue);
+ }
+ });
+}
- // Set the issueWrapper background-image to the organization's avatar
- if (organizationName) {
- const cachedAvatar = avatarCache[organizationName];
- const image = issueElement.querySelector("img") as HTMLImageElement;
- if (cachedAvatar) {
- image.src = cachedAvatar;
- } else if (!fetchInProgress.has(organizationName)) {
- // Mark this organization's avatar as being fetched
- fetchInProgress.add(organizationName);
+function parseAndGenerateLabels(issue: GitHubIssueWithNewFlag) {
+ type LabelKey = "Pricing: " | "Time: " | "Priority: ";
+
+ const labelOrder: Record = { "Pricing: ": 1, "Time: ": 2, "Priority: ": 3 };
+
+ issue.labels.sort((a, b) => {
+ const matchA = a.name.match(/^(Pricing|Time|Priority): /)?.[0] as LabelKey | undefined;
+ const matchB = b.name.match(/^(Pricing|Time|Priority): /)?.[0] as LabelKey | undefined;
+ const orderA = matchA ? labelOrder[matchA] : 0;
+ const orderB = matchB ? labelOrder[matchB] : 0;
+ return orderA - orderB;
+ });
+
+ // Filter labels that begin with specific prefixes
+ const filteredLabels = issue.labels.filter((label) => {
+ return label.name.startsWith("Time: ") || label.name.startsWith("Pricing: ") || label.name.startsWith("Priority: ");
+ });
+
+ // Map the filtered labels to HTML elements
+ const labels = filteredLabels.map((label) => {
+ // Remove the prefix from the label name
+ const name = label.name.replace(/(Time|Pricing|Priority): /, "");
+ if (label.name.startsWith("Pricing: ")) {
+ return ``;
+ } else {
+ return ``;
+ }
+ });
+ return labels;
+}
- // Update the avatarCache synchronously here
- avatarCache[organizationName] = null; // Placeholder value to indicate fetch in progress
+function organizationAvatar(avatarCache: AvatarCache, organizationName: string, issueElement: HTMLDivElement, fetchInProgress: Set) {
+ const cachedAvatar = avatarCache[organizationName];
+ const image = issueElement.querySelector("img") as HTMLImageElement;
+ if (cachedAvatar) {
+ image.src = cachedAvatar;
+ } else if (!fetchInProgress.has(organizationName)) {
+ // Mark this organization's avatar as being fetched
+ fetchInProgress.add(organizationName);
+
+ // Update the avatarCache synchronously here
+ avatarCache[organizationName] = null; // Placeholder value to indicate fetch in progress
+ localStorage.setItem("avatarCache", JSON.stringify(avatarCache));
+
+ fetch(`https://api.github.com/orgs/${organizationName}`)
+ .then((response) => response.json())
+ .then((data) => {
+ if (data && data.avatar_url) {
+ avatarCache[organizationName] = data.avatar_url;
localStorage.setItem("avatarCache", JSON.stringify(avatarCache));
-
- fetch(`https://api.github.com/orgs/${organizationName}`)
- .then((response) => response.json())
- .then((data) => {
- if (data && data.avatar_url) {
- avatarCache[organizationName] = data.avatar_url;
- localStorage.setItem("avatarCache", JSON.stringify(avatarCache));
- if (data.avatar_url) {
- image.src = data.avatar_url;
- }
- }
- })
- .catch((error) => {
- console.error("Error fetching avatar:", error);
- })
- .finally(() => {
- // Fetch is complete, remove from the in-progress set
- fetchInProgress.delete(organizationName);
- });
+ if (data.avatar_url) {
+ updateImageSrc(image, data.avatar_url);
+ }
}
- }
- container.appendChild(issueWrapper);
- }
+ })
+ .catch((error) => {
+ console.error("Error fetching avatar:", error);
+ })
+ .finally(() => {
+ // Fetch is complete, remove from the in-progress set
+ fetchInProgress.delete(organizationName);
+ });
}
- container.classList.add("ready");
}
// Function to update and show the preview
function previewIssue(issuePreview: GitHubIssueWithNewFlag) {
- // const issuesFull = mapping;
const issueFull = mapping.get(issuePreview.id);
- // const issuePreviewUrl = issuePreview.body.match(/https:\/\/github\.com\/[^/]+\/[^/]+\/issues\/\d+/)?.[0];
- // if (!issuePreviewUrl) {
- // throw new Error("Issue preview URL not found");
- // }
-
- // const issueFull = findIssueByUrl(issuesFull, issuePreviewUrl);
if (!issueFull) {
- // console.trace({ issuePreviewUrl, issuesFull });
throw new Error("Issue not found");
}
@@ -156,8 +176,6 @@ function previewIssue(issuePreview: GitHubIssueWithNewFlag) {
issuesContainer?.classList.add("preview-active");
}
-// Function to find an issue by URL
-// function findIssueByUrl(issues: GitHubIssue[], url: string) {
-// console.trace({ issues, url });
-// return issues.find((issue) => issue.html_url === url);
-// }
+function updateImageSrc(imageElement: HTMLImageElement, src: string) {
+ imageElement.src = src;
+}