Skip to content

feat(inspector): insert rows and confirm data-bearing deletes in the CSV editor#1939

Merged
datlechin merged 2 commits into
mainfrom
feat/1469-csv-row-editing
Jul 22, 2026
Merged

feat(inspector): insert rows and confirm data-bearing deletes in the CSV editor#1939
datlechin merged 2 commits into
mainfrom
feat/1469-csv-row-editing

Conversation

@datlechin

Copy link
Copy Markdown
Member

Part 1 of 4 toward #1469 (CSV structural editing). Focused on rows.

What

  • Insert Row Above / Insert Row Below from a row's right-click menu, and mirrored in the Edit menu (where they act on the selected row). Both insert a blank row and scroll to it.
  • Delete confirmation: deleting rows that contain any non-empty cell now asks first. Deleting blank rows still deletes without a prompt.
  • Row insert and delete are each a single named undo step ("Undo Insert Row", "Undo Delete Rows").

Why

The CSV inspector (from #1259, extended by #1913/#1932) can edit cells and add/remove columns, but the only way to add a row was the toolbar Add Row button, which always appends. There was no way to insert at a position, and deletes had no guard for data-bearing rows. This closes the row half of #1469.

How (native / HIG)

  • Row items ride the existing shared row menu through a new dataGridRowStructureMenuItems(forRow:) delegate seam, mirroring the column seam feat(inspector): add column header context menu to rename, insert, and delete columns #1932 added. Only the CSV inspector implements it, so database grids are unaffected.
  • Edit-menu items dispatch through the responder chain (NSApp.sendAction(_:to:nil)) to the focused inspector, gated on keyWindowIsInspector, matching the existing Undo/Redo/Find routing.
  • Insert reuses CSVDocument.insertRow(at:) (already undoable); delete adds a confirm-when-non-empty gate. Per Apple's HIG, undoable deletes normally don't need a prompt, so the prompt is scoped to data-bearing rows and its copy does not claim the action is irreversible.
  • Selection is mapped display-position → store index through the inspector's displayToStore, respecting the filtered/sorted-view invariant (a display row is not a store row).

Tests

  • CSVRowStore.insertRow at a middle index, at the top, clamped past the end, and padding a short row.
  • InspectorRowMenuBuilder item order, action wiring, and row tagging.
  • InspectorDeleteConfirmation.rowsContainData / rowDeleteTitle decision logic.

Docs / changelog

  • docs/features/csv-inspector.mdx Editing section updated.
  • CHANGELOG entry under [Unreleased].

Needs a local Xcode build to confirm compilation (CI lints TablePro/ only, which passes --strict).

@mintlify

mintlify Bot commented Jul 21, 2026

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
TablePro 🟢 Ready View Preview Jul 21, 2026, 5:57 PM

💡 Tip: Enable Workflows to automatically generate PRs for you.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9f95836905

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

registerUndo { document in
document.removeRow(at: index, suppressUndo: false)
}
setUndoActionName(String(localized: "Add Row"))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve the Paste undo label

When rows are pasted, handlePasteRows opens an undo group and sets its action name to Paste, but each pasted row now calls appendRow(). This assignment overwrites the enclosing group's name, so a multi-row paste is presented to users as “Undo Add Row” rather than “Undo Paste”; restore the group name after the append operations or avoid setting an action name from appendRow while a caller owns the group.

Useful? React with 👍 / 👎.

Comment on lines 400 to 403
case #selector(saveDocument(_:)), #selector(saveDocumentAs(_:)),
#selector(toggleInspectorFilter(_:)), #selector(inspectorAddRow(_:)):
#selector(toggleInspectorFilter(_:)), #selector(inspectorAddRow(_:)),
#selector(inspectorInsertRowAbove(_:)), #selector(inspectorInsertRowBelow(_:)):
return nsDocument != nil

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Require a selected row for Edit-menu insertion

The Edit-menu insert commands validate whenever an inspector document exists, even with no selected row. In that state insertStoreIndex falls back to index 0 for Above and rowCount for Below, so invoking commands documented to act on the selected row silently inserts at the beginning or end instead. Disable these actions unless a row is selected (or make the empty-table behavior explicit).

Useful? React with 👍 / 👎.

@mintlify

mintlify Bot commented Jul 21, 2026

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
TablePro 🟡 Building Jul 21, 2026, 5:57 PM

💡 Tip: Enable Workflows to automatically generate PRs for you.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f1f8e5a5ff

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

document.reinsertRow(removed, at: index)
document.reinsertRow(removed, at: index, actionName: actionName)
}
setUndoActionName(actionName)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve Paste name when generating redo

The initial undo label is now restored after the paste loop, but undoing a multi-row paste executes each appendRow undo handler, which calls this method and changes the redo group's action name to Add Row. Consequently, after Undo Paste, the Edit menu presents the next action as “Redo Add Row” rather than “Redo Paste”; the enclosing paste group needs to retain or restore its name while its inverse actions are registered.

Useful? React with 👍 / 👎.

@datlechin

Copy link
Copy Markdown
Member Author

Addressed a code review of this PR. Findings and fixes:

  • Undo naming (both directions): the private undo mirrors (removeRow(suppressUndo:), reinsertRow, reinsertRows) never set the action name, so redo and every later undo degraded to a generic label. Threaded the action name through every registerUndo site, matching the DataChangeManager pattern.
  • Paste label clobber: appendRow()'s new naming overwrote the "Paste" group name during a paste. Re-assert setActionName("Paste") after the append loop.
  • Extracted the display→store insertion mapping into a testable InspectorRowInsertion helper (with tests), symlinked CSVDocument into the test target and added undo-naming tests, corrected the Edit-menu docs, and matched the plain-literal button style.

@datlechin
datlechin merged commit 858ab23 into main Jul 22, 2026
3 checks passed
@datlechin
datlechin deleted the feat/1469-csv-row-editing branch July 22, 2026 03:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant