feat(ui,api,db): implement notifications and custom templates with hand-drawn aesthetic

This commit introduces a significant update to both the frontend and backend, focusing on enhanced user engagement and a consistent visual identity.

Key changes include:

- **Frontend UI/UX Refactor**:
  - Implemented a "hand-drawn" aesthetic across the entire application using CSS overrides, custom SVG charts, and specific border/shadow styles to match the Excalidraw experience.
  - Added a new notification system in the Header to display user updates.
  - Enhanced the Template Picker with more variety and improved interaction models.
  - Added a "Presentation Mode" in the Editor.
  - Improved Dashboard visualizations with hand-drawn style sparklines and charts.
  - Added modal dialogs for creating drawings and templates with custom names.

- **Backend & API Enhancements**:
  - Implemented full CRUD support for custom templates, allowing users to save their drawings as reusable templates.
  - Added a notification service with endpoints to list, mark as read, and mark all as read.
  - Updated the API client to handle more robust JSON responses and error states.
  - Improved CORS/Origin validation in the HTTP middleware to handle proxy headers (`X-Forwarded-Host`, `X-Forwarded-Proto`) more reliably.

- **Database & Infrastructure**:
  - Added a new PostgreSQL migration for the `notifications` table.
  - Updated the data models in the workspace to support templates (including snapshot storage) and notifications.
  - Updated `.gitignore` to exclude graphify cache and AST files.
This commit is contained in:
Tomas Dvorak
2026-05-01 15:07:38 +02:00
parent f3f9e99a97
commit 462a70933d
28 changed files with 26645 additions and 289 deletions
+21
View File
@@ -143,6 +143,14 @@ type Template struct {
PreviewURL *string `json:"preview_url,omitempty"`
}
type CreateTemplateRequest struct {
TeamID string `json:"team_id"`
Name string `json:"name"`
Description string `json:"description"`
Snapshot json.RawMessage `json:"snapshot"`
Metadata map[string]any `json:"metadata"`
}
type ActivityEvent struct {
ID string `json:"id"`
ActorUserID *string `json:"actor_user_id"`
@@ -204,6 +212,19 @@ type LinkReference struct {
CreatedAt time.Time `json:"created_at"`
}
type Notification struct {
ID string `json:"id"`
UserID string `json:"user_id"`
Type string `json:"type"`
Title string `json:"title"`
Description string `json:"description"`
ResourceType string `json:"resource_type,omitempty"`
ResourceID string `json:"resource_id,omitempty"`
Read bool `json:"read"`
MetadataJSON map[string]any `json:"metadata_json"`
CreatedAt time.Time `json:"created_at"`
}
type WorkspaceStats struct {
Teams int `json:"teams"`
Members int `json:"members"`