Fix nx lint setup (#3234)

* Fix nx lint setup

* Fixes

* Fixes

* Add missing metadata

Fixes

Fix

Fixes

* Fix
This commit is contained in:
Charles Bochet
2024-01-04 16:39:57 +01:00
committed by GitHub
parent 52d4f8e466
commit c15e138d72
32 changed files with 2961 additions and 3287 deletions

View File

@ -1,9 +1,11 @@
'use client'
'use client';
import { ResponsiveTimeRange } from '@nivo/calendar'
import { ResponsiveTimeRange } from '@nivo/calendar';
export const ActivityLog = ({ data }: { data: { value: number, day: string }[] }) => {
return <ResponsiveTimeRange
data={data}
/>;
}
export const ActivityLog = ({
data,
}: {
data: { value: number; day: string }[];
}) => {
return <ResponsiveTimeRange data={data} />;
};

View File

@ -1,9 +1,8 @@
import Image from 'next/image';
import Database from 'better-sqlite3';
import AvatarGrid from '@/app/components/AvatarGrid';
import { ResponsiveTimeRange } from '@nivo/calendar'
import { ActivityLog } from './components/ActivityLog';
import { Metadata } from 'next';
import Image from 'next/image';
import { ActivityLog } from './components/ActivityLog';
interface Contributor {
login: string;
@ -11,21 +10,22 @@ interface Contributor {
pullRequestCount: number;
}
export function generateMetadata({ params }: { params: { slug: string } }): Metadata {
return {
title: params.slug + ' | Contributors',
};
export function generateMetadata({
params,
}: {
params: { slug: string };
}): Metadata {
return {
title: params.slug + ' | Contributors',
};
}
export default async function ({ params }: { params: { slug: string } }) {
const db = new Database('db.sqlite', { readonly: true });
export default async function (
{ params }: { params: { slug: string } }) {
const db = new Database('db.sqlite', { readonly: true });
const contributor = db.prepare(`
const contributor = db
.prepare(
`
SELECT
u.login,
u.avatarUrl,
@ -35,9 +35,13 @@ export default async function (
users u
WHERE
u.login = :user_id
`).get({'user_id' : params.slug}) as Contributor;
`,
)
.get({ user_id: params.slug }) as Contributor;
const pullRequestActivity = db.prepare(`
const pullRequestActivity = db
.prepare(
`
SELECT
COUNT(*) as value,
DATE(createdAt) as day
@ -49,11 +53,13 @@ const pullRequestActivity = db.prepare(`
DATE(createdAt)
ORDER BY
DATE(createdAt)
`).all({'user_id': params.slug}) as { value: number, day: string }[];
`,
)
.all({ user_id: params.slug }) as { value: number; day: string }[];
const pullRequestList = db.prepare(`
const pullRequestList = db
.prepare(
`
SELECT
id,
title,
@ -69,32 +75,46 @@ const pullRequestList = db.prepare(`
authorId = (SELECT id FROM users WHERE login = :user_id)
ORDER BY
DATE(createdAt) DESC
`).all({'user_id': params.slug}) as { title: string, createdAt: string, url: string }[];
`,
)
.all({ user_id: params.slug }) as {
title: string;
createdAt: string;
url: string;
}[];
db.close();
return (
<div style={{maxWidth: '900px', display: 'flex', padding: '40px', gap: '24px'}}>
<div style={{ flexDirection: 'column', width: '240px'}}>
<Image src={contributor.avatarUrl} alt={contributor.login} width={240} height={240} />
<div
style={{
maxWidth: '900px',
display: 'flex',
padding: '40px',
gap: '24px',
}}
>
<div style={{ flexDirection: 'column', width: '240px' }}>
<Image
src={contributor.avatarUrl}
alt={contributor.login}
width={240}
height={240}
/>
<h1>{contributor.login}</h1>
</div>
<div style={{flexDirection: 'column'}}>
<div style={{width: '450px', height: '200px'}}>
<ActivityLog
data={pullRequestActivity}
/>
</div>
<div style={{width: '450px'}}>
{pullRequestList.map(pr => (
<div>
<a href={pr.url}>{pr.title}</a>
</div>
))}
<div style={{ flexDirection: 'column' }}>
<div style={{ width: '450px', height: '200px' }}>
<ActivityLog data={pullRequestActivity} />
</div>
<div style={{ width: '450px' }}>
{pullRequestList.map((pr) => (
<div>
<a href={pr.url}>{pr.title}</a>
</div>
))}
</div>
</div>
</div>
);
};
}

View File

@ -1,19 +1,23 @@
import Database from 'better-sqlite3';
export async function GET(
request: Request,
{ params }: { params: { slug: string } }) {
const db = new Database('db.sqlite', { readonly: true });
request: Request,
{ params }: { params: { slug: string } },
) {
const db = new Database('db.sqlite', { readonly: true });
if(params.slug !== 'users' && params.slug !== 'labels' && params.slug !== 'pullRequests' && params.slug !== 'issues') {
return Response.json({ error: 'Invalid table name' }, { status: 400 });
}
if (
params.slug !== 'users' &&
params.slug !== 'labels' &&
params.slug !== 'pullRequests' &&
params.slug !== 'issues'
) {
return Response.json({ error: 'Invalid table name' }, { status: 400 });
}
const rows = db.prepare('SELECT * FROM ' + params.slug).all();
db.close();
const rows = db.prepare('SELECT * FROM ' + params.slug).all();
return Response.json(rows);
db.close();
return Response.json(rows);
}

View File

@ -1,5 +1,5 @@
import Database from 'better-sqlite3';
import { graphql } from '@octokit/graphql';
import Database from 'better-sqlite3';
const db = new Database('db.sqlite', { verbose: console.log });
@ -83,8 +83,13 @@ const query = graphql.defaults({
},
});
async function fetchData(cursor: string | null = null, isIssues: boolean = false, accumulatedData: Array<PullRequestNode | IssueNode> = []): Promise<Array<PullRequestNode | IssueNode>> {
const { repository } = await query<RepoData>(`
async function fetchData(
cursor: string | null = null,
isIssues: boolean = false,
accumulatedData: Array<PullRequestNode | IssueNode> = [],
): Promise<Array<PullRequestNode | IssueNode>> {
const { repository } = await query<RepoData>(
`
query ($cursor: String) {
repository(owner: "twentyhq", name: "twenty") {
pullRequests(first: 100, after: $cursor, orderBy: {field: CREATED_AT, direction: DESC}) @skip(if: ${isIssues}) {
@ -148,10 +153,17 @@ async function fetchData(cursor: string | null = null, isIssues: boolean = false
}
}
}
`, { cursor });
`,
{ cursor },
);
const newAccumulatedData: Array<PullRequestNode | IssueNode> = [...accumulatedData, ...(isIssues ? repository.issues.nodes : repository.pullRequests.nodes)];
const pageInfo = isIssues ? repository.issues.pageInfo : repository.pullRequests.pageInfo;
const newAccumulatedData: Array<PullRequestNode | IssueNode> = [
...accumulatedData,
...(isIssues ? repository.issues.nodes : repository.pullRequests.nodes),
];
const pageInfo = isIssues
? repository.issues.pageInfo
: repository.pullRequests.pageInfo;
if (pageInfo.hasNextPage) {
return fetchData(pageInfo.endCursor, isIssues, newAccumulatedData);
@ -173,11 +185,12 @@ async function fetchAssignableUsers(): Promise<Set<string>> {
}
`);
return new Set(repository.assignableUsers.nodes.map(user => user.login));
return new Set(repository.assignableUsers.nodes.map((user) => user.login));
}
const initDb = () => {
db.prepare(`
db.prepare(
`
CREATE TABLE IF NOT EXISTS pullRequests (
id TEXT PRIMARY KEY,
title TEXT,
@ -190,9 +203,11 @@ const initDb = () => {
authorId TEXT,
FOREIGN KEY (authorId) REFERENCES users(id)
);
`).run();
`,
).run();
db.prepare(`
db.prepare(
`
CREATE TABLE IF NOT EXISTS issues (
id TEXT PRIMARY KEY,
title TEXT,
@ -204,9 +219,11 @@ const initDb = () => {
authorId TEXT,
FOREIGN KEY (authorId) REFERENCES users(id)
);
`).run();
`,
).run();
db.prepare(`
db.prepare(
`
CREATE TABLE IF NOT EXISTS users (
id TEXT PRIMARY KEY,
login TEXT,
@ -214,81 +231,133 @@ const initDb = () => {
url TEXT,
isEmployee BOOLEAN
);
`).run();
`,
).run();
db.prepare(`
db.prepare(
`
CREATE TABLE IF NOT EXISTS labels (
id TEXT PRIMARY KEY,
name TEXT,
color TEXT,
description TEXT
);
`).run();
`,
).run();
db.prepare(`
db.prepare(
`
CREATE TABLE IF NOT EXISTS pullRequestLabels (
pullRequestId TEXT,
labelId TEXT,
FOREIGN KEY (pullRequestId) REFERENCES pullRequests(id),
FOREIGN KEY (labelId) REFERENCES labels(id)
);
`).run();
`,
).run();
db.prepare(`
db.prepare(
`
CREATE TABLE IF NOT EXISTS issueLabels (
issueId TEXT,
labelId TEXT,
FOREIGN KEY (issueId) REFERENCES issues(id),
FOREIGN KEY (labelId) REFERENCES labels(id)
);
`).run();
`,
).run();
};
export async function GET() {
initDb();
initDb();
// TODO if we ever hit API Rate Limiting
const lastPRCursor = null;
const lastIssueCursor = null;
// TODO if we ever hit API Rate Limiting
const lastPRCursor = null;
const lastIssueCursor = null;
const assignableUsers = await fetchAssignableUsers();
const prs = (await fetchData(lastPRCursor)) as Array<PullRequestNode>;
const issues = (await fetchData(lastIssueCursor, true)) as Array<IssueNode>;
const assignableUsers = await fetchAssignableUsers();
const prs = await fetchData(lastPRCursor) as Array<PullRequestNode>;
const issues = await fetchData(lastIssueCursor, true) as Array<IssueNode>;
const insertPR = db.prepare('INSERT INTO pullRequests (id, title, body, url, createdAt, updatedAt, closedAt, mergedAt, authorId) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) ON CONFLICT(id) DO NOTHING');
const insertIssue = db.prepare('INSERT INTO issues (id, title, body, url, createdAt, updatedAt, closedAt, authorId) VALUES (?, ?, ?, ?, ?, ?, ?, ?) ON CONFLICT(id) DO NOTHING');
const insertUser = db.prepare('INSERT INTO users (id, login, avatarUrl, url, isEmployee) VALUES (?, ?, ?, ?, ?) ON CONFLICT(id) DO NOTHING');
const insertLabel = db.prepare('INSERT INTO labels (id, name, color, description) VALUES (?, ?, ?, ?) ON CONFLICT(id) DO NOTHING');
const insertPullRequestLabel = db.prepare('INSERT INTO pullRequestLabels (pullRequestId, labelId) VALUES (?, ?)');
const insertIssueLabel = db.prepare('INSERT INTO issueLabels (issueId, labelId) VALUES (?, ?)');
const insertPR = db.prepare(
'INSERT INTO pullRequests (id, title, body, url, createdAt, updatedAt, closedAt, mergedAt, authorId) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) ON CONFLICT(id) DO NOTHING',
);
const insertIssue = db.prepare(
'INSERT INTO issues (id, title, body, url, createdAt, updatedAt, closedAt, authorId) VALUES (?, ?, ?, ?, ?, ?, ?, ?) ON CONFLICT(id) DO NOTHING',
);
const insertUser = db.prepare(
'INSERT INTO users (id, login, avatarUrl, url, isEmployee) VALUES (?, ?, ?, ?, ?) ON CONFLICT(id) DO NOTHING',
);
const insertLabel = db.prepare(
'INSERT INTO labels (id, name, color, description) VALUES (?, ?, ?, ?) ON CONFLICT(id) DO NOTHING',
);
const insertPullRequestLabel = db.prepare(
'INSERT INTO pullRequestLabels (pullRequestId, labelId) VALUES (?, ?)',
);
const insertIssueLabel = db.prepare(
'INSERT INTO issueLabels (issueId, labelId) VALUES (?, ?)',
);
for (const pr of prs) {
console.log(pr);
if(pr.author == null) { continue; }
insertUser.run(pr.author.resourcePath, pr.author.login, pr.author.avatarUrl, pr.author.url, assignableUsers.has(pr.author.login) ? 1 : 0);
insertPR.run(pr.id, pr.title, pr.body, pr.url, pr.createdAt, pr.updatedAt, pr.closedAt, pr.mergedAt, pr.author.resourcePath);
for (const pr of prs) {
console.log(pr);
if (pr.author == null) {
continue;
}
insertUser.run(
pr.author.resourcePath,
pr.author.login,
pr.author.avatarUrl,
pr.author.url,
assignableUsers.has(pr.author.login) ? 1 : 0,
);
insertPR.run(
pr.id,
pr.title,
pr.body,
pr.url,
pr.createdAt,
pr.updatedAt,
pr.closedAt,
pr.mergedAt,
pr.author.resourcePath,
);
for (const label of pr.labels.nodes) {
insertLabel.run(label.id, label.name, label.color, label.description);
insertPullRequestLabel.run(pr.id, label.id);
}
}
for (const label of pr.labels.nodes) {
insertLabel.run(label.id, label.name, label.color, label.description);
insertPullRequestLabel.run(pr.id, label.id);
}
}
for (const issue of issues) {
if(issue.author == null) { continue; }
insertUser.run(issue.author.resourcePath, issue.author.login, issue.author.avatarUrl, issue.author.url, assignableUsers.has(issue.author.login) ? 1 : 0);
for (const issue of issues) {
if (issue.author == null) {
continue;
}
insertUser.run(
issue.author.resourcePath,
issue.author.login,
issue.author.avatarUrl,
issue.author.url,
assignableUsers.has(issue.author.login) ? 1 : 0,
);
insertIssue.run(issue.id, issue.title, issue.body, issue.url, issue.createdAt, issue.updatedAt, issue.closedAt, issue.author.resourcePath);
insertIssue.run(
issue.id,
issue.title,
issue.body,
issue.url,
issue.createdAt,
issue.updatedAt,
issue.closedAt,
issue.author.resourcePath,
);
for (const label of issue.labels.nodes) {
insertLabel.run(label.id, label.name, label.color, label.description);
insertIssueLabel.run(issue.id, label.id);
}
}
for (const label of issue.labels.nodes) {
insertLabel.run(label.id, label.name, label.color, label.description);
insertIssueLabel.run(issue.id, label.id);
}
}
db.close();
db.close();
return new Response("Data synced", { status: 200 });
};
return new Response('Data synced', { status: 200 });
}

View File

@ -1,5 +1,5 @@
import Image from 'next/image';
import Database from 'better-sqlite3';
import AvatarGrid from '@/app/components/AvatarGrid';
interface Contributor {
@ -9,11 +9,11 @@ interface Contributor {
}
const Contributors = async () => {
const db = new Database('db.sqlite', { readonly: true });
const contributors = db.prepare(`SELECT
const contributors = db
.prepare(
`SELECT
u.login,
u.avatarUrl,
COUNT(pr.id) AS pullRequestCount
@ -25,9 +25,10 @@ const Contributors = async () => {
u.id
ORDER BY
pullRequestCount DESC;
`).all() as Contributor[];
`,
)
.all() as Contributor[];
db.close();
return (

View File

@ -3,6 +3,7 @@
import { createGraphiQLFetcher } from '@graphiql/toolkit';
import { GraphiQL } from 'graphiql';
import dynamic from 'next/dynamic';
import 'graphiql/graphiql.css';
// Create a named function for your component