cambiar push individual por bulk upload via Excel a KAPPA + xlsx package + servicio upload-hu.ts

This commit is contained in:
2026-05-27 23:29:38 -05:00
parent fd7a171a72
commit 96ed01d922
4 changed files with 92 additions and 22 deletions
+23 -21
View File
@@ -2,8 +2,7 @@
import { ref, onMounted, computed } from 'vue'
import { useI18n } from 'vue-i18n'
import { tauriDb, type HuDraftRecord } from '@/services/tauri-db'
import { kappa } from '@/services/kappa-api'
import { stripHtml, parseQuillList } from '@/services/clean-html'
import { pushDraftsToKappa } from '@/services/upload-hu'
import { getTypeLabel, getTypeColor, ItemType } from '@/services/hierarchy'
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
import { Button } from '@/components/ui/button'
@@ -21,6 +20,7 @@ const props = defineProps<{
const drafts = ref<HuDraftRecord[]>([])
const loading = ref(false)
const pushing = ref(false)
const showForm = ref(false)
const editingId = ref<string | null>(null)
@@ -48,6 +48,10 @@ const itemTypeOptions = computed(() =>
draftTypes.map(type => ({ value: type, label: getTypeLabel(type) }))
)
const unPushedDrafts = computed(() =>
drafts.value.filter(d => d.sync_status !== 'pushed')
)
async function loadDrafts() {
loading.value = true
try {
@@ -107,23 +111,20 @@ async function deleteDraft(id: string) {
}
}
async function pushToKappa(d: HuDraftRecord) {
if (!d.title) return
async function pushAllToKappa() {
if (pushing.value) return
pushing.value = true
try {
const result = await kappa.createUserStory({
title: d.hierarchy_path
? `[${d.hierarchy_path}] ${d.title}`
: d.title,
description: d.description || '',
initiative: props.initiativeId,
priority: 'medium',
})
d.sync_status = 'pushed'
d.kappa_id = result.id ?? null
await tauriDb.saveHuDraft(d)
await loadDrafts()
} catch (e) {
console.error('[Alpha] Failed to push draft to KAPPA:', e)
const result = await pushDraftsToKappa(unPushedDrafts.value, props.initiativeId)
if (result.ok > 0) {
for (const d of unPushedDrafts.value) {
d.sync_status = 'pushed'
await tauriDb.saveHuDraft(d).catch(() => {})
}
await loadDrafts()
}
} finally {
pushing.value = false
}
}
@@ -212,14 +213,15 @@ onMounted(loadDrafts)
</div>
<div class="flex gap-1 mt-2">
<Button
v-if="d.sync_status !== 'pushed'"
v-if="unPushedDrafts.length > 0"
size="sm"
variant="default"
class="h-7 text-xs"
@click="pushToKappa(d)"
:disabled="pushing"
@click="pushAllToKappa"
>
<Send class="size-3 mr-1" />
Enviar a KAPPA
{{ pushing ? 'Enviando...' : `Enviar ${unPushedDrafts.length} a KAPPA` }}
</Button>
<Button size="sm" variant="outline" class="h-7 text-xs" @click="editDraft(d)">
<Pencil class="size-3 mr-1" />
+48
View File
@@ -0,0 +1,48 @@
import * as XLSX from 'xlsx'
import { kappa } from '@/services/kappa-api'
import type { HuDraftRecord } from '@/services/tauri-db'
const BASE = '/api'
async function uploadExcel(initiativeId: number, file: Blob): Promise<Response> {
const token = localStorage.getItem('kappa_token')
const formData = new FormData()
formData.append('file', file, 'HistoriasUsuario.xlsx')
return fetch(`${BASE}/userstorys/upload-excel/${initiativeId}/`, {
method: 'POST',
headers: token ? { 'Authorization': `Bearer ${token}` } : {},
body: formData,
})
}
export async function pushDraftsToKappa(drafts: HuDraftRecord[], initiativeId: number): Promise<{ ok: number; fail: number }> {
const wb = XLSX.utils.book_new()
const rows = drafts.map(d => ({
Titulo: d.hierarchy_path ? `[${d.hierarchy_path}] ${d.title}` : d.title,
Descripción: d.description || '',
'Story points': d.story_points ?? '',
Prioridad: null,
Asignado_a: d.assigned_to ?? null,
'Criterios aceptación': d.acceptance_criteria || '',
}))
const ws = XLSX.utils.json_to_sheet(rows)
XLSX.utils.book_append_sheet(wb, ws, 'HistoriasUsuario')
const wbOut = XLSX.write(wb, { bookType: 'xlsx', type: 'array' })
const blob = new Blob([wbOut], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' })
try {
const resp = await uploadExcel(initiativeId, blob)
if (resp.ok) {
return { ok: drafts.length, fail: 0 }
}
const text = await resp.text()
console.error('[Alpha] Upload failed:', resp.status, text)
return { ok: 0, fail: drafts.length }
} catch (e) {
console.error('[Alpha] Upload error:', e)
return { ok: 0, fail: drafts.length }
}
}