fix(jira): keep the Tasks Board view selected after you leave the page (#30588)

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Kelvin Amoaba <97001695+AmoabaKelvin@users.noreply.github.com>
This commit is contained in:
hnkƶ
2026-10-25 03:43:08 +00:00
committed by GitHub
co-authored by Claude Opus 5 Kelvin Amoaba
parent 407e9ebc33
commit 7d0103e8a6
5 changed files with 57 additions and 3 deletions
@@ -0,0 +1,25 @@
export type JiraViewMode = 'list' | 'board'
// Device-local, like the Jira list columns, rather than synced through ui.set.
const STORAGE_KEY = 'orca.jira.view-mode.v1'
export function loadJiraViewMode(): JiraViewMode {
try {
return localStorage.getItem(STORAGE_KEY) === 'board' ? 'board' : 'list'
} catch {
return 'list'
}
}
export function saveJiraViewMode(mode: JiraViewMode): void {
try {
// Storing only the non-default keeps a future default change from being pinned by old devices.
if (mode === 'board') {
localStorage.setItem(STORAGE_KEY, 'board')
} else {
localStorage.removeItem(STORAGE_KEY)
}
} catch {
// The live view stays usable when browser storage is unavailable or full.
}
}
@@ -3,10 +3,11 @@ import { ToggleGroup, ToggleGroupItem } from '@/components/ui/toggle-group'
import { Switch } from '@/components/ui/switch'
import { Label } from '@/components/ui/label'
import { translate } from '@/i18n/i18n'
import type { JiraViewMode } from './jira-view-mode-storage'
type Props = {
mode: 'list' | 'board'
onModeChange: (mode: 'list' | 'board') => void
mode: JiraViewMode
onModeChange: (mode: JiraViewMode) => void
currentSprint: boolean
onCurrentSprintChange: (checked: boolean) => void
sprintDisabled?: boolean
@@ -165,3 +165,25 @@ describe('Jira priority list source owner', () => {
}
)
})
describe('Jira Tasks view mode', () => {
// Leaving Tasks unmounts the hook, so each case reopens it with a fresh render.
function openTasks() {
return renderHook(() => useTaskPageJiraListState(fixture())).result
}
it('reopens on the board after the view mode was switched', async () => {
const first = openTasks()
await act(async () => first.current.setJiraViewMode('board'))
cleanup()
expect(openTasks().current.jiraViewMode).toBe('board')
})
it('reopens on the list once the view mode is switched back', async () => {
const first = openTasks()
await act(async () => first.current.setJiraViewMode('board'))
await act(async () => first.current.setJiraViewMode('list'))
cleanup()
expect(openTasks().current.jiraViewMode).toBe('list')
})
})
@@ -21,6 +21,7 @@ import type {
} from './jira-issue-sorter'
import { jiraListPrioritiesForTarget } from '@/runtime/runtime-jira-client'
import { loadJiraLinkedView, saveJiraLinkedView } from './jira-linked-view-storage'
import { loadJiraViewMode, saveJiraViewMode, type JiraViewMode } from './jira-view-mode-storage'
import {
fallbackJiraSortColumn,
loadJiraListColumnIds,
@@ -103,7 +104,11 @@ export function useTaskPageJiraListState(model: TaskPageLinearViewStateModel) {
items: JiraStatusCatalogItem[]
} | null>(null)
const [activeJiraPreset, setActiveJiraPreset] = useState<JiraPresetId>('assigned')
const [jiraViewMode, setJiraViewMode] = useState<'list' | 'board'>('list')
const [jiraViewMode, setJiraViewModeState] = useState<JiraViewMode>(loadJiraViewMode)
const setJiraViewMode = useCallback((mode: JiraViewMode) => {
setJiraViewModeState(mode)
saveJiraViewMode(mode)
}, [])
const [jiraCurrentSprint, setJiraCurrentSprint] = useState(false)
const [jiraRefreshNonce, setJiraRefreshNonce] = useState(0)
const [jiraProjectStatusOrder, setJiraProjectStatusOrder] = useState<{
@@ -59,6 +59,7 @@ export const LOCAL_STORAGE_MODULE_DISPOSITIONS: Record<string, WslMoveFieldDispo
'src/renderer/src/components/jira-linked-view-storage.ts',
'src/renderer/src/components/jira-list-columns.ts',
'src/renderer/src/components/jira-prompt-templates.ts',
'src/renderer/src/components/jira-view-mode-storage.ts',
'src/renderer/src/components/landing-preflight-dismissal.ts',
'src/renderer/src/components/linear-issue-view-storage.ts',
'src/renderer/src/components/native-chat/NativeChatStructuredSession.test-harness.tsx',