feat: Add Chat UX improvements with notifications and @mention support

- Add ActionBar component with expandable toolbar for mobile
- Add @mention functionality with autocomplete dropdown
- Add browser notification system (push, sound, vibration)
- Add NotificationSettings modal for user preferences
- Add mention badges on room list cards
- Add ReportPreview with Markdown rendering and copy/download
- Add message copy functionality with hover actions
- Add backend mentions field to messages with Alembic migration
- Add lots field to rooms, remove templates
- Optimize WebSocket database session handling
- Various UX polish (animations, accessibility)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
egg
2025-12-08 08:20:37 +08:00
parent 92834dbe0e
commit 599802b818
72 changed files with 6810 additions and 702 deletions

View File

@@ -13,7 +13,6 @@ from app.modules.chat_room import schemas
from app.modules.chat_room.models import MemberRole, RoomStatus
from app.modules.chat_room.services.room_service import room_service
from app.modules.chat_room.services.membership_service import membership_service
from app.modules.chat_room.services.template_service import template_service
from app.modules.chat_room.dependencies import (
get_current_room,
require_room_permission,
@@ -36,25 +35,7 @@ async def create_room(
"""Create a new incident room"""
user_email = current_user["username"]
# Check if using template
if room_data.template:
template = template_service.get_template_by_name(db, room_data.template)
if template:
room = template_service.create_room_from_template(
db,
template.template_id,
user_email,
room_data.title,
room_data.location,
room_data.description
)
else:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"Template '{room_data.template}' not found"
)
else:
room = room_service.create_room(db, user_email, room_data)
room = room_service.create_room(db, user_email, room_data)
# Get user role for response
role = membership_service.get_user_role_in_room(db, room.room_id, user_email)
@@ -508,12 +489,56 @@ async def get_user_permissions(
return permissions[role]
# Template Endpoints
@router.get("/templates", response_model=List[schemas.TemplateResponse])
async def list_templates(
db: Session = Depends(get_db),
_: dict = Depends(get_current_user)
# LOT Endpoints
@router.post("/{room_id}/lots", response_model=List[str])
async def add_lot(
room_id: str,
request: schemas.AddLotRequest,
_: None = Depends(require_room_permission("update_metadata")),
db: Session = Depends(get_db)
):
"""List available room templates"""
templates = template_service.get_templates(db)
return [schemas.TemplateResponse.from_orm(t) for t in templates]
"""Add a LOT batch number to the room"""
from app.modules.chat_room.models import IncidentRoom
room = db.query(IncidentRoom).filter(IncidentRoom.room_id == room_id).first()
if not room:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Room not found")
# Get current lots or initialize empty list
current_lots = room.lots or []
# Prevent duplicates
if request.lot not in current_lots:
current_lots.append(request.lot)
room.lots = current_lots
room.last_updated_at = datetime.utcnow()
db.commit()
db.refresh(room)
return room.lots
@router.delete("/{room_id}/lots/{lot}", response_model=List[str])
async def remove_lot(
room_id: str,
lot: str,
_: None = Depends(require_room_permission("update_metadata")),
db: Session = Depends(get_db)
):
"""Remove a LOT batch number from the room"""
from app.modules.chat_room.models import IncidentRoom
room = db.query(IncidentRoom).filter(IncidentRoom.room_id == room_id).first()
if not room:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Room not found")
current_lots = room.lots or []
if lot in current_lots:
current_lots.remove(lot)
room.lots = current_lots
room.last_updated_at = datetime.utcnow()
db.commit()
db.refresh(room)
return room.lots