Skip to content

Commit e470562

Browse files
committed
feat(deck): add embeddable Vue board web component
Expose nextcloud-deck-board through an opt-in loading event so other Nextcloud apps can reuse the existing board and card detail components. Isolate embedded stores, routing and sessions without changing the host URL or global session headers. Preserve active cards when opening archived card details and keep undo actions bound to their board instance. Co-authored-by: Copilot <copilot@github.com> GPT-6.1 Sol Signed-off-by: Stefan Lender <Stefan.Lender@dataport.de>
1 parent 34377b4 commit e470562

33 files changed

Lines changed: 1845 additions & 38 deletions

‎README.md‎

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,70 @@ which would increase the page loading time significantly.
4848

4949
Improvements on Nextcloud server and Deck itself will improve the situation.
5050

51+
## Embedding a Deck board in another Nextcloud app
52+
53+
Deck provides an opt-in `nextcloud-deck-board` custom element implemented as a
54+
Vue single-file component and registered with Vue's `defineCustomElement()`.
55+
It reuses the
56+
existing board UI without Deck's app navigation or browser-history router.
57+
The normal Deck app and the reference widgets keep their existing entry points.
58+
The element is intended for authenticated, same-instance Nextcloud pages.
59+
Existing Deck permissions apply to every API request; passing a board ID does
60+
not grant access or establish that the board belongs to a particular team.
61+
The host app must validate its own team-resource context.
62+
63+
Before rendering the host page, check that Deck is enabled for the current user
64+
and dispatch its loading event:
65+
66+
```php
67+
$eventDispatcher->dispatchTyped(new \OCA\Deck\Event\LoadBoardWebComponentEvent());
68+
```
69+
70+
This loads `deck-boardComponent`, the Deck styles, and the attachment/editor
71+
integrations. Do not load `deck-main` in the host page. Hosts supporting older
72+
Deck versions must check that the event class exists and show an explicit
73+
unavailable state when this integration is not supported.
74+
75+
```html
76+
<nextcloud-deck-board board-id="42" style="display: block; height: 100%">
77+
</nextcloud-deck-board>
78+
```
79+
80+
Wait for `customElements.whenDefined('nextcloud-deck-board')` before relying on
81+
the component. Vue hosts must configure this tag as a custom element. Give the
82+
element a bounded height; the board handles its own scrolling. The component
83+
uses light DOM to work with Nextcloud's shared styles, dialogs and viewer.
84+
When binding IDs from Vue, use `:board-id.attr="boardId"` and
85+
`:card-id.attr="cardId"` so a `null` card ID removes the attribute rather than
86+
being coerced into an empty or zero-valued DOM property.
87+
Vue manages the element's rendering, reactive attributes and lifecycle. Each
88+
element still mounts an isolated Deck app with its own stores and memory router;
89+
removing an element disposes that app after Vue's disconnection tick. Moving an
90+
element within the same document preserves its mounted instance.
91+
92+
- `board-id`: required positive safe integer. Changing it disposes the previous
93+
instance and opens the new board with independent state.
94+
- `card-id`: optional positive safe integer. Set it to open a card, or remove it
95+
to close card details. Cards must belong to the displayed board. Opening
96+
archived card details after the board has loaded preserves the current list
97+
view and its active cards.
98+
- `deck-ready`: the board and its lists have loaded; `detail` contains `boardId`.
99+
- `deck-error`: loading, navigation, or runtime failed; `detail` contains
100+
`boardId`, `message`, and `status` (HTTP status when available).
101+
- `deck-navigation`: user navigation requested a board/card; `detail` contains
102+
`boardId`, `cardId` (or `null`), and `tabId` (or `null`).
103+
104+
Events bubble. The component never changes the host's URL. The host owns its
105+
route and active navigation styling, and should mirror card navigation into
106+
`card-id`. Cross-board links emit a navigation request but do not change the
107+
embedded board; the host must check its context before changing `board-id`.
108+
Removing the element disposes its Vue app, stores, live-update subscriptions
109+
and session. The embedded sessions do not change global Axios session headers.
110+
111+
Board management/sharing sidebars and global Deck keyboard shortcuts are not
112+
part of this embed entry point. Board-level filtering, view modes, lists, card
113+
editing and card-detail tabs use the existing Deck components.
114+
51115
## Developing
52116

53117
There are multiple ways to develop on Deck. As you will need a Nextcloud server running, the individual options are described below.
@@ -100,6 +164,28 @@ You need to setup a [development environment](https://docs.nextcloud.com/server/
100164
After the finished installation, you can clone the deck project directly in the `/[nextcloud-docker-dev-dir]/workspace/server/apps/` folder.
101165

102166
### Running tests
167+
Run the frontend logic regression tests with `npm test -- --runInBand`.
168+
The embedded board's browser lifecycle, navigation, archive and undo behavior,
169+
and the existing non-interactive board reference entry point are tested in the Cypress E2E
170+
suite. With a running Nextcloud test instance (using the existing `admin`/`admin`
171+
test credentials), build the frontend and run:
172+
173+
```sh
174+
npm run dev
175+
npx cypress run --spec cypress/e2e/embeddedBoard.js
176+
```
177+
178+
The default test URL is `http://nextcloud.local/index.php`; set `CYPRESS_baseUrl`
179+
to use another instance. The spec creates its own user and boards and deletes
180+
the user afterwards. It swaps the normal Deck entry bundle for the embed or
181+
reference bundle in the browser, reusing the authenticated page's integrations
182+
without mounting the full Deck app.
183+
184+
Cypress runs in the existing E2E CI workflow. It does not collect JavaScript
185+
coverage; `npm run test:coverage -- --runInBand` measures the Jest logic tests
186+
only. The Codecov configuration enables project and patch coverage checks,
187+
but does not make Cypress E2E assertions a JavaScript coverage report.
188+
103189
You can use the provided Makefile to run all tests by using:
104190

105191
make test

0 commit comments

Comments
 (0)