diff --git a/.env.example b/.env.example index 06149b167..0f445822b 100644 --- a/.env.example +++ b/.env.example @@ -1,4 +1,7 @@ VITE_APPWRITE_ENDPOINT= +VITE_APPWRITE_GROWTH_ENDPOINT= VITE_GA_PROJECT= VITE_SENTRY_DSN= -VITE_CONSOLE_MODE=self-hosted \ No newline at end of file +VITE_CONSOLE_MODE=self-hosted +VITE_CONSOLE_MODE=cloud +VITE_CONSOLE_TIER=base \ No newline at end of file diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 23c8a98f8..1c666816b 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -13,7 +13,7 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Use Node.js uses: actions/setup-node@v2 with: diff --git a/package-lock.json b/package-lock.json index 785ae480a..52821597c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "0.0.1", "dependencies": { "@analytics/google-analytics": "^1.0.5", - "@aw-labs/appwrite-console": "^13.0.0", + "@aw-labs/appwrite-console": "^13.1.0", "@aw-labs/icons": "0.0.0-77", "@aw-labs/ui": "0.0.0-77", "@popperjs/core": "^2.11.6", @@ -145,9 +145,9 @@ "integrity": "sha512-1Yw7u/COtxx06BfwlI+kVhsa/upKYzmCNrT4c8QDeCY2KMYlnijkUjtHiPU08HxyTIVB5j6d75O0YWVIHwQS8g==" }, "node_modules/@aw-labs/appwrite-console": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/@aw-labs/appwrite-console/-/appwrite-console-13.0.0.tgz", - "integrity": "sha512-a5illDoFZAhgLP8Ae+KHPzBIUozKXzjyHUw6jTwNPZaL+b2RnTe3oRLZU8l8Kt5pB5m7NZx6kAcZm+NMf8NeCw==", + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/@aw-labs/appwrite-console/-/appwrite-console-13.1.0.tgz", + "integrity": "sha512-1FyKke5b3vx+D3VfNYd3YnFhzUOlsj9bD+KTRLWA4WRItb55thFVZJMWQQ4XnZtDiLPuJAn2XjbMSfMr+9XYwg==", "dependencies": { "cross-fetch": "3.1.5", "isomorphic-form-data": "2.0.0" @@ -5399,9 +5399,9 @@ "dev": true }, "node_modules/json5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", - "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, "peer": true, "bin": { @@ -7740,9 +7740,9 @@ "integrity": "sha512-1Yw7u/COtxx06BfwlI+kVhsa/upKYzmCNrT4c8QDeCY2KMYlnijkUjtHiPU08HxyTIVB5j6d75O0YWVIHwQS8g==" }, "@aw-labs/appwrite-console": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/@aw-labs/appwrite-console/-/appwrite-console-13.0.0.tgz", - "integrity": "sha512-a5illDoFZAhgLP8Ae+KHPzBIUozKXzjyHUw6jTwNPZaL+b2RnTe3oRLZU8l8Kt5pB5m7NZx6kAcZm+NMf8NeCw==", + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/@aw-labs/appwrite-console/-/appwrite-console-13.1.0.tgz", + "integrity": "sha512-1FyKke5b3vx+D3VfNYd3YnFhzUOlsj9bD+KTRLWA4WRItb55thFVZJMWQQ4XnZtDiLPuJAn2XjbMSfMr+9XYwg==", "requires": { "cross-fetch": "3.1.5", "isomorphic-form-data": "2.0.0" @@ -11827,9 +11827,9 @@ "dev": true }, "json5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", - "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, "peer": true }, diff --git a/package.json b/package.json index cbd2c487c..266a4d365 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "dependencies": { "@analytics/google-analytics": "^1.0.5", "analytics": "^0.8.1", - "@aw-labs/appwrite-console": "^13.0.0", + "@aw-labs/appwrite-console": "^13.1.0", "@aw-labs/icons": "0.0.0-77", "@aw-labs/ui": "0.0.0-77", "@popperjs/core": "^2.11.6", diff --git a/src/lib/actions/analytics.ts b/src/lib/actions/analytics.ts index d169790ac..a57000024 100644 --- a/src/lib/actions/analytics.ts +++ b/src/lib/actions/analytics.ts @@ -3,7 +3,7 @@ import googleAnalytics from '@analytics/google-analytics'; import { get } from 'svelte/store'; import { page } from '$app/stores'; import { user } from '$lib/stores/user'; -import { Mode } from '$lib/constants'; +import { growthEndpoint, Mode } from '$lib/constants'; const analytics = Analytics({ app: 'appwrite', @@ -40,7 +40,7 @@ function sendEventToGrowth(event: string, path: string, data: object = null): vo email = userStore.email; name = userStore.name; } - fetch('https://growth.appwrite.io/v1/analytics', { + fetch(`${growthEndpoint}/analytics`, { method: 'POST', headers: { 'Content-Type': 'application/json' diff --git a/src/lib/components/copy.svelte b/src/lib/components/copy.svelte index 1f0e5dfd8..0e859e79c 100644 --- a/src/lib/components/copy.svelte +++ b/src/lib/components/copy.svelte @@ -2,6 +2,7 @@ import { trackEvent } from '$lib/actions/analytics'; import { tooltip } from '$lib/actions/tooltip'; import { clickOnEnter } from '$lib/helpers/a11y'; + import { copy } from '$lib/helpers/copy'; import { addNotification } from '$lib/stores/notifications'; export let value: string; @@ -9,27 +10,28 @@ let content = 'Click to copy'; - const copy = async () => { - try { - await navigator.clipboard.writeText(value); + async function handleClick() { + const success = await copy(value); + + if (success) { content = 'Copied'; - } catch (error) { + } else { addNotification({ - message: error.message, + message: 'Unable to copy to clipboard', type: 'error' }); - } finally { - if (event) { - trackEvent('click_id_tag', { - name: event - }); - } } - }; + + if (event) { + trackEvent('click_id_tag', { + name: event + }); + } + } setTimeout(() => (content = 'Click to copy'))} use:tooltip={{ diff --git a/src/lib/components/copyInput.svelte b/src/lib/components/copyInput.svelte index 65bd6bb81..b06f1ae36 100644 --- a/src/lib/components/copyInput.svelte +++ b/src/lib/components/copyInput.svelte @@ -1,5 +1,6 @@ {#if [...$groups]?.length} - +
- Role + Role {#if withCreate} Create {/if} diff --git a/src/lib/components/permissions/roles.svelte b/src/lib/components/permissions/roles.svelte index 39c39bef1..1f8ebaf03 100644 --- a/src/lib/components/permissions/roles.svelte +++ b/src/lib/components/permissions/roles.svelte @@ -92,9 +92,9 @@ {#if [...$groups.keys()]?.length} -
+
- Role + Role diff --git a/src/lib/components/permissions/row.svelte b/src/lib/components/permissions/row.svelte index 66dbbca67..e69f66616 100644 --- a/src/lib/components/permissions/row.svelte +++ b/src/lib/components/permissions/row.svelte @@ -53,59 +53,61 @@ }) .finally(() => { tick().then(() => { - instance.setContent(content.innerHTML); + instance.setContent(content); }); }); } }}> {role} -
- {#if data} - {@const isUser = role.startsWith('user')} - {@const isTeam = role.startsWith('team')} - {@const isAnonymous = !data.email && !data.phone} - {/if}
diff --git a/src/lib/constants.ts b/src/lib/constants.ts index 74b8860e8..428ae6392 100644 --- a/src/lib/constants.ts +++ b/src/lib/constants.ts @@ -7,6 +7,8 @@ export enum Mode { SELF_HOSTED = 'self-hosted' } +export const growthEndpoint = import.meta.env.VITE_APPWRITE_GROWTH_ENDPOINT; + export enum Dependencies { ORGANIZATION = 'dependency:organization', PROJECT = 'dependency:project', diff --git a/src/lib/elements/forms/inputTags.svelte b/src/lib/elements/forms/inputTags.svelte index 93d31f8ac..82528258e 100644 --- a/src/lib/elements/forms/inputTags.svelte +++ b/src/lib/elements/forms/inputTags.svelte @@ -10,9 +10,11 @@ export let autofocus = false; export let disabled = false; export let readonly = false; + export let required = false; let value = ''; let element: HTMLInputElement; + let hiddenEl: HTMLInputElement; let error: string; onMount(() => { @@ -54,11 +56,11 @@ const handleInvalid = (event: Event) => { event.preventDefault(); - if (element.validity.valueMissing) { + if (hiddenEl.validity.valueMissing) { error = 'This field is required'; return; } - error = element.validationMessage; + error = hiddenEl.validationMessage; }; $: if (value) { @@ -67,6 +69,12 @@ +
@@ -98,8 +106,7 @@ bind:value bind:this={element} on:keydown={handleInput} - on:blur={addValue} - on:invalid={handleInvalid} /> + on:blur={addValue} />
{#if error} diff --git a/src/lib/elements/table/cellHead.svelte b/src/lib/elements/table/cellHead.svelte index 7be4a0655..2ec99eca5 100644 --- a/src/lib/elements/table/cellHead.svelte +++ b/src/lib/elements/table/cellHead.svelte @@ -1,9 +1,11 @@
diff --git a/src/lib/elements/table/cellText.svelte b/src/lib/elements/table/cellText.svelte index 59b8fe2e3..59dcba6e4 100644 --- a/src/lib/elements/table/cellText.svelte +++ b/src/lib/elements/table/cellText.svelte @@ -2,8 +2,14 @@ import { Trim } from '$lib/components'; export let title: string; export let showOverflow = false; + export let onlyDesktop = false; -
+
diff --git a/src/lib/elements/table/table.svelte b/src/lib/elements/table/table.svelte index 902a22ed3..42e67b2cd 100644 --- a/src/lib/elements/table/table.svelte +++ b/src/lib/elements/table/table.svelte @@ -1,12 +1,10 @@
diff --git a/src/lib/elements/table/tableScroll.svelte b/src/lib/elements/table/tableScroll.svelte index 77f37c60a..52b84a940 100644 --- a/src/lib/elements/table/tableScroll.svelte +++ b/src/lib/elements/table/tableScroll.svelte @@ -1,7 +1,11 @@ + +
-
+
- +
diff --git a/src/lib/helpers/copy.ts b/src/lib/helpers/copy.ts new file mode 100644 index 000000000..6399995ea --- /dev/null +++ b/src/lib/helpers/copy.ts @@ -0,0 +1,36 @@ +async function securedCopy(value: string) { + try { + await navigator.clipboard.writeText(value); + } catch { + return false; + } + + return true; +} + +function unsecuredCopy(value: string) { + const textArea = document.createElement('textarea'); + textArea.value = value; + document.body.appendChild(textArea); + textArea.focus(); + textArea.select(); + + let success = true; + try { + document.execCommand('copy'); + } catch { + success = false; + } finally { + document.body.removeChild(textArea); + } + + return success; +} + +export async function copy(value: string) { + // securedCopy works only in HTTPS environment. + // unsecuredCopy works in HTTP and only runs if securedCopy fails. + const success = (await securedCopy(value)) || unsecuredCopy(value); + + return success; +} diff --git a/src/lib/layout/activity.svelte b/src/lib/layout/activity.svelte index a74108a63..ebe9c0420 100644 --- a/src/lib/layout/activity.svelte +++ b/src/lib/layout/activity.svelte @@ -1,13 +1,13 @@ {#if $collection} - - {$collection.name} - - -
    - -
-
-

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

-

Last Updated: {toLocaleDateTime($collection.$updatedAt)}

-
-
- - - - -
- - - Update Name - - -
    - - {#if showError === 'name'} - {errorMessage} - {/if} -
-
- - - - -
- - - Update Permissions -

- Choose who can access your collection and documents. For more information, check out - the Permissions Guide in our documentation. -

- - {#if collectionPermissions} - - {/if} - - - - -
- - - Update Document Security - - - - -

- When document security is enabled, users will be able to access documents for - which they have been granted either Document or Collection permissions. -

-

- If document security is disabled, users can access documents only if they have Collection permissions. Document permissions will be ignored. -

-
- - - -
- - - Delete Collection -

- The collection will be permanently deleted, including all the documents within it. - This action is irreversible. -

- - - -
{$collection.name}
-
-

Last Updated: {toLocaleDateTime($collection.$updatedAt)}

-
-
- - - - -
+ + + + + {/if}
- - diff --git a/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/settings/dangerZone.svelte b/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/settings/dangerZone.svelte new file mode 100644 index 000000000..53653a2d4 --- /dev/null +++ b/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/settings/dangerZone.svelte @@ -0,0 +1,31 @@ + + + + Delete Collection +

+ The collection will be permanently deleted, including all the documents within it. This + action is irreversible. +

+ + + +
{$collection.name}
+
+

Last Updated: {toLocaleDateTime($collection.$updatedAt)}

+
+
+ + + + +
+ + diff --git a/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/settings/updateName.svelte b/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/settings/updateName.svelte new file mode 100644 index 000000000..e98422453 --- /dev/null +++ b/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/settings/updateName.svelte @@ -0,0 +1,66 @@ + + +
+ + Update Name + + +
    + +
+
+ + + + +
+
diff --git a/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/settings/updatePermissions.svelte b/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/settings/updatePermissions.svelte new file mode 100644 index 000000000..6589c22c0 --- /dev/null +++ b/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/settings/updatePermissions.svelte @@ -0,0 +1,75 @@ + + + + Update Permissions +

+ Choose who can access your collection and documents. For more information, check out the Permissions Guide in our documentation. +

+ + {#if collectionPermissions} + + {/if} + + + + +
diff --git a/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/settings/updateSecurity.svelte b/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/settings/updateSecurity.svelte new file mode 100644 index 000000000..87d601be6 --- /dev/null +++ b/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/settings/updateSecurity.svelte @@ -0,0 +1,70 @@ + + + + Update Document Security + + + + +

+ When document security is enabled, users will be able to access documents for which they + have been granted either Document or Collection permissions. +

+

+ If document security is disabled, users can access documents only if they have Collection permissions. Document permissions will be ignored. +

+
+ + + +
diff --git a/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/settings/updateStatus.svelte b/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/settings/updateStatus.svelte new file mode 100644 index 000000000..6c1353320 --- /dev/null +++ b/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/settings/updateStatus.svelte @@ -0,0 +1,68 @@ + + + + {$collection.name} + + +
    + +
+
+

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

+

Last Updated: {toLocaleDateTime($collection.$updatedAt)}

+
+
+ + + + +
diff --git a/src/routes/console/project-[project]/functions/function-[function]/create.svelte b/src/routes/console/project-[project]/functions/function-[function]/create.svelte index 14373c646..c8e2f9e08 100644 --- a/src/routes/console/project-[project]/functions/function-[function]/create.svelte +++ b/src/routes/console/project-[project]/functions/function-[function]/create.svelte @@ -97,7 +97,7 @@ files = entrypoint = active = null; showCreate = false; dispatch('created'); - trackEvent('submit_function_create'); + trackEvent('submit_deployment_create'); } catch (error) { addNotification({ type: 'error', diff --git a/src/routes/console/project-[project]/overview/keys/+page.svelte b/src/routes/console/project-[project]/overview/keys/+page.svelte index 1c08f5b5f..714ccea79 100644 --- a/src/routes/console/project-[project]/overview/keys/+page.svelte +++ b/src/routes/console/project-[project]/overview/keys/+page.svelte @@ -35,9 +35,9 @@ Name - last accessed - expiration date - scopes + last accessed + expiration date + scopes {#each data.keys.keys as key} @@ -45,13 +45,13 @@ {key.name} - + {key.accessedAt ? toLocaleDateTime(key.accessedAt) : 'never'} - + {key.expire ? toLocaleDateTime(key.expire) : 'never'} - + {key.scopes.length} Scopes diff --git a/src/routes/console/project-[project]/overview/platforms/[platform]/+page.ts b/src/routes/console/project-[project]/overview/platforms/[platform]/+page.ts index 2779bbeb7..ca361d2c3 100644 --- a/src/routes/console/project-[project]/overview/platforms/[platform]/+page.ts +++ b/src/routes/console/project-[project]/overview/platforms/[platform]/+page.ts @@ -5,7 +5,7 @@ import { Dependencies } from '$lib/constants'; import type { PageLoad } from './$types'; export const load: PageLoad = async ({ params, depends }) => { - depends(Dependencies.PROJECT); + depends(Dependencies.PLATFORM); return { header: Header, diff --git a/src/routes/console/project-[project]/overview/platforms/[platform]/+page@project-[project].svelte b/src/routes/console/project-[project]/overview/platforms/[platform]/+page@project-[project].svelte index b66a71d9e..a4fb03c7d 100644 --- a/src/routes/console/project-[project]/overview/platforms/[platform]/+page@project-[project].svelte +++ b/src/routes/console/project-[project]/overview/platforms/[platform]/+page@project-[project].svelte @@ -20,11 +20,8 @@ import { project } from '../../../store'; import { platform } from './store'; import { Dependencies } from '$lib/constants'; - import type { PageData } from './$types'; import { invalidate } from '$app/navigation'; - export let data: PageData; - const types: Record = { web: Web, android: Android, @@ -41,20 +38,22 @@ let showDelete = false; let name: string = null; + let updating = false; onMount(() => { - name ??= data.platform.name; + name ??= $platform.name; }); - const updateName = async () => { + async function updateName() { + updating = true; try { await sdkForConsole.projects.updatePlatform( $project.$id, - data.platform.$id, + $platform.$id, name, - data.platform.key, - data.platform.store, - data.platform.hostname + $platform.key, + $platform.store, + $platform.hostname ); invalidate(Dependencies.PLATFORM); addNotification({ @@ -67,7 +66,13 @@ message: error.message }); } - }; + } + + $: { + // When platform name is updated, finalize the updating flow + $platform.name; + updating = false; + } @@ -87,7 +92,7 @@ - + diff --git a/src/routes/console/project-[project]/overview/platforms/[platform]/android.svelte b/src/routes/console/project-[project]/overview/platforms/[platform]/android.svelte index ebcd4ce21..fa23169a1 100644 --- a/src/routes/console/project-[project]/overview/platforms/[platform]/android.svelte +++ b/src/routes/console/project-[project]/overview/platforms/[platform]/android.svelte @@ -10,10 +10,10 @@ import { project } from '../../../store'; import { platform } from './store'; - let hostname: string = null; + let key: string = null; onMount(() => { - hostname ??= $platform.hostname; + key ??= $platform.key; }); const updateHostname = async () => { @@ -22,9 +22,9 @@ $project.$id, $platform.$id, $platform.name, - $platform.key, + key, $platform.store, - hostname + $platform.hostname ); invalidate(Dependencies.PLATFORM); trackEvent('submit_platform_update', { @@ -52,16 +52,16 @@ - + 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 2ff8ac01c..7971b24e6 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 @@ -31,9 +31,9 @@ projectId, 'android', $createPlatform.name, + $createPlatform.key, undefined, - undefined, - $createPlatform.hostname + undefined ); $createPlatform.$id = platform.$id; @@ -50,11 +50,11 @@ required bind:value={$createPlatform.name} /> + bind:value={$createPlatform.key} /> 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 08052981f..49cdcd687 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 @@ -41,9 +41,9 @@ projectId, platform, $createPlatform.name, + $createPlatform.key, undefined, - undefined, - $createPlatform.hostname + undefined ); $createPlatform.$id = response.$id; @@ -95,6 +95,6 @@ placeholder="com.company.appname" tooltip="You can find your Bundle Identifier in the General tab for your app's primary target in Xcode." required - bind:value={$createPlatform.hostname} /> + bind:value={$createPlatform.key} /> 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 df6f60ad0..82a356e4c 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 @@ -25,7 +25,7 @@ let platform: Platform = Platform.Android; const projectId = $page.params.project; - const suggestions = ['*.vercel.app', '*.netlify.app', '*.gitpod.app']; + const suggestions = ['*.vercel.app', '*.netlify.app', '*.gitpod.io']; const placeholder: Record< Platform, { @@ -97,9 +97,9 @@ projectId, platform, $createPlatform.name, + platform !== Platform.Web ? $createPlatform.key : undefined, undefined, - undefined, - $createPlatform.hostname + platform === Platform.Web ? $createPlatform.hostname : undefined ); $createPlatform.$id = response.$id; @@ -160,15 +160,16 @@ placeholder={placeholder[platform].name} required bind:value={$createPlatform.name} /> -
- - {#if platform === Platform.Web} + {#if platform === Platform.Web} +
+ +
{#each suggestions as suggestion} {/each}
- {/if} -
+
+ {:else} + + {/if} 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 aa1ff28ea..5a3e555da 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 @@ -12,7 +12,7 @@ import Dark from './dark.svg'; const projectId = $page.params.project; - const suggestions = ['*.vercel.app', '*.netlify.app', '*.gitpod.app']; + const suggestions = ['*.vercel.app', '*.netlify.app', '*.gitpod.io']; $wizard.media = $app.themeInUse === 'dark' ? Dark : Light; async function beforeSubmit() { diff --git a/src/routes/console/project-[project]/settings/+page.svelte b/src/routes/console/project-[project]/settings/+page.svelte index 397054b1a..76277fbf2 100644 --- a/src/routes/console/project-[project]/settings/+page.svelte +++ b/src/routes/console/project-[project]/settings/+page.svelte @@ -17,6 +17,7 @@ let name: string = null; let showDelete = false; + let updating = false; const endpoint = sdkForConsole.client.config.endpoint; const projectId = $page.params.project; @@ -24,7 +25,8 @@ name ??= $project.name; }); - const updateName = async () => { + async function updateName() { + updating = true; try { await sdkForConsole.projects.update($project.$id, name); invalidate(Dependencies.PROJECT); @@ -39,9 +41,15 @@ message: error.message }); } - }; + } - const serviceUpdate = async (service: Service) => { + $: { + // When project name is updated, finalize the updating flow + $project.name; + updating = false; + } + + async function serviceUpdate(service: Service) { try { await sdkForConsole.projects.updateServiceStatus( $project.$id, @@ -65,7 +73,7 @@ message: error.message }); } - }; + } $: services.load($project); @@ -105,7 +113,7 @@ - + diff --git a/src/routes/console/project-[project]/settings/domains/[[page]]/+page.svelte b/src/routes/console/project-[project]/settings/domains/[[page]]/+page.svelte index 79f81461d..4ec970670 100644 --- a/src/routes/console/project-[project]/settings/domains/[[page]]/+page.svelte +++ b/src/routes/console/project-[project]/settings/domains/[[page]]/+page.svelte @@ -4,13 +4,13 @@ import { Pill } from '$lib/elements'; import { Button } from '$lib/elements/forms'; import { - Table, TableBody, TableCell, TableCellHead, TableCellText, TableHeader, - TableRow + TableRow, + TableScroll } from '$lib/elements/table'; import { Container } from '$lib/layout'; import { addNotification } from '$lib/stores/notifications'; @@ -68,14 +68,14 @@ {#if data.domains.total} -
+ - Domain Name + Domain Name Type - Name - Value - + Name + Value + {#each data.domains.domains as domain} @@ -131,7 +131,7 @@ {/each} -
+ {:else} - import { onMount } from 'svelte'; - import { CardGrid, Box, Secret, Empty, EventModal, Heading } from '$lib/components'; - import { - Button, - Form, - FormList, - InputText, - InputChoice, - InputPassword - } from '$lib/elements/forms'; - import { TableList, TableCellText, TableCell } from '$lib/elements/table'; import { Container } from '$lib/layout'; - import { addNotification } from '$lib/stores/notifications'; - import { sdkForConsole } from '$lib/stores/sdk'; - import { webhook } from './store'; - import { page } from '$app/stores'; - import { toLocaleDateTime } from '$lib/helpers/date'; - import Delete from './delete.svelte'; - import Regenerate from './regenerate.svelte'; - import { symmetricDifference } from '$lib/helpers/array'; - import { invalidate } from '$app/navigation'; - import { Dependencies } from '$lib/constants'; - import { writable, type Writable } from 'svelte/store'; - import { trackEvent } from '$lib/actions/analytics'; - - const projectId = $page.params.project; - let name: string = null; - let url: string = null; - - const eventSet: Writable> = writable(new Set()); - - let httpUser: string = null; - let httpPass: string = null; - let security = false; - let showDelete = false; - let showCreateEvent = false; - let areEventsDisabled = true; - let showRegenerate = false; - - onMount(async () => { - name ??= $webhook.name; - url ??= $webhook.url; - $eventSet = new Set($webhook.events); - httpUser ??= $webhook.httpUser; - httpPass ??= $webhook.httpPass; - security = $webhook.security; - }); - - async function updateName() { - try { - await sdkForConsole.projects.updateWebhook( - projectId, - $webhook.$id, - name, - $webhook.events, - $webhook.url, - $webhook.security, - $webhook.httpUser, - $webhook.httpPass - ); - invalidate(Dependencies.WEBHOOK); - addNotification({ - type: 'success', - message: 'Webhook name has been updated' - }); - trackEvent('submit_webhook_update_name'); - } catch (error) { - addNotification({ - type: 'error', - message: error.message - }); - } - } - async function updateUrl() { - try { - await sdkForConsole.projects.updateWebhook( - projectId, - $webhook.$id, - $webhook.name, - $webhook.events, - url, - $webhook.security, - $webhook.httpUser, - $webhook.httpPass - ); - invalidate(Dependencies.WEBHOOK); - addNotification({ - type: 'success', - message: 'Webhook url has been updated' - }); - trackEvent('submit_webhook_update_url'); - } catch (error) { - addNotification({ - type: 'error', - message: error.message - }); - } - } - async function updateEvents() { - try { - await sdkForConsole.projects.updateWebhook( - projectId, - $webhook.$id, - $webhook.name, - Array.from($eventSet), - $webhook.url, - $webhook.security, - $webhook.httpUser, - $webhook.httpPass - ); - invalidate(Dependencies.WEBHOOK); - areEventsDisabled = true; - addNotification({ - type: 'success', - message: 'Webhook events have been updated' - }); - trackEvent('submit_webhook_update_events'); - } catch (error) { - addNotification({ - type: 'error', - message: error.message - }); - } - } - - async function updateSecurity() { - try { - await sdkForConsole.projects.updateWebhook( - projectId, - $webhook.$id, - $webhook.name, - $webhook.events, - $webhook.url, - security, - httpUser, - httpPass - ); - invalidate(Dependencies.WEBHOOK); - addNotification({ - type: 'success', - message: 'Webhook security has been updated' - }); - trackEvent('submit_webhook_update_security'); - } catch (error) { - addNotification({ - type: 'error', - message: error.message - }); - } - } - - function handleEvent(event: CustomEvent) { - eventSet.set($eventSet.add(event.detail)); - } - - $: if ($eventSet) { - if (symmetricDifference(Array.from($eventSet), $webhook.events).length) { - areEventsDisabled = false; - } else areEventsDisabled = true; - } + import DangerZone from './dangerZone.svelte'; + import UpdateEvents from './updateEvents.svelte'; + import UpdateName from './updateName.svelte'; + import UpdateSecurity from './updateSecurity.svelte'; + import UpdateSignature from './updateSignature.svelte'; + import UpdateUrl from './updateURL.svelte'; - - Signature Key -

- Add the Signature Key to the X-Appwrite-Webhook-Signature header to validate your - webhooks. Learn more about webhook validation. -

- -
-

Key

- -
-
- - - -
-
- - Update Name -

Choose any name that will help you distinguish between Webhooks.

- - - - - - - - - -
-
- -
- - Update Url - - - - - - - - - - - -
- -
- - Update Events -

- Set the events that will trigger your webhook. Maximum 100 events allowed. -

- - {#if $eventSet.size} - - {#each Array.from($eventSet) as event} -
  • - - {event} - - - - -
  • - {/each} -
    -
    - -
    - {:else} - (showCreateEvent = true)}> - Add an event to get started - - {/if} -
    - - - - -
    -
    - -
    - - Security -

    - Set an optional basic HTTP authentication username and password to protect your - endpoint from unauthorized access. -

    - - -
    - HTTP Authentication -

    Use to secure your endpoint from untrusted sources.

    -
    - - - - - Warning: Untrusted or self-signed certificates - may not be secure. - - Learn more - -
    -
    - - - - -
    -
    - - -
    - Delete Webhook -
    -

    The webhook will be permanently deleted. This action is irreversible.

    - - - -
    {$webhook.name}
    -
    -

    Last updated: {toLocaleDateTime($webhook.$updatedAt)}

    -
    -
    - - - - -
    + + + + + +
    - - - - - diff --git a/src/routes/console/project-[project]/settings/webhooks/[webhook]/dangerZone.svelte b/src/routes/console/project-[project]/settings/webhooks/[webhook]/dangerZone.svelte new file mode 100644 index 000000000..c531b91a4 --- /dev/null +++ b/src/routes/console/project-[project]/settings/webhooks/[webhook]/dangerZone.svelte @@ -0,0 +1,30 @@ + + + +
    + Delete Webhook +
    +

    The webhook will be permanently deleted. This action is irreversible.

    + + + +
    {$webhook.name}
    +
    +

    Last updated: {toLocaleDateTime($webhook.$updatedAt)}

    +
    +
    + + + + +
    + + diff --git a/src/routes/console/project-[project]/settings/webhooks/[webhook]/updateEvents.svelte b/src/routes/console/project-[project]/settings/webhooks/[webhook]/updateEvents.svelte new file mode 100644 index 000000000..919d21402 --- /dev/null +++ b/src/routes/console/project-[project]/settings/webhooks/[webhook]/updateEvents.svelte @@ -0,0 +1,109 @@ + + +
    + + Update Events +

    + Set the events that will trigger your webhook. Maximum 100 events allowed. +

    + + {#if $eventSet.size} + + {#each Array.from($eventSet) as event} +
  • + + {event} + + + + +
  • + {/each} +
    +
    + +
    + {:else} + (showCreateEvent = true)}>Add an event to get started + {/if} +
    + + + + +
    +
    + + diff --git a/src/routes/console/project-[project]/settings/webhooks/[webhook]/updateName.svelte b/src/routes/console/project-[project]/settings/webhooks/[webhook]/updateName.svelte new file mode 100644 index 000000000..1d4fcd0cf --- /dev/null +++ b/src/routes/console/project-[project]/settings/webhooks/[webhook]/updateName.svelte @@ -0,0 +1,66 @@ + + +
    + + Update Name +

    Choose any name that will help you distinguish between Webhooks.

    + + + + + + + + + +
    +
    diff --git a/src/routes/console/project-[project]/settings/webhooks/[webhook]/updateSecurity.svelte b/src/routes/console/project-[project]/settings/webhooks/[webhook]/updateSecurity.svelte new file mode 100644 index 000000000..dc1d1d8ce --- /dev/null +++ b/src/routes/console/project-[project]/settings/webhooks/[webhook]/updateSecurity.svelte @@ -0,0 +1,110 @@ + + +
    + + Security +

    + Set an optional basic HTTP authentication username and password to protect your endpoint + from unauthorized access. +

    + + +
    + HTTP Authentication +

    Use to secure your endpoint from untrusted sources.

    +
    + + + + + Warning: Untrusted or self-signed certificates may + not be secure. + + Learn more + +
    +
    + + + + +
    +
    diff --git a/src/routes/console/project-[project]/settings/webhooks/[webhook]/updateSignature.svelte b/src/routes/console/project-[project]/settings/webhooks/[webhook]/updateSignature.svelte new file mode 100644 index 000000000..7f65c7677 --- /dev/null +++ b/src/routes/console/project-[project]/settings/webhooks/[webhook]/updateSignature.svelte @@ -0,0 +1,30 @@ + + + + Signature Key +

    + Add the Signature Key to the X-Appwrite-Webhook-Signature header to validate your webhooks. Learn more about webhook validation. +

    + +
    +

    Key

    + +
    +
    + + + +
    + + diff --git a/src/routes/console/project-[project]/settings/webhooks/[webhook]/updateURL.svelte b/src/routes/console/project-[project]/settings/webhooks/[webhook]/updateURL.svelte new file mode 100644 index 000000000..ff775045d --- /dev/null +++ b/src/routes/console/project-[project]/settings/webhooks/[webhook]/updateURL.svelte @@ -0,0 +1,66 @@ + + +
    + + Update Url + + + + + + + + + + + +
    diff --git a/src/routes/console/project-[project]/storage/bucket-[bucket]/[[page]]/+page.svelte b/src/routes/console/project-[project]/storage/bucket-[bucket]/[[page]]/+page.svelte index 0592ac359..3e0dfb37f 100644 --- a/src/routes/console/project-[project]/storage/bucket-[bucket]/[[page]]/+page.svelte +++ b/src/routes/console/project-[project]/storage/bucket-[bucket]/[[page]]/+page.svelte @@ -86,9 +86,9 @@ Filename - Type - Size - Created + Type + Size + Created @@ -99,17 +99,17 @@
    - {file.name} + {file.name}
    Pending
    - {file.mimeType} - + {file.mimeType} + {calculateSize(file.sizeOriginal)} - + {toLocaleDate(file.$createdAt)} @@ -137,14 +137,14 @@
    - {file.name} + {file.name}
    - {file.mimeType} - + {file.mimeType} + {calculateSize(file.sizeOriginal)} - + {toLocaleDate(file.$createdAt)} diff --git a/src/routes/console/project-[project]/storage/bucket-[bucket]/settings/+page.svelte b/src/routes/console/project-[project]/storage/bucket-[bucket]/settings/+page.svelte index b7fd139e5..5d1aa0c48 100644 --- a/src/routes/console/project-[project]/storage/bucket-[bucket]/settings/+page.svelte +++ b/src/routes/console/project-[project]/storage/bucket-[bucket]/settings/+page.svelte @@ -36,8 +36,9 @@ arePermsDisabled = true, encryption: boolean = null, antivirus: boolean = null, - maxSize: number; - let byteUnit = writable('KB'); + maxSize: number, + compression: string = null; + let byteUnit = writable('MB'); let sizeInBytes: number = null; const options = [ { label: 'Bytes', value: 'Bytes' }, @@ -45,6 +46,11 @@ { label: 'Megabytes', value: 'MB' }, { label: 'Gigabytes', value: 'GB' } ]; + const compressionOptions = [ + { label: 'None', value: 'none' }, + { label: 'Gzip', value: 'gzip' }, + { label: 'Zstd', value: 'zstd' } + ]; let suggestedExtensions = ['jpg', 'png', 'svg', 'gif', 'html', 'pdf', 'mp4']; let extensions = $bucket.allowedFileExtensions; let isExtensionsDisabled = true; @@ -57,8 +63,10 @@ bucketPermissions ??= $bucket.$permissions; encryption ??= $bucket.encryption; antivirus ??= $bucket.antivirus; - maxSize = $bucket.maximumFileSize / 1024; + maxSize = $bucket.maximumFileSize / 1024 / 1024; + compression ??= $bucket.compression; }); + $: if (bucketPermissions) { if (symmetricDifference(bucketPermissions, $bucket.$permissions).length) { arePermsDisabled = false; @@ -192,6 +200,17 @@ ); } + function updateCompression() { + updateBucket( + { + compression + }, + { + trackEventName: 'submit_bucket_update_size' + } + ); + } + function updateAllowedExtensions() { updateBucket( { @@ -234,8 +253,8 @@ id="toggle" bind:value={enabled} /> -

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

    -

    Last Updated: {toLocaleDateTime($bucket.$updatedAt)}

    +

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

    +

    Last Updated: {toLocaleDateTime($bucket.$updatedAt)}

    @@ -320,7 +339,7 @@
    Update Security Settings -

    +

    Enable or disable security services for the bucket including Ecryption and Antivirus scanning.

    @@ -381,17 +400,40 @@
    +
    + + Update Compression Algorithm +

    + Choose an algorithm for compression. For files larger than 20MB, compression + will be skipped even if it's enabled. +

    + + + + + + + + + +
    + +
    Update Maximum File Size -

    Set the maximum file size allowed in the bucket.

    +

    Set the maximum file size allowed in the bucket.

      Update Allowed File Extensions -

      +

      A maximum of 100 file extensions can be added. Leave blank to allow all file types.

      @@ -453,7 +495,7 @@ Delete Bucket -

      +

      The bucket will be permanently deleted, including all the files within it. This action is irreversible.

      @@ -462,7 +504,7 @@
      {$bucket.name}
      -

      Last Updated: {toLocaleDateTime($bucket.$updatedAt)}

      +

      Last Updated: {toLocaleDateTime($bucket.$updatedAt)}

      diff --git a/src/routes/register/+page.svelte b/src/routes/register/+page.svelte index 9a7bdf65c..cc0b939c0 100644 --- a/src/routes/register/+page.svelte +++ b/src/routes/register/+page.svelte @@ -16,6 +16,11 @@ import FormList from '$lib/elements/forms/formList.svelte'; import { Dependencies } from '$lib/constants'; import { trackEvent } from '$lib/actions/analytics'; + import LoginLight from '$lib/images/login/login-light-mode.svg'; + import LoginDark from '$lib/images/login/login-dark-mode.svg'; + + let imgLight = LoginLight; + let imgDark = LoginDark; let name: string, mail: string, pass: string, disabled: boolean; let terms = false; @@ -42,7 +47,7 @@ Sign up - Appwrite - + Sign up diff --git a/src/routes/register/invite/[slug]/+page.svelte b/src/routes/register/invite/[slug]/+page.svelte new file mode 100644 index 000000000..cf742a44c --- /dev/null +++ b/src/routes/register/invite/[slug]/+page.svelte @@ -0,0 +1,147 @@ + + + + Sign up - Appwrite + + + + {title} + + + + + + + + + By registering, you agree that you have read, understand, and acknowledge our + Privacy Policy + and accept our + General Terms of Use. + + + + + + + + + + diff --git a/src/routes/register/invite/[slug]/mlh-dark.svg b/src/routes/register/invite/[slug]/mlh-dark.svg new file mode 100644 index 000000000..0e5dbcdf8 --- /dev/null +++ b/src/routes/register/invite/[slug]/mlh-dark.svg @@ -0,0 +1,181 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/routes/register/invite/[slug]/mlh-light.svg b/src/routes/register/invite/[slug]/mlh-light.svg new file mode 100644 index 000000000..2ec970a5d --- /dev/null +++ b/src/routes/register/invite/[slug]/mlh-light.svg @@ -0,0 +1,173 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +