Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions src/lib/helpers/clearSearch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/**
* Creates a clear search function for SearchQuery components
* @param searchQuery
* @returns A function that clears the search input
*/
export function createClearSearch(searchQuery: { clearInput?: () => void } | undefined) {
return () => {
searchQuery?.clearInput?.();
};
}

/**
* @param searchQuery
*/
export function clearSearchInput(searchQuery: { clearInput?: () => void } | undefined) {
searchQuery?.clearInput?.();
}
13 changes: 10 additions & 3 deletions src/lib/layout/responsiveContainerHeader.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
searchPlaceholder = 'Search by ID',
hasFilters = false,
analyticsSource = '',
children
children,
searchQuery = $bindable()
}: {
columns?: Writable<Column[]>;
view?: View;
Expand All @@ -35,8 +36,14 @@
hasFilters?: boolean;
analyticsSource?: string;
children?: Snippet;
searchQuery?: SearchQuery;
} = $props();
// Ensure searchQuery is considered used by TypeScript
$effect(() => {
searchQuery;
});
let hasDisplaySettings = $derived(!hideView || (!hideColumns && $columns?.length));
let numberOfOptions = $derived(
[hasSearch, hasFilters && $columns?.length, hasDisplaySettings].filter(Boolean).length
Expand Down Expand Up @@ -97,14 +104,14 @@
{/if}

{#if showSearch && hasSearch}
<SearchQuery placeholder={searchPlaceholder} />
<SearchQuery bind:this={searchQuery} placeholder={searchPlaceholder} />
Copy link
Member

@ItzNotABug ItzNotABug Sep 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should avoid this pattern. we have many search inputs and creating a binding instance is not the best DX. we should be somehow able to listen to the changes for clear button and clear queries. We already also have below for queries -

queries.clearAll();

not sure if it supports search as well.

{/if}
</Layout.Stack>
{:else}
<Layout.Stack direction="row" justifyContent="space-between">
<Layout.Stack direction="row" alignItems="center">
{#if hasSearch}
<SearchQuery placeholder={searchPlaceholder} />
<SearchQuery bind:this={searchQuery} placeholder={searchPlaceholder} />
{/if}
{#if hasFilters && $columns?.length}
<QuickFilters {columns} {analyticsSource} {filterCols} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import { base } from '$app/paths';
import { page } from '$app/state';
import { EmptySearch, PaginationWithLimit, ViewSelector } from '$lib/components/index.js';
import { clearSearchInput } from '$lib/helpers/clearSearch';
import { Button } from '$lib/elements/forms';
import Link from '$lib/elements/link.svelte';
import { toLocaleDateTime } from '$lib/helpers/date';
Expand Down Expand Up @@ -39,6 +40,8 @@
let showDelete = false;
let showRetry = false;
let selectedDomain: Models.Domain = null;
let searchQuery;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here, for type.

const clearSearch = () => clearSearchInput(searchQuery);
const isDomainVerified = (domain: Models.Domain) => {
return domain.nameservers.toLowerCase() === 'appwrite';
Expand All @@ -47,7 +50,7 @@

<Container>
<Layout.Stack direction="row" justifyContent="space-between">
<SearchQuery placeholder="Search domains" />
<SearchQuery bind:this={searchQuery} placeholder="Search domains" />
<Layout.Stack direction="row" gap="m" inline>
<ViewSelector ui="new" view={View.Table} {columns} hideView />
<Button
Expand Down Expand Up @@ -183,6 +186,7 @@
queries.clearAll();
queries.apply();
}}>Clear filters</Button>
<Button secondary on:click={clearSearch}>Clear search</Button>
</svelte:fragment>
</EmptySearch>
{:else}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@
Tooltip
} from '@appwrite.io/pink-svelte';
import SearchQuery from '$lib/components/searchQuery.svelte';
import { base } from '$app/paths';
import { page } from '$app/state';
import CertificateInfoModal from './certificateInfoModal.svelte';
import DeleteCertificateModal from './deleteCertificateModal.svelte';
Expand All @@ -26,13 +24,18 @@
let showDelete = false;
let showAdvancedInfo = false;
let selectedCertificate = null; //TODO: add type
let searchQuery;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

whats the type?

function clearSearch() {
searchQuery?.clearInput();
}
const now = new Date();
</script>

<Container>
<Layout.Stack direction="row" justifyContent="space-between">
<SearchQuery placeholder="Search by ID" />
<SearchQuery bind:this={searchQuery} placeholder="Search by ID" />
</Layout.Stack>

{#if data.certificates.total}
Expand Down Expand Up @@ -138,13 +141,9 @@
offset={data.offset}
total={data.certificates.total} />
{:else if data?.search}
<EmptySearch hidePages bind:search={data.search} target="certificates">
<EmptySearch hidePages search={data.search} target="certificates">
<svelte:fragment slot="actions">
<Button
secondary
href={`${base}/organization-${page.params.organization}/domains/domain-${page.params.domain}/certificates`}>
Clear search
</Button>
<Button secondary on:click={clearSearch}>Clear search</Button>
</svelte:fragment>
</EmptySearch>
{:else}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
PaginationWithLimit,
SearchQuery
} from '$lib/components';
import { clearSearchInput } from '$lib/helpers/clearSearch';
import { Button } from '$lib/elements/forms';
import { toLocaleDate, toLocaleDateTime } from '$lib/helpers/date';
import { Container } from '$lib/layout';
Expand Down Expand Up @@ -43,6 +44,9 @@

export let data;

let searchQuery;
const clearSearch = () => clearSearchInput(searchQuery);

const columns = writable<Column[]>([
{ id: '$id', title: 'User ID', type: 'string', width: 200 },
{ id: 'name', title: 'Name', type: 'string', width: { min: 260 } },
Expand Down Expand Up @@ -104,7 +108,9 @@
<Container>
<Layout.Stack direction="row" justifyContent="space-between">
<Layout.Stack direction="row" alignItems="center">
<SearchQuery placeholder="Search by name, email, phone, or ID" />
<SearchQuery
bind:this={searchQuery}
placeholder="Search by name, email, phone, or ID" />
</Layout.Stack>
<Layout.Stack direction="row" alignItems="center" justifyContent="flex-end">
<ViewSelector ui="new" view={View.Table} {columns} hideView />
Expand Down Expand Up @@ -215,10 +221,7 @@
total={data.users.total} />
{:else if data.search}
<EmptySearch target="users" hidePagination>
<Button
href={`${base}/project-${page.params.region}-${page.params.project}/auth`}
size="s"
secondary>Clear Search</Button>
<Button on:click={clearSearch} size="s" secondary>Clear Search</Button>
</EmptySearch>
{:else}
<Empty
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
SearchQuery,
PaginationWithLimit
} from '$lib/components';
import { clearSearchInput } from '$lib/helpers/clearSearch';
import Create from '../createTeam.svelte';
import { goto } from '$app/navigation';
import { Container } from '$lib/layout';
Expand Down Expand Up @@ -40,6 +41,8 @@

const region = page.params.region;
const project = page.params.project;
let searchQuery;
const clearSearch = () => clearSearchInput(searchQuery);

let selectedTeams: string[] = [];
let showDelete = false;
Expand Down Expand Up @@ -90,7 +93,7 @@
<Container>
<Layout.Stack direction="row" justifyContent="space-between">
<Layout.Stack direction="row" alignItems="center">
<SearchQuery placeholder="Search by name" />
<SearchQuery bind:this={searchQuery} placeholder="Search by name" />
</Layout.Stack>
<Layout.Stack direction="row" alignItems="center" justifyContent="flex-end">
<Button on:mousedown={() => ($showCreateTeam = true)} event="create_user" size="s">
Expand Down Expand Up @@ -157,9 +160,7 @@
total={data.teams.total} />
{:else if data.search}
<EmptySearch target="teams" search={data.search} hidePagination={data.teams.total === 0}>
<Button secondary size="s" href={`${base}/project-${region}-${project}/auth/teams`}>
Clear Search
</Button>
<Button secondary size="s" on:click={clearSearch}>Clear Search</Button>
</EmptySearch>
{:else}
<Empty
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,14 @@
import { Icon } from '@appwrite.io/pink-svelte';
import { IconPlus } from '@appwrite.io/pink-icons-svelte';
import EmptySearch from '$lib/components/emptySearch.svelte';
import { clearSearchInput } from '$lib/helpers/clearSearch';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Good: Centralized clear helper

Importing clearSearchInput is the right approach for consistent behavior.

Run the following to confirm the helper clears even when the instance is undefined (e.g., updates URL/search params):


🏁 Script executed:

#!/bin/bash
# Inspect helper implementation for fallback behavior
echo "== helper source =="
sed -n '1,200p' src/lib/helpers/clearSearch.ts || true
echo
echo "== look for fallbacks =="
rg -n -C2 -g 'src/lib/helpers/clearSearch.ts' -e 'goto|URLSearchParams|setSearchParams|history|location|clearInput'

Length of output: 1265


Add fallback in clearSearchInput for undefined searchQuery
clearSearchInput currently only calls searchQuery.clearInput; if searchQuery is undefined it no-ops and doesn’t clear URL/search params—add logic to reset search params (e.g. via URLSearchParams or SvelteKit’s goto).

🤖 Prompt for AI Agents
In src/routes/(console)/project-[region]-[project]/databases/+page.svelte around
line 20, the import of clearSearchInput needs its implementation to handle
undefined searchQuery: update clearSearchInput so that if searchQuery is
undefined it still clears the search state by removing the relevant query
param(s) from the current URL (using URLSearchParams and history.replaceState or
SvelteKit's goto with replaceState) and also reset any input value in the DOM if
present; otherwise keep the existing call to searchQuery.clearInput when
searchQuery exists. Ensure the fallback does not trigger a full page reload (use
replace navigation) and preserves other query params.

export let data: PageData;
let showCreate = false;
const project = page.params.project;
let searchQuery: { clearInput: () => void } | undefined;
const clearSearch = () => clearSearchInput(searchQuery);
async function handleCreate(event: CustomEvent<Models.Database>) {
showCreate = false;
Expand Down Expand Up @@ -50,7 +53,8 @@
hasSearch
{columns}
bind:view={data.view}
searchPlaceholder="Search by name or ID">
searchPlaceholder="Search by name or ID"
bind:searchQuery>
{#if $canWriteDatabases}
<Button event="create_database" on:click={() => (showCreate = true)}>
<Icon icon={IconPlus} slot="start" size="s" />
Expand All @@ -73,10 +77,7 @@
total={data.databases.total} />
{:else if data.search}
<EmptySearch target="databases" hidePagination>
<Button
href={`${base}/project-${page.params.region}-${page.params.project}/databases`}
size="s"
secondary>Clear Search</Button>
<Button on:click={clearSearch} size="s" secondary>Clear Search</Button>
</EmptySearch>
{:else}
<Empty
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<script lang="ts">
import { EmptySearch, PaginationWithLimit, SearchQuery, ViewSelector } from '$lib/components';
import { clearSearchInput } from '$lib/helpers/clearSearch';
import { Button } from '$lib/elements/forms';
import { Container } from '$lib/layout';
import { showCreateTable, tableViewColumns } from './store';
Expand All @@ -11,17 +12,17 @@
import { app } from '$lib/stores/app';
import { canWriteTables } from '$lib/stores/roles';
import { IconPlus } from '@appwrite.io/pink-icons-svelte';
import { page } from '$app/state';

export let data: PageData;

const databaseId = page.params.database;
let searchQuery;
const clearSearch = () => clearSearchInput(searchQuery);
</script>

<Container databasesMainScreen>
<Layout.Stack direction="row" justifyContent="space-between">
<Layout.Stack direction="row" alignItems="center">
<SearchQuery placeholder="Search by name or ID" />
<SearchQuery bind:this={searchQuery} placeholder="Search by name or ID" />
</Layout.Stack>

<Layout.Stack direction="row" alignItems="center" justifyContent="flex-end">
Expand Down Expand Up @@ -55,11 +56,7 @@
total={data.tables.total} />
{:else if data.search}
<EmptySearch target="tables" hidePagination>
<Button
size="s"
secondary
href={`${base}/project-${page.params.region}-${page.params.project}/databases/database-${databaseId}`}
>Clear Search</Button>
<Button size="s" secondary on:click={clearSearch}>Clear Search</Button>
</EmptySearch>
{:else}
<Card.Base padding="none">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@
export let data;

let offset = 0;
let searchQuery;

function clearSearch() {
searchQuery?.clearInput();
}

const project = page.params.project;

Expand Down Expand Up @@ -80,7 +85,7 @@

<Container>
<Layout.Stack direction="row" justifyContent="space-between">
<SearchQuery placeholder="Search by name or ID" />
<SearchQuery bind:this={searchQuery} placeholder="Search by name or ID" />

<Button href={`${base}/project-${page.params.region}-${project}/functions/create-function`}>
<Icon icon={IconPlus} slot="start" />
Expand Down Expand Up @@ -133,11 +138,7 @@
total={data.functions.total} />
{:else if data?.search}
<EmptySearch hidePages bind:search={data.search} target="functions">
<Button
secondary
href={`${base}/project-${page.params.region}-${page.params.project}/functions`}>
Clear search
</Button>
<Button secondary on:click={clearSearch}>Clear search</Button>
</EmptySearch>
{:else}
<Empty
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,24 @@
import SearchQuery from '$lib/components/searchQuery.svelte';
import { app } from '$lib/stores/app';
import { Click, trackEvent } from '$lib/actions/analytics';
import { clearSearchInput } from '$lib/helpers/clearSearch';
import Table from './table.svelte';

let { data } = $props();

let showDelete = $state(false);
let showRetry = $state(false);
let selectedProxyRule: Models.ProxyRule = null;
let searchQuery: { clearInput?: () => void } | undefined;

function clearSearch() {
clearSearchInput(searchQuery);
}
</script>

<Container>
<Layout.Stack direction="row" justifyContent="space-between">
<SearchQuery placeholder="Search domain" />
<SearchQuery bind:this={searchQuery} placeholder="Search domain" />
<Button
href={`${base}/project-${page.params.region}-${page.params.project}/functions/function-${page.params.function}/domains/add-domain`}
on:click={() => {
Expand All @@ -44,14 +50,8 @@
offset={data.offset}
total={data.proxyRules.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>
<EmptySearch hidePages search={data.search} target="domains" hidePagination>
<Button secondary on:click={clearSearch}>Clear search</Button>
</EmptySearch>
{:else}
<Card.Base padding="none">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
export let data;

let offset = 0;
let searchQuery;

function applyFilter(filter: string, value: string, event: CustomEvent) {
const target = new URL(page.url);
Expand All @@ -54,6 +55,7 @@
}

function clearSearch() {
searchQuery?.clearInput();
const target = new URL(page.url);
target.search = '';
goto(target.toString(), {
Expand Down Expand Up @@ -89,7 +91,7 @@
<Container>
<Layout.GridFraction start={1} end={3} gap="xxl">
<Layout.Stack gap="xl">
<SearchQuery placeholder="Search template" />
<SearchQuery bind:this={searchQuery} placeholder="Search template" />
<Layout.Stack>
<Accordion title="Use case">
<Layout.Stack>
Expand Down
Loading