mirror of
https://github.com/DefectingCat/DefectingCat.github.io
synced 2025-07-15 16:51:37 +00:00
Add gist page
This commit is contained in:
@ -10,7 +10,6 @@ import classNames from 'classnames';
|
|||||||
import useInView from 'lib/hooks/useInView';
|
import useInView from 'lib/hooks/useInView';
|
||||||
import loadingImage from 'public/images/img/mona-loading-default.gif';
|
import loadingImage from 'public/images/img/mona-loading-default.gif';
|
||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
import Link from 'next/link';
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
gist: Gist;
|
gist: Gist;
|
||||||
@ -48,20 +47,13 @@ const GistsCode = ({ gist, f }: Props) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div ref={ref} className={classNames('pb-4 text-sm')}>
|
<div ref={ref}>
|
||||||
<h1 className="md:text-lg">
|
|
||||||
{gist.owner.login} /
|
|
||||||
<Link href={`/g/${gist.id}`}>{file[f].filename}</Link>
|
|
||||||
</h1>
|
|
||||||
<p className="text-gray-400">Update at: {gist.updated_at}</p>
|
|
||||||
<p className="text-gray-500">{gist.description}</p>
|
|
||||||
|
|
||||||
{rawCode ? (
|
{rawCode ? (
|
||||||
<div className={classNames(!rawCode && 'min-h-[300px]')}>{code}</div>
|
<div className={classNames(!rawCode && 'min-h-[300px]')}>{code}</div>
|
||||||
) : (
|
) : (
|
||||||
<div
|
<div
|
||||||
className={classNames(
|
className={classNames(
|
||||||
'h-[300px] flex',
|
'h-[300px] flex loading',
|
||||||
'flex-col items-center justify-center'
|
'flex-col items-center justify-center'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
@ -1,13 +1,82 @@
|
|||||||
import { GetStaticProps, InferGetStaticPropsType, GetStaticPaths } from 'next';
|
import { GetStaticProps, InferGetStaticPropsType, GetStaticPaths } from 'next';
|
||||||
import dynamic from 'next/dynamic';
|
import dynamic from 'next/dynamic';
|
||||||
import { ReactElement } from 'react';
|
import { ReactElement } from 'react';
|
||||||
|
import { SignalGist } from 'types';
|
||||||
|
import avatar from 'public/images/img/avatar.svg';
|
||||||
|
import Image from 'next/image';
|
||||||
|
import styles from './styles.module.css';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
const MainLayout = dynamic(() => import('layouts/MainLayout'));
|
const MainLayout = dynamic(() => import('layouts/MainLayout'));
|
||||||
|
const GistsCode = dynamic(() => import('components/gists/GistsCode'));
|
||||||
|
|
||||||
const Gist = ({ id }: InferGetStaticPropsType<typeof getStaticProps>) => {
|
const Gist = ({ gist }: InferGetStaticPropsType<typeof getStaticProps>) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<main className="max-w-5xl px-4 mx-auto lg:px-0">{id}</main>
|
<main className="max-w-5xl px-4 mx-auto lg:px-0">
|
||||||
|
<div className={'pb-4 text-sm'}>
|
||||||
|
<div className="flex items-center py-1 ">
|
||||||
|
<Image
|
||||||
|
src={avatar}
|
||||||
|
alt="Avatar"
|
||||||
|
priority
|
||||||
|
width={32}
|
||||||
|
height={32}
|
||||||
|
className="rounded-full "
|
||||||
|
/>
|
||||||
|
<h1 className="ml-2 text-xl">
|
||||||
|
{gist.owner.login} /{Object.keys(gist.files)[0]}
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
<p className="pl-10 text-gray-400 ">Last active: {gist.updated_at}</p>
|
||||||
|
|
||||||
|
<div className="py-4">
|
||||||
|
<p className="pb-2 text-lg text-gray-500">{gist.description}</p>
|
||||||
|
|
||||||
|
{Object.keys(gist.files).map((f) => (
|
||||||
|
<div key={gist.files[f].raw_url} className={styles.wrapper}>
|
||||||
|
<div className="h-[30px] bg-[#f6f8fa] dark:bg-[hsl(220,13%,18%)] flex">
|
||||||
|
<div className="flex items-center h-full mx-3">
|
||||||
|
<div
|
||||||
|
className={classNames(
|
||||||
|
'box-border inline-block',
|
||||||
|
'w-[13px] h-[13px] mr-2',
|
||||||
|
'rounded-full bg-[#ce5347]'
|
||||||
|
)}
|
||||||
|
></div>
|
||||||
|
<div
|
||||||
|
className={classNames(
|
||||||
|
'box-border inline-block',
|
||||||
|
'w-[13px] h-[13px] mr-2',
|
||||||
|
'rounded-full bg-[#d6a243]'
|
||||||
|
)}
|
||||||
|
></div>
|
||||||
|
<div
|
||||||
|
className={classNames(
|
||||||
|
'box-border inline-block',
|
||||||
|
'w-[13px] h-[13px]',
|
||||||
|
'rounded-full bg-[#58a942]'
|
||||||
|
)}
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
className={classNames(
|
||||||
|
'px-4 bg-white',
|
||||||
|
'leading-[30px]',
|
||||||
|
'dark:bg-[hsl(220,13%,18%)] dark:border-b dark:border-b-[rgb(128,203,196)]'
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{gist.files[f].filename}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<GistsCode gist={gist} f={f} />
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -15,16 +84,22 @@ const Gist = ({ id }: InferGetStaticPropsType<typeof getStaticProps>) => {
|
|||||||
export const getStaticPaths: GetStaticPaths = async () => {
|
export const getStaticPaths: GetStaticPaths = async () => {
|
||||||
return {
|
return {
|
||||||
paths: [],
|
paths: [],
|
||||||
fallback: true,
|
fallback: 'blocking',
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getStaticProps: GetStaticProps = async ({ params }) => {
|
export const getStaticProps: GetStaticProps<{
|
||||||
|
id: string | undefined;
|
||||||
|
gist: SignalGist;
|
||||||
|
}> = async ({ params }) => {
|
||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
id: params?.id,
|
id: params?.id?.toString(),
|
||||||
|
gist: await fetch(`https://api.github.com/gists/${params?.id}`).then(
|
||||||
|
(res) => res.json()
|
||||||
|
),
|
||||||
},
|
},
|
||||||
revalidate: 60,
|
revalidate: 3600,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
13
pages/g/styles.module.css
Normal file
13
pages/g/styles.module.css
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
.wrapper {
|
||||||
|
@apply overflow-hidden rounded-lg;
|
||||||
|
@apply mb-8 shadow-lg;
|
||||||
|
/* box-shadow: 0 13px 27px -5px rgb(50 50 93 / 25%),
|
||||||
|
0 8px 16px -8px rgb(0 0 0 / 30%), 0 -6px 16px -6px rgb(0 0 0 / 3%); */
|
||||||
|
}
|
||||||
|
.wrapper pre {
|
||||||
|
margin: unset;
|
||||||
|
border-radius: unset;
|
||||||
|
}
|
||||||
|
.wrapper .loading span {
|
||||||
|
margin: unset;
|
||||||
|
}
|
@ -1,18 +1,21 @@
|
|||||||
import { InferGetStaticPropsType } from 'next';
|
import { GetStaticProps, InferGetStaticPropsType } from 'next';
|
||||||
import { ReactElement } from 'react';
|
import { ReactElement } from 'react';
|
||||||
import { Gist, GithubUser } from 'types';
|
import { Gist, GithubUser } from 'types';
|
||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import dynamic from 'next/dynamic';
|
import dynamic from 'next/dynamic';
|
||||||
import avatar from 'public/images/img/avatar.svg';
|
import avatar from 'public/images/img/avatar.svg';
|
||||||
|
import Link from 'next/link';
|
||||||
|
|
||||||
const MainLayout = dynamic(() => import('layouts/MainLayout'));
|
const MainLayout = dynamic(() => import('layouts/MainLayout'));
|
||||||
const GistsCode = dynamic(() => import('components/gists/GistsCode'));
|
const GistsCode = dynamic(() => import('components/gists/GistsCode'));
|
||||||
|
const Anchor = dynamic(() => import('components/mdx/Anchor'));
|
||||||
|
|
||||||
const Gists = ({
|
const Gists = ({
|
||||||
gists,
|
gists,
|
||||||
user,
|
user,
|
||||||
}: InferGetStaticPropsType<typeof getStaticProps>) => {
|
}: InferGetStaticPropsType<typeof getStaticProps>) => {
|
||||||
|
console.log(gists);
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<main className="max-w-5xl px-4 mx-auto lg:px-0">
|
<main className="max-w-5xl px-4 mx-auto lg:px-0">
|
||||||
@ -53,7 +56,18 @@ const Gists = ({
|
|||||||
{gists.map((g) => (
|
{gists.map((g) => (
|
||||||
<div key={g.id}>
|
<div key={g.id}>
|
||||||
{Object.keys(g.files).map((f) => (
|
{Object.keys(g.files).map((f) => (
|
||||||
<GistsCode key={g.files[f].raw_url} gist={g} f={f} />
|
<div key={g.files[f].raw_url} className="pb-4 ">
|
||||||
|
<h1 className="md:text-lg">
|
||||||
|
{g.owner.login} /
|
||||||
|
<Link href={`/g/${g.id}`} passHref>
|
||||||
|
<Anchor external={false}>{g.files[f].filename}</Anchor>
|
||||||
|
</Link>
|
||||||
|
</h1>
|
||||||
|
<p className="text-gray-400">Update at: {g.updated_at}</p>
|
||||||
|
<p className="text-gray-500">{g.description}</p>
|
||||||
|
|
||||||
|
<GistsCode gist={g} f={f} />
|
||||||
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
@ -64,17 +78,20 @@ const Gists = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getStaticProps = async () => {
|
export const getStaticProps: GetStaticProps<{
|
||||||
|
gists: Gist[];
|
||||||
|
user: GithubUser;
|
||||||
|
}> = async () => {
|
||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
gists: (await fetch(
|
gists: await fetch(
|
||||||
'https://api.github.com/users/DefectingCat/gists'
|
'https://api.github.com/users/DefectingCat/gists'
|
||||||
).then((res) => res.json())) as Gist[],
|
).then((res) => res.json()),
|
||||||
user: (await fetch('https://api.github.com/users/DefectingCat').then(
|
user: await fetch('https://api.github.com/users/DefectingCat').then(
|
||||||
(res) => res.json()
|
(res) => res.json()
|
||||||
)) as GithubUser,
|
),
|
||||||
},
|
},
|
||||||
revalidate: 60,
|
revalidate: 600,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -138,66 +138,7 @@ export interface GithubUser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Generated by https://quicktype.io
|
// Generated by https://quicktype.io
|
||||||
export interface SignalGist {
|
export interface SignalGist extends Gist {
|
||||||
url: string;
|
|
||||||
forks_url: string;
|
|
||||||
commits_url: string;
|
|
||||||
id: string;
|
|
||||||
node_id: string;
|
|
||||||
git_pull_url: string;
|
|
||||||
git_push_url: string;
|
|
||||||
html_url: string;
|
|
||||||
files: { [key: string]: File };
|
|
||||||
public: boolean;
|
|
||||||
created_at: string;
|
|
||||||
updated_at: string;
|
|
||||||
description: string;
|
|
||||||
comments: number;
|
|
||||||
user: null;
|
|
||||||
comments_url: string;
|
|
||||||
owner: Owner;
|
|
||||||
forks: any[];
|
forks: any[];
|
||||||
history: History[];
|
history: History[];
|
||||||
truncated: boolean;
|
|
||||||
}
|
|
||||||
export interface File {
|
|
||||||
filename: string;
|
|
||||||
type: string;
|
|
||||||
language: string;
|
|
||||||
raw_url: string;
|
|
||||||
size: number;
|
|
||||||
truncated: boolean;
|
|
||||||
content: string;
|
|
||||||
}
|
|
||||||
export interface History {
|
|
||||||
user: Owner;
|
|
||||||
version: string;
|
|
||||||
committed_at: string;
|
|
||||||
change_status: ChangeStatus;
|
|
||||||
url: string;
|
|
||||||
}
|
|
||||||
export interface ChangeStatus {
|
|
||||||
total: number;
|
|
||||||
additions: number;
|
|
||||||
deletions: number;
|
|
||||||
}
|
|
||||||
export interface Owner {
|
|
||||||
login: string;
|
|
||||||
id: number;
|
|
||||||
node_id: string;
|
|
||||||
avatar_url: string;
|
|
||||||
gravatar_id: string;
|
|
||||||
url: string;
|
|
||||||
html_url: string;
|
|
||||||
followers_url: string;
|
|
||||||
following_url: string;
|
|
||||||
gists_url: string;
|
|
||||||
starred_url: string;
|
|
||||||
subscriptions_url: string;
|
|
||||||
organizations_url: string;
|
|
||||||
repos_url: string;
|
|
||||||
events_url: string;
|
|
||||||
received_events_url: string;
|
|
||||||
type: string;
|
|
||||||
site_admin: boolean;
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user