Skip to content

Commit

Permalink
Merge branch 'development' of https://github.com/ubiquity/work.ubq.fi
Browse files Browse the repository at this point in the history
…into add-labels-to-preview
  • Loading branch information
zugdev committed Nov 3, 2024
2 parents e6bfd24 + 2334b9f commit c17c9fe
Show file tree
Hide file tree
Showing 16 changed files with 388 additions and 6,068 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ node_modules
.pnp.loader.mjs
static/dist
.env
.wrangler/

cypress/screenshots
cypress/videos
Binary file added bun.lockb
Binary file not shown.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
},
"scripts": {
"start": "wrangler pages dev --port 8080",
"watch": "tsx build/esbuild-server.ts",
"build": "tsx build/esbuild-build.ts",
"format": "run-s format:lint format:prettier format:cspell",
"format:lint": "eslint --fix .",
Expand Down
11 changes: 5 additions & 6 deletions src/home/authentication.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { trackReferralCode } from "./register-referral";
import { getGitHubAccessToken } from "./getters/get-github-access-token";
import { getGitHubUser } from "./getters/get-github-user";
import { GitHubUser } from "./github-types";
import { trackReferralCode } from "./register-referral";
import { displayGitHubUserInformation } from "./rendering/display-github-user-information";
import { renderGitHubLoginButton } from "./rendering/render-github-login-button";

Expand All @@ -11,14 +11,13 @@ export async function authentication() {
return;
}

const accessToken = await getGitHubAccessToken();
if (!accessToken) {
renderGitHubLoginButton();
}

const gitHubUser: null | GitHubUser = await getGitHubUser();
if (gitHubUser) {
await trackReferralCode();
await displayGitHubUserInformation(gitHubUser);
}
const accessToken = await getGitHubAccessToken();
if (!accessToken) {
renderGitHubLoginButton();
}
}
41 changes: 38 additions & 3 deletions src/home/fetch-github/fetch-and-display-previews.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { GitHubIssue } from "../github-types";
import { taskManager } from "../home";
import { applyAvatarsToIssues, renderGitHubIssues } from "../rendering/render-github-issues";
import { renderOrgHeaderLabel } from "../rendering/render-org-header";
import { closeModal } from "../rendering/render-preview-modal";
import { Sorting } from "../sorting/generate-sorting-buttons";
import { sortIssuesController } from "../sorting/sort-issues-controller";
Expand Down Expand Up @@ -45,12 +46,46 @@ function getProposalsOnlyFilter(getProposals: boolean) {
};
}

function filterIssuesByOrganization(issues: GitHubIssue[]): GitHubIssue[] {
// get organization name from first thing after / in URL
const pathSegments = window.location.pathname.split("/").filter(Boolean);
const urlOrgName = pathSegments.length > 0 ? pathSegments[0] : null;

// if there is no organization name in the URL, return all issues
if (!urlOrgName) return issues;

// filter issues by matching the URL organization name with the issue's organization name
const filteredIssues = issues.filter((issue) => {
const [issueOrgName] = issue.repository_url.split("/").slice(-2);
return issueOrgName === urlOrgName;
});

// if no issues match the organization, redirect to home
if (filteredIssues.length === 0) {
console.log(`No issues found for organization "${urlOrgName}". Redirecting to the home page.`);
window.location.href = "/";
}

renderOrgHeaderLabel(urlOrgName);

return filteredIssues;
}

