diff --git a/client/components/edit-document/formatting-icons/index.tsx b/client/components/edit-document/formatting-icons/index.tsx index 08ba4133..ca39c04e 100644 --- a/client/components/edit-document/formatting-icons/index.tsx +++ b/client/components/edit-document/formatting-icons/index.tsx @@ -10,49 +10,43 @@ import { TextareaMarkdownRef } from "textarea-markdown-editor" // TODO: clean up const FormattingIcons = ({ - textareaRef, + textareaRef }: { textareaRef?: RefObject }) => { - - - - const formattingActions = useMemo( - () => { - const handleBoldClick = () => textareaRef?.current?.trigger("bold") - const handleItalicClick = () => textareaRef?.current?.trigger("italic") - const handleLinkClick = () => textareaRef?.current?.trigger("link") - const handleImageClick = () => textareaRef?.current?.trigger("image") - return [ - { - icon: , - name: "bold", - action: handleBoldClick - }, - { - icon: , - name: "italic", - action: handleItalicClick - }, - // { - // icon: , - // name: 'underline', - // action: handleUnderlineClick - // }, - { - icon: , - name: "hyperlink", - action: handleLinkClick - }, - { - icon: , - name: "image", - action: handleImageClick - } - ] - }, - [textareaRef] - ) + const formattingActions = useMemo(() => { + const handleBoldClick = () => textareaRef?.current?.trigger("bold") + const handleItalicClick = () => textareaRef?.current?.trigger("italic") + const handleLinkClick = () => textareaRef?.current?.trigger("link") + const handleImageClick = () => textareaRef?.current?.trigger("image") + return [ + { + icon: , + name: "bold", + action: handleBoldClick + }, + { + icon: , + name: "italic", + action: handleItalicClick + }, + // { + // icon: , + // name: 'underline', + // action: handleUnderlineClick + // }, + { + icon: , + name: "hyperlink", + action: handleLinkClick + }, + { + icon: , + name: "image", + action: handleImageClick + } + ] + }, [textareaRef]) return (
diff --git a/client/components/edit-document/index.tsx b/client/components/edit-document/index.tsx index 980a0866..a675f17a 100644 --- a/client/components/edit-document/index.tsx +++ b/client/components/edit-document/index.tsx @@ -9,15 +9,9 @@ import { import styles from "./document.module.css" import Trash from "@geist-ui/icons/trash" 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" +import { Button, Input, Spacer, Tabs, Textarea } from "@geist-ui/core" import Preview from "@components/preview" // import Link from "next/link" @@ -121,9 +115,7 @@ const Document = ({ )}
- {tab === "edit" && ( - - )} + {tab === "edit" && } {items.map((item) => (
  • @@ -61,6 +61,7 @@ const FileDropdown = ({
  • ))} + ) // a list of files with an icon and a title return ( diff --git a/client/components/new-post/index.tsx b/client/components/new-post/index.tsx index 87459370..46d5606d 100644 --- a/client/components/new-post/index.tsx +++ b/client/components/new-post/index.tsx @@ -65,7 +65,6 @@ const Post = ({ } }, [emptyDoc, initialPost]) - const [passwordModalVisible, setPasswordModalVisible] = useState(false) const sendRequest = useCallback( diff --git a/client/components/post-list/index.tsx b/client/components/post-list/index.tsx index 5f52ef17..7b2440a1 100644 --- a/client/components/post-list/index.tsx +++ b/client/components/post-list/index.tsx @@ -1,4 +1,4 @@ -import { Button, Code, Dot, Input, Note, Text } from "@geist-ui/core" +import { Button, Input, Select, Text } from "@geist-ui/core" import NextLink from "next/link" import Link from "../Link" @@ -7,8 +7,8 @@ import ListItemSkeleton from "./list-item-skeleton" import ListItem from "./list-item" import { Post } from "@lib/types" import { ChangeEvent, useCallback, useEffect, useMemo, useState } from "react" -import debounce from "lodash.debounce" import Cookies from "js-cookie" +import useDebounce from "@lib/hooks/use-debounce" type Props = { initialPosts: Post[] @@ -21,6 +21,9 @@ const PostList = ({ morePosts, initialPosts, error }: Props) => { const [posts, setPosts] = useState(initialPosts) const [searching, setSearching] = useState(false) const [hasMorePosts, setHasMorePosts] = useState(morePosts) + + const debouncedSearchValue = useDebounce(search, 200) + const loadMoreClick = useCallback( (e: React.MouseEvent) => { e.preventDefault() @@ -46,13 +49,15 @@ const PostList = ({ morePosts, initialPosts, error }: Props) => { // update posts on search useEffect(() => { - if (search) { + if (debouncedSearchValue) { // fetch results from /server-api/posts/search const fetchResults = async () => { setSearching(true) //encode search const res = await fetch( - `/server-api/posts/search?q=${encodeURIComponent(search)}`, + `/server-api/posts/search?q=${encodeURIComponent( + debouncedSearchValue + )}`, { method: "GET", headers: { @@ -70,22 +75,22 @@ const PostList = ({ morePosts, initialPosts, error }: Props) => { } else { setPosts(initialPosts) } - }, [initialPosts, search]) + }, [initialPosts, debouncedSearchValue]) const handleSearchChange = (e: ChangeEvent) => { setSearchValue(e.target.value) } - const debouncedSearchHandler = useMemo( - () => debounce(handleSearchChange, 300), - [] - ) + // const debouncedSearchHandler = useMemo( + // () => debounce(handleSearchChange, 300), + // [] + // ) - useEffect(() => { - return () => { - debouncedSearchHandler.cancel() - } - }, [debouncedSearchHandler]) + // useEffect(() => { + // return () => { + // debouncedSearchHandler.cancel() + // } + // }, [debouncedSearchHandler]) const deletePost = useCallback( (postId: string) => async () => { @@ -114,7 +119,7 @@ const PostList = ({ morePosts, initialPosts, error }: Props) => { scale={3 / 2} clearable placeholder="Search..." - onChange={debouncedSearchHandler} + onChange={handleSearchChange} />
    {error && Failed to load.} diff --git a/client/components/post-list/post-list.module.css b/client/components/post-list/post-list.module.css index 2c9fdc71..f81421c2 100644 --- a/client/components/post-list/post-list.module.css +++ b/client/components/post-list/post-list.module.css @@ -28,7 +28,8 @@ .searchContainer { display: flex; align-items: center; - flex-direction: column-reverse; + flex-direction: column; justify-content: center; - margin-bottom: var(--gap-double); + gap: var(--gap-half); + margin-bottom: var(--gap); } diff --git a/client/lib/get-title-for-post-copy.ts b/client/lib/get-title-for-post-copy.ts index f9b4d828..87a230e5 100644 --- a/client/lib/get-title-for-post-copy.ts +++ b/client/lib/get-title-for-post-copy.ts @@ -1,29 +1,35 @@ const replaceLastInString = ( - string: string, - search: string, - replace: string + string: string, + search: string, + replace: string ): string => { - const index = string.lastIndexOf(search); - if (index === -1) { - return string; - } - return string.substring(0, index) + replace + string.substring(index + search.length); + const index = string.lastIndexOf(search) + if (index === -1) { + return string + } + return ( + string.substring(0, index) + + replace + + string.substring(index + search.length) + ) } -const getTitleForPostCopy = ( - title: string, -) => { - const numberAtEndOfTitle = title.split(" ").pop() - if (numberAtEndOfTitle) { - const number = parseInt(numberAtEndOfTitle) - if (number) { - return replaceLastInString(title, numberAtEndOfTitle, (number + 1).toString()) - } else { - return title + " 1" - } - } else { - return title + " 1" - } +const getTitleForPostCopy = (title: string) => { + const numberAtEndOfTitle = title.split(" ").pop() + if (numberAtEndOfTitle) { + const number = parseInt(numberAtEndOfTitle) + if (number) { + return replaceLastInString( + title, + numberAtEndOfTitle, + (number + 1).toString() + ) + } else { + return title + " 1" + } + } else { + return title + " 1" + } } -export default getTitleForPostCopy \ No newline at end of file +export default getTitleForPostCopy diff --git a/client/lib/hooks/use-debounce.ts b/client/lib/hooks/use-debounce.ts index 432edc0f..b40521de 100644 --- a/client/lib/hooks/use-debounce.ts +++ b/client/lib/hooks/use-debounce.ts @@ -1,7 +1,6 @@ -// useDebounce.js import { useState, useEffect } from "react" -export default function useDebounce(value: any, delay: number) { +export default function useDebounce(value: T, delay: number) { const [debouncedValue, setDebouncedValue] = useState(value) useEffect(() => { diff --git a/client/package.json b/client/package.json index 64ae7d8a..81502643 100644 --- a/client/package.json +++ b/client/package.json @@ -19,7 +19,6 @@ "cookie": "^0.4.2", "dotenv": "^16.0.0", "js-cookie": "^3.0.1", - "lodash.debounce": "^4.0.8", "marked": "^4.0.12", "next": "^12.1.1-canary.15", "next-themes": "^0.1.1", diff --git a/client/yarn.lock b/client/yarn.lock index f68da1a5..79f90166 100644 --- a/client/yarn.lock +++ b/client/yarn.lock @@ -2310,11 +2310,6 @@ lodash.camelcase@^4.3.0: resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY= -lodash.debounce@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" - integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= - lodash.merge@^4.6.2: version "4.6.2" resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" diff --git a/server/src/routes/posts.ts b/server/src/routes/posts.ts index b70204f2..a6eded17 100644 --- a/server/src/routes/posts.ts +++ b/server/src/routes/posts.ts @@ -42,7 +42,7 @@ posts.post( parentId: Joi.string().optional().allow(null, "") } }), - async (req, res, next) => { + async (req, res) => { try { // check if all files have titles const files = req.body.files as File[] @@ -218,7 +218,13 @@ posts.get( }, { model: User, - as: "users" + as: "users", + attributes: ["id", "username"] + }, + { + model: Post, + as: "parent", + attributes: ["id", "title", "visibility"] } ], attributes: ["id", "title", "visibility", "createdAt", "deletedAt"],