diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/[...rest]/+page.ts b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/[...rest]/+page.ts index 7bf33de28..11562ad9a 100644 --- a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/[...rest]/+page.ts +++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/[...rest]/+page.ts @@ -2,32 +2,57 @@ import { base } from '$app/paths'; import type { PageLoad } from './$types'; import { redirect } from '@sveltejs/kit'; import { AppwriteException } from '@appwrite.io/console'; +import { databaseRowSheetOptions } from '../table-[table]/store'; -const LEGACY_ROUTE_MAPPINGS = [ +const ROUTE_MAPPINGS: { + pattern: RegExp; + replacement?: string; + sheet?: 'row' | 'column'; +}[] = [ { pattern: /^collection-([^/]+)/, replacement: 'table-$1' }, // document detail page redirect to their parent table - { pattern: /^document-([^/]+)/, replacement: 'table-$1' }, + { pattern: /^document-([^/]+)/, sheet: 'row' }, // attribute detail redirect to table columns { pattern: /^attribute-([^/]+)/, replacement: 'table-$1/columns' }, // attributes list page redirect to table columns - { pattern: /^attributes$/, replacement: 'columns' } + { pattern: /^attributes$/, replacement: 'columns' }, + + + // New format routes, + { pattern: /^row-([^/]+)/, sheet: 'row' } ] as const; function isLegacyRoute(segments: string[]): boolean { return segments.some((segment) => - LEGACY_ROUTE_MAPPINGS.some((mapping) => mapping.pattern.test(segment)) + ROUTE_MAPPINGS.some((mapping) => mapping.pattern.test(segment)) ); } function rewriteLegacySegments(segments: string[]): string[] { - return segments.map((segment) => { - for (const mapping of LEGACY_ROUTE_MAPPINGS) { - if (mapping.pattern.test(segment)) { - return segment.replace(mapping.pattern, mapping.replacement); + return segments + .map((segment) => { + for (const mapping of ROUTE_MAPPINGS) { + if (mapping.pattern.test(segment)) { + if (mapping.sheet && mapping.sheet === 'row') { + const match = segment.match(mapping.pattern); + if (match && match[1]) { + databaseRowSheetOptions.update((options) => ({ + ...options, + rowId: match[1], + title: 'Update row', + mode: 'redirect' + })); + } + } + + return !mapping.replacement + ? null + : segment.replace(mapping.pattern, mapping.replacement); + } } - } - return segment; - }); + return segment; + }) + .filter(Boolean); } export const load: PageLoad = async ({ params, url }) => { 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 b73f1f239..b08b71d2d 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 @@ -383,7 +383,10 @@ disabled: editRow?.isDisabled(), onClick: async () => await editRow?.update() }}> - + | null>(null); let columnFormWrapper = $state(null); @@ -39,10 +43,42 @@ return writable(deepClone(result as Models.Row)); } + async function loadRowFromId() { + if (!rowId) return; + loading = true; + + try { + row = await sdk.forProject(page.params.region, page.params.project).tablesDB.getRow({ + databaseId, + tableId, + rowId, + queries: buildWildcardColumnsQuery($table) + }); + } catch (error) { + addNotification({ + message: `Failed to load row: ${error.message}`, + type: 'error' + }); + + row = null; + } finally { + rowId = null; + loading = false; + } + } + + $effect(() => { + if (!row && rowId) { + loadRowFromId(); + } + }); + $effect(() => { if (row) { work = initWork(); focusFirstInput(); + } else { + work = null; } }); @@ -81,6 +117,8 @@ } export async function update() { + if (!row || !work) return; + try { await sdk.forProject(page.params.region, page.params.project).tablesDB.updateRow({ databaseId, @@ -106,7 +144,7 @@ } export function isDisabled(): boolean { - if (!work || !$table?.columns?.length) return true; + if (!work || !row || !$table?.columns?.length) return true; return $table.columns.every((column) => compareColumns(column, $work, row)); } @@ -120,7 +158,11 @@ } -{#if $table.columns?.length && work} +{#if loading} +
+ +
+{:else if $table.columns?.length && work}
{#each $table.columns as column} diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/spreadsheet.svelte b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/spreadsheet.svelte index bfce84f0b..7115b7790 100644 --- a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/spreadsheet.svelte +++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/spreadsheet.svelte @@ -132,6 +132,11 @@ paginatedRows.clear(); paginatedRows.setPage(1, data.rows.rows); } + + // rowId exists, we have someone from old url format! + if ($databaseRowSheetOptions && $databaseRowSheetOptions.rowId) { + setTimeout(() => ($databaseRowSheetOptions.show = true), 250); + } }); onDestroy(() => ($showCreateColumnSheet.show = false)); diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/store.ts b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/store.ts index 25e579753..013a275d8 100644 --- a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/store.ts +++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/store.ts @@ -57,11 +57,13 @@ export const databaseColumnSheetOptions = writable({ export const databaseRowSheetOptions = writable< DatabaseSheetOptions & { row: Models.Row; + rowId?: string; } >({ title: null, show: false, - row: null + row: null, + rowId: null // for loading from a given id }); export const databaseRelatedRowSheetOptions = writable< @@ -177,6 +179,7 @@ export const paginatedRows = createSparsePagedDataStore(SPREA export const PROHIBITED_ROW_KEYS = [ '$id', + '$sequence', '$collection', '$tableId', '$databaseId',