Merge pull request #2926 from appwrite/fix-SER-1172-table-filters

This commit is contained in:
Jake Barnby
2026-03-24 06:26:27 +00:00
committed by GitHub
3 changed files with 67 additions and 50 deletions
+2 -2
View File
@@ -26,8 +26,8 @@
sizes="120x120"
href="%sveltekit.assets%/logos/apple-touch-icon-120x120.png" />
<!-- apple web app meta tags -->
<meta name="apple-mobile-web-app-capable" content="yes" />
<!-- web app / standalone display meta tags -->
<meta name="mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-title" content="Appwrite Console" />
<meta name="apple-mobile-web-app-status-bar-style" content="default" />
@@ -23,7 +23,7 @@
onUpdateFormValues?: (formValues: object) => void;
} = $props();
let formStore = writable(formValues);
let formStore = writable(formValues ?? {});
function removeArrayItem(key: string, index: number) {
const currentArray = Array.isArray($formStore[key]) ? $formStore[key] : [];
@@ -103,6 +103,8 @@
};
$: table = data.table;
/** Keep sort in sync after client navigations (e.g. filters); onMount alone misses SPA loads. */
$: sortState.set(data.currentSort as SortState);
$: rows = writable(data.rows);
$: if ($rows) {
paginatedRows.clear();
@@ -113,7 +115,9 @@
}
// create index map for O(1) row lookups, reactive!
$: rowIndexMap = new Map($paginatedRows.items.map((row, index) => [row.$id, index]));
$: rowIndexMap = new Map(
$paginatedRows.items.flatMap((r, index) => (r ? [[r.$id, index]] : []))
);
const tableId = page.params.table;
const databaseId = page.params.database;
@@ -912,7 +916,8 @@
<svelte:fragment slot="rows" let:root let:item let:index>
{@const row = $paginatedRows.getItemAtVirtualIndex(index)}
{#if row === null}
<!-- !row: virtualizer can briefly yield null/undefined while row data reloads (e.g. after filters). -->
{#if !row}
<Spreadsheet.Row.Base
{root}
{index}
@@ -936,7 +941,7 @@
select={rowSelection}
hoverEffect
showSelectOnHover
valueWithoutHover={row.$sequence}>
valueWithoutHover={row?.$sequence}>
{#each $tableColumns as { id: columnId, isEditable, hide } (columnId)}
{@const rowColumn = $columns.find((col) => col.key === columnId)}
{#if columnId === '$id' && !hide}
@@ -948,8 +953,8 @@
alignItems="center"
alignContent="center"
justifyContent="space-between">
<Id value={row.$id} tooltipPortal tooltipDelay={200}>
{row.$id}
<Id value={row?.$id} tooltipPortal tooltipDelay={200}>
{row?.$id}
</Id>
<Popover let:show let:hide portal padding="none">
@@ -1009,7 +1014,7 @@
{#if columnId === '$createdAt' || columnId === '$updatedAt'}
<DualTimeView
showDatetime
time={row[columnId]}
time={row?.[columnId]}
canShowPopover={canShowDatetimePopover} />
{:else if columnId === 'actions'}
<SheetOptions
@@ -1033,12 +1038,12 @@
</Button.Button>
{/snippet}
</SheetOptions>
{:else if isRelationship(rowColumn)}
{@const args = getDisplayNamesForTable(row[columnId])}
{:else if rowColumn && isRelationship(rowColumn)}
{@const args = getDisplayNamesForTable(row?.[columnId])}
{#if !isRelationshipToMany(rowColumn)}
{#if row[columnId]}
{#if row?.[columnId]}
{@const displayValue = args
.map((arg) => row[columnId]?.[arg])
.map((arg) => row?.[columnId]?.[arg])
.filter(Boolean)
.join(' | ')}
@@ -1047,9 +1052,9 @@
variant="muted"
on:click={() => {
$databaseRelatedRowSheetOptions.tableId =
row[columnId]?.['$tableId'];
row?.[columnId]?.['$tableId'];
$databaseRelatedRowSheetOptions.rows =
row[columnId]?.['$id'];
row?.[columnId]?.['$id'];
$databaseRelatedRowSheetOptions.show = true;
}}>
{displayValue}
@@ -1067,19 +1072,23 @@
size="xs" />
{/if}
{:else}
{@const itemsNum = row[columnId]?.length}
{@const itemsNum = row?.[columnId]?.length}
Items <Badge
content={itemsNum}
variant="secondary"
size="s" />
{/if}
{:else if isSpatialType(rowColumn) && row[columnId] !== null}
{:else if rowColumn && isSpatialType(rowColumn) && row?.[columnId] !== null}
<Typography.Text truncate>
{JSON.stringify(row[columnId])}
{JSON.stringify(row?.[columnId])}
</Typography.Text>
{:else if !rowColumn}
<Typography.Text truncate>
{formatColumn(row?.[columnId])}
</Typography.Text>
{:else}
{@const value = row[columnId]}
{@const formatted = formatColumn(row[columnId])}
{@const value = row?.[columnId]}
{@const formatted = formatColumn(row?.[columnId])}
{@const isEmptyArray = formatted === 'Empty'}
{@const isDatetimeAttribute = rowColumn.type === 'datetime'}
{@const isEncryptedAttribute =
@@ -1126,38 +1135,46 @@
{/if}
<svelte:fragment slot="cell-editor" let:close>
{@const isRelatedToMany = isRelationshipToMany(rowColumn)}
{@const hasItems = isRelatedToMany
? row[columnId]?.length
: false}
{#if rowColumn}
{@const isRelatedToMany =
isRelationshipToMany(rowColumn)}
{@const hasItems = isRelatedToMany
? row?.[columnId]?.length
: false}
<EditRowCell
{row}
column={rowColumn}
onRowStructureUpdate={async (row) => {
const success = await updateRowContents(row);
if (success) {
// database update succeeded!
paginatedRows.update(index, row);
}
return success;
}}
noInlineEdit={isRelatedToMany && hasItems}
onChange={(row) => paginatedRows.update(index, row)}
onRevert={(row) => paginatedRows.update(index, row)}
openSideSheet={() => {
close(); /* closes the editor */
<EditRowCell
{row}
column={rowColumn}
onRowStructureUpdate={async (row) => {
const success = await updateRowContents(row);
if (success) {
// database update succeeded!
paginatedRows.update(index, row);
}
return success;
}}
noInlineEdit={isRelatedToMany && hasItems}
onChange={(row) => paginatedRows.update(index, row)}
onRevert={(row) => paginatedRows.update(index, row)}
openSideSheet={() => {
close(); /* closes the editor */
if (isRelationshipToMany(rowColumn)) {
openSideSheetForRelationsToMany(
row[columnId],
rowColumn
);
} else {
$databaseRowSheetOptions.autoFocus = true;
onSelectSheetOption('update', null, 'row', row);
}
}} />
if (isRelationshipToMany(rowColumn)) {
openSideSheetForRelationsToMany(
row?.[columnId],
rowColumn
);
} else {
$databaseRowSheetOptions.autoFocus = true;
onSelectSheetOption(
'update',
null,
'row',
row
);
}
}} />
{/if}
</svelte:fragment>
</Spreadsheet.Cell>
{/if}