[PR #1998] [MERGED] fix(positions): detect and repair duplicate task positions automatically #9698

Closed
opened 2026-04-23 09:09:30 -05:00 by GiteaMirror · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/go-vikunja/vikunja/pull/1998
Author: @kolaente
Created: 12/16/2025
Status: Merged
Merged: 12/20/2025
Merged by: @kolaente

Base: mainHead: fix-position-healing


📝 Commits (10+)

  • 3323c05 fix(positions): detect and repair duplicate task positions automatically
  • 00061fa fix(positions): add auth-free recalculation for CLI repair
  • 3fbdddc refactor(positions): use standard error type for ErrNeedsFullRecalculation
  • bda9702 fix(positions): skip conflict detection when recalculating anyway
  • 8c1fb41 refactor(positions): consolidate position refresh to single location
  • 89e3dfe refactor(positions): use map to group positions by view ID
  • 48def13 style(positions): convert if-else chain to switch statement
  • 16d9872 refactor
  • 9e86bff refactor view wepar
  • 8d8626c test: add tests for RepairTaskPositions and fix lint issues

📊 Changes

6 files changed (+921 additions, -43 deletions)

View changed files

📝 frontend/src/helpers/calculateItemPosition.ts (+14 -4)
📝 frontend/src/helpers/calculateTaskPosition.test.ts (+40 -16)
pkg/cmd/repair_task_positions.go (+102 -0)
📝 pkg/models/error.go (+28 -0)
📝 pkg/models/task_position.go (+302 -23)
pkg/models/task_position_test.go (+435 -0)

📄 Description

Summary

  • Add automatic conflict detection to task position updates that redistributes duplicate positions within available gaps
  • Add CLI command vikunja repair-task-positions with --dry-run flag for bulk repair across all views
  • Update frontend calculateItemPosition() to handle edge case where neighbors have identical positions

Background

Relates to: https://community.vikunja.io/t/reordering-not-possible-position-value-the-same-for-different-tasks/4078

Duplicate positions can occur due to race conditions or historical bugs, causing tasks to appear in the wrong order or jump around when the page is refreshed.

Changes

Backend:

  • ErrNeedsFullRecalculation sentinel error and MinPositionSpacing constant (1e-9)
  • findPositionConflicts() - detects duplicate positions in a view
  • resolveTaskPositionConflicts() - redistributes conflicting tasks within available gaps
  • updateTaskPosition() - now detects and resolves conflicts after writes
  • RepairTaskPositions() - bulk repair function for CLI
  • New CLI command vikunja repair-task-positions --dry-run

Frontend:

  • calculateItemPosition() handles equal neighbor positions by nudging above
  • MIN_POSITION_SPACING constant matching backend

Test Plan

  • Backend unit tests for conflict detection and resolution
  • Frontend unit tests for calculateItemPosition edge cases
  • Build passes
  • Lint passes (0 issues)
  • Manual testing: drag tasks in kanban, verify order persists after refresh
  • Manual testing: run vikunja repair-task-positions --dry-run on existing DB

Summary by CodeRabbit

  • New Features

    • Added a repair-task-positions CLI command to detect and resolve task position conflicts, with dry-run preview option.
    • Implemented automatic conflict detection and resolution to ensure unique task positions.
  • Bug Fixes

    • Fixed position calculation edge cases and JSON serialization precision issues.
    • Improved handling of conflicting task positions with deterministic resolution.
  • Tests

    • Added comprehensive test coverage for position repair and conflict resolution logic.

✏️ Tip: You can customize this high-level summary in your review settings.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/go-vikunja/vikunja/pull/1998 **Author:** [@kolaente](https://github.com/kolaente) **Created:** 12/16/2025 **Status:** ✅ Merged **Merged:** 12/20/2025 **Merged by:** [@kolaente](https://github.com/kolaente) **Base:** `main` ← **Head:** `fix-position-healing` --- ### 📝 Commits (10+) - [`3323c05`](https://github.com/go-vikunja/vikunja/commit/3323c05994562e5a1f85b4f67c9453f8b557ba53) fix(positions): detect and repair duplicate task positions automatically - [`00061fa`](https://github.com/go-vikunja/vikunja/commit/00061fa0dceb69542d0ff35a00454554fcb3e220) fix(positions): add auth-free recalculation for CLI repair - [`3fbdddc`](https://github.com/go-vikunja/vikunja/commit/3fbdddc1fb3c9910fefcf46a9fec2696360f5ad4) refactor(positions): use standard error type for ErrNeedsFullRecalculation - [`bda9702`](https://github.com/go-vikunja/vikunja/commit/bda9702817bc90cb0913befcf67ad6d7ad58b67c) fix(positions): skip conflict detection when recalculating anyway - [`8c1fb41`](https://github.com/go-vikunja/vikunja/commit/8c1fb41b7143381f029d1adae8bca184f6c3930e) refactor(positions): consolidate position refresh to single location - [`89e3dfe`](https://github.com/go-vikunja/vikunja/commit/89e3dfe19357a98c7151c26dee61433a9800efaa) refactor(positions): use map to group positions by view ID - [`48def13`](https://github.com/go-vikunja/vikunja/commit/48def136affa02ae6145f27edaf9815ca296d96b) style(positions): convert if-else chain to switch statement - [`16d9872`](https://github.com/go-vikunja/vikunja/commit/16d9872a18d9bb60e42c79a995192d93f7b3a97f) refactor - [`9e86bff`](https://github.com/go-vikunja/vikunja/commit/9e86bfff54f15d569f50f583dd0dd7bb67bd3215) refactor view wepar - [`8d8626c`](https://github.com/go-vikunja/vikunja/commit/8d8626cade8c54244f13f08490191eb7f8275d3e) test: add tests for RepairTaskPositions and fix lint issues ### 📊 Changes **6 files changed** (+921 additions, -43 deletions) <details> <summary>View changed files</summary> 📝 `frontend/src/helpers/calculateItemPosition.ts` (+14 -4) 📝 `frontend/src/helpers/calculateTaskPosition.test.ts` (+40 -16) ➕ `pkg/cmd/repair_task_positions.go` (+102 -0) 📝 `pkg/models/error.go` (+28 -0) 📝 `pkg/models/task_position.go` (+302 -23) ➕ `pkg/models/task_position_test.go` (+435 -0) </details> ### 📄 Description ## Summary - Add automatic conflict detection to task position updates that redistributes duplicate positions within available gaps - Add CLI command `vikunja repair-task-positions` with `--dry-run` flag for bulk repair across all views - Update frontend `calculateItemPosition()` to handle edge case where neighbors have identical positions ## Background Relates to: https://community.vikunja.io/t/reordering-not-possible-position-value-the-same-for-different-tasks/4078 Duplicate positions can occur due to race conditions or historical bugs, causing tasks to appear in the wrong order or jump around when the page is refreshed. ## Changes **Backend:** - `ErrNeedsFullRecalculation` sentinel error and `MinPositionSpacing` constant (1e-9) - `findPositionConflicts()` - detects duplicate positions in a view - `resolveTaskPositionConflicts()` - redistributes conflicting tasks within available gaps - `updateTaskPosition()` - now detects and resolves conflicts after writes - `RepairTaskPositions()` - bulk repair function for CLI - New CLI command `vikunja repair-task-positions --dry-run` **Frontend:** - `calculateItemPosition()` handles equal neighbor positions by nudging above - `MIN_POSITION_SPACING` constant matching backend ## Test Plan - [x] Backend unit tests for conflict detection and resolution - [x] Frontend unit tests for calculateItemPosition edge cases - [x] Build passes - [x] Lint passes (0 issues) - [ ] Manual testing: drag tasks in kanban, verify order persists after refresh - [ ] Manual testing: run `vikunja repair-task-positions --dry-run` on existing DB <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added a `repair-task-positions` CLI command to detect and resolve task position conflicts, with dry-run preview option. * Implemented automatic conflict detection and resolution to ensure unique task positions. * **Bug Fixes** * Fixed position calculation edge cases and JSON serialization precision issues. * Improved handling of conflicting task positions with deterministic resolution. * **Tests** * Added comprehensive test coverage for position repair and conflict resolution logic. <sub>✏️ Tip: You can customize this high-level summary in your review settings.</sub> <!-- end of auto-generated comment: release notes by coderabbit.ai --> --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
GiteaMirror added the pull-request label 2026-04-23 09:09:30 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/vikunja#9698