diff --git a/package.json b/package.json index ba7717f02..c608c667c 100644 --- a/package.json +++ b/package.json @@ -12,9 +12,9 @@ "check:watch": "svelte-check --tsconfig ./tsconfig.json --watch", "lint": "prettier --check . && eslint .", "format": "prettier --write .", - "test": "vitest run", - "test:ui": "vitest --ui", - "test:watch": "vitest watch", + "test": "TZ=EST vitest run", + "test:ui": "TZ=EST vitest --ui", + "test:watch": "TZ=EST vitest watch", "e2e": "playwright test tests/e2e" }, "dependencies": { diff --git a/src/lib/helpers/date.ts b/src/lib/helpers/date.ts index c8aaf0fc8..d0802c9cc 100644 --- a/src/lib/helpers/date.ts +++ b/src/lib/helpers/date.ts @@ -41,6 +41,38 @@ export const toLocaleDateTime = (datetime: string | number) => { return date.toLocaleDateString('en', options); }; +/** + * Returns a date string usig the local timezone in ISO format (yyyy-mm-dd) + * + * @param datetime date string or milliseconds since the epoch + */ +export const toLocaleDateISO = (datetime: string | number) => { + const date = new Date(datetime); + + if (isNaN(date.getTime())) { + return 'n/a'; + } + + // Use Sweden's locale (sv) since it matches ISO format + return date.toLocaleDateString('sv'); +}; + +/** + * Returns a time string usig the local timezone in ISO format (hh:mm:ss) + * + * @param datetime date string or milliseconds since the epoch + */ +export const toLocaleTimeISO = (datetime: string | number) => { + const date = new Date(datetime); + + if (isNaN(date.getTime())) { + return 'n/a'; + } + + // Use Sweden's locale (sv) since it matches ISO format + return date.toLocaleTimeString('sv'); +}; + export const isSameDay = (date1: Date, date2: Date) => { return ( date1.getFullYear() === date2.getFullYear() && diff --git a/src/routes/console/project-[project]/messaging/wizard.svelte b/src/routes/console/project-[project]/messaging/create.svelte similarity index 54% rename from src/routes/console/project-[project]/messaging/wizard.svelte rename to src/routes/console/project-[project]/messaging/create.svelte index 9ee98b32c..e1f5d15bf 100644 --- a/src/routes/console/project-[project]/messaging/wizard.svelte +++ b/src/routes/console/project-[project]/messaging/create.svelte @@ -7,13 +7,12 @@ import { sdk } from '$lib/stores/sdk'; import { Submit, trackError, trackEvent } from '$lib/actions/analytics'; import { addNotification } from '$lib/stores/notifications'; - import { goto, invalidate } from '$app/navigation'; + import { goto } from '$app/navigation'; import { base } from '$app/paths'; import { project } from '../store'; import { wizard } from '$lib/stores/wizard'; - import { providerType, messageParams, operation } from './wizard/store'; + import { providerType, messageParams } from './wizard/store'; import { ID, MessagingProviderType, type Models } from '@appwrite.io/console'; - import { Dependencies } from '$lib/constants'; async function create() { try { @@ -111,114 +110,9 @@ } } - async function update() { - try { - let response: Models.Message; - - const messageId = $messageParams[$providerType].messageId; - - const params = $messageParams[$providerType]; - - console.log(params); - - switch ($providerType) { - case MessagingProviderType.Email: - response = await sdk.forProject.messaging.updateEmail( - messageId, - $messageParams[$providerType].topics, - $messageParams[$providerType].users, - $messageParams[$providerType].targets, - $messageParams[$providerType].subject, - $messageParams[$providerType].content, - $messageParams[$providerType].draft, - $messageParams[$providerType].html, - undefined, - undefined, - $messageParams[$providerType].scheduledAt - ); - break; - case MessagingProviderType.Sms: - response = await sdk.forProject.messaging.updateSms( - messageId, - $messageParams[$providerType].topics, - $messageParams[$providerType].users, - $messageParams[$providerType].targets, - $messageParams[$providerType].content, - $messageParams[$providerType].draft, - $messageParams[$providerType].scheduledAt - ); - break; - case MessagingProviderType.Push: - { - const customData: Record = {}; - const { data } = $messageParams[MessagingProviderType.Push]; - if (data && data.length > 0) { - data.forEach((item) => { - if (item[0] === '') return; - customData[item[0]] = item[1]; - }); - } - - response = await sdk.forProject.messaging.updatePush( - messageId, - $messageParams[$providerType].topics, - $messageParams[$providerType].users, - $messageParams[$providerType].targets, - $messageParams[$providerType].title, - $messageParams[$providerType].body, - customData, - undefined, - undefined, - undefined, - undefined, - undefined, - undefined, - undefined, - $messageParams[$providerType].draft, - $messageParams[$providerType].scheduledAt - ); - } - break; - } - wizard.hide(); - let message = ''; - switch (response.status) { - case 'draft': - message = 'The message has been saved as draft.'; - break; - case 'processing': - message = 'The message is queued for processing.'; - break; - case 'scheduled': - message = 'The message has been scheduled.'; - break; - } - addNotification({ - type: 'success', - message - }); - await invalidate(Dependencies.MESSAGING_MESSAGE); - trackEvent(Submit.MessagingMessageUpdate, { - providerType: $providerType, - status: response.status - }); - await goto(`${base}/console/project-${$project.$id}/messaging/message-${response.$id}`); - } catch (error) { - addNotification({ - type: 'error', - message: error.message - }); - trackError(error, Submit.MessagingMessageUpdate); - } - } - async function saveDraft() { $messageParams[$providerType].draft = true; - if ($operation === 'create') { - create(); - } else { - update(); - } + create(); } const stepsComponents: WizardStepsType = new Map(); @@ -254,8 +148,4 @@ }); - + diff --git a/src/routes/console/project-[project]/messaging/createMessageDropdown.svelte b/src/routes/console/project-[project]/messaging/createMessageDropdown.svelte index f35e08683..4e23952a0 100644 --- a/src/routes/console/project-[project]/messaging/createMessageDropdown.svelte +++ b/src/routes/console/project-[project]/messaging/createMessageDropdown.svelte @@ -3,8 +3,8 @@ import { Button } from '$lib/elements/forms'; import { wizard } from '$lib/stores/wizard'; import { providers } from './providers/store'; - import Wizard from './wizard.svelte'; - import { messageParams, operation, providerType, targetsById } from './wizard/store'; + import Create from './create.svelte'; + import { messageParams, providerType, targetsById } from './wizard/store'; import { topicsById } from './store'; import { MessagingProviderType } from '@appwrite.io/console'; @@ -30,7 +30,6 @@ ) return; $providerType = type; - $operation = 'create'; $topicsById = {}; $targetsById = {}; const common = { @@ -62,7 +61,7 @@ break; } showCreateDropdown = false; - wizard.start(Wizard); + wizard.start(Create); }}> {option.name} diff --git a/src/routes/console/project-[project]/messaging/message-[message]/+page.svelte b/src/routes/console/project-[project]/messaging/message-[message]/+page.svelte index 0f24f99f8..878c47ffd 100644 --- a/src/routes/console/project-[project]/messaging/message-[message]/+page.svelte +++ b/src/routes/console/project-[project]/messaging/message-[message]/+page.svelte @@ -1,111 +1,39 @@ - + {#if $message.providerType === MessagingProviderType.Email} - + {:else if $message.providerType === MessagingProviderType.Sms} - + {:else if $message.providerType === MessagingProviderType.Push} - + {/if} - - + + {#if $message.status !== 'processing'} {/if} diff --git a/src/routes/console/project-[project]/messaging/message-[message]/cancelModal.svelte b/src/routes/console/project-[project]/messaging/message-[message]/cancelModal.svelte new file mode 100644 index 000000000..39802b18d --- /dev/null +++ b/src/routes/console/project-[project]/messaging/message-[message]/cancelModal.svelte @@ -0,0 +1,95 @@ + + + +
+

+ Are you sure you want to cancel the scheduling of {message.data.title ?? + message.data.subject ?? + message.data.content ?? + 'Message'}? +

+
+ + + +
diff --git a/src/routes/console/project-[project]/messaging/message-[message]/emailMessage.svelte b/src/routes/console/project-[project]/messaging/message-[message]/emailMessage.svelte new file mode 100644 index 000000000..6fcaad6d4 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/message-[message]/emailMessage.svelte @@ -0,0 +1,93 @@ + + +
+ +
+ Message +
+ + + + + + + Enable the HTML mode if your message contains HTML tags. + + + + + + + +
+
diff --git a/src/routes/console/project-[project]/messaging/message-[message]/emailPreview.svelte b/src/routes/console/project-[project]/messaging/message-[message]/emailPreview.svelte deleted file mode 100644 index c6d5e051d..000000000 --- a/src/routes/console/project-[project]/messaging/message-[message]/emailPreview.svelte +++ /dev/null @@ -1,33 +0,0 @@ - - - -
- Preview -
- - - - - - -
- -
-
-
-
diff --git a/src/routes/console/project-[project]/messaging/message-[message]/overview.svelte b/src/routes/console/project-[project]/messaging/message-[message]/overview.svelte index b9c95e2d8..c9bbe244f 100644 --- a/src/routes/console/project-[project]/messaging/message-[message]/overview.svelte +++ b/src/routes/console/project-[project]/messaging/message-[message]/overview.svelte @@ -1,64 +1,77 @@ - +
- - {providerType} + + + +
-

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

-

Scheduled at: {toLocaleDateTime(scheduledAt)}

+

Created: {toLocaleDateTime(message.$createdAt)}

+ {#if message.scheduledAt} +

Scheduled at: {toLocaleDateTime(message.scheduledAt)}

+ {/if} + {#if message.deliveredAt} +

Sent at: {toLocaleDateTime(message.deliveredAt)}

+ {/if}
- +
- + {#if message.status === 'draft'} +
+ + +
+ {:else if message.status === 'scheduled'} +
+ + +
+ {:else if message.status === 'failed'} + + {/if}
+ + + + + + diff --git a/src/routes/console/project-[project]/messaging/message-[message]/pushMessage.svelte b/src/routes/console/project-[project]/messaging/message-[message]/pushMessage.svelte new file mode 100644 index 000000000..d35aa1131 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/message-[message]/pushMessage.svelte @@ -0,0 +1,180 @@ + + +
+ +
+ Message +
+ +
+
+ + + + + + + + +
+
    + {#each customData || [] as _, rowIndex} + + + + + + + + + {/each} +
+ {#if dataError} + {dataError} + {/if} + +
+ +
+
+ + + +
+ diff --git a/src/routes/console/project-[project]/messaging/message-[message]/pushPreview.svelte b/src/routes/console/project-[project]/messaging/message-[message]/pushPreview.svelte deleted file mode 100644 index eefb59c0a..000000000 --- a/src/routes/console/project-[project]/messaging/message-[message]/pushPreview.svelte +++ /dev/null @@ -1,33 +0,0 @@ - - - -
- Preview -
- -
-
- - - - - - -
- -
-
-
-
diff --git a/src/routes/console/project-[project]/messaging/message-[message]/scheduleModal.svelte b/src/routes/console/project-[project]/messaging/message-[message]/scheduleModal.svelte new file mode 100644 index 000000000..a8d749d2c --- /dev/null +++ b/src/routes/console/project-[project]/messaging/message-[message]/scheduleModal.svelte @@ -0,0 +1,138 @@ + + + +
+ +
+ + +
+
+ + {#if !dateTime || isNaN(dateTime.getTime())} + The message will be sent later + {:else} + The message will be sent at {dateTime.toLocaleString('en', formatOptions)} + {/if} + +
+ + + + +
diff --git a/src/routes/console/project-[project]/messaging/message-[message]/sendModal.svelte b/src/routes/console/project-[project]/messaging/message-[message]/sendModal.svelte new file mode 100644 index 000000000..fdfaa1d5c --- /dev/null +++ b/src/routes/console/project-[project]/messaging/message-[message]/sendModal.svelte @@ -0,0 +1,100 @@ + + + +
+

+ You are about to send a message to an estimated {totalTargets} targets. Would you like to proceed? +

+ +

This action is irreversible.

+
+ + + + +
diff --git a/src/routes/console/project-[project]/messaging/message-[message]/smsMessage.svelte b/src/routes/console/project-[project]/messaging/message-[message]/smsMessage.svelte new file mode 100644 index 000000000..d71353c40 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/message-[message]/smsMessage.svelte @@ -0,0 +1,68 @@ + + +
+ +
+ Message + +
+ + + + + + + + +
+
diff --git a/src/routes/console/project-[project]/messaging/message-[message]/smsPreview.svelte b/src/routes/console/project-[project]/messaging/message-[message]/smsPreview.svelte deleted file mode 100644 index 8e6e772bb..000000000 --- a/src/routes/console/project-[project]/messaging/message-[message]/smsPreview.svelte +++ /dev/null @@ -1,29 +0,0 @@ - - - -
- Preview - -
- - - - -
- -
-
-
-
diff --git a/src/routes/console/project-[project]/messaging/message-[message]/targets.svelte b/src/routes/console/project-[project]/messaging/message-[message]/targets.svelte deleted file mode 100644 index ca3e6ae03..000000000 --- a/src/routes/console/project-[project]/messaging/message-[message]/targets.svelte +++ /dev/null @@ -1,62 +0,0 @@ - - - - Targets - - {@const sum = targets.length} - {#if sum} -
- - - ID - Name - Identifier - - - {#each targets.slice(offset, offset + limit) as target (target.$id)} - - - {target.$id} - - - - {usersById[target.userId]?.name || 'Unknown'} - - - - {target.providerType === MessagingProviderType.Push - ? target.name - : target.identifier} - - - {/each} - -
-
-

Total targets: {sum}

- -
-
- {:else} - Edit the message to add a Target - {/if} -
-
diff --git a/src/routes/console/project-[project]/messaging/message-[message]/topics.svelte b/src/routes/console/project-[project]/messaging/message-[message]/topics.svelte deleted file mode 100644 index 1df5200aa..000000000 --- a/src/routes/console/project-[project]/messaging/message-[message]/topics.svelte +++ /dev/null @@ -1,59 +0,0 @@ - - - - Topics - - {@const sum = topics.length} - {#if sum} -
- - - ID - Name - Subscribers - - - {#each topics.slice(offset, offset + limit) as topic (topic.$id)} - - - {topic.$id} - - - - {topic.name} - - - - {topic.smsTotal + topic.emailTotal + topic.pushTotal} - - - {/each} - -
-
-

Total topics: {sum}

- -
-
- {:else} - Edit the message to add a Topic - {/if} -
-
diff --git a/src/routes/console/project-[project]/messaging/message-[message]/updateTargets.svelte b/src/routes/console/project-[project]/messaging/message-[message]/updateTargets.svelte new file mode 100644 index 000000000..8c112fba9 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/message-[message]/updateTargets.svelte @@ -0,0 +1,208 @@ + + +
+ + Targets + + {@const sum = targetIds.length} + {#if sum} +
+
+ Target +
+ {#if message.status == 'draft'} + + {/if} +
+
+ + + + + + + + {#each targets.slice(offset, offset + limit) as target (target.$id)} + + +
+ + + + {#if target.providerType === MessagingProviderType.Push} + {target.name} + {:else} + {target.identifier} + {/if} + + +
+
+ + {#if message.status === 'draft'} +
+ +
+ {/if} +
+
+ {/each} +
+
+
+

Total targets: {sum}

+ +
+
+ {:else if message.status == 'draft'} + (showTargets = true)}>Add a target + {:else} + +
+ No targets have been selected. +

+ Need a hand? Check out our . +

+
+
+ {/if} +
+ + + +
+
+ + { + showTargets = false; + targetsById = e.detail; + }}> + Select existing targets to which you want to send this message. + diff --git a/src/routes/console/project-[project]/messaging/message-[message]/updateTopics.svelte b/src/routes/console/project-[project]/messaging/message-[message]/updateTopics.svelte new file mode 100644 index 000000000..be240b2d1 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/message-[message]/updateTopics.svelte @@ -0,0 +1,189 @@ + + +
+ + Topics + + {@const sum = topicIds.length} + {#if sum} +
+
+ Topic +
+ {#if message.status == 'draft'} + + {/if} +
+
+ + + + + + + {#each topics.slice(offset, offset + limit) as topic (topic.$id)} + + +
+ + + + {topic.name} + + + ({getTotal(topic)} targets) + + + +
+
+ + {#if message.status === 'draft'} +
+ +
+ {/if} +
+
+ {/each} +
+
+
+

Total topics: {sum}

+ +
+
+ {:else if message.status == 'draft'} + (showTopics = true)}>Add a topic + {:else} + +
+ No topics have been selected. +

+ Need a hand? Check out our . +

+
+
+ {/if} +
+ + + +
+
+ + { + showTopics = false; + topicsById = e.detail; + }} /> diff --git a/src/routes/console/project-[project]/messaging/wizard/emailFormList.svelte b/src/routes/console/project-[project]/messaging/wizard/emailFormList.svelte index 3de535a53..ca25f281c 100644 --- a/src/routes/console/project-[project]/messaging/wizard/emailFormList.svelte +++ b/src/routes/console/project-[project]/messaging/wizard/emailFormList.svelte @@ -1,5 +1,5 @@ - + Schedule Schedule the time you want to deliver this message. Learn more in our