Fix collection manager JavaScript errors after attribute naming changes
- Update collection manager to use data-collection-id instead of data-content-id - Add safety checks to prevent undefined Map access in addItemControls - Add validation in editor to only initialize collections with valid collection IDs - Resolves TypeError and missing attribute errors in frontend collection management
This commit is contained in:
@@ -1,138 +0,0 @@
|
|||||||
# Collection Reordering Bug Fix - Implementation Plan
|
|
||||||
|
|
||||||
## Problem Summary
|
|
||||||
Collection item reordering fails after content edits. Position updates work at API level but don't persist through the enhancement cycle, causing items to revert to original order after page refresh.
|
|
||||||
|
|
||||||
## Root Cause Analysis
|
|
||||||
1. **Missing HTML Attributes**: `data-item-id` not injected during enhancement (around line 622 in `reconstructCollectionItems()`)
|
|
||||||
2. **API Design Flaw**: No bulk reorder endpoint, only individual item updates
|
|
||||||
3. **ID Generation Inconsistency**: Different patterns for initial items vs new items
|
|
||||||
4. **Attribute Naming Issues**: Collection containers incorrectly use `data-content-id`, content has special `collection-item-` prefixes
|
|
||||||
5. **Obsolete Attributes**: `data-content-type` no longer needed after HTML-only switch
|
|
||||||
6. **Dynamic vs Static**: Frontend dynamically injects IDs instead of getting them from enhanced HTML
|
|
||||||
|
|
||||||
## Architecture Principles
|
|
||||||
- **Static Enhancement**: All IDs should be injected during enhancement, not dynamically by JavaScript
|
|
||||||
- **Unified ID Generation**: Same deterministic system for all entities (content, collections, items)
|
|
||||||
- **Clean Separation**: Collections manage structure, `.insertr` elements manage content
|
|
||||||
- **No Backwards Compatibility**: Clean slate approach, all test data can be cleared
|
|
||||||
|
|
||||||
## Implementation Plan
|
|
||||||
|
|
||||||
### Phase 1: Backend Enhancement Fixes
|
|
||||||
|
|
||||||
#### File: `/home/fitz/insertr/internal/engine/engine.go`
|
|
||||||
- **Line 622**: Add `data-item-id` injection in `reconstructCollectionItems()`
|
|
||||||
- **Line 812**: Replace `initial-` ID pattern with unified generator
|
|
||||||
- **Line 734**: Replace timestamp-based ID pattern with unified generator
|
|
||||||
- **Line 107**: Change collection containers from `data-content-id` to `data-collection-id`
|
|
||||||
|
|
||||||
#### File: `/home/fitz/insertr/internal/engine/injector.go`
|
|
||||||
- **Line 165**: Remove obsolete `data-content-type` attribute injection
|
|
||||||
|
|
||||||
### Phase 2: Frontend API Updates
|
|
||||||
|
|
||||||
#### File: `/home/fitz/insertr/lib/src/core/api-client.js`
|
|
||||||
- Add `reorderCollection()` method for bulk operations
|
|
||||||
- Remove `updateCollectionItemPosition()` method (individual updates)
|
|
||||||
|
|
||||||
#### File: `/home/fitz/insertr/lib/src/ui/collection-manager.js`
|
|
||||||
- Remove dynamic ID injection logic (around line 286)
|
|
||||||
- Update attribute names from `data-collection-item-id` to `data-item-id`
|
|
||||||
- Replace individual position updates with bulk reorder calls
|
|
||||||
|
|
||||||
### Phase 3: Backend API Enhancement
|
|
||||||
|
|
||||||
#### File: `/home/fitz/insertr/internal/api/handlers.go`
|
|
||||||
- Add `ReorderCollection` handler for bulk position updates
|
|
||||||
- Endpoint: `PUT /api/sites/{siteId}/collections/{collectionId}/reorder`
|
|
||||||
|
|
||||||
## Expected HTML Output Change
|
|
||||||
|
|
||||||
### Before
|
|
||||||
```html
|
|
||||||
<div class="testimonials insertr-add" data-content-id="index-testimonials-3ef43e">
|
|
||||||
<div class="testimonial-item"> <!-- Missing data-item-id -->
|
|
||||||
<blockquote class="insertr" data-content-id="collection-item-blockquote-756544" data-content-type="html">
|
|
||||||
```
|
|
||||||
|
|
||||||
### After
|
|
||||||
```html
|
|
||||||
<div class="testimonials insertr-add" data-collection-id="index-testimonials-3ef43e">
|
|
||||||
<div class="testimonial-item" data-item-id="index-testimonials-3ef43e-abc123">
|
|
||||||
<blockquote class="insertr" data-content-id="index-blockquote-def456">
|
|
||||||
```
|
|
||||||
|
|
||||||
## Implementation Steps
|
|
||||||
|
|
||||||
### Day 1: Backend Enhancement
|
|
||||||
1. **Clear test data**: Clean database for fresh start
|
|
||||||
2. **Fix ID injection**: Add `data-item-id` attributes during enhancement
|
|
||||||
3. **Unify ID generation**: Replace inconsistent patterns with unified system
|
|
||||||
4. **Update attribute names**: Change `data-content-id` to `data-collection-id` for collections
|
|
||||||
5. **Remove obsolete attributes**: Clean up `data-content-type`
|
|
||||||
|
|
||||||
### Day 2: Frontend Updates
|
|
||||||
1. **Remove dynamic injection**: Stop generating IDs in JavaScript
|
|
||||||
2. **Update attribute references**: Change to new naming convention
|
|
||||||
3. **Add bulk reorder API**: Implement `reorderCollection()` method
|
|
||||||
4. **Update collection manager**: Use bulk operations instead of individual updates
|
|
||||||
|
|
||||||
### Day 3: Backend API
|
|
||||||
1. **Add bulk reorder endpoint**: Implement `ReorderCollection` handler
|
|
||||||
2. **Route configuration**: Add PUT endpoint for bulk reorder
|
|
||||||
3. **Database operations**: Efficient bulk position updates
|
|
||||||
|
|
||||||
### Day 4: Testing & Validation
|
|
||||||
1. **Test enhancement cycle**: Verify positions persist after content edits
|
|
||||||
2. **Test reordering**: Ensure drag-and-drop works correctly
|
|
||||||
3. **Test page refresh**: Confirm order maintained after reload
|
|
||||||
4. **Cross-browser testing**: Verify compatibility
|
|
||||||
|
|
||||||
## Current Status
|
|
||||||
- ✅ API endpoint accepts `site_id` as query parameter correctly
|
|
||||||
- ✅ Root cause analysis complete
|
|
||||||
- ✅ Implementation plan finalized
|
|
||||||
- ✅ **Phase 1 COMPLETE**: Backend enhancement injection implemented
|
|
||||||
- ✅ Unified ID generation across all entities (collections, items, content)
|
|
||||||
- ✅ Data attribute injection working (data-collection-id, data-item-id, data-content-id)
|
|
||||||
- ✅ Obsolete attributes removed (data-content-type)
|
|
||||||
- ✅ **Phase 2 COMPLETE**: Frontend API updates implemented
|
|
||||||
- ✅ Dynamic ID injection removed (except for new items from server)
|
|
||||||
- ✅ Attribute references updated to data-item-id
|
|
||||||
- ✅ Bulk reorderCollection() API method added
|
|
||||||
- ✅ Individual updateCollectionItemPosition() method removed
|
|
||||||
- ✅ Collection manager uses bulk reorder with optimistic UI
|
|
||||||
- ✅ **Phase 3 COMPLETE**: Backend bulk reorder endpoint implemented
|
|
||||||
- ✅ ReorderCollection handler added with transaction-based bulk updates
|
|
||||||
- ✅ PUT /api/collections/{id}/reorder route configured
|
|
||||||
- ✅ Updated sqlc queries to include last_edited_by in position updates
|
|
||||||
- ✅ Atomic transaction ensures consistency during bulk reorder operations
|
|
||||||
|
|
||||||
## Test Environment
|
|
||||||
- Server: `just dev` (http://localhost:8080)
|
|
||||||
- Test site: `/sites/simple/` with testimonials collection
|
|
||||||
- Database: Shows position conflicts (multiple items at position 1)
|
|
||||||
|
|
||||||
## Success Criteria ✅
|
|
||||||
1. ✅ Collection items maintain order after content edits (Phase 1)
|
|
||||||
2. ✅ Drag-and-drop reordering works without page refresh (Phase 2+3)
|
|
||||||
3. ✅ Order persists through full enhancement cycles (Phase 1)
|
|
||||||
4. ✅ Clean HTML output with proper attributes (Phase 1)
|
|
||||||
5. ✅ No JavaScript errors in browser console (Phase 2)
|
|
||||||
|
|
||||||
## 🎉 IMPLEMENTATION COMPLETE
|
|
||||||
|
|
||||||
All three phases have been successfully implemented:
|
|
||||||
|
|
||||||
**Phase 1**: ✅ Backend enhancement injection with unified ID generation
|
|
||||||
**Phase 2**: ✅ Frontend API updates with bulk operations and optimistic UI
|
|
||||||
**Phase 3**: ✅ Backend bulk reorder endpoint with atomic transactions
|
|
||||||
|
|
||||||
Collection item reordering now works end-to-end with persistence through content edits!
|
|
||||||
|
|
||||||
## Notes
|
|
||||||
- All test data can be cleared - no backwards compatibility needed
|
|
||||||
- Focus on clean implementation over migration
|
|
||||||
- HTML-first approach: all attributes come from server enhancement
|
|
||||||
- Performance: bulk operations instead of individual API calls
|
|
||||||
1
lib/package-lock.json
generated
1
lib/package-lock.json
generated
@@ -311,6 +311,7 @@
|
|||||||
"integrity": "sha512-GVsDdsbJzzy4S/v3dqWPJ7EfvZJfCHiDqe80IyrF59LYuP+e6U1LJoUqeuqRbwAWoMNoXivMNeNAOf5E22VA1w==",
|
"integrity": "sha512-GVsDdsbJzzy4S/v3dqWPJ7EfvZJfCHiDqe80IyrF59LYuP+e6U1LJoUqeuqRbwAWoMNoXivMNeNAOf5E22VA1w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"rollup": "dist/bin/rollup"
|
"rollup": "dist/bin/rollup"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -79,8 +79,10 @@ export class InsertrEditor {
|
|||||||
|
|
||||||
initializeCollection(meta) {
|
initializeCollection(meta) {
|
||||||
const collectionManager = new CollectionManager(meta, this.apiClient, this.auth);
|
const collectionManager = new CollectionManager(meta, this.apiClient, this.auth);
|
||||||
|
if (collectionManager.collectionId) {
|
||||||
collectionManager.initialize();
|
collectionManager.initialize();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
addClickHandler(element, meta) {
|
addClickHandler(element, meta) {
|
||||||
element.addEventListener('click', (e) => {
|
element.addEventListener('click', (e) => {
|
||||||
|
|||||||
@@ -18,9 +18,9 @@ export class CollectionManager {
|
|||||||
this.auth = auth;
|
this.auth = auth;
|
||||||
|
|
||||||
// Extract collection ID from container
|
// Extract collection ID from container
|
||||||
this.collectionId = this.container.getAttribute('data-content-id');
|
this.collectionId = this.container.getAttribute('data-collection-id');
|
||||||
if (!this.collectionId) {
|
if (!this.collectionId) {
|
||||||
console.error('❌ Collection container missing data-content-id attribute');
|
console.error('❌ Collection container missing data-collection-id attribute');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -331,7 +331,7 @@ export class CollectionManager {
|
|||||||
* Add management controls to an item (remove, reorder)
|
* Add management controls to an item (remove, reorder)
|
||||||
*/
|
*/
|
||||||
addItemControls(itemElement, index) {
|
addItemControls(itemElement, index) {
|
||||||
if (this.itemControls.has(itemElement)) return; // Already has controls
|
if (!this.itemControls || this.itemControls.has(itemElement)) return; // Already has controls or not initialized
|
||||||
|
|
||||||
const controls = document.createElement('div');
|
const controls = document.createElement('div');
|
||||||
controls.className = 'insertr-item-controls';
|
controls.className = 'insertr-item-controls';
|
||||||
|
|||||||
Reference in New Issue
Block a user