Commit Graph

12 Commits (master)

Author SHA1 Message Date
mirivlad 4f01f2de2e fix: complete vault layout transition — fs_path everywhere, no more spaces/
- notes.Create(): .md files stored in parent node's fs_path folder
- files.CopyIntoVault/CreateEmptyFile/Duplicate: use parent fs_path
- files.AddPathCopy/AddPathLink: use parent fs_path, set folder fs_path
- files.DeleteNodeAndChildren: move physical folder to .verstak/trash
- UpdateFsPathRecursive: use SafeDisplayNameToPathSegment(child.Title)
- sync_apply.go note ops: use fs_path instead of spaces/
- internal/gui/server.go file upload: use n.FsPath instead of nodeSlug
- VaultCheck diagnostic: walk nodes/files, verify paths on disk
- Tests: create/rename/move/delete/name-conflict/vault-check all pass
2026-06-02 15:43:40 +08:00
mirivlad 0b26f7e5b3 refactor: implement template-driven node tree and human-readable vault layout
Unified Node model: added template_id, fs_path, archived, sort_order fields.
Template registry: system templates embedded as JSON (folder/project/client/
document/recipe), with Registry for enabled/disabled/filtered access.
SafeDisplayNameToPathSegment: human-readable path segments with Cyrillic
support, illegal char replacement, uniqueness via numeric suffixes.
Sidebar refactored: system views (Today/Inbox/Activity) separate from
workspace tree. Creation menu built dynamically from enabled templates.
Create/Rename/Move: physical folder operations with fs_path update,
recursive descendant path updates.
DB migration 012: adds template_id, fs_path, archived columns.
Vault migration command: rebuilds fs_path for existing nodes.
Tests: safename, registry, node model, repository integration.
Docs: VAULT_LAYOUT.md, TEMPLATES.md, PLAN.md updated.
i18n: nav.system, nav.workspace, template.*, common.rename/archive,
migrate.* keys added to ru.json and en.json.
2026-06-02 12:47:06 +08:00
mirivlad 2fa583d157 stabilization: server.go split + i18n templates + frontend localization
cmd/verstak-server/server.go (2838→127 строк): разделён на 12 файлов
- config.go, tokens.go, schema.go
- server.go (только struct + NewServer + ListenAndServe)
- routes.go, middleware.go, smtp.go
- handlers_api.go, handlers_user.go, handlers_web_user.go, handlers_admin.go
- templates.go (конвертирован в функции с i18n.T())

frontend: все русские строки заменены на t() вызовы
- App.svelte, FileTreeRow.svelte, ConfirmModal.svelte
- FilePreviewModal.svelte, fileUtils.js

core: gofmt по всему проекту

Все сборки (CLI, server, gui, frontend), go vet, go test проходят.
check-i18n.sh: frontend чист, Go-файлы с кириллицей — только тесты/легаси.
2026-06-02 11:08:29 +08:00
mirivlad 2487d3bbaa Files tab: multi-selection, drag-and-drop, keyboard shortcuts, custom confirm modal, SVG icons 2026-06-01 01:16:51 +08:00
mirivlad 752b1bb4b8 fix: file upload via GUI + API endpoint
- Replace stub file modal with working file path input
- PUT /api/files/upload — copies external file into vault
- submitFile() JS: posts path to API, refreshes node view
- Button '+ Файл' now opens functional modal
2026-05-31 11:38:49 +08:00
mirivlad b800bce7e4 step 10: plugins system (Lua + templates) + DokuWiki as optional plugin
Plugin Manager:
- Discover plugins from .verstak/plugins/<name>/plugin.json
- Enable/disable per plugin
- Template definitions (JSON) → pre-filled node trees
- SQL migrations from plugins
- Built-in templates loaded from internal/core/plugins/builtin/templates/

Lua Runtime:
- Stub (gopher-lua placeholder) — ready for real implementation
- When dep added: hooks (on_init, on_vault_open, on_node_create),
  sandbox (no io/os.execute), Plugin API

