diff --git a/packages/docusaurus-playground/src/pages/index.mdx b/packages/docusaurus-playground/src/pages/index.mdx index 8572ad2..79c7d8b 100644 --- a/packages/docusaurus-playground/src/pages/index.mdx +++ b/packages/docusaurus-playground/src/pages/index.mdx @@ -19,6 +19,7 @@ import { TimelineItem, ShowcaseCard, JobsPerDepartment, + GithubChallenges, } from '../components/mdx' import * as jobData from '/generated/jobs.json' @@ -355,3 +356,4 @@ import * as jobData from '/generated/jobs.json' + diff --git a/packages/logos-docusaurus-theme/src/client/components/mdx/GithubChallenges/GithubChallenges.scss b/packages/logos-docusaurus-theme/src/client/components/mdx/GithubChallenges/GithubChallenges.scss new file mode 100644 index 0000000..f7116a3 --- /dev/null +++ b/packages/logos-docusaurus-theme/src/client/components/mdx/GithubChallenges/GithubChallenges.scss @@ -0,0 +1,89 @@ +@use '../../../css/utils'; +@use '../../../css/lsd'; + +.mdx-ghc__container { + border-top: 1px solid rgb(var(--lsd-border-primary)); + padding-top: 24px; +} + +.mdx-ghc__issue-title { + margin-bottom: 16px; +} + +.mdx-ghc__issue-title-link { + text-decoration: none; + + &:hover { + text-decoration: underline; + } +} + +.mdx-ghc__header { + margin-top: 16px; + margin-bottom: 40px; +} + +.mdx-ghc__challenge-labels { + margin-bottom: 16px; +} + +.mdx-ghc__challenge-label { + border: 1px solid rgb(var(--lsd-border-primary)); + padding: 4px 8px; + border-radius: 20px; + margin-right: 8px; +} + +.mdx-ghc-subheader-text { + margin-bottom: 40px; +} + +.mdx-ghc__view-on-github-link { + display: block; + width: fit-content; + + margin-top: 40px; + margin-bottom: 56px; + + text-decoration: none; + + &:hover { + text-decoration: underline; + } +} + +.mdx-ghc__participant-photo { + border-radius: 100%; + margin-left: -4px; + border: 1px solid rgb(var(--lsd-border-secondary)); +} + +.mdx-ghc__participant-photo-container { + display: flex; + align-items: center; + justify-content: flex-end; + + direction: rtl; + + padding-left: 4px; +} + +.mdx-ghc__comment-count { + margin-left: 4px; +} + +.mdx-ghc__issue-content-grid { + display: grid; + /* Fixed widths for the 1st, 2nd and 3rd columns, while the 4th column takes up the remaining space */ + grid-template-columns: 82px 135px 82px 1fr; + row-gap: 12px; + margin-top: 24px; + + align-items: center; +} + +.mdx-ghc__achievement { + display: flex; + align-items: center; + padding-left: 4px; +} diff --git a/packages/logos-docusaurus-theme/src/client/components/mdx/GithubChallenges/GithubChallenges.tsx b/packages/logos-docusaurus-theme/src/client/components/mdx/GithubChallenges/GithubChallenges.tsx new file mode 100644 index 0000000..ea05d7b --- /dev/null +++ b/packages/logos-docusaurus-theme/src/client/components/mdx/GithubChallenges/GithubChallenges.tsx @@ -0,0 +1,71 @@ +import { Typography } from '@acid-info/lsd-react' +import { SingleGithubChallenge } from './SingleGithubChallenge' +import React from 'react' +import useFetchGithubIssues, { GithubIssue } from './useFetchGithubIssues' + +type GithubChallengesHeaderProps = { + message?: string +} + +const GithubChallengesHeader: React.FC = ({ + message, +}) => { + return ( + <> + + Open challenges + + + {!!message && {message}} + + ) +} + +const hasChallenges = (githubChallenges: GithubIssue[]): boolean => { + return githubChallenges.length > 0 +} + +type GithubChallengesProps = React.HTMLAttributes & { + org: string + useDummyData?: boolean +} + +export const GithubChallenges: React.FC = ({ + org, + useDummyData, + ...props +}) => { + const [data, error, loading] = useFetchGithubIssues(org, useDummyData) + + if (loading) { + return + } + + if (error) { + return + } + + if (!data || !hasChallenges(data)) { + return + } + + return ( +
+ + + Lorem ipsum dolor sit amet consectetur. Enim magna urna fames mattis + tincidunt nibh mi ornare. Sed amet morbi mauris pellentesque fusce ut. + Bibendum vestibulum Lorem ipsum dolor sit amet consectetur. Enim magna + urna fames mattis tincidunt nibh mi ornare. Sed amet morbi mauris + pellentesque fusce ut. Bibendum vestibulum + + {data.map((issue) => { + return + })} +
+ ) +} diff --git a/packages/logos-docusaurus-theme/src/client/components/mdx/GithubChallenges/SingleGithubChallenge.tsx b/packages/logos-docusaurus-theme/src/client/components/mdx/GithubChallenges/SingleGithubChallenge.tsx new file mode 100644 index 0000000..0d204b1 --- /dev/null +++ b/packages/logos-docusaurus-theme/src/client/components/mdx/GithubChallenges/SingleGithubChallenge.tsx @@ -0,0 +1,119 @@ +import { Button, Typography } from '@acid-info/lsd-react' +import React from 'react' +import { IconExternalLink } from '@logos-theme/components/Icon' +import './GithubChallenges.scss' +import Link from '@docusaurus/Link' +import { GithubIssue } from './useFetchGithubIssues' + +function addSizeToAvatarUrl(avatarUrl: string, size: number = 24): string { + const url = new URL(avatarUrl) + const params = new URLSearchParams(url.search) + params.set('s', size.toString()) + + // Prepend the size parameter to the start of the query string + url.search = Array.from(params.entries()) + .map(([key, value]) => `${key}=${value}`) + .join('&') + + return url.toString() +} + +type SingleGithubChallengeProps = { + issue: GithubIssue +} + +export const SingleGithubChallenge: React.FC = ({ + issue, +}) => { + return ( +
+ + + {issue.title} + + + +
+ {issue.labels.map((label, index) => ( + + {label.name} + + ))} +
+ +
+ {/* 1st row 1st item */} + + Participants + + + {/* 1st row 2nd item */} +
+ + {issue.comments.length} + + {issue.participants.map((participant, index) => ( + {participant.login} + ))} +
+ + {/* 1st row 3rd item */} + + Project + + + {/* 1st row 4th item */} + + {issue.project ? issue.project.name : ''} + + + {/* 2nd row 1st item */} + + Achievement + + + {/* 2nd row 2nd item */} +
+ +
+ + {/* 2nd row 3rd item */} + + Milestone + + + {/* 2nd row 4th item */} + + {issue.milestone || ''} + +
+ + + + +
+ ) +} diff --git a/packages/logos-docusaurus-theme/src/client/components/mdx/GithubChallenges/githubChallengesDummyData.ts b/packages/logos-docusaurus-theme/src/client/components/mdx/GithubChallenges/githubChallengesDummyData.ts new file mode 100644 index 0000000..8e01078 --- /dev/null +++ b/packages/logos-docusaurus-theme/src/client/components/mdx/GithubChallenges/githubChallengesDummyData.ts @@ -0,0 +1,50 @@ +import { GithubIssue } from './useFetchGithubIssues' + +// Only for dev purposes - prevents making multiple requests to the API while developing. +export const dummyGithubIssue: GithubIssue = { + id: '12345', + title: 'Bug in pagination', + body: 'When navigating to the second page, the first item repeats.', + url: 'https://github.com/user/repo/issues/12345', + labels: [ + { + name: 'bug', + }, + { + name: 'frontend', + }, + ], + comments: [ + { + body: 'I have also noticed this issue. Working on a fix now.', + }, + { + body: 'Any updates on this?', + }, + { + body: 'I like turtles.', + }, + ], + participants: [ + { + login: 'alice123', + avatarUrl: + 'https://avatars.githubusercontent.com/u/8811422?u=b4aec0f11a78abe3b71c42e4adfba3ebd61f34aa&v=4', + }, + { + login: 'bob456', + avatarUrl: + 'https://avatars.githubusercontent.com/u/8811422?u=b4aec0f11a78abe3b71c42e4adfba3ebd61f34aa&v=4', + }, + { + login: 'jaquim', + avatarUrl: + 'https://avatars.githubusercontent.com/u/8811422?u=b4aec0f11a78abe3b71c42e4adfba3ebd61f34aa&v=4', + }, + ], + project: { + name: 'Awesome Project', + }, + achievement: 'Solved critical frontend bug', + milestone: 'v1.0.0', +} diff --git a/packages/logos-docusaurus-theme/src/client/components/mdx/GithubChallenges/index.ts b/packages/logos-docusaurus-theme/src/client/components/mdx/GithubChallenges/index.ts new file mode 100644 index 0000000..a9fe8f5 --- /dev/null +++ b/packages/logos-docusaurus-theme/src/client/components/mdx/GithubChallenges/index.ts @@ -0,0 +1 @@ +export * from './GithubChallenges' diff --git a/packages/logos-docusaurus-theme/src/client/components/mdx/GithubChallenges/useFetchGithubIssues.ts b/packages/logos-docusaurus-theme/src/client/components/mdx/GithubChallenges/useFetchGithubIssues.ts new file mode 100644 index 0000000..e3e5794 --- /dev/null +++ b/packages/logos-docusaurus-theme/src/client/components/mdx/GithubChallenges/useFetchGithubIssues.ts @@ -0,0 +1,74 @@ +import { useEffect, useState } from 'react' +import { dummyGithubIssue } from './githubChallengesDummyData' + +type GithubIssueParticipant = { + login: string + avatarUrl: string +} + +type GithubProject = { + name: string +} + +type GithubMilestone = string + +type GithubIssueComment = { + body: string +} + +type GithubIssueLabel = { + name: string +} + +export type GithubIssue = { + id: string + title: string + body: string + url: string + labels: GithubIssueLabel[] + comments: GithubIssueComment[] + participants: GithubIssueParticipant[] + project?: GithubProject + milestone?: GithubMilestone + achievement: string +} + +function useFetchGithubIssues( + org: string, + useDummyData: boolean = false, +): [GithubIssue[] | null, string | null, boolean] { + const [data, setData] = useState(null) + const [errorMessage, setErrorMessage] = useState(null) + const [loading, setLoading] = useState(true) + + useEffect(() => { + if (useDummyData) { + // Mocking an API call with setTimeout + setTimeout(() => { + try { + // Success scenario: + setData([dummyGithubIssue, dummyGithubIssue, dummyGithubIssue]) + setLoading(false) + + // Uncomment the below lines to simulate an error scenario: + // throw new Error("Failed to fetch data"); + } catch (error) { + let errorMessage = 'An error occurred' + if (error instanceof Error) { + errorMessage = error.message + } else if (typeof error === 'string') { + errorMessage = error + } + + console.error(errorMessage) + setErrorMessage(errorMessage) + setLoading(false) + } + }, 2000) // Mock delay of 2 seconds + } + }, []) + + return [data, errorMessage, loading] +} + +export default useFetchGithubIssues diff --git a/packages/logos-docusaurus-theme/src/client/components/mdx/index.ts b/packages/logos-docusaurus-theme/src/client/components/mdx/index.ts index 04e421d..252e306 100644 --- a/packages/logos-docusaurus-theme/src/client/components/mdx/index.ts +++ b/packages/logos-docusaurus-theme/src/client/components/mdx/index.ts @@ -25,3 +25,4 @@ export * from './ShowcaseCard' export * from './SocialCard' export * from './TimelineItem' export * from './JobsPerDepartment' +export * from './GithubChallenges'