From a3e5f7ba128179732a97a3d205e921f64c1aedfe Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Tue, 19 Dec 2023 11:29:53 +0000 Subject: [PATCH 001/403] feat: add sessions scope --- src/lib/constants.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/lib/constants.ts b/src/lib/constants.ts index a2107d03c..377df669d 100644 --- a/src/lib/constants.ts +++ b/src/lib/constants.ts @@ -60,6 +60,11 @@ export const scopes: { description: "Access to create, update, and delete your project's users", category: 'Auth' }, + { + scope: 'sessions', + description: "Access to create and read your project's user sessions", + category: 'Auth' + }, { scope: 'teams.read', description: "Access to read your project's teams", From 40ae318dd4bc31d47bb0ba9cbe1ff3c63a5d3a2d Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Tue, 19 Dec 2023 14:02:09 +0000 Subject: [PATCH 002/403] feat: account scope --- src/lib/constants.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/lib/constants.ts b/src/lib/constants.ts index 377df669d..0a4d5372d 100644 --- a/src/lib/constants.ts +++ b/src/lib/constants.ts @@ -62,7 +62,12 @@ export const scopes: { }, { scope: 'sessions', - description: "Access to create and read your project's user sessions", + description: "Access to create sessions as one of your project's users", + category: 'Auth' + }, + { + scope: 'account', + description: "Access to perform actions as one of your project's users", category: 'Auth' }, { From 76d64cddc04ebf25ba033e211698ecba6ff09347 Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Mon, 16 Oct 2023 15:02:20 -0700 Subject: [PATCH 003/403] Add messaging to navigation --- src/lib/layout/navigation.svelte | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/lib/layout/navigation.svelte b/src/lib/layout/navigation.svelte index 8d5eb201d..d0797059b 100644 --- a/src/lib/layout/navigation.svelte +++ b/src/lib/layout/navigation.svelte @@ -123,6 +123,23 @@ Functions +
  • + trackEvent('click_menu_messaging')} + href={`${projectPath}/messaging`} + use:tooltip={{ + content: 'Messaging', + placement: 'right', + disabled: !narrow + }}> + +
  • Date: Tue, 17 Oct 2023 17:16:39 -0700 Subject: [PATCH 004/403] Add new messaging provider icons --- static/icons/dark/color/firebase.svg | 6 ++++++ static/icons/dark/color/mailgun.svg | 3 +++ static/icons/dark/color/mqtt.svg | 3 +++ static/icons/dark/color/msg91.svg | 4 ++++ static/icons/dark/color/sendgrid.svg | 18 ++++++++++++++++++ static/icons/dark/color/telesign.svg | 5 +++++ static/icons/dark/color/textmagic.svg | 7 +++++++ static/icons/dark/color/twilio.svg | 3 +++ static/icons/dark/color/vonage.svg | 4 ++++ static/icons/dark/grayscale/firebase.svg | 3 +++ static/icons/dark/grayscale/mailgun.svg | 3 +++ static/icons/dark/grayscale/mqtt.svg | 3 +++ static/icons/dark/grayscale/msg91.svg | 3 +++ static/icons/dark/grayscale/sendgrid.svg | 18 ++++++++++++++++++ static/icons/dark/grayscale/telesign.svg | 5 +++++ static/icons/dark/grayscale/textmagic.svg | 3 +++ static/icons/dark/grayscale/twilio.svg | 3 +++ static/icons/dark/grayscale/vonage.svg | 4 ++++ static/icons/light/color/firebase.svg | 6 ++++++ static/icons/light/color/mailgun.svg | 3 +++ static/icons/light/color/mqtt.svg | 3 +++ static/icons/light/color/msg91.svg | 4 ++++ static/icons/light/color/sendgrid.svg | 18 ++++++++++++++++++ static/icons/light/color/telesign.svg | 5 +++++ static/icons/light/color/textmagic.svg | 7 +++++++ static/icons/light/color/twilio.svg | 3 +++ static/icons/light/color/vonage.svg | 4 ++++ static/icons/light/grayscale/firebase.svg | 3 +++ static/icons/light/grayscale/mailgun.svg | 3 +++ static/icons/light/grayscale/mqtt.svg | 3 +++ static/icons/light/grayscale/msg91.svg | 3 +++ static/icons/light/grayscale/sendgrid.svg | 18 ++++++++++++++++++ static/icons/light/grayscale/telesign.svg | 5 +++++ static/icons/light/grayscale/textmagic.svg | 3 +++ static/icons/light/grayscale/twilio.svg | 3 +++ static/icons/light/grayscale/vonage.svg | 4 ++++ 36 files changed, 196 insertions(+) create mode 100644 static/icons/dark/color/firebase.svg create mode 100644 static/icons/dark/color/mailgun.svg create mode 100644 static/icons/dark/color/mqtt.svg create mode 100644 static/icons/dark/color/msg91.svg create mode 100644 static/icons/dark/color/sendgrid.svg create mode 100644 static/icons/dark/color/telesign.svg create mode 100644 static/icons/dark/color/textmagic.svg create mode 100644 static/icons/dark/color/twilio.svg create mode 100644 static/icons/dark/color/vonage.svg create mode 100644 static/icons/dark/grayscale/firebase.svg create mode 100644 static/icons/dark/grayscale/mailgun.svg create mode 100644 static/icons/dark/grayscale/mqtt.svg create mode 100644 static/icons/dark/grayscale/msg91.svg create mode 100644 static/icons/dark/grayscale/sendgrid.svg create mode 100644 static/icons/dark/grayscale/telesign.svg create mode 100644 static/icons/dark/grayscale/textmagic.svg create mode 100644 static/icons/dark/grayscale/twilio.svg create mode 100644 static/icons/dark/grayscale/vonage.svg create mode 100644 static/icons/light/color/firebase.svg create mode 100644 static/icons/light/color/mailgun.svg create mode 100644 static/icons/light/color/mqtt.svg create mode 100644 static/icons/light/color/msg91.svg create mode 100644 static/icons/light/color/sendgrid.svg create mode 100644 static/icons/light/color/telesign.svg create mode 100644 static/icons/light/color/textmagic.svg create mode 100644 static/icons/light/color/twilio.svg create mode 100644 static/icons/light/color/vonage.svg create mode 100644 static/icons/light/grayscale/firebase.svg create mode 100644 static/icons/light/grayscale/mailgun.svg create mode 100644 static/icons/light/grayscale/mqtt.svg create mode 100644 static/icons/light/grayscale/msg91.svg create mode 100644 static/icons/light/grayscale/sendgrid.svg create mode 100644 static/icons/light/grayscale/telesign.svg create mode 100644 static/icons/light/grayscale/textmagic.svg create mode 100644 static/icons/light/grayscale/twilio.svg create mode 100644 static/icons/light/grayscale/vonage.svg diff --git a/static/icons/dark/color/firebase.svg b/static/icons/dark/color/firebase.svg new file mode 100644 index 000000000..2016d2483 --- /dev/null +++ b/static/icons/dark/color/firebase.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/static/icons/dark/color/mailgun.svg b/static/icons/dark/color/mailgun.svg new file mode 100644 index 000000000..eb456be0a --- /dev/null +++ b/static/icons/dark/color/mailgun.svg @@ -0,0 +1,3 @@ + + + diff --git a/static/icons/dark/color/mqtt.svg b/static/icons/dark/color/mqtt.svg new file mode 100644 index 000000000..0d966304c --- /dev/null +++ b/static/icons/dark/color/mqtt.svg @@ -0,0 +1,3 @@ + + + diff --git a/static/icons/dark/color/msg91.svg b/static/icons/dark/color/msg91.svg new file mode 100644 index 000000000..8e1743219 --- /dev/null +++ b/static/icons/dark/color/msg91.svg @@ -0,0 +1,4 @@ + + + + diff --git a/static/icons/dark/color/sendgrid.svg b/static/icons/dark/color/sendgrid.svg new file mode 100644 index 000000000..ea185b767 --- /dev/null +++ b/static/icons/dark/color/sendgrid.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/static/icons/dark/color/telesign.svg b/static/icons/dark/color/telesign.svg new file mode 100644 index 000000000..af90bab97 --- /dev/null +++ b/static/icons/dark/color/telesign.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/static/icons/dark/color/textmagic.svg b/static/icons/dark/color/textmagic.svg new file mode 100644 index 000000000..74def7e81 --- /dev/null +++ b/static/icons/dark/color/textmagic.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/static/icons/dark/color/twilio.svg b/static/icons/dark/color/twilio.svg new file mode 100644 index 000000000..866c3aa77 --- /dev/null +++ b/static/icons/dark/color/twilio.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/static/icons/dark/color/vonage.svg b/static/icons/dark/color/vonage.svg new file mode 100644 index 000000000..76c7c330b --- /dev/null +++ b/static/icons/dark/color/vonage.svg @@ -0,0 +1,4 @@ + + + + diff --git a/static/icons/dark/grayscale/firebase.svg b/static/icons/dark/grayscale/firebase.svg new file mode 100644 index 000000000..e1158a544 --- /dev/null +++ b/static/icons/dark/grayscale/firebase.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/static/icons/dark/grayscale/mailgun.svg b/static/icons/dark/grayscale/mailgun.svg new file mode 100644 index 000000000..7f7b7a5a1 --- /dev/null +++ b/static/icons/dark/grayscale/mailgun.svg @@ -0,0 +1,3 @@ + + + diff --git a/static/icons/dark/grayscale/mqtt.svg b/static/icons/dark/grayscale/mqtt.svg new file mode 100644 index 000000000..d2189eeb4 --- /dev/null +++ b/static/icons/dark/grayscale/mqtt.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/static/icons/dark/grayscale/msg91.svg b/static/icons/dark/grayscale/msg91.svg new file mode 100644 index 000000000..321b9e02d --- /dev/null +++ b/static/icons/dark/grayscale/msg91.svg @@ -0,0 +1,3 @@ + + + diff --git a/static/icons/dark/grayscale/sendgrid.svg b/static/icons/dark/grayscale/sendgrid.svg new file mode 100644 index 000000000..cf1878874 --- /dev/null +++ b/static/icons/dark/grayscale/sendgrid.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/static/icons/dark/grayscale/telesign.svg b/static/icons/dark/grayscale/telesign.svg new file mode 100644 index 000000000..28816bd3c --- /dev/null +++ b/static/icons/dark/grayscale/telesign.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/static/icons/dark/grayscale/textmagic.svg b/static/icons/dark/grayscale/textmagic.svg new file mode 100644 index 000000000..1b11720a7 --- /dev/null +++ b/static/icons/dark/grayscale/textmagic.svg @@ -0,0 +1,3 @@ + + + diff --git a/static/icons/dark/grayscale/twilio.svg b/static/icons/dark/grayscale/twilio.svg new file mode 100644 index 000000000..055fcb079 --- /dev/null +++ b/static/icons/dark/grayscale/twilio.svg @@ -0,0 +1,3 @@ + + + diff --git a/static/icons/dark/grayscale/vonage.svg b/static/icons/dark/grayscale/vonage.svg new file mode 100644 index 000000000..4a790fce9 --- /dev/null +++ b/static/icons/dark/grayscale/vonage.svg @@ -0,0 +1,4 @@ + + + + diff --git a/static/icons/light/color/firebase.svg b/static/icons/light/color/firebase.svg new file mode 100644 index 000000000..d77c18648 --- /dev/null +++ b/static/icons/light/color/firebase.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/static/icons/light/color/mailgun.svg b/static/icons/light/color/mailgun.svg new file mode 100644 index 000000000..eb456be0a --- /dev/null +++ b/static/icons/light/color/mailgun.svg @@ -0,0 +1,3 @@ + + + diff --git a/static/icons/light/color/mqtt.svg b/static/icons/light/color/mqtt.svg new file mode 100644 index 000000000..f116bda13 --- /dev/null +++ b/static/icons/light/color/mqtt.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/static/icons/light/color/msg91.svg b/static/icons/light/color/msg91.svg new file mode 100644 index 000000000..8b660c473 --- /dev/null +++ b/static/icons/light/color/msg91.svg @@ -0,0 +1,4 @@ + + + + diff --git a/static/icons/light/color/sendgrid.svg b/static/icons/light/color/sendgrid.svg new file mode 100644 index 000000000..62fb7378b --- /dev/null +++ b/static/icons/light/color/sendgrid.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/static/icons/light/color/telesign.svg b/static/icons/light/color/telesign.svg new file mode 100644 index 000000000..86427534d --- /dev/null +++ b/static/icons/light/color/telesign.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/static/icons/light/color/textmagic.svg b/static/icons/light/color/textmagic.svg new file mode 100644 index 000000000..6bfc246c5 --- /dev/null +++ b/static/icons/light/color/textmagic.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/static/icons/light/color/twilio.svg b/static/icons/light/color/twilio.svg new file mode 100644 index 000000000..866c3aa77 --- /dev/null +++ b/static/icons/light/color/twilio.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/static/icons/light/color/vonage.svg b/static/icons/light/color/vonage.svg new file mode 100644 index 000000000..12a89b738 --- /dev/null +++ b/static/icons/light/color/vonage.svg @@ -0,0 +1,4 @@ + + + + diff --git a/static/icons/light/grayscale/firebase.svg b/static/icons/light/grayscale/firebase.svg new file mode 100644 index 000000000..e1158a544 --- /dev/null +++ b/static/icons/light/grayscale/firebase.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/static/icons/light/grayscale/mailgun.svg b/static/icons/light/grayscale/mailgun.svg new file mode 100644 index 000000000..7f7b7a5a1 --- /dev/null +++ b/static/icons/light/grayscale/mailgun.svg @@ -0,0 +1,3 @@ + + + diff --git a/static/icons/light/grayscale/mqtt.svg b/static/icons/light/grayscale/mqtt.svg new file mode 100644 index 000000000..d2189eeb4 --- /dev/null +++ b/static/icons/light/grayscale/mqtt.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/static/icons/light/grayscale/msg91.svg b/static/icons/light/grayscale/msg91.svg new file mode 100644 index 000000000..321b9e02d --- /dev/null +++ b/static/icons/light/grayscale/msg91.svg @@ -0,0 +1,3 @@ + + + diff --git a/static/icons/light/grayscale/sendgrid.svg b/static/icons/light/grayscale/sendgrid.svg new file mode 100644 index 000000000..189d454d0 --- /dev/null +++ b/static/icons/light/grayscale/sendgrid.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/static/icons/light/grayscale/telesign.svg b/static/icons/light/grayscale/telesign.svg new file mode 100644 index 000000000..4bd48f242 --- /dev/null +++ b/static/icons/light/grayscale/telesign.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/static/icons/light/grayscale/textmagic.svg b/static/icons/light/grayscale/textmagic.svg new file mode 100644 index 000000000..cc3ac7245 --- /dev/null +++ b/static/icons/light/grayscale/textmagic.svg @@ -0,0 +1,3 @@ + + + diff --git a/static/icons/light/grayscale/twilio.svg b/static/icons/light/grayscale/twilio.svg new file mode 100644 index 000000000..055fcb079 --- /dev/null +++ b/static/icons/light/grayscale/twilio.svg @@ -0,0 +1,3 @@ + + + diff --git a/static/icons/light/grayscale/vonage.svg b/static/icons/light/grayscale/vonage.svg new file mode 100644 index 000000000..4379fc950 --- /dev/null +++ b/static/icons/light/grayscale/vonage.svg @@ -0,0 +1,4 @@ + + + + From 9f3c3b176f5ded80425e82a2cfe3f30cbd8e3812 Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Tue, 28 Nov 2023 20:04:39 -0800 Subject: [PATCH 005/403] Update oauth providers key since it was changed in the backend --- src/lib/stores/oauth-providers.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lib/stores/oauth-providers.ts b/src/lib/stores/oauth-providers.ts index c5752e8ac..9e84290f1 100644 --- a/src/lib/stores/oauth-providers.ts +++ b/src/lib/stores/oauth-providers.ts @@ -24,7 +24,9 @@ export type Providers = { const setProviders = (project: Models.Project): Provider[] => { return ( - project?.providers.map((n) => { + // TODO: Remove @ts-expect-error when SDK is updated + // @ts-expect-error SDK needs to be updated + project?.oAuthProviders.map((n) => { const p = n as Models.Provider & { key: string }; let docs: Provider['docs']; let icon: Provider['icon'] = p.key.toLowerCase(); From ade620c9a5b30d12eef8e202e0564f3373e70f37 Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Tue, 19 Dec 2023 16:13:47 -0800 Subject: [PATCH 006/403] Temporarily fix undefined billing limit Since the 1.5.x branch hasn't been updated with the billing changes, this change adds a fallback so that the console still functions. --- src/lib/layout/containerHeader.svelte | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/lib/layout/containerHeader.svelte b/src/lib/layout/containerHeader.svelte index 08a7813f1..4c348b81a 100644 --- a/src/lib/layout/containerHeader.svelte +++ b/src/lib/layout/containerHeader.svelte @@ -34,8 +34,15 @@ let showDropdown = false; + // TODO: remove the default billing limits when backend is updated with billing code const { bandwidth, documents, storage, users, executions } = ($organization ?? {}) - .billingLimits; + .billingLimits ?? { + bandwidth: 1, + documents: 1, + storage: 1, + users: 1, + executions: 1 + }; const limitedServices = [ { name: 'bandwidth', value: bandwidth }, { name: 'documents', value: documents }, From a99082e4a5bb431a6d54a109f59a2cd80e50f5ee Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Fri, 20 Oct 2023 11:53:16 -0700 Subject: [PATCH 007/403] Add messaging overview route --- src/lib/commandCenter/commands.ts | 1 + .../messaging/+layout.svelte | 62 +++++ .../project-[project]/messaging/+layout.ts | 10 + .../project-[project]/messaging/+page.svelte | 229 +++++++++++++++++ .../project-[project]/messaging/+page.ts | 72 ++++++ .../messaging/breadcrumbs.svelte | 22 ++ .../project-[project]/messaging/create.svelte | 73 ++++++ .../messaging/failedModal.svelte | 21 ++ .../project-[project]/messaging/header.svelte | 44 ++++ .../messaging/messageStatusPill.svelte | 20 ++ .../messaging/provider.svelte | 96 +++++++ .../messaging/providerType.svelte | 59 +++++ .../project-[project]/messaging/store.ts | 240 ++++++++++++++++++ 13 files changed, 949 insertions(+) create mode 100644 src/routes/console/project-[project]/messaging/+layout.svelte create mode 100644 src/routes/console/project-[project]/messaging/+layout.ts create mode 100644 src/routes/console/project-[project]/messaging/+page.svelte create mode 100644 src/routes/console/project-[project]/messaging/+page.ts create mode 100644 src/routes/console/project-[project]/messaging/breadcrumbs.svelte create mode 100644 src/routes/console/project-[project]/messaging/create.svelte create mode 100644 src/routes/console/project-[project]/messaging/failedModal.svelte create mode 100644 src/routes/console/project-[project]/messaging/header.svelte create mode 100644 src/routes/console/project-[project]/messaging/messageStatusPill.svelte create mode 100644 src/routes/console/project-[project]/messaging/provider.svelte create mode 100644 src/routes/console/project-[project]/messaging/providerType.svelte create mode 100644 src/routes/console/project-[project]/messaging/store.ts diff --git a/src/lib/commandCenter/commands.ts b/src/lib/commandCenter/commands.ts index f12bbe2ed..470a61012 100644 --- a/src/lib/commandCenter/commands.ts +++ b/src/lib/commandCenter/commands.ts @@ -17,6 +17,7 @@ const groups = [ 'platforms', 'databases', 'functions', + 'messaging', 'storage', 'domains', 'webhooks', diff --git a/src/routes/console/project-[project]/messaging/+layout.svelte b/src/routes/console/project-[project]/messaging/+layout.svelte new file mode 100644 index 000000000..2b8b30178 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/+layout.svelte @@ -0,0 +1,62 @@ + + + + Messaging - Appwrite + + + diff --git a/src/routes/console/project-[project]/messaging/+layout.ts b/src/routes/console/project-[project]/messaging/+layout.ts new file mode 100644 index 000000000..7db345058 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/+layout.ts @@ -0,0 +1,10 @@ +import Breadcrumbs from './breadcrumbs.svelte'; +import Header from './header.svelte'; +import type { LayoutLoad } from './$types'; + +export const load: LayoutLoad = async () => { + return { + header: Header, + breadcrumbs: Breadcrumbs + }; +}; diff --git a/src/routes/console/project-[project]/messaging/+page.svelte b/src/routes/console/project-[project]/messaging/+page.svelte new file mode 100644 index 000000000..f2b675613 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/+page.svelte @@ -0,0 +1,229 @@ + + + +
    +
    + Messages +
    + +
    +
    + + +
    + + + + +
    +
    +
    +
    + + +
    +
    + + +
    +
    +
    + + {#if data.messages.total} + + + d.$id)} /> + {#each $columns as column} + {#if column.show} + {column.title} + {/if} + {/each} + + + {#each data.messages.messages as message} + + + + {#each $columns as column (column.id)} + {#if column.show} + {#if column.id === '$id'} + {#key $columns} + + {message.$id} + + {/key} + {:else if column.id === 'message'} + + {#if message.providerType === ProviderTypes.Push} + {message.data.title} + {:else if message.providerType === ProviderTypes.Sms} + {message.data.content} + {:else if message.providerType === ProviderTypes.Email} + {message.data.subject} + {:else} + Invalid provider + {/if} + + {:else if column.id === 'providerType'} + + + + {:else if column.id === 'status'} + + { + e.preventDefault(); + errors = message.deliveryErrors; + showFailed = true; + }} /> + + {:else if column.type === 'datetime'} + + {#if !message[column.id]} + - + {:else} + {toLocaleDateTime(message[column.id])} + {/if} + + {:else} + + {message[column.id]} + + {/if} + {/if} + {/each} + + {/each} + + + + 0}> +
    +
    + {selected.length} +

    + + {selected.length > 1 ? 'messages' : 'message'} + + selected +

    +
    + +
    + + + +
    +
    +
    + + + + {:else if data.search && data.search != 'empty'} + +
    + Sorry, we couldn't find '{data.search}' +

    There are no messages that match your search.

    +
    +
    + + + +
    +
    + {:else} + + ($showCreate = true)} /> + {/if} +
    + + + + + diff --git a/src/routes/console/project-[project]/messaging/+page.ts b/src/routes/console/project-[project]/messaging/+page.ts new file mode 100644 index 000000000..25c1e1cb8 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/+page.ts @@ -0,0 +1,72 @@ +import { + View, + getLimit, + getPage, + getQuery, + getSearch, + getView, + pageToOffset +} from '$lib/helpers/load'; +import { CARD_LIMIT } from '$lib/constants'; +import type { PageLoad } from './$types'; +import { messages as data, providersById } from './store'; +import type { Message } from './store'; +import { Query } from '@appwrite.io/console'; +import { sdk } from '$lib/stores/sdk'; +import { queries, queryParamToMap } from '$lib/components/filters/store'; + +export const load: PageLoad = async ({ url, route }) => { + const page = getPage(url); + const search = getSearch(url); + const view = getView(url, route, View.Grid); + const limit = getLimit(url, route, CARD_LIMIT); + const offset = pageToOffset(page, limit); + const query = getQuery(url); + + const parsedQueries = queryParamToMap(query || '[]'); + queries.set(parsedQueries); + + // TODO: remove when the API is ready with data + // This allows us to mock w/ data and when search returns 0 results + let messages: { messages: Message[]; total: number } = { messages: [], total: 0 }; + if (search === 'demo') { + messages = data; + } else { + const params = { + queries: [ + Query.limit(limit), + Query.offset(offset), + Query.orderDesc(''), + ...parsedQueries.values() + ] + }; + + if (search) { + params['search'] = search; + } + + const response = await sdk.forProject.client.call( + 'GET', + new URL(sdk.forProject.client.config.endpoint + '/messaging/messages'), + { + 'X-Appwrite-Project': sdk.forProject.client.config.project, + 'content-type': 'application/json', + 'X-Appwrite-Mode': 'admin' + }, + params + ); + + messages = response; + } + + return { + offset, + limit, + search, + query, + page, + view, + messages, + providersById + }; +}; diff --git a/src/routes/console/project-[project]/messaging/breadcrumbs.svelte b/src/routes/console/project-[project]/messaging/breadcrumbs.svelte new file mode 100644 index 000000000..9e28bee67 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/breadcrumbs.svelte @@ -0,0 +1,22 @@ + + + diff --git a/src/routes/console/project-[project]/messaging/create.svelte b/src/routes/console/project-[project]/messaging/create.svelte new file mode 100644 index 000000000..49a81af91 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/create.svelte @@ -0,0 +1,73 @@ + + + + + + + {#if !showCustomId} +
    + (showCustomId = !showCustomId)}> + +
    + {:else} + + {/if} +
    + + + + +
    diff --git a/src/routes/console/project-[project]/messaging/failedModal.svelte b/src/routes/console/project-[project]/messaging/failedModal.svelte new file mode 100644 index 000000000..6ee183ffd --- /dev/null +++ b/src/routes/console/project-[project]/messaging/failedModal.svelte @@ -0,0 +1,21 @@ + + + +
    +

    Some messages failed to send.

    +
    + +
    +
    + + + + +
    diff --git a/src/routes/console/project-[project]/messaging/header.svelte b/src/routes/console/project-[project]/messaging/header.svelte new file mode 100644 index 000000000..9534915ab --- /dev/null +++ b/src/routes/console/project-[project]/messaging/header.svelte @@ -0,0 +1,44 @@ + + + + + Messaging + + + {#each tabs as tab} + + {tab.title} + + {/each} + + diff --git a/src/routes/console/project-[project]/messaging/messageStatusPill.svelte b/src/routes/console/project-[project]/messaging/messageStatusPill.svelte new file mode 100644 index 000000000..46b309abc --- /dev/null +++ b/src/routes/console/project-[project]/messaging/messageStatusPill.svelte @@ -0,0 +1,20 @@ + + + + {#if status === 'sent'} + + {:else if status === 'scheduled'} + + {/if} + + {status} + + diff --git a/src/routes/console/project-[project]/messaging/provider.svelte b/src/routes/console/project-[project]/messaging/provider.svelte new file mode 100644 index 000000000..5e2da923a --- /dev/null +++ b/src/routes/console/project-[project]/messaging/provider.svelte @@ -0,0 +1,96 @@ + + + + +{#if icon === ''} + Invalid provider +{:else} +
    + {#if !noIcon} +
    + {displayName} +
    + {/if} + + {displayName} + +
    +{/if} diff --git a/src/routes/console/project-[project]/messaging/providerType.svelte b/src/routes/console/project-[project]/messaging/providerType.svelte new file mode 100644 index 000000000..b7db1514f --- /dev/null +++ b/src/routes/console/project-[project]/messaging/providerType.svelte @@ -0,0 +1,59 @@ + + + + +{#if text === ''} + Invalid provider type +{:else} +
    + {#if !noIcon} +
    +
    + {/if} + + {text} + +
    +{/if} diff --git a/src/routes/console/project-[project]/messaging/store.ts b/src/routes/console/project-[project]/messaging/store.ts new file mode 100644 index 000000000..6a08966c0 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/store.ts @@ -0,0 +1,240 @@ +import type { Column } from '$lib/helpers/types'; +import { Providers } from './provider.svelte'; +import { ProviderTypes } from './providerType.svelte'; +import { writable } from 'svelte/store'; + +export const showCreate = writable(false); + +export const columns = writable([ + { id: '$id', title: 'Message ID', type: 'string', show: true, width: 140 }, + { id: 'description', title: 'Description', type: 'string', show: true, width: 140 }, + { id: 'message', title: 'Message', type: 'string', show: false, width: 140 }, + { id: 'providerType', title: 'Type', type: 'string', show: true, width: 100 }, + { id: 'status', title: 'Status', type: 'string', show: true, width: 120 }, + { id: 'scheduledAt', title: 'Scheduled at', type: 'datetime', show: true, width: 120 }, + { id: 'deliveredAt', title: 'Delivered at', type: 'datetime', show: false, width: 120 } +]); + +// TODO: remove this when the SDK and API are ready +export type Message = { + $id: string; + $createdAt: string; + $updatedAt: string; + topics: string[]; + users: string[]; + targets: string[]; + scheduledAt: string; + deliveredAt: string; + deliveryErrors: string[]; + deliveredTo: number; + status: string; + providerType: ProviderTypes; + description: string; + data: { + content?: string; + body?: string; + subject?: string; + title?: string; + }; +}; + +// TODO: remove this when the SDK and API are ready +export const messages: { messages: Message[]; total: number } = { + messages: [ + { + $id: '637a40ba7a703e3936e1', + $createdAt: '2021-08-31T12:00:00.000Z', + $updatedAt: '2021-08-31T12:00:00.000Z', + description: 'Welcome', + providerType: ProviderTypes.Push, + topics: [], + users: ['user-1', 'user-2'], + targets: [], + scheduledAt: '2021-03-01T00:00:00.000Z', + deliveredAt: '2021-03-01T00:00:00.000Z', + deliveryErrors: [], + deliveredTo: 2, + status: 'sent', + data: { + title: 'Welcome to the Cloud', + body: 'Detailed body' + } + }, + { + $id: '637a40ba7a703e3936e2', + $createdAt: '2021-08-31T12:00:00.000Z', + $updatedAt: '2021-08-31T12:00:00.000Z', + description: 'Public beta announcement', + providerType: ProviderTypes.Sms, + topics: [], + users: ['user-1', 'user-2'], + targets: [], + scheduledAt: '2021-03-01T00:00:00.000Z', + deliveredAt: '2021-03-01T00:00:00.000Z', + deliveryErrors: [], + deliveredTo: 2, + status: 'scheduled', + data: { + content: 'Cloud is live on public beta' + } + }, + { + $id: '637a40ba7a703e3936e3', + $createdAt: '2021-08-31T12:00:00.000Z', + $updatedAt: '2021-08-31T12:00:00.000Z', + description: 'Welcome', + providerType: ProviderTypes.Email, + topics: [], + users: ['user-1', 'user-2'], + targets: [], + scheduledAt: '', + deliveredAt: '', + deliveryErrors: [], + deliveredTo: 2, + status: 'draft', + data: { + subject: 'Welcome to the Cloud', + content: 'Detailed content' + } + } + ], + total: 3 +}; + +// TODO: remove this when the SDK and API are ready +export type Provider = { + $id: string; + $createdAt: string; + $updatedAt: string; + name: string; + provider: Providers; + default: boolean; + enabled: boolean; + type: ProviderTypes; + credentials: object; + options: object; +}; + +// TODO: remove this when the SDK and API are ready +export const providersById: { [providerId: string]: Provider } = { + '637a40ba7a703e3936e1': { + $id: '637a40ba7a703e3936e1', + $createdAt: '2021-08-31T12:00:00.000Z', + $updatedAt: '2021-08-31T12:00:00.000Z', + name: 'My Firebase', + provider: Providers.FCM, + type: ProviderTypes.Push, + default: false, + enabled: true, + credentials: {}, + options: {} + }, + '637a40ba7a703e3936e2': { + $id: '637a40ba7a703e3936e2', + $createdAt: '2021-08-31T12:00:00.000Z', + $updatedAt: '2021-08-31T12:00:00.000Z', + name: 'My APNS', + provider: Providers.APNS, + type: ProviderTypes.Push, + default: false, + enabled: false, + credentials: {}, + options: {} + }, + '637a40ba7a703e3936e3': { + $id: '637a40ba7a703e3936e3', + $createdAt: '2021-08-31T12:00:00.000Z', + $updatedAt: '2021-08-31T12:00:00.000Z', + name: 'My MQTT', + provider: Providers.MQTT, + type: ProviderTypes.Push, + default: false, + enabled: false, + credentials: {}, + options: {} + }, + '637a40ba7a703e3936e4': { + $id: '637a40ba7a703e3936e4', + $createdAt: '2021-08-31T12:00:00.000Z', + $updatedAt: '2021-08-31T12:00:00.000Z', + name: 'My Sendgrid', + provider: Providers.Sendgrid, + type: ProviderTypes.Email, + default: false, + enabled: false, + credentials: {}, + options: {} + }, + '637a40ba7a703e3936e5': { + $id: '637a40ba7a703e3936e5', + $createdAt: '2021-08-31T12:00:00.000Z', + $updatedAt: '2021-08-31T12:00:00.000Z', + name: 'My Mailgun', + provider: Providers.Mailgun, + type: ProviderTypes.Email, + default: false, + enabled: false, + credentials: {}, + options: {} + }, + '637a40ba7a703e3936e6': { + $id: '637a40ba7a703e3936e6', + $createdAt: '2021-08-31T12:00:00.000Z', + $updatedAt: '2021-08-31T12:00:00.000Z', + name: 'My Telesign', + provider: Providers.Telesign, + type: ProviderTypes.Sms, + default: false, + enabled: false, + credentials: {}, + options: {} + }, + '637a40ba7a703e3936e7': { + $id: '637a40ba7a703e3936e7', + $createdAt: '2021-08-31T12:00:00.000Z', + $updatedAt: '2021-08-31T12:00:00.000Z', + name: 'My Msg91', + provider: Providers.Msg91, + type: ProviderTypes.Sms, + default: false, + enabled: false, + credentials: {}, + options: {} + }, + '637a40ba7a703e3936e8': { + $id: '637a40ba7a703e3936e8', + $createdAt: '2021-08-31T12:00:00.000Z', + $updatedAt: '2021-08-31T12:00:00.000Z', + name: 'My Textmagic', + provider: Providers.Textmagic, + type: ProviderTypes.Sms, + default: false, + enabled: false, + credentials: {}, + options: {} + }, + '637a40ba7a703e3936e9': { + $id: '637a40ba7a703e3936e9', + $createdAt: '2021-08-31T12:00:00.000Z', + $updatedAt: '2021-08-31T12:00:00.000Z', + name: 'My Vonage', + provider: Providers.Vonage, + type: ProviderTypes.Sms, + default: false, + enabled: false, + credentials: {}, + options: {} + }, + '637a40ba7a703e3936f0': { + $id: '637a40ba7a703e3936f0', + $createdAt: '2021-08-31T12:00:00.000Z', + $updatedAt: '2021-08-31T12:00:00.000Z', + name: 'My Twilio', + provider: Providers.Twilio, + type: ProviderTypes.Sms, + default: false, + enabled: false, + credentials: {}, + options: {} + } +}; From 7532b8e36f52ea3f39b1954ffed747eadca9a996 Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Mon, 20 Nov 2023 13:51:23 -0800 Subject: [PATCH 008/403] Update input elments to support popovers --- src/lib/components/drop.svelte | 7 ++++++- src/lib/elements/forms/inputDomain.svelte | 23 +++++++++++++++++++++- src/lib/elements/forms/inputEmail.svelte | 23 +++++++++++++++++++++- src/lib/elements/forms/inputFile.svelte | 24 +++++++++++++++++++++-- src/lib/elements/forms/inputText.svelte | 23 +++++++++++++++++++++- 5 files changed, 94 insertions(+), 6 deletions(-) diff --git a/src/lib/components/drop.svelte b/src/lib/components/drop.svelte index d6c899df2..f61ff6a24 100644 --- a/src/lib/components/drop.svelte +++ b/src/lib/components/drop.svelte @@ -13,6 +13,7 @@ export let noStyle = false; export let fullWidth = false; export let fixed = false; + export let display = 'block'; const dispatch = createEventDispatcher<{ blur: undefined; @@ -100,7 +101,11 @@ -
    +
    diff --git a/src/lib/elements/forms/inputDomain.svelte b/src/lib/elements/forms/inputDomain.svelte index 58f066199..5445b2ccb 100644 --- a/src/lib/elements/forms/inputDomain.svelte +++ b/src/lib/elements/forms/inputDomain.svelte @@ -1,6 +1,7 @@ + + +
    +
    + Providers +
    + +
    +
    + + +
    + + + +
    +
    +
    +
    + + +
    +
    + + +
    +
    +
    + {#if data.providers.total} + + + d.$id)} /> + {#each $columns as column} + {#if column.show} + {column.title} + {/if} + {/each} + + + {#each data.providers.providers as provider (provider.$id)} + + + {#each $columns as column} + {#if column.show} + {#if column.id === '$id'} + {#key $columns} + + {provider.$id} + + {/key} + {:else if column.id === 'provider'} + + + + {:else if column.id === 'type'} + + + + {:else if column.id === 'enabled'} + + + {#if provider.enabled} + + {/if} + + {provider.enabled ? 'enabled' : 'disabled'} + + + + {:else} + + {provider[column.id]} + + {/if} + {/if} + {/each} + + {/each} + + + + + {:else if data.search} + +
    + Sorry, we couldn't find '{data.search}' +

    There are no providers that match your search.

    +
    + +
    + {:else} + + + {/if} +
    + + diff --git a/src/routes/console/project-[project]/messaging/providers/+page.ts b/src/routes/console/project-[project]/messaging/providers/+page.ts new file mode 100644 index 000000000..ac98e7a7c --- /dev/null +++ b/src/routes/console/project-[project]/messaging/providers/+page.ts @@ -0,0 +1,75 @@ +import { Query } from '@appwrite.io/console'; +import { sdk } from '$lib/stores/sdk'; +import { + View, + getLimit, + getPage, + getQuery, + getSearch, + getView, + pageToOffset +} from '$lib/helpers/load'; +import { PAGE_LIMIT } from '$lib/constants'; +import { providersById, type Provider } from '../store'; +import { queries, queryParamToMap } from '$lib/components/filters/store'; + +const providers = Object.values(providersById); + +let data: { providers: Provider[]; total: number } = { + providers: [...providers], + total: providers.length +}; + +export const load = async ({ url, route }) => { + const page = getPage(url); + const search = getSearch(url); + const view = getView(url, route, View.Grid); + const limit = getLimit(url, route, PAGE_LIMIT); + const offset = pageToOffset(page, limit); + const query = getQuery(url); + + const parsedQueries = queryParamToMap(query || '[]'); + queries.set(parsedQueries); + + // TODO: get rid of demo data + let providers: { providers: Provider[]; total: number } = { providers: [], total: 0 }; + if (search == 'demo') { + providers = data; + } else { + const params = { + queries: [ + Query.limit(limit), + Query.offset(offset), + Query.orderDesc(''), + ...parsedQueries.values() + ] + }; + + if (search) { + params['search'] = search; + } + + const response = await sdk.forProject.client.call( + 'GET', + new URL(sdk.forProject.client.config.endpoint + '/messaging/providers'), + { + 'X-Appwrite-Project': sdk.forProject.client.config.project, + 'content-type': 'application/json', + 'X-Appwrite-Mode': 'admin' + }, + params + ); + + providers = response; + } + + return { + offset, + limit, + search, + query, + page, + view, + providers: providers + }; +}; diff --git a/src/routes/console/project-[project]/messaging/providers/create.svelte b/src/routes/console/project-[project]/messaging/providers/create.svelte new file mode 100644 index 000000000..65528f2c0 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/providers/create.svelte @@ -0,0 +1,68 @@ + + + + + + {#if !showCustomId} +
    + (showCustomId = !showCustomId)} + > +
    + {:else} + + {/if} +
    + + + + +
    diff --git a/src/routes/console/project-[project]/messaging/providers/store.ts b/src/routes/console/project-[project]/messaging/providers/store.ts new file mode 100644 index 000000000..290483e9e --- /dev/null +++ b/src/routes/console/project-[project]/messaging/providers/store.ts @@ -0,0 +1,12 @@ +import { writable } from 'svelte/store'; +import type { Column } from '$lib/helpers/types'; + +export let showCreate = writable(false); + +export const columns = writable([ + { id: '$id', title: 'Provider ID', type: 'string', show: true }, + { id: 'name', title: 'Name', type: 'string', show: true }, + { id: 'provider', title: 'Provider', type: 'string', show: true }, + { id: 'type', title: 'Type', type: 'string', show: true }, + { id: 'enabled', title: 'Status', type: 'boolean', show: true } +]); From 16cc91893a16255ae2b6f37d03a044f88a324573 Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Wed, 25 Oct 2023 17:00:47 -0700 Subject: [PATCH 010/403] Add wizard for creating provider --- src/lib/actions/analytics.ts | 5 +- src/lib/components/labelCard.svelte | 10 + .../messaging/providers/+page.svelte | 59 +-- .../messaging/providers/+page.ts | 2 +- .../messaging/providers/create.svelte | 316 ++++++++++++--- .../providers/createProviderDropdown.svelte | 49 +++ .../messaging/providers/store.ts | 369 ++++++++++++++++++ .../providers/wizard/configure.svelte | 133 +++++++ .../providers/wizard/provider.svelte | 161 ++++++++ .../messaging/providers/wizard/store.ts | 103 +++++ static/images/apns-bundle-id.png | Bin 0 -> 42772 bytes 11 files changed, 1128 insertions(+), 79 deletions(-) create mode 100644 src/routes/console/project-[project]/messaging/providers/createProviderDropdown.svelte create mode 100644 src/routes/console/project-[project]/messaging/providers/wizard/configure.svelte create mode 100644 src/routes/console/project-[project]/messaging/providers/wizard/provider.svelte create mode 100644 src/routes/console/project-[project]/messaging/providers/wizard/store.ts create mode 100644 static/images/apns-bundle-id.png diff --git a/src/lib/actions/analytics.ts b/src/lib/actions/analytics.ts index 8a15993fc..2b7145796 100644 --- a/src/lib/actions/analytics.ts +++ b/src/lib/actions/analytics.ts @@ -287,5 +287,8 @@ export enum Submit { SmsResetTemplate = 'submit_sms_reset_template', SmsUpdateInviteTemplate = 'submit_sms_update_invite_template', SmsUpdateLoginTemplate = 'submit_sms_update_login_template', - SmsUpdateVerificationTemplate = 'submit_sms_update_verification_template' + SmsUpdateVerificationTemplate = 'submit_sms_update_verification_template', + MessagingProviderCreate = 'submit_messaging_provider_create', + MessagingProviderDelete = 'submit_messaging_provider_delete', + MessagingProviderUpdate = 'submit_messaging_provider_update' } diff --git a/src/lib/components/labelCard.svelte b/src/lib/components/labelCard.svelte index 9d30f9b0c..461e5a53f 100644 --- a/src/lib/components/labelCard.svelte +++ b/src/lib/components/labelCard.svelte @@ -1,5 +1,7 @@ @@ -47,10 +46,7 @@
    Providers
    - +
    @@ -63,10 +59,7 @@ hideView allowNoColumns showColsTextMobile /> - +
    {#if data.providers.total} - - - d.$id)} /> - {#each $columns as column} - {#if column.show} - {column.title} - {/if} - {/each} - - - {#each data.providers.providers as provider (provider.$id)} - - - {#each $columns as column} - {#if column.show} - {#if column.id === '$id'} - {#key $columns} - - {provider.$id} - - {/key} - {:else if column.id === 'provider'} - - - - {:else if column.id === 'type'} - - - - {:else if column.id === 'enabled'} - - - {#if provider.enabled} - - {/if} - - {provider.enabled ? 'enabled' : 'disabled'} - - - - {:else} - - {provider[column.id]} - - {/if} - {/if} - {/each} - - {/each} - - + { +export const load = async ({ depends, url, route }) => { + depends(Dependencies.MESSAGING_PROVIDERS); + const page = getPage(url); const search = getSearch(url); const view = getView(url, route, View.Grid); diff --git a/src/routes/console/project-[project]/messaging/providers/table.svelte b/src/routes/console/project-[project]/messaging/providers/table.svelte new file mode 100644 index 000000000..2921c40ec --- /dev/null +++ b/src/routes/console/project-[project]/messaging/providers/table.svelte @@ -0,0 +1,170 @@ + + + + + d.$id)} /> + {#each $columns as column} + {#if column.show} + {column.title} + {/if} + {/each} + + + {#each data.providers.providers as provider (provider.$id)} + + + {#each $columns as column} + {#if column.show} + {#if column.id === '$id'} + {#key $columns} + + {provider.$id} + + {/key} + {:else if column.id === 'provider'} + + + + {:else if column.id === 'type'} + + + + {:else if column.id === 'enabled'} + + + {#if provider.enabled} + + {/if} + + {provider.enabled ? 'enabled' : 'disabled'} + + + + {:else} + + {provider[column.id]} + + {/if} + {/if} + {/each} + + {/each} + + + + 0}> +
    +
    + {selectedIds.length} +

    + + {selectedIds.length > 1 ? 'providers' : 'provider'} + + selected +

    +
    + +
    + + +
    +
    +
    + + +

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

    + + + + +
    From 37a5d11bdaf2721671bc040434318e3304c3be50 Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Tue, 28 Nov 2023 08:44:12 -0800 Subject: [PATCH 014/403] Update InputCheckbox to properly show label and description --- src/lib/elements/forms/inputCheckbox.svelte | 46 ++++++++++----------- 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/src/lib/elements/forms/inputCheckbox.svelte b/src/lib/elements/forms/inputCheckbox.svelte index 4aaf52c6b..0493d3f0b 100644 --- a/src/lib/elements/forms/inputCheckbox.svelte +++ b/src/lib/elements/forms/inputCheckbox.svelte @@ -1,13 +1,10 @@ - {#if label} - - {/if} - -
    - -
    + {#if error} {error} {/if} From cd7e82453eb5a7a3b87e5d38031d62ea3bcb0761 Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Tue, 28 Nov 2023 08:48:36 -0800 Subject: [PATCH 015/403] Update InputRadio to properly show label and description --- src/lib/elements/forms/inputRadio.svelte | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/lib/elements/forms/inputRadio.svelte b/src/lib/elements/forms/inputRadio.svelte index cb3db08ce..a5803fa34 100644 --- a/src/lib/elements/forms/inputRadio.svelte +++ b/src/lib/elements/forms/inputRadio.svelte @@ -3,12 +3,14 @@ export let label: string = null; export let showLabel = true; + // export let label: string; export let id: string; export let group: string; export let value: string; export let name: string; export let required = false; export let disabled = false; + export let fullWidth = false; let element: HTMLInputElement; let error: string; @@ -47,6 +49,24 @@ {/if} + {#if error} {error} From 5ef5986be4cd86418077f6b811fa3537484fc2dc Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Tue, 28 Nov 2023 16:42:09 -0800 Subject: [PATCH 016/403] Create InputDate for only dates --- src/lib/elements/forms/inputDate.svelte | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/lib/elements/forms/inputDate.svelte b/src/lib/elements/forms/inputDate.svelte index a49aa3c4e..380abe279 100644 --- a/src/lib/elements/forms/inputDate.svelte +++ b/src/lib/elements/forms/inputDate.svelte @@ -10,6 +10,8 @@ export let value = ''; export let required = false; export let nullable = false; + export let min: string | number | undefined = undefined; + export let max: string | number | undefined = undefined; export let disabled = false; export let readonly = false; export let autofocus = false; @@ -65,6 +67,8 @@ {readonly} {required} step=".001" + {min} + {max} autocomplete={autocomplete ? 'on' : 'off'} type="date" class="input-text" From 26707526d8eac17798008fc13ba1c10ebb4b5082 Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Tue, 28 Nov 2023 16:42:28 -0800 Subject: [PATCH 017/403] Create InputTime for only times --- src/lib/elements/forms/index.ts | 1 + src/lib/elements/forms/inputTime.svelte | 67 +++++++++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 src/lib/elements/forms/inputTime.svelte diff --git a/src/lib/elements/forms/index.ts b/src/lib/elements/forms/index.ts index 22f3688a2..9858ae0c1 100644 --- a/src/lib/elements/forms/index.ts +++ b/src/lib/elements/forms/index.ts @@ -29,3 +29,4 @@ export { default as Label } from './label.svelte'; export { default as InputProjectId } from './inputProjectId.svelte'; export { default as InputDate } from './inputDate.svelte'; export { default as InputDateRange } from './inputDateRange.svelte'; +export { default as InputTime } from './inputTime.svelte'; diff --git a/src/lib/elements/forms/inputTime.svelte b/src/lib/elements/forms/inputTime.svelte new file mode 100644 index 000000000..bc30b8745 --- /dev/null +++ b/src/lib/elements/forms/inputTime.svelte @@ -0,0 +1,67 @@ + + + + + +
    + +
    + {#if error} + {error} + {/if} +
    From 8b953d4ccd68a840813d9421a78a58da27df1f7d Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Wed, 29 Nov 2023 22:12:20 -0800 Subject: [PATCH 018/403] Add a modal for selecting user targets --- .../messaging/userTargetsModal.svelte | 260 ++++++++++++++++++ 1 file changed, 260 insertions(+) create mode 100644 src/routes/console/project-[project]/messaging/userTargetsModal.svelte diff --git a/src/routes/console/project-[project]/messaging/userTargetsModal.svelte b/src/routes/console/project-[project]/messaging/userTargetsModal.svelte new file mode 100644 index 000000000..3d9b4311c --- /dev/null +++ b/src/routes/console/project-[project]/messaging/userTargetsModal.svelte @@ -0,0 +1,260 @@ + + + + + +

    Grant access to any authenticated or anonymous user.

    + + {#if Object.keys(userResultsById).length > 0} + + {#each Object.entries(userResultsById) as [userId, user]} + {@const selectedCount = user.targets.filter( + (target) => selected[target.$id] + ).length} + + + 0 && + user.targets.every((target) => targetsById[target.$id])} + checked={selectedCount > 0 && selectedCount == user.targets.length} + on:change={(event) => onUserSelection(event, userId)} /> + + + + + {#if user.name} + {user.name} + {:else if user.email} + {user.email} + {:else if user.phone} + {user.phone} + {:else} + {userId} + {/if} + + + + + ({selectedCount} targets) + + + {#each user.targets as target} +
    + onTargetSelection(event, target)}> + +
    + + {#if target.providerType !== ProviderTypes.Push} + {target.identifier} + {:else} + + {target.name} + {/if} +
    +
    +
    +
    + {/each} +
    +
    + {/each} +
    +
    +

    Total results: {totalResults}

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

    There are no Users that match your search.

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

    + You have no users. Create a user to see them here. +

    +

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

    +
    +
    +
    + {/if} + + + + +
    From 96dc9612c87f565bbe5eda8fd9c01569b45cc892 Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Tue, 28 Nov 2023 16:43:37 -0800 Subject: [PATCH 019/403] Create a wizard to send email messages --- src/lib/actions/analytics.ts | 3 +- .../project-[project]/messaging/+page.svelte | 58 ++++--- .../project-[project]/messaging/create.svelte | 158 +++++++++++------- .../messaging/createMessageDropdown.svelte | 67 ++++++++ .../messaging/userTargetsModal.svelte | 8 +- .../messaging/wizard/emailFormList.svelte | 145 ++++++++++++++++ .../messaging/wizard/step1.svelte | 20 +++ .../messaging/wizard/step2.svelte | 99 +++++++++++ .../messaging/wizard/step3.svelte | 101 +++++++++++ .../messaging/wizard/store.ts | 52 ++++++ 10 files changed, 626 insertions(+), 85 deletions(-) create mode 100644 src/routes/console/project-[project]/messaging/createMessageDropdown.svelte create mode 100644 src/routes/console/project-[project]/messaging/wizard/emailFormList.svelte create mode 100644 src/routes/console/project-[project]/messaging/wizard/step1.svelte create mode 100644 src/routes/console/project-[project]/messaging/wizard/step2.svelte create mode 100644 src/routes/console/project-[project]/messaging/wizard/step3.svelte create mode 100644 src/routes/console/project-[project]/messaging/wizard/store.ts diff --git a/src/lib/actions/analytics.ts b/src/lib/actions/analytics.ts index 2b7145796..d985c85b7 100644 --- a/src/lib/actions/analytics.ts +++ b/src/lib/actions/analytics.ts @@ -290,5 +290,6 @@ export enum Submit { SmsUpdateVerificationTemplate = 'submit_sms_update_verification_template', MessagingProviderCreate = 'submit_messaging_provider_create', MessagingProviderDelete = 'submit_messaging_provider_delete', - MessagingProviderUpdate = 'submit_messaging_provider_update' + MessagingProviderUpdate = 'submit_messaging_provider_update', + MessagingMessageCreate = 'submit_messaging_message_create' } diff --git a/src/routes/console/project-[project]/messaging/+page.svelte b/src/routes/console/project-[project]/messaging/+page.svelte index f2b675613..cecbe8af5 100644 --- a/src/routes/console/project-[project]/messaging/+page.svelte +++ b/src/routes/console/project-[project]/messaging/+page.svelte @@ -1,5 +1,4 @@ @@ -54,10 +50,7 @@
    Messages
    - +
    @@ -71,10 +64,7 @@ hideView allowNoColumns showColsTextMobile /> - +
    @@ -219,11 +209,35 @@ single href="https://appwrite.io/docs" target="message" - on:click={() => ($showCreate = true)} /> + on:click={() => ($showCreate = true)}> +
    + + Create your first message to get started. + +

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

    +
    +
    + + + + +
    + {/if} - - - diff --git a/src/routes/console/project-[project]/messaging/create.svelte b/src/routes/console/project-[project]/messaging/create.svelte index 49a81af91..3c9924a97 100644 --- a/src/routes/console/project-[project]/messaging/create.svelte +++ b/src/routes/console/project-[project]/messaging/create.svelte @@ -1,73 +1,111 @@ - - - - - {#if !showCustomId} -
    - (showCustomId = !showCustomId)}> - -
    - {:else} - - {/if} -
    - - - - -
    + diff --git a/src/routes/console/project-[project]/messaging/createMessageDropdown.svelte b/src/routes/console/project-[project]/messaging/createMessageDropdown.svelte new file mode 100644 index 000000000..48d69abfd --- /dev/null +++ b/src/routes/console/project-[project]/messaging/createMessageDropdown.svelte @@ -0,0 +1,67 @@ + + + + + + + + {#each Object.entries(providers) as [type, option]} + { + if ( + type !== ProviderTypes.Email && + type !== ProviderTypes.Sms && + type !== ProviderTypes.Push + ) + return; + $providerType = type; + $targetsById = {}; + const common = { + topics: [], + users: [], + targets: [] + }; + switch (type) { + case ProviderTypes.Email: + $messageParams[$providerType] = { + ...common, + subject: '', + content: '' + }; + break; + case ProviderTypes.Sms: + $messageParams[$providerType] = { + ...common, + content: '' + }; + break; + case ProviderTypes.Push: + $messageParams[$providerType] = { + ...common, + title: '', + body: '' + }; + break; + } + showCreateDropdown = false; + wizard.start(Create); + }}> + {option.name} + + {/each} + + diff --git a/src/routes/console/project-[project]/messaging/userTargetsModal.svelte b/src/routes/console/project-[project]/messaging/userTargetsModal.svelte index 3d9b4311c..fad9a0022 100644 --- a/src/routes/console/project-[project]/messaging/userTargetsModal.svelte +++ b/src/routes/console/project-[project]/messaging/userTargetsModal.svelte @@ -86,7 +86,9 @@ userResultsById = {}; response.users.forEach((user) => { if (providerType !== null) { - user.targets = user.targets.filter((target) => target.providerType === providerType); + user.targets = user.targets.filter( + (target) => target.providerType === providerType + ); } userResultsById = { ...userResultsById, @@ -200,7 +202,9 @@
    + > {#if target.providerType !== ProviderTypes.Push} {target.identifier} {:else} diff --git a/src/routes/console/project-[project]/messaging/wizard/emailFormList.svelte b/src/routes/console/project-[project]/messaging/wizard/emailFormList.svelte new file mode 100644 index 000000000..950c749f8 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/wizard/emailFormList.svelte @@ -0,0 +1,145 @@ + + + + + + + +
    + + + + + + + + + + Enter the email address to which te test message will be +
    (selected = 'other')} + on:keyup|self={clickOnEnter} + role="button" + tabindex="0"> + +
    +
    +
    + + + + + +
    +
    + + + Enable the HTML mode if your message contains HTML tags. + + + + + {#if !showCustomId} +
    + (showCustomId = !showCustomId)} + > +
    + {:else} + + {/if} +
    diff --git a/src/routes/console/project-[project]/messaging/wizard/step1.svelte b/src/routes/console/project-[project]/messaging/wizard/step1.svelte new file mode 100644 index 000000000..01c704873 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/wizard/step1.svelte @@ -0,0 +1,20 @@ + + + + Message + + + Create an {providers[$providerType].text} that will be displayed to your subscribers. Learn more + in our documentation. + + + diff --git a/src/routes/console/project-[project]/messaging/wizard/step2.svelte b/src/routes/console/project-[project]/messaging/wizard/step2.svelte new file mode 100644 index 000000000..60f734edf --- /dev/null +++ b/src/routes/console/project-[project]/messaging/wizard/step2.svelte @@ -0,0 +1,99 @@ + + + + Targets + + Select users to whom this message should be directed. + {#if targetIdsLength == 0} + +
    + +
    + Select recipients to get started +
    +
    +
    + {:else} +
    +
    + + Target + + + + {#each Object.entries($targetsById) as [targetId, target] (targetId)} + + +
    + {target.name ? target.name : target.identifier} +
    +
    + + +
    + +
    +
    +
    + {/each} +
    +
    + + + {/if} + + + diff --git a/src/routes/console/project-[project]/messaging/wizard/step3.svelte b/src/routes/console/project-[project]/messaging/wizard/step3.svelte new file mode 100644 index 000000000..4a62c75ef --- /dev/null +++ b/src/routes/console/project-[project]/messaging/wizard/step3.svelte @@ -0,0 +1,101 @@ + + + + Schedule + + Schedule the time you want your users to receive this message. Learn more in our + documentation. + +
    + + + +
    +
    + + {#if when === 'now'} + The message will be sent immediately + {:else 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/wizard/store.ts b/src/routes/console/project-[project]/messaging/wizard/store.ts new file mode 100644 index 000000000..6ec774cc8 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/wizard/store.ts @@ -0,0 +1,52 @@ +import { ProviderTypes } from '../providerType.svelte'; +import type { Target } from '../userTargetsModal.svelte'; +import { writable } from 'svelte/store'; + +export enum MessageStatuses { + DRAFT = 'draft', + PROCESSING = 'processing' +} + +export type MessageParams = { + messageId: string; + topics: string[]; + users: string[]; + targets: string[]; + description: string; + status: MessageStatuses; + scheduledAt?: string; +}; + +export type EmailMessageParams = MessageParams & { + subject: string; + content: string; + html: boolean; +}; + +export type SMSMessageParams = MessageParams & { + content: string; +}; + +export type PushMessageParams = MessageParams & { + title: string; + body: string; + data: Record; + action?: string; + icon?: string; + sound?: string; + color?: string; + tag?: string; + badge?: string; +}; + +export const providerType = writable(null); +export const targetsById = writable>({}); +export const messageParams = writable<{ + [ProviderTypes.Email]: Partial; + [ProviderTypes.Sms]: Partial; + [ProviderTypes.Push]: Partial; +}>({ + [ProviderTypes.Email]: null, + [ProviderTypes.Sms]: null, + [ProviderTypes.Push]: null +}); From fdb7dd1e9cf9838991641cf69bf6332bf542fd4c Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Wed, 29 Nov 2023 16:58:40 -0800 Subject: [PATCH 020/403] Add a message detail page for email messages --- src/lib/actions/analytics.ts | 3 +- src/lib/constants.ts | 3 +- .../message-[message]/+layout.svelte | 5 ++ .../messaging/message-[message]/+layout.ts | 33 +++++++++++ .../messaging/message-[message]/+page.svelte | 16 ++++++ .../message-[message]/breadcrumbs.svelte | 24 ++++++++ .../messaging/message-[message]/delete.svelte | 38 +++++++++++++ .../message-[message]/deleteModal.svelte | 56 +++++++++++++++++++ .../message-[message]/emailPreview.svelte | 33 +++++++++++ .../messaging/message-[message]/header.svelte | 17 ++++++ .../message-[message]/overview.svelte | 52 +++++++++++++++++ .../messaging/message-[message]/store.ts | 5 ++ .../messaging/providerType.svelte | 2 +- 13 files changed, 284 insertions(+), 3 deletions(-) create mode 100644 src/routes/console/project-[project]/messaging/message-[message]/+layout.svelte create mode 100644 src/routes/console/project-[project]/messaging/message-[message]/+layout.ts create mode 100644 src/routes/console/project-[project]/messaging/message-[message]/+page.svelte create mode 100644 src/routes/console/project-[project]/messaging/message-[message]/breadcrumbs.svelte create mode 100644 src/routes/console/project-[project]/messaging/message-[message]/delete.svelte create mode 100644 src/routes/console/project-[project]/messaging/message-[message]/deleteModal.svelte create mode 100644 src/routes/console/project-[project]/messaging/message-[message]/emailPreview.svelte create mode 100644 src/routes/console/project-[project]/messaging/message-[message]/header.svelte create mode 100644 src/routes/console/project-[project]/messaging/message-[message]/overview.svelte create mode 100644 src/routes/console/project-[project]/messaging/message-[message]/store.ts diff --git a/src/lib/actions/analytics.ts b/src/lib/actions/analytics.ts index d985c85b7..e9c127f9c 100644 --- a/src/lib/actions/analytics.ts +++ b/src/lib/actions/analytics.ts @@ -291,5 +291,6 @@ export enum Submit { MessagingProviderCreate = 'submit_messaging_provider_create', MessagingProviderDelete = 'submit_messaging_provider_delete', MessagingProviderUpdate = 'submit_messaging_provider_update', - MessagingMessageCreate = 'submit_messaging_message_create' + MessagingMessageCreate = 'submit_messaging_message_create', + MessagingMessageDelete = 'submit_messaging_message_delete' } diff --git a/src/lib/constants.ts b/src/lib/constants.ts index 33a02a160..c9868fdcd 100644 --- a/src/lib/constants.ts +++ b/src/lib/constants.ts @@ -48,7 +48,8 @@ export enum Dependencies { RUNTIMES = 'dependency:runtimes', CONSOLE_VARIABLES = 'dependency:console_variables', MESSAGING_PROVIDERS = 'dependency:messaging_providers', - MESSAGING_PROVIDER = 'dependency:messaging_provider' + MESSAGING_PROVIDER = 'dependency:messaging_provider', + MESSAGING_MESSAGE = 'dependency:messaging_message' } export const scopes: { diff --git a/src/routes/console/project-[project]/messaging/message-[message]/+layout.svelte b/src/routes/console/project-[project]/messaging/message-[message]/+layout.svelte new file mode 100644 index 000000000..9d2f6426e --- /dev/null +++ b/src/routes/console/project-[project]/messaging/message-[message]/+layout.svelte @@ -0,0 +1,5 @@ + + Message - Appwrite + + + diff --git a/src/routes/console/project-[project]/messaging/message-[message]/+layout.ts b/src/routes/console/project-[project]/messaging/message-[message]/+layout.ts new file mode 100644 index 000000000..21e6f6aad --- /dev/null +++ b/src/routes/console/project-[project]/messaging/message-[message]/+layout.ts @@ -0,0 +1,33 @@ +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'; +import type { Message } from '../store'; + +export const load: LayoutLoad = async ({ params, depends }) => { + depends(Dependencies.MESSAGING_MESSAGE); + + try { + const response: Message = await sdk.forProject.client.call( + 'GET', + new URL( + `${sdk.forProject.client.config.endpoint}/messaging/messages/${params.message}` + ), + { + 'X-Appwrite-Project': sdk.forProject.client.config.project, + 'content-type': 'application/json', + 'X-Appwrite-Mode': 'admin' + } + ); + + return { + header: Header, + breadcrumbs: Breadcrumbs, + message: response + }; + } catch (e) { + throw error(e.code, e.message); + } +}; diff --git a/src/routes/console/project-[project]/messaging/message-[message]/+page.svelte b/src/routes/console/project-[project]/messaging/message-[message]/+page.svelte new file mode 100644 index 000000000..1867a5dac --- /dev/null +++ b/src/routes/console/project-[project]/messaging/message-[message]/+page.svelte @@ -0,0 +1,16 @@ + + + + + {#if $message.providerType === ProviderTypes.Email} + + {/if} + + diff --git a/src/routes/console/project-[project]/messaging/message-[message]/breadcrumbs.svelte b/src/routes/console/project-[project]/messaging/message-[message]/breadcrumbs.svelte new file mode 100644 index 000000000..caf1d7778 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/message-[message]/breadcrumbs.svelte @@ -0,0 +1,24 @@ + + + diff --git a/src/routes/console/project-[project]/messaging/message-[message]/delete.svelte b/src/routes/console/project-[project]/messaging/message-[message]/delete.svelte new file mode 100644 index 000000000..7d7a2fb77 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/message-[message]/delete.svelte @@ -0,0 +1,38 @@ + + + + Delete message +

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

    + + + +
    + {$message.data.title ?? + $message.data.subject ?? + $message.data.content ?? + 'Message'} +
    +
    +

    + Last updated: {toLocaleDateTime($message.$updatedAt)} +

    +
    +
    + + + + +
    + + diff --git a/src/routes/console/project-[project]/messaging/message-[message]/deleteModal.svelte b/src/routes/console/project-[project]/messaging/message-[message]/deleteModal.svelte new file mode 100644 index 000000000..41988ae73 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/message-[message]/deleteModal.svelte @@ -0,0 +1,56 @@ + + + +

    Are you sure you want to delete this message?

    + + + + +
    diff --git a/src/routes/console/project-[project]/messaging/message-[message]/emailPreview.svelte b/src/routes/console/project-[project]/messaging/message-[message]/emailPreview.svelte new file mode 100644 index 000000000..153a14def --- /dev/null +++ b/src/routes/console/project-[project]/messaging/message-[message]/emailPreview.svelte @@ -0,0 +1,33 @@ + + + +
    + Preview +
    + + + + + + + + + + + + + +
    diff --git a/src/routes/console/project-[project]/messaging/message-[message]/header.svelte b/src/routes/console/project-[project]/messaging/message-[message]/header.svelte new file mode 100644 index 000000000..f97cc9e21 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/message-[message]/header.svelte @@ -0,0 +1,17 @@ + + + + + + {$message.data.title ?? $message.data.subject ?? $message.data.content ?? 'Message'} + + {$message.$id} + + diff --git a/src/routes/console/project-[project]/messaging/message-[message]/overview.svelte b/src/routes/console/project-[project]/messaging/message-[message]/overview.svelte new file mode 100644 index 000000000..9dfb7add3 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/message-[message]/overview.svelte @@ -0,0 +1,52 @@ + + + +
    + + {providerType} + +
    + +
    +
    +

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

    +

    Scheduled at: {toLocaleDateTime(scheduledAt)}

    +
    +
    + +
    +
    +
    + + + + + +
    diff --git a/src/routes/console/project-[project]/messaging/message-[message]/store.ts b/src/routes/console/project-[project]/messaging/message-[message]/store.ts new file mode 100644 index 000000000..97b3c1c5d --- /dev/null +++ b/src/routes/console/project-[project]/messaging/message-[message]/store.ts @@ -0,0 +1,5 @@ +import { derived } from 'svelte/store'; +import { page } from '$app/stores'; +import type { Message } from '../store'; + +export const message = derived(page, ($page) => $page.data.message as Message); diff --git a/src/routes/console/project-[project]/messaging/providerType.svelte b/src/routes/console/project-[project]/messaging/providerType.svelte index b7db1514f..d5e43f9f5 100644 --- a/src/routes/console/project-[project]/messaging/providerType.svelte +++ b/src/routes/console/project-[project]/messaging/providerType.svelte @@ -49,7 +49,7 @@ class="avatar" class:is-size-large={size === 'l'} class:is-size-small={size === 's'}> -
    @@ -147,7 +140,7 @@ limit={data.limit} offset={data.offset} total={data.providers.total} /> - {:else if data.search} + {:else if data.search && data.search != 'empty'}
    Sorry, we couldn't find '{data.search}' @@ -159,11 +152,33 @@ {:else} - + +
    + + Create your first provider to get started. + +

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

    +
    +
    + + + + +
    +
    {/if} - - diff --git a/src/routes/console/project-[project]/messaging/providers/+page.ts b/src/routes/console/project-[project]/messaging/providers/+page.ts index ac98e7a7c..b55c53ff0 100644 --- a/src/routes/console/project-[project]/messaging/providers/+page.ts +++ b/src/routes/console/project-[project]/messaging/providers/+page.ts @@ -70,6 +70,6 @@ export const load = async ({ url, route }) => { query, page, view, - providers: providers + providers }; }; diff --git a/src/routes/console/project-[project]/messaging/providers/create.svelte b/src/routes/console/project-[project]/messaging/providers/create.svelte index 65528f2c0..d828be10c 100644 --- a/src/routes/console/project-[project]/messaging/providers/create.svelte +++ b/src/routes/console/project-[project]/messaging/providers/create.svelte @@ -1,68 +1,274 @@ - - - - {#if !showCustomId} -
    - (showCustomId = !showCustomId)} - > -
    - {:else} - - {/if} -
    - - - - -
    + diff --git a/src/routes/console/project-[project]/messaging/providers/createProviderDropdown.svelte b/src/routes/console/project-[project]/messaging/providers/createProviderDropdown.svelte new file mode 100644 index 000000000..e829f4927 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/providers/createProviderDropdown.svelte @@ -0,0 +1,49 @@ + + + + + + + + {#each Object.entries(providers) as [type, option]} + { + if ( + type !== ProviderTypes.Email && + type !== ProviderTypes.Sms && + type !== ProviderTypes.Push + ) + return; + $providerType = type; + const p = Object.keys(providers[type].providers).shift(); + if (p && isValueOfStringEnum(Providers, p)) { + $provider = p; + } + showCreateDropdown = false; + wizard.start(Create); + }}> + {option.name} + + {/each} + + diff --git a/src/routes/console/project-[project]/messaging/providers/store.ts b/src/routes/console/project-[project]/messaging/providers/store.ts index 290483e9e..714db9d9a 100644 --- a/src/routes/console/project-[project]/messaging/providers/store.ts +++ b/src/routes/console/project-[project]/messaging/providers/store.ts @@ -1,5 +1,7 @@ import { writable } from 'svelte/store'; import type { Column } from '$lib/helpers/types'; +import { Providers } from '../provider.svelte'; +import { ProviderTypes } from '../providerType.svelte'; export let showCreate = writable(false); @@ -10,3 +12,370 @@ export const columns = writable([ { id: 'type', title: 'Type', type: 'string', show: true }, { id: 'enabled', title: 'Status', type: 'boolean', show: true } ]); + +type ProvidersMap = { + [key in ProviderTypes]: { + name: string; + text: string; + icon: string; + providers: { + [key in Providers]?: { + imageIcon: string; + title: string; + description: string; + configure: { + label: string; + name: string; + type: 'text' | 'phone' | 'email' | 'domain' | 'file' | 'switch'; + placeholder?: string; + description?: string; + popover?: string[]; + allowedFileExtensions?: string[]; + }[]; + }; + }; + }; +}; + +export const providers: ProvidersMap = { + [ProviderTypes.Sms]: { + name: 'SMS', + text: 'SMS', + icon: 'annotation', + providers: { + [Providers.Twilio]: { + imageIcon: 'twilio', + title: 'Twilio', + description: '', + configure: [ + { + label: 'Account SID', + name: 'accountSid', + type: 'text', + placeholder: 'Enter Account SID', + popover: [ + 'How to get the Account SID?', + 'Head to Twilio console -> Account info -> Account SID.' + ] + }, + { + label: 'Auth token', + name: 'authToken', + type: 'text', + placeholder: 'Enter Auth token', + popover: [ + 'How to get the Auth token?', + 'Head to Twilio console -> Account info -> Auth Token.' + ] + }, + { + label: 'Sender number', + name: 'from', + type: 'phone', + placeholder: 'Enter phone', + popover: [ + 'How to get sender number?', + 'Head to Twilio console -> Account info -> My Twilio phone number.', + 'If you have multiple Twilio phone numbers, you can select one as the default number.' + ] + } + ] + }, + [Providers.Msg91]: { + imageIcon: 'msg91', + title: 'MSG91', + description: '', + configure: [ + { + label: 'Auth key', + name: 'authKey', + type: 'text', + placeholder: 'Enter auth key', + popover: [ + 'How to get the Auth key?', + 'Create an account in MSG91.', + 'Click to open the Username dropdown -> Authkey -> Verify your mobile number -> Create Authkey.' + ] + }, + { + label: 'Sender ID', + name: 'senderId', + type: 'text', + placeholder: 'Enter sender ID', + popover: [ + 'How to create a Sender ID?', + 'Head to MSG91 dashboard -> SMS -> Sender ID -> Create sender ID.' + ] + }, + { + label: 'Sender number', + name: 'from', + type: 'phone', + placeholder: 'Enter phone' + } + ] + }, + [Providers.Telesign]: { + imageIcon: 'telesign', + title: 'Telesign', + description: '', + configure: [ + { + label: 'Username', + name: 'username', + type: 'text', + placeholder: 'Enter username' + }, + { + label: 'Password', + name: 'password', + type: 'text', + placeholder: 'Enter password' + }, + { + label: 'Sender number', + name: 'from', + type: 'phone', + placeholder: 'Enter phone' + } + ] + }, + [Providers.Textmagic]: { + imageIcon: 'textmagic', + title: 'Textmagic', + description: '', + configure: [ + { + label: 'API key', + name: 'apiKey', + type: 'text', + placeholder: 'Enter API key', + popover: [ + 'How to get the API key?', + 'Create an account in Textmagic.', + 'Head to TextMagic dashboard -> API Settings -> Add new API key.' + ] + }, + { + label: 'Username', + name: 'username', + type: 'text', + placeholder: 'Enter username' + }, + { + label: 'Sender number', + name: 'from', + type: 'phone', + placeholder: 'Enter phone' + } + ] + }, + [Providers.Vonage]: { + imageIcon: 'vonage', + title: 'Vonage', + description: '', + configure: [ + { + label: 'API key', + name: 'apiKey', + type: 'text', + placeholder: 'Enter API key', + popover: [ + 'How to get the API key?', + 'Create an account in Vonage.', + 'Head to Vonage dashboard and copy the API key.' + ] + }, + { + label: 'API secret', + name: 'apiSecret', + type: 'text', + placeholder: 'Enter API secret', + popover: [ + 'How to get the API secret?', + 'Head to Vonage dashboard and copy the API secret.' + ] + }, + { + label: 'Sender number', + name: 'from', + type: 'phone', + placeholder: 'Enter phone' + } + ] + } + } + }, + [ProviderTypes.Email]: { + name: 'Email', + text: 'emails', + icon: 'mail', + providers: { + [Providers.Mailgun]: { + imageIcon: 'mailgun', + title: 'Mailgun', + description: '', + configure: [ + { + label: 'API key', + name: 'apiKey', + type: 'text', + placeholder: 'Enter API key', + popover: [ + 'How to get the API key?', + 'Create an account in Mailgun.', + 'Head to Profile -> API Security -> Add new key.' + ] + }, + { + label: 'Domain', + name: 'domain', + type: 'domain', + placeholder: 'Enter domain', + popover: [ + 'How to create a domain?', + 'Head to Sending -> Domains -> Add new domain.', + 'Follow Mailgun instructions to verify the domain name.' + ] + }, + { + label: 'EU region', + name: 'isEuRegion', + type: 'switch', + description: + 'Enable the EU region setting if your domain is within the European Union.' + }, + { + label: 'Sender email', + name: 'from', + type: 'email', + placeholder: 'Enter email' + } + ] + }, + [Providers.Sendgrid]: { + imageIcon: 'sendgrid', + title: 'Sendgrid', + description: '', + configure: [ + { + label: 'API key', + name: 'apiKey', + type: 'text', + placeholder: 'Enter API key', + popover: [ + 'How to get the API key?', + 'Create an account in Mailgun.', + 'Head to Profile -> API Security -> Add new key.' + ] + }, + { + label: 'Sender email', + name: 'from', + type: 'email', + placeholder: 'Enter email' + } + ] + } + } + }, + [ProviderTypes.Push]: { + name: 'Push notification', + text: 'notifications', + icon: 'device-mobile', + providers: { + [Providers.FCM]: { + imageIcon: 'firebase', + title: 'FCM', + description: 'Firebase Cloud Messaging', + configure: [ + { + label: 'Server key (.json file)', + name: 'serverKey', + type: 'file', + allowedFileExtensions: ['json'], + placeholder: 'Enter server key', + popover: [ + 'How to get the FCM server key?', + 'Head to Project settings -> Service accounts -> Generate new private key.', + 'Generating the new key will result in the download of a JSON file.' + ] + } + ] + }, + [Providers.APNS]: { + imageIcon: 'apple', + title: 'APNS', + description: 'Apple Push Notification Service', + configure: [ + { + label: 'Team ID', + name: 'teamId', + type: 'text', + placeholder: 'Enter team ID', + popover: [ + 'How to get the team ID?', + 'Head to Apple Developer Member Center -> Membership details -> Team ID.' + ] + }, + { + label: 'Bundle ID', + name: 'bundleId', + type: 'text', + placeholder: 'Enter bundle ID', + popover: [ + 'How to get the bundle ID?', + 'Head to Apple Developer Member Center -> Certificates, Identifiers & Profiles -> Identifiers.', + `
    +
    + Screenshot of Bundle ID in Apple +
    +
    +
    +
    +
    +
    ` + ] + }, + { + label: 'Authentication key ID', + name: 'authKeyId', + type: 'text', + placeholder: 'Enter key ID', + popover: [ + 'How to get the auth key ID?', + 'Head to Apple Developer Member Center -> Certificates, Identifiers & Profiles -> Keys.', + 'Click on your key to view details.' + ] + }, + { + label: 'Auth key (.p8 file)', + name: 'authKey', + type: 'file', + allowedFileExtensions: ['p8'], + popover: [ + 'How to get the authentication key?', + 'Head to Apple Developer Member Center (under Program resources) -> Certificates, Identifiers & Profiles -> Keys.', + 'Create a key and give it a name. Enable the Apple Push Notifications service (APNS), and register your key.' + ] + } + ] + } + // [Providers.MQTT]: { + // imageIcon: 'mqtt', + // title: 'MQTT', + // description: 'Message Queuing Telemtry Transport' + // } + } + } +}; diff --git a/src/routes/console/project-[project]/messaging/providers/wizard/configure.svelte b/src/routes/console/project-[project]/messaging/providers/wizard/configure.svelte new file mode 100644 index 000000000..7f1fce5d0 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/providers/wizard/configure.svelte @@ -0,0 +1,133 @@ + + + + Configure + + Set up the credentials below to enable {providers[$providerType].providers[$provider].title} + for sending + {providers[$providerType].text}. + + + {#each inputs as input} + {#if input.type === 'text'} + + + {@html input.popover?.join('

    ')} +
    +
    + {:else if input.type === 'email'} + + +

    + {@html input.popover?.join('

    ')} +

    +
    +
    + {:else if input.type === 'domain'} + + +

    + {@html input.popover?.join('

    ')} +

    +
    +
    + {:else if input.type === 'phone'} + + +

    + {@html input.popover?.join('

    ')} +

    +
    +
    + {:else if input.type === 'file'} + + +

    + {@html input.popover?.join('

    ')} +

    +
    +
    + {:else if input.type === 'switch'} + + + {input.description} + + + {/if} + {/each} +
    + +

    Need a hand?

    + +
    +
    +
    +
    + Read the full guide in the documentation +
    +
    + +
    +
    +
    +
    + Invite a team member to complete this step +
    +
    +
    diff --git a/src/routes/console/project-[project]/messaging/providers/wizard/provider.svelte b/src/routes/console/project-[project]/messaging/providers/wizard/provider.svelte new file mode 100644 index 000000000..1f9e238a1 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/providers/wizard/provider.svelte @@ -0,0 +1,161 @@ + + + + Provider + + + + {#if !showCustomId} +
    + (showCustomId = !showCustomId)} + > +
    + {:else} + + {/if} +

    + Select a provider you would like to enable for sending {providers[$providerType].text}. +

    +
    + {#each Object.entries(providers[$providerType].providers) as [value, option]} + + {option.title} + {#if option.description} + {option.description} + {/if} + + {/each} +
    +
    +
    diff --git a/src/routes/console/project-[project]/messaging/providers/wizard/store.ts b/src/routes/console/project-[project]/messaging/providers/wizard/store.ts new file mode 100644 index 000000000..9f47f8a41 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/providers/wizard/store.ts @@ -0,0 +1,103 @@ +import type { Providers } from '../../provider.svelte'; +import type { ProviderTypes } from '../../providerType.svelte'; +import { writable } from 'svelte/store'; + +type ProviderParams = { + providerId: string; + name: string; + default: boolean; + enabled: boolean; +}; + +/** + * SMS providers + */ + +export type TwilioProviderParams = ProviderParams & { + accountSid: string; + authToken: string; + from: string; +}; + +export type Msg91ProviderParams = ProviderParams & { + from: string; + senderId: string; + authKey: string; +}; + +export type TelesignProviderParams = ProviderParams & { + from: string; + username: string; + password: string; +}; + +export type TextmagicProviderParams = ProviderParams & { + from: string; + username: string; + apiKey: string; +}; + +export type VonageProviderParams = ProviderParams & { + from: string; + apiKey: string; + apiSecret: string; +}; + +/** + * Email providers + */ + +export type MailgunProviderParams = ProviderParams & { + isEuRegion: boolean; + from: string; + apiKey: string; + domain: string; +}; + +export type SendgridProviderParams = ProviderParams & { + from: string; + apiKey: string; +}; + +/** + * Push providers + */ + +export type FCMProviderParams = ProviderParams & { + serverKey: string; +}; + +export type APNSProviderParams = ProviderParams & { + authKey: string; + authKeyId: string; + teamId: string; + bundleId: string; +}; + +export type MQTTProviderParams = ProviderParams & { + serverKey: string; +}; + +export const providerType = writable(null); +export const provider = writable(null); +export const providerParams = writable<{ + twilio: Partial; + msg91: Partial; + telesign: Partial; + textmagic: Partial; + vonage: Partial; + mailgun: Partial; + sendgrid: Partial; + fcm: Partial; + apns: Partial; +}>({ + twilio: null, + msg91: null, + telesign: null, + textmagic: null, + vonage: null, + mailgun: null, + sendgrid: null, + fcm: null, + apns: null +}); diff --git a/static/images/apns-bundle-id.png b/static/images/apns-bundle-id.png new file mode 100644 index 0000000000000000000000000000000000000000..90fde1eff20bccdf9a34bf5555c55483e8d4c40f GIT binary patch literal 42772 zcmdSBXH=7Ezc-2?pg}=Lkq(ZGQ~^Z+0coRxO7FcBdXo|aqz@n>pwcAt-U%f1P((#~ zCkde|(wmfkBm~Zt@!4m;AJ2z(t$lXZav4HMuKOzg@+)_YmWIkj2s?y|it6IiCy#Wf zsLn1?QJtwfM+aUppCyfh|IT|pG4`gSVz@&2cZLd{!3thHxe z5*1ZV0>iO2EfrN!>C;C_dN0mw%+P+&!*F!%_^qZeo=>hlN5g=wrn$n*@#yiX4ZYC> zSLkb6x@!|>K71$<&wm}6F|Q}~tjjP&nc=3K8hN4I>? zJ=yqtfz-jz&++@^Q0jNd$pm$S>)pS9rn*|dOu2ZhOC#*TgJb%MB`#%5m(*vDZW@0tjmc)9PvBofbg^eN&WuTxQ705w^-4T_9g9o-XB) zrC(t*;*2SSLiMn6?;{V?9i8CT^7maHz_y}9RL(nU`sM~f^jleJFctII>#9trZqlA!$&m3q6L_rvSN>F#&DGc8_sEw5^%OS&QL2jG#d z24#AJq~+|8TMccbEm_&+4DU}C=%1e$DmAm^4KjAj``##=9*=D`Epw9&raV3eFEBq@ zo2bd3flawN370$0r8?Fo!0$QP$ZofwHj#azu(i_SYo+AmLEAmlkUYwLra5w;T_u5g zD}w=CTF%d2Z(RfP3NCO(u%4T#6RDQLY!U+e%`3yC=Fs)oR&?J50gWg|F7{@}KWK$5 zL&$`ZG3TknxsZ^+qs7$EqF-Bvz~ze=?mhliL}oqej;%CpSo)An&ECm1R~PO#7j%fv zjpladResaG!_gj04hTFYA3j{n5FKd~dzVn>f|~@N3Egfz%rfnwVR|r}_2T>aDI_$O z8MZ1fsk*jJ*{NFNi-NZgF@~1-=UrS53tb7C#JkNoFP1a?T*2qpoxj3oWGxXy^hwQ~ z4>1cOVD1!qj1{TJ<4hXdxqMBaDHRs2lkea4zGTSP>$`lDX|C?m=77|kkFoiQ;=4zZ zmio6hmeM_7#$#!DOF6x)awoqQ-1e3R3_d(}r3T;r){K5>y!|bFptL>RaaYNvbJB}aI)-0z6;0K5Z(J@kBRaz)J#V;gTaxT=oFsCv|bP0V9qi2 zjE{(5GBGzNW4W6*p;jDvg6>)%kW+YkEOxlTm-#9+^ogSTGaou*E7&9}4^(RR^lp?U zHHkxfBLoeWUfiM$a^>SS@AA+lx`CuX1&K(yyL9z0Erq||9ZY*`1|IKpEd+ySLv?e( zqydSD-7$fXHKPaYv}foUIalb?v<{*~xqU8AwD@~VK`e1q<_i|XC1V?4NRh2YYLFlc zwsY)H4V3<2mvEjKFV)?g4czvP&|CR_Ctlbl(9o5b3hdVBT(PdF9m&i77Ht;J%-2H%cv?GuOLG|ueI z(yb~Tm$&6;8IH$q3GR9~hZ0t(w_?TGUddQW4DCvdj7C}@_XxU05pW;DyLU{!M&m+K zk*ZhEVQQNlUn`T0&a^m<6+I5J%s;o5OZ6Hq(!Sd(y!B~3ams7Iz~wYnG~8F4b@Toe zE~d#@5G-azwmVrYeZrR1MqsPqrudj(ArId#r#<}Hjj<%XAIpbN@qb_8*YN4E2q{WJ z#w1DSM~5>)t_eGS6YQO<^GR|jYgZ4Z^;I)0)#)U76j8+s%EReq}uW%9a~#u}A-Yzg?!mfX?E_h3?WS`;2^0yL(IGPkFGv^5Y>T^XqtrY_7WkEKgb9G~eH|e6sXd z=CFNs8(V4G&(QV6Ii<)g#`Tk-7KqDCvc#2q@3V`?wL`Tb?^|yVZEq)r(+Qzo46r1- z`7b6L7ES*^-0mIPRagg&y-(w;k{H9rWKFY7AX>D$ZP@6Z(12Y4l4~(-M2% zS!mPaXGPLbacEVL-);{-x=kn1X|1$_-)D~(@6Hal~)Y}9r_=;%#Jnt zx~M+R(Cl0mXOA6ThV_zc!7Slsw-Eh+iuhzd^=p9;76xzeZc%2le5@a8ooP39mS znJb5-Txnu-7Qb04*`u9UV6=yM5_pmQ-Z{C$LtIkDa#rA=MBtkOf_~Je*UZ9ZY)4{3 znC#&?oW;7b!9IGetlaBt(7ooZKchLni*F>63yL&@ukfjPrrm3p3q}WKrFy9?pPcTG zX?okGmX>Bxewb8(-Q2r~ktl(d0Doo~u;)_Ud-1R-;`K zslb(0!tx3fvl4Djl6#L#PI_LzxKUUVjN3&$SRhOKLx>-+q4LDcp9x-N+y2?|L7&9? zVAIc4QmqS@V$&{dPA91)Zrg!9^m4pJTiOEGq?r}~Qm8ln^T|h4ukzvn`EV{8Ij~Ej z?4$plQj@T&GhTfnVQ>kTD7h_A?3c2`w*<;4d}W7zy-`w1TvE?>QPf@U4(SnFxv;Z~;Y5vXa-rQ5G#E5pbKQ(~_0 z`A+ZatX7Z$)t@)yx&lg$kHf<-C0%Ra#B!dqxP^8KXW0+?_Bnc4fOq@y1#IL1DyL0z zbE<*q_}4;$J9(c~+RH8n)Kbz#vLLZ~C#h=_s|ryMyh&3@F}5bzvg;M7yeb5DsyWQq zs^|U9+*SR9j&#~wmD{0Lo;((xOMQ}R5#SU*w7)XK>k6MvIyyeuqXE_N`Sdn}N|Ug* zAX3yoAaQ?n%ji{x-%n+|c;A5p+q%UFd!XEwry} zn1Pv2xHyX+x1W-S+?!X6s&Sa-4Kl=Q(BKmM`)nfX>wXiRu4CdG1#gXk+ZZ(=u{7@0 z*;CyjwezHm1F}1MGi5>I;-j3CspF(O-+kLGF5T-^{wq$V^rWn1*AQP;x<2L6?#3kx zQ@htkeIze9whT5`!)C*r{JzQU59>0Bga;|#B}PObyXXgrM{YtZwgH$jebI*+G`^4W zwY8I1SBrx?!=;{sI;O!2Im1=ZyS}VJgLyPM&m8lYkT>+Iie!fY%0Ob^Kv%LRI5t8` z;FE=6cJ^9CozLoMiqq7iCADX`Z3onqKB@^VXO~7>PkF`eWBPT% z&Pv?T<$*))XSJx1Xr|W$8NUw-A$V-3V%?9xuDA{MhfA*A(&G!5>D=WeZj6U-@klN&Ka_) zje1G&F1Al|PT_ePVc_`J&qseG``6AH&Q!coo}m+9{RI+Glm+N;BGxTMu!^#@f?$LE zS87Ei@d~U(@QHihKq4|)UbT2)N<4Z`UfbG=lx1YMNrfiWzHfp+-&fNoHJz*u2DD5#gqYKBBOSX1~f`Oft&RebHq$BakoAyp;a+rQ&`yb~b}wv^@&Mc^&25F;p+_6v$x z<&*tSj+Unaw_90ywe}7*`BuB17+7hLCvWEe9SOmCm(xxD?~;oe>lmqh6m7wUXym&PybW`~@d4^%&MU7}9SKs@XplR9VP z=eZS^p|-zDX|`I-&aP4$siV35f4t*lyLKd~aL^9dvv|4Fshu7pG+e^iPk6goKQ$YMi3#I?puz=)?1IxF-#=hsf)h(j zy-o@)^HdU;2cQ|;Xk3U#-Be9!JiK>3Mj3+5IfLG6E@xOFG20oQF-cM8REGsF{JWO4 zncvB6lCBfCyIj~m+(;{0J`$V(i}?GLL(n=YH=zBGUvuW(edp0m#>yZ4NUV-VijMzK zVPW#my%75T(PAOrqhSB@Q33+Ru_AI1aRL6Lx>E_04P8ySC!hq)aRxk%H9sTi+bCh1}av>q%H>5IC-5>CG zaN_*YS~=qVnu;>pHHVDn$`iEVaCB)l4=sDrW}WA^Ps4#Apd)6yhvZT!J`H!kltw#C zh=;olCH>h7bLMJgJ^E$i(TPY`d&}GPq{Ia|LOJt+H5=@4ob*h(@My8U> zy}|YqqVNVmg(v7<>BngoL~F`IRjUl+;R^NFkZ(Ejk19?^->O5G+CB9Sa+QbNM)Dqy zuQIn!u`*?~zMqI^uWWE#8P2uF zUvCc8<8x55cu?l#Y&U0S(hmCc+iUynmT-oOzs zd_h{=k_ge#5N({NX6YXiru|gaMsyZ-eAkW;QX$Z@l@Hw~@UysaM=Aw#wMUX0n8B3^ z^y@J83o@*qkhU9iHKcED5I~u4jIe0k0A)*jT4~|s6YdxDVVnpOjW>j^bnJP8a@jbq zNl{kG_iZNolAa{w_U=PFm5Inm(R$^0PPT)|y&(k;Cb@mBc&B7MD?Y4Qob?g;qF~N) z!<0MvajU1Ur@ry!rppM{5l`nHFvIJw@r%rP&x5V(3qoQeLvb7}taVt_~l6j}`l5F?MttyQ4ik>U(^xZq5K)d(Q1X%(*kpqdwnb z_?zR~$XWhNY%CK^AZVBwWa2g+pW!iYTqSp3X7e3c*k*dd^@@r8o`6qSG1Xh*#Q@MI zdHIMdc+M+=V6YDGqV+2DEv`IYN5p(S{0;_TIR{DH8wDu{}XxlVfwCTfQXkDX4V7tdJv^@|4_FrCj9V~>NkXIp1r{_773n=JAZ^uB1uLbCE3)^FTv=_=}f=|4Aw zY1+|G>QtIY;8flzRFAX;1xkI-wg87hTis3+y&*28IpcN;03R=(+f_O5MZ-sx*mzCE z;v`o_Xj740<1fo$o0Fo$Myw@>;#kqG;~G{?lWFzmmej25$;@x-O5|v8zIhW)6cEp)W~x$#*2qU8m4V_O0v;D z(212#4_TO+6?b$M9}OsB9+g+0Wq8Eq%3f;?Voxs4C%0m-k?=~Hjj=cDr-Qf8_N<(W zg2vii!QJoAGCPEG-U}$Erc?Tub^_LP2ALeRsO>${&6oeqr=v2~NCC=76#O+!X}|d0 z@>95;k|cKjHda4NBCI>aT#cg43BY~8oGjnriWTn&IM{GXkUKD%Shoy5Dhw?6+gPtx zM)zk`wOxFn(ByVG@!8n9{2gUB{X<5`Ef&62nP7(R_s@b$e-=I-y}7S__o;cs7k0br z*Ps@qY#Z7tT+DqniP}bOAiNY(!pq&vE}sXG@sb`NA>K@(k7fO%i5fD38@_~*q6(B9 z+>%9kcDuY?Vf;m{M^@mLbi+WTI_R>(Wf%c^8v0#SGfaAicq0Jxw{9S4$Fh}ZVPoND zWpi-Qji8+tw1-vHBgS7oGxoIz@eS^6(;7=ma z+h?JrWeK&8?FdLfrvFmf!I-83^OL(jr=Q_=OfPl)2^Lyw8cO?zuTJufi~BhvG8mQ= zWdl8L72gZ9CEEEV$)|Ru#!~>0bL&kKGyo}+<*(5P49)Km!PPz;CRgEhrKQQes*6Px zber@NO6oUhlm{~R{Wn$2KNP8!Eq$flEJo&Bm?avvIlcU# zxjIhL##zQG2(z3BA1*y=Ja{NX5=;5C8}zzZAP6UJoaHZFq?=35U7Chy1$O0!%S;aX za3(&E3$~P)cz4i5*QPaW780B1!`V*j%Sow_I@Kp>ycM4p@V$Vj1>ohIt@J-ul)xOB zz^|yN#KnfxjlNwru{d`BOncUp{M`F?u^FCFNOY9 zBDh{*jQV@%aKe@ej--4MRp^61|C<0(H~!5e0ir3f_sdDqOUgSye148AczUHz>>iYY zn1Y9RXi>%QXa8I1rT-ly*#A#P`OL@4y<<&8(xG#S6VWbd-_&}#T*i5-0!P~ASI#yL z*ff1Z`AY_^@~JkwyNjJ*^Ekc|(B?B^5cq4V6V@5+?M7a5gH5R3oo@cUopOE(jf6GP z4XM|B)jUpKASCc3>JdeVo}G|_6f)mb_0w{Z6qPnhS8qeN`WAN13yf|1>&R*xb=zrR zu*?uK!PK2A-OzWa0WbNR$yEGiU_;}bnCdES+S2j3u`Rm^3qfr=AW&lV$1I!=?23gX z3-%aumk}Cf*5r71EBLYwA4-*EsI@ z$JMP#b+%?>Tr%+C7h%V-x+j5~Rp)d0YIjlsXQxmbSqK&rOxG!FUBpt&+)ae2QD4Ck z(tsrwPfYl)U;I7(Rl^NxZ`1Iw61nVbXITSL7g?+Ti!WU9<3_2r>IU*aqSA#lDQUN_ zGgW)j%0E|e+T}{h6q@B8s%FM?G7-{Wc`SDO#kN%JMvqnXCdpl7V~E4AZlvQQo_9{f zYrAr)cA$+L)sIB>FC99&X>w|HHMhu*x%Hv=rD|0fOC5^0O{cKaBiJO*XJK^v`l_2o%i^Fp3KI|_gClaA;g$&Qn<;+dIjaZ5xdhie znn0sNn8fDN5DSIB2ai$21ntt`i#?w7y65Q^6+%>4R$edlIh7BDZ*w);LS2kySzF3Y zJEGK#to`qJ9z)Q=tiv+Chnp2{5s(97Y23iejyBowj_PGu$!Z!{i7R?s&_j$1-8v%& zI|{igVA;!kq0O@0nT=!_J!xM!(3W0MmN96>hpWW}4k3ZIAd^3edZuCXyTBnHPQ!d)4sk>vv)Ksdy6DIJAd# z-e)R}vN-F;X;B(4-Rut-((Caw9k@Y!e$*mXGtqGJvkHbuZm!b8A0-4mO}E1Ht;^V@ z_y&0#gdk{fN_Y>AOo#!1?lL37kS}=K_(VFq(vOf3ef!U1F4n~_A9PhQ1lwoNl$p*g z)HfW&39DGu@Ht3IDFLgS`!3taVrK){z>)qv5O6jdd7wv-1iEzH`&XB<$JqCY6Q?oAs(0 zd`i`n^I;Hb_+V9`r+#*7@EMftKi^zpBmu3|DoPS*Ybm^#Svwlgxx%qIP$LXBM1w^% z2Gw^^xytPu{0C z)Jm2Dc|iyLV@CSvKwz{pbThwc-E41EuMjy+Ti(zZ#$#VO;aVq@TpvGBPW!N-(AD(1 z2l-!$8E7wxZIbWs*9oWA_sE$T_o_U?eF8{6`D?_ z2HgxlyPx>SB)1;;rOy>t7T!o+EDJ$a6MAIRJxMGAFG$74 z;%qqnOUMDatCRQp)zAz7mEfuVXXP9Jw=!3#_;2mZPXt?^B%T4BryvEfJL%}bXSGqu z8`vP1slq^9ZKiXI>iwhr!VV=^=vlL6~4`4ZeGc3?iwOqTaye zgPP;mC3@pQ>rk$pAN6lSdV5|s#kDr&@YtFuYw}AoJqPoGVP zCI)W0gItjyz4_y2dWC-Wd3%lq_V;>iwd!j#lO|Zvrj8~XmJjPQ=!RB67iiCw8`b1( zR)1#1);j6R9!`6^0S!dGTKXN^s5+0i*;)?Rq!T}hfU^_jh2A)FUObH`eYyj#OMcACe^(OV0-Fd?$i*1=$0Y#!KkQx}EVQzg4Zi!Mu z4;iKZ3038^3?d{m#1mV0zH&U~yWId#q3VSoGLc}t-9?hWWzjP6HGyaQghICf*@!y~ zKu#tAefvGu{k?2q*GH+D7rrIQl~gpn(1SfOe=62sGt))UMO8daPmdD7)Qw$o!@|X(3*A5Gq_MSWeCBf3dfR%WwKJ@idH{`}%E`EyPetqUfuXnL1xqnOo4%~iJGl&_YUgS&$k}VuD9`L0b&@>oAAKq-$Q!+G`U3E*ahg5SS(-G zxX2R$e2T^;3GM@N$RudkIVCHJ0UVO99~hP@jcPstBpSLoS?3)zmMmf_xppk&KJDny zN=S)gyZe=vG=7+h{6?Yb0s$)iP@NCcU|y_|IeqHMY5QM4sGWr$b0pwJW=x;UE?*X_rVRA0J zopbyG5#WI^5(#kc)rj_!$$Gb`rQV+anri?WgQ88;>b%4hSSYut=B}MCo^3krG=-41 zK!jy`Ft*9t!DY6k>EBZwdaRpA?VWW+wc43t}e z1dO5i&!_4quo+)mwf|tc)DUfNQra>A%QekVqfGL@KF)@m2I0)~u@%NwApNEI9{_n~ zA@&2_mIG8wW=*5C`7Oa8AM{e`DW@XIQ5V>3(3|z?f#!WjU}&F<$ls!Qrt=?0Gg^l= zO}iF{`^`3EOLe8+yGL9%xb@UIz&;yLAA>Ih@&hsS)9+asm6E z+4|Su4glM&a;-B5dK^s?`E*NmDfbP!xZ&pRrGa$w+rQv0Rd@c~jc-Gq*?oRa>wUb2 zDQ6*CvYBYg5%dI%3a_UrSMGyt!vn(_J4A|CK3L-!q3~Nlr$#h2eD(V@QC|)KI>czH*_$rD7`M8$#{iM9JQ&UeZ?F$?zV09yZ|i&sP}g-x?(l*- z3&NuT&`9|B2fI&LZj-=<-30rHG0<``@fP$S!A1dR_6;bPkm7Q7cEe!JN>Fkp^=pW| z;Qbe0F01@AYuWa)sgGLi&|yrSrm)1gI{II6W~h&GV?Zpq#`EDyjgL7|h7y7uy@I!m5c%1_xRHR~daEc8QZNv4!6b-A)eDOUdH#%Hw4edf9 zm7UxhztK_h9x3GKd`GTT9PzLj1n-Aj3*{ca(~C5rd`bIlmnMyxz=U3t7nGvNFy9-{ z6J!|7K3^Q%JwBJQQ9Gtlm9_!k^iA#nQRk>t4>}=8OKl(?^(71ynS$K%@KjiUB5kBv^;|Y&s3dSLJWQCx zow_G;lcv6kJ!vHv7BCf8)be*Bs&ACrOOp{5WQzDhy`rvE=6}94sZO^t2>* z`MRADv9l4ubwa5%CX1~84b=kJpnk!JqR1hM1h`h2U@^5XH}tuGOUK1yph4v%o`ThV zJ|Hf^L*CX-96s2biVhmgrcJ&jVyQ0I700ohB|K4_ld@DepGJH$Mg@vCFd+r<-`+1) zmeYNpaIR*O^8iYo{>bPoxvu?lWNtY#n@->-A{xoXbbp>I)t|rjyJ}SZ&|C(d=gl5+ z`QG(c0-=5r*3q4rmOoDPskBMmE+*wCYr6}m)g{6rzXkR$%0v`&!k}(_VQNF%`^Q|EW5h?dNTW(UH){Cp_A2X1k1NL_~JS7s=KZ}2YkHq0Zk`up=v)I^Tc^~-6JmmB%fy6&IKklp}RXk zbQ8z^VgFJ5itrlKFhf=8(=y`PUP66({7_LMb>0b;cP;tfCb%gDYCxRhgLAyBVV*!!VF1DraFk>Sq#EEVY?I@!~kGT6nJ>!g*Bfx#TdgkYd4M@D$<4w+2t)v+BA zR@M9KnJnlBOBFuo^%1$TA*!=BnFH<$znf)arr7V<#uSv z;X*sXDE;GYdtELJ{z@q$7GCtsLy!4@vWEb$$us1EzhYe--SCCbYH^6yzhl9!_SxAbBypc63&j zU)EG3tbr!FAGrrBv7ym$b$obgWNp|YIU}=KpNT0q`5F*sWTiCsekh%B`%!0RS}8Vm(`yaBWgZ#!#|Ki$gd?A zdaoT|e=%cMTk%-$1o**Xq!=zbv@ii zRvMo0QEY|5i=QZ`0WSlz4oskQYUEBI`fnNX z;F_M*pn_49<6j0I*DoqSfBB~c32na!la?qXBrKH$?E>BPKUw9*B?`P^U_4;Fcv?t@IYI0e;r@Vg19~AND^+dvDAr z7&ccl(YKr0(brZwC2%*irrUc(*h|_xyWM^0ad+rq$9hRV{Xq3|2HaG*l~$EO;i$pY zd$UzEeor)F);2ZqQ1$c^T(CK>g^+1qep~AUAZ4xr zO-Xc+#Tj;5?R~ABuN-eWc#PgrR9nQSy4Oa*EIE|wTvw$LTFHGQ2_*_DqJV1I2yo+{ zu=)c&hCt(P$>Yls`=+E7Q6ZkS2K_EOZy~^lXnZhGwu(!fK2Q*7{HRW_a>v} zD;z^aFjSu3J7w5VCs5lkzh}}okvVPu@aau5ha1{Xp5qoVGkhKP__k;BuUXjE&Y-cn zYtLk*J*JQCy`hcx(xWrNai0Q!b`QPGK0Xf&2*@s;kZHMXAbMrM`g5JSeCavpQ9A0G=oj<^udH|wbriuvHwUS~d3>58R9BU?VvsPERlihCl zAGww#-CToutu?-eJ#hYK4%Ewol$E*Ot|y?|+gw}jJ`^m8Q&zKZt6WQIFr9-tdH8rZ zIn>S$V%->x>ayCKoMsjs2}nsVY)H=^>)}dePh+K;<#8EA=FP-G*~uMEvRkXXrPU#~ z`P}PpKYM!*-G-U+sZi;*byQ~AgbKd|@=Ej|5??MkwOSd0t8|8=C1iUFg7SM04)cDf z)DCRkBojrZDs1rc(S50~2xX%t9fK~0mvn~E*)oxXQ4iJ4DnENRFT|I)guqFsVv0rQ z?;(07Zcg@N#V|CbZI#|#U1nB z19!a<1GkAaYPrRTj^f8I^+veEWxEC^GVbQ4%aq}Q!2~Kl1;1aIzVXZOv__6z-A~=B z@GER_qtQUWa%fe3qwUavJ|f7a;>m}mue03kpSEP1!#3LuMWnpkrU2$W6bm=*lj&F= zp!o^RSPSG(}%&kD5ir7rK=xYGyT=(qeNbf~R*pKAKj~U@QQnN2? zSB_FdOs7jSvg8h@#|Z63MQ`4nfzTp>L{k#T5}w2#9snN@%lHcLBXHCz1w{yccAozj z1{-FWbedeqeIO4w zi1II7bmTz$ZEwMcg}n8G*eML9;$-ElP31Q0Hn&5Y%)lg0$RYa_k?g|gKOdjGx&Ls@ zxR|AA@}RZL^e#c$pviS5Uz4+;)z{VVvnW$=6@GKUwHH2cu+SvC*nM{0*GNv*YRCk; z6WJr_@OXrkZNGx0xJhx*FZEvC$B4j*iLC**gV*ZVwVw9yGqF~lUSHW|R|#p@pzO(O zjp#VJ;Fk~4#C-pQ8HDP4_^D~T2wf)rfoJqB%)`G_MJ?>n0=G@P3r4t%9mx!O! z8y#&|Hf7~M*k-GlK*s`Vs|OOctc$lT24sR{q;8eG{(_|T-&Cw%)g2MoQ)hz$q|z(w zjU(4i`DsnEuwnBl0r*P3IiVmcj%RhCh#2HBMdq#=scf4GB>f~{n6qtoV@F3jELnoL zvHL0N1-Gle%awGw2v5(;LgCVU{B?ookt?zg%ixyCnJ^ywN*?ejf z=5Sb}Hc<^t?+X{c!n^P+LeBM^e3^c?TD*21a)i`mP@mNI3Z*`TjdjmtYyDQ3-9RKM3s2b;#da||$^s%*(20EPY0 z`(78NMNn9#T`UM99i#|B#UC@m-(GNg*pibWr7k{|#@K75r(oZyKLD2yY1rL0ri@Ww zP3SL2=h6=DmNPuBxoBIL_*PQo4L*vp`S;jNAw_mb{zi50<3F0QJL;)QTqFZXbHwiZG z|DyMyd@Ti9eaz$SRCHNI;poQ|Tmqb!shjQQd?R4=DSuPjH?93r|6PC^{ynq~V6f}i z6jnU+IHgB^34(sPX zUTrl#81C-08#IO$W%T|{dEaufE=PJYzl-S2j$N-sgYY{-6r%?f)w#49*TmM_0ckUb zdw-ys)+-*l81=Z%G}N0n`>9Wr+Bf}^sA8+18;ZD? z2tRMS=J4Ov(Hz0wpGx&V;V11ix+4xOZvSC~M@EoPRpC;A`Txgzo1-|AL=ho^$NxSv z?EhyrMUhR|-hL>{4M674PaU98V+v33@@O~rP=UC@YYHGHidQy;L)fsY*7|c49+WGa zpgySsu>tsv1=z6&OAm@k7RY6d0aAafy`-upfZ*&hS`ZVsg~(14F~!!;1qTZ23!RWh z9{IwjUsZIeWj(-C{EdL*NYDpvBrwBT)vwL1wg61r02;^0tn$%7Amg3{&B4aWDX6I2 zW?TH9(k@Zd#*#HDbgZH3x7trLuI_aqtYl^Pxot}^>62Y7#IEW50|@Y4@U>T4 zY}h{NUb!rBM?WzE6fooZAN5P)mVlF?UevsK0wDdaQZqh@lqj`DpwzFxhP$?ON%$20Usz-Z_OY{%~0Q}u4%h<4ClyR(5| zA_L8ncT~9jzW@YXzF`_5=o1w8Gyt-5xB%|DCE5o60Aka=_I2063~3n9b)q+pYHYir zW;vw23NpQV1tsnKSt;f*S%o=ZIj#p{$%0wUC~9j8zCU1;0Hm+z#S~LBZ+(oEO^ji& zcF=c#>C^)^@|cXz%DlTk+13uli*>YK2L#Jl%$>hX-U}aTm}-H6Yw}CXl|;BaQX`-E$<(8Dk=hk9D&aaYj8U}+ z+?2pwH~@Z2Z^9*spkzk^E5`6%+}bU$bkTKAV_#?Pk0bREPLs8z=$&(vM4^34_UYKn zPmi{vuY|O`BA&HSW4|WeI#>KC0d=End~M4M=x)t#>iZR};}F|I{bgTbg({k-D$&?k z7iWz;d7EZXA!P}_^`o>lMM7Zt3j)=Zq@bfmrFrGDb9uqrwcK)n2R@my<=;=obu|G) z|AdJa4!jsBt#&WqwDFNzyjnXNcSpNEZE(3cjc;#x$d7Oyisau5F4HS^1eA|Jz6ku0 zFFSN@1{g1Lm&;NG)(6TX%se}2-8oo9%~p|moy31tH*fsHG6GOn@wv;D82-V~yA>#6AlaTZG11GuITgXW76Gd_amNdQCxb{xsYeO*lvO+b zFc<<3HZvgbP&NX2hgLH}j)IM2fjI8a?2G^zfg^`W({6%g$sRt1ygZ6%lrbBD@FmUX%O+*w!+A7irlr4-BN(F-!>Jm~Q(E$}o7qFj8;LlwOmt9?4+> z;m>)3)a$HU+;7oon&$aV??}IR0J2885kS>>aLWUI^HWfD_ykK7_PhO_8+Z0L+@{@PS0zsi9e*#ZUOfos6wC@5)@`fAFKOd z{APhnf14P~@!&;u9Ea2(M)O&!Xy(s7=chS*Xhh5I>&(EdrUP&q8Y#Dn*j0&P>~|WD zRyg_fIbNRVh-+D>Kn+6TdWC?mE@^#ev1M=2o3|){T=%OqtqWk_8}YJRo@87}T8z+9 zGg{4C4~Pi2LAdfvbCN-jR*w-KoD|i!vV8KGhU@_0VX;*vyt1rnK6QosLa%uEq10JS zY9(@H+#wT}{8*;M$4MwJ-SdnpjTq3i*@bfLp$A2l$%M zPmyn=K`Q+2G(H-0h5uh>x6a8a?~wAl>Hn5#C<^{AS*Wz;|8L#615^P~!I>@x9amA` zPy@6z1?DuN!;K&F9t&<&UcB?Av!O_6pnft4W6V?p--Ze>v_;W+#e zTqULGeaCzbX;W~Duy6hPLBtY@x9+M4nHx56zf-O~u#qL#U*+hb7{(^$ol zs6FePF4B~OGfha* zTBm~A8`5ij)C#3vu#p&@u@?n)Z^dwL0aj6g!^6K^W{Tu2gJ%?*1qB+OFDRE=wzuh*>Ggoj9|KIr4wQlh+{)of1`Xt$%~)3k z93iAD>aI0-5+o)ZXcF`l@fvRHLoyh@&Y#| zSP5w@I=mNGgmDmm%u)sFui_xUl0Q#a2Ht$UrULng#uk;s+KPk|tZx6Cv{$L^9gQIUu6;$QtKA*c5EkO7m35UH~Z=Y54gaJAVUs6swb3YhxC z*+BHwxz1P?)1fT6O^SWF^$=k6lOVh}12M!!k-U)86VaRo>(6u~kcHg<2PoS8T|)oO zGQhR!!Ch-iGi7}L&?vV`Ordy<(FAQpFqy%kZzqb>(}#UPBt;RnW~S`>KYSyKQxpeo zU;*ku@nNd;1ey+_zFfIZ;cJTQMSD(6Xo_SH+2mEo5CHwom=c~X zvy>`gYEKEzKs4UfMqCq?oe!m%HkTM_HV0LiyF&RJfC>4se3AX}_Tls)9TkMvmrc`MFq5VGrClMelqJ8|J8Cye_>gjY0X$~h?Ep0H_IlDVW!dQfZiehA(Nid66(YS&by zEp8&Nl|STZ2ZhVVo4bS6@m#V|7P?j|A*ZD5)}y6#(TTjAzMtPdn}RS}%k_$FrZGEQm_P)wpk6~46dS(v+L)*@7)~nu_s%I4ErH~@NNSG& zG6=SQLzW=NxBx4~gx?}1JSw$-H{gCB#ogEHR)cYEYnl^yXUTa-)KVSNa{N?;ZZagS zsp3@GmEf~EiGiB_D+&oeR+82}wc^k43};}a_*z6`Rh2G)8+35V_*5TkUh%V_n6L4m zT>L&7lkDU-rY_Y))dh+oX82c^HasY_Sym{@h=*r{O0{ysNoD|s{#!|?b(=|9F!UEl zW|5V)_aGInzzGZkH@iVE_v(!8fzo|Wj^c@{1SNTuS}nP^KJw|9u1qa)S_66t7l0djK}!$s{ayOwP?F`JIv1=7$k&Nk z7GrC7gAL7nlc&TWRKhDIIW^S5;6T<3Q)B{D8uCYWQk!6}EXG?y>z#69K*c;nxl_-f zMN3dF5_@Onx{cigrKuQvu&0JoNDR+~M;|n0$4}WvM*Y@m(&kO<-(eYu8ZgZ};pwB~ z#5qCTqDH>T5rOX9LnydR?+^sQSyBayPnsSDMcvE`?V$)y!owg|rEK}gj$?9wV5rx8 z7=5!m_UctYfN5V+RcC7b_=;K(*tydfY6V~LLd z6+SC&V|78xDpvITZ7ElZ)Q2ZOsjI0l?c9eGf7wDdDz=&Sdl-aeX6$pJbn8AaQD_h zQUBlnD59W(Sil0Vg6SwJjw>29#7T^bf- zso#0MKi|)tJ9FpG{APZC+?mUN$SCV8&hwl{9j4{nnf#!$OgFwX*WitdZ|AV?l(tDX zBg9mH|4?SEB^gfcxPY^8I54q%PT3>Mwq@}3J^fwM+b(H=1Uo2>Qf`{lEY>N96a%h{ zzAYg}1y2wff}AXBTo2Y2)_*7NupE~EYc1vZgzd8=$36!0a^de?Wwckxj2xZCnPNuh z{-JXF+9{@&f}Xkct86)}5)^__A!wO4b(5FE`aL(#4&L#HQN(qR9@exfq$*yF>YQRJI~q!V_1^#%l3+(xV4Tc-dC+-5M|jk=P^|IU>kpB@ys zsGW@dA@C1F{Mr4tI%r;O(@TXMd}>yWhgYWUvG` z_wG&@2!xjHU`$+VSJ24=SdW131q$ZS!Q76#?BUE@%GE36v(HesH^fHR45zT# zaL;V5jHV^dWNF*;-FDk1cR^fKO~QZ6Q|jttRTFbNgIsws@wz%{)r&fw*?ChU=c(AV zvR{SZH!-+kCzCs0W>_XaU?K{nOl2RF=sjuJh*uU*j4!m?25>>w=!_w&g|N~>u-M+4 z+NYy=JU_8WJuR6^)9;Ikznz6oskqi4xLEG|MI(Wm_)Sf@+txJThZsAT`T%#nqTfDw zFrwd5toPi!(Nq>Tr&i;sr|^Q5!^W^fv?)zXnY$2ce%s1->Div^kBY4uZ}dOAUa~+5 zsGAJX-_qGLU&Gh+ z{FL1GE^HuCR&j_Pt^f7YrUrj}|IF7u&~WO~g=nH)yTfztP&F41j0=cTi zWu63b1x_~|Oz*bh-=3%>%??*O89&r{%*;R_2F5W8>FwHb?Q2Yba7AK!1-?_!&wnL` zle=k1(vhAy-+wPbdSiXRtvKD&_&50bxvD09+yXg4vdx9H6Usie==@ zD^~{>z8PcNo~j7#c-d=?4|Nvqb7?1#tdIE*IpU6a54xf33%yD{4|8zoV-@=WC=nK~ z3u@+ijoqv3*=jE_{em%e(RSSaLpab5Ty$*vNvGte-mf_P_+aEh%yzlm;NM=ezPaYd zw@Ql=>>ja~^BMbbYP81URQ^T8#{F^Xvg@=@<8>X5b(+!vkt3%B}VZ}^{gDutOE zQX{V2==563NJfIvq zJ_%*CC3C{A@Ny$v52|@gS~O0xI9+%!&KbJb2ES~F70t(+p$0Op_X4tY zgJ(2vCfBmxdOz15G;NJFctuxl5fKamcVRa_eU2iMD@>i=n6ba4%OPDN_Y~aVmfsQ^4nv!Ut z-H-BHTGPX%NfL!?0&lWyhR8RRCQ4ZOD`{DTqedD{Vd08);u&JJFA(;{YYEWZjeXCkV)^UW$niU5;6SqSy! z%fZSEobds&5yKfJ-kEKN{}^U{)Y1HRwJ&!1?Sm_X*-?~lcP=k)dv4wa zHSpuX(tAyEB2OA?uU|?zK^K^I+H>#sZS6_l;cA!I59{N*KXwjtOUka&wl z0)9MxG5YC>O-t2>TQ7JL?^s&Yx*us(YKQ~!<%o|}a<{W=#0phr=`&hsg=uX1pzr!< z_^kzsoUmvovCM%#X+RJ#;rOEda(`2mG6&A9i_z~W6P@nUrC#Mw9QVT<$4;#S75hF= zeDkgiArVKTe4eZlM~RK>2gaT<$z`}{ zpFIX%W*_KOPaYWabzK+*FwW5nKr_|TCxi}tb_Nt>KO?Zp-lvFO+|-l#)I(#dOj`h+ zruGL(HPFMgyh%rQwlz^k>P<3nk#8+@)BrY(5w zS;z2 zXwrWOL4 zI@_#1+ZA>)y~OgWy9ek6jFIrT&24md05ZK<@cy*xWJsA7hws+|6c90pXBpNCTQLjmPK6GC(l3?g9 zF*x|@zV!i#7rjKbhiGeIPSfW#`im7<${D*cF8enx!4p6HUn#6_oWAuRBtqTkY|IxCHg|78Es z7g2^h4kbQ*)nl~?d;@PyBVI&W-19BtgEtoLgI}n^`ToY+7BYXH*SudmVwbt|iv8uj zz>xvCK^6)zv{3^o1tyYL`yMvoeUr=jig#5rZ}|P5m~a%Oqq}Kxnq*7y-+3j$@Sd%T zOL}!QW3T1TPH#^?p5BM_0Nvo~&oo4x_cMA}KQ$q()M}@qhbAyO4Xs-gAYq~z|9 zf90B2YqYraQg&X+>nG>N7xsw`ewYM{g?U5$_xMYjY;%xQ5HWFW#fZVg6=B7UC>&igu%0v-WV(R;$mg z)<}JLBDTDxC@!&!q0=06>ZG?O-N-X758?J3-sN?723^mW_-f)n}z1B~d+HyDW3V)BJO#h3RX*`AB zF}VHx+5To?gmLey?r~nT5;kizh`?zxQ6-FqrwgNhZpVdRj~dLrHPsuQ z(9}#qUl%r9G2xV6^{ceBbB5>08;Fnn=gX7iyj{bu(G!w`g5$#*2JsbGHd(EhAPmIPI=oSeXxrr!r8sh-lA8vWyDoT^~c1v)4J?c(D%6)M|+>G0F$C=f5+F3&v zL%MIw+yBUe=!7w4`Yb}+YV32HIr^I3imBehYvRhWK|263O7|P8oqV^l-kz26CO+2t zv9PE>f4<2Tj=&XNiZEK+jQs${%8|)gkl7I$&%TCTm)*lTKX4Vo&aKJ|^_%WeAA%<3 zY&+~7@a?Ma-zmpLxQAE7Te+QxZ|`uoU7Om1IF+f1B{4FaUN`M!pBbgQ za^Z@jUu0{{N{%m^nteClBd?2lb)J|CUd^umEl$_N8?g1WL{&WHNq^?c_#*swGJ@8^ z?5@^)+W5NxuRG%EZ^mXN1uR~mihBJ0`2ryh2NCEp@c0?S(whtoXP=lR&GO~8S3f9M zX6slMIGt&e$yDLhthe_5)F7wRZYSMQ)A}GMm^zA>TLiC9wW{tB*?n1%o#-CITsG>z zX(3|G$8?fh>TeoWDb%W}Sh!~|?ZxZqc%faQENQEoj>FVx8{2ImN2GSz=NhCS=>)(g zve|A!-(|j{$57vMFM-h;gzxj3Hpm?mc^^@)jGYx929^OVD2ueR;|X1(G-(|9XX> z!GSka9uw{cnR#*cN+|qs^CR~WDAJ<+wwe1+d0KZRYxeM4++rdHm(UQp0dV1eANs%> zzY+Hr0_#1>R6HFen0@Rv3=jXJ#VH*ffrq`>j1U_JQrhTF$80_L%9OGwi2D~ff~dFJ=h>2=Nc<{*dW6U22O&}Y|^bIWD2r5Hd%AaX85|6hRQH>Q2?2iGr4 zdd!<6bh5)}O)rA8!iP#R2X_(6^`HNd?80yVM)&_zH~jyZeEF*TnC@D&dcVGGR!=H%8nxNpd~O$F)?$abQhV=6>BS-L zuDcNCD0#o@JRCrH<`2MdHP_X<&KPhMLC#e>h$BN*nM^mgncs+UDS=AOWrdG3Py9V$JVu+cyP| za>4W+$j@N&vE#dX=j);Mch_99kcWIZGM;Y?TG9%eR<89eAn(gM(^bvzF``zEz!xyd ztvfYAc=7|lYhsM->hW6DRf^X(*X#0Uk$E2Y&SRzuyXOkmAFGC)oC(5+L2g@u7*6A3 zyRAY1prM8*gpG?n@SO9h93OTc#BqQ=!(2dspJr7!Bd7f@B;fjL=IRoX*e7gBygDnv zvx4Mr?rt`BSXFfTLKPNyQh1sONvMpFo`i-VfDQdyt)XBr?4+$PI8{gYw?j4g7jH!X z)Ag$}8IiL;o*bzFcFe?I;-qnzZ3GLa*k=Z{KVVsOX^h6y0c8HK(l2SV@;4Gn=eIW4 z1fe@|=MF?NQ3a>s3u*Sx@bV5j>pu%MqDe_>Pfk2422tTBNT?FwuwGJF<~o2#8yx0G zW^Gf%zQ2u2&gv{fI7pLQsn&V%1^6S?%0&Oktv#j+JVpq-GhmOzuge&2v7PV-xyZ=w zj@W9fgE-R&VzXlk3JL_~P5g`F;(qLnEq0Dk2U!TGn?=Mc(r#p9Ma1kxuxgN>nc?+Y z)gK0Ea~9Ca_TH&Ibk|)WeYIfp;U|`PqBO{(5pn!nPI_1gxL7}jyoKbLQ6#(!L?(%^ zc@@SW2F((5Y`H-tZ#?e1F1 zeEsf@&$`hbv%;NCK+uQx>_7Qqr@eg}Zk7RBD4_)Zkp_B^8gai-#rMz|<`p@Du!Sie z)dtEDbXPZ|&&L)xM-Riz4II#5*sBePkUQr+AioZdw$uV#FbCN35$$z=9+3cOZaZ2w z?J2!AM5et#F7dALCB+txuuOcW0+Y45)TiK3HbSD|GG=`9`XPODr(=~#ZTe)vhsd^0U3lADs3#DC43Hus&AW&$ zrCHzlQYG7=e6Xl9D`z(UOME0BVt59=VQU#8&G%G-XRh|2a|&CFPkgi+uk>QE3jYLf(q_I^)I9M59o8IV_Lf3Z@_#*7%KkXh`K$Qo*iSSFeAxdAcX+Vj#fCNBQSal=fgYP;6` zFiQ&sg`tKR0~6bIbWAv{WC#>8XqqoL73aWY`-sYfW1iU}a0f7X3;gH@ZmnNgFHWUq zgCjJEyXKk)qHwo)Nji#_j0`faPUU_}dPj0laPi5@OmE1m>uOARR@h#uFzN8{2&hSJ z(C_;5F*4X;Z8Z=Fd0H8_XpCX1KFCimc0gXvI6Oam0n+TGrUM6s>1aEL~mt2g_Po?#siX!>%tCq_&9au6M4?mPI|`;99MwsVVL&LeMrh?#BwoMyPc zn05)hJpsXv?t7h-8An||b?V}Bq;+JOj0LM^vbof^&FlAtmnIs`=onogep!%SqC1_~tV7B|WM+PrD^VT^3l# ztTqHWN9?tlh4%nC$T4TdCW%aWsKYx<#q&0l)a$WEXZl8K5Uv%g!8U8~ArbBjhvc)2xz4#E|s?^#% ztv`BwP|+@EW+~Z>Rev(JZDvRQcJGKNms^_^ENO@p%$UEl75*(ywWMcDZ#!f{vgna> zsI?cSbg>hR>*DrIl#33SPoa%Ip9+eb2yl!OqB|#=3vK1 z7MK@zO}52FJ~V}1hLzzYmVXOEUd^|4o68_>uF}HL{GV&m3ntSHDjh96q&g^0 zDm|~hSVib6M{{GHx7t019V#>A^JFsZbSPH!DAl+V4*vjDY6DHA$calh5?g=yQ?X9B zPg-t!M_-{`3~*@|KdHqjd^aeS?>*BaSRa1~A|;;1w@<5f zY1_E5Tyg&Mtz(r-qQBOQ1)e7ZXeqqe4J9u3^4!3hZnGN}-pFTqH7`PLBcOiP)MndU zz#jk=N8SA4s*<0WC3akYZZaE7QA)nF1hXE_IC>LUMZR)Jre8BFFs;X%?Z+PNT_UJz z>qjeQ&sKetNjI&heeI?@UUM$@n7Kqybo?(EdH=HAU8J`WHZ6NNb(RUmeMz%nuxLVmpUd^E`Lm zi`|f+9&?KtA4o2EPj83s2?4TmLf3;1+o*R*C+@ztHakn0I!{oJOQ)g&53tOxCtu&%PA8 zw93CberTsvl6!l>_&C?Jq8}-D!_M)_#Boj#Lp3KE@CKqdq8rGMz8h?7xLpqL;4RLX z2vT4c>SlY|&0^w~`>Xt;o_n&XvcT0C0knuhj(q;1TI0rFo)ZM`JVpymL)18+3L)u` zprd({$W)Bt#z$dbQ4;wc`-yHID(3Ird(bq=6vwmYd}J;B{uuQLU&fvlasiMC$G>}# z%~luGgHJ?D{NuKouPV+I|AmR9j#sQ!3!b0mBkw=Y>Y)pG$?}t$BkJx?VR=~KuMFjT zE$rg2B{Q=)k$i3VDSV~e{jbY{?(X$qM-oI$gh-A0o0r*y5(bJ|`y7Yt5-OY(j??Lh zMPE$BMK?!Rkl8g%Mo~DSBTu~cs+|)<(ADCyYbTy=`Ye65zV4U+px7=(#E9fxfF2{o z@Ja8#%cbN^5A3;WB@h3xsJ(QjQHi{6N$0iqf0ISP68J%@QU4Zq6nb*xje^ktxMs^LfjC!@o@@G3HxgMj(~|EMGE1}%?glqFG>$qP z02!o)EW;FeTz<^I#^&C-`TD||gZX#5yE?_>JB}bJ_*dGN#PO!vt2l$HcCN~iSrHJi zpplJBo|dZ}O()-Y!SBpIv?s`!j_&UMDOXD*tyRzSzgCt1O;ZWm8AK5iuEipNA!yOUq!4SOgaz}|`&ZX`~p7s6jakpKR-Tpg$*<>2qBeGS~x zZk#OdVXEJeZ-R!59S_2trgR~mESYLA+@JNj8l#BT4|LoOc4OSkiTRQ$&Ug0*?&s2srlUST7gX@kFTb#Ng_^SA1ew3ehFa3?V>V4KdvE zUL&4atq(dKucC;DiS0vO;q^DFkKg!jCo%8DPK+6i!>TunpO*di*v`)kQA4Z)FL)-AcU13VnWa`HHyx+ZPzun8(ZkW>ByHgT% z>t0Sfru>9-`E-Z1cG2Y%p+evgf74F?fZ&A5l68QwJO*S(4&ndyBQSekXDL{K*W&}s3ZdkG zfHsF`02cYtL(rO=HN*i`k5yp$+3DWMe^25FO;6r2;r1TDDeQO7bD0u(472^^RbRNk zK!kW+{R_t4#vq2rfapkH3fKwi*aV;s7816~HB81+Mpu)-TD8A@Ch=p;qhG<1(O_yiJ+Ph;y&k&_Y+ ze_WgoAb9*)Miem}dHsoxZ844!!}z(S3Vq7aYYM_fg)^mNHMB~8XKslA?cY`&PI0D& zu>rpQaqCBf`T9bw)Z7O+10Wl%{U(dL6%R6LFa%6?!3esA5APZMJC) zA^6N8d-XW)AsTPUS{eYAy)7)M$wflb5V(MuaS0qXc6w;F$#Er!`PR1LesDm>Fz5exIkK4Zs*ZTJ51F~Gi@;2o`< zL!24ey2<8FW{z;51GSnR+p78w%Rb!guqOq=9vg~9%pfQyrsD&=wNKpK&8sFube~e8 z;BZ^}`1#I+d*UQ>1K96ixFOiw5;@vae1AaN)}Qt&ws(>c3!6Srx7yFm)G@MfS_|Z8kBEuy=I0AhV3A}Ar^V5WT}a9uk|3Dq)@LH}vH}W$DVUe$;KeLeW^;Wn z>s7-1=4QHE6}(U*-Z8NJj$x@R$ujU#uS0Wl4L#kP`w@y|cLf$FBph0pMU5k`yfGS- zYK^~|9KLNSYo{?-?ZUxvwcGvg6J@W=)9)tD-00iCaA8O*b#xCeiwUG@s> zX-tzvJTp9QJ^KGH%LHg^PUR6hLz^qV>ELaqAz`pJ?CfkhaVW0{H0Q%ho;n3|#RIs%>L;dtp1yCtu$mx-#v!imt6ThPF;y+59CIXh4f7|2hjNYl##_D~P(M9?j~ z#4a9PT>pJcKgj)tkT5`)8BGU>)IkgY)PiJtrrS5Wq$OZin*@P+3W?1_k~6Q-J9L)W z_qP=Qco!SZkqf8Gyc@&8USFf#&3<8cOen}>BFJPaV4T{vQummF?IrBLRJFLIbS{`& z*zns=RB!4?OU6fqqQ~#uP5Gsc237hpFt8gh+ipX`9k==X#cO?MDj)xYOBQ^`cCBHg z>%(zN_gF_q+7r9MVb;NY5^wJKlw7IW89w!zj}jfcgED5f|7@xdojo}vs>|~Aa=^|F zqp)9CH`q68zrCrDaOad=43~Y%L4wksn)_Z{8E1Hi)|pbf#*}v<-|lDyv;za55zh$t zJn>>Nr%Nyq&b5N&zn@uk2N*catr41lSwrx2b|4mfu1ei_r*fjfb0qQbV-VI`TifxR z;H4a)3bbyk-vvYiUIyzru6j1PJ)ACQVE(5{{x^nmJtzutW1C3?*L)Ch$ECH1Nbt;# zY;5W2{eid6JpilQu{(AkJIy9;Y_mGGC{K-yjKDs5UUE8ARx)l8Ngsje~ zv&|}$ln?1rM+ga7>Q>eTA!e!$KKX81(In-~?^b-$U%#d7rArCi7ZTz6iiCpJfVs@B z7gYpFM;)t(+hWt|T>2^34n@aR!wo>gMh|2)o$|@|k@uJ%xemnGr^$6VK=y&+zon=j zd`_(Y)|=hNAIaPV@e{Mmb-ag24CMYo-UDL?-P*U)OBgR!IX>-1N~3t)Wa=>tY>vRa zW;^tO0qlT0T+wdO%sMI$%yehhPQjGL;!5cg)`OJN>qQ@9@*FhXEcVdNe9Fo9;*IW2 zKc={S?v_fI&(fH#n@O&S!r*;_R1gctVs0j=<}WXYdvn?QoK=0(+A8h65@yu5G?~yM z){XTqj!B;1m}-*U!>03!#Kb0YLGq5y6D~wNI4gmBb6;=YYjdtcpR0HJGGHsGV+TF; zng{4StB$F|xd{^^_Q`43Q7VV5UNyDcxA$I!^MnTCs4;&YSF$2byI;mv0Dj>|>G4TG z6*%(r2pJWE`oSfJX*9yn%7^QfVvjEsG4eu&P_;Z2TvJnGd!uj0n$4IRfiq8i(0NJv zkFF8#?XeOA3;&YtjI$QQYz~QU<2=NMBZu8yNiE!MmX2^e#o8H@+~${PwF0wSFiueV z-j}EG8p?;2-&pmm4@1LeQ6yN%*3)g9&Gh!Z2k;MP+1Rx1Lg(fX5gzmuAiKm& zv_Ih@-RYVjS&t!GDm=$K59Dj7)+#DE~#z7(j4UX#>a)t>%Q0s zjsMvhhY)(D9rIhd+x0CE#=PM@Q68#Kv#7hLE#p^7Hmq=U$B*bpkWA|E<}!N$9-wy_ zih|Q=7*a)n$aeb|SI#xKkcZ8SL5#H}8n)c*y^cHPRgHZQhHOA{l8u_s7<8nfI^MH? zE4s~&q)aagpywC9a61S$!pQy+bC_`g5DodLYx_^T{Hy%Aty%sa0&xaHScZf4)DSA} zU+g^vA0H!f;%T0FK^eACk3=>URLVN3r}lpnDx5L?&lUYYNUi=d1evf8AlmX)A&4*= z5e92*2(*Vt#K7|rvl`c2WDX*m!FK$>R+TfM*K)EUV64oDP}; zQ?S?{Z9Y^&gsXlM2V!bNR`ia)9qCvw5NlA7o`f~ZZ+pZ|`LW)6&Lg(+S~%!FS#n># z{d5%8Sl((l0-L__kbS(*N4gifU~%%D8Rc!^-9Jq`8X4zjbs1#A-$c#G-UZZr#7#?4 zR6$|=8My;69@6>*@LqawkC8+NAQuP0Wy!rpL+q~*01Js%xG&Knd|=z)zj*(xT<28Q z$5J2zkk#VC-3EjacFCE72YmJrWQwdf9)v9ATaf=6g_!(c71th!EHTws*?__@!mtf4 zkXeym=#4G#QaZrsD{1|KZWvnRk6I@QR(B1d&BYWX`_ppws3FPJB1Q9syjt%rHG*x} z0T$UFs#`-?XvigS6foDh`g0#roeq6bQXfdJ@rwC=sQ7Noc-l?oT9CU7Ddf!KDQ`jJ z-y=6AbBJy!y7+bmcq99Y@2JMc_(6%N?&s5vzniWaUIB|kzlD^-98d)TW3Uo6nhjBR zK#p}+h)kig8-OodZ&#p?8wA0z9b(3Ue&ak_R5HZn)PY)}Ak7o-Uw#QuiBCu-R6dyh zB|(~j#6&^BfQ`DJ`_9(Jd{&^?afBue+6%xz-5vpB94V?8QCl&L!RR^N7Ax&^Dqw3# z5_~SmV!}~Z?_F>My6o-(`!4CZXdN3(7>|HHykq-y#&|qDur)Q$=>tfA3}cG??N`k( z<#t#PeQ%g>s%I)4hHVfTM6*Gc6B?G`%t5CBM<2d=9hs;+&}wnMruT#^L2o@@3Ra!O zM37~y!QHIQU%JwE^;4@ACHKQ`WMfoJG`Vcd8Bv=!o<-=SzD!MyJaF?dTl)hyZrI@O zhd4k9Q12lC@q(NU&HG!-~EFe;4q#-}TW3Ng#lGs2<7RWPR!Ng?rO~JY3-tY;| zo_k@`&Z+WI+Au84mH~t;jnSq~tV6zwMxE~bgv2oC;Ic~kO3JjMM|_mr--`CDzt^7h zDEzf;)7vn0+^PFMuJhMcTCQ05Nk!l35$)XRk{$P5(e~J}>qvPl^PDKwNdsj-a-Zrr zH;+-xK}pyfU+IKp9CDod1o%s9v<3937TcJn>WmVF?c>_qP61iVelIJ-&)ytXke;$1 zpIMOTH~-zI-?Rj{nIqT^vD2l9XAv16-9cybqV-Djgz9G7^bo)E27V>ykdDlpc)zPj zgD_K6Ztx7C4ati>1!8CuBxQbX9QNFO8LjGBgJwVMS|8%Za~U?Q_uV+TDQn;uc85;D zQDdBwkY(_6Wy30J1=KZb@6HrYcfg_QioWuj?^L0Cgp>Zw;*kj zke%}}RqKTI3h83u0H}`hp;o1aBu#{ESAmc(hd+eX#X`v`6jfmg1nV1(O7G(!_>P$p{DK>{h|5y7e+&DyF&N!NJX zXAy1eR15Z3O8kM`_t-T&o97-@hhaq5p)&#w6*vABpx#ApnOuB=_|S@AIb(GQA`$sR z(xIf`@_dzt-8vNaKbwqesqd-Ro6y~Jov@A!W);JEfjP%Bw)0eG$BgnfYZ$5-XjXD}s+T|@kbM%7)<;w#Wi8Cd~{#%Q&s3JT}@i&yl& zXtH1P)7doPU@l&BD%rf$xqhyX=7THTbvu({Lm(+*0yQSM1TEuG6rBnDx+{law7Iat z+sVRhFL0q%F%j!kQL29X-42n@DpS&&^}YDgek;Yr4KYT;6=2`FYujMEK`KFCL!CAT zx!AkzBfRn>hh-N(ba=>*iPzYouSJgTJ+Io3PDbBP_FH?@c(wQ7>To`@m&FH)AH%~a z#k2?Ekhjoe@ePy-8}p38{;KH~Cn>)$4MsJ8dsk@$FNDTgs1^C>*4D8w1f>0xzso95 z-$Dib4indm6q@75m{YkwrCh7mVl^S(B|O$GZQN%26oMVkuWL`aZx^^NjEyFuspcFT zrY|sAz1sUN9@?93tB`Hp_yW{!};T0 zy;7_G=N&X*%lnNf{cTH%gm&Jzdg2wgJ6I_btVn!#n-ZGGBu~nv!Hpk1;FeJ&dzvgh~qm-IVvKkW|Sti4}VC@-6XNB62jUtbXm-HScLTo;%VzSOs!Ns#1^lYm#EqtDtAU#;5$N z<-+!)R0+C2QJB7A9Br5Q3LD%Ne3M^MKjjAdh0!lP;?nnX#85S6{|s71qF&W3zRrkz zspBf0D+eZ1kxLmLUQec`yg&(){uo4F@w40>c&YP|DJM7R;ke)WAhK4RUP3w|l>P{l ze{P8j909c{?{s?7NN?%y;~(0_(ekFeEj;pE4SMZKhcM5?-&Sa|pAXj=sS!AqIKZAm zoXJWU@rFV09$`=7im|oVAW} zinnCHQg|?9$8Hp}fo#$JH9vlL{Z`t7YCd&+`knqwy=Ya2tyP|2KFc^{xnn^ZVLQVC zovC2TYtQs?<|Ev$A(7Mh3-9LtP&U&-GEgByk^w8_o>6k?&K)(B+e*<^*avmLPoH8? zDHox=_jf5fwKVNB$&kpZoxV`JKFoOf^5~lmFSXUp4C}{^uVy@qr3~2ip-*d258%S4 z%`=2}w`~Lhv&Ib2Zq3^*8}0k!gDKhT>eEJeQKT#+ry6>pn<~ zVl%bsWGJ^>alABr!(!^6L|xZA+LT;suamuFLY|;nT1_y?q!|{snzb0x4SAr9qLWFQ zQme|;li;O)m@zj17~zenRyBO61#E3_9JfurSe5P)(zelQYlW}RTt5CL=yfAhd-!6DyE@0X>(KbMEG41z_$9B<#9n__a zemUB!dVbP-^ak065XPVA;#S|iu7-*2_1C+kj>}4UPY%kRZO3G3+XV2f_^H|OdflGm z^-~}wgqw0e%^L08F-SD+aUwY8;77I$Opv#%Y{Dn%a<;Vkmk@TB7SX~t1d7xPs4?Xh;)>h1B}ohhA3yxw$1 zYT#poa&&6sON0En_FVcbnHr`Cw)IfWoC_&W32YBX1+h3CVq}tzyY$SAT;eL``?120 zXYdbmHWL0`)J$t&DwuW?y=l49bMPv5hqYFxPrBF#v(%$*z^>a_bMZ&6(B1~yXx0F< zB7-|yk^b`(R8h^R+(@F%*PX}`TdyHeX~Cw8_6mhJCiS0bJr>16DhH32cmT4^Jb9jk zZF-H$!SAz^#_Gv>kLS61dwi=SmGk$}yx46SDv2qtg0AD0RSgS1=amVb(_+7f9U*EY z1gZSO5|7V~W7cj7nI;=k7CMV(d6a6@46b=`p7viNVIE(y_+iUKl?#oY%?qWsxN7U; z8j)w6N>VdnwY=HBxx=4E_r8PyT6C&I4PK^$9EL8Fj-j@i#bx-q! zt4{GQd^8)B*%7jDHEL+88BC#jvAeFudAa7%TU2x%JwJZkwz|eEx8`|3q8yE7y)d+7 z@utZF6KeXW{vbI^OB`>XbLt0!WSMpZl{tLvnL?xpJkKZepI5e>A(0J!s8TYhp&k!j z?izQ=qwBCzaXqFts7exNdahlD$6ES%N$Hj=F^|)pxSi=m3)j}yWD6M2wk)-C^4i%> zzcVP4Rd$Nx3--bi87sU{n#7$b6|R^O=?ux|UtAM;71Q)I4ugr%*!G5zpP}qrd(LE40@ot@aklaET_cDDrBX zoeAsDenJyl782@l+_2+1zwPM3&_nrZ@L+z%KRk~%ArUzGrmv3j~Id$iEJ znl`Q$>ZVcG$0c4H&4d|cF$LwCl+$i>Zn3=&Gt9-(={6gA* zv-_G##dfpsq%+B*R`eS9Nj6%BWv9=>BJ^=3+$5QPL}nZq{tr)s{;})hqm5lWx}YF> zK{HOL#w6>N&32z^7m>YVIq1=t_A!e;WVz9Oi(}mjasGGG-Et#zOz&-f%^K1rkc~+i z1~FB!gu)+aA?fzNs*Sx)xvGky+Xa-=)4B2TWZ#VZyt^}uZ~AUFP%Zs*ry^~M^L(z6 zs#1%Xdn;=JV#lN7#1=vHB^66_!KU3g$HhQ(E!Av#X=*L7X=V{{URovk46nM>%C9-m z)+^3|=L#3fFf)_sWNst#N6#RR_vhQ>xNf(Er4v=?m z4F8f7wGRKrQOwM#0S~n&#M@87@7E@tZ?)>Y57bUG^x%L0la(f6B5)s+SXz?`{HQ)|#;_ZmIN#}Eraiz`wCFgQtDfXoI@|v<<=W`SiNp=sp1#jVNtGJ||TnH$jMW!)VtqZT4PWwot(KB-!RE{Y%oHHeJ&K z|BLMJ*>K!>ns1bQwDhGa%aTm35{G+LO@&Bj4U04;a_ZHw_m;^A$z&x(X1RVz$}xh% zuqQ^UQ{FJEwCxCqW~A`2bNXbaOKw~4kSbZJhw}9-XD~^NbBc-Hhx5VP>4BFScMPUZ zGH|&?s!yp#2h%rKUsGX)X9GQvH5nrhV*heC3wv71vhQHvNavR#|4+n~a8GS@YEnN&pR=6I zftEVhlbz}4FF+BrWW5~j&)vh3(PmF}GMr+wc;nOP>-M&g8%?gn?qw6WKJ~hWP;hd! zHeKZMY7+hPc%!mL$mJdEta)RoP-I#lQqKz7h8$6$(bS-ldE8|XE-aNNwF_}30tGYdLZzFPATvt@L z2gt@Nj-M|`OPDPQ0#c5Z4_IH29$=wYh549{K&!dbfP9 zGsX(@^*wq2_pql)W?rMoNtiW#;&wVMsbr$JMsd&Wa2l6k;yKf=0r=+d^~B)vt&uJk z28l+jlwwVFo``iCOU|Ue-*?Knt8Z&g>Nhmj*r>anv>&bWkHG3;kC((l%=c$%l?D%Ks0<~L3>KMPIHjuP8L zgHq|l1MGkF^^~+3ql?q)*?TS*(IoYowoUmN?r!`Mv1a&TKKZc;qFAf zy26kMfq@j8Ov@_-#Bd|`MpnCBkC5o;oX1BnVPkLRQ9hZA zK6}n4dX_s_;#Alzu|>b4%X5N%0@Of3HSKgtW3L%{Q9-Hc5RQ6|f3Msu{Zb-;L9c8M zzt0nMtK&;Tybed{S~`4C-QSM#0*iu(^EuW2&_5`NnuI}GPHmhd9TfV5>~A*cUAZg8S$ zvrSnWF?gZW?Zk)%P^Py+j zHJ=GZhcY!_*4)yl-D~!iohZFdlu<5*3tc@BT&^8l&%4y8z`jHhk6Z35&d4etwe?uo zV7bcYE%iEeo3iNpEx&4rqhz#yFQj)xYTUdGZ6Z^VBiElSD_%N*@2-)$oc$y%gX99z zYJZ>_DT+}{y>;5H)KbbMbm#*kO($2AZSvBlLs)0WbN-c&0I%SAyBUeQ&RQvNR9YWVJ75qJENnQ|M|J9w*MF$#hm9;s;|f z#nO?nTe|K$of##CtOP6Kohw6$y_mjh|DK}>$Ndz#qDPMvYDEe<@o18_j34U(6Dyq4 zQenH-M4(ys+?TKE&WM9uKKVg_%Xh83AF1=oK7NE33`!$*2vGDfW>L{z8aHuf@T zyJh4R)Sz;Y4KQ<;hgE^m%YwHSpFVAq#n>6@an8^pRQYgG3fOoWcKEGHt}GhQ7GhWV@dvNes8m}?1LvQ$ILea z+TQBbcvbmPKBcYAZQ)LP*La;>n(BJ7%-F4u$KVpAtYjr{32=ZhYOvD(_W)NE+?bBR z8A@ybB99C~{KKjP`-J_u0et@~tD*yVV$d4ahy_-%v#{&!NmOdm3p=c>C(Wr;!0;`t&OH#kMsRGq^zC zx|0G5&-qjY^;F)-BG8l>1PnEIdbCoD6~a$OfuiJ9ye9)1*pb=gJGqfgb|SdXMm-|% zg`4I6T!2xC=DRqCDlI4Nw=Q}0F`@%0lPLSo!g#Ynsn)~9?x_*!MVi}@`zzmgz!|hD zJD?~32mq5Rh$B$Cex={K<5UehxWAk>KxHFC{q87Y*)riVWPoPE0cZNMW1!q0^Kn+( z&TSnAC+4YiaTUbytl_@J8krWSW!r`edR_uOOo;@>Jt6yakCp|fg|}RO3Pp8I>8ehw zhY;L(_hB#%-Zp8vTE%zcrd+8*-D1nhF`f+>KgFt07$mI^t)u%yotDw_GN8<`J9 zF?`_~bPiSWlsyzz%OT0sI`2D8NW6en7 zSBd|?K=N}!u43Z?b*h$DJ6Yub)0oqo@X9C!>{}N{Z;VWXrIQQh(k=G&N`(FP`Z+vo z3On5nf~{oVFY+~MHCXVmo7U*BXh`h7_9;haP zO=2-3tH;yIAcJiuD0Rk6s$g$>>pK6r;7| znUb_Z=@Lw?Up7?xFDl0%%`d}Fx+c#5>}D{X1>N$#e{{gquuBCOlj}{k72j?iz8e#@ z6PqGYVuSQr9OchGjjykaaw)p?^e!ng2U7;ZA0r_>HaNj!=#xIfKrrz3L6Xyc{t`b& z9Wnz*5bhMXWs@RBXgRc--4KLH2T@^Blezy@eDhb{%yR%;YIV#O+=vprsz(zDh%I_^ zMe!3REQBc*SWkCu>J*HOGqe(F4Yn0zSz3V2t_*DmFN!l8Q@F1FS9O~z3YUPb=~x0S zUDeG2`f5Z!)ebfGJ^suwryM#|wx(?u-LN=gTyI?9dY8AlVg+Yk~ zAHy8;r>~y*Xd*Uua>$TLCe#CbrT*+SuW=HXiR1Og^#spcgNX)N<&lTI;XjHG6fK~} z3yMT1Fiahs`FYcEMPf+-!Jb#QbFd3|3_lhqtX zvg4a)XET~Tt1~PmnA+xc0XTDQx}tv`MS{kuAFi#58L>WCSES=!61|R8KjVI!HIBR? zzYr1?4UEiIdo4e$4NbUIAANP2ZntBVmm<7Mnunw&!i$aU+V>g?+nZX}XtvtVE+ zvRq?V_8>3*UGlbTdyauH^Zd8(QE%Ox!r%mqt}5}Ob(-5b4uX2r5fTaKIPwDn*8IL^Lk;_ z?143p#2#+VB17~?N?-VX1wR2nsy5pxh0C&(J_2?ocHxmb8*%=oSJzN&`kU=a@L5`C z&VF{w{pP}Sk6m1E%OrC4FLjy*hyi}mkrVN8f17SU@=7ZyKL0GYxNn`;@$dHrPt8L$ zrRhKO?bK$17oJcAICc{31%pf((q>#nVfbT9&Ae9-V>|k}T+huColQ#~DX&7Q7u$y~ zcf=u0i^Pgi zVg&<>)bw+#ciOXY-t<<)8WG-+t`_|O@m3{CI>=Xpko?kVecDq(w+Ms+KN~acWPNwaAaoc zLZ*$2aS&|`i%;2?o<#?7iAO@UjFy69TVazr}=x%_+R^+H8VrO|u zmwz@xXoM29mR(Ftw5Xh z3KUC>hG|@yfu+M-)tYD=@>EY=JtbwFLVd!zo~jf>^)-{=Eq6es4>tA)c{Jri#xd(o z@0LWN4*W;O6falAq&cL7U+F!~o~TP+bUgXnzTb%VNAvDS>&h5eUhp-VlZ6!B|*34*b|Z9N!Fagh^n=X$c3X*hBgJ0ileT) zLEWO|BLE$sUsqwZMeRCz7iByfx}{vBmQDj_{bOtHAp`jTW7Yk~)H}q}LVtL|IkUa} z;T2Sp&%*CCE((tUmYKqQj%T^dW0u=_p!yT-WpuTXe9ZgeyZj~L*||jF2k3xEug-^u zmSW;FBVlm6*|uXNlr@BZ)O{H#%;=C^m0L@GpD*LU!|rJzPqi55wWulx>*Tbtf3BmU zn|ed`4(A2jw6mFx!V(n?TLFtbyR_J1jn$okhlzg;*|%G-9?o+b(SJ>V3&r7PYH(7}qF| z?W8t8Je*KRm(kAZpdPCKyJUybxud;mY`z@J^MZeMb;Y)~&N{kI|J#kNh7g^>|M`ZB z6DCVj%^eIbq1oNlwOpRi2s~~{BsPbzkY`G&cQqLucR82PV#jIs6odP$)5jsz(V`&O zVeWlR^2Wz|eKS`}I|;q|zOxCGz}0G;)-?qszR~X=I092=P2Y0igE#=yO;nj5d7Fuk z8uBwR-!4nt&i|IZXLVDxV^lR$nsG@oe5BgBWik0xcg|`r3qieDv`q6);x1)0R%Zck zF(rg4Ah4b9^<8oyFz08d=gl=C>oQFA^^|>)PyVSgnC`rtBDq(8c0m=k9Tm~Y77N*K z;rE7DUjDW3;*(8D{Pn~Cdsp`BBgirUIkWIL7I++xV?$=-1&SQ!?MHY1`YrDN&mZLO zR@5n9``*{zk4+KQ30&p) nuTMUEq~+G|p-jWpbN6?m-kR-()~gO=BaXYE|3|5|Rmgt;9qU{G literal 0 HcmV?d00001 From c8ef5158759ec417de111c19698bdab2e9886d53 Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Thu, 30 Nov 2023 17:55:07 -0800 Subject: [PATCH 011/403] Add wizard for updating provider --- .../messaging/providers/update.svelte | 272 ++++++++++++++++++ .../providers/wizard/configure.svelte | 15 + 2 files changed, 287 insertions(+) create mode 100644 src/routes/console/project-[project]/messaging/providers/update.svelte diff --git a/src/routes/console/project-[project]/messaging/providers/update.svelte b/src/routes/console/project-[project]/messaging/providers/update.svelte new file mode 100644 index 000000000..7c75c8bd5 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/providers/update.svelte @@ -0,0 +1,272 @@ + + + diff --git a/src/routes/console/project-[project]/messaging/providers/wizard/configure.svelte b/src/routes/console/project-[project]/messaging/providers/wizard/configure.svelte index 7f1fce5d0..9a6dc02b1 100644 --- a/src/routes/console/project-[project]/messaging/providers/wizard/configure.svelte +++ b/src/routes/console/project-[project]/messaging/providers/wizard/configure.svelte @@ -9,12 +9,27 @@ } from '$lib/elements/forms'; import InputPhone from '$lib/elements/forms/inputPhone.svelte'; import { WizardStep } from '$lib/layout'; + import { onMount } from 'svelte'; import { providers } from '../store'; import { providerType, provider, providerParams } from './store'; let files: Record = {}; const inputs = providers[$providerType].providers[$provider].configure; + onMount(() => { + for (const input of inputs) { + if (input.type === 'file' && $providerParams[$provider][input.name].length > 0) { + const dataTransfer = new DataTransfer(); + const f = new File( + [$providerParams[$provider][input.name]], + `${input.name}.${input.allowedFileExtensions}` + ); + dataTransfer.items.add(f); + files[input.name] = dataTransfer.files; + } + } + }); + async function beforeSubmit() { const promises = []; for (const [key, value] of Object.entries(files)) { From bb705cbf8a12344b3cc731391b287163e82e7701 Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Wed, 25 Oct 2023 16:52:35 -0700 Subject: [PATCH 012/403] Add provider details route --- src/lib/constants.ts | 3 +- .../provider-[provider]/+layout.svelte | 5 + .../providers/provider-[provider]/+layout.ts | 32 ++ .../provider-[provider]/+page.svelte | 12 + .../provider-[provider]/breadcrumbs.svelte | 27 ++ .../provider-[provider]/dangerZone.svelte | 45 +++ .../provider-[provider]/deleteProvider.svelte | 59 +++ .../provider-[provider]/header.svelte | 17 + .../providers/provider-[provider]/store.ts | 9 + .../provider-[provider]/updateName.svelte | 51 +++ .../provider-[provider]/updateStatus.svelte | 367 ++++++++++++++++++ .../messaging/providers/wizard/store.ts.bak | 161 ++++++++ 12 files changed, 787 insertions(+), 1 deletion(-) create mode 100644 src/routes/console/project-[project]/messaging/providers/provider-[provider]/+layout.svelte create mode 100644 src/routes/console/project-[project]/messaging/providers/provider-[provider]/+layout.ts create mode 100644 src/routes/console/project-[project]/messaging/providers/provider-[provider]/+page.svelte create mode 100644 src/routes/console/project-[project]/messaging/providers/provider-[provider]/breadcrumbs.svelte create mode 100644 src/routes/console/project-[project]/messaging/providers/provider-[provider]/dangerZone.svelte create mode 100644 src/routes/console/project-[project]/messaging/providers/provider-[provider]/deleteProvider.svelte create mode 100644 src/routes/console/project-[project]/messaging/providers/provider-[provider]/header.svelte create mode 100644 src/routes/console/project-[project]/messaging/providers/provider-[provider]/store.ts create mode 100644 src/routes/console/project-[project]/messaging/providers/provider-[provider]/updateName.svelte create mode 100644 src/routes/console/project-[project]/messaging/providers/provider-[provider]/updateStatus.svelte create mode 100644 src/routes/console/project-[project]/messaging/providers/wizard/store.ts.bak diff --git a/src/lib/constants.ts b/src/lib/constants.ts index 52d2b999b..5bc06db41 100644 --- a/src/lib/constants.ts +++ b/src/lib/constants.ts @@ -46,7 +46,8 @@ export enum Dependencies { MIGRATIONS = 'dependency:migrations', COLLECTIONS = 'dependency:collections', RUNTIMES = 'dependency:runtimes', - CONSOLE_VARIABLES = 'dependency:console_variables' + CONSOLE_VARIABLES = 'dependency:console_variables', + MESSAGING_PROVIDER = 'dependency:messaging_provider' } export const scopes: { diff --git a/src/routes/console/project-[project]/messaging/providers/provider-[provider]/+layout.svelte b/src/routes/console/project-[project]/messaging/providers/provider-[provider]/+layout.svelte new file mode 100644 index 000000000..944197a93 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/providers/provider-[provider]/+layout.svelte @@ -0,0 +1,5 @@ + + Provider - Appwrite + + + diff --git a/src/routes/console/project-[project]/messaging/providers/provider-[provider]/+layout.ts b/src/routes/console/project-[project]/messaging/providers/provider-[provider]/+layout.ts new file mode 100644 index 000000000..afc8f83ab --- /dev/null +++ b/src/routes/console/project-[project]/messaging/providers/provider-[provider]/+layout.ts @@ -0,0 +1,32 @@ +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_PROVIDER); + + const response = await sdk.forProject.client.call( + 'GET', + new URL(sdk.forProject.client.config.endpoint + '/messaging/providers/' + params.provider), + { + 'X-Appwrite-Project': sdk.forProject.client.config.project, + 'content-type': 'application/json', + 'X-Appwrite-Mode': 'admin' + } + ); + + console.log(response); + + try { + return { + header: Header, + breadcrumbs: Breadcrumbs, + provider: response + }; + } catch (e) { + throw error(e.code, e.message); + } +}; diff --git a/src/routes/console/project-[project]/messaging/providers/provider-[provider]/+page.svelte b/src/routes/console/project-[project]/messaging/providers/provider-[provider]/+page.svelte new file mode 100644 index 000000000..2262f62ac --- /dev/null +++ b/src/routes/console/project-[project]/messaging/providers/provider-[provider]/+page.svelte @@ -0,0 +1,12 @@ + + + + + + + diff --git a/src/routes/console/project-[project]/messaging/providers/provider-[provider]/breadcrumbs.svelte b/src/routes/console/project-[project]/messaging/providers/provider-[provider]/breadcrumbs.svelte new file mode 100644 index 000000000..5a3f26f90 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/providers/provider-[provider]/breadcrumbs.svelte @@ -0,0 +1,27 @@ + + + diff --git a/src/routes/console/project-[project]/messaging/providers/provider-[provider]/dangerZone.svelte b/src/routes/console/project-[project]/messaging/providers/provider-[provider]/dangerZone.svelte new file mode 100644 index 000000000..7befc15c0 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/providers/provider-[provider]/dangerZone.svelte @@ -0,0 +1,45 @@ + + + + + +
    + Delete provider +
    +

    The provider's instance will be permanently deleted. This action is irreversible.

    + + + +
    {$provider.name}
    +
    +

    + Last updated: {toLocaleDateTime($provider.$updatedAt)} +

    +
    +
    + + + + +
    + + diff --git a/src/routes/console/project-[project]/messaging/providers/provider-[provider]/deleteProvider.svelte b/src/routes/console/project-[project]/messaging/providers/provider-[provider]/deleteProvider.svelte new file mode 100644 index 000000000..e32cbf6aa --- /dev/null +++ b/src/routes/console/project-[project]/messaging/providers/provider-[provider]/deleteProvider.svelte @@ -0,0 +1,59 @@ + + + +

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

    + + + + +
    diff --git a/src/routes/console/project-[project]/messaging/providers/provider-[provider]/header.svelte b/src/routes/console/project-[project]/messaging/providers/provider-[provider]/header.svelte new file mode 100644 index 000000000..d78a0f0d4 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/providers/provider-[provider]/header.svelte @@ -0,0 +1,17 @@ + + + + + + {$provider?.name ? $provider?.name : '-'} + + {$provider?.$id} + + diff --git a/src/routes/console/project-[project]/messaging/providers/provider-[provider]/store.ts b/src/routes/console/project-[project]/messaging/providers/provider-[provider]/store.ts new file mode 100644 index 000000000..a69272a70 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/providers/provider-[provider]/store.ts @@ -0,0 +1,9 @@ +import { derived } from 'svelte/store'; +import { page } from '$app/stores'; +import type { Provider } from '../../store'; + +export const provider = derived( + page, + // TODO: Set actual type + ($page) => $page.data.provider as Provider +); diff --git a/src/routes/console/project-[project]/messaging/providers/provider-[provider]/updateName.svelte b/src/routes/console/project-[project]/messaging/providers/provider-[provider]/updateName.svelte new file mode 100644 index 000000000..f77b626ca --- /dev/null +++ b/src/routes/console/project-[project]/messaging/providers/provider-[provider]/updateName.svelte @@ -0,0 +1,51 @@ + + +
    + + Name + + +
      + +
    +
    + + + + +
    +
    diff --git a/src/routes/console/project-[project]/messaging/providers/provider-[provider]/updateStatus.svelte b/src/routes/console/project-[project]/messaging/providers/provider-[provider]/updateStatus.svelte new file mode 100644 index 000000000..f4fddcc74 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/providers/provider-[provider]/updateStatus.svelte @@ -0,0 +1,367 @@ + + + +
    + + {$provider.name} + +
    + +
    +
    +
      + +
    +

    Provider:

    +

    Channel:

    +

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

    +
    +
    +
    + + +
    + + +
    +
    +
    diff --git a/src/routes/console/project-[project]/messaging/providers/wizard/store.ts.bak b/src/routes/console/project-[project]/messaging/providers/wizard/store.ts.bak new file mode 100644 index 000000000..0ee3ba46c --- /dev/null +++ b/src/routes/console/project-[project]/messaging/providers/wizard/store.ts.bak @@ -0,0 +1,161 @@ +import { writable } from 'svelte/store'; +import type { Column } from '$lib/components/viewSelector.svelte'; + +export let showCreate = writable(false); + +export const columns = writable([ + { id: '$id', title: 'Provider ID', show: true }, + { id: 'name', title: 'Name', show: true }, + { id: 'provider', title: 'Provider', show: true }, + { id: 'channel', title: 'Channel', show: true }, + { id: 'status', title: 'Status', show: true } +]); + +export type Instruction = { + text: string; + input: { + label: string; + name: string; + type: 'text' | 'domain' | 'email'; + placeholder: string; + }; +}; + +export const providers = { + sms: { + name: 'SMS', + text: 'SMS', + icon: 'annotation', + providers: { + twilio: { + imageIcon: 'twilio', + title: 'Twilio', + description: '' + }, + msg91: { + imageIcon: 'msg91', + title: 'MSG91', + description: '' + }, + telesign: { + imageIcon: 'telesign', + title: 'Telesign', + description: '' + }, + textmagic: { + imageIcon: 'textmagic', + title: 'Textmagic', + description: '' + }, + vonage: { + imageIcon: 'vonage', + title: 'Vonage', + description: '' + } + } + }, + email: { + name: 'Email', + text: 'emails', + icon: 'mail', + providers: { + mailgun: { + imageIcon: 'mailgun', + title: 'Mailgun', + description: '', + initialize: [ + { + text: 'Before you can create a Mailgun provider, you need to first create a Mailgun account.' + }, + { + text: 'Head to your Profile > API Security.' + }, + { + text: 'Generate a key and give it a name. Copy and paste it in the field below.', + input: { + label: 'API key', + name: 'apiKey', + type: 'text', + placeholder: 'Enter API key' + } + }, + { + // TODO: Update link to domain verification + text: 'Head to Sending > Domains and click on \'Add New Domain\'. Verify your domain by following the instructions.', + input: { + label: 'Base URL', + name: 'baseUrl', + type: 'text', + placeholder: 'Enter base URL' + } + } + ], + configure: [ + { + text: 'Provide a display name your recipient will see when they receive your emails.', + input: { + label: 'From', + name: 'from', + type: 'text', + placeholder: 'Enter name' + } + }, + { + text: 'Provide an email address that will be visible to the recipient as the senders email address for this message.', + input: { + label: 'From email address', + name: 'email', + type: 'email', + placeholder: 'Enter email' + } + }, + { + text: 'Provide an email address for users to use when replying to your emails.', + input: { + label: 'Reply to', + name: 'replyTo', + type: 'email', + placeholder: 'Enter email' + } + }, + { + text: 'Provide the domain as it is registered on Mailgun.', + input: { + label: 'Domain', + name: 'domain', + type: 'domain', + placeholder: 'Enter domain' + } + } + ] + }, + sendgrid: { + imageIcon: 'sendgrid', + title: 'Sendgrid', + description: '' + } + } + }, + push: { + name: 'Push notification', + text: 'notifications', + icon: 'device-mobile', + providers: { + fcm: { + imageIcon: 'firebase', + title: 'FCM', + description: 'Firebase Cloud Messaging' + }, + apns: { + imageIcon: 'apple', + title: 'APNS', + description: 'Apple Push Notification Service' + }, + mqtt: { + imageIcon: 'mqtt', + title: 'MQTT', + description: 'Message Queuing Telemtry Transport' + } + } + } +}; From ae8da6a091140bfa608beb249b7f1554c94c9673 Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Wed, 13 Dec 2023 17:59:33 -0800 Subject: [PATCH 013/403] Refactor providers table and add bulk deletion --- src/lib/constants.ts | 1 + .../messaging/providers/+page.svelte | 76 +------- .../messaging/providers/+page.ts | 6 +- .../messaging/providers/table.svelte | 170 ++++++++++++++++++ 4 files changed, 177 insertions(+), 76 deletions(-) create mode 100644 src/routes/console/project-[project]/messaging/providers/table.svelte diff --git a/src/lib/constants.ts b/src/lib/constants.ts index 5bc06db41..33a02a160 100644 --- a/src/lib/constants.ts +++ b/src/lib/constants.ts @@ -47,6 +47,7 @@ export enum Dependencies { COLLECTIONS = 'dependency:collections', RUNTIMES = 'dependency:runtimes', CONSOLE_VARIABLES = 'dependency:console_variables', + MESSAGING_PROVIDERS = 'dependency:messaging_providers', MESSAGING_PROVIDER = 'dependency:messaging_provider' } diff --git a/src/routes/console/project-[project]/messaging/providers/+page.svelte b/src/routes/console/project-[project]/messaging/providers/+page.svelte index 203bf85c8..9ede84994 100644 --- a/src/routes/console/project-[project]/messaging/providers/+page.svelte +++ b/src/routes/console/project-[project]/messaging/providers/+page.svelte @@ -1,16 +1,5 @@ @@ -79,61 +61,7 @@
  • From 6e675d44d823c92f39790f1b4113b29584e2bc2f Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Fri, 23 Feb 2024 14:26:44 -0800 Subject: [PATCH 240/403] feat(components): bind open on collapsible item This allows binding upstream to detect changes to open. --- src/lib/components/collapsibleItem.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/components/collapsibleItem.svelte b/src/lib/components/collapsibleItem.svelte index 8397454dc..909453544 100644 --- a/src/lib/components/collapsibleItem.svelte +++ b/src/lib/components/collapsibleItem.svelte @@ -6,7 +6,7 @@
  • -
    +
    Date: Fri, 23 Feb 2024 14:27:42 -0800 Subject: [PATCH 241/403] feat(components): increase collapsible's chevron size per design feedback --- src/lib/components/collapsibleItem.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/components/collapsibleItem.svelte b/src/lib/components/collapsibleItem.svelte index 909453544..736f2fe21 100644 --- a/src/lib/components/collapsibleItem.svelte +++ b/src/lib/components/collapsibleItem.svelte @@ -22,7 +22,7 @@ {/if}
    -
    Date: Fri, 23 Feb 2024 14:29:28 -0800 Subject: [PATCH 242/403] fix(messaging): update Need a hand? section based on design feedback --- .../providers/wizard/configure.svelte | 170 +++++++++++------- 1 file changed, 104 insertions(+), 66 deletions(-) diff --git a/src/routes/console/project-[project]/messaging/providers/wizard/configure.svelte b/src/routes/console/project-[project]/messaging/providers/wizard/configure.svelte index 47222cc82..eba51e07f 100644 --- a/src/routes/console/project-[project]/messaging/providers/wizard/configure.svelte +++ b/src/routes/console/project-[project]/messaging/providers/wizard/configure.svelte @@ -14,17 +14,21 @@ import { onMount } from 'svelte'; import { providers } from '../store'; import { providerType, provider, providerParams } from './store'; - import { Table, TableBody, TableCell, TableRowButton, TableRowLink } from '$lib/elements/table'; import { newMemberModal } from '$lib/stores/organization'; import CreateMember from '$routes/console/organization-[organization]/createMember.svelte'; - import Collapsible from '$lib/components/collapsible.svelte'; - import CollapsibleItem from '$lib/components/collapsibleItem.svelte'; import Provider from '../../provider.svelte'; import { MessagingProviderType } from '@appwrite.io/console'; import ProviderTypeComponent from '$routes/console/project-[project]/messaging/providerType.svelte'; + import { + Collapsible, + CollapsibleItem, + ClickableList, + ClickableListItem + } from '$lib/components'; let files: Record = {}; const inputs = providers[$providerType].providers[$provider].configure; + let open = false; onMount(() => { for (const input of inputs) { @@ -164,81 +168,115 @@

    Need a hand?

    - {#if providers[$providerType].providers[$provider].needAHand} - {@const needAHand = providers[$providerType].providers[$provider].needAHand} -
    - - - -
    -
    -
    From 0837b8d49a94bc6d6b8e1c747fb96a6e3046ddb4 Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Thu, 22 Feb 2024 12:56:02 -0800 Subject: [PATCH 243/403] fix(messaging): prevent duplicate create subscriber calls Update subscribersByTargetId with created subscribers so subsequent addTarget() calls won't add the same targets again. --- .../topics/topic-[topic]/subscribers/+page.svelte | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) 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 index 08d6fd58a..c5c308a5e 100644 --- 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 @@ -46,9 +46,14 @@ const targetIds = Object.keys($targetsById).filter( (targetId) => !(targetId in subscribersByTargetId) ); - const promises = targetIds.map((targetId) => - sdk.forProject.messaging.createSubscriber($page.params.topic, ID.unique(), targetId) - ); + const promises = targetIds.map(async (targetId) => { + const subscriber = await sdk.forProject.messaging.createSubscriber( + $page.params.topic, + ID.unique(), + targetId + ); + subscribersByTargetId[targetId] = subscriber; + }); try { await Promise.all(promises); From aaab1118a0649f6e9c1f73b2a9f14630cc351aa0 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Sat, 24 Feb 2024 17:48:46 +0100 Subject: [PATCH 244/403] fix: various issues --- src/hooks.client.ts | 13 +++++++++++++ src/lib/components/filters/content.svelte | 4 ++-- src/lib/helpers/exceptions.ts | 1 + src/routes/+error.svelte | 2 +- src/routes/+layout.ts | 7 ++++--- src/routes/console/+error.svelte | 2 +- .../organization-[organization]/+layout.ts | 5 ++++- .../console/project-[project]/+error.svelte | 2 +- .../console/project-[project]/+layout.ts | 3 ++- .../settings/usage/[[invoice]]/+page.ts | 18 ++++++++---------- 10 files changed, 37 insertions(+), 20 deletions(-) create mode 100644 src/hooks.client.ts create mode 100644 src/lib/helpers/exceptions.ts diff --git a/src/hooks.client.ts b/src/hooks.client.ts new file mode 100644 index 000000000..2345ffb2c --- /dev/null +++ b/src/hooks.client.ts @@ -0,0 +1,13 @@ +import { AppwriteException } from '@appwrite.io/console'; +import type { HandleClientError } from '@sveltejs/kit'; + +export const handleError: HandleClientError = async ({ error, message, status }) => { + if (error instanceof AppwriteException && error.code === 0) { + status = undefined; + message = error.message; + } + return { + message, + status + }; +}; diff --git a/src/lib/components/filters/content.svelte b/src/lib/components/filters/content.svelte index 450aa6375..023ed61ff 100644 --- a/src/lib/components/filters/content.svelte +++ b/src/lib/components/filters/content.svelte @@ -134,7 +134,7 @@ bind:value={operatorKey} /> {#if column && operator && !operator?.hideInput} -
    +
      {#if column.type === 'integer' || column.type === 'double'} {:else if column.type === 'boolean'} @@ -150,7 +150,7 @@ {:else} {/if} -
    + {/if} diff --git a/src/routes/+layout.ts b/src/routes/+layout.ts index 4b3f68520..3919a26c3 100644 --- a/src/routes/+layout.ts +++ b/src/routes/+layout.ts @@ -13,9 +13,10 @@ export const ssr = false; export const load: LayoutLoad = async ({ depends, url }) => { depends(Dependencies.ACCOUNT); - redirectTo.set(url.searchParams.get('forceRedirect') || null); - - url.searchParams.delete('forceRedirect'); + if (url.searchParams.has('forceRedirect')) { + redirectTo.set(url.searchParams.get('forceRedirect') || null); + url.searchParams.delete('forceRedirect'); + } try { const account = await sdk.forConsole.account.get<{ organization?: string }>(); diff --git a/src/routes/console/+error.svelte b/src/routes/console/+error.svelte index 9a50e9be7..33d7695d1 100644 --- a/src/routes/console/+error.svelte +++ b/src/routes/console/+error.svelte @@ -6,7 +6,7 @@ - {$page.status} + {$page.error.status || 'Invalid Argument'} {$page.error.message} diff --git a/src/routes/console/organization-[organization]/+layout.ts b/src/routes/console/organization-[organization]/+layout.ts index cfd212057..79eba27f3 100644 --- a/src/routes/console/organization-[organization]/+layout.ts +++ b/src/routes/console/organization-[organization]/+layout.ts @@ -10,6 +10,7 @@ import { headerAlert } from '$lib/stores/headerAlert'; import ProjectsAtRisk from '$lib/components/billing/alerts/projectsAtRisk.svelte'; import { get } from 'svelte/store'; import { preferences } from '$lib/stores/preferences'; +import type { Organization } from '$lib/stores/organization'; export const load: LayoutLoad = async ({ params, depends }) => { depends(Dependencies.ORGANIZATION); @@ -37,7 +38,9 @@ export const load: LayoutLoad = async ({ params, depends }) => { return { header: Header, breadcrumbs: Breadcrumbs, - organization: await sdk.forConsole.teams.get(params.organization), + organization: await (sdk.forConsole.teams.get( + params.organization + ) as Promise), members: await sdk.forConsole.teams.listMemberships(params.organization) }; } catch (e) { diff --git a/src/routes/console/project-[project]/+error.svelte b/src/routes/console/project-[project]/+error.svelte index 243be6e42..be0053176 100644 --- a/src/routes/console/project-[project]/+error.svelte +++ b/src/routes/console/project-[project]/+error.svelte @@ -5,6 +5,6 @@ - {$page.status} + {$page.error.status || 'Invalid Argument'}

    {$page.error.message}

    diff --git a/src/routes/console/project-[project]/+layout.ts b/src/routes/console/project-[project]/+layout.ts index c25d0cd4c..156a24f34 100644 --- a/src/routes/console/project-[project]/+layout.ts +++ b/src/routes/console/project-[project]/+layout.ts @@ -5,6 +5,7 @@ import type { LayoutLoad } from './$types'; import { preferences } from '$lib/stores/preferences'; import { failedInvoice } from '$lib/stores/billing'; import { isCloud } from '$lib/system'; +import type { Organization } from '$lib/stores/organization'; export const load: LayoutLoad = async ({ params, depends }) => { depends(Dependencies.PROJECT); @@ -22,7 +23,7 @@ export const load: LayoutLoad = async ({ params, depends }) => { return { project, - organization: await sdk.forConsole.teams.get(project.teamId) + organization: await (sdk.forConsole.teams.get(project.teamId) as Promise) }; } catch (e) { error(e.code, e.message); diff --git a/src/routes/console/project-[project]/settings/usage/[[invoice]]/+page.ts b/src/routes/console/project-[project]/settings/usage/[[invoice]]/+page.ts index d29b1e799..2cb455ae0 100644 --- a/src/routes/console/project-[project]/settings/usage/[[invoice]]/+page.ts +++ b/src/routes/console/project-[project]/settings/usage/[[invoice]]/+page.ts @@ -1,24 +1,22 @@ +import type { Aggregation, Invoice } from '$lib/sdk/billing'; +import { accumulateUsage } from '$lib/sdk/usage'; import { getSdkForProject, sdk } from '$lib/stores/sdk'; import { Query } from '@appwrite.io/console'; import type { PageLoad } from './$types'; -import type { Organization } from '$lib/stores/organization'; -import type { Aggregation, Invoice } from '$lib/sdk/billing'; -import { accumulateUsage } from '$lib/sdk/usage'; export const load: PageLoad = async ({ params, parent }) => { const { invoice, project } = params; - const parentData = await parent(); - const org = parentData.organization as Organization; + const { organization } = await parent(); - let startDate: string = org.billingCurrentInvoiceDate; - let endDate: string = org.billingNextInvoiceDate; + let startDate: string = organization.billingCurrentInvoiceDate; + let endDate: string = organization.billingNextInvoiceDate; let currentInvoice: Invoice = undefined; let currentAggregation: Aggregation = undefined; if (invoice) { - currentInvoice = await sdk.forConsole.billing.getInvoice(org.$id, invoice); + currentInvoice = await sdk.forConsole.billing.getInvoice(organization.$id, invoice); currentAggregation = await sdk.forConsole.billing.getAggregation( - org.$id, + organization.$id, currentInvoice.aggregationId ); @@ -27,7 +25,7 @@ export const load: PageLoad = async ({ params, parent }) => { } const [invoices, usage] = await Promise.all([ - sdk.forConsole.billing.listInvoices(org.$id, [Query.orderDesc('from')]), + sdk.forConsole.billing.listInvoices(organization.$id, [Query.orderDesc('from')]), /** * Workaround because project id might not be populated yet. */ From e47c5f0a48407324a0cbbe6c19debea9df4204cf Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Sat, 24 Feb 2024 17:49:11 +0100 Subject: [PATCH 245/403] revert: remove exception helper --- src/lib/helpers/exceptions.ts | 1 - 1 file changed, 1 deletion(-) delete mode 100644 src/lib/helpers/exceptions.ts diff --git a/src/lib/helpers/exceptions.ts b/src/lib/helpers/exceptions.ts deleted file mode 100644 index d5196b555..000000000 --- a/src/lib/helpers/exceptions.ts +++ /dev/null @@ -1 +0,0 @@ -export class AppwriteInvalidArgumentException extends Error {} From 70bc6e45f04d638f73a10d2da56efdedd32821b1 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Sun, 25 Feb 2024 21:15:51 +1300 Subject: [PATCH 246/403] Add messaging to project services --- src/lib/stores/project-services.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/lib/stores/project-services.ts b/src/lib/stores/project-services.ts index cfa94f74a..d522855fd 100644 --- a/src/lib/stores/project-services.ts +++ b/src/lib/stores/project-services.ts @@ -40,6 +40,11 @@ function createServices() { method: ApiService.Locale, value: null }, + { + label: 'Messaging', + method: ApiService.Messaging, + value: null + }, { label: 'Storage', method: ApiService.Storage, @@ -98,6 +103,11 @@ function createServices() { method: ApiService.Locale, value: project.serviceStatusForLocale }, + { + label: 'Messaging', + method: ApiService.Messaging, + value: project.serviceStatusForMessaging + }, { label: 'Storage', method: ApiService.Storage, From 8984e161d395ac23d05b9703c1901cccae31d95e Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Sun, 25 Feb 2024 11:13:52 +0000 Subject: [PATCH 247/403] Detect migration resource values from names --- src/lib/stores/migration.ts | 32 ++++++++++--------- .../settings/migrations/details.svelte | 3 +- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/lib/stores/migration.ts b/src/lib/stores/migration.ts index ab8454ff9..84d07085f 100644 --- a/src/lib/stores/migration.ts +++ b/src/lib/stores/migration.ts @@ -35,21 +35,23 @@ export const createMigrationFormStore = () => { }; }; -const resources = [ - 'user', - 'team', - 'membership', - 'file', - 'bucket', - 'function', - 'environment variable', - 'deployment', - 'database', - 'collection', - 'index', - 'attribute', - 'document' -] as const; +export const ResourcesFriendly = { + user: { singular: 'User', plural: 'Users' }, + team: { singular: 'Team', plural: 'Teams' }, + membership: { singular: 'Membership', plural: 'Memberships' }, + file: { singular: 'File', plural: 'Files' }, + bucket: { singular: 'Bucket', plural: 'Buckets' }, + function: { singular: 'Function', plural: 'Functions' }, + 'environment variable': { singular: 'Environment Variable', plural: 'Environment Variables' }, + deployment: { singular: 'Deployment', plural: 'Deployments' }, + database: { singular: 'Database', plural: 'Databases' }, + collection: { singular: 'Collection', plural: 'Collections' }, + index: { singular: 'Index', plural: 'Indexes' }, + attribute: { singular: 'Attribute', plural: 'Attributes' }, + document: { singular: 'Document', plural: 'Documents' }, +}; + +const resources = Object.keys(ResourcesFriendly); type Resource = (typeof resources)[number]; diff --git a/src/routes/console/project-[project]/settings/migrations/details.svelte b/src/routes/console/project-[project]/settings/migrations/details.svelte index b34a617e6..564c5ac4d 100644 --- a/src/routes/console/project-[project]/settings/migrations/details.svelte +++ b/src/routes/console/project-[project]/settings/migrations/details.svelte @@ -6,6 +6,7 @@ import { parseIfString } from '$lib/helpers/object'; import { formatNum } from '$lib/helpers/string'; import type { Models } from '@appwrite.io/console'; + import { ResourcesFriendly } from '$lib/stores/migration' export let migrations: Models.Migration[] = []; export let migrationId: string = null; @@ -106,7 +107,7 @@
    - {entity + 's'} + {(total(Object.values(entityCounter)) > 1) ? ResourcesFriendly[entity].plural : ResourcesFriendly[entity].singular} {totalItems(entityCounter)}
    From ecb1b559654c3a0757f558abef45e75a2febf731 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Sun, 25 Feb 2024 11:39:37 +0000 Subject: [PATCH 248/403] Run Linter --- src/lib/stores/migration.ts | 2 +- .../project-[project]/settings/migrations/details.svelte | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/lib/stores/migration.ts b/src/lib/stores/migration.ts index 84d07085f..f6498f4b9 100644 --- a/src/lib/stores/migration.ts +++ b/src/lib/stores/migration.ts @@ -48,7 +48,7 @@ export const ResourcesFriendly = { collection: { singular: 'Collection', plural: 'Collections' }, index: { singular: 'Index', plural: 'Indexes' }, attribute: { singular: 'Attribute', plural: 'Attributes' }, - document: { singular: 'Document', plural: 'Documents' }, + document: { singular: 'Document', plural: 'Documents' } }; const resources = Object.keys(ResourcesFriendly); diff --git a/src/routes/console/project-[project]/settings/migrations/details.svelte b/src/routes/console/project-[project]/settings/migrations/details.svelte index 564c5ac4d..7fb707b7b 100644 --- a/src/routes/console/project-[project]/settings/migrations/details.svelte +++ b/src/routes/console/project-[project]/settings/migrations/details.svelte @@ -6,7 +6,7 @@ import { parseIfString } from '$lib/helpers/object'; import { formatNum } from '$lib/helpers/string'; import type { Models } from '@appwrite.io/console'; - import { ResourcesFriendly } from '$lib/stores/migration' + import { ResourcesFriendly } from '$lib/stores/migration'; export let migrations: Models.Migration[] = []; export let migrationId: string = null; @@ -107,7 +107,10 @@
    - {(total(Object.values(entityCounter)) > 1) ? ResourcesFriendly[entity].plural : ResourcesFriendly[entity].singular} + {total(Object.values(entityCounter)) > 1 + ? ResourcesFriendly[entity].plural + : ResourcesFriendly[entity].singular} {totalItems(entityCounter)}
    From 97493c3416be318751a7082302bedefee22c859b Mon Sep 17 00:00:00 2001 From: wess Date: Thu, 8 Feb 2024 09:50:07 -0500 Subject: [PATCH 249/403] working on preview spacing --- .../console/project-[project]/messaging/smsPhone.svelte | 2 +- .../project-[project]/messaging/wizard/smsFormList.svelte | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/routes/console/project-[project]/messaging/smsPhone.svelte b/src/routes/console/project-[project]/messaging/smsPhone.svelte index 918b87220..fc82ed6d3 100644 --- a/src/routes/console/project-[project]/messaging/smsPhone.svelte +++ b/src/routes/console/project-[project]/messaging/smsPhone.svelte @@ -51,7 +51,7 @@ .phone { position: relative; width: 320px; - height: 539px; + height: 430px; background-image: url('./sms-preview-light.svg'); background-repeat: no-repeat; diff --git a/src/routes/console/project-[project]/messaging/wizard/smsFormList.svelte b/src/routes/console/project-[project]/messaging/wizard/smsFormList.svelte index 876639a2f..5627dcd5c 100644 --- a/src/routes/console/project-[project]/messaging/wizard/smsFormList.svelte +++ b/src/routes/console/project-[project]/messaging/wizard/smsFormList.svelte @@ -102,6 +102,6 @@ -
    - +
    +
    From 62a5cbc514798c87e8d4b201400e17a7f54c9257 Mon Sep 17 00:00:00 2001 From: wess Date: Thu, 8 Feb 2024 09:53:27 -0500 Subject: [PATCH 250/403] adjusted height of phone for preview --- .../console/project-[project]/messaging/smsPhone.svelte | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/routes/console/project-[project]/messaging/smsPhone.svelte b/src/routes/console/project-[project]/messaging/smsPhone.svelte index fc82ed6d3..46191efd1 100644 --- a/src/routes/console/project-[project]/messaging/smsPhone.svelte +++ b/src/routes/console/project-[project]/messaging/smsPhone.svelte @@ -36,7 +36,7 @@
    {$project.name}
    -
    +
    Today {getTime()}
    @@ -51,7 +51,7 @@ .phone { position: relative; width: 320px; - height: 430px; + height: 410px; background-image: url('./sms-preview-light.svg'); background-repeat: no-repeat; From f196bcfb485adfb36324aabf32a3449471319bbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Sun, 25 Feb 2024 17:50:01 +0100 Subject: [PATCH 251/403] Fix 2FA deletion copy --- src/routes/console/account/deleteMfa.svelte | 8 ++++++-- .../auth/user-[user]/deleteMfa.svelte | 13 +++++-------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/routes/console/account/deleteMfa.svelte b/src/routes/console/account/deleteMfa.svelte index 6b113e406..d1fc639f9 100644 --- a/src/routes/console/account/deleteMfa.svelte +++ b/src/routes/console/account/deleteMfa.svelte @@ -39,14 +39,18 @@ -

    Are you sure you want to delete this authentication method from your account?

    +

    + Deleting the authentication method will disable multi-factor authentication for your + account. To re-enable it, you'll need to add a new authentication method. +

    +

    Enter the 6-digit verification code generated by your authenticator app to continue.

    diff --git a/src/routes/console/project-[project]/auth/user-[user]/deleteMfa.svelte b/src/routes/console/project-[project]/auth/user-[user]/deleteMfa.svelte index 912fab0b1..06322677f 100644 --- a/src/routes/console/project-[project]/auth/user-[user]/deleteMfa.svelte +++ b/src/routes/console/project-[project]/auth/user-[user]/deleteMfa.svelte @@ -4,8 +4,6 @@ import { Modal } from '$lib/components'; import { Dependencies } from '$lib/constants'; import { Button } from '$lib/elements/forms'; - import FormList from '$lib/elements/forms/formList.svelte'; - import InputDigits from '$lib/elements/forms/inputDigits.svelte'; import { addNotification } from '$lib/stores/notifications'; import { sdk } from '$lib/stores/sdk'; import { AuthenticatorType } from '@appwrite.io/console'; @@ -13,7 +11,6 @@ export let showDelete = false; - let code: string; let error: string; async function deleteProvider() { @@ -34,23 +31,23 @@ } $: if (showDelete) { - code = ''; error = ''; } +

    + Deleting the authentication method will disable multi-factor authentication for this + account. To re-enable it, user will need to add a new authentication method. +

    Are you sure you want to delete this authentication method from your account?

    - - - From f8261e625598ea9c53f24ce0ed046c50fa6278b6 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Sun, 25 Feb 2024 22:50:49 +0100 Subject: [PATCH 252/403] remove unused import --- src/lib/components/id.svelte | 1 - 1 file changed, 1 deletion(-) diff --git a/src/lib/components/id.svelte b/src/lib/components/id.svelte index f36e7002d..42aad2c8f 100644 --- a/src/lib/components/id.svelte +++ b/src/lib/components/id.svelte @@ -1,5 +1,4 @@ - - - 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]/updateTopics.svelte b/src/routes/console/project-[project]/messaging/message-[message]/updateTopics.svelte new file mode 100644 index 000000000..283f03064 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/message-[message]/updateTopics.svelte @@ -0,0 +1,161 @@ + + +
    + + Topics + +
    +
    + Topic +
    + +
    + {@const sum = topicIds.length} + {#if sum} +
    + + + + + + + {#each topics.slice(offset, offset + limit) as topic (topic.$id)} + + +
    + + + + {topic.name} + + + ({getTotal(topic)} targets) + + +
    +
    + +
    + +
    +
    +
    + {/each} +
    +
    +
    +

    Total topics: {sum}

    + +
    +
    + {:else} + (showTopics = true)}>Add a Topic + {/if} +
    + + + +
    +
    + + { + showTopics = false; + topicsById = e.detail; + }} /> From 3d364d193810b01b547aa29e37232ade3c362e00 Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Sun, 25 Feb 2024 17:50:01 -0800 Subject: [PATCH 254/403] feat(messaging): update the message targets card to allow updating --- .../messaging/message-[message]/+page.svelte | 7 +- .../message-[message]/targets.svelte | 62 ------ .../message-[message]/updateTargets.svelte | 182 ++++++++++++++++++ 3 files changed, 187 insertions(+), 64 deletions(-) delete mode 100644 src/routes/console/project-[project]/messaging/message-[message]/targets.svelte create mode 100644 src/routes/console/project-[project]/messaging/message-[message]/updateTargets.svelte 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 c10d41aac..daacb54fc 100644 --- a/src/routes/console/project-[project]/messaging/message-[message]/+page.svelte +++ b/src/routes/console/project-[project]/messaging/message-[message]/+page.svelte @@ -14,7 +14,7 @@ import { isValueOfStringEnum } from '$lib/helpers/types'; import { MessageStatus, MessagingProviderType } from '@appwrite.io/console'; import UpdateTopics from './updateTopics.svelte'; - import Targets from './targets.svelte'; + import UpdateTargets from './updateTargets.svelte'; import { onMount } from 'svelte'; export let data: PageData; @@ -121,7 +121,10 @@ messageId={$message.$id} messageType={$providerType} selectedTopicsById={data.topicsById} /> - + {#if $message.status !== MessageStatus.Processing} {/if} 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]/updateTargets.svelte b/src/routes/console/project-[project]/messaging/message-[message]/updateTargets.svelte new file mode 100644 index 000000000..bf7d3ddf4 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/message-[message]/updateTargets.svelte @@ -0,0 +1,182 @@ + + +
    + + Targets + +
    +
    + Target +
    + +
    + {@const sum = targetIds.length} + {#if sum} +
    + + + + + + + + {#each targets.slice(offset, offset + limit) as target (target.$id)} + + +
    + + + + {#if target.providerType === MessagingProviderType.Push} + {target.name} + {:else} + {target.identifier} + {/if} + + +
    +
    + +
    + +
    +
    +
    + {/each} +
    +
    +
    +

    Total targets: {sum}

    + +
    +
    + {:else} + (showTargets = true)}>Add a Target + {/if} +
    + + + +
    +
    + + { + showTargets = false; + targetsById = e.detail; + }}> + Select existing targets to which you want to send this message. + From 87845fd7dd6fdbd988b0f5e053ccbe8ce512553a Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Sun, 25 Feb 2024 18:18:50 -0800 Subject: [PATCH 255/403] feat(messaging): rename the message preview cards and enable updating --- .../messaging/message-[message]/+page.svelte | 99 ++----------------- .../message-[message]/emailMessage.svelte | 66 +++++++++++++ .../message-[message]/emailPreview.svelte | 33 ------- .../message-[message]/pushMessage.svelte | 71 +++++++++++++ .../message-[message]/pushPreview.svelte | 33 ------- .../message-[message]/smsMessage.svelte | 64 ++++++++++++ .../message-[message]/smsPreview.svelte | 29 ------ 7 files changed, 208 insertions(+), 187 deletions(-) create mode 100644 src/routes/console/project-[project]/messaging/message-[message]/emailMessage.svelte delete mode 100644 src/routes/console/project-[project]/messaging/message-[message]/emailPreview.svelte create mode 100644 src/routes/console/project-[project]/messaging/message-[message]/pushMessage.svelte delete mode 100644 src/routes/console/project-[project]/messaging/message-[message]/pushPreview.svelte create mode 100644 src/routes/console/project-[project]/messaging/message-[message]/smsMessage.svelte delete mode 100644 src/routes/console/project-[project]/messaging/message-[message]/smsPreview.svelte 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 daacb54fc..b8ebca83b 100644 --- a/src/routes/console/project-[project]/messaging/message-[message]/+page.svelte +++ b/src/routes/console/project-[project]/messaging/message-[message]/+page.svelte @@ -1,15 +1,12 @@ {#if $message.providerType === MessagingProviderType.Email} - + {:else if $message.providerType === MessagingProviderType.Sms} - + {:else if $message.providerType === MessagingProviderType.Push} - + {/if} + import { invalidate } from '$app/navigation'; + import { trackEvent, Submit, trackError } from '$lib/actions/analytics'; + import { CardGrid, Heading } from '$lib/components'; + import { Dependencies } from '$lib/constants'; + import { Button, Form, FormList, InputText, InputTextarea } from '$lib/elements/forms'; + import { addNotification } from '$lib/stores/notifications'; + import { sdk } from '$lib/stores/sdk'; + import type { Models } from '@appwrite.io/console'; + import { onMount } from 'svelte'; + + export let message: Models.Message & { data: Record }; + + let subject = ''; + let content = ''; + let disabled = true; + + onMount(() => { + subject = message.data.subject; + content = message.data.content; + }); + + async function update() { + try { + await sdk.forProject.messaging.updateEmail( + message.$id, + undefined, + undefined, + undefined, + subject, + content + ); + await invalidate(Dependencies.MESSAGING_MESSAGE); + addNotification({ + message: 'Message has been updated', + type: 'success' + }); + trackEvent(Submit.MessagingMessageUpdate); + } catch (error) { + addNotification({ + message: error.message, + type: 'error' + }); + trackError(error, Submit.MessagingMessageUpdate); + } + } + + $: disabled = subject === message.data.subject && content === message.data.content; + + +
    + +
    + Message +
    + + + + + + + + + +
    +
    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]/pushMessage.svelte b/src/routes/console/project-[project]/messaging/message-[message]/pushMessage.svelte new file mode 100644 index 000000000..fcc7a1802 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/message-[message]/pushMessage.svelte @@ -0,0 +1,71 @@ + + +
    + +
    + Message +
    + +
    +
    + + + + +
    +
    +
    + + + +
    +
    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]/smsMessage.svelte b/src/routes/console/project-[project]/messaging/message-[message]/smsMessage.svelte new file mode 100644 index 000000000..8d0e63f15 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/message-[message]/smsMessage.svelte @@ -0,0 +1,64 @@ + + +
    + +
    + 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 - -
    - - - - -
    - -
    -
    -
    -
    From cb4a69adb627ccd82adf95ba88f143a32a971335 Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Sun, 25 Feb 2024 21:54:14 -0800 Subject: [PATCH 256/403] fix(messaging): ensure scheduledAt is saved in draft messages --- .../console/project-[project]/messaging/wizard/step3.svelte | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/routes/console/project-[project]/messaging/wizard/step3.svelte b/src/routes/console/project-[project]/messaging/wizard/step3.svelte index ba2e7be3b..c7ee27769 100644 --- a/src/routes/console/project-[project]/messaging/wizard/step3.svelte +++ b/src/routes/console/project-[project]/messaging/wizard/step3.svelte @@ -44,7 +44,6 @@ $messageParams[$providerType].status = MessageStatus.Processing; if (when === 'later') { $messageParams[$providerType].status = 'scheduled' as MessageStatus; - $messageParams[$providerType].scheduledAt = dateTime.toISOString(); } } @@ -61,6 +60,9 @@ ? new Date(now.getTime() - timeZoneOffset).toISOString().split('T')[1].substring(0, 5) : '00:00'; $: dateTime = new Date(`${date}T${time}`); + $: if (!isNaN(dateTime.getTime())) { + $messageParams[$providerType].scheduledAt = dateTime.toISOString(); + } From 2c9788bad802367bba524942b3e6966839cf2278 Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Sun, 25 Feb 2024 22:29:00 -0800 Subject: [PATCH 257/403] fix(messaging): update message details to show scheduled/delivered at Only show when available. Othersise, hide the entire line. --- .../messaging/message-[message]/overview.svelte | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) 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..7e0116886 100644 --- a/src/routes/console/project-[project]/messaging/message-[message]/overview.svelte +++ b/src/routes/console/project-[project]/messaging/message-[message]/overview.svelte @@ -42,7 +42,12 @@

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

    -

    Scheduled at: {toLocaleDateTime(scheduledAt)}

    + {#if $message.scheduledAt} +

    Scheduled at: {toLocaleDateTime($message.scheduledAt)}

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

    Sent at: {toLocaleDateTime($message.deliveredAt)}

    + {/if}
    From 1d6a8017e1c9f4ffe981e08762674e30ec802937 Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Sun, 25 Feb 2024 22:34:41 -0800 Subject: [PATCH 258/403] feat(messaging): update overview card to support scheduling and sending --- .../messaging/message-[message]/+page.svelte | 2 +- .../message-[message]/overview.svelte | 60 ++++---- .../message-[message]/scheduleModal.svelte | 144 ++++++++++++++++++ .../message-[message]/sendModal.svelte | 102 +++++++++++++ 4 files changed, 277 insertions(+), 31 deletions(-) create mode 100644 src/routes/console/project-[project]/messaging/message-[message]/scheduleModal.svelte create mode 100644 src/routes/console/project-[project]/messaging/message-[message]/sendModal.svelte 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 b8ebca83b..d542f2ed7 100644 --- a/src/routes/console/project-[project]/messaging/message-[message]/+page.svelte +++ b/src/routes/console/project-[project]/messaging/message-[message]/+page.svelte @@ -24,7 +24,7 @@ - + {#if $message.providerType === MessagingProviderType.Email} {:else if $message.providerType === MessagingProviderType.Sms} 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 7e0116886..ce12622c6 100644 --- a/src/routes/console/project-[project]/messaging/message-[message]/overview.svelte +++ b/src/routes/console/project-[project]/messaging/message-[message]/overview.svelte @@ -4,38 +4,27 @@ import { message } from './store'; import ProviderType from '../providerType.svelte'; import MessageStatusPill from '../messageStatusPill.svelte'; - import { MessagingProviderType } from '@appwrite.io/console'; + import { MessagingProviderType, type Models } from '@appwrite.io/console'; import { Button } from '$lib/elements/forms'; import FailedModal from '../failedModal.svelte'; + import SendModal from './sendModal.svelte'; + import ScheduleModal from './scheduleModal.svelte'; - let scheduledAt: string = ''; + export let messageType: MessagingProviderType; + export let topics: Models.Topic[]; + + let showSend = false; + let showSchedule = false; let showFailed = false; let errors: string[] = []; - - if ($message.status === 'sent') { - scheduledAt = $message.deliveredAt; - } else if ($message.status === 'scheduled') { - scheduledAt = $message.scheduledAt; - } - - let providerType = 'Invalid provider type'; - switch ($message.providerType) { - case MessagingProviderType.Email: - providerType = 'Email'; - break; - case MessagingProviderType.Sms: - providerType = 'SMS'; - break; - case MessagingProviderType.Push: - providerType = 'Push'; - break; - } - +
    - {providerType} + + +
    @@ -56,14 +45,25 @@ - + {#if $message.status === 'draft' || $message.status === 'scheduled'} +
    + + +
    + {:else if $message.status === 'failed'} + + {/if}
    + + + + 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..2dc24a7fd --- /dev/null +++ b/src/routes/console/project-[project]/messaging/message-[message]/scheduleModal.svelte @@ -0,0 +1,144 @@ + + + +
    + +
    + + +
    +
    + + {#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..ba06222b1 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/message-[message]/sendModal.svelte @@ -0,0 +1,102 @@ + + + +
    +

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

    + +

    This action is irreversible.

    +
    + + + + +
    From 41a7caa6b5a33abf73e64c295376a72ac222a4f5 Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Sun, 25 Feb 2024 22:47:03 -0800 Subject: [PATCH 259/403] refactor(messaging): remove unused update message wizard code --- .../{wizard.svelte => create.svelte} | 119 +----------------- .../messaging/createMessageDropdown.svelte | 7 +- .../messaging/wizard/emailFormList.svelte | 26 ++-- .../messaging/wizard/pushFormList.svelte | 26 ++-- .../messaging/wizard/smsFormList.svelte | 26 ++-- .../messaging/wizard/store.ts | 1 - 6 files changed, 34 insertions(+), 171 deletions(-) rename src/routes/console/project-[project]/messaging/{wizard.svelte => create.svelte} (54%) 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 4fbc93c55..1392df1ec 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, MessageStatus, MessagingProviderType, type Models } from '@appwrite.io/console'; - import { Dependencies } from '$lib/constants'; async function create() { try { @@ -112,115 +111,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].status, - $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].status, - $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].status, - $messageParams[$providerType].scheduledAt - ); - } - break; - } - wizard.hide(); - let message = ''; - switch (response.status) { - case MessageStatus.Draft: - message = 'The message has been saved as draft.'; - break; - case MessageStatus.Processing: - message = 'The message is queued for processing.'; - break; - case 'scheduled': - // TODO: fix message status - message = 'The message has been scheduled.'; - break; - } - addNotification({ - type: 'success', - message - }); - await invalidate(Dependencies.MESSAGING_MESSAGE); - trackEvent(Submit.MessagingMessageUpdate, { - providerType: $providerType, - status: params.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].status = MessageStatus.Draft; - if ($operation === 'create') { - create(); - } else { - update(); - } + create(); } const stepsComponents: WizardStepsType = new Map(); @@ -256,8 +149,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/wizard/emailFormList.svelte b/src/routes/console/project-[project]/messaging/wizard/emailFormList.svelte index bcc6be1d6..60992f0dd 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 @@ + +
    + {#if label} + + {/if} +
    +
    +
    +
    +
    +
    + Select a file to upload + Select a file to upload +
    +
    +
    + Max file size: 1MB + +
    + + {#if value} + {@const fileSize = humanFileSize(value.sizeOriginal)} +
      +
    • +
    • +
    + {/if} +
    +
    +
    + +{#if show} + +{/if} diff --git a/src/routes/console/project-[project]/messaging/wizard/pushFormList.svelte b/src/routes/console/project-[project]/messaging/wizard/pushFormList.svelte index 53c48900c..6565da45b 100644 --- a/src/routes/console/project-[project]/messaging/wizard/pushFormList.svelte +++ b/src/routes/console/project-[project]/messaging/wizard/pushFormList.svelte @@ -45,6 +45,7 @@ import { sdk } from '$lib/stores/sdk'; import PushPhone from '../pushPhone.svelte'; import { onMount } from 'svelte'; + import InputFilePicker from '$lib/elements/forms/inputFilePicker.svelte'; let showCustomId = false; let showTest = false; @@ -148,11 +149,17 @@
    - - - + + + + + + + + +
      {#each customData || [] as _, rowIndex} From 9e177877354f86ed40d684c56e5a601d1eb26935 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Mon, 26 Feb 2024 12:52:43 +0100 Subject: [PATCH 261/403] fix: leftovers --- src/lib/components/filePicker.svelte | 18 +++++++++++------- src/lib/elements/forms/inputFilePicker.svelte | 2 +- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/lib/components/filePicker.svelte b/src/lib/components/filePicker.svelte index 3756f6b9c..0861b504b 100644 --- a/src/lib/components/filePicker.svelte +++ b/src/lib/components/filePicker.svelte @@ -225,6 +225,7 @@
    -
    - {#if files} - {#await files} + {#if files} + {#await files} +

    Loading files...

    - {:then response} +
    + {:then response} +
    {#if response.files?.length} {#if view === 'grid'}
      {/if} - {/await} - {/if} -
    +
    + {/await} + {/if} {/if}
    diff --git a/src/lib/elements/forms/inputFilePicker.svelte b/src/lib/elements/forms/inputFilePicker.svelte index fcd9d7edb..991f777e9 100644 --- a/src/lib/elements/forms/inputFilePicker.svelte +++ b/src/lib/elements/forms/inputFilePicker.svelte @@ -49,7 +49,7 @@
    + style:--box-border-radius="var(--border-radius-xsmall)">
  • {/each} From d825312315a821afb12f44dd4acbba12e548bf52 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Mon, 26 Feb 2024 13:33:20 +0100 Subject: [PATCH 263/403] fix: a11y --- src/lib/components/filePicker.svelte | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/lib/components/filePicker.svelte b/src/lib/components/filePicker.svelte index 1a72e220e..63a613fa8 100644 --- a/src/lib/components/filePicker.svelte +++ b/src/lib/components/filePicker.svelte @@ -21,6 +21,7 @@ import { writable } from 'svelte/store'; import { onMount } from 'svelte'; import Heading from './heading.svelte'; + import { clickOnEnter } from '$lib/helpers/a11y'; export let show: boolean; export let selectedBucket: string = null; @@ -224,12 +225,14 @@ - + @@ -261,13 +264,16 @@ style="--grid-gap:2rem; --grid-item-size:10rem; --grid-item-size-small-screens:8rem;"> {#each response.files as file}
  • - +
  • {/each} From 546dbce72594969501bc609916f4d05df53c6198 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Mon, 26 Feb 2024 14:04:01 +0100 Subject: [PATCH 264/403] fix button --- src/lib/components/filePicker.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/components/filePicker.svelte b/src/lib/components/filePicker.svelte index 63a613fa8..edbee1726 100644 --- a/src/lib/components/filePicker.svelte +++ b/src/lib/components/filePicker.svelte @@ -228,7 +228,7 @@ - {@const sum = targetIds.length} {#if sum} +
    +
    + Target +
    + +
    diff --git a/src/routes/console/project-[project]/messaging/message-[message]/updateTopics.svelte b/src/routes/console/project-[project]/messaging/message-[message]/updateTopics.svelte index 283f03064..3daa4feaa 100644 --- a/src/routes/console/project-[project]/messaging/message-[message]/updateTopics.svelte +++ b/src/routes/console/project-[project]/messaging/message-[message]/updateTopics.svelte @@ -81,22 +81,22 @@ Topics -
    -
    - Topic -
    - -
    {@const sum = topicIds.length} {#if sum} +
    +
    + Topic +
    + +
    From 57cd02825e0733cca5edcdb12783dd49b5fdfc13 Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Mon, 26 Feb 2024 08:18:39 -0800 Subject: [PATCH 271/403] fix(messaging): use sentence case in topic/target empty state --- .../messaging/message-[message]/updateTargets.svelte | 2 +- .../messaging/message-[message]/updateTopics.svelte | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/routes/console/project-[project]/messaging/message-[message]/updateTargets.svelte b/src/routes/console/project-[project]/messaging/message-[message]/updateTargets.svelte index 18f43ca60..bfa045ca6 100644 --- a/src/routes/console/project-[project]/messaging/message-[message]/updateTargets.svelte +++ b/src/routes/console/project-[project]/messaging/message-[message]/updateTargets.svelte @@ -159,7 +159,7 @@ {:else} - (showTargets = true)}>Add a Target + (showTargets = true)}>Add a target {/if} diff --git a/src/routes/console/project-[project]/messaging/message-[message]/updateTopics.svelte b/src/routes/console/project-[project]/messaging/message-[message]/updateTopics.svelte index 3daa4feaa..30c7f5709 100644 --- a/src/routes/console/project-[project]/messaging/message-[message]/updateTopics.svelte +++ b/src/routes/console/project-[project]/messaging/message-[message]/updateTopics.svelte @@ -142,7 +142,7 @@ {:else} - (showTopics = true)}>Add a Topic + (showTopics = true)}>Add a topic {/if} From 722d918cc956d68d90e3cf11de633065f8b8c28b Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Mon, 26 Feb 2024 08:20:21 -0800 Subject: [PATCH 272/403] fix(messaging): make the send modal small It doesn't need that much space since it's just a little bit of content. --- .../messaging/message-[message]/sendModal.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/console/project-[project]/messaging/message-[message]/sendModal.svelte b/src/routes/console/project-[project]/messaging/message-[message]/sendModal.svelte index ba06222b1..1bc47006f 100644 --- a/src/routes/console/project-[project]/messaging/message-[message]/sendModal.svelte +++ b/src/routes/console/project-[project]/messaging/message-[message]/sendModal.svelte @@ -86,7 +86,7 @@ }; - +

    You are about to send a message to an estimated Date: Mon, 26 Feb 2024 08:21:35 -0800 Subject: [PATCH 273/403] fix(messaging): make schedule message modal bigger Give the inputs a bit more room. --- .../messaging/message-[message]/scheduleModal.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/console/project-[project]/messaging/message-[message]/scheduleModal.svelte b/src/routes/console/project-[project]/messaging/message-[message]/scheduleModal.svelte index 2dc24a7fd..76bbef6ca 100644 --- a/src/routes/console/project-[project]/messaging/message-[message]/scheduleModal.svelte +++ b/src/routes/console/project-[project]/messaging/message-[message]/scheduleModal.svelte @@ -119,7 +119,7 @@ $: dateTime = new Date(`${date}T${time}`); - +

    Date: Mon, 26 Feb 2024 08:31:33 -0800 Subject: [PATCH 274/403] fix(messaging): fix topics & targets empty state for non-draft Show empty search and link to docs since they shouldn't edit it. --- .../messaging/message-[message]/+page.svelte | 2 ++ .../message-[message]/updateTargets.svelte | 22 ++++++++++++++++--- .../message-[message]/updateTopics.svelte | 22 ++++++++++++++++--- 3 files changed, 40 insertions(+), 6 deletions(-) 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 d542f2ed7..3c0647e5c 100644 --- a/src/routes/console/project-[project]/messaging/message-[message]/+page.svelte +++ b/src/routes/console/project-[project]/messaging/message-[message]/+page.svelte @@ -35,10 +35,12 @@ {#if $message.status !== MessageStatus.Processing} diff --git a/src/routes/console/project-[project]/messaging/message-[message]/updateTargets.svelte b/src/routes/console/project-[project]/messaging/message-[message]/updateTargets.svelte index bfa045ca6..13abd4a0d 100644 --- a/src/routes/console/project-[project]/messaging/message-[message]/updateTargets.svelte +++ b/src/routes/console/project-[project]/messaging/message-[message]/updateTargets.svelte @@ -1,5 +1,5 @@ + + +
    +
    +

    +

    + + +
    + +

    + The connection to {webhook.url} stopped after {webhook.attempts} consecutive failures. Please refer to the logs below for more information or try to update the webhook to resolve this issue. +

    +
    + +
    +
    + + + + +
    diff --git a/src/routes/console/project-[project]/settings/webhooks/messageStatusPill.svelte b/src/routes/console/project-[project]/settings/webhooks/messageStatusPill.svelte new file mode 100644 index 000000000..be4d09a6e --- /dev/null +++ b/src/routes/console/project-[project]/settings/webhooks/messageStatusPill.svelte @@ -0,0 +1,22 @@ + + + + + + diff --git a/src/routes/console/project-[project]/settings/webhooks/store.ts b/src/routes/console/project-[project]/settings/webhooks/store.ts index 0154c8b7b..4d7bfd323 100644 --- a/src/routes/console/project-[project]/settings/webhooks/store.ts +++ b/src/routes/console/project-[project]/settings/webhooks/store.ts @@ -10,8 +10,8 @@ export const columns = writable([ { id: '$id', title: 'Webhook ID', type: 'string', show: true, width: 150 }, { id: 'name', title: 'Name', type: 'string', show: true, width: 120 }, { id: 'url', title: 'Post URL', type: 'string', show: true, width: 120 }, - { id: 'events', title: 'Events', type: 'string', show: true, width: 120 }, - { id: 'enabled', title: 'Enabled', type: 'string', show: true, width: 120 }, + { id: 'events', title: 'Events', type: 'string', show: true, width: 60 }, + { id: 'enabled', title: 'Status', type: 'string', show: true, width: 150 }, { id: '$createdAt', title: 'Created', type: 'datetime', show: true, width: 120 }, { id: '$updatedAt', title: 'Updated', type: 'datetime', show: true, width: 120 } ]); From 689df57642f5607e865fba4d726e4e60da65aa80 Mon Sep 17 00:00:00 2001 From: wess Date: Mon, 26 Feb 2024 11:52:18 -0500 Subject: [PATCH 276/403] Lint updateds --- src/lib/layout/containerHeader.svelte | 3 +- .../settings/webhooks/+page.svelte | 122 ++++++++---------- .../settings/webhooks/+page.ts | 12 +- .../settings/webhooks/failedModal.svelte | 29 ++--- .../webhooks/messageStatusPill.svelte | 22 ++-- 5 files changed, 81 insertions(+), 107 deletions(-) diff --git a/src/lib/layout/containerHeader.svelte b/src/lib/layout/containerHeader.svelte index 258d89c5c..0f6bf834d 100644 --- a/src/lib/layout/containerHeader.svelte +++ b/src/lib/layout/containerHeader.svelte @@ -168,7 +168,7 @@ {/if}
    - + {#if buttonText} {/if} - diff --git a/src/routes/console/project-[project]/settings/webhooks/+page.svelte b/src/routes/console/project-[project]/settings/webhooks/+page.svelte index a5ebd2c92..dbf8b2971 100644 --- a/src/routes/console/project-[project]/settings/webhooks/+page.svelte +++ b/src/routes/console/project-[project]/settings/webhooks/+page.svelte @@ -7,10 +7,7 @@ - + - + From c6ed6604a03b06d3d6198e14f0478c9660dd9442 Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Mon, 26 Feb 2024 08:53:38 -0800 Subject: [PATCH 277/403] refactor(messaging): update message detail cards to accept message param Rely less on global store for possibility to test in the future. --- .../messaging/message-[message]/+page.svelte | 14 ++------ .../message-[message]/overview.svelte | 33 +++++++++---------- .../message-[message]/scheduleModal.svelte | 15 ++++----- .../message-[message]/sendModal.svelte | 15 ++++----- .../message-[message]/updateTargets.svelte | 26 ++++++++------- .../message-[message]/updateTopics.svelte | 26 ++++++++------- 6 files changed, 63 insertions(+), 66 deletions(-) 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 3c0647e5c..cf3ea176e 100644 --- a/src/routes/console/project-[project]/messaging/message-[message]/+page.svelte +++ b/src/routes/console/project-[project]/messaging/message-[message]/+page.svelte @@ -24,7 +24,7 @@ - + {#if $message.providerType === MessagingProviderType.Email} {:else if $message.providerType === MessagingProviderType.Sms} @@ -32,16 +32,8 @@ {:else if $message.providerType === MessagingProviderType.Push} {/if} - - + + {#if $message.status !== MessageStatus.Processing} {/if} 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 ce12622c6..2b08d0000 100644 --- a/src/routes/console/project-[project]/messaging/message-[message]/overview.svelte +++ b/src/routes/console/project-[project]/messaging/message-[message]/overview.svelte @@ -1,16 +1,15 @@ - +
    - + - +
    -

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

    - {#if $message.scheduledAt} -

    Scheduled at: {toLocaleDateTime($message.scheduledAt)}

    +

    Created: {toLocaleDateTime(message.$createdAt)}

    + {#if message.scheduledAt} +

    Scheduled at: {toLocaleDateTime(message.scheduledAt)}

    {/if} - {#if $message.deliveredAt} -

    Sent at: {toLocaleDateTime($message.deliveredAt)}

    + {#if message.deliveredAt} +

    Sent at: {toLocaleDateTime(message.deliveredAt)}

    {/if}
    - +
    - {#if $message.status === 'draft' || $message.status === 'scheduled'} + {#if message.status === 'draft' || message.status === 'scheduled'}
    - {:else if $message.status === 'failed'} + {:else if message.status === 'failed'} {/if}
    - + - + diff --git a/src/routes/console/project-[project]/messaging/message-[message]/scheduleModal.svelte b/src/routes/console/project-[project]/messaging/message-[message]/scheduleModal.svelte index 76bbef6ca..1b81dbd4c 100644 --- a/src/routes/console/project-[project]/messaging/message-[message]/scheduleModal.svelte +++ b/src/routes/console/project-[project]/messaging/message-[message]/scheduleModal.svelte @@ -9,7 +9,6 @@ import { Dependencies } from '$lib/constants'; export let show = false; - export let messageType: MessagingProviderType; export let message: Models.Message & { data: Record }; export let topics: Models.Topic[]; @@ -35,11 +34,11 @@ }; for (const topic of topics) { - if (messageType == MessagingProviderType.Push) { + if (message.providerType == MessagingProviderType.Push) { totalTargets = totalTargets + topic.pushTotal; - } else if (messageType == MessagingProviderType.Email) { + } else if (message.providerType == MessagingProviderType.Email) { totalTargets = totalTargets + topic.emailTotal; - } else if (messageType == MessagingProviderType.Sms) { + } else if (message.providerType == MessagingProviderType.Sms) { totalTargets = totalTargets + topic.smsTotal; } } @@ -47,7 +46,7 @@ const update = async () => { const status = MessageStatus.Scheduled; try { - if (messageType == MessagingProviderType.Email) { + if (message.providerType == MessagingProviderType.Email) { await sdk.forProject.messaging.updateEmail( message.$id, undefined, @@ -61,7 +60,7 @@ undefined, dateTime.toISOString() ); - } else if (messageType == MessagingProviderType.Sms) { + } else if (message.providerType == MessagingProviderType.Sms) { await sdk.forProject.messaging.updateSms( message.$id, undefined, @@ -71,7 +70,7 @@ status, dateTime.toISOString() ); - } else if (messageType == MessagingProviderType.Push) { + } else if (message.providerType == MessagingProviderType.Push) { await sdk.forProject.messaging.updatePush( message.$id, undefined, @@ -97,7 +96,7 @@ type: 'success' }); trackEvent(Submit.MessagingMessageUpdate, { - providerType: messageType, + providerType: message.providerType, status }); show = false; diff --git a/src/routes/console/project-[project]/messaging/message-[message]/sendModal.svelte b/src/routes/console/project-[project]/messaging/message-[message]/sendModal.svelte index 1bc47006f..2bf51ef7f 100644 --- a/src/routes/console/project-[project]/messaging/message-[message]/sendModal.svelte +++ b/src/routes/console/project-[project]/messaging/message-[message]/sendModal.svelte @@ -9,18 +9,17 @@ import { Dependencies } from '$lib/constants'; export let show = false; - export let messageType: MessagingProviderType; export let message: Models.Message & { data: Record }; export let topics: Models.Topic[]; let totalTargets = message.targets?.length ?? 0; for (const topic of topics) { - if (messageType == MessagingProviderType.Push) { + if (message.providerType == MessagingProviderType.Push) { totalTargets = totalTargets + topic.pushTotal; - } else if (messageType == MessagingProviderType.Email) { + } else if (message.providerType == MessagingProviderType.Email) { totalTargets = totalTargets + topic.emailTotal; - } else if (messageType == MessagingProviderType.Sms) { + } else if (message.providerType == MessagingProviderType.Sms) { totalTargets = totalTargets + topic.smsTotal; } } @@ -28,7 +27,7 @@ const update = async () => { const status = MessageStatus.Processing; try { - if (messageType == MessagingProviderType.Email) { + if (message.providerType == MessagingProviderType.Email) { await sdk.forProject.messaging.updateEmail( message.$id, undefined, @@ -38,7 +37,7 @@ undefined, status ); - } else if (messageType == MessagingProviderType.Sms) { + } else if (message.providerType == MessagingProviderType.Sms) { await sdk.forProject.messaging.updateSms( message.$id, undefined, @@ -47,7 +46,7 @@ undefined, status ); - } else if (messageType == MessagingProviderType.Push) { + } else if (message.providerType == MessagingProviderType.Push) { await sdk.forProject.messaging.updatePush( message.$id, undefined, @@ -72,7 +71,7 @@ type: 'success' }); trackEvent(Submit.MessagingMessageUpdate, { - providerType: messageType, + providerType: message.providerType, status }); show = false; diff --git a/src/routes/console/project-[project]/messaging/message-[message]/updateTargets.svelte b/src/routes/console/project-[project]/messaging/message-[message]/updateTargets.svelte index 13abd4a0d..ba729f0d0 100644 --- a/src/routes/console/project-[project]/messaging/message-[message]/updateTargets.svelte +++ b/src/routes/console/project-[project]/messaging/message-[message]/updateTargets.svelte @@ -18,12 +18,12 @@ import { addNotification } from '$lib/stores/notifications'; import { Button, Form } from '$lib/elements/forms'; import UserTargetsModal from '../userTargetsModal.svelte'; + import { isValueOfStringEnum } from '$lib/helpers/types'; - export let messageId: string; - export let messageType: MessagingProviderType; - export let messageStatus: string; + export let message: Models.Message & { data: Record }; export let selectedTargetsById: Record; + let providerType: MessagingProviderType; let offset = 0; const limit = 10; let showTargets = false; @@ -32,6 +32,10 @@ let targets: Models.Target[] = []; let disabled = true; + if (isValueOfStringEnum(MessagingProviderType, message.providerType)) { + providerType = message.providerType; + } + onMount(() => { targetsById = { ...selectedTargetsById }; }); @@ -43,23 +47,23 @@ async function update() { try { - if (messageType == MessagingProviderType.Email) { + if (message.providerType == MessagingProviderType.Email) { await sdk.forProject.messaging.updateEmail( - messageId, + message.$id, undefined, undefined, targetIds ); - } else if (messageType == MessagingProviderType.Sms) { + } else if (message.providerType == MessagingProviderType.Sms) { await sdk.forProject.messaging.updateSms( - messageId, + message.$id, undefined, undefined, targetIds ); - } else if (messageType == MessagingProviderType.Push) { + } else if (message.providerType == MessagingProviderType.Push) { await sdk.forProject.messaging.updatePush( - messageId, + message.$id, undefined, undefined, targetIds @@ -159,7 +163,7 @@
    - {:else if messageStatus == MessageStatus.Draft} + {:else if message.status == MessageStatus.Draft} (showTargets = true)}>Add a target {:else} @@ -186,7 +190,7 @@ { diff --git a/src/routes/console/project-[project]/messaging/message-[message]/updateTopics.svelte b/src/routes/console/project-[project]/messaging/message-[message]/updateTopics.svelte index ba41efaf4..d0f1da8b6 100644 --- a/src/routes/console/project-[project]/messaging/message-[message]/updateTopics.svelte +++ b/src/routes/console/project-[project]/messaging/message-[message]/updateTopics.svelte @@ -19,12 +19,12 @@ import { Form, Button } from '$lib/elements/forms'; import { onMount } from 'svelte'; import { getTotal } from '../wizard/store'; + import { isValueOfStringEnum } from '$lib/helpers/types'; - export let messageId: string; - export let messageType: MessagingProviderType; - export let messageStatus: string; + export let message: Models.Message; export let selectedTopicsById: Record; + let providerType: MessagingProviderType; let offset = 0; const limit = 10; let showTopics = false; @@ -33,6 +33,10 @@ let topics: Models.Topic[] = []; let disabled = true; + if (isValueOfStringEnum(MessagingProviderType, message.providerType)) { + providerType = message.providerType; + } + onMount(() => { topicsById = { ...selectedTopicsById }; }); @@ -44,12 +48,12 @@ async function update() { try { - if (messageType == MessagingProviderType.Email) { - await sdk.forProject.messaging.updateEmail(messageId, topicIds); - } else if (messageType == MessagingProviderType.Sms) { - await sdk.forProject.messaging.updateSms(messageId, topicIds); - } else if (messageType == MessagingProviderType.Push) { - await sdk.forProject.messaging.updatePush(messageId, topicIds); + if (message.providerType == MessagingProviderType.Email) { + await sdk.forProject.messaging.updateEmail(message.$id, topicIds); + } else if (message.providerType == MessagingProviderType.Sms) { + await sdk.forProject.messaging.updateSms(message.$id, topicIds); + } else if (message.providerType == MessagingProviderType.Push) { + await sdk.forProject.messaging.updatePush(message.$id, topicIds); } await invalidate(Dependencies.MESSAGING_MESSAGE); addNotification({ @@ -142,7 +146,7 @@ - {:else if messageStatus == MessageStatus.Draft} + {:else if message.status == MessageStatus.Draft} (showTopics = true)}>Add a topic {:else} @@ -168,7 +172,7 @@ { From bc9ddf084e261b2df965c88d4613075f7dbd1b32 Mon Sep 17 00:00:00 2001 From: wess Date: Mon, 26 Feb 2024 11:54:40 -0500 Subject: [PATCH 278/403] lint fixes --- .../project-[project]/settings/webhooks/failedModal.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/console/project-[project]/settings/webhooks/failedModal.svelte b/src/routes/console/project-[project]/settings/webhooks/failedModal.svelte index 9b282e914..21274b7e1 100644 --- a/src/routes/console/project-[project]/settings/webhooks/failedModal.svelte +++ b/src/routes/console/project-[project]/settings/webhooks/failedModal.svelte @@ -7,7 +7,7 @@ import Button from '$lib/elements/forms/button.svelte'; export let show: boolean; - export let webhook: { [key: string]: any }; + export let webhook: { [key: string]: string|number|boolean }; const projectId = $page.params.project; const webhookPath = `${base}/console/project-${projectId}/settings/webhooks/${webhook.$id}`; From 91e38b32e9cd0261b766208fc144e849995aa675 Mon Sep 17 00:00:00 2001 From: wess Date: Mon, 26 Feb 2024 12:02:05 -0500 Subject: [PATCH 279/403] Lint fixes --- .../project-[project]/settings/webhooks/failedModal.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/console/project-[project]/settings/webhooks/failedModal.svelte b/src/routes/console/project-[project]/settings/webhooks/failedModal.svelte index 21274b7e1..c73bb51fe 100644 --- a/src/routes/console/project-[project]/settings/webhooks/failedModal.svelte +++ b/src/routes/console/project-[project]/settings/webhooks/failedModal.svelte @@ -7,7 +7,7 @@ import Button from '$lib/elements/forms/button.svelte'; export let show: boolean; - export let webhook: { [key: string]: string|number|boolean }; + export let webhook: { [key: string]: string | number | boolean }; const projectId = $page.params.project; const webhookPath = `${base}/console/project-${projectId}/settings/webhooks/${webhook.$id}`; From 1827f4642ee5a0632bac72bd7106e88643114f96 Mon Sep 17 00:00:00 2001 From: wess Date: Mon, 26 Feb 2024 12:04:25 -0500 Subject: [PATCH 280/403] Lint fixes --- .../project-[project]/settings/webhooks/failedModal.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/console/project-[project]/settings/webhooks/failedModal.svelte b/src/routes/console/project-[project]/settings/webhooks/failedModal.svelte index c73bb51fe..b3ce80f03 100644 --- a/src/routes/console/project-[project]/settings/webhooks/failedModal.svelte +++ b/src/routes/console/project-[project]/settings/webhooks/failedModal.svelte @@ -7,7 +7,7 @@ import Button from '$lib/elements/forms/button.svelte'; export let show: boolean; - export let webhook: { [key: string]: string | number | boolean }; + export let webhook: { [key: string | number]: string | number | boolean }; const projectId = $page.params.project; const webhookPath = `${base}/console/project-${projectId}/settings/webhooks/${webhook.$id}`; From 21e1719fbaacf0709f9f2d0d4e5b863ff34a63ca Mon Sep 17 00:00:00 2001 From: wess Date: Mon, 26 Feb 2024 12:09:34 -0500 Subject: [PATCH 281/403] Lint fixes --- .../project-[project]/settings/webhooks/failedModal.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/console/project-[project]/settings/webhooks/failedModal.svelte b/src/routes/console/project-[project]/settings/webhooks/failedModal.svelte index b3ce80f03..201517a50 100644 --- a/src/routes/console/project-[project]/settings/webhooks/failedModal.svelte +++ b/src/routes/console/project-[project]/settings/webhooks/failedModal.svelte @@ -7,7 +7,7 @@ import Button from '$lib/elements/forms/button.svelte'; export let show: boolean; - export let webhook: { [key: string | number]: string | number | boolean }; + export let webhook: { [key: string ]: any }; const projectId = $page.params.project; const webhookPath = `${base}/console/project-${projectId}/settings/webhooks/${webhook.$id}`; From 3575083c89db3d4ada8e7610beb3d88dd4fab010 Mon Sep 17 00:00:00 2001 From: wess Date: Mon, 26 Feb 2024 12:14:42 -0500 Subject: [PATCH 282/403] Fixing spacing --- .../project-[project]/settings/webhooks/failedModal.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/console/project-[project]/settings/webhooks/failedModal.svelte b/src/routes/console/project-[project]/settings/webhooks/failedModal.svelte index 201517a50..9b282e914 100644 --- a/src/routes/console/project-[project]/settings/webhooks/failedModal.svelte +++ b/src/routes/console/project-[project]/settings/webhooks/failedModal.svelte @@ -7,7 +7,7 @@ import Button from '$lib/elements/forms/button.svelte'; export let show: boolean; - export let webhook: { [key: string ]: any }; + export let webhook: { [key: string]: any }; const projectId = $page.params.project; const webhookPath = `${base}/console/project-${projectId}/settings/webhooks/${webhook.$id}`; From 4410d6000fb24a7a67bb7e8ca025a48d19f56d27 Mon Sep 17 00:00:00 2001 From: wess Date: Mon, 26 Feb 2024 12:23:21 -0500 Subject: [PATCH 283/403] Fixes imports --- .../project-[project]/settings/webhooks/failedModal.svelte | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/routes/console/project-[project]/settings/webhooks/failedModal.svelte b/src/routes/console/project-[project]/settings/webhooks/failedModal.svelte index 9b282e914..e2238671a 100644 --- a/src/routes/console/project-[project]/settings/webhooks/failedModal.svelte +++ b/src/routes/console/project-[project]/settings/webhooks/failedModal.svelte @@ -5,9 +5,10 @@ import Code from '$lib/components/code.svelte'; import Modal from '$lib/components/modal.svelte'; import Button from '$lib/elements/forms/button.svelte'; + import {type Models} from '@appwrite.io/console'; export let show: boolean; - export let webhook: { [key: string]: any }; + export let webhook: Models.Webhook; const projectId = $page.params.project; const webhookPath = `${base}/console/project-${projectId}/settings/webhooks/${webhook.$id}`; From 65daa89003459fcb7d224820a504ebd2f9af38d9 Mon Sep 17 00:00:00 2001 From: wess Date: Mon, 26 Feb 2024 12:25:54 -0500 Subject: [PATCH 284/403] Fixes imports --- .../console/project-[project]/settings/webhooks/+page.svelte | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/routes/console/project-[project]/settings/webhooks/+page.svelte b/src/routes/console/project-[project]/settings/webhooks/+page.svelte index dbf8b2971..b6cb4e930 100644 --- a/src/routes/console/project-[project]/settings/webhooks/+page.svelte +++ b/src/routes/console/project-[project]/settings/webhooks/+page.svelte @@ -24,6 +24,7 @@ import type { PageData } from './$types'; import { columns } from './store'; import { updateCommandGroupRanks } from '$lib/commandCenter'; + import {type Models} from '@appwrite.io/console'; import Create from './createWebhook.svelte'; import FailedModal from './failedModal.svelte'; import MessageStatusPill from './messageStatusPill.svelte'; @@ -31,7 +32,7 @@ export let data: PageData; let showFailed = false; - let selectedWebhook = {}; + let selectedWebhook:Models.Webhook function openWizard() { wizard.start(Create); From 2ed97400fea1edfff549061ac2319f74d906a576 Mon Sep 17 00:00:00 2001 From: wess Date: Mon, 26 Feb 2024 12:27:36 -0500 Subject: [PATCH 285/403] Lint updates --- .../console/project-[project]/settings/webhooks/+page.svelte | 4 ++-- .../project-[project]/settings/webhooks/failedModal.svelte | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/routes/console/project-[project]/settings/webhooks/+page.svelte b/src/routes/console/project-[project]/settings/webhooks/+page.svelte index b6cb4e930..351aaad9a 100644 --- a/src/routes/console/project-[project]/settings/webhooks/+page.svelte +++ b/src/routes/console/project-[project]/settings/webhooks/+page.svelte @@ -24,7 +24,7 @@ import type { PageData } from './$types'; import { columns } from './store'; import { updateCommandGroupRanks } from '$lib/commandCenter'; - import {type Models} from '@appwrite.io/console'; + import { type Models } from '@appwrite.io/console'; import Create from './createWebhook.svelte'; import FailedModal from './failedModal.svelte'; import MessageStatusPill from './messageStatusPill.svelte'; @@ -32,7 +32,7 @@ export let data: PageData; let showFailed = false; - let selectedWebhook:Models.Webhook + let selectedWebhook: Models.Webhook; function openWizard() { wizard.start(Create); diff --git a/src/routes/console/project-[project]/settings/webhooks/failedModal.svelte b/src/routes/console/project-[project]/settings/webhooks/failedModal.svelte index e2238671a..3bf4c27a8 100644 --- a/src/routes/console/project-[project]/settings/webhooks/failedModal.svelte +++ b/src/routes/console/project-[project]/settings/webhooks/failedModal.svelte @@ -5,7 +5,7 @@ import Code from '$lib/components/code.svelte'; import Modal from '$lib/components/modal.svelte'; import Button from '$lib/elements/forms/button.svelte'; - import {type Models} from '@appwrite.io/console'; + import { type Models } from '@appwrite.io/console'; export let show: boolean; export let webhook: Models.Webhook; From 98b16920a817ab723aebfa742d277ff7870f46c4 Mon Sep 17 00:00:00 2001 From: wess Date: Mon, 26 Feb 2024 13:34:37 -0500 Subject: [PATCH 286/403] Fixes issue where null webhook would cause failure --- .../console/project-[project]/settings/webhooks/+page.svelte | 3 --- .../project-[project]/settings/webhooks/failedModal.svelte | 4 +++- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/routes/console/project-[project]/settings/webhooks/+page.svelte b/src/routes/console/project-[project]/settings/webhooks/+page.svelte index 351aaad9a..057859cb0 100644 --- a/src/routes/console/project-[project]/settings/webhooks/+page.svelte +++ b/src/routes/console/project-[project]/settings/webhooks/+page.svelte @@ -41,8 +41,6 @@ const projectId = $page.params.project; $: $updateCommandGroupRanks({ webhooks: 20, domains: 10 }); - - console.log(data.webhooks); @@ -101,7 +99,6 @@ link on:click={(e) => { e.preventDefault(); - console.log(webhook); selectedWebhook = webhook; showFailed = true; }}>Details diff --git a/src/routes/console/project-[project]/settings/webhooks/failedModal.svelte b/src/routes/console/project-[project]/settings/webhooks/failedModal.svelte index 3bf4c27a8..32761aaf0 100644 --- a/src/routes/console/project-[project]/settings/webhooks/failedModal.svelte +++ b/src/routes/console/project-[project]/settings/webhooks/failedModal.svelte @@ -11,7 +11,9 @@ export let webhook: Models.Webhook; const projectId = $page.params.project; - const webhookPath = `${base}/console/project-${projectId}/settings/webhooks/${webhook.$id}`; + const webhookPath = webhook + ? `${base}/console/project-${projectId}/settings/webhooks/` + (webhook['$id'] ?? '') + : ''; From 88f661149bcaba9368a997aa0df697e661b65baa Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Mon, 26 Feb 2024 11:41:07 -0800 Subject: [PATCH 287/403] fix(messaging): show cancel and reschedule for scheduled messages --- .../messaging/message-[message]/overview.svelte | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) 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 2b08d0000..3373321cc 100644 --- a/src/routes/console/project-[project]/messaging/message-[message]/overview.svelte +++ b/src/routes/console/project-[project]/messaging/message-[message]/overview.svelte @@ -3,7 +3,7 @@ import { toLocaleDateTime } from '$lib/helpers/date'; import ProviderType from '../providerType.svelte'; import MessageStatusPill from '../messageStatusPill.svelte'; - import { type Models } from '@appwrite.io/console'; + import { MessageStatus, type Models } from '@appwrite.io/console'; import { Button } from '$lib/elements/forms'; import FailedModal from '../failedModal.svelte'; import SendModal from './sendModal.svelte'; @@ -44,11 +44,16 @@
    - {#if message.status === 'draft' || message.status === 'scheduled'} + {#if message.status === MessageStatus.Draft}
    + {:else if message.status === MessageStatus.Scheduled} +
    + + +
    {:else if message.status === 'failed'} + {#if message.status == MessageStatus.Draft} + + {/if}
    @@ -141,17 +143,19 @@ -
    - +
    diff --git a/src/routes/console/project-[project]/messaging/message-[message]/updateTopics.svelte b/src/routes/console/project-[project]/messaging/message-[message]/updateTopics.svelte index d0f1da8b6..f2ef9f55c 100644 --- a/src/routes/console/project-[project]/messaging/message-[message]/updateTopics.svelte +++ b/src/routes/console/project-[project]/messaging/message-[message]/updateTopics.svelte @@ -83,7 +83,7 @@ - + Topics {@const sum = topicIds.length} @@ -92,15 +92,17 @@
    Topic
    - + {#if message.status == MessageStatus.Draft} + + {/if}
    @@ -125,16 +127,19 @@ -
    - +
    From bd9bf4cb699037c6a1dcd7953c0c024f8eac5c6c Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Mon, 26 Feb 2024 13:02:55 -0800 Subject: [PATCH 289/403] feat(messaging): add custom data to message details --- .../message-[message]/pushMessage.svelte | 109 +++++++++++++++++- 1 file changed, 105 insertions(+), 4 deletions(-) diff --git a/src/routes/console/project-[project]/messaging/message-[message]/pushMessage.svelte b/src/routes/console/project-[project]/messaging/message-[message]/pushMessage.svelte index c882c88fb..f9bd9398d 100644 --- a/src/routes/console/project-[project]/messaging/message-[message]/pushMessage.svelte +++ b/src/routes/console/project-[project]/messaging/message-[message]/pushMessage.svelte @@ -1,6 +1,16 @@ @@ -69,7 +106,71 @@ label="Message" disabled={message.status != MessageStatus.Draft} bind:value={body}> -
    + + + + +
    +
      + {#each customData || [] as _, rowIndex} + + + + + + + + + {/each} +
    + {#if dataError} + {dataError} + {/if} + +
    + From 3c1219dc234aff0f78e5b500781fec5f457d010d Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Mon, 26 Feb 2024 14:52:53 -0800 Subject: [PATCH 290/403] fix(messaging): add html mode switch to email message --- .../message-[message]/emailMessage.svelte | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/routes/console/project-[project]/messaging/message-[message]/emailMessage.svelte b/src/routes/console/project-[project]/messaging/message-[message]/emailMessage.svelte index fa4e9154f..d3b046d8c 100644 --- a/src/routes/console/project-[project]/messaging/message-[message]/emailMessage.svelte +++ b/src/routes/console/project-[project]/messaging/message-[message]/emailMessage.svelte @@ -3,7 +3,7 @@ import { trackEvent, Submit, trackError } from '$lib/actions/analytics'; import { CardGrid, Heading } from '$lib/components'; import { Dependencies } from '$lib/constants'; - import { Button, Form, FormList, InputText, InputTextarea } from '$lib/elements/forms'; + import { Button, Form, FormList, InputSwitch, InputText, InputTextarea } from '$lib/elements/forms'; import { addNotification } from '$lib/stores/notifications'; import { sdk } from '$lib/stores/sdk'; import { MessageStatus, type Models } from '@appwrite.io/console'; @@ -13,11 +13,13 @@ let subject = ''; let content = ''; + let html = false; let disabled = true; onMount(() => { subject = message.data.subject; content = message.data.content; + html = (message.data['html'] ?? false) as boolean; }); async function update() { @@ -28,7 +30,9 @@ undefined, undefined, subject, - content + content, + undefined, + html ); await invalidate(Dependencies.MESSAGING_MESSAGE); addNotification({ @@ -45,7 +49,7 @@ } } - $: disabled = subject === message.data.subject && content === message.data.content; + $: disabled = subject === message.data.subject && content === message.data.content && html === (message.data['html'] ?? false) as boolean;
    @@ -65,6 +69,11 @@ label="Message" disabled={message.status != MessageStatus.Draft} bind:value={content}> + + + Enable the HTML mode if your message contains HTML tags. + +
    From 8d1934f303d10204a5ccf76032bb8ff29dec3b51 Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Mon, 26 Feb 2024 14:54:30 -0800 Subject: [PATCH 291/403] fix(messaging): update topics/targets confirmation message --- .../messaging/message-[message]/updateTargets.svelte | 2 +- .../messaging/message-[message]/updateTopics.svelte | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/routes/console/project-[project]/messaging/message-[message]/updateTargets.svelte b/src/routes/console/project-[project]/messaging/message-[message]/updateTargets.svelte index 159c2299a..c4a1ca0db 100644 --- a/src/routes/console/project-[project]/messaging/message-[message]/updateTargets.svelte +++ b/src/routes/console/project-[project]/messaging/message-[message]/updateTargets.svelte @@ -71,7 +71,7 @@ } await invalidate(Dependencies.MESSAGING_MESSAGE); addNotification({ - message: 'Message has been updated', + message: 'Targets have been updated', type: 'success' }); trackEvent(Submit.MessagingMessageUpdate); diff --git a/src/routes/console/project-[project]/messaging/message-[message]/updateTopics.svelte b/src/routes/console/project-[project]/messaging/message-[message]/updateTopics.svelte index f2ef9f55c..96dd7ab4c 100644 --- a/src/routes/console/project-[project]/messaging/message-[message]/updateTopics.svelte +++ b/src/routes/console/project-[project]/messaging/message-[message]/updateTopics.svelte @@ -57,7 +57,7 @@ } await invalidate(Dependencies.MESSAGING_MESSAGE); addNotification({ - message: 'Message has been updated', + message: 'Topics have been updated', type: 'success' }); trackEvent(Submit.MessagingMessageUpdate); From 2d3c7ef5201bcfc244b56d36e2313a49af7fcf6c Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Mon, 26 Feb 2024 15:05:26 -0800 Subject: [PATCH 292/403] feat(messaging): support cancelling a scheduled message Update status to draft. --- .../message-[message]/cancelModal.svelte | 92 +++++++++++++++++++ .../message-[message]/overview.svelte | 8 +- 2 files changed, 98 insertions(+), 2 deletions(-) create mode 100644 src/routes/console/project-[project]/messaging/message-[message]/cancelModal.svelte 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..504b67a54 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/message-[message]/cancelModal.svelte @@ -0,0 +1,92 @@ + + + +
    +

    + 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]/overview.svelte b/src/routes/console/project-[project]/messaging/message-[message]/overview.svelte index 3373321cc..d020e9b99 100644 --- a/src/routes/console/project-[project]/messaging/message-[message]/overview.svelte +++ b/src/routes/console/project-[project]/messaging/message-[message]/overview.svelte @@ -8,12 +8,14 @@ import FailedModal from '../failedModal.svelte'; import SendModal from './sendModal.svelte'; import ScheduleModal from './scheduleModal.svelte'; - + import CancelModal from './cancelModal.svelte'; + export let message: Models.Message & { data: Record }; export let topics: Models.Topic[]; let showSend = false; let showSchedule = false; + let showCancel = false; let showFailed = false; let errors: string[] = []; @@ -51,7 +53,7 @@ {:else if message.status === MessageStatus.Scheduled}
    - +
    {:else if message.status === 'failed'} @@ -70,4 +72,6 @@ + + From e9333da83d27bd6ad758b210158354b0c7057d35 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Mon, 26 Feb 2024 12:15:47 +0000 Subject: [PATCH 293/403] fix: wizards copy --- src/lib/wizards/functions/steps/executeAccess.svelte | 2 +- src/routes/console/(migration-wizard)/step2.svelte | 2 +- .../console/organization-[organization]/wizard/step1.svelte | 2 +- .../collection-[collection]/wizard/step1.svelte | 2 +- .../console/project-[project]/functions/wizard/step1.svelte | 2 +- .../console/project-[project]/overview/keys/wizard/step1.svelte | 2 +- .../project-[project]/settings/migrations/(import)/step1.svelte | 2 +- .../project-[project]/settings/migrations/(import)/step2.svelte | 2 +- .../project-[project]/settings/webhooks/wizard/step1.svelte | 2 +- .../storage/bucket-[bucket]/create-file/step1.svelte | 2 +- .../storage/bucket-[bucket]/create-file/step2.svelte | 2 +- .../console/wizard/cloudOrganization/inviteMembers.svelte | 2 +- .../wizard/cloudOrganizationChangeTier/inviteMembers.svelte | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/lib/wizards/functions/steps/executeAccess.svelte b/src/lib/wizards/functions/steps/executeAccess.svelte index 6d0e7c29d..6972bb2f6 100644 --- a/src/lib/wizards/functions/steps/executeAccess.svelte +++ b/src/lib/wizards/functions/steps/executeAccess.svelte @@ -5,7 +5,7 @@ - Execution permissions + Permissions Choose who can execute this function using the client API. For more information, visit our - Select resources + Resources Select the resources you need to migrate to Appwrite. Some resources can be migrated, but with limitations. - Project Details + Project details - Create data + Data Provide document data based on attributes you created earlier. diff --git a/src/routes/console/project-[project]/functions/wizard/step1.svelte b/src/routes/console/project-[project]/functions/wizard/step1.svelte index 17408aacb..8700c7bbe 100644 --- a/src/routes/console/project-[project]/functions/wizard/step1.svelte +++ b/src/routes/console/project-[project]/functions/wizard/step1.svelte @@ -20,7 +20,7 @@ - Configuration function + Configuration Create your new Appwrite Function. - Create an API key + API key Let's create an API key. - Select source + Source Select a source platform with the project you want to migrate. - Select source + Resources Select the resources you need to migrate to Appwrite. Some resources can be migrated, but with limitations. - Add your webhook + Webhook configuration Use webhooks to build integrations that subscribe to specific events on Appwrite. Appwrite will send an HTTP POST payload to the webhook's configured URL when one of the specified diff --git a/src/routes/console/project-[project]/storage/bucket-[bucket]/create-file/step1.svelte b/src/routes/console/project-[project]/storage/bucket-[bucket]/create-file/step1.svelte index 8453a8ee0..77a953bc6 100644 --- a/src/routes/console/project-[project]/storage/bucket-[bucket]/create-file/step1.svelte +++ b/src/routes/console/project-[project]/storage/bucket-[bucket]/create-file/step1.svelte @@ -18,7 +18,7 @@ - Create file + File Upload a file to add it to your bucket. {#if isCloud} diff --git a/src/routes/console/project-[project]/storage/bucket-[bucket]/create-file/step2.svelte b/src/routes/console/project-[project]/storage/bucket-[bucket]/create-file/step2.svelte index 6a98039ef..58363e57d 100644 --- a/src/routes/console/project-[project]/storage/bucket-[bucket]/create-file/step2.svelte +++ b/src/routes/console/project-[project]/storage/bucket-[bucket]/create-file/step2.svelte @@ -7,7 +7,7 @@ - Update Permissions + Permissions Choose who can access your buckets and files. For more information, check out the - Invite organization members + Invites Invite team members to collaborate with you in the Appwrite console. Members will have access to all services and payment data within your organization. diff --git a/src/routes/console/wizard/cloudOrganizationChangeTier/inviteMembers.svelte b/src/routes/console/wizard/cloudOrganizationChangeTier/inviteMembers.svelte index 94d86e267..0695e7e0f 100644 --- a/src/routes/console/wizard/cloudOrganizationChangeTier/inviteMembers.svelte +++ b/src/routes/console/wizard/cloudOrganizationChangeTier/inviteMembers.svelte @@ -52,7 +52,7 @@ - Invite organization members + Invites Invite team members to collaborate with you in the Appwrite console. Members will have access to all services and payment data within your organization. From 88a99b702ce80249d4c08a856db758c1746c9c81 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Mon, 26 Feb 2024 12:18:18 +0000 Subject: [PATCH 294/403] fix: more wizard --- .../console/organization-[organization]/wizard/step1.svelte | 2 +- .../project-[project]/settings/webhooks/wizard/step1.svelte | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/routes/console/organization-[organization]/wizard/step1.svelte b/src/routes/console/organization-[organization]/wizard/step1.svelte index bb7577386..612fd11fc 100644 --- a/src/routes/console/organization-[organization]/wizard/step1.svelte +++ b/src/routes/console/organization-[organization]/wizard/step1.svelte @@ -9,7 +9,7 @@ - Project details + Details - Webhook configuration + Configuration Use webhooks to build integrations that subscribe to specific events on Appwrite. Appwrite will send an HTTP POST payload to the webhook's configured URL when one of the specified From 59154148c78e0b90193e31aa0e9e202c27c54160 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Mon, 26 Feb 2024 12:29:28 +0000 Subject: [PATCH 295/403] fix: big wizard audit --- src/lib/pages/domains/wizard/step1.svelte | 2 +- src/routes/console/(migration-wizard)/step1.svelte | 1 + .../billing/wizard/addCredit.svelte | 2 +- .../billing/wizard/paymentDetails.svelte | 2 +- .../overview/keys/wizard/step2.svelte | 2 +- .../overview/platforms/wizard/android/step1.svelte | 2 +- .../overview/platforms/wizard/android/step2.svelte | 1 + .../overview/platforms/wizard/android/step3.svelte | 1 + .../overview/platforms/wizard/apple/step1.svelte | 2 +- .../overview/platforms/wizard/apple/step2.svelte | 1 + .../overview/platforms/wizard/apple/step3.svelte | 1 + .../overview/platforms/wizard/flutter/step1.svelte | 12 ++++++------ .../overview/platforms/wizard/flutter/step2.svelte | 1 + .../overview/platforms/wizard/flutter/step3.svelte | 1 + .../overview/platforms/wizard/step4.svelte | 1 + .../overview/platforms/wizard/web/step1.svelte | 2 +- .../overview/platforms/wizard/web/step2.svelte | 1 + .../wizard/cloudOrganization/confirmDetails.svelte | 2 +- .../cloudOrganizationChangeTier/choosePlan.svelte | 2 +- .../confirmDetails.svelte | 4 ++-- .../cloudOrganizationChangeTier/usageExcess.svelte | 5 +++-- src/routes/console/wizard/feedback/step1.svelte | 1 + src/routes/console/wizard/feedback/step2.svelte | 1 + src/routes/console/wizard/support/step1.svelte | 1 + 24 files changed, 32 insertions(+), 19 deletions(-) diff --git a/src/lib/pages/domains/wizard/step1.svelte b/src/lib/pages/domains/wizard/step1.svelte index 2c0010a3a..794d6d945 100644 --- a/src/lib/pages/domains/wizard/step1.svelte +++ b/src/lib/pages/domains/wizard/step1.svelte @@ -34,7 +34,7 @@ - Add function domain + Domain Use your self-owned domain as the endpoint of your Appwrite API. + {hasProjects ? 'Select project' : 'Create project'} diff --git a/src/routes/console/organization-[organization]/billing/wizard/addCredit.svelte b/src/routes/console/organization-[organization]/billing/wizard/addCredit.svelte index ddc5292c2..d62ffc7ab 100644 --- a/src/routes/console/organization-[organization]/billing/wizard/addCredit.svelte +++ b/src/routes/console/organization-[organization]/billing/wizard/addCredit.svelte @@ -38,7 +38,7 @@ - Add credits + Credits Add Appwrite credits to your organization. A payment method is required before credits can be applied. diff --git a/src/routes/console/organization-[organization]/billing/wizard/paymentDetails.svelte b/src/routes/console/organization-[organization]/billing/wizard/paymentDetails.svelte index b4f54264d..72dfd81c2 100644 --- a/src/routes/console/organization-[organization]/billing/wizard/paymentDetails.svelte +++ b/src/routes/console/organization-[organization]/billing/wizard/paymentDetails.svelte @@ -41,7 +41,7 @@ - Payment details + Details Add a payment method to your organization. You will not be charged until you upgrade to a Pro or Scale plan. diff --git a/src/routes/console/project-[project]/overview/keys/wizard/step2.svelte b/src/routes/console/project-[project]/overview/keys/wizard/step2.svelte index 56638e8a0..383a8d426 100644 --- a/src/routes/console/project-[project]/overview/keys/wizard/step2.svelte +++ b/src/routes/console/project-[project]/overview/keys/wizard/step2.svelte @@ -6,7 +6,7 @@ - Add Scopes + Scopes Choose which permission scopes to grant your application. It is best practice to allow only the permissions you need to meet your project goals. diff --git a/src/routes/console/project-[project]/overview/platforms/wizard/android/step1.svelte b/src/routes/console/project-[project]/overview/platforms/wizard/android/step1.svelte index d756e05b9..bdd6b79a1 100644 --- a/src/routes/console/project-[project]/overview/platforms/wizard/android/step1.svelte +++ b/src/routes/console/project-[project]/overview/platforms/wizard/android/step1.svelte @@ -41,7 +41,7 @@ - Register your Android app + Android registration + Get the SDK

    First, add this to your root level build.gradle file.

    diff --git a/src/routes/console/project-[project]/overview/platforms/wizard/android/step3.svelte b/src/routes/console/project-[project]/overview/platforms/wizard/android/step3.svelte index 736d87555..15c0cbe16 100644 --- a/src/routes/console/project-[project]/overview/platforms/wizard/android/step3.svelte +++ b/src/routes/console/project-[project]/overview/platforms/wizard/android/step3.svelte @@ -15,6 +15,7 @@ val client = Client(context) + Initialize SDK

    Initialize your SDK

    diff --git a/src/routes/console/project-[project]/overview/platforms/wizard/apple/step1.svelte b/src/routes/console/project-[project]/overview/platforms/wizard/apple/step1.svelte index 46adf251d..9c3b9761a 100644 --- a/src/routes/console/project-[project]/overview/platforms/wizard/apple/step1.svelte +++ b/src/routes/console/project-[project]/overview/platforms/wizard/apple/step1.svelte @@ -36,7 +36,7 @@ - Register your bundle ID + Apple registration diff --git a/src/routes/console/project-[project]/overview/platforms/wizard/apple/step2.svelte b/src/routes/console/project-[project]/overview/platforms/wizard/apple/step2.svelte index 2c0519fdb..cc3f1a5d7 100644 --- a/src/routes/console/project-[project]/overview/platforms/wizard/apple/step2.svelte +++ b/src/routes/console/project-[project]/overview/platforms/wizard/apple/step2.svelte @@ -29,6 +29,7 @@ + Get the SDK
    (method = Method.Xcode)} selected={method === Method.Xcode}> diff --git a/src/routes/console/project-[project]/overview/platforms/wizard/apple/step3.svelte b/src/routes/console/project-[project]/overview/platforms/wizard/apple/step3.svelte index 420994b55..c7683a46d 100644 --- a/src/routes/console/project-[project]/overview/platforms/wizard/apple/step3.svelte +++ b/src/routes/console/project-[project]/overview/platforms/wizard/apple/step3.svelte @@ -17,6 +17,7 @@ let client = Client() + Initialize SDK

    Initialize your SDK

    diff --git a/src/routes/console/project-[project]/overview/platforms/wizard/flutter/step1.svelte b/src/routes/console/project-[project]/overview/platforms/wizard/flutter/step1.svelte index 3aa0a579b..c64b948e6 100644 --- a/src/routes/console/project-[project]/overview/platforms/wizard/flutter/step1.svelte +++ b/src/routes/console/project-[project]/overview/platforms/wizard/flutter/step1.svelte @@ -149,16 +149,16 @@ $: registee = { [PlatformType.Flutterandroid]: 'package name', - [PlatformType.Flutterios]: 'bundle ID', - [PlatformType.Flutterlinux]: 'package name', - [PlatformType.Fluttermacos]: 'bundle ID', - [PlatformType.Flutterwindows]: 'package name', - [PlatformType.Flutterweb]: 'hostname' + [PlatformType.Flutterios]: 'Bundle ID', + [PlatformType.Flutterlinux]: 'Package name', + [PlatformType.Fluttermacos]: 'Bundle ID', + [PlatformType.Flutterwindows]: 'Package name', + [PlatformType.Flutterweb]: 'Hostname' }[platform]; - Register your {registee} + {registee} registration
    + Get the SDK

    diff --git a/src/routes/console/project-[project]/overview/platforms/wizard/flutter/step3.svelte b/src/routes/console/project-[project]/overview/platforms/wizard/flutter/step3.svelte index cc82830e2..deb5cb79a 100644 --- a/src/routes/console/project-[project]/overview/platforms/wizard/flutter/step3.svelte +++ b/src/routes/console/project-[project]/overview/platforms/wizard/flutter/step3.svelte @@ -18,6 +18,7 @@ client + Initialize SDK

    Initialize your SDK

    diff --git a/src/routes/console/project-[project]/overview/platforms/wizard/step4.svelte b/src/routes/console/project-[project]/overview/platforms/wizard/step4.svelte index cc2c48958..88a9ae2f7 100644 --- a/src/routes/console/project-[project]/overview/platforms/wizard/step4.svelte +++ b/src/routes/console/project-[project]/overview/platforms/wizard/step4.svelte @@ -6,6 +6,7 @@ + You're ready to go 🎉

    {#if isFirstProject} diff --git a/src/routes/console/project-[project]/overview/platforms/wizard/web/step1.svelte b/src/routes/console/project-[project]/overview/platforms/wizard/web/step1.svelte index af152ddab..661b2472d 100644 --- a/src/routes/console/project-[project]/overview/platforms/wizard/web/step1.svelte +++ b/src/routes/console/project-[project]/overview/platforms/wizard/web/step1.svelte @@ -44,7 +44,7 @@ - Register your hostname + Hostname registration + Get the SDK Choose your preferred method of installation diff --git a/src/routes/console/wizard/cloudOrganization/confirmDetails.svelte b/src/routes/console/wizard/cloudOrganization/confirmDetails.svelte index a7c6209f6..cf3363ab9 100644 --- a/src/routes/console/wizard/cloudOrganization/confirmDetails.svelte +++ b/src/routes/console/wizard/cloudOrganization/confirmDetails.svelte @@ -51,7 +51,7 @@ - Confirm your details + Details Confirm the details of your new organization and start your free trial. diff --git a/src/routes/console/wizard/cloudOrganizationChangeTier/choosePlan.svelte b/src/routes/console/wizard/cloudOrganizationChangeTier/choosePlan.svelte index 5a94e9ec8..2327bd948 100644 --- a/src/routes/console/wizard/cloudOrganizationChangeTier/choosePlan.svelte +++ b/src/routes/console/wizard/cloudOrganizationChangeTier/choosePlan.svelte @@ -103,7 +103,7 @@ - Choose a plan + Plan selection

    Plan

    diff --git a/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte b/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte index e62c6af3f..aa1c4bf8b 100644 --- a/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte +++ b/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte @@ -49,7 +49,7 @@ {#if downgradeToStarter} - Confirm plan change + Change confirmation Your feedback is important to us and helps us improve the services Appwrite offer. If there is a specific reason you chose to change your plan at this time, please let us @@ -65,7 +65,7 @@ {:else} - Confirm your details + Details Confirm the details of your new organization and start your free trial. diff --git a/src/routes/console/wizard/cloudOrganizationChangeTier/usageExcess.svelte b/src/routes/console/wizard/cloudOrganizationChangeTier/usageExcess.svelte index f3b1a6baa..570d2a2c8 100644 --- a/src/routes/console/wizard/cloudOrganizationChangeTier/usageExcess.svelte +++ b/src/routes/console/wizard/cloudOrganizationChangeTier/usageExcess.svelte @@ -7,8 +7,9 @@ - Your usage exceeds the limits of the {tierToPlan($organization.billingPlan).name} plan + + + Your usage exceeds the limits of the {tierToPlan($organization.billingPlan).name} plan View the current usage for {$organization.name} and where you will exceed the limits of your new plan. diff --git a/src/routes/console/wizard/feedback/step1.svelte b/src/routes/console/wizard/feedback/step1.svelte index c3a665590..e2e408b1e 100644 --- a/src/routes/console/wizard/feedback/step1.svelte +++ b/src/routes/console/wizard/feedback/step1.svelte @@ -32,6 +32,7 @@ + {$selectedFeedback.title} {$selectedFeedback.desc} diff --git a/src/routes/console/wizard/feedback/step2.svelte b/src/routes/console/wizard/feedback/step2.svelte index 1e91272cf..56d26c51c 100644 --- a/src/routes/console/wizard/feedback/step2.svelte +++ b/src/routes/console/wizard/feedback/step2.svelte @@ -6,6 +6,7 @@ + Thanks for the feedback!

    diff --git a/src/routes/console/wizard/support/step1.svelte b/src/routes/console/wizard/support/step1.svelte index 06f8f265b..e82448d02 100644 --- a/src/routes/console/wizard/support/step1.svelte +++ b/src/routes/console/wizard/support/step1.svelte @@ -21,6 +21,7 @@ + How can we help you? Please describe your request in detail. If applicable, include steps for reproduction of any From 7f69ea5d55455088fae1c4e8f15a8e167a2c5dd8 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Mon, 26 Feb 2024 14:31:48 +0000 Subject: [PATCH 296/403] fix: typo --- .../console/project-[project]/messaging/providers/create.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/console/project-[project]/messaging/providers/create.svelte b/src/routes/console/project-[project]/messaging/providers/create.svelte index 53cdf91a4..4f25dcda1 100644 --- a/src/routes/console/project-[project]/messaging/providers/create.svelte +++ b/src/routes/console/project-[project]/messaging/providers/create.svelte @@ -156,7 +156,7 @@ const stepsComponents: WizardStepsType = new Map(); stepsComponents.set(1, { - label: 'Proivder', + label: 'Provider', component: Provider }); stepsComponents.set(2, { From 213e72433f551513f30425c6a4c5d2825a2bedd8 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Mon, 26 Feb 2024 16:06:50 +0000 Subject: [PATCH 297/403] chore: vincent suggestions --- .../overview/platforms/wizard/android/step2.svelte | 3 +-- .../overview/platforms/wizard/android/step3.svelte | 3 +-- .../overview/platforms/wizard/apple/step2.svelte | 3 +-- .../overview/platforms/wizard/apple/step3.svelte | 3 +-- .../overview/platforms/wizard/flutter/step2.svelte | 3 +-- .../overview/platforms/wizard/flutter/step3.svelte | 3 +-- .../project-[project]/overview/platforms/wizard/step4.svelte | 3 +-- .../overview/platforms/wizard/web/step2.svelte | 3 +-- .../wizard/cloudOrganizationChangeTier/usageExcess.svelte | 1 - src/routes/console/wizard/feedback/step1.svelte | 1 - src/routes/console/wizard/feedback/step2.svelte | 3 +-- src/routes/console/wizard/support/step1.svelte | 1 - 12 files changed, 9 insertions(+), 21 deletions(-) diff --git a/src/routes/console/project-[project]/overview/platforms/wizard/android/step2.svelte b/src/routes/console/project-[project]/overview/platforms/wizard/android/step2.svelte index 30f7e0d85..a2c5dd1fb 100644 --- a/src/routes/console/project-[project]/overview/platforms/wizard/android/step2.svelte +++ b/src/routes/console/project-[project]/overview/platforms/wizard/android/step2.svelte @@ -10,8 +10,7 @@ - - Get the SDK + Install

    First, add this to your root level build.gradle file.

    And add this to your project's build.gradle file.

    diff --git a/src/routes/console/project-[project]/overview/platforms/wizard/android/step3.svelte b/src/routes/console/project-[project]/overview/platforms/wizard/android/step3.svelte index 15c0cbe16..9b47253d1 100644 --- a/src/routes/console/project-[project]/overview/platforms/wizard/android/step3.svelte +++ b/src/routes/console/project-[project]/overview/platforms/wizard/android/step3.svelte @@ -15,8 +15,7 @@ val client = Client(context) - - Initialize SDK + Initialize

    Initialize your SDK

    diff --git a/src/routes/console/project-[project]/overview/platforms/wizard/apple/step2.svelte b/src/routes/console/project-[project]/overview/platforms/wizard/apple/step2.svelte index cc3f1a5d7..d77381e5b 100644 --- a/src/routes/console/project-[project]/overview/platforms/wizard/apple/step2.svelte +++ b/src/routes/console/project-[project]/overview/platforms/wizard/apple/step2.svelte @@ -29,8 +29,7 @@ - - Get the SDK + Install

    (method = Method.Xcode)} selected={method === Method.Xcode}> Xcode diff --git a/src/routes/console/project-[project]/overview/platforms/wizard/apple/step3.svelte b/src/routes/console/project-[project]/overview/platforms/wizard/apple/step3.svelte index c7683a46d..6ff63e373 100644 --- a/src/routes/console/project-[project]/overview/platforms/wizard/apple/step3.svelte +++ b/src/routes/console/project-[project]/overview/platforms/wizard/apple/step3.svelte @@ -17,8 +17,7 @@ let client = Client() - - Initialize SDK + Initialize

    Initialize your SDK

    diff --git a/src/routes/console/project-[project]/overview/platforms/wizard/flutter/step2.svelte b/src/routes/console/project-[project]/overview/platforms/wizard/flutter/step2.svelte index ab5f13aa8..27d4667f3 100644 --- a/src/routes/console/project-[project]/overview/platforms/wizard/flutter/step2.svelte +++ b/src/routes/console/project-[project]/overview/platforms/wizard/flutter/step2.svelte @@ -9,8 +9,7 @@ - - Get the SDK + Install

    Add Appwrite SDK to your package's pubspec.yaml file. You can diff --git a/src/routes/console/project-[project]/overview/platforms/wizard/flutter/step3.svelte b/src/routes/console/project-[project]/overview/platforms/wizard/flutter/step3.svelte index deb5cb79a..3211a6796 100644 --- a/src/routes/console/project-[project]/overview/platforms/wizard/flutter/step3.svelte +++ b/src/routes/console/project-[project]/overview/platforms/wizard/flutter/step3.svelte @@ -18,8 +18,7 @@ client - - Initialize SDK + Initialize

    Initialize your SDK

    diff --git a/src/routes/console/project-[project]/overview/platforms/wizard/step4.svelte b/src/routes/console/project-[project]/overview/platforms/wizard/step4.svelte index 88a9ae2f7..a1e237d41 100644 --- a/src/routes/console/project-[project]/overview/platforms/wizard/step4.svelte +++ b/src/routes/console/project-[project]/overview/platforms/wizard/step4.svelte @@ -6,8 +6,7 @@ - - You're ready to go 🎉 + All set

    {#if isFirstProject} Congratulations on adding the first platform to your project! Start exploring by diff --git a/src/routes/console/project-[project]/overview/platforms/wizard/web/step2.svelte b/src/routes/console/project-[project]/overview/platforms/wizard/web/step2.svelte index 2eb9793eb..9c21ccc48 100644 --- a/src/routes/console/project-[project]/overview/platforms/wizard/web/step2.svelte +++ b/src/routes/console/project-[project]/overview/platforms/wizard/web/step2.svelte @@ -23,8 +23,7 @@ - - Get the SDK + Install Choose your preferred method of installation

    diff --git a/src/routes/console/wizard/cloudOrganizationChangeTier/usageExcess.svelte b/src/routes/console/wizard/cloudOrganizationChangeTier/usageExcess.svelte index 570d2a2c8..e5bd500fb 100644 --- a/src/routes/console/wizard/cloudOrganizationChangeTier/usageExcess.svelte +++ b/src/routes/console/wizard/cloudOrganizationChangeTier/usageExcess.svelte @@ -8,7 +8,6 @@ - Your usage exceeds the limits of the {tierToPlan($organization.billingPlan).name} plan View the current usage for {$organization.name} and where you will exceed the limits of diff --git a/src/routes/console/wizard/feedback/step1.svelte b/src/routes/console/wizard/feedback/step1.svelte index e2e408b1e..c3a665590 100644 --- a/src/routes/console/wizard/feedback/step1.svelte +++ b/src/routes/console/wizard/feedback/step1.svelte @@ -32,7 +32,6 @@ - {$selectedFeedback.title} {$selectedFeedback.desc} diff --git a/src/routes/console/wizard/feedback/step2.svelte b/src/routes/console/wizard/feedback/step2.svelte index 56d26c51c..66c1c2d56 100644 --- a/src/routes/console/wizard/feedback/step2.svelte +++ b/src/routes/console/wizard/feedback/step2.svelte @@ -6,8 +6,7 @@ - - Thanks for the feedback! + Thanks you
    {#if $app.themeInUse === 'dark'} diff --git a/src/routes/console/wizard/support/step1.svelte b/src/routes/console/wizard/support/step1.svelte index e82448d02..06f8f265b 100644 --- a/src/routes/console/wizard/support/step1.svelte +++ b/src/routes/console/wizard/support/step1.svelte @@ -21,7 +21,6 @@ - How can we help you? Please describe your request in detail. If applicable, include steps for reproduction of any From 8dfb58eaf5b09fb21b0f4d621cc0d9b7fe2d83f6 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Mon, 26 Feb 2024 16:08:17 +0000 Subject: [PATCH 298/403] chore: vincent suggestion --- src/routes/console/(migration-wizard)/step1.svelte | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/routes/console/(migration-wizard)/step1.svelte b/src/routes/console/(migration-wizard)/step1.svelte index e326ac5f3..c34166a7f 100644 --- a/src/routes/console/(migration-wizard)/step1.svelte +++ b/src/routes/console/(migration-wizard)/step1.svelte @@ -12,7 +12,6 @@ let selectedOrg = organizations.length ? organizations[0].$id : null; let projects = [] as Models.ProjectList['projects']; - $: hasProjects = projects.length > 0; let loadingProjects = false; let projectType = 'existing'; @@ -43,10 +42,7 @@ - - - {hasProjects ? 'Select project' : 'Create project'} - + Project
    {#if organizations.length > 1} From 7345a213acfa576120045d67ad1da0d0d8448bb1 Mon Sep 17 00:00:00 2001 From: "Luke B. Silver" <22452787+loks0n@users.noreply.github.com> Date: Tue, 27 Feb 2024 10:28:36 +0000 Subject: [PATCH 299/403] Update src/routes/console/wizard/feedback/step2.svelte Co-authored-by: Carla --- src/routes/console/wizard/feedback/step2.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/console/wizard/feedback/step2.svelte b/src/routes/console/wizard/feedback/step2.svelte index 66c1c2d56..6a79839c5 100644 --- a/src/routes/console/wizard/feedback/step2.svelte +++ b/src/routes/console/wizard/feedback/step2.svelte @@ -6,7 +6,7 @@ - Thanks you + Thank you
    {#if $app.themeInUse === 'dark'} From c218b0b5f13ac6ec45afb13d8e28790b9d9def49 Mon Sep 17 00:00:00 2001 From: wess Date: Tue, 27 Feb 2024 10:36:24 -0500 Subject: [PATCH 300/403] Adds Webbhook enable to analytics Adds disable/enable section to webhook details --- src/lib/actions/analytics.ts | 1 + .../settings/webhooks/[webhook]/+page.svelte | 2 + .../webhooks/[webhook]/details.svelte | 92 +++++++++++++++++++ .../webhooks/messageStatusPill.svelte | 6 +- 4 files changed, 98 insertions(+), 3 deletions(-) create mode 100644 src/routes/console/project-[project]/settings/webhooks/[webhook]/details.svelte diff --git a/src/lib/actions/analytics.ts b/src/lib/actions/analytics.ts index e967ec3d2..906576a49 100644 --- a/src/lib/actions/analytics.ts +++ b/src/lib/actions/analytics.ts @@ -245,6 +245,7 @@ export enum Submit { WebhookUpdateUrl = 'submit_webhook_update_url', WebhookUpdateEvents = 'submit_webhook_update_events', WebhookUpdateName = 'submit_webhook_update_name', + WebhookUpdateEnabled = 'submit_webhook_update_enabled', WebhookUpdateSecurity = 'submit_webhook_update_security', BucketCreate = 'submit_bucket_create', BucketDelete = 'submit_bucket_delete', diff --git a/src/routes/console/project-[project]/settings/webhooks/[webhook]/+page.svelte b/src/routes/console/project-[project]/settings/webhooks/[webhook]/+page.svelte index ab3bd3c63..329aa82df 100644 --- a/src/routes/console/project-[project]/settings/webhooks/[webhook]/+page.svelte +++ b/src/routes/console/project-[project]/settings/webhooks/[webhook]/+page.svelte @@ -6,9 +6,11 @@ import UpdateSecurity from './updateSecurity.svelte'; import UpdateSignature from './updateSignature.svelte'; import UpdateUrl from './updateURL.svelte'; + import Details from './details.svelte'; +
    diff --git a/src/routes/console/project-[project]/settings/webhooks/[webhook]/details.svelte b/src/routes/console/project-[project]/settings/webhooks/[webhook]/details.svelte new file mode 100644 index 000000000..74d50a026 --- /dev/null +++ b/src/routes/console/project-[project]/settings/webhooks/[webhook]/details.svelte @@ -0,0 +1,92 @@ + + + + {$webhook.url} + + +
    +
      + + + +
    • Created: {toLocaleDateTime($webhook.$createdAt)}
    • +
    • Last updated: {toLocaleDateTime($webhook.$updatedAt)}
    • +
    + +
    +
    + + + +
    + + +
    +
    + +
    + + + + + diff --git a/src/routes/console/project-[project]/settings/webhooks/messageStatusPill.svelte b/src/routes/console/project-[project]/settings/webhooks/messageStatusPill.svelte index 3b4fafae6..68dbf385a 100644 --- a/src/routes/console/project-[project]/settings/webhooks/messageStatusPill.svelte +++ b/src/routes/console/project-[project]/settings/webhooks/messageStatusPill.svelte @@ -3,13 +3,13 @@ export let enabled: boolean; - const style = `color: ${enabled ? 'hsl(var(--color-success-100))' : 'hsl(var(--color-danger-100))'}`; - const iconClass = enabled ? 'icon-check-circle' : 'icon-exclamation-circle'; + $:style = `color: ${enabled ? 'hsl(var(--color-success-100))' : 'hsl(var(--color-danger-100))'}`; + $:iconClass = (enabled ? 'icon-check-circle' : 'icon-exclamation-circle') + ' u-font-size-12'; -
    -
    - -
    + {#if message.status === MessageStatus.Draft} +
    + +
    + {/if}
    {/each} diff --git a/src/routes/console/project-[project]/messaging/message-[message]/updateTopics.svelte b/src/routes/console/project-[project]/messaging/message-[message]/updateTopics.svelte index 96dd7ab4c..26d18021d 100644 --- a/src/routes/console/project-[project]/messaging/message-[message]/updateTopics.svelte +++ b/src/routes/console/project-[project]/messaging/message-[message]/updateTopics.svelte @@ -123,24 +123,27 @@ ({getTotal(topic)} targets) - + +
    -
    - -
    + {#if message.status === MessageStatus.Draft} +
    + +
    + {/if}
    {/each} From 02fdd950b6b1ee546cd54117656d9350328b9fea Mon Sep 17 00:00:00 2001 From: Khushboo Verma <43381712+vermakhushboo@users.noreply.github.com> Date: Tue, 27 Feb 2024 17:09:28 +0530 Subject: [PATCH 303/403] Update execution placeholder body --- .../functions/function-[function]/execute.svelte | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/routes/console/project-[project]/functions/function-[function]/execute.svelte b/src/routes/console/project-[project]/functions/function-[function]/execute.svelte index a8460d6db..57d52063d 100644 --- a/src/routes/console/project-[project]/functions/function-[function]/execute.svelte +++ b/src/routes/console/project-[project]/functions/function-[function]/execute.svelte @@ -121,11 +121,7 @@
    - + {:else} @@ -214,7 +210,7 @@ From f29089a748e6812970834b3c70dc3dedff17e30c Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Mon, 26 Feb 2024 16:36:04 -0800 Subject: [PATCH 304/403] fix(messaging): show users w/o targets as disabled --- src/lib/components/collapsibleItem.svelte | 35 ++++++++++++++++--- .../messaging/userTargetsModal.svelte | 30 +++++++++++----- 2 files changed, 53 insertions(+), 12 deletions(-) diff --git a/src/lib/components/collapsibleItem.svelte b/src/lib/components/collapsibleItem.svelte index 736f2fe21..3420b555c 100644 --- a/src/lib/components/collapsibleItem.svelte +++ b/src/lib/components/collapsibleItem.svelte @@ -3,10 +3,11 @@ export let withIndentation = false; export let open = false; + export let disabled = false;
  • -
    +
    - + {#if $$slots.subtitle} - + {/if}
    -
  • + + diff --git a/src/routes/console/project-[project]/messaging/userTargetsModal.svelte b/src/routes/console/project-[project]/messaging/userTargetsModal.svelte index 7552144aa..271f94ecc 100644 --- a/src/routes/console/project-[project]/messaging/userTargetsModal.svelte +++ b/src/routes/console/project-[project]/messaging/userTargetsModal.svelte @@ -132,22 +132,20 @@ {@const selectedCount = user.targets.filter( (target) => selected[target.$id] ).length} - + 0 && - user.targets.every((target) => targetsById[target.$id])} + disabled={!user.targets.length || + (user.targets.length > 0 && + user.targets.every((target) => targetsById[target.$id]))} checked={selectedCount > 0 && selectedCount === user.targets.length} on:change={(event) => onUserSelection(event, userId)} /> - + {#if user.name} {user.name} {:else if user.email} @@ -161,7 +159,11 @@ - ({selectedCount}/{user.targets.length} targets) + {#if user.targets.length === 0} + (0 targets) + {:else} + ({selectedCount}/{user.targets.length} targets) + {/if} {#each user.targets as target} @@ -235,3 +237,15 @@ + + From f492837dd4197c3c1a07e77b3232d3afbebd5c5a Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Mon, 26 Feb 2024 15:51:18 -0800 Subject: [PATCH 305/403] fix(messaging): update link to docs regarding subscribers --- .../topics/topic-[topic]/subscribers/+page.svelte | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) 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 index c5c308a5e..622b6bf41 100644 --- 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 @@ -146,7 +146,7 @@ (showAdd = true)} - href="https://appwrite.io/docs/products/messaging/topics/#subscribe-targets-to-topics" + href="https://appwrite.io/docs/products/messaging/topics#subscribe-targets-to-topics" target="subscriber" /> {/if} @@ -159,10 +159,11 @@

    Add subscribers to this topic by selecting the targets for directing messages. Learn more about subscribers. + class="link">Learn more about subscribers.

    From e9004be4d8a64df25f19a8676ec0cbcd0dd3450b Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Mon, 26 Feb 2024 15:20:03 -0800 Subject: [PATCH 306/403] fix(messaging): fix provider docs link --- .../messaging/providers/wizard/settings.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/console/project-[project]/messaging/providers/wizard/settings.svelte b/src/routes/console/project-[project]/messaging/providers/wizard/settings.svelte index 57908ad4b..e995a63a1 100644 --- a/src/routes/console/project-[project]/messaging/providers/wizard/settings.svelte +++ b/src/routes/console/project-[project]/messaging/providers/wizard/settings.svelte @@ -97,7 +97,7 @@
    From dce4dc4a989cdf62b50d879278e9eb0ef625d67c Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Mon, 26 Feb 2024 15:20:22 -0800 Subject: [PATCH 307/403] fix(messaging) fix need a hand hover color --- .../messaging/providers/wizard/settings.svelte | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/routes/console/project-[project]/messaging/providers/wizard/settings.svelte b/src/routes/console/project-[project]/messaging/providers/wizard/settings.svelte index e995a63a1..46dc634e5 100644 --- a/src/routes/console/project-[project]/messaging/providers/wizard/settings.svelte +++ b/src/routes/console/project-[project]/messaging/providers/wizard/settings.svelte @@ -135,7 +135,7 @@ diff --git a/src/routes/console/account/updateMfa.svelte b/src/routes/console/account/updateMfa.svelte index 140943222..28ebea5d5 100644 --- a/src/routes/console/account/updateMfa.svelte +++ b/src/routes/console/account/updateMfa.svelte @@ -88,5 +88,7 @@ - +{#if showSetup} + +{/if} From a03b54180bfb8ba828d19746e0954e4516db6fca Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Thu, 29 Feb 2024 14:35:02 +0100 Subject: [PATCH 334/403] fix: remove unused import --- src/routes/console/account/mfa.svelte | 1 - 1 file changed, 1 deletion(-) diff --git a/src/routes/console/account/mfa.svelte b/src/routes/console/account/mfa.svelte index 4aa5f71c7..245cbb936 100644 --- a/src/routes/console/account/mfa.svelte +++ b/src/routes/console/account/mfa.svelte @@ -2,7 +2,6 @@ import { invalidate } from '$app/navigation'; import { Submit, trackError } from '$lib/actions/analytics'; import { Modal, Output, Copy, Alert } from '$lib/components'; - import LoadingDots from '$lib/components/loadingDots.svelte'; import { Dependencies } from '$lib/constants'; import { Button, FormList, InputDigits } from '$lib/elements/forms'; import { Table, TableBody, TableCell, TableRow } from '$lib/elements/table'; From e51f3106dbbc80f2cfef0f8666312781d4655bb4 Mon Sep 17 00:00:00 2001 From: wess Date: Thu, 29 Feb 2024 09:23:16 -0500 Subject: [PATCH 335/403] Color updates Sentence Case Update webhook button now takes to details view correctly Shows actual webhook id instead of Webhook ID Fixes spacing between Disabled toggle and Created --- .../console/project-[project]/settings/webhooks/+page.svelte | 2 +- .../settings/webhooks/[webhook]/details.svelte | 3 ++- .../settings/webhooks/[webhook]/header.svelte | 2 +- .../project-[project]/settings/webhooks/failedModal.svelte | 5 +++-- .../settings/webhooks/messageStatusPill.svelte | 2 +- 5 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/routes/console/project-[project]/settings/webhooks/+page.svelte b/src/routes/console/project-[project]/settings/webhooks/+page.svelte index 057859cb0..4adbdffad 100644 --- a/src/routes/console/project-[project]/settings/webhooks/+page.svelte +++ b/src/routes/console/project-[project]/settings/webhooks/+page.svelte @@ -51,7 +51,7 @@ diff --git a/src/routes/console/project-[project]/settings/webhooks/[webhook]/details.svelte b/src/routes/console/project-[project]/settings/webhooks/[webhook]/details.svelte index 9b7ffd46e..37424e263 100644 --- a/src/routes/console/project-[project]/settings/webhooks/[webhook]/details.svelte +++ b/src/routes/console/project-[project]/settings/webhooks/[webhook]/details.svelte @@ -66,7 +66,8 @@ id="enable-switch" bind:value={enabled} /> -
  • Created: {toLocaleDateTime($webhook.$createdAt)}
  • + +
  • Created: {toLocaleDateTime($webhook.$createdAt)}
  • Last updated: {toLocaleDateTime($webhook.$updatedAt)}
  • diff --git a/src/routes/console/project-[project]/settings/webhooks/[webhook]/header.svelte b/src/routes/console/project-[project]/settings/webhooks/[webhook]/header.svelte index 9a09cbb01..8debdc385 100644 --- a/src/routes/console/project-[project]/settings/webhooks/[webhook]/header.svelte +++ b/src/routes/console/project-[project]/settings/webhooks/[webhook]/header.svelte @@ -12,6 +12,6 @@ {$webhook?.name} - Webhook ID + {$webhook?.$id} diff --git a/src/routes/console/project-[project]/settings/webhooks/failedModal.svelte b/src/routes/console/project-[project]/settings/webhooks/failedModal.svelte index a9d0342fd..67437a82b 100644 --- a/src/routes/console/project-[project]/settings/webhooks/failedModal.svelte +++ b/src/routes/console/project-[project]/settings/webhooks/failedModal.svelte @@ -12,7 +12,8 @@ export let showUpdateButton: boolean = true; const projectId = $page.params.project; - const webhookPath = webhook + + $: webhookPath = webhook ? `${base}/console/project-${projectId}/settings/webhooks/` + (webhook['$id'] ?? '') : ''; @@ -31,7 +32,7 @@

    {#if showUpdateButton} - + {/if}
    diff --git a/src/routes/console/project-[project]/settings/webhooks/messageStatusPill.svelte b/src/routes/console/project-[project]/settings/webhooks/messageStatusPill.svelte index 9681c91a0..2c12a4ee0 100644 --- a/src/routes/console/project-[project]/settings/webhooks/messageStatusPill.svelte +++ b/src/routes/console/project-[project]/settings/webhooks/messageStatusPill.svelte @@ -3,7 +3,7 @@ export let enabled: boolean; - $: style = `color: ${enabled ? 'hsl(var(--color-success-100))' : 'hsl(var(--color-danger-100))'}`; + $: style = `color: ${enabled ? 'hsl(var(--color-success-120))' : 'hsl(var(--color-danger-120))'}`; $: iconClass = (enabled ? 'icon-check-circle' : 'icon-exclamation-circle') + ' u-font-size-12'; From c35ff02df79cf0180dc8ba254510bc1de9856347 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Thu, 29 Feb 2024 21:12:00 +0530 Subject: [PATCH 336/403] chore: add prefix keys --- src/lib/commandCenter/commands.ts | 1 + src/lib/commandCenter/searchers/messages.ts | 17 +++++++++++++-- src/lib/commandCenter/searchers/providers.ts | 15 ++++++++++++- src/routes/auth/+layout.svelte | 21 ------------------- src/routes/console/+layout.svelte | 8 +++---- .../console/project-[project]/+layout.svelte | 19 +++++++++-------- .../project-[project]/auth/+layout.svelte | 19 ++++++++++++++++- .../messaging/+layout.svelte | 7 ++++--- .../topics/topic-[topic]/+layout.svelte | 18 ++++++++++++---- 9 files changed, 80 insertions(+), 45 deletions(-) diff --git a/src/lib/commandCenter/commands.ts b/src/lib/commandCenter/commands.ts index 304ccf603..c24491b6d 100644 --- a/src/lib/commandCenter/commands.ts +++ b/src/lib/commandCenter/commands.ts @@ -18,6 +18,7 @@ const groups = [ 'databases', 'functions', 'messaging', + 'messages', 'providers', 'topics', 'storage', diff --git a/src/lib/commandCenter/searchers/messages.ts b/src/lib/commandCenter/searchers/messages.ts index 42f871337..a9d8fc54f 100644 --- a/src/lib/commandCenter/searchers/messages.ts +++ b/src/lib/commandCenter/searchers/messages.ts @@ -18,6 +18,19 @@ const getLabel = (message) => { } }; +const getIcon = (message) => { + switch (message.providerType) { + case MessagingProviderType.Push: + return 'device-mobile'; + case MessagingProviderType.Sms: + return 'annotation'; + case MessagingProviderType.Email: + return 'mail'; + default: + return 'send'; + } +} + export const messagesSearcher = (async (query: string) => { const { messages } = await sdk.forProject.messaging.listMessages([], query || undefined); @@ -29,12 +42,12 @@ export const messagesSearcher = (async (query: string) => { .map( (message) => ({ - group: 'messaging', + group: 'messages', label: getLabel(message), callback: () => { goto(`/console/project-${projectId}/messaging/message-${message.$id}`); }, - icon: 'send', + icon: getIcon(message), }) as const ); }) satisfies Searcher; diff --git a/src/lib/commandCenter/searchers/providers.ts b/src/lib/commandCenter/searchers/providers.ts index 289bbe826..d52877db9 100644 --- a/src/lib/commandCenter/searchers/providers.ts +++ b/src/lib/commandCenter/searchers/providers.ts @@ -4,6 +4,19 @@ import { get } from 'svelte/store'; import type { Searcher } from '../commands'; import { sdk } from '$lib/stores/sdk'; +const getIcon = (provider) => { + switch (provider.type) { + case MessagingProviderType.Push: + return 'device-mobile'; + case MessagingProviderType.Sms: + return 'annotation'; + case MessagingProviderType.Email: + return 'mail'; + default: + return 'send'; + } +} + export const providersSearcher = (async (query: string) => { const { providers } = await sdk.forProject.messaging.listProviders([], query || undefined); @@ -20,7 +33,7 @@ export const providersSearcher = (async (query: string) => { callback: () => { goto(`/console/project-${projectId}/messaging/providers/provider-${provider.$id}`); }, - icon: 'cloud', + icon: getIcon(provider), }) as const ); }) satisfies Searcher; diff --git a/src/routes/auth/+layout.svelte b/src/routes/auth/+layout.svelte index 68866be64..f2ffcf1d2 100644 --- a/src/routes/auth/+layout.svelte +++ b/src/routes/auth/+layout.svelte @@ -1,29 +1,8 @@ diff --git a/src/routes/console/+layout.svelte b/src/routes/console/+layout.svelte index 98ce25767..cca3baecb 100644 --- a/src/routes/console/+layout.svelte +++ b/src/routes/console/+layout.svelte @@ -56,7 +56,7 @@ $: $registerCommands([ { - label: 'Go to projects', + label: 'Go to Projects', callback: () => { goto('/console'); }, @@ -66,7 +66,7 @@ $page.url.pathname.includes('/console/organization-') && !$page.url.pathname.endsWith('/members') && !$page.url.pathname.endsWith('/settings'), - rank: -1 + rank: -1 }, { label: 'Ask the AI', @@ -78,11 +78,11 @@ disabled: !isAssistantEnabled }, { - label: 'Go to account', + label: 'Go to Account', callback: () => { goto('/console/account'); }, - keys: ['i'], + keys: ['g', 'i'], group: 'navigation', rank: -2 }, diff --git a/src/routes/console/project-[project]/+layout.svelte b/src/routes/console/project-[project]/+layout.svelte index f025da2ec..11c9ba940 100644 --- a/src/routes/console/project-[project]/+layout.svelte +++ b/src/routes/console/project-[project]/+layout.svelte @@ -15,6 +15,7 @@ userSearcher } from '$lib/commandCenter/searchers'; import { MigrationBox } from '$lib/components'; + import { page } from '$app/stores'; onMount(() => { return sdk.forConsole.client.subscribe(['project', 'console'], (response) => { @@ -32,7 +33,7 @@ callback: () => { goto(`/console/project-${$project.$id}/auth`); }, - keys: ['a'], + keys: ['g', 'a'], group: 'navigation' }, { @@ -40,7 +41,7 @@ callback: () => { goto(`/console/project-${$project.$id}/databases`); }, - keys: ['d'], + keys: ['g', 'd'], group: 'navigation' }, { @@ -48,7 +49,7 @@ callback: () => { goto(`/console/project-${$project.$id}/functions`); }, - keys: ['f'], + keys: ['g', 'f'], group: 'navigation' }, { @@ -56,7 +57,7 @@ callback: () => { goto(`/console/project-${$project.$id}/messaging`); }, - keys: ['m'], + keys: $page.url.pathname.includes('messaging') ? ['m'] : ['g', 'm'], group: 'navigation' }, { @@ -64,23 +65,23 @@ callback: () => { goto(`/console/project-${$project.$id}/storage`); }, - keys: ['s'], + keys: ['g', 's'], group: 'navigation' }, { - label: 'Go to settings', + label: 'Go to Settings', callback: () => { goto(`/console/project-${$project.$id}/settings`); }, - keys: ['p'], + keys: ['g', 'e'], group: 'navigation' }, { - label: 'Go to overview', + label: 'Go to Overview', callback: () => { goto(`/console/project-${$project.$id}`); }, - keys: ['o'], + keys: ['g', 'o'], group: 'navigation' } ]); diff --git a/src/routes/console/project-[project]/auth/+layout.svelte b/src/routes/console/project-[project]/auth/+layout.svelte index cfb6a198b..ca114d653 100644 --- a/src/routes/console/project-[project]/auth/+layout.svelte +++ b/src/routes/console/project-[project]/auth/+layout.svelte @@ -1,7 +1,8 @@
    -
    -
    - - - From 2d8bf22cd80c0f568b1bf99e60e7f08cf36666f7 Mon Sep 17 00:00:00 2001 From: wess Date: Thu, 29 Feb 2024 13:48:23 -0500 Subject: [PATCH 339/403] linting --- src/lib/layout/unauthenticated.svelte | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/lib/layout/unauthenticated.svelte b/src/lib/layout/unauthenticated.svelte index a62b2e952..7c16c7a8d 100644 --- a/src/lib/layout/unauthenticated.svelte +++ b/src/lib/layout/unauthenticated.svelte @@ -56,7 +56,6 @@ - From ec1c6ac65c97563c2d07b9ed3e4da1ad90d479da Mon Sep 17 00:00:00 2001 From: wess Date: Thu, 29 Feb 2024 13:49:11 -0500 Subject: [PATCH 340/403] Shows details if hook is disabled --- .../console/project-[project]/settings/webhooks/+page.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/console/project-[project]/settings/webhooks/+page.svelte b/src/routes/console/project-[project]/settings/webhooks/+page.svelte index 4adbdffad..ea1a2cbe6 100644 --- a/src/routes/console/project-[project]/settings/webhooks/+page.svelte +++ b/src/routes/console/project-[project]/settings/webhooks/+page.svelte @@ -94,7 +94,7 @@   - {#if webhook.enabled === false && webhook.attempts > 0} + {#if webhook.enabled === false} +
    +
    + + +
    + + + +
    +
    +
    +
    + + +
    +
    + + +
    +
    +
    + {#if data.subscribers.total} +
    + + + {:else if $hasPageQueries} + + {:else if data.search} + +
    + Sorry, we couldn't find '{data.search}' +

    There are no subscribers that match your search.

    +
    + +
    + {:else} + (showAdd = true)} + href="https://appwrite.io/docs/products/messaging/topics#subscribe-targets-to-topics" + target="subscriber" /> + {/if} + + + +

    + Add subscribers to this topic by selecting the targets for directing messages. Learn more about subscribers. +

    +
    +
    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]/+page.ts similarity index 100% rename from src/routes/console/project-[project]/messaging/topics/topic-[topic]/subscribers/+page.ts rename to src/routes/console/project-[project]/messaging/topics/topic-[topic]/+page.ts 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 index 0848e48db..680a967e5 100644 --- a/src/routes/console/project-[project]/messaging/topics/topic-[topic]/header.svelte +++ b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/header.svelte @@ -11,11 +11,6 @@ const tabs = [ { href: path, - title: 'Overview', - event: 'overview' - }, - { - href: `${path}/subscribers`, title: 'Subscribers', event: 'subscribers' }, @@ -23,6 +18,11 @@ href: `${path}/activity`, title: 'Activity', event: 'activity' + }, + { + href: `${path}/settings`, + title: 'Settings', + event: 'settings' } ]; diff --git a/src/routes/console/project-[project]/messaging/topics/topic-[topic]/settings/+page.svelte b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/settings/+page.svelte new file mode 100644 index 000000000..8c5837596 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/settings/+page.svelte @@ -0,0 +1,14 @@ + + + +
    + + + + diff --git a/src/routes/console/project-[project]/messaging/topics/topic-[topic]/dangerZone.svelte b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/settings/dangerZone.svelte similarity index 54% rename from src/routes/console/project-[project]/messaging/topics/topic-[topic]/dangerZone.svelte rename to src/routes/console/project-[project]/messaging/topics/topic-[topic]/settings/dangerZone.svelte index b9a2801bd..4758bcd6f 100644 --- a/src/routes/console/project-[project]/messaging/topics/topic-[topic]/dangerZone.svelte +++ b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/settings/dangerZone.svelte @@ -1,20 +1,10 @@ - - @@ -37,9 +27,9 @@ - - + diff --git a/src/routes/console/project-[project]/messaging/topics/topic-[topic]/details.svelte b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/settings/details.svelte similarity index 92% rename from src/routes/console/project-[project]/messaging/topics/topic-[topic]/details.svelte rename to src/routes/console/project-[project]/messaging/topics/topic-[topic]/settings/details.svelte index 09e919152..be120ba35 100644 --- a/src/routes/console/project-[project]/messaging/topics/topic-[topic]/details.svelte +++ b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/settings/details.svelte @@ -1,7 +1,7 @@ diff --git a/src/routes/console/project-[project]/messaging/topics/topic-[topic]/updateName.svelte b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/settings/updateName.svelte similarity index 97% rename from src/routes/console/project-[project]/messaging/topics/topic-[topic]/updateName.svelte rename to src/routes/console/project-[project]/messaging/topics/topic-[topic]/settings/updateName.svelte index 4b9305911..ad1e1998b 100644 --- a/src/routes/console/project-[project]/messaging/topics/topic-[topic]/updateName.svelte +++ b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/settings/updateName.svelte @@ -2,7 +2,7 @@ import { CardGrid, Heading } from '$lib/components'; import { Button, Form, InputText } from '$lib/elements/forms'; import { onMount } from 'svelte'; - import { topic } from './store'; + import { topic } from '../store'; import { invalidate } from '$app/navigation'; import { trackEvent, Submit, trackError } from '$lib/actions/analytics'; import { Dependencies } from '$lib/constants'; diff --git a/src/routes/console/project-[project]/messaging/topics/topic-[topic]/updatePermissions.svelte b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/settings/updatePermissions.svelte similarity index 98% rename from src/routes/console/project-[project]/messaging/topics/topic-[topic]/updatePermissions.svelte rename to src/routes/console/project-[project]/messaging/topics/topic-[topic]/settings/updatePermissions.svelte index c74b1ad10..7fff86143 100644 --- a/src/routes/console/project-[project]/messaging/topics/topic-[topic]/updatePermissions.svelte +++ b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/settings/updatePermissions.svelte @@ -10,7 +10,7 @@ import { onMount } from 'svelte'; import { Roles } from '$lib/components/permissions'; import { symmetricDifference } from '$lib/helpers/array'; - import { topic } from './store'; + import { topic } from '../store'; const topicId = $page.params.topic; 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 index dec5bf146..29c6212f5 100644 --- a/src/routes/console/project-[project]/messaging/topics/topic-[topic]/store.ts +++ b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/store.ts @@ -1,6 +1,7 @@ -import { derived } from 'svelte/store'; +import { derived, writable } from 'svelte/store'; import { page } from '$app/stores'; import type { Models } from '@appwrite.io/console'; +import type { Column } from '$lib/helpers/types'; export const topic = derived( page, @@ -11,3 +12,11 @@ export const topicTotal = derived( topic, ($topic) => $topic.emailTotal + $topic.smsTotal + $topic.pushTotal ); +export const columns = writable([ + { id: '$id', title: 'Subscriber ID', type: 'string', show: true, width: 140 }, + { id: 'userName', title: 'Name', type: 'string', show: true, filter: false, width: 100 }, + { id: 'targetId', title: 'Target ID', type: 'string', show: true, width: 140 }, + { id: 'target', title: 'Target', type: 'string', show: true, filter: false, width: 140 }, + { id: 'type', title: 'Type', type: 'string', show: true, width: 80 }, + { id: '$createdAt', title: 'Created', type: 'datetime', show: true, width: 100 } +]); \ No newline at end of file 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 deleted file mode 100644 index 622b6bf41..000000000 --- a/src/routes/console/project-[project]/messaging/topics/topic-[topic]/subscribers/+page.svelte +++ /dev/null @@ -1,169 +0,0 @@ - - - -
    -
    - Subscribers -
    - -
    -
    - - -
    - - - -
    -
    -
    -
    - - -
    -
    - - -
    -
    -
    - {#if data.subscribers.total} -
    - - - {:else if $hasPageQueries} - - {:else if data.search} - -
    - Sorry, we couldn't find '{data.search}' -

    There are no subscribers that match your search.

    -
    - -
    - {:else} - (showAdd = true)} - href="https://appwrite.io/docs/products/messaging/topics#subscribe-targets-to-topics" - target="subscriber" /> - {/if} - - - - -

    - Add subscribers to this topic by selecting the targets for directing messages. Learn more about 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 deleted file mode 100644 index f5186a589..000000000 --- a/src/routes/console/project-[project]/messaging/topics/topic-[topic]/subscribers/store.ts +++ /dev/null @@ -1,11 +0,0 @@ -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, filter: false, width: 100 }, - { id: 'targetId', title: 'Target ID', type: 'string', show: true, width: 140 }, - { id: 'target', title: 'Target', type: 'string', show: true, filter: false, width: 140 }, - { id: 'type', title: 'Type', type: 'string', show: true, width: 80 }, - { id: '$createdAt', title: 'Created', type: 'datetime', 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]/table.svelte similarity index 98% rename from src/routes/console/project-[project]/messaging/topics/topic-[topic]/subscribers/table.svelte rename to src/routes/console/project-[project]/messaging/topics/topic-[topic]/table.svelte index 8fce7c8c3..56ccf7cec 100644 --- a/src/routes/console/project-[project]/messaging/topics/topic-[topic]/subscribers/table.svelte +++ b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/table.svelte @@ -19,12 +19,12 @@ import { addNotification } from '$lib/stores/notifications'; import type { PageData } from './$types'; import { columns } from './store'; - import ProviderType from '../../../providerType.svelte'; + import ProviderType from '../../providerType.svelte'; import { toLocaleDateTime } from '$lib/helpers/date'; import { project } from '$routes/console/project-[project]/store'; import { sdk } from '$lib/stores/sdk'; import { page } from '$app/stores'; - import { targetsById } from '../../../store'; + import { targetsById } from '../../store'; import { MessagingProviderType, type Models } from '@appwrite.io/console'; export let data: PageData; From d8a30856f1dcda74984d06844efc757b5b18f3cc Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Thu, 29 Feb 2024 20:26:23 -0800 Subject: [PATCH 353/403] fix(messaging): localize the subscribers columns When it was global, the state (show values) would persist when switching between different projects rather than resetting back to the default. --- .../messaging/topics/topic-[topic]/+page.svelte | 13 +++++++++++-- .../messaging/topics/topic-[topic]/store.ts | 11 +---------- .../messaging/topics/topic-[topic]/table.svelte | 9 +++++---- 3 files changed, 17 insertions(+), 16 deletions(-) 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 index cf086e081..7b977d1ee 100644 --- a/src/routes/console/project-[project]/messaging/topics/topic-[topic]/+page.svelte +++ b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/+page.svelte @@ -23,12 +23,21 @@ import UserTargetsModal from '../../userTargetsModal.svelte'; import { onMount } from 'svelte'; import { Filters, hasPageQueries } from '$lib/components/filters'; - import { columns } from './store'; import { View } from '$lib/helpers/load'; + import { writable } from 'svelte/store'; + import type { Column } from '$lib/helpers/types'; export let data: PageData; let showAdd = false; let subscribersByTargetId: Record = {}; + const columns = writable([ + { id: '$id', title: 'Subscriber ID', type: 'string', show: true, width: 140 }, + { id: 'userName', title: 'Name', type: 'string', show: true, filter: false, width: 100 }, + { id: 'targetId', title: 'Target ID', type: 'string', show: true, width: 140 }, + { id: 'target', title: 'Target', type: 'string', show: true, filter: false, width: 140 }, + { id: 'type', title: 'Type', type: 'string', show: true, width: 80 }, + { id: '$createdAt', title: 'Created', type: 'datetime', show: true, width: 100 } + ]); onMount(() => { $targetsById = {}; @@ -121,7 +130,7 @@ {#if data.subscribers.total} -
    +
    $topic.emailTotal + $topic.smsTotal + $topic.pushTotal ); -export const columns = writable([ - { id: '$id', title: 'Subscriber ID', type: 'string', show: true, width: 140 }, - { id: 'userName', title: 'Name', type: 'string', show: true, filter: false, width: 100 }, - { id: 'targetId', title: 'Target ID', type: 'string', show: true, width: 140 }, - { id: 'target', title: 'Target', type: 'string', show: true, filter: false, width: 140 }, - { id: 'type', title: 'Type', type: 'string', show: true, width: 80 }, - { id: '$createdAt', title: 'Created', type: 'datetime', show: true, width: 100 } -]); \ No newline at end of file diff --git a/src/routes/console/project-[project]/messaging/topics/topic-[topic]/table.svelte b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/table.svelte index 56ccf7cec..e469b7991 100644 --- a/src/routes/console/project-[project]/messaging/topics/topic-[topic]/table.svelte +++ b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/table.svelte @@ -18,7 +18,6 @@ } from '$lib/elements/table'; import { addNotification } from '$lib/stores/notifications'; import type { PageData } from './$types'; - import { columns } from './store'; import ProviderType from '../../providerType.svelte'; import { toLocaleDateTime } from '$lib/helpers/date'; import { project } from '$routes/console/project-[project]/store'; @@ -26,7 +25,9 @@ import { page } from '$app/stores'; import { targetsById } from '../../store'; import { MessagingProviderType, type Models } from '@appwrite.io/console'; + import type { Column } from '$lib/helpers/types'; + export let columns: Column[]; export let data: PageData; let subscribers: Record = {}; @@ -84,7 +85,7 @@ d.$id)} /> - {#each $columns as column} + {#each columns as column} {#if column.show} {column.title} {/if} @@ -97,10 +98,10 @@ href={`${base}/console/project-${$project.$id}/auth/user-${subscriber.target.userId}`}> - {#each $columns as column} + {#each columns as column} {#if column.show} {#if column.id === '$id'} - {#key $columns} + {#key column.id} {subscriber.$id} From 86af600143f06c941348edbe2e893282e4694853 Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Thu, 29 Feb 2024 20:37:01 -0800 Subject: [PATCH 354/403] fix(components): only override columns if prefs found Before this, it didn't matter if a column had show = false as it would default to be show if preferences weren't found. --- src/lib/components/viewSelector.svelte | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/lib/components/viewSelector.svelte b/src/lib/components/viewSelector.svelte index 0ece86889..4aeb21dd7 100644 --- a/src/lib/components/viewSelector.svelte +++ b/src/lib/components/viewSelector.svelte @@ -31,12 +31,15 @@ } else { const prefs = preferences.get($page.route); - columns.set( - $columns.map((column) => { - column.show = prefs.columns?.includes(column.id) ?? true; - return column; - }) - ); + // Override the shown columns only if a preference was set + if (prefs?.columns) { + columns.set( + $columns.map((column) => { + column.show = prefs.columns?.includes(column.id) ?? true; + return column; + }) + ); + } } columns.subscribe((ctx) => { From 6991e5bf32a3ca7fcc77c8e3cccf63a8c736d8cb Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Thu, 29 Feb 2024 20:46:22 -0800 Subject: [PATCH 355/403] fix(messaging): localize the topics columns When it was global, the state (show values) would persist when switching between different projects rather than resetting back to the default. --- .../messaging/topics/+page.svelte | 23 +++++++++++++++++-- .../messaging/topics/store.ts | 11 --------- .../messaging/topics/table.svelte | 9 ++++---- 3 files changed, 26 insertions(+), 17 deletions(-) diff --git a/src/routes/console/project-[project]/messaging/topics/+page.svelte b/src/routes/console/project-[project]/messaging/topics/+page.svelte index 4cd0959c8..118d31a46 100644 --- a/src/routes/console/project-[project]/messaging/topics/+page.svelte +++ b/src/routes/console/project-[project]/messaging/topics/+page.svelte @@ -16,14 +16,33 @@ import { base } from '$app/paths'; import type { Models } from '@appwrite.io/console'; import type { PageData } from './$types'; - import { columns, showCreate } from './store'; + import { showCreate } from './store'; import { View } from '$lib/helpers/load'; import { Filters, hasPageQueries } from '$lib/components/filters'; import Table from './table.svelte'; + import type { Column } from '$lib/helpers/types'; + import { writable } from 'svelte/store'; export let data: PageData; const project = $page.params.project; + 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: 'emailTotal', title: 'Email Subscribers', type: 'integer', show: false, width: 140 }, + { id: 'smsTotal', title: 'SMS Subscribers', type: 'integer', show: false, width: 140 }, + { id: 'pushTotal', title: 'Push Subscribers', type: 'integer', show: false, width: 140 }, + { + id: 'total', + title: 'Subscribers', + type: 'integer', + show: true, + filter: false, + width: 140 + }, + { id: '$createdAt', title: 'Created', type: 'datetime', show: true, width: 140 } + ]); + const topicCreated = async (event: CustomEvent>>) => { await goto(`${base}/console/project-${project}/messaging/topics/topic-${event.detail.$id}`); }; @@ -73,7 +92,7 @@ {#if data.topics.total} -
    +
    ([ - { id: '$id', title: 'Topic ID', type: 'string', show: true, width: 140 }, - { id: 'name', title: 'Name', type: 'string', show: true, width: 140 }, - { id: 'emailTotal', title: 'Email Subscribers', type: 'integer', show: false, width: 140 }, - { id: 'smsTotal', title: 'SMS Subscribers', type: 'integer', show: false, width: 140 }, - { id: 'pushTotal', title: 'Push Subscribers', type: 'integer', show: false, width: 140 }, - { id: 'total', title: 'Subscribers', type: 'integer', show: true, filter: false, 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 index 8e611a83b..9ffc0b2eb 100644 --- a/src/routes/console/project-[project]/messaging/topics/table.svelte +++ b/src/routes/console/project-[project]/messaging/topics/table.svelte @@ -16,13 +16,14 @@ } from '$lib/elements/table'; import { addNotification } from '$lib/stores/notifications'; import type { PageData } from './$types'; - import { columns } from './store'; import { project } from '$routes/console/project-[project]/store'; import { invalidate } from '$app/navigation'; import { Dependencies } from '$lib/constants'; import { sdk } from '$lib/stores/sdk'; import { toLocaleDateTime } from '$lib/helpers/date'; + import type { Column } from '$lib/helpers/types'; + export let columns: Column[]; export let data: PageData; let selectedIds: string[] = []; @@ -62,7 +63,7 @@ d.$id)} /> - {#each $columns as column} + {#each columns as column} {#if column.show} {column.title} {/if} @@ -74,10 +75,10 @@ href={`${base}/console/project-${$project.$id}/messaging/topics/topic-${topic.$id}`}> - {#each $columns as column (column.id)} + {#each columns as column (column.id)} {#if column.show} {#if column.id === '$id'} - {#key $columns} + {#key column.id} {topic.$id} From 2c8acf343097b8342a15fda8794ad3f6b9361eb3 Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Thu, 29 Feb 2024 20:49:10 -0800 Subject: [PATCH 356/403] fix(messaging): localize the messages columns When it was global, the state (show values) would persist when switching between different projects rather than resetting back to the default. --- .../console/project-[project]/messaging/+page.svelte | 12 +++++++++++- .../console/project-[project]/messaging/store.ts | 10 ---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/routes/console/project-[project]/messaging/+page.svelte b/src/routes/console/project-[project]/messaging/+page.svelte index e27bd3f07..ea367ea75 100644 --- a/src/routes/console/project-[project]/messaging/+page.svelte +++ b/src/routes/console/project-[project]/messaging/+page.svelte @@ -34,12 +34,14 @@ import FailedModal from './failedModal.svelte'; import MessageStatusPill from './messageStatusPill.svelte'; import ProviderType from './providerType.svelte'; - import { columns, showCreate } from './store'; + import { showCreate } from './store'; import { sdk } from '$lib/stores/sdk'; import { invalidate } from '$app/navigation'; import { trackEvent, Submit, trackError } from '$lib/actions/analytics'; import { Dependencies } from '$lib/constants'; import { addNotification } from '$lib/stores/notifications'; + import type { Column } from '$lib/helpers/types'; + import { writable } from 'svelte/store'; export let data: PageData; let selected: string[] = []; @@ -50,6 +52,14 @@ let showCreateDropdownMobile = false; let showCreateDropdownDesktop = false; let showCreateDropdownEmpty = false; + const columns = writable([ + { id: '$id', title: 'Message ID', type: 'string', show: true, width: 140 }, + { id: 'message', title: 'Message', type: 'string', show: false, filter: false, width: 140 }, + { id: 'providerType', title: 'Type', type: 'string', show: true, width: 100 }, + { id: 'status', title: 'Status', type: 'string', show: true, width: 120 }, + { id: 'scheduledAt', title: 'Scheduled at', type: 'datetime', show: true, width: 120 }, + { id: 'deliveredAt', title: 'Delivered at', type: 'datetime', show: false, width: 120 } + ]); const project = $page.params.project; diff --git a/src/routes/console/project-[project]/messaging/store.ts b/src/routes/console/project-[project]/messaging/store.ts index bf214f6c3..cdd4bffdc 100644 --- a/src/routes/console/project-[project]/messaging/store.ts +++ b/src/routes/console/project-[project]/messaging/store.ts @@ -1,17 +1,7 @@ -import type { Column } from '$lib/helpers/types'; import type { Models } from '@appwrite.io/console'; import { writable } from 'svelte/store'; export const showCreate = writable(false); -export const columns = writable([ - { id: '$id', title: 'Message ID', type: 'string', show: true, width: 140 }, - { id: 'message', title: 'Message', type: 'string', show: false, filter: false, width: 140 }, - { id: 'providerType', title: 'Type', type: 'string', show: true, width: 100 }, - { id: 'status', title: 'Status', type: 'string', show: true, width: 120 }, - { id: 'scheduledAt', title: 'Scheduled at', type: 'datetime', show: true, width: 120 }, - { id: 'deliveredAt', title: 'Delivered at', type: 'datetime', show: false, width: 120 } -]); - export const targetsById = writable>({}); export const topicsById = writable>({}); From 6f264cf7812febb2c710314d48818159e11276a1 Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Thu, 29 Feb 2024 21:01:14 -0800 Subject: [PATCH 357/403] fix(messaging): provider details design fixes - rename channel label to type for consistency - add spacing below Enabled/Disabled switch --- .../provider-[provider]/updateStatus.svelte | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/routes/console/project-[project]/messaging/providers/provider-[provider]/updateStatus.svelte b/src/routes/console/project-[project]/messaging/providers/provider-[provider]/updateStatus.svelte index 6e62a27fc..adb34d307 100644 --- a/src/routes/console/project-[project]/messaging/providers/provider-[provider]/updateStatus.svelte +++ b/src/routes/console/project-[project]/messaging/providers/provider-[provider]/updateStatus.svelte @@ -134,16 +134,20 @@
    -
    +
    -

    Provider:

    -

    Channel:

    -

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

    +
    +

    + Provider: +

    +

    Type:

    +

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

    +
    From 750a839336d3ae5a47dc603deb32deefaca08188 Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Thu, 29 Feb 2024 21:34:01 -0800 Subject: [PATCH 358/403] feat(messaging): validate before moving to the next message wizard step --- .../messaging/wizard/emailFormList.svelte | 3 ++- .../messaging/wizard/pushFormList.svelte | 2 ++ .../project-[project]/messaging/wizard/smsFormList.svelte | 3 ++- .../project-[project]/messaging/wizard/step2.svelte | 8 +++++++- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/routes/console/project-[project]/messaging/wizard/emailFormList.svelte b/src/routes/console/project-[project]/messaging/wizard/emailFormList.svelte index ca25f281c..693d209fb 100644 --- a/src/routes/console/project-[project]/messaging/wizard/emailFormList.svelte +++ b/src/routes/console/project-[project]/messaging/wizard/emailFormList.svelte @@ -49,6 +49,7 @@ @@ -56,10 +57,10 @@ - diff --git a/src/routes/console/project-[project]/messaging/wizard/pushFormList.svelte b/src/routes/console/project-[project]/messaging/wizard/pushFormList.svelte index 5137cafa2..7858daa6a 100644 --- a/src/routes/console/project-[project]/messaging/wizard/pushFormList.svelte +++ b/src/routes/console/project-[project]/messaging/wizard/pushFormList.svelte @@ -91,6 +91,7 @@ @@ -99,6 +100,7 @@ id="message" label="Message" placeholder="Type here..." + required maxlength={1000} bind:value={$messageParams[MessagingProviderType.Push]['body']}> diff --git a/src/routes/console/project-[project]/messaging/wizard/smsFormList.svelte b/src/routes/console/project-[project]/messaging/wizard/smsFormList.svelte index c01466df6..9b315caa1 100644 --- a/src/routes/console/project-[project]/messaging/wizard/smsFormList.svelte +++ b/src/routes/console/project-[project]/messaging/wizard/smsFormList.svelte @@ -38,8 +38,9 @@ diff --git a/src/routes/console/project-[project]/messaging/wizard/step2.svelte b/src/routes/console/project-[project]/messaging/wizard/step2.svelte index da25ba1fa..b922dd4a2 100644 --- a/src/routes/console/project-[project]/messaging/wizard/step2.svelte +++ b/src/routes/console/project-[project]/messaging/wizard/step2.svelte @@ -41,13 +41,19 @@ $targetsById = rest; } + async function beforeSubmit() { + if (topicIdsLength === 0 && targetIdsLength === 0) { + throw new Error('At least one topic or target is required.'); + } + } + $: topicIdsLength = Object.keys($topicsById).length; $: targetIdsLength = Object.keys($targetsById).length; $: $messageParams[$providerType].targets = Object.keys($targetsById); $: $messageParams[$providerType].topics = Object.keys($topicsById); - + Targets Select targets to whom this message should be directed. From a4e16750650e4db7bb5257d75c7bef932f5fb550 Mon Sep 17 00:00:00 2001 From: Utkarsh Ahuja Date: Fri, 1 Mar 2024 07:18:08 +0000 Subject: [PATCH 359/403] update zoho icon --- static/icons/dark/color/zoho.svg | 34 ++++--------------------- static/icons/dark/grayscale/zoho.svg | 36 +++++++-------------------- static/icons/light/color/zoho.svg | 34 ++++--------------------- static/icons/light/grayscale/zoho.svg | 36 +++++++-------------------- 4 files changed, 28 insertions(+), 112 deletions(-) diff --git a/static/icons/dark/color/zoho.svg b/static/icons/dark/color/zoho.svg index 106cba2ca..3da204a3d 100644 --- a/static/icons/dark/color/zoho.svg +++ b/static/icons/dark/color/zoho.svg @@ -1,30 +1,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + diff --git a/static/icons/dark/grayscale/zoho.svg b/static/icons/dark/grayscale/zoho.svg index 6f037159c..c0ea49a22 100644 --- a/static/icons/dark/grayscale/zoho.svg +++ b/static/icons/dark/grayscale/zoho.svg @@ -1,28 +1,10 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + diff --git a/static/icons/light/color/zoho.svg b/static/icons/light/color/zoho.svg index 106cba2ca..3da204a3d 100644 --- a/static/icons/light/color/zoho.svg +++ b/static/icons/light/color/zoho.svg @@ -1,30 +1,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + diff --git a/static/icons/light/grayscale/zoho.svg b/static/icons/light/grayscale/zoho.svg index 6f037159c..a11e6c57e 100644 --- a/static/icons/light/grayscale/zoho.svg +++ b/static/icons/light/grayscale/zoho.svg @@ -1,28 +1,10 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + From 997b1ec4ee36733aee1fabbc0fad14ad20987a1b Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Fri, 1 Mar 2024 02:31:24 +0100 Subject: [PATCH 360/403] fix: popover --- src/lib/elements/forms/inputDomain.svelte | 8 ++-- src/lib/elements/forms/inputEmail.svelte | 8 ++-- src/lib/elements/forms/inputFile.svelte | 8 ++-- src/lib/elements/forms/inputPassword.svelte | 8 ++-- src/lib/elements/forms/inputPhone.svelte | 8 ++-- src/lib/elements/forms/inputText.svelte | 8 ++-- .../messaging/providers/popoverContent.svelte | 10 ++--- .../providers/settingsFormList.svelte | 43 +++++++++++-------- 8 files changed, 59 insertions(+), 42 deletions(-) diff --git a/src/lib/elements/forms/inputDomain.svelte b/src/lib/elements/forms/inputDomain.svelte index 007c12e97..db798dea7 100644 --- a/src/lib/elements/forms/inputDomain.svelte +++ b/src/lib/elements/forms/inputDomain.svelte @@ -1,5 +1,5 @@
    diff --git a/src/lib/elements/forms/inputEmail.svelte b/src/lib/elements/forms/inputEmail.svelte index 478839bbf..b925a1b62 100644 --- a/src/lib/elements/forms/inputEmail.svelte +++ b/src/lib/elements/forms/inputEmail.svelte @@ -1,5 +1,5 @@
    @@ -10,11 +10,11 @@

    {@html line}

    {/each} - {#if popoverImage} + {#if image} + darkSrc={image.src.dark} + lightSrc={image.src.light} + alt={image.alt} /> {/if}
    diff --git a/src/routes/console/project-[project]/messaging/providers/settingsFormList.svelte b/src/routes/console/project-[project]/messaging/providers/settingsFormList.svelte index e0c330642..92baa0d30 100644 --- a/src/routes/console/project-[project]/messaging/providers/settingsFormList.svelte +++ b/src/routes/console/project-[project]/messaging/providers/settingsFormList.svelte @@ -40,21 +40,31 @@ | FCMProviderParams | APNSProviderParams >; + + function getPopoverProps(input: ProviderInput) { + if (!input.popover) { + return {}; + } + return { + lines: input.popover, + image: input.popoverImage + }; + } {#each inputs as input} - {@const popoverImage = input.popoverImage} + {@const popover = input.popover ? PopoverContent : null} + {@const popoverProps = getPopoverProps(input)} {#if input.type === 'text'} - - - {:else if input.type === 'password'} - - - {:else if input.type === 'email'} - - - {:else if input.type === 'domain'} - - - {:else if input.type === 'phone'} - - - {:else if input.type === 'file'} - - - {:else if input.type === 'switch'} From 3e1cecc40ae41457ac866ef038157b0a395a16dc Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Fri, 1 Mar 2024 02:33:35 +0100 Subject: [PATCH 361/403] fix: use template const for popover props with email input --- .../messaging/providers/popoverContent.svelte | 5 +---- .../messaging/providers/settingsFormList.svelte | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/routes/console/project-[project]/messaging/providers/popoverContent.svelte b/src/routes/console/project-[project]/messaging/providers/popoverContent.svelte index 378e9424d..7b9a1e723 100644 --- a/src/routes/console/project-[project]/messaging/providers/popoverContent.svelte +++ b/src/routes/console/project-[project]/messaging/providers/popoverContent.svelte @@ -11,10 +11,7 @@ {/each} {#if image} - + {/if} diff --git a/src/routes/console/project-[project]/messaging/providers/settingsFormList.svelte b/src/routes/console/project-[project]/messaging/providers/settingsFormList.svelte index 92baa0d30..8d167bbdf 100644 --- a/src/routes/console/project-[project]/messaging/providers/settingsFormList.svelte +++ b/src/routes/console/project-[project]/messaging/providers/settingsFormList.svelte @@ -84,7 +84,7 @@ placeholder={input.placeholder} required={!input.optional} {popover} - popoverProps={getPopoverProps(input)} + {popoverProps} bind:value={params[input.name]}> {:else if input.type === 'domain'} From 0df541c80042c6915bb17e95d01376130eec6d98 Mon Sep 17 00:00:00 2001 From: Arman Date: Fri, 1 Mar 2024 11:55:59 +0100 Subject: [PATCH 362/403] fix: messaging page container header mobile view --- src/lib/components/drop.svelte | 2 + src/lib/components/dropList.svelte | 12 ++++- src/lib/components/filters/filters.svelte | 3 +- src/lib/components/searchQuery.svelte | 3 +- src/lib/components/viewSelector.svelte | 8 +++- .../project-[project]/messaging/+page.svelte | 47 +++++++++---------- 6 files changed, 44 insertions(+), 31 deletions(-) diff --git a/src/lib/components/drop.svelte b/src/lib/components/drop.svelte index f61ff6a24..a1c222e08 100644 --- a/src/lib/components/drop.svelte +++ b/src/lib/components/drop.svelte @@ -12,6 +12,7 @@ export let childStart = false; export let noStyle = false; export let fullWidth = false; + export let wrapperFullWidth = false; export let fixed = false; export let display = 'block'; @@ -104,6 +105,7 @@
    diff --git a/src/lib/components/dropList.svelte b/src/lib/components/dropList.svelte index dd8271f1d..c6ad97dd1 100644 --- a/src/lib/components/dropList.svelte +++ b/src/lib/components/dropList.svelte @@ -11,10 +11,20 @@ export let noStyle = false; export let width: string = null; export let fullWidth = false; + export let wrapperFullWidth = false; export let position: 'relative' | 'static' = 'relative'; - +
    ; + export let fullWidthMobile = false; const parsedQueries = queryParamToMap(query); queries.set(parsedQueries); @@ -55,7 +56,7 @@
    - + + From f10b700dce989d32281654304d40d59993b28cec Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Fri, 1 Mar 2024 20:24:10 -0800 Subject: [PATCH 369/403] feat(databases): show attribute/index failed error in modal --- .../attributes/+page.svelte | 29 +++++++++++++----- .../indexes/+page.svelte | 30 ++++++++++++++----- 2 files changed, 45 insertions(+), 14 deletions(-) diff --git a/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/attributes/+page.svelte b/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/attributes/+page.svelte index bd48e7807..3ca3f4a97 100644 --- a/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/attributes/+page.svelte +++ b/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/attributes/+page.svelte @@ -16,6 +16,7 @@ import { Container } from '$lib/layout'; import Create from '../createAttribute.svelte'; import { isRelationship } from '../document-[document]/attributes/store'; + import FailedModal from '../failedModal.svelte'; import CreateIndex from '../indexes/createIndex.svelte'; import { attributes, type Attributes } from '../store'; import CreateAttributeDropdown from './createAttributeDropdown.svelte'; @@ -35,6 +36,8 @@ let showDelete = false; let showEdit = false; let showCreateIndex = false; + let showFailed = false; + let error = ''; enum attributeFormatIcon { ip = 'location-marker', @@ -89,13 +92,24 @@ {attribute.key}
    {#if attribute.status !== 'available'} - - {attribute.status} - +
    + + {attribute.status} + + {#if attribute.error} + + {/if} +
    {:else if attribute.required} Required {/if} @@ -214,3 +228,4 @@ + diff --git a/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/indexes/+page.svelte b/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/indexes/+page.svelte index 4cc2d4263..a3d50bb09 100644 --- a/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/indexes/+page.svelte +++ b/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/indexes/+page.svelte @@ -20,6 +20,7 @@ import { Button } from '$lib/elements/forms'; import CreateAttributeDropdown from '../attributes/createAttributeDropdown.svelte'; import type { Option } from '../attributes/store'; + import FailedModal from '../failedModal.svelte'; let showDropdown = []; let selectedIndex: Models.Index = null; @@ -29,6 +30,8 @@ let showCreateAttribute = false; let showCreateDropdown = false; let selectedAttribute: Option['name'] = null; + let showFailed = false; + let error = ''; @@ -60,13 +63,24 @@
    {index.key} {#if index.status !== 'available'} - - {index.status} - +
    + + {index.status} + + {#if index.error} + + {/if} +
    {/if}
    @@ -162,3 +176,5 @@ {/if} + + From c24e7b1c9ee4073e49e210bad215c8b38f295323 Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Fri, 1 Mar 2024 20:27:45 -0800 Subject: [PATCH 370/403] feat(databases): prevent deleting processing attributes Most of the time, develoeprs should just wait for processing attributes. If they delete it, it will most likely become stuck. As such, hide the delete button to reduce the occurrence of stuck attributes. --- .../attributes/+page.svelte | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/attributes/+page.svelte b/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/attributes/+page.svelte index 3ca3f4a97..88bc3bef7 100644 --- a/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/attributes/+page.svelte +++ b/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/attributes/+page.svelte @@ -172,15 +172,17 @@ Create Index {/if} - { - selectedAttribute = attribute; - showDelete = true; - showDropdown[index] = false; - }}> - Delete - + {#if attribute.status !== 'processing'} + { + selectedAttribute = attribute; + showDelete = true; + showDropdown[index] = false; + }}> + Delete + + {/if}
    From 0802237e9a01516ac9d8134c7f6f0a3cf779efe2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Mon, 4 Mar 2024 11:10:09 +0100 Subject: [PATCH 371/403] Update console for new MFA methods --- package-lock.json | 8 ++++---- package.json | 2 +- src/routes/console/account/+layout.ts | 2 +- src/routes/console/account/deleteMfa.svelte | 2 +- src/routes/console/account/mfa.svelte | 12 +++++++----- .../project-[project]/auth/user-[user]/+layout.ts | 2 +- .../auth/user-[user]/deleteMfa.svelte | 2 +- src/routes/mfa/+page.svelte | 14 ++------------ 8 files changed, 18 insertions(+), 26 deletions(-) diff --git a/package-lock.json b/package-lock.json index 875763d65..3a1c153f5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,7 +6,7 @@ "": { "name": "@appwrite/console", "dependencies": { - "@appwrite.io/console": "^0.6.0-rc.14", + "@appwrite.io/console": "^0.6.0-rc.17", "@appwrite.io/pink": "0.4.0", "@appwrite.io/pink-icons": "0.4.0", "@popperjs/core": "^2.11.8", @@ -158,9 +158,9 @@ "integrity": "sha512-TD+xbmsBLyYy/IxFimW/YL/9L2IEnM7/EoV9Aeh56U64Ify8o27HJcKjo38XY9Tcn0uOq1AX3thkKgvtWvwFQg==" }, "node_modules/@appwrite.io/console": { - "version": "0.6.0-rc.14", - "resolved": "https://registry.npmjs.org/@appwrite.io/console/-/console-0.6.0-rc.14.tgz", - "integrity": "sha512-7Od0RuGRF01YUCWGTAvlTvgUG7sUCVHG9ig11OKz9jjBxE91BVcWsmqGWiXw+xb4HhF2jiyHd9ZU3sKAo0IC3w==", + "version": "0.6.0-rc.17", + "resolved": "https://registry.npmjs.org/@appwrite.io/console/-/console-0.6.0-rc.17.tgz", + "integrity": "sha512-QCUMpvQIt9NseNHlVNFk8wuTro0i6UXeGxO9nuXtIOC9oC20vi5tdiFz1ImjYS2SVtlB0PJRGf58Q/p2WPoR1g==", "dependencies": { "cross-fetch": "3.1.5", "isomorphic-form-data": "2.0.0" diff --git a/package.json b/package.json index c608c667c..1afb8d285 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ "e2e": "playwright test tests/e2e" }, "dependencies": { - "@appwrite.io/console": "^0.6.0-rc.14", + "@appwrite.io/console": "^0.6.0-rc.17", "@appwrite.io/pink": "0.4.0", "@appwrite.io/pink-icons": "0.4.0", "@popperjs/core": "^2.11.8", diff --git a/src/routes/console/account/+layout.ts b/src/routes/console/account/+layout.ts index 4511cbb1f..2341ee3c0 100644 --- a/src/routes/console/account/+layout.ts +++ b/src/routes/console/account/+layout.ts @@ -8,7 +8,7 @@ export const load: LayoutLoad = async ({ depends }) => { depends(Dependencies.FACTORS); return { - factors: await sdk.forConsole.account.listFactors(), + factors: await sdk.forConsole.account.listMfaFactors(), header: Header, breadcrumbs: Breadcrumbs }; diff --git a/src/routes/console/account/deleteMfa.svelte b/src/routes/console/account/deleteMfa.svelte index d1fc639f9..f6dc1449c 100644 --- a/src/routes/console/account/deleteMfa.svelte +++ b/src/routes/console/account/deleteMfa.svelte @@ -17,7 +17,7 @@ async function deleteProvider() { try { - await sdk.forConsole.account.deleteAuthenticator(AuthenticatorType.Totp, code); + await sdk.forConsole.account.deleteMfaAuthenticator(AuthenticatorType.Totp, code); await invalidate(Dependencies.ACCOUNT); await invalidate(Dependencies.FACTORS); showDelete = false; diff --git a/src/routes/console/account/mfa.svelte b/src/routes/console/account/mfa.svelte index 11d8db720..5f38068bd 100644 --- a/src/routes/console/account/mfa.svelte +++ b/src/routes/console/account/mfa.svelte @@ -16,15 +16,17 @@ let copyParent: HTMLElement; let code: string; let type: Models.MfaType = null; + let codes: Models.MfaRecoveryCodes = null; async function addAuthenticator(): Promise { - type = await sdk.forConsole.account.addAuthenticator(AuthenticatorType.Totp); + type = await sdk.forConsole.account.createMfaAuthenticator(AuthenticatorType.Totp); return sdk.forConsole.avatars.getQR(type.uri, 192 * 2); } async function verifyAuthenticator() { try { - await sdk.forConsole.account.verifyAuthenticator(AuthenticatorType.Totp, code); + await sdk.forConsole.account.updateMfaAuthenticator(AuthenticatorType.Totp, code); + codes = await sdk.forConsole.account.createMfaRecoveryCodes(); await invalidate(Dependencies.ACCOUNT); await invalidate(Dependencies.FACTORS); showSetup = false; @@ -103,8 +105,8 @@ description="Learn more about multi-factor authentication in our documentation." bind:show={showRecoveryCodes} onSubmit={verifyAuthenticator}> - {#if type} - {@const formattedBackupCodes = type.backups.join('\n')} + {#if type && codes} + {@const formattedBackupCodes = codes.recoveryCodes.join('\n')} It is highly recommended to securely store your recovery codes @@ -140,7 +142,7 @@
    - {#each type.backups as code} + {#each codes.recoveryCodes as code} {code} diff --git a/src/routes/console/project-[project]/auth/user-[user]/+layout.ts b/src/routes/console/project-[project]/auth/user-[user]/+layout.ts index a695abc55..e0cc98485 100644 --- a/src/routes/console/project-[project]/auth/user-[user]/+layout.ts +++ b/src/routes/console/project-[project]/auth/user-[user]/+layout.ts @@ -13,7 +13,7 @@ export const load: LayoutLoad = async ({ params, depends }) => { header: Header, breadcrumbs: Breadcrumbs, user: await sdk.forProject.users.get(params.user), - userFactors: await sdk.forProject.users.listFactors(params.user) + userFactors: await sdk.forProject.users.listMfaFactors(params.user) }; } catch (e) { error(e.code, e.message); diff --git a/src/routes/console/project-[project]/auth/user-[user]/deleteMfa.svelte b/src/routes/console/project-[project]/auth/user-[user]/deleteMfa.svelte index 3727ffcba..4e66a6a30 100644 --- a/src/routes/console/project-[project]/auth/user-[user]/deleteMfa.svelte +++ b/src/routes/console/project-[project]/auth/user-[user]/deleteMfa.svelte @@ -15,7 +15,7 @@ async function deleteProvider() { try { - await sdk.forConsole.users.deleteAuthenticator($user.$id, AuthenticatorType.Totp); + await sdk.forConsole.users.deleteMfaAuthenticator($user.$id, AuthenticatorType.Totp); await invalidate(Dependencies.ACCOUNT); await invalidate(Dependencies.FACTORS); showDelete = false; diff --git a/src/routes/mfa/+page.svelte b/src/routes/mfa/+page.svelte index eedc50900..46653e270 100644 --- a/src/routes/mfa/+page.svelte +++ b/src/routes/mfa/+page.svelte @@ -16,10 +16,10 @@ async function verify() { try { disabled = true; - const challenge = await sdk.forConsole.account.createChallenge( + const challenge = await sdk.forConsole.account.createMfaChallenge( AuthenticationFactor.Totp ); - await sdk.forConsole.account.updateChallenge(challenge.$id, code); + await sdk.forConsole.account.updateMfaChallenge(challenge.$id, code); await invalidate(Dependencies.ACCOUNT); trackEvent(Submit.AccountCreate); if ($page.url.searchParams) { @@ -61,14 +61,4 @@ - - - - From 4a6bf182e4410a155782823b0bc7530bf8362dae Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Tue, 5 Mar 2024 13:09:06 -0800 Subject: [PATCH 372/403] fix(messaging): fix provider card height in provider wizard Don't make the height the same or else there will be extra space. --- .../project-[project]/messaging/providers/wizard/provider.svelte | 1 + 1 file changed, 1 insertion(+) diff --git a/src/routes/console/project-[project]/messaging/providers/wizard/provider.svelte b/src/routes/console/project-[project]/messaging/providers/wizard/provider.svelte index 9b41f6d63..e56bf339d 100644 --- a/src/routes/console/project-[project]/messaging/providers/wizard/provider.svelte +++ b/src/routes/console/project-[project]/messaging/providers/wizard/provider.svelte @@ -179,6 +179,7 @@ .grid-box { --grid-gap: 1rem; grid-template-columns: 1fr 1fr; + grid-auto-rows: auto; } :global(body:not(.theme-dark)) .grid-box :global(.card) { From c2640a33f9b6d9dd2a65322f91e78a9ca9371856 Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Tue, 5 Mar 2024 13:40:08 -0800 Subject: [PATCH 373/403] fix(messaging): fix messaging container header The create message button should be in the same row as the search input and filter and column buttons on desktop. --- .../console/project-[project]/messaging/+page.svelte | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/routes/console/project-[project]/messaging/+page.svelte b/src/routes/console/project-[project]/messaging/+page.svelte index d27f3e37c..a9272aee3 100644 --- a/src/routes/console/project-[project]/messaging/+page.svelte +++ b/src/routes/console/project-[project]/messaging/+page.svelte @@ -50,6 +50,7 @@ let showFailed = false; let errors: string[] = []; let showCreateDropdownDesktop = false; + let showCreateDropdownMobile = false; let showCreateDropdownEmpty = false; const columns = writable([ { id: '$id', title: 'Message ID', type: 'string', show: true, width: 140 }, @@ -92,7 +93,9 @@ - +
    + +
    - +
    From 731159cb89b83e4aab09f602018243c91ae2458b Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Wed, 6 Mar 2024 11:19:15 +0100 Subject: [PATCH 374/403] fix: file picker --- src/lib/components/filePicker.svelte | 562 +++++++++++++++------------ 1 file changed, 309 insertions(+), 253 deletions(-) diff --git a/src/lib/components/filePicker.svelte b/src/lib/components/filePicker.svelte index 8ab23a8c7..a7c0a34a2 100644 --- a/src/lib/components/filePicker.svelte +++ b/src/lib/components/filePicker.svelte @@ -23,6 +23,8 @@ import Heading from './heading.svelte'; import { clickOnEnter } from '$lib/helpers/a11y'; import Empty from './empty.svelte'; + import { base } from '$app/paths'; + import { page } from '$app/stores'; export let show: boolean; export let selectedBucket: string = null; @@ -88,13 +90,22 @@ resetBucket(); } + function handleVisibilityChange() { + if (!document.hidden) { + buckets = loadBuckets(); + } + } + let currentBucket: Models.Bucket = null; let currentFile: Models.File = null; - const buckets = sdk.forProject.storage.listBuckets().then((n) => { - currentBucket = n.buckets[0] ?? null; + let buckets: Promise = loadBuckets(); + async function loadBuckets() { + const response = await sdk.forProject.storage.listBuckets(); - return n; - }); + currentBucket = response.buckets[0] ?? null; + + return response; + } $: files = currentBucket && @@ -122,6 +133,8 @@ } + +
    - - {#if currentBucket} -
    -
    -
    - {currentBucket?.name} -
    - - {currentBucket?.$id} - -
    + {#await buckets} +
    - -
    -
    -
      -
    • - -
    • -
    • - -
    • -
    + class="u-position-absolute u-width-full-line u-flex u-flex-vertical u-main-center u-cross-center u-gap-16 u-margin-block-start-32" + style="inset-inline-start: 0;"> +
    +

    Loading files...

    +
    +
    + {:then response} + {#if response?.total} + {#if currentBucket} +
    +
    +
    + {currentBucket?.name} +
    + + {currentBucket?.$id} +
    +
    + +
    +
    +
      +
    • + +
    • +
    • + +
    • +
    +
    + +
    +
    +
    + + {#if files} + {#await files then response} +
    + {#if response?.files?.length} + {#if view === 'grid'} +
      + {#each response?.files as file} +
    • +
      +
      + selectFile(file)} + on:keyup={clickOnEnter} + tabindex="0" + style:aspect-ratio="1/1" + style:display="flex" + style:align-items="flex-end" + style:flex-direction="row-reverse" + style:box-shadow="none" + class="card u-height-100-percent u-gap-16" + style="--card-padding:0.5rem;--card-padding-mobile:0.5rem; --card-border-radius:var(--border-radius-medium);"> + +
      + {file.name} +
      +
    • + {/each} +
    + {/if} + {#if view === 'list'} +
    + + Filename + + ID + + + Type + + + Size + + + Created + + + + {#each response?.files as file} + + selectFile(file)}> + +
    + + + {file.name} + + + {file.name} + +
    +
    + + {file.$id} + + + {file.mimeType} + + + {calculateSize( + file.sizeOriginal + )} + + + {toLocaleDate( + file.$createdAt + )} + +
    + {/each} +
    +
    + {/if} + {:else if $search} + +
    +
    + Sorry we couldn't find "{$search}" +

    + There are no files that match your + search. +

    +
    +
    + +
    +
    +
    + {:else} + +
    +
    + + No files found within this bucket. + +

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

    +
    +
    +
    + {/if} +
    + {/await} + {/if} + {/if} + {:else} + +
    + + No buckets found +
    - - - {#if files} - {#await files} -
    -
    -
    -

    Loading files...

    -
    -
    - {:then response} -
    - {#if response?.files?.length} - {#if view === 'grid'} -
      - {#each response?.files as file} -
    • -
      -
      selectFile(file)} - on:keyup={clickOnEnter} - tabindex="0" - style:aspect-ratio="1/1" - style:display="flex" - style:align-items="flex-end" - style:flex-direction="row-reverse" - style:box-shadow="none" - class="card u-height-100-percent u-gap-16" - style="--card-padding:0.5rem;--card-padding-mobile:0.5rem; --card-border-radius:var(--border-radius-medium);"> - -
      - {file.name} -
      -
    • - {/each} -
    - {/if} - {#if view === 'list'} - - - Filename - - ID - - - Type - - - Size - - - Created - - - - {#each response?.files as file} - selectFile(file)}> - -
    - - - {file.name} - - - {file.name} - -
    -
    - - {file.$id} - - - {file.mimeType} - - - {calculateSize(file.sizeOriginal)} - - - {toLocaleDate(file.$createdAt)} - -
    - {/each} -
    -
    - {/if} - {:else if $search} - -
    -
    - Sorry we couldn't find "{$search}" -

    - There are no files that match your search. -

    -
    -
    - -
    -
    -
    - {:else} - -
    -
    - - No files found within this bucket. - -

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

    -
    -
    -
    - {/if} -
    - {/await} + {/if} - {/if} + {/await}
    From 3699cb85db7bac2afd9d58e4a2f605afe43f9a13 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Wed, 6 Mar 2024 11:38:02 +0100 Subject: [PATCH 375/403] fix: build --- .../messaging/providers/settingsFormInput.svelte | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/routes/console/project-[project]/messaging/providers/settingsFormInput.svelte b/src/routes/console/project-[project]/messaging/providers/settingsFormInput.svelte index 93062d19a..8b17b758c 100644 --- a/src/routes/console/project-[project]/messaging/providers/settingsFormInput.svelte +++ b/src/routes/console/project-[project]/messaging/providers/settingsFormInput.svelte @@ -41,7 +41,8 @@ >; export let fullWidth = false; - let popoverImage = input.popoverImage; + const popover = input.popover ? PopoverContent : null; + const popoverProps = getPopoverProps(input); function getPopoverProps(input: ProviderInput) { if (!input.popover) { @@ -54,8 +55,6 @@ } -{@const popover = input.popover ? PopoverContent : null} -{@const popoverProps = getPopoverProps(input)} {#if input.type === 'text'} Date: Wed, 6 Mar 2024 11:41:55 +0100 Subject: [PATCH 376/403] fix: formatting --- .../messaging/providers/settingsFormInput.svelte | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/routes/console/project-[project]/messaging/providers/settingsFormInput.svelte b/src/routes/console/project-[project]/messaging/providers/settingsFormInput.svelte index 8b17b758c..615e13353 100644 --- a/src/routes/console/project-[project]/messaging/providers/settingsFormInput.svelte +++ b/src/routes/console/project-[project]/messaging/providers/settingsFormInput.svelte @@ -65,7 +65,7 @@ {popover} {popoverProps} {fullWidth} - bind:value={params[input.name]}/> + bind:value={params[input.name]} /> {:else if input.type === 'password'} + bind:value={params[input.name]} /> {:else if input.type === 'email'} + bind:value={params[input.name]} /> {:else if input.type === 'domain'} + bind:value={params[input.name]} /> {:else if input.type === 'phone'} + bind:value={params[input.name]} /> {:else if input.type === 'file'} + bind:files={files[input.name]} /> {:else if input.type === 'switch'} From f1c0b8210320e93926de9975c6041c91d6ec15fd Mon Sep 17 00:00:00 2001 From: Arman Date: Thu, 7 Mar 2024 10:17:46 +0100 Subject: [PATCH 377/403] fix: usage stat reduce function --- src/lib/layout/usage.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/layout/usage.svelte b/src/lib/layout/usage.svelte index bec778df3..381b61899 100644 --- a/src/lib/layout/usage.svelte +++ b/src/lib/layout/usage.svelte @@ -45,8 +45,8 @@ ): Array<[string, number]> { return metrics.reduceRight( (acc, curr) => { - acc.total -= curr.value; acc.data.unshift([curr.date, acc.total]); + acc.total -= curr.value; return acc; }, { From 795c182fb1ebc5bf355ba26ff9a9fff14f595eb2 Mon Sep 17 00:00:00 2001 From: Arman Date: Thu, 7 Mar 2024 15:59:36 +0100 Subject: [PATCH 378/403] refactor: first load redirection --- src/routes/+layout.svelte | 48 ++++++++++++++++++++++----------------- vite.config.ts | 3 ++- 2 files changed, 29 insertions(+), 22 deletions(-) diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 49e6ea616..1452936b0 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -7,7 +7,6 @@ import { reportWebVitals } from '$lib/helpers/vitals'; import { Notifications, Progress } from '$lib/layout'; import { app } from '$lib/stores/app'; - import { user } from '$lib/stores/user'; import { ENV, isCloud } from '$lib/system'; import * as Sentry from '@sentry/svelte'; import LogRocket from 'logrocket'; @@ -17,6 +16,7 @@ import { loading, requestedMigration } from './store'; import { parseIfString } from '$lib/helpers/object'; import Consent, { consent } from '$lib/components/consent.svelte'; + import type { Models } from '@appwrite.io/console'; if (browser) { window.VERCEL_ANALYTICS_ID = import.meta.env.VERCEL_ANALYTICS_ID?.toString() ?? false; @@ -64,37 +64,43 @@ /** * Handle initial load. */ - if (!$page.url.pathname.startsWith('/auth') && !$page.url.pathname.startsWith('/git')) { - const acceptedRoutes = [ - '/login', - '/register', - '/recover', - '/invite', - '/card', - '/hackathon' - ]; - if ($user) { - if ( - !$page.url.pathname.startsWith('/console') && - !$page.url.pathname.startsWith('/invite') && - !$page.url.pathname.startsWith('/card') && - !$page.url.pathname.startsWith('/hackathon') - ) { + + function shouldRedirect(route: string, routes: string[]) { + return !routes.some((n) => route.startsWith(n)); + } + + const authenticationRoutes = ['/auth', '/git']; + const acceptedUnauthenticatedRoutes = [ + '/login', + '/register', + '/recover', + '/invite', + '/card', + '/hackathon', + '/test' + ]; + const acceptedAuthenticatedRoutes = ['/console', '/invite', '/card', '/hackathon']; + + const pathname = $page.url.pathname; + const user = $page.data.account as Models.User>; + + if (shouldRedirect(pathname, authenticationRoutes)) { + if (user?.$id) { + if (shouldRedirect(pathname, acceptedAuthenticatedRoutes)) { await goto(`${base}/console`, { replaceState: true }); } - loading.set(false); } else { - if (acceptedRoutes.some((n) => $page.url.pathname.startsWith(n))) { - await goto(`${base}${$page.url.pathname}${$page.url.search}`); + if (acceptedUnauthenticatedRoutes.some((n) => pathname.startsWith(n))) { + await goto(`${base}${pathname}${$page.url.search}`); } else { await goto(`${base}/login`, { replaceState: true }); } - loading.set(false); } + loading.set(false); } }); diff --git a/vite.config.ts b/vite.config.ts index 754fb4acc..d1d53436e 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -13,7 +13,8 @@ const config = defineConfig({ '@analytics/google-analytics', 'analytics', 'dayjs', - 'dotenv' + 'dotenv', + 'zrender' ] }, define: { From 844f47677a3e020d640121c3a32e2ca930ec3a42 Mon Sep 17 00:00:00 2001 From: Arman Date: Thu, 7 Mar 2024 16:02:59 +0100 Subject: [PATCH 379/403] fix: remove test route --- src/routes/+layout.svelte | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 1452936b0..eadc302f3 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -76,8 +76,7 @@ '/recover', '/invite', '/card', - '/hackathon', - '/test' + '/hackathon' ]; const acceptedAuthenticatedRoutes = ['/console', '/invite', '/card', '/hackathon']; From 611b9b9d76c7c8f33f54c400420275ed65e924f7 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Fri, 8 Mar 2024 00:31:14 +0100 Subject: [PATCH 380/403] fix: design review --- src/lib/components/filePicker.svelte | 106 ++++++++++++------ src/lib/elements/forms/inputFilePicker.svelte | 6 +- .../project-[project]/messaging/create.svelte | 4 +- .../message-[message]/pushMessage.svelte | 32 ++++-- 4 files changed, 103 insertions(+), 45 deletions(-) diff --git a/src/lib/components/filePicker.svelte b/src/lib/components/filePicker.svelte index a7c0a34a2..3ec802af3 100644 --- a/src/lib/components/filePicker.svelte +++ b/src/lib/components/filePicker.svelte @@ -1,8 +1,8 @@ - + diff --git a/src/routes/console/project-[project]/messaging/wizard/step3.svelte b/src/routes/console/project-[project]/messaging/wizard/step3.svelte index 47b9c2b2e..f240a4041 100644 --- a/src/routes/console/project-[project]/messaging/wizard/step3.svelte +++ b/src/routes/console/project-[project]/messaging/wizard/step3.svelte @@ -5,6 +5,9 @@ import { MessagingProviderType } from '@appwrite.io/console'; import { messageParams, providerType } from './store'; import { isSameDay, toLocaleDateISO, toLocaleTimeISO } from '$lib/helpers/date'; + import { wizard } from '$lib/stores/wizard'; + import { Modal } from '$lib/components'; + import { topicsById } from '../store'; let when: 'now' | 'later' = 'now'; let now = new Date(); @@ -13,6 +16,21 @@ let time: string; let dateTime: Date; let docsUrl = `https://appwrite.io/docs/products/messaging`; + let showConfimation = false; + + let totalTargets = $messageParams[$providerType].targets?.length ?? 0; + + const topics = $messageParams[$providerType].topics; + + for (const topic of topics) { + if ($providerType == MessagingProviderType.Push) { + totalTargets += $topicsById[topic].pushTotal; + } else if ($providerType == MessagingProviderType.Email) { + totalTargets += $topicsById[topic].emailTotal; + } else if ($providerType == MessagingProviderType.Sms) { + totalTargets += $topicsById[topic].smsTotal; + } + } switch ($providerType) { case MessagingProviderType.Email: @@ -40,6 +58,18 @@ timeZoneName: 'longGeneric' }; + async function askForConfirmation() { + $wizard.interceptorNotificationEnabled = false; + showConfimation = true; + throw 'Show confirmation'; + } + + async function submit() { + $wizard.interceptorNotificationEnabled = true; + await $wizard.finalAction(); + showConfimation = false; + } + $: if (when === 'now') { date = time = ''; } @@ -56,7 +86,7 @@ } - + Schedule Schedule the time you want to deliver this message. Learn more in our