Files
orca/src/shared/workspace-status-default-migration.ts
T
Eddie JaoudeandJinjing e0a7f0eadd fix: reordered default columns in kanban board (#6934)
* fix: reordered default columns in kanban board

* Introduce dedicated flag to repair reversed default workspace statuses

- Add `_workspaceStatusesReorderedDefaultRepaired` to decouple the
  one-shot repair from the initial status order migration.
- Ensure the repair runs for users who saved the reversed default
  payload (with "Done" on the left) during a short-lived broken build.
- Support both "Completed" and "Done" labels when identifying default
  status shapes to migrate or repair.

---------

Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
2026-07-01 13:17:52 -07:00

84 lines
2.7 KiB
TypeScript

const DEFAULT_STATUS_LABELS: Record<string, readonly string[]> = {
todo: ['Todo'],
'in-progress': ['In progress'],
'in-review': ['In review'],
// Why: both labels have shipped as defaults; either raw shape is safe to migrate.
completed: ['Completed', 'Done']
}
const CONDUCTOR_DEFAULT_STATUS_VISUALS: Record<string, { color: string; icon: string }> = {
todo: { color: 'neutral', icon: 'circle' },
'in-progress': { color: 'conductor-progress', icon: 'conductor-progress' },
'in-review': { color: 'conductor-review', icon: 'conductor-review' },
completed: { color: 'conductor-done', icon: 'conductor-done' }
}
const LEGACY_DEFAULT_STATUS_VISUALS: Record<string, { color: string; icon: string }> = {
todo: { color: 'neutral', icon: 'circle' },
'in-progress': { color: 'blue', icon: 'circle-dot' },
'in-review': { color: 'violet', icon: 'git-pull-request' },
completed: { color: 'emerald', icon: 'circle-check' }
}
const LEGACY_TODO_FIRST_DEFAULT_STATUS_IDS = [
'todo',
'in-progress',
'in-review',
'completed'
] as const
const WORKFLOW_DEFAULT_STATUS_IDS = ['completed', 'in-review', 'in-progress', 'todo'] as const
function isLegacyDefaultStatusPayload(
value: unknown,
orderedIds: readonly string[],
visuals: Record<string, { color: string; icon: string }>
): boolean {
if (!Array.isArray(value) || value.length !== orderedIds.length) {
return false
}
return value.every((rawStatus, index) => {
if (!rawStatus || typeof rawStatus !== 'object' || Array.isArray(rawStatus)) {
return false
}
const raw = rawStatus as Record<string, unknown>
const expectedId = orderedIds[index]!
const expectedVisual = visuals[expectedId]
return (
Object.keys(raw).length === 4 &&
raw.id === expectedId &&
DEFAULT_STATUS_LABELS[expectedId]?.includes(raw.label as string) === true &&
raw.color === expectedVisual?.color &&
raw.icon === expectedVisual?.icon
)
})
}
export function isLegacyDefaultWorkflowStatusPayload(value: unknown): boolean {
return (
isLegacyDefaultStatusPayload(
value,
LEGACY_TODO_FIRST_DEFAULT_STATUS_IDS,
CONDUCTOR_DEFAULT_STATUS_VISUALS
) ||
isLegacyDefaultStatusPayload(
value,
LEGACY_TODO_FIRST_DEFAULT_STATUS_IDS,
LEGACY_DEFAULT_STATUS_VISUALS
) ||
isLegacyDefaultStatusPayload(
value,
WORKFLOW_DEFAULT_STATUS_IDS,
CONDUCTOR_DEFAULT_STATUS_VISUALS
) ||
isLegacyDefaultStatusPayload(value, WORKFLOW_DEFAULT_STATUS_IDS, LEGACY_DEFAULT_STATUS_VISUALS)
)
}
export function isKnownBadPRReorderedDefaultStatusPayload(value: unknown): boolean {
return isLegacyDefaultStatusPayload(
value,
WORKFLOW_DEFAULT_STATUS_IDS,
CONDUCTOR_DEFAULT_STATUS_VISUALS
)
}