QA plans al sugerir HU + cancel analisis + datepicker shadcn
- project-analyzer: saveAsDrafts genera QA plan por cada HU sugerida - DashboardView: cancelAnalysis con AbortController + mensaje limpio - HuDrafts: DatePicker con Calendar + Popover (shadcn-vue) - HuDrafts: formulario dinámico segun tipo (Epic vs HU/Feature/etc) - components/ui: Popover + Calendar creados - qa_plans: tabla separada (cubre drafts + user_stories existentes)
This commit is contained in:
+35
-20
@@ -108,10 +108,6 @@ async function pushDraft(d: HuDraftRecord) {
|
||||
})
|
||||
if (res.ok) {
|
||||
d.syncStatus = 'pushed'; await dbSaveDraft(d)
|
||||
// Auto-generar QA plan tras push exitoso de épica
|
||||
generateAndSavePlan(d.projectId, d.id, d.title, d.description || '', '').catch(e =>
|
||||
console.error(`[Alpha] QA plan auto-gen failed for epic ${d.title}:`, e)
|
||||
)
|
||||
} else {
|
||||
d.syncStatus = 'draft'; await dbSaveDraft(d)
|
||||
}
|
||||
@@ -136,10 +132,6 @@ async function pushDraft(d: HuDraftRecord) {
|
||||
d.kappaId = created.id || undefined
|
||||
d.syncStatus = 'pushed'
|
||||
await dbSaveDraft(d)
|
||||
// Auto-generar QA plan tras push exitoso
|
||||
generateAndSavePlan(d.projectId, d.id, d.title, d.description || '', d.acceptanceCriteria).catch(e =>
|
||||
console.error(`[Alpha] QA plan auto-gen failed for ${d.title}:`, e)
|
||||
)
|
||||
} else {
|
||||
d.syncStatus = 'draft'; await dbSaveDraft(d)
|
||||
}
|
||||
@@ -168,17 +160,26 @@ async function discardDraft(id: string) {
|
||||
|
||||
// ─── Project analysis ────────────────────────────────────
|
||||
const analyzing = ref(false)
|
||||
const analysisAbort = ref<AbortController | null>(null)
|
||||
const analysisResult = ref<{ saved: number; skipped: number } | null>(null)
|
||||
const analysisSummary = ref('')
|
||||
|
||||
function cancelAnalysis() {
|
||||
analysisAbort.value?.abort()
|
||||
analyzing.value = false
|
||||
analysisAbort.value = null
|
||||
analysisSummary.value = 'Análisis cancelado'
|
||||
}
|
||||
|
||||
async function runAnalysis() {
|
||||
if (!project.value) return
|
||||
analyzing.value = true
|
||||
analysisAbort.value = new AbortController()
|
||||
analysisResult.value = null
|
||||
analysisSummary.value = ''
|
||||
|
||||
try {
|
||||
const result = await analyzeProject(project.value.id, project.value.name || '', workItems.userStories)
|
||||
const result = await analyzeProject(project.value.id, project.value.name || '', workItems.userStories, analysisAbort.value?.signal)
|
||||
analysisSummary.value = result.summary
|
||||
|
||||
if (result.hus.length > 0) {
|
||||
@@ -188,8 +189,12 @@ async function runAnalysis() {
|
||||
analysisResult.value = { saved: 0, skipped: 0 }
|
||||
}
|
||||
} catch (e: any) {
|
||||
console.error('[Alpha] Analysis error:', e)
|
||||
analysisSummary.value = `Error: ${e.message}`
|
||||
if (e.name === 'AbortError' || e.message?.includes('aborted')) {
|
||||
analysisSummary.value = 'Análisis cancelado'
|
||||
} else {
|
||||
console.error('[Alpha] Analysis error:', e)
|
||||
analysisSummary.value = `Error: ${e.message}`
|
||||
}
|
||||
analysisResult.value = { saved: 0, skipped: 0 }
|
||||
} finally {
|
||||
analyzing.value = false
|
||||
@@ -313,15 +318,25 @@ const statusLabel = (status: unknown) => {
|
||||
<Sparkles class="size-4" />
|
||||
Análisis completo del proyecto
|
||||
</CardTitle>
|
||||
<Button
|
||||
size="sm"
|
||||
:disabled="analyzing"
|
||||
@click="runAnalysis()"
|
||||
>
|
||||
<Loader2 v-if="analyzing" class="size-4 mr-1 animate-spin" />
|
||||
<Sparkles v-else class="size-4 mr-1" />
|
||||
{{ analyzing ? 'Analizando...' : 'Generar HUs faltantes' }}
|
||||
</Button>
|
||||
<div class="flex gap-2">
|
||||
<Button
|
||||
v-if="analyzing"
|
||||
size="sm"
|
||||
variant="outline"
|
||||
@click="cancelAnalysis()"
|
||||
>
|
||||
Cancelar
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
:disabled="analyzing"
|
||||
@click="runAnalysis()"
|
||||
>
|
||||
<Loader2 v-if="analyzing" class="size-4 mr-1 animate-spin" />
|
||||
<Sparkles v-else class="size-4 mr-1" />
|
||||
{{ analyzing ? 'Analizando...' : 'Generar HUs faltantes' }}
|
||||
</Button>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent v-if="analysisResult" class="space-y-2 text-sm">
|
||||
<p class="text-muted-foreground">{{ analysisSummary }}</p>
|
||||
|
||||
Reference in New Issue
Block a user