feat: Add mobile responsive layout, open room access, and admin room management

Mobile Responsive Layout:
- Add useMediaQuery, useIsMobile, useIsTablet, useIsDesktop hooks for device detection
- Create MobileHeader component with hamburger menu and action drawer
- Create BottomToolbar for mobile navigation (Files, Members)
- Create SlidePanel component for full-screen mobile sidebars
- Update RoomDetail.tsx with mobile/desktop conditional rendering
- Update RoomList.tsx with single-column grid and touch-friendly buttons
- Add CSS custom properties for safe areas and touch targets (min 44px)
- Add mobile viewport meta tags for notched devices

Open Room Access:
- All authenticated users can view all rooms (not just their own)
- Users can join active rooms they're not members of
- Add is_member field to room responses
- Update room list API to return all rooms by default

Admin Room Management:
- Add permanent delete functionality for system admins
- Add delete confirmation dialog with room title verification
- Broadcast room deletion via WebSocket to connected users
- Add users search API for adding members

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
egg
2025-12-05 09:12:10 +08:00
parent 1e44a63a8e
commit 1d5d4d447d
48 changed files with 3505 additions and 401 deletions

View File

@@ -0,0 +1,32 @@
# Proposal: Add Admin Room Management
## Why
Currently, rooms can only be soft-deleted (archived) and non-admin users can still see archived rooms when filtering. This creates two issues:
1. **No permanent deletion**: Archived rooms remain in the database indefinitely, and there's no way to completely remove sensitive or test data.
2. **Archived rooms visible to all**: Non-admin users can view archived rooms by changing the status filter, which may expose historical data that should be hidden from general users.
## What Changes
### 1. Admin-Only Permanent Room Deletion
- Add new endpoint `DELETE /api/rooms/{room_id}/permanent`
- Only system administrator (ymirliu@panjit.com.tw) can execute
- Cascading hard delete of all related data (members, messages, files, reports)
- Clean up MinIO storage for associated files
- Broadcast WebSocket disconnect to active connections
### 2. Hide Archived Rooms from Non-Admin Users
- Modify room listing to exclude ARCHIVED status for non-admin users
- Even "All Status" filter will not show archived rooms for regular users
- Admin users retain full visibility of all room statuses
- Remove "Archived" option from frontend status filter for non-admin users
## Related Specs
- `chat-room`: Room access control and deletion
- `frontend-core`: Room list filtering UI
## Out of Scope
- Batch deletion of multiple rooms
- Scheduled auto-deletion of old archived rooms
- Restore deleted rooms from backup

View File

