From 6cfaa8e354df906cc7d8abb515590fc2ff91b831 Mon Sep 17 00:00:00 2001 From: MTG2000 Date: Wed, 15 Jun 2022 21:05:52 +0300 Subject: [PATCH] fix: fix multline breaks in post body, add slugs to urls --- src/App.tsx | 4 +- .../Inputs/TextEditor/SaveModule.tsx | 3 +- src/Components/Navbar/NavDesktop.tsx | 5 +- src/Components/Navbar/NavMobile.tsx | 5 +- .../Components/PostCard/Header/Header.tsx | 3 +- .../PostCard/StoryCard/StoryCard.tsx | 4 +- .../Components/TrendingCard/TrendingCard.tsx | 3 +- .../ContentEditor/ContentEditor.tsx | 15 ++++- .../Components/AuthorCard/AuthorCard.tsx | 3 +- .../pages/PostDetailsPage/PostDetailsPage.tsx | 5 +- src/utils/helperFunctions.tsx | 10 +++ src/utils/routing/index.ts | 1 + src/utils/routing/routes.ts | 61 +++++++++++++++++++ 13 files changed, 109 insertions(+), 13 deletions(-) create mode 100644 src/utils/routing/index.ts create mode 100644 src/utils/routing/routes.ts diff --git a/src/App.tsx b/src/App.tsx index 56bfecb..0cde4f7 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -83,7 +83,7 @@ function App() { } /> } /> - } /> + } /> } /> } /> } /> @@ -92,7 +92,7 @@ function App() { } /> - } /> + } /> } /> } /> diff --git a/src/Components/Inputs/TextEditor/SaveModule.tsx b/src/Components/Inputs/TextEditor/SaveModule.tsx index ea9186a..dc43fe2 100644 --- a/src/Components/Inputs/TextEditor/SaveModule.tsx +++ b/src/Components/Inputs/TextEditor/SaveModule.tsx @@ -19,7 +19,8 @@ export default function SaveModule(props: Props) { const changeCallback = useDebouncedCallback(ctx => { const { state } = ctx; - const md = getMarkdown(state); + let md = getMarkdown(state); + md = md.replace(/\n(?=\n)/g, "\n\n
\n"); onChange(md); }, [], 500) diff --git a/src/Components/Navbar/NavDesktop.tsx b/src/Components/Navbar/NavDesktop.tsx index 3e64fb7..5c6d14b 100644 --- a/src/Components/Navbar/NavDesktop.tsx +++ b/src/Components/Navbar/NavDesktop.tsx @@ -16,6 +16,7 @@ import { import '@szhsin/react-menu/dist/index.css'; import { FiChevronDown, FiLogIn } from "react-icons/fi"; import Avatar from "src/features/Profiles/Components/Avatar/Avatar"; +import { createRoute } from "src/utils/routing"; export default function NavDesktop() { @@ -171,10 +172,10 @@ export default function NavDesktop() { menuClassName='!p-8 !rounded-12' menuButton={ }> { e.syntheticEvent.preventDefault(); - navigate(`/profile/${curUser.id}`); + navigate(createRoute({ type: 'profile', id: curUser.id, username: curUser.name })); }} className='!p-16 font-medium flex gap-16 hover:bg-gray-100 !rounded-12' > diff --git a/src/Components/Navbar/NavMobile.tsx b/src/Components/Navbar/NavMobile.tsx index b44dc8f..9e39f5f 100644 --- a/src/Components/Navbar/NavMobile.tsx +++ b/src/Components/Navbar/NavMobile.tsx @@ -14,6 +14,7 @@ import styles from './styles.module.css' import '@szhsin/react-menu/dist/index.css'; import { Menu, MenuButton, MenuItem } from "@szhsin/react-menu"; import Avatar from "src/features/Profiles/Components/Avatar/Avatar"; +import { createRoute } from "src/utils/routing"; @@ -85,10 +86,10 @@ export default function NavMobile() { menuClassName='!p-8 !rounded-12' menuButton={ }> { e.syntheticEvent.preventDefault(); - navigate(`/profile/${curUser.id}`); + navigate(createRoute({ type: 'profile', id: curUser.id, username: curUser.name })); }} className='!p-16 font-medium flex gap-16 hover:bg-gray-100 !rounded-12' > diff --git a/src/features/Posts/Components/PostCard/Header/Header.tsx b/src/features/Posts/Components/PostCard/Header/Header.tsx index fc32eba..d4ab7b1 100644 --- a/src/features/Posts/Components/PostCard/Header/Header.tsx +++ b/src/features/Posts/Components/PostCard/Header/Header.tsx @@ -3,6 +3,7 @@ import dayjs from 'dayjs' import { UnionToObjectKeys } from 'src/utils/types/utils'; import { trimText } from 'src/utils/helperFunctions'; import { Link } from 'react-router-dom'; +import { createRoute } from 'src/utils/routing'; interface Props { author: { @@ -44,7 +45,7 @@ export default function Header({ return (
- +
diff --git a/src/features/Posts/Components/PostCard/StoryCard/StoryCard.tsx b/src/features/Posts/Components/PostCard/StoryCard/StoryCard.tsx index bfaaab3..7c2fcb9 100644 --- a/src/features/Posts/Components/PostCard/StoryCard/StoryCard.tsx +++ b/src/features/Posts/Components/PostCard/StoryCard/StoryCard.tsx @@ -6,6 +6,8 @@ import VoteButton from "src/Components/VoteButton/VoteButton" import { useVote } from "src/utils/hooks" import { Tag, Vote_Item_Type } from 'src/graphql'; import Badge from "src/Components/Badge/Badge" +import { toSlug } from "src/utils/helperFunctions" +import { createRoute } from "src/utils/routing" export type StoryCardType = Pick
- +

{story.title}

{story.excerpt}...

diff --git a/src/features/Posts/Components/TrendingCard/TrendingCard.tsx b/src/features/Posts/Components/TrendingCard/TrendingCard.tsx index 575a868..b6f9f6a 100644 --- a/src/features/Posts/Components/TrendingCard/TrendingCard.tsx +++ b/src/features/Posts/Components/TrendingCard/TrendingCard.tsx @@ -3,6 +3,7 @@ import { Link } from 'react-router-dom' import Avatar from 'src/features/Profiles/Components/Avatar/Avatar' import { useTrendingPostsQuery } from 'src/graphql' import { random } from 'src/utils/helperFunctions' +import { createRoute } from 'src/utils/routing' export default function TrendingCard() { @@ -24,7 +25,7 @@ export default function TrendingCard() { ) : trendingPosts.data?.getTrendingPosts.map(post => { - return + return
  • {post.title}

    diff --git a/src/features/Posts/pages/CreatePostPage/Components/ContentEditor/ContentEditor.tsx b/src/features/Posts/pages/CreatePostPage/Components/ContentEditor/ContentEditor.tsx index af35f4e..0aed1b7 100644 --- a/src/features/Posts/pages/CreatePostPage/Components/ContentEditor/ContentEditor.tsx +++ b/src/features/Posts/pages/CreatePostPage/Components/ContentEditor/ContentEditor.tsx @@ -96,11 +96,24 @@ export default function ContentEditor({ placeholder, initialContent, name }: Pro }); + const initContent = `## hello + + +how are you doing man + + +what's up with this face of yours + `.replace(/\n(?=\n)/g, "\n\n
    \n"); + + + console.log(initContent); + + return (
    diff --git a/src/features/Posts/pages/PostDetailsPage/Components/AuthorCard/AuthorCard.tsx b/src/features/Posts/pages/PostDetailsPage/Components/AuthorCard/AuthorCard.tsx index 91f3389..65b2c82 100644 --- a/src/features/Posts/pages/PostDetailsPage/Components/AuthorCard/AuthorCard.tsx +++ b/src/features/Posts/pages/PostDetailsPage/Components/AuthorCard/AuthorCard.tsx @@ -4,6 +4,7 @@ import Button from "src/Components/Button/Button"; import { Author } from "src/features/Posts/types"; import Avatar from "src/features/Profiles/Components/Avatar/Avatar"; import { trimText } from "src/utils/helperFunctions"; +import { createRoute } from "src/utils/routing"; interface Props { author: Pick
    - +
    diff --git a/src/features/Posts/pages/PostDetailsPage/PostDetailsPage.tsx b/src/features/Posts/pages/PostDetailsPage/PostDetailsPage.tsx index 5c12e93..2bfd33a 100644 --- a/src/features/Posts/pages/PostDetailsPage/PostDetailsPage.tsx +++ b/src/features/Posts/pages/PostDetailsPage/PostDetailsPage.tsx @@ -4,6 +4,7 @@ import { useParams } from 'react-router-dom' import LoadingPage from 'src/Components/LoadingPage/LoadingPage' import NotFoundPage from 'src/features/Shared/pages/NotFoundPage/NotFoundPage' import { usePostDetailsQuery } from 'src/graphql' +import { capitalize } from 'src/utils/helperFunctions' import { useAppSelector, } from 'src/utils/hooks' import TrendingCard from '../../Components/TrendingCard/TrendingCard' import AuthorCard from './Components/AuthorCard/AuthorCard' @@ -14,7 +15,9 @@ import styles from './styles.module.scss' export default function PostDetailsPage() { - const { type, id } = useParams() + const { type: _type, id } = useParams(); + const type = capitalize(_type); + const postDetailsQuery = usePostDetailsQuery({ variables: { id: Number(id!), diff --git a/src/utils/helperFunctions.tsx b/src/utils/helperFunctions.tsx index b774510..8729817 100644 --- a/src/utils/helperFunctions.tsx +++ b/src/utils/helperFunctions.tsx @@ -92,4 +92,14 @@ export function generateList(component: React.ReactElement, cnt: number) { return Array(cnt).fill(0).map((_, idx) => React.cloneElement(component, { key: idx })) } +export function toSlug(title: string) { + return title.toLowerCase() + .replace(/[^\w ]+/g, '') + .replace(/ +/g, '-'); +} + +export function capitalize(s?: string) { + return s && s[0].toUpperCase() + s.slice(1); +} + export const withHttp = (url: string) => !/^https?:\/\//i.test(url) ? `http://${url}` : url; \ No newline at end of file diff --git a/src/utils/routing/index.ts b/src/utils/routing/index.ts new file mode 100644 index 0000000..7256eea --- /dev/null +++ b/src/utils/routing/index.ts @@ -0,0 +1 @@ +export * from './routes' \ No newline at end of file diff --git a/src/utils/routing/routes.ts b/src/utils/routing/routes.ts new file mode 100644 index 0000000..b94a3ac --- /dev/null +++ b/src/utils/routing/routes.ts @@ -0,0 +1,61 @@ +import { toSlug } from "../helperFunctions"; + +type RouteOptions = + | { + type: 'post', + id: string | number, + postType: string, + title?: string, + username?: string, + } + | { + type: 'story', + id: string | number, + title?: string, + username?: string, + } + | { + type: 'bounty', + id: string | number, + title?: string, + username?: string, + } + | { + type: 'question', + id: string | number, + title?: string, + username?: string, + } + | { + type: 'profile', + id: string | number, + username?: string, + } + +export function createRoute(options: RouteOptions) { + + + if (options.type === 'post') + return `/blog/post/${options.postType}/${options.id}` + + (options.title ? `/${toSlug(options.title)}` : ""); + + if (options.type === 'story') + return `/blog/post/story/${options.id}` + + (options.title ? `/${toSlug(options.title)}` : ""); + + if (options.type === 'bounty') + return `/blog/post/bounty/${options.id}` + + (options.title ? `/${toSlug(options.title)}` : ""); + + + if (options.type === 'question') + return `/blog/post/question/${options.id}` + + (options.title ? `/${toSlug(options.title)}` : ""); + + + if (options.type === 'profile') + return `/profile/${options.id}` + + (options.username ? `/${toSlug(options.username)}` : ""); + + return '' +} \ No newline at end of file