Added OG Image (#5251)

- Added dynamic OG Image to share and download in contributors page

<img width="1176" alt="Screenshot 2024-05-02 at 16 24 00"
src="https://github.com/twentyhq/twenty/assets/102751374/0579454b-ccc7-46ba-9875-52458f06ee82">

- Added dynamic metadata 

- Added design to contributor page

- Added a NEXT_PUBLIC_HOST_URL in the .env file

Co-authored-by: Ady Beraud <a.beraud96@gmail.com>
This commit is contained in:
Ady Beraud
2024-05-03 17:38:41 +03:00
committed by GitHub
parent a5a9e0e238
commit 20670695d6
6 changed files with 507 additions and 106 deletions

View File

@ -7,11 +7,11 @@ import { Breadcrumb } from '@/app/_components/contributors/Breadcrumb';
import { ContentContainer } from '@/app/_components/contributors/ContentContainer';
import { ProfileCard } from '@/app/_components/contributors/ProfileCard';
import { ProfileInfo } from '@/app/_components/contributors/ProfileInfo';
import { ProfileSharing } from '@/app/_components/contributors/ProfileSharing';
import { PullRequests } from '@/app/_components/contributors/PullRequests';
import { ThankYou } from '@/app/_components/contributors/ThankYou';
import { Background } from '@/app/_components/oss-friends/Background';
import { findAll } from '@/database/database';
import { pullRequestModel, userModel } from '@/database/model';
import { getContributorActivity } from '@/app/contributors/utils/get-contributor-activity';
export function generateMetadata({
params,
@ -24,114 +24,63 @@ export function generateMetadata({
'Explore the impactful contributions of ' +
params.slug +
' on the Twenty Github Repo. Discover their merged pull requests, ongoing work, and top ranking. Join and contribute to the #1 Open-Source CRM thriving community!',
openGraph: {
images: [`/api/contributors/og-image/${params.slug}`],
},
};
}
export default async function ({ params }: { params: { slug: string } }) {
const contributors = await findAll(userModel);
try {
const contributorActivity = await getContributorActivity(params.slug);
if (contributorActivity) {
const {
firstContributionAt,
mergedPRsCount,
rank,
activeDays,
pullRequestActivityArray,
contributorPullRequests,
contributor,
} = contributorActivity;
const contributor = contributors.find(
(contributor) => contributor.id === params.slug,
);
if (!contributor) {
return;
return (
<Background>
<ContentContainer>
<Breadcrumb active={contributor.id} />
<ProfileCard
username={contributor.id}
avatarUrl={contributor.avatarUrl}
firstContributionAt={firstContributionAt}
/>
<ProfileInfo
mergedPRsCount={mergedPRsCount}
rank={rank}
activeDays={activeDays}
/>
<ProfileSharing
userUrl={contributor.url}
username={contributor.id}
/>
<ActivityLog data={pullRequestActivityArray} />
<PullRequests
list={
contributorPullRequests.slice(0, 9) as {
id: string;
title: string;
url: string;
createdAt: string;
mergedAt: string | null;
authorId: string;
}[]
}
/>
<ThankYou username={contributor.id} />
</ContentContainer>
</Background>
);
}
} catch (error) {
console.error('error: ', error);
}
const pullRequests = await findAll(pullRequestModel);
const mergedPullRequests = pullRequests
.filter((pr) => pr.mergedAt !== null)
.filter(
(pr) =>
![
'dependabot',
'cyborch',
'emilienchvt',
'Samox',
'charlesBochet',
'gitstart-app',
'thaisguigon',
'lucasbordeau',
'magrinj',
'Weiko',
'gitstart-twenty',
'bosiraphael',
'martmull',
'FelixMalfait',
'thomtrp',
'Bonapara',
'nimraahmed',
].includes(pr.authorId),
);
const contributorPullRequests = pullRequests.filter(
(pr) => pr.authorId === contributor.id,
);
const mergedContributorPullRequests = contributorPullRequests.filter(
(pr) => pr.mergedAt !== null,
);
const mergedContributorPullRequestsByContributor = mergedPullRequests.reduce(
(acc, pr) => {
acc[pr.authorId] = (acc[pr.authorId] || 0) + 1;
return acc;
},
{},
);
const mergedContributorPullRequestsByContributorArray = Object.entries(
mergedContributorPullRequestsByContributor,
)
.map(([authorId, value]) => ({ authorId, value }))
.sort((a, b) => b.value - a.value);
const contributorRank =
((mergedContributorPullRequestsByContributorArray.findIndex(
(contributor) => contributor.authorId === params.slug,
) +
1) /
contributors.length) *
100;
const pullRequestActivity = contributorPullRequests.reduce((acc, pr) => {
const date = new Date(pr.createdAt).toISOString().split('T')[0];
acc[date] = (acc[date] || 0) + 1;
return acc;
}, []);
const pullRequestActivityArray = Object.entries(pullRequestActivity)
.map(([day, value]) => ({ day, value }))
.sort((a, b) => new Date(a.day).getTime() - new Date(b.day).getTime());
return (
<Background>
<ContentContainer>
<Breadcrumb active={contributor.id} />
<ProfileCard
username={contributor.id}
avatarUrl={contributor.avatarUrl}
firstContributionAt={pullRequestActivityArray[0]?.day}
/>
<ProfileInfo
mergedPRsCount={mergedContributorPullRequests.length}
rank={Math.ceil(Number(contributorRank)).toFixed(0)}
activeDays={pullRequestActivityArray.length}
/>
<ActivityLog data={pullRequestActivityArray} />
<PullRequests
list={
contributorPullRequests.slice(0, 9) as {
id: string;
title: string;
url: string;
createdAt: string;
mergedAt: string | null;
authorId: string;
}[]
}
/>
<ThankYou username={contributor.id} />
</ContentContainer>
</Background>
);
}

View File

@ -0,0 +1,96 @@
import { findAll } from '@/database/database';
import { pullRequestModel, userModel } from '@/database/model';
export const getContributorActivity = async (username: string) => {
const contributors = await findAll(userModel);
const contributor = contributors.find((contributor) => {
return contributor.id === username;
});
if (!contributor) {
return;
}
const pullRequests = await findAll(pullRequestModel);
const mergedPullRequests = pullRequests
.filter((pr) => pr.mergedAt !== null)
.filter(
(pr) =>
![
'dependabot',
'cyborch',
'emilienchvt',
'Samox',
'charlesBochet',
'gitstart-app',
'thaisguigon',
'lucasbordeau',
'magrinj',
'Weiko',
'gitstart-twenty',
'bosiraphael',
'martmull',
'FelixMalfait',
'thomtrp',
'Bonapara',
'nimraahmed',
].includes(pr.authorId),
);
const contributorPullRequests = pullRequests.filter(
(pr) => pr.authorId === contributor.id,
);
const mergedContributorPullRequests = contributorPullRequests.filter(
(pr) => pr.mergedAt !== null,
);
const mergedContributorPullRequestsByContributor = mergedPullRequests.reduce(
(acc, pr) => {
acc[pr.authorId] = (acc[pr.authorId] || 0) + 1;
return acc;
},
{},
);
const mergedContributorPullRequestsByContributorArray = Object.entries(
mergedContributorPullRequestsByContributor,
)
.map(([authorId, value]) => ({ authorId, value }))
.sort((a, b) => b.value - a.value);
const contributorRank =
((mergedContributorPullRequestsByContributorArray.findIndex(
(contributor) => contributor.authorId === username,
) +
1) /
contributors.length) *
100;
const pullRequestActivity = contributorPullRequests.reduce((acc, pr) => {
const date = new Date(pr.createdAt).toISOString().split('T')[0];
acc[date] = (acc[date] || 0) + 1;
return acc;
}, []);
const pullRequestActivityArray = Object.entries(pullRequestActivity)
.map(([day, value]) => ({ day, value }))
.sort((a, b) => new Date(a.day).getTime() - new Date(b.day).getTime());
const firstContributionAt = pullRequestActivityArray[0]?.day;
const mergedPRsCount = mergedContributorPullRequests.length;
const rank = Math.ceil(Number(contributorRank)).toFixed(0);
const activeDays = pullRequestActivityArray.length;
const contributorAvatar = contributor.avatarUrl;
return {
firstContributionAt,
mergedPRsCount,
rank,
activeDays,
pullRequestActivityArray,
contributorPullRequests,
contributorAvatar,
contributor,
};
};