fix(umind): faltaba el botón para editar las notas del conocimiento

Las plantillas de rubro dejan las notas con valores entre corchetes y la propia
pantalla dice "abrilas y reemplazalas por tus datos" — pero no había con qué.
El endpoint para editarlas existía desde que se agregaron las fuentes de texto;
lo que nunca se agregó fue el botón, así que el flujo que el producto promete
no se podía completar. Se elegía la plantilla de restaurante y quedaban cuatro
notas diciendo "[12:00]" sin forma de arreglarlas salvo borrarlas y escribirlas
de nuevo.

Ahora cada nota tiene "Editar": abre el contenido, se corrige y al guardar se
rehacen los fragmentos, así que el agente pasa a contestar con lo nuevo en el
momento.

También se puede editar el texto que se le extrajo a un archivo: si el OCR de
un PDF salió torcido, corregirlo a mano es tan válido como escribir la nota, y
es el mismo código. Las URLs no — su contenido se rehace crawleando y cualquier
corrección se perdería en la próxima actualización.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Lizandro Guarnizo
2026-08-19 20:03:58 -05:00
co-authored by Claude Opus 5
parent 3ceb61c035
commit 195590f5e4
7 changed files with 112 additions and 31 deletions
+78 -1
View File
@@ -109,6 +109,35 @@ async function subirArchivo() {
}
}
// Editar una fuente escrita a mano. Las plantillas de rubro dejan las notas
// con valores entre corchetes para reemplazar — sin esto, no había con qué.
const editandoDoc = ref(null)
const docForm = ref({ titulo: '', contenido: '' })
const guardandoDoc = ref(false)
function editarDocumento(d) {
editandoDoc.value = d
docForm.value = { titulo: d.origen, contenido: d.contenido || '' }
}
async function guardarDocumento() {
if (!editandoDoc.value) return
guardandoDoc.value = true
error.value = ''
try {
await api.put(apiUmind(`/umind/documentos/${editandoDoc.value.ID}`), {
titulo: docForm.value.titulo,
contenido: docForm.value.contenido,
})
editandoDoc.value = null
await cargarDocumentos()
} catch (e) {
error.value = e.message
} finally {
guardandoDoc.value = false
}
}
async function reprocesar(d) {
error.value = ''
try {
@@ -584,15 +613,63 @@ watch(
:title="d.auto_actualizar ? 'Dejar de releer sola' : 'Releer el sitio cada semana'"
@click="alternarAuto(d)"
>{{ d.auto_actualizar ? '🔁 auto' : '↻ manual' }}</button>
<!-- Solo lo que tiene texto propio guardado: una URL se rehace
crawleando, editarla a mano se perdería en la próxima pasada. -->
<button
class="text-sm text-brand hover:underline disabled:opacity-40"
v-if="d.tipo === 'texto' || d.tipo === 'archivo'"
class="text-sm text-brand hover:underline"
@click="editarDocumento(d)"
>Editar</button>
<button
class="text-sm text-tenue hover:text-texto disabled:opacity-40"
:disabled="d.estado === 'procesando'"
:title="d.tipo === 'url' ? 'Volver a leer el sitio' : 'Rehacer los fragmentos'"
@click="reprocesar(d)"
>Actualizar</button>
<button class="text-red-500 hover:text-red-700 text-sm" @click="eliminarDocumento(d.ID)">Eliminar</button>
</div>
</div>
</div>
<!-- Editar una nota o el texto extraído de un archivo -->
<div
v-if="editandoDoc"
class="fixed inset-0 bg-black/40 flex items-center justify-center p-4 z-50"
@click.self="editandoDoc = null"
>
<div class="card w-full max-w-2xl p-6 max-h-[calc(100vh-2rem)] overflow-y-auto">
<h2 class="font-semibold text-texto mb-1">Editar fuente</h2>
<p class="text-xs text-tenue mb-4">
Al guardar se vuelve a leer y el agente empieza a contestar con esto.
</p>
<form class="space-y-3" @submit.prevent="guardarDocumento">
<div>
<label class="label">Título</label>
<input v-model="docForm.titulo" required class="input" />
</div>
<div>
<label class="label">Contenido</label>
<textarea
v-model="docForm.contenido"
rows="16"
required
class="input font-normal leading-relaxed"
></textarea>
<p class="text-xs text-tenue mt-1.5">
Si viene de una plantilla, reemplazá lo que está [entre corchetes] por tus datos.
Lo que quede sin reemplazar el agente lo va a leer tal cual.
</p>
</div>
<div class="flex justify-end gap-2 pt-1">
<button type="button" class="btn-ghost" @click="editandoDoc = null">Cancelar</button>
<button type="submit" class="btn-primary" :disabled="guardandoDoc">
{{ guardandoDoc ? 'Guardando…' : 'Guardar y volver a leer' }}
</button>
</div>
</form>
</div>
</div>
</div>
<!-- Herramientas -->