diff --git a/src/lib/actions/analytics.ts b/src/lib/actions/analytics.ts index e9c127f9c5..39551514b2 100644 --- a/src/lib/actions/analytics.ts +++ b/src/lib/actions/analytics.ts @@ -292,5 +292,11 @@ export enum Submit { MessagingProviderDelete = 'submit_messaging_provider_delete', MessagingProviderUpdate = 'submit_messaging_provider_update', MessagingMessageCreate = 'submit_messaging_message_create', - MessagingMessageDelete = 'submit_messaging_message_delete' + MessagingMessageDelete = 'submit_messaging_message_delete', + MessagingTopicCreate = 'submit_messaging_topic_create', + MessagingTopicDelete = 'submit_messaging_topic_delete', + MessagingTopicUpdateName = 'submit_messaging_topic_update_name', + MessagingTopicUpdateDescription = 'submit_messaging_topic_update_description', + MessagingTopicSubscriberAdd = 'submit_messaging_topic_subscriber_add', + MessagingTopicSubscriberDelete = 'submit_messaging_topic_subscriber_delete' } diff --git a/src/lib/constants.ts b/src/lib/constants.ts index c9868fdcd0..da342ce92c 100644 --- a/src/lib/constants.ts +++ b/src/lib/constants.ts @@ -49,7 +49,10 @@ export enum Dependencies { CONSOLE_VARIABLES = 'dependency:console_variables', MESSAGING_PROVIDERS = 'dependency:messaging_providers', MESSAGING_PROVIDER = 'dependency:messaging_provider', - MESSAGING_MESSAGE = 'dependency:messaging_message' + MESSAGING_MESSAGE = 'dependency:messaging_message', + MESSAGING_TOPICS = 'dependency:messaging_topics', + MESSAGING_TOPIC = 'dependency:messaging_topic', + MESSAGING_TOPIC_SUBSCRIBERS = 'dependency:messaging_topic_subscribers' } export const scopes: { diff --git a/src/routes/console/project-[project]/messaging/actions.svelte b/src/routes/console/project-[project]/messaging/actions.svelte new file mode 100644 index 0000000000..bf2bb5b7bf --- /dev/null +++ b/src/routes/console/project-[project]/messaging/actions.svelte @@ -0,0 +1,44 @@ + + + + + + (showTopics = true)}>Select topics + (showUserTargets = true)}>Select targets + + + + { + showTopics = false; + dispatch('addTopics', e.detail); + }} /> + { + showUserTargets = false; + dispatch('addTargets', e.detail); + }} /> diff --git a/src/routes/console/project-[project]/messaging/create.svelte b/src/routes/console/project-[project]/messaging/create.svelte index feeb993e42..52e96a0292 100644 --- a/src/routes/console/project-[project]/messaging/create.svelte +++ b/src/routes/console/project-[project]/messaging/create.svelte @@ -1,5 +1,4 @@ @@ -29,6 +30,7 @@ ) return; $providerType = type; + $topicsById = {}; $targetsById = {}; const common = { topics: [], diff --git a/src/routes/console/project-[project]/messaging/store.ts b/src/routes/console/project-[project]/messaging/store.ts index 6a08966c05..d30c67b808 100644 --- a/src/routes/console/project-[project]/messaging/store.ts +++ b/src/routes/console/project-[project]/messaging/store.ts @@ -15,6 +15,9 @@ export const columns = writable([ { id: 'deliveredAt', title: 'Delivered at', type: 'datetime', show: false, width: 120 } ]); +export const targetsById = writable>({}); +export const topicsById = writable>({}); + // TODO: remove this when the SDK and API are ready export type Message = { $id: string; @@ -238,3 +241,25 @@ export const providersById: { [providerId: string]: Provider } = { options: {} } }; + +// TODO: remove when sdk has the model +export type Topic = { + $id: string; + $createdAt: string; + $updatedAt: string; + providerId: string; + name: string; + total: number; + description: string; +}; + +export type Target = { + $id: string; + $createdAt: string; + $updatedAt: string; + name: string; + userId: string; + providerId: string; + providerType: ProviderTypes; + identifier: string; +}; diff --git a/src/routes/console/project-[project]/messaging/topics/+page.svelte b/src/routes/console/project-[project]/messaging/topics/+page.svelte new file mode 100644 index 0000000000..659b734de9 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/topics/+page.svelte @@ -0,0 +1,103 @@ + + + +
+
+ Topics +
+ +
+
+ + +
+ + + +
+
+
+
+ + +
+
+ + +
+
+
+ {#if data.topics.total} + + + + + {:else if data.search && data.search != 'empty'} + +
+ Sorry, we couldn't find '{data.search}' +

There are no topics that match your search.

+
+ +
+ {:else} + + ($showCreate = true)} + href="https://appwrite.io/docs/references/cloud/client-web/teams" + target="topic" /> + {/if} + + + diff --git a/src/routes/console/project-[project]/messaging/topics/+page.ts b/src/routes/console/project-[project]/messaging/topics/+page.ts new file mode 100644 index 0000000000..3ba12e6d80 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/topics/+page.ts @@ -0,0 +1,53 @@ +import { Query } from '@appwrite.io/console'; +import { sdk } from '$lib/stores/sdk'; +import { getLimit, getPage, getQuery, getSearch, pageToOffset } from '$lib/helpers/load'; +import { Dependencies, PAGE_LIMIT } from '$lib/constants'; +import { queryParamToMap, queries } from '$lib/components/filters/store'; +import type { Topic } from '../store'; + +export const load = async ({ depends, url, route }) => { + depends(Dependencies.MESSAGING_TOPICS); + const page = getPage(url); + const search = getSearch(url); + const limit = getLimit(url, route, PAGE_LIMIT); + const offset = pageToOffset(page, limit); + const query = getQuery(url); + + const parsedQueries = queryParamToMap(query || '[]'); + queries.set(parsedQueries); + + const payload = { + queries: [ + Query.limit(limit), + Query.offset(offset), + Query.orderDesc(''), + ...parsedQueries.values() + ] + }; + + if (search) { + payload['search'] = search; + } + + // TODO: remove when the API is ready with data + // This allows us to mock w/ data and when search returns 0 results + const topics: { topics: Topic[]; total: number } = await sdk.forProject.client.call( + 'GET', + new URL(sdk.forProject.client.config.endpoint + '/messaging/topics'), + { + 'X-Appwrite-Project': sdk.forProject.client.config.project, + 'content-type': 'application/json', + 'X-Appwrite-Mode': 'admin' + }, + payload + ); + + return { + offset, + limit, + search, + query, + page, + topics + }; +}; diff --git a/src/routes/console/project-[project]/messaging/topics/create.svelte b/src/routes/console/project-[project]/messaging/topics/create.svelte new file mode 100644 index 0000000000..2bb52245e2 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/topics/create.svelte @@ -0,0 +1,88 @@ + + + + + + + + {#if !showCustomId} +
+ (showCustomId = !showCustomId)} + > +
+ {:else} + + {/if} +
+ + + + +
diff --git a/src/routes/console/project-[project]/messaging/topics/store.ts b/src/routes/console/project-[project]/messaging/topics/store.ts new file mode 100644 index 0000000000..0c950c385b --- /dev/null +++ b/src/routes/console/project-[project]/messaging/topics/store.ts @@ -0,0 +1,12 @@ +import type { Column } from '$lib/helpers/types'; +import { writable } from 'svelte/store'; + +export let showCreate = writable(false); + +export const columns = writable([ + { id: '$id', title: 'Topic ID', type: 'string', show: true, width: 140 }, + { id: 'name', title: 'Name', type: 'string', show: true, width: 140 }, + { id: 'description', title: 'Description', type: 'string', show: true, width: 140 }, + { id: 'total', title: 'Subscribers', type: 'integer', show: true, width: 140 }, + { id: '$createdAt', title: 'Created', type: 'datetime', show: true, width: 140 } +]); diff --git a/src/routes/console/project-[project]/messaging/topics/table.svelte b/src/routes/console/project-[project]/messaging/topics/table.svelte new file mode 100644 index 0000000000..c72533d667 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/topics/table.svelte @@ -0,0 +1,154 @@ + + + + + d.$id)} /> + {#each $columns as column} + {#if column.show} + {column.title} + {/if} + {/each} + + + {#each data.topics.topics as topic (topic.$id)} + + + + {#each $columns as column (column.id)} + {#if column.show} + {#if column.id === '$id'} + {#key $columns} + + {topic.$id} + + {/key} + {:else if column.type === 'datetime'} + + {#if !topic[column.id]} + - + {:else} + {toLocaleDateTime(topic[column.id])} + {/if} + + {:else} + + {topic[column.id]} + + {/if} + {/if} + {/each} + + {/each} + + + + 0}> +
+
+ {selectedIds.length} +

+ + {selectedIds.length > 1 ? 'topics' : 'topic'} + + selected +

+
+ +
+ + +
+
+
+ + +

+ Are you sure you want to delete {selectedIds.length} + {selectedIds.length > 1 ? 'topics' : 'topic'}? +

+ + + + +
diff --git a/src/routes/console/project-[project]/messaging/topics/topic-[topic]/+layout.svelte b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/+layout.svelte new file mode 100644 index 0000000000..525eedb90f --- /dev/null +++ b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/+layout.svelte @@ -0,0 +1,5 @@ + + Topic - Appwrite + + + diff --git a/src/routes/console/project-[project]/messaging/topics/topic-[topic]/+layout.ts b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/+layout.ts new file mode 100644 index 0000000000..594acc96ba --- /dev/null +++ b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/+layout.ts @@ -0,0 +1,30 @@ +import type { LayoutLoad } from './$types'; +import Breadcrumbs from './breadcrumbs.svelte'; +import Header from './header.svelte'; +import { sdk } from '$lib/stores/sdk'; +import { Dependencies } from '$lib/constants'; +import { error } from '@sveltejs/kit'; + +export const load: LayoutLoad = async ({ params, depends }) => { + depends(Dependencies.MESSAGING_TOPIC); + + const response = await sdk.forProject.client.call( + 'GET', + new URL(sdk.forProject.client.config.endpoint + '/messaging/topics/' + params.topic), + { + 'X-Appwrite-Project': sdk.forProject.client.config.project, + 'content-type': 'application/json', + 'X-Appwrite-Mode': 'admin' + } + ); + + try { + return { + header: Header, + breadcrumbs: Breadcrumbs, + topic: response + }; + } catch (e) { + throw error(e.code, e.message); + } +}; diff --git a/src/routes/console/project-[project]/messaging/topics/topic-[topic]/+page.svelte b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/+page.svelte new file mode 100644 index 0000000000..dd88db1906 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/+page.svelte @@ -0,0 +1,14 @@ + + + +
+ + + + diff --git a/src/routes/console/project-[project]/messaging/topics/topic-[topic]/activity/+page.svelte b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/activity/+page.svelte new file mode 100644 index 0000000000..f805a79f04 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/activity/+page.svelte @@ -0,0 +1,8 @@ + + + diff --git a/src/routes/console/project-[project]/messaging/topics/topic-[topic]/activity/+page.ts b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/activity/+page.ts new file mode 100644 index 0000000000..97f3d29aeb --- /dev/null +++ b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/activity/+page.ts @@ -0,0 +1,34 @@ +import { Query, type Models } from '@appwrite.io/console'; +import { sdk } from '$lib/stores/sdk'; +import { getLimit, getPage, pageToOffset } from '$lib/helpers/load'; +import { PAGE_LIMIT } from '$lib/constants'; +import type { PageLoad } from './$types'; + +export const load: PageLoad = async ({ params, url, route }) => { + const page = getPage(url); + const limit = getLimit(url, route, PAGE_LIMIT); + const offset = pageToOffset(page, limit); + + const payload = { + queries: [Query.limit(limit), Query.offset(offset)] + }; + + // TODO: remove when the API is ready with data + // This allows us to mock w/ data and when search returns 0 results + const logs: Models.LogList = await sdk.forProject.client.call( + 'GET', + new URL(`${sdk.forProject.client.config.endpoint}/messaging/topics/${params.topic}/logs`), + { + 'X-Appwrite-Project': sdk.forProject.client.config.project, + 'content-type': 'application/json', + 'X-Appwrite-Mode': 'admin' + }, + payload + ); + + return { + offset, + limit, + logs + }; +}; diff --git a/src/routes/console/project-[project]/messaging/topics/topic-[topic]/breadcrumbs.svelte b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/breadcrumbs.svelte new file mode 100644 index 0000000000..c41df553b9 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/breadcrumbs.svelte @@ -0,0 +1,27 @@ + + + diff --git a/src/routes/console/project-[project]/messaging/topics/topic-[topic]/dangerZone.svelte b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/dangerZone.svelte new file mode 100644 index 0000000000..113c2550cd --- /dev/null +++ b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/dangerZone.svelte @@ -0,0 +1,45 @@ + + + + + +
+ Delete topic +
+

+ The topic will be permanently deleted, including all data associated with this topic. This + action is irreversible. +

+ + + +
{$topic.name}
+
+

+ {$topic.total} subscriber{$topic.total === 1 ? '' : 's'} +

+
+
+ + + + +
+ + diff --git a/src/routes/console/project-[project]/messaging/topics/topic-[topic]/deleteTopic.svelte b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/deleteTopic.svelte new file mode 100644 index 0000000000..a3e4226e33 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/deleteTopic.svelte @@ -0,0 +1,56 @@ + + + +

+ Are you sure you want to delete {$topic.name} from '{$project.name}'? +

+ + + + +
diff --git a/src/routes/console/project-[project]/messaging/topics/topic-[topic]/details.svelte b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/details.svelte new file mode 100644 index 0000000000..1e81e5044e --- /dev/null +++ b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/details.svelte @@ -0,0 +1,19 @@ + + + +
+ Details +
+ +
+
+

{$topic.total} subscriber{$topic.total === 1 ? '' : 's'}

+

Created: {toLocaleDateTime($topic.$createdAt)}

+
+
+
+
diff --git a/src/routes/console/project-[project]/messaging/topics/topic-[topic]/header.svelte b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/header.svelte new file mode 100644 index 0000000000..0848e48db2 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/header.svelte @@ -0,0 +1,48 @@ + + + + + + {$topic.name} + + {$topic.$id} + + + + {#each tabs as tab} + + {tab.title} + + {/each} + + diff --git a/src/routes/console/project-[project]/messaging/topics/topic-[topic]/store.ts b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/store.ts new file mode 100644 index 0000000000..a2379dadd2 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/store.ts @@ -0,0 +1,9 @@ +import { derived } from 'svelte/store'; +import { page } from '$app/stores'; +import type { Topic } from '../../store'; + +export const topic = derived( + page, + // TODO: Set actual type + ($page) => $page.data.topic as Topic +); diff --git a/src/routes/console/project-[project]/messaging/topics/topic-[topic]/subscribers/+page.svelte b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/subscribers/+page.svelte new file mode 100644 index 0000000000..02aef8a3e0 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/subscribers/+page.svelte @@ -0,0 +1,163 @@ + + + +
+
+ Subscribers +
+ +
+
+ + +
+ + + +
+
+
+
+ + +
+
+ + +
+
+
+ {#if data.subscribers.total} +
+ + + + {:else if data.search && data.search != 'empty'} + +
+ Sorry, we couldn't find '{data.search}' +

There are no subscribers that match your search.

+
+ +
+ {:else} + + (showAdd = true)} + href="https://appwrite.io/docs/references/cloud/client-web/teams" + target="subscriber" /> + {/if} + + + diff --git a/src/routes/console/project-[project]/messaging/topics/topic-[topic]/subscribers/+page.ts b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/subscribers/+page.ts new file mode 100644 index 0000000000..fe22003d8e --- /dev/null +++ b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/subscribers/+page.ts @@ -0,0 +1,69 @@ +import { Query } from '@appwrite.io/console'; +import { sdk } from '$lib/stores/sdk'; +import { getLimit, getPage, getQuery, getSearch, pageToOffset } from '$lib/helpers/load'; +import { Dependencies, PAGE_LIMIT } from '$lib/constants'; +import type { PageLoad } from './$types'; +import type { Target } from '../../../store'; +import { queryParamToMap, queries } from '$lib/components/filters/store'; + +export type Subscriber = { + $id: string; + $createdAt: string; + $updatedAt: string; + targetId: string; + target: Target; + userName: string; + topicId: string; +}; + +export const load: PageLoad = async ({ params, url, route, depends, parent }) => { + depends(Dependencies.MESSAGING_TOPIC_SUBSCRIBERS); + const page = getPage(url); + const limit = getLimit(url, route, PAGE_LIMIT); + const offset = pageToOffset(page, limit); + const search = getSearch(url); + const query = getQuery(url); + + const parsedQueries = queryParamToMap(query || '[]'); + queries.set(parsedQueries); + + const payload = { + queries: [ + Query.limit(limit), + Query.offset(offset), + Query.orderDesc(''), + ...parsedQueries.values() + ] + }; + + if (search) { + payload['search'] = search; + } + + const { topic } = await parent(); + + // TODO: remove when the API is ready with data + // This allows us to mock w/ data and when search returns 0 results + const subscribers: { subscribers: Subscriber[]; total: number } = + await sdk.forProject.client.call( + 'GET', + new URL( + `${sdk.forProject.client.config.endpoint}/messaging/topics/${params.topic}/subscribers` + ), + { + 'X-Appwrite-Project': sdk.forProject.client.config.project, + 'content-type': 'application/json', + 'X-Appwrite-Mode': 'admin' + }, + payload + ); + + return { + offset, + limit, + search, + query, + topic, + subscribers + }; +}; diff --git a/src/routes/console/project-[project]/messaging/topics/topic-[topic]/subscribers/store.ts b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/subscribers/store.ts new file mode 100644 index 0000000000..014bca76cf --- /dev/null +++ b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/subscribers/store.ts @@ -0,0 +1,11 @@ +import type { Column } from '$lib/helpers/types'; +import { writable } from 'svelte/store'; + +export const columns = writable([ + { id: '$id', title: 'Subscriber ID', type: 'string', show: true, width: 140 }, + { id: 'userName', title: 'Name', type: 'string', show: true, width: 100 }, + { id: 'targetId', title: 'Target ID', type: 'string', show: true, width: 140 }, + { id: 'target', title: 'Target', type: 'string', show: true, width: 140 }, + { id: 'type', title: 'Type', type: 'string', show: true, width: 80 }, + { id: '$createdAt', title: 'Created', type: 'string', show: true, width: 100 } +]); diff --git a/src/routes/console/project-[project]/messaging/topics/topic-[topic]/subscribers/table.svelte b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/subscribers/table.svelte new file mode 100644 index 0000000000..13fbbf7f0a --- /dev/null +++ b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/subscribers/table.svelte @@ -0,0 +1,191 @@ + + + + + d.$id)} /> + {#each $columns as column} + {#if column.show} + {column.title} + {/if} + {/each} + + + {#each data.subscribers.subscribers as subscriber (subscriber.$id)} + {@const target = subscriber.target} + + + + {#each $columns as column} + {#if column.show} + {#if column.id === '$id'} + {#key $columns} + + + {subscriber.$id} + + + {/key} + {:else if column.id === 'targetId'} + + + {subscriber[column.id]} + + + {:else if column.id === 'target'} + + {#if target.providerType === ProviderTypes.Push} + {target.name} + {:else} + {target.identifier} + {/if} + + {:else if column.id === 'type'} + + + + {:else if column.id === '$createdAt'} + + {toLocaleDateTime(subscriber[column.id])} + + {:else} + + {subscriber[column.id]} + + {/if} + {/if} + {/each} + + {/each} + + + + 0}> +
+
+ {selectedIds.length} +

+ + {selectedIds.length > 1 ? 'subscribers' : 'subscriber'} + + selected +

+
+ +
+ + +
+
+
+ + +

+ Are you sure you want to delete {selectedIds.length} + {selectedIds.length > 1 ? 'subscribers' : 'subscriber'}? +

+ + + + +
diff --git a/src/routes/console/project-[project]/messaging/topics/topic-[topic]/updateDescription.svelte b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/updateDescription.svelte new file mode 100644 index 0000000000..137e7944c1 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/updateDescription.svelte @@ -0,0 +1,65 @@ + + +
+ + Description + + +
    + +
+
+ + + + +
+ diff --git a/src/routes/console/project-[project]/messaging/topics/topic-[topic]/updateName.svelte b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/updateName.svelte new file mode 100644 index 0000000000..dfc6dd1af4 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/updateName.svelte @@ -0,0 +1,66 @@ + + +
+ + Name + + +
    + +
+
+ + + + +
+ diff --git a/src/routes/console/project-[project]/messaging/topicsModal.svelte b/src/routes/console/project-[project]/messaging/topicsModal.svelte new file mode 100644 index 0000000000..f1141b26e0 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/topicsModal.svelte @@ -0,0 +1,167 @@ + + + +

Select existing topics you want to send this message to its recipients.

+ + {#if Object.keys(topicResultsById).length > 0} + {#each Object.entries(topicResultsById) as [topicId, topic]} + onTopicSelection(event, topic)}> + + + + {topic.name} + ({topic.total} subscribers) + + + + {/each} +
+

Total results: {totalResults}

+ +
+ {:else if search} + +
+
+ Sorry we couldn't find "{search}" +

There are no topics that match your search.

+
+
+ + +
+
+
+ {:else} + +
+
+

+ You have no topics. Create a topic to see them here. +

+ +

+ Need a hand? Learn more in our + documentation. +

+
+
+
+ {/if} + + + + +
diff --git a/src/routes/console/project-[project]/messaging/userTargetsModal.svelte b/src/routes/console/project-[project]/messaging/userTargetsModal.svelte index fad9a00226..878e77a277 100644 --- a/src/routes/console/project-[project]/messaging/userTargetsModal.svelte +++ b/src/routes/console/project-[project]/messaging/userTargetsModal.svelte @@ -1,16 +1,3 @@ - - @@ -40,12 +55,20 @@ Select users to whom this message should be directed. - {#if targetIdsLength == 0} + {#if targetIdsLength === 0 && topicIdsLength === 0}
- + + +
Select recipients to get started
@@ -59,6 +82,32 @@ + {#each Object.entries($topicsById) as [topicId, topic] (topicId)} + + +
+ + + {topic.name} + ({topic.total} subscribers) + +
+
+ +
+ +
+
+
+ {/each} {#each Object.entries($targetsById) as [targetId, target] (targetId)} @@ -84,15 +133,17 @@
- + + + {/if} - - diff --git a/src/routes/console/project-[project]/messaging/wizard/store.ts b/src/routes/console/project-[project]/messaging/wizard/store.ts index df3fecdcec..3b02644524 100644 --- a/src/routes/console/project-[project]/messaging/wizard/store.ts +++ b/src/routes/console/project-[project]/messaging/wizard/store.ts @@ -1,6 +1,6 @@ import { ProviderTypes } from '../providerType.svelte'; -import type { Target } from '../userTargetsModal.svelte'; import { writable } from 'svelte/store'; +import type { Target } from '../store'; export enum MessageStatuses { DRAFT = 'draft',