Skip to content

Commit ca23b1f

Browse files
committed
feat: executions logs
1 parent 40a3386 commit ca23b1f

File tree

15 files changed

+652
-357
lines changed

15 files changed

+652
-357
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<script lang="ts">
2+
import { ActionMenu } from '@appwrite.io/pink-svelte';
3+
import FiltersModal from './filtersModal.svelte';
4+
import type { Writable } from 'svelte/store';
5+
import type { Column } from '$lib/helpers/types';
6+
7+
export let columns: Writable<Column[]>;
8+
let show = false;
9+
</script>
10+
11+
<ActionMenu.Root>
12+
<ActionMenu.Item.Button on:click={() => (show = true)}>Custom filters</ActionMenu.Item.Button>
13+
</ActionMenu.Root>
14+
15+
{#if show}
16+
<FiltersModal bind:show {columns} analyticsSource="custom-filters" />
17+
{/if}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<script lang="ts">
2+
import { Submit, trackEvent } from '$lib/actions/analytics';
3+
import { Button } from '$lib/elements/forms';
4+
import type { Writable } from 'svelte/store';
5+
import Modal from '../modal.svelte';
6+
import Content from './content.svelte';
7+
import { addFilter, queries, queriesAreDirty, tags, ValidOperators } from './store';
8+
import type { Column } from '$lib/helpers/types';
9+
10+
export let show = false;
11+
export let columns: Writable<Column[]>;
12+
export let analyticsSource = '';
13+
export let clearOnClick = false;
14+
/* eslint @typescript-eslint/no-explicit-any: 'off' */
15+
let value: any = null;
16+
let selectedColumn: string | null = null;
17+
let operatorKey: string | null = null;
18+
let arrayValues: string[] = [];
19+
20+
let applied = $tags.length;
21+
22+
function clearAll() {
23+
selectedColumn = null;
24+
queries.clearAll();
25+
if (clearOnClick) {
26+
trackEvent(Submit.FilterClear, { source: analyticsSource });
27+
queries.apply();
28+
}
29+
}
30+
31+
function apply() {
32+
if (
33+
selectedColumn &&
34+
operatorKey &&
35+
(operatorKey === ValidOperators.IsNotNull ||
36+
operatorKey === ValidOperators.IsNull ||
37+
value ||
38+
arrayValues.length)
39+
) {
40+
addFilter($columns, selectedColumn, operatorKey, value, arrayValues);
41+
selectedColumn = null;
42+
value = null;
43+
operatorKey = null;
44+
arrayValues = [];
45+
}
46+
queries.apply();
47+
}
48+
49+
$: isButtonDisabled = $queriesAreDirty
50+
? false
51+
: !selectedColumn ||
52+
!operatorKey ||
53+
(!value &&
54+
!arrayValues.length &&
55+
operatorKey !== ValidOperators.IsNotNull &&
56+
operatorKey !== ValidOperators.IsNull);
57+
</script>
58+
59+
<Modal title="Filters" bind:show>
60+
<span slot="description"> Apply filter rules to refine the table view </span>
61+
62+
<Content
63+
{columns}
64+
bind:columnId={selectedColumn}
65+
bind:operatorKey
66+
bind:value
67+
bind:arrayValues
68+
on:clear={() => (applied = 0)} />
69+
<svelte:fragment slot="footer">
70+
<Button size="s" text on:click={clearAll}>Clear all</Button>
71+
<Button size="s" on:click={apply} disabled={isButtonDisabled}>Apply</Button>
72+
</svelte:fragment>
73+
</Modal>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
export { default as Filters } from './filters.svelte';
22
export { default as TagList } from './tagList.svelte';
3+
export { default as FilterMenu } from './menu.svelte';
4+
export { default as FilterSubMenu } from './subMenu.svelte';
5+
export { default as CustomFilters } from './customFilters.svelte';
36
export { hasPageQueries, queryParamToMap, queries } from '$lib/components/filters/store';
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<script lang="ts">
2+
import { Button } from '$lib/elements/forms';
3+
import { Card, Divider, Icon } from '@appwrite.io/pink-svelte';
4+
import { tags } from './store';
5+
import { IconFilterLine } from '@appwrite.io/pink-icons-svelte';
6+
import { createMenubar, melt } from '@melt-ui/svelte';
7+
8+
const {
9+
elements: { menubar },
10+
builders: { createMenu }
11+
} = createMenubar();
12+
13+
const {
14+
elements: { trigger: trigger, menu: menu, separator: separator }
15+
} = createMenu();
16+
</script>
17+
18+
<div use:melt={$menubar}>
19+
<div use:melt={$trigger}>
20+
{#if $tags.length}
21+
<Button secondary badge={`${$tags.length}`}>
22+
<Icon icon={IconFilterLine} slot="start" size="s" />
23+
Filters
24+
</Button>
25+
{:else}
26+
<Button secondary>
27+
<Icon icon={IconFilterLine} slot="start" size="s" />
28+
Filters
29+
</Button>
30+
{/if}
31+
</div>
32+
33+
<div class="menu" use:melt={$menu}>
34+
<Card.Base padding="xxxs">
35+
<slot />
36+
<div use:melt={$separator}>
37+
<Divider />
38+
</div>
39+
<slot name="end" />
40+
</Card.Base>
41+
</div>
42+
</div>
43+
44+
<style>
45+
.menu {
46+
min-width: 244px;
47+
z-index: 20;
48+
}
49+
</style>

src/routes/(console)/project-[project]/functions/function-[function]/+page.svelte

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -183,31 +183,6 @@
183183
<Layout.Stack direction="row" gap="s" wrap="wrap">
184184
{#if data.deploymentList.total}
185185
<QuickFilters {columns} />
186-
<Filters
187-
query={data.query}
188-
{columns}
189-
let:disabled
190-
let:toggle
191-
singleCondition
192-
analyticsSource="function_filters">
193-
<div class="u-flex u-gap-4">
194-
<Button
195-
text
196-
on:click={toggle}
197-
{disabled}
198-
ariaLabel="open filter"
199-
compact={!$tags?.length}>
200-
<Icon icon={IconFilterLine} size="s" slot="start" />
201-
<span class="text">More filters</span>
202-
</Button>
203-
{#if $tags?.length}
204-
<div
205-
style="flex-basis:1px; background-color:hsl(var(--border)); width: 1px">
206-
</div>
207-
<Button text on:click={clearAll}>Clear all</Button>
208-
{/if}
209-
</div>
210-
</Filters>
211186
{/if}
212187
</Layout.Stack>
213188
<Layout.Stack direction="row" gap="s" inline>
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
<script lang="ts">
2+
import { Card } from '$lib/components';
3+
import { Link } from '$lib/elements';
4+
import type { Models } from '@appwrite.io/console';
5+
import {
6+
Badge,
7+
Divider,
8+
Input,
9+
Layout,
10+
Table,
11+
Tabs,
12+
Typography
13+
} from '@appwrite.io/pink-svelte';
14+
import { onMount } from 'svelte';
15+
16+
export let selectedLog: Models.Execution;
17+
18+
let requestTab: 'parameters' | 'headers' = 'parameters';
19+
20+
let parameters = [];
21+
22+
onMount(() => {
23+
try {
24+
// Add dummy base URL to parse relative paths
25+
const url = new URL(selectedLog.requestPath, 'http://dummy.local');
26+
if (url.search) {
27+
parameters = Array.from(url.searchParams.entries()).map(([name, value]) => ({
28+
name,
29+
value: decodeURIComponent(value)
30+
}));
31+
}
32+
} catch (error) {
33+
parameters = [];
34+
}
35+
});
36+
37+
onMount(() => {
38+
if (parameters?.length) {
39+
requestTab = 'parameters';
40+
} else if (selectedLog.requestHeaders?.length) {
41+
requestTab = 'headers';
42+
}
43+
});
44+
</script>
45+
46+
<Layout.Stack>
47+
<Layout.Stack gap="none">
48+
<Tabs.Root variant="secondary" let:root>
49+
<Tabs.Item.Button
50+
{root}
51+
active={requestTab === 'parameters'}
52+
on:click={() => (requestTab = 'parameters')}>
53+
Parameters
54+
<Badge variant="secondary" size="s" content={parameters?.length?.toString()} />
55+
</Tabs.Item.Button>
56+
<Tabs.Item.Button
57+
{root}
58+
active={requestTab === 'headers'}
59+
on:click={() => (requestTab = 'headers')}>
60+
Headers <Badge
61+
variant="secondary"
62+
size="s"
63+
content={selectedLog?.requestHeaders?.length?.toString()} />
64+
</Tabs.Item.Button>
65+
</Tabs.Root>
66+
<Divider />
67+
</Layout.Stack>
68+
{#if requestTab === 'parameters'}
69+
{#if parameters?.length}
70+
<Table.Root>
71+
<svelte:fragment slot="header">
72+
<Table.Header.Cell>Key</Table.Header.Cell>
73+
<Table.Header.Cell>Value</Table.Header.Cell>
74+
</svelte:fragment>
75+
{#each parameters as parameter}
76+
<Table.Row>
77+
<Table.Cell>{parameter.name}</Table.Cell>
78+
<Table.Cell>{parameter.value}</Table.Cell>
79+
</Table.Row>
80+
{/each}
81+
</Table.Root>
82+
{:else}
83+
<Card isTile padding="xs" radius="s">
84+
<Typography.Code>No parameters found.</Typography.Code>
85+
</Card>
86+
{/if}
87+
{:else if requestTab === 'headers'}
88+
{#if selectedLog.requestHeaders?.length}
89+
<Table.Root>
90+
<svelte:fragment slot="header">
91+
<Table.Header.Cell>Key</Table.Header.Cell>
92+
<Table.Header.Cell>Value</Table.Header.Cell>
93+
</svelte:fragment>
94+
{#each selectedLog.requestHeaders as request}
95+
<Table.Row>
96+
<Table.Cell>{request.name}</Table.Cell>
97+
<Table.Cell>{request.value}</Table.Cell>
98+
</Table.Row>
99+
{/each}
100+
</Table.Root>
101+
102+
<Input.Helper state="default">
103+
<span>
104+
Missing headers? Check the <Link variant="muted" href="#" external>docs</Link> to
105+
see the supported data and how to log it.
106+
</span>
107+
</Input.Helper>
108+
{:else}
109+
<Card isTile padding="xs" radius="s">
110+
<Typography.Code>No headers found.</Typography.Code>
111+
</Card>
112+
{/if}
113+
{/if}
114+
</Layout.Stack>

0 commit comments

Comments
 (0)