mirror of
https://github.com/appwrite/console.git
synced 2026-06-06 19:27:48 +00:00
fix: migrate tables
This commit is contained in:
+2
-2
@@ -21,9 +21,9 @@
|
||||
"dependencies": {
|
||||
"@appwrite.io/console": "https://pkg.pr.new/appwrite/appwrite/@appwrite.io/console@74f9464",
|
||||
"@appwrite.io/pink-icons": "0.25.0",
|
||||
"@appwrite.io/pink-icons-svelte": "https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@bcb8ad2b",
|
||||
"@appwrite.io/pink-icons-svelte": "https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@64948b6 ",
|
||||
"@appwrite.io/pink-legacy": "^1.0.3",
|
||||
"@appwrite.io/pink-svelte": "https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@5a02879",
|
||||
"@appwrite.io/pink-svelte": "https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@64948b6 ",
|
||||
"@popperjs/core": "^2.11.8",
|
||||
"@sentry/sveltekit": "^8.38.0",
|
||||
"@stripe/stripe-js": "^3.5.0",
|
||||
|
||||
Generated
+14
-14
@@ -15,14 +15,14 @@ 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@bcb8ad2b
|
||||
version: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@bcb8ad2b(svelte@4.2.19)
|
||||
specifier: 'https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@64948b6 '
|
||||
version: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@64948b6(svelte@4.2.19)
|
||||
'@appwrite.io/pink-legacy':
|
||||
specifier: ^1.0.3
|
||||
version: 1.0.3
|
||||
'@appwrite.io/pink-svelte':
|
||||
specifier: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@5a02879
|
||||
version: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@5a02879(react-dom@18.3.1(react@18.3.1))(svelte@4.2.19)
|
||||
specifier: 'https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@64948b6 '
|
||||
version: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@64948b6(react-dom@18.3.1(react@18.3.1))(svelte@4.2.19)
|
||||
'@popperjs/core':
|
||||
specifier: ^2.11.8
|
||||
version: 2.11.8
|
||||
@@ -215,14 +215,14 @@ packages:
|
||||
resolution: {tarball: https://pkg.pr.new/appwrite/appwrite/@appwrite.io/console@74f9464}
|
||||
version: 1.2.1
|
||||
|
||||
'@appwrite.io/pink-icons-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@5a02879249b98cec27dcc3cfa27bd8b20a50b47a':
|
||||
resolution: {tarball: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@5a02879249b98cec27dcc3cfa27bd8b20a50b47a}
|
||||
'@appwrite.io/pink-icons-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@64948b6':
|
||||
resolution: {tarball: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@64948b6}
|
||||
version: 1.0.0-next.7
|
||||
peerDependencies:
|
||||
svelte: ^4.0.0
|
||||
|
||||
'@appwrite.io/pink-icons-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@bcb8ad2b':
|
||||
resolution: {tarball: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@bcb8ad2b}
|
||||
'@appwrite.io/pink-icons-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@64948b6b72fb39c9bac60b63a603942291765189':
|
||||
resolution: {tarball: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@64948b6b72fb39c9bac60b63a603942291765189}
|
||||
version: 1.0.0-next.7
|
||||
peerDependencies:
|
||||
svelte: ^4.0.0
|
||||
@@ -236,8 +236,8 @@ packages:
|
||||
'@appwrite.io/pink-legacy@1.0.3':
|
||||
resolution: {integrity: sha512-GGde5fmPhs+s6/3aFeMPc/kKADG/gTFkYQSy6oBN8pK0y0XNCLrZZgBv+EBbdhwdtqVEWXa0X85Mv9w7jcIlwQ==}
|
||||
|
||||
'@appwrite.io/pink-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@5a02879':
|
||||
resolution: {tarball: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@5a02879}
|
||||
'@appwrite.io/pink-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@64948b6':
|
||||
resolution: {tarball: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@64948b6}
|
||||
version: 1.0.0-next.85
|
||||
peerDependencies:
|
||||
react-dom: ^18.0.0
|
||||
@@ -4099,11 +4099,11 @@ snapshots:
|
||||
|
||||
'@appwrite.io/console@https://pkg.pr.new/appwrite/appwrite/@appwrite.io/console@74f9464': {}
|
||||
|
||||
'@appwrite.io/pink-icons-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@5a02879249b98cec27dcc3cfa27bd8b20a50b47a(svelte@4.2.19)':
|
||||
'@appwrite.io/pink-icons-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@64948b6(svelte@4.2.19)':
|
||||
dependencies:
|
||||
svelte: 4.2.19
|
||||
|
||||
'@appwrite.io/pink-icons-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@bcb8ad2b(svelte@4.2.19)':
|
||||
'@appwrite.io/pink-icons-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@64948b6b72fb39c9bac60b63a603942291765189(svelte@4.2.19)':
|
||||
dependencies:
|
||||
svelte: 4.2.19
|
||||
|
||||
@@ -4116,9 +4116,9 @@ snapshots:
|
||||
'@appwrite.io/pink-icons': 1.0.0
|
||||
the-new-css-reset: 1.11.3
|
||||
|
||||
'@appwrite.io/pink-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@5a02879(react-dom@18.3.1(react@18.3.1))(svelte@4.2.19)':
|
||||
'@appwrite.io/pink-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@64948b6(react-dom@18.3.1(react@18.3.1))(svelte@4.2.19)':
|
||||
dependencies:
|
||||
'@appwrite.io/pink-icons-svelte': https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@5a02879249b98cec27dcc3cfa27bd8b20a50b47a(svelte@4.2.19)
|
||||
'@appwrite.io/pink-icons-svelte': https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@64948b6b72fb39c9bac60b63a603942291765189(svelte@4.2.19)
|
||||
'@floating-ui/dom': 1.6.13
|
||||
'@melt-ui/pp': 0.3.2(@melt-ui/svelte@0.86.3(svelte@4.2.19))(svelte@4.2.19)
|
||||
'@melt-ui/svelte': 0.86.3(svelte@4.2.19)
|
||||
|
||||
@@ -60,11 +60,11 @@
|
||||
</svelte:fragment>
|
||||
</Alert.Inline>
|
||||
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Resource</Table.Header.Cell>
|
||||
<Table.Header.Cell>Free limit</Table.Header.Cell>
|
||||
<Table.Header.Cell>
|
||||
<Table.Root columns={3} let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell {root}>Resource</Table.Header.Cell>
|
||||
<Table.Header.Cell {root}>Free limit</Table.Header.Cell>
|
||||
<Table.Header.Cell {root}>
|
||||
Excess usage <Tooltip
|
||||
><Icon icon={IconInfo} />
|
||||
<span slot="tooltip">Metrics are estimates updated every 24 hours</span>
|
||||
@@ -72,37 +72,37 @@
|
||||
</Table.Header.Cell>
|
||||
</svelte:fragment>
|
||||
{#if excess?.members}
|
||||
<Table.Row>
|
||||
<Table.Cell>Organization members</Table.Cell>
|
||||
<Table.Cell>{plan.members} members</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell {root}>Organization members</Table.Cell>
|
||||
<Table.Cell {root}>{plan.members} members</Table.Cell>
|
||||
<Table.Cell {root}>
|
||||
<p class="u-color-text-danger u-flex u-cross-center u-gap-4">
|
||||
<span class="icon-arrow-up" />
|
||||
{excess?.members} members
|
||||
</p>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/if}
|
||||
{#if excess?.storage}
|
||||
<Table.Row>
|
||||
<Table.Cell>Storage</Table.Cell>
|
||||
<Table.Cell>{plan.storage} GB</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell {root}>Storage</Table.Cell>
|
||||
<Table.Cell {root}>{plan.storage} GB</Table.Cell>
|
||||
<Table.Cell {root}>
|
||||
<p class="u-color-text-danger">
|
||||
<span class="icon-arrow-up" />
|
||||
{humanFileSize(excess?.storage).value}
|
||||
{humanFileSize(excess?.storage).unit}
|
||||
</p>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/if}
|
||||
{#if excess?.executions}
|
||||
<Table.Row>
|
||||
<Table.Cell>Function executions</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell {root}>Function executions</Table.Cell>
|
||||
<Table.Cell {root}>
|
||||
{abbreviateNumber(plan.executions)} executions
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell {root}>
|
||||
<p class="u-color-text-danger">
|
||||
<span class="icon-arrow-up" />
|
||||
<span
|
||||
@@ -113,15 +113,15 @@
|
||||
</span>
|
||||
</p>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/if}
|
||||
{#if excess?.users}
|
||||
<Table.Row>
|
||||
<Table.Cell>Users</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell {root}>Users</Table.Cell>
|
||||
<Table.Cell {root}>
|
||||
{abbreviateNumber(plan.users)} users
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="usage" {root}>
|
||||
<p class="u-color-text-danger">
|
||||
<span class="icon-arrow-up" />
|
||||
<span title={excess?.users ? excess.users.toString() : 'users'}>
|
||||
@@ -129,7 +129,7 @@
|
||||
</span>
|
||||
</p>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/if}
|
||||
</Table.Root>
|
||||
{/if}
|
||||
|
||||
@@ -62,42 +62,40 @@
|
||||
following rates. Next billing period: {toLocaleDate(nextDate)}.
|
||||
</Typography.Text>
|
||||
{/if}
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Resource</Table.Header.Cell>
|
||||
<Table.Header.Cell>Limit</Table.Header.Cell>
|
||||
{#if !isFree}
|
||||
<Table.Header.Cell>Rate</Table.Header.Cell>
|
||||
{/if}
|
||||
<Table.Root
|
||||
columns={[{ id: 'resource' }, { id: 'limit' }, { id: 'rate', hide: isFree }]}
|
||||
let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell column="resource" {root}>Resource</Table.Header.Cell>
|
||||
<Table.Header.Cell column="limit" {root}>Limit</Table.Header.Cell>
|
||||
<Table.Header.Cell column="rate" {root}>Rate</Table.Header.Cell>
|
||||
</svelte:fragment>
|
||||
{#each planData as usage}
|
||||
{#if usage['id'] === 'members'}
|
||||
<Table.Row>
|
||||
<Table.Cell>{usage.resource}</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell column="resource" {root}>{usage.resource}</Table.Cell>
|
||||
<Table.Cell column="limit" {root}>
|
||||
{plan[usage.id] || 'Unlimited'}
|
||||
</Table.Cell>
|
||||
{#if !isFree}
|
||||
<Table.Cell>
|
||||
{formatCurrency(plan.addons?.member?.price)}/{usage?.unit}
|
||||
</Table.Cell>
|
||||
{/if}
|
||||
</Table.Row>
|
||||
<Table.Cell column="rate" {root}>
|
||||
{formatCurrency(plan.addons?.member?.price)}/{usage?.unit}
|
||||
</Table.Cell>
|
||||
</Table.Row.Base>
|
||||
{:else}
|
||||
{@const addon = plan.addons[usage.id]}
|
||||
<Table.Row>
|
||||
<Table.Cell>{usage.resource}</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell column="resource" {root}>{usage.resource}</Table.Cell>
|
||||
<Table.Cell column="limit" {root}>
|
||||
{abbreviateNumber(plan[usage.id])}{usage?.unit}
|
||||
</Table.Cell>
|
||||
{#if !isFree}
|
||||
<Table.Cell>
|
||||
<Table.Cell column="rate" {root}>
|
||||
{formatCurrency(addon?.price)}/{['MB', 'GB', 'TB'].includes(addon?.unit)
|
||||
? addon?.value
|
||||
: abbreviateNumber(addon?.value, 0)}{usage?.unit}
|
||||
</Table.Cell>
|
||||
{/if}
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/if}
|
||||
{/each}
|
||||
</Table.Root>
|
||||
|
||||
@@ -2,12 +2,14 @@
|
||||
import type { PaymentMethodData } from '$lib/sdk/billing';
|
||||
import { Badge, Layout, Link, Popover, Table } from '@appwrite.io/pink-svelte';
|
||||
import CreditCardBrandImage from './creditCardBrandImage.svelte';
|
||||
import type { RootProp } from '@appwrite.io/pink-svelte/dist/table';
|
||||
|
||||
export let root: RootProp;
|
||||
export let paymentMethod: PaymentMethodData;
|
||||
export let isBackup: boolean = false;
|
||||
</script>
|
||||
|
||||
<Table.Cell>
|
||||
<Table.Cell column="cc" {root}>
|
||||
<Layout.Stack direction="row" alignItems="center" gap="s">
|
||||
<CreditCardBrandImage brand={paymentMethod?.brand} />
|
||||
<span>ending in {paymentMethod?.last4}</span>
|
||||
@@ -16,9 +18,10 @@
|
||||
{/if}
|
||||
</Layout.Stack>
|
||||
</Table.Cell>
|
||||
<Table.Cell>{paymentMethod?.name}</Table.Cell>
|
||||
<Table.Cell>{paymentMethod?.expiryMonth}/{paymentMethod?.expiryYear}</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="name" {root}>{paymentMethod?.name}</Table.Cell>
|
||||
<Table.Cell column="expiry" {root}
|
||||
>{paymentMethod?.expiryMonth}/{paymentMethod?.expiryYear}</Table.Cell>
|
||||
<Table.Cell column="status" {root}>
|
||||
{#if paymentMethod?.lastError || paymentMethod?.expired}
|
||||
<Popover let:toggle>
|
||||
<Layout.Stack gap="xs" direction="row">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { Id, Trim } from '.';
|
||||
import { Id } from '.';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { ID, Query, Permission, Role } from '@appwrite.io/console';
|
||||
@@ -9,7 +9,6 @@
|
||||
import InputSearch from '$lib/elements/forms/inputSearch.svelte';
|
||||
import { writable } from 'svelte/store';
|
||||
import { onMount } from 'svelte';
|
||||
import { clickOnEnter } from '$lib/helpers/a11y';
|
||||
import { base } from '$app/paths';
|
||||
import { page } from '$app/stores';
|
||||
import {
|
||||
@@ -256,25 +255,37 @@
|
||||
</Layout.Grid>
|
||||
{/if}
|
||||
{#if view === 'list'}
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Filename</Table.Header.Cell>
|
||||
<Table.Header.Cell width="140px">
|
||||
<Table.Root
|
||||
let:root
|
||||
columns={[
|
||||
{ id: 'filename', width: { min: 140 } },
|
||||
{ id: 'id', width: { min: 100 } },
|
||||
{ id: 'type', width: { min: 100 } },
|
||||
{ id: 'size', width: { min: 100 } },
|
||||
{ id: 'created', width: { min: 120 } }
|
||||
]}>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell column="filename" {root}>
|
||||
Filename
|
||||
</Table.Header.Cell>
|
||||
<Table.Header.Cell column="id" {root}>
|
||||
ID
|
||||
</Table.Header.Cell>
|
||||
<Table.Header.Cell width="100px">
|
||||
<Table.Header.Cell column="type" {root}>
|
||||
Type
|
||||
</Table.Header.Cell>
|
||||
<Table.Header.Cell width="100px">
|
||||
<Table.Header.Cell column="size" {root}>
|
||||
Size
|
||||
</Table.Header.Cell>
|
||||
<Table.Header.Cell width="120px">
|
||||
<Table.Header.Cell column="created" {root}>
|
||||
Created
|
||||
</Table.Header.Cell>
|
||||
</svelte:fragment>
|
||||
{#each response?.files as file}
|
||||
<Table.Button on:click={() => selectFile(file)}>
|
||||
<Table.Cell>
|
||||
<Table.Row.Button
|
||||
{root}
|
||||
on:click={() => selectFile(file)}>
|
||||
<Table.Cell column="filename" {root}>
|
||||
<div
|
||||
class="u-inline-flex u-cross-center u-gap-12">
|
||||
<Selector.Radio
|
||||
@@ -297,19 +308,19 @@
|
||||
</Typography.Text>
|
||||
</div>
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="id" {root}>
|
||||
<Id value={file.$id}>{file.$id}</Id>
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="type" {root}>
|
||||
{file.mimeType}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="size" {root}>
|
||||
{calculateSize(file.sizeOriginal)}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="created" {root}>
|
||||
{toLocaleDate(file.$createdAt)}
|
||||
</Table.Cell>
|
||||
</Table.Button>
|
||||
</Table.Row.Button>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
{/if}
|
||||
|
||||
@@ -136,10 +136,10 @@
|
||||
</Layout.Stack>
|
||||
{#if selectedInstallation}
|
||||
{#await loadRepositories(selectedInstallation, search)}
|
||||
<Table.Root>
|
||||
<Table.Root columns={1} let:root>
|
||||
{#each Array(4) as _}
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell {root}>
|
||||
<Layout.Stack direction="row" alignItems="center">
|
||||
<Skeleton variant="circle" width={24} />
|
||||
|
||||
@@ -149,7 +149,7 @@
|
||||
<Skeleton variant="line" width={76} height={32} />
|
||||
</Layout.Stack>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
{:then response}
|
||||
@@ -159,10 +159,10 @@
|
||||
let:paginatedItems
|
||||
hideFooter={response?.length <= 6}
|
||||
limit={6}>
|
||||
<Table.Root>
|
||||
<Table.Root columns={1} let:root>
|
||||
{#each paginatedItems as repo}
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell {root}>
|
||||
<Layout.Stack direction="row" alignItems="center" gap="s">
|
||||
{#if action === 'select'}
|
||||
<input
|
||||
@@ -229,7 +229,7 @@
|
||||
{/if}
|
||||
</Layout.Stack>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
</Paginator>
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
import Row from './row.svelte';
|
||||
import { Icon, Selector, Table } from '@appwrite.io/pink-svelte';
|
||||
import { IconPlus, IconX } from '@appwrite.io/pink-icons-svelte';
|
||||
import type { Column } from '@appwrite.io/pink-svelte/dist/table';
|
||||
|
||||
export let withCreate = false;
|
||||
export let permissions: string[] = [];
|
||||
@@ -124,59 +125,65 @@
|
||||
|
||||
return a.localeCompare(b);
|
||||
}
|
||||
|
||||
const columns: Column[] = [
|
||||
{ id: 'role', width: { min: 100 } },
|
||||
{ id: 'create', width: { min: 100 }, hide: !withCreate },
|
||||
{ id: 'read', width: { min: 100 } },
|
||||
{ id: 'update', width: { min: 100 } },
|
||||
{ id: 'delete', width: { min: 100 } },
|
||||
{ id: 'action', width: 40 }
|
||||
];
|
||||
</script>
|
||||
|
||||
{#if [...$groups]?.length}
|
||||
<div class="table-wrapper">
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Role</Table.Header.Cell>
|
||||
<Table.Root {columns} let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell column="role" {root}>Role</Table.Header.Cell>
|
||||
{#if withCreate}
|
||||
<Table.Header.Cell width="90px">Create</Table.Header.Cell>
|
||||
<Table.Header.Cell column="create" {root}>Create</Table.Header.Cell>
|
||||
{/if}
|
||||
<Table.Header.Cell width="90px">Read</Table.Header.Cell>
|
||||
<Table.Header.Cell width="90px">Update</Table.Header.Cell>
|
||||
<Table.Header.Cell width="90px">Delete</Table.Header.Cell>
|
||||
<Table.Header.Cell width="40px" />
|
||||
<Table.Header.Cell column="read" {root}>Read</Table.Header.Cell>
|
||||
<Table.Header.Cell column="update" {root}>Update</Table.Header.Cell>
|
||||
<Table.Header.Cell column="delete" {root}>Delete</Table.Header.Cell>
|
||||
<Table.Header.Cell column="action" {root} />
|
||||
</svelte:fragment>
|
||||
{#each [...$groups].sort(sortRoles) as [role, permission] (role)}
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell column="role" {root}>
|
||||
<Row {role} />
|
||||
</Table.Cell>
|
||||
|
||||
{#if withCreate}
|
||||
<Table.Cell>
|
||||
<Selector.Checkbox
|
||||
checked={permission.create}
|
||||
on:change={() => togglePermission(role, 'create')} />
|
||||
</Table.Cell>
|
||||
{/if}
|
||||
<Table.Cell>
|
||||
<Table.Cell column="create" {root}>
|
||||
<Selector.Checkbox
|
||||
checked={permission.create}
|
||||
on:change={() => togglePermission(role, 'create')} />
|
||||
</Table.Cell>
|
||||
<Table.Cell column="read" {root}>
|
||||
<Selector.Checkbox
|
||||
size="s"
|
||||
checked={permission.read}
|
||||
on:change={() => togglePermission(role, 'read')} />
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="update" {root}>
|
||||
<Selector.Checkbox
|
||||
size="s"
|
||||
checked={permission.update}
|
||||
on:change={() => togglePermission(role, 'update')} />
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="delete" {root}>
|
||||
<Selector.Checkbox
|
||||
size="s"
|
||||
checked={permission.delete}
|
||||
on:change={() => togglePermission(role, 'delete')} />
|
||||
</Table.Cell>
|
||||
|
||||
<Table.Cell>
|
||||
<Table.Cell column="action" {root}>
|
||||
<Button compact icon ariaLabel="delete" on:click={() => deleteRole(role)}>
|
||||
<Icon icon={IconX} size="s" />
|
||||
</Button>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
</div>
|
||||
|
||||
@@ -78,24 +78,24 @@
|
||||
|
||||
{#if [...$groups.keys()]?.length}
|
||||
<Layout.Stack>
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Role</Table.Header.Cell>
|
||||
<Table.Header.Cell width="40px" />
|
||||
<Table.Root columns={[{ id: 'role' }, { id: 'action', width: 40 }]} let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell column="role" {root}>Role</Table.Header.Cell>
|
||||
<Table.Header.Cell column="action" {root} />
|
||||
</svelte:fragment>
|
||||
{#each [...$groups.keys()].sort(sortRoles) as role}
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell column="role" {root}>
|
||||
<Row {role} />
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="action" {root}>
|
||||
<Layout.Stack justifyContent="flex-end">
|
||||
<Button compact icon on:click={() => deleteRole(role)}>
|
||||
<Icon icon={IconX} size="s" />
|
||||
</Button>
|
||||
</Layout.Stack>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
<Actions
|
||||
|
||||
@@ -78,18 +78,18 @@
|
||||
>.</Typography.Text>
|
||||
<InputSearch autofocus placeholder="Search by name or ID" bind:value={search} />
|
||||
{#if results?.teams?.length}
|
||||
<Table.Root>
|
||||
<Table.Root columns={[{ id: 'checkbox', width: 40 }, { id: 'team' }]} let:root>
|
||||
{#each results.teams as team (team.$id)}
|
||||
{@const role = `team:${team.$id}`}
|
||||
{@const exists = $groups.has(role)}
|
||||
<Table.Button on:click={() => onSelection(role)} disabled={exists}>
|
||||
<Table.Cell width="40px">
|
||||
<Table.Row.Button {root} on:click={() => onSelection(role)} disabled={exists}>
|
||||
<Table.Cell column="checkbox" {root}>
|
||||
<Selector.Checkbox
|
||||
id={team.$id}
|
||||
checked={exists || selected.has(role)}
|
||||
disabled={exists} />
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="team" {root}>
|
||||
<Layout.Stack direction="row" alignItems="center" gap="s">
|
||||
<AvatarInitials size="xs" name={team.name} />
|
||||
<Layout.Stack gap="none">
|
||||
@@ -102,7 +102,7 @@
|
||||
</Layout.Stack>
|
||||
</Layout.Stack>
|
||||
</Table.Cell>
|
||||
</Table.Button>
|
||||
</Table.Row.Button>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
<div class="u-flex u-margin-block-start-32 u-main-space-between">
|
||||
|
||||
@@ -77,19 +77,19 @@
|
||||
<Typography.Text>Grant access to any authenticated or anonymous user.</Typography.Text>
|
||||
<InputSearch autofocus placeholder="Search by name, email, phone or ID" bind:value={search} />
|
||||
{#if results?.users?.length}
|
||||
<Table.Root>
|
||||
<Table.Root columns={[{ id: 'checkbox', width: 40 }, { id: 'user' }]} let:root>
|
||||
{#each results.users as user (user.$id)}
|
||||
{@const role = `user:${user.$id}`}
|
||||
{@const exists = $groups.has(role)}
|
||||
<Table.Button on:click={() => onSelection(role)} disabled={exists}>
|
||||
<Table.Cell width="40px">
|
||||
<Table.Row.Button {root} on:click={() => onSelection(role)} disabled={exists}>
|
||||
<Table.Cell column="checkbox" {root}>
|
||||
<Selector.Checkbox
|
||||
size="s"
|
||||
id={user.$id}
|
||||
checked={exists || selected.has(role)}
|
||||
disabled={exists} />
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="user" {root}>
|
||||
<Layout.Stack direction="row" alignItems="center" gap="s">
|
||||
{#if user.email || user.phone}
|
||||
{#if user.name}
|
||||
@@ -135,7 +135,7 @@
|
||||
{/if}
|
||||
</Layout.Stack>
|
||||
</Table.Cell>
|
||||
</Table.Button>
|
||||
</Table.Row.Button>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
const prefs = preferences.getCustomCollectionColumns($page.params.collection);
|
||||
columns.set(
|
||||
$columns.map((column) => {
|
||||
column.show = prefs?.includes(column.id) ?? true;
|
||||
column.hide = prefs?.includes(column.id) ?? false;
|
||||
return column;
|
||||
})
|
||||
);
|
||||
@@ -40,7 +40,7 @@
|
||||
if (prefs?.columns) {
|
||||
columns.set(
|
||||
$columns.map((column) => {
|
||||
column.show = prefs.columns?.includes(column.id) ?? true;
|
||||
column.hide = prefs.columns?.includes(column.id) ?? false;
|
||||
return column;
|
||||
})
|
||||
);
|
||||
@@ -48,7 +48,7 @@
|
||||
}
|
||||
|
||||
columns.subscribe((ctx) => {
|
||||
const columns = ctx.filter((n) => n.show).map((n) => n.id);
|
||||
const columns = ctx.filter((n) => n.hide === true).map((n) => n.id);
|
||||
|
||||
if (isCustomCollection) {
|
||||
preferences.setCustomCollectionColumns(columns);
|
||||
@@ -75,14 +75,11 @@
|
||||
});
|
||||
}
|
||||
|
||||
$: selectedColumnsNumber = $columns
|
||||
.filter((c) => !c.hide)
|
||||
.reduce((acc, column) => {
|
||||
if (column.show) {
|
||||
acc++;
|
||||
}
|
||||
return acc;
|
||||
}, 0);
|
||||
$: selectedColumnsNumber = $columns.reduce((acc, column) => {
|
||||
if (column.hide === true) return acc;
|
||||
|
||||
return ++acc;
|
||||
}, 0);
|
||||
</script>
|
||||
|
||||
{#if !hideColumns && view === View.Table}
|
||||
@@ -98,14 +95,15 @@
|
||||
<svelte:fragment slot="tooltip">
|
||||
<ActionMenu.Root>
|
||||
<Layout.Stack>
|
||||
{#each $columns.filter((c) => !c.hide) as column}
|
||||
{#each $columns as column}
|
||||
<InputCheckbox
|
||||
id={column.id}
|
||||
label={column.title}
|
||||
bind:checked={column.show}
|
||||
on:change={() => (column.hide = !column.hide)}
|
||||
checked={!column.hide}
|
||||
disabled={allowNoColumns
|
||||
? false
|
||||
: selectedColumnsNumber <= 1 && column.show} />
|
||||
: selectedColumnsNumber <= 1 && column.hide !== true} />
|
||||
{/each}
|
||||
</Layout.Stack>
|
||||
</ActionMenu.Root>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { Column as PinkColumn } from '@appwrite.io/pink-svelte/dist/table';
|
||||
import type { Writable } from 'svelte/store';
|
||||
|
||||
export type WritableValue<T> = T extends Writable<infer U> ? U : never;
|
||||
@@ -23,26 +24,13 @@ const columnTypes = [
|
||||
'enum'
|
||||
] as const;
|
||||
export type ColumnType = (typeof columnTypes)[number];
|
||||
export type Column = {
|
||||
id: string;
|
||||
export type Column = PinkColumn & {
|
||||
title: string;
|
||||
type: ColumnType;
|
||||
/**
|
||||
* Set to false to hide by default
|
||||
*/
|
||||
show: boolean;
|
||||
width?: number;
|
||||
/**
|
||||
* Set to false to disable filtering for this column
|
||||
*/
|
||||
filter?: boolean;
|
||||
array?: boolean;
|
||||
format?: string;
|
||||
elements?: string[] | { value: string | number; label: string }[];
|
||||
/**
|
||||
* Set to true to hide this column by default
|
||||
*/
|
||||
hide?: boolean;
|
||||
};
|
||||
|
||||
export function isValueOfStringEnum<T extends Record<string, string>>(
|
||||
|
||||
@@ -3,27 +3,36 @@
|
||||
import { Container } from '$lib/layout';
|
||||
import { toLocaleDateTime } from '$lib/helpers/date';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
import { Layout, Table, Card, Empty, Typography } from '@appwrite.io/pink-svelte';
|
||||
import { Layout, Table, Card, Empty } from '@appwrite.io/pink-svelte';
|
||||
import Button from '$lib/elements/forms/button.svelte';
|
||||
import type { Column } from '@appwrite.io/pink-svelte/dist/table';
|
||||
|
||||
export let logs: Models.LogList;
|
||||
export let offset = 0;
|
||||
export let limit = 0;
|
||||
|
||||
const columns: Column[] = [
|
||||
{ id: 'user' },
|
||||
{ id: 'event' },
|
||||
{ id: 'location' },
|
||||
{ id: 'ip' },
|
||||
{ id: 'date' }
|
||||
];
|
||||
</script>
|
||||
|
||||
<Container>
|
||||
{#if logs.total}
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>User</Table.Header.Cell>
|
||||
<Table.Header.Cell>Event</Table.Header.Cell>
|
||||
<Table.Header.Cell>Location</Table.Header.Cell>
|
||||
<Table.Header.Cell>IP</Table.Header.Cell>
|
||||
<Table.Header.Cell>Date</Table.Header.Cell>
|
||||
<Table.Root {columns} let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell column="user" {root}>User</Table.Header.Cell>
|
||||
<Table.Header.Cell column="event" {root}>Event</Table.Header.Cell>
|
||||
<Table.Header.Cell column="location" {root}>Location</Table.Header.Cell>
|
||||
<Table.Header.Cell column="ip" {root}>IP</Table.Header.Cell>
|
||||
<Table.Header.Cell column="date" {root}>Date</Table.Header.Cell>
|
||||
</svelte:fragment>
|
||||
{#each logs.logs as log}
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell column="user" {root}>
|
||||
<Layout.Stack direction="row" alignItems="center">
|
||||
{#if log.userEmail}
|
||||
{#if log.userName}
|
||||
@@ -41,23 +50,23 @@
|
||||
{/if}
|
||||
</Layout.Stack>
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="event" {root}>
|
||||
{log.event}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="location" {root}>
|
||||
{#if log.countryCode !== '--'}
|
||||
{log.countryName}
|
||||
{:else}
|
||||
Unknown
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="ip" {root}>
|
||||
{log.ip}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="date" {root}>
|
||||
{toLocaleDateTime(log.time)}
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
|
||||
|
||||
+26
-26
@@ -215,20 +215,20 @@
|
||||
</div>
|
||||
{#if selectedRequest === 'parameters'}
|
||||
{#if parameters?.length}
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Name</Table.Header.Cell>
|
||||
<Table.Header.Cell>Value</Table.Header.Cell>
|
||||
<Table.Root columns={2} let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell {root}>Name</Table.Header.Cell>
|
||||
<Table.Header.Cell {root}>Value</Table.Header.Cell>
|
||||
</svelte:fragment>
|
||||
{#each parameters as param}
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell {root}>
|
||||
{param.key}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell {root}>
|
||||
{param.value}
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
{/if}
|
||||
@@ -249,20 +249,20 @@
|
||||
</p>
|
||||
{:else if selectedRequest === 'headers'}
|
||||
{#if execution.requestHeaders.length}
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Name</Table.Header.Cell>
|
||||
<Table.Header.Cell>Value</Table.Header.Cell>
|
||||
<Table.Root columns={2} let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell {root}>Name</Table.Header.Cell>
|
||||
<Table.Header.Cell {root}>Value</Table.Header.Cell>
|
||||
</svelte:fragment>
|
||||
{#each execution.requestHeaders as header}
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
{header.key}
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell {root}>
|
||||
{header.name}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell {root}>
|
||||
{header.value}
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
{/if}
|
||||
@@ -363,20 +363,20 @@
|
||||
{/if}
|
||||
{:else if selectedResponse === 'headers'}
|
||||
{#if execution.responseHeaders.length}
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Name</Table.Header.Cell>
|
||||
<Table.Header.Cell>Value</Table.Header.Cell>
|
||||
<Table.Root columns={2} let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell {root}>Name</Table.Header.Cell>
|
||||
<Table.Header.Cell {root}>Value</Table.Header.Cell>
|
||||
</svelte:fragment>
|
||||
{#each execution.responseHeaders as header}
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
{header.key}
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell {root}>
|
||||
{header.name}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell {root}>
|
||||
{header.value}
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
{/if}
|
||||
|
||||
@@ -72,25 +72,30 @@
|
||||
</Layout.Stack>
|
||||
{/if}
|
||||
{#if rules.total}
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Name</Table.Header.Cell>
|
||||
<Table.Header.Cell>Verification status</Table.Header.Cell>
|
||||
<Table.Header.Cell>Certificate status</Table.Header.Cell>
|
||||
{#if $canWriteRules}
|
||||
<Table.Header.Cell width="20px" />
|
||||
{/if}
|
||||
<Table.Root
|
||||
let:root
|
||||
columns={[
|
||||
{ id: 'name' },
|
||||
{ id: 'verification' },
|
||||
{ id: 'certificate' },
|
||||
{ id: 'action', width: 20, hide: !$canWriteRules }
|
||||
]}>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell column="name" {root}>Name</Table.Header.Cell>
|
||||
<Table.Header.Cell column="verification" {root}>Verification status</Table.Header.Cell>
|
||||
<Table.Header.Cell column="certificate" {root}>Certificate status</Table.Header.Cell>
|
||||
<Table.Header.Cell column="action" {root} />
|
||||
</svelte:fragment>
|
||||
{#each rules.rules as domain}
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell column="name" {root}>
|
||||
<Layout.Stack direction="row" alignItems="center">
|
||||
<Link.Anchor href={`https://${domain.domain}`} target="_blank">
|
||||
{domain.domain}
|
||||
</Link.Anchor>
|
||||
</Layout.Stack>
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="verification" {root}>
|
||||
{#if domain.status === 'created'}
|
||||
<Layout.Stack direction="row" alignItems="center">
|
||||
<Badge variant="secondary" content="failed" type="error">
|
||||
@@ -106,7 +111,7 @@
|
||||
</Badge>
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="certificate" {root}>
|
||||
{#if domain.status === 'unverified'}
|
||||
<Layout.Stack direction="row" alignItems="center">
|
||||
<Badge variant="secondary" content="failed" type="error">
|
||||
@@ -133,35 +138,33 @@
|
||||
</Badge>
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
{#if $canWriteRules}
|
||||
<Table.Cell>
|
||||
<Popover let:toggle placement="bottom-start" padding="none">
|
||||
<Button text icon ariaLabel="more options" on:click={toggle}>
|
||||
<Icon icon={IconDotsHorizontal} size="s" />
|
||||
</Button>
|
||||
<ActionMenu.Root slot="tooltip">
|
||||
{#if domain.status !== 'verified'}
|
||||
<ActionMenu.Item.Button
|
||||
leadingIcon={IconRefresh}
|
||||
on:click={() => openRetry(domain)}>
|
||||
{domain.status === 'unverified'
|
||||
? 'Retry generation'
|
||||
: 'Retry verification'}
|
||||
</ActionMenu.Item.Button>
|
||||
{/if}
|
||||
<Table.Cell column="action" {root}>
|
||||
<Popover let:toggle placement="bottom-start" padding="none">
|
||||
<Button text icon ariaLabel="more options" on:click={toggle}>
|
||||
<Icon icon={IconDotsHorizontal} size="s" />
|
||||
</Button>
|
||||
<ActionMenu.Root slot="tooltip">
|
||||
{#if domain.status !== 'verified'}
|
||||
<ActionMenu.Item.Button
|
||||
leadingIcon={IconTrash}
|
||||
on:click={() => {
|
||||
selectedDomain = domain;
|
||||
showDelete = true;
|
||||
}}>
|
||||
Delete
|
||||
leadingIcon={IconRefresh}
|
||||
on:click={() => openRetry(domain)}>
|
||||
{domain.status === 'unverified'
|
||||
? 'Retry generation'
|
||||
: 'Retry verification'}
|
||||
</ActionMenu.Item.Button>
|
||||
</ActionMenu.Root>
|
||||
</Popover>
|
||||
</Table.Cell>
|
||||
{/if}
|
||||
</Table.Row>
|
||||
{/if}
|
||||
<ActionMenu.Item.Button
|
||||
leadingIcon={IconTrash}
|
||||
on:click={() => {
|
||||
selectedDomain = domain;
|
||||
showDelete = true;
|
||||
}}>
|
||||
Delete
|
||||
</ActionMenu.Item.Button>
|
||||
</ActionMenu.Root>
|
||||
</Popover>
|
||||
</Table.Cell>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
{:else}
|
||||
|
||||
@@ -12,25 +12,27 @@
|
||||
$: cnameValue = domain.domain.replace('.' + registerable, '');
|
||||
</script>
|
||||
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Type</Table.Header.Cell>
|
||||
<Table.Header.Cell>Name</Table.Header.Cell>
|
||||
<Table.Header.Cell>Value</Table.Header.Cell>
|
||||
<Table.Header.Cell width="40px" />
|
||||
<Table.Root
|
||||
let:root
|
||||
columns={[{ id: 'type' }, { id: 'name' }, { id: 'value' }, { id: 'action', width: 40 }]}>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell column="type" {root}>Type</Table.Header.Cell>
|
||||
<Table.Header.Cell column="name" {root}>Name</Table.Header.Cell>
|
||||
<Table.Header.Cell column="value" {root}>Value</Table.Header.Cell>
|
||||
<Table.Header.Cell column="action" {root} />
|
||||
</svelte:fragment>
|
||||
<Table.Row>
|
||||
<Table.Cell>CNAME</Table.Cell>
|
||||
<Table.Cell>{cnameValue}</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell column="type" {root}>CNAME</Table.Cell>
|
||||
<Table.Cell column="name" {root}>{cnameValue}</Table.Cell>
|
||||
<Table.Cell column="value" {root}>
|
||||
{target}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="action" {root}>
|
||||
<Button text>
|
||||
<Copy value={target}>
|
||||
<span class="icon-duplicate" aria-hidden="true" />
|
||||
</Copy>
|
||||
</Button>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
</Table.Root>
|
||||
|
||||
@@ -45,18 +45,26 @@
|
||||
it here." />
|
||||
</Card.Base>
|
||||
{:else}
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Provider</Table.Header.Cell>
|
||||
<Table.Header.Cell>Email</Table.Header.Cell>
|
||||
<Table.Header.Cell>Created At</Table.Header.Cell>
|
||||
<Table.Header.Cell>Expiry Date</Table.Header.Cell>
|
||||
<Table.Header.Cell width="40px" />
|
||||
<Table.Root
|
||||
let:root
|
||||
columns={[
|
||||
{ id: 'provider' },
|
||||
{ id: 'email' },
|
||||
{ id: 'createdAt' },
|
||||
{ id: 'expiryDate' },
|
||||
{ id: 'actions', width: 40 }
|
||||
]}>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell column="provider" {root}>Provider</Table.Header.Cell>
|
||||
<Table.Header.Cell column="email" {root}>Email</Table.Header.Cell>
|
||||
<Table.Header.Cell column="createdAt" {root}>Created At</Table.Header.Cell>
|
||||
<Table.Header.Cell column="expiryDate" {root}>Expiry Date</Table.Header.Cell>
|
||||
<Table.Header.Cell column="actions" {root} />
|
||||
</svelte:fragment>
|
||||
{#each $identities as identity (identity.$id)}
|
||||
{@const provider = oAuthProviders[identity.provider]}
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell column="provider" {root}>
|
||||
<Layout.Stack direction="row" alignItems="center">
|
||||
<div class="avatar is-size-small">
|
||||
<span
|
||||
@@ -66,24 +74,21 @@
|
||||
{provider.name}
|
||||
</Layout.Stack>
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="email" {root}>
|
||||
{identity.providerEmail}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="createdAt" {root}>
|
||||
{toLocaleDateTime(identity.$createdAt)}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="expiryDate" {root}>
|
||||
{toLocaleDateTime(identity.providerAccessTokenExpiry)}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Button
|
||||
text
|
||||
class="is-only-icon"
|
||||
on:click={() => deleteIdentity(identity.$id)}>
|
||||
<Table.Cell column="actions" {root}>
|
||||
<Button text on:click={() => deleteIdentity(identity.$id)}>
|
||||
<Icon icon={IconTrash} size="s" />
|
||||
</Button>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
{/if}
|
||||
|
||||
@@ -37,18 +37,18 @@
|
||||
</Button>
|
||||
</Copy>
|
||||
</Layout.Stack>
|
||||
<Table.Root>
|
||||
<Table.Root columns={[{ id: 'code' }, { id: 'action', width: 24 }]} let:root>
|
||||
{#each codes.recoveryCodes as code}
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell column="code" {root}>
|
||||
<Output value={code} hideCopyIcon>{code}</Output>
|
||||
</Table.Cell>
|
||||
<Table.Cell width="24px">
|
||||
<Table.Cell column="action" {root}>
|
||||
<Copy value={code}>
|
||||
<Icon icon={IconDuplicate} />
|
||||
</Copy>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
{/if}
|
||||
|
||||
@@ -48,7 +48,9 @@
|
||||
View or update your billing address. This address will be included in your invoices from Appwrite.
|
||||
<svelte:fragment slot="aside">
|
||||
{#if $addressList.total && countryList?.total}
|
||||
<Table.Root>
|
||||
<Table.Root
|
||||
let:root
|
||||
columns={[{ id: 'address' }, { id: 'links' }, { id: 'actions', width: 40 }]}>
|
||||
{#each $addressList.billingAddresses as address}
|
||||
{@const country = countryList?.countries?.find(
|
||||
(c) => c.code === address.country
|
||||
@@ -57,8 +59,8 @@
|
||||
(org) => address.$id === org.billingAddressId
|
||||
)}
|
||||
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell column="address" {root}>
|
||||
{address.streetAddress},
|
||||
{#if address?.addressLine2}
|
||||
{address.addressLine2},
|
||||
@@ -72,7 +74,7 @@
|
||||
{/if}
|
||||
{country ? country.name : address.country}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="links" {root}>
|
||||
{#if linkedOrgs?.length > 0}
|
||||
<Popover let:toggle>
|
||||
<Tag on:click={toggle} size="s">
|
||||
@@ -98,7 +100,7 @@
|
||||
</Popover>
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
<Table.Cell width="40px">
|
||||
<Table.Cell column="actions" {root}>
|
||||
<Popover let:toggle placement="bottom-end" padding="none">
|
||||
<Button icon text ariaLabel="More options" on:click={toggle}>
|
||||
<Icon icon={IconDotsHorizontal} size="s" />
|
||||
@@ -124,7 +126,7 @@
|
||||
</ActionMenu.Root>
|
||||
</Popover>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
|
||||
|
||||
@@ -49,14 +49,22 @@
|
||||
View or update your payment methods. These can be applied to any organizations you have created.
|
||||
<svelte:fragment slot="aside">
|
||||
{#if $paymentMethods?.total && filteredMethods?.length > 0}
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Credit card</Table.Header.Cell>
|
||||
<Table.Header.Cell>Name</Table.Header.Cell>
|
||||
<Table.Header.Cell>Expiration date</Table.Header.Cell>
|
||||
<Table.Header.Cell />
|
||||
<Table.Header.Cell />
|
||||
<Table.Header.Cell width="40px" />
|
||||
<Table.Root
|
||||
let:root
|
||||
columns={[
|
||||
{ id: 'cc' },
|
||||
{ id: 'name' },
|
||||
{ id: 'expiry' },
|
||||
{ id: 'status' },
|
||||
{ id: 'links' },
|
||||
{ id: 'actions', width: 40 }
|
||||
]}>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell column="cc" {root}>Credit card</Table.Header.Cell>
|
||||
<Table.Header.Cell column="name" {root}>Name</Table.Header.Cell>
|
||||
<Table.Header.Cell column="expiration" {root}
|
||||
>Expiration date</Table.Header.Cell>
|
||||
<Table.Header.Cell column="actions" {root} />
|
||||
</svelte:fragment>
|
||||
{#each filteredMethods as paymentMethod, i}
|
||||
{@const linkedOrgs = orgList?.filter(
|
||||
@@ -65,9 +73,9 @@
|
||||
paymentMethod.$id === org.backupPaymentMethodId
|
||||
)}
|
||||
|
||||
<Table.Row>
|
||||
<CreditCardInfo {paymentMethod} />
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<CreditCardInfo {root} {paymentMethod} />
|
||||
<Table.Cell column="links" {root}>
|
||||
{#if linkedOrgs?.length > 0}
|
||||
<Popover let:toggle>
|
||||
<Tag on:click={toggle} size="s">
|
||||
@@ -93,7 +101,7 @@
|
||||
</Popover>
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="actions" {root}>
|
||||
<Popover let:toggle placement="bottom-start" padding="none">
|
||||
<Button icon text on:click={toggle}>
|
||||
<Icon icon={IconDotsHorizontal} size="s" />
|
||||
@@ -124,7 +132,7 @@
|
||||
</svelte:fragment>
|
||||
</Popover>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
<div>
|
||||
|
||||
@@ -85,17 +85,24 @@
|
||||
<Button secondary on:click={logoutAll}>Sign out all sessions</Button>
|
||||
</Layout.Stack>
|
||||
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Client</Table.Header.Cell>
|
||||
<Table.Header.Cell>Location</Table.Header.Cell>
|
||||
<Table.Header.Cell>IP</Table.Header.Cell>
|
||||
<Table.Header.Cell width="68px" />
|
||||
<Table.Root
|
||||
let:root
|
||||
columns={[
|
||||
{ id: 'client' },
|
||||
{ id: 'location' },
|
||||
{ id: 'ip' },
|
||||
{ id: 'actions', width: 40 }
|
||||
]}>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell column="client" {root}>Client</Table.Header.Cell>
|
||||
<Table.Header.Cell column="location" {root}>Location</Table.Header.Cell>
|
||||
<Table.Header.Cell column="ip" {root}>IP</Table.Header.Cell>
|
||||
<Table.Header.Cell column="actions" {root} />
|
||||
</svelte:fragment>
|
||||
{#each data.sessions.sessions as session}
|
||||
{@const browser = getBrowser(session.clientCode)}
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell column="client" {root}>
|
||||
<Layout.Stack direction="row" alignItems="center">
|
||||
{#if session.clientName}
|
||||
<div class="avatar is-size-small">
|
||||
@@ -131,18 +138,20 @@
|
||||
{/if}
|
||||
</Layout.Stack>
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="location" {root}>
|
||||
{#if session.countryCode !== '--'}
|
||||
{session.countryName}
|
||||
{:else}
|
||||
Unknown
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
<Table.Cell>{session.ip}</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="ip" {root}>
|
||||
{session.ip}
|
||||
</Table.Cell>
|
||||
<Table.Cell column="actions" {root}>
|
||||
<Button size="xs" secondary on:click={() => logout(session)}>Sign out</Button>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
</Container>
|
||||
|
||||
@@ -114,22 +114,22 @@
|
||||
{/if}
|
||||
</div>
|
||||
{#if creditList?.total}
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Code</Table.Header.Cell>
|
||||
<Table.Header.Cell>Total</Table.Header.Cell>
|
||||
<Table.Header.Cell>Remaining</Table.Header.Cell>
|
||||
<Table.Header.Cell>Expires at</Table.Header.Cell>
|
||||
<Table.Root columns={4} let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell {root}>Code</Table.Header.Cell>
|
||||
<Table.Header.Cell {root}>Total</Table.Header.Cell>
|
||||
<Table.Header.Cell {root}>Remaining</Table.Header.Cell>
|
||||
<Table.Header.Cell {root}>Expires at</Table.Header.Cell>
|
||||
</svelte:fragment>
|
||||
{#each creditList.credits as credit}
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell {root}>
|
||||
{credit?.couponId ?? '-'}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell {root}>
|
||||
{formatCurrency(credit.total)}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell {root}>
|
||||
{#if credit.status === 'expired'}
|
||||
<span
|
||||
style="text-decoration: line-through;"
|
||||
@@ -139,7 +139,7 @@
|
||||
{formatCurrency(credit.credits)}
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell {root}>
|
||||
{#if credit.status === 'expired'}
|
||||
<Tooltip>
|
||||
<span>
|
||||
@@ -152,7 +152,7 @@
|
||||
{toLocaleDate(credit.expiration)}
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
{#if creditList?.total > limit}
|
||||
|
||||
@@ -118,13 +118,13 @@
|
||||
{/if}
|
||||
|
||||
{#if alerts.length}
|
||||
<Table.Root>
|
||||
<Table.Root columns={[{ id: 'percentage' }, { id: 'action', width: 40 }]} let:root>
|
||||
{#each alerts.sort() as alert}
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell column="percentage" {root}>
|
||||
{alert}%
|
||||
</Table.Cell>
|
||||
<Table.Cell width="40px">
|
||||
<Table.Cell column="action" {root}>
|
||||
<Button
|
||||
text
|
||||
icon
|
||||
@@ -133,7 +133,7 @@
|
||||
<Icon icon={IconTrash} size="s" />
|
||||
</Button>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
{/if}
|
||||
|
||||
@@ -69,20 +69,27 @@
|
||||
Transaction history for this organization. Download invoices for more details about your payments.
|
||||
<svelte:fragment slot="aside">
|
||||
{#if invoiceList.total > 0}
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Due date</Table.Header.Cell>
|
||||
<Table.Header.Cell width="200px">Status</Table.Header.Cell>
|
||||
<Table.Header.Cell width="120px">Amount due</Table.Header.Cell>
|
||||
<Table.Header.Cell width="40px" />
|
||||
<Table.Root
|
||||
let:root
|
||||
columns={[
|
||||
{ id: 'dueDate' },
|
||||
{ id: 'status', width: { min: 200 } },
|
||||
{ id: 'amount', width: { min: 120 } },
|
||||
{ id: 'action', width: 40 }
|
||||
]}>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell column="dueDate" {root}>Due date</Table.Header.Cell>
|
||||
<Table.Header.Cell column="status" {root}>Status</Table.Header.Cell>
|
||||
<Table.Header.Cell column="amount" {root}>Amount due</Table.Header.Cell>
|
||||
<Table.Header.Cell column="action" {root} />
|
||||
</svelte:fragment>
|
||||
{#each invoiceList?.invoices as invoice}
|
||||
{@const status = invoice.status}
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell column="dueDate" {root}>
|
||||
{toLocaleDate(invoice.dueAt)}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="status" {root}>
|
||||
{@const isDanger =
|
||||
status === 'overdue' ||
|
||||
status === 'failed' ||
|
||||
@@ -115,10 +122,10 @@
|
||||
{/if}
|
||||
</Layout.Stack>
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="amount" {root}>
|
||||
{formatCurrency(invoice.grossAmount)}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="status" {root}>
|
||||
<Popover let:toggle placement="bottom-start" padding="none">
|
||||
<Button text icon ariaLabel="more options" on:click={toggle}>
|
||||
<Icon icon={IconDotsHorizontal} size="s" />
|
||||
@@ -152,7 +159,7 @@
|
||||
</ActionMenu.Root>
|
||||
</Popover>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
{#if invoiceList.total > limit}
|
||||
|
||||
@@ -106,18 +106,26 @@
|
||||
View or update your organization payment methods here.
|
||||
<svelte:fragment slot="aside">
|
||||
{#if $organization?.paymentMethodId}
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Credit card</Table.Header.Cell>
|
||||
<Table.Header.Cell>Name</Table.Header.Cell>
|
||||
<Table.Header.Cell>Expiration date</Table.Header.Cell>
|
||||
<Table.Header.Cell />
|
||||
<Table.Header.Cell width="40px" />
|
||||
<Table.Root
|
||||
let:root
|
||||
columns={[
|
||||
{ id: 'cc' },
|
||||
{ id: 'name' },
|
||||
{ id: 'expiry' },
|
||||
{ id: 'status' },
|
||||
{ id: 'actions', width: 40 }
|
||||
]}>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell column="cc" {root}>Credit card</Table.Header.Cell>
|
||||
<Table.Header.Cell column="name" {root}>Name</Table.Header.Cell>
|
||||
<Table.Header.Cell column="expiry" {root}>Expiration date</Table.Header.Cell>
|
||||
<Table.Header.Cell column="status" {root} />
|
||||
<Table.Header.Cell column="actions" {root} />
|
||||
</svelte:fragment>
|
||||
|
||||
<Table.Row>
|
||||
<CreditCardInfo paymentMethod={defaultPaymentMethod} />
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<CreditCardInfo {root} paymentMethod={defaultPaymentMethod} />
|
||||
<Table.Cell column="actions" {root}>
|
||||
<Popover let:toggle placement="bottom-start" padding="none">
|
||||
<Button text icon ariaLabel="more options" on:click={toggle}>
|
||||
<Icon icon={IconDotsHorizontal} size="s" />
|
||||
@@ -152,11 +160,11 @@
|
||||
</ActionMenu.Root>
|
||||
</Popover>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{#if $organization?.backupPaymentMethodId}
|
||||
<Table.Row>
|
||||
<CreditCardInfo isBackup paymentMethod={backupPaymentMethod} />
|
||||
<Table.Cell width="40px">
|
||||
<Table.Row.Base {root}>
|
||||
<CreditCardInfo {root} isBackup paymentMethod={backupPaymentMethod} />
|
||||
<Table.Cell column="actions" {root}>
|
||||
<Popover let:toggle placement="bottom-start" padding="none">
|
||||
<Button text icon ariaLabel="more options" on:click={toggle}>
|
||||
<Icon icon={IconDotsHorizontal} size="s" />
|
||||
@@ -191,7 +199,7 @@
|
||||
</ActionMenu.Root>
|
||||
</Popover>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/if}
|
||||
</Table.Root>
|
||||
{#if !$organization?.backupPaymentMethodId}
|
||||
|
||||
@@ -36,8 +36,6 @@
|
||||
let showDelete = false;
|
||||
let showRetry = false;
|
||||
let selectedDomain: Domain = null;
|
||||
|
||||
$: console.log(data.domains);
|
||||
</script>
|
||||
|
||||
<Container>
|
||||
@@ -56,33 +54,47 @@
|
||||
</Layout.Stack>
|
||||
|
||||
{#if data.domains.total}
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Domain</Table.Header.Cell>
|
||||
<Table.Header.Cell>Registrar</Table.Header.Cell>
|
||||
<Table.Header.Cell>Nameservers</Table.Header.Cell>
|
||||
<Table.Header.Cell>Expiry date</Table.Header.Cell>
|
||||
<Table.Header.Cell>Renewal</Table.Header.Cell>
|
||||
<Table.Header.Cell>Auto renewal</Table.Header.Cell>
|
||||
<Table.Header.Cell />
|
||||
<Table.Root
|
||||
let:root
|
||||
columns={[
|
||||
{ id: 'domain' },
|
||||
{ id: 'registrar' },
|
||||
{ id: 'nameservers' },
|
||||
{ id: 'expiry_date' },
|
||||
{ id: 'renewal' },
|
||||
{ id: 'auto_renewal' },
|
||||
{ id: 'actions', width: 40 }
|
||||
]}>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell column="domain" {root}>Domain</Table.Header.Cell>
|
||||
<Table.Header.Cell column="registrar" {root}>Registrar</Table.Header.Cell>
|
||||
<Table.Header.Cell column="nameservers" {root}>Nameservers</Table.Header.Cell>
|
||||
<Table.Header.Cell column="expiry_date" {root}>Expiry date</Table.Header.Cell>
|
||||
<Table.Header.Cell column="renewal" {root}>Renewal</Table.Header.Cell>
|
||||
<Table.Header.Cell column="auto_renewal" {root}>Auto renewal</Table.Header.Cell>
|
||||
<Table.Header.Cell column="actions" {root} />
|
||||
</svelte:fragment>
|
||||
{#each data.domains.domains as domain}
|
||||
<Table.Link
|
||||
<Table.Row.Link
|
||||
{root}
|
||||
href={`${base}/organization-${$page.params.organization}/domains/domain-${domain.$id}`}>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="domain" {root}>
|
||||
<Link external icon href={`${$protocol}${domain.domain}`} variant="quiet">
|
||||
{domain.domain}
|
||||
</Link>
|
||||
</Table.Cell>
|
||||
<Table.Cell>{domain?.registrar || '-'}</Table.Cell>
|
||||
<Table.Cell>{domain?.nameservers || '-'}</Table.Cell>
|
||||
<Table.Cell>
|
||||
{domain?.expiry ? toLocaleDateTime(domain.expiry) : '-'}</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="registrar" {root}>{domain?.registrar || '-'}</Table.Cell>
|
||||
<Table.Cell column="nameservers" {root}
|
||||
>{domain?.nameservers || '-'}</Table.Cell>
|
||||
<Table.Cell column="expiry_date" {root}>
|
||||
{domain?.expiry ? toLocaleDateTime(domain.expiry) : '-'}
|
||||
</Table.Cell>
|
||||
<Table.Cell column="renewal" {root}>
|
||||
{domain.renewal ? toLocaleDateTime(domain.renewal) : '-'}
|
||||
</Table.Cell>
|
||||
<Table.Cell>{domain.autoRenewal ? 'On' : 'Off'}</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="auto_renewal" {root}
|
||||
>{domain.autoRenewal ? 'On' : 'Off'}</Table.Cell>
|
||||
<Table.Cell column="actions" {root}>
|
||||
<Layout.Stack direction="row" justifyContent="flex-end">
|
||||
<Popover let:toggle placement="bottom-end" padding="none">
|
||||
<Button
|
||||
@@ -131,7 +143,7 @@
|
||||
</Popover>
|
||||
</Layout.Stack>
|
||||
</Table.Cell>
|
||||
</Table.Link>
|
||||
</Table.Row.Link>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
|
||||
|
||||
+19
-12
@@ -36,20 +36,27 @@
|
||||
</Layout.Stack>
|
||||
|
||||
{#if data.certificates.total}
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>ID</Table.Header.Cell>
|
||||
<Table.Header.Cell>Renewal</Table.Header.Cell>
|
||||
<Table.Header.Cell>Expiry date</Table.Header.Cell>
|
||||
<Table.Header.Cell />
|
||||
<Table.Root
|
||||
let:root
|
||||
columns={[
|
||||
{ id: 'id' },
|
||||
{ id: 'renewal' },
|
||||
{ id: 'expiry' },
|
||||
{ id: 'actions', width: 40 }
|
||||
]}>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell column="id" {root}>ID</Table.Header.Cell>
|
||||
<Table.Header.Cell column="renewal" {root}>Renewal</Table.Header.Cell>
|
||||
<Table.Header.Cell column="expiry" {root}>Expiry date</Table.Header.Cell>
|
||||
<Table.Header.Cell column="actions" {root} />
|
||||
</svelte:fragment>
|
||||
{#each data.certificates.certificates as certificate}
|
||||
{@const isExpired = new Date(certificate.expiresAt) < now}
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell column="id" {root}>
|
||||
<Id value={certificate.$id}>{certificate.$id}</Id>
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="renewal" {root}>
|
||||
{#if certificate?.renewAt && !isExpired}
|
||||
<Layout.Stack direction="row" gap="xs">
|
||||
{certificate.autoRenewal ? 'Auto' : ''}
|
||||
@@ -63,7 +70,7 @@
|
||||
-
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="expiry" {root}>
|
||||
{#if isExpired}
|
||||
<Tooltip>
|
||||
<Badge
|
||||
@@ -80,7 +87,7 @@
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
|
||||
<Table.Cell>
|
||||
<Table.Cell column="actions" {root}>
|
||||
<Layout.Stack direction="row" justifyContent="flex-end">
|
||||
<Popover let:toggle placement="bottom-start" padding="none">
|
||||
<Button
|
||||
@@ -121,7 +128,7 @@
|
||||
</Popover>
|
||||
</Layout.Stack>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
|
||||
|
||||
+17
-17
@@ -50,34 +50,34 @@
|
||||
Forward emails to your domain using the following {capitalize(selectedPreset)} DNS records.
|
||||
</span>
|
||||
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Type</Table.Header.Cell>
|
||||
<Table.Header.Cell>Name</Table.Header.Cell>
|
||||
<Table.Header.Cell>Value</Table.Header.Cell>
|
||||
<Table.Header.Cell>TTL</Table.Header.Cell>
|
||||
<Table.Header.Cell>Priority</Table.Header.Cell>
|
||||
<Table.Root columns={5} let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell {root}>Type</Table.Header.Cell>
|
||||
<Table.Header.Cell {root}>Name</Table.Header.Cell>
|
||||
<Table.Header.Cell {root}>Value</Table.Header.Cell>
|
||||
<Table.Header.Cell {root}>TTL</Table.Header.Cell>
|
||||
<Table.Header.Cell {root}>Priority</Table.Header.Cell>
|
||||
</svelte:fragment>
|
||||
{#await fetchPreset()}
|
||||
{#each Array(2) as _}
|
||||
<Table.Row>
|
||||
<Table.Row.Base {root}>
|
||||
{#each Array(5) as _}
|
||||
<Table.Cell>
|
||||
<Table.Cell {root}>
|
||||
<Skeleton variant="line" width={70} height={15} />
|
||||
</Table.Cell>
|
||||
{/each}
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
{:then presetData}
|
||||
{JSON.stringify(presetData)}
|
||||
{#each presetData as record}
|
||||
<Table.Row>
|
||||
<Table.Cell>{record.type}</Table.Cell>
|
||||
<Table.Cell>{record.name}</Table.Cell>
|
||||
<Table.Cell>{record.value}</Table.Cell>
|
||||
<Table.Cell>{record.ttl}</Table.Cell>
|
||||
<Table.Cell>{record.priority}</Table.Cell>
|
||||
</Table.Row>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell {root}>{record.type}</Table.Cell>
|
||||
<Table.Cell {root}>{record.name}</Table.Cell>
|
||||
<Table.Cell {root}>{record.value}</Table.Cell>
|
||||
<Table.Cell {root}>{record.ttl}</Table.Cell>
|
||||
<Table.Cell {root}>{record.priority}</Table.Cell>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
{/await}
|
||||
</Table.Root>
|
||||
|
||||
@@ -5,13 +5,13 @@ import { derived, writable } from 'svelte/store';
|
||||
|
||||
export const domain = derived(page, ($page) => $page.data.domain as Domain);
|
||||
export const columns = writable<Column[]>([
|
||||
{ id: 'name', title: 'Name', type: 'string', show: true },
|
||||
{ id: 'type', title: 'Type', type: 'string', show: true },
|
||||
{ id: 'value', title: 'Value', type: 'string', show: true },
|
||||
{ id: 'ttl', title: 'TTL', type: 'integer', show: true },
|
||||
{ id: 'priority', title: 'Priority', type: 'integer', show: false },
|
||||
{ id: 'comment', title: 'Comment', type: 'string', show: false },
|
||||
{ id: '$createdAt', title: 'Created', type: 'datetime', show: true }
|
||||
{ id: 'name', title: 'Name', type: 'string' },
|
||||
{ id: 'type', title: 'Type', type: 'string' },
|
||||
{ id: 'value', title: 'Value', type: 'string' },
|
||||
{ id: 'ttl', title: 'TTL', type: 'integer' },
|
||||
{ id: 'priority', title: 'Priority', type: 'integer', hide: true },
|
||||
{ id: 'comment', title: 'Comment', type: 'string', hide: true },
|
||||
{ id: '$createdAt', title: 'Created', type: 'datetime' }
|
||||
]);
|
||||
|
||||
export const recordTypes = [
|
||||
|
||||
+31
-47
@@ -26,66 +26,50 @@
|
||||
</script>
|
||||
|
||||
<Layout.Stack>
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
{#each $columns as column}
|
||||
{#if column.show}
|
||||
<Table.Header.Cell width={column?.width?.toString() ?? ''}>
|
||||
{column.title}
|
||||
</Table.Header.Cell>
|
||||
{/if}
|
||||
<Table.Root columns={[...$columns, { id: 'actions', width: 40 }]} let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
{#each $columns as { id, title } (id)}
|
||||
<Table.Header.Cell column={id} {root}>
|
||||
{title}
|
||||
</Table.Header.Cell>
|
||||
{/each}
|
||||
<Table.Header.Cell width="40" />
|
||||
<Table.Header.Cell column="actions" {root} />
|
||||
</svelte:fragment>
|
||||
|
||||
{#each data.recordList.dnsRecords as record}
|
||||
<Table.Row>
|
||||
<Table.Row.Base {root}>
|
||||
{#each $columns as column}
|
||||
{#if column.show}
|
||||
<Table.Cell column={column.id} {root}>
|
||||
{#if column.id === 'name'}
|
||||
<Table.Cell>
|
||||
<Typography.Code>
|
||||
{record.name}
|
||||
</Typography.Code>
|
||||
</Table.Cell>
|
||||
<Typography.Code>
|
||||
{record.name}
|
||||
</Typography.Code>
|
||||
{:else if column.id === 'type'}
|
||||
<Table.Cell>
|
||||
<Typography.Text>
|
||||
{record.type}
|
||||
</Typography.Text>
|
||||
</Table.Cell>
|
||||
<Typography.Text>
|
||||
{record.type}
|
||||
</Typography.Text>
|
||||
{:else if column.id === 'value'}
|
||||
<Table.Cell>
|
||||
<InteractiveText variant="copy" text={record.value} isVisible />
|
||||
</Table.Cell>
|
||||
<InteractiveText variant="copy" text={record.value} isVisible />
|
||||
{:else if column.id === 'ttl'}
|
||||
<Table.Cell>
|
||||
<Typography.Text>
|
||||
{record.ttl}
|
||||
</Typography.Text>
|
||||
</Table.Cell>
|
||||
<Typography.Text>
|
||||
{record.ttl}
|
||||
</Typography.Text>
|
||||
{:else if column.id === 'priority'}
|
||||
<Table.Cell>
|
||||
<Typography.Text>
|
||||
{record?.priority ?? '-'}
|
||||
</Typography.Text>
|
||||
</Table.Cell>
|
||||
<Typography.Text>
|
||||
{record?.priority ?? '-'}
|
||||
</Typography.Text>
|
||||
{:else if column.id === 'comment'}
|
||||
<Table.Cell>
|
||||
<Typography.Text>
|
||||
{record?.comment ?? '-'}
|
||||
</Typography.Text>
|
||||
</Table.Cell>
|
||||
<Typography.Text>
|
||||
{record?.comment ?? '-'}
|
||||
</Typography.Text>
|
||||
{:else if column.id === '$createdAt'}
|
||||
<Table.Cell>
|
||||
<Typography.Text>
|
||||
{capitalize(timeFromNow(record.$createdAt))}
|
||||
</Typography.Text>
|
||||
</Table.Cell>
|
||||
<Typography.Text>
|
||||
{capitalize(timeFromNow(record.$createdAt))}
|
||||
</Typography.Text>
|
||||
{/if}
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
{/each}
|
||||
<Table.Cell>
|
||||
<Table.Cell column="actions" {root}>
|
||||
<Layout.Stack direction="row" justifyContent="flex-end">
|
||||
<Popover let:toggle placement="bottom-start" padding="none">
|
||||
<Button.Button
|
||||
@@ -127,7 +111,7 @@
|
||||
</Popover>
|
||||
</Layout.Stack>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
|
||||
|
||||
@@ -73,24 +73,26 @@
|
||||
</Typography.Text>
|
||||
</Layout.Stack>
|
||||
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Type</Table.Header.Cell>
|
||||
<Table.Header.Cell>Value</Table.Header.Cell>
|
||||
<Table.Header.Cell />
|
||||
<Table.Root
|
||||
columns={[{ id: 'type' }, { id: 'value' }, { id: 'actions', width: 40 }]}
|
||||
let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell column="type" {root}>Type</Table.Header.Cell>
|
||||
<Table.Header.Cell column="value" {root}>Value</Table.Header.Cell>
|
||||
<Table.Header.Cell column="actions" {root} />
|
||||
</svelte:fragment>
|
||||
{#each nameservers as nameserver}
|
||||
<Table.Row>
|
||||
<Table.Cell>NS</Table.Cell>
|
||||
<Table.Cell>{nameserver}</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell column="type" {root}>NS</Table.Cell>
|
||||
<Table.Cell column="value" {root}>{nameserver}</Table.Cell>
|
||||
<Table.Cell column="actions" {root}>
|
||||
<Layout.Stack alignItems="flex-end">
|
||||
<Copy value={nameserver}>
|
||||
<Icon icon={IconDuplicate} />
|
||||
</Copy>
|
||||
</Layout.Stack>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
<Layout.Stack gap="s" direction="row" alignItems="center">
|
||||
|
||||
@@ -76,11 +76,19 @@
|
||||
</ConsoleButton>
|
||||
</Layout.Stack>
|
||||
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Name</Table.Header.Cell>
|
||||
<Table.Header.Cell>Email</Table.Header.Cell>
|
||||
<Table.Header.Cell>
|
||||
<Table.Root
|
||||
let:root
|
||||
columns={[
|
||||
{ id: 'name' },
|
||||
{ id: 'email' },
|
||||
{ id: 'roles' },
|
||||
{ id: 'mfa' },
|
||||
{ id: 'actions', hide: !$isOwner, width: 40 }
|
||||
]}>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell column="name" {root}>Name</Table.Header.Cell>
|
||||
<Table.Header.Cell column="email" {root}>Email</Table.Header.Cell>
|
||||
<Table.Header.Cell column="roles" {root}>
|
||||
<Layout.Stack direction="row" gap="xxxs" alignItems="center">
|
||||
Roles
|
||||
<Popover let:toggle>
|
||||
@@ -91,14 +99,12 @@
|
||||
</Popover>
|
||||
</Layout.Stack>
|
||||
</Table.Header.Cell>
|
||||
<Table.Header.Cell>2FA</Table.Header.Cell>
|
||||
{#if $isOwner}
|
||||
<Table.Header.Cell width="40px" />
|
||||
{/if}
|
||||
<Table.Header.Cell column="mfa" {root}>2FA</Table.Header.Cell>
|
||||
<Table.Header.Cell column="actions" {root} />
|
||||
</svelte:fragment>
|
||||
{#each data.organizationMembers.memberships as member, index}
|
||||
<Table.Row>
|
||||
<Table.Cell width="40%">
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell column="name" {root}>
|
||||
<Layout.Stack direction="row" alignItems="center" gap="s">
|
||||
<AvatarInitials size="xs" name={member.userName} />
|
||||
<span class="u-trim">
|
||||
@@ -109,59 +115,57 @@
|
||||
{/if}
|
||||
</Layout.Stack>
|
||||
</Table.Cell>
|
||||
<Table.Cell width="30%">
|
||||
<Table.Cell column="email" {root}>
|
||||
{member.userEmail}
|
||||
</Table.Cell>
|
||||
<Table.Cell width="20%">
|
||||
<Table.Cell column="roles" {root}>
|
||||
{member.roles.map((role) => getRoleLabel(role)).join(', ')}
|
||||
</Table.Cell>
|
||||
<Table.Cell width="10%">
|
||||
<Table.Cell column="mfa" {root}>
|
||||
<Badge
|
||||
size="xs"
|
||||
type={member.mfa ? 'success' : undefined}
|
||||
variant="secondary"
|
||||
content={member.mfa ? 'Enabled' : 'Disabled'} />
|
||||
</Table.Cell>
|
||||
{#if $isOwner}
|
||||
<Table.Cell>
|
||||
<Popover let:toggle padding="none" placement="bottom-end">
|
||||
<Button.Button icon variant="ghost" size="s" on:click={toggle}>
|
||||
<Icon size="s" icon={IconDotsHorizontal} />
|
||||
</Button.Button>
|
||||
<div style:min-width="232px" slot="tooltip">
|
||||
<ActionMenu.Root>
|
||||
<Table.Cell column="actions" {root}>
|
||||
<Popover let:toggle padding="none" placement="bottom-end">
|
||||
<Button.Button icon variant="ghost" size="s" on:click={toggle}>
|
||||
<Icon size="s" icon={IconDotsHorizontal} />
|
||||
</Button.Button>
|
||||
<div style:min-width="232px" slot="tooltip">
|
||||
<ActionMenu.Root>
|
||||
<ActionMenu.Item.Button
|
||||
trailingIcon={IconPencil}
|
||||
on:click={() => {
|
||||
selectedMember = member;
|
||||
showEdit = true;
|
||||
showDropdown[index] = false;
|
||||
}}>
|
||||
Edit role
|
||||
</ActionMenu.Item.Button>
|
||||
{#if member.invited && !member.joined}
|
||||
<ActionMenu.Item.Button
|
||||
trailingIcon={IconPencil}
|
||||
trailingIcon={IconRefresh}
|
||||
on:click={() => {
|
||||
selectedMember = member;
|
||||
showEdit = true;
|
||||
showDropdown[index] = false;
|
||||
resend(member);
|
||||
}}>
|
||||
Edit role
|
||||
Resend
|
||||
</ActionMenu.Item.Button>
|
||||
{#if member.invited && !member.joined}
|
||||
<ActionMenu.Item.Button
|
||||
trailingIcon={IconRefresh}
|
||||
on:click={() => {
|
||||
resend(member);
|
||||
}}>
|
||||
Resend
|
||||
</ActionMenu.Item.Button>
|
||||
{/if}
|
||||
<ActionMenu.Item.Button
|
||||
trailingIcon={IconTrash}
|
||||
on:click={() => {
|
||||
selectedMember = member;
|
||||
showDelete = true;
|
||||
}}>
|
||||
Remove
|
||||
</ActionMenu.Item.Button>
|
||||
</ActionMenu.Root>
|
||||
</div>
|
||||
</Popover>
|
||||
</Table.Cell>
|
||||
{/if}
|
||||
</Table.Row>
|
||||
{/if}
|
||||
<ActionMenu.Item.Button
|
||||
trailingIcon={IconTrash}
|
||||
on:click={() => {
|
||||
selectedMember = member;
|
||||
showDelete = true;
|
||||
}}>
|
||||
Remove
|
||||
</ActionMenu.Item.Button>
|
||||
</ActionMenu.Root>
|
||||
</div>
|
||||
</Popover>
|
||||
</Table.Cell>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
|
||||
|
||||
+26
-61
@@ -23,10 +23,6 @@
|
||||
let selectedTab = 'projects';
|
||||
let organizationName: string = null;
|
||||
|
||||
/* enable overflow-x */
|
||||
const columnWidth = 120;
|
||||
const columnWidthSmall = columnWidth / 4;
|
||||
|
||||
async function deleteOrg() {
|
||||
try {
|
||||
if (isCloud) {
|
||||
@@ -72,21 +68,6 @@
|
||||
}
|
||||
];
|
||||
|
||||
$: tabData =
|
||||
selectedTab === 'projects'
|
||||
? {
|
||||
headers: ['Project', '', 'Last Updated'],
|
||||
rows: $projects.projects.map((project) => ({
|
||||
cells: [project.name, '', toLocaleDate(project.$updatedAt)]
|
||||
}))
|
||||
}
|
||||
: {
|
||||
headers: ['Member', '', 'Last Activity'],
|
||||
rows: $members.memberships.map((member) => ({
|
||||
cells: [member.userName, '', toLocaleDate(member.$updatedAt)]
|
||||
}))
|
||||
};
|
||||
|
||||
$: upcomingInvoice = invoices?.invoices.find((i) => i.status === 'upcoming' && i.amount > 0);
|
||||
|
||||
$: if (!showDelete) {
|
||||
@@ -127,51 +108,35 @@
|
||||
</Tabs.Item.Button>
|
||||
{/each}
|
||||
</Tabs.Root>
|
||||
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
{#each tabData.headers as header}
|
||||
<Table.Header.Cell width={columnWidth + 'px'}>{header}</Table.Header.Cell>
|
||||
{/each}
|
||||
</svelte:fragment>
|
||||
{#each tabData.rows as row}
|
||||
<Table.Row>
|
||||
{#each row.cells as cell}
|
||||
<Table.Cell>{cell}</Table.Cell>
|
||||
{/each}
|
||||
</Table.Row>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
<div class="box is-not-desktop">
|
||||
<SecondaryTabs large stretch class="u-sep-block-end u-padding-8">
|
||||
{#each tabs as { name, label, total }}
|
||||
<SecondaryTabsItem
|
||||
center
|
||||
fullWidth
|
||||
disabled={selectedTab === name}
|
||||
on:click={() => (selectedTab = name)}>
|
||||
{label.mobile} ({total})
|
||||
</SecondaryTabsItem>
|
||||
{/each}
|
||||
</SecondaryTabs>
|
||||
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
{#each tabData.headers as header, index}
|
||||
<Table.Header.Cell
|
||||
width={(index === 1 ? columnWidthSmall : columnWidth) + 'px'}
|
||||
>{header}</Table.Header.Cell>
|
||||
{/each}
|
||||
{#if selectedTab === 'projects'}
|
||||
<Table.Root columns={[{ id: 'projects' }, { id: 'lastUpdated' }]} let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell column="projects" {root}>Projects</Table.Header.Cell>
|
||||
<Table.Header.Cell column="lastUpdated" {root}>Last updated</Table.Header.Cell>
|
||||
</svelte:fragment>
|
||||
{#each tabData.rows as row}
|
||||
<Table.Row>
|
||||
{#each row.cells as cell}
|
||||
<Table.Cell>{cell}</Table.Cell>
|
||||
{/each}
|
||||
</Table.Row>
|
||||
{#each $projects.projects as project}
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell column="projects" {root}>{project.name}</Table.Cell>
|
||||
<Table.Cell column="lastUpdated" {root}
|
||||
>{toLocaleDate(project.$updatedAt)}</Table.Cell>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
</div>
|
||||
{:else}
|
||||
<Table.Root columns={[{ id: 'member' }, { id: 'lastUpdated' }]} let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell column="member" {root}>Members</Table.Header.Cell>
|
||||
<Table.Header.Cell column="lastUpdated" {root}>Last updated</Table.Header.Cell>
|
||||
</svelte:fragment>
|
||||
{#each $members.memberships as membership}
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell column="member" {root}>{membership.userName}</Table.Cell>
|
||||
<Table.Cell column="lastUpdated" {root}
|
||||
>{toLocaleDate(membership.$updatedAt)}</Table.Cell>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
{/if}
|
||||
{/if}
|
||||
<InputText
|
||||
label={`Confirm the organization name to continue`}
|
||||
|
||||
+42
-45
@@ -104,17 +104,22 @@
|
||||
|
||||
{#if projects.some((project) => project[metric]) || projects.some( (project) => databaseOperationMetric?.some((metric) => project[metric]) )}
|
||||
<Accordion title="Project breakdown" hideDivider>
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Project</Table.Header.Cell>
|
||||
{#if databaseOperationMetric}
|
||||
<Table.Header.Cell>Reads</Table.Header.Cell>
|
||||
<Table.Header.Cell>Writes</Table.Header.Cell>
|
||||
{:else}
|
||||
<Table.Header.Cell>{getMetricTitle(metric)}</Table.Header.Cell>
|
||||
{/if}
|
||||
|
||||
<Table.Header.Cell>Estimated cost</Table.Header.Cell>
|
||||
<Table.Root
|
||||
columns={[
|
||||
{ id: 'project' },
|
||||
{ id: 'reads', hide: !databaseOperationMetric },
|
||||
{ id: 'writes', hide: !databaseOperationMetric },
|
||||
{ id: 'metric', hide: !!databaseOperationMetric },
|
||||
{ id: 'costs' }
|
||||
]}
|
||||
let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell column="project" {root}>Project</Table.Header.Cell>
|
||||
<Table.Header.Cell column="reads" {root}>Reads</Table.Header.Cell>
|
||||
<Table.Header.Cell column="writes" {root}>Writes</Table.Header.Cell>
|
||||
<Table.Header.Cell column="metric" {root}
|
||||
>{getMetricTitle(metric)}</Table.Header.Cell>
|
||||
<Table.Header.Cell column="costs" {root}>Estimated cost</Table.Header.Cell>
|
||||
</svelte:fragment>
|
||||
{#each groupByProject(metric, estimate, databaseOperationMetric).sort((a, b) => {
|
||||
const aValue = a.usage ?? a.databasesReads ?? 0;
|
||||
@@ -122,49 +127,41 @@
|
||||
return bValue - aValue;
|
||||
}) as project}
|
||||
{#if !$canSeeProjects}
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell column="project" {root}>
|
||||
{data.projectNames[project.projectId]?.name ?? 'Unknown'}
|
||||
</Table.Cell>
|
||||
{#if databaseOperationMetric}
|
||||
<Table.Cell>
|
||||
{format(project.databasesReads ?? 0)}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
{format(project.databasesWrites ?? 0)}
|
||||
</Table.Cell>
|
||||
{:else}
|
||||
<Table.Cell>
|
||||
{format(project.usage)}
|
||||
</Table.Cell>
|
||||
{/if}
|
||||
|
||||
<Table.Cell>
|
||||
<Table.Cell column="reads" {root}>
|
||||
{format(project.databasesReads ?? 0)}
|
||||
</Table.Cell>
|
||||
<Table.Cell column="writes" {root}>
|
||||
{format(project.databasesWrites ?? 0)}
|
||||
</Table.Cell>
|
||||
<Table.Cell column="metric" {root}>
|
||||
{format(project.usage)}
|
||||
</Table.Cell>
|
||||
<Table.Cell column="costs" {root}>
|
||||
{formatCurrency(project.estimate ?? 0)}
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{:else}
|
||||
<Table.Link href={getProjectUsageLink(project.projectId)}>
|
||||
<Table.Cell>
|
||||
<Table.Row.Link href={getProjectUsageLink(project.projectId)} {root}>
|
||||
<Table.Cell column="project" {root}>
|
||||
{data.projectNames[project.projectId]?.name ?? 'Unknown'}
|
||||
</Table.Cell>
|
||||
{#if databaseOperationMetric}
|
||||
<Table.Cell>
|
||||
{format(project.databasesReads ?? 0)}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
{format(project.databasesWrites ?? 0)}
|
||||
</Table.Cell>
|
||||
{:else}
|
||||
<Table.Cell>
|
||||
{format(project.usage)}
|
||||
</Table.Cell>
|
||||
{/if}
|
||||
|
||||
<Table.Cell>
|
||||
<Table.Cell column="reads" {root}>
|
||||
{format(project.databasesReads ?? 0)}
|
||||
</Table.Cell>
|
||||
<Table.Cell column="writes" {root}>
|
||||
{format(project.databasesWrites ?? 0)}
|
||||
</Table.Cell>
|
||||
<Table.Cell column="metric" {root}>
|
||||
{format(project.usage)}
|
||||
</Table.Cell>
|
||||
<Table.Cell column="costs" {root}>
|
||||
{formatCurrency(project.estimate ?? 0)}
|
||||
</Table.Cell>
|
||||
</Table.Link>
|
||||
</Table.Row.Link>
|
||||
{/if}
|
||||
{/each}
|
||||
</Table.Root>
|
||||
|
||||
+8
-8
@@ -56,14 +56,14 @@
|
||||
items={members.memberships}
|
||||
let:paginatedItems
|
||||
hideFooter={members?.total <= 5}>
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Members</Table.Header.Cell>
|
||||
<Table.Header.Cell>Joined</Table.Header.Cell>
|
||||
<Table.Root columns={2} let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell {root}>Members</Table.Header.Cell>
|
||||
<Table.Header.Cell {root}>Joined</Table.Header.Cell>
|
||||
</svelte:fragment>
|
||||
{#each paginatedItems as member}
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell {root}>
|
||||
<Layout.Stack direction="row" alignItems="center" gap="s">
|
||||
<AvatarInitials
|
||||
size="xs"
|
||||
@@ -77,12 +77,12 @@
|
||||
</Layout.Stack>
|
||||
</Layout.Stack>
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell {root}>
|
||||
{member.joined
|
||||
? toLocaleDate(member.joined)
|
||||
: toLocaleDate(member.$createdAt)}
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
</Paginator>
|
||||
|
||||
@@ -33,13 +33,19 @@
|
||||
|
||||
const projectId = $page.params.project;
|
||||
const columns = writable<Column[]>([
|
||||
{ id: '$id', title: 'User ID', type: 'string', show: true, width: 140 },
|
||||
{ id: 'name', title: 'Name', type: 'string', show: true, width: 260 },
|
||||
{ id: 'identifiers', title: 'Identifiers', type: 'string', show: true, width: 140 },
|
||||
{ id: 'status', title: 'Status', type: 'string', show: true, width: 140 },
|
||||
{ id: 'labels', title: 'Labels', type: 'string', show: false, width: 140 },
|
||||
{ id: 'joined', title: 'Joined', type: 'string', show: true, width: 140 },
|
||||
{ id: 'lastActivity', title: 'Last activity', type: 'string', show: false, width: 140 }
|
||||
{ id: '$id', title: 'User ID', type: 'string', width: { min: 140 } },
|
||||
{ id: 'name', title: 'Name', type: 'string', width: { min: 260 } },
|
||||
{ id: 'identifiers', title: 'Identifiers', type: 'string', width: { min: 140 } },
|
||||
{ id: 'status', title: 'Status', type: 'string', width: { min: 140 } },
|
||||
{ id: 'labels', title: 'Labels', type: 'string', hide: true, width: { min: 140 } },
|
||||
{ id: 'joined', title: 'Joined', type: 'string', width: { min: 140 } },
|
||||
{
|
||||
id: 'lastActivity',
|
||||
title: 'Last activity',
|
||||
type: 'string',
|
||||
hide: true,
|
||||
width: { min: 140 }
|
||||
}
|
||||
]);
|
||||
|
||||
async function userCreated(event: CustomEvent<Models.User<Record<string, unknown>>>) {
|
||||
@@ -62,102 +68,81 @@
|
||||
</Layout.Stack>
|
||||
|
||||
{#if data.users.total}
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
{#each $columns as column (column.id)}
|
||||
{#if column.show}
|
||||
<Table.Header.Cell>{column.title}</Table.Header.Cell>
|
||||
{/if}
|
||||
<Table.Root columns={$columns} let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
{#each $columns as { id, title } (id)}
|
||||
<Table.Header.Cell column={id} {root}>{title}</Table.Header.Cell>
|
||||
{/each}
|
||||
</svelte:fragment>
|
||||
{#each data.users.users as user}
|
||||
<Table.Link href={`${base}/project-${projectId}/auth/user-${user.$id}`}>
|
||||
{#each $columns as column (column.id)}
|
||||
{#if column.show}
|
||||
{#if column.id === '$id'}
|
||||
<Table.Cell width={column.width + 'px'}>
|
||||
<Copy value={user.$id} event="user">
|
||||
<Tag size="xs" variant="code">
|
||||
<Icon size="s" icon={IconDuplicate} slot="start" />
|
||||
{user.$id}
|
||||
</Tag>
|
||||
</Copy>
|
||||
</Table.Cell>
|
||||
{:else if column.id === 'name'}
|
||||
<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>
|
||||
{user.name}
|
||||
</span>
|
||||
{:else}
|
||||
<div class="avatar is-size-small">
|
||||
<span
|
||||
class="icon-minus-sm"
|
||||
aria-hidden="true" />
|
||||
</div>
|
||||
{/if}
|
||||
<Table.Row.Link href={`${base}/project-${projectId}/auth/user-${user.$id}`} {root}>
|
||||
{#each $columns as { id } (id)}
|
||||
<Table.Cell column={id} {root}>
|
||||
{#if id === '$id'}
|
||||
<Copy value={user.$id} event="user">
|
||||
<Tag size="xs" variant="code">
|
||||
<Icon size="s" icon={IconDuplicate} slot="start" />
|
||||
{user.$id}
|
||||
</Tag>
|
||||
</Copy>
|
||||
{:else if id === 'name'}
|
||||
<Layout.Stack direction="row" alignItems="center" gap="s">
|
||||
{#if user.email || user.phone}
|
||||
{#if user.name}
|
||||
<AvatarInitials size="xs" name={user.name} />
|
||||
<span>
|
||||
{user.name}
|
||||
</span>
|
||||
{:else}
|
||||
<div class="avatar is-size-small">
|
||||
<span class="icon-anonymous" aria-hidden="true" />
|
||||
<span class="icon-minus-sm" aria-hidden="true" />
|
||||
</div>
|
||||
<span class="text u-trim">{user.name}</span>
|
||||
{/if}
|
||||
</Layout.Stack>
|
||||
</Table.Cell>
|
||||
{:else if column.id === 'identifiers'}
|
||||
<Table.Cell>
|
||||
{user.email && user.phone
|
||||
? [user.email, user.phone].join(',')
|
||||
: user.email || user.phone}
|
||||
</Table.Cell>
|
||||
{:else if column.id === 'status'}
|
||||
<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" />
|
||||
<div class="avatar is-size-small">
|
||||
<span class="icon-anonymous" aria-hidden="true" />
|
||||
</div>
|
||||
<span class="text u-trim">{user.name}</span>
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
{:else if column.id === 'labels'}
|
||||
<Table.Cell>
|
||||
{user.labels.join(', ')}
|
||||
</Table.Cell>
|
||||
{:else if column.id === 'joined'}
|
||||
<Table.Cell>
|
||||
{toLocaleDateTime(user.registration)}
|
||||
</Table.Cell>
|
||||
{:else if column.id === 'lastActivity'}
|
||||
<Table.Cell>
|
||||
{user.accessedAt ? toLocaleDate(user.accessedAt) : 'never'}
|
||||
</Table.Cell>
|
||||
</Layout.Stack>
|
||||
{:else if id === 'identifiers'}
|
||||
{user.email && user.phone
|
||||
? [user.email, user.phone].join(',')
|
||||
: user.email || user.phone}
|
||||
{:else if id === 'status'}
|
||||
{#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}
|
||||
{:else if id === 'labels'}
|
||||
{user.labels.join(', ')}
|
||||
{:else if id === 'joined'}
|
||||
{toLocaleDateTime(user.registration)}
|
||||
{:else if id === 'lastActivity'}
|
||||
{user.accessedAt ? toLocaleDate(user.accessedAt) : 'never'}
|
||||
{:else}
|
||||
<Table.Cell width={column.width + 'px'}>
|
||||
{user[column.id]}
|
||||
</Table.Cell>
|
||||
{user[id]}
|
||||
{/if}
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
{/each}
|
||||
</Table.Link>
|
||||
</Table.Row.Link>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
|
||||
|
||||
@@ -1,15 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { Submit, trackEvent, trackError } from '$lib/actions/analytics';
|
||||
import { Modal, CustomId } from '$lib/components';
|
||||
import { Pill } from '$lib/elements/';
|
||||
import {
|
||||
Button,
|
||||
InputPassword,
|
||||
InputEmail,
|
||||
InputText,
|
||||
InputPhone,
|
||||
FormList
|
||||
} from '$lib/elements/forms';
|
||||
import { Button, InputPassword, InputEmail, InputText, InputPhone } from '$lib/elements/forms';
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { ID } from '@appwrite.io/console';
|
||||
@@ -61,32 +53,21 @@
|
||||
</script>
|
||||
|
||||
<Modal title="Create user" {error} bind:show={showCreate} onSubmit={create}>
|
||||
<FormList>
|
||||
<InputText
|
||||
id="name"
|
||||
label="Name"
|
||||
placeholder="Enter name"
|
||||
autofocus={true}
|
||||
bind:value={name} />
|
||||
<InputEmail id="email" label="Email" placeholder="Enter email" bind:value={mail} />
|
||||
<InputPhone id="phone" label="Phone" placeholder="Enter phone" bind:value={phone} />
|
||||
<InputPassword
|
||||
id="password"
|
||||
label="Password"
|
||||
placeholder="Enter password"
|
||||
bind:value={pass} />
|
||||
<InputText id="name" label="Name" placeholder="Enter name" autofocus={true} bind:value={name} />
|
||||
<InputEmail id="email" label="Email" placeholder="Enter email" bind:value={mail} />
|
||||
<InputPhone id="phone" label="Phone" placeholder="Enter phone" bind:value={phone} />
|
||||
<InputPassword id="password" label="Password" placeholder="Enter password" bind:value={pass} />
|
||||
|
||||
{#if !showDropdown}
|
||||
<div>
|
||||
<Tag
|
||||
size="s"
|
||||
on:click={() => {
|
||||
showDropdown = true;
|
||||
}}><Icon icon={IconPencil} /> User ID</Tag>
|
||||
</div>
|
||||
{/if}
|
||||
<CustomId bind:show={showDropdown} name="User" bind:id fullWidth={true} />
|
||||
</FormList>
|
||||
{#if !showDropdown}
|
||||
<div>
|
||||
<Tag
|
||||
size="s"
|
||||
on:click={() => {
|
||||
showDropdown = true;
|
||||
}}><Icon icon={IconPencil} /> User ID</Tag>
|
||||
</div>
|
||||
{/if}
|
||||
<CustomId bind:show={showDropdown} name="User" bind:id fullWidth={true} />
|
||||
<svelte:fragment slot="footer">
|
||||
<Button text on:mousedown={() => (showCreate = false)}>Cancel</Button>
|
||||
<Button submit>Create</Button>
|
||||
|
||||
@@ -46,27 +46,29 @@
|
||||
</Layout.Stack>
|
||||
|
||||
{#if data.teams.total}
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Name</Table.Header.Cell>
|
||||
<Table.Header.Cell>Members</Table.Header.Cell>
|
||||
<Table.Header.Cell>Created</Table.Header.Cell>
|
||||
<Table.Root columns={3} let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell {root}>Name</Table.Header.Cell>
|
||||
<Table.Header.Cell {root}>Members</Table.Header.Cell>
|
||||
<Table.Header.Cell {root}>Created</Table.Header.Cell>
|
||||
</svelte:fragment>
|
||||
{#each data.teams.teams as team}
|
||||
<Table.Link href={`${base}/project-${project}/auth/teams/team-${team.$id}`}>
|
||||
<Table.Cell>
|
||||
<Table.Row.Link
|
||||
{root}
|
||||
href={`${base}/project-${project}/auth/teams/team-${team.$id}`}>
|
||||
<Table.Cell {root}>
|
||||
<Layout.Stack direction="row" alignItems="center">
|
||||
<AvatarInitials size="xs" name={team.name} />
|
||||
<span class="u-trim">{team.name}</span>
|
||||
</Layout.Stack>
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell {root}>
|
||||
{team.total} members
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell {root}>
|
||||
{toLocaleDateTime(team.$createdAt)}
|
||||
</Table.Cell>
|
||||
</Table.Link>
|
||||
</Table.Row.Link>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
|
||||
|
||||
+21
-12
@@ -37,29 +37,38 @@
|
||||
</Layout.Stack>
|
||||
|
||||
{#if data.memberships.total}
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Name</Table.Header.Cell>
|
||||
<Table.Header.Cell>Roles</Table.Header.Cell>
|
||||
<Table.Header.Cell>Joined</Table.Header.Cell>
|
||||
<Table.Header.Cell width="40px" />
|
||||
<Table.Root
|
||||
let:root
|
||||
columns={[
|
||||
{ id: 'name' },
|
||||
{ id: 'roles' },
|
||||
{ id: 'joined' },
|
||||
{ id: 'actions', width: 40 }
|
||||
]}>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell column="name" {root}>Name</Table.Header.Cell>
|
||||
<Table.Header.Cell column="roles" {root}>Roles</Table.Header.Cell>
|
||||
<Table.Header.Cell column="joined" {root}>Joined</Table.Header.Cell>
|
||||
<Table.Header.Cell column="actions" {root} />
|
||||
</svelte:fragment>
|
||||
{#each data.memberships.memberships as membership}
|
||||
{@const username = membership.userName ? membership.userName : '-'}
|
||||
<Table.Link href={`${base}/project-${project}/auth/user-${membership.userId}`}>
|
||||
<Table.Cell>
|
||||
<Table.Row.Link
|
||||
{root}
|
||||
href={`${base}/project-${project}/auth/user-${membership.userId}`}>
|
||||
<Table.Cell column="name" {root}>
|
||||
<Layout.Stack direction="row" alignItems="center">
|
||||
<AvatarInitials size="xs" name={username} />
|
||||
<span>{username}</span>
|
||||
</Layout.Stack>
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="roles" {root}>
|
||||
{membership.roles}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="joined" {root}>
|
||||
{toLocaleDateTime(membership.joined)}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="actions" {root}>
|
||||
<button
|
||||
class="button is-only-icon is-text"
|
||||
aria-label="Delete item"
|
||||
@@ -71,7 +80,7 @@
|
||||
<span class="icon-trash" aria-hidden="true" />
|
||||
</button>
|
||||
</Table.Cell>
|
||||
</Table.Link>
|
||||
</Table.Row.Link>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
|
||||
|
||||
@@ -14,19 +14,18 @@
|
||||
export let data: PageData;
|
||||
|
||||
const columns = writable<Column[]>([
|
||||
{ id: '$id', title: 'Identity ID', type: 'string', show: true, width: 140 },
|
||||
{ id: 'provider', title: 'Provider', type: 'string', show: true, width: 80 },
|
||||
{ id: 'providerUid', title: 'Provider UID', type: 'string', show: false, width: 80 },
|
||||
{ id: 'providerEmail', title: 'Email', type: 'string', show: true, width: 80 },
|
||||
{ id: '$id', title: 'Identity ID', type: 'string', width: 140 },
|
||||
{ id: 'provider', title: 'Provider', type: 'string', width: 80 },
|
||||
{ id: 'providerUid', title: 'Provider UID', type: 'string', hide: true, width: 80 },
|
||||
{ id: 'providerEmail', title: 'Email', type: 'string', width: 80 },
|
||||
{
|
||||
id: 'providerAccessTokenExpiry',
|
||||
title: 'Expiry Date',
|
||||
type: 'datetime',
|
||||
show: true,
|
||||
width: 60
|
||||
},
|
||||
{ id: '$createdAt', title: 'Created', type: 'datetime', show: true, width: 80 },
|
||||
{ id: '$updatedAt', title: 'Updated', type: 'datetime', show: false, width: 80 }
|
||||
{ id: '$createdAt', title: 'Created', type: 'datetime', width: 80 },
|
||||
{ id: '$updatedAt', title: 'Updated', type: 'datetime', hide: true, width: 80 }
|
||||
]);
|
||||
</script>
|
||||
|
||||
|
||||
@@ -50,62 +50,47 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Selector width="40px" />
|
||||
{#each columns as column}
|
||||
{#if column.show}
|
||||
<Table.Header.Cell width={column.width + 'px'}>{column.title}</Table.Header.Cell>
|
||||
{/if}
|
||||
<Table.Root {columns} allowSelection let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
{#each columns as { id, title }}
|
||||
<Table.Header.Cell column={id} {root}>{title}</Table.Header.Cell>
|
||||
{/each}
|
||||
</svelte:fragment>
|
||||
{#each data.identities.identities as identity (identity.$id)}
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
<Selector.Checkbox size="s" />
|
||||
</Table.Cell>
|
||||
|
||||
<Table.Row.Base {root}>
|
||||
{#each columns as column}
|
||||
{#if column.show}
|
||||
<Table.Cell column={column.id} {root}>
|
||||
{#if column.id === '$id'}
|
||||
{#key columns}
|
||||
<Table.Cell>
|
||||
<Id value={identity[column.id]}>
|
||||
{identity[column.id]}
|
||||
</Id>
|
||||
</Table.Cell>
|
||||
<Id value={identity[column.id]}>
|
||||
{identity[column.id]}
|
||||
</Id>
|
||||
{/key}
|
||||
{:else if column.id === 'provider'}
|
||||
{@const provider = oAuthProviders[identity[column.id]]}
|
||||
<Table.Cell width={column.width + 'px'}>
|
||||
<div class="u-inline-flex u-cross-center u-gap-8">
|
||||
<div class="avatar is-size-small">
|
||||
<img
|
||||
style="--p-text-size: 1rem"
|
||||
height="20"
|
||||
width="20"
|
||||
src={`${base}/icons/${$app.themeInUse}/color/${provider.icon}.svg`}
|
||||
alt={provider.name} />
|
||||
</div>
|
||||
{provider.name}
|
||||
<div class="u-inline-flex u-cross-center u-gap-8">
|
||||
<div class="avatar is-size-small">
|
||||
<img
|
||||
style="--p-text-size: 1rem"
|
||||
height="20"
|
||||
width="20"
|
||||
src={`${base}/icons/${$app.themeInUse}/color/${provider.icon}.svg`}
|
||||
alt={provider.name} />
|
||||
</div>
|
||||
</Table.Cell>
|
||||
{provider.name}
|
||||
</div>
|
||||
{:else if column.type === 'datetime'}
|
||||
<Table.Cell width={column.width + 'px'}>
|
||||
{#if !identity[column.id]}
|
||||
-
|
||||
{:else}
|
||||
{toLocaleDateTime(identity[column.id])}
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
{#if !identity[column.id]}
|
||||
-
|
||||
{:else}
|
||||
{toLocaleDateTime(identity[column.id])}
|
||||
{/if}
|
||||
{:else}
|
||||
<Table.Cell width={column.width + 'px'}>
|
||||
{identity[column.id]}
|
||||
</Table.Cell>
|
||||
{identity[column.id]}
|
||||
{/if}
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
{/each}
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
|
||||
|
||||
@@ -21,29 +21,37 @@
|
||||
|
||||
<Container>
|
||||
{#if data.memberships.total}
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Name</Table.Header.Cell>
|
||||
<Table.Header.Cell>Roles</Table.Header.Cell>
|
||||
<Table.Header.Cell>Joined</Table.Header.Cell>
|
||||
<Table.Header.Cell width="40px" />
|
||||
<Table.Root
|
||||
let:root
|
||||
columns={[
|
||||
{ id: 'name' },
|
||||
{ id: 'roles' },
|
||||
{ id: 'joined' },
|
||||
{ id: 'actions', width: 40 }
|
||||
]}>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell column="name" {root}>Name</Table.Header.Cell>
|
||||
<Table.Header.Cell column="roles" {root}>Roles</Table.Header.Cell>
|
||||
<Table.Header.Cell column="joined" {root}>Joined</Table.Header.Cell>
|
||||
<Table.Header.Cell column="actions" {root} />
|
||||
</svelte:fragment>
|
||||
{#each data.memberships.memberships as membership}
|
||||
<Table.Link
|
||||
<Table.Row.Link
|
||||
{root}
|
||||
href={`${base}/project-${project}/auth/teams/team-${membership.teamId}`}>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="name" {root}>
|
||||
<Layout.Stack direction="row" alignItems="center">
|
||||
<AvatarInitials size="xs" name={membership.teamName} />
|
||||
<span>{membership.teamName ? membership.teamName : 'n/a'}</span>
|
||||
</Layout.Stack>
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="roles" {root}>
|
||||
{membership.roles}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="joined" {root}>
|
||||
{toLocaleDateTime(membership.joined)}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="actions" {root}>
|
||||
<button
|
||||
class="button is-only-icon is-text"
|
||||
aria-label="Delete item"
|
||||
@@ -55,7 +63,7 @@
|
||||
<span class="icon-trash" aria-hidden="true" />
|
||||
</button>
|
||||
</Table.Cell>
|
||||
</Table.Link>
|
||||
</Table.Row.Link>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
{:else}
|
||||
|
||||
@@ -29,17 +29,24 @@
|
||||
<span class="text">Delete All</span>
|
||||
</Button>
|
||||
</Layout.Stack>
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Client</Table.Header.Cell>
|
||||
<Table.Header.Cell>Location</Table.Header.Cell>
|
||||
<Table.Header.Cell>IP</Table.Header.Cell>
|
||||
<Table.Header.Cell width="40px" />
|
||||
<Table.Root
|
||||
let:root
|
||||
columns={[
|
||||
{ id: 'client' },
|
||||
{ id: 'location' },
|
||||
{ id: 'ip' },
|
||||
{ id: 'actions', width: 40 }
|
||||
]}>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell column="client" {root}>Client</Table.Header.Cell>
|
||||
<Table.Header.Cell column="location" {root}>Location</Table.Header.Cell>
|
||||
<Table.Header.Cell column="ip" {root}>IP</Table.Header.Cell>
|
||||
<Table.Header.Cell column="actions" {root} />
|
||||
</svelte:fragment>
|
||||
{#each data.sessions.sessions as session}
|
||||
{@const browser = getBrowser(session.clientCode)}
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell column="client" {root}>
|
||||
<Layout.Stack direction="row" alignItems="center">
|
||||
{#if session.clientName}
|
||||
<div class="avatar is-size-small">
|
||||
@@ -69,15 +76,17 @@
|
||||
<Badge variant="secondary" content={session.provider} />
|
||||
</Layout.Stack>
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="location" {root}>
|
||||
{#if session.countryCode !== '--'}
|
||||
{session.countryName}
|
||||
{:else}
|
||||
Unknown
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
<Table.Cell>{session.ip}</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="ip" {root}>
|
||||
{session.ip}
|
||||
</Table.Cell>
|
||||
<Table.Cell column="actions" {root}>
|
||||
<Button
|
||||
compact
|
||||
icon
|
||||
@@ -89,7 +98,7 @@
|
||||
<span class="icon-trash" aria-hidden="true" />
|
||||
</Button>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
{:else}
|
||||
|
||||
@@ -2,9 +2,9 @@ import type { Column } from '$lib/helpers/types';
|
||||
import { writable } from 'svelte/store';
|
||||
|
||||
export const columns = writable<Column[]>([
|
||||
{ id: '$id', title: 'Target ID', type: 'string', show: true, width: 140 },
|
||||
{ id: 'target', title: 'Target', type: 'string', show: true, filter: false, width: 140 },
|
||||
{ id: 'providerType', title: 'Type', type: 'string', show: true, filter: true, width: 80 },
|
||||
{ id: 'provider', title: 'Provider', type: 'string', show: true, filter: false, width: 80 },
|
||||
{ id: '$createdAt', title: 'Created', type: 'datetime', show: true, width: 100 }
|
||||
{ id: '$id', title: 'Target ID', type: 'string', width: { min: 140 } },
|
||||
{ id: 'target', title: 'Target', type: 'string', filter: false, width: { min: 140 } },
|
||||
{ id: 'providerType', title: 'Type', type: 'string', filter: true, width: { min: 80 } },
|
||||
{ id: 'provider', title: 'Provider', type: 'string', filter: false, width: { min: 80 } },
|
||||
{ id: '$createdAt', title: 'Created', type: 'datetime', width: { min: 100 } }
|
||||
]);
|
||||
|
||||
@@ -52,62 +52,43 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Selector width="40px" />
|
||||
{#each $columns as column}
|
||||
{#if column.show}
|
||||
<Table.Header.Cell width={column.width + 'px'}>{column.title}</Table.Header.Cell>
|
||||
{/if}
|
||||
<Table.Root columns={$columns} allowSelection let:root bind:selectedRows={selectedIds}>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
{#each $columns as { id, title }}
|
||||
<Table.Header.Cell column={id} {root}>{title}</Table.Header.Cell>
|
||||
{/each}
|
||||
</svelte:fragment>
|
||||
{#each data.targets.targets as target (target.$id)}
|
||||
{@const provider = data.providersById[target.providerId]}
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
<Selector.Checkbox size="s" />
|
||||
</Table.Cell>
|
||||
|
||||
<Table.Row.Base {root} id={target.$id}>
|
||||
{#each $columns as column}
|
||||
{#if column.show}
|
||||
<Table.Cell column={column.id} {root}>
|
||||
{#if column.id === '$id'}
|
||||
{#key $columns}
|
||||
<Table.Cell>
|
||||
<Id value={target[column.id]}>
|
||||
{target[column.id]}
|
||||
</Id>
|
||||
</Table.Cell>
|
||||
<Id value={target[column.id]}>
|
||||
{target[column.id]}
|
||||
</Id>
|
||||
{/key}
|
||||
{:else if column.id === 'target'}
|
||||
<Table.Cell>
|
||||
{#if target.providerType === MessagingProviderType.Push}
|
||||
{target.name}
|
||||
{:else}
|
||||
{target.identifier}
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
{#if target.providerType === MessagingProviderType.Push}
|
||||
{target.name}
|
||||
{:else}
|
||||
{target.identifier}
|
||||
{/if}
|
||||
{:else if column.id === 'providerType'}
|
||||
<Table.Cell width={column.width + 'px'}>
|
||||
<ProviderType type={target.providerType} size="s" />
|
||||
</Table.Cell>
|
||||
<ProviderType type={target.providerType} size="s" />
|
||||
{:else if column.id === 'provider'}
|
||||
<Table.Cell width={column.width + 'px'}>
|
||||
{#if provider}
|
||||
<Provider provider={provider.provider} size="s" />
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
{#if provider}
|
||||
<Provider provider={provider.provider} />
|
||||
{/if}
|
||||
{:else if column.id === '$createdAt'}
|
||||
<Table.Cell width={column.width + 'px'}>
|
||||
{toLocaleDateTime(target[column.id])}
|
||||
</Table.Cell>
|
||||
{toLocaleDateTime(target[column.id])}
|
||||
{:else}
|
||||
<Table.Cell width={column.width + 'px'}>
|
||||
{target[column.id]}
|
||||
</Table.Cell>
|
||||
{target[column.id]}
|
||||
{/if}
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
{/each}
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
|
||||
|
||||
@@ -49,14 +49,14 @@
|
||||
label="Multi-factor authentication"
|
||||
bind:value={userMfa} />
|
||||
{#if $userFactors.totp}
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Authenticator</Table.Header.Cell>
|
||||
<Table.Header.Cell width="40px" />
|
||||
<Table.Root columns={[{ id: 'type' }, { id: 'actions', width: 40 }]} let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell column="type" {root}>Authenticator</Table.Header.Cell>
|
||||
<Table.Header.Cell column="actions" {root} />
|
||||
</svelte:fragment>
|
||||
<Table.Row>
|
||||
<Table.Cell>TOTP (One-time code)</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell column="type" {root}>TOTP (One-time code)</Table.Cell>
|
||||
<Table.Cell column="actions" {root}>
|
||||
<Button
|
||||
on:click={() => (showDelete = true)}
|
||||
icon
|
||||
@@ -65,7 +65,7 @@
|
||||
<span class="icon-trash" aria-hidden="true" />
|
||||
</Button>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
</Table.Root>
|
||||
{:else}
|
||||
<Card.Base variant="primary">
|
||||
|
||||
+4
-4
@@ -2,8 +2,8 @@ import type { Column } from '$lib/helpers/types';
|
||||
import { writable } from 'svelte/store';
|
||||
|
||||
export const columns = writable<Column[]>([
|
||||
{ id: '$id', title: 'Database ID', type: 'string', show: true, width: 150 },
|
||||
{ id: 'name', title: 'Name', type: 'string', show: true, width: 120 },
|
||||
{ id: '$createdAt', title: 'Created', type: 'string', show: true, width: 120 },
|
||||
{ id: '$updatedAt', title: 'Updated', type: 'string', show: true, width: 120 }
|
||||
{ id: '$id', title: 'Database ID', type: 'string', width: 150 },
|
||||
{ id: 'name', title: 'Name', type: 'string', width: 120 },
|
||||
{ id: '$createdAt', title: 'Created', type: 'string', width: 120 },
|
||||
{ id: '$updatedAt', title: 'Updated', type: 'string', width: 120 }
|
||||
]);
|
||||
|
||||
+19
-12
@@ -80,17 +80,24 @@
|
||||
</Layout.Stack>
|
||||
|
||||
{#if $attributes.length}
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Key</Table.Header.Cell>
|
||||
<Table.Header.Cell>Type</Table.Header.Cell>
|
||||
<Table.Header.Cell>Default value</Table.Header.Cell>
|
||||
<Table.Header.Cell width="40px" />
|
||||
<Table.Root
|
||||
let:root
|
||||
columns={[
|
||||
{ id: 'key' },
|
||||
{ id: 'type' },
|
||||
{ id: 'default' },
|
||||
{ id: 'actions', width: 40 }
|
||||
]}>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell column="key" {root}>Key</Table.Header.Cell>
|
||||
<Table.Header.Cell column="type" {root}>Type</Table.Header.Cell>
|
||||
<Table.Header.Cell column="default" {root}>Default value</Table.Header.Cell>
|
||||
<Table.Header.Cell column="actions" {root} />
|
||||
</svelte:fragment>
|
||||
{#each $attributes as attribute, index}
|
||||
{@const option = attributeOptions.find((option) => option.type === attribute.type)}
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell column="key" {root}>
|
||||
<Layout.Stack direction="row" alignItems="center">
|
||||
{#if isRelationship(attribute)}
|
||||
<Icon
|
||||
@@ -125,7 +132,7 @@
|
||||
{/if}
|
||||
</Layout.Stack>
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="type" {root}>
|
||||
{#if 'format' in attribute && attribute.format}
|
||||
<span class="u-capitalize">{attribute.format}</span>
|
||||
{:else}
|
||||
@@ -142,12 +149,12 @@
|
||||
{attribute.array ? '[]' : ''}
|
||||
</span>
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="default" {root}>
|
||||
{attribute?.default !== null && attribute?.default !== undefined
|
||||
? attribute?.default
|
||||
: '-'}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="actions" {root}>
|
||||
<Popover let:toggle padding="none" placement="bottom-end">
|
||||
<Button text icon ariaLabel="more options" on:click={toggle}>
|
||||
<Icon icon={IconDotsHorizontal} size="s" />
|
||||
@@ -188,7 +195,7 @@
|
||||
</ActionMenu.Root>
|
||||
</Popover>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
{:else}
|
||||
|
||||
+16
-10
@@ -61,15 +61,21 @@
|
||||
|
||||
{#if relAttributes?.length}
|
||||
<p class="text">This document contains the following relationships:</p>
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell width="70px">Relation</Table.Header.Cell>
|
||||
<Table.Header.Cell width="70px">Setting</Table.Header.Cell>
|
||||
<Table.Header.Cell />
|
||||
<Table.Root
|
||||
let:root
|
||||
columns={[
|
||||
{ id: 'relations', width: 70 },
|
||||
{ id: 'setting', width: 70 },
|
||||
{ id: 'desc' }
|
||||
]}>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell column="relations" {root}>Relation</Table.Header.Cell>
|
||||
<Table.Header.Cell column="setting" {root}>Setting</Table.Header.Cell>
|
||||
<Table.Header.Cell column="desc" {root} />
|
||||
</svelte:fragment>
|
||||
{#each relAttributes as attr}
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell column="relations" {root}>
|
||||
<span class="u-flex u-cross-center u-gap-8">
|
||||
{#if attr.twoWay}
|
||||
<span class="icon-switch-horizontal" />
|
||||
@@ -79,13 +85,13 @@
|
||||
<Trim>{attr.key}</Trim>
|
||||
</span>
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="setting" {root}>
|
||||
{attr.onDelete}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="desc" {root}>
|
||||
{Deletion[attr.onDelete]}
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
<div class="u-flex u-flex-vertical u-gap-16">
|
||||
|
||||
+27
-17
@@ -33,6 +33,8 @@
|
||||
import type { ComponentProps } from 'svelte';
|
||||
import { Click, trackEvent } from '$lib/actions/analytics';
|
||||
|
||||
export let data;
|
||||
|
||||
let showDropdown = [];
|
||||
let selectedIndex: Models.Index = null;
|
||||
let showCreateIndex = false;
|
||||
@@ -72,19 +74,27 @@
|
||||
{/if}
|
||||
</Layout.Stack>
|
||||
|
||||
{#if $collection?.attributes?.length}
|
||||
{#if $indexes.length}
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Key</Table.Header.Cell>
|
||||
<Table.Header.Cell>Type</Table.Header.Cell>
|
||||
<Table.Header.Cell>Attributes</Table.Header.Cell>
|
||||
<Table.Header.Cell>Asc/Desc</Table.Header.Cell>
|
||||
<Table.Header.Cell width="40px" />
|
||||
{#if data.collection?.attributes?.length}
|
||||
{#if data.collection.indexes.length}
|
||||
<Table.Root
|
||||
let:root
|
||||
columns={[
|
||||
{ id: 'key' },
|
||||
{ id: 'type' },
|
||||
{ id: 'attributes' },
|
||||
{ id: 'orders' },
|
||||
{ id: 'actions', width: 40 }
|
||||
]}>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell column="key" {root}>Key</Table.Header.Cell>
|
||||
<Table.Header.Cell column="type" {root}>Type</Table.Header.Cell>
|
||||
<Table.Header.Cell column="attributes" {root}>Attributes</Table.Header.Cell>
|
||||
<Table.Header.Cell column="orders" {root}>Asc/Desc</Table.Header.Cell>
|
||||
<Table.Header.Cell column="actions" {root} />
|
||||
</svelte:fragment>
|
||||
{#each $indexes as index, i}
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
{#each data.collection.indexes as index}
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell column="key" {root}>
|
||||
<Layout.Stack direction="row" alignItems="center">
|
||||
{index.key}
|
||||
{#if index.status !== 'available'}
|
||||
@@ -105,14 +115,14 @@
|
||||
{/if}
|
||||
</Layout.Stack>
|
||||
</Table.Cell>
|
||||
<Table.Cell>{index.type}</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="type" {root}>{index.type}</Table.Cell>
|
||||
<Table.Cell column="attributes" {root}>
|
||||
{index.attributes}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="orders" {root}>
|
||||
{index.orders}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="actions" {root}>
|
||||
<Popover let:toggle padding="none" placement="bottom-end">
|
||||
<Button text icon ariaLabel="more options" on:click={toggle}>
|
||||
<Icon icon={IconDotsHorizontal} size="s" />
|
||||
@@ -134,7 +144,7 @@
|
||||
</ActionMenu.Root>
|
||||
</Popover>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
{:else}
|
||||
|
||||
+11
-8
@@ -28,28 +28,31 @@
|
||||
<Modal bind:show title={selectedRelationship?.key} hideFooter>
|
||||
{#if data?.length}
|
||||
<Paginator items={data} {limit} let:paginatedItems>
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell width="150px">Document ID</Table.Header.Cell>
|
||||
<Table.Root
|
||||
let:root
|
||||
columns={[{ id: '$id', width: 150 }, ...args.map((id) => ({ id }))]}>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell column="$id" {root}>Document ID</Table.Header.Cell>
|
||||
{#if args?.length}
|
||||
{#each args as arg}
|
||||
<Table.Header.Cell>{arg}</Table.Header.Cell>
|
||||
<Table.Header.Cell column={arg} {root}>{arg}</Table.Header.Cell>
|
||||
{/each}
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
{#each paginatedItems as doc}
|
||||
<Table.Link
|
||||
<Table.Row.Link
|
||||
{root}
|
||||
href={`${base}/project-${projectId}/databases/database-${databaseId}/collection-${selectedRelationship.relatedCollection}/document-${doc.$id}`}
|
||||
on:click={() => (show = false)}>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="$id" {root}>
|
||||
<Id value={doc.$id}>{doc.$id}</Id>
|
||||
</Table.Cell>
|
||||
{#if args?.length}
|
||||
{#each args as arg}
|
||||
<Table.Cell>{doc[arg]}</Table.Cell>
|
||||
<Table.Cell column={arg} {root}>{doc[arg]}</Table.Cell>
|
||||
{/each}
|
||||
{/if}
|
||||
</Table.Link>
|
||||
</Table.Row.Link>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
</Paginator>
|
||||
|
||||
+96
-119
@@ -17,7 +17,7 @@
|
||||
import { attributes, collection, columns } from './store';
|
||||
import type { ColumnType } from '$lib/helpers/types';
|
||||
import { toLocaleDateTime } from '$lib/helpers/date';
|
||||
import { Tooltip, Table, Selector, Button, Link } from '@appwrite.io/pink-svelte';
|
||||
import { Tooltip, Table, Button, Link } from '@appwrite.io/pink-svelte';
|
||||
|
||||
export let data: PageData;
|
||||
|
||||
@@ -103,14 +103,14 @@
|
||||
);
|
||||
}
|
||||
|
||||
let selectedDb: string[] = [];
|
||||
let selectedRows: string[] = [];
|
||||
let showDelete = false;
|
||||
let deleting = false;
|
||||
|
||||
async function handleDelete() {
|
||||
showDelete = false;
|
||||
|
||||
const promises = selectedDb.map((documentId) =>
|
||||
const promises = selectedRows.map((documentId) =>
|
||||
sdk.forProject.databases.deleteDocument(databaseId, collectionId, documentId)
|
||||
);
|
||||
try {
|
||||
@@ -118,7 +118,7 @@
|
||||
trackEvent(Submit.DocumentDelete);
|
||||
addNotification({
|
||||
type: 'success',
|
||||
message: `${selectedDb.length} document${selectedDb.length > 1 ? 's' : ''} deleted`
|
||||
message: `${selectedRows.length} document${selectedRows.length > 1 ? 's' : ''} deleted`
|
||||
});
|
||||
invalidate(Dependencies.DOCUMENTS);
|
||||
} catch (error) {
|
||||
@@ -128,7 +128,7 @@
|
||||
});
|
||||
trackError(error, Submit.DocumentDelete);
|
||||
} finally {
|
||||
selectedDb = [];
|
||||
selectedRows = [];
|
||||
showDelete = false;
|
||||
}
|
||||
}
|
||||
@@ -146,25 +146,25 @@
|
||||
let checked = false;
|
||||
</script>
|
||||
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Selector width="40px" />
|
||||
<Table.Header.Cell width="150px">Document ID</Table.Header.Cell>
|
||||
{#each $columns.filter((n) => n.show) as column}
|
||||
{#if column.show}
|
||||
<Table.Header.Cell>{column.title}</Table.Header.Cell>
|
||||
{/if}
|
||||
<Table.Root
|
||||
let:root
|
||||
allowSelection
|
||||
bind:selectedRows
|
||||
columns={[{ id: '$id', width: 150 }, ...$columns, { id: '$created' }, { id: '$updated' }]}>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell column="$id" {root}>Document ID</Table.Header.Cell>
|
||||
{#each $columns as column}
|
||||
<Table.Header.Cell column={column.id} {root}>{column.title}</Table.Header.Cell>
|
||||
{/each}
|
||||
<Table.Header.Cell>Created</Table.Header.Cell>
|
||||
<Table.Header.Cell>Updated</Table.Header.Cell>
|
||||
<Table.Header.Cell column="$created" {root}>Created</Table.Header.Cell>
|
||||
<Table.Header.Cell column="$updated" {root}>Updated</Table.Header.Cell>
|
||||
</svelte:fragment>
|
||||
{#each data.documents.documents as document}
|
||||
<Table.Link
|
||||
<Table.Row.Link
|
||||
{root}
|
||||
id={document.$id}
|
||||
href={`${base}/project-${projectId}/databases/database-${databaseId}/collection-${$collection.$id}/document-${document.$id}`}>
|
||||
<Table.Cell>
|
||||
<Selector.Checkbox size="s" />
|
||||
</Table.Cell>
|
||||
<Table.Cell width="150px">
|
||||
<Table.Cell column="$id" {root}>
|
||||
{#key document.$id}
|
||||
<Id value={document.$id}>
|
||||
{document.$id}
|
||||
@@ -172,96 +172,92 @@
|
||||
{/key}
|
||||
</Table.Cell>
|
||||
|
||||
{#each $columns as column}
|
||||
{#if column.show}
|
||||
{@const attr = $attributes.find((n) => n.key === column.id)}
|
||||
{#each $columns as { id }}
|
||||
{@const attr = $attributes.find((n) => n.key === id)}
|
||||
<Table.Cell column={id} {root}>
|
||||
{#if isRelationship(attr)}
|
||||
{@const args = displayNames?.[attr.relatedCollection] ?? ['$id']}
|
||||
<Table.Cell>
|
||||
{#if !isRelationshipToMany(attr)}
|
||||
{#if document[column.id]}
|
||||
{@const related = document[column.id]}
|
||||
<Link.Button
|
||||
variant="muted"
|
||||
on:click={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
goto(
|
||||
`${base}/project-${projectId}/databases/database-${databaseId}/collection-${attr.relatedCollection}/document-${related.$id}`
|
||||
);
|
||||
}}>
|
||||
{#each args as arg, i}
|
||||
{#if arg !== undefined}
|
||||
{#if i}
|
||||
|
|
||||
{/if}
|
||||
<span class="text" data-private>
|
||||
{related?.[arg]}
|
||||
</span>
|
||||
{/if}
|
||||
{/each}
|
||||
</Link.Button>
|
||||
{:else}
|
||||
<span class="text">n/a</span>
|
||||
{/if}
|
||||
{:else}
|
||||
{@const itemsNum = document[column.id]?.length}
|
||||
<Button.Button
|
||||
variant="extra-compact"
|
||||
disabled={!itemsNum}
|
||||
badge={itemsNum ?? 0}
|
||||
{#if !isRelationshipToMany(attr)}
|
||||
{#if document[+id]}
|
||||
{@const related = document[id]}
|
||||
<Link.Button
|
||||
variant="muted"
|
||||
on:click={(e) => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
relationshipData = document[column.id];
|
||||
showRelationships = true;
|
||||
selectedRelationship = attr;
|
||||
e.stopPropagation();
|
||||
goto(
|
||||
`${base}/project-${projectId}/databases/database-${databaseId}/collection-${attr.relatedCollection}/document-${related.$id}`
|
||||
);
|
||||
}}>
|
||||
Items
|
||||
</Button.Button>
|
||||
{#each args as arg, i}
|
||||
{#if arg !== undefined}
|
||||
{#if i}
|
||||
|
|
||||
{/if}
|
||||
<span class="text" data-private>
|
||||
{related?.[arg]}
|
||||
</span>
|
||||
{/if}
|
||||
{/each}
|
||||
</Link.Button>
|
||||
{:else}
|
||||
<span class="text">n/a</span>
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
{:else}
|
||||
{@const itemsNum = document[id]?.length}
|
||||
<Button.Button
|
||||
variant="extra-compact"
|
||||
disabled={!itemsNum}
|
||||
badge={itemsNum ?? 0}
|
||||
on:click={(e) => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
relationshipData = document[id];
|
||||
showRelationships = true;
|
||||
selectedRelationship = attr;
|
||||
}}>
|
||||
Items
|
||||
</Button.Button>
|
||||
{/if}
|
||||
{:else}
|
||||
{@const formatted = formatColumn(document[column.id])}
|
||||
<Table.Cell>
|
||||
<Tooltip disabled={!formatted.truncated} placement="bottom">
|
||||
<span>
|
||||
{formatted.value}
|
||||
</span>
|
||||
<span style:white-space="pre-wrap" slot="tooltip">
|
||||
{formatted.whole}
|
||||
</span>
|
||||
</Tooltip>
|
||||
</Table.Cell>
|
||||
{@const formatted = formatColumn(document[id])}
|
||||
<Tooltip disabled={!formatted.truncated} placement="bottom">
|
||||
<span>
|
||||
{formatted.value}
|
||||
</span>
|
||||
<span style:white-space="pre-wrap" slot="tooltip">
|
||||
{formatted.whole}
|
||||
</span>
|
||||
</Tooltip>
|
||||
{/if}
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
{/each}
|
||||
<Table.Cell>
|
||||
<Table.Cell column="$created" {root}>
|
||||
{toLocaleDateTime(document.$createdAt)}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="$updated" {root}>
|
||||
{toLocaleDateTime(document.$updatedAt)}
|
||||
</Table.Cell>
|
||||
</Table.Link>
|
||||
</Table.Row.Link>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
|
||||
<RelationshipsModal bind:show={showRelationships} {selectedRelationship} data={relationshipData} />
|
||||
|
||||
<FloatingActionBar show={selectedDb.length > 0}>
|
||||
<FloatingActionBar show={selectedRows.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">{selectedDb.length}</span>
|
||||
<span class="indicator body-text-2 u-bold">{selectedRows.length}</span>
|
||||
<p>
|
||||
<span class="is-only-desktop">
|
||||
{selectedDb.length > 1 ? 'documents' : 'document'}
|
||||
{selectedRows.length > 1 ? 'documents' : 'document'}
|
||||
</span>
|
||||
selected
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="u-flex u-cross-center u-gap-8">
|
||||
<ConsoleButton text on:click={() => (selectedDb = [])}>Cancel</ConsoleButton>
|
||||
<ConsoleButton text on:click={() => (selectedRows = [])}>Cancel</ConsoleButton>
|
||||
<ConsoleButton secondary on:click={() => (showDelete = true)}>
|
||||
<p>Delete</p>
|
||||
</ConsoleButton>
|
||||
@@ -272,20 +268,26 @@
|
||||
<Modal title="Delete Documents" bind:show={showDelete} onSubmit={handleDelete} closable={!deleting}>
|
||||
<div>
|
||||
<p class="text" data-private>
|
||||
Are you sure you want to delete <b>{selectedDb.length}</b>
|
||||
{selectedDb.length > 1 ? 'documents' : 'document'}?
|
||||
Are you sure you want to delete <b>{selectedRows.length}</b>
|
||||
{selectedRows.length > 1 ? 'documents' : 'document'}?
|
||||
</p>
|
||||
|
||||
{#if relAttributes?.length}
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell width="50px">Relation</Table.Header.Cell>
|
||||
<Table.Header.Cell width="50px">Setting</Table.Header.Cell>
|
||||
<Table.Header.Cell />
|
||||
<Table.Root
|
||||
let:root
|
||||
columns={[
|
||||
{ id: 'relation', width: 150 },
|
||||
{ id: 'setting', width: 150 },
|
||||
{ id: 'desc' }
|
||||
]}>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell column="relation" {root}>Relation</Table.Header.Cell>
|
||||
<Table.Header.Cell column="setting" {root}>Setting</Table.Header.Cell>
|
||||
<Table.Header.Cell column="desc" {root} />
|
||||
</svelte:fragment>
|
||||
{#each relAttributes as attr}
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell column="relation" {root}>
|
||||
<span class="u-flex u-cross-center u-gap-8">
|
||||
{#if attr.twoWay}
|
||||
<span class="icon-switch-horizontal" />
|
||||
@@ -295,13 +297,13 @@
|
||||
<span data-private>{attr.key}</span>
|
||||
</span>
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="setting" {root}>
|
||||
{attr.onDelete}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="desc" {root}>
|
||||
{Deletion[attr.onDelete]}
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
<div class="u-flex u-flex-vertical u-gap-16">
|
||||
@@ -326,28 +328,3 @@
|
||||
</ConsoleButton>
|
||||
</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;
|
||||
}
|
||||
}
|
||||
|
||||
:global(.truncated-content-table-cell .truncated) {
|
||||
max-width: 50vw;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
display: inline-block;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
:global(.truncated-content-table-cell:has(.truncated)) {
|
||||
inline-size: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -109,16 +109,16 @@
|
||||
</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>
|
||||
<Table.Root columns={2} let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell {root}>Collection</Table.Header.Cell>
|
||||
<Table.Header.Cell {root}>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>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell {root}>{collection.name}</Table.Cell>
|
||||
<Table.Cell {root}>{toLocaleDate(collection.updatedAt)}</Table.Cell>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
|
||||
|
||||
@@ -7,10 +7,10 @@ export const database = derived(page, ($page) => $page.data.database as Models.D
|
||||
export const showCreate = writable(false);
|
||||
|
||||
export const columns = writable<Column[]>([
|
||||
{ id: '$id', title: 'Collection ID', type: 'string', show: true, width: 150 },
|
||||
{ id: 'name', title: 'Name', type: 'string', show: true, width: 120 },
|
||||
{ id: '$createdAt', title: 'Created', type: 'datetime', show: true, width: 120 },
|
||||
{ id: '$updatedAt', title: 'Updated', type: 'datetime', show: true, width: 120 }
|
||||
{ id: '$id', title: 'Collection ID', type: 'string', width: 150 },
|
||||
{ id: 'name', title: 'Name', type: 'string', width: { min: 120 } },
|
||||
{ id: '$createdAt', title: 'Created', type: 'datetime', width: { min: 120 } },
|
||||
{ id: '$updatedAt', title: 'Updated', type: 'datetime', width: { min: 120 } }
|
||||
]);
|
||||
|
||||
export const backupRetainingOptions = [
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
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 { Badge, Table } from '@appwrite.io/pink-svelte';
|
||||
import type { PageData } from './$types';
|
||||
import { columns } from './store';
|
||||
|
||||
@@ -19,14 +19,14 @@
|
||||
const projectId = $page.params.project;
|
||||
const databaseId = $page.params.database;
|
||||
|
||||
let selected: string[] = [];
|
||||
let selectedRows: string[] = [];
|
||||
let showDelete = false;
|
||||
let deleting = false;
|
||||
|
||||
async function handleDelete() {
|
||||
showDelete = false;
|
||||
|
||||
const promises = selected.map((collectionId) =>
|
||||
const promises = selectedRows.map((collectionId) =>
|
||||
sdk.forProject.databases.deleteCollection(databaseId, collectionId)
|
||||
);
|
||||
try {
|
||||
@@ -34,7 +34,7 @@
|
||||
trackEvent(Submit.CollectionDelete);
|
||||
addNotification({
|
||||
type: 'success',
|
||||
message: `${selected.length} collection${selected.length > 1 ? 's' : ''} deleted`
|
||||
message: `${selectedRows.length} collection${selectedRows.length > 1 ? 's' : ''} deleted`
|
||||
});
|
||||
invalidate(Dependencies.COLLECTIONS);
|
||||
} catch (error) {
|
||||
@@ -44,67 +44,52 @@
|
||||
});
|
||||
trackError(error, Submit.CollectionDelete);
|
||||
} finally {
|
||||
selected = [];
|
||||
selectedRows = [];
|
||||
showDelete = false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
{#if $canWriteCollections}
|
||||
<Table.Header.Selector width="20px" />
|
||||
{/if}
|
||||
{#each $columns as column}
|
||||
{#if column.show}
|
||||
<Table.Header.Cell width={column.width + 'px'}>{column.title}</Table.Header.Cell>
|
||||
{/if}
|
||||
<Table.Root columns={$columns} allowSelection={$canWriteCollections} bind:selectedRows let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
{#each $columns as { id, title }}
|
||||
<Table.Header.Cell column={id} {root}>{title}</Table.Header.Cell>
|
||||
{/each}
|
||||
</svelte:fragment>
|
||||
{#each data.collections.collections as collection (collection.$id)}
|
||||
<Table.Link
|
||||
<Table.Row.Link
|
||||
{root}
|
||||
id={collection.$id}
|
||||
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}
|
||||
<Table.Cell column={column.id} {root}>
|
||||
{#if column.id === '$id'}
|
||||
{#key $columns}
|
||||
<Table.Cell>
|
||||
<Id value={collection.$id}>{collection.$id}</Id>
|
||||
</Table.Cell>
|
||||
<Id value={collection.$id}>{collection.$id}</Id>
|
||||
{/key}
|
||||
{:else if column.id === 'name'}
|
||||
<Table.Cell>
|
||||
{collection.name}
|
||||
</Table.Cell>
|
||||
{collection.name}
|
||||
{:else}
|
||||
<Table.Cell>
|
||||
{toLocaleDateTime(collection[column.id])}
|
||||
</Table.Cell>
|
||||
{toLocaleDateTime(collection[column.id])}
|
||||
{/if}
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
{/each}
|
||||
</Table.Link>
|
||||
</Table.Row.Link>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
|
||||
<FloatingActionBar show={selected.length > 0}>
|
||||
<FloatingActionBar show={selectedRows.length > 0}>
|
||||
<svelte:fragment slot="start">
|
||||
<Badge content={selected.length.toString()} />
|
||||
<Badge content={selectedRows.length.toString()} />
|
||||
<span>
|
||||
<span class="is-only-desktop">
|
||||
{selected.length > 1 ? 'collections' : 'collection'}
|
||||
{selectedRows.length > 1 ? 'collections' : 'collection'}
|
||||
</span>
|
||||
selected
|
||||
</span>
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="end">
|
||||
<Button text on:click={() => (selected = [])}>Cancel</Button>
|
||||
<Button text on:click={() => (selectedRows = [])}>Cancel</Button>
|
||||
<Button secondary on:click={() => (showDelete = true)}>Delete</Button>
|
||||
</svelte:fragment>
|
||||
</FloatingActionBar>
|
||||
@@ -115,8 +100,8 @@
|
||||
onSubmit={handleDelete}
|
||||
closable={!deleting}>
|
||||
<p class="text" data-private>
|
||||
Are you sure you want to delete <b>{selected.length}</b>
|
||||
{selected.length > 1 ? 'collections' : 'collection'}?
|
||||
Are you sure you want to delete <b>{selectedRows.length}</b>
|
||||
{selectedRows.length > 1 ? 'collections' : 'collection'}?
|
||||
</p>
|
||||
<svelte:fragment slot="footer">
|
||||
<Button text on:click={() => (showDelete = false)} disabled={deleting}>Cancel</Button>
|
||||
|
||||
@@ -5,16 +5,16 @@ import { writable } from 'svelte/store';
|
||||
export const columns = writable<Column[]>(
|
||||
isCloud
|
||||
? [
|
||||
{ id: '$id', title: 'Database ID', type: 'string', show: true, width: 150 },
|
||||
{ id: 'name', title: 'Name', type: 'string', show: true, width: 120 },
|
||||
{ id: 'backup', title: 'Backups', type: 'string', show: true, width: 120 },
|
||||
{ id: '$createdAt', title: 'Created', type: 'datetime', show: true, width: 120 },
|
||||
{ id: '$updatedAt', title: 'Updated', type: 'datetime', show: true, width: 120 }
|
||||
{ id: '$id', title: 'Database ID', type: 'string', width: 150 },
|
||||
{ id: 'name', title: 'Name', type: 'string', width: { min: 120 } },
|
||||
{ id: 'backup', title: 'Backups', type: 'string', width: { min: 120 } },
|
||||
{ id: '$createdAt', title: 'Created', type: 'datetime', width: { min: 120 } },
|
||||
{ id: '$updatedAt', title: 'Updated', type: 'datetime', width: { min: 120 } }
|
||||
]
|
||||
: [
|
||||
{ id: '$id', title: 'Database ID', type: 'string', show: true, width: 150 },
|
||||
{ id: 'name', title: 'Name', type: 'string', show: true, width: 120 },
|
||||
{ id: '$createdAt', title: 'Created', type: 'datetime', show: true, width: 120 },
|
||||
{ id: '$updatedAt', title: 'Updated', type: 'datetime', show: true, width: 120 }
|
||||
{ id: '$id', title: 'Database ID', type: 'string', width: 150 },
|
||||
{ id: 'name', title: 'Name', type: 'string', width: { min: 120 } },
|
||||
{ id: '$createdAt', title: 'Created', type: 'datetime', width: { min: 120 } },
|
||||
{ id: '$updatedAt', title: 'Updated', type: 'datetime', width: { min: 120 } }
|
||||
]
|
||||
);
|
||||
|
||||
@@ -20,30 +20,26 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
{#each $columns as column}
|
||||
{#if column.show}
|
||||
<Table.Header.Cell width={column.width}>{column.title}</Table.Header.Cell>
|
||||
{/if}
|
||||
<Table.Root columns={$columns} let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
{#each $columns as { id, title }}
|
||||
<Table.Header.Cell column={id} {root}>{title}</Table.Header.Cell>
|
||||
{/each}
|
||||
</svelte:fragment>
|
||||
{#each data.databases.databases as database (database.$id)}
|
||||
<Table.Link href={`${base}/project-${projectId}/databases/database-${database.$id}`}>
|
||||
<Table.Row.Link
|
||||
{root}
|
||||
href={`${base}/project-${projectId}/databases/database-${database.$id}`}>
|
||||
{#each $columns as column}
|
||||
{#if column.show}
|
||||
<Table.Cell column={column.id} {root}>
|
||||
{#if column.id === '$id'}
|
||||
{#key $columns}
|
||||
<Table.Cell width={column.width + 'px'}>
|
||||
<Id value={database.$id}>
|
||||
{database.$id}
|
||||
</Id>
|
||||
</Table.Cell>
|
||||
<Id value={database.$id}>
|
||||
{database.$id}
|
||||
</Id>
|
||||
{/key}
|
||||
{:else if column.id === 'name'}
|
||||
<Table.Cell width={column.width + 'px'}>
|
||||
{database.name}
|
||||
</Table.Cell>
|
||||
{database.name}
|
||||
{:else if column.id === 'backup'}
|
||||
{@const policies = data.policies?.[database.$id] ?? null}
|
||||
{@const lastBackup = data.lastBackups?.[database.$id] ?? null}
|
||||
@@ -51,31 +47,21 @@
|
||||
?.map((policy) => getPolicyDescription(policy.schedule))
|
||||
.join(', ')}
|
||||
|
||||
<Table.Cell width={column.width + 'px'}>
|
||||
<Tooltip placement="bottom" disabled={!policies || !lastBackup}>
|
||||
<span class="u-trim">
|
||||
{#if !policies}
|
||||
<span class="icon-exclamation" /> No backup policies
|
||||
{:else}
|
||||
{description}
|
||||
{/if}
|
||||
</span>
|
||||
<span slot="tooltip">{`Last backup: ${lastBackup}`}</span>
|
||||
</Tooltip>
|
||||
</Table.Cell>
|
||||
<Tooltip placement="bottom" disabled={!policies || !lastBackup}>
|
||||
<span class="u-trim">
|
||||
{#if !policies}
|
||||
<span class="icon-exclamation" /> No backup policies
|
||||
{:else}
|
||||
{description}
|
||||
{/if}
|
||||
</span>
|
||||
<span slot="tooltip">{`Last backup: ${lastBackup}`}</span>
|
||||
</Tooltip>
|
||||
{:else}
|
||||
<Table.Cell width={column.width + 'px'}>
|
||||
{toLocaleDateTime(database[column.id])}
|
||||
</Table.Cell>
|
||||
{toLocaleDateTime(database[column.id])}
|
||||
{/if}
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
{/each}
|
||||
</Table.Link>
|
||||
</Table.Row.Link>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
|
||||
<style lang="scss">
|
||||
.icon-exclamation {
|
||||
color: hsl(var(--color-warning-100)) !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
+53
-48
@@ -67,16 +67,23 @@
|
||||
</Layout.Stack>
|
||||
|
||||
{#if data.domains.total}
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell width="200px">Domain</Table.Header.Cell>
|
||||
<Table.Header.Cell>Redirect to</Table.Header.Cell>
|
||||
<Table.Header.Cell>Production branch</Table.Header.Cell>
|
||||
<Table.Header.Cell />
|
||||
<Table.Root
|
||||
let:root
|
||||
columns={[
|
||||
{ id: 'domain', width: { min: 200 } },
|
||||
{ id: 'redirect' },
|
||||
{ id: 'branch' },
|
||||
{ id: 'actions', width: 40 }
|
||||
]}>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell column="domain" {root}>Domain</Table.Header.Cell>
|
||||
<Table.Header.Cell column="redirect" {root}>Redirect to</Table.Header.Cell>
|
||||
<Table.Header.Cell column="branch" {root}>Production branch</Table.Header.Cell>
|
||||
<Table.Header.Cell column="actions" {root} />
|
||||
</svelte:fragment>
|
||||
{#each data.domains.rules as domain}
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell column="domain" {root}>
|
||||
<Link external href={`${$protocol}${domain.domain}`} variant="quiet">
|
||||
<Layout.Stack direction="row" alignItems="center" gap="xs">
|
||||
{domain.domain}
|
||||
@@ -84,60 +91,58 @@
|
||||
</Layout.Stack>
|
||||
</Link>
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="redirect" {root}>
|
||||
{domain?.redirectUrl || 'No redirect'}
|
||||
{domain?.redirectStatusCode ? `(${domain.redirectStatusCode})` : ''}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="branch" {root}>
|
||||
{domain.deploymentVcsProviderBranch || '-'}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Layout.Stack direction="row" justifyContent="flex-end">
|
||||
<Popover let:toggle placement="bottom-start" padding="none">
|
||||
<Button
|
||||
text
|
||||
icon
|
||||
on:click={(e) => {
|
||||
e.preventDefault();
|
||||
toggle(e);
|
||||
}}>
|
||||
<Icon icon={IconDotsHorizontal} size="s" />
|
||||
</Button>
|
||||
<Table.Cell column="actions" {root}>
|
||||
<Popover let:toggle placement="bottom-start" padding="none">
|
||||
<Button
|
||||
text
|
||||
icon
|
||||
on:click={(e) => {
|
||||
e.preventDefault();
|
||||
toggle(e);
|
||||
}}>
|
||||
<Icon icon={IconDotsHorizontal} size="s" />
|
||||
</Button>
|
||||
|
||||
<svelte:fragment slot="tooltip" let:toggle>
|
||||
<ActionMenu.Root>
|
||||
{#if domain.status !== 'verified'}
|
||||
<ActionMenu.Item.Button
|
||||
leadingIcon={IconRefresh}
|
||||
on:click={(e) => {
|
||||
e.preventDefault();
|
||||
selectedDomain = domain;
|
||||
showRetry = true;
|
||||
toggle(e);
|
||||
}}>
|
||||
Retry
|
||||
</ActionMenu.Item.Button>
|
||||
{/if}
|
||||
<svelte:fragment slot="tooltip" let:toggle>
|
||||
<ActionMenu.Root>
|
||||
{#if domain.status !== 'verified'}
|
||||
<ActionMenu.Item.Button
|
||||
status="danger"
|
||||
leadingIcon={IconTrash}
|
||||
leadingIcon={IconRefresh}
|
||||
on:click={(e) => {
|
||||
e.preventDefault();
|
||||
selectedDomain = domain;
|
||||
showDelete = true;
|
||||
showRetry = true;
|
||||
toggle(e);
|
||||
trackEvent(Click.DomainDeleteClick, {
|
||||
source: 'functions_domain_overview'
|
||||
});
|
||||
}}>
|
||||
Delete
|
||||
Retry
|
||||
</ActionMenu.Item.Button>
|
||||
</ActionMenu.Root>
|
||||
</svelte:fragment>
|
||||
</Popover>
|
||||
</Layout.Stack>
|
||||
{/if}
|
||||
<ActionMenu.Item.Button
|
||||
status="danger"
|
||||
leadingIcon={IconTrash}
|
||||
on:click={(e) => {
|
||||
e.preventDefault();
|
||||
selectedDomain = domain;
|
||||
showDelete = true;
|
||||
toggle(e);
|
||||
trackEvent(Click.DomainDeleteClick, {
|
||||
source: 'functions_domain_overview'
|
||||
});
|
||||
}}>
|
||||
Delete
|
||||
</ActionMenu.Item.Button>
|
||||
</ActionMenu.Root>
|
||||
</svelte:fragment>
|
||||
</Popover>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
|
||||
|
||||
+18
-18
@@ -94,23 +94,23 @@
|
||||
</Typography.Text>
|
||||
</Layout.Stack>
|
||||
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Type</Table.Header.Cell>
|
||||
<Table.Header.Cell>Name</Table.Header.Cell>
|
||||
<Table.Header.Cell>Value</Table.Header.Cell>
|
||||
<Table.Root columns={3} let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell {root}>Type</Table.Header.Cell>
|
||||
<Table.Header.Cell {root}>Name</Table.Header.Cell>
|
||||
<Table.Header.Cell {root}>Value</Table.Header.Cell>
|
||||
</svelte:fragment>
|
||||
<Table.Row>
|
||||
<Table.Cell>CNAME</Table.Cell>
|
||||
<Table.Cell>{data.domain?.domain}</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell {root}>CNAME</Table.Cell>
|
||||
<Table.Cell {root}>{data.domain?.domain}</Table.Cell>
|
||||
<Table.Cell {root}>
|
||||
<InteractiveText
|
||||
variant="copy"
|
||||
isVisible
|
||||
text={globalThis?.location?.origin}>
|
||||
{globalThis?.location?.origin}</InteractiveText>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
</Table.Root>
|
||||
<Layout.Stack gap="s" direction="row" alignItems="center">
|
||||
<Icon icon={IconInfo} size="s" color="--fgcolor-neutral-secondary" />
|
||||
@@ -145,19 +145,19 @@
|
||||
</Typography.Text>
|
||||
</Layout.Stack>
|
||||
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Type</Table.Header.Cell>
|
||||
<Table.Header.Cell>Value</Table.Header.Cell>
|
||||
<Table.Root columns={2} let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell {root}>Type</Table.Header.Cell>
|
||||
<Table.Header.Cell {root}>Value</Table.Header.Cell>
|
||||
</svelte:fragment>
|
||||
{#each nameservers as nameserver}
|
||||
<Table.Row>
|
||||
<Table.Cell>NS</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell {root}>NS</Table.Cell>
|
||||
<Table.Cell {root}>
|
||||
<InteractiveText variant="copy" isVisible text={nameserver}>
|
||||
{nameserver}</InteractiveText>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
<!-- <Layout.Stack gap="s" direction="row" alignItems="center">
|
||||
|
||||
+10
-10
@@ -22,20 +22,20 @@
|
||||
</Typography.Text>
|
||||
</Layout.Stack>
|
||||
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Type</Table.Header.Cell>
|
||||
<Table.Header.Cell>Name</Table.Header.Cell>
|
||||
<Table.Header.Cell>Value</Table.Header.Cell>
|
||||
<Table.Root columns={3} let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell {root}>Type</Table.Header.Cell>
|
||||
<Table.Header.Cell {root}>Name</Table.Header.Cell>
|
||||
<Table.Header.Cell {root}>Value</Table.Header.Cell>
|
||||
</svelte:fragment>
|
||||
<Table.Row>
|
||||
<Table.Cell>CNAME</Table.Cell>
|
||||
<Table.Cell>{domain?.domain}</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell {root}>CNAME</Table.Cell>
|
||||
<Table.Cell {root}>{domain?.domain}</Table.Cell>
|
||||
<Table.Cell {root}>
|
||||
<Copy value={globalThis?.location?.origin}
|
||||
>{globalThis?.location?.origin}</Copy>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
</Table.Root>
|
||||
<Layout.Stack gap="s" direction="row" alignItems="center">
|
||||
<Icon icon={IconInfo} size="s" color="--fgcolor-neutral-secondary" />
|
||||
|
||||
+16
-16
@@ -67,16 +67,16 @@
|
||||
</Layout.Stack>
|
||||
{#if requestTab === 'parameters'}
|
||||
{#if parameters?.length}
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Key</Table.Header.Cell>
|
||||
<Table.Header.Cell>Value</Table.Header.Cell>
|
||||
<Table.Root columns={2} let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell {root}>Key</Table.Header.Cell>
|
||||
<Table.Header.Cell {root}>Value</Table.Header.Cell>
|
||||
</svelte:fragment>
|
||||
{#each parameters as parameter}
|
||||
<Table.Row>
|
||||
<Table.Cell>{parameter.name}</Table.Cell>
|
||||
<Table.Cell>{parameter.value}</Table.Cell>
|
||||
</Table.Row>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell {root}>{parameter.name}</Table.Cell>
|
||||
<Table.Cell {root}>{parameter.value}</Table.Cell>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
{:else}
|
||||
@@ -86,16 +86,16 @@
|
||||
{/if}
|
||||
{:else if requestTab === 'headers'}
|
||||
{#if selectedLog.requestHeaders?.length}
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Key</Table.Header.Cell>
|
||||
<Table.Header.Cell>Value</Table.Header.Cell>
|
||||
<Table.Root columns={2} let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell {root}>Key</Table.Header.Cell>
|
||||
<Table.Header.Cell {root}>Value</Table.Header.Cell>
|
||||
</svelte:fragment>
|
||||
{#each selectedLog.requestHeaders as request}
|
||||
<Table.Row>
|
||||
<Table.Cell>{request.name}</Table.Cell>
|
||||
<Table.Cell>{request.value}</Table.Cell>
|
||||
</Table.Row>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell {root}>{request.name}</Table.Cell>
|
||||
<Table.Cell {root}>{request.value}</Table.Cell>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
|
||||
|
||||
+8
-8
@@ -81,16 +81,16 @@
|
||||
{/if}
|
||||
{:else if responseTab === 'headers'}
|
||||
{#if selectedLog.responseHeaders?.length}
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Key</Table.Header.Cell>
|
||||
<Table.Header.Cell>Value</Table.Header.Cell>
|
||||
<Table.Root columns={2} let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell {root}>Key</Table.Header.Cell>
|
||||
<Table.Header.Cell {root}>Value</Table.Header.Cell>
|
||||
</svelte:fragment>
|
||||
{#each selectedLog.responseHeaders as request}
|
||||
<Table.Row>
|
||||
<Table.Cell>{request.name}</Table.Cell>
|
||||
<Table.Cell>{request.value}</Table.Cell>
|
||||
</Table.Row>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell {root}>{request.name}</Table.Cell>
|
||||
<Table.Cell {root}>{request.value}</Table.Cell>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
|
||||
|
||||
+7
-14
@@ -2,12 +2,11 @@ import type { Column } from '$lib/helpers/types';
|
||||
import { writable } from 'svelte/store';
|
||||
|
||||
export const columns = writable<Column[]>([
|
||||
{ id: '$id', title: 'Execution ID', type: 'string', show: true, width: 150 },
|
||||
{ id: '$id', title: 'Execution ID', type: 'string', width: 150 },
|
||||
{
|
||||
id: 'requestPath',
|
||||
title: 'Path',
|
||||
type: 'string',
|
||||
show: true,
|
||||
width: 90,
|
||||
format: 'string'
|
||||
},
|
||||
@@ -16,7 +15,7 @@ export const columns = writable<Column[]>([
|
||||
id: 'trigger',
|
||||
title: 'Trigger',
|
||||
type: 'string',
|
||||
show: false,
|
||||
hide: true,
|
||||
width: 90,
|
||||
array: true,
|
||||
format: 'enum',
|
||||
@@ -24,25 +23,23 @@ export const columns = writable<Column[]>([
|
||||
{ value: 'http', label: 'HTTP' },
|
||||
{ value: 'schedule', label: 'Schedule' },
|
||||
{ value: 'event', label: 'Event' }
|
||||
],
|
||||
hide: true
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'requestMethod',
|
||||
title: 'Method',
|
||||
type: 'string',
|
||||
show: false,
|
||||
hide: true,
|
||||
width: 70,
|
||||
array: true,
|
||||
format: 'enum',
|
||||
elements: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],
|
||||
hide: true
|
||||
elements: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE']
|
||||
},
|
||||
{
|
||||
id: 'responseStatusCode',
|
||||
title: 'Status code',
|
||||
type: 'integer',
|
||||
show: false,
|
||||
hide: true,
|
||||
width: 100,
|
||||
format: 'integer',
|
||||
elements: [
|
||||
@@ -62,15 +59,13 @@ export const columns = writable<Column[]>([
|
||||
value: 599,
|
||||
label: 'Server error (500-599)'
|
||||
}
|
||||
],
|
||||
hide: true
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
id: 'status',
|
||||
title: 'Status',
|
||||
type: 'enum',
|
||||
show: true,
|
||||
width: 130,
|
||||
array: true,
|
||||
format: 'enum',
|
||||
@@ -80,7 +75,6 @@ export const columns = writable<Column[]>([
|
||||
id: 'duration',
|
||||
title: 'Duration',
|
||||
type: 'integer',
|
||||
show: true,
|
||||
width: 80,
|
||||
format: 'integer',
|
||||
elements: [
|
||||
@@ -102,7 +96,6 @@ export const columns = writable<Column[]>([
|
||||
id: '$createdAt',
|
||||
title: 'Created',
|
||||
type: 'datetime',
|
||||
show: true,
|
||||
width: 120,
|
||||
format: 'datetime',
|
||||
elements: [
|
||||
|
||||
+44
-57
@@ -16,81 +16,68 @@
|
||||
let selectedLogId: string = null;
|
||||
</script>
|
||||
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
{#each columns as column}
|
||||
{#if column.show && !column.hide}
|
||||
<Table.Header.Cell width={column.width + 'px'}>{column.title}</Table.Header.Cell>
|
||||
{/if}
|
||||
<Table.Root {columns} let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
{#each columns as { id, title }}
|
||||
<Table.Header.Cell column={id} {root}>{title}</Table.Header.Cell>
|
||||
{/each}
|
||||
</svelte:fragment>
|
||||
{#each logs.executions as log}
|
||||
<Table.Button
|
||||
<Table.Row.Button
|
||||
{root}
|
||||
on:click={() => {
|
||||
openSheet = true;
|
||||
selectedLogId = log.$id;
|
||||
}}>
|
||||
{#each columns as column}
|
||||
{#if column.show && !column.hide}
|
||||
<Table.Cell column={column.id} {root}>
|
||||
{#if column.id === '$id'}
|
||||
{#key column.id}
|
||||
<Table.Cell>
|
||||
<Id value={log.$id}>{log.$id}</Id>
|
||||
</Table.Cell>
|
||||
<Id value={log.$id}>{log.$id}</Id>
|
||||
{/key}
|
||||
{:else if column.id === '$createdAt'}
|
||||
<Table.Cell>
|
||||
{capitalize(timeFromNow(log.$createdAt))}
|
||||
</Table.Cell>
|
||||
{capitalize(timeFromNow(log.$createdAt))}
|
||||
{:else if column.id === 'requestPath'}
|
||||
<Table.Cell>
|
||||
<Layout.Stack direction="row" alignItems="center" gap="s">
|
||||
<Badge
|
||||
variant="secondary"
|
||||
type={log.responseStatusCode >= 400
|
||||
? 'error'
|
||||
: log.responseStatusCode === 0
|
||||
? undefined
|
||||
: 'success'}
|
||||
content={log.responseStatusCode.toString()} />
|
||||
<Typography.Code size="m">
|
||||
{log.requestMethod}
|
||||
</Typography.Code>
|
||||
<Typography.Code size="m">
|
||||
{log.requestPath}
|
||||
</Typography.Code>
|
||||
</Layout.Stack>
|
||||
</Table.Cell>
|
||||
<Layout.Stack direction="row" alignItems="center" gap="s">
|
||||
<Badge
|
||||
variant="secondary"
|
||||
type={log.responseStatusCode >= 400
|
||||
? 'error'
|
||||
: log.responseStatusCode === 0
|
||||
? undefined
|
||||
: 'success'}
|
||||
content={log.responseStatusCode.toString()} />
|
||||
<Typography.Code size="m">
|
||||
{log.requestMethod}
|
||||
</Typography.Code>
|
||||
<Typography.Code size="m">
|
||||
{log.requestPath}
|
||||
</Typography.Code>
|
||||
</Layout.Stack>
|
||||
{:else if column.id === 'responseStatusCode'}
|
||||
<Table.Cell>
|
||||
{log.responseStatusCode}
|
||||
</Table.Cell>
|
||||
{log.responseStatusCode}
|
||||
{:else if column.id === 'status'}
|
||||
<Table.Cell>
|
||||
{@const status = log.status}
|
||||
<Tooltip
|
||||
disabled={!log?.scheduledAt || status !== 'scheduled'}
|
||||
maxWidth="400px">
|
||||
<div>
|
||||
<Status
|
||||
status={logStatusConverter(status)}
|
||||
label={capitalize(status)}>
|
||||
{status}
|
||||
</Status>
|
||||
</div>
|
||||
<span slot="tooltip">
|
||||
{`Scheduled to execute on ${toLocaleDateTime(log.scheduledAt)}`}
|
||||
</span>
|
||||
</Tooltip>
|
||||
</Table.Cell>
|
||||
{@const status = log.status}
|
||||
<Tooltip
|
||||
disabled={!log?.scheduledAt || status !== 'scheduled'}
|
||||
maxWidth="400px">
|
||||
<div>
|
||||
<Status
|
||||
status={logStatusConverter(status)}
|
||||
label={capitalize(status)}>
|
||||
{status}
|
||||
</Status>
|
||||
</div>
|
||||
<span slot="tooltip">
|
||||
{`Scheduled to execute on ${toLocaleDateTime(log.scheduledAt)}`}
|
||||
</span>
|
||||
</Tooltip>
|
||||
{:else if column.id === 'duration'}
|
||||
<Table.Cell>
|
||||
{formatTimeDetailed(log.duration)}
|
||||
</Table.Cell>
|
||||
{formatTimeDetailed(log.duration)}
|
||||
{/if}
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
{/each}
|
||||
</Table.Button>
|
||||
</Table.Row.Button>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
|
||||
|
||||
+4
-4
@@ -92,10 +92,10 @@
|
||||
Set the events that will trigger your function. Maximum 100 events allowed.
|
||||
<svelte:fragment slot="aside">
|
||||
{#if $eventSet.size}
|
||||
<Table.Root>
|
||||
<Table.Root columns={1} let:root>
|
||||
{#each Array.from($eventSet) as event}
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell {root}>
|
||||
<Layout.Stack
|
||||
direction="row"
|
||||
justifyContent="space-between"
|
||||
@@ -112,7 +112,7 @@
|
||||
</Button>
|
||||
</Layout.Stack>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
<div>
|
||||
|
||||
@@ -26,12 +26,11 @@ export const repositories: Writable<{
|
||||
export const showCreateDeployment: Writable<boolean> = writable(false);
|
||||
|
||||
export const columns = writable<Column[]>([
|
||||
{ id: '$id', title: 'Deployment ID', type: 'string', show: true, width: 150 },
|
||||
{ id: '$id', title: 'Deployment ID', type: 'string', width: 150 },
|
||||
{
|
||||
id: 'status',
|
||||
title: 'Status',
|
||||
type: 'enum',
|
||||
show: true,
|
||||
width: 110,
|
||||
array: true,
|
||||
format: 'enum',
|
||||
@@ -42,7 +41,6 @@ export const columns = writable<Column[]>([
|
||||
id: 'buildDuration',
|
||||
title: 'Build duration',
|
||||
type: 'integer',
|
||||
show: true,
|
||||
width: 90,
|
||||
elements: [
|
||||
{
|
||||
@@ -64,7 +62,6 @@ export const columns = writable<Column[]>([
|
||||
id: 'sourceSize',
|
||||
title: 'Source size',
|
||||
type: 'integer',
|
||||
show: true,
|
||||
width: 140,
|
||||
elements: [
|
||||
{
|
||||
@@ -85,7 +82,7 @@ export const columns = writable<Column[]>([
|
||||
id: 'buildSize',
|
||||
title: 'Build size',
|
||||
type: 'integer',
|
||||
show: false,
|
||||
hide: true,
|
||||
filter: false,
|
||||
width: 80
|
||||
},
|
||||
@@ -93,7 +90,6 @@ export const columns = writable<Column[]>([
|
||||
id: 'type',
|
||||
title: 'Source',
|
||||
type: 'string',
|
||||
show: true,
|
||||
width: 90,
|
||||
array: true,
|
||||
format: 'enum',
|
||||
@@ -107,7 +103,6 @@ export const columns = writable<Column[]>([
|
||||
id: '$updatedAt',
|
||||
title: 'Updated',
|
||||
type: 'datetime',
|
||||
show: true,
|
||||
width: 150,
|
||||
format: 'datetime'
|
||||
}
|
||||
|
||||
+83
-105
@@ -46,140 +46,118 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
{#each columns as column}
|
||||
{#if column.show}
|
||||
<Table.Header.Cell width={column.width.toString()}>
|
||||
{column.title}
|
||||
</Table.Header.Cell>
|
||||
{/if}
|
||||
<Table.Root columns={[...columns, { id: 'actions', width: 40 }]} let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
{#each columns as { id, title }}
|
||||
<Table.Header.Cell column={id} {root}>
|
||||
{title}
|
||||
</Table.Header.Cell>
|
||||
{/each}
|
||||
<Table.Header.Cell width="40" />
|
||||
<Table.Header.Cell column="actions" {root} />
|
||||
</svelte:fragment>
|
||||
{#each data.deploymentList.deployments as deployment (deployment.$id)}
|
||||
<Table.Link
|
||||
<Table.Row.Link
|
||||
{root}
|
||||
href={`${base}/project-${$page.params.project}/functions/function-${$page.params.function}/deployment-${deployment.$id}`}>
|
||||
{#each columns as column}
|
||||
{#if column.show}
|
||||
<Table.Cell column={column.id} {root}>
|
||||
{#if column.id === '$id'}
|
||||
{#key column.id}
|
||||
<Table.Cell>
|
||||
<Id value={deployment.$id}>{deployment.$id}</Id>
|
||||
</Table.Cell>
|
||||
<Id value={deployment.$id}>{deployment.$id}</Id>
|
||||
{/key}
|
||||
{:else if column.id === 'status'}
|
||||
<Table.Cell>
|
||||
{@const status = deployment.status}
|
||||
{@const status = deployment.status}
|
||||
|
||||
{#if data?.activeDeployment?.$id === deployment?.$id}
|
||||
<Status status="complete" label="Active" />
|
||||
{:else}
|
||||
<Status
|
||||
status={deploymentStatusConverter(status)}
|
||||
label={capitalize(status)} />
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
{#if data?.activeDeployment?.$id === deployment?.$id}
|
||||
<Status status="complete" label="Active" />
|
||||
{:else}
|
||||
<Status
|
||||
status={deploymentStatusConverter(status)}
|
||||
label={capitalize(status)} />
|
||||
{/if}
|
||||
{:else if column.id === 'type'}
|
||||
<Table.Cell>
|
||||
<DeploymentSource {deployment} />
|
||||
</Table.Cell>
|
||||
<DeploymentSource {deployment} />
|
||||
{:else if column.id === '$updatedAt'}
|
||||
<Table.Cell>
|
||||
<DeploymentCreatedBy {deployment} />
|
||||
</Table.Cell>
|
||||
<DeploymentCreatedBy {deployment} />
|
||||
{:else if column.id === 'buildDuration'}
|
||||
<Table.Cell>
|
||||
{#if ['waiting'].includes(deployment.status)}
|
||||
-
|
||||
{:else if ['processing', 'building'].includes(deployment.status)}
|
||||
<span use:timer={{ start: deployment.$createdAt }} />
|
||||
{:else}
|
||||
{formatTimeDetailed(deployment.buildDuration)}
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
{#if ['waiting'].includes(deployment.status)}
|
||||
-
|
||||
{:else if ['processing', 'building'].includes(deployment.status)}
|
||||
<span use:timer={{ start: deployment.$createdAt }} />
|
||||
{:else}
|
||||
{formatTimeDetailed(deployment.buildDuration)}
|
||||
{/if}
|
||||
{:else if column.id === 'sourceSize'}
|
||||
<Table.Cell>
|
||||
{calculateSize(deployment.sourceSize)}
|
||||
</Table.Cell>
|
||||
{calculateSize(deployment.sourceSize)}
|
||||
{:else if column.id === 'buildSize'}
|
||||
<Table.Cell>
|
||||
{calculateSize(deployment.buildSize)}
|
||||
</Table.Cell>
|
||||
{calculateSize(deployment.buildSize)}
|
||||
{/if}
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
{/each}
|
||||
<Table.Cell>
|
||||
<Layout.Stack
|
||||
direction="row"
|
||||
gap="s"
|
||||
alignItems="center"
|
||||
justifyContent="flex-end"
|
||||
inline>
|
||||
<Menu>
|
||||
<Button text icon size="s">
|
||||
<Icon size="s" icon={IconDotsHorizontal} />
|
||||
</Button>
|
||||
<Table.Cell column="actions" {root}>
|
||||
<Menu>
|
||||
<Button text icon size="s">
|
||||
<Icon size="s" icon={IconDotsHorizontal} />
|
||||
</Button>
|
||||
|
||||
<svelte:fragment slot="menu" let:toggle>
|
||||
<ActionMenu.Root>
|
||||
<svelte:fragment slot="menu" let:toggle>
|
||||
<ActionMenu.Root>
|
||||
<ActionMenu.Item.Button
|
||||
trailingIcon={IconRefresh}
|
||||
on:click={() => {
|
||||
selectedDeployment = deployment;
|
||||
showRedeploy = true;
|
||||
toggle();
|
||||
trackEvent(Click.FunctionsRedeployClick);
|
||||
}}>
|
||||
Redeploy
|
||||
</ActionMenu.Item.Button>
|
||||
{#if deployment.status === 'ready' && deployment.$id !== $func.deploymentId}
|
||||
<ActionMenu.Item.Button
|
||||
trailingIcon={IconRefresh}
|
||||
trailingIcon={IconLightningBolt}
|
||||
on:click={() => {
|
||||
selectedDeployment = deployment;
|
||||
showRedeploy = true;
|
||||
showActivate = true;
|
||||
toggle();
|
||||
trackEvent(Click.FunctionsRedeployClick);
|
||||
}}>
|
||||
Redeploy
|
||||
Activate
|
||||
</ActionMenu.Item.Button>
|
||||
{#if deployment.status === 'ready' && deployment.$id !== $func.deploymentId}
|
||||
<ActionMenu.Item.Button
|
||||
trailingIcon={IconLightningBolt}
|
||||
on:click={() => {
|
||||
selectedDeployment = deployment;
|
||||
showActivate = true;
|
||||
toggle();
|
||||
}}>
|
||||
Activate
|
||||
</ActionMenu.Item.Button>
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
<DownloadActionMenuItem {deployment} {toggle} />
|
||||
<DownloadActionMenuItem {deployment} {toggle} />
|
||||
|
||||
{#if deployment.status === 'processing' || deployment.status === 'building' || deployment.status === 'waiting'}
|
||||
<ActionMenu.Item.Button
|
||||
trailingIcon={IconXCircle}
|
||||
on:click={() => {
|
||||
selectedDeployment = deployment;
|
||||
toggle();
|
||||
{#if deployment.status === 'processing' || deployment.status === 'building' || deployment.status === 'waiting'}
|
||||
<ActionMenu.Item.Button
|
||||
trailingIcon={IconXCircle}
|
||||
on:click={() => {
|
||||
selectedDeployment = deployment;
|
||||
toggle();
|
||||
|
||||
showCancel = true;
|
||||
trackEvent(Click.FunctionsDeploymentCancelClick);
|
||||
}}>
|
||||
Cancel
|
||||
</ActionMenu.Item.Button>
|
||||
{/if}
|
||||
{#if deployment.status !== 'building' && deployment.status !== 'processing' && deployment.status !== 'waiting'}
|
||||
<ActionMenu.Item.Button
|
||||
trailingIcon={IconTrash}
|
||||
status="danger"
|
||||
on:click={() => {
|
||||
selectedDeployment = deployment;
|
||||
toggle();
|
||||
showCancel = true;
|
||||
trackEvent(Click.FunctionsDeploymentCancelClick);
|
||||
}}>
|
||||
Cancel
|
||||
</ActionMenu.Item.Button>
|
||||
{/if}
|
||||
{#if deployment.status !== 'building' && deployment.status !== 'processing' && deployment.status !== 'waiting'}
|
||||
<ActionMenu.Item.Button
|
||||
trailingIcon={IconTrash}
|
||||
status="danger"
|
||||
on:click={() => {
|
||||
selectedDeployment = deployment;
|
||||
toggle();
|
||||
|
||||
showDelete = true;
|
||||
trackEvent(Click.FunctionsDeploymentDeleteClick);
|
||||
}}>
|
||||
Delete
|
||||
</ActionMenu.Item.Button>
|
||||
{/if}
|
||||
</ActionMenu.Root>
|
||||
</svelte:fragment>
|
||||
</Menu>
|
||||
</Layout.Stack>
|
||||
showDelete = true;
|
||||
trackEvent(Click.FunctionsDeploymentDeleteClick);
|
||||
}}>
|
||||
Delete
|
||||
</ActionMenu.Item.Button>
|
||||
{/if}
|
||||
</ActionMenu.Root>
|
||||
</svelte:fragment>
|
||||
</Menu>
|
||||
</Table.Cell>
|
||||
</Table.Link>
|
||||
</Table.Row.Link>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
import { toLocaleDateTime } from '$lib/helpers/date';
|
||||
import { Container } from '$lib/layout';
|
||||
import { MessagingProviderType } from '@appwrite.io/console';
|
||||
import type { PageData } from './$types';
|
||||
import CreateMessageDropdown from './createMessageDropdown.svelte';
|
||||
import FailedModal from './failedModal.svelte';
|
||||
import MessageStatusPill from './messageStatusPill.svelte';
|
||||
@@ -31,23 +30,30 @@
|
||||
import type { Column } from '$lib/helpers/types';
|
||||
import { writable } from 'svelte/store';
|
||||
import { canWriteMessages } from '$lib/stores/roles';
|
||||
import { Layout, Selector, Table } from '@appwrite.io/pink-svelte';
|
||||
import { Layout, Table } from '@appwrite.io/pink-svelte';
|
||||
|
||||
export let data;
|
||||
|
||||
let selected: string[] = [];
|
||||
let showDelete = false;
|
||||
let deleting = false;
|
||||
let showFailed = false;
|
||||
let errors: string[] = [];
|
||||
let showCreateDropdownMobile = false;
|
||||
let showCreateDropdownEmpty = false;
|
||||
|
||||
const columns = writable<Column[]>([
|
||||
{ id: '$id', title: 'Message ID', type: 'string', show: true, width: 140 },
|
||||
{ id: 'message', title: 'Message', type: 'string', show: false, filter: false, width: 140 },
|
||||
{ id: 'providerType', title: 'Type', type: 'string', show: true, width: 100 },
|
||||
{ id: 'status', title: 'Status', type: 'string', show: true, width: 120 },
|
||||
{ id: 'scheduledAt', title: 'Scheduled at', type: 'datetime', show: true, width: 120 },
|
||||
{ id: 'deliveredAt', title: 'Delivered at', type: 'datetime', show: false, width: 120 }
|
||||
{ id: '$id', title: 'Message ID', type: 'string', width: 140 },
|
||||
{
|
||||
id: 'message',
|
||||
title: 'Message',
|
||||
type: 'string',
|
||||
hide: true,
|
||||
filter: false,
|
||||
width: { min: 140 }
|
||||
},
|
||||
{ id: 'providerType', title: 'Type', type: 'string', width: { min: 100 } },
|
||||
{ id: 'status', title: 'Status', type: 'string', width: { min: 120 } },
|
||||
{ id: 'scheduledAt', title: 'Scheduled at', type: 'datetime', width: { min: 120 } },
|
||||
{ id: 'deliveredAt', title: 'Delivered at', type: 'datetime', width: { min: 120 } }
|
||||
]);
|
||||
|
||||
const project = $page.params.project;
|
||||
@@ -97,78 +103,61 @@
|
||||
</Layout.Stack>
|
||||
|
||||
{#if data.messages.total}
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
{#if $canWriteMessages}
|
||||
<Table.Header.Selector width="40px" />
|
||||
{/if}
|
||||
{#each $columns as column}
|
||||
{#if column.show}
|
||||
<Table.Cell width={column.width + 'px'}>{column.title}</Table.Cell>
|
||||
{/if}
|
||||
<Table.Root
|
||||
columns={$columns}
|
||||
allowSelection={$canWriteMessages}
|
||||
let:root
|
||||
bind:selectedRows={selected}>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
{#each $columns as { id, title }}
|
||||
<Table.Cell column={id} {root}>{title}</Table.Cell>
|
||||
{/each}
|
||||
</svelte:fragment>
|
||||
{#each data.messages.messages as message (message.$id)}
|
||||
<Table.Link href={`${base}/project-${project}/messaging/message-${message.$id}`}>
|
||||
{#if $canWriteMessages}
|
||||
<Table.Cell>
|
||||
<Selector.Checkbox
|
||||
size="s"
|
||||
disabled={message.status === 'processing'} />
|
||||
</Table.Cell>
|
||||
{/if}
|
||||
<Table.Row.Link
|
||||
{root}
|
||||
id={message.$id}
|
||||
href={`${base}/project-${project}/messaging/message-${message.$id}`}>
|
||||
{#each $columns as column (column.id)}
|
||||
{#if column.show}
|
||||
<Table.Cell column={column.id} {root}>
|
||||
{#if column.id === '$id'}
|
||||
{#key $columns}
|
||||
<Table.Cell>
|
||||
<Id value={message.$id}>{message.$id}</Id>
|
||||
</Table.Cell>
|
||||
<Id value={message.$id}>{message.$id}</Id>
|
||||
{/key}
|
||||
{:else if column.id === 'message'}
|
||||
<Table.Cell>
|
||||
{#if message.providerType === MessagingProviderType.Push}
|
||||
{message.data.title}
|
||||
{:else if message.providerType === MessagingProviderType.Sms}
|
||||
{message.data.content}
|
||||
{:else if message.providerType === MessagingProviderType.Email}
|
||||
{message.data.subject}
|
||||
{:else}
|
||||
Invalid provider
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
{#if message.providerType === MessagingProviderType.Push}
|
||||
{message.data.title}
|
||||
{:else if message.providerType === MessagingProviderType.Sms}
|
||||
{message.data.content}
|
||||
{:else if message.providerType === MessagingProviderType.Email}
|
||||
{message.data.subject}
|
||||
{:else}
|
||||
Invalid provider
|
||||
{/if}
|
||||
{:else if column.id === 'providerType'}
|
||||
<Table.Cell>
|
||||
<ProviderType type={message.providerType} size="xs" />
|
||||
</Table.Cell>
|
||||
<ProviderType type={message.providerType} size="xs" />
|
||||
{:else if column.id === 'status'}
|
||||
<Table.Cell>
|
||||
<MessageStatusPill status={message.status} />
|
||||
{#if message.status === 'failed'}
|
||||
<Button
|
||||
on:click={(e) => {
|
||||
e.preventDefault();
|
||||
errors = message.deliveryErrors;
|
||||
showFailed = true;
|
||||
}}>Details</Button>
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
<MessageStatusPill status={message.status} />
|
||||
{#if message.status === 'failed'}
|
||||
<Button
|
||||
on:click={(e) => {
|
||||
e.preventDefault();
|
||||
errors = message.deliveryErrors;
|
||||
showFailed = true;
|
||||
}}>Details</Button>
|
||||
{/if}
|
||||
{:else if column.type === 'datetime'}
|
||||
<Table.Cell>
|
||||
{#if !message[column.id]}
|
||||
-
|
||||
{:else}
|
||||
{toLocaleDateTime(message[column.id])}
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
{#if !message[column.id]}
|
||||
-
|
||||
{:else}
|
||||
{toLocaleDateTime(message[column.id])}
|
||||
{/if}
|
||||
{:else}
|
||||
<Table.Cell>
|
||||
{message[column.id]}
|
||||
</Table.Cell>
|
||||
{message[column.id]}
|
||||
{/if}
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
{/each}
|
||||
</Table.Link>
|
||||
</Table.Row.Link>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
|
||||
@@ -227,9 +216,7 @@
|
||||
Documentation
|
||||
</Button>
|
||||
{#if $canWriteMessages}
|
||||
<CreateMessageDropdown
|
||||
bind:showCreateDropdown={showCreateDropdownEmpty}
|
||||
let:toggle>
|
||||
<CreateMessageDropdown let:toggle>
|
||||
<Button secondary on:click={toggle} event="create_message">
|
||||
<span class="text">Create message</span>
|
||||
</Button>
|
||||
|
||||
+12
-12
@@ -75,18 +75,18 @@
|
||||
</Card>
|
||||
{:else}
|
||||
<Layout.Stack>
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Target</Table.Header.Cell>
|
||||
<Table.Header.Cell width="40px" />
|
||||
<Table.Root columns={[{ id: 'target' }, { id: 'actions', width: 40 }]} let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell column="target" {root}>Target</Table.Header.Cell>
|
||||
<Table.Header.Cell column="actions" {root} />
|
||||
</svelte:fragment>
|
||||
{#each Object.entries($topicsById) as [topicId, topic] (topicId)}
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell column="target" {root}>
|
||||
{topic.name}
|
||||
({getTotal(topic)} targets)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="actions" {root}>
|
||||
<div class="u-flex u-main-end">
|
||||
<button
|
||||
class="button is-text is-only-icon"
|
||||
@@ -97,15 +97,15 @@
|
||||
</button>
|
||||
</div>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
{#each Object.entries($targetsById) as [targetId, target] (targetId)}
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell column="target" {root}>
|
||||
{target.name ? target.name : target.identifier}
|
||||
</Table.Cell>
|
||||
|
||||
<Table.Cell>
|
||||
<Table.Cell column="actions" {root}>
|
||||
<div class="u-flex u-main-end">
|
||||
<button
|
||||
class="button is-text is-only-icon"
|
||||
@@ -116,7 +116,7 @@
|
||||
</button>
|
||||
</div>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
<div>
|
||||
|
||||
+29
-33
@@ -159,50 +159,46 @@
|
||||
{/if}
|
||||
|
||||
<div class="u-flex u-flex-vertical u-gap-24">
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Target</Table.Header.Cell>
|
||||
|
||||
{#if recipientsAvailable}
|
||||
<Table.Header.Cell>Identifier</Table.Header.Cell>
|
||||
{/if}
|
||||
|
||||
<Table.Header.Cell width="40px" />
|
||||
<Table.Root
|
||||
let:root
|
||||
columns={[
|
||||
{ id: 'target' },
|
||||
{ id: 'identifier', hide: !recipientsAvailable },
|
||||
{ id: 'actions', width: 40 }
|
||||
]}>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell column="target" {root}>Target</Table.Header.Cell>
|
||||
<Table.Header.Cell column="identifier" {root}
|
||||
>Identifier</Table.Header.Cell>
|
||||
<Table.Header.Cell column="actions" {root} />
|
||||
</svelte:fragment>
|
||||
{#each dataSource.slice(offset, offset + limit) as source (source['$id'])}
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell column="target" {root}>
|
||||
{#if source['providerType'] === MessagingProviderType.Push}
|
||||
{source['name']}
|
||||
{:else}
|
||||
{source['identifier']}
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
{#if recipientsAvailable}
|
||||
<Table.Cell>
|
||||
{source['name']}
|
||||
</Table.Cell>
|
||||
{/if}
|
||||
|
||||
<Table.Cell>
|
||||
<Table.Cell column="identifier" {root}>
|
||||
{source['name']}
|
||||
</Table.Cell>
|
||||
<Table.Cell column="actions" {root}>
|
||||
{#if isDraft}
|
||||
<div
|
||||
class="u-flex u-main-end"
|
||||
style="--p-button-size: 1.25rem">
|
||||
<Button
|
||||
text
|
||||
class="is-only-icon"
|
||||
ariaLabel="delete"
|
||||
disabled={!isDraft}
|
||||
on:click={() => removeTarget(source['$id'])}>
|
||||
<span
|
||||
class="icon-x u-font-size-20"
|
||||
aria-hidden="true" />
|
||||
</Button>
|
||||
</div>
|
||||
<Button
|
||||
text
|
||||
class="is-only-icon"
|
||||
ariaLabel="delete"
|
||||
disabled={!isDraft}
|
||||
on:click={() => removeTarget(source['$id'])}>
|
||||
<span
|
||||
class="icon-x u-font-size-20"
|
||||
aria-hidden="true" />
|
||||
</Button>
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
{#if sum > limit}
|
||||
|
||||
+36
-40
@@ -94,46 +94,42 @@
|
||||
</Button>
|
||||
{/if}
|
||||
</Layout.Stack>
|
||||
<div class="u-flex u-flex-vertical u-gap-24">
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Topic</Table.Header.Cell>
|
||||
<Table.Header.Cell width="40px" />
|
||||
</svelte:fragment>
|
||||
{#each topics.slice(offset, offset + limit) as topic (topic.$id)}
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
{topic.name}
|
||||
({getTotal(topic)} targets)
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
{#if message.status === 'draft'}
|
||||
<div
|
||||
class="u-flex u-main-end"
|
||||
style="--p-button-size: 1.25rem">
|
||||
<Button
|
||||
text
|
||||
class="is-only-icon"
|
||||
ariaLabel="delete"
|
||||
disabled={message.status != 'draft'}
|
||||
on:click={() => removeTopic(topic.$id)}>
|
||||
<span
|
||||
class="icon-x u-font-size-20"
|
||||
aria-hidden="true" />
|
||||
</Button>
|
||||
</div>
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
{#if sum > limit}
|
||||
<div class="u-flex u-main-space-between">
|
||||
<p class="text">Total topics: {sum}</p>
|
||||
<PaginationInline {sum} {limit} bind:offset />
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
<Table.Root columns={[{ id: 'topic' }, { id: 'actions', width: 40 }]} let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell column="topic" {root}>Topic</Table.Header.Cell>
|
||||
<Table.Header.Cell column="actions" {root} />
|
||||
</svelte:fragment>
|
||||
{#each topics.slice(offset, offset + limit) as topic (topic.$id)}
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell column="topic" {root}>
|
||||
{topic.name}
|
||||
({getTotal(topic)} targets)
|
||||
</Table.Cell>
|
||||
<Table.Cell column="actions" {root}>
|
||||
{#if message.status === 'draft'}
|
||||
<div class="u-flex u-main-end" style="--p-button-size: 1.25rem">
|
||||
<Button
|
||||
text
|
||||
class="is-only-icon"
|
||||
ariaLabel="delete"
|
||||
disabled={message.status != 'draft'}
|
||||
on:click={() => removeTopic(topic.$id)}>
|
||||
<span
|
||||
class="icon-x u-font-size-20"
|
||||
aria-hidden="true" />
|
||||
</Button>
|
||||
</div>
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
{#if sum > limit}
|
||||
<div class="u-flex u-main-space-between">
|
||||
<p class="text">Total topics: {sum}</p>
|
||||
<PaginationInline {sum} {limit} bind:offset />
|
||||
</div>
|
||||
{/if}
|
||||
{:else if message.status == 'draft'}
|
||||
<Empty on:click={() => (showTopics = true)}>Add a topic</Empty>
|
||||
{:else}
|
||||
|
||||
@@ -7,11 +7,11 @@ import type { ComponentType } from 'svelte';
|
||||
import { IconAnnotation, IconDeviceMobile, IconMail } from '@appwrite.io/pink-icons-svelte';
|
||||
|
||||
export const columns = writable<Column[]>([
|
||||
{ id: '$id', title: 'Provider ID', type: 'string', show: true },
|
||||
{ id: 'name', title: 'Name', type: 'string', show: true },
|
||||
{ id: 'provider', title: 'Provider', type: 'string', show: true },
|
||||
{ id: 'type', title: 'Type', type: 'string', show: true },
|
||||
{ id: 'enabled', title: 'Status', type: 'boolean', show: true }
|
||||
{ id: '$id', title: 'Provider ID', type: 'string' },
|
||||
{ id: 'name', title: 'Name', type: 'string' },
|
||||
{ id: 'provider', title: 'Provider', type: 'string' },
|
||||
{ id: 'type', title: 'Type', type: 'string' },
|
||||
{ id: 'enabled', title: 'Status', type: 'boolean' }
|
||||
]);
|
||||
|
||||
export type ProviderInput = {
|
||||
|
||||
@@ -53,64 +53,51 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
{#if $canWriteProviders}
|
||||
<Table.Header.Selector width="40px" />
|
||||
{/if}
|
||||
{#each $columns as column}
|
||||
{#if column.show}
|
||||
<Table.Header.Cell width={column.width}>{column.title}</Table.Header.Cell>
|
||||
{/if}
|
||||
<Table.Root
|
||||
columns={$columns}
|
||||
allowSelection={$canWriteProviders}
|
||||
let:root
|
||||
bind:selectedRows={selectedIds}>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
{#each $columns as { id, title }}
|
||||
<Table.Header.Cell column={id} {root}>{title}</Table.Header.Cell>
|
||||
{/each}
|
||||
</svelte:fragment>
|
||||
{#each data.providers.providers as provider (provider.$id)}
|
||||
<Table.Link
|
||||
<svelte:component
|
||||
this={$canWriteProviders ? Table.Row.Link : Table.Row.Base}
|
||||
id={provider.$id}
|
||||
href={$canWriteProviders
|
||||
? `${base}/project-${$project.$id}/messaging/providers/provider-${provider.$id}`
|
||||
: '#'}>
|
||||
{#if $canWriteProviders}
|
||||
<Table.Cell>
|
||||
<Selector.Checkbox size="s" id={provider.$id} />
|
||||
</Table.Cell>
|
||||
{/if}
|
||||
: undefined}
|
||||
{root}>
|
||||
{#each $columns as column}
|
||||
{#if column.show}
|
||||
<Table.Cell column={column.id} {root}>
|
||||
{#if column.id === '$id'}
|
||||
{#key $columns}
|
||||
<Table.Cell>
|
||||
<Id value={provider.$id}>{provider.$id}</Id>
|
||||
</Table.Cell>
|
||||
<Id value={provider.$id}>{provider.$id}</Id>
|
||||
{/key}
|
||||
{:else if column.id === 'provider'}
|
||||
<Table.Cell>
|
||||
<Provider provider={provider.provider} />
|
||||
</Table.Cell>
|
||||
<Provider provider={provider.provider} />
|
||||
{:else if column.id === 'type'}
|
||||
<Table.Cell>
|
||||
<ProviderType type={provider.type} size="xs" />
|
||||
</Table.Cell>
|
||||
<ProviderType type={provider.type} size="xs" />
|
||||
{:else if column.id === 'enabled'}
|
||||
<Table.Cell>
|
||||
<Badge
|
||||
variant="secondary"
|
||||
type={provider.enabled ? 'success' : undefined}
|
||||
content={provider.enabled ? 'enabled' : 'disabled'}>
|
||||
<svelte:fragment slot="start">
|
||||
{#if provider.enabled}
|
||||
<Icon icon={IconCheckCircle} size="s" />
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
</Badge>
|
||||
</Table.Cell>
|
||||
<Badge
|
||||
variant="secondary"
|
||||
type={provider.enabled ? 'success' : undefined}
|
||||
content={provider.enabled ? 'enabled' : 'disabled'}>
|
||||
<svelte:fragment slot="start">
|
||||
{#if provider.enabled}
|
||||
<Icon icon={IconCheckCircle} size="s" />
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
</Badge>
|
||||
{:else}
|
||||
<Table.Cell>
|
||||
{provider[column.id]}
|
||||
</Table.Cell>
|
||||
{provider[column.id]}
|
||||
{/if}
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
{/each}
|
||||
</Table.Link>
|
||||
</svelte:component>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
|
||||
|
||||
@@ -30,20 +30,19 @@
|
||||
|
||||
const project = $page.params.project;
|
||||
const columns = writable<Column[]>([
|
||||
{ id: '$id', title: 'Topic ID', type: 'string', show: true, width: 140 },
|
||||
{ id: 'name', title: 'Name', type: 'string', show: true, width: 140 },
|
||||
{ id: 'emailTotal', title: 'Email Subscribers', type: 'integer', show: false, width: 140 },
|
||||
{ id: 'smsTotal', title: 'SMS Subscribers', type: 'integer', show: false, width: 140 },
|
||||
{ id: 'pushTotal', title: 'Push Subscribers', type: 'integer', show: false, width: 140 },
|
||||
{ id: '$id', title: 'Topic ID', type: 'string', width: 140 },
|
||||
{ id: 'name', title: 'Name', type: 'string', width: 140 },
|
||||
{ id: 'emailTotal', title: 'Email Subscribers', type: 'integer', hide: true, width: 140 },
|
||||
{ id: 'smsTotal', title: 'SMS Subscribers', type: 'integer', hide: true, width: 140 },
|
||||
{ id: 'pushTotal', title: 'Push Subscribers', type: 'integer', hide: true, width: 140 },
|
||||
{
|
||||
id: 'total',
|
||||
title: 'Subscribers',
|
||||
type: 'integer',
|
||||
show: true,
|
||||
filter: false,
|
||||
width: 140
|
||||
},
|
||||
{ id: '$createdAt', title: 'Created', type: 'datetime', show: true, width: 140 }
|
||||
{ id: '$createdAt', title: 'Created', type: 'datetime', width: 140 }
|
||||
]);
|
||||
|
||||
const topicCreated = async (event: CustomEvent<Models.Team<Record<string, unknown>>>) => {
|
||||
@@ -58,7 +57,7 @@
|
||||
</Layout.Stack>
|
||||
<Layout.Stack direction="row" alignItems="center" justifyContent="flex-end">
|
||||
<Filters query={data.query} {columns} analyticsSource="messaging_topics_filter" />
|
||||
<ViewSelector view={View.Table} {columns} hideView allowNoColumns showColsTextMobile />
|
||||
<ViewSelector view={View.Table} {columns} hideView allowNoColumns />
|
||||
{#if $canWriteTopics}
|
||||
<Button
|
||||
on:click={() => {
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
import type { Column } from '$lib/helpers/types';
|
||||
import { page } from '$app/stores';
|
||||
import { canWriteTopics } from '$lib/stores/roles';
|
||||
import { Selector, Table } from '@appwrite.io/pink-svelte';
|
||||
import { Table } from '@appwrite.io/pink-svelte';
|
||||
|
||||
export let columns: Column[];
|
||||
export let data: PageData;
|
||||
@@ -49,53 +49,33 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
{#if $canWriteTopics}
|
||||
<Table.Header.Selector width="40px" />
|
||||
{/if}
|
||||
{#each columns as column}
|
||||
{#if column.show}
|
||||
<Table.Header.Cell width={column.width + 'px'}>{column.title}</Table.Header.Cell>
|
||||
{/if}
|
||||
<Table.Root {columns} allowSelection={$canWriteTopics} let:root bind:selectedRows={selectedIds}>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
{#each columns as { id, title }}
|
||||
<Table.Header.Cell column={id} {root}>{title}</Table.Header.Cell>
|
||||
{/each}
|
||||
</svelte:fragment>
|
||||
{#each data.topics.topics as topic (topic.$id)}
|
||||
<Table.Link
|
||||
<Table.Row.Link
|
||||
{root}
|
||||
id={topic.$id}
|
||||
href={`${base}/project-${$page.params.project}/messaging/topics/topic-${topic.$id}`}>
|
||||
{#if $canWriteTopics}
|
||||
<Table.Cell>
|
||||
<Selector.Checkbox size="s" />
|
||||
</Table.Cell>
|
||||
{/if}
|
||||
{#each columns as column (column.id)}
|
||||
{#if column.show}
|
||||
<Table.Cell column={column.id} {root}>
|
||||
{#if column.id === '$id'}
|
||||
{#key column.id}
|
||||
<Table.Cell>
|
||||
<Id value={topic.$id}>{topic.$id}</Id>
|
||||
</Table.Cell>
|
||||
<Id value={topic.$id}>{topic.$id}</Id>
|
||||
{/key}
|
||||
{:else if column.type === 'datetime'}
|
||||
<Table.Cell>
|
||||
{#if !topic[column.id]}
|
||||
-
|
||||
{:else}
|
||||
{toLocaleDateTime(topic[column.id])}
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
{topic[column.id] ? toLocaleDateTime(topic[column.id]) : '-'}
|
||||
{:else if column.id === 'total'}
|
||||
<Table.Cell>
|
||||
{topic.emailTotal + topic.smsTotal + topic.pushTotal}
|
||||
</Table.Cell>
|
||||
{topic.emailTotal + topic.smsTotal + topic.pushTotal}
|
||||
{:else}
|
||||
<Table.Cell>
|
||||
{topic[column.id]}
|
||||
</Table.Cell>
|
||||
{topic[column.id]}
|
||||
{/if}
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
{/each}
|
||||
</Table.Link>
|
||||
</Table.Row.Link>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
|
||||
|
||||
@@ -33,12 +33,12 @@
|
||||
let showAdd = false;
|
||||
let subscribersByTargetId: Record<string, Models.Subscriber> = {};
|
||||
const columns = writable<Column[]>([
|
||||
{ id: '$id', title: 'Subscriber ID', type: 'string', show: true, width: 140 },
|
||||
{ id: 'userName', title: 'Name', type: 'string', show: true, filter: false, width: 100 },
|
||||
{ id: 'targetId', title: 'Target ID', type: 'string', show: true, width: 140 },
|
||||
{ id: 'target', title: 'Target', type: 'string', show: true, filter: false, width: 140 },
|
||||
{ id: 'type', title: 'Type', type: 'string', show: true, width: 80 },
|
||||
{ id: '$createdAt', title: 'Created', type: 'datetime', show: true, width: 100 }
|
||||
{ id: '$id', title: 'Subscriber ID', type: 'string', width: 140 },
|
||||
{ id: 'userName', title: 'Name', type: 'string', filter: false, width: 100 },
|
||||
{ id: 'targetId', title: 'Target ID', type: 'string', width: 140 },
|
||||
{ id: 'target', title: 'Target', type: 'string', filter: false, width: 140 },
|
||||
{ id: 'type', title: 'Type', type: 'string', width: 80 },
|
||||
{ id: '$createdAt', title: 'Created', type: 'datetime', width: 100 }
|
||||
]);
|
||||
|
||||
onMount(() => {
|
||||
|
||||
+32
-51
@@ -5,17 +5,6 @@
|
||||
import { FloatingActionBar, Id, Modal } from '$lib/components';
|
||||
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 { addNotification } from '$lib/stores/notifications';
|
||||
import type { PageData } from './$types';
|
||||
import ProviderType from '../../providerType.svelte';
|
||||
@@ -26,7 +15,7 @@
|
||||
import { targetsById } from '../../store';
|
||||
import { MessagingProviderType, type Models } from '@appwrite.io/console';
|
||||
import type { Column } from '$lib/helpers/types';
|
||||
import { Selector, Table } from '@appwrite.io/pink-svelte';
|
||||
import { Table } from '@appwrite.io/pink-svelte';
|
||||
|
||||
export let columns: Column[];
|
||||
export let data: PageData;
|
||||
@@ -81,52 +70,46 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Selector width="40px" />
|
||||
{#each columns as column}
|
||||
{#if column.show}
|
||||
<Table.Header.Cell width={column.width + 'px'}>{column.title}</Table.Header.Cell>
|
||||
{/if}
|
||||
<Table.Root {columns} allowSelection let:root bind:selectedRows={selectedIds}>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
{#each columns as { id, title }}
|
||||
<Table.Header.Cell column={id} {root}>{title}</Table.Header.Cell>
|
||||
{/each}
|
||||
</svelte:fragment>
|
||||
{#each data.subscribers.subscribers as subscriber (subscriber.$id)}
|
||||
{@const target = subscriber.target}
|
||||
<Table.Link href={`${base}/project-${$project.$id}/auth/user-${subscriber.target.userId}`}>
|
||||
<Table.Cell>
|
||||
<Selector.Checkbox size="s" />
|
||||
</Table.Cell>
|
||||
|
||||
<Table.Row.Link
|
||||
{root}
|
||||
id={subscriber.$id}
|
||||
href={`${base}/project-${$project.$id}/auth/user-${subscriber.target.userId}`}>
|
||||
{#each columns as column}
|
||||
{#if column.show}
|
||||
<Table.Cell>
|
||||
{#if column.id === '$id'}
|
||||
{#key column.id}
|
||||
<Id value={subscriber.$id}>
|
||||
{subscriber.$id}
|
||||
</Id>
|
||||
{/key}
|
||||
{:else if column.id === 'targetId'}
|
||||
<Id value={subscriber[column.id]}>
|
||||
{subscriber[column.id]}
|
||||
<Table.Cell column={column.id} {root}>
|
||||
{#if column.id === '$id'}
|
||||
{#key column.id}
|
||||
<Id value={subscriber.$id}>
|
||||
{subscriber.$id}
|
||||
</Id>
|
||||
{:else if column.id === 'target'}
|
||||
{#if target.providerType === MessagingProviderType.Push}
|
||||
{target.name}
|
||||
{:else}
|
||||
{target.identifier}
|
||||
{/if}
|
||||
{:else if column.id === 'type'}
|
||||
<ProviderType type={subscriber.target.providerType} size="s" />
|
||||
{:else if column.id === '$createdAt'}
|
||||
{toLocaleDateTime(subscriber[column.id])}
|
||||
{:else}
|
||||
{/key}
|
||||
{:else if column.id === 'targetId'}
|
||||
<Id value={subscriber[column.id]}>
|
||||
{subscriber[column.id]}
|
||||
</Id>
|
||||
{:else if column.id === 'target'}
|
||||
{#if target.providerType === MessagingProviderType.Push}
|
||||
{target.name}
|
||||
{:else}
|
||||
{target.identifier}
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
{/if}
|
||||
{:else if column.id === 'type'}
|
||||
<ProviderType type={subscriber.target.providerType} size="s" />
|
||||
{:else if column.id === '$createdAt'}
|
||||
{toLocaleDateTime(subscriber[column.id])}
|
||||
{:else}
|
||||
{subscriber[column.id]}
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
{/each}
|
||||
</Table.Link>
|
||||
</Table.Row.Link>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
|
||||
@@ -153,8 +136,6 @@
|
||||
|
||||
<Modal
|
||||
title="Delete subscriber"
|
||||
icon="exclamation"
|
||||
state="warning"
|
||||
bind:show={showDelete}
|
||||
onSubmit={handleDelete}
|
||||
closable={!deleting}>
|
||||
|
||||
@@ -116,10 +116,10 @@
|
||||
placeholder="Search for topics"
|
||||
bind:value={search} />
|
||||
{#if Object.keys(topicResultsById).length > 0 && !emptyTopicsExists}
|
||||
<Table.Root>
|
||||
<Table.Root columns={1} let:root>
|
||||
{#each Object.entries(topicResultsById) as [topicId, topic]}
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell {root}>
|
||||
<Layout.Stack direction="row" alignItems="center" gap="s">
|
||||
<Selector.Checkbox
|
||||
id={topicId}
|
||||
@@ -133,7 +133,7 @@
|
||||
</span>
|
||||
</Layout.Stack>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
<div class="u-flex u-main-space-between u-cross-center">
|
||||
|
||||
@@ -70,14 +70,14 @@
|
||||
</Card>
|
||||
{:else}
|
||||
<div class="table-wrapper">
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Target</Table.Header.Cell>
|
||||
<Table.Header.Cell width="32px" />
|
||||
<Table.Root columns={[{ id: 'target' }, { id: 'actions', width: 40 }]} let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell column="target" {root}>Target</Table.Header.Cell>
|
||||
<Table.Header.Cell column="actions" {root} />
|
||||
</svelte:fragment>
|
||||
{#each Object.entries($topicsById) as [topicId, topic] (topicId)}
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell column="target" {root}>
|
||||
<div class="u-flex u-cross-center">
|
||||
<span class="title">
|
||||
<span class="u-line-height-1-5">
|
||||
@@ -90,7 +90,7 @@
|
||||
</span></span>
|
||||
</div>
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="actions" {root}>
|
||||
<div class="u-flex u-main-end">
|
||||
<button
|
||||
class="button is-text is-only-icon"
|
||||
@@ -101,19 +101,18 @@
|
||||
</button>
|
||||
</div>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
{#each Object.entries($targetsById) as [targetId, target] (targetId)}
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell column="target" {root}>
|
||||
<div class="u-flex u-cross-center">
|
||||
<span class="text">
|
||||
{target.name ? target.name : target.identifier}
|
||||
</span>
|
||||
</div>
|
||||
</Table.Cell>
|
||||
|
||||
<Table.Cell>
|
||||
<Table.Cell column="actions" {root}>
|
||||
<div class="u-flex u-main-end">
|
||||
<button
|
||||
class="button is-text is-only-icon"
|
||||
@@ -124,7 +123,7 @@
|
||||
</button>
|
||||
</div>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
</div>
|
||||
|
||||
@@ -16,28 +16,28 @@
|
||||
</script>
|
||||
|
||||
{#if data.keys.total}
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Name</Table.Header.Cell>
|
||||
<Table.Header.Cell>Last accessed</Table.Header.Cell>
|
||||
<Table.Header.Cell>Expiration date</Table.Header.Cell>
|
||||
<Table.Header.Cell>Scopes</Table.Header.Cell>
|
||||
<Table.Root columns={4} let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell {root}>Name</Table.Header.Cell>
|
||||
<Table.Header.Cell {root}>Last accessed</Table.Header.Cell>
|
||||
<Table.Header.Cell {root}>Expiration date</Table.Header.Cell>
|
||||
<Table.Header.Cell {root}>Scopes</Table.Header.Cell>
|
||||
</svelte:fragment>
|
||||
{#each data.keys.keys as key}
|
||||
<Table.Link href={`keys/${key.$id}`}>
|
||||
<Table.Cell>
|
||||
<Table.Row.Link href={`keys/${key.$id}`} {root}>
|
||||
<Table.Cell {root}>
|
||||
{key.name}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell {root}>
|
||||
{key.accessedAt ? toLocaleDate(key.accessedAt) : 'never'}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell {root}>
|
||||
{key.expire ? toLocaleDateTime(key.expire) : 'never'}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell {root}>
|
||||
{key.scopes.length} Scopes
|
||||
</Table.Cell>
|
||||
</Table.Link>
|
||||
</Table.Row.Link>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
{:else}
|
||||
|
||||
@@ -123,27 +123,27 @@
|
||||
</script>
|
||||
|
||||
{#if data.platforms.platforms.length}
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Name</Table.Header.Cell>
|
||||
<Table.Header.Cell>Platform type</Table.Header.Cell>
|
||||
<Table.Header.Cell>Last updated</Table.Header.Cell>
|
||||
<Table.Root columns={3} let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell {root}>Name</Table.Header.Cell>
|
||||
<Table.Header.Cell {root}>Platform type</Table.Header.Cell>
|
||||
<Table.Header.Cell {root}>Last updated</Table.Header.Cell>
|
||||
</svelte:fragment>
|
||||
{#each data.platforms.platforms as platform}
|
||||
<Table.Link href={`${path}/${platform.$id}`}>
|
||||
<Table.Cell>
|
||||
<Table.Row.Link href={`${path}/${platform.$id}`} {root}>
|
||||
<Table.Cell {root}>
|
||||
{platform.name}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell {root}>
|
||||
<Layout.Stack direction="row" gap="s" alignItems="center">
|
||||
<Icon icon={getPlatformInfo(platform.type)} />
|
||||
{PlatformTypes[platform.type]}
|
||||
</Layout.Stack>
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell {root}>
|
||||
{platform.$updatedAt ? toLocaleDate(platform.$updatedAt) : 'never'}
|
||||
</Table.Cell>
|
||||
</Table.Link>
|
||||
</Table.Row.Link>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
{:else}
|
||||
|
||||
@@ -152,32 +152,32 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Date</Table.Header.Cell>
|
||||
<Table.Header.Cell>Source</Table.Header.Cell>
|
||||
<Table.Header.Cell>Status</Table.Header.Cell>
|
||||
<Table.Header.Cell />
|
||||
<Table.Root columns={4} let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell {root}>Date</Table.Header.Cell>
|
||||
<Table.Header.Cell {root}>Source</Table.Header.Cell>
|
||||
<Table.Header.Cell {root}>Status</Table.Header.Cell>
|
||||
<Table.Header.Cell {root} />
|
||||
</svelte:fragment>
|
||||
{#each data.migrations as entry}
|
||||
<Table.Row>
|
||||
<Table.Row.Base {root}>
|
||||
{@const status = getStatus(entry.status)}
|
||||
<Table.Cell>
|
||||
<Table.Cell {root}>
|
||||
{isSameDay(new Date(), new Date(entry.$createdAt))
|
||||
? 'Today'
|
||||
: toLocaleDate(entry.$createdAt)}
|
||||
</Table.Cell>
|
||||
<Table.Cell>{entry.source}</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell {root}>{entry.source}</Table.Cell>
|
||||
<Table.Cell {root}>
|
||||
<Status label={capitalize(status)} {status} />
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell {root}>
|
||||
<div class="u-flex u-main-end">
|
||||
<Button secondary on:click={() => showDetails(entry)}
|
||||
>Details</Button>
|
||||
</div>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
{:else}
|
||||
|
||||
@@ -94,15 +94,17 @@
|
||||
</Button>
|
||||
</Layout.Stack>
|
||||
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Repository</Table.Header.Cell>
|
||||
<Table.Header.Cell>Updated</Table.Header.Cell>
|
||||
<Table.Header.Cell width="20px" />
|
||||
<Table.Root
|
||||
let:root
|
||||
columns={[{ id: 'repo' }, { id: 'updated' }, { id: 'actions', width: 20 }]}>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell column="repo" {root}>Repository</Table.Header.Cell>
|
||||
<Table.Header.Cell column="updated" {root}>Updated</Table.Header.Cell>
|
||||
<Table.Header.Cell column="actions" {root} />
|
||||
</svelte:fragment>
|
||||
{#each installations as installation, i}
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell column="repo" {root}>
|
||||
<Layout.Stack direction="row" gap="s" alignItems="center">
|
||||
<Avatar alt={installation.provider} size="xs">
|
||||
<Icon
|
||||
@@ -114,10 +116,10 @@
|
||||
</Link>
|
||||
</Layout.Stack>
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="updated" {root}>
|
||||
{dayjs().to(installation.$updatedAt)}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="actions" {root}>
|
||||
<Popover let:toggle padding="none" placement="bottom-end">
|
||||
<button
|
||||
type="button"
|
||||
@@ -145,7 +147,7 @@
|
||||
</ActionMenu.Root>
|
||||
</Popover>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
{#if total > limit}
|
||||
|
||||
@@ -219,20 +219,22 @@
|
||||
}
|
||||
]} />
|
||||
{#if data.usage.executionsBreakdown.length > 0}
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Function</Table.Header.Cell>
|
||||
<Table.Header.Cell>Usage</Table.Header.Cell>
|
||||
<Table.Root columns={2} let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell {root}>Function</Table.Header.Cell>
|
||||
<Table.Header.Cell {root}>Usage</Table.Header.Cell>
|
||||
</svelte:fragment>
|
||||
{#each data.usage.executionsBreakdown as func}
|
||||
<Table.Link href={`${baseRoute}/functions/function-${func.resourceId}`}>
|
||||
<Table.Cell>
|
||||
<Table.Row.Link
|
||||
href={`${baseRoute}/functions/function-${func.resourceId}`}
|
||||
{root}>
|
||||
<Table.Cell {root}>
|
||||
{func.name ?? func.resourceId}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell {root}>
|
||||
{formatNum(func.value)} executions
|
||||
</Table.Cell>
|
||||
</Table.Link>
|
||||
</Table.Row.Link>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
{/if}
|
||||
@@ -367,24 +369,24 @@
|
||||
</div>
|
||||
{#if data.usage.authPhoneCountryBreakdown.length > 0}
|
||||
<Accordion title="Region breakdown">
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Region</Table.Header.Cell>
|
||||
<Table.Header.Cell>Amount</Table.Header.Cell>
|
||||
<Table.Header.Cell>Estimated cost</Table.Header.Cell>
|
||||
<Table.Root columns={3} let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell {root}>Region</Table.Header.Cell>
|
||||
<Table.Header.Cell {root}>Amount</Table.Header.Cell>
|
||||
<Table.Header.Cell {root}>Estimated cost</Table.Header.Cell>
|
||||
</svelte:fragment>
|
||||
{#each data.usage.authPhoneCountryBreakdown as phone}
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell {root}>
|
||||
{getCountryName(phone.name)}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell {root}>
|
||||
{formatNumberWithCommas(phone.value)}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell {root}>
|
||||
{formatCurrency(phone.estimate)}
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
</Accordion>
|
||||
|
||||
@@ -45,63 +45,48 @@
|
||||
</Layout.Stack>
|
||||
|
||||
{#if data.webhooks.total}
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
{#each $columns as column}
|
||||
{#if column.show}
|
||||
<Table.Header.Cell width={column.width + 'px'}
|
||||
>{column.title}</Table.Header.Cell>
|
||||
{/if}
|
||||
<Table.Root columns={$columns} let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
{#each $columns as { id, title }}
|
||||
<Table.Header.Cell column={id} {root}>{title}</Table.Header.Cell>
|
||||
{/each}
|
||||
</svelte:fragment>
|
||||
{#each data.webhooks.webhooks as webhook}
|
||||
<Table.Link href={`${base}/project-${projectId}/settings/webhooks/${webhook.$id}`}>
|
||||
<Table.Row.Link
|
||||
{root}
|
||||
href={`${base}/project-${projectId}/settings/webhooks/${webhook.$id}`}>
|
||||
{#each $columns as column (column.id)}
|
||||
{#if column.show}
|
||||
<Table.Cell column={column.id} {root}>
|
||||
{#if column.id === '$id'}
|
||||
{#key $columns}
|
||||
<Table.Cell>
|
||||
<Id value={webhook.$id}>{webhook.$id}</Id>
|
||||
</Table.Cell>
|
||||
<Id value={webhook.$id}>{webhook.$id}</Id>
|
||||
{/key}
|
||||
{:else if column.id === 'events'}
|
||||
<Table.Cell>
|
||||
{webhook.events.length}
|
||||
</Table.Cell>
|
||||
{webhook.events.length}
|
||||
{:else if column.type === 'datetime'}
|
||||
<Table.Cell>
|
||||
{#if !webhook[column.id]}
|
||||
-
|
||||
{:else}
|
||||
{toLocaleDateTime(webhook[column.id])}
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
{webhook[column.id] ? toLocaleDateTime(webhook[column.id]) : '-'}
|
||||
{:else if column.id === 'enabled'}
|
||||
<Table.Cell>
|
||||
<Layout.Stack direction="row" gap="s" alignItems="normal">
|
||||
<Status
|
||||
label={webhook.enabled ? 'Enabled' : 'Disabled'}
|
||||
status={webhook.enabled ? 'complete' : 'failed'} />
|
||||
<Layout.Stack direction="row" gap="s" alignItems="normal">
|
||||
<Status
|
||||
label={webhook.enabled ? 'Enabled' : 'Disabled'}
|
||||
status={webhook.enabled ? 'complete' : 'failed'} />
|
||||
|
||||
{#if webhook.enabled === false}
|
||||
<Link.Button
|
||||
variant="muted"
|
||||
on:click={(e) => {
|
||||
e.preventDefault();
|
||||
selectedWebhook = webhook;
|
||||
showFailed = true;
|
||||
}}>Details</Link.Button>
|
||||
{/if}
|
||||
</Layout.Stack>
|
||||
</Table.Cell>
|
||||
{#if webhook.enabled === false}
|
||||
<Link.Button
|
||||
variant="muted"
|
||||
on:click={(e) => {
|
||||
e.preventDefault();
|
||||
selectedWebhook = webhook;
|
||||
showFailed = true;
|
||||
}}>Details</Link.Button>
|
||||
{/if}
|
||||
</Layout.Stack>
|
||||
{:else}
|
||||
<Table.Cell>
|
||||
{webhook[column.id]}
|
||||
</Table.Cell>
|
||||
{webhook[column.id]}
|
||||
{/if}
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
{/each}
|
||||
</Table.Link>
|
||||
</Table.Row.Link>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
{:else}
|
||||
|
||||
+4
-4
@@ -72,10 +72,10 @@
|
||||
Set the events that will trigger your webhook. Maximum 100 events allowed.
|
||||
<svelte:fragment slot="aside">
|
||||
{#if $eventSet.size}
|
||||
<Table.Root>
|
||||
<Table.Root columns={1} let:root>
|
||||
{#each Array.from($eventSet) as event}
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell {root}>
|
||||
<Layout.Stack
|
||||
direction="row"
|
||||
justifyContent="space-between"
|
||||
@@ -92,7 +92,7 @@
|
||||
</Button>
|
||||
</Layout.Stack>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
<div>
|
||||
|
||||
@@ -20,10 +20,10 @@
|
||||
<Fieldset legend="Events">
|
||||
<Layout.Stack gap="s">
|
||||
{#if events.length}
|
||||
<Table.Root>
|
||||
<Table.Root columns={1} let:root>
|
||||
{#each events as event}
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell {root}>
|
||||
<Layout.Stack
|
||||
direction="row"
|
||||
justifyContent="space-between"
|
||||
@@ -40,7 +40,7 @@
|
||||
</Button>
|
||||
</Layout.Stack>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
<div>
|
||||
|
||||
@@ -1,17 +1,12 @@
|
||||
// import { page } from '$app/stores';
|
||||
import type { Column } from '$lib/helpers/types';
|
||||
// import type { Models } from '@appwrite.io/console';
|
||||
import { writable } from 'svelte/store';
|
||||
|
||||
// export const database = derived(page, ($page) => $page.data.database as Models.Database);
|
||||
// export const showCreate = writable(false);
|
||||
|
||||
export const columns = writable<Column[]>([
|
||||
{ id: '$id', title: 'Webhook ID', type: 'string', show: false, width: 200 },
|
||||
{ id: 'name', title: 'Name', type: 'string', show: true, width: 200 },
|
||||
{ id: 'url', title: 'Post URL', type: 'string', show: true, width: 200 },
|
||||
{ id: 'events', title: 'Events', type: 'string', show: true, width: 120 },
|
||||
{ id: 'enabled', title: 'Status', type: 'string', show: true, width: 180 },
|
||||
{ id: '$createdAt', title: 'Created', type: 'datetime', show: true, width: 200 },
|
||||
{ id: '$updatedAt', title: 'Updated', type: 'datetime', show: true, width: 200 }
|
||||
{ id: '$id', title: 'Webhook ID', type: 'string', hide: true, width: 150 },
|
||||
{ id: 'name', title: 'Name', type: 'string', width: { min: 200 } },
|
||||
{ id: 'url', title: 'Post URL', type: 'string', width: { min: 200 } },
|
||||
{ id: 'events', title: 'Events', type: 'string', width: { min: 120 } },
|
||||
{ id: 'enabled', title: 'Status', type: 'string', width: { min: 180 } },
|
||||
{ id: '$createdAt', title: 'Created', type: 'datetime', width: { min: 200 } },
|
||||
{ id: '$updatedAt', title: 'Updated', type: 'datetime', width: { min: 200 } }
|
||||
]);
|
||||
|
||||
@@ -189,16 +189,26 @@
|
||||
limit={6}
|
||||
let:paginatedItems
|
||||
hideFooter={variables.length <= 6}>
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell width="200px">Key</Table.Header.Cell>
|
||||
<Table.Header.Cell>Value</Table.Header.Cell>
|
||||
<Table.Header.Cell width="10px"></Table.Header.Cell>
|
||||
<Table.Root
|
||||
let:root
|
||||
columns={[
|
||||
{ id: 'key', width: 200 },
|
||||
{ id: 'value' },
|
||||
{ id: 'actions', width: 40 }
|
||||
]}>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell column="key" {root}
|
||||
>Key</Table.Header.Cell>
|
||||
<Table.Header.Cell column="value" {root}
|
||||
>Value</Table.Header.Cell>
|
||||
<Table.Header.Cell column="actions" {root}
|
||||
></Table.Header.Cell>
|
||||
</svelte:fragment>
|
||||
{#each paginatedItems as variable}
|
||||
<Table.Row>
|
||||
<Table.Cell>{variable.key}</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell column="key" {root}
|
||||
>{variable.key}</Table.Cell>
|
||||
<Table.Cell column="value" {root}>
|
||||
<!-- TODO: fix max width -->
|
||||
<div style="max-width: 20rem">
|
||||
{#if variable.secret}
|
||||
@@ -220,7 +230,7 @@
|
||||
{/if}
|
||||
</div>
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell column="actions" {root}>
|
||||
<div style="margin-inline-start: auto">
|
||||
<Popover
|
||||
padding="none"
|
||||
@@ -282,7 +292,7 @@
|
||||
</Popover>
|
||||
</div>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
</Paginator>
|
||||
|
||||
@@ -9,7 +9,6 @@ export const columns = writable<Column[]>([
|
||||
id: 'status',
|
||||
title: 'Status',
|
||||
type: 'enum',
|
||||
show: true,
|
||||
width: 110,
|
||||
array: true,
|
||||
format: 'enum',
|
||||
@@ -20,7 +19,6 @@ export const columns = writable<Column[]>([
|
||||
id: 'buildDuration',
|
||||
title: 'Build duration',
|
||||
type: 'integer',
|
||||
show: true,
|
||||
width: 90,
|
||||
elements: [
|
||||
{
|
||||
@@ -42,7 +40,7 @@ export const columns = writable<Column[]>([
|
||||
id: 'sourceSize',
|
||||
title: 'Source size',
|
||||
type: 'integer',
|
||||
show: false,
|
||||
hide: true,
|
||||
width: 140,
|
||||
elements: [
|
||||
{
|
||||
@@ -63,7 +61,6 @@ export const columns = writable<Column[]>([
|
||||
id: 'buildSize',
|
||||
title: 'Build size',
|
||||
type: 'integer',
|
||||
show: true,
|
||||
filter: false,
|
||||
width: 80
|
||||
},
|
||||
@@ -71,7 +68,6 @@ export const columns = writable<Column[]>([
|
||||
id: 'type',
|
||||
title: 'Source',
|
||||
type: 'string',
|
||||
show: true,
|
||||
width: 90,
|
||||
array: true,
|
||||
format: 'enum',
|
||||
@@ -85,7 +81,6 @@ export const columns = writable<Column[]>([
|
||||
id: '$updatedAt',
|
||||
title: 'Updated',
|
||||
type: 'datetime',
|
||||
show: true,
|
||||
width: 150,
|
||||
format: 'datetime'
|
||||
}
|
||||
|
||||
@@ -28,69 +28,54 @@
|
||||
let selectedDeployment: Models.Deployment = null;
|
||||
</script>
|
||||
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
{#each $columns as column}
|
||||
{#if column.show}
|
||||
<Table.Header.Cell width={column?.width?.toString() ?? ''}>
|
||||
{column.title}
|
||||
</Table.Header.Cell>
|
||||
{/if}
|
||||
<Table.Root columns={[...$columns, { id: 'actions', width: 40 }]} let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
{#each $columns as { id, title }}
|
||||
<Table.Header.Cell column={id} {root}>
|
||||
{title}
|
||||
</Table.Header.Cell>
|
||||
{/each}
|
||||
<Table.Header.Cell width="40" />
|
||||
<Table.Header.Cell column="actions" {root} />
|
||||
</svelte:fragment>
|
||||
{#each data.deploymentList.deployments as deployment}
|
||||
<Table.Link
|
||||
<Table.Row.Link
|
||||
{root}
|
||||
href={`${base}/project-${$page.params.project}/sites/site-${$page.params.site}/deployments/deployment-${deployment.$id}`}>
|
||||
{#each $columns as column}
|
||||
{#if column.show}
|
||||
<Table.Cell column={column.id} {root}>
|
||||
{#if column.id === '$id'}
|
||||
{#key column.id}
|
||||
<Table.Cell width={column?.width?.toString() ?? ''}>
|
||||
<Id value={deployment.$id}>{deployment.$id}</Id>
|
||||
</Table.Cell>
|
||||
<Id value={deployment.$id}>{deployment.$id}</Id>
|
||||
{/key}
|
||||
{:else if column.id === 'status'}
|
||||
<Table.Cell width={column?.width?.toString() ?? ''}>
|
||||
{@const status = deployment.status}
|
||||
{#if data?.activeDeployment?.$id === deployment?.$id}
|
||||
<Status status="complete" label="Active" />
|
||||
{:else}
|
||||
<Status
|
||||
status={deploymentStatusConverter(status)}
|
||||
label={capitalize(status)} />
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
{@const status = deployment.status}
|
||||
{#if data?.activeDeployment?.$id === deployment?.$id}
|
||||
<Status status="complete" label="Active" />
|
||||
{:else}
|
||||
<Status
|
||||
status={deploymentStatusConverter(status)}
|
||||
label={capitalize(status)} />
|
||||
{/if}
|
||||
{:else if column.id === 'type'}
|
||||
<Table.Cell width={column?.width?.toString() ?? ''}>
|
||||
<DeploymentSource {deployment} />
|
||||
</Table.Cell>
|
||||
<DeploymentSource {deployment} />
|
||||
{:else if column.id === '$updatedAt'}
|
||||
<Table.Cell width={column?.width?.toString() ?? ''}>
|
||||
<DeploymentCreatedBy {deployment} />
|
||||
</Table.Cell>
|
||||
<DeploymentCreatedBy {deployment} />
|
||||
{:else if column.id === 'buildDuration'}
|
||||
<Table.Cell width={column?.width?.toString() ?? ''}>
|
||||
{#if ['waiting'].includes(deployment.status)}
|
||||
-
|
||||
{:else if ['processing', 'building'].includes(deployment.status)}
|
||||
<span use:timer={{ start: deployment.$createdAt }} />
|
||||
{:else}
|
||||
{formatTimeDetailed(deployment.buildDuration)}
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
{#if ['waiting'].includes(deployment.status)}
|
||||
-
|
||||
{:else if ['processing', 'building'].includes(deployment.status)}
|
||||
<span use:timer={{ start: deployment.$createdAt }} />
|
||||
{:else}
|
||||
{formatTimeDetailed(deployment.buildDuration)}
|
||||
{/if}
|
||||
{:else if column.id === 'sourceSize'}
|
||||
<Table.Cell width={column?.width?.toString() ?? ''}>
|
||||
{calculateSize(deployment.sourceSize)}
|
||||
</Table.Cell>
|
||||
{calculateSize(deployment.sourceSize)}
|
||||
{:else if column.id === 'buildSize'}
|
||||
<Table.Cell width={column?.width?.toString() ?? ''}>
|
||||
{calculateSize(deployment.buildSize)}
|
||||
</Table.Cell>
|
||||
{calculateSize(deployment.buildSize)}
|
||||
{/if}
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
{/each}
|
||||
<Table.Cell>
|
||||
<Table.Cell column="actions" {root}>
|
||||
<Layout.Stack alignItems="flex-end">
|
||||
<DeploymentActionMenu
|
||||
{deployment}
|
||||
@@ -102,7 +87,7 @@
|
||||
activeDeployment={data.site.deploymentId} />
|
||||
</Layout.Stack>
|
||||
</Table.Cell>
|
||||
</Table.Link>
|
||||
</Table.Row.Link>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
|
||||
|
||||
+15
-14
@@ -43,21 +43,22 @@
|
||||
</Button>
|
||||
</Layout.Stack>
|
||||
{#if deploymentList?.total}
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Deployment ID</Table.Header.Cell>
|
||||
<Table.Header.Cell>Status</Table.Header.Cell>
|
||||
<Table.Header.Cell>Source</Table.Header.Cell>
|
||||
<Table.Header.Cell>Updated</Table.Header.Cell>
|
||||
<Table.Header.Cell />
|
||||
<Table.Root columns={5} let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell {root}>Deployment ID</Table.Header.Cell>
|
||||
<Table.Header.Cell {root}>Status</Table.Header.Cell>
|
||||
<Table.Header.Cell {root}>Source</Table.Header.Cell>
|
||||
<Table.Header.Cell {root}>Updated</Table.Header.Cell>
|
||||
<Table.Header.Cell {root} />
|
||||
</svelte:fragment>
|
||||
{#each deploymentList?.deployments as deployment}
|
||||
<Table.Link
|
||||
<Table.Row.Link
|
||||
{root}
|
||||
href={`${base}/project-${$page.params.project}/sites/site-${$page.params.site}/deployments/deployment-${deployment.$id}`}>
|
||||
<Table.Cell>
|
||||
<Table.Cell {root}>
|
||||
<Id value={deployment.$id}>{deployment.$id}</Id>
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell {root}>
|
||||
{@const status = deployment.status}
|
||||
{#if activeDeployment?.$id === deployment?.$id}
|
||||
<Status status="complete" label="Active" />
|
||||
@@ -68,13 +69,13 @@
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
|
||||
<Table.Cell>
|
||||
<Table.Cell {root}>
|
||||
<DeploymentSource {deployment} />
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell {root}>
|
||||
<DeploymentCreatedBy {deployment} />
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell {root}>
|
||||
<Layout.Stack alignItems="flex-end">
|
||||
<DeploymentActionMenu
|
||||
{deployment}
|
||||
@@ -86,7 +87,7 @@
|
||||
activeDeployment={site.deploymentId} />
|
||||
</Layout.Stack>
|
||||
</Table.Cell>
|
||||
</Table.Link>
|
||||
</Table.Row.Link>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
{:else}
|
||||
|
||||
@@ -69,16 +69,16 @@
|
||||
</Layout.Stack>
|
||||
|
||||
{#if data.domains.total}
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell width="200px">Domain</Table.Header.Cell>
|
||||
<Table.Header.Cell>Redirect to</Table.Header.Cell>
|
||||
<Table.Header.Cell>Production branch</Table.Header.Cell>
|
||||
<Table.Header.Cell />
|
||||
<Table.Root columns={4} let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell {root}>Domain</Table.Header.Cell>
|
||||
<Table.Header.Cell {root}>Redirect to</Table.Header.Cell>
|
||||
<Table.Header.Cell {root}>Production branch</Table.Header.Cell>
|
||||
<Table.Header.Cell {root} />
|
||||
</svelte:fragment>
|
||||
{#each data.domains.rules as domain}
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell {root}>
|
||||
<Link external href={`${$protocol}${domain.domain}`} variant="quiet">
|
||||
<Layout.Stack direction="row" alignItems="center" gap="xs">
|
||||
{domain.domain}
|
||||
@@ -87,14 +87,14 @@
|
||||
</Link>
|
||||
</Table.Cell>
|
||||
<!-- TODO design redirect status code -->
|
||||
<Table.Cell>
|
||||
<Table.Cell {root}>
|
||||
{domain?.redirectUrl || 'No redirect'}
|
||||
{domain?.redirectStatusCode ? `(${domain.redirectStatusCode})` : ''}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell {root}>
|
||||
{domain.deploymentVcsProviderBranch || '-'}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Cell {root}>
|
||||
<Layout.Stack direction="row" justifyContent="flex-end">
|
||||
<Popover let:toggle placement="bottom-start" padding="none">
|
||||
<Button
|
||||
@@ -140,7 +140,7 @@
|
||||
</Popover>
|
||||
</Layout.Stack>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
|
||||
|
||||
+18
-18
@@ -94,23 +94,23 @@
|
||||
</Typography.Text>
|
||||
</Layout.Stack>
|
||||
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Type</Table.Header.Cell>
|
||||
<Table.Header.Cell>Name</Table.Header.Cell>
|
||||
<Table.Header.Cell>Value</Table.Header.Cell>
|
||||
<Table.Root columns={3} let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell {root}>Type</Table.Header.Cell>
|
||||
<Table.Header.Cell {root}>Name</Table.Header.Cell>
|
||||
<Table.Header.Cell {root}>Value</Table.Header.Cell>
|
||||
</svelte:fragment>
|
||||
<Table.Row>
|
||||
<Table.Cell>CNAME</Table.Cell>
|
||||
<Table.Cell>{data.domain?.domain}</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell {root}>CNAME</Table.Cell>
|
||||
<Table.Cell {root}>{data.domain?.domain}</Table.Cell>
|
||||
<Table.Cell {root}>
|
||||
<InteractiveText
|
||||
variant="copy"
|
||||
isVisible
|
||||
text={globalThis?.location?.origin}>
|
||||
{globalThis?.location?.origin}</InteractiveText>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
</Table.Root>
|
||||
<Layout.Stack gap="s" direction="row" alignItems="center">
|
||||
<Icon icon={IconInfo} size="s" color="--fgcolor-neutral-secondary" />
|
||||
@@ -145,19 +145,19 @@
|
||||
</Typography.Text>
|
||||
</Layout.Stack>
|
||||
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Type</Table.Header.Cell>
|
||||
<Table.Header.Cell>Value</Table.Header.Cell>
|
||||
<Table.Root columns={2} let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell {root}>Type</Table.Header.Cell>
|
||||
<Table.Header.Cell {root}>Value</Table.Header.Cell>
|
||||
</svelte:fragment>
|
||||
{#each nameservers as nameserver}
|
||||
<Table.Row>
|
||||
<Table.Cell>NS</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell {root}>NS</Table.Cell>
|
||||
<Table.Cell {root}>
|
||||
<InteractiveText variant="copy" isVisible text={nameserver}>
|
||||
{nameserver}</InteractiveText>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
<!-- <Layout.Stack gap="s" direction="row" alignItems="center">
|
||||
|
||||
+10
-10
@@ -22,20 +22,20 @@
|
||||
</Typography.Text>
|
||||
</Layout.Stack>
|
||||
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Type</Table.Header.Cell>
|
||||
<Table.Header.Cell>Name</Table.Header.Cell>
|
||||
<Table.Header.Cell>Value</Table.Header.Cell>
|
||||
<Table.Root columns={3} let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell {root}>Type</Table.Header.Cell>
|
||||
<Table.Header.Cell {root}>Name</Table.Header.Cell>
|
||||
<Table.Header.Cell {root}>Value</Table.Header.Cell>
|
||||
</svelte:fragment>
|
||||
<Table.Row>
|
||||
<Table.Cell>CNAME</Table.Cell>
|
||||
<Table.Cell>{domain?.domain}</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell {root}>CNAME</Table.Cell>
|
||||
<Table.Cell {root}>{domain?.domain}</Table.Cell>
|
||||
<Table.Cell {root}>
|
||||
<Copy value={globalThis?.location?.origin}
|
||||
>{globalThis?.location?.origin}</Copy>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Row.Base>
|
||||
</Table.Root>
|
||||
<Layout.Stack gap="s" direction="row" alignItems="center">
|
||||
<Icon icon={IconInfo} size="s" color="--fgcolor-neutral-secondary" />
|
||||
|
||||
+16
-16
@@ -67,16 +67,16 @@
|
||||
</Layout.Stack>
|
||||
{#if requestTab === 'parameters'}
|
||||
{#if parameters?.length}
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Key</Table.Header.Cell>
|
||||
<Table.Header.Cell>Value</Table.Header.Cell>
|
||||
<Table.Root columns={2} let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell {root}>Key</Table.Header.Cell>
|
||||
<Table.Header.Cell {root}>Value</Table.Header.Cell>
|
||||
</svelte:fragment>
|
||||
{#each parameters as parameter}
|
||||
<Table.Row>
|
||||
<Table.Cell>{parameter.name}</Table.Cell>
|
||||
<Table.Cell>{parameter.value}</Table.Cell>
|
||||
</Table.Row>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell {root}>{parameter.name}</Table.Cell>
|
||||
<Table.Cell {root}>{parameter.value}</Table.Cell>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
{:else}
|
||||
@@ -86,16 +86,16 @@
|
||||
{/if}
|
||||
{:else if requestTab === 'headers'}
|
||||
{#if selectedLog.requestHeaders?.length}
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Key</Table.Header.Cell>
|
||||
<Table.Header.Cell>Value</Table.Header.Cell>
|
||||
<Table.Root columns={2} let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell {root}>Key</Table.Header.Cell>
|
||||
<Table.Header.Cell {root}>Value</Table.Header.Cell>
|
||||
</svelte:fragment>
|
||||
{#each selectedLog.requestHeaders as request}
|
||||
<Table.Row>
|
||||
<Table.Cell>{request.name}</Table.Cell>
|
||||
<Table.Cell>{request.value}</Table.Cell>
|
||||
</Table.Row>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell {root}>{request.name}</Table.Cell>
|
||||
<Table.Cell {root}>{request.value}</Table.Cell>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
|
||||
|
||||
+8
-8
@@ -73,16 +73,16 @@
|
||||
{/if}
|
||||
{:else if responseTab === 'headers'}
|
||||
{#if selectedLog.responseHeaders?.length}
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Key</Table.Header.Cell>
|
||||
<Table.Header.Cell>Value</Table.Header.Cell>
|
||||
<Table.Root columns={2} let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell {root}>Key</Table.Header.Cell>
|
||||
<Table.Header.Cell {root}>Value</Table.Header.Cell>
|
||||
</svelte:fragment>
|
||||
{#each selectedLog.responseHeaders as request}
|
||||
<Table.Row>
|
||||
<Table.Cell>{request.name}</Table.Cell>
|
||||
<Table.Cell>{request.value}</Table.Cell>
|
||||
</Table.Row>
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell {root}>{request.name}</Table.Cell>
|
||||
<Table.Cell {root}>{request.value}</Table.Cell>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
|
||||
|
||||
@@ -2,12 +2,11 @@ import type { Column } from '$lib/helpers/types';
|
||||
import { writable } from 'svelte/store';
|
||||
|
||||
export const columns = writable<Column[]>([
|
||||
{ id: '$id', title: 'Log ID', type: 'string', show: true, width: 150 },
|
||||
{ id: '$id', title: 'Log ID', type: 'string', width: 150 },
|
||||
{
|
||||
id: 'requestPath',
|
||||
title: 'Path',
|
||||
type: 'string',
|
||||
show: true,
|
||||
width: 90,
|
||||
format: 'string'
|
||||
},
|
||||
@@ -16,7 +15,7 @@ export const columns = writable<Column[]>([
|
||||
id: 'trigger',
|
||||
title: 'Trigger',
|
||||
type: 'string',
|
||||
show: false,
|
||||
hide: true,
|
||||
width: 90,
|
||||
array: true,
|
||||
format: 'enum',
|
||||
@@ -25,25 +24,23 @@ export const columns = writable<Column[]>([
|
||||
{ value: 'schedule', label: 'Schedule' },
|
||||
{ value: 'event', label: 'Event' }
|
||||
],
|
||||
filter: false,
|
||||
hide: true
|
||||
filter: false
|
||||
},
|
||||
{
|
||||
id: 'requestMethod',
|
||||
title: 'Method',
|
||||
type: 'string',
|
||||
show: false,
|
||||
hide: true,
|
||||
width: 70,
|
||||
array: true,
|
||||
format: 'enum',
|
||||
elements: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],
|
||||
hide: true
|
||||
elements: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE']
|
||||
},
|
||||
{
|
||||
id: 'responseStatusCode',
|
||||
title: 'Status code',
|
||||
type: 'integer',
|
||||
show: false,
|
||||
hide: true,
|
||||
width: 100,
|
||||
format: 'integer',
|
||||
elements: [
|
||||
@@ -64,7 +61,6 @@ export const columns = writable<Column[]>([
|
||||
label: 'Server error (500-599)'
|
||||
}
|
||||
],
|
||||
hide: true,
|
||||
filter: false //TODO: re-enable
|
||||
},
|
||||
|
||||
@@ -72,7 +68,6 @@ export const columns = writable<Column[]>([
|
||||
id: 'duration',
|
||||
title: 'Duration',
|
||||
type: 'integer',
|
||||
show: true,
|
||||
width: 80,
|
||||
format: 'integer',
|
||||
elements: [
|
||||
@@ -89,14 +84,12 @@ export const columns = writable<Column[]>([
|
||||
label: 'more than 30 seconds'
|
||||
}
|
||||
],
|
||||
filter: false,
|
||||
hide: true
|
||||
filter: false
|
||||
},
|
||||
{
|
||||
id: '$createdAt',
|
||||
title: 'Created',
|
||||
type: 'datetime',
|
||||
show: true,
|
||||
width: 120,
|
||||
format: 'datetime',
|
||||
elements: [
|
||||
|
||||
@@ -14,55 +14,46 @@
|
||||
let selectedLogId: string = null;
|
||||
</script>
|
||||
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
{#each columns as column}
|
||||
{#if column.show}
|
||||
<Table.Header.Cell width={column.width + 'px'}>{column.title}</Table.Header.Cell>
|
||||
{/if}
|
||||
<Table.Root {columns} let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
{#each columns as { id, title }}
|
||||
<Table.Header.Cell column={id} {root}>{title}</Table.Header.Cell>
|
||||
{/each}
|
||||
</svelte:fragment>
|
||||
{#each logs.executions as log}
|
||||
<Table.Button
|
||||
<Table.Row.Button
|
||||
{root}
|
||||
on:click={() => {
|
||||
openSheet = true;
|
||||
selectedLogId = log.$id;
|
||||
}}>
|
||||
{#each columns as column}
|
||||
{#if column.show}
|
||||
<Table.Cell column={column.id} {root}>
|
||||
{#if column.id === '$id'}
|
||||
{#key column.id}
|
||||
<Table.Cell>
|
||||
<Id value={log.$id}>{log.$id}</Id>
|
||||
</Table.Cell>
|
||||
<Id value={log.$id}>{log.$id}</Id>
|
||||
{/key}
|
||||
{:else if column.id === '$createdAt'}
|
||||
<Table.Cell>
|
||||
{capitalize(timeFromNow(log.$createdAt))}
|
||||
</Table.Cell>
|
||||
{capitalize(timeFromNow(log.$createdAt))}
|
||||
{:else if column.id === 'responseStatusCode'}
|
||||
<Table.Cell>
|
||||
{log.responseStatusCode}
|
||||
</Table.Cell>
|
||||
{log.responseStatusCode}
|
||||
{:else if column.id === 'requestPath'}
|
||||
<Table.Cell>
|
||||
<Layout.Stack direction="row" alignItems="center" gap="s">
|
||||
<Badge
|
||||
variant="secondary"
|
||||
type={log.responseStatusCode >= 400 ? 'error' : 'success'}
|
||||
content={log.responseStatusCode.toString()} />
|
||||
<Typography.Code size="m">
|
||||
{log.requestMethod}
|
||||
</Typography.Code>
|
||||
<Typography.Code size="m">
|
||||
{log.requestPath}
|
||||
</Typography.Code>
|
||||
</Layout.Stack>
|
||||
</Table.Cell>
|
||||
<Layout.Stack direction="row" alignItems="center" gap="s">
|
||||
<Badge
|
||||
variant="secondary"
|
||||
type={log.responseStatusCode >= 400 ? 'error' : 'success'}
|
||||
content={log.responseStatusCode.toString()} />
|
||||
<Typography.Code size="m">
|
||||
{log.requestMethod}
|
||||
</Typography.Code>
|
||||
<Typography.Code size="m">
|
||||
{log.requestPath}
|
||||
</Typography.Code>
|
||||
</Layout.Stack>
|
||||
{/if}
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
{/each}
|
||||
</Table.Button>
|
||||
</Table.Row.Button>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user