From e518cf749d5b668999bdffc144a3b5910d368cfa Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 11 Sep 2025 20:03:22 +0530 Subject: [PATCH] feat: combo-box on relationship searching. --- package.json | 4 +- pnpm-lock.yaml | 20 +++--- .../rows/columns/types/relationship.svelte | 67 ++++++++++++++++++- 3 files changed, 76 insertions(+), 15 deletions(-) diff --git a/package.json b/package.json index bf15dfbe5..ebc68859c 100644 --- a/package.json +++ b/package.json @@ -24,9 +24,9 @@ "@ai-sdk/svelte": "^1.1.24", "@appwrite.io/console": "https://pkg.pr.new/appwrite-labs/cloud/@appwrite.io/console@6031134", "@appwrite.io/pink-icons": "0.25.0", - "@appwrite.io/pink-icons-svelte": "https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@d8326d0", + "@appwrite.io/pink-icons-svelte": "https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@0fefd92", "@appwrite.io/pink-legacy": "^1.0.3", - "@appwrite.io/pink-svelte": "https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@d8326d0", + "@appwrite.io/pink-svelte": "https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@0fefd92", "@faker-js/faker": "^9.9.0", "@popperjs/core": "^2.11.8", "@sentry/sveltekit": "^8.38.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 088515c16..34a2258a0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -18,14 +18,14 @@ importers: specifier: 0.25.0 version: 0.25.0 '@appwrite.io/pink-icons-svelte': - specifier: https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@d8326d0 - version: https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@d8326d0(svelte@5.25.3) + specifier: https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@0fefd92 + version: https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@0fefd92(svelte@5.25.3) '@appwrite.io/pink-legacy': specifier: ^1.0.3 version: 1.0.3 '@appwrite.io/pink-svelte': - specifier: https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@d8326d0 - version: https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@d8326d0(svelte@5.25.3) + specifier: https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@0fefd92 + version: https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@0fefd92(svelte@5.25.3) '@faker-js/faker': specifier: ^9.9.0 version: 9.9.0 @@ -269,8 +269,8 @@ packages: peerDependencies: svelte: ^4.0.0 - '@appwrite.io/pink-icons-svelte@https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@d8326d0': - resolution: {tarball: https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@d8326d0} + '@appwrite.io/pink-icons-svelte@https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@0fefd92': + resolution: {tarball: https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@0fefd92} version: 2.0.0-RC.1 peerDependencies: svelte: ^4.0.0 @@ -284,8 +284,8 @@ packages: '@appwrite.io/pink-legacy@1.0.3': resolution: {integrity: sha512-GGde5fmPhs+s6/3aFeMPc/kKADG/gTFkYQSy6oBN8pK0y0XNCLrZZgBv+EBbdhwdtqVEWXa0X85Mv9w7jcIlwQ==} - '@appwrite.io/pink-svelte@https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@d8326d0': - resolution: {tarball: https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@d8326d0} + '@appwrite.io/pink-svelte@https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@0fefd92': + resolution: {tarball: https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@0fefd92} version: 2.0.0-RC.2 peerDependencies: svelte: ^4.0.0 @@ -3706,7 +3706,7 @@ snapshots: dependencies: svelte: 5.25.3 - '@appwrite.io/pink-icons-svelte@https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@d8326d0(svelte@5.25.3)': + '@appwrite.io/pink-icons-svelte@https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@0fefd92(svelte@5.25.3)': dependencies: svelte: 5.25.3 @@ -3719,7 +3719,7 @@ snapshots: '@appwrite.io/pink-icons': 1.0.0 the-new-css-reset: 1.11.3 - '@appwrite.io/pink-svelte@https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@d8326d0(svelte@5.25.3)': + '@appwrite.io/pink-svelte@https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@0fefd92(svelte@5.25.3)': dependencies: '@appwrite.io/pink-icons-svelte': 2.0.0-RC.1(svelte@5.25.3) '@floating-ui/dom': 1.6.13 diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/rows/columns/types/relationship.svelte b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/rows/columns/types/relationship.svelte index 47cecb98c..fb829633b 100644 --- a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/rows/columns/types/relationship.svelte +++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/rows/columns/types/relationship.svelte @@ -7,7 +7,8 @@ import { type ComponentType, onMount } from 'svelte'; import { isRelationshipToMany } from '../../store'; import { IconPlus, IconRelationship, IconX } from '@appwrite.io/pink-icons-svelte'; - import { Icon, Layout, Typography } from '@appwrite.io/pink-svelte'; + import { Input, Icon, Layout, Typography } from '@appwrite.io/pink-svelte'; + import { debounce } from '$lib/helpers/debounce'; type SelectOption = { label: string; @@ -42,6 +43,8 @@ let limit = 10; let offset = 0; + let searchNoResultsOption = undefined; + onMount(async () => { if (isRelationshipToMany(column)) { if (Array.isArray(value)) { @@ -80,7 +83,22 @@ return rows; } - function getAvailableOptions(excludeIndex?: number) { + async function searchRows(search: string = null) { + if (!search) return; + + const displayNames = preferences.getDisplayNames(column.relatedTable); + + const queries = []; + displayNames.forEach((name) => queries.push(Query.contains(name, search))); + + return await sdk.forProject(page.params.region, page.params.project).tablesDB.listRows({ + databaseId, + tableId: column.relatedTable, + queries + }); + } + + function getAvailableOptions(excludeIndex?: number): SelectOption[] { return options?.filter((option) => { const otherItems = excludeIndex !== undefined @@ -166,6 +184,44 @@ return baseOptions; } + // original list + let originalListPreSearch: Models.RowList; + + const debouncedSearch = debounce(async () => { + const availableOptions = getAvailableOptions(); + const includesItem = availableOptions + .filter((opt) => { + const label = String(opt.label ?? '').toLowerCase(); + const value = String(opt.value ?? '').toLowerCase(); + return ( + label.includes(newItemValue.toLowerCase()) || + value.includes(newItemValue.toLowerCase()) + ); + }) + .filter(Boolean); + + if (!includesItem.length) { + originalListPreSearch = rowList; + + try { + searchNoResultsOption = { + disabled: true, + message: 'Searching...' + }; + + const searchResults = await searchRows(newItemValue); + if (searchResults) { + rowList = searchResults; + } + } finally { + searchNoResultsOption = undefined; + } + } else { + // reset + rowList = originalListPreSearch; + } + }, 500); + // Reactive statements $: getRows(search).then((res) => (rowList = res)); @@ -193,6 +249,10 @@ $: if (limit && !isRelationshipToMany(column) && limited) { label = undefined; } + + $: if (newItemValue && newItemValue !== '') { + debouncedSearch(); + } {#if isRelationshipToMany(column)} @@ -298,13 +358,14 @@ {#if showInput} -