mirror of
https://github.com/wekan/wekan.git
synced 2026-01-08 02:28:50 +01:00
8 KiB
8 KiB
Wekan Persistence Improvements - Quick Reference
What Was Changed?
❌ Removed
- Board-level
collapsedfield from Swimlanes - Board-level
collapsedfield from Lists - REST API endpoint for updating list
collapsedstatus collapse()mutation from Swimlanes
✅ Added
- Per-user position history with undo/redo
- LocalStorage validation and cleanup
- SwimlaneId validation migration
- Checkpoint/savepoint system for position history
- Enhanced data validation for all UI preferences
How It Works
Per-User Settings (Your Preferences)
These are NOW per-user and persisted:
- ✅ Swimlane collapse state
- ✅ List collapse state
- ✅ List width
- ✅ Swimlane height
Where it's stored:
- Logged-in users:
user.profile - Non-logged-in users: Browser localStorage
- Validated & cleaned automatically
Position History (Card Movements)
Every time you move a card:
- Automatically tracked in
userPositionHistorycollection - Stored with previous and new position
- Can be undone with
Meteor.call('userPositionHistory.undo', historyId) - Checkpoints can be created with
Meteor.call('userPositionHistory.createCheckpoint', boardId, name)
Data Validation
All UI preference data is validated:
- List widths: 100-1000 pixels
- Swimlane heights: -1 (auto) or 50-2000 pixels
- Corrupted data: automatically removed
- Invalid data: rejected on write
For Users
What Changed?
- Your collapse preferences are now private to you (not shared with others)
- They persist across page reloads
- They work even if not logged in (saved in browser)
- Invalid data is automatically cleaned up
What You Can Do (Coming Soon)
- Undo/redo card movements
- Create savepoints of board state
- Restore to previous savepoints
- Use Ctrl+Z to undo
For Developers
New Collections
UserPositionHistory
{
userId: String,
boardId: String,
entityType: 'card' | 'list' | 'swimlane' | 'checklist' | 'checklistItem',
entityId: String,
actionType: 'move' | 'create' | 'delete',
previousState: Object,
newState: Object,
isCheckpoint: Boolean,
checkpointName: String,
createdAt: Date
}
New Meteor Methods
// Create a checkpoint
Meteor.call('userPositionHistory.createCheckpoint', boardId, 'name');
// Undo a change
Meteor.call('userPositionHistory.undo', historyId);
// Get recent history
Meteor.call('userPositionHistory.getRecent', boardId, 50, (err, result) => {
// result is array of history entries
});
// Get checkpoints
Meteor.call('userPositionHistory.getCheckpoints', boardId, (err, checkpoints) => {
// result is array of checkpoints
});
// Restore to checkpoint
Meteor.call('userPositionHistory.restoreToCheckpoint', checkpointId);
Updated Models
cards.js
move()now automatically tracks changes- Uses
UserPositionHistory.trackChange()
swimlanes.js
collapsedfield removed (use profile.collapsedSwimlanes)collapse()mutation removed
lists.js
collapsedfield removed (use profile.collapsedLists)- Removed from REST API
users.js
- Enhanced
getListWidthFromStorage()with validation - Enhanced
setSwimlaneHeightToStorage()with validation - Added automatic cleanup of invalid data
New Files
client/lib/localStorageValidator.js
- validateAndCleanLocalStorage()
- shouldRunCleanup()
- getValidatedLocalStorageData()
- setValidatedLocalStorageData()
- validators object with all validation functions
models/lib/userStorageHelpers.js
- getValidatedNumber()
- setValidatedNumber()
- getValidatedBoolean()
- setValidatedBoolean()
models/userPositionHistory.js
- UserPositionHistory collection
- Helpers: getDescription(), canUndo(), undo()
- Meteor methods for interaction
server/migrations/ensureValidSwimlaneIds.js
- Runs automatically on startup
- Fixes cards/lists without swimlaneId
- Rescues orphaned data
Migration Details
Automatic Migration: ensureValidSwimlaneIds
Runs on server startup:
-
Finds cards without swimlaneId
- Assigns them to default swimlane
-
Finds orphaned cards
- SwimlaneId points to deleted swimlane
- Moves them to "Rescued Data" swimlane
-
Adds validation hooks
- Prevents swimlaneId removal
- Auto-assigns on card creation
Tracking:
Migrations.findOne({ name: 'ensure-valid-swimlane-ids' })
// Shows results of migration
Data Examples
Before (Broken)
// Swimlane with board-level collapse
{
_id: 'swim123',
title: 'Development',
collapsed: true // ❌ Shared with all users!
}
// Card without swimlaneId
{
_id: 'card456',
title: 'Fix bug',
swimlaneId: undefined // ❌ No swimlane!
}
After (Fixed)
// Swimlane - no collapsed field
{
_id: 'swim123',
title: 'Development',
// collapsed: removed ✅
}
// User's profile - has per-user settings
{
_id: 'user789',
profile: {
collapsedSwimlanes: {
'board123': {
'swim123': true // ✅ Per-user!
}
},
listWidths: {
'board123': {
'list456': 300 // ✅ Per-user!
}
}
}
}
// Card with swimlaneId
{
_id: 'card456',
title: 'Fix bug',
swimlaneId: 'swim123' // ✅ Always set!
}
// Position history entry
{
_id: 'hist789',
userId: 'user789',
boardId: 'board123',
entityType: 'card',
entityId: 'card456',
actionType: 'move',
previousState: { swimlaneId: 'swim123', listId: 'list456', sort: 1 },
newState: { swimlaneId: 'swim123', listId: 'list789', sort: 2 },
createdAt: ISODate('2025-12-23T07:00:00Z')
}
Troubleshooting
Q: My collapse state isn't persisting
A: Make sure you're using the new per-user settings methods:
user.setCollapsedSwimlane(boardId, swimlaneId, true);
user.getCollapsedSwimlaneFromStorage(boardId, swimlaneId);
Q: I see "Rescued Data" swimlane with orphaned cards
A: Migration found cards pointing to deleted swimlanes. They're safe in the rescue swimlane. You can move them to proper swimlanes.
Q: localStorage is being cleared
A: That's intentional - we only keep valid data. Invalid/corrupted data is removed automatically during daily cleanup.
Q: How do I create a checkpoint?
A: Use the Meteor method:
Meteor.call('userPositionHistory.createCheckpoint', boardId, 'Before big changes');
Q: How do I undo a card move?
A: Use the Meteor method:
Meteor.call('userPositionHistory.undo', historyEntryId);
Performance Notes
Storage
- localStorage: Max 50 boards, max 100 items per board
- UserPositionHistory: Max 1000 entries per user per board
- Auto-cleanup: Runs daily
Queries
- Limited to 100 results per query
- Indexed by userId, boardId, createdAt
- Fast checkpoint retrieval
Validation
- Runs on startup (once per day)
- Only validates if needed
- Removes excess data automatically
What's Next?
Coming Soon
- Undo/redo buttons in UI
- History sidebar
- Keyboard shortcuts (Ctrl+Z)
- Checkpoint UI
Future
- Field-level history (description, comments)
- Search across historical values
- Visual timeline
- Collaborative undo
Files to Know
| File | Purpose |
|---|---|
| models/userPositionHistory.js | Position history collection |
| client/lib/localStorageValidator.js | Data validation |
| server/migrations/ensureValidSwimlaneIds.js | Automatic migration |
| models/swimlanes.js | Swimlane model |
| models/lists.js | List model |
| models/cards.js | Card model with tracking |
Questions?
See detailed documentation:
- ARCHITECTURE_IMPROVEMENTS.md - Complete guide
- PERSISTENCE_AUDIT.md - System audit
- IMPLEMENTATION_SUMMARY.md - Implementation details
- FIXES_CHECKLIST.md - What was fixed
Status: ✅ Ready for use
Last Updated: 2025-12-23