agregar endpoint /epicdevelopment/ + store de epicas y HUs por proyecto

This commit is contained in:
2026-05-27 13:46:18 -05:00
parent 458c358688
commit 0f26506d54
4 changed files with 106 additions and 8 deletions
+16
View File
@@ -3,6 +3,7 @@ import type {
KappaLoginResponse, KappaLoginResponse,
KappaInitiative, KappaInitiative,
KappaUserStory, KappaUserStory,
KappaEpicDevelopment,
KappaLogbookMaster, KappaLogbookMaster,
KappaLogbookEntry, KappaLogbookEntry,
KappaPlanningMaster, KappaPlanningMaster,
@@ -103,6 +104,21 @@ class KappaAPI {
return this.request<KappaUserStory[]>('GET', path) return this.request<KappaUserStory[]>('GET', path)
} }
async getEpicDevelopment(initiativeId: number, page = 1, pageSize = 50): Promise<PaginatedResponse<KappaEpicDevelopment>> {
return this.request<PaginatedResponse<KappaEpicDevelopment>>('GET', `/epicdevelopment/?initiative=${initiativeId}&page=${page}&page_size=${pageSize}`)
}
async getAllEpicDevelopment(initiativeId: number): Promise<KappaEpicDevelopment[]> {
const first = await this.getEpicDevelopment(initiativeId, 1, 100)
const all = [...first.results]
const totalPages = Math.ceil(first.count / 100)
for (let p = 2; p <= totalPages; p++) {
const page = await this.getEpicDevelopment(initiativeId, p, 100)
all.push(...page.results)
}
return all
}
async getLogbooks(initiativeId?: number): Promise<KappaLogbookEntry[]> { async getLogbooks(initiativeId?: number): Promise<KappaLogbookEntry[]> {
const path = initiativeId ? `/logbooks/?initiative=${initiativeId}` : '/logbooks/' const path = initiativeId ? `/logbooks/?initiative=${initiativeId}` : '/logbooks/'
return this.request<KappaLogbookEntry[]>('GET', path) return this.request<KappaLogbookEntry[]>('GET', path)
+22
View File
@@ -10,6 +10,17 @@ export interface ProjectRecord {
end_date: string | null end_date: string | null
} }
export interface WorkItemRecord {
id: number
project_id: number
code: string | null
title: string
description: string | null
type: string
status: string
priority: string
}
export interface AlphaUserRecord { export interface AlphaUserRecord {
id: number id: number
email: string email: string
@@ -91,6 +102,17 @@ export const tauriDb = {
return invoke('delete_project', { id }) return invoke('delete_project', { id })
}, },
// Work Items
getWorkItems(projectId: number): Promise<WorkItemRecord[]> {
return invoke('get_work_items', { projectId })
},
saveWorkItem(item: WorkItemRecord): Promise<number> {
return invoke('save_work_item', { item })
},
deleteWorkItem(id: number): Promise<void> {
return invoke('delete_work_item', { id })
},
// Users // Users
getUsers(): Promise<AlphaUserRecord[]> { getUsers(): Promise<AlphaUserRecord[]> {
return invoke('get_users') return invoke('get_users')
+44 -7
View File
@@ -1,7 +1,9 @@
import { defineStore } from 'pinia' import { defineStore } from 'pinia'
import { ref, computed } from 'vue' import { ref, computed } from 'vue'
import { kappa } from '@/services/kappa-api' import { kappa } from '@/services/kappa-api'
import type { KappaUserStory, KappaLogbookEntry, KappaPlanningEntry } from '@/types/kappa' import { tauriDb } from '@/services/tauri-db'
import { stripHtml } from '@/services/clean-html'
import type { KappaUserStory, KappaLogbookEntry, KappaPlanningEntry, KappaEpicDevelopment } from '@/types/kappa'
export const useWorkItemsStore = defineStore('workitems', () => { export const useWorkItemsStore = defineStore('workitems', () => {
const creating = ref(false) const creating = ref(false)
@@ -9,13 +11,15 @@ export const useWorkItemsStore = defineStore('workitems', () => {
const error = ref<string | null>(null) const error = ref<string | null>(null)
const userStories = ref<KappaUserStory[]>([]) const userStories = ref<KappaUserStory[]>([])
const epics = ref<KappaEpicDevelopment[]>([])
const logbooks = ref<KappaLogbookEntry[]>([]) const logbooks = ref<KappaLogbookEntry[]>([])
const plannings = ref<KappaPlanningEntry[]>([]) const plannings = ref<KappaPlanningEntry[]>([])
const totalHUs = computed(() => userStories.value.length) const totalHUs = computed(() => userStories.value.length)
const totalEpics = computed(() => epics.value.length)
const inProgressHUs = computed(() => const inProgressHUs = computed(() =>
userStories.value.filter(us => userStories.value.filter(hu =>
us.status && ['in_progress', 'doing', 'wip', 'active'].includes(us.status.toLowerCase()) hu.status && ['in_progress', 'doing', 'wip', 'active', 'in progress'].includes(hu.status.toLowerCase())
).length ).length
) )
const totalSessions = computed(() => logbooks.value.length) const totalSessions = computed(() => logbooks.value.length)
@@ -38,18 +42,34 @@ export const useWorkItemsStore = defineStore('workitems', () => {
async function fetchWorkItems(initiativeId?: number) { async function fetchWorkItems(initiativeId?: number) {
loading.value = true loading.value = true
error.value = null error.value = null
const id = initiativeId || Number(localStorage.getItem('kappa_last_project'))
if (!id) {
loading.value = false
return
}
try { try {
const [stories, logs, plans] = await Promise.all([ const [stories, logs, plans, epicData] = await Promise.all([
kappa.getUserStories(initiativeId), kappa.getUserStories(id).catch(() => [] as KappaUserStory[]),
kappa.getLogbooks(initiativeId), kappa.getLogbooks(id).catch(() => [] as KappaLogbookEntry[]),
kappa.getPlannings(initiativeId), kappa.getPlannings(id).catch(() => [] as KappaPlanningEntry[]),
kappa.getAllEpicDevelopment(id).catch(() => [] as KappaEpicDevelopment[]),
]) ])
const storiesData = stories as KappaUserStory[] | { results?: KappaUserStory[] } const storiesData = stories as KappaUserStory[] | { results?: KappaUserStory[] }
const logsData = logs as KappaLogbookEntry[] | { results?: KappaLogbookEntry[] } const logsData = logs as KappaLogbookEntry[] | { results?: KappaLogbookEntry[] }
const plansData = plans as KappaPlanningEntry[] | { results?: KappaPlanningEntry[] } const plansData = plans as KappaPlanningEntry[] | { results?: KappaPlanningEntry[] }
userStories.value = Array.isArray(storiesData) ? storiesData : (storiesData.results ?? []) userStories.value = Array.isArray(storiesData) ? storiesData : (storiesData.results ?? [])
logbooks.value = Array.isArray(logsData) ? logsData : (logsData.results ?? []) logbooks.value = Array.isArray(logsData) ? logsData : (logsData.results ?? [])
plannings.value = Array.isArray(plansData) ? plansData : (plansData.results ?? []) plannings.value = Array.isArray(plansData) ? plansData : (plansData.results ?? [])
epics.value = epicData.map(epic => ({
...epic,
description: stripHtml(epic.description || ''),
}))
syncHUsToTurso(id, userStories.value)
} catch (e: any) { } catch (e: any) {
error.value = e.message error.value = e.message
} finally { } finally {
@@ -57,14 +77,31 @@ export const useWorkItemsStore = defineStore('workitems', () => {
} }
} }
async function syncHUsToTurso(projectId: number, hus: KappaUserStory[]) {
for (const hu of hus) {
await tauriDb.saveWorkItem({
id: hu.id ?? 0,
project_id: projectId,
code: hu.code ?? null,
title: hu.title,
description: stripHtml(hu.description || ''),
type: 'hu',
status: hu.status || 'backlog',
priority: hu.priority || 'medium',
}).catch(() => {})
}
}
return { return {
creating, creating,
loading, loading,
error, error,
userStories, userStories,
epics,
logbooks, logbooks,
plannings, plannings,
totalHUs, totalHUs,
totalEpics,
inProgressHUs, inProgressHUs,
totalSessions, totalSessions,
createUserStory, createUserStory,
+23
View File
@@ -48,6 +48,29 @@ export interface KappaUserStory {
created_at?: string created_at?: string
} }
export interface KappaEpicDevelopment {
id: number
code?: string
title?: string
name?: string
description?: string
status?: string
priority?: string
initiative?: number
initiative_name?: string
initiative_key?: string
assigned_to?: number | null
assigned_name?: string
story_points?: number
estimated_hours?: number
actual_hours?: number
start_date?: string
due_date?: string
completed_date?: string
created_at?: string
updated_at?: string
}
export interface KappaLogbookMaster { export interface KappaLogbookMaster {
id?: number id?: number
initiative: number | string initiative: number | string