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

Add proper ORM and postgres support #3978

Merged
merged 3 commits into from
Feb 14, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"@hello-pangea/dnd": "^16.2.0",
"@hookform/resolvers": "^3.1.1",
"@jsdevtools/rehype-toc": "^3.0.2",
"@libsql/client": "^0.4.3",
"@mdx-js/react": "^3.0.0",
"@nestjs/apollo": "^11.0.5",
"@nestjs/axios": "^3.0.1",
Expand Down Expand Up @@ -76,6 +77,7 @@
"deep-equal": "^2.2.2",
"docusaurus-node-polyfills": "^1.0.0",
"dotenv-cli": "^7.2.1",
"drizzle-orm": "^0.29.3",
"esbuild-plugin-svgr": "^2.1.0",
"file-type": "16.5.4",
"framer-motion": "^10.12.17",
Expand Down Expand Up @@ -238,6 +240,7 @@
"cross-var": "^1.1.0",
"danger": "^11.3.0",
"dotenv-cli": "^7.2.1",
"drizzle-kit": "^0.20.14",
"eslint": "^8.53.0",
"eslint-config-next": "14.0.4",
"eslint-config-prettier": "^9.1.0",
Expand Down
3 changes: 3 additions & 0 deletions packages/twenty-website/.env.example
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
BASE_URL=http://localhost:3000
GITHUB_TOKEN=your_github_token
DATABASE_DRIVER=sqlite # or pg
DATABASE_PG_URL=postgres://website:website@localhost:5432/website # only if using postgres

7 changes: 6 additions & 1 deletion packages/twenty-website/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
"lint": "next lint",
"database:generate:pg": "drizzle-kit generate:pg --config=src/database/postgres/drizzle-posgres.config.ts",
"database:generate:sqlite": "drizzle-kit generate:sqlite --config=src/database/sqlite/drizzle-sqlite.config.ts"
},
"dependencies": {
"postgres": "^3.4.3"
}
}
13 changes: 5 additions & 8 deletions packages/twenty-website/src/app/components/AvatarGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import styled from '@emotion/styled';
import Link from 'next/link';

export interface User {
login: string;
id: string;
avatarUrl: string;
}