GUI:
- Template selector in create node modal
- POST /api/nodes/from-template creates tree from template
- Built-in "Клиент" template: Overview note + Документы/Переписка/Скриншоты

CLI:
- verstak plugin list/enable/disable/templates

DokuWiki Importer:
- Moved to contrib/plugins/importer-dokuwiki/ (optional plugin)
- plugin.json + migration + README

DokuWiki removed from MVP core — now an opt-in plugin.

Acceptance: go build ./... pass, go test ./... pass (all packages).
2026-05-31 11:20:45 +08:00
mirivlad d6f7f1a9b8 steps 8+9: worklog + FTS5 search
STEP 8 — Worklog:
- Migration 006: worklog_entries table (node_id, date, minutes,
  approximate, billable, summary, details)
- WorklogService: Add, Get, Update, Delete, ListByNode, SumMinutes,
  Report (text report generator with total time)
- CLI: verstak log add/list/report  (verstak log --help for usage)
- GUI tab: entries list with date/time/approx, add form with
  minutes+text+approx checkbox, total minutes counter

STEP 9 — FTS5 Search:
- FTS5 virtual table created lazily by search.Rebuild()
  (works with/without FTS5 compiled in — graceful fallback)
- SearchService: Index, Remove, Rebuild, Search (with FTS5 MATCH)
- CLI: verstak index rebuild — builds search index from node titles
- GUI search bar uses /api/search?q= (FTS5 when available,
  fallback to LIKE on node titles)

Acceptance: go build ./... pass, go test ./... pass (all packages).
2026-05-31 02:25:25 +08:00
mirivlad dae53fcbba step 7: actions — table, service, CLI, GUI tab + confirm dialog
- Migration 005: actions table (node_id, title, kind, command, args_json,
  working_dir, url, confirm_required, capture_output)
- ActionService: Create, Get, ListByNode, Delete, Run
  Run dispatches: open_url/file/folder (xdg-open), run_command/script
  (exec.Command), open_terminal, launch_app
- CLI: verstak action add/list/run/delete
  'run' shows confirm prompt for confirm_required actions
- GUI 'Действия' tab: button list with kind label, confirm_required
  opens editor overlay with action info + confirm, delete button
- 7 unit tests for ActionService

Acceptance: go build ./... pass, go test ./... pass.
2026-05-31 01:52:23 +08:00
mirivlad 9ee6df0d3f feat: node section assignment for sidebar filtering + search fix
Backend:
- Migration 004: add 'section' column to nodes table
  (NULL=inbox, values: clients/projects/recipes/documents/archive)
- Create(parentID, type, title, section) — section stored on root nodes
- ListRoots(includeDeleted, section) — filters by section
  (section='inbox' returns nodes with NULL section)
- GET /api/nodes?section=X filters root nodes by section
- POST /api/nodes accepts 'section' field in body

Frontend:
- Sidebar separates 'НАВИГАЦИЯ' (virtual sections) from 'ДЕЛА' (real nodes)
- Each section loads only its own nodes: GET /api/nodes?section=clients etc.
- Creating from a section sets the section automatically
- Inbox shows only nodes with no section
- selectBySearch(id) closes result dropdown after selection
- All types shown in Russian (Дело, Заметка, Папка, etc.)

Acceptance: go build pass, go test pass (all packages),
  manual: Pro projects section shows only project-nodes,
  clients only client-nodes, inbox only unsectioned nodes.
2026-05-31 01:26:46 +08:00
mirivlad 14ff1a25b9 fix: bind sidebar selection to filtered content
Root cause: single global 'cur' node ID was shared across all
sections. Switching between 'Клиенты'/'Проекты'/etc did not
change the rendered content because renderToday/renderInbox/
loadSection all loaded the same flat root-node list and
switchTab('ov') re-rendered selN(cur) regardless of which
section was active.

