[WiP] init & test
This commit is contained in:
parent
2e74624240
commit
2f252da9db
|
@ -3,6 +3,7 @@
|
||||||
margin: 0 -2.4rem 1.5em;
|
margin: 0 -2.4rem 1.5em;
|
||||||
padding: 0.8rem 2.4rem;
|
padding: 0.8rem 2.4rem;
|
||||||
transition: background-color 0.3s;
|
transition: background-color 0.3s;
|
||||||
|
border: 1px solid red;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: #f6f6f6;
|
background-color: #f6f6f6;
|
||||||
|
@ -32,25 +33,25 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.commentLevel1 {
|
//.commentLevel1 {
|
||||||
margin-left: 3.2rem;
|
// margin-left: 3.2rem;
|
||||||
}
|
//}
|
||||||
|
//
|
||||||
.commentLevel2 {
|
//.commentLevel2 {
|
||||||
margin-left: 6.4rem;
|
// margin-left: 6.4rem;
|
||||||
}
|
//}
|
||||||
|
//
|
||||||
.commentLevel3 {
|
//.commentLevel3 {
|
||||||
margin-left: 9.6rem;
|
// margin-left: 9.6rem;
|
||||||
}
|
//}
|
||||||
|
//
|
||||||
.commentLevel4 {
|
//.commentLevel4 {
|
||||||
margin-left: 12.8rem;
|
// margin-left: 12.8rem;
|
||||||
}
|
//}
|
||||||
|
//
|
||||||
.commentLevel5 {
|
//.commentLevel5 {
|
||||||
margin-left: 16rem;
|
// margin-left: 16rem;
|
||||||
}
|
//}
|
||||||
|
|
||||||
.commentControls {
|
.commentControls {
|
||||||
@include font-size(1.2rem);
|
@include font-size(1.2rem);
|
||||||
|
|
|
@ -12,6 +12,7 @@ import { formatDate } from '../../utils'
|
||||||
import { SharePopup } from './SharePopup'
|
import { SharePopup } from './SharePopup'
|
||||||
import stylesHeader from '../Nav/Header.module.scss'
|
import stylesHeader from '../Nav/Header.module.scss'
|
||||||
import Userpic from '../Author/Userpic'
|
import Userpic from '../Author/Userpic'
|
||||||
|
import CommentWrapper from './CommentWrapper'
|
||||||
|
|
||||||
export default (props: {
|
export default (props: {
|
||||||
level?: number
|
level?: number
|
||||||
|
@ -34,114 +35,116 @@ export default (props: {
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class={clsx(styles.comment, { [styles[`commentLevel${props.level}`]]: Boolean(props.level) })}>
|
<CommentWrapper level={props.level}>
|
||||||
<Show when={!!body()}>
|
<li class={clsx(styles.comment, { [styles[`commentLevel${props.level}`]]: Boolean(props.level) })}>
|
||||||
<div class={styles.commentContent}>
|
<Show when={!!body()}>
|
||||||
<Show
|
<div class={styles.commentContent}>
|
||||||
when={!props.compact}
|
<Show
|
||||||
fallback={
|
when={!props.compact}
|
||||||
<div>
|
fallback={
|
||||||
<Userpic user={comment().createdBy as Author} isBig={false} isAuthorsList={false} />
|
<div>
|
||||||
<small class={styles.commentArticle}>
|
<Userpic user={comment().createdBy as Author} isBig={false} isAuthorsList={false} />
|
||||||
<a href={`#comment-${comment()?.id}`}>{comment()?.shout.title || ''}</a>
|
<small class={styles.commentArticle}>
|
||||||
</small>
|
<a href={`#comment-${comment()?.id}`}>{comment()?.shout.title || ''}</a>
|
||||||
</div>
|
</small>
|
||||||
}
|
|
||||||
>
|
|
||||||
<div class={styles.commentDetails}>
|
|
||||||
<div class={styles.commentAuthor}>
|
|
||||||
<AuthorCard
|
|
||||||
author={comment()?.createdBy as Author}
|
|
||||||
hideDescription={true}
|
|
||||||
hideFollow={true}
|
|
||||||
isComments={true}
|
|
||||||
hasLink={true}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class={styles.commentDate}>{formattedDate()}</div>
|
|
||||||
<div
|
|
||||||
class={styles.commentRating}
|
|
||||||
classList={{
|
|
||||||
[styles.commentRatingPositive]: comment().stat?.rating > 0,
|
|
||||||
[styles.commentRatingNegative]: comment().stat?.rating < 0
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<button class={clsx(styles.commentRatingControl, styles.commentRatingControlUp)} />
|
|
||||||
<div class={styles.commentRatingValue}>{comment().stat?.rating || 0}</div>
|
|
||||||
<button class={clsx(styles.commentRatingControl, styles.commentRatingControlDown)} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Show>
|
|
||||||
|
|
||||||
<div
|
|
||||||
class={styles.commentBody}
|
|
||||||
contenteditable={props.canEdit}
|
|
||||||
id={'comment-' + (comment().id || '')}
|
|
||||||
>
|
|
||||||
<MD body={body()} />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Show when={!props.compact}>
|
|
||||||
<div class={styles.commentControls}>
|
|
||||||
<button
|
|
||||||
class={clsx(styles.commentControl, styles.commentControlReply)}
|
|
||||||
onClick={() => setIsReplyVisible(!isReplyVisible())}
|
|
||||||
>
|
|
||||||
<Icon name="reply" class={styles.icon} />
|
|
||||||
{t('Reply')}
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<Show when={props.canEdit}>
|
|
||||||
{/*FIXME implement edit comment modal*/}
|
|
||||||
{/*<button*/}
|
|
||||||
{/* class={clsx(styles.commentControl, styles.commentControlEdit)}*/}
|
|
||||||
{/* onClick={() => showModal('editComment')}*/}
|
|
||||||
{/*>*/}
|
|
||||||
{/* <Icon name="edit" class={styles.icon} />*/}
|
|
||||||
{/* {t('Edit')}*/}
|
|
||||||
{/*</button>*/}
|
|
||||||
<button
|
|
||||||
class={clsx(styles.commentControl, styles.commentControlDelete)}
|
|
||||||
onClick={() => remove()}
|
|
||||||
>
|
|
||||||
<Icon name="delete" class={styles.icon} />
|
|
||||||
{t('Delete')}
|
|
||||||
</button>
|
|
||||||
</Show>
|
|
||||||
|
|
||||||
<SharePopup
|
|
||||||
containerCssClass={stylesHeader.control}
|
|
||||||
trigger={
|
|
||||||
<button class={clsx(styles.commentControl, styles.commentControlShare)}>
|
|
||||||
<Icon name="share" class={styles.icon} />
|
|
||||||
{t('Share')}
|
|
||||||
</button>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/*<button*/}
|
|
||||||
{/* class={clsx(styles.commentControl, styles.commentControlComplain)}*/}
|
|
||||||
{/* onClick={() => showModal('reportComment')}*/}
|
|
||||||
{/*>*/}
|
|
||||||
{/* {t('Report')}*/}
|
|
||||||
{/*</button>*/}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Show when={isReplyVisible()}>
|
|
||||||
<form class={styles.replyForm}>
|
|
||||||
<textarea name="reply" id="reply" rows="5" />
|
|
||||||
<div class={styles.replyFormControls}>
|
|
||||||
<button class="button button--light" onClick={() => setIsReplyVisible(false)}>
|
|
||||||
{t('Cancel')}
|
|
||||||
</button>
|
|
||||||
<button class="button">{t('Send')}</button>
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
}
|
||||||
|
>
|
||||||
|
<div class={styles.commentDetails}>
|
||||||
|
<div class={styles.commentAuthor}>
|
||||||
|
<AuthorCard
|
||||||
|
author={comment()?.createdBy as Author}
|
||||||
|
hideDescription={true}
|
||||||
|
hideFollow={true}
|
||||||
|
isComments={true}
|
||||||
|
hasLink={true}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class={styles.commentDate}>{formattedDate()}</div>
|
||||||
|
<div
|
||||||
|
class={styles.commentRating}
|
||||||
|
classList={{
|
||||||
|
[styles.commentRatingPositive]: comment().stat?.rating > 0,
|
||||||
|
[styles.commentRatingNegative]: comment().stat?.rating < 0
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<button class={clsx(styles.commentRatingControl, styles.commentRatingControlUp)} />
|
||||||
|
<div class={styles.commentRatingValue}>{comment().stat?.rating || 0}</div>
|
||||||
|
<button class={clsx(styles.commentRatingControl, styles.commentRatingControlDown)} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</Show>
|
</Show>
|
||||||
</Show>
|
|
||||||
</div>
|
<div
|
||||||
</Show>
|
class={styles.commentBody}
|
||||||
</div>
|
contenteditable={props.canEdit}
|
||||||
|
id={'comment-' + (comment().id || '')}
|
||||||
|
>
|
||||||
|
<MD body={body()} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Show when={!props.compact}>
|
||||||
|
<div class={styles.commentControls}>
|
||||||
|
<button
|
||||||
|
class={clsx(styles.commentControl, styles.commentControlReply)}
|
||||||
|
onClick={() => setIsReplyVisible(!isReplyVisible())}
|
||||||
|
>
|
||||||
|
<Icon name="reply" class={styles.icon} />
|
||||||
|
{t('Reply')}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<Show when={props.canEdit}>
|
||||||
|
{/*FIXME implement edit comment modal*/}
|
||||||
|
{/*<button*/}
|
||||||
|
{/* class={clsx(styles.commentControl, styles.commentControlEdit)}*/}
|
||||||
|
{/* onClick={() => showModal('editComment')}*/}
|
||||||
|
{/*>*/}
|
||||||
|
{/* <Icon name="edit" class={styles.icon} />*/}
|
||||||
|
{/* {t('Edit')}*/}
|
||||||
|
{/*</button>*/}
|
||||||
|
<button
|
||||||
|
class={clsx(styles.commentControl, styles.commentControlDelete)}
|
||||||
|
onClick={() => remove()}
|
||||||
|
>
|
||||||
|
<Icon name="delete" class={styles.icon} />
|
||||||
|
{t('Delete')}
|
||||||
|
</button>
|
||||||
|
</Show>
|
||||||
|
|
||||||
|
<SharePopup
|
||||||
|
containerCssClass={stylesHeader.control}
|
||||||
|
trigger={
|
||||||
|
<button class={clsx(styles.commentControl, styles.commentControlShare)}>
|
||||||
|
<Icon name="share" class={styles.icon} />
|
||||||
|
{t('Share')}
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/*<button*/}
|
||||||
|
{/* class={clsx(styles.commentControl, styles.commentControlComplain)}*/}
|
||||||
|
{/* onClick={() => showModal('reportComment')}*/}
|
||||||
|
{/*>*/}
|
||||||
|
{/* {t('Report')}*/}
|
||||||
|
{/*</button>*/}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Show when={isReplyVisible()}>
|
||||||
|
<form class={styles.replyForm}>
|
||||||
|
<textarea name="reply" id="reply" rows="5" />
|
||||||
|
<div class={styles.replyFormControls}>
|
||||||
|
<button class="button button--light" onClick={() => setIsReplyVisible(false)}>
|
||||||
|
{t('Cancel')}
|
||||||
|
</button>
|
||||||
|
<button class="button">{t('Send')}</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</Show>
|
||||||
|
</Show>
|
||||||
|
</div>
|
||||||
|
</Show>
|
||||||
|
</li>
|
||||||
|
</CommentWrapper>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
71
src/components/Article/CommentWrapper.tsx
Normal file
71
src/components/Article/CommentWrapper.tsx
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
import type { JSX } from 'solid-js/jsx-runtime'
|
||||||
|
import { Switch, Match } from 'solid-js'
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
level?: number
|
||||||
|
children: JSX.Element
|
||||||
|
}
|
||||||
|
|
||||||
|
const CommentWrapper = (props: Props) => {
|
||||||
|
return (
|
||||||
|
<Switch fallback={props.children}>
|
||||||
|
<Match when={props.level === 1}>
|
||||||
|
<ul>{props.children}</ul>
|
||||||
|
</Match>
|
||||||
|
<Match when={props.level === 2}>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<ul>{props.children}</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</Match>
|
||||||
|
<Match when={props.level === 3}>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<ul>{props.children}</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</Match>
|
||||||
|
<Match when={props.level === 4}>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<ul>{props.children}</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</Match>
|
||||||
|
<Match when={props.level === 5}>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<ul>{props.children}</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</Match>
|
||||||
|
</Switch>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CommentWrapper
|
|
@ -1,4 +1,4 @@
|
||||||
import { For, Show, createMemo, createSignal, onMount } from 'solid-js'
|
import { For, Show, createMemo, createSignal, onMount, createEffect } from 'solid-js'
|
||||||
import { useSession } from '../../context/session'
|
import { useSession } from '../../context/session'
|
||||||
import Comment from './Comment'
|
import Comment from './Comment'
|
||||||
import { t } from '../../utils/intl'
|
import { t } from '../../utils/intl'
|
||||||
|
@ -49,6 +49,25 @@ export const CommentsTree = (props: { shoutSlug: string }) => {
|
||||||
return level
|
return level
|
||||||
}
|
}
|
||||||
onMount(async () => await loadMore())
|
onMount(async () => await loadMore())
|
||||||
|
|
||||||
|
function nestComments(commentList) {
|
||||||
|
const commentMap = {}
|
||||||
|
commentList.forEach((comment) => (commentMap[comment.id] = comment))
|
||||||
|
commentList.forEach((comment) => {
|
||||||
|
if (comment.replyTo !== null) {
|
||||||
|
const parent = commentMap[comment.replyTo]
|
||||||
|
;(parent.children = parent.children || []).push(comment)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return commentList.filter((comment) => {
|
||||||
|
return comment.replyTo === null
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
createEffect(() => {
|
||||||
|
console.log('!!! reactions():', nestComments(reactions()))
|
||||||
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Show when={!isCommentsLoading()} fallback={<Loading />}>
|
<Show when={!isCommentsLoading()} fallback={<Loading />}>
|
||||||
|
@ -83,15 +102,20 @@ export const CommentsTree = (props: { shoutSlug: string }) => {
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<For each={reactions().reverse()}>
|
<ul>
|
||||||
{(reaction: Reaction) => (
|
<For each={reactions().reverse()}>
|
||||||
<Comment
|
{(reaction: Reaction) => (
|
||||||
comment={reaction}
|
<>
|
||||||
level={getCommentLevel(reaction)}
|
{JSON.stringify(getCommentLevel(reaction))}
|
||||||
canEdit={reaction.createdBy?.slug === session()?.user?.slug}
|
<Comment
|
||||||
/>
|
comment={reaction}
|
||||||
)}
|
level={getCommentLevel(reaction)}
|
||||||
</For>
|
canEdit={reaction.createdBy?.slug === session()?.user?.slug}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</For>
|
||||||
|
</ul>
|
||||||
|
|
||||||
<Show when={isLoadMoreButtonVisible()}>
|
<Show when={isLoadMoreButtonVisible()}>
|
||||||
<button onClick={loadMore}>{t('Load more')}</button>
|
<button onClick={loadMore}>{t('Load more')}</button>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user