agregar endpoint /epicdevelopment/ + store de epicas y HUs por proyecto
This commit is contained in:
@@ -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)
|
||||||
|
|||||||
@@ -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
@@ -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,
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user