mirror of
https://github.com/appwrite/console.git
synced 2026-06-06 19:27:48 +00:00
Merge branch 'feat-pink-v2' into add-tips-to-sites
This commit is contained in:
-1
@@ -12,7 +12,6 @@
|
||||
import { timeFromNow, toLocaleDateTime } from '$lib/helpers/date';
|
||||
import { type Models } from '@appwrite.io/console';
|
||||
import type { Column } from '$lib/helpers/types';
|
||||
import { tooltip } from '$lib/actions/tooltip';
|
||||
import { Pill } from '$lib/elements';
|
||||
import { calculateTime } from '$lib/helpers/timeConversion';
|
||||
import { log } from '$lib/stores/logs';
|
||||
|
||||
+9
-4
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import Link from '$lib/elements/link.svelte';
|
||||
import { timeFromNow } from '$lib/helpers/date';
|
||||
import { capitalize } from '$lib/helpers/string';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
import { Typography } from '@appwrite.io/pink-svelte';
|
||||
|
||||
@@ -9,12 +10,16 @@
|
||||
|
||||
{#if deployment.providerCommitAuthor}
|
||||
<Typography.Text variant="m-400">
|
||||
{timeFromNow(deployment.$updatedAt)} ago by <Link
|
||||
href={deployment.providerCommitAuthorUrl}
|
||||
external>{deployment.providerCommitAuthor}</Link>
|
||||
<span title={deployment.$updatedAt}>
|
||||
{capitalize(timeFromNow(deployment.$updatedAt))}
|
||||
</span>
|
||||
ago by <Link href={deployment.providerCommitAuthorUrl} external
|
||||
>{deployment.providerCommitAuthor}</Link>
|
||||
</Typography.Text>
|
||||
{:else}
|
||||
<Typography.Text variant="m-400">
|
||||
{timeFromNow(deployment.$updatedAt)}
|
||||
<span title={deployment.$updatedAt}>
|
||||
{capitalize(timeFromNow(deployment.$updatedAt))}
|
||||
</span>
|
||||
</Typography.Text>
|
||||
{/if}
|
||||
|
||||
@@ -1,20 +1,18 @@
|
||||
<script lang="ts">
|
||||
import { Trim } from '$lib/components';
|
||||
import { Link, Pill } from '$lib/elements';
|
||||
import { consoleVariables } from '$routes/(console)/store';
|
||||
import { protocol } from '$routes/(console)/store';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
import { IconExternalLink } from '@appwrite.io/pink-icons-svelte';
|
||||
import { ActionMenu, Icon, Layout, Popover } from '@appwrite.io/pink-svelte';
|
||||
|
||||
export let domains: Models.ProxyRuleList;
|
||||
|
||||
let protocol: 'http://' | 'https://' = $consoleVariables?._APP_OPTIONS_FORCE_HTTPS
|
||||
? 'https://'
|
||||
: 'http://';
|
||||
$: console.log(domains);
|
||||
</script>
|
||||
|
||||
<Layout.Stack gap="xxs" direction="row" alignItems="center">
|
||||
<Link external href={`${protocol}${domains.rules[0].domain}`} variant="muted">
|
||||
<Link external href={`${$protocol}${domains.rules[0].domain}`} variant="muted">
|
||||
<Layout.Stack gap="xxs" direction="row" alignItems="center">
|
||||
<Trim alternativeTrim>
|
||||
{domains.rules[0].domain}
|
||||
@@ -27,15 +25,17 @@
|
||||
<Pill button on:click={toggle}>
|
||||
+{domains.rules.length - 1}
|
||||
</Pill>
|
||||
<svelte:fragment slot="popover">
|
||||
<svelte:fragment slot="tooltip">
|
||||
<ActionMenu.Root>
|
||||
{#each domains.rules as rule, i}
|
||||
{#if i !== 0}
|
||||
<ActionMenu.Item.Anchor
|
||||
href={`${protocol}${rule.domain}`}
|
||||
href={`${$protocol}${rule.domain}`}
|
||||
external
|
||||
leadingIcon={IconExternalLink}>
|
||||
{rule.domain}
|
||||
<Trim alternativeTrim>
|
||||
{rule.domain}
|
||||
</Trim>
|
||||
</ActionMenu.Item.Anchor>
|
||||
{/if}
|
||||
{/each}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
import { Button, InputText } from '$lib/elements/forms';
|
||||
import { copy } from '$lib/helpers/copy';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { consoleVariables } from '$routes/(console)/store';
|
||||
import { protocol } from '$routes/(console)/store';
|
||||
import { IconDuplicate } from '@appwrite.io/pink-icons-svelte';
|
||||
import { Image, Input, Layout } from '@appwrite.io/pink-svelte';
|
||||
import { onMount } from 'svelte';
|
||||
@@ -12,7 +12,7 @@
|
||||
export let show = false;
|
||||
export let siteURL: string;
|
||||
|
||||
let url = ($consoleVariables?._APP_OPTIONS_FORCE_HTTPS ? 'https://' : 'http://') + siteURL;
|
||||
let url = $protocol + siteURL;
|
||||
|
||||
let image = '';
|
||||
onMount(() => {
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
import { IconExternalLink, IconQrcode } from '@appwrite.io/pink-icons-svelte';
|
||||
import OpenOnMobileModal from './openOnMobileModal.svelte';
|
||||
import DeploymentDomains from './deploymentDomains.svelte';
|
||||
import { consoleVariables } from '$routes/(console)/store';
|
||||
import { protocol } from '$routes/(console)/store';
|
||||
|
||||
export let deployment: Models.Deployment;
|
||||
export let proxyRuleList: Models.ProxyRuleList = { total: 0, rules: [] };
|
||||
@@ -56,8 +56,9 @@
|
||||
{/if}
|
||||
</Layout.Stack>
|
||||
{#if siteUrl}
|
||||
<Button icon text on:click={() => (show = true)}
|
||||
><Icon icon={IconQrcode} /></Button>
|
||||
<Button icon text on:click={() => (show = true)}>
|
||||
<Icon icon={IconQrcode} />
|
||||
</Button>
|
||||
{/if}
|
||||
</Layout.Stack>
|
||||
{#if proxyRuleList?.total}
|
||||
@@ -72,12 +73,7 @@
|
||||
<Typography.Text variant="m-400" color="--color-fgcolor-neutral-tertiary">
|
||||
Domains
|
||||
</Typography.Text>
|
||||
<Link
|
||||
external
|
||||
href={`${
|
||||
$consoleVariables?._APP_OPTIONS_FORCE_HTTPS ? 'https://' : 'http://'
|
||||
}${deployment.domain}`}
|
||||
variant="muted">
|
||||
<Link external href={`${$protocol}${deployment.domain}`} variant="muted">
|
||||
<Layout.Stack gap="xxs" direction="row" alignItems="center">
|
||||
<Trim alternativeTrim>
|
||||
{deployment.domain}
|
||||
|
||||
@@ -12,7 +12,8 @@ export const load = async ({ depends, params }) => {
|
||||
sdk.forProject.sites.get(params.site),
|
||||
sdk.forProject.proxy.listRules([
|
||||
Query.equal('resourceType', 'site'),
|
||||
Query.equal('resourceId', params.site)
|
||||
Query.equal('resourceId', params.site),
|
||||
Query.orderDesc('')
|
||||
])
|
||||
]);
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
<script lang="ts">
|
||||
import Container from '$lib/layout/container.svelte';
|
||||
import { Container } from '$lib/layout';
|
||||
import { Divider, Layout } from '@appwrite.io/pink-svelte';
|
||||
import SiteCard from '../(components)/siteCard.svelte';
|
||||
import DomainsOverview from './domainsOverview.svelte';
|
||||
import DeploymentsOverview from './deploymentsOverview.svelte';
|
||||
|
||||
export let data;
|
||||
|
||||
@@ -10,5 +13,15 @@
|
||||
</script>
|
||||
|
||||
<Container>
|
||||
<SiteCard deployment={data.deployment} proxyRuleList={data.proxyRuleList} />
|
||||
<Layout.Stack gap="xxl">
|
||||
<SiteCard deployment={data.deployment} proxyRuleList={data.proxyRuleList} />
|
||||
|
||||
<Divider />
|
||||
<Layout.Stack direction="row" gap="xxl">
|
||||
<DomainsOverview proxyRuleList={data.proxyRuleList} />
|
||||
<DeploymentsOverview
|
||||
activeDeployment={data.deployment}
|
||||
deploymentList={data.deploymentList} />
|
||||
</Layout.Stack>
|
||||
</Layout.Stack>
|
||||
</Container>
|
||||
|
||||
@@ -1,17 +1,20 @@
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { Dependencies } from '$lib/constants';
|
||||
import { Query } from '@appwrite.io/console';
|
||||
|
||||
export const load = async ({ params, depends, parent }) => {
|
||||
depends(Dependencies.SITE);
|
||||
|
||||
depends(Dependencies.SITES_DOMAINS);
|
||||
const { site, proxyRuleList } = await parent();
|
||||
|
||||
const [deployment] = await Promise.all([
|
||||
sdk.forProject.sites.getDeployment(params.site, site.deploymentId)
|
||||
const [deployment, deploymentList] = await Promise.all([
|
||||
sdk.forProject.sites.getDeployment(params.site, site.deploymentId),
|
||||
sdk.forProject.sites.listDeployments(params.site, [Query.limit(5), Query.orderDesc('')])
|
||||
]);
|
||||
return {
|
||||
site,
|
||||
deployment,
|
||||
deploymentList,
|
||||
proxyRuleList
|
||||
};
|
||||
};
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
<script lang="ts">
|
||||
import { Badge, Layout, Status, Table, Typography } from '@appwrite.io/pink-svelte';
|
||||
import OpenOnMobileModal from '../(components)/openOnMobileModal.svelte';
|
||||
import Button from '$lib/elements/forms/button.svelte';
|
||||
import { base } from '$app/paths';
|
||||
import { page } from '$app/stores';
|
||||
import { type Models } from '@appwrite.io/console';
|
||||
import DeploymentCreatedBy from '../(components)/deploymentCreatedBy.svelte';
|
||||
import DeploymentSource from '../(components)/deploymentSource.svelte';
|
||||
import Id from '$lib/components/id.svelte';
|
||||
|
||||
export let activeDeployment: Models.Deployment;
|
||||
export let deploymentList: Models.DeploymentList = undefined;
|
||||
|
||||
let showDomainQR = false;
|
||||
let selectedDomainURL: string;
|
||||
</script>
|
||||
|
||||
<Layout.Stack>
|
||||
<Layout.Stack direction="row" justifyContent="space-between" alignItems="center">
|
||||
<Layout.Stack gap="xs" direction="row" alignItems="center" inline>
|
||||
<Typography.Text variant="l-500">Deployments</Typography.Text><Badge
|
||||
variant="secondary"
|
||||
content={deploymentList?.total.toString()}
|
||||
size="s" />
|
||||
</Layout.Stack>
|
||||
<Button
|
||||
secondary
|
||||
href={`${base}/project-${$page.params.project}/sites/site-${$page.params.site}/deployments`}>
|
||||
View all
|
||||
</Button>
|
||||
</Layout.Stack>
|
||||
{#if deploymentList?.total}
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Deployment ID</Table.Header.Cell>
|
||||
<Table.Header.Cell>Status</Table.Header.Cell>
|
||||
<Table.Header.Cell>Source</Table.Header.Cell>
|
||||
<Table.Header.Cell>Updated</Table.Header.Cell>
|
||||
</svelte:fragment>
|
||||
{#each deploymentList?.deployments as deployment}
|
||||
<Table.Link
|
||||
href={`${base}/project-${$page.params.project}/sites/site-${$page.params.site}/deployments/deployment-${deployment.$id}`}>
|
||||
<Table.Cell>
|
||||
<Id value={deployment.$id}>{deployment.$id}</Id>
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
{@const status = deployment.status}
|
||||
{#if activeDeployment?.$id === deployment?.$id}
|
||||
<Status status="complete" label="active" />
|
||||
{:else}
|
||||
<Status
|
||||
status={status === 'failed'
|
||||
? status
|
||||
: status === 'building'
|
||||
? 'pending'
|
||||
: 'ready'}
|
||||
label={status} />
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
|
||||
<Table.Cell>
|
||||
<DeploymentSource {deployment} />
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<DeploymentCreatedBy {deployment} />
|
||||
</Table.Cell>
|
||||
</Table.Link>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
{/if}
|
||||
</Layout.Stack>
|
||||
|
||||
{#if showDomainQR && selectedDomainURL}
|
||||
<OpenOnMobileModal bind:show={showDomainQR} siteURL={selectedDomainURL} />
|
||||
{/if}
|
||||
@@ -6,7 +6,7 @@
|
||||
import Link from '$lib/elements/link.svelte';
|
||||
import { toLocaleDateTime } from '$lib/helpers/date';
|
||||
import Container from '$lib/layout/container.svelte';
|
||||
import { consoleVariables } from '$routes/(console)/store.js';
|
||||
import { protocol } from '$routes/(console)/store.js';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
import {
|
||||
IconDotsHorizontal,
|
||||
@@ -50,9 +50,7 @@
|
||||
<Layout.Stack direction="row" alignItems="center" gap="xs">
|
||||
<Link
|
||||
external
|
||||
href={`${
|
||||
$consoleVariables?._APP_OPTIONS_FORCE_HTTPS ? 'https://' : 'http://'
|
||||
}${domain.domain}`}
|
||||
href={`${$protocol}${domain.domain}`}
|
||||
size="s"
|
||||
variant="quiet">
|
||||
{domain.domain}
|
||||
|
||||
+3
@@ -19,6 +19,8 @@
|
||||
Typography
|
||||
} from '@appwrite.io/pink-svelte';
|
||||
import RecordsCard from '../recordsCard.svelte';
|
||||
import { invalidate } from '$app/navigation';
|
||||
import { Dependencies } from '$lib/constants';
|
||||
|
||||
const backPage = `${base}/project-${$page.params.project}/sites/site-${$page.params.site}/domains`;
|
||||
|
||||
@@ -33,6 +35,7 @@
|
||||
$page.params.site
|
||||
);
|
||||
console.log(domainData);
|
||||
invalidate(Dependencies.SITES_DOMAINS);
|
||||
} catch (error) {
|
||||
addNotification({
|
||||
type: 'error',
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
<script lang="ts">
|
||||
import { base } from '$app/paths';
|
||||
import { page } from '$app/stores';
|
||||
import { Badge, Divider, Icon, Layout, Typography } from '@appwrite.io/pink-svelte';
|
||||
import OpenOnMobileModal from '../(components)/openOnMobileModal.svelte';
|
||||
import { timeFromNow } from '$lib/helpers/date';
|
||||
import { IconExternalLink, IconQrcode } from '@appwrite.io/pink-icons-svelte';
|
||||
import { protocol } from '$routes/(console)/store';
|
||||
import { type Models } from '@appwrite.io/console';
|
||||
import { Link } from '$lib/elements';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { Card } from '$lib/components';
|
||||
|
||||
export let proxyRuleList: Models.ProxyRuleList;
|
||||
|
||||
let showDomainQR = false;
|
||||
let selectedDomainURL: string;
|
||||
</script>
|
||||
|
||||
<Layout.Stack>
|
||||
<Layout.Stack direction="row" justifyContent="space-between" alignItems="center">
|
||||
<Layout.Stack gap="xs" direction="row" alignItems="center" inline>
|
||||
<Typography.Text variant="l-500">Domains</Typography.Text><Badge
|
||||
variant="secondary"
|
||||
content={proxyRuleList?.total.toString()}
|
||||
size="s" />
|
||||
</Layout.Stack>
|
||||
<Button
|
||||
secondary
|
||||
href={`${base}/project-${$page.params.project}/sites/site-${$page.params.site}/domains`}>
|
||||
View all
|
||||
</Button>
|
||||
</Layout.Stack>
|
||||
<Card padding="s" isTile>
|
||||
{#each proxyRuleList?.rules?.slice(0, 3) as rule, i}
|
||||
<Layout.Stack
|
||||
gap="xs"
|
||||
alignItems="center"
|
||||
justifyContent="space-between"
|
||||
direction="row">
|
||||
<Layout.Stack gap="xs">
|
||||
<Link variant="quiet-muted" href={`${$protocol}${rule.domain}`} external>
|
||||
{rule.domain}
|
||||
<Icon icon={IconExternalLink} />
|
||||
</Link>
|
||||
<Typography.Text>
|
||||
Added {timeFromNow(rule.$createdAt)}
|
||||
</Typography.Text>
|
||||
</Layout.Stack>
|
||||
<Button
|
||||
icon
|
||||
secondary
|
||||
on:click={() => {
|
||||
showDomainQR = true;
|
||||
selectedDomainURL = rule.domain;
|
||||
console.log(rule.domain);
|
||||
}}>
|
||||
<Icon icon={IconQrcode} />
|
||||
</Button>
|
||||
</Layout.Stack>
|
||||
{#if i < 2 && i < proxyRuleList.rules.length - 1}
|
||||
<Divider />
|
||||
{/if}
|
||||
{/each}
|
||||
</Card>
|
||||
</Layout.Stack>
|
||||
|
||||
{#if showDomainQR && selectedDomainURL}
|
||||
<OpenOnMobileModal bind:show={showDomainQR} siteURL={selectedDomainURL} />
|
||||
{/if}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
<script lang="ts">
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
import { IconInfo } from '@appwrite.io/pink-icons-svelte';
|
||||
import { Badge, Icon, Layout, Table, Tabs, Typography } from '@appwrite.io/pink-svelte';
|
||||
|
||||
export let selectedLog: Models.Execution;
|
||||
|
||||
let requestTab: 'parameters' | 'headers' | 'body' = 'parameters';
|
||||
</script>
|
||||
|
||||
<Layout.Stack>
|
||||
<Tabs.Root variant="secondary">
|
||||
<Tabs.Item.Button
|
||||
active={requestTab === 'parameters'}
|
||||
on:click={() => (requestTab = 'parameters')}>
|
||||
Parameters
|
||||
</Tabs.Item.Button>
|
||||
<Tabs.Item.Button
|
||||
active={requestTab === 'headers'}
|
||||
on:click={() => (requestTab = 'headers')}>
|
||||
Headers <Badge
|
||||
variant="secondary"
|
||||
size="s"
|
||||
content={selectedLog?.requestHeaders?.length?.toString()} />
|
||||
</Tabs.Item.Button>
|
||||
<Tabs.Item.Button active={requestTab === 'body'} on:click={() => (requestTab = 'body')}>
|
||||
Body
|
||||
</Tabs.Item.Button>
|
||||
</Tabs.Root>
|
||||
{#if requestTab === 'parameters'}
|
||||
<Typography.Code>No parameters found.</Typography.Code>
|
||||
{:else if requestTab === 'headers'}
|
||||
{#if selectedLog.requestHeaders?.length}
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Key</Table.Header.Cell>
|
||||
<Table.Header.Cell>Value</Table.Header.Cell>
|
||||
</svelte:fragment>
|
||||
{#each selectedLog.requestHeaders as request}
|
||||
<Table.Row>
|
||||
<Table.Cell>{request.name}</Table.Cell>
|
||||
<Table.Cell>{request.value}</Table.Cell>
|
||||
</Table.Row>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
<p>
|
||||
<Layout.Stack direction="row" gap="xs" alignItems="center">
|
||||
<Icon icon={IconInfo} size="s" color="--color-fgcolor-neutral-secondary" /> Missing
|
||||
headers? Check our docs to see the supported data and how to log it.
|
||||
</Layout.Stack>
|
||||
</p>
|
||||
{:else}
|
||||
<Typography.Code>No headers found.</Typography.Code>
|
||||
{/if}
|
||||
{:else if requestTab === 'body'}
|
||||
<Typography.Code>No body found.</Typography.Code>
|
||||
{/if}
|
||||
</Layout.Stack>
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
<script lang="ts">
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
import { IconInfo } from '@appwrite.io/pink-icons-svelte';
|
||||
import { Badge, Icon, Layout, Table, Tabs, Typography } from '@appwrite.io/pink-svelte';
|
||||
|
||||
export let selectedLog: Models.Execution;
|
||||
|
||||
let responseTab: 'logs' | 'errors' | 'headers' | 'body' = 'logs';
|
||||
</script>
|
||||
|
||||
<Layout.Stack>
|
||||
<Tabs.Root variant="secondary">
|
||||
<Tabs.Item.Button active={responseTab === 'logs'} on:click={() => (responseTab = 'logs')}>
|
||||
Logs
|
||||
</Tabs.Item.Button>
|
||||
<Tabs.Item.Button
|
||||
active={responseTab === 'errors'}
|
||||
on:click={() => (responseTab = 'errors')}>
|
||||
Errors
|
||||
</Tabs.Item.Button>
|
||||
<Tabs.Item.Button
|
||||
active={responseTab === 'headers'}
|
||||
on:click={() => (responseTab = 'headers')}>
|
||||
Headers <Badge
|
||||
variant="secondary"
|
||||
size="s"
|
||||
content={selectedLog?.responseHeaders?.length?.toString()} />
|
||||
</Tabs.Item.Button>
|
||||
<Tabs.Item.Button active={responseTab === 'body'} on:click={() => (responseTab = 'body')}>
|
||||
Body
|
||||
</Tabs.Item.Button>
|
||||
</Tabs.Root>
|
||||
{#if responseTab === 'logs'}
|
||||
{#if selectedLog.logs}
|
||||
{selectedLog.logs}
|
||||
{:else}
|
||||
<Typography.Code>No logs found.</Typography.Code>
|
||||
{/if}
|
||||
{:else if responseTab === 'errors'}
|
||||
{#if selectedLog.errors}
|
||||
{selectedLog.errors}
|
||||
{:else}
|
||||
<Typography.Code>No errors found.</Typography.Code>
|
||||
{/if}
|
||||
{:else if responseTab === 'headers'}
|
||||
{#if selectedLog.responseHeaders?.length}
|
||||
<Table.Root>
|
||||
<svelte:fragment slot="header">
|
||||
<Table.Header.Cell>Key</Table.Header.Cell>
|
||||
<Table.Header.Cell>Value</Table.Header.Cell>
|
||||
</svelte:fragment>
|
||||
{#each selectedLog.responseHeaders as request}
|
||||
<Table.Row>
|
||||
<Table.Cell>{request.name}</Table.Cell>
|
||||
<Table.Cell>{request.value}</Table.Cell>
|
||||
</Table.Row>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
<p>
|
||||
<Layout.Stack direction="row" gap="xs" alignItems="center">
|
||||
<Icon icon={IconInfo} size="s" color="--color-fgcolor-neutral-secondary" /> Missing
|
||||
headers? Check our docs to see the supported data and how to log it.
|
||||
</Layout.Stack>
|
||||
</p>
|
||||
{:else}
|
||||
<Typography.Code>No headers found.</Typography.Code>
|
||||
{/if}
|
||||
{:else if responseTab === 'body'}
|
||||
{#if selectedLog.responseBody}
|
||||
{selectedLog.responseBody}
|
||||
{:else}
|
||||
<Typography.Code>No parameters found.</Typography.Code>
|
||||
{/if}
|
||||
{/if}
|
||||
</Layout.Stack>
|
||||
@@ -107,10 +107,10 @@
|
||||
</div>
|
||||
{/if} -->
|
||||
{#if data?.logs?.total}
|
||||
<Table columns={$columns} executions={data.logs} />
|
||||
<Table columns={$columns} logs={data.logs} />
|
||||
|
||||
<PaginationWithLimit
|
||||
name="Executions"
|
||||
name="Logs"
|
||||
limit={data.limit}
|
||||
offset={data.offset}
|
||||
total={data.logs.total} />
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
<script lang="ts">
|
||||
import Button from '$lib/elements/forms/button.svelte';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
import { IconChevronDown, IconChevronUp } from '@appwrite.io/pink-icons-svelte';
|
||||
import { calculateTime } from '$lib/helpers/timeConversion';
|
||||
import {
|
||||
Accordion,
|
||||
Badge,
|
||||
Icon,
|
||||
Layout,
|
||||
Sheet,
|
||||
Tag,
|
||||
Typography
|
||||
} from '@appwrite.io/pink-svelte';
|
||||
import { timeFromNow } from '$lib/helpers/date';
|
||||
import LogsRequest from './(components)/LogsRequest.svelte';
|
||||
import LogsResponse from './(components)/LogsResponse.svelte';
|
||||
|
||||
export let open = false;
|
||||
export let selectedLogId: string;
|
||||
export let logs: Models.Execution[];
|
||||
|
||||
function nextLog() {
|
||||
const currentIndex = logs.findIndex((log) => log.$id === selectedLogId);
|
||||
if (currentIndex < logs.length - 1) {
|
||||
selectedLogId = logs[currentIndex + 1].$id;
|
||||
}
|
||||
}
|
||||
function previousLog() {
|
||||
const currentIndex = logs.findIndex((log) => log.$id === selectedLogId);
|
||||
if (currentIndex > 0) {
|
||||
selectedLogId = logs[currentIndex - 1].$id;
|
||||
}
|
||||
}
|
||||
$: if (!open) {
|
||||
selectedLogId = null;
|
||||
}
|
||||
|
||||
$: 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;
|
||||
$: console.log(selectedLog);
|
||||
</script>
|
||||
|
||||
<Sheet bind:open>
|
||||
<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>
|
||||
<Tag size="s">{selectedLog?.$id}</Tag>
|
||||
</Layout.Stack>
|
||||
<Layout.Stack direction="row" gap="s" alignItems="center" inline>
|
||||
<Button icon text size="s" on:click={previousLog} disabled={isFirstLog}>
|
||||
<Icon icon={IconChevronUp}></Icon>
|
||||
</Button>
|
||||
<Button icon text size="s" on:click={nextLog} disabled={isLastLog}>
|
||||
<Icon icon={IconChevronDown}></Icon>
|
||||
</Button>
|
||||
</Layout.Stack>
|
||||
</Layout.Stack>
|
||||
</div>
|
||||
{#if selectedLog}
|
||||
<Layout.Stack gap="xl">
|
||||
<Accordion title="Details" open>
|
||||
<Layout.Stack gap="xl">
|
||||
<Layout.Stack direction="row" gap="xxl">
|
||||
<Layout.Stack gap="xs" inline>
|
||||
<Typography.Text
|
||||
variant="m-400"
|
||||
color="--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="--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="--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="--color-fgcolor-neutral-tertiary">
|
||||
Created
|
||||
</Typography.Text>
|
||||
<Typography.Text variant="m-400">
|
||||
{timeFromNow(selectedLog.$createdAt)}
|
||||
</Typography.Text>
|
||||
</Layout.Stack>
|
||||
</Layout.Stack>
|
||||
<Layout.Stack gap="xs" inline>
|
||||
<Typography.Text variant="m-400" color="--color-fgcolor-neutral-tertiary">
|
||||
Path
|
||||
</Typography.Text>
|
||||
<Typography.Text variant="m-400">
|
||||
{selectedLog.requestPath}
|
||||
</Typography.Text>
|
||||
</Layout.Stack>
|
||||
</Layout.Stack>
|
||||
</Accordion>
|
||||
<Accordion title="Request" open>
|
||||
<LogsRequest {selectedLog} />
|
||||
</Accordion>
|
||||
<Accordion title="Response" open>
|
||||
<LogsResponse {selectedLog} />
|
||||
</Accordion>
|
||||
</Layout.Stack>
|
||||
{/if}
|
||||
</Sheet>
|
||||
@@ -1,13 +1,16 @@
|
||||
<script lang="ts">
|
||||
import { Id } from '$lib/components';
|
||||
import { TableRow } from '$lib/elements/table';
|
||||
import { timeFromNow } from '$lib/helpers/date';
|
||||
import type { Column } from '$lib/helpers/types';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
import { Badge, InlineCode, Layout, Table } from '@appwrite.io/pink-svelte';
|
||||
import Sheet from './sheet.svelte';
|
||||
|
||||
export let columns: Column[];
|
||||
export let executions: Models.ExecutionList;
|
||||
export let logs: Models.ExecutionList;
|
||||
|
||||
let openSheet = false;
|
||||
let selectedLogId: string = null;
|
||||
</script>
|
||||
|
||||
<Table.Root>
|
||||
@@ -18,38 +21,44 @@
|
||||
{/if}
|
||||
{/each}
|
||||
</svelte:fragment>
|
||||
{#each executions.executions as execution}
|
||||
<TableRow>
|
||||
{#each logs.executions as log}
|
||||
<Table.Button
|
||||
on:click={() => {
|
||||
openSheet = true;
|
||||
selectedLogId = log.$id;
|
||||
}}>
|
||||
{#each columns as column}
|
||||
{#if column.show}
|
||||
{#if column.id === '$id'}
|
||||
{#key column.id}
|
||||
<Table.Cell>
|
||||
<Id value={execution.$id}>{execution.$id}</Id>
|
||||
<Id value={log.$id}>{log.$id}</Id>
|
||||
</Table.Cell>
|
||||
{/key}
|
||||
{:else if column.id === '$createdAt'}
|
||||
<Table.Cell>
|
||||
{timeFromNow(execution.$createdAt)}
|
||||
{timeFromNow(log.$createdAt)}
|
||||
</Table.Cell>
|
||||
{:else if column.id === 'responseStatusCode'}
|
||||
<Table.Cell>
|
||||
{execution.responseStatusCode}
|
||||
{log.responseStatusCode}
|
||||
</Table.Cell>
|
||||
{:else if column.id === 'requestPath'}
|
||||
<Table.Cell>
|
||||
<Layout.Stack direction="row" alignItems="center" gap="s">
|
||||
<Badge
|
||||
variant="secondary"
|
||||
type={execution.responseStatusCode >= 400 ? 'error' : 'success'}
|
||||
content={execution.responseStatusCode.toString()} />
|
||||
<InlineCode code={execution.requestMethod} />
|
||||
<InlineCode code={execution.requestPath} />
|
||||
type={log.responseStatusCode >= 400 ? 'error' : 'success'}
|
||||
content={log.responseStatusCode.toString()} />
|
||||
<InlineCode code={log.requestMethod} />
|
||||
<InlineCode code={log.requestPath} />
|
||||
</Layout.Stack>
|
||||
</Table.Cell>
|
||||
{/if}
|
||||
{/if}
|
||||
{/each}
|
||||
</TableRow>
|
||||
</Table.Button>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
|
||||
<Sheet bind:open={openSheet} bind:selectedLogId logs={logs.executions} />
|
||||
|
||||
@@ -9,6 +9,11 @@ export const consoleVariables = derived(
|
||||
page,
|
||||
($page) => $page.data.consoleVariables as Models.ConsoleVariables
|
||||
);
|
||||
export const protocol = derived(page, ($page) =>
|
||||
($page.data.consoleVariables as Models.ConsoleVariables)?._APP_OPTIONS_FORCE_HTTPS
|
||||
? 'https://'
|
||||
: 'http://'
|
||||
);
|
||||
|
||||
export const activeHeaderAlert = writable<HeaderAlert>(null);
|
||||
export const orgMissingPaymentMethod = writable<Organization>(null);
|
||||
|
||||
Reference in New Issue
Block a user