Expand Down Expand Up @@ -66,13 +66,10 @@ const AvatarGrid = ({ users }: { users: User[] }) => {
return (
<AvatarGridContainer>
{users.map((user) => (
<Link
href={`/developers/contributors/${user.login}`}
key={`l_${user.login}`}
>
<AvatarItem key={user.login}>
<img src={user.avatarUrl} alt={user.login} />
<span className="username">{user.login}</span>
<Link href={`/developers/contributors/${user.id}`} key={`l_${user.id}`}>
<AvatarItem key={user.id}>
<img src={user.avatarUrl} alt={user.id} />
<span className="username">{user.id}</span>
</AvatarItem>
</Link>
))}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ export const ActivityLog = ({
}: {
data: { value: number; day: string }[];
}) => {
if (!data.length) {
return null;
}
return (
<CardContainer>
<Title>Activity</Title>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,12 @@ export const ProfileCard = ({
<StyledGithubIcon size="M" color="rgba(0,0,0,1)" />
</a>
</h3>
<p className="duration">
Contributing since{' '}
{format(new Date(firstContributionAt), 'MMMM yyyy')}
</p>
{firstContributionAt && (
<p className="duration">
Contributing since{' '}
{format(new Date(firstContributionAt), 'MMMM yyyy')}
</p>
)}
</Details>
</ProfileContainer>
);
Expand Down
210 changes: 90 additions & 120 deletions packages/twenty-website/src/app/developers/contributors/[slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import Database from 'better-sqlite3';
import { Metadata } from 'next';

import { Background } from '@/app/components/oss-friends/Background';
Expand All @@ -9,12 +8,8 @@ import { ProfileCard } from '@/app/developers/contributors/[slug]/components/Pro
import { ProfileInfo } from '@/app/developers/contributors/[slug]/components/ProfileInfo';
import { PullRequests } from '@/app/developers/contributors/[slug]/components/PullRequests';
import { ThankYou } from '@/app/developers/contributors/[slug]/components/ThankYou';

interface Contributor {
login: string;
avatarUrl: string;
pullRequestCount: number;
}
import { findAll } from '@/database/database';
import { pullRequestModel, userModel } from '@/database/model';

export function generateMetadata({
params,
Expand All @@ -27,134 +22,109 @@ export function generateMetadata({
}

export default async function ({ params }: { params: { slug: string } }) {
const db = new Database('db.sqlite', { readonly: true });
const contributors = await findAll(userModel);

const contributor = db
.prepare(
`
SELECT
u.login,
u.avatarUrl,
(SELECT COUNT(*) FROM pullRequests WHERE authorId = u.id) AS pullRequestCount,
(SELECT COUNT(*) FROM issues WHERE authorId = u.id) AS issuesCount
FROM
users u
WHERE
u.login = :user_id
`,
)
.get({ user_id: params.slug }) as Contributor;
const contributor = contributors.find(
(contributor) => contributor.id === params.slug,
);

const pullRequestActivity = db
.prepare(
`
SELECT
COUNT(*) as value,
DATE(createdAt) as day
FROM
pullRequests
WHERE
authorId = (SELECT id FROM users WHERE login = :user_id)
GROUP BY
DATE(createdAt)
ORDER BY
DATE(createdAt)
`,
)
.all({ user_id: params.slug }) as { value: number; day: string }[];
if (!contributor) {
return;
}

// Latest PRs.
const pullRequestList = db
.prepare(
`
SELECT
id,
title,
body,
url,
createdAt,
updatedAt,
closedAt,
mergedAt,
authorId
FROM
pullRequests
WHERE
authorId = (SELECT id FROM users WHERE login = :user_id)
ORDER BY
DATE(createdAt) DESC
LIMIT
10
`,
)
.all({ user_id: params.slug }) as {
title: string;
createdAt: string;
url: string;
id: string;
mergedAt: string | null;
authorId: string;
}[];
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 mergedPullRequests = db
.prepare(
`
SELECT * FROM (
SELECT
merged_pr_counts.*,
(RANK() OVER(ORDER BY merged_count) - 1) / CAST( total_authors as float) * 100 as rank_percentage
FROM
(
SELECT
authorId,
COUNT(*) FILTER (WHERE mergedAt IS NOT NULL) as merged_count
FROM
pullRequests pr
JOIN
users u ON pr.authorId = u.id
WHERE
u.isEmployee = FALSE
GROUP BY
authorId
) AS merged_pr_counts
CROSS JOIN
(
SELECT COUNT(DISTINCT authorId) as total_authors
FROM pullRequests pr
JOIN
users u ON pr.authorId = u.id
WHERE
u.isEmployee = FALSE
) AS author_counts
) WHERE authorId = (SELECT id FROM users WHERE login = :user_id)
`,
)
.all({ user_id: params.slug }) as {
merged_count: number;
rank_percentage: number;
}[];
const contributorPullRequests = pullRequests.filter(
(pr) => pr.authorId === contributor.id,
);
const mergedContributorPullRequests = contributorPullRequests.filter(
(pr) => pr.mergedAt !== null,
);

db.close();
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.login} />
<Breadcrumb active={contributor.id} />
<ProfileCard
username={contributor.login}
username={contributor.id}
avatarUrl={contributor.avatarUrl}
firstContributionAt={pullRequestActivity[0].day}
firstContributionAt={pullRequestActivityArray[0]?.day}
/>
<ProfileInfo
mergedPRsCount={mergedPullRequests[0].merged_count}
rank={(100 - Number(mergedPullRequests[0].rank_percentage)).toFixed(
0,
)}
activeDays={pullRequestActivity.length}
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;
}[]
}
/>
<ActivityLog data={pullRequestActivity} />
<PullRequests list={pullRequestList} />
<ThankYou authorId={contributor.login} />
</ContentContainer>
</>
Expand Down

This file was deleted.

Loading
Loading