feat: implement comments and activity panel in workspace

- Added CommentsPanel component for managing comments on documents.
- Integrated comment creation, deletion, and resolution functionalities.
- Implemented activity tracking for document interactions.
- Enhanced SketchPage with editing and saving capabilities.
- Introduced template management API endpoints for creating, sharing, and deleting templates.
- Added runtime validation report for frontend and backend.
- Created GettingStartedPanel for user onboarding with template options.
- Implemented Playwright E2E tests for accessibility and export functionality.
This commit is contained in:
Anurag Jangid 2026-10-22 21:18:10 +05:30
parent 6e354ba041
commit 809235e962
41 changed files with 2840 additions and 285 deletions

View file

@ -0,0 +1,44 @@
from datetime import datetime
from pydantic import BaseModel, Field
class CommentCreate(BaseModel):
body: str = Field(min_length=1, max_length=5000)
parent_id: str | None = None
class CommentResponse(BaseModel):
id: str
document_id: str
body: str
parent_id: str | None = None
author_id: int
author_name: str
created_at: datetime
updated_at: datetime
resolved: bool = False
class CommentResolveRequest(BaseModel):
resolved: bool
class NotificationResponse(BaseModel):
id: str
kind: str
message: str
document_id: str | None = None
comment_id: str | None = None
actor_name: str
read: bool
created_at: datetime
class ActivityResponse(BaseModel):
id: str
document_id: str
kind: str
message: str
actor_name: str
created_at: datetime

View file

@ -21,12 +21,15 @@ class DocumentCreate(BaseModel):
content: dict[str, Any] = Field(default_factory=dict)
template_id: str | None = None
stead_id: str | None = None
parent_page_id: str | None = None
class DocumentUpdate(BaseModel):
title: str | None = None
content: dict[str, Any] | None = None
starred: bool | None = None
stead_id: str | None = None
parent_page_id: str | None = None
class ShareRequest(BaseModel):
@ -40,6 +43,7 @@ class DocumentResponse(BaseModel):
title: str
template_id: str | None = None
stead_id: str | None = None
parent_page_id: str | None = None
content: dict[str, Any]
created_by: str
created_at: datetime
@ -49,3 +53,13 @@ class DocumentResponse(BaseModel):
owner_id: int | None = None
visibility: Visibility = "private"
members: list[DocumentMember] = Field(default_factory=list)
class DocumentVersionResponse(BaseModel):
id: str
document_id: str
title: str
content: dict[str, Any]
created_by: str
created_at: datetime
reason: str

View file

@ -0,0 +1,24 @@
from datetime import datetime
from typing import Any
from pydantic import BaseModel, Field
class TemplateCreate(BaseModel):
name: str = Field(min_length=1, max_length=120)
description: str = Field(default="", max_length=500)
category: str = Field(default="General", min_length=1, max_length=60)
emoji: str = Field(default="📄", max_length=8)
content: dict[str, Any] = Field(default_factory=dict)
class TemplateResponse(TemplateCreate):
id: str
owner_id: int
created_at: datetime
updated_at: datetime
members: list[dict[str, Any]] = Field(default_factory=list)
class TemplateShareRequest(BaseModel):
email_or_username: str

View file

@ -23,6 +23,11 @@ class UserUpdate(BaseModel):
occupation: str | None = Field(default=None, max_length=150)
class ChangePasswordRequest(BaseModel):
current_password: str = Field(min_length=1, max_length=128)
new_password: str = Field(min_length=8, max_length=128)
class UserResponse(UserBase):
model_config = ConfigDict(from_attributes=True)