diff --git a/public/images/blog/blog-tablepro-0-81-1-light-1408.avif b/public/images/blog/blog-tablepro-0-81-1-light-1408.avif new file mode 100644 index 00000000..f10bd0cc Binary files /dev/null and b/public/images/blog/blog-tablepro-0-81-1-light-1408.avif differ diff --git a/public/images/blog/blog-tablepro-0-81-1-light-1408.webp b/public/images/blog/blog-tablepro-0-81-1-light-1408.webp new file mode 100644 index 00000000..e9939801 Binary files /dev/null and b/public/images/blog/blog-tablepro-0-81-1-light-1408.webp differ diff --git a/public/images/blog/blog-tablepro-0-81-1-light-704.avif b/public/images/blog/blog-tablepro-0-81-1-light-704.avif new file mode 100644 index 00000000..92cf0de4 Binary files /dev/null and b/public/images/blog/blog-tablepro-0-81-1-light-704.avif differ diff --git a/public/images/blog/blog-tablepro-0-81-1-light-704.webp b/public/images/blog/blog-tablepro-0-81-1-light-704.webp new file mode 100644 index 00000000..24defad2 Binary files /dev/null and b/public/images/blog/blog-tablepro-0-81-1-light-704.webp differ diff --git a/public/images/blog/blog-tablepro-0-81-2-light-1408.avif b/public/images/blog/blog-tablepro-0-81-2-light-1408.avif new file mode 100644 index 00000000..b5445e8b Binary files /dev/null and b/public/images/blog/blog-tablepro-0-81-2-light-1408.avif differ diff --git a/public/images/blog/blog-tablepro-0-81-2-light-1408.webp b/public/images/blog/blog-tablepro-0-81-2-light-1408.webp new file mode 100644 index 00000000..c07f9469 Binary files /dev/null and b/public/images/blog/blog-tablepro-0-81-2-light-1408.webp differ diff --git a/public/images/blog/blog-tablepro-0-81-2-light-704.avif b/public/images/blog/blog-tablepro-0-81-2-light-704.avif new file mode 100644 index 00000000..6d2ba8ef Binary files /dev/null and b/public/images/blog/blog-tablepro-0-81-2-light-704.avif differ diff --git a/public/images/blog/blog-tablepro-0-81-2-light-704.webp b/public/images/blog/blog-tablepro-0-81-2-light-704.webp new file mode 100644 index 00000000..bcfc02fd Binary files /dev/null and b/public/images/blog/blog-tablepro-0-81-2-light-704.webp differ diff --git a/public/images/blog/blog-tablepro-0-81-3-light-1408.avif b/public/images/blog/blog-tablepro-0-81-3-light-1408.avif new file mode 100644 index 00000000..3833ecb2 Binary files /dev/null and b/public/images/blog/blog-tablepro-0-81-3-light-1408.avif differ diff --git a/public/images/blog/blog-tablepro-0-81-3-light-1408.webp b/public/images/blog/blog-tablepro-0-81-3-light-1408.webp new file mode 100644 index 00000000..749ae1e6 Binary files /dev/null and b/public/images/blog/blog-tablepro-0-81-3-light-1408.webp differ diff --git a/public/images/blog/blog-tablepro-0-81-3-light-704.avif b/public/images/blog/blog-tablepro-0-81-3-light-704.avif new file mode 100644 index 00000000..d73b84d1 Binary files /dev/null and b/public/images/blog/blog-tablepro-0-81-3-light-704.avif differ diff --git a/public/images/blog/blog-tablepro-0-81-3-light-704.webp b/public/images/blog/blog-tablepro-0-81-3-light-704.webp new file mode 100644 index 00000000..4130e469 Binary files /dev/null and b/public/images/blog/blog-tablepro-0-81-3-light-704.webp differ diff --git a/public/images/blog/connection-login-warning.png b/public/images/blog/connection-login-warning.png new file mode 100644 index 00000000..bd6f878a Binary files /dev/null and b/public/images/blog/connection-login-warning.png differ diff --git a/public/images/blog/connections-strip-database-tabs.png b/public/images/blog/connections-strip-database-tabs.png new file mode 100644 index 00000000..d05b61a3 Binary files /dev/null and b/public/images/blog/connections-strip-database-tabs.png differ diff --git a/public/images/blog/theme-dracula-content.png b/public/images/blog/theme-dracula-content.png new file mode 100644 index 00000000..7324797f Binary files /dev/null and b/public/images/blog/theme-dracula-content.png differ diff --git a/public/og/blog/tablepro-0-81.png b/public/og/blog/tablepro-0-81.png new file mode 100644 index 00000000..511b9fc4 Binary files /dev/null and b/public/og/blog/tablepro-0-81.png differ diff --git a/resources/blog/tablepro-0-81.md b/resources/blog/tablepro-0-81.md new file mode 100644 index 00000000..748558d5 --- /dev/null +++ b/resources/blog/tablepro-0-81.md @@ -0,0 +1,94 @@ +--- +slug: tablepro-0-81 +title: "TablePro 0.81: Tabs per Database, Firebase and Bigtable" +description: Each database on a connection keeps its own tabs, plugins for Firestore, Realtime Database and Bigtable, and themes that reach every content view. +date: 2026-10-16 +release: "TablePro 0.81" +author: TablePro Team +tags: [release, connections, oracle] +ogPunchline: Each database keeps its own tabs. Firebase and Bigtable connect. Themes reach every pane. +--- + +TablePro 0.81 is out: 126 changes, 67 of them fixes. + +The tab bar follows the database you're on, Firestore, Realtime Database and Bigtable connect through new plugins, and themes now color every content view. A few rarely used features are gone, and the security fixes make this a critical update. + + + +## Tabs per database + +With a database per tenant on one connection, every tab used to land in one strip, and two `orders` tabs looked the same. Now each database in the connections strip keeps its own tabs, and the tab bar shows the tabs of the one you're on. + +Switching database from the toolbar, the sidebar or **Open Database** brings back that database's last tab. Picking a tab of another database moves the sidebar there without changing the saved default. Query tabs stay on the database or schema they were opened in. + +On servers that switch schemas, such as Oracle, the query editor has a schema picker, so a query tab can point at another schema while the sidebar stays put. + +## Firebase and Bigtable + +Two new registry plugins, both contributed by [@i87ce](https://github.com/i87ce). Pick one in **Choose a Database** and TablePro offers the download before the form opens. + +- **Cloud Firestore and Firebase Realtime Database** share one plugin. Sign in with a service account key, Application Default Credentials or the emulators. A Firestore collection is a table, a document is a row, and subcollections show as collection groups such as `*/orders` +- **Google Cloud Bigtable** works over the REST API. Rows show `_key` first and one column per `family:qualifier`, and a filter on `_key` reads only that key range + +Neither has SQL. The editor takes request lines instead, such as `GET users/alice` in Firestore. + +## Themes reach every pane + +A theme now colors the editor, the data grid, JSON trees, diffs, ER diagrams and charts, while controls and Settings keep the system look. It can also set the window background, which the sidebar, inspector and toolbar take on in macOS 26 and later. + + + +**Settings > Appearance** has a **Light theme** and a **Dark theme** picker, plus **New Theme Based On**, **Rename** and **Show in Finder** for custom themes. Default Light and Default Dark use the system colors and Xcode's default syntax colors. + +**Themes made for 0.80 and earlier don't load.** Recreate a custom theme with **New Theme Based On**. Fonts left the theme file too: **Editor Font** is in **Settings > Editor** and **Data Grid Font** in **Settings > Data**. + +## Oracle password warnings + +An Oracle account in its password grace period used to time out after 30 seconds. It connects now, with a banner showing the server's warning. **Test Connection** shows it too. + + + +## Removed + +- **Plugins signed by other developers no longer load.** Every registry plugin is signed by TablePro +- **HTML and XML export are gone** +- **The Cursor AI provider is gone**, and xAI needs an API key instead of Sign in with xAI. Cursor still reaches TablePro through MCP +- **Every MCP request needs a token**, including one from this Mac +- Server-Side Export for Oracle, Snowflake and BigQuery. Run the unload statement in a query tab +- Export as SQL in the ER diagram, PostgreSQL enum label editing, the Server Dashboard for SQLite and DuckDB, and per-kind notification toggles + +## Security + +- MCP, pairing and query link prompts no longer take focus from the app you're typing in, and Return denies instead of approving +- A pre-connect script asks before it runs when MCP, AppleScript, the AI assistant, Compare or Copy To opens the connection +- Import and Transfer To go through Safe Mode's confirmation, Touch ID and the audit log + +That's why 0.81 is marked critical: the update alert comes up right away, without Skip or Remind Me Later. + +## Also new + +- Updates download as a delta from any of the last five releases. From 0.80 that's 14 MB on Apple silicon instead of a 32 MB zip +- The `tablepro` command ships inside the app, and **Settings > General** shows the Terminal line that links it. No administrator prompt +- The MCP server runs only while **Enable MCP Server** is on +- A setting in **Settings > General** hides the version and **Check for Updates** on the Welcome window, by [@RaffeYang](https://github.com/RaffeYang) +- AI chat scrolls without stutter and follows a reply as it streams + +## Fixes worth knowing about + +- Clearing a date, number or boolean cell saved an empty string instead of NULL, which MySQL stored as `0000-00-00 00:00:00` +- MySQL dumps failed to restore on zero dates or `ANSI_QUOTES`, and shifted `TIMESTAMP` values across time zones +- **Show DDL** on a view printed a made-up `CREATE TABLE` on SQL Server, Oracle, Dameng, DuckDB, Redshift and Cassandra +- On iPhone and iPad, a query with more than one statement ran only the first + +## What it will not do + +- Firestore and Realtime Database have no live listeners. A grid shows what was read until you refresh it +- Bigtable has no GoogleSQL and no reverse scans +- PostgreSQL schemas inside one database stay one entry in the connections strip +- An old theme has no converter. It has to be made again + +## Getting it + +TablePro checks for updates on its own, or choose **TablePro > Check for Updates…**, or download it from [tablepro.app](https://tablepro.app). + +The Oracle, Cassandra, Cloudflare D1, Dameng, DuckDB, DynamoDB, Elasticsearch, SAP HANA, libSQL, MongoDB, MSSQL, Spanner, Teradata, Trino and Typesense drivers have updates in **Settings > Plugins**. diff --git a/resources/data/assets.json b/resources/data/assets.json index 293c9996..be49d862 100644 --- a/resources/data/assets.json +++ b/resources/data/assets.json @@ -10909,6 +10909,165 @@ "/images/blog/connection-custom-icons.png" ] }, + "blog-tablepro-0-81-1": { + "kind": "figure", + "type": "screenshot", + "family": "blog", + "ownerRepo": "web", + "slot": true, + "handoffPriority": "P3", + "usedOn": [ + { + "path": "/blog/tablepro-0-81", + "section": "figure-1" + } + ], + "aspect": "2400:1600", + "priority": false, + "theme": "single", + "locale": "shared", + "mobile": null, + "description": { + "en": "A MySQL connection with two databases in the connections strip, tenant_b selected, and only its orders and customers tabs in the tab bar.", + "vi": null + }, + "alt": { + "en": "TablePro main window with the connections strip on the left listing Tenants tenant_a and Tenants tenant_b, tenant_b selected, the toolbar showing the Tenants connection and the tenant_b database, a tab bar with orders and customers tabs, and the orders table open with two rows for Umbrella and Hooli", + "vi": null + }, + "caption": { + "en": "The tab bar shows only tenant_b's tabs. tenant_a keeps its own until you switch back.", + "vi": null + }, + "replacement": { + "dir": "public/images/blog", + "base": "blog-tablepro-0-81-1" + }, + "status": "supplied", + "src": { + "light": { + "widths": [ + 704, + 1408 + ], + "formats": [ + "avif", + "webp" + ], + "width": 1408, + "height": 938 + } + }, + "legacySource": [ + "/images/blog/connections-strip-database-tabs.png" + ] + }, + "blog-tablepro-0-81-2": { + "kind": "figure", + "type": "screenshot", + "family": "blog", + "ownerRepo": "web", + "slot": true, + "handoffPriority": "P3", + "usedOn": [ + { + "path": "/blog/tablepro-0-81", + "section": "figure-2" + } + ], + "aspect": "3024:1722", + "priority": false, + "theme": "single", + "locale": "shared", + "mobile": null, + "description": { + "en": "A query tab under the Dracula theme, with the editor, tab bar and result grid in the theme's colors.", + "vi": null + }, + "alt": { + "en": "TablePro main window in dark mode under the Dracula theme, with a SELECT on the Chinook Track table highlighted in pink, cyan and yellow, the editor and result grid in the theme's dark purple-grey, and the sidebar listing the sample database's tables", + "vi": null + }, + "caption": { + "en": "Dracula colors the editor and the result grid. The sidebar, toolbar and controls keep the system look.", + "vi": null + }, + "replacement": { + "dir": "public/images/blog", + "base": "blog-tablepro-0-81-2" + }, + "status": "supplied", + "src": { + "light": { + "widths": [ + 704, + 1408 + ], + "formats": [ + "avif", + "webp" + ], + "width": 1408, + "height": 801 + } + }, + "legacySource": [ + "/images/blog/theme-dracula-content.png" + ] + }, + "blog-tablepro-0-81-3": { + "kind": "figure", + "type": "screenshot", + "family": "blog", + "ownerRepo": "web", + "slot": true, + "handoffPriority": "P3", + "usedOn": [ + { + "path": "/blog/tablepro-0-81", + "section": "figure-3" + } + ], + "aspect": "2200:1240", + "priority": false, + "theme": "single", + "locale": "shared", + "mobile": null, + "description": { + "en": "An Oracle connection open with a yellow banner showing the server's password expiry warning.", + "vi": null + }, + "alt": { + "en": "TablePro main window connected to an Oracle 23ai database, with a yellow banner reading Connected with a warning and ORA-28098 saying the password will expire within 7 days, the schema list in the sidebar, and No tabs open in the main area", + "vi": null + }, + "caption": { + "en": "An Oracle password in its grace period connects, and the server's warning shows above the tabs.", + "vi": null + }, + "replacement": { + "dir": "public/images/blog", + "base": "blog-tablepro-0-81-3" + }, + "status": "supplied", + "src": { + "light": { + "widths": [ + 704, + 1408 + ], + "formats": [ + "avif", + "webp" + ], + "width": 1408, + "height": 793 + } + }, + "legacySource": [ + "/images/blog/connection-login-warning.png" + ] + }, "blog-tablepro-for-iphone-1": { "kind": "phone", "type": "screenshot-phone", diff --git a/resources/js/lib/data/asset-locales/de.json b/resources/js/lib/data/asset-locales/de.json index 74b0e7e7..5f77de73 100644 --- a/resources/js/lib/data/asset-locales/de.json +++ b/resources/js/lib/data/asset-locales/de.json @@ -952,6 +952,30 @@ "en": "Three connections to the same server, told apart by their icons." } }, + "blog-tablepro-0-81-1": { + "alt": { + "en": "TablePro main window with the connections strip on the left listing Tenants tenant_a and Tenants tenant_b, tenant_b selected, the toolbar showing the Tenants connection and the tenant_b database, a tab bar with orders and customers tabs, and the orders table open with two rows for Umbrella and Hooli" + }, + "caption": { + "en": "The tab bar shows only tenant_b's tabs. tenant_a keeps its own until you switch back." + } + }, + "blog-tablepro-0-81-2": { + "alt": { + "en": "TablePro main window in dark mode under the Dracula theme, with a SELECT on the Chinook Track table highlighted in pink, cyan and yellow, the editor and result grid in the theme's dark purple-grey, and the sidebar listing the sample database's tables" + }, + "caption": { + "en": "Dracula colors the editor and the result grid. The sidebar, toolbar and controls keep the system look." + } + }, + "blog-tablepro-0-81-3": { + "alt": { + "en": "TablePro main window connected to an Oracle 23ai database, with a yellow banner reading Connected with a warning and ORA-28098 saying the password will expire within 7 days, the schema list in the sidebar, and No tabs open in the main area" + }, + "caption": { + "en": "An Oracle password in its grace period connects, and the server's warning shows above the tabs." + } + }, "blog-tablepro-for-iphone-1": { "alt": { "en": "The Chinook Track table open in TablePro on iPhone, listing TrackId, Name, AlbumId and MediaTypeId for the first rows, with a pager reading 1-100 of 3503 and Tables, Query, History and Info along the bottom" diff --git a/resources/js/lib/data/asset-locales/en.json b/resources/js/lib/data/asset-locales/en.json index d166947b..ffed1c53 100644 --- a/resources/js/lib/data/asset-locales/en.json +++ b/resources/js/lib/data/asset-locales/en.json @@ -952,6 +952,30 @@ "en": "Three connections to the same server, told apart by their icons." } }, + "blog-tablepro-0-81-1": { + "alt": { + "en": "TablePro main window with the connections strip on the left listing Tenants tenant_a and Tenants tenant_b, tenant_b selected, the toolbar showing the Tenants connection and the tenant_b database, a tab bar with orders and customers tabs, and the orders table open with two rows for Umbrella and Hooli" + }, + "caption": { + "en": "The tab bar shows only tenant_b's tabs. tenant_a keeps its own until you switch back." + } + }, + "blog-tablepro-0-81-2": { + "alt": { + "en": "TablePro main window in dark mode under the Dracula theme, with a SELECT on the Chinook Track table highlighted in pink, cyan and yellow, the editor and result grid in the theme's dark purple-grey, and the sidebar listing the sample database's tables" + }, + "caption": { + "en": "Dracula colors the editor and the result grid. The sidebar, toolbar and controls keep the system look." + } + }, + "blog-tablepro-0-81-3": { + "alt": { + "en": "TablePro main window connected to an Oracle 23ai database, with a yellow banner reading Connected with a warning and ORA-28098 saying the password will expire within 7 days, the schema list in the sidebar, and No tabs open in the main area" + }, + "caption": { + "en": "An Oracle password in its grace period connects, and the server's warning shows above the tabs." + } + }, "blog-tablepro-for-iphone-1": { "alt": { "en": "The Chinook Track table open in TablePro on iPhone, listing TrackId, Name, AlbumId and MediaTypeId for the first rows, with a pager reading 1-100 of 3503 and Tables, Query, History and Info along the bottom" diff --git a/resources/js/lib/data/asset-locales/es.json b/resources/js/lib/data/asset-locales/es.json index b515cde1..dc6de284 100644 --- a/resources/js/lib/data/asset-locales/es.json +++ b/resources/js/lib/data/asset-locales/es.json @@ -952,6 +952,30 @@ "en": "Three connections to the same server, told apart by their icons." } }, + "blog-tablepro-0-81-1": { + "alt": { + "en": "TablePro main window with the connections strip on the left listing Tenants tenant_a and Tenants tenant_b, tenant_b selected, the toolbar showing the Tenants connection and the tenant_b database, a tab bar with orders and customers tabs, and the orders table open with two rows for Umbrella and Hooli" + }, + "caption": { + "en": "The tab bar shows only tenant_b's tabs. tenant_a keeps its own until you switch back." + } + }, + "blog-tablepro-0-81-2": { + "alt": { + "en": "TablePro main window in dark mode under the Dracula theme, with a SELECT on the Chinook Track table highlighted in pink, cyan and yellow, the editor and result grid in the theme's dark purple-grey, and the sidebar listing the sample database's tables" + }, + "caption": { + "en": "Dracula colors the editor and the result grid. The sidebar, toolbar and controls keep the system look." + } + }, + "blog-tablepro-0-81-3": { + "alt": { + "en": "TablePro main window connected to an Oracle 23ai database, with a yellow banner reading Connected with a warning and ORA-28098 saying the password will expire within 7 days, the schema list in the sidebar, and No tabs open in the main area" + }, + "caption": { + "en": "An Oracle password in its grace period connects, and the server's warning shows above the tabs." + } + }, "blog-tablepro-for-iphone-1": { "alt": { "en": "The Chinook Track table open in TablePro on iPhone, listing TrackId, Name, AlbumId and MediaTypeId for the first rows, with a pager reading 1-100 of 3503 and Tables, Query, History and Info along the bottom" diff --git a/resources/js/lib/data/asset-locales/fr.json b/resources/js/lib/data/asset-locales/fr.json index cae0683d..fac69701 100644 --- a/resources/js/lib/data/asset-locales/fr.json +++ b/resources/js/lib/data/asset-locales/fr.json @@ -952,6 +952,30 @@ "en": "Three connections to the same server, told apart by their icons." } }, + "blog-tablepro-0-81-1": { + "alt": { + "en": "TablePro main window with the connections strip on the left listing Tenants tenant_a and Tenants tenant_b, tenant_b selected, the toolbar showing the Tenants connection and the tenant_b database, a tab bar with orders and customers tabs, and the orders table open with two rows for Umbrella and Hooli" + }, + "caption": { + "en": "The tab bar shows only tenant_b's tabs. tenant_a keeps its own until you switch back." + } + }, + "blog-tablepro-0-81-2": { + "alt": { + "en": "TablePro main window in dark mode under the Dracula theme, with a SELECT on the Chinook Track table highlighted in pink, cyan and yellow, the editor and result grid in the theme's dark purple-grey, and the sidebar listing the sample database's tables" + }, + "caption": { + "en": "Dracula colors the editor and the result grid. The sidebar, toolbar and controls keep the system look." + } + }, + "blog-tablepro-0-81-3": { + "alt": { + "en": "TablePro main window connected to an Oracle 23ai database, with a yellow banner reading Connected with a warning and ORA-28098 saying the password will expire within 7 days, the schema list in the sidebar, and No tabs open in the main area" + }, + "caption": { + "en": "An Oracle password in its grace period connects, and the server's warning shows above the tabs." + } + }, "blog-tablepro-for-iphone-1": { "alt": { "en": "The Chinook Track table open in TablePro on iPhone, listing TrackId, Name, AlbumId and MediaTypeId for the first rows, with a pager reading 1-100 of 3503 and Tables, Query, History and Info along the bottom" diff --git a/resources/js/lib/data/asset-locales/id.json b/resources/js/lib/data/asset-locales/id.json index b347f715..3145f2cf 100644 --- a/resources/js/lib/data/asset-locales/id.json +++ b/resources/js/lib/data/asset-locales/id.json @@ -952,6 +952,30 @@ "en": "Three connections to the same server, told apart by their icons." } }, + "blog-tablepro-0-81-1": { + "alt": { + "en": "TablePro main window with the connections strip on the left listing Tenants tenant_a and Tenants tenant_b, tenant_b selected, the toolbar showing the Tenants connection and the tenant_b database, a tab bar with orders and customers tabs, and the orders table open with two rows for Umbrella and Hooli" + }, + "caption": { + "en": "The tab bar shows only tenant_b's tabs. tenant_a keeps its own until you switch back." + } + }, + "blog-tablepro-0-81-2": { + "alt": { + "en": "TablePro main window in dark mode under the Dracula theme, with a SELECT on the Chinook Track table highlighted in pink, cyan and yellow, the editor and result grid in the theme's dark purple-grey, and the sidebar listing the sample database's tables" + }, + "caption": { + "en": "Dracula colors the editor and the result grid. The sidebar, toolbar and controls keep the system look." + } + }, + "blog-tablepro-0-81-3": { + "alt": { + "en": "TablePro main window connected to an Oracle 23ai database, with a yellow banner reading Connected with a warning and ORA-28098 saying the password will expire within 7 days, the schema list in the sidebar, and No tabs open in the main area" + }, + "caption": { + "en": "An Oracle password in its grace period connects, and the server's warning shows above the tabs." + } + }, "blog-tablepro-for-iphone-1": { "alt": { "en": "The Chinook Track table open in TablePro on iPhone, listing TrackId, Name, AlbumId and MediaTypeId for the first rows, with a pager reading 1-100 of 3503 and Tables, Query, History and Info along the bottom" diff --git a/resources/js/lib/data/asset-locales/it.json b/resources/js/lib/data/asset-locales/it.json index a890bec5..de160f30 100644 --- a/resources/js/lib/data/asset-locales/it.json +++ b/resources/js/lib/data/asset-locales/it.json @@ -952,6 +952,30 @@ "en": "Three connections to the same server, told apart by their icons." } }, + "blog-tablepro-0-81-1": { + "alt": { + "en": "TablePro main window with the connections strip on the left listing Tenants tenant_a and Tenants tenant_b, tenant_b selected, the toolbar showing the Tenants connection and the tenant_b database, a tab bar with orders and customers tabs, and the orders table open with two rows for Umbrella and Hooli" + }, + "caption": { + "en": "The tab bar shows only tenant_b's tabs. tenant_a keeps its own until you switch back." + } + }, + "blog-tablepro-0-81-2": { + "alt": { + "en": "TablePro main window in dark mode under the Dracula theme, with a SELECT on the Chinook Track table highlighted in pink, cyan and yellow, the editor and result grid in the theme's dark purple-grey, and the sidebar listing the sample database's tables" + }, + "caption": { + "en": "Dracula colors the editor and the result grid. The sidebar, toolbar and controls keep the system look." + } + }, + "blog-tablepro-0-81-3": { + "alt": { + "en": "TablePro main window connected to an Oracle 23ai database, with a yellow banner reading Connected with a warning and ORA-28098 saying the password will expire within 7 days, the schema list in the sidebar, and No tabs open in the main area" + }, + "caption": { + "en": "An Oracle password in its grace period connects, and the server's warning shows above the tabs." + } + }, "blog-tablepro-for-iphone-1": { "alt": { "en": "The Chinook Track table open in TablePro on iPhone, listing TrackId, Name, AlbumId and MediaTypeId for the first rows, with a pager reading 1-100 of 3503 and Tables, Query, History and Info along the bottom" diff --git a/resources/js/lib/data/asset-locales/ja.json b/resources/js/lib/data/asset-locales/ja.json index 33fd86a5..ef7141ab 100644 --- a/resources/js/lib/data/asset-locales/ja.json +++ b/resources/js/lib/data/asset-locales/ja.json @@ -952,6 +952,30 @@ "en": "Three connections to the same server, told apart by their icons." } }, + "blog-tablepro-0-81-1": { + "alt": { + "en": "TablePro main window with the connections strip on the left listing Tenants tenant_a and Tenants tenant_b, tenant_b selected, the toolbar showing the Tenants connection and the tenant_b database, a tab bar with orders and customers tabs, and the orders table open with two rows for Umbrella and Hooli" + }, + "caption": { + "en": "The tab bar shows only tenant_b's tabs. tenant_a keeps its own until you switch back." + } + }, + "blog-tablepro-0-81-2": { + "alt": { + "en": "TablePro main window in dark mode under the Dracula theme, with a SELECT on the Chinook Track table highlighted in pink, cyan and yellow, the editor and result grid in the theme's dark purple-grey, and the sidebar listing the sample database's tables" + }, + "caption": { + "en": "Dracula colors the editor and the result grid. The sidebar, toolbar and controls keep the system look." + } + }, + "blog-tablepro-0-81-3": { + "alt": { + "en": "TablePro main window connected to an Oracle 23ai database, with a yellow banner reading Connected with a warning and ORA-28098 saying the password will expire within 7 days, the schema list in the sidebar, and No tabs open in the main area" + }, + "caption": { + "en": "An Oracle password in its grace period connects, and the server's warning shows above the tabs." + } + }, "blog-tablepro-for-iphone-1": { "alt": { "en": "The Chinook Track table open in TablePro on iPhone, listing TrackId, Name, AlbumId and MediaTypeId for the first rows, with a pager reading 1-100 of 3503 and Tables, Query, History and Info along the bottom" diff --git a/resources/js/lib/data/asset-locales/ko.json b/resources/js/lib/data/asset-locales/ko.json index 00f9a42c..56cb98ce 100644 --- a/resources/js/lib/data/asset-locales/ko.json +++ b/resources/js/lib/data/asset-locales/ko.json @@ -952,6 +952,30 @@ "en": "Three connections to the same server, told apart by their icons." } }, + "blog-tablepro-0-81-1": { + "alt": { + "en": "TablePro main window with the connections strip on the left listing Tenants tenant_a and Tenants tenant_b, tenant_b selected, the toolbar showing the Tenants connection and the tenant_b database, a tab bar with orders and customers tabs, and the orders table open with two rows for Umbrella and Hooli" + }, + "caption": { + "en": "The tab bar shows only tenant_b's tabs. tenant_a keeps its own until you switch back." + } + }, + "blog-tablepro-0-81-2": { + "alt": { + "en": "TablePro main window in dark mode under the Dracula theme, with a SELECT on the Chinook Track table highlighted in pink, cyan and yellow, the editor and result grid in the theme's dark purple-grey, and the sidebar listing the sample database's tables" + }, + "caption": { + "en": "Dracula colors the editor and the result grid. The sidebar, toolbar and controls keep the system look." + } + }, + "blog-tablepro-0-81-3": { + "alt": { + "en": "TablePro main window connected to an Oracle 23ai database, with a yellow banner reading Connected with a warning and ORA-28098 saying the password will expire within 7 days, the schema list in the sidebar, and No tabs open in the main area" + }, + "caption": { + "en": "An Oracle password in its grace period connects, and the server's warning shows above the tabs." + } + }, "blog-tablepro-for-iphone-1": { "alt": { "en": "The Chinook Track table open in TablePro on iPhone, listing TrackId, Name, AlbumId and MediaTypeId for the first rows, with a pager reading 1-100 of 3503 and Tables, Query, History and Info along the bottom" diff --git a/resources/js/lib/data/asset-locales/pt-BR.json b/resources/js/lib/data/asset-locales/pt-BR.json index 0b6ee775..d8fe38b8 100644 --- a/resources/js/lib/data/asset-locales/pt-BR.json +++ b/resources/js/lib/data/asset-locales/pt-BR.json @@ -952,6 +952,30 @@ "en": "Three connections to the same server, told apart by their icons." } }, + "blog-tablepro-0-81-1": { + "alt": { + "en": "TablePro main window with the connections strip on the left listing Tenants tenant_a and Tenants tenant_b, tenant_b selected, the toolbar showing the Tenants connection and the tenant_b database, a tab bar with orders and customers tabs, and the orders table open with two rows for Umbrella and Hooli" + }, + "caption": { + "en": "The tab bar shows only tenant_b's tabs. tenant_a keeps its own until you switch back." + } + }, + "blog-tablepro-0-81-2": { + "alt": { + "en": "TablePro main window in dark mode under the Dracula theme, with a SELECT on the Chinook Track table highlighted in pink, cyan and yellow, the editor and result grid in the theme's dark purple-grey, and the sidebar listing the sample database's tables" + }, + "caption": { + "en": "Dracula colors the editor and the result grid. The sidebar, toolbar and controls keep the system look." + } + }, + "blog-tablepro-0-81-3": { + "alt": { + "en": "TablePro main window connected to an Oracle 23ai database, with a yellow banner reading Connected with a warning and ORA-28098 saying the password will expire within 7 days, the schema list in the sidebar, and No tabs open in the main area" + }, + "caption": { + "en": "An Oracle password in its grace period connects, and the server's warning shows above the tabs." + } + }, "blog-tablepro-for-iphone-1": { "alt": { "en": "The Chinook Track table open in TablePro on iPhone, listing TrackId, Name, AlbumId and MediaTypeId for the first rows, with a pager reading 1-100 of 3503 and Tables, Query, History and Info along the bottom" diff --git a/resources/js/lib/data/asset-locales/vi.json b/resources/js/lib/data/asset-locales/vi.json index 72257eed..32ae2ece 100644 --- a/resources/js/lib/data/asset-locales/vi.json +++ b/resources/js/lib/data/asset-locales/vi.json @@ -952,6 +952,30 @@ "en": "Three connections to the same server, told apart by their icons." } }, + "blog-tablepro-0-81-1": { + "alt": { + "en": "TablePro main window with the connections strip on the left listing Tenants tenant_a and Tenants tenant_b, tenant_b selected, the toolbar showing the Tenants connection and the tenant_b database, a tab bar with orders and customers tabs, and the orders table open with two rows for Umbrella and Hooli" + }, + "caption": { + "en": "The tab bar shows only tenant_b's tabs. tenant_a keeps its own until you switch back." + } + }, + "blog-tablepro-0-81-2": { + "alt": { + "en": "TablePro main window in dark mode under the Dracula theme, with a SELECT on the Chinook Track table highlighted in pink, cyan and yellow, the editor and result grid in the theme's dark purple-grey, and the sidebar listing the sample database's tables" + }, + "caption": { + "en": "Dracula colors the editor and the result grid. The sidebar, toolbar and controls keep the system look." + } + }, + "blog-tablepro-0-81-3": { + "alt": { + "en": "TablePro main window connected to an Oracle 23ai database, with a yellow banner reading Connected with a warning and ORA-28098 saying the password will expire within 7 days, the schema list in the sidebar, and No tabs open in the main area" + }, + "caption": { + "en": "An Oracle password in its grace period connects, and the server's warning shows above the tabs." + } + }, "blog-tablepro-for-iphone-1": { "alt": { "en": "The Chinook Track table open in TablePro on iPhone, listing TrackId, Name, AlbumId and MediaTypeId for the first rows, with a pager reading 1-100 of 3503 and Tables, Query, History and Info along the bottom" diff --git a/resources/js/lib/data/asset-locales/zh-Hans.json b/resources/js/lib/data/asset-locales/zh-Hans.json index 2f978663..061f190e 100644 --- a/resources/js/lib/data/asset-locales/zh-Hans.json +++ b/resources/js/lib/data/asset-locales/zh-Hans.json @@ -952,6 +952,30 @@ "en": "Three connections to the same server, told apart by their icons." } }, + "blog-tablepro-0-81-1": { + "alt": { + "en": "TablePro main window with the connections strip on the left listing Tenants tenant_a and Tenants tenant_b, tenant_b selected, the toolbar showing the Tenants connection and the tenant_b database, a tab bar with orders and customers tabs, and the orders table open with two rows for Umbrella and Hooli" + }, + "caption": { + "en": "The tab bar shows only tenant_b's tabs. tenant_a keeps its own until you switch back." + } + }, + "blog-tablepro-0-81-2": { + "alt": { + "en": "TablePro main window in dark mode under the Dracula theme, with a SELECT on the Chinook Track table highlighted in pink, cyan and yellow, the editor and result grid in the theme's dark purple-grey, and the sidebar listing the sample database's tables" + }, + "caption": { + "en": "Dracula colors the editor and the result grid. The sidebar, toolbar and controls keep the system look." + } + }, + "blog-tablepro-0-81-3": { + "alt": { + "en": "TablePro main window connected to an Oracle 23ai database, with a yellow banner reading Connected with a warning and ORA-28098 saying the password will expire within 7 days, the schema list in the sidebar, and No tabs open in the main area" + }, + "caption": { + "en": "An Oracle password in its grace period connects, and the server's warning shows above the tabs." + } + }, "blog-tablepro-for-iphone-1": { "alt": { "en": "The Chinook Track table open in TablePro on iPhone, listing TrackId, Name, AlbumId and MediaTypeId for the first rows, with a pager reading 1-100 of 3503 and Tables, Query, History and Info along the bottom" diff --git a/resources/js/lib/data/asset-locales/zh-Hant.json b/resources/js/lib/data/asset-locales/zh-Hant.json index 7f86bdca..d3b2ee3a 100644 --- a/resources/js/lib/data/asset-locales/zh-Hant.json +++ b/resources/js/lib/data/asset-locales/zh-Hant.json @@ -952,6 +952,30 @@ "en": "Three connections to the same server, told apart by their icons." } }, + "blog-tablepro-0-81-1": { + "alt": { + "en": "TablePro main window with the connections strip on the left listing Tenants tenant_a and Tenants tenant_b, tenant_b selected, the toolbar showing the Tenants connection and the tenant_b database, a tab bar with orders and customers tabs, and the orders table open with two rows for Umbrella and Hooli" + }, + "caption": { + "en": "The tab bar shows only tenant_b's tabs. tenant_a keeps its own until you switch back." + } + }, + "blog-tablepro-0-81-2": { + "alt": { + "en": "TablePro main window in dark mode under the Dracula theme, with a SELECT on the Chinook Track table highlighted in pink, cyan and yellow, the editor and result grid in the theme's dark purple-grey, and the sidebar listing the sample database's tables" + }, + "caption": { + "en": "Dracula colors the editor and the result grid. The sidebar, toolbar and controls keep the system look." + } + }, + "blog-tablepro-0-81-3": { + "alt": { + "en": "TablePro main window connected to an Oracle 23ai database, with a yellow banner reading Connected with a warning and ORA-28098 saying the password will expire within 7 days, the schema list in the sidebar, and No tabs open in the main area" + }, + "caption": { + "en": "An Oracle password in its grace period connects, and the server's warning shows above the tabs." + } + }, "blog-tablepro-for-iphone-1": { "alt": { "en": "The Chinook Track table open in TablePro on iPhone, listing TrackId, Name, AlbumId and MediaTypeId for the first rows, with a pager reading 1-100 of 3503 and Tables, Query, History and Info along the bottom" diff --git a/resources/js/lib/data/asset-slots.json b/resources/js/lib/data/asset-slots.json index 89c267bb..56a0ae85 100644 --- a/resources/js/lib/data/asset-slots.json +++ b/resources/js/lib/data/asset-slots.json @@ -5249,6 +5249,93 @@ "base": "blog-tablepro-0-80-4" } }, + "blog-tablepro-0-81-1": { + "kind": "figure", + "type": "screenshot", + "slot": true, + "aspect": "2400:1600", + "priority": false, + "theme": "single", + "locale": "shared", + "mobile": null, + "status": "supplied", + "src": { + "light": { + "widths": [ + 704, + 1408 + ], + "formats": [ + "avif", + "webp" + ], + "width": 1408, + "height": 938 + } + }, + "replacement": { + "dir": "public/images/blog", + "base": "blog-tablepro-0-81-1" + } + }, + "blog-tablepro-0-81-2": { + "kind": "figure", + "type": "screenshot", + "slot": true, + "aspect": "3024:1722", + "priority": false, + "theme": "single", + "locale": "shared", + "mobile": null, + "status": "supplied", + "src": { + "light": { + "widths": [ + 704, + 1408 + ], + "formats": [ + "avif", + "webp" + ], + "width": 1408, + "height": 801 + } + }, + "replacement": { + "dir": "public/images/blog", + "base": "blog-tablepro-0-81-2" + } + }, + "blog-tablepro-0-81-3": { + "kind": "figure", + "type": "screenshot", + "slot": true, + "aspect": "2200:1240", + "priority": false, + "theme": "single", + "locale": "shared", + "mobile": null, + "status": "supplied", + "src": { + "light": { + "widths": [ + 704, + 1408 + ], + "formats": [ + "avif", + "webp" + ], + "width": 1408, + "height": 793 + } + }, + "replacement": { + "dir": "public/images/blog", + "base": "blog-tablepro-0-81-3" + } + }, "blog-tablepro-for-iphone-1": { "kind": "phone", "type": "screenshot-phone", diff --git a/tests/Feature/Landing/BlogTest.php b/tests/Feature/Landing/BlogTest.php index 62aac93a..7b05ddf8 100644 --- a/tests/Feature/Landing/BlogTest.php +++ b/tests/Feature/Landing/BlogTest.php @@ -25,6 +25,7 @@ // A post keeps the date it was published; an edit never re-dates it. const BLOG_PUBLISHED = [ + 'tablepro-0-81' => '2026-10-16', 'tablepro-0-80' => '2026-10-11', 'tablepro-0-77' => '2026-10-02', 'tablepro-0-76' => '2026-09-28', @@ -129,7 +130,7 @@ function blogSlotIds(string $html): array ->where('posts.0.url', '/blog/' . $expected[0]) ->where('posts.0.locale', 'en') ->where('posts.0.date', BLOG_PUBLISHED[$expected[0]]) - ->where('posts.0.dateFormatted', 'October 11, 2026') + ->where('posts.0.dateFormatted', 'October 16, 2026') ->where('posts', fn($posts): bool => collect($posts)->every( fn(array $post): bool => $post['kind'] === (array_key_exists($post['slug'], BLOG_GUIDES) ? 'guide' : 'release'), ))); @@ -443,14 +444,14 @@ function blogSlotIds(string $html): array ->where('seo.alternates', fn($alternates): bool => collect($alternates)->pluck('hreflang')->all() === ['en', 'vi']) ->missing('content.seo.indexable') ->has('posts', count(BLOG_GUIDES) + count(BLOG_PUBLISHED)) - ->where('posts', fn($posts): bool => collect($posts)->slice(1, $guides)->every( + ->where('posts', fn($posts): bool => collect($posts)->slice(2, $guides)->every( fn(array $post): bool => $post['kind'] === 'guide' && $post['locale'] === 'vi' && $post['url'] === "/vi/blog/{$post['slug']}", )) - ->where('posts.0.slug', 'tablepro-0-80') + ->where('posts.0.slug', 'tablepro-0-81') ->where('posts.0.locale', 'en') - ->where('posts.0.url', '/blog/tablepro-0-80') - ->where('posts.0.title', blogMatter('tablepro-0-80')['title']) - ->where('posts.0.dateFormatted', '11 tháng 10 năm 2026') + ->where('posts.0.url', '/blog/tablepro-0-81') + ->where('posts.0.title', blogMatter('tablepro-0-81')['title']) + ->where('posts.0.dateFormatted', '16 tháng 10 năm 2026') ->where('localization.switcher.0.href', '/blog')); expect($response->getContent())->toContain('