mirror of
https://github.com/appwrite/console.git
synced 2026-06-06 19:27:48 +00:00
Merge pull request #254 from appwrite/chore-update-upload-file-box
feat: update upload file box and some CSS
This commit is contained in:
Generated
+4
-4
@@ -9,7 +9,7 @@
|
||||
"version": "0.0.1",
|
||||
"dependencies": {
|
||||
"@analytics/google-analytics": "^1.0.5",
|
||||
"@appwrite.io/pink": "^0.0.3",
|
||||
"@appwrite.io/pink": "^0.0.4",
|
||||
"@aw-labs/appwrite-console": "^13.1.0",
|
||||
"@popperjs/core": "^2.11.6",
|
||||
"@sentry/svelte": "^7.36.0",
|
||||
@@ -146,9 +146,9 @@
|
||||
"integrity": "sha512-1Yw7u/COtxx06BfwlI+kVhsa/upKYzmCNrT4c8QDeCY2KMYlnijkUjtHiPU08HxyTIVB5j6d75O0YWVIHwQS8g=="
|
||||
},
|
||||
"node_modules/@appwrite.io/pink": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@appwrite.io/pink/-/pink-0.0.3.tgz",
|
||||
"integrity": "sha512-hxLMLvtUGkurnKcdwRH36GyeNZelOPSl5qrniwWwGQbpO+S8SakjMNqL1AF/+4JnypfNZUzJNRGTo+VGbrwang==",
|
||||
"version": "0.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@appwrite.io/pink/-/pink-0.0.4.tgz",
|
||||
"integrity": "sha512-pCXxBqSikG5PpBb2y84tTRH6cAMUYbROlQN8LuGoY2J+vTWMT+HQ7+RAAwRWU1Dlle4FgOFFCKmqU95g6X2a6g==",
|
||||
"dependencies": {
|
||||
"@appwrite.io/pink-icons": "*",
|
||||
"normalize.css": "^8.0.1",
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@analytics/google-analytics": "^1.0.5",
|
||||
"@appwrite.io/pink": "^0.0.3",
|
||||
"@appwrite.io/pink": "^0.0.4",
|
||||
"@aw-labs/appwrite-console": "^13.1.0",
|
||||
"@popperjs/core": "^2.11.6",
|
||||
"@sentry/svelte": "^7.36.0",
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
<ul class="drop-tabs">
|
||||
<slot />
|
||||
</ul>
|
||||
@@ -1,9 +0,0 @@
|
||||
<script lang="ts">
|
||||
export let disabled = false;
|
||||
</script>
|
||||
|
||||
<li class="drop-tabs-item">
|
||||
<button class="drop-tabs-button" {disabled} on:click>
|
||||
<span class="text"><slot /></span>
|
||||
</button>
|
||||
</li>
|
||||
@@ -1,16 +0,0 @@
|
||||
<script lang="ts">
|
||||
export let href: string;
|
||||
export let disabled = false;
|
||||
</script>
|
||||
|
||||
<li class="drop-tabs-item">
|
||||
{#if disabled}
|
||||
<button class="drop-tabs-button" disabled>
|
||||
<span class="text"><slot /></span>
|
||||
</button>
|
||||
{:else}
|
||||
<a class="drop-tabs-button" {href}>
|
||||
<span class="text"><slot /></span>
|
||||
</a>
|
||||
{/if}
|
||||
</li>
|
||||
@@ -20,9 +20,8 @@ export { default as DropListItem } from './dropListItem.svelte';
|
||||
export { default as DropListLink } from './dropListLink.svelte';
|
||||
export { default as Collapsible } from './collapsible.svelte';
|
||||
export { default as CollapsibleItem } from './collapsibleItem.svelte';
|
||||
export { default as DropTabs } from './dropTabs.svelte';
|
||||
export { default as DropTabsItem } from './dropTabsItem.svelte';
|
||||
export { default as DropTabsLink } from './dropTabsLink.svelte';
|
||||
export { default as SecondaryTabs } from './secondaryTabs.svelte';
|
||||
export { default as SecondaryTabsItem } from './secondaryTabsItem.svelte';
|
||||
export { default as Avatar } from './avatar.svelte';
|
||||
export { default as AvatarInitials } from './avatarInitials.svelte';
|
||||
export { default as AvatarGroup } from './avatarGroup.svelte';
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
<ul class="secondary-tabs">
|
||||
<slot />
|
||||
</ul>
|
||||
@@ -0,0 +1,22 @@
|
||||
<script lang="ts">
|
||||
export let href: string;
|
||||
export let disabled = false;
|
||||
</script>
|
||||
|
||||
<li class="secondary-tabs-item">
|
||||
{#if href}
|
||||
{#if disabled}
|
||||
<button class="secondary-tabs-button" disabled>
|
||||
<span class="text"><slot /></span>
|
||||
</button>
|
||||
{:else}
|
||||
<a class="secondary-tabs-button" {href}>
|
||||
<span class="text"><slot /></span>
|
||||
</a>
|
||||
{/if}
|
||||
{:else}
|
||||
<button class="secondary-tabs-button" {disabled} on:click>
|
||||
<span class="text"><slot /></span>
|
||||
</button>
|
||||
{/if}
|
||||
</li>
|
||||
@@ -1,21 +1,21 @@
|
||||
<script lang="ts">
|
||||
import { Trim } from '$lib/components';
|
||||
import { Button } from '.';
|
||||
import { humanFileSize } from '$lib/helpers/sizeConvertion';
|
||||
|
||||
export let label: string = null;
|
||||
export let files: FileList;
|
||||
export let list = new DataTransfer();
|
||||
export let allowedFileExtensions: string[] = [];
|
||||
export let maxSize: number = null;
|
||||
|
||||
let input: HTMLInputElement;
|
||||
let hovering = false;
|
||||
|
||||
function dropHandler(ev: DragEvent) {
|
||||
ev.dataTransfer.dropEffect = 'move';
|
||||
hovering = false;
|
||||
if (ev.dataTransfer.items) {
|
||||
// Use DataTransferItemList interface to access the file(s)
|
||||
for (let i = 0; i < ev.dataTransfer.items.length; i++) {
|
||||
// If dropped items aren't files, reject them
|
||||
if (ev.dataTransfer.items[i].kind === 'file') {
|
||||
list.items.clear();
|
||||
list.items.add(ev.dataTransfer.items[i].getAsFile());
|
||||
@@ -28,6 +28,8 @@
|
||||
function dragOverHandler() {
|
||||
hovering = true;
|
||||
}
|
||||
|
||||
$: fileArray = files?.length ? Array.from(files) : [];
|
||||
</script>
|
||||
|
||||
<input
|
||||
@@ -42,42 +44,77 @@
|
||||
<p class="text">{label}</p>
|
||||
{/if}
|
||||
<div
|
||||
class="card is-border-dashed is-no-shadow"
|
||||
class="box is-no-shadow u-padding-24"
|
||||
style="--box-border-radius:var(--border-radius-xsmall); z-index: 1"
|
||||
class:is-border-dashed={!hovering}
|
||||
class:is-hover-with-file={hovering}
|
||||
on:drop|preventDefault={dropHandler}
|
||||
on:dragover|preventDefault={dragOverHandler}
|
||||
on:dragenter|preventDefault
|
||||
on:dragleave|preventDefault={() => (hovering = false)}>
|
||||
<div class="u-flex u-main-center u-cross-center u-gap-32">
|
||||
<div class="avatar is-size-large u-min-width-0">
|
||||
<span class="icon-folder" aria-hidden="true" />
|
||||
<div class="upload-file-box">
|
||||
<div class="upload-file-box-image">
|
||||
<span class="icon-upload" aria-hidden="true" />
|
||||
</div>
|
||||
<div class="u-min-width-0 u-text-center">
|
||||
<h5 class="upload-file-box-title heading-level-7 u-inline">
|
||||
<span class="is-only-desktop">Drag and drop files here to upload</span>
|
||||
<span class="is-not-desktop">Upload a File</span>
|
||||
</h5>
|
||||
{#if allowedFileExtensions?.length}
|
||||
<button
|
||||
class="tooltip u-inline u-margin-inline-start-4"
|
||||
aria-label="variables info">
|
||||
<span class="icon-info" aria-hidden="true" />
|
||||
<span class="tooltip-popup" role="tooltip"
|
||||
>Only {allowedFileExtensions.join(', ')} accepted.</span>
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="u-flex u-main-center u-cross-center u-gap-16 u-flex-vertical-mobile">
|
||||
{#if maxSize}
|
||||
{@const readableMaxSize = humanFileSize(maxSize)}
|
||||
<p class="upload-file-box-info body-text-2 u-normal">
|
||||
Max file size: {readableMaxSize.value + readableMaxSize.unit}
|
||||
</p>
|
||||
{/if}
|
||||
<button
|
||||
class="button is-secondary is-full-width-mobile"
|
||||
type="button"
|
||||
on:click={() => input.click()}>
|
||||
<span class="text">Choose a file</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="u-grid u-gap-16 u-min-width-0">
|
||||
<p>Drag and drop files here</p>
|
||||
<div class="u-flex u-gap-8 u-min-width-0">
|
||||
<Button secondary on:click={() => input.click()}>
|
||||
<span class="icon-upload" aria-hidden="true" />
|
||||
<span class="text">Choose File</span>
|
||||
</Button>
|
||||
|
||||
{#if files?.length}
|
||||
{@const fileName = files.item(0).name.split('.')}
|
||||
<div class="u-flex u-cross-center u-min-width-0">
|
||||
<Trim>{fileName[0]}</Trim>
|
||||
<span class="u-min-width-0 u-flex-shrink-0 u-margin-inline-end-16"
|
||||
>.{fileName[1]}</span>
|
||||
{#if files?.length}
|
||||
<ul class="upload-file-box-list u-min-width-0">
|
||||
{#each fileArray as file}
|
||||
{@const fileName = file.name.split('.')}
|
||||
{@const fileSize = humanFileSize(file.size)}
|
||||
<li class="u-flex u-cross-center u-min-width-0">
|
||||
<span class="icon-document" aria-hidden="true" />
|
||||
<span class="upload-file-box-name u-trim u-min-width-0">
|
||||
<Trim>{fileName[0]}</Trim>
|
||||
</span>
|
||||
<span class="upload-file-box-name u-min-width-0 u-flex-shrink-0">
|
||||
.{fileName[1]}
|
||||
</span>
|
||||
<span
|
||||
class="upload-file-box-size u-margin-inline-start-4 u-margin-inline-end-16">
|
||||
{fileSize.value + fileSize.unit}
|
||||
</span>
|
||||
<button
|
||||
on:click={() => (files = null)}
|
||||
type="button"
|
||||
class="button is-text is-only-icon"
|
||||
style="--button-size:1.5rem;"
|
||||
class="button is-text is-only-icon u-margin-inline-start-auto"
|
||||
aria-label="remove file"
|
||||
title="Remove file">
|
||||
style="--button-size:1.5rem;">
|
||||
<span class="icon-x" aria-hidden="true" />
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -93,7 +93,7 @@
|
||||
<span class="text">Support</span>
|
||||
</a>
|
||||
</nav>
|
||||
<nav class="u-flex u-height-100-percents u-sep-inline-start">
|
||||
<nav class="u-flex u-height-100-percent u-sep-inline-start">
|
||||
{#if $user}
|
||||
<div class="drop-wrapper" class:is-open={showDropdown} bind:this={droplistElement}>
|
||||
<button class="user-profile-button" on:click={() => (showDropdown = !showDropdown)}>
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
<div class="u-margin-block-start-40" />
|
||||
</section>
|
||||
<section class="grid-1-1-col-2 u-flex u-main-center u-cross-center">
|
||||
<div class="container u-flex u-flex-vertical u-cross-center u-height-100-percents">
|
||||
<div class="container u-flex u-flex-vertical u-cross-center u-height-100-percent">
|
||||
<div class="u-margin-block-start-auto" />
|
||||
|
||||
<div class="u-max-width-500 u-width-full-line">
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<script lang="ts">
|
||||
import { Container } from '$lib/layout';
|
||||
import { BarChart, LineChart } from '$lib/charts';
|
||||
import { Card, DropTabs, DropTabsLink, Heading, Tiles } from '$lib/components';
|
||||
import { Card, SecondaryTabs, SecondaryTabsItem, Heading, Tiles } from '$lib/components';
|
||||
import { Colors } from '$lib/charts/config';
|
||||
import type { Models } from '@aw-labs/appwrite-console';
|
||||
import { page } from '$app/stores';
|
||||
@@ -42,19 +42,19 @@
|
||||
<Container>
|
||||
<div class="u-flex u-main-space-between common-section">
|
||||
<Heading tag="h2" size="5">{title}</Heading>
|
||||
<DropTabs>
|
||||
<DropTabsLink href={`${path}/24h`} disabled={$page.params.period === '24h'}>
|
||||
<SecondaryTabs>
|
||||
<SecondaryTabsItem href={`${path}/24h`} disabled={$page.params.period === '24h'}>
|
||||
24h
|
||||
</DropTabsLink>
|
||||
<DropTabsLink
|
||||
</SecondaryTabsItem>
|
||||
<SecondaryTabsItem
|
||||
href={`${path}/30d`}
|
||||
disabled={!$page.params.period || $page.params.period === '30d'}>
|
||||
30d
|
||||
</DropTabsLink>
|
||||
<DropTabsLink href={`${path}/90d`} disabled={$page.params.period === '90d'}>
|
||||
</SecondaryTabsItem>
|
||||
<SecondaryTabsItem href={`${path}/90d`} disabled={$page.params.period === '90d'}>
|
||||
90d
|
||||
</DropTabsLink>
|
||||
</DropTabs>
|
||||
</SecondaryTabsItem>
|
||||
</SecondaryTabs>
|
||||
</div>
|
||||
<Card>
|
||||
{#if count}
|
||||
|
||||
+9
-9
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { Container } from '$lib/layout';
|
||||
import { Card, DropListLink, DropTabs, Heading } from '$lib/components';
|
||||
import { Card, SecondaryTabsItem, SecondaryTabs, Heading } from '$lib/components';
|
||||
import { last } from '$lib/layout/usage.svelte';
|
||||
import { BarChart } from '$lib/charts';
|
||||
import { page } from '$app/stores';
|
||||
@@ -15,23 +15,23 @@
|
||||
<Container>
|
||||
<div class="u-flex u-main-space-between common-section">
|
||||
<Heading tag="h2" size="5">Functions</Heading>
|
||||
<DropTabs>
|
||||
<DropListLink
|
||||
<SecondaryTabs>
|
||||
<SecondaryTabsItem
|
||||
href={`/console/project-${data.project.$id}/functions/function-${data.function.$id}/usage/24h`}
|
||||
disabled={($page.params.period ?? '24h') === '24h'}>
|
||||
24h
|
||||
</DropListLink>
|
||||
<DropListLink
|
||||
</SecondaryTabsItem>
|
||||
<SecondaryTabsItem
|
||||
href={`/console/project-${data.project.$id}/functions/function-${data.function.$id}/usage/30d`}
|
||||
disabled={$page.params.period === '30d'}>
|
||||
30d
|
||||
</DropListLink>
|
||||
<DropListLink
|
||||
</SecondaryTabsItem>
|
||||
<SecondaryTabsItem
|
||||
href={`/console/project-${data.project.$id}/functions/function-${data.function.$id}/usage/90d`}
|
||||
disabled={$page.params.period === '90d'}>
|
||||
90d
|
||||
</DropListLink>
|
||||
</DropTabs>
|
||||
</SecondaryTabsItem>
|
||||
</SecondaryTabs>
|
||||
</div>
|
||||
{#if count}
|
||||
<Card>
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
import { page } from '$app/stores';
|
||||
import { uploader } from '$lib/stores/uploader';
|
||||
import { bucket } from './store';
|
||||
import { calculateSize } from '$lib/helpers/sizeConvertion';
|
||||
import { Permissions } from '$lib/components/permissions';
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import { trackEvent } from '$lib/actions/analytics';
|
||||
@@ -50,8 +49,10 @@
|
||||
<svelte:fragment slot="header">Create File</svelte:fragment>
|
||||
<FormList>
|
||||
<div>
|
||||
<InputFile bind:files allowedFileExtensions={$bucket.allowedFileExtensions} />
|
||||
<p>Max file size: {calculateSize($bucket.maximumFileSize)}</p>
|
||||
<InputFile
|
||||
bind:files
|
||||
allowedFileExtensions={$bucket.allowedFileExtensions}
|
||||
maxSize={$bucket.maximumFileSize} />
|
||||
</div>
|
||||
|
||||
{#if !showCustomId}
|
||||
|
||||
@@ -1,22 +1,28 @@
|
||||
import '@testing-library/jest-dom';
|
||||
import { vi } from 'vitest';
|
||||
import { render, fireEvent } from '@testing-library/svelte';
|
||||
import { DropTabsItem } from '../../../src/lib/components';
|
||||
import { SecondaryTabsItem } from '../../../src/lib/components';
|
||||
|
||||
test('shows button', () => {
|
||||
const { getByRole } = render(DropTabsItem);
|
||||
const { getByRole } = render(SecondaryTabsItem);
|
||||
|
||||
expect(getByRole('button')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('shows link', () => {
|
||||
render(SecondaryTabsItem, { href: 'https://www.appwrite.io' });
|
||||
const href = document.querySelector('a');
|
||||
expect(href).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('shows button - disabled', () => {
|
||||
const { getByRole } = render(DropTabsItem, { disabled: true });
|
||||
const { getByRole } = render(SecondaryTabsItem, { href: null, disabled: true });
|
||||
|
||||
expect(getByRole('button')).toBeDisabled();
|
||||
});
|
||||
|
||||
test('shows button - on:click', async () => {
|
||||
const { getByRole, component } = render(DropTabsItem);
|
||||
const { getByRole, component } = render(SecondaryTabsItem);
|
||||
const button = getByRole('button');
|
||||
|
||||
const callback = vi.fn();
|
||||
|
||||
Reference in New Issue
Block a user