diff --git a/package-lock.json b/package-lock.json index e908202ae..c7d75651e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,7 +6,7 @@ "": { "name": "@appwrite/console", "dependencies": { - "@appwrite.io/console": "^0.6.0-rc.12", + "@appwrite.io/console": "^0.6.0-rc.14", "@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.12", - "resolved": "https://registry.npmjs.org/@appwrite.io/console/-/console-0.6.0-rc.12.tgz", - "integrity": "sha512-pDov75TCkBmJdUPrWuzRW7uM28HYqiMFtVFrUoavDd/lMPBS7RnPXL4sBHsGY8AUldHE3oBcGVPkNoQfEAgLlw==", + "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==", "dependencies": { "cross-fetch": "3.1.5", "isomorphic-form-data": "2.0.0" diff --git a/package.json b/package.json index 0d826dea2..ba7717f02 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ "e2e": "playwright test tests/e2e" }, "dependencies": { - "@appwrite.io/console": "^0.6.0-rc.12", + "@appwrite.io/console": "^0.6.0-rc.14", "@appwrite.io/pink": "0.4.0", "@appwrite.io/pink-icons": "0.4.0", "@popperjs/core": "^2.11.8", 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/actions/analytics.ts b/src/lib/actions/analytics.ts index e967ec3d2..5da9bede1 100644 --- a/src/lib/actions/analytics.ts +++ b/src/lib/actions/analytics.ts @@ -301,7 +301,7 @@ export enum Submit { MessagingTopicCreate = 'submit_messaging_topic_create', MessagingTopicDelete = 'submit_messaging_topic_delete', MessagingTopicUpdateName = 'submit_messaging_topic_update_name', - MessagingTopicUpdateDescription = 'submit_messaging_topic_update_description', + MessagingTopicUpdatePermissions = 'submit_messaging_topic_update_permissions', MessagingTopicSubscriberAdd = 'submit_messaging_topic_subscriber_add', MessagingTopicSubscriberDelete = 'submit_messaging_topic_subscriber_delete' } diff --git a/src/lib/components/clickableListItem.svelte b/src/lib/components/clickableListItem.svelte index 78a4dbe08..03e6c294b 100644 --- a/src/lib/components/clickableListItem.svelte +++ b/src/lib/components/clickableListItem.svelte @@ -1,18 +1,39 @@
  • - - {#if $$slots.default} -
    - -
    - {/if} - {#if $$slots.desc} -
    -

    -
    - {/if} -
    + {#if href} + + {#if $$slots.default} +
    + +
    + {/if} + {#if $$slots.desc} +
    +

    +
    + {/if} +
    + {:else} + + {/if}
  • diff --git a/src/lib/components/collapsibleItem.svelte b/src/lib/components/collapsibleItem.svelte index 8397454dc..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/lib/components/imagePreview.svelte b/src/lib/components/imagePreview.svelte new file mode 100644 index 000000000..5993df089 --- /dev/null +++ b/src/lib/components/imagePreview.svelte @@ -0,0 +1,24 @@ + + + +
    + +
    +
    +
    +
    +
    +
    diff --git a/src/lib/components/index.ts b/src/lib/components/index.ts index 854ddb8df..685b34d63 100644 --- a/src/lib/components/index.ts +++ b/src/lib/components/index.ts @@ -72,3 +72,4 @@ export { default as FakeModal } from './fakeModal.svelte'; export { default as RadioBoxes } from './radioBoxes.svelte'; export { default as ModalWrapper } from './modalWrapper.svelte'; export { default as ModalSideCol } from './modalSideCol.svelte'; +export { default as ImagePreview } from './imagePreview.svelte'; diff --git a/src/lib/components/trim.svelte b/src/lib/components/trim.svelte index 2d56222c3..27da7d77f 100644 --- a/src/lib/components/trim.svelte +++ b/src/lib/components/trim.svelte @@ -16,16 +16,13 @@ - - {#if showTooltip} - - - - {:else} - - {/if} + + diff --git a/src/lib/elements/forms/inputDigits.svelte b/src/lib/elements/forms/inputDigits.svelte index dee662d63..ae0162864 100644 --- a/src/lib/elements/forms/inputDigits.svelte +++ b/src/lib/elements/forms/inputDigits.svelte @@ -13,6 +13,8 @@ let element: HTMLOListElement; + let autoSubmitted = false; + const { elements: { root, input } } = createPinInput({ @@ -20,14 +22,27 @@ defaultValue: value.split(''), onValueChange: ({ next }) => { value = next.join(''); + + if (value.length === 6 && !autoSubmitted) { + autoSubmitted = true; + const firstInputElement = element.querySelector('input'); + firstInputElement?.form.requestSubmit(); + } + return next; } }); onMount(() => { - if (element && autofocus) { - element.querySelector('input')?.focus(); - } + const interval = setInterval(() => { + const input = element.querySelector('input'); + if (element) { + if (input && autofocus) { + input.focus(); + } + clearInterval(interval); + } + }, 10); }); 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. { + async listAddresses(queries: string[] = []): Promise { const path = `/account/billing-addresses`; const params = { queries diff --git a/src/lib/stores/migration.ts b/src/lib/stores/migration.ts index dd794ccdf..f6498f4b9 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', - 'envVar', - '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]; @@ -101,7 +103,7 @@ export const migrationFormToResources = ( addResource('function'); } if (formData.functions.env) { - addResource('envVar'); + addResource('environment variable'); } if (formData.functions.inactive) { addResource('deployment'); @@ -155,7 +157,7 @@ export const resourcesToMigrationForm = ( if (resources.includes('function') && isVersionAtLeast(version, '1.4.0')) { formData.functions.root = true; } - if (resources.includes('envVar') && isVersionAtLeast(version, '1.4.0')) { + if (resources.includes('environment variable') && isVersionAtLeast(version, '1.4.0')) { formData.functions.env = true; } if (resources.includes('deployment') && isVersionAtLeast(version, '1.4.0')) { 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, 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 - {$page.status} + {$page.error.status || 'Invalid Argument'} {$page.error.message} diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 99cc475ff..8c8e27929 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -54,7 +54,8 @@ '/recover', '/invite', '/card', - '/hackathon' + '/hackathon', + '/mfa' ]; if ($user) { 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/(migration-wizard)/resource-form.svelte b/src/routes/console/(migration-wizard)/resource-form.svelte index 77572a0b5..41d39cee0 100644 --- a/src/routes/console/(migration-wizard)/resource-form.svelte +++ b/src/routes/console/(migration-wizard)/resource-form.svelte @@ -3,7 +3,7 @@ import { Button } from '$lib/elements/forms'; import { deepMap } from '$lib/helpers/object'; import type { WritableValue } from '$lib/helpers/types'; - import { sdk, type getSdkForProject } from '$lib/stores/sdk'; + import { type getSdkForProject } from '$lib/stores/sdk'; import { onMount } from 'svelte'; @@ -107,19 +107,10 @@ ); break; case 'firebase': - if ($provider.projectId) { - // OAuth - report = await sdk.forProject.migrations.getFirebaseReportOAuth( - providerResources.firebase, - $provider.projectId - ); - } else if ($provider.serviceAccount) { - // Manual auth - report = await projectSdk.migrations.getFirebaseReport( - providerResources.firebase, - $provider.serviceAccount - ); - } + report = await projectSdk.migrations.getFirebaseReport( + providerResources.firebase, + $provider.serviceAccount + ); break; case 'nhost': @@ -353,7 +344,7 @@
    Import all functions and their active deployment -

    Provider:

    -

    Channel:

    -

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

    +

    Provider:

    +

    Channel:

    +

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

    - -
    diff --git a/src/routes/console/project-[project]/messaging/providers/settingsFormList.svelte b/src/routes/console/project-[project]/messaging/providers/settingsFormList.svelte new file mode 100644 index 000000000..609b55790 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/providers/settingsFormList.svelte @@ -0,0 +1,141 @@ + + + + {#each inputs as input} + {@const popoverImage = input.popoverImage} + {#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'} + + +

    {@html input.description}

    +
    +
    + {:else if input.type === 'checkbox'} + + + {input.description} + + + {:else if input.type === 'select'} + + {/if} + {/each} +
    diff --git a/src/routes/console/project-[project]/messaging/providers/store.ts b/src/routes/console/project-[project]/messaging/providers/store.ts index c93e5f445..37bcd459c 100644 --- a/src/routes/console/project-[project]/messaging/providers/store.ts +++ b/src/routes/console/project-[project]/messaging/providers/store.ts @@ -1,7 +1,7 @@ import type { Column } from '$lib/helpers/types'; import { writable } from 'svelte/store'; import { Providers } from '../provider.svelte'; -import { MessagingProviderType, Encryption } from '@appwrite.io/console'; +import { MessagingProviderType, SmtpEncryption } from '@appwrite.io/console'; export const columns = writable([ { id: '$id', title: 'Provider ID', type: 'string', show: true }, @@ -11,6 +11,28 @@ export const columns = writable([ { id: 'enabled', title: 'Status', type: 'boolean', show: true } ]); +export type ProviderInput = { + label: string; + name: string; + type: + | 'text' + | 'password' + | 'phone' + | 'email' + | 'domain' + | 'file' + | 'switch' + | 'select' + | 'checkbox'; + placeholder?: string; + description?: string; + popover?: string[]; + popoverImage?: { src: { light: string; dark: string }; alt: string }; + allowedFileExtensions?: string[]; + optional?: boolean; + options?: { label: string; value: string | number | boolean }[]; +}; + type ProvidersMap = { [key in MessagingProviderType]: { name: string; @@ -23,25 +45,7 @@ type ProvidersMap = { title: string; description: string; needAHand?: string[]; - configure: { - label: string; - name: string; - type: - | 'text' - | 'password' - | 'phone' - | 'email' - | 'domain' - | 'file' - | 'switch' - | 'select'; - placeholder?: string; - description?: string; - popover?: string[]; - allowedFileExtensions?: string[]; - optional?: boolean; - options?: { label: string; value: string | number | boolean }[]; - }[]; + configure: ProviderInput[]; }; }; }; @@ -73,7 +77,14 @@ export const providers: ProvidersMap = { 'How to get the
    FCM service account JSON?', 'Head to Project settings -> Service accounts -> Generate new private key.', 'Generating the new key will result in the download of a JSON file.' - ] + ], + popoverImage: { + src: { + light: '/images/messaging/fcm-service-account-json-light.png', + dark: '/images/messaging/fcm-service-account-json-dark.png' + }, + alt: 'Screenshot of how to generate the Firebase Service Account JSON file' + } } ] }, @@ -89,8 +100,15 @@ export const providers: ProvidersMap = { placeholder: 'Enter team ID', popover: [ 'How to get the team ID?', - 'Head to Apple Developer Member Center -> Membership details -> Team ID.' - ] + 'Head to Apple Developer Member Center -> Membership details -> Team ID.' + ], + popoverImage: { + src: { + light: '/images/messaging/apns-team-id.png', + dark: '/images/messaging/apns-team-id.png' + }, + alt: 'Screenshot of where to find the Team ID in the Apple Developer Member Center' + } }, { label: 'Bundle ID', @@ -99,27 +117,15 @@ export const providers: ProvidersMap = { 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 -
    -
    -
    -
    -
    -
    ` - ] + 'Head to Apple Developer Member Center -> Certificates, Identifiers & Profiles -> Identifiers.' + ], + popoverImage: { + src: { + light: '/images/messaging/apns-bundle-id.png', + dark: '/images/messaging/apns-bundle-id.png' + }, + alt: 'Screenshot of where to find the Bundle ID in the Apple Developer Member Center' + } }, { label: 'Authentication key ID', @@ -128,9 +134,16 @@ export const providers: ProvidersMap = { placeholder: 'Enter key ID', popover: [ 'How to get the auth key ID?', - 'Head to Apple Developer Member Center -> Certificates, Identifiers & Profiles -> Keys.', + 'Head to Apple Developer Member Center -> Certificates, Identifiers & Profiles -> Keys.', 'Click on your key to view details.' - ] + ], + popoverImage: { + src: { + light: '/images/messaging/apns-authentication-key-id.png', + dark: '/images/messaging/apns-authentication-key-id.png' + }, + alt: 'Screenshot of how to find the Authentication Key ID in the Apple Developer Member Center' + } }, { label: 'Auth key (.p8 file)', @@ -139,9 +152,23 @@ export const providers: ProvidersMap = { allowedFileExtensions: ['p8'], popover: [ 'How to get the authentication key?', - 'Head to Apple Developer Member Center (under Program resources) -> Certificates, Identifiers & Profiles -> Keys.', + '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.' - ] + ], + popoverImage: { + src: { + light: '/images/messaging/apns-auth-key.png', + dark: '/images/messaging/apns-auth-key.png' + }, + alt: 'Screenshot of where to download the Authentication Key in the Apple Developer Member Center' + } + }, + { + label: 'Sandbox', + name: 'sandbox', + type: 'switch', + description: + 'Enable sandbox mode for testing on apps signed with development provisioning profiles. Learn more.' } ] } @@ -300,7 +327,7 @@ export const providers: ProvidersMap = { label: 'Server host', name: 'host', type: 'text', - placeholder: 'Enter host' + placeholder: 'smtp.server.com' }, { label: 'Server port', @@ -328,16 +355,16 @@ export const providers: ProvidersMap = { name: 'encryption', type: 'select', options: [ - { label: 'None', value: Encryption.None }, - { label: 'SSL', value: Encryption.Ssl }, - { label: 'TLS', value: Encryption.Tls } + { label: 'None', value: SmtpEncryption.None }, + { label: 'SSL', value: SmtpEncryption.Ssl }, + { label: 'TLS', value: SmtpEncryption.Tls } ] }, { label: 'Auto TLS', name: 'autoTLS', - description: 'Automatically uses TLS encryption', - type: 'switch', + description: 'Automatically uses TLS encryption if available.', + type: 'checkbox', optional: true }, { @@ -345,7 +372,11 @@ export const providers: ProvidersMap = { name: 'mailer', type: 'text', optional: true, - placeholder: 'Enter mailer' + placeholder: 'Enter mailer', + popover: [ + 'What is the Mailer?', + 'The value to use for the X-Mailer header.' + ] } ] } @@ -439,16 +470,21 @@ export const providers: ProvidersMap = { description: '', configure: [ { - label: 'Username', - name: 'username', + label: 'Customer ID', + name: 'customerId', type: 'text', - placeholder: 'Enter username' + placeholder: 'Enter customer ID' }, { - label: 'Password', - name: 'password', + label: 'API Key', + name: 'apiKey', type: 'password', - placeholder: 'Enter password' + placeholder: 'Enter API key', + popover: [ + 'How to get the API key?', + 'Create an account in Telesign.', + 'Head to Telesign portal -> Profile -> API Keys.' + ] }, { label: 'Sender number', @@ -525,3 +561,96 @@ export const providers: ProvidersMap = { } } }; + +type ProviderParams = { + providerId: string; + name: string; + 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; + customerId: string; + apiKey: 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 & { + fromEmail: string; + fromName: string; + replyToEmail: string; + replyToName: string; + isEuRegion: boolean; + apiKey: string; + domain: string; +}; + +export type SendgridProviderParams = ProviderParams & { + fromEmail: string; + fromName: string; + replyToEmail: string; + replyToName: string; + apiKey: string; +}; + +export type SMTPProviderParams = ProviderParams & { + fromEmail: string; + fromName: string; + replyToEmail: string; + replyToName: string; + host: string; + port: number; + username: string; + password: string; + encryption: SmtpEncryption; + autoTLS: boolean; + mailer: string; +}; + +/** + * Push providers + */ +export type FCMProviderParams = ProviderParams & { + serviceAccountJSON: string; +}; + +export type APNSProviderParams = ProviderParams & { + authKey: string; + authKeyId: string; + teamId: string; + bundleId: string; + sandbox: boolean; +}; + +export type MQTTProviderParams = ProviderParams & { + serverKey: string; +}; diff --git a/src/routes/console/project-[project]/messaging/providers/update.svelte b/src/routes/console/project-[project]/messaging/providers/update.svelte deleted file mode 100644 index 82e0f7d4b..000000000 --- a/src/routes/console/project-[project]/messaging/providers/update.svelte +++ /dev/null @@ -1,164 +0,0 @@ - - - diff --git a/src/routes/console/project-[project]/messaging/providers/wizard/configure.svelte b/src/routes/console/project-[project]/messaging/providers/wizard/configure.svelte deleted file mode 100644 index 47222cc82..000000000 --- a/src/routes/console/project-[project]/messaging/providers/wizard/configure.svelte +++ /dev/null @@ -1,244 +0,0 @@ - - - - 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 === 'password'} - - - {@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} - - - {:else if input.type === 'select'} - - {/if} - {/each} -
    - -
    -

    Need a hand?

    - - {#if providers[$providerType].providers[$provider].needAHand} - {@const needAHand = providers[$providerType].providers[$provider].needAHand} -
    - - - -
    -
    -
    - How to enable - {#if $providerType == MessagingProviderType.Push}notifications{:else}{/if} service? -
    -
    -
    - {#each needAHand as p} -

    - {@html p} -

    - {/each} -
    -
    -
    -
    - {/if} - - - - - -
    -
    -
    -
    - Read the full guide in the documentation -
    -
    -
    -
    - ($newMemberModal = true)}> - -
    -
    -
    -
    - 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 index b5b8fb1d2..cda98136b 100644 --- a/src/routes/console/project-[project]/messaging/providers/wizard/provider.svelte +++ b/src/routes/console/project-[project]/messaging/providers/wizard/provider.svelte @@ -6,15 +6,13 @@ import { FormList, InputText } from '$lib/elements/forms'; import { Pill } from '$lib/elements'; import { Providers } from '../../provider.svelte'; - import { Encryption } from '@appwrite.io/console'; + import { SmtpEncryption } from '@appwrite.io/console'; let name = ''; let showCustomId = false; let id: string = null; async function beforeSubmit() { - console.log($provider); - switch ($provider) { case Providers.Twilio: $providerParams[$provider] = { @@ -41,8 +39,8 @@ providerId: id, name: name, enabled: true, - username: '', - password: '', + customerId: '', + apiKey: '', from: '' }; break; @@ -102,7 +100,7 @@ username: '', password: '', autoTLS: true, - encryption: Encryption.Tls, + encryption: SmtpEncryption.Tls, mailer: '', fromEmail: '', fromName: '', @@ -126,7 +124,8 @@ authKey: '', authKeyId: '', teamId: '', - bundleId: '' + bundleId: '', + sandbox: false }; break; } diff --git a/src/routes/console/project-[project]/messaging/providers/wizard/settings.svelte b/src/routes/console/project-[project]/messaging/providers/wizard/settings.svelte new file mode 100644 index 000000000..46dc634e5 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/providers/wizard/settings.svelte @@ -0,0 +1,174 @@ + + + + Settings + + Set up the credentials below to enable {providers[$providerType].providers[$provider].title} + for sending + {providers[$providerType].text}. + + + + +
    +

    Need a hand?

    + +
    + {#if providers[$providerType].providers[$provider].needAHand} + {@const needAHand = providers[$providerType].providers[$provider].needAHand} +
    + + + +
    +
    +
    + How to enable + {#if $providerType == MessagingProviderType.Push}notifications{:else}{/if} service? +
    +
    +
    + {#each needAHand as p} +

    + {@html p} +

    + {/each} +
    +
    +
    +
    +
    + {/if} + + + +
    +
    +
    +
    +

    Read the full guide in the documentation

    +
    +
    +
    + ($newMemberModal = true)}> +
    +
    +
    +
    +

    Invite a team member to complete this step

    +
    +
    +
    +
    +
    +
    + + + + + diff --git a/src/routes/console/project-[project]/messaging/providers/wizard/store.ts b/src/routes/console/project-[project]/messaging/providers/wizard/store.ts index 764669921..41741b3ce 100644 --- a/src/routes/console/project-[project]/messaging/providers/wizard/store.ts +++ b/src/routes/console/project-[project]/messaging/providers/wizard/store.ts @@ -1,101 +1,18 @@ +import type { MessagingProviderType } from '@appwrite.io/console'; import { writable } from 'svelte/store'; import type { Providers } from '../../provider.svelte'; -import type { MessagingProviderType, Encryption } from '@appwrite.io/console'; - -type ProviderParams = { - providerId: string; - name: string; - 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 & { - fromEmail: string; - fromName: string; - replyToEmail: string; - replyToName: string; - isEuRegion: boolean; - apiKey: string; - domain: string; -}; - -export type SendgridProviderParams = ProviderParams & { - fromEmail: string; - fromName: string; - replyToEmail: string; - replyToName: string; - apiKey: string; -}; - -export type SMTPProviderParams = ProviderParams & { - fromEmail: string; - fromName: string; - replyToEmail: string; - replyToName: string; - host: string; - port: number; - username: string; - password: string; - encryption: Encryption; - autoTLS: boolean; - mailer: string; -}; - -/** - * Push providers - */ - -export type FCMProviderParams = ProviderParams & { - serviceAccountJSON: string; -}; - -export type APNSProviderParams = ProviderParams & { - authKey: string; - authKeyId: string; - teamId: string; - bundleId: string; -}; - -export type MQTTProviderParams = ProviderParams & { - serverKey: string; -}; +import type { + APNSProviderParams, + FCMProviderParams, + MailgunProviderParams, + Msg91ProviderParams, + SMTPProviderParams, + SendgridProviderParams, + TelesignProviderParams, + TextmagicProviderParams, + TwilioProviderParams, + VonageProviderParams +} from '../store'; export const providerType = writable(null); export const provider = writable(null); diff --git a/src/routes/console/project-[project]/messaging/smsPhone.svelte b/src/routes/console/project-[project]/messaging/smsPhone.svelte index 918b87220..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: 539px; + height: 410px; background-image: url('./sms-preview-light.svg'); background-repeat: no-repeat; 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 c2b549369..8c5837596 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 @@ -3,10 +3,12 @@ import DangerZone from './dangerZone.svelte'; import Details from './details.svelte'; import UpdateName from './updateName.svelte'; + import UpdatePermissions from './updatePermissions.svelte';
    + 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..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 @@ -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); @@ -141,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} @@ -154,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.

    diff --git a/src/routes/console/project-[project]/messaging/topics/topic-[topic]/updatePermissions.svelte b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/updatePermissions.svelte new file mode 100644 index 000000000..c74b1ad10 --- /dev/null +++ b/src/routes/console/project-[project]/messaging/topics/topic-[topic]/updatePermissions.svelte @@ -0,0 +1,65 @@ + + +
    + + Subscription access +

    + Choose who can subscribe to this topic using the client API. Learn more about + Permissions. +

    + + + + + + + +
    +
    diff --git a/src/routes/console/project-[project]/messaging/topicsModal.svelte b/src/routes/console/project-[project]/messaging/topicsModal.svelte index 95a03b79c..68c446084 100644 --- a/src/routes/console/project-[project]/messaging/topicsModal.svelte +++ b/src/routes/console/project-[project]/messaging/topicsModal.svelte @@ -91,86 +91,112 @@ -

    - Select existing topics you want to send this message to its targets. The message will be - sent only to targets. -

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

    Total results: {totalResults}

    - +
    +

    + Select existing topics you want to send this message to its targets. The message will be + sent only to targets. +

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

    Total results: {totalResults}

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

    There are no topics that match your search.

    +
    +
    + + +
    +
    +
    +
    +

    Total results: {totalResults}

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

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

    +

    + Need a hand? Learn more in our . +

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

    There are no topics that match your search.

    -
    -
    - - -
    -
    -
    - {:else} - -
    -
    -

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

    -

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

    -
    -
    -
    - {/if} - +
    - +
    +
    + {selectedSize} + Topics selected +
    + +
    diff --git a/src/routes/console/project-[project]/messaging/userTargetsModal.svelte b/src/routes/console/project-[project]/messaging/userTargetsModal.svelte index 7552144aa..066caa90b 100644 --- a/src/routes/console/project-[project]/messaging/userTargetsModal.svelte +++ b/src/routes/console/project-[project]/messaging/userTargetsModal.svelte @@ -24,6 +24,8 @@ let totalResults = 0; let userResultsById: Record>> = {}; // use a hash map so we can quickly look up a user by id let selected: Record = {}; + let selectedSize = 0; + let selectedUsers = 0; let hasSelection = false; function reset() { @@ -108,7 +110,16 @@ request(); } - $: selectedSize = Object.keys(selected).length; + $: { + selectedSize = 0; + const users = new Set(); + for (const s in selected) { + const target = selected[s]; + users.add(target.userId); + selectedSize++; + } + selectedUsers = users.size; + } $: hasSelection = selectedSize > 0; @@ -118,120 +129,167 @@ - +
    + - - {#if Object.keys(userResultsById).length > 0} -
    - - {#each Object.entries(userResultsById) as [userId, user] (userId)} - {@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}/{user.targets.length} targets) - - - {#each user.targets as target} -
    - onTargetSelection(event, target)}> - -
    - - {#if target.providerType !== MessagingProviderType.Push} - {target.identifier} - {:else} - {target.name} - {/if} -
    +
    + +
    + {#if Object.keys(userResultsById).length > 0} +
    +
    + + {#each Object.entries(userResultsById) as [userId, user] (userId)} + {@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} + + + + + {#if user.targets.length === 0} + (0 targets) + {:else} + ({selectedCount}/{user.targets.length} targets) + {/if} + + + {#each user.targets as target} +
    + + onTargetSelection(event, target)}> + +
    + + {#if target.providerType !== MessagingProviderType.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.

    - {/each} - - - {/each} - -
    -
    -

    Total results: {totalResults}

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

    There are no Users that match your search.

    -
    -
    - - -
    +
    + + +
    +
    +
    +
    +

    Total results: {totalResults}

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

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

    +

    + Need a hand? Learn more in our . +

    +
    +
    +
    + {/if}
    - - {:else} - -
    -
    -

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

    -

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

    -
    -
    -
    - {/if} - +
    +
    - +
    +
    + {selectedUsers} + Users selected +
    + +
    + + diff --git a/src/routes/console/project-[project]/messaging/wizard.svelte b/src/routes/console/project-[project]/messaging/wizard.svelte index 4fbc93c55..9ee98b32c 100644 --- a/src/routes/console/project-[project]/messaging/wizard.svelte +++ b/src/routes/console/project-[project]/messaging/wizard.svelte @@ -12,7 +12,7 @@ import { project } from '../store'; import { wizard } from '$lib/stores/wizard'; import { providerType, messageParams, operation } from './wizard/store'; - import { ID, MessageStatus, MessagingProviderType, type Models } from '@appwrite.io/console'; + import { ID, MessagingProviderType, type Models } from '@appwrite.io/console'; import { Dependencies } from '$lib/constants'; async function create() { @@ -32,7 +32,7 @@ undefined, undefined, undefined, - $messageParams[$providerType].status, + $messageParams[$providerType].draft, $messageParams[$providerType].html, $messageParams[$providerType].scheduledAt ); @@ -44,7 +44,7 @@ $messageParams[$providerType].topics, $messageParams[$providerType].users, $messageParams[$providerType].targets, - $messageParams[$providerType].status, + $messageParams[$providerType].draft, $messageParams[$providerType].scheduledAt ); break; @@ -74,7 +74,7 @@ undefined, undefined, undefined, - $messageParams[$providerType].status, + $messageParams[$providerType].draft, $messageParams[$providerType].scheduledAt ); } @@ -83,14 +83,13 @@ wizard.hide(); let message = ''; switch (response.status) { - case MessageStatus.Draft: + case 'draft': message = 'The message has been saved as draft.'; break; - case MessageStatus.Processing: + case 'processing': message = 'The message is queued for processing.'; break; case 'scheduled': - // TODO: fix message status message = 'The message has been scheduled.'; break; } @@ -131,7 +130,7 @@ $messageParams[$providerType].targets, $messageParams[$providerType].subject, $messageParams[$providerType].content, - $messageParams[$providerType].status, + $messageParams[$providerType].draft, $messageParams[$providerType].html, undefined, undefined, @@ -145,7 +144,7 @@ $messageParams[$providerType].users, $messageParams[$providerType].targets, $messageParams[$providerType].content, - $messageParams[$providerType].status, + $messageParams[$providerType].draft, $messageParams[$providerType].scheduledAt ); break; @@ -175,7 +174,7 @@ undefined, undefined, undefined, - $messageParams[$providerType].status, + $messageParams[$providerType].draft, $messageParams[$providerType].scheduledAt ); } @@ -184,14 +183,13 @@ wizard.hide(); let message = ''; switch (response.status) { - case MessageStatus.Draft: + case 'draft': message = 'The message has been saved as draft.'; break; - case MessageStatus.Processing: + case 'processing': message = 'The message is queued for processing.'; break; case 'scheduled': - // TODO: fix message status message = 'The message has been scheduled.'; break; } @@ -202,7 +200,7 @@ await invalidate(Dependencies.MESSAGING_MESSAGE); trackEvent(Submit.MessagingMessageUpdate, { providerType: $providerType, - status: params.status + status: response.status }); await goto(`${base}/console/project-${$project.$id}/messaging/message-${response.$id}`); } catch (error) { @@ -215,7 +213,7 @@ } async function saveDraft() { - $messageParams[$providerType].status = MessageStatus.Draft; + $messageParams[$providerType].draft = true; if ($operation === 'create') { create(); } else { diff --git a/src/routes/console/project-[project]/messaging/wizard/emailFormList.svelte b/src/routes/console/project-[project]/messaging/wizard/emailFormList.svelte index bcc6be1d6..3de535a53 100644 --- a/src/routes/console/project-[project]/messaging/wizard/emailFormList.svelte +++ b/src/routes/console/project-[project]/messaging/wizard/emailFormList.svelte @@ -13,7 +13,7 @@ import { CustomId, Modal } from '$lib/components'; import { user } from '$lib/stores/user'; import { clickOnEnter } from '$lib/helpers/a11y'; - import { ID, MessageStatus, MessagingProviderType } from '@appwrite.io/console'; + import { ID, MessagingProviderType } from '@appwrite.io/console'; import { sdk } from '$lib/stores/sdk'; let showCustomId = false; @@ -36,7 +36,7 @@ undefined, undefined, undefined, - MessageStatus.Processing, + undefined, $messageParams[MessagingProviderType.Email]?.html || false, undefined ); diff --git a/src/routes/console/project-[project]/messaging/wizard/pushFormList.svelte b/src/routes/console/project-[project]/messaging/wizard/pushFormList.svelte index 53c48900c..8a81efc16 100644 --- a/src/routes/console/project-[project]/messaging/wizard/pushFormList.svelte +++ b/src/routes/console/project-[project]/messaging/wizard/pushFormList.svelte @@ -41,7 +41,7 @@ import { CustomId, Modal } from '$lib/components'; import { user } from '$lib/stores/user'; import { clickOnEnter } from '$lib/helpers/a11y'; - import { ID, MessageStatus, MessagingProviderType } from '@appwrite.io/console'; + import { ID, MessagingProviderType } from '@appwrite.io/console'; import { sdk } from '$lib/stores/sdk'; import PushPhone from '../pushPhone.svelte'; import { onMount } from 'svelte'; @@ -76,7 +76,7 @@ undefined, undefined, undefined, - MessageStatus.Processing, + undefined, undefined ); } diff --git a/src/routes/console/project-[project]/messaging/wizard/smsFormList.svelte b/src/routes/console/project-[project]/messaging/wizard/smsFormList.svelte index 876639a2f..dac09f2fb 100644 --- a/src/routes/console/project-[project]/messaging/wizard/smsFormList.svelte +++ b/src/routes/console/project-[project]/messaging/wizard/smsFormList.svelte @@ -5,7 +5,7 @@ import { CustomId, Modal } from '$lib/components'; import { user } from '$lib/stores/user'; import { clickOnEnter } from '$lib/helpers/a11y'; - import { ID, MessageStatus, MessagingProviderType } from '@appwrite.io/console'; + import { ID, MessagingProviderType } from '@appwrite.io/console'; import { sdk } from '$lib/stores/sdk'; import SMSPhone from '../smsPhone.svelte'; @@ -24,7 +24,7 @@ $messageParams[MessagingProviderType.Sms]?.topics || [], $messageParams[MessagingProviderType.Sms]?.users || [], $messageParams[MessagingProviderType.Sms]?.targets || [], - MessageStatus.Processing, + undefined, undefined ); } @@ -102,6 +102,6 @@
    -
    - +
    +
    diff --git a/src/routes/console/project-[project]/messaging/wizard/step2.svelte b/src/routes/console/project-[project]/messaging/wizard/step2.svelte index b7ebda677..da25ba1fa 100644 --- a/src/routes/console/project-[project]/messaging/wizard/step2.svelte +++ b/src/routes/console/project-[project]/messaging/wizard/step2.svelte @@ -89,7 +89,7 @@ {topic.name} - ({getTotal(topic)} subscribers) + ({getTotal(topic)} targets)
    diff --git a/src/routes/console/project-[project]/messaging/wizard/step3.svelte b/src/routes/console/project-[project]/messaging/wizard/step3.svelte index ba2e7be3b..29059d029 100644 --- a/src/routes/console/project-[project]/messaging/wizard/step3.svelte +++ b/src/routes/console/project-[project]/messaging/wizard/step3.svelte @@ -2,7 +2,7 @@ import { Button, FormList, InputDate, InputSelect, InputTime } from '$lib/elements/forms'; import Helper from '$lib/elements/forms/helper.svelte'; import { WizardStep } from '$lib/layout'; - import { MessageStatus, MessagingProviderType } from '@appwrite.io/console'; + import { MessagingProviderType } from '@appwrite.io/console'; import { messageParams, providerType } from './store'; let when: 'now' | 'later' = 'now'; @@ -41,9 +41,7 @@ }; async function beforeSubmit() { - $messageParams[$providerType].status = MessageStatus.Processing; if (when === 'later') { - $messageParams[$providerType].status = 'scheduled' as MessageStatus; $messageParams[$providerType].scheduledAt = dateTime.toISOString(); } } diff --git a/src/routes/console/project-[project]/messaging/wizard/store.ts b/src/routes/console/project-[project]/messaging/wizard/store.ts index e710f7278..9a8457adf 100644 --- a/src/routes/console/project-[project]/messaging/wizard/store.ts +++ b/src/routes/console/project-[project]/messaging/wizard/store.ts @@ -1,4 +1,4 @@ -import { MessageStatus, MessagingProviderType, type Models } from '@appwrite.io/console'; +import { MessagingProviderType, type Models } from '@appwrite.io/console'; import { get, writable } from 'svelte/store'; export type MessageParams = { @@ -6,7 +6,7 @@ export type MessageParams = { topics: string[]; users: string[]; targets: string[]; - status: MessageStatus; + draft: boolean; scheduledAt?: string; }; diff --git a/src/routes/console/project-[project]/overview/keys/wizard/step1.svelte b/src/routes/console/project-[project]/overview/keys/wizard/step1.svelte index 7cd385384..cb53ed034 100644 --- a/src/routes/console/project-[project]/overview/keys/wizard/step1.svelte +++ b/src/routes/console/project-[project]/overview/keys/wizard/step1.svelte @@ -6,7 +6,7 @@ - Create an API key + API key Let's create an API key. - 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 + 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 736d87555..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,7 +15,7 @@ val client = Client(context) - Initialize SDK + Initialize

    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..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,7 +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 420994b55..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,7 +17,7 @@ let client = Client() - Initialize SDK + Initialize

    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 + 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 cc82830e2..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,7 +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 cc2c48958..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,7 +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/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 + Install Choose your preferred method of installation

    diff --git a/src/routes/console/project-[project]/settings/migrations/(import)/step1.svelte b/src/routes/console/project-[project]/settings/migrations/(import)/step1.svelte index 390b42db6..dc1bdbe8b 100644 --- a/src/routes/console/project-[project]/settings/migrations/(import)/step1.svelte +++ b/src/routes/console/project-[project]/settings/migrations/(import)/step1.svelte @@ -1,19 +1,13 @@ - Select source + Source Select a source platform with the project you want to migrate. {:else if $provider.provider === 'firebase'} - {#if !firebaseProjects?.length} - - - - - +
    - - {:else} - - ({ - label: project.displayName, - value: project.projectId - }))} /> - -

    - -

    - {/if} +
    {:else if $provider.provider === 'supabase'}

    Postgres credentials

    diff --git a/src/routes/console/project-[project]/settings/migrations/(import)/step2.svelte b/src/routes/console/project-[project]/settings/migrations/(import)/step2.svelte index 53c9839cb..6528ed9d7 100644 --- a/src/routes/console/project-[project]/settings/migrations/(import)/step2.svelte +++ b/src/routes/console/project-[project]/settings/migrations/(import)/step2.svelte @@ -7,7 +7,7 @@ - Select source + Resources Select the resources you need to migrate to Appwrite. Some resources can be migrated, but with limitations.
    - {entity + 's'} + {total(Object.values(entityCounter)) > 1 + ? ResourcesFriendly[entity].plural + : ResourcesFriendly[entity].singular} {totalItems(entityCounter)}
    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. */ diff --git a/src/routes/console/project-[project]/settings/webhooks/wizard/step1.svelte b/src/routes/console/project-[project]/settings/webhooks/wizard/step1.svelte index 4045874d7..c48e6b0ab 100644 --- a/src/routes/console/project-[project]/settings/webhooks/wizard/step1.svelte +++ b/src/routes/console/project-[project]/settings/webhooks/wizard/step1.svelte @@ -6,7 +6,7 @@ - Add your 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 - Confirm your details + Details Confirm the details of your new organization and start your free trial. diff --git a/src/routes/console/wizard/cloudOrganization/inviteMembers.svelte b/src/routes/console/wizard/cloudOrganization/inviteMembers.svelte index e1359f39b..1bfe98fc6 100644 --- a/src/routes/console/wizard/cloudOrganization/inviteMembers.svelte +++ b/src/routes/console/wizard/cloudOrganization/inviteMembers.svelte @@ -36,7 +36,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. 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/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. diff --git a/src/routes/console/wizard/cloudOrganizationChangeTier/usageExcess.svelte b/src/routes/console/wizard/cloudOrganizationChangeTier/usageExcess.svelte index f3b1a6baa..e5bd500fb 100644 --- a/src/routes/console/wizard/cloudOrganizationChangeTier/usageExcess.svelte +++ b/src/routes/console/wizard/cloudOrganizationChangeTier/usageExcess.svelte @@ -7,8 +7,8 @@ - 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/step2.svelte b/src/routes/console/wizard/feedback/step2.svelte index 1e91272cf..6a79839c5 100644 --- a/src/routes/console/wizard/feedback/step2.svelte +++ b/src/routes/console/wizard/feedback/step2.svelte @@ -6,7 +6,7 @@ - Thanks for the feedback! + Thank you

    {#if $app.themeInUse === 'dark'} diff --git a/src/routes/login/+page.svelte b/src/routes/login/+page.svelte index 4d49845ae..e60e5811b 100644 --- a/src/routes/login/+page.svelte +++ b/src/routes/login/+page.svelte @@ -75,7 +75,6 @@ OAuthProvider.Github, window.location.origin + url, window.location.origin, - undefined, ['read:user', 'user:email'] ); } diff --git a/src/routes/mfa/+page.svelte b/src/routes/mfa/+page.svelte index 1e804f5d4..eedc50900 100644 --- a/src/routes/mfa/+page.svelte +++ b/src/routes/mfa/+page.svelte @@ -16,7 +16,7 @@ async function verify() { try { disabled = true; - const challenge = await sdk.forConsole.account.create2FAChallenge( + const challenge = await sdk.forConsole.account.createChallenge( AuthenticationFactor.Totp ); await sdk.forConsole.account.updateChallenge(challenge.$id, code); diff --git a/src/routes/register/+page.svelte b/src/routes/register/+page.svelte index 5344cea31..ccc179174 100644 --- a/src/routes/register/+page.svelte +++ b/src/routes/register/+page.svelte @@ -64,7 +64,6 @@ OAuthProvider.Github, window.location.origin, window.location.origin, - undefined, ['read:user', 'user:email'] ); } diff --git a/static/images/apns-bundle-id.png b/static/images/apns-bundle-id.png deleted file mode 100644 index 90fde1eff..000000000 Binary files a/static/images/apns-bundle-id.png and /dev/null differ diff --git a/static/images/messaging/apns-auth-key.png b/static/images/messaging/apns-auth-key.png new file mode 100644 index 000000000..9034d5d2b Binary files /dev/null and b/static/images/messaging/apns-auth-key.png differ diff --git a/static/images/messaging/apns-authentication-key-id.png b/static/images/messaging/apns-authentication-key-id.png new file mode 100644 index 000000000..6101664f4 Binary files /dev/null and b/static/images/messaging/apns-authentication-key-id.png differ diff --git a/static/images/messaging/apns-bundle-id.png b/static/images/messaging/apns-bundle-id.png new file mode 100644 index 000000000..8ef8b8f32 Binary files /dev/null and b/static/images/messaging/apns-bundle-id.png differ diff --git a/static/images/messaging/apns-team-id.png b/static/images/messaging/apns-team-id.png new file mode 100644 index 000000000..65ee4dd87 Binary files /dev/null and b/static/images/messaging/apns-team-id.png differ diff --git a/static/images/messaging/fcm-service-account-json-dark.png b/static/images/messaging/fcm-service-account-json-dark.png new file mode 100644 index 000000000..0ee51da95 Binary files /dev/null and b/static/images/messaging/fcm-service-account-json-dark.png differ diff --git a/static/images/messaging/fcm-service-account-json-light.png b/static/images/messaging/fcm-service-account-json-light.png new file mode 100644 index 000000000..66bb96fc0 Binary files /dev/null and b/static/images/messaging/fcm-service-account-json-light.png differ