From 5ea00a880fcdf9f26323a8f5818a73531304aa30 Mon Sep 17 00:00:00 2001 From: Leandro Palazzolo Date: Fri, 2 Feb 2024 19:08:47 -0300 Subject: [PATCH 1/5] fix: get icon url from json instead of notion (WIP) --- components/table/table.tsx | 14 +++++++++++++- next.config.js | 6 +++++- types/filters.ts | 2 ++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/components/table/table.tsx b/components/table/table.tsx index a638ad8..a7ea8d0 100644 --- a/components/table/table.tsx +++ b/components/table/table.tsx @@ -16,6 +16,7 @@ import { ExternalLink, Content, Time, Project } from "./row"; import { useContributions } from "@/hooks/useContributions"; import { KudosQueryParameters } from "@/lib/notion/types"; import dynamic from "next/dynamic"; +import { useFilters } from "@/contexts/filters"; const Labels = dynamic(() => import("./row").then((m) => m.Labels), { ssr: false, }); @@ -38,6 +39,8 @@ export const Table = ({ items, queries = {} }: ITableProps) => { { name: "ACTIONS", uid: "actions" }, ]); + const { filterOptions } = useFilters(); + const { data: results, fetchNextPage, @@ -57,12 +60,21 @@ export const Table = ({ items, queries = {} }: ITableProps) => { const renderCell = React.useCallback( (item: Contribution, columnKey: React.Key) => { const cellValue = item[columnKey as keyof Contribution]; + // TODO: this is slow and repetitive. + // 1. Instead of filters, create a map of repo => icon url + // 2. Create a helper function that receives the the issue id, extracts the main url + // and returns the icon url + const avatar = + filterOptions.repositories.find((repo) => + item.url.startsWith(repo.repository_url!), + )?.icon || null; + console.log(avatar, item.url); switch (columnKey) { case "project": return ( Date: Mon, 5 Feb 2024 09:44:06 -0300 Subject: [PATCH 2/5] refactor: getting icon from an issue url --- components/table/table.tsx | 48 +++++++++++++++++++++++++++++--------- utils/github.ts | 12 ++++++++++ 2 files changed, 49 insertions(+), 11 deletions(-) diff --git a/components/table/table.tsx b/components/table/table.tsx index a7ea8d0..3209874 100644 --- a/components/table/table.tsx +++ b/components/table/table.tsx @@ -1,5 +1,11 @@ "use client"; -import React, { useCallback, useEffect, useRef, useState } from "react"; +import React, { + useCallback, + useEffect, + useMemo, + useRef, + useState, +} from "react"; import { useMediaQuery } from "react-responsive"; import { Table as NuiTable, @@ -17,6 +23,7 @@ import { useContributions } from "@/hooks/useContributions"; import { KudosQueryParameters } from "@/lib/notion/types"; import dynamic from "next/dynamic"; import { useFilters } from "@/contexts/filters"; +import { extractRepositoryUrlFromIssue } from "@/utils/github"; const Labels = dynamic(() => import("./row").then((m) => m.Labels), { ssr: false, }); @@ -30,6 +37,11 @@ interface ITableProps { items: PaginatedContributions; queries?: Partial; } + +interface RepositoryMap { + [key: string]: string; +} + export const Table = ({ items, queries = {} }: ITableProps) => { const [columns, setColumns] = useState([ { name: "PROJECT", uid: "project" }, @@ -57,19 +69,33 @@ export const Table = ({ items, queries = {} }: ITableProps) => { return results?.pages.flatMap((page) => page.data) || []; }, [results]); + const repositoryIconMap: RepositoryMap = useMemo(() => { + const map: RepositoryMap = {}; + filterOptions.repositories.forEach((repository) => { + if (repository.repository_url && repository.icon) { + map[repository.repository_url] = repository.icon; + } + }); + return map; + }, [filterOptions.repositories]); + const useGetIconByRepositoryUrl = (repositoryIconMap: RepositoryMap) => { + const getIconByRepositoryUrl = useCallback( + (repositoryUrl: string): string | null => { + return repositoryIconMap[repositoryUrl]; + }, + [repositoryIconMap], + ); + + return getIconByRepositoryUrl; + }; + + const getIconByRepositoryUrl = useGetIconByRepositoryUrl(repositoryIconMap); + const renderCell = React.useCallback( (item: Contribution, columnKey: React.Key) => { const cellValue = item[columnKey as keyof Contribution]; - // TODO: this is slow and repetitive. - // 1. Instead of filters, create a map of repo => icon url - // 2. Create a helper function that receives the the issue id, extracts the main url - // and returns the icon url - const avatar = - filterOptions.repositories.find((repo) => - item.url.startsWith(repo.repository_url!), - )?.icon || null; - - console.log(avatar, item.url); + const repository = extractRepositoryUrlFromIssue(item.url); + const avatar = !!repository ? getIconByRepositoryUrl(repository) : null; switch (columnKey) { case "project": return ( diff --git a/utils/github.ts b/utils/github.ts index 1b1ab2c..dcbb73e 100644 --- a/utils/github.ts +++ b/utils/github.ts @@ -24,3 +24,15 @@ export const getProjectUrls = (organization: string, repository?: string) => { : undefined, }; }; +export const extractRepositoryUrlFromIssue = ( + issueUrl: string, +): string | null => { + // Regex pattern to match the repository URL in the issue URL + const regex = /(https:\/\/github\.com\/[^/]+\/[^/]+)\/issues\/\d+/; + + // Use the regex pattern to extract the repository URL + const match = issueUrl.match(regex); + + // If a match is found, return the repository URL, otherwise, return null + return match ? match[1] : null; +}; From 4253132b9f448792b3edea288dd98835bea6aedb Mon Sep 17 00:00:00 2001 From: Leandro Palazzolo Date: Tue, 6 Feb 2024 12:57:20 -0300 Subject: [PATCH 3/5] feat: use custom logo for polkadot --- components/table/table.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/components/table/table.tsx b/components/table/table.tsx index ff730f6..7398358 100644 --- a/components/table/table.tsx +++ b/components/table/table.tsx @@ -72,7 +72,11 @@ export const Table = ({ items, queries = {} }: ITableProps) => { const repositoryIconMap: RepositoryMap = useMemo(() => { const map: RepositoryMap = {}; filterOptions.repositories.forEach((repository) => { - map[repository.repository_url] = repository.icon; + map[repository.repository_url] = repository.repository_url + .toLowerCase() + .includes("polkadot") + ? "/images/polkadot-logo.png" + : repository.icon; }); return map; }, [filterOptions.repositories]); From adbc884746434b72305d55e2f3304dd14d569a2f Mon Sep 17 00:00:00 2001 From: Leandro Palazzolo Date: Tue, 6 Feb 2024 13:05:13 -0300 Subject: [PATCH 4/5] refactor: remove avatar from contribution --- app/explore/[slug]/page.tsx | 5 +---- app/page.tsx | 5 +---- hooks/useContributions.tsx | 5 +---- types/contribution.ts | 1 - utils/github.ts | 19 ------------------- utils/notion.ts | 5 +---- 6 files changed, 4 insertions(+), 36 deletions(-) diff --git a/app/explore/[slug]/page.tsx b/app/explore/[slug]/page.tsx index f145388..c857e86 100644 --- a/app/explore/[slug]/page.tsx +++ b/app/explore/[slug]/page.tsx @@ -35,10 +35,7 @@ export default async function ExplorePage({ params }: IProps) { page_size: DEFAULT_PAGE_SIZE, filter: queryFilter, }); - const contributions = transformNotionDataToContributions( - data, - filterOptions.repositories, - ); + const contributions = transformNotionDataToContributions(data); const items: PaginatedCustomDataResponse = { data: contributions, hasMore: data.has_more, diff --git a/app/page.tsx b/app/page.tsx index 1d75952..eba5c8f 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -13,10 +13,7 @@ export default async function Home() { const data = await queryDatabase({ page_size: DEFAULT_PAGE_SIZE, }); - const contributions = transformNotionDataToContributions( - data, - filterOptions.repositories, - ); + const contributions = transformNotionDataToContributions(data); const items: PaginatedCustomDataResponse = { data: contributions, hasMore: data.has_more, diff --git a/hooks/useContributions.tsx b/hooks/useContributions.tsx index f5633e2..b4fa155 100644 --- a/hooks/useContributions.tsx +++ b/hooks/useContributions.tsx @@ -32,10 +32,7 @@ export const useContributions = ( start_cursor: next_cursor, }); return { - data: transformNotionDataToContributions( - response, - filterOptions.repositories, - ), + data: transformNotionDataToContributions(response), hasMore: response.has_more, nextCursor: response.next_cursor ?? undefined, }; diff --git a/types/contribution.ts b/types/contribution.ts index 830e4ad..5fc7e46 100644 --- a/types/contribution.ts +++ b/types/contribution.ts @@ -2,7 +2,6 @@ import { PaginatedCustomDataResponse } from "."; export type Contribution = { id: number; - avatar: string | null; labels: string[]; languages: string[]; project: string; diff --git a/utils/github.ts b/utils/github.ts index d290b7d..266ea99 100644 --- a/utils/github.ts +++ b/utils/github.ts @@ -1,22 +1,3 @@ -import { Repository } from "@/types/filters"; - -export function getImagePath( - githubUrl: string, - repositories: Repository[], -): string | null { - const lowerCaseGithubUrl = githubUrl.toLowerCase(); - - if (lowerCaseGithubUrl.includes("polkadot")) { - return "/images/polkadot-logo.png"; - } - - const repository = repositories.find( - ({ repository_url }) => repository_url.toLowerCase() === lowerCaseGithubUrl, - ); - - return repository?.icon ?? null; -} - export const getProjectUrls = (organization: string, repository?: string) => { return { organizationUrl: `https://github.com/${organization}`, diff --git a/utils/notion.ts b/utils/notion.ts index 839c97f..152bde4 100644 --- a/utils/notion.ts +++ b/utils/notion.ts @@ -1,6 +1,5 @@ import { QueryDatabaseResponse } from "@notionhq/client/build/src/api-endpoints"; import { Contribution } from "@/types/contribution"; -import { getImagePath } from "./github"; import { GOOD_FIRST_ISSUE_KEY, GOOD_FIRST_ISSUE_LABELS, @@ -8,11 +7,10 @@ import { LANGUAGES_KEY, PROJECTS_KEY, } from "@/data/filters"; -import { FilterOption, Filters, Repository } from "@/types/filters"; +import { FilterOption, Filters } from "@/types/filters"; export function transformNotionDataToContributions( notionData: QueryDatabaseResponse, - repositoriesData: Repository[], ): Contribution[] { return notionData.results.reduce((acc: Contribution[], currentItem: any) => { const properties = currentItem.properties; @@ -23,7 +21,6 @@ export function transformNotionDataToContributions( const organization = urlElements.pop(); const contribution: Contribution = { id, - avatar: getImagePath(avatarKey, repositoriesData), labels: properties["Issue Labels"].multi_select.map( (label: any) => label.name, ), From 9c7422d32d712061522b8ccc10949659cc8fe8c3 Mon Sep 17 00:00:00 2001 From: Leandro Palazzolo Date: Tue, 6 Feb 2024 13:08:20 -0300 Subject: [PATCH 5/5] chore: add missing dependency --- components/table/table.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/table/table.tsx b/components/table/table.tsx index 7398358..e7388b9 100644 --- a/components/table/table.tsx +++ b/components/table/table.tsx @@ -149,7 +149,7 @@ export const Table = ({ items, queries = {} }: ITableProps) => { return cellValue; } }, - [], + [getIconByRepositoryUrl], ); const handleScroll = useCallback(() => {