This commit is contained in:
Pico2x 2022-08-29 15:59:52 +01:00
parent 2aff501c66
commit cc2a1962bc
5 changed files with 30 additions and 36 deletions

View File

@ -2,11 +2,11 @@ import { JSONContent } from '@tiptap/core'
export type Post = {
id: string
name: string
title: string
content: JSONContent
creatorId: string // User id
createdTime: number
slug: string
}
export const MAX_POST_NAME_LENGTH = 480
export const MAX_POST_TITLE_LENGTH = 480

View File

@ -3,7 +3,7 @@ import * as admin from 'firebase-admin'
import { getUser } from './utils'
import { slugify } from '../../common/util/slugify'
import { randomString } from '../../common/util/random'
import { Post, MAX_POST_NAME_LENGTH } from '../../common/post'
import { Post, MAX_POST_TITLE_LENGTH } from '../../common/post'
import { APIError, newEndpoint, validate } from './api'
import { JSONContent } from '@tiptap/core'
import { z } from 'zod'
@ -32,21 +32,21 @@ const contentSchema: z.ZodType<JSONContent> = z.lazy(() =>
)
const postSchema = z.object({
name: z.string().min(1).max(MAX_POST_NAME_LENGTH),
title: z.string().min(1).max(MAX_POST_TITLE_LENGTH),
content: contentSchema,
})
export const createpost = newEndpoint({}, async (req, auth) => {
const firestore = admin.firestore()
const { name, content } = validate(postSchema, req.body)
const { title, content } = validate(postSchema, req.body)
const creator = await getUser(auth.uid)
if (!creator)
throw new APIError(400, 'No user exists with the authenticated user ID.')
console.log('creating post owned by', creator.username, 'named', name)
console.log('creating post owned by', creator.username, 'titled', title)
const slug = await getSlug(name)
const slug = await getSlug(title)
const postRef = firestore.collection('posts').doc()
@ -54,18 +54,18 @@ export const createpost = newEndpoint({}, async (req, auth) => {
id: postRef.id,
creatorId: creator.id,
slug,
name,
title,
createdTime: Date.now(),
content: content,
}
await postRef.create(post)
return { status: 'success', post: post }
return { status: 'success', post }
})
export const getSlug = async (name: string) => {
const proposedSlug = slugify(name)
export const getSlug = async (title: string) => {
const proposedSlug = slugify(title)
const preexistingPost = await getPostFromSlug(proposedSlug)

View File

@ -1,5 +1,6 @@
import { auth } from './users'
import { APIError, getFunctionUrl } from 'common/api'
import { JSONContent } from '@tiptap/core'
export { APIError } from 'common/api'
export async function call(url: string, method: string, params: any) {
@ -89,6 +90,6 @@ export function getCurrentUser(params: any) {
return call(getFunctionUrl('getcurrentuser'), 'GET', params)
}
export function createPost(params: any) {
export function createPost(params: { title: string; content: JSONContent }) {
return call(getFunctionUrl('createpost'), 'POST', params)
}

View File

@ -7,26 +7,25 @@ import Textarea from 'react-expanding-textarea'
import { TextEditor, useTextEditor } from 'web/components/editor'
import { createPost } from 'web/lib/firebase/api'
import clsx from 'clsx'
import { useRouter } from 'next/router'
import { Post, MAX_POST_NAME_LENGTH } from 'common/post'
import Router from 'next/router'
import { MAX_POST_TITLE_LENGTH } from 'common/post'
import { postPath } from 'web/lib/firebase/posts'
export default function CreatePost() {
const [name, setName] = useState('')
const [title, setTitle] = useState('')
const [error, setError] = useState('')
const [isSubmitting, setIsSubmitting] = useState(false)
const router = useRouter()
const { editor, upload } = useTextEditor({
disabled: isSubmitting,
})
const isValid = editor && name.length > 0 && editor.isEmpty === false
const isValid = editor && title.length > 0 && editor.isEmpty === false
async function savePost(name: string) {
async function savePost(title: string) {
if (!editor) return
const newPost = {
name: name,
title: title,
content: editor.getJSON(),
}
@ -36,7 +35,7 @@ export default function CreatePost() {
return e
})
if (result.post) {
await router.push(postPath((result.post as Post).slug))
await Router.push(postPath(result.post.slug))
}
}
@ -49,21 +48,21 @@ export default function CreatePost() {
<div className="form-control w-full">
<label className="label">
<span className="mb-1">
Name<span className={'text-red-700'}>*</span>
Title<span className={'text-red-700'}> *</span>
</span>
</label>
<Textarea
placeholder="e.g. Elon Mania Post"
className="input input-bordered resize-none"
autoFocus
maxLength={MAX_POST_NAME_LENGTH}
value={name}
onChange={(e) => setName(e.target.value || '')}
maxLength={MAX_POST_TITLE_LENGTH}
value={title}
onChange={(e) => setTitle(e.target.value || '')}
/>
<Spacer h={6} />
<label className="label">
<span className="mb-1">
Content<span className={'text-red-700'}>*</span>
Content<span className={'text-red-700'}> *</span>
</span>
</label>
<TextEditor editor={editor} upload={upload} />
@ -78,7 +77,7 @@ export default function CreatePost() {
disabled={isSubmitting || !isValid || upload.isLoading}
onClick={async () => {
setIsSubmitting(true)
await savePost(name)
await savePost(title)
setIsSubmitting(false)
}}
>

View File

@ -1,6 +1,5 @@
import { Page } from 'web/components/page'
import { fromPropz, usePropz } from 'web/hooks/use-propz'
import { postPath, getPostBySlug } from 'web/lib/firebase/posts'
import { Post } from 'common/post'
import { Title } from 'web/components/title'
@ -18,13 +17,11 @@ import { Col } from 'web/components/layout/col'
import { ENV_CONFIG } from 'common/envs/constants'
import Custom404 from 'web/pages/404'
export const getStaticProps = fromPropz(getStaticPropz)
export async function getStaticPropz(props: { params: { slugs: string[] } }) {
export async function getStaticProps(props: { params: { slugs: string[] } }) {
const { slugs } = props.params
const post = await getPostBySlug(slugs[0])
const creatorPromise = post ? getUser(post.creatorId) : null
const creator = await creatorPromise
const creator = post ? await getUser(post.creatorId) : null
return {
props: {
@ -41,12 +38,9 @@ export async function getStaticPaths() {
}
export default function PostPage(props: { post: Post; creator: User }) {
props = usePropz(props, getStaticPropz) ?? {
post: null,
}
const [isShareOpen, setShareOpen] = useState(false)
if (props.post === null) {
if (props.post == null) {
return <Custom404 />
}
@ -56,7 +50,7 @@ export default function PostPage(props: { post: Post; creator: User }) {
<Page>
<div className="mx-auto w-full max-w-3xl ">
<Spacer h={1} />
<Title className="!mt-0" text={props.post.name} />
<Title className="!mt-0" text={props.post.title} />
<Row>
<Col className="flex-1">
<div className={'inline-flex'}>