DashboardView: asignación real desde KAPPA + status_name desde lookup + columna asignado como texto
- KappaUserStory ampliado con assigned_to, asignado_a, assigned_name - EnrichedUserStory ahora tiene _assignedUserId, _assignedName, _statusName - parseAssignedUser() extrae user ID desde múltiples formatos de KAPPA - syncHUsToTurso persiste assigned_to en BD local - DashboardView: columna Asignado muestra nombre real desde KAPPA (texto, no Select) - statuses-db.ts: lookup de estados con seed en Dexie + resolveStatusName() seguro para booleanos/números (String() antes de trim) - tauri-db.ts: fallback Dexie para get/save user_stories (funciona en bun dev) - db.ts: nueva tabla user_stories en Dexie (version 8) - Filtros de tabla alineados a la derecha (justify-end)
This commit is contained in:
+19
-1
@@ -111,6 +111,22 @@ export interface CellMemberRecord {
|
||||
addedAt: string
|
||||
}
|
||||
|
||||
export interface DexieUserStory {
|
||||
id: number
|
||||
initiative_id: number
|
||||
title: string
|
||||
status: string | null
|
||||
priority: string | null
|
||||
assigned_to: number | null
|
||||
code: string | null
|
||||
description: string | null
|
||||
acceptance_criteria: string | null
|
||||
story_points: number | null
|
||||
sprint: string | null
|
||||
has_impairment: boolean | number
|
||||
created_at: string | null
|
||||
}
|
||||
|
||||
const db = new Dexie('alpha-core') as Dexie & {
|
||||
settings: Dexie.Table<SettingEntry, string>
|
||||
project_docs: Dexie.Table<ProjectDocRecord, number>
|
||||
@@ -123,9 +139,10 @@ const db = new Dexie('alpha-core') as Dexie & {
|
||||
lookups: Dexie.Table<LookupRecord, string>
|
||||
cells: Dexie.Table<CellRecord, string>
|
||||
cell_members: Dexie.Table<CellMemberRecord, string>
|
||||
user_stories: Dexie.Table<DexieUserStory, number>
|
||||
}
|
||||
|
||||
db.version(7).stores({
|
||||
db.version(8).stores({
|
||||
settings: '&key',
|
||||
project_docs: '&projectId, projectName, updatedAt',
|
||||
sessions: '++id, projectId, date',
|
||||
@@ -137,6 +154,7 @@ db.version(7).stores({
|
||||
lookups: '&[type+id], type',
|
||||
cells: '&id',
|
||||
cell_members: '[cellId+userId], cellId, userId',
|
||||
user_stories: '&id, initiative_id',
|
||||
})
|
||||
|
||||
export default db
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
import { saveLookup, getLookups } from '@/services/users-db'
|
||||
|
||||
export interface StatusDef {
|
||||
id: number
|
||||
name: string
|
||||
description: string
|
||||
}
|
||||
|
||||
const STATUSES: StatusDef[] = [
|
||||
{ id: 1, name: 'Por hacer', description: 'Tarea pendiente por iniciar' },
|
||||
{ id: 2, name: 'En progreso', description: 'Tarea actualmente en desarrollo' },
|
||||
{ id: 3, name: 'En revisión', description: 'Tarea en proceso de revisión' },
|
||||
{ id: 4, name: 'En pruebas', description: 'Tarea en fase de pruebas' },
|
||||
{ id: 5, name: 'Completado', description: 'Tarea finalizada' },
|
||||
{ id: 6, name: 'Bloqueado', description: 'Tarea bloqueada por dependencias' },
|
||||
{ id: 7, name: 'Cancelado', description: 'Tarea cancelada definitivamente' },
|
||||
]
|
||||
|
||||
const STATUS_MAP: Record<string, number> = {
|
||||
'todo': 1,
|
||||
'por hacer': 1,
|
||||
'in_progress': 2,
|
||||
'doing': 2,
|
||||
'wip': 2,
|
||||
'active': 2,
|
||||
'in progress': 2,
|
||||
'en progreso': 2,
|
||||
'true': 2,
|
||||
'review': 3,
|
||||
'revisión': 3,
|
||||
'testing': 4,
|
||||
'pruebas': 4,
|
||||
'done': 5,
|
||||
'completed': 5,
|
||||
'closed': 5,
|
||||
'finalizado': 5,
|
||||
'blocked': 6,
|
||||
'bloqueado': 6,
|
||||
'cancelled': 7,
|
||||
'cancelado': 7,
|
||||
'false': 1,
|
||||
}
|
||||
|
||||
let cachedStatuses: Map<number, StatusDef> | null = null
|
||||
|
||||
export function resolveStatusName(raw: unknown): string {
|
||||
const str = raw != null ? String(raw).trim().toLowerCase() : ''
|
||||
if (!str) return 'Por hacer'
|
||||
const id = STATUS_MAP[str]
|
||||
if (!id) return String(raw)
|
||||
const def = STATUSES.find(s => s.id === id)
|
||||
return def?.name ?? String(raw)
|
||||
}
|
||||
|
||||
export function resolveStatusId(raw: unknown): number {
|
||||
const str = raw != null ? String(raw).trim().toLowerCase() : ''
|
||||
if (!str) return 1
|
||||
return STATUS_MAP[str] ?? 1
|
||||
}
|
||||
|
||||
export async function seedStatusLookups(): Promise<void> {
|
||||
for (const s of STATUSES) {
|
||||
await saveLookup('status', s.id, s.name, s.description)
|
||||
}
|
||||
cachedStatuses = new Map(STATUSES.map(s => [s.id, s]))
|
||||
}
|
||||
|
||||
export async function loadStatusLookups(): Promise<StatusDef[]> {
|
||||
const records = await getLookups('status')
|
||||
if (records.length > 0) {
|
||||
cachedStatuses = new Map(records.map(r => [r.id, { id: r.id, name: r.name, description: r.description ?? '' }]))
|
||||
return Array.from(cachedStatuses.values())
|
||||
}
|
||||
return STATUSES
|
||||
}
|
||||
|
||||
export function getCachedStatuses(): StatusDef[] {
|
||||
if (cachedStatuses) return Array.from(cachedStatuses.values())
|
||||
return STATUSES
|
||||
}
|
||||
@@ -43,6 +43,19 @@ async function fallbackInvoke<T>(cmd: string, args?: Record<string, unknown>): P
|
||||
if (u) try { await (db as any).table('alpha_users').put(u) } catch {}
|
||||
return null as unknown as T
|
||||
}
|
||||
// ─── User Stories → Dexie ──────────────────────────
|
||||
case 'get_user_stories': {
|
||||
const initiativeId = (args as any)?.initiativeId
|
||||
try {
|
||||
const all = await (db as any).table('user_stories').toArray()
|
||||
return (initiativeId ? all.filter((r: any) => r.initiative_id === initiativeId) : all) as unknown as T
|
||||
} catch { return [] as unknown as T }
|
||||
}
|
||||
case 'save_user_story': {
|
||||
const s = (args as any)?.story
|
||||
if (s) try { await (db as any).table('user_stories').put(s) } catch {}
|
||||
return null as unknown as T
|
||||
}
|
||||
// ─── Por defecto: no hay fallback ─────────────────
|
||||
default:
|
||||
return null as unknown as T
|
||||
|
||||
Reference in New Issue
Block a user