|
| 1 | +<script lang="ts"> |
| 2 | + import { page } from '$app/stores'; |
| 3 | + import { |
| 4 | + TableHeader, |
| 5 | + TableBody, |
| 6 | + TableRowLink, |
| 7 | + TableCellHead, |
| 8 | + TableCellText, |
| 9 | + TableCell, |
| 10 | + TableScroll, |
| 11 | + } from '$lib/elements/table'; |
| 12 | + import { Button } from '$lib/elements/forms'; |
| 13 | + import { |
| 14 | + Empty, |
| 15 | + EmptySearch, |
| 16 | + SearchQuery, |
| 17 | + PaginationWithLimit, |
| 18 | + Heading, |
| 19 | + } from '$lib/components'; |
| 20 | + import { toLocaleDateTime } from '$lib/helpers/date'; |
| 21 | + import { Container } from '$lib/layout'; |
| 22 | + import { base } from '$app/paths'; |
| 23 | + import { ID, type Models } from '@appwrite.io/console'; |
| 24 | + import type { PageData } from './$types'; |
| 25 | + import { writable } from 'svelte/store'; |
| 26 | + import { sdk } from '$lib/stores/sdk'; |
| 27 | + import { addNotification } from '$lib/stores/notifications'; |
| 28 | + import { Submit, trackError, trackEvent } from '$lib/actions/analytics'; |
| 29 | + import { invalidate } from '$app/navigation'; |
| 30 | + import { Dependencies } from '$lib/constants'; |
| 31 | + import type { Subscriber } from './+page'; |
| 32 | +
|
| 33 | + export let data: PageData; |
| 34 | + let users = writable(new Map<string, Models.User<Models.Preferences>>()); |
| 35 | + let selectedSubscriber: Subscriber | null = null; |
| 36 | + let showAdd = false; |
| 37 | + let showDelete = false; |
| 38 | +
|
| 39 | + const project = $page.params.project; |
| 40 | +
|
| 41 | + async function add(event: CustomEvent<string[]>) { |
| 42 | + const userIds = event.detail; |
| 43 | +
|
| 44 | + async function addSubscriber(userId: string) { |
| 45 | + try { |
| 46 | + await sdk.forProject.client.call( |
| 47 | + 'POST', |
| 48 | + new URL( |
| 49 | + `${sdk.forProject.client.config.endpoint}/messaging/topics/${$page.params.topic}/subscribers` |
| 50 | + ), |
| 51 | + { |
| 52 | + 'X-Appwrite-Project': sdk.forProject.client.config.project, |
| 53 | + 'content-type': 'application/json', |
| 54 | + 'X-Appwrite-Mode': 'admin' |
| 55 | + }, |
| 56 | + { |
| 57 | + subscriberId: ID.unique(), |
| 58 | + topicId: $page.params.topic, |
| 59 | + targetId: userId |
| 60 | + } |
| 61 | + ); |
| 62 | + trackEvent(Submit.MessagingTopicCreate); |
| 63 | + await invalidate(Dependencies.MESSAGING_TOPIC_SUBSCRIBERS); |
| 64 | + } catch (e) { |
| 65 | + trackError(e, Submit.MessagingTopicCreate); |
| 66 | + } |
| 67 | + } |
| 68 | +
|
| 69 | + const promises = userIds.map(addSubscriber); |
| 70 | +
|
| 71 | + await Promise.all(promises); |
| 72 | +
|
| 73 | + showAdd = false; |
| 74 | + addNotification({ |
| 75 | + type: 'success', |
| 76 | + message: `Added ${userIds.length} subscriber${userIds.length > 1 ? 's' : ''} to topic}` |
| 77 | + }); |
| 78 | + } |
| 79 | +
|
| 80 | + $: console.log($users); |
| 81 | +</script> |
| 82 | + |
| 83 | +<Container> |
| 84 | + <div class="u-flex u-flex-vertical"> |
| 85 | + <div class="u-flex u-main-space-between"> |
| 86 | + <Heading tag="h2" size="5">Subscribers</Heading> |
| 87 | + <div class="is-only-mobile"> |
| 88 | + <Button on:click={() => (showAdd = true)} event="create_subscriber"> |
| 89 | + <span class="icon-plus" aria-hidden="true" /> |
| 90 | + <span class="text">Create topic</span> |
| 91 | + </Button> |
| 92 | + </div> |
| 93 | + </div> |
| 94 | + <!-- TODO: fix width of search input in mobile --> |
| 95 | + <SearchQuery search={data.search} placeholder="Search by name"> |
| 96 | + <div class="u-flex u-gap-16 is-not-mobile"> |
| 97 | + <Button on:click={() => (showAdd = true)} event="create_subscriber"> |
| 98 | + <span class="icon-plus" aria-hidden="true" /> |
| 99 | + <span class="text">Add subscriber</span> |
| 100 | + </Button> |
| 101 | + </div> |
| 102 | + </SearchQuery> |
| 103 | + </div> |
| 104 | + {#if data.subscribers.total} |
| 105 | + <TableScroll> |
| 106 | + <TableHeader> |
| 107 | + <TableCellHead>Name</TableCellHead> |
| 108 | + <TableCellHead onlyDesktop>Created</TableCellHead> |
| 109 | + <TableCellHead width={30} /> |
| 110 | + </TableHeader> |
| 111 | + <TableBody> |
| 112 | + {#each data.subscribers.subscribers as subscriber} |
| 113 | + {@const user = data.targetsById.get(subscriber.$id)} |
| 114 | + <TableRowLink |
| 115 | + href={`${base}/console/project-${project}/auth/users/user-${user.$id}`}> |
| 116 | + <!-- <TableCell title="ID"> |
| 117 | + <Id value={topic.$id}> |
| 118 | + {topic.$id} |
| 119 | + </Id> |
| 120 | + </TableCell> --> |
| 121 | + <TableCell title="Name"> |
| 122 | + {user.name ?? '-'} |
| 123 | + </TableCell> |
| 124 | + <TableCellText onlyDesktop title="Created"> |
| 125 | + {toLocaleDateTime(subscriber.$createdAt)} |
| 126 | + </TableCellText> |
| 127 | + <TableCell> |
| 128 | + <button |
| 129 | + class="button is-only-icon is-text" |
| 130 | + aria-label="Delete item" |
| 131 | + on:click|preventDefault={() => { |
| 132 | + selectedSubscriber = subscriber; |
| 133 | + showDelete = true; |
| 134 | + trackEvent('click_delete_subscriber'); |
| 135 | + }}> |
| 136 | + <span class="icon-trash" aria-hidden="true" /> |
| 137 | + </button> |
| 138 | + </TableCell> |
| 139 | + </TableRowLink> |
| 140 | + {/each} |
| 141 | + </TableBody> |
| 142 | + </TableScroll> |
| 143 | + |
| 144 | + <PaginationWithLimit |
| 145 | + name="Subscribers" |
| 146 | + limit={data.limit} |
| 147 | + offset={data.offset} |
| 148 | + total={data.subscribers.total} /> |
| 149 | + <!-- TODO: remove data.search != 'empty' when the API is ready with data --> |
| 150 | + {:else if data.search && data.search != 'empty'} |
| 151 | + <EmptySearch> |
| 152 | + <div class="u-text-center"> |
| 153 | + <b>Sorry, we couldn't find '{data.search}'</b> |
| 154 | + <p>There are no subscribers that match your search.</p> |
| 155 | + </div> |
| 156 | + <Button |
| 157 | + secondary |
| 158 | + href={`/console/project-${$page.params.project}/messaging/topics/topic-${$page.params.topic}/subscribers`}> |
| 159 | + Clear Search |
| 160 | + </Button> |
| 161 | + </EmptySearch> |
| 162 | + {:else} |
| 163 | + <!-- TODO: update docs link --> |
| 164 | + <Empty |
| 165 | + single |
| 166 | + on:click={() => (showAdd = true)} |
| 167 | + href="https://appwrite.io/docs/references/cloud/client-web/teams" |
| 168 | + target="subscriber" /> |
| 169 | + {/if} |
| 170 | +</Container> |
| 171 | + |
| 172 | +<!-- TODO: handle create --> |
| 173 | +<!-- <UserModal bind:show={showAdd} on:submit={add} bind:users /> --> |
0 commit comments