fix: various things

This commit is contained in:
Torsten Dittmann
2025-02-20 14:31:21 +01:00
parent 9e6193f74c
commit 9db43d5b32
36 changed files with 727 additions and 501 deletions
+2 -2
View File
@@ -21,9 +21,9 @@
"dependencies": {
"@appwrite.io/console": "https://pkg.pr.new/appwrite/appwrite/@appwrite.io/console@d13e864",
"@appwrite.io/pink-icons": "0.25.0",
"@appwrite.io/pink-icons-svelte": "https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@2ff4e332",
"@appwrite.io/pink-icons-svelte": "https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@011c2131",
"@appwrite.io/pink-legacy": "^1.0.1",
"@appwrite.io/pink-svelte": "https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@134aa5d",
"@appwrite.io/pink-svelte": "https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@011c2131",
"@popperjs/core": "^2.11.8",
"@sentry/sveltekit": "^8.38.0",
"@stripe/stripe-js": "^3.5.0",
+14 -14
View File
@@ -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@2ff4e332
version: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@2ff4e332(svelte@4.2.19)
specifier: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@011c2131
version: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@011c2131(svelte@4.2.19)
'@appwrite.io/pink-legacy':
specifier: ^1.0.1
version: 1.0.1
'@appwrite.io/pink-svelte':
specifier: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@134aa5d
version: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@134aa5d(react-dom@18.3.1(react@18.3.1))(svelte@4.2.19)
specifier: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@011c2131
version: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@011c2131(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@d13e864}
version: 1.2.1
'@appwrite.io/pink-icons-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@134aa5d0d1920f2524d866d213e1134cb62f8962':
resolution: {tarball: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@134aa5d0d1920f2524d866d213e1134cb62f8962}
'@appwrite.io/pink-icons-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@011c2131':
resolution: {tarball: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@011c2131}
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@2ff4e332':
resolution: {tarball: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@2ff4e332}
'@appwrite.io/pink-icons-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@011c21311ddfbacaa53563f02a1dcba32db8b595':
resolution: {tarball: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@011c21311ddfbacaa53563f02a1dcba32db8b595}
version: 1.0.0-next.7
peerDependencies:
svelte: ^4.0.0
@@ -236,8 +236,8 @@ packages:
'@appwrite.io/pink-legacy@1.0.1':
resolution: {integrity: sha512-e5IZx2drqSxgl2WXvmr0eLfg/WiOCzuqQE8oksD+9GoFBkcL9HWvXul5GjFni3RBAN9XFRL3nUExGk4T0H8sFw==}
'@appwrite.io/pink-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@134aa5d':
resolution: {tarball: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@134aa5d}
'@appwrite.io/pink-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@011c2131':
resolution: {tarball: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@011c2131}
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@d13e864': {}
'@appwrite.io/pink-icons-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@134aa5d0d1920f2524d866d213e1134cb62f8962(svelte@4.2.19)':
'@appwrite.io/pink-icons-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@011c2131(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@2ff4e332(svelte@4.2.19)':
'@appwrite.io/pink-icons-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@011c21311ddfbacaa53563f02a1dcba32db8b595(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@134aa5d(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@011c2131(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@134aa5d0d1920f2524d866d213e1134cb62f8962(svelte@4.2.19)
'@appwrite.io/pink-icons-svelte': https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@011c21311ddfbacaa53563f02a1dcba32db8b595(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)
+117 -84
View File
@@ -1,5 +1,121 @@
{
"backgroundColor": "rgba(255,255,255,0)",
"backgroundColor": "var(--color-bgcolor-neutral-primary)",
"categoryAxis": {
"axisLine": {
"lineStyle": {
"color": "var(--color-fgcolor-neutral-tertiary)"
},
"show": true
},
"axisTick": {
"lineStyle": {
"color": "var(--color-fgcolor-neutral-tertiary)"
},
"show": true
},
"axisLabel": {
"color": "var(--color-fgcolor-neutral-tertiary)",
"show": true
},
"splitLine": {
"show": false
},
"splitArea": {
"show": false
}
},
"valueAxis": {
"axisLabel": {
"color": "var(--color-fgcolor-neutral-tertiary)",
"show": true
},
"splitLine": {
"lineStyle": {
"color": ["var(--color-border-neutral)"]
},
"show": true
},
"axisLine": {
"show": false
},
"axisTick": {
"show": false
},
"splitArea": {
"show": false
}
},
"logAxis": {
"axisLine": {
"lineStyle": {
"color": "var(--color-fgcolor-neutral-tertiary)"
},
"show": true
},
"axisTick": {
"lineStyle": {
"color": "var(--color-fgcolor-neutral-tertiary)"
},
"show": true
},
"axisLabel": {
"color": "var(--color-fgcolor-neutral-tertiary)",
"show": true
},
"splitLine": {
"lineStyle": {
"color": ["var(--color-border-neutral)"]
},
"show": true
},
"splitArea": {
"show": false
}
},
"timeAxis": {
"axisLine": {
"lineStyle": {
"color": "var(--color-fgcolor-neutral-tertiary)"
},
"show": true
},
"axisTick": {
"lineStyle": {
"color": "var(--color-fgcolor-neutral-tertiary)"
},
"show": true
},
"axisLabel": {
"color": "var(--color-fgcolor-neutral-tertiary)",
"show": true
},
"splitLine": {
"lineStyle": {
"color": ["var(--color-border-neutral)"]
},
"show": true
},
"splitArea": {
"show": false
}
},
"tooltip": {
"backgroundColor": "var(--color-bgcolor-neutral-primary)",
"borderColor": "var(--color-border-neutral)",
"textStyle": {
"color": "var(--color-fgcolor-neutral-secondary)"
},
"axisPointer": {
"lineStyle": {
"color": "var(--color-border-neutral-strong)",
"width": 1
},
"crossStyle": {
"color": "var(--color-border-neutral-strong)",
"width": 1
}
}
},
"textStyle": {},
"line": {
"itemStyle": {
@@ -12,89 +128,6 @@
"symbol": "emptyCircle",
"smooth": true
},
"bar": {
"itemStyle": {
"barBorderColor": "#ccc"
}
},
"categoryAxis": {
"axisLine": {
"show": true
},
"axisTick": {
"show": true
},
"axisLabel": {
"show": true
},
"splitLine": {
"show": false
},
"splitArea": {
"show": false
}
},
"valueAxis": {
"axisLine": {
"show": false
},
"axisTick": {
"show": false
},
"axisLabel": {
"show": true
},
"splitLine": {
"show": true
},
"splitArea": {
"show": false
}
},
"logAxis": {
"axisLine": {
"show": true
},
"axisTick": {
"show": true
},
"axisLabel": {
"show": true
},
"splitLine": {
"show": true
},
"splitArea": {
"show": false
}
},
"timeAxis": {
"axisLine": {
"show": true
},
"axisTick": {
"show": true
},
"axisLabel": {
"show": true
},
"splitLine": {
"show": true
},
"splitArea": {
"show": false
}
},
"tooltip": {
"axisPointer": {
"lineStyle": {
"width": 1
},
"crossStyle": {
"width": 1
}
}
},
"timeline": {
"lineStyle": {
"width": 1
+2 -4
View File
@@ -4,15 +4,13 @@
import { app } from '$lib/stores/app';
import { dailyFormat, hourlyFormat, defaultConfig } from './config';
import base from './base.json';
import light from './light.json';
import dark from './dark.json';
import type { ECharts } from 'echarts/core';
import type { BarSeriesOption, LineSeriesOption } from 'echarts/charts';
import type { EChartsOption } from 'echarts';
import { wizard } from '$lib/stores/wizard';
registerTheme('light', { ...base, ...light });
registerTheme('dark', { ...base, ...dark });
registerTheme('light', base);
registerTheme('dark', base);
export let options: EChartsOption;
export let series: (BarSeriesOption | LineSeriesOption)[];
+3 -3
View File
@@ -120,10 +120,10 @@
"color": "#444444"
}
},
"backgroundColor": "#373B4D",
"borderColor": "#373B4D",
"backgroundColor": "var(--color-bgcolor-neutral-primary)",
"borderColor": "var(--color-border-neutral)",
"textStyle": {
"color": "#F2F2F8"
"color": "var(--color-fgcolor-neutral-secondary)"
}
},
"timeline": {
+21 -88
View File
@@ -1,149 +1,82 @@
{
"backgroundColor": "rgba(255,255,255,0)",
"title": {
"textStyle": {
"color": "#373b4d"
},
"subtextStyle": {
"color": "#616b7c"
}
},
"bar": {
"itemStyle": {
"barBorderColor": "#ccc"
}
},
"backgroundColor": "var(--color-bgcolor-neutral-primary)",
"categoryAxis": {
"axisLine": {
"lineStyle": {
"color": "#6E7079"
"color": "var(--color-fgcolor-neutral-tertiary)"
}
},
"axisTick": {
"lineStyle": {
"color": "#6E7079"
"color": "var(--color-fgcolor-neutral-tertiary)"
}
},
"axisLabel": {
"color": "#6E7079"
"color": "var(--color-fgcolor-neutral-tertiary)"
}
},
"valueAxis": {
"axisLabel": {
"color": "#6E7079"
"color": "var(--color-fgcolor-neutral-tertiary)"
},
"splitLine": {
"lineStyle": {
"color": ["#E8E9F0"]
"color": ["var(--color-border-neutral)"]
}
}
},
"logAxis": {
"axisLine": {
"lineStyle": {
"color": "#6E7079"
"color": "var(--color-fgcolor-neutral-tertiary)"
}
},
"axisTick": {
"lineStyle": {
"color": "#6E7079"
"color": "var(--color-fgcolor-neutral-tertiary)"
}
},
"axisLabel": {
"color": "#6E7079"
"color": "var(--color-fgcolor-neutral-tertiary)"
},
"splitLine": {
"lineStyle": {
"color": ["#E0E6F1"]
"color": ["var(--color-border-neutral)"]
}
}
},
"timeAxis": {
"axisLine": {
"lineStyle": {
"color": "#6E7079"
"color": "var(--color-fgcolor-neutral-tertiary)"
}
},
"axisTick": {
"lineStyle": {
"color": "#6E7079"
"color": "var(--color-fgcolor-neutral-tertiary)"
}
},
"axisLabel": {
"color": "#6E7079"
"color": "var(--color-fgcolor-neutral-tertiary)"
},
"splitLine": {
"lineStyle": {
"color": ["#E0E6F1"]
"color": ["var(--color-border-neutral)"]
}
}
},
"toolbox": {
"iconStyle": {
"borderColor": "#999"
},
"emphasis": {
"iconStyle": {
"borderColor": "#666"
}
}
},
"legend": {
"textStyle": {
"color": "#333"
}
},
"tooltip": {
"backgroundColor": "var(--color-bgcolor-neutral-primary)",
"borderColor": "var(--color-border-neutral)",
"textStyle": {
"color": "var(--color-fgcolor-neutral-secondary)"
},
"axisPointer": {
"lineStyle": {
"color": "#ccc"
"color": "var(--color-border-neutral-strong)"
},
"crossStyle": {
"color": "#ccc"
}
}
},
"timeline": {
"lineStyle": {
"color": "#DAE1F5"
},
"itemStyle": {
"color": "#A4B1D7"
},
"controlStyle": {
"color": "#A4B1D7",
"borderColor": "#A4B1D7"
},
"checkpointStyle": {
"color": "#316bf3",
"borderColor": "#fff"
},
"label": {
"color": "#A4B1D7"
},
"emphasis": {
"itemStyle": {
"color": "#FFF"
},
"controlStyle": {
"color": "#A4B1D7",
"borderColor": "#A4B1D7"
},
"label": {
"color": "#A4B1D7"
}
}
},
"visualMap": {
"color": ["#bf444c", "#d88273", "#f6efa6"]
},
"markPoint": {
"label": {
"color": "#eee"
},
"emphasis": {
"label": {
"color": "#eee"
"color": "var(--color-border-neutral-strong)"
}
}
}
+2 -2
View File
@@ -27,7 +27,7 @@
{#if single}
<Card.Base padding="none">
<Empty title={`Create your first ${target}`} {description} {src}>
<svelte:fragment slot="actions">
<slot name="actions" slot="actions">
<Button
external
{href}
@@ -44,7 +44,7 @@
size="s">
Create {target}
</Button>
</svelte:fragment>
</slot>
</Empty>
</Card.Base>
{:else}
+1 -1
View File
@@ -14,7 +14,7 @@
ValidOperators
} from './store';
import { createEventDispatcher } from 'svelte';
import { Icon } from '@appwrite.io/pink-svelte';
import { Icon, Popover } from '@appwrite.io/pink-svelte';
import { IconFilter } from '@appwrite.io/pink-icons-svelte';
export let query = '[]';
+35 -27
View File
@@ -1,14 +1,13 @@
<script lang="ts">
import { createEventDispatcher } from 'svelte';
import { DropList, DropListItem } from '..';
import Label from './label.svelte';
import Custom from './custom.svelte';
import Team from './team.svelte';
import User from './user.svelte';
import type { Permission } from './permissions.svelte';
import type { Writable } from 'svelte/store';
import { ActionMenu, Popover } from '@appwrite.io/pink-svelte';
export let showDropdown: boolean;
export let showUser: boolean;
export let showTeam: boolean;
export let showLabel: boolean;
@@ -16,34 +15,43 @@
export let groups: Writable<Map<string, Permission>>;
const dispatch = createEventDispatcher();
$: if (showUser || showTeam || showCustom) {
showDropdown = false;
}
</script>
<DropList bind:show={showDropdown} placement="bottom-end" fixed>
<slot />
<svelte:fragment slot="list">
<DropListItem disabled={$groups.has('any')} on:click={() => dispatch('create', ['any'])}>
Any
</DropListItem>
<DropListItem
disabled={$groups.has('guests')}
on:click={() => dispatch('create', ['guests'])}>
All guests
</DropListItem>
<DropListItem
disabled={$groups.has('users')}
on:click={() => dispatch('create', ['users'])}>
All users
</DropListItem>
<DropListItem on:click={() => (showUser = true)}>Select users</DropListItem>
<DropListItem on:click={() => (showTeam = true)}>Select teams</DropListItem>
<DropListItem on:click={() => (showLabel = true)}>Label</DropListItem>
<DropListItem on:click={() => (showCustom = true)}>Custom permission</DropListItem>
<Popover let:toggle>
<slot {toggle} />
<svelte:fragment slot="tooltip">
<ActionMenu.Root>
<ActionMenu.Item.Button
disabled={$groups.has('any')}
on:click={() => dispatch('create', ['any'])}>
Any
</ActionMenu.Item.Button>
<ActionMenu.Item.Button
disabled={$groups.has('any')}
on:click={() => dispatch('create', ['any'])}>
Any
</ActionMenu.Item.Button>
<ActionMenu.Item.Button
disabled={$groups.has('guests')}
on:click={() => dispatch('create', ['guests'])}>
All guests
</ActionMenu.Item.Button>
<ActionMenu.Item.Button
disabled={$groups.has('users')}
on:click={() => dispatch('create', ['users'])}>
All users
</ActionMenu.Item.Button>
<ActionMenu.Item.Button on:click={() => (showUser = true)}
>Select users</ActionMenu.Item.Button>
<ActionMenu.Item.Button on:click={() => (showTeam = true)}
>Select teams</ActionMenu.Item.Button>
<ActionMenu.Item.Button on:click={() => (showLabel = true)}
>Label</ActionMenu.Item.Button>
<ActionMenu.Item.Button on:click={() => (showCustom = true)}
>Custom permission</ActionMenu.Item.Button>
</ActionMenu.Root>
</svelte:fragment>
</DropList>
</Popover>
<User bind:show={showUser} on:create {groups} />
<Team
@@ -34,7 +34,6 @@
let showTeam = false;
let showLabel = false;
let showCustom = false;
let showDropdown = false;
const groups = writable<Map<string, Permission>>(new Map());
@@ -71,8 +70,6 @@
return n;
});
showDropdown = false;
}
function fromPermissionString(permission: string): void {
@@ -212,12 +209,12 @@
<Actions
bind:showLabel
bind:showCustom
bind:showDropdown
bind:showTeam
bind:showUser
{groups}
on:create={create}>
<Button text on:click={() => (showDropdown = !showDropdown)}>
on:create={create}
let:toggle>
<Button text on:click={toggle}>
<Icon icon={IconPlus} slot="start" size="s" />
Add role
</Button>
@@ -229,12 +226,12 @@
<Actions
bind:showLabel
bind:showCustom
bind:showDropdown
bind:showTeam
bind:showUser
{groups}
on:create={create}>
<Button secondary icon on:click={() => (showDropdown = !showDropdown)}>
on:create={create}
let:toggle>
<Button secondary icon on:click={toggle}>
<Icon icon={IconPlus} size="s" />
</Button>
</Actions>
+6 -6
View File
@@ -117,12 +117,12 @@
<Actions
bind:showLabel
bind:showCustom
bind:showDropdown
bind:showTeam
bind:showUser
{groups}
on:create={create}>
<Button text on:click={() => (showDropdown = !showDropdown)}>
on:create={create}
let:toggle>
<Button text on:click={toggle}>
<Icon icon={IconPlus} slot="start" size="s" />
Add role
</Button>
@@ -134,12 +134,12 @@
<Actions
bind:showLabel
bind:showCustom
bind:showDropdown
bind:showTeam
bind:showUser
{groups}
on:create={create}>
<Button secondary icon on:click={() => (showDropdown = !showDropdown)}>
on:create={create}
let:toggle>
<Button secondary icon on:click={toggle}>
<Icon icon={IconPlus} size="s" />
</Button>
</Actions>
+1 -1
View File
@@ -9,7 +9,7 @@
</script>
<Base>
<Layout.Stack>
<Layout.Stack gap="s">
{#if isCloud}
{#if $organization?.billingPlan !== BillingPlan.FREE}
<Typography.Text variant="m-600">Roles</Typography.Text>
+6 -27
View File
@@ -1,37 +1,16 @@
<script lang="ts">
import { trackEvent } from '$lib/actions/analytics';
import { IconDuplicate } from '@appwrite.io/pink-icons-svelte';
import { Copy } from '.';
import { Tooltip } from '@appwrite.io/pink-svelte';
import { Input } from '@appwrite.io/pink-svelte';
export let show = false;
export let value: string;
export let copyEvent: string = null;
</script>
<div class="interactive-text-output" class:is-textarea={show} data-private>
{#if show}
<span class="text u-line-height-1-5 u-break-all">{value}</span>
{:else}
<span class="text">••••••••••••</span>
{/if}
<div class="u-flex u-cross-child-start u-gap-8">
<Tooltip>
<button
class="interactive-text-output-button"
aria-label="show hidden text"
type="button"
on:click={() => {
show = !show;
trackEvent(`click_secret_${show ? 'show' : 'hide'}`);
}}>
<span class:icon-eye-off={show} class:icon-eye={!show} aria-hidden="true" />
</button>
<span slot="tooltip">{show ? 'Hide secret' : 'Show secret'}</span>
</Tooltip>
<Input.Password {value}>
<div slot="end">
<Copy {value} event={copyEvent} eventContext="click_secret_copy">
<button class="interactive-text-output-button" aria-label="copy text" type="button">
<span class="icon-duplicate" aria-hidden="true" />
</button>
<Input.Action icon={IconDuplicate} />
</Copy>
</div>
</div>
</Input.Password>
+1
View File
@@ -279,6 +279,7 @@
</div>
</Sidebar.Base>
</div>
{#if subNavigation}
<div class="sub-navigation" class:icons={state === 'icons'}>
<svelte:component this={subNavigation} />
+14 -11
View File
@@ -1,6 +1,7 @@
<script lang="ts">
import { Heading } from '$lib/components';
import { wizard } from '$lib/stores/wizard';
import { Layout } from '@appwrite.io/pink-svelte';
import { onDestroy } from 'svelte';
/**
@@ -20,18 +21,20 @@
}
</script>
<header class="form-header" class:hide-divider={!$$slots.subtitle}>
<Heading tag="h1" size="6">
<slot name="title" />
</Heading>
{#if $$slots.subtitle}
<p>
<slot name="subtitle" />
</p>
{/if}
</header>
<Layout.Stack>
<header class="form-header" class:hide-divider={!$$slots.subtitle}>
<Heading tag="h1" size="6">
<slot name="title" />
</Heading>
{#if $$slots.subtitle}
<p>
<slot name="subtitle" />
</p>
{/if}
</header>
<slot />
<slot />
</Layout.Stack>
<style>
.hide-divider {
+33 -30
View File
@@ -23,6 +23,7 @@
import { wizard } from '$lib/stores/wizard';
import { createEventDispatcher, type SvelteComponent } from 'svelte';
import WizardExitModal from './wizardExitModal.svelte';
import { Layout } from '@appwrite.io/pink-svelte';
export let title: string;
export let steps: WizardStepsType;
@@ -192,38 +193,40 @@
{/if}
</div>
<div class="wizard-main">
<Form noStyle onSubmit={submit}>
{#each sortedSteps as [step, { component }]}
{#if $wizard.step === step}
<svelte:component this={component} />
{/if}
{/each}
<div class="u-z-index-5 form-footer">
<div class="u-flex u-main-end u-gap-12">
{#if !isLastStep && currentStep?.optional}
<Button text on:click={() => dispatch('finish')}>
Skip optional steps
<Form onSubmit={submit}>
<Layout.Stack>
{#each sortedSteps as [step, { component }]}
{#if $wizard.step === step}
<svelte:component this={component} />
{/if}
{/each}
<div class="u-z-index-5 form-footer">
<div class="u-flex u-main-end u-gap-12">
{#if !isLastStep && currentStep?.optional}
<Button text on:click={() => dispatch('finish')}>
Skip optional steps
</Button>
{/if}
{#if $wizard.step === 1}
<Button secondary on:click={handleExit}>Cancel</Button>
{:else}
<Button secondary on:click={previousStep}>Back</Button>
{/if}
{#if currentStep?.actions}
{#each currentStep.actions as action}
<Button secondary on:click={action.onClick}>
{action.label}</Button>
{/each}
{/if}
<Button submit disabled={$wizard.nextDisabled}>
{isLastStep ? finalAction : 'Next'}
</Button>
{/if}
{#if $wizard.step === 1}
<Button secondary on:click={handleExit}>Cancel</Button>
{:else}
<Button secondary on:click={previousStep}>Back</Button>
{/if}
{#if currentStep?.actions}
{#each currentStep.actions as action}
<Button secondary on:click={action.onClick}>
{action.label}</Button>
{/each}
{/if}
<Button submit disabled={$wizard.nextDisabled}>
{isLastStep ? finalAction : 'Next'}
</Button>
</div>
</div>
</div>
</Layout.Stack>
</Form>
</div>
</section>
@@ -81,10 +81,10 @@
<Table.Header.Cell>Name</Table.Header.Cell>
<Table.Header.Cell>Email</Table.Header.Cell>
<Table.Header.Cell>
<Layout.Stack direction="row" gap="xxs" alignItems="center">
<Layout.Stack direction="row" gap="xxxs" alignItems="center">
Roles
<Popover let:toggle>
<Button.Button icon variant="compact" size="s" on:click={toggle}>
<Button.Button icon variant="extra-compact" size="s" on:click={toggle}>
<Icon size="s" icon={IconInfo} />
</Button.Button>
<svelte:component this={Upgrade} slot="tooltip" />
@@ -28,7 +28,6 @@
const projectId = $page.params.project;
const databaseId = $page.params.database;
let showCreateDropdown = false;
let showEmptyCreateDropdown = false;
let showDropdown = [];
let selectedOption: Option['name'] = null;
@@ -53,7 +52,7 @@
<Heading tag="h2" size="5">Attributes</Heading>
{#if $canWriteCollections}
<CreateAttributeDropdown bind:showCreateDropdown bind:selectedOption bind:showCreate />
<CreateAttributeDropdown bind:selectedOption bind:showCreate />
{/if}
</div>
@@ -197,18 +196,8 @@
<p class="text">Total results: {$attributes.length}</p>
</div>
{:else}
<Empty
allowCreate={$canWriteCollections}
single
target="attribute"
on:click={() => (showEmptyCreateDropdown = true)}>
<div class="u-text-center">
<Heading size="7" tag="h2">Create your first attribute to get started.</Heading>
<p class="body-text-2 u-bold u-margin-block-start-4">
Need a hand? Learn more in our documentation.
</p>
</div>
<div class="u-flex u-gap-16 u-main-center">
<Empty single target="attribute">
<svelte:fragment slot="actions">
<Button
external
href="https://appwrite.io/docs/products/databases/collections#attributes"
@@ -216,21 +205,13 @@
event="empty_documentation"
ariaLabel={`create {target}`}>Documentation</Button>
{#if $canWriteCollections}
<CreateAttributeDropdown
bind:showCreateDropdown={showEmptyCreateDropdown}
bind:selectedOption
bind:showCreate>
<Button
secondary
event="create_attribute"
on:click={() => {
showEmptyCreateDropdown = !showEmptyCreateDropdown;
}}>
<CreateAttributeDropdown bind:selectedOption bind:showCreate let:toggle>
<Button secondary event="create_attribute" on:click={toggle}>
Create attribute
</Button>
</CreateAttributeDropdown>
{/if}
</div>
</svelte:fragment>
</Empty>
{/if}
</Container>
@@ -1,36 +1,30 @@
<script lang="ts">
import { DropList, DropListItem } from '$lib/components';
import { Button } from '$lib/elements/forms';
import { Icon } from '@appwrite.io/pink-svelte';
import { ActionMenu, Icon, Popover } from '@appwrite.io/pink-svelte';
import { attributeOptions, type Option } from './store';
import { IconPlus } from '@appwrite.io/pink-icons-svelte';
export let showCreateDropdown = false;
export let selectedOption: Option['name'] = null;
export let showCreate = false;
</script>
<DropList bind:show={showCreateDropdown} scrollable>
<slot>
<Button
on:click={() => (showCreateDropdown = !showCreateDropdown)}
event="create_attribute">
<Popover let:toggle padding="none">
<slot {toggle}>
<Button on:click={toggle} event="create_attribute">
<Icon icon={IconPlus} slot="start" size="s" />
Create attribute
</Button>
</slot>
<svelte:fragment slot="list">
<ActionMenu.Root slot="tooltip">
{#each attributeOptions as attribute}
<DropListItem
icon={attribute.icon}
<ActionMenu.Item.Button
leadingIcon={attribute.icon}
on:click={() => {
selectedOption = attribute.name;
showCreateDropdown = false;
showCreate = true;
}}>
{attribute.name}
</DropListItem>
</ActionMenu.Item.Button>
{/each}
</svelte:fragment>
</DropList>
</ActionMenu.Root>
</Popover>
@@ -1,31 +1,30 @@
<script lang="ts">
import { DropList, DropListItem } from '$lib/components';
import { createEventDispatcher } from 'svelte';
import { targetsById } from './wizard/store';
import UserTargetsModal from './userTargetsModal.svelte';
import TopicsModal from './topicsModal.svelte';
import { topicsById } from './store';
import type { MessagingProviderType } from '@appwrite.io/console';
import { ActionMenu, Popover } from '@appwrite.io/pink-svelte';
export let showDropdown: boolean;
export let showUserTargets: boolean;
export let showTopics: boolean;
export let providerType: MessagingProviderType = null;
const dispatch = createEventDispatcher();
$: if (showUserTargets || showTopics) {
showDropdown = false;
}
</script>
<DropList bind:show={showDropdown} placement="bottom-end" fixed>
<slot />
<svelte:fragment slot="list">
<DropListItem on:click={() => (showTopics = true)}>Select topics</DropListItem>
<DropListItem on:click={() => (showUserTargets = true)}>Select targets</DropListItem>
<Popover let:toggle placement="bottom-end">
<slot {toggle} />
<svelte:fragment slot="tooltip">
<ActionMenu.Root>
<ActionMenu.Item.Button on:click={() => (showTopics = true)}
>Select topics</ActionMenu.Item.Button>
<ActionMenu.Item.Button on:click={() => (showUserTargets = true)}
>Select targets</ActionMenu.Item.Button>
</ActionMenu.Root>
</svelte:fragment>
</DropList>
</Popover>
<TopicsModal
{providerType}
@@ -17,7 +17,6 @@
import { IconPlus } from '@appwrite.io/pink-icons-svelte';
import { Icon } from '@appwrite.io/pink-svelte';
let showDropdown = false;
let showTopics = false;
let showUserTargets = false;
let targetIdsLength = 0;
@@ -65,12 +64,12 @@
<div class="u-flex u-cross-center u-flex-vertical u-main-center u-flex">
<Actions
providerType={$providerType}
bind:showDropdown
bind:showUserTargets
bind:showTopics
on:addTargets={addTargets}
on:addTopics={addTopics}>
<Button secondary icon on:click={() => (showDropdown = !showDropdown)}>
on:addTopics={addTopics}
let:toggle>
<Button secondary icon on:click={toggle}>
<Icon icon={IconPlus} size="s" />
</Button>
</Actions>
@@ -143,12 +142,12 @@
</div>
<Actions
providerType={$providerType}
bind:showDropdown
bind:showUserTargets
bind:showTopics
on:addTargets={addTargets}
on:addTopics={addTopics}>
<Button text on:click={() => (showDropdown = !showDropdown)}>
on:addTopics={addTopics}
let:toggle>
<Button text on:click={toggle}>
<Icon icon={IconPlus} slot="start" size="s" />
Add
</Button>
@@ -18,7 +18,6 @@
import { project } from '../store';
import Bandwidth from './bandwidth.svelte';
import { createApiKey } from './keys/+page.svelte';
import Onboard from './onboard.svelte';
import Realtime from './realtime.svelte';
import Requests from './requests.svelte';
import { usage } from './store';
@@ -27,7 +26,6 @@
import type { Metric } from '$lib/sdk/usage';
import { periodToDates } from '$lib/layout/usage.svelte';
import { canWriteProjects } from '$lib/stores/roles';
import { hasOnboardingDismissed } from '$lib/helpers/onboarding';
import { Card, Layout, Typography } from '@appwrite.io/pink-svelte';
import { writable, type Writable } from 'svelte/store';
import { IconPlus } from '@appwrite.io/pink-icons-svelte';
@@ -125,13 +123,6 @@
</Typography.Title>
<Typography.Text>Documents</Typography.Text>
</div>
<div class="grid-item-1-end-end">
<Typography.Text
>Databases: {formatNum(
$usage.databasesTotal ?? 0
)}</Typography.Text>
</div>
</div>
</Card.Link>
<Card.Link
@@ -155,12 +146,6 @@
</Typography.Title>
<Typography.Text>Storage</Typography.Text>
</div>
<div class="grid-item-1-end-end">
<Typography.Text>
Buckets: {formatNum($usage.bucketsTotal ?? 0)}
</Typography.Text>
</div>
</div>
</Card.Link>
<Card.Link
@@ -6,8 +6,16 @@
import type { UsagePeriods } from '$lib/layout';
import { createEventDispatcher } from 'svelte';
import { BarChart } from '$lib/charts';
import { Popover, Typography, Icon, ActionMenu, Link, Layout } from '@appwrite.io/pink-svelte';
import { IconChevronDown } from '@appwrite.io/pink-icons-svelte';
import {
Popover,
Typography,
Icon,
ActionMenu,
Link,
Layout,
Button
} from '@appwrite.io/pink-svelte';
import { IconChevronDown, IconChevronUp } from '@appwrite.io/pink-icons-svelte';
export let period: UsagePeriods;
@@ -29,13 +37,11 @@
</Typography.Title>
<Typography.Text>Bandwidth</Typography.Text>
</div>
<Popover let:toggle padding="none">
<Link.Button on:click={toggle} variant="quiet">
<Layout.Stack direction="row" gap="none">
<span>{period}</span>
<Icon icon={IconChevronDown} />
</Layout.Stack>
</Link.Button>
<Popover let:toggle padding="none" let:showing>
<Button.Button on:click={toggle} variant="extra-compact">
{period}
<Icon icon={showing ? IconChevronUp : IconChevronDown} slot="end" />
</Button.Button>
<svelte:fragment slot="tooltip">
<ActionMenu.Root>
<ActionMenu.Item.Button on:click={() => dispatch('change', '24h')}
@@ -62,9 +62,7 @@
<p>Update the expiration date to keep the key active</p>
</Alert>
{/if}
<FormList>
<ExpirationInput bind:value={expiration} />
</FormList>
<ExpirationInput bind:value={expiration} />
</svelte:fragment>
<svelte:fragment slot="actions">
@@ -4,10 +4,12 @@
import { Icon } from '@appwrite.io/pink-svelte';
import { createApiKey } from './+page.svelte';
import { IconPlus } from '@appwrite.io/pink-icons-svelte';
import { base } from '$app/paths';
import { page } from '$app/stores';
</script>
{#if $canWriteKeys}
<Button on:click={createApiKey}>
<Button href={`${base}/project-${$page.params.project}/overview/keys/create`}>
<Icon icon={IconPlus} slot="start" size="s" />
Create API key
</Button>
@@ -0,0 +1,101 @@
<script lang="ts">
import { base } from '$app/paths';
import { page } from '$app/stores';
import Card from '$lib/components/card.svelte';
import { InputText } from '$lib/elements/forms/index.js';
import { Wizard } from '$lib/layout';
import { Fieldset, Layout, Typography } from '@appwrite.io/pink-svelte';
import ExpirationInput from '../expirationInput.svelte';
import Scopes from '../scopes.svelte';
import Button from '$lib/elements/forms/button.svelte';
import Form from '$lib/elements/forms/form.svelte';
import { sdk } from '$lib/stores/sdk';
import { onboarding } from '$routes/(console)/project-[project]/store';
import { goto, invalidate } from '$app/navigation';
import { Dependencies } from '$lib/constants';
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
import { addNotification } from '$lib/stores/notifications';
import { writable } from 'svelte/store';
export let data;
let showExitModal = false;
let formComponent: Form;
let isSubmitting = writable(false);
let name = '',
expire = '';
let scopes = [];
async function create() {
try {
const { $id } = await sdk.forConsole.projects.createKey(
$page.params.project,
name,
scopes,
expire || undefined
);
if ($onboarding) {
await invalidate(Dependencies.PROJECT);
}
trackEvent(Submit.KeyCreate, {
scopes: scopes
});
goto(`${base}/project-${$page.params.project}/overview/keys/${$id}`);
addNotification({
message: `API key has been created`,
type: 'success'
});
} catch (error) {
addNotification({
type: 'error',
message: error.message
});
trackError(error, Submit.KeyCreate);
}
}
</script>
<Wizard
title="Create API key"
href={`${base}/project-${$page.params.project}/overview/keys/`}
bind:showExitModal
column
confirmExit>
<Form bind:this={formComponent} onSubmit={create} bind:isSubmitting>
<Layout.Stack gap="xxl">
<Fieldset legend="Step 1">
<Layout.Stack>
<InputText
id="name"
label="Name"
placeholder="API key name"
required
bind:value={name} />
<ExpirationInput bind:value={expire} />
</Layout.Stack>
</Fieldset>
<Fieldset legend="Scopes">
<Layout.Stack gap="xl">
<Typography.Text>
Choose which permission scopes to grant your application. It is best
practice to allow only the permissions you need to meet your project goals.
</Typography.Text>
<Scopes bind:scopes />
</Layout.Stack>
</Fieldset>
</Layout.Stack>
</Form>
<svelte:fragment slot="footer">
<Button fullWidthMobile secondary on:click={() => (showExitModal = true)}>Cancel</Button>
<Button
fullWidthMobile
on:click={() => formComponent.triggerSubmit()}
disabled={$isSubmitting}>
Create
</Button>
</svelte:fragment>
</Wizard>
@@ -73,7 +73,7 @@
}
</script>
<InputSelect bind:value={expirationSelect} {options} id="preset" label="Expiration Date">
<InputSelect bind:value={expirationSelect} {options} id="preset" label="Expiration date">
<svelte:fragment slot="helper">
{#if expirationSelect !== 'custom' && expirationSelect !== null}
<Helper type="neutral">Your key will expire in {toLocaleDate(value)}</Helper>
@@ -5,6 +5,7 @@
import { onMount } from 'svelte';
import { symmetricDifference } from '$lib/helpers/array';
import Checkbox from './checkbox.svelte';
import { Accordion, Divider, Input, Layout, Selector } from '@appwrite.io/pink-svelte';
export let scopes: string[];
@@ -81,47 +82,36 @@
}
</script>
<ul class="buttons-list u-main-end">
<li class="buttons-list-item">
<Layout.Stack>
<Layout.Stack direction="row-reverse" alignItems="center" gap="s">
<Button text on:click={deselectAll}>Deselect all</Button>
</li>
<li class="buttons-list-item">
<span style:height="20px">
<Divider vertical />
</span>
<Button text on:click={selectAll}>Select all</Button>
</li>
</ul>
<Collapsible>
{#each [Category.Auth, Category.Database, Category.Functions, Category.Storage, Category.Messaging, Category.Other] as category}
{@const checked = categoryState(category, scopes)}
<CollapsibleItem withIndentation>
<svelte:fragment slot="beforetitle">
<Checkbox
{checked}
indeterminate={checked === null ? true : false}
on:change={(e) => onCategoryChange(e, category)} />
</svelte:fragment>
<svelte:fragment slot="title">
{category}
</svelte:fragment>
<svelte:fragment slot="subtitle">
{@const scopesLength = allScopes.filter(
(n) => n.category === category && scopes.includes(n.scope)
).length}
({scopesLength}
{scopesLength === 1 ? 'Scope' : 'Scopes'})
</svelte:fragment>
<div class="form">
<FormList>
</Layout.Stack>
<Layout.Stack gap="none">
{#each [Category.Auth, Category.Database, Category.Functions, Category.Storage, Category.Messaging, Category.Other] as category}
{@const checked = categoryState(category, scopes)}
{@const scopesLength = allScopes.filter(
(n) => n.category === category && scopes.includes(n.scope)
).length}
<Accordion
selectable
title={category}
badge={`${scopesLength} ${scopesLength === 1 ? 'Scope' : 'Scopes'}`}
{checked}>
<Layout.Stack>
{#each allScopes.filter((s) => s.category === category) as scope}
<InputChoice
<Selector.Checkbox
size="s"
id={scope.scope}
label={scope.scope}
bind:value={activeScopes[scope.scope]}>
{scope.description}
</InputChoice>
description={scope.description}
bind:checked={activeScopes[scope.scope]} />
{/each}
</FormList>
</div>
</CollapsibleItem>
{/each}
</Collapsible>
</Layout.Stack>
</Accordion>
{/each}
</Layout.Stack>
</Layout.Stack>
@@ -1,5 +1,5 @@
<script lang="ts">
import { FormList, InputText } from '$lib/elements/forms';
import { InputText } from '$lib/elements/forms';
import { WizardStep } from '$lib/layout';
import ExpirationInput from '../expirationInput.svelte';
import { key } from './store';
@@ -7,14 +7,6 @@
<WizardStep>
<svelte:fragment slot="title">API key</svelte:fragment>
<svelte:fragment slot="subtitle">Let's create an API key.</svelte:fragment>
<FormList>
<InputText
id="name"
label="Name"
placeholder="API key name"
required
bind:value={$key.name} />
<ExpirationInput bind:value={$key.expire} />
</FormList>
<InputText id="name" label="Name" placeholder="API key name" required bind:value={$key.name} />
<ExpirationInput bind:value={$key.expire} />
</WizardStep>
@@ -1,5 +1,4 @@
<script lang="ts">
import { FormList } from '$lib/elements/forms';
import { WizardStep } from '$lib/layout';
import Scopes from '../scopes.svelte';
import { key } from './store';
@@ -11,7 +10,5 @@
Choose which permission scopes to grant your application. It is best practice to allow only
the permissions you need to meet your project goals.
</svelte:fragment>
<FormList>
<Scopes bind:scopes={$key.scopes} />
</FormList>
<Scopes bind:scopes={$key.scopes} />
</WizardStep>
@@ -54,14 +54,20 @@
<script lang="ts">
import { base } from '$app/paths';
import { page } from '$app/stores';
import { DropList, DropListItem, Heading } from '$lib/components';
import { Button } from '$lib/elements/forms';
import { toLocaleDate } from '$lib/helpers/date';
import { app } from '$lib/stores/app';
import type { PageData } from './$types';
import { canWritePlatforms } from '$lib/stores/roles';
import { setOverviewAction } from '../context';
import { ActionMenu, Card, Empty, Popover, Table } from '@appwrite.io/pink-svelte';
import {
ActionMenu,
Card,
Empty,
Icon,
Layout,
Popover,
Table
} from '@appwrite.io/pink-svelte';
import Action from './action.svelte';
import {
IconAndroid,
@@ -70,6 +76,7 @@
IconFlutter,
IconReact
} from '@appwrite.io/pink-icons-svelte';
import type { ComponentType } from 'svelte';
export let data: PageData;
@@ -89,22 +96,21 @@
'react-native-ios' = 'iOS',
'web' = 'Web'
}
let showDropdownEmpty = false;
const path = `${base}/project-${$page.params.project}/overview/platforms`;
const getPlatformInfo = (platform: string) => {
function getPlatformInfo(platform: string): ComponentType {
if (platform.includes('flutter')) {
return 'color/flutter';
return IconFlutter;
} else if (platform.includes('react-native')) {
return 'color/react';
return IconReact;
} else if (platform.includes('apple')) {
return 'color/apple';
return IconApple;
} else if (platform.includes('android')) {
return 'color/android';
return IconAndroid;
} else {
return 'unknown';
return IconCode;
}
};
}
setOverviewAction(Action);
</script>
@@ -122,7 +128,10 @@
{platform.name}
</Table.Cell>
<Table.Cell>
{PlatformTypes[platform.type]}
<Layout.Stack direction="row" gap="s" alignItems="center">
<Icon icon={getPlatformInfo(platform.type)} />
{PlatformTypes[platform.type]}
</Layout.Stack>
</Table.Cell>
<Table.Cell>
{platform.$updatedAt ? toLocaleDate(platform.$updatedAt) : 'never'}
@@ -143,7 +152,7 @@
<span class="text">Add platform</span>
</Button>
{/if}
<div style:min-width="232px" slot="tooltip">
<svelte:fragment slot="tooltip">
<ActionMenu.Root>
<ActionMenu.Item.Button
on:click={() => addPlatform(Platform.Web)}
@@ -171,7 +180,7 @@
React Native
</ActionMenu.Item.Button>
</ActionMenu.Root>
</div>
</svelte:fragment>
</Popover>
</svelte:fragment>
</Empty>
@@ -49,14 +49,12 @@
<svelte:fragment slot="title">Package name</svelte:fragment>
Your package name is generally the applicationId in your app-level build.gradle file.
<svelte:fragment slot="aside">
<FormList>
<InputText
id="key"
label="Package Name"
bind:value={key}
required
placeholder="com.company.appname" />
</FormList>
<InputText
id="key"
label="Package name"
bind:value={key}
required
placeholder="com.company.appname" />
</svelte:fragment>
<svelte:fragment slot="actions">
@@ -49,14 +49,12 @@
<svelte:fragment slot="title">Package name</svelte:fragment>
Your package name is generally the applicationId in your app-level build.gradle file.
<svelte:fragment slot="aside">
<FormList>
<InputText
id="package-name"
label="Package Name"
bind:value={key}
required
placeholder="com.company.appname" />
</FormList>
<InputText
id="package-name"
label="Package name"
bind:value={key}
required
placeholder="com.company.appname" />
</svelte:fragment>
<svelte:fragment slot="actions">
@@ -1,28 +1,29 @@
<script lang="ts">
import { Card, DropList, DropListItem } from '$lib/components';
import { Card } from '$lib/components';
import { totalMetrics } from './+layout.svelte';
import { usage } from './store';
import type { UsagePeriods } from '$lib/layout';
import { createEventDispatcher } from 'svelte';
import { LineChart } from '$lib/charts';
import { formatNum } from '$lib/helpers/string';
import { ActionMenu, Icon, Layout, Link, Popover, Typography } from '@appwrite.io/pink-svelte';
import { IconChevronDown } from '@appwrite.io/pink-icons-svelte';
import {
ActionMenu,
Icon,
Layout,
Button,
Popover,
Typography
} from '@appwrite.io/pink-svelte';
import { IconChevronDown, IconChevronUp } from '@appwrite.io/pink-icons-svelte';
export let period: UsagePeriods;
let showPeriod = false;
const dispatch = createEventDispatcher();
$: requests = $usage?.requests as unknown as Array<{
date: number;
value: number;
}>;
$: if (period) {
showPeriod = false;
}
</script>
<Layout.Stack justifyContent="space-between" direction="row" alignItems="flex-start">
@@ -32,13 +33,11 @@
</Typography.Title>
<Typography.Text>Requests</Typography.Text>
</div>
<Popover let:toggle padding="none">
<Link.Button on:click={toggle} variant="quiet">
<Layout.Stack direction="row" gap="none">
<span>{period}</span>
<Icon icon={IconChevronDown} />
</Layout.Stack>
</Link.Button>
<Popover let:toggle padding="none" let:showing>
<Button.Button on:click={toggle} variant="extra-compact">
{period}
<Icon icon={showing ? IconChevronUp : IconChevronDown} slot="end" />
</Button.Button>
<ActionMenu.Root slot="tooltip">
<ActionMenu.Item.Button on:click={() => dispatch('change', '24h')}
>24h</ActionMenu.Item.Button>
@@ -13,6 +13,231 @@ export const usage = cachedStore<
load: async (start, end, period) => {
const usages = await sdk.forProject.project.getUsage(start, end, period);
set(usages);
set({
executionsTotal: 123,
documentsTotal: 123,
databasesTotal: 123,
databasesStorageTotal: 123,
usersTotal: 1123,
filesStorageTotal: 123,
functionsStorageTotal: 15152301,
buildsStorageTotal: 15152301,
deploymentsStorageTotal: 123,
bucketsTotal: 123,
executionsMbSecondsTotal: 234234,
buildsMbSecondsTotal: 6912,
databasesReadsTotal: 234324,
databasesWritesTotal: 234234,
requests: [
{ value: 1, date: '2025-01-20T00:00:00.000+00:00' },
{ value: 4, date: '2025-01-21T00:00:00.000+00:00' },
{ value: 10, date: '2025-01-22T00:00:00.000+00:00' },
{ value: 45, date: '2025-01-23T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-24T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-25T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-26T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-27T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-28T00:00:00.000+00:00' },
{ value: 23, date: '2025-01-29T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-30T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-31T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-01T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-02T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-03T00:00:00.000+00:00' },
{ value: 23, date: '2025-02-04T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-05T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-06T00:00:00.000+00:00' },
{ value: 2, date: '2025-02-07T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-08T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-09T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-10T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-11T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-12T00:00:00.000+00:00' },
{ value: 234, date: '2025-02-13T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-14T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-15T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-16T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-17T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-18T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-19T00:00:00.000+00:00' }
],
network: [
{ date: '2025-01-20T00:00:00.000+00:00', value: 0 },
{ date: '2025-01-21T00:00:00.000+00:00', value: 0 },
{ date: '2025-01-22T00:00:00.000+00:00', value: 0 },
{ date: '2025-01-23T00:00:00.000+00:00', value: 123 },
{ date: '2025-01-24T00:00:00.000+00:00', value: 0 },
{ date: '2025-01-25T00:00:00.000+00:00', value: 0 },
{ date: '2025-01-26T00:00:00.000+00:00', value: 0 },
{ date: '2025-01-27T00:00:00.000+00:00', value: 0 },
{ date: '2025-01-28T00:00:00.000+00:00', value: 0 },
{ date: '2025-01-29T00:00:00.000+00:00', value: 0 },
{ date: '2025-01-30T00:00:00.000+00:00', value: 1 },
{ date: '2025-01-31T00:00:00.000+00:00', value: 0 },
{ date: '2025-02-01T00:00:00.000+00:00', value: 0 },
{ date: '2025-02-02T00:00:00.000+00:00', value: 0 },
{ date: '2025-02-03T00:00:00.000+00:00', value: 0 },
{ date: '2025-02-04T00:00:00.000+00:00', value: 0 },
{ date: '2025-02-05T00:00:00.000+00:00', value: 2 },
{ date: '2025-02-06T00:00:00.000+00:00', value: 0 },
{ date: '2025-02-07T00:00:00.000+00:00', value: 0 },
{ date: '2025-02-08T00:00:00.000+00:00', value: 0 },
{ date: '2025-02-09T00:00:00.000+00:00', value: 0 },
{ date: '2025-02-10T00:00:00.000+00:00', value: 0 },
{ date: '2025-02-11T00:00:00.000+00:00', value: 0 },
{ date: '2025-02-12T00:00:00.000+00:00', value: 0 },
{ date: '2025-02-13T00:00:00.000+00:00', value: 0 },
{ date: '2025-02-14T00:00:00.000+00:00', value: 0 },
{ date: '2025-02-15T00:00:00.000+00:00', value: 0 },
{ date: '2025-02-16T00:00:00.000+00:00', value: 0 },
{ date: '2025-02-17T00:00:00.000+00:00', value: 0 },
{ date: '2025-02-18T00:00:00.000+00:00', value: 45 },
{ date: '2025-02-19T00:00:00.000+00:00', value: 0 }
],
users: [
{ value: 0, date: '2025-01-20T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-21T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-22T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-23T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-24T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-25T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-26T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-27T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-28T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-29T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-30T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-31T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-01T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-02T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-03T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-04T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-05T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-06T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-07T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-08T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-09T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-10T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-11T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-12T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-13T00:00:00.000+00:00' },
{ value: 1, date: '2025-02-14T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-15T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-16T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-17T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-18T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-19T00:00:00.000+00:00' }
],
executions: [
{ value: 0, date: '2025-01-20T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-21T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-22T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-23T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-24T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-25T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-26T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-27T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-28T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-29T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-30T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-31T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-01T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-02T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-03T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-04T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-05T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-06T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-07T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-08T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-09T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-10T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-11T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-12T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-13T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-14T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-15T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-16T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-17T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-18T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-19T00:00:00.000+00:00' }
],
executionsBreakdown: [],
bucketsBreakdown: [],
databasesStorageBreakdown: [
{ resourceId: '67b5ee88002a0f1572ef', name: 'test', value: 0 }
],
executionsMbSecondsBreakdown: [],
buildsMbSecondsBreakdown: [],
functionsStorageBreakdown: [],
authPhoneTotal: 0,
authPhoneEstimate: 0,
authPhoneCountryBreakdown: [],
databasesReads: [
{ value: 0, date: '2025-01-20T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-21T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-22T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-23T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-24T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-25T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-26T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-27T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-28T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-29T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-30T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-31T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-01T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-02T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-03T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-04T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-05T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-06T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-07T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-08T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-09T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-10T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-11T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-12T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-13T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-14T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-15T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-16T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-17T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-18T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-19T00:00:00.000+00:00' }
],
databasesWrites: [
{ value: 0, date: '2025-01-20T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-21T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-22T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-23T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-24T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-25T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-26T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-27T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-28T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-29T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-30T00:00:00.000+00:00' },
{ value: 0, date: '2025-01-31T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-01T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-02T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-03T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-04T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-05T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-06T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-07T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-08T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-09T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-10T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-11T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-12T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-13T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-14T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-15T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-16T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-17T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-18T00:00:00.000+00:00' },
{ value: 0, date: '2025-02-19T00:00:00.000+00:00' }
]
});
}
};
});
@@ -3,9 +3,7 @@
import { base } from '$app/paths';
import { page } from '$app/stores';
import { Submit, trackEvent, trackError } from '$lib/actions/analytics';
import { Modal } from '$lib/components';
import Confirm from '$lib/components/confirm.svelte';
import { Button } from '$lib/elements/forms';
import { addNotification } from '$lib/stores/notifications';
import { sdk } from '$lib/stores/sdk';