fix: fix multline breaks in post body, add slugs to urls

This commit is contained in:
MTG2000
2022-06-15 21:05:52 +03:00
parent cc566df768
commit 6cfaa8e354
13 changed files with 109 additions and 13 deletions

View File

@@ -83,7 +83,7 @@ function App() {
<Route path="/products/category/:id" element={<CategoryPage />} />
<Route path="/products" element={<ExplorePage />} />
<Route path="/blog/post/:type/:id" element={<PostDetailsPage />} />
<Route path="/blog/post/:type/:id/*" element={<PostDetailsPage />} />
<Route path="/blog/preview-post/:type" element={<PreviewPostPage />} />
<Route path="/blog/create-post" element={<ProtectedRoute><CreatePostPage /></ProtectedRoute>} />
<Route path="/blog" element={<FeedPage />} />
@@ -92,7 +92,7 @@ function App() {
<Route path="/donate" element={<DonatePage />} />
<Route path="/profile/:id" element={<ProfilePage />} />
<Route path="/profile/:id/*" element={<ProfilePage />} />
<Route path="/login" element={<LoginPage />} />
<Route path="/logout" element={<LogoutPage />} />

View File

@@ -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<br/>\n");
onChange(md);
}, [], 500)

View File

@@ -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={<MenuButton ><Avatar src={curUser.avatar} width={40} /> </MenuButton>}>
<MenuItem
href={`/profile/${curUser.id}`}
href={createRoute({ type: 'profile', id: curUser.id, username: curUser.name })}
onClick={(e) => {
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'
>

View File

@@ -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={<MenuButton ><Avatar src={curUser.avatar} width={32} /> </MenuButton>}>
<MenuItem
href={`/profile/${curUser.id}`}
href={createRoute({ type: 'profile', id: curUser.id, username: curUser.name })}
onClick={(e) => {
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'
>

View File

@@ -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 (
<div className='flex gap-8'>
<Link to={`/profile/${props.author.id}`}>
<Link to={createRoute({ type: 'profile', id: props.author.id, username: props.author.name })}>
<Avatar width={avatarSize[size]} src={props.author.avatar} />
</Link>
<div className='overflow-hidden'>

View File

@@ -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,
| 'id'
@@ -36,7 +38,7 @@ export default function StoryCard({ story }: Props) {
<img src={story.cover_image} className='h-[200px] w-full object-cover' alt="" />
<div className="p-24">
<Header author={story.author} date={story.createdAt} />
<Link to={`/blog/post/Story/${story.id}`}>
<Link to={createRoute({ type: 'story', id: story.id, title: story.title })}>
<h2 className="text-h5 font-bolder mt-16">{story.title}</h2>
</Link>
<p className="text-body4 text-gray-600 mt-8">{story.excerpt}...</p>

View File

@@ -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 <Link key={post.id} to={`/blog/post/${post.__typename}/${post.id}`} className="border-b py-16 last-of-type:border-b-0">
return <Link key={post.id} to={createRoute({ type: 'post', postType: post.__typename!, id: post.id, title: post.title })} className="border-b py-16 last-of-type:border-b-0">
<li className="flex items-start gap-8">
<Avatar width={24} src={post.author.avatar} />
<p className="text-body5 font-medium">{post.title}</p>

View File

@@ -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<br/>\n");
console.log(initContent);
return (
<div className={`remirror-theme ${styles.wrapper} bg-white`}>
<Remirror
manager={manager}
initialContent={initialContent}
initialContent={initContent}
>
<TextEditorComponents.SaveModule name={name} />
<Toolbar />

View File

@@ -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<Author,
@@ -17,7 +18,7 @@ export default function AuthorCard({ author }: Props) {
return (
<div className="bg-white p-16 border-2 border-gray-200 rounded-12">
<div className='flex gap-8'>
<Link to={`/profile/${author.id}`}>
<Link to={createRoute({ type: 'profile', id: author.id, username: author.name })}>
<Avatar width={48} src={author.avatar} />
</Link>
<div className="overflow-hidden">

View File

@@ -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!),

View File

@@ -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;

View File

@@ -0,0 +1 @@
export * from './routes'

View File

@@ -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 ''
}