diff --git a/src/lib/components/filePicker.svelte b/src/lib/components/filePicker.svelte index bcb681cdd6..34a984fc78 100644 --- a/src/lib/components/filePicker.svelte +++ b/src/lib/components/filePicker.svelte @@ -17,6 +17,7 @@ Card, Divider, Empty, + Icon, Layout, Modal, Selector, @@ -24,23 +25,28 @@ Table, ToggleButton, Tooltip, - Typography + Typography, + Upload } from '@appwrite.io/pink-svelte'; import Form from '$lib/elements/forms/form.svelte'; import { isSmallViewport } from '$lib/stores/viewport'; - import { IconViewGrid, IconViewList } from '@appwrite.io/pink-icons-svelte'; + import { IconInfo, IconPlus, IconViewGrid, IconViewList } from '@appwrite.io/pink-icons-svelte'; import { showCreateBucket } from '$routes/(console)/project-[region]-[project]/storage/+page.svelte'; + import { preferences } from '$lib/stores/preferences'; export let show: boolean; export let mimeTypeQuery: string = 'image/'; export let allowedExtension: string = '*'; export let selectedBucket: string = null; export let selectedFile: string = null; - export let onSelect: (e: Models.File) => void; + export let onSelect: (e: Models.File, localFile: boolean) => void; export let gridImageDimensions: { imageHeight?: number; imageWidth?: number } = { imageHeight: 148 }; - + export let showLocalFileBucket: boolean = false; + export let localFileBucketTitle = 'Upload local file'; + let localFileBucketSelected = true; + let localFile: FileList = null; let search = writable(''); let searchEnabled = false; let fileSelector: HTMLInputElement; @@ -48,11 +54,22 @@ let view: 'grid' | 'list' = 'list'; onMount(() => { + const lastSelectedBucket = preferences.getKey('lastSelectedBucket', null); + localFileBucketSelected = !lastSelectedBucket; + selectedBucket = currentBucket?.$id; }); - function onSubmit() { - onSelect(currentFile); + async function onSubmit() { + // localfile needs to be uploaded first + if (localFileBucketSelected) { + await uploadFile(); + } + + // Save preference based on selection + preferences.setKey('lastSelectedBucket', localFileBucketSelected ? null : selectedBucket); + + onSelect(currentFile, localFileBucketSelected); closeModal(); } @@ -68,12 +85,19 @@ async function uploadFile() { try { uploading = true; - const file = await sdk - .forProject(page.params.region, page.params.project) - .storage.createFile(selectedBucket, ID.unique(), fileSelector.files[0], [ - Permission.read(Role.any()) - ]); - search.set($search === null ? '' : null); + let file = null; + if (localFileBucketSelected) { + file = await sdk + .forConsoleIn(page.params.region) + .storage.createFile('default', ID.unique(), localFile[0]); + } else { + file = await sdk + .forProject(page.params.region, page.params.project) + .storage.createFile(selectedBucket, ID.unique(), fileSelector.files[0], [ + Permission.read(Role.any()) + ]); + search.set($search === null ? '' : null); + } selectFile(file); } catch (e) { console.error(e); @@ -82,7 +106,17 @@ } } + function selectLocalBucket() { + localFileBucketSelected = true; + selectBucket(null); + } + function selectBucket(bucket: Models.Bucket | null) { + if (bucket) { + localFileBucketSelected = false; + localFile = null; + } + search.set(''); currentBucket = bucket; selectedBucket = bucket?.$id ?? null; @@ -91,8 +125,10 @@ function selectFile(file: Models.File) { currentFile = file; - selectedBucket = currentFile.bucketId; - selectedFile = currentFile.$id; + if (!localFileBucketSelected) { + selectedBucket = currentFile.bucketId; + selectedFile = currentFile.$id; + } } function resetFile() { @@ -123,10 +159,24 @@ const response = await sdk .forProject(page.params.region, page.params.project) .storage.listBuckets(); - const bucket = response.buckets[0] ?? null; + + const lastSelectedBucket = preferences.getKey('lastSelectedBucket', null); + let preferredBucket = null; + + if (lastSelectedBucket) { + preferredBucket = response.buckets.find((bucket) => bucket.$id === lastSelectedBucket); + } + const bucket = preferredBucket ?? response.buckets[0] ?? null; + if (bucket) { currentBucket = bucket; selectedBucket = bucket.$id; + if (preferredBucket) { + localFileBucketSelected = false; + } + } else { + // in case when the last bucket selected was deleted + localFileBucketSelected = true; } return response; @@ -176,206 +226,268 @@
- -
- - {#if $isSmallViewport} - - {/if} - - {#await buckets then response} - {#if response?.total} - {#if currentBucket} - - {#if !$isSmallViewport} - {#key currentBucket?.$id} - - {currentBucket?.name} - - {currentBucket?.$id} - + {#if localFileBucketSelected} +
+ + {localFileBucketTitle} + + + + + + Drag and drop files here or click to upload + + + + - {/key} - {/if} - - - - {#if !$isSmallViewport} - - {/if} + {allowedExtension} files are allowed + + Max file size: 10MB + + + {#if localFile} + { + return { + ...f, + name: f.name, + size: f.size, + extension: f.type, + removable: true + }; + })} + on:remove={() => (localFile = null)} /> + {/if} + +
+ {:else} +
+ + {#if $isSmallViewport} + + {/if} - {#if files} - {#await files} - - - Loading files... + {#await buckets then response} + {#if response?.total} + {#if currentBucket} + + {#if !$isSmallViewport} + {#key currentBucket?.$id} + + {currentBucket?.name} + + {currentBucket?.$id} + + + {/key} + {/if} + + + + {#if !$isSmallViewport} + + {/if} - {:then response} - {#if response?.files?.length} - {#if view === 'grid'} - {#if $isSmallViewport} - - {#each response?.files as file} - selectFile(file)} /> - {/each} - - {:else} - - {#each response?.files as file} -
+ + + {#if files} + {#await files} + + + Loading files... + + {:then response} + {#if response?.files?.length} + {#if view === 'grid'} + {#if $isSmallViewport} + + {#each response?.files as file} selectFile(file)} /> -
- {/each} -
- {/if} - {/if} - {#if view === 'list'} - - - - Filename - - - ID - - - Type - - - Size - - - Created - - - {#each response?.files as file (file.$id)} - selectFile(file)}> - -
- + {:else} + + {#each response?.files as file} +
+ - -
- {file.name} -
- - - - {truncatedFilename( - file - )} - - - - {file.name} - - + src={getPreview( + currentBucket.$id, + file.$id, + 360 + )} + on:click={() => + selectFile(file)} />
- - - {file.$id} - - - {file.mimeType} - - - {calculateSize(file.sizeOriginal)} - - - - - - {/each} - + {/each} +
+ {/if} + {/if} + {#if view === 'list'} + + + + Filename + + + ID + + + Type + + + Size + + + Created + + + {#each response?.files as file (file.$id)} + selectFile(file)}> + +
+ + +
+ {file.name} +
+ + + + {truncatedFilename( + file + )} + + + + {file.name} + + +
+
+ + {file.$id} + + + {file.mimeType} + + + {calculateSize( + file.sizeOriginal + )} + + + + +
+ {/each} +
+ {/if} + {:else if $search} + + + + {:else} + + + + + + + + {/if} - {:else if $search} - - - - {:else} - - - - - - - - - {/if} - {/await} + {/await} + {/if} {/if} {/if} - {:else} - - - - - - - - - - {/if} - {/await} - -
- + {/await} +
+
+ {/if} +
- diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/+page.svelte b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/+page.svelte index 377287069e..7439aa0972 100644 --- a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/+page.svelte @@ -62,7 +62,7 @@ $: hasColumns = !!$table.columns.length; $: hasValidColumns = $table?.columns?.some((col) => col.status === 'available'); - async function onSelect(file: Models.File) { + async function onSelect(file: Models.File, localFile = false) { $isCsvImportInProgress = true; try { @@ -71,7 +71,8 @@ .migrations.createCsvMigration({ bucketId: file.bucketId, fileId: file.$id, - resourceId: `${page.params.database}:${page.params.table}` + resourceId: `${page.params.database}:${page.params.table}`, + internalFile: localFile }); addNotification({ @@ -227,6 +228,8 @@