mirror of
https://github.com/Freika/dawarich.git
synced 2026-01-10 01:01:39 -05:00
7.9 KiB
7.9 KiB
Bulk Delete Points Feature - Summary
Overview
Added a bulk delete feature that allows users to select multiple points on the map by drawing a rectangle and delete them all at once, with confirmation and without page reload.
Changes Made
Backend (API)
-
app/controllers/api/v1/points_controller.rb
- Added
bulk_destroyto authentication (before_action) on line 4 - Added
bulk_destroyaction (lines 48-59) that:- Accepts
point_idsarray parameter - Validates that points exist
- Deletes points belonging to current user
- Returns JSON with success message and count
- Accepts
- Added
bulk_destroy_paramsprivate method (lines 71-73) to permitpoint_idsarray
- Added
-
config/routes.rb (lines 127-131)
- Added
DELETE /api/v1/points/bulk_destroycollection route
- Added
Frontend
-
app/javascript/maps/visits.js
- Import (line 3): Added
createPolylinesLayerimport from./polylines - Constructor (line 8): Added
mapsControllerparameter to receive maps controller reference - Selection UI (lines 389-427): Updated
addSelectionCancelButton()to add:- "Cancel Selection" button (warning style)
- "Delete Points" button (error/danger style) with:
- Trash icon SVG
- Point count badge showing number of selected points
- Both buttons in flex container
- Delete Logic (lines 432-529): Added
deleteSelectedPoints()async method:- Extracts point IDs from
this.selectedPointsarray at index 6 (not 2!) - Shows confirmation dialog with warning message
- Makes DELETE request to
/api/v1/points/bulk_destroywith Bearer token auth - On success:
- Removes markers from map via
mapsController.removeMarker() - Updates polylines layer
- Updates heatmap with remaining points
- Updates fog layer if enabled
- Clears selection and removes buttons
- Shows success flash message
- Removes markers from map via
- On error: Shows error flash message
- Extracts point IDs from
- Polylines Update (lines 534-577): Added
updatePolylinesAfterDeletion()helper method:- Checks if polylines layer was visible before deletion
- Removes old polylines layer
- Creates new polylines layer with updated markers
- Re-adds to map ONLY if it was visible before (preserves layer state)
- Updates layer control with new polylines reference
- Import (line 3): Added
-
app/javascript/controllers/maps_controller.js (line 211)
- Pass
this(maps controller reference) when creating VisitsManager - Enables VisitsManager to call maps controller methods like
removeMarker(),updateFog(), etc.
- Pass
Technical Details
Point ID Extraction
The point array structure is:
[lat, lng, ?, ?, timestamp, ?, id, country, ?]
0 1 2 3 4 5 6 7 8
So point ID is at index 6, not index 2!
API Request Format
DELETE /api/v1/points/bulk_destroy
Headers:
Authorization: Bearer {apiKey}
Content-Type: application/json
X-CSRF-Token: {token}
Body:
{
"point_ids": ["123", "456", "789"]
}
API Response Format
Success (200):
{
"message": "Points were successfully destroyed",
"count": 3
}
Error (422):
{
"error": "No points selected"
}
Map Updates Without Page Reload
After deletion, the following map elements are updated:
- Markers: Removed via
mapsController.removeMarker(id)for each deleted point - Polylines/Routes: Recreated with remaining points, preserving visibility state
- Heatmap: Updated with
setLatLngs()using remaining markers - Fog of War: Recalculated if layer is enabled
- Layer Control: Rebuilt to reflect updated layers
- Selection: Cleared (rectangle removed, buttons hidden)
Layer State Preservation
The Routes layer visibility is preserved after deletion:
- If Routes was enabled before deletion → stays enabled
- If Routes was disabled before deletion → stays disabled
This is achieved by:
- Checking
map.hasLayer(polylinesLayer)before deletion - Storing state in
wasPolyLayerVisibleboolean - Only calling
polylinesLayer.addTo(map)if it was visible - Explicitly calling
map.removeLayer(polylinesLayer)if it was NOT visible
User Experience
Workflow
- User clicks area selection tool button (square with dashed border icon)
- Selection mode activates (map dragging disabled)
- User draws rectangle by clicking and dragging on map
- On mouse up:
- Rectangle finalizes
- Points within bounds are selected
- Visits drawer shows selected visits
- Two buttons appear at top of drawer:
- "Cancel Selection" (yellow/warning)
- "Delete Points" with count badge (red/error)
- User clicks "Delete Points" button
- Warning confirmation dialog appears:
⚠️ WARNING: This will permanently delete X points from your location history. This action cannot be undone! Are you sure you want to continue? - If confirmed:
- Points deleted via API
- Map updates without reload
- Success message: "Successfully deleted X points"
- Selection cleared automatically
- If canceled:
- No action taken
- Dialog closes
UI Elements
- Area Selection Button: Located in top-right corner of map, shows dashed square icon
- Cancel Button: Yellow/warning styled, full width in drawer
- Delete Button: Red/error styled, shows trash icon + count badge
- Count Badge: Small badge showing number of selected points (e.g., "5")
- Flash Messages: Success (green) or error (red) notifications
Testing
Playwright Tests (e2e/bulk-delete-points.spec.js)
Created 12 comprehensive tests covering:
- ✅ Area selection button visibility
- ✅ Selection mode activation
- ⏳ Point selection and delete button appearance (needs debugging)
- ⏳ Point count badge display (needs debugging)
- ⏳ Cancel/Delete button pair (needs debugging)
- ⏳ Cancel functionality (needs debugging)
- ⏳ Confirmation dialog (needs debugging)
- ⏳ Successful deletion with flash message (needs debugging)
- ⏳ Routes layer state preservation when disabled (needs debugging)
- ⏳ Routes layer state preservation when enabled (needs debugging)
- ⏳ Heatmap update after deletion (needs debugging)
- ⏳ Selection cleanup after deletion (needs debugging)
Note: Tests 1-3 pass, but tests involving the delete button are timing out. This may be due to:
- Points not being selected properly in test environment
- Drawer not opening
- Different date range needed
- Need to wait for visits API call to complete
Manual Testing Verified
- ✅ Area selection tool activation
- ✅ Rectangle drawing
- ✅ Point selection
- ✅ Delete button with count badge
- ✅ Confirmation dialog
- ✅ Successful deletion
- ✅ Map updates without reload
- ✅ Routes layer visibility preservation
- ✅ Heatmap updates
- ✅ Success flash messages
Security Considerations
- ✅ API endpoint requires authentication (
authenticate_active_api_user!) - ✅ Points are scoped to
current_api_user.points(can't delete other users' points) - ✅ Strong parameters used to permit only
point_idsarray - ✅ CSRF token included in request headers
- ✅ Confirmation dialog prevents accidental deletion
- ✅ Warning message clearly states action is irreversible
Performance Considerations
- Bulk deletion is more efficient than individual deletes (single API call)
- Map updates are batched (all markers removed, then layers updated once)
- No page reload means faster UX
- Potential improvement: Add loading indicator for large deletions
Future Enhancements
- Add loading indicator during deletion
- Add "Undo" functionality (would require soft deletes)
- Allow selection of individual points within rectangle (checkbox per point)
- Add keyboard shortcuts (Delete key to delete selected points)
- Add selection stats in drawer header (e.g., "15 points selected, 2.3 km total distance")
- Support polygon selection (not just rectangle)
- Add "Select All Points" button for current date range