Update summary.md and README for sharing/collaboration/backup session
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,31 +1,59 @@
|
||||
# Fabled Assistant
|
||||
|
||||
A self-hosted note-taking and task-tracking application with integrated LLM capabilities. Write, organize, and enhance your notes with the help of a local AI assistant — all running on your own hardware.
|
||||
A self-hosted second brain and project management application with integrated LLM capabilities. Write, organise, and act on your notes and tasks with the help of a local AI assistant — all running on your own hardware.
|
||||
|
||||
## What It Does
|
||||
|
||||
**Notes with inline formatting** — Write in Markdown with a live-preview editor. Headings, bold, italic, lists, and code blocks render inline as you type, similar to Obsidian or Typora.
|
||||
**Notes with inline formatting** — Write in Markdown with a live-preview editor (Tiptap/ProseMirror). Headings, bold, italic, lists, code blocks, and task checklists render inline. A slash-command menu (`/`) inserts common blocks without leaving the keyboard.
|
||||
|
||||
**Task tracking** — Any note can become a task with a status (todo, in progress, done), priority level, and due date. Convert freely between notes and tasks without losing content.
|
||||
**Task tracking** — Notes convert freely to tasks (and back). Tasks carry status (`todo` → `in_progress` → `done`), priority, due date, sub-tasks, milestone assignment, and work logs with time tracking.
|
||||
|
||||
**Wikilinks and backlinks** — Link notes together with `[[Title]]` syntax. Click a wikilink to navigate to (or auto-create) the referenced note. Each note shows what links to it.
|
||||
**Projects and milestones** — Group related notes and tasks into projects. Milestones give projects a timeline and show completion progress. A kanban-style project view groups tasks by milestone.
|
||||
|
||||
**Tag organization** — Add `#tags` anywhere in your text. Tags are extracted automatically and support hierarchical filtering (e.g., `#project/webapp` matches both `project` and `project/webapp`). Tag autocomplete suggests existing tags as you type.
|
||||
**Project Workspace** — `/workspace/:projectId` opens a three-panel environment (tasks / chat / notes) locked to a project. The AI assistant creates and updates content directly in the workspace; new notes auto-load in the editor and the task list refreshes automatically.
|
||||
|
||||
**AI writing assistant** — Select a section of your note and give the assistant an instruction ("summarize this", "make it more concise", "add examples"). The assistant streams a suggestion that you can accept or reject. Powered by Ollama running locally.
|
||||
**Wikilinks and backlinks** — Link notes with `[[Title]]` syntax. Click a wikilink to navigate to (or create) the referenced note. Each note shows what links to it. The editor suggests existing note titles as candidate links.
|
||||
|
||||
**AI chat** — Have conversations with your AI assistant. The chat is context-aware: it can automatically find and reference your notes to give more relevant answers. Attach specific notes for focused discussions. Save useful responses as new notes.
|
||||
**Tag organisation** — Tags are first-class columns (stored as a PostgreSQL array, not extracted from body text). Tag autocomplete, tag-based filtering, and a force-directed graph view show how notes cluster.
|
||||
|
||||
**Multi-user support** — Multiple users can share the same instance with isolated data. The first registered user becomes the admin.
|
||||
**Knowledge graph** — `/graph` renders all notes, tasks, and tags as a D3 force-directed graph. Tag nodes cluster notes that share tags; project hub nodes (invisible) attract project members. Click any node to open a slide-in peek panel.
|
||||
|
||||
**Dark and light themes** — Defaults to dark mode with a one-click toggle. All views respect your preference.
|
||||
**AI chat** — Full conversation history with SSE streaming. The assistant automatically retrieves semantically relevant notes (RAG) and injects them as context. Attach specific notes by paperclip for focused discussions. Useful replies can be saved directly as notes.
|
||||
|
||||
**AI writing assistant** — Select a passage in the editor, give an instruction ("make this more concise", "add examples"), and stream a diff-style suggestion you can accept or reject.
|
||||
|
||||
**Web research** — The assistant can search the web (SearXNG), fetch pages, and synthesise findings. Research results are saved as notes. A lightweight `search_web` tool answers quick questions inline.
|
||||
|
||||
**Collaboration and sharing** — Share any project or note with other users or groups. Three permission levels: `viewer`, `editor`, `admin`. A "Shared with me" page lists all incoming shares. In-app notifications (with push) alert recipients when items are shared or when they are added to a group.
|
||||
|
||||
**Groups** — Admins can create platform-wide groups, assign users roles (`member` / `owner`), and share resources with the group in one action.
|
||||
|
||||
**In-app notifications** — A bell icon in the nav shows unread notification count with a 60-second polling interval. Clicking a notification navigates to the relevant resource and marks it read.
|
||||
|
||||
**CalDAV calendar** — Connect an external CalDAV server (Nextcloud, Radicale, etc.) and have the assistant create, list, search, update, and delete calendar events via natural language.
|
||||
|
||||
**Push notifications** — Web Push (VAPID) notifies you when AI generation completes, even in another tab. Configurable per-user from the Notifications settings tab.
|
||||
|
||||
**PWA** — Installable as a desktop or mobile app. Service worker caches the shell; push is handled by `public/sw.js`.
|
||||
|
||||
**Data export and backup** — Export your data as a Markdown ZIP (with YAML frontmatter) or a JSON array from the Data settings tab. Admins can export/restore full application backups (version 2 includes projects, milestones, task logs, AI drafts, note versions, push subscriptions) with proper ID remapping on restore.
|
||||
|
||||
**OAuth / OIDC login** — Supports PKCE-based OIDC in addition to local username/password auth. `LOCAL_AUTH_ENABLED` can disable local login entirely for SSO-only deployments.
|
||||
|
||||
**Multi-user with isolation** — All data is scoped to the owning user. Access to shared resources is resolved through `services/access.py` using the permission rank system. The first registered user becomes admin.
|
||||
|
||||
**Dark and light themes** — Defaults to dark (slate-indigo palette). One-click toggle in the header.
|
||||
|
||||
**Keyboard shortcuts** — `g`+`h/n/t/p/c/g` navigate sections; `n` new note; `t` new task; `?` shows the shortcut panel. Full list available in-app.
|
||||
|
||||
---
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- [Docker](https://docs.docker.com/get-docker/) and Docker Compose
|
||||
- A machine with enough resources to run an LLM (8GB+ RAM recommended for smaller models)
|
||||
- A machine with enough RAM to run an LLM (8 GB+ recommended for smaller models like `llama3.2`)
|
||||
|
||||
### Quick Start
|
||||
|
||||
@@ -42,54 +70,69 @@ A self-hosted note-taking and task-tracking application with integrated LLM capa
|
||||
|
||||
3. Open `http://localhost:5000` in your browser.
|
||||
|
||||
4. Register the first user account (this account becomes the admin).
|
||||
4. Register the first user account — this account becomes the admin.
|
||||
|
||||
5. Go to **Settings** to download an LLM model. Smaller models like `llama3.2` (2GB) work well for getting started.
|
||||
5. Go to **Settings → General** to pull an LLM model (`llama3.2` at 2 GB is a good starting point).
|
||||
|
||||
### Day-to-Day Usage
|
||||
|
||||
- **Create a note** from the Notes page. Use Markdown — formatting renders live in the editor.
|
||||
- **Link notes** by typing `[[` to get a wikilink autocomplete dropdown.
|
||||
- **Tag your notes** by typing `#` followed by a tag name. Autocomplete suggests existing tags.
|
||||
- **Use the AI assistant** in the bottom panel of the editor. Select a section, write an instruction, and click Generate.
|
||||
- **Chat with the AI** from the Chat page. Attach notes for context or let the assistant find relevant notes automatically.
|
||||
- **Convert notes to tasks** from the note viewer to add status, priority, and due dates.
|
||||
- **Save chat responses** as notes to preserve useful AI-generated content.
|
||||
- **Backup your data** from Settings (admin users can export and restore full backups).
|
||||
- **Create a note** from the Notes page. Use Markdown — formatting renders live.
|
||||
- **Link notes** by typing `[[` for a wikilink autocomplete dropdown.
|
||||
- **Tag your notes** — add tags in the sidebar tag input; autocomplete suggests existing tags.
|
||||
- **Use the AI writing assistant** — select text in the editor, write an instruction, stream a suggestion.
|
||||
- **Chat with the AI** — the assistant finds relevant notes automatically. Attach specific notes for focused context.
|
||||
- **Convert notes ↔ tasks** from the viewer toolbar.
|
||||
- **Open a project workspace** from the project page — chat, tasks, and note editor in one view.
|
||||
- **Share a project or note** — click Share in the project/note/task viewer toolbar, search for users or pick a group.
|
||||
- **Manage groups** (admins) — Settings → Groups tab.
|
||||
- **Backup your data** — Settings → Data tab for personal export; admin section for full application backup.
|
||||
|
||||
---
|
||||
|
||||
## Configuration
|
||||
|
||||
Configuration is done via environment variables. See `docker-compose.yml` for defaults.
|
||||
Configuration is via environment variables. See `docker-compose.yml` for defaults.
|
||||
|
||||
| Variable | Default | Description |
|
||||
|----------|---------|-------------|
|
||||
| `DATABASE_URL` | `postgresql+asyncpg://...` | PostgreSQL connection string |
|
||||
| `SECRET_KEY` | (required) | Session signing key |
|
||||
| `OLLAMA_BASE_URL` | `http://ollama:11434` | Ollama API endpoint |
|
||||
| `DEFAULT_MODEL` | `llama3.1` | Default LLM model to auto-pull on startup |
|
||||
| `SECURE_COOKIES` | `false` | Set to `true` when behind TLS to add `Secure` flag to session cookies |
|
||||
| `LOG_LEVEL` | `INFO` | Logging level |
|
||||
| `DEFAULT_MODEL` | `llama3.1` | LLM model to warm on startup |
|
||||
| `EMBEDDING_MODEL` | `nomic-embed-text` | Model used for semantic search / RAG |
|
||||
| `SECURE_COOKIES` | `false` | Set `true` behind TLS |
|
||||
| `LOG_LEVEL` | `INFO` | Logging verbosity |
|
||||
| `OIDC_ISSUER` | — | OIDC issuer URL for SSO login |
|
||||
| `OIDC_CLIENT_ID` | — | OIDC client ID |
|
||||
| `OIDC_CLIENT_SECRET` | — | OIDC client secret |
|
||||
| `LOCAL_AUTH_ENABLED` | `true` | Set `false` to disable local login |
|
||||
| `SEARXNG_URL` | — | SearXNG base URL for web search |
|
||||
| `BASE_URL` | — | Public URL (used in email links and OIDC redirect) |
|
||||
|
||||
For production deployments, `docker-compose.prod.yml` supports Docker secrets (`SECRET_KEY_FILE`, `DATABASE_URL_FILE`) and includes network isolation, health checks, and resource limits.
|
||||
For production, `docker-compose.prod.yml` supports Docker secrets (`SECRET_KEY_FILE`, `DATABASE_URL_FILE`) and includes network isolation, health checks, and resource limits.
|
||||
|
||||
---
|
||||
|
||||
## Production Deployment
|
||||
|
||||
### Reverse Proxy (Required)
|
||||
|
||||
Fabled Assistant does **not** handle SSL/TLS. You must run it behind a reverse proxy for production use:
|
||||
Fabled Assistant does **not** handle SSL/TLS. Run it behind a reverse proxy:
|
||||
|
||||
- **Nginx**, **Traefik**, or **Caddy** in front of the app container
|
||||
- Terminate TLS at the proxy and forward traffic to port 5000
|
||||
- Terminate TLS at the proxy; forward to port 5000
|
||||
- **Do not expose port 5000 directly to the internet**
|
||||
- **Rate-limit auth endpoints** at the proxy layer — recommended: limit `/api/auth/login` and `/api/auth/register` to ~5 requests/minute per IP to prevent brute-force attacks
|
||||
- **Set Content Security Policy headers** at the proxy — recommended: `default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self'`
|
||||
- **Rate-limit auth endpoints** — recommended: ≤5 req/min per IP on `/api/auth/login` and `/api/auth/register`
|
||||
- **Set CSP headers** — recommended: `default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self'`
|
||||
|
||||
### Security Checklist
|
||||
|
||||
- **Set a strong `SECRET_KEY`** — used to sign session cookies. Generate one with `python -c "import secrets; print(secrets.token_hex(32))"` or use Docker secrets via `SECRET_KEY_FILE`.
|
||||
- **Registration auto-closes** — After the first user registers (who becomes admin), registration is closed by default. The admin can re-enable it from the user management page (`/admin/users`).
|
||||
- **Use Docker secrets in production** — `docker-compose.prod.yml` reads `SECRET_KEY_FILE` and `DATABASE_URL_FILE` instead of plain environment variables.
|
||||
- **Keep Ollama on an internal network** — The default compose files keep Ollama on a Docker-internal network, not exposed to the host.
|
||||
- **Strong `SECRET_KEY`** — generate with `python -c "import secrets; print(secrets.token_hex(32))"` or use Docker secrets via `SECRET_KEY_FILE`
|
||||
- **Registration** — auto-closes after the first user (admin). Re-enable from Settings → Users or send invite links.
|
||||
- **Session invalidation** — changing or resetting a password bumps `session_version`, evicting all other active sessions.
|
||||
- **Keep Ollama on an internal network** — both compose files keep it off the host network.
|
||||
|
||||
---
|
||||
|
||||
## Technical Overview
|
||||
|
||||
@@ -98,61 +141,69 @@ Fabled Assistant does **not** handle SSL/TLS. You must run it behind a reverse p
|
||||
| Layer | Technology |
|
||||
|-------|------------|
|
||||
| Frontend | Vue 3, TypeScript, Vite, Pinia, Vue Router |
|
||||
| Editor | Tiptap (ProseMirror) with custom extensions |
|
||||
| Backend | Python 3.12, Quart (async Flask-like framework) |
|
||||
| Database | PostgreSQL 16, SQLAlchemy 2.0 (async), Alembic migrations |
|
||||
| LLM | Ollama (or any OpenAI-compatible API) |
|
||||
| Deployment | Docker Compose (app + PostgreSQL + Ollama) |
|
||||
| Editor | Tiptap (ProseMirror) with custom slash-command extension |
|
||||
| Backend | Python 3.12, Quart (async ASGI) |
|
||||
| Database | PostgreSQL 16, SQLAlchemy 2.0 async, Alembic |
|
||||
| LLM | Ollama (local) — any OpenAI-compatible API |
|
||||
| Search | SearXNG (optional, self-hosted) |
|
||||
| Push | Web Push / VAPID (pywebpush 2.x) |
|
||||
| Deployment | Docker Compose |
|
||||
|
||||
### Architecture
|
||||
|
||||
The application runs as a single container serving both the Vue.js SPA and the REST API. The frontend is built by Vite during the Docker image build and served as static files by Quart. API routes live under `/api/`.
|
||||
The app runs as a single container serving the Vue SPA and REST API (`/api/`). The frontend is built by Vite during the Docker image build and served as static files by Quart.
|
||||
|
||||
LLM interactions use Server-Sent Events (SSE) for streaming responses. Chat generation runs in background `asyncio` tasks with an in-memory event buffer that supports client reconnection without data loss.
|
||||
LLM interactions stream via Server-Sent Events (SSE). Chat generation runs in background `asyncio` tasks with an in-memory event buffer supporting client reconnection without data loss. An abort mechanism lets users cancel in-flight generations.
|
||||
|
||||
The editor uses a Markdown-to-HTML-to-Markdown round-trip: content is stored as Markdown, converted to HTML for Tiptap editing, and serialized back to Markdown on every change. ProseMirror decoration plugins provide visual highlighting for tags and wikilinks without custom node types.
|
||||
Semantic search (RAG) uses `nomic-embed-text` via Ollama to generate embeddings stored in PostgreSQL. Notes above 0.60 cosine similarity are auto-injected into the system prompt; notes between 0.45–0.60 appear as sidebar suggestions.
|
||||
|
||||
Permission resolution is centralised in `services/access.py`. All resource access goes through `get_project_permission` / `get_note_permission`, which check ownership, direct shares, group membership shares, and note→project inheritance in order, returning the highest applicable permission.
|
||||
|
||||
### Database
|
||||
|
||||
All data is stored in PostgreSQL. The schema uses a unified model where tasks are notes with additional attributes (`status`, `priority`, `due_date`). Migrations are idempotent raw SQL and run automatically on container startup.
|
||||
PostgreSQL with SQLAlchemy 2.0 async. Tasks are notes with non-null `status` (unified `Note` model). Tags are stored as a `ARRAY[text]` column. Migrations run automatically on startup via Alembic.
|
||||
|
||||
### Project Structure
|
||||
|
||||
```
|
||||
fabledassistant/
|
||||
├── docker-compose.yml # Development stack
|
||||
├── docker-compose.prod.yml # Production stack (Docker Swarm)
|
||||
├── Dockerfile # Multi-stage build (Node + Python)
|
||||
├── alembic/ # Database migrations
|
||||
├── src/fabledassistant/ # Python backend
|
||||
│ ├── app.py # Quart app factory
|
||||
│ ├── models/ # SQLAlchemy models
|
||||
│ ├── routes/ # API route blueprints
|
||||
│ ├── services/ # Business logic
|
||||
│ └── static/ # Built frontend (generated)
|
||||
└── frontend/ # Vue.js frontend
|
||||
├── docker-compose.yml # Development stack
|
||||
├── docker-compose.prod.yml # Production stack (Docker Swarm)
|
||||
├── Dockerfile # Multi-stage build (Node → Python)
|
||||
├── alembic/ # Database migrations
|
||||
├── src/fabledassistant/
|
||||
│ ├── app.py # Quart app factory + blueprint registration
|
||||
│ ├── models/ # SQLAlchemy models
|
||||
│ ├── routes/ # API blueprints
|
||||
│ ├── services/ # Business logic (access, sharing, groups, …)
|
||||
│ └── static/ # Built frontend (generated at build time)
|
||||
└── frontend/
|
||||
└── src/
|
||||
├── views/ # Page components
|
||||
├── components/ # Reusable UI components
|
||||
├── extensions/ # Tiptap/ProseMirror plugins
|
||||
├── composables/ # Vue composables
|
||||
├── stores/ # Pinia state management
|
||||
└── api/ # API client
|
||||
├── views/ # Page-level components
|
||||
├── components/ # Reusable UI components
|
||||
├── composables/ # Vue composables (autosave, shortcuts, …)
|
||||
├── stores/ # Pinia stores (auth, chat, notes, notifications, …)
|
||||
└── api/ # Typed API client (client.ts)
|
||||
```
|
||||
|
||||
### Development
|
||||
|
||||
All development is done via Docker:
|
||||
All development is done via Docker. No local dependency installation required.
|
||||
|
||||
```bash
|
||||
# Start the dev stack
|
||||
# Start the dev stack (hot-reload not included — rebuild on changes)
|
||||
docker compose up --build
|
||||
|
||||
# Reset database (destroy volumes and rebuild)
|
||||
# Reset the database
|
||||
docker compose down -v && docker compose up --build
|
||||
|
||||
# Lint, format, typecheck, test (runs inside Docker via Makefile)
|
||||
make check
|
||||
```
|
||||
|
||||
No local dependency installation required.
|
||||
CI runs on Forgejo Actions with a custom runner image (`py3.12-node22`) that has Python 3.12 and Node 22 pre-installed. Pushes to `dev` build a `:dev` image; merges to `main` build `:latest`.
|
||||
|
||||
---
|
||||
|
||||
## License
|
||||
|
||||
|
||||
+42
-1
@@ -12,7 +12,48 @@
|
||||
> Include file-level details in the commit body when the change is non-trivial.
|
||||
|
||||
## Last Updated
|
||||
2026-03-10 — Feature batch: workspace view, graph view, settings tabs, message queue persistence, ToolCallCard direct-API confirm, duplicate detection scoping, push notification fixes.
|
||||
2026-03-11 — Multi-user sharing & collaboration, in-app notifications, groups management, backup rewrite.
|
||||
|
||||
**Multi-user sharing & collaboration:**
|
||||
- `alembic/versions/0025_add_sharing_and_notifications.py` (new): creates `groups`, `group_memberships`, `project_shares`, `note_shares`, `notifications` tables. Partial unique indexes via raw SQL. CHECK constraint enforces exclusive user/group target on share rows.
|
||||
- `src/fabledassistant/models/group.py` (new): `Group` + `GroupMembership` SQLAlchemy models.
|
||||
- `src/fabledassistant/models/share.py` (new): `ProjectShare` + `NoteShare` models with `shared_with_user_id`, `shared_with_group_id`, `permission`, `invited_by` columns.
|
||||
- `src/fabledassistant/models/notification.py` (new): `Notification` model with `type`, `payload` (JSONB), `read_at`.
|
||||
- `src/fabledassistant/models/__init__.py`: exports all three new model groups.
|
||||
- `src/fabledassistant/services/access.py` (new): `PERMISSION_RANK` dict (`viewer=1 editor=2 admin=3 owner=4`). `get_project_permission(uid, project_id)` and `get_note_permission(uid, note_id)` — check ownership, direct share, group-based share, and note→project inheritance; return highest permission string or `None`. Helper predicates: `can_read_*`, `can_write_*`, `can_admin_*`.
|
||||
- `src/fabledassistant/services/groups.py` (new): `create_group`, `list_groups`, `update_group`, `delete_group`, `add_member`, `update_member_role`, `remove_member`.
|
||||
- `src/fabledassistant/routes/groups.py` (new): CRUD at `/api/groups` and `/api/groups/:id`; member management at `/api/groups/:id/members/:uid`.
|
||||
- `src/fabledassistant/services/sharing.py` (new): `share_project/note`, `update_project/note_share`, `remove_project/note_share`, `list_project/note_shares`, `list_shared_with_me`.
|
||||
- `src/fabledassistant/routes/shares.py` (new): project shares at `/api/projects/:id/shares`, note shares at `/api/notes/:id/shares`, `GET /api/shared-with-me`.
|
||||
- `src/fabledassistant/services/notifications.py`: extended with `create_in_app_notification`, `notify_project_shared`, `notify_note_shared`, `notify_group_added`, `list_in_app_notifications`, `unread_notification_count`, `mark_notification_read`, `mark_all_notifications_read`.
|
||||
- `src/fabledassistant/routes/in_app_notifications.py` (new): `GET /api/notifications`, `GET /api/notifications/count`, `POST /api/notifications/:id/read`, `POST /api/notifications/read-all`.
|
||||
- `src/fabledassistant/routes/users.py` (new): `GET /api/users/search?q=` — username/email prefix search, min 2 chars, excludes self.
|
||||
- `src/fabledassistant/services/projects.py`: added `get_project_for_user(accessing_uid, project_id)` → `(Project, perm) | None` and `list_projects_for_user(uid)` (owned + shared).
|
||||
- `src/fabledassistant/services/notes.py`: added `get_note_for_user(accessing_uid, note_id)` → `(Note, perm) | None`.
|
||||
- `src/fabledassistant/routes/projects.py`: `list_projects_route` uses `list_projects_for_user`; `get_project_route` uses `get_project_for_user` and adds `permission` field; `get_project_notes_route` access-checks via `get_project_for_user`.
|
||||
- `src/fabledassistant/routes/notes.py`, `routes/tasks.py`: `get_note_route`/`get_task_route` use `get_note_for_user` and add `permission` field.
|
||||
- `src/fabledassistant/app.py`: registers `groups_bp`, `shares_bp`, `notifications_bp`, `users_bp`.
|
||||
|
||||
**Frontend — sharing & notifications:**
|
||||
- `frontend/src/api/client.ts`: added `ShareEntry`, `GroupEntry`, `GroupMember`, `NotificationEntry`, `UserSearchResult` TypeScript interfaces and API helper functions for all new endpoints.
|
||||
- `frontend/src/stores/notifications.ts` (new): Pinia store — `count`, `items`, `fetchCount`, `fetchAll`, `markRead`, `markAll`.
|
||||
- `frontend/src/components/NotificationBell.vue` (new): bell SVG icon with unread count badge, document-click-outside close, 60s polling interval, toggles `NotificationsPanel`.
|
||||
- `frontend/src/components/NotificationsPanel.vue` (new): absolute-positioned dropdown listing unread notifications by type icon, bold inviter name, relative timestamp. "Mark all read" button. Click navigates to `payload.url`.
|
||||
- `frontend/src/components/ShareDialog.vue` (new): `<Teleport to="body">` modal. Props: `resourceType: 'project' | 'note'`, `resourceId`, `resourceTitle`. User tab: debounced user search dropdown + permission select + Add button. Group tab: group picker + permission select. Current shares list with inline permission change and remove.
|
||||
- `frontend/src/views/SharedWithMeView.vue` (new): `/shared` route. Grid of shared projects (color bar, title, owner, permission badge). List of shared notes/tasks (icon, title, owner, permission badge).
|
||||
- `frontend/src/components/AppHeader.vue`: `NotificationBell` added to `nav-right` before the `?` button; "Shared" nav link added to desktop center nav and mobile menu.
|
||||
- `frontend/src/views/ProjectView.vue`: "Share" button + `showShare` ref + `<ShareDialog>` at template bottom.
|
||||
- `frontend/src/views/NoteViewerView.vue`: "Share" button in toolbar + `<ShareDialog>` after layout root.
|
||||
- `frontend/src/views/TaskViewerView.vue`: "Share" button in toolbar + `<ShareDialog>` after layout root.
|
||||
- `frontend/src/views/SettingsView.vue`: "groups" added to `VALID_TABS`; Groups admin tab added to sidebar. Groups panel: create group form, groups list with member count, per-group "Manage" panel with user search + role select + add, member list with per-member remove.
|
||||
- `frontend/src/router/index.ts`: `/shared` → `SharedWithMeView` route added.
|
||||
|
||||
**Backup rewrite:**
|
||||
- `src/fabledassistant/services/backup.py`: full rewrite to version 2. `export_full_backup()` and `export_user_backup()` now include all tables: projects, milestones, task logs, note drafts (AI draft model), note versions, push subscriptions. `restore_full_backup()` dispatches to `_restore_v1()` or `_restore_v2()` by version key. `_restore_v2()` builds ID maps (`user_id_map`, `project_id_map`, `milestone_id_map`, `note_id_map`); two-pass note restore patches `parent_id` after all notes are inserted.
|
||||
|
||||
---
|
||||
|
||||
**Previous session (2026-03-10):** Feature batch: workspace view, graph view, settings tabs, message queue persistence, ToolCallCard direct-API confirm, duplicate detection scoping, push notification fixes.
|
||||
|
||||
**UI polish pass — design language:**
|
||||
- `frontend/src/assets/theme.css`: added Fraunces Google Font import; `h1/h2/h3` use `font-family: 'Fraunces', Georgia, serif`; `--radius-md` 8→12px, `--radius-lg` 12→18px; added thin indigo-tinted scrollbars (4px); added bubble-specific CSS variables (`--color-bubble-user-*`, `--color-bubble-asst-shadow`); dark palette shifted from generic navy (#1a1a2e family) to slate-indigo (#111113 family).
|
||||
|
||||
Reference in New Issue
Block a user