mirror of
https://github.com/appwrite/console.git
synced 2026-06-06 19:27:48 +00:00
Merge branch 'feat-pink-v2' into 'remove-jwt'.
This commit is contained in:
+1
-1
@@ -27,7 +27,7 @@
|
||||
"@appwrite.io/pink-icons": "0.25.0",
|
||||
"@appwrite.io/pink-icons-svelte": "https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@d68e5e4",
|
||||
"@appwrite.io/pink-legacy": "^1.0.3",
|
||||
"@appwrite.io/pink-svelte": "https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@d68e5e4",
|
||||
"@appwrite.io/pink-svelte": "https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@b39a7c4",
|
||||
"@popperjs/core": "^2.11.8",
|
||||
"@sentry/sveltekit": "^8.38.0",
|
||||
"@stripe/stripe-js": "^3.5.0",
|
||||
|
||||
Generated
+12
-12
@@ -27,8 +27,8 @@ importers:
|
||||
specifier: ^1.0.3
|
||||
version: 1.0.3
|
||||
'@appwrite.io/pink-svelte':
|
||||
specifier: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@d68e5e4
|
||||
version: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@d68e5e4(react-dom@18.3.1(react@18.3.1))(svelte@5.25.3)
|
||||
specifier: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@b39a7c4
|
||||
version: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@b39a7c4(react-dom@18.3.1(react@18.3.1))(svelte@5.25.3)
|
||||
'@popperjs/core':
|
||||
specifier: ^2.11.8
|
||||
version: 2.11.8
|
||||
@@ -258,14 +258,14 @@ packages:
|
||||
resolution: {tarball: https://pkg.pr.new/appwrite/appwrite/@appwrite.io/console@c2f54c6}
|
||||
version: 1.2.1
|
||||
|
||||
'@appwrite.io/pink-icons-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@d68e5e4':
|
||||
resolution: {tarball: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@d68e5e4}
|
||||
'@appwrite.io/pink-icons-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@b39a7c45d4b8ebf03059018d195141c8d2b7c221':
|
||||
resolution: {tarball: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@b39a7c45d4b8ebf03059018d195141c8d2b7c221}
|
||||
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@d68e5e4de190f223a64383f8b35e04624c577513':
|
||||
resolution: {tarball: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@d68e5e4de190f223a64383f8b35e04624c577513}
|
||||
'@appwrite.io/pink-icons-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@d68e5e4':
|
||||
resolution: {tarball: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@d68e5e4}
|
||||
version: 1.0.0-next.7
|
||||
peerDependencies:
|
||||
svelte: ^4.0.0
|
||||
@@ -279,8 +279,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@d68e5e4':
|
||||
resolution: {tarball: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@d68e5e4}
|
||||
'@appwrite.io/pink-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@b39a7c4':
|
||||
resolution: {tarball: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@b39a7c4}
|
||||
version: 1.0.0-next.85
|
||||
peerDependencies:
|
||||
react-dom: ^18.0.0
|
||||
@@ -3627,11 +3627,11 @@ snapshots:
|
||||
|
||||
'@appwrite.io/console@https://pkg.pr.new/appwrite/appwrite/@appwrite.io/console@c2f54c6': {}
|
||||
|
||||
'@appwrite.io/pink-icons-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@d68e5e4(svelte@5.25.3)':
|
||||
'@appwrite.io/pink-icons-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@b39a7c45d4b8ebf03059018d195141c8d2b7c221(svelte@5.25.3)':
|
||||
dependencies:
|
||||
svelte: 5.25.3
|
||||
|
||||
'@appwrite.io/pink-icons-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@d68e5e4de190f223a64383f8b35e04624c577513(svelte@5.25.3)':
|
||||
'@appwrite.io/pink-icons-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@d68e5e4(svelte@5.25.3)':
|
||||
dependencies:
|
||||
svelte: 5.25.3
|
||||
|
||||
@@ -3644,9 +3644,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@d68e5e4(react-dom@18.3.1(react@18.3.1))(svelte@5.25.3)':
|
||||
'@appwrite.io/pink-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@b39a7c4(react-dom@18.3.1(react@18.3.1))(svelte@5.25.3)':
|
||||
dependencies:
|
||||
'@appwrite.io/pink-icons-svelte': https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@d68e5e4de190f223a64383f8b35e04624c577513(svelte@5.25.3)
|
||||
'@appwrite.io/pink-icons-svelte': https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@b39a7c45d4b8ebf03059018d195141c8d2b7c221(svelte@5.25.3)
|
||||
'@floating-ui/dom': 1.6.13
|
||||
'@melt-ui/pp': 0.3.2(@melt-ui/svelte@0.86.6(svelte@5.25.3))(svelte@5.25.3)
|
||||
'@melt-ui/svelte': 0.86.6(svelte@5.25.3)
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import { goto } from '$app/navigation';
|
||||
import { project } from '$routes/(console)/project-[region]-[project]/store';
|
||||
import { get } from 'svelte/store';
|
||||
import type { Searcher } from '../commands';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { base } from '$app/paths';
|
||||
|
||||
@@ -11,14 +11,7 @@
|
||||
} from '$lib/elements/forms';
|
||||
import type { Writable } from 'svelte/store';
|
||||
import Modal from '../modal.svelte';
|
||||
import {
|
||||
addFilter,
|
||||
generateTag,
|
||||
operators,
|
||||
queries,
|
||||
ValidOperators,
|
||||
type TagValue
|
||||
} from './store';
|
||||
import { generateTag, operators, ValidOperators, type TagValue } from './store';
|
||||
import type { Column } from '$lib/helpers/types';
|
||||
import { TagList } from '.';
|
||||
import { Icon, Layout } from '@appwrite.io/pink-svelte';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import type { Column } from '$lib/helpers/types';
|
||||
import { type Writable } from 'svelte/store';
|
||||
import { CustomFilters, FiltersBottomSheet } from '$lib/components/filters';
|
||||
import { CustomFilters } from '$lib/components/filters';
|
||||
import { addFilterAndApply, type FilterData } from './quickFilters';
|
||||
import { parsedTags } from './setFilters';
|
||||
import Menu from '../menu/menu.svelte';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { Button, InputSelect, InputText } from '$lib/elements/forms';
|
||||
import { Button, InputText } from '$lib/elements/forms';
|
||||
import { Fieldset, Input, Layout, Selector, Skeleton } from '@appwrite.io/pink-svelte';
|
||||
import SelectRootModal from './selectRootModal.svelte';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
Typography,
|
||||
Icon,
|
||||
Avatar,
|
||||
Skeleton,
|
||||
Button as PinkButton
|
||||
} from '@appwrite.io/pink-svelte';
|
||||
import { IconLockClosed, IconPlus } from '@appwrite.io/pink-icons-svelte';
|
||||
@@ -43,7 +42,7 @@
|
||||
} = $props();
|
||||
|
||||
let search = $state('');
|
||||
let selectedInstallation = null;
|
||||
let selectedInstallation: string = null;
|
||||
let isLoadingRepositories = $state(null);
|
||||
|
||||
async function loadInstallations() {
|
||||
@@ -111,6 +110,8 @@
|
||||
$repositories.search = search;
|
||||
$repositories.installationId = installationId;
|
||||
}
|
||||
|
||||
$inspect(selectedRepository);
|
||||
</script>
|
||||
|
||||
{#if hasInstallations}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { Card, Tooltip, Icon } from '@appwrite.io/pink-svelte';
|
||||
import { Card, Tooltip } from '@appwrite.io/pink-svelte';
|
||||
import type { HTMLAttributes } from 'svelte/elements';
|
||||
import type { BaseCardProps } from './card.svelte';
|
||||
import type { ComponentType } from 'svelte';
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
$: totalPages = Math.ceil(total / limit);
|
||||
$: currentPage = Math.floor(offset / limit + 1);
|
||||
$: pages = pagination(currentPage, totalPages);
|
||||
// $: pages = pagination(currentPage, totalPages);
|
||||
|
||||
function handleOptionClick(e: CustomEvent) {
|
||||
if (currentPage !== e.detail) {
|
||||
@@ -35,22 +35,22 @@
|
||||
}
|
||||
}
|
||||
|
||||
function pagination(page: number, total: number) {
|
||||
const pagesShown = 5;
|
||||
const start = Math.max(
|
||||
1,
|
||||
Math.min(page - Math.floor((pagesShown - 3) / 2), total - pagesShown + 2)
|
||||
);
|
||||
const end = Math.min(
|
||||
total,
|
||||
Math.max(page + Math.floor((pagesShown - 2) / 2), pagesShown - 1)
|
||||
);
|
||||
return [
|
||||
...(start > 2 ? [1, '...'] : start > 1 ? [1] : []),
|
||||
...Array.from({ length: end + 1 - start }, (_, i) => i + start),
|
||||
...(end < total - 1 ? ['...', total] : end < total ? [total] : [])
|
||||
];
|
||||
}
|
||||
// function pagination(page: number, total: number) {
|
||||
// const pagesShown = 5;
|
||||
// const start = Math.max(
|
||||
// 1,
|
||||
// Math.min(page - Math.floor((pagesShown - 3) / 2), total - pagesShown + 2)
|
||||
// );
|
||||
// const end = Math.min(
|
||||
// total,
|
||||
// Math.max(page + Math.floor((pagesShown - 2) / 2), pagesShown - 1)
|
||||
// );
|
||||
// return [
|
||||
// ...(start > 2 ? [1, '...'] : start > 1 ? [1] : []),
|
||||
// ...Array.from({ length: end + 1 - start }, (_, i) => i + start),
|
||||
// ...(end < total - 1 ? ['...', total] : end < total ? [total] : [])
|
||||
// ];
|
||||
// }
|
||||
</script>
|
||||
|
||||
{#if !hidePages}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
hasLimit = false,
|
||||
name = 'items',
|
||||
gap = 's',
|
||||
offset = $bindable(0),
|
||||
children
|
||||
}: {
|
||||
items: T[];
|
||||
@@ -23,13 +24,12 @@
|
||||
gap?:
|
||||
| ('none' | 'xxxs' | 'xxs' | 'xs' | 's' | 'm' | 'l' | 'xl' | 'xxl' | 'xxxl')
|
||||
| undefined;
|
||||
offset?: number;
|
||||
children: Snippet<[T[], number]>;
|
||||
} = $props();
|
||||
|
||||
let total = $derived(items.length);
|
||||
|
||||
let offset = $state(0);
|
||||
|
||||
let paginatedItems = $derived(items.slice(offset, offset + limit));
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/state';
|
||||
import { goto } from '$app/navigation';
|
||||
import { onMount, onDestroy } from 'svelte';
|
||||
import { onDestroy } from 'svelte';
|
||||
import { trackEvent } from '$lib/actions/analytics';
|
||||
import { Icon, Input } from '@appwrite.io/pink-svelte';
|
||||
import { IconSearch, IconX } from '@appwrite.io/pink-icons-svelte';
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
|
||||
import type { HTMLAttributes } from 'svelte/elements';
|
||||
import type { NavbarProject } from '$lib/components/navbar.svelte';
|
||||
import { SHOW_INIT_FEATURES } from '$lib/system';
|
||||
|
||||
type $$Props = HTMLAttributes<HTMLElement> & {
|
||||
state?: 'closed' | 'open' | 'icons';
|
||||
@@ -190,46 +191,49 @@
|
||||
<span slot="tooltip">{projectOption.name}</span>
|
||||
</Tooltip>
|
||||
{/each}
|
||||
<div class="only-mobile divider">
|
||||
<Divider />
|
||||
</div>
|
||||
<div class="products-label-container">
|
||||
<span class="products-label" class:hidden={state === 'icons'}>Deploy</span>
|
||||
<span class="products-label-indicator" class:hidden={state !== 'icons'}
|
||||
></span>
|
||||
</div>
|
||||
{@const deployProjectOptions = projectOptions.filter(
|
||||
(projectOption) => projectOption.category === 'deploy'
|
||||
)}
|
||||
{#each deployProjectOptions as projectOption}
|
||||
<Tooltip placement="right" disabled={state !== 'icons'}>
|
||||
<a
|
||||
href={`/console/project-${project.region}-${project.$id}/${projectOption.slug}`}
|
||||
class="link"
|
||||
class:active={page.url.pathname.includes(projectOption.slug)}
|
||||
on:click={() => {
|
||||
trackEvent(`click_menu_${projectOption.slug}`);
|
||||
sideBarIsOpen = false;
|
||||
}}>
|
||||
<span class="link-icon">
|
||||
<Icon icon={projectOption.icon} size="s" />
|
||||
</span>
|
||||
<span
|
||||
class:no-text={state === 'icons'}
|
||||
class:has-text={state === 'open'}
|
||||
class="link-text">
|
||||
{projectOption.name}
|
||||
{#if projectOption?.badge}
|
||||
<Badge
|
||||
variant="secondary"
|
||||
content={projectOption.badge}
|
||||
size="xs" />
|
||||
{/if}
|
||||
</span>
|
||||
</a>
|
||||
<span slot="tooltip">{projectOption.name}</span>
|
||||
</Tooltip>
|
||||
{/each}
|
||||
{#if SHOW_INIT_FEATURES}
|
||||
<div class="only-mobile divider">
|
||||
<Divider />
|
||||
</div>
|
||||
<div class="products-label-container">
|
||||
<span class="products-label" class:hidden={state === 'icons'}
|
||||
>Deploy</span>
|
||||
<span class="products-label-indicator" class:hidden={state !== 'icons'}
|
||||
></span>
|
||||
</div>
|
||||
{@const deployProjectOptions = projectOptions.filter(
|
||||
(projectOption) => projectOption.category === 'deploy'
|
||||
)}
|
||||
{#each deployProjectOptions as projectOption}
|
||||
<Tooltip placement="right" disabled={state !== 'icons'}>
|
||||
<a
|
||||
href={`/console/project-${project.region}-${project.$id}/${projectOption.slug}`}
|
||||
class="link"
|
||||
class:active={page.url.pathname.includes(projectOption.slug)}
|
||||
on:click={() => {
|
||||
trackEvent(`click_menu_${projectOption.slug}`);
|
||||
sideBarIsOpen = false;
|
||||
}}>
|
||||
<span class="link-icon">
|
||||
<Icon icon={projectOption.icon} size="s" />
|
||||
</span>
|
||||
<span
|
||||
class:no-text={state === 'icons'}
|
||||
class:has-text={state === 'open'}
|
||||
class="link-text">
|
||||
{projectOption.name}
|
||||
{#if projectOption?.badge}
|
||||
<Badge
|
||||
variant="secondary"
|
||||
content={projectOption.badge}
|
||||
size="xs" />
|
||||
{/if}
|
||||
</span>
|
||||
</a>
|
||||
<span slot="tooltip">{projectOption.name}</span>
|
||||
</Tooltip>
|
||||
{/each}
|
||||
{/if}
|
||||
<div class="only-mobile divider">
|
||||
<Divider />
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { DropList } from '$lib/components';
|
||||
import { SelectSearchCheckbox } from '..';
|
||||
import { Icon, Layout, Tag } from '@appwrite.io/pink-svelte';
|
||||
import { Icon, Tag } from '@appwrite.io/pink-svelte';
|
||||
import { IconChevronDown, IconChevronUp } from '@appwrite.io/pink-icons-svelte';
|
||||
|
||||
type Option = {
|
||||
|
||||
@@ -135,7 +135,6 @@
|
||||
<svelte:fragment slot="list">
|
||||
<slot name="tooltip" {limit} {tier} {title} {upgradeMethod} {hasUsageFees}>
|
||||
{#if hasProjectLimitation}
|
||||
{@const count = limit > 1 ? serviceId : serviceId.replace('s', '')}
|
||||
<p class="text">
|
||||
You are limited to {limit}
|
||||
{title.toLocaleLowerCase()} per project on the {tier} plan.
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
import type { Coupon } from '$lib/sdk/billing';
|
||||
import { app } from '$lib/stores/app';
|
||||
import type { Campaign } from '$lib/stores/campaigns';
|
||||
import { getApiEndpoint } from '$lib/stores/sdk';
|
||||
import { Typography, Layout, Avatar } from '@appwrite.io/pink-svelte';
|
||||
import { getCampaignImageUrl } from '$routes/(public)/card/helpers';
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { afterNavigate, goto } from '$app/navigation';
|
||||
import { page } from '$app/state';
|
||||
import { get, writable } from 'svelte/store';
|
||||
import { writable } from 'svelte/store';
|
||||
|
||||
export function createPersistentPagination(limit: number) {
|
||||
const url = page.url;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { Client, type Models, Sites, Storage } from '@appwrite.io/console';
|
||||
import { writable } from 'svelte/store';
|
||||
import { createAdminClient } from '$lib/stores/sdk';
|
||||
import { getApiEndpoint } from '$lib/stores/sdk';
|
||||
import { page } from '$app/state';
|
||||
|
||||
|
||||
+2
-1
@@ -11,7 +11,7 @@ export const VARS = {
|
||||
APPWRITE_ENDPOINT: env.PUBLIC_APPWRITE_ENDPOINT ?? undefined,
|
||||
GROWTH_ENDPOINT: env.PUBLIC_GROWTH_ENDPOINT ?? undefined,
|
||||
PUBLIC_STRIPE_KEY: env.PUBLIC_STRIPE_KEY ?? undefined,
|
||||
APPWRITE_MULTI_REGION: env.PUBLIC_APPWRITE_MULTI_REGION ?? false
|
||||
APPWRITE_MULTI_REGION: env.PUBLIC_APPWRITE_MULTI_REGION === 'true'
|
||||
};
|
||||
|
||||
export const ENV = {
|
||||
@@ -28,3 +28,4 @@ export const isDev = ENV.DEV;
|
||||
export const isProd = ENV.PROD;
|
||||
export const hasStripePublicKey = !!VARS.PUBLIC_STRIPE_KEY;
|
||||
export const GRACE_PERIOD_OVERRIDE = false;
|
||||
export const SHOW_INIT_FEATURES = !ENV.PROD || env.PUBLIC_APPWRITE_INIT_FEATURES === 'true';
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import { base } from '$app/paths';
|
||||
import { page } from '$app/state';
|
||||
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
|
||||
import { CreditsApplied, EstimatedTotal, SelectPaymentMethod } from '$lib/components/billing';
|
||||
import { CreditsApplied, SelectPaymentMethod } from '$lib/components/billing';
|
||||
import { BillingPlan, Dependencies } from '$lib/constants';
|
||||
import { Button, Form, InputSelect, InputTags, InputText } from '$lib/elements/forms';
|
||||
import { toLocaleDate } from '$lib/helpers/date';
|
||||
|
||||
@@ -3,18 +3,12 @@
|
||||
import { base } from '$app/paths';
|
||||
import { page } from '$app/state';
|
||||
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
|
||||
import {
|
||||
PlanComparisonBox,
|
||||
PlanSelection,
|
||||
SelectPaymentMethod,
|
||||
SelectPlan
|
||||
} from '$lib/components/billing';
|
||||
import { PlanComparisonBox, PlanSelection, SelectPaymentMethod } from '$lib/components/billing';
|
||||
import ValidateCreditModal from '$lib/components/billing/validateCreditModal.svelte';
|
||||
import { BillingPlan, Dependencies } from '$lib/constants';
|
||||
import { Button, Form, InputTags, InputText } from '$lib/elements/forms';
|
||||
import { Wizard } from '$lib/layout';
|
||||
|
||||
import type { Coupon, PaymentList } from '$lib/sdk/billing';
|
||||
import type { Coupon } from '$lib/sdk/billing';
|
||||
import { isOrganization, tierToPlan } from '$lib/stores/billing';
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import { type OrganizationError, type Organization } from '$lib/stores/organization';
|
||||
@@ -37,7 +31,6 @@
|
||||
let formComponent: Form;
|
||||
let isSubmitting = writable(false);
|
||||
|
||||
let methods: PaymentList;
|
||||
let name: string;
|
||||
let billingPlan: BillingPlan = BillingPlan.FREE;
|
||||
let paymentMethodId: string;
|
||||
@@ -95,11 +88,6 @@
|
||||
}
|
||||
});
|
||||
|
||||
async function loadPaymentMethods() {
|
||||
methods = await sdk.forConsole.billing.listPaymentMethods();
|
||||
paymentMethodId = methods.paymentMethods.find((method) => !!method?.last4)?.$id ?? null;
|
||||
}
|
||||
|
||||
async function validate(organizationId: string, invites: string[]) {
|
||||
try {
|
||||
const org = await sdk.forConsole.billing.validateOrganization(organizationId, invites);
|
||||
|
||||
@@ -6,7 +6,7 @@ import { isOrganization, tierToPlan } from '$lib/stores/billing';
|
||||
import { ID } from '@appwrite.io/console';
|
||||
import { BillingPlan } from '$lib/constants';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import { base } from '$service-worker';
|
||||
import { base } from '$app/paths';
|
||||
|
||||
export const load: PageLoad = async ({ parent }) => {
|
||||
const { organizations } = await parent();
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
import { onMount } from 'svelte';
|
||||
import { trackEvent } from '$lib/actions/analytics';
|
||||
import { selectedInvoice, showRetryModal } from './store';
|
||||
import { organization } from '$lib/stores/organization';
|
||||
import {
|
||||
ActionMenu,
|
||||
Badge,
|
||||
|
||||
@@ -35,7 +35,6 @@
|
||||
new Date($organization?.billingStartDate).getTime() - today.getTime() > 0 &&
|
||||
$plansInfo.get($organization.billingPlan)?.trialDays;
|
||||
const extraUsage = currentInvoice ? currentInvoice.amount - currentPlan?.price : 0;
|
||||
const extraAddons = currentInvoice ? currentInvoice.usage?.length : 0;
|
||||
|
||||
function usageNameToLabel(name: string): string {
|
||||
switch (name) {
|
||||
|
||||
@@ -66,20 +66,23 @@
|
||||
if (setAsDefault) {
|
||||
await sdk.forConsole.billing.setDefaultPaymentMethod(paymentMethodId);
|
||||
}
|
||||
const { clientSecret } = await sdk.forConsole.billing.retryPayment(
|
||||
const { clientSecret, status } = await sdk.forConsole.billing.retryPayment(
|
||||
$organization.$id,
|
||||
invoice.$id,
|
||||
paymentMethodId
|
||||
);
|
||||
|
||||
await confirmPayment(
|
||||
$organization.$id,
|
||||
clientSecret,
|
||||
paymentMethodId ? paymentMethodId : $organization.paymentMethodId,
|
||||
`${base}/organization-${$organization.$id}/billing?type=validate-invoice&invoice=${invoice.$id}`
|
||||
);
|
||||
if (status !== 'succeeded' && status !== 'cancelled') {
|
||||
// probably still pending, confirm via stripe!
|
||||
await confirmPayment(
|
||||
$organization.$id,
|
||||
clientSecret,
|
||||
paymentMethodId ? paymentMethodId : $organization.paymentMethodId,
|
||||
`${base}/organization-${$organization.$id}/billing?type=validate-invoice&invoice=${invoice.$id}`
|
||||
);
|
||||
|
||||
await sdk.forConsole.billing.updateInvoiceStatus($organization.$id, invoice.$id);
|
||||
await sdk.forConsole.billing.updateInvoiceStatus($organization.$id, invoice.$id);
|
||||
}
|
||||
|
||||
invalidate(Dependencies.ORGANIZATION);
|
||||
invalidate(Dependencies.INVOICES);
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
import { Button, Form, InputSelect, InputTags, InputTextarea } from '$lib/elements/forms';
|
||||
import { formatCurrency } from '$lib/helpers/numbers.js';
|
||||
import { Wizard } from '$lib/layout';
|
||||
import { type Coupon, type PaymentList } from '$lib/sdk/billing';
|
||||
import { isOrganization, plansInfo, type Tier, tierToPlan } from '$lib/stores/billing';
|
||||
import { type Coupon } from '$lib/sdk/billing';
|
||||
import { isOrganization, plansInfo, tierToPlan } from '$lib/stores/billing';
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import { currentPlan, organization } from '$lib/stores/organization';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
|
||||
@@ -4,7 +4,7 @@ import { getLimit, getPage, getQuery, getSearch, pageToOffset } from '$lib/helpe
|
||||
import { Dependencies, PAGE_LIMIT } from '$lib/constants';
|
||||
import { queries, queryParamToMap } from '$lib/components/filters';
|
||||
|
||||
export const load = async ({ depends, url, route, params }) => {
|
||||
export const load = async ({ depends, url, route }) => {
|
||||
depends(Dependencies.DOMAINS);
|
||||
const page = getPage(url);
|
||||
const limit = getLimit(url, route, PAGE_LIMIT);
|
||||
|
||||
-1
@@ -11,7 +11,6 @@
|
||||
import { IconInfo } from '@appwrite.io/pink-icons-svelte';
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { page } from '$app/state';
|
||||
import { recordTypes } from './store';
|
||||
import { Dependencies } from '$lib/constants';
|
||||
|
||||
@@ -11,12 +11,13 @@
|
||||
import { members, newMemberModal, organization } from '$lib/stores/organization';
|
||||
import {
|
||||
canSeeBilling,
|
||||
canSeeDomains,
|
||||
canSeeProjects,
|
||||
canSeeTeams,
|
||||
isBilling,
|
||||
isOwner
|
||||
} from '$lib/stores/roles';
|
||||
import { GRACE_PERIOD_OVERRIDE, isCloud } from '$lib/system';
|
||||
import { GRACE_PERIOD_OVERRIDE, isCloud, SHOW_INIT_FEATURES } from '$lib/system';
|
||||
import { IconGithub, IconPlus } from '@appwrite.io/pink-icons-svelte';
|
||||
import { Icon, Tooltip, Typography, Layout, Badge } from '@appwrite.io/pink-svelte';
|
||||
|
||||
@@ -44,8 +45,7 @@
|
||||
href: `${path}/domains`,
|
||||
event: 'domains',
|
||||
title: 'Domains',
|
||||
disabled: !isCloud
|
||||
// disabled: !(isCloud && $canSeeDomains) //TODO: enable this before release
|
||||
disabled: !isCloud || !$canSeeDomains || !SHOW_INIT_FEATURES
|
||||
},
|
||||
{
|
||||
href: `${path}/members`,
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@
|
||||
import { Table, Tabs, Alert } from '@appwrite.io/pink-svelte';
|
||||
import DeleteOrganizationEstimation from './deleteOrganizationEstimation.svelte';
|
||||
import { onMount } from 'svelte';
|
||||
import type { EstimationDeleteOrganization, Invoice, InvoiceList } from '$lib/sdk/billing';
|
||||
import type { EstimationDeleteOrganization, InvoiceList } from '$lib/sdk/billing';
|
||||
|
||||
export let showDelete = false;
|
||||
export let invoices: InvoiceList;
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
<Table.Header.Cell {root} />
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
{#each invoices as invoice, i}
|
||||
{#each invoices as invoice (invoice.$id)}
|
||||
{@const status = invoice.status}
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell column="date" {root}>
|
||||
|
||||
+3
-3
@@ -41,9 +41,9 @@
|
||||
return `${base}/project-${region}-${projectId}/settings/usage`;
|
||||
}
|
||||
|
||||
function getProjectName(projectId: string): string {
|
||||
return data.projects[projectId]?.name ?? 'Unknown';
|
||||
}
|
||||
// function getProjectName(projectId: string): string {
|
||||
// return data.projects[projectId]?.name ?? 'Unknown';
|
||||
// }
|
||||
|
||||
function groupByProject(
|
||||
metric: Metric | undefined,
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
import deepEqual from 'deep-equal';
|
||||
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
|
||||
import type { EmailTemplateLocale, EmailTemplateType } from '@appwrite.io/console';
|
||||
import { Card, Icon, Layout, Tooltip, Typography } from '@appwrite.io/pink-svelte';
|
||||
import { Icon, Layout, Tooltip, Typography } from '@appwrite.io/pink-svelte';
|
||||
import { IconInfo } from '@appwrite.io/pink-icons-svelte';
|
||||
|
||||
export let loading = false;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
|
||||
import { Modal } from '$lib/components';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
|
||||
+10
-7
@@ -24,6 +24,7 @@
|
||||
import { base } from '$app/paths';
|
||||
import { IconPlus } from '@appwrite.io/pink-icons-svelte';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
import { SHOW_INIT_FEATURES } from '$lib/system';
|
||||
|
||||
export let data: PageData;
|
||||
|
||||
@@ -99,13 +100,15 @@
|
||||
analyticsSource="database_documents" />
|
||||
<Layout.Stack direction="row" alignItems="center" justifyContent="flex-end">
|
||||
<ViewSelector view={data.view} {columns} hideView />
|
||||
<Button
|
||||
secondary
|
||||
event={Click.DatabaseImportCsv}
|
||||
disabled={!(hasAttributes && hasValidAttributes)}
|
||||
on:click={() => (showImportCSV = true)}>
|
||||
Import CSV
|
||||
</Button>
|
||||
{#if SHOW_INIT_FEATURES}
|
||||
<Button
|
||||
secondary
|
||||
event={Click.DatabaseImportCsv}
|
||||
disabled={!(hasAttributes && hasValidAttributes)}
|
||||
on:click={() => (showImportCSV = true)}>
|
||||
Import CSV
|
||||
</Button>
|
||||
{/if}
|
||||
{#if !$isSmallViewport}
|
||||
<Button
|
||||
disabled={!(hasAttributes && hasValidAttributes)}
|
||||
|
||||
-1
@@ -2,7 +2,6 @@
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { page } from '$app/state';
|
||||
import { get } from 'svelte/store';
|
||||
|
||||
export async function submitDatetime(
|
||||
databaseId: string,
|
||||
|
||||
-1
@@ -1,6 +1,5 @@
|
||||
<script context="module" lang="ts">
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
import { get } from 'svelte/store';
|
||||
import { page } from '$app/state';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
|
||||
|
||||
-1
@@ -1,5 +1,4 @@
|
||||
<script context="module" lang="ts">
|
||||
import { get } from 'svelte/store';
|
||||
import { page } from '$app/state';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
|
||||
-1
@@ -1,5 +1,4 @@
|
||||
<script context="module" lang="ts">
|
||||
import { get } from 'svelte/store';
|
||||
import { page } from '$app/state';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
|
||||
-1
@@ -1,5 +1,4 @@
|
||||
<script context="module" lang="ts">
|
||||
import { get } from 'svelte/store';
|
||||
import { page } from '$app/state';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
|
||||
-1
@@ -1,5 +1,4 @@
|
||||
<script context="module" lang="ts">
|
||||
import { get } from 'svelte/store';
|
||||
import { page } from '$app/state';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
|
||||
-1
@@ -1,5 +1,4 @@
|
||||
<script context="module" lang="ts">
|
||||
import { get } from 'svelte/store';
|
||||
import { page } from '$app/state';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
|
||||
-1
@@ -10,7 +10,6 @@
|
||||
export let show = false;
|
||||
export let data: Partial<Models.Document>[];
|
||||
export let selectedRelationship: Models.AttributeRelationship = null;
|
||||
const projectId = page.params.project;
|
||||
const databaseId = page.params.database;
|
||||
const limit = 10;
|
||||
|
||||
|
||||
-1
@@ -28,7 +28,6 @@
|
||||
|
||||
export let data: PageData;
|
||||
|
||||
const projectId = page.params.project;
|
||||
const databaseId = page.params.database;
|
||||
const collectionId = page.params.collection;
|
||||
let showRelationships = false;
|
||||
|
||||
-1
@@ -1,5 +1,4 @@
|
||||
<script context="module" lang="ts">
|
||||
import { get } from 'svelte/store';
|
||||
import { page } from '$app/state';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
|
||||
-1
@@ -16,7 +16,6 @@
|
||||
import Confirm from '$lib/components/confirm.svelte';
|
||||
|
||||
export let data: PageData;
|
||||
const projectId = page.params.project;
|
||||
const databaseId = page.params.database;
|
||||
|
||||
let selectedRows: string[] = [];
|
||||
|
||||
+25
-26
@@ -3,13 +3,12 @@
|
||||
import { Modal } from '$lib/components';
|
||||
import { onMount } from 'svelte';
|
||||
import { page } from '$app/state';
|
||||
import { func } from '../store';
|
||||
import { Alert, Code, Layout, Tabs } from '@appwrite.io/pink-svelte';
|
||||
import { Link } from '$lib/elements';
|
||||
|
||||
export let show = false;
|
||||
|
||||
let lang = 'js';
|
||||
// let lang = 'js';
|
||||
let codeSnippets = {};
|
||||
let os = 'unknown';
|
||||
let category = 'Unix';
|
||||
@@ -17,8 +16,8 @@
|
||||
const functionId = page.params.function;
|
||||
|
||||
onMount(() => {
|
||||
lang = setLanguage($func.runtime);
|
||||
codeSnippets = setCodeSnippets(lang);
|
||||
// lang = setLanguage($func.runtime);
|
||||
codeSnippets = setCodeSnippets();
|
||||
os = navigator['userAgentData']?.platform || navigator?.platform || 'unknown';
|
||||
|
||||
if (os.includes('Win')) {
|
||||
@@ -30,29 +29,29 @@
|
||||
}
|
||||
});
|
||||
|
||||
function setLanguage(runtime: string) {
|
||||
if (runtime.includes('node') || runtime.includes('deno')) {
|
||||
return 'js';
|
||||
} else if (runtime.includes('php')) {
|
||||
return 'php';
|
||||
} else if (runtime.includes('python')) {
|
||||
return 'py';
|
||||
} else if (runtime.includes('dart')) {
|
||||
return 'dart';
|
||||
} else if (runtime.includes('dotnet')) {
|
||||
return 'cs';
|
||||
} else if (runtime.includes('ruby')) {
|
||||
return 'rb';
|
||||
} else if (runtime.includes('swift')) {
|
||||
return 'swift';
|
||||
} else if (runtime.includes('kotlin')) {
|
||||
return 'kt';
|
||||
} else if (runtime.includes('java')) {
|
||||
return 'java';
|
||||
}
|
||||
}
|
||||
// function setLanguage(runtime: string) {
|
||||
// if (runtime.includes('node') || runtime.includes('deno')) {
|
||||
// return 'js';
|
||||
// } else if (runtime.includes('php')) {
|
||||
// return 'php';
|
||||
// } else if (runtime.includes('python')) {
|
||||
// return 'py';
|
||||
// } else if (runtime.includes('dart')) {
|
||||
// return 'dart';
|
||||
// } else if (runtime.includes('dotnet')) {
|
||||
// return 'cs';
|
||||
// } else if (runtime.includes('ruby')) {
|
||||
// return 'rb';
|
||||
// } else if (runtime.includes('swift')) {
|
||||
// return 'swift';
|
||||
// } else if (runtime.includes('kotlin')) {
|
||||
// return 'kt';
|
||||
// } else if (runtime.includes('java')) {
|
||||
// return 'java';
|
||||
// }
|
||||
// }
|
||||
|
||||
function setCodeSnippets(lang: string) {
|
||||
function setCodeSnippets() {
|
||||
return {
|
||||
Unix: {
|
||||
code: `appwrite client --projectId="${page.params.project}" && \\
|
||||
|
||||
+1
-3
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { base } from '$app/paths';
|
||||
import { page } from '$app/state';
|
||||
import { PaginationWithLimit, ViewSelector, EmptyFilter } from '$lib/components';
|
||||
import { PaginationWithLimit, EmptyFilter } from '$lib/components';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { columns, deploymentList, func } from './store';
|
||||
import { Container, ResponsiveContainerHeader } from '$lib/layout';
|
||||
@@ -9,7 +9,6 @@
|
||||
import { GRACE_PERIOD_OVERRIDE, isCloud } from '$lib/system';
|
||||
import { readOnly } from '$lib/stores/billing';
|
||||
import Table from './table.svelte';
|
||||
import { View } from '$lib/helpers/load';
|
||||
import DeploymentCard from './(components)/deploymentCard.svelte';
|
||||
import RedeployModal from './(modals)/redeployModal.svelte';
|
||||
import { canWriteFunctions } from '$lib/stores/roles';
|
||||
@@ -23,7 +22,6 @@
|
||||
} from '@appwrite.io/pink-icons-svelte';
|
||||
import { app } from '$lib/stores/app';
|
||||
import CreateActionMenu from './(components)/createActionMenu.svelte';
|
||||
import { ParsedTagList, QuickFilters } from '$lib/components/filters';
|
||||
import { Menu } from '$lib/components/menu';
|
||||
import DownloadActionMenuItem from './(components)/downloadActionMenuItem.svelte';
|
||||
|
||||
|
||||
+1
-3
@@ -18,7 +18,6 @@
|
||||
Icon,
|
||||
Layout,
|
||||
Logs,
|
||||
Popover,
|
||||
Spinner,
|
||||
Typography
|
||||
} from '@appwrite.io/pink-svelte';
|
||||
@@ -26,8 +25,7 @@
|
||||
import { formatTimeDetailed } from '$lib/helpers/timeConversion';
|
||||
import { timer } from '$lib/actions/timer';
|
||||
import { app } from '$lib/stores/app';
|
||||
import { getOutputDownload, getSourceDownload, showCreateDeployment } from '../store';
|
||||
import { IconDotsHorizontal, IconRefresh, IconTerminal } from '@appwrite.io/pink-icons-svelte';
|
||||
import { IconDotsHorizontal, IconRefresh } from '@appwrite.io/pink-icons-svelte';
|
||||
import { Menu } from '$lib/components/menu';
|
||||
import { canWriteFunctions } from '$lib/stores/roles';
|
||||
import { Click, trackEvent } from '$lib/actions/analytics';
|
||||
|
||||
+126
-117
@@ -46,124 +46,133 @@
|
||||
$: selectedLog = logs?.find((log) => log.$id === selectedLogId);
|
||||
$: isFirstLog = logs.findIndex((log) => log.$id === selectedLogId) === 0;
|
||||
$: isLastLog = logs.findIndex((log) => log.$id === selectedLogId) === logs.length - 1;
|
||||
|
||||
let sheet: HTMLDivElement;
|
||||
function handleClickOutside(event: MouseEvent) {
|
||||
if (sheet && !sheet.contains(event.target as Node)) {
|
||||
open = false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:window onclick={() => (open = false)} />
|
||||
<svelte:window onclick={handleClickOutside} />
|
||||
|
||||
<Sheet bind:open closeOnBlur={false}>
|
||||
<div slot="header" style:width="100%">
|
||||
<Layout.Stack direction="row" justifyContent="space-between" alignItems="center">
|
||||
<Layout.Stack direction="row" gap="m" alignItems="center">
|
||||
<Typography.Text variant="m-400">Execution ID</Typography.Text>
|
||||
<Copy value={selectedLog?.$id}>
|
||||
<Tag size="s" variant="code">{selectedLog?.$id}</Tag>
|
||||
</Copy>
|
||||
</Layout.Stack>
|
||||
<Layout.Stack direction="row" gap="xs" alignItems="center" inline>
|
||||
<Button icon text size="xs" on:click={previousLog} disabled={isFirstLog}>
|
||||
<Icon icon={IconChevronUp} />
|
||||
</Button>
|
||||
<Button icon text size="xs" on:click={nextLog} disabled={isLastLog}>
|
||||
<Icon icon={IconChevronDown} />
|
||||
</Button>
|
||||
</Layout.Stack>
|
||||
</Layout.Stack>
|
||||
</div>
|
||||
{#if selectedLog}
|
||||
<Layout.Stack gap="xl">
|
||||
<Accordion title="Details" open>
|
||||
<Layout.Stack gap="xxxl">
|
||||
<Layout.Stack gap="xxxl" direction="row" wrap="wrap">
|
||||
<Layout.Stack gap="xs" inline>
|
||||
<Typography.Text variant="m-400" color="--fgcolor-neutral-tertiary">
|
||||
Method
|
||||
</Typography.Text>
|
||||
<Typography.Text variant="m-400">
|
||||
{selectedLog.requestMethod}
|
||||
</Typography.Text>
|
||||
</Layout.Stack>
|
||||
<Layout.Stack gap="xs" inline>
|
||||
<Typography.Text variant="m-400" color="--fgcolor-neutral-tertiary">
|
||||
Status code
|
||||
</Typography.Text>
|
||||
<span>
|
||||
<Badge
|
||||
content={selectedLog.responseStatusCode.toString()}
|
||||
variant="secondary"
|
||||
type={selectedLog?.responseStatusCode >= 400
|
||||
? 'error'
|
||||
: selectedLog.responseStatusCode === 0
|
||||
? undefined
|
||||
: 'success'} />
|
||||
</span>
|
||||
</Layout.Stack>
|
||||
<Layout.Stack gap="xs" inline>
|
||||
<Typography.Text variant="m-400" color="--fgcolor-neutral-tertiary">
|
||||
Status
|
||||
</Typography.Text>
|
||||
|
||||
<Tooltip
|
||||
disabled={!selectedLog?.scheduledAt ||
|
||||
selectedLog.status !== 'scheduled'}
|
||||
maxWidth="400px">
|
||||
<div>
|
||||
<Status
|
||||
status={logStatusConverter(selectedLog.status)}
|
||||
label={capitalize(selectedLog.status)}>
|
||||
</Status>
|
||||
</div>
|
||||
<span slot="tooltip">
|
||||
{`Scheduled to execute on ${toLocaleDateTime(selectedLog.scheduledAt)}`}
|
||||
</span>
|
||||
</Tooltip>
|
||||
</Layout.Stack>
|
||||
|
||||
<Layout.Stack gap="xs" inline>
|
||||
<Typography.Text variant="m-400" color="--fgcolor-neutral-tertiary">
|
||||
Triggered by
|
||||
</Typography.Text>
|
||||
<Typography.Text variant="m-400">
|
||||
{capitalize(selectedLog.trigger)}
|
||||
</Typography.Text>
|
||||
</Layout.Stack>
|
||||
|
||||
<Layout.Stack gap="xs" inline>
|
||||
<Typography.Text variant="m-400" color="--fgcolor-neutral-tertiary">
|
||||
Duration
|
||||
</Typography.Text>
|
||||
<Typography.Text variant="m-400">
|
||||
{calculateTime(selectedLog.duration)}
|
||||
</Typography.Text>
|
||||
</Layout.Stack>
|
||||
|
||||
<Layout.Stack gap="xs" inline>
|
||||
<Typography.Text variant="m-400" color="--fgcolor-neutral-tertiary">
|
||||
Created
|
||||
</Typography.Text>
|
||||
<Typography.Text variant="m-400">
|
||||
{capitalize(timeFromNow(selectedLog.$createdAt))}
|
||||
</Typography.Text>
|
||||
</Layout.Stack>
|
||||
</Layout.Stack>
|
||||
<Layout.Stack gap="xs" inline alignItems="flex-start">
|
||||
<Typography.Text variant="m-400" color="--fgcolor-neutral-tertiary">
|
||||
Path
|
||||
</Typography.Text>
|
||||
<div>
|
||||
<InteractiveText
|
||||
text={selectedLog.requestPath}
|
||||
variant="copy-code"
|
||||
isVisible />
|
||||
</div>
|
||||
</Layout.Stack>
|
||||
<div style="position: absolute; top: 0; " bind:this={sheet}>
|
||||
<Sheet bind:open closeOnBlur={false}>
|
||||
<div slot="header" style:width="100%">
|
||||
<Layout.Stack direction="row" justifyContent="space-between" alignItems="center">
|
||||
<Layout.Stack direction="row" gap="m" alignItems="center">
|
||||
<Typography.Text variant="m-400">Execution ID</Typography.Text>
|
||||
<Copy value={selectedLog?.$id}>
|
||||
<Tag size="s" variant="code">{selectedLog?.$id}</Tag>
|
||||
</Copy>
|
||||
</Layout.Stack>
|
||||
</Accordion>
|
||||
<Accordion title="Request" open>
|
||||
<LogsRequest {selectedLog} />
|
||||
</Accordion>
|
||||
<Accordion title="Response" open hideDivider>
|
||||
<LogsResponse {selectedLog} product="function" {logging} />
|
||||
</Accordion>
|
||||
</Layout.Stack>
|
||||
{/if}
|
||||
</Sheet>
|
||||
<Layout.Stack direction="row" gap="xs" alignItems="center" inline>
|
||||
<Button icon text size="xs" on:click={previousLog} disabled={isFirstLog}>
|
||||
<Icon icon={IconChevronUp} />
|
||||
</Button>
|
||||
<Button icon text size="xs" on:click={nextLog} disabled={isLastLog}>
|
||||
<Icon icon={IconChevronDown} />
|
||||
</Button>
|
||||
</Layout.Stack>
|
||||
</Layout.Stack>
|
||||
</div>
|
||||
{#if selectedLog}
|
||||
<Layout.Stack gap="xl">
|
||||
<Accordion title="Details" open>
|
||||
<Layout.Stack gap="xxxl">
|
||||
<Layout.Stack gap="xxxl" direction="row" wrap="wrap">
|
||||
<Layout.Stack gap="xs" inline>
|
||||
<Typography.Text variant="m-400" color="--fgcolor-neutral-tertiary">
|
||||
Method
|
||||
</Typography.Text>
|
||||
<Typography.Text variant="m-400">
|
||||
{selectedLog.requestMethod}
|
||||
</Typography.Text>
|
||||
</Layout.Stack>
|
||||
<Layout.Stack gap="xs" inline>
|
||||
<Typography.Text variant="m-400" color="--fgcolor-neutral-tertiary">
|
||||
Status code
|
||||
</Typography.Text>
|
||||
<span>
|
||||
<Badge
|
||||
content={selectedLog.responseStatusCode.toString()}
|
||||
variant="secondary"
|
||||
type={selectedLog?.responseStatusCode >= 400
|
||||
? 'error'
|
||||
: selectedLog.responseStatusCode === 0
|
||||
? undefined
|
||||
: 'success'} />
|
||||
</span>
|
||||
</Layout.Stack>
|
||||
<Layout.Stack gap="xs" inline>
|
||||
<Typography.Text variant="m-400" color="--fgcolor-neutral-tertiary">
|
||||
Status
|
||||
</Typography.Text>
|
||||
|
||||
<Tooltip
|
||||
disabled={!selectedLog?.scheduledAt ||
|
||||
selectedLog.status !== 'scheduled'}
|
||||
maxWidth="400px">
|
||||
<div>
|
||||
<Status
|
||||
status={logStatusConverter(selectedLog.status)}
|
||||
label={capitalize(selectedLog.status)}>
|
||||
</Status>
|
||||
</div>
|
||||
<span slot="tooltip">
|
||||
{`Scheduled to execute on ${toLocaleDateTime(selectedLog.scheduledAt)}`}
|
||||
</span>
|
||||
</Tooltip>
|
||||
</Layout.Stack>
|
||||
|
||||
<Layout.Stack gap="xs" inline>
|
||||
<Typography.Text variant="m-400" color="--fgcolor-neutral-tertiary">
|
||||
Triggered by
|
||||
</Typography.Text>
|
||||
<Typography.Text variant="m-400">
|
||||
{capitalize(selectedLog.trigger)}
|
||||
</Typography.Text>
|
||||
</Layout.Stack>
|
||||
|
||||
<Layout.Stack gap="xs" inline>
|
||||
<Typography.Text variant="m-400" color="--fgcolor-neutral-tertiary">
|
||||
Duration
|
||||
</Typography.Text>
|
||||
<Typography.Text variant="m-400">
|
||||
{calculateTime(selectedLog.duration)}
|
||||
</Typography.Text>
|
||||
</Layout.Stack>
|
||||
|
||||
<Layout.Stack gap="xs" inline>
|
||||
<Typography.Text variant="m-400" color="--fgcolor-neutral-tertiary">
|
||||
Created
|
||||
</Typography.Text>
|
||||
<Typography.Text variant="m-400">
|
||||
{capitalize(timeFromNow(selectedLog.$createdAt))}
|
||||
</Typography.Text>
|
||||
</Layout.Stack>
|
||||
</Layout.Stack>
|
||||
<Layout.Stack gap="xs" inline alignItems="flex-start">
|
||||
<Typography.Text variant="m-400" color="--fgcolor-neutral-tertiary">
|
||||
Path
|
||||
</Typography.Text>
|
||||
<div>
|
||||
<InteractiveText
|
||||
text={selectedLog.requestPath}
|
||||
variant="copy-code"
|
||||
isVisible />
|
||||
</div>
|
||||
</Layout.Stack>
|
||||
</Layout.Stack>
|
||||
</Accordion>
|
||||
<Accordion title="Request" open>
|
||||
<LogsRequest {selectedLog} />
|
||||
</Accordion>
|
||||
<Accordion title="Response" open hideDivider>
|
||||
<LogsResponse {selectedLog} product="function" {logging} />
|
||||
</Accordion>
|
||||
</Layout.Stack>
|
||||
{/if}
|
||||
</Sheet>
|
||||
</div>
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
import { toLocaleDateTime } from '$lib/helpers/date';
|
||||
import type { Column } from '$lib/helpers/types';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
import { Badge, Layout, Status, Table, Tooltip, Typography } from '@appwrite.io/pink-svelte';
|
||||
import { Badge, Status, Table, Tooltip, Typography } from '@appwrite.io/pink-svelte';
|
||||
import Sheet from './sheet.svelte';
|
||||
import { capitalize } from '$lib/helpers/string';
|
||||
import { formatTimeDetailed } from '$lib/helpers/timeConversion';
|
||||
|
||||
+2
-2
@@ -2,9 +2,9 @@
|
||||
import { base } from '$app/paths';
|
||||
import { CardGrid, SvgIcon } from '$lib/components';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { timeFromNow, toLocaleDateTime } from '$lib/helpers/date';
|
||||
import { toLocaleDateTime } from '$lib/helpers/date';
|
||||
import { project } from '$routes/(console)/project-[region]-[project]/store';
|
||||
import { Layout, Tooltip, Typography } from '@appwrite.io/pink-svelte';
|
||||
import { Layout, Typography } from '@appwrite.io/pink-svelte';
|
||||
import { func } from '../store';
|
||||
import { capitalize } from '$lib/helpers/string';
|
||||
</script>
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
|
||||
export let data;
|
||||
|
||||
let offset = 0;
|
||||
|
||||
function applyFilter(filter: string, value: string, event: CustomEvent) {
|
||||
const target = new URL(page.url);
|
||||
if (event?.detail) {
|
||||
@@ -45,6 +47,7 @@
|
||||
previous.forEach((n) => target.searchParams.append(filter, n));
|
||||
}
|
||||
target.searchParams.delete('page');
|
||||
offset = 0;
|
||||
goto(target.toString());
|
||||
}
|
||||
|
||||
@@ -140,7 +143,7 @@
|
||||
</Layout.Stack>
|
||||
<Layout.Stack gap="l">
|
||||
{#if data.templates?.length > 0}
|
||||
<Paginator items={data.templates} limit={12} hidePages={false} hasLimit>
|
||||
<Paginator items={data.templates} limit={12} hidePages={false} hasLimit bind:offset>
|
||||
{#snippet children(paginatedItems: typeof data.templates)}
|
||||
<Layout.Grid columns={2} columnsXL={3} columnsXS={1}>
|
||||
{#each paginatedItems as template}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Dependencies, PAGE_LIMIT } from '$lib/constants';
|
||||
import { Dependencies } from '$lib/constants';
|
||||
import { getSearch } from '$lib/helpers/load';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load: PageLoad = async ({ url, route, depends, parent, params }) => {
|
||||
export const load: PageLoad = async ({ url, depends, parent, params }) => {
|
||||
depends(Dependencies.FUNCTIONS);
|
||||
|
||||
const search = getSearch(url);
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
import { Cover } from '$lib/layout';
|
||||
import { Typography } from '@appwrite.io/pink-svelte';
|
||||
|
||||
const projectId = page.params.project;
|
||||
const path = `${base}/project-${page.params.region}-${page.params.project}/messaging`;
|
||||
const tabs = [
|
||||
{
|
||||
|
||||
-1
@@ -1,6 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { invalidate } from '$app/navigation';
|
||||
import { Modal } from '$lib/components';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
|
||||
-1
@@ -2,7 +2,6 @@
|
||||
import {
|
||||
InputDomain,
|
||||
InputEmail,
|
||||
InputFile,
|
||||
InputSelect,
|
||||
InputPhone,
|
||||
InputSwitch,
|
||||
|
||||
-9
@@ -5,15 +5,6 @@
|
||||
import { providerType, provider, providerParams } from './store';
|
||||
import SettingsFormList from '../settingsFormList.svelte';
|
||||
|
||||
import { MessagingProviderType } from '@appwrite.io/console';
|
||||
import {
|
||||
Collapsible,
|
||||
CollapsibleItem,
|
||||
ClickableList,
|
||||
ClickableListItem
|
||||
} from '$lib/components';
|
||||
import { getProviderText } from '../../helper';
|
||||
|
||||
let files: Record<string, FileList> = {};
|
||||
$: inputs = providers[$providerType].providers[$provider].configure;
|
||||
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@
|
||||
import { writable } from 'svelte/store';
|
||||
import type { Column } from '$lib/helpers/types';
|
||||
import { base } from '$app/paths';
|
||||
import { Icon, Layout, Typography } from '@appwrite.io/pink-svelte';
|
||||
import { Icon, Layout } from '@appwrite.io/pink-svelte';
|
||||
import { IconPlus } from '@appwrite.io/pink-icons-svelte';
|
||||
|
||||
export let data;
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
let formComponent: Form;
|
||||
let isSubmitting = writable(false);
|
||||
|
||||
let scopes = [];
|
||||
let scopes: string[] = [];
|
||||
let name = '',
|
||||
expire = '';
|
||||
|
||||
|
||||
+3
-3
@@ -20,8 +20,8 @@
|
||||
export let key: Models.DevKey | Models.Key;
|
||||
export let keyType: 'api' | 'dev' = 'api';
|
||||
|
||||
let name = null;
|
||||
let scopes = null;
|
||||
let name: string = null;
|
||||
let scopes: string[] = null;
|
||||
|
||||
let showDelete = false;
|
||||
const isApiKey = keyType === 'api';
|
||||
@@ -184,7 +184,7 @@
|
||||
|
||||
<CardGrid>
|
||||
<svelte:fragment slot="title">Delete {label} key</svelte:fragment>
|
||||
The Dev key will be permanently deleted. This action is irreversible.
|
||||
The {label} key will be permanently deleted. This action is irreversible.
|
||||
<svelte:fragment slot="aside">
|
||||
<Box>
|
||||
<div class="u-flex u-gap-16">
|
||||
|
||||
@@ -34,8 +34,8 @@
|
||||
const isExpiring = key.expire && diffDays(new Date(), new Date(key.expire)) < 14;
|
||||
|
||||
return {
|
||||
status: isExpired ? 'error' : isExpiring ? 'warning' : null,
|
||||
message: isExpired ? 'Expired' : isExpiring ? 'Expires soon' : null
|
||||
message: isExpired ? 'Expired' : isExpiring ? 'Expires soon' : null,
|
||||
status: isExpired ? (isApiKey ? 'error' : 'warning') : isExpiring ? 'warning' : null
|
||||
};
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
if (isApiKey)
|
||||
return 'Use API keys to authenticate your app’s requests in production, granting secure access to live data and services.';
|
||||
else
|
||||
return 'Dev keys allow bypassing rate limits and accessing more detailed error messages while in development.';
|
||||
return 'Dev keys allow bypassing rate limits and CORS errors in your development environment.';
|
||||
}
|
||||
|
||||
const columns = isApiKey ? $keyColumns : $devKeyColumns;
|
||||
|
||||
+4
-12
@@ -75,20 +75,12 @@
|
||||
<svelte:fragment slot="title">Expiration date</svelte:fragment>
|
||||
Set a date after which your {label} key will expire.
|
||||
<svelte:fragment slot="aside">
|
||||
{#if isExpired}
|
||||
{#if isExpired || isExpiring}
|
||||
<Alert.Inline
|
||||
status="error"
|
||||
status={isExpired && isApiKey ? 'error' : 'warning'}
|
||||
on:dismiss={() => (alertsDismissed = true)}
|
||||
title="Your {label} key has expired">
|
||||
For security reasons, we recommend you delete your expired key and create a new
|
||||
one.
|
||||
</Alert.Inline>
|
||||
{:else if isExpiring}
|
||||
<Alert.Inline
|
||||
status="warning"
|
||||
on:dismiss={() => (alertsDismissed = true)}
|
||||
title="Your {label} key is about to expire">
|
||||
Update the expiration date to keep the key active
|
||||
title={`Your ${label} key ${isExpired ? 'has expired' : 'is about to expire'}`}>
|
||||
Update the expiration date to keep the key active.
|
||||
</Alert.Inline>
|
||||
{/if}
|
||||
<ExpirationInput bind:value={expiration} {expiryOptions} />
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
import { writable, type Writable } from 'svelte/store';
|
||||
import { IconPlus } from '@appwrite.io/pink-icons-svelte';
|
||||
import { isSmallViewport } from '$lib/stores/viewport';
|
||||
import { SHOW_INIT_FEATURES } from '$lib/system';
|
||||
|
||||
let period: UsagePeriods = '30d';
|
||||
$: path = `${base}/project-${page.params.region}-${page.params.project}/overview`;
|
||||
@@ -232,11 +233,13 @@
|
||||
event="keys"
|
||||
href={`${path}/keys`}
|
||||
selected={isTabSelected('keys')}>API keys</Tab>
|
||||
<Tab
|
||||
noscroll
|
||||
event="keys"
|
||||
href={`${path}/dev-keys`}
|
||||
selected={isTabSelected('dev-keys')}>Dev keys</Tab>
|
||||
{#if SHOW_INIT_FEATURES}
|
||||
<Tab
|
||||
noscroll
|
||||
event="keys"
|
||||
href={`${path}/dev-keys`}
|
||||
selected={isTabSelected('dev-keys')}>Dev keys</Tab>
|
||||
{/if}
|
||||
</Tabs>
|
||||
{#if $action}
|
||||
<svelte:component this={$action} />
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
<Form onSubmit={create} isModal>
|
||||
<Modal title="Create dev key" bind:open={$showDevKeysCreateModal}>
|
||||
<span slot="description">
|
||||
Test your app without rate limits and more detailed error messages.
|
||||
Bypass Appwrite rate limits and CORS errors in your development environment.
|
||||
</span>
|
||||
|
||||
<Layout.Stack>
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
<Typography.Title color="--fgcolor-neutral-primary" size="xl">
|
||||
{$project?.name}
|
||||
</Typography.Title>
|
||||
<Layout.Stack alignItems="center">
|
||||
<Layout.Stack alignItems="center" inline>
|
||||
<Id value={$project.$id}>{$project.$id}</Id>
|
||||
<RegionEndpoint />
|
||||
</Layout.Stack>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { base } from '$app/paths';
|
||||
import { page } from '$app/state';
|
||||
import { Id } from '$lib/components';
|
||||
import { Cover, CoverTitle } from '$lib/layout';
|
||||
import { key } from './store';
|
||||
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import type { Component, ComponentType } from 'svelte';
|
||||
import type { ComponentType } from 'svelte';
|
||||
|
||||
// export let icon: Component;
|
||||
export let icon: ComponentType; //TODO: switch to Component after pink 2 uses svelte 5
|
||||
|
||||
@@ -41,13 +41,11 @@
|
||||
total={data.rules.total} />
|
||||
{:else if data?.search}
|
||||
<EmptySearch hidePages bind:search={data.search} target="domains" hidePagination>
|
||||
<svelte:fragment slot="actions">
|
||||
<Button
|
||||
secondary
|
||||
on:click={() => {
|
||||
data.search = '';
|
||||
}}>Clear search</Button>
|
||||
</svelte:fragment>
|
||||
<Button
|
||||
secondary
|
||||
on:click={() => {
|
||||
data.search = '';
|
||||
}}>Clear search</Button>
|
||||
</EmptySearch>
|
||||
{:else}
|
||||
<Card.Base padding="none">
|
||||
|
||||
-2
@@ -5,7 +5,6 @@
|
||||
import { Wizard } from '$lib/layout';
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { Fieldset } from '@appwrite.io/pink-svelte';
|
||||
import { goto, invalidate } from '$app/navigation';
|
||||
import { Dependencies } from '$lib/constants';
|
||||
import { writable } from 'svelte/store';
|
||||
@@ -17,7 +16,6 @@
|
||||
|
||||
let formComponent: Form;
|
||||
let isSubmitting = $state(writable(false));
|
||||
let showConnectRepo = $state(false);
|
||||
let domainName = $state('');
|
||||
|
||||
onMount(() => {
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ import { Dependencies } from '$lib/constants.js';
|
||||
import { isCloud } from '$lib/system';
|
||||
import type { Domain, DomainsList } from '$lib/sdk/domains.js';
|
||||
|
||||
export const load = async ({ parent, depends, params }) => {
|
||||
export const load = async ({ depends, params }) => {
|
||||
depends(Dependencies.DOMAINS);
|
||||
|
||||
let domain: Domain;
|
||||
|
||||
@@ -22,8 +22,6 @@
|
||||
let showFailed = false;
|
||||
let selectedWebhook: Models.Webhook;
|
||||
|
||||
const projectId = page.params.project;
|
||||
|
||||
$: $updateCommandGroupRanks({ webhooks: 20, domains: 10 });
|
||||
</script>
|
||||
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@
|
||||
let showExitModal = false;
|
||||
|
||||
let name = '',
|
||||
events = [],
|
||||
events: string[] = [],
|
||||
url = '',
|
||||
security = true,
|
||||
httpUser = '',
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
import { protocol } from '$routes/(console)/store';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
import { IconDuplicate } from '@appwrite.io/pink-icons-svelte';
|
||||
import { Icon, Image, Input, Layout, Tooltip } from '@appwrite.io/pink-svelte';
|
||||
import { Icon, Image, Layout, Tooltip } from '@appwrite.io/pink-svelte';
|
||||
|
||||
let {
|
||||
show = $bindable(),
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
export let variant: 'primary' | 'secondary' = 'primary';
|
||||
|
||||
let show = false;
|
||||
const siteUrl = proxyRuleList.total > 0 ? proxyRuleList.rules[0].domain : undefined;
|
||||
|
||||
$: totalSize = humanFileSize(deployment?.totalSize ?? 0);
|
||||
|
||||
|
||||
@@ -135,9 +135,6 @@
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Environment variables" badge="Optional" hideDivider>
|
||||
<svelte:fragment slot="title">
|
||||
Environment variables <Badge content="Optional" variant="secondary" />
|
||||
</svelte:fragment>
|
||||
<Layout.Stack gap="xl">
|
||||
Set up environment variables to securely manage keys and settings for your
|
||||
project.
|
||||
|
||||
+12
-1
@@ -13,6 +13,8 @@
|
||||
|
||||
export let data;
|
||||
|
||||
let offset = 0;
|
||||
|
||||
function applyFilter(filter: string, value: string, event: CustomEvent) {
|
||||
const target = new URL(page.url);
|
||||
if (event?.detail) {
|
||||
@@ -31,6 +33,7 @@
|
||||
previous.forEach((n) => target.searchParams.append(filter, n));
|
||||
}
|
||||
target.searchParams.delete('page');
|
||||
offset = 0;
|
||||
goto(target.toString());
|
||||
}
|
||||
|
||||
@@ -47,6 +50,8 @@
|
||||
}
|
||||
|
||||
url.searchParams.delete('page');
|
||||
offset = 0;
|
||||
|
||||
goto(url.toString(), { keepFocus: true });
|
||||
}, 250);
|
||||
|
||||
@@ -125,7 +130,13 @@
|
||||
</svelte:fragment>
|
||||
<Layout.Stack gap="l">
|
||||
{#if data.templates?.length > 0}
|
||||
<Paginator items={data.templates} limit={12} hidePages={false} hasLimit gap="m">
|
||||
<Paginator
|
||||
items={data.templates}
|
||||
limit={12}
|
||||
hidePages={false}
|
||||
hasLimit
|
||||
gap="m"
|
||||
bind:offset>
|
||||
{#snippet children(paginatedItems: typeof data.templates)}
|
||||
<Layout.Grid columns={3} columnsXS={2} columnsXXS={1}>
|
||||
{#each paginatedItems as template (template.name)}
|
||||
|
||||
+3
-3
@@ -24,7 +24,7 @@
|
||||
import Details from '../../details.svelte';
|
||||
import Configuration from './configuration.svelte';
|
||||
import Aside from '../../aside.svelte';
|
||||
import { Adapter, BuildRuntime, Framework, ID } from '@appwrite.io/console';
|
||||
import { Adapter, BuildRuntime, Framework, ID, type Models } from '@appwrite.io/console';
|
||||
import {
|
||||
ConnectBehaviour,
|
||||
NewRepository,
|
||||
@@ -56,12 +56,12 @@
|
||||
let rootDir = './';
|
||||
let connectBehaviour: 'now' | 'later' = 'now';
|
||||
let repositoryBehaviour: 'new' | 'existing' = 'new';
|
||||
let repositoryName = undefined;
|
||||
let repositoryName: string = undefined;
|
||||
let repositoryPrivate = true;
|
||||
let selectedInstallationId = '';
|
||||
let selectedRepository = '';
|
||||
let showSiteConfig = false;
|
||||
let variables = [];
|
||||
let variables: Partial<Models.TemplateVariable>[] = [];
|
||||
let silentMode = false;
|
||||
|
||||
onMount(async () => {
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
import { Cover } from '$lib/layout';
|
||||
import { Typography } from '@appwrite.io/pink-svelte';
|
||||
|
||||
$: projectId = page.params.project;
|
||||
$: path = `${base}/project-${page.params.region}-${page.params.project}/sites`;
|
||||
$: tabs = [
|
||||
{
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@
|
||||
import { IconList, IconPlus, IconSearch } from '@appwrite.io/pink-icons-svelte';
|
||||
|
||||
onMount(() => {
|
||||
let previousStatus = null;
|
||||
let previousStatus: string = null;
|
||||
return sdk.forConsole.client.subscribe<Models.Deployment>('console', (message) => {
|
||||
if (previousStatus === message.payload.status) {
|
||||
return;
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { PaginationWithLimit, ViewSelector, EmptyFilter, Empty } from '$lib/components';
|
||||
import { PaginationWithLimit, EmptyFilter, Empty } from '$lib/components';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { Container, ResponsiveContainerHeader } from '$lib/layout';
|
||||
import { Adapter, BuildRuntime, Framework, type Models } from '@appwrite.io/console';
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@
|
||||
];
|
||||
|
||||
let range = SiteUsageRange.ThirtyDays;
|
||||
let metrics = [
|
||||
let metrics: { id: string; value: string | null; description: string }[] = [
|
||||
{
|
||||
id: 'buildsTotal',
|
||||
value: null,
|
||||
|
||||
+5
-7
@@ -39,13 +39,11 @@
|
||||
total={data.domains.total} />
|
||||
{:else if data?.search}
|
||||
<EmptySearch hidePages bind:search={data.search} target="domains" hidePagination>
|
||||
<svelte:fragment slot="actions">
|
||||
<Button
|
||||
secondary
|
||||
on:click={() => {
|
||||
data.search = '';
|
||||
}}>Clear search</Button>
|
||||
</svelte:fragment>
|
||||
<Button
|
||||
secondary
|
||||
on:click={() => {
|
||||
data.search = '';
|
||||
}}>Clear search</Button>
|
||||
</EmptySearch>
|
||||
{:else}
|
||||
<Card.Base padding="none">
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@
|
||||
let domain = baseDomain;
|
||||
let domainStatus: 'complete' | 'failed' | 'pending' = 'complete';
|
||||
|
||||
let error = null;
|
||||
let error: string = null;
|
||||
async function onSubmit() {
|
||||
try {
|
||||
await sdk
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
import { Cover, CoverTitle } from '$lib/layout';
|
||||
import { site } from './store';
|
||||
|
||||
$: projectId = page.params.project;
|
||||
$: path = `${base}/project-${page.params.region}-${page.params.project}/sites/site-${page.params.site}`;
|
||||
$: tabs = [
|
||||
{
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
<script lang="ts">
|
||||
import { invalidate } from '$app/navigation';
|
||||
import { EmptyFilter, PaginationWithLimit, ViewSelector } from '$lib/components';
|
||||
import { EmptyFilter, PaginationWithLimit } from '$lib/components';
|
||||
import { Dependencies } from '$lib/constants';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { Container, ResponsiveContainerHeader } from '$lib/layout';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { onMount } from 'svelte';
|
||||
import Table from './table.svelte';
|
||||
import { ParsedTagList, QuickFilters } from '$lib/components/filters';
|
||||
import { Card, Empty, Layout } from '@appwrite.io/pink-svelte';
|
||||
import { View } from '$lib/helpers/load';
|
||||
import { Card, Empty } from '@appwrite.io/pink-svelte';
|
||||
import { columns } from './store';
|
||||
|
||||
export let data;
|
||||
|
||||
+104
-87
@@ -42,94 +42,111 @@
|
||||
$: selectedLog = logs?.find((log) => log.$id === selectedLogId);
|
||||
$: isFirstLog = logs.findIndex((log) => log.$id === selectedLogId) === 0;
|
||||
$: isLastLog = logs.findIndex((log) => log.$id === selectedLogId) === logs.length - 1;
|
||||
|
||||
let sheet: HTMLDivElement;
|
||||
function handleClickOutside(event: MouseEvent) {
|
||||
if (sheet && !sheet.contains(event.target as Node)) {
|
||||
open = false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:window onclick={() => (open = false)} />
|
||||
<svelte:window onclick={handleClickOutside} />
|
||||
|
||||
<Sheet bind:open closeOnBlur={false}>
|
||||
<div slot="header" style:width="100%">
|
||||
<Layout.Stack direction="row" justifyContent="space-between" alignItems="center">
|
||||
<Layout.Stack direction="row" gap="m" alignItems="center">
|
||||
<Typography.Text variant="m-400">Log ID</Typography.Text>
|
||||
<Copy value={selectedLog?.$id}>
|
||||
<Tag size="s" variant="code">{selectedLog?.$id}</Tag>
|
||||
</Copy>
|
||||
</Layout.Stack>
|
||||
<Layout.Stack direction="row" gap="xs" alignItems="center" inline>
|
||||
<Button icon text size="xs" on:click={previousLog} disabled={isFirstLog}>
|
||||
<Icon icon={IconChevronUp} />
|
||||
</Button>
|
||||
<Button icon text size="xs" on:click={nextLog} disabled={isLastLog}>
|
||||
<Icon icon={IconChevronDown} />
|
||||
</Button>
|
||||
</Layout.Stack>
|
||||
</Layout.Stack>
|
||||
</div>
|
||||
{#if selectedLog}
|
||||
<Layout.Stack gap="xl">
|
||||
<Accordion title="Details" open>
|
||||
<Layout.Stack gap="xl">
|
||||
<Layout.Stack direction="row">
|
||||
<Layout.Grid columnsXS={2} columns={4} gap="xxxl" rowGap="xl">
|
||||
<Layout.Stack gap="xs" inline>
|
||||
<Typography.Text variant="m-400" color="--fgcolor-neutral-tertiary">
|
||||
Method
|
||||
</Typography.Text>
|
||||
<Typography.Text variant="m-400">
|
||||
{selectedLog.requestMethod}
|
||||
</Typography.Text>
|
||||
</Layout.Stack>
|
||||
<Layout.Stack gap="xs" inline>
|
||||
<Typography.Text variant="m-400" color="--fgcolor-neutral-tertiary">
|
||||
Status code
|
||||
</Typography.Text>
|
||||
<span>
|
||||
<Badge
|
||||
content={selectedLog.responseStatusCode.toString()}
|
||||
variant="secondary"
|
||||
type={selectedLog?.responseStatusCode >= 400
|
||||
? 'error'
|
||||
: 'success'} />
|
||||
</span>
|
||||
</Layout.Stack>
|
||||
<Layout.Stack gap="xs" inline>
|
||||
<Typography.Text variant="m-400" color="--fgcolor-neutral-tertiary">
|
||||
Duration
|
||||
</Typography.Text>
|
||||
<Typography.Text variant="m-400">
|
||||
{calculateTime(selectedLog.duration)}
|
||||
</Typography.Text>
|
||||
</Layout.Stack>
|
||||
<Layout.Stack gap="xs" inline>
|
||||
<Typography.Text variant="m-400" color="--fgcolor-neutral-tertiary">
|
||||
Created
|
||||
</Typography.Text>
|
||||
<Typography.Text variant="m-400">
|
||||
{capitalize(timeFromNow(selectedLog.$createdAt))}
|
||||
</Typography.Text>
|
||||
</Layout.Stack>
|
||||
</Layout.Grid>
|
||||
</Layout.Stack>
|
||||
|
||||
<Layout.Stack gap="xs" inline alignItems="flex-start">
|
||||
<Typography.Text variant="m-400" color="--fgcolor-neutral-tertiary">
|
||||
Path
|
||||
</Typography.Text>
|
||||
<div>
|
||||
<InteractiveText
|
||||
text={selectedLog.requestPath}
|
||||
variant="copy-code"
|
||||
isVisible />
|
||||
</div>
|
||||
</Layout.Stack>
|
||||
<div style="position: absolute; top: 0; " bind:this={sheet}>
|
||||
<Sheet bind:open closeOnBlur={false}>
|
||||
<div slot="header" style:width="100%">
|
||||
<Layout.Stack direction="row" justifyContent="space-between" alignItems="center">
|
||||
<Layout.Stack direction="row" gap="m" alignItems="center">
|
||||
<Typography.Text variant="m-400">Log ID</Typography.Text>
|
||||
<Copy value={selectedLog?.$id}>
|
||||
<Tag size="s" variant="code">{selectedLog?.$id}</Tag>
|
||||
</Copy>
|
||||
</Layout.Stack>
|
||||
</Accordion>
|
||||
<Accordion title="Request" open>
|
||||
<LogsRequest {selectedLog} />
|
||||
</Accordion>
|
||||
<Accordion title="Response" open hideDivider>
|
||||
<LogsResponse {selectedLog} logging={$site?.logging} product="site" />
|
||||
</Accordion>
|
||||
</Layout.Stack>
|
||||
{/if}
|
||||
</Sheet>
|
||||
<Layout.Stack direction="row" gap="xs" alignItems="center" inline>
|
||||
<Button icon text size="xs" on:click={previousLog} disabled={isFirstLog}>
|
||||
<Icon icon={IconChevronUp} />
|
||||
</Button>
|
||||
<Button icon text size="xs" on:click={nextLog} disabled={isLastLog}>
|
||||
<Icon icon={IconChevronDown} />
|
||||
</Button>
|
||||
</Layout.Stack>
|
||||
</Layout.Stack>
|
||||
</div>
|
||||
{#if selectedLog}
|
||||
<Layout.Stack gap="xl">
|
||||
<Accordion title="Details" open>
|
||||
<Layout.Stack gap="xl">
|
||||
<Layout.Stack direction="row">
|
||||
<Layout.Grid columnsXS={2} columns={4} gap="xxxl" rowGap="xl">
|
||||
<Layout.Stack gap="xs" inline>
|
||||
<Typography.Text
|
||||
variant="m-400"
|
||||
color="--fgcolor-neutral-tertiary">
|
||||
Method
|
||||
</Typography.Text>
|
||||
<Typography.Text variant="m-400">
|
||||
{selectedLog.requestMethod}
|
||||
</Typography.Text>
|
||||
</Layout.Stack>
|
||||
<Layout.Stack gap="xs" inline>
|
||||
<Typography.Text
|
||||
variant="m-400"
|
||||
color="--fgcolor-neutral-tertiary">
|
||||
Status code
|
||||
</Typography.Text>
|
||||
<span>
|
||||
<Badge
|
||||
content={selectedLog.responseStatusCode.toString()}
|
||||
variant="secondary"
|
||||
type={selectedLog?.responseStatusCode >= 400
|
||||
? 'error'
|
||||
: 'success'} />
|
||||
</span>
|
||||
</Layout.Stack>
|
||||
<Layout.Stack gap="xs" inline>
|
||||
<Typography.Text
|
||||
variant="m-400"
|
||||
color="--fgcolor-neutral-tertiary">
|
||||
Duration
|
||||
</Typography.Text>
|
||||
<Typography.Text variant="m-400">
|
||||
{calculateTime(selectedLog.duration)}
|
||||
</Typography.Text>
|
||||
</Layout.Stack>
|
||||
<Layout.Stack gap="xs" inline>
|
||||
<Typography.Text
|
||||
variant="m-400"
|
||||
color="--fgcolor-neutral-tertiary">
|
||||
Created
|
||||
</Typography.Text>
|
||||
<Typography.Text variant="m-400">
|
||||
{capitalize(timeFromNow(selectedLog.$createdAt))}
|
||||
</Typography.Text>
|
||||
</Layout.Stack>
|
||||
</Layout.Grid>
|
||||
</Layout.Stack>
|
||||
|
||||
<Layout.Stack gap="xs" inline alignItems="flex-start">
|
||||
<Typography.Text variant="m-400" color="--fgcolor-neutral-tertiary">
|
||||
Path
|
||||
</Typography.Text>
|
||||
<div>
|
||||
<InteractiveText
|
||||
text={selectedLog.requestPath}
|
||||
variant="copy-code"
|
||||
isVisible />
|
||||
</div>
|
||||
</Layout.Stack>
|
||||
</Layout.Stack>
|
||||
</Accordion>
|
||||
<Accordion title="Request" open>
|
||||
<LogsRequest {selectedLog} />
|
||||
</Accordion>
|
||||
<Accordion title="Response" open hideDivider>
|
||||
<LogsResponse {selectedLog} logging={$site?.logging} product="site" />
|
||||
</Accordion>
|
||||
</Layout.Stack>
|
||||
{/if}
|
||||
</Sheet>
|
||||
</div>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import { Id } from '$lib/components';
|
||||
import type { Column } from '$lib/helpers/types';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
import { Badge, Layout, Table, Typography } from '@appwrite.io/pink-svelte';
|
||||
import { Badge, Table, Typography } from '@appwrite.io/pink-svelte';
|
||||
import Sheet from './sheet.svelte';
|
||||
import DualTimeView from '$lib/components/dualTimeView.svelte';
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { Dependencies } from '$lib/constants';
|
||||
import { page } from '$app/state';
|
||||
|
||||
export const load = async ({ params, depends, parent }) => {
|
||||
depends(Dependencies.VARIABLES);
|
||||
|
||||
+91
-76
@@ -15,19 +15,76 @@
|
||||
import { getFrameworkIcon } from '$lib/stores/sites';
|
||||
import { page } from '$app/state';
|
||||
|
||||
export let site: Models.Site;
|
||||
export let frameworks: Models.Framework[];
|
||||
let selectedFramework: Models.Framework = frameworks.find(
|
||||
(framework) => framework.key === site.framework
|
||||
let {
|
||||
site,
|
||||
frameworks
|
||||
}: {
|
||||
site: Models.Site;
|
||||
frameworks: Models.Framework[];
|
||||
} = $props();
|
||||
|
||||
let frameworkKey = $state(site.framework);
|
||||
let installCommand = $state(site?.installCommand);
|
||||
let buildCommand = $state(site?.buildCommand);
|
||||
let outputDirectory = $state(site?.outputDirectory);
|
||||
let fallback = $state(site?.fallbackFile);
|
||||
let adapter: Adapter = $state(site.adapter as Adapter);
|
||||
|
||||
let selectedFramework: Models.Framework = $derived(
|
||||
frameworks.find((framework) => framework.key === site.framework)
|
||||
);
|
||||
let frameworkKey = site.framework;
|
||||
let adapter: Adapter = site.adapter as Adapter;
|
||||
let installCommand = site?.installCommand;
|
||||
let buildCommand = site?.buildCommand;
|
||||
let outputDirectory = site?.outputDirectory;
|
||||
let fallback = site?.fallbackFile;
|
||||
let isButtonDisabled = true;
|
||||
let showFallback = site.adapter === Adapter.Static;
|
||||
let showFallback = $derived(adapter === Adapter.Static);
|
||||
let hasChanges = $derived(
|
||||
installCommand === site?.installCommand &&
|
||||
buildCommand === site?.buildCommand &&
|
||||
outputDirectory === site?.outputDirectory &&
|
||||
selectedFramework?.key === site?.framework &&
|
||||
fallback === (site?.fallbackFile || undefined) &&
|
||||
adapter === site?.adapter
|
||||
);
|
||||
let frameworkAdapterData = $derived(
|
||||
selectedFramework.adapters.find((a) => a.key === adapter) ?? selectedFramework.adapters[0]
|
||||
);
|
||||
|
||||
$effect(() => {
|
||||
if (selectedFramework?.key !== site.framework) {
|
||||
//Update adapter
|
||||
const singleAdapter = selectedFramework?.adapters?.length <= 1;
|
||||
if (singleAdapter) {
|
||||
const hasSSR = selectedFramework?.adapters?.some((a) => a?.key === Adapter.Ssr);
|
||||
const hasStatic = selectedFramework?.adapters?.some(
|
||||
(a) => a?.key === Adapter.Static
|
||||
);
|
||||
if (!hasSSR) {
|
||||
adapter = Adapter.Static;
|
||||
} else if (!hasStatic) {
|
||||
adapter = Adapter.Ssr;
|
||||
}
|
||||
}
|
||||
|
||||
//Update values
|
||||
const data = selectedFramework.adapters.find((a) => a.key === adapter);
|
||||
installCommand = data.installCommand;
|
||||
buildCommand = data.buildCommand;
|
||||
outputDirectory = data.outputDirectory;
|
||||
adapter = selectedFramework.adapters[0].key as Adapter;
|
||||
} else {
|
||||
adapter = site.adapter as Adapter;
|
||||
installCommand = site?.installCommand ?? frameworkAdapterData.installCommand;
|
||||
buildCommand = site?.buildCommand ?? frameworkAdapterData.buildCommand;
|
||||
outputDirectory = site?.outputDirectory ?? frameworkAdapterData.outputDirectory;
|
||||
}
|
||||
});
|
||||
|
||||
$effect(() => {
|
||||
if (adapter === Adapter.Static) {
|
||||
if (!fallback) {
|
||||
fallback ||= selectedFramework.adapters.find(
|
||||
(a) => a.key === Adapter.Static
|
||||
).fallbackFile;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
async function update() {
|
||||
let adptr = selectedFramework.adapters.find((a) => a.key === adapter);
|
||||
@@ -50,12 +107,13 @@
|
||||
outputDirectory || undefined,
|
||||
(site?.buildRuntime as BuildRuntime) || undefined,
|
||||
(adptr?.key as Adapter) || undefined,
|
||||
fallback || undefined,
|
||||
adptr?.key === 'static' ? fallback || undefined : undefined,
|
||||
site.installationId || undefined,
|
||||
site.providerRepositoryId || undefined,
|
||||
site.providerBranch || undefined,
|
||||
site.providerSilentMode || undefined,
|
||||
site.providerRootDirectory || undefined
|
||||
site.providerRootDirectory || undefined,
|
||||
site?.specification || undefined
|
||||
);
|
||||
await invalidate(Dependencies.SITE);
|
||||
addNotification({
|
||||
@@ -72,41 +130,16 @@
|
||||
}
|
||||
}
|
||||
|
||||
$: if (
|
||||
installCommand === site?.installCommand &&
|
||||
buildCommand === site?.buildCommand &&
|
||||
outputDirectory === site?.outputDirectory &&
|
||||
selectedFramework?.key === site?.framework &&
|
||||
fallback === (site?.fallbackFile || undefined) &&
|
||||
adapter === site?.adapter
|
||||
) {
|
||||
isButtonDisabled = true;
|
||||
} else {
|
||||
// console.log(adapter, site?.adapter);
|
||||
isButtonDisabled = false;
|
||||
}
|
||||
function reset(type: 'installCommand' | 'buildCommand' | 'outputDirectory') {
|
||||
const data = selectedFramework.adapters.find((a) => a.key === adapter);
|
||||
|
||||
$: frameworkAdapterData = selectedFramework.adapters.find((a) => a.key === adapter);
|
||||
|
||||
$: if (adapter === Adapter.Static) {
|
||||
showFallback = true;
|
||||
fallback ||= selectedFramework.adapters.find((a) => a.key === Adapter.Static).fallbackFile;
|
||||
} else {
|
||||
showFallback = false;
|
||||
fallback = undefined;
|
||||
}
|
||||
|
||||
$: if (fallback === '') {
|
||||
fallback = null;
|
||||
}
|
||||
|
||||
$: hasSSR = selectedFramework?.adapters?.some((a) => a?.key === Adapter.Ssr);
|
||||
$: hasStatic = selectedFramework?.adapters?.some((a) => a?.key === Adapter.Static);
|
||||
$: if (selectedFramework?.adapters?.length <= 1 || !hasSSR) {
|
||||
adapter = Adapter.Static;
|
||||
}
|
||||
$: if (selectedFramework?.adapters?.length <= 1 || !hasStatic) {
|
||||
adapter = Adapter.Ssr;
|
||||
if (type === 'installCommand') {
|
||||
installCommand = site?.installCommand ?? data.installCommand;
|
||||
} else if (type === 'buildCommand') {
|
||||
buildCommand = site?.buildCommand ?? data.buildCommand;
|
||||
} else if (type === 'outputDirectory') {
|
||||
outputDirectory = site?.outputDirectory ?? data.outputDirectory;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -199,16 +232,10 @@
|
||||
id="installCommand"
|
||||
label="Install command"
|
||||
bind:value={installCommand}
|
||||
placeholder={frameworkAdapterData?.installCommand} />
|
||||
placeholder={frameworkAdapterData?.installCommand ||
|
||||
'Enter install command'} />
|
||||
|
||||
<Button
|
||||
secondary
|
||||
size="s"
|
||||
on:click={() =>
|
||||
(installCommand =
|
||||
site?.installCommand ??
|
||||
selectedFramework.adapters[site.adapter]
|
||||
?.defaultInstallCommand)}>
|
||||
<Button secondary size="s" on:click={() => reset('installCommand')}>
|
||||
Reset
|
||||
</Button>
|
||||
</Layout.Stack>
|
||||
@@ -217,15 +244,9 @@
|
||||
id="buildCommand"
|
||||
label="Build command"
|
||||
bind:value={buildCommand}
|
||||
placeholder={frameworkAdapterData?.buildCommand} />
|
||||
<Button
|
||||
secondary
|
||||
size="s"
|
||||
on:click={() =>
|
||||
(buildCommand =
|
||||
site?.buildCommand ??
|
||||
selectedFramework.adapters[site.adapter]
|
||||
?.defaultBuildCommand)}>
|
||||
placeholder={frameworkAdapterData?.buildCommand ||
|
||||
'Enter build command'} />
|
||||
<Button secondary size="s" on:click={() => reset('buildCommand')}>
|
||||
Reset
|
||||
</Button>
|
||||
</Layout.Stack>
|
||||
@@ -234,15 +255,9 @@
|
||||
id="outputDirectory"
|
||||
label="Output directory"
|
||||
bind:value={outputDirectory}
|
||||
placeholder={frameworkAdapterData?.outputDirectory} />
|
||||
<Button
|
||||
secondary
|
||||
size="s"
|
||||
on:click={() =>
|
||||
(outputDirectory =
|
||||
site?.outputDirectory ??
|
||||
selectedFramework.adapters[site.adapter]
|
||||
?.defaultOutputDirectory)}>
|
||||
placeholder={frameworkAdapterData?.outputDirectory ||
|
||||
'Enter output directory'} />
|
||||
<Button secondary size="s" on:click={() => reset('outputDirectory')}>
|
||||
Reset
|
||||
</Button>
|
||||
</Layout.Stack>
|
||||
@@ -267,7 +282,7 @@
|
||||
</svelte:fragment>
|
||||
|
||||
<svelte:fragment slot="actions">
|
||||
<Button disabled={isButtonDisabled} submit>Update</Button>
|
||||
<Button disabled={hasChanges} submit>Update</Button>
|
||||
</svelte:fragment>
|
||||
</CardGrid>
|
||||
</Form>
|
||||
|
||||
+13
-12
@@ -21,20 +21,21 @@
|
||||
site.$id,
|
||||
site.name,
|
||||
site.framework as Framework,
|
||||
site.enabled || undefined,
|
||||
site?.enabled || undefined,
|
||||
logging,
|
||||
site.timeout || undefined,
|
||||
site.installCommand || undefined,
|
||||
site.buildCommand || undefined,
|
||||
site.outputDirectory || undefined,
|
||||
site?.timeout || undefined,
|
||||
site?.installCommand || undefined,
|
||||
site?.buildCommand || undefined,
|
||||
site?.outputDirectory || undefined,
|
||||
(site?.buildRuntime as BuildRuntime) || undefined,
|
||||
site.adapter as Adapter,
|
||||
site.fallbackFile || undefined,
|
||||
site.installationId || undefined,
|
||||
site.providerRepositoryId || undefined,
|
||||
site.providerBranch || undefined,
|
||||
site.providerSilentMode || undefined,
|
||||
site.providerRootDirectory || undefined
|
||||
site?.adapter as Adapter,
|
||||
site?.fallbackFile || undefined,
|
||||
site?.installationId || undefined,
|
||||
site?.providerRepositoryId || undefined,
|
||||
site?.providerBranch || undefined,
|
||||
site?.providerSilentMode || undefined,
|
||||
site?.providerRootDirectory || undefined,
|
||||
site?.specification || undefined
|
||||
);
|
||||
await invalidate(Dependencies.SITE);
|
||||
addNotification({
|
||||
|
||||
+14
-13
@@ -25,20 +25,21 @@
|
||||
site.$id,
|
||||
siteName,
|
||||
site.framework as Framework,
|
||||
site.enabled || undefined,
|
||||
site.logging || undefined,
|
||||
site.timeout || undefined,
|
||||
site.installCommand || undefined,
|
||||
site.buildCommand || undefined,
|
||||
site.outputDirectory || undefined,
|
||||
site?.enabled || undefined,
|
||||
site?.logging || undefined,
|
||||
site?.timeout || undefined,
|
||||
site?.installCommand || undefined,
|
||||
site?.buildCommand || undefined,
|
||||
site?.outputDirectory || undefined,
|
||||
(site?.buildRuntime as BuildRuntime) || undefined,
|
||||
site.adapter as Adapter,
|
||||
site.fallbackFile || undefined,
|
||||
site.installationId || undefined,
|
||||
site.providerRepositoryId || undefined,
|
||||
site.providerBranch || undefined,
|
||||
site.providerSilentMode || undefined,
|
||||
site.providerRootDirectory || undefined
|
||||
site?.adapter as Adapter,
|
||||
site?.fallbackFile || undefined,
|
||||
site?.installationId || undefined,
|
||||
site?.providerRepositoryId || undefined,
|
||||
site?.providerBranch || undefined,
|
||||
site?.providerSilentMode || undefined,
|
||||
site?.providerRootDirectory || undefined,
|
||||
site?.specification || undefined
|
||||
);
|
||||
await invalidate(Dependencies.SITE);
|
||||
addNotification({
|
||||
|
||||
+12
-11
@@ -68,20 +68,21 @@
|
||||
site.$id,
|
||||
site.name,
|
||||
site?.framework as Framework,
|
||||
site.enabled || undefined,
|
||||
site.logging || undefined,
|
||||
site.timeout || undefined,
|
||||
site.installCommand || undefined,
|
||||
site.buildCommand || undefined,
|
||||
site.outputDirectory || undefined,
|
||||
site?.enabled || undefined,
|
||||
site?.logging || undefined,
|
||||
site?.timeout || undefined,
|
||||
site?.installCommand || undefined,
|
||||
site?.buildCommand || undefined,
|
||||
site?.outputDirectory || undefined,
|
||||
(site?.buildRuntime as BuildRuntime) || undefined,
|
||||
site.adapter as Adapter,
|
||||
site.fallbackFile || undefined,
|
||||
site.installationId || undefined,
|
||||
site.providerRepositoryId || undefined,
|
||||
site?.adapter as Adapter,
|
||||
site?.fallbackFile || undefined,
|
||||
site?.installationId || undefined,
|
||||
site?.providerRepositoryId || undefined,
|
||||
selectedBranch || undefined,
|
||||
silentMode || undefined,
|
||||
selectedDir || undefined
|
||||
selectedDir || undefined,
|
||||
site?.specification || undefined
|
||||
);
|
||||
await invalidate(Dependencies.SITE);
|
||||
addNotification({
|
||||
|
||||
+13
-13
@@ -26,20 +26,20 @@
|
||||
site.$id,
|
||||
site.name,
|
||||
site.framework as Framework,
|
||||
site.enabled || undefined,
|
||||
site.logging || undefined,
|
||||
site.timeout || undefined,
|
||||
site.installCommand || undefined,
|
||||
site.buildCommand || undefined,
|
||||
site.outputDirectory || undefined,
|
||||
site?.enabled || undefined,
|
||||
site?.logging || undefined,
|
||||
site?.timeout || undefined,
|
||||
site?.installCommand || undefined,
|
||||
site?.buildCommand || undefined,
|
||||
site?.outputDirectory || undefined,
|
||||
(site?.buildRuntime as BuildRuntime) || undefined,
|
||||
site.adapter as Adapter,
|
||||
site.fallbackFile || undefined,
|
||||
site.installationId || undefined,
|
||||
site.providerRepositoryId || undefined,
|
||||
site.providerBranch || undefined,
|
||||
site.providerSilentMode || undefined,
|
||||
site.providerRootDirectory || undefined,
|
||||
site?.adapter as Adapter,
|
||||
site?.fallbackFile || undefined,
|
||||
site?.installationId || undefined,
|
||||
site?.providerRepositoryId || undefined,
|
||||
site?.providerBranch || undefined,
|
||||
site?.providerSilentMode || undefined,
|
||||
site?.providerRootDirectory || undefined,
|
||||
specification || undefined
|
||||
);
|
||||
await invalidate(Dependencies.FUNCTION);
|
||||
|
||||
+14
-13
@@ -31,20 +31,21 @@
|
||||
site.$id,
|
||||
site.name,
|
||||
site?.framework as Framework,
|
||||
site.enabled || undefined,
|
||||
site.logging || undefined,
|
||||
site.timeout || undefined,
|
||||
site.installCommand || undefined,
|
||||
site.buildCommand || undefined,
|
||||
site.outputDirectory || undefined,
|
||||
site?.enabled || undefined,
|
||||
site?.logging || undefined,
|
||||
site?.timeout || undefined,
|
||||
site?.installCommand || undefined,
|
||||
site?.buildCommand || undefined,
|
||||
site?.outputDirectory || undefined,
|
||||
(buildRuntime as BuildRuntime) || undefined,
|
||||
site.adapter as Adapter,
|
||||
site.fallbackFile || undefined,
|
||||
site.installationId || undefined,
|
||||
site.providerRepositoryId || undefined,
|
||||
site.providerBranch || undefined,
|
||||
site.providerSilentMode || undefined,
|
||||
site.providerRootDirectory || undefined
|
||||
site?.adapter as Adapter,
|
||||
site?.fallbackFile || undefined,
|
||||
site?.installationId || undefined,
|
||||
site?.providerRepositoryId || undefined,
|
||||
site?.providerBranch || undefined,
|
||||
site?.providerSilentMode || undefined,
|
||||
site?.providerRootDirectory || undefined,
|
||||
site?.specification || undefined
|
||||
);
|
||||
await invalidate(Dependencies.SITE);
|
||||
addNotification({
|
||||
|
||||
+13
-12
@@ -24,20 +24,21 @@
|
||||
site.$id,
|
||||
site.name,
|
||||
site?.framework as Framework,
|
||||
site.enabled || undefined,
|
||||
site.logging || undefined,
|
||||
site?.enabled || undefined,
|
||||
site?.logging || undefined,
|
||||
timeout || undefined,
|
||||
site.installCommand || undefined,
|
||||
site.buildCommand || undefined,
|
||||
site.outputDirectory || undefined,
|
||||
site?.installCommand || undefined,
|
||||
site?.buildCommand || undefined,
|
||||
site?.outputDirectory || undefined,
|
||||
(site?.buildRuntime as BuildRuntime) || undefined,
|
||||
site.adapter as Adapter,
|
||||
site.fallbackFile || undefined,
|
||||
site.installationId || undefined,
|
||||
site.providerRepositoryId || undefined,
|
||||
site.providerBranch || undefined,
|
||||
site.providerSilentMode || undefined,
|
||||
site.providerRootDirectory || undefined
|
||||
site?.adapter as Adapter,
|
||||
site?.fallbackFile || undefined,
|
||||
site?.installationId || undefined,
|
||||
site?.providerRepositoryId || undefined,
|
||||
site?.providerBranch || undefined,
|
||||
site?.providerSilentMode || undefined,
|
||||
site?.providerRootDirectory || undefined,
|
||||
site?.specification || undefined
|
||||
);
|
||||
await invalidate(Dependencies.SITE);
|
||||
addNotification({
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
let showDelete = false;
|
||||
let selectedFile: Models.File = null;
|
||||
|
||||
const projectId = page.params.project;
|
||||
const bucketId = page.params.bucket;
|
||||
|
||||
function getPreview(fileId: string) {
|
||||
|
||||
+91
-85
@@ -21,15 +21,12 @@
|
||||
Alert,
|
||||
Badge,
|
||||
Button as PinkButton,
|
||||
InteractiveText,
|
||||
Layout,
|
||||
Icon,
|
||||
Popover,
|
||||
Table,
|
||||
Typography
|
||||
} from '@appwrite.io/pink-svelte';
|
||||
import {
|
||||
IconChevronRight,
|
||||
IconDotsHorizontal,
|
||||
IconDuplicate,
|
||||
IconKey,
|
||||
@@ -42,6 +39,7 @@
|
||||
import { type Models, Permission, Role } from '@appwrite.io/console';
|
||||
import { isSmallViewport } from '$lib/stores/viewport';
|
||||
import { Menu } from '$lib/components/menu';
|
||||
import { SHOW_INIT_FEATURES } from '$lib/system';
|
||||
|
||||
let showFileAlert = true;
|
||||
|
||||
@@ -212,7 +210,10 @@
|
||||
</div>
|
||||
<svelte:fragment slot="aside">
|
||||
<div>
|
||||
<p><span class="u-bold">Filename:</span> {$file.name}</p>
|
||||
<p>
|
||||
<span class="u-bold">Filename:</span>
|
||||
<span class="u-trim">{$file.name}</span>
|
||||
</p>
|
||||
<p><span class="u-bold">MIME type:</span> {$file.mimeType}</p>
|
||||
<p><span class="u-bold">Size:</span> {calculateSize($file.sizeOriginal)}</p>
|
||||
<p><span class="u-bold">Created:</span> {toLocaleDate($file.$createdAt)}</p>
|
||||
@@ -231,51 +232,55 @@
|
||||
</svelte:fragment>
|
||||
</CardGrid>
|
||||
|
||||
<CardGrid>
|
||||
<svelte:fragment slot="title">File tokens</svelte:fragment>
|
||||
Use tokens to provide public access to the file.
|
||||
<svelte:fragment slot="aside">
|
||||
{#if $tokens.total}
|
||||
<Layout.Stack
|
||||
justifyContent="flex-end"
|
||||
direction={$isSmallViewport ? 'column' : 'row'}>
|
||||
<Button secondary on:click={() => (showManageToken = true)}>
|
||||
<Icon size="s" icon={IconPlus} />
|
||||
<span class="text">Create token</span>
|
||||
</Button>
|
||||
</Layout.Stack>
|
||||
{#if SHOW_INIT_FEATURES}
|
||||
<CardGrid>
|
||||
<svelte:fragment slot="title">File tokens</svelte:fragment>
|
||||
Use tokens to provide public access to the file.
|
||||
<svelte:fragment slot="aside">
|
||||
{#if $tokens.total}
|
||||
<Layout.Stack
|
||||
justifyContent="flex-end"
|
||||
direction={$isSmallViewport ? 'column' : 'row'}>
|
||||
<Button secondary on:click={() => (showManageToken = true)}>
|
||||
<Icon size="s" icon={IconPlus} />
|
||||
<span class="text">Create token</span>
|
||||
</Button>
|
||||
</Layout.Stack>
|
||||
|
||||
<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>
|
||||
<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 $tokens.tokens as token}
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell column="created" {root}
|
||||
>{toLocaleDate(token.$createdAt)}</Table.Cell>
|
||||
{#each $tokens.tokens as token}
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell column="created" {root}
|
||||
>{toLocaleDate(token.$createdAt)}</Table.Cell>
|
||||
|
||||
<Table.Cell column="expire" {root}>
|
||||
<Layout.Stack gap="s" direction="row">
|
||||
{@const expiration = getExpiryDetails(token)}
|
||||
{token.expire ? cleanFormattedDate(token.expire) : 'Never'}
|
||||
<Table.Cell column="expire" {root}>
|
||||
<Layout.Stack gap="s" direction="row">
|
||||
{@const expiration = getExpiryDetails(token)}
|
||||
{token.expire
|
||||
? cleanFormattedDate(token.expire)
|
||||
: 'Never'}
|
||||
|
||||
{#if expiration.status}
|
||||
<Badge
|
||||
size="s"
|
||||
variant="secondary"
|
||||
type={expiration.status}
|
||||
content={expiration.message} />
|
||||
{/if}
|
||||
</Layout.Stack>
|
||||
</Table.Cell>
|
||||
{#if expiration.status}
|
||||
<Badge
|
||||
size="s"
|
||||
variant="secondary"
|
||||
type={expiration.status}
|
||||
content={expiration.message} />
|
||||
{/if}
|
||||
</Layout.Stack>
|
||||
</Table.Cell>
|
||||
|
||||
<Table.Cell column="last_accessed" {root}
|
||||
>{token.accessedAt
|
||||
? cleanFormattedDate(token.accessedAt, true)
|
||||
: 'Never'}</Table.Cell>
|
||||
<Table.Cell column="last_accessed" {root}
|
||||
>{token.accessedAt
|
||||
? cleanFormattedDate(token.accessedAt, true)
|
||||
: 'Never'}</Table.Cell>
|
||||
|
||||
<Table.Cell column="actions" {root}>
|
||||
<Layout.Stack alignItems="flex-end">
|
||||
@@ -284,53 +289,54 @@
|
||||
<Icon size="s" icon={IconDotsHorizontal} />
|
||||
</PinkButton.Button>
|
||||
|
||||
<svelte:fragment slot="menu" let:toggle>
|
||||
<ActionMenu.Root>
|
||||
<ActionMenu.Root noPadding>
|
||||
<svelte:fragment slot="menu" let:toggle>
|
||||
<ActionMenu.Root>
|
||||
<ActionMenu.Root noPadding>
|
||||
<ActionMenu.Item.Button
|
||||
on:click={(e) => {
|
||||
toggle(e);
|
||||
showCopyUrlModal = true;
|
||||
selectedFileToken = token;
|
||||
}}
|
||||
leadingIcon={IconDuplicate}>
|
||||
Copy URL
|
||||
</ActionMenu.Item.Button>
|
||||
</ActionMenu.Root>
|
||||
<ActionMenu.Item.Button
|
||||
leadingIcon={IconPencil}
|
||||
on:click={(e) => {
|
||||
toggle(e);
|
||||
showCopyUrlModal = true;
|
||||
showManageToken = true;
|
||||
selectedFileToken = token;
|
||||
}}
|
||||
leadingIcon={IconDuplicate}>
|
||||
Copy URL
|
||||
}}>
|
||||
Edit expiry
|
||||
</ActionMenu.Item.Button>
|
||||
<ActionMenu.Item.Button
|
||||
status="danger"
|
||||
leadingIcon={IconTrash}
|
||||
on:click={async () => {
|
||||
toggle(e);
|
||||
tokenDeleteMode = true;
|
||||
showManageToken = true;
|
||||
selectedFileToken = token;
|
||||
}}>
|
||||
Delete
|
||||
</ActionMenu.Item.Button>
|
||||
</ActionMenu.Root>
|
||||
<ActionMenu.Item.Button
|
||||
leadingIcon={IconPencil}
|
||||
on:click={(e) => {
|
||||
toggle(e);
|
||||
showManageToken = true;
|
||||
selectedFileToken = token;
|
||||
}}>
|
||||
Edit expiry
|
||||
</ActionMenu.Item.Button>
|
||||
<ActionMenu.Item.Button
|
||||
status="danger"
|
||||
leadingIcon={IconTrash}
|
||||
on:click={async (e) => {
|
||||
toggle(e);
|
||||
tokenDeleteMode = true;
|
||||
showManageToken = true;
|
||||
selectedFileToken = token;
|
||||
}}>
|
||||
Delete
|
||||
</ActionMenu.Item.Button>
|
||||
</ActionMenu.Root>
|
||||
</svelte:fragment>
|
||||
</Menu>
|
||||
</Layout.Stack>
|
||||
</Table.Cell>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
{:else}
|
||||
<Empty on:click={() => (showManageToken = true)}>Create new file token</Empty>
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
</CardGrid>
|
||||
|
||||
</svelte:fragment>
|
||||
</Menu>
|
||||
</Layout.Stack>
|
||||
</Table.Cell>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
{:else}
|
||||
<Empty on:click={() => (showManageToken = true)}
|
||||
>Create new file token</Empty>
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
</CardGrid>
|
||||
{/if}
|
||||
<CardGrid>
|
||||
<svelte:fragment slot="title">Permissions</svelte:fragment>
|
||||
Assign read or write permissions at the bucket level or file level. If bucket level permissions
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
import { page } from '$app/state';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
import { Modal, Card, CopyInput } from '$lib/components';
|
||||
import { Modal, CopyInput } from '$lib/components';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { Alert, Layout, Tabs, Typography } from '@appwrite.io/pink-svelte';
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
import { Table } from '@appwrite.io/pink-svelte';
|
||||
|
||||
export let data: PageData;
|
||||
const projectId = page.params.project;
|
||||
</script>
|
||||
|
||||
<Table.Root columns={$columns} let:root>
|
||||
|
||||
@@ -103,9 +103,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
async function requestAccess() {
|
||||
//TODO: Implement request access
|
||||
}
|
||||
// async function requestAccess() {
|
||||
// //TODO: Implement request access
|
||||
// }
|
||||
|
||||
$: console.log(data);
|
||||
</script>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user