Show auto primary keys in bulk insert preview

Render omitted auto integer primary key values as muted auto text in the bulk insert preview so generated IDs are easier to understand.

Expose the auto primary key flag in insert UI metadata and cover the preview behavior in Playwright.
This commit is contained in:
Simon Willison 2026-07-03 12:27:02 -07:00
commit 3aea678eab
5 changed files with 29 additions and 6 deletions

View file

@ -1979,7 +1979,8 @@ textarea.row-edit-input {
border-right: none;
}
.row-edit-bulk-preview-null {
.row-edit-bulk-preview-null,
.row-edit-bulk-preview-auto {
color: var(--muted);
font-style: italic;
}

View file

@ -6038,6 +6038,25 @@ function bulkInsertPreviewValue(value) {
return String(value);
}
function bulkInsertPreviewCell(column, hasValue, value) {
if (!hasValue && column.is_auto_pk) {
return {
text: "auto",
className: "row-edit-bulk-preview-auto",
};
}
if (value === null) {
return {
text: bulkInsertPreviewValue(value),
className: "row-edit-bulk-preview-null",
};
}
return {
text: hasValue ? bulkInsertPreviewValue(value) : "",
className: "",
};
}
function renderBulkInsertPreview(state, rows) {
state.bulkInsertPreview.textContent = "";
var summary = document.createElement("p");
@ -6068,9 +6087,10 @@ function renderBulkInsertPreview(state, rows) {
var td = document.createElement("td");
var hasValue = Object.prototype.hasOwnProperty.call(row, column.name);
var value = hasValue ? row[column.name] : "";
td.textContent = hasValue ? bulkInsertPreviewValue(value) : "";
if (value === null) {
td.className = "row-edit-bulk-preview-null";
var cell = bulkInsertPreviewCell(column, hasValue, value);
td.textContent = cell.text;
if (cell.className) {
td.className = cell.className;
}
tr.appendChild(td);
});

View file

@ -205,7 +205,7 @@ class TableContext(Context):
)
table_insert_ui: dict = field(
metadata={
"help": "Information needed to enable the row insertion UI, or ``None`` if row insertion is not available to the current actor. When present it has ``path``, ``tableName``, ``columns`` and ``primaryKeys`` keys; each column includes ``name``, ``sqlite_type``, ``notnull``, ``default``, ``has_default``, ``is_pk``, ``value_kind`` and ``column_type`` keys."
"help": "Information needed to enable the row insertion UI, or ``None`` if row insertion is not available to the current actor. When present it has ``path``, ``tableName``, ``columns`` and ``primaryKeys`` keys; each column includes ``name``, ``sqlite_type``, ``notnull``, ``default``, ``has_default``, ``is_pk``, ``is_auto_pk``, ``value_kind`` and ``column_type`` keys."
}
)
table_alter_ui: dict = field(
@ -507,6 +507,7 @@ async def _table_insert_ui(
"default": column.default_value,
"has_default": column.default_value is not None,
"is_pk": is_pk,
"is_auto_pk": is_auto_pk,
"value_kind": _column_value_kind_for_insert_form(column),
"column_type": (
{"type": column_type.name, "config": column_type.config}

View file

@ -389,7 +389,7 @@ Many of these keys are shared with the :ref:`JSON API <json_api>` for this page.
SQL definition for this table
``table_insert_ui`` - ``dict``
Information needed to enable the row insertion UI, or ``None`` if row insertion is not available to the current actor. When present it has ``path``, ``tableName``, ``columns`` and ``primaryKeys`` keys; each column includes ``name``, ``sqlite_type``, ``notnull``, ``default``, ``has_default``, ``is_pk``, ``value_kind`` and ``column_type`` keys.
Information needed to enable the row insertion UI, or ``None`` if row insertion is not available to the current actor. When present it has ``path``, ``tableName``, ``columns`` and ``primaryKeys`` keys; each column includes ``name``, ``sqlite_type``, ``notnull``, ``default``, ``has_default``, ``is_pk``, ``is_auto_pk``, ``value_kind`` and ``column_type`` keys.
``table_page_data`` - ``dict``
JSON data used by JavaScript on the table page. Includes ``database``, ``table`` and ``tableUrl``, plus optional ``foreignKeys`` mapping column names to autocomplete URLs, optional ``insertRow`` data and optional ``alterTable`` data.

View file

@ -1329,6 +1329,7 @@ def test_bulk_insert_omits_columns_absent_from_pasted_input(page, datasette_serv
preview_text = dialog.locator(".row-edit-bulk-preview-table").inner_text()
assert "Only title" in preview_text
assert "undefined" not in preview_text
assert dialog.locator(".row-edit-bulk-preview-auto").inner_text() == "auto"
dialog.locator(".row-edit-save").click()
dialog.locator(