List view task order problem in multi-page saved filter (Typesense)

Description

When using a saved filter (List View) in Vikunja, the ordering of tasks across multiple pages is incorrect. Specifically, tasks are not appearing on the expected pages based on their position property.

This issue does not occur in the regular List View (without saved filter). It is also not reproducible on **try instance **because it does not have Typesense enabled.

Expected Behavior

  • Tasks should be ordered by task.position on both pages.
  • When a task that was not previously displayed in the saved filter starts satisfying the filter condition, it should receive position = 0 (under question) and appear on the 2nd page.
  • When a task that was previously displayed and ordered in the saved filter disappears and later reappears, it should retain its original position on the 1st page, pushing the last task on the 1st page to the 2nd page.
  • The 2nd page should maintain the same ordering logic as the 1st page, showing tasks with highest positions first and tasks with position = 0 at the end (under question).

Actual Behavior

  • The 2nd page does not update correctly and continues to display certain tasks that should now appear on the 1st page.
  • The 1st page maintains correct order but skips tasks that should be displayed, instead showing them on the 2nd page.

Steps to Reproduce

  1. Create a saved filter in Vikunja.
  2. Populate the list with more than 50 tasks to trigger pagination.
  3. Observe task order changes when new tasks are added or existing tasks naturally disappear and reappear.
  4. Check if tasks with position = 0 are consistently placed at the end of the 1st page.
  5. Notice that tasks that should appear on the 1st page are instead displayed on the 2nd page, breaking the expected behavior.

Environment

  • Vikunja: v0.24.1-773-66293795e7 (latest changes from main branch)
  • Typesense: v27.1
  • Redis: v7.4.0
  • DB: MariaDB vLTS

Potential Cause

A likely cause is the following commit: fix(typesense): do not try to sort by position when searching in a sa… · go-vikunja/vikunja@e56b223 · GitHub

This commit removes sorting by position for saved filters, stating:

“Do not try to sort by position when searching in a saved filter. This change fixes a bug where Typesense would try to sort by the project view of a saved filter. The view position is not indexed in Typesense, hence filtering fails. Because sorting by position is not a feature in saved filters, I’ve removed the logic for sorting saved filters with Typesense.”

However, Typesense does appear to index different view positions within the task collection, including views under saved filters.

Workaround/Fix

When replaying Typesense request and replacing the default sort_by parameter (done(missing_values:last):asc,created(missing_values:last):desc ) with:

positions.view_179(missing_values:last):asc

Sorting works correctly again.

Additionally, commenting out the following section restores the expected behavior:

# task_search.go:592 (or somewhere near)
/*if opts.isSavedFilter && param.sortBy == taskPropertyPosition {
	continue
}*/

Additional Notes

  • This issue only affects saved filters.
  • Regular List View does not experience this problem, even though new tasks still receive position values by default.
  • It appears that Typesense is aware of different view positions, contradicting the commit’s claim that “The view position is not indexed in Typesense.”

Thanks for the report! I’ll take a look.

You seem quite proficient in the code though, do you want to send a PR?

Yes, but it should not show tasks which were already shown on the first page.

Please let me verify additional details with you.

I assume you just agreed that last page in List view of saved filter should show tasks with position 0 at the very end - meaning the ones that satisfy the filter condition but were never re-ordered in the scope of the view - but I don’t think it’s per design.

For example, when in regular List View new task is created it’s position is initially 0 - but task position code on backend checks if it’s 0 right away and overrides it with lowest possible position in the view (first/2).
This is one way to confirm position 0 is not wanted to be in list view.

Other way to look at this is by imagining task with position 0 at the end of the list, or anywhere in the list really. Based on the current position calculation logic when some task is dragged between other 2 tasks - it’s position becomes the delta position / 2 + prev. position.
If some task would be dragged to the end of list near the task with position 0 it’s own position value would be drastically decreased eventually placing it far away from the place of drop closer to middle of the list.

I think it should be clear now why I think task with position 0 should not be allowed to be neither displayed, nor saved with such position not only in regular list views, but also in saved filters.

Yet we can still see tasks with position 0 in regular list view when changing the task’s project for example - because there is no position recalculation during the task update.

Also we can still see tasks with position 0 in list views of saved filters when given task starts to satisfy the filter condition - because position related CRON job does not take list views into account for position recalculation.

What do you think about 2 issues mentioned? Should they also be taken into account as part of the current topic’s bug fix?

Currently, it’s the other way around. Tasks with position 0 are always sorted first.

Each task should have a position in every view though, even if it was never explicitly reordered before.

But since the task was dragged away, it should be placed away from the other task?
Not sure if I understand what you mean here.

The cron job should take that into account. If that does not work, that’s a bug.