Fix: split selection into two distinct states:
  sel = {kind:'section', section:'today'|'inbox'|'clients'|...}
    or  sel = {kind:'node',     nodeId:'<uuid>'}

Each section renders its own content (title, quick-actions,
filtered items, empty state). Real nodes show their own
dashboard. Tab dispatch checks sel.kind first.

Sidebar separated into:
  'НАВИГАЦИЯ' — virtual sections (today/inbox/7 categories)
  'ДЕЛА'       — real user nodes from API

Russian type labels everywhere (TL map). Section metadata
(SEC_META) provides per-section empty states and action types.

Known limitation: section content currently shows all root
nodes (backend has no section/group column yet). When section
assignment is added to the data model, filtering will wire
up without frontend changes — renderSectionList already
receives the section id.
2026-05-30 21:56:07 +08:00
mirivlad 168625671a step 6 redesign: dashboard, sidebar sections, add menu, editor UX
Per 10-point UX spec:
- Contrast boosted (text #e4e4ef instead of #ccc)
- Dashboard view: badges, quick-actions, grouped sub-items/notes/files
- Notes tab filters by type=note, Files tab shows only files
- Tab placeholders: Actions, Worklog, Activity
- Single + Add button with dropdown menu (case/note/file/action/worklog)
- Sidebar navigation: Today, Inbox, Clients, Projects, Recipes, Docs, Archive
- Russian type labels (no raw CASE/note)
- Note editor: breadcrumb, title, readable-width textarea (720px)
- Wails-ready SPA: inline JS, fetch to /api/*, no external deps
2026-05-30 21:04:18 +08:00
mirivlad 39271fc28f steps 4-6 + doc overhaul: files, notes, GUI, plugins docs
DOCUMENTATION (shift from personal to universal product):
- README.md: rewritten with 'one product, different doors' framing,
  universal entities table, audience segments
- 01_Product_Spec.md: removed personal references (sshkeeper, Godot,
  DokuWiki, servers), added audience segments (freelancer, repairmaster,
  developer, maker, consultant), universal scenarios
- 02_Architecture.md: added 'Plugins (Extensibility)' section with
  calendar/kanban/importer/template examples
- 03_Data_Model_Storage.md: added section 6 on plugin extensibility
  (node_meta, type registry, SQL migrations per plugin)
- 09_Extensibility.md (NEW): full plugin architecture — Lua runtime,
  plugin.json, hooks, sandbox, templates, registry
- PLAN.md: added step 16 (plugins), updated status table
- 00_README.md: rewritten product index with plugin principle

CODE — STEP 4 (Files):
- migration 002: files table (id, node_id, filename, path,
  storage_mode, size, sha256, mime, ...)
- FileService: AddExternal, CopyIntoVault, Get, ListByNode,
  MarkMissing, DeleteToTrash, Open (xdg-open)
- file_test.go: 5 tests (external, copy-vault, list-node,
  delete-trash, MIME guess)

CODE — STEP 5 (Notes):
- migration 003: notes table (node_id PK, file_id, format,
  original_format, encrypted)
- NoteService: Create (node+file+link), Read, Save (with backup to
  .verstak/history/), Delete, Load
- note_test.go: 3 tests (create-read, save-backup, delete)

CODE — STEP 6 (GUI):
- cmd/verstak-gui/main.go: launches GUI server, opens browser
- internal/gui/server.go: HTTP API for nodes/notes/files/search
- internal/gui/index.html.go: full inline SPA frontend (dark theme,
  sidebar tree, cards grid, note editor, search, create modals)
- Navigation: sidebar tree → click node → detail view with
  children + files cards → tab switch (overview/notes/files)
  → create node/note via modal → edit note in fullscreen
  textarea → save (with history backup)

Acceptance: go build ./... pass, go build -tags gui ./cmd/verstak-gui pass,
  go test ./... pass (20+ tests). GUI serves on random port, opens browser.
  API returns JSON for all resource types.
2026-05-30 20:35:04 +08:00