feat: implement unified editor with content persistence and server-side upsert
- Replace dual update systems with single markdown-first editor architecture - Add server-side upsert to eliminate 404 errors on PUT operations - Fix content persistence race condition between preview and save operations - Remove legacy updateElementContent system entirely - Add comprehensive authentication with JWT scaffolding and dev mode - Implement EditContext.updateOriginalContent() for proper baseline management - Enable markdown formatting in all text elements (h1-h6, p, div, etc) - Clean terminology: remove 'unified' references from codebase Technical changes: * core/editor.js: Remove legacy update system, unify content types as markdown * ui/Editor.js: Add updateOriginalContent() method to fix save persistence * ui/Previewer.js: Clean live preview system for all content types * api/handlers.go: Implement UpsertContent for idempotent PUT operations * auth/*: Complete authentication service with OAuth scaffolding * db/queries/content.sql: Add upsert query with ON CONFLICT handling * Schema: Remove type constraints, rely on server-side validation Result: Clean content editing with persistent saves, no 404 errors, markdown support in all text elements
This commit is contained in:
120
TODO.md
120
TODO.md
@@ -242,3 +242,123 @@ CREATE INDEX IF NOT EXISTS idx_content_site_id ON content(site_id);
|
||||
- `db/*/setup.sql` - Contains table creation queries (sqlc generates type-safe functions)
|
||||
- `internal/db/database.go` - Manual index/trigger creation using raw SQL
|
||||
- **Best Practice**: Use sqlc for what it supports, manual SQL for what it doesn't
|
||||
|
||||
## 🔄 **Editor Cache Architecture & Content State Management** (Dec 2024)
|
||||
|
||||
### **Current Architecture Issues Identified**
|
||||
|
||||
**Problem**: Conflict between preview system and content persistence after save operations.
|
||||
|
||||
**Root Cause**: The unified Editor system was designed with preview-first architecture:
|
||||
- `originalContent` stores DOM state when editing begins
|
||||
- `clearPreview()` always restores to `originalContent`
|
||||
- This creates race condition: `applyContent()` → `clearPreview()` → content reverted
|
||||
|
||||
### **✅ Implemented Solution: Post-Save Baseline Update**
|
||||
|
||||
**Strategy**: After successful save, update the stored `originalContent` to match the new saved state.
|
||||
|
||||
**Implementation** (`lib/src/ui/Editor.js`):
|
||||
```js
|
||||
// In save handler:
|
||||
context.applyContent(content); // Apply new content to DOM
|
||||
context.updateOriginalContent(); // Update baseline to match current DOM
|
||||
this.previewer.clearPreview(); // Clear preview (won't revert since baseline matches)
|
||||
```
|
||||
|
||||
**Benefits**:
|
||||
- ✅ Content persists after save operations
|
||||
- ✅ Future cancellations restore to saved state, not pre-edit state
|
||||
- ✅ Maintains clean preview functionality
|
||||
- ✅ No breaking changes to existing architecture
|
||||
|
||||
### **Future Considerations: Draft System Architecture**
|
||||
|
||||
**Current State Management**:
|
||||
- **Browser Cache**: DOM elements store current content state
|
||||
- **Server Cache**: Database stores persisted content
|
||||
- **No Intermediate Cache**: Edits are either preview (temporary) or saved (permanent)
|
||||
|
||||
**Potential Draft System Design**:
|
||||
|
||||
#### **Option 1: LocalStorage Drafts**
|
||||
```js
|
||||
// Auto-save drafts locally during editing
|
||||
const draftKey = `insertr_draft_${contentId}_${siteId}`;
|
||||
localStorage.setItem(draftKey, JSON.stringify({
|
||||
content: currentContent,
|
||||
timestamp: Date.now(),
|
||||
originalContent: baseline
|
||||
}));
|
||||
```
|
||||
|
||||
**Benefits**: Offline support, immediate feedback, no server load
|
||||
**Drawbacks**: Per-browser, no cross-device sync, storage limits
|
||||
|
||||
#### **Option 2: Server-Side Drafts**
|
||||
```js
|
||||
// Auto-save drafts to server with special draft flag
|
||||
PUT /api/content/{id}/draft
|
||||
{
|
||||
"value": "Draft content...",
|
||||
"type": "markdown",
|
||||
"is_draft": true
|
||||
}
|
||||
```
|
||||
|
||||
**Benefits**: Cross-device sync, unlimited storage, collaborative editing potential
|
||||
**Drawbacks**: Server complexity, authentication requirements, network dependency
|
||||
|
||||
#### **Option 3: Hybrid Draft System**
|
||||
- **LocalStorage**: Immediate draft saving during typing
|
||||
- **Server Sync**: Periodic sync of drafts (every 30s or on significant changes)
|
||||
- **Conflict Resolution**: Handle cases where server content changed while editing draft
|
||||
|
||||
### **Cache Invalidation Strategy**
|
||||
|
||||
**Current Behavior**:
|
||||
- Content is cached in DOM until page reload
|
||||
- No automatic refresh when content changes on server
|
||||
- No awareness of multi-user editing scenarios
|
||||
|
||||
**Recommended Enhancements**:
|
||||
|
||||
#### **Option A: Manual Refresh Strategy**
|
||||
- Add "Refresh Content" button to editor interface
|
||||
- Check server content before editing (warn if changed)
|
||||
- Simple conflict resolution (server wins vs local wins vs merge)
|
||||
|
||||
#### **Option B: Polling Strategy**
|
||||
- Poll server every N minutes for content changes
|
||||
- Show notification if content was updated by others
|
||||
- Allow user to choose: keep editing, reload, or merge
|
||||
|
||||
#### **Option C: WebSocket Strategy**
|
||||
- Real-time content change notifications
|
||||
- Live collaborative editing indicators
|
||||
- Automatic conflict resolution
|
||||
|
||||
### **Implementation Priority**
|
||||
|
||||
**Phase 1** (Immediate): ✅ **COMPLETED**
|
||||
- Fix content persistence after save (baseline update approach)
|
||||
|
||||
**Phase 2** (Short-term):
|
||||
- Add LocalStorage draft auto-save during editing
|
||||
- Implement draft recovery on page reload
|
||||
- Basic conflict detection (server timestamp vs local timestamp)
|
||||
|
||||
**Phase 3** (Long-term):
|
||||
- Server-side draft support
|
||||
- Real-time collaboration features
|
||||
- Advanced conflict resolution
|
||||
|
||||
### **Design Principles for Draft System**
|
||||
|
||||
1. **Progressive Enhancement**: Site works without drafts, drafts enhance UX
|
||||
2. **Data Safety**: Never lose user content, even in edge cases
|
||||
3. **Performance First**: Drafts shouldn't impact site loading for regular visitors
|
||||
4. **Conflict Transparency**: Always show user what's happening with their content
|
||||
5. **Graceful Degradation**: Fallback to basic editing if draft system fails
|
||||
|
||||
**Note**: Current architecture already supports foundation for all these enhancements through the unified Editor system and API client pattern.
|
||||
|
||||
Reference in New Issue
Block a user