[WiP] init & test

This commit is contained in:
ilya-bkv 2022-12-16 08:35:53 +03:00
parent 2e74624240
commit 2f252da9db
4 changed files with 235 additions and 136 deletions

View File

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

View File

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

View 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

View File

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