Issue 131 Tasks Forgot Your View - edmozley/freeitsm GitHub Wiki
Tasks always reopened on the board (issue #131)
Reported by tjedelhauser ยท Fixed in #1459
1. What you saw
Switch Tasks to the list, or to All tasks, then reload the page. Both snap back: the board, showing only your own work. Every time.
Not a save that failed. There was no save at all.
2. What was actually wrong
Two lines of state in assets/js/tasks.js:
let currentFilter = 'my';
let currentView = 'board';
switchView() and setFilter() changed those variables, repainted, and stopped. Nothing wrote them anywhere, and nothing read them back on load. So every page load started from the hardcoded defaults, exactly as reported.
The part that makes it a real complaint rather than a nitpick
It was the only thing on that page that forgot. Everything around it already remembered, per analyst:
| Already saved | Key |
|---|---|
| Task opens in the side panel or the large window | tasks_detail_view |
| Large window: two columns or tabs (#1454) | tasks_modal_layout |
| Which fields appear on a board card | tasks_card_fields |
| Tasks calendar: subtask scope | tasks_calendar_subtasks |
| Tasks calendar: span mode | tasks_calendar_span_mode |
| Task table: columns and sort | tasks_table_v1 |
And one tab away, the tickets calendar already saved the identical "my work vs everybody's" choice as tickets_calendar_scope. The board was the outlier.
3. Where it is stored, and why not in the browser
A user preference, in user_preferences, against the analyst - not localStorage.
Three reasons, in order of weight:
- Consistency. Every sibling control listed above is already a server-side preference. Storing this one locally would mean your panel choice follows you to another machine and your view choice does not, which is arbitrary and impossible to explain.
- It follows the person. Same doctrine as the recent trail in #1450: per analyst rather than per browser, so it survives signing out and reaches your other machine.
- No flash.
tasks/index.phpalready reads a set of preference keys in one query and publishes them to the page, precisely so "tasks.js must not have to fetch a preference before it can open anything." Two more keys join that existingIN (...)list. Anything read client-side would paint the board and then swap it out.
That third point is why the panes' initial visibility and the buttons' active class are decided in PHP, not by tasks.js on load.
4. ๐ What is deliberately NOT remembered
Only board/list and my/all. The team dropdown, the analyst dropdown, the tag filter and the search box still clear on every visit.
The rule was already written down, in data-table.js for the saved table views (discussion #96):
A filter is how you like to look at things; a search is a question you asked once.
There is a sharper reason as well, and it is the one that decided the scope:
A narrow filter that survives the night is how somebody opens Tasks in the morning to an empty board and concludes their work has been deleted.
A stored analyst id can also outlive the analyst - the product already carries dozens of ticket rows pointing at deleted people, so this is not hypothetical. Board-or-list and mine-or-everyone's can do neither: neither can hide a task beyond the plain meaning of the button you pressed.
So setFilter() saves only the two coarse values, even though currentFilter can also hold 'team' and 'analyst':
if (filter === 'my' || filter === 'all') saveTaskPreference('tasks_filter', filter);
5. A small deliberate inconsistency
The save is fire-and-forget and silent on failure, matching the tasks calendar. The board has already redrawn the way you asked; a failed save costs you the choice next time and nothing now, and a toast about a view preference would be worse than quietly showing you the default tomorrow.
The detail-panel switch one screen away does toast on failure, and that stays. Moving a task into the large window is a considered choice you would want to know had not stuck. Flicking between board and list is not.
6. ๐ Files
| File | Change |
|---|---|
tasks/index.php |
Reads tasks_view / tasks_filter in the existing preference query; renders the active buttons and the visible pane from them; publishes both to the page |
assets/js/tasks.js |
Initial state taken from the published values; saveTaskPreference() helper; saves in switchView() and (guarded) setFilter(); cache-buster to v=39 |
No schema change - user_preferences already exists and is keyed on (analyst_id, preference_key).
Values are whitelisted on read, not trusted: the column is free text, and an unrecognised value must land on the default rather than on a view that does not exist and renders blank.
7. How it was verified
Driven in headless Chrome against the real page, clicking the actual buttons in a same-origin harness rather than posting to the endpoint by hand, on an analyst with no existing preference:
1 initial activeView=board activeFilter=my boardVisible=true listVisible=false
PASS starts on the board with My tasks
PASS board pane visible, list hidden
2 clicked List activeView=list activeFilter=my boardVisible=false listVisible=true
PASS list is now active and visible
3 after reload activeView=list activeFilter=my TASK_VIEW=list
PASS LIST SURVIVED THE REFRESH
PASS and the list pane is the one showing
PASS server published TASK_VIEW=list (no flash of the board)
5 after reload activeView=list activeFilter=all TASK_FILTER=all
PASS ALL TASKS SURVIVED THE REFRESH
PASS and the list view is still remembered too
6 after team PASS a team filter is NOT remembered (still All)
7 after search PASS a search is NOT remembered
DONE errors=0
Proved load-bearing by breaking it
With the single line saveTaskPreference('tasks_view', view) commented out, the harness reproduces the reported bug exactly and the checks fail:
3 after reload activeView=board boardVisible=true listVisible=false
FAIL LIST SURVIVED THE REFRESH
FAIL and the list pane is the one showing
FAIL server published TASK_VIEW=list (no flash of the board)
PASS ALL TASKS SURVIVED THE REFRESH <- the filter save was left in
DONE errors=4
The filter still passing while the view failed is the useful half: it shows the two are saved independently rather than one check covering both.
8. What this means for you
Nothing to configure. Pick the list, or All tasks, and Tasks opens that way next time - on any machine you sign in from.
To go back, pick the board again. There is no setting to find, because the buttons are the setting.
9. Related
- Tasks
- Issue #129 - Every page returned HTTP 500 after upgrading - reported by the same person the same day