mirror of
https://github.com/appwrite/console.git
synced 2026-06-06 19:27:48 +00:00
feat: combo-box on relationship searching.
This commit is contained in:
+2
-2
@@ -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",
|
||||
|
||||
Generated
+10
-10
@@ -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
|
||||
|
||||
+64
-3
@@ -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<Models.Row>;
|
||||
|
||||
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();
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if isRelationshipToMany(column)}
|
||||
@@ -298,13 +358,14 @@
|
||||
<!-- Input for adding new items -->
|
||||
{#if showInput}
|
||||
<Layout.Stack direction="row">
|
||||
<InputSelect
|
||||
<Input.ComboBox
|
||||
{id}
|
||||
required
|
||||
placeholder={`Select ${column.key}`}
|
||||
bind:value={newItemValue}
|
||||
options={getAvailableOptions()}
|
||||
on:change={addNewItem}
|
||||
noResultsOption={searchNoResultsOption}
|
||||
leadingIcon={!limited ? IconRelationship : undefined} />
|
||||
|
||||
<div style:padding-block-start="0.5rem">
|
||||
|
||||
Reference in New Issue
Block a user