Skip to content

Commit 3b75786

Browse files
committed
add github card
1 parent 99cff02 commit 3b75786

6 files changed

Lines changed: 223 additions & 2 deletions

File tree

src/Constants.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import React from 'react'
22
import ConferencesCard from './cards/ConferencesCard'
3-
import ReposCard from './cards/ReposCard'
43
import { SiGithub } from 'react-icons/si'
54
import { SiYcombinator } from 'react-icons/si'
65
import { FaDev } from 'react-icons/fa'
@@ -20,6 +19,7 @@ import { DevtoCard } from 'src/features/devtoCard'
2019
import { HashnodeCard } from 'src/features/hashnodeCard'
2120
import { MediumCard } from 'src/features/mediumCard'
2221
import { FreecodecampCard } from 'src/features/freecodecampCard'
22+
import { GithubCard } from 'src/features/githubCard'
2323

2424

2525

@@ -47,7 +47,7 @@ export const SUPPORTED_CARDS = [
4747
icon: <SiGithub className="blockHeaderWhite" />,
4848
analyticsTag: 'repos',
4949
label: 'Github repositories',
50-
component: ReposCard,
50+
component: GithubCard,
5151
},
5252
{
5353
value: 'hackernews',
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { useQueries, UseQueryOptions } from '@tanstack/react-query'
2+
import { QueryConfig, ExtractFnReturnType } from 'src/lib/react-query'
3+
import { ArticleType } from 'src/types'
4+
import { axios } from 'src/lib/axios'
5+
6+
const getArticles = async (tag: string, dateRange: string): Promise<ArticleType[]> => {
7+
return axios.get(`/data/v2/github/${tag}/${dateRange}.json`)
8+
}
9+
10+
type QueryFnType = typeof getArticles
11+
12+
type UseGetArticlesOptions = {
13+
config?: QueryConfig<QueryFnType>
14+
tags: string[]
15+
dateRange: "daily" | "monthly" | "weekly"
16+
}
17+
18+
export const useGetArticles = ({ config, tags, dateRange }: UseGetArticlesOptions) => {
19+
return useQueries({
20+
queries: tags.map<UseQueryOptions<ArticleType[]>>((tag) => {
21+
return {
22+
...config,
23+
queryKey: ['githubArticles', tag, dateRange],
24+
queryFn: () => getArticles(tag, dateRange),
25+
}
26+
})
27+
})
28+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import { useMemo } from 'react'
2+
import CardLink from 'src/components/CardLink'
3+
import CardItemWithActions from 'src/components/CardItemWithActions'
4+
import { Attributes } from 'src/lib/analytics'
5+
import { ArticleItemPropsType } from 'src/types'
6+
import ColoredLanguagesBadge from 'src/components/ColoredLanguagesBadge'
7+
import { VscRepo, VscRepoForked, VscStarFull } from 'react-icons/vsc'
8+
9+
const sourceName = 'github'
10+
11+
const ArticleItem = (props: ArticleItemPropsType) => {
12+
const { item, index, listingMode, selectedTag } = props
13+
14+
const title = useMemo(() => {
15+
return `${item.owner ? item.owner + '/' : ''}${item.title}`
16+
}, [item])
17+
18+
return (
19+
<CardItemWithActions
20+
source={sourceName}
21+
key={index}
22+
index={index}
23+
item={{ ...item, title }}
24+
cardItem={
25+
<>
26+
<CardLink
27+
className="githubTitle"
28+
link={item.url}
29+
analyticsAttributes={{
30+
[Attributes.POINTS]: item.reactions,
31+
[Attributes.TRIGERED_FROM]: 'card',
32+
[Attributes.TITLE]: title,
33+
[Attributes.LINK]: item.url,
34+
[Attributes.SOURCE]: sourceName,
35+
[Attributes.LANGUAGE]: selectedTag?.value,
36+
}}>
37+
<VscRepo className={'rowTitleIcon'} />
38+
{item.owner && `${item?.owner}/`}
39+
<b>{item.title}</b>
40+
</CardLink>
41+
<p className="rowDescription">{item.description}</p>
42+
{listingMode === 'normal' && (
43+
<div className="rowDetails">
44+
<ColoredLanguagesBadge languages={item.tags} />
45+
{item.reactions && (
46+
<span className="rowItem">
47+
<VscStarFull className="rowItemIcon" /> {item.reactions} stars
48+
</span>
49+
)}
50+
{item.forks && (
51+
<span className="rowItem">
52+
<VscRepoForked className="rowItemIcon" /> {item.forks} forks
53+
</span>
54+
)}
55+
</div>
56+
)}
57+
</>
58+
}
59+
/>
60+
)
61+
}
62+
63+
export default ArticleItem
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
import { useState, useEffect } from 'react'
2+
import CardComponent from 'src/components/CardComponent'
3+
import { ListComponent } from 'src/components/List'
4+
import { useGetArticles } from '../api/getArticles'
5+
import { ArticleType, CardPropsType } from 'src/types'
6+
import { useUserPreferences } from 'src/stores/preferences'
7+
import { getCardTagsValue } from 'src/utils/DataEnhancement'
8+
import ArticleItem from './ArticleItem'
9+
import { Tag } from 'src/features/remoteConfig'
10+
import { GLOBAL_TAG, MY_LANGUAGES_TAG } from 'src/Constants'
11+
import { trackCardLanguageSelect, trackCardDateRangeSelect } from 'src/lib/analytics'
12+
import SelectableCard from 'src/components/SelectableCard'
13+
14+
const TAGS_MENU_ID = 'tags-menu'
15+
const DATE_RANGE_MENU_ID = 'date-range-id'
16+
17+
type DateRangeType = {
18+
value: "daily" | "monthly" | "weekly"
19+
label: string
20+
}
21+
22+
export function GithubCard(props: CardPropsType) {
23+
const dateRanges: DateRangeType[] = [
24+
{ label: 'the day', value: 'daily' },
25+
{ label: 'the week', value: 'weekly' },
26+
{ label: 'the month', value: 'monthly' },
27+
]
28+
const { label, icon, withAds } = props
29+
const { userSelectedTags, cardsSettings, setCardSettings, listingMode } = useUserPreferences()
30+
const [selectedTag, setSelectedTag] = useState<Tag>()
31+
const [selectedDateRange, setSelectedDateRange] = useState<DateRangeType>(dateRanges[0])
32+
33+
useEffect(() => {
34+
if (selectedTag) {
35+
setCardSettings(label.toLowerCase(), { language: selectedTag.label })
36+
}
37+
}, [selectedTag])
38+
39+
useEffect(() => {
40+
if (selectedDateRange) {
41+
setCardSettings(label.toLowerCase(), { language: selectedDateRange.value })
42+
}
43+
}, [selectedDateRange])
44+
45+
const getQueryTags = () => {
46+
if (!selectedTag) {
47+
return []
48+
}
49+
if (!selectedTag?.githubValues) {
50+
throw Error(`Github Trending does not support ${selectedTag.label}.`)
51+
}
52+
53+
if (selectedTag.value === MY_LANGUAGES_TAG.githubValues[0]) {
54+
return getCardTagsValue(userSelectedTags, 'githubValues')
55+
}
56+
return selectedTag.githubValues
57+
}
58+
59+
const results = useGetArticles({ tags: getQueryTags(), dateRange: selectedDateRange.value })
60+
61+
const getIsLoading = () => results.some((result) => result.isLoading)
62+
63+
const getData = () => {
64+
return results
65+
.reduce((acc: ArticleType[], curr) => {
66+
if (!curr.data) return acc
67+
return [...acc, ...curr.data]
68+
}, [])
69+
.sort((a, b) => b.reactions - a.reactions)
70+
}
71+
72+
const renderItem = (item: ArticleType, index: number) => (
73+
<ArticleItem
74+
item={item}
75+
key={`rp-${index}`}
76+
index={index}
77+
selectedTag={selectedTag}
78+
listingMode={listingMode}
79+
/>
80+
)
81+
82+
const HeaderTitle = () => {
83+
return (
84+
<div style={{ display: 'inline-block', margin: 0, padding: 0 }}>
85+
<SelectableCard
86+
isLanguage={true}
87+
tagId={TAGS_MENU_ID}
88+
selectedTag={selectedTag}
89+
setSelectedTag={setSelectedTag}
90+
fallbackTag={GLOBAL_TAG}
91+
cardSettings={cardsSettings?.repos?.language}
92+
trackEvent={(tag: Tag) => trackCardLanguageSelect('Repos', tag.value)}
93+
data={userSelectedTags.map((tag) => ({
94+
label: tag.label,
95+
value: tag.value,
96+
}))}
97+
/>
98+
<span> Repos of </span>
99+
<SelectableCard
100+
tagId={DATE_RANGE_MENU_ID}
101+
selectedTag={selectedDateRange}
102+
setSelectedTag={setSelectedDateRange}
103+
fallbackTag={dateRanges[0]}
104+
trackEvent={(tag: DateRangeType) => trackCardDateRangeSelect('Repos', tag.value)}
105+
cardSettings={cardsSettings?.repos?.dateRange}
106+
data={dateRanges}
107+
/>
108+
</div>
109+
)
110+
}
111+
112+
return (
113+
<CardComponent
114+
fullBlock={true}
115+
icon={<span className="blockHeaderIcon">{icon}</span>}
116+
link="https://github.com/"
117+
title={<HeaderTitle />}>
118+
<ListComponent
119+
items={getData()}
120+
isLoading={getIsLoading()}
121+
renderItem={renderItem}
122+
withAds={withAds}
123+
/>
124+
</CardComponent>
125+
)
126+
}

src/features/githubCard/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from "./components/GithubCard";

src/types/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ export type ArticleType = {
4949
flair_text?: string
5050
flair_background_color?: string
5151
flair_text_color?: string
52+
owner?: string
53+
forks?: string
54+
starsInDateRange?: string
5255
}
5356

5457
export type CardPropsType = {

0 commit comments

Comments
 (0)