Files
gitmost/apps/client
glm5.2 agent 180 0c7d67fe2a feat(tree): add Expand all / Collapse all to the space page tree
The space sidebar tree loaded children one level at a time, so there was
no way to expand the whole tree at once - doing it client-side would mean
recursively paging /pages/sidebar-pages hundreds of times. Add a server
endpoint that returns the whole space tree in one permission-filtered
request, and two menu items in the Space menu that drive it.

Server:
- POST /pages/tree (reuses SidebarPageDto, CASL Read gate) returns
  { items: [...] } - a flat list in the same shape as /pages/sidebar-pages
  (id, slugId, title, icon, position, parentPageId, spaceId, hasChildren,
  canEdit), sorted by position (collate 'C') then id.
- pageRepo.getSpaceDescendants(spaceId, opts): recursive CTE seeded from
  space roots (parentPageId IS NULL). getSpaceDescendantsExcludingRestricted
  is also added (space-rooted variant of getPageAnd*ExcludingRestricted)
  but not used by the read endpoint - see below.
- pageService.getSidebarPagesTree: fetches the whole space tree WITHOUT
  SQL restricted-pruning and lets filterAccessibleTreePages drop
  inaccessible pages + their subtrees. This mirrors the stepwise
  /pages/sidebar-pages behavior, so a restricted page the user HAS
  access to stays visible in expand-all (an earlier draft pruned in SQL
  and hid them - a behavioural regression). canEdit is per-page in
  restricted spaces (filterAccessiblePageIdsWithPermissions) and
  space-wide in open spaces. filterAccessibleTreePages is now public
  and accepts rootPageId=null to treat every top-level page as a root.
- hasChildren is derived in JS (a page hasChildren iff some returned row
  has it as parentPageId) - O(n), no N subqueries.

Client:
- SpaceTree is now a forwardRef exposing { expandAll, collapseAll,
  isExpanding } via useImperativeHandle. expandAll fires one
  getSpaceTree request, merges the full nested tree into treeDataAtom
  (replace-and-merge so the authoritative server tree wins over stale
  partially-loaded roots), opens every branch id of the current space,
  and guards against space switches via spaceIdRef. Errors are logged
  AND surfaced in a notification with the real reason - never a generic
  string. collapseAll clears ONLY current-space ids from the shared
  open-map (does not disturb other spaces).
- isExpanding is lifted to reactive state in SpaceSidebar and passed as
  a prop to SpaceMenu so the Expand item's disabled state actually
  updates (a ref mutation alone would not re-render).
- Two Menu.Items inside SpaceMenu (Expand all / Collapse all), gated
  only by read access (not canManage) - these are view operations.
2026-06-20 14:44:25 +03:00
..
2024-06-07 17:29:34 +01:00
2024-01-09 18:58:26 +01:00
2024-12-09 14:51:31 +00:00
2026-06-18 18:07:54 +03:00
2024-01-09 18:58:26 +01:00
2024-01-09 18:58:26 +01:00
2024-01-09 18:58:26 +01:00
2024-01-09 18:58:26 +01:00

React + TypeScript + Vite

This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.

Currently, two official plugins are available:

Expanding the ESLint configuration

If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:

  • Configure the top-level parserOptions property like this:
   parserOptions: {
    ecmaVersion: 'latest',
    sourceType: 'module',
    project: ['./tsconfig.json', './tsconfig.node.json'],
    tsconfigRootDir: __dirname,
   },
  • Replace plugin:@typescript-eslint/recommended to plugin:@typescript-eslint/recommended-type-checked or plugin:@typescript-eslint/strict-type-checked
  • Optionally add plugin:@typescript-eslint/stylistic-type-checked
  • Install eslint-plugin-react and add plugin:react/recommended & plugin:react/jsx-runtime to the extends list