// checks the cache's integrity, sorts issues, checks Directory/Proposals toggle, renders them and applies avatars
export async function displayGitHubIssues(sorting?: Sorting, options = { ordering: "normal" }) {
export async function displayGitHubIssues({
sorting,
options = { ordering: "normal" },
skipAnimation = false,
}: {
sorting?: Sorting;
options?: { ordering: string };
skipAnimation?: boolean;
} = {}) {
await checkCacheIntegrityAndSyncTasks();
const cachedTasks = taskManager.getTasks();
const sortedIssues = sortIssuesController(cachedTasks, sorting, options);
const sortedAndFiltered = sortedIssues.filter(getProposalsOnlyFilter(isProposalOnlyViewer));
renderGitHubIssues(sortedAndFiltered);
let sortedAndFiltered = sortedIssues.filter(getProposalsOnlyFilter(isProposalOnlyViewer));
sortedAndFiltered = filterIssuesByOrganization(sortedAndFiltered);
renderGitHubIssues(sortedAndFiltered, skipAnimation);
applyAvatarsToIssues();
}
8 changes: 6 additions & 2 deletions src/home/fetch-github/fetch-issues-full.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,13 @@ export async function postLoadUpdateIssues() {
const fetchedIssues = await fetchIssues();

if (issuesAreDifferent(cachedIssues, fetchedIssues)) {
await saveIssuesToCache(cachedIssues, fetchedIssues);
await saveIssuesToCache(cachedIssues, fetchedIssues); // this handles stale and new issues
await taskManager.syncTasks();
void displayGitHubIssues();
if (cachedIssues.length === 0) {
void displayGitHubIssues(); // if it's first time loading keep animation
} else {
void displayGitHubIssues({ skipAnimation: true }); // if there were cached issues skip animation
}
}
} catch (error) {
console.error("Error updating issues cache", error);
Expand Down
8 changes: 4 additions & 4 deletions src/home/rendering/display-github-user-information.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { isOrgMemberWithoutScope } from "../getters/get-github-access-token";
import { GitHubUser } from "../github-types";
import { renderErrorInModal } from "./display-popup-modal";
import { getSupabase, renderAugmentAccessButton, authenticationElement } from "./render-github-login-button";
import { toolbar } from "../ready-toolbar";
import { renderErrorInModal } from "./display-popup-modal";
import { authenticationElement, getSupabase, renderAugmentAccessButton } from "./render-github-login-button";

export async function displayGitHubUserInformation(gitHubUser: GitHubUser) {
const authenticatedDivElement = document.createElement("div");
Expand All @@ -18,14 +18,14 @@ export async function displayGitHubUserInformation(gitHubUser: GitHubUser) {
img.classList.add("github-avatar-default");
}
img.alt = gitHubUser.login;
authenticatedDivElement.appendChild(img);

const divNameElement = document.createElement("div");

// Falls back to login because the name is not required for a GitHub user
divNameElement.textContent = gitHubUser.name || gitHubUser.login;
divNameElement.classList.add("full");
authenticatedDivElement.appendChild(divNameElement);
authenticatedDivElement.appendChild(img);

authenticatedDivElement.addEventListener("click", async function signOut() {
const supabase = getSupabase();
Expand All @@ -34,7 +34,7 @@ export async function displayGitHubUserInformation(gitHubUser: GitHubUser) {
renderErrorInModal(error, "Error logging out");
alert("Error logging out");
}
window.location.reload();
window.location.replace("/");
});

if (await isOrgMemberWithoutScope()) {
Expand Down
19 changes: 9 additions & 10 deletions src/home/rendering/render-github-issues.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { setupKeyboardNavigation } from "./setup-keyboard-navigation";
import { isProposalOnlyViewer } from "../fetch-github/fetch-and-display-previews";
import { waitForElement } from "./utils";

export function renderGitHubIssues(tasks: GitHubIssue[]) {
export function renderGitHubIssues(tasks: GitHubIssue[], skipAnimation: boolean) {
const container = taskManager.getContainer();
if (container.classList.contains("ready")) {
container.classList.remove("ready");
Expand All @@ -23,8 +23,12 @@ export function renderGitHubIssues(tasks: GitHubIssue[]) {
if (!existingIssueIds.has(task.id.toString())) {
const issueWrapper = everyNewIssue({ gitHubIssue: task, container });
if (issueWrapper) {
setTimeout(() => issueWrapper.classList.add("active"), delay);
delay += baseDelay;
if (skipAnimation) {
issueWrapper.classList.add("active");
} else {
setTimeout(() => issueWrapper.classList.add("active"), delay);
delay += baseDelay;
}
}
}
}
Expand Down Expand Up @@ -196,8 +200,8 @@ function updateUrlWithIssueId(issueID: number) {
newURL.searchParams.set("proposal", "true");
}

// Push to history
window.history.pushState({ issueID }, "", newURL.toString());
// Set issue in URL
window.history.replaceState({ issueID }, "", newURL.toString());
}

// Opens the preview modal if a URL contains an issueID
Expand Down Expand Up @@ -225,11 +229,6 @@ export function loadIssueFromUrl() {
void viewIssueDetails(issue);
}

// This ensure previews load for the URL
window.addEventListener("popstate", () => {
location.reload();
});

export function applyAvatarsToIssues() {
const container = taskManager.getContainer();
const issueElements = Array.from(container.querySelectorAll(".issue-element-inner"));
Expand Down
28 changes: 28 additions & 0 deletions src/home/rendering/render-org-header.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { organizationImageCache } from "../fetch-github/fetch-issues-full";

export function renderOrgHeaderLabel(orgName: string): void {
const brandingDiv = document.getElementById("branding");
if (!brandingDiv) return;

// Fetch the organization logo from the cache
const logoBlob = organizationImageCache.get(orgName);

if (logoBlob) {
// Convert Blob to a URL
const logoUrl = URL.createObjectURL(logoBlob);

const img = document.createElement("img");
img.src = logoUrl;
img.alt = `${orgName} Logo`;
console.log("oi");
img.id = "logo";

// Replace the existing SVG with the new image
const svgLogo = brandingDiv.querySelector("svg#logo");
if (svgLogo) brandingDiv.replaceChild(img, svgLogo);
}

// Update the organization name inside the span with class 'full'
const orgNameSpan = brandingDiv.querySelector("span.full");
if (orgNameSpan) orgNameSpan.textContent = `${orgName} | `;
}
42 changes: 6 additions & 36 deletions src/home/rendering/render-preview-modal.ts
Original file line number Diff line number Diff line change
@@ -1,41 +1,11 @@
export const modal = document.createElement("div");
modal.classList.add("preview");
const modalContent = document.createElement("div");
modalContent.classList.add("preview-content");
const modalHeader = document.createElement("div");
modalHeader.classList.add("preview-header");
export const titleAnchor = document.createElement("a");
titleAnchor.setAttribute("target", "_blank");
export const titleHeader = document.createElement("h1");
const closeButton = document.createElement("button");
closeButton.classList.add("close-preview");
closeButton.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="m336-280-56-56 144-144-144-143 56-56 144 144 143-144 56 56-144 143 144 144-56 56-143-144-144 144Z"/></svg>`;
const modalBody = document.createElement("div");
modalBody.classList.add("preview-body");
export const modalBodyInner = document.createElement("div");
modalBodyInner.classList.add("preview-body-inner");
modalHeader.appendChild(closeButton);
titleAnchor.appendChild(titleHeader);
const openNewLinkIcon = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M200-120q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h280v80H200v560h560v-280h80v280q0 33-23.5 56.5T760-120H200Zm188-212-56-56 372-372H560v-80h280v280h-80v-144L388-332Z"/></svg>`;
const openNewLink = document.createElement("span");
openNewLink.classList.add("open-new-link");
openNewLink.innerHTML = openNewLinkIcon;

const errorIcon = `<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#808080"><path d="M109-120q-11 0-20-5.5T75-140q-5-9-5.5-19.5T75-180l370-640q6-10 15.5-15t19.5-5q10 0 19.5 5t15.5 15l370 640q6 10 5.5 20.5T885-140q-5 9-14 14.5t-20 5.5H109Zm69-80h604L480-720 178-200Zm302-40q17 0 28.5-11.5T520-280q0-17-11.5-28.5T480-320q-17 0-28.5 11.5T440-280q0 17 11.5 28.5T480-240Zm0-120q17 0 28.5-11.5T520-400v-120q0-17-11.5-28.5T480-560q-17 0-28.5 11.5T440-520v120q0 17 11.5 28.5T480-360Zm0-100Z"/></svg>`;
const error = document.createElement("span");
error.classList.add("error");
error.innerHTML = errorIcon;

titleAnchor.appendChild(error);
titleAnchor.appendChild(openNewLink);
modalHeader.appendChild(titleAnchor);
modalBody.appendChild(modalBodyInner);
modalContent.appendChild(modalHeader);
modalContent.appendChild(modalBody);
modal.appendChild(modalContent);
document.body.appendChild(modal);
export const modal = document.getElementById("preview-modal") as HTMLDivElement;
export const titleAnchor = document.getElementById("preview-title-anchor") as HTMLAnchorElement;
export const titleHeader = document.getElementById("preview-title") as HTMLHeadingElement;
export const modalBodyInner = document.getElementById("preview-body-inner") as HTMLDivElement;
export const issuesContainer = document.getElementById("issues-container");

const closeButton = modal.querySelector(".close-preview") as HTMLButtonElement;

closeButton.addEventListener("click", closeModal);
document.addEventListener("keydown", (event) => {
if (event.key === "Escape") {
Expand Down
10 changes: 5 additions & 5 deletions src/home/sorting/sorting-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@ export class SortingManager {
}

public render() {
this._toolBarFilters.appendChild(this._sortingButtons);
this._toolBarFilters.appendChild(this._filterTextBox);
this._toolBarFilters.appendChild(this._sortingButtons);
}

private _generateFilterTextBox() {
const textBox = document.createElement("input");
textBox.type = "text";
textBox.id = `filter-${this._instanceId}`;
textBox.placeholder = "Text Filter";
textBox.placeholder = "Search";

// Handle CTRL+F
document.addEventListener("keydown", (event) => {
Expand All @@ -51,7 +51,7 @@ export class SortingManager {

const issuesContainer = document.getElementById("issues-container") as HTMLDivElement;

const filterIssues = () => {
function filterIssues() {
try {
const filterText = textBox.value.toLowerCase();
const issues = Array.from(issuesContainer.children) as HTMLDivElement[];
Expand All @@ -69,7 +69,7 @@ export class SortingManager {
} catch (error) {
return renderErrorInModal(error as Error);
}
};
}

// Observer to detect when children are added to the issues container (only once)
const observer = new MutationObserver(() => {
Expand Down Expand Up @@ -163,7 +163,7 @@ export class SortingManager {

// Apply the sorting based on the new state (normal or reverse)
try {
void displayGitHubIssues(option as Sorting, { ordering: newOrdering });
void displayGitHubIssues({ sorting: option as Sorting, options: { ordering: newOrdering } });
} catch (error) {
renderErrorCatch(error as ErrorEvent);
}
Expand Down
31 changes: 31 additions & 0 deletions static/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,37 @@
><div id="filters" class="filters-container"></div>
<div id="authentication"></div>
</div>
<div id="preview-modal" class="preview">
<div class="preview-content">
<div class="preview-header">
<button class="close-preview">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960">
<path d="m336-280-56-56 144-144-144-143 56-56 144 144 143-144 56 56-144 143 144 144-56 56-143-144-144 144Z" />
</svg>
</button>
<a id="preview-title-anchor" target="_blank">
<h1 id="preview-title"></h1>
<span class="error">
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#808080">
<path
d="M109-120q-11 0-20-5.5T75-140q-5-9-5.5-19.5T75-180l370-640q6-10 15.5-15t19.5-5q10 0 19.5 5t15.5 15l370 640q6 10 5.5 20.5T885-140q-5 9-14 14.5t-20 5.5H109Zm69-80h604L480-720 178-200Zm302-40q17 0 28.5-11.5T520-280q0-17-11.5-28.5T480-320q-17 0-28.5 11.5T440-280q0 17 11.5 28.5T480-240Zm0-120q17 0 28.5-11.5T520-400v-120q0-17-11.5-28.5T480-560q-17 0-28.5 11.5T440-520v120q0 17 11.5 28.5T480-360Zm0-100Z"
/>
</svg>
</span>
<span class="open-new-link">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960">
<path
d="M200-120q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h280v80H200v560h560v-280h80v280q0 33-23.5 56.5T760-120H200Zm188-212-56-56 372-372H560v-80h280v280h-80v-144L388-332Z"
/>
</svg>
</span>
</a>
</div>
<div class="preview-body">
<div id="preview-body-inner" class="preview-body-inner"></div>
</div>
</div>
</div>
<div id="bottom-bar" class="toolbar"
><div id="mobile-modal-scrub"><button id="scrub-left">&lsaquo;</button><button id="scrub-right">&rsaquo;</button></div
><div id="filters-bottom" class="filters-container"></div
Expand Down
Loading

0 comments on commit c17c9fe

Please sign in to comment.