Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Filter feeds #427

Closed
wants to merge 18 commits into from
Closed
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions app/api/leaderboard/functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
ReleasesResponse,
LeaderboardAPIResponse,
Release,
Repository,
} from "@/lib/types";
import { getContributors } from "@/lib/api";
import { env } from "@/env.mjs";
Expand Down Expand Up @@ -113,3 +114,42 @@ export default async function fetchGitHubReleases(
)
.slice(0, sliceLimit);
}

interface RepositoriesResponse {
organization: {
repositories: {
nodes: {
name: string;
}[];
};
};
}

dgparmar14 marked this conversation as resolved.
Show resolved Hide resolved
export async function fetchAllReposName() {
const result: RepositoriesResponse = await octokit.graphql.paginate(
`
query paginate($cursor: String, $organization: String!) {
organization(login: $organization) {
repositories(first: 10, after: $cursor, orderBy: { field: STARGAZERS, direction: DESC }) {
nodes {
name
}
pageInfo {
hasNextPage
endCursor
}
}
}
}
`,
{
organization: "coronasafe",
dgparmar14 marked this conversation as resolved.
Show resolved Hide resolved
},
);

const allRepositoryNames = result.organization.repositories.nodes.map(
(repo) => repo.name,
);

return allRepositoryNames;
dgparmar14 marked this conversation as resolved.
Show resolved Hide resolved
}
74 changes: 59 additions & 15 deletions app/feed/page.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,47 @@
import LoadingText from "@/components/LoadingText";
import { IGitHubEvent } from "@/lib/gh_events";
import GitHubEvent from "@/components/gh_events/GitHubEvent";
import { env } from "@/env.mjs";
import octokit from "@/lib/octokit";
import {
// fetchAllBranchName,
fetchAllReposName,
} from "../api/leaderboard/functions";
import GithubFeedFilter from "../../components/gh_events/GithubFeedFilter";
import GitHubEvent from "@/components/gh_events/GitHubEvent";
import { FilterOption } from "@/lib/types";

const GITHUB_ORG: string = env.NEXT_PUBLIC_GITHUB_ORG;

export const revalidate = 600;

type Props = {
interface FeedPageProps {
searchParams: {
page?: string;
repository: string;
events: string;
};
};
}

export default async function FeedPage({ searchParams }: Props) {
const events = await octokit.paginate(
export default async function FeedPage({ searchParams }: FeedPageProps) {
const { repository, events } = searchParams;
const repositories = await fetchAllReposName();
const filterEvents: FilterOption[] = [
{ title: "repository", options: repositories },
{
title: "events",
options: [
"PullRequestReviewCommentEvent",
"PullRequestReviewEvent",
"MemberEvent",
"IssuesEvent",
"IssueCommentEvent",
"PullRequestEvent",
"PushEvent",
"ForkEvent",
"ReleaseEvent",
],
},
] as const;
let allEvents = await octokit.paginate(
"GET /orgs/{org}/events",
{
org: GITHUB_ORG,
Expand All @@ -26,18 +52,36 @@ export default async function FeedPage({ searchParams }: Props) {
return data.filter(exludeBotEvents).filter(excludeBlacklistedEvents);
},
);
if (!Object.entries(events).length) {
if (!Object.entries(allEvents).length) {
return <LoadingText text="Fetching latest events" />;
}

if (searchParams.repository) {
allEvents = allEvents.filter((e) =>
e.repo.name.includes(
env.NEXT_PUBLIC_GITHUB_ORG + "/" + searchParams.repository,
),
);
}

if (searchParams.events) {
allEvents = allEvents.filter((e) => e.type === searchParams.events);
}

return (
<div className="relative mx-auto my-8 flow-root max-w-4xl p-4">
<h1 className="text-4xl text-primary-500 dark:text-white">Feed</h1>
<ul role="list" className="mb-20 mt-10 flex flex-col gap-4 space-y-4">
{events.map((e) => (
<GitHubEvent key={e.id} event={e} />
))}
</ul>
</div>
<>
<div className="lg:justify-betw flex flex-col lg:flex-row-reverse">
<GithubFeedFilter filterEvents={filterEvents} />
<div className="relative flow-root w-full max-w-4xl p-4 lg:my-8">
<h1 className="text-4xl text-primary-500 dark:text-white">Feed</h1>
<ul role="list" className="mb-20 mt-10 flex flex-col gap-4 space-y-4">
{allEvents.map((e) => (
<GitHubEvent key={e.id} event={e} />
))}
</ul>
</div>
</div>
</>
);
}

Expand Down
62 changes: 62 additions & 0 deletions components/gh_events/GithubFeedFilter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
"use client";
import { FilterOption } from "@/lib/types";
import { usePathname, useRouter, useSearchParams } from "next/navigation";

const GithubFeed = (props: { filterEvents: FilterOption[] }) => {
const { filterEvents } = props;
const router = useRouter();
const pathname = usePathname();
const searchParams = useSearchParams();

const updateSearchParam = (key: string, value: string) => {
const params = new URLSearchParams(searchParams.toString());

!!value ? params.set(key, value) : params.delete(key);

router.push(pathname + "?" + params.toString());
};

return (
<div className="flex flex-col lg:flex-row-reverse lg:justify-between">
{/* Filter Component */}
<div className="w-full lg:sticky lg:top-20 lg:ml-auto lg:mr-0 lg:w-auto">
<div className="mx-auto min-w-max rounded-lg border border-primary-500 p-4 shadow-lg lg:my-20">
<span className="mb-2 text-2xl font-bold">Filter Activity</span>
<div className="mx-auto mt-4">
<ul className="filters mx-auto space-y-4">
{filterEvents.map((filter, index) => (
<li key={index} className="flex flex-col overflow-x-hidden">
<span className="mb-2 font-semibold">{filter.title}</span>
{filter.options && (
<select
className="rounded-md border-2 border-secondary-600 bg-background p-2 sm:p-1"
value={filter.selectedOption}
onChange={(e) => {
updateSearchParam(filter.title, e.target.value);
}}
>
<option className="w-2 sm:w-auto sm:text-sm" value="">
All
</option>
{filter.options.map((option, optionIndex) => (
<option
className="w-2 sm:w-auto sm:text-sm"
key={optionIndex}
value={option}
>
{option}
</option>
))}
</select>
)}
</li>
))}
</ul>
</div>
</div>
</div>
</div>
);
};

export default GithubFeed;
6 changes: 5 additions & 1 deletion lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,11 @@ export type ContributorSocials = {
linkedin: string;
slack: string;
};

export type FilterOption = {
title: string;
options: string[];
selectedOption?: string; // Add selectedOption property
};
export type PageProps = {
searchParams: {
search?: string;
Expand Down