Merge pull request #3002 from appwrite/fix-duplicate-actions-column-key

fix: avoid actions column key collision in database tables
This commit is contained in:
Harsh Mahajan
2026-04-23 17:32:51 +05:30
committed by GitHub
5 changed files with 32 additions and 32 deletions
@@ -89,7 +89,7 @@
return [...idColumn, ...columns.filter((column) => !column.isAction), ...systemColumns];
}
$: selected = preferences.getCustomTableColumns(page.params.table);
$: selected = preferences.getCustomTableColumns(table.$id);
$: if (table.fields) {
const freshColumns = createTableColumns(table.fields, selected);
@@ -155,7 +155,7 @@
onDestroy(() => ($showCreateColumnSheet.show = false));
</script>
{#key page.params.table}
{#key table.$id}
<Container expanded expandHeightButton style="background: var(--bgcolor-neutral-primary)">
<Layout.Stack direction="column" gap="xl">
<Layout.Stack direction="row" justifyContent="space-between">
@@ -24,7 +24,8 @@
isCsvImportInProgress,
isWaterfallFromFaker,
reorderItems,
showCreateIndexSheet
showCreateIndexSheet,
INTERNAL_ACTIONS_COLUMN_ID
} from '../store';
import EditColumn from './edit.svelte';
import DeleteColumn from './deleteColumn.svelte';
@@ -336,7 +337,7 @@
minimumWidth: 200,
resizable: true
},
{ id: 'actions', width: 40, isAction: true, resizable: false }
{ id: INTERNAL_ACTIONS_COLUMN_ID, width: 40, isAction: true, resizable: false }
]);
$effect(() => {
@@ -388,7 +389,7 @@
<Spreadsheet.Header.Cell column="indexed" {root}>Indexed</Spreadsheet.Header.Cell>
<Spreadsheet.Header.Cell column="default" {root}
>Default value</Spreadsheet.Header.Cell>
<Spreadsheet.Header.Cell column="actions" {root} />
<Spreadsheet.Header.Cell column={INTERNAL_ACTIONS_COLUMN_ID} {root} />
</svelte:fragment>
{#each updatedColumnsForSheet as column, index (column.key)}
@@ -544,7 +545,7 @@
{_default}
{/if}
</Spreadsheet.Cell>
<Spreadsheet.Cell column="actions" {root} isEditable={false}>
<Spreadsheet.Cell column={INTERNAL_ACTIONS_COLUMN_ID} {root} isEditable={false}>
{#if $isCsvImportInProgress}
<CsvDisabled>
<Button disabled text icon ariaLabel="more options">
@@ -14,7 +14,12 @@
import { showColumnsSuggestionsModal } from '../(suggestions)/store';
import IconAINotification from '../(suggestions)/icon/aiNotification.svelte';
import { type Columns, type ColumnDirection, showCreateColumnSheet } from './store';
import {
type Columns,
type ColumnDirection,
showCreateColumnSheet,
INTERNAL_ACTIONS_COLUMN_ID
} from './store';
import { isCloud } from '$lib/system';
import { slide } from 'svelte/transition';
@@ -76,9 +81,9 @@
function insertColumnInOrder() {
if (!key) return;
const currentOrder = columnsOrder?.length
? columnsOrder
: columns?.map((col) => col.id) || [];
const currentOrder = (
columnsOrder?.length ? columnsOrder : columns?.map((col) => col.id) || []
).filter((columnId) => columnId !== '$id' && columnId !== INTERNAL_ACTIONS_COLUMN_ID);
// if the length is empty,
// means there's no ordering done.
@@ -88,12 +93,7 @@
let newOrder: string[];
if (!direction || !direction.neighbour) {
// Find the actions column position
const actionsIndex = currentOrder.indexOf('actions');
const beforeActionsOrder =
actionsIndex !== -1 ? currentOrder.slice(0, actionsIndex) : currentOrder;
const lastTwo = beforeActionsOrder.slice(-2);
const lastTwo = currentOrder.slice(-2);
const hasTimestampColumnsAtEnd =
lastTwo.length === 2 &&
lastTwo.includes('$createdAt') &&
@@ -107,8 +107,7 @@
currentOrder.indexOf('$updatedAt')
);
} else {
// Insert at the end, but before actions
insertIndex = actionsIndex !== -1 ? actionsIndex : currentOrder.length;
insertIndex = currentOrder.length;
}
newOrder = [
@@ -120,14 +119,7 @@
const neighbourIndex = currentOrder.indexOf(direction.neighbour);
if (neighbourIndex === -1) {
const actionsIndex = currentOrder.indexOf('actions');
const insertIndex = actionsIndex !== -1 ? actionsIndex : currentOrder.length;
newOrder = [
...currentOrder.slice(0, insertIndex),
key,
...currentOrder.slice(insertIndex)
];
newOrder = [...currentOrder, key];
} else {
const insertIndex = direction.to === 'left' ? neighbourIndex : neighbourIndex + 1;
newOrder = [
@@ -42,7 +42,8 @@
expandTabs,
databaseRelatedRowSheetOptions,
rowPermissionSheet,
type Columns
type Columns,
INTERNAL_ACTIONS_COLUMN_ID
} from './store';
import type { Column, ColumnType } from '$lib/helpers/types';
import {
@@ -164,7 +165,7 @@
function setupColumns() {
const order = preferences.getColumnOrder(tableId);
const systemColumns = new Set(['$id', 'actions']);
const systemColumns = new Set(['$id', INTERNAL_ACTIONS_COLUMN_ID]);
const validColumnKeys = new Set([
...$columns.map((col) => col.key),
@@ -187,6 +188,7 @@
function makeTableColumns() {
const selectedColumnsToHide = preferences.getCustomTableColumns(tableId);
const staticColumnIds = new Set(['$id', INTERNAL_ACTIONS_COLUMN_ID]);
const baseColumns: Column[] = table.fields.map((field: Field) => {
return {
@@ -241,7 +243,7 @@
hide: !!selectedColumnsToHide?.includes('$updatedAt')
},
{
id: 'actions',
id: INTERNAL_ACTIONS_COLUMN_ID,
title: '',
width: 40,
isAction: true,
@@ -257,7 +259,10 @@
const fixedRightColumn = staticColumns[3];
const reorderableColumns = [...baseColumns, staticColumns[1], staticColumns[2]];
const reorderedColumns = reorderItems(reorderableColumns, $columnsOrder);
const reorderedColumns = reorderItems(
reorderableColumns,
$columnsOrder.filter((columnId) => !staticColumnIds.has(columnId))
);
const finalColumns = [fixedLeftColumn, ...reorderedColumns, fixedRightColumn];
@@ -856,7 +861,7 @@
<svelte:fragment slot="header" let:root>
{#each $tableColumns as column (column.id)}
{#if column.isAction}
<Spreadsheet.Header.Cell column="actions" {root}>
<Spreadsheet.Header.Cell column={INTERNAL_ACTIONS_COLUMN_ID} {root}>
<Tooltip>
<Button.Button
icon
@@ -1019,7 +1024,7 @@
showDatetime
time={row?.[columnId]}
canShowPopover={canShowDatetimePopover} />
{:else if columnId === 'actions'}
{:else if columnId === INTERNAL_ACTIONS_COLUMN_ID}
<SheetOptions
type="row"
column={rowColumn}
@@ -58,6 +58,8 @@ export const isWaterfallFromFaker = writable(false);
export const tableColumns = writable<Column[]>([]);
export const INTERNAL_ACTIONS_COLUMN_ID = '$actions';
export const isCsvImportInProgress = writable(false);
export const columnsOrder = writable<string[]>([]);