mirror of
https://github.com/appwrite/console.git
synced 2026-06-06 19:27:48 +00:00
Merge pull request #313 from appwrite/refactor/create-file-wizard
Refactor: change create file from modal to wizard
This commit is contained in:
@@ -20,7 +20,7 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<header class="form-header">
|
||||
<header class="form-header" class:hide-divider={!$$slots.subtitle}>
|
||||
<Heading tag="h1" size="6">
|
||||
<slot name="title" />
|
||||
</Heading>
|
||||
@@ -32,3 +32,10 @@
|
||||
</header>
|
||||
|
||||
<slot />
|
||||
|
||||
<style>
|
||||
.hide-divider {
|
||||
padding-block-end: 0;
|
||||
border-block-end: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
+10
-7
@@ -23,11 +23,14 @@ val client = Client(context)
|
||||
value={project}>Project ID</Id
|
||||
>.
|
||||
</p>
|
||||
<Code
|
||||
label="Android SDK"
|
||||
labelIcon="android"
|
||||
language="kotlin"
|
||||
{code}
|
||||
withCopy
|
||||
withLineNumbers />
|
||||
<div class="u-margin-block-start-16">
|
||||
<Code
|
||||
label="Android SDK"
|
||||
labelIcon="android"
|
||||
language="kotlin"
|
||||
{code}
|
||||
withCopy
|
||||
withLineNumbers
|
||||
noMargin />
|
||||
</div>
|
||||
</WizardStep>
|
||||
|
||||
@@ -19,5 +19,7 @@
|
||||
<p class="common-section">
|
||||
You can also install the SDK using the Dart package manager from your terminal.
|
||||
</p>
|
||||
<Code label="Bash" language="sh" code={example2} withCopy />
|
||||
<div class="u-margin-block-start-16">
|
||||
<Code label="Bash" language="sh" code={example2} withCopy noMargin />
|
||||
</div>
|
||||
</WizardStep>
|
||||
|
||||
+10
-1
@@ -25,7 +25,16 @@ client
|
||||
Initialize your SDK by pointing the client to your Appwrite project using your <Id
|
||||
value={project}>Project ID</Id>
|
||||
</p>
|
||||
<Code label="Flutter SDK" labelIcon="flutter" language="dart" {code} withCopy withLineNumbers />
|
||||
<div class="u-margin-block-start-16">
|
||||
<Code
|
||||
label="Flutter SDK"
|
||||
labelIcon="flutter"
|
||||
language="dart"
|
||||
{code}
|
||||
withCopy
|
||||
withLineNumbers
|
||||
noMargin />
|
||||
</div>
|
||||
<p class="common-section">
|
||||
Before sending any API calls to your new Appwrite project, make sure your device or emulator
|
||||
has network access to your Appwrite project's hostname or IP address.
|
||||
|
||||
@@ -21,5 +21,14 @@ client
|
||||
value={project}>Project ID</Id
|
||||
>.
|
||||
</p>
|
||||
<Code label="Web SDK" labelIcon="code" language="js" {code} withCopy withLineNumbers />
|
||||
<div class="u-margin-block-start-16">
|
||||
<Code
|
||||
label="Web SDK"
|
||||
labelIcon="code"
|
||||
language="js"
|
||||
{code}
|
||||
withCopy
|
||||
withLineNumbers
|
||||
noMargin />
|
||||
</div>
|
||||
</WizardStep>
|
||||
|
||||
@@ -1,54 +1,51 @@
|
||||
<script lang="ts" context="module">
|
||||
let showCreate = writable(false);
|
||||
|
||||
export const showCreateFile = () => {
|
||||
showCreate.set(true);
|
||||
wizard.start(Create);
|
||||
};
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import { invalidate } from '$app/navigation';
|
||||
import { base } from '$app/paths';
|
||||
import { page } from '$app/stores';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { Pill } from '$lib/elements';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
|
||||
import {
|
||||
Empty,
|
||||
EmptySearch,
|
||||
Avatar,
|
||||
DropList,
|
||||
DropListItem,
|
||||
DropListLink,
|
||||
SearchQuery,
|
||||
PaginationWithLimit
|
||||
Empty,
|
||||
EmptySearch,
|
||||
PaginationWithLimit,
|
||||
SearchQuery
|
||||
} from '$lib/components';
|
||||
import Create from './create.svelte';
|
||||
import Delete from './deleteFile.svelte';
|
||||
import { Dependencies } from '$lib/constants';
|
||||
import { Pill } from '$lib/elements';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import {
|
||||
Table,
|
||||
TableHeader,
|
||||
TableBody,
|
||||
TableRowLink,
|
||||
TableRow,
|
||||
TableCell,
|
||||
TableCellHead,
|
||||
TableCellText,
|
||||
TableCell
|
||||
TableHeader,
|
||||
TableRow,
|
||||
TableRowLink
|
||||
} from '$lib/elements/table';
|
||||
import { toLocaleDate } from '$lib/helpers/date';
|
||||
import { bytesToSize, calculateSize } from '$lib/helpers/sizeConvertion';
|
||||
import { Container, ContainerHeader } from '$lib/layout';
|
||||
import { base } from '$app/paths';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
import { uploader } from '$lib/stores/uploader';
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import type { PageData } from './$types';
|
||||
import { invalidate } from '$app/navigation';
|
||||
import { Dependencies } from '$lib/constants';
|
||||
import { Submit, trackEvent, trackError } from '$lib/actions/analytics';
|
||||
import { uploader } from '$lib/stores/uploader';
|
||||
import { wizard } from '$lib/stores/wizard';
|
||||
import { tooltip } from '$lib/actions/tooltip';
|
||||
import { readOnly, showUsageRatesModal } from '$lib/stores/billing';
|
||||
import { writable } from 'svelte/store';
|
||||
import { sdk } from '$lib/stores/sdk.js';
|
||||
import Create from './create-file/create.svelte';
|
||||
import DeleteFile from './deleteFile.svelte';
|
||||
|
||||
export let data: PageData;
|
||||
export let data;
|
||||
|
||||
let showDelete = false;
|
||||
let showDropdown = [];
|
||||
@@ -60,11 +57,6 @@
|
||||
const getPreview = (fileId: string) =>
|
||||
sdk.forProject.storage.getFilePreview(bucketId, fileId, 32, 32).toString() + '&mode=admin';
|
||||
|
||||
async function fileCreated() {
|
||||
$showCreate = false;
|
||||
await invalidate(Dependencies.FILES);
|
||||
}
|
||||
|
||||
async function fileDeleted(event: CustomEvent<Models.File>) {
|
||||
showDelete = false;
|
||||
uploader.removeFile(event.detail);
|
||||
@@ -102,7 +94,7 @@
|
||||
disabled: !isButtonDisabled
|
||||
}}>
|
||||
<Button
|
||||
on:click={() => ($showCreate = true)}
|
||||
on:click={() => wizard.start(Create)}
|
||||
event="create_file"
|
||||
disabled={isButtonDisabled}>
|
||||
<span class="icon-plus" aria-hidden="true" />
|
||||
@@ -264,11 +256,10 @@
|
||||
single
|
||||
href="https://appwrite.io/docs/products/storage/upload-download"
|
||||
target="file"
|
||||
on:click={() => ($showCreate = true)} />
|
||||
on:click={() => wizard.start(Create)} />
|
||||
{/if}
|
||||
</Container>
|
||||
|
||||
<Create bind:showCreate={$showCreate} on:created={fileCreated} />
|
||||
{#if selectedFile}
|
||||
<Delete file={selectedFile} bind:showDelete on:deleted={fileDeleted} />
|
||||
<DeleteFile file={selectedFile} bind:showDelete on:deleted={fileDeleted} />
|
||||
{/if}
|
||||
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
<script lang="ts">
|
||||
import { invalidate } from '$app/navigation';
|
||||
import { page } from '$app/stores';
|
||||
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
|
||||
import { Dependencies } from '$lib/constants';
|
||||
import type { WizardStepsType } from '$lib/layout/wizard.svelte';
|
||||
import Wizard from '$lib/layout/wizard.svelte';
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import { uploader } from '$lib/stores/uploader';
|
||||
import { wizard } from '$lib/stores/wizard';
|
||||
import { ID } from '@appwrite.io/console';
|
||||
import Step1 from './step1.svelte';
|
||||
import Step2 from './step2.svelte';
|
||||
import { createFile } from './store';
|
||||
|
||||
const bucketId = $page.params.bucket;
|
||||
|
||||
const stepComponents: WizardStepsType = new Map();
|
||||
|
||||
stepComponents.set(1, {
|
||||
component: Step1,
|
||||
label: 'Create'
|
||||
});
|
||||
|
||||
stepComponents.set(2, {
|
||||
component: Step2,
|
||||
label: 'Permissions'
|
||||
});
|
||||
|
||||
async function create() {
|
||||
try {
|
||||
await uploader.uploadFile(
|
||||
bucketId,
|
||||
$createFile.id ?? ID.unique(),
|
||||
$createFile.files[0],
|
||||
$createFile.permissions
|
||||
);
|
||||
|
||||
createFile.reset();
|
||||
wizard.hide();
|
||||
invalidate(Dependencies.FILES);
|
||||
|
||||
addNotification({
|
||||
type: 'success',
|
||||
message: `File has been uploaded`
|
||||
});
|
||||
trackEvent(Submit.FileCreate, {
|
||||
customId: !!$createFile.id
|
||||
});
|
||||
} catch (e) {
|
||||
addNotification({
|
||||
type: 'error',
|
||||
message: e.message
|
||||
});
|
||||
trackError(e, Submit.FileCreate);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<Wizard title="Create file" steps={stepComponents} on:exit={createFile.reset} on:finish={create} />
|
||||
@@ -0,0 +1,44 @@
|
||||
<script lang="ts">
|
||||
import { CustomId } from '$lib/components';
|
||||
import { Pill } from '$lib/elements';
|
||||
import { FormList, InputFile } from '$lib/elements/forms';
|
||||
import WizardStep from '$lib/layout/wizardStep.svelte';
|
||||
import { bucket } from '../store';
|
||||
import { createFile } from './store';
|
||||
|
||||
let showCustomId = false;
|
||||
</script>
|
||||
|
||||
<WizardStep>
|
||||
<svelte:fragment slot="title">Create file</svelte:fragment>
|
||||
<svelte:fragment slot="subtitle">Upload a file to add it to your bucket.</svelte:fragment>
|
||||
<FormList>
|
||||
<div class="u-width-full-line u-overflow-hidden">
|
||||
<InputFile
|
||||
required
|
||||
bind:files={$createFile.files}
|
||||
allowedFileExtensions={$bucket.allowedFileExtensions}
|
||||
maxSize={$bucket.maximumFileSize} />
|
||||
</div>
|
||||
|
||||
{#if !showCustomId}
|
||||
<div>
|
||||
<Pill button on:click={() => (showCustomId = !showCustomId)}>
|
||||
<span class="icon-pencil" aria-hidden="true" /><span class="text">
|
||||
File ID
|
||||
</span>
|
||||
</Pill>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="custom-id-wrapper">
|
||||
<CustomId bind:show={showCustomId} name="File" bind:id={$createFile.id} />
|
||||
</div>
|
||||
{/if}
|
||||
</FormList>
|
||||
</WizardStep>
|
||||
|
||||
<style lang="scss">
|
||||
.custom-id-wrapper :global(.is-inner-modal) {
|
||||
inline-size: auto;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,39 @@
|
||||
<script lang="ts">
|
||||
import Alert from '$lib/components/alert.svelte';
|
||||
import Permissions from '$lib/components/permissions/permissions.svelte';
|
||||
import WizardStep from '$lib/layout/wizardStep.svelte';
|
||||
import { bucket } from '../store';
|
||||
import { createFile } from './store';
|
||||
</script>
|
||||
|
||||
<WizardStep>
|
||||
<svelte:fragment slot="title">Update Permissions</svelte:fragment>
|
||||
<svelte:fragment slot="subtitle">
|
||||
Choose who can access your buckets and files. For more information, check out the
|
||||
<a
|
||||
href="https://appwrite.io/docs/advanced/platform/permissions"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="link">
|
||||
Permissions Guide
|
||||
</a>.</svelte:fragment>
|
||||
|
||||
{#if $bucket.fileSecurity}
|
||||
<div class="common-section">
|
||||
<Alert type="info">
|
||||
<svelte:fragment slot="title">File security enabled</svelte:fragment>
|
||||
Users will be able to access this file if they have been granted
|
||||
<b>either File or Bucket permissions</b>.
|
||||
</Alert>
|
||||
</div>
|
||||
<div class="common-section">
|
||||
<Permissions bind:permissions={$createFile.permissions} />
|
||||
</div>
|
||||
{:else}
|
||||
<Alert type="info">
|
||||
<svelte:fragment slot="title">File security disabled</svelte:fragment>
|
||||
If you want to assign file permissions, navigate to Bucket settings and enable file security.
|
||||
Otherwise, only Bucket permissions will be used.
|
||||
</Alert>
|
||||
{/if}
|
||||
</WizardStep>
|
||||
@@ -0,0 +1,24 @@
|
||||
import { writable } from 'svelte/store';
|
||||
|
||||
type CreateFile = {
|
||||
files: FileList | null;
|
||||
id: string | null;
|
||||
permissions: string[];
|
||||
};
|
||||
|
||||
const initialState: CreateFile = {
|
||||
files: null,
|
||||
id: null,
|
||||
permissions: []
|
||||
};
|
||||
|
||||
export const createFile = (function initialize() {
|
||||
const store = writable<CreateFile>({ ...initialState });
|
||||
|
||||
return {
|
||||
...store,
|
||||
reset() {
|
||||
store.set({ ...initialState });
|
||||
}
|
||||
};
|
||||
})();
|
||||
Reference in New Issue
Block a user