cambiar push individual por bulk upload via Excel a KAPPA + xlsx package + servicio upload-hu.ts
This commit is contained in:
+23
-21
@@ -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" />
|
||||
|
||||
@@ -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 }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user