Add description to posts (#71)

Closes #37
This commit is contained in:
Joaquin "Florius" Azcarate 2022-04-14 23:25:31 +02:00 committed by GitHub
parent 2ba613d562
commit 5df56fbdae
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 96 additions and 3 deletions

View file

@ -0,0 +1,25 @@
import { ChangeEvent, memo } from "react"
import { Input } from "@geist-ui/core"
import styles from "../post.module.css"
type props = {
onChange: (e: ChangeEvent<HTMLInputElement>) => void
description?: string
}
const Description = ({ onChange, description }: props) => {
return (
<div className={styles.description}>
<Input
value={description}
onChange={onChange}
label="Description"
maxLength={256}
width="100%"
/>
</div>
)
}
export default memo(Description)

View file

@ -24,6 +24,7 @@ import EditDocumentList from "@components/edit-document-list"
import { ChangeEvent } from "react"
import DatePicker from "react-datepicker"
import getTitleForPostCopy from "@lib/get-title-for-post-copy"
import Description from "./description"
const Post = ({
initialPost,
@ -35,6 +36,7 @@ const Post = ({
const { setToast } = useToasts()
const router = useRouter()
const [title, setTitle] = useState<string>()
const [description, setDescription] = useState<string>()
const [expiresAt, setExpiresAt] = useState<Date | null>(null)
const emptyDoc = useMemo(
@ -62,6 +64,7 @@ const Post = ({
)
setTitle(getTitleForPostCopy(initialPost.title))
setDescription(initialPost.description)
}
}, [emptyDoc, initialPost])
@ -88,6 +91,7 @@ const Post = ({
},
body: JSON.stringify({
title,
description,
files: docs,
...data
})
@ -187,6 +191,13 @@ const Post = ({
[setTitle]
)
const onChangeDescription = useCallback(
(e: ChangeEvent<HTMLTextAreaElement>) => {
setDescription(e.target.value)
},
[setDescription]
)
const updateDocTitle = useCallback(
(i: number) => (title: string) => {
setDocs((docs) =>
@ -284,6 +295,7 @@ const Post = ({
return (
<div style={{ paddingBottom: 150 }}>
<Title title={title} onChange={onChangeTitle} />
<Description description={description} onChange={onChangeDescription} />
<FileDropzone setDocs={uploadDocs} />
<EditDocumentList
onPaste={onPaste}

View file

@ -25,6 +25,12 @@
margin-bottom: var(--gap);
}
.description {
width: 100%;
margin-bottom: var(--gap);
}
@media screen and (max-width: 650px) {
.title {
align-items: flex-start;

View file

@ -13,6 +13,12 @@
gap: var(--gap-half);
}
.oneline {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
@media screen and (max-width: 700px) {
.badges {
flex-direction: column;

View file

@ -78,6 +78,12 @@ const ListItem = ({
)}
</Text>
{post.description && (
<Text p className={styles.oneline}>
{post.description}
</Text>
)}
<div className={styles.badges}>
<VisibilityBadge visibility={post.visibility} />
<CreatedAgoBadge createdAt={post.createdAt} />

View file

@ -149,6 +149,11 @@ const PostPage = ({ post: initialPost, isProtected }: Props) => {
</span>
</span>
</div>
{post.description && (
<div>
<Text p>{post.description}</Text>
</div>
)}
{/* {post.files.length > 1 && <FileTree files={post.files} />} */}
{post.files?.map(({ id, content, title }: File) => (
<DocumentComponent

View file

@ -55,6 +55,9 @@ export class Post extends Model {
@Column
title!: string
@Column
description?: string
@BelongsToMany(() => User, () => PostAuthor)
users?: User[]

View file

@ -0,0 +1,12 @@
"use strict"
import { DataTypes } from "sequelize"
import type { Migration } from "../database"
export const up: Migration = async ({ context: queryInterface }) =>
queryInterface.addColumn("posts", "description", {
type: DataTypes.STRING,
allowNull: true
})
export const down: Migration = async ({ context: queryInterface }) =>
await queryInterface.removeColumn("posts", "description")

View file

@ -31,6 +31,7 @@ posts.post(
celebrate({
body: {
title: Joi.string().required(),
description: Joi.string().optional().min(0).max(256),
files: Joi.any().required(),
visibility: Joi.string()
.custom(postVisibilitySchema, "valid visibility")
@ -66,6 +67,7 @@ posts.post(
const newPost = new Post({
title: req.body.title,
description: req.body.description,
visibility: req.body.visibility,
password: hashedPassword,
expiresAt: req.body.expiresAt
@ -126,7 +128,7 @@ posts.post(
posts.get("/", secretKey, async (req, res, next) => {
try {
const posts = await Post.findAll({
attributes: ["id", "title", "visibility", "createdAt"]
attributes: ["id", "title", "description", "visibility", "createdAt"]
})
res.json(posts)
} catch (e) {
@ -159,7 +161,14 @@ posts.get("/mine", jwt, async (req: UserJwtRequest, res, next) => {
attributes: ["id", "title", "visibility"]
}
],
attributes: ["id", "title", "visibility", "createdAt", "expiresAt"]
attributes: [
"id",
"title",
"description",
"visibility",
"createdAt",
"expiresAt"
]
}
]
})
@ -205,6 +214,7 @@ posts.get(
where: {
[Op.or]: [
{ title: { [Op.like]: `%${q}%` } },
{ description: { [Op.like]: `%${q}%` } },
{ "$files.title$": { [Op.like]: `%${q}%` } },
{ "$files.content$": { [Op.like]: `%${q}%` } }
],
@ -227,7 +237,14 @@ posts.get(
attributes: ["id", "title", "visibility"]
}
],
attributes: ["id", "title", "visibility", "createdAt", "deletedAt"],
attributes: [
"id",
"title",
"description",
"visibility",
"createdAt",
"deletedAt"
],
order: [["createdAt", "DESC"]]
})
@ -259,6 +276,7 @@ const fullPostSequelizeOptions = {
attributes: [
"id",
"title",
"description",
"visibility",
"createdAt",
"updatedAt",