diff --git a/package-lock.json b/package-lock.json index bbb8f3858..65711f67d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,7 @@ "@sentry/svelte": "^7.44.2", "@sentry/tracing": "^7.44.2", "analytics": "^0.8.1", + "dotenv": "^16.0.3", "echarts": "^5.4.1", "logrocket": "^3.0.1", "pretty-bytes": "^6.1.0", @@ -3659,6 +3660,14 @@ "node": ">=12" } }, + "node_modules/dotenv": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", + "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==", + "engines": { + "node": ">=12" + } + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", diff --git a/package.json b/package.json index 052ee234b..a7cc3b720 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "@sentry/svelte": "^7.44.2", "@sentry/tracing": "^7.44.2", "analytics": "^0.8.1", + "dotenv": "^16.0.3", "echarts": "^5.4.1", "logrocket": "^3.0.1", "pretty-bytes": "^6.1.0", diff --git a/src/lib/components/copy.svelte b/src/lib/components/copy.svelte index c6cc8fe7d..33050e82e 100644 --- a/src/lib/components/copy.svelte +++ b/src/lib/components/copy.svelte @@ -33,6 +33,8 @@ setTimeout(() => (content = 'Click to copy'))} diff --git a/src/lib/components/output.svelte b/src/lib/components/output.svelte index e8830076c..ff658d7d5 100644 --- a/src/lib/components/output.svelte +++ b/src/lib/components/output.svelte @@ -2,16 +2,18 @@ import Copy from './copy.svelte'; export let value: string; + export let hideCopyIcon = false; -
+
- -
- -
+ {#if !hideCopyIcon} +
+ +
+ {/if}
diff --git a/src/lib/components/permissions/roles.svelte b/src/lib/components/permissions/roles.svelte index 1f8ebaf03..7f2b32454 100644 --- a/src/lib/components/permissions/roles.svelte +++ b/src/lib/components/permissions/roles.svelte @@ -104,7 +104,7 @@ -
+
import { onMount } from 'svelte'; import { FormItem, Helper, Label } from '.'; + import TextCounter from './textCounter.svelte'; export let label: string; export let optionalText: string | undefined = undefined; @@ -58,14 +59,11 @@ type="text" class="input-text" bind:value + class:u-padding-inline-end-56={typeof maxlength === 'number'} bind:this={element} on:invalid={handleInvalid} /> {#if maxlength} - - {value?.length ?? 0} - - {maxlength} - + {/if}
{#if error} diff --git a/src/lib/elements/forms/inputTextarea.svelte b/src/lib/elements/forms/inputTextarea.svelte index cc049ce8c..2bcf64117 100644 --- a/src/lib/elements/forms/inputTextarea.svelte +++ b/src/lib/elements/forms/inputTextarea.svelte @@ -1,6 +1,7 @@ -
diff --git a/src/lib/elements/forms/textCounter.svelte b/src/lib/elements/forms/textCounter.svelte new file mode 100644 index 000000000..14e707720 --- /dev/null +++ b/src/lib/elements/forms/textCounter.svelte @@ -0,0 +1,28 @@ + + + 0}> + {count} + + {max} + + + diff --git a/src/lib/layout/footer.svelte b/src/lib/layout/footer.svelte index e7ecd1b6e..6ca938a4c 100644 --- a/src/lib/layout/footer.svelte +++ b/src/lib/layout/footer.svelte @@ -11,13 +11,13 @@
diff --git a/src/lib/layout/notifications.svelte b/src/lib/layout/notifications.svelte index 202702799..3200a1280 100644 --- a/src/lib/layout/notifications.svelte +++ b/src/lib/layout/notifications.svelte @@ -1,19 +1,22 @@ {#if $notifications}
    {#each $notifications as notification (notification.id)} - dismissNotification(notification.id)} - buttons={notification?.buttons}> - {notification.message} - +
  • + dismissNotification(notification.id)} + buttons={notification?.buttons}> + {notification.message} + +
  • {/each}
@@ -22,8 +25,15 @@ diff --git a/src/lib/stores/app.ts b/src/lib/stores/app.ts index 4ddd2e08a..66946f3f1 100644 --- a/src/lib/stores/app.ts +++ b/src/lib/stores/app.ts @@ -74,7 +74,7 @@ function createFeedbackStore() { customFields: value ? [{ id: '40655', value }] : undefined }) }); - if (response.status !== 200) { + if (response.status >= 400) { throw new Error('Failed to submit feedback'); } } diff --git a/src/lib/stores/notifications.ts b/src/lib/stores/notifications.ts index 397b578e4..25ba01968 100644 --- a/src/lib/stores/notifications.ts +++ b/src/lib/stores/notifications.ts @@ -33,11 +33,7 @@ export const addNotification = (notification: Omit) => { const n = { ...defaults, ...notification }; notifications.update((all) => { - if (all.length < 3) { - return [n, ...all]; - } else { - return [n, ...all.slice(0, 2)]; - } + return [n, ...all.slice(0, 4)]; }); if (n.timeout) setTimeout(() => dismissNotification(n.id), n.timeout); diff --git a/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/[[page]]/+page.svelte b/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/[[page]]/+page.svelte index 21b646508..7b007be14 100644 --- a/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/[[page]]/+page.svelte +++ b/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/[[page]]/+page.svelte @@ -120,9 +120,9 @@ href={`${base}/console/project-${projectId}/databases/database-${databaseId}/collection-${$collection.$id}/document-${document.$id}`}> - + diff --git a/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/attributes/string.svelte b/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/attributes/string.svelte index 820f76ef8..d80410309 100644 --- a/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/attributes/string.svelte +++ b/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/attributes/string.svelte @@ -37,6 +37,7 @@ - +{#if data.size > 50} + +{:else} + +{/if} Indicate whether this is a required attribute diff --git a/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/indexes/createIndex.svelte b/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/indexes/createIndex.svelte index c1c21e6d1..5528ddee2 100644 --- a/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/indexes/createIndex.svelte +++ b/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/indexes/createIndex.svelte @@ -133,6 +133,7 @@
- +
- {#if data.variables.total} + {@const limit = 10} + {@const sum = data.variables.total} + {#if sum}
Key - Value + Value - {#each data.variables.variables as variable, i} + {#each data.variables.variables.slice(offset, offset + limit) as variable, i} - + {variable.key} @@ -435,19 +447,19 @@ {/each}
- +
+

Total variables: {sum}

+ +
{:else} - (showVariablesModal = !showVariablesModal)} - >Create a variable to get started + (showVariablesModal = !showVariablesModal)}> + Create a variable to get started + {/if} @@ -505,3 +517,6 @@ on:created={handleVariableCreated} on:updated={handleVariableUpdated} /> {/if} +{#if showVariablesUpload} + +{/if} diff --git a/src/routes/console/project-[project]/functions/function-[function]/settings/store.ts b/src/routes/console/project-[project]/functions/function-[function]/settings/store.ts new file mode 100644 index 000000000..3f8cf0cea --- /dev/null +++ b/src/routes/console/project-[project]/functions/function-[function]/settings/store.ts @@ -0,0 +1,8 @@ +import { page } from '$app/stores'; +import { derived } from 'svelte/store'; +import type { Models } from '@aw-labs/appwrite-console'; + +export const variables = derived( + page, + ($page) => $page.data.variables.variables as Models.Variable[] +); diff --git a/src/routes/console/project-[project]/functions/function-[function]/settings/uploadVariables.svelte b/src/routes/console/project-[project]/functions/function-[function]/settings/uploadVariables.svelte index 617f40b46..974932a16 100644 --- a/src/routes/console/project-[project]/functions/function-[function]/settings/uploadVariables.svelte +++ b/src/routes/console/project-[project]/functions/function-[function]/settings/uploadVariables.svelte @@ -6,69 +6,74 @@ import { Button, InputFile } from '$lib/elements/forms'; import { addNotification } from '$lib/stores/notifications'; import { sdk } from '$lib/stores/sdk'; - import { createEventDispatcher } from 'svelte'; + import { parse } from 'dotenv'; + import { variables } from './store'; export let show = false; - const dispatch = createEventDispatcher(); - const functionId = $page.params.function; - let files: FileList; - const handleSubmit = async () => { - if (files?.length) { - const variables = await parseFile(files[0]); - for (const variable of variables) { - try { - await sdk.forProject.functions.createVariable( - functionId, - variable.key, - variable.value - ); - invalidate(Dependencies.VARIABLES); - addNotification({ - type: 'success', - message: 'Variable uploaded' - }); - } catch (error) { - addNotification({ - type: 'error', - message: error.message - }); + let files: FileList; + let error: string; + + async function handleSubmit() { + try { + if (!files?.length) { + throw new Error('No file selected'); + } + + const uploaded = parse(await files[0].text()); + + if (!Object.keys(uploaded).length) { + throw new Error('No variables found'); + } + + const entries = Object.entries(uploaded); + + for (const [key, value] of entries) { + if (value.length > 8192) { + throw new Error(`Variable ${key} is longer than 8192 allowed characters`); } } - dispatch('uploaded', variables); - } else { - addNotification({ - type: 'error', - message: 'No file uploaded' - }); - } - }; - async function parseFile(file: File) { - if (file) { - let variables = []; - let text = await file.text(); - text.split('\n').forEach((line) => { - const [key, value] = line.split('='); - variables.push({ key, value }); + await Promise.all( + entries + .filter(([, value]) => !!value) + .map(([key, value]) => { + const found = $variables.find((variable) => variable.key === key); + return found + ? sdk.forProject.functions.updateVariable( + functionId, + found.$id, + key, + value + ) + : sdk.forProject.functions.createVariable(functionId, key, value); + }) + ); + + invalidate(Dependencies.VARIABLES); + addNotification({ + type: 'success', + message: 'Variables uploaded' }); - return variables; + show = false; + } catch (e) { + error = e.message; } } - + Upload Variables

Upload multiple variables via a .env file that will be passed to your function at runtime.

- + - +