Skip to content
This repository was archived by the owner on Jan 17, 2022. It is now read-only.

Add move posts modal #332

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/components/comments/ViewComment.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ export const ViewComment: FunctionComponent<Props> = ({
</span>
}
/>
<PostDropDownMenu key={`comment-dropdown-menu-${id}`} post={struct} space={space} />
<PostDropDownMenu key={`comment-dropdown-menu-${id}`} postDetails={comment} space={space} />
</div>}
content={showEditForm
? <EditComment struct={struct} content={content as CommentContent} callback={() => setShowEditForm(false)}/>
Expand Down
26 changes: 26 additions & 0 deletions src/components/posts/MovePostLink.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React, { useState } from 'react'
import { Post } from '@subsocial/types/substrate/interfaces'
import { MoveModal } from 'src/components/posts/modals/MoveModal'

type Props = {
post: Post
}

export const MovePostLink = ({ post }: Props) => {

const [ open, setOpen ] = useState<boolean>()
const title = 'Move post'

return <>
<a
className='DfBlackLink'
onClick={() => setOpen(true)}
title={title}
>
{title}
</a>
<MoveModal post={post} open={open} onClose={() => setOpen(false)} />
</>
}

export default MovePostLink
7 changes: 0 additions & 7 deletions src/components/posts/ShareModal/index.module.sass

This file was deleted.

128 changes: 128 additions & 0 deletions src/components/posts/modals/MoveModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import React, { useState } from 'react'
import { withCalls, withMulti, spacesQueryToProp } from 'src/components/substrate'
import { Modal } from 'antd'
import Button from 'antd/lib/button'
import { withMyAccount, MyAccountProps } from 'src/components/utils/MyAccount'
import { LabeledValue } from 'antd/lib/select'
import SelectSpacePreview from 'src/components/utils/SelectSpacePreview'
import BN from 'bn.js'
import { OptionId } from '@subsocial/types/substrate/classes'
import { TxFailedCallback, TxCallback } from 'src/components/substrate/SubstrateTxButton'
import dynamic from 'next/dynamic'
import { isEmptyArray, nonEmptyArr } from '@subsocial/utils';
import { DynamicPostPreview } from 'src/components/posts/view-post/DynamicPostPreview'
import { CreateSpaceButton } from 'src/components/spaces/helpers'
import { useRouter } from 'next/router'
import { postUrl } from 'src/components/urls/subsocial'
import { Post, PostId, Space, SpaceId } from '@subsocial/types/substrate/interfaces'
import modalStyles from 'src/components/posts/modals/index.module.sass';
import NoData from 'src/components/utils/EmptyList'

const TxButton = dynamic(() => import('src/components/utils/TxButton'), { ssr: false })

type Props = MyAccountProps & {
post: Post
spaceIds?: BN[]
open: boolean
onClose: () => void
}

const InnerMoveModal = (props: Props) => {
const { open, onClose, post, post: { id: postId } } = props
let { spaceIds } = props

if (post.space_id.isSome && spaceIds) {
const postSpaceId = post.space_id.unwrap()
spaceIds = spaceIds.filter(spaceId => !spaceId.eq(postSpaceId))
}

if (!spaceIds) {
return null
}

const router = useRouter()

const [ spaceId, setSpaceId ] = useState(spaceIds[0])

const onTxFailed: TxFailedCallback = () => {
// TODO show a failure message
onClose()
}

const onTxSuccess: TxCallback = () => {
// TODO show a success message
router.push(
'/[spaceId]/posts/[postId]',
postUrl(
{ id: spaceId as SpaceId } as Space,
{ id: postId as PostId })
)
onClose()
}

const newTxParams = () => {
const spaceIdOption = new OptionId(spaceId)
return [ postId, spaceIdOption ]
}

const renderTxButton = () => nonEmptyArr(spaceIds)
? <TxButton
type='primary'
label={`Move`}
params={newTxParams}
tx={'posts.movePost'}
onFailed={onTxFailed}
onSuccess={onTxSuccess}
successMessage='Moved post to another space'
failedMessage='Failed to move post'
/>
: <CreateSpaceButton>Create one more space</CreateSpaceButton>

const renderMovePostView = () => {
if (isEmptyArray(spaceIds)) {
return <NoData description='You need to have at least one more space to move post' />
}

return <div className={modalStyles.DfPostActionModalBody}>
<span className={modalStyles.DfPostActionModalSelector}>
<SelectSpacePreview
spaceIds={spaceIds || []}
onSelect={saveSpace}
imageSize={24}
defaultValue={spaceId?.toString()}
/>
</span>

<div style={{margin: '0.75rem 0'}}>
<DynamicPostPreview id={postId} asRegularPost />
</div>
</div>
}

const saveSpace = (value: string | number | LabeledValue) => {
setSpaceId(new BN(value as string))
}

return <Modal
onCancel={onClose}
visible={open}
title={'Move post to another space'}
className={modalStyles.DfPostActionModal}
footer={
<>
<Button onClick={onClose}>Cancel</Button>
{renderTxButton()}
</>
}
>
{renderMovePostView()}
</Modal>
}

export const MoveModal = withMulti(
InnerMoveModal,
withMyAccount,
withCalls<Props>(
spacesQueryToProp(`spaceIdsByOwner`, { paramName: 'address', propName: 'spaceIds' })
)
)
3 changes: 3 additions & 0 deletions src/components/posts/modals/ShareModal/index.module.sass
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.DfShareModalMdEditor
.CodeMirror
height: 5rem
Original file line number Diff line number Diff line change
@@ -1,25 +1,27 @@
import React, { useState } from 'react';
import { withCalls, withMulti, getTxParams, spacesQueryToProp } from '../../substrate';
import { withCalls, withMulti, getTxParams, spacesQueryToProp } from 'src/components/substrate';
import { Modal } from 'antd';
import Button from 'antd/lib/button';
import { withMyAccount, MyAccountProps } from '../../utils/MyAccount';
import { withMyAccount, MyAccountProps } from 'src/components/utils/MyAccount';
import { LabeledValue } from 'antd/lib/select';
import SelectSpacePreview from '../../utils/SelectSpacePreview';
import SelectSpacePreview from 'src/components/utils/SelectSpacePreview';
import BN from 'bn.js';
import { PostExtension, SharedPost, IpfsContent } from '@subsocial/types/substrate/classes';
import { useForm, Controller, ErrorMessage } from 'react-hook-form';
import { useSubsocialApi } from '../../utils/SubsocialApiContext';
import { useSubsocialApi } from 'src/components/utils/SubsocialApiContext';
import { IpfsCid } from '@subsocial/types/substrate/interfaces';
import { TxFailedCallback, TxCallback } from 'src/components/substrate/SubstrateTxButton';
import dynamic from 'next/dynamic';
import { buildSharePostValidationSchema } from '../PostValidation';
import { isEmptyArray } from '@subsocial/utils';
import DfMdEditor from '../../utils/DfMdEditor';
import { DynamicPostPreview } from '../view-post/DynamicPostPreview';
import { CreateSpaceButton } from '../../spaces/helpers';
import { buildSharePostValidationSchema } from 'src/components/posts/PostValidation';
import { isEmptyArray, nonEmptyArr } from '@subsocial/utils';
import DfMdEditor from 'src/components/utils/DfMdEditor';
import { DynamicPostPreview } from 'src/components/posts/view-post/DynamicPostPreview';
import { CreateSpaceButton } from 'src/components/spaces/helpers';
import styles from './index.module.sass'
import modalStyles from 'src/components/posts/modals/index.module.sass'
import NoData from 'src/components/utils/EmptyList';

const TxButton = dynamic(() => import('../../utils/TxButton'), { ssr: false });
const TxButton = dynamic(() => import('src/components/utils/TxButton'), { ssr: false });

type Props = MyAccountProps & {
postId: BN
Expand Down Expand Up @@ -69,8 +71,8 @@ const InnerShareModal = (props: Props) => {
return [ spaceId, extension, new IpfsContent(hash) ];
};

const renderTxButton = () =>
<TxButton
const renderTxButton = () => nonEmptyArr(spaceIds)
? <TxButton
type='primary'
label={`Create a post`}
disabled={isSubmitting}
Expand All @@ -86,38 +88,31 @@ const InnerShareModal = (props: Props) => {
successMessage='Shared to your space'
failedMessage='Failed to share'
/>
: <CreateSpaceButton>Create my first space</CreateSpaceButton>

const renderShareView = () => {
if (isEmptyArray(spaceIds)) {
return (
<CreateSpaceButton>
<a className='ui button primary'>
Create my first space
</a>
</CreateSpaceButton>
)
return <NoData description='You need to have at least one space to share post'/>
}

return <div className='DfShareModalBody'>
<span className='mr-3'>
Share the post to your space:
{' '}
return <div className={modalStyles.DfPostActionModalBody}>
<span className={modalStyles.DfPostActionModalSelector}>
<SelectSpacePreview
spaceIds={spaceIds}
spaceIds={spaceIds || []}
onSelect={saveSpace}
imageSize={24}
defaultValue={spaceId?.toString()}
/>
</span>

<form className='my-2'>
<form style={{margin: '0.75rem 0'}}>
<Controller
control={control}
as={<DfMdEditor />}
options={{ autofocus: true }}
name={Fields.body}
value={body}
className={errors[Fields.body] && 'error'}
className={`${errors[Fields.body] && 'error'} ${styles.DfShareModalMdEditor}`}
/>
<div className='DfError'>
<ErrorMessage errors={errors} name={Fields.body} />
Expand All @@ -135,7 +130,7 @@ const InnerShareModal = (props: Props) => {
onCancel={onClose}
visible={open}
title={'Share post'}
className={styles.DfShareModal}
className={modalStyles.DfPostActionModal}
footer={
<>
<Button onClick={onClose}>Cancel</Button>
Expand Down
11 changes: 11 additions & 0 deletions src/components/posts/modals/index.module.sass
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
@import 'src/styles/subsocial-vars.scss'

.DfPostActionModal
width: $max_width_content !important

.DfPostActionModalBody
\:global .DfSegment
margin: 0

.DfPostActionModalSelector
width: $max_width_content !important
10 changes: 6 additions & 4 deletions src/components/posts/share/SpaceShareLink.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ import React, { useState } from 'react'
import { PostWithSomeDetails } from '@subsocial/types/dto';
import { PostExtension } from '@subsocial/types/substrate/classes';
import { EditOutlined } from '@ant-design/icons';
import { ShareModal } from '../ShareModal'
import { isRegularPost } from '../view-post';
import { IconWithLabel } from '../../utils';
import { ShareModal } from 'src/components/posts/modals/ShareModal'
import { isRegularPost } from 'src/components/posts/view-post';
import { IconWithLabel } from 'src/components/utils';
import { useAuth } from 'src/components/auth/AuthContext';

type Props = {
postDetails: PostWithSomeDetails
Expand All @@ -19,14 +20,15 @@ export const SpaceShareLink = ({
}
}: Props) => {

const { openSignInModal, state: { isSteps: { isSignIn } } } = useAuth()
const [ open, setOpen ] = useState<boolean>()
const postId = isRegularPost(extension as PostExtension) ? id : ext && ext.post.struct.id
const title = 'Write a post'

return <>
<a
className='DfBlackLink'
onClick={() => setOpen(true)}
onClick={() => isSignIn ? setOpen(true) : openSignInModal('AuthRequired')}
title={title}
>
<IconWithLabel icon={<EditOutlined />} label={title} />
Expand Down
2 changes: 1 addition & 1 deletion src/components/posts/view-post/PostPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export const PostPage: NextPage<PostDetailsProps> = ({ postDetails: initialPost,
<HeadMeta title={title} desc={mdToText(body)} image={image} canonical={canonical} tags={tags} />
<div className='DfRow'>
<h1 className='DfPostName'>{titleMsg}</h1>
<PostDropDownMenu post={struct} space={spaceStruct} withEditButton />
<PostDropDownMenu postDetails={postDetails} space={spaceStruct} withEditButton />
</div>
<div className='DfRow'>
<PostCreator postDetails={postDetails} withSpaceName space={spaceData} />
Expand Down
3 changes: 1 addition & 2 deletions src/components/posts/view-post/ViewSharedPreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@ import { InnerPreviewProps } from '.';
export const SharedPreview: React.FunctionComponent<InnerPreviewProps> = ({ postDetails, space, withActions, replies }) => {
const [ commentsSection, setCommentsSection ] = useState(false)

const { struct } = postDetails.post
return <>
<div className='DfRow'>
<PostCreator postDetails={postDetails} space={space} withSpaceName />
<PostDropDownMenu space={space.struct} post={struct}/>
<PostDropDownMenu space={space.struct} postDetails={postDetails}/>
</div>
<SharePostContent postDetails={postDetails} space={space} />
{withActions && <PostActionsPanel postDetails={postDetails} space={space.struct} toogleCommentSection={() => setCommentsSection(!commentsSection)} preview />}
Expand Down
11 changes: 8 additions & 3 deletions src/components/posts/view-post/helpers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,11 @@ import { postUrl, editPostUrl, HasSpaceIdOrHandle, HasPostId } from 'src/compone
import { ShareDropdown } from '../share/ShareDropdown';
import { ButtonLink } from 'src/components/utils/ButtonLink';
import { DfMd } from 'src/components/utils/DfMd';
import MovePostLink from 'src/components/posts/MovePostLink';

type DropdownProps = {
space: Space
post: Post
postDetails: PostWithSomeDetails
withEditButton?: boolean
}

Expand All @@ -57,7 +58,8 @@ const ReactionModal = ({ postId }: ReactionModalProps) => {
}

export const PostDropDownMenu: React.FunctionComponent<DropdownProps> = (props) => {
const { space, post, withEditButton = false } = props
const { space, postDetails, withEditButton = false } = props
const { post: { struct: post } } = postDetails
const isMyPost = isMyAddress(post.owner);
const postId = post.id
const postKey = `post-${postId.toString()}`
Expand All @@ -77,6 +79,9 @@ export const PostDropDownMenu: React.FunctionComponent<DropdownProps> = (props)
{isMyPost && <Menu.Item key={`hidden-${postKey}`}>
<HiddenPostButton post={post} asLink />
</Menu.Item>}
{isMyPost && !isComment(post.extension) && <Menu.Item key={`move-${postKey}`}>
<MovePostLink post={post} />
</Menu.Item>}
<Menu.Item key={`view-reaction-${postKey}`} >
<ReactionModal postId={postId} />
</Menu.Item>
Expand Down Expand Up @@ -311,7 +316,7 @@ export const InfoPostPreview: React.FunctionComponent<InfoForPostPreviewProps> =
<div className='w-100'>
<div className='DfRow'>
<PostCreator postDetails={postDetails} space={space} withSpaceName />
<PostDropDownMenu post={struct} space={space.struct} withEditButton />
<PostDropDownMenu postDetails={postDetails} space={space.struct} withEditButton />
</div>
<PostContent postDetails={postDetails} space={space.struct} />
<ViewTags tags={content?.tags} />
Expand Down
Loading