Backend:
- Fix MoveNode validation: wouldCreateCycle walks from newParentID up
toward root, rejects if nodeID is encountered (parent into descendant)
- Allow moving descendant to ancestor (C into A) and child to root
- Add isContainerType validation for new parent
- Add 8 tests covering all scenarios + duplicate ID invariant
Frontend TreeNode.svelte:
- Build parent map from full tree (not just loaded children)
- canDrop uses parent map for cycle detection
- Reactive drop-valid/drop-invalid CSS via pre-computed dropAllowed map
- Keyed {#each nodes as node (node.id)} for correct identity tracking
- Auto-expand container on 600ms drag-over hover
- Proper dragleave detection (ignore transitions to child elements)
- Clean up state on dragend
Frontend App.svelte:
- reloadTreePreservingExpanded: fresh roots + children (no patching)
- Root area visual drop indicator (dashed outline)
- dragleave handler for root area
Clean up stale GUI dist assets
- Backend: add HasChildren field to NodeDTO; ListWorkspaceTree/ListChildren
populate it by querying CountChildren for container types
- Node repository: add CountChildren(parentID, types...) method
- TreeNode: toggle shown only when has_children (not isContainer); double-click
on row = expand/collapse; icon click = expand/collapse; drop-valid class via
DOM classList for DnD highlight; auto-expand collapsed container on 500ms
hover during drag; auto-scroll near edge during drag
- App.svelte: selectNode no longer resets workspaceTree/expanded; new
reloadTreePreservingExpanded() helper re-fetches children for all expanded
nodes after DnD move / delete; deleteWorkspaceNode preserves expanded state
- Backend: ListWorkspaceTree/ListWorkspaceChildren filter to container types
only (case, client, project, folder, document, recipe)
- TreeNode: full-row context menu (removed label stopPropagation),
double-click toggles expand, icon-click toggles expand, DnD auto-expand
on 500ms hover, auto-scroll near edges, drag-over highlight via classList
- App.svelte: toggleExpand uses ListWorkspaceChildren, submitCreateNode uses
ListWorkspaceChildren for child tree population
- Note/file nodes no longer appear in the sidebar workspace tree
TreeNode.svelte:
- Native HTML5 drag-and-drop with move effect
- Lazy tree expand/collapse (arrow for container types only)
- Drop validation: no self-drop, container-only, descendant check
- 'case' icon kind added
App.svelte:
- toggleExpand loads children via ListChildren into tree
- handleNodeDrop calls MoveNode(draggedId, targetId), refreshes tree
- Root workspace area is a drop target (handleDropRoot)
- Overview section shows nodeKindLabel instead of raw type enum
- Context menu shows Create only for container types
- Create modal title uses 'Создать элемент'
- submitCreateNode expands parent after child creation
TemplateIcon.svelte: added 'case' icon (folder-like with dividers)
i18n: added nav.createNode key (ru+en)
- TreeNode.svelte: no white spacer for leaf nodes, iconKind maps node.type
directly, 32px rows with hover/selected states
- App.svelte: header shows localized nodeKindLabel, auto-select created
node, create modal with Пустое дело card + template descriptions,
disable button until name+type chosen
- i18n: add kind.folder/note/file, template descriptions,
template.optionNone → Пустое дело / Empty case