@@ -0,0 +1,66 @@
# chat-room Specification Delta
## ADDED Requirements
### Requirement: Admin Permanent Room Deletion
The system SHALL provide system administrators with the ability to permanently delete rooms, including all associated data (members, messages, files, reports). This operation is irreversible and restricted to system administrators only.
#### Scenario: Admin permanently deletes a room
- **WHEN** a system administrator sends `DELETE /api/rooms/{room_id}/permanent`
- **THEN** the system SHALL verify the user is ymirliu@panjit.com.tw
- **AND** hard delete the room record from incident_rooms table
- **AND** cascade delete all room_members records
- **AND** cascade delete all messages and related reactions/edit_history
- **AND** cascade delete all room_files records
- **AND** delete associated files from MinIO storage
- **AND** cascade delete all generated_reports records
- **AND** delete associated report files from MinIO storage
- **AND** broadcast disconnect event to any active WebSocket connections in the room
- **AND** return status 200 with `{"message": "Room permanently deleted"}`
#### Scenario: Non-admin attempts permanent deletion
- **WHEN** a non-admin user sends `DELETE /api/rooms/{room_id}/permanent`
- **THEN** the system SHALL return status 403 with "Only system administrators can permanently delete rooms"
#### Scenario: Permanent delete non-existent room
- **WHEN** a system administrator sends `DELETE /api/rooms/{room_id}/permanent` for a non-existent room
- **THEN** the system SHALL return status 404 with "Room not found"
### Requirement: Hide Archived Rooms from Non-Admin Users
The system SHALL hide rooms with ARCHIVED status from non-admin users in all listing operations, ensuring historical/archived data is only visible to system administrators.
#### Scenario: Non-admin lists rooms with any filter
- **WHEN** a non-admin user sends `GET /api/rooms` with any status filter (including no filter)
- **THEN** the system SHALL exclude all rooms with status "archived" from the response
- **AND** only return rooms with status "active" or "resolved"
#### Scenario: Non-admin explicitly requests archived rooms
- **WHEN** a non-admin user sends `GET /api/rooms?status=archived`
- **THEN** the system SHALL return an empty list
- **AND** return total count of 0
#### Scenario: Admin can view archived rooms
- **WHEN** a system administrator sends `GET /api/rooms?status=archived`
- **THEN** the system SHALL return all archived rooms
- **AND** include full room details
#### Scenario: Admin views all rooms including archived
- **WHEN** a system administrator sends `GET /api/rooms` without status filter
- **THEN** the system SHALL return all rooms regardless of status
- **AND** include archived rooms in the response
## MODIFIED Requirements
### Requirement: List and Filter Incident Rooms
The system SHALL provide endpoints to list incident rooms with filtering capabilities by status, incident type, severity, date range, and user membership. The system SHALL automatically exclude rooms with ARCHIVED status from listing results for non-admin users, ensuring archived rooms are only visible to system administrators.
#### Scenario: List all active rooms for current user
- **WHEN** an authenticated user sends `GET /api/rooms?status=active`
- **THEN** the system SHALL return all active rooms
- **AND** include room metadata (title, type, severity, member count, last activity)
- **AND** sort by last_activity_at descending (most recent first)
#### Scenario: Non-admin user lists rooms without status filter
- **WHEN** a non-admin user sends `GET /api/rooms` without status parameter
- **THEN** the system SHALL return rooms with status "active" or "resolved" only
- **AND** automatically exclude archived rooms from results

View File

@@ -0,0 +1,67 @@
# frontend-core Specification Delta
## MODIFIED Requirements
### Requirement: Incident Room List
The frontend SHALL display a filterable, searchable list of incident rooms accessible to the current user. The frontend SHALL restrict the status filter options to show only "Active" and "Resolved" for non-admin users, and SHALL display all status options including "Archived" only for system administrators.
#### Scenario: Filter rooms by status (Non-admin)
- **WHEN** a non-admin user views the status filter dropdown
- **THEN** the system SHALL:
- Display only "Active" and "Resolved" options
- NOT display "Archived" option
- NOT display "All Status" option that would include archived rooms
#### Scenario: Filter rooms by status (Admin)
- **WHEN** a system administrator views the status filter dropdown
- **THEN** the system SHALL:
- Display all status options: "All Status", "Active", "Resolved", "Archived"
- Allow viewing archived rooms
#### Scenario: Default status filter
- **WHEN** a user navigates to the room list page
- **THEN** the system SHALL:
- Default to "Active" status filter for all users
- Fetch only active rooms initially
## ADDED Requirements
### Requirement: Admin Room Deletion Interface
The frontend SHALL provide system administrators with the ability to permanently delete rooms through a dedicated UI control.
#### Scenario: Display delete button for admin
- **WHEN** a system administrator views a room detail page
- **THEN** the system SHALL:
- Display a "Delete Room Permanently" button in room settings/actions
- Style the button with warning color (red)
- Only show this button to admin users
#### Scenario: Hide delete button for non-admin
- **WHEN** a non-admin user views a room detail page
- **THEN** the system SHALL:
- NOT display permanent delete option
- Only show standard archive option (if owner)
#### Scenario: Confirm permanent deletion
- **WHEN** an admin clicks "Delete Room Permanently"
- **THEN** the system SHALL:
- Display a confirmation dialog with warning text
- Require typing room name to confirm (optional safety measure)
- Explain that deletion is irreversible
- Show what will be deleted (messages, files, reports)
#### Scenario: Execute permanent deletion
- **WHEN** an admin confirms permanent deletion
- **THEN** the system SHALL:
- Send DELETE request to `/api/rooms/{room_id}/permanent`
- Show loading state during deletion
- Navigate to room list on success
- Show success toast message
- Show error message on failure
#### Scenario: Handle active users in deleted room
- **WHEN** a room is permanently deleted while other users are viewing it
- **THEN** the system SHALL:
- Receive WebSocket disconnect event
- Display "Room has been deleted" message
- Navigate affected users to room list

View File

@@ -0,0 +1,89 @@
# Tasks: Add Admin Room Management
## Phase 1: Backend - Hide Archived Rooms
### 1.1 Modify room listing to exclude archived for non-admin
- [x] Update `room_service.list_user_rooms()` to filter out ARCHIVED status for non-admin
- [x] Ensure admin users can still see all statuses
- [x] Handle case where non-admin explicitly requests `status=archived` (return empty)
- [x] Write unit tests for filtered listing behavior
### 1.2 Update room count queries
- [x] Ensure total count excludes archived for non-admin
- [x] Verify pagination works correctly with filtered results
## Phase 2: Backend - Permanent Deletion
### 2.1 Fix room_files foreign key constraint
- [x] Add `ondelete="CASCADE"` to room_files.room_id foreign key
- [x] Create database migration or rebuild schema
### 2.2 Create permanent delete service method
- [x] Add `permanent_delete_room()` method to room_service
- [x] Implement cascading delete for all related tables
- [x] Add MinIO file cleanup logic
- [x] Handle WebSocket broadcast for room deletion event
### 2.3 Create permanent delete endpoint
- [x] Add `DELETE /api/rooms/{room_id}/permanent` endpoint
- [x] Implement admin-only authorization check
- [x] Return appropriate error responses (403 for non-admin, 404 for not found)
- [x] Write integration tests
## Phase 3: Frontend - Status Filter Changes
### 3.1 Add admin detection to frontend
- [x] Create utility to check if current user is admin
- [x] Store admin status in auth store or derive from username
### 3.2 Update room list status filter
- [x] Conditionally render filter options based on admin status
- [x] Remove "All Status" and "Archived" for non-admin users
- [x] Keep default filter as "Active"
- [x] Test filter behavior for both user types
## Phase 4: Frontend - Permanent Delete UI
### 4.1 Add delete button to room detail
- [x] Create "Delete Room Permanently" button (admin only)
- [x] Style with warning/danger color scheme
- [x] Position in room settings or header actions
### 4.2 Implement confirmation dialog
- [x] Create confirmation modal with warning text
- [x] List what will be deleted (members, messages, files, reports)
- [x] Add optional room name confirmation input
- [x] Implement cancel and confirm buttons
### 4.3 Handle deletion flow
- [x] Call DELETE `/api/rooms/{room_id}/permanent` on confirm
- [x] Show loading state during deletion
- [x] Navigate to room list on success
- [x] Display error toast on failure
### 4.4 Handle WebSocket room deletion event
- [x] Listen for room_deleted event in WebSocket handler
- [x] Display notification to affected users
- [x] Navigate users away from deleted room
## Phase 5: Testing & Validation
### 5.1 Backend tests
- [x] Test non-admin cannot see archived rooms
- [x] Test admin can see all rooms including archived
- [x] Test permanent delete endpoint authorization
- [x] Test cascading delete removes all related data
- [x] Test MinIO cleanup on permanent delete
### 5.2 Frontend tests
- [x] Test status filter options for admin vs non-admin
- [x] Test delete button visibility
- [x] Test confirmation dialog flow
- [x] Test WebSocket room deletion handling
## Validation Checklist
- [x] Run `openspec validate add-admin-room-management --strict`
- [x] All existing tests pass
- [x] New tests cover all scenarios
- [x] Manual testing of full admin flow
- [x] Manual testing of non-admin restrictions