From bc16dea7b063ba0ee9f39b47fb6058c2e87b687e Mon Sep 17 00:00:00 2001 From: Darshan Date: Mon, 29 Sep 2025 19:49:48 +0530 Subject: [PATCH] update: abstracted indexes for base views. --- src/lib/stores/navigation.ts | 16 +- .../(entity)/helpers/terminology.ts | 1 + .../database-[database]/(entity)/index.ts | 1 + .../(entity)/views/(layouts)/index.ts | 2 + .../(entity)/views/(layouts)/sidesheet.svelte | 174 ++++++++++ .../views/(layouts)/spreadsheet.svelte | 123 +++++++ .../(entity)/views/(layouts)/store.ts | 5 + .../(entity)/views/failedModal.svelte | 34 ++ .../views/indexes/create.svelte} | 148 ++++---- .../views/indexes/delete.svelte} | 56 +-- .../(entity)/views/indexes/index.ts | 2 + .../views/indexes/overview.svelte} | 8 +- .../views}/indexes/select.svelte | 2 + .../(entity)/views/indexes/view.svelte | 308 +++++++++++++++++ .../table-[table]/+layout.svelte | 34 +- .../table-[table]/columns/+page.svelte | 2 +- .../table-[table]/indexes/+page.svelte | 318 +++--------------- .../table-[table]/settings/+page.svelte | 5 +- 18 files changed, 871 insertions(+), 368 deletions(-) create mode 100644 src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/(layouts)/index.ts create mode 100644 src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/(layouts)/sidesheet.svelte create mode 100644 src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/(layouts)/spreadsheet.svelte create mode 100644 src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/(layouts)/store.ts create mode 100644 src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/failedModal.svelte rename src/routes/(console)/project-[region]-[project]/databases/database-[database]/{table-[table]/indexes/createIndex.svelte => (entity)/views/indexes/create.svelte} (60%) rename src/routes/(console)/project-[region]-[project]/databases/database-[database]/{table-[table]/indexes/deleteIndex.svelte => (entity)/views/indexes/delete.svelte} (58%) create mode 100644 src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/indexes/index.ts rename src/routes/(console)/project-[region]-[project]/databases/database-[database]/{table-[table]/indexes/overviewIndex.svelte => (entity)/views/indexes/overview.svelte} (82%) rename src/routes/(console)/project-[region]-[project]/databases/database-[database]/{table-[table] => (entity)/views}/indexes/select.svelte (96%) create mode 100644 src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/indexes/view.svelte diff --git a/src/lib/stores/navigation.ts b/src/lib/stores/navigation.ts index fc598a672..598bcdb85 100644 --- a/src/lib/stores/navigation.ts +++ b/src/lib/stores/navigation.ts @@ -12,13 +12,21 @@ type ResolveArgs = T extends RouteId : [route: T, params: RouteParams] : [route: T]; +export function withPath(base: string, ...parts: string[]) { + return [base.replace(/\/+$/, ''), ...parts].join('/'); +} + +export function resolveRoute(route: T, params?: Record) { + // type cast is necessary here! + const resolveArgs = params ? ([route, params] as [T, RouteParams]) : [route]; + + return resolve(...(resolveArgs as ResolveArgs)); +} + export function navigate( route: T, params?: Record ): Promise { // type cast is necessary here! - const resolveArgs = params ? ([route, params] as [T, RouteParams]) : [route]; - const resolvedPathname = resolve(...(resolveArgs as ResolveArgs)); - - return goto(resolvedPathname); + return goto(resolveRoute(route, params)); } diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/helpers/terminology.ts b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/helpers/terminology.ts index 77c497527..00f289cdd 100644 --- a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/helpers/terminology.ts +++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/helpers/terminology.ts @@ -9,6 +9,7 @@ import type { Term, TerminologyResult, TerminologyShape } from '$database/(entit export type DatabaseType = 'legacy' | 'tablesdb' | 'documentsdb' | 'vectordb'; export type Entity = Partial; export type Field = Partial; +export type Index = Partial; export const baseTerminology = { tablesdb: { diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/index.ts b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/index.ts index a7558f559..ec2d76f1d 100644 --- a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/index.ts +++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/index.ts @@ -1,4 +1,5 @@ export * from './helpers'; +export * from './views/indexes'; export * from './views/settings'; export { default as Usage } from './views/usage/view.svelte'; export { default as EntityContainer } from './views/container.svelte'; diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/(layouts)/index.ts b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/(layouts)/index.ts new file mode 100644 index 000000000..432635bff --- /dev/null +++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/(layouts)/index.ts @@ -0,0 +1,2 @@ +export { default as SideSheet } from './sidesheet.svelte'; +export { default as SpreadsheetContainer } from './spreadsheet.svelte'; diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/(layouts)/sidesheet.svelte b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/(layouts)/sidesheet.svelte new file mode 100644 index 000000000..68b981d3a --- /dev/null +++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/(layouts)/sidesheet.svelte @@ -0,0 +1,174 @@ + + +
+ +
+ + + {title} + {#if titleBadge} + + {/if} + + {#if topAction && topAction.text && topAction.show} + {#if topAction.mode === 'copy-tag'} + + + {topAction.text} + + + {:else} + + {/if} + {/if} + + +
+ + +
{ + try { + const keepOpen = await submit?.onClick?.(); + if (!keepOpen) { + show = false; + } + } catch (error) { + // error occurred, dont close the sidebar + } + }}> + + {@render children?.()} + +
+ + {#if submit} + + {/if} +
+
+
+ + diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/(layouts)/spreadsheet.svelte b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/(layouts)/spreadsheet.svelte new file mode 100644 index 000000000..30483eb68 --- /dev/null +++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/(layouts)/spreadsheet.svelte @@ -0,0 +1,123 @@ + + +
+ {@render children()} +
+ + diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/(layouts)/store.ts b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/(layouts)/store.ts new file mode 100644 index 000000000..b1d1ca96f --- /dev/null +++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/(layouts)/store.ts @@ -0,0 +1,5 @@ +import { writable } from 'svelte/store'; + +export const scrollStore = writable(null); + +export const sheetHeightStore = writable('74.5vh'); diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/failedModal.svelte b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/failedModal.svelte new file mode 100644 index 000000000..e177e613e --- /dev/null +++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/failedModal.svelte @@ -0,0 +1,34 @@ + + + + +
+

+ + + {header} +

+

{error}

+
+ + + + +
diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/indexes/createIndex.svelte b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/indexes/create.svelte similarity index 60% rename from src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/indexes/createIndex.svelte rename to src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/indexes/create.svelte index 85c5b518a..931c04709 100644 --- a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/indexes/createIndex.svelte +++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/indexes/create.svelte @@ -1,5 +1,14 @@ + + @@ -183,10 +207,12 @@ bind:value={key} autofocus /> - + - {#each columnList as column, index} + {@const fieldType = terminology.field.title.singular} + {@const fieldTypeLower = terminology.field.lower.singular} + {#each fieldList as field, index} {@const direction = $isSmallViewport ? 'column' : 'row'} + id={`field-${index}`} + label={index === 0 ? fieldType : undefined} + placeholder="Select {fieldType}" + bind:value={field.value} /> {#if selectedType === IndexType.Key} @@ -220,7 +246,7 @@ id={`length-${index}`} label={index === 0 ? 'Length' : undefined} placeholder="Enter length" - bind:value={column.length} /> + bind:value={field.length} /> {/if} {#if $isSmallViewport} @@ -228,9 +254,9 @@ @@ -241,9 +267,9 @@ icon size="s" secondary - disabled={columnList.length <= 1} + disabled={fieldList.length <= 1} on:click={() => { - columnList = remove(columnList, index); + fieldList = remove(fieldList, index); }}> @@ -252,9 +278,9 @@ {/each}
-
diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/indexes/deleteIndex.svelte b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/indexes/delete.svelte similarity index 58% rename from src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/indexes/deleteIndex.svelte rename to src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/indexes/delete.svelte index 956bb1b6a..3aabefa4d 100644 --- a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/indexes/deleteIndex.svelte +++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/indexes/delete.svelte @@ -1,49 +1,57 @@ + {#if selectedIndex?.columns?.length} {#each selectedIndex.columns as column, i} diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/indexes/select.svelte b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/indexes/select.svelte similarity index 96% rename from src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/indexes/select.svelte rename to src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/indexes/select.svelte index e356097a5..fb91f3a7a 100644 --- a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/indexes/select.svelte +++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/indexes/select.svelte @@ -3,6 +3,8 @@ import { Icon } from '@appwrite.io/pink-svelte'; import { IconChevronDown } from '@appwrite.io/pink-icons-svelte'; + // TODO: @itznotabug: svelte5 + export let value: string; export let id: string; export let label: string; diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/indexes/view.svelte b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/indexes/view.svelte new file mode 100644 index 000000000..4a2873d12 --- /dev/null +++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/views/indexes/view.svelte @@ -0,0 +1,308 @@ + + + + {#snippet children(_, dependencies, terminology)} + + + {#if $canWriteTables} + + {/if} + + + +
+ {#if entity.columns?.length} + {#if entity.indexes.length} + + (showCreateIndex = true)}> + + Key + Type + Columns + + + Lengths + + + + {#each entity.indexes as index (index.key)} + + + + {index.key} + {#if index.status !== 'available'} + + {#if index.error} + { + e.preventDefault(); + error = index.error; + showFailed = true; + }}>Details + {/if} + {/if} + + + {index.type} + + {index.columns.join(', ')} + + + + + + {index.lengths} + + + + + + { + toggle(); + selectedIndex = index; + showOverview = true; + }}>Overview + +
+ +
+ + { + toggle(); + showDelete = true; + selectedIndex = index; + trackEvent(Click.DatabaseIndexDelete); + }}>Delete +
+
+
+
+ {/each} + + + + + {@const length = entity.indexes.length} + {length} + {length === 1 ? 'index' : 'indexes'} + + + +
+
+ {:else} + {@render emptyIndexesSheetView(() => (showCreateIndex = true))} + {/if} + {:else} + {@render emptyColumnsSheetView(() => (showCreateColumnSheet = true))} + {/if} + + {#if selectedIndexes.length > 0} +
+ + +
+ + + + {selectedIndexes.length > 1 ? 'indexes' : 'index'} + selected + + +
+
+ + + + +
+
+ {/if} +
+ + await createIndex.create() + }}> + + + + {#if selectedIndex} + + {:else if selectedIndexes && selectedIndexes.length} + + {/if} + + + + + + + {/snippet} +
+ + diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/+layout.svelte b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/+layout.svelte index fcc995b71..6c8a262c2 100644 --- a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/+layout.svelte +++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/+layout.svelte @@ -57,13 +57,15 @@ import { generateFakeRecords, generateColumns } from '$lib/helpers/faker'; import { addNotification } from '$lib/stores/notifications'; import { sleep } from '$lib/helpers/promises'; - import CreateIndex from './indexes/createIndex.svelte'; import { hash } from '$lib/helpers/string'; import { preferences } from '$lib/stores/preferences'; import { buildRowUrl, isRelationship } from './rows/store'; import { chunks } from '$lib/helpers/array'; import { Submit, trackEvent } from '$lib/actions/analytics'; + import { CreateIndex } from '$database/(entity)'; + import { EntityContainer } from '$database/(entity)/index.js'; + let editRow: EditRow; let editRelatedRow: EditRelatedRow; let editRowPermissions: EditRowPermissions; @@ -431,10 +433,32 @@ await createIndex.create(); } }}> - + + + + {#snippet children(_, dependencies, terminology)} + { + await sdk + .forProject(page.params.region, page.params.project) + .tablesDB.createIndex({ + databaseId: page.params.database, + tableId: page.params.table, + key: index.key, + type: index.type, + columns: index.fields, + lengths: index.lengths, + orders: index.orders + }); + }} /> + {/snippet} + {#if showFailed} - + {/if} diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/indexes/+page.svelte b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/indexes/+page.svelte index 53a4327e9..fe838a1fa 100644 --- a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/indexes/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/indexes/+page.svelte @@ -1,288 +1,68 @@ - - - {#if $canWriteTables} - - {/if} - - + + {#snippet emptyIndexesSheetView(toggle)} + + {/snippet} -
- {#if data.table?.columns?.length} - {#if data.table.indexes.length} - - (showCreateIndex = true)}> - - Key - Type - Columns - - - Lengths - - - - {#each data.table.indexes as index} - - - - {index.key} - {#if index.status !== 'available'} - - {#if index.error} - { - e.preventDefault(); - error = index.error; - showFailed = true; - }}>Details - {/if} - {/if} - - - {index.type} - - {index.columns.join(', ')} - - - - - - {index.lengths} - - - - - - { - toggle(); - selectedIndex = index; - showOverview = true; - }}>Overview - -
- -
- - { - toggle(); - showDelete = true; - selectedIndex = index; - trackEvent(Click.DatabaseIndexDelete); - }}>Delete -
-
-
-
- {/each} - - - - - {@const length = data.table.indexes.length} - {length} - {length === 1 ? 'index' : 'indexes'} - - - -
-
- {:else} - (showCreateIndex = true), - disabled: !$table?.columns?.length - } - }} /> - {/if} - {:else} + {#snippet emptyColumnsSheetView(toggle)} { - $showCreateColumnSheet.show = true; - } + onClick: toggle } }} /> - {/if} - - {#if selectedIndexes.length > 0} -
- - -
- - - - {selectedIndexes.length > 1 ? 'indexes' : 'index'} - selected - - -
-
- - - - -
-
- {/if} -
- - await createIndex.create() - }}> - - - -{#if selectedIndex} - -{:else if selectedIndexes && selectedIndexes.length} - -{/if} - - - - - - - - + {/snippet} +
diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/settings/+page.svelte b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/settings/+page.svelte index ead1b079c..90d4eb3c0 100644 --- a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/settings/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/settings/+page.svelte @@ -12,7 +12,6 @@ UpdateStatus } from '$database/(entity)'; - const tablesDB = sdk.forProject(page.params.region, page.params.project).tablesDB; const params = $derived.by(() => { return { name: $table.name, @@ -22,7 +21,7 @@ }); async function deleteTable() { - await tablesDB.deleteTable({ ...params }); + await sdk.forProject(page.params.region, page.params.project).tablesDB.deleteTable({ ...params }); } async function updateTable( @@ -33,7 +32,7 @@ rowSecurity: boolean; }> ) { - await tablesDB.updateTable({ ...params, ...updates }); + await sdk.forProject(page.params.region, page.params.project).tablesDB.updateTable({ ...params, ...updates }); }