Skip to content

Commit

Permalink
feat: users by followers (#132)
Browse files Browse the repository at this point in the history
* chore: update fakes

* chore: wip

* feat: add users by followers ui
  • Loading branch information
tom-bywild authored Jan 6, 2023
1 parent 4fe0fdb commit 7b9d943
Show file tree
Hide file tree
Showing 14 changed files with 367 additions and 27 deletions.
62 changes: 50 additions & 12 deletions web/scripts/generate-trends.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,17 @@ function persist(data: Array<[pathFragments: string[], items: unknown[]]>) {
}
}

function prepareDirectories(source: Array<string[]>) {
if (fs.existsSync(base)) {
fs.rmSync(base, { recursive: true });
}

source.forEach((fragments) => {
const dir = path.join(...fragments.slice(0, -1));
fs.mkdirSync(dir, { recursive: true });
});
}

function composeFakeReposByStarsItems(params: { count: number }) {
const { count } = params;

Expand Down Expand Up @@ -62,24 +73,50 @@ function composeFakeReposByStarsItems(params: { count: number }) {
return items.sort((a, b) => b.trend.stargazers_count - a.trend.stargazers_count);
}

function prepareDirectories(source: Array<string[]>) {
if (fs.existsSync(base)) {
fs.rmSync(base, { recursive: true });
}
function composeFakeUsersByFollowersItems(params: { count: number }) {
const { count } = params;

source.forEach((fragments) => {
const dir = path.join(...fragments.slice(0, -1));
fs.mkdirSync(dir, { recursive: true });
const items = Array.from({ length: count }).map((_, index) => {
const name = faker.word.adjective(50);
const login = name.toLowerCase();
const avatar_url = faker.image.abstract();

return {
original: {
id: index + 100,
name,
bio: faker.lorem.sentence(10),
login,
avatar_url,
html_url: `https://github.com/${login}`,
followers: Number(faker.random.numeric(3)),
following: Number(faker.random.numeric(2)),
public_repos: Number(faker.random.numeric(2))
},
trend: {
followers: Number(faker.random.numeric(2))
}
};
});

return items.sort((a, b) => b.trend.followers - a.trend.followers);
}

function composeConfigs(params: { count: number }): Array<[pathFragments: string[], items: any[]]> {
function composeConfigs(params: { count: number }) {
const { count } = params;

return ranges.map((range) => [
[base, 'github', 'trends', 'repos-by-stars', `${range}.json`],
composeFakeReposByStarsItems({ count })
const res = ranges.map((range) => [
[
[base, 'github', 'trends', 'repos-by-stars', `${range}.json`],
composeFakeReposByStarsItems({ count })
],
[
[base, 'github', 'trends', 'users-by-followers', `${range}.json`],
composeFakeUsersByFollowersItems({ count })
]
]);

return res.flat() as Array<[string[], unknown[]]>;
}

/**
Expand All @@ -88,8 +125,9 @@ function composeConfigs(params: { count: number }): Array<[pathFragments: string
function run() {
const { count } = getArgv();
const configs = composeConfigs({ count });
const itemPaths = configs.map((tuples) => tuples[0]);

prepareDirectories(configs.map(([fragments]) => fragments));
prepareDirectories(itemPaths);
persist(configs);
}

Expand Down
1 change: 1 addition & 0 deletions web/src/lib/blocks/views/Iconic.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
| 'carbon:star-filled'
| 'carbon:user-avatar-filled-alt'
| 'carbon:data-view-alt'
| 'carbon:group'
| (string & {});
export let size: '16' | '20' | '24' | '32' | '40' | '48' | '56' = '24';
export let hFlip: boolean | undefined = undefined;
Expand Down
31 changes: 26 additions & 5 deletions web/src/lib/statistics/models/github.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { GithubTrendItem } from '../types/github';
import type { GithubRepoByStarsTrendItem, GithubUserByFollowersTrendItem } from '../types/github';

export const githubTrendRanges = [
'1h',
Expand Down Expand Up @@ -37,13 +37,14 @@ export function mapRangeToLabel(source: string) {
}
}

export async function fetchReposByStars(params: {
async function fetchTrendItems<T>(params: {
range: typeof githubTrendRanges[number];
}): Promise<{ items: GithubTrendItem[] }> {
const { range } = params;
path: string;
}): Promise<{ items: T[] }> {
const { path, range } = params;

const fetcher = async () =>
fetch(`${import.meta.env.VITE_STATS_GH_TRENDS_BASE_URL}/repos-by-stars/${range}.json`, {
fetch([import.meta.env.VITE_STATS_GH_TRENDS_BASE_URL, path, `${range}.json`].join('/'), {
headers: {
'Content-Type': 'application/json'
}
Expand All @@ -58,3 +59,23 @@ export async function fetchReposByStars(params: {
return { items: [] };
}
}

export async function fetchReposByStars(params: {
range: typeof githubTrendRanges[number];
}): Promise<{ items: GithubRepoByStarsTrendItem[] }> {
const { range } = params;
return fetchTrendItems<GithubRepoByStarsTrendItem>({
range,
path: 'repos-by-stars'
});
}

export async function fetchUsersByFollowers(params: {
range: typeof githubTrendRanges[number];
}): Promise<{ items: GithubUserByFollowersTrendItem[] }> {
const { range } = params;
return fetchTrendItems<GithubUserByFollowersTrendItem>({
range,
path: 'users-by-followers'
});
}
19 changes: 18 additions & 1 deletion web/src/lib/statistics/types/github.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export type GithubTrendItem = {
export type GithubRepoByStarsTrendItem = {
original: {
id: number;
name: string;
Expand All @@ -16,3 +16,20 @@ export type GithubTrendItem = {
stargazers_count: 97;
};
};

export type GithubUserByFollowersTrendItem = {
original: {
id: number;
name: string;
bio?: string;
login: string;
avatar_url: string;
html_url: string;
followers?: number;
following?: number;
public_repos?: number;
};
trend: {
followers: number;
};
};
14 changes: 12 additions & 2 deletions web/src/routes/statistic/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,22 @@

<SectionsColumn>
<PackageDetailSection title="Github Stars">
<SubGrid size="2">
<SubGrid size="1">
<SubGridItem
withSpaceY="xs"
key="Trending packages by stars"
title="Trending packages by stars"
url="/statistic/github/stars/6h"
url="/statistic/github/repos-by-stars/6h"
emphasis="key"
class="p-0"
>
<Iconic name="carbon:arrow-right" />
</SubGridItem>
<SubGridItem
withSpaceY="xs"
key="Trending users by followers"
title="Trending users by followers"
url="/statistic/github/users-by-followers/24h"
emphasis="key"
class="p-0"
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ import { redirect } from '@sveltejs/kit';
import type { PageLoad } from './$types';

export const load: PageLoad = async () => {
throw redirect(301, '/statistic/github/stars/6h');
throw redirect(301, '/statistic/github/repos-by-stars/6h');
};
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,20 @@
<BaseMeta
title={`Trending R packages by Github stars`}
description={`Trending R packages by Github stars for the last ${mapRangeToLabel(selectedRange)}`}
path="/statistic/github/stars/{selectedRange}"
path="/statistic/github/repos-by-stars/{selectedRange}"
image={{
url: `https://www.cran-e.com/api/statistic/github/stars/${selectedRange}/poster.jpeg`,
url: `https://www.cran-e.com/api/statistic/github/repos-by-stars/${selectedRange}/poster.jpeg`,
alt: `Poster for range ${selectedRange}`
}}
/>
<BreadcrumbMeta
items={[
{ name: 'Statistics', href: '/statistic' },
{ name: 'Github statistic', href: '/github/statistic' },
{ name: 'Trending R packages by Github stars', href: '/statistic/github/stars' },
{ name: 'Trending R packages by Github stars', href: '/statistic/github/repos-by-stars' },
{
name: `Trending R packages by Github stars for the last ${mapRangeToLabel(selectedRange)}`,
href: `/statistic/github/stars/${selectedRange}`
href: `/statistic/github/repos-by-stars/${selectedRange}`
}
]}
/>
Expand Down Expand Up @@ -69,7 +69,7 @@
class="appearance-none bg-black/0 overflow-hidden border border-neutral-500 px-2 rounded cursor-pointer"
on:change={(ev) => {
const { value } = ev.currentTarget;
window.location.href = `/statistic/github/stars/${value}`;
window.location.href = `/statistic/github/repos-by-stars/${value}`;
}}
>
{#each ranges as range}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
</script>

<OpenGraphImage
title={`Trending R-code on GitHub`}
title="Trending R-code on GitHub"
{subtitle}
titleSize="md"
textVariant="fit"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { fetchUsersByFollowers, githubTrendRanges } from '$lib/statistics/models/github';
import type { PageServerLoad } from '.svelte-kit/types/src/routes/$types';
import { error } from '@sveltejs/kit';

export const load: PageServerLoad = async ({ params, setHeaders }) => {
setHeaders({
'Cache-Control': 's-maxage=3600, stale-while-revalidate=7200'
});

// @ts-expect-error Range not picked up by type inference.
const range: typeof githubTrendRanges[number] = params.range;

if (!githubTrendRanges.includes(range)) {
throw error(401, `Invalid range: ${range}`);
}

const { items } = await fetchUsersByFollowers({ range });

return {
items,
ranges: githubTrendRanges,
selectedRange: range
};
};
Loading

0 comments on commit 7b9d943

Please sign in to comment.