colocate components
This commit is contained in:
parent
96c4023c14
commit
96da95818f
98 changed files with 70 additions and 360 deletions
|
@ -3,7 +3,7 @@
|
||||||
import { FormEvent, useState } from "react"
|
import { FormEvent, useState } from "react"
|
||||||
import styles from "./auth.module.css"
|
import styles from "./auth.module.css"
|
||||||
import { useRouter } from "next/navigation"
|
import { useRouter } from "next/navigation"
|
||||||
import Link from "../link"
|
import Link from "../../components/link"
|
||||||
import { Button, Input, Note } from "@geist-ui/core/dist"
|
import { Button, Input, Note } from "@geist-ui/core/dist"
|
||||||
import { signIn } from "next-auth/react"
|
import { signIn } from "next-auth/react"
|
||||||
import { Github as GithubIcon } from "@geist-ui/icons"
|
import { Github as GithubIcon } from "@geist-ui/icons"
|
|
@ -1,4 +1,4 @@
|
||||||
import PageSeo from "@components/page-seo"
|
import PageSeo from "app/components/page-seo"
|
||||||
|
|
||||||
export default function AuthHead() {
|
export default function AuthHead() {
|
||||||
return <PageSeo title="Sign In" />
|
return <PageSeo title="Sign In" />
|
|
@ -1,5 +1,5 @@
|
||||||
import Auth from "@components/auth"
|
import Auth from "../components"
|
||||||
import Header from "@components/header"
|
import Header from "app/components/header"
|
||||||
|
|
||||||
export default function SignInPage() {
|
export default function SignInPage() {
|
||||||
return (
|
return (
|
||||||
|
|
5
client/app/(auth)/signup/head.tsx
Normal file
5
client/app/(auth)/signup/head.tsx
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import PageSeo from "app/components/page-seo"
|
||||||
|
|
||||||
|
export default function AuthHead() {
|
||||||
|
return <PageSeo title="Sign Up" />
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
import Auth from "@components/auth"
|
import Auth from "../components"
|
||||||
import Header from "@components/header"
|
import Header from "app/components/header"
|
||||||
import { getRequiresPasscode } from "pages/api/auth/requires-passcode"
|
import { getRequiresPasscode } from "pages/api/auth/requires-passcode"
|
||||||
|
|
||||||
const getPasscode = async () => {
|
const getPasscode = async () => {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import ShiftBy from "@components/shift-by"
|
import ShiftBy from "app/components/shift-by"
|
||||||
import { Button, Popover } from "@geist-ui/core/dist"
|
import { Button, Popover } from "@geist-ui/core/dist"
|
||||||
import ChevronDown from "@geist-ui/icons/chevronDown"
|
import ChevronDown from "@geist-ui/icons/chevronDown"
|
||||||
import CodeIcon from "@geist-ui/icons/fileFunction"
|
import CodeIcon from "@geist-ui/icons/fileFunction"
|
|
@ -2,10 +2,10 @@ import { File } from "@lib/types"
|
||||||
import FileIcon from "@geist-ui/icons/fileText"
|
import FileIcon from "@geist-ui/icons/fileText"
|
||||||
import CodeIcon from "@geist-ui/icons/fileLambda"
|
import CodeIcon from "@geist-ui/icons/fileLambda"
|
||||||
import styles from "./file-tree.module.css"
|
import styles from "./file-tree.module.css"
|
||||||
import ShiftBy from "@components/shift-by"
|
import ShiftBy from "app/components/shift-by"
|
||||||
import { useEffect, useState } from "react"
|
import { useEffect, useState } from "react"
|
||||||
import { codeFileExtensions } from "@lib/constants"
|
import { codeFileExtensions } from "@lib/constants"
|
||||||
import Link from "@components/link"
|
import Link from "app/components/link"
|
||||||
|
|
||||||
type Item = File & {
|
type Item = File & {
|
||||||
icon: JSX.Element
|
icon: JSX.Element
|
|
@ -12,7 +12,7 @@ import FormattingIcons from "./formatting-icons"
|
||||||
import TextareaMarkdown, { TextareaMarkdownRef } from "textarea-markdown-editor"
|
import TextareaMarkdown, { TextareaMarkdownRef } from "textarea-markdown-editor"
|
||||||
|
|
||||||
import { Button, Input, Spacer, Tabs, Textarea } from "@geist-ui/core/dist"
|
import { Button, Input, Spacer, Tabs, Textarea } from "@geist-ui/core/dist"
|
||||||
import Preview from "@components/preview"
|
import Preview from "./preview"
|
||||||
|
|
||||||
// import Link from "next/link"
|
// import Link from "next/link"
|
||||||
type Props = {
|
type Props = {
|
|
@ -8,7 +8,6 @@ type Props = {
|
||||||
fileId?: string
|
fileId?: string
|
||||||
content?: string
|
content?: string
|
||||||
title?: string
|
title?: string
|
||||||
// file extensions we can highlight
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const MarkdownPreview = ({ height = 500, fileId, content, title }: Props) => {
|
const MarkdownPreview = ({ height = 500, fileId, content, title }: Props) => {
|
||||||
|
@ -26,18 +25,13 @@ const MarkdownPreview = ({ height = 500, fileId, content, title }: Props) => {
|
||||||
setIsLoading(false)
|
setIsLoading(false)
|
||||||
}
|
}
|
||||||
} else if (content) {
|
} else if (content) {
|
||||||
// add title and query to url params
|
|
||||||
const urlQuery = new URLSearchParams({
|
const urlQuery = new URLSearchParams({
|
||||||
title: title || "",
|
title: title || "",
|
||||||
content
|
content
|
||||||
})
|
})
|
||||||
|
|
||||||
const resp = await fetch(`/api/files/get-html?${urlQuery}`, {
|
const resp = await fetch(`/api/files/get-html?${urlQuery}`, {
|
||||||
method: "GET",
|
method: "GET"
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
Authorization: `Bearer ${getCookie(TOKEN_COOKIE_NAME)}`
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
if (resp.ok) {
|
if (resp.ok) {
|
|
@ -1,5 +1,5 @@
|
||||||
import type { Document } from "@lib/types"
|
import type { Document } from "@lib/types"
|
||||||
import DocumentComponent from "@components/edit-document"
|
import DocumentComponent from "./edit-document"
|
||||||
import { ChangeEvent, memo, useCallback } from "react"
|
import { ChangeEvent, memo, useCallback } from "react"
|
||||||
|
|
||||||
const DocumentList = ({
|
const DocumentList = ({
|
|
@ -4,17 +4,16 @@ import { Button, useToasts, Input, ButtonDropdown } from "@geist-ui/core/dist"
|
||||||
import { useRouter } from "next/navigation"
|
import { useRouter } from "next/navigation"
|
||||||
import { useCallback, useState } from "react"
|
import { useCallback, useState } from "react"
|
||||||
import generateUUID from "@lib/generate-uuid"
|
import generateUUID from "@lib/generate-uuid"
|
||||||
import FileDropzone from "./drag-and-drop"
|
|
||||||
import styles from "./post.module.css"
|
import styles from "./post.module.css"
|
||||||
import Title from "./title"
|
|
||||||
import type { PostVisibility, Document as DocumentType } from "@lib/types"
|
import type { PostVisibility, Document as DocumentType } from "@lib/types"
|
||||||
import PasswordModal from "./password-modal"
|
import EditDocumentList from "./edit-document-list"
|
||||||
import EditDocumentList from "@components/edit-document-list"
|
|
||||||
import { ChangeEvent } from "react"
|
import { ChangeEvent } from "react"
|
||||||
import DatePicker from "react-datepicker"
|
import DatePicker from "react-datepicker"
|
||||||
import getTitleForPostCopy from "@lib/get-title-for-post-copy"
|
import getTitleForPostCopy from "@lib/get-title-for-post-copy"
|
||||||
import Description from "./description"
|
import Description from "./description"
|
||||||
import { PostWithFiles } from "@lib/server/prisma"
|
import { PostWithFiles } from "@lib/server/prisma"
|
||||||
|
import PasswordModal from "./password-modal"
|
||||||
|
import Title from "./title"
|
||||||
|
|
||||||
const emptyDoc = {
|
const emptyDoc = {
|
||||||
title: "",
|
title: "",
|
|
@ -1,7 +1,7 @@
|
||||||
import { ChangeEvent, memo, useEffect, useState } from "react"
|
import { ChangeEvent, memo, useEffect, useState } from "react"
|
||||||
import { Text } from "@geist-ui/core/dist"
|
import { Text } from "@geist-ui/core/dist"
|
||||||
|
|
||||||
import ShiftBy from "@components/shift-by"
|
import ShiftBy from "app/components/shift-by"
|
||||||
import styles from "../post.module.css"
|
import styles from "../post.module.css"
|
||||||
import { Input } from "@geist-ui/core/dist"
|
import { Input } from "@geist-ui/core/dist"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import NewPost from "@components/new-post"
|
import NewPost from "app/(posts)/new/components/new"
|
||||||
import { useRouter } from "next/navigation"
|
import { useRouter } from "next/navigation"
|
||||||
import { getPostWithFiles } from "@lib/server/prisma"
|
import { getPostWithFiles } from "@lib/server/prisma"
|
||||||
import Header from "@components/header"
|
import Header from "app/components/header"
|
||||||
|
|
||||||
const NewFromExisting = async ({
|
const NewFromExisting = async ({
|
||||||
params
|
params
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import PageSeo from "@components/page-seo"
|
import PageSeo from "app/components/page-seo"
|
||||||
|
|
||||||
export default function NewPostHead() {
|
export default function NewPostHead() {
|
||||||
return <PageSeo title="Create a new Drift" />
|
return <PageSeo title="Create a new Drift" />
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import Header from "@components/header"
|
import Header from "app/components/header"
|
||||||
import NewPost from "@components/new-post"
|
import NewPost from "app/(posts)/new/components/new"
|
||||||
import "@styles/react-datepicker.css"
|
import "@styles/react-datepicker.css"
|
||||||
|
|
||||||
const New = () => <>
|
const New = () => <>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import VisibilityBadge from "@components/badges/visibility-badge"
|
import VisibilityBadge from "app/components/badges/visibility-badge"
|
||||||
import DocumentComponent from "@components/view-document"
|
import DocumentComponent from "./view-document"
|
||||||
import styles from "./post-page.module.css"
|
import styles from "./post-page.module.css"
|
||||||
|
|
||||||
import type { PostVisibility } from "@lib/types"
|
import type { PostVisibility } from "@lib/types"
|
||||||
|
@ -10,15 +10,15 @@ import { useEffect, useState } from "react"
|
||||||
import Archive from "@geist-ui/icons/archive"
|
import Archive from "@geist-ui/icons/archive"
|
||||||
import Edit from "@geist-ui/icons/edit"
|
import Edit from "@geist-ui/icons/edit"
|
||||||
import Parent from "@geist-ui/icons/arrowUpCircle"
|
import Parent from "@geist-ui/icons/arrowUpCircle"
|
||||||
import FileDropdown from "@components/file-dropdown"
|
import FileDropdown from "app/(posts)/components/file-dropdown"
|
||||||
import ScrollToTop from "@components/scroll-to-top"
|
import ScrollToTop from "app/components/scroll-to-top"
|
||||||
import { useRouter } from "next/navigation"
|
import { useRouter } from "next/navigation"
|
||||||
import ExpirationBadge from "@components/badges/expiration-badge"
|
import ExpirationBadge from "app/components/badges/expiration-badge"
|
||||||
import CreatedAgoBadge from "@components/badges/created-ago-badge"
|
import CreatedAgoBadge from "app/components/badges/created-ago-badge"
|
||||||
import PasswordModalPage from "./password-modal-wrapper"
|
import PasswordModalPage from "./password-modal-wrapper"
|
||||||
import VisibilityControl from "@components/badges/visibility-control"
|
import VisibilityControl from "app/components/badges/visibility-control"
|
||||||
import { File, PostWithFiles } from "@lib/server/prisma"
|
import { File, PostWithFiles } from "@lib/server/prisma"
|
||||||
import Header from "@components/header"
|
import Header from "app/components/header"
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
post: PostWithFiles
|
post: PostWithFiles
|
|
@ -14,8 +14,8 @@ import {
|
||||||
Tooltip,
|
Tooltip,
|
||||||
Tag
|
Tag
|
||||||
} from "@geist-ui/core/dist"
|
} from "@geist-ui/core/dist"
|
||||||
import HtmlPreview from "@components/preview"
|
import HtmlPreview from "app/(posts)/new/components/edit-document-list/edit-document/preview"
|
||||||
import FadeIn from "@components/fade-in"
|
import FadeIn from "app/components/fade-in"
|
||||||
|
|
||||||
// import Link from "next/link"
|
// import Link from "next/link"
|
||||||
type Props = {
|
type Props = {
|
|
@ -1,4 +1,4 @@
|
||||||
import PageSeo from "@components/page-seo"
|
import PageSeo from "app/components/page-seo"
|
||||||
import { getPostById } from "@lib/server/prisma"
|
import { getPostById } from "@lib/server/prisma"
|
||||||
|
|
||||||
export default async function Head({
|
export default async function Head({
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import type { GetServerSideProps } from "next"
|
import type { GetServerSideProps } from "next"
|
||||||
|
|
||||||
import type { Post } from "@lib/types"
|
import type { Post } from "@lib/types"
|
||||||
import PostPage from "@components/post-page"
|
import PostPage from "app/(posts)/post/[id]/components/post-page"
|
||||||
import { USER_COOKIE_NAME } from "@lib/constants"
|
import { USER_COOKIE_NAME } from "@lib/constants"
|
||||||
import { notFound } from "next/navigation"
|
import { notFound } from "next/navigation"
|
||||||
import { getPostById } from "@lib/server/prisma"
|
import { getPostById } from "@lib/server/prisma"
|
||||||
import { getCurrentUser, getSession } from "@lib/server/session"
|
import { getCurrentUser, getSession } from "@lib/server/session"
|
||||||
import Header from "@components/header"
|
import Header from "app/components/header"
|
||||||
|
|
||||||
export type PostProps = {
|
export type PostProps = {
|
||||||
post: Post
|
post: Post
|
||||||
|
|
|
@ -4,7 +4,7 @@ import byteToMB from "@lib/byte-to-mb"
|
||||||
import { Post } from "@lib/types"
|
import { Post } from "@lib/types"
|
||||||
import Table from "rc-table"
|
import Table from "rc-table"
|
||||||
import { useEffect, useMemo, useState } from "react"
|
import { useEffect, useMemo, useState } from "react"
|
||||||
import { adminFetcher } from "."
|
import { adminFetcher } from "./admin"
|
||||||
import ActionDropdown from "./action-dropdown"
|
import ActionDropdown from "./action-dropdown"
|
||||||
|
|
||||||
const PostTable = () => {
|
const PostTable = () => {
|
|
@ -1,7 +1,7 @@
|
||||||
import { Fieldset, useToasts } from "@geist-ui/core/dist"
|
import { Fieldset, useToasts } from "@geist-ui/core/dist"
|
||||||
import { User } from "@lib/types"
|
import { User } from "@lib/types"
|
||||||
import { useEffect, useMemo, useState } from "react"
|
import { useEffect, useMemo, useState } from "react"
|
||||||
import { adminFetcher } from "."
|
import { adminFetcher } from "./admin"
|
||||||
import Table from "rc-table"
|
import Table from "rc-table"
|
||||||
import SettingsGroup from "@components/settings-group"
|
import SettingsGroup from "@components/settings-group"
|
||||||
import ActionDropdown from "./action-dropdown"
|
import ActionDropdown from "./action-dropdown"
|
|
@ -1,8 +1,5 @@
|
||||||
import Admin from "@components/admin"
|
import Admin from "./components/admin"
|
||||||
import { TOKEN_COOKIE_NAME } from "@lib/constants"
|
|
||||||
import { isUserAdmin } from "@lib/server/prisma"
|
|
||||||
import { getCurrentUser } from "@lib/server/session"
|
import { getCurrentUser } from "@lib/server/session"
|
||||||
import { cookies } from "next/headers"
|
|
||||||
import { notFound } from "next/navigation"
|
import { notFound } from "next/navigation"
|
||||||
|
|
||||||
const AdminPage = async () => {
|
const AdminPage = async () => {
|
||||||
|
|
|
@ -27,6 +27,7 @@ import { useTheme } from "next-themes"
|
||||||
// import useUserData from "@lib/hooks/use-user-data"
|
// import useUserData from "@lib/hooks/use-user-data"
|
||||||
import Link from "next/link"
|
import Link from "next/link"
|
||||||
import { usePathname } from "next/navigation"
|
import { usePathname } from "next/navigation"
|
||||||
|
import { signOut } from "next-auth/react"
|
||||||
|
|
||||||
type Tab = {
|
type Tab = {
|
||||||
name: string
|
name: string
|
||||||
|
@ -99,7 +100,7 @@ const Header = ({ signedIn = false }) => {
|
||||||
name: "sign out",
|
name: "sign out",
|
||||||
icon: <SignOutIcon />,
|
icon: <SignOutIcon />,
|
||||||
value: "signout",
|
value: "signout",
|
||||||
href: "/signout"
|
onClick: () => signOut()
|
||||||
},
|
},
|
||||||
...defaultPages
|
...defaultPages
|
||||||
])
|
])
|
|
@ -1,5 +1,5 @@
|
||||||
"use client"
|
"use client"
|
||||||
import ShiftBy from "@components/shift-by"
|
import ShiftBy from "app/components/shift-by"
|
||||||
import { Spacer, Tabs, Card, Textarea, Text } from "@geist-ui/core/dist"
|
import { Spacer, Tabs, Card, Textarea, Text } from "@geist-ui/core/dist"
|
||||||
import Image from "next/image"
|
import Image from "next/image"
|
||||||
import styles from "./home.module.css"
|
import styles from "./home.module.css"
|
|
@ -7,7 +7,7 @@ import ListItemSkeleton from "./list-item-skeleton"
|
||||||
import ListItem from "./list-item"
|
import ListItem from "./list-item"
|
||||||
import { ChangeEvent, useCallback, useEffect, useState } from "react"
|
import { ChangeEvent, useCallback, useEffect, useState } from "react"
|
||||||
import useDebounce from "@lib/hooks/use-debounce"
|
import useDebounce from "@lib/hooks/use-debounce"
|
||||||
import Link from "@components/link"
|
import Link from "app/components/link"
|
||||||
import { TOKEN_COOKIE_NAME } from "@lib/constants"
|
import { TOKEN_COOKIE_NAME } from "@lib/constants"
|
||||||
import { getCookie } from "cookies-next"
|
import { getCookie } from "cookies-next"
|
||||||
import type { PostWithFiles } from "@lib/server/prisma"
|
import type { PostWithFiles } from "@lib/server/prisma"
|
|
@ -7,15 +7,15 @@ import {
|
||||||
Badge,
|
Badge,
|
||||||
Button
|
Button
|
||||||
} from "@geist-ui/core/dist"
|
} from "@geist-ui/core/dist"
|
||||||
import FadeIn from "@components/fade-in"
|
import FadeIn from "app/components/fade-in"
|
||||||
import Trash from "@geist-ui/icons/trash"
|
import Trash from "@geist-ui/icons/trash"
|
||||||
import ExpirationBadge from "@components/badges/expiration-badge"
|
import ExpirationBadge from "app/components/badges/expiration-badge"
|
||||||
import CreatedAgoBadge from "@components/badges/created-ago-badge"
|
import CreatedAgoBadge from "app/components/badges/created-ago-badge"
|
||||||
import Edit from "@geist-ui/icons/edit"
|
import Edit from "@geist-ui/icons/edit"
|
||||||
import { useRouter } from "next/navigation"
|
import { useRouter } from "next/navigation"
|
||||||
import Parent from "@geist-ui/icons/arrowUpCircle"
|
import Parent from "@geist-ui/icons/arrowUpCircle"
|
||||||
import styles from "./list-item.module.css"
|
import styles from "./list-item.module.css"
|
||||||
import Link from "@components/link"
|
import Link from "app/components/link"
|
||||||
import type { PostWithFiles } from "@lib/server/prisma"
|
import type { PostWithFiles } from "@lib/server/prisma"
|
||||||
import type { PostVisibility } from "@lib/types"
|
import type { PostVisibility } from "@lib/types"
|
||||||
import type { File } from "@lib/server/prisma"
|
import type { File } from "@lib/server/prisma"
|
||||||
|
@ -40,10 +40,6 @@ const ListItem = ({
|
||||||
router.push(`/post/${post.parentId}`)
|
router.push(`/post/${post.parentId}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
console.log(post)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FadeIn>
|
<FadeIn>
|
||||||
<li key={post.id}>
|
<li key={post.id}>
|
|
@ -1,4 +1,4 @@
|
||||||
import PageSeo from "@components/page-seo"
|
import PageSeo from "app/components/page-seo"
|
||||||
|
|
||||||
export default function Head() {
|
export default function Head() {
|
||||||
return <PageSeo title="Drift - Your profile" isPrivate />
|
return <PageSeo title="Drift - Your profile" isPrivate />
|
|
@ -1,8 +1,8 @@
|
||||||
import { redirect } from "next/navigation"
|
import { redirect } from "next/navigation"
|
||||||
import { getPostsByUser } from "@lib/server/prisma"
|
import { getPostsByUser } from "@lib/server/prisma"
|
||||||
import PostList from "@components/post-list"
|
import PostList from "app/components/post-list"
|
||||||
import { getCurrentUser } from "@lib/server/session"
|
import { getCurrentUser } from "@lib/server/session"
|
||||||
import Header from "@components/header"
|
import Header from "app/components/header"
|
||||||
import { authOptions } from "@lib/server/auth"
|
import { authOptions } from "@lib/server/auth"
|
||||||
|
|
||||||
export default async function Mine() {
|
export default async function Mine() {
|
|
@ -1,7 +1,7 @@
|
||||||
import Header from "@components/header"
|
import Header from "app/components/header"
|
||||||
import { getCurrentUser } from "@lib/server/session"
|
import { getCurrentUser } from "@lib/server/session"
|
||||||
import { getWelcomeContent } from "pages/api/welcome"
|
import { getWelcomeContent } from "pages/api/welcome"
|
||||||
import Home from "./home"
|
import Home from "./components/home"
|
||||||
|
|
||||||
const getWelcomeData = async () => {
|
const getWelcomeData = async () => {
|
||||||
const welcomeContent = await getWelcomeContent()
|
const welcomeContent = await getWelcomeContent()
|
|
@ -1,4 +1,4 @@
|
||||||
import PageSeo from "@components/page-seo"
|
import PageSeo from "app/components/page-seo"
|
||||||
|
|
||||||
export default function Head() {
|
export default function Head() {
|
||||||
return <PageSeo title="Drift - Settings" isPrivate />
|
return <PageSeo title="Drift - Settings" isPrivate />
|
|
@ -1,7 +1,7 @@
|
||||||
import Header from "@components/header"
|
import Header from "app/components/header"
|
||||||
import SettingsGroup from "@components/settings-group"
|
import SettingsGroup from "./components/settings-group"
|
||||||
import Password from "@components/settings/sections/password"
|
import Password from "app/settings/components/sections/password"
|
||||||
import Profile from "@components/settings/sections/profile"
|
import Profile from "app/settings/components/sections/profile"
|
||||||
import { authOptions } from "@lib/server/auth"
|
import { authOptions } from "@lib/server/auth"
|
||||||
import { getCurrentUser } from "@lib/server/session"
|
import { getCurrentUser } from "@lib/server/session"
|
||||||
import { redirect } from "next/navigation"
|
import { redirect } from "next/navigation"
|
|
@ -1,66 +0,0 @@
|
||||||
import Header from "@components/header"
|
|
||||||
import { GeistProvider, CssBaseline, Themes, Page } from "@geist-ui/core/dist"
|
|
||||||
import type { NextComponentType, NextPageContext } from "next"
|
|
||||||
import { SkeletonTheme } from "react-loading-skeleton"
|
|
||||||
|
|
||||||
const App = ({
|
|
||||||
Component,
|
|
||||||
pageProps
|
|
||||||
}: {
|
|
||||||
Component: NextComponentType<NextPageContext, any, any>
|
|
||||||
pageProps: any
|
|
||||||
}) => {
|
|
||||||
const skeletonBaseColor = "var(--light-gray)"
|
|
||||||
const skeletonHighlightColor = "var(--lighter-gray)"
|
|
||||||
|
|
||||||
const customTheme = Themes.createFromLight({
|
|
||||||
type: "custom",
|
|
||||||
palette: {
|
|
||||||
background: "var(--bg)",
|
|
||||||
foreground: "var(--fg)",
|
|
||||||
accents_1: "var(--lightest-gray)",
|
|
||||||
accents_2: "var(--lighter-gray)",
|
|
||||||
accents_3: "var(--light-gray)",
|
|
||||||
accents_4: "var(--gray)",
|
|
||||||
accents_5: "var(--darker-gray)",
|
|
||||||
accents_6: "var(--darker-gray)",
|
|
||||||
accents_7: "var(--darkest-gray)",
|
|
||||||
accents_8: "var(--darkest-gray)",
|
|
||||||
border: "var(--light-gray)",
|
|
||||||
warning: "var(--warning)"
|
|
||||||
},
|
|
||||||
expressiveness: {
|
|
||||||
dropdownBoxShadow: "0 0 0 1px var(--light-gray)",
|
|
||||||
shadowSmall: "0 0 0 1px var(--light-gray)",
|
|
||||||
shadowLarge: "0 0 0 1px var(--light-gray)",
|
|
||||||
shadowMedium: "0 0 0 1px var(--light-gray)"
|
|
||||||
},
|
|
||||||
layout: {
|
|
||||||
gap: "var(--gap)",
|
|
||||||
gapHalf: "var(--gap-half)",
|
|
||||||
gapQuarter: "var(--gap-quarter)",
|
|
||||||
gapNegative: "var(--gap-negative)",
|
|
||||||
gapHalfNegative: "var(--gap-half-negative)",
|
|
||||||
gapQuarterNegative: "var(--gap-quarter-negative)",
|
|
||||||
radius: "var(--radius)"
|
|
||||||
},
|
|
||||||
font: {
|
|
||||||
mono: "var(--font-mono)",
|
|
||||||
sans: "var(--font-sans)"
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return (
|
|
||||||
<GeistProvider themes={[customTheme]} themeType={"custom"}>
|
|
||||||
<SkeletonTheme
|
|
||||||
baseColor={skeletonBaseColor}
|
|
||||||
highlightColor={skeletonHighlightColor}
|
|
||||||
>
|
|
||||||
<CssBaseline />
|
|
||||||
<Header />
|
|
||||||
<Component {...pageProps} />
|
|
||||||
</SkeletonTheme>
|
|
||||||
</GeistProvider>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default App
|
|
|
@ -1,14 +1,14 @@
|
||||||
import { PrismaAdapter } from "@next-auth/prisma-adapter"
|
import { PrismaAdapter } from "@next-auth/prisma-adapter"
|
||||||
import { NextAuthOptions } from "next-auth"
|
import { NextAuthOptions } from "next-auth"
|
||||||
import GitHubProvider from "next-auth/providers/github"
|
import GitHubProvider from "next-auth/providers/github"
|
||||||
import prisma from "lib/server/prisma"
|
import prisma from "@lib/server/prisma"
|
||||||
import config from "@lib/config"
|
import config from "@lib/config"
|
||||||
|
|
||||||
const providers: NextAuthOptions["providers"] = [
|
const providers: NextAuthOptions["providers"] = [
|
||||||
GitHubProvider({
|
GitHubProvider({
|
||||||
clientId: config.GITHUB_CLIENT_ID,
|
clientId: config.GITHUB_CLIENT_ID,
|
||||||
clientSecret: config.GITHUB_CLIENT_SECRET
|
clientSecret: config.GITHUB_CLIENT_SECRET
|
||||||
}),
|
})
|
||||||
]
|
]
|
||||||
|
|
||||||
export const authOptions: NextAuthOptions = {
|
export const authOptions: NextAuthOptions = {
|
||||||
|
@ -41,7 +41,7 @@ export const authOptions: NextAuthOptions = {
|
||||||
})
|
})
|
||||||
|
|
||||||
if (!dbUser) {
|
if (!dbUser) {
|
||||||
// TODO: user should be defined?
|
// TODO: user should be defined? should we invalidate/signout?
|
||||||
if (user) {
|
if (user) {
|
||||||
token.id = user.id
|
token.id = user.id
|
||||||
token.role = "user"
|
token.role = "user"
|
||||||
|
@ -59,4 +59,3 @@ export const authOptions: NextAuthOptions = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} as const
|
} as const
|
||||||
|
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
import config from "@lib/config"
|
|
||||||
import { User } from "@prisma/client"
|
|
||||||
import prisma from "@lib/server/prisma"
|
|
||||||
import { sign } from "jsonwebtoken"
|
|
||||||
|
|
||||||
export async function generateAndExpireAccessToken(userId: User["id"]) {
|
|
||||||
const token = sign({ id: userId }, config.jwt_secret, { expiresIn: "2d" })
|
|
||||||
|
|
||||||
await prisma.authTokens.create({
|
|
||||||
data: {
|
|
||||||
userId: userId,
|
|
||||||
token: token
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// TODO: set expiredReason?
|
|
||||||
prisma.authTokens.deleteMany({
|
|
||||||
where: {
|
|
||||||
userId: userId,
|
|
||||||
token: {
|
|
||||||
not: token
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return token
|
|
||||||
}
|
|
|
@ -4,8 +4,6 @@ declare global {
|
||||||
|
|
||||||
import config from "@lib/config"
|
import config from "@lib/config"
|
||||||
import { Post, PrismaClient, File, User } from "@prisma/client"
|
import { Post, PrismaClient, File, User } from "@prisma/client"
|
||||||
import { cache } from "react"
|
|
||||||
import { generateAndExpireAccessToken } from "./generate-access-token"
|
|
||||||
|
|
||||||
const prisma = new PrismaClient()
|
const prisma = new PrismaClient()
|
||||||
|
|
||||||
|
@ -140,23 +138,11 @@ export const createUser = async (
|
||||||
throw new Error("Wrong registration password")
|
throw new Error("Wrong registration password")
|
||||||
}
|
}
|
||||||
|
|
||||||
// const salt = await genSalt(10)
|
|
||||||
|
|
||||||
// the first user is the admin
|
|
||||||
const isUserAdminByDefault =
|
const isUserAdminByDefault =
|
||||||
config.enable_admin && (await prisma.user.count()) === 0
|
config.enable_admin && (await prisma.user.count()) === 0
|
||||||
const userRole = isUserAdminByDefault ? "admin" : "user"
|
const userRole = isUserAdminByDefault ? "admin" : "user"
|
||||||
|
|
||||||
// const user = await prisma.user.create({
|
|
||||||
// data: {
|
|
||||||
// username,
|
|
||||||
// password: await bcrypt.hash(password, salt),
|
|
||||||
// role: userRole,
|
|
||||||
// },
|
|
||||||
// })
|
|
||||||
|
|
||||||
// const token = await generateAndExpireAccessToken(user.id)
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
// user,
|
// user,
|
||||||
// token
|
// token
|
||||||
|
|
|
@ -1,59 +0,0 @@
|
||||||
import "@styles/globals.css"
|
|
||||||
import type { AppProps as NextAppProps } from "next/app"
|
|
||||||
|
|
||||||
import "react-loading-skeleton/dist/skeleton.css"
|
|
||||||
import Head from "next/head"
|
|
||||||
import { ThemeProvider } from "next-themes"
|
|
||||||
import App from "@components/app"
|
|
||||||
import React from "react"
|
|
||||||
|
|
||||||
type AppProps<P = any> = {
|
|
||||||
pageProps: P
|
|
||||||
} & Omit<NextAppProps<P>, "pageProps">
|
|
||||||
|
|
||||||
function MyApp({ Component, pageProps }: AppProps) {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<Head>
|
|
||||||
<meta charSet="utf-8" />
|
|
||||||
<meta
|
|
||||||
name="viewport"
|
|
||||||
content="width=device-width, initial-scale=1, shrink-to-fit=no"
|
|
||||||
/>
|
|
||||||
<link
|
|
||||||
rel="apple-touch-icon"
|
|
||||||
sizes="180x180"
|
|
||||||
href="/assets/apple-touch-icon.png"
|
|
||||||
/>
|
|
||||||
<link
|
|
||||||
rel="icon"
|
|
||||||
type="image/png"
|
|
||||||
sizes="32x32"
|
|
||||||
href="/assets/favicon-32x32.png"
|
|
||||||
/>
|
|
||||||
<link
|
|
||||||
rel="icon"
|
|
||||||
type="image/png"
|
|
||||||
sizes="16x16"
|
|
||||||
href="/assets/favicon-16x16.png"
|
|
||||||
/>
|
|
||||||
<link rel="manifest" href="/site.webmanifest" />
|
|
||||||
<link
|
|
||||||
rel="mask-icon"
|
|
||||||
href="/assets/safari-pinned-tab.svg"
|
|
||||||
color="#5bbad5"
|
|
||||||
/>
|
|
||||||
<meta name="apple-mobile-web-app-title" content="Drift" />
|
|
||||||
<meta name="application-name" content="Drift" />
|
|
||||||
<meta name="msapplication-TileColor" content="#da532c" />
|
|
||||||
<meta name="theme-color" content="#ffffff" />
|
|
||||||
<title>Drift</title>
|
|
||||||
</Head>
|
|
||||||
<ThemeProvider defaultTheme="system" disableTransitionOnChange>
|
|
||||||
<App Component={Component} pageProps={pageProps} />
|
|
||||||
</ThemeProvider>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default MyApp
|
|
|
@ -1,39 +0,0 @@
|
||||||
import { CssBaseline } from "@geist-ui/core/dist"
|
|
||||||
import Document, {
|
|
||||||
Html,
|
|
||||||
Head,
|
|
||||||
Main,
|
|
||||||
NextScript,
|
|
||||||
DocumentContext
|
|
||||||
} from "next/document"
|
|
||||||
|
|
||||||
class MyDocument extends Document {
|
|
||||||
static async getInitialProps(ctx: DocumentContext) {
|
|
||||||
const initialProps = await Document.getInitialProps(ctx)
|
|
||||||
const styles = CssBaseline.flush()
|
|
||||||
|
|
||||||
return {
|
|
||||||
...initialProps,
|
|
||||||
styles: (
|
|
||||||
<>
|
|
||||||
{initialProps.styles}
|
|
||||||
{styles}
|
|
||||||
</> // TODO: Investigate typescript
|
|
||||||
) as any
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<Html lang="en">
|
|
||||||
<Head />
|
|
||||||
<body>
|
|
||||||
<Main />
|
|
||||||
<NextScript />
|
|
||||||
</body>
|
|
||||||
</Html>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default MyDocument
|
|
|
@ -1,12 +0,0 @@
|
||||||
import ErrorComponent from "@components/error"
|
|
||||||
|
|
||||||
function Error({ statusCode }: { statusCode: number }) {
|
|
||||||
return <ErrorComponent status={statusCode} />
|
|
||||||
}
|
|
||||||
|
|
||||||
Error.getInitialProps = ({ res, err }: { res: any; err: any }) => {
|
|
||||||
const statusCode = res ? res.statusCode : err ? err.statusCode : 404
|
|
||||||
return { statusCode }
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Error
|
|
|
@ -1,51 +0,0 @@
|
||||||
import { NextApiRequest, NextApiResponse } from "next"
|
|
||||||
import prisma from "@lib/server/prisma"
|
|
||||||
import bcrypt from "bcrypt"
|
|
||||||
import { signin } from "@lib/server/signin"
|
|
||||||
import { setCookie } from "cookies-next"
|
|
||||||
import { TOKEN_COOKIE_NAME, USER_COOKIE_NAME } from "@lib/constants"
|
|
||||||
|
|
||||||
export default async function handler(
|
|
||||||
req: NextApiRequest,
|
|
||||||
res: NextApiResponse
|
|
||||||
) {
|
|
||||||
const { username, password } = req.body
|
|
||||||
if (!username || !password) {
|
|
||||||
return res.status(400).json({ error: "Missing param" })
|
|
||||||
}
|
|
||||||
|
|
||||||
const user = await prisma.user.findFirst({
|
|
||||||
where: {
|
|
||||||
username
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
if (!user || !user.password) {
|
|
||||||
return res.status(401).json({ error: "Unauthorized" })
|
|
||||||
}
|
|
||||||
|
|
||||||
const isPasswordValid = await bcrypt.compare(password, user.password)
|
|
||||||
if (!isPasswordValid) {
|
|
||||||
return res.status(401).json({ error: "Unauthorized" })
|
|
||||||
}
|
|
||||||
|
|
||||||
const token = await signin(user.id, req, res)
|
|
||||||
setCookie(TOKEN_COOKIE_NAME, token, {
|
|
||||||
path: "/",
|
|
||||||
maxAge: 60 * 60 * 24 * 7, // 1 week
|
|
||||||
httpOnly: true,
|
|
||||||
secure: process.env.NODE_ENV === "production",
|
|
||||||
req,
|
|
||||||
res
|
|
||||||
})
|
|
||||||
setCookie(USER_COOKIE_NAME, user.id, {
|
|
||||||
path: "/",
|
|
||||||
maxAge: 60 * 60 * 24 * 7, // 1 week
|
|
||||||
httpOnly: true,
|
|
||||||
secure: process.env.NODE_ENV === "production",
|
|
||||||
req,
|
|
||||||
res
|
|
||||||
})
|
|
||||||
|
|
||||||
return res.status(201).json({ token: token, userId: user.id })
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
import { NextApiRequest, NextApiResponse } from "next"
|
|
||||||
import { createUser } from "@lib/server/prisma"
|
|
||||||
|
|
||||||
export default async function handler(
|
|
||||||
req: NextApiRequest,
|
|
||||||
res: NextApiResponse
|
|
||||||
) {
|
|
||||||
const { username, password, serverPassword } = req.body
|
|
||||||
const { user, token } = await createUser(username, password, serverPassword)
|
|
||||||
|
|
||||||
return res.status(201).json({ token: token, userId: user.id })
|
|
||||||
}
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { NextApiRequest, NextApiResponse } from "next"
|
import { NextApiRequest, NextApiResponse } from "next"
|
||||||
import prisma from "lib/server/prisma"
|
import prisma from "@lib/server/prisma"
|
||||||
import { parseQueryParam } from "@lib/server/parse-query-param"
|
import { parseQueryParam } from "@lib/server/parse-query-param"
|
||||||
|
|
||||||
const getRawFile = async (req: NextApiRequest, res: NextApiResponse) => {
|
const getRawFile = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||||
|
|
|
@ -9,10 +9,10 @@ import {
|
||||||
import { authOptions } from "@lib/server/auth"
|
import { authOptions } from "@lib/server/auth"
|
||||||
import { CreatePostSchema } from "@lib/validations/post"
|
import { CreatePostSchema } from "@lib/validations/post"
|
||||||
import { Post } from "@prisma/client"
|
import { Post } from "@prisma/client"
|
||||||
import prisma, { getPostById } from "lib/server/prisma"
|
import prisma, { getPostById } from "@lib/server/prisma"
|
||||||
import { NextApiRequest, NextApiResponse } from "next"
|
import { NextApiRequest, NextApiResponse } from "next"
|
||||||
import { unstable_getServerSession } from "next-auth/next"
|
import { unstable_getServerSession } from "next-auth/next"
|
||||||
import { File } from "lib/server/prisma"
|
import { File } from "@lib/server/prisma"
|
||||||
import * as crypto from "crypto"
|
import * as crypto from "crypto"
|
||||||
import { getHtmlFromFile } from "@lib/server/get-html-from-drift-file"
|
import { getHtmlFromFile } from "@lib/server/get-html-from-drift-file"
|
||||||
import { getSession } from "next-auth/react"
|
import { getSession } from "next-auth/react"
|
||||||
|
|
|
@ -113,7 +113,6 @@ model User {
|
||||||
role String? @default("user")
|
role String? @default("user")
|
||||||
password String? @db.Text
|
password String? @db.Text
|
||||||
|
|
||||||
|
|
||||||
@@map("users")
|
@@map("users")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,13 +39,13 @@
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
"paths": {
|
"paths": {
|
||||||
"@components/*": [
|
"@components/*": [
|
||||||
"components/*"
|
"app/components/*"
|
||||||
],
|
],
|
||||||
"@lib/*": [
|
"@lib/*": [
|
||||||
"lib/*"
|
"lib/*"
|
||||||
],
|
],
|
||||||
"@styles/*": [
|
"@styles/*": [
|
||||||
"styles/*"
|
"app/styles/*"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue