Init Repo
This commit is contained in:
@@ -0,0 +1,286 @@
|
||||
# Permanent Delete Workflow Implementation
|
||||
|
||||
## Overview
|
||||
|
||||
This document describes the implementation of the permanent delete confirmation workflow for the Recovery Management feature (Task 9).
|
||||
|
||||
## Requirements
|
||||
|
||||
Task 9 requires the following functionality:
|
||||
1. Wire up confirmation dialog to permanent delete actions
|
||||
2. Implement confirmation token validation
|
||||
3. Add loading states during permanent deletion
|
||||
4. Handle success and error responses appropriately
|
||||
5. Update UI state after successful permanent deletion
|
||||
|
||||
## Implementation Details
|
||||
|
||||
### 1. Confirmation Dialog Integration
|
||||
|
||||
The permanent delete workflow is initiated from the `DeletedItemsManagementView.vue` component:
|
||||
|
||||
#### Single Item Deletion
|
||||
```typescript
|
||||
const handlePermanentDelete = (type: 'shot' | 'asset', item: DeletedShot | DeletedAsset) => {
|
||||
const deleteItem = {
|
||||
id: item.id,
|
||||
name: item.name,
|
||||
type,
|
||||
project_name: item.project_name,
|
||||
episode_name: 'episode_name' in item ? item.episode_name : undefined,
|
||||
task_count: item.task_count,
|
||||
submission_count: item.submission_count,
|
||||
attachment_count: item.attachment_count,
|
||||
note_count: item.note_count,
|
||||
review_count: item.review_count
|
||||
}
|
||||
|
||||
itemsToDelete.value = [deleteItem]
|
||||
permanentDeleteType.value = 'single'
|
||||
showPermanentDeleteDialog.value = true
|
||||
}
|
||||
```
|
||||
|
||||
#### Bulk Deletion
|
||||
```typescript
|
||||
const handleBulkPermanentDelete = () => {
|
||||
const deleteItems = selectedItems.value.map(item => {
|
||||
// Maps selected items to the required format
|
||||
}).filter((item): item is NonNullable<typeof item> => item !== null)
|
||||
|
||||
itemsToDelete.value = deleteItems
|
||||
permanentDeleteType.value = 'bulk'
|
||||
showPermanentDeleteDialog.value = true
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Confirmation Token Validation
|
||||
|
||||
The `PermanentDeleteConfirmDialog.vue` component implements a secure confirmation workflow:
|
||||
|
||||
#### Token Generation
|
||||
```typescript
|
||||
const generateConfirmationToken = (): string => {
|
||||
if (isBulkOperation.value) {
|
||||
const shotCount = props.items.filter(item => item.type === 'shot').length
|
||||
const assetCount = props.items.filter(item => item.type === 'asset').length
|
||||
|
||||
if (shotCount > 0 && assetCount > 0) {
|
||||
return 'CONFIRM_MIXED_BULK_PERMANENT_DELETE'
|
||||
} else if (shotCount > 0) {
|
||||
return 'CONFIRM_BULK_SHOTS_PERMANENT_DELETE'
|
||||
} else {
|
||||
return 'CONFIRM_BULK_ASSETS_PERMANENT_DELETE'
|
||||
}
|
||||
} else {
|
||||
const item = props.items[0]
|
||||
if (item.type === 'shot') {
|
||||
return 'CONFIRM_SHOT_PERMANENT_DELETE'
|
||||
} else {
|
||||
return 'CONFIRM_ASSET_PERMANENT_DELETE'
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### User Confirmation
|
||||
- User must type the exact confirmation phrase (e.g., "DELETE Shot_001" or "DELETE 5 ITEMS")
|
||||
- Paste is disabled to prevent accidental confirmations
|
||||
- Delete button is disabled until confirmation phrase matches exactly
|
||||
|
||||
### 3. Loading States
|
||||
|
||||
Loading states are managed throughout the deletion process:
|
||||
|
||||
```typescript
|
||||
// State management
|
||||
const isPermanentDeleting = ref(false)
|
||||
|
||||
// In the dialog component
|
||||
<Button
|
||||
variant="destructive"
|
||||
@click="handleDelete"
|
||||
:disabled="!isConfirmed || isDeleting || isLoadingInfo || !!loadError"
|
||||
>
|
||||
<Loader2 v-if="isDeleting" class="mr-2 h-4 w-4 animate-spin" />
|
||||
<Trash2 v-else class="mr-2 h-4 w-4" />
|
||||
{{ isDeleting ? 'Deleting...' : 'Permanently Delete' }}
|
||||
</Button>
|
||||
```
|
||||
|
||||
### 4. Success and Error Response Handling
|
||||
|
||||
The `executePermanentDelete` function handles all response scenarios:
|
||||
|
||||
```typescript
|
||||
const executePermanentDelete = async (confirmationToken: string) => {
|
||||
try {
|
||||
isPermanentDeleting.value = true
|
||||
|
||||
if (permanentDeleteType.value === 'single') {
|
||||
const item = itemsToDelete.value[0]
|
||||
let result
|
||||
|
||||
if (item.type === 'shot') {
|
||||
result = await recoveryService.permanentDeleteShot(item.id, confirmationToken)
|
||||
} else {
|
||||
result = await recoveryService.permanentDeleteAsset(item.id, confirmationToken)
|
||||
}
|
||||
|
||||
toast({
|
||||
title: 'Permanent Deletion Successful',
|
||||
description: `${result.name} and all related data have been permanently deleted`,
|
||||
})
|
||||
|
||||
// Update UI state (see section 5)
|
||||
} else {
|
||||
// Handle bulk deletion with detailed feedback
|
||||
// Shows success count and any errors
|
||||
}
|
||||
|
||||
showPermanentDeleteDialog.value = false
|
||||
itemsToDelete.value = []
|
||||
} catch (err: any) {
|
||||
toast({
|
||||
title: 'Permanent Deletion Failed',
|
||||
description: err.response?.data?.detail || 'Failed to permanently delete items',
|
||||
variant: 'destructive'
|
||||
})
|
||||
} finally {
|
||||
isPermanentDeleting.value = false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 5. UI State Updates
|
||||
|
||||
After successful deletion, the UI is updated to reflect the changes:
|
||||
|
||||
```typescript
|
||||
// Remove from lists
|
||||
if (item.type === 'shot') {
|
||||
deletedShots.value = deletedShots.value.filter(s => s.id !== item.id)
|
||||
selectedItems.value = selectedItems.value.filter(selected =>
|
||||
!(selected.type === 'shot' && selected.id === item.id))
|
||||
} else {
|
||||
deletedAssets.value = deletedAssets.value.filter(a => a.id !== item.id)
|
||||
selectedItems.value = selectedItems.value.filter(selected =>
|
||||
!(selected.type === 'asset' && selected.id === item.id))
|
||||
}
|
||||
|
||||
// Close dialog and clear state
|
||||
showPermanentDeleteDialog.value = false
|
||||
itemsToDelete.value = []
|
||||
```
|
||||
|
||||
## Backend Implementation
|
||||
|
||||
### API Endpoints
|
||||
|
||||
The backend provides the following endpoints:
|
||||
|
||||
1. **Single Shot Deletion**: `DELETE /admin/shots/{shot_id}/permanent`
|
||||
2. **Single Asset Deletion**: `DELETE /admin/assets/{asset_id}/permanent`
|
||||
3. **Bulk Shot Deletion**: `DELETE /admin/shots/bulk-permanent`
|
||||
4. **Bulk Asset Deletion**: `DELETE /admin/assets/bulk-permanent`
|
||||
|
||||
### Security Features
|
||||
|
||||
1. **Rate Limiting**: Maximum 10 permanent delete operations per minute per user
|
||||
2. **Token Validation**: Backend validates confirmation tokens before proceeding
|
||||
3. **Transaction Safety**: All deletions are performed within database transactions
|
||||
4. **Rollback on Failure**: If any part of the deletion fails, all changes are rolled back
|
||||
5. **Audit Logging**: All permanent deletions are logged for audit purposes
|
||||
|
||||
### Cascading Deletion
|
||||
|
||||
The backend ensures complete data removal:
|
||||
- Tasks associated with the shot/asset
|
||||
- Submissions and their files
|
||||
- Attachments and their files
|
||||
- Production notes
|
||||
- Reviews
|
||||
- Activity records
|
||||
- File system cleanup
|
||||
|
||||
## Frontend Service Layer
|
||||
|
||||
The `recovery.ts` service provides type-safe methods:
|
||||
|
||||
```typescript
|
||||
async permanentDeleteShot(shotId: number, confirmationToken: string): Promise<PermanentDeleteResult>
|
||||
async permanentDeleteAsset(assetId: number, confirmationToken: string): Promise<PermanentDeleteResult>
|
||||
async bulkPermanentDeleteShots(shotIds: number[], confirmationToken: string): Promise<BulkPermanentDeleteResult>
|
||||
async bulkPermanentDeleteAssets(assetIds: number[], confirmationToken: string): Promise<BulkPermanentDeleteResult>
|
||||
```
|
||||
|
||||
## User Experience Flow
|
||||
|
||||
1. User navigates to Recovery Management page
|
||||
2. User selects item(s) to permanently delete
|
||||
3. User clicks "Permanent Delete" button
|
||||
4. Confirmation dialog appears with:
|
||||
- Warning about irreversible action
|
||||
- List of items to be deleted
|
||||
- Impact summary (tasks, files, etc.)
|
||||
- Confirmation phrase requirement
|
||||
5. User types exact confirmation phrase
|
||||
6. Delete button becomes enabled
|
||||
7. User clicks "Permanently Delete"
|
||||
8. Loading state shows during deletion
|
||||
9. Success/error toast notification appears
|
||||
10. UI updates to remove deleted items
|
||||
11. Dialog closes automatically
|
||||
|
||||
## Testing Recommendations
|
||||
|
||||
To verify the implementation:
|
||||
|
||||
1. **Single Item Deletion**
|
||||
- Test shot deletion with correct confirmation
|
||||
- Test asset deletion with correct confirmation
|
||||
- Verify UI updates after deletion
|
||||
|
||||
2. **Bulk Deletion**
|
||||
- Test bulk deletion of shots only
|
||||
- Test bulk deletion of assets only
|
||||
- Test bulk deletion of mixed items
|
||||
|
||||
3. **Error Scenarios**
|
||||
- Test with invalid confirmation phrase
|
||||
- Test network error handling
|
||||
- Test rate limit enforcement
|
||||
|
||||
4. **UI States**
|
||||
- Verify loading states during deletion
|
||||
- Verify disabled states during operation
|
||||
- Verify toast notifications
|
||||
|
||||
## Compliance with Requirements
|
||||
|
||||
✅ **Requirement 6.3**: Confirmation dialog with data loss warnings - Implemented
|
||||
✅ **Requirement 6.5**: Success messages and UI updates - Implemented
|
||||
✅ **Requirement 8.1**: Immediate data removal - Implemented
|
||||
✅ **Requirement 8.4**: Rollback on failure - Implemented
|
||||
|
||||
## Files Modified
|
||||
|
||||
### Frontend
|
||||
- `frontend/src/views/admin/DeletedItemsManagementView.vue` - Main view with workflow handlers
|
||||
- `frontend/src/components/admin/PermanentDeleteConfirmDialog.vue` - Confirmation dialog
|
||||
- `frontend/src/services/recovery.ts` - Service layer methods
|
||||
|
||||
### Backend
|
||||
- `backend/routers/admin.py` - API endpoints
|
||||
- `backend/services/recovery_service.py` - Business logic
|
||||
|
||||
## Conclusion
|
||||
|
||||
Task 9 has been successfully implemented with all required functionality:
|
||||
- ✅ Confirmation dialog integration
|
||||
- ✅ Token validation
|
||||
- ✅ Loading states
|
||||
- ✅ Success/error handling
|
||||
- ✅ UI state updates
|
||||
|
||||
The implementation provides a secure, user-friendly workflow for permanent deletion with proper safeguards and feedback mechanisms.
|
||||
Reference in New Issue
Block a user