Comment tree rerender Rerender fix
This commit is contained in:
parent
0cd5dd1498
commit
971e4e97a6
|
@ -5,20 +5,19 @@ import { Show, createMemo, createSignal, For } from 'solid-js'
|
||||||
import { clsx } from 'clsx'
|
import { clsx } from 'clsx'
|
||||||
import type { Author, Reaction } from '../../graphql/types.gen'
|
import type { Author, Reaction } from '../../graphql/types.gen'
|
||||||
import { t } from '../../utils/intl'
|
import { t } from '../../utils/intl'
|
||||||
import { deleteReaction } from '../../stores/zine/reactions'
|
import { createReaction, deleteReaction } from '../../stores/zine/reactions'
|
||||||
import MD from './MD'
|
import MD from './MD'
|
||||||
import { formatDate } from '../../utils'
|
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 { apiClient } from '../../utils/apiClient'
|
|
||||||
import { useSession } from '../../context/session'
|
import { useSession } from '../../context/session'
|
||||||
|
import { ReactionKind } from '../../graphql/types.gen'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
level: number
|
|
||||||
comment: Reaction
|
comment: Reaction
|
||||||
compact?: boolean
|
compact?: boolean
|
||||||
reactions: Reaction[]
|
reactions?: Reaction[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Comment = (props: Props) => {
|
export const Comment = (props: Props) => {
|
||||||
|
@ -41,20 +40,24 @@ export const Comment = (props: Props) => {
|
||||||
const compose = (event) => setPostMessageText(event.target.value)
|
const compose = (event) => setPostMessageText(event.target.value)
|
||||||
const handleCreate = async (event) => {
|
const handleCreate = async (event) => {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
// await createReaction({
|
try {
|
||||||
await apiClient.createReaction({
|
await createReaction({
|
||||||
kind: 7,
|
kind: ReactionKind.Comment,
|
||||||
replyTo: props.comment.id,
|
replyTo: props.comment.id,
|
||||||
body: postMessageText(),
|
body: postMessageText(),
|
||||||
shout: comment().shout.id
|
shout: comment().shout.id
|
||||||
})
|
})
|
||||||
|
setIsReplyVisible(false)
|
||||||
|
} catch (error) {
|
||||||
|
console.log('!!! err:', error)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const formattedDate = createMemo(() =>
|
const formattedDate = createMemo(() =>
|
||||||
formatDate(new Date(comment()?.createdAt), { hour: 'numeric', minute: 'numeric' })
|
formatDate(new Date(comment()?.createdAt), { hour: 'numeric', minute: 'numeric' })
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<li class={clsx(styles.comment, { [styles[`commentLevel${props.level}`]]: Boolean(props.level) })}>
|
<li class={styles.comment}>
|
||||||
<Show when={!!body()}>
|
<Show when={!!body()}>
|
||||||
<div class={styles.commentContent}>
|
<div class={styles.commentContent}>
|
||||||
<Show
|
<Show
|
||||||
|
@ -93,7 +96,7 @@ export const Comment = (props: Props) => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Show>
|
</Show>
|
||||||
|
<div style={{ color: 'red' }}>{comment().id}</div>
|
||||||
<div
|
<div
|
||||||
class={styles.commentBody}
|
class={styles.commentBody}
|
||||||
contenteditable={canEdit()}
|
contenteditable={canEdit()}
|
||||||
|
@ -170,11 +173,13 @@ export const Comment = (props: Props) => {
|
||||||
</Show>
|
</Show>
|
||||||
</div>
|
</div>
|
||||||
</Show>
|
</Show>
|
||||||
|
<Show when={props.reactions}>
|
||||||
<ul>
|
<ul>
|
||||||
<For each={props.reactions.filter((r) => r.replyTo === props.comment.id)}>
|
<For each={props.reactions.filter((r) => r.replyTo === props.comment.id)}>
|
||||||
{(reaction) => <Comment reactions={props.reactions} comment={reaction} level={props.level + 1} />}
|
{(reaction) => <Comment reactions={props.reactions} comment={reaction} />}
|
||||||
</For>
|
</For>
|
||||||
</ul>
|
</ul>
|
||||||
|
</Show>
|
||||||
</li>
|
</li>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,11 +21,12 @@ export const CommentsTree = (props: { shoutSlug: string }) => {
|
||||||
const { session } = useSession()
|
const { session } = useSession()
|
||||||
const { sortedReactions, loadReactionsBy } = useReactionsStore()
|
const { sortedReactions, loadReactionsBy } = useReactionsStore()
|
||||||
const reactions = createMemo<Reaction[]>(() =>
|
const reactions = createMemo<Reaction[]>(() =>
|
||||||
sortedReactions()
|
sortedReactions().sort(commentsOrder() === 'rating' ? byStat('rating') : byCreated)
|
||||||
.sort(commentsOrder() === 'rating' ? byStat('rating') : byCreated)
|
|
||||||
.filter((r) => r.shout.slug === props.shoutSlug)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
createEffect(() => {
|
||||||
|
console.log('!!! sortedReactions():', sortedReactions())
|
||||||
|
})
|
||||||
const loadMore = async () => {
|
const loadMore = async () => {
|
||||||
try {
|
try {
|
||||||
const page = getCommentsPage()
|
const page = getCommentsPage()
|
||||||
|
@ -49,24 +50,6 @@ export const CommentsTree = (props: { shoutSlug: string }) => {
|
||||||
}
|
}
|
||||||
onMount(async () => await loadMore())
|
onMount(async () => await loadMore())
|
||||||
|
|
||||||
const nestComments = (commentList) => {
|
|
||||||
const commentMap = {}
|
|
||||||
commentList.forEach((comment) => {
|
|
||||||
commentMap[comment.id] = comment
|
|
||||||
if (comment.replyTo !== null) {
|
|
||||||
const parent = commentMap[comment.replyTo] ?? []
|
|
||||||
;(parent.children = parent.children || []).push(comment)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return commentList.filter((comment) => {
|
|
||||||
return !comment.replyTo
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
createEffect(() => {
|
|
||||||
console.log('!!! re:', nestComments(reactions()))
|
|
||||||
})
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Show when={!isCommentsLoading()} fallback={<Loading />}>
|
<Show when={!isCommentsLoading()} fallback={<Loading />}>
|
||||||
|
@ -103,7 +86,7 @@ export const CommentsTree = (props: { shoutSlug: string }) => {
|
||||||
|
|
||||||
<ul class={styles.comments}>
|
<ul class={styles.comments}>
|
||||||
<For each={reactions().filter((r) => !r.replyTo)}>
|
<For each={reactions().filter((r) => !r.replyTo)}>
|
||||||
{(reaction) => <Comment level={0} reactions={reactions()} comment={reaction} />}
|
{(reaction) => <Comment reactions={reactions()} comment={reaction} />}
|
||||||
</For>
|
</For>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
|
|
@ -36,11 +36,13 @@ export const AuthorCard = (props: AuthorCardProps) => {
|
||||||
actions: { loadSession }
|
actions: { loadSession }
|
||||||
} = useSession()
|
} = useSession()
|
||||||
|
|
||||||
|
if (!props.author) return false // FIXME: с сервера должен приходить автор реакции (ApiClient.CreateReaction)
|
||||||
|
|
||||||
const [isSubscribing, setIsSubscribing] = createSignal(false)
|
const [isSubscribing, setIsSubscribing] = createSignal(false)
|
||||||
|
|
||||||
const subscribed = createMemo<boolean>(
|
const subscribed = createMemo<boolean>(() => {
|
||||||
() => session()?.news?.authors?.some((u) => u === props.author.slug) || false
|
return session()?.news?.authors?.some((u) => u === props.author.slug) || false
|
||||||
)
|
})
|
||||||
|
|
||||||
const subscribe = async (really = true) => {
|
const subscribe = async (really = true) => {
|
||||||
setIsSubscribing(true)
|
setIsSubscribing(true)
|
||||||
|
|
|
@ -8,12 +8,9 @@ import { follow, unfollow } from '../../stores/zine/common'
|
||||||
import { getLogger } from '../../utils/logger'
|
import { getLogger } from '../../utils/logger'
|
||||||
import { clsx } from 'clsx'
|
import { clsx } from 'clsx'
|
||||||
import { useSession } from '../../context/session'
|
import { useSession } from '../../context/session'
|
||||||
import { StatMetrics } from '../_shared/StatMetrics'
|
|
||||||
import { ShowOnlyOnClient } from '../_shared/ShowOnlyOnClient'
|
import { ShowOnlyOnClient } from '../_shared/ShowOnlyOnClient'
|
||||||
import { Icon } from '../_shared/Icon'
|
import { Icon } from '../_shared/Icon'
|
||||||
|
|
||||||
const log = getLogger('TopicCard')
|
|
||||||
|
|
||||||
interface TopicProps {
|
interface TopicProps {
|
||||||
topic: Topic
|
topic: Topic
|
||||||
compact?: boolean
|
compact?: boolean
|
||||||
|
|
|
@ -6,19 +6,10 @@ export default gql`
|
||||||
error
|
error
|
||||||
reaction {
|
reaction {
|
||||||
id
|
id
|
||||||
createdBy {
|
|
||||||
slug
|
|
||||||
name
|
|
||||||
userpic
|
|
||||||
}
|
|
||||||
body
|
body
|
||||||
kind
|
kind
|
||||||
range
|
range
|
||||||
createdAt
|
createdAt
|
||||||
shout {
|
|
||||||
id
|
|
||||||
slug
|
|
||||||
}
|
|
||||||
replyTo
|
replyTo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -498,7 +498,7 @@ export type ReactionBy = {
|
||||||
|
|
||||||
export type ReactionInput = {
|
export type ReactionInput = {
|
||||||
body?: InputMaybe<Scalars['String']>
|
body?: InputMaybe<Scalars['String']>
|
||||||
kind: Scalars['Int']
|
kind: ReactionKind
|
||||||
range?: InputMaybe<Scalars['String']>
|
range?: InputMaybe<Scalars['String']>
|
||||||
replyTo?: InputMaybe<Scalars['Int']>
|
replyTo?: InputMaybe<Scalars['Int']>
|
||||||
shout: Scalars['Int']
|
shout: Scalars['Int']
|
||||||
|
|
|
@ -23,9 +23,16 @@ export const loadReactionsBy = async ({
|
||||||
setSortedReactions(data)
|
setSortedReactions(data)
|
||||||
return { hasMore }
|
return { hasMore }
|
||||||
}
|
}
|
||||||
export const createReaction = async (reaction: ReactionInput) => {
|
|
||||||
const { reaction: r } = await apiClient.createReaction(reaction)
|
export const createReaction = async (input: ReactionInput) => {
|
||||||
return r
|
try {
|
||||||
|
const reaction = await apiClient.createReaction(input)
|
||||||
|
console.log('!!! reaction:', reaction)
|
||||||
|
reaction.shout = { slug: input.shout }
|
||||||
|
setSortedReactions((prev) => [...prev, reaction])
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[createReaction]', error)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
export const updateReaction = async (reaction: Reaction) => {
|
export const updateReaction = async (reaction: Reaction) => {
|
||||||
const { reaction: r } = await apiClient.updateReaction({ reaction })
|
const { reaction: r } = await apiClient.updateReaction({ reaction })
|
||||||
|
|
|
@ -230,11 +230,10 @@ export const apiClient = {
|
||||||
console.debug('createArticle response:', response)
|
console.debug('createArticle response:', response)
|
||||||
return response.data.createShout
|
return response.data.createShout
|
||||||
},
|
},
|
||||||
createReaction: async (reaction) => {
|
createReaction: async (input: ReactionInput) => {
|
||||||
//TODO: add ReactionInput Type after debug
|
const response = await privateGraphQLClient.mutation(reactionCreate, { reaction: input }).toPromise()
|
||||||
const response = await privateGraphQLClient.mutation(reactionCreate, { reaction }).toPromise()
|
console.debug('[createReaction]:', response.data)
|
||||||
console.log('!!! response:', response)
|
return response.data.createReaction.reaction
|
||||||
return response.data
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// CUDL
|
// CUDL
|
||||||
|
|
Loading…
Reference in New Issue
Block a user