fix: stuff

This commit is contained in:
Torsten Dittmann
2025-02-26 22:17:30 +04:00
parent 485fb3d1fc
commit 360874bdcb
22 changed files with 302 additions and 422 deletions
+2 -2
View File
@@ -21,9 +21,9 @@
"dependencies": {
"@appwrite.io/console": "https://pkg.pr.new/appwrite/appwrite/@appwrite.io/console@08ec153",
"@appwrite.io/pink-icons": "0.25.0",
"@appwrite.io/pink-icons-svelte": "https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@f0532207 ",
"@appwrite.io/pink-icons-svelte": "https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@dd94b87a ",
"@appwrite.io/pink-legacy": "^1.0.2",
"@appwrite.io/pink-svelte": "https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@f0532207 ",
"@appwrite.io/pink-svelte": "https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@dd94b87a ",
"@popperjs/core": "^2.11.8",
"@sentry/sveltekit": "^8.38.0",
"@stripe/stripe-js": "^3.5.0",
+5 -5
View File
@@ -18,8 +18,8 @@ importers:
specifier: 0.25.0
version: 0.25.0
'@appwrite.io/pink-icons-svelte':
specifier: 'https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@f0532207 '
version: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@f0532207(svelte@4.2.19)
specifier: 'https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@dd94b87a '
version: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@dd94b87a(svelte@4.2.19)
'@appwrite.io/pink-legacy':
specifier: ^1.0.2
version: 1.0.2
@@ -218,8 +218,8 @@ packages:
resolution: {tarball: https://pkg.pr.new/appwrite/appwrite/@appwrite.io/console@08ec153}
version: 1.2.1
'@appwrite.io/pink-icons-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@f0532207':
resolution: {tarball: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@f0532207}
'@appwrite.io/pink-icons-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@dd94b87a':
resolution: {tarball: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@dd94b87a}
version: 1.0.0-next.7
peerDependencies:
svelte: ^4.0.0
@@ -3917,7 +3917,7 @@ snapshots:
'@appwrite.io/console@https://pkg.pr.new/appwrite/appwrite/@appwrite.io/console@08ec153': {}
'@appwrite.io/pink-icons-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@f0532207(svelte@4.2.19)':
'@appwrite.io/pink-icons-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@dd94b87a(svelte@4.2.19)':
dependencies:
svelte: 4.2.19
+2 -3
View File
@@ -1,6 +1,5 @@
<script>
import { Heading } from '$lib/components';
import { Card } from '@appwrite.io/pink-svelte';
import { Card, Typography } from '@appwrite.io/pink-svelte';
export let href;
</script>
@@ -8,7 +7,7 @@
<div class="grid-item-1">
<div class="grid-item-1-start-start">
<div class="eyebrow-heading-3"><slot name="eyebrow" /></div>
<Heading tag="h2" size="7"><slot name="title" /></Heading>
<Typography.Title size="s"><slot name="title" /></Typography.Title>
<div class="u-padding-block-start-4"><slot name="subtitle" /></div>
</div>
+1 -3
View File
@@ -45,9 +45,7 @@
<Form isModal {onSubmit} bind:this={formComponent}>
<Modal {title} bind:open={show} {hideFooter} {dismissible}>
<svelte:fragment slot="description">
<slot name="description" />
</svelte:fragment>
<slot slot="description" name="description" />
{#if error}
<div bind:this={alert}>
<Alert
+4 -1
View File
@@ -13,6 +13,9 @@
</Button.Anchor>
</span>
{/if}
<Typography.Title truncate color="--color-fgcolor-neutral-primary" size={$isSmallViewport ? 'm' : 'l'}>
<Typography.Title
truncate
color="--color-fgcolor-neutral-primary"
size={$isSmallViewport ? 'm' : 'l'}>
<slot />
</Typography.Title>
+2 -2
View File
@@ -61,10 +61,10 @@
import { Container } from '$lib/layout';
import { BarChart } from '$lib/charts';
import { formatNumberWithCommas } from '$lib/helpers/numbers';
import { Card, SecondaryTabs, SecondaryTabsItem, Heading } from '$lib/components';
import { Card } from '$lib/components';
import { ProjectUsageRange, type Models } from '@appwrite.io/console';
import { page } from '$app/stores';
import { Layout, Tag, Typography } from '@appwrite.io/pink-svelte';
import { Layout, Typography } from '@appwrite.io/pink-svelte';
import { goto } from '$app/navigation';
import { InputSelect } from '$lib/elements/forms';
+29 -23
View File
@@ -6,6 +6,7 @@
import { page } from '$app/stores';
import { type Models } from '@appwrite.io/console';
import { formatNumberWithCommas } from '$lib/helpers/numbers';
import { Layout, Typography } from '@appwrite.io/pink-svelte';
export let title: string;
export let total: number[];
@@ -17,35 +18,40 @@
</script>
<Container overlapCover={overlapContainerCover}>
<div class="u-flex u-main-space-between common-section">
{#if showHeader}
{#if showHeader}
<div class="u-flex u-main-space-between common-section">
<Heading tag="h2" size="5">{title}</Heading>
{/if}
{#if path}
<SecondaryTabs>
<SecondaryTabsItem href={`${path}/24h`} disabled={$page.params.period === '24h'}>
24h
</SecondaryTabsItem>
<SecondaryTabsItem
href={`${path}/30d`}
disabled={!$page.params.period || $page.params.period === '30d'}>
30d
</SecondaryTabsItem>
<SecondaryTabsItem href={`${path}/90d`} disabled={$page.params.period === '90d'}>
90d
</SecondaryTabsItem>
</SecondaryTabs>
{/if}
</div>
{#if path}
<SecondaryTabs>
<SecondaryTabsItem
href={`${path}/24h`}
disabled={$page.params.period === '24h'}>
24h
</SecondaryTabsItem>
<SecondaryTabsItem
href={`${path}/30d`}
disabled={!$page.params.period || $page.params.period === '30d'}>
30d
</SecondaryTabsItem>
<SecondaryTabsItem
href={`${path}/90d`}
disabled={$page.params.period === '90d'}>
90d
</SecondaryTabsItem>
</SecondaryTabs>
{/if}
</div>
{/if}
<Card>
{#if count}
{@const totalCount = total.reduce((a, b) => a + b, 0)}
<Heading tag="h6" size="6">{formatNumberWithCommas(totalCount)}</Heading>
<p>Total {title.toLocaleLowerCase()}</p>
<div class="u-margin-block-start-16" />
<Layout.Stack gap="xs">
<Typography.Title>{formatNumberWithCommas(totalCount)}</Typography.Title>
<Typography.Text>Total {title.toLocaleLowerCase()}</Typography.Text>
</Layout.Stack>
<div class="multiple-chart-container u-flex-vertical u-gap-16">
<BarChart
formatted={$page.params.period === '24h' ? 'hours' : 'days'}
@@ -157,65 +157,6 @@
{/if}
{/if}
{/each}
<!-- <Table.Cell>
<Layout.Stack direction="row" alignItems="center" gap="s">
{#if user.email || user.phone}
{#if user.name}
<AvatarInitials size="xs" name={user.name} />
<span class="text u-trim">{user.name}</span>
{:else}
<div class="avatar is-size-small">
<span class="icon-minus-sm" aria-hidden="true" />
</div>
{/if}
{:else}
<div class="avatar is-size-small">
<span class="icon-anonymous" aria-hidden="true" />
</div>
<span class="text u-trim">{user.name}</span>
{/if}
</Layout.Stack>
</Table.Cell>
<Table.Cell>
{user.email && user.phone
? [user.email, user.phone].join(',')
: user.email || user.phone}
</Table.Cell>
<Table.Cell>
{#if user.status}
{@const success = user.emailVerification || user.phoneVerification}
<Badge
size="xs"
variant="secondary"
type={success ? 'success' : undefined}
content={user.emailVerification && user.phoneVerification
? 'verified'
: user.emailVerification
? 'verified email'
: user.phoneVerification
? 'verified phone'
: 'unverified'} />
{:else}
<Badge size="xs" variant="secondary" type="error" content="blocked" />
{/if}
</Table.Cell>
<Table.Cell>
<Copy value={user.$id} event="user">
<Tag size="xs" variant="code">
<Icon size="s" icon={IconDuplicate} />
{user.$id}
</Tag>
</Copy>
</Table.Cell>
<Table.Cell>
{user.labels.join(', ')}
</Table.Cell>
<Table.Cell>
{toLocaleDateTime(user.registration)}
</Table.Cell>
<Table.Cell>
{user.accessedAt ? toLocaleDate(user.accessedAt) : 'never'}
</Table.Cell> -->
</Table.Link>
{/each}
</Table.Root>
@@ -60,7 +60,7 @@
}
</script>
<Modal title="Create user" {error} size="big" bind:show={showCreate} onSubmit={create}>
<Modal title="Create user" {error} bind:show={showCreate} onSubmit={create}>
<FormList>
<InputText
id="name"
@@ -58,7 +58,12 @@
Roles are used to manage access permissions. You can create any role you want.
</Alert.Inline>
<InputTags id="tags" label="Roles" placeholder="Add roles" bind:tags={roles} helper="Roles are used to manage access permissions. You can create any role you want." />
<InputTags
id="tags"
label="Roles"
placeholder="Add roles"
bind:tags={roles}
helper="Roles are used to manage access permissions. You can create any role you want." />
</FormList>
<svelte:fragment slot="footer">
<Button text on:click={() => (showCreate = false)}>Cancel</Button>
@@ -16,6 +16,7 @@
import { canWriteDatabases } from '$lib/stores/roles';
import { Icon, Layout } from '@appwrite.io/pink-svelte';
import { IconPlus } from '@appwrite.io/pink-icons-svelte';
import EmptySearch from '$lib/components/emptySearch.svelte';
export let data: PageData;
@@ -78,6 +79,11 @@
limit={data.limit}
offset={data.offset}
total={data.databases.total} />
{:else if data.search}
<EmptySearch target="databases" hidePagination>
<Button href={`${base}/project-${$page.params.project}/databases`} size="s" secondary
>Clear Search</Button>
</EmptySearch>
{:else}
<Empty
single
@@ -1,8 +1,7 @@
<script lang="ts">
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
import { Alert, CustomId, Modal } from '$lib/components';
import { Pill } from '$lib/elements';
import { Button, FormList, InputText } from '$lib/elements/forms';
import { Button, InputText } from '$lib/elements/forms';
import { addNotification } from '$lib/stores/notifications';
import { sdk } from '$lib/stores/sdk';
import { ID } from '@appwrite.io/console';
@@ -13,6 +12,8 @@
import { upgradeURL } from '$lib/stores/billing';
import CreatePolicy from './database-[database]/backups/createPolicy.svelte';
import { cronExpression, type UserBackupPolicy } from '$lib/helpers/backups';
import { Icon, Tag } from '@appwrite.io/pink-svelte';
import { IconPencil } from '@appwrite.io/pink-icons-svelte';
export let showCreate = false;
let totalPolicies: UserBackupPolicy[] = [];
@@ -103,54 +104,52 @@
}
</script>
<Modal title="Create database" size="big" onSubmit={create} bind:show={showCreate}>
<FormList gap={8}>
<InputText
id="name"
label="Name"
placeholder="Enter database name"
bind:value={name}
autofocus
required />
<Modal title="Create database" onSubmit={create} bind:show={showCreate}>
<InputText
id="name"
label="Name"
placeholder="Enter database name"
bind:value={name}
autofocus
required />
{#if !showCustomId}
<div>
<Pill button on:click={() => (showCustomId = !showCustomId)}
><span class="icon-pencil" aria-hidden="true" /><span class="text">
Database ID
</span></Pill>
</div>
{:else}
<CustomId bind:show={showCustomId} name="Database" bind:id autofocus={false} />
{/if}
{#if !showCustomId}
<div>
<Tag
size="s"
on:click={() => {
showCustomId = true;
}}><Icon icon={IconPencil} /> Database ID</Tag>
</div>
{/if}
<CustomId bind:show={showCustomId} name="Database" bind:id autofocus={false} />
{#if isCloud}
<div class="u-flex-vertical u-gap-24 u-padding-block-start-24">
{#if $organization?.billingPlan === BillingPlan.FREE}
{#if showPlanUpgradeAlert}
<Alert
type="warning"
dismissible
on:dismiss={() => (showPlanUpgradeAlert = false)}>
<svelte:fragment slot="title">
This database won't be backed up
</svelte:fragment>
Upgrade your plan to ensure your data stays safe and backed up.
<svelte:fragment slot="buttons">
<Button href={$upgradeURL} text>Upgrade plan</Button>
</svelte:fragment>
</Alert>
{/if}
{:else}
<CreatePolicy
bind:totalPolicies
bind:isShowing={showCreate}
title="Backup policies"
subtitle="Protect your data and ensure quick recovery by adding backup policies." />
{#if isCloud}
<div class="u-flex-vertical u-gap-24 u-padding-block-start-24">
{#if $organization?.billingPlan === BillingPlan.FREE}
{#if showPlanUpgradeAlert}
<Alert
type="warning"
dismissible
on:dismiss={() => (showPlanUpgradeAlert = false)}>
<svelte:fragment slot="title">
This database won't be backed up
</svelte:fragment>
Upgrade your plan to ensure your data stays safe and backed up.
<svelte:fragment slot="buttons">
<Button href={$upgradeURL} text>Upgrade plan</Button>
</svelte:fragment>
</Alert>
{/if}
</div>
{/if}
</FormList>
{:else}
<CreatePolicy
bind:totalPolicies
bind:isShowing={showCreate}
title="Backup policies"
subtitle="Protect your data and ensure quick recovery by adding backup policies." />
{/if}
</div>
{/if}
<svelte:fragment slot="footer">
<Button secondary on:click={() => (showCreate = false)}>Cancel</Button>
<Button submit>Create</Button>
@@ -12,8 +12,8 @@
import EmptyLightTablet from '$lib/images/backups/upgrade/backups-tablet-light.png';
import { upgradeURL } from '$lib/stores/billing';
import { Card } from '$lib/components';
import { isCloud } from '$lib/system';
import { Card, Layout, Typography } from '@appwrite.io/pink-svelte';
const title = isCloud
? 'Backups are available on paid plans'
@@ -25,7 +25,7 @@
</script>
<div>
<Card style="--card-padding: 1rem; --card-padding-mobile: 1rem">
<Card.Base padding="s">
<div class="u-flex u-gap-24 u-flex-vertical-mobile u-cross-center">
<div
style:--p-file-preview-border-color="transparent"
@@ -78,35 +78,32 @@
{/if}
</div>
</div>
<div class="u-flex u-flex-vertical-mobile u-gap-mobile-6">
<div class="u-flex-vertical u-gap-8">
<h3 class="body-text-2 u-bold">
{title}
</h3>
<Layout.Stack direction="row" alignItems="center" wrap="wrap">
<Layout.Stack gap="xs">
<Typography.Text variant="m-600">{title}</Typography.Text>
<span class="upgrade-description">
{message} Schedule automatic or manual backups to protect your data and ensure
quick recovery.
</span>
</div>
</Layout.Stack>
<span class="is-only-mobile-button">
<Button
external={!isCloud}
href={isCloud ? $upgradeURL : 'https://cloud.appwrite.io/register'}>
{isCloud ? 'Upgrade plan' : 'Sign up'}
</Button>
</span>
</Layout.Stack>
<div class="is-not-mobile">
<Button
external={!isCloud}
class="is-not-mobile"
href={isCloud ? $upgradeURL : 'https://cloud.appwrite.io/register'}>
{isCloud ? 'Upgrade plan' : 'Sign up'}
</Button>
<Button
fullWidthMobile
external={!isCloud}
class="is-only-mobile-button u-margin-block-start-32"
href={isCloud ? $upgradeURL : 'https://cloud.appwrite.io/register'}>
{isCloud ? 'Upgrade plan' : 'Sign up'}
</Button>
</div>
</div>
</Card>
</Card.Base>
</div>
<style>
@@ -8,6 +8,8 @@
import { addNotification } from '$lib/stores/notifications';
import { sdk } from '$lib/stores/sdk';
import { ID } from '@appwrite.io/console';
import { IconPencil } from '@appwrite.io/pink-icons-svelte';
import { Icon, Tag } from '@appwrite.io/pink-svelte';
import { createEventDispatcher } from 'svelte';
export let showCreate = false;
@@ -64,19 +66,14 @@
{#if !showCustomId}
<div>
<Pill button on:click={() => (showCustomId = !showCustomId)}
><span class="icon-pencil" aria-hidden="true" /><span class="text">
Collection ID
</span></Pill>
<Tag
size="s"
on:click={() => {
showCustomId = true;
}}><Icon icon={IconPencil} /> Collection ID</Tag>
</div>
{:else}
<CustomId
autofocus
bind:show={showCustomId}
name="Collection"
bind:id
fullWidth={true} />
{/if}
<CustomId autofocus bind:show={showCustomId} name="Collection" bind:id fullWidth={true} />
</FormList>
<svelte:fragment slot="footer">
<Button secondary on:click={() => (showCreate = false)}>Cancel</Button>
@@ -8,17 +8,9 @@
import { addNotification } from '$lib/stores/notifications';
import { sdk } from '$lib/stores/sdk';
import { database } from './store';
import {
TableBody,
TableCell,
TableCellHead,
TableHeader,
TableRow,
TableScroll
} from '$lib/elements/table';
import { toLocaleDate } from '$lib/helpers/date';
import { type Models, Query } from '@appwrite.io/console';
import { Table } from '@appwrite.io/pink-svelte';
const databaseId = $page.params.database;
@@ -28,9 +20,6 @@
let error = null;
let isLoadingDocumentsCount = false;
/* enable overflow-x */
const columnWidth = 135;
$: collectionItems = [];
let collections: Models.CollectionList = null;
@@ -100,99 +89,84 @@
}
</script>
<div class="max-height-dialog">
<Modal title="Delete database" bind:show={showDelete} onSubmit={handleDelete}>
{#await listCollections()}
<div class="u-flex u-main-center">
<div class="loader" />
</div>
{:then}
{#if error}
<p class="text" data-private>
Are you sure you want to delete <b>{$database.name}</b>?
</p>
{:else if collectionItems.length > 0}
<p class="text" data-private>
The following collections and all data associated with <b>{$database.name}</b>,
will be permanently deleted.
</p>
<div class="u-flex-vertical u-gap-16">
<TableScroll dense noMargin class="table">
<TableHeader>
<TableCellHead width={columnWidth}>Collection</TableCellHead>
<!-- small spacer placeholder -->
<TableCellHead width={columnWidth / 4} />
<TableCellHead width={columnWidth}>Last Updated</TableCellHead>
</TableHeader>
<TableBody>
{#each collectionItems as collection}
<TableRow>
<TableCell title="Collection">{collection.name}</TableCell>
<TableCell />
<TableCell title="Last Updated"
>{toLocaleDate(collection.updatedAt)}</TableCell>
</TableRow>
{/each}
</TableBody>
</TableScroll>
{#if collectionItems.length < collections.total}
<div class="u-flex u-gap-16 u-cross-center">
<button class="u-underline" on:click={listCollections} type="button">
Show more
</button>
{#if isLoadingDocumentsCount}
<div class="loader is-small" />
{/if}
</div>
{:else if collectionItems.length > 25}
<button
class="u-underline"
on:click={() => {
collectionItems = collectionItems.slice(0, 3);
}}
type="button">
Show less
</button>
{/if}
</div>
{:else}
<p class="text" data-private>
Are you sure you want to delete <b>{$database.name}</b>?
</p>
{/if}
{/await}
{#if !isLoadingDocumentsCount}
<p class="text" data-private>
<b>
Once deleted, this database and its backups cannot be restored. This action is
irreversible.
</b>
</p>
<FormList>
<div class="input-check-box-friction">
<InputCheckbox
required
id="delete_policy"
bind:checked={confirmedDeletion}
label="I understand and confirm" />
</div>
</FormList>
<Modal title="Delete database" bind:show={showDelete} onSubmit={handleDelete}>
<p class="text" slot="description">
{#if collectionItems.length > 0}
The following collections and all data associated with <b>{$database.name}</b>, will be
permanently deleted.
{:else}
Are you sure you want to delete <b>{$database.name}</b>?
{/if}
</p>
{#await listCollections()}
<div class="u-flex u-main-center">
<div class="loader" />
</div>
{:then}
{#if error}
<p class="text">
Are you sure you want to delete <b>{$database.name}</b>?
</p>
{:else if collectionItems.length > 0}
<div class="u-flex-vertical u-gap-16">
<Table.Root>
<svelte:fragment slot="header">
<Table.Header.Cell>Collection</Table.Header.Cell>
<Table.Header.Cell>Last Updated</Table.Header.Cell>
</svelte:fragment>
{#each collectionItems as collection}
<Table.Row>
<Table.Cell>{collection.name}</Table.Cell>
<Table.Cell>{toLocaleDate(collection.updatedAt)}</Table.Cell>
</Table.Row>
{/each}
</Table.Root>
<svelte:fragment slot="footer">
<Button text on:click={() => (showDelete = false)}>Cancel</Button>
<Button secondary submit disabled={!confirmedDeletion}>Delete</Button>
</svelte:fragment>
</Modal>
</div>
{#if collectionItems.length < collections.total}
<div class="u-flex u-gap-16 u-cross-center">
<button class="u-underline" on:click={listCollections} type="button">
Show more
</button>
<style>
:global(.max-height-dialog dialog) {
max-height: 650px;
}
</style>
{#if isLoadingDocumentsCount}
<div class="loader is-small" />
{/if}
</div>
{:else if collectionItems.length > 25}
<button
class="u-underline"
on:click={() => {
collectionItems = collectionItems.slice(0, 3);
}}
type="button">
Show less
</button>
{/if}
</div>
{/if}
{/await}
{#if !isLoadingDocumentsCount}
<p class="text" data-private>
<b>
Once deleted, this database and its backups cannot be restored. This action is
irreversible.
</b>
</p>
<FormList>
<div class="input-check-box-friction">
<InputCheckbox
required
id="delete_policy"
bind:checked={confirmedDeletion}
label="I understand and confirm" />
</div>
</FormList>
{/if}
<svelte:fragment slot="footer">
<Button text on:click={() => (showDelete = false)}>Cancel</Button>
<Button danger submit disabled={!confirmedDeletion}>Delete</Button>
</svelte:fragment>
</Modal>
@@ -55,19 +55,15 @@
{#if $database}
<Container>
<Card>
<div class="common-section grid-1-2">
<div class="grid-1-2-col-1">
<div class="grid-1-2-col-1 u-flex u-cross-center u-gap-16">
<Heading tag="h6" size="7">{$database.name}</Heading>
</div>
</div>
<CardGrid>
<svelte:fragment slot="title">{$database.name}</svelte:fragment>
<svelte:fragment slot="aside">
<div class="grid-1-2-col-2">
<p>Created: {toLocaleDateTime($database.$createdAt)}</p>
<p>Last updated: {toLocaleDateTime($database.$updatedAt)}</p>
</div>
</div>
</Card>
</svelte:fragment>
</CardGrid>
<Form onSubmit={updateName}>
<CardGrid>
@@ -7,21 +7,11 @@
import FloatingActionBar from '$lib/components/floatingActionBar.svelte';
import { Dependencies } from '$lib/constants';
import { Button } from '$lib/elements/forms';
import {
TableBody,
TableCell,
TableCellCheck,
TableCellHead,
TableCellHeadCheck,
TableCellText,
TableHeader,
TableRowLink,
TableScroll
} from '$lib/elements/table';
import { toLocaleDateTime } from '$lib/helpers/date';
import { addNotification } from '$lib/stores/notifications';
import { canWriteCollections } from '$lib/stores/roles';
import { sdk } from '$lib/stores/sdk';
import { Badge, Selector, Table } from '@appwrite.io/pink-svelte';
import type { PageData } from './$types';
import { columns } from './store';
@@ -60,69 +50,63 @@
}
</script>
<TableScroll>
<TableHeader>
<Table.Root>
<svelte:fragment slot="header">
{#if $canWriteCollections}
<TableCellHeadCheck
bind:selected
pageItemsIds={data.collections.collections.map((c) => c.$id)} />
<Table.Header.Selector width="20px" />
{/if}
{#each $columns as column}
{#if column.show}
<TableCellHead width={column.width}>{column.title}</TableCellHead>
<Table.Header.Cell width={column.width + 'px'}>{column.title}</Table.Header.Cell>
{/if}
{/each}
</TableHeader>
<TableBody>
{#each data.collections.collections as collection (collection.$id)}
<TableRowLink
href={`${base}/project-${projectId}/databases/database-${databaseId}/collection-${collection.$id}`}>
{#if $canWriteCollections}
<TableCellCheck bind:selectedIds={selected} id={collection.$id} />
{/if}
{#each $columns as column}
{#if column.show}
{#if column.id === '$id'}
{#key $columns}
<TableCell title={column.title} width={column.width}>
<Id value={collection.$id}>{collection.$id}</Id>
</TableCell>
{/key}
{:else if column.id === 'name'}
<TableCellText title={column.title} width={column.width}>
{collection.name}
</TableCellText>
{:else}
<TableCellText title={column.title} width={column.width}>
{toLocaleDateTime(collection[column.id])}
</TableCellText>
{/if}
</svelte:fragment>
{#each data.collections.collections as collection (collection.$id)}
<Table.Link
href={`${base}/project-${projectId}/databases/database-${databaseId}/collection-${collection.$id}`}>
{#if $canWriteCollections}
<Table.Cell>
<Selector.Checkbox size="s" />
</Table.Cell>
{/if}
{#each $columns as column}
{#if column.show}
{#if column.id === '$id'}
{#key $columns}
<Table.Cell>
<Id value={collection.$id}>{collection.$id}</Id>
</Table.Cell>
{/key}
{:else if column.id === 'name'}
<Table.Cell>
{collection.name}
</Table.Cell>
{:else}
<Table.Cell>
{toLocaleDateTime(collection[column.id])}
</Table.Cell>
{/if}
{/each}
</TableRowLink>
{/each}
</TableBody>
</TableScroll>
{/if}
{/each}
</Table.Link>
{/each}
</Table.Root>
<FloatingActionBar show={selected.length > 0}>
<div class="u-flex u-cross-center u-main-space-between actions">
<div class="u-flex u-cross-center u-gap-8">
<span class="indicator body-text-2 u-bold">{selected.length}</span>
<p>
<span class="is-only-desktop">
{selected.length > 1 ? 'collections' : 'collection'}
</span>
selected
</p>
</div>
<div class="u-flex u-cross-center u-gap-8">
<Button text on:click={() => (selected = [])}>Cancel</Button>
<Button secondary on:click={() => (showDelete = true)}>
<p>Delete</p>
</Button>
</div>
</div>
<svelte:fragment slot="start">
<Badge content={selected.length.toString()} />
<span>
<span class="is-only-desktop">
{selected.length > 1 ? 'collections' : 'collection'}
</span>
selected
</span>
</svelte:fragment>
<svelte:fragment slot="end">
<Button text on:click={() => (selected = [])}>Cancel</Button>
<Button secondary on:click={() => (showDelete = true)}>Delete</Button>
</svelte:fragment>
</FloatingActionBar>
<Modal
@@ -139,16 +123,3 @@
<Button secondary submit disabled={deleting}>Delete</Button>
</svelte:fragment>
</Modal>
<style lang="scss">
.actions {
.indicator {
border-radius: 0.25rem;
background: hsl(var(--color-information-100));
color: hsl(var(--color-neutral-0));
padding: 0rem 0.375rem;
display: inline-block;
}
}
</style>
@@ -16,25 +16,23 @@
$: writesTotal = data.databaseWritesTotal;
</script>
<div class="u-flex u-flex-vertical u-gap-16">
<Usage
title="Usage"
path={`${base}/project-${$page.params.project}/databases/database-${$page.params.database}/usage`}
{total}
{count}
countMetadata={{
legend: 'Collections',
title: 'Total collections'
}} />
<Usage
title="Usage"
path={`${base}/project-${$page.params.project}/databases/database-${$page.params.database}/usage`}
{total}
{count}
countMetadata={{
legend: 'Collections',
title: 'Total collections'
}} />
<UsageMultiple
title="Reads and writes"
showHeader={false}
overlapContainerCover
total={[readsTotal, writesTotal]}
count={[reads, writes]}
legendData={[
{ name: 'Reads', value: readsTotal },
{ name: 'Writes', value: writesTotal }
]} />
</div>
<UsageMultiple
title="Reads and writes"
showHeader={false}
overlapContainerCover
total={[readsTotal, writesTotal]}
count={[reads, writes]}
legendData={[
{ name: 'Reads', value: readsTotal },
{ name: 'Writes', value: writesTotal }
]} />
@@ -2,19 +2,9 @@
import { base } from '$app/paths';
import { page } from '$app/stores';
import { Id } from '$lib/components';
import {
TableBody,
TableCell,
TableCellHead,
TableCellText,
TableHeader,
TableRowLink,
TableScroll
} from '$lib/elements/table';
import { toLocaleDateTime } from '$lib/helpers/date';
import type { PageData } from './$types';
import { columns } from './store';
import Cell from '$lib/elements/table/cell.svelte';
import { Tooltip, Table } from '@appwrite.io/pink-svelte';
export let data: PageData;
@@ -15,25 +15,23 @@
$: writesTotal = data.databasesWritesTotal;
</script>
<div class="u-flex u-flex-vertical u-gap-16">
<Usage
title="Usage"
path={`${base}/project-${$page.params.project}/databases/usage`}
{total}
{count}
countMetadata={{
legend: 'Databases',
title: 'Total databases'
}} />
<Usage
title="Usage"
path={`${base}/project-${$page.params.project}/databases/usage`}
{total}
{count}
countMetadata={{
legend: 'Databases',
title: 'Total databases'
}} />
<UsageMultiple
title="Reads and writes"
showHeader={false}
overlapContainerCover
total={[readsTotal, writesTotal]}
count={[reads, writes]}
legendData={[
{ name: 'Reads', value: readsTotal },
{ name: 'Writes', value: writesTotal }
]} />
</div>
<UsageMultiple
title="Reads and writes"
showHeader={false}
overlapContainerCover
total={[readsTotal, writesTotal]}
count={[reads, writes]}
legendData={[
{ name: 'Reads', value: readsTotal },
{ name: 'Writes', value: writesTotal }
]} />
@@ -7,7 +7,7 @@
import { IconPlus, IconX } from '@appwrite.io/pink-icons-svelte';
let showCreate = false;
export let events: string[];
let eventSet = new Set<string>();
+2
View File
@@ -5,6 +5,7 @@ body {
}
[data-loading='true'] .page-loader {
pointer-events: initial;
visibility: visible;
opacity: 1;
}
@@ -21,6 +22,7 @@ body {
}
.page-loader {
pointer-events: none;
visibility: hidden;
opacity: 0;
z-index: 100000;