Skip to content

feat(contexts): export and import menus and pages - #41

Open
rubenvdlinde wants to merge 1 commit into
stack/n2-application-overviewfrom
stack/n3-export-import
Open

rubenvdlinde wants to merge 1 commit into
stack/n2-application-overviewfrom
stack/n3-export-import

Conversation

@rubenvdlinde

Copy link
Copy Markdown
Collaborator

Rebuild of #27 on application pages (nextcloud#3075, see #13). Stacked on #40.

What changes

An exported application scheme now carries its menu and its pages with their widgets, so an application can move between instances with its pages and menu intact.

  • Export: pages is the page list of the page API (title, technical name, widgets with type, configuration, content and position). A data widget names its node by node_rel_id, the relation id of that node in the scheme's nodes, which carry the uuid. Menu items name tables and views by targetUuid, pages by targetPageId (the page's id in the scheme), parents by parentTechnicalName. A menu item whose target is gone is left out.
  • Import: the nodes are set first, then the pages, then the menu. The start page of the scheme fills the local start page, but only when the scheme arranged it on the grid (a widget that is not a table or view, or a position); a scheme that only lists tables leaves the start page to the nodes, as before. A grid page replaces the local page with the same technical name, or is added. A data widget whose table or view does not exist here, or that the importer cannot add to the application (no manage right), is left out with its place. A menu item that is invalid or whose target does not exist here or cannot be managed is skipped; a child whose parent was skipped moves to the top; a later item with a taken technical name gets a derived one.
  • Older schemes with gridViews: every grid view becomes a grid page, titled as the view, with its widgets placed as its layout placed them. A data widget's content.target (table or view by uuid) becomes its node. A menu item that opened the grid view opens that page; a node pointing at the grid view is not imported as a view.
  • Validation: the import request becomes a ContextScheme in the controller; a malformed scheme (no name, wrong types, tables without addTables/modifyTables, a page that is not an object, a grid view without uuid or title) is a 400 that never reaches the service. A BadRequestError (an invalid widget, for instance) or a missing page rolls the import back with a 400 or 404.
  • Dialog: the preview has a "Menu and pages" switch. On, the menu, the pages and any grid views of the file come along; pages only come along with the resources they show, since their data widgets name those nodes.
  • API: menuItems, pages and gridViews on POST /api/2/contexts/{id}/scheme/import (OpenAPI and TS types regenerated). The menu and page logic lives in a new ContextSchemeService.

Carried over from #27, and what changed because of pages

  • Carried over: menu export by uuid and parent technical name, skipping unusable items on import, derived technical names, ContextScheme::createFromInputArray, the controller's rollbacks, the dialog's switch, the service accessors that a test can replace.
  • Replaced: grid views by uuid. Pages are exported instead; an older scheme's grid views are converted to pages, not imported as views. feat(contexts): export and import menus and grid views聽#27 required a widget's rows to be readable; a page widget becomes a node of the application, so the import now requires the manage right a node needs (the same check as the page API).
  • Dropped: reusing or copying a grid view by uuid (pages have no uuid). Re-importing a scheme matches grid pages by technical name; a page without one is added again.

Tests

Nextcloud 34 container (PostgreSQL 16), one file per call:

  • tests/unit/Service/ContextSchemeServiceTest.php (new): OK (7 tests, 27 assertions): export by uuid and page id and skipping broken items; page targets and grid view targets mapped on import; taken technical names; start page filled only when arranged; page replaced by technical name and added otherwise; data widgets without a usable node left out; a grid view turned into a page.
  • tests/unit/Model/ContextSchemeTest.php (new): OK (12 tests, 31 assertions)
  • tests/unit/Service/ContextServiceTest.php: OK (36 tests, 120 assertions) (nodes, then pages, then menu; no pages or menu left alone; an empty menu clears it; the export carries pages and menu).
  • tests/unit/Controller/ContextControllerTest.php: OK (7 tests, 20 assertions) (malformed scheme 400 without the service, rollbacks with 400/500/404, menu, pages and grid views passed on).
  • Playwright at 1600 x 1000: a scheme imported through the dialog brings its menu (Dashboard, Front page, Cases, Handbook) and its pages, and the front page shows its header; with "Menu and pages" off the request has neither and the menu stays; an older scheme's grid view becomes a page with its header and data widget, its menu item opens it. 3 passed. tables-import-export-scheme.spec.ts: 2 passed.
  • composer cs:check clean, psalm No errors found!, composer openapi regenerated, npm run lint 0 errors (1 inherited warning in store.js), npm run stylelint clean.

Size: 1,413 changed lines without the generated OpenAPI files.

Prepared in the Conduction fork for porting upstream by @remko48. Prepared with Claude Code.

An exported application scheme now carries its menu and its pages with
their widgets, so an application moves between instances with its
pages and menu intact.

- Export: pages come as the page API returns them; data widgets name
  their node by its relation id in the scheme's nodes. Menu items name
  tables and views by uuid, pages by their id in the scheme and their
  parent by technical name. An item whose target is gone is left out.
- Import: pages come after the nodes, the menu after the pages. The start
  page is filled only when the scheme arranged it on the grid; a grid
  page replaces the page with the same technical name or is added. A data
  widget whose table or view does not exist here, or that the importer
  cannot add, is left out. A menu item that is invalid or whose target
  cannot be used is skipped; a child whose parent was skipped moves to
  the top.
- Older schemes: every grid view of the scheme becomes a grid page with
  its widgets in place, its data widgets pointing at their table or view
  as a node; a menu item that opened it opens that page, and its node is
  no longer imported as a view.
- Validation: the import request is validated into a ContextScheme in
  the controller; a malformed scheme is a 400, and every failure rolls
  the import back.
- Dialog: a "Menu and pages" switch in the preview brings both along;
  pages only come with the resources they show.
- API: menuItems, pages and gridViews on the import endpoint (OpenAPI
  and TS types regenerated).

Assisted-by: ClaudeCode:claude-opus-5-5
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