The insert-database modal called the public bridge /api/v1/tables route,
which requires a databaseId and a Baserow user JWT — the modal supplied
neither, so the request returned 400 then 501.
Add a step 0 to pick a workspace and database (auto-resolved when each
lists only one), then list tables via the admin endpoint
GET /api/v1/admin/tables?databaseId=X. The client extension is also
rewired to .extend() the shared DatabaseView node.
Resolve wikilinks to /s/<spaceSlug>/p/<slugId> via buildPageUrl instead of
the inexistent /page/<uuid> route. Persist slugId and spaceSlug as node
attributes so the URL can be rebuilt from the document alone, without an
extra lookup round-trip.
The client extension now .extend()s the shared WikilinkNode from
@docmost/editor-ext to keep the schema identical between client and the
Hocuspocus server.
Server: rows from kysely with camelCase plugin already arrive as
sourcePageId / targetPageId / spaceId / spaceName. Drop the snake_case
indexing and update the spec accordingly.
Client: remove the unreachable try/catch around React.lazy for
react-force-graph-2d — lazy() never throws synchronously, the catch
was dead code from an earlier wip.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The server-side TransformHttpResponseInterceptor wraps every body in
{ data, success, status }. The axios interceptor only unwraps the
transport layer, so calls return that envelope object — read .data
to get the actual payload.
Aligns the remaining Acadenice REST clients (backlinks, clipper,
slash-commands, sync-blocks, templates, graph, rbac) with the
existing convention and drops a few hardcoded /api/v1 prefixes that
duplicated the api baseURL.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds two new entry points around the bridge-backed database view:
- /database admin modal to manage fields (field-admin-modal)
- slash command to create a database from the editor
(create-database-modal + create-database-slash)
Wires the new components into the editor slash menu and the
database-view module index.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replace all @Controller('acadenice/...') decorators with 'v1/...' on 16 NestJS controllers. Update all client services, hooks, tests, extension-clipper, and doc comments to match. DB table names (acadenice_*) and folder structure untouched.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Patch 023 attempted to read process.env.VITE_BRIDGE_TOKEN, but the
vite.config.ts define block uses { 'process.env': {...} } which only
substitutes the literal expression 'process.env' standalone, not when
followed by a member access like 'process.env.X'. So the runtime call
evaluated to undefined and the bridge interceptor never sent a Bearer
header — every /database call got 401.
Switch to Vite's standard pattern: VITE_BRIDGE_TOKEN lives in
apps/client/.env.local (gitignored, must be created locally) and is
auto-exposed via import.meta.env. Verified: the dev server substitutes
it inline at transform time as 'brg_smoketest_admin'.
Patch 025.
The server applies a global TransformHttpResponseInterceptor that wraps
every response body in { data, success, status }. Native Docmost client
services use the api axios instance whose interceptor already unwraps
once, so callers see r.data === payload directly.
The acadenice client services use axios directly (no interceptor), so
r.data === { data, success, status } envelope. Calling templates.map()
on the envelope crashed <TemplatePickerModal> with 'templates.map is
not a function' — exact symptom Corentin hit (white screen on click).
Patched 4 services to read r.data.data: templates, sync-blocks,
slash-commands, clipper. The notifications service already uses the api
instance so it was untouched.
A future refactor should migrate all 4 to the shared api instance for
consistency and to inherit auth/redirect handling.
Patch 024.
The previous fix (Patch 021) read import.meta.env.VITE_BRIDGE_TOKEN, but
Vite only auto-exposes VITE_* in import.meta.env when the .env lives in
apps/client/. Our .env is at the monorepo root and is loaded via
loadEnv() in vite.config.ts, then injected through the define block
under the 'process.env' key. So the runtime variable lives at
process.env.VITE_BRIDGE_TOKEN, not import.meta.env.VITE_BRIDGE_TOKEN.
Without this, the bridge proxy received no Bearer header and returned
401 Unauthorized for every /database slash command request — exactly
what Corentin reported.
Patch 023.
Cross-origin (5173 vs 4000) blocked the auth cookie from reaching the
bridge — every /database slash command request 401'd silently. Two
changes:
1. vite.config.ts: add /bridge -> http://localhost:4000 proxy with
path rewrite + /bridge-events -> /api/events for SSE. Same-origin =
browser sends the auth cookie automatically.
2. bridge-client.ts: resolveBridgeUrl() defaults to /bridge instead
of absolute http://localhost:4000. Also adds a VITE_BRIDGE_TOKEN env
fallback for dev (the bridge requires Bearer auth and the Docmost
session cookie is HttpOnly so JS cannot read it).
Patch 021.
SpaceSidebar crashed with "Rendered more hooks than during the previous
render" because R3.6 added a useDisclosure() AFTER `if (!space) return`.
When `space` flipped from undefined (loading) to defined (loaded), the
hook count changed and React threw, triggering the Error Boundary and
blanking the page.
This single bug was the root cause of 5 reported failures (R4.7 smoke):
create page, sub-page, wikilink, /database, /template, /sync-block —
all blocked by the white screen.
Fix: hoist the hook above the conditional return. Hook order now stable.
Graph view was empty for users who built page hierarchies (sub-pages) but had
not placed any wikilinks. The graph service now queries pages.parent_page_id
as a second edge source (type: parent_child) and merges it with acadenice_backlink
edges, so hierarchy-only workspaces display meaningful graphs immediately.
- dto: added parent_child to LinkType enum; added slug field to GraphNode
- service: loadParentChildEdges (permission-filtered SQL), parallel merge with loadEdges
- controller: always appends parent_child to the effective type list
- client: graph-client.ts typed for parent_child and slug; graph-canvas renders
dashed grey lines for parent_child vs solid brand lines for wikilinks; legend
with aria-label; title/slug/untitled fallback chain for node labels
- space sidebar: Graph menu item -> /s/:spaceSlug/graph
- new route: /s/:spaceSlug/graph -> SpaceGraph page (injects spaceId filter)
- i18n: en-US + fr-FR keys for legend and space graph
- tests: 42 server + 59 client, all green; 10 new R4.6 tests
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Convert 17 server spec files from vitest to Jest (vi -> jest globals)
- Add jest.mock stubs for ESM-only prosemirror/html and collaboration modules
- Fix Zod v4 strict UUID validation failures in test fixtures (version byte [1-8] required)
- Add JwtAuthGuard.overrideGuard in all controller specs that lacked it
- Fix jest.Mock type inference (ReturnType<typeof jest.fn> -> jest.Mock) to prevent 'never' arg errors
- Delete vitest.config.ts (CJS), keep vitest.config.mts (ESM-compatible) on client
- Add global mocks for @excalidraw/excalidraw and @/main.tsx in client test-setup
- Result: client 38/38 suites 313/313 tests, server acadenice 21/21 suites 210/210 tests, 0 TS errors
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Bridges native Docmost mention notification pipeline (already active for
collab path) to the REST API path via NotificationEmitterService. Adds
AcadeniceNotificationsModule with mention detector, notification facade API,
preferences endpoint, /notifications full page, /settings/notifications
preferences page, and bell count polling (30s). No new DB migration —
native notifications table handles page.user_mention.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Custom bidirectional markdown converter (no new deps) with full round-trip
support for database-view, wikilink, mention nodes. DualEditor component wraps
PageEditor with a toolbar toggle (WYSIWYG<->markdown), lossy-switch modal, and
localStorage persistence per page. 77 tests covering 24 round-trip cases + 4
custom nodes + 9 edge cases. i18n FR+EN.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Minimal testid additions to 4 renderer files so Playwright can target
stable selectors: table-renderer, cell-{rowId}-{fieldName}, kanban-board,
kanban-column-{label}, kanban-card-{rowId}, calendar-renderer,
inline-editor-input, inline-editor-readonly.
Also adds Dockerfile.e2e for the client build used in docker-compose.e2e.yml.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Improve cmd-k / ctrl-k behavior
Use cmd-k on macOS/iOS for search and keep ctrl-k everywhere else.
Fixes a bug where ctrl-k on macOS, which cuts to the end of the line,
was also triggering the search prompt.
* comment submit: cmd-enter (mac) / ctrl-enter (win/linux)