Use EventComments on the poll and calendar pages and publish comments through one publishComment
This commit is contained in:
parent
9c3d77a2f2
commit
b77c8eafd1
11 changed files with 84 additions and 210 deletions
|
|
@ -10,7 +10,7 @@ and NIP-43 tables in [SKILL.md](SKILL.md). Routes are under `src/routes/`.
|
|||
|---|---|---|---|---|
|
||||
| Chat | `MESSAGE` (9) | none | `src/app/rooms.ts` | `spaces/[relay]/chat`, `spaces/[relay]/[h]` (`RoomChat`) |
|
||||
| Threads | `THREAD` (11) | `Thread` | none | `spaces/[relay]/threads`, `threads/[id]` (`ThreadCreate`) |
|
||||
| Comments | `COMMENT` (1111) | `Comment` | `src/app/content.ts` (`makeCommentFilter`) | `CommentCompose`, `EventReply` |
|
||||
| Comments | `COMMENT` (1111) | `Comment` | `src/app/content.ts` (`makeCommentFilter`), `src/app/rooms.ts` (`publishComment`) | `CommentCompose`, `EventReply`, `EventComments` |
|
||||
| Articles | `LONG_FORM` (30023) | `Article` | `src/app/articles.ts` | `spaces/[relay]/articles`, `articles/create`, `articles/[address]` |
|
||||
| Calendar | `EVENT_TIME` (31923) | `TimeEvent` | `src/app/feeds.ts` (`makeCalendarFeed`) | `spaces/[relay]/calendar`, `calendar/[address]` (`CalendarEventForm`) |
|
||||
| Classifieds | `CLASSIFIED` (30402) | `Classified` | `src/app/classifieds.ts` | `spaces/[relay]/classifieds`, `classifieds/[address]` (`ClassifiedForm`) |
|
||||
|
|
|
|||
|
|
@ -379,8 +379,8 @@ Plugin mutators already return a `Command`: `roomLists.get().addRelay(url).then(
|
|||
|
||||
Some call sites call `thunks.get().publish({event, relays, delay})` directly. Anything that
|
||||
honours the `send_delay` window does, because `Command` cannot carry it: room chat
|
||||
(`RoomChat.svelte`), the comment composers (`CommentCompose.svelte` and `EventReply.svelte`) and
|
||||
`publishRoomQuote` in `rooms.ts`. So do the push adapters and `ProfileDelete.svelte`. DMs go through
|
||||
(`RoomChat.svelte`), and `publishComment` (behind both comment composers) and `publishRoomQuote` in
|
||||
`rooms.ts`. So do the push adapters and `ProfileDelete.svelte`. DMs go through
|
||||
`wraps.get().publish({event, recipients})`, which returns a merged thunk (see `reactions.ts`).
|
||||
NIP-86 calls (`relayManagement.get().forUrl(url)`) are not thunks. They return
|
||||
`{result, error}`, and the caller handles `error`.
|
||||
|
|
|
|||
|
|
@ -573,14 +573,17 @@ test("US-052 comment on and react to community posts", async ({seed, as}) => {
|
|||
await expect(heroCard.getByRole("button", {name: PARTY})).toBeVisible()
|
||||
|
||||
await bob.getByRole("button", {name: /^Discussion/}).click()
|
||||
await bob.getByRole("button", {name: "Leave comment"}).click()
|
||||
await bob.getByRole("button", {name: "Add a comment"}).click()
|
||||
|
||||
const reply = bob.locator("form").filter({has: bob.locator(".note-editor")})
|
||||
|
||||
await noteEditor(reply).pressSequentially("Is there parking at The Green?")
|
||||
await reply.getByRole("button", {name: "Post Reply"}).click()
|
||||
await reply.getByRole("button", {name: "Comment"}).click()
|
||||
|
||||
await expect(bob.getByText("Is there parking at The Green?")).toBeVisible()
|
||||
// The composer holds what was typed until the relay confirms it, so match the comment itself.
|
||||
await expect(
|
||||
bob.locator('[data-component="Comment"]').filter({hasText: "Is there parking at The Green?"}),
|
||||
).toBeVisible()
|
||||
|
||||
const alice = await as(users.alice, calendarPath)
|
||||
|
||||
|
|
@ -594,14 +597,18 @@ test("US-052 comment on and react to community posts", async ({seed, as}) => {
|
|||
|
||||
await expect(alice.getByText("Is there parking at The Green?")).toBeVisible()
|
||||
|
||||
await alice.getByRole("button", {name: "Leave comment"}).click()
|
||||
await alice.getByRole("button", {name: "Add a comment"}).click()
|
||||
|
||||
const alicesReply = alice.locator("form").filter({has: alice.locator(".note-editor")})
|
||||
|
||||
await noteEditor(alicesReply).pressSequentially("Yes, in the field behind the pub.")
|
||||
await alicesReply.getByRole("button", {name: "Post Reply"}).click()
|
||||
await alicesReply.getByRole("button", {name: "Comment"}).click()
|
||||
|
||||
await expect(alice.getByText("Yes, in the field behind the pub.")).toBeVisible()
|
||||
await expect(
|
||||
alice
|
||||
.locator('[data-component="Comment"]')
|
||||
.filter({hasText: "Yes, in the field behind the pub."}),
|
||||
).toBeVisible()
|
||||
})
|
||||
|
||||
test("US-053 browse and search the library", async ({seed, as}) => {
|
||||
|
|
|
|||
|
|
@ -1,78 +0,0 @@
|
|||
<script lang="ts">
|
||||
import {sortBy} from "@welshman/lib"
|
||||
import type {TrustedEvent} from "@welshman/util"
|
||||
import SortVertical from "@assets/icons/sort-vertical.svg?dataurl"
|
||||
import Reply from "@assets/icons/reply-2.svg?dataurl"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
import Button from "@lib/components/Button.svelte"
|
||||
import NoteCard from "@app/components/NoteCard.svelte"
|
||||
import NoteContent from "@app/components/NoteContent.svelte"
|
||||
import CommentActions from "@app/components/CommentActions.svelte"
|
||||
import EventReply from "@app/components/EventReply.svelte"
|
||||
import type {FeedContext} from "@app/feeds"
|
||||
|
||||
type Props = {
|
||||
url: string
|
||||
event: TrustedEvent
|
||||
replies: TrustedEvent[]
|
||||
context: FeedContext
|
||||
}
|
||||
|
||||
const {url, event, replies, context}: Props = $props()
|
||||
|
||||
const expand = () => {
|
||||
showAll = true
|
||||
}
|
||||
|
||||
const openReply = () => {
|
||||
showReply = true
|
||||
}
|
||||
|
||||
const closeReply = () => {
|
||||
showReply = false
|
||||
}
|
||||
|
||||
let showAll = $state(false)
|
||||
let showReply = $state(false)
|
||||
|
||||
const ordered = $derived(sortBy(reply => reply.created_at, replies))
|
||||
</script>
|
||||
|
||||
<div class="flex flex-col gap-2 sm:gap-4">
|
||||
{#if ordered.length === 0 && !showReply}
|
||||
<div class="flex flex-col items-center gap-3 py-6">
|
||||
<p class="opacity-75">No comments yet — start the conversation.</p>
|
||||
<Button class="button button-primary" onclick={openReply}>
|
||||
<Icon icon={Reply} />
|
||||
Leave comment
|
||||
</Button>
|
||||
</div>
|
||||
{:else}
|
||||
{#if !showAll && ordered.length > 4}
|
||||
<div class="flex justify-center">
|
||||
<Button class="button button-link" onclick={expand}>
|
||||
<Icon icon={SortVertical} />
|
||||
Show all {ordered.length} replies
|
||||
</Button>
|
||||
</div>
|
||||
{/if}
|
||||
{#each ordered.slice(0, showAll ? undefined : 4) as reply (reply.id)}
|
||||
<NoteCard event={reply} {url} class="card z-feature w-full">
|
||||
<div class="ml-12 flex flex-col gap-3">
|
||||
<NoteContent showEntire event={reply} {url} />
|
||||
<CommentActions event={reply} {url} {context} />
|
||||
</div>
|
||||
</NoteCard>
|
||||
{/each}
|
||||
{#if showReply}
|
||||
<EventReply {url} {event} onClose={closeReply} onSubmit={closeReply} />
|
||||
{:else}
|
||||
<div class="flex justify-end px-2 pb-2">
|
||||
<Button class="button button-primary" onclick={openReply}>
|
||||
<Icon icon={Reply} />
|
||||
Leave comment
|
||||
</Button>
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
|
|
@ -1,8 +1,7 @@
|
|||
<script lang="ts">
|
||||
import {writable} from "svelte/store"
|
||||
import type {TrustedEvent} from "@welshman/util"
|
||||
import {tagSpec, tagValue} from "@welshman/util"
|
||||
import {Comment, Note} from "@welshman/domain"
|
||||
import {Note} from "@welshman/domain"
|
||||
import {isMobile, preventDefault} from "@lib/html"
|
||||
import Paperclip from "@assets/icons/paperclip-2.svg?dataurl"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
|
|
@ -12,7 +11,7 @@
|
|||
import {thunks, writer} from "@app/core"
|
||||
import {DraftKey} from "@app/drafts"
|
||||
import {makeEditor} from "@app/editor"
|
||||
import {toSpace} from "@app/rooms"
|
||||
import {publishComment} from "@app/rooms"
|
||||
import {loadSendDelay} from "@app/settings"
|
||||
import {pushToast} from "@app/toast"
|
||||
|
||||
|
|
@ -31,8 +30,6 @@
|
|||
|
||||
const {event, onCancel, onSubmit, parent, url, noun = "Comment"}: Props = $props()
|
||||
|
||||
const h = $derived(tagValue(tagSpec("h"), event.tags))
|
||||
|
||||
const draftKey = new DraftKey<Values>(`comment:${event.id}:${parent?.id ?? ""}`)
|
||||
const initialValues = draftKey.get()
|
||||
const uploading = writable(false)
|
||||
|
|
@ -40,26 +37,19 @@
|
|||
const selectFiles = () => editor.then(ed => ed.commands.selectFiles())
|
||||
|
||||
// A reply to a room event is a NIP-22 comment, and a reply to a kind 1 note is a NIP-10 note.
|
||||
const renderReply = async (content: string, tags: string[][]) => {
|
||||
const publishReply = async (content: string, tags: string[][]) => {
|
||||
if (url) {
|
||||
const eventWriter = await toSpace(
|
||||
writer(Comment)
|
||||
.setContent(content)
|
||||
.addTags(...tags)
|
||||
.setRootFromEvent(event)
|
||||
.setParentFromEvent(parent ?? event),
|
||||
url,
|
||||
h,
|
||||
)
|
||||
|
||||
return {relays: [url], event: await eventWriter.renderTemplate()}
|
||||
return publishComment({url, event, parent, content, tags})
|
||||
}
|
||||
|
||||
return writer(Note)
|
||||
.setContent(content)
|
||||
.addTags(...tags)
|
||||
.setParent(parent ?? event)
|
||||
.render()
|
||||
return $thunks.publish({
|
||||
...(await writer(Note)
|
||||
.setContent(content)
|
||||
.addTags(...tags)
|
||||
.setParent(parent ?? event)
|
||||
.render()),
|
||||
delay: await loadSendDelay(),
|
||||
})
|
||||
}
|
||||
|
||||
const submit = async () => {
|
||||
|
|
@ -77,8 +67,7 @@
|
|||
loading = true
|
||||
|
||||
try {
|
||||
const reply = await renderReply(content, ed.storage.nostr.getEditorTags())
|
||||
const thunk = $thunks.publish({...reply, delay: await loadSendDelay()})
|
||||
const thunk = await publishReply(content, ed.storage.nostr.getEditorTags())
|
||||
const error = await thunk.waitForError()
|
||||
|
||||
if (error) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<script lang="ts">
|
||||
import {onMount} from "svelte"
|
||||
import cx from "classnames"
|
||||
import {removeUndefined} from "@welshman/lib"
|
||||
import type {TrustedEvent} from "@welshman/util"
|
||||
import {getCommentFiltersForRoot} from "@welshman/util"
|
||||
|
|
@ -16,9 +17,10 @@
|
|||
event: TrustedEvent
|
||||
url?: string
|
||||
context: FeedContext
|
||||
columnClass?: string
|
||||
}
|
||||
|
||||
const {event, url, context}: Props = $props()
|
||||
const {event, url, context, columnClass}: Props = $props()
|
||||
|
||||
const relays = removeUndefined([url])
|
||||
const filters = getCommentFiltersForRoot([event])
|
||||
|
|
@ -48,10 +50,8 @@
|
|||
</script>
|
||||
|
||||
<section class="flex flex-col">
|
||||
<!-- The heading rule is a page-level divider, so it runs full width; the comments below it
|
||||
stay in the article's reading column. -->
|
||||
<div class="border-b px-5 sm:px-8" style="border-color: var(--line)">
|
||||
<div class="mx-auto flex w-full max-w-[68ch] flex-wrap items-center justify-between gap-2 py-3">
|
||||
<div class={cx("flex w-full flex-wrap items-center justify-between gap-2 py-3", columnClass)}>
|
||||
<h2 class="text-lg font-bold">
|
||||
{nodes.length === 0
|
||||
? "Discussion about this post"
|
||||
|
|
@ -66,7 +66,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="px-5 sm:px-8">
|
||||
<div class="mx-auto flex w-full max-w-[68ch] flex-col pb-10">
|
||||
<div class={cx("flex w-full flex-col pb-10", columnClass)}>
|
||||
{#if url && replyTo?.id === event.id}
|
||||
<div class="py-4">
|
||||
<CommentCompose {url} {event} onCancel={clearReplyTo} onSubmit={clearReplyTo} />
|
||||
|
|
|
|||
|
|
@ -2,8 +2,6 @@
|
|||
import {onMount} from "svelte"
|
||||
import {writable} from "svelte/store"
|
||||
import type {TrustedEvent} from "@welshman/util"
|
||||
import {tagSpec, tagValue} from "@welshman/util"
|
||||
import {Comment} from "@welshman/domain"
|
||||
import {isMobile, preventDefault} from "@lib/html"
|
||||
import {fly} from "@lib/transition"
|
||||
import Paperclip from "@assets/icons/paperclip-2.svg?dataurl"
|
||||
|
|
@ -12,12 +10,10 @@
|
|||
import Spinner from "@lib/components/Spinner.svelte"
|
||||
import EditorContent from "@app/editor/EditorContent.svelte"
|
||||
import ComposeParent from "@app/components/ComposeParent.svelte"
|
||||
import {prependParent, toSpace} from "@app/rooms"
|
||||
import {prependParent, publishComment} from "@app/rooms"
|
||||
import {makeEditor} from "@app/editor"
|
||||
import {DraftKey} from "@app/drafts"
|
||||
import {pushToast} from "@app/toast"
|
||||
import {thunks, writer} from "@app/core"
|
||||
import {loadSendDelay} from "@app/settings"
|
||||
|
||||
type Values = {
|
||||
content?: string | object
|
||||
|
|
@ -33,7 +29,6 @@
|
|||
}
|
||||
|
||||
const {url, event, parent, onClose, onClearParent, onSubmit}: Props = $props()
|
||||
const h = $derived(tagValue(tagSpec("h"), event.tags))
|
||||
const draftKey = new DraftKey<Values>(`reply:${event.id}:${parent?.id || ""}`)
|
||||
const initialValues = draftKey.get()
|
||||
const uploading = writable(false)
|
||||
|
|
@ -47,8 +42,7 @@
|
|||
}
|
||||
|
||||
const ed = await editor
|
||||
let content = ed.getText({blockSeparator: "\n"}).trim()
|
||||
let tags = ed.storage.nostr.getEditorTags()
|
||||
const content = ed.getText({blockSeparator: "\n"}).trim()
|
||||
|
||||
if (!content) {
|
||||
return pushToast({
|
||||
|
|
@ -57,24 +51,11 @@
|
|||
})
|
||||
}
|
||||
|
||||
if (parent) {
|
||||
;({content, tags} = await prependParent(parent, {content, tags}, url))
|
||||
}
|
||||
|
||||
const eventWriter = await toSpace(
|
||||
writer(Comment)
|
||||
.setContent(content)
|
||||
.addTags(...tags)
|
||||
.setRootFromEvent(event)
|
||||
.setParentFromEvent(event),
|
||||
const tags = ed.storage.nostr.getEditorTags()
|
||||
const thunk = await publishComment({
|
||||
url,
|
||||
h,
|
||||
)
|
||||
|
||||
const thunk = $thunks.publish({
|
||||
relays: [url],
|
||||
event: await eventWriter.renderTemplate(),
|
||||
delay: await loadSendDelay(),
|
||||
event,
|
||||
...(await prependParent(parent, {content, tags}, url)),
|
||||
})
|
||||
|
||||
draftKey.clear()
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import {
|
|||
toNostrURI,
|
||||
} from "@welshman/util"
|
||||
import type {EventContent, TrustedEvent} from "@welshman/util"
|
||||
import {Message} from "@welshman/domain"
|
||||
import {Comment, Message} from "@welshman/domain"
|
||||
import type {BaseEventReader, EventWriter} from "@welshman/domain"
|
||||
import {MembershipStatus, RoomLists, makeRoomKey, createSearch, publish} from "@welshman/app"
|
||||
import type {Room, RoomMeta} from "@welshman/app"
|
||||
|
|
@ -33,6 +33,7 @@ import {
|
|||
} from "@app/core"
|
||||
import {deriveSpacePermissions, deriveUserIsSpaceStaff} from "@app/management"
|
||||
import {makeRoomPath} from "@app/routes"
|
||||
import {loadSendDelay} from "@app/settings"
|
||||
|
||||
export const PROTECTED = ["-"]
|
||||
|
||||
|
|
@ -139,6 +140,34 @@ export const publishRoomQuote = async ({
|
|||
})
|
||||
}
|
||||
|
||||
export const publishComment = async ({
|
||||
url,
|
||||
event,
|
||||
parent = event,
|
||||
content,
|
||||
tags,
|
||||
}: EventContent & {
|
||||
url: string
|
||||
event: TrustedEvent
|
||||
parent?: TrustedEvent
|
||||
}) => {
|
||||
const eventWriter = await toSpace(
|
||||
writer(Comment)
|
||||
.setContent(content)
|
||||
.addTags(...tags)
|
||||
.setRootFromEvent(event)
|
||||
.setParentFromEvent(parent),
|
||||
url,
|
||||
tagValue(tagSpec("h"), event.tags),
|
||||
)
|
||||
|
||||
return thunks.get().publish({
|
||||
relays: [url],
|
||||
event: await eventWriter.renderTemplate(),
|
||||
delay: await loadSendDelay(),
|
||||
})
|
||||
}
|
||||
|
||||
export const publishToSpace = async (
|
||||
eventWriter: EventWriter<BaseEventReader>,
|
||||
{url, h, shareToChat}: {url: string; h?: string; shareToChat?: boolean},
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="border-t" style="border-color: var(--line)">
|
||||
<EventComments event={$event} {url} {context} />
|
||||
<EventComments event={$event} {url} {context} columnClass="mx-auto max-w-[68ch]" />
|
||||
</div>
|
||||
</div>
|
||||
<ArticleAuthorSidebar {url} event={$event} />
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
import CalendarEventHeader from "@app/components/CalendarEventHeader.svelte"
|
||||
import CalendarEventMeta from "@app/components/CalendarEventMeta.svelte"
|
||||
import CalendarEventDate from "@app/components/CalendarEventDate.svelte"
|
||||
import CalendarEventDiscussion from "@app/components/CalendarEventDiscussion.svelte"
|
||||
import EventComments from "@app/components/EventComments.svelte"
|
||||
import CalendarEventPeople from "@app/components/CalendarEventPeople.svelte"
|
||||
import CalendarRsvp from "@app/components/CalendarRsvp.svelte"
|
||||
import {deriveRsvps, getRsvpsByStatus, makeRsvpFilter} from "@app/calendar"
|
||||
|
|
@ -37,7 +37,7 @@
|
|||
const event = $events.one(address, [url]).$
|
||||
const timeEvent = derived(event, $event => ($event ? reader(TimeEvent)($event) : undefined))
|
||||
const filters = $derived($event ? getCommentFiltersForRoot([$event]) : [])
|
||||
const replies = $derived($events.desc(filters).$)
|
||||
const comments = $derived($events.asc(filters).$)
|
||||
const rsvps = $derived($event ? deriveRsvps($event) : readable<TrustedEvent[]>([]))
|
||||
const people = $derived(getRsvpsByStatus($rsvps))
|
||||
|
||||
|
|
@ -113,8 +113,8 @@
|
|||
aria-pressed={tab === "discussion"}
|
||||
onclick={showTab("discussion")}>
|
||||
Discussion
|
||||
{#if $replies.length > 0}
|
||||
<span class="opacity-75">{$replies.length}</span>
|
||||
{#if $comments.length > 0}
|
||||
<span class="opacity-75">{$comments.length}</span>
|
||||
{/if}
|
||||
</Button>
|
||||
<Button
|
||||
|
|
@ -138,7 +138,7 @@
|
|||
{/if}
|
||||
</div>
|
||||
{:else if tab === "discussion"}
|
||||
<CalendarEventDiscussion {url} event={$event} replies={$replies} {context} />
|
||||
<EventComments {url} event={$event} {context} />
|
||||
{:else}
|
||||
<CalendarEventPeople {url} event={$event} rsvps={$rsvps} />
|
||||
{/if}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,14 @@
|
|||
<script lang="ts">
|
||||
import {onDestroy, onMount} from "svelte"
|
||||
import {sleep} from "@welshman/lib"
|
||||
import {POLL, POLL_RESPONSE, getCommentFiltersForRoot} from "@welshman/util"
|
||||
import SortVertical from "@assets/icons/sort-vertical.svg?dataurl"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
import {POLL, POLL_RESPONSE} from "@welshman/util"
|
||||
import PageContent from "@lib/components/PageContent.svelte"
|
||||
import Spinner from "@lib/components/Spinner.svelte"
|
||||
import Button from "@lib/components/Button.svelte"
|
||||
import SpaceBar from "@app/components/SpaceBar.svelte"
|
||||
import NoteCard from "@app/components/NoteCard.svelte"
|
||||
import NoteContent from "@app/components/NoteContent.svelte"
|
||||
import CommentActions from "@app/components/CommentActions.svelte"
|
||||
import EventReply from "@app/components/EventReply.svelte"
|
||||
import EventComments from "@app/components/EventComments.svelte"
|
||||
import {events, network} from "@app/core"
|
||||
import {makeFeedContext} from "@app/feeds"
|
||||
import {decodeRelay} from "@app/relays"
|
||||
|
|
@ -23,28 +20,11 @@
|
|||
const url = decodeRelay(relay)
|
||||
const context = makeFeedContext({relays: [url]})
|
||||
const event = $events.one(id, [url]).$
|
||||
const filters = $derived($event ? getCommentFiltersForRoot([$event]) : [])
|
||||
const comments = $derived($events.asc(filters).$)
|
||||
|
||||
const back = () => history.back()
|
||||
|
||||
const openReply = () => {
|
||||
showReply = true
|
||||
}
|
||||
|
||||
const closeReply = () => {
|
||||
showReply = false
|
||||
}
|
||||
|
||||
const expand = () => {
|
||||
showAll = true
|
||||
}
|
||||
|
||||
onDestroy(context.cleanup)
|
||||
|
||||
let showAll = $state(false)
|
||||
let showReply = $state(false)
|
||||
|
||||
onMount(() => {
|
||||
const controller = new AbortController()
|
||||
|
||||
|
|
@ -61,16 +41,6 @@
|
|||
controller.abort()
|
||||
}
|
||||
})
|
||||
|
||||
$effect(() => {
|
||||
if (filters.length > 0) {
|
||||
const controller = new AbortController()
|
||||
|
||||
$network.request({relays: [url], filters, signal: controller.signal})
|
||||
|
||||
return () => controller.abort()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<SpaceBar {back}>
|
||||
|
|
@ -81,37 +51,13 @@
|
|||
|
||||
<PageContent class="flex flex-col gap-2 p-2 sm:gap-4 sm:p-4">
|
||||
{#if $event}
|
||||
<div class="flex flex-col gap-3">
|
||||
<NoteCard event={$event} {url} class="card z-feature w-full">
|
||||
<div class="flex flex-col gap-3 ml-12 flex flex-col gap-3">
|
||||
<NoteContent showEntire event={$event} {url} />
|
||||
<CommentActions showActivity {url} event={$event} {context} />
|
||||
</div>
|
||||
</NoteCard>
|
||||
{#if !showAll && $comments.length > 4}
|
||||
<div class="flex justify-center">
|
||||
<Button class="button button-link" onclick={expand}>
|
||||
<Icon icon={SortVertical} />
|
||||
Show all {$comments.length} comments
|
||||
</Button>
|
||||
</div>
|
||||
{/if}
|
||||
{#each $comments.slice(0, showAll ? undefined : 4) as reply (reply.id)}
|
||||
<NoteCard event={reply} {url} class="card z-feature w-full">
|
||||
<div class="flex flex-col gap-3 ml-12">
|
||||
<NoteContent showEntire event={reply} {url} />
|
||||
<CommentActions event={reply} {url} {context} />
|
||||
</div>
|
||||
</NoteCard>
|
||||
{/each}
|
||||
</div>
|
||||
{#if showReply}
|
||||
<EventReply {url} event={$event} onClose={closeReply} onSubmit={closeReply} />
|
||||
{:else}
|
||||
<div class="flex justify-end">
|
||||
<Button class="button button-primary" onclick={openReply}>Comment on this poll</Button>
|
||||
<NoteCard event={$event} {url} class="card z-feature w-full">
|
||||
<div class="ml-12 flex flex-col gap-3">
|
||||
<NoteContent showEntire event={$event} {url} />
|
||||
<CommentActions showActivity {url} event={$event} {context} />
|
||||
</div>
|
||||
{/if}
|
||||
</NoteCard>
|
||||
<EventComments event={$event} {url} {context} />
|
||||
{:else}
|
||||
<div class="flex justify-center py-20">
|
||||
{#await sleep(5000)}
|
||||
|
|
|
|||
Loading…
Reference in a new issue