Commit Graph

77 Commits

Author SHA1 Message Date
vvzvlad 3903e2b823 Merge pull request 'perf(client): срезать фоновые ре-рендеры и дубли (#344)' (#360) from perf/344-background-rerenders into develop
Reviewed-on: #360
2026-07-10 07:03:35 +03:00
agent_coder 1bcc96685e perf(client): cut background re-renders + duplicate work (#344)
Outside the editor the UI did background work on every tree event, socket
reconnect, and navigation. Tree infra (virtualization/memo/O(N) utils) was
already good — the cost was in the subscriptions and duplicates around it.
Client-only; behavior 1:1.

- Setter-only atom subscriptions → useSetAtom: space-tree-row, use-tree-mutation,
  use-tree-socket no longer subscribe every visible row to the WHOLE treeDataAtom
  value (a tree event re-rendered all ~20-30 rows, bypassing the DocTreeRow memo).
  space-tree-node-menu / mention-list read the tree imperatively (store.get) in
  their handlers only. breadcrumb.tsx uses a selectAtom slice (ancestor chain +
  field equality) instead of the whole-tree subscription.
- Socket handler cleanup (BUG): use-tree-socket + use-query-subscription now
  socket.off() their named handlers on cleanup (were accumulating listeners on
  every reconnect → duplicated invalidations/tree-walks). Mirrors
  use-notification-socket.
- Field-update tree path: invalidateOnUpdatePage does a pointwise patch of the
  cached embed subtrees instead of a blanket invalidatePageTree() (refetch storm);
  structural events keep the blanket invalidate.
- usePageMetaQuery: a content-less select slice for the 13 peripheral subscribers
  that read only title/permissions/id, so they stop re-rendering every ~3s while
  typing / on every collab page.updated (page.tsx keeps the full query for content).
- page.tsx: skeleton + placeholderData keepPreviousData (no blank flash on nav).
- Removed refetchOnMount:true where socket/mutation invalidation already keeps the
  cache fresh (favorite/space/space-watcher/workspace). KEPT it on the 3 queries
  with NO other freshness path (trash-list, created-by, recent-changes) — the
  global default is refetchOnMount:false, so those overrides are load-bearing.
- Small: resize mousemove/up attached only while dragging; per-row emoji-picker
  keydown gated on `opened`; AiChatWindow queries enabled only when the window is
  open.

Gate: client tsc 0, client vitest page+websocket 200 passed (+editor suites),
build ok.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 04:37:35 +03:00
agent_coder 456a91d289 fix(#342 review F1-F4): chunk-load error boundary + non-blocking posthog + tests
- F1 [HIGH]: added a root ChunkLoadErrorBoundary (react-error-boundary) wrapping
  the routed app in main.tsx, ABOVE all the route-level/Aside/AiChatWindow
  Suspense boundaries. A stale-deploy chunk 404 (React.lazy reject) is caught and
  auto-reloads once (sessionStorage-guarded against a reload loop), else shows a
  manual "new version available" reload UI — instead of unmounting the whole tree
  to a white screen. Existing per-feature ErrorBoundaries untouched.
- F2 [MED-HIGH]: posthog no longer blocks/blanks the cloud first paint. main.tsx
  now renders <App/> immediately for everyone, then `void initAnalytics()` — which
  keeps the exact cloud gate, dynamically imports posthog, and RE-RENDERS the same
  React root wrapped in PostHogProvider (React reconciles onto the painted DOM, so
  cloud ends up wrapped exactly as before). The import+init is try/catch'd: a
  failed analytics chunk (network / stale-404 / ad-blocker on a "posthog" chunk)
  degrades to no-analytics instead of a permanently blank page.
- F3: sanitize-url.test.ts mirroring editor-ext's security contract (javascript:/
  data:/vbscript:/obfuscated → ""; https/relative/mailto preserved).
- F4: the idle-warm `void import(...)` prefetch in layout.tsx gets `.catch(()=>{})`
  so a failed best-effort prefetch can't surface as an unhandledrejection.

No new deps (lockfile unchanged). Gate: client tsc 0, sanitize test 3/3, client
build succeeds (entry chunk still 556K, posthog in separate dynamic chunks).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-06 04:18:29 +03:00
agent_coder 515c08afed perf(client): route + component code-splitting — eager JS 3.5MB -> 1.12MB (#342)
Everything sat in the eager startup graph (App.tsx statically imported all 28
routes; the editor pulled TipTap + KaTeX + ~45 lowlight grammars + drawio;
posthog + AI SDK loaded for everyone) — a /login visitor downloaded+compiled the
whole editor. Client-only; functionality 1:1, only WHEN code loads changed.

Result (prod build): eager JS 3.5MB -> ~1.12MB, entry 1920KB -> 552KB; KaTeX
(250KB) and the TipTap engine (~586KB) are now lazy chunks, off the startup path.

- App.tsx: route-level React.lazy + Suspense (editor Page, all settings/*, share,
  space/home routes). Auth/redirect/cold-start routes stay eager. Suspense lives
  inside Layout/ShareLayout around the Outlet so the shell stays mounted.
- Lazy KaTeX node views (math-inline-lazy/math-block-lazy) + lazy drawio
  (drawio-view-lazy/drawio-menu-lazy), mirroring mermaid/excalidraw, each with a
  node-sized Suspense placeholder so a slow chunk can't crash the editor.
- posthog-js is now a conditional dynamic import under the unchanged
  isCloud() && isPostHogEnabled gate — self-hosted never downloads it.
- AiChatWindow is React.lazy, mounted on first open and kept mounted (a live AI
  stream isn't torn down); renders null while closed (identical behavior).
- Cut eager TipTap pulls from always-loaded shell modules: editor-atoms /
  global-bridge Editor -> import type; Aside lazily loaded (page routes only);
  config.ts sanitizeUrl and use-clipboard execCommandCopy moved to client-local
  src/lib/{sanitize-url,copy-to-clipboard}.ts (byte-identical to the editor-ext
  originals, dropping the barrel's top-level @tiptap import); WebSocketStatus
  import replaced with the "connected" literal the status atom already stores.
- vite.config.ts: a vendor-katex chunk group (TipTap/PM/Yjs intentionally NOT
  grouped — grouping dragged the engine eager; documented in the config).
- lowlight grammar registration is left inside the (now-lazy) editor chunk:
  listLanguages()/highlighting are synchronous, so deferring registration would
  change behavior for marginal in-chunk gain — the route split already removes it
  from startup, which was the complaint.

Gate: client build succeeds, tsc --noEmit clean, frozen install EXIT 0 (added
@braintree/sanitize-url as a direct client dep + regenerated the lock).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-06 04:18:29 +03:00
agent_coder 731a4f0dca refactor(#292 review): extract NAVBAR_COLLAPSE_BREAKPOINT constant (F2)
The AppShell navbar breakpoint and both burger toggles' hiddenFrom/visibleFrom
must be equal, or the sidebar becomes unreachable on tablet widths (the round-1
regression). A comment guarded that before; now a shared const does. Add
NAVBAR_COLLAPSE_BREAKPOINT='md' to sidebar-atom.ts and reference it from the navbar
breakpoint (global-app-shell) + both toggles (app-header). aside.breakpoint and the
sm brand/search gates are intentionally separate contracts, left untouched.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 22:02:37 +03:00
claude-stand fa439d7c7b fix(ui): match sidebar toggle breakpoint to navbar (md) so the tablet drawer opens
Follow-up to the navbar sm->md change on this branch: the two header sidebar
toggles were still gated at sm, so in the 768-991 band the DESKTOP toggle was
shown while the navbar used the MOBILE drawer collapse state — clicking it
flipped the wrong atom and the drawer could not be opened (sidebar unreachable
at 768/820, caught by QA). Gate the mobile toggle hiddenFrom=md and the desktop
toggle visibleFrom=md so the mobile toggle drives the drawer across the whole
tablet band.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 18:19:59 +03:00
claude-stand affa32cbaa fix(ui): collapse global sidebar to a drawer below 992px (tablet layout overflow)
At tablet widths (~768px) the fixed ~300px global sidebar stayed pinned, leaving
too little room for content: the settings tables (Members etc.) overflowed the
offset content area and pushed the Role/actions columns off-screen with no
horizontal scroll (unreachable). Raise the AppShell navbar (and page aside)
breakpoint from `sm` (768px) to `md` (992px) so the whole tablet band uses the
toggle drawer (closed by default) and content gets the full width.

Verified with Playwright screenshots: 768px settings/members now fits all columns
(table right 736<768, no overflow); desktop (>=992px) unchanged (sidebar pinned,
content offset); mobile unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 16:28:03 +03:00
agent_coder 85b303e387 feat(ai-chat): dock the floating chat window into the sidebar (closes #276)
Drag the floating AI-chat window onto the sidebar and release over it to DOCK it
— the window pins to the live navbar rect, overlaying the page tree; a drop-zone
highlight shows while dragging over it. Closing the chat re-shows the tree.
Undock via a header button or by dragging the docked window back onto content
(pops out floating at the drop point). The docked/floating mode persists in
localStorage and the docked window follows the navbar width (manual resize,
space<->shared route change) via a ResizeObserver + sidebar-toggle/transitionend
re-sync; when the navbar is collapsed/absent the window falls back to floating
instead of vanishing. Dock/undock only flips a mode atom + geometry — ChatThread
is never remounted, so an in-flight response stream is not interrupted.
Frontend only.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 01:57:00 +03:00
claude code agent 227 7a7aa79eab feat(ai-chat): auto-open last chat bound to the document (#191)
On opening the floating AI-chat window from the header on a document page,
auto-open the LAST chat bound to that document. Binding reuses the existing
ai_chats.page_id (no migration): the bound chat is the requesting user's
most-recent non-deleted chat created on that page, so a new chat on the page
becomes the bound one for free. Resolution happens only on a genuine
closed -> open transition; the provenance badge deep-link is untouched.

Server: AiChatRepo.findLatestByPage + POST /ai-chat/bound-chat (BoundChatDto),
both read-only and owner/workspace-scoped.
Client: getBoundChat service + useOpenAiChatForCurrentPage hook wired into the
app-header entry point (fail-soft to a fresh chat; draft/role cleared only on a
real switch).
Tests: repo scoping/ordering, controller wiring, and hook behavior.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 21:01:38 +03:00
claude_code 7884dc2e1a feat(editor): add gitmost bridge for listing spaces/pages and creating a page with a recording
Extend the window.gitmost native-host bridge with three methods that work
when no page is open, registered globally at the app-shell level (not in
page-editor.tsx) so the react-router navigate fn and the api-client are
available:

- listSpaces(): reuse getSpaces() -> [{id, name}], flags truncation.
- listPages({spaceId, parentPageId?}): reuse getSidebarPages()
  -> [{id, title, hasChildren}], first page only (truncated flag).
- createPageWithRecording({spaceId, parentPageId?, title?, base64,
  filename, mimeType}): validate/decode the audio first (so a bad payload
  leaves no junk page), resolve the space slug via getSpaceById (no-space
  probe), createPage(), navigate via the router (no reload), wait for the
  new page's editor to be mounted+editable+Yjs-connected, then run the same
  uploadAudioAction path as insertRecording. Resolve-only error contract:
  no-space | create-failed | editor-timeout | insert-failed.

DRY: extract the base64 decode/validate + audio-insert pipeline from
page-editor.tsx into features/editor/gitmost/gitmost-recording.ts; the
existing insertRecording now delegates to it (behavior unchanged).

Mount GitmostGlobalBridge once in GlobalAppShell. Before navigating, reset
the shared yjsConnectionStatusAtom so the readiness gate waits for the NEW
page's provider to connect instead of a stale "connected" from a previously
open page.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 03:51:17 +03:00
claude_code d21e1430b0 refactor(ui): replace star icon with message icon in app header 2026-06-23 01:25:48 +03:00
claude_code c53ce35312 feat(ui): swap AI-chat and comments icons to avoid confusion
The AI chat button used IconSparkles and the page comments button used
IconMessage, which read as visually similar speech bubbles. Replace the
AI icon with IconMessageCircleStar (chat bubble + star) and the comments
icon with IconMessages (overlapping bubbles) so the two are clearly
distinct.

- app-header.tsx: IconSparkles -> IconMessageCircleStar
- page-header-menu.tsx: IconMessage -> IconMessages
2026-06-22 20:34:39 +03:00
claude_code b60190ff1e style(dashboard): make home page container responsive padding
Adjust AppShell padding to responsive values and add a CSS module that
handles container top and side padding for different breakpoints,
replacing the previous fixed `pt="xl"` usage.
2026-06-22 03:27:40 +03:00
claude_code 8f994460ad refactor(comments): tidy comments panel header and quote layout
- Merge the comments side-panel header into the Open/Resolved tab row,
  then drop the now-redundant "Comments" title; the panel keeps its
  accessible name via the AppShell.Aside aria-label.
- Overlay the close (X) button on the right of the tab row and nudge it
  up 4px to align with the tab labels; the tab list stays full-width so
  its bottom border line is preserved. The toc/details tabs keep their
  existing shared header and scroll area unchanged.
- Quote block (.textSelection): increase top margin (2px -> 8px) so it
  no longer sticks to the timestamp when it is the first block, and add
  margin-left: 6px so the quote's left bar lines up with the comment
  body text left edge.
2026-06-22 02:12:13 +03:00
claude_code c83343d3a3 refactor(comments): move panel title and close button into the tabs row
Merge the comments side-panel header into the Open/Resolved tab row to
save vertical space: title on the left, tabs centered, close button on
the right.

- comment-list-with-tabs: add optional `title`/`onClose` props; render
  the title and close button as absolutely-positioned overlays around a
  full-width centered Tabs.List. Keeping them outside Tabs.List preserves
  the tablist ARIA contract (only role="tab" children) while the tab
  list's full-width bottom border line is retained.
- aside: pass `title`/`onClose` to CommentListWithTabs for the comments
  tab and drop the shared header for that tab; the toc/details tabs keep
  their existing shared header and scroll area unchanged.
2026-06-22 00:37:53 +03:00
claude_code 4f035b8e19 feat(client): declutter space sidebar and global header
- Remove the large active-space name header in the space sidebar;
  the active space stays highlighted in the spaces grid below.
- Move "Space settings" into the user avatar (top) menu next to
  "Workspace settings"; it shows only while viewing a space and is
  detected via useMatch("/s/:spaceSlug/*").
- Make the brand logo non-selectable/non-draggable (user-select:none
  on .brand, draggable=false on the img).
- Remove the redundant "Home" button next to the logo (the logo
  already links to /home).
- Remove the version label under the Settings sidebar menu.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 23:50:30 +03:00
claude_code ebfb947ba2 style(comments): tighten aside panel spacing and widen it
- Widen the comments/aside panel from 350 to 420 (~20% wider)
- Remove double padding around the panel: AppShell.Aside p="md"->"sm"
  and inner Box p="md"->p={0}; reduce header-to-tabs gap mb="md"->"sm"
- Reduce empty space below the add-comment input (paddingBottom 25->10),
  align the avatar with the input box (marginTop 10->2) and re-anchor the
  send button (bottom 30->15)
- Pull the timestamp closer to the nickname via tighter line-height
  (lh 1.2 on the name, 1.1 on the "… ago" text)
2026-06-21 23:09:11 +03:00
vvzvlad 8178d21c00 fix(client): glue version string to logo on the app header baseline
Wrap the logo link and the APP_VERSION text into a single bottom-aligned
Group so they read as one lockup ("gitmost v0.9..."). Move the version
styling into a new .brandVersion CSS class: shrink it from 12px to 10px,
keep the dimmed color and selectability, and lift it via margin-bottom so
its text baseline sits on the wordmark baseline of the 30px desktop logo
(derived from the logo SVG geometry). Drop the redundant lh prop.
2026-06-18 20:13:46 +03:00
vvzvlad 8f5be58f9b feat(ai-chat): move AI chat icon into the global top bar
Move the AI-chat toggle icon (IconSparkles) from the page header menu
into the global top bar, placed next to the notifications icon. The
"AI chat enabled" gate (workspace.settings.ai.chat) is preserved, and
the icon style is aligned with the neighbouring notifications icon
(subtle, size sm). As a result the entry point is now available on all
routes instead of only on page routes.

- app-header.tsx: render the gated AI-chat ActionIcon before
  NotificationPopover; wire it to aiChatWindowOpenAtom.
- page-header-menu.tsx: remove the old AI icon block and its now-unused
  imports/locals.
2026-06-18 17:50:42 +03:00
vvzvlad a0a8d3c97f feat(client): show git-describe version next to the brand logo
Display the app version (output of `git describe --tags`) in the header
beside the gitmost logo: a clean tag renders as `vX.Y.Z`, otherwise the
tag plus commits-since and short hash (e.g. v0.90.1-56-g25975acd).

- vite.config.ts: resolve APP_VERSION from env (Docker/CI) -> git describe
  (local) -> package.json version fallback
- app-header.tsx: render APP_VERSION after the brand block (ml="md"),
  nudge the Home nav group (ml={50} -> "xl")
- Dockerfile: accept APP_VERSION build-arg in the builder stage (.git is
  excluded from the build context)
- CI: pass APP_VERSION build-arg — release.yml uses the tag, develop.yml
  computes git describe with fetch-depth: 0
- nx.json: add APP_VERSION to the build target inputs so the cache
  invalidates when the version changes
2026-06-18 04:51:21 +03:00
vvzvlad 4f6b667cf7 feat(brand): roll out Gitmost logo, favicon and app name
Replace the bare brand text on pages with the Gitmost logo lockup
(mark + "gitmost" wordmark) and use the mark as the favicon.

- add generated logo lockups (text outlined from Space Grotesk SemiBold)
  in dark/light ink variants; add reusable theme-aware <BrandLogo> component
- use BrandLogo in the global header (mark-only on mobile, full lockup on
  desktop) and on auth pages, dropping the old Docmost icon + plain text
- point favicon to /brand/gitmost-favicon.svg (SVG primary + PNG fallbacks);
  regenerate favicon/app-icon PNGs from the brand SVGs
- rename app name Docmost -> Gitmost (getAppName, index.html title/apple
  title, manifest name); use getAppName() in the 404 title
- align theme/background colors to the brand tile (#0E1117)
- move brand guide and logos into docs/brand/ (canonical home) with a README,
  and serve runtime copies from apps/client/public/brand/
2026-06-18 00:12:26 +03:00
vvzvlad 7609538f9c feat(ai-chat): convert AI chat from aside panel to floating window
Replace the docked right-aside AI chat with a floating, draggable,
resizable, minimizable window per the GitmostAgent design. The "AI chat"
entry points (page header menu, page-history item) now open the window
instead of the aside tab.

- Add ai-chat-window.tsx + ai-chat-window.module.css: fixed-position
  window with viewport-clamped drag, CSS resize, minimize (hides body
  via CSS so ChatThread/useChat stays mounted and streaming is not
  aborted), and geometry kept in state (survives close/reopen, re-clamped
  on open via useLayoutEffect, size tracked with a ResizeObserver).
- Reuse ChatThread, ConversationList and the transcript components
  unchanged; move all orchestration (active chat, adopt-new-chat,
  openPage, queries) into the window.
- Header shows a tokens-only badge: sum of persisted metadata.usage for
  the active chat (no cost/context-total data available), hidden at 0.
- Add aiChatWindowOpenAtom; mount the window once in global-app-shell.
- Remove the aside "ai-chat" tab handling and delete ai-chat-panel.tsx.
- Type IAiChatMessageRow.metadata.usage; add "Minimize" and
  "Tokens used in this chat" i18n keys.
2026-06-17 17:11:01 +03:00
vvzvlad 44b340dc1a feat(ai-chat): agent write tools, provenance wiring, chat panel + provider settings UI" -m "Backend:
- Add reversible write tools to the per-user agent toolset (page create/update/
  move/soft-delete; comment reply + resolve), exposed under the user's JWT and
  enforced by Docmost CASL; no permanent/force delete (D3).
- Non-spoofable agent provenance: sign actor/aiChatId into the access and collab
  tokens (TokenService), propagate via jwt.strategy onto the request, and set
  pages.last_updated_source/last_updated_ai_chat_id on REST create/update/move and
  comments.created_source/resolved_source/ai_chat_id.
- packages/mcp: add an optional getCollabToken provider (content-edit provenance)
  and guard against empty tokens; service-account /mcp path unchanged.

Frontend:
- Admin 'AI / Models' settings section: provider/model/embedding/base URL, a
  write-only API key field, system prompt, and Test connection.
- AI chat panel (useChat + DefaultChatTransport): conversation list, streamed
  messages, tool-call action log and page citations; header entry point gated on
  settings.ai.chat.

Compile-verified (server nest build + client tsc/vite); not yet live-tested.
Known gaps: history 'AI agent' badge (C3), vector RAG (D), external MCP (E);
chat tool-card citation links pending a fix.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 02:39:26 +03:00
vvzvlad 422912afb8 chore(fork): rebrand logo text from Docmost to Gitmost
Update the app logo name (sidebar header and login page), including
the image alt and aria-label, from "Docmost" to "Gitmost".
2026-06-16 23:00:32 +03:00
vvzvlad a88b3f776c feat(fork)!: remove all frontend Enterprise-Edition code (community build)
Strip the proprietary client EE so the fork ships a clean community/AGPL
edition, mirroring Forkmost. Delete apps/client/src/ee (201 files) and
packages/ee, and patch every consumer that imported from @/ee/*.

- gate-out EE features (useHasFeature -> false): API keys, SSO, MFA, SCIM,
  audit logs, AI / AI-chat, templates, page permissions, page verification,
  comment resolution, trash retention, viewer comments
- drop cloud/billing/trial/entitlement/posthog flows; sign-in is now
  email+password only (no SSO/LDAP/cloud)
- remove EE routes from App.tsx and EE entries from sidebars/settings nav
- restore the community page-share button (ShareModal) that the EE
  PageShareModal used to provide
- remove the dead "Attachments" search filter, dead MFA navigation and
  orphaned route constants

Client type-checks clean; full `pnpm build` is green for all three projects.
2026-06-16 22:32:44 +03:00
Philip Okugbe 6191acfa14 fix: a11y (#2275) 2026-06-09 22:51:55 +01:00
Philip Okugbe 92c0e36e46 fix(a11y): WCAG 2.1 AA fixes (#2219) 2026-05-20 16:47:25 +01:00
Philip Okugbe 6cf8101ab3 feat(ee): templates (#2215)
* feat(ee): templates
* fix tree
* fix
2026-05-19 02:41:52 +01:00
Peter Tripp 932c1ad5b7 Better trash (#2190)
* Better trash

I recently lost a bunch of time editing and searching for pages that were actually in the Trash. Docmost intentionally tries to not link to Trashed pages, but the url of that Trashed page and any inbound links still work.  This makes it clearer when a page you are interacting with is in the Trash.

- /trash
  - Refactored banner into `trash-banner.tsx`
  - Refactored "Restore" modal into `use-restore-page-modal.tsx`
- Page (when isDeleted)
  - Add: `trash-banner.tsx`
  - Add breadcrumbs: `Parent / Child / Page (Deleted)`
  - Change: Deleted Pages are read-only
  - Replace "Move to Trash" with "Restore" in page menu (invokes `use-restore-page-modal`)

I tried very hard to keep this simple and re-use existing translation strings wherever possible.

* cleanup

---------

Co-authored-by: Philipinho <16838612+Philipinho@users.noreply.github.com>
2026-05-14 14:41:10 +01:00
Philip Okugbe 537e45bc11 feat: page details section and backlinks (#2186)
* feat: page details section and backlinks
2026-05-09 17:03:08 +01:00
Philip Okugbe bdc369fce0 feat(editor): fixed toolbar preference (#2185)
* feat(editor): fixed toolbar preference

* remove key

* cleanup translation strings

* update axios
2026-05-09 13:27:03 +01:00
Philip Okugbe dbe6c2d6ba feat: A11y fixes (#2148) 2026-05-04 21:21:37 +01:00
Philip Okugbe 641ce142df feat(ee): SCIM (#1347)
* SCIM - init (EE)

* accept db transaction

* sync

* Content parser support for scim+json

* patch scimmy

* sync

* return early if userIds is empty

* sync

* SCIM db table

* fixes

* scim tokens

* backfill

* feat(audit): add scim token events

* rename scim migration

* fix

* fix translation

* cleanup
2026-05-01 14:53:30 +01:00
Philip Okugbe a3a9f35005 fix home flickers (#2108) 2026-04-13 23:54:03 +01:00
Philip Okugbe d42091ccb1 feat: favorites (#2103)
* feat: favorites and templates(ee)

* rename migrations

* fix sidebar

* cleanup tabs

* fix

* turn off templates

* cleanup

* uuid validation
2026-04-12 22:06:25 +01:00
Philip Okugbe 57efb91bd3 feat(ee): ai chat (#2098)
* feat: ai chat

* feat: ai chat

* sync

* cleanup

* view space button
2026-04-10 19:23:47 +01:00
Philipinho d5e4b8bb59 fix ui 2026-03-01 20:58:04 +00:00
Philip Okugbe 05b3c65b0f feat: notifications (#1947)
* feat: notifications
* feat: watchers

* improvements

* handle page move for watchers

* make watchers non-blocking

* more
2026-02-14 20:00:38 -08:00
Philip Okugbe 1280f96f37 feat: implement space and workspace icons (#1558)
* feat: implement space and workspace icons
- Create reusable AvatarUploader component supporting avatars, space icons, and workspace icons
- Add Sharp package for server-side image resizing and optimization
- Create reusable AvatarUploader component supporting avatars, space icons, and workspace icons
- Support removing icons

* add workspace logo support
- add upload loader
- add white background to transparent image
- other fixes and enhancements

* dark mode

* fixes

* cleanup
2025-09-15 21:11:37 +01:00
Philip Okugbe f12866cf42 feat(EE): full-text search in attachments (#1502)
* feat(EE): fulltext search in attachments

* feat: global search
- search filters
- attachments search ui
- and more

* fix import

* fix import

* rename migration

* add GIN index

* fix table name

* sanitize
2025-09-02 05:27:01 +01:00
Philip Okugbe ca9558b246 feat(EE): resolve comments (#1420)
* feat: resolve comment (EE)

* Add resolve to comment mark in editor (EE)

* comment ui permissions

* sticky comment state tabs (EE)

* cleanup

* feat: add space_id to comments and allow space admins to delete any comment

- Add space_id column to comments table with data migration from pages
- Add last_edited_by_id, resolved_by_id, and updated_at columns to comments
- Update comment deletion permissions to allow space admins to delete any comment
- Backfill space_id on old comments

* fix foreign keys
2025-07-29 21:36:48 +01:00
Philip Okugbe b30bf61dc4 feat: home space list (#1400) 2025-07-25 00:21:40 +01:00
Philip Okugbe 44e592763d feat: quick theme toggle and Mantine 8 upgrade (#1369)
* upgrade to mantine v8

* feat: quick theme toggle
2025-07-15 06:28:27 +01:00
Philip Okugbe 9f144d35fb posthog integration (cloud) (#1304) 2025-06-27 10:58:36 +01:00
Philipinho 33c314d4e8 remove clickoutside hook 2025-04-24 17:56:54 +01:00
Philip Okugbe 6c422011ac feat: public page sharing (#1012)
* Share - WIP

* - public attachment links
- WIP

* WIP

* WIP

* Share - WIP

* WIP

* WIP

* include userRole in space object

* WIP

* Server render shared page meta tags

* disable user select

* Close Navbar on outside click on mobile

* update shared page spaceId

* WIP

* fix

* close sidebar on click

* close sidebar

* defaults

* update copy

* Store share key in lowercase

* refactor page breadcrumbs

* Change copy

* add link ref

* open link button

* add meta og:title

* add twitter tags

* WIP

* make shares/info endpoint public

* fix

* * add /p/ segment to share urls
* minore fixes

* change mobile breadcrumb icon
2025-04-22 20:37:32 +01:00
sanua356 233536314f feat: add Table of contents (#981)
* chore: add table of contents module

* refactor

* lint

* null check

---------

Co-authored-by: Philipinho <16838612+Philipinho@users.noreply.github.com>
2025-04-05 19:03:42 +01:00
Philip Okugbe b81c9ee10c feat: cloud and ee (#805)
* stripe init
git submodules for enterprise modules

* * Cloud billing UI - WIP
* Proxy websockets in dev mode
* Separate workspace login and creation for cloud
* Other fixes

* feat: billing (cloud)

* * add domain service
* prepare links from workspace hostname

* WIP

* Add exchange token generation
* Validate JWT token type during verification

* domain service

* add SkipTransform decorator

* * updates (server)
* add new packages
* new sso migration file

* WIP

* Fix hostname generation

* WIP

* WIP

* Reduce input error font-size
* set max password length

* jwt package

* license page - WIP

* * License management UI
* Move license key store to db

* add reflector

* SSO enforcement

* * Add default plan
* Add usePlan hook

* * Fix auth container margin in mobile
* Redirect login and home to select page in cloud

* update .gitignore

* Default to yearly

* * Trial messaging
* Handle ended trials

* Don't set to readonly on collab disconnect (Cloud)

* Refine trial (UI)
* Fix bug caused by using jotai optics atom in AppHeader component

* configurable database maximum pool

* Close SSO form on save

* wip

* sync

* Only show sign-in in cloud

* exclude base api part from workspaceId check

* close db connection beforeApplicationShutdown

* Add health/live endpoint

* clear cookie on hostname change

* reset currentUser atom

* Change text

* return 401 if workspace does not match

* feat: show user workspace list in cloud login page

* sync

* Add home path

* Prefetch to speed up queries

* * Add robots.txt
* Disallow login and forgot password routes

* wildcard user-agent

* Fix space query cache

* fix

* fix

* use space uuid for recent pages

* prefetch billing plans

* enhance license page

* sync
2025-03-06 13:38:37 +00:00
Philip Okugbe 0ef6b1978a feat: UI pagination and members search (#724)
* feat: pagination (UI)

* Fixes

* feat: add search to member list page

* responsiveness
2025-02-13 23:28:00 +00:00
lleohao 670ee64179 Support I18n (#243)
* feat: support i18n

* feat: wip support i18n

* feat: complete space translation

* feat: complete page translation

* feat: update space translation

* feat: update workspace translation

* feat: update group translation

* feat: update workspace translation

* feat: update page translation

* feat: update user translation

* chore: update pnpm-lock

* feat: add query translation

* refactor: merge to single file

* chore: remove necessary code

* feat: save language to BE

* fix: only load current language

* feat: save language to locale column

* fix: cleanups

* add language menu to preferences page

* new translations

* translate editor

* Translate editor placeholders

* translate space selection component

---------

Co-authored-by: Philip Okugbe <phil@docmost.com>
Co-authored-by: Philip Okugbe <16838612+Philipinho@users.noreply.github.com>
2025-01-04 13:17:17 +00:00