Skip to content

feat(contexts): give applications a menu - #3135

Open
rubenvdlinde wants to merge 2 commits into
feat/noid/grid-pages-apifrom
feat/noid/app-menu-model
Open

rubenvdlinde wants to merge 2 commits into
feat/noid/grid-pages-apifrom
feat/noid/app-menu-model

Conversation

@rubenvdlinde

@rubenvdlinde rubenvdlinde commented Oct 22, 2026 •

Copy link
Copy Markdown

Part of #3099, on top of #3133. #3099 gives every application a menu: inside Tables it's what the page bar designs, and when the application is opened on its own, it's the navigation. This pull request adds the menu to the data model and to the application's responses. Saving a menu follows in the next pull request.

This replaces #3086 by @remko48, rebuilt on the page model from #3100. He's co-author of the commits that reuse his code.

Size: 1033 lines: 457 code, 478 tests and 98 generated OpenAPI.

What changes

  • A menu item has a label, an optional icon and description, and opens one of four things: a table, a view, a page of the same application, or a link.
  • Each item has a technical name, unique within its application. Without one it gets item_<id>, the same way pages, views and columns get theirs. item_<number> is reserved for those automatic names.
  • An item can sit under another item, one level deep. The column is here; saving nested menus follows in feat(contexts): nest menu items one level deep #3137.
  • An item whose target is gone is marked as broken when it's read. That covers a deleted table or view, a deleted page, a page of another application, and a table or view the reader can't open. Tables and views in the menu are part of the application, so everyone it's shared with can normally open them.
  • Application responses carry their menu, loaded for all applications in a response in one query. Where menus aren't loaded, like the navigation bar or the permission lookup, the field is left out; it's optional in the OpenAPI spec.
  • Deleting an application deletes its menu. The application row is now deleted first, inside a retried transaction, so on SQLite it holds the write lock before it reads. Deleting its shares no longer swallows database errors, so the retry actually happens.

How it was tested

On Nextcloud 34 with PostgreSQL:

  • MenuItemTest and MenuItemMapperTest (database: broken targets, one query for all menus, the unique technical name)
  • ContextServiceTest, including that deleting an application removes the application row first
  • findAllContainingNode compares application ids as numbers and doesn't load menus it doesn't need
  • a menu item a sharee can't open is broken for them, not for the owner
  • a transient database error during delete is retried
  • the full unit suite on the top of the stack (feat(contexts): carry the menu through export and import #3138), on PostgreSQL and SQLite: 665 tests
  • composer cs:check, psalm and rector, all clean

🖼️ Screenshots

Backend only, no UI changes.

🏁 Checklist

  • ⛑️ Tests (unit and/or integration) are included or not needed
  • 🔙 Backport requests are created or not needed: /backport to stableX.X
  • 📅 Milestone is set
  • 🌸 PR title is meaningful (if it should be in the changelog: is it meaningful to users?)

🤖 AI (if applicable)

  • The content of this PR was partly or fully generated using AI

rubenvdlinde and others added 2 commits October 26, 2026 10:24
A menu item has a label, an optional icon and description, and opens a
table, a view, a page of the same application or a link. Items have a
technical name unique within the application (item_<id> by default)
and may sit under another item. An item whose target is gone is read
as broken. Applications carry their menu in their responses, loaded
for all applications of a response in one query.

Deleting an application deletes its menu, and deletes the application
row first inside a retried transaction.

Co-authored-by: remko48 <remko@conduction.nl>
Assisted-by: ClaudeCode:claude-opus-5-5
Signed-off-by: Ruben van der Linde <ruben@conduction.nl>
Assisted-by: ClaudeCode:claude-opus-5-5
Signed-off-by: Ruben van der Linde <ruben@conduction.nl>
@rubenvdlinde
rubenvdlinde force-pushed the feat/noid/app-menu-model branch from 7e236cc to c7a6e95 Compare October 26, 2026 09:24
@rubenvdlinde
rubenvdlinde marked this pull request as ready for review October 26, 2026 09:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants